From 1fda5c79202ea51c2c007ec03aa2fafbcc28af67 Mon Sep 17 00:00:00 2001 From: Timo K Date: Mon, 24 Nov 2025 10:17:29 +0100 Subject: [PATCH 001/748] remove otel to see what impact it has on tests. --- src/initializer.tsx | 11 - src/otel/OTelCall.ts | 188 ------- src/otel/OTelCallAbstractMediaStreamSpan.ts | 69 --- src/otel/OTelCallFeedMediaStreamSpan.ts | 64 --- src/otel/OTelCallMediaStreamTrackSpan.ts | 69 --- .../OTelCallTransceiverMediaStreamSpan.ts | 61 --- src/otel/OTelGroupCallMembership.ts | 477 ------------------ src/otel/ObjectFlattener.test.ts | 266 ---------- src/otel/ObjectFlattener.ts | 100 ---- src/otel/otel.test.ts | 79 --- src/otel/otel.ts | 117 ----- src/room/InCallView.tsx | 2 - src/settings/submit-rageshake.ts | 9 - 13 files changed, 1512 deletions(-) delete mode 100644 src/otel/OTelCall.ts delete mode 100644 src/otel/OTelCallAbstractMediaStreamSpan.ts delete mode 100644 src/otel/OTelCallFeedMediaStreamSpan.ts delete mode 100644 src/otel/OTelCallMediaStreamTrackSpan.ts delete mode 100644 src/otel/OTelCallTransceiverMediaStreamSpan.ts delete mode 100644 src/otel/OTelGroupCallMembership.ts delete mode 100644 src/otel/ObjectFlattener.test.ts delete mode 100644 src/otel/ObjectFlattener.ts delete mode 100644 src/otel/otel.test.ts delete mode 100644 src/otel/otel.ts diff --git a/src/initializer.tsx b/src/initializer.tsx index d0797e9d1..2ecd11625 100644 --- a/src/initializer.tsx +++ b/src/initializer.tsx @@ -26,7 +26,6 @@ import { import { getUrlParams } from "./UrlParams"; import { Config } from "./config/Config"; -import { ElementCallOpenTelemetry } from "./otel/otel"; import { platform } from "./Platform"; import { isFailure } from "./utils/fetch"; @@ -101,7 +100,6 @@ enum LoadState { class DependencyLoadStates { public config: LoadState = LoadState.None; public sentry: LoadState = LoadState.None; - public openTelemetry: LoadState = LoadState.None; public allDepsAreLoaded(): boolean { return !Object.values(this).some((s) => s !== LoadState.Loaded); @@ -266,15 +264,6 @@ export class Initializer { this.loadStates.sentry = LoadState.Loaded; } - // OpenTelemetry (also only after config loaded) - if ( - this.loadStates.openTelemetry === LoadState.None && - this.loadStates.config === LoadState.Loaded - ) { - ElementCallOpenTelemetry.globalInit(); - this.loadStates.openTelemetry = LoadState.Loaded; - } - if (this.loadStates.allDepsAreLoaded()) { // resolve if there is no dependency that is not loaded resolve(); diff --git a/src/otel/OTelCall.ts b/src/otel/OTelCall.ts deleted file mode 100644 index e70cedf2d..000000000 --- a/src/otel/OTelCall.ts +++ /dev/null @@ -1,188 +0,0 @@ -/* -Copyright 2023, 2024 New Vector Ltd. - -SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial -Please see LICENSE in the repository root for full details. -*/ - -import { type Span } from "@opentelemetry/api"; -import { type MatrixCall } from "matrix-js-sdk"; -import { CallEvent } from "matrix-js-sdk/lib/webrtc/call"; -import { - type TransceiverStats, - type CallFeedStats, -} from "matrix-js-sdk/lib/webrtc/stats/statsReport"; - -import { ObjectFlattener } from "./ObjectFlattener"; -import { ElementCallOpenTelemetry } from "./otel"; -import { type OTelCallAbstractMediaStreamSpan } from "./OTelCallAbstractMediaStreamSpan"; -import { OTelCallTransceiverMediaStreamSpan } from "./OTelCallTransceiverMediaStreamSpan"; -import { OTelCallFeedMediaStreamSpan } from "./OTelCallFeedMediaStreamSpan"; - -type StreamId = string; -type MID = string; - -/** - * Tracks an individual call within a group call, either to a full-mesh peer or a focus - */ -export class OTelCall { - private readonly trackFeedSpan = new Map< - StreamId, - OTelCallAbstractMediaStreamSpan - >(); - private readonly trackTransceiverSpan = new Map< - MID, - OTelCallAbstractMediaStreamSpan - >(); - - public constructor( - public userId: string, - public deviceId: string, - public call: MatrixCall, - public span: Span, - ) { - if (call.peerConn) { - this.addCallPeerConnListeners(); - } else { - this.call.once( - CallEvent.PeerConnectionCreated, - this.addCallPeerConnListeners, - ); - } - } - - public dispose(): void { - this.call.peerConn?.removeEventListener( - "connectionstatechange", - this.onCallConnectionStateChanged, - ); - this.call.peerConn?.removeEventListener( - "signalingstatechange", - this.onCallSignalingStateChanged, - ); - this.call.peerConn?.removeEventListener( - "iceconnectionstatechange", - this.onIceConnectionStateChanged, - ); - this.call.peerConn?.removeEventListener( - "icegatheringstatechange", - this.onIceGatheringStateChanged, - ); - this.call.peerConn?.removeEventListener( - "icecandidateerror", - this.onIceCandidateError, - ); - } - - private addCallPeerConnListeners = (): void => { - this.call.peerConn?.addEventListener( - "connectionstatechange", - this.onCallConnectionStateChanged, - ); - this.call.peerConn?.addEventListener( - "signalingstatechange", - this.onCallSignalingStateChanged, - ); - this.call.peerConn?.addEventListener( - "iceconnectionstatechange", - this.onIceConnectionStateChanged, - ); - this.call.peerConn?.addEventListener( - "icegatheringstatechange", - this.onIceGatheringStateChanged, - ); - this.call.peerConn?.addEventListener( - "icecandidateerror", - this.onIceCandidateError, - ); - }; - - public onCallConnectionStateChanged = (): void => { - this.span.addEvent("matrix.call.callConnectionStateChange", { - callConnectionState: this.call.peerConn?.connectionState, - }); - }; - - public onCallSignalingStateChanged = (): void => { - this.span.addEvent("matrix.call.callSignalingStateChange", { - callSignalingState: this.call.peerConn?.signalingState, - }); - }; - - public onIceConnectionStateChanged = (): void => { - this.span.addEvent("matrix.call.iceConnectionStateChange", { - iceConnectionState: this.call.peerConn?.iceConnectionState, - }); - }; - - public onIceGatheringStateChanged = (): void => { - this.span.addEvent("matrix.call.iceGatheringStateChange", { - iceGatheringState: this.call.peerConn?.iceGatheringState, - }); - }; - - public onIceCandidateError = (ev: Event): void => { - const flatObject = {}; - ObjectFlattener.flattenObjectRecursive(ev, flatObject, "error.", 0); - - this.span.addEvent("matrix.call.iceCandidateError", flatObject); - }; - - public onCallFeedStats(callFeeds: CallFeedStats[]): void { - let prvFeeds: StreamId[] = [...this.trackFeedSpan.keys()]; - - callFeeds.forEach((feed) => { - if (!this.trackFeedSpan.has(feed.stream)) { - this.trackFeedSpan.set( - feed.stream, - new OTelCallFeedMediaStreamSpan( - ElementCallOpenTelemetry.instance, - this.span, - feed, - ), - ); - } - this.trackFeedSpan.get(feed.stream)?.update(feed); - prvFeeds = prvFeeds.filter((prvStreamId) => prvStreamId !== feed.stream); - }); - - prvFeeds.forEach((prvStreamId) => { - this.trackFeedSpan.get(prvStreamId)?.end(); - this.trackFeedSpan.delete(prvStreamId); - }); - } - - public onTransceiverStats(transceiverStats: TransceiverStats[]): void { - let prvTransSpan: MID[] = [...this.trackTransceiverSpan.keys()]; - - transceiverStats.forEach((transStats) => { - if (!this.trackTransceiverSpan.has(transStats.mid)) { - this.trackTransceiverSpan.set( - transStats.mid, - new OTelCallTransceiverMediaStreamSpan( - ElementCallOpenTelemetry.instance, - this.span, - transStats, - ), - ); - } - this.trackTransceiverSpan.get(transStats.mid)?.update(transStats); - prvTransSpan = prvTransSpan.filter( - (prvStreamId) => prvStreamId !== transStats.mid, - ); - }); - - prvTransSpan.forEach((prvMID) => { - this.trackTransceiverSpan.get(prvMID)?.end(); - this.trackTransceiverSpan.delete(prvMID); - }); - } - - public end(): void { - this.trackFeedSpan.forEach((feedSpan) => feedSpan.end()); - this.trackTransceiverSpan.forEach((transceiverSpan) => - transceiverSpan.end(), - ); - this.span.end(); - } -} diff --git a/src/otel/OTelCallAbstractMediaStreamSpan.ts b/src/otel/OTelCallAbstractMediaStreamSpan.ts deleted file mode 100644 index 69e415475..000000000 --- a/src/otel/OTelCallAbstractMediaStreamSpan.ts +++ /dev/null @@ -1,69 +0,0 @@ -/* -Copyright 2023, 2024 New Vector Ltd. - -SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial -Please see LICENSE in the repository root for full details. -*/ - -import opentelemetry, { type Span } from "@opentelemetry/api"; -import { type TrackStats } from "matrix-js-sdk/lib/webrtc/stats/statsReport"; - -import { type ElementCallOpenTelemetry } from "./otel"; -import { OTelCallMediaStreamTrackSpan } from "./OTelCallMediaStreamTrackSpan"; - -type TrackId = string; - -export abstract class OTelCallAbstractMediaStreamSpan { - protected readonly trackSpans = new Map< - TrackId, - OTelCallMediaStreamTrackSpan - >(); - public readonly span; - - public constructor( - protected readonly oTel: ElementCallOpenTelemetry, - protected readonly callSpan: Span, - protected readonly type: string, - ) { - const ctx = opentelemetry.trace.setSpan( - opentelemetry.context.active(), - callSpan, - ); - const options = { - links: [ - { - context: callSpan.spanContext(), - }, - ], - }; - this.span = oTel.tracer.startSpan(this.type, options, ctx); - } - - protected upsertTrackSpans(tracks: TrackStats[]): void { - let prvTracks: TrackId[] = [...this.trackSpans.keys()]; - tracks.forEach((t) => { - if (!this.trackSpans.has(t.id)) { - this.trackSpans.set( - t.id, - new OTelCallMediaStreamTrackSpan(this.oTel, this.span, t), - ); - } - this.trackSpans.get(t.id)?.update(t); - prvTracks = prvTracks.filter((prvTrackId) => prvTrackId !== t.id); - }); - - prvTracks.forEach((prvTrackId) => { - this.trackSpans.get(prvTrackId)?.end(); - this.trackSpans.delete(prvTrackId); - }); - } - - public abstract update(data: object): void; - - public end(): void { - this.trackSpans.forEach((tSpan) => { - tSpan.end(); - }); - this.span.end(); - } -} diff --git a/src/otel/OTelCallFeedMediaStreamSpan.ts b/src/otel/OTelCallFeedMediaStreamSpan.ts deleted file mode 100644 index 59c780a5c..000000000 --- a/src/otel/OTelCallFeedMediaStreamSpan.ts +++ /dev/null @@ -1,64 +0,0 @@ -/* -Copyright 2023, 2024 New Vector Ltd. - -SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial -Please see LICENSE in the repository root for full details. -*/ - -import { type Span } from "@opentelemetry/api"; -import { - type CallFeedStats, - type TrackStats, -} from "matrix-js-sdk/lib/webrtc/stats/statsReport"; - -import { type ElementCallOpenTelemetry } from "./otel"; -import { OTelCallAbstractMediaStreamSpan } from "./OTelCallAbstractMediaStreamSpan"; - -export class OTelCallFeedMediaStreamSpan extends OTelCallAbstractMediaStreamSpan { - private readonly prev: { isAudioMuted: boolean; isVideoMuted: boolean }; - - public constructor( - protected readonly oTel: ElementCallOpenTelemetry, - protected readonly callSpan: Span, - callFeed: CallFeedStats, - ) { - const postFix = - callFeed.type === "local" && callFeed.prefix === "from-call-feed" - ? "(clone)" - : ""; - super(oTel, callSpan, `matrix.call.feed.${callFeed.type}${postFix}`); - this.span.setAttribute("feed.streamId", callFeed.stream); - this.span.setAttribute("feed.type", callFeed.type); - this.span.setAttribute("feed.readFrom", callFeed.prefix); - this.span.setAttribute("feed.purpose", callFeed.purpose); - this.prev = { - isAudioMuted: callFeed.isAudioMuted, - isVideoMuted: callFeed.isVideoMuted, - }; - this.span.addEvent("matrix.call.feed.initState", this.prev); - } - - public update(callFeed: CallFeedStats): void { - if (this.prev.isAudioMuted !== callFeed.isAudioMuted) { - this.span.addEvent("matrix.call.feed.audioMuted", { - isAudioMuted: callFeed.isAudioMuted, - }); - this.prev.isAudioMuted = callFeed.isAudioMuted; - } - if (this.prev.isVideoMuted !== callFeed.isVideoMuted) { - this.span.addEvent("matrix.call.feed.isVideoMuted", { - isVideoMuted: callFeed.isVideoMuted, - }); - this.prev.isVideoMuted = callFeed.isVideoMuted; - } - - const trackStats: TrackStats[] = []; - if (callFeed.video) { - trackStats.push(callFeed.video); - } - if (callFeed.audio) { - trackStats.push(callFeed.audio); - } - this.upsertTrackSpans(trackStats); - } -} diff --git a/src/otel/OTelCallMediaStreamTrackSpan.ts b/src/otel/OTelCallMediaStreamTrackSpan.ts deleted file mode 100644 index c81acd4f5..000000000 --- a/src/otel/OTelCallMediaStreamTrackSpan.ts +++ /dev/null @@ -1,69 +0,0 @@ -/* -Copyright 2023, 2024 New Vector Ltd. - -SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial -Please see LICENSE in the repository root for full details. -*/ - -import { type TrackStats } from "matrix-js-sdk/lib/webrtc/stats/statsReport"; -import opentelemetry, { type Span } from "@opentelemetry/api"; - -import { type ElementCallOpenTelemetry } from "./otel"; - -export class OTelCallMediaStreamTrackSpan { - private readonly span: Span; - private prev: TrackStats; - - public constructor( - protected readonly oTel: ElementCallOpenTelemetry, - protected readonly streamSpan: Span, - data: TrackStats, - ) { - const ctx = opentelemetry.trace.setSpan( - opentelemetry.context.active(), - streamSpan, - ); - const options = { - links: [ - { - context: streamSpan.spanContext(), - }, - ], - }; - const type = `matrix.call.track.${data.label}.${data.kind}`; - this.span = oTel.tracer.startSpan(type, options, ctx); - this.span.setAttribute("track.trackId", data.id); - this.span.setAttribute("track.kind", data.kind); - this.span.setAttribute("track.constrainDeviceId", data.constrainDeviceId); - this.span.setAttribute("track.settingDeviceId", data.settingDeviceId); - this.span.setAttribute("track.label", data.label); - - this.span.addEvent("matrix.call.track.initState", { - readyState: data.readyState, - muted: data.muted, - enabled: data.enabled, - }); - this.prev = data; - } - - public update(data: TrackStats): void { - if (this.prev.muted !== data.muted) { - this.span.addEvent("matrix.call.track.muted", { muted: data.muted }); - } - if (this.prev.enabled !== data.enabled) { - this.span.addEvent("matrix.call.track.enabled", { - enabled: data.enabled, - }); - } - if (this.prev.readyState !== data.readyState) { - this.span.addEvent("matrix.call.track.readyState", { - readyState: data.readyState, - }); - } - this.prev = data; - } - - public end(): void { - this.span.end(); - } -} diff --git a/src/otel/OTelCallTransceiverMediaStreamSpan.ts b/src/otel/OTelCallTransceiverMediaStreamSpan.ts deleted file mode 100644 index 675d793ef..000000000 --- a/src/otel/OTelCallTransceiverMediaStreamSpan.ts +++ /dev/null @@ -1,61 +0,0 @@ -/* -Copyright 2023, 2024 New Vector Ltd. - -SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial -Please see LICENSE in the repository root for full details. -*/ - -import { type Span } from "@opentelemetry/api"; -import { - type TrackStats, - type TransceiverStats, -} from "matrix-js-sdk/lib/webrtc/stats/statsReport"; - -import { type ElementCallOpenTelemetry } from "./otel"; -import { OTelCallAbstractMediaStreamSpan } from "./OTelCallAbstractMediaStreamSpan"; - -export class OTelCallTransceiverMediaStreamSpan extends OTelCallAbstractMediaStreamSpan { - private readonly prev: { - direction: string; - currentDirection: string; - }; - - public constructor( - protected readonly oTel: ElementCallOpenTelemetry, - protected readonly callSpan: Span, - stats: TransceiverStats, - ) { - super(oTel, callSpan, `matrix.call.transceiver.${stats.mid}`); - this.span.setAttribute("transceiver.mid", stats.mid); - - this.prev = { - direction: stats.direction, - currentDirection: stats.currentDirection, - }; - this.span.addEvent("matrix.call.transceiver.initState", this.prev); - } - - public update(stats: TransceiverStats): void { - if (this.prev.currentDirection !== stats.currentDirection) { - this.span.addEvent("matrix.call.transceiver.currentDirection", { - currentDirection: stats.currentDirection, - }); - this.prev.currentDirection = stats.currentDirection; - } - if (this.prev.direction !== stats.direction) { - this.span.addEvent("matrix.call.transceiver.direction", { - direction: stats.direction, - }); - this.prev.direction = stats.direction; - } - - const trackStats: TrackStats[] = []; - if (stats.sender) { - trackStats.push(stats.sender); - } - if (stats.receiver) { - trackStats.push(stats.receiver); - } - this.upsertTrackSpans(trackStats); - } -} diff --git a/src/otel/OTelGroupCallMembership.ts b/src/otel/OTelGroupCallMembership.ts deleted file mode 100644 index 668b989cc..000000000 --- a/src/otel/OTelGroupCallMembership.ts +++ /dev/null @@ -1,477 +0,0 @@ -/* -Copyright 2023, 2024 New Vector Ltd. - -SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial -Please see LICENSE in the repository root for full details. -*/ - -import opentelemetry, { - type Span, - type Attributes, - type Context, -} from "@opentelemetry/api"; -import { - type GroupCall, - type MatrixClient, - type MatrixEvent, - type RoomMember, -} from "matrix-js-sdk"; -import { logger } from "matrix-js-sdk/lib/logger"; -import { - type CallError, - type CallState, - type MatrixCall, - type VoipEvent, -} from "matrix-js-sdk/lib/webrtc/call"; -import { - type CallsByUserAndDevice, - type GroupCallError, - GroupCallEvent, - type GroupCallStatsReport, -} from "matrix-js-sdk/lib/webrtc/groupCall"; -import { - type ConnectionStatsReport, - type ByteSentStatsReport, - type SummaryStatsReport, - type CallFeedReport, -} from "matrix-js-sdk/lib/webrtc/stats/statsReport"; - -import { ElementCallOpenTelemetry } from "./otel"; -import { ObjectFlattener } from "./ObjectFlattener"; -import { OTelCall } from "./OTelCall"; - -/** - * Represent the span of time which we intend to be joined to a group call - */ -export class OTelGroupCallMembership { - private callMembershipSpan?: Span; - private groupCallContext?: Context; - private myUserId = "unknown"; - private myDeviceId: string; - private myMember?: RoomMember; - private callsByCallId = new Map(); - private statsReportSpan: { - span: Span | undefined; - stats: OTelStatsReportEvent[]; - }; - private readonly speakingSpans = new Map>(); - - public constructor( - private groupCall: GroupCall, - client: MatrixClient, - ) { - const clientId = client.getUserId(); - if (clientId) { - this.myUserId = clientId; - const myMember = groupCall.room.getMember(clientId); - if (myMember) { - this.myMember = myMember; - } - } - this.myDeviceId = client.getDeviceId() || "unknown"; - this.statsReportSpan = { span: undefined, stats: [] }; - this.groupCall.on(GroupCallEvent.CallsChanged, this.onCallsChanged); - } - - public dispose(): void { - this.groupCall.removeListener( - GroupCallEvent.CallsChanged, - this.onCallsChanged, - ); - } - - public onJoinCall(): void { - if (!ElementCallOpenTelemetry.instance) return; - if (this.callMembershipSpan !== undefined) { - logger.warn("Call membership span is already started"); - return; - } - - // Create the main span that tracks the time we intend to be in the call - this.callMembershipSpan = - ElementCallOpenTelemetry.instance.tracer.startSpan( - "matrix.groupCallMembership", - ); - this.callMembershipSpan.setAttribute( - "matrix.confId", - this.groupCall.groupCallId, - ); - this.callMembershipSpan.setAttribute("matrix.userId", this.myUserId); - this.callMembershipSpan.setAttribute("matrix.deviceId", this.myDeviceId); - this.callMembershipSpan.setAttribute( - "matrix.displayName", - this.myMember ? this.myMember.name : "unknown-name", - ); - - this.groupCallContext = opentelemetry.trace.setSpan( - opentelemetry.context.active(), - this.callMembershipSpan, - ); - - this.callMembershipSpan?.addEvent("matrix.joinCall"); - } - - public onLeaveCall(): void { - if (this.callMembershipSpan === undefined) { - logger.warn("Call membership span is already ended"); - return; - } - - this.callMembershipSpan.addEvent("matrix.leaveCall"); - // and end the span to indicate we've left - this.callMembershipSpan.end(); - this.callMembershipSpan = undefined; - this.groupCallContext = undefined; - } - - public onUpdateRoomState(event: MatrixEvent): void { - if ( - !event || - (!event.getType().startsWith("m.call") && - !event.getType().startsWith("org.matrix.msc3401.call")) - ) { - return; - } - - this.callMembershipSpan?.addEvent( - `matrix.roomStateEvent_${event.getType()}`, - ObjectFlattener.flattenVoipEvent(event.getContent()), - ); - } - - public onCallsChanged(calls: CallsByUserAndDevice): void { - for (const [userId, userCalls] of calls.entries()) { - for (const [deviceId, call] of userCalls.entries()) { - if (!this.callsByCallId.has(call.callId)) { - if (ElementCallOpenTelemetry.instance) { - const span = ElementCallOpenTelemetry.instance.tracer.startSpan( - `matrix.call`, - undefined, - this.groupCallContext, - ); - // XXX: anonymity - span.setAttribute("matrix.call.target.userId", userId); - span.setAttribute("matrix.call.target.deviceId", deviceId); - const displayName = - this.groupCall.room.getMember(userId)?.name ?? "unknown"; - span.setAttribute("matrix.call.target.displayName", displayName); - this.callsByCallId.set( - call.callId, - new OTelCall(userId, deviceId, call, span), - ); - } - } - } - } - - for (const callTrackingInfo of this.callsByCallId.values()) { - const userCalls = calls.get(callTrackingInfo.userId); - if ( - !userCalls || - !userCalls.has(callTrackingInfo.deviceId) || - userCalls.get(callTrackingInfo.deviceId)?.callId !== - callTrackingInfo.call.callId - ) { - callTrackingInfo.end(); - this.callsByCallId.delete(callTrackingInfo.call.callId); - } - } - } - - public onCallStateChange(call: MatrixCall, newState: CallState): void { - const callTrackingInfo = this.callsByCallId.get(call.callId); - if (!callTrackingInfo) { - logger.error(`Got call state change for unknown call ID ${call.callId}`); - return; - } - - callTrackingInfo.span.addEvent("matrix.call.stateChange", { - state: newState, - }); - } - - public onSendEvent(call: MatrixCall, event: VoipEvent): void { - const eventType = event.eventType as string; - if ( - !eventType.startsWith("m.call") && - !eventType.startsWith("org.matrix.call") - ) - return; - - const callTrackingInfo = this.callsByCallId.get(call.callId); - if (!callTrackingInfo) { - logger.error(`Got call send event for unknown call ID ${call.callId}`); - return; - } - - if (event.type === "toDevice") { - callTrackingInfo.span.addEvent( - `matrix.sendToDeviceEvent_${event.eventType}`, - ObjectFlattener.flattenVoipEvent(event), - ); - } else if (event.type === "sendEvent") { - callTrackingInfo.span.addEvent( - `matrix.sendToRoomEvent_${event.eventType}`, - ObjectFlattener.flattenVoipEvent(event), - ); - } - } - - public onReceivedVoipEvent(event: MatrixEvent): void { - // These come straight from CallEventHandler so don't have - // a call already associated (in principle we could receive - // events for calls we don't know about). - const callId = event.getContent().call_id; - if (!callId) { - this.callMembershipSpan?.addEvent("matrix.receive_voip_event_no_callid", { - "sender.userId": event.getSender(), - }); - logger.error("Received call event with no call ID!"); - return; - } - - const call = this.callsByCallId.get(callId); - if (!call) { - this.callMembershipSpan?.addEvent( - "matrix.receive_voip_event_unknown_callid", - { - "sender.userId": event.getSender(), - }, - ); - logger.error("Received call event for unknown call ID " + callId); - return; - } - - call.span.addEvent("matrix.receive_voip_event", { - "sender.userId": event.getSender(), - ...ObjectFlattener.flattenVoipEvent(event.getContent()), - }); - } - - public onToggleMicrophoneMuted(newValue: boolean): void { - this.callMembershipSpan?.addEvent("matrix.toggleMicMuted", { - "matrix.microphone.muted": newValue, - }); - } - - public onSetMicrophoneMuted(setMuted: boolean): void { - this.callMembershipSpan?.addEvent("matrix.setMicMuted", { - "matrix.microphone.muted": setMuted, - }); - } - - public onToggleLocalVideoMuted(newValue: boolean): void { - this.callMembershipSpan?.addEvent("matrix.toggleVidMuted", { - "matrix.video.muted": newValue, - }); - } - - public onSetLocalVideoMuted(setMuted: boolean): void { - this.callMembershipSpan?.addEvent("matrix.setVidMuted", { - "matrix.video.muted": setMuted, - }); - } - - public onToggleScreensharing(newValue: boolean): void { - this.callMembershipSpan?.addEvent("matrix.setVidMuted", { - "matrix.screensharing.enabled": newValue, - }); - } - - public onSpeaking( - member: RoomMember, - deviceId: string, - speaking: boolean, - ): void { - if (speaking) { - // Ensure that there's an audio activity span for this speaker - let deviceMap = this.speakingSpans.get(member); - if (deviceMap === undefined) { - deviceMap = new Map(); - this.speakingSpans.set(member, deviceMap); - } - - if (!deviceMap.has(deviceId)) { - const span = ElementCallOpenTelemetry.instance.tracer.startSpan( - "matrix.audioActivity", - undefined, - this.groupCallContext, - ); - span.setAttribute("matrix.userId", member.userId); - span.setAttribute("matrix.displayName", member.rawDisplayName); - - deviceMap.set(deviceId, span); - } - } else { - // End the audio activity span for this speaker, if any - const deviceMap = this.speakingSpans.get(member); - deviceMap?.get(deviceId)?.end(); - deviceMap?.delete(deviceId); - - if (deviceMap?.size === 0) this.speakingSpans.delete(member); - } - } - - public onCallError(error: CallError, call: MatrixCall): void { - const callTrackingInfo = this.callsByCallId.get(call.callId); - if (!callTrackingInfo) { - logger.error(`Got error for unknown call ID ${call.callId}`); - return; - } - - callTrackingInfo.span.recordException(error); - } - - public onGroupCallError(error: GroupCallError): void { - this.callMembershipSpan?.recordException(error); - } - - public onUndecryptableToDevice(event: MatrixEvent): void { - this.callMembershipSpan?.addEvent("matrix.toDevice.undecryptable", { - "sender.userId": event.getSender(), - }); - } - - public onCallFeedStatsReport( - report: GroupCallStatsReport, - ): void { - if (!ElementCallOpenTelemetry.instance) return; - let call: OTelCall | undefined; - const callId = report.report?.callId; - - if (callId) { - call = this.callsByCallId.get(callId); - } - - if (!call) { - this.callMembershipSpan?.addEvent( - OTelStatsReportType.CallFeedReport + "_unknown_callId", - { - "call.callId": callId, - "call.opponentMemberId": report.report?.opponentMemberId - ? report.report?.opponentMemberId - : "unknown", - }, - ); - logger.error( - `Received ${OTelStatsReportType.CallFeedReport} with unknown call ID: ${callId}`, - ); - return; - } else { - call.onCallFeedStats(report.report.callFeeds); - call.onTransceiverStats(report.report.transceiver); - } - } - - public onConnectionStatsReport( - statsReport: GroupCallStatsReport, - ): void { - this.buildCallStatsSpan( - OTelStatsReportType.ConnectionReport, - statsReport.report, - ); - } - - public onByteSentStatsReport( - statsReport: GroupCallStatsReport, - ): void { - this.buildCallStatsSpan( - OTelStatsReportType.ByteSentReport, - statsReport.report, - ); - } - - public buildCallStatsSpan( - type: OTelStatsReportType, - report: ByteSentStatsReport | ConnectionStatsReport, - ): void { - if (!ElementCallOpenTelemetry.instance) return; - let call: OTelCall | undefined; - const callId = report?.callId; - - if (callId) { - call = this.callsByCallId.get(callId); - } - - if (!call) { - this.callMembershipSpan?.addEvent(type + "_unknown_callid", { - "call.callId": callId, - "call.opponentMemberId": report.opponentMemberId - ? report.opponentMemberId - : "unknown", - }); - logger.error(`Received ${type} with unknown call ID: ${callId}`); - return; - } - const data = ObjectFlattener.flattenReportObject(type, report); - const ctx = opentelemetry.trace.setSpan( - opentelemetry.context.active(), - call.span, - ); - - const options = { - links: [ - { - context: call.span.spanContext(), - }, - ], - }; - - const span = ElementCallOpenTelemetry.instance.tracer.startSpan( - type, - options, - ctx, - ); - - span.setAttribute("matrix.callId", callId ?? "unknown"); - span.setAttribute( - "matrix.opponentMemberId", - report.opponentMemberId ? report.opponentMemberId : "unknown", - ); - span.addEvent("matrix.call.connection_stats_event", data); - span.end(); - } - - public onSummaryStatsReport( - statsReport: GroupCallStatsReport, - ): void { - if (!ElementCallOpenTelemetry.instance) return; - - const type = OTelStatsReportType.SummaryReport; - const data = ObjectFlattener.flattenSummaryStatsReportObject(statsReport); - if (this.statsReportSpan.span === undefined && this.callMembershipSpan) { - const ctx = opentelemetry.trace.setSpan( - opentelemetry.context.active(), - this.callMembershipSpan, - ); - const span = ElementCallOpenTelemetry.instance?.tracer.startSpan( - "matrix.groupCallMembership.summaryReport", - undefined, - ctx, - ); - if (span === undefined) { - return; - } - span.setAttribute("matrix.confId", this.groupCall.groupCallId); - span.setAttribute("matrix.userId", this.myUserId); - span.setAttribute( - "matrix.displayName", - this.myMember ? this.myMember.name : "unknown-name", - ); - span.addEvent(type, data); - span.end(); - } - } -} - -interface OTelStatsReportEvent { - type: OTelStatsReportType; - data: Attributes; -} - -enum OTelStatsReportType { - ConnectionReport = "matrix.call.stats.connection", - ByteSentReport = "matrix.call.stats.byteSent", - SummaryReport = "matrix.stats.summary", - CallFeedReport = "matrix.stats.call_feed", -} diff --git a/src/otel/ObjectFlattener.test.ts b/src/otel/ObjectFlattener.test.ts deleted file mode 100644 index 5685617c4..000000000 --- a/src/otel/ObjectFlattener.test.ts +++ /dev/null @@ -1,266 +0,0 @@ -/* -Copyright 2023, 2024 New Vector Ltd. - -SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial -Please see LICENSE in the repository root for full details. -*/ - -import { type GroupCallStatsReport } from "matrix-js-sdk/lib/webrtc/groupCall"; -import { - type AudioConcealment, - type ByteSentStatsReport, - type ConnectionStatsReport, -} from "matrix-js-sdk/lib/webrtc/stats/statsReport"; -import { describe, expect, it } from "vitest"; - -import { ObjectFlattener } from "../../src/otel/ObjectFlattener"; - -describe("ObjectFlattener", () => { - const noConcealment: AudioConcealment = { - concealedAudio: 0, - totalAudioDuration: 0, - }; - - const statsReport: GroupCallStatsReport = { - report: { - callId: "callId", - opponentMemberId: "opponentMemberId", - bandwidth: { upload: 426, download: 0 }, - bitrate: { - upload: 426, - download: 0, - audio: { - upload: 124, - download: 0, - }, - video: { - upload: 302, - download: 0, - }, - }, - packetLoss: { - total: 0, - download: 0, - upload: 0, - }, - framerate: { - local: new Map([ - ["LOCAL_AUDIO_TRACK_ID", 0], - ["LOCAL_VIDEO_TRACK_ID", 30], - ]), - remote: new Map([ - ["REMOTE_AUDIO_TRACK_ID", 0], - ["REMOTE_VIDEO_TRACK_ID", 60], - ]), - }, - resolution: { - local: new Map([ - ["LOCAL_AUDIO_TRACK_ID", { height: -1, width: -1 }], - ["LOCAL_VIDEO_TRACK_ID", { height: 460, width: 780 }], - ]), - remote: new Map([ - ["REMOTE_AUDIO_TRACK_ID", { height: -1, width: -1 }], - ["REMOTE_VIDEO_TRACK_ID", { height: 960, width: 1080 }], - ]), - }, - jitter: new Map([ - ["REMOTE_AUDIO_TRACK_ID", 2], - ["REMOTE_VIDEO_TRACK_ID", 50], - ]), - codec: { - local: new Map([ - ["LOCAL_AUDIO_TRACK_ID", "opus"], - ["LOCAL_VIDEO_TRACK_ID", "v8"], - ]), - remote: new Map([ - ["REMOTE_AUDIO_TRACK_ID", "opus"], - ["REMOTE_VIDEO_TRACK_ID", "v9"], - ]), - }, - transport: [ - { - ip: "ff11::5fa:abcd:999c:c5c5:50000", - type: "udp", - localIp: "2aaa:9999:2aaa:999:8888:2aaa:2aaa:7777:50000", - isFocus: true, - localCandidateType: "host", - remoteCandidateType: "host", - networkType: "ethernet", - rtt: NaN, - }, - { - ip: "10.10.10.2:22222", - type: "tcp", - localIp: "10.10.10.100:33333", - isFocus: true, - localCandidateType: "srfx", - remoteCandidateType: "srfx", - networkType: "ethernet", - rtt: 0, - }, - ], - audioConcealment: new Map([ - ["REMOTE_AUDIO_TRACK_ID", noConcealment], - ["REMOTE_VIDEO_TRACK_ID", noConcealment], - ]), - totalAudioConcealment: noConcealment, - }, - }; - - describe("on flattenObjectRecursive", () => { - it("should flatter an Map object", () => { - const flatObject = {}; - ObjectFlattener.flattenObjectRecursive( - statsReport.report.resolution, - flatObject, - "matrix.call.stats.connection.resolution.", - 0, - ); - expect(flatObject).toEqual({ - "matrix.call.stats.connection.resolution.local.LOCAL_AUDIO_TRACK_ID.height": - -1, - "matrix.call.stats.connection.resolution.local.LOCAL_AUDIO_TRACK_ID.width": - -1, - - "matrix.call.stats.connection.resolution.local.LOCAL_VIDEO_TRACK_ID.height": 460, - "matrix.call.stats.connection.resolution.local.LOCAL_VIDEO_TRACK_ID.width": 780, - - "matrix.call.stats.connection.resolution.remote.REMOTE_AUDIO_TRACK_ID.height": - -1, - "matrix.call.stats.connection.resolution.remote.REMOTE_AUDIO_TRACK_ID.width": - -1, - - "matrix.call.stats.connection.resolution.remote.REMOTE_VIDEO_TRACK_ID.height": 960, - "matrix.call.stats.connection.resolution.remote.REMOTE_VIDEO_TRACK_ID.width": 1080, - }); - }); - it("should flatter an Array object", () => { - const flatObject = {}; - ObjectFlattener.flattenObjectRecursive( - statsReport.report.transport, - flatObject, - "matrix.call.stats.connection.transport.", - 0, - ); - expect(flatObject).toEqual({ - "matrix.call.stats.connection.transport.0.ip": - "ff11::5fa:abcd:999c:c5c5:50000", - "matrix.call.stats.connection.transport.0.type": "udp", - "matrix.call.stats.connection.transport.0.localIp": - "2aaa:9999:2aaa:999:8888:2aaa:2aaa:7777:50000", - "matrix.call.stats.connection.transport.0.isFocus": true, - "matrix.call.stats.connection.transport.0.localCandidateType": "host", - "matrix.call.stats.connection.transport.0.remoteCandidateType": "host", - "matrix.call.stats.connection.transport.0.networkType": "ethernet", - "matrix.call.stats.connection.transport.0.rtt": "NaN", - "matrix.call.stats.connection.transport.1.ip": "10.10.10.2:22222", - "matrix.call.stats.connection.transport.1.type": "tcp", - "matrix.call.stats.connection.transport.1.localIp": - "10.10.10.100:33333", - "matrix.call.stats.connection.transport.1.isFocus": true, - "matrix.call.stats.connection.transport.1.localCandidateType": "srfx", - "matrix.call.stats.connection.transport.1.remoteCandidateType": "srfx", - "matrix.call.stats.connection.transport.1.networkType": "ethernet", - "matrix.call.stats.connection.transport.1.rtt": 0, - }); - }); - }); - - describe("on flattenReportObject Connection Stats", () => { - it("should flatten a Report to otel Attributes Object", () => { - expect( - ObjectFlattener.flattenReportObject( - "matrix.call.stats.connection", - statsReport.report, - ), - ).toEqual({ - "matrix.call.stats.connection.callId": "callId", - "matrix.call.stats.connection.opponentMemberId": "opponentMemberId", - "matrix.call.stats.connection.bandwidth.download": 0, - "matrix.call.stats.connection.bandwidth.upload": 426, - "matrix.call.stats.connection.bitrate.audio.download": 0, - "matrix.call.stats.connection.bitrate.audio.upload": 124, - "matrix.call.stats.connection.bitrate.download": 0, - "matrix.call.stats.connection.bitrate.upload": 426, - "matrix.call.stats.connection.bitrate.video.download": 0, - "matrix.call.stats.connection.bitrate.video.upload": 302, - "matrix.call.stats.connection.codec.local.LOCAL_AUDIO_TRACK_ID": "opus", - "matrix.call.stats.connection.codec.local.LOCAL_VIDEO_TRACK_ID": "v8", - "matrix.call.stats.connection.codec.remote.REMOTE_AUDIO_TRACK_ID": - "opus", - "matrix.call.stats.connection.codec.remote.REMOTE_VIDEO_TRACK_ID": "v9", - "matrix.call.stats.connection.framerate.local.LOCAL_AUDIO_TRACK_ID": 0, - "matrix.call.stats.connection.framerate.local.LOCAL_VIDEO_TRACK_ID": 30, - "matrix.call.stats.connection.framerate.remote.REMOTE_AUDIO_TRACK_ID": 0, - "matrix.call.stats.connection.framerate.remote.REMOTE_VIDEO_TRACK_ID": 60, - "matrix.call.stats.connection.jitter.REMOTE_AUDIO_TRACK_ID": 2, - "matrix.call.stats.connection.jitter.REMOTE_VIDEO_TRACK_ID": 50, - "matrix.call.stats.connection.packetLoss.download": 0, - "matrix.call.stats.connection.packetLoss.total": 0, - "matrix.call.stats.connection.packetLoss.upload": 0, - "matrix.call.stats.connection.resolution.local.LOCAL_AUDIO_TRACK_ID.height": - -1, - "matrix.call.stats.connection.resolution.local.LOCAL_AUDIO_TRACK_ID.width": - -1, - "matrix.call.stats.connection.resolution.local.LOCAL_VIDEO_TRACK_ID.height": 460, - "matrix.call.stats.connection.resolution.local.LOCAL_VIDEO_TRACK_ID.width": 780, - "matrix.call.stats.connection.resolution.remote.REMOTE_AUDIO_TRACK_ID.height": - -1, - "matrix.call.stats.connection.resolution.remote.REMOTE_AUDIO_TRACK_ID.width": - -1, - "matrix.call.stats.connection.resolution.remote.REMOTE_VIDEO_TRACK_ID.height": 960, - "matrix.call.stats.connection.resolution.remote.REMOTE_VIDEO_TRACK_ID.width": 1080, - "matrix.call.stats.connection.transport.0.ip": - "ff11::5fa:abcd:999c:c5c5:50000", - "matrix.call.stats.connection.transport.0.type": "udp", - "matrix.call.stats.connection.transport.0.localIp": - "2aaa:9999:2aaa:999:8888:2aaa:2aaa:7777:50000", - "matrix.call.stats.connection.transport.0.isFocus": true, - "matrix.call.stats.connection.transport.0.localCandidateType": "host", - "matrix.call.stats.connection.transport.0.remoteCandidateType": "host", - "matrix.call.stats.connection.transport.0.networkType": "ethernet", - "matrix.call.stats.connection.transport.0.rtt": "NaN", - "matrix.call.stats.connection.transport.1.ip": "10.10.10.2:22222", - "matrix.call.stats.connection.transport.1.type": "tcp", - "matrix.call.stats.connection.transport.1.localIp": - "10.10.10.100:33333", - "matrix.call.stats.connection.transport.1.isFocus": true, - "matrix.call.stats.connection.transport.1.localCandidateType": "srfx", - "matrix.call.stats.connection.transport.1.remoteCandidateType": "srfx", - "matrix.call.stats.connection.transport.1.networkType": "ethernet", - "matrix.call.stats.connection.transport.1.rtt": 0, - "matrix.call.stats.connection.audioConcealment.REMOTE_AUDIO_TRACK_ID.concealedAudio": 0, - "matrix.call.stats.connection.audioConcealment.REMOTE_AUDIO_TRACK_ID.totalAudioDuration": 0, - "matrix.call.stats.connection.audioConcealment.REMOTE_VIDEO_TRACK_ID.concealedAudio": 0, - "matrix.call.stats.connection.audioConcealment.REMOTE_VIDEO_TRACK_ID.totalAudioDuration": 0, - "matrix.call.stats.connection.totalAudioConcealment.concealedAudio": 0, - "matrix.call.stats.connection.totalAudioConcealment.totalAudioDuration": 0, - }); - }); - }); - - describe("on flattenByteSendStatsReportObject", () => { - const byteSentStatsReport = new Map< - string, - number - >() as ByteSentStatsReport; - byteSentStatsReport.callId = "callId"; - byteSentStatsReport.opponentMemberId = "opponentMemberId"; - byteSentStatsReport.set("4aa92608-04c6-428e-8312-93e17602a959", 132093); - byteSentStatsReport.set("a08e4237-ee30-4015-a932-b676aec894b1", 913448); - - it("should flatten a Report to otel Attributes Object", () => { - expect( - ObjectFlattener.flattenReportObject( - "matrix.call.stats.bytesSend", - byteSentStatsReport, - ), - ).toEqual({ - "matrix.call.stats.bytesSend.4aa92608-04c6-428e-8312-93e17602a959": 132093, - "matrix.call.stats.bytesSend.a08e4237-ee30-4015-a932-b676aec894b1": 913448, - }); - expect(byteSentStatsReport.callId).toEqual("callId"); - expect(byteSentStatsReport.opponentMemberId).toEqual("opponentMemberId"); - }); - }); -}); diff --git a/src/otel/ObjectFlattener.ts b/src/otel/ObjectFlattener.ts deleted file mode 100644 index a963c7434..000000000 --- a/src/otel/ObjectFlattener.ts +++ /dev/null @@ -1,100 +0,0 @@ -/* -Copyright 2023, 2024 New Vector Ltd. - -SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial -Please see LICENSE in the repository root for full details. -*/ -import { type Attributes } from "@opentelemetry/api"; -import { type VoipEvent } from "matrix-js-sdk/lib/webrtc/call"; -import { type GroupCallStatsReport } from "matrix-js-sdk/lib/webrtc/groupCall"; -import { - type ByteSentStatsReport, - type ConnectionStatsReport, - type SummaryStatsReport, -} from "matrix-js-sdk/lib/webrtc/stats/statsReport"; - -export class ObjectFlattener { - public static flattenReportObject( - prefix: string, - report: ConnectionStatsReport | ByteSentStatsReport, - ): Attributes { - const flatObject = {}; - ObjectFlattener.flattenObjectRecursive(report, flatObject, `${prefix}.`, 0); - return flatObject; - } - - public static flattenByteSentStatsReportObject( - statsReport: GroupCallStatsReport, - ): Attributes { - const flatObject = {}; - ObjectFlattener.flattenObjectRecursive( - statsReport.report, - flatObject, - "matrix.stats.bytesSent.", - 0, - ); - return flatObject; - } - - public static flattenSummaryStatsReportObject( - statsReport: GroupCallStatsReport, - ): Attributes { - const flatObject = {}; - ObjectFlattener.flattenObjectRecursive( - statsReport.report, - flatObject, - "matrix.stats.summary.", - 0, - ); - return flatObject; - } - - /* Flattens out an object into a single layer with components - * of the key separated by dots - */ - public static flattenVoipEvent(event: VoipEvent): Attributes { - const flatObject = {}; - ObjectFlattener.flattenObjectRecursive( - event as unknown as Record, // XXX Types - flatObject, - "matrix.event.", - 0, - ); - - return flatObject; - } - - public static flattenObjectRecursive( - obj: object, - flatObject: Attributes, - prefix: string, - depth: number, - ): void { - if (depth > 10) - throw new Error( - "Depth limit exceeded: aborting VoipEvent recursion. Prefix is " + - prefix, - ); - let entries; - if (obj instanceof Map) { - entries = obj.entries(); - } else { - entries = Object.entries(obj); - } - for (const [k, v] of entries) { - if (["string", "number", "boolean"].includes(typeof v) || v === null) { - let value; - value = v === null ? "null" : v; - value = typeof v === "number" && Number.isNaN(v) ? "NaN" : value; - flatObject[prefix + k] = value; - } else if (typeof v === "object") { - ObjectFlattener.flattenObjectRecursive( - v, - flatObject, - prefix + k + ".", - depth + 1, - ); - } - } - } -} diff --git a/src/otel/otel.test.ts b/src/otel/otel.test.ts deleted file mode 100644 index 0bf0573f2..000000000 --- a/src/otel/otel.test.ts +++ /dev/null @@ -1,79 +0,0 @@ -/* -Copyright 2025 New Vector Ltd. - -SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial -Please see LICENSE in the repository root for full details. -*/ - -import { - expect, - describe, - it, - vi, - beforeEach, - beforeAll, - afterAll, -} from "vitest"; - -import { ElementCallOpenTelemetry } from "./otel"; -import { mockConfig } from "../utils/test"; - -describe("ElementCallOpenTelemetry", () => { - describe("embedded package", () => { - beforeAll(() => { - vi.stubEnv("VITE_PACKAGE", "embedded"); - }); - - beforeEach(() => { - mockConfig({}); - }); - - afterAll(() => { - vi.unstubAllEnvs(); - }); - - it("does not create instance without config value", () => { - ElementCallOpenTelemetry.globalInit(); - expect(ElementCallOpenTelemetry.instance?.isOtlpEnabled).toBe(false); - }); - - it("ignores config value and does not create instance", () => { - mockConfig({ - opentelemetry: { - collector_url: "https://collector.example.com.localhost", - }, - }); - ElementCallOpenTelemetry.globalInit(); - expect(ElementCallOpenTelemetry.instance?.isOtlpEnabled).toBe(false); - }); - }); - - describe("full package", () => { - beforeAll(() => { - vi.stubEnv("VITE_PACKAGE", "full"); - }); - - beforeEach(() => { - mockConfig({}); - }); - - afterAll(() => { - vi.unstubAllEnvs(); - }); - - it("does not create instance without config value", () => { - ElementCallOpenTelemetry.globalInit(); - expect(ElementCallOpenTelemetry.instance?.isOtlpEnabled).toBe(false); - }); - - it("creates instance with config value", () => { - mockConfig({ - opentelemetry: { - collector_url: "https://collector.example.com.localhost", - }, - }); - ElementCallOpenTelemetry.globalInit(); - expect(ElementCallOpenTelemetry.instance?.isOtlpEnabled).toBe(true); - }); - }); -}); diff --git a/src/otel/otel.ts b/src/otel/otel.ts deleted file mode 100644 index 915c3d587..000000000 --- a/src/otel/otel.ts +++ /dev/null @@ -1,117 +0,0 @@ -/* -Copyright 2023, 2024 New Vector Ltd. - -SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial -Please see LICENSE in the repository root for full details. -*/ - -import { - SimpleSpanProcessor, - type SpanProcessor, -} from "@opentelemetry/sdk-trace-base"; -import { OTLPTraceExporter } from "@opentelemetry/exporter-trace-otlp-http"; -import { WebTracerProvider } from "@opentelemetry/sdk-trace-web"; -import opentelemetry, { type Tracer } from "@opentelemetry/api"; -import { resourceFromAttributes } from "@opentelemetry/resources"; -import { ATTR_SERVICE_NAME } from "@opentelemetry/semantic-conventions"; -import { logger } from "matrix-js-sdk/lib/logger"; - -import { PosthogSpanProcessor } from "../analytics/PosthogSpanProcessor"; -import { Config } from "../config/Config"; -import { RageshakeSpanProcessor } from "../analytics/RageshakeSpanProcessor"; -import { getRageshakeSubmitUrl } from "../settings/submit-rageshake"; - -const SERVICE_NAME = "element-call"; - -let sharedInstance: ElementCallOpenTelemetry; - -export class ElementCallOpenTelemetry { - private _provider: WebTracerProvider; - private _tracer: Tracer; - private otlpExporter?: OTLPTraceExporter; - public readonly rageshakeProcessor?: RageshakeSpanProcessor; - - public static globalInit(): void { - // this is only supported in the full package as the is currently no support for passing in the collector URL from the widget host - const collectorUrl = - import.meta.env.VITE_PACKAGE === "full" - ? Config.get().opentelemetry?.collector_url - : undefined; - // we always enable opentelemetry in general. We only enable the OTLP - // collector if a URL is defined (and in future if another setting is defined) - // Posthog reporting is enabled or disabled - // within the posthog code. - const shouldEnableOtlp = Boolean(collectorUrl); - - if (!sharedInstance || sharedInstance.isOtlpEnabled !== shouldEnableOtlp) { - logger.info("(Re)starting OpenTelemetry debug reporting"); - sharedInstance?.dispose(); - - sharedInstance = new ElementCallOpenTelemetry( - collectorUrl, - getRageshakeSubmitUrl(), - ); - } - } - - public static get instance(): ElementCallOpenTelemetry { - return sharedInstance; - } - - private constructor( - collectorUrl: string | undefined, - rageshakeUrl: string | undefined, - ) { - const spanProcessors: SpanProcessor[] = []; - - if (collectorUrl) { - logger.info("Enabling OTLP collector with URL " + collectorUrl); - this.otlpExporter = new OTLPTraceExporter({ - url: collectorUrl, - }); - spanProcessors.push(new SimpleSpanProcessor(this.otlpExporter)); - } else { - logger.info("OTLP collector disabled"); - } - - if (rageshakeUrl) { - this.rageshakeProcessor = new RageshakeSpanProcessor(); - spanProcessors.push(this.rageshakeProcessor); - } - - spanProcessors.push(new PosthogSpanProcessor()); - - this._provider = new WebTracerProvider({ - resource: resourceFromAttributes({ - // This is how we can make Jaeger show a reasonable service in the dropdown on the left. - [ATTR_SERVICE_NAME]: SERVICE_NAME, - }), - spanProcessors, - }); - - opentelemetry.trace.setGlobalTracerProvider(this._provider); - this._tracer = opentelemetry.trace.getTracer( - // This is not the serviceName shown in jaeger - "my-element-call-otl-tracer", - ); - } - - public dispose(): void { - opentelemetry.trace.disable(); - this._provider?.shutdown().catch((e) => { - logger.error("Failed to shutdown OpenTelemetry", e); - }); - } - - public get isOtlpEnabled(): boolean { - return Boolean(this.otlpExporter); - } - - public get tracer(): Tracer { - return this._tracer; - } - - public get provider(): WebTracerProvider { - return this._provider; - } -} diff --git a/src/room/InCallView.tsx b/src/room/InCallView.tsx index b17d3aaee..72a35da68 100644 --- a/src/room/InCallView.tsx +++ b/src/room/InCallView.tsx @@ -48,7 +48,6 @@ import { useCallViewKeyboardShortcuts } from "../useCallViewKeyboardShortcuts"; import { ElementWidgetActions, widget } from "../widget"; import styles from "./InCallView.module.css"; import { GridTile } from "../tile/GridTile"; -import { type OTelGroupCallMembership } from "../otel/OTelGroupCallMembership"; import { SettingsModal, defaultSettingsTab } from "../settings/SettingsModal"; import { useRageshakeRequestModal } from "../settings/submit-rageshake"; import { RageshakeRequestModal } from "./RageshakeRequestModal"; @@ -180,7 +179,6 @@ export interface InCallViewProps { matrixRoom: MatrixRoom; muteStates: MuteStates; header: HeaderStyle; - otelGroupCallMembership?: OTelGroupCallMembership; onShareClick: (() => void) | null; } diff --git a/src/settings/submit-rageshake.ts b/src/settings/submit-rageshake.ts index bfd551262..276d8e609 100644 --- a/src/settings/submit-rageshake.ts +++ b/src/settings/submit-rageshake.ts @@ -17,7 +17,6 @@ import { type CryptoApi } from "matrix-js-sdk/lib/crypto-api"; import { getLogsForReport } from "./rageshake"; import { useClient } from "../ClientContext"; import { Config } from "../config/Config"; -import { ElementCallOpenTelemetry } from "../otel/otel"; import { type RageshakeRequestModal } from "../room/RageshakeRequestModal"; import { getUrlParams } from "../UrlParams"; @@ -274,14 +273,6 @@ export function useSubmitRageshake( for (const entry of logs) { body.append("compressed-log", await gzip(entry.lines), entry.id); } - - body.append( - "file", - await gzip( - ElementCallOpenTelemetry.instance.rageshakeProcessor!.dump(), - ), - "traces.json.gz", - ); } if (opts.rageshakeRequestId) { From 2f928673831fd2730a1bb150c73e82e9433c372e Mon Sep 17 00:00:00 2001 From: Timo K Date: Mon, 24 Nov 2025 12:36:36 +0100 Subject: [PATCH 002/748] remove otel deps --- package.json | 7 -- yarn.lock | 249 +-------------------------------------------------- 2 files changed, 1 insertion(+), 255 deletions(-) diff --git a/package.json b/package.json index 62ea9f4fb..75ae74e5f 100644 --- a/package.json +++ b/package.json @@ -47,13 +47,6 @@ "@livekit/protocol": "^1.42.2", "@livekit/track-processors": "^0.5.5", "@mediapipe/tasks-vision": "^0.10.18", - "@opentelemetry/api": "^1.4.0", - "@opentelemetry/core": "^2.0.0", - "@opentelemetry/exporter-trace-otlp-http": "^0.203.0", - "@opentelemetry/resources": "^2.0.0", - "@opentelemetry/sdk-trace-base": "^2.0.0", - "@opentelemetry/sdk-trace-web": "^2.0.0", - "@opentelemetry/semantic-conventions": "^1.25.1", "@playwright/test": "^1.56.1", "@radix-ui/react-dialog": "^1.0.4", "@radix-ui/react-slider": "^1.1.2", diff --git a/yarn.lock b/yarn.lock index 97ca19859..f7b4242e2 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2989,146 +2989,6 @@ __metadata: languageName: node linkType: hard -"@opentelemetry/api-logs@npm:0.203.0": - version: 0.203.0 - resolution: "@opentelemetry/api-logs@npm:0.203.0" - dependencies: - "@opentelemetry/api": "npm:^1.3.0" - checksum: 10c0/e7a0a0ff46aaeb62192a99f45ef4889222e4fea09be25cab6fea811afc2df95c02ea050b2c98dfc0fc5a6ec6a623d87096af2751fdf91ddbb3afcab61b5325da - languageName: node - linkType: hard - -"@opentelemetry/api@npm:^1.3.0, @opentelemetry/api@npm:^1.4.0": - version: 1.9.0 - resolution: "@opentelemetry/api@npm:1.9.0" - checksum: 10c0/9aae2fe6e8a3a3eeb6c1fdef78e1939cf05a0f37f8a4fae4d6bf2e09eb1e06f966ece85805626e01ba5fab48072b94f19b835449e58b6d26720ee19a58298add - languageName: node - linkType: hard - -"@opentelemetry/core@npm:2.0.1, @opentelemetry/core@npm:^2.0.0": - version: 2.0.1 - resolution: "@opentelemetry/core@npm:2.0.1" - dependencies: - "@opentelemetry/semantic-conventions": "npm:^1.29.0" - peerDependencies: - "@opentelemetry/api": ">=1.0.0 <1.10.0" - checksum: 10c0/d587b1289559757d80da98039f9f57612f84f72ec608cd665dc467c7c6c5ce3a987dfcc2c63b521c7c86ce984a2552b3ead15a0dc458de1cf6bde5cdfe4ca9d8 - languageName: node - linkType: hard - -"@opentelemetry/exporter-trace-otlp-http@npm:^0.203.0": - version: 0.203.0 - resolution: "@opentelemetry/exporter-trace-otlp-http@npm:0.203.0" - dependencies: - "@opentelemetry/core": "npm:2.0.1" - "@opentelemetry/otlp-exporter-base": "npm:0.203.0" - "@opentelemetry/otlp-transformer": "npm:0.203.0" - "@opentelemetry/resources": "npm:2.0.1" - "@opentelemetry/sdk-trace-base": "npm:2.0.1" - peerDependencies: - "@opentelemetry/api": ^1.3.0 - checksum: 10c0/21a65ebc40dcab05cf11178e5037f96847ce344c4a855aac46dcab3f74982016318ee75fafdfeeb42f10b92a0a781b7cd8b2b5b036cbe53c14714fd13940142e - languageName: node - linkType: hard - -"@opentelemetry/otlp-exporter-base@npm:0.203.0": - version: 0.203.0 - resolution: "@opentelemetry/otlp-exporter-base@npm:0.203.0" - dependencies: - "@opentelemetry/core": "npm:2.0.1" - "@opentelemetry/otlp-transformer": "npm:0.203.0" - peerDependencies: - "@opentelemetry/api": ^1.3.0 - checksum: 10c0/ad5b771b06b192f06f332f60701d1ad208df88a05975b16e1cdd1dff8e1cb66e775b3e9de513c2f5d48f390f25ca35411ead08ce4849c8203b86a264d34561d3 - languageName: node - linkType: hard - -"@opentelemetry/otlp-transformer@npm:0.203.0": - version: 0.203.0 - resolution: "@opentelemetry/otlp-transformer@npm:0.203.0" - dependencies: - "@opentelemetry/api-logs": "npm:0.203.0" - "@opentelemetry/core": "npm:2.0.1" - "@opentelemetry/resources": "npm:2.0.1" - "@opentelemetry/sdk-logs": "npm:0.203.0" - "@opentelemetry/sdk-metrics": "npm:2.0.1" - "@opentelemetry/sdk-trace-base": "npm:2.0.1" - protobufjs: "npm:^7.3.0" - peerDependencies: - "@opentelemetry/api": ^1.3.0 - checksum: 10c0/3f7b4bfe4bcab4db434ff2c4e59b53de53642d379b80056610456d8e9ae0cbab0f8b69f088078637b7b5ceffd0ac2fda68469c5f295b1c0ac625f522f640338c - languageName: node - linkType: hard - -"@opentelemetry/resources@npm:2.0.1, @opentelemetry/resources@npm:^2.0.0": - version: 2.0.1 - resolution: "@opentelemetry/resources@npm:2.0.1" - dependencies: - "@opentelemetry/core": "npm:2.0.1" - "@opentelemetry/semantic-conventions": "npm:^1.29.0" - peerDependencies: - "@opentelemetry/api": ">=1.3.0 <1.10.0" - checksum: 10c0/96532b7553b26607a7a892d72f6b03ad12bd542dc23c95135a8ae40362da9c883c21a4cff3d2296d9e0e9bd899a5977e325ed52d83142621a8ffe81d08d99341 - languageName: node - linkType: hard - -"@opentelemetry/sdk-logs@npm:0.203.0": - version: 0.203.0 - resolution: "@opentelemetry/sdk-logs@npm:0.203.0" - dependencies: - "@opentelemetry/api-logs": "npm:0.203.0" - "@opentelemetry/core": "npm:2.0.1" - "@opentelemetry/resources": "npm:2.0.1" - peerDependencies: - "@opentelemetry/api": ">=1.4.0 <1.10.0" - checksum: 10c0/02dd9d9969628f05f71ae1d149f1aa6d1fee2dad607923a68a1cfc923e94b046dcc0e18e85e865324e3bda0cee7a5a0ba9fa0d57e4e95fa672be103e2ce60270 - languageName: node - linkType: hard - -"@opentelemetry/sdk-metrics@npm:2.0.1": - version: 2.0.1 - resolution: "@opentelemetry/sdk-metrics@npm:2.0.1" - dependencies: - "@opentelemetry/core": "npm:2.0.1" - "@opentelemetry/resources": "npm:2.0.1" - peerDependencies: - "@opentelemetry/api": ">=1.9.0 <1.10.0" - checksum: 10c0/fcf7ae23d459e5da7cb6fe150064b6dc4e11e47925b08980c3b357bd5534ad388898bbacd0ff8befef6801f43b35142dc7123f028ffde2d0fe2bd72177d07639 - languageName: node - linkType: hard - -"@opentelemetry/sdk-trace-base@npm:2.0.1, @opentelemetry/sdk-trace-base@npm:^2.0.0": - version: 2.0.1 - resolution: "@opentelemetry/sdk-trace-base@npm:2.0.1" - dependencies: - "@opentelemetry/core": "npm:2.0.1" - "@opentelemetry/resources": "npm:2.0.1" - "@opentelemetry/semantic-conventions": "npm:^1.29.0" - peerDependencies: - "@opentelemetry/api": ">=1.3.0 <1.10.0" - checksum: 10c0/4e3c733296012b758d007e9c0d8a5b175edbe9a680c73ec75303476e7982b73ad4209f1a2791c1a94c428e5a53eba6c2a72faa430c70336005aa58744d6cb37b - languageName: node - linkType: hard - -"@opentelemetry/sdk-trace-web@npm:^2.0.0": - version: 2.0.1 - resolution: "@opentelemetry/sdk-trace-web@npm:2.0.1" - dependencies: - "@opentelemetry/core": "npm:2.0.1" - "@opentelemetry/sdk-trace-base": "npm:2.0.1" - peerDependencies: - "@opentelemetry/api": ">=1.0.0 <1.10.0" - checksum: 10c0/48821b91430e24378b0b5b2632e78efdd018a3f840462a6aeba6ce318a6480bad2f623cc7f7f625a9266028ad44b78eb8456181778de6cb18725f26c44e2729b - languageName: node - linkType: hard - -"@opentelemetry/semantic-conventions@npm:^1.25.1, @opentelemetry/semantic-conventions@npm:^1.29.0": - version: 1.36.0 - resolution: "@opentelemetry/semantic-conventions@npm:1.36.0" - checksum: 10c0/edc8a6fe3ec4fc0c67ba3a92b86fb3dcc78fe1eb4f19838d8013c3232b9868540a034dd25cfe0afdd5eae752c5f0e9f42272ff46da144a2d5b35c644478e1c62 - languageName: node - linkType: hard - "@oxc-resolver/binding-darwin-arm64@npm:11.3.0": version: 11.3.0 resolution: "@oxc-resolver/binding-darwin-arm64@npm:11.3.0" @@ -3384,79 +3244,6 @@ __metadata: languageName: node linkType: hard -"@protobufjs/aspromise@npm:^1.1.1, @protobufjs/aspromise@npm:^1.1.2": - version: 1.1.2 - resolution: "@protobufjs/aspromise@npm:1.1.2" - checksum: 10c0/a83343a468ff5b5ec6bff36fd788a64c839e48a07ff9f4f813564f58caf44d011cd6504ed2147bf34835bd7a7dd2107052af755961c6b098fd8902b4f6500d0f - languageName: node - linkType: hard - -"@protobufjs/base64@npm:^1.1.2": - version: 1.1.2 - resolution: "@protobufjs/base64@npm:1.1.2" - checksum: 10c0/eec925e681081af190b8ee231f9bad3101e189abbc182ff279da6b531e7dbd2a56f1f306f37a80b1be9e00aa2d271690d08dcc5f326f71c9eed8546675c8caf6 - languageName: node - linkType: hard - -"@protobufjs/codegen@npm:^2.0.4": - version: 2.0.4 - resolution: "@protobufjs/codegen@npm:2.0.4" - checksum: 10c0/26ae337c5659e41f091606d16465bbcc1df1f37cc1ed462438b1f67be0c1e28dfb2ca9f294f39100c52161aef82edf758c95d6d75650a1ddf31f7ddee1440b43 - languageName: node - linkType: hard - -"@protobufjs/eventemitter@npm:^1.1.0": - version: 1.1.0 - resolution: "@protobufjs/eventemitter@npm:1.1.0" - checksum: 10c0/1eb0a75180e5206d1033e4138212a8c7089a3d418c6dfa5a6ce42e593a4ae2e5892c4ef7421f38092badba4040ea6a45f0928869989411001d8c1018ea9a6e70 - languageName: node - linkType: hard - -"@protobufjs/fetch@npm:^1.1.0": - version: 1.1.0 - resolution: "@protobufjs/fetch@npm:1.1.0" - dependencies: - "@protobufjs/aspromise": "npm:^1.1.1" - "@protobufjs/inquire": "npm:^1.1.0" - checksum: 10c0/cda6a3dc2d50a182c5865b160f72077aac197046600091dbb005dd0a66db9cce3c5eaed6d470ac8ed49d7bcbeef6ee5f0bc288db5ff9a70cbd003e5909065233 - languageName: node - linkType: hard - -"@protobufjs/float@npm:^1.0.2": - version: 1.0.2 - resolution: "@protobufjs/float@npm:1.0.2" - checksum: 10c0/18f2bdede76ffcf0170708af15c9c9db6259b771e6b84c51b06df34a9c339dbbeec267d14ce0bddd20acc142b1d980d983d31434398df7f98eb0c94a0eb79069 - languageName: node - linkType: hard - -"@protobufjs/inquire@npm:^1.1.0": - version: 1.1.0 - resolution: "@protobufjs/inquire@npm:1.1.0" - checksum: 10c0/64372482efcba1fb4d166a2664a6395fa978b557803857c9c03500e0ac1013eb4b1aacc9ed851dd5fc22f81583670b4f4431bae186f3373fedcfde863ef5921a - languageName: node - linkType: hard - -"@protobufjs/path@npm:^1.1.2": - version: 1.1.2 - resolution: "@protobufjs/path@npm:1.1.2" - checksum: 10c0/cece0a938e7f5dfd2fa03f8c14f2f1cf8b0d6e13ac7326ff4c96ea311effd5fb7ae0bba754fbf505312af2e38500250c90e68506b97c02360a43793d88a0d8b4 - languageName: node - linkType: hard - -"@protobufjs/pool@npm:^1.1.0": - version: 1.1.0 - resolution: "@protobufjs/pool@npm:1.1.0" - checksum: 10c0/eda2718b7f222ac6e6ad36f758a92ef90d26526026a19f4f17f668f45e0306a5bd734def3f48f51f8134ae0978b6262a5c517c08b115a551756d1a3aadfcf038 - languageName: node - linkType: hard - -"@protobufjs/utf8@npm:^1.1.0": - version: 1.1.0 - resolution: "@protobufjs/utf8@npm:1.1.0" - checksum: 10c0/a3fe31fe3fa29aa3349e2e04ee13dc170cc6af7c23d92ad49e3eeaf79b9766264544d3da824dba93b7855bd6a2982fb40032ef40693da98a136d835752beb487 - languageName: node - linkType: hard - "@radix-ui/number@npm:1.1.1": version: 1.1.1 resolution: "@radix-ui/number@npm:1.1.1" @@ -5240,7 +5027,7 @@ __metadata: languageName: node linkType: hard -"@types/node@npm:*, @types/node@npm:>=13.7.0": +"@types/node@npm:*": version: 24.1.0 resolution: "@types/node@npm:24.1.0" dependencies: @@ -7485,13 +7272,6 @@ __metadata: "@livekit/protocol": "npm:^1.42.2" "@livekit/track-processors": "npm:^0.5.5" "@mediapipe/tasks-vision": "npm:^0.10.18" - "@opentelemetry/api": "npm:^1.4.0" - "@opentelemetry/core": "npm:^2.0.0" - "@opentelemetry/exporter-trace-otlp-http": "npm:^0.203.0" - "@opentelemetry/resources": "npm:^2.0.0" - "@opentelemetry/sdk-trace-base": "npm:^2.0.0" - "@opentelemetry/sdk-trace-web": "npm:^2.0.0" - "@opentelemetry/semantic-conventions": "npm:^1.25.1" "@playwright/test": "npm:^1.56.1" "@radix-ui/react-dialog": "npm:^1.0.4" "@radix-ui/react-slider": "npm:^1.1.2" @@ -10198,13 +9978,6 @@ __metadata: languageName: node linkType: hard -"long@npm:^5.0.0": - version: 5.3.1 - resolution: "long@npm:5.3.1" - checksum: 10c0/8726994c6359bb7162fb94563e14c3f9c0f0eeafd90ec654738f4f144a5705756d36a873c442f172ee2a4b51e08d14ab99765b49aa1fb994c5ba7fe12057bca2 - languageName: node - linkType: hard - "loose-envify@npm:^1.4.0": version: 1.4.0 resolution: "loose-envify@npm:1.4.0" @@ -11718,26 +11491,6 @@ __metadata: languageName: node linkType: hard -"protobufjs@npm:^7.3.0": - version: 7.4.0 - resolution: "protobufjs@npm:7.4.0" - dependencies: - "@protobufjs/aspromise": "npm:^1.1.2" - "@protobufjs/base64": "npm:^1.1.2" - "@protobufjs/codegen": "npm:^2.0.4" - "@protobufjs/eventemitter": "npm:^1.1.0" - "@protobufjs/fetch": "npm:^1.1.0" - "@protobufjs/float": "npm:^1.0.2" - "@protobufjs/inquire": "npm:^1.1.0" - "@protobufjs/path": "npm:^1.1.2" - "@protobufjs/pool": "npm:^1.1.0" - "@protobufjs/utf8": "npm:^1.1.0" - "@types/node": "npm:>=13.7.0" - long: "npm:^5.0.0" - checksum: 10c0/a5460a63fe596523b9a067cbce39a6b310d1a71750fda261f076535662aada97c24450e18c5bc98a27784f70500615904ff1227e1742183509f0db4fdede669b - languageName: node - linkType: hard - "proxy-from-env@npm:^1.1.0": version: 1.1.0 resolution: "proxy-from-env@npm:1.1.0" From 8bf651837139184c107582c5d74c135934455035 Mon Sep 17 00:00:00 2001 From: Timo K Date: Mon, 24 Nov 2025 12:42:00 +0100 Subject: [PATCH 003/748] remove span processor endpoints --- src/analytics/PosthogSpanProcessor.ts | 157 ------------------------ src/analytics/RageshakeSpanProcessor.ts | 135 -------------------- 2 files changed, 292 deletions(-) delete mode 100644 src/analytics/PosthogSpanProcessor.ts delete mode 100644 src/analytics/RageshakeSpanProcessor.ts diff --git a/src/analytics/PosthogSpanProcessor.ts b/src/analytics/PosthogSpanProcessor.ts deleted file mode 100644 index a00462002..000000000 --- a/src/analytics/PosthogSpanProcessor.ts +++ /dev/null @@ -1,157 +0,0 @@ -/* -Copyright 2023, 2024 New Vector Ltd. - -SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial -Please see LICENSE in the repository root for full details. -*/ - -import { - type SpanProcessor, - type ReadableSpan, - type Span, -} from "@opentelemetry/sdk-trace-base"; -import { hrTimeToMilliseconds } from "@opentelemetry/core"; -import { logger } from "matrix-js-sdk/lib/logger"; - -import { PosthogAnalytics } from "./PosthogAnalytics"; - -interface PrevCall { - callId: string; - hangupTs: number; -} - -/** - * The maximum time between hanging up and joining the same call that we would - * consider a 'rejoin' on the user's part. - */ -const maxRejoinMs = 2 * 60 * 1000; // 2 minutes - -/** - * Span processor that extracts certain metrics from spans to send to PostHog - */ -export class PosthogSpanProcessor implements SpanProcessor { - public async forceFlush(): Promise {} - - public onStart(span: Span): void { - // Hack: Yield to allow attributes to be set before processing - try { - switch (span.name) { - case "matrix.groupCallMembership": - this.onGroupCallMembershipStart(span); - return; - case "matrix.groupCallMembership.summaryReport": - this.onSummaryReportStart(span); - return; - } - } catch (e) { - // log to avoid tripping @typescript-eslint/no-unused-vars - logger.debug(e); - } - } - - public onEnd(span: ReadableSpan): void { - switch (span.name) { - case "matrix.groupCallMembership": - this.onGroupCallMembershipEnd(span); - return; - } - } - - private get prevCall(): PrevCall | null { - // This is stored in localStorage so we can remember the previous call - // across app restarts - const data = localStorage.getItem("matrix-prev-call"); - if (data === null) return null; - - try { - return JSON.parse(data); - } catch (e) { - logger.warn("Invalid prev call data", data, "error:", e); - return null; - } - } - - private set prevCall(data: PrevCall | null) { - localStorage.setItem("matrix-prev-call", JSON.stringify(data)); - } - - private onGroupCallMembershipStart(span: ReadableSpan): void { - const prevCall = this.prevCall; - const newCallId = span.attributes["matrix.confId"] as string; - - // If the user joined the same call within a short time frame, log this as a - // rejoin. This is interesting as a call quality metric, since rejoins may - // indicate that users had to intervene to make the product work. - if (prevCall !== null && newCallId === prevCall.callId) { - const duration = hrTimeToMilliseconds(span.startTime) - prevCall.hangupTs; - if (duration <= maxRejoinMs) { - PosthogAnalytics.instance.trackEvent({ - eventName: "Rejoin", - callId: prevCall.callId, - rejoinDuration: duration, - }); - } - } - } - - private onGroupCallMembershipEnd(span: ReadableSpan): void { - this.prevCall = { - callId: span.attributes["matrix.confId"] as string, - hangupTs: hrTimeToMilliseconds(span.endTime), - }; - } - - private onSummaryReportStart(span: ReadableSpan): void { - // Searching for an event like this: - // matrix.stats.summary - // matrix.stats.summary.percentageReceivedAudioMedia: 0.75 - // matrix.stats.summary.percentageReceivedMedia: 1 - // matrix.stats.summary.percentageReceivedVideoMedia: 0.75 - // matrix.stats.summary.maxJitter: 100 - // matrix.stats.summary.maxPacketLoss: 20 - const event = span.events.find((e) => e.name === "matrix.stats.summary"); - if (event !== undefined) { - const attributes = event.attributes; - if (attributes) { - const mediaReceived = `${attributes["matrix.stats.summary.percentageReceivedMedia"]}`; - const videoReceived = `${attributes["matrix.stats.summary.percentageReceivedVideoMedia"]}`; - const audioReceived = `${attributes["matrix.stats.summary.percentageReceivedAudioMedia"]}`; - const maxJitter = `${attributes["matrix.stats.summary.maxJitter"]}`; - const maxPacketLoss = `${attributes["matrix.stats.summary.maxPacketLoss"]}`; - const peerConnections = `${attributes["matrix.stats.summary.peerConnections"]}`; - const percentageConcealedAudio = `${attributes["matrix.stats.summary.percentageConcealedAudio"]}`; - const opponentUsersInCall = `${attributes["matrix.stats.summary.opponentUsersInCall"]}`; - const opponentDevicesInCall = `${attributes["matrix.stats.summary.opponentDevicesInCall"]}`; - const diffDevicesToPeerConnections = `${attributes["matrix.stats.summary.diffDevicesToPeerConnections"]}`; - const ratioPeerConnectionToDevices = `${attributes["matrix.stats.summary.ratioPeerConnectionToDevices"]}`; - - PosthogAnalytics.instance.trackEvent( - { - eventName: "MediaReceived", - callId: span.attributes["matrix.confId"] as string, - mediaReceived: mediaReceived, - audioReceived: audioReceived, - videoReceived: videoReceived, - maxJitter: maxJitter, - maxPacketLoss: maxPacketLoss, - peerConnections: peerConnections, - percentageConcealedAudio: percentageConcealedAudio, - opponentUsersInCall: opponentUsersInCall, - opponentDevicesInCall: opponentDevicesInCall, - diffDevicesToPeerConnections: diffDevicesToPeerConnections, - ratioPeerConnectionToDevices: ratioPeerConnectionToDevices, - }, - // Send instantly because the window might be closing - { send_instantly: true }, - ); - } - } - } - - /** - * Shutdown the processor. - */ - public async shutdown(): Promise { - return Promise.resolve(); - } -} diff --git a/src/analytics/RageshakeSpanProcessor.ts b/src/analytics/RageshakeSpanProcessor.ts deleted file mode 100644 index eca657db9..000000000 --- a/src/analytics/RageshakeSpanProcessor.ts +++ /dev/null @@ -1,135 +0,0 @@ -/* -Copyright 2023, 2024 New Vector Ltd. - -SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial -Please see LICENSE in the repository root for full details. -*/ - -import { type AttributeValue, type Attributes } from "@opentelemetry/api"; -import { hrTimeToMicroseconds } from "@opentelemetry/core"; -import { - type SpanProcessor, - type ReadableSpan, - type Span, -} from "@opentelemetry/sdk-trace-base"; - -const dumpAttributes = ( - attr: Attributes, -): { - key: string; - type: - | "string" - | "number" - | "bigint" - | "boolean" - | "symbol" - | "undefined" - | "object" - | "function"; - value: AttributeValue | undefined; -}[] => - Object.entries(attr).map(([key, value]) => ({ - key, - type: typeof value, - value, - })); - -/** - * Exports spans on demand to the Jaeger JSON format, which can be attached to - * rageshakes and loaded into analysis tools like Jaeger and Stalk. - */ -export class RageshakeSpanProcessor implements SpanProcessor { - private readonly spans: ReadableSpan[] = []; - - public async forceFlush(): Promise {} - - public onStart(span: Span): void { - this.spans.push(span); - } - - public onEnd(): void {} - - /** - * Dumps the spans collected so far as Jaeger-compatible JSON. - */ - public dump(): string { - const now = Date.now() * 1000; // Jaeger works in microseconds - const traces = new Map(); - - // Organize spans by their trace IDs - for (const span of this.spans) { - const traceId = span.spanContext().traceId; - let trace = traces.get(traceId); - - if (trace === undefined) { - trace = []; - traces.set(traceId, trace); - } - - trace.push(span); - } - - const processId = "p1"; - const processes = { - [processId]: { - serviceName: "element-call", - tags: [], - }, - warnings: null, - }; - - return JSON.stringify({ - // Honestly not sure what some of these fields mean, I just know that - // they're present in Jaeger JSON exports - total: 0, - limit: 0, - offset: 0, - errors: null, - data: [...traces.entries()].map(([traceId, spans]) => ({ - traceID: traceId, - warnings: null, - processes, - spans: spans.map((span) => { - const ctx = span.spanContext(); - const startTime = hrTimeToMicroseconds(span.startTime); - // If the span has not yet ended, pretend that it ends now - const duration = - span.duration[0] === -1 - ? now - startTime - : hrTimeToMicroseconds(span.duration); - - return { - traceID: traceId, - spanID: ctx.spanId, - operationName: span.name, - processID: processId, - warnings: null, - startTime, - duration, - references: - span.parentSpanContext?.spanId === undefined - ? [] - : [ - { - refType: "CHILD_OF", - traceID: traceId, - spanID: span.parentSpanContext?.spanId, - }, - ], - tags: dumpAttributes(span.attributes), - logs: span.events.map((event) => ({ - timestamp: hrTimeToMicroseconds(event.time), - // The name of the event is in the "event" field, aparently. - fields: [ - ...dumpAttributes(event.attributes ?? {}), - { key: "event", type: "string", value: event.name }, - ], - })), - }; - }), - })), - }); - } - - public async shutdown(): Promise {} -} From e2607d6399c29a97744cb8c071271202b681e711 Mon Sep 17 00:00:00 2001 From: Valere Date: Tue, 25 Nov 2025 11:10:53 +0100 Subject: [PATCH 004/748] Config: UrlParams to control noiseSuppression and echoCancellation --- src/UrlParams.test.ts | 35 +++++ src/UrlParams.ts | 13 ++ src/state/CallViewModel/CallViewModel.ts | 2 + .../remoteMembers/ConnectionFactory.ts | 12 +- .../remoteMembers/ECConnectionFactory.test.ts | 134 ++++++++++++++++++ 5 files changed, 195 insertions(+), 1 deletion(-) create mode 100644 src/state/CallViewModel/remoteMembers/ECConnectionFactory.test.ts diff --git a/src/UrlParams.test.ts b/src/UrlParams.test.ts index cd8fc6d56..cd195f545 100644 --- a/src/UrlParams.test.ts +++ b/src/UrlParams.test.ts @@ -332,6 +332,41 @@ describe("UrlParams", () => { expect(computeUrlParams("?intent=join_existing").skipLobby).toBe(false); }); }); + + describe("noiseSuppression", () => { + it("defaults to true", () => { + expect(computeUrlParams().noiseSuppression).toBe(true); + }); + + it("is parsed", () => { + expect(computeUrlParams("?intent=start_call&noiseSuppression=true").noiseSuppression).toBe( + true, + ); + expect(computeUrlParams("?intent=start_call&noiseSuppression&bar=foo").noiseSuppression).toBe( + true, + ); + expect(computeUrlParams("?noiseSuppression=false").noiseSuppression).toBe( + false, + ); + }); + }); + + + describe("echoCancellation", () => { + it("defaults to true", () => { + expect(computeUrlParams().echoCancellation).toBe(true); + }); + + it("is parsed", () => { + expect(computeUrlParams("?echoCancellation=true").echoCancellation).toBe( + true, + ); + expect(computeUrlParams("?echoCancellation=false").echoCancellation).toBe( + false, + ); + }); + }); + describe("header", () => { it("uses header if provided", () => { expect(computeUrlParams("?header=app_bar&hideHeader=true").header).toBe( diff --git a/src/UrlParams.ts b/src/UrlParams.ts index 4eb692986..f78841fb9 100644 --- a/src/UrlParams.ts +++ b/src/UrlParams.ts @@ -233,6 +233,17 @@ export interface UrlConfiguration { */ waitForCallPickup: boolean; + /** + * Whether to enable echo cancellation for audio capture. + * Defaults to true. + */ + echoCancellation?: boolean; + /** + * Whether to enable noise suppression for audio capture. + * Defaults to true. + */ + noiseSuppression?: boolean; + callIntent?: RTCCallIntent; } interface IntentAndPlatformDerivedConfiguration { @@ -525,6 +536,8 @@ export const computeUrlParams = (search = "", hash = ""): UrlParams => { ]), waitForCallPickup: parser.getFlag("waitForCallPickup"), autoLeaveWhenOthersLeft: parser.getFlag("autoLeave"), + noiseSuppression: parser.getFlagParam("noiseSuppression", true), + echoCancellation: parser.getFlagParam("echoCancellation", true), }; // Log the final configuration for debugging purposes. diff --git a/src/state/CallViewModel/CallViewModel.ts b/src/state/CallViewModel/CallViewModel.ts index 506eca1b8..b4df27381 100644 --- a/src/state/CallViewModel/CallViewModel.ts +++ b/src/state/CallViewModel/CallViewModel.ts @@ -415,6 +415,8 @@ export function createCallViewModel$( livekitKeyProvider, getUrlParams().controlledAudioDevices, options.livekitRoomFactory, + getUrlParams().echoCancellation, + getUrlParams().noiseSuppression, ); const connectionManager = createConnectionManager$({ diff --git a/src/state/CallViewModel/remoteMembers/ConnectionFactory.ts b/src/state/CallViewModel/remoteMembers/ConnectionFactory.ts index f58fcb764..c3a68c54b 100644 --- a/src/state/CallViewModel/remoteMembers/ConnectionFactory.ts +++ b/src/state/CallViewModel/remoteMembers/ConnectionFactory.ts @@ -41,8 +41,10 @@ export class ECConnectionFactory implements ConnectionFactory { * @param client - The OpenID client parts for authentication, needed to get openID and JWT tokens. * @param devices - Used for video/audio out/in capture options. * @param processorState$ - Effects like background blur (only for publishing connection?) - * @param e2eeLivekitOptions - The E2EE options to use for the LiveKit Room. + * @param livekitKeyProvider * @param controlledAudioDevices - Option to indicate whether audio output device is controlled externally (native mobile app). + * @param echoCancellation - Whether to enable echo cancellation for audio capture. + * @param noiseSuppression - Whether to enable noise suppression for audio capture. * @param livekitRoomFactory - Optional factory function (for testing) to create LivekitRoom instances. If not provided, a default factory is used. */ public constructor( @@ -52,6 +54,8 @@ export class ECConnectionFactory implements ConnectionFactory { livekitKeyProvider: BaseKeyProvider | undefined, private controlledAudioDevices: boolean, livekitRoomFactory?: () => LivekitRoom, + echoCancellation: boolean = true, + noiseSuppression: boolean = true, ) { const defaultFactory = (): LivekitRoom => new LivekitRoom( @@ -65,6 +69,8 @@ export class ECConnectionFactory implements ConnectionFactory { worker: new E2EEWorker(), }, this.controlledAudioDevices, + echoCancellation, + noiseSuppression, ), ); this.livekitRoomFactory = livekitRoomFactory ?? defaultFactory; @@ -95,6 +101,8 @@ function generateRoomOption( processorState: ProcessorState, e2eeLivekitOptions: E2EEOptions | undefined, controlledAudioDevices: boolean, + echoCancellation: boolean, + noiseSuppression: boolean, ): RoomOptions { return { ...defaultLiveKitOptions, @@ -106,6 +114,8 @@ function generateRoomOption( audioCaptureDefaults: { ...defaultLiveKitOptions.audioCaptureDefaults, deviceId: devices.audioInput.selected$.value?.id, + echoCancellation, + noiseSuppression, }, audioOutput: { // When using controlled audio devices, we don't want to set the diff --git a/src/state/CallViewModel/remoteMembers/ECConnectionFactory.test.ts b/src/state/CallViewModel/remoteMembers/ECConnectionFactory.test.ts new file mode 100644 index 000000000..cbf334be1 --- /dev/null +++ b/src/state/CallViewModel/remoteMembers/ECConnectionFactory.test.ts @@ -0,0 +1,134 @@ +/* +Copyright 2025 Element Creations Ltd. + +SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial +Please see LICENSE in the repository root for full details. +*/ + +import { afterEach, beforeEach, describe, expect, test, vi } from "vitest"; +import { Room as LivekitRoom } from "livekit-client"; +import { BehaviorSubject } from "rxjs"; +import fetchMock from "fetch-mock"; +import { logger } from "matrix-js-sdk/lib/logger"; +import EventEmitter from "events"; + +import { ObservableScope } from "../../ObservableScope.ts"; +import { ECConnectionFactory } from "./ConnectionFactory.ts"; +import type { OpenIDClientParts } from "../../../livekit/openIDSFU.ts"; +import { exampleTransport, mockMediaDevices } from "../../../utils/test.ts"; +import type { ProcessorState } from "../../../livekit/TrackProcessorContext.tsx"; +import { constant } from "../../Behavior"; + +// At the top of your test file, after imports +vi.mock("livekit-client", async () => { + const actual = await vi.importActual("livekit-client"); + return { + ...actual, + Room: vi.fn().mockImplementation(function (this: LivekitRoom, options) { + const emitter = new EventEmitter(); + return { + on: emitter.on.bind(emitter), + off: emitter.off.bind(emitter), + emit: emitter.emit.bind(emitter), + disconnect: vi.fn(), + remoteParticipants: new Map(), + } as unknown as LivekitRoom; + }), + }; +}); + +let testScope: ObservableScope; +let mockClient: OpenIDClientParts; + +beforeEach(() => { + testScope = new ObservableScope(); + mockClient = { + getOpenIdToken: vi.fn().mockReturnValue(""), + getDeviceId: vi.fn().mockReturnValue("DEV000"), + }; +}); + +describe("ECConnectionFactory - Audio inputs options", () => { + test.each([ + { echo: true, noise: true }, + { echo: true, noise: false }, + { echo: false, noise: true }, + { echo: false, noise: false }, + ])( + "it sets echoCancellation=$echo and noiseSuppression=$noise based on constructor parameters", + ({ echo, noise }) => { + // test("it sets echoCancellation and noiseSuppression based on constructor parameters", () => { + const RoomConstructor = vi.mocked(LivekitRoom); + + const ecConnectionFactory = new ECConnectionFactory( + mockClient, + mockMediaDevices({}), + new BehaviorSubject({ + supported: true, + processor: undefined, + }), + undefined, + false, + undefined, + echo, + noise, + ); + ecConnectionFactory.createConnection(exampleTransport, testScope, logger); + + // Check if Room was constructed with expected options + expect(RoomConstructor).toHaveBeenCalledWith( + expect.objectContaining({ + audioCaptureDefaults: expect.objectContaining({ + echoCancellation: echo, + noiseSuppression: noise, + }), + }), + ); + }, + ); +}); + +describe("ECConnectionFactory - ControlledAudioDevice", () => { + test.each([{ controlled: true }, { controlled: false }])( + "it sets controlledAudioDevice=$controlled then uses deviceId accordingly", + ({ controlled }) => { + // test("it sets echoCancellation and noiseSuppression based on constructor parameters", () => { + const RoomConstructor = vi.mocked(LivekitRoom); + + const ecConnectionFactory = new ECConnectionFactory( + mockClient, + mockMediaDevices({ + audioOutput: { + available$: constant(new Map()), + selected$: constant({ id: "DEV00", virtualEarpiece: false }), + select: () => {}, + } + }), + new BehaviorSubject({ + supported: true, + processor: undefined, + }), + undefined, + controlled, + undefined, + false, + false, + ); + ecConnectionFactory.createConnection(exampleTransport, testScope, logger); + + // Check if Room was constructed with expected options + expect(RoomConstructor).toHaveBeenCalledWith( + expect.objectContaining({ + audioOutput: expect.objectContaining({ + deviceId: controlled ? undefined : "DEV00", + }), + }), + ); + }, + ); +}); + +afterEach(() => { + testScope.end(); + fetchMock.reset(); +}); From 7f3596845c4c14a801aeb6557bab6a01a56918e7 Mon Sep 17 00:00:00 2001 From: Valere Date: Tue, 25 Nov 2025 11:40:38 +0100 Subject: [PATCH 005/748] fix formatting --- src/UrlParams.test.ts | 15 ++++++++------- .../remoteMembers/ECConnectionFactory.test.ts | 2 +- 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/src/UrlParams.test.ts b/src/UrlParams.test.ts index cd195f545..faba394f3 100644 --- a/src/UrlParams.test.ts +++ b/src/UrlParams.test.ts @@ -339,19 +339,20 @@ describe("UrlParams", () => { }); it("is parsed", () => { - expect(computeUrlParams("?intent=start_call&noiseSuppression=true").noiseSuppression).toBe( - true, - ); - expect(computeUrlParams("?intent=start_call&noiseSuppression&bar=foo").noiseSuppression).toBe( - true, - ); + expect( + computeUrlParams("?intent=start_call&noiseSuppression=true") + .noiseSuppression, + ).toBe(true); + expect( + computeUrlParams("?intent=start_call&noiseSuppression&bar=foo") + .noiseSuppression, + ).toBe(true); expect(computeUrlParams("?noiseSuppression=false").noiseSuppression).toBe( false, ); }); }); - describe("echoCancellation", () => { it("defaults to true", () => { expect(computeUrlParams().echoCancellation).toBe(true); diff --git a/src/state/CallViewModel/remoteMembers/ECConnectionFactory.test.ts b/src/state/CallViewModel/remoteMembers/ECConnectionFactory.test.ts index cbf334be1..78e230573 100644 --- a/src/state/CallViewModel/remoteMembers/ECConnectionFactory.test.ts +++ b/src/state/CallViewModel/remoteMembers/ECConnectionFactory.test.ts @@ -102,7 +102,7 @@ describe("ECConnectionFactory - ControlledAudioDevice", () => { available$: constant(new Map()), selected$: constant({ id: "DEV00", virtualEarpiece: false }), select: () => {}, - } + }, }), new BehaviorSubject({ supported: true, From d22d7460fe3e1c9de246d127cbb978fccf903308 Mon Sep 17 00:00:00 2001 From: Timo K Date: Tue, 25 Nov 2025 20:18:34 +0100 Subject: [PATCH 006/748] Another larger refactor to fix sfu switches and in general proper cleanup. --- locales/en/app.json | 3 + src/room/InCallView.tsx | 2 + src/state/CallViewModel/CallViewModel.ts | 22 +- .../localMember/LocalMembership.test.ts | 77 ++- .../localMember/LocalMembership.ts | 476 ++++++++++-------- .../localMember/LocalTransport.test.ts | 36 ++ .../CallViewModel/localMember/Publisher.ts | 70 +-- .../remoteMembers/Connection.test.ts | 6 +- .../CallViewModel/remoteMembers/Connection.ts | 47 +- .../remoteMembers/ConnectionManager.ts | 3 +- src/state/ObservableScope.ts | 42 +- src/utils/errors.ts | 26 + 12 files changed, 482 insertions(+), 328 deletions(-) diff --git a/locales/en/app.json b/locales/en/app.json index 9e8fbbd34..32d10663d 100644 --- a/locales/en/app.json +++ b/locales/en/app.json @@ -108,11 +108,14 @@ "connection_lost_description": "You were disconnected from the call.", "e2ee_unsupported": "Incompatible browser", "e2ee_unsupported_description": "Your web browser does not support encrypted calls. Supported browsers include Chrome, Safari, and Firefox 117+.", + "failed_to_start_livekit": "Failed to start Livekit", "generic": "Something went wrong", "generic_description": "Submitting debug logs will help us track down the problem.", "insufficient_capacity": "Insufficient capacity", "insufficient_capacity_description": "The server has reached its maximum capacity and you cannot join the call at this time. Try again later, or contact your server admin if the problem persists.", "matrix_rtc_transport_missing": "The server is not configured to work with {{brand}}. Please contact your server admin (Domain: {{domain}}, Error Code: {{ errorCode }}).", + "membership_manager": "Membership Manager Error", + "membership_manager_description": "The Membership Manager had to shut down. This is caused by many consequtive failed network requests.", "open_elsewhere": "Opened in another tab", "open_elsewhere_description": "{{brand}} has been opened in another tab. If that doesn't sound right, try reloading the page.", "room_creation_restricted": "Failed to create call", diff --git a/src/room/InCallView.tsx b/src/room/InCallView.tsx index b17d3aaee..6ae004d8a 100644 --- a/src/room/InCallView.tsx +++ b/src/room/InCallView.tsx @@ -146,6 +146,8 @@ export const ActiveCall: FC = (props) => { reactionsReader.reactions$, scope.behavior(trackProcessorState$), ); + // TODO move this somewhere else once we use the callViewModel in the lobby as well! + vm.join(); setVm(vm); vm.leave$.pipe(scope.bind()).subscribe(props.onLeft); diff --git a/src/state/CallViewModel/CallViewModel.ts b/src/state/CallViewModel/CallViewModel.ts index 506eca1b8..082da4778 100644 --- a/src/state/CallViewModel/CallViewModel.ts +++ b/src/state/CallViewModel/CallViewModel.ts @@ -102,7 +102,6 @@ import { createLocalMembership$, enterRTCSession, LivekitState, - type LocalMemberConnectionState, } from "./localMember/LocalMembership.ts"; import { createLocalTransport$ } from "./localMember/LocalTransport.ts"; import { @@ -202,7 +201,7 @@ export interface CallViewModel { hangup: () => void; // joining - join: () => LocalMemberConnectionState; + join: () => void; // screen sharing /** @@ -572,15 +571,6 @@ export function createCallViewModel$( ), ); - // CODESMELL? - // This is functionally the same Observable as leave$, except here it's - // hoisted to the top of the class. This enables the cyclic dependency between - // leave$ -> autoLeave$ -> callPickupState$ -> livekitConnectionState$ -> - // localConnection$ -> transports$ -> joined$ -> leave$. - const leaveHoisted$ = new Subject< - "user" | "timeout" | "decline" | "allOthersLeft" - >(); - /** * Whether various media/event sources should pretend to be disconnected from * all network input, even if their connection still technically works. @@ -840,10 +830,7 @@ export function createCallViewModel$( merge( autoLeave$, merge(userHangup$, widgetHangup$).pipe(map(() => "user" as const)), - ).pipe( - scope.share, - tap((reason) => leaveHoisted$.next(reason)), - ); + ).pipe(scope.share); const spotlightSpeaker$ = scope.behavior( userMedia$.pipe( @@ -1448,16 +1435,13 @@ export function createCallViewModel$( // reassigned here to make it publicly accessible const toggleScreenSharing = localMembership.toggleScreenSharing; - const join = localMembership.requestConnect; - // TODO-MULTI-SFU: Use this view model for the lobby as well, and only call this once 'join' is clicked? - join(); return { autoLeave$: autoLeave$, callPickupState$: callPickupState$, ringOverlay$: ringOverlay$, leave$: leave$, hangup: (): void => userHangup$.next(), - join: join, + join: localMembership.requestConnect, toggleScreenSharing: toggleScreenSharing, sharingScreen$: sharingScreen$, diff --git a/src/state/CallViewModel/localMember/LocalMembership.test.ts b/src/state/CallViewModel/localMember/LocalMembership.test.ts index 9459d419c..a3bfe158f 100644 --- a/src/state/CallViewModel/localMember/LocalMembership.test.ts +++ b/src/state/CallViewModel/localMember/LocalMembership.test.ts @@ -12,12 +12,15 @@ import { } from "matrix-js-sdk/lib/matrixrtc"; import { describe, expect, it, vi } from "vitest"; import { AutoDiscovery } from "matrix-js-sdk/lib/autodiscovery"; -import { map } from "rxjs"; +import { BehaviorSubject, map, of } from "rxjs"; import { logger } from "matrix-js-sdk/lib/logger"; +import { type LocalParticipant } from "livekit-client"; import { MatrixRTCMode } from "../../../settings/settings"; import { + flushPromises, mockConfig, + mockLivekitRoom, mockMuteStates, withTestScheduler, } from "../../../utils/test"; @@ -27,14 +30,19 @@ import { LivekitState, } from "./LocalMembership"; import { MatrixRTCTransportMissingError } from "../../../utils/errors"; -import { Epoch } from "../../ObservableScope"; +import { Epoch, ObservableScope } from "../../ObservableScope"; import { constant } from "../../Behavior"; import { ConnectionManagerData } from "../remoteMembers/ConnectionManager"; -import { type Publisher } from "./Publisher"; +import { type Connection } from "../remoteMembers/Connection"; const MATRIX_RTC_MODE = MatrixRTCMode.Legacy; const getUrlParams = vi.hoisted(() => vi.fn(() => ({}))); vi.mock("../../../UrlParams", () => ({ getUrlParams })); +vi.mock("@livekit/components-core", () => ({ + observeParticipantEvents: vi + .fn() + .mockReturnValue(of({ isScreenShareEnabled: false })), +})); describe("LocalMembership", () => { describe("enterRTCSession", () => { @@ -183,7 +191,7 @@ describe("LocalMembership", () => { processor: undefined, }), logger: logger, - createPublisherFactory: (): Publisher => ({}) as unknown as Publisher, + createPublisherFactory: vi.fn(), joinMatrixRTC: async (): Promise => {}, homeserverConnected$: constant(true), }; @@ -216,7 +224,7 @@ describe("LocalMembership", () => { }); expectObservable(localMembership.connectionState.livekit$).toBe("ne", { - n: { state: LivekitState.Uninitialized }, + n: { state: LivekitState.Connecting }, e: { state: LivekitState.Error, error: expect.toSatisfy( @@ -226,4 +234,63 @@ describe("LocalMembership", () => { }); }); }); + + it("recreates publisher if new connection is used", async () => { + const scope = new ObservableScope(); + const aTransport = { + livekit_service_url: "a", + } as LivekitTransport; + const bTransport = { + livekit_service_url: "b", + } as LivekitTransport; + + const localTransport$ = new BehaviorSubject(aTransport); + + const connectionManagerData = new ConnectionManagerData(); + + connectionManagerData.add( + { + livekitRoom: mockLivekitRoom({ + localParticipant: { + isScreenShareEnabled: false, + trackPublications: [], + } as unknown as LocalParticipant, + }), + state$: constant({ + state: "ConnectedToLkRoom", + }), + transport: aTransport, + } as unknown as Connection, + [], + ); + connectionManagerData.add( + { + state$: constant({ + state: "ConnectedToLkRoom", + }), + transport: bTransport, + } as unknown as Connection, + [], + ); + + const publisherFactory = + defaultCreateLocalMemberValues.createPublisherFactory as ReturnType< + typeof vi.fn + >; + + createLocalMembership$({ + scope, + ...defaultCreateLocalMemberValues, + connectionManager: { + connectionManagerData$: constant(new Epoch(connectionManagerData)), + }, + localTransport$, + }); + await flushPromises(); + localTransport$.next(bTransport); + await flushPromises(); + expect(publisherFactory).toHaveBeenCalledTimes(2); + expect(publisherFactory.mock.calls[0][0].transport).toBe(aTransport); + expect(publisherFactory.mock.calls[1][0].transport).toBe(bTransport); + }); }); diff --git a/src/state/CallViewModel/localMember/LocalMembership.ts b/src/state/CallViewModel/localMember/LocalMembership.ts index 36952c5a9..cfc715e07 100644 --- a/src/state/CallViewModel/localMember/LocalMembership.ts +++ b/src/state/CallViewModel/localMember/LocalMembership.ts @@ -30,50 +30,68 @@ import { tap, } from "rxjs"; import { type Logger } from "matrix-js-sdk/lib/logger"; +import { deepCompare } from "matrix-js-sdk/lib/utils"; -import { type Behavior } from "../../Behavior"; +import { constant, type Behavior } from "../../Behavior"; import { type IConnectionManager } from "../remoteMembers/ConnectionManager"; import { ObservableScope } from "../../ObservableScope"; import { type Publisher } from "./Publisher"; import { type MuteStates } from "../../MuteStates"; import { and$ } from "../../../utils/observable"; -import { ElementCallError, UnknownCallError } from "../../../utils/errors"; +import { + ElementCallError, + MembershipManagerError, + UnknownCallError, +} from "../../../utils/errors"; import { ElementWidgetActions, widget } from "../../../widget"; import { getUrlParams } from "../../../UrlParams.ts"; import { PosthogAnalytics } from "../../../analytics/PosthogAnalytics.ts"; import { MatrixRTCMode } from "../../../settings/settings.ts"; import { Config } from "../../../config/Config.ts"; -import { - type Connection, - type ConnectionState, -} from "../remoteMembers/Connection.ts"; +import { type Connection } from "../remoteMembers/Connection.ts"; export enum LivekitState { - Uninitialized = "uninitialized", - Connecting = "connecting", - Connected = "connected", Error = "error", + /** Not even a transport is available to the LocalMembership */ + WaitingForTransport = "waiting_for_transport", + /** A transport is and we are loading the connection based on the transport */ + Connecting = "connecting", + InitialisingPublisher = "uninitialized", + Initialized = "Initialized", + CreatingTracks = "creating_tracks", + ReadyToPublish = "ready_to_publish", + WaitingToPublish = "publishing", + Connected = "connected", Disconnected = "disconnected", Disconnecting = "disconnecting", } type LocalMemberLivekitState = | { state: LivekitState.Error; error: ElementCallError } - | { state: LivekitState.Connected } + | { state: LivekitState.WaitingForTransport } | { state: LivekitState.Connecting } - | { state: LivekitState.Uninitialized } + | { state: LivekitState.InitialisingPublisher } + | { state: LivekitState.Initialized } + | { state: LivekitState.CreatingTracks } + | { state: LivekitState.ReadyToPublish } + | { state: LivekitState.WaitingToPublish } + | { state: LivekitState.Connected } | { state: LivekitState.Disconnected } | { state: LivekitState.Disconnecting }; export enum MatrixState { + WaitingForTransport = "waiting_for_transport", + Ready = "ready", + Connecting = "connecting", Connected = "connected", Disconnected = "disconnected", - Connecting = "connecting", Error = "Error", } type LocalMemberMatrixState = | { state: MatrixState.Connected } + | { state: MatrixState.WaitingForTransport } + | { state: MatrixState.Ready } | { state: MatrixState.Connecting } | { state: MatrixState.Disconnected } | { state: MatrixState.Error; error: Error }; @@ -102,7 +120,7 @@ interface Props { muteStates: MuteStates; connectionManager: IConnectionManager; createPublisherFactory: (connection: Connection) => Publisher; - joinMatrixRTC: (trasnport: LivekitTransport) => Promise; + joinMatrixRTC: (transport: LivekitTransport) => Promise; homeserverConnected$: Behavior; localTransport$: Behavior; matrixRTCSession: Pick< @@ -136,9 +154,9 @@ export const createLocalMembership$ = ({ muteStates, matrixRTCSession, }: Props): { - requestConnect: () => LocalMemberConnectionState; + requestConnect: () => void; startTracks: () => Behavior; - requestDisconnect: () => Observable | null; + requestDisconnect: () => void; connectionState: LocalMemberConnectionState; sharingScreen$: Behavior; /** @@ -157,27 +175,8 @@ export const createLocalMembership$ = ({ } => { const logger = parentLogger.getChild("[LocalMembership]"); logger.debug(`Creating local membership..`); - const state = { - livekit$: new BehaviorSubject({ - state: LivekitState.Uninitialized, - }), - matrix$: new BehaviorSubject({ - state: MatrixState.Disconnected, - }), - }; - // This should be used in a combineLatest with publisher$ to connect. - // to make it possible to call startTracks before the preferredTransport$ has resolved. - const trackStartRequested$ = new BehaviorSubject(false); - - // This should be used in a combineLatest with publisher$ to connect. - // to make it possible to call startTracks before the preferredTransport$ has resolved. - const connectRequested$ = new BehaviorSubject(false); - - // This should be used in a combineLatest with publisher$ to connect. - const tracks$ = new BehaviorSubject([]); - - // unwrap the local transport and set the state of the LocalMembership to error in case the transport is an error. + // Unwrap the local transport and set the state of the LocalMembership to error in case the transport is an error. const localTransport$ = scope.behavior( localTransportCanThrow$.pipe( catchError((e: unknown) => { @@ -191,7 +190,7 @@ export const createLocalMembership$ = ({ : new Error("Unknown error from localTransport"), ); } - state.livekit$.next({ state: LivekitState.Error, error }); + setLivekitError(error); return of(null); }), ), @@ -203,12 +202,12 @@ export const createLocalMembership$ = ({ connectionManager.connectionManagerData$, localTransport$, ]).pipe( - map(([connectionData, localTransport]) => { + map(([{ value: connectionData }, localTransport]) => { if (localTransport === null) { return null; } - return connectionData.value.getConnectionForTransport(localTransport); + return connectionData.getConnectionForTransport(localTransport); }), tap((connection) => { logger.info( @@ -236,34 +235,6 @@ export const createLocalMembership$ = ({ ), ); - const publisher$ = new BehaviorSubject(null); - localConnection$.pipe(scope.bind()).subscribe((connection) => { - if (connection !== null && publisher$.value === null) { - // TODO looks strange to not change publisher if connection changes. - // @toger5 will take care of this! - publisher$.next(createPublisherFactory(connection)); - } - }); - - // const mutestate= publisher$.pipe(switchMap((publisher) => { - // return publisher.muteState$ - // }); - - combineLatest([publisher$, trackStartRequested$]).subscribe( - ([publisher, shouldStartTracks]) => { - if (publisher && shouldStartTracks) { - publisher - .createAndSetupTracks() - .then((tracks) => { - tracks$.next(tracks); - }) - .catch((error) => { - logger.error("Error creating tracks:", error); - }); - } - }, - ); - // MATRIX RELATED // /** @@ -286,90 +257,230 @@ export const createLocalMembership$ = ({ ), ); + // This should be used in a combineLatest with publisher$ to connect. + // to make it possible to call startTracks before the preferredTransport$ has resolved. + const trackStartRequested$ = new BehaviorSubject(false); + + // This should be used in a combineLatest with publisher$ to connect. + // to make it possible to call startTracks before the preferredTransport$ has resolved. + const connectRequested$ = new BehaviorSubject(false); + + /** + * The publisher is stored in here an abstracts creating and publishing tracks. + */ + const publisher$ = new BehaviorSubject(null); + /** + * Extract the tracks from the published. Also reacts to changing publishers. + */ + const tracks$ = scope.behavior( + publisher$.pipe(switchMap((p) => (p ? p.tracks$ : constant([])))), + ); + const publishing$ = scope.behavior( + publisher$.pipe(switchMap((p) => (p ? p.publishing$ : constant(false)))), + ); + const startTracks = (): Behavior => { trackStartRequested$.next(true); return tracks$; }; - combineLatest([publisher$, tracks$]).subscribe(([publisher, tracks]) => { - if ( - tracks.length === 0 || - // change this to !== Publishing - state.livekit$.value.state !== LivekitState.Uninitialized - ) { - return; + const requestConnect = (): void => { + trackStartRequested$.next(true); + connectRequested$.next(true); + }; + + const requestDisconnect = (): void => { + connectRequested$.next(false); + }; + + // Take care of the publisher$ + // create a new one as soon as a local Connection is available + // + // Recreate a new one once the local connection changes + // - stop publishing + // - destruct all current streams + // - overwrite current publisher + scope.reconcile(localConnection$, async (connection) => { + if (connection !== null) { + publisher$.next(createPublisherFactory(connection)); } - state.livekit$.next({ state: LivekitState.Connecting }); - publisher - ?.startPublishing() - .then(() => { - state.livekit$.next({ state: LivekitState.Connected }); - }) - .catch((error) => { - state.livekit$.next({ state: LivekitState.Error, error }); - }); + return Promise.resolve(async (): Promise => { + await publisher$?.value?.stopPublishing(); + publisher$?.value?.stopTracks(); + }); }); - combineLatest([localTransport$, connectRequested$]).subscribe( - // TODO reconnect when transport changes => create test. - ([transport, connectRequested]) => { - if ( - transport === null || - !connectRequested || - state.matrix$.value.state !== MatrixState.Disconnected - ) { - logger.info( - "Not yet connecting because: ", - "transport === null:", - transport === null, - "!connectRequested:", - !connectRequested, - "state.matrix$.value.state !== MatrixState.Disconnected:", - state.matrix$.value.state !== MatrixState.Disconnected, - ); - return; - } - state.matrix$.next({ state: MatrixState.Connecting }); - logger.info("Matrix State connecting"); + // const mutestate= publisher$.pipe(switchMap((publisher) => { + // return publisher.muteState$ + // }); - joinMatrixRTC(transport).catch((error) => { - logger.error(error); - state.matrix$.next({ state: MatrixState.Error, error }); - }); + // For each publisher create the descired tracks + // If we recreate a new publisher we remember the trackStartRequested$ value and immediately create the tracks + // THIS might be fine without a reconcile. There is no cleanup needed. We always get a working publisher + // track start request can than just toggle the tracks. + // TODO does this need `reconcile` to make sure we wait for createAndSetupTracks before we stop tracks? + combineLatest([publisher$, trackStartRequested$]).subscribe( + ([publisher, shouldStartTracks]) => { + if (publisher && shouldStartTracks) { + publisher.createAndSetupTracks().catch( + // TODO make this set some error state + (e) => logger.error(e), + ); + } else if (publisher) { + publisher.stopTracks(); + } }, ); - // TODO add this and update `state.matrix$` based on it. - // useTypedEventEmitter( - // rtcSession, - // MatrixRTCSessionEvent.MembershipManagerError, - // (error) => setExternalError(new ConnectionLostError()), - // ); + // Use reconcile here to not run concurrent createAndSetupTracks calls + // `tracks$` will update once they are ready. + scope.reconcile( + scope.behavior(combineLatest([publisher$, trackStartRequested$])), + async ([publisher, shouldStartTracks]) => { + if (publisher && shouldStartTracks) { + await publisher.createAndSetupTracks().catch((e) => logger.error(e)); + } else if (publisher) { + publisher.stopTracks(); + } + }, + ); - const requestConnect = (): LocalMemberConnectionState => { - trackStartRequested$.next(true); - connectRequested$.next(true); + // Based on `connectRequested$` we start publishing tracks. (once they are there!) + scope.reconcile( + scope.behavior(combineLatest([publisher$, tracks$, connectRequested$])), + async ([publisher, tracks, shouldConnect]) => { + if (shouldConnect === publisher?.publishing$.value) + return Promise.resolve(); + if (tracks.length !== 0 && shouldConnect) { + try { + await publisher?.startPublishing(); + } catch (error) { + // will take care of "FailedToStartLk" errors. + setLivekitError(error as ElementCallError); + } + } else if (tracks.length !== 0 && !shouldConnect) { + try { + await publisher?.stopPublishing(); + } catch (error) { + setLivekitError(new UnknownCallError(error as Error)); + } + } + }, + ); - return state; + const fatalLivekitError$ = new BehaviorSubject(null); + const setLivekitError = (e: ElementCallError): void => { + if (fatalLivekitError$.value !== null) + logger.error("Multiple Livkit Errors:", e); + else fatalLivekitError$.next(e); }; + const livekitState$: Observable = combineLatest([ + publisher$, + localTransport$, + localConnection$, + tracks$, + publishing$, + connectRequested$, + trackStartRequested$, + fatalLivekitError$, + ]).pipe( + map( + ([ + publisher, + localTransport, + localConnection, + tracks, + publishing, + shouldConnect, + shouldStartTracks, + error, + ]) => { + // read this: + // if(!) return {state: ...} + // if(!) return {state: } + // + // as: + // We do have but not yet so we are in + if (error !== null) return { state: LivekitState.Error, error }; + const hasTracks = tracks.length > 0; + if (!localTransport) return { state: LivekitState.WaitingForTransport }; + if (!localConnection) return { state: LivekitState.Connecting }; + if (!publisher) return { state: LivekitState.InitialisingPublisher }; + if (!shouldStartTracks) return { state: LivekitState.Initialized }; + if (!hasTracks) return { state: LivekitState.CreatingTracks }; + if (!shouldConnect) return { state: LivekitState.ReadyToPublish }; + if (!publishing) return { state: LivekitState.WaitingToPublish }; + return { state: LivekitState.Connected }; + }, + ), + distinctUntilChanged(deepCompare), + ); - const requestDisconnect = (): Behavior | null => { - if (state.livekit$.value.state !== LivekitState.Connected) return null; - state.livekit$.next({ state: LivekitState.Disconnecting }); - combineLatest([publisher$, tracks$], (publisher, tracks) => { - publisher - ?.stopPublishing() - .then(() => { - tracks.forEach((track) => track.stop()); - state.livekit$.next({ state: LivekitState.Disconnected }); - }) - .catch((error) => { - state.livekit$.next({ state: LivekitState.Error, error }); - }); - }); - - return state.livekit$; + const fatalMatrixError$ = new BehaviorSubject(null); + const setMatrixError = (e: ElementCallError): void => { + if (fatalMatrixError$.value !== null) + logger.error("Multiple Matrix Errors:", e); + else fatalMatrixError$.next(e); }; + const matrixState$: Behavior = scope.behavior( + combineLatest([ + localTransport$, + connectRequested$, + homeserverConnected$, + ]).pipe( + map(([localTransport, connectRequested, homeserverConnected]) => { + if (!localTransport) return { state: MatrixState.WaitingForTransport }; + if (!connectRequested) return { state: MatrixState.Ready }; + if (!homeserverConnected) return { state: MatrixState.Connecting }; + return { state: MatrixState.Connected }; + }), + ), + ); + + // Keep matrix rtc session in sync with localTransport$, connectRequested$ and muteStates.video.enabled$ + scope.reconcile( + scope.behavior(combineLatest([localTransport$, connectRequested$])), + async ([transport, shouldConnect]) => { + if (!shouldConnect) return; + + if (!transport) return; + try { + await joinMatrixRTC(transport); + } catch (error) { + logger.error("Error entering RTC session", error); + if (error instanceof Error) + setMatrixError(new MembershipManagerError(error)); + } + + // Update our member event when our mute state changes. + const callIntentScope = new ObservableScope(); + // because this uses its own scope, we can start another reconciliation for the duration of one connection. + callIntentScope.reconcile( + muteStates.video.enabled$, + async (videoEnabled) => + matrixRTCSession.updateCallIntent(videoEnabled ? "video" : "audio"), + ); + + return async (): Promise => { + callIntentScope.end(); + try { + // Update matrixRTCSession to allow udpating the transport without leaving the session! + await matrixRTCSession.leaveRoomSession(); + } catch (e) { + logger.error("Error leaving RTC session", e); + } + try { + await widget?.api.transport.send(ElementWidgetActions.HangupCall, {}); + } catch (e) { + logger.error("Failed to send hangup action", e); + } + }; + }, + ); + + const participant$ = scope.behavior( + localConnection$.pipe(map((c) => c?.livekitRoom?.localParticipant ?? null)), + ); // Pause upstream of all local media tracks when we're disconnected from // MatrixRTC, because it can be an unpleasant surprise for the app to say @@ -377,12 +488,12 @@ export const createLocalMembership$ = ({ // We use matrixConnected$ rather than reconnecting$ because we want to // pause tracks during the initial joining sequence too until we're sure // that our own media is displayed on screen. - combineLatest([localConnection$, homeserverConnected$]) + // TODO refactor this based no livekitState$ + combineLatest([participant$, homeserverConnected$]) .pipe(scope.bind()) - .subscribe(([connection, connected]) => { - if (connection?.state$.value.state !== "ConnectedToLkRoom") return; - const publications = - connection.livekitRoom.localParticipant.trackPublications.values(); + .subscribe(([participant, connected]) => { + if (!participant) return; + const publications = participant.trackPublications.values(); if (connected) { for (const p of publications) { if (p.track?.isUpstreamPaused === true) { @@ -419,85 +530,13 @@ export const createLocalMembership$ = ({ } } }); - // TODO: Refactor updateCallIntent to sth like this: - // combineLatest([muteStates.video.enabled$,localTransport$, state.matrix$]).pipe(map(()=>{ - // matrixRTCSession.updateCallIntent(videoEnabled ? "video" : "audio"), - // })) - // - - // TODO I do not fully understand what this does. - // Is it needed? - // Is this at the right place? - // Can this be simplified? - // Start and stop session membership as needed - // Discussed in statndup -> It seems we can remove this (there is another call to enterRTCSession in this file) - // MAKE SURE TO UNDERSTAND why reconcile is needed and what is potentially missing from the alternative enterRTCSession block. - // @toger5 will try to take care of this. - scope.reconcile(localTransport$, async (transport) => { - if (transport !== null && transport !== undefined) { - try { - state.matrix$.next({ state: MatrixState.Connecting }); - await joinMatrixRTC(transport); - } catch (e) { - logger.error("Error entering RTC session", e); - } - - // Update our member event when our mute state changes. - const intentScope = new ObservableScope(); - intentScope.reconcile(muteStates.video.enabled$, async (videoEnabled) => - matrixRTCSession.updateCallIntent(videoEnabled ? "video" : "audio"), - ); - - return async (): Promise => { - intentScope.end(); - // Only sends Matrix leave event. The LiveKit session will disconnect - // as soon as either the stopConnection$ handler above gets to it or - // the view model is destroyed. - try { - await matrixRTCSession.leaveRoomSession(); - } catch (e) { - logger.error("Error leaving RTC session", e); - } - try { - await widget?.api.transport.send(ElementWidgetActions.HangupCall, {}); - } catch (e) { - logger.error("Failed to send hangup action", e); - } - }; - } - }); - - localConnection$ - .pipe( - distinctUntilChanged(), - switchMap((c) => - c === null ? of({ state: "Initialized" } as ConnectionState) : c.state$, - ), - map((s) => { - logger.trace(`Local connection state update: ${s.state}`); - if (s.state == "FailedToStart") { - return s.error instanceof ElementCallError - ? s.error - : new UnknownCallError(s.error); - } - }), - scope.bind(), - ) - .subscribe((error) => { - if (error !== undefined) - state.livekit$.next({ state: LivekitState.Error, error }); - }); /** * Whether the user is currently sharing their screen. */ const sharingScreen$ = scope.behavior( - localConnection$.pipe( - switchMap((c) => - c !== null - ? observeSharingScreen$(c.livekitRoom.localParticipant) - : of(false), - ), + participant$.pipe( + switchMap((p) => (p !== null ? observeSharingScreen$(p) : of(false))), ), ); @@ -527,24 +566,23 @@ export const createLocalMembership$ = ({ // We also allow screen sharing to be toggled even if the connection // is still initializing or publishing tracks, because there's no // technical reason to disallow this. LiveKit will publish if it can. - localConnection$.value?.livekitRoom.localParticipant - .setScreenShareEnabled(targetScreenshareState, screenshareSettings) + participant$.value + ?.setScreenShareEnabled(targetScreenshareState, screenshareSettings) .catch(logger.error); }; } - const participant$ = scope.behavior( - localConnection$.pipe(map((c) => c?.livekitRoom?.localParticipant ?? null)), - ); return { startTracks, requestConnect, requestDisconnect, - connectionState: state, + connectionState: { + livekit$: scope.behavior(livekitState$), + matrix$: matrixState$, + }, homeserverConnected$, connected$, reconnecting$, - sharingScreen$, toggleScreenSharing, participant$, diff --git a/src/state/CallViewModel/localMember/LocalTransport.test.ts b/src/state/CallViewModel/localMember/LocalTransport.test.ts index d543f97a0..c1c36fa5a 100644 --- a/src/state/CallViewModel/localMember/LocalTransport.test.ts +++ b/src/state/CallViewModel/localMember/LocalTransport.test.ts @@ -7,6 +7,7 @@ Please see LICENSE in the repository root for full details. import { afterEach, beforeEach, describe, expect, it, vi } from "vitest"; import { type CallMembership } from "matrix-js-sdk/lib/matrixrtc"; +import { BehaviorSubject } from "rxjs"; import { mockConfig, flushPromises } from "../../../utils/test"; import { createLocalTransport$ } from "./LocalTransport"; @@ -117,4 +118,39 @@ describe("LocalTransport", () => { type: "livekit", }); }); + + it("updates local transport when oldest member changes", async () => { + // Use config so transport discovery succeeds, but delay OpenID JWT fetch + mockConfig({ + livekit: { livekit_service_url: "https://lk.example.org" }, + }); + const memberships$ = new BehaviorSubject(new Epoch([])); + const openIdResolver = Promise.withResolvers(); + + vi.spyOn(openIDSFU, "getSFUConfigWithOpenID").mockReturnValue( + openIdResolver.promise, + ); + + const localTransport$ = createLocalTransport$({ + scope, + roomId: "!room:example.org", + useOldestMember$: constant(true), + memberships$, + client: { + getDomain: () => "", + getOpenIdToken: vi.fn(), + getDeviceId: vi.fn(), + }, + }); + + openIdResolver.resolve?.({ url: "https://lk.example.org", jwt: "jwt" }); + expect(localTransport$.value).toBe(null); + await flushPromises(); + // final + expect(localTransport$.value).toStrictEqual({ + livekit_alias: "!room:example.org", + livekit_service_url: "https://lk.example.org", + type: "livekit", + }); + }); }); diff --git a/src/state/CallViewModel/localMember/Publisher.ts b/src/state/CallViewModel/localMember/Publisher.ts index 11f35424a..df6addb8a 100644 --- a/src/state/CallViewModel/localMember/Publisher.ts +++ b/src/state/CallViewModel/localMember/Publisher.ts @@ -14,6 +14,7 @@ import { ConnectionState as LivekitConnectionState, } from "livekit-client"; import { + BehaviorSubject, map, NEVER, type Observable, @@ -33,6 +34,7 @@ import { getUrlParams } from "../../../UrlParams.ts"; import { observeTrackReference$ } from "../../MediaViewModel.ts"; import { type Connection } from "../remoteMembers/Connection.ts"; import { type ObservableScope } from "../../ObservableScope.ts"; +import { FailToStartLivekitConnection } from "../../../utils/errors.ts"; /** * A wrapper for a Connection object. @@ -40,7 +42,6 @@ import { type ObservableScope } from "../../ObservableScope.ts"; * The Publisher is also responsible for creating the media tracks. */ export class Publisher { - public tracks: LocalTrack[] = []; /** * Creates a new Publisher. * @param scope - The observable scope to use for managing the publisher. @@ -81,6 +82,9 @@ export class Publisher { }); } + private _tracks$ = new BehaviorSubject[]>([]); + public tracks$ = this._tracks$ as Behavior[]>; + /** * Start the connection to LiveKit and publish local tracks. * @@ -94,50 +98,36 @@ export class Publisher { * @throws {InsufficientCapacityError} if the LiveKit server indicates that it has insufficient capacity to accept the connection. * @throws {SFURoomCreationRestrictedError} if the LiveKit server indicates that the room does not exist and cannot be created. */ - public async createAndSetupTracks(): Promise { + public async createAndSetupTracks(): Promise { const lkRoom = this.connection.livekitRoom; // Observe mute state changes and update LiveKit microphone/camera states accordingly this.observeMuteStates(this.scope); - // TODO: This should be an autostarted connection no need to start here. just check the connection state. - // TODO: This will fetch the JWT token. Perhaps we could keep it preloaded - // instead? This optimization would only be safe for a publish connection, - // because we don't want to leak the user's intent to perhaps join a call to - // remote servers before they actually commit to it. - // const { promise, resolve, reject } = Promise.withResolvers(); - // const sub = this.connection.state$.subscribe((s) => { - // if (s.state === "FailedToStart") { - // reject(new Error("Disconnected from LiveKit server")); - // } else if (s.state === "ConnectedToLkRoom") { - // resolve(); - // } - // }); - // try { - // await promise; - // } catch (e) { - // throw e; - // } finally { - // sub.unsubscribe(); - // } // TODO-MULTI-SFU: Prepublish a microphone track const audio = this.muteStates.audio.enabled$.value; const video = this.muteStates.video.enabled$.value; // createTracks throws if called with audio=false and video=false if (audio || video) { // TODO this can still throw errors? It will also prompt for permissions if not already granted - this.tracks = - (await lkRoom.localParticipant - .createTracks({ - audio, - video, - }) - .catch((error) => { - this.logger?.error("Failed to create tracks", error); - })) ?? []; + return lkRoom.localParticipant + .createTracks({ + audio, + video, + }) + .then((tracks) => { + this._tracks$.next(tracks); + }); } - return this.tracks; + throw Error("audio and video is false"); } + private _publishing$ = new BehaviorSubject(false); + public publishing$ = this.scope.behavior(this._publishing$); + /** + * + * @returns + * @throws ElementCallError + */ public async startPublishing(): Promise { const lkRoom = this.connection.livekitRoom; const { promise, resolve, reject } = Promise.withResolvers(); @@ -147,7 +137,7 @@ export class Publisher { resolve(); break; case "FailedToStart": - reject(new Error("Failed to connect to LiveKit server")); + reject(new FailToStartLivekitConnection()); break; default: this.logger?.info("waiting for connection: ", s.state); @@ -160,7 +150,7 @@ export class Publisher { } finally { sub.unsubscribe(); } - for (const track of this.tracks) { + for (const track of this.tracks$.value) { // TODO: handle errors? Needs the signaling connection to be up, but it has some retries internally // with a timeout. await lkRoom.localParticipant.publishTrack(track).catch((error) => { @@ -169,7 +159,8 @@ export class Publisher { // TODO: check if the connection is still active? and break the loop if not? } - return this.tracks; + this._publishing$.next(true); + return this.tracks$.value; } public async stopPublishing(): Promise { @@ -185,6 +176,15 @@ export class Publisher { }; localParticipant.trackPublications.forEach(addToTracksIfDefined); await localParticipant.unpublishTracks(tracks); + this._publishing$.next(false); + } + + /** + * Stops all tracks that are currently running + */ + public stopTracks(): void { + this.tracks$.value.forEach((t) => t.stop()); + this._tracks$.next([]); } /// Private methods diff --git a/src/state/CallViewModel/remoteMembers/Connection.test.ts b/src/state/CallViewModel/remoteMembers/Connection.test.ts index 3f58bcf6d..2ead768be 100644 --- a/src/state/CallViewModel/remoteMembers/Connection.test.ts +++ b/src/state/CallViewModel/remoteMembers/Connection.test.ts @@ -193,7 +193,7 @@ describe("Start connection states", () => { capturedState = capturedStates.pop(); if (capturedState!.state === "FailedToStart") { expect(capturedState!.error.message).toEqual("Something went wrong"); - expect(capturedState!.transport.livekit_alias).toEqual( + expect(connection.transport.livekit_alias).toEqual( livekitFocus.livekit_alias, ); } else { @@ -249,7 +249,7 @@ describe("Start connection states", () => { expect(capturedState?.error.message).toContain( "SFU Config fetch failed with exception Error", ); - expect(capturedState?.transport.livekit_alias).toEqual( + expect(connection.transport.livekit_alias).toEqual( livekitFocus.livekit_alias, ); } else { @@ -313,7 +313,7 @@ describe("Start connection states", () => { expect(capturedState.error.message).toContain( "Failed to connect to livekit", ); - expect(capturedState.transport.livekit_alias).toEqual( + expect(connection.transport.livekit_alias).toEqual( livekitFocus.livekit_alias, ); } else { diff --git a/src/state/CallViewModel/remoteMembers/Connection.ts b/src/state/CallViewModel/remoteMembers/Connection.ts index c17fae2b6..81bc9f294 100644 --- a/src/state/CallViewModel/remoteMembers/Connection.ts +++ b/src/state/CallViewModel/remoteMembers/Connection.ts @@ -50,16 +50,14 @@ export interface ConnectionOpts { export type ConnectionState = | { state: "Initialized" } - | { state: "FetchingConfig"; transport: LivekitTransport } - | { state: "ConnectingToLkRoom"; transport: LivekitTransport } - | { state: "PublishingTracks"; transport: LivekitTransport } - | { state: "FailedToStart"; error: Error; transport: LivekitTransport } + | { state: "FetchingConfig" } + | { state: "ConnectingToLkRoom" } | { state: "ConnectedToLkRoom"; livekitConnectionState$: Observable; - transport: LivekitTransport; } - | { state: "Stopped"; transport: LivekitTransport }; + | { state: "FailedToStart"; error: Error } + | { state: "Stopped" }; /** * A connection to a Matrix RTC LiveKit backend. @@ -77,6 +75,22 @@ export class Connection { */ public readonly state$: Behavior = this._state$; + /** + * The media transport to connect to. + */ + public readonly transport: LivekitTransport; + + public readonly livekitRoom: LivekitRoom; + + /** + * An observable of the participants that are publishing on this connection. (Excluding our local participant) + * This is derived from `participantsIncludingSubscribers$` and `remoteTransports$`. + * It filters the participants to only those that are associated with a membership that claims to publish on this connection. + */ + public readonly remoteParticipantsWithTracks$: Behavior< + PublishingParticipant[] + >; + /** * Whether the connection has been stopped. * @see Connection.stop @@ -104,7 +118,6 @@ export class Connection { try { this._state$.next({ state: "FetchingConfig", - transport: this.transport, }); const { url, jwt } = await this.getSFUConfigWithOpenID(); // If we were stopped while fetching the config, don't proceed to connect @@ -112,7 +125,6 @@ export class Connection { this._state$.next({ state: "ConnectingToLkRoom", - transport: this.transport, }); try { await this.livekitRoom.connect(url, jwt); @@ -143,7 +155,6 @@ export class Connection { this._state$.next({ state: "ConnectedToLkRoom", - transport: this.transport, livekitConnectionState$: connectionStateObserver(this.livekitRoom), }); } catch (error) { @@ -151,7 +162,6 @@ export class Connection { this._state$.next({ state: "FailedToStart", error: error instanceof Error ? error : new Error(`${error}`), - transport: this.transport, }); throw error; } @@ -179,28 +189,11 @@ export class Connection { await this.livekitRoom.disconnect(); this._state$.next({ state: "Stopped", - transport: this.transport, }); this.stopped = true; } - /** - * An observable of the participants that are publishing on this connection. (Excluding our local participant) - * This is derived from `participantsIncludingSubscribers$` and `remoteTransports$`. - * It filters the participants to only those that are associated with a membership that claims to publish on this connection. - */ - public readonly remoteParticipantsWithTracks$: Behavior< - PublishingParticipant[] - >; - - /** - * The media transport to connect to. - */ - public readonly transport: LivekitTransport; - private readonly client: OpenIDClientParts; - public readonly livekitRoom: LivekitRoom; - private readonly logger: Logger; /** diff --git a/src/state/CallViewModel/remoteMembers/ConnectionManager.ts b/src/state/CallViewModel/remoteMembers/ConnectionManager.ts index d9a0380ea..0b9f939ca 100644 --- a/src/state/CallViewModel/remoteMembers/ConnectionManager.ts +++ b/src/state/CallViewModel/remoteMembers/ConnectionManager.ts @@ -92,7 +92,6 @@ interface Props { } // TODO - write test for scopes (do we really need to bind scope) export interface IConnectionManager { - transports$: Behavior>; connectionManagerData$: Behavior>; } /** @@ -216,7 +215,7 @@ export function createConnectionManager$({ new Epoch(new ConnectionManagerData()), ); - return { transports$, connectionManagerData$ }; + return { connectionManagerData$ }; } function removeDuplicateTransports( diff --git a/src/state/ObservableScope.ts b/src/state/ObservableScope.ts index 27f501c74..6d8674149 100644 --- a/src/state/ObservableScope.ts +++ b/src/state/ObservableScope.ts @@ -123,8 +123,22 @@ export class ObservableScope { callback: (value: T) => Promise<(() => Promise) | void>, ): void { let latestValue: T | typeof nothing = nothing; - let reconciledValue: T | typeof nothing = nothing; + let reconcilePromise: Promise | undefined = undefined; let cleanUp: (() => Promise) | void = undefined; + + // While this loop runs it will process the latest from `value$` until it caught up with the updates. + // It might skip updates from `value$` and only process the newest value after callback has resolved. + const reconcileLoop = async (): Promise => { + let prevVal: T | typeof nothing = nothing; + while (latestValue !== prevVal) { + await cleanUp?.(); // Call the previous value's clean-up handler + prevVal = latestValue; + + if (latestValue !== nothing) cleanUp = await callback(latestValue); // Sync current value... + // `latestValue` might have gotten updated during the `await callback`. That is why we loop here + } + }; + value$ .pipe( catchError(() => EMPTY), // Ignore errors @@ -132,23 +146,15 @@ export class ObservableScope { endWith(nothing), // Clean up when the scope ends ) .subscribe((value) => { - void (async (): Promise => { - if (latestValue === nothing) { - latestValue = value; - while (latestValue !== reconciledValue) { - await cleanUp?.(); // Call the previous value's clean-up handler - reconciledValue = latestValue; - if (latestValue !== nothing) - cleanUp = await callback(latestValue); // Sync current value - } - // Reset to signal that reconciliation is done for now - latestValue = nothing; - } else { - // There's already an instance of the above 'while' loop running - // concurrently. Just update the latest value and let it be handled. - latestValue = value; - } - })(); + // Always track the latest value! The `reconcileLoop` will run until it "processed" the "last" `latestValue`. + latestValue = value; + // There's already an instance of the below 'reconcileLoop' loop running + // concurrently. So lets let the loop handle it. NEVER instanciate two `reconcileLoop`s. + if (reconcilePromise) return; + + reconcilePromise = reconcileLoop().finally(() => { + reconcilePromise = undefined; + }); }); } diff --git a/src/utils/errors.ts b/src/utils/errors.ts index b77c0ff0b..cdd0e75ce 100644 --- a/src/utils/errors.ts +++ b/src/utils/errors.ts @@ -13,6 +13,8 @@ export enum ErrorCode { */ MISSING_MATRIX_RTC_TRANSPORT = "MISSING_MATRIX_RTC_TRANSPORT", CONNECTION_LOST_ERROR = "CONNECTION_LOST_ERROR", + INTERNAL_MEMBERSHIP_MANAGER = "INTERNAL_MEMBERSHIP_MANAGER", + FAILED_TO_START_LIVEKIT = "FAILED_TO_START_LIVEKIT", /** LiveKit indicates that the server has hit its track limits */ INSUFFICIENT_CAPACITY_ERROR = "INSUFFICIENT_CAPACITY_ERROR", E2EE_NOT_SUPPORTED = "E2EE_NOT_SUPPORTED", @@ -27,6 +29,7 @@ export enum ErrorCategory { NETWORK_CONNECTIVITY = "NETWORK_CONNECTIVITY", CLIENT_CONFIGURATION = "CLIENT_CONFIGURATION", UNKNOWN = "UNKNOWN", + SYSTEM_FAILURE = "SYSTEM_FAILURE", // SYSTEM_FAILURE / FEDERATION_FAILURE .. } @@ -83,6 +86,18 @@ export class ConnectionLostError extends ElementCallError { } } +export class MembershipManagerError extends ElementCallError { + public constructor(error: Error) { + super( + t("error.membership_manager"), + ErrorCode.INTERNAL_MEMBERSHIP_MANAGER, + ErrorCategory.SYSTEM_FAILURE, + t("error.membership_manager_description"), + error, + ); + } +} + export class E2EENotSupportedError extends ElementCallError { public constructor() { super( @@ -120,6 +135,17 @@ export class FailToGetOpenIdToken extends ElementCallError { } } +export class FailToStartLivekitConnection extends ElementCallError { + public constructor() { + super( + t("error.failed_to_start_livekit"), + ErrorCode.FAILED_TO_START_LIVEKIT, + ErrorCategory.NETWORK_CONNECTIVITY, + undefined, + ); + } +} + export class InsufficientCapacityError extends ElementCallError { public constructor() { super( From e5117f705d78113e8c236ba0d6e1cd6e3c50a9cb Mon Sep 17 00:00:00 2001 From: Timo K Date: Thu, 27 Nov 2025 14:42:23 +0100 Subject: [PATCH 007/748] More testing and cleaning up --- .../localMember/LocalMembership.test.ts | 252 +++++++++++++++--- .../localMember/LocalMembership.ts | 171 ++++++------ .../CallViewModel/localMember/Publisher.ts | 18 ++ src/state/ObservableScope.ts | 7 +- 4 files changed, 321 insertions(+), 127 deletions(-) diff --git a/src/state/CallViewModel/localMember/LocalMembership.test.ts b/src/state/CallViewModel/localMember/LocalMembership.test.ts index a3bfe158f..6c6c3d6ee 100644 --- a/src/state/CallViewModel/localMember/LocalMembership.test.ts +++ b/src/state/CallViewModel/localMember/LocalMembership.test.ts @@ -14,7 +14,7 @@ import { describe, expect, it, vi } from "vitest"; import { AutoDiscovery } from "matrix-js-sdk/lib/autodiscovery"; import { BehaviorSubject, map, of } from "rxjs"; import { logger } from "matrix-js-sdk/lib/logger"; -import { type LocalParticipant } from "livekit-client"; +import { type LocalParticipant, type LocalTrack } from "livekit-client"; import { MatrixRTCMode } from "../../../settings/settings"; import { @@ -34,6 +34,7 @@ import { Epoch, ObservableScope } from "../../ObservableScope"; import { constant } from "../../Behavior"; import { ConnectionManagerData } from "../remoteMembers/ConnectionManager"; import { type Connection } from "../remoteMembers/Connection"; +import { type Publisher } from "./Publisher"; const MATRIX_RTC_MODE = MatrixRTCMode.Legacy; const getUrlParams = vi.hoisted(() => vi.fn(() => ({}))); @@ -235,44 +236,54 @@ describe("LocalMembership", () => { }); }); - it("recreates publisher if new connection is used", async () => { + const aTransport = { + livekit_service_url: "a", + } as LivekitTransport; + const bTransport = { + livekit_service_url: "b", + } as LivekitTransport; + + const connectionManagerData = new ConnectionManagerData(); + + connectionManagerData.add( + { + livekitRoom: mockLivekitRoom({ + localParticipant: { + isScreenShareEnabled: false, + trackPublications: [], + } as unknown as LocalParticipant, + }), + state$: constant({ + state: "ConnectedToLkRoom", + }), + transport: aTransport, + } as unknown as Connection, + [], + ); + connectionManagerData.add( + { + state$: constant({ + state: "ConnectedToLkRoom", + }), + transport: bTransport, + } as unknown as Connection, + [], + ); + + it("recreates publisher if new connection is used and ENDS always unpublish and end tracks", async () => { const scope = new ObservableScope(); - const aTransport = { - livekit_service_url: "a", - } as LivekitTransport; - const bTransport = { - livekit_service_url: "b", - } as LivekitTransport; const localTransport$ = new BehaviorSubject(aTransport); - const connectionManagerData = new ConnectionManagerData(); + const publishers: Publisher[] = []; - connectionManagerData.add( - { - livekitRoom: mockLivekitRoom({ - localParticipant: { - isScreenShareEnabled: false, - trackPublications: [], - } as unknown as LocalParticipant, - }), - state$: constant({ - state: "ConnectedToLkRoom", - }), - transport: aTransport, - } as unknown as Connection, - [], + defaultCreateLocalMemberValues.createPublisherFactory.mockImplementation( + () => { + const p = { stopPublishing: vi.fn(), stopTracks: vi.fn() }; + publishers.push(p as unknown as Publisher); + return p; + }, ); - connectionManagerData.add( - { - state$: constant({ - state: "ConnectedToLkRoom", - }), - transport: bTransport, - } as unknown as Connection, - [], - ); - const publisherFactory = defaultCreateLocalMemberValues.createPublisherFactory as ReturnType< typeof vi.fn @@ -290,7 +301,182 @@ describe("LocalMembership", () => { localTransport$.next(bTransport); await flushPromises(); expect(publisherFactory).toHaveBeenCalledTimes(2); + expect(publishers.length).toBe(2); + // stop the first Publisher and let the second one life. + expect(publishers[0].stopTracks).toHaveBeenCalled(); + expect(publishers[1].stopTracks).not.toHaveBeenCalled(); + expect(publishers[0].stopPublishing).toHaveBeenCalled(); + expect(publishers[1].stopPublishing).not.toHaveBeenCalled(); expect(publisherFactory.mock.calls[0][0].transport).toBe(aTransport); expect(publisherFactory.mock.calls[1][0].transport).toBe(bTransport); + scope.end(); + await flushPromises(); + // stop all tracks after ending scopes + expect(publishers[1].stopPublishing).toHaveBeenCalled(); + expect(publishers[1].stopTracks).toHaveBeenCalled(); + + defaultCreateLocalMemberValues.createPublisherFactory.mockReset(); + }); + + it("only start tracks if requested", async () => { + const scope = new ObservableScope(); + + const localTransport$ = new BehaviorSubject(aTransport); + + const publishers: Publisher[] = []; + + const tracks$ = new BehaviorSubject([]); + const publishing$ = new BehaviorSubject(false); + defaultCreateLocalMemberValues.createPublisherFactory.mockImplementation( + () => { + const p = { + stopPublishing: vi.fn(), + stopTracks: vi.fn(), + createAndSetupTracks: vi.fn().mockImplementation(async () => { + tracks$.next([{}, {}] as LocalTrack[]); + return Promise.resolve(); + }), + tracks$, + publishing$, + }; + publishers.push(p as unknown as Publisher); + return p; + }, + ); + const publisherFactory = + defaultCreateLocalMemberValues.createPublisherFactory as ReturnType< + typeof vi.fn + >; + + const localMembership = createLocalMembership$({ + scope, + ...defaultCreateLocalMemberValues, + connectionManager: { + connectionManagerData$: constant(new Epoch(connectionManagerData)), + }, + localTransport$, + }); + await flushPromises(); + expect(publisherFactory).toHaveBeenCalledOnce(); + expect(localMembership.tracks$.value.length).toBe(0); + localMembership.startTracks(); + await flushPromises(); + expect(localMembership.tracks$.value.length).toBe(2); + scope.end(); + await flushPromises(); + // stop all tracks after ending scopes + expect(publishers[0].stopPublishing).toHaveBeenCalled(); + expect(publishers[0].stopTracks).toHaveBeenCalled(); + }); + // TODO add an integration test combining publisher and localMembership + // + it("tracks livekit state correctly", async () => { + const scope = new ObservableScope(); + + const localTransport$ = new BehaviorSubject(null); + const connectionManagerData$ = new BehaviorSubject< + Epoch + >(new Epoch(new ConnectionManagerData())); + const publishers: Publisher[] = []; + + const tracks$ = new BehaviorSubject([]); + const publishing$ = new BehaviorSubject(false); + const createTrackResolver = Promise.withResolvers(); + const publishResolver = Promise.withResolvers(); + defaultCreateLocalMemberValues.createPublisherFactory.mockImplementation( + () => { + const p = { + stopPublishing: vi.fn(), + stopTracks: vi.fn().mockImplementation(() => { + logger.info("stopTracks"); + tracks$.next([]); + }), + createAndSetupTracks: vi.fn().mockImplementation(async () => { + await createTrackResolver.promise; + tracks$.next([{}, {}] as LocalTrack[]); + }), + startPublishing: vi.fn().mockImplementation(async () => { + await publishResolver.promise; + publishing$.next(true); + }), + tracks$, + publishing$, + }; + publishers.push(p as unknown as Publisher); + return p; + }, + ); + + const publisherFactory = + defaultCreateLocalMemberValues.createPublisherFactory as ReturnType< + typeof vi.fn + >; + + const localMembership = createLocalMembership$({ + scope, + ...defaultCreateLocalMemberValues, + connectionManager: { + connectionManagerData$, + }, + localTransport$, + }); + + await flushPromises(); + expect(localMembership.connectionState.livekit$.value).toStrictEqual({ + state: LivekitState.WaitingForTransport, + }); + localTransport$.next(aTransport); + await flushPromises(); + expect(localMembership.connectionState.livekit$.value).toStrictEqual({ + state: LivekitState.WaitingForConnection, + }); + connectionManagerData$.next(new Epoch(connectionManagerData)); + await flushPromises(); + expect(localMembership.connectionState.livekit$.value).toStrictEqual({ + state: LivekitState.Initialized, + }); + expect(publisherFactory).toHaveBeenCalledOnce(); + expect(localMembership.tracks$.value.length).toBe(0); + + // ------- + localMembership.startTracks(); + // ------- + + await flushPromises(); + expect(localMembership.connectionState.livekit$.value).toStrictEqual({ + state: LivekitState.CreatingTracks, + }); + createTrackResolver.resolve(); + await flushPromises(); + expect(localMembership.connectionState.livekit$.value).toStrictEqual({ + state: LivekitState.ReadyToPublish, + }); + + // ------- + localMembership.requestConnect(); + // ------- + + expect(localMembership.connectionState.livekit$.value).toStrictEqual({ + state: LivekitState.WaitingToPublish, + }); + + publishResolver.resolve(); + await flushPromises(); + expect(localMembership.connectionState.livekit$.value).toStrictEqual({ + state: LivekitState.Connected, + }); + expect(publishers[0].stopPublishing).not.toHaveBeenCalled(); + + expect(localMembership.connectionState.livekit$.isStopped).toBe(false); + scope.end(); + await flushPromises(); + expect(localMembership.connectionState.livekit$.isStopped).toBe(true); + // stays in connected state because it is stopped before the update to tracks update the state. + expect(localMembership.connectionState.livekit$.value).toStrictEqual({ + state: LivekitState.Connected, + }); + // stop all tracks after ending scopes + expect(publishers[0].stopPublishing).toHaveBeenCalled(); + expect(publishers[0].stopTracks).toHaveBeenCalled(); }); }); diff --git a/src/state/CallViewModel/localMember/LocalMembership.ts b/src/state/CallViewModel/localMember/LocalMembership.ts index cfc715e07..706aeaca7 100644 --- a/src/state/CallViewModel/localMember/LocalMembership.ts +++ b/src/state/CallViewModel/localMember/LocalMembership.ts @@ -22,10 +22,12 @@ import { catchError, combineLatest, distinctUntilChanged, + from, map, type Observable, of, scan, + startWith, switchMap, tap, } from "rxjs"; @@ -54,13 +56,13 @@ export enum LivekitState { Error = "error", /** Not even a transport is available to the LocalMembership */ WaitingForTransport = "waiting_for_transport", - /** A transport is and we are loading the connection based on the transport */ - Connecting = "connecting", - InitialisingPublisher = "uninitialized", + /** A connection appeared so we can initialise the publisher */ + WaitingForConnection = "waiting_for_connection", + /** Connection and transport arrived, publisher Initialized */ Initialized = "Initialized", CreatingTracks = "creating_tracks", ReadyToPublish = "ready_to_publish", - WaitingToPublish = "publishing", + WaitingToPublish = "waiting_to_publish", Connected = "connected", Disconnected = "disconnected", Disconnecting = "disconnecting", @@ -69,8 +71,7 @@ export enum LivekitState { type LocalMemberLivekitState = | { state: LivekitState.Error; error: ElementCallError } | { state: LivekitState.WaitingForTransport } - | { state: LivekitState.Connecting } - | { state: LivekitState.InitialisingPublisher } + | { state: LivekitState.WaitingForConnection } | { state: LivekitState.Initialized } | { state: LivekitState.CreatingTracks } | { state: LivekitState.ReadyToPublish } @@ -163,12 +164,10 @@ export const createLocalMembership$ = ({ * Callback to toggle screen sharing. If null, screen sharing is not possible. */ toggleScreenSharing: (() => void) | null; + tracks$: Behavior; participant$: Behavior; connection$: Behavior; homeserverConnected$: Behavior; - // deprecated fields - /** @deprecated use state instead*/ - connected$: Behavior; // this needs to be discussed /** @deprecated use state instead*/ reconnecting$: Behavior; @@ -217,20 +216,19 @@ export const createLocalMembership$ = ({ ), ); + const localConnectionState$ = localConnection$.pipe( + switchMap((connection) => (connection ? connection.state$ : of(null))), + ); + // /** // * Whether we are "fully" connected to the call. Accounts for both the // * connection to the MatrixRTC session and the LiveKit publish connection. // */ - // // TODO use this in combination with the MemberState. const connected$ = scope.behavior( and$( homeserverConnected$, - localConnection$.pipe( - switchMap((c) => - c - ? c.state$.pipe(map((state) => state.state === "ConnectedToLkRoom")) - : of(false), - ), + localConnectionState$.pipe( + map((state) => (state ? state.state === "ConnectedToLkRoom" : false)), ), ), ); @@ -259,7 +257,7 @@ export const createLocalMembership$ = ({ // This should be used in a combineLatest with publisher$ to connect. // to make it possible to call startTracks before the preferredTransport$ has resolved. - const trackStartRequested$ = new BehaviorSubject(false); + const trackStartRequested = Promise.withResolvers(); // This should be used in a combineLatest with publisher$ to connect. // to make it possible to call startTracks before the preferredTransport$ has resolved. @@ -273,19 +271,21 @@ export const createLocalMembership$ = ({ * Extract the tracks from the published. Also reacts to changing publishers. */ const tracks$ = scope.behavior( - publisher$.pipe(switchMap((p) => (p ? p.tracks$ : constant([])))), + publisher$.pipe(switchMap((p) => (p?.tracks$ ? p.tracks$ : constant([])))), ); const publishing$ = scope.behavior( - publisher$.pipe(switchMap((p) => (p ? p.publishing$ : constant(false)))), + publisher$.pipe( + switchMap((p) => (p?.publishing$ ? p.publishing$ : constant(false))), + ), ); const startTracks = (): Behavior => { - trackStartRequested$.next(true); + trackStartRequested.resolve(); return tracks$; }; const requestConnect = (): void => { - trackStartRequested$.next(true); + trackStartRequested.resolve(); connectRequested$.next(true); }; @@ -310,37 +310,18 @@ export const createLocalMembership$ = ({ }); }); - // const mutestate= publisher$.pipe(switchMap((publisher) => { - // return publisher.muteState$ - // }); - - // For each publisher create the descired tracks - // If we recreate a new publisher we remember the trackStartRequested$ value and immediately create the tracks - // THIS might be fine without a reconcile. There is no cleanup needed. We always get a working publisher - // track start request can than just toggle the tracks. - // TODO does this need `reconcile` to make sure we wait for createAndSetupTracks before we stop tracks? - combineLatest([publisher$, trackStartRequested$]).subscribe( - ([publisher, shouldStartTracks]) => { - if (publisher && shouldStartTracks) { - publisher.createAndSetupTracks().catch( - // TODO make this set some error state - (e) => logger.error(e), - ); - } else if (publisher) { - publisher.stopTracks(); - } - }, - ); - // Use reconcile here to not run concurrent createAndSetupTracks calls // `tracks$` will update once they are ready. scope.reconcile( - scope.behavior(combineLatest([publisher$, trackStartRequested$])), - async ([publisher, shouldStartTracks]) => { - if (publisher && shouldStartTracks) { + scope.behavior( + combineLatest([publisher$, tracks$, from(trackStartRequested.promise)]), + null, + ), + async (valueIfReady) => { + if (!valueIfReady) return; + const [publisher, tracks] = valueIfReady; + if (publisher && tracks.length === 0) { await publisher.createAndSetupTracks().catch((e) => logger.error(e)); - } else if (publisher) { - publisher.stopTracks(); } }, ); @@ -349,8 +330,7 @@ export const createLocalMembership$ = ({ scope.reconcile( scope.behavior(combineLatest([publisher$, tracks$, connectRequested$])), async ([publisher, tracks, shouldConnect]) => { - if (shouldConnect === publisher?.publishing$.value) - return Promise.resolve(); + if (shouldConnect === publisher?.publishing$.value) return; if (tracks.length !== 0 && shouldConnect) { try { await publisher?.startPublishing(); @@ -374,46 +354,53 @@ export const createLocalMembership$ = ({ logger.error("Multiple Livkit Errors:", e); else fatalLivekitError$.next(e); }; - const livekitState$: Observable = combineLatest([ - publisher$, - localTransport$, - localConnection$, - tracks$, - publishing$, - connectRequested$, - trackStartRequested$, - fatalLivekitError$, - ]).pipe( - map( - ([ - publisher, - localTransport, - localConnection, - tracks, - publishing, - shouldConnect, - shouldStartTracks, - error, - ]) => { - // read this: - // if(!) return {state: ...} - // if(!) return {state: } - // - // as: - // We do have but not yet so we are in - if (error !== null) return { state: LivekitState.Error, error }; - const hasTracks = tracks.length > 0; - if (!localTransport) return { state: LivekitState.WaitingForTransport }; - if (!localConnection) return { state: LivekitState.Connecting }; - if (!publisher) return { state: LivekitState.InitialisingPublisher }; - if (!shouldStartTracks) return { state: LivekitState.Initialized }; - if (!hasTracks) return { state: LivekitState.CreatingTracks }; - if (!shouldConnect) return { state: LivekitState.ReadyToPublish }; - if (!publishing) return { state: LivekitState.WaitingToPublish }; - return { state: LivekitState.Connected }; - }, + const livekitState$: Behavior = scope.behavior( + combineLatest([ + publisher$, + localTransport$, + tracks$.pipe( + tap((t) => { + logger.info("tracks$: ", t); + }), + ), + publishing$, + connectRequested$, + from(trackStartRequested.promise).pipe( + map(() => true), + startWith(false), + ), + fatalLivekitError$, + ]).pipe( + map( + ([ + publisher, + localTransport, + tracks, + publishing, + shouldConnect, + shouldStartTracks, + error, + ]) => { + // read this: + // if(!) return {state: ...} + // if(!) return {state: } + // + // as: + // We do have but not yet so we are in + if (error !== null) return { state: LivekitState.Error, error }; + const hasTracks = tracks.length > 0; + if (!localTransport) + return { state: LivekitState.WaitingForTransport }; + if (!publisher) return { state: LivekitState.WaitingForConnection }; + if (!shouldStartTracks) return { state: LivekitState.Initialized }; + if (!hasTracks) return { state: LivekitState.CreatingTracks }; + if (!shouldConnect) return { state: LivekitState.ReadyToPublish }; + if (!publishing) return { state: LivekitState.WaitingToPublish }; + return { state: LivekitState.Connected }; + }, + ), + distinctUntilChanged(deepCompare), ), - distinctUntilChanged(deepCompare), ); const fatalMatrixError$ = new BehaviorSubject(null); @@ -577,15 +564,15 @@ export const createLocalMembership$ = ({ requestConnect, requestDisconnect, connectionState: { - livekit$: scope.behavior(livekitState$), + livekit$: livekitState$, matrix$: matrixState$, }, + tracks$, + participant$, homeserverConnected$, - connected$, reconnecting$, sharingScreen$, toggleScreenSharing, - participant$, connection$: localConnection$, }; }; diff --git a/src/state/CallViewModel/localMember/Publisher.ts b/src/state/CallViewModel/localMember/Publisher.ts index df6addb8a..14f44491a 100644 --- a/src/state/CallViewModel/localMember/Publisher.ts +++ b/src/state/CallViewModel/localMember/Publisher.ts @@ -15,6 +15,7 @@ import { } from "livekit-client"; import { BehaviorSubject, + combineLatest, map, NEVER, type Observable, @@ -80,6 +81,23 @@ export class Publisher { ); void this.stopPublishing(); }); + + // TODO move mute state handling here using reconcile (instead of inside the mute state class) + // this.scope.reconcile( + // this.scope.behavior( + // combineLatest([this.muteStates.video.enabled$, this.tracks$]), + // ), + // async ([videoEnabled, tracks]) => { + // const track = tracks.find((t) => t.kind == Track.Kind.Video); + // if (!track) return; + + // if (videoEnabled) { + // await track.unmute(); + // } else { + // await track.mute(); + // } + // }, + // ); } private _tracks$ = new BehaviorSubject[]>([]); diff --git a/src/state/ObservableScope.ts b/src/state/ObservableScope.ts index 6d8674149..812cfcd7f 100644 --- a/src/state/ObservableScope.ts +++ b/src/state/ObservableScope.ts @@ -80,8 +80,11 @@ export class ObservableScope { error(err: unknown) { subject$.error(err); }, + complete() { + subject$.complete(); + }, }); - if (subject$.value === nothing) + if (subject$.value === nothing && !subject$.isStopped) throw new Error("Behavior failed to synchronously emit an initial value"); return subject$ as Behavior; } @@ -125,11 +128,11 @@ export class ObservableScope { let latestValue: T | typeof nothing = nothing; let reconcilePromise: Promise | undefined = undefined; let cleanUp: (() => Promise) | void = undefined; + let prevVal: T | typeof nothing = nothing; // While this loop runs it will process the latest from `value$` until it caught up with the updates. // It might skip updates from `value$` and only process the newest value after callback has resolved. const reconcileLoop = async (): Promise => { - let prevVal: T | typeof nothing = nothing; while (latestValue !== prevVal) { await cleanUp?.(); // Call the previous value's clean-up handler prevVal = latestValue; From 4b0f6e76c4f8df8b227fdbff5bf4800afef9e63c Mon Sep 17 00:00:00 2001 From: Timo K Date: Thu, 27 Nov 2025 15:38:31 +0100 Subject: [PATCH 008/748] revert complete behavior check --- src/state/ObservableScope.ts | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/state/ObservableScope.ts b/src/state/ObservableScope.ts index 812cfcd7f..e3fc644f7 100644 --- a/src/state/ObservableScope.ts +++ b/src/state/ObservableScope.ts @@ -80,11 +80,8 @@ export class ObservableScope { error(err: unknown) { subject$.error(err); }, - complete() { - subject$.complete(); - }, }); - if (subject$.value === nothing && !subject$.isStopped) + if (subject$.value === nothing) throw new Error("Behavior failed to synchronously emit an initial value"); return subject$ as Behavior; } From fc39e82666182e273a40a7c3bc0a10b7bdf9267c Mon Sep 17 00:00:00 2001 From: Valere Date: Thu, 27 Nov 2025 15:52:25 +0100 Subject: [PATCH 009/748] Fix: Camera is not muted when the earpiece mode is enabled --- src/state/MuteStates.test.ts | 190 +++++++++++++++++++++++++++++++++++ src/state/MuteStates.ts | 58 ++++++++++- 2 files changed, 243 insertions(+), 5 deletions(-) create mode 100644 src/state/MuteStates.test.ts diff --git a/src/state/MuteStates.test.ts b/src/state/MuteStates.test.ts new file mode 100644 index 000000000..7b02d1907 --- /dev/null +++ b/src/state/MuteStates.test.ts @@ -0,0 +1,190 @@ +/* +Copyright 2025 Element Creations Ltd. + +SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial +Please see LICENSE in the repository root for full details. +*/ + +import { afterEach, beforeEach, describe, expect, test, vi } from "vitest"; +import { BehaviorSubject } from "rxjs"; +import { logger } from "matrix-js-sdk/lib/logger"; + +import { MuteStates, MuteState } from "./MuteStates"; +import { + type AudioOutputDeviceLabel, + type DeviceLabel, + type MediaDevice, + type SelectedAudioOutputDevice, + type SelectedDevice, +} from "./MediaDevices"; +import { constant } from "./Behavior"; +import { ObservableScope } from "./ObservableScope"; +import { flushPromises, mockMediaDevices } from "../utils/test"; + +const getUrlParams = vi.hoisted(() => vi.fn(() => ({}))); +vi.mock("../UrlParams", () => ({ getUrlParams })); + +let testScope: ObservableScope; + +beforeEach(() => { + testScope = new ObservableScope(); +}); + +afterEach(() => { + testScope.end(); +}); + +describe("MuteState", () => { + test("should automatically mute if force mute is set", async () => { + const forceMute$ = new BehaviorSubject(false); + + const deviceStub = { + available$: constant( + new Map([ + ["fbac11", { type: "name", name: "HD Camera" }], + ]), + ), + selected$: constant({ id: "fbac11" }), + select(): void {}, + } as unknown as MediaDevice; + + const muteState = new MuteState( + testScope, + deviceStub, + constant(true), + true, + forceMute$, + ); + let lastEnabled: boolean = false; + muteState.enabled$.subscribe((enabled) => { + lastEnabled = enabled; + }); + let setEnabled: ((enabled: boolean) => void) | null = null; + muteState.setEnabled$.subscribe((setter) => { + setEnabled = setter; + }); + + await flushPromises(); + + setEnabled!(true); + await flushPromises(); + expect(lastEnabled).toBe(true); + + // Now force mute + forceMute$.next(true); + await flushPromises(); + // Should automatically mute + expect(lastEnabled).toBe(false); + + // Try to unmute can not work + expect(setEnabled).toBeNull(); + + // Disable force mute + forceMute$.next(false); + await flushPromises(); + + // TODO I'd expect it to go back to previous state (enabled) + // but actually it goes back to the initial state from construction (disabled) + // Should go back to previous state (enabled) + // Skip for now + // expect(lastEnabled).toBe(true); + + // But yet it can be unmuted now + expect(setEnabled).not.toBeNull(); + + setEnabled!(true); + await flushPromises(); + expect(lastEnabled).toBe(true); + }); +}); + +describe("MuteStates", () => { + function aAudioOutputDevices(): MediaDevice< + AudioOutputDeviceLabel, + SelectedAudioOutputDevice + > { + const selected$ = new BehaviorSubject< + SelectedAudioOutputDevice | undefined + >({ + id: "default", + virtualEarpiece: false, + }); + return { + available$: constant( + new Map([ + ["default", { type: "speaker" }], + ["0000", { type: "speaker" }], + ["1111", { type: "earpiece" }], + ["222", { type: "name", name: "Bluetooth Speaker" }], + ]), + ), + selected$, + select(id: string): void { + if (!this.available$.getValue().has(id)) { + logger.warn(`Attempted to select unknown device id: ${id}`); + return; + } + selected$.next({ + id, + /** For test purposes we ignore this */ + virtualEarpiece: false, + }); + }, + }; + } + + function aVideoInput(): MediaDevice { + const selected$ = new BehaviorSubject( + undefined, + ); + return { + available$: constant( + new Map([ + ["0000", { type: "name", name: "HD Camera" }], + ["1111", { type: "name", name: "WebCam Pro" }], + ]), + ), + selected$, + select(id: string): void { + if (!this.available$.getValue().has(id)) { + logger.warn(`Attempted to select unknown device id: ${id}`); + return; + } + selected$.next({ id }); + }, + }; + } + + test("should mute camera when in earpiece mode", async () => { + const audioOutputDevice = aAudioOutputDevices(); + + const mediaDevices = mockMediaDevices({ + audioOutput: audioOutputDevice, + videoInput: aVideoInput(), + // other devices are not relevant for this test + }); + const muteStates = new MuteStates( + testScope, + mediaDevices, + // consider joined + constant(true), + ); + + let lastVideoEnabled: boolean = false; + muteStates.video.enabled$.subscribe((enabled) => { + lastVideoEnabled = enabled; + }); + + expect(muteStates.video.setEnabled$.value).toBeDefined(); + muteStates.video.setEnabled$.value?.(true); + await flushPromises(); + + expect(lastVideoEnabled).toBe(true); + + // Select earpiece audio output + audioOutputDevice.select("1111"); + await flushPromises(); + // Video should be automatically muted + expect(lastVideoEnabled).toBe(false); + }); +}); diff --git a/src/state/MuteStates.ts b/src/state/MuteStates.ts index 50be5e056..777e3aa45 100644 --- a/src/state/MuteStates.ts +++ b/src/state/MuteStates.ts @@ -27,7 +27,7 @@ import { ElementWidgetActions, widget } from "../widget"; import { Config } from "../config/Config"; import { getUrlParams } from "../UrlParams"; import { type ObservableScope } from "./ObservableScope"; -import { type Behavior } from "./Behavior"; +import { type Behavior, constant } from "./Behavior"; interface MuteStateData { enabled$: Observable; @@ -38,31 +38,55 @@ interface MuteStateData { export type Handler = (desired: boolean) => Promise; const defaultHandler: Handler = async (desired) => Promise.resolve(desired); -class MuteState { +/** + * Internal class - exported only for testing purposes. + * Do not use directly outside of tests. + */ +export class MuteState { + // TODO: rewrite this to explain behavior, it is not understandable, and cannot add logging private readonly enabledByDefault$ = this.enabledByConfig && !getUrlParams().skipLobby ? this.joined$.pipe(map((isJoined) => !isJoined)) : of(false); private readonly handler$ = new BehaviorSubject(defaultHandler); + public setHandler(handler: Handler): void { if (this.handler$.value !== defaultHandler) throw new Error("Multiple mute state handlers are not supported"); this.handler$.next(handler); } + public unsetHandler(): void { this.handler$.next(defaultHandler); } + private readonly devicesConnected$ = combineLatest([ + this.device.available$, + this.forceMute$, + ]).pipe( + map(([available, forceMute]) => { + return !forceMute && available.size > 0; + }), + ); + private readonly data$ = this.scope.behavior( - this.device.available$.pipe( - map((available) => available.size > 0), + this.devicesConnected$.pipe( + // this.device.available$.pipe( + // map((available) => available.size > 0), distinctUntilChanged(), withLatestFrom( this.enabledByDefault$, (devicesConnected, enabledByDefault) => { - if (!devicesConnected) + logger.info( + `MuteState: devices connected: ${devicesConnected}, enabled by default: ${enabledByDefault}`, + ); + if (!devicesConnected) { + logger.info( + `MuteState: devices connected: ${devicesConnected}, disabling`, + ); return { enabled$: of(false), set: null, toggle: null }; + } // Assume the default value only once devices are actually connected let enabled = enabledByDefault; @@ -135,21 +159,45 @@ class MuteState { private readonly device: MediaDevice, private readonly joined$: Observable, private readonly enabledByConfig: boolean, + /** + * An optional observable which, when it emits `true`, will force the mute. + * Used for video to stop camera when earpiece mode is on. + * @private + */ + private readonly forceMute$: Observable, ) {} } export class MuteStates { + /** + * True if the selected audio output device is an earpiece. + * Used to force-disable video when on earpiece. + */ + private readonly isEarpiece$ = combineLatest( + this.mediaDevices.audioOutput.available$, + this.mediaDevices.audioOutput.selected$, + ).pipe( + map(([available, selected]) => { + if (!selected?.id) return false; + const device = available.get(selected.id); + logger.info(`MuteStates: selected audio output device:`, device); + return device?.type === "earpiece"; + }), + ); + public readonly audio = new MuteState( this.scope, this.mediaDevices.audioInput, this.joined$, Config.get().media_devices.enable_audio, + constant(false), ); public readonly video = new MuteState( this.scope, this.mediaDevices.videoInput, this.joined$, Config.get().media_devices.enable_video, + this.isEarpiece$, ); public constructor( From 46f8fe4ec7362cf9e5b033563503be33d4e355b8 Mon Sep 17 00:00:00 2001 From: Timo K Date: Thu, 27 Nov 2025 16:43:03 +0100 Subject: [PATCH 010/748] fix test errors --- .../CallViewModel/localMember/LocalMembership.test.ts | 10 +++++++--- src/state/CallViewModel/localMember/Publisher.ts | 1 - 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/src/state/CallViewModel/localMember/LocalMembership.test.ts b/src/state/CallViewModel/localMember/LocalMembership.test.ts index 6c6c3d6ee..f5256005f 100644 --- a/src/state/CallViewModel/localMember/LocalMembership.test.ts +++ b/src/state/CallViewModel/localMember/LocalMembership.test.ts @@ -225,7 +225,7 @@ describe("LocalMembership", () => { }); expectObservable(localMembership.connectionState.livekit$).toBe("ne", { - n: { state: LivekitState.Connecting }, + n: { state: LivekitState.WaitingForConnection }, e: { state: LivekitState.Error, error: expect.toSatisfy( @@ -279,7 +279,11 @@ describe("LocalMembership", () => { defaultCreateLocalMemberValues.createPublisherFactory.mockImplementation( () => { - const p = { stopPublishing: vi.fn(), stopTracks: vi.fn() }; + const p = { + stopPublishing: vi.fn(), + stopTracks: vi.fn(), + publishing$: constant(false), + }; publishers.push(p as unknown as Publisher); return p; }, @@ -367,6 +371,7 @@ describe("LocalMembership", () => { // stop all tracks after ending scopes expect(publishers[0].stopPublishing).toHaveBeenCalled(); expect(publishers[0].stopTracks).toHaveBeenCalled(); + publisherFactory.mockClear(); }); // TODO add an integration test combining publisher and localMembership // @@ -470,7 +475,6 @@ describe("LocalMembership", () => { expect(localMembership.connectionState.livekit$.isStopped).toBe(false); scope.end(); await flushPromises(); - expect(localMembership.connectionState.livekit$.isStopped).toBe(true); // stays in connected state because it is stopped before the update to tracks update the state. expect(localMembership.connectionState.livekit$.value).toStrictEqual({ state: LivekitState.Connected, diff --git a/src/state/CallViewModel/localMember/Publisher.ts b/src/state/CallViewModel/localMember/Publisher.ts index 14f44491a..7fc7d9243 100644 --- a/src/state/CallViewModel/localMember/Publisher.ts +++ b/src/state/CallViewModel/localMember/Publisher.ts @@ -15,7 +15,6 @@ import { } from "livekit-client"; import { BehaviorSubject, - combineLatest, map, NEVER, type Observable, From c0913b654612347282a0a0d8098d10dccff40303 Mon Sep 17 00:00:00 2001 From: Timo K Date: Thu, 27 Nov 2025 18:02:46 +0100 Subject: [PATCH 011/748] fix playwright test --- locales/en/app.json | 2 +- .../CallViewModel/localMember/LocalMembership.test.ts | 1 + src/state/CallViewModel/localMember/Publisher.ts | 11 +++++++++-- 3 files changed, 11 insertions(+), 3 deletions(-) diff --git a/locales/en/app.json b/locales/en/app.json index 32d10663d..1ff066ea6 100644 --- a/locales/en/app.json +++ b/locales/en/app.json @@ -108,7 +108,7 @@ "connection_lost_description": "You were disconnected from the call.", "e2ee_unsupported": "Incompatible browser", "e2ee_unsupported_description": "Your web browser does not support encrypted calls. Supported browsers include Chrome, Safari, and Firefox 117+.", - "failed_to_start_livekit": "Failed to start Livekit", + "failed_to_start_livekit": "Failed to start Livekit connection", "generic": "Something went wrong", "generic_description": "Submitting debug logs will help us track down the problem.", "insufficient_capacity": "Insufficient capacity", diff --git a/src/state/CallViewModel/localMember/LocalMembership.test.ts b/src/state/CallViewModel/localMember/LocalMembership.test.ts index f5256005f..e5b7cc4a3 100644 --- a/src/state/CallViewModel/localMember/LocalMembership.test.ts +++ b/src/state/CallViewModel/localMember/LocalMembership.test.ts @@ -483,4 +483,5 @@ describe("LocalMembership", () => { expect(publishers[0].stopPublishing).toHaveBeenCalled(); expect(publishers[0].stopTracks).toHaveBeenCalled(); }); + // TODO add tests for matrix local matrix participation. }); diff --git a/src/state/CallViewModel/localMember/Publisher.ts b/src/state/CallViewModel/localMember/Publisher.ts index 7fc7d9243..2021d6180 100644 --- a/src/state/CallViewModel/localMember/Publisher.ts +++ b/src/state/CallViewModel/localMember/Publisher.ts @@ -34,7 +34,10 @@ import { getUrlParams } from "../../../UrlParams.ts"; import { observeTrackReference$ } from "../../MediaViewModel.ts"; import { type Connection } from "../remoteMembers/Connection.ts"; import { type ObservableScope } from "../../ObservableScope.ts"; -import { FailToStartLivekitConnection } from "../../../utils/errors.ts"; +import { + ElementCallError, + FailToStartLivekitConnection, +} from "../../../utils/errors.ts"; /** * A wrapper for a Connection object. @@ -154,7 +157,11 @@ export class Publisher { resolve(); break; case "FailedToStart": - reject(new FailToStartLivekitConnection()); + reject( + s.error instanceof ElementCallError + ? s.error + : new FailToStartLivekitConnection(), + ); break; default: this.logger?.info("waiting for connection: ", s.state); From 149f3d02ae583d90c5cd458c7d290106d5aba1c5 Mon Sep 17 00:00:00 2001 From: Valere Date: Thu, 27 Nov 2025 18:47:33 +0100 Subject: [PATCH 012/748] fix: The force mute state was not synced to the handler --- src/state/MuteStates.test.ts | 22 ++++++++++++++++++++++ src/state/MuteStates.ts | 7 +++++-- 2 files changed, 27 insertions(+), 2 deletions(-) diff --git a/src/state/MuteStates.test.ts b/src/state/MuteStates.test.ts index 7b02d1907..f2a6e35f8 100644 --- a/src/state/MuteStates.test.ts +++ b/src/state/MuteStates.test.ts @@ -170,6 +170,13 @@ describe("MuteStates", () => { constant(true), ); + let latestSyncedState: boolean | null = null; + muteStates.video.setHandler(async (enabled: boolean): Promise => { + logger.info(`Video mute state set to: ${enabled}`); + latestSyncedState = enabled; + return Promise.resolve(enabled); + }); + let lastVideoEnabled: boolean = false; muteStates.video.enabled$.subscribe((enabled) => { lastVideoEnabled = enabled; @@ -186,5 +193,20 @@ describe("MuteStates", () => { await flushPromises(); // Video should be automatically muted expect(lastVideoEnabled).toBe(false); + expect(latestSyncedState).toBe(false); + + // Try to switch to speaker + audioOutputDevice.select("0000"); + await flushPromises(); + // TODO I'd expect it to go back to previous state (enabled)?? + // But maybe not? If you move the phone away from your ear you may not want it + // to automatically enable video? + expect(lastVideoEnabled).toBe(false); + + // But yet it can be unmuted now + expect(muteStates.video.setEnabled$.value).toBeDefined(); + muteStates.video.setEnabled$.value?.(true); + await flushPromises(); + expect(lastVideoEnabled).toBe(true); }); }); diff --git a/src/state/MuteStates.ts b/src/state/MuteStates.ts index 777e3aa45..f1d61db58 100644 --- a/src/state/MuteStates.ts +++ b/src/state/MuteStates.ts @@ -72,8 +72,6 @@ export class MuteState { private readonly data$ = this.scope.behavior( this.devicesConnected$.pipe( - // this.device.available$.pipe( - // map((available) => available.size > 0), distinctUntilChanged(), withLatestFrom( this.enabledByDefault$, @@ -85,6 +83,11 @@ export class MuteState { logger.info( `MuteState: devices connected: ${devicesConnected}, disabling`, ); + // We need to sync the mute state with the handler + // to ensure nothing is beeing published. + this.handler$.value(false).catch((err) => { + logger.error("MuteState-disable: handler error", err); + }); return { enabled$: of(false), set: null, toggle: null }; } From 2011aef116f21e8ad2aaaac004c141538c4ae29d Mon Sep 17 00:00:00 2001 From: Timo K Date: Fri, 28 Nov 2025 17:59:10 +0100 Subject: [PATCH 013/748] skip "Should show error screen if call creation is restricted" on ff --- playwright/errors.spec.ts | 5 +++++ src/state/CallViewModel/localMember/LocalMembership.ts | 1 - src/state/CallViewModel/localMember/Publisher.ts | 1 + src/state/CallViewModel/remoteMembers/Connection.ts | 1 - 4 files changed, 6 insertions(+), 2 deletions(-) diff --git a/playwright/errors.spec.ts b/playwright/errors.spec.ts index 851e448d9..0dc9fa384 100644 --- a/playwright/errors.spec.ts +++ b/playwright/errors.spec.ts @@ -75,7 +75,12 @@ test("Should automatically retry non fatal JWT errors", async ({ test("Should show error screen if call creation is restricted", async ({ page, + browserName, }) => { + test.skip( + browserName === "firefox", + "The test to check the video visibility is not working in Firefox CI environment. looks like video is disabled?", + ); await page.goto("/"); // We need the socket connection to fail, but this cannot be done by using the websocket route. diff --git a/src/state/CallViewModel/localMember/LocalMembership.ts b/src/state/CallViewModel/localMember/LocalMembership.ts index 706aeaca7..a68738e1a 100644 --- a/src/state/CallViewModel/localMember/LocalMembership.ts +++ b/src/state/CallViewModel/localMember/LocalMembership.ts @@ -335,7 +335,6 @@ export const createLocalMembership$ = ({ try { await publisher?.startPublishing(); } catch (error) { - // will take care of "FailedToStartLk" errors. setLivekitError(error as ElementCallError); } } else if (tracks.length !== 0 && !shouldConnect) { diff --git a/src/state/CallViewModel/localMember/Publisher.ts b/src/state/CallViewModel/localMember/Publisher.ts index 2021d6180..a93ef392d 100644 --- a/src/state/CallViewModel/localMember/Publisher.ts +++ b/src/state/CallViewModel/localMember/Publisher.ts @@ -174,6 +174,7 @@ export class Publisher { } finally { sub.unsubscribe(); } + for (const track of this.tracks$.value) { // TODO: handle errors? Needs the signaling connection to be up, but it has some retries internally // with a timeout. diff --git a/src/state/CallViewModel/remoteMembers/Connection.ts b/src/state/CallViewModel/remoteMembers/Connection.ts index 81bc9f294..afa519fb9 100644 --- a/src/state/CallViewModel/remoteMembers/Connection.ts +++ b/src/state/CallViewModel/remoteMembers/Connection.ts @@ -110,7 +110,6 @@ export class Connection { * @throws {InsufficientCapacityError} if the LiveKit server indicates that it has insufficient capacity to accept the connection. * @throws {SFURoomCreationRestrictedError} if the LiveKit server indicates that the room does not exist and cannot be created. */ - // TODO dont make this throw and instead store a connection error state in this class? // TODO consider an autostart pattern... public async start(): Promise { this.logger.debug("Starting Connection"); From 66dece98a5cb7b2ece7ec28e665edcf387916ce8 Mon Sep 17 00:00:00 2001 From: Timo K Date: Fri, 28 Nov 2025 21:50:22 +0100 Subject: [PATCH 014/748] add more test for publisher --- playwright/errors.spec.ts | 2 +- .../localMember/Publisher.test.ts | 138 ++++++++++++++++++ .../CallViewModel/localMember/Publisher.ts | 14 +- src/utils/errors.ts | 4 +- src/utils/test.ts | 6 +- 5 files changed, 154 insertions(+), 10 deletions(-) create mode 100644 src/state/CallViewModel/localMember/Publisher.test.ts diff --git a/playwright/errors.spec.ts b/playwright/errors.spec.ts index 0dc9fa384..0d36f7ab4 100644 --- a/playwright/errors.spec.ts +++ b/playwright/errors.spec.ts @@ -79,7 +79,7 @@ test("Should show error screen if call creation is restricted", async ({ }) => { test.skip( browserName === "firefox", - "The test to check the video visibility is not working in Firefox CI environment. looks like video is disabled?", + "The is test is not working on firefox CI environment.", ); await page.goto("/"); diff --git a/src/state/CallViewModel/localMember/Publisher.test.ts b/src/state/CallViewModel/localMember/Publisher.test.ts new file mode 100644 index 000000000..f45f7abe8 --- /dev/null +++ b/src/state/CallViewModel/localMember/Publisher.test.ts @@ -0,0 +1,138 @@ +/* +Copyright 2025 Element Creations Ltd. + +SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial +Please see LICENSE in the repository root for full details. +*/ + +import { + afterEach, + beforeEach, + describe, + expect, + it, + type Mock, + vi, +} from "vitest"; +import { ConnectionState as LivekitConenctionState } from "livekit-client"; +import { type BehaviorSubject } from "rxjs"; + +import { ObservableScope } from "../../ObservableScope"; +import { constant } from "../../Behavior"; +import { + mockLivekitRoom, + mockLocalParticipant, + mockMediaDevices, +} from "../../../utils/test"; +import { Publisher } from "./Publisher"; +import { + type Connection, + type ConnectionState, +} from "../remoteMembers/Connection"; +import { type MuteStates } from "../../MuteStates"; +import { FailToStartLivekitConnection } from "../../../utils/errors"; + +describe("Publisher", () => { + let scope: ObservableScope; + let connection: Connection; + let muteStates: MuteStates; + beforeEach(() => { + muteStates = { + audio: { + enabled$: constant(false), + unsetHandler: vi.fn(), + setHandler: vi.fn(), + }, + video: { + enabled$: constant(false), + unsetHandler: vi.fn(), + setHandler: vi.fn(), + }, + } as unknown as MuteStates; + scope = new ObservableScope(); + connection = { + state$: constant({ + state: "ConnectedToLkRoom", + livekitConnectionState$: constant(LivekitConenctionState.Connected), + }), + livekitRoom: mockLivekitRoom({ + localParticipant: mockLocalParticipant({}), + }), + } as unknown as Connection; + }); + + afterEach(() => scope.end()); + + it("throws if livekit room could not publish", async () => { + const publisher = new Publisher( + scope, + connection, + mockMediaDevices({}), + muteStates, + constant({ supported: false, processor: undefined }), + ); + + // should do nothing if no tracks have been created yet. + await publisher.startPublishing(); + expect( + connection.livekitRoom.localParticipant.publishTrack, + ).not.toHaveBeenCalled(); + + await expect(publisher.createAndSetupTracks()).rejects.toThrow( + Error("audio and video is false"), + ); + + (muteStates.audio.enabled$ as BehaviorSubject).next(true); + + ( + connection.livekitRoom.localParticipant.createTracks as Mock + ).mockResolvedValue([{}, {}]); + + await expect(publisher.createAndSetupTracks()).resolves.not.toThrow(); + expect( + connection.livekitRoom.localParticipant.createTracks, + ).toHaveBeenCalledOnce(); + + // failiour due to localParticipant.publishTrack + ( + connection.livekitRoom.localParticipant.publishTrack as Mock + ).mockRejectedValue(Error("testError")); + + await expect(publisher.startPublishing()).rejects.toThrow( + new FailToStartLivekitConnection("testError"), + ); + + // does not try other conenction after the first one failed + expect( + connection.livekitRoom.localParticipant.publishTrack, + ).toHaveBeenCalledTimes(1); + + // failiour due to connection.state$ + const beforeState = connection.state$.value; + (connection.state$ as BehaviorSubject).next({ + state: "FailedToStart", + error: Error("testStartError"), + }); + + await expect(publisher.startPublishing()).rejects.toThrow( + new FailToStartLivekitConnection("testStartError"), + ); + (connection.state$ as BehaviorSubject).next(beforeState); + + // does not try other conenction after the first one failed + expect( + connection.livekitRoom.localParticipant.publishTrack, + ).toHaveBeenCalledTimes(1); + + // success case + ( + connection.livekitRoom.localParticipant.publishTrack as Mock + ).mockResolvedValue({}); + + await expect(publisher.startPublishing()).resolves.not.toThrow(); + + expect( + connection.livekitRoom.localParticipant.publishTrack, + ).toHaveBeenCalledTimes(3); + }); +}); diff --git a/src/state/CallViewModel/localMember/Publisher.ts b/src/state/CallViewModel/localMember/Publisher.ts index a93ef392d..3f3192d14 100644 --- a/src/state/CallViewModel/localMember/Publisher.ts +++ b/src/state/CallViewModel/localMember/Publisher.ts @@ -56,7 +56,7 @@ export class Publisher { */ public constructor( private scope: ObservableScope, - private connection: Connection, + private connection: Pick, //setE2EEEnabled, devices: MediaDevices, private readonly muteStates: MuteStates, trackerProcessorState$: Behavior, @@ -160,7 +160,7 @@ export class Publisher { reject( s.error instanceof ElementCallError ? s.error - : new FailToStartLivekitConnection(), + : new FailToStartLivekitConnection(s.error.message), ); break; default: @@ -180,17 +180,16 @@ export class Publisher { // with a timeout. await lkRoom.localParticipant.publishTrack(track).catch((error) => { this.logger?.error("Failed to publish track", error); + throw new FailToStartLivekitConnection( + error instanceof Error ? error.message : error, + ); }); - - // TODO: check if the connection is still active? and break the loop if not? } this._publishing$.next(true); return this.tracks$.value; } public async stopPublishing(): Promise { - // TODO-MULTI-SFU: Move these calls back to ObservableScope.onEnd once scope - // actually has the right lifetime this.muteStates.audio.unsetHandler(); this.muteStates.video.unsetHandler(); @@ -246,6 +245,9 @@ export class Publisher { // the process of being restarted. activeMicTrack.mediaStreamTrack.readyState !== "ended" ) { + this.logger?.info( + "Restarting audio device track due to active media device changed (workaroundRestartAudioInputTrackChrome)", + ); // Restart the track, which will cause Livekit to do another // getUserMedia() call with deviceId: default to get the *new* default device. // Note that room.switchActiveDevice() won't work: Livekit will ignore it because diff --git a/src/utils/errors.ts b/src/utils/errors.ts index cdd0e75ce..bb37754ab 100644 --- a/src/utils/errors.ts +++ b/src/utils/errors.ts @@ -136,12 +136,12 @@ export class FailToGetOpenIdToken extends ElementCallError { } export class FailToStartLivekitConnection extends ElementCallError { - public constructor() { + public constructor(e?: string) { super( t("error.failed_to_start_livekit"), ErrorCode.FAILED_TO_START_LIVEKIT, ErrorCategory.NETWORK_CONNECTIVITY, - undefined, + e, ); } } diff --git a/src/utils/test.ts b/src/utils/test.ts index 471d35d8d..d243b3439 100644 --- a/src/utils/test.ts +++ b/src/utils/test.ts @@ -284,6 +284,8 @@ export function mockLivekitRoom( ): LivekitRoom { const livekitRoom = { options: {}, + setE2EEEnabled: vi.fn(), + ...mockEmitter(), ...room, } as Partial as LivekitRoom; @@ -306,7 +308,9 @@ export function mockLocalParticipant( return { isLocal: true, trackPublications: new Map(), - unpublishTracks: async () => Promise.resolve(), + publishTrack: vi.fn(), + unpublishTracks: vi.fn(), + createTracks: vi.fn(), getTrackPublication: () => ({}) as Partial as LocalTrackPublication, ...mockEmitter(), From 5aa82295fdb2bb522c3e4c9c4d07542555f3ed69 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 1 Dec 2025 01:28:55 +0000 Subject: [PATCH 015/748] Update embedded package dependencies --- embedded/android/gradle/libs.versions.toml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/embedded/android/gradle/libs.versions.toml b/embedded/android/gradle/libs.versions.toml index 8ec7801a3..5a91e19e6 100644 --- a/embedded/android/gradle/libs.versions.toml +++ b/embedded/android/gradle/libs.versions.toml @@ -2,11 +2,11 @@ # https://docs.gradle.org/current/userguide/platforms.html#sub::toml-dependencies-format [versions] -android_gradle_plugin = "8.13.0" +android_gradle_plugin = "8.13.1" [libraries] android_gradle_plugin = { module = "com.android.tools.build:gradle", version.ref = "android_gradle_plugin" } [plugins] android_library = { id = "com.android.library", version.ref = "android_gradle_plugin" } -maven_publish = { id = "com.vanniktech.maven.publish", version = "0.34.0" } \ No newline at end of file +maven_publish = { id = "com.vanniktech.maven.publish", version = "0.35.0" } \ No newline at end of file From 04bbf83ac52339432eb69a699b4448782dfe6129 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 1 Dec 2025 11:00:52 +0000 Subject: [PATCH 016/748] Update GitHub Actions --- .github/workflows/build-and-publish-docker.yaml | 4 ++-- .github/workflows/build-element-call.yaml | 2 +- .github/workflows/lint.yaml | 2 +- .github/workflows/publish-embedded-packages.yaml | 12 ++++++------ .github/workflows/publish.yaml | 4 ++-- .github/workflows/test.yaml | 4 ++-- .github/workflows/translations-download.yaml | 4 ++-- .github/workflows/translations-upload.yaml | 2 +- 8 files changed, 17 insertions(+), 17 deletions(-) diff --git a/.github/workflows/build-and-publish-docker.yaml b/.github/workflows/build-and-publish-docker.yaml index a50fca48e..4ad1a551b 100644 --- a/.github/workflows/build-and-publish-docker.yaml +++ b/.github/workflows/build-and-publish-docker.yaml @@ -23,7 +23,7 @@ jobs: packages: write steps: - name: Check it out - uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4 + uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 - name: 📥 Download artifact uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4 @@ -42,7 +42,7 @@ jobs: - name: Extract metadata (tags, labels) for Docker id: meta - uses: docker/metadata-action@c1e51972afc2121e065aed6d45c65596fe445f3f # v5.8.0 + uses: docker/metadata-action@318604b99e75e41977312d83839a89be02ca4893 # v5.9.0 with: images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} tags: ${{ inputs.docker_tags}} diff --git a/.github/workflows/build-element-call.yaml b/.github/workflows/build-element-call.yaml index 214c78d67..01553fecd 100644 --- a/.github/workflows/build-element-call.yaml +++ b/.github/workflows/build-element-call.yaml @@ -32,7 +32,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout code - uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4 + uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 - name: Enable Corepack run: corepack enable - name: Yarn cache diff --git a/.github/workflows/lint.yaml b/.github/workflows/lint.yaml index e02712312..32dde8690 100644 --- a/.github/workflows/lint.yaml +++ b/.github/workflows/lint.yaml @@ -7,7 +7,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout code - uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4 + uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 - name: Enable Corepack run: corepack enable - name: Yarn cache diff --git a/.github/workflows/publish-embedded-packages.yaml b/.github/workflows/publish-embedded-packages.yaml index 546191abe..275397b52 100644 --- a/.github/workflows/publish-embedded-packages.yaml +++ b/.github/workflows/publish-embedded-packages.yaml @@ -85,7 +85,7 @@ jobs: run: find ${{ env.FILENAME_PREFIX }} -type f -print0 | sort -z | xargs -0 sha256sum | tee ${{ env.FILENAME_PREFIX }}.sha256 - name: Upload if: ${{ needs.versioning.outputs.DRY_RUN == 'false' }} - uses: softprops/action-gh-release@6da8fa9354ddfdc4aeace5fc48d7f679b5214090 # v2 + uses: softprops/action-gh-release@a06a81a03ee405af7f2048a818ed3f03bbf83c7b # v2 with: files: | ${{ env.FILENAME_PREFIX }}.tar.gz @@ -103,7 +103,7 @@ jobs: id-token: write # Allow npm to authenticate as a trusted publisher steps: - name: Checkout - uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4 + uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 - name: 📥 Download built element-call artifact uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4 @@ -142,7 +142,7 @@ jobs: contents: read steps: - name: Checkout - uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4 + uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 - name: 📥 Download built element-call artifact uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4 @@ -197,7 +197,7 @@ jobs: contents: read steps: - name: Checkout - uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4 + uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 with: path: element-call @@ -210,7 +210,7 @@ jobs: path: element-call/embedded/ios/Sources/dist - name: Checkout element-call-swift - uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4 + uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 with: repository: element-hq/element-call-swift path: element-call-swift @@ -262,7 +262,7 @@ jobs: echo "iOS: ${{ needs.publish_ios.outputs.ARTIFACT_VERSION }}" - name: Add release notes if: ${{ needs.versioning.outputs.DRY_RUN == 'false' }} - uses: softprops/action-gh-release@6da8fa9354ddfdc4aeace5fc48d7f679b5214090 # v2 + uses: softprops/action-gh-release@a06a81a03ee405af7f2048a818ed3f03bbf83c7b # v2 with: append_body: true body: | diff --git a/.github/workflows/publish.yaml b/.github/workflows/publish.yaml index 348356356..6a5c090e4 100644 --- a/.github/workflows/publish.yaml +++ b/.github/workflows/publish.yaml @@ -42,7 +42,7 @@ jobs: - name: Create Checksum run: find ${{ env.FILENAME_PREFIX }} -type f -print0 | sort -z | xargs -0 sha256sum | tee ${{ env.FILENAME_PREFIX }}.sha256 - name: Upload - uses: softprops/action-gh-release@6da8fa9354ddfdc4aeace5fc48d7f679b5214090 # v2 + uses: softprops/action-gh-release@a06a81a03ee405af7f2048a818ed3f03bbf83c7b # v2 with: files: | ${{ env.FILENAME_PREFIX }}.tar.gz @@ -68,7 +68,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Add release note - uses: softprops/action-gh-release@6da8fa9354ddfdc4aeace5fc48d7f679b5214090 # v2 + uses: softprops/action-gh-release@a06a81a03ee405af7f2048a818ed3f03bbf83c7b # v2 with: append_body: true body: | diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml index 54035ea40..3251f50e7 100644 --- a/.github/workflows/test.yaml +++ b/.github/workflows/test.yaml @@ -9,7 +9,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout code - uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4 + uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 - name: Enable Corepack run: corepack enable - name: Yarn cache @@ -33,7 +33,7 @@ jobs: timeout-minutes: 60 runs-on: ubuntu-latest steps: - - uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4 + - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 - name: Enable Corepack run: corepack enable - uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4 diff --git a/.github/workflows/translations-download.yaml b/.github/workflows/translations-download.yaml index 39e68ec30..76fe418c8 100644 --- a/.github/workflows/translations-download.yaml +++ b/.github/workflows/translations-download.yaml @@ -13,7 +13,7 @@ jobs: steps: - name: Checkout the code - uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4 + uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 - name: Enable Corepack run: corepack enable @@ -42,7 +42,7 @@ jobs: - name: Create Pull Request id: cpr - uses: peter-evans/create-pull-request@271a8d0340265f705b14b6d32b9829c1cb33d45e # v7.0.8 + uses: peter-evans/create-pull-request@84ae59a2cdc2258d6fa0732dd66352dddae2a412 # v7.0.9 with: token: ${{ secrets.ELEMENT_BOT_TOKEN }} branch: actions/localazy-download diff --git a/.github/workflows/translations-upload.yaml b/.github/workflows/translations-upload.yaml index e7c3ee3de..4c0625131 100644 --- a/.github/workflows/translations-upload.yaml +++ b/.github/workflows/translations-upload.yaml @@ -14,7 +14,7 @@ jobs: steps: - name: Checkout the code - uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4 + uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 - name: Upload uses: localazy/upload@27e6b5c0fddf4551596b42226b1c24124335d24a # v1 From 28158bfc232a18e490683791b86d223c507b1f56 Mon Sep 17 00:00:00 2001 From: Timo K Date: Mon, 24 Nov 2025 09:44:21 +0100 Subject: [PATCH 017/748] temp --- godot/README.md | 0 godot/main.ts | 76 ++++++++++++++++++++++++ index.html | 12 ++++ package.json | 3 + src/ClientContext.tsx | 2 +- src/state/CallViewModel/CallViewModel.ts | 3 + tsconfig.json | 7 ++- vite-godot.config.js | 32 ++++++++++ vite.config.ts | 42 ++++++++----- yarn.lock | 13 ++++ 10 files changed, 172 insertions(+), 18 deletions(-) create mode 100644 godot/README.md create mode 100644 godot/main.ts create mode 100644 vite-godot.config.js diff --git a/godot/README.md b/godot/README.md new file mode 100644 index 000000000..e69de29bb diff --git a/godot/main.ts b/godot/main.ts new file mode 100644 index 000000000..8ba85b532 --- /dev/null +++ b/godot/main.ts @@ -0,0 +1,76 @@ +/* +Copyright 2025 New Vector Ltd. + +SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial +Please see LICENSE in the repository root for full details. +*/ +import { of } from "rxjs"; + +import { loadClient } from "../src/ClientContext.tsx"; +import { createCallViewModel$ } from "../src/state/CallViewModel/CallViewModel.ts"; +import { MuteStates } from "../src/state/MuteStates.ts"; +import { ObservableScope } from "../src/state/ObservableScope.ts"; +import { getUrlParams } from "../src/UrlParams.ts"; +import { MediaDevices } from "../src/state/MediaDevices"; +import { constant } from "../src/state/Behavior.ts"; +import { E2eeType } from "../src/e2ee/e2eeType.ts"; + +console.log("test Godot EC export"); + +export async function start(): Promise { + const initResults = await loadClient(); + if (initResults === null) { + console.error("could not init client"); + return; + } + const { client } = initResults; + const scope = new ObservableScope(); + const { roomId } = getUrlParams(); + if (roomId === null) { + console.error("could not get roomId from url params"); + return; + } + const room = client.getRoom(roomId); + if (room === null) { + console.error("could not get room from client"); + return; + } + const mediaDevices = new MediaDevices(scope); + const muteStates = new MuteStates(scope, mediaDevices, constant(true)); + const callViewModel = createCallViewModel$( + scope, + client.matrixRTC.getRoomSession(room), + room, + mediaDevices, + muteStates, + { encryptionSystem: { kind: E2eeType.PER_PARTICIPANT } }, + of({}), + of({}), + constant({ supported: false, processor: undefined }), + ); + callViewModel.join(); + // callViewModel.audioParticipants$.pipe( + // switchMap((lkRooms) => { + // for (const item of lkRooms) { + // item.livekitRoom.registerTextStreamHandler; + // } + // }), + // ); +} +// Example default godot export + +// +// +// +// My Template +// +// +// +// +// +// +// +// diff --git a/index.html b/index.html index f17c73c0b..2043b2aab 100644 --- a/index.html +++ b/index.html @@ -40,6 +40,18 @@ + <% if (packageType !== "full") { %>
+ <% } %> + + + <% if (packageType === "godot") { %> + + + + <% } %> diff --git a/package.json b/package.json index 62ea9f4fb..31ae40d33 100644 --- a/package.json +++ b/package.json @@ -13,6 +13,8 @@ "build:embedded": "yarn build:full --config vite-embedded.config.js", "build:embedded:production": "yarn build:embedded", "build:embedded:development": "yarn build:embedded --mode development", + "build:godot": "yarn build:full --config vite-godot.config.js", + "build:godot:development": "yarn build:godot --mode development", "serve": "vite preview", "prettier:check": "prettier -c .", "prettier:format": "prettier -w .", @@ -133,6 +135,7 @@ "vite": "^7.0.0", "vite-plugin-generate-file": "^0.3.0", "vite-plugin-html": "^3.2.2", + "vite-plugin-singlefile": "^2.3.0", "vite-plugin-svgr": "^4.0.0", "vitest": "^3.0.0", "vitest-axe": "^1.0.0-pre.3" diff --git a/src/ClientContext.tsx b/src/ClientContext.tsx index 1488965ac..518aa38eb 100644 --- a/src/ClientContext.tsx +++ b/src/ClientContext.tsx @@ -358,7 +358,7 @@ export type InitResult = { passwordlessUser: boolean; }; -async function loadClient(): Promise { +export async function loadClient(): Promise { if (widget) { // We're inside a widget, so let's engage *matryoshka mode* logger.log("Using a matryoshka client"); diff --git a/src/state/CallViewModel/CallViewModel.ts b/src/state/CallViewModel/CallViewModel.ts index 506eca1b8..4d214714d 100644 --- a/src/state/CallViewModel/CallViewModel.ts +++ b/src/state/CallViewModel/CallViewModel.ts @@ -251,6 +251,8 @@ export interface CallViewModel { participantCount$: Behavior; /** Participants sorted by livekit room so they can be used in the audio rendering */ audioParticipants$: Behavior; + /** use the layout instead, this is just for the godot export. */ + userMedia$: Behavior; /** List of participants raising their hand */ handsRaised$: Behavior>; /** List of reactions. Keys are: membership.membershipId (currently predefined as: `${membershipEvent.userId}:${membershipEvent.deviceId}`)*/ @@ -1495,6 +1497,7 @@ export function createCallViewModel$( spotlight$: spotlight$, pip$: pip$, layout$: layout$, + userMedia$, tileStoreGeneration$: tileStoreGeneration$, showSpotlightIndicators$: showSpotlightIndicators$, showSpeakingIndicators$: showSpeakingIndicators$, diff --git a/tsconfig.json b/tsconfig.json index e864ecfc9..7c13dfc76 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -50,6 +50,11 @@ "plugins": [{ "name": "typescript-eslint-language-service" }] }, - "include": ["./src/**/*.ts", "./src/**/*.tsx", "./playwright/**/*.ts"], + "include": [ + "./src/**/*.ts", + "./src/**/*.tsx", + "./playwright/**/*.ts", + "./godot/**/*.ts" + ], "exclude": ["**.test.ts"] } diff --git a/vite-godot.config.js b/vite-godot.config.js new file mode 100644 index 000000000..f17a8d3f3 --- /dev/null +++ b/vite-godot.config.js @@ -0,0 +1,32 @@ +/* +Copyright 2025 New Vector Ltd. + +SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial +Please see LICENSE in the repository root for full details. +*/ + +import { defineConfig, mergeConfig } from "vite"; +import { viteSingleFile } from "vite-plugin-singlefile"; +import fullConfig from "./vite.config"; + +const base = "./"; + +// Config for embedded deployments (possibly hosted under a non-root path) +export default defineConfig((env) => + mergeConfig( + fullConfig({ ...env, packageType: "godot" }), + defineConfig({ + base, // Use relative URLs to allow the app to be hosted under any path + // publicDir: false, // Don't serve the public directory which only contains the favicon + build: { + manifest: true, + lib: { + entry: "./godot/main.ts", + name: "matrixrtc-ec-godot", + // the proper extensions will be added + fileName: "matrixrtc-ec-godot", + }, + }, + }), + ), +); diff --git a/vite.config.ts b/vite.config.ts index a0bb9de55..970cb5926 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -7,14 +7,17 @@ Please see LICENSE in the repository root for full details. import { loadEnv, + PluginOption, searchForWorkspaceRoot, type ConfigEnv, type UserConfig, } from "vite"; import svgrPlugin from "vite-plugin-svgr"; import { createHtmlPlugin } from "vite-plugin-html"; + import { codecovVitePlugin } from "@codecov/vite-plugin"; import { sentryVitePlugin } from "@sentry/vite-plugin"; + import react from "@vitejs/plugin-react"; import { realpathSync } from "fs"; import * as fs from "node:fs"; @@ -24,14 +27,14 @@ import * as fs from "node:fs"; export default ({ mode, packageType, -}: ConfigEnv & { packageType?: "full" | "embedded" }): UserConfig => { +}: ConfigEnv & { packageType?: "full" | "embedded" | "godot" }): UserConfig => { const env = loadEnv(mode, process.cwd()); // Environment variables with the VITE_ prefix are accessible at runtime. // So, we set this to allow for build/package specific behavior. // In future we might be able to do what is needed via code splitting at // build time. process.env.VITE_PACKAGE = packageType ?? "full"; - const plugins = [ + const plugins: PluginOption[] = [ react(), svgrPlugin({ svgrOptions: { @@ -41,16 +44,6 @@ export default ({ }, }), - createHtmlPlugin({ - entry: "src/main.tsx", - inject: { - data: { - brand: env.VITE_PRODUCT_NAME || "Element Call", - packageType: process.env.VITE_PACKAGE, - }, - }, - }), - codecovVitePlugin({ enableBundleAnalysis: process.env.CODECOV_TOKEN !== undefined, bundleName: "element-call", @@ -73,6 +66,18 @@ export default ({ ); } + plugins.push( + createHtmlPlugin({ + entry: packageType === "godot" ? "godot/main.ts" : "src/main.tsx", + inject: { + data: { + brand: env.VITE_PRODUCT_NAME || "Element Call", + packageType: process.env.VITE_PACKAGE, + }, + }, + }), + ); + // The crypto WASM module is imported dynamically. Since it's common // for developers to use a linked copy of matrix-js-sdk or Rust // crypto (which could reside anywhere on their file system), Vite @@ -120,10 +125,15 @@ export default ({ // Default naming fallback return "assets/[name]-[hash][extname]"; }, - manualChunks: { - // we should be able to remove this one https://github.com/matrix-org/matrix-rust-sdk-crypto-wasm/pull/167 lands - "matrix-sdk-crypto-wasm": ["@matrix-org/matrix-sdk-crypto-wasm"], - }, + manualChunks: + packageType !== "godot" + ? { + // we should be able to remove this one https://github.com/matrix-org/matrix-rust-sdk-crypto-wasm/pull/167 lands + "matrix-sdk-crypto-wasm": [ + "@matrix-org/matrix-sdk-crypto-wasm", + ], + } + : undefined, }, }, }, diff --git a/yarn.lock b/yarn.lock index 97ca19859..61af02ac6 100644 --- a/yarn.lock +++ b/yarn.lock @@ -7571,6 +7571,7 @@ __metadata: vite: "npm:^7.0.0" vite-plugin-generate-file: "npm:^0.3.0" vite-plugin-html: "npm:^3.2.2" + vite-plugin-singlefile: "npm:^2.3.0" vite-plugin-svgr: "npm:^4.0.0" vitest: "npm:^3.0.0" vitest-axe: "npm:^1.0.0-pre.3" @@ -13966,6 +13967,18 @@ __metadata: languageName: node linkType: hard +"vite-plugin-singlefile@npm:^2.3.0": + version: 2.3.0 + resolution: "vite-plugin-singlefile@npm:2.3.0" + dependencies: + micromatch: "npm:^4.0.8" + peerDependencies: + rollup: ^4.44.1 + vite: ^5.4.11 || ^6.0.0 || ^7.0.0 + checksum: 10c0/d6ebb545d749b228bbd8fd8746a954f09d000dd69d200a651358e74136947b932f7f869536e1698e0d81e2f0694357c8bec3a957101a7e77d0d3c40193eb4cf1 + languageName: node + linkType: hard + "vite-plugin-svgr@npm:^4.0.0": version: 4.3.0 resolution: "vite-plugin-svgr@npm:4.3.0" From 2d8ffc0ccda249aafa57a4c361714ff6fd4a79f6 Mon Sep 17 00:00:00 2001 From: Timo K Date: Sun, 30 Nov 2025 20:31:21 +0100 Subject: [PATCH 018/748] almost mvp --- godot/README.md | 14 + godot/favicon.ico | Bin 0 -> 2439 bytes godot/helper.ts | 51 ++ godot/index.html | 45 ++ godot/main.ts | 236 +++++-- package.json | 2 + src/room/InCallView.tsx | 2 +- src/state/CallViewModel/CallViewModel.ts | 27 +- src/widget.ts | 19 +- vite-godot.config.js | 3 +- yarn.lock | 845 ++++++++++++++++++++++- 11 files changed, 1144 insertions(+), 100 deletions(-) create mode 100644 godot/favicon.ico create mode 100644 godot/helper.ts create mode 100644 godot/index.html diff --git a/godot/README.md b/godot/README.md index e69de29bb..7f00df247 100644 --- a/godot/README.md +++ b/godot/README.md @@ -0,0 +1,14 @@ +## url parameters +widgetId = $matrix_widget_id +perParticipantE2EE = true +userId = $matrix_user_id +deviceId = $org.matrix.msc3819.matrix_device_id +baseUrl = $org.matrix.msc4039.matrix_base_url + +parentUrl = // will be inserted automatically + +http://localhost?widgetId=&perParticipantE2EE=true&userId=&deviceId=&baseUrl=&roomId= + +-> + +http://localhost:3000?widgetId=$matrix_widget_id&perParticipantE2EE=true&userId=$matrix_user_id&deviceId=$org.matrix.msc3819.matrix_device_id&baseUrl=$org.matrix.msc4039.matrix_base_url&roomId=$matrix_room_id diff --git a/godot/favicon.ico b/godot/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..e531e6f274fb3efb29316f441b7057f745758ee3 GIT binary patch literal 2439 zcmV;233&F2P)Z$GcPbOEG;=TH6tA!@bK^{BqcdBG?S8&>FMb?FE2SUFU3Q#V=xG9ka78TU#cFhb(k-UtL`c-rg}yO*KbGH9$WU z($gQMqzLQkBcGooii#Y(yDNHmDr#vv5D=G@mOK|3q{gO@000PrNklX?LPZ z5I|*V5jQ}Eh+9n5?29HbW|_SF|9|y@CI*$Is@oY-r0>_snIrdf7u8h-6bcfFL?V$$ zBoc{4B9TZW63LosXV9%o`c`j=)t^+lgH9>yU-k2-4l2{3X*echy7r0AnCTeiu>aqn zn)UDdF;vHsq3bYBiKeVG#~qFaa)}ihN7jd^a*U`o8gtBP_g62lQr9xfxD~Z4%yg#X zgRFmZMsy}7+|&x)(MOG}e|H89EQ8@ptzd5dFzes`j~Vm~U&J#WD;j7ip)ws)#SuEPxk)5_WD zx}gguS2ep9`)_QRt1#cemKV11E@yw@ZRtvm(s^-L*Q)yB$NzhdY&C>k-Kna2<0brs zrsQNNR%6TSKx+3NuGIT_(%P zL9_i@6guW?xKgiDQ_?SVE9>j#;Yg^A+5J-{WHnwCUd6D zGIAggv0A6wuGEBPMFbkLr6q7HjBur*7S>19qIE;$R;Ad_yRK#}-2b7G%C#=I!@Ga8 z>ngDe7Kuw~a;wkVfA(J^T&d6Slyn6nRADaho(h|{QLfZGSji!5D{BRCx}4#?`6tqq z`iB0W+>5LofU)?F(B5UVtJE&oE{x0^Qk8EP1_KR|q<6t~F|(EcWz4k;mjexv0J>m1 zxK!%PXFT`9TC6Ko<7g3)xgYW*S+$3gI9CgNe5X^W>2SzOa0TpwZPTVPgT#?Id=7s^ z1MGrr;m}APCg|!+U0cMvQZLadX#o2#YY!msuDm2yDn82!(56{?fKbBDf|R{klB?M} zmn_B2S_A}ad@nZ>T_L()o3ts6)F4yRvY+fqeSP=1f)g?*~-m{w? zHZwKHS(^ZW%HPX&nyV!z^T*d?-*46s9WfHO!ycyOu-T+fW^w*>S@ZpmO$ky)qVRwT zSzAqdh_RQ`>!$4k@>CLqctqxaceUapj6t&ctWBhI0G74Wq{jd_136i%NT&*x^}gMt z#{ekHw}1WvDh+6vRLIpeU>g#sJ3wWP4|CICRnSzgm_-aWsdjXfcz+DIIvfhC$^-Sd6#^65OWS+U6@ zW&)5zi3ZaNE7m;QKfZmOC$tU2t}suTktqJ5hq}wbro2xNV^=6wG|I|+GcKmzfIl}U7h3hphBd{THu?JtjEu1eK1G6()(F^0D&J2 z3GkB6i*p-2&qm^A$UCc?bOxH?T~Qf1;*0RD_{?GEbIeH+sK76Acx2h}u9_UP4rE>) z!ZUzdiA@6_qE#*5E4f{?5E4xJe&@L!tT}2KPoNd%GWYBjAeK+f@p z1-MdUhf5BqfredZCGX!rUj<)(2)Vivb7fLG6^4PP58*D@73XuSpOB31D}XPe4wW2U z-i2PrOsAS00c<0NUSuw|uIO&U0N9sNynVUSsr0|1=|Cn-zus;%=XsAx7?Z-_Oak3> zTi)rHE3tT`v}sjlBABG!675wNZ1!Fh4DLDjETokZpu1a16?9z$i>|r&HAvZ;8u?Qx;9Zc$Je6s}%~3#Lv(*AGrq_a_B0>mObYlXb8Fb z`A>j>NwVd=&N&Af*5vG?tW_mG%6q=x9%Q}T?7z1$}D4F)I!SMbZ*yD*LB2b=&@dqN*B+QseXEVOS>X$yY(H;iuNbPImb8SZUy zxfb#A6@VjWFG&PrIbT*Qs%PSRQ8z}pO4<`Rv)H}sXUudBy?53 { + logger.info("try making sticky MatrixRTCSdk"); + void widget.api + .setAlwaysOnScreen(true) + .then(() => { + logger.info("sticky MatrixRTCSdk"); + }) + .catch((error) => { + logger.error("failed to make sticky MatrixRTCSdk", error); + }); +}; +export const TEXT_LK_TOPIC = "matrixRTC"; +/** + * simple helper operator to combine the last emitted and the current emitted value of a rxjs observable + * + * I think there should be a builtin for this but i did not find it... + */ +export const currentAndPrev = scan< + LivekitRoomItem[], + { + prev: LivekitRoomItem[]; + current: LivekitRoomItem[]; + } +>( + ({ current: lastCurrentVal }, items) => ({ + prev: lastCurrentVal, + current: items, + }), + { + prev: [], + current: [], + }, +); diff --git a/godot/index.html b/godot/index.html new file mode 100644 index 000000000..ff654748d --- /dev/null +++ b/godot/index.html @@ -0,0 +1,45 @@ + + + + Godot MatrixRTC Widget + + + + + + + +
+ + + diff --git a/godot/main.ts b/godot/main.ts index 8ba85b532..98bb49722 100644 --- a/godot/main.ts +++ b/godot/main.ts @@ -4,42 +4,57 @@ Copyright 2025 New Vector Ltd. SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial Please see LICENSE in the repository root for full details. */ -import { of } from "rxjs"; -import { loadClient } from "../src/ClientContext.tsx"; -import { createCallViewModel$ } from "../src/state/CallViewModel/CallViewModel.ts"; -import { MuteStates } from "../src/state/MuteStates.ts"; -import { ObservableScope } from "../src/state/ObservableScope.ts"; -import { getUrlParams } from "../src/UrlParams.ts"; +// import { type InitResult } from "../src/ClientContext"; +import { map, type Observable, of, Subject, switchMap } from "rxjs"; +import { MatrixRTCSessionEvent } from "matrix-js-sdk/lib/matrixrtc"; +import { type TextStreamInfo } from "livekit-client/dist/src/room/types"; +import { + type Room as LivekitRoom, + type TextStreamReader, +} from "livekit-client"; + +import { type Behavior, constant } from "../src/state/Behavior"; +import { createCallViewModel$ } from "../src/state/CallViewModel/CallViewModel"; +import { ObservableScope } from "../src/state/ObservableScope"; +import { getUrlParams } from "../src/UrlParams"; +import { MuteStates } from "../src/state/MuteStates"; import { MediaDevices } from "../src/state/MediaDevices"; -import { constant } from "../src/state/Behavior.ts"; -import { E2eeType } from "../src/e2ee/e2eeType.ts"; +import { E2eeType } from "../src/e2ee/e2eeType"; +import { type LocalMemberConnectionState } from "../src/state/CallViewModel/localMember/LocalMembership"; +import { + currentAndPrev, + logger, + TEXT_LK_TOPIC, + tryMakeSticky, + widget, +} from "./helper"; +import { ElementWidgetActions } from "../src/widget"; -console.log("test Godot EC export"); - -export async function start(): Promise { - const initResults = await loadClient(); - if (initResults === null) { - console.error("could not init client"); - return; - } - const { client } = initResults; +interface MatrixRTCSdk { + join: () => LocalMemberConnectionState; + /** @throws on leave errors */ + leave: () => void; + data$: Observable<{ sender: string; data: string }>; + sendData?: (data: Record) => Promise; +} +export async function createMatrixRTCSdk(): Promise { + logger.info("Hello"); + const client = await widget.client; + logger.info("client created"); const scope = new ObservableScope(); const { roomId } = getUrlParams(); - if (roomId === null) { - console.error("could not get roomId from url params"); - return; - } + if (roomId === null) throw Error("could not get roomId from url params"); + const room = client.getRoom(roomId); - if (room === null) { - console.error("could not get room from client"); - return; - } + if (room === null) throw Error("could not get room from client"); + const mediaDevices = new MediaDevices(scope); const muteStates = new MuteStates(scope, mediaDevices, constant(true)); + const rtcSession = client.matrixRTC.getRoomSession(room); const callViewModel = createCallViewModel$( scope, - client.matrixRTC.getRoomSession(room), + rtcSession, room, mediaDevices, muteStates, @@ -48,29 +63,148 @@ export async function start(): Promise { of({}), constant({ supported: false, processor: undefined }), ); - callViewModel.join(); - // callViewModel.audioParticipants$.pipe( - // switchMap((lkRooms) => { - // for (const item of lkRooms) { - // item.livekitRoom.registerTextStreamHandler; - // } - // }), - // ); -} -// Example default godot export + logger.info("CallViewModelCreated"); + // create data listener + const data$ = new Subject<{ sender: string; data: string }>(); -// -// -// -// My Template -// -// -// -// -// -// -// -// + // const lkTextStreamHandlerFunction = async ( + // reader: TextStreamReader, + // participantInfo: { identity: string }, + // livekitRoom: LivekitRoom, + // ): Promise => { + // const info = reader.info; + // console.log( + // `Received text stream from ${participantInfo.identity}\n` + + // ` Topic: ${info.topic}\n` + + // ` Timestamp: ${info.timestamp}\n` + + // ` ID: ${info.id}\n` + + // ` Size: ${info.size}`, // Optional, only available if the stream was sent with `sendText` + // ); + + // const participants = callViewModel.livekitRoomItems$.value.find( + // (i) => i.livekitRoom === livekitRoom, + // )?.participants; + // if (participants && participants.includes(participantInfo.identity)) { + // const text = await reader.readAll(); + // console.log(`Received text: ${text}`); + // data$.next({ sender: participantInfo.identity, data: text }); + // } else { + // logger.warn( + // "Received text from unknown participant", + // participantInfo.identity, + // ); + // } + // }; + + // const livekitRoomItemsSub = callViewModel.livekitRoomItems$ + // .pipe(currentAndPrev) + // .subscribe({ + // next: ({ prev, current }) => { + // const prevRooms = prev.map((i) => i.livekitRoom); + // const currentRooms = current.map((i) => i.livekitRoom); + // const addedRooms = currentRooms.filter((r) => !prevRooms.includes(r)); + // const removedRooms = prevRooms.filter((r) => !currentRooms.includes(r)); + // addedRooms.forEach((r) => + // r.registerTextStreamHandler( + // TEXT_LK_TOPIC, + // (reader, participantInfo) => + // void lkTextStreamHandlerFunction(reader, participantInfo, r), + // ), + // ); + // removedRooms.forEach((r) => + // r.unregisterTextStreamHandler(TEXT_LK_TOPIC), + // ); + // }, + // complete: () => { + // logger.info("Livekit room items subscription completed"); + // for (const item of callViewModel.livekitRoomItems$.value) { + // logger.info("unregistering room item from room", item.url); + // item.livekitRoom.unregisterTextStreamHandler(TEXT_LK_TOPIC); + // } + // }, + // }); + + // create sendData function + // const sendFn: Behavior<(data: string) => Promise> = + // scope.behavior( + // callViewModel.localMatrixLivekitMember$.pipe( + // switchMap((m) => { + // if (!m) + // return of((data: string): never => { + // throw Error("local membership not yet ready."); + // }); + // return m.participant$.pipe( + // map((p) => { + // if (p === null) { + // return (data: string): never => { + // throw Error("local participant not yet ready to send data."); + // }; + // } else { + // return async (data: string): Promise => + // p.sendText(data, { topic: TEXT_LK_TOPIC }); + // } + // }), + // ); + // }), + // ), + // ); + + // const sendData = async (data: Record): Promise => { + // const dataString = JSON.stringify(data); + // try { + // const info = await sendFn.value(dataString); + // logger.info(`Sent text with stream ID: ${info.id}`); + // } catch (e) { + // console.error("failed sending: ", dataString, e); + // } + // }; + + // after hangup gets called + const leaveSubs = callViewModel.leave$.subscribe(() => { + const scheduleWidgetCloseOnLeave = async (): Promise => { + const leaveResolver = Promise.withResolvers(); + logger.info("waiting for RTC leave"); + rtcSession.on(MatrixRTCSessionEvent.JoinStateChanged, (isJoined) => { + logger.info("received RTC join update: ", isJoined); + if (!isJoined) leaveResolver.resolve(); + }); + await leaveResolver.promise; + logger.info("send Unstick"); + await widget.api + .setAlwaysOnScreen(false) + .catch((e) => + logger.error( + "Failed to set call widget `alwaysOnScreen` to false", + e, + ), + ); + logger.info("send Close"); + await widget.api.transport + .send(ElementWidgetActions.Close, {}) + .catch((e) => logger.error("Failed to send close action", e)); + }; + + // schedule close first and then leave (scope.end) + void scheduleWidgetCloseOnLeave(); + + // actual hangup (ending scope will send the leave event.. its kinda odd. since you might end up closing the widget too fast) + scope.end(); + }); + + logger.info("createMatrixRTCSdk done"); + + return { + join: (): LocalMemberConnectionState => { + // first lets try making the widget sticky + tryMakeSticky(); + return callViewModel.join(); + }, + leave: (): void => { + callViewModel.hangup(); + leaveSubs.unsubscribe(); + // livekitRoomItemsSub.unsubscribe(); + }, + data$, + // sendData, + }; +} diff --git a/package.json b/package.json index 31ae40d33..c87d5b01c 100644 --- a/package.json +++ b/package.json @@ -113,6 +113,7 @@ "loglevel": "^1.9.1", "matrix-js-sdk": "github:matrix-org/matrix-js-sdk#head=toger5/sticky-events&commit=e7f5bec51b6f70501a025b79fe5021c933385b21", "matrix-widget-api": "^1.13.0", + "node-stdlib-browser": "^1.3.1", "normalize.css": "^8.0.1", "observable-hooks": "^4.2.3", "pako": "^2.0.4", @@ -135,6 +136,7 @@ "vite": "^7.0.0", "vite-plugin-generate-file": "^0.3.0", "vite-plugin-html": "^3.2.2", + "vite-plugin-node-stdlib-browser": "^0.2.1", "vite-plugin-singlefile": "^2.3.0", "vite-plugin-svgr": "^4.0.0", "vitest": "^3.0.0", diff --git a/src/room/InCallView.tsx b/src/room/InCallView.tsx index b17d3aaee..bed9afae0 100644 --- a/src/room/InCallView.tsx +++ b/src/room/InCallView.tsx @@ -251,7 +251,7 @@ export const InCallView: FC = ({ () => void toggleRaisedHand(), ); - const audioParticipants = useBehavior(vm.audioParticipants$); + const audioParticipants = useBehavior(vm.livekitRoomItems$); const participantCount = useBehavior(vm.participantCount$); const reconnecting = useBehavior(vm.reconnecting$); const windowMode = useBehavior(vm.windowMode$); diff --git a/src/state/CallViewModel/CallViewModel.ts b/src/state/CallViewModel/CallViewModel.ts index 4d214714d..253eb05ed 100644 --- a/src/state/CallViewModel/CallViewModel.ts +++ b/src/state/CallViewModel/CallViewModel.ts @@ -12,6 +12,7 @@ import { ExternalE2EEKeyProvider, type Room as LivekitRoom, type RoomOptions, + type LocalParticipant as LocalLivekitParticipant, } from "livekit-client"; import { type Room as MatrixRoom } from "matrix-js-sdk"; import { @@ -174,12 +175,19 @@ interface LayoutScanState { } type MediaItem = UserMedia | ScreenShare; -type AudioLivekitItem = { +export type LivekitRoomItem = { livekitRoom: LivekitRoom; participants: string[]; url: string; }; +export type LocalMatrixLivekitMember = Pick< + MatrixLivekitMember, + "userId" | "membership$" | "connection$" +> & { + participant$: Behavior; +}; + /** * The return of createCallViewModel$ * this interface represents the root source of data for the call view. @@ -197,8 +205,11 @@ export interface CallViewModel { callPickupState$: Behavior< "unknown" | "ringing" | "timeout" | "decline" | "success" | null >; + /** Observable that emits when the user should leave the call (hangup pressed, widget action, error). + * THIS DOES NOT LEAVE THE CALL YET. The only way to leave the call (send the hangup event) is by ending the scope. + */ leave$: Observable<"user" | AutoLeaveReason>; - /** Call to initiate hangup. Use in conbination with connectino state track the async hangup process. */ + /** Call to initiate hangup. Use in conbination with reconnectino state track the async hangup process. */ hangup: () => void; // joining @@ -250,9 +261,10 @@ export interface CallViewModel { */ participantCount$: Behavior; /** Participants sorted by livekit room so they can be used in the audio rendering */ - audioParticipants$: Behavior; + livekitRoomItems$: Behavior; /** use the layout instead, this is just for the godot export. */ userMedia$: Behavior; + localMatrixLivekitMember$: Behavior; /** List of participants raising their hand */ handsRaised$: Behavior>; /** List of reactions. Keys are: membership.membershipId (currently predefined as: `${membershipEvent.userId}:${membershipEvent.deviceId}`)*/ @@ -503,14 +515,14 @@ export function createCallViewModel$( userId: userId, }; - const localMatrixLivekitMember$: Behavior = + const localMatrixLivekitMember$: Behavior = scope.behavior( localRtcMembership$.pipe( switchMap((membership) => { if (!membership) return of(null); return of( // casting is save here since we know that localRtcMembership$ is !== null since we reached this case. - localMatrixLivekitMemberUninitialized as MatrixLivekitMember, + localMatrixLivekitMemberUninitialized as LocalMatrixLivekitMember, ); }), ), @@ -621,7 +633,7 @@ export function createCallViewModel$( return a$; }), map((members) => - members.reduce((acc, curr) => { + members.reduce((acc, curr) => { if (!curr) return acc; const existing = acc.find((item) => item.url === curr.url); @@ -1477,7 +1489,7 @@ export function createCallViewModel$( ), participantCount$: participantCount$, - audioParticipants$: audioParticipants$, + livekitRoomItems$: audioParticipants$, handsRaised$: handsRaised$, reactions$: reactions$, @@ -1498,6 +1510,7 @@ export function createCallViewModel$( pip$: pip$, layout$: layout$, userMedia$, + localMatrixLivekitMember$, tileStoreGeneration$: tileStoreGeneration$, showSpotlightIndicators$: showSpotlightIndicators$, showSpeakingIndicators$: showSpeakingIndicators$, diff --git a/src/widget.ts b/src/widget.ts index 60163c7cd..7862df33c 100644 --- a/src/widget.ts +++ b/src/widget.ts @@ -64,6 +64,12 @@ export const widget = ((): WidgetHelpers | null => { try { const { widgetId, parentUrl } = getUrlParams(); + const { roomId, userId, deviceId, baseUrl, e2eEnabled, allowIceFallback } = + getUrlParams(); + if (!roomId) throw new Error("Room ID must be supplied"); + if (!userId) throw new Error("User ID must be supplied"); + if (!deviceId) throw new Error("Device ID must be supplied"); + if (!baseUrl) throw new Error("Base URL must be supplied"); if (widgetId && parentUrl) { const parentOrigin = new URL(parentUrl).origin; logger.info("Widget API is available"); @@ -92,19 +98,6 @@ export const widget = ((): WidgetHelpers | null => { // We need to do this now rather than later because it has capabilities to // request, and is responsible for starting the transport (should it be?) - const { - roomId, - userId, - deviceId, - baseUrl, - e2eEnabled, - allowIceFallback, - } = getUrlParams(); - if (!roomId) throw new Error("Room ID must be supplied"); - if (!userId) throw new Error("User ID must be supplied"); - if (!deviceId) throw new Error("Device ID must be supplied"); - if (!baseUrl) throw new Error("Base URL must be supplied"); - // These are all the event types the app uses const sendEvent = [ EventType.CallNotify, // Sent as a deprecated fallback diff --git a/vite-godot.config.js b/vite-godot.config.js index f17a8d3f3..5fdba09eb 100644 --- a/vite-godot.config.js +++ b/vite-godot.config.js @@ -6,8 +6,8 @@ Please see LICENSE in the repository root for full details. */ import { defineConfig, mergeConfig } from "vite"; -import { viteSingleFile } from "vite-plugin-singlefile"; import fullConfig from "./vite.config"; +import nodePolyfills from "vite-plugin-node-stdlib-browser"; const base = "./"; @@ -27,6 +27,7 @@ export default defineConfig((env) => fileName: "matrixrtc-ec-godot", }, }, + plugins: [nodePolyfills()], }), ), ); diff --git a/yarn.lock b/yarn.lock index 61af02ac6..5ec8f55b1 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2711,6 +2711,13 @@ __metadata: languageName: node linkType: hard +"@jridgewell/sourcemap-codec@npm:^1.5.5": + version: 1.5.5 + resolution: "@jridgewell/sourcemap-codec@npm:1.5.5" + checksum: 10c0/f9e538f302b63c0ebc06eecb1dd9918dd4289ed36147a0ddce35d6ea4d7ebbda243cda7b2213b6a5e1d8087a298d5cf630fb2bd39329cdecb82017023f6081a0 + languageName: node + linkType: hard + "@jridgewell/trace-mapping@npm:^0.3.23, @jridgewell/trace-mapping@npm:^0.3.24, @jridgewell/trace-mapping@npm:^0.3.25": version: 0.3.25 resolution: "@jridgewell/trace-mapping@npm:0.3.25" @@ -4479,6 +4486,22 @@ __metadata: languageName: node linkType: hard +"@rollup/plugin-inject@npm:^5.0.3": + version: 5.0.5 + resolution: "@rollup/plugin-inject@npm:5.0.5" + dependencies: + "@rollup/pluginutils": "npm:^5.0.1" + estree-walker: "npm:^2.0.2" + magic-string: "npm:^0.30.3" + peerDependencies: + rollup: ^1.20.0||^2.0.0||^3.0.0||^4.0.0 + peerDependenciesMeta: + rollup: + optional: true + checksum: 10c0/22d10cf44fa56a6683d5ac4df24a9003379b3dcaae9897f5c30c844afc2ebca83cfaa5557f13a1399b1c8a0d312c3217bcacd508b7ebc4b2cbee401bd1ec8be2 + languageName: node + linkType: hard + "@rollup/pluginutils@npm:^4.2.0": version: 4.2.1 resolution: "@rollup/pluginutils@npm:4.2.1" @@ -4489,6 +4512,22 @@ __metadata: languageName: node linkType: hard +"@rollup/pluginutils@npm:^5.0.1": + version: 5.3.0 + resolution: "@rollup/pluginutils@npm:5.3.0" + dependencies: + "@types/estree": "npm:^1.0.0" + estree-walker: "npm:^2.0.2" + picomatch: "npm:^4.0.2" + peerDependencies: + rollup: ^1.20.0||^2.0.0||^3.0.0||^4.0.0 + peerDependenciesMeta: + rollup: + optional: true + checksum: 10c0/001834bf62d7cf5bac424d2617c113f7f7d3b2bf3c1778cbcccb72cdc957b68989f8e7747c782c2b911f1dde8257f56f8ac1e779e29e74e638e3f1e2cac2bcd0 + languageName: node + linkType: hard + "@rollup/pluginutils@npm:^5.1.3": version: 5.1.3 resolution: "@rollup/pluginutils@npm:5.1.3" @@ -6128,6 +6167,30 @@ __metadata: languageName: node linkType: hard +"asn1.js@npm:^4.10.1": + version: 4.10.1 + resolution: "asn1.js@npm:4.10.1" + dependencies: + bn.js: "npm:^4.0.0" + inherits: "npm:^2.0.1" + minimalistic-assert: "npm:^1.0.0" + checksum: 10c0/afa7f3ab9e31566c80175a75b182e5dba50589dcc738aa485be42bdd787e2a07246a4b034d481861123cbe646a7656f318f4f1cad2e9e5e808a210d5d6feaa88 + languageName: node + linkType: hard + +"assert@npm:^2.0.0": + version: 2.1.0 + resolution: "assert@npm:2.1.0" + dependencies: + call-bind: "npm:^1.0.2" + is-nan: "npm:^1.3.2" + object-is: "npm:^1.1.5" + object.assign: "npm:^4.1.4" + util: "npm:^0.12.5" + checksum: 10c0/7271a5da883c256a1fa690677bf1dd9d6aa882139f2bed1cd15da4f9e7459683e1da8e32a203d6cc6767e5e0f730c77a9532a87b896b4b0af0dd535f668775f0 + languageName: node + linkType: hard + "assertion-error@npm:^2.0.1": version: 2.0.1 resolution: "assertion-error@npm:2.0.1" @@ -6318,6 +6381,20 @@ __metadata: languageName: node linkType: hard +"bn.js@npm:^4.0.0, bn.js@npm:^4.1.0, bn.js@npm:^4.11.9": + version: 4.12.2 + resolution: "bn.js@npm:4.12.2" + checksum: 10c0/09a249faa416a9a1ce68b5f5ec8bbca87fe54e5dd4ef8b1cc8a4969147b80035592bddcb1e9cc814c3ba79e573503d5c5178664b722b509fb36d93620dba9b57 + languageName: node + linkType: hard + +"bn.js@npm:^5.2.1, bn.js@npm:^5.2.2": + version: 5.2.2 + resolution: "bn.js@npm:5.2.2" + checksum: 10c0/cb97827d476aab1a0194df33cd84624952480d92da46e6b4a19c32964aa01553a4a613502396712704da2ec8f831cf98d02e74ca03398404bd78a037ba93f2ab + languageName: node + linkType: hard + "boolbase@npm:^1.0.0": version: 1.0.0 resolution: "boolbase@npm:1.0.0" @@ -6393,6 +6470,96 @@ __metadata: languageName: node linkType: hard +"brorand@npm:^1.0.1, brorand@npm:^1.1.0": + version: 1.1.0 + resolution: "brorand@npm:1.1.0" + checksum: 10c0/6f366d7c4990f82c366e3878492ba9a372a73163c09871e80d82fb4ae0d23f9f8924cb8a662330308206e6b3b76ba1d528b4601c9ef73c2166b440b2ea3b7571 + languageName: node + linkType: hard + +"browser-resolve@npm:^2.0.0": + version: 2.0.0 + resolution: "browser-resolve@npm:2.0.0" + dependencies: + resolve: "npm:^1.17.0" + checksum: 10c0/06c43adf3cb1939825ab9a4ac355b23272820ee421a20d04f62e0dabd9ea305e497b97f3ac027f87d53c366483aafe8673bbe1aaa5e41cd69eeafa65ac5fda6e + languageName: node + linkType: hard + +"browserify-aes@npm:^1.0.4, browserify-aes@npm:^1.2.0": + version: 1.2.0 + resolution: "browserify-aes@npm:1.2.0" + dependencies: + buffer-xor: "npm:^1.0.3" + cipher-base: "npm:^1.0.0" + create-hash: "npm:^1.1.0" + evp_bytestokey: "npm:^1.0.3" + inherits: "npm:^2.0.1" + safe-buffer: "npm:^5.0.1" + checksum: 10c0/967f2ae60d610b7b252a4cbb55a7a3331c78293c94b4dd9c264d384ca93354c089b3af9c0dd023534efdc74ffbc82510f7ad4399cf82bc37bc07052eea485f18 + languageName: node + linkType: hard + +"browserify-cipher@npm:^1.0.1": + version: 1.0.1 + resolution: "browserify-cipher@npm:1.0.1" + dependencies: + browserify-aes: "npm:^1.0.4" + browserify-des: "npm:^1.0.0" + evp_bytestokey: "npm:^1.0.0" + checksum: 10c0/aa256dcb42bc53a67168bbc94ab85d243b0a3b56109dee3b51230b7d010d9b78985ffc1fb36e145c6e4db151f888076c1cfc207baf1525d3e375cbe8187fe27d + languageName: node + linkType: hard + +"browserify-des@npm:^1.0.0": + version: 1.0.2 + resolution: "browserify-des@npm:1.0.2" + dependencies: + cipher-base: "npm:^1.0.1" + des.js: "npm:^1.0.0" + inherits: "npm:^2.0.1" + safe-buffer: "npm:^5.1.2" + checksum: 10c0/943eb5d4045eff80a6cde5be4e5fbb1f2d5002126b5a4789c3c1aae3cdddb1eb92b00fb92277f512288e5c6af330730b1dbabcf7ce0923e749e151fcee5a074d + languageName: node + linkType: hard + +"browserify-rsa@npm:^4.0.0, browserify-rsa@npm:^4.1.1": + version: 4.1.1 + resolution: "browserify-rsa@npm:4.1.1" + dependencies: + bn.js: "npm:^5.2.1" + randombytes: "npm:^2.1.0" + safe-buffer: "npm:^5.2.1" + checksum: 10c0/b650ee1192e3d7f3d779edc06dd96ed8720362e72ac310c367b9d7fe35f7e8dbb983c1829142b2b3215458be8bf17c38adc7224920843024ed8cf39e19c513c0 + languageName: node + linkType: hard + +"browserify-sign@npm:^4.2.3": + version: 4.2.5 + resolution: "browserify-sign@npm:4.2.5" + dependencies: + bn.js: "npm:^5.2.2" + browserify-rsa: "npm:^4.1.1" + create-hash: "npm:^1.2.0" + create-hmac: "npm:^1.1.7" + elliptic: "npm:^6.6.1" + inherits: "npm:^2.0.4" + parse-asn1: "npm:^5.1.9" + readable-stream: "npm:^2.3.8" + safe-buffer: "npm:^5.2.1" + checksum: 10c0/6192f9696934bbba58932d098face34c2ab9cac09feed826618b86b8c00a897dab7324cd9aa7d6cb1597064f197264ad72fa5418d4d52bf3c8f9b9e0e124655e + languageName: node + linkType: hard + +"browserify-zlib@npm:^0.2.0": + version: 0.2.0 + resolution: "browserify-zlib@npm:0.2.0" + dependencies: + pako: "npm:~1.0.5" + checksum: 10c0/9ab10b6dc732c6c5ec8ebcbe5cb7fe1467f97402c9b2140113f47b5f187b9438f93a8e065d8baf8b929323c18324fbf1105af479ee86d9d36cab7d7ef3424ad9 + languageName: node + linkType: hard + "browserslist@npm:^4.24.0, browserslist@npm:^4.24.3, browserslist@npm:^4.24.4": version: 4.24.4 resolution: "browserslist@npm:4.24.4" @@ -6437,6 +6604,23 @@ __metadata: languageName: node linkType: hard +"buffer-xor@npm:^1.0.3": + version: 1.0.3 + resolution: "buffer-xor@npm:1.0.3" + checksum: 10c0/fd269d0e0bf71ecac3146187cfc79edc9dbb054e2ee69b4d97dfb857c6d997c33de391696d04bdd669272751fa48e7872a22f3a6c7b07d6c0bc31dbe02a4075c + languageName: node + linkType: hard + +"buffer@npm:^5.7.1": + version: 5.7.1 + resolution: "buffer@npm:5.7.1" + dependencies: + base64-js: "npm:^1.3.1" + ieee754: "npm:^1.1.13" + checksum: 10c0/27cac81cff434ed2876058d72e7c4789d11ff1120ef32c9de48f59eab58179b66710c488987d295ae89a228f835fc66d088652dffeb8e3ba8659f80eb091d55e + languageName: node + linkType: hard + "buffer@npm:^6.0.3": version: 6.0.3 resolution: "buffer@npm:6.0.3" @@ -6454,6 +6638,13 @@ __metadata: languageName: node linkType: hard +"builtin-status-codes@npm:^3.0.0": + version: 3.0.0 + resolution: "builtin-status-codes@npm:3.0.0" + checksum: 10c0/c37bbba11a34c4431e56bd681b175512e99147defbe2358318d8152b3a01df7bf25e0305873947e5b350073d5ef41a364a22b37e48f1fb6d2fe6d5286a0f348c + languageName: node + linkType: hard + "bytesish@npm:^0.4.1": version: 0.4.4 resolution: "bytesish@npm:0.4.4" @@ -6508,7 +6699,7 @@ __metadata: languageName: node linkType: hard -"call-bind@npm:^1.0.2, call-bind@npm:^1.0.7, call-bind@npm:^1.0.8": +"call-bind@npm:^1.0.0, call-bind@npm:^1.0.2, call-bind@npm:^1.0.7, call-bind@npm:^1.0.8": version: 1.0.8 resolution: "call-bind@npm:1.0.8" dependencies: @@ -6722,6 +6913,17 @@ __metadata: languageName: node linkType: hard +"cipher-base@npm:^1.0.0, cipher-base@npm:^1.0.1, cipher-base@npm:^1.0.3": + version: 1.0.7 + resolution: "cipher-base@npm:1.0.7" + dependencies: + inherits: "npm:^2.0.4" + safe-buffer: "npm:^5.2.1" + to-buffer: "npm:^1.2.2" + checksum: 10c0/53c5046a9d9b60c586479b8f13fde263c3f905e13f11e8e04c7a311ce399c91d9c3ec96642332e0de077d356e1014ee12bba96f74fbaad0de750f49122258836 + languageName: node + linkType: hard + "classnames@npm:^2.3.1, classnames@npm:^2.5.1": version: 2.5.1 resolution: "classnames@npm:2.5.1" @@ -6885,6 +7087,20 @@ __metadata: languageName: node linkType: hard +"console-browserify@npm:^1.1.0": + version: 1.2.0 + resolution: "console-browserify@npm:1.2.0" + checksum: 10c0/89b99a53b7d6cee54e1e64fa6b1f7ac24b844b4019c5d39db298637e55c1f4ffa5c165457ad984864de1379df2c8e1886cbbdac85d9dbb6876a9f26c3106f226 + languageName: node + linkType: hard + +"constants-browserify@npm:^1.0.0": + version: 1.0.0 + resolution: "constants-browserify@npm:1.0.0" + checksum: 10c0/ab49b1d59a433ed77c964d90d19e08b2f77213fb823da4729c0baead55e3c597f8f97ebccfdfc47bd896d43854a117d114c849a6f659d9986420e97da0f83ac5 + languageName: node + linkType: hard + "content-type@npm:^1.0.4": version: 1.0.5 resolution: "content-type@npm:1.0.5" @@ -6957,6 +7173,50 @@ __metadata: languageName: node linkType: hard +"create-ecdh@npm:^4.0.4": + version: 4.0.4 + resolution: "create-ecdh@npm:4.0.4" + dependencies: + bn.js: "npm:^4.1.0" + elliptic: "npm:^6.5.3" + checksum: 10c0/77b11a51360fec9c3bce7a76288fc0deba4b9c838d5fb354b3e40c59194d23d66efe6355fd4b81df7580da0661e1334a235a2a5c040b7569ba97db428d466e7f + languageName: node + linkType: hard + +"create-hash@npm:^1.1.0, create-hash@npm:^1.2.0": + version: 1.2.0 + resolution: "create-hash@npm:1.2.0" + dependencies: + cipher-base: "npm:^1.0.1" + inherits: "npm:^2.0.1" + md5.js: "npm:^1.3.4" + ripemd160: "npm:^2.0.1" + sha.js: "npm:^2.4.0" + checksum: 10c0/d402e60e65e70e5083cb57af96d89567954d0669e90550d7cec58b56d49c4b193d35c43cec8338bc72358198b8cbf2f0cac14775b651e99238e1cf411490f915 + languageName: node + linkType: hard + +"create-hmac@npm:^1.1.7": + version: 1.1.7 + resolution: "create-hmac@npm:1.1.7" + dependencies: + cipher-base: "npm:^1.0.3" + create-hash: "npm:^1.1.0" + inherits: "npm:^2.0.1" + ripemd160: "npm:^2.0.0" + safe-buffer: "npm:^5.0.1" + sha.js: "npm:^2.4.8" + checksum: 10c0/24332bab51011652a9a0a6d160eed1e8caa091b802335324ae056b0dcb5acbc9fcf173cf10d128eba8548c3ce98dfa4eadaa01bd02f44a34414baee26b651835 + languageName: node + linkType: hard + +"create-require@npm:^1.1.1": + version: 1.1.1 + resolution: "create-require@npm:1.1.1" + checksum: 10c0/157cbc59b2430ae9a90034a5f3a1b398b6738bf510f713edc4d4e45e169bc514d3d99dd34d8d01ca7ae7830b5b8b537e46ae8f3c8f932371b0875c0151d7ec91 + languageName: node + linkType: hard + "cross-spawn@npm:^7.0.2": version: 7.0.3 resolution: "cross-spawn@npm:7.0.3" @@ -6979,6 +7239,26 @@ __metadata: languageName: node linkType: hard +"crypto-browserify@npm:^3.12.1": + version: 3.12.1 + resolution: "crypto-browserify@npm:3.12.1" + dependencies: + browserify-cipher: "npm:^1.0.1" + browserify-sign: "npm:^4.2.3" + create-ecdh: "npm:^4.0.4" + create-hash: "npm:^1.2.0" + create-hmac: "npm:^1.1.7" + diffie-hellman: "npm:^5.0.3" + hash-base: "npm:~3.0.4" + inherits: "npm:^2.0.4" + pbkdf2: "npm:^3.1.2" + public-encrypt: "npm:^4.0.3" + randombytes: "npm:^2.1.0" + randomfill: "npm:^1.0.4" + checksum: 10c0/184a2def7b16628e79841243232ab5497f18d8e158ac21b7ce90ab172427d0a892a561280adc08f9d4d517bce8db2a5b335dc21abb970f787f8e874bd7b9db7d + languageName: node + linkType: hard + "css-blank-pseudo@npm:^7.0.1": version: 7.0.1 resolution: "css-blank-pseudo@npm:7.0.1" @@ -7267,6 +7547,16 @@ __metadata: languageName: node linkType: hard +"des.js@npm:^1.0.0": + version: 1.1.0 + resolution: "des.js@npm:1.1.0" + dependencies: + inherits: "npm:^2.0.1" + minimalistic-assert: "npm:^1.0.0" + checksum: 10c0/671354943ad67493e49eb4c555480ab153edd7cee3a51c658082fcde539d2690ed2a4a0b5d1f401f9cde822edf3939a6afb2585f32c091f2d3a1b1665cd45236 + languageName: node + linkType: hard + "detect-libc@npm:^1.0.3": version: 1.0.3 resolution: "detect-libc@npm:1.0.3" @@ -7283,6 +7573,17 @@ __metadata: languageName: node linkType: hard +"diffie-hellman@npm:^5.0.3": + version: 5.0.3 + resolution: "diffie-hellman@npm:5.0.3" + dependencies: + bn.js: "npm:^4.1.0" + miller-rabin: "npm:^4.0.0" + randombytes: "npm:^2.0.0" + checksum: 10c0/ce53ccafa9ca544b7fc29b08a626e23a9b6562efc2a98559a0c97b4718937cebaa9b5d7d0a05032cc9c1435e9b3c1532b9e9bf2e0ede868525922807ad6e1ecf + languageName: node + linkType: hard + "dijkstrajs@npm:^1.0.1": version: 1.0.3 resolution: "dijkstrajs@npm:1.0.3" @@ -7353,6 +7654,13 @@ __metadata: languageName: node linkType: hard +"domain-browser@npm:4.22.0": + version: 4.22.0 + resolution: "domain-browser@npm:4.22.0" + checksum: 10c0/2ef7eda6d2161038fda0c9aa4c9e18cc7a0baa89ea6be975d449527c2eefd4b608425db88508e2859acc472f46f402079274b24bd75e3fb506f28c5dba203129 + languageName: node + linkType: hard + "domelementtype@npm:^2.0.1, domelementtype@npm:^2.2.0, domelementtype@npm:^2.3.0": version: 2.3.0 resolution: "domelementtype@npm:2.3.0" @@ -7549,6 +7857,7 @@ __metadata: loglevel: "npm:^1.9.1" matrix-js-sdk: "github:matrix-org/matrix-js-sdk#head=toger5/sticky-events&commit=e7f5bec51b6f70501a025b79fe5021c933385b21" matrix-widget-api: "npm:^1.13.0" + node-stdlib-browser: "npm:^1.3.1" normalize.css: "npm:^8.0.1" observable-hooks: "npm:^4.2.3" pako: "npm:^2.0.4" @@ -7571,6 +7880,7 @@ __metadata: vite: "npm:^7.0.0" vite-plugin-generate-file: "npm:^0.3.0" vite-plugin-html: "npm:^3.2.2" + vite-plugin-node-stdlib-browser: "npm:^0.2.1" vite-plugin-singlefile: "npm:^2.3.0" vite-plugin-svgr: "npm:^4.0.0" vitest: "npm:^3.0.0" @@ -7578,6 +7888,21 @@ __metadata: languageName: unknown linkType: soft +"elliptic@npm:^6.5.3, elliptic@npm:^6.6.1": + version: 6.6.1 + resolution: "elliptic@npm:6.6.1" + dependencies: + bn.js: "npm:^4.11.9" + brorand: "npm:^1.1.0" + hash.js: "npm:^1.0.0" + hmac-drbg: "npm:^1.0.1" + inherits: "npm:^2.0.4" + minimalistic-assert: "npm:^1.0.1" + minimalistic-crypto-utils: "npm:^1.0.1" + checksum: 10c0/8b24ef782eec8b472053793ea1e91ae6bee41afffdfcb78a81c0a53b191e715cbe1292aa07165958a9bbe675bd0955142560b1a007ffce7d6c765bcaf951a867 + languageName: node + linkType: hard + "emoji-regex@npm:^8.0.0": version: 8.0.0 resolution: "emoji-regex@npm:8.0.0" @@ -8389,13 +8714,24 @@ __metadata: languageName: node linkType: hard -"events@npm:^3.2.0, events@npm:^3.3.0": +"events@npm:^3.0.0, events@npm:^3.2.0, events@npm:^3.3.0": version: 3.3.0 resolution: "events@npm:3.3.0" checksum: 10c0/d6b6f2adbccbcda74ddbab52ed07db727ef52e31a61ed26db9feb7dc62af7fc8e060defa65e5f8af9449b86b52cc1a1f6a79f2eafcf4e62add2b7a1fa4a432f6 languageName: node linkType: hard +"evp_bytestokey@npm:^1.0.0, evp_bytestokey@npm:^1.0.3": + version: 1.0.3 + resolution: "evp_bytestokey@npm:1.0.3" + dependencies: + md5.js: "npm:^1.3.4" + node-gyp: "npm:latest" + safe-buffer: "npm:^5.1.1" + checksum: 10c0/77fbe2d94a902a80e9b8f5a73dcd695d9c14899c5e82967a61b1fc6cbbb28c46552d9b127cff47c45fcf684748bdbcfa0a50410349109de87ceb4b199ef6ee99 + languageName: node + linkType: hard + "expect-type@npm:^1.2.1": version: 1.2.1 resolution: "expect-type@npm:1.2.1" @@ -8791,6 +9127,13 @@ __metadata: languageName: node linkType: hard +"generator-function@npm:^2.0.0": + version: 2.0.1 + resolution: "generator-function@npm:2.0.1" + checksum: 10c0/8a9f59df0f01cfefafdb3b451b80555e5cf6d76487095db91ac461a0e682e4ff7a9dbce15f4ecec191e53586d59eece01949e05a4b4492879600bbbe8e28d6b8 + languageName: node + linkType: hard + "gensync@npm:^1.0.0-beta.2": version: 1.0.0-beta.2 resolution: "gensync@npm:1.0.0-beta.2" @@ -9093,6 +9436,38 @@ __metadata: languageName: node linkType: hard +"hash-base@npm:^3.0.0, hash-base@npm:^3.1.2": + version: 3.1.2 + resolution: "hash-base@npm:3.1.2" + dependencies: + inherits: "npm:^2.0.4" + readable-stream: "npm:^2.3.8" + safe-buffer: "npm:^5.2.1" + to-buffer: "npm:^1.2.1" + checksum: 10c0/f3b7fae1853b31340048dd659f40f5260ca6f3ff53b932f807f4ab701ee09039f6e9dbe1841723ff61e20f3f69d6387a352e4ccc5f997dedb0d375c7d88bc15e + languageName: node + linkType: hard + +"hash-base@npm:~3.0.4": + version: 3.0.5 + resolution: "hash-base@npm:3.0.5" + dependencies: + inherits: "npm:^2.0.4" + safe-buffer: "npm:^5.2.1" + checksum: 10c0/6dc185b79bad9b6d525cd132a588e4215380fdc36fec6f7a8a58c5db8e3b642557d02ad9c367f5e476c7c3ad3ccffa3607f308b124e1ed80e3b80a1b254db61e + languageName: node + linkType: hard + +"hash.js@npm:^1.0.0, hash.js@npm:^1.0.3": + version: 1.1.7 + resolution: "hash.js@npm:1.1.7" + dependencies: + inherits: "npm:^2.0.3" + minimalistic-assert: "npm:^1.0.1" + checksum: 10c0/41ada59494eac5332cfc1ce6b7ebdd7b88a3864a6d6b08a3ea8ef261332ed60f37f10877e0c825aaa4bddebf164fbffa618286aeeec5296675e2671cbfa746c4 + languageName: node + linkType: hard + "hasown@npm:^2.0.0, hasown@npm:^2.0.2": version: 2.0.2 resolution: "hasown@npm:2.0.2" @@ -9130,6 +9505,17 @@ __metadata: languageName: node linkType: hard +"hmac-drbg@npm:^1.0.1": + version: 1.0.1 + resolution: "hmac-drbg@npm:1.0.1" + dependencies: + hash.js: "npm:^1.0.3" + minimalistic-assert: "npm:^1.0.0" + minimalistic-crypto-utils: "npm:^1.0.1" + checksum: 10c0/f3d9ba31b40257a573f162176ac5930109816036c59a09f901eb2ffd7e5e705c6832bedfff507957125f2086a0ab8f853c0df225642a88bf1fcaea945f20600d + languageName: node + linkType: hard + "hoist-non-react-statics@npm:^3.3.2": version: 3.3.2 resolution: "hoist-non-react-statics@npm:3.3.2" @@ -9217,6 +9603,13 @@ __metadata: languageName: node linkType: hard +"https-browserify@npm:^1.0.0": + version: 1.0.0 + resolution: "https-browserify@npm:1.0.0" + checksum: 10c0/e17b6943bc24ea9b9a7da5714645d808670af75a425f29baffc3284962626efdc1eb3aa9bbffaa6e64028a6ad98af5b09fabcb454a8f918fb686abfdc9e9b8ae + languageName: node + linkType: hard + "https-proxy-agent@npm:^5.0.0": version: 5.0.1 resolution: "https-proxy-agent@npm:5.0.1" @@ -9296,7 +9689,7 @@ __metadata: languageName: node linkType: hard -"ieee754@npm:^1.2.1": +"ieee754@npm:^1.1.13, ieee754@npm:^1.2.1": version: 1.2.1 resolution: "ieee754@npm:1.2.1" checksum: 10c0/b0782ef5e0935b9f12883a2e2aa37baa75da6e66ce6515c168697b42160807d9330de9a32ec1ed73149aea02e0d822e572bca6f1e22bdcbd2149e13b050b17bb @@ -9358,7 +9751,7 @@ __metadata: languageName: node linkType: hard -"inherits@npm:2, inherits@npm:^2.0.3, inherits@npm:^2.0.4, inherits@npm:~2.0.3": +"inherits@npm:2, inherits@npm:^2.0.1, inherits@npm:^2.0.3, inherits@npm:^2.0.4, inherits@npm:~2.0.3, inherits@npm:~2.0.4": version: 2.0.4 resolution: "inherits@npm:2.0.4" checksum: 10c0/4e531f648b29039fb7426fb94075e6545faa1eb9fe83c29f0b6d9e7263aceb4289d2d4557db0d428188eeb449cc7c5e77b0a0b2c4e248ff2a65933a0dee49ef2 @@ -9386,6 +9779,16 @@ __metadata: languageName: node linkType: hard +"is-arguments@npm:^1.0.4": + version: 1.2.0 + resolution: "is-arguments@npm:1.2.0" + dependencies: + call-bound: "npm:^1.0.2" + has-tostringtag: "npm:^1.0.2" + checksum: 10c0/6377344b31e9fcb707c6751ee89b11f132f32338e6a782ec2eac9393b0cbd32235dad93052998cda778ee058754860738341d8114910d50ada5615912bb929fc + languageName: node + linkType: hard + "is-array-buffer@npm:^3.0.4, is-array-buffer@npm:^3.0.5": version: 3.0.5 resolution: "is-array-buffer@npm:3.0.5" @@ -9525,6 +9928,19 @@ __metadata: languageName: node linkType: hard +"is-generator-function@npm:^1.0.7": + version: 1.1.2 + resolution: "is-generator-function@npm:1.1.2" + dependencies: + call-bound: "npm:^1.0.4" + generator-function: "npm:^2.0.0" + get-proto: "npm:^1.0.1" + has-tostringtag: "npm:^1.0.2" + safe-regex-test: "npm:^1.1.0" + checksum: 10c0/83da102e89c3e3b71d67b51d47c9f9bc862bceb58f87201727e27f7fa19d1d90b0ab223644ecaee6fc6e3d2d622bb25c966fbdaf87c59158b01ce7c0fe2fa372 + languageName: node + linkType: hard + "is-glob@npm:^4.0.0, is-glob@npm:^4.0.1, is-glob@npm:^4.0.3, is-glob@npm:~4.0.1": version: 4.0.3 resolution: "is-glob@npm:4.0.3" @@ -9541,6 +9957,16 @@ __metadata: languageName: node linkType: hard +"is-nan@npm:^1.3.2": + version: 1.3.2 + resolution: "is-nan@npm:1.3.2" + dependencies: + call-bind: "npm:^1.0.0" + define-properties: "npm:^1.1.3" + checksum: 10c0/8bfb286f85763f9c2e28ea32e9127702fe980ffd15fa5d63ade3be7786559e6e21355d3625dd364c769c033c5aedf0a2ed3d4025d336abf1b9241e3d9eddc5b0 + languageName: node + linkType: hard + "is-negated-glob@npm:^1.0.0": version: 1.0.0 resolution: "is-negated-glob@npm:1.0.0" @@ -9663,7 +10089,7 @@ __metadata: languageName: node linkType: hard -"is-typed-array@npm:^1.1.13, is-typed-array@npm:^1.1.14, is-typed-array@npm:^1.1.15": +"is-typed-array@npm:^1.1.13, is-typed-array@npm:^1.1.14, is-typed-array@npm:^1.1.15, is-typed-array@npm:^1.1.3": version: 1.1.15 resolution: "is-typed-array@npm:1.1.15" dependencies: @@ -9742,6 +10168,13 @@ __metadata: languageName: node linkType: hard +"isomorphic-timers-promises@npm:^1.0.1": + version: 1.0.1 + resolution: "isomorphic-timers-promises@npm:1.0.1" + checksum: 10c0/3b4761d0012ebe6b6382246079fc667f3513f36fe4042638f2bfb7db1557e4f1acd33a9c9907706c04270890ec6434120f132f3f300161a42a7dd8628926c8a4 + languageName: node + linkType: hard + "istanbul-lib-coverage@npm:^3.0.0, istanbul-lib-coverage@npm:^3.2.2": version: 3.2.2 resolution: "istanbul-lib-coverage@npm:3.2.2" @@ -10290,6 +10723,15 @@ __metadata: languageName: node linkType: hard +"magic-string@npm:^0.30.3": + version: 0.30.21 + resolution: "magic-string@npm:0.30.21" + dependencies: + "@jridgewell/sourcemap-codec": "npm:^1.5.5" + checksum: 10c0/299378e38f9a270069fc62358522ddfb44e94244baa0d6a8980ab2a9b2490a1d03b236b447eee309e17eb3bddfa482c61259d47960eb018a904f0ded52780c4a + languageName: node + linkType: hard + "magicast@npm:^0.3.5": version: 0.3.5 resolution: "magicast@npm:0.3.5" @@ -10385,6 +10827,17 @@ __metadata: languageName: node linkType: hard +"md5.js@npm:^1.3.4": + version: 1.3.5 + resolution: "md5.js@npm:1.3.5" + dependencies: + hash-base: "npm:^3.0.0" + inherits: "npm:^2.0.1" + safe-buffer: "npm:^5.1.2" + checksum: 10c0/b7bd75077f419c8e013fc4d4dada48be71882e37d69a44af65a2f2804b91e253441eb43a0614423a1c91bb830b8140b0dc906bc797245e2e275759584f4efcc5 + languageName: node + linkType: hard + "merge2@npm:^1.3.0, merge2@npm:^1.4.1": version: 1.4.1 resolution: "merge2@npm:1.4.1" @@ -10402,6 +10855,18 @@ __metadata: languageName: node linkType: hard +"miller-rabin@npm:^4.0.0": + version: 4.0.1 + resolution: "miller-rabin@npm:4.0.1" + dependencies: + bn.js: "npm:^4.0.0" + brorand: "npm:^1.0.1" + bin: + miller-rabin: bin/miller-rabin + checksum: 10c0/26b2b96f6e49dbcff7faebb78708ed2f5f9ae27ac8cbbf1d7c08f83cf39bed3d418c0c11034dce997da70d135cc0ff6f3a4c15dc452f8e114c11986388a64346 + languageName: node + linkType: hard + "mime-db@npm:1.52.0": version: 1.52.0 resolution: "mime-db@npm:1.52.0" @@ -10425,6 +10890,20 @@ __metadata: languageName: node linkType: hard +"minimalistic-assert@npm:^1.0.0, minimalistic-assert@npm:^1.0.1": + version: 1.0.1 + resolution: "minimalistic-assert@npm:1.0.1" + checksum: 10c0/96730e5601cd31457f81a296f521eb56036e6f69133c0b18c13fe941109d53ad23a4204d946a0d638d7f3099482a0cec8c9bb6d642604612ce43ee536be3dddd + languageName: node + linkType: hard + +"minimalistic-crypto-utils@npm:^1.0.1": + version: 1.0.1 + resolution: "minimalistic-crypto-utils@npm:1.0.1" + checksum: 10c0/790ecec8c5c73973a4fbf2c663d911033e8494d5fb0960a4500634766ab05d6107d20af896ca2132e7031741f19888154d44b2408ada0852446705441383e9f8 + languageName: node + linkType: hard + "minimatch@npm:^3.0.2, minimatch@npm:^3.0.4, minimatch@npm:^3.0.5, minimatch@npm:^3.1.1, minimatch@npm:^3.1.2": version: 3.1.2 resolution: "minimatch@npm:3.1.2" @@ -10675,6 +11154,41 @@ __metadata: languageName: node linkType: hard +"node-stdlib-browser@npm:^1.3.1": + version: 1.3.1 + resolution: "node-stdlib-browser@npm:1.3.1" + dependencies: + assert: "npm:^2.0.0" + browser-resolve: "npm:^2.0.0" + browserify-zlib: "npm:^0.2.0" + buffer: "npm:^5.7.1" + console-browserify: "npm:^1.1.0" + constants-browserify: "npm:^1.0.0" + create-require: "npm:^1.1.1" + crypto-browserify: "npm:^3.12.1" + domain-browser: "npm:4.22.0" + events: "npm:^3.0.0" + https-browserify: "npm:^1.0.0" + isomorphic-timers-promises: "npm:^1.0.1" + os-browserify: "npm:^0.3.0" + path-browserify: "npm:^1.0.1" + pkg-dir: "npm:^5.0.0" + process: "npm:^0.11.10" + punycode: "npm:^1.4.1" + querystring-es3: "npm:^0.2.1" + readable-stream: "npm:^3.6.0" + stream-browserify: "npm:^3.0.0" + stream-http: "npm:^3.2.0" + string_decoder: "npm:^1.0.0" + timers-browserify: "npm:^2.0.4" + tty-browserify: "npm:0.0.1" + url: "npm:^0.11.4" + util: "npm:^0.12.4" + vm-browserify: "npm:^1.0.1" + checksum: 10c0/5b0cb5d4499b1b1c73f54db3e9e69b2a3a8aebe2ead2e356b0a03c1dfca6b5c5d2f6516e24301e76dc7b68999b9d0ae3da6c3f1dec421eed80ad6cb9eec0f356 + languageName: node + linkType: hard + "nopt@npm:^8.0.0": version: 8.1.0 resolution: "nopt@npm:8.1.0" @@ -10765,6 +11279,16 @@ __metadata: languageName: node linkType: hard +"object-is@npm:^1.1.5": + version: 1.1.6 + resolution: "object-is@npm:1.1.6" + dependencies: + call-bind: "npm:^1.0.7" + define-properties: "npm:^1.2.1" + checksum: 10c0/506af444c4dce7f8e31f34fc549e2fb8152d6b9c4a30c6e62852badd7f520b579c679af433e7a072f9d78eb7808d230dc12e1cf58da9154dfbf8813099ea0fe0 + languageName: node + linkType: hard + "object-keys@npm:^1.1.1": version: 1.1.1 resolution: "object-keys@npm:1.1.1" @@ -10876,6 +11400,13 @@ __metadata: languageName: node linkType: hard +"os-browserify@npm:^0.3.0": + version: 0.3.0 + resolution: "os-browserify@npm:0.3.0" + checksum: 10c0/6ff32cb1efe2bc6930ad0fd4c50e30c38010aee909eba8d65be60af55efd6cbb48f0287e3649b4e3f3a63dce5a667b23c187c4293a75e557f0d5489d735bcf52 + languageName: node + linkType: hard + "own-keys@npm:^1.0.1": version: 1.0.1 resolution: "own-keys@npm:1.0.1" @@ -11008,6 +11539,13 @@ __metadata: languageName: node linkType: hard +"pako@npm:~1.0.5": + version: 1.0.11 + resolution: "pako@npm:1.0.11" + checksum: 10c0/86dd99d8b34c3930345b8bbeb5e1cd8a05f608eeb40967b293f72fe469d0e9c88b783a8777e4cc7dc7c91ce54c5e93d88ff4b4f060e6ff18408fd21030d9ffbe + languageName: node + linkType: hard + "param-case@npm:^3.0.4": version: 3.0.4 resolution: "param-case@npm:3.0.4" @@ -11027,6 +11565,19 @@ __metadata: languageName: node linkType: hard +"parse-asn1@npm:^5.0.0, parse-asn1@npm:^5.1.9": + version: 5.1.9 + resolution: "parse-asn1@npm:5.1.9" + dependencies: + asn1.js: "npm:^4.10.1" + browserify-aes: "npm:^1.2.0" + evp_bytestokey: "npm:^1.0.3" + pbkdf2: "npm:^3.1.5" + safe-buffer: "npm:^5.2.1" + checksum: 10c0/6dfe27c121be3d63ebbf95f03d2ae0a07dd716d44b70b0bd3458790a822a80de05361c62147271fd7b845dcc2d37755d9c9c393064a3438fe633779df0bc07e7 + languageName: node + linkType: hard + "parse-json@npm:^5.0.0, parse-json@npm:^5.2.0": version: 5.2.0 resolution: "parse-json@npm:5.2.0" @@ -11077,6 +11628,13 @@ __metadata: languageName: node linkType: hard +"path-browserify@npm:^1.0.1": + version: 1.0.1 + resolution: "path-browserify@npm:1.0.1" + checksum: 10c0/8b8c3fd5c66bd340272180590ae4ff139769e9ab79522e2eb82e3d571a89b8117c04147f65ad066dccfb42fcad902e5b7d794b3d35e0fd840491a8ddbedf8c66 + languageName: node + linkType: hard + "path-exists@npm:^4.0.0": version: 4.0.0 resolution: "path-exists@npm:4.0.0" @@ -11150,6 +11708,20 @@ __metadata: languageName: node linkType: hard +"pbkdf2@npm:^3.1.2, pbkdf2@npm:^3.1.5": + version: 3.1.5 + resolution: "pbkdf2@npm:3.1.5" + dependencies: + create-hash: "npm:^1.2.0" + create-hmac: "npm:^1.1.7" + ripemd160: "npm:^2.0.3" + safe-buffer: "npm:^5.2.1" + sha.js: "npm:^2.4.12" + to-buffer: "npm:^1.2.1" + checksum: 10c0/ea42e8695e49417eefabb19a08ab19a602cc6cc72d2df3f109c39309600230dee3083a6f678d5d42fe035d6ae780038b80ace0e68f9792ee2839bf081fe386f3 + languageName: node + linkType: hard + "picocolors@npm:^1.0.0, picocolors@npm:^1.1.1": version: 1.1.1 resolution: "picocolors@npm:1.1.1" @@ -11178,6 +11750,15 @@ __metadata: languageName: node linkType: hard +"pkg-dir@npm:^5.0.0": + version: 5.0.0 + resolution: "pkg-dir@npm:5.0.0" + dependencies: + find-up: "npm:^5.0.0" + checksum: 10c0/793a496d685dc55bbbdbbb22d884535c3b29241e48e3e8d37e448113a71b9e42f5481a61fdc672d7322de12fbb2c584dd3a68bf89b18fffce5c48a390f911bc5 + languageName: node + linkType: hard + "playwright-core@npm:1.56.1": version: 1.56.1 resolution: "playwright-core@npm:1.56.1" @@ -11674,6 +12255,13 @@ __metadata: languageName: node linkType: hard +"process@npm:^0.11.10": + version: 0.11.10 + resolution: "process@npm:0.11.10" + checksum: 10c0/40c3ce4b7e6d4b8c3355479df77aeed46f81b279818ccdc500124e6a5ab882c0cc81ff7ea16384873a95a74c4570b01b120f287abbdd4c877931460eca6084b3 + languageName: node + linkType: hard + "progress@npm:^2.0.3": version: 2.0.3 resolution: "progress@npm:2.0.3" @@ -11746,6 +12334,27 @@ __metadata: languageName: node linkType: hard +"public-encrypt@npm:^4.0.3": + version: 4.0.3 + resolution: "public-encrypt@npm:4.0.3" + dependencies: + bn.js: "npm:^4.1.0" + browserify-rsa: "npm:^4.0.0" + create-hash: "npm:^1.1.0" + parse-asn1: "npm:^5.0.0" + randombytes: "npm:^2.0.1" + safe-buffer: "npm:^5.1.2" + checksum: 10c0/6c2cc19fbb554449e47f2175065d6b32f828f9b3badbee4c76585ac28ae8641aafb9bb107afc430c33c5edd6b05dbe318df4f7d6d7712b1093407b11c4280700 + languageName: node + linkType: hard + +"punycode@npm:^1.4.1": + version: 1.4.1 + resolution: "punycode@npm:1.4.1" + checksum: 10c0/354b743320518aef36f77013be6e15da4db24c2b4f62c5f1eb0529a6ed02fbaf1cb52925785f6ab85a962f2b590d9cd5ad730b70da72b5f180e2556b8bd3ca08 + languageName: node + linkType: hard + "punycode@npm:^2.1.0, punycode@npm:^2.3.1": version: 2.3.1 resolution: "punycode@npm:2.3.1" @@ -11766,6 +12375,22 @@ __metadata: languageName: node linkType: hard +"qs@npm:^6.12.3": + version: 6.14.0 + resolution: "qs@npm:6.14.0" + dependencies: + side-channel: "npm:^1.1.0" + checksum: 10c0/8ea5d91bf34f440598ee389d4a7d95820e3b837d3fd9f433871f7924801becaa0cd3b3b4628d49a7784d06a8aea9bc4554d2b6d8d584e2d221dc06238a42909c + languageName: node + linkType: hard + +"querystring-es3@npm:^0.2.1": + version: 0.2.1 + resolution: "querystring-es3@npm:0.2.1" + checksum: 10c0/476938c1adb45c141f024fccd2ffd919a3746e79ed444d00e670aad68532977b793889648980e7ca7ff5ffc7bfece623118d0fbadcaf217495eeb7059ae51580 + languageName: node + linkType: hard + "queue-microtask@npm:^1.2.2": version: 1.2.3 resolution: "queue-microtask@npm:1.2.3" @@ -11784,6 +12409,25 @@ __metadata: languageName: node linkType: hard +"randombytes@npm:^2.0.0, randombytes@npm:^2.0.1, randombytes@npm:^2.0.5, randombytes@npm:^2.1.0": + version: 2.1.0 + resolution: "randombytes@npm:2.1.0" + dependencies: + safe-buffer: "npm:^5.1.0" + checksum: 10c0/50395efda7a8c94f5dffab564f9ff89736064d32addf0cc7e8bf5e4166f09f8ded7a0849ca6c2d2a59478f7d90f78f20d8048bca3cdf8be09d8e8a10790388f3 + languageName: node + linkType: hard + +"randomfill@npm:^1.0.4": + version: 1.0.4 + resolution: "randomfill@npm:1.0.4" + dependencies: + randombytes: "npm:^2.0.5" + safe-buffer: "npm:^5.1.0" + checksum: 10c0/11aeed35515872e8f8a2edec306734e6b74c39c46653607f03c68385ab8030e2adcc4215f76b5e4598e028c4750d820afd5c65202527d831d2a5f207fe2bc87c + languageName: node + linkType: hard + "react-dom@npm:19": version: 19.1.0 resolution: "react-dom@npm:19.1.0" @@ -11978,18 +12622,7 @@ __metadata: languageName: node linkType: hard -"readable-stream@npm:^3.4.0": - version: 3.6.2 - resolution: "readable-stream@npm:3.6.2" - dependencies: - inherits: "npm:^2.0.3" - string_decoder: "npm:^1.1.1" - util-deprecate: "npm:^1.0.1" - checksum: 10c0/e37be5c79c376fdd088a45fa31ea2e423e5d48854be7a22a58869b4e84d25047b193f6acb54f1012331e1bcd667ffb569c01b99d36b0bd59658fb33f513511b7 - languageName: node - linkType: hard - -"readable-stream@npm:~2.3.6": +"readable-stream@npm:^2.3.8, readable-stream@npm:~2.3.6": version: 2.3.8 resolution: "readable-stream@npm:2.3.8" dependencies: @@ -12004,6 +12637,17 @@ __metadata: languageName: node linkType: hard +"readable-stream@npm:^3.4.0, readable-stream@npm:^3.5.0, readable-stream@npm:^3.6.0": + version: 3.6.2 + resolution: "readable-stream@npm:3.6.2" + dependencies: + inherits: "npm:^2.0.3" + string_decoder: "npm:^1.1.1" + util-deprecate: "npm:^1.0.1" + checksum: 10c0/e37be5c79c376fdd088a45fa31ea2e423e5d48854be7a22a58869b4e84d25047b193f6acb54f1012331e1bcd667ffb569c01b99d36b0bd59658fb33f513511b7 + languageName: node + linkType: hard + "readdirp@npm:^4.0.1": version: 4.1.2 resolution: "readdirp@npm:4.1.2" @@ -12220,6 +12864,19 @@ __metadata: languageName: node linkType: hard +"resolve@npm:^1.17.0": + version: 1.22.11 + resolution: "resolve@npm:1.22.11" + dependencies: + is-core-module: "npm:^2.16.1" + path-parse: "npm:^1.0.7" + supports-preserve-symlinks-flag: "npm:^1.0.0" + bin: + resolve: bin/resolve + checksum: 10c0/f657191507530f2cbecb5815b1ee99b20741ea6ee02a59c57028e9ec4c2c8d7681afcc35febbd554ac0ded459db6f2d8153382c53a2f266cee2575e512674409 + languageName: node + linkType: hard + "resolve@npm:^1.22.10": version: 1.22.10 resolution: "resolve@npm:1.22.10" @@ -12259,6 +12916,19 @@ __metadata: languageName: node linkType: hard +"resolve@patch:resolve@npm%3A^1.17.0#optional!builtin": + version: 1.22.11 + resolution: "resolve@patch:resolve@npm%3A1.22.11#optional!builtin::version=1.22.11&hash=c3c19d" + dependencies: + is-core-module: "npm:^2.16.1" + path-parse: "npm:^1.0.7" + supports-preserve-symlinks-flag: "npm:^1.0.0" + bin: + resolve: bin/resolve + checksum: 10c0/ee5b182f2e37cb1165465e58c6abc797fec0a80b5ba3231607beb4677db0c9291ac010c47cf092b6daa2b7f518d69a0e21888e7e2b633f68d501a874212a8c63 + languageName: node + linkType: hard + "resolve@patch:resolve@npm%3A^1.22.10#optional!builtin": version: 1.22.10 resolution: "resolve@patch:resolve@npm%3A1.22.10#optional!builtin::version=1.22.10&hash=c3c19d" @@ -12332,6 +13002,16 @@ __metadata: languageName: node linkType: hard +"ripemd160@npm:^2.0.0, ripemd160@npm:^2.0.1, ripemd160@npm:^2.0.3": + version: 2.0.3 + resolution: "ripemd160@npm:2.0.3" + dependencies: + hash-base: "npm:^3.1.2" + inherits: "npm:^2.0.4" + checksum: 10c0/3f472fb453241cfe692a77349accafca38dbcdc9d96d5848c088b2932ba41eb968630ecff7b175d291c7487a4945aee5a81e30c064d1f94e36070f7e0c37ed6c + languageName: node + linkType: hard + "rollup@npm:^4.43.0": version: 4.50.1 resolution: "rollup@npm:4.50.1" @@ -12479,6 +13159,13 @@ __metadata: languageName: node linkType: hard +"safe-buffer@npm:^5.0.1, safe-buffer@npm:^5.1.0, safe-buffer@npm:^5.1.1, safe-buffer@npm:^5.1.2, safe-buffer@npm:^5.2.1, safe-buffer@npm:~5.2.0": + version: 5.2.1 + resolution: "safe-buffer@npm:5.2.1" + checksum: 10c0/6501914237c0a86e9675d4e51d89ca3c21ffd6a31642efeba25ad65720bce6921c9e7e974e5be91a786b25aa058b5303285d3c15dbabf983a919f5f630d349f3 + languageName: node + linkType: hard + "safe-buffer@npm:~5.1.0, safe-buffer@npm:~5.1.1": version: 5.1.2 resolution: "safe-buffer@npm:5.1.2" @@ -12486,13 +13173,6 @@ __metadata: languageName: node linkType: hard -"safe-buffer@npm:~5.2.0": - version: 5.2.1 - resolution: "safe-buffer@npm:5.2.1" - checksum: 10c0/6501914237c0a86e9675d4e51d89ca3c21ffd6a31642efeba25ad65720bce6921c9e7e974e5be91a786b25aa058b5303285d3c15dbabf983a919f5f630d349f3 - languageName: node - linkType: hard - "safe-push-apply@npm:^1.0.0": version: 1.0.0 resolution: "safe-push-apply@npm:1.0.0" @@ -12657,6 +13337,26 @@ __metadata: languageName: node linkType: hard +"setimmediate@npm:^1.0.4": + version: 1.0.5 + resolution: "setimmediate@npm:1.0.5" + checksum: 10c0/5bae81bfdbfbd0ce992893286d49c9693c82b1bcc00dcaaf3a09c8f428fdeacf4190c013598b81875dfac2b08a572422db7df779a99332d0fce186d15a3e4d49 + languageName: node + linkType: hard + +"sha.js@npm:^2.4.0, sha.js@npm:^2.4.12, sha.js@npm:^2.4.8": + version: 2.4.12 + resolution: "sha.js@npm:2.4.12" + dependencies: + inherits: "npm:^2.0.4" + safe-buffer: "npm:^5.2.1" + to-buffer: "npm:^1.2.0" + bin: + sha.js: bin.js + checksum: 10c0/9d36bdd76202c8116abbe152a00055ccd8a0099cb28fc17c01fa7bb2c8cffb9ca60e2ab0fe5f274ed6c45dc2633d8c39cf7ab050306c231904512ba9da4d8ab1 + languageName: node + linkType: hard + "shebang-command@npm:^2.0.0": version: 2.0.0 resolution: "shebang-command@npm:2.0.0" @@ -12901,6 +13601,16 @@ __metadata: languageName: node linkType: hard +"stream-browserify@npm:^3.0.0": + version: 3.0.0 + resolution: "stream-browserify@npm:3.0.0" + dependencies: + inherits: "npm:~2.0.4" + readable-stream: "npm:^3.5.0" + checksum: 10c0/ec3b975a4e0aa4b3dc5e70ffae3fc8fd29ac725353a14e72f213dff477b00330140ad014b163a8cbb9922dfe90803f81a5ea2b269e1bbfd8bd71511b88f889ad + languageName: node + linkType: hard + "stream-composer@npm:^1.0.2": version: 1.0.2 resolution: "stream-composer@npm:1.0.2" @@ -12910,6 +13620,18 @@ __metadata: languageName: node linkType: hard +"stream-http@npm:^3.2.0": + version: 3.2.0 + resolution: "stream-http@npm:3.2.0" + dependencies: + builtin-status-codes: "npm:^3.0.0" + inherits: "npm:^2.0.4" + readable-stream: "npm:^3.6.0" + xtend: "npm:^4.0.2" + checksum: 10c0/f128fb8076d60cd548f229554b6a1a70c08a04b7b2afd4dbe7811d20f27f7d4112562eb8bce86d72a8691df3b50573228afcf1271e55e81f981536c67498bc41 + languageName: node + linkType: hard + "streamx@npm:^2.12.0, streamx@npm:^2.12.5, streamx@npm:^2.13.2, streamx@npm:^2.14.0": version: 2.22.0 resolution: "streamx@npm:2.22.0" @@ -13026,7 +13748,7 @@ __metadata: languageName: node linkType: hard -"string_decoder@npm:^1.1.1": +"string_decoder@npm:^1.0.0, string_decoder@npm:^1.1.1": version: 1.3.0 resolution: "string_decoder@npm:1.3.0" dependencies: @@ -13228,6 +13950,15 @@ __metadata: languageName: node linkType: hard +"timers-browserify@npm:^2.0.4": + version: 2.0.12 + resolution: "timers-browserify@npm:2.0.12" + dependencies: + setimmediate: "npm:^1.0.4" + checksum: 10c0/98e84db1a685bc8827c117a8bc62aac811ad56a995d07938fc7ed8cdc5bf3777bfe2d4e5da868847194e771aac3749a20f6cdd22091300fe889a76fe214a4641 + languageName: node + linkType: hard + "tinybench@npm:^2.9.0": version: 2.9.0 resolution: "tinybench@npm:2.9.0" @@ -13301,6 +14032,17 @@ __metadata: languageName: node linkType: hard +"to-buffer@npm:^1.2.0, to-buffer@npm:^1.2.1, to-buffer@npm:^1.2.2": + version: 1.2.2 + resolution: "to-buffer@npm:1.2.2" + dependencies: + isarray: "npm:^2.0.5" + safe-buffer: "npm:^5.2.1" + typed-array-buffer: "npm:^1.0.3" + checksum: 10c0/56bc56352f14a2c4a0ab6277c5fc19b51e9534882b98eb068b39e14146591e62fa5b06bf70f7fed1626230463d7e60dca81e815096656e5e01c195c593873d12 + languageName: node + linkType: hard + "to-regex-range@npm:^5.0.1": version: 5.0.1 resolution: "to-regex-range@npm:5.0.1" @@ -13438,6 +14180,13 @@ __metadata: languageName: node linkType: hard +"tty-browserify@npm:0.0.1": + version: 0.0.1 + resolution: "tty-browserify@npm:0.0.1" + checksum: 10c0/5e34883388eb5f556234dae75b08e069b9e62de12bd6d87687f7817f5569430a6dfef550b51dbc961715ae0cd0eb5a059e6e3fc34dc127ea164aa0f9b5bb033d + languageName: node + linkType: hard + "tunnel@npm:^0.0.6": version: 0.0.6 resolution: "tunnel@npm:0.0.6" @@ -13772,6 +14521,16 @@ __metadata: languageName: node linkType: hard +"url@npm:^0.11.4": + version: 0.11.4 + resolution: "url@npm:0.11.4" + dependencies: + punycode: "npm:^1.4.1" + qs: "npm:^6.12.3" + checksum: 10c0/cc93405ae4a9b97a2aa60ca67f1cb1481c0221cb4725a7341d149be5e2f9cfda26fd432d64dbbec693d16593b68b8a46aad8e5eab21f814932134c9d8620c662 + languageName: node + linkType: hard + "use-callback-ref@npm:^1.3.3": version: 1.3.3 resolution: "use-callback-ref@npm:1.3.3" @@ -13821,6 +14580,19 @@ __metadata: languageName: node linkType: hard +"util@npm:^0.12.4, util@npm:^0.12.5": + version: 0.12.5 + resolution: "util@npm:0.12.5" + dependencies: + inherits: "npm:^2.0.3" + is-arguments: "npm:^1.0.4" + is-generator-function: "npm:^1.0.7" + is-typed-array: "npm:^1.1.3" + which-typed-array: "npm:^1.1.2" + checksum: 10c0/c27054de2cea2229a66c09522d0fa1415fb12d861d08523a8846bf2e4cbf0079d4c3f725f09dcb87493549bcbf05f5798dce1688b53c6c17201a45759e7253f3 + languageName: node + linkType: hard + "uuid@npm:13": version: 13.0.0 resolution: "uuid@npm:13.0.0" @@ -13967,6 +14739,18 @@ __metadata: languageName: node linkType: hard +"vite-plugin-node-stdlib-browser@npm:^0.2.1": + version: 0.2.1 + resolution: "vite-plugin-node-stdlib-browser@npm:0.2.1" + dependencies: + "@rollup/plugin-inject": "npm:^5.0.3" + peerDependencies: + node-stdlib-browser: ^1.2.0 + vite: ^2.0.0 || ^3.0.0 || ^4.0.0 + checksum: 10c0/4686bde59d0396d8684433e1a14ddce868dc422f80e306a0c1cb5e86564d9f7c38a67865ca339e4ff57784ec4bada149034038cad6911a2dfcac8debfc9bd20a + languageName: node + linkType: hard + "vite-plugin-singlefile@npm:^2.3.0": version: 2.3.0 resolution: "vite-plugin-singlefile@npm:2.3.0" @@ -14117,6 +14901,13 @@ __metadata: languageName: node linkType: hard +"vm-browserify@npm:^1.0.1": + version: 1.1.2 + resolution: "vm-browserify@npm:1.1.2" + checksum: 10c0/0cc1af6e0d880deb58bc974921320c187f9e0a94f25570fca6b1bd64e798ce454ab87dfd797551b1b0cc1849307421aae0193cedf5f06bdb5680476780ee344b + languageName: node + linkType: hard + "void-elements@npm:3.1.0": version: 3.1.0 resolution: "void-elements@npm:3.1.0" @@ -14316,7 +15107,7 @@ __metadata: languageName: node linkType: hard -"which-typed-array@npm:^1.1.19": +"which-typed-array@npm:^1.1.19, which-typed-array@npm:^1.1.2": version: 1.1.19 resolution: "which-typed-array@npm:1.1.19" dependencies: @@ -14441,7 +15232,7 @@ __metadata: languageName: node linkType: hard -"xtend@npm:~4.0.1": +"xtend@npm:^4.0.2, xtend@npm:~4.0.1": version: 4.0.2 resolution: "xtend@npm:4.0.2" checksum: 10c0/366ae4783eec6100f8a02dff02ac907bf29f9a00b82ac0264b4d8b832ead18306797e283cf19de776538babfdcb2101375ec5646b59f08c52128ac4ab812ed0e From 284a52c23cbbed7b43f9aa4a46836751f675d1e8 Mon Sep 17 00:00:00 2001 From: Timo K Date: Mon, 1 Dec 2025 12:43:17 +0100 Subject: [PATCH 019/748] mvp --- godot/index.html | 6 +- godot/main.ts | 198 ++++++++++-------- src/state/CallViewModel/CallViewModel.ts | 24 ++- .../CallViewModel/localMember/Publisher.ts | 33 ++- .../remoteMembers/Connection.test.ts | 28 ++- .../CallViewModel/remoteMembers/Connection.ts | 29 +-- .../remoteMembers/ConnectionFactory.ts | 2 +- .../remoteMembers/ConnectionManager.test.ts | 52 ++--- .../remoteMembers/ConnectionManager.ts | 39 ++-- .../MatrixLivekitMembers.test.ts | 121 ++++++----- .../remoteMembers/MatrixLivekitMembers.ts | 11 +- .../remoteMembers/integration.test.ts | 4 +- 12 files changed, 296 insertions(+), 251 deletions(-) diff --git a/godot/index.html b/godot/index.html index ff654748d..7d5f96c01 100644 --- a/godot/index.html +++ b/godot/index.html @@ -20,7 +20,7 @@ await window.matrixRTCSdk.join(); console.info("matrixRTCSdk joined "); - // sdk.data$.subscribe((data) => { + // window.matrixRTCSdk.data$.subscribe((data) => { // console.log(data); // const div = document.getElementById("data"); // div.appendChild(document.createTextNode(data)); @@ -36,9 +36,9 @@ - +
diff --git a/godot/main.ts b/godot/main.ts index 98bb49722..ede612cbc 100644 --- a/godot/main.ts +++ b/godot/main.ts @@ -6,7 +6,7 @@ Please see LICENSE in the repository root for full details. */ // import { type InitResult } from "../src/ClientContext"; -import { map, type Observable, of, Subject, switchMap } from "rxjs"; +import { map, type Observable, of, Subject, switchMap, tap } from "rxjs"; import { MatrixRTCSessionEvent } from "matrix-js-sdk/lib/matrixrtc"; import { type TextStreamInfo } from "livekit-client/dist/src/room/types"; import { @@ -36,7 +36,7 @@ interface MatrixRTCSdk { /** @throws on leave errors */ leave: () => void; data$: Observable<{ sender: string; data: string }>; - sendData?: (data: Record) => Promise; + sendData?: (data: unknown) => Promise; } export async function createMatrixRTCSdk(): Promise { logger.info("Hello"); @@ -67,97 +67,115 @@ export async function createMatrixRTCSdk(): Promise { // create data listener const data$ = new Subject<{ sender: string; data: string }>(); - // const lkTextStreamHandlerFunction = async ( - // reader: TextStreamReader, - // participantInfo: { identity: string }, - // livekitRoom: LivekitRoom, - // ): Promise => { - // const info = reader.info; - // console.log( - // `Received text stream from ${participantInfo.identity}\n` + - // ` Topic: ${info.topic}\n` + - // ` Timestamp: ${info.timestamp}\n` + - // ` ID: ${info.id}\n` + - // ` Size: ${info.size}`, // Optional, only available if the stream was sent with `sendText` - // ); + const lkTextStreamHandlerFunction = async ( + reader: TextStreamReader, + participantInfo: { identity: string }, + livekitRoom: LivekitRoom, + ): Promise => { + const info = reader.info; + logger.info( + `Received text stream from ${participantInfo.identity}\n` + + ` Topic: ${info.topic}\n` + + ` Timestamp: ${info.timestamp}\n` + + ` ID: ${info.id}\n` + + ` Size: ${info.size}`, // Optional, only available if the stream was sent with `sendText` + ); - // const participants = callViewModel.livekitRoomItems$.value.find( - // (i) => i.livekitRoom === livekitRoom, - // )?.participants; - // if (participants && participants.includes(participantInfo.identity)) { - // const text = await reader.readAll(); - // console.log(`Received text: ${text}`); - // data$.next({ sender: participantInfo.identity, data: text }); - // } else { - // logger.warn( - // "Received text from unknown participant", - // participantInfo.identity, - // ); - // } - // }; + const participants = callViewModel.livekitRoomItems$.value.find( + (i) => i.livekitRoom === livekitRoom, + )?.participants; + if (participants && participants.includes(participantInfo.identity)) { + const text = await reader.readAll(); + logger.info(`Received text: ${text}`); + data$.next({ sender: participantInfo.identity, data: text }); + } else { + logger.warn( + "Received text from unknown participant", + participantInfo.identity, + ); + } + }; - // const livekitRoomItemsSub = callViewModel.livekitRoomItems$ - // .pipe(currentAndPrev) - // .subscribe({ - // next: ({ prev, current }) => { - // const prevRooms = prev.map((i) => i.livekitRoom); - // const currentRooms = current.map((i) => i.livekitRoom); - // const addedRooms = currentRooms.filter((r) => !prevRooms.includes(r)); - // const removedRooms = prevRooms.filter((r) => !currentRooms.includes(r)); - // addedRooms.forEach((r) => - // r.registerTextStreamHandler( - // TEXT_LK_TOPIC, - // (reader, participantInfo) => - // void lkTextStreamHandlerFunction(reader, participantInfo, r), - // ), - // ); - // removedRooms.forEach((r) => - // r.unregisterTextStreamHandler(TEXT_LK_TOPIC), - // ); - // }, - // complete: () => { - // logger.info("Livekit room items subscription completed"); - // for (const item of callViewModel.livekitRoomItems$.value) { - // logger.info("unregistering room item from room", item.url); - // item.livekitRoom.unregisterTextStreamHandler(TEXT_LK_TOPIC); - // } - // }, - // }); + const livekitRoomItemsSub = callViewModel.livekitRoomItems$ + .pipe( + tap((beforecurrentAndPrev) => { + logger.info( + `LiveKit room items updated: ${beforecurrentAndPrev.length}`, + beforecurrentAndPrev, + ); + }), + currentAndPrev, + tap((aftercurrentAndPrev) => { + logger.info( + `LiveKit room items updated: ${aftercurrentAndPrev.current.length}, ${aftercurrentAndPrev.prev.length}`, + aftercurrentAndPrev, + ); + }), + ) + .subscribe({ + next: ({ prev, current }) => { + const prevRooms = prev.map((i) => i.livekitRoom); + const currentRooms = current.map((i) => i.livekitRoom); + const addedRooms = currentRooms.filter((r) => !prevRooms.includes(r)); + const removedRooms = prevRooms.filter((r) => !currentRooms.includes(r)); + addedRooms.forEach((r) => { + logger.info(`Registering text stream handler for room `); + r.registerTextStreamHandler( + TEXT_LK_TOPIC, + (reader, participantInfo) => + void lkTextStreamHandlerFunction(reader, participantInfo, r), + ); + }); + removedRooms.forEach((r) => { + logger.info(`Unregistering text stream handler for room `); + r.unregisterTextStreamHandler(TEXT_LK_TOPIC); + }); + }, + complete: () => { + logger.info("Livekit room items subscription completed"); + for (const item of callViewModel.livekitRoomItems$.value) { + logger.info("unregistering room item from room", item.url); + item.livekitRoom.unregisterTextStreamHandler(TEXT_LK_TOPIC); + } + }, + }); // create sendData function - // const sendFn: Behavior<(data: string) => Promise> = - // scope.behavior( - // callViewModel.localMatrixLivekitMember$.pipe( - // switchMap((m) => { - // if (!m) - // return of((data: string): never => { - // throw Error("local membership not yet ready."); - // }); - // return m.participant$.pipe( - // map((p) => { - // if (p === null) { - // return (data: string): never => { - // throw Error("local participant not yet ready to send data."); - // }; - // } else { - // return async (data: string): Promise => - // p.sendText(data, { topic: TEXT_LK_TOPIC }); - // } - // }), - // ); - // }), - // ), - // ); + const sendFn: Behavior<(data: string) => Promise> = + scope.behavior( + callViewModel.localmatrixLivekitMembers$.pipe( + switchMap((m) => { + if (!m) + return of((data: string): never => { + throw Error("local membership not yet ready."); + }); + return m.participant$.pipe( + map((p) => { + if (p === null) { + return (data: string): never => { + throw Error("local participant not yet ready to send data."); + }; + } else { + return async (data: string): Promise => + p.sendText(data, { topic: TEXT_LK_TOPIC }); + } + }), + ); + }), + ), + ); - // const sendData = async (data: Record): Promise => { - // const dataString = JSON.stringify(data); - // try { - // const info = await sendFn.value(dataString); - // logger.info(`Sent text with stream ID: ${info.id}`); - // } catch (e) { - // console.error("failed sending: ", dataString, e); - // } - // }; + const sendData = async (data: unknown): Promise => { + const dataString = JSON.stringify(data); + logger.info("try sending: ", dataString); + try { + await Promise.resolve(); + const info = await sendFn.value(dataString); + logger.info(`Sent text with stream ID: ${info.id}`); + } catch (e) { + logger.error("failed sending: ", dataString, e); + } + }; // after hangup gets called const leaveSubs = callViewModel.leave$.subscribe(() => { @@ -202,9 +220,9 @@ export async function createMatrixRTCSdk(): Promise { leave: (): void => { callViewModel.hangup(); leaveSubs.unsubscribe(); - // livekitRoomItemsSub.unsubscribe(); + livekitRoomItemsSub.unsubscribe(); }, data$, - // sendData, + sendData, }; } diff --git a/src/state/CallViewModel/CallViewModel.ts b/src/state/CallViewModel/CallViewModel.ts index 253eb05ed..a4738f77f 100644 --- a/src/state/CallViewModel/CallViewModel.ts +++ b/src/state/CallViewModel/CallViewModel.ts @@ -264,7 +264,7 @@ export interface CallViewModel { livekitRoomItems$: Behavior; /** use the layout instead, this is just for the godot export. */ userMedia$: Behavior; - localMatrixLivekitMember$: Behavior; + localmatrixLivekitMembers$: Behavior; /** List of participants raising their hand */ handsRaised$: Behavior>; /** List of reactions. Keys are: membership.membershipId (currently predefined as: `${membershipEvent.userId}:${membershipEvent.deviceId}`)*/ @@ -449,7 +449,7 @@ export function createCallViewModel$( logger: logger, }); - const matrixLivekitMembers$ = createMatrixLivekitMembers$({ + const { matrixLivekitMembers$ } = createMatrixLivekitMembers$({ scope: scope, membershipsWithTransport$: membershipsAndTransports.membershipsWithTransport$, @@ -515,7 +515,7 @@ export function createCallViewModel$( userId: userId, }; - const localMatrixLivekitMember$: Behavior = + const localmatrixLivekitMembers$: Behavior = scope.behavior( localRtcMembership$.pipe( switchMap((membership) => { @@ -607,8 +607,11 @@ export function createCallViewModel$( const reconnecting$ = localMembership.reconnecting$; const pretendToBeDisconnected$ = reconnecting$; - const audioParticipants$ = scope.behavior( + const livekitRoomItems$ = scope.behavior( matrixLivekitMembers$.pipe( + tap((val) => { + logger.debug("matrixLivekitMembers$ updated", val.value); + }), switchMap((membersWithEpoch) => { const members = membersWithEpoch.value; const a$ = combineLatest( @@ -649,6 +652,12 @@ export function createCallViewModel$( return acc; }, []), ), + tap((val) => { + logger.debug( + "livekitRoomItems$ updated", + val.map((v) => v.url), + ); + }), ), [], ); @@ -676,7 +685,7 @@ export function createCallViewModel$( */ const userMedia$ = scope.behavior( combineLatest([ - localMatrixLivekitMember$, + localmatrixLivekitMembers$, matrixLivekitMembers$, duplicateTiles.value$, ]).pipe( @@ -1489,8 +1498,7 @@ export function createCallViewModel$( ), participantCount$: participantCount$, - livekitRoomItems$: audioParticipants$, - + livekitRoomItems$, handsRaised$: handsRaised$, reactions$: reactions$, joinSoundEffect$: joinSoundEffect$, @@ -1510,7 +1518,7 @@ export function createCallViewModel$( pip$: pip$, layout$: layout$, userMedia$, - localMatrixLivekitMember$, + localmatrixLivekitMembers$, tileStoreGeneration$: tileStoreGeneration$, showSpotlightIndicators$: showSpotlightIndicators$, showSpeakingIndicators$: showSpeakingIndicators$, diff --git a/src/state/CallViewModel/localMember/Publisher.ts b/src/state/CallViewModel/localMember/Publisher.ts index 11f35424a..2508637ee 100644 --- a/src/state/CallViewModel/localMember/Publisher.ts +++ b/src/state/CallViewModel/localMember/Publisher.ts @@ -56,15 +56,15 @@ export class Publisher { devices: MediaDevices, private readonly muteStates: MuteStates, trackerProcessorState$: Behavior, - private logger?: Logger, + private logger: Logger, ) { - this.logger?.info("[PublishConnection] Create LiveKit room"); + this.logger.info("[PublishConnection] Create LiveKit room"); const { controlledAudioDevices } = getUrlParams(); const room = connection.livekitRoom; room.setE2EEEnabled(room.options.e2ee !== undefined)?.catch((e: Error) => { - this.logger?.error("Failed to set E2EE enabled on room", e); + this.logger.error("Failed to set E2EE enabled on room", e); }); // Setup track processor syncing (blur) @@ -74,7 +74,7 @@ export class Publisher { this.workaroundRestartAudioInputTrackChrome(devices, scope); this.scope.onEnd(() => { - this.logger?.info( + this.logger.info( "[PublishConnection] Scope ended -> stop publishing all tracks", ); void this.stopPublishing(); @@ -132,13 +132,14 @@ export class Publisher { video, }) .catch((error) => { - this.logger?.error("Failed to create tracks", error); + this.logger.error("Failed to create tracks", error); })) ?? []; } return this.tracks; } public async startPublishing(): Promise { + this.logger.info("Start publishing"); const lkRoom = this.connection.livekitRoom; const { promise, resolve, reject } = Promise.withResolvers(); const sub = this.connection.state$.subscribe((s) => { @@ -150,7 +151,7 @@ export class Publisher { reject(new Error("Failed to connect to LiveKit server")); break; default: - this.logger?.info("waiting for connection: ", s.state); + this.logger.info("waiting for connection: ", s.state); } }); try { @@ -160,12 +161,14 @@ export class Publisher { } finally { sub.unsubscribe(); } + this.logger.info("publish ", this.tracks.length, "tracks"); for (const track of this.tracks) { // TODO: handle errors? Needs the signaling connection to be up, but it has some retries internally // with a timeout. await lkRoom.localParticipant.publishTrack(track).catch((error) => { - this.logger?.error("Failed to publish track", error); + this.logger.error("Failed to publish track", error); }); + this.logger.info("published track ", track.kind, track.id); // TODO: check if the connection is still active? and break the loop if not? } @@ -229,7 +232,7 @@ export class Publisher { .getTrackPublication(Track.Source.Microphone) ?.audioTrack?.restartTrack() .catch((e) => { - this.logger?.error(`Failed to restart audio device track`, e); + this.logger.error(`Failed to restart audio device track`, e); }); } }); @@ -249,7 +252,7 @@ export class Publisher { selected$.pipe(scope.bind()).subscribe((device) => { if (lkRoom.state != LivekitConnectionState.Connected) return; // if (this.connectionState$.value !== ConnectionState.Connected) return; - this.logger?.info( + this.logger.info( "[LivekitRoom] syncDevice room.getActiveDevice(kind) !== d.id :", lkRoom.getActiveDevice(kind), " !== ", @@ -262,7 +265,7 @@ export class Publisher { lkRoom .switchActiveDevice(kind, device.id) .catch((e: Error) => - this.logger?.error( + this.logger.error( `Failed to sync ${kind} device with LiveKit`, e, ), @@ -287,10 +290,7 @@ export class Publisher { try { await lkRoom.localParticipant.setMicrophoneEnabled(desired); } catch (e) { - this.logger?.error( - "Failed to update LiveKit audio input mute state", - e, - ); + this.logger.error("Failed to update LiveKit audio input mute state", e); } return lkRoom.localParticipant.isMicrophoneEnabled; }); @@ -298,10 +298,7 @@ export class Publisher { try { await lkRoom.localParticipant.setCameraEnabled(desired); } catch (e) { - this.logger?.error( - "Failed to update LiveKit video input mute state", - e, - ); + this.logger.error("Failed to update LiveKit video input mute state", e); } return lkRoom.localParticipant.isCameraEnabled; }); diff --git a/src/state/CallViewModel/remoteMembers/Connection.test.ts b/src/state/CallViewModel/remoteMembers/Connection.test.ts index 3f58bcf6d..f719e86bf 100644 --- a/src/state/CallViewModel/remoteMembers/Connection.test.ts +++ b/src/state/CallViewModel/remoteMembers/Connection.test.ts @@ -382,17 +382,15 @@ describe("Publishing participants observations", () => { const bobIsAPublisher = Promise.withResolvers(); const danIsAPublisher = Promise.withResolvers(); const observedPublishers: PublishingParticipant[][] = []; - const s = connection.remoteParticipantsWithTracks$.subscribe( - (publishers) => { - observedPublishers.push(publishers); - if (publishers.some((p) => p.identity === "@bob:example.org:DEV111")) { - bobIsAPublisher.resolve(); - } - if (publishers.some((p) => p.identity === "@dan:example.org:DEV333")) { - danIsAPublisher.resolve(); - } - }, - ); + const s = connection.remoteParticipants$.subscribe((publishers) => { + observedPublishers.push(publishers); + if (publishers.some((p) => p.identity === "@bob:example.org:DEV111")) { + bobIsAPublisher.resolve(); + } + if (publishers.some((p) => p.identity === "@dan:example.org:DEV333")) { + danIsAPublisher.resolve(); + } + }); onTestFinished(() => s.unsubscribe()); // The publishingParticipants$ observable is derived from the current members of the // livekitRoom and the rtc membership in order to publish the members that are publishing @@ -437,11 +435,9 @@ describe("Publishing participants observations", () => { const connection = setupRemoteConnection(); let observedPublishers: PublishingParticipant[][] = []; - const s = connection.remoteParticipantsWithTracks$.subscribe( - (publishers) => { - observedPublishers.push(publishers); - }, - ); + const s = connection.remoteParticipants$.subscribe((publishers) => { + observedPublishers.push(publishers); + }); onTestFinished(() => s.unsubscribe()); let participants: RemoteParticipant[] = [ diff --git a/src/state/CallViewModel/remoteMembers/Connection.ts b/src/state/CallViewModel/remoteMembers/Connection.ts index c17fae2b6..fd75e5512 100644 --- a/src/state/CallViewModel/remoteMembers/Connection.ts +++ b/src/state/CallViewModel/remoteMembers/Connection.ts @@ -19,7 +19,7 @@ import { RoomEvent, } from "livekit-client"; import { type LivekitTransport } from "matrix-js-sdk/lib/matrixrtc"; -import { BehaviorSubject, map, type Observable } from "rxjs"; +import { BehaviorSubject, type Observable } from "rxjs"; import { type Logger } from "matrix-js-sdk/lib/logger"; import { @@ -146,6 +146,10 @@ export class Connection { transport: this.transport, livekitConnectionState$: connectionStateObserver(this.livekitRoom), }); + this.logger.info( + "Connected to LiveKit room", + this.transport.livekit_service_url, + ); } catch (error) { this.logger.debug(`Failed to connect to LiveKit room: ${error}`); this._state$.next({ @@ -189,9 +193,7 @@ export class Connection { * This is derived from `participantsIncludingSubscribers$` and `remoteTransports$`. * It filters the participants to only those that are associated with a membership that claims to publish on this connection. */ - public readonly remoteParticipantsWithTracks$: Behavior< - PublishingParticipant[] - >; + public readonly remoteParticipants$: Behavior; /** * The media transport to connect to. @@ -213,7 +215,7 @@ export class Connection { public constructor(opts: ConnectionOpts, logger: Logger) { this.logger = logger.getChild("[Connection]"); this.logger.info( - `[Connection] Creating new connection to ${opts.transport.livekit_service_url} ${opts.transport.livekit_alias}`, + `Creating new connection to ${opts.transport.livekit_service_url} ${opts.transport.livekit_alias}`, ); const { transport, client, scope } = opts; @@ -223,20 +225,21 @@ export class Connection { // REMOTE participants with track!!! // this.remoteParticipantsWithTracks$ - this.remoteParticipantsWithTracks$ = scope.behavior( + this.remoteParticipants$ = scope.behavior( // only tracks remote participants connectedParticipantsObserver(this.livekitRoom, { additionalRoomEvents: [ RoomEvent.TrackPublished, RoomEvent.TrackUnpublished, ], - }).pipe( - map((participants) => { - return participants.filter( - (participant) => participant.getTrackPublications().length > 0, - ); - }), - ), + }), + // .pipe( + // map((participants) => { + // return participants.filter( + // (participant) => participant.getTrackPublications().length > 0, + // ); + // }), + // ) [], ); diff --git a/src/state/CallViewModel/remoteMembers/ConnectionFactory.ts b/src/state/CallViewModel/remoteMembers/ConnectionFactory.ts index f58fcb764..0fb0b5a79 100644 --- a/src/state/CallViewModel/remoteMembers/ConnectionFactory.ts +++ b/src/state/CallViewModel/remoteMembers/ConnectionFactory.ts @@ -13,7 +13,7 @@ import { type BaseKeyProvider, } from "livekit-client"; import { type Logger } from "matrix-js-sdk/lib/logger"; -import E2EEWorker from "livekit-client/e2ee-worker?worker"; +import E2EEWorker from "livekit-client/e2ee-worker?worker&inline"; import { type ObservableScope } from "../../ObservableScope.ts"; import { Connection } from "./Connection.ts"; diff --git a/src/state/CallViewModel/remoteMembers/ConnectionManager.test.ts b/src/state/CallViewModel/remoteMembers/ConnectionManager.test.ts index 484a44e74..b50762854 100644 --- a/src/state/CallViewModel/remoteMembers/ConnectionManager.test.ts +++ b/src/state/CallViewModel/remoteMembers/ConnectionManager.test.ts @@ -289,47 +289,47 @@ describe("connectionManagerData$ stream", () => { a: expect.toSatisfy((e) => { const data: ConnectionManagerData = e.value; expect(data.getConnections().length).toBe(2); - expect(data.getParticipantForTransport(TRANSPORT_1).length).toBe(0); - expect(data.getParticipantForTransport(TRANSPORT_2).length).toBe(0); + expect(data.getParticipantsForTransport(TRANSPORT_1).length).toBe(0); + expect(data.getParticipantsForTransport(TRANSPORT_2).length).toBe(0); return true; }), b: expect.toSatisfy((e) => { const data: ConnectionManagerData = e.value; expect(data.getConnections().length).toBe(2); - expect(data.getParticipantForTransport(TRANSPORT_1).length).toBe(1); - expect(data.getParticipantForTransport(TRANSPORT_2).length).toBe(0); - expect(data.getParticipantForTransport(TRANSPORT_1)[0].identity).toBe( - "user1A", - ); + expect(data.getParticipantsForTransport(TRANSPORT_1).length).toBe(1); + expect(data.getParticipantsForTransport(TRANSPORT_2).length).toBe(0); + expect( + data.getParticipantsForTransport(TRANSPORT_1)[0].identity, + ).toBe("user1A"); return true; }), c: expect.toSatisfy((e) => { const data: ConnectionManagerData = e.value; expect(data.getConnections().length).toBe(2); - expect(data.getParticipantForTransport(TRANSPORT_1).length).toBe(1); - expect(data.getParticipantForTransport(TRANSPORT_2).length).toBe(1); - expect(data.getParticipantForTransport(TRANSPORT_1)[0].identity).toBe( - "user1A", - ); - expect(data.getParticipantForTransport(TRANSPORT_2)[0].identity).toBe( - "user2A", - ); + expect(data.getParticipantsForTransport(TRANSPORT_1).length).toBe(1); + expect(data.getParticipantsForTransport(TRANSPORT_2).length).toBe(1); + expect( + data.getParticipantsForTransport(TRANSPORT_1)[0].identity, + ).toBe("user1A"); + expect( + data.getParticipantsForTransport(TRANSPORT_2)[0].identity, + ).toBe("user2A"); return true; }), d: expect.toSatisfy((e) => { const data: ConnectionManagerData = e.value; expect(data.getConnections().length).toBe(2); - expect(data.getParticipantForTransport(TRANSPORT_1).length).toBe(2); - expect(data.getParticipantForTransport(TRANSPORT_2).length).toBe(1); - expect(data.getParticipantForTransport(TRANSPORT_1)[0].identity).toBe( - "user1A", - ); - expect(data.getParticipantForTransport(TRANSPORT_1)[1].identity).toBe( - "user1B", - ); - expect(data.getParticipantForTransport(TRANSPORT_2)[0].identity).toBe( - "user2A", - ); + expect(data.getParticipantsForTransport(TRANSPORT_1).length).toBe(2); + expect(data.getParticipantsForTransport(TRANSPORT_2).length).toBe(1); + expect( + data.getParticipantsForTransport(TRANSPORT_1)[0].identity, + ).toBe("user1A"); + expect( + data.getParticipantsForTransport(TRANSPORT_1)[1].identity, + ).toBe("user1B"); + expect( + data.getParticipantsForTransport(TRANSPORT_2)[0].identity, + ).toBe("user2A"); return true; }), }); diff --git a/src/state/CallViewModel/remoteMembers/ConnectionManager.ts b/src/state/CallViewModel/remoteMembers/ConnectionManager.ts index d9a0380ea..bd07cfa13 100644 --- a/src/state/CallViewModel/remoteMembers/ConnectionManager.ts +++ b/src/state/CallViewModel/remoteMembers/ConnectionManager.ts @@ -24,7 +24,10 @@ import { type ConnectionFactory } from "./ConnectionFactory.ts"; export class ConnectionManagerData { private readonly store: Map< string, - [Connection, (LocalParticipant | RemoteParticipant)[]] + { + connection: Connection; + participants: (LocalParticipant | RemoteParticipant)[]; + } > = new Map(); public constructor() {} @@ -36,9 +39,9 @@ export class ConnectionManagerData { const key = this.getKey(connection.transport); const existing = this.store.get(key); if (!existing) { - this.store.set(key, [connection, participants]); + this.store.set(key, { connection, participants }); } else { - existing[1].push(...participants); + existing.participants.push(...participants); } } @@ -47,25 +50,26 @@ export class ConnectionManagerData { } public getConnections(): Connection[] { - return Array.from(this.store.values()).map(([connection]) => connection); + return Array.from(this.store.values()).map(({ connection }) => connection); } public getConnectionForTransport( transport: LivekitTransport, ): Connection | null { - return this.store.get(this.getKey(transport))?.[0] ?? null; + return this.store.get(this.getKey(transport))?.connection ?? null; } - public getParticipantForTransport( + public getParticipantsForTransport( transport: LivekitTransport, ): (LocalParticipant | RemoteParticipant)[] { const key = transport.livekit_service_url + "|" + transport.livekit_alias; const existing = this.store.get(key); if (existing) { - return existing[1]; + return existing.participants; } return []; } + /** * Get all connections where the given participant is publishing. * In theory, there could be several connections where the same participant is publishing but with @@ -76,8 +80,12 @@ export class ConnectionManagerData { participantId: ParticipantId, ): Connection[] { const connections: Connection[] = []; - for (const [connection, participants] of this.store.values()) { - if (participants.some((p) => p.identity === participantId)) { + for (const { connection, participants } of this.store.values()) { + if ( + participants.some( + (participant) => participant?.identity === participantId, + ) + ) { connections.push(connection); } } @@ -183,23 +191,24 @@ export function createConnectionManager$({ const epoch = connections.epoch; // Map the connections to list of {connection, participants}[] - const listOfConnectionsWithPublishingParticipants = - connections.value.map((connection) => { - return connection.remoteParticipantsWithTracks$.pipe( + const listOfConnectionsWithParticipants = connections.value.map( + (connection) => { + return connection.remoteParticipants$.pipe( map((participants) => ({ connection, participants, })), ); - }); + }, + ); // probably not required - if (listOfConnectionsWithPublishingParticipants.length === 0) { + if (listOfConnectionsWithParticipants.length === 0) { return of(new Epoch(new ConnectionManagerData(), epoch)); } // combineLatest the several streams into a single stream with the ConnectionManagerData - return combineLatest(listOfConnectionsWithPublishingParticipants).pipe( + return combineLatest(listOfConnectionsWithParticipants).pipe( map( (lists) => new Epoch( diff --git a/src/state/CallViewModel/remoteMembers/MatrixLivekitMembers.test.ts b/src/state/CallViewModel/remoteMembers/MatrixLivekitMembers.test.ts index e675f7230..7547a68be 100644 --- a/src/state/CallViewModel/remoteMembers/MatrixLivekitMembers.test.ts +++ b/src/state/CallViewModel/remoteMembers/MatrixLivekitMembers.test.ts @@ -91,7 +91,7 @@ test("should signal participant not yet connected to livekit", () => { }), ); - const matrixLivekitMember$ = createMatrixLivekitMembers$({ + const { matrixLivekitMembers$ } = createMatrixLivekitMembers$({ scope: testScope, membershipsWithTransport$: testScope.behavior(membershipsWithTransport$), connectionManager: { @@ -99,21 +99,24 @@ test("should signal participant not yet connected to livekit", () => { } as unknown as IConnectionManager, }); - expectObservable(matrixLivekitMember$.pipe(map((e) => e.value))).toBe("a", { - a: expect.toSatisfy((data: MatrixLivekitMember[]) => { - expect(data.length).toEqual(1); - expectObservable(data[0].membership$).toBe("a", { - a: bobMembership, - }); - expectObservable(data[0].participant$).toBe("a", { - a: null, - }); - expectObservable(data[0].connection$).toBe("a", { - a: null, - }); - return true; - }), - }); + expectObservable(matrixLivekitMembers$.pipe(map((e) => e.value))).toBe( + "a", + { + a: expect.toSatisfy((data: MatrixLivekitMember[]) => { + expect(data.length).toEqual(1); + expectObservable(data[0].membership$).toBe("a", { + a: bobMembership, + }); + expectObservable(data[0].participant$).toBe("a", { + a: null, + }); + expectObservable(data[0].connection$).toBe("a", { + a: null, + }); + return true; + }), + }, + ); }); }); @@ -171,7 +174,7 @@ test("should signal participant on a connection that is publishing", () => { }), ); - const matrixLivekitMember$ = createMatrixLivekitMembers$({ + const { matrixLivekitMembers$ } = createMatrixLivekitMembers$({ scope: testScope, membershipsWithTransport$: testScope.behavior(membershipsWithTransport$), connectionManager: { @@ -179,25 +182,28 @@ test("should signal participant on a connection that is publishing", () => { } as unknown as IConnectionManager, }); - expectObservable(matrixLivekitMember$.pipe(map((e) => e.value))).toBe("a", { - a: expect.toSatisfy((data: MatrixLivekitMember[]) => { - expect(data.length).toEqual(1); - expectObservable(data[0].membership$).toBe("a", { - a: bobMembership, - }); - expectObservable(data[0].participant$).toBe("a", { - a: expect.toSatisfy((participant) => { - expect(participant).toBeDefined(); - expect(participant!.identity).toEqual(bobParticipantId); - return true; - }), - }); - expectObservable(data[0].connection$).toBe("a", { - a: connection, - }); - return true; - }), - }); + expectObservable(matrixLivekitMembers$.pipe(map((e) => e.value))).toBe( + "a", + { + a: expect.toSatisfy((data: MatrixLivekitMember[]) => { + expect(data.length).toEqual(1); + expectObservable(data[0].membership$).toBe("a", { + a: bobMembership, + }); + expectObservable(data[0].participant$).toBe("a", { + a: expect.toSatisfy((participant) => { + expect(participant).toBeDefined(); + expect(participant!.identity).toEqual(bobParticipantId); + return true; + }), + }); + expectObservable(data[0].connection$).toBe("a", { + a: connection, + }); + return true; + }), + }, + ); }); }); @@ -222,7 +228,7 @@ test("should signal participant on a connection that is not publishing", () => { }), ); - const matrixLivekitMember$ = createMatrixLivekitMembers$({ + const { matrixLivekitMembers$ } = createMatrixLivekitMembers$({ scope: testScope, membershipsWithTransport$: testScope.behavior(membershipsWithTransport$), connectionManager: { @@ -230,21 +236,24 @@ test("should signal participant on a connection that is not publishing", () => { } as unknown as IConnectionManager, }); - expectObservable(matrixLivekitMember$.pipe(map((e) => e.value))).toBe("a", { - a: expect.toSatisfy((data: MatrixLivekitMember[]) => { - expect(data.length).toEqual(1); - expectObservable(data[0].membership$).toBe("a", { - a: bobMembership, - }); - expectObservable(data[0].participant$).toBe("a", { - a: null, - }); - expectObservable(data[0].connection$).toBe("a", { - a: connection, - }); - return true; - }), - }); + expectObservable(matrixLivekitMembers$.pipe(map((e) => e.value))).toBe( + "a", + { + a: expect.toSatisfy((data: MatrixLivekitMember[]) => { + expect(data.length).toEqual(1); + expectObservable(data[0].membership$).toBe("a", { + a: bobMembership, + }); + expectObservable(data[0].participant$).toBe("a", { + a: null, + }); + expectObservable(data[0].connection$).toBe("a", { + a: connection, + }); + return true; + }), + }, + ); }); }); @@ -283,7 +292,7 @@ describe("Publication edge case", () => { }), ); - const matrixLivekitMember$ = createMatrixLivekitMembers$({ + const { matrixLivekitMembers$ } = createMatrixLivekitMembers$({ scope: testScope, membershipsWithTransport$: testScope.behavior( membershipsWithTransport$, @@ -293,7 +302,7 @@ describe("Publication edge case", () => { } as unknown as IConnectionManager, }); - expectObservable(matrixLivekitMember$.pipe(map((e) => e.value))).toBe( + expectObservable(matrixLivekitMembers$.pipe(map((e) => e.value))).toBe( "a", { a: expect.toSatisfy((data: MatrixLivekitMember[]) => { @@ -349,7 +358,7 @@ describe("Publication edge case", () => { }), ); - const matrixLivekitMember$ = createMatrixLivekitMembers$({ + const { matrixLivekitMembers$ } = createMatrixLivekitMembers$({ scope: testScope, membershipsWithTransport$: testScope.behavior( membershipsWithTransport$, @@ -359,7 +368,7 @@ describe("Publication edge case", () => { } as unknown as IConnectionManager, }); - expectObservable(matrixLivekitMember$.pipe(map((e) => e.value))).toBe( + expectObservable(matrixLivekitMembers$.pipe(map((e) => e.value))).toBe( "a", { a: expect.toSatisfy((data: MatrixLivekitMember[]) => { diff --git a/src/state/CallViewModel/remoteMembers/MatrixLivekitMembers.ts b/src/state/CallViewModel/remoteMembers/MatrixLivekitMembers.ts index 2f1526308..72e2883a2 100644 --- a/src/state/CallViewModel/remoteMembers/MatrixLivekitMembers.ts +++ b/src/state/CallViewModel/remoteMembers/MatrixLivekitMembers.ts @@ -61,12 +61,12 @@ export function createMatrixLivekitMembers$({ scope, membershipsWithTransport$, connectionManager, -}: Props): Behavior> { +}: Props): { matrixLivekitMembers$: Behavior> } { /** * Stream of all the call members and their associated livekit data (if available). */ - return scope.behavior( + const matrixLivekitMembers$ = scope.behavior( combineLatest([ membershipsWithTransport$, connectionManager.connectionManagerData$, @@ -91,7 +91,7 @@ export function createMatrixLivekitMembers$({ const participantId = /*membership.membershipID*/ `${membership.userId}:${membership.deviceId}`; const participants = transport - ? managerData.getParticipantForTransport(transport) + ? managerData.getParticipantsForTransport(transport) : []; const participant = participants.find((p) => p.identity == participantId) ?? null; @@ -121,6 +121,11 @@ export function createMatrixLivekitMembers$({ ), ), ); + return { + matrixLivekitMembers$, + // TODO add only publishing participants... maybe. disucss at least + // scope.behavior(matrixLivekitMembers$.pipe(map((items) => items.value.map((i)=>{ i.})))) + }; } // TODO add back in the callviewmodel pauseWhen(this.pretendToBeDisconnected$) diff --git a/src/state/CallViewModel/remoteMembers/integration.test.ts b/src/state/CallViewModel/remoteMembers/integration.test.ts index e3aa6be8d..cafffb384 100644 --- a/src/state/CallViewModel/remoteMembers/integration.test.ts +++ b/src/state/CallViewModel/remoteMembers/integration.test.ts @@ -124,14 +124,14 @@ test("bob, carl, then bob joining no tracks yet", () => { logger: logger, }); - const matrixLivekitItems$ = createMatrixLivekitMembers$({ + const { matrixLivekitMembers$ } = createMatrixLivekitMembers$({ scope: testScope, membershipsWithTransport$: membershipsAndTransports.membershipsWithTransport$, connectionManager, }); - expectObservable(matrixLivekitItems$).toBe(vMarble, { + expectObservable(matrixLivekitMembers$).toBe(vMarble, { a: expect.toSatisfy((e: Epoch) => { const items = e.value; expect(items.length).toBe(1); From 0664af0f1b3ef694c7733881bcca1195f197c0c9 Mon Sep 17 00:00:00 2001 From: Timo K Date: Mon, 1 Dec 2025 13:49:33 +0100 Subject: [PATCH 020/748] log cleanup and expose members$ --- godot/index.html | 39 ++++++++++++++++--- godot/main.ts | 5 ++- src/state/CallViewModel/CallViewModel.ts | 23 ++++++++--- .../CallViewModel/localMember/Publisher.ts | 6 +-- .../remoteMembers/ConnectionFactory.ts | 1 + 5 files changed, 58 insertions(+), 16 deletions(-) diff --git a/godot/index.html b/godot/index.html index 7d5f96c01..39bcf4842 100644 --- a/godot/index.html +++ b/godot/index.html @@ -4,6 +4,7 @@ Godot MatrixRTC Widget + @@ -39,6 +65,7 @@ +
diff --git a/godot/main.ts b/godot/main.ts index ede612cbc..c5ee29a83 100644 --- a/godot/main.ts +++ b/godot/main.ts @@ -30,12 +30,14 @@ import { widget, } from "./helper"; import { ElementWidgetActions } from "../src/widget"; +import { type MatrixLivekitMember } from "../src/state/CallViewModel/remoteMembers/MatrixLivekitMembers"; interface MatrixRTCSdk { join: () => LocalMemberConnectionState; /** @throws on leave errors */ leave: () => void; data$: Observable<{ sender: string; data: string }>; + members$: Behavior; sendData?: (data: unknown) => Promise; } export async function createMatrixRTCSdk(): Promise { @@ -143,7 +145,7 @@ export async function createMatrixRTCSdk(): Promise { // create sendData function const sendFn: Behavior<(data: string) => Promise> = scope.behavior( - callViewModel.localmatrixLivekitMembers$.pipe( + callViewModel.localMatrixLivekitMember$.pipe( switchMap((m) => { if (!m) return of((data: string): never => { @@ -223,6 +225,7 @@ export async function createMatrixRTCSdk(): Promise { livekitRoomItemsSub.unsubscribe(); }, data$, + members$: callViewModel.matrixLivekitMembers$, sendData, }; } diff --git a/src/state/CallViewModel/CallViewModel.ts b/src/state/CallViewModel/CallViewModel.ts index a4738f77f..86def81e0 100644 --- a/src/state/CallViewModel/CallViewModel.ts +++ b/src/state/CallViewModel/CallViewModel.ts @@ -264,7 +264,8 @@ export interface CallViewModel { livekitRoomItems$: Behavior; /** use the layout instead, this is just for the godot export. */ userMedia$: Behavior; - localmatrixLivekitMembers$: Behavior; + matrixLivekitMembers$: Behavior; + localMatrixLivekitMember$: Behavior; /** List of participants raising their hand */ handsRaised$: Behavior>; /** List of reactions. Keys are: membership.membershipId (currently predefined as: `${membershipEvent.userId}:${membershipEvent.deviceId}`)*/ @@ -446,7 +447,7 @@ export function createCallViewModel$( }, ), ), - logger: logger, + logger, }); const { matrixLivekitMembers$ } = createMatrixLivekitMembers$({ @@ -488,6 +489,9 @@ export function createCallViewModel$( mediaDevices, muteStates, trackProcessorState$, + logger.getChild( + "[Publisher " + connection.transport.livekit_service_url + "]", + ), ); }, connectionManager: connectionManager, @@ -515,7 +519,7 @@ export function createCallViewModel$( userId: userId, }; - const localmatrixLivekitMembers$: Behavior = + const localMatrixLivekitMember$: Behavior = scope.behavior( localRtcMembership$.pipe( switchMap((membership) => { @@ -685,7 +689,7 @@ export function createCallViewModel$( */ const userMedia$ = scope.behavior( combineLatest([ - localmatrixLivekitMembers$, + localMatrixLivekitMember$, matrixLivekitMembers$, duplicateTiles.value$, ]).pipe( @@ -1518,7 +1522,16 @@ export function createCallViewModel$( pip$: pip$, layout$: layout$, userMedia$, - localmatrixLivekitMembers$, + localMatrixLivekitMember$, + matrixLivekitMembers$: scope.behavior( + matrixLivekitMembers$.pipe( + // TODO flatten this so its not a obs of obs. + map((members) => members.value), + tap((v) => { + logger.debug("matrixLivekitMembers$ updated (exported)", v); + }), + ), + ), tileStoreGeneration$: tileStoreGeneration$, showSpotlightIndicators$: showSpotlightIndicators$, showSpeakingIndicators$: showSpeakingIndicators$, diff --git a/src/state/CallViewModel/localMember/Publisher.ts b/src/state/CallViewModel/localMember/Publisher.ts index 2508637ee..51082f384 100644 --- a/src/state/CallViewModel/localMember/Publisher.ts +++ b/src/state/CallViewModel/localMember/Publisher.ts @@ -58,7 +58,7 @@ export class Publisher { trackerProcessorState$: Behavior, private logger: Logger, ) { - this.logger.info("[PublishConnection] Create LiveKit room"); + this.logger.info("Create LiveKit room"); const { controlledAudioDevices } = getUrlParams(); const room = connection.livekitRoom; @@ -74,9 +74,7 @@ export class Publisher { this.workaroundRestartAudioInputTrackChrome(devices, scope); this.scope.onEnd(() => { - this.logger.info( - "[PublishConnection] Scope ended -> stop publishing all tracks", - ); + this.logger.info("Scope ended -> stop publishing all tracks"); void this.stopPublishing(); }); } diff --git a/src/state/CallViewModel/remoteMembers/ConnectionFactory.ts b/src/state/CallViewModel/remoteMembers/ConnectionFactory.ts index 0fb0b5a79..4d4a23cbb 100644 --- a/src/state/CallViewModel/remoteMembers/ConnectionFactory.ts +++ b/src/state/CallViewModel/remoteMembers/ConnectionFactory.ts @@ -13,6 +13,7 @@ import { type BaseKeyProvider, } from "livekit-client"; import { type Logger } from "matrix-js-sdk/lib/logger"; +// imported as inline to support worker when loaded from a cdn (cross domain) import E2EEWorker from "livekit-client/e2ee-worker?worker&inline"; import { type ObservableScope } from "../../ObservableScope.ts"; From 1490359e4c29743916c065c90f9a3267b0383ad2 Mon Sep 17 00:00:00 2001 From: Timo K Date: Mon, 1 Dec 2025 14:05:41 +0100 Subject: [PATCH 021/748] cleanup changes `godot`->`sdk` add docs --- godot/README.md | 14 --------- godot/favicon.ico | Bin 2439 -> 0 bytes index.html | 10 ------ package.json | 4 +-- sdk/README.md | 35 +++++++++++++++++++++ {godot => sdk}/helper.ts | 4 +++ {godot => sdk}/index.html | 4 +-- {godot => sdk}/main.ts | 15 ++++++++- src/state/CallViewModel/CallViewModel.ts | 2 +- tsconfig.json | 2 +- vite-godot.config.js => vite-sdk.config.js | 8 ++--- vite.config.ts | 6 ++-- 12 files changed, 66 insertions(+), 38 deletions(-) delete mode 100644 godot/README.md delete mode 100644 godot/favicon.ico create mode 100644 sdk/README.md rename {godot => sdk}/helper.ts (94%) rename {godot => sdk}/index.html (95%) rename {godot => sdk}/main.ts (94%) rename vite-godot.config.js => vite-sdk.config.js (83%) diff --git a/godot/README.md b/godot/README.md deleted file mode 100644 index 7f00df247..000000000 --- a/godot/README.md +++ /dev/null @@ -1,14 +0,0 @@ -## url parameters -widgetId = $matrix_widget_id -perParticipantE2EE = true -userId = $matrix_user_id -deviceId = $org.matrix.msc3819.matrix_device_id -baseUrl = $org.matrix.msc4039.matrix_base_url - -parentUrl = // will be inserted automatically - -http://localhost?widgetId=&perParticipantE2EE=true&userId=&deviceId=&baseUrl=&roomId= - --> - -http://localhost:3000?widgetId=$matrix_widget_id&perParticipantE2EE=true&userId=$matrix_user_id&deviceId=$org.matrix.msc3819.matrix_device_id&baseUrl=$org.matrix.msc4039.matrix_base_url&roomId=$matrix_room_id diff --git a/godot/favicon.ico b/godot/favicon.ico deleted file mode 100644 index e531e6f274fb3efb29316f441b7057f745758ee3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2439 zcmV;233&F2P)Z$GcPbOEG;=TH6tA!@bK^{BqcdBG?S8&>FMb?FE2SUFU3Q#V=xG9ka78TU#cFhb(k-UtL`c-rg}yO*KbGH9$WU z($gQMqzLQkBcGooii#Y(yDNHmDr#vv5D=G@mOK|3q{gO@000PrNklX?LPZ z5I|*V5jQ}Eh+9n5?29HbW|_SF|9|y@CI*$Is@oY-r0>_snIrdf7u8h-6bcfFL?V$$ zBoc{4B9TZW63LosXV9%o`c`j=)t^+lgH9>yU-k2-4l2{3X*echy7r0AnCTeiu>aqn zn)UDdF;vHsq3bYBiKeVG#~qFaa)}ihN7jd^a*U`o8gtBP_g62lQr9xfxD~Z4%yg#X zgRFmZMsy}7+|&x)(MOG}e|H89EQ8@ptzd5dFzes`j~Vm~U&J#WD;j7ip)ws)#SuEPxk)5_WD zx}gguS2ep9`)_QRt1#cemKV11E@yw@ZRtvm(s^-L*Q)yB$NzhdY&C>k-Kna2<0brs zrsQNNR%6TSKx+3NuGIT_(%P zL9_i@6guW?xKgiDQ_?SVE9>j#;Yg^A+5J-{WHnwCUd6D zGIAggv0A6wuGEBPMFbkLr6q7HjBur*7S>19qIE;$R;Ad_yRK#}-2b7G%C#=I!@Ga8 z>ngDe7Kuw~a;wkVfA(J^T&d6Slyn6nRADaho(h|{QLfZGSji!5D{BRCx}4#?`6tqq z`iB0W+>5LofU)?F(B5UVtJE&oE{x0^Qk8EP1_KR|q<6t~F|(EcWz4k;mjexv0J>m1 zxK!%PXFT`9TC6Ko<7g3)xgYW*S+$3gI9CgNe5X^W>2SzOa0TpwZPTVPgT#?Id=7s^ z1MGrr;m}APCg|!+U0cMvQZLadX#o2#YY!msuDm2yDn82!(56{?fKbBDf|R{klB?M} zmn_B2S_A}ad@nZ>T_L()o3ts6)F4yRvY+fqeSP=1f)g?*~-m{w? zHZwKHS(^ZW%HPX&nyV!z^T*d?-*46s9WfHO!ycyOu-T+fW^w*>S@ZpmO$ky)qVRwT zSzAqdh_RQ`>!$4k@>CLqctqxaceUapj6t&ctWBhI0G74Wq{jd_136i%NT&*x^}gMt z#{ekHw}1WvDh+6vRLIpeU>g#sJ3wWP4|CICRnSzgm_-aWsdjXfcz+DIIvfhC$^-Sd6#^65OWS+U6@ zW&)5zi3ZaNE7m;QKfZmOC$tU2t}suTktqJ5hq}wbro2xNV^=6wG|I|+GcKmzfIl}U7h3hphBd{THu?JtjEu1eK1G6()(F^0D&J2 z3GkB6i*p-2&qm^A$UCc?bOxH?T~Qf1;*0RD_{?GEbIeH+sK76Acx2h}u9_UP4rE>) z!ZUzdiA@6_qE#*5E4f{?5E4xJe&@L!tT}2KPoNd%GWYBjAeK+f@p z1-MdUhf5BqfredZCGX!rUj<)(2)Vivb7fLG6^4PP58*D@73XuSpOB31D}XPe4wW2U z-i2PrOsAS00c<0NUSuw|uIO&U0N9sNynVUSsr0|1=|Cn-zus;%=XsAx7?Z-_Oak3> zTi)rHE3tT`v}sjlBABG!675wNZ1!Fh4DLDjETokZpu1a16?9z$i>|r&HAvZ;8u?Qx;9Zc$Je6s}%~3#Lv(*AGrq_a_B0>mObYlXb8Fb z`A>j>NwVd=&N&Af*5vG?tW_mG%6q=x9%Q}T?7z1$}D4F)I!SMbZ*yD*LB2b=&@dqN*B+QseXEVOS>X$yY(H;iuNbPImb8SZUy zxfb#A6@VjWFG&PrIbT*Qs%PSRQ8z}pO4<`Rv)H}sXUudBy?53
<% } %> - - - <% if (packageType === "godot") { %> - - - - <% } %> diff --git a/package.json b/package.json index c87d5b01c..0b598e97c 100644 --- a/package.json +++ b/package.json @@ -13,8 +13,8 @@ "build:embedded": "yarn build:full --config vite-embedded.config.js", "build:embedded:production": "yarn build:embedded", "build:embedded:development": "yarn build:embedded --mode development", - "build:godot": "yarn build:full --config vite-godot.config.js", - "build:godot:development": "yarn build:godot --mode development", + "build:sdk": "yarn build:full --config vite-sdk.config.js", + "build:sdk:development": "yarn build:sdk --mode development", "serve": "vite preview", "prettier:check": "prettier -c .", "prettier:format": "prettier -w .", diff --git a/sdk/README.md b/sdk/README.md new file mode 100644 index 000000000..03801b836 --- /dev/null +++ b/sdk/README.md @@ -0,0 +1,35 @@ +# SDK mode + +EC can be build in sdk mode. This will result in a compiled js file that can be imported in very simple webapps. + +It allows to use matrixRTC in combination with livekit without relying on element call. + +This is done by instantiating the call view model and exposing some useful behaviors (observables) and methods. + +This folder contains an example index.html file that showcases the sdk in use (hosted on localhost:8123 with a webserver ellowing cors (for example `npx serve -l 81234 --cors`)) as a godot engine HTML export template. + +## Widgets + +The sdk mode is particularly interesting to be used in widgets where you do not need to pay attention to matrix login/cs api ... +To create a widget see the example index.html file in this folder. And add it to EW via: +`/addwidget ` (see **url parameters** for more details on ``) + +### url parameters + +``` +widgetId = $matrix_widget_id +perParticipantE2EE = true +userId = $matrix_user_id +deviceId = $org.matrix.msc3819.matrix_device_id +baseUrl = $org.matrix.msc4039.matrix_base_url +``` + +`parentUrl = // will be inserted automatically` + +Full template use as ``: + +``` +http://localhost:3000?widgetId=$matrix_widget_id&perParticipantE2EE=true&userId=$matrix_user_id&deviceId=$org.matrix.msc3819.matrix_device_id&baseUrl=$org.matrix.msc4039.matrix_base_url&roomId=$matrix_room_id +``` + +the `$` prefixed variables will be replaced by EW on widget instantiation. (e.g. `$matrix_user_id` -> `@user:example.com` (url encoding will also be applied automatically by EW) -> `%40user%3Aexample.com`) diff --git a/godot/helper.ts b/sdk/helper.ts similarity index 94% rename from godot/helper.ts rename to sdk/helper.ts index 8f5c710e5..7dc2138aa 100644 --- a/godot/helper.ts +++ b/sdk/helper.ts @@ -5,6 +5,10 @@ SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial Please see LICENSE in the repository root for full details. */ +/** + * This file contains helper functions and types for the MatrixRTC SDK. + */ + import { logger as rootLogger } from "matrix-js-sdk/lib/logger"; import { scan } from "rxjs"; diff --git a/godot/index.html b/sdk/index.html similarity index 95% rename from godot/index.html rename to sdk/index.html index 39bcf4842..c66274ff2 100644 --- a/godot/index.html +++ b/sdk/index.html @@ -4,8 +4,8 @@ Godot MatrixRTC Widget +
- -
-
+
+
+ + +
+
+
diff --git a/sdk/main.ts b/sdk/main.ts index 9c81ab2f2..205ec0600 100644 --- a/sdk/main.ts +++ b/sdk/main.ts @@ -18,12 +18,25 @@ Please see LICENSE in the repository root for full details. * - setting up encryption and scharing keys */ -import { map, type Observable, of, Subject, switchMap, tap } from "rxjs"; -import { MatrixRTCSessionEvent } from "matrix-js-sdk/lib/matrixrtc"; -import { type TextStreamInfo } from "livekit-client/dist/src/room/types"; +import { + combineLatest, + map, + type Observable, + of, + shareReplay, + Subject, + switchMap, + tap, +} from "rxjs"; +import { + type CallMembership, + MatrixRTCSessionEvent, +} from "matrix-js-sdk/lib/matrixrtc"; import { type Room as LivekitRoom, type TextStreamReader, + type LocalParticipant, + type RemoteParticipant, } from "livekit-client"; import { type Behavior, constant } from "../src/state/Behavior"; @@ -42,14 +55,23 @@ import { widget, } from "./helper"; import { ElementWidgetActions } from "../src/widget"; -import { type MatrixLivekitMember } from "../src/state/CallViewModel/remoteMembers/MatrixLivekitMembers"; +import { type Connection } from "../src/state/CallViewModel/remoteMembers/Connection"; interface MatrixRTCSdk { join: () => LocalMemberConnectionState; /** @throws on leave errors */ leave: () => void; data$: Observable<{ sender: string; data: string }>; - members$: Behavior; + /** + * flattened list of members + */ + members$: Behavior< + { + connection: Connection | null; + membership: CallMembership; + participant: LocalParticipant | RemoteParticipant | null; + }[] + >; /** Use the LocalMemberConnectionState returned from `join` for a more detailed connection state */ connected$: Behavior; sendData?: (data: unknown) => Promise; @@ -242,7 +264,30 @@ export async function createMatrixRTCSdk(): Promise { }, data$, connected$: callViewModel.connected$, - members$: callViewModel.matrixLivekitMembers$, + members$: scope.behavior( + callViewModel.matrixLivekitMembers$.pipe( + switchMap((members) => { + const listOfMemberObservables = members.map((member) => + combineLatest([ + member.connection$, + member.membership$, + member.participant$, + ]).pipe( + map(([connection, membership, participant]) => ({ + connection, + membership, + participant, + })), + // using shareReplay instead of a Behavior here because the behavior would need + // a tricky scope.end() setup. + shareReplay({ bufferSize: 1, refCount: true }), + ), + ); + return combineLatest(listOfMemberObservables); + }), + ), + [], + ), sendData, }; } diff --git a/src/state/CallViewModel/CallViewModel.ts b/src/state/CallViewModel/CallViewModel.ts index ba83203cb..4fb1c35af 100644 --- a/src/state/CallViewModel/CallViewModel.ts +++ b/src/state/CallViewModel/CallViewModel.ts @@ -1519,7 +1519,6 @@ export function createCallViewModel$( localMatrixLivekitMember$, matrixLivekitMembers$: scope.behavior( matrixLivekitMembers$.pipe( - // TODO flatten this so its not a obs of obs. map((members) => members.value), tap((v) => { logger.debug("matrixLivekitMembers$ updated (exported)", v); diff --git a/vite-sdk.config.js b/vite-sdk.config.js index 13b46bd6f..ac1e4de31 100644 --- a/vite-sdk.config.js +++ b/vite-sdk.config.js @@ -6,26 +6,27 @@ Please see LICENSE in the repository root for full details. */ import { defineConfig, mergeConfig } from "vite"; -import fullConfig from "./vite.config"; +import nodePolyfills from "vite-plugin-node-stdlib-browser"; const base = "./"; // Config for embedded deployments (possibly hosted under a non-root path) -export default defineConfig((env) => +export default defineConfig(() => mergeConfig( - fullConfig({ ...env, packageType: "sdk" }), defineConfig({ + worker: { format: "es" }, base, // Use relative URLs to allow the app to be hosted under any path - // publicDir: false, // Don't serve the public directory which only contains the favicon build: { + sourcemap: true, manifest: true, lib: { + formats: ["es"], entry: "./sdk/main.ts", - name: "matrixrtc-sdk", - // the proper extensions will be added + name: "MatrixrtcSdk", fileName: "matrixrtc-sdk", }, }, + plugins: [nodePolyfills()], }), ), ); diff --git a/vite.config.ts b/vite.config.ts index 2f8c72c11..97d643ec4 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -27,7 +27,7 @@ import * as fs from "node:fs"; export default ({ mode, packageType, -}: ConfigEnv & { packageType?: "full" | "embedded" | "sdk" }): UserConfig => { +}: ConfigEnv & { packageType?: "full" | "embedded" }): UserConfig => { const env = loadEnv(mode, process.cwd()); // Environment variables with the VITE_ prefix are accessible at runtime. // So, we set this to allow for build/package specific behavior. @@ -68,7 +68,7 @@ export default ({ plugins.push( createHtmlPlugin({ - entry: packageType === "sdk" ? "sdk/main.ts" : "src/main.tsx", + entry: "src/main.tsx", inject: { data: { brand: env.VITE_PRODUCT_NAME || "Element Call", @@ -125,15 +125,10 @@ export default ({ // Default naming fallback return "assets/[name]-[hash][extname]"; }, - manualChunks: - packageType !== "sdk" - ? { - // we should be able to remove this one https://github.com/matrix-org/matrix-rust-sdk-crypto-wasm/pull/167 lands - "matrix-sdk-crypto-wasm": [ - "@matrix-org/matrix-sdk-crypto-wasm", - ], - } - : undefined, + manualChunks: { + // we should be able to remove this one https://github.com/matrix-org/matrix-rust-sdk-crypto-wasm/pull/167 lands + "matrix-sdk-crypto-wasm": ["@matrix-org/matrix-sdk-crypto-wasm"], + }, }, }, }, diff --git a/yarn.lock b/yarn.lock index 94b731302..4e5eff653 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2711,6 +2711,13 @@ __metadata: languageName: node linkType: hard +"@jridgewell/sourcemap-codec@npm:^1.5.5": + version: 1.5.5 + resolution: "@jridgewell/sourcemap-codec@npm:1.5.5" + checksum: 10c0/f9e538f302b63c0ebc06eecb1dd9918dd4289ed36147a0ddce35d6ea4d7ebbda243cda7b2213b6a5e1d8087a298d5cf630fb2bd39329cdecb82017023f6081a0 + languageName: node + linkType: hard + "@jridgewell/trace-mapping@npm:^0.3.23, @jridgewell/trace-mapping@npm:^0.3.24, @jridgewell/trace-mapping@npm:^0.3.25": version: 0.3.25 resolution: "@jridgewell/trace-mapping@npm:0.3.25" @@ -4479,6 +4486,22 @@ __metadata: languageName: node linkType: hard +"@rollup/plugin-inject@npm:^5.0.3": + version: 5.0.5 + resolution: "@rollup/plugin-inject@npm:5.0.5" + dependencies: + "@rollup/pluginutils": "npm:^5.0.1" + estree-walker: "npm:^2.0.2" + magic-string: "npm:^0.30.3" + peerDependencies: + rollup: ^1.20.0||^2.0.0||^3.0.0||^4.0.0 + peerDependenciesMeta: + rollup: + optional: true + checksum: 10c0/22d10cf44fa56a6683d5ac4df24a9003379b3dcaae9897f5c30c844afc2ebca83cfaa5557f13a1399b1c8a0d312c3217bcacd508b7ebc4b2cbee401bd1ec8be2 + languageName: node + linkType: hard + "@rollup/pluginutils@npm:^4.2.0": version: 4.2.1 resolution: "@rollup/pluginutils@npm:4.2.1" @@ -4489,6 +4512,22 @@ __metadata: languageName: node linkType: hard +"@rollup/pluginutils@npm:^5.0.1": + version: 5.3.0 + resolution: "@rollup/pluginutils@npm:5.3.0" + dependencies: + "@types/estree": "npm:^1.0.0" + estree-walker: "npm:^2.0.2" + picomatch: "npm:^4.0.2" + peerDependencies: + rollup: ^1.20.0||^2.0.0||^3.0.0||^4.0.0 + peerDependenciesMeta: + rollup: + optional: true + checksum: 10c0/001834bf62d7cf5bac424d2617c113f7f7d3b2bf3c1778cbcccb72cdc957b68989f8e7747c782c2b911f1dde8257f56f8ac1e779e29e74e638e3f1e2cac2bcd0 + languageName: node + linkType: hard + "@rollup/pluginutils@npm:^5.1.3": version: 5.1.3 resolution: "@rollup/pluginutils@npm:5.1.3" @@ -6128,6 +6167,30 @@ __metadata: languageName: node linkType: hard +"asn1.js@npm:^4.10.1": + version: 4.10.1 + resolution: "asn1.js@npm:4.10.1" + dependencies: + bn.js: "npm:^4.0.0" + inherits: "npm:^2.0.1" + minimalistic-assert: "npm:^1.0.0" + checksum: 10c0/afa7f3ab9e31566c80175a75b182e5dba50589dcc738aa485be42bdd787e2a07246a4b034d481861123cbe646a7656f318f4f1cad2e9e5e808a210d5d6feaa88 + languageName: node + linkType: hard + +"assert@npm:^2.0.0": + version: 2.1.0 + resolution: "assert@npm:2.1.0" + dependencies: + call-bind: "npm:^1.0.2" + is-nan: "npm:^1.3.2" + object-is: "npm:^1.1.5" + object.assign: "npm:^4.1.4" + util: "npm:^0.12.5" + checksum: 10c0/7271a5da883c256a1fa690677bf1dd9d6aa882139f2bed1cd15da4f9e7459683e1da8e32a203d6cc6767e5e0f730c77a9532a87b896b4b0af0dd535f668775f0 + languageName: node + linkType: hard + "assertion-error@npm:^2.0.1": version: 2.0.1 resolution: "assertion-error@npm:2.0.1" @@ -6318,6 +6381,20 @@ __metadata: languageName: node linkType: hard +"bn.js@npm:^4.0.0, bn.js@npm:^4.1.0, bn.js@npm:^4.11.9": + version: 4.12.2 + resolution: "bn.js@npm:4.12.2" + checksum: 10c0/09a249faa416a9a1ce68b5f5ec8bbca87fe54e5dd4ef8b1cc8a4969147b80035592bddcb1e9cc814c3ba79e573503d5c5178664b722b509fb36d93620dba9b57 + languageName: node + linkType: hard + +"bn.js@npm:^5.2.1, bn.js@npm:^5.2.2": + version: 5.2.2 + resolution: "bn.js@npm:5.2.2" + checksum: 10c0/cb97827d476aab1a0194df33cd84624952480d92da46e6b4a19c32964aa01553a4a613502396712704da2ec8f831cf98d02e74ca03398404bd78a037ba93f2ab + languageName: node + linkType: hard + "boolbase@npm:^1.0.0": version: 1.0.0 resolution: "boolbase@npm:1.0.0" @@ -6393,6 +6470,96 @@ __metadata: languageName: node linkType: hard +"brorand@npm:^1.0.1, brorand@npm:^1.1.0": + version: 1.1.0 + resolution: "brorand@npm:1.1.0" + checksum: 10c0/6f366d7c4990f82c366e3878492ba9a372a73163c09871e80d82fb4ae0d23f9f8924cb8a662330308206e6b3b76ba1d528b4601c9ef73c2166b440b2ea3b7571 + languageName: node + linkType: hard + +"browser-resolve@npm:^2.0.0": + version: 2.0.0 + resolution: "browser-resolve@npm:2.0.0" + dependencies: + resolve: "npm:^1.17.0" + checksum: 10c0/06c43adf3cb1939825ab9a4ac355b23272820ee421a20d04f62e0dabd9ea305e497b97f3ac027f87d53c366483aafe8673bbe1aaa5e41cd69eeafa65ac5fda6e + languageName: node + linkType: hard + +"browserify-aes@npm:^1.0.4, browserify-aes@npm:^1.2.0": + version: 1.2.0 + resolution: "browserify-aes@npm:1.2.0" + dependencies: + buffer-xor: "npm:^1.0.3" + cipher-base: "npm:^1.0.0" + create-hash: "npm:^1.1.0" + evp_bytestokey: "npm:^1.0.3" + inherits: "npm:^2.0.1" + safe-buffer: "npm:^5.0.1" + checksum: 10c0/967f2ae60d610b7b252a4cbb55a7a3331c78293c94b4dd9c264d384ca93354c089b3af9c0dd023534efdc74ffbc82510f7ad4399cf82bc37bc07052eea485f18 + languageName: node + linkType: hard + +"browserify-cipher@npm:^1.0.1": + version: 1.0.1 + resolution: "browserify-cipher@npm:1.0.1" + dependencies: + browserify-aes: "npm:^1.0.4" + browserify-des: "npm:^1.0.0" + evp_bytestokey: "npm:^1.0.0" + checksum: 10c0/aa256dcb42bc53a67168bbc94ab85d243b0a3b56109dee3b51230b7d010d9b78985ffc1fb36e145c6e4db151f888076c1cfc207baf1525d3e375cbe8187fe27d + languageName: node + linkType: hard + +"browserify-des@npm:^1.0.0": + version: 1.0.2 + resolution: "browserify-des@npm:1.0.2" + dependencies: + cipher-base: "npm:^1.0.1" + des.js: "npm:^1.0.0" + inherits: "npm:^2.0.1" + safe-buffer: "npm:^5.1.2" + checksum: 10c0/943eb5d4045eff80a6cde5be4e5fbb1f2d5002126b5a4789c3c1aae3cdddb1eb92b00fb92277f512288e5c6af330730b1dbabcf7ce0923e749e151fcee5a074d + languageName: node + linkType: hard + +"browserify-rsa@npm:^4.0.0, browserify-rsa@npm:^4.1.1": + version: 4.1.1 + resolution: "browserify-rsa@npm:4.1.1" + dependencies: + bn.js: "npm:^5.2.1" + randombytes: "npm:^2.1.0" + safe-buffer: "npm:^5.2.1" + checksum: 10c0/b650ee1192e3d7f3d779edc06dd96ed8720362e72ac310c367b9d7fe35f7e8dbb983c1829142b2b3215458be8bf17c38adc7224920843024ed8cf39e19c513c0 + languageName: node + linkType: hard + +"browserify-sign@npm:^4.2.3": + version: 4.2.5 + resolution: "browserify-sign@npm:4.2.5" + dependencies: + bn.js: "npm:^5.2.2" + browserify-rsa: "npm:^4.1.1" + create-hash: "npm:^1.2.0" + create-hmac: "npm:^1.1.7" + elliptic: "npm:^6.6.1" + inherits: "npm:^2.0.4" + parse-asn1: "npm:^5.1.9" + readable-stream: "npm:^2.3.8" + safe-buffer: "npm:^5.2.1" + checksum: 10c0/6192f9696934bbba58932d098face34c2ab9cac09feed826618b86b8c00a897dab7324cd9aa7d6cb1597064f197264ad72fa5418d4d52bf3c8f9b9e0e124655e + languageName: node + linkType: hard + +"browserify-zlib@npm:^0.2.0": + version: 0.2.0 + resolution: "browserify-zlib@npm:0.2.0" + dependencies: + pako: "npm:~1.0.5" + checksum: 10c0/9ab10b6dc732c6c5ec8ebcbe5cb7fe1467f97402c9b2140113f47b5f187b9438f93a8e065d8baf8b929323c18324fbf1105af479ee86d9d36cab7d7ef3424ad9 + languageName: node + linkType: hard + "browserslist@npm:^4.24.0, browserslist@npm:^4.24.3, browserslist@npm:^4.24.4": version: 4.24.4 resolution: "browserslist@npm:4.24.4" @@ -6437,6 +6604,23 @@ __metadata: languageName: node linkType: hard +"buffer-xor@npm:^1.0.3": + version: 1.0.3 + resolution: "buffer-xor@npm:1.0.3" + checksum: 10c0/fd269d0e0bf71ecac3146187cfc79edc9dbb054e2ee69b4d97dfb857c6d997c33de391696d04bdd669272751fa48e7872a22f3a6c7b07d6c0bc31dbe02a4075c + languageName: node + linkType: hard + +"buffer@npm:^5.7.1": + version: 5.7.1 + resolution: "buffer@npm:5.7.1" + dependencies: + base64-js: "npm:^1.3.1" + ieee754: "npm:^1.1.13" + checksum: 10c0/27cac81cff434ed2876058d72e7c4789d11ff1120ef32c9de48f59eab58179b66710c488987d295ae89a228f835fc66d088652dffeb8e3ba8659f80eb091d55e + languageName: node + linkType: hard + "buffer@npm:^6.0.3": version: 6.0.3 resolution: "buffer@npm:6.0.3" @@ -6454,6 +6638,13 @@ __metadata: languageName: node linkType: hard +"builtin-status-codes@npm:^3.0.0": + version: 3.0.0 + resolution: "builtin-status-codes@npm:3.0.0" + checksum: 10c0/c37bbba11a34c4431e56bd681b175512e99147defbe2358318d8152b3a01df7bf25e0305873947e5b350073d5ef41a364a22b37e48f1fb6d2fe6d5286a0f348c + languageName: node + linkType: hard + "bytesish@npm:^0.4.1": version: 0.4.4 resolution: "bytesish@npm:0.4.4" @@ -6508,7 +6699,7 @@ __metadata: languageName: node linkType: hard -"call-bind@npm:^1.0.2, call-bind@npm:^1.0.7, call-bind@npm:^1.0.8": +"call-bind@npm:^1.0.0, call-bind@npm:^1.0.2, call-bind@npm:^1.0.7, call-bind@npm:^1.0.8": version: 1.0.8 resolution: "call-bind@npm:1.0.8" dependencies: @@ -6571,24 +6762,10 @@ __metadata: languageName: node linkType: hard -"caniuse-lite@npm:^1.0.30001688": - version: 1.0.30001701 - resolution: "caniuse-lite@npm:1.0.30001701" - checksum: 10c0/a814bd4dd8b49645ca51bc6ee42120660a36394bb54eb6084801d3f2bbb9471e5e1a9a8a25f44f83086a032d46e66b33031e2aa345f699b90a7e84a9836b819c - languageName: node - linkType: hard - -"caniuse-lite@npm:^1.0.30001702": - version: 1.0.30001720 - resolution: "caniuse-lite@npm:1.0.30001720" - checksum: 10c0/ba9f963364ec4bfc8359d15d7e2cf365185fa1fddc90b4f534c71befedae9b3dd0cd2583a25ffc168a02d7b61b6c18b59bda0a1828ea2a5250fd3e35c2c049e9 - languageName: node - linkType: hard - -"caniuse-lite@npm:^1.0.30001726": - version: 1.0.30001726 - resolution: "caniuse-lite@npm:1.0.30001726" - checksum: 10c0/2c5f91da7fd9ebf8c6b432818b1498ea28aca8de22b30dafabe2a2a6da1e014f10e67e14f8e68e872a0867b6b4cd6001558dde04e3ab9770c9252ca5c8849d0e +"caniuse-lite@npm:^1.0.30001688, caniuse-lite@npm:^1.0.30001702, caniuse-lite@npm:^1.0.30001726": + version: 1.0.30001757 + resolution: "caniuse-lite@npm:1.0.30001757" + checksum: 10c0/3ccb71fa2bf1f8c96ff1bf9b918b08806fed33307e20a3ce3259155fda131eaf96cfcd88d3d309c8fd7f8285cc71d89a3b93648a1c04814da31c301f98508d42 languageName: node linkType: hard @@ -6722,6 +6899,17 @@ __metadata: languageName: node linkType: hard +"cipher-base@npm:^1.0.0, cipher-base@npm:^1.0.1, cipher-base@npm:^1.0.3": + version: 1.0.7 + resolution: "cipher-base@npm:1.0.7" + dependencies: + inherits: "npm:^2.0.4" + safe-buffer: "npm:^5.2.1" + to-buffer: "npm:^1.2.2" + checksum: 10c0/53c5046a9d9b60c586479b8f13fde263c3f905e13f11e8e04c7a311ce399c91d9c3ec96642332e0de077d356e1014ee12bba96f74fbaad0de750f49122258836 + languageName: node + linkType: hard + "classnames@npm:^2.3.1, classnames@npm:^2.5.1": version: 2.5.1 resolution: "classnames@npm:2.5.1" @@ -6885,6 +7073,20 @@ __metadata: languageName: node linkType: hard +"console-browserify@npm:^1.1.0": + version: 1.2.0 + resolution: "console-browserify@npm:1.2.0" + checksum: 10c0/89b99a53b7d6cee54e1e64fa6b1f7ac24b844b4019c5d39db298637e55c1f4ffa5c165457ad984864de1379df2c8e1886cbbdac85d9dbb6876a9f26c3106f226 + languageName: node + linkType: hard + +"constants-browserify@npm:^1.0.0": + version: 1.0.0 + resolution: "constants-browserify@npm:1.0.0" + checksum: 10c0/ab49b1d59a433ed77c964d90d19e08b2f77213fb823da4729c0baead55e3c597f8f97ebccfdfc47bd896d43854a117d114c849a6f659d9986420e97da0f83ac5 + languageName: node + linkType: hard + "content-type@npm:^1.0.4": version: 1.0.5 resolution: "content-type@npm:1.0.5" @@ -6957,6 +7159,50 @@ __metadata: languageName: node linkType: hard +"create-ecdh@npm:^4.0.4": + version: 4.0.4 + resolution: "create-ecdh@npm:4.0.4" + dependencies: + bn.js: "npm:^4.1.0" + elliptic: "npm:^6.5.3" + checksum: 10c0/77b11a51360fec9c3bce7a76288fc0deba4b9c838d5fb354b3e40c59194d23d66efe6355fd4b81df7580da0661e1334a235a2a5c040b7569ba97db428d466e7f + languageName: node + linkType: hard + +"create-hash@npm:^1.1.0, create-hash@npm:^1.2.0": + version: 1.2.0 + resolution: "create-hash@npm:1.2.0" + dependencies: + cipher-base: "npm:^1.0.1" + inherits: "npm:^2.0.1" + md5.js: "npm:^1.3.4" + ripemd160: "npm:^2.0.1" + sha.js: "npm:^2.4.0" + checksum: 10c0/d402e60e65e70e5083cb57af96d89567954d0669e90550d7cec58b56d49c4b193d35c43cec8338bc72358198b8cbf2f0cac14775b651e99238e1cf411490f915 + languageName: node + linkType: hard + +"create-hmac@npm:^1.1.7": + version: 1.1.7 + resolution: "create-hmac@npm:1.1.7" + dependencies: + cipher-base: "npm:^1.0.3" + create-hash: "npm:^1.1.0" + inherits: "npm:^2.0.1" + ripemd160: "npm:^2.0.0" + safe-buffer: "npm:^5.0.1" + sha.js: "npm:^2.4.8" + checksum: 10c0/24332bab51011652a9a0a6d160eed1e8caa091b802335324ae056b0dcb5acbc9fcf173cf10d128eba8548c3ce98dfa4eadaa01bd02f44a34414baee26b651835 + languageName: node + linkType: hard + +"create-require@npm:^1.1.1": + version: 1.1.1 + resolution: "create-require@npm:1.1.1" + checksum: 10c0/157cbc59b2430ae9a90034a5f3a1b398b6738bf510f713edc4d4e45e169bc514d3d99dd34d8d01ca7ae7830b5b8b537e46ae8f3c8f932371b0875c0151d7ec91 + languageName: node + linkType: hard + "cross-spawn@npm:^7.0.2": version: 7.0.3 resolution: "cross-spawn@npm:7.0.3" @@ -6979,6 +7225,26 @@ __metadata: languageName: node linkType: hard +"crypto-browserify@npm:^3.12.1": + version: 3.12.1 + resolution: "crypto-browserify@npm:3.12.1" + dependencies: + browserify-cipher: "npm:^1.0.1" + browserify-sign: "npm:^4.2.3" + create-ecdh: "npm:^4.0.4" + create-hash: "npm:^1.2.0" + create-hmac: "npm:^1.1.7" + diffie-hellman: "npm:^5.0.3" + hash-base: "npm:~3.0.4" + inherits: "npm:^2.0.4" + pbkdf2: "npm:^3.1.2" + public-encrypt: "npm:^4.0.3" + randombytes: "npm:^2.1.0" + randomfill: "npm:^1.0.4" + checksum: 10c0/184a2def7b16628e79841243232ab5497f18d8e158ac21b7ce90ab172427d0a892a561280adc08f9d4d517bce8db2a5b335dc21abb970f787f8e874bd7b9db7d + languageName: node + linkType: hard + "css-blank-pseudo@npm:^7.0.1": version: 7.0.1 resolution: "css-blank-pseudo@npm:7.0.1" @@ -7267,6 +7533,16 @@ __metadata: languageName: node linkType: hard +"des.js@npm:^1.0.0": + version: 1.1.0 + resolution: "des.js@npm:1.1.0" + dependencies: + inherits: "npm:^2.0.1" + minimalistic-assert: "npm:^1.0.0" + checksum: 10c0/671354943ad67493e49eb4c555480ab153edd7cee3a51c658082fcde539d2690ed2a4a0b5d1f401f9cde822edf3939a6afb2585f32c091f2d3a1b1665cd45236 + languageName: node + linkType: hard + "detect-libc@npm:^1.0.3": version: 1.0.3 resolution: "detect-libc@npm:1.0.3" @@ -7283,6 +7559,17 @@ __metadata: languageName: node linkType: hard +"diffie-hellman@npm:^5.0.3": + version: 5.0.3 + resolution: "diffie-hellman@npm:5.0.3" + dependencies: + bn.js: "npm:^4.1.0" + miller-rabin: "npm:^4.0.0" + randombytes: "npm:^2.0.0" + checksum: 10c0/ce53ccafa9ca544b7fc29b08a626e23a9b6562efc2a98559a0c97b4718937cebaa9b5d7d0a05032cc9c1435e9b3c1532b9e9bf2e0ede868525922807ad6e1ecf + languageName: node + linkType: hard + "dijkstrajs@npm:^1.0.1": version: 1.0.3 resolution: "dijkstrajs@npm:1.0.3" @@ -7353,6 +7640,13 @@ __metadata: languageName: node linkType: hard +"domain-browser@npm:4.22.0": + version: 4.22.0 + resolution: "domain-browser@npm:4.22.0" + checksum: 10c0/2ef7eda6d2161038fda0c9aa4c9e18cc7a0baa89ea6be975d449527c2eefd4b608425db88508e2859acc472f46f402079274b24bd75e3fb506f28c5dba203129 + languageName: node + linkType: hard + "domelementtype@npm:^2.0.1, domelementtype@npm:^2.2.0, domelementtype@npm:^2.3.0": version: 2.3.0 resolution: "domelementtype@npm:2.3.0" @@ -7549,6 +7843,7 @@ __metadata: loglevel: "npm:^1.9.1" matrix-js-sdk: "npm:^39.2.0" matrix-widget-api: "npm:^1.14.0" + node-stdlib-browser: "npm:^1.3.1" normalize.css: "npm:^8.0.1" observable-hooks: "npm:^4.2.3" pako: "npm:^2.0.4" @@ -7571,12 +7866,29 @@ __metadata: vite: "npm:^7.0.0" vite-plugin-generate-file: "npm:^0.3.0" vite-plugin-html: "npm:^3.2.2" + vite-plugin-node-stdlib-browser: "npm:^0.2.1" + vite-plugin-singlefile: "npm:^2.3.0" vite-plugin-svgr: "npm:^4.0.0" vitest: "npm:^3.0.0" vitest-axe: "npm:^1.0.0-pre.3" languageName: unknown linkType: soft +"elliptic@npm:^6.5.3, elliptic@npm:^6.6.1": + version: 6.6.1 + resolution: "elliptic@npm:6.6.1" + dependencies: + bn.js: "npm:^4.11.9" + brorand: "npm:^1.1.0" + hash.js: "npm:^1.0.0" + hmac-drbg: "npm:^1.0.1" + inherits: "npm:^2.0.4" + minimalistic-assert: "npm:^1.0.1" + minimalistic-crypto-utils: "npm:^1.0.1" + checksum: 10c0/8b24ef782eec8b472053793ea1e91ae6bee41afffdfcb78a81c0a53b191e715cbe1292aa07165958a9bbe675bd0955142560b1a007ffce7d6c765bcaf951a867 + languageName: node + linkType: hard + "emoji-regex@npm:^8.0.0": version: 8.0.0 resolution: "emoji-regex@npm:8.0.0" @@ -8388,13 +8700,24 @@ __metadata: languageName: node linkType: hard -"events@npm:^3.2.0, events@npm:^3.3.0": +"events@npm:^3.0.0, events@npm:^3.2.0, events@npm:^3.3.0": version: 3.3.0 resolution: "events@npm:3.3.0" checksum: 10c0/d6b6f2adbccbcda74ddbab52ed07db727ef52e31a61ed26db9feb7dc62af7fc8e060defa65e5f8af9449b86b52cc1a1f6a79f2eafcf4e62add2b7a1fa4a432f6 languageName: node linkType: hard +"evp_bytestokey@npm:^1.0.0, evp_bytestokey@npm:^1.0.3": + version: 1.0.3 + resolution: "evp_bytestokey@npm:1.0.3" + dependencies: + md5.js: "npm:^1.3.4" + node-gyp: "npm:latest" + safe-buffer: "npm:^5.1.1" + checksum: 10c0/77fbe2d94a902a80e9b8f5a73dcd695d9c14899c5e82967a61b1fc6cbbb28c46552d9b127cff47c45fcf684748bdbcfa0a50410349109de87ceb4b199ef6ee99 + languageName: node + linkType: hard + "expect-type@npm:^1.2.1": version: 1.2.1 resolution: "expect-type@npm:1.2.1" @@ -8790,6 +9113,13 @@ __metadata: languageName: node linkType: hard +"generator-function@npm:^2.0.0": + version: 2.0.1 + resolution: "generator-function@npm:2.0.1" + checksum: 10c0/8a9f59df0f01cfefafdb3b451b80555e5cf6d76487095db91ac461a0e682e4ff7a9dbce15f4ecec191e53586d59eece01949e05a4b4492879600bbbe8e28d6b8 + languageName: node + linkType: hard + "gensync@npm:^1.0.0-beta.2": version: 1.0.0-beta.2 resolution: "gensync@npm:1.0.0-beta.2" @@ -9092,6 +9422,38 @@ __metadata: languageName: node linkType: hard +"hash-base@npm:^3.0.0, hash-base@npm:^3.1.2": + version: 3.1.2 + resolution: "hash-base@npm:3.1.2" + dependencies: + inherits: "npm:^2.0.4" + readable-stream: "npm:^2.3.8" + safe-buffer: "npm:^5.2.1" + to-buffer: "npm:^1.2.1" + checksum: 10c0/f3b7fae1853b31340048dd659f40f5260ca6f3ff53b932f807f4ab701ee09039f6e9dbe1841723ff61e20f3f69d6387a352e4ccc5f997dedb0d375c7d88bc15e + languageName: node + linkType: hard + +"hash-base@npm:~3.0.4": + version: 3.0.5 + resolution: "hash-base@npm:3.0.5" + dependencies: + inherits: "npm:^2.0.4" + safe-buffer: "npm:^5.2.1" + checksum: 10c0/6dc185b79bad9b6d525cd132a588e4215380fdc36fec6f7a8a58c5db8e3b642557d02ad9c367f5e476c7c3ad3ccffa3607f308b124e1ed80e3b80a1b254db61e + languageName: node + linkType: hard + +"hash.js@npm:^1.0.0, hash.js@npm:^1.0.3": + version: 1.1.7 + resolution: "hash.js@npm:1.1.7" + dependencies: + inherits: "npm:^2.0.3" + minimalistic-assert: "npm:^1.0.1" + checksum: 10c0/41ada59494eac5332cfc1ce6b7ebdd7b88a3864a6d6b08a3ea8ef261332ed60f37f10877e0c825aaa4bddebf164fbffa618286aeeec5296675e2671cbfa746c4 + languageName: node + linkType: hard + "hasown@npm:^2.0.0, hasown@npm:^2.0.2": version: 2.0.2 resolution: "hasown@npm:2.0.2" @@ -9129,6 +9491,17 @@ __metadata: languageName: node linkType: hard +"hmac-drbg@npm:^1.0.1": + version: 1.0.1 + resolution: "hmac-drbg@npm:1.0.1" + dependencies: + hash.js: "npm:^1.0.3" + minimalistic-assert: "npm:^1.0.0" + minimalistic-crypto-utils: "npm:^1.0.1" + checksum: 10c0/f3d9ba31b40257a573f162176ac5930109816036c59a09f901eb2ffd7e5e705c6832bedfff507957125f2086a0ab8f853c0df225642a88bf1fcaea945f20600d + languageName: node + linkType: hard + "hoist-non-react-statics@npm:^3.3.2": version: 3.3.2 resolution: "hoist-non-react-statics@npm:3.3.2" @@ -9216,6 +9589,13 @@ __metadata: languageName: node linkType: hard +"https-browserify@npm:^1.0.0": + version: 1.0.0 + resolution: "https-browserify@npm:1.0.0" + checksum: 10c0/e17b6943bc24ea9b9a7da5714645d808670af75a425f29baffc3284962626efdc1eb3aa9bbffaa6e64028a6ad98af5b09fabcb454a8f918fb686abfdc9e9b8ae + languageName: node + linkType: hard + "https-proxy-agent@npm:^5.0.0": version: 5.0.1 resolution: "https-proxy-agent@npm:5.0.1" @@ -9295,7 +9675,7 @@ __metadata: languageName: node linkType: hard -"ieee754@npm:^1.2.1": +"ieee754@npm:^1.1.13, ieee754@npm:^1.2.1": version: 1.2.1 resolution: "ieee754@npm:1.2.1" checksum: 10c0/b0782ef5e0935b9f12883a2e2aa37baa75da6e66ce6515c168697b42160807d9330de9a32ec1ed73149aea02e0d822e572bca6f1e22bdcbd2149e13b050b17bb @@ -9357,7 +9737,7 @@ __metadata: languageName: node linkType: hard -"inherits@npm:2, inherits@npm:^2.0.3, inherits@npm:^2.0.4, inherits@npm:~2.0.3": +"inherits@npm:2, inherits@npm:^2.0.1, inherits@npm:^2.0.3, inherits@npm:^2.0.4, inherits@npm:~2.0.3, inherits@npm:~2.0.4": version: 2.0.4 resolution: "inherits@npm:2.0.4" checksum: 10c0/4e531f648b29039fb7426fb94075e6545faa1eb9fe83c29f0b6d9e7263aceb4289d2d4557db0d428188eeb449cc7c5e77b0a0b2c4e248ff2a65933a0dee49ef2 @@ -9385,6 +9765,16 @@ __metadata: languageName: node linkType: hard +"is-arguments@npm:^1.0.4": + version: 1.2.0 + resolution: "is-arguments@npm:1.2.0" + dependencies: + call-bound: "npm:^1.0.2" + has-tostringtag: "npm:^1.0.2" + checksum: 10c0/6377344b31e9fcb707c6751ee89b11f132f32338e6a782ec2eac9393b0cbd32235dad93052998cda778ee058754860738341d8114910d50ada5615912bb929fc + languageName: node + linkType: hard + "is-array-buffer@npm:^3.0.4, is-array-buffer@npm:^3.0.5": version: 3.0.5 resolution: "is-array-buffer@npm:3.0.5" @@ -9524,6 +9914,19 @@ __metadata: languageName: node linkType: hard +"is-generator-function@npm:^1.0.7": + version: 1.1.2 + resolution: "is-generator-function@npm:1.1.2" + dependencies: + call-bound: "npm:^1.0.4" + generator-function: "npm:^2.0.0" + get-proto: "npm:^1.0.1" + has-tostringtag: "npm:^1.0.2" + safe-regex-test: "npm:^1.1.0" + checksum: 10c0/83da102e89c3e3b71d67b51d47c9f9bc862bceb58f87201727e27f7fa19d1d90b0ab223644ecaee6fc6e3d2d622bb25c966fbdaf87c59158b01ce7c0fe2fa372 + languageName: node + linkType: hard + "is-glob@npm:^4.0.0, is-glob@npm:^4.0.1, is-glob@npm:^4.0.3, is-glob@npm:~4.0.1": version: 4.0.3 resolution: "is-glob@npm:4.0.3" @@ -9540,6 +9943,16 @@ __metadata: languageName: node linkType: hard +"is-nan@npm:^1.3.2": + version: 1.3.2 + resolution: "is-nan@npm:1.3.2" + dependencies: + call-bind: "npm:^1.0.0" + define-properties: "npm:^1.1.3" + checksum: 10c0/8bfb286f85763f9c2e28ea32e9127702fe980ffd15fa5d63ade3be7786559e6e21355d3625dd364c769c033c5aedf0a2ed3d4025d336abf1b9241e3d9eddc5b0 + languageName: node + linkType: hard + "is-negated-glob@npm:^1.0.0": version: 1.0.0 resolution: "is-negated-glob@npm:1.0.0" @@ -9662,7 +10075,7 @@ __metadata: languageName: node linkType: hard -"is-typed-array@npm:^1.1.13, is-typed-array@npm:^1.1.14, is-typed-array@npm:^1.1.15": +"is-typed-array@npm:^1.1.13, is-typed-array@npm:^1.1.14, is-typed-array@npm:^1.1.15, is-typed-array@npm:^1.1.3": version: 1.1.15 resolution: "is-typed-array@npm:1.1.15" dependencies: @@ -9741,6 +10154,13 @@ __metadata: languageName: node linkType: hard +"isomorphic-timers-promises@npm:^1.0.1": + version: 1.0.1 + resolution: "isomorphic-timers-promises@npm:1.0.1" + checksum: 10c0/3b4761d0012ebe6b6382246079fc667f3513f36fe4042638f2bfb7db1557e4f1acd33a9c9907706c04270890ec6434120f132f3f300161a42a7dd8628926c8a4 + languageName: node + linkType: hard + "istanbul-lib-coverage@npm:^3.0.0, istanbul-lib-coverage@npm:^3.2.2": version: 3.2.2 resolution: "istanbul-lib-coverage@npm:3.2.2" @@ -10289,6 +10709,15 @@ __metadata: languageName: node linkType: hard +"magic-string@npm:^0.30.3": + version: 0.30.21 + resolution: "magic-string@npm:0.30.21" + dependencies: + "@jridgewell/sourcemap-codec": "npm:^1.5.5" + checksum: 10c0/299378e38f9a270069fc62358522ddfb44e94244baa0d6a8980ab2a9b2490a1d03b236b447eee309e17eb3bddfa482c61259d47960eb018a904f0ded52780c4a + languageName: node + linkType: hard + "magicast@npm:^0.3.5": version: 0.3.5 resolution: "magicast@npm:0.3.5" @@ -10384,6 +10813,17 @@ __metadata: languageName: node linkType: hard +"md5.js@npm:^1.3.4": + version: 1.3.5 + resolution: "md5.js@npm:1.3.5" + dependencies: + hash-base: "npm:^3.0.0" + inherits: "npm:^2.0.1" + safe-buffer: "npm:^5.1.2" + checksum: 10c0/b7bd75077f419c8e013fc4d4dada48be71882e37d69a44af65a2f2804b91e253441eb43a0614423a1c91bb830b8140b0dc906bc797245e2e275759584f4efcc5 + languageName: node + linkType: hard + "merge2@npm:^1.3.0, merge2@npm:^1.4.1": version: 1.4.1 resolution: "merge2@npm:1.4.1" @@ -10401,6 +10841,18 @@ __metadata: languageName: node linkType: hard +"miller-rabin@npm:^4.0.0": + version: 4.0.1 + resolution: "miller-rabin@npm:4.0.1" + dependencies: + bn.js: "npm:^4.0.0" + brorand: "npm:^1.0.1" + bin: + miller-rabin: bin/miller-rabin + checksum: 10c0/26b2b96f6e49dbcff7faebb78708ed2f5f9ae27ac8cbbf1d7c08f83cf39bed3d418c0c11034dce997da70d135cc0ff6f3a4c15dc452f8e114c11986388a64346 + languageName: node + linkType: hard + "mime-db@npm:1.52.0": version: 1.52.0 resolution: "mime-db@npm:1.52.0" @@ -10424,6 +10876,20 @@ __metadata: languageName: node linkType: hard +"minimalistic-assert@npm:^1.0.0, minimalistic-assert@npm:^1.0.1": + version: 1.0.1 + resolution: "minimalistic-assert@npm:1.0.1" + checksum: 10c0/96730e5601cd31457f81a296f521eb56036e6f69133c0b18c13fe941109d53ad23a4204d946a0d638d7f3099482a0cec8c9bb6d642604612ce43ee536be3dddd + languageName: node + linkType: hard + +"minimalistic-crypto-utils@npm:^1.0.1": + version: 1.0.1 + resolution: "minimalistic-crypto-utils@npm:1.0.1" + checksum: 10c0/790ecec8c5c73973a4fbf2c663d911033e8494d5fb0960a4500634766ab05d6107d20af896ca2132e7031741f19888154d44b2408ada0852446705441383e9f8 + languageName: node + linkType: hard + "minimatch@npm:^3.0.2, minimatch@npm:^3.0.4, minimatch@npm:^3.0.5, minimatch@npm:^3.1.1, minimatch@npm:^3.1.2": version: 3.1.2 resolution: "minimatch@npm:3.1.2" @@ -10674,6 +11140,41 @@ __metadata: languageName: node linkType: hard +"node-stdlib-browser@npm:^1.3.1": + version: 1.3.1 + resolution: "node-stdlib-browser@npm:1.3.1" + dependencies: + assert: "npm:^2.0.0" + browser-resolve: "npm:^2.0.0" + browserify-zlib: "npm:^0.2.0" + buffer: "npm:^5.7.1" + console-browserify: "npm:^1.1.0" + constants-browserify: "npm:^1.0.0" + create-require: "npm:^1.1.1" + crypto-browserify: "npm:^3.12.1" + domain-browser: "npm:4.22.0" + events: "npm:^3.0.0" + https-browserify: "npm:^1.0.0" + isomorphic-timers-promises: "npm:^1.0.1" + os-browserify: "npm:^0.3.0" + path-browserify: "npm:^1.0.1" + pkg-dir: "npm:^5.0.0" + process: "npm:^0.11.10" + punycode: "npm:^1.4.1" + querystring-es3: "npm:^0.2.1" + readable-stream: "npm:^3.6.0" + stream-browserify: "npm:^3.0.0" + stream-http: "npm:^3.2.0" + string_decoder: "npm:^1.0.0" + timers-browserify: "npm:^2.0.4" + tty-browserify: "npm:0.0.1" + url: "npm:^0.11.4" + util: "npm:^0.12.4" + vm-browserify: "npm:^1.0.1" + checksum: 10c0/5b0cb5d4499b1b1c73f54db3e9e69b2a3a8aebe2ead2e356b0a03c1dfca6b5c5d2f6516e24301e76dc7b68999b9d0ae3da6c3f1dec421eed80ad6cb9eec0f356 + languageName: node + linkType: hard + "nopt@npm:^8.0.0": version: 8.1.0 resolution: "nopt@npm:8.1.0" @@ -10764,6 +11265,16 @@ __metadata: languageName: node linkType: hard +"object-is@npm:^1.1.5": + version: 1.1.6 + resolution: "object-is@npm:1.1.6" + dependencies: + call-bind: "npm:^1.0.7" + define-properties: "npm:^1.2.1" + checksum: 10c0/506af444c4dce7f8e31f34fc549e2fb8152d6b9c4a30c6e62852badd7f520b579c679af433e7a072f9d78eb7808d230dc12e1cf58da9154dfbf8813099ea0fe0 + languageName: node + linkType: hard + "object-keys@npm:^1.1.1": version: 1.1.1 resolution: "object-keys@npm:1.1.1" @@ -10875,6 +11386,13 @@ __metadata: languageName: node linkType: hard +"os-browserify@npm:^0.3.0": + version: 0.3.0 + resolution: "os-browserify@npm:0.3.0" + checksum: 10c0/6ff32cb1efe2bc6930ad0fd4c50e30c38010aee909eba8d65be60af55efd6cbb48f0287e3649b4e3f3a63dce5a667b23c187c4293a75e557f0d5489d735bcf52 + languageName: node + linkType: hard + "own-keys@npm:^1.0.1": version: 1.0.1 resolution: "own-keys@npm:1.0.1" @@ -11007,6 +11525,13 @@ __metadata: languageName: node linkType: hard +"pako@npm:~1.0.5": + version: 1.0.11 + resolution: "pako@npm:1.0.11" + checksum: 10c0/86dd99d8b34c3930345b8bbeb5e1cd8a05f608eeb40967b293f72fe469d0e9c88b783a8777e4cc7dc7c91ce54c5e93d88ff4b4f060e6ff18408fd21030d9ffbe + languageName: node + linkType: hard + "param-case@npm:^3.0.4": version: 3.0.4 resolution: "param-case@npm:3.0.4" @@ -11026,6 +11551,19 @@ __metadata: languageName: node linkType: hard +"parse-asn1@npm:^5.0.0, parse-asn1@npm:^5.1.9": + version: 5.1.9 + resolution: "parse-asn1@npm:5.1.9" + dependencies: + asn1.js: "npm:^4.10.1" + browserify-aes: "npm:^1.2.0" + evp_bytestokey: "npm:^1.0.3" + pbkdf2: "npm:^3.1.5" + safe-buffer: "npm:^5.2.1" + checksum: 10c0/6dfe27c121be3d63ebbf95f03d2ae0a07dd716d44b70b0bd3458790a822a80de05361c62147271fd7b845dcc2d37755d9c9c393064a3438fe633779df0bc07e7 + languageName: node + linkType: hard + "parse-json@npm:^5.0.0, parse-json@npm:^5.2.0": version: 5.2.0 resolution: "parse-json@npm:5.2.0" @@ -11076,6 +11614,13 @@ __metadata: languageName: node linkType: hard +"path-browserify@npm:^1.0.1": + version: 1.0.1 + resolution: "path-browserify@npm:1.0.1" + checksum: 10c0/8b8c3fd5c66bd340272180590ae4ff139769e9ab79522e2eb82e3d571a89b8117c04147f65ad066dccfb42fcad902e5b7d794b3d35e0fd840491a8ddbedf8c66 + languageName: node + linkType: hard + "path-exists@npm:^4.0.0": version: 4.0.0 resolution: "path-exists@npm:4.0.0" @@ -11149,6 +11694,20 @@ __metadata: languageName: node linkType: hard +"pbkdf2@npm:^3.1.2, pbkdf2@npm:^3.1.5": + version: 3.1.5 + resolution: "pbkdf2@npm:3.1.5" + dependencies: + create-hash: "npm:^1.2.0" + create-hmac: "npm:^1.1.7" + ripemd160: "npm:^2.0.3" + safe-buffer: "npm:^5.2.1" + sha.js: "npm:^2.4.12" + to-buffer: "npm:^1.2.1" + checksum: 10c0/ea42e8695e49417eefabb19a08ab19a602cc6cc72d2df3f109c39309600230dee3083a6f678d5d42fe035d6ae780038b80ace0e68f9792ee2839bf081fe386f3 + languageName: node + linkType: hard + "picocolors@npm:^1.0.0, picocolors@npm:^1.1.1": version: 1.1.1 resolution: "picocolors@npm:1.1.1" @@ -11177,6 +11736,15 @@ __metadata: languageName: node linkType: hard +"pkg-dir@npm:^5.0.0": + version: 5.0.0 + resolution: "pkg-dir@npm:5.0.0" + dependencies: + find-up: "npm:^5.0.0" + checksum: 10c0/793a496d685dc55bbbdbbb22d884535c3b29241e48e3e8d37e448113a71b9e42f5481a61fdc672d7322de12fbb2c584dd3a68bf89b18fffce5c48a390f911bc5 + languageName: node + linkType: hard + "playwright-core@npm:1.56.1": version: 1.56.1 resolution: "playwright-core@npm:1.56.1" @@ -11673,6 +12241,13 @@ __metadata: languageName: node linkType: hard +"process@npm:^0.11.10": + version: 0.11.10 + resolution: "process@npm:0.11.10" + checksum: 10c0/40c3ce4b7e6d4b8c3355479df77aeed46f81b279818ccdc500124e6a5ab882c0cc81ff7ea16384873a95a74c4570b01b120f287abbdd4c877931460eca6084b3 + languageName: node + linkType: hard + "progress@npm:^2.0.3": version: 2.0.3 resolution: "progress@npm:2.0.3" @@ -11745,6 +12320,27 @@ __metadata: languageName: node linkType: hard +"public-encrypt@npm:^4.0.3": + version: 4.0.3 + resolution: "public-encrypt@npm:4.0.3" + dependencies: + bn.js: "npm:^4.1.0" + browserify-rsa: "npm:^4.0.0" + create-hash: "npm:^1.1.0" + parse-asn1: "npm:^5.0.0" + randombytes: "npm:^2.0.1" + safe-buffer: "npm:^5.1.2" + checksum: 10c0/6c2cc19fbb554449e47f2175065d6b32f828f9b3badbee4c76585ac28ae8641aafb9bb107afc430c33c5edd6b05dbe318df4f7d6d7712b1093407b11c4280700 + languageName: node + linkType: hard + +"punycode@npm:^1.4.1": + version: 1.4.1 + resolution: "punycode@npm:1.4.1" + checksum: 10c0/354b743320518aef36f77013be6e15da4db24c2b4f62c5f1eb0529a6ed02fbaf1cb52925785f6ab85a962f2b590d9cd5ad730b70da72b5f180e2556b8bd3ca08 + languageName: node + linkType: hard + "punycode@npm:^2.1.0, punycode@npm:^2.3.1": version: 2.3.1 resolution: "punycode@npm:2.3.1" @@ -11765,6 +12361,22 @@ __metadata: languageName: node linkType: hard +"qs@npm:^6.12.3": + version: 6.14.0 + resolution: "qs@npm:6.14.0" + dependencies: + side-channel: "npm:^1.1.0" + checksum: 10c0/8ea5d91bf34f440598ee389d4a7d95820e3b837d3fd9f433871f7924801becaa0cd3b3b4628d49a7784d06a8aea9bc4554d2b6d8d584e2d221dc06238a42909c + languageName: node + linkType: hard + +"querystring-es3@npm:^0.2.1": + version: 0.2.1 + resolution: "querystring-es3@npm:0.2.1" + checksum: 10c0/476938c1adb45c141f024fccd2ffd919a3746e79ed444d00e670aad68532977b793889648980e7ca7ff5ffc7bfece623118d0fbadcaf217495eeb7059ae51580 + languageName: node + linkType: hard + "queue-microtask@npm:^1.2.2": version: 1.2.3 resolution: "queue-microtask@npm:1.2.3" @@ -11783,6 +12395,25 @@ __metadata: languageName: node linkType: hard +"randombytes@npm:^2.0.0, randombytes@npm:^2.0.1, randombytes@npm:^2.0.5, randombytes@npm:^2.1.0": + version: 2.1.0 + resolution: "randombytes@npm:2.1.0" + dependencies: + safe-buffer: "npm:^5.1.0" + checksum: 10c0/50395efda7a8c94f5dffab564f9ff89736064d32addf0cc7e8bf5e4166f09f8ded7a0849ca6c2d2a59478f7d90f78f20d8048bca3cdf8be09d8e8a10790388f3 + languageName: node + linkType: hard + +"randomfill@npm:^1.0.4": + version: 1.0.4 + resolution: "randomfill@npm:1.0.4" + dependencies: + randombytes: "npm:^2.0.5" + safe-buffer: "npm:^5.1.0" + checksum: 10c0/11aeed35515872e8f8a2edec306734e6b74c39c46653607f03c68385ab8030e2adcc4215f76b5e4598e028c4750d820afd5c65202527d831d2a5f207fe2bc87c + languageName: node + linkType: hard + "react-dom@npm:19": version: 19.1.0 resolution: "react-dom@npm:19.1.0" @@ -11977,18 +12608,7 @@ __metadata: languageName: node linkType: hard -"readable-stream@npm:^3.4.0": - version: 3.6.2 - resolution: "readable-stream@npm:3.6.2" - dependencies: - inherits: "npm:^2.0.3" - string_decoder: "npm:^1.1.1" - util-deprecate: "npm:^1.0.1" - checksum: 10c0/e37be5c79c376fdd088a45fa31ea2e423e5d48854be7a22a58869b4e84d25047b193f6acb54f1012331e1bcd667ffb569c01b99d36b0bd59658fb33f513511b7 - languageName: node - linkType: hard - -"readable-stream@npm:~2.3.6": +"readable-stream@npm:^2.3.8, readable-stream@npm:~2.3.6": version: 2.3.8 resolution: "readable-stream@npm:2.3.8" dependencies: @@ -12003,6 +12623,17 @@ __metadata: languageName: node linkType: hard +"readable-stream@npm:^3.4.0, readable-stream@npm:^3.5.0, readable-stream@npm:^3.6.0": + version: 3.6.2 + resolution: "readable-stream@npm:3.6.2" + dependencies: + inherits: "npm:^2.0.3" + string_decoder: "npm:^1.1.1" + util-deprecate: "npm:^1.0.1" + checksum: 10c0/e37be5c79c376fdd088a45fa31ea2e423e5d48854be7a22a58869b4e84d25047b193f6acb54f1012331e1bcd667ffb569c01b99d36b0bd59658fb33f513511b7 + languageName: node + linkType: hard + "readdirp@npm:^4.0.1": version: 4.1.2 resolution: "readdirp@npm:4.1.2" @@ -12219,6 +12850,19 @@ __metadata: languageName: node linkType: hard +"resolve@npm:^1.17.0": + version: 1.22.11 + resolution: "resolve@npm:1.22.11" + dependencies: + is-core-module: "npm:^2.16.1" + path-parse: "npm:^1.0.7" + supports-preserve-symlinks-flag: "npm:^1.0.0" + bin: + resolve: bin/resolve + checksum: 10c0/f657191507530f2cbecb5815b1ee99b20741ea6ee02a59c57028e9ec4c2c8d7681afcc35febbd554ac0ded459db6f2d8153382c53a2f266cee2575e512674409 + languageName: node + linkType: hard + "resolve@npm:^1.22.10": version: 1.22.10 resolution: "resolve@npm:1.22.10" @@ -12258,6 +12902,19 @@ __metadata: languageName: node linkType: hard +"resolve@patch:resolve@npm%3A^1.17.0#optional!builtin": + version: 1.22.11 + resolution: "resolve@patch:resolve@npm%3A1.22.11#optional!builtin::version=1.22.11&hash=c3c19d" + dependencies: + is-core-module: "npm:^2.16.1" + path-parse: "npm:^1.0.7" + supports-preserve-symlinks-flag: "npm:^1.0.0" + bin: + resolve: bin/resolve + checksum: 10c0/ee5b182f2e37cb1165465e58c6abc797fec0a80b5ba3231607beb4677db0c9291ac010c47cf092b6daa2b7f518d69a0e21888e7e2b633f68d501a874212a8c63 + languageName: node + linkType: hard + "resolve@patch:resolve@npm%3A^1.22.10#optional!builtin": version: 1.22.10 resolution: "resolve@patch:resolve@npm%3A1.22.10#optional!builtin::version=1.22.10&hash=c3c19d" @@ -12331,6 +12988,16 @@ __metadata: languageName: node linkType: hard +"ripemd160@npm:^2.0.0, ripemd160@npm:^2.0.1, ripemd160@npm:^2.0.3": + version: 2.0.3 + resolution: "ripemd160@npm:2.0.3" + dependencies: + hash-base: "npm:^3.1.2" + inherits: "npm:^2.0.4" + checksum: 10c0/3f472fb453241cfe692a77349accafca38dbcdc9d96d5848c088b2932ba41eb968630ecff7b175d291c7487a4945aee5a81e30c064d1f94e36070f7e0c37ed6c + languageName: node + linkType: hard + "rollup@npm:^4.43.0": version: 4.50.1 resolution: "rollup@npm:4.50.1" @@ -12478,6 +13145,13 @@ __metadata: languageName: node linkType: hard +"safe-buffer@npm:^5.0.1, safe-buffer@npm:^5.1.0, safe-buffer@npm:^5.1.1, safe-buffer@npm:^5.1.2, safe-buffer@npm:^5.2.1, safe-buffer@npm:~5.2.0": + version: 5.2.1 + resolution: "safe-buffer@npm:5.2.1" + checksum: 10c0/6501914237c0a86e9675d4e51d89ca3c21ffd6a31642efeba25ad65720bce6921c9e7e974e5be91a786b25aa058b5303285d3c15dbabf983a919f5f630d349f3 + languageName: node + linkType: hard + "safe-buffer@npm:~5.1.0, safe-buffer@npm:~5.1.1": version: 5.1.2 resolution: "safe-buffer@npm:5.1.2" @@ -12485,13 +13159,6 @@ __metadata: languageName: node linkType: hard -"safe-buffer@npm:~5.2.0": - version: 5.2.1 - resolution: "safe-buffer@npm:5.2.1" - checksum: 10c0/6501914237c0a86e9675d4e51d89ca3c21ffd6a31642efeba25ad65720bce6921c9e7e974e5be91a786b25aa058b5303285d3c15dbabf983a919f5f630d349f3 - languageName: node - linkType: hard - "safe-push-apply@npm:^1.0.0": version: 1.0.0 resolution: "safe-push-apply@npm:1.0.0" @@ -12665,6 +13332,26 @@ __metadata: languageName: node linkType: hard +"setimmediate@npm:^1.0.4": + version: 1.0.5 + resolution: "setimmediate@npm:1.0.5" + checksum: 10c0/5bae81bfdbfbd0ce992893286d49c9693c82b1bcc00dcaaf3a09c8f428fdeacf4190c013598b81875dfac2b08a572422db7df779a99332d0fce186d15a3e4d49 + languageName: node + linkType: hard + +"sha.js@npm:^2.4.0, sha.js@npm:^2.4.12, sha.js@npm:^2.4.8": + version: 2.4.12 + resolution: "sha.js@npm:2.4.12" + dependencies: + inherits: "npm:^2.0.4" + safe-buffer: "npm:^5.2.1" + to-buffer: "npm:^1.2.0" + bin: + sha.js: bin.js + checksum: 10c0/9d36bdd76202c8116abbe152a00055ccd8a0099cb28fc17c01fa7bb2c8cffb9ca60e2ab0fe5f274ed6c45dc2633d8c39cf7ab050306c231904512ba9da4d8ab1 + languageName: node + linkType: hard + "shebang-command@npm:^2.0.0": version: 2.0.0 resolution: "shebang-command@npm:2.0.0" @@ -12909,6 +13596,16 @@ __metadata: languageName: node linkType: hard +"stream-browserify@npm:^3.0.0": + version: 3.0.0 + resolution: "stream-browserify@npm:3.0.0" + dependencies: + inherits: "npm:~2.0.4" + readable-stream: "npm:^3.5.0" + checksum: 10c0/ec3b975a4e0aa4b3dc5e70ffae3fc8fd29ac725353a14e72f213dff477b00330140ad014b163a8cbb9922dfe90803f81a5ea2b269e1bbfd8bd71511b88f889ad + languageName: node + linkType: hard + "stream-composer@npm:^1.0.2": version: 1.0.2 resolution: "stream-composer@npm:1.0.2" @@ -12918,6 +13615,18 @@ __metadata: languageName: node linkType: hard +"stream-http@npm:^3.2.0": + version: 3.2.0 + resolution: "stream-http@npm:3.2.0" + dependencies: + builtin-status-codes: "npm:^3.0.0" + inherits: "npm:^2.0.4" + readable-stream: "npm:^3.6.0" + xtend: "npm:^4.0.2" + checksum: 10c0/f128fb8076d60cd548f229554b6a1a70c08a04b7b2afd4dbe7811d20f27f7d4112562eb8bce86d72a8691df3b50573228afcf1271e55e81f981536c67498bc41 + languageName: node + linkType: hard + "streamx@npm:^2.12.0, streamx@npm:^2.12.5, streamx@npm:^2.13.2, streamx@npm:^2.14.0": version: 2.22.0 resolution: "streamx@npm:2.22.0" @@ -13034,7 +13743,7 @@ __metadata: languageName: node linkType: hard -"string_decoder@npm:^1.1.1": +"string_decoder@npm:^1.0.0, string_decoder@npm:^1.1.1": version: 1.3.0 resolution: "string_decoder@npm:1.3.0" dependencies: @@ -13236,6 +13945,15 @@ __metadata: languageName: node linkType: hard +"timers-browserify@npm:^2.0.4": + version: 2.0.12 + resolution: "timers-browserify@npm:2.0.12" + dependencies: + setimmediate: "npm:^1.0.4" + checksum: 10c0/98e84db1a685bc8827c117a8bc62aac811ad56a995d07938fc7ed8cdc5bf3777bfe2d4e5da868847194e771aac3749a20f6cdd22091300fe889a76fe214a4641 + languageName: node + linkType: hard + "tinybench@npm:^2.9.0": version: 2.9.0 resolution: "tinybench@npm:2.9.0" @@ -13309,6 +14027,17 @@ __metadata: languageName: node linkType: hard +"to-buffer@npm:^1.2.0, to-buffer@npm:^1.2.1, to-buffer@npm:^1.2.2": + version: 1.2.2 + resolution: "to-buffer@npm:1.2.2" + dependencies: + isarray: "npm:^2.0.5" + safe-buffer: "npm:^5.2.1" + typed-array-buffer: "npm:^1.0.3" + checksum: 10c0/56bc56352f14a2c4a0ab6277c5fc19b51e9534882b98eb068b39e14146591e62fa5b06bf70f7fed1626230463d7e60dca81e815096656e5e01c195c593873d12 + languageName: node + linkType: hard + "to-regex-range@npm:^5.0.1": version: 5.0.1 resolution: "to-regex-range@npm:5.0.1" @@ -13446,6 +14175,13 @@ __metadata: languageName: node linkType: hard +"tty-browserify@npm:0.0.1": + version: 0.0.1 + resolution: "tty-browserify@npm:0.0.1" + checksum: 10c0/5e34883388eb5f556234dae75b08e069b9e62de12bd6d87687f7817f5569430a6dfef550b51dbc961715ae0cd0eb5a059e6e3fc34dc127ea164aa0f9b5bb033d + languageName: node + linkType: hard + "tunnel@npm:^0.0.6": version: 0.0.6 resolution: "tunnel@npm:0.0.6" @@ -13780,6 +14516,16 @@ __metadata: languageName: node linkType: hard +"url@npm:^0.11.4": + version: 0.11.4 + resolution: "url@npm:0.11.4" + dependencies: + punycode: "npm:^1.4.1" + qs: "npm:^6.12.3" + checksum: 10c0/cc93405ae4a9b97a2aa60ca67f1cb1481c0221cb4725a7341d149be5e2f9cfda26fd432d64dbbec693d16593b68b8a46aad8e5eab21f814932134c9d8620c662 + languageName: node + linkType: hard + "use-callback-ref@npm:^1.3.3": version: 1.3.3 resolution: "use-callback-ref@npm:1.3.3" @@ -13829,6 +14575,19 @@ __metadata: languageName: node linkType: hard +"util@npm:^0.12.4, util@npm:^0.12.5": + version: 0.12.5 + resolution: "util@npm:0.12.5" + dependencies: + inherits: "npm:^2.0.3" + is-arguments: "npm:^1.0.4" + is-generator-function: "npm:^1.0.7" + is-typed-array: "npm:^1.1.3" + which-typed-array: "npm:^1.1.2" + checksum: 10c0/c27054de2cea2229a66c09522d0fa1415fb12d861d08523a8846bf2e4cbf0079d4c3f725f09dcb87493549bcbf05f5798dce1688b53c6c17201a45759e7253f3 + languageName: node + linkType: hard + "uuid@npm:13": version: 13.0.0 resolution: "uuid@npm:13.0.0" @@ -13975,6 +14734,30 @@ __metadata: languageName: node linkType: hard +"vite-plugin-node-stdlib-browser@npm:^0.2.1": + version: 0.2.1 + resolution: "vite-plugin-node-stdlib-browser@npm:0.2.1" + dependencies: + "@rollup/plugin-inject": "npm:^5.0.3" + peerDependencies: + node-stdlib-browser: ^1.2.0 + vite: ^2.0.0 || ^3.0.0 || ^4.0.0 + checksum: 10c0/4686bde59d0396d8684433e1a14ddce868dc422f80e306a0c1cb5e86564d9f7c38a67865ca339e4ff57784ec4bada149034038cad6911a2dfcac8debfc9bd20a + languageName: node + linkType: hard + +"vite-plugin-singlefile@npm:^2.3.0": + version: 2.3.0 + resolution: "vite-plugin-singlefile@npm:2.3.0" + dependencies: + micromatch: "npm:^4.0.8" + peerDependencies: + rollup: ^4.44.1 + vite: ^5.4.11 || ^6.0.0 || ^7.0.0 + checksum: 10c0/d6ebb545d749b228bbd8fd8746a954f09d000dd69d200a651358e74136947b932f7f869536e1698e0d81e2f0694357c8bec3a957101a7e77d0d3c40193eb4cf1 + languageName: node + linkType: hard + "vite-plugin-svgr@npm:^4.0.0": version: 4.3.0 resolution: "vite-plugin-svgr@npm:4.3.0" @@ -14113,6 +14896,13 @@ __metadata: languageName: node linkType: hard +"vm-browserify@npm:^1.0.1": + version: 1.1.2 + resolution: "vm-browserify@npm:1.1.2" + checksum: 10c0/0cc1af6e0d880deb58bc974921320c187f9e0a94f25570fca6b1bd64e798ce454ab87dfd797551b1b0cc1849307421aae0193cedf5f06bdb5680476780ee344b + languageName: node + linkType: hard + "void-elements@npm:3.1.0": version: 3.1.0 resolution: "void-elements@npm:3.1.0" @@ -14312,7 +15102,7 @@ __metadata: languageName: node linkType: hard -"which-typed-array@npm:^1.1.19": +"which-typed-array@npm:^1.1.19, which-typed-array@npm:^1.1.2": version: 1.1.19 resolution: "which-typed-array@npm:1.1.19" dependencies: @@ -14437,7 +15227,7 @@ __metadata: languageName: node linkType: hard -"xtend@npm:~4.0.1": +"xtend@npm:^4.0.2, xtend@npm:~4.0.1": version: 4.0.2 resolution: "xtend@npm:4.0.2" checksum: 10c0/366ae4783eec6100f8a02dff02ac907bf29f9a00b82ac0264b4d8b832ead18306797e283cf19de776538babfdcb2101375ec5646b59f08c52128ac4ab812ed0e From 0e04fd9433a402e29e8517382345bf6d2e7e8ae4 Mon Sep 17 00:00:00 2001 From: Valere Date: Tue, 2 Dec 2025 14:14:28 +0100 Subject: [PATCH 041/748] fix: The handset mode overlay is visible a split second for every call --- src/room/EarpieceOverlay.module.css | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/room/EarpieceOverlay.module.css b/src/room/EarpieceOverlay.module.css index d0757cdb1..e007fc447 100644 --- a/src/room/EarpieceOverlay.module.css +++ b/src/room/EarpieceOverlay.module.css @@ -2,7 +2,7 @@ position: fixed; z-index: var(--call-view-overlay-layer); inset: 0; - display: flex; + display: none; flex-direction: column; align-items: center; justify-content: center; @@ -12,6 +12,7 @@ @keyframes fade-in { from { opacity: 0; + display: flex; } to { opacity: 1; From 83ea154e1a4c83d5e171a417e99ed4108f7f0192 Mon Sep 17 00:00:00 2001 From: Robin Date: Tue, 2 Dec 2025 10:36:53 -0500 Subject: [PATCH 042/748] Fix the wrong layout being used until window size changes While looking into what had regressed https://github.com/element-hq/element-call/issues/3588, I found that 28047217b85e2e6f491c887ac7099499662fa46e had filled in a couple of behaviors with non-reactive default values, the "natural window mode" behavior being among them. This meant that the app would no longer determine the correct window mode upon joining a call, instead always guessing "normal" as the value. This change restores its reactivity. --- src/state/CallViewModel/CallViewModel.test.ts | 42 +++++++++++++++++++ src/state/CallViewModel/CallViewModel.ts | 19 ++++++--- .../CallViewModel/CallViewModelTestUtils.ts | 3 ++ 3 files changed, 59 insertions(+), 5 deletions(-) diff --git a/src/state/CallViewModel/CallViewModel.test.ts b/src/state/CallViewModel/CallViewModel.test.ts index ef59270f6..2e5b57008 100644 --- a/src/state/CallViewModel/CallViewModel.test.ts +++ b/src/state/CallViewModel/CallViewModel.test.ts @@ -502,6 +502,48 @@ describe("CallViewModel", () => { }); }); + test("layout reacts to window size", () => { + withTestScheduler(({ behavior, schedule, expectObservable }) => { + const windowSizeInputMarbles = "abc"; + const expectedLayoutMarbles = " abc"; + withCallViewModel( + { + remoteParticipants$: constant([aliceParticipant]), + rtcMembers$: constant([localRtcMember, aliceRtcMember]), + windowSize$: behavior(windowSizeInputMarbles, { + a: { width: 300, height: 600 }, // Start very narrow, like a phone + b: { width: 1000, height: 800 }, // Go to normal desktop window size + c: { width: 200, height: 180 }, // Go to PiP size + }), + }, + (vm) => { + expectObservable(summarizeLayout$(vm.layout$)).toBe( + expectedLayoutMarbles, + { + a: { + // This is the expected one-on-one layout for a narrow window + type: "spotlight-expanded", + spotlight: [`${aliceId}:0`], + pip: `${localId}:0`, + }, + b: { + // In a larger window, expect the normal one-on-one layout + type: "one-on-one", + local: `${localId}:0`, + remote: `${aliceId}:0`, + }, + c: { + // In a PiP-sized window, we of course expect a PiP layout + type: "pip", + spotlight: [`${aliceId}:0`], + }, + }, + ); + }, + ); + }); + }); + test("spotlight speakers swap places", () => { withTestScheduler(({ behavior, schedule, expectObservable }) => { // Go immediately into spotlight mode for the test diff --git a/src/state/CallViewModel/CallViewModel.ts b/src/state/CallViewModel/CallViewModel.ts index 3c15958ae..c8f5d8369 100644 --- a/src/state/CallViewModel/CallViewModel.ts +++ b/src/state/CallViewModel/CallViewModel.ts @@ -147,6 +147,8 @@ export interface CallViewModelOptions { livekitRoomFactory?: (options?: RoomOptions) => LivekitRoom; /** Optional behavior overriding the local connection state, mainly for testing purposes. */ connectionState$?: Behavior; + /** Optional behavior overriding the computed window size, mainly for testing purposes. */ + windowSize$?: Behavior<{ width: number; height: number }>; } // Do not play any sounds if the participant count has exceeded this @@ -949,11 +951,19 @@ export function createCallViewModel$( const pipEnabled$ = scope.behavior(setPipEnabled$, false); + const windowSize$ = + options.windowSize$ ?? + scope.behavior<{ width: number; height: number }>( + fromEvent(window, "resize").pipe( + startWith(null), + map(() => ({ width: window.innerWidth, height: window.innerHeight })), + ), + ); + + // A guess at what the window's mode should be based on its size and shape. const naturalWindowMode$ = scope.behavior( - fromEvent(window, "resize").pipe( - map(() => { - const height = window.innerHeight; - const width = window.innerWidth; + windowSize$.pipe( + map(({ width, height }) => { if (height <= 400 && width <= 340) return "pip"; // Our layouts for flat windows are better at adapting to a small width // than our layouts for narrow windows are at adapting to a small height, @@ -963,7 +973,6 @@ export function createCallViewModel$( return "normal"; }), ), - "normal", ); /** diff --git a/src/state/CallViewModel/CallViewModelTestUtils.ts b/src/state/CallViewModel/CallViewModelTestUtils.ts index f86921c5f..f80b4bcbe 100644 --- a/src/state/CallViewModel/CallViewModelTestUtils.ts +++ b/src/state/CallViewModel/CallViewModelTestUtils.ts @@ -75,6 +75,7 @@ export interface CallViewModelInputs { speaking: Map>; mediaDevices: MediaDevices; initialSyncState: SyncState; + windowSize$: Behavior<{ width: number; height: number }>; } const localParticipant = mockLocalParticipant({ identity: "" }); @@ -89,6 +90,7 @@ export function withCallViewModel( speaking = new Map(), mediaDevices = mockMediaDevices({}), initialSyncState = SyncState.Syncing, + windowSize$ = constant({ width: 1000, height: 800 }), }: Partial = {}, continuation: ( vm: CallViewModel, @@ -173,6 +175,7 @@ export function withCallViewModel( setE2EEEnabled: async () => Promise.resolve(), }), connectionState$, + windowSize$, }, raisedHands$, reactions$, From 44980a2744e5f5b198c83e5de91f7d03aba0ab93 Mon Sep 17 00:00:00 2001 From: Valere Date: Tue, 2 Dec 2025 16:39:26 +0100 Subject: [PATCH 043/748] review: rename `deviceConnected` to `canControlDevices` --- src/state/MuteStates.ts | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/state/MuteStates.ts b/src/state/MuteStates.ts index f1d61db58..632e04262 100644 --- a/src/state/MuteStates.ts +++ b/src/state/MuteStates.ts @@ -61,7 +61,7 @@ export class MuteState { this.handler$.next(defaultHandler); } - private readonly devicesConnected$ = combineLatest([ + private readonly canControlDevices$ = combineLatest([ this.device.available$, this.forceMute$, ]).pipe( @@ -71,17 +71,17 @@ export class MuteState { ); private readonly data$ = this.scope.behavior( - this.devicesConnected$.pipe( + this.canControlDevices$.pipe( distinctUntilChanged(), withLatestFrom( this.enabledByDefault$, - (devicesConnected, enabledByDefault) => { + (canControlDevices, enabledByDefault) => { logger.info( - `MuteState: devices connected: ${devicesConnected}, enabled by default: ${enabledByDefault}`, + `MuteState: canControlDevices: ${canControlDevices}, enabled by default: ${enabledByDefault}`, ); - if (!devicesConnected) { + if (!canControlDevices) { logger.info( - `MuteState: devices connected: ${devicesConnected}, disabling`, + `MuteState: devices connected: ${canControlDevices}, disabling`, ); // We need to sync the mute state with the handler // to ensure nothing is beeing published. From be0c7eb365c863457a2f69271612f5ce0dabd854 Mon Sep 17 00:00:00 2001 From: Valere Date: Tue, 2 Dec 2025 17:43:58 +0100 Subject: [PATCH 044/748] review: fix mock import module --- .../CallViewModel/remoteMembers/ECConnectionFactory.test.ts | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/state/CallViewModel/remoteMembers/ECConnectionFactory.test.ts b/src/state/CallViewModel/remoteMembers/ECConnectionFactory.test.ts index 78e230573..0c439a6b1 100644 --- a/src/state/CallViewModel/remoteMembers/ECConnectionFactory.test.ts +++ b/src/state/CallViewModel/remoteMembers/ECConnectionFactory.test.ts @@ -20,10 +20,9 @@ import type { ProcessorState } from "../../../livekit/TrackProcessorContext.tsx" import { constant } from "../../Behavior"; // At the top of your test file, after imports -vi.mock("livekit-client", async () => { - const actual = await vi.importActual("livekit-client"); +vi.mock("livekit-client", async (importOriginal) => { return { - ...actual, + ...(await importOriginal()), Room: vi.fn().mockImplementation(function (this: LivekitRoom, options) { const emitter = new EventEmitter(); return { From ac9acc0158f2f4c885ef29634053a5c41674d32a Mon Sep 17 00:00:00 2001 From: Valere Date: Tue, 2 Dec 2025 17:47:00 +0100 Subject: [PATCH 045/748] review: refactor convert params to object for generateRoomOption --- .../remoteMembers/ConnectionFactory.ts | 38 ++++++++++++------- 1 file changed, 24 insertions(+), 14 deletions(-) diff --git a/src/state/CallViewModel/remoteMembers/ConnectionFactory.ts b/src/state/CallViewModel/remoteMembers/ConnectionFactory.ts index c3a68c54b..8a3175e1f 100644 --- a/src/state/CallViewModel/remoteMembers/ConnectionFactory.ts +++ b/src/state/CallViewModel/remoteMembers/ConnectionFactory.ts @@ -59,19 +59,19 @@ export class ECConnectionFactory implements ConnectionFactory { ) { const defaultFactory = (): LivekitRoom => new LivekitRoom( - generateRoomOption( - this.devices, - this.processorState$.value, - livekitKeyProvider && { + generateRoomOption({ + devices: this.devices, + processorState: this.processorState$.value, + e2eeLivekitOptions: livekitKeyProvider && { keyProvider: livekitKeyProvider, // It's important that every room use a separate E2EE worker. // They get confused if given streams from multiple rooms. worker: new E2EEWorker(), }, - this.controlledAudioDevices, + controlledAudioDevices: this.controlledAudioDevices, echoCancellation, noiseSuppression, - ), + }), ); this.livekitRoomFactory = livekitRoomFactory ?? defaultFactory; } @@ -96,14 +96,24 @@ export class ECConnectionFactory implements ConnectionFactory { /** * Generate the initial LiveKit RoomOptions based on the current media devices and processor state. */ -function generateRoomOption( - devices: MediaDevices, - processorState: ProcessorState, - e2eeLivekitOptions: E2EEOptions | undefined, - controlledAudioDevices: boolean, - echoCancellation: boolean, - noiseSuppression: boolean, -): RoomOptions { +function generateRoomOption({ + devices, + processorState, + e2eeLivekitOptions, + controlledAudioDevices, + echoCancellation, + noiseSuppression, +}: { + devices: MediaDevices; + processorState: ProcessorState; + e2eeLivekitOptions: + | E2EEManagerOptions + | { e2eeManager: BaseE2EEManager } + | undefined; + controlledAudioDevices: boolean; + echoCancellation: boolean; + noiseSuppression: boolean; +}): RoomOptions { return { ...defaultLiveKitOptions, videoCaptureDefaults: { From f6a3a371cbf6259fbb8b798e40e0aff92b3eecec Mon Sep 17 00:00:00 2001 From: Valere Date: Tue, 2 Dec 2025 17:52:27 +0100 Subject: [PATCH 046/748] fix lint --- src/state/CallViewModel/remoteMembers/ConnectionFactory.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/state/CallViewModel/remoteMembers/ConnectionFactory.ts b/src/state/CallViewModel/remoteMembers/ConnectionFactory.ts index 8a3175e1f..7c3a9eab3 100644 --- a/src/state/CallViewModel/remoteMembers/ConnectionFactory.ts +++ b/src/state/CallViewModel/remoteMembers/ConnectionFactory.ts @@ -7,10 +7,11 @@ Please see LICENSE in the repository root for full details. import { type LivekitTransport } from "matrix-js-sdk/lib/matrixrtc"; import { - type E2EEOptions, Room as LivekitRoom, type RoomOptions, type BaseKeyProvider, + type E2EEManagerOptions, + type BaseE2EEManager, } from "livekit-client"; import { type Logger } from "matrix-js-sdk/lib/logger"; import E2EEWorker from "livekit-client/e2ee-worker?worker"; From 2e646bfac163ea48b45de6fc8a22d52e8a0e01cd Mon Sep 17 00:00:00 2001 From: Timo K Date: Tue, 2 Dec 2025 19:40:08 +0100 Subject: [PATCH 047/748] Unify LiveKit and Matrix connection states --- src/room/GroupCallView.tsx | 1 + src/state/CallViewModel/CallViewModel.ts | 47 ++-- .../localMember/HomeserverConnected.test.ts | 58 ++--- .../localMember/HomeserverConnected.ts | 38 +-- .../localMember/LocalMembership.test.ts | 26 +- .../localMember/LocalMembership.ts | 244 +++++++++--------- .../localMember/Publisher.test.ts | 3 +- .../CallViewModel/localMember/Publisher.ts | 2 +- .../remoteMembers/Connection.test.ts | 9 +- .../CallViewModel/remoteMembers/Connection.ts | 43 +-- 10 files changed, 238 insertions(+), 233 deletions(-) diff --git a/src/room/GroupCallView.tsx b/src/room/GroupCallView.tsx index 75438f7f0..43602716d 100644 --- a/src/room/GroupCallView.tsx +++ b/src/room/GroupCallView.tsx @@ -160,6 +160,7 @@ export const GroupCallView: FC = ({ }, [rtcSession]); // TODO move this into the callViewModel LocalMembership.ts + // We might actually not need this at all. Since we get into fatalError on those errors already? useTypedEventEmitter( rtcSession, MatrixRTCSessionEvent.MembershipManagerError, diff --git a/src/state/CallViewModel/CallViewModel.ts b/src/state/CallViewModel/CallViewModel.ts index 3c15958ae..9bfa979c7 100644 --- a/src/state/CallViewModel/CallViewModel.ts +++ b/src/state/CallViewModel/CallViewModel.ts @@ -452,18 +452,14 @@ export function createCallViewModel$( const localMembership = createLocalMembership$({ scope: scope, - homeserverConnected$: createHomeserverConnected$( + homeserverConnected: createHomeserverConnected$( scope, client, matrixRTCSession, ), muteStates: muteStates, - joinMatrixRTC: async (transport: LivekitTransport) => { - return enterRTCSession( - matrixRTCSession, - transport, - connectOptions$.value, - ); + joinMatrixRTC: (transport: LivekitTransport) => { + enterRTCSession(matrixRTCSession, transport, connectOptions$.value); }, createPublisherFactory: (connection: Connection) => { return new Publisher( @@ -573,17 +569,6 @@ export function createCallViewModel$( ), ); - /** - * Whether various media/event sources should pretend to be disconnected from - * all network input, even if their connection still technically works. - */ - // We do this when the app is in the 'reconnecting' state, because it might be - // that the LiveKit connection is still functional while the homeserver is - // down, for example, and we want to avoid making people worry that the app is - // in a split-brained state. - // DISCUSSION own membership manager ALSO this probably can be simplifis - const reconnecting$ = localMembership.reconnecting$; - const audioParticipants$ = scope.behavior( matrixLivekitMembers$.pipe( switchMap((membersWithEpoch) => { @@ -631,7 +616,7 @@ export function createCallViewModel$( ); const handsRaised$ = scope.behavior( - handsRaisedSubject$.pipe(pauseWhen(reconnecting$)), + handsRaisedSubject$.pipe(pauseWhen(localMembership.reconnecting$)), ); const reactions$ = scope.behavior( @@ -644,7 +629,7 @@ export function createCallViewModel$( ]), ), ), - pauseWhen(reconnecting$), + pauseWhen(localMembership.reconnecting$), ), ); @@ -735,7 +720,7 @@ export function createCallViewModel$( livekitRoom$, focusUrl$, mediaDevices, - reconnecting$, + localMembership.reconnecting$, displayName$, matrixMemberMetadataStore.createAvatarUrlBehavior$(userId), handsRaised$.pipe(map((v) => v[participantId]?.time ?? null)), @@ -827,11 +812,17 @@ export function createCallViewModel$( }), ); - const leave$: Observable<"user" | "timeout" | "decline" | "allOthersLeft"> = - merge( - autoLeave$, - merge(userHangup$, widgetHangup$).pipe(map(() => "user" as const)), - ).pipe(scope.share); + const shouldLeave$: Observable< + "user" | "timeout" | "decline" | "allOthersLeft" + > = merge( + autoLeave$, + merge(userHangup$, widgetHangup$).pipe(map(() => "user" as const)), + ).pipe(scope.share); + + shouldLeave$.pipe(scope.bind()).subscribe((reason) => { + logger.info(`Call left due to ${reason}`); + localMembership.requestDisconnect(); + }); const spotlightSpeaker$ = scope.behavior( userMedia$.pipe( @@ -1453,7 +1444,7 @@ export function createCallViewModel$( autoLeave$: autoLeave$, callPickupState$: callPickupState$, ringOverlay$: ringOverlay$, - leave$: leave$, + leave$: shouldLeave$, hangup: (): void => userHangup$.next(), join: localMembership.requestConnect, toggleScreenSharing: toggleScreenSharing, @@ -1500,7 +1491,7 @@ export function createCallViewModel$( showFooter$: showFooter$, earpieceMode$: earpieceMode$, audioOutputSwitcher$: audioOutputSwitcher$, - reconnecting$: reconnecting$, + reconnecting$: localMembership.reconnecting$, }; } diff --git a/src/state/CallViewModel/localMember/HomeserverConnected.test.ts b/src/state/CallViewModel/localMember/HomeserverConnected.test.ts index 1f61e5333..87ca35d0d 100644 --- a/src/state/CallViewModel/localMember/HomeserverConnected.test.ts +++ b/src/state/CallViewModel/localMember/HomeserverConnected.test.ts @@ -97,106 +97,106 @@ describe("createHomeserverConnected$", () => { // LLM generated test cases. They are a bit overkill but I improved the mocking so it is // easy enough to read them so I think they can stay. it("is false when sync state is not Syncing", () => { - const hsConnected$ = createHomeserverConnected$(scope, client, session); - expect(hsConnected$.value).toBe(false); + const hsConnected = createHomeserverConnected$(scope, client, session); + expect(hsConnected.combined$.value).toBe(false); }); it("remains false while membership status is not Connected even if sync is Syncing", () => { - const hsConnected$ = createHomeserverConnected$(scope, client, session); + const hsConnected = createHomeserverConnected$(scope, client, session); client.setSyncState(SyncState.Syncing); - expect(hsConnected$.value).toBe(false); // membership still disconnected + expect(hsConnected.combined$.value).toBe(false); // membership still disconnected }); it("is false when membership status transitions to Connected but ProbablyLeft is true", () => { - const hsConnected$ = createHomeserverConnected$(scope, client, session); + const hsConnected = createHomeserverConnected$(scope, client, session); // Make sync loop OK client.setSyncState(SyncState.Syncing); // Indicate probable leave before connection session.setProbablyLeft(true); session.setMembershipStatus(Status.Connected); - expect(hsConnected$.value).toBe(false); + expect(hsConnected.combined$.value).toBe(false); }); it("becomes true only when all three conditions are satisfied", () => { - const hsConnected$ = createHomeserverConnected$(scope, client, session); + const hsConnected = createHomeserverConnected$(scope, client, session); // 1. Sync loop connected client.setSyncState(SyncState.Syncing); - expect(hsConnected$.value).toBe(false); // not yet membership connected + expect(hsConnected.combined$.value).toBe(false); // not yet membership connected // 2. Membership connected session.setMembershipStatus(Status.Connected); - expect(hsConnected$.value).toBe(true); // probablyLeft is false + expect(hsConnected.combined$.value).toBe(true); // probablyLeft is false }); it("drops back to false when sync loop leaves Syncing", () => { - const hsConnected$ = createHomeserverConnected$(scope, client, session); + const hsConnected = createHomeserverConnected$(scope, client, session); // Reach connected state client.setSyncState(SyncState.Syncing); session.setMembershipStatus(Status.Connected); - expect(hsConnected$.value).toBe(true); + expect(hsConnected.combined$.value).toBe(true); // Sync loop error => should flip false client.setSyncState(SyncState.Error); - expect(hsConnected$.value).toBe(false); + expect(hsConnected.combined$.value).toBe(false); }); it("drops back to false when membership status becomes disconnected", () => { - const hsConnected$ = createHomeserverConnected$(scope, client, session); + const hsConnected = createHomeserverConnected$(scope, client, session); client.setSyncState(SyncState.Syncing); session.setMembershipStatus(Status.Connected); - expect(hsConnected$.value).toBe(true); + expect(hsConnected.combined$.value).toBe(true); session.setMembershipStatus(Status.Disconnected); - expect(hsConnected$.value).toBe(false); + expect(hsConnected.combined$.value).toBe(false); }); it("drops to false when ProbablyLeft is emitted after being true", () => { - const hsConnected$ = createHomeserverConnected$(scope, client, session); + const hsConnected = createHomeserverConnected$(scope, client, session); client.setSyncState(SyncState.Syncing); session.setMembershipStatus(Status.Connected); - expect(hsConnected$.value).toBe(true); + expect(hsConnected.combined$.value).toBe(true); session.setProbablyLeft(true); - expect(hsConnected$.value).toBe(false); + expect(hsConnected.combined$.value).toBe(false); }); it("recovers to true if ProbablyLeft becomes false again while other conditions remain true", () => { - const hsConnected$ = createHomeserverConnected$(scope, client, session); + const hsConnected = createHomeserverConnected$(scope, client, session); client.setSyncState(SyncState.Syncing); session.setMembershipStatus(Status.Connected); - expect(hsConnected$.value).toBe(true); + expect(hsConnected.combined$.value).toBe(true); session.setProbablyLeft(true); - expect(hsConnected$.value).toBe(false); + expect(hsConnected.combined$.value).toBe(false); // Simulate clearing the flag (in realistic scenario membership manager would update) session.setProbablyLeft(false); - expect(hsConnected$.value).toBe(true); + expect(hsConnected.combined$.value).toBe(true); }); it("composite sequence reflects each individual failure reason", () => { - const hsConnected$ = createHomeserverConnected$(scope, client, session); + const hsConnected = createHomeserverConnected$(scope, client, session); // Initially false (sync error + disconnected + not probably left) - expect(hsConnected$.value).toBe(false); + expect(hsConnected.combined$.value).toBe(false); // Fix sync only client.setSyncState(SyncState.Syncing); - expect(hsConnected$.value).toBe(false); + expect(hsConnected.combined$.value).toBe(false); // Fix membership session.setMembershipStatus(Status.Connected); - expect(hsConnected$.value).toBe(true); + expect(hsConnected.combined$.value).toBe(true); // Introduce probablyLeft -> false session.setProbablyLeft(true); - expect(hsConnected$.value).toBe(false); + expect(hsConnected.combined$.value).toBe(false); // Restore notProbablyLeft -> true again session.setProbablyLeft(false); - expect(hsConnected$.value).toBe(true); + expect(hsConnected.combined$.value).toBe(true); // Drop sync -> false client.setSyncState(SyncState.Error); - expect(hsConnected$.value).toBe(false); + expect(hsConnected.combined$.value).toBe(false); }); }); diff --git a/src/state/CallViewModel/localMember/HomeserverConnected.ts b/src/state/CallViewModel/localMember/HomeserverConnected.ts index e1c280785..c8bcd0217 100644 --- a/src/state/CallViewModel/localMember/HomeserverConnected.ts +++ b/src/state/CallViewModel/localMember/HomeserverConnected.ts @@ -25,6 +25,11 @@ import { type NodeStyleEventEmitter } from "../../../utils/test"; */ const logger = rootLogger.getChild("[HomeserverConnected]"); +export interface HomeserverConnected { + combined$: Behavior; + rtsSession$: Behavior; +} + /** * Behavior representing whether we consider ourselves connected to the Matrix homeserver * for the purposes of a MatrixRTC session. @@ -39,7 +44,7 @@ export function createHomeserverConnected$( client: NodeStyleEventEmitter & Pick, matrixRTCSession: NodeStyleEventEmitter & Pick, -): Behavior { +): HomeserverConnected { const syncing$ = ( fromEvent(client, ClientEvent.Sync) as Observable<[SyncState]> ).pipe( @@ -47,12 +52,15 @@ export function createHomeserverConnected$( map(([state]) => state === SyncState.Syncing), ); - const membershipConnected$ = fromEvent( - matrixRTCSession, - MembershipManagerEvent.StatusChanged, - ).pipe( - startWith(null), - map(() => matrixRTCSession.membershipStatus === Status.Connected), + const rtsSession$ = scope.behavior( + fromEvent(matrixRTCSession, MembershipManagerEvent.StatusChanged).pipe( + map(() => matrixRTCSession.membershipStatus ?? Status.Unknown), + ), + Status.Unknown, + ); + + const membershipConnected$ = rtsSession$.pipe( + map((status) => status === Status.Connected), ); // This is basically notProbablyLeft$ @@ -71,15 +79,13 @@ export function createHomeserverConnected$( map(() => matrixRTCSession.probablyLeft !== true), ); - const connectedCombined$ = and$( - syncing$, - membershipConnected$, - certainlyConnected$, - ).pipe( - tap((connected) => { - logger.info(`Homeserver connected update: ${connected}`); - }), + const combined$ = scope.behavior( + and$(syncing$, membershipConnected$, certainlyConnected$).pipe( + tap((connected) => { + logger.info(`Homeserver connected update: ${connected}`); + }), + ), ); - return scope.behavior(connectedCombined$); + return { combined$, rtsSession$ }; } diff --git a/src/state/CallViewModel/localMember/LocalMembership.test.ts b/src/state/CallViewModel/localMember/LocalMembership.test.ts index cff5c06dc..1ef7abd63 100644 --- a/src/state/CallViewModel/localMember/LocalMembership.test.ts +++ b/src/state/CallViewModel/localMember/LocalMembership.test.ts @@ -7,6 +7,7 @@ Please see LICENSE in the repository root for full details. */ import { + Status, type LivekitTransport, type MatrixRTCSession, } from "matrix-js-sdk/lib/matrixrtc"; @@ -51,7 +52,7 @@ vi.mock("@livekit/components-core", () => ({ describe("LocalMembership", () => { describe("enterRTCSession", () => { - it("It joins the correct Session", async () => { + it("It joins the correct Session", () => { const focusFromOlderMembership = { type: "livekit", livekit_service_url: "http://my-oldest-member-service-url.com", @@ -107,7 +108,7 @@ describe("LocalMembership", () => { joinRoomSession: vi.fn(), }) as unknown as MatrixRTCSession; - await enterRTCSession( + enterRTCSession( mockedSession, { livekit_alias: "roomId", @@ -136,7 +137,7 @@ describe("LocalMembership", () => { ); }); - it("It should not fail with configuration error if homeserver config has livekit url but not fallback", async () => { + it("It should not fail with configuration error if homeserver config has livekit url but not fallback", () => { mockConfig({}); vi.spyOn(AutoDiscovery, "getRawClientConfig").mockResolvedValue({ "org.matrix.msc4143.rtc_foci": [ @@ -165,7 +166,7 @@ describe("LocalMembership", () => { joinRoomSession: vi.fn(), }) as unknown as MatrixRTCSession; - await enterRTCSession( + enterRTCSession( mockedSession, { livekit_alias: "roomId", @@ -190,7 +191,6 @@ describe("LocalMembership", () => { leaveRoomSession: () => {}, } as unknown as MatrixRTCSession, muteStates: mockMuteStates(), - isHomeserverConnected: constant(true), trackProcessorState$: constant({ supported: false, processor: undefined, @@ -198,7 +198,10 @@ describe("LocalMembership", () => { logger: logger, createPublisherFactory: vi.fn(), joinMatrixRTC: async (): Promise => {}, - homeserverConnected$: constant(true), + homeserverConnected: { + combined$: constant(true), + rtsSession$: constant(Status.Connected), + }, }; it("throws error on missing RTC config error", () => { @@ -258,8 +261,7 @@ describe("LocalMembership", () => { } as unknown as LocalParticipant, }), state$: constant({ - state: "ConnectedToLkRoom", - livekitConnectionState$: constant(LivekitConnectionState.Connected), + state: LivekitConnectionState.Connected, }), transport: aTransport, } as unknown as Connection, @@ -268,7 +270,7 @@ describe("LocalMembership", () => { connectionManagerData.add( { state$: constant({ - state: "ConnectedToLkRoom", + state: LivekitConnectionState.Connected, }), transport: bTransport, } as unknown as Connection, @@ -443,7 +445,7 @@ describe("LocalMembership", () => { connectionManagerData$.next(new Epoch(connectionManagerData)); await flushPromises(); expect(localMembership.connectionState.livekit$.value).toStrictEqual({ - state: RTCBackendState.Initialized, + state: LivekitConnectionState.Connected, }); expect(publisherFactory).toHaveBeenCalledOnce(); expect(localMembership.tracks$.value.length).toBe(0); @@ -473,7 +475,7 @@ describe("LocalMembership", () => { publishResolver.resolve(); await flushPromises(); expect(localMembership.connectionState.livekit$.value).toStrictEqual({ - state: RTCBackendState.Connected, + state: RTCBackendState.ConnectedAndPublishing, }); expect(publishers[0].stopPublishing).not.toHaveBeenCalled(); @@ -482,7 +484,7 @@ describe("LocalMembership", () => { await flushPromises(); // stays in connected state because it is stopped before the update to tracks update the state. expect(localMembership.connectionState.livekit$.value).toStrictEqual({ - state: RTCBackendState.Connected, + state: RTCBackendState.ConnectedAndPublishing, }); // stop all tracks after ending scopes expect(publishers[0].stopPublishing).toHaveBeenCalled(); diff --git a/src/state/CallViewModel/localMember/LocalMembership.ts b/src/state/CallViewModel/localMember/LocalMembership.ts index 60ae79b8e..33af51924 100644 --- a/src/state/CallViewModel/localMember/LocalMembership.ts +++ b/src/state/CallViewModel/localMember/LocalMembership.ts @@ -11,10 +11,11 @@ import { ParticipantEvent, type LocalParticipant, type ScreenShareCaptureOptions, - ConnectionState, + ConnectionState as LivekitConnectionState, } from "livekit-client"; import { observeParticipantEvents } from "@livekit/components-core"; import { + Status as RTCSessionStatus, type LivekitTransport, type MatrixRTCSession, } from "matrix-js-sdk/lib/matrixrtc"; @@ -27,7 +28,7 @@ import { map, type Observable, of, - scan, + pairwise, startWith, switchMap, tap, @@ -37,10 +38,9 @@ import { deepCompare } from "matrix-js-sdk/lib/utils"; import { constant, type Behavior } from "../../Behavior"; import { type IConnectionManager } from "../remoteMembers/ConnectionManager"; -import { ObservableScope } from "../../ObservableScope"; +import { type ObservableScope } from "../../ObservableScope"; import { type Publisher } from "./Publisher"; import { type MuteStates } from "../../MuteStates"; -import { and$ } from "../../../utils/observable"; import { ElementCallError, MembershipManagerError, @@ -51,7 +51,11 @@ import { getUrlParams } from "../../../UrlParams.ts"; import { PosthogAnalytics } from "../../../analytics/PosthogAnalytics.ts"; import { MatrixRTCMode } from "../../../settings/settings.ts"; import { Config } from "../../../config/Config.ts"; -import { type Connection } from "../remoteMembers/Connection.ts"; +import { + type ConnectionState, + type Connection, +} from "../remoteMembers/Connection.ts"; +import { type HomeserverConnected } from "./HomeserverConnected.ts"; export enum RTCBackendState { Error = "error", @@ -59,47 +63,32 @@ export enum RTCBackendState { WaitingForTransport = "waiting_for_transport", /** A connection appeared so we can initialise the publisher */ WaitingForConnection = "waiting_for_connection", - /** Connection and transport arrived, publisher Initialized */ - Initialized = "Initialized", + /** Implies lk connection is connected */ CreatingTracks = "creating_tracks", + /** Implies lk connection is connected */ ReadyToPublish = "ready_to_publish", + /** Implies lk connection is connected */ WaitingToPublish = "waiting_to_publish", - Connected = "connected", - Disconnected = "disconnected", - Disconnecting = "disconnecting", + /** Implies lk connection is connected */ + ConnectedAndPublishing = "fully_connected", } -type LocalMemberRtcBackendState = +type LocalMemberRTCBackendState = | { state: RTCBackendState.Error; error: ElementCallError } - | { state: RTCBackendState.WaitingForTransport } - | { state: RTCBackendState.WaitingForConnection } - | { state: RTCBackendState.Initialized } - | { state: RTCBackendState.CreatingTracks } - | { state: RTCBackendState.ReadyToPublish } - | { state: RTCBackendState.WaitingToPublish } - | { state: RTCBackendState.Connected } - | { state: RTCBackendState.Disconnected } - | { state: RTCBackendState.Disconnecting }; + | { state: Exclude } + | ConnectionState; -export enum MatrixState { +export enum MatrixAdditionalState { WaitingForTransport = "waiting_for_transport", - Ready = "ready", - Connecting = "connecting", - Connected = "connected", - Disconnected = "disconnected", - Error = "Error", } type LocalMemberMatrixState = - | { state: MatrixState.Connected } - | { state: MatrixState.WaitingForTransport } - | { state: MatrixState.Ready } - | { state: MatrixState.Connecting } - | { state: MatrixState.Disconnected } - | { state: MatrixState.Error; error: Error }; + | { state: MatrixAdditionalState.WaitingForTransport } + | { state: "Error"; error: Error } + | { state: RTCSessionStatus }; export interface LocalMemberConnectionState { - livekit$: Behavior; + livekit$: Behavior; matrix$: Behavior; } @@ -122,8 +111,8 @@ interface Props { muteStates: MuteStates; connectionManager: IConnectionManager; createPublisherFactory: (connection: Connection) => Publisher; - joinMatrixRTC: (transport: LivekitTransport) => Promise; - homeserverConnected$: Behavior; + joinMatrixRTC: (transport: LivekitTransport) => void; + homeserverConnected: HomeserverConnected; localTransport$: Behavior; matrixRTCSession: Pick< MatrixRTCSession, @@ -149,7 +138,7 @@ export const createLocalMembership$ = ({ scope, connectionManager, localTransport$: localTransportCanThrow$, - homeserverConnected$, + homeserverConnected, createPublisherFactory, joinMatrixRTC, logger: parentLogger, @@ -175,10 +164,14 @@ export const createLocalMembership$ = ({ tracks$: Behavior; participant$: Behavior; connection$: Behavior; - homeserverConnected$: Behavior; - // this needs to be discussed - /** @deprecated use state instead*/ + /** Shorthand for connectionState.matrix.state === Status.Reconnecting + * Direct translation to the js-sdk membership manager connection `Status`. + */ reconnecting$: Behavior; + /** Shorthand for connectionState.matrix.state === Status.Disconnected + * Direct translation to the js-sdk membership manager connection `Status`. + */ + disconnected$: Behavior; } => { const logger = parentLogger.getChild("[LocalMembership]"); logger.debug(`Creating local membership..`); @@ -232,49 +225,31 @@ export const createLocalMembership$ = ({ // * Whether we are "fully" connected to the call. Accounts for both the // * connection to the MatrixRTC session and the LiveKit publish connection. // */ - const connected$ = scope.behavior( - and$( - homeserverConnected$.pipe( - tap((v) => logger.debug("matrix: Connected state changed", v)), - ), - localConnectionState$.pipe( - switchMap((state) => { - logger.debug("livekit: Connected state changed", state); - if (!state) return of(false); - if (state.state === "ConnectedToLkRoom") { - logger.debug( - "livekit: Connected state changed (inner livekitConnectionState$)", - state.livekitConnectionState$.value, - ); - return state.livekitConnectionState$.pipe( - map((lkState) => lkState === ConnectionState.Connected), - ); - } - return of(false); - }), - ), - ).pipe(tap((v) => logger.debug("combined: Connected state changed", v))), - ); + // TODO remove this and just make it one single check of livekitConnectionState$ + // const connected$ = scope.behavior( + // localConnectionState$.pipe( + // switchMap((state) => { + // logger.debug("livekit: Connected state changed", state); + // if (!state) return of(false); + // if (state.state === "ConnectedToLkRoom") { + // logger.debug( + // "livekit: Connected state changed (inner livekitConnectionState$)", + // state.livekitConnectionState$.value, + // ); + // return state.livekitConnectionState$.pipe( + // map((lkState) => lkState === ConnectionState.Connected), + // ); + // } + // return of(false); + // }), + // ), + // ); // MATRIX RELATED - // /** - // * Whether we should tell the user that we're reconnecting to the call. - // */ - // DISCUSSION is there a better way to do this? - // sth that is more deriectly implied from the membership manager of the js sdk. (fromEvent(matrixRTCSession, Reconnecting)) ??? or similar const reconnecting$ = scope.behavior( - connected$.pipe( - // We are reconnecting if we previously had some successful initial - // connection but are now disconnected - scan( - ({ connectedPreviously }, connectedNow) => ({ - connectedPreviously: connectedPreviously || connectedNow, - reconnecting: connectedPreviously && !connectedNow, - }), - { connectedPreviously: false, reconnecting: false }, - ), - map(({ reconnecting }) => reconnecting), + homeserverConnected.rtsSession$.pipe( + map((sessionStatus) => sessionStatus === RTCSessionStatus.Reconnecting), ), ); @@ -374,8 +349,9 @@ export const createLocalMembership$ = ({ logger.error("Multiple Livkit Errors:", e); else fatalLivekitError$.next(e); }; - const livekitState$: Behavior = scope.behavior( + const livekitState$: Behavior = scope.behavior( combineLatest([ + localConnectionState$, publisher$, localTransport$, tracks$.pipe( @@ -389,10 +365,12 @@ export const createLocalMembership$ = ({ map(() => true), startWith(false), ), + // TODO use local connection state here to give the full pciture of the livekit state! fatalLivekitError$, ]).pipe( map( ([ + localConnectionState, publisher, localTransport, tracks, @@ -411,13 +389,21 @@ export const createLocalMembership$ = ({ const hasTracks = tracks.length > 0; if (!localTransport) return { state: RTCBackendState.WaitingForTransport }; - if (!publisher) + if (!localConnectionState) return { state: RTCBackendState.WaitingForConnection }; - if (!shouldStartTracks) return { state: RTCBackendState.Initialized }; + if ( + localConnectionState.state !== LivekitConnectionState.Connected || + !publisher + ) + // pass through the localConnectionState while we do not yet have a publisher or the state + // of the connection is not yet connected + return { state: localConnectionState.state }; + if (!shouldStartTracks) + return { state: LivekitConnectionState.Connected }; if (!hasTracks) return { state: RTCBackendState.CreatingTracks }; if (!shouldConnect) return { state: RTCBackendState.ReadyToPublish }; if (!publishing) return { state: RTCBackendState.WaitingToPublish }; - return { state: RTCBackendState.Connected }; + return { state: RTCBackendState.ConnectedAndPublishing }; }, ), distinctUntilChanged(deepCompare), @@ -431,58 +417,70 @@ export const createLocalMembership$ = ({ else fatalMatrixError$.next(e); }; const matrixState$: Behavior = scope.behavior( - combineLatest([ - localTransport$, - connectRequested$, - homeserverConnected$, - ]).pipe( - map(([localTransport, connectRequested, homeserverConnected]) => { - if (!localTransport) return { state: MatrixState.WaitingForTransport }; - if (!connectRequested) return { state: MatrixState.Ready }; - if (!homeserverConnected) return { state: MatrixState.Connecting }; - return { state: MatrixState.Connected }; + combineLatest([localTransport$, homeserverConnected.rtsSession$]).pipe( + map(([localTransport, rtcSessionStatus]) => { + if (!localTransport) + return { state: MatrixAdditionalState.WaitingForTransport }; + return { state: rtcSessionStatus }; }), ), ); - // Keep matrix rtc session in sync with localTransport$, connectRequested$ and muteStates.video.enabled$ + // inform the widget about the connect and disconnect intent from the user. + scope + .behavior(connectRequested$.pipe(pairwise(), scope.bind()), [ + undefined, + connectRequested$.value, + ]) + .subscribe(([prev, current]) => { + if (!widget) return; + if (!prev && current) { + try { + void widget.api.transport.send(ElementWidgetActions.JoinCall, {}); + } catch (e) { + logger.error("Failed to send join action", e); + } + } + if (prev && !current) { + try { + void widget?.api.transport.send(ElementWidgetActions.HangupCall, {}); + } catch (e) { + logger.error("Failed to send hangup action", e); + } + } + }); + + combineLatest([muteStates.video.enabled$, homeserverConnected.combined$]) + .pipe(scope.bind()) + .subscribe(([videoEnabled, connected]) => { + if (!connected) return; + void matrixRTCSession.updateCallIntent(videoEnabled ? "video" : "audio"); + }); + + // Keep matrix rtc session in sync with localTransport$, connectRequested$ scope.reconcile( scope.behavior(combineLatest([localTransport$, connectRequested$])), async ([transport, shouldConnect]) => { + if (!transport) return; + // if shouldConnect=false we will do the disconnect as the cleanup from the previous reconcile iteration. if (!shouldConnect) return; - if (!transport) return; try { - await joinMatrixRTC(transport); + joinMatrixRTC(transport); } catch (error) { logger.error("Error entering RTC session", error); if (error instanceof Error) setMatrixError(new MembershipManagerError(error)); } - // Update our member event when our mute state changes. - const callIntentScope = new ObservableScope(); - // because this uses its own scope, we can start another reconciliation for the duration of one connection. - callIntentScope.reconcile( - muteStates.video.enabled$, - async (videoEnabled) => - matrixRTCSession.updateCallIntent(videoEnabled ? "video" : "audio"), - ); - - return async (): Promise => { - callIntentScope.end(); + return Promise.resolve(async (): Promise => { try { - // Update matrixRTCSession to allow udpating the transport without leaving the session! - await matrixRTCSession.leaveRoomSession(); + // TODO Update matrixRTCSession to allow udpating the transport without leaving the session! + await matrixRTCSession.leaveRoomSession(1000); } catch (e) { logger.error("Error leaving RTC session", e); } - try { - await widget?.api.transport.send(ElementWidgetActions.HangupCall, {}); - } catch (e) { - logger.error("Failed to send hangup action", e); - } - }; + }); }, ); @@ -497,7 +495,7 @@ export const createLocalMembership$ = ({ // pause tracks during the initial joining sequence too until we're sure // that our own media is displayed on screen. // TODO refactor this based no livekitState$ - combineLatest([participant$, homeserverConnected$]) + combineLatest([participant$, homeserverConnected.combined$]) .pipe(scope.bind()) .subscribe(([participant, connected]) => { if (!participant) return; @@ -590,8 +588,15 @@ export const createLocalMembership$ = ({ }, tracks$, participant$, - homeserverConnected$, reconnecting$, + disconnected$: scope.behavior( + matrixState$.pipe( + map( + (sessionStatus) => + sessionStatus.state === RTCSessionStatus.Disconnected, + ), + ), + ), sharingScreen$, toggleScreenSharing, connection$: localConnection$, @@ -626,11 +631,11 @@ interface EnterRTCSessionOptions { * @throws If the widget could not send ElementWidgetActions.JoinCall action. */ // Exported for unit testing -export async function enterRTCSession( +export function enterRTCSession( rtcSession: MatrixRTCSession, transport: LivekitTransport, { encryptMedia, matrixRTCMode }: EnterRTCSessionOptions, -): Promise { +): void { PosthogAnalytics.instance.eventCallEnded.cacheStartCall(new Date()); PosthogAnalytics.instance.eventCallStarted.track(rtcSession.room.roomId); @@ -669,7 +674,4 @@ export async function enterRTCSession( unstableSendStickyEvents: matrixRTCMode === MatrixRTCMode.Matrix_2_0, }, ); - if (widget) { - await widget.api.transport.send(ElementWidgetActions.JoinCall, {}); - } } diff --git a/src/state/CallViewModel/localMember/Publisher.test.ts b/src/state/CallViewModel/localMember/Publisher.test.ts index 9b3e5b2a7..5468d1ff8 100644 --- a/src/state/CallViewModel/localMember/Publisher.test.ts +++ b/src/state/CallViewModel/localMember/Publisher.test.ts @@ -53,8 +53,7 @@ describe("Publisher", () => { scope = new ObservableScope(); connection = { state$: constant({ - state: "ConnectedToLkRoom", - livekitConnectionState$: constant(LivekitConenctionState.Connected), + state: LivekitConenctionState.Connected, }), livekitRoom: mockLivekitRoom({ localParticipant: mockLocalParticipant({}), diff --git a/src/state/CallViewModel/localMember/Publisher.ts b/src/state/CallViewModel/localMember/Publisher.ts index 326dedafc..6e4a9b35e 100644 --- a/src/state/CallViewModel/localMember/Publisher.ts +++ b/src/state/CallViewModel/localMember/Publisher.ts @@ -160,7 +160,7 @@ export class Publisher { const { promise, resolve, reject } = Promise.withResolvers(); const sub = this.connection.state$.subscribe((s) => { switch (s.state) { - case "ConnectedToLkRoom": + case LivekitConnectionState.Connected: resolve(); break; case "FailedToStart": diff --git a/src/state/CallViewModel/remoteMembers/Connection.test.ts b/src/state/CallViewModel/remoteMembers/Connection.test.ts index 2ead768be..efee1ccb1 100644 --- a/src/state/CallViewModel/remoteMembers/Connection.test.ts +++ b/src/state/CallViewModel/remoteMembers/Connection.test.ts @@ -125,7 +125,10 @@ function setupRemoteConnection(): Connection { }; }); - fakeLivekitRoom.connect.mockResolvedValue(undefined); + fakeLivekitRoom.connect.mockImplementation(async (): Promise => { + fakeLivekitRoom.state = LivekitConnectionState.Connected; + return Promise.resolve(); + }); return new Connection(opts, logger); } @@ -309,7 +312,7 @@ describe("Start connection states", () => { capturedState = capturedStates.pop(); - if (capturedState && capturedState?.state === "FailedToStart") { + if (capturedState && capturedState.state === "FailedToStart") { expect(capturedState.error.message).toContain( "Failed to connect to livekit", ); @@ -345,7 +348,7 @@ describe("Start connection states", () => { const connectingState = capturedStates.shift(); expect(connectingState?.state).toEqual("ConnectingToLkRoom"); const connectedState = capturedStates.shift(); - expect(connectedState?.state).toEqual("ConnectedToLkRoom"); + expect(connectedState?.state).toEqual("connected"); }); it("shutting down the scope should stop the connection", async () => { diff --git a/src/state/CallViewModel/remoteMembers/Connection.ts b/src/state/CallViewModel/remoteMembers/Connection.ts index 4f3bbda47..962f56d97 100644 --- a/src/state/CallViewModel/remoteMembers/Connection.ts +++ b/src/state/CallViewModel/remoteMembers/Connection.ts @@ -12,7 +12,7 @@ import { } from "@livekit/components-core"; import { ConnectionError, - type ConnectionState as LivekitConenctionState, + type ConnectionState as LivekitConnectionState, type Room as LivekitRoom, type LocalParticipant, type RemoteParticipant, @@ -47,17 +47,17 @@ export interface ConnectionOpts { /** Optional factory to create the LiveKit room, mainly for testing purposes. */ livekitRoomFactory: () => LivekitRoom; } - +export enum ConnectionAdditionalState { + Initialized = "Initialized", + FetchingConfig = "FetchingConfig", + // FailedToStart = "FailedToStart", + Stopped = "Stopped", + ConnectingToLkRoom = "ConnectingToLkRoom", +} export type ConnectionState = - | { state: "Initialized" } - | { state: "FetchingConfig" } - | { state: "ConnectingToLkRoom" } - | { - state: "ConnectedToLkRoom"; - livekitConnectionState$: Behavior; - } - | { state: "FailedToStart"; error: Error } - | { state: "Stopped" }; + | { state: ConnectionAdditionalState } + | { state: LivekitConnectionState } + | { state: "FailedToStart"; error: Error }; /** * A connection to a Matrix RTC LiveKit backend. @@ -67,7 +67,7 @@ export type ConnectionState = export class Connection { // Private Behavior private readonly _state$ = new BehaviorSubject({ - state: "Initialized", + state: ConnectionAdditionalState.Initialized, }); /** @@ -118,14 +118,14 @@ export class Connection { this.stopped = false; try { this._state$.next({ - state: "FetchingConfig", + state: ConnectionAdditionalState.FetchingConfig, }); const { url, jwt } = await this.getSFUConfigWithOpenID(); // If we were stopped while fetching the config, don't proceed to connect if (this.stopped) return; this._state$.next({ - state: "ConnectingToLkRoom", + state: ConnectionAdditionalState.ConnectingToLkRoom, }); try { await this.livekitRoom.connect(url, jwt); @@ -154,12 +154,13 @@ export class Connection { // If we were stopped while connecting, don't proceed to update state. if (this.stopped) return; - this._state$.next({ - state: "ConnectedToLkRoom", - livekitConnectionState$: this.scope.behavior( - connectionStateObserver(this.livekitRoom), - ), - }); + connectionStateObserver(this.livekitRoom) + .pipe(this.scope.bind()) + .subscribe((lkState) => { + this._state$.next({ + state: lkState, + }); + }); } catch (error) { this.logger.debug(`Failed to connect to LiveKit room: ${error}`); this._state$.next({ @@ -191,7 +192,7 @@ export class Connection { if (this.stopped) return; await this.livekitRoom.disconnect(); this._state$.next({ - state: "Stopped", + state: ConnectionAdditionalState.Stopped, }); this.stopped = true; } From b85f36598c7c404f782f1a5dc091f3759cda1f57 Mon Sep 17 00:00:00 2001 From: Valere Date: Wed, 3 Dec 2025 08:54:52 +0100 Subject: [PATCH 048/748] fix: mistake in file name --- .../CallViewModel/{Layout.switch.test.ts => LayoutSwitch.test.ts} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename src/state/CallViewModel/{Layout.switch.test.ts => LayoutSwitch.test.ts} (100%) diff --git a/src/state/CallViewModel/Layout.switch.test.ts b/src/state/CallViewModel/LayoutSwitch.test.ts similarity index 100% rename from src/state/CallViewModel/Layout.switch.test.ts rename to src/state/CallViewModel/LayoutSwitch.test.ts From a93ceeae4ba2402c7fc8ccc3d2c774ab66006210 Mon Sep 17 00:00:00 2001 From: Valere Date: Wed, 3 Dec 2025 09:01:26 +0100 Subject: [PATCH 049/748] review: Keep previous behavior for now to always auto switch --- src/state/CallViewModel/LayoutSwitch.test.ts | 11 +++++++---- src/state/CallViewModel/LayoutSwitch.ts | 6 +++--- 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/src/state/CallViewModel/LayoutSwitch.test.ts b/src/state/CallViewModel/LayoutSwitch.test.ts index 57df5563d..d00347437 100644 --- a/src/state/CallViewModel/LayoutSwitch.test.ts +++ b/src/state/CallViewModel/LayoutSwitch.test.ts @@ -101,21 +101,24 @@ test("Can manually force grid when there is a screenshare", () => { }); }); -test("Should not auto-switch after manually selected grid", () => { +test("Should auto-switch after manually selected grid", () => { withTestScheduler(({ cold, behavior, expectObservable, schedule }): void => { const { gridMode$, setGridMode } = createLayoutModeSwitch( scope, behavior("n", { n: "normal" }), + // Two screenshares will happen in sequence cold("-ft-ft", { f: false, t: true }), ); + // There was a screen-share that forced spotlight, then + // the user manually switch back to grid schedule("---g", { g: () => setGridMode("grid"), }); - const expectation = "ggsg"; - // If we did not respect manual selection, the expectation would be: - // const expectation = "ggsg-s"; + // If we did want to respect manual selection, the expectation would be: + // const expectation = "ggsg"; + const expectation = "ggsg-s"; expectObservable(gridMode$).toBe(expectation, { g: "grid", diff --git a/src/state/CallViewModel/LayoutSwitch.ts b/src/state/CallViewModel/LayoutSwitch.ts index c7a1e6316..cfb31d530 100644 --- a/src/state/CallViewModel/LayoutSwitch.ts +++ b/src/state/CallViewModel/LayoutSwitch.ts @@ -97,9 +97,9 @@ export function createLayoutModeSwitch( } // Respect user's grid choice - // XXX If we want to allow switching automatically again after we can - // return hasAutoSwitched: false here instead of keeping the previous value. - return { mode: "grid", hasAutoSwitched: acc.hasAutoSwitched }; + // XXX If we want to forbid switching automatically again after we can + // return hasAutoSwitched: acc.hasAutoSwitched here instead of setting to false. + return { mode: "grid", hasAutoSwitched: false }; }, // initial value { mode: "grid", hasAutoSwitched: false }, From 88721be9521843ab106fabc4e1c447bcabb2247a Mon Sep 17 00:00:00 2001 From: Timo K Date: Wed, 3 Dec 2025 10:04:22 +0100 Subject: [PATCH 050/748] cleanup --- src/room/GroupCallView.tsx | 1 + src/room/InCallView.tsx | 1 + .../localMember/LocalMembership.ts | 25 ------------------- 3 files changed, 2 insertions(+), 25 deletions(-) diff --git a/src/room/GroupCallView.tsx b/src/room/GroupCallView.tsx index 43602716d..dfd11ff32 100644 --- a/src/room/GroupCallView.tsx +++ b/src/room/GroupCallView.tsx @@ -314,6 +314,7 @@ export const GroupCallView: FC = ({ const navigate = useNavigate(); + // TODO split this into leave and onDisconnect const onLeft = useCallback( ( reason: "timeout" | "user" | "allOthersLeft" | "decline" | "error", diff --git a/src/room/InCallView.tsx b/src/room/InCallView.tsx index 6ae004d8a..7ae3700cd 100644 --- a/src/room/InCallView.tsx +++ b/src/room/InCallView.tsx @@ -151,6 +151,7 @@ export const ActiveCall: FC = (props) => { setVm(vm); vm.leave$.pipe(scope.bind()).subscribe(props.onLeft); + return (): void => { scope.end(); }; diff --git a/src/state/CallViewModel/localMember/LocalMembership.ts b/src/state/CallViewModel/localMember/LocalMembership.ts index 33af51924..6a31ce4b2 100644 --- a/src/state/CallViewModel/localMember/LocalMembership.ts +++ b/src/state/CallViewModel/localMember/LocalMembership.ts @@ -221,30 +221,6 @@ export const createLocalMembership$ = ({ switchMap((connection) => (connection ? connection.state$ : of(null))), ); - // /** - // * Whether we are "fully" connected to the call. Accounts for both the - // * connection to the MatrixRTC session and the LiveKit publish connection. - // */ - // TODO remove this and just make it one single check of livekitConnectionState$ - // const connected$ = scope.behavior( - // localConnectionState$.pipe( - // switchMap((state) => { - // logger.debug("livekit: Connected state changed", state); - // if (!state) return of(false); - // if (state.state === "ConnectedToLkRoom") { - // logger.debug( - // "livekit: Connected state changed (inner livekitConnectionState$)", - // state.livekitConnectionState$.value, - // ); - // return state.livekitConnectionState$.pipe( - // map((lkState) => lkState === ConnectionState.Connected), - // ); - // } - // return of(false); - // }), - // ), - // ); - // MATRIX RELATED const reconnecting$ = scope.behavior( @@ -365,7 +341,6 @@ export const createLocalMembership$ = ({ map(() => true), startWith(false), ), - // TODO use local connection state here to give the full pciture of the livekit state! fatalLivekitError$, ]).pipe( map( From 8110d22c8bd9d00df76d3bfa1b6b3b70618810c4 Mon Sep 17 00:00:00 2001 From: Timo K Date: Wed, 3 Dec 2025 10:27:30 +0100 Subject: [PATCH 051/748] fix lint --- sdk/main.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/sdk/main.ts b/sdk/main.ts index 205ec0600..c9a46df9d 100644 --- a/sdk/main.ts +++ b/sdk/main.ts @@ -39,6 +39,9 @@ import { type RemoteParticipant, } from "livekit-client"; +// TODO how can this get fixed? to just be part of `livekit-client` +// Can this be done in the tsconfig.json +import { type TextStreamInfo } from "../node_modules/livekit-client/dist/src/room/types"; import { type Behavior, constant } from "../src/state/Behavior"; import { createCallViewModel$ } from "../src/state/CallViewModel/CallViewModel"; import { ObservableScope } from "../src/state/ObservableScope"; From b34a75d99078394955a50c6470c0b25a00754adf Mon Sep 17 00:00:00 2001 From: Timo K Date: Wed, 3 Dec 2025 13:08:51 +0100 Subject: [PATCH 052/748] fix knip --- index.html | 2 -- package.json | 1 - vite-sdk.config.js | 32 -------------------------------- vite-sdk.config.ts | 28 ++++++++++++++++++++++++++++ yarn.lock | 13 ------------- 5 files changed, 28 insertions(+), 48 deletions(-) delete mode 100644 vite-sdk.config.js create mode 100644 vite-sdk.config.ts diff --git a/index.html b/index.html index 2cf11d1aa..f17c73c0b 100644 --- a/index.html +++ b/index.html @@ -40,8 +40,6 @@ - <% if (packageType !== "full") { %>
- <% } %> diff --git a/package.json b/package.json index 578525ae6..a1a67c050 100644 --- a/package.json +++ b/package.json @@ -137,7 +137,6 @@ "vite-plugin-generate-file": "^0.3.0", "vite-plugin-html": "^3.2.2", "vite-plugin-node-stdlib-browser": "^0.2.1", - "vite-plugin-singlefile": "^2.3.0", "vite-plugin-svgr": "^4.0.0", "vitest": "^3.0.0", "vitest-axe": "^1.0.0-pre.3" diff --git a/vite-sdk.config.js b/vite-sdk.config.js deleted file mode 100644 index ac1e4de31..000000000 --- a/vite-sdk.config.js +++ /dev/null @@ -1,32 +0,0 @@ -/* -Copyright 2025 New Vector Ltd. - -SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial -Please see LICENSE in the repository root for full details. -*/ - -import { defineConfig, mergeConfig } from "vite"; -import nodePolyfills from "vite-plugin-node-stdlib-browser"; - -const base = "./"; - -// Config for embedded deployments (possibly hosted under a non-root path) -export default defineConfig(() => - mergeConfig( - defineConfig({ - worker: { format: "es" }, - base, // Use relative URLs to allow the app to be hosted under any path - build: { - sourcemap: true, - manifest: true, - lib: { - formats: ["es"], - entry: "./sdk/main.ts", - name: "MatrixrtcSdk", - fileName: "matrixrtc-sdk", - }, - }, - plugins: [nodePolyfills()], - }), - ), -); diff --git a/vite-sdk.config.ts b/vite-sdk.config.ts new file mode 100644 index 000000000..dfa0c023c --- /dev/null +++ b/vite-sdk.config.ts @@ -0,0 +1,28 @@ +/* +Copyright 2025 New Vector Ltd. + +SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial +Please see LICENSE in the repository root for full details. +*/ + +import { defineConfig, mergeConfig } from "vite"; +import nodePolyfills from "vite-plugin-node-stdlib-browser"; + +const base = "./"; + +// Config for embedded deployments (possibly hosted under a non-root path) +export default defineConfig(() => ({ + worker: { format: "es" as const }, + base, // Use relative URLs to allow the app to be hosted under any path + build: { + sourcemap: true, + manifest: true, + lib: { + formats: ["es" as const], + entry: "./sdk/main.ts", + name: "MatrixrtcSdk", + fileName: "matrixrtc-sdk", + }, + }, + plugins: [nodePolyfills()], +})); diff --git a/yarn.lock b/yarn.lock index 4e5eff653..d775322c5 100644 --- a/yarn.lock +++ b/yarn.lock @@ -7867,7 +7867,6 @@ __metadata: vite-plugin-generate-file: "npm:^0.3.0" vite-plugin-html: "npm:^3.2.2" vite-plugin-node-stdlib-browser: "npm:^0.2.1" - vite-plugin-singlefile: "npm:^2.3.0" vite-plugin-svgr: "npm:^4.0.0" vitest: "npm:^3.0.0" vitest-axe: "npm:^1.0.0-pre.3" @@ -14746,18 +14745,6 @@ __metadata: languageName: node linkType: hard -"vite-plugin-singlefile@npm:^2.3.0": - version: 2.3.0 - resolution: "vite-plugin-singlefile@npm:2.3.0" - dependencies: - micromatch: "npm:^4.0.8" - peerDependencies: - rollup: ^4.44.1 - vite: ^5.4.11 || ^6.0.0 || ^7.0.0 - checksum: 10c0/d6ebb545d749b228bbd8fd8746a954f09d000dd69d200a651358e74136947b932f7f869536e1698e0d81e2f0694357c8bec3a957101a7e77d0d3c40193eb4cf1 - languageName: node - linkType: hard - "vite-plugin-svgr@npm:^4.0.0": version: 4.3.0 resolution: "vite-plugin-svgr@npm:4.3.0" From bbd92f666be991cf4e1ffde591cbb614b66b16a3 Mon Sep 17 00:00:00 2001 From: Robin Date: Wed, 3 Dec 2025 10:42:04 -0500 Subject: [PATCH 053/748] Simplify computation of analytics ID Since we now bundle a trusted Element Call widget with our messenger applications and this widget reports analytics to an endpoint determined by the messenger app, there is no longer any reason to compute a different analytics ID from the one used by the messenger app. --- src/analytics/PosthogAnalytics.ts | 32 ++++--------------------------- 1 file changed, 4 insertions(+), 28 deletions(-) diff --git a/src/analytics/PosthogAnalytics.ts b/src/analytics/PosthogAnalytics.ts index 8b2aa91d9..46223afe0 100644 --- a/src/analytics/PosthogAnalytics.ts +++ b/src/analytics/PosthogAnalytics.ts @@ -247,9 +247,8 @@ export class PosthogAnalytics { // wins, and the first writer will send tracking with an ID that doesn't match the one on the server // until the next time account data is refreshed and this function is called (most likely on next // page load). This will happen pretty infrequently, so we can tolerate the possibility. - const accountDataAnalyticsId = analyticsIdGenerator(); - await this.setAccountAnalyticsId(accountDataAnalyticsId); - analyticsID = await this.hashedEcAnalyticsId(accountDataAnalyticsId); + analyticsID = analyticsIdGenerator(); + await this.setAccountAnalyticsId(analyticsID); } } catch (e) { // The above could fail due to network requests, but not essential to starting the application, @@ -270,37 +269,14 @@ export class PosthogAnalytics { private async getAnalyticsId(): Promise { const client: MatrixClient = window.matrixclient; - let accountAnalyticsId: string | null; if (widget) { - accountAnalyticsId = getUrlParams().posthogUserId; + return getUrlParams().posthogUserId; } else { const accountData = await client.getAccountDataFromServer( PosthogAnalytics.ANALYTICS_EVENT_TYPE, ); - accountAnalyticsId = accountData?.id ?? null; + return accountData?.id ?? null; } - if (accountAnalyticsId) { - // we dont just use the element web analytics ID because that would allow to associate - // users between the two posthog instances. By using a hash from the username and the element web analytics id - // it is not possible to conclude the element web posthog user id from the element call user id and vice versa. - return await this.hashedEcAnalyticsId(accountAnalyticsId); - } - return null; - } - - private async hashedEcAnalyticsId( - accountAnalyticsId: string, - ): Promise { - const client: MatrixClient = window.matrixclient; - const posthogIdMaterial = "ec" + accountAnalyticsId + client.getUserId(); - const bufferForPosthogId = await crypto.subtle.digest( - "sha-256", - new TextEncoder().encode(posthogIdMaterial), - ); - const view = new Int32Array(bufferForPosthogId); - return Array.from(view) - .map((b) => Math.abs(b).toString(16).padStart(2, "0")) - .join(""); } private async setAccountAnalyticsId(analyticsID: string): Promise { From 0ed7194d87175edb277f212a21f747229b219c8d Mon Sep 17 00:00:00 2001 From: Valere Date: Wed, 3 Dec 2025 17:10:57 +0100 Subject: [PATCH 054/748] fix: earpiece overlay not showing + playwright test! --- playwright.config.ts | 24 +++- playwright/mobile/create-call-mobile.spec.ts | 112 +++++++++++++++++++ playwright/mobile/fixture-mobile-create.ts | 73 ++++++++++++ src/room/EarpieceOverlay.module.css | 3 +- 4 files changed, 209 insertions(+), 3 deletions(-) create mode 100644 playwright/mobile/create-call-mobile.spec.ts create mode 100644 playwright/mobile/fixture-mobile-create.ts diff --git a/playwright.config.ts b/playwright.config.ts index 7a8ee5305..391e746f0 100644 --- a/playwright.config.ts +++ b/playwright.config.ts @@ -38,6 +38,7 @@ export default defineConfig({ projects: [ { name: "chromium", + testIgnore: "**/mobile/**", use: { ...devices["Desktop Chrome"], permissions: [ @@ -56,9 +57,9 @@ export default defineConfig({ }, }, }, - { name: "firefox", + testIgnore: "**/mobile/**", use: { ...devices["Desktop Firefox"], ignoreHTTPSErrors: true, @@ -70,6 +71,27 @@ export default defineConfig({ }, }, }, + { + name: "mobile", + testMatch: "**/mobile/**", + use: { + ...devices["Pixel 7"], + ignoreHTTPSErrors: true, + permissions: [ + "clipboard-write", + "clipboard-read", + "microphone", + "camera", + ], + launchOptions: { + args: [ + "--use-fake-ui-for-media-stream", + "--use-fake-device-for-media-stream", + "--mute-audio", + ], + }, + }, + }, // No safari for now, until I find a solution to fix `Not allowed to request resource` due to calling // clear http to the homeserver diff --git a/playwright/mobile/create-call-mobile.spec.ts b/playwright/mobile/create-call-mobile.spec.ts new file mode 100644 index 000000000..853294ea6 --- /dev/null +++ b/playwright/mobile/create-call-mobile.spec.ts @@ -0,0 +1,112 @@ +/* +Copyright 2025 Element Creations Ltd. + +SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial +Please see LICENSE in the repository root for full details. +*/ + +import { expect, test } from "@playwright/test"; + +import { mobileTest } from "./fixture-mobile-create.ts"; + +test("@mobile Start a new call then leave and show the feedback screen", async ({ + page, +}) => { + await page.goto("/"); + + await page.getByTestId("home_callName").click(); + await page.getByTestId("home_callName").fill("HelloCall"); + await page.getByTestId("home_displayName").click(); + await page.getByTestId("home_displayName").fill("John Doe"); + await page.getByTestId("home_go").click(); + + // await page.pause(); + await expect(page.locator("video")).toBeVisible(); + await expect(page.getByTestId("lobby_joinCall")).toBeVisible(); + + await page.getByRole("button", { name: "Continue in browser" }).click(); + // Join the call + await page.getByTestId("lobby_joinCall").click(); + + // Ensure that the call is connected + await page + .locator("div") + .filter({ hasText: /^HelloCall$/ }) + .click(); + // Check the number of participants + await expect(page.locator("div").filter({ hasText: /^1$/ })).toBeVisible(); + // The tooltip with the name should be visible + await expect(page.getByTestId("name_tag")).toContainText("John Doe"); + + // leave the call + await page.getByTestId("incall_leave").click(); + await expect(page.getByRole("heading")).toContainText( + "John Doe, your call has ended. How did it go?", + ); + await expect(page.getByRole("main")).toContainText( + "Why not finish by setting up a password to keep your account?", + ); + + await expect( + page.getByRole("link", { name: "Not now, return to home screen" }), + ).toBeVisible(); +}); + +mobileTest("Start a new call as widget", async ({ asMobile, browser }) => { + test.slow(); // Triples the timeout + const { creatorPage, inviteLink } = asMobile; + + // test("Show earpiece overlay when output is earpiece", async ({ browser }) => { + // Use reduce motion to disable animations that are making the tests a bit flaky + + // ======== + // ACT: The other user use the invite link to join the call as a guest + // ======== + const guestInviteeContext = await browser.newContext({ + reducedMotion: "reduce", + }); + const guestPage = await guestInviteeContext.newPage(); + await guestPage.goto(inviteLink + "&controlledAudioDevices=true"); + + await guestPage.getByRole("button", { name: "Continue in browser" }).click(); + + await guestPage.getByTestId("joincall_displayName").fill("Invitee"); + await expect(guestPage.getByTestId("joincall_joincall")).toBeVisible(); + await guestPage.getByTestId("joincall_joincall").click(); + await guestPage.getByTestId("lobby_joinCall").click(); + + // ======== + // ASSERT: check that there are two members in the call + // ======== + + // There should be two participants now + await expect( + guestPage.getByTestId("roomHeader_participants_count"), + ).toContainText("2"); + expect(await guestPage.getByTestId("videoTile").count()).toBe(2); + + // Same in creator page + await expect( + creatorPage.getByTestId("roomHeader_participants_count"), + ).toContainText("2"); + expect(await creatorPage.getByTestId("videoTile").count()).toBe(2); + + // TEST: control audio devices from the invitee page + + await guestPage.evaluate(() => { + window.controls.setAvailableAudioDevices([ + { id: "speaker", name: "Speaker", isSpeaker: true }, + { id: "earpiece", name: "Handset", isEarpiece: true }, + { id: "headphones", name: "Headphones" }, + ]); + window.controls.setAudioDevice("earpiece"); + }); + await expect( + guestPage.getByRole("heading", { name: "Handset Mode" }), + ).toBeVisible(); + await expect( + guestPage.getByRole("button", { name: "Back to Speaker Mode" }), + ).toBeVisible(); + + // await guestPage.pause(); +}); diff --git a/playwright/mobile/fixture-mobile-create.ts b/playwright/mobile/fixture-mobile-create.ts new file mode 100644 index 000000000..053335d3d --- /dev/null +++ b/playwright/mobile/fixture-mobile-create.ts @@ -0,0 +1,73 @@ +/* +Copyright 2025 New Vector Ltd. + +SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial +Please see LICENSE in the repository root for full details. +*/ + +import { type Browser, type Page, test, expect } from "@playwright/test"; + +export interface MobileCreateFixtures { + asMobile: { + creatorPage: Page; + inviteLink: string; + }; +} + +export const mobileTest = test.extend({ + asMobile: async ({ browser }, puse) => { + const fixtures = await createCallAndInvite(browser); + await puse({ + creatorPage: fixtures.page, + inviteLink: fixtures.inviteLink, + }); + }, +}); + +/** + * Create a call and generate an invite link + */ +async function createCallAndInvite( + browser: Browser, +): Promise<{ page: Page; inviteLink: string }> { + const creatorContext = await browser.newContext({ reducedMotion: "reduce" }); + const creatorPage = await creatorContext.newPage(); + + await creatorPage.goto("/"); + + // ======== + // ARRANGE: The first user creates a call as guest, join it, then click the invite button to copy the invite link + // ======== + await creatorPage.getByTestId("home_callName").click(); + await creatorPage.getByTestId("home_callName").fill("Welcome"); + await creatorPage.getByTestId("home_displayName").click(); + await creatorPage.getByTestId("home_displayName").fill("Inviter"); + await creatorPage.getByTestId("home_go").click(); + await expect(creatorPage.locator("video")).toBeVisible(); + + await creatorPage + .getByRole("button", { name: "Continue in browser" }) + .click(); + // join + await creatorPage.getByTestId("lobby_joinCall").click(); + + // Get the invite link + await creatorPage.getByRole("button", { name: "Invite" }).click(); + await expect( + creatorPage.getByRole("heading", { name: "Invite to this call" }), + ).toBeVisible(); + await expect(creatorPage.getByRole("img", { name: "QR Code" })).toBeVisible(); + await expect(creatorPage.getByTestId("modal_inviteLink")).toBeVisible(); + await expect(creatorPage.getByTestId("modal_inviteLink")).toBeVisible(); + await creatorPage.getByTestId("modal_inviteLink").click(); + + const inviteLink = (await creatorPage.evaluate( + "navigator.clipboard.readText()", + )) as string; + expect(inviteLink).toContain("room/#/"); + + return { + page: creatorPage, + inviteLink, + }; +} diff --git a/src/room/EarpieceOverlay.module.css b/src/room/EarpieceOverlay.module.css index e007fc447..1718b0f26 100644 --- a/src/room/EarpieceOverlay.module.css +++ b/src/room/EarpieceOverlay.module.css @@ -12,7 +12,6 @@ @keyframes fade-in { from { opacity: 0; - display: flex; } to { opacity: 1; @@ -20,6 +19,7 @@ } .overlay[data-show="true"] { + display: flex; animation: fade-in 200ms; } @@ -29,7 +29,6 @@ } to { opacity: 0; - display: none; } } From bcb2b36888abf5d99e6be6cde104f4a12d23c91f Mon Sep 17 00:00:00 2001 From: Valere Date: Wed, 3 Dec 2025 17:17:58 +0100 Subject: [PATCH 055/748] keep livekit 1.9.4 as the latest is breaking the dev backend --- dev-backend-docker-compose.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dev-backend-docker-compose.yml b/dev-backend-docker-compose.yml index 50498c7a4..c7591847c 100644 --- a/dev-backend-docker-compose.yml +++ b/dev-backend-docker-compose.yml @@ -47,7 +47,7 @@ services: - ecbackend livekit: - image: livekit/livekit-server:latest + image: livekit/livekit-server:v1.9.4 pull_policy: always hostname: livekit-sfu command: --dev --config /etc/livekit.yaml @@ -67,7 +67,7 @@ services: - ecbackend livekit-1: - image: livekit/livekit-server:latest + image: livekit/livekit-server:v1.9.4 pull_policy: always hostname: livekit-sfu-1 command: --dev --config /etc/livekit.yaml From af08c1830e5212a76e136bf856131675948cd850 Mon Sep 17 00:00:00 2001 From: Valere Date: Wed, 3 Dec 2025 17:17:58 +0100 Subject: [PATCH 056/748] keep livekit 1.9.4 as the latest is breaking the dev backend --- dev-backend-docker-compose.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dev-backend-docker-compose.yml b/dev-backend-docker-compose.yml index 50498c7a4..c7591847c 100644 --- a/dev-backend-docker-compose.yml +++ b/dev-backend-docker-compose.yml @@ -47,7 +47,7 @@ services: - ecbackend livekit: - image: livekit/livekit-server:latest + image: livekit/livekit-server:v1.9.4 pull_policy: always hostname: livekit-sfu command: --dev --config /etc/livekit.yaml @@ -67,7 +67,7 @@ services: - ecbackend livekit-1: - image: livekit/livekit-server:latest + image: livekit/livekit-server:v1.9.4 pull_policy: always hostname: livekit-sfu-1 command: --dev --config /etc/livekit.yaml From c7491c3e9747cb0325807b3e9a989c10ab9551d5 Mon Sep 17 00:00:00 2001 From: Valere Date: Wed, 3 Dec 2025 17:25:32 +0100 Subject: [PATCH 057/748] move fixture to correct folder --- playwright/{mobile => fixtures}/fixture-mobile-create.ts | 0 playwright/mobile/create-call-mobile.spec.ts | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) rename playwright/{mobile => fixtures}/fixture-mobile-create.ts (100%) diff --git a/playwright/mobile/fixture-mobile-create.ts b/playwright/fixtures/fixture-mobile-create.ts similarity index 100% rename from playwright/mobile/fixture-mobile-create.ts rename to playwright/fixtures/fixture-mobile-create.ts diff --git a/playwright/mobile/create-call-mobile.spec.ts b/playwright/mobile/create-call-mobile.spec.ts index 853294ea6..9005d5103 100644 --- a/playwright/mobile/create-call-mobile.spec.ts +++ b/playwright/mobile/create-call-mobile.spec.ts @@ -7,7 +7,7 @@ Please see LICENSE in the repository root for full details. import { expect, test } from "@playwright/test"; -import { mobileTest } from "./fixture-mobile-create.ts"; +import { mobileTest } from "../fixtures/fixture-mobile-create.ts"; test("@mobile Start a new call then leave and show the feedback screen", async ({ page, From fdc66a1d62bce8e38b0d89192eba0b70056e2f3c Mon Sep 17 00:00:00 2001 From: Valere Date: Wed, 3 Dec 2025 18:36:51 +0100 Subject: [PATCH 058/748] fix: existing screenshare switching twice --- src/state/CallViewModel/LayoutSwitch.test.ts | 25 ++++++++++++++++ src/state/CallViewModel/LayoutSwitch.ts | 30 ++++++++++++++------ 2 files changed, 47 insertions(+), 8 deletions(-) diff --git a/src/state/CallViewModel/LayoutSwitch.test.ts b/src/state/CallViewModel/LayoutSwitch.test.ts index d00347437..c1941eb87 100644 --- a/src/state/CallViewModel/LayoutSwitch.test.ts +++ b/src/state/CallViewModel/LayoutSwitch.test.ts @@ -144,6 +144,31 @@ test("Should switch back to grid mode when the remote screen share ends", () => }); }); +test("can switch manually to grid after screen share while manually in spotlight", () => { + withTestScheduler(({ cold, behavior, schedule, expectObservable }): void => { + // Initially, no one is sharing. Then the user manually switches to + // spotlight. After a screen share starts, the user manually switches to + // grid. + const shareMarbles = " f-t-"; + const setModeMarbles = "-s-g"; + const expectation = " gs-g"; + const { gridMode$, setGridMode } = createLayoutModeSwitch( + scope, + behavior("n", { n: "normal" }), + cold(shareMarbles, { f: false, t: true }), + ); + schedule(setModeMarbles, { + g: () => setGridMode("grid"), + s: () => setGridMode("spotlight"), + }); + + expectObservable(gridMode$).toBe(expectation, { + g: "grid", + s: "spotlight", + }); + }); +}); + test("Should auto-switch to spotlight when in flat window mode", () => { withTestScheduler(({ cold, behavior, expectObservable }): void => { const { gridMode$ } = createLayoutModeSwitch( diff --git a/src/state/CallViewModel/LayoutSwitch.ts b/src/state/CallViewModel/LayoutSwitch.ts index cfb31d530..65c6bcb16 100644 --- a/src/state/CallViewModel/LayoutSwitch.ts +++ b/src/state/CallViewModel/LayoutSwitch.ts @@ -59,7 +59,13 @@ export function createLayoutModeSwitch( // To allow the user to override the auto-switch by selecting grid mode again. scan< [GridMode, boolean, WindowMode], - { mode: GridMode; hasAutoSwitched: boolean } + { + mode: GridMode; + /** Remember if the change was user driven or not */ + hasAutoSwitched: boolean; + /** To know if it is new screen share or an already handled */ + prevShare: boolean; + } >( (acc, [userSelection, hasScreenShares, windowMode]) => { const isFlatMode = windowMode === "flat"; @@ -73,6 +79,7 @@ export function createLayoutModeSwitch( return { mode: "spotlight", hasAutoSwitched: acc.hasAutoSwitched, + prevShare: hasScreenShares, }; } @@ -82,6 +89,7 @@ export function createLayoutModeSwitch( return { mode: "spotlight", hasAutoSwitched: acc.hasAutoSwitched, + prevShare: hasScreenShares, }; } @@ -89,20 +97,26 @@ export function createLayoutModeSwitch( // auto-switch to spotlight mode for better experience. // But we only do it once, if the user switches back to grid mode, // we respect that choice until they explicitly change it again. - if (hasScreenShares && !acc.hasAutoSwitched) { - logger.debug( - `Auto-switching to spotlight mode, hasScreenShares=${hasScreenShares}`, - ); - return { mode: "spotlight", hasAutoSwitched: true }; + const isNewShare = hasScreenShares && !acc.prevShare; + if (isNewShare && !acc.hasAutoSwitched) { + return { + mode: "spotlight", + hasAutoSwitched: true, + prevShare: true, + }; } // Respect user's grid choice // XXX If we want to forbid switching automatically again after we can // return hasAutoSwitched: acc.hasAutoSwitched here instead of setting to false. - return { mode: "grid", hasAutoSwitched: false }; + return { + mode: "grid", + hasAutoSwitched: false, + prevShare: hasScreenShares, + }; }, // initial value - { mode: "grid", hasAutoSwitched: false }, + { mode: "grid", hasAutoSwitched: false, prevShare: false }, ), map(({ mode }) => mode), ), From be7407ea3d7fc060538f8c3e52b2aa2bb4ea25bf Mon Sep 17 00:00:00 2001 From: Valere Date: Thu, 4 Dec 2025 09:37:07 +0100 Subject: [PATCH 059/748] review: quick renaming --- src/state/CallViewModel/LayoutSwitch.test.ts | 17 +++++++++++++++ src/state/CallViewModel/LayoutSwitch.ts | 22 ++++++++++---------- 2 files changed, 28 insertions(+), 11 deletions(-) diff --git a/src/state/CallViewModel/LayoutSwitch.test.ts b/src/state/CallViewModel/LayoutSwitch.test.ts index c1941eb87..ae5a3896e 100644 --- a/src/state/CallViewModel/LayoutSwitch.test.ts +++ b/src/state/CallViewModel/LayoutSwitch.test.ts @@ -144,6 +144,23 @@ test("Should switch back to grid mode when the remote screen share ends", () => }); }); +test("can auto-switch to spotlight again after first screen share ends", () => { + withTestScheduler(({ cold, behavior, expectObservable }): void => { + const shareMarble = "ftft"; + const gridsMarble = "gsgs"; + const { gridMode$ } = createLayoutModeSwitch( + scope, + behavior("n", { n: "normal" }), + cold(shareMarble, { f: false, t: true }), + ); + + expectObservable(gridMode$).toBe(gridsMarble, { + g: "grid", + s: "spotlight", + }); + }); +}); + test("can switch manually to grid after screen share while manually in spotlight", () => { withTestScheduler(({ cold, behavior, schedule, expectObservable }): void => { // Initially, no one is sharing. Then the user manually switches to diff --git a/src/state/CallViewModel/LayoutSwitch.ts b/src/state/CallViewModel/LayoutSwitch.ts index 65c6bcb16..3ad932044 100644 --- a/src/state/CallViewModel/LayoutSwitch.ts +++ b/src/state/CallViewModel/LayoutSwitch.ts @@ -64,10 +64,10 @@ export function createLayoutModeSwitch( /** Remember if the change was user driven or not */ hasAutoSwitched: boolean; /** To know if it is new screen share or an already handled */ - prevShare: boolean; + hasScreenShares: boolean; } >( - (acc, [userSelection, hasScreenShares, windowMode]) => { + (prev, [userSelection, hasScreenShares, windowMode]) => { const isFlatMode = windowMode === "flat"; // Always force spotlight in flat mode, grid layout is not supported @@ -78,8 +78,8 @@ export function createLayoutModeSwitch( logger.debug(`Forcing spotlight mode, windowMode=${windowMode}`); return { mode: "spotlight", - hasAutoSwitched: acc.hasAutoSwitched, - prevShare: hasScreenShares, + hasAutoSwitched: prev.hasAutoSwitched, + hasScreenShares, }; } @@ -88,8 +88,8 @@ export function createLayoutModeSwitch( if (userSelection === "spotlight") { return { mode: "spotlight", - hasAutoSwitched: acc.hasAutoSwitched, - prevShare: hasScreenShares, + hasAutoSwitched: prev.hasAutoSwitched, + hasScreenShares, }; } @@ -97,12 +97,12 @@ export function createLayoutModeSwitch( // auto-switch to spotlight mode for better experience. // But we only do it once, if the user switches back to grid mode, // we respect that choice until they explicitly change it again. - const isNewShare = hasScreenShares && !acc.prevShare; - if (isNewShare && !acc.hasAutoSwitched) { + const isNewShare = hasScreenShares && !prev.hasScreenShares; + if (isNewShare && !prev.hasAutoSwitched) { return { mode: "spotlight", hasAutoSwitched: true, - prevShare: true, + hasScreenShares: true, }; } @@ -112,11 +112,11 @@ export function createLayoutModeSwitch( return { mode: "grid", hasAutoSwitched: false, - prevShare: hasScreenShares, + hasScreenShares, }; }, // initial value - { mode: "grid", hasAutoSwitched: false, prevShare: false }, + { mode: "grid", hasAutoSwitched: false, hasScreenShares: false }, ), map(({ mode }) => mode), ), From 940c787040b50ab3d1e1eb22010c36a6b7a8af7e Mon Sep 17 00:00:00 2001 From: Valere Date: Thu, 4 Dec 2025 10:06:45 +0100 Subject: [PATCH 060/748] review: quick renaming --- playwright/fixtures/fixture-mobile-create.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/playwright/fixtures/fixture-mobile-create.ts b/playwright/fixtures/fixture-mobile-create.ts index 053335d3d..3920c978b 100644 --- a/playwright/fixtures/fixture-mobile-create.ts +++ b/playwright/fixtures/fixture-mobile-create.ts @@ -15,9 +15,9 @@ export interface MobileCreateFixtures { } export const mobileTest = test.extend({ - asMobile: async ({ browser }, puse) => { + asMobile: async ({ browser }, pUse) => { const fixtures = await createCallAndInvite(browser); - await puse({ + await pUse({ creatorPage: fixtures.page, inviteLink: fixtures.inviteLink, }); From 7a2c1af44b14cce336eb91b3664501fb9a874ed8 Mon Sep 17 00:00:00 2001 From: Valere Date: Thu, 4 Dec 2025 10:36:57 +0100 Subject: [PATCH 061/748] review: use simple transition instead of keyframe --- src/room/EarpieceOverlay.module.css | 27 +++++---------------------- 1 file changed, 5 insertions(+), 22 deletions(-) diff --git a/src/room/EarpieceOverlay.module.css b/src/room/EarpieceOverlay.module.css index 1718b0f26..e53a1974b 100644 --- a/src/room/EarpieceOverlay.module.css +++ b/src/room/EarpieceOverlay.module.css @@ -2,39 +2,22 @@ position: fixed; z-index: var(--call-view-overlay-layer); inset: 0; - display: none; + display: flex; flex-direction: column; align-items: center; justify-content: center; gap: var(--cpd-space-2x); -} - -@keyframes fade-in { - from { - opacity: 0; - } - to { - opacity: 1; - } + transition: opacity 200ms; } .overlay[data-show="true"] { - display: flex; - animation: fade-in 200ms; -} - -@keyframes fade-out { - from { - opacity: 1; - } - to { - opacity: 0; - } + opacity: 1; } .overlay[data-show="false"] { - animation: fade-out 130ms forwards; + opacity: 0; pointer-events: none; + transition-duration: 130ms; } .overlay::before { From 71bf55f3581438245210f229a13f372a18a3f473 Mon Sep 17 00:00:00 2001 From: Valere Date: Thu, 4 Dec 2025 10:37:14 +0100 Subject: [PATCH 062/748] also test that video is muted when earpiece overlay is on --- playwright/mobile/create-call-mobile.spec.ts | 101 ++++++++++--------- 1 file changed, 52 insertions(+), 49 deletions(-) diff --git a/playwright/mobile/create-call-mobile.spec.ts b/playwright/mobile/create-call-mobile.spec.ts index 9005d5103..141ffaaec 100644 --- a/playwright/mobile/create-call-mobile.spec.ts +++ b/playwright/mobile/create-call-mobile.spec.ts @@ -52,61 +52,64 @@ test("@mobile Start a new call then leave and show the feedback screen", async ( ).toBeVisible(); }); -mobileTest("Start a new call as widget", async ({ asMobile, browser }) => { - test.slow(); // Triples the timeout - const { creatorPage, inviteLink } = asMobile; +mobileTest( + "Test earpiece overlay in controlledAudioDevices mode", + async ({ asMobile, browser }) => { + test.slow(); // Triples the timeout + const { creatorPage, inviteLink } = asMobile; - // test("Show earpiece overlay when output is earpiece", async ({ browser }) => { - // Use reduce motion to disable animations that are making the tests a bit flaky + // ======== + // ACT: The other user use the invite link to join the call as a guest + // ======== + const guestInviteeContext = await browser.newContext({ + reducedMotion: "reduce", + }); + const guestPage = await guestInviteeContext.newPage(); + await guestPage.goto(inviteLink + "&controlledAudioDevices=true"); - // ======== - // ACT: The other user use the invite link to join the call as a guest - // ======== - const guestInviteeContext = await browser.newContext({ - reducedMotion: "reduce", - }); - const guestPage = await guestInviteeContext.newPage(); - await guestPage.goto(inviteLink + "&controlledAudioDevices=true"); + await guestPage + .getByRole("button", { name: "Continue in browser" }) + .click(); - await guestPage.getByRole("button", { name: "Continue in browser" }).click(); + await guestPage.getByTestId("joincall_displayName").fill("Invitee"); + await expect(guestPage.getByTestId("joincall_joincall")).toBeVisible(); + await guestPage.getByTestId("joincall_joincall").click(); + await guestPage.getByTestId("lobby_joinCall").click(); - await guestPage.getByTestId("joincall_displayName").fill("Invitee"); - await expect(guestPage.getByTestId("joincall_joincall")).toBeVisible(); - await guestPage.getByTestId("joincall_joincall").click(); - await guestPage.getByTestId("lobby_joinCall").click(); + // ======== + // ASSERT: check that there are two members in the call + // ======== - // ======== - // ASSERT: check that there are two members in the call - // ======== + // There should be two participants now + await expect( + guestPage.getByTestId("roomHeader_participants_count"), + ).toContainText("2"); + expect(await guestPage.getByTestId("videoTile").count()).toBe(2); - // There should be two participants now - await expect( - guestPage.getByTestId("roomHeader_participants_count"), - ).toContainText("2"); - expect(await guestPage.getByTestId("videoTile").count()).toBe(2); + // Same in creator page + await expect( + creatorPage.getByTestId("roomHeader_participants_count"), + ).toContainText("2"); + expect(await creatorPage.getByTestId("videoTile").count()).toBe(2); - // Same in creator page - await expect( - creatorPage.getByTestId("roomHeader_participants_count"), - ).toContainText("2"); - expect(await creatorPage.getByTestId("videoTile").count()).toBe(2); + // TEST: control audio devices from the invitee page - // TEST: control audio devices from the invitee page + await guestPage.evaluate(() => { + window.controls.setAvailableAudioDevices([ + { id: "speaker", name: "Speaker", isSpeaker: true }, + { id: "earpiece", name: "Handset", isEarpiece: true }, + { id: "headphones", name: "Headphones" }, + ]); + window.controls.setAudioDevice("earpiece"); + }); + await expect( + guestPage.getByRole("heading", { name: "Handset Mode" }), + ).toBeVisible(); + await expect( + guestPage.getByRole("button", { name: "Back to Speaker Mode" }), + ).toBeVisible(); - await guestPage.evaluate(() => { - window.controls.setAvailableAudioDevices([ - { id: "speaker", name: "Speaker", isSpeaker: true }, - { id: "earpiece", name: "Handset", isEarpiece: true }, - { id: "headphones", name: "Headphones" }, - ]); - window.controls.setAudioDevice("earpiece"); - }); - await expect( - guestPage.getByRole("heading", { name: "Handset Mode" }), - ).toBeVisible(); - await expect( - guestPage.getByRole("button", { name: "Back to Speaker Mode" }), - ).toBeVisible(); - - // await guestPage.pause(); -}); + // Should auto-mute the video when earpiece is selected + await expect(guestPage.getByTestId("incall_videomute")).toBeDisabled(); + }, +); From 7c40b0e177fbbfbf14c7c28b71a22b58f6df94e4 Mon Sep 17 00:00:00 2001 From: Timo K Date: Fri, 5 Dec 2025 19:48:02 +0100 Subject: [PATCH 063/748] ideas --- src/state/CallViewModel/CallViewModel.ts | 47 +++++++++++-------- .../CallViewModel/remoteMembers/Connection.ts | 43 +++++++++-------- 2 files changed, 51 insertions(+), 39 deletions(-) diff --git a/src/state/CallViewModel/CallViewModel.ts b/src/state/CallViewModel/CallViewModel.ts index 9bfa979c7..3c15958ae 100644 --- a/src/state/CallViewModel/CallViewModel.ts +++ b/src/state/CallViewModel/CallViewModel.ts @@ -452,14 +452,18 @@ export function createCallViewModel$( const localMembership = createLocalMembership$({ scope: scope, - homeserverConnected: createHomeserverConnected$( + homeserverConnected$: createHomeserverConnected$( scope, client, matrixRTCSession, ), muteStates: muteStates, - joinMatrixRTC: (transport: LivekitTransport) => { - enterRTCSession(matrixRTCSession, transport, connectOptions$.value); + joinMatrixRTC: async (transport: LivekitTransport) => { + return enterRTCSession( + matrixRTCSession, + transport, + connectOptions$.value, + ); }, createPublisherFactory: (connection: Connection) => { return new Publisher( @@ -569,6 +573,17 @@ export function createCallViewModel$( ), ); + /** + * Whether various media/event sources should pretend to be disconnected from + * all network input, even if their connection still technically works. + */ + // We do this when the app is in the 'reconnecting' state, because it might be + // that the LiveKit connection is still functional while the homeserver is + // down, for example, and we want to avoid making people worry that the app is + // in a split-brained state. + // DISCUSSION own membership manager ALSO this probably can be simplifis + const reconnecting$ = localMembership.reconnecting$; + const audioParticipants$ = scope.behavior( matrixLivekitMembers$.pipe( switchMap((membersWithEpoch) => { @@ -616,7 +631,7 @@ export function createCallViewModel$( ); const handsRaised$ = scope.behavior( - handsRaisedSubject$.pipe(pauseWhen(localMembership.reconnecting$)), + handsRaisedSubject$.pipe(pauseWhen(reconnecting$)), ); const reactions$ = scope.behavior( @@ -629,7 +644,7 @@ export function createCallViewModel$( ]), ), ), - pauseWhen(localMembership.reconnecting$), + pauseWhen(reconnecting$), ), ); @@ -720,7 +735,7 @@ export function createCallViewModel$( livekitRoom$, focusUrl$, mediaDevices, - localMembership.reconnecting$, + reconnecting$, displayName$, matrixMemberMetadataStore.createAvatarUrlBehavior$(userId), handsRaised$.pipe(map((v) => v[participantId]?.time ?? null)), @@ -812,17 +827,11 @@ export function createCallViewModel$( }), ); - const shouldLeave$: Observable< - "user" | "timeout" | "decline" | "allOthersLeft" - > = merge( - autoLeave$, - merge(userHangup$, widgetHangup$).pipe(map(() => "user" as const)), - ).pipe(scope.share); - - shouldLeave$.pipe(scope.bind()).subscribe((reason) => { - logger.info(`Call left due to ${reason}`); - localMembership.requestDisconnect(); - }); + const leave$: Observable<"user" | "timeout" | "decline" | "allOthersLeft"> = + merge( + autoLeave$, + merge(userHangup$, widgetHangup$).pipe(map(() => "user" as const)), + ).pipe(scope.share); const spotlightSpeaker$ = scope.behavior( userMedia$.pipe( @@ -1444,7 +1453,7 @@ export function createCallViewModel$( autoLeave$: autoLeave$, callPickupState$: callPickupState$, ringOverlay$: ringOverlay$, - leave$: shouldLeave$, + leave$: leave$, hangup: (): void => userHangup$.next(), join: localMembership.requestConnect, toggleScreenSharing: toggleScreenSharing, @@ -1491,7 +1500,7 @@ export function createCallViewModel$( showFooter$: showFooter$, earpieceMode$: earpieceMode$, audioOutputSwitcher$: audioOutputSwitcher$, - reconnecting$: localMembership.reconnecting$, + reconnecting$: reconnecting$, }; } diff --git a/src/state/CallViewModel/remoteMembers/Connection.ts b/src/state/CallViewModel/remoteMembers/Connection.ts index 962f56d97..549777f9f 100644 --- a/src/state/CallViewModel/remoteMembers/Connection.ts +++ b/src/state/CallViewModel/remoteMembers/Connection.ts @@ -12,7 +12,7 @@ import { } from "@livekit/components-core"; import { ConnectionError, - type ConnectionState as LivekitConnectionState, + ConnectionState as LivekitConnectionState, type Room as LivekitRoom, type LocalParticipant, type RemoteParticipant, @@ -47,17 +47,24 @@ export interface ConnectionOpts { /** Optional factory to create the LiveKit room, mainly for testing purposes. */ livekitRoomFactory: () => LivekitRoom; } -export enum ConnectionAdditionalState { +export class FailedToStartError extends Error { + public constructor(message: string) { + super(message); + this.name = "FailedToStartError"; + } +} + +export enum ConnectionState { Initialized = "Initialized", FetchingConfig = "FetchingConfig", - // FailedToStart = "FailedToStart", Stopped = "Stopped", ConnectingToLkRoom = "ConnectingToLkRoom", + LivekitDisconnected = "disconnected", + LivekitConnecting = "connecting", + LivekitConnected = "connected", + LivekitReconnecting = "reconnecting", + LivekitSignalReconnecting = "signalReconnecting", } -export type ConnectionState = - | { state: ConnectionAdditionalState } - | { state: LivekitConnectionState } - | { state: "FailedToStart"; error: Error }; /** * A connection to a Matrix RTC LiveKit backend. @@ -66,14 +73,15 @@ export type ConnectionState = */ export class Connection { // Private Behavior - private readonly _state$ = new BehaviorSubject({ - state: ConnectionAdditionalState.Initialized, - }); + private readonly _state$ = new BehaviorSubject< + ConnectionState | FailedToStartError + >(ConnectionState.Initialized); /** * The current state of the connection to the media transport. */ - public readonly state$: Behavior = this._state$; + public readonly state$: Behavior = + this._state$; /** * The media transport to connect to. @@ -117,16 +125,12 @@ export class Connection { this.logger.debug("Starting Connection"); this.stopped = false; try { - this._state$.next({ - state: ConnectionAdditionalState.FetchingConfig, - }); + this._state$.next(ConnectionState.FetchingConfig); const { url, jwt } = await this.getSFUConfigWithOpenID(); // If we were stopped while fetching the config, don't proceed to connect if (this.stopped) return; - this._state$.next({ - state: ConnectionAdditionalState.ConnectingToLkRoom, - }); + this._state$.next(ConnectionState.ConnectingToLkRoom); try { await this.livekitRoom.connect(url, jwt); } catch (e) { @@ -157,9 +161,8 @@ export class Connection { connectionStateObserver(this.livekitRoom) .pipe(this.scope.bind()) .subscribe((lkState) => { - this._state$.next({ - state: lkState, - }); + // It si save to cast lkState to ConnectionState as they are fully overlapping. + this._state$.next(lkState as unknown as ConnectionState); }); } catch (error) { this.logger.debug(`Failed to connect to LiveKit room: ${error}`); From e4fee457cf8972713b86758c3743dbfdf9207b3b Mon Sep 17 00:00:00 2001 From: Timo K Date: Mon, 8 Dec 2025 09:41:01 +0100 Subject: [PATCH 064/748] allow to use custom applications --- sdk/index.html | 4 +++- sdk/main.ts | 12 ++++++++++-- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/sdk/index.html b/sdk/index.html index f90312f10..51110ebd7 100644 --- a/sdk/index.html +++ b/sdk/index.html @@ -8,7 +8,9 @@ import { createMatrixRTCSdk } from "http://localhost:8123/matrixrtc-sdk.js"; try { - window.matrixRTCSdk = await createMatrixRTCSdk(); + window.matrixRTCSdk = await createMatrixRTCSdk( + "com.github.toger5.godot-game", + ); console.info("createMatrixRTCSdk was created!"); } catch (e) { console.error("createMatrixRTCSdk", e); diff --git a/sdk/main.ts b/sdk/main.ts index c9a46df9d..1dfbbcbfa 100644 --- a/sdk/main.ts +++ b/sdk/main.ts @@ -30,7 +30,9 @@ import { } from "rxjs"; import { type CallMembership, + MatrixRTCSession, MatrixRTCSessionEvent, + SlotDescription, } from "matrix-js-sdk/lib/matrixrtc"; import { type Room as LivekitRoom, @@ -80,7 +82,10 @@ interface MatrixRTCSdk { sendData?: (data: unknown) => Promise; } -export async function createMatrixRTCSdk(): Promise { +export async function createMatrixRTCSdk( + application: string = "m.call", + id: string = "", +): Promise { logger.info("Hello"); const client = await widget.client; logger.info("client created"); @@ -93,7 +98,10 @@ export async function createMatrixRTCSdk(): Promise { const mediaDevices = new MediaDevices(scope); const muteStates = new MuteStates(scope, mediaDevices, constant(true)); - const rtcSession = client.matrixRTC.getRoomSession(room); + const rtcSession = new MatrixRTCSession(client, room, { + application, + id, + }); const callViewModel = createCallViewModel$( scope, rtcSession, From 2986f90a5f21f12519be862be5d53b3ca96c7d64 Mon Sep 17 00:00:00 2001 From: Robin Date: Mon, 8 Dec 2025 22:29:15 -0500 Subject: [PATCH 065/748] Allow MatrixRTC mode to be configured in tests --- src/state/CallViewModel/CallViewModel.ts | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/state/CallViewModel/CallViewModel.ts b/src/state/CallViewModel/CallViewModel.ts index 5cc33f5d4..fb50696f5 100644 --- a/src/state/CallViewModel/CallViewModel.ts +++ b/src/state/CallViewModel/CallViewModel.ts @@ -56,7 +56,7 @@ import { accumulate, generateItems, pauseWhen } from "../../utils/observable"; import { duplicateTiles, MatrixRTCMode, - matrixRTCMode, + matrixRTCMode as matrixRTCModeSetting, playReactionsSound, showReactions, } from "../../settings/settings"; @@ -149,6 +149,8 @@ export interface CallViewModelOptions { connectionState$?: Behavior; /** Optional behavior overriding the computed window size, mainly for testing purposes. */ windowSize$?: Behavior<{ width: number; height: number }>; + /** Optional behavior overriding the MatrixRTC mode, mainly for testing purposes. */ + matrixRTCMode$?: Behavior; } // Do not play any sounds if the participant count has exceeded this @@ -399,13 +401,15 @@ export function createCallViewModel$( memberships$, ); + const matrixRTCMode$ = options.matrixRTCMode$ ?? matrixRTCModeSetting.value$; + const localTransport$ = createLocalTransport$({ scope: scope, memberships$: memberships$, client, roomId: matrixRoom.roomId, useOldestMember$: scope.behavior( - matrixRTCMode.value$.pipe(map((v) => v === MatrixRTCMode.Legacy)), + matrixRTCMode$.pipe(map((v) => v === MatrixRTCMode.Legacy)), ), }); @@ -446,7 +450,7 @@ export function createCallViewModel$( }); const connectOptions$ = scope.behavior( - matrixRTCMode.value$.pipe( + matrixRTCMode$.pipe( map((mode) => ({ encryptMedia: livekitKeyProvider !== undefined, // TODO. This might need to get called again on each change of matrixRTCMode... From 5a9a62039c76f68e3155b819a520f6f500cab0f8 Mon Sep 17 00:00:00 2001 From: Robin Date: Mon, 8 Dec 2025 22:42:57 -0500 Subject: [PATCH 066/748] Test CallViewModel in all MatrixRTC modes --- src/state/CallViewModel/CallViewModel.test.ts | 11 +- .../CallViewModel/CallViewModelTestUtils.ts | 224 +++++++++--------- src/state/CallViewModelWidget.test.ts | 70 +++--- 3 files changed, 165 insertions(+), 140 deletions(-) diff --git a/src/state/CallViewModel/CallViewModel.test.ts b/src/state/CallViewModel/CallViewModel.test.ts index 2e5b57008..86cde12a0 100644 --- a/src/state/CallViewModel/CallViewModel.test.ts +++ b/src/state/CallViewModel/CallViewModel.test.ts @@ -60,7 +60,8 @@ import { import { MediaDevices } from "../MediaDevices.ts"; import { getValue } from "../../utils/observable.ts"; import { type Behavior, constant } from "../Behavior.ts"; -import { withCallViewModel } from "./CallViewModelTestUtils.ts"; +import { withCallViewModel as withCallViewModelInMode } from "./CallViewModelTestUtils.ts"; +import { MatrixRTCMode } from "../../settings/settings.ts"; vi.mock("rxjs", async (importOriginal) => ({ ...(await importOriginal()), @@ -229,7 +230,13 @@ function mockRingEvent( // need a value to fill in for them when emitting notifications const mockLegacyRingEvent = {} as { event_id: string } & ICallNotifyContent; -describe("CallViewModel", () => { +describe.each([ + [MatrixRTCMode.Legacy], + [MatrixRTCMode.Compatibil], + [MatrixRTCMode.Matrix_2_0], +])("CallViewModel (%s mode)", (mode) => { + const withCallViewModel = withCallViewModelInMode(mode); + test("participants are retained during a focus switch", () => { withTestScheduler(({ behavior, expectObservable }) => { // Participants disappear on frame 2 and come back on frame 3 diff --git a/src/state/CallViewModel/CallViewModelTestUtils.ts b/src/state/CallViewModel/CallViewModelTestUtils.ts index f80b4bcbe..e9996a41b 100644 --- a/src/state/CallViewModel/CallViewModelTestUtils.ts +++ b/src/state/CallViewModel/CallViewModelTestUtils.ts @@ -53,6 +53,7 @@ import { import { type Behavior, constant } from "../Behavior"; import { type ProcessorState } from "../../livekit/TrackProcessorContext"; import { type MediaDevices } from "../MediaDevices"; +import { type MatrixRTCMode } from "../../settings/settings"; mockConfig({ livekit: { livekit_service_url: "http://my-default-service-url.com" }, @@ -80,117 +81,126 @@ export interface CallViewModelInputs { const localParticipant = mockLocalParticipant({ identity: "" }); -export function withCallViewModel( - { - remoteParticipants$ = constant([]), - rtcMembers$ = constant([localRtcMember]), - livekitConnectionState$: connectionState$ = constant( - ConnectionState.Connected, - ), - speaking = new Map(), - mediaDevices = mockMediaDevices({}), - initialSyncState = SyncState.Syncing, - windowSize$ = constant({ width: 1000, height: 800 }), - }: Partial = {}, - continuation: ( - vm: CallViewModel, - rtcSession: MockRTCSession, - subjects: { raisedHands$: BehaviorSubject> }, - setSyncState: (value: SyncState) => void, - ) => void, - options: CallViewModelOptions = { - encryptionSystem: { kind: E2eeType.PER_PARTICIPANT }, - autoLeaveWhenOthersLeft: false, - }, -): void { - let syncState = initialSyncState; - const setSyncState = (value: SyncState): void => { - const prev = syncState; - syncState = value; - room.client.emit(ClientEvent.Sync, value, prev); - }; - const room = mockMatrixRoom({ - client: new (class extends EventEmitter { - public getUserId(): string | undefined { - return localRtcMember.userId; - } +export function withCallViewModel(mode: MatrixRTCMode) { + return ( + { + remoteParticipants$ = constant([]), + rtcMembers$ = constant([localRtcMember]), + livekitConnectionState$: connectionState$ = constant( + ConnectionState.Connected, + ), + speaking = new Map(), + mediaDevices = mockMediaDevices({}), + initialSyncState = SyncState.Syncing, + windowSize$ = constant({ width: 1000, height: 800 }), + }: Partial = {}, + continuation: ( + vm: CallViewModel, + rtcSession: MockRTCSession, + subjects: { + raisedHands$: BehaviorSubject>; + }, + setSyncState: (value: SyncState) => void, + ) => void, + options: CallViewModelOptions = { + encryptionSystem: { kind: E2eeType.PER_PARTICIPANT }, + autoLeaveWhenOthersLeft: false, + }, + ): void => { + let syncState = initialSyncState; + const setSyncState = (value: SyncState): void => { + const prev = syncState; + syncState = value; + room.client.emit(ClientEvent.Sync, value, prev); + }; + const room = mockMatrixRoom({ + client: new (class extends EventEmitter { + public getUserId(): string | undefined { + return localRtcMember.userId; + } - public getDeviceId(): string { - return localRtcMember.deviceId; - } + public getDeviceId(): string { + return localRtcMember.deviceId; + } - public getDomain(): string { - return "example.com"; - } + public getDomain(): string { + return "example.com"; + } - public getSyncState(): SyncState { - return syncState; - } - })() as Partial as MatrixClient, - getMembers: () => Array.from(roomMembers.values()), - getMembersWithMembership: () => Array.from(roomMembers.values()), - }); - const rtcSession = new MockRTCSession(room, []).withMemberships(rtcMembers$); - const participantsSpy = vi - .spyOn(ComponentsCore, "connectedParticipantsObserver") - .mockReturnValue(remoteParticipants$); - const mediaSpy = vi - .spyOn(ComponentsCore, "observeParticipantMedia") - .mockImplementation((p) => - of({ participant: p } as Partial< - ComponentsCore.ParticipantMedia - > as ComponentsCore.ParticipantMedia), + public getSyncState(): SyncState { + return syncState; + } + })() as Partial as MatrixClient, + getMembers: () => Array.from(roomMembers.values()), + getMembersWithMembership: () => Array.from(roomMembers.values()), + }); + const rtcSession = new MockRTCSession(room, []).withMemberships( + rtcMembers$, ); - const eventsSpy = vi - .spyOn(ComponentsCore, "observeParticipantEvents") - .mockImplementation((p, ...eventTypes) => { - if (eventTypes.includes(ParticipantEvent.IsSpeakingChanged)) { - return (speaking.get(p) ?? of(false)).pipe( - map((s): Participant => ({ ...p, isSpeaking: s }) as Participant), - ); - } else { - return of(p); - } + const participantsSpy = vi + .spyOn(ComponentsCore, "connectedParticipantsObserver") + .mockReturnValue(remoteParticipants$); + const mediaSpy = vi + .spyOn(ComponentsCore, "observeParticipantMedia") + .mockImplementation((p) => + of({ participant: p } as Partial< + ComponentsCore.ParticipantMedia + > as ComponentsCore.ParticipantMedia), + ); + const eventsSpy = vi + .spyOn(ComponentsCore, "observeParticipantEvents") + .mockImplementation((p, ...eventTypes) => { + if (eventTypes.includes(ParticipantEvent.IsSpeakingChanged)) { + return (speaking.get(p) ?? of(false)).pipe( + map((s): Participant => ({ ...p, isSpeaking: s }) as Participant), + ); + } else { + return of(p); + } + }); + + const roomEventSelectorSpy = vi + .spyOn(ComponentsCore, "roomEventSelector") + .mockImplementation((_room, _eventType) => of()); + const muteStates = mockMuteStates(); + const raisedHands$ = new BehaviorSubject>( + {}, + ); + const reactions$ = new BehaviorSubject>({}); + + const vm = createCallViewModel$( + testScope(), + rtcSession.asMockedSession(), + room, + mediaDevices, + muteStates, + { + ...options, + livekitRoomFactory: (): LivekitRoom => + mockLivekitRoom({ + localParticipant, + disconnect: async () => Promise.resolve(), + setE2EEEnabled: async () => Promise.resolve(), + }), + connectionState$, + windowSize$, + matrixRTCMode$: constant(mode), + }, + raisedHands$, + reactions$, + new BehaviorSubject({ + processor: undefined, + supported: undefined, + }), + ); + + onTestFinished(() => { + participantsSpy.mockRestore(); + mediaSpy.mockRestore(); + eventsSpy.mockRestore(); + roomEventSelectorSpy.mockRestore(); }); - const roomEventSelectorSpy = vi - .spyOn(ComponentsCore, "roomEventSelector") - .mockImplementation((_room, _eventType) => of()); - const muteStates = mockMuteStates(); - const raisedHands$ = new BehaviorSubject>({}); - const reactions$ = new BehaviorSubject>({}); - - const vm = createCallViewModel$( - testScope(), - rtcSession.asMockedSession(), - room, - mediaDevices, - muteStates, - { - ...options, - livekitRoomFactory: (): LivekitRoom => - mockLivekitRoom({ - localParticipant, - disconnect: async () => Promise.resolve(), - setE2EEEnabled: async () => Promise.resolve(), - }), - connectionState$, - windowSize$, - }, - raisedHands$, - reactions$, - new BehaviorSubject({ - processor: undefined, - supported: undefined, - }), - ); - - onTestFinished(() => { - participantsSpy.mockRestore(); - mediaSpy.mockRestore(); - eventsSpy.mockRestore(); - roomEventSelectorSpy.mockRestore(); - }); - - continuation(vm, rtcSession, { raisedHands$: raisedHands$ }, setSyncState); + continuation(vm, rtcSession, { raisedHands$: raisedHands$ }, setSyncState); + }; } diff --git a/src/state/CallViewModelWidget.test.ts b/src/state/CallViewModelWidget.test.ts index afcf69bab..5d6442f16 100644 --- a/src/state/CallViewModelWidget.test.ts +++ b/src/state/CallViewModelWidget.test.ts @@ -15,6 +15,7 @@ import { constant } from "./Behavior.ts"; import { aliceParticipant, localRtcMember } from "../utils/test-fixtures.ts"; import { ElementWidgetActions, widget } from "../widget.ts"; import { E2eeType } from "../e2ee/e2eeType.ts"; +import { MatrixRTCMode } from "../settings/settings.ts"; vi.mock("@livekit/components-core", { spy: true }); @@ -34,36 +35,43 @@ vi.mock("../widget", () => ({ }, })); -it("expect leave when ElementWidgetActions.HangupCall is called", async () => { - const pr = Promise.withResolvers(); - withCallViewModel( - { - remoteParticipants$: constant([aliceParticipant]), - rtcMembers$: constant([localRtcMember]), - }, - (vm: CallViewModel) => { - vm.leave$.subscribe((s: string) => { - pr.resolve(s); - }); +it.each([ + [MatrixRTCMode.Legacy], + [MatrixRTCMode.Compatibil], + [MatrixRTCMode.Matrix_2_0], +])( + "expect leave when ElementWidgetActions.HangupCall is called (%s mode)", + async (mode) => { + const pr = Promise.withResolvers(); + withCallViewModel(mode)( + { + remoteParticipants$: constant([aliceParticipant]), + rtcMembers$: constant([localRtcMember]), + }, + (vm: CallViewModel) => { + vm.leave$.subscribe((s: string) => { + pr.resolve(s); + }); - widget!.lazyActions!.emit( - ElementWidgetActions.HangupCall, - new CustomEvent(ElementWidgetActions.HangupCall, { - detail: { - action: "im.vector.hangup", - api: "toWidget", - data: {}, - requestId: "widgetapi-1761237395918", - widgetId: "mrUjS9T6uKUOWHMxXvLbSv0F", - }, - }), - ); - }, - { - encryptionSystem: { kind: E2eeType.PER_PARTICIPANT }, - }, - ); + widget!.lazyActions!.emit( + ElementWidgetActions.HangupCall, + new CustomEvent(ElementWidgetActions.HangupCall, { + detail: { + action: "im.vector.hangup", + api: "toWidget", + data: {}, + requestId: "widgetapi-1761237395918", + widgetId: "mrUjS9T6uKUOWHMxXvLbSv0F", + }, + }), + ); + }, + { + encryptionSystem: { kind: E2eeType.PER_PARTICIPANT }, + }, + ); - const source = await pr.promise; - expect(source).toBe("user"); -}); + const source = await pr.promise; + expect(source).toBe("user"); + }, +); From cc8e250d96b0ea9a8c4a3b2a6c1691e98a69c8d9 Mon Sep 17 00:00:00 2001 From: Robin Date: Mon, 8 Dec 2025 22:54:46 -0500 Subject: [PATCH 067/748] Remove a brittle cast from local member code --- src/state/CallViewModel/CallViewModel.ts | 32 +++++++++++------------- 1 file changed, 15 insertions(+), 17 deletions(-) diff --git a/src/state/CallViewModel/CallViewModel.ts b/src/state/CallViewModel/CallViewModel.ts index fb50696f5..b11c1357a 100644 --- a/src/state/CallViewModel/CallViewModel.ts +++ b/src/state/CallViewModel/CallViewModel.ts @@ -504,25 +504,23 @@ export function createCallViewModel$( ), ); - const localMatrixLivekitMemberUninitialized = { - membership$: localRtcMembership$, - participant$: localMembership.participant$, - connection$: localMembership.connection$, - userId: userId, - }; - - const localMatrixLivekitMember$: Behavior = - scope.behavior( - localRtcMembership$.pipe( - switchMap((membership) => { - if (!membership) return of(null); - return of( - // casting is save here since we know that localRtcMembership$ is !== null since we reached this case. - localMatrixLivekitMemberUninitialized as MatrixLivekitMember, - ); + const localMatrixLivekitMember$ = scope.behavior( + localRtcMembership$.pipe( + generateItems( + // Generate a local member when membership is non-null + function* (membership) { + if (membership !== null) yield { keys: ["local"], data: membership }; + }, + (_scope, membership$) => ({ + membership$, + participant$: localMembership.participant$, + connection$: localMembership.connection$, + userId, }), ), - ); + map(([localMember]) => localMember ?? null), + ), + ); // ------------------------------------------------------------------------ // callLifecycle From 47cd343d447a91977bdb9a69ff1ef2f6e1c56ab9 Mon Sep 17 00:00:00 2001 From: Robin Date: Mon, 8 Dec 2025 23:01:44 -0500 Subject: [PATCH 068/748] Prove that the remote members modules only output remote members They had loose types that were allowing them also output local members. They don't do this, it's just misleading. --- .../remoteMembers/Connection.test.ts | 7 ++-- .../CallViewModel/remoteMembers/Connection.ts | 7 +--- .../remoteMembers/ConnectionManager.test.ts | 40 +++++++++---------- .../remoteMembers/ConnectionManager.ts | 26 +++++------- 4 files changed, 33 insertions(+), 47 deletions(-) diff --git a/src/state/CallViewModel/remoteMembers/Connection.test.ts b/src/state/CallViewModel/remoteMembers/Connection.test.ts index 2ead768be..4ba4c0b74 100644 --- a/src/state/CallViewModel/remoteMembers/Connection.test.ts +++ b/src/state/CallViewModel/remoteMembers/Connection.test.ts @@ -32,7 +32,6 @@ import { Connection, type ConnectionOpts, type ConnectionState, - type PublishingParticipant, } from "./Connection.ts"; import { ObservableScope } from "../../ObservableScope.ts"; import { type OpenIDClientParts } from "../../../livekit/openIDSFU.ts"; @@ -381,7 +380,7 @@ describe("Publishing participants observations", () => { const bobIsAPublisher = Promise.withResolvers(); const danIsAPublisher = Promise.withResolvers(); - const observedPublishers: PublishingParticipant[][] = []; + const observedPublishers: RemoteParticipant[][] = []; const s = connection.remoteParticipantsWithTracks$.subscribe( (publishers) => { observedPublishers.push(publishers); @@ -394,7 +393,7 @@ describe("Publishing participants observations", () => { }, ); onTestFinished(() => s.unsubscribe()); - // The publishingParticipants$ observable is derived from the current members of the + // The remoteParticipants$ observable is derived from the current members of the // livekitRoom and the rtc membership in order to publish the members that are publishing // on this connection. @@ -436,7 +435,7 @@ describe("Publishing participants observations", () => { const connection = setupRemoteConnection(); - let observedPublishers: PublishingParticipant[][] = []; + let observedPublishers: RemoteParticipant[][] = []; const s = connection.remoteParticipantsWithTracks$.subscribe( (publishers) => { observedPublishers.push(publishers); diff --git a/src/state/CallViewModel/remoteMembers/Connection.ts b/src/state/CallViewModel/remoteMembers/Connection.ts index 4f3bbda47..ed6b04720 100644 --- a/src/state/CallViewModel/remoteMembers/Connection.ts +++ b/src/state/CallViewModel/remoteMembers/Connection.ts @@ -14,7 +14,6 @@ import { ConnectionError, type ConnectionState as LivekitConenctionState, type Room as LivekitRoom, - type LocalParticipant, type RemoteParticipant, RoomEvent, } from "livekit-client"; @@ -34,8 +33,6 @@ import { SFURoomCreationRestrictedError, } from "../../../utils/errors.ts"; -export type PublishingParticipant = LocalParticipant | RemoteParticipant; - export interface ConnectionOpts { /** The media transport to connect to. */ transport: LivekitTransport; @@ -89,9 +86,7 @@ export class Connection { * This is derived from `participantsIncludingSubscribers$` and `remoteTransports$`. * It filters the participants to only those that are associated with a membership that claims to publish on this connection. */ - public readonly remoteParticipantsWithTracks$: Behavior< - PublishingParticipant[] - >; + public readonly remoteParticipantsWithTracks$: Behavior; /** * Whether the connection has been stopped. diff --git a/src/state/CallViewModel/remoteMembers/ConnectionManager.test.ts b/src/state/CallViewModel/remoteMembers/ConnectionManager.test.ts index 484a44e74..da1da06f6 100644 --- a/src/state/CallViewModel/remoteMembers/ConnectionManager.test.ts +++ b/src/state/CallViewModel/remoteMembers/ConnectionManager.test.ts @@ -8,7 +8,7 @@ Please see LICENSE in the repository root for full details. import { afterEach, beforeEach, describe, expect, test, vi } from "vitest"; import { BehaviorSubject } from "rxjs"; import { type LivekitTransport } from "matrix-js-sdk/lib/matrixrtc"; -import { type Participant as LivekitParticipant } from "livekit-client"; +import { type RemoteParticipant } from "livekit-client"; import { logger } from "matrix-js-sdk/lib/logger"; import { Epoch, mapEpoch, ObservableScope } from "../../ObservableScope.ts"; @@ -201,23 +201,20 @@ describe("connections$ stream", () => { describe("connectionManagerData$ stream", () => { // Used in test to control fake connections' remoteParticipantsWithTracks$ streams - let fakePublishingParticipantsStreams: Map< - string, - Behavior - >; + let fakeRemoteParticipantsStreams: Map>; function keyForTransport(transport: LivekitTransport): string { return `${transport.livekit_service_url}|${transport.livekit_alias}`; } beforeEach(() => { - fakePublishingParticipantsStreams = new Map(); + fakeRemoteParticipantsStreams = new Map(); - function getPublishingParticipantsFor( + function getRemoteParticipantsFor( transport: LivekitTransport, - ): Behavior { + ): Behavior { return ( - fakePublishingParticipantsStreams.get(keyForTransport(transport)) ?? + fakeRemoteParticipantsStreams.get(keyForTransport(transport)) ?? new BehaviorSubject([]) ); } @@ -227,13 +224,12 @@ describe("connectionManagerData$ stream", () => { .fn() .mockImplementation( (transport: LivekitTransport, scope: ObservableScope) => { - const fakePublishingParticipants$ = new BehaviorSubject< - LivekitParticipant[] + const fakeRemoteParticipants$ = new BehaviorSubject< + RemoteParticipant[] >([]); const mockConnection = { transport, - remoteParticipantsWithTracks$: - getPublishingParticipantsFor(transport), + remoteParticipantsWithTracks$: getRemoteParticipantsFor(transport), } as unknown as Connection; vi.mocked(mockConnection).start = vi.fn(); vi.mocked(mockConnection).stop = vi.fn(); @@ -242,36 +238,36 @@ describe("connectionManagerData$ stream", () => { void mockConnection.stop(); }); - fakePublishingParticipantsStreams.set( + fakeRemoteParticipantsStreams.set( keyForTransport(transport), - fakePublishingParticipants$, + fakeRemoteParticipants$, ); return mockConnection; }, ); }); - test("Should report connections with the publishing participants", () => { + test("Should report connections with the remote participants", () => { withTestScheduler(({ expectObservable, schedule, behavior }) => { // Setup the fake participants streams behavior // ============================== - fakePublishingParticipantsStreams.set( + fakeRemoteParticipantsStreams.set( keyForTransport(TRANSPORT_1), behavior("oa-b", { o: [], - a: [{ identity: "user1A" } as LivekitParticipant], + a: [{ identity: "user1A" } as RemoteParticipant], b: [ - { identity: "user1A" } as LivekitParticipant, - { identity: "user1B" } as LivekitParticipant, + { identity: "user1A" } as RemoteParticipant, + { identity: "user1B" } as RemoteParticipant, ], }), ); - fakePublishingParticipantsStreams.set( + fakeRemoteParticipantsStreams.set( keyForTransport(TRANSPORT_2), behavior("o-a", { o: [], - a: [{ identity: "user2A" } as LivekitParticipant], + a: [{ identity: "user2A" } as RemoteParticipant], }), ); // ============================== diff --git a/src/state/CallViewModel/remoteMembers/ConnectionManager.ts b/src/state/CallViewModel/remoteMembers/ConnectionManager.ts index 0b9f939ca..c01b8cf9b 100644 --- a/src/state/CallViewModel/remoteMembers/ConnectionManager.ts +++ b/src/state/CallViewModel/remoteMembers/ConnectionManager.ts @@ -12,7 +12,7 @@ import { } from "matrix-js-sdk/lib/matrixrtc"; import { BehaviorSubject, combineLatest, map, of, switchMap, tap } from "rxjs"; import { type Logger } from "matrix-js-sdk/lib/logger"; -import { type LocalParticipant, type RemoteParticipant } from "livekit-client"; +import { type RemoteParticipant } from "livekit-client"; import { type Behavior } from "../../Behavior.ts"; import { type Connection } from "./Connection.ts"; @@ -22,17 +22,12 @@ import { areLivekitTransportsEqual } from "./MatrixLivekitMembers.ts"; import { type ConnectionFactory } from "./ConnectionFactory.ts"; export class ConnectionManagerData { - private readonly store: Map< - string, - [Connection, (LocalParticipant | RemoteParticipant)[]] - > = new Map(); + private readonly store: Map = + new Map(); public constructor() {} - public add( - connection: Connection, - participants: (LocalParticipant | RemoteParticipant)[], - ): void { + public add(connection: Connection, participants: RemoteParticipant[]): void { const key = this.getKey(connection.transport); const existing = this.store.get(key); if (!existing) { @@ -58,7 +53,7 @@ export class ConnectionManagerData { public getParticipantForTransport( transport: LivekitTransport, - ): (LocalParticipant | RemoteParticipant)[] { + ): RemoteParticipant[] { const key = transport.livekit_service_url + "|" + transport.livekit_alias; const existing = this.store.get(key); if (existing) { @@ -182,23 +177,24 @@ export function createConnectionManager$({ const epoch = connections.epoch; // Map the connections to list of {connection, participants}[] - const listOfConnectionsWithPublishingParticipants = - connections.value.map((connection) => { + const listOfConnectionsWithRemoteParticipants = connections.value.map( + (connection) => { return connection.remoteParticipantsWithTracks$.pipe( map((participants) => ({ connection, participants, })), ); - }); + }, + ); // probably not required - if (listOfConnectionsWithPublishingParticipants.length === 0) { + if (listOfConnectionsWithRemoteParticipants.length === 0) { return of(new Epoch(new ConnectionManagerData(), epoch)); } // combineLatest the several streams into a single stream with the ConnectionManagerData - return combineLatest(listOfConnectionsWithPublishingParticipants).pipe( + return combineLatest(listOfConnectionsWithRemoteParticipants).pipe( map( (lists) => new Epoch( From a7a3d4e93cf1ca580b99b9c8c21e926d6930d480 Mon Sep 17 00:00:00 2001 From: Robin Date: Mon, 8 Dec 2025 23:06:19 -0500 Subject: [PATCH 069/748] Remove unsound participant casts By tagging participant behaviors with a type (local vs. remote) we can now tell what kind of participant it will be in a completely type-safe manner. --- src/state/CallViewModel/CallViewModel.ts | 50 ++++++++------ .../MatrixLivekitMembers.test.ts | 20 +++--- .../remoteMembers/MatrixLivekitMembers.ts | 27 +++++--- .../remoteMembers/integration.test.ts | 14 ++-- src/state/UserMedia.ts | 69 ++++++++++--------- 5 files changed, 100 insertions(+), 80 deletions(-) diff --git a/src/state/CallViewModel/CallViewModel.ts b/src/state/CallViewModel/CallViewModel.ts index b11c1357a..f4f817763 100644 --- a/src/state/CallViewModel/CallViewModel.ts +++ b/src/state/CallViewModel/CallViewModel.ts @@ -110,6 +110,7 @@ import { ECConnectionFactory } from "./remoteMembers/ConnectionFactory.ts"; import { createConnectionManager$ } from "./remoteMembers/ConnectionManager.ts"; import { createMatrixLivekitMembers$, + type TaggedParticipant, type MatrixLivekitMember, } from "./remoteMembers/MatrixLivekitMembers.ts"; import { @@ -504,23 +505,28 @@ export function createCallViewModel$( ), ); - const localMatrixLivekitMember$ = scope.behavior( - localRtcMembership$.pipe( - generateItems( - // Generate a local member when membership is non-null - function* (membership) { - if (membership !== null) yield { keys: ["local"], data: membership }; - }, - (_scope, membership$) => ({ - membership$, - participant$: localMembership.participant$, - connection$: localMembership.connection$, - userId, - }), + const localMatrixLivekitMember$ = + scope.behavior | null>( + localRtcMembership$.pipe( + generateItems( + // Generate a local member when membership is non-null + function* (membership) { + if (membership !== null) + yield { keys: ["local"], data: membership }; + }, + (_scope, membership$) => ({ + membership$, + participant: { + type: "local" as const, + value$: localMembership.participant$, + }, + connection$: localMembership.connection$, + userId, + }), + ), + map(([localMember]) => localMember ?? null), ), - map(([localMember]) => localMember ?? null), - ), - ); + ); // ------------------------------------------------------------------------ // callLifecycle @@ -597,7 +603,7 @@ export function createCallViewModel$( const members = membersWithEpoch.value; const a$ = combineLatest( members.map((member) => - combineLatest([member.connection$, member.participant$]).pipe( + combineLatest([member.connection$, member.participant.value$]).pipe( map(([connection, participant]) => { // do not render audio for local participant if (!connection || !participant || participant.isLocal) @@ -675,8 +681,10 @@ export function createCallViewModel$( let localParticipantId: string | undefined = undefined; // add local member if available if (localMatrixLivekitMember) { - const { userId, participant$, connection$, membership$ } = + const { userId, connection$, membership$ } = localMatrixLivekitMember; + const participant: TaggedParticipant = + localMatrixLivekitMember.participant; // Widen the type localParticipantId = `${userId}:${membership$.value.deviceId}`; // should be membership$.value.membershipID which is not optional // const participantId = membership$.value.membershipID; if (localParticipantId) { @@ -686,7 +694,7 @@ export function createCallViewModel$( dup, localParticipantId, userId, - participant$, + participant, connection$, ], data: undefined, @@ -697,7 +705,7 @@ export function createCallViewModel$( // add remote members that are available for (const { userId, - participant$, + participant, connection$, membership$, } of matrixLivekitMembers) { @@ -706,7 +714,7 @@ export function createCallViewModel$( // const participantId = membership$.value?.identity; for (let dup = 0; dup < 1 + duplicateTiles; dup++) { yield { - keys: [dup, participantId, userId, participant$, connection$], + keys: [dup, participantId, userId, participant, connection$], data: undefined, }; } diff --git a/src/state/CallViewModel/remoteMembers/MatrixLivekitMembers.test.ts b/src/state/CallViewModel/remoteMembers/MatrixLivekitMembers.test.ts index e675f7230..195078e0e 100644 --- a/src/state/CallViewModel/remoteMembers/MatrixLivekitMembers.test.ts +++ b/src/state/CallViewModel/remoteMembers/MatrixLivekitMembers.test.ts @@ -100,12 +100,12 @@ test("should signal participant not yet connected to livekit", () => { }); expectObservable(matrixLivekitMember$.pipe(map((e) => e.value))).toBe("a", { - a: expect.toSatisfy((data: MatrixLivekitMember[]) => { + a: expect.toSatisfy((data: MatrixLivekitMember<"remote">[]) => { expect(data.length).toEqual(1); expectObservable(data[0].membership$).toBe("a", { a: bobMembership, }); - expectObservable(data[0].participant$).toBe("a", { + expectObservable(data[0].participant.value$).toBe("a", { a: null, }); expectObservable(data[0].connection$).toBe("a", { @@ -180,12 +180,12 @@ test("should signal participant on a connection that is publishing", () => { }); expectObservable(matrixLivekitMember$.pipe(map((e) => e.value))).toBe("a", { - a: expect.toSatisfy((data: MatrixLivekitMember[]) => { + a: expect.toSatisfy((data: MatrixLivekitMember<"remote">[]) => { expect(data.length).toEqual(1); expectObservable(data[0].membership$).toBe("a", { a: bobMembership, }); - expectObservable(data[0].participant$).toBe("a", { + expectObservable(data[0].participant.value$).toBe("a", { a: expect.toSatisfy((participant) => { expect(participant).toBeDefined(); expect(participant!.identity).toEqual(bobParticipantId); @@ -231,12 +231,12 @@ test("should signal participant on a connection that is not publishing", () => { }); expectObservable(matrixLivekitMember$.pipe(map((e) => e.value))).toBe("a", { - a: expect.toSatisfy((data: MatrixLivekitMember[]) => { + a: expect.toSatisfy((data: MatrixLivekitMember<"remote">[]) => { expect(data.length).toEqual(1); expectObservable(data[0].membership$).toBe("a", { a: bobMembership, }); - expectObservable(data[0].participant$).toBe("a", { + expectObservable(data[0].participant.value$).toBe("a", { a: null, }); expectObservable(data[0].connection$).toBe("a", { @@ -296,7 +296,7 @@ describe("Publication edge case", () => { expectObservable(matrixLivekitMember$.pipe(map((e) => e.value))).toBe( "a", { - a: expect.toSatisfy((data: MatrixLivekitMember[]) => { + a: expect.toSatisfy((data: MatrixLivekitMember<"remote">[]) => { expect(data.length).toEqual(2); expectObservable(data[0].membership$).toBe("a", { a: bobMembership, @@ -305,7 +305,7 @@ describe("Publication edge case", () => { // The real connection should be from transportA as per the membership a: connectionA, }); - expectObservable(data[0].participant$).toBe("a", { + expectObservable(data[0].participant.value$).toBe("a", { a: expect.toSatisfy((participant) => { expect(participant).toBeDefined(); expect(participant!.identity).toEqual(bobParticipantId); @@ -362,7 +362,7 @@ describe("Publication edge case", () => { expectObservable(matrixLivekitMember$.pipe(map((e) => e.value))).toBe( "a", { - a: expect.toSatisfy((data: MatrixLivekitMember[]) => { + a: expect.toSatisfy((data: MatrixLivekitMember<"remote">[]) => { expect(data.length).toEqual(2); expectObservable(data[0].membership$).toBe("a", { a: bobMembership, @@ -371,7 +371,7 @@ describe("Publication edge case", () => { // The real connection should be from transportA as per the membership a: connectionA, }); - expectObservable(data[0].participant$).toBe("a", { + expectObservable(data[0].participant.value$).toBe("a", { // No participant as Bob is not publishing on his membership transport a: null, }); diff --git a/src/state/CallViewModel/remoteMembers/MatrixLivekitMembers.ts b/src/state/CallViewModel/remoteMembers/MatrixLivekitMembers.ts index 2f1526308..bcb4e7e27 100644 --- a/src/state/CallViewModel/remoteMembers/MatrixLivekitMembers.ts +++ b/src/state/CallViewModel/remoteMembers/MatrixLivekitMembers.ts @@ -5,10 +5,7 @@ SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial Please see LICENSE in the repository root for full details. */ -import { - type LocalParticipant as LocalLivekitParticipant, - type RemoteParticipant as RemoteLivekitParticipant, -} from "livekit-client"; +import { type LocalParticipant, type RemoteParticipant } from "livekit-client"; import { type LivekitTransport, type CallMembership, @@ -24,16 +21,24 @@ import { generateItemsWithEpoch } from "../../../utils/observable"; const logger = rootLogger.getChild("[MatrixLivekitMembers]"); +/** + * A dynamic participant value with a static tag to tell what kind of + * participant it can be (local vs. remote). + */ +export type TaggedParticipant = + | { type: "local"; value$: Behavior } + | { type: "remote"; value$: Behavior }; + /** * Represents a Matrix call member and their associated LiveKit participation. * `livekitParticipant` can be undefined if the member is not yet connected to the livekit room * or if it has no livekit transport at all. */ -export interface MatrixLivekitMember { +export interface MatrixLivekitMember< + ParticipantType extends TaggedParticipant["type"], +> { membership$: Behavior; - participant$: Behavior< - LocalLivekitParticipant | RemoteLivekitParticipant | null - >; + participant: TaggedParticipant & { type: ParticipantType }; connection$: Behavior; // participantId: string; We do not want a participantId here since it will be generated by the jwt // TODO decide if we can also drop the userId. Its in the matrix membership anyways. @@ -61,7 +66,7 @@ export function createMatrixLivekitMembers$({ scope, membershipsWithTransport$, connectionManager, -}: Props): Behavior> { +}: Props): Behavior[]>> { /** * Stream of all the call members and their associated livekit data (if available). */ @@ -110,12 +115,14 @@ export function createMatrixLivekitMembers$({ logger.debug( `Updating data$ for participantId: ${participantId}, userId: ${userId}`, ); + const { participant$, ...rest } = scope.splitBehavior(data$); // will only get called once per `participantId, userId` pair. // updates to data$ and as a result to displayName$ and mxcAvatarUrl$ are more frequent. return { participantId, userId, - ...scope.splitBehavior(data$), + participant: { type: "remote" as const, value$: participant$ }, + ...rest, }; }, ), diff --git a/src/state/CallViewModel/remoteMembers/integration.test.ts b/src/state/CallViewModel/remoteMembers/integration.test.ts index e3aa6be8d..34b62dadb 100644 --- a/src/state/CallViewModel/remoteMembers/integration.test.ts +++ b/src/state/CallViewModel/remoteMembers/integration.test.ts @@ -132,7 +132,7 @@ test("bob, carl, then bob joining no tracks yet", () => { }); expectObservable(matrixLivekitItems$).toBe(vMarble, { - a: expect.toSatisfy((e: Epoch) => { + a: expect.toSatisfy((e: Epoch[]>) => { const items = e.value; expect(items.length).toBe(1); const item = items[0]!; @@ -147,12 +147,12 @@ test("bob, carl, then bob joining no tracks yet", () => { ), ), }); - expectObservable(item.participant$).toBe("a", { + expectObservable(item.participant.value$).toBe("a", { a: null, }); return true; }), - b: expect.toSatisfy((e: Epoch) => { + b: expect.toSatisfy((e: Epoch[]>) => { const items = e.value; expect(items.length).toBe(2); @@ -161,7 +161,7 @@ test("bob, carl, then bob joining no tracks yet", () => { expectObservable(item.membership$).toBe("a", { a: bobMembership, }); - expectObservable(item.participant$).toBe("a", { + expectObservable(item.participant.value$).toBe("a", { a: null, }); } @@ -172,7 +172,7 @@ test("bob, carl, then bob joining no tracks yet", () => { expectObservable(item.membership$).toBe("a", { a: carlMembership, }); - expectObservable(item.participant$).toBe("a", { + expectObservable(item.participant.value$).toBe("a", { a: null, }); expectObservable(item.connection$).toBe("a", { @@ -189,7 +189,7 @@ test("bob, carl, then bob joining no tracks yet", () => { } return true; }), - c: expect.toSatisfy((e: Epoch) => { + c: expect.toSatisfy((e: Epoch[]>) => { const items = e.value; expect(items.length).toBe(3); @@ -216,7 +216,7 @@ test("bob, carl, then bob joining no tracks yet", () => { return true; }), }); - expectObservable(item.participant$).toBe("a", { + expectObservable(item.participant.value$).toBe("a", { a: null, }); } diff --git a/src/state/UserMedia.ts b/src/state/UserMedia.ts index 38f22122d..690870e68 100644 --- a/src/state/UserMedia.ts +++ b/src/state/UserMedia.ts @@ -27,6 +27,7 @@ import type { ReactionOption } from "../reactions"; import { observeSpeaker$ } from "./observeSpeaker.ts"; import { generateItems } from "../utils/observable.ts"; import { ScreenShare } from "./ScreenShare.ts"; +import { type TaggedParticipant } from "./CallViewModel/remoteMembers/MatrixLivekitMembers.ts"; /** * Sorting bins defining the order in which media tiles appear in the layout. @@ -68,40 +69,46 @@ enum SortingBin { * for inclusion in the call layout and tracks associated screen shares. */ export class UserMedia { - public readonly vm: UserMediaViewModel = this.participant$.value?.isLocal - ? new LocalUserMediaViewModel( - this.scope, - this.id, - this.userId, - this.participant$ as Behavior, - this.encryptionSystem, - this.livekitRoom$, - this.focusUrl$, - this.mediaDevices, - this.displayName$, - this.mxcAvatarUrl$, - this.scope.behavior(this.handRaised$), - this.scope.behavior(this.reaction$), - ) - : new RemoteUserMediaViewModel( - this.scope, - this.id, - this.userId, - this.participant$ as Behavior, - this.encryptionSystem, - this.livekitRoom$, - this.focusUrl$, - this.pretendToBeDisconnected$, - this.displayName$, - this.mxcAvatarUrl$, - this.scope.behavior(this.handRaised$), - this.scope.behavior(this.reaction$), - ); + public readonly vm: UserMediaViewModel = + this.participant.type === "local" + ? new LocalUserMediaViewModel( + this.scope, + this.id, + this.userId, + this.participant.value$, + this.encryptionSystem, + this.livekitRoom$, + this.focusUrl$, + this.mediaDevices, + this.displayName$, + this.mxcAvatarUrl$, + this.scope.behavior(this.handRaised$), + this.scope.behavior(this.reaction$), + ) + : new RemoteUserMediaViewModel( + this.scope, + this.id, + this.userId, + this.participant.value$, + this.encryptionSystem, + this.livekitRoom$, + this.focusUrl$, + this.pretendToBeDisconnected$, + this.displayName$, + this.mxcAvatarUrl$, + this.scope.behavior(this.handRaised$), + this.scope.behavior(this.reaction$), + ); private readonly speaker$ = this.scope.behavior( observeSpeaker$(this.vm.speaking$), ); + // TypeScript needs this widening of the type to happen in a separate statement + private readonly participant$: Behavior< + LocalParticipant | RemoteParticipant | null + > = this.participant.value$; + /** * All screen share media associated with this user media. */ @@ -184,9 +191,7 @@ export class UserMedia { private readonly scope: ObservableScope, public readonly id: string, private readonly userId: string, - private readonly participant$: Behavior< - LocalParticipant | RemoteParticipant | null - >, + private readonly participant: TaggedParticipant, private readonly encryptionSystem: EncryptionSystem, private readonly livekitRoom$: Behavior, private readonly focusUrl$: Behavior, From d8b9568400eb9267a2dc5f3efdff09cfec770831 Mon Sep 17 00:00:00 2001 From: Robin Date: Mon, 8 Dec 2025 23:33:41 -0500 Subject: [PATCH 070/748] Stop publisher in a less brittle way --- .../CallViewModel/localMember/LocalMembership.ts | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/state/CallViewModel/localMember/LocalMembership.ts b/src/state/CallViewModel/localMember/LocalMembership.ts index 60ae79b8e..71261d379 100644 --- a/src/state/CallViewModel/localMember/LocalMembership.ts +++ b/src/state/CallViewModel/localMember/LocalMembership.ts @@ -323,12 +323,14 @@ export const createLocalMembership$ = ({ // - overwrite current publisher scope.reconcile(localConnection$, async (connection) => { if (connection !== null) { - publisher$.next(createPublisherFactory(connection)); + const publisher = createPublisherFactory(connection); + publisher$.next(publisher); + // Clean-up callback + return Promise.resolve(async (): Promise => { + await publisher.stopPublishing(); + publisher.stopTracks(); + }); } - return Promise.resolve(async (): Promise => { - await publisher$?.value?.stopPublishing(); - publisher$?.value?.stopTracks(); - }); }); // Use reconcile here to not run concurrent createAndSetupTracks calls From 9481dc401c6c06c32085560431552247a56ddb16 Mon Sep 17 00:00:00 2001 From: Robin Date: Mon, 8 Dec 2025 23:34:42 -0500 Subject: [PATCH 071/748] Remove extraneous 'scope running' check Semantically, behaviors are only meaningful for as long as their scope is running. Setting a behavior's value to an empty array once its scope ends is not guaranteed to work (as it depends on execution order of how the scope is ended), and subscribers should be robust enough to handle clean-up of all connections at the end of the scope either way. --- .../CallViewModel/remoteMembers/ConnectionManager.ts | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/src/state/CallViewModel/remoteMembers/ConnectionManager.ts b/src/state/CallViewModel/remoteMembers/ConnectionManager.ts index 0b9f939ca..09a8e79f9 100644 --- a/src/state/CallViewModel/remoteMembers/ConnectionManager.ts +++ b/src/state/CallViewModel/remoteMembers/ConnectionManager.ts @@ -10,7 +10,7 @@ import { type LivekitTransport, type ParticipantId, } from "matrix-js-sdk/lib/matrixrtc"; -import { BehaviorSubject, combineLatest, map, of, switchMap, tap } from "rxjs"; +import { combineLatest, map, of, switchMap, tap } from "rxjs"; import { type Logger } from "matrix-js-sdk/lib/logger"; import { type LocalParticipant, type RemoteParticipant } from "livekit-client"; @@ -115,9 +115,6 @@ export function createConnectionManager$({ logger: parentLogger, }: Props): IConnectionManager { const logger = parentLogger.getChild("[ConnectionManager]"); - - const running$ = new BehaviorSubject(true); - scope.onEnd(() => running$.next(false)); // TODO logger: only construct one logger from the client and make it compatible via a EC specific sing /** @@ -129,10 +126,7 @@ export function createConnectionManager$({ * externally this is modified via `registerTransports()`. */ const transports$ = scope.behavior( - combineLatest([running$, inputTransports$]).pipe( - map(([running, transports]) => - transports.mapInner((transport) => (running ? transport : [])), - ), + inputTransports$.pipe( map((transports) => transports.mapInner(removeDuplicateTransports)), tap(({ value: transports }) => { logger.trace( From 2f3f9f95eb6ed5961ff7769c246b0a29a97d181c Mon Sep 17 00:00:00 2001 From: Robin Date: Mon, 8 Dec 2025 23:38:15 -0500 Subject: [PATCH 072/748] Use more compact optional chaining and coalescing notation --- src/state/CallViewModel/remoteMembers/ConnectionManager.ts | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/state/CallViewModel/remoteMembers/ConnectionManager.ts b/src/state/CallViewModel/remoteMembers/ConnectionManager.ts index 09a8e79f9..755ba3ddc 100644 --- a/src/state/CallViewModel/remoteMembers/ConnectionManager.ts +++ b/src/state/CallViewModel/remoteMembers/ConnectionManager.ts @@ -60,11 +60,7 @@ export class ConnectionManagerData { transport: LivekitTransport, ): (LocalParticipant | RemoteParticipant)[] { const key = transport.livekit_service_url + "|" + transport.livekit_alias; - const existing = this.store.get(key); - if (existing) { - return existing[1]; - } - return []; + return this.store.get(key)?.[1] ?? []; } /** * Get all connections where the given participant is publishing. From 6ee3ef27954d1148ad4e3d7854d84431fb6c349b Mon Sep 17 00:00:00 2001 From: Robin Date: Mon, 8 Dec 2025 23:38:54 -0500 Subject: [PATCH 073/748] Edit a misleading log line The factory function is called once per item to construct the item. It is not called on future updates to the item's data. --- src/state/CallViewModel/remoteMembers/MatrixLivekitMembers.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/state/CallViewModel/remoteMembers/MatrixLivekitMembers.ts b/src/state/CallViewModel/remoteMembers/MatrixLivekitMembers.ts index 2f1526308..79ad933c2 100644 --- a/src/state/CallViewModel/remoteMembers/MatrixLivekitMembers.ts +++ b/src/state/CallViewModel/remoteMembers/MatrixLivekitMembers.ts @@ -108,7 +108,7 @@ export function createMatrixLivekitMembers$({ // Each update where the key of the generator array do not change will result in updates to the `data$` observable in the factory. (scope, data$, participantId, userId) => { logger.debug( - `Updating data$ for participantId: ${participantId}, userId: ${userId}`, + `Generating member for participantId: ${participantId}, userId: ${userId}`, ); // will only get called once per `participantId, userId` pair. // updates to data$ and as a result to displayName$ and mxcAvatarUrl$ are more frequent. From bf801364a68927e0cd67ccfe8d53876507333ff0 Mon Sep 17 00:00:00 2001 From: Timo K Date: Tue, 9 Dec 2025 15:23:30 +0100 Subject: [PATCH 074/748] cleanup and tests --- src/state/CallViewModel/CallViewModel.ts | 16 +- ...Membership.test.ts => LocalMember.test.ts} | 180 ++++++------ .../{LocalMembership.ts => LocalMember.ts} | 256 +++++++++--------- .../localMember/Publisher.test.ts | 13 +- .../CallViewModel/localMember/Publisher.ts | 30 +- .../remoteMembers/Connection.test.ts | 48 ++-- .../CallViewModel/remoteMembers/Connection.ts | 28 +- yarn.lock | 6 +- 8 files changed, 302 insertions(+), 275 deletions(-) rename src/state/CallViewModel/localMember/{LocalMembership.test.ts => LocalMember.test.ts} (74%) rename src/state/CallViewModel/localMember/{LocalMembership.ts => LocalMember.ts} (77%) diff --git a/src/state/CallViewModel/CallViewModel.ts b/src/state/CallViewModel/CallViewModel.ts index 3c15958ae..e06990b2c 100644 --- a/src/state/CallViewModel/CallViewModel.ts +++ b/src/state/CallViewModel/CallViewModel.ts @@ -94,14 +94,13 @@ import { type SpotlightLandscapeLayoutMedia, type SpotlightPortraitLayoutMedia, } from "../layout-types.ts"; -import { type ElementCallError } from "../../utils/errors.ts"; +import { ElementCallError } from "../../utils/errors.ts"; import { type ObservableScope } from "../ObservableScope.ts"; import { createHomeserverConnected$ } from "./localMember/HomeserverConnected.ts"; import { createLocalMembership$, enterRTCSession, - RTCBackendState, -} from "./localMember/LocalMembership.ts"; +} from "./localMember/LocalMember.ts"; import { createLocalTransport$ } from "./localMember/LocalTransport.ts"; import { createMemberships$, @@ -452,13 +451,13 @@ export function createCallViewModel$( const localMembership = createLocalMembership$({ scope: scope, - homeserverConnected$: createHomeserverConnected$( + homeserverConnected: createHomeserverConnected$( scope, client, matrixRTCSession, ), muteStates: muteStates, - joinMatrixRTC: async (transport: LivekitTransport) => { + joinMatrixRTC: (transport: LivekitTransport) => { return enterRTCSession( matrixRTCSession, transport, @@ -1455,7 +1454,7 @@ export function createCallViewModel$( ringOverlay$: ringOverlay$, leave$: leave$, hangup: (): void => userHangup$.next(), - join: localMembership.requestConnect, + join: localMembership.requestJoinAndPublish, toggleScreenSharing: toggleScreenSharing, sharingScreen$: sharingScreen$, @@ -1465,9 +1464,8 @@ export function createCallViewModel$( unhoverScreen: (): void => screenUnhover$.next(), fatalError$: scope.behavior( - localMembership.connectionState.livekit$.pipe( - filter((v) => v.state === RTCBackendState.Error), - map((s) => s.error), + localMembership.localMemberState$.pipe( + filter((v) => v instanceof ElementCallError), ), null, ), diff --git a/src/state/CallViewModel/localMember/LocalMembership.test.ts b/src/state/CallViewModel/localMember/LocalMember.test.ts similarity index 74% rename from src/state/CallViewModel/localMember/LocalMembership.test.ts rename to src/state/CallViewModel/localMember/LocalMember.test.ts index 1ef7abd63..2f8d11a51 100644 --- a/src/state/CallViewModel/localMember/LocalMembership.test.ts +++ b/src/state/CallViewModel/localMember/LocalMember.test.ts @@ -7,7 +7,7 @@ Please see LICENSE in the repository root for full details. */ import { - Status, + Status as RTCMemberStatus, type LivekitTransport, type MatrixRTCSession, } from "matrix-js-sdk/lib/matrixrtc"; @@ -15,11 +15,7 @@ import { describe, expect, it, vi } from "vitest"; import { AutoDiscovery } from "matrix-js-sdk/lib/autodiscovery"; import { BehaviorSubject, map, of } from "rxjs"; import { logger } from "matrix-js-sdk/lib/logger"; -import { - ConnectionState as LivekitConnectionState, - type LocalParticipant, - type LocalTrack, -} from "livekit-client"; +import { type LocalParticipant, type LocalTrack } from "livekit-client"; import { MatrixRTCMode } from "../../../settings/settings"; import { @@ -30,16 +26,19 @@ import { withTestScheduler, } from "../../../utils/test"; import { + TransportState, createLocalMembership$, enterRTCSession, - RTCBackendState, -} from "./LocalMembership"; + PublishState, + TrackState, +} from "./LocalMember"; import { MatrixRTCTransportMissingError } from "../../../utils/errors"; import { Epoch, ObservableScope } from "../../ObservableScope"; import { constant } from "../../Behavior"; import { ConnectionManagerData } from "../remoteMembers/ConnectionManager"; -import { type Connection } from "../remoteMembers/Connection"; +import { ConnectionState, type Connection } from "../remoteMembers/Connection"; import { type Publisher } from "./Publisher"; +import { C } from "vitest/dist/chunks/global.d.MAmajcmJ.js"; const MATRIX_RTC_MODE = MatrixRTCMode.Legacy; const getUrlParams = vi.hoisted(() => vi.fn(() => ({}))); @@ -200,21 +199,18 @@ describe("LocalMembership", () => { joinMatrixRTC: async (): Promise => {}, homeserverConnected: { combined$: constant(true), - rtsSession$: constant(Status.Connected), + rtsSession$: constant(RTCMemberStatus.Connected), }, }; it("throws error on missing RTC config error", () => { withTestScheduler(({ scope, hot, expectObservable }) => { - const goodTransport = { - livekit_service_url: "other", - } as LivekitTransport; - - const localTransport$ = scope.behavior( + const localTransport$ = scope.behavior( hot("1ms #", {}, new MatrixRTCTransportMissingError("domain.com")), - goodTransport, + null, ); + // we do not need any connection data since we want to fail before reaching that. const mockConnectionManager = { transports$: scope.behavior( localTransport$.pipe(map((t) => new Epoch([t]))), @@ -230,15 +226,11 @@ describe("LocalMembership", () => { connectionManager: mockConnectionManager, localTransport$, }); + localMembership.requestJoinAndPublish(); - expectObservable(localMembership.connectionState.livekit$).toBe("ne", { - n: { state: RTCBackendState.WaitingForConnection }, - e: { - state: RTCBackendState.Error, - error: expect.toSatisfy( - (e) => e instanceof MatrixRTCTransportMissingError, - ), - }, + expectObservable(localMembership.localMemberState$).toBe("ne", { + n: TransportState.Waiting, + e: expect.toSatisfy((e) => e instanceof MatrixRTCTransportMissingError), }); }); }); @@ -250,32 +242,24 @@ describe("LocalMembership", () => { livekit_service_url: "b", } as LivekitTransport; - const connectionManagerData = new ConnectionManagerData(); - - connectionManagerData.add( - { - livekitRoom: mockLivekitRoom({ - localParticipant: { - isScreenShareEnabled: false, - trackPublications: [], - } as unknown as LocalParticipant, - }), - state$: constant({ - state: LivekitConnectionState.Connected, - }), - transport: aTransport, - } as unknown as Connection, - [], - ); - connectionManagerData.add( - { - state$: constant({ - state: LivekitConnectionState.Connected, - }), - transport: bTransport, - } as unknown as Connection, - [], - ); + const connectionTransportAConnected = { + livekitRoom: mockLivekitRoom({ + localParticipant: { + isScreenShareEnabled: false, + trackPublications: [], + } as unknown as LocalParticipant, + }), + state$: constant(ConnectionState.LivekitConnected), + transport: aTransport, + } as unknown as Connection; + const connectionTransportAConnecting = { + ...connectionTransportAConnected, + state$: constant(ConnectionState.LivekitConnecting), + } as unknown as Connection; + const connectionTransportBConnected = { + state$: constant(ConnectionState.LivekitConnected), + transport: bTransport, + } as unknown as Connection; it("recreates publisher if new connection is used and ENDS always unpublish and end tracks", async () => { const scope = new ObservableScope(); @@ -300,6 +284,9 @@ describe("LocalMembership", () => { typeof vi.fn >; + const connectionManagerData = new ConnectionManagerData(); + connectionManagerData.add(connectionTransportAConnected, []); + connectionManagerData.add(connectionTransportBConnected, []); createLocalMembership$({ scope, ...defaultCreateLocalMemberValues, @@ -359,6 +346,9 @@ describe("LocalMembership", () => { typeof vi.fn >; + const connectionManagerData = new ConnectionManagerData(); + connectionManagerData.add(connectionTransportAConnected, []); + // connectionManagerData.add(connectionTransportB, []); const localMembership = createLocalMembership$({ scope, ...defaultCreateLocalMemberValues, @@ -385,10 +375,11 @@ describe("LocalMembership", () => { it("tracks livekit state correctly", async () => { const scope = new ObservableScope(); + const connectionManagerData = new ConnectionManagerData(); const localTransport$ = new BehaviorSubject(null); - const connectionManagerData$ = new BehaviorSubject< - Epoch - >(new Epoch(new ConnectionManagerData())); + const connectionManagerData$ = new BehaviorSubject( + new Epoch(connectionManagerData), + ); const publishers: Publisher[] = []; const tracks$ = new BehaviorSubject([]); @@ -434,19 +425,45 @@ describe("LocalMembership", () => { }); await flushPromises(); - expect(localMembership.connectionState.livekit$.value).toStrictEqual({ - state: RTCBackendState.WaitingForTransport, - }); + expect(localMembership.localMemberState$.value).toStrictEqual( + TransportState.Waiting, + ); localTransport$.next(aTransport); await flushPromises(); - expect(localMembership.connectionState.livekit$.value).toStrictEqual({ - state: RTCBackendState.WaitingForConnection, + expect(localMembership.localMemberState$.value).toStrictEqual({ + matrix: RTCMemberStatus.Connected, + media: { connection: null, tracks: TrackState.WaitingForUser }, }); - connectionManagerData$.next(new Epoch(connectionManagerData)); + + const connectionManagerData2 = new ConnectionManagerData(); + connectionManagerData2.add( + // clone because we will mutate this later. + { ...connectionTransportAConnecting } as unknown as Connection, + [], + ); + + connectionManagerData$.next(new Epoch(connectionManagerData2)); await flushPromises(); - expect(localMembership.connectionState.livekit$.value).toStrictEqual({ - state: LivekitConnectionState.Connected, + expect(localMembership.localMemberState$.value).toStrictEqual({ + matrix: RTCMemberStatus.Connected, + media: { + connection: ConnectionState.LivekitConnecting, + tracks: TrackState.WaitingForUser, + }, }); + + ( + connectionManagerData2.getConnectionForTransport(aTransport)! + .state$ as BehaviorSubject + ).next(ConnectionState.LivekitConnected); + expect(localMembership.localMemberState$.value).toStrictEqual({ + matrix: RTCMemberStatus.Connected, + media: { + connection: ConnectionState.LivekitConnected, + tracks: TrackState.WaitingForUser, + }, + }); + expect(publisherFactory).toHaveBeenCalledOnce(); expect(localMembership.tracks$.value.length).toBe(0); @@ -455,37 +472,46 @@ describe("LocalMembership", () => { // ------- await flushPromises(); - expect(localMembership.connectionState.livekit$.value).toStrictEqual({ - state: RTCBackendState.CreatingTracks, + expect(localMembership.localMemberState$.value).toStrictEqual({ + matrix: RTCMemberStatus.Connected, + media: { + tracks: TrackState.Creating, + connection: ConnectionState.LivekitConnected, + }, }); createTrackResolver.resolve(); await flushPromises(); - expect(localMembership.connectionState.livekit$.value).toStrictEqual({ - state: RTCBackendState.ReadyToPublish, - }); + expect( + // eslint-disable-next-line @typescript-eslint/no-explicit-any + (localMembership.localMemberState$.value as any).media, + ).toStrictEqual(PublishState.WaitingForUser); // ------- - localMembership.requestConnect(); + localMembership.requestJoinAndPublish(); // ------- - expect(localMembership.connectionState.livekit$.value).toStrictEqual({ - state: RTCBackendState.WaitingToPublish, - }); + expect( + // eslint-disable-next-line @typescript-eslint/no-explicit-any + (localMembership.localMemberState$.value as any).media, + ).toStrictEqual(PublishState.Starting); publishResolver.resolve(); await flushPromises(); - expect(localMembership.connectionState.livekit$.value).toStrictEqual({ - state: RTCBackendState.ConnectedAndPublishing, - }); + expect( + // eslint-disable-next-line @typescript-eslint/no-explicit-any + (localMembership.localMemberState$.value as any).media, + ).toStrictEqual(PublishState.Publishing); + expect(publishers[0].stopPublishing).not.toHaveBeenCalled(); - expect(localMembership.connectionState.livekit$.isStopped).toBe(false); + expect(localMembership.localMemberState$.isStopped).toBe(false); scope.end(); await flushPromises(); // stays in connected state because it is stopped before the update to tracks update the state. - expect(localMembership.connectionState.livekit$.value).toStrictEqual({ - state: RTCBackendState.ConnectedAndPublishing, - }); + expect( + // eslint-disable-next-line @typescript-eslint/no-explicit-any + (localMembership.localMemberState$.value as any).media, + ).toStrictEqual(PublishState.Publishing); // stop all tracks after ending scopes expect(publishers[0].stopPublishing).toHaveBeenCalled(); expect(publishers[0].stopTracks).toHaveBeenCalled(); diff --git a/src/state/CallViewModel/localMember/LocalMembership.ts b/src/state/CallViewModel/localMember/LocalMember.ts similarity index 77% rename from src/state/CallViewModel/localMember/LocalMembership.ts rename to src/state/CallViewModel/localMember/LocalMember.ts index 6a31ce4b2..e2fcc70ea 100644 --- a/src/state/CallViewModel/localMember/LocalMembership.ts +++ b/src/state/CallViewModel/localMember/LocalMember.ts @@ -11,7 +11,6 @@ import { ParticipantEvent, type LocalParticipant, type ScreenShareCaptureOptions, - ConnectionState as LivekitConnectionState, } from "livekit-client"; import { observeParticipantEvents } from "@livekit/components-core"; import { @@ -36,62 +35,66 @@ import { import { type Logger } from "matrix-js-sdk/lib/logger"; import { deepCompare } from "matrix-js-sdk/lib/utils"; -import { constant, type Behavior } from "../../Behavior"; -import { type IConnectionManager } from "../remoteMembers/ConnectionManager"; -import { type ObservableScope } from "../../ObservableScope"; -import { type Publisher } from "./Publisher"; -import { type MuteStates } from "../../MuteStates"; +import { constant, type Behavior } from "../../Behavior.ts"; +import { type IConnectionManager } from "../remoteMembers/ConnectionManager.ts"; +import { type ObservableScope } from "../../ObservableScope.ts"; +import { type Publisher } from "./Publisher.ts"; +import { type MuteStates } from "../../MuteStates.ts"; import { ElementCallError, MembershipManagerError, UnknownCallError, -} from "../../../utils/errors"; -import { ElementWidgetActions, widget } from "../../../widget"; +} from "../../../utils/errors.ts"; +import { ElementWidgetActions, widget } from "../../../widget.ts"; import { getUrlParams } from "../../../UrlParams.ts"; import { PosthogAnalytics } from "../../../analytics/PosthogAnalytics.ts"; import { MatrixRTCMode } from "../../../settings/settings.ts"; import { Config } from "../../../config/Config.ts"; import { - type ConnectionState, + ConnectionState, type Connection, + type FailedToStartError, } from "../remoteMembers/Connection.ts"; import { type HomeserverConnected } from "./HomeserverConnected.ts"; -export enum RTCBackendState { - Error = "error", +export enum TransportState { /** Not even a transport is available to the LocalMembership */ - WaitingForTransport = "waiting_for_transport", - /** A connection appeared so we can initialise the publisher */ - WaitingForConnection = "waiting_for_connection", - /** Implies lk connection is connected */ - CreatingTracks = "creating_tracks", - /** Implies lk connection is connected */ - ReadyToPublish = "ready_to_publish", - /** Implies lk connection is connected */ - WaitingToPublish = "waiting_to_publish", - /** Implies lk connection is connected */ - ConnectedAndPublishing = "fully_connected", + Waiting = "transport_waiting", } -type LocalMemberRTCBackendState = - | { state: RTCBackendState.Error; error: ElementCallError } - | { state: Exclude } - | ConnectionState; - -export enum MatrixAdditionalState { - WaitingForTransport = "waiting_for_transport", +export enum PublishState { + WaitingForUser = "publish_waiting_for_user", + /** Implies lk connection is connected */ + Starting = "publish_start_publishing", + /** Implies lk connection is connected */ + Publishing = "publish_publishing", } -type LocalMemberMatrixState = - | { state: MatrixAdditionalState.WaitingForTransport } - | { state: "Error"; error: Error } - | { state: RTCSessionStatus }; - -export interface LocalMemberConnectionState { - livekit$: Behavior; - matrix$: Behavior; +export enum TrackState { + /** The track is waiting for user input to create tracks (waiting to call `startTracks()`) */ + WaitingForUser = "tracks_waiting_for_user", + /** Implies lk connection is connected */ + Creating = "tracks_creating", + /** Implies lk connection is connected */ + Ready = "tracks_ready", } +export type LocalMemberMediaState = + | { + tracks: TrackState; + connection: ConnectionState | FailedToStartError; + } + | PublishState + | ElementCallError; +export type LocalMemberMatrixState = Error | RTCSessionStatus; +export type LocalMemberState = + | ElementCallError + | TransportState.Waiting + | { + media: LocalMemberMediaState; + matrix: LocalMemberMatrixState; + }; + /* * - get well known * - get oldest membership @@ -146,16 +149,16 @@ export const createLocalMembership$ = ({ matrixRTCSession, }: Props): { /** - * This starts audio and video tracks. They will be reused when calling `requestConnect`. + * This starts audio and video tracks. They will be reused when calling `requestPublish`. */ startTracks: () => Behavior; /** - * This sets a inner state (shouldConnect) to true and instructs the js-sdk and livekit to keep the user + * This sets a inner state (shouldPublish) to true and instructs the js-sdk and livekit to keep the user * connected to matrix and livekit. */ - requestConnect: () => void; + requestJoinAndPublish: () => void; requestDisconnect: () => void; - connectionState: LocalMemberConnectionState; + localMemberState$: Behavior; sharingScreen$: Behavior; /** * Callback to toggle screen sharing. If null, screen sharing is not possible. @@ -164,11 +167,11 @@ export const createLocalMembership$ = ({ tracks$: Behavior; participant$: Behavior; connection$: Behavior; - /** Shorthand for connectionState.matrix.state === Status.Reconnecting + /** Shorthand for homeserverConnected.rtcSession === Status.Reconnecting * Direct translation to the js-sdk membership manager connection `Status`. */ reconnecting$: Behavior; - /** Shorthand for connectionState.matrix.state === Status.Disconnected + /** Shorthand for homeserverConnected.rtcSession === Status.Disconnected * Direct translation to the js-sdk membership manager connection `Status`. */ disconnected$: Behavior; @@ -190,7 +193,7 @@ export const createLocalMembership$ = ({ : new Error("Unknown error from localTransport"), ); } - setLivekitError(error); + setTransportError(error); return of(null); }), ), @@ -223,19 +226,13 @@ export const createLocalMembership$ = ({ // MATRIX RELATED - const reconnecting$ = scope.behavior( - homeserverConnected.rtsSession$.pipe( - map((sessionStatus) => sessionStatus === RTCSessionStatus.Reconnecting), - ), - ); - // This should be used in a combineLatest with publisher$ to connect. // to make it possible to call startTracks before the preferredTransport$ has resolved. const trackStartRequested = Promise.withResolvers(); // This should be used in a combineLatest with publisher$ to connect. // to make it possible to call startTracks before the preferredTransport$ has resolved. - const connectRequested$ = new BehaviorSubject(false); + const joinAndPublishRequested$ = new BehaviorSubject(false); /** * The publisher is stored in here an abstracts creating and publishing tracks. @@ -256,13 +253,13 @@ export const createLocalMembership$ = ({ return tracks$; }; - const requestConnect = (): void => { + const requestJoinAndPublish = (): void => { trackStartRequested.resolve(); - connectRequested$.next(true); + joinAndPublishRequested$.next(true); }; const requestDisconnect = (): void => { - connectRequested$.next(false); + joinAndPublishRequested$.next(false); }; // Take care of the publisher$ @@ -300,112 +297,129 @@ export const createLocalMembership$ = ({ // Based on `connectRequested$` we start publishing tracks. (once they are there!) scope.reconcile( - scope.behavior(combineLatest([publisher$, tracks$, connectRequested$])), - async ([publisher, tracks, shouldConnect]) => { - if (shouldConnect === publisher?.publishing$.value) return; - if (tracks.length !== 0 && shouldConnect) { + scope.behavior( + combineLatest([publisher$, tracks$, joinAndPublishRequested$]), + ), + async ([publisher, tracks, shouldJoinAndPublish]) => { + if (shouldJoinAndPublish === publisher?.publishing$.value) return; + if (tracks.length !== 0 && shouldJoinAndPublish) { try { await publisher?.startPublishing(); } catch (error) { - setLivekitError(error as ElementCallError); + setMediaError(error as ElementCallError); } - } else if (tracks.length !== 0 && !shouldConnect) { + } else if (tracks.length !== 0 && !shouldJoinAndPublish) { try { await publisher?.stopPublishing(); } catch (error) { - setLivekitError(new UnknownCallError(error as Error)); + setMediaError(new UnknownCallError(error as Error)); } } }, ); - const fatalLivekitError$ = new BehaviorSubject(null); - const setLivekitError = (e: ElementCallError): void => { - if (fatalLivekitError$.value !== null) - logger.error("Multiple Livkit Errors:", e); - else fatalLivekitError$.next(e); + const fatalMediaError$ = new BehaviorSubject(null); + const setMediaError = (e: ElementCallError): void => { + if (fatalMediaError$.value !== null) + logger.error("Multiple Media Errors:", e); + else fatalMediaError$.next(e); }; - const livekitState$: Behavior = scope.behavior( + + const fatalTransportError$ = new BehaviorSubject( + null, + ); + const setTransportError = (e: ElementCallError): void => { + if (fatalTransportError$.value !== null) + logger.error("Multiple Transport Errors:", e); + else fatalTransportError$.next(e); + }; + + const mediaState$: Behavior = scope.behavior( combineLatest([ localConnectionState$, - publisher$, localTransport$, - tracks$.pipe( - tap((t) => { - logger.info("tracks$: ", t); - }), - ), + tracks$, publishing$, - connectRequested$, + joinAndPublishRequested$, from(trackStartRequested.promise).pipe( map(() => true), startWith(false), ), - fatalLivekitError$, ]).pipe( map( ([ localConnectionState, - publisher, localTransport, tracks, publishing, - shouldConnect, + shouldPublish, shouldStartTracks, - error, ]) => { - // read this: - // if(!
) return {state: ...} - // if(!) return {state: } - // - // as: - // We do have but not yet so we are in - if (error !== null) return { state: RTCBackendState.Error, error }; + if (!localTransport) return null; const hasTracks = tracks.length > 0; - if (!localTransport) - return { state: RTCBackendState.WaitingForTransport }; - if (!localConnectionState) - return { state: RTCBackendState.WaitingForConnection }; + let trackState: TrackState = TrackState.WaitingForUser; + if (hasTracks && shouldStartTracks) trackState = TrackState.Ready; + if (!hasTracks && shouldStartTracks) trackState = TrackState.Creating; + if ( - localConnectionState.state !== LivekitConnectionState.Connected || - !publisher + localConnectionState !== ConnectionState.LivekitConnected || + trackState !== TrackState.Ready ) - // pass through the localConnectionState while we do not yet have a publisher or the state - // of the connection is not yet connected - return { state: localConnectionState.state }; - if (!shouldStartTracks) - return { state: LivekitConnectionState.Connected }; - if (!hasTracks) return { state: RTCBackendState.CreatingTracks }; - if (!shouldConnect) return { state: RTCBackendState.ReadyToPublish }; - if (!publishing) return { state: RTCBackendState.WaitingToPublish }; - return { state: RTCBackendState.ConnectedAndPublishing }; + return { + connection: localConnectionState, + tracks: trackState, + }; + if (!shouldPublish) return PublishState.WaitingForUser; + if (!publishing) return PublishState.Starting; + return PublishState.Publishing; }, ), distinctUntilChanged(deepCompare), ), ); - const fatalMatrixError$ = new BehaviorSubject(null); const setMatrixError = (e: ElementCallError): void => { if (fatalMatrixError$.value !== null) logger.error("Multiple Matrix Errors:", e); else fatalMatrixError$.next(e); }; - const matrixState$: Behavior = scope.behavior( - combineLatest([localTransport$, homeserverConnected.rtsSession$]).pipe( - map(([localTransport, rtcSessionStatus]) => { - if (!localTransport) - return { state: MatrixAdditionalState.WaitingForTransport }; - return { state: rtcSessionStatus }; - }), + + const localMemberState$ = scope.behavior( + combineLatest([ + mediaState$, + homeserverConnected.rtsSession$, + fatalMatrixError$, + fatalTransportError$, + fatalMediaError$, + ]).pipe( + map( + ([ + mediaState, + rtcSessionStatus, + matrixError, + transportError, + mediaError, + ]) => { + if (transportError !== null) return transportError; + // `mediaState` will be 'null' until the transport appears. + if (mediaState && rtcSessionStatus) + return { + matrix: matrixError ?? rtcSessionStatus, + media: mediaError ?? mediaState, + }; + else { + return TransportState.Waiting; + } + }, + ), ), ); // inform the widget about the connect and disconnect intent from the user. scope - .behavior(connectRequested$.pipe(pairwise(), scope.bind()), [ + .behavior(joinAndPublishRequested$.pipe(pairwise(), scope.bind()), [ undefined, - connectRequested$.value, + joinAndPublishRequested$.value, ]) .subscribe(([prev, current]) => { if (!widget) return; @@ -434,7 +448,7 @@ export const createLocalMembership$ = ({ // Keep matrix rtc session in sync with localTransport$, connectRequested$ scope.reconcile( - scope.behavior(combineLatest([localTransport$, connectRequested$])), + scope.behavior(combineLatest([localTransport$, joinAndPublishRequested$])), async ([transport, shouldConnect]) => { if (!transport) return; // if shouldConnect=false we will do the disconnect as the cleanup from the previous reconcile iteration. @@ -555,21 +569,19 @@ export const createLocalMembership$ = ({ return { startTracks, - requestConnect, + requestJoinAndPublish, requestDisconnect, - connectionState: { - livekit$: livekitState$, - matrix$: matrixState$, - }, + localMemberState$, tracks$, participant$, - reconnecting$, + reconnecting$: scope.behavior( + homeserverConnected.rtsSession$.pipe( + map((sessionStatus) => sessionStatus === RTCSessionStatus.Reconnecting), + ), + ), disconnected$: scope.behavior( - matrixState$.pipe( - map( - (sessionStatus) => - sessionStatus.state === RTCSessionStatus.Disconnected, - ), + homeserverConnected.rtsSession$.pipe( + map((state) => state === RTCSessionStatus.Disconnected), ), ), sharingScreen$, diff --git a/src/state/CallViewModel/localMember/Publisher.test.ts b/src/state/CallViewModel/localMember/Publisher.test.ts index 5468d1ff8..6d27c0429 100644 --- a/src/state/CallViewModel/localMember/Publisher.test.ts +++ b/src/state/CallViewModel/localMember/Publisher.test.ts @@ -52,9 +52,7 @@ describe("Publisher", () => { } as unknown as MuteStates; scope = new ObservableScope(); connection = { - state$: constant({ - state: LivekitConenctionState.Connected, - }), + state$: constant(LivekitConenctionState.Connected), livekitRoom: mockLivekitRoom({ localParticipant: mockLocalParticipant({}), }), @@ -110,15 +108,14 @@ describe("Publisher", () => { // failiour due to connection.state$ const beforeState = connection.state$.value; - (connection.state$ as BehaviorSubject).next({ - state: "FailedToStart", - error: Error("testStartError"), - }); + (connection.state$ as BehaviorSubject).next(Error("testStartError")); await expect(publisher.startPublishing()).rejects.toThrow( new FailToStartLivekitConnection("testStartError"), ); - (connection.state$ as BehaviorSubject).next(beforeState); + (connection.state$ as BehaviorSubject).next( + beforeState, + ); // does not try other conenction after the first one failed expect( diff --git a/src/state/CallViewModel/localMember/Publisher.ts b/src/state/CallViewModel/localMember/Publisher.ts index 6e4a9b35e..b32e7e99c 100644 --- a/src/state/CallViewModel/localMember/Publisher.ts +++ b/src/state/CallViewModel/localMember/Publisher.ts @@ -32,7 +32,10 @@ import { } from "../../../livekit/TrackProcessorContext.tsx"; import { getUrlParams } from "../../../UrlParams.ts"; import { observeTrackReference$ } from "../../MediaViewModel.ts"; -import { type Connection } from "../remoteMembers/Connection.ts"; +import { + ConnectionState, + type Connection, +} from "../remoteMembers/Connection.ts"; import { type ObservableScope } from "../../ObservableScope.ts"; import { ElementCallError, @@ -158,20 +161,17 @@ export class Publisher { this.logger.debug("startPublishing called"); const lkRoom = this.connection.livekitRoom; const { promise, resolve, reject } = Promise.withResolvers(); - const sub = this.connection.state$.subscribe((s) => { - switch (s.state) { - case LivekitConnectionState.Connected: - resolve(); - break; - case "FailedToStart": - reject( - s.error instanceof ElementCallError - ? s.error - : new FailToStartLivekitConnection(s.error.message), - ); - break; - default: - this.logger.info("waiting for connection: ", s.state); + const sub = this.connection.state$.subscribe((state) => { + if (state instanceof Error) { + const error = + state instanceof ElementCallError + ? state + : new FailToStartLivekitConnection(state.message); + reject(error); + } else if (state === ConnectionState.LivekitConnected) { + resolve(); + } else { + this.logger.info("waiting for connection: ", state); } }); try { diff --git a/src/state/CallViewModel/remoteMembers/Connection.test.ts b/src/state/CallViewModel/remoteMembers/Connection.test.ts index efee1ccb1..a90f0aa2d 100644 --- a/src/state/CallViewModel/remoteMembers/Connection.test.ts +++ b/src/state/CallViewModel/remoteMembers/Connection.test.ts @@ -30,8 +30,8 @@ import { logger } from "matrix-js-sdk/lib/logger"; import type { LivekitTransport } from "matrix-js-sdk/lib/matrixrtc"; import { Connection, + ConnectionState, type ConnectionOpts, - type ConnectionState, type PublishingParticipant, } from "./Connection.ts"; import { ObservableScope } from "../../ObservableScope.ts"; @@ -151,7 +151,7 @@ describe("Start connection states", () => { }; const connection = new Connection(opts, logger); - expect(connection.state$.getValue().state).toEqual("Initialized"); + expect(connection.state$.getValue()).toEqual("Initialized"); }); it("fail to getOpenId token then error state", async () => { @@ -167,7 +167,7 @@ describe("Start connection states", () => { const connection = new Connection(opts, logger); - const capturedStates: ConnectionState[] = []; + const capturedStates: (ConnectionState | Error)[] = []; const s = connection.state$.subscribe((value) => { capturedStates.push(value); }); @@ -187,22 +187,20 @@ describe("Start connection states", () => { let capturedState = capturedStates.pop(); expect(capturedState).toBeDefined(); - expect(capturedState!.state).toEqual("FetchingConfig"); + expect(capturedState!).toEqual("FetchingConfig"); deferred.reject(new FailToGetOpenIdToken(new Error("Failed to get token"))); await vi.runAllTimersAsync(); capturedState = capturedStates.pop(); - if (capturedState!.state === "FailedToStart") { - expect(capturedState!.error.message).toEqual("Something went wrong"); + if (capturedState instanceof Error) { + expect(capturedState.message).toEqual("Something went wrong"); expect(connection.transport.livekit_alias).toEqual( livekitFocus.livekit_alias, ); } else { - expect.fail( - "Expected FailedToStart state but got " + capturedState?.state, - ); + expect.fail("Expected FailedToStart state but got " + capturedState); } }); @@ -219,7 +217,7 @@ describe("Start connection states", () => { const connection = new Connection(opts, logger); - const capturedStates: ConnectionState[] = []; + const capturedStates: (ConnectionState | Error)[] = []; const s = connection.state$.subscribe((value) => { capturedStates.push(value); }); @@ -241,24 +239,22 @@ describe("Start connection states", () => { let capturedState = capturedStates.pop(); expect(capturedState).toBeDefined(); - expect(capturedState?.state).toEqual("FetchingConfig"); + expect(capturedState).toEqual(ConnectionState.FetchingConfig); deferredSFU.resolve(); await vi.runAllTimersAsync(); capturedState = capturedStates.pop(); - if (capturedState?.state === "FailedToStart") { - expect(capturedState?.error.message).toContain( + if (capturedState instanceof Error) { + expect(capturedState.message).toContain( "SFU Config fetch failed with exception Error", ); expect(connection.transport.livekit_alias).toEqual( livekitFocus.livekit_alias, ); } else { - expect.fail( - "Expected FailedToStart state but got " + capturedState?.state, - ); + expect.fail("Expected FailedToStart state but got " + capturedState); } }); @@ -275,7 +271,7 @@ describe("Start connection states", () => { const connection = new Connection(opts, logger); - const capturedStates: ConnectionState[] = []; + const capturedStates: (ConnectionState | Error)[] = []; const s = connection.state$.subscribe((value) => { capturedStates.push(value); }); @@ -305,17 +301,15 @@ describe("Start connection states", () => { let capturedState = capturedStates.pop(); expect(capturedState).toBeDefined(); - expect(capturedState?.state).toEqual("FetchingConfig"); + expect(capturedState).toEqual(ConnectionState.FetchingConfig); deferredSFU.resolve(); await vi.runAllTimersAsync(); capturedState = capturedStates.pop(); - if (capturedState && capturedState.state === "FailedToStart") { - expect(capturedState.error.message).toContain( - "Failed to connect to livekit", - ); + if (capturedState instanceof Error) { + expect(capturedState.message).toContain("Failed to connect to livekit"); expect(connection.transport.livekit_alias).toEqual( livekitFocus.livekit_alias, ); @@ -332,7 +326,7 @@ describe("Start connection states", () => { const connection = setupRemoteConnection(); - const capturedStates: ConnectionState[] = []; + const capturedStates: (ConnectionState | Error)[] = []; const s = connection.state$.subscribe((value) => { capturedStates.push(value); }); @@ -342,13 +336,13 @@ describe("Start connection states", () => { await vi.runAllTimersAsync(); const initialState = capturedStates.shift(); - expect(initialState?.state).toEqual("Initialized"); + expect(initialState).toEqual(ConnectionState.Initialized); const fetchingState = capturedStates.shift(); - expect(fetchingState?.state).toEqual("FetchingConfig"); + expect(fetchingState).toEqual(ConnectionState.FetchingConfig); const connectingState = capturedStates.shift(); - expect(connectingState?.state).toEqual("ConnectingToLkRoom"); + expect(connectingState).toEqual(ConnectionState.ConnectingToLkRoom); const connectedState = capturedStates.shift(); - expect(connectedState?.state).toEqual("connected"); + expect(connectedState).toEqual(ConnectionState.LivekitConnected); }); it("shutting down the scope should stop the connection", async () => { diff --git a/src/state/CallViewModel/remoteMembers/Connection.ts b/src/state/CallViewModel/remoteMembers/Connection.ts index 549777f9f..29ad7a8cf 100644 --- a/src/state/CallViewModel/remoteMembers/Connection.ts +++ b/src/state/CallViewModel/remoteMembers/Connection.ts @@ -12,7 +12,6 @@ import { } from "@livekit/components-core"; import { ConnectionError, - ConnectionState as LivekitConnectionState, type Room as LivekitRoom, type LocalParticipant, type RemoteParticipant, @@ -55,14 +54,21 @@ export class FailedToStartError extends Error { } export enum ConnectionState { + /** The start state of a connection. It has been created but nothing has loaded yet. */ Initialized = "Initialized", + /** `start` has been called on the connection. It aquires the jwt info to conenct to the LK Room */ FetchingConfig = "FetchingConfig", Stopped = "Stopped", ConnectingToLkRoom = "ConnectingToLkRoom", + /** The same as ConnectionState.Disconnected from `livekit-client` */ LivekitDisconnected = "disconnected", + /** The same as ConnectionState.Connecting from `livekit-client` */ LivekitConnecting = "connecting", + /** The same as ConnectionState.Connected from `livekit-client` */ LivekitConnected = "connected", + /** The same as ConnectionState.Reconnecting from `livekit-client` */ LivekitReconnecting = "reconnecting", + /** The same as ConnectionState.SignalReconnecting from `livekit-client` */ LivekitSignalReconnecting = "signalReconnecting", } @@ -73,15 +79,14 @@ export enum ConnectionState { */ export class Connection { // Private Behavior - private readonly _state$ = new BehaviorSubject< - ConnectionState | FailedToStartError - >(ConnectionState.Initialized); + private readonly _state$ = new BehaviorSubject( + ConnectionState.Initialized, + ); /** * The current state of the connection to the media transport. */ - public readonly state$: Behavior = - this._state$; + public readonly state$: Behavior = this._state$; /** * The media transport to connect to. @@ -161,15 +166,12 @@ export class Connection { connectionStateObserver(this.livekitRoom) .pipe(this.scope.bind()) .subscribe((lkState) => { - // It si save to cast lkState to ConnectionState as they are fully overlapping. + // It is save to cast lkState to ConnectionState as they are fully overlapping. this._state$.next(lkState as unknown as ConnectionState); }); } catch (error) { this.logger.debug(`Failed to connect to LiveKit room: ${error}`); - this._state$.next({ - state: "FailedToStart", - error: error instanceof Error ? error : new Error(`${error}`), - }); + this._state$.next(error instanceof Error ? error : new Error(`${error}`)); throw error; } } @@ -194,9 +196,7 @@ export class Connection { ); if (this.stopped) return; await this.livekitRoom.disconnect(); - this._state$.next({ - state: ConnectionAdditionalState.Stopped, - }); + this._state$.next(ConnectionState.Stopped); this.stopped = true; } diff --git a/yarn.lock b/yarn.lock index 94b731302..f0ca83a70 100644 --- a/yarn.lock +++ b/yarn.lock @@ -10353,8 +10353,8 @@ __metadata: linkType: hard "matrix-js-sdk@npm:^39.2.0": - version: 39.2.0 - resolution: "matrix-js-sdk@npm:39.2.0" + version: 39.3.0 + resolution: "matrix-js-sdk@npm:39.3.0" dependencies: "@babel/runtime": "npm:^7.12.5" "@matrix-org/matrix-sdk-crypto-wasm": "npm:^15.3.0" @@ -10370,7 +10370,7 @@ __metadata: sdp-transform: "npm:^3.0.0" unhomoglyph: "npm:^1.0.6" uuid: "npm:13" - checksum: 10c0/f8b5261de2744305330ba3952821ca9303698170bfd3a0ff8a767b9286d4e8d4ed5aaf6fbaf8a1e8ff9dbd859102a2a47d882787e2da3b3078965bec00157959 + checksum: 10c0/031c9ec042e00c32dc531f82fc59c64cc25fb665abfc642b1f0765c530d60684f8bd63daf0cdd0dbe96b4f87ea3f4148f9d3f024a59d57eceaec1ce5d0164755 languageName: node linkType: hard From 7af89b421693b58d06baf2f044bdd3e39d97a623 Mon Sep 17 00:00:00 2001 From: Timo K Date: Tue, 9 Dec 2025 17:36:56 +0100 Subject: [PATCH 075/748] fix lint --- src/state/CallViewModel/localMember/LocalMember.test.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/state/CallViewModel/localMember/LocalMember.test.ts b/src/state/CallViewModel/localMember/LocalMember.test.ts index 2f8d11a51..6a9f196e9 100644 --- a/src/state/CallViewModel/localMember/LocalMember.test.ts +++ b/src/state/CallViewModel/localMember/LocalMember.test.ts @@ -38,7 +38,6 @@ import { constant } from "../../Behavior"; import { ConnectionManagerData } from "../remoteMembers/ConnectionManager"; import { ConnectionState, type Connection } from "../remoteMembers/Connection"; import { type Publisher } from "./Publisher"; -import { C } from "vitest/dist/chunks/global.d.MAmajcmJ.js"; const MATRIX_RTC_MODE = MatrixRTCMode.Legacy; const getUrlParams = vi.hoisted(() => vi.fn(() => ({}))); From 0ebc6078dd5cae4f8a2317e4ffb22f128ebd1e75 Mon Sep 17 00:00:00 2001 From: Timo K Date: Wed, 10 Dec 2025 12:08:59 +0100 Subject: [PATCH 076/748] Update LocalMember.ts --- .../CallViewModel/localMember/LocalMember.ts | 34 +++++++++++-------- 1 file changed, 19 insertions(+), 15 deletions(-) diff --git a/src/state/CallViewModel/localMember/LocalMember.ts b/src/state/CallViewModel/localMember/LocalMember.ts index e2fcc70ea..193dd53c4 100644 --- a/src/state/CallViewModel/localMember/LocalMember.ts +++ b/src/state/CallViewModel/localMember/LocalMember.ts @@ -407,9 +407,7 @@ export const createLocalMembership$ = ({ matrix: matrixError ?? rtcSessionStatus, media: mediaError ?? mediaState, }; - else { - return TransportState.Waiting; - } + return TransportState.Waiting; }, ), ), @@ -423,19 +421,21 @@ export const createLocalMembership$ = ({ ]) .subscribe(([prev, current]) => { if (!widget) return; + // JOIN prev=false (was left) => current-true (now joiend) if (!prev && current) { - try { - void widget.api.transport.send(ElementWidgetActions.JoinCall, {}); - } catch (e) { - logger.error("Failed to send join action", e); - } + widget.api.transport + .send(ElementWidgetActions.JoinCall, {}) + .catch((e) => { + logger.error("Failed to send join action", e); + }); } + // LEAVE prev=false (was joined) => current-true (now left) if (prev && !current) { - try { - void widget?.api.transport.send(ElementWidgetActions.HangupCall, {}); - } catch (e) { - logger.error("Failed to send hangup action", e); - } + widget.api.transport + .send(ElementWidgetActions.HangupCall, {}) + .catch((e) => { + logger.error("Failed to send hangup action", e); + }); } }); @@ -575,8 +575,12 @@ export const createLocalMembership$ = ({ tracks$, participant$, reconnecting$: scope.behavior( - homeserverConnected.rtsSession$.pipe( - map((sessionStatus) => sessionStatus === RTCSessionStatus.Reconnecting), + localMemberState$.pipe( + map((state) => { + if (typeof state === "object" && "matrix" in state) + return state.matrix === RTCSessionStatus.Reconnecting; + return false; + }), ), ), disconnected$: scope.behavior( From 6efce232f81528c4df4b61f56393dc62e0040549 Mon Sep 17 00:00:00 2001 From: Timo K Date: Wed, 10 Dec 2025 18:50:19 +0100 Subject: [PATCH 077/748] fix playwright tests --- src/state/CallViewModel/CallViewModel.ts | 63 ++++++++++---- .../CallViewModel/localMember/LocalMember.ts | 82 ++++++++++++------- .../CallViewModel/localMember/Publisher.ts | 60 +++++++------- .../CallViewModel/remoteMembers/Connection.ts | 4 +- 4 files changed, 129 insertions(+), 80 deletions(-) diff --git a/src/state/CallViewModel/CallViewModel.ts b/src/state/CallViewModel/CallViewModel.ts index e04f46981..35ab658be 100644 --- a/src/state/CallViewModel/CallViewModel.ts +++ b/src/state/CallViewModel/CallViewModel.ts @@ -99,6 +99,7 @@ import { createHomeserverConnected$ } from "./localMember/HomeserverConnected.ts import { createLocalMembership$, enterRTCSession, + TransportState, } from "./localMember/LocalMember.ts"; import { createLocalTransport$ } from "./localMember/LocalTransport.ts"; import { @@ -577,17 +578,6 @@ export function createCallViewModel$( ), ); - /** - * Whether various media/event sources should pretend to be disconnected from - * all network input, even if their connection still technically works. - */ - // We do this when the app is in the 'reconnecting' state, because it might be - // that the LiveKit connection is still functional while the homeserver is - // down, for example, and we want to avoid making people worry that the app is - // in a split-brained state. - // DISCUSSION own membership manager ALSO this probably can be simplifis - const reconnecting$ = localMembership.reconnecting$; - const audioParticipants$ = scope.behavior( matrixLivekitMembers$.pipe( switchMap((membersWithEpoch) => { @@ -635,7 +625,7 @@ export function createCallViewModel$( ); const handsRaised$ = scope.behavior( - handsRaisedSubject$.pipe(pauseWhen(reconnecting$)), + handsRaisedSubject$.pipe(pauseWhen(localMembership.reconnecting$)), ); const reactions$ = scope.behavior( @@ -648,7 +638,7 @@ export function createCallViewModel$( ]), ), ), - pauseWhen(reconnecting$), + pauseWhen(localMembership.reconnecting$), ), ); @@ -739,7 +729,7 @@ export function createCallViewModel$( livekitRoom$, focusUrl$, mediaDevices, - reconnecting$, + localMembership.reconnecting$, displayName$, matrixMemberMetadataStore.createAvatarUrlBehavior$(userId), handsRaised$.pipe(map((v) => v[participantId]?.time ?? null)), @@ -1422,6 +1412,37 @@ export function createCallViewModel$( // reassigned here to make it publicly accessible const toggleScreenSharing = localMembership.toggleScreenSharing; + const errors$ = scope.behavior<{ + transportError?: ElementCallError; + matrixError?: ElementCallError; + connectionError?: ElementCallError; + publishError?: ElementCallError; + } | null>( + localMembership.localMemberState$.pipe( + map((value) => { + const returnObject: { + transportError?: ElementCallError; + matrixError?: ElementCallError; + connectionError?: ElementCallError; + publishError?: ElementCallError; + } = {}; + if (value instanceof ElementCallError) return { transportError: value }; + if (value === TransportState.Waiting) return null; + if (value.matrix instanceof ElementCallError) + returnObject.matrixError = value.matrix; + if (value.media instanceof ElementCallError) + returnObject.publishError = value.media; + else if ( + typeof value.media === "object" && + value.media.connection instanceof ElementCallError + ) + returnObject.connectionError = value.media.connection; + return returnObject; + }), + ), + null, + ); + return { autoLeave$: autoLeave$, callPickupState$: callPickupState$, @@ -1438,8 +1459,16 @@ export function createCallViewModel$( unhoverScreen: (): void => screenUnhover$.next(), fatalError$: scope.behavior( - localMembership.localMemberState$.pipe( - filter((v) => v instanceof ElementCallError), + errors$.pipe( + map((errors) => { + return ( + errors?.transportError ?? + errors?.matrixError ?? + errors?.connectionError ?? + null + ); + }), + filter((error) => error !== null), ), null, ), @@ -1472,7 +1501,7 @@ export function createCallViewModel$( showFooter$: showFooter$, earpieceMode$: earpieceMode$, audioOutputSwitcher$: audioOutputSwitcher$, - reconnecting$: reconnecting$, + reconnecting$: localMembership.reconnecting$, }; } diff --git a/src/state/CallViewModel/localMember/LocalMember.ts b/src/state/CallViewModel/localMember/LocalMember.ts index df42cba99..532d5d551 100644 --- a/src/state/CallViewModel/localMember/LocalMember.ts +++ b/src/state/CallViewModel/localMember/LocalMember.ts @@ -42,6 +42,7 @@ import { type Publisher } from "./Publisher.ts"; import { type MuteStates } from "../../MuteStates.ts"; import { ElementCallError, + FailToStartLivekitConnection, MembershipManagerError, UnknownCallError, } from "../../../utils/errors.ts"; @@ -56,6 +57,7 @@ import { type FailedToStartError, } from "../remoteMembers/Connection.ts"; import { type HomeserverConnected } from "./HomeserverConnected.ts"; +import { and$ } from "../../../utils/observable.ts"; export enum TransportState { /** Not even a transport is available to the LocalMembership */ @@ -86,13 +88,12 @@ export type LocalMemberMediaState = } | PublishState | ElementCallError; -export type LocalMemberMatrixState = Error | RTCSessionStatus; export type LocalMemberState = | ElementCallError | TransportState.Waiting | { media: LocalMemberMediaState; - matrix: LocalMemberMatrixState; + matrix: ElementCallError | RTCSessionStatus; }; /* @@ -220,10 +221,6 @@ export const createLocalMembership$ = ({ ), ); - const localConnectionState$ = localConnection$.pipe( - switchMap((connection) => (connection ? connection.state$ : of(null))), - ); - // MATRIX RELATED // This should be used in a combineLatest with publisher$ to connect. @@ -308,23 +305,27 @@ export const createLocalMembership$ = ({ try { await publisher?.startPublishing(); } catch (error) { - setMediaError(error as ElementCallError); + const message = + error instanceof Error ? error.message : String(error); + setPublishError(new FailToStartLivekitConnection(message)); } } else if (tracks.length !== 0 && !shouldJoinAndPublish) { try { await publisher?.stopPublishing(); } catch (error) { - setMediaError(new UnknownCallError(error as Error)); + setPublishError(new UnknownCallError(error as Error)); } } }, ); - const fatalMediaError$ = new BehaviorSubject(null); - const setMediaError = (e: ElementCallError): void => { - if (fatalMediaError$.value !== null) - logger.error("Multiple Media Errors:", e); - else fatalMediaError$.next(e); + // STATE COMPUTATION + + // These are non fatal since we can join a room and concume media even though publishing failed. + const publishError$ = new BehaviorSubject(null); + const setPublishError = (e: ElementCallError): void => { + if (publishError$.value !== null) logger.error("Multiple Media Errors:", e); + else publishError$.next(e); }; const fatalTransportError$ = new BehaviorSubject( @@ -336,6 +337,10 @@ export const createLocalMembership$ = ({ else fatalTransportError$.next(e); }; + const localConnectionState$ = localConnection$.pipe( + switchMap((connection) => (connection ? connection.state$ : of(null))), + ); + const mediaState$: Behavior = scope.behavior( combineLatest([ localConnectionState$, @@ -392,22 +397,22 @@ export const createLocalMembership$ = ({ homeserverConnected.rtsSession$, fatalMatrixError$, fatalTransportError$, - fatalMediaError$, + publishError$, ]).pipe( map( ([ mediaState, rtcSessionStatus, - matrixError, - transportError, - mediaError, + fatalMatrixError, + fatalTransportError, + publishError, ]) => { - if (transportError !== null) return transportError; - // `mediaState` will be 'null' until the transport appears. + if (fatalTransportError !== null) return fatalTransportError; + // `mediaState` will be 'null' until the transport/connection appears. if (mediaState && rtcSessionStatus) return { - matrix: matrixError ?? rtcSessionStatus, - media: mediaError ?? mediaState, + matrix: fatalMatrixError ?? rtcSessionStatus, + media: publishError ?? mediaState, }; return TransportState.Waiting; }, @@ -415,6 +420,31 @@ export const createLocalMembership$ = ({ ), ); + /** + * Whether we are "fully" connected to the call. Accounts for both the + * connection to the MatrixRTC session and the LiveKit publish connection. + */ + const matrixAndLivekitConnected$ = scope.behavior( + and$( + homeserverConnected.combined$, + localConnectionState$.pipe( + map((state) => state === ConnectionState.LivekitConnected), + ), + ).pipe( + tap((v) => logger.debug("livekit+matrix: Connected state changed", v)), + ), + ); + + /** + * Whether we should tell the user that we're reconnecting to the call. + */ + const reconnecting$ = scope.behavior( + matrixAndLivekitConnected$.pipe( + pairwise(), + map(([prev, current]) => prev === true && current === false), + ), + ); + // inform the widget about the connect and disconnect intent from the user. scope .behavior(joinAndPublishRequested$.pipe(pairwise(), scope.bind()), [ @@ -576,15 +606,7 @@ export const createLocalMembership$ = ({ localMemberState$, tracks$, participant$, - reconnecting$: scope.behavior( - localMemberState$.pipe( - map((state) => { - if (typeof state === "object" && "matrix" in state) - return state.matrix === RTCSessionStatus.Reconnecting; - return false; - }), - ), - ), + reconnecting$, disconnected$: scope.behavior( homeserverConnected.rtsSession$.pipe( map((state) => state === RTCSessionStatus.Disconnected), diff --git a/src/state/CallViewModel/localMember/Publisher.ts b/src/state/CallViewModel/localMember/Publisher.ts index b32e7e99c..df67f1799 100644 --- a/src/state/CallViewModel/localMember/Publisher.ts +++ b/src/state/CallViewModel/localMember/Publisher.ts @@ -32,15 +32,8 @@ import { } from "../../../livekit/TrackProcessorContext.tsx"; import { getUrlParams } from "../../../UrlParams.ts"; import { observeTrackReference$ } from "../../MediaViewModel.ts"; -import { - ConnectionState, - type Connection, -} from "../remoteMembers/Connection.ts"; +import { type Connection } from "../remoteMembers/Connection.ts"; import { type ObservableScope } from "../../ObservableScope.ts"; -import { - ElementCallError, - FailToStartLivekitConnection, -} from "../../../utils/errors.ts"; /** * A wrapper for a Connection object. @@ -160,27 +153,29 @@ export class Publisher { public async startPublishing(): Promise { this.logger.debug("startPublishing called"); const lkRoom = this.connection.livekitRoom; - const { promise, resolve, reject } = Promise.withResolvers(); - const sub = this.connection.state$.subscribe((state) => { - if (state instanceof Error) { - const error = - state instanceof ElementCallError - ? state - : new FailToStartLivekitConnection(state.message); - reject(error); - } else if (state === ConnectionState.LivekitConnected) { - resolve(); - } else { - this.logger.info("waiting for connection: ", state); - } - }); - try { - await promise; - } catch (e) { - throw e; - } finally { - sub.unsubscribe(); - } + + // we do not need to do this since lk will wait in `localParticipant.publishTrack` + // const { promise, resolve, reject } = Promise.withResolvers(); + // const sub = this.connection.state$.subscribe((state) => { + // if (state instanceof Error) { + // const error = + // state instanceof ElementCallError + // ? state + // : new FailToStartLivekitConnection(state.message); + // reject(error); + // } else if (state === ConnectionState.LivekitConnected) { + // resolve(); + // } else { + // this.logger.info("waiting for connection: ", state); + // } + // }); + // try { + // await promise; + // } catch (e) { + // throw e; + // } finally { + // sub.unsubscribe(); + // } for (const track of this.tracks$.value) { this.logger.info("publish ", this.tracks$.value.length, "tracks"); @@ -188,9 +183,10 @@ export class Publisher { // with a timeout. await lkRoom.localParticipant.publishTrack(track).catch((error) => { this.logger.error("Failed to publish track", error); - throw new FailToStartLivekitConnection( - error instanceof Error ? error.message : error, - ); + // throw new FailToStartLivekitConnection( + // error instanceof Error ? error.message : error, + // ); + throw error; }); this.logger.info("published track ", track.kind, track.id); diff --git a/src/state/CallViewModel/remoteMembers/Connection.ts b/src/state/CallViewModel/remoteMembers/Connection.ts index 29ad7a8cf..2fd9eaa8e 100644 --- a/src/state/CallViewModel/remoteMembers/Connection.ts +++ b/src/state/CallViewModel/remoteMembers/Connection.ts @@ -150,7 +150,8 @@ export class Connection { throw new InsufficientCapacityError(); } if (e.status === 404) { - // error msg is "Could not establish signal connection: requested room does not exist" + // error msg is "Failed to create call" + // error description is "Call creation might be restricted to authorized users only. Try again later, or contact your server admin if the problem persists." // The room does not exist. There are two different modes of operation for the SFU: // - the room is created on the fly when connecting (livekit `auto_create` option) // - Only authorized users can create rooms, so the room must exist before connecting (done by the auth jwt service) @@ -172,6 +173,7 @@ export class Connection { } catch (error) { this.logger.debug(`Failed to connect to LiveKit room: ${error}`); this._state$.next(error instanceof Error ? error : new Error(`${error}`)); + // Its okay to ignore the throw. The error is part of the state. throw error; } } From 1941fc9ca1cc17becdc170e5c5b691ae8edd6c0f Mon Sep 17 00:00:00 2001 From: Timo K Date: Wed, 10 Dec 2025 19:12:52 +0100 Subject: [PATCH 078/748] fix tests. --- src/state/CallViewModel/localMember/LocalMember.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/state/CallViewModel/localMember/LocalMember.ts b/src/state/CallViewModel/localMember/LocalMember.ts index 532d5d551..73908fcb0 100644 --- a/src/state/CallViewModel/localMember/LocalMember.ts +++ b/src/state/CallViewModel/localMember/LocalMember.ts @@ -443,6 +443,7 @@ export const createLocalMembership$ = ({ pairwise(), map(([prev, current]) => prev === true && current === false), ), + false, ); // inform the widget about the connect and disconnect intent from the user. From 667a3d0e3d911ad602b48ae4906ef0da6dc3f085 Mon Sep 17 00:00:00 2001 From: Timo K Date: Wed, 10 Dec 2025 19:18:16 +0100 Subject: [PATCH 079/748] fix test not checking for livekit connection state anymore. --- .../CallViewModel/localMember/Publisher.test.ts | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/src/state/CallViewModel/localMember/Publisher.test.ts b/src/state/CallViewModel/localMember/Publisher.test.ts index 6d27c0429..68845fa22 100644 --- a/src/state/CallViewModel/localMember/Publisher.test.ts +++ b/src/state/CallViewModel/localMember/Publisher.test.ts @@ -98,7 +98,7 @@ describe("Publisher", () => { ).mockRejectedValue(Error("testError")); await expect(publisher.startPublishing()).rejects.toThrow( - new FailToStartLivekitConnection("testError"), + new Error("testError"), ); // does not try other conenction after the first one failed @@ -106,17 +106,6 @@ describe("Publisher", () => { connection.livekitRoom.localParticipant.publishTrack, ).toHaveBeenCalledTimes(1); - // failiour due to connection.state$ - const beforeState = connection.state$.value; - (connection.state$ as BehaviorSubject).next(Error("testStartError")); - - await expect(publisher.startPublishing()).rejects.toThrow( - new FailToStartLivekitConnection("testStartError"), - ); - (connection.state$ as BehaviorSubject).next( - beforeState, - ); - // does not try other conenction after the first one failed expect( connection.livekitRoom.localParticipant.publishTrack, From b380532d3080275388810ec124d578dd57a787b5 Mon Sep 17 00:00:00 2001 From: Timo K Date: Wed, 10 Dec 2025 21:14:13 +0100 Subject: [PATCH 080/748] lots of error logging and fixing playwright --- src/room/GroupCallView.tsx | 1 + src/room/InCallView.tsx | 7 ++++++- src/room/LobbyView.tsx | 4 ++-- src/state/CallViewModel/CallViewModel.ts | 15 +++++++++++++- .../CallViewModel/localMember/LocalMember.ts | 20 +++++++++++++------ .../localMember/LocalTransport.ts | 2 +- .../CallViewModel/remoteMembers/Connection.ts | 14 +++++++++---- 7 files changed, 48 insertions(+), 15 deletions(-) diff --git a/src/room/GroupCallView.tsx b/src/room/GroupCallView.tsx index dfd11ff32..1542678e8 100644 --- a/src/room/GroupCallView.tsx +++ b/src/room/GroupCallView.tsx @@ -446,6 +446,7 @@ export const GroupCallView: FC = ({ let body: ReactNode; if (externalError) { + logger.debug("External error occurred:", externalError); // If an error was recorded within this component but outside // GroupCallErrorBoundary, create a component that rethrows the error from // within the error boundary, so it can be handled uniformly diff --git a/src/room/InCallView.tsx b/src/room/InCallView.tsx index 7ae3700cd..18acf843e 100644 --- a/src/room/InCallView.tsx +++ b/src/room/InCallView.tsx @@ -127,6 +127,7 @@ export const ActiveCall: FC = (props) => { const mediaDevices = useMediaDevices(); const trackProcessorState$ = useTrackProcessorObservable$(); useEffect(() => { + logger.info("START CALL VIEW SCOPE"); const scope = new ObservableScope(); const reactionsReader = new ReactionsReader(scope, props.rtcSession); const { autoLeaveWhenOthersLeft, waitForCallPickup, sendNotificationType } = @@ -153,6 +154,7 @@ export const ActiveCall: FC = (props) => { vm.leave$.pipe(scope.bind()).subscribe(props.onLeft); return (): void => { + logger.info("END CALL VIEW SCOPE"); scope.end(); }; }, [ @@ -271,7 +273,10 @@ export const InCallView: FC = ({ const ringOverlay = useBehavior(vm.ringOverlay$); const fatalCallError = useBehavior(vm.fatalError$); // Stop the rendering and throw for the error boundary - if (fatalCallError) throw fatalCallError; + if (fatalCallError) { + logger.debug("fatalCallError stop rendering", fatalCallError); + throw fatalCallError; + } // We need to set the proper timings on the animation based upon the sound length. const ringDuration = pickupPhaseAudio?.soundDuration["waiting"] ?? 1; diff --git a/src/room/LobbyView.tsx b/src/room/LobbyView.tsx index ad4f30b38..10e098f1d 100644 --- a/src/room/LobbyView.tsx +++ b/src/room/LobbyView.tsx @@ -79,9 +79,9 @@ export const LobbyView: FC = ({ waitingForInvite, }) => { useEffect(() => { - logger.info("[Lifecycle] GroupCallView Component mounted"); + logger.info("[Lifecycle] LobbyView Component mounted"); return (): void => { - logger.info("[Lifecycle] GroupCallView Component unmounted"); + logger.info("[Lifecycle] LobbyView Component unmounted"); }; }, []); diff --git a/src/state/CallViewModel/CallViewModel.ts b/src/state/CallViewModel/CallViewModel.ts index 35ab658be..6a9eadea3 100644 --- a/src/state/CallViewModel/CallViewModel.ts +++ b/src/state/CallViewModel/CallViewModel.ts @@ -15,6 +15,7 @@ import { } from "livekit-client"; import { type Room as MatrixRoom } from "matrix-js-sdk"; import { + catchError, combineLatest, distinctUntilChanged, filter, @@ -425,7 +426,18 @@ export function createCallViewModel$( connectionFactory: connectionFactory, inputTransports$: scope.behavior( combineLatest( - [localTransport$, membershipsAndTransports.transports$], + [ + localTransport$.pipe( + catchError((e) => { + logger.info( + "dont pass local transport to createConnectionManager$. localTransport$ threw an error", + e, + ); + return of(null); + }), + ), + membershipsAndTransports.transports$, + ], (localTransport, transports) => { const localTransportAsArray = localTransport ? [localTransport] : []; return transports.mapInner((transports) => [ @@ -1461,6 +1473,7 @@ export function createCallViewModel$( fatalError$: scope.behavior( errors$.pipe( map((errors) => { + logger.debug("errors$ to compute any fatal errors:", errors); return ( errors?.transportError ?? errors?.matrixError ?? diff --git a/src/state/CallViewModel/localMember/LocalMember.ts b/src/state/CallViewModel/localMember/LocalMember.ts index 73908fcb0..40fb62d62 100644 --- a/src/state/CallViewModel/localMember/LocalMember.ts +++ b/src/state/CallViewModel/localMember/LocalMember.ts @@ -324,17 +324,23 @@ export const createLocalMembership$ = ({ // These are non fatal since we can join a room and concume media even though publishing failed. const publishError$ = new BehaviorSubject(null); const setPublishError = (e: ElementCallError): void => { - if (publishError$.value !== null) logger.error("Multiple Media Errors:", e); - else publishError$.next(e); + if (publishError$.value !== null) { + logger.error("Multiple Media Errors:", e); + } else { + publishError$.next(e); + } }; const fatalTransportError$ = new BehaviorSubject( null, ); + const setTransportError = (e: ElementCallError): void => { - if (fatalTransportError$.value !== null) + if (fatalTransportError$.value !== null) { logger.error("Multiple Transport Errors:", e); - else fatalTransportError$.next(e); + } else { + fatalTransportError$.next(e); + } }; const localConnectionState$ = localConnection$.pipe( @@ -386,9 +392,11 @@ export const createLocalMembership$ = ({ ); const fatalMatrixError$ = new BehaviorSubject(null); const setMatrixError = (e: ElementCallError): void => { - if (fatalMatrixError$.value !== null) + if (fatalMatrixError$.value !== null) { logger.error("Multiple Matrix Errors:", e); - else fatalMatrixError$.next(e); + } else { + fatalMatrixError$.next(e); + } }; const localMemberState$ = scope.behavior( diff --git a/src/state/CallViewModel/localMember/LocalTransport.ts b/src/state/CallViewModel/localMember/LocalTransport.ts index 0a85bbc13..1320b8c46 100644 --- a/src/state/CallViewModel/localMember/LocalTransport.ts +++ b/src/state/CallViewModel/localMember/LocalTransport.ts @@ -85,7 +85,7 @@ export const createLocalTransport$ = ({ * The transport that we would personally prefer to publish on (if not for the * transport preferences of others, perhaps). * - * @throws + * @throws MatrixRTCTransportMissingError | FailToGetOpenIdToken */ const preferredTransport$: Behavior = scope.behavior( customLivekitUrl.value$.pipe( diff --git a/src/state/CallViewModel/remoteMembers/Connection.ts b/src/state/CallViewModel/remoteMembers/Connection.ts index 2fd9eaa8e..c801b3ae6 100644 --- a/src/state/CallViewModel/remoteMembers/Connection.ts +++ b/src/state/CallViewModel/remoteMembers/Connection.ts @@ -29,8 +29,10 @@ import { import { type Behavior } from "../../Behavior.ts"; import { type ObservableScope } from "../../ObservableScope.ts"; import { + ElementCallError, InsufficientCapacityError, SFURoomCreationRestrictedError, + UnknownCallError, } from "../../../utils/errors.ts"; export type PublishingParticipant = LocalParticipant | RemoteParticipant; @@ -79,9 +81,9 @@ export enum ConnectionState { */ export class Connection { // Private Behavior - private readonly _state$ = new BehaviorSubject( - ConnectionState.Initialized, - ); + private readonly _state$ = new BehaviorSubject< + ConnectionState | ElementCallError + >(ConnectionState.Initialized); /** * The current state of the connection to the media transport. @@ -131,6 +133,8 @@ export class Connection { this.stopped = false; try { this._state$.next(ConnectionState.FetchingConfig); + // We should already have this information after creating the localTransport. + // It would probably be better to forward this here. const { url, jwt } = await this.getSFUConfigWithOpenID(); // If we were stopped while fetching the config, don't proceed to connect if (this.stopped) return; @@ -172,7 +176,9 @@ export class Connection { }); } catch (error) { this.logger.debug(`Failed to connect to LiveKit room: ${error}`); - this._state$.next(error instanceof Error ? error : new Error(`${error}`)); + this._state$.next( + error instanceof ElementCallError ? error : new UnknownCallError(error), + ); // Its okay to ignore the throw. The error is part of the state. throw error; } From 8dac0366b64d22da6ede6162dc3e2dcf7d57273b Mon Sep 17 00:00:00 2001 From: Timo K Date: Wed, 10 Dec 2025 21:17:33 +0100 Subject: [PATCH 081/748] fix lints --- src/state/CallViewModel/localMember/Publisher.test.ts | 6 +----- src/state/CallViewModel/remoteMembers/Connection.ts | 6 +++++- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/state/CallViewModel/localMember/Publisher.test.ts b/src/state/CallViewModel/localMember/Publisher.test.ts index 68845fa22..40763a999 100644 --- a/src/state/CallViewModel/localMember/Publisher.test.ts +++ b/src/state/CallViewModel/localMember/Publisher.test.ts @@ -26,12 +26,8 @@ import { mockMediaDevices, } from "../../../utils/test"; import { Publisher } from "./Publisher"; -import { - type Connection, - type ConnectionState, -} from "../remoteMembers/Connection"; +import { type Connection } from "../remoteMembers/Connection"; import { type MuteStates } from "../../MuteStates"; -import { FailToStartLivekitConnection } from "../../../utils/errors"; describe("Publisher", () => { let scope: ObservableScope; diff --git a/src/state/CallViewModel/remoteMembers/Connection.ts b/src/state/CallViewModel/remoteMembers/Connection.ts index c801b3ae6..6015bf01f 100644 --- a/src/state/CallViewModel/remoteMembers/Connection.ts +++ b/src/state/CallViewModel/remoteMembers/Connection.ts @@ -177,7 +177,11 @@ export class Connection { } catch (error) { this.logger.debug(`Failed to connect to LiveKit room: ${error}`); this._state$.next( - error instanceof ElementCallError ? error : new UnknownCallError(error), + error instanceof ElementCallError + ? error + : error instanceof Error + ? new UnknownCallError(error) + : new UnknownCallError(new Error(`${error}`)), ); // Its okay to ignore the throw. The error is part of the state. throw error; From e626698fda8dd87213ccda763d3f04f86b830478 Mon Sep 17 00:00:00 2001 From: Timo K Date: Wed, 10 Dec 2025 21:22:55 +0100 Subject: [PATCH 082/748] fix connection tests --- .../remoteMembers/Connection.test.ts | 21 ++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/src/state/CallViewModel/remoteMembers/Connection.test.ts b/src/state/CallViewModel/remoteMembers/Connection.test.ts index a90f0aa2d..95ff931ef 100644 --- a/src/state/CallViewModel/remoteMembers/Connection.test.ts +++ b/src/state/CallViewModel/remoteMembers/Connection.test.ts @@ -36,7 +36,10 @@ import { } from "./Connection.ts"; import { ObservableScope } from "../../ObservableScope.ts"; import { type OpenIDClientParts } from "../../../livekit/openIDSFU.ts"; -import { FailToGetOpenIdToken } from "../../../utils/errors.ts"; +import { + ElementCallError, + FailToGetOpenIdToken, +} from "../../../utils/errors.ts"; let testScope: ObservableScope; @@ -246,8 +249,11 @@ describe("Start connection states", () => { capturedState = capturedStates.pop(); - if (capturedState instanceof Error) { - expect(capturedState.message).toContain( + if ( + capturedState instanceof ElementCallError && + capturedState.cause instanceof Error + ) { + expect(capturedState.cause.message).toContain( "SFU Config fetch failed with exception Error", ); expect(connection.transport.livekit_alias).toEqual( @@ -308,8 +314,13 @@ describe("Start connection states", () => { capturedState = capturedStates.pop(); - if (capturedState instanceof Error) { - expect(capturedState.message).toContain("Failed to connect to livekit"); + if ( + capturedState instanceof ElementCallError && + capturedState.cause instanceof Error + ) { + expect(capturedState.cause.message).toContain( + "Failed to connect to livekit", + ); expect(connection.transport.livekit_alias).toEqual( livekitFocus.livekit_alias, ); From aabd76044b7a4d9bc259f5ff1c76ac1eab3d8682 Mon Sep 17 00:00:00 2001 From: Timo K Date: Wed, 10 Dec 2025 21:25:35 +0100 Subject: [PATCH 083/748] fix lint --- src/state/CallViewModel/CallViewModel.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/state/CallViewModel/CallViewModel.ts b/src/state/CallViewModel/CallViewModel.ts index 6a9eadea3..aac88a3be 100644 --- a/src/state/CallViewModel/CallViewModel.ts +++ b/src/state/CallViewModel/CallViewModel.ts @@ -428,7 +428,7 @@ export function createCallViewModel$( combineLatest( [ localTransport$.pipe( - catchError((e) => { + catchError((e: unknown) => { logger.info( "dont pass local transport to createConnectionManager$. localTransport$ threw an error", e, From 170a38c0bae050c752d99aed150f2dfd9605b86d Mon Sep 17 00:00:00 2001 From: Timo K Date: Thu, 11 Dec 2025 11:30:14 +0100 Subject: [PATCH 084/748] fix playwright incompatible browser toast --- playwright/fixtures/widget-user.ts | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/playwright/fixtures/widget-user.ts b/playwright/fixtures/widget-user.ts index 433c960b4..b0c46788a 100644 --- a/playwright/fixtures/widget-user.ts +++ b/playwright/fixtures/widget-user.ts @@ -113,7 +113,8 @@ async function registerUser( await page.getByRole("button", { name: "Register" }).click(); const continueButton = page.getByRole("button", { name: "Continue" }); try { - await expect(continueButton).toBeVisible({ timeout: 5000 }); + await expect(continueButton).toBeVisible({ timeout: 700 }); + // why do we need to put in the passwor if there is a continue button? await page .getByRole("textbox", { name: "Password", exact: true }) .fill(PASSWORD); @@ -124,6 +125,16 @@ async function registerUser( await expect( page.getByRole("heading", { name: `Welcome ${username}` }), ).toBeVisible(); + + // Dismiss incompatible browser toast + const dismissButton = page.getByRole("button", { name: "Dismiss" }); + try { + await expect(dismissButton).toBeVisible({ timeout: 700 }); + await dismissButton.click(); + } catch { + // dismissButton not visible, continue as normal + } + await setDevToolElementCallDevUrl(page); const clientHandle = await page.evaluateHandle(() => From 328cc7133a2377043061cf0e162547661a8eca55 Mon Sep 17 00:00:00 2001 From: Timo K Date: Thu, 11 Dec 2025 11:32:28 +0100 Subject: [PATCH 085/748] update playwright so that we do not even need the dismiss anymore. --- package.json | 2 +- yarn.lock | 30 +++++++++++++++--------------- 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/package.json b/package.json index 21c870adb..f65865e42 100644 --- a/package.json +++ b/package.json @@ -54,7 +54,7 @@ "@opentelemetry/sdk-trace-base": "^2.0.0", "@opentelemetry/sdk-trace-web": "^2.0.0", "@opentelemetry/semantic-conventions": "^1.25.1", - "@playwright/test": "^1.56.1", + "@playwright/test": "^1.57.0", "@radix-ui/react-dialog": "^1.0.4", "@radix-ui/react-slider": "^1.1.2", "@radix-ui/react-visually-hidden": "^1.0.3", diff --git a/yarn.lock b/yarn.lock index f0ca83a70..02a4a3ce1 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3373,14 +3373,14 @@ __metadata: languageName: node linkType: hard -"@playwright/test@npm:^1.56.1": - version: 1.56.1 - resolution: "@playwright/test@npm:1.56.1" +"@playwright/test@npm:^1.57.0": + version: 1.57.0 + resolution: "@playwright/test@npm:1.57.0" dependencies: - playwright: "npm:1.56.1" + playwright: "npm:1.57.0" bin: playwright: cli.js - checksum: 10c0/2b5b0e1f2e6a18f6e5ce6897c7440ca78f64e0b004834e9808e93ad2b78b96366b562ae4366602669cf8ad793a43d85481b58541e74be71e905e732d833dd691 + checksum: 10c0/35ba4b28be72bf0a53e33dbb11c6cff848fb9a37f49e893ce63a90675b5291ec29a1ba82c8a3b043abaead129400f0589623e9ace2e6a1c8eaa409721ecc3774 languageName: node linkType: hard @@ -7492,7 +7492,7 @@ __metadata: "@opentelemetry/sdk-trace-base": "npm:^2.0.0" "@opentelemetry/sdk-trace-web": "npm:^2.0.0" "@opentelemetry/semantic-conventions": "npm:^1.25.1" - "@playwright/test": "npm:^1.56.1" + "@playwright/test": "npm:^1.57.0" "@radix-ui/react-dialog": "npm:^1.0.4" "@radix-ui/react-slider": "npm:^1.1.2" "@radix-ui/react-visually-hidden": "npm:^1.0.3" @@ -11177,27 +11177,27 @@ __metadata: languageName: node linkType: hard -"playwright-core@npm:1.56.1": - version: 1.56.1 - resolution: "playwright-core@npm:1.56.1" +"playwright-core@npm:1.57.0": + version: 1.57.0 + resolution: "playwright-core@npm:1.57.0" bin: playwright-core: cli.js - checksum: 10c0/ffd40142b99c68678b387445d5b42f1fee4ab0b65d983058c37f342e5629f9cdbdac0506ea80a0dfd41a8f9f13345bad54e9a8c35826ef66dc765f4eb3db8da7 + checksum: 10c0/798e35d83bf48419a8c73de20bb94d68be5dde68de23f95d80a0ebe401e3b83e29e3e84aea7894d67fa6c79d2d3d40cc5bcde3e166f657ce50987aaa2421b6a9 languageName: node linkType: hard -"playwright@npm:1.56.1": - version: 1.56.1 - resolution: "playwright@npm:1.56.1" +"playwright@npm:1.57.0": + version: 1.57.0 + resolution: "playwright@npm:1.57.0" dependencies: fsevents: "npm:2.3.2" - playwright-core: "npm:1.56.1" + playwright-core: "npm:1.57.0" dependenciesMeta: fsevents: optional: true bin: playwright: cli.js - checksum: 10c0/8e9965aede86df0f4722063385748498977b219630a40a10d1b82b8bd8d4d4e9b6b65ecbfa024331a30800163161aca292fb6dd7446c531a1ad25f4155625ab4 + checksum: 10c0/ab03c99a67b835bdea9059f516ad3b6e42c21025f9adaa161a4ef6bc7ca716dcba476d287140bb240d06126eb23f889a8933b8f5f1f1a56b80659d92d1358899 languageName: node linkType: hard From c1c73b0f02a8c1e6ee6e4fec4b567a2a0e0b29a4 Mon Sep 17 00:00:00 2001 From: Timo K Date: Thu, 11 Dec 2025 15:04:07 +0100 Subject: [PATCH 086/748] lint --- sdk/main.ts | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/sdk/main.ts b/sdk/main.ts index 1dfbbcbfa..d26832778 100644 --- a/sdk/main.ts +++ b/sdk/main.ts @@ -32,7 +32,6 @@ import { type CallMembership, MatrixRTCSession, MatrixRTCSessionEvent, - SlotDescription, } from "matrix-js-sdk/lib/matrixrtc"; import { type Room as LivekitRoom, @@ -98,10 +97,13 @@ export async function createMatrixRTCSdk( const mediaDevices = new MediaDevices(scope); const muteStates = new MuteStates(scope, mediaDevices, constant(true)); - const rtcSession = new MatrixRTCSession(client, room, { - application, - id, - }); + const slot = { application, id }; + const rtcSession = new MatrixRTCSession( + client, + room, + MatrixRTCSession.sessionMembershipsForSlot(room, slot), + slot, + ); const callViewModel = createCallViewModel$( scope, rtcSession, From 08306d663a16ad6193d7bb395649c0a228ffe160 Mon Sep 17 00:00:00 2001 From: Timo K Date: Thu, 11 Dec 2025 16:04:12 +0100 Subject: [PATCH 087/748] remove duplicated connecting state and update Test setup --- .../remoteMembers/Connection.test.ts | 40 +++++++++++-------- .../CallViewModel/remoteMembers/Connection.ts | 22 +++++----- 2 files changed, 35 insertions(+), 27 deletions(-) diff --git a/src/state/CallViewModel/remoteMembers/Connection.test.ts b/src/state/CallViewModel/remoteMembers/Connection.test.ts index 95ff931ef..8f9471d0e 100644 --- a/src/state/CallViewModel/remoteMembers/Connection.test.ts +++ b/src/state/CallViewModel/remoteMembers/Connection.test.ts @@ -50,11 +50,6 @@ let fakeLivekitRoom: MockedObject; let localParticipantEventEmiter: EventEmitter; let fakeLocalParticipant: MockedObject; -let fakeRoomEventEmiter: EventEmitter; -// let fakeMembershipsFocusMap$: BehaviorSubject< -// { membership: CallMembership; transport: LivekitTransport }[] -// >; - const livekitFocus: LivekitTransport = { livekit_alias: "!roomID:example.org", livekit_service_url: "https://matrix-rtc.example.org/livekit/jwt", @@ -91,22 +86,25 @@ function setupTest(): void { localParticipantEventEmiter, ), } as unknown as LocalParticipant); - fakeRoomEventEmiter = new EventEmitter(); + const fakeRoomEventEmitter = new EventEmitter(); fakeLivekitRoom = vi.mocked({ connect: vi.fn(), disconnect: vi.fn(), remoteParticipants: new Map(), localParticipant: fakeLocalParticipant, state: LivekitConnectionState.Disconnected, - on: fakeRoomEventEmiter.on.bind(fakeRoomEventEmiter), - off: fakeRoomEventEmiter.off.bind(fakeRoomEventEmiter), - addListener: fakeRoomEventEmiter.addListener.bind(fakeRoomEventEmiter), + on: fakeRoomEventEmitter.on.bind(fakeRoomEventEmitter), + off: fakeRoomEventEmitter.off.bind(fakeRoomEventEmitter), + addListener: fakeRoomEventEmitter.addListener.bind(fakeRoomEventEmitter), removeListener: - fakeRoomEventEmiter.removeListener.bind(fakeRoomEventEmiter), + fakeRoomEventEmitter.removeListener.bind(fakeRoomEventEmitter), removeAllListeners: - fakeRoomEventEmiter.removeAllListeners.bind(fakeRoomEventEmiter), + fakeRoomEventEmitter.removeAllListeners.bind(fakeRoomEventEmitter), setE2EEEnabled: vi.fn().mockResolvedValue(undefined), + emit: (eventName: string | symbol, ...args: unknown[]) => { + fakeRoomEventEmitter.emit(eventName, ...args); + }, } as unknown as LivekitRoom); } @@ -129,7 +127,13 @@ function setupRemoteConnection(): Connection { }); fakeLivekitRoom.connect.mockImplementation(async (): Promise => { + const changeEv = RoomEvent.ConnectionStateChanged; + + fakeLivekitRoom.state = LivekitConnectionState.Connecting; + fakeLivekitRoom.emit(changeEv, fakeLivekitRoom.state); fakeLivekitRoom.state = LivekitConnectionState.Connected; + fakeLivekitRoom.emit(changeEv, fakeLivekitRoom.state); + return Promise.resolve(); }); @@ -350,8 +354,10 @@ describe("Start connection states", () => { expect(initialState).toEqual(ConnectionState.Initialized); const fetchingState = capturedStates.shift(); expect(fetchingState).toEqual(ConnectionState.FetchingConfig); + const disconnectedState = capturedStates.shift(); + expect(disconnectedState).toEqual(ConnectionState.LivekitDisconnected); const connectingState = capturedStates.shift(); - expect(connectingState).toEqual(ConnectionState.ConnectingToLkRoom); + expect(connectingState).toEqual(ConnectionState.LivekitConnecting); const connectedState = capturedStates.shift(); expect(connectedState).toEqual(ConnectionState.LivekitConnected); }); @@ -419,7 +425,7 @@ describe("Publishing participants observations", () => { ); participants.forEach((p) => - fakeRoomEventEmiter.emit(RoomEvent.ParticipantConnected, p), + fakeLivekitRoom.emit(RoomEvent.ParticipantConnected, p), ); // At this point there should be no publishers @@ -432,7 +438,7 @@ describe("Publishing participants observations", () => { fakeRemoteLivekitParticipant("@dan:example.org:DEV333", 2), ]; participants.forEach((p) => - fakeRoomEventEmiter.emit(RoomEvent.ParticipantConnected, p), + fakeLivekitRoom.emit(RoomEvent.ParticipantConnected, p), ); // At this point there should be no publishers @@ -462,7 +468,7 @@ describe("Publishing participants observations", () => { ); for (const participant of participants) { - fakeRoomEventEmiter.emit(RoomEvent.ParticipantConnected, participant); + fakeLivekitRoom.emit(RoomEvent.ParticipantConnected, participant); } // At this point there should be no publishers @@ -471,7 +477,7 @@ describe("Publishing participants observations", () => { participants = [fakeRemoteLivekitParticipant("@bob:example.org:DEV111", 1)]; for (const participant of participants) { - fakeRoomEventEmiter.emit(RoomEvent.ParticipantConnected, participant); + fakeLivekitRoom.emit(RoomEvent.ParticipantConnected, participant); } // We should have bob has a publisher now @@ -488,7 +494,7 @@ describe("Publishing participants observations", () => { (p) => p.identity !== "@bob:example.org:DEV111", ); - fakeRoomEventEmiter.emit( + fakeLivekitRoom.emit( RoomEvent.ParticipantDisconnected, fakeRemoteLivekitParticipant("@bob:example.org:DEV111"), ); diff --git a/src/state/CallViewModel/remoteMembers/Connection.ts b/src/state/CallViewModel/remoteMembers/Connection.ts index 6015bf01f..8f8c0924c 100644 --- a/src/state/CallViewModel/remoteMembers/Connection.ts +++ b/src/state/CallViewModel/remoteMembers/Connection.ts @@ -18,7 +18,7 @@ import { RoomEvent, } from "livekit-client"; import { type LivekitTransport } from "matrix-js-sdk/lib/matrixrtc"; -import { BehaviorSubject, map } from "rxjs"; +import { BehaviorSubject, map, skip, skipWhile } from "rxjs"; import { type Logger } from "matrix-js-sdk/lib/logger"; import { @@ -61,7 +61,6 @@ export enum ConnectionState { /** `start` has been called on the connection. It aquires the jwt info to conenct to the LK Room */ FetchingConfig = "FetchingConfig", Stopped = "Stopped", - ConnectingToLkRoom = "ConnectingToLkRoom", /** The same as ConnectionState.Disconnected from `livekit-client` */ LivekitDisconnected = "disconnected", /** The same as ConnectionState.Connecting from `livekit-client` */ @@ -139,7 +138,17 @@ export class Connection { // If we were stopped while fetching the config, don't proceed to connect if (this.stopped) return; - this._state$.next(ConnectionState.ConnectingToLkRoom); + // Setup observer once we are done with getSFUConfigWithOpenID + connectionStateObserver(this.livekitRoom) + .pipe( + this.scope.bind(), + map((s) => s as unknown as ConnectionState), + ) + .subscribe((lkState) => { + // It is save to cast lkState to ConnectionState as they are fully overlapping. + this._state$.next(lkState); + }); + try { await this.livekitRoom.connect(url, jwt); } catch (e) { @@ -167,13 +176,6 @@ export class Connection { } // If we were stopped while connecting, don't proceed to update state. if (this.stopped) return; - - connectionStateObserver(this.livekitRoom) - .pipe(this.scope.bind()) - .subscribe((lkState) => { - // It is save to cast lkState to ConnectionState as they are fully overlapping. - this._state$.next(lkState as unknown as ConnectionState); - }); } catch (error) { this.logger.debug(`Failed to connect to LiveKit room: ${error}`); this._state$.next( From 9a7e797af48da255682e6db017dafd0e9a4624f0 Mon Sep 17 00:00:00 2001 From: Timo K Date: Thu, 11 Dec 2025 16:17:45 +0100 Subject: [PATCH 088/748] fix lint --- src/state/CallViewModel/remoteMembers/Connection.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/state/CallViewModel/remoteMembers/Connection.ts b/src/state/CallViewModel/remoteMembers/Connection.ts index 8f8c0924c..8b4479e82 100644 --- a/src/state/CallViewModel/remoteMembers/Connection.ts +++ b/src/state/CallViewModel/remoteMembers/Connection.ts @@ -18,7 +18,7 @@ import { RoomEvent, } from "livekit-client"; import { type LivekitTransport } from "matrix-js-sdk/lib/matrixrtc"; -import { BehaviorSubject, map, skip, skipWhile } from "rxjs"; +import { BehaviorSubject, map } from "rxjs"; import { type Logger } from "matrix-js-sdk/lib/logger"; import { From 207b161b3ba25a7eae243a741c0fb7c3dfaf8eb9 Mon Sep 17 00:00:00 2001 From: Timo K Date: Thu, 11 Dec 2025 17:17:56 +0100 Subject: [PATCH 089/748] fix logger and dismiss button presses --- playwright/fixtures/widget-user.ts | 10 +++++++++- src/room/GroupCallView.tsx | 1 - src/room/InCallView.tsx | 4 +++- 3 files changed, 12 insertions(+), 3 deletions(-) diff --git a/playwright/fixtures/widget-user.ts b/playwright/fixtures/widget-user.ts index b0c46788a..51dffbc69 100644 --- a/playwright/fixtures/widget-user.ts +++ b/playwright/fixtures/widget-user.ts @@ -126,8 +126,16 @@ async function registerUser( page.getByRole("heading", { name: `Welcome ${username}` }), ).toBeVisible(); + await page.pause(); + const browserUnsupportedToast = page + .getByText("Element does not support this browser") + .locator("..") + .locator(".."); + // Dismiss incompatible browser toast - const dismissButton = page.getByRole("button", { name: "Dismiss" }); + const dismissButton = browserUnsupportedToast.getByRole("button", { + name: "Dismiss", + }); try { await expect(dismissButton).toBeVisible({ timeout: 700 }); await dismissButton.click(); diff --git a/src/room/GroupCallView.tsx b/src/room/GroupCallView.tsx index 1542678e8..dfd11ff32 100644 --- a/src/room/GroupCallView.tsx +++ b/src/room/GroupCallView.tsx @@ -446,7 +446,6 @@ export const GroupCallView: FC = ({ let body: ReactNode; if (externalError) { - logger.debug("External error occurred:", externalError); // If an error was recorded within this component but outside // GroupCallErrorBoundary, create a component that rethrows the error from // within the error boundary, so it can be handled uniformly diff --git a/src/room/InCallView.tsx b/src/room/InCallView.tsx index 18acf843e..add8154af 100644 --- a/src/room/InCallView.tsx +++ b/src/room/InCallView.tsx @@ -24,7 +24,7 @@ import { type MatrixRTCSession } from "matrix-js-sdk/lib/matrixrtc"; import classNames from "classnames"; import { BehaviorSubject, map } from "rxjs"; import { useObservable } from "observable-hooks"; -import { logger } from "matrix-js-sdk/lib/logger"; +import { logger as rootLogger } from "matrix-js-sdk/lib/logger"; import { VoiceCallSolidIcon, VolumeOnSolidIcon, @@ -109,6 +109,8 @@ import { useTrackProcessorObservable$ } from "../livekit/TrackProcessorContext.t import { type Layout } from "../state/layout-types.ts"; import { ObservableScope } from "../state/ObservableScope.ts"; +const logger = rootLogger.getChild("[InCallView]"); + const maxTapDurationMs = 400; export interface ActiveCallProps From 8225e4f2608a10e0662e5004df2ecddef1bea0b8 Mon Sep 17 00:00:00 2001 From: Timo K Date: Thu, 11 Dec 2025 17:22:02 +0100 Subject: [PATCH 090/748] remove page.pause --- playwright/fixtures/widget-user.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/playwright/fixtures/widget-user.ts b/playwright/fixtures/widget-user.ts index 51dffbc69..efff8a804 100644 --- a/playwright/fixtures/widget-user.ts +++ b/playwright/fixtures/widget-user.ts @@ -126,7 +126,6 @@ async function registerUser( page.getByRole("heading", { name: `Welcome ${username}` }), ).toBeVisible(); - await page.pause(); const browserUnsupportedToast = page .getByText("Element does not support this browser") .locator("..") From 7edc97b9175dddd27ee3f90acb48de5de13fb3f4 Mon Sep 17 00:00:00 2001 From: Timo K Date: Thu, 11 Dec 2025 17:24:35 +0100 Subject: [PATCH 091/748] remove continue button things --- playwright/fixtures/widget-user.ts | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/playwright/fixtures/widget-user.ts b/playwright/fixtures/widget-user.ts index efff8a804..6236928c3 100644 --- a/playwright/fixtures/widget-user.ts +++ b/playwright/fixtures/widget-user.ts @@ -111,17 +111,7 @@ async function registerUser( await page.getByRole("textbox", { name: "Confirm password" }).click(); await page.getByRole("textbox", { name: "Confirm password" }).fill(PASSWORD); await page.getByRole("button", { name: "Register" }).click(); - const continueButton = page.getByRole("button", { name: "Continue" }); - try { - await expect(continueButton).toBeVisible({ timeout: 700 }); - // why do we need to put in the passwor if there is a continue button? - await page - .getByRole("textbox", { name: "Password", exact: true }) - .fill(PASSWORD); - await continueButton.click(); - } catch { - // continueButton not visible, continue as normal - } + await expect( page.getByRole("heading", { name: `Welcome ${username}` }), ).toBeVisible(); From df2f503a05d4e9f45cb7a2e01204cb83c7a2396b Mon Sep 17 00:00:00 2001 From: Timo K Date: Thu, 11 Dec 2025 18:00:23 +0100 Subject: [PATCH 092/748] review --- src/settings/DeveloperSettingsTab.test.tsx | 1 + src/settings/DeveloperSettingsTab.tsx | 26 ++++++++-------------- src/settings/SettingsModal.tsx | 1 + 3 files changed, 11 insertions(+), 17 deletions(-) diff --git a/src/settings/DeveloperSettingsTab.test.tsx b/src/settings/DeveloperSettingsTab.test.tsx index c18cf23bb..7bdf7091d 100644 --- a/src/settings/DeveloperSettingsTab.test.tsx +++ b/src/settings/DeveloperSettingsTab.test.tsx @@ -79,6 +79,7 @@ describe("DeveloperSettingsTab", () => { const { container } = render( , diff --git a/src/settings/DeveloperSettingsTab.tsx b/src/settings/DeveloperSettingsTab.tsx index 7f90c4c16..d16e3ef7f 100644 --- a/src/settings/DeveloperSettingsTab.tsx +++ b/src/settings/DeveloperSettingsTab.tsx @@ -22,13 +22,13 @@ import { import { logger } from "matrix-js-sdk/lib/logger"; import { EditInPlace, + ErrorMessage, Root as Form, Heading, HelpMessage, InlineField, Label, RadioControl, - Text, } from "@vector-im/compound-web"; import { FieldRow, InputField } from "../input/Input"; @@ -50,6 +50,7 @@ import { getSFUConfigWithOpenID } from "../livekit/openIDSFU"; interface Props { client: MatrixClient; + roomId: string; livekitRooms?: { room: LivekitRoom; url: string; isLocal?: boolean }[]; env: ImportMetaEnv; } @@ -57,6 +58,7 @@ interface Props { export const DeveloperSettingsTab: FC = ({ client, livekitRooms, + roomId, env, }) => { const { t } = useTranslation(); @@ -221,7 +223,6 @@ export const DeveloperSettingsTab: FC = ({ />{" "} e.preventDefault()} helpLabel={ customLivekitUrl === null @@ -240,30 +241,22 @@ export const DeveloperSettingsTab: FC = ({ customLivekitUrlTextBuffer === null ) { setCustomLivekitUrl(null); - return Promise.resolve(); + return; } try { - logger.debug("try setting"); await getSFUConfigWithOpenID( client, customLivekitUrlTextBuffer, - "Test-room-alias-" + Date.now().toString() + client.getUserId(), + roomId, ); - logger.debug("done setting! Success"); setCustomLivekitUrlUpdateError(null); setCustomLivekitUrl(customLivekitUrlTextBuffer); - } catch (e) { - logger.error("failed setting", e); + } catch { setCustomLivekitUrlUpdateError("invalid URL (did not update)"); - // automatically unset the error after 4 seconds (2 seconds will be for the save label) - setTimeout(() => { - logger.debug("unsetting error"); - setCustomLivekitUrlUpdateError(null); - }, 2000); } }, - [customLivekitUrlTextBuffer, setCustomLivekitUrl, client], + [customLivekitUrlTextBuffer, setCustomLivekitUrl, client, roomId], )} value={customLivekitUrlTextBuffer ?? ""} onChange={useCallback( @@ -278,11 +271,10 @@ export const DeveloperSettingsTab: FC = ({ }, [setCustomLivekitUrl], )} + serverInvalid={customLivekitUrlUpdateError !== null} > {customLivekitUrlUpdateError !== null && ( - - {customLivekitUrlUpdateError} - + {customLivekitUrlUpdateError} )} diff --git a/src/settings/SettingsModal.tsx b/src/settings/SettingsModal.tsx index 2b4078aa5..30ac36185 100644 --- a/src/settings/SettingsModal.tsx +++ b/src/settings/SettingsModal.tsx @@ -213,6 +213,7 @@ export const SettingsModal: FC = ({ env={import.meta.env} client={client} livekitRooms={livekitRooms} + roomId={roomId} /> ), }; From f8310b46112c1207fb05a36c987014dd630c9119 Mon Sep 17 00:00:00 2001 From: Valere Date: Fri, 12 Dec 2025 10:31:08 +0100 Subject: [PATCH 093/748] publisher: only use highlevel participant APIs --- .../localMember/LocalMembership.test.ts | 37 +- .../localMember/LocalMembership.ts | 115 +++-- .../localMember/Publisher.test.ts | 426 +++++++++++++----- .../CallViewModel/localMember/Publisher.ts | 324 +++++++------ src/utils/test.ts | 2 + 5 files changed, 608 insertions(+), 296 deletions(-) diff --git a/src/state/CallViewModel/localMember/LocalMembership.test.ts b/src/state/CallViewModel/localMember/LocalMembership.test.ts index cff5c06dc..247e8ed10 100644 --- a/src/state/CallViewModel/localMember/LocalMembership.test.ts +++ b/src/state/CallViewModel/localMember/LocalMembership.test.ts @@ -271,6 +271,7 @@ describe("LocalMembership", () => { state: "ConnectedToLkRoom", }), transport: bTransport, + livekitRoom: mockLivekitRoom({}), } as unknown as Connection, [], ); @@ -281,13 +282,17 @@ describe("LocalMembership", () => { const localTransport$ = new BehaviorSubject(aTransport); const publishers: Publisher[] = []; - + let seed = 0; defaultCreateLocalMemberValues.createPublisherFactory.mockImplementation( () => { + const a = seed; + seed += 1; + logger.info(`creating [${a}]`); const p = { - stopPublishing: vi.fn(), + stopPublishing: vi.fn().mockImplementation(() => { + logger.info(`stopPublishing [${a}]`); + }), stopTracks: vi.fn(), - publishing$: constant(false), }; publishers.push(p as unknown as Publisher); return p; @@ -322,7 +327,7 @@ describe("LocalMembership", () => { await flushPromises(); // stop all tracks after ending scopes expect(publishers[1].stopPublishing).toHaveBeenCalled(); - expect(publishers[1].stopTracks).toHaveBeenCalled(); + // expect(publishers[1].stopTracks).toHaveBeenCalled(); defaultCreateLocalMemberValues.createPublisherFactory.mockReset(); }); @@ -367,15 +372,17 @@ describe("LocalMembership", () => { }); await flushPromises(); expect(publisherFactory).toHaveBeenCalledOnce(); - expect(localMembership.tracks$.value.length).toBe(0); + // expect(localMembership.tracks$.value.length).toBe(0); + expect(publishers[0].createAndSetupTracks).not.toHaveBeenCalled(); localMembership.startTracks(); await flushPromises(); - expect(localMembership.tracks$.value.length).toBe(2); + expect(publishers[0].createAndSetupTracks).toHaveBeenCalled(); + // expect(localMembership.tracks$.value.length).toBe(2); scope.end(); await flushPromises(); // stop all tracks after ending scopes expect(publishers[0].stopPublishing).toHaveBeenCalled(); - expect(publishers[0].stopTracks).toHaveBeenCalled(); + // expect(publishers[0].stopTracks).toHaveBeenCalled(); publisherFactory.mockClear(); }); // TODO add an integration test combining publisher and localMembership @@ -446,16 +453,16 @@ describe("LocalMembership", () => { state: RTCBackendState.Initialized, }); expect(publisherFactory).toHaveBeenCalledOnce(); - expect(localMembership.tracks$.value.length).toBe(0); + // expect(localMembership.tracks$.value.length).toBe(0); // ------- localMembership.startTracks(); // ------- await flushPromises(); - expect(localMembership.connectionState.livekit$.value).toStrictEqual({ - state: RTCBackendState.CreatingTracks, - }); + // expect(localMembership.connectionState.livekit$.value).toStrictEqual({ + // state: RTCBackendState.CreatingTracks, + // }); createTrackResolver.resolve(); await flushPromises(); expect(localMembership.connectionState.livekit$.value).toStrictEqual({ @@ -466,9 +473,9 @@ describe("LocalMembership", () => { localMembership.requestConnect(); // ------- - expect(localMembership.connectionState.livekit$.value).toStrictEqual({ - state: RTCBackendState.WaitingToPublish, - }); + // expect(localMembership.connectionState.livekit$.value).toStrictEqual({ + // state: RTCBackendState.WaitingToPublish, + // }); publishResolver.resolve(); await flushPromises(); @@ -486,7 +493,7 @@ describe("LocalMembership", () => { }); // stop all tracks after ending scopes expect(publishers[0].stopPublishing).toHaveBeenCalled(); - expect(publishers[0].stopTracks).toHaveBeenCalled(); + // expect(publishers[0].stopTracks).toHaveBeenCalled(); }); // TODO add tests for matrix local matrix participation. }); diff --git a/src/state/CallViewModel/localMember/LocalMembership.ts b/src/state/CallViewModel/localMember/LocalMembership.ts index 60ae79b8e..de36a098e 100644 --- a/src/state/CallViewModel/localMember/LocalMembership.ts +++ b/src/state/CallViewModel/localMember/LocalMembership.ts @@ -6,12 +6,13 @@ Please see LICENSE in the repository root for full details. */ import { - type LocalTrack, type Participant, ParticipantEvent, type LocalParticipant, type ScreenShareCaptureOptions, ConnectionState, + RoomEvent, + MediaDeviceFailure, } from "livekit-client"; import { observeParticipantEvents } from "@livekit/components-core"; import { @@ -24,6 +25,7 @@ import { combineLatest, distinctUntilChanged, from, + fromEvent, map, type Observable, of, @@ -61,9 +63,9 @@ export enum RTCBackendState { WaitingForConnection = "waiting_for_connection", /** Connection and transport arrived, publisher Initialized */ Initialized = "Initialized", - CreatingTracks = "creating_tracks", + // CreatingTracks = "creating_tracks", ReadyToPublish = "ready_to_publish", - WaitingToPublish = "waiting_to_publish", + // WaitingToPublish = "waiting_to_publish", Connected = "connected", Disconnected = "disconnected", Disconnecting = "disconnecting", @@ -74,9 +76,9 @@ type LocalMemberRtcBackendState = | { state: RTCBackendState.WaitingForTransport } | { state: RTCBackendState.WaitingForConnection } | { state: RTCBackendState.Initialized } - | { state: RTCBackendState.CreatingTracks } + // | { state: RTCBackendState.CreatingTracks } | { state: RTCBackendState.ReadyToPublish } - | { state: RTCBackendState.WaitingToPublish } + // | { state: RTCBackendState.WaitingToPublish } | { state: RTCBackendState.Connected } | { state: RTCBackendState.Disconnected } | { state: RTCBackendState.Disconnecting }; @@ -159,7 +161,7 @@ export const createLocalMembership$ = ({ /** * This starts audio and video tracks. They will be reused when calling `requestConnect`. */ - startTracks: () => Behavior; + startTracks: () => Behavior; /** * This sets a inner state (shouldConnect) to true and instructs the js-sdk and livekit to keep the user * connected to matrix and livekit. @@ -172,7 +174,7 @@ export const createLocalMembership$ = ({ * Callback to toggle screen sharing. If null, screen sharing is not possible. */ toggleScreenSharing: (() => void) | null; - tracks$: Behavior; + // tracks$: Behavior; participant$: Behavior; connection$: Behavior; homeserverConnected$: Behavior; @@ -224,6 +226,33 @@ export const createLocalMembership$ = ({ ), ); + // Tracks error that happen when creating the local tracks. + const mediaErrors$ = localConnection$.pipe( + switchMap((connection) => { + if (!connection) { + return of(null); + } else { + return fromEvent( + connection.livekitRoom, + RoomEvent.MediaDevicesError, + (error: Error) => { + return MediaDeviceFailure.getFailure(error) ?? null; + }, + ); + } + }), + ); + + mediaErrors$.pipe(scope.bind()).subscribe((error) => { + if (error) { + logger.error(`Failed to create local tracks:`, error); + // TODO is it fatal? Do we need to create a new Specialized Error? + setMatrixError( + new UnknownCallError(new Error(`Media device error: ${error}`)), + ); + } + }); + const localConnectionState$ = localConnection$.pipe( switchMap((connection) => (connection ? connection.state$ : of(null))), ); @@ -293,16 +322,16 @@ export const createLocalMembership$ = ({ /** * Extract the tracks from the published. Also reacts to changing publishers. */ - const tracks$ = scope.behavior( - publisher$.pipe(switchMap((p) => (p?.tracks$ ? p.tracks$ : constant([])))), - ); - const publishing$ = scope.behavior( - publisher$.pipe(switchMap((p) => p?.publishing$ ?? constant(false))), - ); + // const tracks$ = scope.behavior( + // publisher$.pipe(switchMap((p) => (p?.tracks$ ? p.tracks$ : constant([])))), + // ); + // const publishing$ = scope.behavior( + // publisher$.pipe(switchMap((p) => p?.publishing$ ?? constant(false))), + // ); - const startTracks = (): Behavior => { + const startTracks = (): Behavior => { trackStartRequested.resolve(); - return tracks$; + return constant(undefined); }; const requestConnect = (): void => { @@ -327,7 +356,7 @@ export const createLocalMembership$ = ({ } return Promise.resolve(async (): Promise => { await publisher$?.value?.stopPublishing(); - publisher$?.value?.stopTracks(); + await publisher$?.value?.stopTracks(); }); }); @@ -335,13 +364,16 @@ export const createLocalMembership$ = ({ // `tracks$` will update once they are ready. scope.reconcile( scope.behavior( - combineLatest([publisher$, tracks$, from(trackStartRequested.promise)]), + combineLatest([ + publisher$ /*, tracks$*/, + from(trackStartRequested.promise), + ]), null, ), async (valueIfReady) => { if (!valueIfReady) return; - const [publisher, tracks] = valueIfReady; - if (publisher && tracks.length === 0) { + const [publisher] = valueIfReady; + if (publisher) { await publisher.createAndSetupTracks().catch((e) => logger.error(e)); } }, @@ -349,22 +381,23 @@ export const createLocalMembership$ = ({ // Based on `connectRequested$` we start publishing tracks. (once they are there!) scope.reconcile( - scope.behavior(combineLatest([publisher$, tracks$, connectRequested$])), - async ([publisher, tracks, shouldConnect]) => { - if (shouldConnect === publisher?.publishing$.value) return; - if (tracks.length !== 0 && shouldConnect) { + scope.behavior(combineLatest([publisher$, connectRequested$])), + async ([publisher, shouldConnect]) => { + if (shouldConnect) { try { await publisher?.startPublishing(); } catch (error) { setLivekitError(error as ElementCallError); } - } else if (tracks.length !== 0 && !shouldConnect) { - try { - await publisher?.stopPublishing(); - } catch (error) { - setLivekitError(new UnknownCallError(error as Error)); - } } + // XXX Why is that? + // else { + // try { + // await publisher?.stopPublishing(); + // } catch (error) { + // setLivekitError(new UnknownCallError(error as Error)); + // } + // } }, ); @@ -378,12 +411,12 @@ export const createLocalMembership$ = ({ combineLatest([ publisher$, localTransport$, - tracks$.pipe( - tap((t) => { - logger.info("tracks$: ", t); - }), - ), - publishing$, + // tracks$.pipe( + // tap((t) => { + // logger.info("tracks$: ", t); + // }), + // ), + // publishing$, connectRequested$, from(trackStartRequested.promise).pipe( map(() => true), @@ -395,8 +428,8 @@ export const createLocalMembership$ = ({ ([ publisher, localTransport, - tracks, - publishing, + // tracks, + // publishing, shouldConnect, shouldStartTracks, error, @@ -408,15 +441,15 @@ export const createLocalMembership$ = ({ // as: // We do have but not yet so we are in if (error !== null) return { state: RTCBackendState.Error, error }; - const hasTracks = tracks.length > 0; + // const hasTracks = tracks.length > 0; if (!localTransport) return { state: RTCBackendState.WaitingForTransport }; if (!publisher) return { state: RTCBackendState.WaitingForConnection }; if (!shouldStartTracks) return { state: RTCBackendState.Initialized }; - if (!hasTracks) return { state: RTCBackendState.CreatingTracks }; + // if (!hasTracks) return { state: RTCBackendState.CreatingTracks }; if (!shouldConnect) return { state: RTCBackendState.ReadyToPublish }; - if (!publishing) return { state: RTCBackendState.WaitingToPublish }; + // if (!publishing) return { state: RTCBackendState.WaitingToPublish }; return { state: RTCBackendState.Connected }; }, ), @@ -588,7 +621,7 @@ export const createLocalMembership$ = ({ livekit$: livekitState$, matrix$: matrixState$, }, - tracks$, + // tracks$, participant$, homeserverConnected$, reconnecting$, diff --git a/src/state/CallViewModel/localMember/Publisher.test.ts b/src/state/CallViewModel/localMember/Publisher.test.ts index 9b3e5b2a7..3ab3d48c0 100644 --- a/src/state/CallViewModel/localMember/Publisher.test.ts +++ b/src/state/CallViewModel/localMember/Publisher.test.ts @@ -5,66 +5,320 @@ SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial Please see LICENSE in the repository root for full details. */ +import { afterEach, beforeEach, describe, expect, it, test, vi } from "vitest"; import { - afterEach, - beforeEach, - describe, - expect, - it, - type Mock, - vi, -} from "vitest"; -import { ConnectionState as LivekitConenctionState } from "livekit-client"; -import { type BehaviorSubject } from "rxjs"; + ConnectionState as LivekitConnectionState, + LocalParticipant, + type LocalTrack, + type LocalTrackPublication, + ParticipantEvent, + Track, +} from "livekit-client"; +import { BehaviorSubject } from "rxjs"; import { logger } from "matrix-js-sdk/lib/logger"; import { ObservableScope } from "../../ObservableScope"; import { constant } from "../../Behavior"; import { + flushPromises, mockLivekitRoom, - mockLocalParticipant, - mockMediaDevices, + mockMediaDevices } from "../../../utils/test"; import { Publisher } from "./Publisher"; -import { - type Connection, - type ConnectionState, -} from "../remoteMembers/Connection"; +import { type Connection } from "../remoteMembers/Connection"; import { type MuteStates } from "../../MuteStates"; -import { FailToStartLivekitConnection } from "../../../utils/errors"; -describe("Publisher", () => { - let scope: ObservableScope; - let connection: Connection; - let muteStates: MuteStates; - beforeEach(() => { - muteStates = { - audio: { - enabled$: constant(false), - unsetHandler: vi.fn(), - setHandler: vi.fn(), - }, - video: { - enabled$: constant(false), - unsetHandler: vi.fn(), - setHandler: vi.fn(), - }, - } as unknown as MuteStates; - scope = new ObservableScope(); - connection = { - state$: constant({ - state: "ConnectedToLkRoom", - livekitConnectionState$: constant(LivekitConenctionState.Connected), - }), - livekitRoom: mockLivekitRoom({ - localParticipant: mockLocalParticipant({}), - }), - } as unknown as Connection; +let scope: ObservableScope; + +beforeEach(() => { + scope = new ObservableScope(); +}); + +// afterEach(() => scope.end()); + +function createMockLocalTrack(source: Track.Source): LocalTrack { + const track = { + source, + isMuted: false, + isUpstreamPaused: false, + } as Partial as LocalTrack; + + vi.mocked(track).mute = vi.fn().mockImplementation(() => { + track.isMuted = true; + }); + vi.mocked(track).unmute = vi.fn().mockImplementation(() => { + track.isMuted = false; + }); + vi.mocked(track).pauseUpstream = vi.fn().mockImplementation(() => { + // @ts-expect-error - for that test we want to set isUpstreamPaused directly + track.isUpstreamPaused = true; + }); + vi.mocked(track).resumeUpstream = vi.fn().mockImplementation(() => { + // @ts-expect-error - for that test we want to set isUpstreamPaused directly + track.isUpstreamPaused = false; }); - afterEach(() => scope.end()); + return track; +} - it("throws if livekit room could not publish", async () => { +function createMockMuteState(enabled$: BehaviorSubject): { + enabled$: BehaviorSubject; + setHandler: (h: (enabled: boolean) => void) => void; + unsetHandler: () => void; +} { + let currentHandler = (enabled: boolean): void => {}; + + const ms = { + enabled$, + setHandler: vi.fn().mockImplementation((h: (enabled: boolean) => void) => { + currentHandler = h; + }), + unsetHandler: vi.fn().mockImplementation(() => { + currentHandler = (enabled: boolean): void => {}; + }), + }; + // forward enabled$ emissions to the current handler + enabled$.subscribe((enabled) => { + logger.info(`MockMuteState: enabled changed to ${enabled}`); + currentHandler(enabled); + }); + + return ms; +} + +let connection: Connection; +let muteStates: MuteStates; +let localParticipant: LocalParticipant; +let audioEnabled$: BehaviorSubject; +let videoEnabled$: BehaviorSubject; +let trackPublications: LocalTrackPublication[]; +// use it to control when track creation resolves, default to resolved +let createTrackLock: Promise; + +beforeEach(() => { + trackPublications = []; + audioEnabled$ = new BehaviorSubject(false); + videoEnabled$ = new BehaviorSubject(false); + createTrackLock = Promise.resolve(); + + muteStates = { + audio: createMockMuteState(audioEnabled$), + video: createMockMuteState(videoEnabled$), + } as unknown as MuteStates; + + const mockSendDataPacket = vi.fn(); + const mockEngine = { + client: { + sendUpdateLocalMetadata: vi.fn(), + }, + on: vi.fn().mockReturnThis(), + sendDataPacket: mockSendDataPacket, + }; + + localParticipant = new LocalParticipant( + "local-sid", + "local-identity", + // @ts-expect-error - for that test we want a real LocalParticipant to have the pending publications logic + mockEngine, + { + adaptiveStream: true, + dynacase: false, + audioCaptureDefaults: {}, + videoCaptureDefaults: {}, + stopLocalTrackOnUnpublish: true, + reconnectPolicy: "always", + disconnectOnPageLeave: true, + }, + new Map(), + {}, + ); + + vi.mocked(localParticipant).createTracks = vi + .fn() + .mockImplementation(async (opts) => { + const tracks: LocalTrack[] = []; + if (opts.audio) { + tracks.push(createMockLocalTrack(Track.Source.Microphone)); + } + if (opts.video) { + tracks.push(createMockLocalTrack(Track.Source.Camera)); + } + await createTrackLock; + return tracks; + }); + + vi.mocked(localParticipant).publishTrack = vi + .fn() + .mockImplementation(async (track: LocalTrack) => { + const pub = { + track, + source: track.source, + mute: track.mute, + unmute: track.unmute, + } as Partial as LocalTrackPublication; + trackPublications.push(pub); + localParticipant.emit(ParticipantEvent.LocalTrackPublished, pub); + return Promise.resolve(pub); + }); + + vi.mocked(localParticipant).getTrackPublication = vi + .fn() + .mockImplementation((source: Track.Source) => { + return trackPublications.find((pub) => pub.track?.source === source); + }); + + connection = { + state$: constant({ + state: "ConnectedToLkRoom", + livekitConnectionState$: constant(LivekitConnectionState.Connected), + }), + livekitRoom: mockLivekitRoom({ + localParticipant: localParticipant, + }), + } as unknown as Connection; +}); + +describe("Publisher", () => { + let publisher: Publisher; + + beforeEach(() => { + publisher = new Publisher( + scope, + connection, + mockMediaDevices({}), + muteStates, + constant({ supported: false, processor: undefined }), + logger, + ); + }); + + afterEach(() => {}); + + it("Should not create tracks if started muted to avoid unneeded permission requests", async () => { + const createTracksSpy = vi.spyOn( + connection.livekitRoom.localParticipant, + "createTracks", + ); + + audioEnabled$.next(false); + videoEnabled$.next(false); + await publisher.createAndSetupTracks(); + + expect(createTracksSpy).not.toHaveBeenCalled(); + }); + + it("Should minimize permission request by querying create at once", async () => { + const enableCameraAndMicrophoneSpy = vi.spyOn( + localParticipant, + "enableCameraAndMicrophone", + ); + const createTracksSpy = vi.spyOn(localParticipant, "createTracks"); + + audioEnabled$.next(true); + videoEnabled$.next(true); + await publisher.createAndSetupTracks(); + await flushPromises(); + + expect(enableCameraAndMicrophoneSpy).toHaveBeenCalled(); + + // It should create both at once + expect(createTracksSpy).toHaveBeenCalledWith({ + audio: true, + video: true, + }); + }); + + it("Ensure no data is streamed until publish has been called", async () => { + audioEnabled$.next(true); + await publisher.createAndSetupTracks(); + + // The track should be created and paused + expect(localParticipant.createTracks).toHaveBeenCalledWith({ + audio: true, + video: undefined, + }); + await flushPromises(); + expect(localParticipant.publishTrack).toHaveBeenCalled(); + + await flushPromises(); + const track = localParticipant.getTrackPublication( + Track.Source.Microphone, + )?.track; + expect(track).toBeDefined(); + expect(track!.pauseUpstream).toHaveBeenCalled(); + expect(track!.isUpstreamPaused).toBe(true); + }); + + it("Ensure resume upstream when published is called", async () => { + videoEnabled$.next(true); + await publisher.createAndSetupTracks(); + // await flushPromises(); + await publisher.startPublishing(); + + const track = localParticipant.getTrackPublication( + Track.Source.Camera, + )?.track; + expect(track).toBeDefined(); + // expect(track.pauseUpstream).toHaveBeenCalled(); + expect(track!.isUpstreamPaused).toBe(false); + }); + + describe("Mute states", () => { + let publisher: Publisher; + beforeEach(() => { + publisher = new Publisher( + scope, + connection, + mockMediaDevices({}), + muteStates, + constant({ supported: false, processor: undefined }), + logger, + ); + }); + + test.each([ + { mutes: { audioEnabled: true, videoEnabled: false } }, + { mutes: { audioEnabled: true, videoEnabled: false } }, + ])("only create the tracks that are unmuted $mutes", async ({ mutes }) => { + // Ensure all muted + audioEnabled$.next(mutes.audioEnabled); + videoEnabled$.next(mutes.videoEnabled); + + vi.mocked(connection.livekitRoom.localParticipant).createTracks = vi + .fn() + .mockResolvedValue([]); + + await publisher.createAndSetupTracks(); + + expect( + connection.livekitRoom.localParticipant.createTracks, + ).toHaveBeenCalledOnce(); + + expect( + connection.livekitRoom.localParticipant.createTracks, + ).toHaveBeenCalledWith({ + audio: mutes.audioEnabled ? true : undefined, + video: mutes.videoEnabled ? true : undefined, + }); + }); + }); + + it("does mute unmute audio", async () => {}); +}); + +describe("Bug fix", () => { + // There is a race condition when creating and publishing tracks while the mute state changes. + // This race condition could cause tracks to be published even though they are muted at the + // beginning of a call coming from lobby. + // This is caused by our stack using manually the low level API to create and publish tracks, + // but also using the higher level setMicrophoneEnabled and setCameraEnabled functions that also create + // and publish tracks, and managing pending publications. + // Race is as follow, on creation of the Publisher we create the tracks then publish them. + // If in the middle of that process the mute state changes: + // - the `setMicrophoneEnabled` will be no-op because it is not aware of our created track and can't see any pending publication + // - If start publication is requested it will publish the track even though there was a mute request. + it("wrongly publish tracks while muted", async () => { + // setLogLevel(`debug`); const publisher = new Publisher( scope, connection, @@ -73,68 +327,34 @@ describe("Publisher", () => { constant({ supported: false, processor: undefined }), logger, ); + audioEnabled$.next(true); - // should do nothing if no tracks have been created yet. - await publisher.startPublishing(); - expect( - connection.livekitRoom.localParticipant.publishTrack, - ).not.toHaveBeenCalled(); + const resolvers = Promise.withResolvers(); + createTrackLock = resolvers.promise; - await expect(publisher.createAndSetupTracks()).rejects.toThrow( - Error("audio and video is false"), - ); - - (muteStates.audio.enabled$ as BehaviorSubject).next(true); - - ( - connection.livekitRoom.localParticipant.createTracks as Mock - ).mockResolvedValue([{}, {}]); - - await expect(publisher.createAndSetupTracks()).resolves.not.toThrow(); - expect( - connection.livekitRoom.localParticipant.createTracks, - ).toHaveBeenCalledOnce(); - - // failiour due to localParticipant.publishTrack - ( - connection.livekitRoom.localParticipant.publishTrack as Mock - ).mockRejectedValue(Error("testError")); - - await expect(publisher.startPublishing()).rejects.toThrow( - new FailToStartLivekitConnection("testError"), - ); - - // does not try other conenction after the first one failed - expect( - connection.livekitRoom.localParticipant.publishTrack, - ).toHaveBeenCalledTimes(1); - - // failiour due to connection.state$ - const beforeState = connection.state$.value; - (connection.state$ as BehaviorSubject).next({ - state: "FailedToStart", - error: Error("testStartError"), + // Initially the audio is unmuted, so creating tracks should publish the audio track + const createTracks = publisher.createAndSetupTracks(); + void publisher.startPublishing(); + void createTracks.then(() => { + void publisher.startPublishing(); }); + // now mute the audio before allowing track creation to complete + audioEnabled$.next(false); + resolvers.resolve(undefined); + await createTracks; - await expect(publisher.startPublishing()).rejects.toThrow( - new FailToStartLivekitConnection("testStartError"), - ); - (connection.state$ as BehaviorSubject).next(beforeState); + await flushPromises(); - // does not try other conenction after the first one failed - expect( - connection.livekitRoom.localParticipant.publishTrack, - ).toHaveBeenCalledTimes(1); + const track = localParticipant.getTrackPublication( + Track.Source.Microphone, + )?.track; + expect(track).toBeDefined(); - // success case - ( - connection.livekitRoom.localParticipant.publishTrack as Mock - ).mockResolvedValue({}); - - await expect(publisher.startPublishing()).resolves.not.toThrow(); - - expect( - connection.livekitRoom.localParticipant.publishTrack, - ).toHaveBeenCalledTimes(3); + try { + expect(localParticipant.publishTrack).not.toHaveBeenCalled(); + } catch { + expect(track!.mute).toHaveBeenCalled(); + expect(track!.isMuted).toBe(true); + } }); }); diff --git a/src/state/CallViewModel/localMember/Publisher.ts b/src/state/CallViewModel/localMember/Publisher.ts index 326dedafc..5da6d899a 100644 --- a/src/state/CallViewModel/localMember/Publisher.ts +++ b/src/state/CallViewModel/localMember/Publisher.ts @@ -6,15 +6,14 @@ SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial Please see LICENSE in the repository root for full details. */ import { + ConnectionState as LivekitConnectionState, + type LocalTrackPublication, LocalVideoTrack, + ParticipantEvent, type Room as LivekitRoom, Track, - type LocalTrack, - type LocalTrackPublication, - ConnectionState as LivekitConnectionState, } from "livekit-client"; import { - BehaviorSubject, map, NEVER, type Observable, @@ -34,10 +33,6 @@ import { getUrlParams } from "../../../UrlParams.ts"; import { observeTrackReference$ } from "../../MediaViewModel.ts"; import { type Connection } from "../remoteMembers/Connection.ts"; import { type ObservableScope } from "../../ObservableScope.ts"; -import { - ElementCallError, - FailToStartLivekitConnection, -} from "../../../utils/errors.ts"; /** * A wrapper for a Connection object. @@ -45,14 +40,21 @@ import { * The Publisher is also responsible for creating the media tracks. */ export class Publisher { + /** + * By default, livekit will start publishing tracks as soon as they are created. + * In the matrix RTC world, we want to control when tracks are published based + * on whether the user is part of the RTC session or not. + */ + public shouldPublish = false; + /** * Creates a new Publisher. * @param scope - The observable scope to use for managing the publisher. * @param connection - The connection to use for publishing. * @param devices - The media devices to use for audio and video input. * @param muteStates - The mute states for audio and video. - * @param e2eeLivekitOptions - The E2EE options to use for the LiveKit room. Use to share the same key provider across connections!. * @param trackerProcessorState$ - The processor state for the video track processor (e.g. background blur). + * @param logger - The logger to use for logging :D. */ public constructor( private scope: ObservableScope, @@ -62,7 +64,6 @@ export class Publisher { trackerProcessorState$: Behavior, private logger: Logger, ) { - this.logger.info("Create LiveKit room"); const { controlledAudioDevices } = getUrlParams(); const room = connection.livekitRoom; @@ -80,41 +81,54 @@ export class Publisher { this.scope.onEnd(() => { this.logger.info("Scope ended -> stop publishing all tracks"); void this.stopPublishing(); + muteStates.audio.unsetHandler(); + muteStates.video.unsetHandler(); }); - // TODO move mute state handling here using reconcile (instead of inside the mute state class) - // this.scope.reconcile( - // this.scope.behavior( - // combineLatest([this.muteStates.video.enabled$, this.tracks$]), - // ), - // async ([videoEnabled, tracks]) => { - // const track = tracks.find((t) => t.kind == Track.Kind.Video); - // if (!track) return; - - // if (videoEnabled) { - // await track.unmute(); - // } else { - // await track.mute(); - // } - // }, - // ); + this.connection.livekitRoom.localParticipant.on( + ParticipantEvent.LocalTrackPublished, + this.onLocalTrackPublished.bind(this), + ); } - private _tracks$ = new BehaviorSubject[]>([]); - public tracks$ = this._tracks$ as Behavior[]>; - + // LiveKit will publish the tracks as soon as they are created + // but we want to control when tracks are published. + // We cannot just mute the tracks, even if this will effectively stop the publishing, + // it would also prevent the user from seeing their own video/audio preview. + // So for that we use pauseUpStream(): Stops sending media to the server by replacing + // the sender track with null, but keeps the local MediaStreamTrack active. + // The user can still see/hear themselves locally, but remote participants see nothing + private onLocalTrackPublished( + localTrackPublication: LocalTrackPublication, + ): void { + this.logger.info("Local track published", localTrackPublication); + const lkRoom = this.connection.livekitRoom; + if (!this.shouldPublish) { + this.pauseUpstreams(lkRoom, [localTrackPublication.source]).catch((e) => { + this.logger.error(`Failed to pause upstreams`, e); + }); + } + // also check the mute state and apply it + if (localTrackPublication.source === Track.Source.Microphone) { + const enabled = this.muteStates.audio.enabled$.value; + lkRoom.localParticipant.setMicrophoneEnabled(enabled).catch((e) => { + this.logger.error( + `Failed to enable microphone track, enabled:${enabled}`, + e, + ); + }); + } else if (localTrackPublication.source === Track.Source.Camera) { + const enabled = this.muteStates.video.enabled$.value; + lkRoom.localParticipant.setCameraEnabled(enabled).catch((e) => { + this.logger.error( + `Failed to enable camera track, enabled:${enabled}`, + e, + ); + }); + } + } /** - * Start the connection to LiveKit and publish local tracks. * - * This will: - * wait for the connection to be ready. - // * 1. Request an OpenId token `request_token` (allows matrix users to verify their identity with a third-party service.) - // * 2. Use this token to request the SFU config to the MatrixRtc authentication service. - // * 3. Connect to the configured LiveKit room. - // * 4. Create local audio and video tracks based on the current mute states and publish them to the room. - * - * @throws {InsufficientCapacityError} if the LiveKit server indicates that it has insufficient capacity to accept the connection. - * @throws {SFURoomCreationRestrictedError} if the LiveKit server indicates that the room does not exist and cannot be created. */ public async createAndSetupTracks(): Promise { this.logger.debug("createAndSetupTracks called"); @@ -122,119 +136,141 @@ export class Publisher { // Observe mute state changes and update LiveKit microphone/camera states accordingly this.observeMuteStates(this.scope); - // TODO-MULTI-SFU: Prepublish a microphone track + // Check if audio and/or video is enabled. We only create tracks if enabled, + // because it could prompt for permission, and we don't want to do that unnecessarily. const audio = this.muteStates.audio.enabled$.value; const video = this.muteStates.video.enabled$.value; - // createTracks throws if called with audio=false and video=false - if (audio || video) { - // TODO this can still throw errors? It will also prompt for permissions if not already granted - return lkRoom.localParticipant - .createTracks({ - audio, - video, - }) - .then((tracks) => { - this.logger.info( - "created track", - tracks.map((t) => t.kind + ", " + t.id), - ); - this._tracks$.next(tracks); - }) - .catch((error) => { - this.logger.error("Failed to create tracks", error); - }); - } - throw Error("audio and video is false"); + + const enableTracks = async (): Promise => { + if (audio && video) { + // Enable both at once in order to have a single permission prompt! + await lkRoom.localParticipant.enableCameraAndMicrophone(); + } else if (audio) { + await lkRoom.localParticipant.setMicrophoneEnabled(true); + } else if (video) { + await lkRoom.localParticipant.setCameraEnabled(true); + } + return; + }; + + // We cannot just wait because this call could wait for the track to be + // published (and not just created), which we don't want yet. + // Notice it will wait for that only the first time, when tracks are created, the + // later calls will be instant :/ + enableTracks() + .then(() => { + // At this point, LiveKit will have created & published the tracks as soon as possible + // but we want to control when tracks are published. + // We cannot just mute the tracks, even if this will effectively stop the publishing, + // it would also prevent the user from seeing their own video/audio preview. + // So for that we use pauseUpStream(): Stops sending media to the server by replacing + // the sender track with null, but keeps the local MediaStreamTrack active. + // The user can still see/hear themselves locally, but remote participants see nothing + if (!this.shouldPublish) { + this.pauseUpstreams(lkRoom, [ + Track.Source.Microphone, + Track.Source.Camera, + ]).catch((e) => { + this.logger.error(`Failed to pause upstreams`, e); + }); + } + }) + .catch((e: Error) => { + this.logger.error(`Failed to enable camera and microphone`, e); + }); + + return Promise.resolve(); + } + + private async pauseUpstreams( + lkRoom: LivekitRoom, + sources: Track.Source[], + ): Promise { + for (const source of sources) { + const track = lkRoom.localParticipant.getTrackPublication(source)?.track; + if (track) { + await track.pauseUpstream(); + } else { + this.logger.warn( + `No track found for source ${source} to pause upstream`, + ); + } + } + } + + private async resumeUpstreams( + lkRoom: LivekitRoom, + sources: Track.Source[], + ): Promise { + for (const source of sources) { + const track = lkRoom.localParticipant.getTrackPublication(source)?.track; + if (track) { + await track.resumeUpstream(); + } else { + this.logger.warn( + `No track found for source ${source} to resume upstream`, + ); + } + } } - private _publishing$ = new BehaviorSubject(false); - public publishing$ = this.scope.behavior(this._publishing$); /** + * + * Request to publish local tracks to the LiveKit room. + * This will wait for the connection to be ready before publishing. + * Livekit also have some local retry logic for publishing tracks. + * Can be called multiple times, localparticipant manages the state of published tracks (or pending publications). * * @returns - * @throws ElementCallError */ - public async startPublishing(): Promise { + public async startPublishing(): Promise { + if (this.shouldPublish) { + this.logger.debug(`Already publishing, ignoring startPublishing call`); + return; + } + this.shouldPublish = true; this.logger.debug("startPublishing called"); + const lkRoom = this.connection.livekitRoom; - const { promise, resolve, reject } = Promise.withResolvers(); - const sub = this.connection.state$.subscribe((s) => { - switch (s.state) { - case "ConnectedToLkRoom": - resolve(); - break; - case "FailedToStart": - reject( - s.error instanceof ElementCallError - ? s.error - : new FailToStartLivekitConnection(s.error.message), - ); - break; - default: - this.logger.info("waiting for connection: ", s.state); - } - }); + + // Resume upstream for both audio and video tracks + // We need to call it explicitly because call setTrackEnabled does not always + // resume upstream. It will only if you switch the track from disabled to enabled, + // but if the track is already enabled but upstream is paused, it won't resume it. + // TODO what about screen share? try { - await promise; + await this.resumeUpstreams(lkRoom, [ + Track.Source.Microphone, + Track.Source.Camera, + ]); } catch (e) { - throw e; - } finally { - sub.unsubscribe(); + this.logger.error(`Failed to resume upstreams`, e); } - - for (const track of this.tracks$.value) { - this.logger.info("publish ", this.tracks$.value.length, "tracks"); - // TODO: handle errors? Needs the signaling connection to be up, but it has some retries internally - // with a timeout. - await lkRoom.localParticipant.publishTrack(track).catch((error) => { - this.logger.error("Failed to publish track", error); - throw new FailToStartLivekitConnection( - error instanceof Error ? error.message : error, - ); - }); - this.logger.info("published track ", track.kind, track.id); - - // TODO: check if the connection is still active? and break the loop if not? - } - this._publishing$.next(true); - return this.tracks$.value; } public async stopPublishing(): Promise { this.logger.debug("stopPublishing called"); - // TODO-MULTI-SFU: Move these calls back to ObservableScope.onEnd once scope - // actually has the right lifetime - this.muteStates.audio.unsetHandler(); - this.muteStates.video.unsetHandler(); - - const localParticipant = this.connection.livekitRoom.localParticipant; - const tracks: LocalTrack[] = []; - const addToTracksIfDefined = (p: LocalTrackPublication): void => { - if (p.track !== undefined) tracks.push(p.track); - }; - localParticipant.trackPublications.forEach(addToTracksIfDefined); - this.logger.debug( - "list of tracks to unpublish:", - tracks.map((t) => t.kind + ", " + t.id), - "start unpublishing now", - ); - await localParticipant.unpublishTracks(tracks).catch((error) => { - this.logger.error("Failed to unpublish tracks", error); - throw error; - }); - this.logger.debug( - "unpublished tracks", - tracks.map((t) => t.kind + ", " + t.id), - ); - this._publishing$.next(false); + this.shouldPublish = false; + await this.pauseUpstreams(this.connection.livekitRoom, [ + Track.Source.Microphone, + Track.Source.Camera, + Track.Source.ScreenShare, + ]); } - /** - * Stops all tracks that are currently running - */ - public stopTracks(): void { - this.tracks$.value.forEach((t) => t.stop()); - this._tracks$.next([]); + public async stopTracks(): Promise { + const lkRoom = this.connection.livekitRoom; + for (const source of [ + Track.Source.Microphone, + Track.Source.Camera, + Track.Source.ScreenShare, + ]) { + const localPub = lkRoom.localParticipant.getTrackPublication(source); + if (localPub?.track) { + // stops and unpublishes the track + await lkRoom.localParticipant.unpublishTrack(localPub!.track, true); + } + } } /// Private methods @@ -336,17 +372,31 @@ export class Publisher { */ private observeMuteStates(scope: ObservableScope): void { const lkRoom = this.connection.livekitRoom; - this.muteStates.audio.setHandler(async (desired) => { + this.muteStates.audio.setHandler(async (enable) => { try { - await lkRoom.localParticipant.setMicrophoneEnabled(desired); + this.logger.debug( + `handler: Setting LiveKit microphone enabled: ${enable}`, + ); + await lkRoom.localParticipant.setMicrophoneEnabled(enable); + // Unmute will restart the track if it was paused upstream, + // but until explicitly requested, we want to keep it paused. + if (!this.shouldPublish && enable) { + await this.pauseUpstreams(lkRoom, [Track.Source.Microphone]); + } } catch (e) { this.logger.error("Failed to update LiveKit audio input mute state", e); } return lkRoom.localParticipant.isMicrophoneEnabled; }); - this.muteStates.video.setHandler(async (desired) => { + this.muteStates.video.setHandler(async (enable) => { try { - await lkRoom.localParticipant.setCameraEnabled(desired); + this.logger.debug(`handler: Setting LiveKit camera enabled: ${enable}`); + await lkRoom.localParticipant.setCameraEnabled(enable); + // Unmute will restart the track if it was paused upstream, + // but until explicitly requested, we want to keep it paused. + if (!this.shouldPublish && enable) { + await this.pauseUpstreams(lkRoom, [Track.Source.Camera]); + } } catch (e) { this.logger.error("Failed to update LiveKit video input mute state", e); } diff --git a/src/utils/test.ts b/src/utils/test.ts index bd7dcd6f4..24b9bef0c 100644 --- a/src/utils/test.ts +++ b/src/utils/test.ts @@ -311,6 +311,8 @@ export function mockLocalParticipant( publishTrack: vi.fn(), unpublishTracks: vi.fn().mockResolvedValue([]), createTracks: vi.fn(), + setMicrophoneEnabled: vi.fn(), + setCameraEnabled: vi.fn(), getTrackPublication: () => ({}) as Partial as LocalTrackPublication, ...mockEmitter(), From 610af439a8fbf371cc310af84fe1e96775b1a86e Mon Sep 17 00:00:00 2001 From: Valere Date: Fri, 12 Dec 2025 10:37:37 +0100 Subject: [PATCH 094/748] cleaning: just use `LocalTrackPublished` event to pause/unpause --- .../CallViewModel/localMember/Publisher.ts | 34 +++++-------------- 1 file changed, 8 insertions(+), 26 deletions(-) diff --git a/src/state/CallViewModel/localMember/Publisher.ts b/src/state/CallViewModel/localMember/Publisher.ts index 5da6d899a..d4ad656c4 100644 --- a/src/state/CallViewModel/localMember/Publisher.ts +++ b/src/state/CallViewModel/localMember/Publisher.ts @@ -152,32 +152,14 @@ export class Publisher { } return; }; - - // We cannot just wait because this call could wait for the track to be - // published (and not just created), which we don't want yet. - // Notice it will wait for that only the first time, when tracks are created, the - // later calls will be instant :/ - enableTracks() - .then(() => { - // At this point, LiveKit will have created & published the tracks as soon as possible - // but we want to control when tracks are published. - // We cannot just mute the tracks, even if this will effectively stop the publishing, - // it would also prevent the user from seeing their own video/audio preview. - // So for that we use pauseUpStream(): Stops sending media to the server by replacing - // the sender track with null, but keeps the local MediaStreamTrack active. - // The user can still see/hear themselves locally, but remote participants see nothing - if (!this.shouldPublish) { - this.pauseUpstreams(lkRoom, [ - Track.Source.Microphone, - Track.Source.Camera, - ]).catch((e) => { - this.logger.error(`Failed to pause upstreams`, e); - }); - } - }) - .catch((e: Error) => { - this.logger.error(`Failed to enable camera and microphone`, e); - }); + // We don't await enableTracks, because livekit could block until the tracks + // are fully published, and not only that they are created. + // We don't have control on that, localParticipant creates and publishes the tracks + // asap. + // We are using the `ParticipantEvent.LocalTrackPublished` to be notified + // when tracks are actually published, and at that point + // we can pause upstream if needed (depending on if startPublishing has been called). + void enableTracks(); return Promise.resolve(); } From b3b76d8b3d26e367c325233bf4c86745b41b7763 Mon Sep 17 00:00:00 2001 From: Valere Date: Fri, 12 Dec 2025 11:54:43 +0100 Subject: [PATCH 095/748] post merge --- .../CallViewModel/localMember/LocalMember.ts | 35 +++++++------------ 1 file changed, 12 insertions(+), 23 deletions(-) diff --git a/src/state/CallViewModel/localMember/LocalMember.ts b/src/state/CallViewModel/localMember/LocalMember.ts index 5898a3da3..241cb633b 100644 --- a/src/state/CallViewModel/localMember/LocalMember.ts +++ b/src/state/CallViewModel/localMember/LocalMember.ts @@ -10,7 +10,6 @@ import { ParticipantEvent, type LocalParticipant, type ScreenShareCaptureOptions, - ConnectionState, RoomEvent, MediaDeviceFailure, } from "livekit-client"; @@ -329,11 +328,10 @@ export const createLocalMembership$ = ({ // Based on `connectRequested$` we start publishing tracks. (once they are there!) scope.reconcile( scope.behavior( - combineLatest([publisher$, tracks$, joinAndPublishRequested$]), + combineLatest([publisher$, joinAndPublishRequested$]), ), - async ([publisher, tracks, shouldJoinAndPublish]) => { - if (shouldJoinAndPublish === publisher?.publishing$.value) return; - if (tracks.length !== 0 && shouldJoinAndPublish) { + async ([publisher, shouldJoinAndPublish]) => { + if (shouldJoinAndPublish) { try { await publisher?.startPublishing(); } catch (error) { @@ -341,7 +339,7 @@ export const createLocalMembership$ = ({ error instanceof Error ? error.message : String(error); setPublishError(new FailToStartLivekitConnection(message)); } - } else if (tracks.length !== 0 && !shouldJoinAndPublish) { + } else { try { await publisher?.stopPublishing(); } catch (error) { @@ -391,15 +389,6 @@ export const createLocalMembership$ = ({ combineLatest([ localConnectionState$, localTransport$, - // tracks$.pipe( - // tap((t) => { - // logger.info("tracks$: ", t); - // }), - // ), - // publishing$, - connectRequested$, - tracks$, - publishing$, joinAndPublishRequested$, from(trackStartRequested.promise).pipe( map(() => true), @@ -410,16 +399,17 @@ export const createLocalMembership$ = ({ ([ localConnectionState, localTransport, - tracks, - publishing, + // tracks, + // publishing, shouldPublish, shouldStartTracks, ]) => { if (!localTransport) return null; - const hasTracks = tracks.length > 0; - let trackState: TrackState = TrackState.WaitingForUser; - if (hasTracks && shouldStartTracks) trackState = TrackState.Ready; - if (!hasTracks && shouldStartTracks) trackState = TrackState.Creating; + // const hasTracks = tracks.length > 0; + // let trackState: TrackState = TrackState.WaitingForUser; + // if (hasTracks && shouldStartTracks) trackState = TrackState.Ready; + // if (!hasTracks && shouldStartTracks) trackState = TrackState.Creating; + const trackState: TrackState = shouldStartTracks ? TrackState.Ready : TrackState.WaitingForUser; if ( localConnectionState !== ConnectionState.LivekitConnected || @@ -430,7 +420,7 @@ export const createLocalMembership$ = ({ tracks: trackState, }; if (!shouldPublish) return PublishState.WaitingForUser; - if (!publishing) return PublishState.Starting; + // if (!publishing) return PublishState.Starting; return PublishState.Publishing; }, ), @@ -660,7 +650,6 @@ export const createLocalMembership$ = ({ requestJoinAndPublish, requestDisconnect, localMemberState$, - tracks$, participant$, reconnecting$, disconnected$: scope.behavior( From 93da69983dfaa6aa7850429d7aa09bbe4af2224b Mon Sep 17 00:00:00 2001 From: Valere Date: Fri, 12 Dec 2025 14:40:45 +0100 Subject: [PATCH 096/748] post merge: partial mapping of tracks/publish states --- .../localMember/LocalMember.test.ts | 18 ++++++++++-------- .../CallViewModel/localMember/LocalMember.ts | 18 +++++++++++------- .../localMember/Publisher.test.ts | 2 +- 3 files changed, 22 insertions(+), 16 deletions(-) diff --git a/src/state/CallViewModel/localMember/LocalMember.test.ts b/src/state/CallViewModel/localMember/LocalMember.test.ts index 892bbb3db..0d77611bf 100644 --- a/src/state/CallViewModel/localMember/LocalMember.test.ts +++ b/src/state/CallViewModel/localMember/LocalMember.test.ts @@ -254,10 +254,12 @@ describe("LocalMembership", () => { const connectionTransportAConnecting = { ...connectionTransportAConnected, state$: constant(ConnectionState.LivekitConnecting), + livekitRoom: mockLivekitRoom({}), } as unknown as Connection; const connectionTransportBConnected = { state$: constant(ConnectionState.LivekitConnected), transport: bTransport, + livekitRoom: mockLivekitRoom({}), } as unknown as Connection; it("recreates publisher if new connection is used and ENDS always unpublish and end tracks", async () => { @@ -477,13 +479,13 @@ describe("LocalMembership", () => { // ------- await flushPromises(); - expect(localMembership.localMemberState$.value).toStrictEqual({ - matrix: RTCMemberStatus.Connected, - media: { - tracks: TrackState.Creating, - connection: ConnectionState.LivekitConnected, - }, - }); + // expect(localMembership.localMemberState$.value).toStrictEqual({ + // matrix: RTCMemberStatus.Connected, + // media: { + // tracks: TrackState.Creating, + // connection: ConnectionState.LivekitConnected, + // }, + // }); createTrackResolver.resolve(); await flushPromises(); expect( @@ -498,7 +500,7 @@ describe("LocalMembership", () => { expect( // eslint-disable-next-line @typescript-eslint/no-explicit-any (localMembership.localMemberState$.value as any).media, - ).toStrictEqual(PublishState.Starting); + ).toStrictEqual(PublishState.Publishing); publishResolver.resolve(); await flushPromises(); diff --git a/src/state/CallViewModel/localMember/LocalMember.ts b/src/state/CallViewModel/localMember/LocalMember.ts index 241cb633b..21386fcd6 100644 --- a/src/state/CallViewModel/localMember/LocalMember.ts +++ b/src/state/CallViewModel/localMember/LocalMember.ts @@ -74,6 +74,8 @@ export enum PublishState { Publishing = "publish_publishing", } +// TODO not sure how to map that correctly with the +// new publisher that does not manage tracks itself anymore export enum TrackState { /** The track is waiting for user input to create tracks (waiting to call `startTracks()`) */ WaitingForUser = "tracks_waiting_for_user", @@ -244,7 +246,7 @@ export const createLocalMembership$ = ({ if (error) { logger.error(`Failed to create local tracks:`, error); setMatrixError( - // TODO is it fatal? Do we need to create a new Specialized Error? + // TODO is it fatal? Do we need to create a new Specialized Error? new UnknownCallError(new Error(`Media device error: ${error}`)), ); } @@ -327,11 +329,11 @@ export const createLocalMembership$ = ({ // Based on `connectRequested$` we start publishing tracks. (once they are there!) scope.reconcile( - scope.behavior( - combineLatest([publisher$, joinAndPublishRequested$]), - ), + scope.behavior(combineLatest([publisher$, joinAndPublishRequested$])), async ([publisher, shouldJoinAndPublish]) => { - if (shouldJoinAndPublish) { + // Get the current publishing state to avoid redundant calls. + const isPublishing = publisher?.shouldPublish === true; + if (shouldJoinAndPublish && !isPublishing) { try { await publisher?.startPublishing(); } catch (error) { @@ -339,7 +341,7 @@ export const createLocalMembership$ = ({ error instanceof Error ? error.message : String(error); setPublishError(new FailToStartLivekitConnection(message)); } - } else { + } else if (isPublishing) { try { await publisher?.stopPublishing(); } catch (error) { @@ -409,7 +411,9 @@ export const createLocalMembership$ = ({ // let trackState: TrackState = TrackState.WaitingForUser; // if (hasTracks && shouldStartTracks) trackState = TrackState.Ready; // if (!hasTracks && shouldStartTracks) trackState = TrackState.Creating; - const trackState: TrackState = shouldStartTracks ? TrackState.Ready : TrackState.WaitingForUser; + const trackState: TrackState = shouldStartTracks + ? TrackState.Ready + : TrackState.WaitingForUser; if ( localConnectionState !== ConnectionState.LivekitConnected || diff --git a/src/state/CallViewModel/localMember/Publisher.test.ts b/src/state/CallViewModel/localMember/Publisher.test.ts index 3ab3d48c0..3cc96bc2d 100644 --- a/src/state/CallViewModel/localMember/Publisher.test.ts +++ b/src/state/CallViewModel/localMember/Publisher.test.ts @@ -22,7 +22,7 @@ import { constant } from "../../Behavior"; import { flushPromises, mockLivekitRoom, - mockMediaDevices + mockMediaDevices, } from "../../../utils/test"; import { Publisher } from "./Publisher"; import { type Connection } from "../remoteMembers/Connection"; From 8f2055b4f473313cf5ab8e2f16952dc256128633 Mon Sep 17 00:00:00 2001 From: Valere Date: Fri, 12 Dec 2025 14:46:13 +0100 Subject: [PATCH 097/748] eslint fix --- src/state/CallViewModel/localMember/LocalMember.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/state/CallViewModel/localMember/LocalMember.ts b/src/state/CallViewModel/localMember/LocalMember.ts index 21386fcd6..b75bf5221 100644 --- a/src/state/CallViewModel/localMember/LocalMember.ts +++ b/src/state/CallViewModel/localMember/LocalMember.ts @@ -303,7 +303,7 @@ export const createLocalMembership$ = ({ // Clean-up callback return Promise.resolve(async (): Promise => { await publisher.stopPublishing(); - publisher.stopTracks(); + await publisher.stopTracks(); }); } }); From 190cdfcb6030edbe2b2cc08ae8765908a380eeb5 Mon Sep 17 00:00:00 2001 From: Valere Date: Fri, 12 Dec 2025 17:03:16 +0100 Subject: [PATCH 098/748] comment now dead state variant --- src/state/CallViewModel/localMember/LocalMember.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/state/CallViewModel/localMember/LocalMember.ts b/src/state/CallViewModel/localMember/LocalMember.ts index b75bf5221..daadbe7c9 100644 --- a/src/state/CallViewModel/localMember/LocalMember.ts +++ b/src/state/CallViewModel/localMember/LocalMember.ts @@ -68,8 +68,8 @@ export enum TransportState { export enum PublishState { WaitingForUser = "publish_waiting_for_user", - /** Implies lk connection is connected */ - Starting = "publish_start_publishing", + // /** Implies lk connection is connected */ + // Starting = "publish_start_publishing", /** Implies lk connection is connected */ Publishing = "publish_publishing", } @@ -79,8 +79,8 @@ export enum PublishState { export enum TrackState { /** The track is waiting for user input to create tracks (waiting to call `startTracks()`) */ WaitingForUser = "tracks_waiting_for_user", - /** Implies lk connection is connected */ - Creating = "tracks_creating", + // /** Implies lk connection is connected */ + // Creating = "tracks_creating", /** Implies lk connection is connected */ Ready = "tracks_ready", } From 909d980dff83d96bd81db2d692b9c4f9f31745c9 Mon Sep 17 00:00:00 2001 From: Timo K Date: Mon, 15 Dec 2025 18:23:30 +0100 Subject: [PATCH 099/748] still with broken tests... --- package.json | 2 +- src/e2ee/matrixKeyProvider.ts | 65 ++- src/livekit/MatrixAudioRenderer.tsx | 3 +- src/room/InCallView.tsx | 1 + src/state/CallViewModel/CallViewModel.test.ts | 3 - src/state/CallViewModel/CallViewModel.ts | 25 +- .../remoteMembers/ConnectionManager.ts | 25 +- .../MatrixLivekitMembers.test.ts | 437 ++++++++---------- .../remoteMembers/MatrixLivekitMembers.ts | 107 ++++- yarn.lock | 42 +- 10 files changed, 353 insertions(+), 357 deletions(-) diff --git a/package.json b/package.json index 21c870adb..1efb504b7 100644 --- a/package.json +++ b/package.json @@ -109,7 +109,7 @@ "livekit-client": "^2.13.0", "lodash-es": "^4.17.21", "loglevel": "^1.9.1", - "matrix-js-sdk": "^39.2.0", + "matrix-js-sdk": "github:matrix-org/matrix-js-sdk#head=toger5/use-membershipID-for-session-state-events&commit=f5f1b8efb46b3d55a7eebfabb4a61496640b8b00", "matrix-widget-api": "^1.14.0", "normalize.css": "^8.0.1", "observable-hooks": "^4.2.3", diff --git a/src/e2ee/matrixKeyProvider.ts b/src/e2ee/matrixKeyProvider.ts index 95033f873..1d1c45884 100644 --- a/src/e2ee/matrixKeyProvider.ts +++ b/src/e2ee/matrixKeyProvider.ts @@ -11,6 +11,12 @@ import { type MatrixRTCSession, MatrixRTCSessionEvent, } from "matrix-js-sdk/lib/matrixrtc"; +import { type CallMembershipIdentityParts } from "matrix-js-sdk/lib/matrixrtc/EncryptionManager"; + +import { + computeLivekitParticipantIdentity, + livekitIdentityInput, +} from "../state/CallViewModel/remoteMembers/MatrixLivekitMembers"; export class MatrixKeyProvider extends BaseKeyProvider { private rtcSession?: MatrixRTCSession; @@ -42,31 +48,46 @@ export class MatrixKeyProvider extends BaseKeyProvider { private onEncryptionKeyChanged = ( encryptionKey: Uint8Array, encryptionKeyIndex: number, - participantId: string, + membership: CallMembershipIdentityParts, ): void => { - crypto.subtle - .importKey("raw", encryptionKey, "HKDF", false, [ + const unhashedIdentity = livekitIdentityInput(membership); + + // This is the only way we can get the kind of the membership event we just received the key for. + // best case we want to recompute this once the memberships change (you can receive the key before the participant...) + // + // TODO change this to `?? "rtc"` for newer versions. + const kind = + this.rtcSession?.memberships.find( + (m) => + m.userId === membership.userId && + m.deviceId === membership.deviceId && + m.memberId === membership.memberId, + )?.kind ?? "session"; + + Promise.all([ + crypto.subtle.importKey("raw", encryptionKey, "HKDF", false, [ "deriveBits", "deriveKey", - ]) - .then( - (keyMaterial) => { - this.onSetEncryptionKey( - keyMaterial, - participantId, - encryptionKeyIndex, - ); + ]), + computeLivekitParticipantIdentity(membership, kind), + ]).then( + ([keyMaterial, livekitParticipantId]) => { + this.onSetEncryptionKey( + keyMaterial, + livekitParticipantId, + encryptionKeyIndex, + ); - logger.debug( - `Sent new key to livekit room=${this.rtcSession?.room.roomId} participantId=${participantId} encryptionKeyIndex=${encryptionKeyIndex}`, - ); - }, - (e) => { - logger.error( - `Failed to create key material from buffer for livekit room=${this.rtcSession?.room.roomId} participantId=${participantId} encryptionKeyIndex=${encryptionKeyIndex}`, - e, - ); - }, - ); + logger.debug( + `Sent new key to livekit room=${this.rtcSession?.room.roomId} participantId=${livekitParticipantId} (before hash: ${unhashedIdentity}) encryptionKeyIndex=${encryptionKeyIndex}`, + ); + }, + (e) => { + logger.error( + `Failed to create key material from buffer for livekit room=${this.rtcSession?.room.roomId} participantId before hash=${unhashedIdentity} encryptionKeyIndex=${encryptionKeyIndex}`, + e, + ); + }, + ); }; } diff --git a/src/livekit/MatrixAudioRenderer.tsx b/src/livekit/MatrixAudioRenderer.tsx index 5b1149e99..0fa5d0005 100644 --- a/src/livekit/MatrixAudioRenderer.tsx +++ b/src/livekit/MatrixAudioRenderer.tsx @@ -15,7 +15,6 @@ import { type AudioTrackProps, } from "@livekit/components-react"; import { logger } from "matrix-js-sdk/lib/logger"; -import { type ParticipantId } from "matrix-js-sdk/lib/matrixrtc"; import { useEarpieceAudioConfig } from "../MediaDevicesContext"; import { useReactiveState } from "../useReactiveState"; @@ -32,7 +31,7 @@ export interface MatrixAudioRendererProps { * This list needs to be composed based on the matrixRTC members so that we do not play audio from users * that are not expected to be in the rtc session (local user is excluded). */ - validIdentities: ParticipantId[]; + validIdentities: string[]; /** * If set to `true`, mutes all audio tracks rendered by the component. * @remarks diff --git a/src/room/InCallView.tsx b/src/room/InCallView.tsx index 6ae004d8a..e9932fdc5 100644 --- a/src/room/InCallView.tsx +++ b/src/room/InCallView.tsx @@ -785,6 +785,7 @@ export const InCallView: FC = ({ onTouchEnd={onControlsTouchEnd} /> )} + {!showControls &&
}
); diff --git a/src/state/CallViewModel/CallViewModel.test.ts b/src/state/CallViewModel/CallViewModel.test.ts index 2e5b57008..be598702b 100644 --- a/src/state/CallViewModel/CallViewModel.test.ts +++ b/src/state/CallViewModel/CallViewModel.test.ts @@ -1248,9 +1248,6 @@ describe("CallViewModel", () => { y: () => { rtcSession.membershipStatus = Status.Connected; }, - n: () => { - rtcSession.membershipStatus = Status.Reconnecting; - }, }); schedule(probablyLeftMarbles, { y: () => { diff --git a/src/state/CallViewModel/CallViewModel.ts b/src/state/CallViewModel/CallViewModel.ts index 5cc33f5d4..289b642ca 100644 --- a/src/state/CallViewModel/CallViewModel.ts +++ b/src/state/CallViewModel/CallViewModel.ts @@ -591,10 +591,9 @@ export function createCallViewModel$( const audioParticipants$ = scope.behavior( matrixLivekitMembers$.pipe( - switchMap((membersWithEpoch) => { - const members = membersWithEpoch.value; + switchMap((members) => { const a$ = combineLatest( - members.map((member) => + members.value.map((member) => combineLatest([member.connection$, member.participant$]).pipe( map(([connection, participant]) => { // do not render audio for local participant @@ -667,22 +666,22 @@ export function createCallViewModel$( generateItems( function* ([ localMatrixLivekitMember, - { value: matrixLivekitMembers }, + matrixLivekitMembers, duplicateTiles, ]) { - let localParticipantId: string | undefined = undefined; + let localUserMediaId: string | undefined = undefined; // add local member if available if (localMatrixLivekitMember) { const { userId, participant$, connection$, membership$ } = localMatrixLivekitMember; - localParticipantId = `${userId}:${membership$.value.deviceId}`; // should be membership$.value.membershipID which is not optional - // const participantId = membership$.value.membershipID; - if (localParticipantId) { + localUserMediaId = `${userId}:${membership$.value.deviceId}`; // should be membership$.value.membershipID which is not optional + + if (localUserMediaId) { for (let dup = 0; dup < 1 + duplicateTiles; dup++) { yield { keys: [ dup, - localParticipantId, + localUserMediaId, userId, participant$, connection$, @@ -698,13 +697,13 @@ export function createCallViewModel$( participant$, connection$, membership$, - } of matrixLivekitMembers) { - const participantId = `${userId}:${membership$.value.deviceId}`; - if (participantId === localParticipantId) continue; + } of matrixLivekitMembers.value) { + const userMediaId = `${userId}:${membership$.value.deviceId}`; + if (userMediaId === localUserMediaId) continue; // const participantId = membership$.value?.identity; for (let dup = 0; dup < 1 + duplicateTiles; dup++) { yield { - keys: [dup, participantId, userId, participant$, connection$], + keys: [dup, userMediaId, userId, participant$, connection$], data: undefined, }; } diff --git a/src/state/CallViewModel/remoteMembers/ConnectionManager.ts b/src/state/CallViewModel/remoteMembers/ConnectionManager.ts index 755ba3ddc..6660df623 100644 --- a/src/state/CallViewModel/remoteMembers/ConnectionManager.ts +++ b/src/state/CallViewModel/remoteMembers/ConnectionManager.ts @@ -6,10 +6,7 @@ SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial Please see LICENSE in the repository root for full details. */ -import { - type LivekitTransport, - type ParticipantId, -} from "matrix-js-sdk/lib/matrixrtc"; +import { type LivekitTransport } from "matrix-js-sdk/lib/matrixrtc"; import { combineLatest, map, of, switchMap, tap } from "rxjs"; import { type Logger } from "matrix-js-sdk/lib/logger"; import { type LocalParticipant, type RemoteParticipant } from "livekit-client"; @@ -62,24 +59,8 @@ export class ConnectionManagerData { const key = transport.livekit_service_url + "|" + transport.livekit_alias; return this.store.get(key)?.[1] ?? []; } - /** - * Get all connections where the given participant is publishing. - * In theory, there could be several connections where the same participant is publishing but with - * only well behaving clients a participant should only be publishing on a single connection. - * @param participantId - */ - public getConnectionsForParticipant( - participantId: ParticipantId, - ): Connection[] { - const connections: Connection[] = []; - for (const [connection, participants] of this.store.values()) { - if (participants.some((p) => p.identity === participantId)) { - connections.push(connection); - } - } - return connections; - } } + interface Props { scope: ObservableScope; connectionFactory: ConnectionFactory; @@ -202,7 +183,7 @@ export function createConnectionManager$({ ); }), ), - new Epoch(new ConnectionManagerData()), + new Epoch(new ConnectionManagerData(), -1), ); return { connectionManagerData$ }; diff --git a/src/state/CallViewModel/remoteMembers/MatrixLivekitMembers.test.ts b/src/state/CallViewModel/remoteMembers/MatrixLivekitMembers.test.ts index e675f7230..c2e60798f 100644 --- a/src/state/CallViewModel/remoteMembers/MatrixLivekitMembers.test.ts +++ b/src/state/CallViewModel/remoteMembers/MatrixLivekitMembers.test.ts @@ -10,8 +10,7 @@ import { type CallMembership, type LivekitTransport, } from "matrix-js-sdk/lib/matrixrtc"; -import { getParticipantId } from "matrix-js-sdk/lib/matrixrtc/utils"; -import { combineLatest, map, type Observable } from "rxjs"; +import { BehaviorSubject, combineLatest, map, type Observable } from "rxjs"; import { type IConnectionManager } from "./ConnectionManager.ts"; import { @@ -26,14 +25,19 @@ import { } from "../../ObservableScope.ts"; import { ConnectionManagerData } from "./ConnectionManager.ts"; import { + flushPromises, mockCallMembership, mockRemoteParticipant, withTestScheduler, } from "../../../utils/test.ts"; import { type Connection } from "./Connection.ts"; +import { constant } from "../../Behavior.ts"; let testScope: ObservableScope; +const fallbackMemberId = (userId: string, deviceId: string): string => + `${userId}:${deviceId}`; + const transportA: LivekitTransport = { type: "livekit", livekit_service_url: "https://lk.example.org", @@ -76,49 +80,41 @@ function epochMeWith$( ); } -test("should signal participant not yet connected to livekit", () => { - withTestScheduler(({ behavior, expectObservable }) => { - const { memberships$, membershipsWithTransport$ } = fromMemberships$( - behavior("a", { - a: [bobMembership], - }), - ); +test("should signal participant not yet connected to livekit", async () => { + const mockedMemberships$ = new BehaviorSubject([bobMembership]); + const mockConnectionManagerData$ = new BehaviorSubject( + new ConnectionManagerData(), + ); + const { memberships$, membershipsWithTransport$ } = + createEpochedMemberships$(mockedMemberships$); - const connectionManagerData$ = epochMeWith$( - memberships$, - behavior("a", { - a: new ConnectionManagerData(), - }), - ); + const connectionManagerData$ = epochMeWith$( + memberships$, + mockConnectionManagerData$, + ); - const matrixLivekitMember$ = createMatrixLivekitMembers$({ - scope: testScope, - membershipsWithTransport$: testScope.behavior(membershipsWithTransport$), - connectionManager: { - connectionManagerData$: connectionManagerData$, - } as unknown as IConnectionManager, - }); - - expectObservable(matrixLivekitMember$.pipe(map((e) => e.value))).toBe("a", { - a: expect.toSatisfy((data: MatrixLivekitMember[]) => { - expect(data.length).toEqual(1); - expectObservable(data[0].membership$).toBe("a", { - a: bobMembership, - }); - expectObservable(data[0].participant$).toBe("a", { - a: null, - }); - expectObservable(data[0].connection$).toBe("a", { - a: null, - }); - return true; - }), - }); + const matrixLivekitMember$ = createMatrixLivekitMembers$({ + scope: testScope, + membershipsWithTransport$: testScope.behavior(membershipsWithTransport$), + connectionManager: { + connectionManagerData$: connectionManagerData$, + } as unknown as IConnectionManager, }); + + await flushPromises(); + expect(matrixLivekitMember$.value.value).toSatisfy( + (data: MatrixLivekitMember[]) => { + expect(data.length).toEqual(1); + expect(data[0].membership$.value).toBe(bobMembership); + expect(data[0].participant$.value).toBe(null); + expect(data[0].connection$.value).toBe(null); + return true; + }, + ); }); // Helper to create epoch'ed memberships$ and membershipsWithTransport$ from memberships observable. -function fromMemberships$(m$: Observable): { +function createEpochedMemberships$(m$: Observable): { memberships$: Observable>; membershipsWithTransport$: Observable< Epoch<{ membership: CallMembership; transport?: LivekitTransport }[]> @@ -143,32 +139,115 @@ function fromMemberships$(m$: Observable): { }; } -test("should signal participant on a connection that is publishing", () => { - withTestScheduler(({ behavior, expectObservable }) => { - const bobParticipantId = getParticipantId( +test("should signal participant on a connection that is publishing", async () => { + const bobParticipantId = fallbackMemberId( + bobMembership.userId, + bobMembership.deviceId, + ); + + const { memberships$, membershipsWithTransport$ } = createEpochedMemberships$( + constant([bobMembership]), + ); + + const connection = { + transport: bobMembership.getTransport(bobMembership), + } as unknown as Connection; + const dataWithPublisher = new ConnectionManagerData(); + dataWithPublisher.add(connection, [ + mockRemoteParticipant({ identity: bobParticipantId }), + ]); + + const connectionManagerData$ = epochMeWith$( + memberships$, + constant(dataWithPublisher), + ); + + const matrixLivekitMember$ = createMatrixLivekitMembers$({ + scope: testScope, + membershipsWithTransport$: testScope.behavior(membershipsWithTransport$), + connectionManager: { + connectionManagerData$: connectionManagerData$, + } as unknown as IConnectionManager, + }); + + await flushPromises(); + expect(matrixLivekitMember$.value.value).toSatisfy( + (data: MatrixLivekitMember[]) => { + expect(data.length).toEqual(1); + expect(data[0].membership$.value).toBe(bobMembership); + expect(data[0].participant$.value).toSatisfy((participant) => { + expect(participant).toBeDefined(); + expect(participant!.identity).toEqual(bobParticipantId); + return true; + }); + expect(data[0].connection$.value).toBe(connection); + return true; + }, + ); +}); + +test("should signal participant on a connection that is not publishing", async () => { + const { memberships$, membershipsWithTransport$ } = createEpochedMemberships$( + constant([bobMembership]), + ); + + const connection = { + transport: bobMembership.getTransport(bobMembership), + } as unknown as Connection; + const dataWithPublisher = new ConnectionManagerData(); + dataWithPublisher.add(connection, []); + + const connectionManagerData$ = epochMeWith$( + memberships$, + constant(dataWithPublisher), + ); + + const matrixLivekitMember$ = createMatrixLivekitMembers$({ + scope: testScope, + membershipsWithTransport$: testScope.behavior(membershipsWithTransport$), + connectionManager: { + connectionManagerData$: connectionManagerData$, + } as unknown as IConnectionManager, + }); + await flushPromises(); + expect(matrixLivekitMember$.value.value).toSatisfy( + (data: MatrixLivekitMember[]) => { + expect(data.length).toEqual(1); + expect(data[0].membership$.value).toBe(bobMembership); + expect(data[0].participant$.value).toBe(null); + expect(data[0].connection$.value).toBe(connection); + return true; + }, + ); +}); + +describe("Publication edge case", () => { + test("bob is publishing in several connections", async () => { + const { memberships$, membershipsWithTransport$ } = + createEpochedMemberships$(constant([bobMembership, carlMembership])); + + const connectionWithPublisher = new ConnectionManagerData(); + const bobParticipantId = fallbackMemberId( bobMembership.userId, bobMembership.deviceId, ); - - const { memberships$, membershipsWithTransport$ } = fromMemberships$( - behavior("a", { - a: [bobMembership], - }), - ); - - const connection = { - transport: bobMembership.getTransport(bobMembership), + const connectionA = { + transport: transportA, } as unknown as Connection; - const dataWithPublisher = new ConnectionManagerData(); - dataWithPublisher.add(connection, [ + const connectionB = { + transport: transportB, + } as unknown as Connection; + + connectionWithPublisher.add(connectionA, [ + mockRemoteParticipant({ identity: bobParticipantId }), + ]); + connectionWithPublisher.add(connectionB, [ mockRemoteParticipant({ identity: bobParticipantId }), ]); const connectionManagerData$ = epochMeWith$( memberships$, - behavior("a", { - a: dataWithPublisher, - }), + constant(connectionWithPublisher), ); const matrixLivekitMember$ = createMatrixLivekitMembers$({ @@ -178,207 +257,73 @@ test("should signal participant on a connection that is publishing", () => { connectionManagerData$: connectionManagerData$, } as unknown as IConnectionManager, }); + await flushPromises(); + expect(matrixLivekitMember$.value.value).toSatisfy( + (data: MatrixLivekitMember[]) => { + expect(data.length).toEqual(2); + expect(data[0].membership$.value).toBe(bobMembership); + expect(data[0].connection$.value).toBe(connectionA); + expect(data[0].participant$.value).toSatisfy((participant) => { + expect(participant).toBeDefined(); + expect(participant!.identity).toEqual(bobParticipantId); + return true; + }); - expectObservable(matrixLivekitMember$.pipe(map((e) => e.value))).toBe("a", { - a: expect.toSatisfy((data: MatrixLivekitMember[]) => { - expect(data.length).toEqual(1); - expectObservable(data[0].membership$).toBe("a", { - a: bobMembership, - }); - expectObservable(data[0].participant$).toBe("a", { - a: expect.toSatisfy((participant) => { - expect(participant).toBeDefined(); - expect(participant!.identity).toEqual(bobParticipantId); - return true; - }), - }); - expectObservable(data[0].connection$).toBe("a", { - a: connection, - }); return true; - }), - }); - }); -}); - -test("should signal participant on a connection that is not publishing", () => { - withTestScheduler(({ behavior, expectObservable }) => { - const { memberships$, membershipsWithTransport$ } = fromMemberships$( - behavior("a", { - a: [bobMembership], - }), + }, ); - - const connection = { - transport: bobMembership.getTransport(bobMembership), - } as unknown as Connection; - const dataWithPublisher = new ConnectionManagerData(); - dataWithPublisher.add(connection, []); - - const connectionManagerData$ = epochMeWith$( - memberships$, - behavior("a", { - a: dataWithPublisher, - }), - ); - - const matrixLivekitMember$ = createMatrixLivekitMembers$({ - scope: testScope, - membershipsWithTransport$: testScope.behavior(membershipsWithTransport$), - connectionManager: { - connectionManagerData$: connectionManagerData$, - } as unknown as IConnectionManager, - }); - - expectObservable(matrixLivekitMember$.pipe(map((e) => e.value))).toBe("a", { - a: expect.toSatisfy((data: MatrixLivekitMember[]) => { - expect(data.length).toEqual(1); - expectObservable(data[0].membership$).toBe("a", { - a: bobMembership, - }); - expectObservable(data[0].participant$).toBe("a", { - a: null, - }); - expectObservable(data[0].connection$).toBe("a", { - a: connection, - }); - return true; - }), - }); }); }); -describe("Publication edge case", () => { - test("bob is publishing in several connections", () => { - withTestScheduler(({ behavior, expectObservable }) => { - const { memberships$, membershipsWithTransport$ } = fromMemberships$( - behavior("a", { - a: [bobMembership, carlMembership], - }), - ); +test("bob is publishing in the wrong connection", async () => { + const mockedMemberships$ = new BehaviorSubject([ + bobMembership, + carlMembership, + ]); - const connectionWithPublisher = new ConnectionManagerData(); - const bobParticipantId = getParticipantId( - bobMembership.userId, - bobMembership.deviceId, - ); - const connectionA = { - transport: transportA, - } as unknown as Connection; - const connectionB = { - transport: transportB, - } as unknown as Connection; + const { memberships$, membershipsWithTransport$ } = + createEpochedMemberships$(mockedMemberships$); - connectionWithPublisher.add(connectionA, [ - mockRemoteParticipant({ identity: bobParticipantId }), - ]); - connectionWithPublisher.add(connectionB, [ - mockRemoteParticipant({ identity: bobParticipantId }), - ]); + const connectionWithPublisher = new ConnectionManagerData(); - const connectionManagerData$ = epochMeWith$( - memberships$, - behavior("a", { - a: connectionWithPublisher, - }), - ); + const bobParticipantId = fallbackMemberId( + bobMembership.userId, + bobMembership.deviceId, + ); + const connectionA = { transport: transportA } as unknown as Connection; + const connectionB = { transport: transportB } as unknown as Connection; - const matrixLivekitMember$ = createMatrixLivekitMembers$({ - scope: testScope, - membershipsWithTransport$: testScope.behavior( - membershipsWithTransport$, - ), - connectionManager: { - connectionManagerData$: connectionManagerData$, - } as unknown as IConnectionManager, - }); + // Bob is not publishing on A + connectionWithPublisher.add(connectionA, []); + // Bob is publishing on B but his membership says A + connectionWithPublisher.add(connectionB, [ + mockRemoteParticipant({ identity: bobParticipantId }), + ]); - expectObservable(matrixLivekitMember$.pipe(map((e) => e.value))).toBe( - "a", - { - a: expect.toSatisfy((data: MatrixLivekitMember[]) => { - expect(data.length).toEqual(2); - expectObservable(data[0].membership$).toBe("a", { - a: bobMembership, - }); - expectObservable(data[0].connection$).toBe("a", { - // The real connection should be from transportA as per the membership - a: connectionA, - }); - expectObservable(data[0].participant$).toBe("a", { - a: expect.toSatisfy((participant) => { - expect(participant).toBeDefined(); - expect(participant!.identity).toEqual(bobParticipantId); - return true; - }), - }); - return true; - }), - }, - ); - }); + const connectionsWithPublisher$ = new BehaviorSubject( + connectionWithPublisher, + ); + const connectionManagerData$ = epochMeWith$( + memberships$, + connectionsWithPublisher$, + ); + + const matrixLivekitMember$ = createMatrixLivekitMembers$({ + scope: testScope, + membershipsWithTransport$: testScope.behavior(membershipsWithTransport$), + connectionManager: { + connectionManagerData$: connectionManagerData$, + } as unknown as IConnectionManager, }); - test("bob is publishing in the wrong connection", () => { - withTestScheduler(({ behavior, expectObservable }) => { - const { memberships$, membershipsWithTransport$ } = fromMemberships$( - behavior("a", { - a: [bobMembership, carlMembership], - }), - ); - - const connectionWithPublisher = new ConnectionManagerData(); - const bobParticipantId = getParticipantId( - bobMembership.userId, - bobMembership.deviceId, - ); - const connectionA = { transport: transportA } as unknown as Connection; - const connectionB = { transport: transportB } as unknown as Connection; - - // Bob is not publishing on A - connectionWithPublisher.add(connectionA, []); - // Bob is publishing on B but his membership says A - connectionWithPublisher.add(connectionB, [ - mockRemoteParticipant({ identity: bobParticipantId }), - ]); - - const connectionManagerData$ = epochMeWith$( - memberships$, - behavior("a", { - a: connectionWithPublisher, - }), - ); - - const matrixLivekitMember$ = createMatrixLivekitMembers$({ - scope: testScope, - membershipsWithTransport$: testScope.behavior( - membershipsWithTransport$, - ), - connectionManager: { - connectionManagerData$: connectionManagerData$, - } as unknown as IConnectionManager, - }); - - expectObservable(matrixLivekitMember$.pipe(map((e) => e.value))).toBe( - "a", - { - a: expect.toSatisfy((data: MatrixLivekitMember[]) => { - expect(data.length).toEqual(2); - expectObservable(data[0].membership$).toBe("a", { - a: bobMembership, - }); - expectObservable(data[0].connection$).toBe("a", { - // The real connection should be from transportA as per the membership - a: connectionA, - }); - expectObservable(data[0].participant$).toBe("a", { - // No participant as Bob is not publishing on his membership transport - a: null, - }); - return true; - }), - }, - ); - }); - }); + await flushPromises(); + expect(matrixLivekitMember$.value.value).toSatisfy( + (data: MatrixLivekitMember[]) => { + expect(data.length).toEqual(2); + expect(data[0].membership$.value).toBe(bobMembership); + expect(data[0].connection$.value).toBe(connectionA); + expect(data[0].participant$.value).toBe(null); + return true; + }, + ); }); diff --git a/src/state/CallViewModel/remoteMembers/MatrixLivekitMembers.ts b/src/state/CallViewModel/remoteMembers/MatrixLivekitMembers.ts index 79ad933c2..9c6a05c99 100644 --- a/src/state/CallViewModel/remoteMembers/MatrixLivekitMembers.ts +++ b/src/state/CallViewModel/remoteMembers/MatrixLivekitMembers.ts @@ -13,8 +13,11 @@ import { type LivekitTransport, type CallMembership, } from "matrix-js-sdk/lib/matrixrtc"; -import { combineLatest, filter, map } from "rxjs"; +import { combineLatest, filter, map, switchMap } from "rxjs"; import { logger as rootLogger } from "matrix-js-sdk/lib/logger"; +import { sha256 } from "matrix-js-sdk/lib/digest"; +import { encodeUnpaddedBase64Url } from "matrix-js-sdk"; +import { type CallMembershipIdentityParts } from "matrix-js-sdk/lib/matrixrtc/EncryptionManager"; import { type Behavior } from "../../Behavior"; import { type IConnectionManager } from "./ConnectionManager"; @@ -62,64 +65,89 @@ export function createMatrixLivekitMembers$({ membershipsWithTransport$, connectionManager, }: Props): Behavior> { + /** + * This internal observable is used to compute the async sha256 hash of the user's identity. + * a promise is treated like an observable. So we can switchMap on the promise from the identity computation. + * The last update to `membershipsWithTransport$` will always be the last promise we pass to switchMap. + * So we will eventually always end up with the latest memberships and their identities. + */ + const membershipsWithTransportAndLivekitIdentity$ = + membershipsWithTransport$.pipe( + switchMap(async (membershipsWithTransport) => { + const { value, epoch } = membershipsWithTransport; + const membershipsWithTransportAndLkIdentityPromises = value.map( + async (obj) => { + return computeLivekitParticipantIdentity( + obj.membership, + obj.membership.kind, + ); + }, + ); + const identities = await Promise.all( + membershipsWithTransportAndLkIdentityPromises, + ); + const membershipsWithTransportAndLkIdentity = value.map( + ({ transport, membership }, index) => { + return { transport, membership, identity: identities[index] }; + }, + ); + return new Epoch(membershipsWithTransportAndLkIdentity, epoch); + }), + ); + /** * Stream of all the call members and their associated livekit data (if available). */ - return scope.behavior( combineLatest([ - membershipsWithTransport$, + membershipsWithTransportAndLivekitIdentity$, connectionManager.connectionManagerData$, ]).pipe( filter((values) => values.every((value) => value.epoch === values[0].epoch), ), - map( - ([ - { value: membershipsWithTransports, epoch }, - { value: managerData }, - ]) => - new Epoch([membershipsWithTransports, managerData] as const, epoch), - ), + map(([x, y]) => new Epoch([x.value, y.value] as const, x.epoch)), generateItemsWithEpoch( // Generator function. // creates an array of `{key, data}[]` // Each change in the keys (new key, missing key) will result in a call to the factory function. - function* ([membershipsWithTransports, managerData]) { - for (const { membership, transport } of membershipsWithTransports) { - // TODO! cannot use membership.membershipID yet, Currently its hardcoded by the jwt service to - const participantId = /*membership.membershipID*/ `${membership.userId}:${membership.deviceId}`; - + function* ([membershipsWithTransportAndLivekitIdentity, managerData]) { + for (const { + membership, + transport, + identity, + } of membershipsWithTransportAndLivekitIdentity) { const participants = transport ? managerData.getParticipantForTransport(transport) : []; const participant = - participants.find((p) => p.identity == participantId) ?? null; + participants.find((p) => p.identity == identity) ?? null; const connection = transport ? managerData.getConnectionForTransport(transport) : null; yield { - keys: [participantId, membership.userId], + keys: [identity, membership.userId, membership.deviceId], data: { membership, participant, connection }, }; } }, // Each update where the key of the generator array do not change will result in updates to the `data$` observable in the factory. - (scope, data$, participantId, userId) => { + (scope, data$, identity, userId, deviceId) => { logger.debug( - `Generating member for participantId: ${participantId}, userId: ${userId}`, + `Generating member for livekitIdentity: ${identity}, userId:deviceId: ${userId}${deviceId}`, ); // will only get called once per `participantId, userId` pair. // updates to data$ and as a result to displayName$ and mxcAvatarUrl$ are more frequent. return { - participantId, + identity, userId, ...scope.splitBehavior(data$), }; }, ), ), + new Epoch([], -1), ); } @@ -136,3 +164,42 @@ export function areLivekitTransportsEqual( if (!t1 && !t2) return true; return false; } + +const livekitParticipantIdentityCache = new Map(); + +/** + * The string that is computed based on the membership and used for the computing the hash. + * `${userId}:${deviceId}:${membershipID}` + * as the direct imput for: await sha256(input) + */ +export const livekitIdentityInput = ({ + userId, + deviceId, + memberId, +}: CallMembershipIdentityParts): string => `${userId}|${deviceId}|${memberId}`; + +export async function computeLivekitParticipantIdentity( + membership: CallMembershipIdentityParts, + kind: "rtc" | "session", +): Promise { + switch (kind) { + case "rtc": { + const input = livekitIdentityInput(membership); + if (livekitParticipantIdentityCache.size > 400) + // prevent memory leaks in a stupid/simple way + livekitParticipantIdentityCache.clear(); + // TODO use non deprecated memberId + if (livekitParticipantIdentityCache.has(input)) + return livekitParticipantIdentityCache.get(input)!; + else { + const hashBuffer = await sha256(input); + const hashedString = encodeUnpaddedBase64Url(hashBuffer); + livekitParticipantIdentityCache.set(input, hashedString); + return hashedString; + } + } + case "session": + default: + return `${membership.userId}:${membership.deviceId}`; + } +} diff --git a/yarn.lock b/yarn.lock index 94b731302..707a64807 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2795,10 +2795,10 @@ __metadata: languageName: node linkType: hard -"@matrix-org/matrix-sdk-crypto-wasm@npm:^15.3.0": - version: 15.3.0 - resolution: "@matrix-org/matrix-sdk-crypto-wasm@npm:15.3.0" - checksum: 10c0/45628f36b7b0e54a8777ae67a7233dbdf3e3cf14e0d95d21f62f89a7ea7e3f907232f1eb7b1262193b1e227759fad47af829dcccc103ded89011f13c66f01d76 +"@matrix-org/matrix-sdk-crypto-wasm@npm:^16.0.0": + version: 16.0.0 + resolution: "@matrix-org/matrix-sdk-crypto-wasm@npm:16.0.0" + checksum: 10c0/13b4ede3e618da819957abff778afefcf3baf9a2faac04a36bb5a07a44fae2ea05fbfa072eb3408d48b2b7b9aaf27242ce52c594c8ce9bf1fb8b3aade2832be1 languageName: node linkType: hard @@ -6571,24 +6571,10 @@ __metadata: languageName: node linkType: hard -"caniuse-lite@npm:^1.0.30001688": - version: 1.0.30001701 - resolution: "caniuse-lite@npm:1.0.30001701" - checksum: 10c0/a814bd4dd8b49645ca51bc6ee42120660a36394bb54eb6084801d3f2bbb9471e5e1a9a8a25f44f83086a032d46e66b33031e2aa345f699b90a7e84a9836b819c - languageName: node - linkType: hard - -"caniuse-lite@npm:^1.0.30001702": - version: 1.0.30001720 - resolution: "caniuse-lite@npm:1.0.30001720" - checksum: 10c0/ba9f963364ec4bfc8359d15d7e2cf365185fa1fddc90b4f534c71befedae9b3dd0cd2583a25ffc168a02d7b61b6c18b59bda0a1828ea2a5250fd3e35c2c049e9 - languageName: node - linkType: hard - -"caniuse-lite@npm:^1.0.30001726": - version: 1.0.30001726 - resolution: "caniuse-lite@npm:1.0.30001726" - checksum: 10c0/2c5f91da7fd9ebf8c6b432818b1498ea28aca8de22b30dafabe2a2a6da1e014f10e67e14f8e68e872a0867b6b4cd6001558dde04e3ab9770c9252ca5c8849d0e +"caniuse-lite@npm:^1.0.30001688, caniuse-lite@npm:^1.0.30001702, caniuse-lite@npm:^1.0.30001726": + version: 1.0.30001760 + resolution: "caniuse-lite@npm:1.0.30001760" + checksum: 10c0/cee26dff5c5b15ba073ab230200e43c0d4e88dc3bac0afe0c9ab963df70aaa876c3e513dde42a027f317136bf6e274818d77b073708b74c5807dfad33c029d3c languageName: node linkType: hard @@ -7547,7 +7533,7 @@ __metadata: livekit-client: "npm:^2.13.0" lodash-es: "npm:^4.17.21" loglevel: "npm:^1.9.1" - matrix-js-sdk: "npm:^39.2.0" + matrix-js-sdk: "github:matrix-org/matrix-js-sdk#head=toger5/use-membershipID-for-session-state-events&commit=f5f1b8efb46b3d55a7eebfabb4a61496640b8b00" matrix-widget-api: "npm:^1.14.0" normalize.css: "npm:^8.0.1" observable-hooks: "npm:^4.2.3" @@ -10352,12 +10338,12 @@ __metadata: languageName: node linkType: hard -"matrix-js-sdk@npm:^39.2.0": - version: 39.2.0 - resolution: "matrix-js-sdk@npm:39.2.0" +"matrix-js-sdk@github:matrix-org/matrix-js-sdk#head=toger5/use-membershipID-for-session-state-events&commit=f5f1b8efb46b3d55a7eebfabb4a61496640b8b00": + version: 39.3.0 + resolution: "matrix-js-sdk@https://github.com/matrix-org/matrix-js-sdk.git#commit=f5f1b8efb46b3d55a7eebfabb4a61496640b8b00" dependencies: "@babel/runtime": "npm:^7.12.5" - "@matrix-org/matrix-sdk-crypto-wasm": "npm:^15.3.0" + "@matrix-org/matrix-sdk-crypto-wasm": "npm:^16.0.0" another-json: "npm:^0.2.0" bs58: "npm:^6.0.0" content-type: "npm:^1.0.4" @@ -10370,7 +10356,7 @@ __metadata: sdp-transform: "npm:^3.0.0" unhomoglyph: "npm:^1.0.6" uuid: "npm:13" - checksum: 10c0/f8b5261de2744305330ba3952821ca9303698170bfd3a0ff8a767b9286d4e8d4ed5aaf6fbaf8a1e8ff9dbd859102a2a47d882787e2da3b3078965bec00157959 + checksum: 10c0/9607b0c063c873a24c1a2d05cc7500d60c32556ec82b666ebaae5c5e829faf5bb7639780efddea7211e6b9873098bd53b97656f041e932e8b0de0c208ccabbff languageName: node linkType: hard From 00d4b8e985db7b9546d584610a777ef6a4a0e9f5 Mon Sep 17 00:00:00 2001 From: Robin Date: Mon, 15 Dec 2025 12:52:23 -0500 Subject: [PATCH 100/748] Use a more suitable filter operator to compute local member --- src/state/CallViewModel/CallViewModel.ts | 27 +++++++++--------- src/utils/observable.test.ts | 35 ++++++++++++++++++++++-- src/utils/observable.ts | 23 ++++++++++++++++ 3 files changed, 69 insertions(+), 16 deletions(-) diff --git a/src/state/CallViewModel/CallViewModel.ts b/src/state/CallViewModel/CallViewModel.ts index f4f817763..f54fc9f53 100644 --- a/src/state/CallViewModel/CallViewModel.ts +++ b/src/state/CallViewModel/CallViewModel.ts @@ -52,7 +52,12 @@ import { ScreenShareViewModel, type UserMediaViewModel, } from "../MediaViewModel"; -import { accumulate, generateItems, pauseWhen } from "../../utils/observable"; +import { + accumulate, + filterBehavior, + generateItems, + pauseWhen, +} from "../../utils/observable"; import { duplicateTiles, MatrixRTCMode, @@ -505,16 +510,13 @@ export function createCallViewModel$( ), ); - const localMatrixLivekitMember$ = - scope.behavior | null>( + const localMatrixLivekitMember$: Behavior | null> = + scope.behavior( localRtcMembership$.pipe( - generateItems( - // Generate a local member when membership is non-null - function* (membership) { - if (membership !== null) - yield { keys: ["local"], data: membership }; - }, - (_scope, membership$) => ({ + filterBehavior((membership) => membership !== null), + map((membership$) => { + if (membership$ === null) return null; + return { membership$, participant: { type: "local" as const, @@ -522,9 +524,8 @@ export function createCallViewModel$( }, connection$: localMembership.connection$, userId, - }), - ), - map(([localMember]) => localMember ?? null), + }; + }), ), ); diff --git a/src/utils/observable.test.ts b/src/utils/observable.test.ts index d1034e7b8..be6773675 100644 --- a/src/utils/observable.test.ts +++ b/src/utils/observable.test.ts @@ -5,11 +5,12 @@ SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial Please see LICENSE in the repository root for full details. */ -import { test } from "vitest"; -import { Subject } from "rxjs"; +import { expect, test } from "vitest"; +import { type Observable, of, Subject, switchMap } from "rxjs"; import { withTestScheduler } from "./test"; -import { generateItems, pauseWhen } from "./observable"; +import { filterBehavior, generateItems, pauseWhen } from "./observable"; +import { type Behavior } from "../state/Behavior"; test("pauseWhen", () => { withTestScheduler(({ behavior, expectObservable }) => { @@ -72,3 +73,31 @@ test("generateItems", () => { expectObservable(scope4$).toBe(scope4Marbles); }); }); + +test("filterBehavior", () => { + withTestScheduler(({ behavior, expectObservable }) => { + // Filtering the input should segment it into 2 modes of non-null behavior. + const inputMarbles = " abcxabx"; + const filteredMarbles = "a--xa-x"; + + const input$ = behavior(inputMarbles, { + a: "a", + b: "b", + c: "c", + x: null, + }); + const filtered$: Observable | null> = input$.pipe( + filterBehavior((value) => typeof value === "string"), + ); + + expectObservable(filtered$).toBe(filteredMarbles, { + a: expect.any(Object), + x: null, + }); + expectObservable( + filtered$.pipe( + switchMap((value$) => (value$ === null ? of(null) : value$)), + ), + ).toBe(inputMarbles, { a: "a", b: "b", c: "c", x: null }); + }); +}); diff --git a/src/utils/observable.ts b/src/utils/observable.ts index 053921cd3..a6dafea3f 100644 --- a/src/utils/observable.ts +++ b/src/utils/observable.ts @@ -22,6 +22,7 @@ import { withLatestFrom, BehaviorSubject, type OperatorFunction, + distinctUntilChanged, } from "rxjs"; import { type Behavior } from "../state/Behavior"; @@ -185,6 +186,28 @@ export function generateItemsWithEpoch< ); } +/** + * Segments a behavior into periods during which its value matches the filter + * (outputting a behavior with a narrowed type) and periods during which it does + * not match (outputting null). + */ +export function filterBehavior( + predicate: (value: T) => value is S, +): OperatorFunction | null> { + return (input$) => + input$.pipe( + scan | null>((acc$, input) => { + if (predicate(input)) { + const output$ = acc$ ?? new BehaviorSubject(input); + output$.next(input); + return output$; + } + return null; + }, null), + distinctUntilChanged(), + ); +} + function generateItemsInternal< Input, Keys extends [unknown, ...unknown[]], From 8a18e70e20561dc6e9e7e0464c985509adc70076 Mon Sep 17 00:00:00 2001 From: Robin Date: Mon, 15 Dec 2025 13:14:45 -0500 Subject: [PATCH 101/748] Split MatrixLivekitMembers more verbosely into two types --- src/state/CallViewModel/CallViewModel.ts | 14 +++--- .../MatrixLivekitMembers.test.ts | 12 ++--- .../remoteMembers/MatrixLivekitMembers.ts | 46 ++++++++++++------- .../remoteMembers/integration.test.ts | 8 ++-- 4 files changed, 46 insertions(+), 34 deletions(-) diff --git a/src/state/CallViewModel/CallViewModel.ts b/src/state/CallViewModel/CallViewModel.ts index f54fc9f53..55a1368e2 100644 --- a/src/state/CallViewModel/CallViewModel.ts +++ b/src/state/CallViewModel/CallViewModel.ts @@ -116,7 +116,7 @@ import { createConnectionManager$ } from "./remoteMembers/ConnectionManager.ts"; import { createMatrixLivekitMembers$, type TaggedParticipant, - type MatrixLivekitMember, + type LocalMatrixLivekitMember, } from "./remoteMembers/MatrixLivekitMembers.ts"; import { type AutoLeaveReason, @@ -510,7 +510,7 @@ export function createCallViewModel$( ), ); - const localMatrixLivekitMember$: Behavior | null> = + const localMatrixLivekitMember$: Behavior = scope.behavior( localRtcMembership$.pipe( filterBehavior((membership) => membership !== null), @@ -682,10 +682,8 @@ export function createCallViewModel$( let localParticipantId: string | undefined = undefined; // add local member if available if (localMatrixLivekitMember) { - const { userId, connection$, membership$ } = + const { userId, participant, connection$, membership$ } = localMatrixLivekitMember; - const participant: TaggedParticipant = - localMatrixLivekitMember.participant; // Widen the type localParticipantId = `${userId}:${membership$.value.deviceId}`; // should be membership$.value.membershipID which is not optional // const participantId = membership$.value.membershipID; if (localParticipantId) { @@ -695,7 +693,7 @@ export function createCallViewModel$( dup, localParticipantId, userId, - participant, + participant satisfies TaggedParticipant as TaggedParticipant, // Widen the type safely connection$, ], data: undefined, @@ -727,7 +725,7 @@ export function createCallViewModel$( dup, participantId, userId, - participant$, + participant, connection$, ) => { const livekitRoom$ = scope.behavior( @@ -746,7 +744,7 @@ export function createCallViewModel$( scope, `${participantId}:${dup}`, userId, - participant$, + participant, options.encryptionSystem, livekitRoom$, focusUrl$, diff --git a/src/state/CallViewModel/remoteMembers/MatrixLivekitMembers.test.ts b/src/state/CallViewModel/remoteMembers/MatrixLivekitMembers.test.ts index 195078e0e..77c000157 100644 --- a/src/state/CallViewModel/remoteMembers/MatrixLivekitMembers.test.ts +++ b/src/state/CallViewModel/remoteMembers/MatrixLivekitMembers.test.ts @@ -15,7 +15,7 @@ import { combineLatest, map, type Observable } from "rxjs"; import { type IConnectionManager } from "./ConnectionManager.ts"; import { - type MatrixLivekitMember, + type RemoteMatrixLivekitMember, createMatrixLivekitMembers$, } from "./MatrixLivekitMembers.ts"; import { @@ -100,7 +100,7 @@ test("should signal participant not yet connected to livekit", () => { }); expectObservable(matrixLivekitMember$.pipe(map((e) => e.value))).toBe("a", { - a: expect.toSatisfy((data: MatrixLivekitMember<"remote">[]) => { + a: expect.toSatisfy((data: RemoteMatrixLivekitMember[]) => { expect(data.length).toEqual(1); expectObservable(data[0].membership$).toBe("a", { a: bobMembership, @@ -180,7 +180,7 @@ test("should signal participant on a connection that is publishing", () => { }); expectObservable(matrixLivekitMember$.pipe(map((e) => e.value))).toBe("a", { - a: expect.toSatisfy((data: MatrixLivekitMember<"remote">[]) => { + a: expect.toSatisfy((data: RemoteMatrixLivekitMember[]) => { expect(data.length).toEqual(1); expectObservable(data[0].membership$).toBe("a", { a: bobMembership, @@ -231,7 +231,7 @@ test("should signal participant on a connection that is not publishing", () => { }); expectObservable(matrixLivekitMember$.pipe(map((e) => e.value))).toBe("a", { - a: expect.toSatisfy((data: MatrixLivekitMember<"remote">[]) => { + a: expect.toSatisfy((data: RemoteMatrixLivekitMember[]) => { expect(data.length).toEqual(1); expectObservable(data[0].membership$).toBe("a", { a: bobMembership, @@ -296,7 +296,7 @@ describe("Publication edge case", () => { expectObservable(matrixLivekitMember$.pipe(map((e) => e.value))).toBe( "a", { - a: expect.toSatisfy((data: MatrixLivekitMember<"remote">[]) => { + a: expect.toSatisfy((data: RemoteMatrixLivekitMember[]) => { expect(data.length).toEqual(2); expectObservable(data[0].membership$).toBe("a", { a: bobMembership, @@ -362,7 +362,7 @@ describe("Publication edge case", () => { expectObservable(matrixLivekitMember$.pipe(map((e) => e.value))).toBe( "a", { - a: expect.toSatisfy((data: MatrixLivekitMember<"remote">[]) => { + a: expect.toSatisfy((data: RemoteMatrixLivekitMember[]) => { expect(data.length).toEqual(2); expectObservable(data[0].membership$).toBe("a", { a: bobMembership, diff --git a/src/state/CallViewModel/remoteMembers/MatrixLivekitMembers.ts b/src/state/CallViewModel/remoteMembers/MatrixLivekitMembers.ts index 67146facf..4cca0d5b2 100644 --- a/src/state/CallViewModel/remoteMembers/MatrixLivekitMembers.ts +++ b/src/state/CallViewModel/remoteMembers/MatrixLivekitMembers.ts @@ -21,30 +21,44 @@ import { generateItemsWithEpoch } from "../../../utils/observable"; const logger = rootLogger.getChild("[MatrixLivekitMembers]"); -/** - * A dynamic participant value with a static tag to tell what kind of - * participant it can be (local vs. remote). - */ +interface LocalTaggedParticipant { + type: "local"; + value$: Behavior; +} +interface RemoteTaggedParticipant { + type: "remote"; + value$: Behavior; +} export type TaggedParticipant = - | { type: "local"; value$: Behavior } - | { type: "remote"; value$: Behavior }; + | LocalTaggedParticipant + | RemoteTaggedParticipant; -/** - * Represents a Matrix call member and their associated LiveKit participation. - * `livekitParticipant` can be undefined if the member is not yet connected to the livekit room - * or if it has no livekit transport at all. - */ -export interface MatrixLivekitMember< - ParticipantType extends TaggedParticipant["type"], -> { +interface MatrixLivekitMember { membership$: Behavior; - participant: TaggedParticipant & { type: ParticipantType }; connection$: Behavior; // participantId: string; We do not want a participantId here since it will be generated by the jwt // TODO decide if we can also drop the userId. Its in the matrix membership anyways. userId: string; } +/** + * Represents the local Matrix call member and their associated LiveKit participation. + * `livekitParticipant` can be null if the member is not yet connected to the livekit room + * or if it has no livekit transport at all. + */ +export interface LocalMatrixLivekitMember extends MatrixLivekitMember { + participant: LocalTaggedParticipant; +} + +/** + * Represents a remote Matrix call member and their associated LiveKit participation. + * `livekitParticipant` can be null if the member is not yet connected to the livekit room + * or if it has no livekit transport at all. + */ +export interface RemoteMatrixLivekitMember extends MatrixLivekitMember { + participant: RemoteTaggedParticipant; +} + interface Props { scope: ObservableScope; membershipsWithTransport$: Behavior< @@ -66,7 +80,7 @@ export function createMatrixLivekitMembers$({ scope, membershipsWithTransport$, connectionManager, -}: Props): Behavior[]>> { +}: Props): Behavior> { /** * Stream of all the call members and their associated livekit data (if available). */ diff --git a/src/state/CallViewModel/remoteMembers/integration.test.ts b/src/state/CallViewModel/remoteMembers/integration.test.ts index 34b62dadb..2c3591a5c 100644 --- a/src/state/CallViewModel/remoteMembers/integration.test.ts +++ b/src/state/CallViewModel/remoteMembers/integration.test.ts @@ -29,7 +29,7 @@ import { type ProcessorState } from "../../../livekit/TrackProcessorContext.tsx" import { areLivekitTransportsEqual, createMatrixLivekitMembers$, - type MatrixLivekitMember, + type RemoteMatrixLivekitMember, } from "./MatrixLivekitMembers.ts"; import { createConnectionManager$ } from "./ConnectionManager.ts"; import { membershipsAndTransports$ } from "../../SessionBehaviors.ts"; @@ -132,7 +132,7 @@ test("bob, carl, then bob joining no tracks yet", () => { }); expectObservable(matrixLivekitItems$).toBe(vMarble, { - a: expect.toSatisfy((e: Epoch[]>) => { + a: expect.toSatisfy((e: Epoch) => { const items = e.value; expect(items.length).toBe(1); const item = items[0]!; @@ -152,7 +152,7 @@ test("bob, carl, then bob joining no tracks yet", () => { }); return true; }), - b: expect.toSatisfy((e: Epoch[]>) => { + b: expect.toSatisfy((e: Epoch) => { const items = e.value; expect(items.length).toBe(2); @@ -189,7 +189,7 @@ test("bob, carl, then bob joining no tracks yet", () => { } return true; }), - c: expect.toSatisfy((e: Epoch[]>) => { + c: expect.toSatisfy((e: Epoch) => { const items = e.value; expect(items.length).toBe(3); From 5bc6ed5885c8de4220f7542fe4382c727c03629f Mon Sep 17 00:00:00 2001 From: Timo K Date: Mon, 15 Dec 2025 20:17:57 +0100 Subject: [PATCH 102/748] small refactor to make it testable. --- src/room/CallEventAudioRenderer.test.tsx | 8 +++ src/room/InCallView.test.tsx | 10 ++- src/state/CallViewModel/CallViewModel.test.ts | 22 +++++-- .../LivekitParticipantIdentity.ts | 53 +++++++++++++++ .../MatrixLivekitMembers.test.ts | 1 - .../remoteMembers/MatrixLivekitMembers.ts | 66 ++++--------------- .../remoteMembers/integration.test.ts | 6 ++ src/utils/test.ts | 28 +++++++- 8 files changed, 134 insertions(+), 60 deletions(-) create mode 100644 src/state/CallViewModel/remoteMembers/LivekitParticipantIdentity.ts diff --git a/src/room/CallEventAudioRenderer.test.tsx b/src/room/CallEventAudioRenderer.test.tsx index 733346ebb..38f56b14d 100644 --- a/src/room/CallEventAudioRenderer.test.tsx +++ b/src/room/CallEventAudioRenderer.test.tsx @@ -23,6 +23,7 @@ import { import { exampleTransport, + mockComputeLivekitParticipantIdentity$, mockMatrixRoomMember, mockRtcMembership, } from "../utils/test"; @@ -47,6 +48,13 @@ vitest.mock("../rtcSessionHelpers", async (importOriginal) => ({ ...(await importOriginal()), makeTransport: (): [LivekitTransport] => [exampleTransport], })); +vitest.mock( + import("../state/CallViewModel/remoteMembers/LivekitParticipantIdentity.ts"), + async (importOriginal) => ({ + ...(await importOriginal()), + computeLivekitParticipantIdentity$: mockComputeLivekitParticipantIdentity$, + }), +); afterEach(() => { vitest.clearAllMocks(); diff --git a/src/room/InCallView.test.tsx b/src/room/InCallView.test.tsx index a137074b1..cd0af5470 100644 --- a/src/room/InCallView.test.tsx +++ b/src/room/InCallView.test.tsx @@ -22,8 +22,8 @@ import { BrowserRouter } from "react-router-dom"; import { TooltipProvider } from "@vector-im/compound-web"; import { RoomContext, useLocalParticipant } from "@livekit/components-react"; -import { InCallView } from "./InCallView"; import { + mockComputeLivekitParticipantIdentity$, mockLivekitRoom, mockLocalParticipant, mockMatrixRoom, @@ -34,6 +34,7 @@ import { mockRtcMembership, type MockRTCSession, } from "../utils/test"; +import { InCallView } from "./InCallView"; import { E2eeType } from "../e2ee/e2eeType"; import { getBasicCallViewModelEnvironment } from "../utils/test-viewmodel"; import { alice, local } from "../utils/test-fixtures"; @@ -61,6 +62,13 @@ vi.mock("../livekit/MatrixAudioRenderer"); vi.mock("react-use-measure", () => ({ default: (): [() => void, object] => [(): void => {}, {}], })); +vi.mock( + import("../state/CallViewModel/remoteMembers/LivekitParticipantIdentity.ts"), + async (importOriginal) => ({ + ...(await importOriginal()), + computeLivekitParticipantIdentity$: mockComputeLivekitParticipantIdentity$, + }), +); const localRtcMember = mockRtcMembership("@carol:example.org", "CCCC"); const localParticipant = mockLocalParticipant({ diff --git a/src/state/CallViewModel/CallViewModel.test.ts b/src/state/CallViewModel/CallViewModel.test.ts index be598702b..58814bbe3 100644 --- a/src/state/CallViewModel/CallViewModel.test.ts +++ b/src/state/CallViewModel/CallViewModel.test.ts @@ -44,6 +44,7 @@ import { mockRtcMembership, testScope, exampleTransport, + mockComputeLivekitParticipantIdentity$, } from "../../utils/test.ts"; import { E2eeType } from "../../e2ee/e2eeType.ts"; import { @@ -77,11 +78,22 @@ vi.mock("../e2ee/matrixKeyProvider"); const getUrlParams = vi.hoisted(() => vi.fn(() => ({}))); vi.mock("../UrlParams", () => ({ getUrlParams })); -vi.mock("../rtcSessionHelpers", async (importOriginal) => ({ - ...(await importOriginal()), - makeTransport: async (): Promise => - Promise.resolve(exampleTransport), -})); +vi.mock( + "../state/CallViewModel/localMember/localTransport", + async (importOriginal) => ({ + ...(await importOriginal()), + makeTransport: async (): Promise => + Promise.resolve(exampleTransport), + }), +); + +vi.mock( + import("./remoteMembers/LivekitParticipantIdentity.ts"), + async (importOriginal) => ({ + ...(await importOriginal()), + computeLivekitParticipantIdentity$: mockComputeLivekitParticipantIdentity$, + }), +); const yesNo = { y: true, diff --git a/src/state/CallViewModel/remoteMembers/LivekitParticipantIdentity.ts b/src/state/CallViewModel/remoteMembers/LivekitParticipantIdentity.ts new file mode 100644 index 000000000..e43d0bd1b --- /dev/null +++ b/src/state/CallViewModel/remoteMembers/LivekitParticipantIdentity.ts @@ -0,0 +1,53 @@ +/* +Copyright 2025 New Vector Ltd. + +SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial +Please see LICENSE in the repository root for full details. +*/ + +import { encodeUnpaddedBase64Url } from "matrix-js-sdk"; +import { sha256 } from "matrix-js-sdk/lib/digest"; +import { type CallMembershipIdentityParts } from "matrix-js-sdk/lib/matrixrtc/EncryptionManager"; +import { from, type Observable } from "rxjs"; + +const livekitParticipantIdentityCache = new Map(); + +/** + * The string that is computed based on the membership and used for the computing the hash. + * `${userId}:${deviceId}:${membershipID}` + * as the direct imput for: await sha256(input) + */ +export const livekitIdentityInput = ({ + userId, + deviceId, + memberId, +}: CallMembershipIdentityParts): string => `${userId}|${deviceId}|${memberId}`; + +export function computeLivekitParticipantIdentity$( + membership: CallMembershipIdentityParts, + kind: "rtc" | "session", +): Observable { + const compute = async (): Promise => { + switch (kind) { + case "rtc": { + const input = livekitIdentityInput(membership); + if (livekitParticipantIdentityCache.size > 400) + // prevent memory leaks in a stupid/simple way + livekitParticipantIdentityCache.clear(); + // TODO use non deprecated memberId + if (livekitParticipantIdentityCache.has(input)) + return livekitParticipantIdentityCache.get(input)!; + else { + const hashBuffer = await sha256(input); + const hashedString = encodeUnpaddedBase64Url(hashBuffer); + livekitParticipantIdentityCache.set(input, hashedString); + return hashedString; + } + } + case "session": + default: + return `${membership.userId}:${membership.deviceId}`; + } + }; + return from(compute()); +} diff --git a/src/state/CallViewModel/remoteMembers/MatrixLivekitMembers.test.ts b/src/state/CallViewModel/remoteMembers/MatrixLivekitMembers.test.ts index c2e60798f..68a67546a 100644 --- a/src/state/CallViewModel/remoteMembers/MatrixLivekitMembers.test.ts +++ b/src/state/CallViewModel/remoteMembers/MatrixLivekitMembers.test.ts @@ -28,7 +28,6 @@ import { flushPromises, mockCallMembership, mockRemoteParticipant, - withTestScheduler, } from "../../../utils/test.ts"; import { type Connection } from "./Connection.ts"; import { constant } from "../../Behavior.ts"; diff --git a/src/state/CallViewModel/remoteMembers/MatrixLivekitMembers.ts b/src/state/CallViewModel/remoteMembers/MatrixLivekitMembers.ts index 9c6a05c99..30abfc9bb 100644 --- a/src/state/CallViewModel/remoteMembers/MatrixLivekitMembers.ts +++ b/src/state/CallViewModel/remoteMembers/MatrixLivekitMembers.ts @@ -15,15 +15,13 @@ import { } from "matrix-js-sdk/lib/matrixrtc"; import { combineLatest, filter, map, switchMap } from "rxjs"; import { logger as rootLogger } from "matrix-js-sdk/lib/logger"; -import { sha256 } from "matrix-js-sdk/lib/digest"; -import { encodeUnpaddedBase64Url } from "matrix-js-sdk"; -import { type CallMembershipIdentityParts } from "matrix-js-sdk/lib/matrixrtc/EncryptionManager"; import { type Behavior } from "../../Behavior"; import { type IConnectionManager } from "./ConnectionManager"; import { Epoch, type ObservableScope } from "../../ObservableScope"; import { type Connection } from "./Connection"; import { generateItemsWithEpoch } from "../../../utils/observable"; +import { computeLivekitParticipantIdentity$ } from "./LivekitParticipantIdentity"; const logger = rootLogger.getChild("[MatrixLivekitMembers]"); @@ -73,25 +71,28 @@ export function createMatrixLivekitMembers$({ */ const membershipsWithTransportAndLivekitIdentity$ = membershipsWithTransport$.pipe( - switchMap(async (membershipsWithTransport) => { + switchMap((membershipsWithTransport) => { const { value, epoch } = membershipsWithTransport; const membershipsWithTransportAndLkIdentityPromises = value.map( - async (obj) => { - return computeLivekitParticipantIdentity( + (obj) => { + return computeLivekitParticipantIdentity$( obj.membership, obj.membership.kind, ); }, ); - const identities = await Promise.all( + return combineLatest( membershipsWithTransportAndLkIdentityPromises, + ).pipe( + map((identities) => { + const membershipsWithTransportAndLkIdentity = value.map( + ({ transport, membership }, index) => { + return { transport, membership, identity: identities[index] }; + }, + ); + return new Epoch(membershipsWithTransportAndLkIdentity, epoch); + }), ); - const membershipsWithTransportAndLkIdentity = value.map( - ({ transport, membership }, index) => { - return { transport, membership, identity: identities[index] }; - }, - ); - return new Epoch(membershipsWithTransportAndLkIdentity, epoch); }), ); @@ -164,42 +165,3 @@ export function areLivekitTransportsEqual( if (!t1 && !t2) return true; return false; } - -const livekitParticipantIdentityCache = new Map(); - -/** - * The string that is computed based on the membership and used for the computing the hash. - * `${userId}:${deviceId}:${membershipID}` - * as the direct imput for: await sha256(input) - */ -export const livekitIdentityInput = ({ - userId, - deviceId, - memberId, -}: CallMembershipIdentityParts): string => `${userId}|${deviceId}|${memberId}`; - -export async function computeLivekitParticipantIdentity( - membership: CallMembershipIdentityParts, - kind: "rtc" | "session", -): Promise { - switch (kind) { - case "rtc": { - const input = livekitIdentityInput(membership); - if (livekitParticipantIdentityCache.size > 400) - // prevent memory leaks in a stupid/simple way - livekitParticipantIdentityCache.clear(); - // TODO use non deprecated memberId - if (livekitParticipantIdentityCache.has(input)) - return livekitParticipantIdentityCache.get(input)!; - else { - const hashBuffer = await sha256(input); - const hashedString = encodeUnpaddedBase64Url(hashBuffer); - livekitParticipantIdentityCache.set(input, hashedString); - return hashedString; - } - } - case "session": - default: - return `${membership.userId}:${membership.deviceId}`; - } -} diff --git a/src/state/CallViewModel/remoteMembers/integration.test.ts b/src/state/CallViewModel/remoteMembers/integration.test.ts index e3aa6be8d..3ad81fa8a 100644 --- a/src/state/CallViewModel/remoteMembers/integration.test.ts +++ b/src/state/CallViewModel/remoteMembers/integration.test.ts @@ -22,6 +22,7 @@ import { ECConnectionFactory } from "./ConnectionFactory.ts"; import { type OpenIDClientParts } from "../../../livekit/openIDSFU.ts"; import { mockCallMembership, + mockComputeLivekitParticipantIdentity$, mockMediaDevices, withTestScheduler, } from "../../../utils/test.ts"; @@ -43,6 +44,11 @@ let lkRoomFactory: () => LivekitRoom; const createdMockLivekitRooms: Map = new Map(); +vi.mock(import("./LivekitParticipantIdentity.ts"), async (importOriginal) => ({ + ...(await importOriginal()), + computeLivekitParticipantIdentity$: mockComputeLivekitParticipantIdentity$, +})); + beforeEach(() => { testScope = new ObservableScope(); mockClient = { diff --git a/src/utils/test.ts b/src/utils/test.ts index bd7dcd6f4..28fc85463 100644 --- a/src/utils/test.ts +++ b/src/utils/test.ts @@ -15,6 +15,7 @@ import { vitest, } from "vitest"; import { + encodeUnpaddedBase64, MatrixEvent, type Room as MatrixRoom, type Room, @@ -43,13 +44,14 @@ import { type Room as LivekitRoom, Track, } from "livekit-client"; -import { randomUUID } from "crypto"; +import { createHash, randomUUID } from "crypto"; import { type TrackReference } from "@livekit/components-core"; import EventEmitter from "events"; import { type KeyTransportEvents, type KeyTransportEventsHandlerMap, } from "matrix-js-sdk/lib/matrixrtc/IKeyTransport"; +import { type CallMembershipIdentityParts } from "matrix-js-sdk/lib/matrixrtc/EncryptionManager"; import { LocalUserMediaViewModel, @@ -522,3 +524,27 @@ export function mockMuteStates( const observableScope = new ObservableScope(); return new MuteStates(observableScope, mockMediaDevices({}), joined$); } + +export const mockComputeLivekitParticipantIdentity$ = ( + membership: CallMembershipIdentityParts, + kind: "rtc" | "session", +): Observable => { + function sha256(commitmentStr: string): string { + return encodeUnpaddedBase64( + createHash("sha256").update(commitmentStr, "utf8").digest(), + ); + } + let hash; + switch (kind) { + case "rtc": { + hash = sha256( + `${membership.userId}|${membership.deviceId}|${membership.memberId}`, + ); + break; + } + case "session": + default: + hash = `${membership.userId}:${membership.deviceId}`; + } + return of(hash); +}; From 15a12b2d9c0eda53fd60a0be424b992965d6ba5d Mon Sep 17 00:00:00 2001 From: Robin Date: Mon, 15 Dec 2025 14:22:20 -0500 Subject: [PATCH 103/748] Make layout tests more concise --- src/state/CallViewModel/LayoutSwitch.test.ts | 267 ++++++------------- 1 file changed, 87 insertions(+), 180 deletions(-) diff --git a/src/state/CallViewModel/LayoutSwitch.test.ts b/src/state/CallViewModel/LayoutSwitch.test.ts index ae5a3896e..a0d2d8c3b 100644 --- a/src/state/CallViewModel/LayoutSwitch.test.ts +++ b/src/state/CallViewModel/LayoutSwitch.test.ts @@ -5,198 +5,105 @@ SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial Please see LICENSE in the repository root for full details. */ -import { afterEach, beforeEach, describe, expect, test } from "vitest"; -import { firstValueFrom, of } from "rxjs"; +import { describe, test } from "vitest"; import { createLayoutModeSwitch } from "./LayoutSwitch"; -import { ObservableScope } from "../ObservableScope"; -import { constant } from "../Behavior"; -import { withTestScheduler } from "../../utils/test"; +import { testScope, withTestScheduler } from "../../utils/test"; -let scope: ObservableScope; -beforeEach(() => { - scope = new ObservableScope(); -}); -afterEach(() => { - scope.end(); -}); - -describe("Default mode", () => { - test("Should be in grid layout by default", async () => { - const { gridMode$ } = createLayoutModeSwitch( - scope, - constant("normal"), - of(false), - ); - - const mode = await firstValueFrom(gridMode$); - expect(mode).toBe("grid"); - }); - - test("Should switch to spotlight mode when window mode is flat", async () => { - const { gridMode$ } = createLayoutModeSwitch( - scope, - constant("flat"), - of(false), - ); - - const mode = await firstValueFrom(gridMode$); - expect(mode).toBe("spotlight"); - }); -}); - -test("Should allow switching modes manually", () => { - withTestScheduler(({ cold, behavior, expectObservable, schedule }): void => { +function testLayoutSwitch({ + windowMode = "n", + hasScreenShares = "n", + userSelection = "", + expectedGridMode, +}: { + windowMode?: string; + hasScreenShares?: string; + userSelection?: string; + expectedGridMode: string; +}): void { + withTestScheduler(({ behavior, schedule, expectObservable }) => { const { gridMode$, setGridMode } = createLayoutModeSwitch( - scope, - behavior("n", { n: "normal" }), - cold("f", { f: false, t: true }), + testScope(), + behavior(windowMode, { n: "normal", N: "narrow", f: "flat" }), + behavior(hasScreenShares, { y: true, n: false }), ); - - schedule("--sgs", { - s: () => setGridMode("spotlight"), - g: () => setGridMode("grid"), - }); - - expectObservable(gridMode$).toBe("g-sgs", { - g: "grid", - s: "spotlight", - }); - }); -}); - -test("Should switch to spotlight mode when there is a remote screen share", () => { - withTestScheduler(({ cold, behavior, expectObservable }): void => { - const shareMarble = "f--t"; - const gridsMarble = "g--s"; - const { gridMode$ } = createLayoutModeSwitch( - scope, - behavior("n", { n: "normal" }), - cold(shareMarble, { f: false, t: true }), - ); - - expectObservable(gridMode$).toBe(gridsMarble, { - g: "grid", - s: "spotlight", - }); - }); -}); - -test("Can manually force grid when there is a screenshare", () => { - withTestScheduler(({ cold, behavior, expectObservable, schedule }): void => { - const { gridMode$, setGridMode } = createLayoutModeSwitch( - scope, - behavior("n", { n: "normal" }), - cold("-ft", { f: false, t: true }), - ); - - schedule("---g", { - g: () => setGridMode("grid"), - }); - - expectObservable(gridMode$).toBe("ggsg", { - g: "grid", - s: "spotlight", - }); - }); -}); - -test("Should auto-switch after manually selected grid", () => { - withTestScheduler(({ cold, behavior, expectObservable, schedule }): void => { - const { gridMode$, setGridMode } = createLayoutModeSwitch( - scope, - behavior("n", { n: "normal" }), - // Two screenshares will happen in sequence - cold("-ft-ft", { f: false, t: true }), - ); - - // There was a screen-share that forced spotlight, then - // the user manually switch back to grid - schedule("---g", { - g: () => setGridMode("grid"), - }); - - // If we did want to respect manual selection, the expectation would be: - // const expectation = "ggsg"; - const expectation = "ggsg-s"; - - expectObservable(gridMode$).toBe(expectation, { - g: "grid", - s: "spotlight", - }); - }); -}); - -test("Should switch back to grid mode when the remote screen share ends", () => { - withTestScheduler(({ cold, behavior, expectObservable }): void => { - const shareMarble = "f--t--f-"; - const gridsMarble = "g--s--g-"; - const { gridMode$ } = createLayoutModeSwitch( - scope, - behavior("n", { n: "normal" }), - cold(shareMarble, { f: false, t: true }), - ); - - expectObservable(gridMode$).toBe(gridsMarble, { - g: "grid", - s: "spotlight", - }); - }); -}); - -test("can auto-switch to spotlight again after first screen share ends", () => { - withTestScheduler(({ cold, behavior, expectObservable }): void => { - const shareMarble = "ftft"; - const gridsMarble = "gsgs"; - const { gridMode$ } = createLayoutModeSwitch( - scope, - behavior("n", { n: "normal" }), - cold(shareMarble, { f: false, t: true }), - ); - - expectObservable(gridMode$).toBe(gridsMarble, { - g: "grid", - s: "spotlight", - }); - }); -}); - -test("can switch manually to grid after screen share while manually in spotlight", () => { - withTestScheduler(({ cold, behavior, schedule, expectObservable }): void => { - // Initially, no one is sharing. Then the user manually switches to - // spotlight. After a screen share starts, the user manually switches to - // grid. - const shareMarbles = " f-t-"; - const setModeMarbles = "-s-g"; - const expectation = " gs-g"; - const { gridMode$, setGridMode } = createLayoutModeSwitch( - scope, - behavior("n", { n: "normal" }), - cold(shareMarbles, { f: false, t: true }), - ); - schedule(setModeMarbles, { + schedule(userSelection, { g: () => setGridMode("grid"), s: () => setGridMode("spotlight"), }); - - expectObservable(gridMode$).toBe(expectation, { + expectObservable(gridMode$).toBe(expectedGridMode, { g: "grid", s: "spotlight", }); }); +} + +describe("default mode", () => { + test("uses grid layout by default", () => + testLayoutSwitch({ + expectedGridMode: "g", + })); + + test("uses spotlight mode when window mode is flat", () => + testLayoutSwitch({ + windowMode: " f", + expectedGridMode: "s", + })); }); -test("Should auto-switch to spotlight when in flat window mode", () => { - withTestScheduler(({ cold, behavior, expectObservable }): void => { - const { gridMode$ } = createLayoutModeSwitch( - scope, - behavior("naf", { n: "normal", a: "narrow", f: "flat" }), - cold("f", { f: false, t: true }), - ); +test("allows switching modes manually", () => + testLayoutSwitch({ + userSelection: " --sgs", + expectedGridMode: "g-sgs", + })); - expectObservable(gridMode$).toBe("g-s-", { - g: "grid", - s: "spotlight", - }); - }); -}); +test("switches to spotlight mode when there is a remote screen share", () => + testLayoutSwitch({ + hasScreenShares: " n--y", + expectedGridMode: "g--s", + })); + +test("can manually switch to grid when there is a screenshare", () => + testLayoutSwitch({ + hasScreenShares: " n-y", + userSelection: " ---g", + expectedGridMode: "g-sg", + })); + +test("auto-switches after manually selecting grid", () => + testLayoutSwitch({ + // Two screenshares will happen in sequence. There is a screen share that + // forces spotlight, then the user manually switches back to grid. + hasScreenShares: " n-y-ny", + userSelection: " ---g", + expectedGridMode: "g-sg-s", + // If we did want to respect manual selection, the expectation would be: g-sg + })); + +test("switches back to grid mode when the remote screen share ends", () => + testLayoutSwitch({ + hasScreenShares: " n--y--n", + expectedGridMode: "g--s--g", + })); + +test("auto-switches to spotlight again after first screen share ends", () => + testLayoutSwitch({ + hasScreenShares: " nyny", + expectedGridMode: "gsgs", + })); + +test("switches manually to grid after screen share while manually in spotlight", () => + testLayoutSwitch({ + // Initially, no one is sharing. Then the user manually switches to spotlight. + // After a screen share starts, the user manually switches to grid. + hasScreenShares: " n-y", + userSelection: " -s-g", + expectedGridMode: "gs-g", + })); + +test("auto-switches to spotlight when in flat window mode", () => + testLayoutSwitch({ + // First normal, then narrow, then flat. + windowMode: " nNf", + expectedGridMode: "g-s", + })); From 53cc79f7387d5cce44e5b138fbdf7b5668196410 Mon Sep 17 00:00:00 2001 From: Robin Date: Mon, 15 Dec 2025 14:33:00 -0500 Subject: [PATCH 104/748] Allow user to switch layouts while phone is in landscape This fixes a regression on the development branch: the layout switcher would not respond to input while the window mode is 'flat' (i.e. while a mobile phone is in landscape orientation). See https://github.com/element-hq/element-call/pull/3605#discussion_r2586226422 for more context. I was having a little trouble interpreting the emergent behavior of the layout switching code, so I refactored it in the process into a form that I think is a more direct description of the behavior we want (while not making it as terse as my original implementation). --- src/state/CallViewModel/CallViewModel.ts | 9 +- src/state/CallViewModel/LayoutSwitch.test.ts | 23 +++ src/state/CallViewModel/LayoutSwitch.ts | 143 +++++++------------ 3 files changed, 81 insertions(+), 94 deletions(-) diff --git a/src/state/CallViewModel/CallViewModel.ts b/src/state/CallViewModel/CallViewModel.ts index aac88a3be..e2e3924bd 100644 --- a/src/state/CallViewModel/CallViewModel.ts +++ b/src/state/CallViewModel/CallViewModel.ts @@ -946,11 +946,12 @@ export function createCallViewModel$( ), ); - const hasRemoteScreenShares$: Observable = spotlight$.pipe( - map((spotlight) => - spotlight.some((vm) => !vm.local && vm instanceof ScreenShareViewModel), + const hasRemoteScreenShares$ = scope.behavior( + spotlight$.pipe( + map((spotlight) => + spotlight.some((vm) => !vm.local && vm instanceof ScreenShareViewModel), + ), ), - distinctUntilChanged(), ); const pipEnabled$ = scope.behavior(setPipEnabled$, false); diff --git a/src/state/CallViewModel/LayoutSwitch.test.ts b/src/state/CallViewModel/LayoutSwitch.test.ts index a0d2d8c3b..0d184017b 100644 --- a/src/state/CallViewModel/LayoutSwitch.test.ts +++ b/src/state/CallViewModel/LayoutSwitch.test.ts @@ -107,3 +107,26 @@ test("auto-switches to spotlight when in flat window mode", () => windowMode: " nNf", expectedGridMode: "g-s", })); + +test("allows switching modes manually when in flat window mode", () => + testLayoutSwitch({ + // Window becomes flat, then user switches to grid and back. + // Finally the window returns to a normal shape. + windowMode: " nf--n", + userSelection: " --gs", + expectedGridMode: "gsgsg", + })); + +test("stays in spotlight while there are screen shares even when window mode changes", () => + testLayoutSwitch({ + windowMode: " nfn", + hasScreenShares: " y", + expectedGridMode: "s", + })); + +test("ignores end of screen share until window mode returns to normal", () => + testLayoutSwitch({ + windowMode: " nf-n", + hasScreenShares: " y-n", + expectedGridMode: "s--g", + })); diff --git a/src/state/CallViewModel/LayoutSwitch.ts b/src/state/CallViewModel/LayoutSwitch.ts index 3ad932044..97a4ee6fe 100644 --- a/src/state/CallViewModel/LayoutSwitch.ts +++ b/src/state/CallViewModel/LayoutSwitch.ts @@ -6,122 +6,85 @@ Please see LICENSE in the repository root for full details. */ import { - BehaviorSubject, combineLatest, map, - type Observable, - scan, + Subject, + startWith, + skipWhile, + switchMap, } from "rxjs"; -import { logger } from "matrix-js-sdk/lib/logger"; import { type GridMode, type WindowMode } from "./CallViewModel.ts"; -import { type Behavior } from "../Behavior.ts"; +import { constant, type Behavior } from "../Behavior.ts"; import { type ObservableScope } from "../ObservableScope.ts"; /** * Creates a layout mode switch that allows switching between grid and spotlight modes. - * The actual layout mode can be overridden to spotlight mode if there is a remote screen share active - * or if the window mode is flat. + * The actual layout mode might switch automatically to spotlight if there is a + * remote screen share active or if the window mode is flat. * * @param scope - The observable scope to manage subscriptions. - * @param windowMode$ - The current window mode observable. - * @param hasRemoteScreenShares$ - An observable indicating if there are remote screen shares active. + * @param windowMode$ - The current window mode. + * @param hasRemoteScreenShares$ - A behavior indicating if there are remote screen shares active. */ export function createLayoutModeSwitch( scope: ObservableScope, windowMode$: Behavior, - hasRemoteScreenShares$: Observable, + hasRemoteScreenShares$: Behavior, ): { gridMode$: Behavior; setGridMode: (value: GridMode) => void; } { - const gridModeUserSelection$ = new BehaviorSubject("grid"); - + const userSelection$ = new Subject(); // Callback to set the grid mode desired by the user. // Notice that this is only a preference, the actual grid mode can be overridden // if there is a remote screen share active. - const setGridMode = (value: GridMode): void => { - gridModeUserSelection$.next(value); - }; + const setGridMode = (value: GridMode): void => userSelection$.next(value); + + /** + * The natural grid mode - the mode that the grid would prefer to be in, + * not accounting for the user's manual selections. + */ + const naturalGridMode$ = scope.behavior( + combineLatest( + [hasRemoteScreenShares$, windowMode$], + (hasRemoteScreenShares, windowMode) => + // When there are screen shares or the window is flat (as with a phone + // in landscape orientation), spotlight is a better experience. + // We want screen shares to be big and readable, and we want flipping + // your phone into landscape to be a quick way of maximising the + // spotlight tile. + hasRemoteScreenShares || windowMode === "flat" ? "spotlight" : "grid", + ), + ); + /** * The layout mode of the media tile grid. */ - const gridMode$ = - // If the user hasn't selected spotlight and somebody starts screen sharing, - // automatically switch to spotlight mode and reset when screen sharing ends - scope.behavior( - combineLatest([ - gridModeUserSelection$, - hasRemoteScreenShares$, - windowMode$, - ]).pipe( - // Scan to keep track if we have auto-switched already or not. - // To allow the user to override the auto-switch by selecting grid mode again. - scan< - [GridMode, boolean, WindowMode], - { - mode: GridMode; - /** Remember if the change was user driven or not */ - hasAutoSwitched: boolean; - /** To know if it is new screen share or an already handled */ - hasScreenShares: boolean; - } - >( - (prev, [userSelection, hasScreenShares, windowMode]) => { - const isFlatMode = windowMode === "flat"; + const gridMode$ = scope.behavior( + // Whenever the user makes a selection, we enter a new mode of behavior: + userSelection$.pipe( + map((selection) => { + if (selection === "grid") + // The user has selected grid mode. Start by respecting their choice, + // but then follow the natural mode again as soon as it matches. + return naturalGridMode$.pipe( + skipWhile((naturalMode) => naturalMode !== selection), + startWith(selection), + ); - // Always force spotlight in flat mode, grid layout is not supported - // in that mode. - // TODO: strange that we do that for flat mode but not for other modes? - // TODO: Why is this not handled in layoutMedia$ like other window modes? - if (isFlatMode) { - logger.debug(`Forcing spotlight mode, windowMode=${windowMode}`); - return { - mode: "spotlight", - hasAutoSwitched: prev.hasAutoSwitched, - hasScreenShares, - }; - } - - // User explicitly chose spotlight. - // Respect that choice. - if (userSelection === "spotlight") { - return { - mode: "spotlight", - hasAutoSwitched: prev.hasAutoSwitched, - hasScreenShares, - }; - } - - // User has chosen grid mode. If a screen share starts, we will - // auto-switch to spotlight mode for better experience. - // But we only do it once, if the user switches back to grid mode, - // we respect that choice until they explicitly change it again. - const isNewShare = hasScreenShares && !prev.hasScreenShares; - if (isNewShare && !prev.hasAutoSwitched) { - return { - mode: "spotlight", - hasAutoSwitched: true, - hasScreenShares: true, - }; - } - - // Respect user's grid choice - // XXX If we want to forbid switching automatically again after we can - // return hasAutoSwitched: acc.hasAutoSwitched here instead of setting to false. - return { - mode: "grid", - hasAutoSwitched: false, - hasScreenShares, - }; - }, - // initial value - { mode: "grid", hasAutoSwitched: false, hasScreenShares: false }, - ), - map(({ mode }) => mode), - ), - "grid", - ); + // The user has selected spotlight mode. If this matches the natural + // mode, then follow the natural mode going forward. + return selection === naturalGridMode$.value + ? naturalGridMode$ + : constant(selection); + }), + // Initially the mode of behavior is to just follow the natural grid mode. + startWith(naturalGridMode$), + // Switch between each mode of behavior. + switchMap((mode$) => mode$), + ), + ); return { gridMode$, From c7e9f1ce1449313adb2f3ef82661b8c70c222d95 Mon Sep 17 00:00:00 2001 From: Robin Date: Mon, 15 Dec 2025 15:09:46 -0500 Subject: [PATCH 105/748] Explicitly pass the MatrixRTC mode to CallViewModel --- src/room/InCallView.tsx | 2 ++ src/state/CallViewModel/CallViewModelTestUtils.ts | 2 +- src/utils/test-viewmodel.ts | 2 ++ 3 files changed, 5 insertions(+), 1 deletion(-) diff --git a/src/room/InCallView.tsx b/src/room/InCallView.tsx index add8154af..41582039b 100644 --- a/src/room/InCallView.tsx +++ b/src/room/InCallView.tsx @@ -88,6 +88,7 @@ import { ReactionsOverlay } from "./ReactionsOverlay"; import { CallEventAudioRenderer } from "./CallEventAudioRenderer"; import { debugTileLayout as debugTileLayoutSetting, + matrixRTCMode as matrixRTCModeSetting, useSetting, } from "../settings/settings"; import { ReactionsReader } from "../reactions/ReactionsReader"; @@ -144,6 +145,7 @@ export const ActiveCall: FC = (props) => { encryptionSystem: props.e2eeSystem, autoLeaveWhenOthersLeft, waitForCallPickup: waitForCallPickup && sendNotificationType === "ring", + matrixRTCMode$: matrixRTCModeSetting.value$, }, reactionsReader.raisedHands$, reactionsReader.reactions$, diff --git a/src/state/CallViewModel/CallViewModelTestUtils.ts b/src/state/CallViewModel/CallViewModelTestUtils.ts index e9996a41b..377c67710 100644 --- a/src/state/CallViewModel/CallViewModelTestUtils.ts +++ b/src/state/CallViewModel/CallViewModelTestUtils.ts @@ -105,6 +105,7 @@ export function withCallViewModel(mode: MatrixRTCMode) { options: CallViewModelOptions = { encryptionSystem: { kind: E2eeType.PER_PARTICIPANT }, autoLeaveWhenOthersLeft: false, + matrixRTCMode$: constant(mode), }, ): void => { let syncState = initialSyncState; @@ -184,7 +185,6 @@ export function withCallViewModel(mode: MatrixRTCMode) { }), connectionState$, windowSize$, - matrixRTCMode$: constant(mode), }, raisedHands$, reactions$, diff --git a/src/utils/test-viewmodel.ts b/src/utils/test-viewmodel.ts index 98c45d866..0745be726 100644 --- a/src/utils/test-viewmodel.ts +++ b/src/utils/test-viewmodel.ts @@ -37,6 +37,7 @@ import { import { aliceRtcMember, localRtcMember } from "./test-fixtures"; import { type RaisedHandInfo, type ReactionInfo } from "../reactions"; import { constant } from "../state/Behavior"; +import { MatrixRTCMode } from "../settings/settings"; mockConfig({ livekit: { livekit_service_url: "https://example.com" } }); @@ -162,6 +163,7 @@ export function getBasicCallViewModelEnvironment( setE2EEEnabled: async () => Promise.resolve(), }), connectionState$: constant(ConnectionState.Connected), + matrixRTCMode$: constant(MatrixRTCMode.Legacy), ...callViewModelOptions, }, handRaisedSubject$, From 87fbbb9a3f4410c9815733772fd52cae79f4fc8a Mon Sep 17 00:00:00 2001 From: Robin Date: Mon, 15 Dec 2025 15:16:47 -0500 Subject: [PATCH 106/748] Make MatrixRTC mode a required input to CallViewModel --- src/state/CallViewModel/CallViewModel.ts | 11 ++++------- src/state/CallViewModel/CallViewModelTestUtils.ts | 11 +++++------ 2 files changed, 9 insertions(+), 13 deletions(-) diff --git a/src/state/CallViewModel/CallViewModel.ts b/src/state/CallViewModel/CallViewModel.ts index 9ebe025c7..8f8b20cf9 100644 --- a/src/state/CallViewModel/CallViewModel.ts +++ b/src/state/CallViewModel/CallViewModel.ts @@ -62,7 +62,6 @@ import { import { duplicateTiles, MatrixRTCMode, - matrixRTCMode as matrixRTCModeSetting, playReactionsSound, showReactions, } from "../../settings/settings"; @@ -156,8 +155,8 @@ export interface CallViewModelOptions { connectionState$?: Behavior; /** Optional behavior overriding the computed window size, mainly for testing purposes. */ windowSize$?: Behavior<{ width: number; height: number }>; - /** Optional behavior overriding the MatrixRTC mode, mainly for testing purposes. */ - matrixRTCMode$?: Behavior; + /** The version & compatibility mode of MatrixRTC that we should use. */ + matrixRTCMode$: Behavior; } // Do not play any sounds if the participant count has exceeded this @@ -408,15 +407,13 @@ export function createCallViewModel$( memberships$, ); - const matrixRTCMode$ = options.matrixRTCMode$ ?? matrixRTCModeSetting.value$; - const localTransport$ = createLocalTransport$({ scope: scope, memberships$: memberships$, client, roomId: matrixRoom.roomId, useOldestMember$: scope.behavior( - matrixRTCMode$.pipe(map((v) => v === MatrixRTCMode.Legacy)), + options.matrixRTCMode$.pipe(map((v) => v === MatrixRTCMode.Legacy)), ), }); @@ -468,7 +465,7 @@ export function createCallViewModel$( }); const connectOptions$ = scope.behavior( - matrixRTCMode$.pipe( + options.matrixRTCMode$.pipe( map((mode) => ({ encryptMedia: livekitKeyProvider !== undefined, // TODO. This might need to get called again on each change of matrixRTCMode... diff --git a/src/state/CallViewModel/CallViewModelTestUtils.ts b/src/state/CallViewModel/CallViewModelTestUtils.ts index 377c67710..b6f532751 100644 --- a/src/state/CallViewModel/CallViewModelTestUtils.ts +++ b/src/state/CallViewModel/CallViewModelTestUtils.ts @@ -102,11 +102,7 @@ export function withCallViewModel(mode: MatrixRTCMode) { }, setSyncState: (value: SyncState) => void, ) => void, - options: CallViewModelOptions = { - encryptionSystem: { kind: E2eeType.PER_PARTICIPANT }, - autoLeaveWhenOthersLeft: false, - matrixRTCMode$: constant(mode), - }, + options: Partial = {}, ): void => { let syncState = initialSyncState; const setSyncState = (value: SyncState): void => { @@ -176,7 +172,8 @@ export function withCallViewModel(mode: MatrixRTCMode) { mediaDevices, muteStates, { - ...options, + encryptionSystem: { kind: E2eeType.PER_PARTICIPANT }, + autoLeaveWhenOthersLeft: false, livekitRoomFactory: (): LivekitRoom => mockLivekitRoom({ localParticipant, @@ -185,6 +182,8 @@ export function withCallViewModel(mode: MatrixRTCMode) { }), connectionState$, windowSize$, + matrixRTCMode$: constant(mode), + ...options, }, raisedHands$, reactions$, From 92bcc52e87f3336c3d79aa41f82168fad695b1f7 Mon Sep 17 00:00:00 2001 From: Robin Date: Wed, 10 Dec 2025 12:55:52 -0500 Subject: [PATCH 107/748] Remove unused method The doc comment here was about to become stale, so let's just remove it. --- .../remoteMembers/ConnectionManager.ts | 25 +++---------------- 1 file changed, 4 insertions(+), 21 deletions(-) diff --git a/src/state/CallViewModel/remoteMembers/ConnectionManager.ts b/src/state/CallViewModel/remoteMembers/ConnectionManager.ts index 6c2d64e0d..f316e8011 100644 --- a/src/state/CallViewModel/remoteMembers/ConnectionManager.ts +++ b/src/state/CallViewModel/remoteMembers/ConnectionManager.ts @@ -6,10 +6,7 @@ SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial Please see LICENSE in the repository root for full details. */ -import { - type LivekitTransport, - type ParticipantId, -} from "matrix-js-sdk/lib/matrixrtc"; +import { type LivekitTransport } from "matrix-js-sdk/lib/matrixrtc"; import { combineLatest, map, of, switchMap, tap } from "rxjs"; import { type Logger } from "matrix-js-sdk/lib/logger"; import { type RemoteParticipant } from "livekit-client"; @@ -57,34 +54,20 @@ export class ConnectionManagerData { const key = transport.livekit_service_url + "|" + transport.livekit_alias; return this.store.get(key)?.[1] ?? []; } - /** - * Get all connections where the given participant is publishing. - * In theory, there could be several connections where the same participant is publishing but with - * only well behaving clients a participant should only be publishing on a single connection. - * @param participantId - */ - public getConnectionsForParticipant( - participantId: ParticipantId, - ): Connection[] { - const connections: Connection[] = []; - for (const [connection, participants] of this.store.values()) { - if (participants.some((p) => p.identity === participantId)) { - connections.push(connection); - } - } - return connections; - } } + interface Props { scope: ObservableScope; connectionFactory: ConnectionFactory; inputTransports$: Behavior>; logger: Logger; } + // TODO - write test for scopes (do we really need to bind scope) export interface IConnectionManager { connectionManagerData$: Behavior>; } + /** * Crete a `ConnectionManager` * @param scope the observable scope used by this object. From 2c54263b2f632806cc23300b9eb8c68abac49a86 Mon Sep 17 00:00:00 2001 From: Robin Date: Wed, 10 Dec 2025 15:09:40 -0500 Subject: [PATCH 108/748] Don't show 'waiting for media' on connected participants We would show 'waiting for media' on participants that were connected but had no published tracks, because we were filtering them out of the remote participants list on connections. I believe this was done in an attempt to limit our view to only the participants that have a matching MatrixRTC membership. But that's fully redundant to the "Matrix-LiveKit members" module, which actually has the right information to do this (the MatrixRTC memberships). --- .../remoteMembers/Connection.test.ts | 103 ++++++------------ .../CallViewModel/remoteMembers/Connection.ts | 31 ++---- .../remoteMembers/ConnectionManager.test.ts | 6 +- .../remoteMembers/ConnectionManager.ts | 2 +- 4 files changed, 46 insertions(+), 96 deletions(-) diff --git a/src/state/CallViewModel/remoteMembers/Connection.test.ts b/src/state/CallViewModel/remoteMembers/Connection.test.ts index 4318708e2..30c934b94 100644 --- a/src/state/CallViewModel/remoteMembers/Connection.test.ts +++ b/src/state/CallViewModel/remoteMembers/Connection.test.ts @@ -39,6 +39,7 @@ import { ElementCallError, FailToGetOpenIdToken, } from "../../../utils/errors.ts"; +import { mockRemoteParticipant } from "../../../utils/test.ts"; let testScope: ObservableScope; @@ -376,46 +377,32 @@ describe("Start connection states", () => { }); }); -function fakeRemoteLivekitParticipant( - id: string, - publications: number = 1, -): RemoteParticipant { - return { - identity: id, - getTrackPublications: () => Array(publications), - } as unknown as RemoteParticipant; -} - -describe("Publishing participants observations", () => { - it("should emit the list of publishing participants", () => { +describe("remote participants", () => { + it("emits the list of remote participants", () => { setupTest(); const connection = setupRemoteConnection(); - const bobIsAPublisher = Promise.withResolvers(); - const danIsAPublisher = Promise.withResolvers(); - const observedPublishers: RemoteParticipant[][] = []; - const s = connection.remoteParticipantsWithTracks$.subscribe( - (publishers) => { - observedPublishers.push(publishers); - if (publishers.some((p) => p.identity === "@bob:example.org:DEV111")) { - bobIsAPublisher.resolve(); - } - if (publishers.some((p) => p.identity === "@dan:example.org:DEV333")) { - danIsAPublisher.resolve(); - } - }, - ); + const observedParticipants: RemoteParticipant[][] = []; + const s = connection.remoteParticipants$.subscribe((participants) => { + observedParticipants.push(participants); + }); onTestFinished(() => s.unsubscribe()); // The remoteParticipants$ observable is derived from the current members of the // livekitRoom and the rtc membership in order to publish the members that are publishing // on this connection. - let participants: RemoteParticipant[] = [ - fakeRemoteLivekitParticipant("@alice:example.org:DEV000", 0), - fakeRemoteLivekitParticipant("@bob:example.org:DEV111", 0), - fakeRemoteLivekitParticipant("@carol:example.org:DEV222", 0), - fakeRemoteLivekitParticipant("@dan:example.org:DEV333", 0), + const participants: RemoteParticipant[] = [ + mockRemoteParticipant({ identity: "@alice:example.org:DEV000" }), + mockRemoteParticipant({ identity: "@bob:example.org:DEV111" }), + mockRemoteParticipant({ identity: "@carol:example.org:DEV222" }), + // Mock Dan to have no published tracks. We want him to still show show up + // in the participants list. + mockRemoteParticipant({ + identity: "@dan:example.org:DEV333", + getTrackPublication: () => undefined, + getTrackPublications: () => [], + }), ]; // Let's simulate 3 members on the livekitRoom @@ -427,21 +414,8 @@ describe("Publishing participants observations", () => { fakeLivekitRoom.emit(RoomEvent.ParticipantConnected, p), ); - // At this point there should be no publishers - expect(observedPublishers.pop()!.length).toEqual(0); - - participants = [ - fakeRemoteLivekitParticipant("@alice:example.org:DEV000", 1), - fakeRemoteLivekitParticipant("@bob:example.org:DEV111", 1), - fakeRemoteLivekitParticipant("@carol:example.org:DEV222", 1), - fakeRemoteLivekitParticipant("@dan:example.org:DEV333", 2), - ]; - participants.forEach((p) => - fakeLivekitRoom.emit(RoomEvent.ParticipantConnected, p), - ); - - // At this point there should be no publishers - expect(observedPublishers.pop()!.length).toEqual(4); + // All remote participants should be present + expect(observedParticipants.pop()!.length).toEqual(4); }); it("should be scoped to parent scope", (): void => { @@ -449,16 +423,14 @@ describe("Publishing participants observations", () => { const connection = setupRemoteConnection(); - let observedPublishers: RemoteParticipant[][] = []; - const s = connection.remoteParticipantsWithTracks$.subscribe( - (publishers) => { - observedPublishers.push(publishers); - }, - ); + let observedParticipants: RemoteParticipant[][] = []; + const s = connection.remoteParticipants$.subscribe((participants) => { + observedParticipants.push(participants); + }); onTestFinished(() => s.unsubscribe()); let participants: RemoteParticipant[] = [ - fakeRemoteLivekitParticipant("@bob:example.org:DEV111", 0), + mockRemoteParticipant({ identity: "@bob:example.org:DEV111" }), ]; // Let's simulate 3 members on the livekitRoom @@ -470,35 +442,26 @@ describe("Publishing participants observations", () => { fakeLivekitRoom.emit(RoomEvent.ParticipantConnected, participant); } - // At this point there should be no publishers - expect(observedPublishers.pop()!.length).toEqual(0); - - participants = [fakeRemoteLivekitParticipant("@bob:example.org:DEV111", 1)]; - - for (const participant of participants) { - fakeLivekitRoom.emit(RoomEvent.ParticipantConnected, participant); - } - - // We should have bob has a publisher now - const publishers = observedPublishers.pop(); - expect(publishers?.length).toEqual(1); - expect(publishers?.[0]?.identity).toEqual("@bob:example.org:DEV111"); + // We should have bob as a participant now + const ps = observedParticipants.pop(); + expect(ps?.length).toEqual(1); + expect(ps?.[0]?.identity).toEqual("@bob:example.org:DEV111"); // end the parent scope testScope.end(); - observedPublishers = []; + observedParticipants = []; - // SHOULD NOT emit any more publishers as the scope is ended + // SHOULD NOT emit any more participants as the scope is ended participants = participants.filter( (p) => p.identity !== "@bob:example.org:DEV111", ); fakeLivekitRoom.emit( RoomEvent.ParticipantDisconnected, - fakeRemoteLivekitParticipant("@bob:example.org:DEV111"), + mockRemoteParticipant({ identity: "@bob:example.org:DEV111" }), ); - expect(observedPublishers.length).toEqual(0); + expect(observedParticipants.length).toEqual(0); }); }); diff --git a/src/state/CallViewModel/remoteMembers/Connection.ts b/src/state/CallViewModel/remoteMembers/Connection.ts index 3d685c8ab..05d0ec9e9 100644 --- a/src/state/CallViewModel/remoteMembers/Connection.ts +++ b/src/state/CallViewModel/remoteMembers/Connection.ts @@ -14,7 +14,6 @@ import { ConnectionError, type Room as LivekitRoom, type RemoteParticipant, - RoomEvent, } from "livekit-client"; import { type LivekitTransport } from "matrix-js-sdk/lib/matrixrtc"; import { BehaviorSubject, map } from "rxjs"; @@ -96,11 +95,13 @@ export class Connection { private scope: ObservableScope; /** - * An observable of the participants that are publishing on this connection. (Excluding our local participant) - * This is derived from `participantsIncludingSubscribers$` and `remoteTransports$`. - * It filters the participants to only those that are associated with a membership that claims to publish on this connection. + * The remote LiveKit participants that are visible on this connection. + * + * Note that this may include participants that are connected only to + * subscribe, or publishers that are otherwise unattested in MatrixRTC state. + * It is therefore more low-level than what should be presented to the user. */ - public readonly remoteParticipantsWithTracks$: Behavior; + public readonly remoteParticipants$: Behavior; /** * Whether the connection has been stopped. @@ -231,23 +232,9 @@ export class Connection { this.transport = transport; this.client = client; - // REMOTE participants with track!!! - // this.remoteParticipantsWithTracks$ - this.remoteParticipantsWithTracks$ = scope.behavior( - // only tracks remote participants - connectedParticipantsObserver(this.livekitRoom, { - additionalRoomEvents: [ - RoomEvent.TrackPublished, - RoomEvent.TrackUnpublished, - ], - }).pipe( - map((participants) => { - return participants.filter( - (participant) => participant.getTrackPublications().length > 0, - ); - }), - ), - [], + this.remoteParticipants$ = scope.behavior( + // Only tracks remote participants + connectedParticipantsObserver(this.livekitRoom), ); scope.onEnd(() => { diff --git a/src/state/CallViewModel/remoteMembers/ConnectionManager.test.ts b/src/state/CallViewModel/remoteMembers/ConnectionManager.test.ts index da1da06f6..70bfb4def 100644 --- a/src/state/CallViewModel/remoteMembers/ConnectionManager.test.ts +++ b/src/state/CallViewModel/remoteMembers/ConnectionManager.test.ts @@ -52,7 +52,7 @@ beforeEach(() => { (transport: LivekitTransport, scope: ObservableScope) => { const mockConnection = { transport, - remoteParticipantsWithTracks$: new BehaviorSubject([]), + remoteParticipants$: new BehaviorSubject([]), } as unknown as Connection; vi.mocked(mockConnection).start = vi.fn(); vi.mocked(mockConnection).stop = vi.fn(); @@ -200,7 +200,7 @@ describe("connections$ stream", () => { }); describe("connectionManagerData$ stream", () => { - // Used in test to control fake connections' remoteParticipantsWithTracks$ streams + // Used in test to control fake connections' remoteParticipants$ streams let fakeRemoteParticipantsStreams: Map>; function keyForTransport(transport: LivekitTransport): string { @@ -229,7 +229,7 @@ describe("connectionManagerData$ stream", () => { >([]); const mockConnection = { transport, - remoteParticipantsWithTracks$: getRemoteParticipantsFor(transport), + remoteParticipants$: getRemoteParticipantsFor(transport), } as unknown as Connection; vi.mocked(mockConnection).start = vi.fn(); vi.mocked(mockConnection).stop = vi.fn(); diff --git a/src/state/CallViewModel/remoteMembers/ConnectionManager.ts b/src/state/CallViewModel/remoteMembers/ConnectionManager.ts index f316e8011..8db62236c 100644 --- a/src/state/CallViewModel/remoteMembers/ConnectionManager.ts +++ b/src/state/CallViewModel/remoteMembers/ConnectionManager.ts @@ -152,7 +152,7 @@ export function createConnectionManager$({ // Map the connections to list of {connection, participants}[] const listOfConnectionsWithRemoteParticipants = connections.value.map( (connection) => { - return connection.remoteParticipantsWithTracks$.pipe( + return connection.remoteParticipants$.pipe( map((participants) => ({ connection, participants, From 93ab3ba1ffdbb637e42ed5ab0df83d6ee0924108 Mon Sep 17 00:00:00 2001 From: Robin Date: Wed, 10 Dec 2025 17:16:38 -0500 Subject: [PATCH 109/748] Compute the 'waiting for media' state less implicitly On second glance, the way that we determined a media tile to be 'waiting for media' was too implicit for my taste. It would appear on a surface reading to depend on whether a participant was currently publishing any video. But in reality, the 'video' object was always defined as long as a LiveKit participant existed, so in reality it depended on just the participant. We should show this relationship more explicitly by moving the computation into the view model, where it can depend on the participant directly. --- src/state/MediaViewModel.test.ts | 31 +++++++++++++++++++++++++-- src/state/MediaViewModel.ts | 10 ++++++++- src/tile/GridTile.test.tsx | 10 ++++++--- src/tile/GridTile.tsx | 6 +++++- src/tile/MediaView.test.tsx | 36 ++++++++++++++++++-------------- src/tile/MediaView.tsx | 6 +++--- src/tile/SpotlightTile.test.tsx | 3 ++- src/tile/SpotlightTile.tsx | 18 +++++++++++++++- src/utils/test.ts | 20 +++++++++++------- 9 files changed, 104 insertions(+), 36 deletions(-) diff --git a/src/state/MediaViewModel.test.ts b/src/state/MediaViewModel.test.ts index 61fa2d8c0..2ca14d19c 100644 --- a/src/state/MediaViewModel.test.ts +++ b/src/state/MediaViewModel.test.ts @@ -20,6 +20,7 @@ import { createLocalMedia, createRemoteMedia, withTestScheduler, + mockRemoteParticipant, } from "../utils/test"; import { getValue } from "../utils/observable"; import { constant } from "./Behavior"; @@ -44,7 +45,11 @@ const rtcMembership = mockRtcMembership("@alice:example.org", "AAAA"); test("control a participant's volume", () => { const setVolumeSpy = vi.fn(); - const vm = createRemoteMedia(rtcMembership, {}, { setVolume: setVolumeSpy }); + const vm = createRemoteMedia( + rtcMembership, + {}, + mockRemoteParticipant({ setVolume: setVolumeSpy }), + ); withTestScheduler(({ expectObservable, schedule }) => { schedule("-ab---c---d|", { a() { @@ -88,7 +93,7 @@ test("control a participant's volume", () => { }); test("toggle fit/contain for a participant's video", () => { - const vm = createRemoteMedia(rtcMembership, {}, {}); + const vm = createRemoteMedia(rtcMembership, {}, mockRemoteParticipant({})); withTestScheduler(({ expectObservable, schedule }) => { schedule("-ab|", { a: () => vm.toggleFitContain(), @@ -199,3 +204,25 @@ test("switch cameras", async () => { }); expect(deviceId).toBe("front camera"); }); + +test("remote media is in waiting state when participant has not yet connected", () => { + const vm = createRemoteMedia(rtcMembership, {}, null); // null participant + expect(vm.waitingForMedia$.value).toBe(true); +}); + +test("remote media is not in waiting state when participant is connected", () => { + const vm = createRemoteMedia(rtcMembership, {}, mockRemoteParticipant({})); + expect(vm.waitingForMedia$.value).toBe(false); +}); + +test("remote media is not in waiting state when participant is connected with no publications", () => { + const vm = createRemoteMedia( + rtcMembership, + {}, + mockRemoteParticipant({ + getTrackPublication: () => undefined, + getTrackPublications: () => [], + }), + ); + expect(vm.waitingForMedia$.value).toBe(false); +}); diff --git a/src/state/MediaViewModel.ts b/src/state/MediaViewModel.ts index 74e64b932..3d0ff75b3 100644 --- a/src/state/MediaViewModel.ts +++ b/src/state/MediaViewModel.ts @@ -268,7 +268,7 @@ abstract class BaseMediaViewModel { encryptionSystem: EncryptionSystem, audioSource: AudioSource, videoSource: VideoSource, - livekitRoom$: Behavior, + protected readonly livekitRoom$: Behavior, public readonly focusUrl$: Behavior, public readonly displayName$: Behavior, public readonly mxcAvatarUrl$: Behavior, @@ -596,6 +596,14 @@ export class LocalUserMediaViewModel extends BaseUserMediaViewModel { * A remote participant's user media. */ export class RemoteUserMediaViewModel extends BaseUserMediaViewModel { + /** + * Whether we are waiting for this user's LiveKit participant to exist. This + * could be because either we or the remote party are still connecting. + */ + public readonly waitingForMedia$ = this.scope.behavior( + this.participant$.pipe(map((participant) => participant === null)), + ); + // This private field is used to override the value from the superclass private __speaking$: Behavior; public get speaking$(): Behavior { diff --git a/src/tile/GridTile.test.tsx b/src/tile/GridTile.test.tsx index e3172a22d..9bc0efb29 100644 --- a/src/tile/GridTile.test.tsx +++ b/src/tile/GridTile.test.tsx @@ -12,7 +12,11 @@ import { axe } from "vitest-axe"; import { type MatrixRTCSession } from "matrix-js-sdk/lib/matrixrtc"; import { GridTile } from "./GridTile"; -import { mockRtcMembership, createRemoteMedia } from "../utils/test"; +import { + mockRtcMembership, + createRemoteMedia, + mockRemoteParticipant, +} from "../utils/test"; import { GridTileViewModel } from "../state/TileViewModel"; import { ReactionsSenderProvider } from "../reactions/useReactionsSender"; import type { CallViewModel } from "../state/CallViewModel/CallViewModel"; @@ -31,11 +35,11 @@ test("GridTile is accessible", async () => { rawDisplayName: "Alice", getMxcAvatarUrl: () => "mxc://adfsg", }, - { + mockRemoteParticipant({ setVolume() {}, getTrackPublication: () => ({}) as Partial as RemoteTrackPublication, - }, + }), ); const fakeRtcSession = { diff --git a/src/tile/GridTile.tsx b/src/tile/GridTile.tsx index 57409869a..7768e8f02 100644 --- a/src/tile/GridTile.tsx +++ b/src/tile/GridTile.tsx @@ -69,6 +69,7 @@ interface UserMediaTileProps extends TileProps { vm: UserMediaViewModel; mirror: boolean; locallyMuted: boolean; + waitingForMedia?: boolean; primaryButton?: ReactNode; menuStart?: ReactNode; menuEnd?: ReactNode; @@ -79,6 +80,7 @@ const UserMediaTile: FC = ({ vm, showSpeakingIndicators, locallyMuted, + waitingForMedia, primaryButton, menuStart, menuEnd, @@ -194,7 +196,7 @@ const UserMediaTile: FC = ({ raisedHandTime={handRaised ?? undefined} currentReaction={reaction ?? undefined} raisedHandOnClick={raisedHandOnClick} - localParticipant={vm.local} + waitingForMedia={waitingForMedia} focusUrl={focusUrl} audioStreamStats={audioStreamStats} videoStreamStats={videoStreamStats} @@ -290,6 +292,7 @@ const RemoteUserMediaTile: FC = ({ ...props }) => { const { t } = useTranslation(); + const waitingForMedia = useBehavior(vm.waitingForMedia$); const locallyMuted = useBehavior(vm.locallyMuted$); const localVolume = useBehavior(vm.localVolume$); const onSelectMute = useCallback( @@ -311,6 +314,7 @@ const RemoteUserMediaTile: FC = ({ { video: trackReference, userId: "@alice:example.com", mxcAvatarUrl: undefined, - localParticipant: false, focusable: true, }; @@ -66,24 +65,13 @@ describe("MediaView", () => { }); }); - describe("with no participant", () => { - it("shows avatar for local user", () => { - render( - , - ); + describe("with no video", () => { + it("shows avatar", () => { + render(); expect( screen.getByRole("img", { name: "@alice:example.com" }), ).toBeVisible(); - expect(screen.queryAllByText("Waiting for media...").length).toBe(0); - }); - it("shows avatar and label for remote user", () => { - render( - , - ); - expect( - screen.getByRole("img", { name: "@alice:example.com" }), - ).toBeVisible(); - expect(screen.getByText("Waiting for media...")).toBeVisible(); + expect(screen.queryByTestId("video")).toBe(null); }); }); @@ -94,6 +82,22 @@ describe("MediaView", () => { }); }); + describe("waitingForMedia", () => { + test("defaults to false", () => { + render(); + expect(screen.queryAllByText("Waiting for media...").length).toBe(0); + }); + test("shows and is accessible", async () => { + const { container } = render( + + + , + ); + expect(await axe(container)).toHaveNoViolations(); + expect(screen.getByText("Waiting for media...")).toBeVisible(); + }); + }); + describe("unencryptedWarning", () => { test("is shown and accessible", async () => { const { container } = render( diff --git a/src/tile/MediaView.tsx b/src/tile/MediaView.tsx index e8a30cd4f..8bb38d948 100644 --- a/src/tile/MediaView.tsx +++ b/src/tile/MediaView.tsx @@ -43,7 +43,7 @@ interface Props extends ComponentProps { raisedHandTime?: Date; currentReaction?: ReactionOption; raisedHandOnClick?: () => void; - localParticipant: boolean; + waitingForMedia?: boolean; audioStreamStats?: RTCInboundRtpStreamStats | RTCOutboundRtpStreamStats; videoStreamStats?: RTCInboundRtpStreamStats | RTCOutboundRtpStreamStats; // The focus url, mainly for debugging purposes @@ -71,7 +71,7 @@ export const MediaView: FC = ({ raisedHandTime, currentReaction, raisedHandOnClick, - localParticipant, + waitingForMedia, audioStreamStats, videoStreamStats, focusUrl, @@ -129,7 +129,7 @@ export const MediaView: FC = ({ /> )} - {!video && !localParticipant && ( + {waitingForMedia && (
{t("video_tile.waiting_for_media")}
diff --git a/src/tile/SpotlightTile.test.tsx b/src/tile/SpotlightTile.test.tsx index fb7008b88..981c03694 100644 --- a/src/tile/SpotlightTile.test.tsx +++ b/src/tile/SpotlightTile.test.tsx @@ -17,6 +17,7 @@ import { mockRtcMembership, createLocalMedia, createRemoteMedia, + mockRemoteParticipant, } from "../utils/test"; import { SpotlightTileViewModel } from "../state/TileViewModel"; import { constant } from "../state/Behavior"; @@ -33,7 +34,7 @@ test("SpotlightTile is accessible", async () => { rawDisplayName: "Alice", getMxcAvatarUrl: () => "mxc://adfsg", }, - {}, + mockRemoteParticipant({}), ); const vm2 = createLocalMedia( diff --git a/src/tile/SpotlightTile.tsx b/src/tile/SpotlightTile.tsx index 48dd0f8cd..8109784f3 100644 --- a/src/tile/SpotlightTile.tsx +++ b/src/tile/SpotlightTile.tsx @@ -38,6 +38,7 @@ import { type MediaViewModel, ScreenShareViewModel, type UserMediaViewModel, + type RemoteUserMediaViewModel, } from "../state/MediaViewModel"; import { useInitial } from "../useInitial"; import { useMergedRefs } from "../useMergedRefs"; @@ -84,6 +85,21 @@ const SpotlightLocalUserMediaItem: FC = ({ SpotlightLocalUserMediaItem.displayName = "SpotlightLocalUserMediaItem"; +interface SpotlightRemoteUserMediaItemProps + extends SpotlightUserMediaItemBaseProps { + vm: RemoteUserMediaViewModel; +} + +const SpotlightRemoteUserMediaItem: FC = ({ + vm, + ...props +}) => { + const waitingForMedia = useBehavior(vm.waitingForMedia$); + return ( + + ); +}; + interface SpotlightUserMediaItemProps extends SpotlightItemBaseProps { vm: UserMediaViewModel; } @@ -103,7 +119,7 @@ const SpotlightUserMediaItem: FC = ({ return vm instanceof LocalUserMediaViewModel ? ( ) : ( - + ); }; diff --git a/src/utils/test.ts b/src/utils/test.ts index bd7dcd6f4..c69a22699 100644 --- a/src/utils/test.ts +++ b/src/utils/test.ts @@ -319,12 +319,12 @@ export function mockLocalParticipant( } export function createLocalMedia( - localRtcMember: CallMembership, + rtcMember: CallMembership, roomMember: Partial, localParticipant: LocalParticipant, mediaDevices: MediaDevices, ): LocalUserMediaViewModel { - const member = mockMatrixRoomMember(localRtcMember, roomMember); + const member = mockMatrixRoomMember(rtcMember, roomMember); return new LocalUserMediaViewModel( testScope(), "local", @@ -359,22 +359,26 @@ export function mockRemoteParticipant( } export function createRemoteMedia( - localRtcMember: CallMembership, + rtcMember: CallMembership, roomMember: Partial, - participant: Partial, + participant: RemoteParticipant | null, ): RemoteUserMediaViewModel { - const member = mockMatrixRoomMember(localRtcMember, roomMember); - const remoteParticipant = mockRemoteParticipant(participant); + const member = mockMatrixRoomMember(rtcMember, roomMember); return new RemoteUserMediaViewModel( testScope(), "remote", member.userId, - of(remoteParticipant), + constant(participant), { kind: E2eeType.PER_PARTICIPANT, }, constant( - mockLivekitRoom({}, { remoteParticipants$: of([remoteParticipant]) }), + mockLivekitRoom( + {}, + { + remoteParticipants$: of(participant ? [participant] : []), + }, + ), ), constant("https://rtc-example.org"), constant(false), From ea6f934667972f4db3fda40bc36c6b4927b75397 Mon Sep 17 00:00:00 2001 From: Robin Date: Wed, 10 Dec 2025 17:17:37 -0500 Subject: [PATCH 110/748] Don't show user as 'waiting for media' if they don't intend to publish We don't expect them to be publishing on any transport; they might be a subscribe-only bot. --- src/state/MediaViewModel.test.ts | 10 ++++++++++ src/state/MediaViewModel.ts | 9 ++++++++- src/utils/test.ts | 15 +++++++-------- 3 files changed, 25 insertions(+), 9 deletions(-) diff --git a/src/state/MediaViewModel.test.ts b/src/state/MediaViewModel.test.ts index 2ca14d19c..92868216a 100644 --- a/src/state/MediaViewModel.test.ts +++ b/src/state/MediaViewModel.test.ts @@ -226,3 +226,13 @@ test("remote media is not in waiting state when participant is connected with no ); expect(vm.waitingForMedia$.value).toBe(false); }); + +test("remote media is not in waiting state when user does not intend to publish anywhere", () => { + const vm = createRemoteMedia( + rtcMembership, + {}, + mockRemoteParticipant({}), + undefined, // No room (no advertised transport) + ); + expect(vm.waitingForMedia$.value).toBe(false); +}); diff --git a/src/state/MediaViewModel.ts b/src/state/MediaViewModel.ts index 3d0ff75b3..86119caa6 100644 --- a/src/state/MediaViewModel.ts +++ b/src/state/MediaViewModel.ts @@ -601,7 +601,14 @@ export class RemoteUserMediaViewModel extends BaseUserMediaViewModel { * could be because either we or the remote party are still connecting. */ public readonly waitingForMedia$ = this.scope.behavior( - this.participant$.pipe(map((participant) => participant === null)), + combineLatest( + [this.livekitRoom$, this.participant$], + (livekitRoom, participant) => + // If livekitRoom is undefined, the user is not attempting to publish on + // any transport and so we shouldn't expect a participant. (They might + // be a subscribe-only bot for example.) + livekitRoom !== undefined && participant === null, + ), ); // This private field is used to override the value from the superclass diff --git a/src/utils/test.ts b/src/utils/test.ts index c69a22699..b900d8015 100644 --- a/src/utils/test.ts +++ b/src/utils/test.ts @@ -362,6 +362,12 @@ export function createRemoteMedia( rtcMember: CallMembership, roomMember: Partial, participant: RemoteParticipant | null, + livekitRoom: LivekitRoom | undefined = mockLivekitRoom( + {}, + { + remoteParticipants$: of(participant ? [participant] : []), + }, + ), ): RemoteUserMediaViewModel { const member = mockMatrixRoomMember(rtcMember, roomMember); return new RemoteUserMediaViewModel( @@ -372,14 +378,7 @@ export function createRemoteMedia( { kind: E2eeType.PER_PARTICIPANT, }, - constant( - mockLivekitRoom( - {}, - { - remoteParticipants$: of(participant ? [participant] : []), - }, - ), - ), + constant(livekitRoom), constant("https://rtc-example.org"), constant(false), constant(member.rawDisplayName ?? "nodisplayname"), From 6149dd2c9a1277aa005954989931af883150c7ec Mon Sep 17 00:00:00 2001 From: Robin Date: Wed, 10 Dec 2025 17:18:58 -0500 Subject: [PATCH 111/748] Make the video behavior less confusing There's no reason to allow it to take on placeholder values. It should be defined when the media has a published video track and undefined when not. --- .../CallViewModel/localMember/Publisher.ts | 2 +- src/state/MediaViewModel.ts | 28 +++++++++---------- src/tile/GridTile.tsx | 2 +- 3 files changed, 15 insertions(+), 17 deletions(-) diff --git a/src/state/CallViewModel/localMember/Publisher.ts b/src/state/CallViewModel/localMember/Publisher.ts index df67f1799..21c5d801a 100644 --- a/src/state/CallViewModel/localMember/Publisher.ts +++ b/src/state/CallViewModel/localMember/Publisher.ts @@ -358,7 +358,7 @@ export class Publisher { const track$ = scope.behavior( observeTrackReference$(room.localParticipant, Track.Source.Camera).pipe( map((trackRef) => { - const track = trackRef?.publication?.track; + const track = trackRef?.publication.track; return track instanceof LocalVideoTrack ? track : null; }), ), diff --git a/src/state/MediaViewModel.ts b/src/state/MediaViewModel.ts index 86119caa6..9888d6bfb 100644 --- a/src/state/MediaViewModel.ts +++ b/src/state/MediaViewModel.ts @@ -7,8 +7,8 @@ Please see LICENSE in the repository root for full details. import { type AudioSource, - type TrackReferenceOrPlaceholder, type VideoSource, + type TrackReference, observeParticipantEvents, observeParticipantMedia, roomEventSelector, @@ -33,7 +33,6 @@ import { type Observable, Subject, combineLatest, - distinctUntilKeyChanged, filter, fromEvent, interval, @@ -60,14 +59,11 @@ import { type ObservableScope } from "./ObservableScope"; export function observeTrackReference$( participant: Participant, source: Track.Source, -): Observable { +): Observable { return observeParticipantMedia(participant).pipe( - map(() => ({ - participant: participant, - publication: participant.getTrackPublication(source), - source, - })), - distinctUntilKeyChanged("publication"), + map(() => participant.getTrackPublication(source)), + distinctUntilChanged(), + map((publication) => publication && { participant, publication, source }), ); } @@ -226,7 +222,7 @@ abstract class BaseMediaViewModel { /** * The LiveKit video track for this media. */ - public readonly video$: Behavior; + public readonly video$: Behavior; /** * Whether there should be a warning that this media is unencrypted. */ @@ -241,10 +237,12 @@ abstract class BaseMediaViewModel { private observeTrackReference$( source: Track.Source, - ): Behavior { + ): Behavior { return this.scope.behavior( this.participant$.pipe( - switchMap((p) => (!p ? of(null) : observeTrackReference$(p, source))), + switchMap((p) => + !p ? of(undefined) : observeTrackReference$(p, source), + ), ), ); } @@ -281,8 +279,8 @@ abstract class BaseMediaViewModel { [audio$, this.video$], (a, v) => encryptionSystem.kind !== E2eeType.NONE && - (a?.publication?.isEncrypted === false || - v?.publication?.isEncrypted === false), + (a?.publication.isEncrypted === false || + v?.publication.isEncrypted === false), ), ); @@ -471,7 +469,7 @@ export class LocalUserMediaViewModel extends BaseUserMediaViewModel { private readonly videoTrack$: Observable = this.video$.pipe( switchMap((v) => { - const track = v?.publication?.track; + const track = v?.publication.track; if (!(track instanceof LocalVideoTrack)) return of(null); return merge( // Watch for track restarts because they indicate a camera switch. diff --git a/src/tile/GridTile.tsx b/src/tile/GridTile.tsx index 7768e8f02..2f750c50a 100644 --- a/src/tile/GridTile.tsx +++ b/src/tile/GridTile.tsx @@ -150,7 +150,7 @@ const UserMediaTile: FC = ({ const tile = ( Date: Tue, 16 Dec 2025 11:20:38 +0100 Subject: [PATCH 112/748] switch synapse docker image to one with sticky event support --- dev-backend-docker-compose.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dev-backend-docker-compose.yml b/dev-backend-docker-compose.yml index c7591847c..5e955831c 100644 --- a/dev-backend-docker-compose.yml +++ b/dev-backend-docker-compose.yml @@ -88,7 +88,7 @@ services: synapse: hostname: homeserver - image: docker.io/matrixdotorg/synapse:latest + image: ghcr.io/element-hq/synapse:pr-18968-dcb7678281bc02d4551043a6338fe5b7e6aa47ce pull_policy: always environment: - SYNAPSE_CONFIG_PATH=/data/cfg/homeserver.yaml @@ -106,7 +106,7 @@ services: synapse-1: hostname: homeserver-1 - image: docker.io/matrixdotorg/synapse:latest + image: ghcr.io/element-hq/synapse:pr-18968-dcb7678281bc02d4551043a6338fe5b7e6aa47ce pull_policy: always environment: - SYNAPSE_CONFIG_PATH=/data/cfg/homeserver.yaml From ff3d6bd088f5024207c2921830b374e0e9c0fa71 Mon Sep 17 00:00:00 2001 From: fkwp Date: Tue, 16 Dec 2025 11:22:25 +0100 Subject: [PATCH 113/748] enable sticky events --- backend/dev_homeserver-othersite.yaml | 2 ++ backend/dev_homeserver.yaml | 2 +- backend/playwright_homeserver-othersite.yaml | 2 ++ backend/playwright_homeserver.yaml | 2 ++ 4 files changed, 7 insertions(+), 1 deletion(-) diff --git a/backend/dev_homeserver-othersite.yaml b/backend/dev_homeserver-othersite.yaml index 947e33cde..81e775cab 100644 --- a/backend/dev_homeserver-othersite.yaml +++ b/backend/dev_homeserver-othersite.yaml @@ -38,6 +38,8 @@ experimental_features: # MSC4222 needed for syncv2 state_after. This allow clients to # correctly track the state of the room. msc4222_enabled: true + # sticky events for MatrixRTC user state + msc4354_enabled: true # The maximum allowed duration by which sent events can be delayed, as # per MSC4140. Must be a positive value if set. Defaults to no diff --git a/backend/dev_homeserver.yaml b/backend/dev_homeserver.yaml index fe89d95a4..dc7b42c84 100644 --- a/backend/dev_homeserver.yaml +++ b/backend/dev_homeserver.yaml @@ -38,7 +38,7 @@ experimental_features: # MSC4222 needed for syncv2 state_after. This allow clients to # correctly track the state of the room. msc4222_enabled: true - # sticky events for matrixRTC user state + # sticky events for MatrixRTC user state msc4354_enabled: true # The maximum allowed duration by which sent events can be delayed, as diff --git a/backend/playwright_homeserver-othersite.yaml b/backend/playwright_homeserver-othersite.yaml index 5cb0dd65d..35640ae9a 100644 --- a/backend/playwright_homeserver-othersite.yaml +++ b/backend/playwright_homeserver-othersite.yaml @@ -38,6 +38,8 @@ experimental_features: # MSC4222 needed for syncv2 state_after. This allow clients to # correctly track the state of the room. msc4222_enabled: true + # sticky events for MatrixRTC user state + msc4354_enabled: true # The maximum allowed duration by which sent events can be delayed, as # per MSC4140. Must be a positive value if set. Defaults to no diff --git a/backend/playwright_homeserver.yaml b/backend/playwright_homeserver.yaml index 0d7b175c2..a83247cd9 100644 --- a/backend/playwright_homeserver.yaml +++ b/backend/playwright_homeserver.yaml @@ -38,6 +38,8 @@ experimental_features: # MSC4222 needed for syncv2 state_after. This allow clients to # correctly track the state of the room. msc4222_enabled: true + # sticky events for MatrixRTC user state + msc4354_enabled: true # The maximum allowed duration by which sent events can be delayed, as # per MSC4140. Must be a positive value if set. Defaults to no From 80e760ca55d7e454f73d6fb36f33d3f036b36d67 Mon Sep 17 00:00:00 2001 From: Valere Date: Tue, 16 Dec 2025 13:40:06 +0100 Subject: [PATCH 114/748] review --- .../CallViewModel/localMember/LocalMember.ts | 38 +++++-------------- .../localMember/Publisher.test.ts | 2 +- .../CallViewModel/localMember/Publisher.ts | 35 ++++++++++------- 3 files changed, 32 insertions(+), 43 deletions(-) diff --git a/src/state/CallViewModel/localMember/LocalMember.ts b/src/state/CallViewModel/localMember/LocalMember.ts index daadbe7c9..9ef94fe4c 100644 --- a/src/state/CallViewModel/localMember/LocalMember.ts +++ b/src/state/CallViewModel/localMember/LocalMember.ts @@ -37,7 +37,7 @@ import { import { type Logger } from "matrix-js-sdk/lib/logger"; import { deepCompare } from "matrix-js-sdk/lib/utils"; -import { constant, type Behavior } from "../../Behavior.ts"; +import { type Behavior } from "../../Behavior.ts"; import { type IConnectionManager } from "../remoteMembers/ConnectionManager.ts"; import { type ObservableScope } from "../../ObservableScope.ts"; import { type Publisher } from "./Publisher.ts"; @@ -68,6 +68,8 @@ export enum TransportState { export enum PublishState { WaitingForUser = "publish_waiting_for_user", + // XXX: This state is removed for now since we do not have full control over + // track publication anymore with the publisher abstraction, might come back in the future? // /** Implies lk connection is connected */ // Starting = "publish_start_publishing", /** Implies lk connection is connected */ @@ -79,6 +81,8 @@ export enum PublishState { export enum TrackState { /** The track is waiting for user input to create tracks (waiting to call `startTracks()`) */ WaitingForUser = "tracks_waiting_for_user", + // XXX: This state is removed for now since we do not have full control over + // track creation anymore with the publisher abstraction, might come back in the future? // /** Implies lk connection is connected */ // Creating = "tracks_creating", /** Implies lk connection is connected */ @@ -154,9 +158,10 @@ export const createLocalMembership$ = ({ matrixRTCSession, }: Props): { /** - * This starts audio and video tracks. They will be reused when calling `requestPublish`. + * This request to start audio and video tracks. + * Can be called early to pre-emptively get media permissions and start devices. */ - startTracks: () => Behavior; + startTracks: () => void; /** * This sets a inner state (shouldPublish) to true and instructs the js-sdk and livekit to keep the user * connected to matrix and livekit. @@ -265,19 +270,10 @@ export const createLocalMembership$ = ({ * The publisher is stored in here an abstracts creating and publishing tracks. */ const publisher$ = new BehaviorSubject(null); - /** - * Extract the tracks from the published. Also reacts to changing publishers. - */ - // const tracks$ = scope.behavior( - // publisher$.pipe(switchMap((p) => (p?.tracks$ ? p.tracks$ : constant([])))), - // ); - // const publishing$ = scope.behavior( - // publisher$.pipe(switchMap((p) => p?.publishing$ ?? constant(false))), - // ); - const startTracks = (): Behavior => { + const startTracks = (): void => { trackStartRequested.resolve(); - return constant(undefined); + // This used to return the tracks, but now they are only accessible via the publisher. }; const requestJoinAndPublish = (): void => { @@ -348,14 +344,6 @@ export const createLocalMembership$ = ({ setPublishError(new UnknownCallError(error as Error)); } } - // XXX Why is that? - // else { - // try { - // await publisher?.stopPublishing(); - // } catch (error) { - // setLivekitError(new UnknownCallError(error as Error)); - // } - // } }, ); @@ -401,16 +389,10 @@ export const createLocalMembership$ = ({ ([ localConnectionState, localTransport, - // tracks, - // publishing, shouldPublish, shouldStartTracks, ]) => { if (!localTransport) return null; - // const hasTracks = tracks.length > 0; - // let trackState: TrackState = TrackState.WaitingForUser; - // if (hasTracks && shouldStartTracks) trackState = TrackState.Ready; - // if (!hasTracks && shouldStartTracks) trackState = TrackState.Creating; const trackState: TrackState = shouldStartTracks ? TrackState.Ready : TrackState.WaitingForUser; diff --git a/src/state/CallViewModel/localMember/Publisher.test.ts b/src/state/CallViewModel/localMember/Publisher.test.ts index 3cc96bc2d..38a80beda 100644 --- a/src/state/CallViewModel/localMember/Publisher.test.ts +++ b/src/state/CallViewModel/localMember/Publisher.test.ts @@ -34,7 +34,7 @@ beforeEach(() => { scope = new ObservableScope(); }); -// afterEach(() => scope.end()); +afterEach(() => scope.end()); function createMockLocalTrack(source: Track.Source): LocalTrack { const track = { diff --git a/src/state/CallViewModel/localMember/Publisher.ts b/src/state/CallViewModel/localMember/Publisher.ts index d4ad656c4..4428d8454 100644 --- a/src/state/CallViewModel/localMember/Publisher.ts +++ b/src/state/CallViewModel/localMember/Publisher.ts @@ -97,7 +97,7 @@ export class Publisher { // it would also prevent the user from seeing their own video/audio preview. // So for that we use pauseUpStream(): Stops sending media to the server by replacing // the sender track with null, but keeps the local MediaStreamTrack active. - // The user can still see/hear themselves locally, but remote participants see nothing + // The user can still see/hear themselves locally, but remote participants see nothing. private onLocalTrackPublished( localTrackPublication: LocalTrackPublication, ): void { @@ -128,6 +128,15 @@ export class Publisher { } } /** + * Create and setup local audio and video tracks based on the current mute states. + * It creates the tracks only if audio and/or video is enabled, to avoid unnecessary + * permission prompts. + * + * It also observes mute state changes to update LiveKit microphone/camera states accordingly. + * If a track is not created initially because disabled, it will be created when unmuting. + * + * This call is not blocking anymore, instead callers can listen to the + * `RoomEvent.MediaDevicesError` event in the LiveKit room to be notified of any errors. * */ public async createAndSetupTracks(): Promise { @@ -141,25 +150,21 @@ export class Publisher { const audio = this.muteStates.audio.enabled$.value; const video = this.muteStates.video.enabled$.value; - const enableTracks = async (): Promise => { - if (audio && video) { - // Enable both at once in order to have a single permission prompt! - await lkRoom.localParticipant.enableCameraAndMicrophone(); - } else if (audio) { - await lkRoom.localParticipant.setMicrophoneEnabled(true); - } else if (video) { - await lkRoom.localParticipant.setCameraEnabled(true); - } - return; - }; - // We don't await enableTracks, because livekit could block until the tracks + // We don't await the creation, because livekit could block until the tracks // are fully published, and not only that they are created. // We don't have control on that, localParticipant creates and publishes the tracks // asap. // We are using the `ParticipantEvent.LocalTrackPublished` to be notified // when tracks are actually published, and at that point // we can pause upstream if needed (depending on if startPublishing has been called). - void enableTracks(); + if (audio && video) { + // Enable both at once in order to have a single permission prompt! + void lkRoom.localParticipant.enableCameraAndMicrophone(); + } else if (audio) { + void lkRoom.localParticipant.setMicrophoneEnabled(true); + } else if (video) { + void lkRoom.localParticipant.setCameraEnabled(true); + } return Promise.resolve(); } @@ -233,6 +238,8 @@ export class Publisher { public async stopPublishing(): Promise { this.logger.debug("stopPublishing called"); this.shouldPublish = false; + // Pause upstream will stop sending media to the server, while keeping + // the local MediaStreamTrack active, so the user can still see themselves. await this.pauseUpstreams(this.connection.livekitRoom, [ Track.Source.Microphone, Track.Source.Camera, From ab7e3486b3ea1953f1435acbced309189476e78b Mon Sep 17 00:00:00 2001 From: Timo K Date: Wed, 17 Dec 2025 09:53:49 +0100 Subject: [PATCH 115/748] Make use of the new jwt service endpoint (with delayed event delegation) This also does all the compatibility work. When to use which endpoint to authenticate agains a jwt service. --- src/livekit/openIDSFU.ts | 90 ++++++++++++++++--- src/state/CallViewModel/CallViewModel.ts | 32 ++++++- .../localMember/LocalMember.test.ts | 3 + .../CallViewModel/localMember/LocalMember.ts | 5 +- .../localMember/LocalTransport.test.ts | 18 +++- .../localMember/LocalTransport.ts | 63 +++++++++---- .../remoteMembers/Connection.test.ts | 17 ++-- .../CallViewModel/remoteMembers/Connection.ts | 20 ++++- .../remoteMembers/ConnectionFactory.ts | 18 +++- .../remoteMembers/ConnectionManager.test.ts | 13 ++- .../remoteMembers/ConnectionManager.ts | 27 ++++-- .../remoteMembers/ECConnectionFactory.test.ts | 20 ++++- .../remoteMembers/MatrixLivekitMembers.ts | 6 +- .../remoteMembers/integration.test.ts | 2 + src/state/SessionBehaviors.ts | 15 +++- src/utils/test.ts | 10 ++- yarn.lock | 9 +- 17 files changed, 294 insertions(+), 74 deletions(-) diff --git a/src/livekit/openIDSFU.ts b/src/livekit/openIDSFU.ts index 3ae003fb1..f07bb0359 100644 --- a/src/livekit/openIDSFU.ts +++ b/src/livekit/openIDSFU.ts @@ -7,9 +7,11 @@ Please see LICENSE in the repository root for full details. import { type IOpenIDToken, type MatrixClient } from "matrix-js-sdk"; import { logger } from "matrix-js-sdk/lib/logger"; +import { type CallMembershipIdentityParts } from "matrix-js-sdk/lib/matrixrtc/EncryptionManager"; import { FailToGetOpenIdToken } from "../utils/errors"; import { doNetworkOperationWithRetry } from "../utils/matrix"; +import { Config } from "../config/Config"; export interface SFUConfig { url: string; @@ -33,8 +35,12 @@ export type OpenIDClientParts = Pick< */ export async function getSFUConfigWithOpenID( client: OpenIDClientParts, + membership: CallMembershipIdentityParts, serviceUrl: string, - matrixRoomId: string, + livekitRoomAlias: string, + matrix2jwt: boolean, + delayEndpointBaseUrl?: string, + delayId?: string, ): Promise { let openIdToken: IOpenIDToken; try { @@ -49,21 +55,31 @@ export async function getSFUConfigWithOpenID( logger.debug("Got openID token", openIdToken); logger.info(`Trying to get JWT for focus ${serviceUrl}...`); - const sfuConfig = await getLiveKitJWT( - client, + const args: [CallMembershipIdentityParts, string, string, IOpenIDToken] = [ + membership, serviceUrl, - matrixRoomId, + livekitRoomAlias, openIdToken, - ); - logger.info(`Got JWT from call's active focus URL.`); - - return sfuConfig; + ]; + if (matrix2jwt) { + const sfuConfig = await getLiveKitJWTWithDelayDelegation( + ...args, + delayEndpointBaseUrl, + delayId, + ); + logger.info(`Got JWT from call's active focus URL.`); + return sfuConfig; + } else { + const sfuConfig = await getLiveKitJWT(...args); + logger.info(`Got JWT from call's active focus URL.`); + return sfuConfig; + } } async function getLiveKitJWT( - client: OpenIDClientParts, + membership: CallMembershipIdentityParts, livekitServiceURL: string, - roomName: string, + livekitRoomAlias: string, openIDToken: IOpenIDToken, ): Promise { try { @@ -73,9 +89,9 @@ async function getLiveKitJWT( "Content-Type": "application/json", }, body: JSON.stringify({ - room: roomName, + room: livekitRoomAlias, openid_token: openIDToken, - device_id: client.getDeviceId(), + device_id: membership.deviceId, }), }); if (!res.ok) { @@ -86,3 +102,53 @@ async function getLiveKitJWT( throw new Error("SFU Config fetch failed with exception " + e); } } + +export async function getLiveKitJWTWithDelayDelegation( + membership: CallMembershipIdentityParts, + livekitServiceURL: string, + livekitRoomAlias: string, + openIDToken: IOpenIDToken, + delayEndpointBaseUrl?: string, + delayId?: string, +): Promise { + const { userId, deviceId, memberId } = membership; + + const body = { + room_id: livekitRoomAlias, + slot_id: "m.call#ROOM", + openid_token: openIDToken, + member: { + id: memberId, + claimed_user_id: userId, + claimed_device_id: deviceId, + }, + }; + + let bodyDalayParts = {}; + // Also check for empty string + if (delayId && delayEndpointBaseUrl) { + const delayTimeoutMs = + Config.get().matrix_rtc_session?.delayed_leave_event_delay_ms ?? 1000; + bodyDalayParts = { + delay_id: delayId, + delay_timeout: delayTimeoutMs, + delay_cs_api_url: delayEndpointBaseUrl, + }; + } + + try { + const res = await fetch(livekitServiceURL + "/get_token", { + method: "POST", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify({ ...body, ...bodyDalayParts }), + }); + if (!res.ok) { + throw new Error("SFU Config fetch failed with status code " + res.status); + } + return await res.json(); + } catch (e) { + throw new Error("SFU Config fetch failed with exception " + e); + } +} diff --git a/src/state/CallViewModel/CallViewModel.ts b/src/state/CallViewModel/CallViewModel.ts index e1869cf60..23c58268c 100644 --- a/src/state/CallViewModel/CallViewModel.ts +++ b/src/state/CallViewModel/CallViewModel.ts @@ -41,10 +41,12 @@ import { } from "rxjs"; import { logger as rootLogger } from "matrix-js-sdk/lib/logger"; import { + MembershipManagerEvent, type LivekitTransport, type MatrixRTCSession, } from "matrix-js-sdk/lib/matrixrtc"; import { type IWidgetApiRequest } from "matrix-widget-api"; +import { type CallMembershipIdentityParts } from "matrix-js-sdk/lib/matrixrtc/EncryptionManager"; import { LocalUserMediaViewModel, @@ -98,7 +100,7 @@ import { type SpotlightLandscapeLayoutMedia, type SpotlightPortraitLayoutMedia, } from "../layout-types.ts"; -import { ElementCallError } from "../../utils/errors.ts"; +import { ElementCallError, UnknownCallError } from "../../utils/errors.ts"; import { type ObservableScope } from "../ObservableScope.ts"; import { createHomeserverConnected$ } from "./localMember/HomeserverConnected.ts"; import { @@ -375,8 +377,11 @@ export function createCallViewModel$( trackProcessorState$: Behavior, ): CallViewModel { const client = matrixRoom.client; - const userId = client.getUserId()!; - const deviceId = client.getDeviceId()!; + const userId = client.getUserId(); + const deviceId = client.getDeviceId(); + if (!(userId && deviceId)) + throw new UnknownCallError(new Error("userId and deviceId are required")); + const livekitKeyProvider = getE2eeKeyProvider( options.encryptionSystem, matrixRTCSession, @@ -407,10 +412,29 @@ export function createCallViewModel$( memberships$, ); + const ownMembershipIdentity: CallMembershipIdentityParts = { + userId, + deviceId, + memberId: `${userId}:${deviceId}`, + }; + const localTransport$ = createLocalTransport$({ scope: scope, memberships$: memberships$, + ownMembershipIdentity, client, + useMatrix2$: scope.behavior( + options.matrixRTCMode$.pipe(map((v) => v === MatrixRTCMode.Matrix_2_0)), + ), + delayId$: scope.behavior( + ( + fromEvent( + matrixRTCSession, + MembershipManagerEvent.DelayIdChanged, + ) as Observable + ).pipe(map((v) => v ?? null)), + matrixRTCSession.delayId ?? null, + ), roomId: matrixRoom.roomId, useOldestMember$: scope.behavior( options.matrixRTCMode$.pipe(map((v) => v === MatrixRTCMode.Legacy)), @@ -455,6 +479,7 @@ export function createCallViewModel$( ), ), logger: logger, + ownMembershipIdentity, }); const matrixLivekitMembers$ = createMatrixLivekitMembers$({ @@ -485,6 +510,7 @@ export function createCallViewModel$( joinMatrixRTC: (transport: LivekitTransport) => { return enterRTCSession( matrixRTCSession, + ownMembershipIdentity, transport, connectOptions$.value, ); diff --git a/src/state/CallViewModel/localMember/LocalMember.test.ts b/src/state/CallViewModel/localMember/LocalMember.test.ts index 6a9f196e9..8de14039f 100644 --- a/src/state/CallViewModel/localMember/LocalMember.test.ts +++ b/src/state/CallViewModel/localMember/LocalMember.test.ts @@ -24,6 +24,7 @@ import { mockLivekitRoom, mockMuteStates, withTestScheduler, + ownMemberMock, } from "../../../utils/test"; import { TransportState, @@ -108,6 +109,7 @@ describe("LocalMembership", () => { enterRTCSession( mockedSession, + ownMemberMock, { livekit_alias: "roomId", livekit_service_url: "http://my-well-known-service-url.com", @@ -166,6 +168,7 @@ describe("LocalMembership", () => { enterRTCSession( mockedSession, + ownMemberMock, { livekit_alias: "roomId", livekit_service_url: "http://my-well-known-service-url.com", diff --git a/src/state/CallViewModel/localMember/LocalMember.ts b/src/state/CallViewModel/localMember/LocalMember.ts index 40fb62d62..6f554423f 100644 --- a/src/state/CallViewModel/localMember/LocalMember.ts +++ b/src/state/CallViewModel/localMember/LocalMember.ts @@ -34,6 +34,7 @@ import { } from "rxjs"; import { type Logger } from "matrix-js-sdk/lib/logger"; import { deepCompare } from "matrix-js-sdk/lib/utils"; +import { type CallMembershipIdentityParts } from "matrix-js-sdk/lib/matrixrtc/EncryptionManager"; import { constant, type Behavior } from "../../Behavior.ts"; import { type IConnectionManager } from "../remoteMembers/ConnectionManager.ts"; @@ -657,6 +658,7 @@ interface EnterRTCSessionOptions { // Exported for unit testing export function enterRTCSession( rtcSession: MatrixRTCSession, + ownMembershipIdentity: CallMembershipIdentityParts, transport: LivekitTransport, { encryptMedia, matrixRTCMode }: EnterRTCSessionOptions, ): void { @@ -674,7 +676,8 @@ export function enterRTCSession( const multiSFU = matrixRTCMode !== MatrixRTCMode.Legacy; // Multi-sfu does not need a preferred foci list. just the focus that is actually used. // TODO where/how do we track errors originating from the ongoing rtcSession? - rtcSession.joinRoomSession( + rtcSession.joinRTCSession( + ownMembershipIdentity, multiSFU ? [] : [transport], multiSFU ? transport : undefined, { diff --git a/src/state/CallViewModel/localMember/LocalTransport.test.ts b/src/state/CallViewModel/localMember/LocalTransport.test.ts index c1c36fa5a..ba0307575 100644 --- a/src/state/CallViewModel/localMember/LocalTransport.test.ts +++ b/src/state/CallViewModel/localMember/LocalTransport.test.ts @@ -9,7 +9,7 @@ import { afterEach, beforeEach, describe, expect, it, vi } from "vitest"; import { type CallMembership } from "matrix-js-sdk/lib/matrixrtc"; import { BehaviorSubject } from "rxjs"; -import { mockConfig, flushPromises } from "../../../utils/test"; +import { mockConfig, flushPromises, ownMemberMock } from "../../../utils/test"; import { createLocalTransport$ } from "./LocalTransport"; import { constant } from "../../Behavior"; import { Epoch, ObservableScope } from "../../ObservableScope"; @@ -32,10 +32,14 @@ describe("LocalTransport", () => { memberships$: constant(new Epoch([])), client: { getDomain: () => "", + baseUrl: "example.org", // These won't be called in this error path but satisfy the type getOpenIdToken: vi.fn(), getDeviceId: vi.fn(), }, + ownMembershipIdentity: ownMemberMock, + useMatrix2$: constant(false), + delayId$: constant("delay_id_mock"), }); await flushPromises(); @@ -65,11 +69,15 @@ describe("LocalTransport", () => { useOldestMember$: constant(false), memberships$: constant(new Epoch([])), client: { + baseUrl: "https://lk.example.org", // Use empty domain to skip .well-known and use config directly getDomain: () => "", getOpenIdToken: vi.fn(), getDeviceId: vi.fn(), }, + ownMembershipIdentity: ownMemberMock, + useMatrix2$: constant(false), + delayId$: constant("delay_id_mock"), }); localTransport$.subscribe( (o) => observations.push(o), @@ -105,7 +113,11 @@ describe("LocalTransport", () => { getDomain: () => "", getOpenIdToken: vi.fn(), getDeviceId: vi.fn(), + baseUrl: "https://lk.example.org", }, + ownMembershipIdentity: ownMemberMock, + useMatrix2$: constant(false), + delayId$: constant("delay_id_mock"), }); openIdResolver.resolve?.({ url: "https://lk.example.org", jwt: "jwt" }); @@ -140,7 +152,11 @@ describe("LocalTransport", () => { getDomain: () => "", getOpenIdToken: vi.fn(), getDeviceId: vi.fn(), + baseUrl: "https://lk.example.org", }, + ownMembershipIdentity: ownMemberMock, + useMatrix2$: constant(false), + delayId$: constant("delay_id_mock"), }); openIdResolver.resolve?.({ url: "https://lk.example.org", jwt: "jwt" }); diff --git a/src/state/CallViewModel/localMember/LocalTransport.ts b/src/state/CallViewModel/localMember/LocalTransport.ts index 1320b8c46..6c3e1cd0a 100644 --- a/src/state/CallViewModel/localMember/LocalTransport.ts +++ b/src/state/CallViewModel/localMember/LocalTransport.ts @@ -23,6 +23,7 @@ import { } from "rxjs"; import { logger as rootLogger } from "matrix-js-sdk/lib/logger"; import { AutoDiscovery } from "matrix-js-sdk/lib/autodiscovery"; +import { type CallMembershipIdentityParts } from "matrix-js-sdk/lib/matrixrtc/EncryptionManager"; import { type Behavior } from "../../Behavior.ts"; import { type Epoch, type ObservableScope } from "../../ObservableScope.ts"; @@ -34,6 +35,7 @@ import { } from "../../../livekit/openIDSFU.ts"; import { areLivekitTransportsEqual } from "../remoteMembers/MatrixLivekitMembers.ts"; import { customLivekitUrl } from "../../../settings/settings.ts"; +import { type LivekitTransportWithVersion } from "../remoteMembers/ConnectionManager.ts"; const logger = rootLogger.getChild("[LocalTransport]"); @@ -44,10 +46,13 @@ const logger = rootLogger.getChild("[LocalTransport]"); */ interface Props { scope: ObservableScope; + ownMembershipIdentity: CallMembershipIdentityParts; memberships$: Behavior>; - client: Pick & OpenIDClientParts; + client: Pick & OpenIDClientParts; roomId: string; useOldestMember$: Behavior; + useMatrix2$: Behavior; + delayId$: Behavior; } /** @@ -62,20 +67,26 @@ interface Props { export const createLocalTransport$ = ({ scope, memberships$, + ownMembershipIdentity, client, roomId, useOldestMember$, -}: Props): Behavior => { + useMatrix2$, + delayId$, +}: Props): Behavior => { /** * The transport over which we should be actively publishing our media. * undefined when not joined. */ const oldestMemberTransport$ = scope.behavior( memberships$.pipe( - map( - (memberships) => - memberships.value[0]?.getTransport(memberships.value[0]) ?? null, - ), + map((memberships) => { + const oldestMember = memberships.value[0]; + const t = oldestMember?.getTransport(memberships.value[0]); + if (!t) return null; + // Here we will use the matrix2 information from the oldest member transport. + return { ...t, useMatrix2: oldestMember.kind === "rtc" }; + }), first((t) => t != null && isLivekitTransport(t)), ), null, @@ -87,12 +98,24 @@ export const createLocalTransport$ = ({ * * @throws MatrixRTCTransportMissingError | FailToGetOpenIdToken */ - const preferredTransport$: Behavior = scope.behavior( - customLivekitUrl.value$.pipe( - switchMap((customUrl) => from(makeTransport(client, roomId, customUrl))), - ), - null, - ); + const preferredTransport$: Behavior = + scope.behavior( + combineLatest([customLivekitUrl.value$, useMatrix2$, delayId$]).pipe( + switchMap(([customUrl, useMatrix2, delayId]) => + from( + makeTransport( + client, + ownMembershipIdentity, + roomId, + customUrl, + useMatrix2, + delayId ?? undefined, + ), + ), + ), + ), + null, + ); /** * The chosen transport we should advertise in our MatrixRTC membership. @@ -123,10 +146,13 @@ const FOCI_WK_KEY = "org.matrix.msc4143.rtc_foci"; * @throws MatrixRTCTransportMissingError | FailToGetOpenIdToken */ async function makeTransport( - client: Pick & OpenIDClientParts, + client: Pick & OpenIDClientParts, + membership: CallMembershipIdentityParts, roomId: string, urlFromDevSettings: string | null, -): Promise { + matrix2jwt = false, + delayId?: string, +): Promise { let transport: LivekitTransport | undefined; logger.trace("Searching for a preferred transport"); //TODO refactor this to use the jwt service returned alias. @@ -176,13 +202,18 @@ async function makeTransport( transport = transportFromConf; } - if (!transport) throw new MatrixRTCTransportMissingError(domain ?? ""); // this will call the jwt/sfu/get endpoint to pre create the livekit room. + if (!transport) throw new MatrixRTCTransportMissingError(domain ?? ""); + // this will call the jwt/sfu/get endpoint to pre create the livekit room. await getSFUConfigWithOpenID( client, + membership, transport.livekit_service_url, transport.livekit_alias, + matrix2jwt, + client.baseUrl, + delayId, ); - return transport; + return { ...transport, useMatrix2: matrix2jwt }; } diff --git a/src/state/CallViewModel/remoteMembers/Connection.test.ts b/src/state/CallViewModel/remoteMembers/Connection.test.ts index 30c934b94..533f451a4 100644 --- a/src/state/CallViewModel/remoteMembers/Connection.test.ts +++ b/src/state/CallViewModel/remoteMembers/Connection.test.ts @@ -27,7 +27,6 @@ import EventEmitter from "events"; import { type IOpenIDToken } from "matrix-js-sdk"; import { logger } from "matrix-js-sdk/lib/logger"; -import type { LivekitTransport } from "matrix-js-sdk/lib/matrixrtc"; import { Connection, ConnectionState, @@ -39,7 +38,8 @@ import { ElementCallError, FailToGetOpenIdToken, } from "../../../utils/errors.ts"; -import { mockRemoteParticipant } from "../../../utils/test.ts"; +import { mockRemoteParticipant, ownMemberMock } from "../../../utils/test.ts"; +import { type LivekitTransportWithVersion } from "./ConnectionManager.ts"; let testScope: ObservableScope; @@ -50,10 +50,11 @@ let fakeLivekitRoom: MockedObject; let localParticipantEventEmiter: EventEmitter; let fakeLocalParticipant: MockedObject; -const livekitFocus: LivekitTransport = { +const livekitFocus: LivekitTransportWithVersion = { livekit_alias: "!roomID:example.org", livekit_service_url: "https://matrix-rtc.example.org/livekit/jwt", type: "livekit", + useMatrix2: false, }; function setupTest(): void { @@ -137,7 +138,7 @@ function setupRemoteConnection(): Connection { return Promise.resolve(); }); - return new Connection(opts, logger); + return new Connection(opts, logger, ownMemberMock); } afterEach(() => { @@ -156,7 +157,7 @@ describe("Start connection states", () => { scope: testScope, livekitRoomFactory: () => fakeLivekitRoom, }; - const connection = new Connection(opts, logger); + const connection = new Connection(opts, logger, ownMemberMock); expect(connection.state$.getValue()).toEqual("Initialized"); }); @@ -172,7 +173,7 @@ describe("Start connection states", () => { livekitRoomFactory: () => fakeLivekitRoom, }; - const connection = new Connection(opts, logger); + const connection = new Connection(opts, logger, ownMemberMock); const capturedStates: (ConnectionState | Error)[] = []; const s = connection.state$.subscribe((value) => { @@ -222,7 +223,7 @@ describe("Start connection states", () => { livekitRoomFactory: () => fakeLivekitRoom, }; - const connection = new Connection(opts, logger); + const connection = new Connection(opts, logger, ownMemberMock); const capturedStates: (ConnectionState | Error)[] = []; const s = connection.state$.subscribe((value) => { @@ -279,7 +280,7 @@ describe("Start connection states", () => { livekitRoomFactory: () => fakeLivekitRoom, }; - const connection = new Connection(opts, logger); + const connection = new Connection(opts, logger, ownMemberMock); const capturedStates: (ConnectionState | Error)[] = []; const s = connection.state$.subscribe((value) => { diff --git a/src/state/CallViewModel/remoteMembers/Connection.ts b/src/state/CallViewModel/remoteMembers/Connection.ts index 05d0ec9e9..d32bbce69 100644 --- a/src/state/CallViewModel/remoteMembers/Connection.ts +++ b/src/state/CallViewModel/remoteMembers/Connection.ts @@ -18,6 +18,7 @@ import { import { type LivekitTransport } from "matrix-js-sdk/lib/matrixrtc"; import { BehaviorSubject, map } from "rxjs"; import { type Logger } from "matrix-js-sdk/lib/logger"; +import { type CallMembershipIdentityParts } from "matrix-js-sdk/lib/matrixrtc/EncryptionManager"; import { getSFUConfigWithOpenID, @@ -35,7 +36,7 @@ import { export interface ConnectionOpts { /** The media transport to connect to. */ - transport: LivekitTransport; + transport: LivekitTransport & { useMatrix2: boolean }; /** The Matrix client to use for OpenID and SFU config requests. */ client: OpenIDClientParts; /** The observable scope to use for this connection. */ @@ -88,7 +89,7 @@ export class Connection { /** * The media transport to connect to. */ - public readonly transport: LivekitTransport; + public readonly transport: LivekitTransport & { useMatrix2: boolean }; public readonly livekitRoom: LivekitRoom; @@ -189,9 +190,18 @@ export class Connection { protected async getSFUConfigWithOpenID(): Promise { return await getSFUConfigWithOpenID( this.client, + this.ownMembershipIdentity, this.transport.livekit_service_url, this.transport.livekit_alias, + this.transport.useMatrix2, ); + // client: OpenIDClientParts, + // membership: CallMembershipIdentityParts, + // serviceUrl: string, + // livekitRoomAlias: string, + // matrix2jwt: boolean, + // delayEndpointBaseUrl?: string, + // delayId?: string, } /** @@ -220,7 +230,11 @@ export class Connection { * * @param logger */ - public constructor(opts: ConnectionOpts, logger: Logger) { + public constructor( + opts: ConnectionOpts, + logger: Logger, + private ownMembershipIdentity: CallMembershipIdentityParts, + ) { this.logger = logger.getChild("[Connection]"); this.logger.info( `[Connection] Creating new connection to ${opts.transport.livekit_service_url} ${opts.transport.livekit_alias}`, diff --git a/src/state/CallViewModel/remoteMembers/ConnectionFactory.ts b/src/state/CallViewModel/remoteMembers/ConnectionFactory.ts index 7c3a9eab3..82a1a78a5 100644 --- a/src/state/CallViewModel/remoteMembers/ConnectionFactory.ts +++ b/src/state/CallViewModel/remoteMembers/ConnectionFactory.ts @@ -5,7 +5,6 @@ SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial Please see LICENSE in the repository root for full details. */ -import { type LivekitTransport } from "matrix-js-sdk/lib/matrixrtc"; import { Room as LivekitRoom, type RoomOptions, @@ -15,6 +14,7 @@ import { } from "livekit-client"; import { type Logger } from "matrix-js-sdk/lib/logger"; import E2EEWorker from "livekit-client/e2ee-worker?worker"; +import { type CallMembershipIdentityParts } from "matrix-js-sdk/lib/matrixrtc/EncryptionManager"; import { type ObservableScope } from "../../ObservableScope.ts"; import { Connection } from "./Connection.ts"; @@ -23,13 +23,15 @@ import type { MediaDevices } from "../../MediaDevices.ts"; import type { Behavior } from "../../Behavior.ts"; import type { ProcessorState } from "../../../livekit/TrackProcessorContext.tsx"; import { defaultLiveKitOptions } from "../../../livekit/options.ts"; +import { type LivekitTransportWithVersion } from "./ConnectionManager.ts"; // TODO evaluate if this should be done like the Publisher Factory export interface ConnectionFactory { createConnection( - transport: LivekitTransport, + transport: LivekitTransportWithVersion, scope: ObservableScope, logger: Logger, + ownMembershipIdentity: CallMembershipIdentityParts, ): Connection; } @@ -77,10 +79,19 @@ export class ECConnectionFactory implements ConnectionFactory { this.livekitRoomFactory = livekitRoomFactory ?? defaultFactory; } + /** + * + * @param transport + * @param scope + * @param logger + * @param ownMembershipIdentity required to connect (using the jwt service) with the SFU. + * @returns + */ public createConnection( - transport: LivekitTransport, + transport: LivekitTransportWithVersion, scope: ObservableScope, logger: Logger, + ownMembershipIdentity: CallMembershipIdentityParts, ): Connection { return new Connection( { @@ -90,6 +101,7 @@ export class ECConnectionFactory implements ConnectionFactory { livekitRoomFactory: this.livekitRoomFactory, }, logger, + ownMembershipIdentity, ); } } diff --git a/src/state/CallViewModel/remoteMembers/ConnectionManager.test.ts b/src/state/CallViewModel/remoteMembers/ConnectionManager.test.ts index 70bfb4def..4ab916469 100644 --- a/src/state/CallViewModel/remoteMembers/ConnectionManager.test.ts +++ b/src/state/CallViewModel/remoteMembers/ConnectionManager.test.ts @@ -14,26 +14,29 @@ import { logger } from "matrix-js-sdk/lib/logger"; import { Epoch, mapEpoch, ObservableScope } from "../../ObservableScope.ts"; import { createConnectionManager$, + type LivekitTransportWithVersion, type ConnectionManagerData, } from "./ConnectionManager.ts"; import { type ConnectionFactory } from "./ConnectionFactory.ts"; import { type Connection } from "./Connection.ts"; -import { withTestScheduler } from "../../../utils/test.ts"; +import { ownMemberMock, withTestScheduler } from "../../../utils/test.ts"; import { areLivekitTransportsEqual } from "./MatrixLivekitMembers.ts"; import { type Behavior } from "../../Behavior.ts"; // Some test constants -const TRANSPORT_1: LivekitTransport = { +const TRANSPORT_1: LivekitTransportWithVersion = { type: "livekit", livekit_service_url: "https://lk.example.org", livekit_alias: "!alias:example.org", + useMatrix2: false, }; -const TRANSPORT_2: LivekitTransport = { +const TRANSPORT_2: LivekitTransportWithVersion = { type: "livekit", livekit_service_url: "https://lk.sample.com", livekit_alias: "!alias:sample.com", + useMatrix2: false, }; let fakeConnectionFactory: ConnectionFactory; @@ -80,6 +83,7 @@ describe("connections$ stream", () => { a: new Epoch([TRANSPORT_1, TRANSPORT_2], 0), }), logger: logger, + ownMembershipIdentity: ownMemberMock, }); expectObservable( @@ -124,6 +128,7 @@ describe("connections$ stream", () => { f: new Epoch([TRANSPORT_1, TRANSPORT_2], 5), }), logger: logger, + ownMembershipIdentity: ownMemberMock, }); expectObservable( @@ -166,6 +171,7 @@ describe("connections$ stream", () => { c: new Epoch([TRANSPORT_1], 2), }), logger: logger, + ownMembershipIdentity: ownMemberMock, }); expectObservable( @@ -279,6 +285,7 @@ describe("connectionManagerData$ stream", () => { a: new Epoch([TRANSPORT_1, TRANSPORT_2], 0), }), logger, + ownMembershipIdentity: ownMemberMock, }); expectObservable(connectionManagerData$).toBe("abcd", { diff --git a/src/state/CallViewModel/remoteMembers/ConnectionManager.ts b/src/state/CallViewModel/remoteMembers/ConnectionManager.ts index 4303d50a5..d5852d845 100644 --- a/src/state/CallViewModel/remoteMembers/ConnectionManager.ts +++ b/src/state/CallViewModel/remoteMembers/ConnectionManager.ts @@ -10,6 +10,7 @@ import { type LivekitTransport } from "matrix-js-sdk/lib/matrixrtc"; import { combineLatest, map, of, switchMap, tap } from "rxjs"; import { type Logger } from "matrix-js-sdk/lib/logger"; import { type RemoteParticipant } from "livekit-client"; +import { type CallMembershipIdentityParts } from "matrix-js-sdk/lib/matrixrtc/EncryptionManager"; import { type Behavior } from "../../Behavior.ts"; import { type Connection } from "./Connection.ts"; @@ -18,6 +19,10 @@ import { generateItemsWithEpoch } from "../../../utils/observable.ts"; import { areLivekitTransportsEqual } from "./MatrixLivekitMembers.ts"; import { type ConnectionFactory } from "./ConnectionFactory.ts"; +export type LivekitTransportWithVersion = LivekitTransport & { + useMatrix2: boolean; +}; + export class ConnectionManagerData { private readonly store: Map = new Map(); @@ -59,8 +64,9 @@ export class ConnectionManagerData { interface Props { scope: ObservableScope; connectionFactory: ConnectionFactory; - inputTransports$: Behavior>; + inputTransports$: Behavior>; logger: Logger; + ownMembershipIdentity: CallMembershipIdentityParts; } // TODO - write test for scopes (do we really need to bind scope) @@ -87,6 +93,7 @@ export function createConnectionManager$({ connectionFactory, inputTransports$, logger: parentLogger, + ownMembershipIdentity, }: Props): IConnectionManager { const logger = parentLogger.getChild("[ConnectionManager]"); // TODO logger: only construct one logger from the client and make it compatible via a EC specific sing @@ -119,20 +126,26 @@ export function createConnectionManager$({ function* (transports) { for (const transport of transports) yield { - keys: [transport.livekit_service_url, transport.livekit_alias], + keys: [ + transport.livekit_service_url, + transport.livekit_alias, + transport.useMatrix2, + ], data: undefined, }; }, - (scope, _data$, serviceUrl, alias) => { + (scope, _data$, serviceUrl, alias, useMatrix2) => { logger.debug(`Creating connection to ${serviceUrl} (${alias})`); const connection = connectionFactory.createConnection( { type: "livekit", livekit_service_url: serviceUrl, livekit_alias: alias, + useMatrix2, }, scope, logger, + ownMembershipIdentity, ); // Start the connection immediately // Use connection state to track connection progress @@ -187,12 +200,12 @@ export function createConnectionManager$({ return { connectionManagerData$ }; } -function removeDuplicateTransports( - transports: LivekitTransport[], -): LivekitTransport[] { +function removeDuplicateTransports( + transports: T[], +): T[] { return transports.reduce((acc, transport) => { if (!acc.some((t) => areLivekitTransportsEqual(t, transport))) acc.push(transport); return acc; - }, [] as LivekitTransport[]); + }, [] as T[]); } diff --git a/src/state/CallViewModel/remoteMembers/ECConnectionFactory.test.ts b/src/state/CallViewModel/remoteMembers/ECConnectionFactory.test.ts index 0c439a6b1..3c60e7760 100644 --- a/src/state/CallViewModel/remoteMembers/ECConnectionFactory.test.ts +++ b/src/state/CallViewModel/remoteMembers/ECConnectionFactory.test.ts @@ -15,7 +15,11 @@ import EventEmitter from "events"; import { ObservableScope } from "../../ObservableScope.ts"; import { ECConnectionFactory } from "./ConnectionFactory.ts"; import type { OpenIDClientParts } from "../../../livekit/openIDSFU.ts"; -import { exampleTransport, mockMediaDevices } from "../../../utils/test.ts"; +import { + exampleTransport, + mockMediaDevices, + ownMemberMock, +} from "../../../utils/test.ts"; import type { ProcessorState } from "../../../livekit/TrackProcessorContext.tsx"; import { constant } from "../../Behavior"; @@ -72,7 +76,12 @@ describe("ECConnectionFactory - Audio inputs options", () => { echo, noise, ); - ecConnectionFactory.createConnection(exampleTransport, testScope, logger); + ecConnectionFactory.createConnection( + exampleTransport, + testScope, + logger, + ownMemberMock, + ); // Check if Room was constructed with expected options expect(RoomConstructor).toHaveBeenCalledWith( @@ -113,7 +122,12 @@ describe("ECConnectionFactory - ControlledAudioDevice", () => { false, false, ); - ecConnectionFactory.createConnection(exampleTransport, testScope, logger); + ecConnectionFactory.createConnection( + exampleTransport, + testScope, + logger, + ownMemberMock, + ); // Check if Room was constructed with expected options expect(RoomConstructor).toHaveBeenCalledWith( diff --git a/src/state/CallViewModel/remoteMembers/MatrixLivekitMembers.ts b/src/state/CallViewModel/remoteMembers/MatrixLivekitMembers.ts index 0c61ba066..9178c3479 100644 --- a/src/state/CallViewModel/remoteMembers/MatrixLivekitMembers.ts +++ b/src/state/CallViewModel/remoteMembers/MatrixLivekitMembers.ts @@ -176,9 +176,9 @@ export function createMatrixLivekitMembers$({ // TODO add back in the callviewmodel pauseWhen(this.pretendToBeDisconnected$) // TODO add this to the JS-SDK -export function areLivekitTransportsEqual( - t1: LivekitTransport | null, - t2: LivekitTransport | null, +export function areLivekitTransportsEqual( + t1: T | null, + t2: T | null, ): boolean { if (t1 && t2) return t1.livekit_service_url === t2.livekit_service_url; // In case we have different lk rooms in the same SFU (depends on the livekit authorization service) diff --git a/src/state/CallViewModel/remoteMembers/integration.test.ts b/src/state/CallViewModel/remoteMembers/integration.test.ts index 202b3f568..c9e02a7cf 100644 --- a/src/state/CallViewModel/remoteMembers/integration.test.ts +++ b/src/state/CallViewModel/remoteMembers/integration.test.ts @@ -24,6 +24,7 @@ import { mockCallMembership, mockComputeLivekitParticipantIdentity$, mockMediaDevices, + ownMemberMock, withTestScheduler, } from "../../../utils/test.ts"; import { type ProcessorState } from "../../../livekit/TrackProcessorContext.tsx"; @@ -128,6 +129,7 @@ test("bob, carl, then bob joining no tracks yet", () => { connectionFactory: ecConnectionFactory, inputTransports$: membershipsAndTransports.transports$, logger: logger, + ownMembershipIdentity: ownMemberMock, }); const matrixLivekitItems$ = createMatrixLivekitMembers$({ diff --git a/src/state/SessionBehaviors.ts b/src/state/SessionBehaviors.ts index e174a1ccc..b61d2fe6a 100644 --- a/src/state/SessionBehaviors.ts +++ b/src/state/SessionBehaviors.ts @@ -8,7 +8,6 @@ Please see LICENSE in the repository root for full details. import { type CallMembership, isLivekitTransport, - type LivekitTransport, type MatrixRTCSession, MatrixRTCSessionEvent, } from "matrix-js-sdk/lib/matrixrtc"; @@ -21,15 +20,18 @@ import { type ObservableScope, } from "./ObservableScope"; import { type Behavior } from "./Behavior"; +import { type LivekitTransportWithVersion } from "./CallViewModel/remoteMembers/ConnectionManager"; export const membershipsAndTransports$ = ( scope: ObservableScope, memberships$: Behavior>, ): { membershipsWithTransport$: Behavior< - Epoch<{ membership: CallMembership; transport?: LivekitTransport }[]> + Epoch< + { membership: CallMembership; transport?: LivekitTransportWithVersion }[] + > >; - transports$: Behavior>; + transports$: Behavior>; } => { /** * Lists the transports used by ourselves, plus all other MatrixRTC session @@ -47,7 +49,12 @@ export const membershipsAndTransports$ = ( const transport = membership.getTransport(oldestMembership); return { membership, - transport: isLivekitTransport(transport) ? transport : undefined, + transport: isLivekitTransport(transport) + ? { + ...transport, + useMatrix2: membership.kind === "rtc", + } + : undefined, }; }); }), diff --git a/src/utils/test.ts b/src/utils/test.ts index 7d2516409..968b71605 100644 --- a/src/utils/test.ts +++ b/src/utils/test.ts @@ -25,7 +25,6 @@ import { import { CallMembership, type LivekitFocusSelection, - type LivekitTransport, type MatrixRTCSession, MatrixRTCSessionEvent, type MatrixRTCSessionEventHandlerMap, @@ -67,6 +66,7 @@ import { type MediaDevices } from "../state/MediaDevices"; import { type Behavior, constant } from "../state/Behavior"; import { ObservableScope } from "../state/ObservableScope"; import { MuteStates } from "../state/MuteStates"; +import { type LivekitTransportWithVersion } from "../state/CallViewModel/remoteMembers/ConnectionManager"; export function withFakeTimers(continuation: () => void): void { vi.useFakeTimers(); @@ -197,10 +197,11 @@ export function mockEmitter(): EmitterMock { }; } -export const exampleTransport: LivekitTransport = { +export const exampleTransport: LivekitTransportWithVersion = { type: "livekit", livekit_service_url: "https://lk.example.org", livekit_alias: "!alias:example.org", + useMatrix2: false, }; export function mockCallMembership( @@ -256,6 +257,11 @@ export function mockRtcMembership( return cms; } +export const ownMemberMock: CallMembershipIdentityParts = { + userId: "@alice:example.org", + deviceId: "DEVICE", + memberId: "@alice:example.org:DEVICE", +}; // Maybe it'd be good to move this to matrix-js-sdk? Our testing needs are // rather simple, but if one util to mock a member is good enough for us, maybe // it's useful for matrix-js-sdk consumers in general. diff --git a/yarn.lock b/yarn.lock index db1db4910..a3211330b 100644 --- a/yarn.lock +++ b/yarn.lock @@ -10338,9 +10338,9 @@ __metadata: languageName: node linkType: hard -"matrix-js-sdk@github:matrix-org/matrix-js-sdk#head=toger5/use-membershipID-for-session-state-events&commit=f5f1b8efb46b3d55a7eebfabb4a61496640b8b00": - version: 39.3.0 - resolution: "matrix-js-sdk@https://github.com/matrix-org/matrix-js-sdk.git#commit=f5f1b8efb46b3d55a7eebfabb4a61496640b8b00" +"matrix-js-sdk@portal:/Users/timo/Projects/matrix-js-sdk::locator=element-call%40workspace%3A.": + version: 0.0.0-use.local + resolution: "matrix-js-sdk@portal:/Users/timo/Projects/matrix-js-sdk::locator=element-call%40workspace%3A." dependencies: "@babel/runtime": "npm:^7.12.5" "@matrix-org/matrix-sdk-crypto-wasm": "npm:^16.0.0" @@ -10356,9 +10356,8 @@ __metadata: sdp-transform: "npm:^3.0.0" unhomoglyph: "npm:^1.0.6" uuid: "npm:13" - checksum: 10c0/9607b0c063c873a24c1a2d05cc7500d60c32556ec82b666ebaae5c5e829faf5bb7639780efddea7211e6b9873098bd53b97656f041e932e8b0de0c208ccabbff languageName: node - linkType: hard + linkType: soft "matrix-widget-api@npm:^1.14.0": version: 1.15.0 From 50f3bf00aee60fde10012c8999599346819f87c0 Mon Sep 17 00:00:00 2001 From: Timo K Date: Wed, 17 Dec 2025 10:22:46 +0100 Subject: [PATCH 116/748] use correct js-sdk --- package.json | 2 +- yarn.lock | 11 ++++++----- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/package.json b/package.json index 35589771b..f34fab5f9 100644 --- a/package.json +++ b/package.json @@ -109,7 +109,7 @@ "livekit-client": "^2.13.0", "lodash-es": "^4.17.21", "loglevel": "^1.9.1", - "matrix-js-sdk": "github:matrix-org/matrix-js-sdk#head=toger5/use-membershipID-for-session-state-events&commit=f5f1b8efb46b3d55a7eebfabb4a61496640b8b00", + "matrix-js-sdk": "github:matrix-org/matrix-js-sdk#head=toger5/use-membershipID-for-session-state-events&commit=9779ac975df2f296958e3c4be254fa46ebd67ea4", "matrix-widget-api": "^1.14.0", "normalize.css": "^8.0.1", "observable-hooks": "^4.2.3", diff --git a/yarn.lock b/yarn.lock index a3211330b..b83976a28 100644 --- a/yarn.lock +++ b/yarn.lock @@ -7533,7 +7533,7 @@ __metadata: livekit-client: "npm:^2.13.0" lodash-es: "npm:^4.17.21" loglevel: "npm:^1.9.1" - matrix-js-sdk: "github:matrix-org/matrix-js-sdk#head=toger5/use-membershipID-for-session-state-events&commit=f5f1b8efb46b3d55a7eebfabb4a61496640b8b00" + matrix-js-sdk: "github:matrix-org/matrix-js-sdk#head=toger5/use-membershipID-for-session-state-events&commit=9779ac975df2f296958e3c4be254fa46ebd67ea4" matrix-widget-api: "npm:^1.14.0" normalize.css: "npm:^8.0.1" observable-hooks: "npm:^4.2.3" @@ -10338,9 +10338,9 @@ __metadata: languageName: node linkType: hard -"matrix-js-sdk@portal:/Users/timo/Projects/matrix-js-sdk::locator=element-call%40workspace%3A.": - version: 0.0.0-use.local - resolution: "matrix-js-sdk@portal:/Users/timo/Projects/matrix-js-sdk::locator=element-call%40workspace%3A." +"matrix-js-sdk@github:matrix-org/matrix-js-sdk#head=toger5/use-membershipID-for-session-state-events&commit=9779ac975df2f296958e3c4be254fa46ebd67ea4": + version: 39.3.0 + resolution: "matrix-js-sdk@https://github.com/matrix-org/matrix-js-sdk.git#commit=9779ac975df2f296958e3c4be254fa46ebd67ea4" dependencies: "@babel/runtime": "npm:^7.12.5" "@matrix-org/matrix-sdk-crypto-wasm": "npm:^16.0.0" @@ -10356,8 +10356,9 @@ __metadata: sdp-transform: "npm:^3.0.0" unhomoglyph: "npm:^1.0.6" uuid: "npm:13" + checksum: 10c0/78c27847b58c229513bd28c4c4ad391d8af6722711d3d0f42e93a537d7a827a7233e920936dd8d7005c7893bad17a503c3f62b56ecfed3cf4ae81a5097b4ac21 languageName: node - linkType: soft + linkType: hard "matrix-widget-api@npm:^1.14.0": version: 1.15.0 From 55d18f10fe45cd78c528f46b96db8eecabc7c9ce Mon Sep 17 00:00:00 2001 From: Timo K Date: Fri, 19 Dec 2025 19:23:41 +0100 Subject: [PATCH 117/748] temp refactored membership rtcidentity --- package.json | 2 +- src/e2ee/matrixKeyProvider.ts | 110 +++++++++++------- src/state/CallViewModel/CallViewModel.test.ts | 9 -- .../LivekitParticipantIdentity.ts | 53 --------- .../remoteMembers/MatrixLivekitMembers.ts | 57 ++------- .../remoteMembers/integration.test.ts | 6 - src/utils/test.ts | 3 +- yarn.lock | 8 +- 8 files changed, 87 insertions(+), 161 deletions(-) delete mode 100644 src/state/CallViewModel/remoteMembers/LivekitParticipantIdentity.ts diff --git a/package.json b/package.json index f34fab5f9..6c74b84cd 100644 --- a/package.json +++ b/package.json @@ -109,7 +109,7 @@ "livekit-client": "^2.13.0", "lodash-es": "^4.17.21", "loglevel": "^1.9.1", - "matrix-js-sdk": "github:matrix-org/matrix-js-sdk#head=toger5/use-membershipID-for-session-state-events&commit=9779ac975df2f296958e3c4be254fa46ebd67ea4", + "matrix-js-sdk": "github:matrix-org/matrix-js-sdk#head=toger5/use-membershipID-for-session-state-events&commit=2bb3b03a248e689f7460f4e70d5ffbf10353c725", "matrix-widget-api": "^1.14.0", "normalize.css": "^8.0.1", "observable-hooks": "^4.2.3", diff --git a/src/e2ee/matrixKeyProvider.ts b/src/e2ee/matrixKeyProvider.ts index a499f45ca..166fd82cd 100644 --- a/src/e2ee/matrixKeyProvider.ts +++ b/src/e2ee/matrixKeyProvider.ts @@ -6,18 +6,13 @@ Please see LICENSE in the repository root for full details. */ import { BaseKeyProvider } from "livekit-client"; -import { logger } from "matrix-js-sdk/lib/logger"; import { type MatrixRTCSession, MatrixRTCSessionEvent, } from "matrix-js-sdk/lib/matrixrtc"; import { type CallMembershipIdentityParts } from "matrix-js-sdk/lib/matrixrtc/EncryptionManager"; -import { firstValueFrom } from "rxjs"; - -import { - computeLivekitParticipantIdentity$, - livekitIdentityInput, -} from "../state/CallViewModel/remoteMembers/LivekitParticipantIdentity"; +import { logger as rootLogger } from "matrix-js-sdk/lib/logger"; +const logger = rootLogger.getChild("[MatrixKeyProvider]"); export class MatrixKeyProvider extends BaseKeyProvider { private rtcSession?: MatrixRTCSession; @@ -32,6 +27,10 @@ export class MatrixKeyProvider extends BaseKeyProvider { MatrixRTCSessionEvent.EncryptionKeyChanged, this.onEncryptionKeyChanged, ); + this.rtcSession.off( + MatrixRTCSessionEvent.MembershipsChanged, + this.onMembershipsChanged, + ); } this.rtcSession = rtcSession; @@ -40,55 +39,86 @@ export class MatrixKeyProvider extends BaseKeyProvider { MatrixRTCSessionEvent.EncryptionKeyChanged, this.onEncryptionKeyChanged, ); + this.rtcSession.on( + MatrixRTCSessionEvent.MembershipsChanged, + this.onMembershipsChanged, + ); // The new session could be aware of keys of which the old session wasn't, // so emit key changed events this.rtcSession.reemitEncryptionKeys(); } + private keyCache = new Array<{ + membership: CallMembershipIdentityParts; + encryptionKey: Uint8Array; + encryptionKeyIndex: number; + }>(); + + private onMembershipsChanged = (): void => { + const duplicatedArray = this.keyCache; + // Reset key cache first. It will get repopulated when calling `onEncryptionKeyChanged` + this.keyCache = []; + let next = duplicatedArray.pop(); + while (next !== undefined) { + logger.debug( + "[KeyCache] remove key event from the cache and try adding it again. For membership: ", + next.membership, + ); + this.onEncryptionKeyChanged( + next.encryptionKey, + next.encryptionKeyIndex, + next.membership, + ); + next = duplicatedArray.pop(); + } + }; + private onEncryptionKeyChanged = ( encryptionKey: Uint8Array, encryptionKeyIndex: number, membership: CallMembershipIdentityParts, ): void => { - const unhashedIdentity = livekitIdentityInput(membership); - // This is the only way we can get the kind of the membership event we just received the key for. // best case we want to recompute this once the memberships change (you can receive the key before the participant...) - // - // TODO change this to `?? "rtc"` for newer versions. - const kind = - this.rtcSession?.memberships.find( - (m) => - m.userId === membership.userId && - m.deviceId === membership.deviceId && - m.memberId === membership.memberId, - )?.kind ?? "session"; + const membershipFull = this.rtcSession?.memberships.find( + (m) => + m.userId === membership.userId && + m.deviceId === membership.deviceId && + m.memberId === membership.memberId, + ); + if (!membershipFull) { + logger.debug( + "[KeyCache] Added key event to the cache because we do not have a membership for it (yet): ", + membership, + ); + this.keyCache.push({ membership, encryptionKey, encryptionKeyIndex }); + return; + } - Promise.all([ - crypto.subtle.importKey("raw", encryptionKey, "HKDF", false, [ + crypto.subtle + .importKey("raw", encryptionKey, "HKDF", false, [ "deriveBits", "deriveKey", - ]), - firstValueFrom(computeLivekitParticipantIdentity$(membership, kind)), - ]).then( - ([keyMaterial, livekitParticipantId]) => { - this.onSetEncryptionKey( - keyMaterial, - livekitParticipantId, - encryptionKeyIndex, - ); + ]) + .then( + (keyMaterial) => { + this.onSetEncryptionKey( + keyMaterial, + membershipFull.rtcBackendIdentity, + encryptionKeyIndex, + ); - logger.debug( - `Sent new key to livekit room=${this.rtcSession?.room.roomId} participantId=${livekitParticipantId} (before hash: ${unhashedIdentity}) encryptionKeyIndex=${encryptionKeyIndex}`, - ); - }, - (e) => { - logger.error( - `Failed to create key material from buffer for livekit room=${this.rtcSession?.room.roomId} participantId before hash=${unhashedIdentity} encryptionKeyIndex=${encryptionKeyIndex}`, - e, - ); - }, - ); + logger.debug( + `Sent new key to livekit room=${this.rtcSession?.room.roomId} participantId=${membershipFull.rtcBackendIdentity} (before hash: ${membershipFull.userId}) encryptionKeyIndex=${encryptionKeyIndex}`, + ); + }, + (e) => { + logger.error( + `Failed to create key material from buffer for livekit room=${this.rtcSession?.room.roomId} participantId before hash=${membershipFull.userId} encryptionKeyIndex=${encryptionKeyIndex}`, + e, + ); + }, + ); }; } diff --git a/src/state/CallViewModel/CallViewModel.test.ts b/src/state/CallViewModel/CallViewModel.test.ts index 505cb19f3..6e3837c42 100644 --- a/src/state/CallViewModel/CallViewModel.test.ts +++ b/src/state/CallViewModel/CallViewModel.test.ts @@ -44,7 +44,6 @@ import { mockRtcMembership, testScope, exampleTransport, - mockComputeLivekitParticipantIdentity$, } from "../../utils/test.ts"; import { E2eeType } from "../../e2ee/e2eeType.ts"; import { @@ -88,14 +87,6 @@ vi.mock( }), ); -vi.mock( - import("./remoteMembers/LivekitParticipantIdentity.ts"), - async (importOriginal) => ({ - ...(await importOriginal()), - computeLivekitParticipantIdentity$: mockComputeLivekitParticipantIdentity$, - }), -); - const yesNo = { y: true, n: false, diff --git a/src/state/CallViewModel/remoteMembers/LivekitParticipantIdentity.ts b/src/state/CallViewModel/remoteMembers/LivekitParticipantIdentity.ts deleted file mode 100644 index e43d0bd1b..000000000 --- a/src/state/CallViewModel/remoteMembers/LivekitParticipantIdentity.ts +++ /dev/null @@ -1,53 +0,0 @@ -/* -Copyright 2025 New Vector Ltd. - -SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial -Please see LICENSE in the repository root for full details. -*/ - -import { encodeUnpaddedBase64Url } from "matrix-js-sdk"; -import { sha256 } from "matrix-js-sdk/lib/digest"; -import { type CallMembershipIdentityParts } from "matrix-js-sdk/lib/matrixrtc/EncryptionManager"; -import { from, type Observable } from "rxjs"; - -const livekitParticipantIdentityCache = new Map(); - -/** - * The string that is computed based on the membership and used for the computing the hash. - * `${userId}:${deviceId}:${membershipID}` - * as the direct imput for: await sha256(input) - */ -export const livekitIdentityInput = ({ - userId, - deviceId, - memberId, -}: CallMembershipIdentityParts): string => `${userId}|${deviceId}|${memberId}`; - -export function computeLivekitParticipantIdentity$( - membership: CallMembershipIdentityParts, - kind: "rtc" | "session", -): Observable { - const compute = async (): Promise => { - switch (kind) { - case "rtc": { - const input = livekitIdentityInput(membership); - if (livekitParticipantIdentityCache.size > 400) - // prevent memory leaks in a stupid/simple way - livekitParticipantIdentityCache.clear(); - // TODO use non deprecated memberId - if (livekitParticipantIdentityCache.has(input)) - return livekitParticipantIdentityCache.get(input)!; - else { - const hashBuffer = await sha256(input); - const hashedString = encodeUnpaddedBase64Url(hashBuffer); - livekitParticipantIdentityCache.set(input, hashedString); - return hashedString; - } - } - case "session": - default: - return `${membership.userId}:${membership.deviceId}`; - } - }; - return from(compute()); -} diff --git a/src/state/CallViewModel/remoteMembers/MatrixLivekitMembers.ts b/src/state/CallViewModel/remoteMembers/MatrixLivekitMembers.ts index 9178c3479..a5d6b2f6a 100644 --- a/src/state/CallViewModel/remoteMembers/MatrixLivekitMembers.ts +++ b/src/state/CallViewModel/remoteMembers/MatrixLivekitMembers.ts @@ -10,7 +10,7 @@ import { type LivekitTransport, type CallMembership, } from "matrix-js-sdk/lib/matrixrtc"; -import { combineLatest, filter, map, switchMap } from "rxjs"; +import { combineLatest, filter, map } from "rxjs"; import { logger as rootLogger } from "matrix-js-sdk/lib/logger"; import { type Behavior } from "../../Behavior"; @@ -18,7 +18,6 @@ import { type IConnectionManager } from "./ConnectionManager"; import { Epoch, type ObservableScope } from "../../ObservableScope"; import { type Connection } from "./Connection"; import { generateItemsWithEpoch } from "../../../utils/observable"; -import { computeLivekitParticipantIdentity$ } from "./LivekitParticipantIdentity"; const logger = rootLogger.getChild("[MatrixLivekitMembers]"); @@ -82,45 +81,12 @@ export function createMatrixLivekitMembers$({ membershipsWithTransport$, connectionManager, }: Props): Behavior> { - /** - * This internal observable is used to compute the async sha256 hash of the user's identity. - * a promise is treated like an observable. So we can switchMap on the promise from the identity computation. - * The last update to `membershipsWithTransport$` will always be the last promise we pass to switchMap. - * So we will eventually always end up with the latest memberships and their identities. - */ - const membershipsWithTransportAndLivekitIdentity$ = - membershipsWithTransport$.pipe( - switchMap((membershipsWithTransport) => { - const { value, epoch } = membershipsWithTransport; - const membershipsWithTransportAndLkIdentityPromises = value.map( - (obj) => { - return computeLivekitParticipantIdentity$( - obj.membership, - obj.membership.kind, - ); - }, - ); - return combineLatest( - membershipsWithTransportAndLkIdentityPromises, - ).pipe( - map((identities) => { - const membershipsWithTransportAndLkIdentity = value.map( - ({ transport, membership }, index) => { - return { transport, membership, identity: identities[index] }; - }, - ); - return new Epoch(membershipsWithTransportAndLkIdentity, epoch); - }), - ); - }), - ); - /** * Stream of all the call members and their associated livekit data (if available). */ return scope.behavior( combineLatest([ - membershipsWithTransportAndLivekitIdentity$, + membershipsWithTransport$, connectionManager.connectionManagerData$, ]).pipe( filter((values) => @@ -131,37 +97,34 @@ export function createMatrixLivekitMembers$({ // Generator function. // creates an array of `{key, data}[]` // Each change in the keys (new key, missing key) will result in a call to the factory function. - function* ([membershipsWithTransportAndLivekitIdentity, managerData]) { - for (const { - membership, - transport, - identity, - } of membershipsWithTransportAndLivekitIdentity) { + function* ([membershipsWithTransport, managerData]) { + for (const { membership, transport } of membershipsWithTransport) { const participants = transport ? managerData.getParticipantForTransport(transport) : []; const participant = - participants.find((p) => p.identity == identity) ?? null; + participants.find( + (p) => p.identity == membership.rtcBackendIdentity, + ) ?? null; const connection = transport ? managerData.getConnectionForTransport(transport) : null; yield { - keys: [identity, membership.userId, membership.deviceId], + keys: [membership.userId, membership.deviceId], data: { membership, participant, connection }, }; } }, // Each update where the key of the generator array do not change will result in updates to the `data$` observable in the factory. - (scope, data$, identity, userId, deviceId) => { + (scope, data$, userId, deviceId) => { logger.debug( - `Generating member for livekitIdentity: ${identity}, userId:deviceId: ${userId}${deviceId}`, + `Generating member for livekitIdentity: ${data$.value.membership.rtcBackendIdentity}, userId:deviceId: ${userId}${deviceId}`, ); const { participant$, ...rest } = scope.splitBehavior(data$); // will only get called once per `participantId, userId` pair. // updates to data$ and as a result to displayName$ and mxcAvatarUrl$ are more frequent. return { - identity, userId, participant: { type: "remote" as const, value$: participant$ }, ...rest, diff --git a/src/state/CallViewModel/remoteMembers/integration.test.ts b/src/state/CallViewModel/remoteMembers/integration.test.ts index c9e02a7cf..00062c60d 100644 --- a/src/state/CallViewModel/remoteMembers/integration.test.ts +++ b/src/state/CallViewModel/remoteMembers/integration.test.ts @@ -22,7 +22,6 @@ import { ECConnectionFactory } from "./ConnectionFactory.ts"; import { type OpenIDClientParts } from "../../../livekit/openIDSFU.ts"; import { mockCallMembership, - mockComputeLivekitParticipantIdentity$, mockMediaDevices, ownMemberMock, withTestScheduler, @@ -45,11 +44,6 @@ let lkRoomFactory: () => LivekitRoom; const createdMockLivekitRooms: Map = new Map(); -vi.mock(import("./LivekitParticipantIdentity.ts"), async (importOriginal) => ({ - ...(await importOriginal()), - computeLivekitParticipantIdentity$: mockComputeLivekitParticipantIdentity$, -})); - beforeEach(() => { testScope = new ObservableScope(); mockClient = { diff --git a/src/utils/test.ts b/src/utils/test.ts index 968b71605..56148b32d 100644 --- a/src/utils/test.ts +++ b/src/utils/test.ts @@ -252,7 +252,8 @@ export function mockRtcMembership( content: data, }); - const cms = new CallMembership(event, data); + const membershipData = CallMembership.membershipDataFromMatrixEvent(event); + const cms = new CallMembership(event, membershipData, "xx"); vi.mocked(cms).getTransport = vi.fn().mockReturnValue(fociPreferred[0]); return cms; } diff --git a/yarn.lock b/yarn.lock index b83976a28..c4b2e957d 100644 --- a/yarn.lock +++ b/yarn.lock @@ -7533,7 +7533,7 @@ __metadata: livekit-client: "npm:^2.13.0" lodash-es: "npm:^4.17.21" loglevel: "npm:^1.9.1" - matrix-js-sdk: "github:matrix-org/matrix-js-sdk#head=toger5/use-membershipID-for-session-state-events&commit=9779ac975df2f296958e3c4be254fa46ebd67ea4" + matrix-js-sdk: "github:matrix-org/matrix-js-sdk#head=toger5/use-membershipID-for-session-state-events&commit=2bb3b03a248e689f7460f4e70d5ffbf10353c725" matrix-widget-api: "npm:^1.14.0" normalize.css: "npm:^8.0.1" observable-hooks: "npm:^4.2.3" @@ -10338,9 +10338,9 @@ __metadata: languageName: node linkType: hard -"matrix-js-sdk@github:matrix-org/matrix-js-sdk#head=toger5/use-membershipID-for-session-state-events&commit=9779ac975df2f296958e3c4be254fa46ebd67ea4": +"matrix-js-sdk@github:matrix-org/matrix-js-sdk#head=toger5/use-membershipID-for-session-state-events&commit=2bb3b03a248e689f7460f4e70d5ffbf10353c725": version: 39.3.0 - resolution: "matrix-js-sdk@https://github.com/matrix-org/matrix-js-sdk.git#commit=9779ac975df2f296958e3c4be254fa46ebd67ea4" + resolution: "matrix-js-sdk@https://github.com/matrix-org/matrix-js-sdk.git#commit=2bb3b03a248e689f7460f4e70d5ffbf10353c725" dependencies: "@babel/runtime": "npm:^7.12.5" "@matrix-org/matrix-sdk-crypto-wasm": "npm:^16.0.0" @@ -10356,7 +10356,7 @@ __metadata: sdp-transform: "npm:^3.0.0" unhomoglyph: "npm:^1.0.6" uuid: "npm:13" - checksum: 10c0/78c27847b58c229513bd28c4c4ad391d8af6722711d3d0f42e93a537d7a827a7233e920936dd8d7005c7893bad17a503c3f62b56ecfed3cf4ae81a5097b4ac21 + checksum: 10c0/2e7061f6e648c91aaeb30b3e01626d855e24efcb330bbe432fcba199bd46b0b0d998cbc545748e1c72a7b643d25581f988fcad9bbaa42912a6ec96a27c41d0de languageName: node linkType: hard From 852d2ee37540ae335526fedf1772f1715989e803 Mon Sep 17 00:00:00 2001 From: Timo K Date: Mon, 22 Dec 2025 13:35:40 +0100 Subject: [PATCH 118/748] after merge cleanup --- sdk/main.ts | 14 ++- src/state/CallViewModel/CallViewModel.ts | 56 +++------ .../CallViewModel/localMember/LocalMember.ts | 13 +- .../remoteMembers/Connection.test.ts | 43 ++----- .../CallViewModel/remoteMembers/Connection.ts | 2 +- .../remoteMembers/ConnectionManager.ts | 11 +- .../MatrixLivekitMembers.test.ts | 117 ++++++++++-------- .../remoteMembers/MatrixLivekitMembers.ts | 7 +- .../remoteMembers/integration.test.ts | 4 +- yarn.lock | 9 ++ 10 files changed, 118 insertions(+), 158 deletions(-) diff --git a/sdk/main.ts b/sdk/main.ts index d26832778..5b23a700c 100644 --- a/sdk/main.ts +++ b/sdk/main.ts @@ -50,7 +50,6 @@ import { getUrlParams } from "../src/UrlParams"; import { MuteStates } from "../src/state/MuteStates"; import { MediaDevices } from "../src/state/MediaDevices"; import { E2eeType } from "../src/e2ee/e2eeType"; -import { type LocalMemberConnectionState } from "../src/state/CallViewModel/localMember/LocalMembership"; import { currentAndPrev, logger, @@ -62,7 +61,11 @@ import { ElementWidgetActions } from "../src/widget"; import { type Connection } from "../src/state/CallViewModel/remoteMembers/Connection"; interface MatrixRTCSdk { - join: () => LocalMemberConnectionState; + /** + * observe connected$ to track the state. + * @returns + */ + join: () => void; /** @throws on leave errors */ leave: () => void; data$: Observable<{ sender: string; data: string }>; @@ -201,7 +204,7 @@ export async function createMatrixRTCSdk( return of((data: string): never => { throw Error("local membership not yet ready."); }); - return m.participant$.pipe( + return m.participant.value$.pipe( map((p) => { if (p === null) { return (data: string): never => { @@ -264,11 +267,10 @@ export async function createMatrixRTCSdk( logger.info("createMatrixRTCSdk done"); return { - join: (): LocalMemberConnectionState => { + join: (): void => { // first lets try making the widget sticky tryMakeSticky(); callViewModel.join(); - return callViewModel.connectionState; }, leave: (): void => { callViewModel.hangup(); @@ -284,7 +286,7 @@ export async function createMatrixRTCSdk( combineLatest([ member.connection$, member.membership$, - member.participant$, + member.participant.value$, ]).pipe( map(([connection, membership, participant]) => ({ connection, diff --git a/src/state/CallViewModel/CallViewModel.ts b/src/state/CallViewModel/CallViewModel.ts index 2bd51cb9f..00a7d3e9d 100644 --- a/src/state/CallViewModel/CallViewModel.ts +++ b/src/state/CallViewModel/CallViewModel.ts @@ -12,7 +12,6 @@ import { ExternalE2EEKeyProvider, type Room as LivekitRoom, type RoomOptions, - type LocalParticipant as LocalLivekitParticipant, } from "livekit-client"; import { type Room as MatrixRoom } from "matrix-js-sdk"; import { @@ -81,7 +80,7 @@ import { } from "../../reactions"; import { shallowEquals } from "../../utils/array"; import { type MediaDevices } from "../MediaDevices"; -import { type Behavior } from "../Behavior"; +import { constant, type Behavior } from "../Behavior"; import { E2eeType } from "../../e2ee/e2eeType"; import { MatrixKeyProvider } from "../../e2ee/matrixKeyProvider"; import { type MuteStates } from "../MuteStates"; @@ -105,9 +104,8 @@ import { createHomeserverConnected$ } from "./localMember/HomeserverConnected.ts import { createLocalMembership$, enterRTCSession, - type LocalMemberConnectionState, - RTCBackendState, -} from "./localMember/LocalMembership.ts"; + TransportState, +} from "./localMember/LocalMember.ts"; import { createLocalTransport$ } from "./localMember/LocalTransport.ts"; import { createMemberships$, @@ -119,6 +117,7 @@ import { createMatrixLivekitMembers$, type TaggedParticipant, type LocalMatrixLivekitMember, + type RemoteMatrixLivekitMember, } from "./remoteMembers/MatrixLivekitMembers.ts"; import { type AutoLeaveReason, @@ -158,7 +157,7 @@ export interface CallViewModelOptions { /** Optional behavior overriding the computed window size, mainly for testing purposes. */ windowSize$?: Behavior<{ width: number; height: number }>; /** The version & compatibility mode of MatrixRTC that we should use. */ - matrixRTCMode$: Behavior; + matrixRTCMode$?: Behavior; } // Do not play any sounds if the participant count has exceeded this @@ -190,13 +189,6 @@ export type LivekitRoomItem = { url: string; }; -export type LocalMatrixLivekitMember = Pick< - MatrixLivekitMember, - "userId" | "membership$" | "connection$" -> & { - participant$: Behavior; -}; - /** * The return of createCallViewModel$ * this interface represents the root source of data for the call view. @@ -273,7 +265,7 @@ export interface CallViewModel { livekitRoomItems$: Behavior; userMedia$: Behavior; /** use the layout instead, this is just for the sdk export. */ - matrixLivekitMembers$: Behavior; + matrixLivekitMembers$: Behavior; localMatrixLivekitMember$: Behavior; /** List of participants raising their hand */ handsRaised$: Behavior>; @@ -357,26 +349,15 @@ export interface CallViewModel { switch: () => void; } | null>; - // connection state /** - * Whether various media/event sources should pretend to be disconnected from - * all network input, even if their connection still technically works. + * Whether the app is currently reconnecting to the LiveKit server and/or setting the matrix rtc room state. */ - // We do this when the app is in the 'reconnecting' state, because it might be - // that the LiveKit connection is still functional while the homeserver is - // down, for example, and we want to avoid making people worry that the app is - // in a split-brained state. - // DISCUSSION own membership manager ALSO this probably can be simplifis reconnecting$: Behavior; /** * Shortcut for not requireing to parse and combine connectionState.matrix and connectionState.livekit */ connected$: Behavior; - /** - * - */ - connectionState: LocalMemberConnectionState; } /** @@ -406,6 +387,8 @@ export function createCallViewModel$( options.encryptionSystem, matrixRTCSession, ); + const matrixRTCMode$ = + options.matrixRTCMode$ ?? constant(MatrixRTCMode.Legacy); // Each hbar seperates a block of input variables required for the CallViewModel to function. // The outputs of this block is written under the hbar. @@ -438,7 +421,7 @@ export function createCallViewModel$( client, roomId: matrixRoom.roomId, useOldestMember$: scope.behavior( - options.matrixRTCMode$.pipe(map((v) => v === MatrixRTCMode.Legacy)), + matrixRTCMode$.pipe(map((v) => v === MatrixRTCMode.Legacy)), ), }); @@ -482,7 +465,7 @@ export function createCallViewModel$( logger, }); - const { matrixLivekitMembers$ } = createMatrixLivekitMembers$({ + const matrixLivekitMembers$ = createMatrixLivekitMembers$({ scope: scope, membershipsWithTransport$: membershipsAndTransports.membershipsWithTransport$, @@ -490,7 +473,7 @@ export function createCallViewModel$( }); const connectOptions$ = scope.behavior( - options.matrixRTCMode$.pipe( + matrixRTCMode$.pipe( map((mode) => ({ encryptMedia: livekitKeyProvider !== undefined, // TODO. This might need to get called again on each change of matrixRTCMode... @@ -1527,17 +1510,6 @@ export function createCallViewModel$( null, ), - participantCount$, - livekitRoomItems$, - handsRaised$, - reactions$, - joinSoundEffect$, - leaveSoundEffect$, - newHandRaised$, - newScreenShare$, - audibleReactions$, - visibleReactions$, - handsRaised$: handsRaised$, reactions$: reactions$, joinSoundEffect$: joinSoundEffect$, @@ -1546,7 +1518,6 @@ export function createCallViewModel$( newScreenShare$: newScreenShare$, audibleReactions$: audibleReactions$, visibleReactions$: visibleReactions$, - windowMode$: windowMode$, spotlightExpanded$: spotlightExpanded$, toggleSpotlightExpanded$: toggleSpotlightExpanded$, @@ -1574,6 +1545,9 @@ export function createCallViewModel$( earpieceMode$: earpieceMode$, audioOutputSwitcher$: audioOutputSwitcher$, reconnecting$: localMembership.reconnecting$, + participantCount$, + livekitRoomItems$, + connected$: localMembership.connected$, }; } diff --git a/src/state/CallViewModel/localMember/LocalMember.ts b/src/state/CallViewModel/localMember/LocalMember.ts index 0c6516ad6..6d28bc56a 100644 --- a/src/state/CallViewModel/localMember/LocalMember.ts +++ b/src/state/CallViewModel/localMember/LocalMember.ts @@ -177,14 +177,18 @@ export const createLocalMembership$ = ({ // tracks$: Behavior; participant$: Behavior; connection$: Behavior; - /** Shorthand for homeserverConnected.rtcSession === Status.Reconnecting - * Direct translation to the js-sdk membership manager connection `Status`. + /** + * Tracks the homserver and livekit connected state and based on that computes reconnecting. */ reconnecting$: Behavior; /** Shorthand for homeserverConnected.rtcSession === Status.Disconnected * Direct translation to the js-sdk membership manager connection `Status`. */ disconnected$: Behavior; + /** + * Fully connected + */ + connected$: Behavior; } => { const logger = parentLogger.getChild("[LocalMembership]"); logger.debug(`Creating local membership..`); @@ -637,11 +641,8 @@ export const createLocalMembership$ = ({ requestDisconnect, localMemberState$, participant$, -<<<<<<< HEAD:src/state/CallViewModel/localMember/LocalMembership.ts - connected$, -======= ->>>>>>> livekit:src/state/CallViewModel/localMember/LocalMember.ts reconnecting$, + connected$: matrixAndLivekitConnected$, disconnected$: scope.behavior( homeserverConnected.rtsSession$.pipe( map((state) => state === RTCSessionStatus.Disconnected), diff --git a/src/state/CallViewModel/remoteMembers/Connection.test.ts b/src/state/CallViewModel/remoteMembers/Connection.test.ts index 044902f93..bcc0bac2e 100644 --- a/src/state/CallViewModel/remoteMembers/Connection.test.ts +++ b/src/state/CallViewModel/remoteMembers/Connection.test.ts @@ -392,7 +392,7 @@ describe("remote participants", () => { // livekitRoom and the rtc membership in order to publish the members that are publishing // on this connection. - const participants: RemoteParticipant[] = [ + let participants: RemoteParticipant[] = [ mockRemoteParticipant({ identity: "@alice:example.org:DEV000" }), mockRemoteParticipant({ identity: "@bob:example.org:DEV111" }), mockRemoteParticipant({ identity: "@carol:example.org:DEV222" }), @@ -414,28 +414,23 @@ describe("remote participants", () => { fakeLivekitRoom.emit(RoomEvent.ParticipantConnected, p), ); -<<<<<<< HEAD // At this point there should be ~~no~~ publishers // We do have publisher now, since we do not filter for publishers anymore (to also have participants with only data tracks) // The filtering we do is just based on the matrixRTC member events. - expect(observedPublishers.pop()!.length).toEqual(4); + expect(observedParticipants.pop()!.length).toEqual(4); participants = [ - fakeRemoteLivekitParticipant("@alice:example.org:DEV000", 1), - fakeRemoteLivekitParticipant("@bob:example.org:DEV111", 1), - fakeRemoteLivekitParticipant("@carol:example.org:DEV222", 1), - fakeRemoteLivekitParticipant("@dan:example.org:DEV333", 2), + mockRemoteParticipant({ identity: "@alice:example.org:DEV000" }), + mockRemoteParticipant({ identity: "@bob:example.org:DEV111" }), + mockRemoteParticipant({ identity: "@carol:example.org:DEV222" }), + mockRemoteParticipant({ identity: "@dan:example.org:DEV333" }), ]; participants.forEach((p) => - fakeRoomEventEmiter.emit(RoomEvent.ParticipantConnected, p), + fakeLivekitRoom.emit(RoomEvent.ParticipantConnected, p), ); // At this point there should be no publishers - expect(observedPublishers.pop()!.length).toEqual(4); -======= - // All remote participants should be present expect(observedParticipants.pop()!.length).toEqual(4); ->>>>>>> livekit }); it("should be scoped to parent scope", (): void => { @@ -443,15 +438,9 @@ describe("remote participants", () => { const connection = setupRemoteConnection(); -<<<<<<< HEAD - let observedPublishers: PublishingParticipant[][] = []; - const s = connection.remoteParticipants$.subscribe((publishers) => { - observedPublishers.push(publishers); -======= let observedParticipants: RemoteParticipant[][] = []; const s = connection.remoteParticipants$.subscribe((participants) => { observedParticipants.push(participants); ->>>>>>> livekit }); onTestFinished(() => s.unsubscribe()); @@ -468,28 +457,10 @@ describe("remote participants", () => { fakeLivekitRoom.emit(RoomEvent.ParticipantConnected, participant); } -<<<<<<< HEAD - // At this point there should be ~~no~~ publishers - // We do have publisher now, since we do not filter for publishers anymore (to also have participants with only data tracks) - // The filtering we do is just based on the matrixRTC member events. - expect(observedPublishers.pop()!.length).toEqual(1); - - participants = [fakeRemoteLivekitParticipant("@bob:example.org:DEV111", 1)]; - - for (const participant of participants) { - fakeRoomEventEmiter.emit(RoomEvent.ParticipantConnected, participant); - } - - // We should have bob has a publisher now - const publishers = observedPublishers.pop(); - expect(publishers?.length).toEqual(1); - expect(publishers?.[0]?.identity).toEqual("@bob:example.org:DEV111"); -======= // We should have bob as a participant now const ps = observedParticipants.pop(); expect(ps?.length).toEqual(1); expect(ps?.[0]?.identity).toEqual("@bob:example.org:DEV111"); ->>>>>>> livekit // end the parent scope testScope.end(); diff --git a/src/state/CallViewModel/remoteMembers/Connection.ts b/src/state/CallViewModel/remoteMembers/Connection.ts index 9f3f562e1..cf92e2a62 100644 --- a/src/state/CallViewModel/remoteMembers/Connection.ts +++ b/src/state/CallViewModel/remoteMembers/Connection.ts @@ -16,7 +16,7 @@ import { type RemoteParticipant, } from "livekit-client"; import { type LivekitTransport } from "matrix-js-sdk/lib/matrixrtc"; -import { BehaviorSubject } from "rxjs"; +import { BehaviorSubject, map } from "rxjs"; import { type Logger } from "matrix-js-sdk/lib/logger"; import { diff --git a/src/state/CallViewModel/remoteMembers/ConnectionManager.ts b/src/state/CallViewModel/remoteMembers/ConnectionManager.ts index 5db80d081..c1b4af591 100644 --- a/src/state/CallViewModel/remoteMembers/ConnectionManager.ts +++ b/src/state/CallViewModel/remoteMembers/ConnectionManager.ts @@ -19,8 +19,10 @@ import { areLivekitTransportsEqual } from "./MatrixLivekitMembers.ts"; import { type ConnectionFactory } from "./ConnectionFactory.ts"; export class ConnectionManagerData { - private readonly store: Map = - new Map(); + private readonly store: Map< + string, + { connection: Connection; participants: RemoteParticipant[] } + > = new Map(); public constructor() {} @@ -166,11 +168,8 @@ export function createConnectionManager$({ ); // probably not required -<<<<<<< HEAD - if (listOfConnectionsWithParticipants.length === 0) { -======= + if (listOfConnectionsWithRemoteParticipants.length === 0) { ->>>>>>> livekit return of(new Epoch(new ConnectionManagerData(), epoch)); } diff --git a/src/state/CallViewModel/remoteMembers/MatrixLivekitMembers.test.ts b/src/state/CallViewModel/remoteMembers/MatrixLivekitMembers.test.ts index f5929ff9b..d26bac378 100644 --- a/src/state/CallViewModel/remoteMembers/MatrixLivekitMembers.test.ts +++ b/src/state/CallViewModel/remoteMembers/MatrixLivekitMembers.test.ts @@ -91,7 +91,7 @@ test("should signal participant not yet connected to livekit", () => { }), ); - const { matrixLivekitMembers$ } = createMatrixLivekitMembers$({ + const matrixLivekitMembers$ = createMatrixLivekitMembers$({ scope: testScope, membershipsWithTransport$: testScope.behavior(membershipsWithTransport$), connectionManager: { @@ -99,21 +99,24 @@ test("should signal participant not yet connected to livekit", () => { } as unknown as IConnectionManager, }); - expectObservable(matrixLivekitMember$.pipe(map((e) => e.value))).toBe("a", { - a: expect.toSatisfy((data: RemoteMatrixLivekitMember[]) => { - expect(data.length).toEqual(1); - expectObservable(data[0].membership$).toBe("a", { - a: bobMembership, - }); - expectObservable(data[0].participant.value$).toBe("a", { - a: null, - }); - expectObservable(data[0].connection$).toBe("a", { - a: null, - }); - return true; - }), - }); + expectObservable(matrixLivekitMembers$.pipe(map((e) => e.value))).toBe( + "a", + { + a: expect.toSatisfy((data: RemoteMatrixLivekitMember[]) => { + expect(data.length).toEqual(1); + expectObservable(data[0].membership$).toBe("a", { + a: bobMembership, + }); + expectObservable(data[0].participant.value$).toBe("a", { + a: null, + }); + expectObservable(data[0].connection$).toBe("a", { + a: null, + }); + return true; + }), + }, + ); }); }); @@ -171,7 +174,7 @@ test("should signal participant on a connection that is publishing", () => { }), ); - const { matrixLivekitMembers$ } = createMatrixLivekitMembers$({ + const matrixLivekitMembers$ = createMatrixLivekitMembers$({ scope: testScope, membershipsWithTransport$: testScope.behavior(membershipsWithTransport$), connectionManager: { @@ -179,25 +182,28 @@ test("should signal participant on a connection that is publishing", () => { } as unknown as IConnectionManager, }); - expectObservable(matrixLivekitMember$.pipe(map((e) => e.value))).toBe("a", { - a: expect.toSatisfy((data: RemoteMatrixLivekitMember[]) => { - expect(data.length).toEqual(1); - expectObservable(data[0].membership$).toBe("a", { - a: bobMembership, - }); - expectObservable(data[0].participant.value$).toBe("a", { - a: expect.toSatisfy((participant) => { - expect(participant).toBeDefined(); - expect(participant!.identity).toEqual(bobParticipantId); - return true; - }), - }); - expectObservable(data[0].connection$).toBe("a", { - a: connection, - }); - return true; - }), - }); + expectObservable(matrixLivekitMembers$.pipe(map((e) => e.value))).toBe( + "a", + { + a: expect.toSatisfy((data: RemoteMatrixLivekitMember[]) => { + expect(data.length).toEqual(1); + expectObservable(data[0].membership$).toBe("a", { + a: bobMembership, + }); + expectObservable(data[0].participant.value$).toBe("a", { + a: expect.toSatisfy((participant) => { + expect(participant).toBeDefined(); + expect(participant!.identity).toEqual(bobParticipantId); + return true; + }), + }); + expectObservable(data[0].connection$).toBe("a", { + a: connection, + }); + return true; + }), + }, + ); }); }); @@ -222,7 +228,7 @@ test("should signal participant on a connection that is not publishing", () => { }), ); - const { matrixLivekitMembers$ } = createMatrixLivekitMembers$({ + const matrixLivekitMembers$ = createMatrixLivekitMembers$({ scope: testScope, membershipsWithTransport$: testScope.behavior(membershipsWithTransport$), connectionManager: { @@ -230,21 +236,24 @@ test("should signal participant on a connection that is not publishing", () => { } as unknown as IConnectionManager, }); - expectObservable(matrixLivekitMember$.pipe(map((e) => e.value))).toBe("a", { - a: expect.toSatisfy((data: RemoteMatrixLivekitMember[]) => { - expect(data.length).toEqual(1); - expectObservable(data[0].membership$).toBe("a", { - a: bobMembership, - }); - expectObservable(data[0].participant.value$).toBe("a", { - a: null, - }); - expectObservable(data[0].connection$).toBe("a", { - a: connection, - }); - return true; - }), - }); + expectObservable(matrixLivekitMembers$.pipe(map((e) => e.value))).toBe( + "a", + { + a: expect.toSatisfy((data: RemoteMatrixLivekitMember[]) => { + expect(data.length).toEqual(1); + expectObservable(data[0].membership$).toBe("a", { + a: bobMembership, + }); + expectObservable(data[0].participant.value$).toBe("a", { + a: null, + }); + expectObservable(data[0].connection$).toBe("a", { + a: connection, + }); + return true; + }), + }, + ); }); }); @@ -283,7 +292,7 @@ describe("Publication edge case", () => { }), ); - const { matrixLivekitMembers$ } = createMatrixLivekitMembers$({ + const matrixLivekitMembers$ = createMatrixLivekitMembers$({ scope: testScope, membershipsWithTransport$: testScope.behavior( membershipsWithTransport$, @@ -349,7 +358,7 @@ describe("Publication edge case", () => { }), ); - const { matrixLivekitMembers$ } = createMatrixLivekitMembers$({ + const matrixLivekitMembers$ = createMatrixLivekitMembers$({ scope: testScope, membershipsWithTransport$: testScope.behavior( membershipsWithTransport$, diff --git a/src/state/CallViewModel/remoteMembers/MatrixLivekitMembers.ts b/src/state/CallViewModel/remoteMembers/MatrixLivekitMembers.ts index a77037dd5..6501adb42 100644 --- a/src/state/CallViewModel/remoteMembers/MatrixLivekitMembers.ts +++ b/src/state/CallViewModel/remoteMembers/MatrixLivekitMembers.ts @@ -85,7 +85,7 @@ export function createMatrixLivekitMembers$({ * Stream of all the call members and their associated livekit data (if available). */ - const matrixLivekitMembers$ = scope.behavior( + return scope.behavior( combineLatest([ membershipsWithTransport$, connectionManager.connectionManagerData$, @@ -142,11 +142,6 @@ export function createMatrixLivekitMembers$({ ), ), ); - return { - matrixLivekitMembers$, - // TODO add only publishing participants... maybe. disucss at least - // scope.behavior(matrixLivekitMembers$.pipe(map((items) => items.value.map((i)=>{ i.})))) - }; } // TODO add back in the callviewmodel pauseWhen(this.pretendToBeDisconnected$) diff --git a/src/state/CallViewModel/remoteMembers/integration.test.ts b/src/state/CallViewModel/remoteMembers/integration.test.ts index 1093d7219..6108c7bca 100644 --- a/src/state/CallViewModel/remoteMembers/integration.test.ts +++ b/src/state/CallViewModel/remoteMembers/integration.test.ts @@ -124,14 +124,14 @@ test("bob, carl, then bob joining no tracks yet", () => { logger: logger, }); - const { matrixLivekitMembers$ } = createMatrixLivekitMembers$({ + const matrixLivekitMembers$ = createMatrixLivekitMembers$({ scope: testScope, membershipsWithTransport$: membershipsAndTransports.membershipsWithTransport$, connectionManager, }); - expectObservable(matrixLivekitItems$).toBe(vMarble, { + expectObservable(matrixLivekitMembers$).toBe(vMarble, { a: expect.toSatisfy((e: Epoch) => { const items = e.value; expect(items.length).toBe(1); diff --git a/yarn.lock b/yarn.lock index c220c9cea..d9202de22 100644 --- a/yarn.lock +++ b/yarn.lock @@ -11735,6 +11735,15 @@ __metadata: languageName: node linkType: hard +"pkg-dir@npm:^5.0.0": + version: 5.0.0 + resolution: "pkg-dir@npm:5.0.0" + dependencies: + find-up: "npm:^5.0.0" + checksum: 10c0/793a496d685dc55bbbdbbb22d884535c3b29241e48e3e8d37e448113a71b9e42f5481a61fdc672d7322de12fbb2c584dd3a68bf89b18fffce5c48a390f911bc5 + languageName: node + linkType: hard + "playwright-core@npm:1.57.0": version: 1.57.0 resolution: "playwright-core@npm:1.57.0" From 725ff31d6f8c86f02b1bc3da255a26a182d11001 Mon Sep 17 00:00:00 2001 From: Timo K Date: Mon, 22 Dec 2025 13:42:16 +0100 Subject: [PATCH 119/748] reduce PR diff --- src/ClientContext.tsx | 2 +- src/state/CallViewModel/CallViewModel.ts | 18 ++++++------------ 2 files changed, 7 insertions(+), 13 deletions(-) diff --git a/src/ClientContext.tsx b/src/ClientContext.tsx index 518aa38eb..1488965ac 100644 --- a/src/ClientContext.tsx +++ b/src/ClientContext.tsx @@ -358,7 +358,7 @@ export type InitResult = { passwordlessUser: boolean; }; -export async function loadClient(): Promise { +async function loadClient(): Promise { if (widget) { // We're inside a widget, so let's engage *matryoshka mode* logger.log("Using a matryoshka client"); diff --git a/src/state/CallViewModel/CallViewModel.ts b/src/state/CallViewModel/CallViewModel.ts index 00a7d3e9d..252c0c8fc 100644 --- a/src/state/CallViewModel/CallViewModel.ts +++ b/src/state/CallViewModel/CallViewModel.ts @@ -649,12 +649,6 @@ export function createCallViewModel$( return acc; }, []), ), - tap((val) => { - logger.debug( - "livekitRoomItems$ updated", - val.map((v) => v.url), - ); - }), ), [], ); @@ -1480,10 +1474,10 @@ export function createCallViewModel$( ); return { - autoLeave$, - callPickupState$, - ringOverlay$, - leave$, + autoLeave$: autoLeave$, + callPickupState$: callPickupState$, + ringOverlay$: ringOverlay$, + leave$: leave$, hangup: (): void => userHangup$.next(), join: localMembership.requestJoinAndPublish, toggleScreenSharing: toggleScreenSharing, @@ -1509,7 +1503,7 @@ export function createCallViewModel$( ), null, ), - + participantCount$: participantCount, handsRaised$: handsRaised$, reactions$: reactions$, joinSoundEffect$: joinSoundEffect$, @@ -1518,6 +1512,7 @@ export function createCallViewModel$( newScreenShare$: newScreenShare$, audibleReactions$: audibleReactions$, visibleReactions$: visibleReactions$, + windowMode$: windowMode$, spotlightExpanded$: spotlightExpanded$, toggleSpotlightExpanded$: toggleSpotlightExpanded$, @@ -1545,7 +1540,6 @@ export function createCallViewModel$( earpieceMode$: earpieceMode$, audioOutputSwitcher$: audioOutputSwitcher$, reconnecting$: localMembership.reconnecting$, - participantCount$, livekitRoomItems$, connected$: localMembership.connected$, }; From 150dda16c83a1f27b734430976e83cdc466edda0 Mon Sep 17 00:00:00 2001 From: Timo K Date: Mon, 22 Dec 2025 13:44:24 +0100 Subject: [PATCH 120/748] fix lint --- src/state/CallViewModel/CallViewModel.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/state/CallViewModel/CallViewModel.ts b/src/state/CallViewModel/CallViewModel.ts index 252c0c8fc..5324c65de 100644 --- a/src/state/CallViewModel/CallViewModel.ts +++ b/src/state/CallViewModel/CallViewModel.ts @@ -1503,7 +1503,7 @@ export function createCallViewModel$( ), null, ), - participantCount$: participantCount, + participantCount$: participantCount$, handsRaised$: handsRaised$, reactions$: reactions$, joinSoundEffect$: joinSoundEffect$, From 9bd7888fab0ab6f8e3977782ce159885526de6eb Mon Sep 17 00:00:00 2001 From: Timo K Date: Tue, 23 Dec 2025 12:48:54 +0100 Subject: [PATCH 121/748] copyright. --- sdk/helper.ts | 2 +- sdk/main.ts | 2 +- vite-sdk.config.ts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/sdk/helper.ts b/sdk/helper.ts index 7dc2138aa..a3d597be3 100644 --- a/sdk/helper.ts +++ b/sdk/helper.ts @@ -1,5 +1,5 @@ /* -Copyright 2025 New Vector Ltd. +Copyright 2025 Element Creations Ltd. SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial Please see LICENSE in the repository root for full details. diff --git a/sdk/main.ts b/sdk/main.ts index 5b23a700c..376674a41 100644 --- a/sdk/main.ts +++ b/sdk/main.ts @@ -1,5 +1,5 @@ /* -Copyright 2025 New Vector Ltd. +Copyright 2025 Element Creations Ltd. SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial Please see LICENSE in the repository root for full details. diff --git a/vite-sdk.config.ts b/vite-sdk.config.ts index dfa0c023c..48fb6f220 100644 --- a/vite-sdk.config.ts +++ b/vite-sdk.config.ts @@ -1,5 +1,5 @@ /* -Copyright 2025 New Vector Ltd. +Copyright 2025 Element Creations Ltd. SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial Please see LICENSE in the repository root for full details. From 3ba2d13e2771dae0ca1e4687b690c6661f669f9a Mon Sep 17 00:00:00 2001 From: Timo K Date: Sun, 28 Dec 2025 21:04:46 +0100 Subject: [PATCH 122/748] use the js-sdk where the hashed rtcSessionIdeintity is already part of the event (no need to compute it in the encryption manager) --- package.json | 2 +- src/e2ee/matrixKeyProvider.ts | 55 ++--------------------------------- yarn.lock | 10 +++---- 3 files changed, 8 insertions(+), 59 deletions(-) diff --git a/package.json b/package.json index 6c74b84cd..2611587a4 100644 --- a/package.json +++ b/package.json @@ -109,7 +109,7 @@ "livekit-client": "^2.13.0", "lodash-es": "^4.17.21", "loglevel": "^1.9.1", - "matrix-js-sdk": "github:matrix-org/matrix-js-sdk#head=toger5/use-membershipID-for-session-state-events&commit=2bb3b03a248e689f7460f4e70d5ffbf10353c725", + "matrix-js-sdk": "github:matrix-org/matrix-js-sdk#head=toger5/use-membershipID-for-session-state-events&commit=8cea2c05839ebcaa90945504a453b9b1e1092fc4", "matrix-widget-api": "^1.14.0", "normalize.css": "^8.0.1", "observable-hooks": "^4.2.3", diff --git a/src/e2ee/matrixKeyProvider.ts b/src/e2ee/matrixKeyProvider.ts index 166fd82cd..962c9bc62 100644 --- a/src/e2ee/matrixKeyProvider.ts +++ b/src/e2ee/matrixKeyProvider.ts @@ -10,7 +10,6 @@ import { type MatrixRTCSession, MatrixRTCSessionEvent, } from "matrix-js-sdk/lib/matrixrtc"; -import { type CallMembershipIdentityParts } from "matrix-js-sdk/lib/matrixrtc/EncryptionManager"; import { logger as rootLogger } from "matrix-js-sdk/lib/logger"; const logger = rootLogger.getChild("[MatrixKeyProvider]"); @@ -27,10 +26,6 @@ export class MatrixKeyProvider extends BaseKeyProvider { MatrixRTCSessionEvent.EncryptionKeyChanged, this.onEncryptionKeyChanged, ); - this.rtcSession.off( - MatrixRTCSessionEvent.MembershipsChanged, - this.onMembershipsChanged, - ); } this.rtcSession = rtcSession; @@ -39,63 +34,17 @@ export class MatrixKeyProvider extends BaseKeyProvider { MatrixRTCSessionEvent.EncryptionKeyChanged, this.onEncryptionKeyChanged, ); - this.rtcSession.on( - MatrixRTCSessionEvent.MembershipsChanged, - this.onMembershipsChanged, - ); // The new session could be aware of keys of which the old session wasn't, // so emit key changed events this.rtcSession.reemitEncryptionKeys(); } - private keyCache = new Array<{ - membership: CallMembershipIdentityParts; - encryptionKey: Uint8Array; - encryptionKeyIndex: number; - }>(); - - private onMembershipsChanged = (): void => { - const duplicatedArray = this.keyCache; - // Reset key cache first. It will get repopulated when calling `onEncryptionKeyChanged` - this.keyCache = []; - let next = duplicatedArray.pop(); - while (next !== undefined) { - logger.debug( - "[KeyCache] remove key event from the cache and try adding it again. For membership: ", - next.membership, - ); - this.onEncryptionKeyChanged( - next.encryptionKey, - next.encryptionKeyIndex, - next.membership, - ); - next = duplicatedArray.pop(); - } - }; - private onEncryptionKeyChanged = ( encryptionKey: Uint8Array, encryptionKeyIndex: number, - membership: CallMembershipIdentityParts, + rtcBackendIdentity: string, ): void => { - // This is the only way we can get the kind of the membership event we just received the key for. - // best case we want to recompute this once the memberships change (you can receive the key before the participant...) - const membershipFull = this.rtcSession?.memberships.find( - (m) => - m.userId === membership.userId && - m.deviceId === membership.deviceId && - m.memberId === membership.memberId, - ); - if (!membershipFull) { - logger.debug( - "[KeyCache] Added key event to the cache because we do not have a membership for it (yet): ", - membership, - ); - this.keyCache.push({ membership, encryptionKey, encryptionKeyIndex }); - return; - } - crypto.subtle .importKey("raw", encryptionKey, "HKDF", false, [ "deriveBits", @@ -105,7 +54,7 @@ export class MatrixKeyProvider extends BaseKeyProvider { (keyMaterial) => { this.onSetEncryptionKey( keyMaterial, - membershipFull.rtcBackendIdentity, + rtcBackendIdentity, encryptionKeyIndex, ); diff --git a/yarn.lock b/yarn.lock index c4b2e957d..0ddaad61a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -7533,7 +7533,7 @@ __metadata: livekit-client: "npm:^2.13.0" lodash-es: "npm:^4.17.21" loglevel: "npm:^1.9.1" - matrix-js-sdk: "github:matrix-org/matrix-js-sdk#head=toger5/use-membershipID-for-session-state-events&commit=2bb3b03a248e689f7460f4e70d5ffbf10353c725" + matrix-js-sdk: "github:matrix-org/matrix-js-sdk#head=toger5/use-membershipID-for-session-state-events&commit=8cea2c05839ebcaa90945504a453b9b1e1092fc4" matrix-widget-api: "npm:^1.14.0" normalize.css: "npm:^8.0.1" observable-hooks: "npm:^4.2.3" @@ -10338,9 +10338,9 @@ __metadata: languageName: node linkType: hard -"matrix-js-sdk@github:matrix-org/matrix-js-sdk#head=toger5/use-membershipID-for-session-state-events&commit=2bb3b03a248e689f7460f4e70d5ffbf10353c725": - version: 39.3.0 - resolution: "matrix-js-sdk@https://github.com/matrix-org/matrix-js-sdk.git#commit=2bb3b03a248e689f7460f4e70d5ffbf10353c725" +"matrix-js-sdk@github:matrix-org/matrix-js-sdk#head=toger5/use-membershipID-for-session-state-events&commit=8cea2c05839ebcaa90945504a453b9b1e1092fc4": + version: 39.4.0 + resolution: "matrix-js-sdk@https://github.com/matrix-org/matrix-js-sdk.git#commit=8cea2c05839ebcaa90945504a453b9b1e1092fc4" dependencies: "@babel/runtime": "npm:^7.12.5" "@matrix-org/matrix-sdk-crypto-wasm": "npm:^16.0.0" @@ -10356,7 +10356,7 @@ __metadata: sdp-transform: "npm:^3.0.0" unhomoglyph: "npm:^1.0.6" uuid: "npm:13" - checksum: 10c0/2e7061f6e648c91aaeb30b3e01626d855e24efcb330bbe432fcba199bd46b0b0d998cbc545748e1c72a7b643d25581f988fcad9bbaa42912a6ec96a27c41d0de + checksum: 10c0/2375dd3d9191f78fe589b0d3170f3da7792ed469a81d3ba3cd12f4915fd33a859f8af3491edb9cf0cdaa1f881a3ea7c1bf7539e850ad0360ec9981271f462c81 languageName: node linkType: hard From 0f5c5d8be56d0f3bd522516cb7e693d4c879033a Mon Sep 17 00:00:00 2001 From: Timo K Date: Mon, 29 Dec 2025 17:38:54 +0100 Subject: [PATCH 123/748] cleanup based on new js-sdk impl --- package.json | 2 +- src/e2ee/matrixKeyProvider.ts | 6 +- src/livekit/openIDSFU.ts | 37 +++++++--- src/room/CallEventAudioRenderer.test.tsx | 8 --- src/room/InCallView.test.tsx | 8 --- src/settings/settings.ts | 6 ++ src/state/CallViewModel/CallViewModel.ts | 40 +++++------ .../localMember/LocalTransport.test.ts | 8 +-- .../localMember/LocalTransport.ts | 65 +++++++++-------- .../remoteMembers/Connection.test.ts | 4 +- .../CallViewModel/remoteMembers/Connection.ts | 23 +++--- .../remoteMembers/ConnectionFactory.ts | 9 ++- .../remoteMembers/ConnectionManager.test.ts | 21 +++--- .../remoteMembers/ConnectionManager.ts | 72 +++++++++++++------ .../remoteMembers/integration.test.ts | 10 ++- src/state/SessionBehaviors.ts | 15 ++-- src/utils/test.ts | 5 +- yarn.lock | 8 +-- 18 files changed, 191 insertions(+), 156 deletions(-) diff --git a/package.json b/package.json index 2611587a4..346c12cf7 100644 --- a/package.json +++ b/package.json @@ -109,7 +109,7 @@ "livekit-client": "^2.13.0", "lodash-es": "^4.17.21", "loglevel": "^1.9.1", - "matrix-js-sdk": "github:matrix-org/matrix-js-sdk#head=toger5/use-membershipID-for-session-state-events&commit=8cea2c05839ebcaa90945504a453b9b1e1092fc4", + "matrix-js-sdk": "github:matrix-org/matrix-js-sdk#head=toger5/use-membershipID-for-session-state-events&commit=6f0815930a008eff8f86e6e5748d447be0e7c25e", "matrix-widget-api": "^1.14.0", "normalize.css": "^8.0.1", "observable-hooks": "^4.2.3", diff --git a/src/e2ee/matrixKeyProvider.ts b/src/e2ee/matrixKeyProvider.ts index 962c9bc62..a9b0865ff 100644 --- a/src/e2ee/matrixKeyProvider.ts +++ b/src/e2ee/matrixKeyProvider.ts @@ -11,6 +11,7 @@ import { MatrixRTCSessionEvent, } from "matrix-js-sdk/lib/matrixrtc"; import { logger as rootLogger } from "matrix-js-sdk/lib/logger"; +import { type CallMembershipIdentityParts } from "matrix-js-sdk/lib/matrixrtc/EncryptionManager"; const logger = rootLogger.getChild("[MatrixKeyProvider]"); export class MatrixKeyProvider extends BaseKeyProvider { @@ -43,6 +44,7 @@ export class MatrixKeyProvider extends BaseKeyProvider { private onEncryptionKeyChanged = ( encryptionKey: Uint8Array, encryptionKeyIndex: number, + membershipParts: CallMembershipIdentityParts, rtcBackendIdentity: string, ): void => { crypto.subtle @@ -59,12 +61,12 @@ export class MatrixKeyProvider extends BaseKeyProvider { ); logger.debug( - `Sent new key to livekit room=${this.rtcSession?.room.roomId} participantId=${membershipFull.rtcBackendIdentity} (before hash: ${membershipFull.userId}) encryptionKeyIndex=${encryptionKeyIndex}`, + `Sent new key to livekit room=${this.rtcSession?.room.roomId} participantId=${rtcBackendIdentity} (before hash: ${membershipParts.userId}) encryptionKeyIndex=${encryptionKeyIndex}`, ); }, (e) => { logger.error( - `Failed to create key material from buffer for livekit room=${this.rtcSession?.room.roomId} participantId before hash=${membershipFull.userId} encryptionKeyIndex=${encryptionKeyIndex}`, + `Failed to create key material from buffer for livekit room=${this.rtcSession?.room.roomId} participantId before hash=${membershipParts.userId} encryptionKeyIndex=${encryptionKeyIndex}`, e, ); }, diff --git a/src/livekit/openIDSFU.ts b/src/livekit/openIDSFU.ts index f07bb0359..aaf07615b 100644 --- a/src/livekit/openIDSFU.ts +++ b/src/livekit/openIDSFU.ts @@ -6,8 +6,8 @@ Please see LICENSE in the repository root for full details. */ import { type IOpenIDToken, type MatrixClient } from "matrix-js-sdk"; -import { logger } from "matrix-js-sdk/lib/logger"; import { type CallMembershipIdentityParts } from "matrix-js-sdk/lib/matrixrtc/EncryptionManager"; +import { type Logger } from "matrix-js-sdk/lib/logger"; import { FailToGetOpenIdToken } from "../utils/errors"; import { doNetworkOperationWithRetry } from "../utils/matrix"; @@ -28,8 +28,17 @@ export type OpenIDClientParts = Pick< * to the matrix RTC backend in order to get acces to the SFU. * It has built-in retry for calls to the homeserver with a backoff policy. * @param client + * @param membership * @param serviceUrl - * @param matrixRoomId + * @param forceOldEndpoint This will use the old jwt endpoint which will create the rtc backend identity based on string concatination + * instead of a hash. + * This function by default uses whatever is possible with the current jwt service installed next to the SFU. + * For remote connections this does not matter, since we will not publish there we can rely on the newest option. + * For our own connection we can only use the hashed version if we also send the new matrix2.0 sticky events. + * @param livekitRoomAlias + * @param delayEndpointBaseUrl + * @param delayId + * @param logger * @returns Object containing the token information * @throws FailToGetOpenIdToken */ @@ -37,10 +46,11 @@ export async function getSFUConfigWithOpenID( client: OpenIDClientParts, membership: CallMembershipIdentityParts, serviceUrl: string, + forceOldJwtEndpoint: boolean, livekitRoomAlias: string, - matrix2jwt: boolean, delayEndpointBaseUrl?: string, delayId?: string, + logger?: Logger, ): Promise { let openIdToken: IOpenIDToken; try { @@ -52,26 +62,35 @@ export async function getSFUConfigWithOpenID( error instanceof Error ? error : new Error("Unknown error"), ); } - logger.debug("Got openID token", openIdToken); + logger?.debug("Got openID token", openIdToken); - logger.info(`Trying to get JWT for focus ${serviceUrl}...`); + logger?.info(`Trying to get JWT for focus ${serviceUrl}...`); const args: [CallMembershipIdentityParts, string, string, IOpenIDToken] = [ membership, serviceUrl, livekitRoomAlias, openIdToken, ]; - if (matrix2jwt) { + try { + // we do not want to try the old endpoint, since we are not sending the new matrix2.0 sticky events (no hashed identity in the event) + if (forceOldJwtEndpoint) throw new Error("Force old jwt endpoint"); + if (!delayId) + throw new Error("No delayId, Won't try matrix 2.0 jwt endpoint."); + const sfuConfig = await getLiveKitJWTWithDelayDelegation( ...args, delayEndpointBaseUrl, delayId, ); - logger.info(`Got JWT from call's active focus URL.`); + logger?.info(`Got JWT from call's active focus URL.`); return sfuConfig; - } else { + } catch (e) { + logger?.warn( + `Failed fetching jwt with matrix 2.0 endpoint (retry with legacy)`, + e, + ); const sfuConfig = await getLiveKitJWT(...args); - logger.info(`Got JWT from call's active focus URL.`); + logger?.info(`Got JWT from call's active focus URL.`); return sfuConfig; } } diff --git a/src/room/CallEventAudioRenderer.test.tsx b/src/room/CallEventAudioRenderer.test.tsx index 38f56b14d..733346ebb 100644 --- a/src/room/CallEventAudioRenderer.test.tsx +++ b/src/room/CallEventAudioRenderer.test.tsx @@ -23,7 +23,6 @@ import { import { exampleTransport, - mockComputeLivekitParticipantIdentity$, mockMatrixRoomMember, mockRtcMembership, } from "../utils/test"; @@ -48,13 +47,6 @@ vitest.mock("../rtcSessionHelpers", async (importOriginal) => ({ ...(await importOriginal()), makeTransport: (): [LivekitTransport] => [exampleTransport], })); -vitest.mock( - import("../state/CallViewModel/remoteMembers/LivekitParticipantIdentity.ts"), - async (importOriginal) => ({ - ...(await importOriginal()), - computeLivekitParticipantIdentity$: mockComputeLivekitParticipantIdentity$, - }), -); afterEach(() => { vitest.clearAllMocks(); diff --git a/src/room/InCallView.test.tsx b/src/room/InCallView.test.tsx index cd0af5470..8ac4bccba 100644 --- a/src/room/InCallView.test.tsx +++ b/src/room/InCallView.test.tsx @@ -23,7 +23,6 @@ import { TooltipProvider } from "@vector-im/compound-web"; import { RoomContext, useLocalParticipant } from "@livekit/components-react"; import { - mockComputeLivekitParticipantIdentity$, mockLivekitRoom, mockLocalParticipant, mockMatrixRoom, @@ -62,13 +61,6 @@ vi.mock("../livekit/MatrixAudioRenderer"); vi.mock("react-use-measure", () => ({ default: (): [() => void, object] => [(): void => {}, {}], })); -vi.mock( - import("../state/CallViewModel/remoteMembers/LivekitParticipantIdentity.ts"), - async (importOriginal) => ({ - ...(await importOriginal()), - computeLivekitParticipantIdentity$: mockComputeLivekitParticipantIdentity$, - }), -); const localRtcMember = mockRtcMembership("@carol:example.org", "CCCC"); const localParticipant = mockLocalParticipant({ diff --git a/src/settings/settings.ts b/src/settings/settings.ts index f85e1414b..33408fd90 100644 --- a/src/settings/settings.ts +++ b/src/settings/settings.ts @@ -127,6 +127,12 @@ export const alwaysShowIphoneEarpiece = new Setting( export enum MatrixRTCMode { Legacy = "legacy", Compatibil = "compatibil", + /** This implies using + * - sticky events + * - hashed RTC backend identity + * - the new endpoint for the jwt token on the local membership (remote memberships will always try the new jwt endpoint first -> then the legacy one) + * - use the hashed identity for the local membership + */ Matrix_2_0 = "matrix_2_0", } diff --git a/src/state/CallViewModel/CallViewModel.ts b/src/state/CallViewModel/CallViewModel.ts index 23c58268c..922a390e4 100644 --- a/src/state/CallViewModel/CallViewModel.ts +++ b/src/state/CallViewModel/CallViewModel.ts @@ -415,17 +415,18 @@ export function createCallViewModel$( const ownMembershipIdentity: CallMembershipIdentityParts = { userId, deviceId, + // TODO look into this!!! memberId: `${userId}:${deviceId}`, }; + const useOldJwtEndpoint$ = scope.behavior( + options.matrixRTCMode$.pipe(map((v) => v !== MatrixRTCMode.Matrix_2_0)), + ); const localTransport$ = createLocalTransport$({ scope: scope, memberships$: memberships$, ownMembershipIdentity, client, - useMatrix2$: scope.behavior( - options.matrixRTCMode$.pipe(map((v) => v === MatrixRTCMode.Matrix_2_0)), - ), delayId$: scope.behavior( ( fromEvent( @@ -436,6 +437,7 @@ export function createCallViewModel$( matrixRTCSession.delayId ?? null, ), roomId: matrixRoom.roomId, + useOldJwtEndpoint$, useOldestMember$: scope.behavior( options.matrixRTCMode$.pipe(map((v) => v === MatrixRTCMode.Legacy)), ), @@ -455,29 +457,19 @@ export function createCallViewModel$( const connectionManager = createConnectionManager$({ scope: scope, connectionFactory: connectionFactory, - inputTransports$: scope.behavior( - combineLatest( - [ - localTransport$.pipe( - catchError((e: unknown) => { - logger.info( - "dont pass local transport to createConnectionManager$. localTransport$ threw an error", - e, - ); - return of(null); - }), - ), - membershipsAndTransports.transports$, - ], - (localTransport, transports) => { - const localTransportAsArray = localTransport ? [localTransport] : []; - return transports.mapInner((transports) => [ - ...localTransportAsArray, - ...transports, - ]); - }, + localTransport$: scope.behavior( + localTransport$.pipe( + catchError((e: unknown) => { + logger.info( + "could not pass local transport to createConnectionManager$. localTransport$ threw an error", + e, + ); + return of(null); + }), ), ), + remoteTransports$: membershipsAndTransports.transports$, + forceOldJwtEndpointForLocalTransport$: useOldJwtEndpoint$, logger: logger, ownMembershipIdentity, }); diff --git a/src/state/CallViewModel/localMember/LocalTransport.test.ts b/src/state/CallViewModel/localMember/LocalTransport.test.ts index ba0307575..e7df6e33e 100644 --- a/src/state/CallViewModel/localMember/LocalTransport.test.ts +++ b/src/state/CallViewModel/localMember/LocalTransport.test.ts @@ -38,7 +38,7 @@ describe("LocalTransport", () => { getDeviceId: vi.fn(), }, ownMembershipIdentity: ownMemberMock, - useMatrix2$: constant(false), + useOldJwtEndpoint$: constant(false), delayId$: constant("delay_id_mock"), }); await flushPromises(); @@ -76,7 +76,7 @@ describe("LocalTransport", () => { getDeviceId: vi.fn(), }, ownMembershipIdentity: ownMemberMock, - useMatrix2$: constant(false), + useOldJwtEndpoint$: constant(false), delayId$: constant("delay_id_mock"), }); localTransport$.subscribe( @@ -116,7 +116,7 @@ describe("LocalTransport", () => { baseUrl: "https://lk.example.org", }, ownMembershipIdentity: ownMemberMock, - useMatrix2$: constant(false), + useOldJwtEndpoint$: constant(false), delayId$: constant("delay_id_mock"), }); @@ -155,7 +155,7 @@ describe("LocalTransport", () => { baseUrl: "https://lk.example.org", }, ownMembershipIdentity: ownMemberMock, - useMatrix2$: constant(false), + useOldJwtEndpoint$: constant(false), delayId$: constant("delay_id_mock"), }); diff --git a/src/state/CallViewModel/localMember/LocalTransport.ts b/src/state/CallViewModel/localMember/LocalTransport.ts index 6c3e1cd0a..b44cf9671 100644 --- a/src/state/CallViewModel/localMember/LocalTransport.ts +++ b/src/state/CallViewModel/localMember/LocalTransport.ts @@ -35,7 +35,6 @@ import { } from "../../../livekit/openIDSFU.ts"; import { areLivekitTransportsEqual } from "../remoteMembers/MatrixLivekitMembers.ts"; import { customLivekitUrl } from "../../../settings/settings.ts"; -import { type LivekitTransportWithVersion } from "../remoteMembers/ConnectionManager.ts"; const logger = rootLogger.getChild("[LocalTransport]"); @@ -51,7 +50,7 @@ interface Props { client: Pick & OpenIDClientParts; roomId: string; useOldestMember$: Behavior; - useMatrix2$: Behavior; + useOldJwtEndpoint$: Behavior; delayId$: Behavior; } @@ -62,6 +61,11 @@ interface Props { * @prop useOldestMember Whether to use the same transport as the oldest member. * This will only update once the first oldest member appears. Will not recompute if the oldest member leaves. * + * @prop useOldJwtEndpoint$ Whether to set forceOldJwtEndpoint the use the old JWT endpoint. + * This is used when the connection manager needs to know if it has to use the legacy endpoint which implies a string concatenated rtcBackendIdentity. + * (which is expected for non sticky event based rtc member events) + * @returns Behavior<(LivekitTransport & { forceOldJwtEndpoint: boolean }) | null> The `forceOldJwtEndpoint` field is added to let the connection EncryptionManager + * know that this transport is for the local member and it IS RELEVANT which jwt endpoint to use. (for the local member transport, we need to know which jwt endpoint to use) * @throws MatrixRTCTransportMissingError | FailToGetOpenIdToken */ export const createLocalTransport$ = ({ @@ -71,21 +75,20 @@ export const createLocalTransport$ = ({ client, roomId, useOldestMember$, - useMatrix2$, + useOldJwtEndpoint$, delayId$, -}: Props): Behavior => { +}: Props): Behavior => { /** * The transport over which we should be actively publishing our media. * undefined when not joined. */ const oldestMemberTransport$ = scope.behavior( - memberships$.pipe( - map((memberships) => { + combineLatest([memberships$, useOldJwtEndpoint$]).pipe( + map(([memberships, forceOldJwtEndpoint]) => { const oldestMember = memberships.value[0]; - const t = oldestMember?.getTransport(memberships.value[0]); - if (!t) return null; - // Here we will use the matrix2 information from the oldest member transport. - return { ...t, useMatrix2: oldestMember.kind === "rtc" }; + const transport = oldestMember?.getTransport(memberships.value[0]); + if (!transport) return null; + return { ...transport, forceOldJwtEndpoint }; }), first((t) => t != null && isLivekitTransport(t)), ), @@ -98,24 +101,23 @@ export const createLocalTransport$ = ({ * * @throws MatrixRTCTransportMissingError | FailToGetOpenIdToken */ - const preferredTransport$: Behavior = - scope.behavior( - combineLatest([customLivekitUrl.value$, useMatrix2$, delayId$]).pipe( - switchMap(([customUrl, useMatrix2, delayId]) => - from( - makeTransport( - client, - ownMembershipIdentity, - roomId, - customUrl, - useMatrix2, - delayId ?? undefined, - ), + const preferredTransport$: Behavior = scope.behavior( + combineLatest([customLivekitUrl.value$, delayId$, useOldJwtEndpoint$]).pipe( + switchMap(([customUrl, delayId, forceOldJwtEndpoint]) => + from( + makeTransport( + client, + ownMembershipIdentity, + roomId, + customUrl, + forceOldJwtEndpoint, + delayId ?? undefined, ), ), ), - null, - ); + ), + null, + ); /** * The chosen transport we should advertise in our MatrixRTC membership. @@ -131,7 +133,7 @@ export const createLocalTransport$ = ({ ? (oldestMemberTransport ?? preferredTransport) : preferredTransport, ), - distinctUntilChanged(areLivekitTransportsEqual), + distinctUntilChanged((t1, t2) => areLivekitTransportsEqual(t1, t2)), ), ); }; @@ -142,6 +144,8 @@ const FOCI_WK_KEY = "org.matrix.msc4143.rtc_foci"; * * @param client * @param roomId + * @param useMatrix2 This implies using the matrix2 jwt endpoint (including delayed event delegation of the jwt token) + * @param delayId * @returns * @throws MatrixRTCTransportMissingError | FailToGetOpenIdToken */ @@ -150,9 +154,9 @@ async function makeTransport( membership: CallMembershipIdentityParts, roomId: string, urlFromDevSettings: string | null, - matrix2jwt = false, + forceOldJwtEndpoint: boolean, delayId?: string, -): Promise { +): Promise { let transport: LivekitTransport | undefined; logger.trace("Searching for a preferred transport"); //TODO refactor this to use the jwt service returned alias. @@ -209,11 +213,12 @@ async function makeTransport( client, membership, transport.livekit_service_url, + forceOldJwtEndpoint, transport.livekit_alias, - matrix2jwt, client.baseUrl, delayId, + logger, ); - return { ...transport, useMatrix2: matrix2jwt }; + return { ...transport, forceOldJwtEndpoint }; } diff --git a/src/state/CallViewModel/remoteMembers/Connection.test.ts b/src/state/CallViewModel/remoteMembers/Connection.test.ts index 533f451a4..575786418 100644 --- a/src/state/CallViewModel/remoteMembers/Connection.test.ts +++ b/src/state/CallViewModel/remoteMembers/Connection.test.ts @@ -26,6 +26,7 @@ import fetchMock from "fetch-mock"; import EventEmitter from "events"; import { type IOpenIDToken } from "matrix-js-sdk"; import { logger } from "matrix-js-sdk/lib/logger"; +import { type LivekitTransport } from "matrix-js-sdk/lib/matrixrtc/LivekitTransport"; import { Connection, @@ -39,7 +40,6 @@ import { FailToGetOpenIdToken, } from "../../../utils/errors.ts"; import { mockRemoteParticipant, ownMemberMock } from "../../../utils/test.ts"; -import { type LivekitTransportWithVersion } from "./ConnectionManager.ts"; let testScope: ObservableScope; @@ -50,7 +50,7 @@ let fakeLivekitRoom: MockedObject; let localParticipantEventEmiter: EventEmitter; let fakeLocalParticipant: MockedObject; -const livekitFocus: LivekitTransportWithVersion = { +const livekitFocus: LivekitTransport = { livekit_alias: "!roomID:example.org", livekit_service_url: "https://matrix-rtc.example.org/livekit/jwt", type: "livekit", diff --git a/src/state/CallViewModel/remoteMembers/Connection.ts b/src/state/CallViewModel/remoteMembers/Connection.ts index d32bbce69..e070b56bb 100644 --- a/src/state/CallViewModel/remoteMembers/Connection.ts +++ b/src/state/CallViewModel/remoteMembers/Connection.ts @@ -35,8 +35,10 @@ import { } from "../../../utils/errors.ts"; export interface ConnectionOpts { + /** Whether we always try to connect to this connection via the legacy jwt endpoint. (no hash identity) */ + forceOldJwtEndpoint?: boolean; /** The media transport to connect to. */ - transport: LivekitTransport & { useMatrix2: boolean }; + transport: LivekitTransport; /** The Matrix client to use for OpenID and SFU config requests. */ client: OpenIDClientParts; /** The observable scope to use for this connection. */ @@ -89,7 +91,7 @@ export class Connection { /** * The media transport to connect to. */ - public readonly transport: LivekitTransport & { useMatrix2: boolean }; + public readonly transport: LivekitTransport; public readonly livekitRoom: LivekitRoom; @@ -192,16 +194,14 @@ export class Connection { this.client, this.ownMembershipIdentity, this.transport.livekit_service_url, + this.forceOldJwtEndpoint, this.transport.livekit_alias, - this.transport.useMatrix2, + // For the remote members we intentionally do not pass a delayEndpointBaseUrl. + undefined, + // and no delayId. + undefined, + this.logger, ); - // client: OpenIDClientParts, - // membership: CallMembershipIdentityParts, - // serviceUrl: string, - // livekitRoomAlias: string, - // matrix2jwt: boolean, - // delayEndpointBaseUrl?: string, - // delayId?: string, } /** @@ -222,7 +222,7 @@ export class Connection { private readonly client: OpenIDClientParts; private readonly logger: Logger; - + private readonly forceOldJwtEndpoint: boolean; /** * Creates a new connection to a matrix RTC LiveKit backend. * @@ -235,6 +235,7 @@ export class Connection { logger: Logger, private ownMembershipIdentity: CallMembershipIdentityParts, ) { + this.forceOldJwtEndpoint = opts.forceOldJwtEndpoint ?? false; this.logger = logger.getChild("[Connection]"); this.logger.info( `[Connection] Creating new connection to ${opts.transport.livekit_service_url} ${opts.transport.livekit_alias}`, diff --git a/src/state/CallViewModel/remoteMembers/ConnectionFactory.ts b/src/state/CallViewModel/remoteMembers/ConnectionFactory.ts index 82a1a78a5..94652d16a 100644 --- a/src/state/CallViewModel/remoteMembers/ConnectionFactory.ts +++ b/src/state/CallViewModel/remoteMembers/ConnectionFactory.ts @@ -15,6 +15,7 @@ import { import { type Logger } from "matrix-js-sdk/lib/logger"; import E2EEWorker from "livekit-client/e2ee-worker?worker"; import { type CallMembershipIdentityParts } from "matrix-js-sdk/lib/matrixrtc/EncryptionManager"; +import { type LivekitTransport } from "matrix-js-sdk/lib/matrixrtc/LivekitTransport"; import { type ObservableScope } from "../../ObservableScope.ts"; import { Connection } from "./Connection.ts"; @@ -23,15 +24,15 @@ import type { MediaDevices } from "../../MediaDevices.ts"; import type { Behavior } from "../../Behavior.ts"; import type { ProcessorState } from "../../../livekit/TrackProcessorContext.tsx"; import { defaultLiveKitOptions } from "../../../livekit/options.ts"; -import { type LivekitTransportWithVersion } from "./ConnectionManager.ts"; // TODO evaluate if this should be done like the Publisher Factory export interface ConnectionFactory { createConnection( - transport: LivekitTransportWithVersion, + transport: LivekitTransport, scope: ObservableScope, logger: Logger, ownMembershipIdentity: CallMembershipIdentityParts, + forceOldJwtEndpoint?: boolean, ): Connection; } @@ -88,10 +89,11 @@ export class ECConnectionFactory implements ConnectionFactory { * @returns */ public createConnection( - transport: LivekitTransportWithVersion, + transport: LivekitTransport, scope: ObservableScope, logger: Logger, ownMembershipIdentity: CallMembershipIdentityParts, + forceOldJwtEndpoint?: boolean, ): Connection { return new Connection( { @@ -99,6 +101,7 @@ export class ECConnectionFactory implements ConnectionFactory { client: this.client, scope: scope, livekitRoomFactory: this.livekitRoomFactory, + forceOldJwtEndpoint, }, logger, ownMembershipIdentity, diff --git a/src/state/CallViewModel/remoteMembers/ConnectionManager.test.ts b/src/state/CallViewModel/remoteMembers/ConnectionManager.test.ts index 4ab916469..088bf41b1 100644 --- a/src/state/CallViewModel/remoteMembers/ConnectionManager.test.ts +++ b/src/state/CallViewModel/remoteMembers/ConnectionManager.test.ts @@ -14,29 +14,26 @@ import { logger } from "matrix-js-sdk/lib/logger"; import { Epoch, mapEpoch, ObservableScope } from "../../ObservableScope.ts"; import { createConnectionManager$, - type LivekitTransportWithVersion, type ConnectionManagerData, } from "./ConnectionManager.ts"; import { type ConnectionFactory } from "./ConnectionFactory.ts"; import { type Connection } from "./Connection.ts"; import { ownMemberMock, withTestScheduler } from "../../../utils/test.ts"; import { areLivekitTransportsEqual } from "./MatrixLivekitMembers.ts"; -import { type Behavior } from "../../Behavior.ts"; +import { constant, type Behavior } from "../../Behavior.ts"; // Some test constants -const TRANSPORT_1: LivekitTransportWithVersion = { +const TRANSPORT_1: LivekitTransport = { type: "livekit", livekit_service_url: "https://lk.example.org", livekit_alias: "!alias:example.org", - useMatrix2: false, }; -const TRANSPORT_2: LivekitTransportWithVersion = { +const TRANSPORT_2: LivekitTransport = { type: "livekit", livekit_service_url: "https://lk.sample.com", livekit_alias: "!alias:sample.com", - useMatrix2: false, }; let fakeConnectionFactory: ConnectionFactory; @@ -79,7 +76,8 @@ describe("connections$ stream", () => { const { connectionManagerData$ } = createConnectionManager$({ scope: testScope, connectionFactory: fakeConnectionFactory, - inputTransports$: behavior("a", { + localTransport$: constant(null), + remoteTransports$: behavior("a", { a: new Epoch([TRANSPORT_1, TRANSPORT_2], 0), }), logger: logger, @@ -119,7 +117,8 @@ describe("connections$ stream", () => { const { connectionManagerData$ } = createConnectionManager$({ scope: testScope, connectionFactory: fakeConnectionFactory, - inputTransports$: behavior("abcdef", { + localTransport$: constant(null), + remoteTransports$: behavior("abcdef", { a: new Epoch([TRANSPORT_1], 0), b: new Epoch([TRANSPORT_1], 1), c: new Epoch([TRANSPORT_1], 2), @@ -165,7 +164,8 @@ describe("connections$ stream", () => { const { connectionManagerData$ } = createConnectionManager$({ scope: testScope, connectionFactory: fakeConnectionFactory, - inputTransports$: behavior("abc", { + localTransport$: constant(null), + remoteTransports$: behavior("abc", { a: new Epoch([TRANSPORT_1], 0), b: new Epoch([TRANSPORT_1, TRANSPORT_2], 1), c: new Epoch([TRANSPORT_1], 2), @@ -281,7 +281,8 @@ describe("connectionManagerData$ stream", () => { const { connectionManagerData$ } = createConnectionManager$({ scope: testScope, connectionFactory: fakeConnectionFactory, - inputTransports$: behavior("a", { + localTransport$: constant(null), + remoteTransports$: behavior("a", { a: new Epoch([TRANSPORT_1, TRANSPORT_2], 0), }), logger, diff --git a/src/state/CallViewModel/remoteMembers/ConnectionManager.ts b/src/state/CallViewModel/remoteMembers/ConnectionManager.ts index d5852d845..6101f79bf 100644 --- a/src/state/CallViewModel/remoteMembers/ConnectionManager.ts +++ b/src/state/CallViewModel/remoteMembers/ConnectionManager.ts @@ -7,22 +7,18 @@ Please see LICENSE in the repository root for full details. */ import { type LivekitTransport } from "matrix-js-sdk/lib/matrixrtc"; -import { combineLatest, map, of, switchMap, tap } from "rxjs"; +import { combineLatest, map, of, switchMap } from "rxjs"; import { type Logger } from "matrix-js-sdk/lib/logger"; import { type RemoteParticipant } from "livekit-client"; import { type CallMembershipIdentityParts } from "matrix-js-sdk/lib/matrixrtc/EncryptionManager"; -import { type Behavior } from "../../Behavior.ts"; +import { constant, type Behavior } from "../../Behavior.ts"; import { type Connection } from "./Connection.ts"; import { Epoch, type ObservableScope } from "../../ObservableScope.ts"; import { generateItemsWithEpoch } from "../../../utils/observable.ts"; import { areLivekitTransportsEqual } from "./MatrixLivekitMembers.ts"; import { type ConnectionFactory } from "./ConnectionFactory.ts"; -export type LivekitTransportWithVersion = LivekitTransport & { - useMatrix2: boolean; -}; - export class ConnectionManagerData { private readonly store: Map = new Map(); @@ -64,7 +60,9 @@ export class ConnectionManagerData { interface Props { scope: ObservableScope; connectionFactory: ConnectionFactory; - inputTransports$: Behavior>; + localTransport$: Behavior; + remoteTransports$: Behavior>; + forceOldJwtEndpointForLocalTransport$?: Behavior; logger: Logger; ownMembershipIdentity: CallMembershipIdentityParts; } @@ -91,13 +89,29 @@ export interface IConnectionManager { export function createConnectionManager$({ scope, connectionFactory, - inputTransports$, + localTransport$, + remoteTransports$, + forceOldJwtEndpointForLocalTransport$ = constant(false), logger: parentLogger, ownMembershipIdentity, }: Props): IConnectionManager { const logger = parentLogger.getChild("[ConnectionManager]"); // TODO logger: only construct one logger from the client and make it compatible via a EC specific sing + const allInputTransports$ = combineLatest([ + localTransport$, + remoteTransports$, + ]).pipe( + map(([localTransport, transports]) => { + const localTransportAsArray = localTransport ? [localTransport] : []; + return transports.mapInner((transports) => [ + ...localTransportAsArray, + ...transports, + ]); + }), + map((transports) => transports.mapInner(removeDuplicateTransports)), + ); + /** * All transports currently managed by the ConnectionManager. * @@ -106,14 +120,32 @@ export function createConnectionManager$({ * It is build based on the list of subscribed transports (`transportsSubscriptions$`). * externally this is modified via `registerTransports()`. */ - const transports$ = scope.behavior( - inputTransports$.pipe( - map((transports) => transports.mapInner(removeDuplicateTransports)), - tap(({ value: transports }) => { - logger.trace( - `Managing transports: ${transports.map((t) => t.livekit_service_url).join(", ")}`, - ); - }), + const transportsWithJwtTag$ = scope.behavior( + combineLatest([ + allInputTransports$, + localTransport$, + forceOldJwtEndpointForLocalTransport$, + ]).pipe( + map( + ([ + transports, + localTransport, + forceOldJwtEndpointForLocalTransport, + ]) => { + // nmodify only the local transport with forceOldJwtEndpointForLocalTransport + const index = transports.value.findIndex((t) => + areLivekitTransportsEqual(localTransport, t), + ); + transports.value[index].forceOldJwtEndpoint = + forceOldJwtEndpointForLocalTransport; + logger.trace( + `Managing transports: ${transports.value.map((t) => t.livekit_service_url).join(", ")}`, + ); + return transports as Epoch< + (LivekitTransport & { forceOldJwtEndpoint?: boolean })[] + >; + }, + ), ), ); @@ -121,7 +153,7 @@ export function createConnectionManager$({ * Connections for each transport in use by one or more session members. */ const connections$ = scope.behavior( - transports$.pipe( + transportsWithJwtTag$.pipe( generateItemsWithEpoch( function* (transports) { for (const transport of transports) @@ -129,23 +161,23 @@ export function createConnectionManager$({ keys: [ transport.livekit_service_url, transport.livekit_alias, - transport.useMatrix2, + transport.forceOldJwtEndpoint, ], data: undefined, }; }, - (scope, _data$, serviceUrl, alias, useMatrix2) => { + (scope, _data$, serviceUrl, alias, forceOldJwtEndpoint) => { logger.debug(`Creating connection to ${serviceUrl} (${alias})`); const connection = connectionFactory.createConnection( { type: "livekit", livekit_service_url: serviceUrl, livekit_alias: alias, - useMatrix2, }, scope, logger, ownMembershipIdentity, + forceOldJwtEndpoint, ); // Start the connection immediately // Use connection state to track connection progress diff --git a/src/state/CallViewModel/remoteMembers/integration.test.ts b/src/state/CallViewModel/remoteMembers/integration.test.ts index 00062c60d..df10c8619 100644 --- a/src/state/CallViewModel/remoteMembers/integration.test.ts +++ b/src/state/CallViewModel/remoteMembers/integration.test.ts @@ -13,11 +13,7 @@ import fetchMock from "fetch-mock"; import { type LivekitTransport } from "matrix-js-sdk/lib/matrixrtc"; import { logger } from "matrix-js-sdk/lib/logger"; -import { - type Epoch, - ObservableScope, - trackEpoch, -} from "../../ObservableScope.ts"; +import { type Epoch, ObservableScope, trackEpoch } from "../../ObservableScope.ts"; import { ECConnectionFactory } from "./ConnectionFactory.ts"; import { type OpenIDClientParts } from "../../../livekit/openIDSFU.ts"; import { @@ -34,6 +30,7 @@ import { } from "./MatrixLivekitMembers.ts"; import { createConnectionManager$ } from "./ConnectionManager.ts"; import { membershipsAndTransports$ } from "../../SessionBehaviors.ts"; +import { constant } from "../../Behavior.ts"; // Test the integration of ConnectionManager and MatrixLivekitMerger @@ -121,7 +118,8 @@ test("bob, carl, then bob joining no tracks yet", () => { const connectionManager = createConnectionManager$({ scope: testScope, connectionFactory: ecConnectionFactory, - inputTransports$: membershipsAndTransports.transports$, + localTransport$: constant(null), + remoteTransports$: membershipsAndTransports.transports$, logger: logger, ownMembershipIdentity: ownMemberMock, }); diff --git a/src/state/SessionBehaviors.ts b/src/state/SessionBehaviors.ts index b61d2fe6a..e174a1ccc 100644 --- a/src/state/SessionBehaviors.ts +++ b/src/state/SessionBehaviors.ts @@ -8,6 +8,7 @@ Please see LICENSE in the repository root for full details. import { type CallMembership, isLivekitTransport, + type LivekitTransport, type MatrixRTCSession, MatrixRTCSessionEvent, } from "matrix-js-sdk/lib/matrixrtc"; @@ -20,18 +21,15 @@ import { type ObservableScope, } from "./ObservableScope"; import { type Behavior } from "./Behavior"; -import { type LivekitTransportWithVersion } from "./CallViewModel/remoteMembers/ConnectionManager"; export const membershipsAndTransports$ = ( scope: ObservableScope, memberships$: Behavior>, ): { membershipsWithTransport$: Behavior< - Epoch< - { membership: CallMembership; transport?: LivekitTransportWithVersion }[] - > + Epoch<{ membership: CallMembership; transport?: LivekitTransport }[]> >; - transports$: Behavior>; + transports$: Behavior>; } => { /** * Lists the transports used by ourselves, plus all other MatrixRTC session @@ -49,12 +47,7 @@ export const membershipsAndTransports$ = ( const transport = membership.getTransport(oldestMembership); return { membership, - transport: isLivekitTransport(transport) - ? { - ...transport, - useMatrix2: membership.kind === "rtc", - } - : undefined, + transport: isLivekitTransport(transport) ? transport : undefined, }; }); }), diff --git a/src/utils/test.ts b/src/utils/test.ts index a860bde07..02277af0e 100644 --- a/src/utils/test.ts +++ b/src/utils/test.ts @@ -25,6 +25,7 @@ import { import { CallMembership, type LivekitFocusSelection, + type LivekitTransport, type MatrixRTCSession, MatrixRTCSessionEvent, type MatrixRTCSessionEventHandlerMap, @@ -66,7 +67,6 @@ import { type MediaDevices } from "../state/MediaDevices"; import { type Behavior, constant } from "../state/Behavior"; import { ObservableScope } from "../state/ObservableScope"; import { MuteStates } from "../state/MuteStates"; -import { type LivekitTransportWithVersion } from "../state/CallViewModel/remoteMembers/ConnectionManager"; export function withFakeTimers(continuation: () => void): void { vi.useFakeTimers(); @@ -197,11 +197,10 @@ export function mockEmitter(): EmitterMock { }; } -export const exampleTransport: LivekitTransportWithVersion = { +export const exampleTransport: LivekitTransport = { type: "livekit", livekit_service_url: "https://lk.example.org", livekit_alias: "!alias:example.org", - useMatrix2: false, }; export function mockCallMembership( diff --git a/yarn.lock b/yarn.lock index 0ddaad61a..835555278 100644 --- a/yarn.lock +++ b/yarn.lock @@ -7533,7 +7533,7 @@ __metadata: livekit-client: "npm:^2.13.0" lodash-es: "npm:^4.17.21" loglevel: "npm:^1.9.1" - matrix-js-sdk: "github:matrix-org/matrix-js-sdk#head=toger5/use-membershipID-for-session-state-events&commit=8cea2c05839ebcaa90945504a453b9b1e1092fc4" + matrix-js-sdk: "github:matrix-org/matrix-js-sdk#head=toger5/use-membershipID-for-session-state-events&commit=6f0815930a008eff8f86e6e5748d447be0e7c25e" matrix-widget-api: "npm:^1.14.0" normalize.css: "npm:^8.0.1" observable-hooks: "npm:^4.2.3" @@ -10338,9 +10338,9 @@ __metadata: languageName: node linkType: hard -"matrix-js-sdk@github:matrix-org/matrix-js-sdk#head=toger5/use-membershipID-for-session-state-events&commit=8cea2c05839ebcaa90945504a453b9b1e1092fc4": +"matrix-js-sdk@github:matrix-org/matrix-js-sdk#head=toger5/use-membershipID-for-session-state-events&commit=6f0815930a008eff8f86e6e5748d447be0e7c25e": version: 39.4.0 - resolution: "matrix-js-sdk@https://github.com/matrix-org/matrix-js-sdk.git#commit=8cea2c05839ebcaa90945504a453b9b1e1092fc4" + resolution: "matrix-js-sdk@https://github.com/matrix-org/matrix-js-sdk.git#commit=6f0815930a008eff8f86e6e5748d447be0e7c25e" dependencies: "@babel/runtime": "npm:^7.12.5" "@matrix-org/matrix-sdk-crypto-wasm": "npm:^16.0.0" @@ -10356,7 +10356,7 @@ __metadata: sdp-transform: "npm:^3.0.0" unhomoglyph: "npm:^1.0.6" uuid: "npm:13" - checksum: 10c0/2375dd3d9191f78fe589b0d3170f3da7792ed469a81d3ba3cd12f4915fd33a859f8af3491edb9cf0cdaa1f881a3ea7c1bf7539e850ad0360ec9981271f462c81 + checksum: 10c0/a5a904a79f3660d1f6fe217195e662adf82af4a445681e47f292772d9d4d63ce60aaca209f40c41e2d659bee2b17cd5b3345bbad77795032057f2c0e3129cc77 languageName: node linkType: hard From 72ec1439f41770dc89815c728081de2926c69287 Mon Sep 17 00:00:00 2001 From: Will Hunt <2072976+Half-Shot@users.noreply.github.com> Date: Mon, 29 Dec 2025 17:45:41 +0000 Subject: [PATCH 124/748] Support MSC4143 RTC Transport endpoint (#3629) * Use rtc-focus branch of js-sdk * Update makeTransport to fetch backend transports and validate all transports before response. * Fix test * Add test * Loads more tests * Add tests for openid errors * improve comment * update to develop commit * Add JWT parsing * Use JWT * Cleanup * fixup tests * fixup tests * lint * lint lint * Fix `Reconnecting` --- package.json | 2 +- playwright/errors.spec.ts | 4 +- playwright/fixtures/jwt-token.ts | 22 ++ playwright/sfu-reconnect-bug.spec.ts | 6 - src/livekit/openIDSFU.test.ts | 112 +++++++++ src/livekit/openIDSFU.ts | 54 +++- src/state/CallViewModel/CallViewModel.test.ts | 4 +- .../localMember/LocalTransport.test.ts | 238 +++++++++++++----- .../localMember/LocalTransport.ts | 169 +++++++++---- .../remoteMembers/Connection.test.ts | 7 +- .../remoteMembers/integration.test.ts | 3 +- src/utils/test-fixtures.ts | 14 ++ yarn.lock | 18 +- 13 files changed, 522 insertions(+), 131 deletions(-) create mode 100644 playwright/fixtures/jwt-token.ts create mode 100644 src/livekit/openIDSFU.test.ts diff --git a/package.json b/package.json index 53538928b..c67c2e4cc 100644 --- a/package.json +++ b/package.json @@ -111,7 +111,7 @@ "livekit-client": "^2.13.0", "lodash-es": "^4.17.21", "loglevel": "^1.9.1", - "matrix-js-sdk": "^39.2.0", + "matrix-js-sdk": "matrix-org/matrix-js-sdk#2218ec4e3102e841ba3e794e1c492c0a5aa6c1c3", "matrix-widget-api": "^1.14.0", "node-stdlib-browser": "^1.3.1", "normalize.css": "^8.0.1", diff --git a/playwright/errors.spec.ts b/playwright/errors.spec.ts index 0d36f7ab4..085fb0b4a 100644 --- a/playwright/errors.spec.ts +++ b/playwright/errors.spec.ts @@ -7,6 +7,8 @@ Please see LICENSE in the repository root for full details. import { expect, test } from "@playwright/test"; +import { createJTWToken } from "./fixtures/jwt-token"; + test("Should show error screen if fails to get JWT token", async ({ page }) => { await page.goto("/"); @@ -93,7 +95,7 @@ test("Should show error screen if call creation is restricted", async ({ contentType: "application/json", body: JSON.stringify({ url: "wss://badurltotricktest/livekit/sfu", - jwt: "FAKE", + jwt: createJTWToken("@fake:user", "!fake:room"), }), }), ); diff --git a/playwright/fixtures/jwt-token.ts b/playwright/fixtures/jwt-token.ts new file mode 100644 index 000000000..18119c7e0 --- /dev/null +++ b/playwright/fixtures/jwt-token.ts @@ -0,0 +1,22 @@ +/* +Copyright 2025 New Vector Ltd. + +SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial +Please see LICENSE in the repository root for full details. +*/ + +export function createJTWToken(sub: string, room: string): string { + return [ + {}, // header + { + // payload + sub, + video: { + room, + }, + }, + {}, // signature + ] + .map((d) => global.btoa(JSON.stringify(d))) + .join("."); +} diff --git a/playwright/sfu-reconnect-bug.spec.ts b/playwright/sfu-reconnect-bug.spec.ts index 6138eb784..9f666f0f5 100644 --- a/playwright/sfu-reconnect-bug.spec.ts +++ b/playwright/sfu-reconnect-bug.spec.ts @@ -68,11 +68,6 @@ test("When creator left, avoid reconnect to the same SFU", async ({ reducedMotion: "reduce", }); const guestCPage = await guestC.newPage(); - let sfuGetCallCount = 0; - await guestCPage.route("**/livekit/jwt/sfu/get", async (route) => { - sfuGetCallCount++; - await route.continue(); - }); // Track WebSocket connections let wsConnectionCount = 0; await guestCPage.routeWebSocket("**", (ws) => { @@ -100,5 +95,4 @@ test("When creator left, avoid reconnect to the same SFU", async ({ // https://github.com/element-hq/element-call/issues/3344 // The app used to request a new jwt token then to reconnect to the SFU expect(wsConnectionCount).toBe(1); - expect(sfuGetCallCount).toBe(2 /* the first one is for the warmup */); }); diff --git a/src/livekit/openIDSFU.test.ts b/src/livekit/openIDSFU.test.ts new file mode 100644 index 000000000..2a260b015 --- /dev/null +++ b/src/livekit/openIDSFU.test.ts @@ -0,0 +1,112 @@ +/* +Copyright 2025 Element Creations Ltd. + +SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial +Please see LICENSE in the repository root for full details. +*/ + +import { + beforeEach, + afterEach, + describe, + expect, + it, + type MockedObject, + vitest, +} from "vitest"; +import fetchMock from "fetch-mock"; + +import { getSFUConfigWithOpenID, type OpenIDClientParts } from "./openIDSFU"; +import { testJWTToken } from "../utils/test-fixtures"; + +const sfuUrl = "https://sfu.example.org"; + +describe("getSFUConfigWithOpenID", () => { + let matrixClient: MockedObject; + beforeEach(() => { + matrixClient = { + getOpenIdToken: vitest.fn(), + getDeviceId: vitest.fn(), + }; + }); + afterEach(() => { + vitest.clearAllMocks(); + fetchMock.reset(); + }); + it("should handle fetching a token", async () => { + fetchMock.post("https://sfu.example.org/sfu/get", () => { + return { + status: 200, + body: { url: sfuUrl, jwt: testJWTToken }, + }; + }); + const config = await getSFUConfigWithOpenID( + matrixClient, + "https://sfu.example.org", + "!example_room_id", + ); + expect(config).toEqual({ + jwt: testJWTToken, + url: sfuUrl, + livekitIdentity: "@me:example.org:ABCDEF", + livekitAlias: "!example_room_id", + }); + void (await fetchMock.flush()); + }); + it("should fail if the SFU errors", async () => { + fetchMock.post("https://sfu.example.org/sfu/get", () => { + return { + status: 500, + body: { error: "Test failure" }, + }; + }); + try { + await getSFUConfigWithOpenID( + matrixClient, + "https://sfu.example.org", + "!example_room_id", + ); + } catch (ex) { + expect(((ex as Error).cause as Error).message).toEqual( + "SFU Config fetch failed with status code 500", + ); + void (await fetchMock.flush()); + return; + } + expect.fail("Expected test to throw;"); + }); + + it("should retry fetching the openid token", async () => { + let count = 0; + matrixClient.getOpenIdToken.mockImplementation(async () => { + count++; + if (count < 2) { + throw Error("Test failure"); + } + return Promise.resolve({ + token_type: "Bearer", + access_token: "foobar", + matrix_server_name: "example.org", + expires_in: 30, + }); + }); + fetchMock.post("https://sfu.example.org/sfu/get", () => { + return { + status: 200, + body: { url: sfuUrl, jwt: testJWTToken }, + }; + }); + const config = await getSFUConfigWithOpenID( + matrixClient, + "https://sfu.example.org", + "!example_room_id", + ); + expect(config).toEqual({ + jwt: testJWTToken, + url: sfuUrl, + livekitIdentity: "@me:example.org:ABCDEF", + livekitAlias: "!example_room_id", + }); + void (await fetchMock.flush()); + }); +}); diff --git a/src/livekit/openIDSFU.ts b/src/livekit/openIDSFU.ts index 3ae003fb1..b3c07397f 100644 --- a/src/livekit/openIDSFU.ts +++ b/src/livekit/openIDSFU.ts @@ -11,9 +11,47 @@ import { logger } from "matrix-js-sdk/lib/logger"; import { FailToGetOpenIdToken } from "../utils/errors"; import { doNetworkOperationWithRetry } from "../utils/matrix"; +/** + * Configuration and access tokens provided by the SFU on successful authentication. + */ export interface SFUConfig { url: string; jwt: string; + livekitAlias: string; + livekitIdentity: string; +} + +/** + * Decoded details from the JWT. + */ +interface SFUJWTPayload { + /** + * Expiration time for the JWT. + * Note: This value is in seconds since Unix epoch. + */ + exp: number; + /** + * Name of the instance which authored the JWT + */ + iss: string; + /** + * Time at which the JWT can start to be used. + * Note: This value is in seconds since Unix epoch. + */ + nbf: number; + /** + * Subject. The Livekit alias in this context. + */ + sub: string; + /** + * The set of permissions for the user. + */ + video: { + canPublish: boolean; + canSubscribe: boolean; + room: string; + roomJoin: boolean; + }; } // The bits we need from MatrixClient @@ -57,7 +95,17 @@ export async function getSFUConfigWithOpenID( ); logger.info(`Got JWT from call's active focus URL.`); - return sfuConfig; + // Pull the details from the JWT + const [, payloadStr] = sfuConfig.jwt.split("."); + // TODO: Prefer Uint8Array.fromBase64 when widely available + const payload = JSON.parse(global.atob(payloadStr)) as SFUJWTPayload; + return { + jwt: sfuConfig.jwt, + url: sfuConfig.url, + livekitAlias: payload.video.room, + // NOTE: Currently unused. + livekitIdentity: payload.sub, + }; } async function getLiveKitJWT( @@ -65,7 +113,7 @@ async function getLiveKitJWT( livekitServiceURL: string, roomName: string, openIDToken: IOpenIDToken, -): Promise { +): Promise<{ url: string; jwt: string }> { try { const res = await fetch(livekitServiceURL + "/sfu/get", { method: "POST", @@ -83,6 +131,6 @@ async function getLiveKitJWT( } return await res.json(); } catch (e) { - throw new Error("SFU Config fetch failed with exception " + e); + throw new Error("SFU Config fetch failed with exception", { cause: e }); } } diff --git a/src/state/CallViewModel/CallViewModel.test.ts b/src/state/CallViewModel/CallViewModel.test.ts index 86cde12a0..3205c07f1 100644 --- a/src/state/CallViewModel/CallViewModel.test.ts +++ b/src/state/CallViewModel/CallViewModel.test.ts @@ -1256,7 +1256,9 @@ describe.each([ rtcSession.membershipStatus = Status.Connected; }, n: () => { - rtcSession.membershipStatus = Status.Reconnecting; + // NOTE: This was removed in https://github.com/matrix-org/matrix-js-sdk/pull/5103 accidentally. + // eslint-disable-next-line @typescript-eslint/no-explicit-any + rtcSession.membershipStatus = "Reconnecting" as any; }, }); schedule(probablyLeftMarbles, { diff --git a/src/state/CallViewModel/localMember/LocalTransport.test.ts b/src/state/CallViewModel/localMember/LocalTransport.test.ts index c1c36fa5a..3e69bf2c3 100644 --- a/src/state/CallViewModel/localMember/LocalTransport.test.ts +++ b/src/state/CallViewModel/localMember/LocalTransport.test.ts @@ -5,9 +5,18 @@ SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial Please see LICENSE in the repository root for full details. */ -import { afterEach, beforeEach, describe, expect, it, vi } from "vitest"; +import { + afterEach, + beforeEach, + describe, + expect, + it, + type MockedObject, + vi, +} from "vitest"; import { type CallMembership } from "matrix-js-sdk/lib/matrixrtc"; -import { BehaviorSubject } from "rxjs"; +import { BehaviorSubject, lastValueFrom } from "rxjs"; +import fetchMock from "fetch-mock"; import { mockConfig, flushPromises } from "../../../utils/test"; import { createLocalTransport$ } from "./LocalTransport"; @@ -18,31 +27,22 @@ import { FailToGetOpenIdToken, } from "../../../utils/errors"; import * as openIDSFU from "../../../livekit/openIDSFU"; +import { customLivekitUrl } from "../../../settings/settings"; +import { testJWTToken } from "../../../utils/test-fixtures"; describe("LocalTransport", () => { + const openIdResponse: openIDSFU.SFUConfig = { + url: "https://lk.example.org", + jwt: testJWTToken, + livekitAlias: "!example_room_id", + livekitIdentity: "@lk_user:ABCDEF", + }; + let scope: ObservableScope; - beforeEach(() => (scope = new ObservableScope())); - afterEach(() => scope.end()); - - it("throws if config is missing", async () => { - const localTransport$ = createLocalTransport$({ - scope, - roomId: "!room:example.org", - useOldestMember$: constant(false), - memberships$: constant(new Epoch([])), - client: { - getDomain: () => "", - // These won't be called in this error path but satisfy the type - getOpenIdToken: vi.fn(), - getDeviceId: vi.fn(), - }, - }); - await flushPromises(); - - expect(() => localTransport$.value).toThrow( - new MatrixRTCTransportMissingError(""), - ); + beforeEach(() => { + scope = new ObservableScope(); }); + afterEach(() => scope.end()); it("throws FailToGetOpenIdToken when OpenID fetch fails", async () => { // Provide a valid config so makeTransportInternal resolves a transport @@ -61,12 +61,14 @@ describe("LocalTransport", () => { const errors: Error[] = []; const localTransport$ = createLocalTransport$({ scope, - roomId: "!room:example.org", + roomId: "!example_room_id", useOldestMember$: constant(false), memberships$: constant(new Epoch([])), client: { // Use empty domain to skip .well-known and use config directly getDomain: () => "", + // eslint-disable-next-line @typescript-eslint/naming-convention + _unstable_getRTCTransports: async () => Promise.resolve([]), getOpenIdToken: vi.fn(), getDeviceId: vi.fn(), }, @@ -84,41 +86,6 @@ describe("LocalTransport", () => { expect(() => localTransport$.value).toThrow(expectedError); }); - it("emits preferred transport after OpenID resolves", async () => { - // Use config so transport discovery succeeds, but delay OpenID JWT fetch - mockConfig({ - livekit: { livekit_service_url: "https://lk.example.org" }, - }); - - const openIdResolver = Promise.withResolvers(); - - vi.spyOn(openIDSFU, "getSFUConfigWithOpenID").mockReturnValue( - openIdResolver.promise, - ); - - const localTransport$ = createLocalTransport$({ - scope, - roomId: "!room:example.org", - useOldestMember$: constant(false), - memberships$: constant(new Epoch([])), - client: { - getDomain: () => "", - getOpenIdToken: vi.fn(), - getDeviceId: vi.fn(), - }, - }); - - openIdResolver.resolve?.({ url: "https://lk.example.org", jwt: "jwt" }); - expect(localTransport$.value).toBe(null); - await flushPromises(); - // final - expect(localTransport$.value).toStrictEqual({ - livekit_alias: "!room:example.org", - livekit_service_url: "https://lk.example.org", - type: "livekit", - }); - }); - it("updates local transport when oldest member changes", async () => { // Use config so transport discovery succeeds, but delay OpenID JWT fetch mockConfig({ @@ -133,24 +100,171 @@ describe("LocalTransport", () => { const localTransport$ = createLocalTransport$({ scope, - roomId: "!room:example.org", + roomId: "!example_room_id", useOldestMember$: constant(true), memberships$, client: { getDomain: () => "", + // eslint-disable-next-line @typescript-eslint/naming-convention + _unstable_getRTCTransports: async () => Promise.resolve([]), getOpenIdToken: vi.fn(), getDeviceId: vi.fn(), }, }); - openIdResolver.resolve?.({ url: "https://lk.example.org", jwt: "jwt" }); + openIdResolver.resolve?.(openIdResponse); expect(localTransport$.value).toBe(null); await flushPromises(); // final expect(localTransport$.value).toStrictEqual({ - livekit_alias: "!room:example.org", + livekit_alias: "!example_room_id", livekit_service_url: "https://lk.example.org", type: "livekit", }); }); + + type LocalTransportProps = Parameters[0]; + + describe("transport configuration mechanisms", () => { + let localTransportOpts: LocalTransportProps & { + client: MockedObject; + }; + let openIdResolver: PromiseWithResolvers; + beforeEach(() => { + mockConfig({}); + customLivekitUrl.setValue(customLivekitUrl.defaultValue); + localTransportOpts = { + scope, + roomId: "!example_room_id", + useOldestMember$: constant(false), + memberships$: constant(new Epoch([])), + client: { + getDomain: vi.fn().mockReturnValue(""), + // eslint-disable-next-line @typescript-eslint/naming-convention + _unstable_getRTCTransports: vi.fn().mockResolvedValue([]), + getOpenIdToken: vi.fn(), + getDeviceId: vi.fn(), + }, + }; + openIdResolver = Promise.withResolvers(); + vi.spyOn(openIDSFU, "getSFUConfigWithOpenID").mockReturnValue( + openIdResolver.promise, + ); + }); + + afterEach(() => { + fetchMock.reset(); + }); + + it("supports getting transport via application config", async () => { + mockConfig({ + livekit: { livekit_service_url: "https://lk.example.org" }, + }); + const localTransport$ = createLocalTransport$(localTransportOpts); + openIdResolver.resolve?.(openIdResponse); + expect(localTransport$.value).toBe(null); + await flushPromises(); + expect(localTransport$.value).toStrictEqual({ + livekit_alias: "!example_room_id", + livekit_service_url: "https://lk.example.org", + type: "livekit", + }); + }); + it("supports getting transport via user settings", async () => { + customLivekitUrl.setValue("https://lk.example.org"); + const localTransport$ = createLocalTransport$(localTransportOpts); + openIdResolver.resolve?.(openIdResponse); + expect(localTransport$.value).toBe(null); + await flushPromises(); + expect(localTransport$.value).toStrictEqual({ + livekit_alias: "!example_room_id", + livekit_service_url: "https://lk.example.org", + type: "livekit", + }); + }); + it("supports getting transport via backend", async () => { + localTransportOpts.client._unstable_getRTCTransports.mockResolvedValue([ + { type: "livekit", livekit_service_url: "https://lk.example.org" }, + ]); + const localTransport$ = createLocalTransport$(localTransportOpts); + openIdResolver.resolve?.(openIdResponse); + expect(localTransport$.value).toBe(null); + await flushPromises(); + expect(localTransport$.value).toStrictEqual({ + livekit_alias: "!example_room_id", + livekit_service_url: "https://lk.example.org", + type: "livekit", + }); + }); + it("fails fast if the openID request fails for backend config", async () => { + localTransportOpts.client._unstable_getRTCTransports.mockResolvedValue([ + { type: "livekit", livekit_service_url: "https://lk.example.org" }, + ]); + openIdResolver.reject( + new FailToGetOpenIdToken(new Error("Test driven error")), + ); + try { + await lastValueFrom(createLocalTransport$(localTransportOpts)); + throw Error("Expected test to throw"); + } catch (ex) { + expect(ex).toBeInstanceOf(FailToGetOpenIdToken); + } + }); + it("supports getting transport via well-known", async () => { + localTransportOpts.client.getDomain.mockReturnValue("example.org"); + fetchMock.getOnce("https://example.org/.well-known/matrix/client", { + "org.matrix.msc4143.rtc_foci": [ + { type: "livekit", livekit_service_url: "https://lk.example.org" }, + ], + }); + const localTransport$ = createLocalTransport$(localTransportOpts); + openIdResolver.resolve?.(openIdResponse); + expect(localTransport$.value).toBe(null); + await flushPromises(); + expect(localTransport$.value).toStrictEqual({ + livekit_alias: "!example_room_id", + livekit_service_url: "https://lk.example.org", + type: "livekit", + }); + expect(fetchMock.done()).toEqual(true); + }); + it("fails fast if the openId request fails for the well-known config", async () => { + localTransportOpts.client.getDomain.mockReturnValue("example.org"); + fetchMock.getOnce("https://example.org/.well-known/matrix/client", { + "org.matrix.msc4143.rtc_foci": [ + { type: "livekit", livekit_service_url: "https://lk.example.org" }, + ], + }); + openIdResolver.reject( + new FailToGetOpenIdToken(new Error("Test driven error")), + ); + try { + await lastValueFrom(createLocalTransport$(localTransportOpts)); + throw Error("Expected test to throw"); + } catch (ex) { + expect(ex).toBeInstanceOf(FailToGetOpenIdToken); + } + }); + it("throws if no options are available", async () => { + const localTransport$ = createLocalTransport$({ + scope, + roomId: "!example_room_id", + useOldestMember$: constant(false), + memberships$: constant(new Epoch([])), + client: { + getDomain: () => "", + // eslint-disable-next-line @typescript-eslint/naming-convention + _unstable_getRTCTransports: async () => Promise.resolve([]), + // These won't be called in this error path but satisfy the type + getOpenIdToken: vi.fn(), + getDeviceId: vi.fn(), + }, + }); + await flushPromises(); + + expect(() => localTransport$.value).toThrow( + new MatrixRTCTransportMissingError(""), + ); + }); + }); }); diff --git a/src/state/CallViewModel/localMember/LocalTransport.ts b/src/state/CallViewModel/localMember/LocalTransport.ts index 1320b8c46..e72b076f5 100644 --- a/src/state/CallViewModel/localMember/LocalTransport.ts +++ b/src/state/CallViewModel/localMember/LocalTransport.ts @@ -8,11 +8,11 @@ Please see LICENSE in the repository root for full details. import { type CallMembership, isLivekitTransport, - type LivekitTransportConfig, type LivekitTransport, isLivekitTransportConfig, + type Transport, } from "matrix-js-sdk/lib/matrixrtc"; -import { type MatrixClient } from "matrix-js-sdk"; +import { MatrixError, type MatrixClient } from "matrix-js-sdk"; import { combineLatest, distinctUntilChanged, @@ -27,7 +27,10 @@ import { AutoDiscovery } from "matrix-js-sdk/lib/autodiscovery"; import { type Behavior } from "../../Behavior.ts"; import { type Epoch, type ObservableScope } from "../../ObservableScope.ts"; import { Config } from "../../../config/Config.ts"; -import { MatrixRTCTransportMissingError } from "../../../utils/errors.ts"; +import { + FailToGetOpenIdToken, + MatrixRTCTransportMissingError, +} from "../../../utils/errors.ts"; import { getSFUConfigWithOpenID, type OpenIDClientParts, @@ -45,7 +48,8 @@ const logger = rootLogger.getChild("[LocalTransport]"); interface Props { scope: ObservableScope; memberships$: Behavior>; - client: Pick & OpenIDClientParts; + client: Pick & + OpenIDClientParts; roomId: string; useOldestMember$: Behavior; } @@ -116,73 +120,150 @@ export const createLocalTransport$ = ({ const FOCI_WK_KEY = "org.matrix.msc4143.rtc_foci"; /** + * Determine the correct Transport for the current session, including + * validating auth against the service to ensure it's correct. + * Prefers in order: * - * @param client - * @param roomId - * @returns + * 1. The `urlFromDevSettings` value. If this cannot be validated, the function will throw. + * 2. The transports returned via the homeserver. + * 3. The transports returned via .well-known. + * 4. The transport configured in Element Call's config. + * + * @param client The authenticated Matrix client for the current user + * @param roomId The ID of the room to be connected to. + * @param urlFromDevSettings Override URL provided by the user's local config. + * @returns A fully validated transport config. * @throws MatrixRTCTransportMissingError | FailToGetOpenIdToken */ async function makeTransport( - client: Pick & OpenIDClientParts, + client: Pick & + OpenIDClientParts, roomId: string, urlFromDevSettings: string | null, ): Promise { - let transport: LivekitTransport | undefined; logger.trace("Searching for a preferred transport"); - //TODO refactor this to use the jwt service returned alias. - const livekitAlias = roomId; + + // We will call `getSFUConfigWithOpenID` once per transport here as it's our + // only mechanism of valiation. This means we will also ask the + // homeserver for a OpenID token a few times. Since OpenID tokens are single + // use we don't want to risk any issues by re-using a token. + // + // If the OpenID request were to fail then it's acceptable for us to fail + // this function early, as we assume the homeserver has got some problems. // DEVTOOL: Highest priority: Load from devtool setting if (urlFromDevSettings !== null) { - const transportFromStorage: LivekitTransport = { + logger.info("Using LiveKit transport from dev tools: ", urlFromDevSettings); + // Validate that the SFU is up. Otherwise, we want to fail on this + // as we don't permit other SFUs. + const config = await getSFUConfigWithOpenID( + client, + urlFromDevSettings, + roomId, + ); + return { type: "livekit", livekit_service_url: urlFromDevSettings, - livekit_alias: livekitAlias, + livekit_alias: config.livekitAlias, }; - logger.info( - "Using LiveKit transport from dev tools: ", - transportFromStorage, - ); - transport = transportFromStorage; } - // WELL_KNOWN: Prioritize the .well-known/matrix/client, if available, over the configured SFU + async function getFirstUsableTransport( + transports: Transport[], + ): Promise { + for (const potentialTransport of transports) { + if (isLivekitTransportConfig(potentialTransport)) { + try { + const { livekitAlias } = await getSFUConfigWithOpenID( + client, + potentialTransport.livekit_service_url, + roomId, + ); + return { + ...potentialTransport, + livekit_alias: livekitAlias, + }; + } catch (ex) { + if (ex instanceof FailToGetOpenIdToken) { + // Explictly throw these + throw ex; + } + logger.debug( + `Could not use SFU service "${potentialTransport.livekit_service_url}" as SFU`, + ex, + ); + } + } + } + return null; + } + + // MSC4143: Attempt to fetch transports from backend. + if ("_unstable_getRTCTransports" in client) { + try { + const selectedTransport = await getFirstUsableTransport( + await client._unstable_getRTCTransports(), + ); + if (selectedTransport) { + logger.info("Using backend-configured SFU", selectedTransport); + return selectedTransport; + } + } catch (ex) { + if (ex instanceof MatrixError && ex.httpStatus === 404) { + // Expected, this is an unstable endpoint and it's not required. + logger.debug("Backend does not provide any RTC transports", ex); + } else if (ex instanceof FailToGetOpenIdToken) { + throw ex; + } else { + // We got an error that wasn't just missing support for the feature, so log it loudly. + logger.error( + "Unexpected error fetching RTC transports from backend", + ex, + ); + } + } + } + + // Legacy MSC4143 (to be removed) WELL_KNOWN: Prioritize the .well-known/matrix/client, if available. const domain = client.getDomain(); - if (domain && transport === undefined) { + if (domain) { // we use AutoDiscovery instead of relying on the MatrixClient having already // been fully configured and started const wellKnownFoci = (await AutoDiscovery.getRawClientConfig(domain))?.[ FOCI_WK_KEY ]; - if (Array.isArray(wellKnownFoci)) { - const wellKnownTransport: LivekitTransportConfig | undefined = - wellKnownFoci.find((f) => f && isLivekitTransportConfig(f)); - if (wellKnownTransport !== undefined) { - logger.info("Using LiveKit transport from .well-known: ", transport); - transport = { ...wellKnownTransport, livekit_alias: livekitAlias }; - } + const selectedTransport = Array.isArray(wellKnownFoci) + ? await getFirstUsableTransport(wellKnownFoci) + : null; + if (selectedTransport) { + logger.info("Using .well-known SFU", selectedTransport); + return selectedTransport; } } // CONFIG: Least prioritized; Load from config file const urlFromConf = Config.get().livekit?.livekit_service_url; - if (urlFromConf && transport === undefined) { - const transportFromConf: LivekitTransport = { - type: "livekit", - livekit_service_url: urlFromConf, - livekit_alias: livekitAlias, - }; - logger.info("Using LiveKit transport from config: ", transportFromConf); - transport = transportFromConf; + if (urlFromConf) { + try { + const { livekitAlias } = await getSFUConfigWithOpenID( + client, + urlFromConf, + roomId, + ); + const selectedTransport: LivekitTransport = { + type: "livekit", + livekit_service_url: urlFromConf, + livekit_alias: livekitAlias, + }; + logger.info("Using config SFU", selectedTransport); + return selectedTransport; + } catch (ex) { + if (ex instanceof FailToGetOpenIdToken) { + throw ex; + } + logger.error("Failed to validate config SFU", ex); + } } - if (!transport) throw new MatrixRTCTransportMissingError(domain ?? ""); // this will call the jwt/sfu/get endpoint to pre create the livekit room. - - await getSFUConfigWithOpenID( - client, - transport.livekit_service_url, - transport.livekit_alias, - ); - - return transport; + throw new MatrixRTCTransportMissingError(domain ?? ""); } diff --git a/src/state/CallViewModel/remoteMembers/Connection.test.ts b/src/state/CallViewModel/remoteMembers/Connection.test.ts index bcc0bac2e..c1e24eb4d 100644 --- a/src/state/CallViewModel/remoteMembers/Connection.test.ts +++ b/src/state/CallViewModel/remoteMembers/Connection.test.ts @@ -39,6 +39,7 @@ import { ElementCallError, FailToGetOpenIdToken, } from "../../../utils/errors.ts"; +import { testJWTToken } from "../../../utils/test-fixtures.ts"; import { mockRemoteParticipant } from "../../../utils/test.ts"; let testScope: ObservableScope; @@ -121,7 +122,7 @@ function setupRemoteConnection(): Connection { status: 200, body: { url: "wss://matrix-rtc.m.localhost/livekit/sfu", - jwt: "ATOKEN", + jwt: testJWTToken, }, }; }); @@ -258,7 +259,7 @@ describe("Start connection states", () => { capturedState.cause instanceof Error ) { expect(capturedState.cause.message).toContain( - "SFU Config fetch failed with exception Error", + "SFU Config fetch failed with exception", ); expect(connection.transport.livekit_alias).toEqual( livekitFocus.livekit_alias, @@ -294,7 +295,7 @@ describe("Start connection states", () => { status: 200, body: { url: "wss://matrix-rtc.m.localhost/livekit/sfu", - jwt: "ATOKEN", + jwt: testJWTToken, }, }; }); diff --git a/src/state/CallViewModel/remoteMembers/integration.test.ts b/src/state/CallViewModel/remoteMembers/integration.test.ts index 6108c7bca..d885ddc6e 100644 --- a/src/state/CallViewModel/remoteMembers/integration.test.ts +++ b/src/state/CallViewModel/remoteMembers/integration.test.ts @@ -33,6 +33,7 @@ import { } from "./MatrixLivekitMembers.ts"; import { createConnectionManager$ } from "./ConnectionManager.ts"; import { membershipsAndTransports$ } from "../../SessionBehaviors.ts"; +import { testJWTToken } from "../../../utils/test-fixtures.ts"; // Test the integration of ConnectionManager and MatrixLivekitMerger @@ -85,7 +86,7 @@ beforeEach(() => { status: 200, body: { url: `wss://${domain}/livekit/sfu`, - jwt: "ATOKEN", + jwt: testJWTToken, }, }; }); diff --git a/src/utils/test-fixtures.ts b/src/utils/test-fixtures.ts index 4cf330b71..f915bb19a 100644 --- a/src/utils/test-fixtures.ts +++ b/src/utils/test-fixtures.ts @@ -59,3 +59,17 @@ export const daveRTLRtcMember = mockRtcMembership("@dave2:example.org", "DDDD"); export const daveRTL = mockMatrixRoomMember(daveRTLRtcMember, { rawDisplayName: "\u202eevaD", }); + +export const testJWTToken = [ + {}, // header + { + // payload + sub: "@me:example.org:ABCDEF", + video: { + room: "!example_room_id", + }, + }, + {}, // signature +] + .map((d) => global.btoa(JSON.stringify(d))) + .join("."); diff --git a/yarn.lock b/yarn.lock index d9202de22..abb3ef95b 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2802,10 +2802,10 @@ __metadata: languageName: node linkType: hard -"@matrix-org/matrix-sdk-crypto-wasm@npm:^15.3.0": - version: 15.3.0 - resolution: "@matrix-org/matrix-sdk-crypto-wasm@npm:15.3.0" - checksum: 10c0/45628f36b7b0e54a8777ae67a7233dbdf3e3cf14e0d95d21f62f89a7ea7e3f907232f1eb7b1262193b1e227759fad47af829dcccc103ded89011f13c66f01d76 +"@matrix-org/matrix-sdk-crypto-wasm@npm:^16.0.0": + version: 16.0.0 + resolution: "@matrix-org/matrix-sdk-crypto-wasm@npm:16.0.0" + checksum: 10c0/13b4ede3e618da819957abff778afefcf3baf9a2faac04a36bb5a07a44fae2ea05fbfa072eb3408d48b2b7b9aaf27242ce52c594c8ce9bf1fb8b3aade2832be1 languageName: node linkType: hard @@ -7841,7 +7841,7 @@ __metadata: livekit-client: "npm:^2.13.0" lodash-es: "npm:^4.17.21" loglevel: "npm:^1.9.1" - matrix-js-sdk: "npm:^39.2.0" + matrix-js-sdk: "matrix-org/matrix-js-sdk#2218ec4e3102e841ba3e794e1c492c0a5aa6c1c3" matrix-widget-api: "npm:^1.14.0" node-stdlib-browser: "npm:^1.3.1" normalize.css: "npm:^8.0.1" @@ -10780,12 +10780,12 @@ __metadata: languageName: node linkType: hard -"matrix-js-sdk@npm:^39.2.0": +"matrix-js-sdk@matrix-org/matrix-js-sdk#2218ec4e3102e841ba3e794e1c492c0a5aa6c1c3": version: 39.3.0 - resolution: "matrix-js-sdk@npm:39.3.0" + resolution: "matrix-js-sdk@https://github.com/matrix-org/matrix-js-sdk.git#commit=2218ec4e3102e841ba3e794e1c492c0a5aa6c1c3" dependencies: "@babel/runtime": "npm:^7.12.5" - "@matrix-org/matrix-sdk-crypto-wasm": "npm:^15.3.0" + "@matrix-org/matrix-sdk-crypto-wasm": "npm:^16.0.0" another-json: "npm:^0.2.0" bs58: "npm:^6.0.0" content-type: "npm:^1.0.4" @@ -10798,7 +10798,7 @@ __metadata: sdp-transform: "npm:^3.0.0" unhomoglyph: "npm:^1.0.6" uuid: "npm:13" - checksum: 10c0/031c9ec042e00c32dc531f82fc59c64cc25fb665abfc642b1f0765c530d60684f8bd63daf0cdd0dbe96b4f87ea3f4148f9d3f024a59d57eceaec1ce5d0164755 + checksum: 10c0/feca51c7ada5a56aa6cfb74f29bd1640a20804e9de689d23f10c5227e07ba4f66ebbb9606e1384390dca277a6942886706198394717694a9cfb1f20cd36ca377 languageName: node linkType: hard From da55d84bdecb99e435fd685cbe8cb0e00905675c Mon Sep 17 00:00:00 2001 From: Valere Date: Tue, 30 Dec 2025 17:02:44 +0100 Subject: [PATCH 125/748] Add script to check that the tsdoc is correct and up-to-date --- .eslintrc.cjs | 20 +- package.json | 4 +- playwright/fixtures/widget-user.ts | 1 - src/e2ee/sharedKeyManagement.ts | 4 +- src/livekit/MatrixAudioRenderer.tsx | 6 +- src/livekit/openIDSFU.ts | 6 +- src/reactions/ReactionsReader.ts | 6 +- src/room/useLoadGroupCall.ts | 16 +- src/settings/rageshake.ts | 26 ++- .../CallNotificationLifecycle.ts | 2 +- .../CallViewModel/localMember/LocalMember.ts | 19 +- .../CallViewModel/localMember/Publisher.ts | 5 +- .../CallViewModel/remoteMembers/Connection.ts | 2 +- .../remoteMembers/ConnectionFactory.ts | 4 +- .../remoteMembers/ConnectionManager.ts | 8 +- src/useAudioContext.tsx | 11 +- src/utils/displayname.ts | 7 + src/utils/errors.ts | 55 ++++++ src/utils/matrix.ts | 7 +- src/utils/media.ts | 1 + src/utils/observable.ts | 1 - yarn.lock | 180 +++++++++++++++++- 22 files changed, 333 insertions(+), 58 deletions(-) diff --git a/.eslintrc.cjs b/.eslintrc.cjs index 067c52466..2cd63d63e 100644 --- a/.eslintrc.cjs +++ b/.eslintrc.cjs @@ -8,7 +8,7 @@ Please see LICENSE in the repository root for full details. `; module.exports = { - plugins: ["matrix-org", "rxjs"], + plugins: ["matrix-org", "rxjs", "jsdoc"], extends: [ "plugin:matrix-org/react", "plugin:matrix-org/a11y", @@ -26,6 +26,13 @@ module.exports = { node: true, }, rules: { + "jsdoc/no-types": "error", + "jsdoc/empty-tags": "error", + "jsdoc/check-property-names": "error", + "jsdoc/check-values": "error", + "jsdoc/check-param-names": "warn", + // "jsdoc/require-param": "warn", + "jsdoc/require-param-description": "warn", "matrix-org/require-copyright-header": ["error", COPYRIGHT_HEADER], "jsx-a11y/media-has-caption": "off", "react/display-name": "error", @@ -75,6 +82,17 @@ module.exports = { "no-console": ["error"], }, }, + { + files: ["**/*.test.ts", "**/*.test.tsx", "**/test.ts", "**/test.tsx", "**/test-**"], + rules: { + "jsdoc/no-types": "off", + "jsdoc/empty-tags": "off", + "jsdoc/check-property-names": "off", + "jsdoc/check-values": "off", + "jsdoc/check-param-names": "off", + "jsdoc/require-param-description": "off", + } + } ], settings: { react: { diff --git a/package.json b/package.json index c67c2e4cc..e5b574443 100644 --- a/package.json +++ b/package.json @@ -18,11 +18,12 @@ "serve": "vite preview", "prettier:check": "prettier -c .", "prettier:format": "prettier -w .", - "lint": "yarn lint:types && yarn lint:eslint && yarn lint:knip", + "lint": "yarn lint:types && yarn lint:eslint && yarn lint:knip && yarn lint:tsdoc", "lint:eslint": "eslint --max-warnings 0 src playwright", "lint:eslint-fix": "eslint --max-warnings 0 src playwright --fix", "lint:knip": "knip", "lint:types": "tsc", + "lint:tsdoc": "eslint --ext .ts,.tsx src", "i18n": "i18next", "i18n:check": "i18next --fail-on-warnings --fail-on-update", "test": "vitest", @@ -95,6 +96,7 @@ "eslint-config-prettier": "^10.0.0", "eslint-plugin-deprecate": "^0.8.2", "eslint-plugin-import": "^2.26.0", + "eslint-plugin-jsdoc": "^61.5.0", "eslint-plugin-jsx-a11y": "^6.5.1", "eslint-plugin-matrix-org": "2.1.0", "eslint-plugin-react": "^7.29.4", diff --git a/playwright/fixtures/widget-user.ts b/playwright/fixtures/widget-user.ts index 6236928c3..f1f738b73 100644 --- a/playwright/fixtures/widget-user.ts +++ b/playwright/fixtures/widget-user.ts @@ -67,7 +67,6 @@ const CONFIG_JSON = { /** * Set the Element Call URL in the dev tool settings using `window.mxSettingsStore` via `page.evaluate`. - * @param page */ const setDevToolElementCallDevUrl = process.env.USE_DOCKER ? async (page: Page): Promise => { diff --git a/src/e2ee/sharedKeyManagement.ts b/src/e2ee/sharedKeyManagement.ts index c68ba4534..18d007e2b 100644 --- a/src/e2ee/sharedKeyManagement.ts +++ b/src/e2ee/sharedKeyManagement.ts @@ -34,8 +34,8 @@ const getRoomSharedKeyLocalStorageKey = (roomId: string): string => `room-shared-key-${roomId}`; /** - * An upto-date shared key for the room. Either from local storage or the value from `setInitialValue`. - * @param roomId + * An up-to-date shared key for the room. Either from local storage or the value from `setInitialValue`. + * @param roomId The room ID we want the shared key for. * @param setInitialValue The value we get from the URL. The hook will overwrite the local storage value with this. * @returns [roomSharedKey, setRoomSharedKey] like a react useState hook. */ diff --git a/src/livekit/MatrixAudioRenderer.tsx b/src/livekit/MatrixAudioRenderer.tsx index 5b1149e99..741529b84 100644 --- a/src/livekit/MatrixAudioRenderer.tsx +++ b/src/livekit/MatrixAudioRenderer.tsx @@ -166,7 +166,11 @@ interface StereoPanAudioTrackProps { * It main purpose is to remount the AudioTrack component when switching from * audioContext to normal audio playback. * As of now the AudioTrack component does not support adding audio nodes while being mounted. - * @param param0 + * @param props The component props + * @param props.trackRef The track reference + * @param props.muted If the track should be muted + * @param props.audioContext The audio context to use + * @param props.audioNodes The audio nodes to use * @returns */ function AudioTrackWithAudioNodes({ diff --git a/src/livekit/openIDSFU.ts b/src/livekit/openIDSFU.ts index b3c07397f..34c98a88d 100644 --- a/src/livekit/openIDSFU.ts +++ b/src/livekit/openIDSFU.ts @@ -63,9 +63,9 @@ export type OpenIDClientParts = Pick< * Gets a bearer token from the homeserver and then use it to authenticate * to the matrix RTC backend in order to get acces to the SFU. * It has built-in retry for calls to the homeserver with a backoff policy. - * @param client - * @param serviceUrl - * @param matrixRoomId + * @param client The Matrix client + * @param serviceUrl The URL of the livekit SFU service + * @param matrixRoomId The Matrix room ID for which to get the SFU config * @returns Object containing the token information * @throws FailToGetOpenIdToken */ diff --git a/src/reactions/ReactionsReader.ts b/src/reactions/ReactionsReader.ts index 74b47c77f..7ce59812a 100644 --- a/src/reactions/ReactionsReader.ts +++ b/src/reactions/ReactionsReader.ts @@ -135,10 +135,10 @@ export class ReactionsReader { } /** - * Fetchest any hand wave reactions by the given sender on the given + * Fetches any hand wave reactions by the given sender on the given * membership event. - * @param membershipEventId - * @param expectedSender + * @param membershipEventId - The user membership event id. + * @param expectedSender - The expected sender of the reaction. * @returns A MatrixEvent if one was found. */ private getLastReactionEvent( diff --git a/src/room/useLoadGroupCall.ts b/src/room/useLoadGroupCall.ts index ab6ccf648..2cd0d40b0 100644 --- a/src/room/useLoadGroupCall.ts +++ b/src/room/useLoadGroupCall.ts @@ -106,22 +106,18 @@ async function joinRoomAfterInvite( export class CallTerminatedMessage extends Error { /** + * Creates a new CallTerminatedMessage. + * + * @param icon The icon to display with the message * @param messageTitle The title of the call ended screen message (translated) + * @param messageBody The message explaining the kind of termination + * (kick, ban, knock reject, etc.) (translated) + * @param reason The user-provided reason for the termination (kick/ban) */ public constructor( - /** - * The icon to display with the message. - */ public readonly icon: ComponentType>, messageTitle: string, - /** - * The message explaining the kind of termination (kick, ban, knock reject, - * etc.) (translated) - */ public readonly messageBody: string, - /** - * The user-provided reason for the termination (kick/ban) - */ public readonly reason?: string, ) { super(messageTitle); diff --git a/src/settings/rageshake.ts b/src/settings/rageshake.ts index 6c1a0f619..26d0839b0 100644 --- a/src/settings/rageshake.ts +++ b/src/settings/rageshake.ts @@ -99,7 +99,7 @@ class ConsoleLogger extends EventEmitter { /** * Returns the log lines to flush to disk and empties the internal log buffer - * @return {string} \n delimited log lines + * @return \n delimited log lines */ public popLogs(): string { const logsToFlush = this.logs; @@ -109,7 +109,7 @@ class ConsoleLogger extends EventEmitter { /** * Returns lines currently in the log buffer without removing them - * @return {string} \n delimited log lines + * @return \n delimited log lines */ public peekLogs(): string { return this.logs; @@ -139,7 +139,7 @@ class IndexedDBLogStore { } /** - * @return {Promise} Resolves when the store is ready. + * @return Resolves when the store is ready. */ public async connect(): Promise { const req = this.indexedDB.open("logs"); @@ -219,7 +219,7 @@ class IndexedDBLogStore { * This guarantees that we will always eventually do a flush when flush() is * called. * - * @return {Promise} Resolved when the logs have been flushed. + * @return Resolved when the logs have been flushed. */ public flush = async (): Promise => { // check if a flush() operation is ongoing @@ -270,7 +270,7 @@ class IndexedDBLogStore { * returned are deleted at the same time, so this can be called at startup * to do house-keeping to keep the logs from growing too large. * - * @return {Promise} Resolves to an array of objects. The array is + * @return Resolves to an array of objects. The array is * sorted in time (oldest first) based on when the log file was created (the * log ID). The objects have said log ID in an "id" field and "lines" which * is a big string with all the new-line delimited logs. @@ -421,12 +421,12 @@ class IndexedDBLogStore { /** * Helper method to collect results from a Cursor and promiseify it. - * @param {ObjectStore|Index} store The store to perform openCursor on. - * @param {IDBKeyRange=} keyRange Optional key range to apply on the cursor. - * @param {Function} resultMapper A function which is repeatedly called with a + * @param store - The store to perform openCursor on. + * @param keyRange - Optional key range to apply on the cursor. + * @param resultMapper - A function which is repeatedly called with a * Cursor. * Return the data you want to keep. - * @return {Promise} Resolves to an array of whatever you returned from + * @return Resolves to an array of whatever you returned from * resultMapper. */ async function selectQuery( @@ -464,9 +464,7 @@ declare global { /** * Configure rage shaking support for sending bug reports. * Modifies globals. - * @param {boolean} setUpPersistence When true (default), the persistence will - * be set up immediately for the logs. - * @return {Promise} Resolves when set up. + * @return Resolves when set up. */ export async function init(): Promise { global.mx_rage_logger = new ConsoleLogger(); @@ -503,7 +501,7 @@ export async function init(): Promise { /** * Try to start up the rageshake storage for logs. If not possible (client unsupported) * then this no-ops. - * @return {Promise} Resolves when complete. + * @return Resolves when complete. */ async function tryInitStorage(): Promise { if (global.mx_rage_initStoragePromise) { @@ -536,7 +534,7 @@ async function tryInitStorage(): Promise { /** * Get a recent snapshot of the logs, ready for attaching to a bug report * - * @return {LogEntry[]} list of log data + * @return list of log data */ export async function getLogsForReport(): Promise { if (!global.mx_rage_logger) { diff --git a/src/state/CallViewModel/CallNotificationLifecycle.ts b/src/state/CallViewModel/CallNotificationLifecycle.ts index 2a0bf2f19..d90f35ba4 100644 --- a/src/state/CallViewModel/CallNotificationLifecycle.ts +++ b/src/state/CallViewModel/CallNotificationLifecycle.ts @@ -81,7 +81,7 @@ export interface Props { localUser: { deviceId: string; userId: string }; } /** - * @returns {callPickupState$, autoLeave$} + * @returns two observables: * `callPickupState$` The current call pickup state of the call. * - "unknown": The client has not yet sent the notification event. We don't know if it will because it first needs to send its own membership. * Then we can conclude if we were the first one to join or not. diff --git a/src/state/CallViewModel/localMember/LocalMember.ts b/src/state/CallViewModel/localMember/LocalMember.ts index 6d28bc56a..dc22db23c 100644 --- a/src/state/CallViewModel/localMember/LocalMember.ts +++ b/src/state/CallViewModel/localMember/LocalMember.ts @@ -138,7 +138,16 @@ interface Props { * We want * - a publisher * - - * @param param0 + * @param props The properties required to create the local membership. + * @param props.scope The observable scope to use. + * @param props.connectionManager The connection manager to get connections from. + * @param props.createPublisherFactory Factory to create a publisher once we have a connection. + * @param props.joinMatrixRTC Callback to join the matrix RTC session once we have a transport. + * @param props.homeserverConnected The homeserver connected state. + * @param props.localTransport$ The local transport to use for publishing. + * @param props.logger The logger to use. + * @param props.muteStates The mute states for video and audio. + * @param props.matrixRTCSession The matrix RTC session to join. * @returns * - publisher: The handle to create tracks and publish them to the room. * - connected$: the current connection state. Including matrix server and livekit server connection. (only considering the livekit server we are using for our own media publication) @@ -676,9 +685,11 @@ interface EnterRTCSessionOptions { * - Delay events management * - Handles retries (fails only after several attempts) * - * @param rtcSession - * @param transport - * @param options + * @param rtcSession - The MatrixRTCSession to join. + * @param transport - The LivekitTransport to use for this session. + * @param options - Options for entering the RTC session. + * @param options.encryptMedia - Whether to encrypt media. + * @param options.matrixRTCMode - The Matrix RTC mode to use. * @throws If the widget could not send ElementWidgetActions.JoinCall action. */ // Exported for unit testing diff --git a/src/state/CallViewModel/localMember/Publisher.ts b/src/state/CallViewModel/localMember/Publisher.ts index 3cb3bd04e..27c537262 100644 --- a/src/state/CallViewModel/localMember/Publisher.ts +++ b/src/state/CallViewModel/localMember/Publisher.ts @@ -143,7 +143,7 @@ export class Publisher { this.logger.debug("createAndSetupTracks called"); const lkRoom = this.connection.livekitRoom; // Observe mute state changes and update LiveKit microphone/camera states accordingly - this.observeMuteStates(this.scope); + this.observeMuteStates(); // Check if audio and/or video is enabled. We only create tracks if enabled, // because it could prompt for permission, and we don't want to do that unnecessarily. @@ -356,10 +356,9 @@ export class Publisher { /** * Observe changes in the mute states and update the LiveKit room accordingly. - * @param scope * @private */ - private observeMuteStates(scope: ObservableScope): void { + private observeMuteStates(): void { const lkRoom = this.connection.livekitRoom; this.muteStates.audio.setHandler(async (enable) => { try { diff --git a/src/state/CallViewModel/remoteMembers/Connection.ts b/src/state/CallViewModel/remoteMembers/Connection.ts index cf92e2a62..41dfe6658 100644 --- a/src/state/CallViewModel/remoteMembers/Connection.ts +++ b/src/state/CallViewModel/remoteMembers/Connection.ts @@ -218,7 +218,7 @@ export class Connection { * * @param opts - Connection options {@link ConnectionOpts}. * - * @param logger + * @param logger - The logger to use. */ public constructor(opts: ConnectionOpts, logger: Logger) { this.logger = logger.getChild("[Connection]"); diff --git a/src/state/CallViewModel/remoteMembers/ConnectionFactory.ts b/src/state/CallViewModel/remoteMembers/ConnectionFactory.ts index 48e5b8d87..c33640594 100644 --- a/src/state/CallViewModel/remoteMembers/ConnectionFactory.ts +++ b/src/state/CallViewModel/remoteMembers/ConnectionFactory.ts @@ -43,11 +43,11 @@ export class ECConnectionFactory implements ConnectionFactory { * @param client - The OpenID client parts for authentication, needed to get openID and JWT tokens. * @param devices - Used for video/audio out/in capture options. * @param processorState$ - Effects like background blur (only for publishing connection?) - * @param livekitKeyProvider + * @param livekitKeyProvider - Optional key provider for end-to-end encryption. * @param controlledAudioDevices - Option to indicate whether audio output device is controlled externally (native mobile app). + * @param livekitRoomFactory - Optional factory function (for testing) to create LivekitRoom instances. If not provided, a default factory is used. * @param echoCancellation - Whether to enable echo cancellation for audio capture. * @param noiseSuppression - Whether to enable noise suppression for audio capture. - * @param livekitRoomFactory - Optional factory function (for testing) to create LivekitRoom instances. If not provided, a default factory is used. */ public constructor( private client: OpenIDClientParts, diff --git a/src/state/CallViewModel/remoteMembers/ConnectionManager.ts b/src/state/CallViewModel/remoteMembers/ConnectionManager.ts index c1b4af591..101e34ed9 100644 --- a/src/state/CallViewModel/remoteMembers/ConnectionManager.ts +++ b/src/state/CallViewModel/remoteMembers/ConnectionManager.ts @@ -76,9 +76,11 @@ export interface IConnectionManager { /** * Crete a `ConnectionManager` - * @param scope the observable scope used by this object. - * @param connectionFactory used to create new connections. - * @param _transportsSubscriptions$ A list of Behaviors each containing a LIST of LivekitTransport. + * @param props - Configuration object + * @param props.scope - The observable scope used by this object + * @param props.connectionFactory - Used to create new connections + * @param props.inputTransports$ - A list of Behaviors each containing a LIST of LivekitTransport. + * @param props.logger - The logger to use * Each of these behaviors can be interpreted as subscribed list of transports. * * Using `registerTransports` independent external modules can control what connections diff --git a/src/useAudioContext.tsx b/src/useAudioContext.tsx index 59334ddac..4d08dde89 100644 --- a/src/useAudioContext.tsx +++ b/src/useAudioContext.tsx @@ -22,9 +22,12 @@ import * as controls from "./controls"; * Play a sound though a given AudioContext. Will take * care of connecting the correct buffer and gating * through gain. - * @param volume The volume to play at. * @param ctx The context to play through. * @param buffer The buffer to play. + * @param volume The volume to play at. + * @param stereoPan The stereo pan to apply. + * @param delayS Delay in seconds before starting playing. + * @param abort Optional AbortController that can be used to stop playback. * @returns A promise that resolves when the sound has finished playing. */ async function playSound( @@ -55,9 +58,11 @@ async function playSound( * Play a sound though a given AudioContext, looping until stopped. Will take * care of connecting the correct buffer and gating * through gain. - * @param volume The volume to play at. * @param ctx The context to play through. * @param buffer The buffer to play. + * @param volume The volume to play at. + * @param stereoPan The stereo pan to apply. + * @param delayS Delay in seconds between each loop. * @returns A function used to end the sound. This function will return a promise when the sound has stopped. */ function playSoundLooping( @@ -120,7 +125,7 @@ interface UseAudioContext { /** * Add an audio context which can be used to play * a set of preloaded sounds. - * @param props + * @param props The properties for the audio context. * @returns Either an instance that can be used to play sounds, or null if not ready. */ export function useAudioContext( diff --git a/src/utils/displayname.ts b/src/utils/displayname.ts index 5ab5de9b5..bc49b29ec 100644 --- a/src/utils/displayname.ts +++ b/src/utils/displayname.ts @@ -77,6 +77,13 @@ export function shouldDisambiguate( ); } +/** + * Calculates a display name for a member, optionally disambiguating it. + * @param member - The member to calculate the display name for. + * @param member.rawDisplayName - The raw display name of the member + * @param member.userId - The user ID of the member + * @param disambiguate - Whether to disambiguate the display name. + */ export function calculateDisplayName( member: { rawDisplayName?: string; userId: string }, disambiguate: boolean, diff --git a/src/utils/errors.ts b/src/utils/errors.ts index bb37754ab..3ac2527a8 100644 --- a/src/utils/errors.ts +++ b/src/utils/errors.ts @@ -57,9 +57,16 @@ export class ElementCallError extends Error { } } +/** + * Configuration problem due to no MatrixRTC backend/SFU is exposed via .well-known and no fallback configured. + */ export class MatrixRTCTransportMissingError extends ElementCallError { public domain: string; + /** + * Creates an instance of MatrixRTCTransportMissingError. + * @param domain - The domain where the MatrixRTC transport is missing. + */ public constructor(domain: string) { super( t("error.call_is_not_supported"), @@ -75,7 +82,11 @@ export class MatrixRTCTransportMissingError extends ElementCallError { } } +/** + * Error indicating that the connection to the call was lost and could not be re-established. + */ export class ConnectionLostError extends ElementCallError { + public constructor() { super( t("error.connection_lost"), @@ -86,7 +97,17 @@ export class ConnectionLostError extends ElementCallError { } } +/** + * Error indicating a failure in the membership manager causing the join call + * operation to fail. + */ export class MembershipManagerError extends ElementCallError { + + /** + * Creates an instance of MembershipManagerError. + * + * @param error - The underlying error that caused the membership manager failure. + */ public constructor(error: Error) { super( t("error.membership_manager"), @@ -98,7 +119,11 @@ export class MembershipManagerError extends ElementCallError { } } +/** + * Error indicating that end-to-end encryption is not supported in the current environment. + */ export class E2EENotSupportedError extends ElementCallError { + public constructor() { super( t("error.e2ee_unsupported"), @@ -109,7 +134,15 @@ export class E2EENotSupportedError extends ElementCallError { } } +/** + * Error indicating an unknown issue occurred during a call operation. + */ export class UnknownCallError extends ElementCallError { + + /** + * Creates an instance of UnknownCallError. + * @param error - The underlying error that caused the unknown issue. + */ public constructor(error: Error) { super( t("error.generic"), @@ -122,7 +155,14 @@ export class UnknownCallError extends ElementCallError { } } +/** + * Error indicating a failure to obtain an OpenID token. + */ export class FailToGetOpenIdToken extends ElementCallError { + /** + * Creates an instance of FailToGetOpenIdToken. + * @param error - The underlying error that caused the failure. + */ public constructor(error: Error) { super( t("error.generic"), @@ -135,7 +175,15 @@ export class FailToGetOpenIdToken extends ElementCallError { } } +/** + * Error indicating a failure to start publishing on a LiveKit connection. + */ export class FailToStartLivekitConnection extends ElementCallError { + + /** + * Creates an instance of FailToStartLivekitConnection. + * @param e - An optional error message providing additional context. + */ public constructor(e?: string) { super( t("error.failed_to_start_livekit"), @@ -146,6 +194,9 @@ export class FailToStartLivekitConnection extends ElementCallError { } } +/** + * Error indicating that a LiveKit's server has hit its track limits. + */ export class InsufficientCapacityError extends ElementCallError { public constructor() { super( @@ -157,6 +208,10 @@ export class InsufficientCapacityError extends ElementCallError { } } +/** + * Error indicating that room creation is restricted by the SFU. + * Only authorized users can create rooms, so the room must exist before connecting (done by the auth jwt service) + */ export class SFURoomCreationRestrictedError extends ElementCallError { public constructor() { super( diff --git a/src/utils/matrix.ts b/src/utils/matrix.ts index 0a2b5c1a5..4e3ae3c32 100644 --- a/src/utils/matrix.ts +++ b/src/utils/matrix.ts @@ -188,7 +188,6 @@ function fullAliasFromRoomName(roomName: string, client: MatrixClient): string { * Applies some basic sanitisation to a room name that the user * has given us * @param input The room name from the user - * @param client A matrix client object */ export function sanitiseRoomNameInput(input: string): string { // check to see if the user has entered a fully qualified room @@ -304,8 +303,9 @@ export async function createRoom( /** * Returns an absolute URL to that will load Element Call with the given room * @param roomId ID of the room - * @param roomName Name of the room * @param encryptionSystem what encryption (or EncryptionSystem.Unencrypted) the room uses + * @param roomName Name of the room + * @param viaServers Optional list of servers to include as 'via' parameters in the URL */ export function getAbsoluteRoomUrl( roomId: string, @@ -321,8 +321,9 @@ export function getAbsoluteRoomUrl( /** * Returns a relative URL to that will load Element Call with the given room * @param roomId ID of the room - * @param roomName Name of the room * @param encryptionSystem what encryption (or EncryptionSystem.Unencrypted) the room uses + * @param roomName Name of the room + * @param viaServers Optional list of servers to include as 'via' parameters in the URL */ export function getRelativeRoomUrl( roomId: string, diff --git a/src/utils/media.ts b/src/utils/media.ts index cdd81aa78..3750aa4ec 100644 --- a/src/utils/media.ts +++ b/src/utils/media.ts @@ -8,6 +8,7 @@ Please see LICENSE in the repository root for full details. /** * Finds a media device with label matching 'deviceName' * @param deviceName The label of the device to look for + * @param kind The kind of media device to look for * @param devices The list of devices to search * @returns A matching media device or undefined if no matching device was found */ diff --git a/src/utils/observable.ts b/src/utils/observable.ts index a6dafea3f..9739353f2 100644 --- a/src/utils/observable.ts +++ b/src/utils/observable.ts @@ -135,7 +135,6 @@ interface ItemHandle { * requested at a later time, and destroyed (have their scope ended) when the * key is no longer requested. * - * @param input$ The input value to be mapped. * @param generator A generator function yielding a tuple of keys and the * currently associated data for each item that it wants to exist. * @param factory A function constructing an individual item, given the item's key, diff --git a/yarn.lock b/yarn.lock index abb3ef95b..401bb7c94 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2224,6 +2224,26 @@ __metadata: languageName: node linkType: hard +"@es-joy/jsdoccomment@npm:~0.76.0": + version: 0.76.0 + resolution: "@es-joy/jsdoccomment@npm:0.76.0" + dependencies: + "@types/estree": "npm:^1.0.8" + "@typescript-eslint/types": "npm:^8.46.0" + comment-parser: "npm:1.4.1" + esquery: "npm:^1.6.0" + jsdoc-type-pratt-parser: "npm:~6.10.0" + checksum: 10c0/8fe4edec7d60562787ea8c77193ebe8737a9e28ec3143d383506b63890d0ffd45a2813e913ad1f00f227cb10e3a1fb913e5a696b33d499dc564272ff1a6f3fdb + languageName: node + linkType: hard + +"@es-joy/resolve.exports@npm:1.2.0": + version: 1.2.0 + resolution: "@es-joy/resolve.exports@npm:1.2.0" + checksum: 10c0/7e4713471f5eccb17a925a12415a2d9e372a42376813a19f6abd9c35e8d01ab1403777265817da67c6150cffd4f558d9ad51e26a8de6911dad89d9cb7eedacd8 + languageName: node + linkType: hard + "@esbuild/aix-ppc64@npm:0.25.1": version: 0.25.1 resolution: "@esbuild/aix-ppc64@npm:0.25.1" @@ -4898,6 +4918,13 @@ __metadata: languageName: node linkType: hard +"@sindresorhus/base62@npm:^1.0.0": + version: 1.0.0 + resolution: "@sindresorhus/base62@npm:1.0.0" + checksum: 10c0/9a14df0f058fdf4731c30f0f05728a4822144ee42236030039d7fa5a1a1072c2879feba8091fd4a17c8922d1056bc07bada77c31fddc3e15836fc05a266fd918 + languageName: node + linkType: hard + "@stylistic/eslint-plugin@npm:^3.0.0": version: 3.1.0 resolution: "@stylistic/eslint-plugin@npm:3.1.0" @@ -5196,7 +5223,7 @@ __metadata: languageName: node linkType: hard -"@types/estree@npm:1.0.8": +"@types/estree@npm:1.0.8, @types/estree@npm:^1.0.8": version: 1.0.8 resolution: "@types/estree@npm:1.0.8" checksum: 10c0/39d34d1afaa338ab9763f37ad6066e3f349444f9052b9676a7cc0252ef9485a41c6d81c9c4e0d26e9077993354edf25efc853f3224dd4b447175ef62bdcc86a5 @@ -5526,6 +5553,13 @@ __metadata: languageName: node linkType: hard +"@typescript-eslint/types@npm:^8.46.0": + version: 8.51.0 + resolution: "@typescript-eslint/types@npm:8.51.0" + checksum: 10c0/eb3473d0bb71eb886438f35887b620ffadae7853b281752a40c73158aee644d136adeb82549be7d7c30f346fe888b2e979dff7e30e67b35377e8281018034529 + languageName: node + linkType: hard + "@typescript-eslint/typescript-estree@npm:5.62.0": version: 5.62.0 resolution: "@typescript-eslint/typescript-estree@npm:5.62.0" @@ -5886,6 +5920,15 @@ __metadata: languageName: node linkType: hard +"acorn@npm:^8.15.0": + version: 8.15.0 + resolution: "acorn@npm:8.15.0" + bin: + acorn: bin/acorn + checksum: 10c0/dec73ff59b7d6628a01eebaece7f2bdb8bb62b9b5926dcad0f8931f2b8b79c2be21f6c68ac095592adb5adb15831a3635d9343e6a91d028bbe85d564875ec3ec + languageName: node + linkType: hard + "acorn@npm:^8.9.0": version: 8.12.1 resolution: "acorn@npm:8.12.1" @@ -5995,6 +6038,13 @@ __metadata: languageName: node linkType: hard +"are-docs-informative@npm:^0.0.2": + version: 0.0.2 + resolution: "are-docs-informative@npm:0.0.2" + checksum: 10c0/f0326981bd699c372d268b526b170a28f2e1aec2cf99d7de0686083528427ecdf6ae41fef5d9988e224a5616298af747ad8a76e7306b0a7c97cc085a99636d60 + languageName: node + linkType: hard + "argparse@npm:^2.0.1": version: 2.0.1 resolution: "argparse@npm:2.0.1" @@ -7045,6 +7095,13 @@ __metadata: languageName: node linkType: hard +"comment-parser@npm:1.4.1": + version: 1.4.1 + resolution: "comment-parser@npm:1.4.1" + checksum: 10c0/d6c4be3f5be058f98b24f2d557f745d8fe1cc9eb75bebbdccabd404a0e1ed41563171b16285f593011f8b6a5ec81f564fb1f2121418ac5cbf0f49255bf0840dd + languageName: node + linkType: hard + "common-tags@npm:^1.8.0": version: 1.8.2 resolution: "common-tags@npm:1.8.2" @@ -7455,6 +7512,18 @@ __metadata: languageName: node linkType: hard +"debug@npm:^4.4.3": + version: 4.4.3 + resolution: "debug@npm:4.4.3" + dependencies: + ms: "npm:^2.1.3" + peerDependenciesMeta: + supports-color: + optional: true + checksum: 10c0/d79136ec6c83ecbefd0f6a5593da6a9c91ec4d7ddc4b54c883d6e71ec9accb5f67a1a5e96d00a328196b5b5c86d365e98d8a3a70856aaf16b4e7b1985e67f5a6 + languageName: node + linkType: hard + "decamelize@npm:^1.2.0": version: 1.2.0 resolution: "decamelize@npm:1.2.0" @@ -7825,6 +7894,7 @@ __metadata: eslint-config-prettier: "npm:^10.0.0" eslint-plugin-deprecate: "npm:^0.8.2" eslint-plugin-import: "npm:^2.26.0" + eslint-plugin-jsdoc: "npm:^61.5.0" eslint-plugin-jsx-a11y: "npm:^6.5.1" eslint-plugin-matrix-org: "npm:2.1.0" eslint-plugin-react: "npm:^7.29.4" @@ -8399,6 +8469,30 @@ __metadata: languageName: node linkType: hard +"eslint-plugin-jsdoc@npm:^61.5.0": + version: 61.5.0 + resolution: "eslint-plugin-jsdoc@npm:61.5.0" + dependencies: + "@es-joy/jsdoccomment": "npm:~0.76.0" + "@es-joy/resolve.exports": "npm:1.2.0" + are-docs-informative: "npm:^0.0.2" + comment-parser: "npm:1.4.1" + debug: "npm:^4.4.3" + escape-string-regexp: "npm:^4.0.0" + espree: "npm:^10.4.0" + esquery: "npm:^1.6.0" + html-entities: "npm:^2.6.0" + object-deep-merge: "npm:^2.0.0" + parse-imports-exports: "npm:^0.2.4" + semver: "npm:^7.7.3" + spdx-expression-parse: "npm:^4.0.0" + to-valid-identifier: "npm:^1.0.0" + peerDependencies: + eslint: ^7.0.0 || ^8.0.0 || ^9.0.0 + checksum: 10c0/fabb04f6efe58a167a0839d3c05676a76080c6e91d98a269fa768c1bfd835aa0ded5822d400da2874216177044d2d227ebe241d73e923f3fe1c08bafd19cfd3d + languageName: node + linkType: hard + "eslint-plugin-jsx-a11y@npm:^6.5.1": version: 6.10.2 resolution: "eslint-plugin-jsx-a11y@npm:6.10.2" @@ -8633,6 +8727,17 @@ __metadata: languageName: node linkType: hard +"espree@npm:^10.4.0": + version: 10.4.0 + resolution: "espree@npm:10.4.0" + dependencies: + acorn: "npm:^8.15.0" + acorn-jsx: "npm:^5.3.2" + eslint-visitor-keys: "npm:^4.2.1" + checksum: 10c0/c63fe06131c26c8157b4083313cb02a9a54720a08e21543300e55288c40e06c3fc284bdecf108d3a1372c5934a0a88644c98714f38b6ae8ed272b40d9ea08d6b + languageName: node + linkType: hard + "espree@npm:^9.6.0, espree@npm:^9.6.1": version: 9.6.1 resolution: "espree@npm:9.6.1" @@ -9526,6 +9631,13 @@ __metadata: languageName: node linkType: hard +"html-entities@npm:^2.6.0": + version: 2.6.0 + resolution: "html-entities@npm:2.6.0" + checksum: 10c0/7c8b15d9ea0cd00dc9279f61bab002ba6ca8a7a0f3c36ed2db3530a67a9621c017830d1d2c1c65beb9b8e3436ea663e9cf8b230472e0e413359399413b27c8b7 + languageName: node + linkType: hard + "html-escaper@npm:^2.0.0": version: 2.0.2 resolution: "html-escaper@npm:2.0.2" @@ -10295,6 +10407,13 @@ __metadata: languageName: node linkType: hard +"jsdoc-type-pratt-parser@npm:~6.10.0": + version: 6.10.0 + resolution: "jsdoc-type-pratt-parser@npm:6.10.0" + checksum: 10c0/8ea395df0cae0e41d4bdba5f8d81b8d3e467fe53d1e4182a5d4e653235a5f17d60ed137343d68dbc74fa10e767f1c58fb85b1f6d5489c2cf16fc7216cc6d3e1a + languageName: node + linkType: hard + "jsdom@npm:^26.0.0": version: 26.1.0 resolution: "jsdom@npm:26.1.0" @@ -11250,6 +11369,13 @@ __metadata: languageName: node linkType: hard +"object-deep-merge@npm:^2.0.0": + version: 2.0.0 + resolution: "object-deep-merge@npm:2.0.0" + checksum: 10c0/69e8741131ad49fa8720fb96007a3c82dca1119b5d874151d2ecbcc3b44ccd46e8553c7a30b0abcba752c099ba361bbba97f33a68c9ae54c57eed7be116ffc97 + languageName: node + linkType: hard + "object-inspect@npm:^1.13.3": version: 1.13.3 resolution: "object-inspect@npm:1.13.3" @@ -11563,6 +11689,15 @@ __metadata: languageName: node linkType: hard +"parse-imports-exports@npm:^0.2.4": + version: 0.2.4 + resolution: "parse-imports-exports@npm:0.2.4" + dependencies: + parse-statements: "npm:1.0.11" + checksum: 10c0/51b729037208abdf65c4a1f8e9ed06f4e7ccd907c17c668a64db54b37d95bb9e92081f8b16e4133e14102af3cb4e89870975b6ad661b4d654e9ec8f4fb5c77d6 + languageName: node + linkType: hard + "parse-json@npm:^5.0.0, parse-json@npm:^5.2.0": version: 5.2.0 resolution: "parse-json@npm:5.2.0" @@ -11575,6 +11710,13 @@ __metadata: languageName: node linkType: hard +"parse-statements@npm:1.0.11": + version: 1.0.11 + resolution: "parse-statements@npm:1.0.11" + checksum: 10c0/48960e085019068a5f5242e875fd9d21ec87df2e291acf5ad4e4887b40eab6929a8c8d59542acb85a6497e870c5c6a24f5ab7f980ef5f907c14cc5f7984a93f3 + languageName: node + linkType: hard + "parse5-htmlparser2-tree-adapter@npm:^7.0.0": version: 7.1.0 resolution: "parse5-htmlparser2-tree-adapter@npm:7.1.0" @@ -12820,6 +12962,13 @@ __metadata: languageName: node linkType: hard +"reserved-identifiers@npm:^1.0.0": + version: 1.2.0 + resolution: "reserved-identifiers@npm:1.2.0" + checksum: 10c0/b82651b12e6c608e80463c3753d275bc20fd89294d0415f04e670aeec3611ae3582ddc19e8fedd497e7d0bcbfaddab6a12823ec86e855b1e6a245e0a734eb43d + languageName: node + linkType: hard + "resolve-from@npm:^4.0.0": version: 4.0.0 resolution: "resolve-from@npm:4.0.0" @@ -13280,6 +13429,15 @@ __metadata: languageName: node linkType: hard +"semver@npm:^7.7.3": + version: 7.7.3 + resolution: "semver@npm:7.7.3" + bin: + semver: bin/semver.js + checksum: 10c0/4afe5c986567db82f44c8c6faef8fe9df2a9b1d98098fc1721f57c696c4c21cebd572f297fc21002f81889492345b8470473bc6f4aff5fb032a6ea59ea2bc45e + languageName: node + linkType: hard + "set-blocking@npm:^2.0.0": version: 2.0.0 resolution: "set-blocking@npm:2.0.0" @@ -13548,6 +13706,16 @@ __metadata: languageName: node linkType: hard +"spdx-expression-parse@npm:^4.0.0": + version: 4.0.0 + resolution: "spdx-expression-parse@npm:4.0.0" + dependencies: + spdx-exceptions: "npm:^2.1.0" + spdx-license-ids: "npm:^3.0.0" + checksum: 10c0/965c487e77f4fb173f1c471f3eef4eb44b9f0321adc7f93d95e7620da31faa67d29356eb02523cd7df8a7fc1ec8238773cdbf9e45bd050329d2b26492771b736 + languageName: node + linkType: hard + "spdx-license-ids@npm:^3.0.0": version: 3.0.20 resolution: "spdx-license-ids@npm:3.0.20" @@ -14055,6 +14223,16 @@ __metadata: languageName: node linkType: hard +"to-valid-identifier@npm:^1.0.0": + version: 1.0.0 + resolution: "to-valid-identifier@npm:1.0.0" + dependencies: + "@sindresorhus/base62": "npm:^1.0.0" + reserved-identifiers: "npm:^1.0.0" + checksum: 10c0/569b49f43b5aaaa20677e67f0f1cdcff344855149934cfb80c793c7ac7c30e191b224bc81cab40fb57641af9ca73795c78053c164a2addc617671e2d22c13a4a + languageName: node + linkType: hard + "toggle-selection@npm:^1.0.6": version: 1.0.6 resolution: "toggle-selection@npm:1.0.6" From 5e715765d9d1205dd83f5514d080e45055e04bd8 Mon Sep 17 00:00:00 2001 From: Valere Date: Tue, 30 Dec 2025 18:17:07 +0100 Subject: [PATCH 126/748] fix: un-needed tsdoc script --- .eslintrc.cjs | 12 +++++++++--- package.json | 3 +-- src/utils/errors.ts | 5 ----- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/.eslintrc.cjs b/.eslintrc.cjs index 2cd63d63e..11116ed2d 100644 --- a/.eslintrc.cjs +++ b/.eslintrc.cjs @@ -83,7 +83,13 @@ module.exports = { }, }, { - files: ["**/*.test.ts", "**/*.test.tsx", "**/test.ts", "**/test.tsx", "**/test-**"], + files: [ + "**/*.test.ts", + "**/*.test.tsx", + "**/test.ts", + "**/test.tsx", + "**/test-**", + ], rules: { "jsdoc/no-types": "off", "jsdoc/empty-tags": "off", @@ -91,8 +97,8 @@ module.exports = { "jsdoc/check-values": "off", "jsdoc/check-param-names": "off", "jsdoc/require-param-description": "off", - } - } + }, + }, ], settings: { react: { diff --git a/package.json b/package.json index e5b574443..336dd5d75 100644 --- a/package.json +++ b/package.json @@ -18,12 +18,11 @@ "serve": "vite preview", "prettier:check": "prettier -c .", "prettier:format": "prettier -w .", - "lint": "yarn lint:types && yarn lint:eslint && yarn lint:knip && yarn lint:tsdoc", + "lint": "yarn lint:types && yarn lint:eslint && yarn lint:knip", "lint:eslint": "eslint --max-warnings 0 src playwright", "lint:eslint-fix": "eslint --max-warnings 0 src playwright --fix", "lint:knip": "knip", "lint:types": "tsc", - "lint:tsdoc": "eslint --ext .ts,.tsx src", "i18n": "i18next", "i18n:check": "i18next --fail-on-warnings --fail-on-update", "test": "vitest", diff --git a/src/utils/errors.ts b/src/utils/errors.ts index 3ac2527a8..cddf90def 100644 --- a/src/utils/errors.ts +++ b/src/utils/errors.ts @@ -86,7 +86,6 @@ export class MatrixRTCTransportMissingError extends ElementCallError { * Error indicating that the connection to the call was lost and could not be re-established. */ export class ConnectionLostError extends ElementCallError { - public constructor() { super( t("error.connection_lost"), @@ -102,7 +101,6 @@ export class ConnectionLostError extends ElementCallError { * operation to fail. */ export class MembershipManagerError extends ElementCallError { - /** * Creates an instance of MembershipManagerError. * @@ -123,7 +121,6 @@ export class MembershipManagerError extends ElementCallError { * Error indicating that end-to-end encryption is not supported in the current environment. */ export class E2EENotSupportedError extends ElementCallError { - public constructor() { super( t("error.e2ee_unsupported"), @@ -138,7 +135,6 @@ export class E2EENotSupportedError extends ElementCallError { * Error indicating an unknown issue occurred during a call operation. */ export class UnknownCallError extends ElementCallError { - /** * Creates an instance of UnknownCallError. * @param error - The underlying error that caused the unknown issue. @@ -179,7 +175,6 @@ export class FailToGetOpenIdToken extends ElementCallError { * Error indicating a failure to start publishing on a LiveKit connection. */ export class FailToStartLivekitConnection extends ElementCallError { - /** * Creates an instance of FailToStartLivekitConnection. * @param e - An optional error message providing additional context. From 88cfd32e5165226d07487a9b295b5b962b845378 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 31 Dec 2025 13:52:04 +0000 Subject: [PATCH 127/748] Update dependency livekit-client to v2.16.1 --- yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/yarn.lock b/yarn.lock index abb3ef95b..874357f59 100644 --- a/yarn.lock +++ b/yarn.lock @@ -10538,8 +10538,8 @@ __metadata: linkType: hard "livekit-client@npm:^2.13.0": - version: 2.16.0 - resolution: "livekit-client@npm:2.16.0" + version: 2.16.1 + resolution: "livekit-client@npm:2.16.1" dependencies: "@livekit/mutex": "npm:1.1.1" "@livekit/protocol": "npm:1.42.2" @@ -10553,7 +10553,7 @@ __metadata: webrtc-adapter: "npm:^9.0.1" peerDependencies: "@types/dom-mediacapture-record": ^1 - checksum: 10c0/5d03adc5d09efde343ab894db397529dff26117598e773b23a5df90a4fb166bde12c6bb1f2cfd1d28dbaf93fe9f275026d7abb75f2ffd2ba816393a2d58e6c7e + checksum: 10c0/a16f7e603730410b640991cdb1a9d5ad3b0b06b23b8fe2e76674e6a9ba54ed4c8e7e4f6ad15fe67c8de6557da161e1265b40802c4e3701db3fe0d7ea9250b1e2 languageName: node linkType: hard From a6aa4526cf8a015e2d4856d141355d1d6b32918d Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 31 Dec 2025 13:52:19 +0000 Subject: [PATCH 128/748] Update LiveKit components --- yarn.lock | 46 ++++++++++++++++++++++++++++++++++++---------- 1 file changed, 36 insertions(+), 10 deletions(-) diff --git a/yarn.lock b/yarn.lock index abb3ef95b..0b7a88ffd 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2486,7 +2486,26 @@ __metadata: languageName: node linkType: hard -"@floating-ui/dom@npm:1.6.13, @floating-ui/dom@npm:^1.0.0": +"@floating-ui/core@npm:^1.7.3": + version: 1.7.3 + resolution: "@floating-ui/core@npm:1.7.3" + dependencies: + "@floating-ui/utils": "npm:^0.2.10" + checksum: 10c0/edfc23800122d81df0df0fb780b7328ae6c5f00efbb55bd48ea340f4af8c5b3b121ceb4bb81220966ab0f87b443204d37105abdd93d94846468be3243984144c + languageName: node + linkType: hard + +"@floating-ui/dom@npm:1.7.4": + version: 1.7.4 + resolution: "@floating-ui/dom@npm:1.7.4" + dependencies: + "@floating-ui/core": "npm:^1.7.3" + "@floating-ui/utils": "npm:^0.2.10" + checksum: 10c0/da6166c25f9b0729caa9f498685a73a0e28251613b35d27db8de8014bc9d045158a23c092b405321a3d67c2064909b6e2a7e6c1c9cc0f62967dca5779f5aef30 + languageName: node + linkType: hard + +"@floating-ui/dom@npm:^1.0.0": version: 1.6.13 resolution: "@floating-ui/dom@npm:1.6.13" dependencies: @@ -2522,6 +2541,13 @@ __metadata: languageName: node linkType: hard +"@floating-ui/utils@npm:^0.2.10": + version: 0.2.10 + resolution: "@floating-ui/utils@npm:0.2.10" + checksum: 10c0/e9bc2a1730ede1ee25843937e911ab6e846a733a4488623cd353f94721b05ec2c9ec6437613a2ac9379a94c2fd40c797a2ba6fa1df2716f5ce4aa6ddb1cf9ea4 + languageName: node + linkType: hard + "@floating-ui/utils@npm:^0.2.9": version: 0.2.9 resolution: "@floating-ui/utils@npm:0.2.9" @@ -2738,25 +2764,25 @@ __metadata: languageName: node linkType: hard -"@livekit/components-core@npm:0.12.11, @livekit/components-core@npm:^0.12.0": - version: 0.12.11 - resolution: "@livekit/components-core@npm:0.12.11" +"@livekit/components-core@npm:0.12.12, @livekit/components-core@npm:^0.12.0": + version: 0.12.12 + resolution: "@livekit/components-core@npm:0.12.12" dependencies: - "@floating-ui/dom": "npm:1.6.13" + "@floating-ui/dom": "npm:1.7.4" loglevel: "npm:1.9.1" rxjs: "npm:7.8.2" peerDependencies: livekit-client: ^2.15.14 tslib: ^2.6.2 - checksum: 10c0/9c2ac3d30bb8cc9067ae0b2049784f81e90e57df9eabf7edbaf3c8ceb65a63f644a4e6abeb6cc38d3ebe52663d8dbb88535e01a965011f365d5ae1f3daf86052 + checksum: 10c0/788ae01fa6c58a0edbd629f4195f2f3a7bc94660d2fb729af8b27cab2b151abe36cd0a666989811c6187e51d32c847119853010a82be55844750ab3978079c38 languageName: node linkType: hard "@livekit/components-react@npm:^2.0.0": - version: 2.9.16 - resolution: "@livekit/components-react@npm:2.9.16" + version: 2.9.17 + resolution: "@livekit/components-react@npm:2.9.17" dependencies: - "@livekit/components-core": "npm:0.12.11" + "@livekit/components-core": "npm:0.12.12" clsx: "npm:2.1.1" events: "npm:^3.3.0" jose: "npm:^6.0.12" @@ -2770,7 +2796,7 @@ __metadata: peerDependenciesMeta: "@livekit/krisp-noise-filter": optional: true - checksum: 10c0/4ba4ff473c5a29d3107412733a6676a3b708d70684ed463e9b34cda26abb3d2f317c2828a52e730837b756de9df3fc248260d6f390aedebfb6ec96ef63c7b151 + checksum: 10c0/ba64ada37d4b3ce4d5ee7c5b2a6bddbffc17c2e641e95881aac9f02b4ff7428105e0a372d364e50ff124e988b7426d322d94caabdb55b634aebf0144d7e37f99 languageName: node linkType: hard From 057bc4e2ad03f9b54fcfe48b222368e3767e6b4f Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Sat, 3 Jan 2026 18:06:04 +0000 Subject: [PATCH 129/748] Update all non-major dependencies --- package.json | 6 +- yarn.lock | 2186 ++++++++++++++++++++++++++++++++------------------ 2 files changed, 1418 insertions(+), 774 deletions(-) diff --git a/package.json b/package.json index c67c2e4cc..263682b27 100644 --- a/package.json +++ b/package.json @@ -42,16 +42,16 @@ "@codecov/vite-plugin": "^1.3.0", "@fontsource/inconsolata": "^5.1.0", "@fontsource/inter": "^5.1.0", - "@formatjs/intl-durationformat": "^0.7.0", + "@formatjs/intl-durationformat": "^0.9.0", "@formatjs/intl-segmenter": "^11.7.3", "@livekit/components-core": "^0.12.0", "@livekit/components-react": "^2.0.0", "@livekit/protocol": "^1.42.2", - "@livekit/track-processors": "^0.5.5", + "@livekit/track-processors": "^0.7.0", "@mediapipe/tasks-vision": "^0.10.18", "@opentelemetry/api": "^1.4.0", "@opentelemetry/core": "^2.0.0", - "@opentelemetry/exporter-trace-otlp-http": "^0.203.0", + "@opentelemetry/exporter-trace-otlp-http": "^0.208.0", "@opentelemetry/resources": "^2.0.0", "@opentelemetry/sdk-trace-base": "^2.0.0", "@opentelemetry/sdk-trace-web": "^2.0.0", diff --git a/yarn.lock b/yarn.lock index abb3ef95b..04dc117b7 100644 --- a/yarn.lock +++ b/yarn.lock @@ -60,7 +60,7 @@ __metadata: languageName: node linkType: hard -"@ampproject/remapping@npm:^2.2.0, @ampproject/remapping@npm:^2.3.0": +"@ampproject/remapping@npm:^2.3.0": version: 2.3.0 resolution: "@ampproject/remapping@npm:2.3.0" dependencies: @@ -122,33 +122,40 @@ __metadata: languageName: node linkType: hard -"@babel/compat-data@npm:^7.27.7, @babel/compat-data@npm:^7.28.0": +"@babel/compat-data@npm:^7.27.7": version: 7.28.0 resolution: "@babel/compat-data@npm:7.28.0" checksum: 10c0/c4e527302bcd61052423f757355a71c3bc62362bac13f7f130de16e439716f66091ff5bdecda418e8fa0271d4c725f860f0ee23ab7bf6e769f7a8bb16dfcb531 languageName: node linkType: hard +"@babel/compat-data@npm:^7.28.5": + version: 7.28.5 + resolution: "@babel/compat-data@npm:7.28.5" + checksum: 10c0/702a25de73087b0eba325c1d10979eed7c9b6662677386ba7b5aa6eace0fc0676f78343bae080a0176ae26f58bd5535d73b9d0fbb547fef377692e8b249353a7 + languageName: node + linkType: hard + "@babel/core@npm:^7.16.5, @babel/core@npm:^7.18.5, @babel/core@npm:^7.21.3, @babel/core@npm:^7.28.0": - version: 7.28.0 - resolution: "@babel/core@npm:7.28.0" + version: 7.28.5 + resolution: "@babel/core@npm:7.28.5" dependencies: - "@ampproject/remapping": "npm:^2.2.0" "@babel/code-frame": "npm:^7.27.1" - "@babel/generator": "npm:^7.28.0" + "@babel/generator": "npm:^7.28.5" "@babel/helper-compilation-targets": "npm:^7.27.2" - "@babel/helper-module-transforms": "npm:^7.27.3" - "@babel/helpers": "npm:^7.27.6" - "@babel/parser": "npm:^7.28.0" + "@babel/helper-module-transforms": "npm:^7.28.3" + "@babel/helpers": "npm:^7.28.4" + "@babel/parser": "npm:^7.28.5" "@babel/template": "npm:^7.27.2" - "@babel/traverse": "npm:^7.28.0" - "@babel/types": "npm:^7.28.0" + "@babel/traverse": "npm:^7.28.5" + "@babel/types": "npm:^7.28.5" + "@jridgewell/remapping": "npm:^2.3.5" convert-source-map: "npm:^2.0.0" debug: "npm:^4.1.0" gensync: "npm:^1.0.0-beta.2" json5: "npm:^2.2.3" semver: "npm:^6.3.1" - checksum: 10c0/423302e7c721e73b1c096217880272e02020dfb697a55ccca60ad01bba90037015f84d0c20c6ce297cf33a19bb704bc5c2b3d3095f5284dfa592bd1de0b9e8c3 + checksum: 10c0/535f82238027621da6bdffbdbe896ebad3558b311d6f8abc680637a9859b96edbf929ab010757055381570b29cf66c4a295b5618318d27a4273c0e2033925e72 languageName: node linkType: hard @@ -191,6 +198,19 @@ __metadata: languageName: node linkType: hard +"@babel/generator@npm:^7.28.5": + version: 7.28.5 + resolution: "@babel/generator@npm:7.28.5" + dependencies: + "@babel/parser": "npm:^7.28.5" + "@babel/types": "npm:^7.28.5" + "@jridgewell/gen-mapping": "npm:^0.3.12" + "@jridgewell/trace-mapping": "npm:^0.3.28" + jsesc: "npm:^3.0.2" + checksum: 10c0/9f219fe1d5431b6919f1a5c60db8d5d34fe546c0d8f5a8511b32f847569234ffc8032beb9e7404649a143f54e15224ecb53a3d11b6bb85c3203e573d91fca752 + languageName: node + linkType: hard + "@babel/helper-annotate-as-pure@npm:^7.25.9": version: 7.25.9 resolution: "@babel/helper-annotate-as-pure@npm:7.25.9" @@ -239,6 +259,23 @@ __metadata: languageName: node linkType: hard +"@babel/helper-create-class-features-plugin@npm:^7.28.3, @babel/helper-create-class-features-plugin@npm:^7.28.5": + version: 7.28.5 + resolution: "@babel/helper-create-class-features-plugin@npm:7.28.5" + dependencies: + "@babel/helper-annotate-as-pure": "npm:^7.27.3" + "@babel/helper-member-expression-to-functions": "npm:^7.28.5" + "@babel/helper-optimise-call-expression": "npm:^7.27.1" + "@babel/helper-replace-supers": "npm:^7.27.1" + "@babel/helper-skip-transparent-expression-wrappers": "npm:^7.27.1" + "@babel/traverse": "npm:^7.28.5" + semver: "npm:^6.3.1" + peerDependencies: + "@babel/core": ^7.0.0 + checksum: 10c0/786a6514efcf4514aaad85beed419b9184d059f4c9a9a95108f320142764999827252a851f7071de19f29424d369616573ecbaa347f1ce23fb12fc6827d9ff56 + languageName: node + linkType: hard + "@babel/helper-create-regexp-features-plugin@npm:^7.18.6": version: 7.26.3 resolution: "@babel/helper-create-regexp-features-plugin@npm:7.26.3" @@ -297,6 +334,16 @@ __metadata: languageName: node linkType: hard +"@babel/helper-member-expression-to-functions@npm:^7.28.5": + version: 7.28.5 + resolution: "@babel/helper-member-expression-to-functions@npm:7.28.5" + dependencies: + "@babel/traverse": "npm:^7.28.5" + "@babel/types": "npm:^7.28.5" + checksum: 10c0/4e6e05fbf4dffd0bc3e55e28fcaab008850be6de5a7013994ce874ec2beb90619cda4744b11607a60f8aae0227694502908add6188ceb1b5223596e765b44814 + languageName: node + linkType: hard + "@babel/helper-module-imports@npm:^7.27.1": version: 7.27.1 resolution: "@babel/helper-module-imports@npm:7.27.1" @@ -307,7 +354,7 @@ __metadata: languageName: node linkType: hard -"@babel/helper-module-transforms@npm:^7.27.1, @babel/helper-module-transforms@npm:^7.27.3": +"@babel/helper-module-transforms@npm:^7.27.1": version: 7.27.3 resolution: "@babel/helper-module-transforms@npm:7.27.3" dependencies: @@ -320,6 +367,19 @@ __metadata: languageName: node linkType: hard +"@babel/helper-module-transforms@npm:^7.28.3": + version: 7.28.3 + resolution: "@babel/helper-module-transforms@npm:7.28.3" + dependencies: + "@babel/helper-module-imports": "npm:^7.27.1" + "@babel/helper-validator-identifier": "npm:^7.27.1" + "@babel/traverse": "npm:^7.28.3" + peerDependencies: + "@babel/core": ^7.0.0 + checksum: 10c0/549be62515a6d50cd4cfefcab1b005c47f89bd9135a22d602ee6a5e3a01f27571868ada10b75b033569f24dc4a2bb8d04bfa05ee75c16da7ade2d0db1437fcdb + languageName: node + linkType: hard + "@babel/helper-optimise-call-expression@npm:^7.27.1": version: 7.27.1 resolution: "@babel/helper-optimise-call-expression@npm:7.27.1" @@ -407,6 +467,13 @@ __metadata: languageName: node linkType: hard +"@babel/helper-validator-identifier@npm:^7.28.5": + version: 7.28.5 + resolution: "@babel/helper-validator-identifier@npm:7.28.5" + checksum: 10c0/42aaebed91f739a41f3d80b72752d1f95fd7c72394e8e4bd7cdd88817e0774d80a432451bcba17c2c642c257c483bf1d409dd4548883429ea9493a3bc4ab0847 + languageName: node + linkType: hard + "@babel/helper-validator-option@npm:^7.27.1": version: 7.27.1 resolution: "@babel/helper-validator-option@npm:7.27.1" @@ -425,13 +492,13 @@ __metadata: languageName: node linkType: hard -"@babel/helpers@npm:^7.27.6": - version: 7.27.6 - resolution: "@babel/helpers@npm:7.27.6" +"@babel/helpers@npm:^7.28.4": + version: 7.28.4 + resolution: "@babel/helpers@npm:7.28.4" dependencies: "@babel/template": "npm:^7.27.2" - "@babel/types": "npm:^7.27.6" - checksum: 10c0/448bac96ef8b0f21f2294a826df9de6bf4026fd023f8a6bb6c782fe3e61946801ca24381490b8e58d861fee75cd695a1882921afbf1f53b0275ee68c938bd6d3 + "@babel/types": "npm:^7.28.4" + checksum: 10c0/aaa5fb8098926dfed5f223adf2c5e4c7fbba4b911b73dfec2d7d3083f8ba694d201a206db673da2d9b3ae8c01793e795767654558c450c8c14b4c2175b4fcb44 languageName: node linkType: hard @@ -502,15 +569,26 @@ __metadata: languageName: node linkType: hard -"@babel/plugin-bugfix-firefox-class-in-computed-class-key@npm:^7.27.1": - version: 7.27.1 - resolution: "@babel/plugin-bugfix-firefox-class-in-computed-class-key@npm:7.27.1" +"@babel/parser@npm:^7.28.5": + version: 7.28.5 + resolution: "@babel/parser@npm:7.28.5" + dependencies: + "@babel/types": "npm:^7.28.5" + bin: + parser: ./bin/babel-parser.js + checksum: 10c0/5bbe48bf2c79594ac02b490a41ffde7ef5aa22a9a88ad6bcc78432a6ba8a9d638d531d868bd1f104633f1f6bba9905746e15185b8276a3756c42b765d131b1ef + languageName: node + linkType: hard + +"@babel/plugin-bugfix-firefox-class-in-computed-class-key@npm:^7.28.5": + version: 7.28.5 + resolution: "@babel/plugin-bugfix-firefox-class-in-computed-class-key@npm:7.28.5" dependencies: "@babel/helper-plugin-utils": "npm:^7.27.1" - "@babel/traverse": "npm:^7.27.1" + "@babel/traverse": "npm:^7.28.5" peerDependencies: "@babel/core": ^7.0.0 - checksum: 10c0/7dfffa978ae1cd179641a7c4b4ad688c6828c2c58ec96b118c2fb10bc3715223de6b88bff1ebff67056bb5fccc568ae773e3b83c592a1b843423319f80c99ebd + checksum: 10c0/844b7c7e9eec6d858262b2f3d5af75d3a6bbd9d3ecc740d95271fbdd84985731674536f5d8ac98f2dc0e8872698b516e406636e4d0cb04b50afe471172095a53 languageName: node linkType: hard @@ -549,15 +627,15 @@ __metadata: languageName: node linkType: hard -"@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly@npm:^7.27.1": - version: 7.27.1 - resolution: "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly@npm:7.27.1" +"@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly@npm:^7.28.3": + version: 7.28.3 + resolution: "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly@npm:7.28.3" dependencies: "@babel/helper-plugin-utils": "npm:^7.27.1" - "@babel/traverse": "npm:^7.27.1" + "@babel/traverse": "npm:^7.28.3" peerDependencies: "@babel/core": ^7.0.0 - checksum: 10c0/b94e6c3fc019e988b1499490829c327a1067b4ddea8ad402f6d0554793c9124148c2125338c723661b6dff040951abc1f092afbf3f2d234319cd580b68e52445 + checksum: 10c0/3cdc27c4e08a632a58e62c6017369401976edf1cd9ae73fd9f0d6770ddd9accf40b494db15b66bab8db2a8d5dc5bab5ca8c65b19b81fdca955cd8cbbe24daadb languageName: node linkType: hard @@ -674,14 +752,14 @@ __metadata: languageName: node linkType: hard -"@babel/plugin-transform-block-scoping@npm:^7.28.0": - version: 7.28.0 - resolution: "@babel/plugin-transform-block-scoping@npm:7.28.0" +"@babel/plugin-transform-block-scoping@npm:^7.28.5": + version: 7.28.5 + resolution: "@babel/plugin-transform-block-scoping@npm:7.28.5" dependencies: "@babel/helper-plugin-utils": "npm:^7.27.1" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 10c0/787d85e72a92917e735aa54e23062fa777031f8a07046e67f5026eff3d91e64eb535575dd1df917b0011bee014ae51287478af14c1d4ba60bc81e326bc044cfc + checksum: 10c0/6b098887b375c23813ccee7a00179501fc5f709b4ee5a4b2a5c5c9ef3b44cee49e240214b1a9b4ad2bd1911fab3335eac2f0a3c5f014938a1b61bec84cec4845 languageName: node linkType: hard @@ -697,31 +775,31 @@ __metadata: languageName: node linkType: hard -"@babel/plugin-transform-class-static-block@npm:^7.27.1": - version: 7.27.1 - resolution: "@babel/plugin-transform-class-static-block@npm:7.27.1" +"@babel/plugin-transform-class-static-block@npm:^7.28.3": + version: 7.28.3 + resolution: "@babel/plugin-transform-class-static-block@npm:7.28.3" dependencies: - "@babel/helper-create-class-features-plugin": "npm:^7.27.1" + "@babel/helper-create-class-features-plugin": "npm:^7.28.3" "@babel/helper-plugin-utils": "npm:^7.27.1" peerDependencies: "@babel/core": ^7.12.0 - checksum: 10c0/396997dd81fc1cf242b921e337d25089d6b9dc3596e81322ff11a6359326dc44f2f8b82dcc279c2e514cafaf8964dc7ed39e9fab4b8af1308b57387d111f6a20 + checksum: 10c0/8c922a64f6f5b359f7515c89ef0037bad583b4484dfebc1f6bc1cf13462547aaceb19788827c57ec9a2d62495f34c4b471ca636bf61af00fdaea5e9642c82b60 languageName: node linkType: hard -"@babel/plugin-transform-classes@npm:^7.28.0": - version: 7.28.0 - resolution: "@babel/plugin-transform-classes@npm:7.28.0" +"@babel/plugin-transform-classes@npm:^7.28.4": + version: 7.28.4 + resolution: "@babel/plugin-transform-classes@npm:7.28.4" dependencies: "@babel/helper-annotate-as-pure": "npm:^7.27.3" "@babel/helper-compilation-targets": "npm:^7.27.2" "@babel/helper-globals": "npm:^7.28.0" "@babel/helper-plugin-utils": "npm:^7.27.1" "@babel/helper-replace-supers": "npm:^7.27.1" - "@babel/traverse": "npm:^7.28.0" + "@babel/traverse": "npm:^7.28.4" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 10c0/3b213b43104fe99dd7e79401a86d09e545836e057a70ffe77e8196a87bf67ae167e502ae90afdf0d1a2be683be5652514aaeda743bd984e583523dd8ecfef887 + checksum: 10c0/76687ed37216ff012c599870dc00183fb716f22e1a02fe9481943664c0e4d0d88c3da347dc3fe290d4728f4d47cd594ffa621d23845e2bb8ab446e586308e066 languageName: node linkType: hard @@ -749,6 +827,18 @@ __metadata: languageName: node linkType: hard +"@babel/plugin-transform-destructuring@npm:^7.28.5": + version: 7.28.5 + resolution: "@babel/plugin-transform-destructuring@npm:7.28.5" + dependencies: + "@babel/helper-plugin-utils": "npm:^7.27.1" + "@babel/traverse": "npm:^7.28.5" + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 10c0/288207f488412b23bb206c7c01ba143714e2506b72a9ec09e993f28366cc8188d121bde714659b3437984a86d2881d9b1b06de3089d5582823ccf2f3b3eaa2c4 + languageName: node + linkType: hard + "@babel/plugin-transform-dotall-regex@npm:^7.27.1": version: 7.27.1 resolution: "@babel/plugin-transform-dotall-regex@npm:7.27.1" @@ -807,14 +897,14 @@ __metadata: languageName: node linkType: hard -"@babel/plugin-transform-exponentiation-operator@npm:^7.27.1": - version: 7.27.1 - resolution: "@babel/plugin-transform-exponentiation-operator@npm:7.27.1" +"@babel/plugin-transform-exponentiation-operator@npm:^7.28.5": + version: 7.28.5 + resolution: "@babel/plugin-transform-exponentiation-operator@npm:7.28.5" dependencies: "@babel/helper-plugin-utils": "npm:^7.27.1" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 10c0/953d21e01fed76da8e08fb5094cade7bf8927c1bb79301916bec2db0593b41dbcfbca1024ad5db886b72208a93ada8f57a219525aad048cf15814eeb65cf760d + checksum: 10c0/006566e003c2a8175346cc4b3260fcd9f719b912ceae8a4e930ce02ee3cf0b2841d5c21795ba71790871783d3c0c1c3d22ce441b8819c37975844bfba027d3f7 languageName: node linkType: hard @@ -876,14 +966,14 @@ __metadata: languageName: node linkType: hard -"@babel/plugin-transform-logical-assignment-operators@npm:^7.27.1": - version: 7.27.1 - resolution: "@babel/plugin-transform-logical-assignment-operators@npm:7.27.1" +"@babel/plugin-transform-logical-assignment-operators@npm:^7.28.5": + version: 7.28.5 + resolution: "@babel/plugin-transform-logical-assignment-operators@npm:7.28.5" dependencies: "@babel/helper-plugin-utils": "npm:^7.27.1" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 10c0/5b0abc7c0d09d562bf555c646dce63a30288e5db46fd2ce809a61d064415da6efc3b2b3c59b8e4fe98accd072c89a2f7c3765b400e4bf488651735d314d9feeb + checksum: 10c0/fba4faa96d86fa745b0539bb631deee3f2296f0643c087a50ad0fac2e5f0a787fa885e9bdd90ae3e7832803f3c08e7cd3f1e830e7079dbdc023704923589bb23 languageName: node linkType: hard @@ -922,17 +1012,17 @@ __metadata: languageName: node linkType: hard -"@babel/plugin-transform-modules-systemjs@npm:^7.27.1": - version: 7.27.1 - resolution: "@babel/plugin-transform-modules-systemjs@npm:7.27.1" +"@babel/plugin-transform-modules-systemjs@npm:^7.28.5": + version: 7.28.5 + resolution: "@babel/plugin-transform-modules-systemjs@npm:7.28.5" dependencies: - "@babel/helper-module-transforms": "npm:^7.27.1" + "@babel/helper-module-transforms": "npm:^7.28.3" "@babel/helper-plugin-utils": "npm:^7.27.1" - "@babel/helper-validator-identifier": "npm:^7.27.1" - "@babel/traverse": "npm:^7.27.1" + "@babel/helper-validator-identifier": "npm:^7.28.5" + "@babel/traverse": "npm:^7.28.5" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 10c0/f16fca62d144d9cbf558e7b5f83e13bb6d0f21fdeff3024b0cecd42ffdec0b4151461da42bd0963512783ece31aafa5ffe03446b4869220ddd095b24d414e2b5 + checksum: 10c0/7e8c0bcff79689702b974f6a0fedb5d0c6eeb5a5e3384deb7028e7cfe92a5242cc80e981e9c1817aad29f2ecc01841753365dd38d877aa0b91737ceec2acfd07 languageName: node linkType: hard @@ -993,18 +1083,18 @@ __metadata: languageName: node linkType: hard -"@babel/plugin-transform-object-rest-spread@npm:^7.28.0": - version: 7.28.0 - resolution: "@babel/plugin-transform-object-rest-spread@npm:7.28.0" +"@babel/plugin-transform-object-rest-spread@npm:^7.28.4": + version: 7.28.4 + resolution: "@babel/plugin-transform-object-rest-spread@npm:7.28.4" dependencies: "@babel/helper-compilation-targets": "npm:^7.27.2" "@babel/helper-plugin-utils": "npm:^7.27.1" "@babel/plugin-transform-destructuring": "npm:^7.28.0" "@babel/plugin-transform-parameters": "npm:^7.27.7" - "@babel/traverse": "npm:^7.28.0" + "@babel/traverse": "npm:^7.28.4" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 10c0/360dc6fd5285ee5e1d3be8a1fb0decd120b2a1726800317b4ab48b7c91616247030239b7fa06ceaa1a8a586fde1e143c24d45f8d41956876099d97d664f8ef1e + checksum: 10c0/81725c8d6349957899975f3f789b1d4fb050ee8b04468ebfaccd5b59e0bda15cbfdef09aee8b4359f322b6715149d680361f11c1a420c4bdbac095537ecf7a90 languageName: node linkType: hard @@ -1043,6 +1133,18 @@ __metadata: languageName: node linkType: hard +"@babel/plugin-transform-optional-chaining@npm:^7.28.5": + version: 7.28.5 + resolution: "@babel/plugin-transform-optional-chaining@npm:7.28.5" + dependencies: + "@babel/helper-plugin-utils": "npm:^7.27.1" + "@babel/helper-skip-transparent-expression-wrappers": "npm:^7.27.1" + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 10c0/adf5f70b1f9eb0dd6ff3d159a714683af3c910775653e667bd9f864c3dc2dc9872aba95f6c1e5f2a9675067241942f4fd0d641147ef4bf2bd8bc15f1fa0f2ed5 + languageName: node + linkType: hard + "@babel/plugin-transform-parameters@npm:^7.27.7": version: 7.27.7 resolution: "@babel/plugin-transform-parameters@npm:7.27.7" @@ -1090,14 +1192,14 @@ __metadata: languageName: node linkType: hard -"@babel/plugin-transform-react-display-name@npm:^7.27.1": - version: 7.27.1 - resolution: "@babel/plugin-transform-react-display-name@npm:7.27.1" +"@babel/plugin-transform-react-display-name@npm:^7.28.0": + version: 7.28.0 + resolution: "@babel/plugin-transform-react-display-name@npm:7.28.0" dependencies: "@babel/helper-plugin-utils": "npm:^7.27.1" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 10c0/6cd474b5fb30a2255027d8fc19975aee1c1da54dd8bc8b79802676096182ca4136302ce65a24fbb277f8fe30f266006bbf327ef6be2846d3681eb57509744125 + checksum: 10c0/f5f86d2ad92be3e962158f344c2e385e23e2dfae7c8c7dc32138fb2cc46f63f5e50386c9f6c6fc16dbf1792c7bb650ad92c18203d0c2c0bd875bc28b0b80ef30 languageName: node linkType: hard @@ -1161,14 +1263,14 @@ __metadata: languageName: node linkType: hard -"@babel/plugin-transform-regenerator@npm:^7.28.0": - version: 7.28.1 - resolution: "@babel/plugin-transform-regenerator@npm:7.28.1" +"@babel/plugin-transform-regenerator@npm:^7.28.4": + version: 7.28.4 + resolution: "@babel/plugin-transform-regenerator@npm:7.28.4" dependencies: "@babel/helper-plugin-utils": "npm:^7.27.1" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 10c0/6c9e6eb80ce9c0bde0876c80979e078fbc85dc802272cba4ee72b5b1c858472e38167c418917e4f0d4384ce888706d95544a8d266880c0e199e167e078168b67 + checksum: 10c0/5ad14647ffaac63c920e28df1b580ee2e932586bbdc71f61ec264398f68a5406c71a7f921de397a41b954a69316c5ab90e5d789ffa2bb34c5e6feb3727cfefb8 languageName: node linkType: hard @@ -1251,18 +1353,18 @@ __metadata: languageName: node linkType: hard -"@babel/plugin-transform-typescript@npm:^7.27.1": - version: 7.27.1 - resolution: "@babel/plugin-transform-typescript@npm:7.27.1" +"@babel/plugin-transform-typescript@npm:^7.28.5": + version: 7.28.5 + resolution: "@babel/plugin-transform-typescript@npm:7.28.5" dependencies: - "@babel/helper-annotate-as-pure": "npm:^7.27.1" - "@babel/helper-create-class-features-plugin": "npm:^7.27.1" + "@babel/helper-annotate-as-pure": "npm:^7.27.3" + "@babel/helper-create-class-features-plugin": "npm:^7.28.5" "@babel/helper-plugin-utils": "npm:^7.27.1" "@babel/helper-skip-transparent-expression-wrappers": "npm:^7.27.1" "@babel/plugin-syntax-typescript": "npm:^7.27.1" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 10c0/48f1db5de17a0f9fc365ff4fb046010aedc7aad813a7aa42fb73fcdab6442f9e700dde2cc0481086e01b0dae662ae4d3e965a52cde154f0f146d243a8ac68e93 + checksum: 10c0/09e574ba5462e56452b4ceecae65e53c8e697a2d3559ce5d210bed10ac28a18aa69377e7550c30520eb29b40c417ee61997d5d58112657f22983244b78915a7c languageName: node linkType: hard @@ -1314,18 +1416,18 @@ __metadata: linkType: hard "@babel/preset-env@npm:^7.22.20": - version: 7.28.0 - resolution: "@babel/preset-env@npm:7.28.0" + version: 7.28.5 + resolution: "@babel/preset-env@npm:7.28.5" dependencies: - "@babel/compat-data": "npm:^7.28.0" + "@babel/compat-data": "npm:^7.28.5" "@babel/helper-compilation-targets": "npm:^7.27.2" "@babel/helper-plugin-utils": "npm:^7.27.1" "@babel/helper-validator-option": "npm:^7.27.1" - "@babel/plugin-bugfix-firefox-class-in-computed-class-key": "npm:^7.27.1" + "@babel/plugin-bugfix-firefox-class-in-computed-class-key": "npm:^7.28.5" "@babel/plugin-bugfix-safari-class-field-initializer-scope": "npm:^7.27.1" "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "npm:^7.27.1" "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "npm:^7.27.1" - "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": "npm:^7.27.1" + "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": "npm:^7.28.3" "@babel/plugin-proposal-private-property-in-object": "npm:7.21.0-placeholder-for-preset-env.2" "@babel/plugin-syntax-import-assertions": "npm:^7.27.1" "@babel/plugin-syntax-import-attributes": "npm:^7.27.1" @@ -1334,42 +1436,42 @@ __metadata: "@babel/plugin-transform-async-generator-functions": "npm:^7.28.0" "@babel/plugin-transform-async-to-generator": "npm:^7.27.1" "@babel/plugin-transform-block-scoped-functions": "npm:^7.27.1" - "@babel/plugin-transform-block-scoping": "npm:^7.28.0" + "@babel/plugin-transform-block-scoping": "npm:^7.28.5" "@babel/plugin-transform-class-properties": "npm:^7.27.1" - "@babel/plugin-transform-class-static-block": "npm:^7.27.1" - "@babel/plugin-transform-classes": "npm:^7.28.0" + "@babel/plugin-transform-class-static-block": "npm:^7.28.3" + "@babel/plugin-transform-classes": "npm:^7.28.4" "@babel/plugin-transform-computed-properties": "npm:^7.27.1" - "@babel/plugin-transform-destructuring": "npm:^7.28.0" + "@babel/plugin-transform-destructuring": "npm:^7.28.5" "@babel/plugin-transform-dotall-regex": "npm:^7.27.1" "@babel/plugin-transform-duplicate-keys": "npm:^7.27.1" "@babel/plugin-transform-duplicate-named-capturing-groups-regex": "npm:^7.27.1" "@babel/plugin-transform-dynamic-import": "npm:^7.27.1" "@babel/plugin-transform-explicit-resource-management": "npm:^7.28.0" - "@babel/plugin-transform-exponentiation-operator": "npm:^7.27.1" + "@babel/plugin-transform-exponentiation-operator": "npm:^7.28.5" "@babel/plugin-transform-export-namespace-from": "npm:^7.27.1" "@babel/plugin-transform-for-of": "npm:^7.27.1" "@babel/plugin-transform-function-name": "npm:^7.27.1" "@babel/plugin-transform-json-strings": "npm:^7.27.1" "@babel/plugin-transform-literals": "npm:^7.27.1" - "@babel/plugin-transform-logical-assignment-operators": "npm:^7.27.1" + "@babel/plugin-transform-logical-assignment-operators": "npm:^7.28.5" "@babel/plugin-transform-member-expression-literals": "npm:^7.27.1" "@babel/plugin-transform-modules-amd": "npm:^7.27.1" "@babel/plugin-transform-modules-commonjs": "npm:^7.27.1" - "@babel/plugin-transform-modules-systemjs": "npm:^7.27.1" + "@babel/plugin-transform-modules-systemjs": "npm:^7.28.5" "@babel/plugin-transform-modules-umd": "npm:^7.27.1" "@babel/plugin-transform-named-capturing-groups-regex": "npm:^7.27.1" "@babel/plugin-transform-new-target": "npm:^7.27.1" "@babel/plugin-transform-nullish-coalescing-operator": "npm:^7.27.1" "@babel/plugin-transform-numeric-separator": "npm:^7.27.1" - "@babel/plugin-transform-object-rest-spread": "npm:^7.28.0" + "@babel/plugin-transform-object-rest-spread": "npm:^7.28.4" "@babel/plugin-transform-object-super": "npm:^7.27.1" "@babel/plugin-transform-optional-catch-binding": "npm:^7.27.1" - "@babel/plugin-transform-optional-chaining": "npm:^7.27.1" + "@babel/plugin-transform-optional-chaining": "npm:^7.28.5" "@babel/plugin-transform-parameters": "npm:^7.27.7" "@babel/plugin-transform-private-methods": "npm:^7.27.1" "@babel/plugin-transform-private-property-in-object": "npm:^7.27.1" "@babel/plugin-transform-property-literals": "npm:^7.27.1" - "@babel/plugin-transform-regenerator": "npm:^7.28.0" + "@babel/plugin-transform-regenerator": "npm:^7.28.4" "@babel/plugin-transform-regexp-modifiers": "npm:^7.27.1" "@babel/plugin-transform-reserved-words": "npm:^7.27.1" "@babel/plugin-transform-shorthand-properties": "npm:^7.27.1" @@ -1389,7 +1491,7 @@ __metadata: semver: "npm:^6.3.1" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 10c0/f343103b8f0e8da5be4ae031aff8bf35da4764997af4af78ae9506f421b785dd45da1bc09f845b1fc308c8b7d134aead4a1f89e7fb6e213cd2f9fe1d2aa78bc9 + checksum: 10c0/d1b730158de290f1c54ed7db0f4fed3f82db5f868ab0a4cb3fc2ea76ed683b986ae136f6e7eb0b44b91bc9a99039a2559851656b4fd50193af1a815a3e32e524 languageName: node linkType: hard @@ -1407,33 +1509,33 @@ __metadata: linkType: hard "@babel/preset-react@npm:^7.22.15": - version: 7.27.1 - resolution: "@babel/preset-react@npm:7.27.1" + version: 7.28.5 + resolution: "@babel/preset-react@npm:7.28.5" dependencies: "@babel/helper-plugin-utils": "npm:^7.27.1" "@babel/helper-validator-option": "npm:^7.27.1" - "@babel/plugin-transform-react-display-name": "npm:^7.27.1" + "@babel/plugin-transform-react-display-name": "npm:^7.28.0" "@babel/plugin-transform-react-jsx": "npm:^7.27.1" "@babel/plugin-transform-react-jsx-development": "npm:^7.27.1" "@babel/plugin-transform-react-pure-annotations": "npm:^7.27.1" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 10c0/a80b02ef08b026cb9830d6512d08c7cd378eef4c0631dacba4aa1106240d9bb76af6373463f0255f4bbdbfcce40375a61e92735375906ba5871629b0c314bc45 + checksum: 10c0/0d785e708ff301f4102bd4738b77e550e32f981e54dfd3de1191b4d68306bbb934d2d465fc78a6bc22fff0a6b3ce3195a53984f52755c4349e7264c7e01e8c7c languageName: node linkType: hard "@babel/preset-typescript@npm:^7.23.0": - version: 7.27.1 - resolution: "@babel/preset-typescript@npm:7.27.1" + version: 7.28.5 + resolution: "@babel/preset-typescript@npm:7.28.5" dependencies: "@babel/helper-plugin-utils": "npm:^7.27.1" "@babel/helper-validator-option": "npm:^7.27.1" "@babel/plugin-syntax-jsx": "npm:^7.27.1" "@babel/plugin-transform-modules-commonjs": "npm:^7.27.1" - "@babel/plugin-transform-typescript": "npm:^7.27.1" + "@babel/plugin-transform-typescript": "npm:^7.28.5" peerDependencies: "@babel/core": ^7.0.0-0 - checksum: 10c0/cba6ca793d915f8aff9fe2f13b0dfbf5fd3f2e9a17f17478ec9878e9af0d206dcfe93154b9fd353727f16c1dca7c7a3ceb4943f8d28b216235f106bc0fbbcaa3 + checksum: 10c0/b3d55548854c105085dd80f638147aa8295bc186d70492289242d6c857cb03a6c61ec15186440ea10ed4a71cdde7d495f5eb3feda46273f36b0ac926e8409629 languageName: node linkType: hard @@ -1545,6 +1647,21 @@ __metadata: languageName: node linkType: hard +"@babel/traverse@npm:^7.28.3, @babel/traverse@npm:^7.28.4, @babel/traverse@npm:^7.28.5": + version: 7.28.5 + resolution: "@babel/traverse@npm:7.28.5" + dependencies: + "@babel/code-frame": "npm:^7.27.1" + "@babel/generator": "npm:^7.28.5" + "@babel/helper-globals": "npm:^7.28.0" + "@babel/parser": "npm:^7.28.5" + "@babel/template": "npm:^7.27.2" + "@babel/types": "npm:^7.28.5" + debug: "npm:^4.3.1" + checksum: 10c0/f6c4a595993ae2b73f2d4cd9c062f2e232174d293edd4abe1d715bd6281da8d99e47c65857e8d0917d9384c65972f4acdebc6749a7c40a8fcc38b3c7fb3e706f + languageName: node + linkType: hard + "@babel/types@npm:^7.0.0, @babel/types@npm:^7.10.3, @babel/types@npm:^7.20.7, @babel/types@npm:^7.21.3": version: 7.26.0 resolution: "@babel/types@npm:7.26.0" @@ -1585,16 +1702,6 @@ __metadata: languageName: node linkType: hard -"@babel/types@npm:^7.27.6": - version: 7.27.7 - resolution: "@babel/types@npm:7.27.7" - dependencies: - "@babel/helper-string-parser": "npm:^7.27.1" - "@babel/helper-validator-identifier": "npm:^7.27.1" - checksum: 10c0/1d1dcb5fa7cfba2b4034a3ab99ba17049bfc4af9e170935575246cdb1cee68b04329a0111506d9ae83fb917c47dbd4394a6db5e32fbd041b7834ffbb17ca086b - languageName: node - linkType: hard - "@babel/types@npm:^7.28.0": version: 7.28.2 resolution: "@babel/types@npm:7.28.2" @@ -1605,6 +1712,16 @@ __metadata: languageName: node linkType: hard +"@babel/types@npm:^7.28.4, @babel/types@npm:^7.28.5": + version: 7.28.5 + resolution: "@babel/types@npm:7.28.5" + dependencies: + "@babel/helper-string-parser": "npm:^7.27.1" + "@babel/helper-validator-identifier": "npm:^7.28.5" + checksum: 10c0/a5a483d2100befbf125793640dec26b90b95fd233a94c19573325898a5ce1e52cdfa96e495c7dcc31b5eca5b66ce3e6d4a0f5a4a62daec271455959f208ab08a + languageName: node + linkType: hard + "@bcoe/v8-coverage@npm:^1.0.2": version: 1.0.2 resolution: "@bcoe/v8-coverage@npm:1.0.2" @@ -1662,10 +1779,10 @@ __metadata: languageName: node linkType: hard -"@csstools/color-helpers@npm:^5.0.2": - version: 5.0.2 - resolution: "@csstools/color-helpers@npm:5.0.2" - checksum: 10c0/bebaddb28b9eb58b0449edd5d0c0318fa88f3cb079602ee27e88c9118070d666dcc4e09a5aa936aba2fde6ba419922ade07b7b506af97dd7051abd08dfb2959b +"@csstools/color-helpers@npm:^5.1.0": + version: 5.1.0 + resolution: "@csstools/color-helpers@npm:5.1.0" + checksum: 10c0/b7f99d2e455cf1c9b41a67a5327d5d02888cd5c8802a68b1887dffef537d9d4bc66b3c10c1e62b40bbed638b6c1d60b85a232f904ed7b39809c4029cb36567db languageName: node linkType: hard @@ -1689,19 +1806,6 @@ __metadata: languageName: node linkType: hard -"@csstools/css-color-parser@npm:^3.0.10": - version: 3.0.10 - resolution: "@csstools/css-color-parser@npm:3.0.10" - dependencies: - "@csstools/color-helpers": "npm:^5.0.2" - "@csstools/css-calc": "npm:^2.1.4" - peerDependencies: - "@csstools/css-parser-algorithms": ^3.0.5 - "@csstools/css-tokenizer": ^3.0.4 - checksum: 10c0/8f8a2395b117c2f09366b5c9bf49bc740c92a65b6330fe3cc1e76abafd0d1000e42a657d7b0a3814846a66f1d69896142f7e36d7a4aca77de977e5cc5f944747 - languageName: node - linkType: hard - "@csstools/css-color-parser@npm:^3.0.7": version: 3.0.7 resolution: "@csstools/css-color-parser@npm:3.0.7" @@ -1715,6 +1819,19 @@ __metadata: languageName: node linkType: hard +"@csstools/css-color-parser@npm:^3.1.0": + version: 3.1.0 + resolution: "@csstools/css-color-parser@npm:3.1.0" + dependencies: + "@csstools/color-helpers": "npm:^5.1.0" + "@csstools/css-calc": "npm:^2.1.4" + peerDependencies: + "@csstools/css-parser-algorithms": ^3.0.5 + "@csstools/css-tokenizer": ^3.0.4 + checksum: 10c0/0e0c670ad54ec8ec4d9b07568b80defd83b9482191f5e8ca84ab546b7be6db5d7cc2ba7ac9fae54488b129a4be235d6183d3aab4416fec5e89351f73af4222c5 + languageName: node + linkType: hard + "@csstools/css-parser-algorithms@npm:^3.0.4": version: 3.0.4 resolution: "@csstools/css-parser-algorithms@npm:3.0.4" @@ -1757,6 +1874,21 @@ __metadata: languageName: node linkType: hard +"@csstools/postcss-alpha-function@npm:^1.0.1": + version: 1.0.1 + resolution: "@csstools/postcss-alpha-function@npm:1.0.1" + dependencies: + "@csstools/css-color-parser": "npm:^3.1.0" + "@csstools/css-parser-algorithms": "npm:^3.0.5" + "@csstools/css-tokenizer": "npm:^3.0.4" + "@csstools/postcss-progressive-custom-properties": "npm:^4.2.1" + "@csstools/utilities": "npm:^2.0.0" + peerDependencies: + postcss: ^8.4 + checksum: 10c0/35ca209e572534ade21ac5c18aad702aa492eb39e2d0e475f441371063418fe9650554e6a59b1318d3a615da83ef54d9a588faa27063ecc0a568ef7290a6b488 + languageName: node + linkType: hard + "@csstools/postcss-cascade-layers@npm:^5.0.2": version: 5.0.2 resolution: "@csstools/postcss-cascade-layers@npm:5.0.2" @@ -1769,62 +1901,92 @@ __metadata: languageName: node linkType: hard -"@csstools/postcss-color-function@npm:^4.0.10": - version: 4.0.10 - resolution: "@csstools/postcss-color-function@npm:4.0.10" +"@csstools/postcss-color-function-display-p3-linear@npm:^1.0.1": + version: 1.0.1 + resolution: "@csstools/postcss-color-function-display-p3-linear@npm:1.0.1" dependencies: - "@csstools/css-color-parser": "npm:^3.0.10" + "@csstools/css-color-parser": "npm:^3.1.0" "@csstools/css-parser-algorithms": "npm:^3.0.5" "@csstools/css-tokenizer": "npm:^3.0.4" - "@csstools/postcss-progressive-custom-properties": "npm:^4.1.0" + "@csstools/postcss-progressive-custom-properties": "npm:^4.2.1" "@csstools/utilities": "npm:^2.0.0" peerDependencies: postcss: ^8.4 - checksum: 10c0/a6e65d37a114f95634a07660daa1aa52f4abfb6ddd740cc9267967a5948f5c72469a6ba2432ab1f31616d6f1a4ab963b69f778497496986535831b0b2b399f75 + checksum: 10c0/d02d45410c9257f5620c766f861f8fa3762b74ef01fdba8060b33a4c98f929e2219cd476b25bd4181ac186158a4d99a0da555c0b6ba45a7ac4a3a5885baad1f5 languageName: node linkType: hard -"@csstools/postcss-color-mix-function@npm:^3.0.10": - version: 3.0.10 - resolution: "@csstools/postcss-color-mix-function@npm:3.0.10" +"@csstools/postcss-color-function@npm:^4.0.12": + version: 4.0.12 + resolution: "@csstools/postcss-color-function@npm:4.0.12" dependencies: - "@csstools/css-color-parser": "npm:^3.0.10" + "@csstools/css-color-parser": "npm:^3.1.0" "@csstools/css-parser-algorithms": "npm:^3.0.5" "@csstools/css-tokenizer": "npm:^3.0.4" - "@csstools/postcss-progressive-custom-properties": "npm:^4.1.0" + "@csstools/postcss-progressive-custom-properties": "npm:^4.2.1" "@csstools/utilities": "npm:^2.0.0" peerDependencies: postcss: ^8.4 - checksum: 10c0/9505a09a805f52555bd06c8f54d537a99578efe5c7e643c9fdaca8cbb7d74d4d3e07b829c6aed315c75ec5ce113261fb402e01b67e4a423ed39ea8991a6dded0 + checksum: 10c0/a355b04d90f89c8e37a4a23543151558060acc68fb2e7d1c3549bebeeae2b147eec26af1fbc6ee690f0ba4830263f2d181f5331d16d3483b5542be46996fa755 languageName: node linkType: hard -"@csstools/postcss-color-mix-variadic-function-arguments@npm:^1.0.0": - version: 1.0.0 - resolution: "@csstools/postcss-color-mix-variadic-function-arguments@npm:1.0.0" +"@csstools/postcss-color-mix-function@npm:^3.0.12": + version: 3.0.12 + resolution: "@csstools/postcss-color-mix-function@npm:3.0.12" dependencies: - "@csstools/css-color-parser": "npm:^3.0.10" + "@csstools/css-color-parser": "npm:^3.1.0" "@csstools/css-parser-algorithms": "npm:^3.0.5" "@csstools/css-tokenizer": "npm:^3.0.4" - "@csstools/postcss-progressive-custom-properties": "npm:^4.1.0" + "@csstools/postcss-progressive-custom-properties": "npm:^4.2.1" "@csstools/utilities": "npm:^2.0.0" peerDependencies: postcss: ^8.4 - checksum: 10c0/dd45bd19931cc4780247173b793e5f1e6409b76f92b04fe26e07b0fa048aedc7bcbd92356a558581f695654c2f2d189e1b40b14a9c3f246e86e83b0edf646066 + checksum: 10c0/3e98a5118852083d1f87a3f842f78088192b1f9f08fdf1f3b3ef1e8969e18fdadc1e3bcac3d113a07c8917a7e8fa65fdec55a31df9a1b726c8d7ae89db86e8e5 languageName: node linkType: hard -"@csstools/postcss-content-alt-text@npm:^2.0.6": - version: 2.0.6 - resolution: "@csstools/postcss-content-alt-text@npm:2.0.6" +"@csstools/postcss-color-mix-variadic-function-arguments@npm:^1.0.2": + version: 1.0.2 + resolution: "@csstools/postcss-color-mix-variadic-function-arguments@npm:1.0.2" dependencies: + "@csstools/css-color-parser": "npm:^3.1.0" "@csstools/css-parser-algorithms": "npm:^3.0.5" "@csstools/css-tokenizer": "npm:^3.0.4" - "@csstools/postcss-progressive-custom-properties": "npm:^4.1.0" + "@csstools/postcss-progressive-custom-properties": "npm:^4.2.1" "@csstools/utilities": "npm:^2.0.0" peerDependencies: postcss: ^8.4 - checksum: 10c0/e7d21002a84d0fba4fe815fb7d3d19b81fb1719a7b6fdd240eb6639d58937b64d6f5c9aa11ffe8a64891a2ed181818cd56d346f58949c2eaa9df7c82ee95ef8e + checksum: 10c0/34073f0f0d33e4958f90763e692955a8e8c678b74284234497c4aa0d2143756e1b3616e0c09832caad498870e227ca0a681316afe3a71224fc40ade0ead1bdd9 + languageName: node + linkType: hard + +"@csstools/postcss-content-alt-text@npm:^2.0.8": + version: 2.0.8 + resolution: "@csstools/postcss-content-alt-text@npm:2.0.8" + dependencies: + "@csstools/css-parser-algorithms": "npm:^3.0.5" + "@csstools/css-tokenizer": "npm:^3.0.4" + "@csstools/postcss-progressive-custom-properties": "npm:^4.2.1" + "@csstools/utilities": "npm:^2.0.0" + peerDependencies: + postcss: ^8.4 + checksum: 10c0/4c330cc2a1e434688a62613ecceb1434cd725ce024c1ad8d4a4c76b9839d1f3ea8566a8c6494921e2b46ec7feef6af8ed6548c216dcb8f0feab4b1d52c96228e + languageName: node + linkType: hard + +"@csstools/postcss-contrast-color-function@npm:^2.0.12": + version: 2.0.12 + resolution: "@csstools/postcss-contrast-color-function@npm:2.0.12" + dependencies: + "@csstools/css-color-parser": "npm:^3.1.0" + "@csstools/css-parser-algorithms": "npm:^3.0.5" + "@csstools/css-tokenizer": "npm:^3.0.4" + "@csstools/postcss-progressive-custom-properties": "npm:^4.2.1" + "@csstools/utilities": "npm:^2.0.0" + peerDependencies: + postcss: ^8.4 + checksum: 10c0/b783ce948cdf1513ee238e9115b42881a8d3e5d13c16038601b1c470d661cfaeeece4eea29904fb9fcae878bad86f766810fa798a703ab9ad4b0cf276b173f8f languageName: node linkType: hard @@ -1853,59 +2015,59 @@ __metadata: languageName: node linkType: hard -"@csstools/postcss-gamut-mapping@npm:^2.0.10": - version: 2.0.10 - resolution: "@csstools/postcss-gamut-mapping@npm:2.0.10" +"@csstools/postcss-gamut-mapping@npm:^2.0.11": + version: 2.0.11 + resolution: "@csstools/postcss-gamut-mapping@npm:2.0.11" dependencies: - "@csstools/css-color-parser": "npm:^3.0.10" + "@csstools/css-color-parser": "npm:^3.1.0" "@csstools/css-parser-algorithms": "npm:^3.0.5" "@csstools/css-tokenizer": "npm:^3.0.4" peerDependencies: postcss: ^8.4 - checksum: 10c0/87cd8289478bf88195469fcf4f80c8fed9e0e5ef76a335a10c4c21582542acb16cced1e00e7da90deaf2e62e383a5c6fe402f429f227c87a2c20e2545a69c537 + checksum: 10c0/490b8ccf10e30879a4415afbdd3646e1cdac3671586b7916855cf47a536f3be75eed014396056bde6528e0cb76d904e79bad78afc0b499e837264cf22519d145 languageName: node linkType: hard -"@csstools/postcss-gradients-interpolation-method@npm:^5.0.10": - version: 5.0.10 - resolution: "@csstools/postcss-gradients-interpolation-method@npm:5.0.10" +"@csstools/postcss-gradients-interpolation-method@npm:^5.0.12": + version: 5.0.12 + resolution: "@csstools/postcss-gradients-interpolation-method@npm:5.0.12" dependencies: - "@csstools/css-color-parser": "npm:^3.0.10" + "@csstools/css-color-parser": "npm:^3.1.0" "@csstools/css-parser-algorithms": "npm:^3.0.5" "@csstools/css-tokenizer": "npm:^3.0.4" - "@csstools/postcss-progressive-custom-properties": "npm:^4.1.0" + "@csstools/postcss-progressive-custom-properties": "npm:^4.2.1" "@csstools/utilities": "npm:^2.0.0" peerDependencies: postcss: ^8.4 - checksum: 10c0/206d079d7679a9609a4fb227ddaf3443d04cff88b55bcfec1cf63c9de372b8720edde8614fc51d2237e4edbff8ce34697f912bc25c2ae41390353fce88455515 + checksum: 10c0/70b3d6c7050ce882ed2281e71eb4493531ae8d55d21899920eeeb6c205d90aaf430419a66235484ccce3a1a1891367dfc0ef772f3866ae3a9d8ec5ddd0cfe894 languageName: node linkType: hard -"@csstools/postcss-hwb-function@npm:^4.0.10": - version: 4.0.10 - resolution: "@csstools/postcss-hwb-function@npm:4.0.10" +"@csstools/postcss-hwb-function@npm:^4.0.12": + version: 4.0.12 + resolution: "@csstools/postcss-hwb-function@npm:4.0.12" dependencies: - "@csstools/css-color-parser": "npm:^3.0.10" + "@csstools/css-color-parser": "npm:^3.1.0" "@csstools/css-parser-algorithms": "npm:^3.0.5" "@csstools/css-tokenizer": "npm:^3.0.4" - "@csstools/postcss-progressive-custom-properties": "npm:^4.1.0" + "@csstools/postcss-progressive-custom-properties": "npm:^4.2.1" "@csstools/utilities": "npm:^2.0.0" peerDependencies: postcss: ^8.4 - checksum: 10c0/defb9b319b14228307196b9a88e3cbf0acd1d3768b936716dca846875068ad4453e7a2a3d75d1fab5534c8655e9c555e1fa70d30e2c85d68ed2117a7cfe7837c + checksum: 10c0/d0dac34da9d7ac654060b6b27690a419718e990b21ff3e63266ea59934a865bc6aeae8eb8e1ca3e227a8b2a208657e3ab70ccdf0437f1f09d21ab848bbffcaa2 languageName: node linkType: hard -"@csstools/postcss-ic-unit@npm:^4.0.2": - version: 4.0.2 - resolution: "@csstools/postcss-ic-unit@npm:4.0.2" +"@csstools/postcss-ic-unit@npm:^4.0.4": + version: 4.0.4 + resolution: "@csstools/postcss-ic-unit@npm:4.0.4" dependencies: - "@csstools/postcss-progressive-custom-properties": "npm:^4.1.0" + "@csstools/postcss-progressive-custom-properties": "npm:^4.2.1" "@csstools/utilities": "npm:^2.0.0" postcss-value-parser: "npm:^4.2.0" peerDependencies: postcss: ^8.4 - checksum: 10c0/26adb8351143e591080f542d87b223ee5ebc5f33f6d03b217505b249ceb19c46a06732a88000e3a1857ae712a6ea0ffa089a24ad8b8042421490539de5c3d0e8 + checksum: 10c0/20168e70ecb4abf7a69e407d653b6c7c9c82f2c7b1da0920e1d035f62b5ef8552cc7f1b62e0dca318df13c348e79fba862e1a4bb0e9432119a82b10aeb511752 languageName: node linkType: hard @@ -1930,17 +2092,17 @@ __metadata: languageName: node linkType: hard -"@csstools/postcss-light-dark-function@npm:^2.0.9": - version: 2.0.9 - resolution: "@csstools/postcss-light-dark-function@npm:2.0.9" +"@csstools/postcss-light-dark-function@npm:^2.0.11": + version: 2.0.11 + resolution: "@csstools/postcss-light-dark-function@npm:2.0.11" dependencies: "@csstools/css-parser-algorithms": "npm:^3.0.5" "@csstools/css-tokenizer": "npm:^3.0.4" - "@csstools/postcss-progressive-custom-properties": "npm:^4.1.0" + "@csstools/postcss-progressive-custom-properties": "npm:^4.2.1" "@csstools/utilities": "npm:^2.0.0" peerDependencies: postcss: ^8.4 - checksum: 10c0/ee2937f0e5dcaafd10349f0914596e8e1ef6f9d46939c6a6b0e2e63cab0552594e5140bf56e485048c3bca6634dd9673a176c57b9e77001332787f4263835c0f + checksum: 10c0/0175be41bb0044a48bc98d5c55cce41ed6b9ada88253c5f20d0ca17287cba4b429742b458ac5744675b9a286109e13ac51d64e226ab16040d7b051ba64c0c77b languageName: node linkType: hard @@ -2044,29 +2206,50 @@ __metadata: languageName: node linkType: hard -"@csstools/postcss-oklab-function@npm:^4.0.10": - version: 4.0.10 - resolution: "@csstools/postcss-oklab-function@npm:4.0.10" +"@csstools/postcss-oklab-function@npm:^4.0.12": + version: 4.0.12 + resolution: "@csstools/postcss-oklab-function@npm:4.0.12" dependencies: - "@csstools/css-color-parser": "npm:^3.0.10" + "@csstools/css-color-parser": "npm:^3.1.0" "@csstools/css-parser-algorithms": "npm:^3.0.5" "@csstools/css-tokenizer": "npm:^3.0.4" - "@csstools/postcss-progressive-custom-properties": "npm:^4.1.0" + "@csstools/postcss-progressive-custom-properties": "npm:^4.2.1" "@csstools/utilities": "npm:^2.0.0" peerDependencies: postcss: ^8.4 - checksum: 10c0/421d1f2574941c3caecd608588533581fc0766998cc85474008a49b5f1011249cb2be7ef9f21a346fd3895598da18e58860fde06d34b1b833918fa880c41c18f + checksum: 10c0/40d4f51b568c8299c054f8971d0e85fa7da609ba23ce6c84dc17e16bc3838640ed6da75c3886dc9a96a11005773c6e23cba13a5510c781b2d633d07ad7bda6b7 languageName: node linkType: hard -"@csstools/postcss-progressive-custom-properties@npm:^4.1.0": - version: 4.1.0 - resolution: "@csstools/postcss-progressive-custom-properties@npm:4.1.0" +"@csstools/postcss-position-area-property@npm:^1.0.0": + version: 1.0.0 + resolution: "@csstools/postcss-position-area-property@npm:1.0.0" + peerDependencies: + postcss: ^8.4 + checksum: 10c0/38f770454d46bfed01d43a3f5e7ac07d3111399b374a7198ae6503cdb6288e410c7b4199f5a7af8f16aeb688216445ade97be417c084313d6c56f55e50d34559 + languageName: node + linkType: hard + +"@csstools/postcss-progressive-custom-properties@npm:^4.2.1": + version: 4.2.1 + resolution: "@csstools/postcss-progressive-custom-properties@npm:4.2.1" dependencies: postcss-value-parser: "npm:^4.2.0" peerDependencies: postcss: ^8.4 - checksum: 10c0/175081a5c53e37a282f596e01359d4411800e4017c2d389caaa2b7c9b7507a50c5f1ac3d937f27f000be3ac2ac788cad9c1490ec6bc1d4de51331f3cc8ccda8e + checksum: 10c0/56e9a147799719fd5c550c035437693dd50cdfef46d66a4f2ce8f196e1006a096aa47d412710a89c3dc9808068a0a101c7f607a507ed68e925580c6f921e84d5 + languageName: node + linkType: hard + +"@csstools/postcss-property-rule-prelude-list@npm:^1.0.0": + version: 1.0.0 + resolution: "@csstools/postcss-property-rule-prelude-list@npm:1.0.0" + dependencies: + "@csstools/css-parser-algorithms": "npm:^3.0.5" + "@csstools/css-tokenizer": "npm:^3.0.4" + peerDependencies: + postcss: ^8.4 + checksum: 10c0/ae8bbca3a77ca59c21c11899a904f9d9417a19a3359d01dee042e0489b7ddfe7cea13ae275b7e7936d9b0b99c0a13f7f685f962cd63ca3d3d2b6e5eacc293a0d languageName: node linkType: hard @@ -2083,18 +2266,18 @@ __metadata: languageName: node linkType: hard -"@csstools/postcss-relative-color-syntax@npm:^3.0.10": - version: 3.0.10 - resolution: "@csstools/postcss-relative-color-syntax@npm:3.0.10" +"@csstools/postcss-relative-color-syntax@npm:^3.0.12": + version: 3.0.12 + resolution: "@csstools/postcss-relative-color-syntax@npm:3.0.12" dependencies: - "@csstools/css-color-parser": "npm:^3.0.10" + "@csstools/css-color-parser": "npm:^3.1.0" "@csstools/css-parser-algorithms": "npm:^3.0.5" "@csstools/css-tokenizer": "npm:^3.0.4" - "@csstools/postcss-progressive-custom-properties": "npm:^4.1.0" + "@csstools/postcss-progressive-custom-properties": "npm:^4.2.1" "@csstools/utilities": "npm:^2.0.0" peerDependencies: postcss: ^8.4 - checksum: 10c0/de9c41a936a77dab68cdb2dd23a26ba1b92d90bf2a7cf463fada2f2daf6ad0d7394fa2b1ed444f509006992961d993383a34a9afd3a48a9dc67a3793afcd9bb8 + checksum: 10c0/11af386c8193e22c148ac034eee94c56da3060bdbde3196d2d641b088e12de35bef187bcd7d421f9e4d49c4f1cfc28b24e136e62107e02ed7007a3a28f635d06 languageName: node linkType: hard @@ -2135,15 +2318,38 @@ __metadata: languageName: node linkType: hard -"@csstools/postcss-text-decoration-shorthand@npm:^4.0.2": - version: 4.0.2 - resolution: "@csstools/postcss-text-decoration-shorthand@npm:4.0.2" +"@csstools/postcss-syntax-descriptor-syntax-production@npm:^1.0.1": + version: 1.0.1 + resolution: "@csstools/postcss-syntax-descriptor-syntax-production@npm:1.0.1" dependencies: - "@csstools/color-helpers": "npm:^5.0.2" + "@csstools/css-tokenizer": "npm:^3.0.4" + peerDependencies: + postcss: ^8.4 + checksum: 10c0/b9b3d84a50b86b1af1b8b7e56a64d5eebc1c89c323a5263306c5c69ddb05a4d468d7072a7786b0ea6601629035df0089565e9d98d55d0f4eb7201cf7ed1bb3e9 + languageName: node + linkType: hard + +"@csstools/postcss-system-ui-font-family@npm:^1.0.0": + version: 1.0.0 + resolution: "@csstools/postcss-system-ui-font-family@npm:1.0.0" + dependencies: + "@csstools/css-parser-algorithms": "npm:^3.0.5" + "@csstools/css-tokenizer": "npm:^3.0.4" + peerDependencies: + postcss: ^8.4 + checksum: 10c0/6a81761ae3cae643659b1416a7a892cf1505474896193b8abc26cff319cb6b1a20b64c5330d64019fba458e058da3abc9407d0ebf0c102289c0b79ef99b4c6d6 + languageName: node + linkType: hard + +"@csstools/postcss-text-decoration-shorthand@npm:^4.0.3": + version: 4.0.3 + resolution: "@csstools/postcss-text-decoration-shorthand@npm:4.0.3" + dependencies: + "@csstools/color-helpers": "npm:^5.1.0" postcss-value-parser: "npm:^4.2.0" peerDependencies: postcss: ^8.4 - checksum: 10c0/01e2f3717e7a42224dc1a746491c55a381cf208cb7588f0308eeefe730675be4c7bb56c0cc557e75999c981e67da7d0b0bb68610635752c89ef251ee435b9cac + checksum: 10c0/f6af7d5dcf599edcf76c5e396ef2d372bbe1c1f3fbaaccd91e91049e64b6ff68b44f459277aef0a8110baca3eaa21275012adc52ccb8c0fc526a4c35577f8fce languageName: node linkType: hard @@ -2196,31 +2402,31 @@ __metadata: languageName: node linkType: hard -"@emnapi/core@npm:^1.4.3": - version: 1.4.3 - resolution: "@emnapi/core@npm:1.4.3" +"@emnapi/core@npm:^1.7.1": + version: 1.8.0 + resolution: "@emnapi/core@npm:1.8.0" dependencies: - "@emnapi/wasi-threads": "npm:1.0.2" + "@emnapi/wasi-threads": "npm:1.1.0" tslib: "npm:^2.4.0" - checksum: 10c0/e30101d16d37ef3283538a35cad60e22095aff2403fb9226a35330b932eb6740b81364d525537a94eb4fb51355e48ae9b10d779c0dd1cdcd55d71461fe4b45c7 + checksum: 10c0/4bb07df0a6ba6478bd4bee2a3609df1f9ef835588227261e9d8ef40f25a9e7596d837f663a4b2c2193d7e8a130370cab5a8063255d81c30903a8c167435d2687 languageName: node linkType: hard -"@emnapi/runtime@npm:^1.4.3": - version: 1.4.3 - resolution: "@emnapi/runtime@npm:1.4.3" +"@emnapi/runtime@npm:^1.7.1": + version: 1.8.0 + resolution: "@emnapi/runtime@npm:1.8.0" dependencies: tslib: "npm:^2.4.0" - checksum: 10c0/3b7ab72d21cb4e034f07df80165265f85f445ef3f581d1bc87b67e5239428baa00200b68a7d5e37a0425c3a78320b541b07f76c5530f6f6f95336a6294ebf30b + checksum: 10c0/25330ade92c48d19f4dc896ecfe906a45c95bd2d3d4155fcf4934e796703f90f23c8f2e7466be44ec734b68ea3e50f64831647d75e1bd44aebbbe1ca870f932a languageName: node linkType: hard -"@emnapi/wasi-threads@npm:1.0.2": - version: 1.0.2 - resolution: "@emnapi/wasi-threads@npm:1.0.2" +"@emnapi/wasi-threads@npm:1.1.0": + version: 1.1.0 + resolution: "@emnapi/wasi-threads@npm:1.1.0" dependencies: tslib: "npm:^2.4.0" - checksum: 10c0/f0621b1fc715221bd2d8332c0ca922617bcd77cdb3050eae50a124eb8923c54fa425d23982dc8f29d505c8798a62d1049bace8b0686098ff9dd82270e06d772e + checksum: 10c0/e6d54bf2b1e64cdd83d2916411e44e579b6ae35d5def0dea61a3c452d9921373044dff32a8b8473ae60c80692bdc39323e98b96a3f3d87ba6886b24dd0ef7ca1 languageName: node linkType: hard @@ -2231,6 +2437,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/aix-ppc64@npm:0.27.2": + version: 0.27.2 + resolution: "@esbuild/aix-ppc64@npm:0.27.2" + conditions: os=aix & cpu=ppc64 + languageName: node + linkType: hard + "@esbuild/android-arm64@npm:0.25.1": version: 0.25.1 resolution: "@esbuild/android-arm64@npm:0.25.1" @@ -2238,6 +2451,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/android-arm64@npm:0.27.2": + version: 0.27.2 + resolution: "@esbuild/android-arm64@npm:0.27.2" + conditions: os=android & cpu=arm64 + languageName: node + linkType: hard + "@esbuild/android-arm@npm:0.25.1": version: 0.25.1 resolution: "@esbuild/android-arm@npm:0.25.1" @@ -2245,6 +2465,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/android-arm@npm:0.27.2": + version: 0.27.2 + resolution: "@esbuild/android-arm@npm:0.27.2" + conditions: os=android & cpu=arm + languageName: node + linkType: hard + "@esbuild/android-x64@npm:0.25.1": version: 0.25.1 resolution: "@esbuild/android-x64@npm:0.25.1" @@ -2252,6 +2479,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/android-x64@npm:0.27.2": + version: 0.27.2 + resolution: "@esbuild/android-x64@npm:0.27.2" + conditions: os=android & cpu=x64 + languageName: node + linkType: hard + "@esbuild/darwin-arm64@npm:0.25.1": version: 0.25.1 resolution: "@esbuild/darwin-arm64@npm:0.25.1" @@ -2259,6 +2493,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/darwin-arm64@npm:0.27.2": + version: 0.27.2 + resolution: "@esbuild/darwin-arm64@npm:0.27.2" + conditions: os=darwin & cpu=arm64 + languageName: node + linkType: hard + "@esbuild/darwin-x64@npm:0.25.1": version: 0.25.1 resolution: "@esbuild/darwin-x64@npm:0.25.1" @@ -2266,6 +2507,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/darwin-x64@npm:0.27.2": + version: 0.27.2 + resolution: "@esbuild/darwin-x64@npm:0.27.2" + conditions: os=darwin & cpu=x64 + languageName: node + linkType: hard + "@esbuild/freebsd-arm64@npm:0.25.1": version: 0.25.1 resolution: "@esbuild/freebsd-arm64@npm:0.25.1" @@ -2273,6 +2521,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/freebsd-arm64@npm:0.27.2": + version: 0.27.2 + resolution: "@esbuild/freebsd-arm64@npm:0.27.2" + conditions: os=freebsd & cpu=arm64 + languageName: node + linkType: hard + "@esbuild/freebsd-x64@npm:0.25.1": version: 0.25.1 resolution: "@esbuild/freebsd-x64@npm:0.25.1" @@ -2280,6 +2535,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/freebsd-x64@npm:0.27.2": + version: 0.27.2 + resolution: "@esbuild/freebsd-x64@npm:0.27.2" + conditions: os=freebsd & cpu=x64 + languageName: node + linkType: hard + "@esbuild/linux-arm64@npm:0.25.1": version: 0.25.1 resolution: "@esbuild/linux-arm64@npm:0.25.1" @@ -2287,6 +2549,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/linux-arm64@npm:0.27.2": + version: 0.27.2 + resolution: "@esbuild/linux-arm64@npm:0.27.2" + conditions: os=linux & cpu=arm64 + languageName: node + linkType: hard + "@esbuild/linux-arm@npm:0.25.1": version: 0.25.1 resolution: "@esbuild/linux-arm@npm:0.25.1" @@ -2294,6 +2563,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/linux-arm@npm:0.27.2": + version: 0.27.2 + resolution: "@esbuild/linux-arm@npm:0.27.2" + conditions: os=linux & cpu=arm + languageName: node + linkType: hard + "@esbuild/linux-ia32@npm:0.25.1": version: 0.25.1 resolution: "@esbuild/linux-ia32@npm:0.25.1" @@ -2301,6 +2577,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/linux-ia32@npm:0.27.2": + version: 0.27.2 + resolution: "@esbuild/linux-ia32@npm:0.27.2" + conditions: os=linux & cpu=ia32 + languageName: node + linkType: hard + "@esbuild/linux-loong64@npm:0.25.1": version: 0.25.1 resolution: "@esbuild/linux-loong64@npm:0.25.1" @@ -2308,6 +2591,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/linux-loong64@npm:0.27.2": + version: 0.27.2 + resolution: "@esbuild/linux-loong64@npm:0.27.2" + conditions: os=linux & cpu=loong64 + languageName: node + linkType: hard + "@esbuild/linux-mips64el@npm:0.25.1": version: 0.25.1 resolution: "@esbuild/linux-mips64el@npm:0.25.1" @@ -2315,6 +2605,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/linux-mips64el@npm:0.27.2": + version: 0.27.2 + resolution: "@esbuild/linux-mips64el@npm:0.27.2" + conditions: os=linux & cpu=mips64el + languageName: node + linkType: hard + "@esbuild/linux-ppc64@npm:0.25.1": version: 0.25.1 resolution: "@esbuild/linux-ppc64@npm:0.25.1" @@ -2322,6 +2619,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/linux-ppc64@npm:0.27.2": + version: 0.27.2 + resolution: "@esbuild/linux-ppc64@npm:0.27.2" + conditions: os=linux & cpu=ppc64 + languageName: node + linkType: hard + "@esbuild/linux-riscv64@npm:0.25.1": version: 0.25.1 resolution: "@esbuild/linux-riscv64@npm:0.25.1" @@ -2329,6 +2633,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/linux-riscv64@npm:0.27.2": + version: 0.27.2 + resolution: "@esbuild/linux-riscv64@npm:0.27.2" + conditions: os=linux & cpu=riscv64 + languageName: node + linkType: hard + "@esbuild/linux-s390x@npm:0.25.1": version: 0.25.1 resolution: "@esbuild/linux-s390x@npm:0.25.1" @@ -2336,6 +2647,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/linux-s390x@npm:0.27.2": + version: 0.27.2 + resolution: "@esbuild/linux-s390x@npm:0.27.2" + conditions: os=linux & cpu=s390x + languageName: node + linkType: hard + "@esbuild/linux-x64@npm:0.25.1": version: 0.25.1 resolution: "@esbuild/linux-x64@npm:0.25.1" @@ -2343,6 +2661,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/linux-x64@npm:0.27.2": + version: 0.27.2 + resolution: "@esbuild/linux-x64@npm:0.27.2" + conditions: os=linux & cpu=x64 + languageName: node + linkType: hard + "@esbuild/netbsd-arm64@npm:0.25.1": version: 0.25.1 resolution: "@esbuild/netbsd-arm64@npm:0.25.1" @@ -2350,6 +2675,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/netbsd-arm64@npm:0.27.2": + version: 0.27.2 + resolution: "@esbuild/netbsd-arm64@npm:0.27.2" + conditions: os=netbsd & cpu=arm64 + languageName: node + linkType: hard + "@esbuild/netbsd-x64@npm:0.25.1": version: 0.25.1 resolution: "@esbuild/netbsd-x64@npm:0.25.1" @@ -2357,6 +2689,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/netbsd-x64@npm:0.27.2": + version: 0.27.2 + resolution: "@esbuild/netbsd-x64@npm:0.27.2" + conditions: os=netbsd & cpu=x64 + languageName: node + linkType: hard + "@esbuild/openbsd-arm64@npm:0.25.1": version: 0.25.1 resolution: "@esbuild/openbsd-arm64@npm:0.25.1" @@ -2364,6 +2703,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/openbsd-arm64@npm:0.27.2": + version: 0.27.2 + resolution: "@esbuild/openbsd-arm64@npm:0.27.2" + conditions: os=openbsd & cpu=arm64 + languageName: node + linkType: hard + "@esbuild/openbsd-x64@npm:0.25.1": version: 0.25.1 resolution: "@esbuild/openbsd-x64@npm:0.25.1" @@ -2371,6 +2717,20 @@ __metadata: languageName: node linkType: hard +"@esbuild/openbsd-x64@npm:0.27.2": + version: 0.27.2 + resolution: "@esbuild/openbsd-x64@npm:0.27.2" + conditions: os=openbsd & cpu=x64 + languageName: node + linkType: hard + +"@esbuild/openharmony-arm64@npm:0.27.2": + version: 0.27.2 + resolution: "@esbuild/openharmony-arm64@npm:0.27.2" + conditions: os=openharmony & cpu=arm64 + languageName: node + linkType: hard + "@esbuild/sunos-x64@npm:0.25.1": version: 0.25.1 resolution: "@esbuild/sunos-x64@npm:0.25.1" @@ -2378,6 +2738,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/sunos-x64@npm:0.27.2": + version: 0.27.2 + resolution: "@esbuild/sunos-x64@npm:0.27.2" + conditions: os=sunos & cpu=x64 + languageName: node + linkType: hard + "@esbuild/win32-arm64@npm:0.25.1": version: 0.25.1 resolution: "@esbuild/win32-arm64@npm:0.25.1" @@ -2385,6 +2752,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/win32-arm64@npm:0.27.2": + version: 0.27.2 + resolution: "@esbuild/win32-arm64@npm:0.27.2" + conditions: os=win32 & cpu=arm64 + languageName: node + linkType: hard + "@esbuild/win32-ia32@npm:0.25.1": version: 0.25.1 resolution: "@esbuild/win32-ia32@npm:0.25.1" @@ -2392,6 +2766,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/win32-ia32@npm:0.27.2": + version: 0.27.2 + resolution: "@esbuild/win32-ia32@npm:0.27.2" + conditions: os=win32 & cpu=ia32 + languageName: node + linkType: hard + "@esbuild/win32-x64@npm:0.25.1": version: 0.25.1 resolution: "@esbuild/win32-x64@npm:0.25.1" @@ -2399,6 +2780,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/win32-x64@npm:0.27.2": + version: 0.27.2 + resolution: "@esbuild/win32-x64@npm:0.27.2" + conditions: os=win32 & cpu=x64 + languageName: node + linkType: hard + "@eslint-community/eslint-utils@npm:^4.2.0": version: 4.4.0 resolution: "@eslint-community/eslint-utils@npm:4.4.0" @@ -2530,28 +2918,40 @@ __metadata: linkType: hard "@fontsource/inconsolata@npm:^5.1.0": - version: 5.2.6 - resolution: "@fontsource/inconsolata@npm:5.2.6" - checksum: 10c0/3e76e02ca075ed81d4e1f7b3de39051cf98a1c5e0acc5ef348f0e2fd5ba9047c79fefc245cc78dbfa98b0fb4dafe8882cd3df57a451c02b104ccc877cccf8433 + version: 5.2.8 + resolution: "@fontsource/inconsolata@npm:5.2.8" + checksum: 10c0/2d5788a41bc60d7d00e5ba75689241a5146a4f60a3ec79d14dd2a0a5aa1ec2e697aa6aed3d1c0564208d32916aea588535f16a57f7a775b554d7f9adb03ad64a languageName: node linkType: hard "@fontsource/inter@npm:^5.1.0": - version: 5.2.6 - resolution: "@fontsource/inter@npm:5.2.6" - checksum: 10c0/7a1347608aab06e53665272ed41fd906ffa96c57b004e8aae91b98177bba97c54b60305d956254c4771387c383f9bdbd917006fb34c9721c020e6017d33e9a5c + version: 5.2.8 + resolution: "@fontsource/inter@npm:5.2.8" + checksum: 10c0/f737dd50005e4809887ba55ae0c9b7174216d6d14875d17a4fbb9a0ad75dec4265928b805a43fe16a23f14a878f1974a398bbfc84ad65c79fc4d4b9c3ea154e1 languageName: node linkType: hard -"@formatjs/ecma402-abstract@npm:2.3.4": - version: 2.3.4 - resolution: "@formatjs/ecma402-abstract@npm:2.3.4" +"@formatjs/ecma402-abstract@npm:2.3.6": + version: 2.3.6 + resolution: "@formatjs/ecma402-abstract@npm:2.3.6" dependencies: "@formatjs/fast-memoize": "npm:2.2.7" - "@formatjs/intl-localematcher": "npm:0.6.1" + "@formatjs/intl-localematcher": "npm:0.6.2" decimal.js: "npm:^10.4.3" tslib: "npm:^2.8.0" - checksum: 10c0/2644bc618a34dc610ef9691281eeb45ae6175e6982cf19f1bd140672fc95c748747ce3c85b934649ea7e4a304f7ae0060625fd53d5df76f92ca3acf743e1eb0a + checksum: 10c0/63be2a73d3168bf45ab5d50db58376e852db5652d89511ae6e44f1fa03ad96ebbfe9b06a1dfaa743db06e40eb7f33bd77530b9388289855cca79a0e3fc29eacf + languageName: node + linkType: hard + +"@formatjs/ecma402-abstract@npm:3.0.7": + version: 3.0.7 + resolution: "@formatjs/ecma402-abstract@npm:3.0.7" + dependencies: + "@formatjs/fast-memoize": "npm:3.0.2" + "@formatjs/intl-localematcher": "npm:0.7.4" + decimal.js: "npm:^10.4.3" + tslib: "npm:^2.8.0" + checksum: 10c0/0fdc25ef72dcd5bbe1deeb190be2f0a2e2770a2135904d16ddfb424305a1efed14b026fba6c48121bc32f693abf1fe08c0ee12cb7d888cb2ba92963236d82c77 languageName: node linkType: hard @@ -2564,34 +2964,53 @@ __metadata: languageName: node linkType: hard -"@formatjs/intl-durationformat@npm:^0.7.0": - version: 0.7.4 - resolution: "@formatjs/intl-durationformat@npm:0.7.4" +"@formatjs/fast-memoize@npm:3.0.2": + version: 3.0.2 + resolution: "@formatjs/fast-memoize@npm:3.0.2" dependencies: - "@formatjs/ecma402-abstract": "npm:2.3.4" - "@formatjs/intl-localematcher": "npm:0.6.1" tslib: "npm:^2.8.0" - checksum: 10c0/e340cab41fcb52639c73f25a422a2cf252c0fb8d328b88bd72b8f995e2d7ffa5d6aa7bb4f4e11862d45bd7eef398d9c8a1cf9d400bcf89c42ff3c38e63196dbe + checksum: 10c0/f7d1074090df309d37322979fe5fc96451531317b42bd927102a3a86dee537b1cb0e378158c74e00efd9714a0aa0f1e5a673c749535df200e13167112676ce88 languageName: node linkType: hard -"@formatjs/intl-localematcher@npm:0.6.1": - version: 0.6.1 - resolution: "@formatjs/intl-localematcher@npm:0.6.1" +"@formatjs/intl-durationformat@npm:^0.9.0": + version: 0.9.1 + resolution: "@formatjs/intl-durationformat@npm:0.9.1" + dependencies: + "@formatjs/ecma402-abstract": "npm:3.0.7" + "@formatjs/intl-localematcher": "npm:0.7.4" + tslib: "npm:^2.8.0" + checksum: 10c0/6f7b01027c07162b26be3014bba17a7633d1f9cfe6c26c5f403e72b92ac26c67cda2d88aeedab891b080664cfb4aace0eacec70b6f006616fe0d322dc2e8145d + languageName: node + linkType: hard + +"@formatjs/intl-localematcher@npm:0.6.2": + version: 0.6.2 + resolution: "@formatjs/intl-localematcher@npm:0.6.2" dependencies: tslib: "npm:^2.8.0" - checksum: 10c0/bacbedd508519c1bb5ca2620e89dc38f12101be59439aa14aa472b222915b462cb7d679726640f6dcf52a05dd218b5aa27ccd60f2e5010bb96f1d4929848cde0 + checksum: 10c0/22a17a4c67160b6c9f52667914acfb7b79cd6d80630d4ac6d4599ce447cb89d2a64f7d58fa35c3145ddb37fef893f0a45b9a55e663a4eb1f2ae8b10a89fac235 + languageName: node + linkType: hard + +"@formatjs/intl-localematcher@npm:0.7.4": + version: 0.7.4 + resolution: "@formatjs/intl-localematcher@npm:0.7.4" + dependencies: + "@formatjs/fast-memoize": "npm:3.0.2" + tslib: "npm:^2.8.0" + checksum: 10c0/7fc31e13397317faadee033dcf668cda49f031b28542c634c920339f374f483235543e08be2077152cfe5dd41e651d8d2d37b6ece8aa044c0998c48f5472fb1a languageName: node linkType: hard "@formatjs/intl-segmenter@npm:^11.7.3": - version: 11.7.10 - resolution: "@formatjs/intl-segmenter@npm:11.7.10" + version: 11.7.12 + resolution: "@formatjs/intl-segmenter@npm:11.7.12" dependencies: - "@formatjs/ecma402-abstract": "npm:2.3.4" - "@formatjs/intl-localematcher": "npm:0.6.1" + "@formatjs/ecma402-abstract": "npm:2.3.6" + "@formatjs/intl-localematcher": "npm:0.6.2" tslib: "npm:^2.8.0" - checksum: 10c0/f84974d00a020cf9f7c153c56f2bb20a104b1cce33c6672c491c842f2b2367d6746bc903a7f18e922da1a89c7ee6edd9e79bf6971dd26c41b6c9faaa76e6c57e + checksum: 10c0/5ab30a9b9e9a63b9c29c3b90a94e7e5eef958829ed0b03a0117998fe0c1e213546eeebe0636b4559d27db86868bffc5311e3619248a2416045c99de6982fa46a languageName: node linkType: hard @@ -2680,6 +3099,16 @@ __metadata: languageName: node linkType: hard +"@jridgewell/remapping@npm:^2.3.5": + version: 2.3.5 + resolution: "@jridgewell/remapping@npm:2.3.5" + dependencies: + "@jridgewell/gen-mapping": "npm:^0.3.5" + "@jridgewell/trace-mapping": "npm:^0.3.24" + checksum: 10c0/3de494219ffeb2c5c38711d0d7bb128097edf91893090a2dbc8ee0b55d092bb7347b1fd0f478486c5eab010e855c73927b1666f2107516d472d24a73017d1194 + languageName: node + linkType: hard + "@jridgewell/resolve-uri@npm:^3.1.0": version: 3.1.2 resolution: "@jridgewell/resolve-uri@npm:3.1.2" @@ -2781,7 +3210,7 @@ __metadata: languageName: node linkType: hard -"@livekit/protocol@npm:1.42.2, @livekit/protocol@npm:^1.42.2": +"@livekit/protocol@npm:1.42.2": version: 1.42.2 resolution: "@livekit/protocol@npm:1.42.2" dependencies: @@ -2790,15 +3219,24 @@ __metadata: languageName: node linkType: hard -"@livekit/track-processors@npm:^0.5.5": - version: 0.5.8 - resolution: "@livekit/track-processors@npm:0.5.8" +"@livekit/protocol@npm:^1.42.2": + version: 1.43.4 + resolution: "@livekit/protocol@npm:1.43.4" + dependencies: + "@bufbuild/protobuf": "npm:^1.10.0" + checksum: 10c0/38077ceec44151b7481a95ce25869570b1466359de4992d9367002fc5b0925fc8ca120ed448099ae552064f23664ebe0920669f4fba97164eacbf181664683f2 + languageName: node + linkType: hard + +"@livekit/track-processors@npm:^0.7.0": + version: 0.7.0 + resolution: "@livekit/track-processors@npm:0.7.0" dependencies: "@mediapipe/tasks-vision": "npm:0.10.14" peerDependencies: "@types/dom-mediacapture-transform": ^0.1.9 livekit-client: ^1.12.0 || ^2.1.0 - checksum: 10c0/1ea87fd79b518a7736b5c0052522ba31cc161fe1181ac0d438fa8a01a25347729b375a4865ea8da3422a922a4cffbc6cf58af13141d79b75f5ea19196e2b97b4 + checksum: 10c0/4c1ec427586e885c44d2865a98008b563d002b1b98d117383637a696597d71a0ff64d8a5bcba48033298e5c2cbaa9e357481e8a4a182982a355eb9e0eeb87643 languageName: node linkType: hard @@ -2816,14 +3254,14 @@ __metadata: languageName: node linkType: hard -"@napi-rs/wasm-runtime@npm:^0.2.11": - version: 0.2.11 - resolution: "@napi-rs/wasm-runtime@npm:0.2.11" +"@napi-rs/wasm-runtime@npm:^1.1.0": + version: 1.1.1 + resolution: "@napi-rs/wasm-runtime@npm:1.1.1" dependencies: - "@emnapi/core": "npm:^1.4.3" - "@emnapi/runtime": "npm:^1.4.3" - "@tybys/wasm-util": "npm:^0.9.0" - checksum: 10c0/049bd14c58b99fbe0967b95e9921c5503df196b59be22948d2155f17652eb305cff6728efd8685338b855da7e476dd2551fbe3a313fc2d810938f0717478441e + "@emnapi/core": "npm:^1.7.1" + "@emnapi/runtime": "npm:^1.7.1" + "@tybys/wasm-util": "npm:^0.10.1" + checksum: 10c0/04d57b67e80736e41fe44674a011878db0a8ad893f4d44abb9d3608debb7c174224cba2796ed5b0c1d367368159f3ca6be45f1c59222f70e32ddc880f803d447 languageName: node linkType: hard @@ -2996,12 +3434,12 @@ __metadata: languageName: node linkType: hard -"@opentelemetry/api-logs@npm:0.203.0": - version: 0.203.0 - resolution: "@opentelemetry/api-logs@npm:0.203.0" +"@opentelemetry/api-logs@npm:0.208.0": + version: 0.208.0 + resolution: "@opentelemetry/api-logs@npm:0.208.0" dependencies: "@opentelemetry/api": "npm:^1.3.0" - checksum: 10c0/e7a0a0ff46aaeb62192a99f45ef4889222e4fea09be25cab6fea811afc2df95c02ea050b2c98dfc0fc5a6ec6a623d87096af2751fdf91ddbb3afcab61b5325da + checksum: 10c0/dc1fbee6219df4166509f43b74ea936bb18b6d594565b0bcf56b654a1c958b50d6046b8739dc36c98149fe890c02150ff3814e963f5ea439a07ff3c562555b99 languageName: node linkType: hard @@ -3012,219 +3450,268 @@ __metadata: languageName: node linkType: hard -"@opentelemetry/core@npm:2.0.1, @opentelemetry/core@npm:^2.0.0": - version: 2.0.1 - resolution: "@opentelemetry/core@npm:2.0.1" +"@opentelemetry/core@npm:2.2.0, @opentelemetry/core@npm:^2.0.0": + version: 2.2.0 + resolution: "@opentelemetry/core@npm:2.2.0" dependencies: "@opentelemetry/semantic-conventions": "npm:^1.29.0" peerDependencies: "@opentelemetry/api": ">=1.0.0 <1.10.0" - checksum: 10c0/d587b1289559757d80da98039f9f57612f84f72ec608cd665dc467c7c6c5ce3a987dfcc2c63b521c7c86ce984a2552b3ead15a0dc458de1cf6bde5cdfe4ca9d8 + checksum: 10c0/f618b63f2f560d052791d2406b1411722aa4b0585031242e6906f869f0a707ffe725c4b29bf18aed1f202e1ab5dfc3a9f769c517ac8521338b33ac8c4265fba9 languageName: node linkType: hard -"@opentelemetry/exporter-trace-otlp-http@npm:^0.203.0": - version: 0.203.0 - resolution: "@opentelemetry/exporter-trace-otlp-http@npm:0.203.0" +"@opentelemetry/exporter-trace-otlp-http@npm:^0.208.0": + version: 0.208.0 + resolution: "@opentelemetry/exporter-trace-otlp-http@npm:0.208.0" dependencies: - "@opentelemetry/core": "npm:2.0.1" - "@opentelemetry/otlp-exporter-base": "npm:0.203.0" - "@opentelemetry/otlp-transformer": "npm:0.203.0" - "@opentelemetry/resources": "npm:2.0.1" - "@opentelemetry/sdk-trace-base": "npm:2.0.1" + "@opentelemetry/core": "npm:2.2.0" + "@opentelemetry/otlp-exporter-base": "npm:0.208.0" + "@opentelemetry/otlp-transformer": "npm:0.208.0" + "@opentelemetry/resources": "npm:2.2.0" + "@opentelemetry/sdk-trace-base": "npm:2.2.0" peerDependencies: "@opentelemetry/api": ^1.3.0 - checksum: 10c0/21a65ebc40dcab05cf11178e5037f96847ce344c4a855aac46dcab3f74982016318ee75fafdfeeb42f10b92a0a781b7cd8b2b5b036cbe53c14714fd13940142e + checksum: 10c0/5e901388febb6e797aa7ed1705373df322df4ba47eaf545a85bb4e1e3b3056993a455d9d6a68e94dc57e6c8112d580129b374bf2982595244edf664663b93e66 languageName: node linkType: hard -"@opentelemetry/otlp-exporter-base@npm:0.203.0": - version: 0.203.0 - resolution: "@opentelemetry/otlp-exporter-base@npm:0.203.0" +"@opentelemetry/otlp-exporter-base@npm:0.208.0": + version: 0.208.0 + resolution: "@opentelemetry/otlp-exporter-base@npm:0.208.0" dependencies: - "@opentelemetry/core": "npm:2.0.1" - "@opentelemetry/otlp-transformer": "npm:0.203.0" + "@opentelemetry/core": "npm:2.2.0" + "@opentelemetry/otlp-transformer": "npm:0.208.0" peerDependencies: "@opentelemetry/api": ^1.3.0 - checksum: 10c0/ad5b771b06b192f06f332f60701d1ad208df88a05975b16e1cdd1dff8e1cb66e775b3e9de513c2f5d48f390f25ca35411ead08ce4849c8203b86a264d34561d3 + checksum: 10c0/c2b2014da16e2a2be0ebe525b1a62b3e64e286fc9c2575444e4c75bbe0060a83762172180dc7a97cdaaaa8c6765076073edea30340459fc1820cd43468ff98b0 languageName: node linkType: hard -"@opentelemetry/otlp-transformer@npm:0.203.0": - version: 0.203.0 - resolution: "@opentelemetry/otlp-transformer@npm:0.203.0" +"@opentelemetry/otlp-transformer@npm:0.208.0": + version: 0.208.0 + resolution: "@opentelemetry/otlp-transformer@npm:0.208.0" dependencies: - "@opentelemetry/api-logs": "npm:0.203.0" - "@opentelemetry/core": "npm:2.0.1" - "@opentelemetry/resources": "npm:2.0.1" - "@opentelemetry/sdk-logs": "npm:0.203.0" - "@opentelemetry/sdk-metrics": "npm:2.0.1" - "@opentelemetry/sdk-trace-base": "npm:2.0.1" + "@opentelemetry/api-logs": "npm:0.208.0" + "@opentelemetry/core": "npm:2.2.0" + "@opentelemetry/resources": "npm:2.2.0" + "@opentelemetry/sdk-logs": "npm:0.208.0" + "@opentelemetry/sdk-metrics": "npm:2.2.0" + "@opentelemetry/sdk-trace-base": "npm:2.2.0" protobufjs: "npm:^7.3.0" peerDependencies: "@opentelemetry/api": ^1.3.0 - checksum: 10c0/3f7b4bfe4bcab4db434ff2c4e59b53de53642d379b80056610456d8e9ae0cbab0f8b69f088078637b7b5ceffd0ac2fda68469c5f295b1c0ac625f522f640338c + checksum: 10c0/70c04b2a52f0b2f8aece25ad21401c32ed3136ccd6e82b767d570a24d5456a5ded206ed4cc60ebc09eac08a4aa9c03bc8dcbf10730e491f1af3e7768c361ac12 languageName: node linkType: hard -"@opentelemetry/resources@npm:2.0.1, @opentelemetry/resources@npm:^2.0.0": - version: 2.0.1 - resolution: "@opentelemetry/resources@npm:2.0.1" +"@opentelemetry/resources@npm:2.2.0, @opentelemetry/resources@npm:^2.0.0": + version: 2.2.0 + resolution: "@opentelemetry/resources@npm:2.2.0" dependencies: - "@opentelemetry/core": "npm:2.0.1" + "@opentelemetry/core": "npm:2.2.0" "@opentelemetry/semantic-conventions": "npm:^1.29.0" peerDependencies: "@opentelemetry/api": ">=1.3.0 <1.10.0" - checksum: 10c0/96532b7553b26607a7a892d72f6b03ad12bd542dc23c95135a8ae40362da9c883c21a4cff3d2296d9e0e9bd899a5977e325ed52d83142621a8ffe81d08d99341 + checksum: 10c0/f08fa69ccccb6d14b6932fabe6f8e097c0dfc41ae8f4c0f6c54fb04bc3d9c04e742da3e22d7240d74b585287101126d97a0da192b493a9724dc07a56ca1b77e0 languageName: node linkType: hard -"@opentelemetry/sdk-logs@npm:0.203.0": - version: 0.203.0 - resolution: "@opentelemetry/sdk-logs@npm:0.203.0" +"@opentelemetry/sdk-logs@npm:0.208.0": + version: 0.208.0 + resolution: "@opentelemetry/sdk-logs@npm:0.208.0" dependencies: - "@opentelemetry/api-logs": "npm:0.203.0" - "@opentelemetry/core": "npm:2.0.1" - "@opentelemetry/resources": "npm:2.0.1" + "@opentelemetry/api-logs": "npm:0.208.0" + "@opentelemetry/core": "npm:2.2.0" + "@opentelemetry/resources": "npm:2.2.0" peerDependencies: "@opentelemetry/api": ">=1.4.0 <1.10.0" - checksum: 10c0/02dd9d9969628f05f71ae1d149f1aa6d1fee2dad607923a68a1cfc923e94b046dcc0e18e85e865324e3bda0cee7a5a0ba9fa0d57e4e95fa672be103e2ce60270 + checksum: 10c0/a167ee7d2818e435ff7480836461f94543e4e39f0e8e8013d462c635def9b960dcf1a29e5536743946b51ef13b764f518d9edb511e89bc1e8995acc96f54241f languageName: node linkType: hard -"@opentelemetry/sdk-metrics@npm:2.0.1": - version: 2.0.1 - resolution: "@opentelemetry/sdk-metrics@npm:2.0.1" +"@opentelemetry/sdk-metrics@npm:2.2.0": + version: 2.2.0 + resolution: "@opentelemetry/sdk-metrics@npm:2.2.0" dependencies: - "@opentelemetry/core": "npm:2.0.1" - "@opentelemetry/resources": "npm:2.0.1" + "@opentelemetry/core": "npm:2.2.0" + "@opentelemetry/resources": "npm:2.2.0" peerDependencies: "@opentelemetry/api": ">=1.9.0 <1.10.0" - checksum: 10c0/fcf7ae23d459e5da7cb6fe150064b6dc4e11e47925b08980c3b357bd5534ad388898bbacd0ff8befef6801f43b35142dc7123f028ffde2d0fe2bd72177d07639 + checksum: 10c0/a2668f9ef937123552a5ab96ec23675931ae7d3223ec7a31c8aac95fbbfb0b03a54a873f17f2356b04db7031421e7e3d7e3bf9d96d9069a0b97c680a2c158bc4 languageName: node linkType: hard -"@opentelemetry/sdk-trace-base@npm:2.0.1, @opentelemetry/sdk-trace-base@npm:^2.0.0": - version: 2.0.1 - resolution: "@opentelemetry/sdk-trace-base@npm:2.0.1" +"@opentelemetry/sdk-trace-base@npm:2.2.0, @opentelemetry/sdk-trace-base@npm:^2.0.0": + version: 2.2.0 + resolution: "@opentelemetry/sdk-trace-base@npm:2.2.0" dependencies: - "@opentelemetry/core": "npm:2.0.1" - "@opentelemetry/resources": "npm:2.0.1" + "@opentelemetry/core": "npm:2.2.0" + "@opentelemetry/resources": "npm:2.2.0" "@opentelemetry/semantic-conventions": "npm:^1.29.0" peerDependencies: "@opentelemetry/api": ">=1.3.0 <1.10.0" - checksum: 10c0/4e3c733296012b758d007e9c0d8a5b175edbe9a680c73ec75303476e7982b73ad4209f1a2791c1a94c428e5a53eba6c2a72faa430c70336005aa58744d6cb37b + checksum: 10c0/a67715b71d7253cd61ea79954f56491796ac7a660d03d5381fd81defd4546042bb465b27e1b6eee4b1ed32c00305a5349a16d04fd44314c9a1d371a0a638107a languageName: node linkType: hard "@opentelemetry/sdk-trace-web@npm:^2.0.0": - version: 2.0.1 - resolution: "@opentelemetry/sdk-trace-web@npm:2.0.1" + version: 2.2.0 + resolution: "@opentelemetry/sdk-trace-web@npm:2.2.0" dependencies: - "@opentelemetry/core": "npm:2.0.1" - "@opentelemetry/sdk-trace-base": "npm:2.0.1" + "@opentelemetry/core": "npm:2.2.0" + "@opentelemetry/sdk-trace-base": "npm:2.2.0" peerDependencies: "@opentelemetry/api": ">=1.0.0 <1.10.0" - checksum: 10c0/48821b91430e24378b0b5b2632e78efdd018a3f840462a6aeba6ce318a6480bad2f623cc7f7f625a9266028ad44b78eb8456181778de6cb18725f26c44e2729b + checksum: 10c0/002296bb929d4992575415ea93c2a68411cd5018c6e7fa27b7cd48e78741b7eddfb87eb0903e7ca42740acb04ac4e8508d00f7651bdc63b433055af955201d31 languageName: node linkType: hard "@opentelemetry/semantic-conventions@npm:^1.25.1, @opentelemetry/semantic-conventions@npm:^1.29.0": - version: 1.36.0 - resolution: "@opentelemetry/semantic-conventions@npm:1.36.0" - checksum: 10c0/edc8a6fe3ec4fc0c67ba3a92b86fb3dcc78fe1eb4f19838d8013c3232b9868540a034dd25cfe0afdd5eae752c5f0e9f42272ff46da144a2d5b35c644478e1c62 + version: 1.38.0 + resolution: "@opentelemetry/semantic-conventions@npm:1.38.0" + checksum: 10c0/ae93e39ac18bf47df2b11d43e9a0dc1673b9d33e5f1e7f357c92968e6329fb9a67cf8a447e9a7150948ee3f8178b38274db365b8fa775a8c54802e0c6ccdd2ca languageName: node linkType: hard -"@oxc-resolver/binding-darwin-arm64@npm:11.3.0": - version: 11.3.0 - resolution: "@oxc-resolver/binding-darwin-arm64@npm:11.3.0" +"@oxc-resolver/binding-android-arm-eabi@npm:11.16.2": + version: 11.16.2 + resolution: "@oxc-resolver/binding-android-arm-eabi@npm:11.16.2" + conditions: os=android & cpu=arm + languageName: node + linkType: hard + +"@oxc-resolver/binding-android-arm64@npm:11.16.2": + version: 11.16.2 + resolution: "@oxc-resolver/binding-android-arm64@npm:11.16.2" + conditions: os=android & cpu=arm64 + languageName: node + linkType: hard + +"@oxc-resolver/binding-darwin-arm64@npm:11.16.2": + version: 11.16.2 + resolution: "@oxc-resolver/binding-darwin-arm64@npm:11.16.2" conditions: os=darwin & cpu=arm64 languageName: node linkType: hard -"@oxc-resolver/binding-darwin-x64@npm:11.3.0": - version: 11.3.0 - resolution: "@oxc-resolver/binding-darwin-x64@npm:11.3.0" +"@oxc-resolver/binding-darwin-x64@npm:11.16.2": + version: 11.16.2 + resolution: "@oxc-resolver/binding-darwin-x64@npm:11.16.2" conditions: os=darwin & cpu=x64 languageName: node linkType: hard -"@oxc-resolver/binding-freebsd-x64@npm:11.3.0": - version: 11.3.0 - resolution: "@oxc-resolver/binding-freebsd-x64@npm:11.3.0" +"@oxc-resolver/binding-freebsd-x64@npm:11.16.2": + version: 11.16.2 + resolution: "@oxc-resolver/binding-freebsd-x64@npm:11.16.2" conditions: os=freebsd & cpu=x64 languageName: node linkType: hard -"@oxc-resolver/binding-linux-arm-gnueabihf@npm:11.3.0": - version: 11.3.0 - resolution: "@oxc-resolver/binding-linux-arm-gnueabihf@npm:11.3.0" +"@oxc-resolver/binding-linux-arm-gnueabihf@npm:11.16.2": + version: 11.16.2 + resolution: "@oxc-resolver/binding-linux-arm-gnueabihf@npm:11.16.2" conditions: os=linux & cpu=arm languageName: node linkType: hard -"@oxc-resolver/binding-linux-arm64-gnu@npm:11.3.0": - version: 11.3.0 - resolution: "@oxc-resolver/binding-linux-arm64-gnu@npm:11.3.0" +"@oxc-resolver/binding-linux-arm-musleabihf@npm:11.16.2": + version: 11.16.2 + resolution: "@oxc-resolver/binding-linux-arm-musleabihf@npm:11.16.2" + conditions: os=linux & cpu=arm + languageName: node + linkType: hard + +"@oxc-resolver/binding-linux-arm64-gnu@npm:11.16.2": + version: 11.16.2 + resolution: "@oxc-resolver/binding-linux-arm64-gnu@npm:11.16.2" conditions: os=linux & cpu=arm64 & libc=glibc languageName: node linkType: hard -"@oxc-resolver/binding-linux-arm64-musl@npm:11.3.0": - version: 11.3.0 - resolution: "@oxc-resolver/binding-linux-arm64-musl@npm:11.3.0" +"@oxc-resolver/binding-linux-arm64-musl@npm:11.16.2": + version: 11.16.2 + resolution: "@oxc-resolver/binding-linux-arm64-musl@npm:11.16.2" conditions: os=linux & cpu=arm64 & libc=musl languageName: node linkType: hard -"@oxc-resolver/binding-linux-riscv64-gnu@npm:11.3.0": - version: 11.3.0 - resolution: "@oxc-resolver/binding-linux-riscv64-gnu@npm:11.3.0" +"@oxc-resolver/binding-linux-ppc64-gnu@npm:11.16.2": + version: 11.16.2 + resolution: "@oxc-resolver/binding-linux-ppc64-gnu@npm:11.16.2" + conditions: os=linux & cpu=ppc64 & libc=glibc + languageName: node + linkType: hard + +"@oxc-resolver/binding-linux-riscv64-gnu@npm:11.16.2": + version: 11.16.2 + resolution: "@oxc-resolver/binding-linux-riscv64-gnu@npm:11.16.2" conditions: os=linux & cpu=riscv64 & libc=glibc languageName: node linkType: hard -"@oxc-resolver/binding-linux-s390x-gnu@npm:11.3.0": - version: 11.3.0 - resolution: "@oxc-resolver/binding-linux-s390x-gnu@npm:11.3.0" +"@oxc-resolver/binding-linux-riscv64-musl@npm:11.16.2": + version: 11.16.2 + resolution: "@oxc-resolver/binding-linux-riscv64-musl@npm:11.16.2" + conditions: os=linux & cpu=riscv64 & libc=musl + languageName: node + linkType: hard + +"@oxc-resolver/binding-linux-s390x-gnu@npm:11.16.2": + version: 11.16.2 + resolution: "@oxc-resolver/binding-linux-s390x-gnu@npm:11.16.2" conditions: os=linux & cpu=s390x & libc=glibc languageName: node linkType: hard -"@oxc-resolver/binding-linux-x64-gnu@npm:11.3.0": - version: 11.3.0 - resolution: "@oxc-resolver/binding-linux-x64-gnu@npm:11.3.0" +"@oxc-resolver/binding-linux-x64-gnu@npm:11.16.2": + version: 11.16.2 + resolution: "@oxc-resolver/binding-linux-x64-gnu@npm:11.16.2" conditions: os=linux & cpu=x64 & libc=glibc languageName: node linkType: hard -"@oxc-resolver/binding-linux-x64-musl@npm:11.3.0": - version: 11.3.0 - resolution: "@oxc-resolver/binding-linux-x64-musl@npm:11.3.0" +"@oxc-resolver/binding-linux-x64-musl@npm:11.16.2": + version: 11.16.2 + resolution: "@oxc-resolver/binding-linux-x64-musl@npm:11.16.2" conditions: os=linux & cpu=x64 & libc=musl languageName: node linkType: hard -"@oxc-resolver/binding-wasm32-wasi@npm:11.3.0": - version: 11.3.0 - resolution: "@oxc-resolver/binding-wasm32-wasi@npm:11.3.0" +"@oxc-resolver/binding-openharmony-arm64@npm:11.16.2": + version: 11.16.2 + resolution: "@oxc-resolver/binding-openharmony-arm64@npm:11.16.2" + conditions: os=openharmony & cpu=arm64 + languageName: node + linkType: hard + +"@oxc-resolver/binding-wasm32-wasi@npm:11.16.2": + version: 11.16.2 + resolution: "@oxc-resolver/binding-wasm32-wasi@npm:11.16.2" dependencies: - "@napi-rs/wasm-runtime": "npm:^0.2.11" + "@napi-rs/wasm-runtime": "npm:^1.1.0" conditions: cpu=wasm32 languageName: node linkType: hard -"@oxc-resolver/binding-win32-arm64-msvc@npm:11.3.0": - version: 11.3.0 - resolution: "@oxc-resolver/binding-win32-arm64-msvc@npm:11.3.0" +"@oxc-resolver/binding-win32-arm64-msvc@npm:11.16.2": + version: 11.16.2 + resolution: "@oxc-resolver/binding-win32-arm64-msvc@npm:11.16.2" conditions: os=win32 & cpu=arm64 languageName: node linkType: hard -"@oxc-resolver/binding-win32-x64-msvc@npm:11.3.0": - version: 11.3.0 - resolution: "@oxc-resolver/binding-win32-x64-msvc@npm:11.3.0" +"@oxc-resolver/binding-win32-ia32-msvc@npm:11.16.2": + version: 11.16.2 + resolution: "@oxc-resolver/binding-win32-ia32-msvc@npm:11.16.2" + conditions: os=win32 & cpu=ia32 + languageName: node + linkType: hard + +"@oxc-resolver/binding-win32-x64-msvc@npm:11.16.2": + version: 11.16.2 + resolution: "@oxc-resolver/binding-win32-x64-msvc@npm:11.16.2" conditions: os=win32 & cpu=x64 languageName: node linkType: hard @@ -3478,10 +3965,10 @@ __metadata: languageName: node linkType: hard -"@radix-ui/primitive@npm:1.1.2": - version: 1.1.2 - resolution: "@radix-ui/primitive@npm:1.1.2" - checksum: 10c0/5e2d2528d2fe37c16865e77b0beaac2b415a817ad13d8178db6e8187b2a092672568a64ee0041510abfde3034490a5cadd3057049bb15789020c06892047597c +"@radix-ui/primitive@npm:1.1.3": + version: 1.1.3 + resolution: "@radix-ui/primitive@npm:1.1.3" + checksum: 10c0/88860165ee7066fa2c179f32ffcd3ee6d527d9dcdc0e8be85e9cb0e2c84834be8e3c1a976c74ba44b193f709544e12f54455d892b28e32f0708d89deda6b9f1d languageName: node linkType: hard @@ -3625,18 +4112,18 @@ __metadata: linkType: hard "@radix-ui/react-dialog@npm:^1.0.4, @radix-ui/react-dialog@npm:^1.1.1": - version: 1.1.14 - resolution: "@radix-ui/react-dialog@npm:1.1.14" + version: 1.1.15 + resolution: "@radix-ui/react-dialog@npm:1.1.15" dependencies: - "@radix-ui/primitive": "npm:1.1.2" + "@radix-ui/primitive": "npm:1.1.3" "@radix-ui/react-compose-refs": "npm:1.1.2" "@radix-ui/react-context": "npm:1.1.2" - "@radix-ui/react-dismissable-layer": "npm:1.1.10" - "@radix-ui/react-focus-guards": "npm:1.1.2" + "@radix-ui/react-dismissable-layer": "npm:1.1.11" + "@radix-ui/react-focus-guards": "npm:1.1.3" "@radix-ui/react-focus-scope": "npm:1.1.7" "@radix-ui/react-id": "npm:1.1.1" "@radix-ui/react-portal": "npm:1.1.9" - "@radix-ui/react-presence": "npm:1.1.4" + "@radix-ui/react-presence": "npm:1.1.5" "@radix-ui/react-primitive": "npm:2.1.3" "@radix-ui/react-slot": "npm:1.2.3" "@radix-ui/react-use-controllable-state": "npm:1.2.2" @@ -3652,7 +4139,7 @@ __metadata: optional: true "@types/react-dom": optional: true - checksum: 10c0/ab7bc783510ed8fccfe91020b214f4a571d5a1d46d398faa33f4c151bc9f586c47483b307e72b67687b06694c194b3aa80dd1de728460fa765db9f3057690ba3 + checksum: 10c0/2f2c88e3c281acaea2fd9b96fa82132d59177d3aa5da2e7c045596fd4028e84e44ac52ac28f4f236910605dd7d9338c2858ba44a9ced2af2e3e523abbfd33014 languageName: node linkType: hard @@ -3682,11 +4169,11 @@ __metadata: languageName: node linkType: hard -"@radix-ui/react-dismissable-layer@npm:1.1.10": - version: 1.1.10 - resolution: "@radix-ui/react-dismissable-layer@npm:1.1.10" +"@radix-ui/react-dismissable-layer@npm:1.1.11": + version: 1.1.11 + resolution: "@radix-ui/react-dismissable-layer@npm:1.1.11" dependencies: - "@radix-ui/primitive": "npm:1.1.2" + "@radix-ui/primitive": "npm:1.1.3" "@radix-ui/react-compose-refs": "npm:1.1.2" "@radix-ui/react-primitive": "npm:2.1.3" "@radix-ui/react-use-callback-ref": "npm:1.1.1" @@ -3701,7 +4188,7 @@ __metadata: optional: true "@types/react-dom": optional: true - checksum: 10c0/21a2d03689f5e06586135b6a735937ef14f2571fdf6044a3019bc3f9fa368a9400b5a9b631f43e8ad3682693449e369ffa7cc8642764246ce18ebe7359a45faf + checksum: 10c0/c825572a64073c4d3853702029979f6658770ffd6a98eabc4984e1dee1b226b4078a2a4dc7003f96475b438985e9b21a58e75f51db74dd06848dcae1f2d395dc languageName: node linkType: hard @@ -3766,16 +4253,16 @@ __metadata: languageName: node linkType: hard -"@radix-ui/react-focus-guards@npm:1.1.2": - version: 1.1.2 - resolution: "@radix-ui/react-focus-guards@npm:1.1.2" +"@radix-ui/react-focus-guards@npm:1.1.3": + version: 1.1.3 + resolution: "@radix-ui/react-focus-guards@npm:1.1.3" peerDependencies: "@types/react": "*" react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc peerDependenciesMeta: "@types/react": optional: true - checksum: 10c0/8d6fa55752b9b6e55d1eebb643178e38a824e8ba418eb29031b2979077a12c4e3922892de9f984dd326f77071a14960cd81e99a960beea07598b8c80da618dc5 + checksum: 10c0/0bab65eb8d7e4f72f685d63de7fbba2450e3cb15ad6a20a16b42195e9d335c576356f5a47cb58d1ffc115393e46d7b14b12c5d4b10029b0ec090861255866985 languageName: node linkType: hard @@ -4018,9 +4505,9 @@ __metadata: languageName: node linkType: hard -"@radix-ui/react-presence@npm:1.1.4": - version: 1.1.4 - resolution: "@radix-ui/react-presence@npm:1.1.4" +"@radix-ui/react-presence@npm:1.1.5": + version: 1.1.5 + resolution: "@radix-ui/react-presence@npm:1.1.5" dependencies: "@radix-ui/react-compose-refs": "npm:1.1.2" "@radix-ui/react-use-layout-effect": "npm:1.1.1" @@ -4034,7 +4521,7 @@ __metadata: optional: true "@types/react-dom": optional: true - checksum: 10c0/8202647139d6f5097b0abcc43dfba471c00b69da95ca336afe3ea23a165e05ca21992f40fc801760fe442f3e064e54e2f2cbcb9ad758c4b07ef6c69a5b6777bd + checksum: 10c0/d0e61d314250eeaef5369983cb790701d667f51734bafd98cf759072755562018052c594e6cdc5389789f4543cb0a4d98f03ff4e8f37338d6b5bf51a1700c1d1 languageName: node linkType: hard @@ -4076,6 +4563,25 @@ __metadata: languageName: node linkType: hard +"@radix-ui/react-primitive@npm:2.1.4": + version: 2.1.4 + resolution: "@radix-ui/react-primitive@npm:2.1.4" + dependencies: + "@radix-ui/react-slot": "npm:1.2.4" + peerDependencies: + "@types/react": "*" + "@types/react-dom": "*" + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + "@types/react": + optional: true + "@types/react-dom": + optional: true + checksum: 10c0/90d687b222a25975371ed1f9f08648d75237214b8dec4cbaf09ec9ac951339b17421278f1aff2fb7c5672ba8bd03774a94904efdba73805dd5cc947ce5be8c4a + languageName: node + linkType: hard + "@radix-ui/react-progress@npm:^1.1.0": version: 1.1.1 resolution: "@radix-ui/react-progress@npm:1.1.1" @@ -4143,11 +4649,11 @@ __metadata: linkType: hard "@radix-ui/react-slider@npm:^1.1.2": - version: 1.3.5 - resolution: "@radix-ui/react-slider@npm:1.3.5" + version: 1.3.6 + resolution: "@radix-ui/react-slider@npm:1.3.6" dependencies: "@radix-ui/number": "npm:1.1.1" - "@radix-ui/primitive": "npm:1.1.2" + "@radix-ui/primitive": "npm:1.1.3" "@radix-ui/react-collection": "npm:1.1.7" "@radix-ui/react-compose-refs": "npm:1.1.2" "@radix-ui/react-context": "npm:1.1.2" @@ -4167,7 +4673,7 @@ __metadata: optional: true "@types/react-dom": optional: true - checksum: 10c0/2f5f37f953d78ac02ed74120afe76badf3a7d0e19036f4de6cdeda38220718a1d5113ffc2f43e0b3de73e14564cae9a09d1968ee3f9641625849d126a036717f + checksum: 10c0/a53d7854e28c5ef3d29b76c8d04cc3c723b982b643152cd5a8fefc7a8359180f8fd21753e5a08302a290bc837e7be04f2efad9d308b7a4a23326df6a6b1ac882 languageName: node linkType: hard @@ -4201,6 +4707,21 @@ __metadata: languageName: node linkType: hard +"@radix-ui/react-slot@npm:1.2.4": + version: 1.2.4 + resolution: "@radix-ui/react-slot@npm:1.2.4" + dependencies: + "@radix-ui/react-compose-refs": "npm:1.1.2" + peerDependencies: + "@types/react": "*" + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + "@types/react": + optional: true + checksum: 10c0/8b719bb934f1ae5ac0e37214783085c17c2f1080217caf514c1c6cc3d9ca56c7e19d25470b26da79aa6e605ab36589edaade149b76f5fc0666f1063e2fc0a0dc + languageName: node + linkType: hard + "@radix-ui/react-use-callback-ref@npm:1.1.0": version: 1.1.0 resolution: "@radix-ui/react-use-callback-ref@npm:1.1.0" @@ -4388,10 +4909,10 @@ __metadata: linkType: hard "@radix-ui/react-visually-hidden@npm:^1.0.3": - version: 1.2.3 - resolution: "@radix-ui/react-visually-hidden@npm:1.2.3" + version: 1.2.4 + resolution: "@radix-ui/react-visually-hidden@npm:1.2.4" dependencies: - "@radix-ui/react-primitive": "npm:2.1.3" + "@radix-ui/react-primitive": "npm:2.1.4" peerDependencies: "@types/react": "*" "@types/react-dom": "*" @@ -4402,7 +4923,7 @@ __metadata: optional: true "@types/react-dom": optional: true - checksum: 10c0/cf86a37f1cbee50a964056f3dc4f6bb1ee79c76daa321f913aa20ff3e1ccdfafbf2b114d7bb616aeefc7c4b895e6ca898523fdb67710d89bd5d8edb739a0d9b6 + checksum: 10c0/cca313cd3268f483612da1ab91c4cca55a54d24963dd543154f2d043bfdca21a96ab0582152ae473de44769474867d5433dbadae799a42932e6204fd2d5fa889 languageName: node linkType: hard @@ -4413,69 +4934,69 @@ __metadata: languageName: node linkType: hard -"@react-spring/animated@npm:~10.0.1": - version: 10.0.1 - resolution: "@react-spring/animated@npm:10.0.1" +"@react-spring/animated@npm:~10.0.3": + version: 10.0.3 + resolution: "@react-spring/animated@npm:10.0.3" dependencies: - "@react-spring/shared": "npm:~10.0.1" - "@react-spring/types": "npm:~10.0.1" + "@react-spring/shared": "npm:~10.0.3" + "@react-spring/types": "npm:~10.0.3" peerDependencies: react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 - checksum: 10c0/aaccd4a8b0280ac846d463b253ad8f092ee4afc9dbedc8e77616adf5399ffec755344f09fdd8487cadaf815840dff84d354d1143579c27c2fcd6937549b5fc40 + checksum: 10c0/6142522f310926729a92009a108ec1bd0d1fe3dca7e9aa0c49692c82fbed28f70c0ea9808fc7452f04bb688ae34333e780f794495906fa4b0efbfc7d53a19b6b languageName: node linkType: hard -"@react-spring/core@npm:~10.0.1": - version: 10.0.1 - resolution: "@react-spring/core@npm:10.0.1" +"@react-spring/core@npm:~10.0.3": + version: 10.0.3 + resolution: "@react-spring/core@npm:10.0.3" dependencies: - "@react-spring/animated": "npm:~10.0.1" - "@react-spring/shared": "npm:~10.0.1" - "@react-spring/types": "npm:~10.0.1" + "@react-spring/animated": "npm:~10.0.3" + "@react-spring/shared": "npm:~10.0.3" + "@react-spring/types": "npm:~10.0.3" peerDependencies: react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 - checksum: 10c0/059b122dda4138e5e7e461abd49350921e326735ca9a1d8aa19b1fdbae0937661b5f71af6fe82fd8f59e8db5549627849b38cc3f7ef2ec7ee9c93c3d6225174f + checksum: 10c0/d941541d4a40a5229f488e78b414149d54238065178fdd14db307a851d285d521ab1914c0d426b102e0190651dbe752aeb743cee4cd497f5c066be937f2d1790 languageName: node linkType: hard -"@react-spring/rafz@npm:~10.0.1": - version: 10.0.1 - resolution: "@react-spring/rafz@npm:10.0.1" - checksum: 10c0/cba76f143d3a06f79dd0c09f7aefd17df9cca9b2c1ef7f9103255e5351326f4a42a5a1366f731a78f74380d96ba683bcc2a49312ed1e4b9e9e249e72c9ff68cb +"@react-spring/rafz@npm:~10.0.3": + version: 10.0.3 + resolution: "@react-spring/rafz@npm:10.0.3" + checksum: 10c0/4cf6f710e2be64a3d94e90a20a24a93c68a89b618538d32aaf0079217f9fbed610395051a181d2d010c7ed6898cb7239a3f2ced1d91dd93e4138563ffd2d44ce languageName: node linkType: hard -"@react-spring/shared@npm:~10.0.1": - version: 10.0.1 - resolution: "@react-spring/shared@npm:10.0.1" +"@react-spring/shared@npm:~10.0.3": + version: 10.0.3 + resolution: "@react-spring/shared@npm:10.0.3" dependencies: - "@react-spring/rafz": "npm:~10.0.1" - "@react-spring/types": "npm:~10.0.1" + "@react-spring/rafz": "npm:~10.0.3" + "@react-spring/types": "npm:~10.0.3" peerDependencies: react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 - checksum: 10c0/f056aaa018b3744afd8244e8eea24534d32f92fad9ace815b80e159b296fb5db148e2c9bd840ad9a5188e7a3c0778fd564b8af9ae02cd500e019a228398fb3cf + checksum: 10c0/d8b33b2390792924d0ff2b57b3098d1c6b688a788fc67e83b168928659aad7435dd2c399925a765ffa5080182634dde8f9f76c919f2c259a33af15319187f72f languageName: node linkType: hard -"@react-spring/types@npm:~10.0.1": - version: 10.0.1 - resolution: "@react-spring/types@npm:10.0.1" - checksum: 10c0/260890f9c156dc69b77c846510017156d8c0a07cce70edc7c108e57b0cf4122b26a15e724b191481a51b2c914296de9e81d56618b2c339339d4b221930691baa +"@react-spring/types@npm:~10.0.3": + version: 10.0.3 + resolution: "@react-spring/types@npm:10.0.3" + checksum: 10c0/f9bc2619dc9997fe93ebab90fd98118106e53bc45c9c279caaa7081b69d3ed0186d603d5ed445e56bb8ad0075553d15908a2a54e3a0a36ef7cd43a03c1650b02 languageName: node linkType: hard "@react-spring/web@npm:^10.0.0": - version: 10.0.1 - resolution: "@react-spring/web@npm:10.0.1" + version: 10.0.3 + resolution: "@react-spring/web@npm:10.0.3" dependencies: - "@react-spring/animated": "npm:~10.0.1" - "@react-spring/core": "npm:~10.0.1" - "@react-spring/shared": "npm:~10.0.1" - "@react-spring/types": "npm:~10.0.1" + "@react-spring/animated": "npm:~10.0.3" + "@react-spring/core": "npm:~10.0.3" + "@react-spring/shared": "npm:~10.0.3" + "@react-spring/types": "npm:~10.0.3" peerDependencies: react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 - checksum: 10c0/a0c788c9fd881ccb834feb22fc0694e74e59f7b76e498f0096f5b65e2c9812513955bf45ee27d7c5348f56a7bba7c5a6961d4be663728bb2172fe5aa6b6bdfc4 + checksum: 10c0/cafbf55991d68920e94419b5b081cfb0aea2ddfa193e984861ab53306365bf81152bce2861370f9b26d4027dd714e8acc0dfbd57bd2eda99e827c3212e22a51c languageName: node linkType: hard @@ -4512,7 +5033,7 @@ __metadata: languageName: node linkType: hard -"@rollup/pluginutils@npm:^5.0.1": +"@rollup/pluginutils@npm:^5.0.1, @rollup/pluginutils@npm:^5.2.0": version: 5.3.0 resolution: "@rollup/pluginutils@npm:5.3.0" dependencies: @@ -4528,22 +5049,6 @@ __metadata: languageName: node linkType: hard -"@rollup/pluginutils@npm:^5.1.3": - version: 5.1.3 - resolution: "@rollup/pluginutils@npm:5.1.3" - dependencies: - "@types/estree": "npm:^1.0.0" - estree-walker: "npm:^2.0.2" - picomatch: "npm:^4.0.2" - peerDependencies: - rollup: ^1.20.0||^2.0.0||^3.0.0||^4.0.0 - peerDependenciesMeta: - rollup: - optional: true - checksum: 10c0/ba46ad588733fb01d184ee3bc7a127d626158bc840b5874a94c129ff62689d12f16f537530709c54da6f3b71f67d705c4e09235b1dc9542e9d47ee8f2d0b8b9e - languageName: node - linkType: hard - "@rollup/rollup-android-arm-eabi@npm:4.50.1": version: 4.50.1 resolution: "@rollup/rollup-android-arm-eabi@npm:4.50.1" @@ -5041,39 +5546,38 @@ __metadata: linkType: hard "@testing-library/dom@npm:^10.1.0": - version: 10.4.0 - resolution: "@testing-library/dom@npm:10.4.0" + version: 10.4.1 + resolution: "@testing-library/dom@npm:10.4.1" dependencies: "@babel/code-frame": "npm:^7.10.4" "@babel/runtime": "npm:^7.12.5" "@types/aria-query": "npm:^5.0.1" aria-query: "npm:5.3.0" - chalk: "npm:^4.1.0" dom-accessibility-api: "npm:^0.5.9" lz-string: "npm:^1.5.0" + picocolors: "npm:1.1.1" pretty-format: "npm:^27.0.2" - checksum: 10c0/0352487720ecd433400671e773df0b84b8268fb3fe8e527cdfd7c11b1365b398b4e0eddba6e7e0c85e8d615f48257753283fccec41f6b986fd6c85f15eb5f84f + checksum: 10c0/19ce048012d395ad0468b0dbcc4d0911f6f9e39464d7a8464a587b29707eed5482000dad728f5acc4ed314d2f4d54f34982999a114d2404f36d048278db815b1 languageName: node linkType: hard "@testing-library/jest-dom@npm:^6.6.3": - version: 6.6.4 - resolution: "@testing-library/jest-dom@npm:6.6.4" + version: 6.9.1 + resolution: "@testing-library/jest-dom@npm:6.9.1" dependencies: "@adobe/css-tools": "npm:^4.4.0" aria-query: "npm:^5.0.0" css.escape: "npm:^1.5.1" dom-accessibility-api: "npm:^0.6.3" - lodash: "npm:^4.17.21" picocolors: "npm:^1.1.1" redent: "npm:^3.0.0" - checksum: 10c0/cb73adf4910f654f6cc61cfb9a551efdffa04ef423bc7fbfd67a6d8aa31c6c6dc6363fe9db23a35fc7cb32ff1390e6e1c77575c2fa70d8b028a943af32bc214c + checksum: 10c0/4291ebd2f0f38d14cefac142c56c337941775a5807e2a3d6f1a14c2fbd6be76a18e498ed189e95bedc97d9e8cf1738049bc76c85b5bc5e23fae7c9e10f7b3a12 languageName: node linkType: hard "@testing-library/react@npm:^16.0.0": - version: 16.3.0 - resolution: "@testing-library/react@npm:16.3.0" + version: 16.3.1 + resolution: "@testing-library/react@npm:16.3.1" dependencies: "@babel/runtime": "npm:^7.12.5" peerDependencies: @@ -5087,7 +5591,7 @@ __metadata: optional: true "@types/react-dom": optional: true - checksum: 10c0/3a2cb1f87c9a67e1ebbbcfd99b94b01e496fc35147be8bc5d8bf07a699c7d523a09d57ef2f7b1d91afccd1a28e21eda3b00d80187fbb51b1de01e422592d845e + checksum: 10c0/5a26ceaa4ab1d065be722d93e3b019883864ae038f9fd1c974f5b8a173f5f35a25768ecb2baa02a783299f009cbcd09fa7ee0b8b3d360d1c0f81535436358b28 languageName: node linkType: hard @@ -5100,12 +5604,12 @@ __metadata: languageName: node linkType: hard -"@tybys/wasm-util@npm:^0.9.0": - version: 0.9.0 - resolution: "@tybys/wasm-util@npm:0.9.0" +"@tybys/wasm-util@npm:^0.10.1": + version: 0.10.1 + resolution: "@tybys/wasm-util@npm:0.10.1" dependencies: tslib: "npm:^2.4.0" - checksum: 10c0/f9fde5c554455019f33af6c8215f1a1435028803dc2a2825b077d812bed4209a1a64444a4ca0ce2ea7e1175c8d88e2f9173a36a33c199e8a5c671aa31de8242d + checksum: 10c0/b255094f293794c6d2289300c5fbcafbb5532a3aed3a5ffd2f8dc1828e639b88d75f6a376dd8f94347a44813fd7a7149d8463477a9a49525c8b2dcaa38c2d1e8 languageName: node linkType: hard @@ -5280,20 +5784,20 @@ __metadata: linkType: hard "@types/node@npm:*, @types/node@npm:>=13.7.0": - version: 24.1.0 - resolution: "@types/node@npm:24.1.0" + version: 25.0.3 + resolution: "@types/node@npm:25.0.3" dependencies: - undici-types: "npm:~7.8.0" - checksum: 10c0/6c4686bc144f6ce7bffd4cadc3e1196e2217c1da4c639c637213719c8a3ee58b6c596b994befcbffeacd9d9eb0c3bff6529d2bc27da5d1cb9d58b1da0056f9f4 + undici-types: "npm:~7.16.0" + checksum: 10c0/b7568f0d765d9469621615e2bb257c7fd1953d95e9acbdb58dffb6627a2c4150d405a4600aa1ad8a40182a94fe5f903cafd3c0a2f5132814debd0e3bfd61f835 languageName: node linkType: hard "@types/node@npm:^24.0.0": - version: 24.10.0 - resolution: "@types/node@npm:24.10.0" + version: 24.10.4 + resolution: "@types/node@npm:24.10.4" dependencies: undici-types: "npm:~7.16.0" - checksum: 10c0/f82ed7194e16f5590ef7afdc20c6d09068c76d50278b485ede8f0c5749683536e3064ffa8def8db76915196afb3724b854aa5723c64d6571b890b14492943b46 + checksum: 10c0/069639cb7233ee747df1897b5e784f6b6c5da765c96c94773c580aac888fa1a585048d2a6e95eb8302d89c7a9df75801c8b5a0b7d0221d4249059cf09a5f4228 languageName: node linkType: hard @@ -5305,43 +5809,43 @@ __metadata: linkType: hard "@types/pako@npm:^2.0.3": - version: 2.0.3 - resolution: "@types/pako@npm:2.0.3" - checksum: 10c0/45119ac3c4e8a77317c35493327039b74e333562f06ce038048228918d8ddfaa7958125aab960d1565b3861046022754c414dba1eecb210c44a32c415956bee2 + version: 2.0.4 + resolution: "@types/pako@npm:2.0.4" + checksum: 10c0/5765bf8bc7e77ee141c454118f03e544b8f6cb51eb257d82dc5830feeab8cd00818af3a1eabefdfbe8dd3ae9916ed5403937bf1031a0ee51deea27fdf4dccdfb languageName: node linkType: hard "@types/qrcode@npm:^1.5.5": - version: 1.5.5 - resolution: "@types/qrcode@npm:1.5.5" + version: 1.5.6 + resolution: "@types/qrcode@npm:1.5.6" dependencies: "@types/node": "npm:*" - checksum: 10c0/b8e6709905d1edb32dda414408acab18ac4aefcbe7bf96d9e32ba94218f45b99c8938ba7a09863ce82a67b226195099fd0f48881d16ee844899087b7f249955f + checksum: 10c0/84844ca63e5f32bc47d44dda0f8a6f7cdcc7ce44e7b24f10f19d50796f31d12c058f702a8f7d352c9e82a023a9abc36fa1ad01ddf0a209dd8ed4562ea76481fc languageName: node linkType: hard "@types/react-dom@npm:^19.0.0": - version: 19.1.6 - resolution: "@types/react-dom@npm:19.1.6" + version: 19.2.3 + resolution: "@types/react-dom@npm:19.2.3" peerDependencies: - "@types/react": ^19.0.0 - checksum: 10c0/7ba74eee2919e3f225e898b65fdaa16e54952aaf9e3472a080ddc82ca54585e46e60b3c52018d21d4b7053f09d27b8293e9f468b85f9932ff452cd290cc131e8 + "@types/react": ^19.2.0 + checksum: 10c0/b486ebe0f4e2fb35e2e108df1d8fc0927ca5d6002d5771e8a739de11239fe62d0e207c50886185253c99eb9dedfeeb956ea7429e5ba17f6693c7acb4c02f8cd1 languageName: node linkType: hard "@types/react@npm:^19.0.0": - version: 19.1.8 - resolution: "@types/react@npm:19.1.8" + version: 19.2.7 + resolution: "@types/react@npm:19.2.7" dependencies: - csstype: "npm:^3.0.2" - checksum: 10c0/4908772be6dc941df276931efeb0e781777fa76e4d5d12ff9f75eb2dcc2db3065e0100efde16fde562c5bafa310cc8f50c1ee40a22640459e066e72cd342143e + csstype: "npm:^3.2.2" + checksum: 10c0/a7b75f1f9fcb34badd6f84098be5e35a0aeca614bc91f93d2698664c0b2ba5ad128422bd470ada598238cebe4f9e604a752aead7dc6f5a92261d0c7f9b27cfd1 languageName: node linkType: hard "@types/sdp-transform@npm:^2.4.5": - version: 2.4.10 - resolution: "@types/sdp-transform@npm:2.4.10" - checksum: 10c0/3482950907edc1b841a9d550c391b89b1d56f078bed33e83fb01d2de3097c6045d4627fb50b192712ff34c71784b476dce044c4df735808a9d0bfeca1e77df7d + version: 2.15.0 + resolution: "@types/sdp-transform@npm:2.15.0" + checksum: 10c0/8740a51ef3478dcc560952d815edb650680f924e00fcb19eea74a8422640e9a1e18a63d9dda750576598cb1c15b8bb6a68bd5076a9e9ac170d828cb97fa1ff26 languageName: node linkType: hard @@ -5390,23 +5894,22 @@ __metadata: linkType: hard "@typescript-eslint/eslint-plugin@npm:^8.31.0": - version: 8.38.0 - resolution: "@typescript-eslint/eslint-plugin@npm:8.38.0" + version: 8.51.0 + resolution: "@typescript-eslint/eslint-plugin@npm:8.51.0" dependencies: "@eslint-community/regexpp": "npm:^4.10.0" - "@typescript-eslint/scope-manager": "npm:8.38.0" - "@typescript-eslint/type-utils": "npm:8.38.0" - "@typescript-eslint/utils": "npm:8.38.0" - "@typescript-eslint/visitor-keys": "npm:8.38.0" - graphemer: "npm:^1.4.0" + "@typescript-eslint/scope-manager": "npm:8.51.0" + "@typescript-eslint/type-utils": "npm:8.51.0" + "@typescript-eslint/utils": "npm:8.51.0" + "@typescript-eslint/visitor-keys": "npm:8.51.0" ignore: "npm:^7.0.0" natural-compare: "npm:^1.4.0" - ts-api-utils: "npm:^2.1.0" + ts-api-utils: "npm:^2.2.0" peerDependencies: - "@typescript-eslint/parser": ^8.38.0 + "@typescript-eslint/parser": ^8.51.0 eslint: ^8.57.0 || ^9.0.0 - typescript: ">=4.8.4 <5.9.0" - checksum: 10c0/199b82e9f0136baecf515df7c31bfed926a7c6d4e6298f64ee1a77c8bdd7a8cb92a2ea55a5a345c9f2948a02f7be6d72530efbe803afa1892b593fbd529d0c27 + typescript: ">=4.8.4 <6.0.0" + checksum: 10c0/3140e66a0f722338d56bf3de2b7cbb9a74a812d8da90fc61975ea029f6a401252c0824063d4c4baab9827de6f0209b34f4bbdc46e3f5fefd8fa2ff4a3980406f languageName: node linkType: hard @@ -5422,31 +5925,31 @@ __metadata: linkType: hard "@typescript-eslint/parser@npm:^8.31.0": - version: 8.38.0 - resolution: "@typescript-eslint/parser@npm:8.38.0" + version: 8.51.0 + resolution: "@typescript-eslint/parser@npm:8.51.0" dependencies: - "@typescript-eslint/scope-manager": "npm:8.38.0" - "@typescript-eslint/types": "npm:8.38.0" - "@typescript-eslint/typescript-estree": "npm:8.38.0" - "@typescript-eslint/visitor-keys": "npm:8.38.0" + "@typescript-eslint/scope-manager": "npm:8.51.0" + "@typescript-eslint/types": "npm:8.51.0" + "@typescript-eslint/typescript-estree": "npm:8.51.0" + "@typescript-eslint/visitor-keys": "npm:8.51.0" debug: "npm:^4.3.4" peerDependencies: eslint: ^8.57.0 || ^9.0.0 - typescript: ">=4.8.4 <5.9.0" - checksum: 10c0/5580c2a328f0c15f85e4a0961a07584013cc0aca85fe868486187f7c92e9e3f6602c6e3dab917b092b94cd492ed40827c6f5fea42730bef88eb17592c947adf4 + typescript: ">=4.8.4 <6.0.0" + checksum: 10c0/b6aab1d82cc98a77aaae7637bf2934980104799793b3fd5b893065d930fe9b23cd6c2059d6f73fb454ea08f9e956e84fa940310d8435092a14be645a42062d94 languageName: node linkType: hard -"@typescript-eslint/project-service@npm:8.38.0": - version: 8.38.0 - resolution: "@typescript-eslint/project-service@npm:8.38.0" +"@typescript-eslint/project-service@npm:8.51.0": + version: 8.51.0 + resolution: "@typescript-eslint/project-service@npm:8.51.0" dependencies: - "@typescript-eslint/tsconfig-utils": "npm:^8.38.0" - "@typescript-eslint/types": "npm:^8.38.0" + "@typescript-eslint/tsconfig-utils": "npm:^8.51.0" + "@typescript-eslint/types": "npm:^8.51.0" debug: "npm:^4.3.4" peerDependencies: - typescript: ">=4.8.4 <5.9.0" - checksum: 10c0/87d2f55521e289bbcdc666b1f4587ee2d43039cee927310b05abaa534b528dfb1b5565c1545bb4996d7fbdf9d5a3b0aa0e6c93a8f1289e3fcfd60d246364a884 + typescript: ">=4.8.4 <6.0.0" + checksum: 10c0/c6e6efbf79e126261e1742990b0872a34bbbe9931d99f0aabd12cb70a65a361e02d626db4b632dabee2b2c26b7e5b48344fc5a796c56438ae0788535e2bbe092 languageName: node linkType: hard @@ -5470,38 +5973,38 @@ __metadata: languageName: node linkType: hard -"@typescript-eslint/scope-manager@npm:8.38.0": - version: 8.38.0 - resolution: "@typescript-eslint/scope-manager@npm:8.38.0" +"@typescript-eslint/scope-manager@npm:8.51.0": + version: 8.51.0 + resolution: "@typescript-eslint/scope-manager@npm:8.51.0" dependencies: - "@typescript-eslint/types": "npm:8.38.0" - "@typescript-eslint/visitor-keys": "npm:8.38.0" - checksum: 10c0/ceaf489ea1f005afb187932a7ee363dfe1e0f7cc3db921283991e20e4c756411a5e25afbec72edd2095d6a4384f73591f4c750cf65b5eaa650c90f64ef9fe809 + "@typescript-eslint/types": "npm:8.51.0" + "@typescript-eslint/visitor-keys": "npm:8.51.0" + checksum: 10c0/dd1e75fc13e6b1119954612d9e8ad3f2d91bc37dcde85fd00e959171aaf6c716c4c265c90c5accf24b5831bd3f48510b0775e5583085b8fa2ad5c37c8980ae1a languageName: node linkType: hard -"@typescript-eslint/tsconfig-utils@npm:8.38.0, @typescript-eslint/tsconfig-utils@npm:^8.38.0": - version: 8.38.0 - resolution: "@typescript-eslint/tsconfig-utils@npm:8.38.0" +"@typescript-eslint/tsconfig-utils@npm:8.51.0, @typescript-eslint/tsconfig-utils@npm:^8.51.0": + version: 8.51.0 + resolution: "@typescript-eslint/tsconfig-utils@npm:8.51.0" peerDependencies: - typescript: ">=4.8.4 <5.9.0" - checksum: 10c0/1a90da16bf1f7cfbd0303640a8ead64a0080f2b1d5969994bdac3b80abfa1177f0c6fbf61250bae082e72cf5014308f2f5cc98edd6510202f13420a7ffd07a84 + typescript: ">=4.8.4 <6.0.0" + checksum: 10c0/46cab9a5342b4a8f8a1d05aaee4236c5262a540ad0bca1f0e8dad5d63ed1e634b88ce0c82a612976dab09861e21086fc995a368df0435ac43fb960e0b9e5cde2 languageName: node linkType: hard -"@typescript-eslint/type-utils@npm:8.38.0": - version: 8.38.0 - resolution: "@typescript-eslint/type-utils@npm:8.38.0" +"@typescript-eslint/type-utils@npm:8.51.0": + version: 8.51.0 + resolution: "@typescript-eslint/type-utils@npm:8.51.0" dependencies: - "@typescript-eslint/types": "npm:8.38.0" - "@typescript-eslint/typescript-estree": "npm:8.38.0" - "@typescript-eslint/utils": "npm:8.38.0" + "@typescript-eslint/types": "npm:8.51.0" + "@typescript-eslint/typescript-estree": "npm:8.51.0" + "@typescript-eslint/utils": "npm:8.51.0" debug: "npm:^4.3.4" - ts-api-utils: "npm:^2.1.0" + ts-api-utils: "npm:^2.2.0" peerDependencies: eslint: ^8.57.0 || ^9.0.0 - typescript: ">=4.8.4 <5.9.0" - checksum: 10c0/27795c4bd0be395dda3424e57d746639c579b7522af1c17731b915298a6378fd78869e8e141526064b6047db2c86ba06444469ace19c98cda5779d06f4abd37c + typescript: ">=4.8.4 <6.0.0" + checksum: 10c0/7c17214e54bc3a4fe4551d9251ffbac52e84ca46eeae840c0f981994b7cbcc837ef32a2b6d510b02d958a8f568df355e724d9c6938a206716271a1b0c00801b7 languageName: node linkType: hard @@ -5519,10 +6022,10 @@ __metadata: languageName: node linkType: hard -"@typescript-eslint/types@npm:8.38.0, @typescript-eslint/types@npm:^8.38.0": - version: 8.38.0 - resolution: "@typescript-eslint/types@npm:8.38.0" - checksum: 10c0/f0ac0060c98c0f3d1871f107177b6ae25a0f1846ca8bd8cfc7e1f1dd0ddce293cd8ac4a5764d6a767de3503d5d01defcd68c758cb7ba6de52f82b209a918d0d2 +"@typescript-eslint/types@npm:8.51.0, @typescript-eslint/types@npm:^8.51.0": + version: 8.51.0 + resolution: "@typescript-eslint/types@npm:8.51.0" + checksum: 10c0/eb3473d0bb71eb886438f35887b620ffadae7853b281752a40c73158aee644d136adeb82549be7d7c30f346fe888b2e979dff7e30e67b35377e8281018034529 languageName: node linkType: hard @@ -5562,23 +6065,22 @@ __metadata: languageName: node linkType: hard -"@typescript-eslint/typescript-estree@npm:8.38.0": - version: 8.38.0 - resolution: "@typescript-eslint/typescript-estree@npm:8.38.0" +"@typescript-eslint/typescript-estree@npm:8.51.0": + version: 8.51.0 + resolution: "@typescript-eslint/typescript-estree@npm:8.51.0" dependencies: - "@typescript-eslint/project-service": "npm:8.38.0" - "@typescript-eslint/tsconfig-utils": "npm:8.38.0" - "@typescript-eslint/types": "npm:8.38.0" - "@typescript-eslint/visitor-keys": "npm:8.38.0" + "@typescript-eslint/project-service": "npm:8.51.0" + "@typescript-eslint/tsconfig-utils": "npm:8.51.0" + "@typescript-eslint/types": "npm:8.51.0" + "@typescript-eslint/visitor-keys": "npm:8.51.0" debug: "npm:^4.3.4" - fast-glob: "npm:^3.3.2" - is-glob: "npm:^4.0.3" minimatch: "npm:^9.0.4" semver: "npm:^7.6.0" - ts-api-utils: "npm:^2.1.0" + tinyglobby: "npm:^0.2.15" + ts-api-utils: "npm:^2.2.0" peerDependencies: - typescript: ">=4.8.4 <5.9.0" - checksum: 10c0/00a00f6549877f4ae5c2847fa5ac52bf42cbd59a87533856c359e2746e448ed150b27a6137c92fd50c06e6a4b39e386d6b738fac97d80d05596e81ce55933230 + typescript: ">=4.8.4 <6.0.0" + checksum: 10c0/5386acc67298a6757681b6264c29a6b9304be7a188f11498bbaa82bb0a3095fd79394ad80d6520bdff3fa3093199f9a438246604ee3281b76f7ed574b7516854 languageName: node linkType: hard @@ -5600,18 +6102,18 @@ __metadata: languageName: node linkType: hard -"@typescript-eslint/utils@npm:8.38.0": - version: 8.38.0 - resolution: "@typescript-eslint/utils@npm:8.38.0" +"@typescript-eslint/utils@npm:8.51.0": + version: 8.51.0 + resolution: "@typescript-eslint/utils@npm:8.51.0" dependencies: "@eslint-community/eslint-utils": "npm:^4.7.0" - "@typescript-eslint/scope-manager": "npm:8.38.0" - "@typescript-eslint/types": "npm:8.38.0" - "@typescript-eslint/typescript-estree": "npm:8.38.0" + "@typescript-eslint/scope-manager": "npm:8.51.0" + "@typescript-eslint/types": "npm:8.51.0" + "@typescript-eslint/typescript-estree": "npm:8.51.0" peerDependencies: eslint: ^8.57.0 || ^9.0.0 - typescript: ">=4.8.4 <5.9.0" - checksum: 10c0/e97a45bf44f315f9ed8c2988429e18c88e3369c9ee3227ee86446d2d49f7325abebbbc9ce801e178f676baa986d3e1fd4b5391f1640c6eb8944c123423ae43bb + typescript: ">=4.8.4 <6.0.0" + checksum: 10c0/ffb8237cfb33a1998ae2812b136d42fb65e7497f185d46097d19e43112e41b3ef59f901ba679c2e5372ad3007026f6e5add3a3de0f2e75ce6896918713fa38a8 languageName: node linkType: hard @@ -5650,13 +6152,13 @@ __metadata: languageName: node linkType: hard -"@typescript-eslint/visitor-keys@npm:8.38.0": - version: 8.38.0 - resolution: "@typescript-eslint/visitor-keys@npm:8.38.0" +"@typescript-eslint/visitor-keys@npm:8.51.0": + version: 8.51.0 + resolution: "@typescript-eslint/visitor-keys@npm:8.51.0" dependencies: - "@typescript-eslint/types": "npm:8.38.0" + "@typescript-eslint/types": "npm:8.51.0" eslint-visitor-keys: "npm:^4.2.1" - checksum: 10c0/071a756e383f41a6c9e51d78c8c64bd41cd5af68b0faef5fbaec4fa5dbd65ec9e4cd610c2e2cdbe9e2facc362995f202850622b78e821609a277b5b601a1d4ec + checksum: 10c0/fce5603961cf336e71095f7599157de65e3182f61cbd6cab33a43551ee91485b4e9bf6cacc1b275cf6f3503b92f8568fe2267a45c82e60e386ee73db727a26ca languageName: node linkType: hard @@ -6223,21 +6725,20 @@ __metadata: languageName: node linkType: hard -"autoprefixer@npm:^10.4.21": - version: 10.4.21 - resolution: "autoprefixer@npm:10.4.21" +"autoprefixer@npm:^10.4.23": + version: 10.4.23 + resolution: "autoprefixer@npm:10.4.23" dependencies: - browserslist: "npm:^4.24.4" - caniuse-lite: "npm:^1.0.30001702" - fraction.js: "npm:^4.3.7" - normalize-range: "npm:^0.1.2" + browserslist: "npm:^4.28.1" + caniuse-lite: "npm:^1.0.30001760" + fraction.js: "npm:^5.3.4" picocolors: "npm:^1.1.1" postcss-value-parser: "npm:^4.2.0" peerDependencies: postcss: ^8.1.0 bin: autoprefixer: bin/autoprefixer - checksum: 10c0/de5b71d26d0baff4bbfb3d59f7cf7114a6030c9eeb66167acf49a32c5b61c68e308f1e0f869d92334436a221035d08b51cd1b2f2c4689b8d955149423c16d4d4 + checksum: 10c0/3765c5d0fa3e95fb2ebe9d5a6d4da0156f5d346c7ec9ac0fbf5c97c8139d0ca1e8743bf5dc1b4aa954467be6929fddf8498a3b6202d468d70b5f359f3b6af90f languageName: node linkType: hard @@ -6345,6 +6846,15 @@ __metadata: languageName: node linkType: hard +"baseline-browser-mapping@npm:^2.9.0": + version: 2.9.11 + resolution: "baseline-browser-mapping@npm:2.9.11" + bin: + baseline-browser-mapping: dist/cli.js + checksum: 10c0/eba49fcc1b33ab994aeeb73a4848f2670e06a0886dd5b903689ae6f60d47e7f1bea9262dbb2548c48179e858f7eda2b82ddf941ae783b862f4dcc51085a246f2 + languageName: node + linkType: hard + "before-after-hook@npm:^2.2.0": version: 2.2.3 resolution: "before-after-hook@npm:2.2.3" @@ -6560,7 +7070,7 @@ __metadata: languageName: node linkType: hard -"browserslist@npm:^4.24.0, browserslist@npm:^4.24.3, browserslist@npm:^4.24.4": +"browserslist@npm:^4.24.0, browserslist@npm:^4.24.3": version: 4.24.4 resolution: "browserslist@npm:4.24.4" dependencies: @@ -6574,7 +7084,7 @@ __metadata: languageName: node linkType: hard -"browserslist@npm:^4.25.0, browserslist@npm:^4.25.1": +"browserslist@npm:^4.25.1": version: 4.25.1 resolution: "browserslist@npm:4.25.1" dependencies: @@ -6588,6 +7098,21 @@ __metadata: languageName: node linkType: hard +"browserslist@npm:^4.28.1": + version: 4.28.1 + resolution: "browserslist@npm:4.28.1" + dependencies: + baseline-browser-mapping: "npm:^2.9.0" + caniuse-lite: "npm:^1.0.30001759" + electron-to-chromium: "npm:^1.5.263" + node-releases: "npm:^2.0.27" + update-browserslist-db: "npm:^1.2.0" + bin: + browserslist: cli.js + checksum: 10c0/545a5fa9d7234e3777a7177ec1e9134bb2ba60a69e6b95683f6982b1473aad347c77c1264ccf2ac5dea609a9731fbfbda6b85782bdca70f80f86e28a402504bd + languageName: node + linkType: hard + "bs58@npm:^6.0.0": version: 6.0.0 resolution: "bs58@npm:6.0.0" @@ -6762,13 +7287,20 @@ __metadata: languageName: node linkType: hard -"caniuse-lite@npm:^1.0.30001688, caniuse-lite@npm:^1.0.30001702, caniuse-lite@npm:^1.0.30001726": +"caniuse-lite@npm:^1.0.30001688, caniuse-lite@npm:^1.0.30001726": version: 1.0.30001757 resolution: "caniuse-lite@npm:1.0.30001757" checksum: 10c0/3ccb71fa2bf1f8c96ff1bf9b918b08806fed33307e20a3ce3259155fda131eaf96cfcd88d3d309c8fd7f8285cc71d89a3b93648a1c04814da31c301f98508d42 languageName: node linkType: hard +"caniuse-lite@npm:^1.0.30001759, caniuse-lite@npm:^1.0.30001760": + version: 1.0.30001762 + resolution: "caniuse-lite@npm:1.0.30001762" + checksum: 10c0/93707eac5b0240af3f2ce6e2d7ab504a6fefcf9c2f9cd8fb9d488e496a333c61e557dab0472c1b00c17bc386a5dbb792aa4c778cda2d768e17f986617d7aec53 + languageName: node + linkType: hard + "caseless@npm:~0.12.0": version: 0.12.0 resolution: "caseless@npm:0.12.0" @@ -6789,7 +7321,7 @@ __metadata: languageName: node linkType: hard -"chalk@npm:4.1.2, chalk@npm:^4.0.0, chalk@npm:^4.0.2, chalk@npm:^4.1.0, chalk@npm:~4.1.0": +"chalk@npm:4.1.2, chalk@npm:^4.0.0, chalk@npm:^4.0.2, chalk@npm:~4.1.0": version: 4.1.2 resolution: "chalk@npm:4.1.2" dependencies: @@ -7256,16 +7788,16 @@ __metadata: languageName: node linkType: hard -"css-has-pseudo@npm:^7.0.2": - version: 7.0.2 - resolution: "css-has-pseudo@npm:7.0.2" +"css-has-pseudo@npm:^7.0.3": + version: 7.0.3 + resolution: "css-has-pseudo@npm:7.0.3" dependencies: "@csstools/selector-specificity": "npm:^5.0.0" postcss-selector-parser: "npm:^7.0.0" postcss-value-parser: "npm:^4.2.0" peerDependencies: postcss: ^8.4 - checksum: 10c0/456e9ce1eec8a535683c329956acfe53ce5a208345d7f2fcbe662626be8b3c98681e9041d7f4980316714397b0c1c3defde25653d629c396df17803d599c4edf + checksum: 10c0/c89f68e17bed229e9a3e98da5032e1360c83d45d974bc3fb8d6b5358399bca80cce7929e4a621a516a75536edb78678dc486eb41841eeed28cca79e3be4bdc27 languageName: node linkType: hard @@ -7318,10 +7850,10 @@ __metadata: languageName: node linkType: hard -"cssdb@npm:^8.3.0": - version: 8.3.0 - resolution: "cssdb@npm:8.3.0" - checksum: 10c0/56d13cbddd90e63f45f24f71f35314f9718b72760acdf15367e33014eb45df775ae97ec05c08afaa6b4b147c757e9554c1bf39ddcdaeeb26b6c2adfeee503ae7 +"cssdb@npm:^8.6.0": + version: 8.6.0 + resolution: "cssdb@npm:8.6.0" + checksum: 10c0/4bb7b77ba24902e8d481e9514ec0be56e205186a2b7d9f5027fedfe718952c559c62acfd2859f92869f8090da7c2170f83d68170db5058a6ba8d9d5e8ded3b3e languageName: node linkType: hard @@ -7344,10 +7876,10 @@ __metadata: languageName: node linkType: hard -"csstype@npm:^3.0.2": - version: 3.1.3 - resolution: "csstype@npm:3.1.3" - checksum: 10c0/80c089d6f7e0c5b2bd83cf0539ab41474198579584fa10d86d0cafe0642202343cbc119e076a0b1aece191989477081415d66c9fefbf3c957fc2fc4b7009f248 +"csstype@npm:^3.2.2": + version: 3.2.3 + resolution: "csstype@npm:3.2.3" + checksum: 10c0/cd29c51e70fa822f1cecd8641a1445bed7063697469d35633b516e60fe8c1bde04b08f6c5b6022136bb669b64c63d4173af54864510fbb4ee23281801841a3ce languageName: node linkType: hard @@ -7754,6 +8286,13 @@ __metadata: languageName: node linkType: hard +"electron-to-chromium@npm:^1.5.263": + version: 1.5.267 + resolution: "electron-to-chromium@npm:1.5.267" + checksum: 10c0/0732bdb891b657f2e43266a3db8cf86fff6cecdcc8d693a92beff214e136cb5c2ee7dc5945ed75fa1db16e16bad0c38695527a020d15f39e79084e0b2e447621 + languageName: node + linkType: hard + "electron-to-chromium@npm:^1.5.73": version: 1.5.109 resolution: "electron-to-chromium@npm:1.5.109" @@ -7772,16 +8311,16 @@ __metadata: "@codecov/vite-plugin": "npm:^1.3.0" "@fontsource/inconsolata": "npm:^5.1.0" "@fontsource/inter": "npm:^5.1.0" - "@formatjs/intl-durationformat": "npm:^0.7.0" + "@formatjs/intl-durationformat": "npm:^0.9.0" "@formatjs/intl-segmenter": "npm:^11.7.3" "@livekit/components-core": "npm:^0.12.0" "@livekit/components-react": "npm:^2.0.0" "@livekit/protocol": "npm:^1.42.2" - "@livekit/track-processors": "npm:^0.5.5" + "@livekit/track-processors": "npm:^0.7.0" "@mediapipe/tasks-vision": "npm:^0.10.18" "@opentelemetry/api": "npm:^1.4.0" "@opentelemetry/core": "npm:^2.0.0" - "@opentelemetry/exporter-trace-otlp-http": "npm:^0.203.0" + "@opentelemetry/exporter-trace-otlp-http": "npm:^0.208.0" "@opentelemetry/resources": "npm:^2.0.0" "@opentelemetry/sdk-trace-base": "npm:^2.0.0" "@opentelemetry/sdk-trace-web": "npm:^2.0.0" @@ -8283,6 +8822,95 @@ __metadata: languageName: node linkType: hard +"esbuild@npm:^0.27.0": + version: 0.27.2 + resolution: "esbuild@npm:0.27.2" + dependencies: + "@esbuild/aix-ppc64": "npm:0.27.2" + "@esbuild/android-arm": "npm:0.27.2" + "@esbuild/android-arm64": "npm:0.27.2" + "@esbuild/android-x64": "npm:0.27.2" + "@esbuild/darwin-arm64": "npm:0.27.2" + "@esbuild/darwin-x64": "npm:0.27.2" + "@esbuild/freebsd-arm64": "npm:0.27.2" + "@esbuild/freebsd-x64": "npm:0.27.2" + "@esbuild/linux-arm": "npm:0.27.2" + "@esbuild/linux-arm64": "npm:0.27.2" + "@esbuild/linux-ia32": "npm:0.27.2" + "@esbuild/linux-loong64": "npm:0.27.2" + "@esbuild/linux-mips64el": "npm:0.27.2" + "@esbuild/linux-ppc64": "npm:0.27.2" + "@esbuild/linux-riscv64": "npm:0.27.2" + "@esbuild/linux-s390x": "npm:0.27.2" + "@esbuild/linux-x64": "npm:0.27.2" + "@esbuild/netbsd-arm64": "npm:0.27.2" + "@esbuild/netbsd-x64": "npm:0.27.2" + "@esbuild/openbsd-arm64": "npm:0.27.2" + "@esbuild/openbsd-x64": "npm:0.27.2" + "@esbuild/openharmony-arm64": "npm:0.27.2" + "@esbuild/sunos-x64": "npm:0.27.2" + "@esbuild/win32-arm64": "npm:0.27.2" + "@esbuild/win32-ia32": "npm:0.27.2" + "@esbuild/win32-x64": "npm:0.27.2" + dependenciesMeta: + "@esbuild/aix-ppc64": + optional: true + "@esbuild/android-arm": + optional: true + "@esbuild/android-arm64": + optional: true + "@esbuild/android-x64": + optional: true + "@esbuild/darwin-arm64": + optional: true + "@esbuild/darwin-x64": + optional: true + "@esbuild/freebsd-arm64": + optional: true + "@esbuild/freebsd-x64": + optional: true + "@esbuild/linux-arm": + optional: true + "@esbuild/linux-arm64": + optional: true + "@esbuild/linux-ia32": + optional: true + "@esbuild/linux-loong64": + optional: true + "@esbuild/linux-mips64el": + optional: true + "@esbuild/linux-ppc64": + optional: true + "@esbuild/linux-riscv64": + optional: true + "@esbuild/linux-s390x": + optional: true + "@esbuild/linux-x64": + optional: true + "@esbuild/netbsd-arm64": + optional: true + "@esbuild/netbsd-x64": + optional: true + "@esbuild/openbsd-arm64": + optional: true + "@esbuild/openbsd-x64": + optional: true + "@esbuild/openharmony-arm64": + optional: true + "@esbuild/sunos-x64": + optional: true + "@esbuild/win32-arm64": + optional: true + "@esbuild/win32-ia32": + optional: true + "@esbuild/win32-x64": + optional: true + bin: + esbuild: bin/esbuild + checksum: 10c0/cf83f626f55500f521d5fe7f4bc5871bec240d3deb2a01fbd379edc43b3664d1167428738a5aad8794b35d1cca985c44c375b1cd38a2ca613c77ced2c83aafcd + languageName: node + linkType: hard + "escalade@npm:^3.1.1, escalade@npm:^3.2.0": version: 3.2.0 resolution: "escalade@npm:3.2.0" @@ -8943,21 +9571,21 @@ __metadata: languageName: node linkType: hard -"formatly@npm:^0.2.4": - version: 0.2.4 - resolution: "formatly@npm:0.2.4" +"formatly@npm:^0.3.0": + version: 0.3.0 + resolution: "formatly@npm:0.3.0" dependencies: fd-package-json: "npm:^2.0.0" bin: formatly: bin/index.mjs - checksum: 10c0/43c6272a12199bc6319e7ef7043f209e7005fc35bc1b15e96ef16ad46a12fddc2b7c179fe8ade174c728e8454e3ebdc8428867cee78b082d18a91dae72866336 + checksum: 10c0/ef9dbd3cdaee649e9604ea060d8d62d8131eb81117634336592ee2193fc7c98a3f1f1b5d09a045dbd36287ba88edf868ef179d39fbda2f34fbe2be70c42dd014 languageName: node linkType: hard -"fraction.js@npm:^4.3.7": - version: 4.3.7 - resolution: "fraction.js@npm:4.3.7" - checksum: 10c0/df291391beea9ab4c263487ffd9d17fed162dbb736982dee1379b2a8cc94e4e24e46ed508c6d278aded9080ba51872f1bc5f3a5fd8d7c74e5f105b508ac28711 +"fraction.js@npm:^5.3.4": + version: 5.3.4 + resolution: "fraction.js@npm:5.3.4" + checksum: 10c0/f90079fe9bfc665e0a07079938e8ff71115bce9462f17b32fc283f163b0540ec34dc33df8ed41bb56f028316b04361b9a9995b9ee9258617f8338e0b05c5f95a languageName: node linkType: hard @@ -10240,12 +10868,12 @@ __metadata: languageName: node linkType: hard -"jiti@npm:^2.4.2": - version: 2.4.2 - resolution: "jiti@npm:2.4.2" +"jiti@npm:^2.6.0": + version: 2.6.1 + resolution: "jiti@npm:2.6.1" bin: jiti: lib/jiti-cli.mjs - checksum: 10c0/4ceac133a08c8faff7eac84aabb917e85e8257f5ad659e843004ce76e981c457c390a220881748ac67ba1b940b9b729b30fb85cbaf6e7989f04b6002c94da331 + checksum: 10c0/79b2e96a8e623f66c1b703b98ec1b8be4500e1d217e09b09e343471bbb9c105381b83edbb979d01cef18318cc45ce6e153571b6c83122170eefa531c64b6789b languageName: node linkType: hard @@ -10288,6 +10916,17 @@ __metadata: languageName: node linkType: hard +"js-yaml@npm:^4.1.1": + version: 4.1.1 + resolution: "js-yaml@npm:4.1.1" + dependencies: + argparse: "npm:^2.0.1" + bin: + js-yaml: bin/js-yaml.js + checksum: 10c0/561c7d7088c40a9bb53cc75becbfb1df6ae49b34b5e6e5a81744b14ae8667ec564ad2527709d1a6e7d5e5fa6d483aa0f373a50ad98d42fde368ec4a190d4fae7 + languageName: node + linkType: hard + "jsbn@npm:1.1.0": version: 1.1.0 resolution: "jsbn@npm:1.1.0" @@ -10464,29 +11103,28 @@ __metadata: linkType: hard "knip@npm:^5.27.2": - version: 5.62.0 - resolution: "knip@npm:5.62.0" + version: 5.79.0 + resolution: "knip@npm:5.79.0" dependencies: "@nodelib/fs.walk": "npm:^1.2.3" fast-glob: "npm:^3.3.3" - formatly: "npm:^0.2.4" - jiti: "npm:^2.4.2" - js-yaml: "npm:^4.1.0" + formatly: "npm:^0.3.0" + jiti: "npm:^2.6.0" + js-yaml: "npm:^4.1.1" minimist: "npm:^1.2.8" - oxc-resolver: "npm:^11.1.0" + oxc-resolver: "npm:^11.15.0" picocolors: "npm:^1.1.1" picomatch: "npm:^4.0.1" - smol-toml: "npm:^1.3.4" - strip-json-comments: "npm:5.0.2" - zod: "npm:^3.22.4" - zod-validation-error: "npm:^3.0.3" + smol-toml: "npm:^1.5.2" + strip-json-comments: "npm:5.0.3" + zod: "npm:^4.1.11" peerDependencies: "@types/node": ">=18" - typescript: ">=5.0.4" + typescript: ">=5.0.4 <7" bin: knip: bin/knip.js knip-bun: bin/knip-bun.js - checksum: 10c0/ffc6c123d132bb423936859c3ae5cb85154cfc862985f74637bc54a4920ef34c1f19d41020f7af25100ea8e7ae61f1f5279af8066043434444bcba82b8dc1611 + checksum: 10c0/dc3599247763912c0602621b83d125cba4e111d85ec5f01f9b65808a0091a60d7be85ed6cecc93d0afb39b895127231f7a68dd4c4bb7e210dd727b6ef9c1571d languageName: node linkType: hard @@ -10576,9 +11214,9 @@ __metadata: linkType: hard "lodash-es@npm:^4.17.21": - version: 4.17.21 - resolution: "lodash-es@npm:4.17.21" - checksum: 10c0/fb407355f7e6cd523a9383e76e6b455321f0f153a6c9625e21a8827d10c54c2a2341bd2ae8d034358b60e07325e1330c14c224ff582d04612a46a4f0479ff2f2 + version: 4.17.22 + resolution: "lodash-es@npm:4.17.22" + checksum: 10c0/5f28a262183cca43e08c580622557f393cb889386df2d8adf7c852bfdff7a84c5e629df5aa6c5c6274e83b38172f239d3e4e72e1ad27352d9ae9766627338089 languageName: node linkType: hard @@ -10596,13 +11234,6 @@ __metadata: languageName: node linkType: hard -"lodash@npm:^4.17.21": - version: 4.17.21 - resolution: "lodash@npm:4.17.21" - checksum: 10c0/d8cbea072bb08655bb4c989da418994b073a608dffa608b09ac04b43a791b12aeae7cd7ad919aa4c925f33b48490b5cfe6c1f71d827956071dae2e7bb3a6b74c - languageName: node - linkType: hard - "loglevel@npm:1.9.1": version: 1.9.1 resolution: "loglevel@npm:1.9.1" @@ -11139,6 +11770,13 @@ __metadata: languageName: node linkType: hard +"node-releases@npm:^2.0.27": + version: 2.0.27 + resolution: "node-releases@npm:2.0.27" + checksum: 10c0/f1e6583b7833ea81880627748d28a3a7ff5703d5409328c216ae57befbced10ce2c991bea86434e8ec39003bd017f70481e2e5f8c1f7e0a7663241f81d6e00e2 + languageName: node + linkType: hard + "node-stdlib-browser@npm:^1.3.1": version: 1.3.1 resolution: "node-stdlib-browser@npm:1.3.1" @@ -11204,13 +11842,6 @@ __metadata: languageName: node linkType: hard -"normalize-range@npm:^0.1.2": - version: 0.1.2 - resolution: "normalize-range@npm:0.1.2" - checksum: 10c0/bf39b73a63e0a42ad1a48c2bd1bda5a07ede64a7e2567307a407674e595bcff0fa0d57e8e5f1e7fa5e91000797c7615e13613227aaaa4d6d6e87f5bd5cc95de6 - languageName: node - linkType: hard - "normalize.css@npm:^8.0.1": version: 8.0.1 resolution: "normalize.css@npm:8.0.1" @@ -11403,24 +12034,35 @@ __metadata: languageName: node linkType: hard -"oxc-resolver@npm:^11.1.0": - version: 11.3.0 - resolution: "oxc-resolver@npm:11.3.0" +"oxc-resolver@npm:^11.15.0": + version: 11.16.2 + resolution: "oxc-resolver@npm:11.16.2" dependencies: - "@oxc-resolver/binding-darwin-arm64": "npm:11.3.0" - "@oxc-resolver/binding-darwin-x64": "npm:11.3.0" - "@oxc-resolver/binding-freebsd-x64": "npm:11.3.0" - "@oxc-resolver/binding-linux-arm-gnueabihf": "npm:11.3.0" - "@oxc-resolver/binding-linux-arm64-gnu": "npm:11.3.0" - "@oxc-resolver/binding-linux-arm64-musl": "npm:11.3.0" - "@oxc-resolver/binding-linux-riscv64-gnu": "npm:11.3.0" - "@oxc-resolver/binding-linux-s390x-gnu": "npm:11.3.0" - "@oxc-resolver/binding-linux-x64-gnu": "npm:11.3.0" - "@oxc-resolver/binding-linux-x64-musl": "npm:11.3.0" - "@oxc-resolver/binding-wasm32-wasi": "npm:11.3.0" - "@oxc-resolver/binding-win32-arm64-msvc": "npm:11.3.0" - "@oxc-resolver/binding-win32-x64-msvc": "npm:11.3.0" + "@oxc-resolver/binding-android-arm-eabi": "npm:11.16.2" + "@oxc-resolver/binding-android-arm64": "npm:11.16.2" + "@oxc-resolver/binding-darwin-arm64": "npm:11.16.2" + "@oxc-resolver/binding-darwin-x64": "npm:11.16.2" + "@oxc-resolver/binding-freebsd-x64": "npm:11.16.2" + "@oxc-resolver/binding-linux-arm-gnueabihf": "npm:11.16.2" + "@oxc-resolver/binding-linux-arm-musleabihf": "npm:11.16.2" + "@oxc-resolver/binding-linux-arm64-gnu": "npm:11.16.2" + "@oxc-resolver/binding-linux-arm64-musl": "npm:11.16.2" + "@oxc-resolver/binding-linux-ppc64-gnu": "npm:11.16.2" + "@oxc-resolver/binding-linux-riscv64-gnu": "npm:11.16.2" + "@oxc-resolver/binding-linux-riscv64-musl": "npm:11.16.2" + "@oxc-resolver/binding-linux-s390x-gnu": "npm:11.16.2" + "@oxc-resolver/binding-linux-x64-gnu": "npm:11.16.2" + "@oxc-resolver/binding-linux-x64-musl": "npm:11.16.2" + "@oxc-resolver/binding-openharmony-arm64": "npm:11.16.2" + "@oxc-resolver/binding-wasm32-wasi": "npm:11.16.2" + "@oxc-resolver/binding-win32-arm64-msvc": "npm:11.16.2" + "@oxc-resolver/binding-win32-ia32-msvc": "npm:11.16.2" + "@oxc-resolver/binding-win32-x64-msvc": "npm:11.16.2" dependenciesMeta: + "@oxc-resolver/binding-android-arm-eabi": + optional: true + "@oxc-resolver/binding-android-arm64": + optional: true "@oxc-resolver/binding-darwin-arm64": optional: true "@oxc-resolver/binding-darwin-x64": @@ -11429,25 +12071,35 @@ __metadata: optional: true "@oxc-resolver/binding-linux-arm-gnueabihf": optional: true + "@oxc-resolver/binding-linux-arm-musleabihf": + optional: true "@oxc-resolver/binding-linux-arm64-gnu": optional: true "@oxc-resolver/binding-linux-arm64-musl": optional: true + "@oxc-resolver/binding-linux-ppc64-gnu": + optional: true "@oxc-resolver/binding-linux-riscv64-gnu": optional: true + "@oxc-resolver/binding-linux-riscv64-musl": + optional: true "@oxc-resolver/binding-linux-s390x-gnu": optional: true "@oxc-resolver/binding-linux-x64-gnu": optional: true "@oxc-resolver/binding-linux-x64-musl": optional: true + "@oxc-resolver/binding-openharmony-arm64": + optional: true "@oxc-resolver/binding-wasm32-wasi": optional: true "@oxc-resolver/binding-win32-arm64-msvc": optional: true + "@oxc-resolver/binding-win32-ia32-msvc": + optional: true "@oxc-resolver/binding-win32-x64-msvc": optional: true - checksum: 10c0/9437976bd39125538e031b89e75e29e7340b844da16afa1088d2c2a21770051a81f583dd77823894d7065ee2dc6431d8c5f158ac227035d33b430b78efa358dc + checksum: 10c0/b20a0fea18fdf31dbaee51354ce7b987ba8f3e780c6c1de9034628033a69d0b3085f9596d9925797d9340bdf4b98cd72a258b0728d0d5e5de2b1748154921b42 languageName: node linkType: hard @@ -11707,7 +12359,7 @@ __metadata: languageName: node linkType: hard -"picocolors@npm:^1.0.0, picocolors@npm:^1.1.1": +"picocolors@npm:1.1.1, picocolors@npm:^1.0.0, picocolors@npm:^1.1.1": version: 1.1.1 resolution: "picocolors@npm:1.1.1" checksum: 10c0/e2e3e8170ab9d7c7421969adaa7e1b31434f789afb9b3f115f6b96d91945041ac3ceb02e9ec6fe6510ff036bcc0bf91e69a1772edc0b707e12b19c0f2d6bcf58 @@ -11811,18 +12463,18 @@ __metadata: languageName: node linkType: hard -"postcss-color-functional-notation@npm:^7.0.10": - version: 7.0.10 - resolution: "postcss-color-functional-notation@npm:7.0.10" +"postcss-color-functional-notation@npm:^7.0.12": + version: 7.0.12 + resolution: "postcss-color-functional-notation@npm:7.0.12" dependencies: - "@csstools/css-color-parser": "npm:^3.0.10" + "@csstools/css-color-parser": "npm:^3.1.0" "@csstools/css-parser-algorithms": "npm:^3.0.5" "@csstools/css-tokenizer": "npm:^3.0.4" - "@csstools/postcss-progressive-custom-properties": "npm:^4.1.0" + "@csstools/postcss-progressive-custom-properties": "npm:^4.2.1" "@csstools/utilities": "npm:^2.0.0" peerDependencies: postcss: ^8.4 - checksum: 10c0/62ee77ef220488cfb4a1c5af4f5203a0c2951c8a0613088ffc946130d48b63ca28ab67b18ed380a288a7ce51c2360a75d8d08d2db389e48f4ebb78a3e52d15b6 + checksum: 10c0/dc80ba1a956ae9b396596bda72d9bdb92de96874378a38ba4e2177ffa35339dc76d894920bb013b6f10c9b75cfb41778e09956a438c2e9ea41b684f766c55f4a languageName: node linkType: hard @@ -11904,16 +12556,16 @@ __metadata: languageName: node linkType: hard -"postcss-double-position-gradients@npm:^6.0.2": - version: 6.0.2 - resolution: "postcss-double-position-gradients@npm:6.0.2" +"postcss-double-position-gradients@npm:^6.0.4": + version: 6.0.4 + resolution: "postcss-double-position-gradients@npm:6.0.4" dependencies: - "@csstools/postcss-progressive-custom-properties": "npm:^4.1.0" + "@csstools/postcss-progressive-custom-properties": "npm:^4.2.1" "@csstools/utilities": "npm:^2.0.0" postcss-value-parser: "npm:^4.2.0" peerDependencies: postcss: ^8.4 - checksum: 10c0/7b4759813f99039c6a7c8e70b46ff4c34c27e723a9ff7f0e1044e293d568357e1d39233f94b1bf3b2768b1207348138faea0781086a66b7b8e39e780657da523 + checksum: 10c0/6dbbe7a3855e84a9319df434e210225f6dfa7262e5959611355f1769c2c9d30d37a19737712f20eac6354876fff4ba556d8d0b12a90c78d8ab97c9a8da534a7c languageName: node linkType: hard @@ -11969,18 +12621,18 @@ __metadata: languageName: node linkType: hard -"postcss-lab-function@npm:^7.0.10": - version: 7.0.10 - resolution: "postcss-lab-function@npm:7.0.10" +"postcss-lab-function@npm:^7.0.12": + version: 7.0.12 + resolution: "postcss-lab-function@npm:7.0.12" dependencies: - "@csstools/css-color-parser": "npm:^3.0.10" + "@csstools/css-color-parser": "npm:^3.1.0" "@csstools/css-parser-algorithms": "npm:^3.0.5" "@csstools/css-tokenizer": "npm:^3.0.4" - "@csstools/postcss-progressive-custom-properties": "npm:^4.1.0" + "@csstools/postcss-progressive-custom-properties": "npm:^4.2.1" "@csstools/utilities": "npm:^2.0.0" peerDependencies: postcss: ^8.4 - checksum: 10c0/3e235b52f6c119937a0b41aa351f5f9ef6e17bf1b868e7068c9a04f3d31c247d0296c862388febb7fec5102d81413ccade8a4788904289afd34aa072de71390b + checksum: 10c0/de39b59da3b97c18d055d81fba68993e93253184ed76f103c888273584f868c551d047814dd54445980a1bdc5987e8f8af141383d84ecc641e5a6ee7bd901095 languageName: node linkType: hard @@ -12049,23 +12701,26 @@ __metadata: linkType: hard "postcss-preset-env@npm:^10.0.0": - version: 10.2.4 - resolution: "postcss-preset-env@npm:10.2.4" + version: 10.6.0 + resolution: "postcss-preset-env@npm:10.6.0" dependencies: + "@csstools/postcss-alpha-function": "npm:^1.0.1" "@csstools/postcss-cascade-layers": "npm:^5.0.2" - "@csstools/postcss-color-function": "npm:^4.0.10" - "@csstools/postcss-color-mix-function": "npm:^3.0.10" - "@csstools/postcss-color-mix-variadic-function-arguments": "npm:^1.0.0" - "@csstools/postcss-content-alt-text": "npm:^2.0.6" + "@csstools/postcss-color-function": "npm:^4.0.12" + "@csstools/postcss-color-function-display-p3-linear": "npm:^1.0.1" + "@csstools/postcss-color-mix-function": "npm:^3.0.12" + "@csstools/postcss-color-mix-variadic-function-arguments": "npm:^1.0.2" + "@csstools/postcss-content-alt-text": "npm:^2.0.8" + "@csstools/postcss-contrast-color-function": "npm:^2.0.12" "@csstools/postcss-exponential-functions": "npm:^2.0.9" "@csstools/postcss-font-format-keywords": "npm:^4.0.0" - "@csstools/postcss-gamut-mapping": "npm:^2.0.10" - "@csstools/postcss-gradients-interpolation-method": "npm:^5.0.10" - "@csstools/postcss-hwb-function": "npm:^4.0.10" - "@csstools/postcss-ic-unit": "npm:^4.0.2" + "@csstools/postcss-gamut-mapping": "npm:^2.0.11" + "@csstools/postcss-gradients-interpolation-method": "npm:^5.0.12" + "@csstools/postcss-hwb-function": "npm:^4.0.12" + "@csstools/postcss-ic-unit": "npm:^4.0.4" "@csstools/postcss-initial": "npm:^2.0.1" "@csstools/postcss-is-pseudo-class": "npm:^5.0.3" - "@csstools/postcss-light-dark-function": "npm:^2.0.9" + "@csstools/postcss-light-dark-function": "npm:^2.0.11" "@csstools/postcss-logical-float-and-clear": "npm:^3.0.0" "@csstools/postcss-logical-overflow": "npm:^2.0.0" "@csstools/postcss-logical-overscroll-behavior": "npm:^2.0.0" @@ -12075,38 +12730,42 @@ __metadata: "@csstools/postcss-media-queries-aspect-ratio-number-values": "npm:^3.0.5" "@csstools/postcss-nested-calc": "npm:^4.0.0" "@csstools/postcss-normalize-display-values": "npm:^4.0.0" - "@csstools/postcss-oklab-function": "npm:^4.0.10" - "@csstools/postcss-progressive-custom-properties": "npm:^4.1.0" + "@csstools/postcss-oklab-function": "npm:^4.0.12" + "@csstools/postcss-position-area-property": "npm:^1.0.0" + "@csstools/postcss-progressive-custom-properties": "npm:^4.2.1" + "@csstools/postcss-property-rule-prelude-list": "npm:^1.0.0" "@csstools/postcss-random-function": "npm:^2.0.1" - "@csstools/postcss-relative-color-syntax": "npm:^3.0.10" + "@csstools/postcss-relative-color-syntax": "npm:^3.0.12" "@csstools/postcss-scope-pseudo-class": "npm:^4.0.1" "@csstools/postcss-sign-functions": "npm:^1.1.4" "@csstools/postcss-stepped-value-functions": "npm:^4.0.9" - "@csstools/postcss-text-decoration-shorthand": "npm:^4.0.2" + "@csstools/postcss-syntax-descriptor-syntax-production": "npm:^1.0.1" + "@csstools/postcss-system-ui-font-family": "npm:^1.0.0" + "@csstools/postcss-text-decoration-shorthand": "npm:^4.0.3" "@csstools/postcss-trigonometric-functions": "npm:^4.0.9" "@csstools/postcss-unset-value": "npm:^4.0.0" - autoprefixer: "npm:^10.4.21" - browserslist: "npm:^4.25.0" + autoprefixer: "npm:^10.4.23" + browserslist: "npm:^4.28.1" css-blank-pseudo: "npm:^7.0.1" - css-has-pseudo: "npm:^7.0.2" + css-has-pseudo: "npm:^7.0.3" css-prefers-color-scheme: "npm:^10.0.0" - cssdb: "npm:^8.3.0" + cssdb: "npm:^8.6.0" postcss-attribute-case-insensitive: "npm:^7.0.1" postcss-clamp: "npm:^4.1.0" - postcss-color-functional-notation: "npm:^7.0.10" + postcss-color-functional-notation: "npm:^7.0.12" postcss-color-hex-alpha: "npm:^10.0.0" postcss-color-rebeccapurple: "npm:^10.0.0" postcss-custom-media: "npm:^11.0.6" postcss-custom-properties: "npm:^14.0.6" postcss-custom-selectors: "npm:^8.0.5" postcss-dir-pseudo-class: "npm:^9.0.1" - postcss-double-position-gradients: "npm:^6.0.2" + postcss-double-position-gradients: "npm:^6.0.4" postcss-focus-visible: "npm:^10.0.1" postcss-focus-within: "npm:^9.0.1" postcss-font-variant: "npm:^5.0.0" postcss-gap-properties: "npm:^6.0.0" postcss-image-set-function: "npm:^7.0.0" - postcss-lab-function: "npm:^7.0.10" + postcss-lab-function: "npm:^7.0.12" postcss-logical: "npm:^8.1.0" postcss-nesting: "npm:^13.0.2" postcss-opacity-percentage: "npm:^3.0.0" @@ -12118,7 +12777,7 @@ __metadata: postcss-selector-not: "npm:^8.0.1" peerDependencies: postcss: ^8.4 - checksum: 10c0/d7f8494d355567dc4ea66fe765c86ba9b1e9ce5061ada5c80c51fdf6c98b004b0b7ef17b5f64d197e1bec2e22ef4b6c613b998e1c1bcad0b53f0a3e303ded2fe + checksum: 10c0/61162c9d675004db842d58829605c3c9ee81ed1a15684793a419b94c2c28e3be2ff9a7373f0996a1a255caf208d8f3d5dd907e61af1bbb0c7634e3215e87fc56 languageName: node linkType: hard @@ -12207,11 +12866,11 @@ __metadata: linkType: hard "prettier@npm:^3.0.0": - version: 3.6.2 - resolution: "prettier@npm:3.6.2" + version: 3.7.4 + resolution: "prettier@npm:3.7.4" bin: prettier: bin/prettier.cjs - checksum: 10c0/488cb2f2b99ec13da1e50074912870217c11edaddedeadc649b1244c749d15ba94e846423d062e2c4c9ae683e2d65f754de28889ba06e697ac4f988d44f45812 + checksum: 10c0/9675d2cd08eacb1faf1d1a2dbfe24bfab6a912b059fc9defdb380a408893d88213e794a40a2700bd29b140eb3172e0b07c852853f6e22f16f3374659a1a13389 languageName: node linkType: hard @@ -12414,24 +13073,24 @@ __metadata: linkType: hard "react-dom@npm:19": - version: 19.1.0 - resolution: "react-dom@npm:19.1.0" + version: 19.2.3 + resolution: "react-dom@npm:19.2.3" dependencies: - scheduler: "npm:^0.26.0" + scheduler: "npm:^0.27.0" peerDependencies: - react: ^19.1.0 - checksum: 10c0/3e26e89bb6c67c9a6aa86cb888c7a7f8258f2e347a6d2a15299c17eb16e04c19194e3452bc3255bd34000a61e45e2cb51e46292392340432f133e5a5d2dfb5fc + react: ^19.2.3 + checksum: 10c0/dc43f7ede06f46f3acc16ee83107c925530de9b91d1d0b3824583814746ff4c498ea64fd65cd83aba363205268adff52e2827c582634ae7b15069deaeabc4892 languageName: node linkType: hard "react-i18next@npm:^15.0.0": - version: 15.6.1 - resolution: "react-i18next@npm:15.6.1" + version: 15.7.4 + resolution: "react-i18next@npm:15.7.4" dependencies: "@babel/runtime": "npm:^7.27.6" html-parse-stringify: "npm:^3.0.1" peerDependencies: - i18next: ">= 23.2.3" + i18next: ">= 23.4.0" react: ">= 16.8.0" typescript: ^5 peerDependenciesMeta: @@ -12441,7 +13100,7 @@ __metadata: optional: true typescript: optional: true - checksum: 10c0/10cd131005a70a493e307f4f710ea9921d5a955a5281064cad79162e5051e2bcfc119f50c7bee0fad06e33a1795308a006089d5b67969d52b66afbe149514305 + checksum: 10c0/643c5d3ced4b44084c871a55e876159561c14f378f90bf53286c1291082703e293573da18ad692b43b357b60d2f7251bc417feb0b522de8cec5c414e5ebdf6c1 languageName: node linkType: hard @@ -12521,20 +13180,20 @@ __metadata: linkType: hard "react-router-dom@npm:^7.0.0": - version: 7.7.1 - resolution: "react-router-dom@npm:7.7.1" + version: 7.11.0 + resolution: "react-router-dom@npm:7.11.0" dependencies: - react-router: "npm:7.7.1" + react-router: "npm:7.11.0" peerDependencies: react: ">=18" react-dom: ">=18" - checksum: 10c0/292455db6991d8559a9e94857440393d9fd011471ff231f8c3a40be6749f74347f20c183a2e9b52830ec54d2bf3b2e1310c006e709e66b27206b0c36ab54def6 + checksum: 10c0/0e8061fe0ef7915cc411dd92f5f41109f6343b6abef36571b08ff231365bf61f52364bea128d1c964e9b8eb19426c9bd21923df0b3e1bb993d21bd2b7440fb49 languageName: node linkType: hard -"react-router@npm:7.7.1": - version: 7.7.1 - resolution: "react-router@npm:7.7.1" +"react-router@npm:7.11.0": + version: 7.11.0 + resolution: "react-router@npm:7.11.0" dependencies: cookie: "npm:^1.0.1" set-cookie-parser: "npm:^2.6.0" @@ -12544,7 +13203,7 @@ __metadata: peerDependenciesMeta: react-dom: optional: true - checksum: 10c0/e55fe74a2947939526c79e496ab1fc501fd8e89a191a20157d94cfe712d4d9d84f68627811cf1d477a36b98250fcad958bf1237fc41ff0a8b2de00ddc8c53e3b + checksum: 10c0/eb3693d63d1c52221a3449de5db170e2fa9e00536b011998b17f8a277f8b5e89b752d104dbbeb4ee3d474f8e4570167db00293b4510f63277e5e6658c5dab22b languageName: node linkType: hard @@ -12578,9 +13237,9 @@ __metadata: linkType: hard "react@npm:19": - version: 19.1.0 - resolution: "react@npm:19.1.0" - checksum: 10c0/530fb9a62237d54137a13d2cfb67a7db6a2156faed43eecc423f4713d9b20c6f2728b026b45e28fcd72e8eadb9e9ed4b089e99f5e295d2f0ad3134251bdd3698 + version: 19.2.3 + resolution: "react@npm:19.2.3" + checksum: 10c0/094220b3ba3a76c1b668f972ace1dd15509b157aead1b40391d1c8e657e720c201d9719537375eff08f5e0514748c0319063392a6f000e31303aafc4471f1436 languageName: node linkType: hard @@ -13187,8 +13846,8 @@ __metadata: linkType: hard "sass@npm:^1.42.1": - version: 1.89.2 - resolution: "sass@npm:1.89.2" + version: 1.97.1 + resolution: "sass@npm:1.97.1" dependencies: "@parcel/watcher": "npm:^2.4.1" chokidar: "npm:^4.0.0" @@ -13199,7 +13858,7 @@ __metadata: optional: true bin: sass: sass.js - checksum: 10c0/752ccc7581b0c6395f63918116c20924e99943a86d79e94f5c4a0d41b1e981fe1f0ecd1ee82fff21496f81dbc91f68fb35a498166562ec8ec53e7aad7c3dbd9d + checksum: 10c0/c389d5d6405869b49fa2291e8328500fe7936f3b72136bc2c338bee6e7fec936bb9a48d77a1310dea66aa4669ba74ae6b82a112eb32521b9b36d740138a39ea0 languageName: node linkType: hard @@ -13212,10 +13871,10 @@ __metadata: languageName: node linkType: hard -"scheduler@npm:^0.26.0": - version: 0.26.0 - resolution: "scheduler@npm:0.26.0" - checksum: 10c0/5b8d5bfddaae3513410eda54f2268e98a376a429931921a81b5c3a2873aab7ca4d775a8caac5498f8cbc7d0daeab947cf923dbd8e215d61671f9f4e392d34356 +"scheduler@npm:^0.27.0": + version: 0.27.0 + resolution: "scheduler@npm:0.27.0" + checksum: 10c0/4f03048cb05a3c8fddc45813052251eca00688f413a3cee236d984a161da28db28ba71bd11e7a3dd02f7af84ab28d39fb311431d3b3772fed557945beb00c452 languageName: node linkType: hard @@ -13450,10 +14109,10 @@ __metadata: languageName: node linkType: hard -"smol-toml@npm:^1.3.4": - version: 1.4.0 - resolution: "smol-toml@npm:1.4.0" - checksum: 10c0/5f46599c8404ab9e4f9328b3a4f84d0eb01764279826424d225c5c2f3e36d0ee5533eda81aa6507fb24597fd0909611a57273f513a03545e1ad54ee4642ad94f +"smol-toml@npm:^1.5.2": + version: 1.6.0 + resolution: "smol-toml@npm:1.6.0" + checksum: 10c0/baf33bb6cd914d481329e31998a12829cd126541458ba400791212c80f1245d5b27dac04a56a52c02b287d2a494f1628c05fc19643286b258b2e0bb9fe67747c languageName: node linkType: hard @@ -13794,10 +14453,10 @@ __metadata: languageName: node linkType: hard -"strip-json-comments@npm:5.0.2": - version: 5.0.2 - resolution: "strip-json-comments@npm:5.0.2" - checksum: 10c0/e9841b8face78a01b0eb66f81e0a3419186a96f1d26817a5e1f5260b0631c10e0a7f711dddc5988edf599e5c079e4dd6e91defd21523e556636ba5679786f5ac +"strip-json-comments@npm:5.0.3": + version: 5.0.3 + resolution: "strip-json-comments@npm:5.0.3" + checksum: 10c0/daaf20b29f69fb51112698f4a9a662490dbb78d5baf6127c75a0a83c2ac6c078a8c0f74b389ad5e0519d6fc359c4a57cb9971b1ae201aef62ce45a13247791e0 languageName: node linkType: hard @@ -14105,12 +14764,12 @@ __metadata: languageName: node linkType: hard -"ts-api-utils@npm:^2.1.0": - version: 2.1.0 - resolution: "ts-api-utils@npm:2.1.0" +"ts-api-utils@npm:^2.2.0": + version: 2.4.0 + resolution: "ts-api-utils@npm:2.4.0" peerDependencies: typescript: ">=4.8.4" - checksum: 10c0/9806a38adea2db0f6aa217ccc6bc9c391ddba338a9fe3080676d0d50ed806d305bb90e8cef0276e793d28c8a929f400abb184ddd7ff83a416959c0f4d2ce754f + checksum: 10c0/ed185861aef4e7124366a3f6561113557a57504267d4d452a51e0ba516a9b6e713b56b4aeaab9fa13de9db9ab755c65c8c13a777dba9133c214632cb7b65c083 languageName: node linkType: hard @@ -14294,43 +14953,23 @@ __metadata: languageName: node linkType: hard -"typescript@npm:^5.0.4": - version: 5.8.2 - resolution: "typescript@npm:5.8.2" +"typescript@npm:^5.0.4, typescript@npm:^5.8.3": + version: 5.9.3 + resolution: "typescript@npm:5.9.3" bin: tsc: bin/tsc tsserver: bin/tsserver - checksum: 10c0/5c4f6fbf1c6389b6928fe7b8fcd5dc73bb2d58cd4e3883f1d774ed5bd83b151cbac6b7ecf11723de56d4676daeba8713894b1e9af56174f2f9780ae7848ec3c6 + checksum: 10c0/6bd7552ce39f97e711db5aa048f6f9995b53f1c52f7d8667c1abdc1700c68a76a308f579cd309ce6b53646deb4e9a1be7c813a93baaf0a28ccd536a30270e1c5 languageName: node linkType: hard -"typescript@npm:^5.8.3": - version: 5.8.3 - resolution: "typescript@npm:5.8.3" +"typescript@patch:typescript@npm%3A^5.0.4#optional!builtin, typescript@patch:typescript@npm%3A^5.8.3#optional!builtin": + version: 5.9.3 + resolution: "typescript@patch:typescript@npm%3A5.9.3#optional!builtin::version=5.9.3&hash=5786d5" bin: tsc: bin/tsc tsserver: bin/tsserver - checksum: 10c0/5f8bb01196e542e64d44db3d16ee0e4063ce4f3e3966df6005f2588e86d91c03e1fb131c2581baf0fb65ee79669eea6e161cd448178986587e9f6844446dbb48 - languageName: node - linkType: hard - -"typescript@patch:typescript@npm%3A^5.0.4#optional!builtin": - version: 5.8.2 - resolution: "typescript@patch:typescript@npm%3A5.8.2#optional!builtin::version=5.8.2&hash=5786d5" - bin: - tsc: bin/tsc - tsserver: bin/tsserver - checksum: 10c0/5448a08e595cc558ab321e49d4cac64fb43d1fa106584f6ff9a8d8e592111b373a995a1d5c7f3046211c8a37201eb6d0f1566f15cdb7a62a5e3be01d087848e2 - languageName: node - linkType: hard - -"typescript@patch:typescript@npm%3A^5.8.3#optional!builtin": - version: 5.8.3 - resolution: "typescript@patch:typescript@npm%3A5.8.3#optional!builtin::version=5.8.3&hash=5786d5" - bin: - tsc: bin/tsc - tsserver: bin/tsserver - checksum: 10c0/39117e346ff8ebd87ae1510b3a77d5d92dae5a89bde588c747d25da5c146603a99c8ee588c7ef80faaf123d89ed46f6dbd918d534d641083177d5fac38b8a1cb + checksum: 10c0/ad09fdf7a756814dce65bc60c1657b40d44451346858eea230e10f2e95a289d9183b6e32e5c11e95acc0ccc214b4f36289dcad4bf1886b0adb84d711d336a430 languageName: node linkType: hard @@ -14363,13 +15002,6 @@ __metadata: languageName: node linkType: hard -"undici-types@npm:~7.8.0": - version: 7.8.0 - resolution: "undici-types@npm:7.8.0" - checksum: 10c0/9d9d246d1dc32f318d46116efe3cfca5a72d4f16828febc1918d94e58f6ffcf39c158aa28bf5b4fc52f410446bc7858f35151367bd7a49f21746cab6497b709b - languageName: node - linkType: hard - "undici@npm:^5.25.4": version: 5.29.0 resolution: "undici@npm:5.29.0" @@ -14506,6 +15138,20 @@ __metadata: languageName: node linkType: hard +"update-browserslist-db@npm:^1.2.0": + version: 1.2.3 + resolution: "update-browserslist-db@npm:1.2.3" + dependencies: + escalade: "npm:^3.2.0" + picocolors: "npm:^1.1.1" + peerDependencies: + browserslist: ">= 4.21.0" + bin: + update-browserslist-db: cli.js + checksum: 10c0/13a00355ea822388f68af57410ce3255941d5fb9b7c49342c4709a07c9f230bbef7f7499ae0ca7e0de532e79a82cc0c4edbd125f1a323a1845bf914efddf8bec + languageName: node + linkType: hard + "uri-js@npm:^4.2.2": version: 4.4.1 resolution: "uri-js@npm:4.4.1" @@ -14746,23 +15392,23 @@ __metadata: linkType: hard "vite-plugin-svgr@npm:^4.0.0": - version: 4.3.0 - resolution: "vite-plugin-svgr@npm:4.3.0" + version: 4.5.0 + resolution: "vite-plugin-svgr@npm:4.5.0" dependencies: - "@rollup/pluginutils": "npm:^5.1.3" + "@rollup/pluginutils": "npm:^5.2.0" "@svgr/core": "npm:^8.1.0" "@svgr/plugin-jsx": "npm:^8.1.0" peerDependencies: vite: ">=2.6.0" - checksum: 10c0/a73f10d319f72cd8c16bf9701cf18170f2300f98c72c6bf939565de0b1e93916bd70c6f5a446dc034b4405c72d382655c7c16be4bd1cbf35bbcde5febf7aeffc + checksum: 10c0/3e1959fec626bb4f5a8ec13ff15bc40ffbc1c0ff38149bebe3f37dc2d67ed1f276f129ff7983e06946cf712e19996affd9d6868aa7d20d8921d1fe4449109b55 languageName: node linkType: hard "vite@npm:^5.0.0 || ^6.0.0 || ^7.0.0-0, vite@npm:^7.0.0": - version: 7.1.12 - resolution: "vite@npm:7.1.12" + version: 7.3.0 + resolution: "vite@npm:7.3.0" dependencies: - esbuild: "npm:^0.25.0" + esbuild: "npm:^0.27.0" fdir: "npm:^6.5.0" fsevents: "npm:~2.3.3" picomatch: "npm:^4.0.3" @@ -14809,7 +15455,7 @@ __metadata: optional: true bin: vite: bin/vite.js - checksum: 10c0/cef4d4b4a84e663e09b858964af36e916892ac8540068df42a05ced637ceeae5e9ef71c72d54f3cfc1f3c254af16634230e221b6e2327c2a66d794bb49203262 + checksum: 10c0/0457c196cdd5761ec351c0f353945430fbad330e615b9eeab729c8ae163334f18acdc1d9cd7d9d673dbf111f07f6e4f0b25d4ac32360e65b4a6df9991046f3ff languageName: node linkType: hard @@ -15314,18 +15960,16 @@ __metadata: languageName: node linkType: hard -"zod-validation-error@npm:^3.0.3": - version: 3.4.0 - resolution: "zod-validation-error@npm:3.4.0" - peerDependencies: - zod: ^3.18.0 - checksum: 10c0/aaadb0e65c834aacb12fa088663d52d9f4224b5fe6958f09b039f4ab74145fda381c8a7d470bfddf7ddd9bbb5fdfbb52739cd66958ce6d388c256a44094d1fba - languageName: node - linkType: hard - "zod@npm:^3.22.4": version: 3.24.2 resolution: "zod@npm:3.24.2" checksum: 10c0/c638c7220150847f13ad90635b3e7d0321b36cce36f3fc6050ed960689594c949c326dfe2c6fa87c14b126ee5d370ccdebd6efb304f41ef5557a4aaca2824565 languageName: node linkType: hard + +"zod@npm:^4.1.11": + version: 4.3.4 + resolution: "zod@npm:4.3.4" + checksum: 10c0/a096102c8b31ecdb913bacb08d5a0fe8447bbe4f54cff421a0c5830a5552da76aae9fd8a01f2e9fdeaae35da1a73762551bc9d14cfedb13a44056de1ed2eb76f + languageName: node + linkType: hard From c35b96062757bfeb5ff1a7c6786ec947ba8198c6 Mon Sep 17 00:00:00 2001 From: Timo K Date: Mon, 5 Jan 2026 10:42:08 +0100 Subject: [PATCH 130/748] fix lints --- src/settings/DeveloperSettingsTab.tsx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/settings/DeveloperSettingsTab.tsx b/src/settings/DeveloperSettingsTab.tsx index d16e3ef7f..0b77f0957 100644 --- a/src/settings/DeveloperSettingsTab.tsx +++ b/src/settings/DeveloperSettingsTab.tsx @@ -50,7 +50,7 @@ import { getSFUConfigWithOpenID } from "../livekit/openIDSFU"; interface Props { client: MatrixClient; - roomId: string; + roomId?: string; livekitRooms?: { room: LivekitRoom; url: string; isLocal?: boolean }[]; env: ImportMetaEnv; } @@ -237,6 +237,7 @@ export const DeveloperSettingsTab: FC = ({ onSave={useCallback( async (e: React.FormEvent): Promise => { if ( + roomId === undefined || customLivekitUrlTextBuffer === "" || customLivekitUrlTextBuffer === null ) { From f260a2072826b9011bcd9951b6f29a210f797fc1 Mon Sep 17 00:00:00 2001 From: Will Hunt <2072976+Half-Shot@users.noreply.github.com> Date: Mon, 5 Jan 2026 12:41:26 +0000 Subject: [PATCH 131/748] Set latest tag when publishing a docker release. (#3650) Fixes https://github.com/element-hq/element-call/issues/3647 --- .github/workflows/publish.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/publish.yaml b/.github/workflows/publish.yaml index 6a5c090e4..7f2c58fe2 100644 --- a/.github/workflows/publish.yaml +++ b/.github/workflows/publish.yaml @@ -61,6 +61,7 @@ jobs: docker_tags: | type=sha,format=short,event=branch type=raw,value=${{ github.event.release.tag_name }} + type=raw,value=latest # Like before, using ${{ env.VERSION }} above doesn't work add_docker_release_note: needs: publish_docker From 5fa170c9c96c7ed08b31dd27805c3ce39c991f26 Mon Sep 17 00:00:00 2001 From: Robin Date: Mon, 5 Jan 2026 13:54:08 +0100 Subject: [PATCH 132/748] Fix builds --- src/initializer.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/initializer.tsx b/src/initializer.tsx index d0797e9d1..267d818af 100644 --- a/src/initializer.tsx +++ b/src/initializer.tsx @@ -16,7 +16,7 @@ import LanguageDetector from "i18next-browser-languagedetector"; import * as Sentry from "@sentry/react"; import { logger } from "matrix-js-sdk/lib/logger"; import { shouldPolyfill as shouldPolyfillSegmenter } from "@formatjs/intl-segmenter/should-polyfill"; -import { shouldPolyfill as shouldPolyfillDurationFormat } from "@formatjs/intl-durationformat/should-polyfill"; +import { shouldPolyfill as shouldPolyfillDurationFormat } from "@formatjs/intl-durationformat/should-polyfill.js"; import { useLocation, useNavigationType, @@ -123,7 +123,7 @@ export class Initializer { } if (shouldPolyfillDurationFormat()) { - polyfills.push(import("@formatjs/intl-durationformat/polyfill-force")); + polyfills.push(import("@formatjs/intl-durationformat/polyfill-force.js")); } await Promise.all(polyfills); From b6ca0c4cd6bc460417603f95e2dc9c3e81171d59 Mon Sep 17 00:00:00 2001 From: Robin Date: Mon, 5 Jan 2026 13:55:58 +0100 Subject: [PATCH 133/748] Fix tests --- src/__snapshots__/AppBar.test.tsx.snap | 2 +- src/__snapshots__/Modal.test.tsx.snap | 12 ++--- src/__snapshots__/Toast.test.tsx.snap | 6 +-- .../ReactionToggleButton.test.tsx.snap | 10 ++-- .../__snapshots__/InCallView.test.tsx.snap | 14 +++--- .../DeveloperSettingsTab.test.tsx.snap | 48 +++++++++---------- src/vitest.setup.ts | 2 +- 7 files changed, 47 insertions(+), 47 deletions(-) diff --git a/src/__snapshots__/AppBar.test.tsx.snap b/src/__snapshots__/AppBar.test.tsx.snap index fe61d09be..25bb54ed0 100644 --- a/src/__snapshots__/AppBar.test.tsx.snap +++ b/src/__snapshots__/AppBar.test.tsx.snap @@ -13,7 +13,7 @@ exports[`AppBar > renders 1`] = ` class="nav leftNav" > - +
diff --git a/src/UrlParams.ts b/src/UrlParams.ts index f78841fb9..048e802b0 100644 --- a/src/UrlParams.ts +++ b/src/UrlParams.ts @@ -261,7 +261,8 @@ interface IntentAndPlatformDerivedConfiguration { // clearer what each flag means, and helps us avoid coupling Element Call's // behavior to the needs of specific consumers. export interface UrlParams - extends UrlProperties, + extends + UrlProperties, UrlConfiguration, IntentAndPlatformDerivedConfiguration {} diff --git a/src/grid/Grid.tsx b/src/grid/Grid.tsx index 6c85b8afe..91fd55cad 100644 --- a/src/grid/Grid.tsx +++ b/src/grid/Grid.tsx @@ -200,8 +200,11 @@ interface Drag { export type DragCallback = (drag: Drag) => void; -interface LayoutMemoProps - extends LayoutProps { +interface LayoutMemoProps< + LayoutModel, + TileModel, + R extends HTMLElement, +> extends LayoutProps { Layout: ComponentType>; } diff --git a/src/room/InCallView.tsx b/src/room/InCallView.tsx index c6f22b432..fdbd44614 100644 --- a/src/room/InCallView.tsx +++ b/src/room/InCallView.tsx @@ -113,8 +113,10 @@ const logger = rootLogger.getChild("[InCallView]"); const maxTapDurationMs = 400; -export interface ActiveCallProps - extends Omit { +export interface ActiveCallProps extends Omit< + InCallViewProps, + "vm" | "livekitRoom" | "connState" +> { e2eeSystem: EncryptionSystem; // TODO refactor those reasons into an enum onLeft: ( diff --git a/src/state/MediaDevices.ts b/src/state/MediaDevices.ts index 2349e3617..cea975198 100644 --- a/src/state/MediaDevices.ts +++ b/src/state/MediaDevices.ts @@ -212,9 +212,10 @@ class AudioInput implements MediaDevice { } } -class AudioOutput - implements MediaDevice -{ +class AudioOutput implements MediaDevice< + AudioOutputDeviceLabel, + SelectedAudioOutputDevice +> { private logger = rootLogger.getChild("[MediaDevices AudioOutput]"); public readonly available$ = this.scope.behavior( availableRawDevices$( @@ -274,9 +275,10 @@ class AudioOutput } } -class ControlledAudioOutput - implements MediaDevice -{ +class ControlledAudioOutput implements MediaDevice< + AudioOutputDeviceLabel, + SelectedAudioOutputDevice +> { private logger = rootLogger.getChild("[MediaDevices ControlledAudioOutput]"); // We need to subscribe to the raw devices so that the OS does update the input // back to what it was before. otherwise we will switch back to the default diff --git a/src/tile/SpotlightTile.tsx b/src/tile/SpotlightTile.tsx index 8109784f3..2042e8194 100644 --- a/src/tile/SpotlightTile.tsx +++ b/src/tile/SpotlightTile.tsx @@ -70,8 +70,7 @@ interface SpotlightUserMediaItemBaseProps extends SpotlightItemBaseProps { videoFit: "contain" | "cover"; } -interface SpotlightLocalUserMediaItemProps - extends SpotlightUserMediaItemBaseProps { +interface SpotlightLocalUserMediaItemProps extends SpotlightUserMediaItemBaseProps { vm: LocalUserMediaViewModel; } @@ -85,8 +84,7 @@ const SpotlightLocalUserMediaItem: FC = ({ SpotlightLocalUserMediaItem.displayName = "SpotlightLocalUserMediaItem"; -interface SpotlightRemoteUserMediaItemProps - extends SpotlightUserMediaItemBaseProps { +interface SpotlightRemoteUserMediaItemProps extends SpotlightUserMediaItemBaseProps { vm: RemoteUserMediaViewModel; } From 5d5d75ebdf3dab22f810eff4c64e8219c009bf74 Mon Sep 17 00:00:00 2001 From: Timo K Date: Mon, 5 Jan 2026 21:08:33 +0100 Subject: [PATCH 143/748] fixup merge --- sdk/main.ts | 7 +-- src/livekit/openIDSFU.test.ts | 7 +++ .../localMember/LocalTransport.test.ts | 19 +++++++- .../localMember/LocalTransport.ts | 47 +++++++++++-------- 4 files changed, 53 insertions(+), 27 deletions(-) diff --git a/sdk/main.ts b/sdk/main.ts index 376674a41..8d07ab07c 100644 --- a/sdk/main.ts +++ b/sdk/main.ts @@ -101,12 +101,7 @@ export async function createMatrixRTCSdk( const mediaDevices = new MediaDevices(scope); const muteStates = new MuteStates(scope, mediaDevices, constant(true)); const slot = { application, id }; - const rtcSession = new MatrixRTCSession( - client, - room, - MatrixRTCSession.sessionMembershipsForSlot(room, slot), - slot, - ); + const rtcSession = new MatrixRTCSession(client, room, slot); const callViewModel = createCallViewModel$( scope, rtcSession, diff --git a/src/livekit/openIDSFU.test.ts b/src/livekit/openIDSFU.test.ts index 2a260b015..8b263662c 100644 --- a/src/livekit/openIDSFU.test.ts +++ b/src/livekit/openIDSFU.test.ts @@ -18,6 +18,7 @@ import fetchMock from "fetch-mock"; import { getSFUConfigWithOpenID, type OpenIDClientParts } from "./openIDSFU"; import { testJWTToken } from "../utils/test-fixtures"; +import { ownMemberMock } from "../utils/test"; const sfuUrl = "https://sfu.example.org"; @@ -42,7 +43,9 @@ describe("getSFUConfigWithOpenID", () => { }); const config = await getSFUConfigWithOpenID( matrixClient, + ownMemberMock, "https://sfu.example.org", + false, "!example_room_id", ); expect(config).toEqual({ @@ -63,7 +66,9 @@ describe("getSFUConfigWithOpenID", () => { try { await getSFUConfigWithOpenID( matrixClient, + ownMemberMock, "https://sfu.example.org", + false, "!example_room_id", ); } catch (ex) { @@ -98,7 +103,9 @@ describe("getSFUConfigWithOpenID", () => { }); const config = await getSFUConfigWithOpenID( matrixClient, + ownMemberMock, "https://sfu.example.org", + false, "!example_room_id", ); expect(config).toEqual({ diff --git a/src/state/CallViewModel/localMember/LocalTransport.test.ts b/src/state/CallViewModel/localMember/LocalTransport.test.ts index c77297ef7..2199ca946 100644 --- a/src/state/CallViewModel/localMember/LocalTransport.test.ts +++ b/src/state/CallViewModel/localMember/LocalTransport.test.ts @@ -49,6 +49,8 @@ describe("LocalTransport", () => { useOldestMember$: constant(false), memberships$: constant(new Epoch([])), client: { + // eslint-disable-next-line @typescript-eslint/naming-convention + _unstable_getRTCTransports: async () => Promise.resolve([]), getDomain: () => "", baseUrl: "example.org", // These won't be called in this error path but satisfy the type @@ -130,6 +132,8 @@ describe("LocalTransport", () => { useOldestMember$: constant(false), memberships$: constant(new Epoch([])), client: { + // eslint-disable-next-line @typescript-eslint/naming-convention + _unstable_getRTCTransports: async () => Promise.resolve([]), getDomain: () => "", getOpenIdToken: vi.fn(), getDeviceId: vi.fn(), @@ -140,7 +144,12 @@ describe("LocalTransport", () => { delayId$: constant("delay_id_mock"), }); - openIdResolver.resolve?.({ url: "https://lk.example.org", jwt: "jwt" }); + openIdResolver.resolve?.({ + url: "https://lk.example.org", + jwt: "jwt", + livekitAlias: "!room:example.org", + livekitIdentity: ownMemberMock.userId + ":" + ownMemberMock.deviceId, + }); expect(localTransport$.value).toBe(null); await flushPromises(); // final @@ -203,11 +212,15 @@ describe("LocalTransport", () => { mockConfig({}); customLivekitUrl.setValue(customLivekitUrl.defaultValue); localTransportOpts = { + ownMembershipIdentity: ownMemberMock, scope, roomId: "!example_room_id", useOldestMember$: constant(false), + useOldJwtEndpoint$: constant(false), + delayId$: constant(null), memberships$: constant(new Epoch([])), client: { + baseUrl: "https://example.org", getDomain: vi.fn().mockReturnValue(""), // eslint-disable-next-line @typescript-eslint/naming-convention _unstable_getRTCTransports: vi.fn().mockResolvedValue([]), @@ -317,11 +330,15 @@ describe("LocalTransport", () => { it("throws if no options are available", async () => { const localTransport$ = createLocalTransport$({ scope, + ownMembershipIdentity: ownMemberMock, roomId: "!example_room_id", useOldestMember$: constant(false), + useOldJwtEndpoint$: constant(false), + delayId$: constant(null), memberships$: constant(new Epoch([])), client: { getDomain: () => "", + baseUrl: "https://example.org", // eslint-disable-next-line @typescript-eslint/naming-convention _unstable_getRTCTransports: async () => Promise.resolve([]), // These won't be called in this error path but satisfy the type diff --git a/src/state/CallViewModel/localMember/LocalTransport.ts b/src/state/CallViewModel/localMember/LocalTransport.ts index d8b5dfcea..1853ff6df 100644 --- a/src/state/CallViewModel/localMember/LocalTransport.ts +++ b/src/state/CallViewModel/localMember/LocalTransport.ts @@ -178,7 +178,6 @@ async function makeTransport( forceOldJwtEndpoint: boolean, delayId?: string, ): Promise { - let transport: LivekitTransport | undefined; logger.trace("Searching for a preferred transport"); // We will call `getSFUConfigWithOpenID` once per transport here as it's our @@ -194,32 +193,47 @@ async function makeTransport( logger.info("Using LiveKit transport from dev tools: ", urlFromDevSettings); // Validate that the SFU is up. Otherwise, we want to fail on this // as we don't permit other SFUs. - const config = await getSFUConfigWithOpenID( + // This will call the jwt/sfu/get endpoint to pre create the livekit room. + const { livekitAlias } = await getSFUConfigWithOpenID( client, + membership, urlFromDevSettings, + forceOldJwtEndpoint, roomId, + client.baseUrl, + delayId, + logger, ); return { type: "livekit", livekit_service_url: urlFromDevSettings, - livekit_alias: config.livekitAlias, + livekit_alias: livekitAlias, + forceOldJwtEndpoint, }; } async function getFirstUsableTransport( transports: Transport[], - ): Promise { + ): Promise<(LivekitTransport & { forceOldJwtEndpoint: boolean }) | null> { for (const potentialTransport of transports) { if (isLivekitTransportConfig(potentialTransport)) { try { + // This will call the jwt/sfu/get endpoint to pre create the livekit room. const { livekitAlias } = await getSFUConfigWithOpenID( client, + membership, potentialTransport.livekit_service_url, + forceOldJwtEndpoint, roomId, + client.baseUrl, + delayId, + logger, ); + return { ...potentialTransport, livekit_alias: livekitAlias, + forceOldJwtEndpoint, }; } catch (ex) { if (ex instanceof FailToGetOpenIdToken) { @@ -283,10 +297,16 @@ async function makeTransport( const urlFromConf = Config.get().livekit?.livekit_service_url; if (urlFromConf) { try { + // This will call the jwt/sfu/get endpoint to pre create the livekit room. const { livekitAlias } = await getSFUConfigWithOpenID( client, + membership, urlFromConf, + forceOldJwtEndpoint, roomId, + client.baseUrl, + delayId, + logger, ); const selectedTransport: LivekitTransport = { type: "livekit", @@ -294,7 +314,7 @@ async function makeTransport( livekit_alias: livekitAlias, }; logger.info("Using config SFU", selectedTransport); - return selectedTransport; + return { ...selectedTransport, forceOldJwtEndpoint }; } catch (ex) { if (ex instanceof FailToGetOpenIdToken) { throw ex; @@ -303,19 +323,6 @@ async function makeTransport( } } - if (!transport) throw new MatrixRTCTransportMissingError(domain ?? ""); - - // this will call the jwt/sfu/get endpoint to pre create the livekit room. - await getSFUConfigWithOpenID( - client, - membership, - transport.livekit_service_url, - forceOldJwtEndpoint, - transport.livekit_alias, - client.baseUrl, - delayId, - logger, - ); - - return { ...transport, forceOldJwtEndpoint }; + // If we do not have returned a transport by now we throw an error + throw new MatrixRTCTransportMissingError(domain ?? ""); } From 00fca6e3c731e24ed1ceffddde33e690412d3589 Mon Sep 17 00:00:00 2001 From: Timo K Date: Mon, 5 Jan 2026 21:17:37 +0100 Subject: [PATCH 144/748] simplify localTransport --- .../localMember/LocalTransport.ts | 73 +++++++------------ 1 file changed, 25 insertions(+), 48 deletions(-) diff --git a/src/state/CallViewModel/localMember/LocalTransport.ts b/src/state/CallViewModel/localMember/LocalTransport.ts index 1853ff6df..50d6cec6e 100644 --- a/src/state/CallViewModel/localMember/LocalTransport.ts +++ b/src/state/CallViewModel/localMember/LocalTransport.ts @@ -180,6 +180,26 @@ async function makeTransport( ): Promise { logger.trace("Searching for a preferred transport"); + async function doOpenIdAndJWTFromUrl( + url: string, + ): Promise { + const { livekitAlias } = await getSFUConfigWithOpenID( + client, + membership, + url, + forceOldJwtEndpoint, + roomId, + client.baseUrl, + delayId, + logger, + ); + return { + type: "livekit", + livekit_service_url: url, + livekit_alias: livekitAlias, + forceOldJwtEndpoint, + }; + } // We will call `getSFUConfigWithOpenID` once per transport here as it's our // only mechanism of valiation. This means we will also ask the // homeserver for a OpenID token a few times. Since OpenID tokens are single @@ -190,26 +210,11 @@ async function makeTransport( // DEVTOOL: Highest priority: Load from devtool setting if (urlFromDevSettings !== null) { - logger.info("Using LiveKit transport from dev tools: ", urlFromDevSettings); // Validate that the SFU is up. Otherwise, we want to fail on this // as we don't permit other SFUs. // This will call the jwt/sfu/get endpoint to pre create the livekit room. - const { livekitAlias } = await getSFUConfigWithOpenID( - client, - membership, - urlFromDevSettings, - forceOldJwtEndpoint, - roomId, - client.baseUrl, - delayId, - logger, - ); - return { - type: "livekit", - livekit_service_url: urlFromDevSettings, - livekit_alias: livekitAlias, - forceOldJwtEndpoint, - }; + logger.info("Using LiveKit transport from dev tools: ", urlFromDevSettings); + return await doOpenIdAndJWTFromUrl(urlFromDevSettings); } async function getFirstUsableTransport( @@ -219,22 +224,9 @@ async function makeTransport( if (isLivekitTransportConfig(potentialTransport)) { try { // This will call the jwt/sfu/get endpoint to pre create the livekit room. - const { livekitAlias } = await getSFUConfigWithOpenID( - client, - membership, + return await doOpenIdAndJWTFromUrl( potentialTransport.livekit_service_url, - forceOldJwtEndpoint, - roomId, - client.baseUrl, - delayId, - logger, ); - - return { - ...potentialTransport, - livekit_alias: livekitAlias, - forceOldJwtEndpoint, - }; } catch (ex) { if (ex instanceof FailToGetOpenIdToken) { // Explictly throw these @@ -298,23 +290,8 @@ async function makeTransport( if (urlFromConf) { try { // This will call the jwt/sfu/get endpoint to pre create the livekit room. - const { livekitAlias } = await getSFUConfigWithOpenID( - client, - membership, - urlFromConf, - forceOldJwtEndpoint, - roomId, - client.baseUrl, - delayId, - logger, - ); - const selectedTransport: LivekitTransport = { - type: "livekit", - livekit_service_url: urlFromConf, - livekit_alias: livekitAlias, - }; - logger.info("Using config SFU", selectedTransport); - return { ...selectedTransport, forceOldJwtEndpoint }; + logger.info("Using config SFU", urlFromConf); + return await doOpenIdAndJWTFromUrl(urlFromConf); } catch (ex) { if (ex instanceof FailToGetOpenIdToken) { throw ex; From 15800872862fccd5839b4f64ad3cb8b27a570140 Mon Sep 17 00:00:00 2001 From: Timo K Date: Mon, 5 Jan 2026 21:24:52 +0100 Subject: [PATCH 145/748] use latest js-sdk --- package.json | 2 +- yarn.lock | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index 95c30ef6e..1d4d63932 100644 --- a/package.json +++ b/package.json @@ -112,7 +112,7 @@ "livekit-client": "^2.13.0", "lodash-es": "^4.17.21", "loglevel": "^1.9.1", - "matrix-js-sdk": "github:matrix-org/matrix-js-sdk#head=toger5/use-membershipID-for-session-state-events&commit=6f0815930a008eff8f86e6e5748d447be0e7c25e", + "matrix-js-sdk": "matrix-org/matrix-js-sdk#develop", "matrix-widget-api": "^1.14.0", "node-stdlib-browser": "^1.3.1", "normalize.css": "^8.0.1", diff --git a/yarn.lock b/yarn.lock index 1a2004720..6c0e49480 100644 --- a/yarn.lock +++ b/yarn.lock @@ -7951,7 +7951,7 @@ __metadata: livekit-client: "npm:^2.13.0" lodash-es: "npm:^4.17.21" loglevel: "npm:^1.9.1" - matrix-js-sdk: "github:matrix-org/matrix-js-sdk#head=toger5/use-membershipID-for-session-state-events&commit=6f0815930a008eff8f86e6e5748d447be0e7c25e" + matrix-js-sdk: "matrix-org/matrix-js-sdk#develop" matrix-widget-api: "npm:^1.14.0" node-stdlib-browser: "npm:^1.3.1" normalize.css: "npm:^8.0.1" @@ -10939,9 +10939,9 @@ __metadata: languageName: node linkType: hard -"matrix-js-sdk@github:matrix-org/matrix-js-sdk#head=toger5/use-membershipID-for-session-state-events&commit=6f0815930a008eff8f86e6e5748d447be0e7c25e": +"matrix-js-sdk@matrix-org/matrix-js-sdk#develop": version: 39.4.0 - resolution: "matrix-js-sdk@https://github.com/matrix-org/matrix-js-sdk.git#commit=6f0815930a008eff8f86e6e5748d447be0e7c25e" + resolution: "matrix-js-sdk@https://github.com/matrix-org/matrix-js-sdk.git#commit=4b89fb23c54aaf7826bd127d8fa21cc7bb87688f" dependencies: "@babel/runtime": "npm:^7.12.5" "@matrix-org/matrix-sdk-crypto-wasm": "npm:^16.0.0" @@ -10957,7 +10957,7 @@ __metadata: sdp-transform: "npm:^3.0.0" unhomoglyph: "npm:^1.0.6" uuid: "npm:13" - checksum: 10c0/a5a904a79f3660d1f6fe217195e662adf82af4a445681e47f292772d9d4d63ce60aaca209f40c41e2d659bee2b17cd5b3345bbad77795032057f2c0e3129cc77 + checksum: 10c0/bc7443bf67822e9bc7b8e531b4e61e6ebac41c2fd8047ac0567456c264ae0d1911fbef6e437d312a3adeead86cd5e7134944e3fd73d28002777618bc0ebaa1ca languageName: node linkType: hard From 69a4189517ca83016053b8d2f1722e2324076d45 Mon Sep 17 00:00:00 2001 From: Timo K Date: Mon, 5 Jan 2026 21:58:26 +0100 Subject: [PATCH 146/748] self review --- src/e2ee/matrixKeyProvider.ts | 4 ++-- src/livekit/openIDSFU.ts | 29 ++++++++++++++---------- src/room/InCallView.test.tsx | 2 +- src/room/InCallView.tsx | 1 - src/state/CallViewModel/CallViewModel.ts | 3 ++- 5 files changed, 22 insertions(+), 17 deletions(-) diff --git a/src/e2ee/matrixKeyProvider.ts b/src/e2ee/matrixKeyProvider.ts index d7aebc4b0..63a96755f 100644 --- a/src/e2ee/matrixKeyProvider.ts +++ b/src/e2ee/matrixKeyProvider.ts @@ -61,12 +61,12 @@ export class MatrixKeyProvider extends BaseKeyProvider { ); logger.debug( - `Sent new key to livekit room=${this.rtcSession?.room.roomId} participantId=${rtcBackendIdentity} (before hash: ${membershipParts.userId}) encryptionKeyIndex=${encryptionKeyIndex}`, + `Sent new key to livekit room=${this.rtcSession?.room.roomId} participantId=${rtcBackendIdentity} (before hash: ${membershipParts.userId}:${membershipParts.deviceId}) encryptionKeyIndex=${encryptionKeyIndex}`, ); }, (e) => { logger.error( - `Failed to create key material from buffer for livekit room=${this.rtcSession?.room.roomId} participantId before hash=${membershipParts.userId} encryptionKeyIndex=${encryptionKeyIndex}`, + `Failed to create key material from buffer for livekit room=${this.rtcSession?.room.roomId} participantId before hash=${membershipParts.userId}:${membershipParts.deviceId} encryptionKeyIndex=${encryptionKeyIndex}`, e, ); }, diff --git a/src/livekit/openIDSFU.ts b/src/livekit/openIDSFU.ts index 7d6dfc245..6728a243e 100644 --- a/src/livekit/openIDSFU.ts +++ b/src/livekit/openIDSFU.ts @@ -20,6 +20,7 @@ export interface SFUConfig { url: string; jwt: string; livekitAlias: string; + // NOTE: Currently unused. livekitIdentity: string; } @@ -68,7 +69,7 @@ export type OpenIDClientParts = Pick< * @param client The Matrix client * @param membership * @param serviceUrl The URL of the livekit SFU service - * @param forceOldEndpoint This will use the old jwt endpoint which will create the rtc backend identity based on string concatination + * @param forceOldJwtEndpoint This will use the old jwt endpoint which will create the rtc backend identity based on string concatination * instead of a hash. * This function by default uses whatever is possible with the current jwt service installed next to the SFU. * For remote connections this does not matter, since we will not publish there we can rely on the newest option. @@ -103,12 +104,6 @@ export async function getSFUConfigWithOpenID( logger?.debug("Got openID token", openIdToken); logger?.info(`Trying to get JWT for focus ${serviceUrl}...`); - const args: [CallMembershipIdentityParts, string, string, IOpenIDToken] = [ - membership, - serviceUrl, - roomId, - openIdToken, - ]; let sfuConfig: { url: string; jwt: string }; try { @@ -118,7 +113,10 @@ export async function getSFUConfigWithOpenID( throw new Error("No delayId, Won't try matrix 2.0 jwt endpoint."); sfuConfig = await getLiveKitJWTWithDelayDelegation( - ...args, + membership, + serviceUrl, + roomId, + openIdToken, delayEndpointBaseUrl, delayId, ); @@ -128,23 +126,30 @@ export async function getSFUConfigWithOpenID( `Failed fetching jwt with matrix 2.0 endpoint (retry with legacy)`, e, ); - sfuConfig = await getLiveKitJWT(...args); + sfuConfig = await getLiveKitJWT( + membership.deviceId, + serviceUrl, + roomId, + openIdToken, + ); logger?.info(`Got JWT from call's active focus URL.`); } // Pull the details from the JWT const [, payloadStr] = sfuConfig.jwt.split("."); - + // TODO: Prefer Uint8Array.fromBase64 when widely available const payload = JSON.parse(global.atob(payloadStr)) as SFUJWTPayload; return { jwt: sfuConfig.jwt, url: sfuConfig.url, livekitAlias: payload.video.room, // NOTE: Currently unused. + // Probably also not helpful since we now compute the backendIdentity on joining the call so we can use it for the encryption manager. + // The only reason for us to know it locally is to connect the right users with the lk world. (and to set our own keys) livekitIdentity: payload.sub, }; } async function getLiveKitJWT( - membership: CallMembershipIdentityParts, + deviceId: string, livekitServiceURL: string, matrixRoomId: string, openIDToken: IOpenIDToken, @@ -159,7 +164,7 @@ async function getLiveKitJWT( // This is the actual livekit room alias. For the legacy jwt endpoint simply the room id was used. room: matrixRoomId, openid_token: openIDToken, - device_id: membership.deviceId, + device_id: deviceId, }), }); if (!res.ok) { diff --git a/src/room/InCallView.test.tsx b/src/room/InCallView.test.tsx index 8ac4bccba..a137074b1 100644 --- a/src/room/InCallView.test.tsx +++ b/src/room/InCallView.test.tsx @@ -22,6 +22,7 @@ import { BrowserRouter } from "react-router-dom"; import { TooltipProvider } from "@vector-im/compound-web"; import { RoomContext, useLocalParticipant } from "@livekit/components-react"; +import { InCallView } from "./InCallView"; import { mockLivekitRoom, mockLocalParticipant, @@ -33,7 +34,6 @@ import { mockRtcMembership, type MockRTCSession, } from "../utils/test"; -import { InCallView } from "./InCallView"; import { E2eeType } from "../e2ee/e2eeType"; import { getBasicCallViewModelEnvironment } from "../utils/test-viewmodel"; import { alice, local } from "../utils/test-fixtures"; diff --git a/src/room/InCallView.tsx b/src/room/InCallView.tsx index a21c33025..fdbd44614 100644 --- a/src/room/InCallView.tsx +++ b/src/room/InCallView.tsx @@ -795,7 +795,6 @@ export const InCallView: FC = ({ onTouchEnd={onControlsTouchEnd} /> )} - {!showControls &&
}
); diff --git a/src/state/CallViewModel/CallViewModel.ts b/src/state/CallViewModel/CallViewModel.ts index 9c2fbc3d1..093abfade 100644 --- a/src/state/CallViewModel/CallViewModel.ts +++ b/src/state/CallViewModel/CallViewModel.ts @@ -423,7 +423,8 @@ export function createCallViewModel$( const ownMembershipIdentity: CallMembershipIdentityParts = { userId, deviceId, - // TODO look into this!!! + // This will eventually become the salt for the hash endpoint. + // For now we keep it as the user+device string since it is expected by non matrix matrixRTCMode === Legacy. memberId: `${userId}:${deviceId}`, }; From 556a87d1411d30e9b5aa600e33c97e2dfebce930 Mon Sep 17 00:00:00 2001 From: Timo K Date: Mon, 5 Jan 2026 22:20:19 +0100 Subject: [PATCH 147/748] fix js-doc --- src/livekit/openIDSFU.ts | 8 ++++---- src/state/CallViewModel/localMember/LocalMember.ts | 8 ++++---- src/state/CallViewModel/localMember/LocalTransport.ts | 6 ++++-- .../CallViewModel/remoteMembers/ConnectionFactory.ts | 11 ++++++----- .../CallViewModel/remoteMembers/ConnectionManager.ts | 10 +++++++--- .../remoteMembers/ECConnectionFactory.test.ts | 4 ++-- 6 files changed, 27 insertions(+), 20 deletions(-) diff --git a/src/livekit/openIDSFU.ts b/src/livekit/openIDSFU.ts index 6728a243e..b89243c19 100644 --- a/src/livekit/openIDSFU.ts +++ b/src/livekit/openIDSFU.ts @@ -67,7 +67,7 @@ export type OpenIDClientParts = Pick< * to the matrix RTC backend in order to get acces to the SFU. * It has built-in retry for calls to the homeserver with a backoff policy. * @param client The Matrix client - * @param membership + * @param membership Our own membership identity parts used to send to jwt service. * @param serviceUrl The URL of the livekit SFU service * @param forceOldJwtEndpoint This will use the old jwt endpoint which will create the rtc backend identity based on string concatination * instead of a hash. @@ -75,9 +75,9 @@ export type OpenIDClientParts = Pick< * For remote connections this does not matter, since we will not publish there we can rely on the newest option. * For our own connection we can only use the hashed version if we also send the new matrix2.0 sticky events. * @param roomId The room id used in the jwt request. This is NOT the livekit_alias. The jwt service will provide the alias. It maps matrix room ids <-> Livekit aliases. - * @param delayEndpointBaseUrl - * @param delayId - * @param logger + * @param delayEndpointBaseUrl The URL of the matrix homeserver. + * @param delayId The delay id used for the jwt service to manage. + * @param logger optional logger. * @returns Object containing the token information * @throws FailToGetOpenIdToken */ diff --git a/src/state/CallViewModel/localMember/LocalMember.ts b/src/state/CallViewModel/localMember/LocalMember.ts index 890165dda..17f766fff 100644 --- a/src/state/CallViewModel/localMember/LocalMember.ts +++ b/src/state/CallViewModel/localMember/LocalMember.ts @@ -687,10 +687,9 @@ interface EnterRTCSessionOptions { * - Handles retries (fails only after several attempts) * * @param rtcSession - The MatrixRTCSession to join. + * @param ownMembershipIdentity - Options for entering the RTC session. * @param transport - The LivekitTransport to use for this session. - * @param options - Options for entering the RTC session. - * @param options.encryptMedia - Whether to encrypt media. - * @param options.matrixRTCMode - The Matrix RTC mode to use. + * @param options - `encryptMedia`: Whether to encrypt media `matrixRTCMode`: The Matrix RTC mode to use. * @throws If the widget could not send ElementWidgetActions.JoinCall action. */ // Exported for unit testing @@ -698,8 +697,9 @@ export function enterRTCSession( rtcSession: MatrixRTCSession, ownMembershipIdentity: CallMembershipIdentityParts, transport: LivekitTransport, - { encryptMedia, matrixRTCMode }: EnterRTCSessionOptions, + options: EnterRTCSessionOptions, ): void { + const { encryptMedia, matrixRTCMode } = options; PosthogAnalytics.instance.eventCallEnded.cacheStartCall(new Date()); PosthogAnalytics.instance.eventCallStarted.track(rtcSession.room.roomId); diff --git a/src/state/CallViewModel/localMember/LocalTransport.ts b/src/state/CallViewModel/localMember/LocalTransport.ts index 50d6cec6e..fa3168059 100644 --- a/src/state/CallViewModel/localMember/LocalTransport.ts +++ b/src/state/CallViewModel/localMember/LocalTransport.ts @@ -159,10 +159,12 @@ const FOCI_WK_KEY = "org.matrix.msc4143.rtc_foci"; * 4. The transport configured in Element Call's config. * * @param client The authenticated Matrix client for the current user + * @param membership The membership identity of the user. * @param roomId The ID of the room to be connected to. * @param urlFromDevSettings Override URL provided by the user's local config. - * @param useMatrix2 This implies using the matrix2 jwt endpoint (including delayed event delegation of the jwt token) - * @param delayId + * @param forceOldJwtEndpoint Whether to force the old JWT endpoint (not hashing the backendIdentity). + * @param delayId the delay id passed to the jwt service. + * * @returns A fully validated transport config. * @throws MatrixRTCTransportMissingError | FailToGetOpenIdToken */ diff --git a/src/state/CallViewModel/remoteMembers/ConnectionFactory.ts b/src/state/CallViewModel/remoteMembers/ConnectionFactory.ts index 8e9c0dab4..668538aca 100644 --- a/src/state/CallViewModel/remoteMembers/ConnectionFactory.ts +++ b/src/state/CallViewModel/remoteMembers/ConnectionFactory.ts @@ -31,8 +31,8 @@ export interface ConnectionFactory { createConnection( transport: LivekitTransport, scope: ObservableScope, - logger: Logger, ownMembershipIdentity: CallMembershipIdentityParts, + logger: Logger, forceOldJwtEndpoint?: boolean, ): Connection; } @@ -83,17 +83,18 @@ export class ECConnectionFactory implements ConnectionFactory { /** * - * @param transport - * @param scope - * @param logger + * @param transport The transport to use for this connection. + * @param scope The observable scope (used for clean-up) * @param ownMembershipIdentity required to connect (using the jwt service) with the SFU. + * @param logger The logger instance to use for this connection. + * @param forceOldJwtEndpoint Use the old JWT endpoint independent of what the sfu supports. * @returns */ public createConnection( transport: LivekitTransport, scope: ObservableScope, - logger: Logger, ownMembershipIdentity: CallMembershipIdentityParts, + logger: Logger, forceOldJwtEndpoint?: boolean, ): Connection { return new Connection( diff --git a/src/state/CallViewModel/remoteMembers/ConnectionManager.ts b/src/state/CallViewModel/remoteMembers/ConnectionManager.ts index aa5a15ba2..9d546d24c 100644 --- a/src/state/CallViewModel/remoteMembers/ConnectionManager.ts +++ b/src/state/CallViewModel/remoteMembers/ConnectionManager.ts @@ -83,8 +83,12 @@ export interface IConnectionManager { * @param props - Configuration object * @param props.scope - The observable scope used by this object * @param props.connectionFactory - Used to create new connections - * @param props.inputTransports$ - A list of Behaviors each containing a LIST of LivekitTransport. - * @param props.logger - The logger to use + * @param props.localTransport$ - The local transport to use. (deduplicated with remoteTransports$) + * @param props.remoteTransports$ - All other transports. The connection manager will create connections for each transport. (deduplicated with localTransport$) + * @param props.ownMembershipIdentity - The own membership identity to use. + * @param props.logger - The logger to use. + * @param props.forceOldJwtEndpointForLocalTransport$ - Use the old JWT endpoint independent of what the sfu supports. Only applies for localTransport$. + * * Each of these behaviors can be interpreted as subscribed list of transports. * * Using `registerTransports` independent external modules can control what connections @@ -183,8 +187,8 @@ export function createConnectionManager$({ livekit_alias: alias, }, scope, - logger, ownMembershipIdentity, + logger, forceOldJwtEndpoint, ); // Start the connection immediately diff --git a/src/state/CallViewModel/remoteMembers/ECConnectionFactory.test.ts b/src/state/CallViewModel/remoteMembers/ECConnectionFactory.test.ts index 3c60e7760..f28bd1580 100644 --- a/src/state/CallViewModel/remoteMembers/ECConnectionFactory.test.ts +++ b/src/state/CallViewModel/remoteMembers/ECConnectionFactory.test.ts @@ -79,8 +79,8 @@ describe("ECConnectionFactory - Audio inputs options", () => { ecConnectionFactory.createConnection( exampleTransport, testScope, - logger, ownMemberMock, + logger, ); // Check if Room was constructed with expected options @@ -125,8 +125,8 @@ describe("ECConnectionFactory - ControlledAudioDevice", () => { ecConnectionFactory.createConnection( exampleTransport, testScope, - logger, ownMemberMock, + logger, ); // Check if Room was constructed with expected options From 83d04ac1222784de3af2997e2021ebf2a8766fdd Mon Sep 17 00:00:00 2001 From: Timo K Date: Wed, 7 Jan 2026 13:26:37 +0100 Subject: [PATCH 148/748] fix tests and remove duplicated mocks. --- .../localMember/LocalMember.test.ts | 11 ++- .../localMember/LocalTransport.test.ts | 6 ++ .../localMember/LocalTransport.ts | 6 +- .../remoteMembers/ConnectionManager.ts | 8 +- .../MatrixLivekitMembers.test.ts | 6 +- .../MatrixMemberMetadata.test.ts | 72 ++++++++-------- .../remoteMembers/integration.test.ts | 8 +- src/utils/test-fixtures.ts | 14 ++-- src/utils/test.ts | 84 +++++++------------ 9 files changed, 103 insertions(+), 112 deletions(-) diff --git a/src/state/CallViewModel/localMember/LocalMember.test.ts b/src/state/CallViewModel/localMember/LocalMember.test.ts index edd5ea1ec..8a7505eb9 100644 --- a/src/state/CallViewModel/localMember/LocalMember.test.ts +++ b/src/state/CallViewModel/localMember/LocalMember.test.ts @@ -104,7 +104,7 @@ describe("LocalMembership", () => { getOldestMembership: vi.fn().mockReturnValue({ getPreferredFoci: vi.fn().mockReturnValue([focusFromOlderMembership]), }), - joinRoomSession: vi.fn(), + joinRTCSession: vi.fn(), }) as unknown as MatrixRTCSession; enterRTCSession( @@ -121,7 +121,12 @@ describe("LocalMembership", () => { }, ); - expect(mockedSession.joinRoomSession).toHaveBeenLastCalledWith( + expect(mockedSession.joinRTCSession).toHaveBeenLastCalledWith( + { + deviceId: "DEVICE", + memberId: "@alice:example.org:DEVICE", + userId: "@alice:example.org", + }, [ { livekit_alias: "roomId", @@ -163,7 +168,7 @@ describe("LocalMembership", () => { }, memberships: [], getFocusInUse: vi.fn(), - joinRoomSession: vi.fn(), + joinRTCSession: vi.fn(), }) as unknown as MatrixRTCSession; enterRTCSession( diff --git a/src/state/CallViewModel/localMember/LocalTransport.test.ts b/src/state/CallViewModel/localMember/LocalTransport.test.ts index 2199ca946..c37cab56b 100644 --- a/src/state/CallViewModel/localMember/LocalTransport.test.ts +++ b/src/state/CallViewModel/localMember/LocalTransport.test.ts @@ -154,6 +154,7 @@ describe("LocalTransport", () => { await flushPromises(); // final expect(localTransport$.value).toStrictEqual({ + forceOldJwtEndpoint: false, livekit_alias: "!room:example.org", livekit_service_url: "https://lk.example.org", type: "livekit", @@ -195,6 +196,7 @@ describe("LocalTransport", () => { await flushPromises(); // final expect(localTransport$.value).toStrictEqual({ + forceOldJwtEndpoint: false, livekit_alias: "!example_room_id", livekit_service_url: "https://lk.example.org", type: "livekit", @@ -247,6 +249,7 @@ describe("LocalTransport", () => { expect(localTransport$.value).toBe(null); await flushPromises(); expect(localTransport$.value).toStrictEqual({ + forceOldJwtEndpoint: false, livekit_alias: "!example_room_id", livekit_service_url: "https://lk.example.org", type: "livekit", @@ -259,6 +262,7 @@ describe("LocalTransport", () => { expect(localTransport$.value).toBe(null); await flushPromises(); expect(localTransport$.value).toStrictEqual({ + forceOldJwtEndpoint: false, livekit_alias: "!example_room_id", livekit_service_url: "https://lk.example.org", type: "livekit", @@ -273,6 +277,7 @@ describe("LocalTransport", () => { expect(localTransport$.value).toBe(null); await flushPromises(); expect(localTransport$.value).toStrictEqual({ + forceOldJwtEndpoint: false, livekit_alias: "!example_room_id", livekit_service_url: "https://lk.example.org", type: "livekit", @@ -304,6 +309,7 @@ describe("LocalTransport", () => { expect(localTransport$.value).toBe(null); await flushPromises(); expect(localTransport$.value).toStrictEqual({ + forceOldJwtEndpoint: false, livekit_alias: "!example_room_id", livekit_service_url: "https://lk.example.org", type: "livekit", diff --git a/src/state/CallViewModel/localMember/LocalTransport.ts b/src/state/CallViewModel/localMember/LocalTransport.ts index fa3168059..0dae3c991 100644 --- a/src/state/CallViewModel/localMember/LocalTransport.ts +++ b/src/state/CallViewModel/localMember/LocalTransport.ts @@ -84,7 +84,9 @@ export const createLocalTransport$ = ({ useOldestMember$, useOldJwtEndpoint$, delayId$, -}: Props): Behavior => { +}: Props): Behavior< + (LivekitTransport & { forceOldJwtEndpoint: boolean }) | null +> => { /** * The transport over which we should be actively publishing our media. * undefined when not joined. @@ -108,7 +110,7 @@ export const createLocalTransport$ = ({ * * @throws MatrixRTCTransportMissingError | FailToGetOpenIdToken */ - const preferredTransport$: Behavior = scope.behavior( + const preferredTransport$ = scope.behavior( combineLatest([customLivekitUrl.value$, delayId$, useOldJwtEndpoint$]).pipe( switchMap(([customUrl, delayId, forceOldJwtEndpoint]) => from( diff --git a/src/state/CallViewModel/remoteMembers/ConnectionManager.ts b/src/state/CallViewModel/remoteMembers/ConnectionManager.ts index 9d546d24c..e5a542dfa 100644 --- a/src/state/CallViewModel/remoteMembers/ConnectionManager.ts +++ b/src/state/CallViewModel/remoteMembers/ConnectionManager.ts @@ -144,12 +144,14 @@ export function createConnectionManager$({ localTransport, forceOldJwtEndpointForLocalTransport, ]) => { - // nmodify only the local transport with forceOldJwtEndpointForLocalTransport + // modify only the local transport with forceOldJwtEndpointForLocalTransport const index = transports.value.findIndex((t) => areLivekitTransportsEqual(localTransport, t), ); - transports.value[index].forceOldJwtEndpoint = - forceOldJwtEndpointForLocalTransport; + if (index !== -1) { + transports.value[index].forceOldJwtEndpoint = + forceOldJwtEndpointForLocalTransport; + } logger.trace( `Managing transports: ${transports.value.map((t) => t.livekit_service_url).join(", ")}`, ); diff --git a/src/state/CallViewModel/remoteMembers/MatrixLivekitMembers.test.ts b/src/state/CallViewModel/remoteMembers/MatrixLivekitMembers.test.ts index de0d7ecc2..55549a102 100644 --- a/src/state/CallViewModel/remoteMembers/MatrixLivekitMembers.test.ts +++ b/src/state/CallViewModel/remoteMembers/MatrixLivekitMembers.test.ts @@ -26,7 +26,7 @@ import { import { ConnectionManagerData } from "./ConnectionManager.ts"; import { flushPromises, - mockCallMembership, + mockRtcMembership, mockRemoteParticipant, } from "../../../utils/test.ts"; import { type Connection } from "./Connection.ts"; @@ -49,12 +49,12 @@ const transportB: LivekitTransport = { livekit_alias: "!alias:sample.com", }; -const bobMembership = mockCallMembership( +const bobMembership = mockRtcMembership( "@bob:example.org", "DEV000", transportA, ); -const carlMembership = mockCallMembership( +const carlMembership = mockRtcMembership( "@carl:sample.com", "DEV111", transportB, diff --git a/src/state/CallViewModel/remoteMembers/MatrixMemberMetadata.test.ts b/src/state/CallViewModel/remoteMembers/MatrixMemberMetadata.test.ts index 6f3923519..f7dd775c8 100644 --- a/src/state/CallViewModel/remoteMembers/MatrixMemberMetadata.test.ts +++ b/src/state/CallViewModel/remoteMembers/MatrixMemberMetadata.test.ts @@ -18,7 +18,7 @@ import { it } from "vitest"; import { ObservableScope } from "../../ObservableScope.ts"; import type { Room as MatrixRoom } from "matrix-js-sdk/lib/models/room"; import { - mockCallMembership, + mockRtcMembership, mockMatrixRoomMember, withTestScheduler, } from "../../../utils/test.ts"; @@ -111,7 +111,7 @@ describe("MatrixMemberMetadata", () => { rawDisplayName: "it's a me", }); const memberships$ = behavior("a", { - a: [mockCallMembership("@local:example.com", "DEVICE1")], + a: [mockRtcMembership("@local:example.com", "DEVICE1")], }); const metadataStore = createMatrixMemberMetadata$( testScope, @@ -149,8 +149,8 @@ describe("MatrixMemberMetadata", () => { withTestScheduler(({ behavior, expectObservable }) => { const memberships$ = behavior("a", { a: [ - mockCallMembership("@alice:example.com", "DEVICE1"), - mockCallMembership("@bob:example.com", "DEVICE1"), + mockRtcMembership("@alice:example.com", "DEVICE1"), + mockRtcMembership("@bob:example.com", "DEVICE1"), ], }); const metadataStore = createMatrixMemberMetadata$( @@ -179,7 +179,7 @@ describe("MatrixMemberMetadata", () => { setUpBasicRoom(); const memberships$ = behavior("a", { - a: [mockCallMembership("@no-name:foo.bar", "D000")], + a: [mockRtcMembership("@no-name:foo.bar", "D000")], }); const metadataStore = createMatrixMemberMetadata$( testScope, @@ -201,11 +201,11 @@ describe("MatrixMemberMetadata", () => { const memberships$ = behavior("a", { a: [ - mockCallMembership("@bob:example.com", "DEVICE1"), - mockCallMembership("@bob:example.com", "DEVICE2"), - mockCallMembership("@bob:foo.bar", "BOB000"), - mockCallMembership("@carl:example.com", "C000"), - mockCallMembership("@evil:example.com", "E000"), + mockRtcMembership("@bob:example.com", "DEVICE1"), + mockRtcMembership("@bob:example.com", "DEVICE2"), + mockRtcMembership("@bob:foo.bar", "BOB000"), + mockRtcMembership("@carl:example.com", "C000"), + mockRtcMembership("@evil:example.com", "E000"), ], }); @@ -233,10 +233,10 @@ describe("MatrixMemberMetadata", () => { setUpBasicRoom(); const memberships$ = behavior("ab", { - a: [mockCallMembership("@bob:example.com", "DEVICE1")], + a: [mockRtcMembership("@bob:example.com", "DEVICE1")], b: [ - mockCallMembership("@bob:example.com", "DEVICE1"), - mockCallMembership("@bob:foo.bar", "BOB000"), + mockRtcMembership("@bob:example.com", "DEVICE1"), + mockRtcMembership("@bob:foo.bar", "BOB000"), ], }); @@ -262,10 +262,10 @@ describe("MatrixMemberMetadata", () => { const memberships$ = behavior("ab", { a: [ - mockCallMembership("@bob:example.com", "DEVICE1"), - mockCallMembership("@bob:foo.bar", "BOB000"), + mockRtcMembership("@bob:example.com", "DEVICE1"), + mockRtcMembership("@bob:foo.bar", "BOB000"), ], - b: [mockCallMembership("@bob:example.com", "DEVICE1")], + b: [mockRtcMembership("@bob:example.com", "DEVICE1")], }); const metadataStore = createMatrixMemberMetadata$( @@ -292,8 +292,8 @@ describe("MatrixMemberMetadata", () => { const memberships$ = behavior("a", { a: [ - mockCallMembership("@bob:example.com", "B000"), - mockCallMembership("@carl:example.com", "C000"), + mockRtcMembership("@bob:example.com", "B000"), + mockRtcMembership("@carl:example.com", "C000"), ], }); const metadataStore = createMatrixMemberMetadata$( @@ -331,16 +331,16 @@ describe("MatrixMemberMetadata", () => { // - room join/leave // - disambiguate const memberships$ = behavior("ab-d", { - a: [mockCallMembership(CARL, "C000")], + a: [mockRtcMembership(CARL, "C000")], b: [ - mockCallMembership(CARL, "C000"), + mockRtcMembership(CARL, "C000"), // bob joins - mockCallMembership(BOB, "B000"), + mockRtcMembership(BOB, "B000"), ], // c carl gets renamed to BOB d: [ // carl leaves - mockCallMembership(BOB, "B000"), + mockRtcMembership(BOB, "B000"), ], }); schedule("--a-", { @@ -379,8 +379,8 @@ describe("MatrixMemberMetadata", () => { it("should disambiguate users with invisible characters", () => { withTestScheduler(({ behavior, expectObservable }) => { - const bobRtcMember = mockCallMembership("@bob:example.org", "BBBB"); - const bobZeroWidthSpaceRtcMember = mockCallMembership( + const bobRtcMember = mockRtcMembership("@bob:example.org", "BBBB"); + const bobZeroWidthSpaceRtcMember = mockRtcMembership( "@bob2:example.org", "BBBB", ); @@ -397,9 +397,9 @@ describe("MatrixMemberMetadata", () => { fakeMemberWith(bobZeroWidthSpace); fakeMemberWith({ userId: "@carol:example.org" }); const memberships$ = behavior("ab", { - a: [mockCallMembership("@carol:example.org", "1111"), bobRtcMember], + a: [mockRtcMembership("@carol:example.org", "1111"), bobRtcMember], b: [ - mockCallMembership("@carol:example.org", "1111"), + mockRtcMembership("@carol:example.org", "1111"), bobRtcMember, bobZeroWidthSpaceRtcMember, ], @@ -450,8 +450,8 @@ describe("MatrixMemberMetadata", () => { it("should strip RTL characters from displayname", () => { withTestScheduler(({ behavior, expectObservable }) => { - const daveRtcMember = mockCallMembership("@dave:example.org", "DDDD"); - const daveRTLRtcMember = mockCallMembership( + const daveRtcMember = mockRtcMembership("@dave:example.org", "DDDD"); + const daveRTLRtcMember = mockRtcMembership( "@dave2:example.org", "DDDD", ); @@ -466,9 +466,9 @@ describe("MatrixMemberMetadata", () => { fakeMemberWith(daveRTL); fakeMemberWith(dave); const memberships$ = behavior("ab", { - a: [mockCallMembership("@carol:example.org", "DDDD")], + a: [mockRtcMembership("@carol:example.org", "DDDD")], b: [ - mockCallMembership("@carol:example.org", "DDDD"), + mockRtcMembership("@carol:example.org", "DDDD"), daveRtcMember, daveRTLRtcMember, ], @@ -527,8 +527,8 @@ describe("MatrixMemberMetadata", () => { }); const memberships$ = behavior("a", { a: [ - mockCallMembership("@local:example.com", "DEVICE1"), - mockCallMembership("@alice:example.com", "DEVICE1"), + mockRtcMembership("@local:example.com", "DEVICE1"), + mockRtcMembership("@alice:example.com", "DEVICE1"), ], }); const metadataStore = createMatrixMemberMetadata$( @@ -562,12 +562,12 @@ describe("MatrixMemberMetadata", () => { fakeMemberWith({ userId: "@carl:example.com" }); fakeMemberWith({ userId: "@bob:example.com" }); const memberships$ = behavior("ab-d", { - a: [mockCallMembership("@bob:example.com", "B000")], + a: [mockRtcMembership("@bob:example.com", "B000")], b: [ - mockCallMembership("@bob:example.com", "B000"), - mockCallMembership("@carl:example.com", "C000"), + mockRtcMembership("@bob:example.com", "B000"), + mockRtcMembership("@carl:example.com", "C000"), ], - d: [mockCallMembership("@carl:example.com", "C000")], + d: [mockRtcMembership("@carl:example.com", "C000")], }); const metadataStore = createMatrixMemberMetadata$( diff --git a/src/state/CallViewModel/remoteMembers/integration.test.ts b/src/state/CallViewModel/remoteMembers/integration.test.ts index 84e094876..c29f07c04 100644 --- a/src/state/CallViewModel/remoteMembers/integration.test.ts +++ b/src/state/CallViewModel/remoteMembers/integration.test.ts @@ -21,8 +21,8 @@ import { import { ECConnectionFactory } from "./ConnectionFactory.ts"; import { type OpenIDClientParts } from "../../../livekit/openIDSFU.ts"; import { - mockCallMembership, mockMediaDevices, + mockRtcMembership, ownMemberMock, withTestScheduler, } from "../../../utils/test.ts"; @@ -101,9 +101,9 @@ afterEach(() => { test("bob, carl, then bob joining no tracks yet", () => { withTestScheduler(({ expectObservable, behavior, scope }) => { - const bobMembership = mockCallMembership("@bob:example.com", "BDEV000"); - const carlMembership = mockCallMembership("@carl:example.com", "CDEV000"); - const daveMembership = mockCallMembership("@dave:foo.bar", "DDEV000"); + const bobMembership = mockRtcMembership("@bob:example.com", "BDEV000"); + const carlMembership = mockRtcMembership("@carl:example.com", "CDEV000"); + const daveMembership = mockRtcMembership("@dave:foo.bar", "DDEV000"); const eMarble = "abc"; const vMarble = "abc"; diff --git a/src/utils/test-fixtures.ts b/src/utils/test-fixtures.ts index f915bb19a..dcdb9f9c9 100644 --- a/src/utils/test-fixtures.ts +++ b/src/utils/test-fixtures.ts @@ -17,14 +17,16 @@ export const localRtcMemberDevice2 = mockRtcMembership( "2222", ); export const local = mockMatrixRoomMember(localRtcMember); -// export const localParticipant = mockLocalParticipant({ identity: "" }); + export const localId = `${local.userId}:${localRtcMember.deviceId}`; -export const aliceRtcMember = mockRtcMembership("@alice:example.org", "AAAA"); +export const aliceDeviceId = "AAAA"; +export const aliceUserId = "@alice:example.org"; +export const aliceId = `${aliceUserId}:${aliceDeviceId}`; +export const aliceRtcMember = mockRtcMembership(aliceUserId, aliceDeviceId); export const alice = mockMatrixRoomMember(aliceRtcMember, { rawDisplayName: "Alice", }); -export const aliceId = `${alice.userId}:${aliceRtcMember.deviceId}`; export const aliceParticipant = mockRemoteParticipant({ identity: aliceId }); export const aliceDoppelgangerRtcMember = mockRtcMembership( @@ -38,11 +40,13 @@ export const aliceDoppelganger = mockMatrixRoomMember( }, ); -export const bobRtcMember = mockRtcMembership("@bob:example.org", "BBBB"); +export const bobDeviceId = "BBBB"; +export const bobUserId = "@bob:example.org"; +export const bobId = `${bobUserId}:${bobDeviceId}`; +export const bobRtcMember = mockRtcMembership(bobUserId, bobDeviceId); export const bob = mockMatrixRoomMember(bobRtcMember, { rawDisplayName: "Bob", }); -export const bobId = `${bob.userId}:${bobRtcMember.deviceId}`; export const bobZeroWidthSpaceRtcMember = mockRtcMembership( "@bob2:example.org", diff --git a/src/utils/test.ts b/src/utils/test.ts index 02277af0e..b19ea9610 100644 --- a/src/utils/test.ts +++ b/src/utils/test.ts @@ -203,40 +203,30 @@ export const exampleTransport: LivekitTransport = { livekit_alias: "!alias:example.org", }; -export function mockCallMembership( - userId: string, - deviceId: string, - transport?: Transport, -): CallMembership { - const t = transport ?? transportForUser(userId); - return { - userId: userId, - deviceId: deviceId, - getTransport: vi.fn().mockReturnValue(t), - transports: [t], - } as unknown as CallMembership; -} - -function transportForUser(userId: string): Transport { - const domain = userId.split(":")[1]; - return { - type: "livekit", - livekit_service_url: `https://lk.${domain}`, - livekit_alias: `!alias:${domain}`, - }; -} - export function mockRtcMembership( user: string | RoomMember, deviceId: string, - callId = "", - fociPreferred: Transport[] = [exampleTransport], - focusActive: LivekitFocusSelection = { - type: "livekit", - focus_selection: "oldest_membership", + customOverwrites?: { + rtcBackendIdentity?: string; + callId?: string; + fociPreferred?: Transport[]; + focusActive?: LivekitFocusSelection; + membership?: Partial; }, - membership: Partial = {}, ): CallMembership { + // setup defaults based on overwrites and fallback values. + const { rtcBackendIdentity, callId, fociPreferred, focusActive, membership } = + { + fociPreferred: [exampleTransport], + focusActive: { + type: "livekit" as const, + focus_selection: "oldest_membership" as const, + }, + callId: "", + membership: {}, + ...customOverwrites, + }; + const data: SessionMembershipData = { application: "m.call", call_id: callId, @@ -245,15 +235,21 @@ export function mockRtcMembership( focus_active: focusActive, ...membership, }; + const userId = typeof user === "string" ? user : user.userId; const event = new MatrixEvent({ - sender: typeof user === "string" ? user : user.userId, + sender: userId, event_id: `$-ev-${randomUUID()}:example.org`, content: data, }); const membershipData = CallMembership.membershipDataFromMatrixEvent(event); - const cms = new CallMembership(event, membershipData, "xx"); + const cms = new CallMembership( + event, + membershipData, + rtcBackendIdentity ?? `${userId}:${deviceId}`, + ); vi.mocked(cms).getTransport = vi.fn().mockReturnValue(fociPreferred[0]); + return cms; } @@ -486,7 +482,7 @@ export class MockRTCSession extends TypedEventEmitter< if (value !== prev) this.emit(MembershipManagerEvent.ProbablyLeft, value); } - public async joinRoomSession(): Promise { + public async joinRTCSession(): Promise { return Promise.resolve(); } } @@ -535,27 +531,3 @@ export function mockMuteStates( const observableScope = new ObservableScope(); return new MuteStates(observableScope, mockMediaDevices({}), joined$); } - -export const mockComputeLivekitParticipantIdentity$ = ( - membership: CallMembershipIdentityParts, - kind: "rtc" | "session", -): Observable => { - function sha256(commitmentStr: string): string { - return encodeUnpaddedBase64( - createHash("sha256").update(commitmentStr, "utf8").digest(), - ); - } - let hash; - switch (kind) { - case "rtc": { - hash = sha256( - `${membership.userId}|${membership.deviceId}|${membership.memberId}`, - ); - break; - } - case "session": - default: - hash = `${membership.userId}:${membership.deviceId}`; - } - return of(hash); -}; From 6480df44e9c4706b6b49ba723b2e70233bb00eea Mon Sep 17 00:00:00 2001 From: Timo K Date: Wed, 7 Jan 2026 15:10:24 +0100 Subject: [PATCH 149/748] add tests for open id delay fallback --- src/livekit/openIDSFU.test.ts | 99 +++++++++++++++++++ .../MatrixLivekitMembers.test.ts | 16 ++- src/utils/test.ts | 3 +- 3 files changed, 106 insertions(+), 12 deletions(-) diff --git a/src/livekit/openIDSFU.test.ts b/src/livekit/openIDSFU.test.ts index 8b263662c..22e487f51 100644 --- a/src/livekit/openIDSFU.test.ts +++ b/src/livekit/openIDSFU.test.ts @@ -34,6 +34,7 @@ describe("getSFUConfigWithOpenID", () => { vitest.clearAllMocks(); fetchMock.reset(); }); + it("should handle fetching a token", async () => { fetchMock.post("https://sfu.example.org/sfu/get", () => { return { @@ -56,6 +57,7 @@ describe("getSFUConfigWithOpenID", () => { }); void (await fetchMock.flush()); }); + it("should fail if the SFU errors", async () => { fetchMock.post("https://sfu.example.org/sfu/get", () => { return { @@ -81,6 +83,103 @@ describe("getSFUConfigWithOpenID", () => { expect.fail("Expected test to throw;"); }); + it("should try legacy and then new endpoint with delay delegation", async () => { + fetchMock.post("https://sfu.example.org/get_token", () => { + return { + status: 500, + body: { error: "Test failure" }, + }; + }); + fetchMock.post("https://sfu.example.org/sfu/get", () => { + return { + status: 500, + body: { error: "Test failure" }, + }; + }); + try { + await getSFUConfigWithOpenID( + matrixClient, + ownMemberMock, + "https://sfu.example.org", + false, + "!example_room_id", + "https://matrix.homeserverserver.org", + "mock_delay_id", + ); + } catch (ex) { + logger.info(ex); + expect(((ex as Error).cause as Error).message).toEqual( + "SFU Config fetch failed with status code 500", + ); + void (await fetchMock.flush()); + } + const calls = fetchMock.calls(); + expect(calls.length).toBe(2); + + expect(calls[0][0]).toStrictEqual("https://sfu.example.org/get_token"); + expect(calls[0][1]).toStrictEqual({ + // check if it uses correct delayID! + body: '{"room_id":"!example_room_id","slot_id":"m.call#ROOM","member":{"id":"@alice:example.org:DEVICE","claimed_user_id":"@alice:example.org","claimed_device_id":"DEVICE"},"delay_id":"mock_delay_id","delay_timeout":1000,"delay_cs_api_url":"https://matrix.homeserverserver.org"}', + method: "POST", + headers: { + "Content-Type": "application/json", + }, + }); + + expect(calls[1][0]).toStrictEqual("https://sfu.example.org/sfu/get"); + + expect(calls[1][1]).toStrictEqual({ + body: '{"room":"!example_room_id","device_id":"DEVICE"}', + headers: { + "Content-Type": "application/json", + }, + method: "POST", + }); + }); + + it("dont try legacy if endpoint with delay delegation is sucessful", async () => { + fetchMock.post("https://sfu.example.org/get_token", () => { + return { + status: 200, + body: { url: sfuUrl, jwt: testJWTToken }, + }; + }); + fetchMock.post("https://sfu.example.org/sfu/get", () => { + return { + status: 500, + body: { error: "Test failure" }, + }; + }); + try { + await getSFUConfigWithOpenID( + matrixClient, + ownMemberMock, + "https://sfu.example.org", + false, + "!example_room_id", + "https://matrix.homeserverserver.org", + "mock_delay_id", + ); + } catch (ex) { + expect(((ex as Error).cause as Error).message).toEqual( + "SFU Config fetch failed with status code 500", + ); + void (await fetchMock.flush()); + } + const calls = fetchMock.calls(); + expect(calls.length).toBe(1); + + expect(calls[0][0]).toStrictEqual("https://sfu.example.org/get_token"); + expect(calls[0][1]).toStrictEqual({ + // check if it uses correct delayID! + body: '{"room_id":"!example_room_id","slot_id":"m.call#ROOM","member":{"id":"@alice:example.org:DEVICE","claimed_user_id":"@alice:example.org","claimed_device_id":"DEVICE"},"delay_id":"mock_delay_id","delay_timeout":1000,"delay_cs_api_url":"https://matrix.homeserverserver.org"}', + method: "POST", + headers: { + "Content-Type": "application/json", + }, + }); + }); + it("should retry fetching the openid token", async () => { let count = 0; matrixClient.getOpenIdToken.mockImplementation(async () => { diff --git a/src/state/CallViewModel/remoteMembers/MatrixLivekitMembers.test.ts b/src/state/CallViewModel/remoteMembers/MatrixLivekitMembers.test.ts index 55549a102..5d34f7be1 100644 --- a/src/state/CallViewModel/remoteMembers/MatrixLivekitMembers.test.ts +++ b/src/state/CallViewModel/remoteMembers/MatrixLivekitMembers.test.ts @@ -49,16 +49,12 @@ const transportB: LivekitTransport = { livekit_alias: "!alias:sample.com", }; -const bobMembership = mockRtcMembership( - "@bob:example.org", - "DEV000", - transportA, -); -const carlMembership = mockRtcMembership( - "@carl:sample.com", - "DEV111", - transportB, -); +const bobMembership = mockRtcMembership("@bob:example.org", "DEV000", { + fociPreferred: [transportA], +}); +const carlMembership = mockRtcMembership("@carl:sample.com", "DEV111", { + fociPreferred: [transportB], +}); beforeEach(() => { testScope = new ObservableScope(); diff --git a/src/utils/test.ts b/src/utils/test.ts index b19ea9610..d24ad1309 100644 --- a/src/utils/test.ts +++ b/src/utils/test.ts @@ -15,7 +15,6 @@ import { vitest, } from "vitest"; import { - encodeUnpaddedBase64, MatrixEvent, type Room as MatrixRoom, type Room, @@ -44,7 +43,7 @@ import { type Room as LivekitRoom, Track, } from "livekit-client"; -import { createHash, randomUUID } from "crypto"; +import { randomUUID } from "crypto"; import { type TrackReference } from "@livekit/components-core"; import EventEmitter from "events"; import { From d48042f5220fca828a471892f52ed23879261728 Mon Sep 17 00:00:00 2001 From: Timo K Date: Wed, 7 Jan 2026 15:18:37 +0100 Subject: [PATCH 150/748] fix lint --- src/livekit/openIDSFU.test.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/livekit/openIDSFU.test.ts b/src/livekit/openIDSFU.test.ts index 22e487f51..aed66d33e 100644 --- a/src/livekit/openIDSFU.test.ts +++ b/src/livekit/openIDSFU.test.ts @@ -107,7 +107,6 @@ describe("getSFUConfigWithOpenID", () => { "mock_delay_id", ); } catch (ex) { - logger.info(ex); expect(((ex as Error).cause as Error).message).toEqual( "SFU Config fetch failed with status code 500", ); From dd562bdaf51ec99c63c0a754c31bf2d9d90fe186 Mon Sep 17 00:00:00 2001 From: Timo K Date: Wed, 7 Jan 2026 15:36:32 +0100 Subject: [PATCH 151/748] dont use throw for logic. --- src/livekit/openIDSFU.ts | 51 +++++++++++++++++++++++----------------- 1 file changed, 29 insertions(+), 22 deletions(-) diff --git a/src/livekit/openIDSFU.ts b/src/livekit/openIDSFU.ts index b89243c19..6bade4efe 100644 --- a/src/livekit/openIDSFU.ts +++ b/src/livekit/openIDSFU.ts @@ -105,35 +105,42 @@ export async function getSFUConfigWithOpenID( logger?.info(`Trying to get JWT for focus ${serviceUrl}...`); - let sfuConfig: { url: string; jwt: string }; - try { - // we do not want to try the old endpoint, since we are not sending the new matrix2.0 sticky events (no hashed identity in the event) - if (forceOldJwtEndpoint) throw new Error("Force old jwt endpoint"); - if (!delayId) - throw new Error("No delayId, Won't try matrix 2.0 jwt endpoint."); + let sfuConfig: { url: string; jwt: string } | undefined; - sfuConfig = await getLiveKitJWTWithDelayDelegation( - membership, - serviceUrl, - roomId, - openIdToken, - delayEndpointBaseUrl, - delayId, - ); - logger?.info(`Got JWT from call's active focus URL.`); - } catch (e) { - logger?.warn( - `Failed fetching jwt with matrix 2.0 endpoint (retry with legacy)`, - e, - ); + // If forceOldJwtEndpoint is set we indicate that we do not want to try the new endpoint, + // since we are not sending the new matrix2.0 sticky events (no hashed identity in the event) + if (forceOldJwtEndpoint === false) { + try { + sfuConfig = await getLiveKitJWTWithDelayDelegation( + membership, + serviceUrl, + roomId, + openIdToken, + delayEndpointBaseUrl, + delayId, + ); + logger?.info(`Got JWT from call's active focus URL.`); + } catch (e) { + sfuConfig = undefined; + logger?.warn( + `Failed fetching jwt with matrix 2.0 endpoint (retry with legacy)`, + e, + ); + logger?.info(`Got JWT from call's active focus URL.`); + } + } + + // Either forceOldJwtEndpoint = true or getLiveKitJWTWithDelayDelegation throws -> reset sfuConfig = undefined + if (sfuConfig === undefined) { sfuConfig = await getLiveKitJWT( membership.deviceId, serviceUrl, roomId, openIdToken, ); - logger?.info(`Got JWT from call's active focus URL.`); - } // Pull the details from the JWT + } + + // Pull the details from the JWT const [, payloadStr] = sfuConfig.jwt.split("."); // TODO: Prefer Uint8Array.fromBase64 when widely available const payload = JSON.parse(global.atob(payloadStr)) as SFUJWTPayload; From d814f60f23b8d366bc7ef802ecfd87cbb24536ec Mon Sep 17 00:00:00 2001 From: Timo K Date: Wed, 7 Jan 2026 15:47:44 +0100 Subject: [PATCH 152/748] review (docstrings) and remove unused artifacts. --- src/state/CallViewModel/CallViewModel.ts | 1 + .../localMember/LocalTransport.ts | 20 +++++++------------ .../remoteMembers/Connection.test.ts | 1 - 3 files changed, 8 insertions(+), 14 deletions(-) diff --git a/src/state/CallViewModel/CallViewModel.ts b/src/state/CallViewModel/CallViewModel.ts index 093abfade..9654920d8 100644 --- a/src/state/CallViewModel/CallViewModel.ts +++ b/src/state/CallViewModel/CallViewModel.ts @@ -431,6 +431,7 @@ export function createCallViewModel$( const useOldJwtEndpoint$ = scope.behavior( matrixRTCMode$.pipe(map((v) => v !== MatrixRTCMode.Matrix_2_0)), ); + const localTransport$ = createLocalTransport$({ scope: scope, memberships$: memberships$, diff --git a/src/state/CallViewModel/localMember/LocalTransport.ts b/src/state/CallViewModel/localMember/LocalTransport.ts index 0dae3c991..8a6a750be 100644 --- a/src/state/CallViewModel/localMember/LocalTransport.ts +++ b/src/state/CallViewModel/localMember/LocalTransport.ts @@ -68,11 +68,10 @@ interface Props { * @prop useOldestMember Whether to use the same transport as the oldest member. * This will only update once the first oldest member appears. Will not recompute if the oldest member leaves. * - * @prop useOldJwtEndpoint$ Whether to set forceOldJwtEndpoint the use the old JWT endpoint. + * @prop useOldJwtEndpoint$ Whether to set forceOldJwtEndpoint on the returned transport and to use the old JWT endpoint. * This is used when the connection manager needs to know if it has to use the legacy endpoint which implies a string concatenated rtcBackendIdentity. * (which is expected for non sticky event based rtc member events) - * @returns Behavior<(LivekitTransport & { forceOldJwtEndpoint: boolean }) | null> The `forceOldJwtEndpoint` field is added to let the connection EncryptionManager - * know that this transport is for the local member and it IS RELEVANT which jwt endpoint to use. (for the local member transport, we need to know which jwt endpoint to use) + * @returns The local transport. It will be created using the correct sfu endpoint based on the useOldJwtEndpoint$ value. * @throws MatrixRTCTransportMissingError | FailToGetOpenIdToken */ export const createLocalTransport$ = ({ @@ -84,9 +83,7 @@ export const createLocalTransport$ = ({ useOldestMember$, useOldJwtEndpoint$, delayId$, -}: Props): Behavior< - (LivekitTransport & { forceOldJwtEndpoint: boolean }) | null -> => { +}: Props): Behavior => { /** * The transport over which we should be actively publishing our media. * undefined when not joined. @@ -97,7 +94,7 @@ export const createLocalTransport$ = ({ const oldestMember = memberships.value[0]; const transport = oldestMember?.getTransport(memberships.value[0]); if (!transport) return null; - return { ...transport, forceOldJwtEndpoint }; + return transport; }), first((t) => t != null && isLivekitTransport(t)), ), @@ -181,12 +178,10 @@ async function makeTransport( urlFromDevSettings: string | null, forceOldJwtEndpoint: boolean, delayId?: string, -): Promise { +): Promise { logger.trace("Searching for a preferred transport"); - async function doOpenIdAndJWTFromUrl( - url: string, - ): Promise { + async function doOpenIdAndJWTFromUrl(url: string): Promise { const { livekitAlias } = await getSFUConfigWithOpenID( client, membership, @@ -201,7 +196,6 @@ async function makeTransport( type: "livekit", livekit_service_url: url, livekit_alias: livekitAlias, - forceOldJwtEndpoint, }; } // We will call `getSFUConfigWithOpenID` once per transport here as it's our @@ -223,7 +217,7 @@ async function makeTransport( async function getFirstUsableTransport( transports: Transport[], - ): Promise<(LivekitTransport & { forceOldJwtEndpoint: boolean }) | null> { + ): Promise { for (const potentialTransport of transports) { if (isLivekitTransportConfig(potentialTransport)) { try { diff --git a/src/state/CallViewModel/remoteMembers/Connection.test.ts b/src/state/CallViewModel/remoteMembers/Connection.test.ts index 916e7dd4a..239a5c755 100644 --- a/src/state/CallViewModel/remoteMembers/Connection.test.ts +++ b/src/state/CallViewModel/remoteMembers/Connection.test.ts @@ -55,7 +55,6 @@ const livekitFocus: LivekitTransport = { livekit_alias: "!roomID:example.org", livekit_service_url: "https://matrix-rtc.example.org/livekit/jwt", type: "livekit", - useMatrix2: false, }; function setupTest(): void { From 75fca3108a17be45be925e67d86e48d4b5218674 Mon Sep 17 00:00:00 2001 From: Timo K Date: Wed, 7 Jan 2026 16:08:20 +0100 Subject: [PATCH 153/748] cleanup an rename compatibility mode --- src/settings/DeveloperSettingsTab.tsx | 4 ++-- src/settings/settings.ts | 2 +- src/state/CallViewModel/CallViewModel.test.ts | 2 +- src/state/CallViewModel/CallViewModel.ts | 6 +++++- src/state/CallViewModel/localMember/LocalMember.ts | 4 +++- src/state/CallViewModelWidget.test.ts | 2 +- 6 files changed, 13 insertions(+), 7 deletions(-) diff --git a/src/settings/DeveloperSettingsTab.tsx b/src/settings/DeveloperSettingsTab.tsx index 254aaf0f4..c88eadf0b 100644 --- a/src/settings/DeveloperSettingsTab.tsx +++ b/src/settings/DeveloperSettingsTab.tsx @@ -275,8 +275,8 @@ export const DeveloperSettingsTab: FC = ({ name={matrixRTCModeRadioGroup} control={ } diff --git a/src/settings/settings.ts b/src/settings/settings.ts index 33408fd90..a674f1aae 100644 --- a/src/settings/settings.ts +++ b/src/settings/settings.ts @@ -126,7 +126,7 @@ export const alwaysShowIphoneEarpiece = new Setting( export enum MatrixRTCMode { Legacy = "legacy", - Compatibil = "compatibil", + Compatibility = "compatibility", /** This implies using * - sticky events * - hashed RTC backend identity diff --git a/src/state/CallViewModel/CallViewModel.test.ts b/src/state/CallViewModel/CallViewModel.test.ts index 6e3837c42..376d8986e 100644 --- a/src/state/CallViewModel/CallViewModel.test.ts +++ b/src/state/CallViewModel/CallViewModel.test.ts @@ -235,7 +235,7 @@ const mockLegacyRingEvent = {} as { event_id: string } & ICallNotifyContent; describe.each([ [MatrixRTCMode.Legacy], - [MatrixRTCMode.Compatibil], + [MatrixRTCMode.Compatibility], [MatrixRTCMode.Matrix_2_0], ])("CallViewModel (%s mode)", (mode) => { const withCallViewModel = withCallViewModelInMode(mode); diff --git a/src/state/CallViewModel/CallViewModel.ts b/src/state/CallViewModel/CallViewModel.ts index 9654920d8..c75b3ec49 100644 --- a/src/state/CallViewModel/CallViewModel.ts +++ b/src/state/CallViewModel/CallViewModel.ts @@ -429,7 +429,11 @@ export function createCallViewModel$( }; const useOldJwtEndpoint$ = scope.behavior( - matrixRTCMode$.pipe(map((v) => v !== MatrixRTCMode.Matrix_2_0)), + matrixRTCMode$.pipe( + map( + (v) => v === MatrixRTCMode.Legacy || v === MatrixRTCMode.Compatibility, + ), + ), ); const localTransport$ = createLocalTransport$({ diff --git a/src/state/CallViewModel/localMember/LocalMember.ts b/src/state/CallViewModel/localMember/LocalMember.ts index 17f766fff..5b72266f3 100644 --- a/src/state/CallViewModel/localMember/LocalMember.ts +++ b/src/state/CallViewModel/localMember/LocalMember.ts @@ -711,7 +711,9 @@ export function enterRTCSession( const useDeviceSessionMemberEvents = features?.feature_use_device_session_member_events; const { sendNotificationType: notificationType, callIntent } = getUrlParams(); - const multiSFU = matrixRTCMode !== MatrixRTCMode.Legacy; + const multiSFU = + matrixRTCMode === MatrixRTCMode.Compatibility || + matrixRTCMode === MatrixRTCMode.Matrix_2_0; // Multi-sfu does not need a preferred foci list. just the focus that is actually used. // TODO where/how do we track errors originating from the ongoing rtcSession? rtcSession.joinRTCSession( diff --git a/src/state/CallViewModelWidget.test.ts b/src/state/CallViewModelWidget.test.ts index 5d6442f16..76776720b 100644 --- a/src/state/CallViewModelWidget.test.ts +++ b/src/state/CallViewModelWidget.test.ts @@ -37,7 +37,7 @@ vi.mock("../widget", () => ({ it.each([ [MatrixRTCMode.Legacy], - [MatrixRTCMode.Compatibil], + [MatrixRTCMode.Compatibility], [MatrixRTCMode.Matrix_2_0], ])( "expect leave when ElementWidgetActions.HangupCall is called (%s mode)", From d5ad2e38e2583670f4ec11e7a000691b478a536a Mon Sep 17 00:00:00 2001 From: Timo K Date: Wed, 7 Jan 2026 16:09:08 +0100 Subject: [PATCH 154/748] fix up tests --- src/state/CallViewModel/localMember/LocalTransport.test.ts | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/state/CallViewModel/localMember/LocalTransport.test.ts b/src/state/CallViewModel/localMember/LocalTransport.test.ts index c37cab56b..2199ca946 100644 --- a/src/state/CallViewModel/localMember/LocalTransport.test.ts +++ b/src/state/CallViewModel/localMember/LocalTransport.test.ts @@ -154,7 +154,6 @@ describe("LocalTransport", () => { await flushPromises(); // final expect(localTransport$.value).toStrictEqual({ - forceOldJwtEndpoint: false, livekit_alias: "!room:example.org", livekit_service_url: "https://lk.example.org", type: "livekit", @@ -196,7 +195,6 @@ describe("LocalTransport", () => { await flushPromises(); // final expect(localTransport$.value).toStrictEqual({ - forceOldJwtEndpoint: false, livekit_alias: "!example_room_id", livekit_service_url: "https://lk.example.org", type: "livekit", @@ -249,7 +247,6 @@ describe("LocalTransport", () => { expect(localTransport$.value).toBe(null); await flushPromises(); expect(localTransport$.value).toStrictEqual({ - forceOldJwtEndpoint: false, livekit_alias: "!example_room_id", livekit_service_url: "https://lk.example.org", type: "livekit", @@ -262,7 +259,6 @@ describe("LocalTransport", () => { expect(localTransport$.value).toBe(null); await flushPromises(); expect(localTransport$.value).toStrictEqual({ - forceOldJwtEndpoint: false, livekit_alias: "!example_room_id", livekit_service_url: "https://lk.example.org", type: "livekit", @@ -277,7 +273,6 @@ describe("LocalTransport", () => { expect(localTransport$.value).toBe(null); await flushPromises(); expect(localTransport$.value).toStrictEqual({ - forceOldJwtEndpoint: false, livekit_alias: "!example_room_id", livekit_service_url: "https://lk.example.org", type: "livekit", @@ -309,7 +304,6 @@ describe("LocalTransport", () => { expect(localTransport$.value).toBe(null); await flushPromises(); expect(localTransport$.value).toStrictEqual({ - forceOldJwtEndpoint: false, livekit_alias: "!example_room_id", livekit_service_url: "https://lk.example.org", type: "livekit", From 0eeed4e18e58289b10b21b788281853b758a7938 Mon Sep 17 00:00:00 2001 From: Timo K Date: Wed, 7 Jan 2026 17:02:06 +0100 Subject: [PATCH 155/748] fix test snapshot --- src/settings/__snapshots__/DeveloperSettingsTab.test.tsx.snap | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/settings/__snapshots__/DeveloperSettingsTab.test.tsx.snap b/src/settings/__snapshots__/DeveloperSettingsTab.test.tsx.snap index 4a2dada09..1c82d07b4 100644 --- a/src/settings/__snapshots__/DeveloperSettingsTab.test.tsx.snap +++ b/src/settings/__snapshots__/DeveloperSettingsTab.test.tsx.snap @@ -284,7 +284,7 @@ exports[`DeveloperSettingsTab > renders and matches snapshot 1`] = ` name="_r_0_" title="" type="radio" - value="compatibil" + value="compatibility" />
Date: Wed, 7 Jan 2026 17:21:08 +0100 Subject: [PATCH 156/748] add retries and be more specific when we fall back to legacy endpoint --- src/livekit/openIDSFU.ts | 133 +++++++++++++++++++++++---------------- 1 file changed, 79 insertions(+), 54 deletions(-) diff --git a/src/livekit/openIDSFU.ts b/src/livekit/openIDSFU.ts index 6bade4efe..8c4434bd4 100644 --- a/src/livekit/openIDSFU.ts +++ b/src/livekit/openIDSFU.ts @@ -5,7 +5,12 @@ SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial Please see LICENSE in the repository root for full details. */ -import { type IOpenIDToken, type MatrixClient } from "matrix-js-sdk"; +import { + HTTPError, + retryNetworkOperation, + type IOpenIDToken, + type MatrixClient, +} from "matrix-js-sdk"; import { type CallMembershipIdentityParts } from "matrix-js-sdk/lib/matrixrtc/EncryptionManager"; import { type Logger } from "matrix-js-sdk/lib/logger"; @@ -111,33 +116,49 @@ export async function getSFUConfigWithOpenID( // since we are not sending the new matrix2.0 sticky events (no hashed identity in the event) if (forceOldJwtEndpoint === false) { try { - sfuConfig = await getLiveKitJWTWithDelayDelegation( - membership, - serviceUrl, - roomId, - openIdToken, - delayEndpointBaseUrl, - delayId, - ); - logger?.info(`Got JWT from call's active focus URL.`); + await retryNetworkOperation(4, async () => { + sfuConfig = await getLiveKitJWTWithDelayDelegation( + membership, + serviceUrl, + roomId, + openIdToken, + delayEndpointBaseUrl, + delayId, + ); + logger?.info(`Got JWT from call's active focus URL.`); + }); } catch (e) { - sfuConfig = undefined; - logger?.warn( - `Failed fetching jwt with matrix 2.0 endpoint (retry with legacy)`, - e, - ); - logger?.info(`Got JWT from call's active focus URL.`); + if (e instanceof NotSupportedError) { + logger?.warn( + `Failed fetching jwt with matrix 2.0 endpoint (retry with legacy) Not supported`, + e, + ); + sfuConfig = undefined; + } else { + logger?.warn( + `Failed fetching jwt with matrix 2.0 endpoint other issues -> not going to try with legacy endpoint`, + e, + ); + } } } + // DEPRECATED // Either forceOldJwtEndpoint = true or getLiveKitJWTWithDelayDelegation throws -> reset sfuConfig = undefined if (sfuConfig === undefined) { - sfuConfig = await getLiveKitJWT( - membership.deviceId, - serviceUrl, - roomId, - openIdToken, - ); + await retryNetworkOperation(4, async () => { + sfuConfig = await getLiveKitJWT( + membership.deviceId, + serviceUrl, + roomId, + openIdToken, + ); + }); + logger?.info(`Got JWT from call's active focus URL.`); + } + + if (!sfuConfig) { + throw new Error("No `sfuConfig` after trying with old and new endpoints"); } // Pull the details from the JWT @@ -161,25 +182,28 @@ async function getLiveKitJWT( matrixRoomId: string, openIDToken: IOpenIDToken, ): Promise<{ url: string; jwt: string }> { - try { - const res = await fetch(livekitServiceURL + "/sfu/get", { - method: "POST", - headers: { - "Content-Type": "application/json", - }, - body: JSON.stringify({ - // This is the actual livekit room alias. For the legacy jwt endpoint simply the room id was used. - room: matrixRoomId, - openid_token: openIDToken, - device_id: deviceId, - }), - }); - if (!res.ok) { - throw new Error("SFU Config fetch failed with status code " + res.status); - } - return await res.json(); - } catch (e) { - throw new Error("SFU Config fetch failed with exception", { cause: e }); + const res = await fetch(livekitServiceURL + "/sfu/get", { + method: "POST", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify({ + // This is the actual livekit room alias. For the legacy jwt endpoint simply the room id was used. + room: matrixRoomId, + openid_token: openIDToken, + device_id: deviceId, + }), + }); + if (!res.ok) { + throw new Error("SFU Config fetch failed with status code " + res.status); + } + return await res.json(); +} + +class NotSupportedError extends Error { + public constructor(message: string) { + super(message); + this.name = "NotSupported"; } } @@ -216,19 +240,20 @@ export async function getLiveKitJWTWithDelayDelegation( }; } - try { - const res = await fetch(livekitServiceURL + "/get_token", { - method: "POST", - headers: { - "Content-Type": "application/json", - }, - body: JSON.stringify({ ...body, ...bodyDalayParts }), - }); - if (!res.ok) { - throw new Error("SFU Config fetch failed with status code " + res.status); + const res = await fetch(livekitServiceURL + "/get_token", { + method: "POST", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify({ ...body, ...bodyDalayParts }), + }); + if (!res.ok) { + const msg = "SFU Config fetch failed with status code " + res.status; + if (res.status === 404) { + throw new NotSupportedError(msg); + } else { + throw new Error(msg); } - return await res.json(); - } catch (e) { - throw new Error("SFU Config fetch failed with exception " + e); } + return await res.json(); } From a5a4bb2b8233cebb01cd17aa025ed1b2e97247d3 Mon Sep 17 00:00:00 2001 From: Timo K Date: Wed, 7 Jan 2026 17:38:29 +0100 Subject: [PATCH 157/748] add retries inside the `getLiveKitJWTWithDelayDelegation` and `getLiveKitJWT` functions. --- src/livekit/openIDSFU.ts | 90 +++++++++++++++++++++++----------------- 1 file changed, 52 insertions(+), 38 deletions(-) diff --git a/src/livekit/openIDSFU.ts b/src/livekit/openIDSFU.ts index 8c4434bd4..cf9ad5bce 100644 --- a/src/livekit/openIDSFU.ts +++ b/src/livekit/openIDSFU.ts @@ -6,7 +6,6 @@ Please see LICENSE in the repository root for full details. */ import { - HTTPError, retryNetworkOperation, type IOpenIDToken, type MatrixClient, @@ -116,17 +115,15 @@ export async function getSFUConfigWithOpenID( // since we are not sending the new matrix2.0 sticky events (no hashed identity in the event) if (forceOldJwtEndpoint === false) { try { - await retryNetworkOperation(4, async () => { - sfuConfig = await getLiveKitJWTWithDelayDelegation( - membership, - serviceUrl, - roomId, - openIdToken, - delayEndpointBaseUrl, - delayId, - ); - logger?.info(`Got JWT from call's active focus URL.`); - }); + sfuConfig = await getLiveKitJWTWithDelayDelegation( + membership, + serviceUrl, + roomId, + openIdToken, + delayEndpointBaseUrl, + delayId, + ); + logger?.info(`Got JWT from call's active focus URL.`); } catch (e) { if (e instanceof NotSupportedError) { logger?.warn( @@ -146,14 +143,13 @@ export async function getSFUConfigWithOpenID( // DEPRECATED // Either forceOldJwtEndpoint = true or getLiveKitJWTWithDelayDelegation throws -> reset sfuConfig = undefined if (sfuConfig === undefined) { - await retryNetworkOperation(4, async () => { - sfuConfig = await getLiveKitJWT( - membership.deviceId, - serviceUrl, - roomId, - openIdToken, - ); - }); + sfuConfig = await getLiveKitJWT( + membership.deviceId, + serviceUrl, + roomId, + openIdToken, + ); + logger?.info(`Got JWT from call's active focus URL.`); } @@ -175,25 +171,33 @@ export async function getSFUConfigWithOpenID( livekitIdentity: payload.sub, }; } - +const RETRIES = 4; async function getLiveKitJWT( deviceId: string, livekitServiceURL: string, matrixRoomId: string, openIDToken: IOpenIDToken, ): Promise<{ url: string; jwt: string }> { - const res = await fetch(livekitServiceURL + "/sfu/get", { - method: "POST", - headers: { - "Content-Type": "application/json", - }, - body: JSON.stringify({ - // This is the actual livekit room alias. For the legacy jwt endpoint simply the room id was used. - room: matrixRoomId, - openid_token: openIDToken, - device_id: deviceId, - }), + let res: Response | undefined; + await retryNetworkOperation(RETRIES, async () => { + res = await fetch(livekitServiceURL + "/sfu/get", { + method: "POST", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify({ + // This is the actual livekit room alias. For the legacy jwt endpoint simply the room id was used. + room: matrixRoomId, + openid_token: openIDToken, + device_id: deviceId, + }), + }); }); + if (!res) { + throw new Error( + `Network error while connecting to jwt service after ${RETRIES} retries`, + ); + } if (!res.ok) { throw new Error("SFU Config fetch failed with status code " + res.status); } @@ -240,13 +244,23 @@ export async function getLiveKitJWTWithDelayDelegation( }; } - const res = await fetch(livekitServiceURL + "/get_token", { - method: "POST", - headers: { - "Content-Type": "application/json", - }, - body: JSON.stringify({ ...body, ...bodyDalayParts }), + let res: Response | undefined; + + await retryNetworkOperation(RETRIES, async () => { + res = await fetch(livekitServiceURL + "/get_token", { + method: "POST", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify({ ...body, ...bodyDalayParts }), + }); }); + + if (!res) { + throw new Error( + `Network error while connecting to jwt service after ${RETRIES} retries`, + ); + } if (!res.ok) { const msg = "SFU Config fetch failed with status code " + res.status; if (res.status === 404) { From 385f63e83e5d0bec8184e62e06e1253d567f8c9a Mon Sep 17 00:00:00 2001 From: Timo K Date: Wed, 7 Jan 2026 17:46:39 +0100 Subject: [PATCH 158/748] fix tests --- src/livekit/openIDSFU.test.ts | 6 +++--- src/state/CallViewModel/remoteMembers/Connection.test.ts | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/livekit/openIDSFU.test.ts b/src/livekit/openIDSFU.test.ts index aed66d33e..5f286958d 100644 --- a/src/livekit/openIDSFU.test.ts +++ b/src/livekit/openIDSFU.test.ts @@ -74,7 +74,7 @@ describe("getSFUConfigWithOpenID", () => { "!example_room_id", ); } catch (ex) { - expect(((ex as Error).cause as Error).message).toEqual( + expect((ex as Error).message).toEqual( "SFU Config fetch failed with status code 500", ); void (await fetchMock.flush()); @@ -107,7 +107,7 @@ describe("getSFUConfigWithOpenID", () => { "mock_delay_id", ); } catch (ex) { - expect(((ex as Error).cause as Error).message).toEqual( + expect((ex as Error).message).toEqual( "SFU Config fetch failed with status code 500", ); void (await fetchMock.flush()); @@ -160,7 +160,7 @@ describe("getSFUConfigWithOpenID", () => { "mock_delay_id", ); } catch (ex) { - expect(((ex as Error).cause as Error).message).toEqual( + expect((ex as Error).message).toEqual( "SFU Config fetch failed with status code 500", ); void (await fetchMock.flush()); diff --git a/src/state/CallViewModel/remoteMembers/Connection.test.ts b/src/state/CallViewModel/remoteMembers/Connection.test.ts index 239a5c755..0130a5cea 100644 --- a/src/state/CallViewModel/remoteMembers/Connection.test.ts +++ b/src/state/CallViewModel/remoteMembers/Connection.test.ts @@ -259,7 +259,7 @@ describe("Start connection states", () => { capturedState.cause instanceof Error ) { expect(capturedState.cause.message).toContain( - "SFU Config fetch failed with exception", + "SFU Config fetch failed with status code 500", ); expect(connection.transport.livekit_alias).toEqual( livekitFocus.livekit_alias, From 1909aef1862c049482855483a172f15ba8ad0d74 Mon Sep 17 00:00:00 2001 From: Timo K Date: Thu, 8 Jan 2026 12:27:17 +0100 Subject: [PATCH 159/748] temp --- src/livekit/openIDSFU.ts | 5 +++-- src/state/CallViewModel/localMember/LocalMember.ts | 7 ++++++- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/src/livekit/openIDSFU.ts b/src/livekit/openIDSFU.ts index cf9ad5bce..df1d02a5f 100644 --- a/src/livekit/openIDSFU.ts +++ b/src/livekit/openIDSFU.ts @@ -133,7 +133,8 @@ export async function getSFUConfigWithOpenID( sfuConfig = undefined; } else { logger?.warn( - `Failed fetching jwt with matrix 2.0 endpoint other issues -> not going to try with legacy endpoint`, + `Failed fetching jwt with matrix 2.0 endpoint other issues ->`, + `(not going to try with legacy endpoint: forceOldJwtEndpoint is set to false, we did not get a not supported error from the sfu)`, e, ); } @@ -234,7 +235,7 @@ export async function getLiveKitJWTWithDelayDelegation( let bodyDalayParts = {}; // Also check for empty string - if (delayId && delayEndpointBaseUrl) { + if (delayId && delayEndpointBaseUrl && false) { const delayTimeoutMs = Config.get().matrix_rtc_session?.delayed_leave_event_delay_ms ?? 1000; bodyDalayParts = { diff --git a/src/state/CallViewModel/localMember/LocalMember.ts b/src/state/CallViewModel/localMember/LocalMember.ts index 5b72266f3..eb5061327 100644 --- a/src/state/CallViewModel/localMember/LocalMember.ts +++ b/src/state/CallViewModel/localMember/LocalMember.ts @@ -552,7 +552,12 @@ export const createLocalMembership$ = ({ ); const participant$ = scope.behavior( - localConnection$.pipe(map((c) => c?.livekitRoom?.localParticipant ?? null)), + localConnection$.pipe( + map((c) => c?.livekitRoom?.localParticipant ?? null), + tap((p) => { + logger.debug("participant$ updated:", p?.identity); + }), + ), ); // Pause upstream of all local media tracks when we're disconnected from From 0439fdefefd0e5c880b0f8b4555b3a19f1f7112b Mon Sep 17 00:00:00 2001 From: Will Hunt <2072976+Half-Shot@users.noreply.github.com> Date: Thu, 8 Jan 2026 11:51:28 +0000 Subject: [PATCH 160/748] Remove duplicate IntentAndPlatformDerivedConfiguration interface (#3658) --- src/UrlParams.ts | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/UrlParams.ts b/src/UrlParams.ts index 048e802b0..9b262a434 100644 --- a/src/UrlParams.ts +++ b/src/UrlParams.ts @@ -246,10 +246,7 @@ export interface UrlConfiguration { callIntent?: RTCCallIntent; } -interface IntentAndPlatformDerivedConfiguration { - defaultAudioEnabled?: boolean; - defaultVideoEnabled?: boolean; -} + interface IntentAndPlatformDerivedConfiguration { defaultAudioEnabled?: boolean; defaultVideoEnabled?: boolean; From d4b06b0f9c505d33aaa560a2dad2c71deaa2b474 Mon Sep 17 00:00:00 2001 From: Timo K Date: Thu, 8 Jan 2026 14:27:47 +0100 Subject: [PATCH 161/748] fix connection recreation which breaks EC lk connection --- .../remoteMembers/ConnectionManager.ts | 54 +++++++++---------- 1 file changed, 25 insertions(+), 29 deletions(-) diff --git a/src/state/CallViewModel/remoteMembers/ConnectionManager.ts b/src/state/CallViewModel/remoteMembers/ConnectionManager.ts index e5a542dfa..5c50f0cdd 100644 --- a/src/state/CallViewModel/remoteMembers/ConnectionManager.ts +++ b/src/state/CallViewModel/remoteMembers/ConnectionManager.ts @@ -110,20 +110,6 @@ export function createConnectionManager$({ const logger = parentLogger.getChild("[ConnectionManager]"); // TODO logger: only construct one logger from the client and make it compatible via a EC specific sing - const allInputTransports$ = combineLatest([ - localTransport$, - remoteTransports$, - ]).pipe( - map(([localTransport, transports]) => { - const localTransportAsArray = localTransport ? [localTransport] : []; - return transports.mapInner((transports) => [ - ...localTransportAsArray, - ...transports, - ]); - }), - map((transports) => transports.mapInner(removeDuplicateTransports)), - ); - /** * All transports currently managed by the ConnectionManager. * @@ -134,30 +120,38 @@ export function createConnectionManager$({ */ const transportsWithJwtTag$ = scope.behavior( combineLatest([ - allInputTransports$, + remoteTransports$, localTransport$, forceOldJwtEndpointForLocalTransport$, ]).pipe( + // combine local and remote transports into one transport array + // and set the forceOldJwtEndpoint property on the local transport map( ([ - transports, + remoteTransports, localTransport, forceOldJwtEndpointForLocalTransport, ]) => { - // modify only the local transport with forceOldJwtEndpointForLocalTransport - const index = transports.value.findIndex((t) => - areLivekitTransportsEqual(localTransport, t), - ); - if (index !== -1) { - transports.value[index].forceOldJwtEndpoint = - forceOldJwtEndpointForLocalTransport; + let localTransportAsArray: (LivekitTransport & { + forceOldJwtEndpoint: boolean; + })[] = []; + if (localTransport) { + localTransportAsArray = [ + { + ...localTransport, + forceOldJwtEndpoint: forceOldJwtEndpointForLocalTransport, + }, + ]; } - logger.trace( - `Managing transports: ${transports.value.map((t) => t.livekit_service_url).join(", ")}`, + return new Epoch( + removeDuplicateTransports([ + ...localTransportAsArray, + ...remoteTransports.value, + ]) as (LivekitTransport & { + forceOldJwtEndpoint?: boolean; + })[], + remoteTransports.epoch, ); - return transports as Epoch< - (LivekitTransport & { forceOldJwtEndpoint?: boolean })[] - >; }, ), ), @@ -181,7 +175,9 @@ export function createConnectionManager$({ }; }, (scope, _data$, serviceUrl, alias, forceOldJwtEndpoint) => { - logger.debug(`Creating connection to ${serviceUrl} (${alias})`); + logger.debug( + `Creating connection to ${serviceUrl} (${alias}, forceOldJwtEndpoint: ${forceOldJwtEndpoint})`, + ); const connection = connectionFactory.createConnection( { type: "livekit", From 8fe49d681adeb2afa4ef24511a1523ee1f0b0be7 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 8 Jan 2026 19:49:47 +0000 Subject: [PATCH 162/748] Update Compound --- yarn.lock | 168 ++++++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 150 insertions(+), 18 deletions(-) diff --git a/yarn.lock b/yarn.lock index b350926d3..4e7c6e379 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3838,6 +3838,25 @@ __metadata: languageName: node linkType: hard +"@radix-ui/react-arrow@npm:1.1.7": + version: 1.1.7 + resolution: "@radix-ui/react-arrow@npm:1.1.7" + dependencies: + "@radix-ui/react-primitive": "npm:2.1.3" + peerDependencies: + "@types/react": "*" + "@types/react-dom": "*" + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + "@types/react": + optional: true + "@types/react-dom": + optional: true + checksum: 10c0/c3b46766238b3ee2a394d8806a5141432361bf1425110c9f0dcf480bda4ebd304453a53f294b5399c6ee3ccfcae6fd544921fd01ddc379cf5942acdd7168664b + languageName: node + linkType: hard + "@radix-ui/react-collection@npm:1.1.1": version: 1.1.1 resolution: "@radix-ui/react-collection@npm:1.1.1" @@ -3908,16 +3927,16 @@ __metadata: languageName: node linkType: hard -"@radix-ui/react-context-menu@npm:^2.2.1": - version: 2.2.4 - resolution: "@radix-ui/react-context-menu@npm:2.2.4" +"@radix-ui/react-context-menu@npm:^2.2.16": + version: 2.2.16 + resolution: "@radix-ui/react-context-menu@npm:2.2.16" dependencies: - "@radix-ui/primitive": "npm:1.1.1" - "@radix-ui/react-context": "npm:1.1.1" - "@radix-ui/react-menu": "npm:2.1.4" - "@radix-ui/react-primitive": "npm:2.0.1" - "@radix-ui/react-use-callback-ref": "npm:1.1.0" - "@radix-ui/react-use-controllable-state": "npm:1.1.0" + "@radix-ui/primitive": "npm:1.1.3" + "@radix-ui/react-context": "npm:1.1.2" + "@radix-ui/react-menu": "npm:2.1.16" + "@radix-ui/react-primitive": "npm:2.1.3" + "@radix-ui/react-use-callback-ref": "npm:1.1.1" + "@radix-ui/react-use-controllable-state": "npm:1.2.2" peerDependencies: "@types/react": "*" "@types/react-dom": "*" @@ -3928,7 +3947,7 @@ __metadata: optional: true "@types/react-dom": optional: true - checksum: 10c0/f500590b1300dfcd8a2d0fb51fcada0e7d9a1a354ac239328ffdd32f3736bde888ebf0cd64d9039f7d894e3d13eb549a872359669de8c7ff128ee1afb9cf21a8 + checksum: 10c0/950f7559e65474a19145238cf44d744cb1e49be2221ff18436ba49b496b05ccf93bd3906aaa2c7ab76bc77daf694911a78442801e0053f57d2e57ebbfd281c49 languageName: node linkType: hard @@ -4228,6 +4247,42 @@ __metadata: languageName: node linkType: hard +"@radix-ui/react-menu@npm:2.1.16": + version: 2.1.16 + resolution: "@radix-ui/react-menu@npm:2.1.16" + dependencies: + "@radix-ui/primitive": "npm:1.1.3" + "@radix-ui/react-collection": "npm:1.1.7" + "@radix-ui/react-compose-refs": "npm:1.1.2" + "@radix-ui/react-context": "npm:1.1.2" + "@radix-ui/react-direction": "npm:1.1.1" + "@radix-ui/react-dismissable-layer": "npm:1.1.11" + "@radix-ui/react-focus-guards": "npm:1.1.3" + "@radix-ui/react-focus-scope": "npm:1.1.7" + "@radix-ui/react-id": "npm:1.1.1" + "@radix-ui/react-popper": "npm:1.2.8" + "@radix-ui/react-portal": "npm:1.1.9" + "@radix-ui/react-presence": "npm:1.1.5" + "@radix-ui/react-primitive": "npm:2.1.3" + "@radix-ui/react-roving-focus": "npm:1.1.11" + "@radix-ui/react-slot": "npm:1.2.3" + "@radix-ui/react-use-callback-ref": "npm:1.1.1" + aria-hidden: "npm:^1.2.4" + react-remove-scroll: "npm:^2.6.3" + peerDependencies: + "@types/react": "*" + "@types/react-dom": "*" + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + "@types/react": + optional: true + "@types/react-dom": + optional: true + checksum: 10c0/27516b2b987fa9181c4da8645000af8f60691866a349d7a46b9505fa7d2e9d92b9e364db4f7305d08e9e57d0e1afc8df8354f8ee3c12aa05c0100c16b0e76c27 + languageName: node + linkType: hard + "@radix-ui/react-menu@npm:2.1.4": version: 2.1.4 resolution: "@radix-ui/react-menu@npm:2.1.4" @@ -4292,6 +4347,34 @@ __metadata: languageName: node linkType: hard +"@radix-ui/react-popper@npm:1.2.8": + version: 1.2.8 + resolution: "@radix-ui/react-popper@npm:1.2.8" + dependencies: + "@floating-ui/react-dom": "npm:^2.0.0" + "@radix-ui/react-arrow": "npm:1.1.7" + "@radix-ui/react-compose-refs": "npm:1.1.2" + "@radix-ui/react-context": "npm:1.1.2" + "@radix-ui/react-primitive": "npm:2.1.3" + "@radix-ui/react-use-callback-ref": "npm:1.1.1" + "@radix-ui/react-use-layout-effect": "npm:1.1.1" + "@radix-ui/react-use-rect": "npm:1.1.1" + "@radix-ui/react-use-size": "npm:1.1.1" + "@radix-ui/rect": "npm:1.1.1" + peerDependencies: + "@types/react": "*" + "@types/react-dom": "*" + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + "@types/react": + optional: true + "@types/react-dom": + optional: true + checksum: 10c0/48e3f13eac3b8c13aca8ded37d74db17e1bb294da8d69f142ab6b8719a06c3f90051668bed64520bf9f3abdd77b382ce7ce209d056bb56137cecc949b69b421c + languageName: node + linkType: hard + "@radix-ui/react-portal@npm:1.1.3": version: 1.1.3 resolution: "@radix-ui/react-portal@npm:1.1.3" @@ -4476,6 +4559,33 @@ __metadata: languageName: node linkType: hard +"@radix-ui/react-roving-focus@npm:1.1.11": + version: 1.1.11 + resolution: "@radix-ui/react-roving-focus@npm:1.1.11" + dependencies: + "@radix-ui/primitive": "npm:1.1.3" + "@radix-ui/react-collection": "npm:1.1.7" + "@radix-ui/react-compose-refs": "npm:1.1.2" + "@radix-ui/react-context": "npm:1.1.2" + "@radix-ui/react-direction": "npm:1.1.1" + "@radix-ui/react-id": "npm:1.1.1" + "@radix-ui/react-primitive": "npm:2.1.3" + "@radix-ui/react-use-callback-ref": "npm:1.1.1" + "@radix-ui/react-use-controllable-state": "npm:1.2.2" + peerDependencies: + "@types/react": "*" + "@types/react-dom": "*" + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + "@types/react": + optional: true + "@types/react-dom": + optional: true + checksum: 10c0/2cd43339c36e89a3bf1db8aab34b939113dfbde56bf3a33df2d74757c78c9489b847b1962f1e2441c67e41817d120cb6177943e0f655f47bc1ff8e44fd55b1a2 + languageName: node + linkType: hard + "@radix-ui/react-separator@npm:^1.1.0": version: 1.1.1 resolution: "@radix-ui/react-separator@npm:1.1.1" @@ -4725,6 +4835,21 @@ __metadata: languageName: node linkType: hard +"@radix-ui/react-use-rect@npm:1.1.1": + version: 1.1.1 + resolution: "@radix-ui/react-use-rect@npm:1.1.1" + dependencies: + "@radix-ui/rect": "npm:1.1.1" + peerDependencies: + "@types/react": "*" + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + "@types/react": + optional: true + checksum: 10c0/271711404c05c589c8dbdaa748749e7daf44bcc6bffc9ecd910821c3ebca0ee245616cf5b39653ce690f53f875c3836fd3f36f51ab1c628273b6db599eee4864 + languageName: node + linkType: hard + "@radix-ui/react-use-size@npm:1.1.0": version: 1.1.0 resolution: "@radix-ui/react-use-size@npm:1.1.0" @@ -4781,6 +4906,13 @@ __metadata: languageName: node linkType: hard +"@radix-ui/rect@npm:1.1.1": + version: 1.1.1 + resolution: "@radix-ui/rect@npm:1.1.1" + checksum: 10c0/0dac4f0f15691199abe6a0e067821ddd9d0349c0c05f39834e4eafc8403caf724106884035ae91bbc826e10367e6a5672e7bec4d4243860fa7649de246b1f60b + languageName: node + linkType: hard + "@react-spring/animated@npm:~10.0.3": version: 10.0.3 resolution: "@react-spring/animated@npm:10.0.3" @@ -6026,8 +6158,8 @@ __metadata: linkType: hard "@vector-im/compound-design-tokens@npm:^6.0.0": - version: 6.0.0 - resolution: "@vector-im/compound-design-tokens@npm:6.0.0" + version: 6.6.0 + resolution: "@vector-im/compound-design-tokens@npm:6.6.0" peerDependencies: "@types/react": "*" react: ^17 || ^18 || ^19.0.0 @@ -6036,16 +6168,16 @@ __metadata: optional: true react: optional: true - checksum: 10c0/1af5b2b73a3a55149047cd0716f071b83a4df8a210c9ad432db4cc2f9b9e72e958f93ff850dbaddb88e37a01870c5eb810b03dfb0acc89cc147eaaf6cf1dada1 + checksum: 10c0/93b152dd1de96371f9b6b1f7dbcc381d7ab598031dbc900f52d610f015766c0d4426ae6e47d417e723bfb62d1a53099155b4d788848b78232916ba132c03c2fe languageName: node linkType: hard "@vector-im/compound-web@npm:^8.0.0": - version: 8.2.0 - resolution: "@vector-im/compound-web@npm:8.2.0" + version: 8.3.4 + resolution: "@vector-im/compound-web@npm:8.3.4" dependencies: "@floating-ui/react": "npm:^0.27.0" - "@radix-ui/react-context-menu": "npm:^2.2.1" + "@radix-ui/react-context-menu": "npm:^2.2.16" "@radix-ui/react-dropdown-menu": "npm:^2.1.1" "@radix-ui/react-form": "npm:^0.1.0" "@radix-ui/react-progress": "npm:^1.1.0" @@ -6057,12 +6189,12 @@ __metadata: "@fontsource/inconsolata": ^5 "@fontsource/inter": ^5 "@types/react": "*" - "@vector-im/compound-design-tokens": ">=1.6.1 <6.0.0" + "@vector-im/compound-design-tokens": ">=1.6.1 <7.0.0" react: ^18 || ^19.0.0 peerDependenciesMeta: "@types/react": optional: true - checksum: 10c0/4ac4074dcf9611bdff7de4bf66763397c926d6312f31758bcabe3e7bf704cb76bc2ce1023fe5f2cf0d05e97c9c540fef8b63edea7a521a2f7b4b7fbcb883fb17 + checksum: 10c0/44764fa64b5fce2e7181e25b50ee970eda4d921cf650b92bd5e88df0eb60872f3086b8702d18f55c3e39b3751ac19f10bafda8c4306df65c3605bd44b297d95c languageName: node linkType: hard From f5f8bb549a6944ab14d36811f7045af65bdd258b Mon Sep 17 00:00:00 2001 From: Valere Date: Thu, 8 Jan 2026 13:16:58 +0100 Subject: [PATCH 163/748] delete outdated default mute state config --- src/config/ConfigOptions.ts | 8 -------- src/state/MuteStates.ts | 5 ++--- 2 files changed, 2 insertions(+), 11 deletions(-) diff --git a/src/config/ConfigOptions.ts b/src/config/ConfigOptions.ts index c587fa502..44cdf1287 100644 --- a/src/config/ConfigOptions.ts +++ b/src/config/ConfigOptions.ts @@ -163,10 +163,6 @@ export interface ResolvedConfigOptions extends ConfigOptions { }; }; ssla: string; - media_devices: { - enable_audio: boolean; - enable_video: boolean; - }; app_prompt: boolean; } @@ -181,9 +177,5 @@ export const DEFAULT_CONFIG: ResolvedConfigOptions = { feature_use_device_session_member_events: true, }, ssla: "https://static.element.io/legal/element-software-and-services-license-agreement-uk-1.pdf", - media_devices: { - enable_audio: true, - enable_video: true, - }, app_prompt: true, }; diff --git a/src/state/MuteStates.ts b/src/state/MuteStates.ts index 632e04262..7f048f27e 100644 --- a/src/state/MuteStates.ts +++ b/src/state/MuteStates.ts @@ -24,7 +24,6 @@ import { import { type MediaDevices, type MediaDevice } from "../state/MediaDevices"; import { ElementWidgetActions, widget } from "../widget"; -import { Config } from "../config/Config"; import { getUrlParams } from "../UrlParams"; import { type ObservableScope } from "./ObservableScope"; import { type Behavior, constant } from "./Behavior"; @@ -192,14 +191,14 @@ export class MuteStates { this.scope, this.mediaDevices.audioInput, this.joined$, - Config.get().media_devices.enable_audio, + true, constant(false), ); public readonly video = new MuteState( this.scope, this.mediaDevices.videoInput, this.joined$, - Config.get().media_devices.enable_video, + true, this.isEarpiece$, ); From a9153f2781dd31bebab2e66cddd6cf6f3f5c99af Mon Sep 17 00:00:00 2001 From: Valere Date: Fri, 9 Jan 2026 12:00:45 +0100 Subject: [PATCH 164/748] fix: Regression on default mutestate for voicecall + end-2-end tests --- playwright/fixtures/widget-user.ts | 95 +++++++----- playwright/widget/voice-call-dm.spec.ts | 183 ++++++++++++++++++++++++ sdk/main.ts | 2 +- src/UrlParams.test.ts | 4 - src/UrlParams.ts | 34 +---- src/button/Button.tsx | 3 + src/room/RoomPage.tsx | 15 +- src/state/MuteStates.test.ts | 7 +- src/state/MuteStates.ts | 140 +++++++++--------- src/state/initialMuteState.test.ts | 95 ++++++++++++ src/state/initialMuteState.ts | 46 ++++++ src/utils/test.ts | 2 +- 12 files changed, 467 insertions(+), 159 deletions(-) create mode 100644 playwright/widget/voice-call-dm.spec.ts create mode 100644 src/state/initialMuteState.test.ts create mode 100644 src/state/initialMuteState.ts diff --git a/playwright/fixtures/widget-user.ts b/playwright/fixtures/widget-user.ts index f1f738b73..0611c97e4 100644 --- a/playwright/fixtures/widget-user.ts +++ b/playwright/fixtures/widget-user.ts @@ -17,6 +17,7 @@ import type { MatrixClient } from "matrix-js-sdk"; export type UserBaseFixture = { mxId: string; + displayName: string; page: Page; clientHandle: JSHandle; }; @@ -28,6 +29,7 @@ export type BaseWidgetSetup = { export interface MyFixtures { asWidget: BaseWidgetSetup; + callType: "room" | "dm"; } const PASSWORD = "foobarbaz1!"; @@ -145,25 +147,27 @@ async function registerUser( } export const widgetTest = test.extend({ - asWidget: async ({ browser, context }, pUse) => { + // allow per-test override: `widgetTest.use({ callType: "dm" })` + callType: ["room", { option: true }], + asWidget: async ({ browser, context, callType }, pUse) => { await context.route(`http://localhost:8081/config.json*`, async (route) => { await route.fulfill({ json: CONFIG_JSON }); }); - const userA = `brooks_${Date.now()}`; - const userB = `whistler_${Date.now()}`; + const brooksDisplayName = `brooks_${Date.now()}`; + const whistlerDisplayName = `whistler_${Date.now()}`; // Register users const { page: ewPage1, clientHandle: brooksClientHandle, mxId: brooksMxId, - } = await registerUser(browser, userA); + } = await registerUser(browser, brooksDisplayName); const { page: ewPage2, clientHandle: whistlerClientHandle, mxId: whistlerMxId, - } = await registerUser(browser, userB); + } = await registerUser(browser, whistlerDisplayName); // Invite the second user await ewPage1 @@ -171,37 +175,60 @@ export const widgetTest = test.extend({ .getByRole("button", { name: "New conversation" }) .click(); - await ewPage1.getByRole("menuitem", { name: "New Room" }).click(); - await ewPage1.getByRole("textbox", { name: "Name" }).fill("Welcome Room"); - await ewPage1.getByRole("button", { name: "Create room" }).click(); - await expect(ewPage1.getByText("You created this room.")).toBeVisible(); - await expect(ewPage1.getByText("Encryption enabled")).toBeVisible(); + if (callType === "room") { - await ewPage1 - .getByRole("button", { name: "Invite to this room", exact: true }) - .click(); - await expect( - ewPage1.getByRole("heading", { name: "Invite to Welcome Room" }), - ).toBeVisible(); + await ewPage1.getByRole("menuitem", { name: "New Room" }).click(); + await ewPage1.getByRole("textbox", { name: "Name" }).fill("Welcome Room"); + await ewPage1.getByRole("button", { name: "Create room" }).click(); + await expect(ewPage1.getByText("You created this room.")).toBeVisible(); + await expect(ewPage1.getByText("Encryption enabled")).toBeVisible(); - // To get the invite textbox we need to specifically select within the - // dialog, since there is another textbox in the background (the message - // composer). In theory the composer shouldn't be visible to Playwright at - // all because the invite dialog has trapped focus, but the focus trap - // doesn't quite work right on Firefox. - await ewPage1.getByRole("dialog").getByRole("textbox").fill(whistlerMxId); - await ewPage1.getByRole("dialog").getByRole("textbox").click(); - await ewPage1.getByRole("button", { name: "Invite" }).click(); + await ewPage1 + .getByRole("button", { name: "Invite to this room", exact: true }) + .click(); + await expect( + ewPage1.getByRole("heading", { name: "Invite to Welcome Room" }), + ).toBeVisible(); - // Accept the invite - await expect( - ewPage2.getByRole("option", { name: "Welcome Room" }), - ).toBeVisible(); - await ewPage2.getByRole("option", { name: "Welcome Room" }).click(); - await ewPage2.getByRole("button", { name: "Accept" }).click(); - await expect( - ewPage2.getByRole("main").getByRole("heading", { name: "Welcome Room" }), - ).toBeVisible(); + // To get the invite textbox we need to specifically select within the + // dialog, since there is another textbox in the background (the message + // composer). In theory the composer shouldn't be visible to Playwright at + // all because the invite dialog has trapped focus, but the focus trap + // doesn't quite work right on Firefox. + await ewPage1.getByRole("dialog").getByRole("textbox").fill(whistlerMxId); + await ewPage1.getByRole("dialog").getByRole("textbox").click(); + await ewPage1.getByRole("button", { name: "Invite" }).click(); + + // Accept the invite + await expect( + ewPage2.getByRole("option", { name: "Welcome Room" }), + ).toBeVisible(); + await ewPage2.getByRole("option", { name: "Welcome Room" }).click(); + await ewPage2.getByRole("button", { name: "Accept" }).click(); + await expect( + ewPage2.getByRole("main").getByRole("heading", { name: "Welcome Room" }), + ).toBeVisible(); + } else if (callType === "dm") { + await ewPage1.getByRole("menuitem", { name: "Start chat" }).click(); + await ewPage1.getByRole('textbox', { name: 'Search' }).click(); + await ewPage1.getByRole('textbox', { name: 'Search' }).fill(whistlerMxId); + await ewPage1.getByRole("button", { name: "Go" }).click(); + + // Wait and send the first message to create the DM + await expect(ewPage1.getByText(/Send your first message to invite/)).toBeVisible(); + + await ewPage1.locator('.mx_BasicMessageComposer_input > div').click(); + await ewPage1.getByRole('textbox', { name: 'Send a message…' }).fill('Hello!'); + await ewPage1.getByRole("button", { name: "Send message" }).click(); + + await expect(ewPage1.getByText('This is the beginning of your')).toBeVisible(); + + + // Accept the DM invite from brooks + // This how playwright record selects the DM invite in the room list + await ewPage2.getByRole('option', { name: 'Open room' }).click(); + await ewPage2.getByRole('button', { name: 'Start chatting' }).click(); + } // Renamed use to pUse, as a workaround for eslint error that was thinking this use was a react use. await pUse({ @@ -209,11 +236,13 @@ export const widgetTest = test.extend({ mxId: brooksMxId, page: ewPage1, clientHandle: brooksClientHandle, + displayName: brooksDisplayName }, whistler: { mxId: whistlerMxId, page: ewPage2, clientHandle: whistlerClientHandle, + displayName: whistlerDisplayName }, }); }, diff --git a/playwright/widget/voice-call-dm.spec.ts b/playwright/widget/voice-call-dm.spec.ts new file mode 100644 index 000000000..39a1b8cb6 --- /dev/null +++ b/playwright/widget/voice-call-dm.spec.ts @@ -0,0 +1,183 @@ +/* +Copyright 2026 Element Creations Ltd. + +SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial +Please see LICENSE in the repository root for full details. +*/ + +import { expect, test } from "@playwright/test"; + +import { widgetTest } from "../fixtures/widget-user.ts"; + +widgetTest.use({callType: "dm"}); + +widgetTest("Start a new voice call in DM as widget", async ({ asWidget }) => { + test.slow(); // Triples the timeout + + const { brooks, whistler } = asWidget; + + await expect( + brooks.page.getByRole("button", { name: "Voice call" }), + ).toBeVisible(); + await brooks.page.getByRole("button", { name: "Voice call" }).click(); + + await expect( + brooks.page.getByRole("menuitem", { name: "Element Call" }), + ).toBeVisible(); + + await brooks.page.getByRole("menuitem", { name: "Element Call" }).click(); + + await expect( + brooks.page + .locator('iframe[title="Element Call"]') + ).toBeVisible(); + + const brooksFrame = brooks.page + .locator('iframe[title="Element Call"]') + .contentFrame(); + + // We should show a ringing overlay, let's check for that + await expect(brooksFrame.getByText(`Waiting for ${whistler.displayName} to join…`)).toBeVisible(); + + + await expect(whistler.page.getByText('Incoming voice call')).toBeVisible(); + await whistler.page.getByRole('button', { name: 'Accept' }).click(); + + await expect( + whistler.page + .locator('iframe[title="Element Call"]') + ).toBeVisible(); + + const whistlerFrame = whistler.page + .locator('iframe[title="Element Call"]') + .contentFrame(); + + // ASSERT the button states for whistler (the callee) + { + // The only way to know if it is muted or not is to look at the data-kind attribute.. + const videoButton = whistlerFrame.getByTestId('incall_videomute'); + // video should be off by default in a voice call + await expect(videoButton).toHaveAttribute("aria-label", /^Start video$/); + + + const audioButton = whistlerFrame.getByTestId('incall_mute'); + // audio should be on for the voice call + await expect(audioButton).toHaveAttribute("aria-label", /^Mute microphone$/); + } + + // ASSERT the button states for brools (the caller) + { + // The only way to know if it is muted or not is to look at the data-kind attribute.. + const videoButton = brooksFrame.getByTestId('incall_videomute'); + // video should be off by default in a voice call + await expect(videoButton).toHaveAttribute("aria-label", /^Start video$/); + + + const audioButton = brooksFrame.getByTestId('incall_mute'); + // audio should be on for the voice call + await expect(audioButton).toHaveAttribute("aria-label", /^Mute microphone$/); + } + + // In order to confirm that the call is disconnected we will check that the message composer is shown again. + // So first we need to confirm that it is hidden when in the call. + await expect(whistler.page.locator(".mx_BasicMessageComposer")).not.toBeVisible(); + await expect(brooks.page.locator(".mx_BasicMessageComposer")).not.toBeVisible(); + + // ASSERT hanging up on one side ends the call for both + { + const hangupButton = brooksFrame.getByTestId('incall_leave'); + await hangupButton.click(); + } + + // The widget should be closed on both sides and the timeline should be back on screen + await expect(whistler.page.locator(".mx_BasicMessageComposer")).toBeVisible(); + await expect(brooks.page.locator(".mx_BasicMessageComposer")).toBeVisible(); + +}); + + + +widgetTest("Start a new video call in DM as widget", async ({ asWidget, browserName }) => { + test.slow(); // Triples the timeout + + const { brooks, whistler } = asWidget; + + await expect( + brooks.page.getByRole("button", { name: "Video call" }), + ).toBeVisible(); + await brooks.page.getByRole("button", { name: "Video call" }).click(); + + await expect( + brooks.page.getByRole("menuitem", { name: "Element Call" }), + ).toBeVisible(); + + await brooks.page.getByRole("menuitem", { name: "Element Call" }).click(); + + await expect( + brooks.page + .locator('iframe[title="Element Call"]') + ).toBeVisible(); + + const brooksFrame = brooks.page + .locator('iframe[title="Element Call"]') + .contentFrame(); + + // We should show a ringing overlay, let's check for that + await expect(brooksFrame.getByText(`Waiting for ${whistler.displayName} to join…`)).toBeVisible(); + + + await expect(whistler.page.getByText('Incoming video call')).toBeVisible(); + await whistler.page.getByRole('button', { name: 'Accept' }).click(); + + await expect( + whistler.page + .locator('iframe[title="Element Call"]') + ).toBeVisible(); + + const whistlerFrame = whistler.page + .locator('iframe[title="Element Call"]') + .contentFrame(); + + // ASSERT the button states for whistler (the callee) + { + // The only way to know if it is muted or not is to look at the data-kind attribute.. + const videoButton = whistlerFrame.getByTestId('incall_videomute'); + // video should be on by default in a voice call + await expect(videoButton).toHaveAttribute("aria-label", /^Stop video$/); + + + const audioButton = whistlerFrame.getByTestId('incall_mute'); + // audio should be on for the voice call + await expect(audioButton).toHaveAttribute("aria-label", /^Mute microphone$/); + } + + // ASSERT the button states for brools (the caller) + { + // The only way to know if it is muted or not is to look at the data-kind attribute.. + const videoButton = brooksFrame.getByTestId('incall_videomute'); + // video should be on by default in a voice call + await expect(videoButton).toHaveAttribute("aria-label", /^Stop video$/); + + + const audioButton = brooksFrame.getByTestId('incall_mute'); + // audio should be on for the voice call + await expect(audioButton).toHaveAttribute("aria-label", /^Mute microphone$/); + } + + // In order to confirm that the call is disconnected we will check that the message composer is shown again. + // So first we need to confirm that it is hidden when in the call. + await expect(whistler.page.locator(".mx_BasicMessageComposer")).not.toBeVisible(); + await expect(brooks.page.locator(".mx_BasicMessageComposer")).not.toBeVisible(); + + // ASSERT hanging up on one side ends the call for both + { + const hangupButton = brooksFrame.getByTestId('incall_leave'); + await hangupButton.click(); + } + + // The widget should be closed on both sides and the timeline should be back on screen + await expect(whistler.page.locator(".mx_BasicMessageComposer")).toBeVisible(); + await expect(brooks.page.locator(".mx_BasicMessageComposer")).toBeVisible(); + +}); + diff --git a/sdk/main.ts b/sdk/main.ts index 376674a41..add71dbe8 100644 --- a/sdk/main.ts +++ b/sdk/main.ts @@ -99,7 +99,7 @@ export async function createMatrixRTCSdk( if (room === null) throw Error("could not get room from client"); const mediaDevices = new MediaDevices(scope); - const muteStates = new MuteStates(scope, mediaDevices, constant(true)); + const muteStates = new MuteStates(scope, mediaDevices, { audioEnabled: true, videoEnabled: true }); const slot = { application, id }; const rtcSession = new MatrixRTCSession( client, diff --git a/src/UrlParams.test.ts b/src/UrlParams.test.ts index faba394f3..bff772c27 100644 --- a/src/UrlParams.test.ts +++ b/src/UrlParams.test.ts @@ -256,8 +256,6 @@ describe("UrlParams", () => { skipLobby: false, returnToLobby: false, sendNotificationType: "notification", - defaultAudioEnabled: true, - defaultVideoEnabled: true, }); it("use no-intent-defaults with unknown intent", () => { expect(computeUrlParams()).toMatchObject(noIntentDefaults); @@ -395,8 +393,6 @@ describe("UrlParams", () => { expect.any(Object), "configuration:", expect.any(Object), - "intentAndPlatformDerivedConfiguration:", - {}, ); }); }); diff --git a/src/UrlParams.ts b/src/UrlParams.ts index 9b262a434..edac5c078 100644 --- a/src/UrlParams.ts +++ b/src/UrlParams.ts @@ -247,11 +247,6 @@ export interface UrlConfiguration { callIntent?: RTCCallIntent; } -interface IntentAndPlatformDerivedConfiguration { - defaultAudioEnabled?: boolean; - defaultVideoEnabled?: boolean; -} - // If you need to add a new flag to this interface, prefer a name that describes // a specific behavior (such as 'confineToRoom'), rather than one that describes // the situations that call for this behavior ('isEmbedded'). This makes it @@ -260,8 +255,7 @@ interface IntentAndPlatformDerivedConfiguration { export interface UrlParams extends UrlProperties, - UrlConfiguration, - IntentAndPlatformDerivedConfiguration {} + UrlConfiguration {} // This is here as a stopgap, but what would be far nicer is a function that // takes a UrlParams and returns a query string. That would enable us to @@ -461,29 +455,6 @@ export const computeUrlParams = (search = "", hash = ""): UrlParams => { }; } - const intentAndPlatformDerivedConfiguration: IntentAndPlatformDerivedConfiguration = - {}; - // Desktop also includes web. Its anything that is not mobile. - const desktopMobile = platform === "desktop" ? "desktop" : "mobile"; - switch (desktopMobile) { - case "desktop": - case "mobile": - switch (intent) { - case UserIntent.StartNewCall: - case UserIntent.JoinExistingCall: - case UserIntent.StartNewCallDM: - case UserIntent.JoinExistingCallDM: - intentAndPlatformDerivedConfiguration.defaultAudioEnabled = true; - intentAndPlatformDerivedConfiguration.defaultVideoEnabled = true; - break; - case UserIntent.StartNewCallDMVoice: - case UserIntent.JoinExistingCallDMVoice: - intentAndPlatformDerivedConfiguration.defaultAudioEnabled = true; - intentAndPlatformDerivedConfiguration.defaultVideoEnabled = false; - break; - } - } - const properties: UrlProperties = { widgetId, parentUrl, @@ -548,15 +519,12 @@ export const computeUrlParams = (search = "", hash = ""): UrlParams => { properties, "configuration:", configuration, - "intentAndPlatformDerivedConfiguration:", - intentAndPlatformDerivedConfiguration, ); return { ...properties, ...intentPreset, ...pickBy(configuration, (v?: unknown) => v !== undefined), - ...intentAndPlatformDerivedConfiguration, }; }; diff --git a/src/button/Button.tsx b/src/button/Button.tsx index c11c92dde..9cd579d19 100644 --- a/src/button/Button.tsx +++ b/src/button/Button.tsx @@ -35,6 +35,7 @@ export const MicButton: FC = ({ muted, ...props }) => { = ({ muted, ...props }) => { > = ({ { + const urlParams = useUrlParams(); const { confineToRoom, appPrompt, preload, header, displayName, skipLobby } = - useUrlParams(); + urlParams; const { t } = useTranslation(); const { roomAlias, roomId, viaServers } = useRoomIdentifier(); @@ -68,15 +68,12 @@ export const RoomPage: FC = () => { const devices = useMediaDevices(); const [muteStates, setMuteStates] = useState(null); - const joined$ = useObservable( - (inputs$) => inputs$.pipe(map(([joined]) => joined)), - [joined], - ); + useEffect(() => { const scope = new ObservableScope(); - setMuteStates(new MuteStates(scope, devices, joined$)); + setMuteStates(new MuteStates(scope, devices, calculateInitialMuteState(urlParams, import.meta.env.VITE_PACKAGE, window.location.hostname))); return (): void => scope.end(); - }, [devices, joined$]); + }, [devices, urlParams]); useEffect(() => { // If we've finished loading, are not already authed and we've been given a display name as diff --git a/src/state/MuteStates.test.ts b/src/state/MuteStates.test.ts index f2a6e35f8..db3f503e6 100644 --- a/src/state/MuteStates.test.ts +++ b/src/state/MuteStates.test.ts @@ -51,7 +51,6 @@ describe("MuteState", () => { const muteState = new MuteState( testScope, deviceStub, - constant(true), true, forceMute$, ); @@ -166,8 +165,10 @@ describe("MuteStates", () => { const muteStates = new MuteStates( testScope, mediaDevices, - // consider joined - constant(true), + { + audioEnabled: false, + videoEnabled: false, + } ); let latestSyncedState: boolean | null = null; diff --git a/src/state/MuteStates.ts b/src/state/MuteStates.ts index 7f048f27e..7b29e31d0 100644 --- a/src/state/MuteStates.ts +++ b/src/state/MuteStates.ts @@ -24,7 +24,6 @@ import { import { type MediaDevices, type MediaDevice } from "../state/MediaDevices"; import { ElementWidgetActions, widget } from "../widget"; -import { getUrlParams } from "../UrlParams"; import { type ObservableScope } from "./ObservableScope"; import { type Behavior, constant } from "./Behavior"; @@ -42,12 +41,6 @@ const defaultHandler: Handler = async (desired) => Promise.resolve(desired); * Do not use directly outside of tests. */ export class MuteState { - // TODO: rewrite this to explain behavior, it is not understandable, and cannot add logging - private readonly enabledByDefault$ = - this.enabledByConfig && !getUrlParams().skipLobby - ? this.joined$.pipe(map((isJoined) => !isJoined)) - : of(false); - private readonly handler$ = new BehaviorSubject(defaultHandler); public setHandler(handler: Handler): void { @@ -72,76 +65,73 @@ export class MuteState { private readonly data$ = this.scope.behavior( this.canControlDevices$.pipe( distinctUntilChanged(), - withLatestFrom( - this.enabledByDefault$, - (canControlDevices, enabledByDefault) => { + map((canControlDevices) => { + logger.info( + `MuteState: canControlDevices: ${canControlDevices}, enabled by default: ${this.enabledByDefault}`, + ); + if (!canControlDevices) { logger.info( - `MuteState: canControlDevices: ${canControlDevices}, enabled by default: ${enabledByDefault}`, + `MuteState: devices connected: ${canControlDevices}, disabling`, ); - if (!canControlDevices) { - logger.info( - `MuteState: devices connected: ${canControlDevices}, disabling`, - ); - // We need to sync the mute state with the handler - // to ensure nothing is beeing published. - this.handler$.value(false).catch((err) => { - logger.error("MuteState-disable: handler error", err); - }); - return { enabled$: of(false), set: null, toggle: null }; - } + // We need to sync the mute state with the handler + // to ensure nothing is beeing published. + this.handler$.value(false).catch((err) => { + logger.error("MuteState-disable: handler error", err); + }); + return { enabled$: of(false), set: null, toggle: null }; + } - // Assume the default value only once devices are actually connected - let enabled = enabledByDefault; - const set$ = new Subject(); - const toggle$ = new Subject(); - const desired$ = merge(set$, toggle$.pipe(map(() => !enabled))); - const enabled$ = new Observable((subscriber) => { - subscriber.next(enabled); - let latestDesired = enabledByDefault; - let syncing = false; + // Assume the default value only once devices are actually connected + let enabled = this.enabledByDefault; + const set$ = new Subject(); + const toggle$ = new Subject(); + const desired$ = merge(set$, toggle$.pipe(map(() => !enabled))); + const enabled$ = new Observable((subscriber) => { + subscriber.next(enabled); + let latestDesired = this.enabledByDefault; + let syncing = false; - const sync = async (): Promise => { - if (enabled === latestDesired) syncing = false; - else { - const previouslyEnabled = enabled; - enabled = await firstValueFrom( - this.handler$.pipe( - switchMap(async (handler) => handler(latestDesired)), - ), - ); - if (enabled === previouslyEnabled) { - syncing = false; - } else { - subscriber.next(enabled); - syncing = true; - sync().catch((err) => { - // TODO: better error handling - logger.error("MuteState: handler error", err); - }); - } - } - }; - - const s = desired$.subscribe((desired) => { - latestDesired = desired; - if (syncing === false) { + const sync = async (): Promise => { + if (enabled === latestDesired) syncing = false; + else { + const previouslyEnabled = enabled; + enabled = await firstValueFrom( + this.handler$.pipe( + switchMap(async (handler) => handler(latestDesired)), + ), + ); + if (enabled === previouslyEnabled) { + syncing = false; + } else { + subscriber.next(enabled); syncing = true; sync().catch((err) => { // TODO: better error handling logger.error("MuteState: handler error", err); }); } - }); - return (): void => s.unsubscribe(); - }); - - return { - set: (enabled: boolean): void => set$.next(enabled), - toggle: (): void => toggle$.next(), - enabled$, + } }; - }, - ), + + const s = desired$.subscribe((desired) => { + latestDesired = desired; + if (syncing === false) { + syncing = true; + sync().catch((err) => { + // TODO: better error handling + logger.error("MuteState: handler error", err); + }); + } + }); + return (): void => s.unsubscribe(); + }); + + return { + set: (enabled: boolean): void => set$.next(enabled), + toggle: (): void => toggle$.next(), + enabled$, + }; + }), ), ); @@ -159,8 +149,7 @@ export class MuteState { public constructor( private readonly scope: ObservableScope, private readonly device: MediaDevice, - private readonly joined$: Observable, - private readonly enabledByConfig: boolean, + private readonly enabledByDefault: boolean, /** * An optional observable which, when it emits `true`, will force the mute. * Used for video to stop camera when earpiece mode is on. @@ -175,10 +164,10 @@ export class MuteStates { * True if the selected audio output device is an earpiece. * Used to force-disable video when on earpiece. */ - private readonly isEarpiece$ = combineLatest( + private readonly isEarpiece$ = combineLatest([ this.mediaDevices.audioOutput.available$, this.mediaDevices.audioOutput.selected$, - ).pipe( + ]).pipe( map(([available, selected]) => { if (!selected?.id) return false; const device = available.get(selected.id); @@ -190,22 +179,23 @@ export class MuteStates { public readonly audio = new MuteState( this.scope, this.mediaDevices.audioInput, - this.joined$, - true, + this.initialMuteState.audioEnabled, constant(false), ); public readonly video = new MuteState( this.scope, this.mediaDevices.videoInput, - this.joined$, - true, + this.initialMuteState.videoEnabled, this.isEarpiece$, ); public constructor( private readonly scope: ObservableScope, private readonly mediaDevices: MediaDevices, - private readonly joined$: Observable, + private readonly initialMuteState: { + audioEnabled: boolean; + videoEnabled: boolean; + }, ) { if (widget !== null) { // Sync our mute states with the hosting client diff --git a/src/state/initialMuteState.test.ts b/src/state/initialMuteState.test.ts new file mode 100644 index 000000000..08be50ef4 --- /dev/null +++ b/src/state/initialMuteState.test.ts @@ -0,0 +1,95 @@ +/* +Copyright 2026 Element Creations Ltd. + +SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial +Please see LICENSE in the repository root for full details. +*/ + +import { test, expect } from "vitest"; +import { type RTCCallIntent } from "matrix-js-sdk/lib/matrixrtc"; + +import { calculateInitialMuteState } from "./initialMuteState"; + + +test.each<{ + callIntent: RTCCallIntent; + packageType: "full" | "embedded"; +}>([ + { callIntent: "audio", packageType: "full" }, + { callIntent: "audio", packageType: "embedded" }, + { callIntent: "video", packageType: "full" }, + { callIntent: "video", packageType: "embedded" }, + { callIntent: "unknown", packageType: "full" }, + { callIntent: "unknown", packageType: "embedded" }, +])( + "Should allow to unmute on start if not skipping lobby (callIntent: $callIntent, packageType: $packageType)", + ({ callIntent, packageType }) => { + const { audioEnabled, videoEnabled } = calculateInitialMuteState( + { skipLobby: false, callIntent }, + packageType, + ); + expect(audioEnabled).toBe(true); + expect(videoEnabled).toBe(callIntent !== "audio"); + }, +); + +test.each<{ + callIntent: RTCCallIntent; +}>([ + { callIntent: "audio" }, + { callIntent: "video" }, + { callIntent: "unknown" }, +])( + "Should always mute on start if skipping lobby on non embedded build (callIntent: $callIntent)", + ({ callIntent }) => { + const { audioEnabled, videoEnabled } = calculateInitialMuteState( + { skipLobby: true, callIntent }, + "full", + ); + expect(audioEnabled).toBe(false); + expect(videoEnabled).toBe(false); + }, +); + +test.each<{ + callIntent: RTCCallIntent; +}>([ + { callIntent: "audio" }, + { callIntent: "video" }, + { callIntent: "unknown" }, +])( + "Can start unmuted if skipping lobby on embedded build (callIntent: $callIntent)", + ({ callIntent }) => { + const { audioEnabled, videoEnabled } = calculateInitialMuteState( + { skipLobby: true, callIntent }, + "embedded", + ); + expect(audioEnabled).toBe(true); + expect(videoEnabled).toBe(callIntent !== "audio"); + }, +); + + +test.each<{ + isDevBuild: boolean; + currentHost: string; + expectedEnabled: boolean; +}>([ + { isDevBuild: true, currentHost: "localhost", expectedEnabled: true }, + { isDevBuild: false, currentHost: "localhost", expectedEnabled: false }, + { isDevBuild: true, currentHost: "call.example.com", expectedEnabled: false }, + { isDevBuild: false, currentHost: "call.example.com", expectedEnabled: false }, +]) +("Should trust localhost domain when in dev mode isDevBuild($isDevBuild) host($currentHost)", ( + {isDevBuild, currentHost, expectedEnabled} +) => { + const { audioEnabled, videoEnabled } = calculateInitialMuteState( + { skipLobby: true, callIntent: "video" }, + "full", + currentHost, + isDevBuild, + ); + + expect(audioEnabled).toBe(expectedEnabled); + expect(videoEnabled).toBe(expectedEnabled); +}); diff --git a/src/state/initialMuteState.ts b/src/state/initialMuteState.ts new file mode 100644 index 000000000..41b365591 --- /dev/null +++ b/src/state/initialMuteState.ts @@ -0,0 +1,46 @@ +/* +Copyright 2026 Element Creations Ltd. + +SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial +Please see LICENSE in the repository root for full details. +*/ + +import { type UrlParams } from "../UrlParams.ts"; + +/** + * Calculates the initial mute state for media devices based on configuration. + * + * It is not always possible to start the widget with audio/video unmuted due to privacy concerns. + * This function encapsulates the logic to determine the appropriate initial state. + */ +export function calculateInitialMuteState( + urlParams: Pick, + packageType: "full" | "embedded", + hostname: string | undefined = undefined, + isDevBuild: boolean = import.meta.env.DEV, +): { audioEnabled: boolean; videoEnabled: boolean } { + const { skipLobby, callIntent } = urlParams; + + const isTrustedHost = + packageType == "embedded" || + // Trust local hosts in dev mode to make local testing easier + (hostname == "localhost" && isDevBuild); + + if (skipLobby && !isTrustedHost) { + // If host not trusted and lobby skipped, default to muted to protect user privacy. + // This prevents users from inadvertently joining with active audio/video + // when browser permissions were previously granted in a different context. + return { + audioEnabled: false, + videoEnabled: false, + }; + } + + // Embedded contexts are trusted environments, so they allow unmuted by default. + // Same for when showing a lobby, as users can adjust their settings there. + // Additionally, if the call intent is "audio", we disable video by default. + return { + audioEnabled: true, + videoEnabled: callIntent != "audio", + }; +} diff --git a/src/utils/test.ts b/src/utils/test.ts index 9a8459088..95d6ed0cb 100644 --- a/src/utils/test.ts +++ b/src/utils/test.ts @@ -525,5 +525,5 @@ export function mockMuteStates( joined$: Observable = of(true), ): MuteStates { const observableScope = new ObservableScope(); - return new MuteStates(observableScope, mockMediaDevices({}), joined$); + return new MuteStates(observableScope, mockMediaDevices({}), { audioEnabled: false, videoEnabled: false }); } From 231a80d9de13ec9ca2be35b082540dba68dca0da Mon Sep 17 00:00:00 2001 From: Valere Date: Fri, 9 Jan 2026 12:32:36 +0100 Subject: [PATCH 165/748] update snapshot, mute buttons have aria-label now --- src/room/__snapshots__/InCallView.test.tsx.snap | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/room/__snapshots__/InCallView.test.tsx.snap b/src/room/__snapshots__/InCallView.test.tsx.snap index a6405579c..52f4a7021 100644 --- a/src/room/__snapshots__/InCallView.test.tsx.snap +++ b/src/room/__snapshots__/InCallView.test.tsx.snap @@ -286,6 +286,7 @@ exports[`InCallView > rendering > renders 1`] = ` > + } + > + + + + ( + currentMedia as RemoteScreenShareViewModel + ).adjustPlaybackVolume(v) + } + onValueCommit={() => + ( + currentMedia as RemoteScreenShareViewModel + ).commitPlaybackVolume() + } + /> + + + )} + } + > + + + + + + ) + ); +}; + interface Props { ref?: Ref; vm: SpotlightTileViewModel; @@ -263,37 +332,9 @@ export const SpotlightTile: FC = ({ const latestMedia = useLatest(media); const latestVisibleId = useLatest(visibleId); const visibleIndex = media.findIndex((vm) => vm.id === visibleId); + const visibleMedia = media.at(visibleIndex); const canGoBack = visibleIndex > 0; const canGoToNext = visibleIndex !== -1 && visibleIndex < media.length - 1; - const currentMedia = media[visibleIndex]; - // only "audioEnabled$" needs to be checked but I wanted to be more specific just in - // case more models are added in the future, since screen shares always have video - const currentScreenShare = - currentMedia && - "audioEnabled$" in currentMedia && - "videoEnabled$" in currentMedia - ? (currentMedia as RemoteScreenShareViewModel) - : null; - - const isScreenShare = currentScreenShare != null; - - const hasAudio$ = useBehavior( - currentScreenShare?.audioEnabled$ ?? constant(false), - ); - - const isLocalScreenShare = currentScreenShare?.local ?? false; - - const screenShareLocallyMuted = useBehavior( - currentScreenShare?.playbackMuted$ ?? constant(false), - ); - - const ScreenShareVolumeIcon = screenShareLocallyMuted - ? VolumeOffIcon - : VolumeOnIcon; - - const screenShareVolume = useBehavior( - currentScreenShare?.playbackVolume$ ?? constant(0), - ); const isFullscreen = useCallback((): boolean => { const rootElement = document.body; @@ -362,7 +403,6 @@ export const SpotlightTile: FC = ({ }, [latestVisibleId, latestMedia, setScrollToId]); const ToggleExpandIcon = expanded ? CollapseIcon : ExpandIcon; - const [openVolumeMenu, setOpenVolumeMenu] = useState(false); return ( = ({ /> ))}
-
- {/* - Show volume slider only when the tile is a screenshare, has audio, - is in spotlight mode, and isn't your own screen share. - */} - {isScreenShare && - hasAudio$ && - onToggleExpanded && - !isLocalScreenShare && ( - - - - } - > - - - - ( - currentMedia as RemoteScreenShareViewModel - ).adjustPlaybackVolume(v) - } - onValueCommit={() => - ( - currentMedia as RemoteScreenShareViewModel - ).commitPlaybackVolume() - } - /> - - - )} - +
+ {visibleMedia?.type === "screen share" && !visibleMedia.local && ( + + )} + {platform === "desktop" && ( + + )} {onToggleExpanded && (
@@ -760,12 +726,13 @@ export const InCallView: FC = ({ const allConnections = useBehavior(vm.allConnections$); return ( + // The onClick handler here exists to control the visibility of the footer, + // and the footer is also viewable by moving focus into it, so this is fine. + // eslint-disable-next-line jsx-a11y/no-static-element-interactions, jsx-a11y/click-events-have-key-events
diff --git a/src/room/LayoutToggle.tsx b/src/room/LayoutToggle.tsx index 6cddc95f6..ca6aa467a 100644 --- a/src/room/LayoutToggle.tsx +++ b/src/room/LayoutToggle.tsx @@ -5,7 +5,7 @@ SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial Please see LICENSE in the repository root for full details. */ -import { type ChangeEvent, type FC, type TouchEvent, useCallback } from "react"; +import { type ChangeEvent, type FC, useCallback } from "react"; import { useTranslation } from "react-i18next"; import { Tooltip } from "@vector-im/compound-web"; import { @@ -22,15 +22,9 @@ interface Props { layout: Layout; setLayout: (layout: Layout) => void; className?: string; - onTouchEnd?: (e: TouchEvent) => void; } -export const LayoutToggle: FC = ({ - layout, - setLayout, - className, - onTouchEnd, -}) => { +export const LayoutToggle: FC = ({ layout, setLayout, className }) => { const { t } = useTranslation(); const onChange = useCallback( @@ -47,7 +41,6 @@ export const LayoutToggle: FC = ({ value="spotlight" checked={layout === "spotlight"} onChange={onChange} - onTouchEnd={onTouchEnd} /> @@ -58,7 +51,6 @@ export const LayoutToggle: FC = ({ value="grid" checked={layout === "grid"} onChange={onChange} - onTouchEnd={onTouchEnd} /> diff --git a/src/tile/SpotlightTile.module.css b/src/tile/SpotlightTile.module.css index 178d13f3b..fe13f906b 100644 --- a/src/tile/SpotlightTile.module.css +++ b/src/tile/SpotlightTile.module.css @@ -84,7 +84,6 @@ Please see LICENSE in the repository root for full details. .expand { appearance: none; cursor: pointer; - opacity: 0; padding: var(--cpd-space-2x); border: none; border-radius: var(--cpd-radius-pill-effect); @@ -148,17 +147,21 @@ Please see LICENSE in the repository root for full details. } } -.expand:active { +.expand:active, .expand[data-state="open"] { background: var(--cpd-color-gray-100); } @media (hover) { + .tile > div > button { + opacity: 0; + } .tile:hover > div > button { opacity: 1; } } -.tile:has(:focus-visible) > div > button { +.tile:has(:focus-visible) > div > button, +.tile > div:has([data-state="open"]) > button { opacity: 1; } From 885a523e9189aa41bb83045f36e7fe9b0bdafe9b Mon Sep 17 00:00:00 2001 From: Robin Date: Mon, 9 Mar 2026 10:44:22 +0100 Subject: [PATCH 343/748] Fix formatting --- src/tile/SpotlightTile.module.css | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/tile/SpotlightTile.module.css b/src/tile/SpotlightTile.module.css index fe13f906b..af0e0add5 100644 --- a/src/tile/SpotlightTile.module.css +++ b/src/tile/SpotlightTile.module.css @@ -147,7 +147,8 @@ Please see LICENSE in the repository root for full details. } } -.expand:active, .expand[data-state="open"] { +.expand:active, +.expand[data-state="open"] { background: var(--cpd-color-gray-100); } From 4922249f41339c6deedc77465bbda3bbd3373a61 Mon Sep 17 00:00:00 2001 From: Robin Date: Mon, 9 Mar 2026 13:00:43 +0100 Subject: [PATCH 344/748] Unpin Knip and LiveKit track processors These dependencies were held back on old versions because of issues that are now resolved (see 2fca7e37191e81f015426eb3756a19b19277031e and 44eb8acaeec990656e921d954694e459722acb48). --- package.json | 4 +- yarn.lock | 224 ++++++++++++++++++++++++++------------------------- 2 files changed, 117 insertions(+), 111 deletions(-) diff --git a/package.json b/package.json index 705b0f103..9ee0ad263 100644 --- a/package.json +++ b/package.json @@ -48,7 +48,7 @@ "@livekit/components-core": "^0.12.0", "@livekit/components-react": "^2.0.0", "@livekit/protocol": "^1.42.2", - "@livekit/track-processors": "^0.6.0 || ^0.7.1", + "@livekit/track-processors": "^0.7.1", "@mediapipe/tasks-vision": "^0.10.18", "@playwright/test": "^1.57.0", "@radix-ui/react-dialog": "^1.0.4", @@ -101,7 +101,7 @@ "i18next-browser-languagedetector": "^8.0.0", "i18next-parser": "^9.1.0", "jsdom": "^26.0.0", - "knip": "5.82.1", + "knip": "^5.86.0", "livekit-client": "^2.13.0", "lodash-es": "^4.17.21", "loglevel": "^1.9.1", diff --git a/yarn.lock b/yarn.lock index 4675d0e1a..bd90ded3e 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3345,15 +3345,15 @@ __metadata: languageName: node linkType: hard -"@livekit/track-processors@npm:^0.6.0 || ^0.7.1": - version: 0.6.1 - resolution: "@livekit/track-processors@npm:0.6.1" +"@livekit/track-processors@npm:^0.7.1": + version: 0.7.2 + resolution: "@livekit/track-processors@npm:0.7.2" dependencies: "@mediapipe/tasks-vision": "npm:0.10.14" peerDependencies: "@types/dom-mediacapture-transform": ^0.1.9 livekit-client: ^1.12.0 || ^2.1.0 - checksum: 10c0/80f54663c7e13de299de9e2565b6cbd2ba74ea0a4a8adf8a366e8cfd0e19dedfb9d699899137f1a6133414f28779877eeb3200074c03893bc63aeb0d8c912a91 + checksum: 10c0/d5638942205ea05a507254f61157696881332b866ff538d1e93bd2267c31ce80c9a81dfc4f8c4b7c96910452b13511ee06be1ae7ab30c299b73fe04baf80a673 languageName: node linkType: hard @@ -3371,7 +3371,7 @@ __metadata: languageName: node linkType: hard -"@napi-rs/wasm-runtime@npm:^1.1.0": +"@napi-rs/wasm-runtime@npm:^1.1.1": version: 1.1.1 resolution: "@napi-rs/wasm-runtime@npm:1.1.1" dependencies: @@ -3551,144 +3551,144 @@ __metadata: languageName: node linkType: hard -"@oxc-resolver/binding-android-arm-eabi@npm:11.16.2": - version: 11.16.2 - resolution: "@oxc-resolver/binding-android-arm-eabi@npm:11.16.2" +"@oxc-resolver/binding-android-arm-eabi@npm:11.19.1": + version: 11.19.1 + resolution: "@oxc-resolver/binding-android-arm-eabi@npm:11.19.1" conditions: os=android & cpu=arm languageName: node linkType: hard -"@oxc-resolver/binding-android-arm64@npm:11.16.2": - version: 11.16.2 - resolution: "@oxc-resolver/binding-android-arm64@npm:11.16.2" +"@oxc-resolver/binding-android-arm64@npm:11.19.1": + version: 11.19.1 + resolution: "@oxc-resolver/binding-android-arm64@npm:11.19.1" conditions: os=android & cpu=arm64 languageName: node linkType: hard -"@oxc-resolver/binding-darwin-arm64@npm:11.16.2": - version: 11.16.2 - resolution: "@oxc-resolver/binding-darwin-arm64@npm:11.16.2" +"@oxc-resolver/binding-darwin-arm64@npm:11.19.1": + version: 11.19.1 + resolution: "@oxc-resolver/binding-darwin-arm64@npm:11.19.1" conditions: os=darwin & cpu=arm64 languageName: node linkType: hard -"@oxc-resolver/binding-darwin-x64@npm:11.16.2": - version: 11.16.2 - resolution: "@oxc-resolver/binding-darwin-x64@npm:11.16.2" +"@oxc-resolver/binding-darwin-x64@npm:11.19.1": + version: 11.19.1 + resolution: "@oxc-resolver/binding-darwin-x64@npm:11.19.1" conditions: os=darwin & cpu=x64 languageName: node linkType: hard -"@oxc-resolver/binding-freebsd-x64@npm:11.16.2": - version: 11.16.2 - resolution: "@oxc-resolver/binding-freebsd-x64@npm:11.16.2" +"@oxc-resolver/binding-freebsd-x64@npm:11.19.1": + version: 11.19.1 + resolution: "@oxc-resolver/binding-freebsd-x64@npm:11.19.1" conditions: os=freebsd & cpu=x64 languageName: node linkType: hard -"@oxc-resolver/binding-linux-arm-gnueabihf@npm:11.16.2": - version: 11.16.2 - resolution: "@oxc-resolver/binding-linux-arm-gnueabihf@npm:11.16.2" +"@oxc-resolver/binding-linux-arm-gnueabihf@npm:11.19.1": + version: 11.19.1 + resolution: "@oxc-resolver/binding-linux-arm-gnueabihf@npm:11.19.1" conditions: os=linux & cpu=arm languageName: node linkType: hard -"@oxc-resolver/binding-linux-arm-musleabihf@npm:11.16.2": - version: 11.16.2 - resolution: "@oxc-resolver/binding-linux-arm-musleabihf@npm:11.16.2" +"@oxc-resolver/binding-linux-arm-musleabihf@npm:11.19.1": + version: 11.19.1 + resolution: "@oxc-resolver/binding-linux-arm-musleabihf@npm:11.19.1" conditions: os=linux & cpu=arm languageName: node linkType: hard -"@oxc-resolver/binding-linux-arm64-gnu@npm:11.16.2": - version: 11.16.2 - resolution: "@oxc-resolver/binding-linux-arm64-gnu@npm:11.16.2" +"@oxc-resolver/binding-linux-arm64-gnu@npm:11.19.1": + version: 11.19.1 + resolution: "@oxc-resolver/binding-linux-arm64-gnu@npm:11.19.1" conditions: os=linux & cpu=arm64 & libc=glibc languageName: node linkType: hard -"@oxc-resolver/binding-linux-arm64-musl@npm:11.16.2": - version: 11.16.2 - resolution: "@oxc-resolver/binding-linux-arm64-musl@npm:11.16.2" +"@oxc-resolver/binding-linux-arm64-musl@npm:11.19.1": + version: 11.19.1 + resolution: "@oxc-resolver/binding-linux-arm64-musl@npm:11.19.1" conditions: os=linux & cpu=arm64 & libc=musl languageName: node linkType: hard -"@oxc-resolver/binding-linux-ppc64-gnu@npm:11.16.2": - version: 11.16.2 - resolution: "@oxc-resolver/binding-linux-ppc64-gnu@npm:11.16.2" +"@oxc-resolver/binding-linux-ppc64-gnu@npm:11.19.1": + version: 11.19.1 + resolution: "@oxc-resolver/binding-linux-ppc64-gnu@npm:11.19.1" conditions: os=linux & cpu=ppc64 & libc=glibc languageName: node linkType: hard -"@oxc-resolver/binding-linux-riscv64-gnu@npm:11.16.2": - version: 11.16.2 - resolution: "@oxc-resolver/binding-linux-riscv64-gnu@npm:11.16.2" +"@oxc-resolver/binding-linux-riscv64-gnu@npm:11.19.1": + version: 11.19.1 + resolution: "@oxc-resolver/binding-linux-riscv64-gnu@npm:11.19.1" conditions: os=linux & cpu=riscv64 & libc=glibc languageName: node linkType: hard -"@oxc-resolver/binding-linux-riscv64-musl@npm:11.16.2": - version: 11.16.2 - resolution: "@oxc-resolver/binding-linux-riscv64-musl@npm:11.16.2" +"@oxc-resolver/binding-linux-riscv64-musl@npm:11.19.1": + version: 11.19.1 + resolution: "@oxc-resolver/binding-linux-riscv64-musl@npm:11.19.1" conditions: os=linux & cpu=riscv64 & libc=musl languageName: node linkType: hard -"@oxc-resolver/binding-linux-s390x-gnu@npm:11.16.2": - version: 11.16.2 - resolution: "@oxc-resolver/binding-linux-s390x-gnu@npm:11.16.2" +"@oxc-resolver/binding-linux-s390x-gnu@npm:11.19.1": + version: 11.19.1 + resolution: "@oxc-resolver/binding-linux-s390x-gnu@npm:11.19.1" conditions: os=linux & cpu=s390x & libc=glibc languageName: node linkType: hard -"@oxc-resolver/binding-linux-x64-gnu@npm:11.16.2": - version: 11.16.2 - resolution: "@oxc-resolver/binding-linux-x64-gnu@npm:11.16.2" +"@oxc-resolver/binding-linux-x64-gnu@npm:11.19.1": + version: 11.19.1 + resolution: "@oxc-resolver/binding-linux-x64-gnu@npm:11.19.1" conditions: os=linux & cpu=x64 & libc=glibc languageName: node linkType: hard -"@oxc-resolver/binding-linux-x64-musl@npm:11.16.2": - version: 11.16.2 - resolution: "@oxc-resolver/binding-linux-x64-musl@npm:11.16.2" +"@oxc-resolver/binding-linux-x64-musl@npm:11.19.1": + version: 11.19.1 + resolution: "@oxc-resolver/binding-linux-x64-musl@npm:11.19.1" conditions: os=linux & cpu=x64 & libc=musl languageName: node linkType: hard -"@oxc-resolver/binding-openharmony-arm64@npm:11.16.2": - version: 11.16.2 - resolution: "@oxc-resolver/binding-openharmony-arm64@npm:11.16.2" +"@oxc-resolver/binding-openharmony-arm64@npm:11.19.1": + version: 11.19.1 + resolution: "@oxc-resolver/binding-openharmony-arm64@npm:11.19.1" conditions: os=openharmony & cpu=arm64 languageName: node linkType: hard -"@oxc-resolver/binding-wasm32-wasi@npm:11.16.2": - version: 11.16.2 - resolution: "@oxc-resolver/binding-wasm32-wasi@npm:11.16.2" +"@oxc-resolver/binding-wasm32-wasi@npm:11.19.1": + version: 11.19.1 + resolution: "@oxc-resolver/binding-wasm32-wasi@npm:11.19.1" dependencies: - "@napi-rs/wasm-runtime": "npm:^1.1.0" + "@napi-rs/wasm-runtime": "npm:^1.1.1" conditions: cpu=wasm32 languageName: node linkType: hard -"@oxc-resolver/binding-win32-arm64-msvc@npm:11.16.2": - version: 11.16.2 - resolution: "@oxc-resolver/binding-win32-arm64-msvc@npm:11.16.2" +"@oxc-resolver/binding-win32-arm64-msvc@npm:11.19.1": + version: 11.19.1 + resolution: "@oxc-resolver/binding-win32-arm64-msvc@npm:11.19.1" conditions: os=win32 & cpu=arm64 languageName: node linkType: hard -"@oxc-resolver/binding-win32-ia32-msvc@npm:11.16.2": - version: 11.16.2 - resolution: "@oxc-resolver/binding-win32-ia32-msvc@npm:11.16.2" +"@oxc-resolver/binding-win32-ia32-msvc@npm:11.19.1": + version: 11.19.1 + resolution: "@oxc-resolver/binding-win32-ia32-msvc@npm:11.19.1" conditions: os=win32 & cpu=ia32 languageName: node linkType: hard -"@oxc-resolver/binding-win32-x64-msvc@npm:11.16.2": - version: 11.16.2 - resolution: "@oxc-resolver/binding-win32-x64-msvc@npm:11.16.2" +"@oxc-resolver/binding-win32-x64-msvc@npm:11.19.1": + version: 11.19.1 + resolution: "@oxc-resolver/binding-win32-x64-msvc@npm:11.19.1" conditions: os=win32 & cpu=x64 languageName: node linkType: hard @@ -8380,7 +8380,7 @@ __metadata: "@livekit/components-core": "npm:^0.12.0" "@livekit/components-react": "npm:^2.0.0" "@livekit/protocol": "npm:^1.42.2" - "@livekit/track-processors": "npm:^0.6.0 || ^0.7.1" + "@livekit/track-processors": "npm:^0.7.1" "@mediapipe/tasks-vision": "npm:^0.10.18" "@playwright/test": "npm:^1.57.0" "@radix-ui/react-dialog": "npm:^1.0.4" @@ -8433,7 +8433,7 @@ __metadata: i18next-browser-languagedetector: "npm:^8.0.0" i18next-parser: "npm:^9.1.0" jsdom: "npm:^26.0.0" - knip: "npm:5.82.1" + knip: "npm:^5.86.0" livekit-client: "npm:^2.13.0" lodash-es: "npm:^4.17.21" loglevel: "npm:^1.9.1" @@ -11039,17 +11039,6 @@ __metadata: languageName: node linkType: hard -"js-yaml@npm:^4.1.1": - version: 4.1.1 - resolution: "js-yaml@npm:4.1.1" - dependencies: - argparse: "npm:^2.0.1" - bin: - js-yaml: bin/js-yaml.js - checksum: 10c0/561c7d7088c40a9bb53cc75becbfb1df6ae49b34b5e6e5a81744b14ae8667ec564ad2527709d1a6e7d5e5fa6d483aa0f373a50ad98d42fde368ec4a190d4fae7 - languageName: node - linkType: hard - "jsbn@npm:1.1.0": version: 1.1.0 resolution: "jsbn@npm:1.1.0" @@ -11232,21 +11221,22 @@ __metadata: languageName: node linkType: hard -"knip@npm:5.82.1": - version: 5.82.1 - resolution: "knip@npm:5.82.1" +"knip@npm:^5.86.0": + version: 5.86.0 + resolution: "knip@npm:5.86.0" dependencies: "@nodelib/fs.walk": "npm:^1.2.3" fast-glob: "npm:^3.3.3" formatly: "npm:^0.3.0" jiti: "npm:^2.6.0" - js-yaml: "npm:^4.1.1" minimist: "npm:^1.2.8" - oxc-resolver: "npm:^11.15.0" + oxc-resolver: "npm:^11.19.1" picocolors: "npm:^1.1.1" picomatch: "npm:^4.0.1" smol-toml: "npm:^1.5.2" strip-json-comments: "npm:5.0.3" + unbash: "npm:^2.2.0" + yaml: "npm:^2.8.2" zod: "npm:^4.1.11" peerDependencies: "@types/node": ">=18" @@ -11254,7 +11244,7 @@ __metadata: bin: knip: bin/knip.js knip-bun: bin/knip-bun.js - checksum: 10c0/c3bfe898fe3103bb6a59ee2ba4297f05ea4d2db474571db89ae199ebbd74eafa5061d05b3bc2c75e4ec2322ba7ffee44493c76132d3d8991fae66ba742b9ccb4 + checksum: 10c0/6905c3c2bd21b1f5d51bf83568d1eff67d9d74dd9547c428f810b0dbc3624225a0c41b8e8caccbb111df2db175933aa853345798a05f91f9344ce3aca26898ff languageName: node linkType: hard @@ -12173,30 +12163,30 @@ __metadata: languageName: node linkType: hard -"oxc-resolver@npm:^11.15.0": - version: 11.16.2 - resolution: "oxc-resolver@npm:11.16.2" +"oxc-resolver@npm:^11.19.1": + version: 11.19.1 + resolution: "oxc-resolver@npm:11.19.1" dependencies: - "@oxc-resolver/binding-android-arm-eabi": "npm:11.16.2" - "@oxc-resolver/binding-android-arm64": "npm:11.16.2" - "@oxc-resolver/binding-darwin-arm64": "npm:11.16.2" - "@oxc-resolver/binding-darwin-x64": "npm:11.16.2" - "@oxc-resolver/binding-freebsd-x64": "npm:11.16.2" - "@oxc-resolver/binding-linux-arm-gnueabihf": "npm:11.16.2" - "@oxc-resolver/binding-linux-arm-musleabihf": "npm:11.16.2" - "@oxc-resolver/binding-linux-arm64-gnu": "npm:11.16.2" - "@oxc-resolver/binding-linux-arm64-musl": "npm:11.16.2" - "@oxc-resolver/binding-linux-ppc64-gnu": "npm:11.16.2" - "@oxc-resolver/binding-linux-riscv64-gnu": "npm:11.16.2" - "@oxc-resolver/binding-linux-riscv64-musl": "npm:11.16.2" - "@oxc-resolver/binding-linux-s390x-gnu": "npm:11.16.2" - "@oxc-resolver/binding-linux-x64-gnu": "npm:11.16.2" - "@oxc-resolver/binding-linux-x64-musl": "npm:11.16.2" - "@oxc-resolver/binding-openharmony-arm64": "npm:11.16.2" - "@oxc-resolver/binding-wasm32-wasi": "npm:11.16.2" - "@oxc-resolver/binding-win32-arm64-msvc": "npm:11.16.2" - "@oxc-resolver/binding-win32-ia32-msvc": "npm:11.16.2" - "@oxc-resolver/binding-win32-x64-msvc": "npm:11.16.2" + "@oxc-resolver/binding-android-arm-eabi": "npm:11.19.1" + "@oxc-resolver/binding-android-arm64": "npm:11.19.1" + "@oxc-resolver/binding-darwin-arm64": "npm:11.19.1" + "@oxc-resolver/binding-darwin-x64": "npm:11.19.1" + "@oxc-resolver/binding-freebsd-x64": "npm:11.19.1" + "@oxc-resolver/binding-linux-arm-gnueabihf": "npm:11.19.1" + "@oxc-resolver/binding-linux-arm-musleabihf": "npm:11.19.1" + "@oxc-resolver/binding-linux-arm64-gnu": "npm:11.19.1" + "@oxc-resolver/binding-linux-arm64-musl": "npm:11.19.1" + "@oxc-resolver/binding-linux-ppc64-gnu": "npm:11.19.1" + "@oxc-resolver/binding-linux-riscv64-gnu": "npm:11.19.1" + "@oxc-resolver/binding-linux-riscv64-musl": "npm:11.19.1" + "@oxc-resolver/binding-linux-s390x-gnu": "npm:11.19.1" + "@oxc-resolver/binding-linux-x64-gnu": "npm:11.19.1" + "@oxc-resolver/binding-linux-x64-musl": "npm:11.19.1" + "@oxc-resolver/binding-openharmony-arm64": "npm:11.19.1" + "@oxc-resolver/binding-wasm32-wasi": "npm:11.19.1" + "@oxc-resolver/binding-win32-arm64-msvc": "npm:11.19.1" + "@oxc-resolver/binding-win32-ia32-msvc": "npm:11.19.1" + "@oxc-resolver/binding-win32-x64-msvc": "npm:11.19.1" dependenciesMeta: "@oxc-resolver/binding-android-arm-eabi": optional: true @@ -12238,7 +12228,7 @@ __metadata: optional: true "@oxc-resolver/binding-win32-x64-msvc": optional: true - checksum: 10c0/b20a0fea18fdf31dbaee51354ce7b987ba8f3e780c6c1de9034628033a69d0b3085f9596d9925797d9340bdf4b98cd72a258b0728d0d5e5de2b1748154921b42 + checksum: 10c0/8ac4eaffa9c0bcbb9f4f4a2b43786457ec5a68684d8776cb78b5a15ce3d1a79d3e67262aa3c635f98a0c1cd6cd56a31fcb05bffb9a286100056e4ab06b928833 languageName: node linkType: hard @@ -15153,6 +15143,13 @@ __metadata: languageName: node linkType: hard +"unbash@npm:^2.2.0": + version: 2.2.0 + resolution: "unbash@npm:2.2.0" + checksum: 10c0/f218a30e2b65147dba16fcea5d9cbfe5af9d9518e98083b9790b9884959c82c5c8f85e7feeea717430e2ea6b352a1d57ad98e90fe488638606de12c9254cbf35 + languageName: node + linkType: hard + "unbox-primitive@npm:^1.1.0": version: 1.1.0 resolution: "unbox-primitive@npm:1.1.0" @@ -16105,6 +16102,15 @@ __metadata: languageName: node linkType: hard +"yaml@npm:^2.8.2": + version: 2.8.2 + resolution: "yaml@npm:2.8.2" + bin: + yaml: bin.mjs + checksum: 10c0/703e4dc1e34b324aa66876d63618dcacb9ed49f7e7fe9b70f1e703645be8d640f68ab84f12b86df8ac960bac37acf5513e115de7c970940617ce0343c8c9cd96 + languageName: node + linkType: hard + "yargs-parser@npm:^18.1.2": version: 18.1.3 resolution: "yargs-parser@npm:18.1.3" From 4c7fad30c064bdba8d58f15683827625b4e49f1d Mon Sep 17 00:00:00 2001 From: Robin Date: Mon, 9 Mar 2026 13:11:16 +0100 Subject: [PATCH 345/748] Silence new Knip errors --- knip.ts | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/knip.ts b/knip.ts index d23d42fec..3be3e6539 100644 --- a/knip.ts +++ b/knip.ts @@ -34,6 +34,12 @@ export default { // then Knip will flag it as a false positive // https://github.com/webpro-nl/knip/issues/766 "@vector-im/compound-web", + // Yarn plugins are allowed to depend on packages provided by the Yarn + // runtime. These shouldn't be listed in package.json, because plugins + // should work before Yarn even installs dependencies for the first time. + // https://yarnpkg.com/advanced/plugin-tutorial#what-does-a-plugin-look-like + "@yarnpkg/core", + "@yarnpkg/parsers", "matrix-widget-api", ], ignoreExportsUsedInFile: true, From 8f418ce9fd5c1d2090b242adf7801368b11231bb Mon Sep 17 00:00:00 2001 From: Valere Date: Mon, 9 Mar 2026 13:59:39 +0100 Subject: [PATCH 346/748] fix cla link --- .github/PULL_REQUEST_TEMPLATE.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index e68c0f42f..787ddc730 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -36,4 +36,4 @@ Uncomment this markdown table below and edit the last line `|||`: - [ ] Pull request includes screenshots or videos if containing UI changes - [ ] Tests written for new code (and old code if feasible). - [ ] Linter and other CI checks pass. -- [ ] I have licensed the changes to Element by completing the [Contributor License Agreement (CLA)](https://cla-assistant.io/element-hq/element-web) +- [ ] I have licensed the changes to Element by completing the [Contributor License Agreement (CLA)](https://cla-assistant.io/element-hq/element-call) From ca3837f44ebdb3340340af1b95d8eae924f67667 Mon Sep 17 00:00:00 2001 From: Valere Date: Mon, 9 Mar 2026 15:07:42 +0100 Subject: [PATCH 347/748] fix merge issue that added back a deprecated test --- src/state/media/MediaViewModel.test.ts | 15 --------------- 1 file changed, 15 deletions(-) diff --git a/src/state/media/MediaViewModel.test.ts b/src/state/media/MediaViewModel.test.ts index f64dd3eea..9d873ccba 100644 --- a/src/state/media/MediaViewModel.test.ts +++ b/src/state/media/MediaViewModel.test.ts @@ -160,21 +160,6 @@ test("control a participant's screen share volume", () => { }); }); -test("toggle fit/contain for a participant's video", () => { - const vm = mockRemoteMedia(rtcMembership, {}, mockRemoteParticipant({})); - withTestScheduler(({ expectObservable, schedule }) => { - schedule("-ab|", { - a: () => vm.toggleCropVideo(), - b: () => vm.toggleCropVideo(), - }); - expectObservable(vm.cropVideo$).toBe("abc", { - a: true, - b: false, - c: true, - }); - }); -}); - test("local media remembers whether it should always be shown", () => { const vm1 = mockLocalMedia( rtcMembership, From 3da762ab36faf06915053cdab9f91b12fd8a76c8 Mon Sep 17 00:00:00 2001 From: Valere Date: Mon, 9 Mar 2026 17:49:04 +0100 Subject: [PATCH 348/748] fix: typo inverting with/height in PIP spotlight tile --- src/room/InCallView.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/room/InCallView.tsx b/src/room/InCallView.tsx index aceb07cf5..d8803b22e 100644 --- a/src/room/InCallView.tsx +++ b/src/room/InCallView.tsx @@ -584,8 +584,8 @@ export const InCallView: FC = ({ vm={layout.spotlight} expanded onToggleExpanded={null} - targetWidth={gridBounds.height} - targetHeight={gridBounds.width} + targetWidth={gridBounds.width} + targetHeight={gridBounds.height} showIndicators={false} focusable={!contentObscured} aria-hidden={contentObscured} From 699e31f59a00c358f0a9fe6b68ac2fa19c909a45 Mon Sep 17 00:00:00 2001 From: JephDiel Date: Mon, 9 Mar 2026 22:25:54 -0500 Subject: [PATCH 349/748] Download Avatar from relevent source Instead of relying on failures directly use the available method to download the avatar. --- src/Avatar.test.tsx | 50 ++++++--------------- src/Avatar.tsx | 56 ++++++++++-------------- src/ClientContext.tsx | 15 ++++--- src/settings/useSubmitRageshake.test.tsx | 2 +- 4 files changed, 47 insertions(+), 76 deletions(-) diff --git a/src/Avatar.test.tsx b/src/Avatar.test.tsx index 1ad0f4beb..3d75d4c12 100644 --- a/src/Avatar.test.tsx +++ b/src/Avatar.test.tsx @@ -17,8 +17,15 @@ import EventEmitter from "events"; import { widget } from "./widget"; const TestComponent: FC< - PropsWithChildren<{ client: MatrixClient; supportsThumbnails?: boolean }> -> = ({ client, children, supportsThumbnails }) => { + PropsWithChildren<{ + client: MatrixClient; + supportsAuthenticatedMedia?: boolean; + }> +> = ({ + client, + children, + supportsAuthenticatedMedia: supportsAuthenticatedMedia, +}) => { return ( { expect(client.mxcUrlToHttp).toBeCalledTimes(0); }); -test("should just render a placeholder when thumbnails are not supported", () => { - const client = vi.mocked({ - getAccessToken: () => "my-access-token", - mxcUrlToHttp: () => vi.fn(), - } as unknown as MatrixClient); - - vi.spyOn(client, "mxcUrlToHttp"); - const member = mockMatrixRoomMember( - mockRtcMembership("@alice:example.org", "AAAA"), - { - getMxcAvatarUrl: () => "mxc://example.org/alice-avatar", - }, - ); - const displayName = "Alice"; - render( - - - , - ); - const element = screen.getByRole("img", { name: "@alice:example.org" }); - expect(element.tagName).toEqual("SPAN"); - expect(client.mxcUrlToHttp).toBeCalledTimes(0); -}); - -test("should attempt to fetch authenticated media", async () => { +test("should attempt to fetch authenticated media if supported", async () => { const expectedAuthUrl = "http://example.org/media/alice-avatar"; const expectedObjectURL = "my-object-url"; const accessToken = "my-access-token"; @@ -142,7 +120,7 @@ test("should attempt to fetch authenticated media", async () => { ); const displayName = "Alice"; render( - + { }); }); -test("should use widget API when unable to authenticate media", async () => { +test("should attempt to use widget API if authenticate media is not supported", async () => { const expectedMXCUrl = "mxc://example.org/alice-avatar"; const expectedObjectURL = "my-object-url"; const theBlob = new Blob([]); @@ -188,7 +166,7 @@ test("should use widget API when unable to authenticate media", async () => { ); const displayName = "Alice"; render( - + = ({ const sizePx = useMemo( () => Object.values(Size).includes(size as Size) - ? sizes.get(size as Size) + ? sizes.get(size as Size)! : (size as number), [size], ); @@ -88,17 +88,29 @@ export const Avatar: FC = ({ const [avatarUrl, setAvatarUrl] = useState(undefined); useEffect(() => { - if (!src) { + if (!src || clientState?.state !== "valid") { + setAvatarUrl(undefined); + return; + } + + const { authenticated, supportedFeatures } = clientState; + let blob: Promise; + + if ( + supportedFeatures.authenticatedMedia && + authenticated?.client && + sizePx + ) { + blob = getAvatarFromServer(authenticated.client, src, sizePx); + } else if (widget?.api) { + blob = getAvatarFromWidgetAPI(widget.api, src); + } else { setAvatarUrl(undefined); return; } let objectUrl: string | undefined; - - getAvatarFromServer(clientState, src, sizePx) // Try to download directly from the mxc:// - .catch((ex) => { - return getAvatarFromWidget(widget?.api, src); // Fallback to trying to use the MSC4039 Widget API - }) + blob .then((blob) => { objectUrl = URL.createObjectURL(blob); setAvatarUrl(objectUrl); @@ -128,26 +140,10 @@ export const Avatar: FC = ({ }; async function getAvatarFromServer( - clientState: ClientState | undefined, + client: MatrixClient, src: string, - sizePx: number | undefined, + sizePx: number, ): Promise { - if (clientState?.state !== "valid") { - throw new Error("Client state must be valid"); - } - if (!sizePx) { - throw new Error("size must be supplied"); - } - - const { authenticated, supportedFeatures } = clientState; - const client = authenticated?.client; - if (!client) { - throw new Error("Client must be supplied"); - } - if (!supportedFeatures.thumbnails) { - throw new Error("Thumbnails are not supported"); - } - const httpSrc = getAvatarUrl(client, src, sizePx); if (!httpSrc) { throw new Error("Failed to get http avatar URL"); @@ -169,14 +165,10 @@ async function getAvatarFromServer( return blob; } -async function getAvatarFromWidget( - api: WidgetApi | undefined, +async function getAvatarFromWidgetAPI( + api: WidgetApi, src: string, ): Promise { - if (!api) { - throw new Error("No widget api given"); - } - const response = await api.downloadFile(src); const file = response.file; diff --git a/src/ClientContext.tsx b/src/ClientContext.tsx index 1488965ac..7059cd693 100644 --- a/src/ClientContext.tsx +++ b/src/ClientContext.tsx @@ -48,7 +48,7 @@ export type ValidClientState = { disconnected: boolean; supportedFeatures: { reactions: boolean; - thumbnails: boolean; + authenticatedMedia: boolean; }; setClient: (client: MatrixClient, session: Session) => void; }; @@ -249,7 +249,8 @@ export const ClientProvider: FC = ({ children }) => { const [isDisconnected, setIsDisconnected] = useState(false); const [supportsReactions, setSupportsReactions] = useState(false); - const [supportsThumbnails, setSupportsThumbnails] = useState(false); + const [supportsAuthenticatedMedia, setSupportsAuthenticatedMedia] = + useState(false); const state: ClientState | undefined = useMemo(() => { if (alreadyOpenedErr) { @@ -275,7 +276,7 @@ export const ClientProvider: FC = ({ children }) => { disconnected: isDisconnected, supportedFeatures: { reactions: supportsReactions, - thumbnails: supportsThumbnails, + authenticatedMedia: supportsAuthenticatedMedia, }, }; }, [ @@ -286,7 +287,7 @@ export const ClientProvider: FC = ({ children }) => { setClient, isDisconnected, supportsReactions, - supportsThumbnails, + supportsAuthenticatedMedia, ]); const onSync = useCallback( @@ -312,8 +313,8 @@ export const ClientProvider: FC = ({ children }) => { } if (initClientState.widgetApi) { - // There is currently no widget API for authenticated media thumbnails. - setSupportsThumbnails(false); + // There is currently no way for widgets to request authenticated media directly from the server. + setSupportsAuthenticatedMedia(false); const reactSend = initClientState.widgetApi.hasCapability( "org.matrix.msc2762.send.event:m.reaction", ); @@ -335,7 +336,7 @@ export const ClientProvider: FC = ({ children }) => { } } else { setSupportsReactions(true); - setSupportsThumbnails(true); + setSupportsAuthenticatedMedia(true); } return (): void => { diff --git a/src/settings/useSubmitRageshake.test.tsx b/src/settings/useSubmitRageshake.test.tsx index b278d4b1c..d69255e03 100644 --- a/src/settings/useSubmitRageshake.test.tsx +++ b/src/settings/useSubmitRageshake.test.tsx @@ -78,7 +78,7 @@ function renderWithMockClient( disconnected: false, supportedFeatures: { reactions: true, - thumbnails: true, + authenticatedMedia: true, }, setClient: vi.fn(), authenticated: { From 143b560b20e46ca87b7cd802198d6ec12e65009a Mon Sep 17 00:00:00 2001 From: Valere Date: Tue, 10 Mar 2026 09:05:05 +0100 Subject: [PATCH 350/748] Add a playwright test to ensure object fit is correct --- playwright/widget/huddle-call.test.ts | 2 +- playwright/widget/pip-call.test.ts | 74 +++++++++++++++++++++++++++ playwright/widget/test-helpers.ts | 12 +++++ 3 files changed, 87 insertions(+), 1 deletion(-) create mode 100644 playwright/widget/pip-call.test.ts diff --git a/playwright/widget/huddle-call.test.ts b/playwright/widget/huddle-call.test.ts index b42c0ab25..d4ba00068 100644 --- a/playwright/widget/huddle-call.test.ts +++ b/playwright/widget/huddle-call.test.ts @@ -60,7 +60,7 @@ widgetTest("Create and join a group call", async ({ addUser, browserName }) => { // The only way to know if it is muted or not is to look at the data-kind attribute.. const videoButton = frame.getByTestId("incall_videomute"); await expect(videoButton).toBeVisible(); - // video should be off by default in a voice call + // video should be on await expect(videoButton).toHaveAttribute("aria-label", /^Stop video$/); } diff --git a/playwright/widget/pip-call.test.ts b/playwright/widget/pip-call.test.ts new file mode 100644 index 000000000..49ebec524 --- /dev/null +++ b/playwright/widget/pip-call.test.ts @@ -0,0 +1,74 @@ +/* +Copyright 2026 Element Creations Ltd. + +SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial +Please see LICENSE in the repository root for full details. +*/ + +import { expect, test } from "@playwright/test"; + +import { widgetTest } from "../fixtures/widget-user.ts"; +import { HOST1, TestHelpers } from "./test-helpers.ts"; + +widgetTest("Put call in PIP", async ({ addUser, browserName }) => { + test.skip( + browserName === "firefox", + "The is test is not working on firefox CI environment. No mic/audio device inputs so cam/mic are disabled", + ); + + test.slow(); + + const valere = await addUser("Valere", HOST1); + const timo = await addUser("Timo", HOST1); + + const callRoom = "TeamRoom"; + await TestHelpers.createRoom(callRoom, valere.page, [timo.mxId]); + + await TestHelpers.createRoom("DoubleTask", valere.page); + + await TestHelpers.acceptRoomInvite(callRoom, timo.page); + + await TestHelpers.switchToRoomNamed(valere.page, callRoom); + + // Start the call as Valere + await TestHelpers.startCallInCurrentRoom(valere.page, false); + await expect( + valere.page.locator('iframe[title="Element Call"]'), + ).toBeVisible(); + + await TestHelpers.joinCallFromLobby(valere.page); + + await TestHelpers.joinCallInCurrentRoom(timo.page); + + { + const frame = timo.page + .locator('iframe[title="Element Call"]') + .contentFrame(); + + const videoButton = frame.getByTestId("incall_videomute"); + await expect(videoButton).toBeVisible(); + // check that the video is on + await expect(videoButton).toHaveAttribute("aria-label", /^Stop video$/); + } + + // Switch to the other room, the call should go to PIP + await TestHelpers.switchToRoomNamed(valere.page, "DoubleTask"); + + // We should see the PIP overlay + await expect(valere.page.locator(".mx_WidgetPip_overlay")).toBeVisible(); + + { + // wait a bit so that the PIP has rendered the video + await valere.page.waitForTimeout(600); + + // Check for a bug where the video had the wrong fit in PIP + const frame = valere.page + .locator('iframe[title="Element Call"]') + .contentFrame(); + const videoElements = await frame.locator("video").all(); + expect(videoElements.length).toBe(1); + + const pipVideo = videoElements[0]; + await expect(pipVideo).toHaveCSS("object-fit", "cover"); + } +}); diff --git a/playwright/widget/test-helpers.ts b/playwright/widget/test-helpers.ts index 6fe4479be..4562ba5a1 100644 --- a/playwright/widget/test-helpers.ts +++ b/playwright/widget/test-helpers.ts @@ -276,4 +276,16 @@ export class TestHelpers { }); } } + + /** + * Switches to a room in the room list by its name. + * @param page - The EW page + * @param roomName - The name of the room to switch to + */ + public static async switchToRoomNamed( + page: Page, + roomName: string, + ): Promise { + await page.getByRole("option", { name: `Open room ${roomName}` }).click(); + } } From 8db1c4c37016092b17e0ed281d63234cb9253751 Mon Sep 17 00:00:00 2001 From: Timo K Date: Wed, 4 Mar 2026 16:47:15 +0100 Subject: [PATCH 351/748] Implement new Pip Layout (with control buttons) --- src/button/Button.tsx | 9 ++++- src/room/InCallView.module.css | 43 +++++++++++++----------- src/room/InCallView.tsx | 14 +++++++- src/state/CallViewModel/CallViewModel.ts | 2 +- src/state/PipLayout.ts | 3 +- 5 files changed, 48 insertions(+), 23 deletions(-) diff --git a/src/button/Button.tsx b/src/button/Button.tsx index 3136e2da2..4bb0058de 100644 --- a/src/button/Button.tsx +++ b/src/button/Button.tsx @@ -23,6 +23,7 @@ import styles from "./Button.module.css"; interface MicButtonProps extends ComponentPropsWithoutRef<"button"> { muted: boolean; + size: "sm" | "lg"; } export const MicButton: FC = ({ muted, ...props }) => { @@ -47,6 +48,7 @@ export const MicButton: FC = ({ muted, ...props }) => { interface VideoButtonProps extends ComponentPropsWithoutRef<"button"> { muted: boolean; + size: "sm" | "lg"; } export const VideoButton: FC = ({ muted, ...props }) => { @@ -71,6 +73,7 @@ export const VideoButton: FC = ({ muted, ...props }) => { interface ShareScreenButtonProps extends ComponentPropsWithoutRef<"button"> { enabled: boolean; + size: "sm" | "lg"; } export const ShareScreenButton: FC = ({ @@ -94,7 +97,11 @@ export const ShareScreenButton: FC = ({ ); }; -export const EndCallButton: FC> = ({ +interface EndCallButtonProps extends ComponentPropsWithoutRef<"button"> { + size: "sm" | "lg"; +} + +export const EndCallButton: FC = ({ className, ...props }) => { diff --git a/src/room/InCallView.module.css b/src/room/InCallView.module.css index 55724932d..70f7c73a4 100644 --- a/src/room/InCallView.module.css +++ b/src/room/InCallView.module.css @@ -108,22 +108,9 @@ Please see LICENSE in the repository root for full details. } } -@media (max-width: 370px) { - .shareScreen { - display: none; - } - - @media (max-height: 400px) { - .footer { - display: none; - } - } -} - -@media (max-width: 320px) { - .invite, - .raiseHand { - display: none; +@media (max-height: 800px) { + .footer { + padding-block: var(--cpd-space-8x); } } @@ -133,9 +120,27 @@ Please see LICENSE in the repository root for full details. } } -@media (max-height: 800px) { - .footer { - padding-block: var(--cpd-space-8x); +@media (max-width: 370px) { + .shareScreen { + display: none; + } + + /* PIP custom css */ + @media (max-height: 400px) { + .shareScreen { + display: flex; + } + .footer { + padding-block-start: var(--cpd-space-3x); + padding-block-end: var(--cpd-space-2x); + } + } +} + +@media (max-width: 320px) { + .invite, + .raiseHand { + display: none; } } diff --git a/src/room/InCallView.tsx b/src/room/InCallView.tsx index d8803b22e..f1a872a08 100644 --- a/src/room/InCallView.tsx +++ b/src/room/InCallView.tsx @@ -640,8 +640,10 @@ export const InCallView: FC = ({ const buttons: JSX.Element[] = []; + const buttonSize = layout.type === "pip" ? "sm" : "lg"; buttons.push( = ({ data-testid="incall_mute" />, = ({ if (vm.toggleScreenSharing !== null) { buttons.push( = ({ if (supportsReactions) { buttons.push( = ({ ); } if (layout.type !== "pip") - buttons.push(); + buttons.push( + , + ); buttons.push( { switch (mode) { case "pip": - return of(false); + return of(true); case "normal": case "narrow": return of(true); diff --git a/src/state/PipLayout.ts b/src/state/PipLayout.ts index 56e9aeb22..25a84e949 100644 --- a/src/state/PipLayout.ts +++ b/src/state/PipLayout.ts @@ -16,7 +16,8 @@ export function pipLayout( prevTiles: TileStore, ): [PipLayout, TileStore] { const update = prevTiles.from(0); - update.registerSpotlight(media.spotlight, true); + // Dont maximise in pip since we want the rounded corners and the footer + update.registerSpotlight(media.spotlight, false); const tiles = update.build(); return [ { From 38382539ad22e6e920a001c8b284e0548f876df2 Mon Sep 17 00:00:00 2001 From: Timo K Date: Mon, 9 Mar 2026 13:42:28 +0100 Subject: [PATCH 352/748] fix lints --- src/button/Button.tsx | 7 ++++--- src/button/ReactionToggleButton.tsx | 1 + 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/src/button/Button.tsx b/src/button/Button.tsx index 4bb0058de..51fc0a1f4 100644 --- a/src/button/Button.tsx +++ b/src/button/Button.tsx @@ -121,9 +121,10 @@ export const EndCallButton: FC = ({ ); }; -export const SettingsButton: FC> = ( - props, -) => { +interface SettingsButtonProps extends ComponentPropsWithoutRef<"button"> { + size: "sm" | "lg"; +} +export const SettingsButton: FC = (props) => { const { t } = useTranslation(); return ( diff --git a/src/button/ReactionToggleButton.tsx b/src/button/ReactionToggleButton.tsx index 0c722bafa..3e8f647fa 100644 --- a/src/button/ReactionToggleButton.tsx +++ b/src/button/ReactionToggleButton.tsx @@ -166,6 +166,7 @@ export function ReactionPopupMenu({ interface ReactionToggleButtonProps extends ComponentPropsWithoutRef<"button"> { identifier: string; vm: CallViewModel; + size: "sm" | "lg"; } export function ReactionToggleButton({ From 273eedd256816599bd6b03063aaa4311941a20e6 Mon Sep 17 00:00:00 2001 From: Timo K Date: Mon, 9 Mar 2026 13:42:47 +0100 Subject: [PATCH 353/748] keep pip as it was before on mobile --- src/state/CallViewModel/CallViewModel.ts | 4 ++-- src/state/PipLayout.ts | 8 ++++++-- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/src/state/CallViewModel/CallViewModel.ts b/src/state/CallViewModel/CallViewModel.ts index 9a9ac11cc..18e49d0a9 100644 --- a/src/state/CallViewModel/CallViewModel.ts +++ b/src/state/CallViewModel/CallViewModel.ts @@ -63,7 +63,7 @@ import { playReactionsSound, showReactions, } from "../../settings/settings"; -import { isFirefox } from "../../Platform"; +import { isFirefox, platform } from "../../Platform"; import { setPipEnabled$ } from "../../controls"; import { TileStore } from "../TileStore"; import { gridLikeLayout } from "../GridLikeLayout"; @@ -1271,7 +1271,7 @@ export function createCallViewModel$( switchMap((mode) => { switch (mode) { case "pip": - return of(true); + return of(platform === "desktop" ? true : false); case "normal": case "narrow": return of(true); diff --git a/src/state/PipLayout.ts b/src/state/PipLayout.ts index 25a84e949..6ac1e4f02 100644 --- a/src/state/PipLayout.ts +++ b/src/state/PipLayout.ts @@ -5,6 +5,7 @@ SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial Please see LICENSE in the repository root for full details. */ +import { platform } from "../Platform.ts"; import { type PipLayout, type PipLayoutMedia } from "./layout-types.ts"; import { type TileStore } from "./TileStore"; @@ -16,8 +17,11 @@ export function pipLayout( prevTiles: TileStore, ): [PipLayout, TileStore] { const update = prevTiles.from(0); - // Dont maximise in pip since we want the rounded corners and the footer - update.registerSpotlight(media.spotlight, false); + // Dont maximise in pip on EW since we want the rounded corners and the footer + update.registerSpotlight( + media.spotlight, + platform === "desktop" ? false : true, + ); const tiles = update.build(); return [ { From 54bef07b3b895ee391928460d5a9cf98eed5a40b Mon Sep 17 00:00:00 2001 From: Timo K Date: Mon, 9 Mar 2026 14:40:13 +0100 Subject: [PATCH 354/748] linter --- src/button/Button.tsx | 8 ++++---- src/button/ReactionToggleButton.tsx | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/button/Button.tsx b/src/button/Button.tsx index 51fc0a1f4..00d803f1f 100644 --- a/src/button/Button.tsx +++ b/src/button/Button.tsx @@ -23,7 +23,7 @@ import styles from "./Button.module.css"; interface MicButtonProps extends ComponentPropsWithoutRef<"button"> { muted: boolean; - size: "sm" | "lg"; + size?: "sm" | "lg"; } export const MicButton: FC = ({ muted, ...props }) => { @@ -48,7 +48,7 @@ export const MicButton: FC = ({ muted, ...props }) => { interface VideoButtonProps extends ComponentPropsWithoutRef<"button"> { muted: boolean; - size: "sm" | "lg"; + size?: "sm" | "lg"; } export const VideoButton: FC = ({ muted, ...props }) => { @@ -98,7 +98,7 @@ export const ShareScreenButton: FC = ({ }; interface EndCallButtonProps extends ComponentPropsWithoutRef<"button"> { - size: "sm" | "lg"; + size?: "sm" | "lg"; } export const EndCallButton: FC = ({ @@ -122,7 +122,7 @@ export const EndCallButton: FC = ({ }; interface SettingsButtonProps extends ComponentPropsWithoutRef<"button"> { - size: "sm" | "lg"; + size?: "sm" | "lg"; } export const SettingsButton: FC = (props) => { const { t } = useTranslation(); diff --git a/src/button/ReactionToggleButton.tsx b/src/button/ReactionToggleButton.tsx index 3e8f647fa..28163321c 100644 --- a/src/button/ReactionToggleButton.tsx +++ b/src/button/ReactionToggleButton.tsx @@ -166,7 +166,7 @@ export function ReactionPopupMenu({ interface ReactionToggleButtonProps extends ComponentPropsWithoutRef<"button"> { identifier: string; vm: CallViewModel; - size: "sm" | "lg"; + size?: "sm" | "lg"; } export function ReactionToggleButton({ From 6485da8fff9fbd5c2957f327b251c914d91b2deb Mon Sep 17 00:00:00 2001 From: Timo K Date: Tue, 10 Mar 2026 15:17:41 +0100 Subject: [PATCH 355/748] add playwright tests for new pip layout --- .../pip-call-button-interaction.test.ts | 71 +++++++++++++++++++ 1 file changed, 71 insertions(+) create mode 100644 playwright/widget/pip-call-button-interaction.test.ts diff --git a/playwright/widget/pip-call-button-interaction.test.ts b/playwright/widget/pip-call-button-interaction.test.ts new file mode 100644 index 000000000..776596725 --- /dev/null +++ b/playwright/widget/pip-call-button-interaction.test.ts @@ -0,0 +1,71 @@ +/* +Copyright 2026 Element Creations Ltd. + +SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial +Please see LICENSE in the repository root for full details. +*/ + +import { expect, test } from "@playwright/test"; + +import { widgetTest } from "../fixtures/widget-user.ts"; +import { HOST1, TestHelpers } from "./test-helpers.ts"; + +widgetTest( + "Footer interaction in PiP", + async ({ addUser, browserName, page }) => { + test.skip( + browserName === "firefox", + "The is test is not working on firefox CI environment. No mic/audio device inputs so cam/mic are disabled", + ); + + test.slow(); + + const valere = await addUser("Valere", HOST1); + + const callRoom = "CallRoom"; + await TestHelpers.createRoom("CallRoom", valere.page); + + await TestHelpers.createRoom("OtherRoom", valere.page); + + await TestHelpers.switchToRoomNamed(valere.page, callRoom); + + // Start the call as Valere + await TestHelpers.startCallInCurrentRoom(valere.page, false); + await expect( + valere.page.locator('iframe[title="Element Call"]'), + ).toBeVisible(); + + await TestHelpers.joinCallFromLobby(valere.page); + // wait a bit so that the PIP has rendered + await valere.page.waitForTimeout(600); + + // Switch to the other room, the call should go to PIP + await TestHelpers.switchToRoomNamed(valere.page, "OtherRoom"); + + // We should see the PIP overlay + const iFrame = valere.page + .locator('iframe[title="Element Call"]') + .contentFrame(); + + { + // Check for a bug where the video had the wrong fit in PIP + const hangupButton = iFrame.getByRole("button", { name: "End call" }); + const videoMuteButton = iFrame.getByRole("button", { + name: "Stop video", + }); + const audioMuteButton = iFrame.getByRole("button", { + name: "Mute microphone", + }); + await expect(hangupButton).toBeVisible(); + await expect(videoMuteButton).toBeVisible(); + await expect(audioMuteButton).toBeVisible(); + + // TODO once we have the EW version that supports the interactive pip element we can activate those checks + // await videoMuteButton.click(); + // await audioMuteButton.click(); + + // await expect(videoMuteButton).toHaveCSS("disabled", "true"); + // await expect(audioMuteButton).toHaveCSS("disabled", "true"); + } + }, +); From 1e400bc5502bee7f46e6a658fe55cb39cc34c369 Mon Sep 17 00:00:00 2001 From: Timo K Date: Tue, 10 Mar 2026 18:26:12 +0100 Subject: [PATCH 356/748] remove unsused import --- .../pip-call-button-interaction.test.ts | 93 +++++++++---------- 1 file changed, 45 insertions(+), 48 deletions(-) diff --git a/playwright/widget/pip-call-button-interaction.test.ts b/playwright/widget/pip-call-button-interaction.test.ts index 776596725..84cee3faf 100644 --- a/playwright/widget/pip-call-button-interaction.test.ts +++ b/playwright/widget/pip-call-button-interaction.test.ts @@ -10,62 +10,59 @@ import { expect, test } from "@playwright/test"; import { widgetTest } from "../fixtures/widget-user.ts"; import { HOST1, TestHelpers } from "./test-helpers.ts"; -widgetTest( - "Footer interaction in PiP", - async ({ addUser, browserName, page }) => { - test.skip( - browserName === "firefox", - "The is test is not working on firefox CI environment. No mic/audio device inputs so cam/mic are disabled", - ); +widgetTest("Footer interaction in PiP", async ({ addUser, browserName }) => { + test.skip( + browserName === "firefox", + "The is test is not working on firefox CI environment. No mic/audio device inputs so cam/mic are disabled", + ); - test.slow(); + test.slow(); - const valere = await addUser("Valere", HOST1); + const valere = await addUser("Valere", HOST1); + await valere.page.pause(); + const callRoom = "CallRoom"; + await TestHelpers.createRoom("CallRoom", valere.page); - const callRoom = "CallRoom"; - await TestHelpers.createRoom("CallRoom", valere.page); + await TestHelpers.createRoom("OtherRoom", valere.page); - await TestHelpers.createRoom("OtherRoom", valere.page); + await TestHelpers.switchToRoomNamed(valere.page, callRoom); - await TestHelpers.switchToRoomNamed(valere.page, callRoom); + // Start the call as Valere + await TestHelpers.startCallInCurrentRoom(valere.page, false); + await expect( + valere.page.locator('iframe[title="Element Call"]'), + ).toBeVisible(); - // Start the call as Valere - await TestHelpers.startCallInCurrentRoom(valere.page, false); - await expect( - valere.page.locator('iframe[title="Element Call"]'), - ).toBeVisible(); + await TestHelpers.joinCallFromLobby(valere.page); + // wait a bit so that the PIP has rendered + await valere.page.waitForTimeout(600); - await TestHelpers.joinCallFromLobby(valere.page); - // wait a bit so that the PIP has rendered - await valere.page.waitForTimeout(600); + // Switch to the other room, the call should go to PIP + await TestHelpers.switchToRoomNamed(valere.page, "OtherRoom"); - // Switch to the other room, the call should go to PIP - await TestHelpers.switchToRoomNamed(valere.page, "OtherRoom"); + // We should see the PIP overlay + const iFrame = valere.page + .locator('iframe[title="Element Call"]') + .contentFrame(); - // We should see the PIP overlay - const iFrame = valere.page - .locator('iframe[title="Element Call"]') - .contentFrame(); + { + // Check for a bug where the video had the wrong fit in PIP + const hangupButton = iFrame.getByRole("button", { name: "End call" }); + const videoMuteButton = iFrame.getByRole("button", { + name: "Stop video", + }); + const audioMuteButton = iFrame.getByRole("button", { + name: "Mute microphone", + }); + await expect(hangupButton).toBeVisible(); + await expect(videoMuteButton).toBeVisible(); + await expect(audioMuteButton).toBeVisible(); - { - // Check for a bug where the video had the wrong fit in PIP - const hangupButton = iFrame.getByRole("button", { name: "End call" }); - const videoMuteButton = iFrame.getByRole("button", { - name: "Stop video", - }); - const audioMuteButton = iFrame.getByRole("button", { - name: "Mute microphone", - }); - await expect(hangupButton).toBeVisible(); - await expect(videoMuteButton).toBeVisible(); - await expect(audioMuteButton).toBeVisible(); + // TODO once we have the EW version that supports the interactive pip element we can activate those checks + // await videoMuteButton.click(); + // await audioMuteButton.click(); - // TODO once we have the EW version that supports the interactive pip element we can activate those checks - // await videoMuteButton.click(); - // await audioMuteButton.click(); - - // await expect(videoMuteButton).toHaveCSS("disabled", "true"); - // await expect(audioMuteButton).toHaveCSS("disabled", "true"); - } - }, -); + // await expect(videoMuteButton).toHaveCSS("disabled", "true"); + // await expect(audioMuteButton).toHaveCSS("disabled", "true"); + } +}); From c9557e91d5453a2085b5c62c034eb6aa5346bafc Mon Sep 17 00:00:00 2001 From: fkwp Date: Wed, 11 Mar 2026 13:06:20 +0100 Subject: [PATCH 357/748] fix: add id-token permission as its required by tailscale login (part 3) (#3793) * Push docker images to oci.element.io * prettier * add id-token permission as its required by tailscale login * pass secrets to reusable workflows --- .github/workflows/build.yaml | 1 + .github/workflows/pr-deploy.yaml | 1 + .github/workflows/publish.yaml | 1 + 3 files changed, 3 insertions(+) diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index 4f9e80f2b..32ce25c98 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -51,6 +51,7 @@ jobs: packages: write id-token: write uses: ./.github/workflows/build-and-publish-docker.yaml + secrets: inherit with: artifact_run_id: ${{ github.run_id }} docker_tags: | diff --git a/.github/workflows/pr-deploy.yaml b/.github/workflows/pr-deploy.yaml index 62b37acae..138ab2b5f 100644 --- a/.github/workflows/pr-deploy.yaml +++ b/.github/workflows/pr-deploy.yaml @@ -62,6 +62,7 @@ jobs: packages: write id-token: write uses: ./.github/workflows/build-and-publish-docker.yaml + secrets: inherit with: artifact_run_id: ${{ github.event.workflow_run.id || github.run_id }} docker_tags: | diff --git a/.github/workflows/publish.yaml b/.github/workflows/publish.yaml index ade91019d..ceedf7813 100644 --- a/.github/workflows/publish.yaml +++ b/.github/workflows/publish.yaml @@ -57,6 +57,7 @@ jobs: packages: write id-token: write uses: ./.github/workflows/build-and-publish-docker.yaml + secrets: inherit with: artifact_run_id: ${{ github.event.workflow_run.id || github.run_id }} docker_tags: | From 3a9d3945293f8baea4f698353cec42c602c765fd Mon Sep 17 00:00:00 2001 From: Timo K Date: Wed, 11 Mar 2026 14:05:09 +0100 Subject: [PATCH 358/748] activate click tests --- playwright/widget/pip-call-button-interaction.test.ts | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/playwright/widget/pip-call-button-interaction.test.ts b/playwright/widget/pip-call-button-interaction.test.ts index 84cee3faf..a646db2f1 100644 --- a/playwright/widget/pip-call-button-interaction.test.ts +++ b/playwright/widget/pip-call-button-interaction.test.ts @@ -58,11 +58,10 @@ widgetTest("Footer interaction in PiP", async ({ addUser, browserName }) => { await expect(videoMuteButton).toBeVisible(); await expect(audioMuteButton).toBeVisible(); - // TODO once we have the EW version that supports the interactive pip element we can activate those checks - // await videoMuteButton.click(); - // await audioMuteButton.click(); + await videoMuteButton.click(); + await audioMuteButton.click(); - // await expect(videoMuteButton).toHaveCSS("disabled", "true"); - // await expect(audioMuteButton).toHaveCSS("disabled", "true"); + await expect(videoMuteButton).toHaveCSS("disabled", "true"); + await expect(audioMuteButton).toHaveCSS("disabled", "true"); } }); From 41f7b643fb1a91ca32d144c53d6dec6831e5e04c Mon Sep 17 00:00:00 2001 From: fkwp Date: Wed, 11 Mar 2026 14:20:05 +0100 Subject: [PATCH 359/748] Add zizmor checks on CI (#3792) * zizmor auto fixes * add github action for security analysis with zizmor * add access token to iOS push action --- .../workflows/build-and-publish-docker.yaml | 2 + .github/workflows/build-element-call.yaml | 2 + .github/workflows/deploy-to-netlify.yaml | 10 ++- .github/workflows/lint.yaml | 2 + .../workflows/publish-embedded-packages.yaml | 69 +++++++++++++------ .github/workflows/publish.yaml | 4 +- .github/workflows/test.yaml | 4 ++ .github/workflows/translations-download.yaml | 2 + .github/workflows/translations-upload.yaml | 2 + .github/workflows/zizmor.yml | 23 +++++++ 10 files changed, 93 insertions(+), 27 deletions(-) create mode 100644 .github/workflows/zizmor.yml diff --git a/.github/workflows/build-and-publish-docker.yaml b/.github/workflows/build-and-publish-docker.yaml index 6e8f01f54..65d499f75 100644 --- a/.github/workflows/build-and-publish-docker.yaml +++ b/.github/workflows/build-and-publish-docker.yaml @@ -25,6 +25,8 @@ jobs: steps: - name: Check it out uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 + with: + persist-credentials: false - name: 📥 Download artifact uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4 diff --git a/.github/workflows/build-element-call.yaml b/.github/workflows/build-element-call.yaml index 4ca5ccade..300138e0a 100644 --- a/.github/workflows/build-element-call.yaml +++ b/.github/workflows/build-element-call.yaml @@ -33,6 +33,8 @@ jobs: steps: - name: Checkout code uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 + with: + persist-credentials: false - name: Enable Corepack run: corepack enable - name: Yarn cache diff --git a/.github/workflows/deploy-to-netlify.yaml b/.github/workflows/deploy-to-netlify.yaml index 3f964ad47..766093289 100644 --- a/.github/workflows/deploy-to-netlify.yaml +++ b/.github/workflows/deploy-to-netlify.yaml @@ -63,11 +63,15 @@ jobs: - name: Add config file run: | - if [ "${{ inputs.package }}" = "full" ]; then - curl -s "https://raw.githubusercontent.com/${{ inputs.pr_head_full_name }}/${{ inputs.pr_head_ref }}/config/config_netlify_preview.json" > webapp/config.json + if [ "${INPUTS_PACKAGE}" = "full" ]; then + curl -s "https://raw.githubusercontent.com/${INPUTS_PR_HEAD_FULL_NAME}/${INPUTS_PR_HEAD_REF}/config/config_netlify_preview.json" > webapp/config.json else - curl -s "https://raw.githubusercontent.com/${{ inputs.pr_head_full_name }}/${{ inputs.pr_head_ref }}/config/config_netlify_preview_sdk.json" > webapp/config.json + curl -s "https://raw.githubusercontent.com/${INPUTS_PR_HEAD_FULL_NAME}/${INPUTS_PR_HEAD_REF}/config/config_netlify_preview_sdk.json" > webapp/config.json fi + env: + INPUTS_PACKAGE: ${{ inputs.package }} + INPUTS_PR_HEAD_FULL_NAME: ${{ inputs.pr_head_full_name }} + INPUTS_PR_HEAD_REF: ${{ inputs.pr_head_ref }} - name: ☁️ Deploy to Netlify id: netlify uses: nwtgck/actions-netlify@4cbaf4c08f1a7bfa537d6113472ef4424e4eb654 # v3.0 diff --git a/.github/workflows/lint.yaml b/.github/workflows/lint.yaml index 32dde8690..763d2eacb 100644 --- a/.github/workflows/lint.yaml +++ b/.github/workflows/lint.yaml @@ -8,6 +8,8 @@ jobs: steps: - name: Checkout code uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 + with: + persist-credentials: false - name: Enable Corepack run: corepack enable - name: Yarn cache diff --git a/.github/workflows/publish-embedded-packages.yaml b/.github/workflows/publish-embedded-packages.yaml index fc8a640fa..1c6cd7b1c 100644 --- a/.github/workflows/publish-embedded-packages.yaml +++ b/.github/workflows/publish-embedded-packages.yaml @@ -71,7 +71,9 @@ jobs: contents: write # required to upload release asset steps: - name: Determine filename - run: echo "FILENAME_PREFIX=element-call-embedded-${{ needs.versioning.outputs.UNPREFIXED_VERSION }}" >> "$GITHUB_ENV" + run: echo "FILENAME_PREFIX=element-call-embedded-${NEEDS_VERSIONING_OUTPUTS_UNPREFIXED_VERSION}" >> "$GITHUB_ENV" + env: + NEEDS_VERSIONING_OUTPUTS_UNPREFIXED_VERSION: ${{ needs.versioning.outputs.UNPREFIXED_VERSION }} - name: 📥 Download built element-call artifact uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4 with: @@ -80,9 +82,9 @@ jobs: name: build-output-embedded path: ${{ env.FILENAME_PREFIX}} - name: Create Tarball - run: tar --numeric-owner -cvzf ${{ env.FILENAME_PREFIX }}.tar.gz ${{ env.FILENAME_PREFIX }} + run: tar --numeric-owner -cvzf ${FILENAME_PREFIX}.tar.gz ${FILENAME_PREFIX} - name: Create Checksum - run: find ${{ env.FILENAME_PREFIX }} -type f -print0 | sort -z | xargs -0 sha256sum | tee ${{ env.FILENAME_PREFIX }}.sha256 + run: find ${FILENAME_PREFIX} -type f -print0 | sort -z | xargs -0 sha256sum | tee ${FILENAME_PREFIX}.sha256 - name: Upload if: ${{ needs.versioning.outputs.DRY_RUN == 'false' }} uses: softprops/action-gh-release@a06a81a03ee405af7f2048a818ed3f03bbf83c7b # v2 @@ -104,6 +106,8 @@ jobs: steps: - name: Checkout uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 + with: + persist-credentials: false - name: 📥 Download built element-call artifact uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4 @@ -123,13 +127,16 @@ jobs: - name: Publish npm working-directory: embedded/web run: | - npm version ${{ needs.versioning.outputs.PREFIXED_VERSION }} --no-git-tag-version + npm version ${NEEDS_VERSIONING_OUTPUTS_PREFIXED_VERSION} --no-git-tag-version echo "ARTIFACT_VERSION=$(jq '.version' --raw-output package.json)" >> "$GITHUB_ENV" - npm publish --provenance --access public --tag ${{ needs.versioning.outputs.TAG }} ${{ needs.versioning.outputs.DRY_RUN == 'true' && '--dry-run' || '' }} + npm publish --provenance --access public --tag ${NEEDS_VERSIONING_OUTPUTS_TAG} ${{ needs.versioning.outputs.DRY_RUN == 'true' && '--dry-run' || '' }} + env: + NEEDS_VERSIONING_OUTPUTS_PREFIXED_VERSION: ${{ needs.versioning.outputs.PREFIXED_VERSION }} + NEEDS_VERSIONING_OUTPUTS_TAG: ${{ needs.versioning.outputs.TAG }} - id: artifact_version name: Output artifact version - run: echo "ARTIFACT_VERSION=${{env.ARTIFACT_VERSION}}" >> "$GITHUB_OUTPUT" + run: echo "ARTIFACT_VERSION=${ARTIFACT_VERSION}" >> "$GITHUB_OUTPUT" publish_android: needs: [build_element_call, versioning] @@ -143,6 +150,8 @@ jobs: steps: - name: Checkout uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 + with: + persist-credentials: false - name: 📥 Download built element-call artifact uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4 @@ -161,16 +170,19 @@ jobs: - name: Get artifact version # Anything that is not a final release will be tagged as a snapshot run: | - if [[ "${{ needs.versioning.outputs.TAG }}" == "latest" ]]; then - echo "ARTIFACT_VERSION=${{ needs.versioning.outputs.UNPREFIXED_VERSION }}" >> "$GITHUB_ENV" - elif [[ "${{ needs.versioning.outputs.TAG }}" == "rc" ]]; then - echo "ARTIFACT_VERSION=${{ needs.versioning.outputs.UNPREFIXED_VERSION }}" >> "$GITHUB_ENV" + if [[ "${NEEDS_VERSIONING_OUTPUTS_TAG}" == "latest" ]]; then + echo "ARTIFACT_VERSION=${NEEDS_VERSIONING_OUTPUTS_UNPREFIXED_VERSION}" >> "$GITHUB_ENV" + elif [[ "${NEEDS_VERSIONING_OUTPUTS_TAG}" == "rc" ]]; then + echo "ARTIFACT_VERSION=${NEEDS_VERSIONING_OUTPUTS_UNPREFIXED_VERSION}" >> "$GITHUB_ENV" else - echo "ARTIFACT_VERSION=${{ needs.versioning.outputs.UNPREFIXED_VERSION }}-SNAPSHOT" >> "$GITHUB_ENV" + echo "ARTIFACT_VERSION=${NEEDS_VERSIONING_OUTPUTS_UNPREFIXED_VERSION}-SNAPSHOT" >> "$GITHUB_ENV" fi + env: + NEEDS_VERSIONING_OUTPUTS_TAG: ${{ needs.versioning.outputs.TAG }} + NEEDS_VERSIONING_OUTPUTS_UNPREFIXED_VERSION: ${{ needs.versioning.outputs.UNPREFIXED_VERSION }} - name: Set version string - run: sed -i "s/0.0.0/${{ env.ARTIFACT_VERSION }}/g" embedded/android/lib/src/main/kotlin/io/element/android/call/embedded/Version.kt + run: sed -i "s/0.0.0/${ARTIFACT_VERSION}/g" embedded/android/lib/src/main/kotlin/io/element/android/call/embedded/Version.kt - name: Publish AAR working-directory: embedded/android @@ -184,7 +196,7 @@ jobs: - id: artifact_version name: Output artifact version - run: echo "ARTIFACT_VERSION=${{env.ARTIFACT_VERSION}}" >> "$GITHUB_OUTPUT" + run: echo "ARTIFACT_VERSION=${ARTIFACT_VERSION}" >> "$GITHUB_OUTPUT" publish_ios: needs: [build_element_call, versioning] @@ -200,6 +212,7 @@ jobs: uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 with: path: element-call + persist-credentials: false - name: 📥 Download built element-call artifact uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4 @@ -215,15 +228,18 @@ jobs: repository: element-hq/element-call-swift path: element-call-swift token: ${{ secrets.SWIFT_RELEASE_TOKEN }} + persist-credentials: false - name: Copy files run: rsync -a --delete --exclude .git element-call/embedded/ios/ element-call-swift - name: Get artifact version - run: echo "ARTIFACT_VERSION=${{ needs.versioning.outputs.UNPREFIXED_VERSION }}" >> "$GITHUB_ENV" + run: echo "ARTIFACT_VERSION=${NEEDS_VERSIONING_OUTPUTS_UNPREFIXED_VERSION}" >> "$GITHUB_ENV" + env: + NEEDS_VERSIONING_OUTPUTS_UNPREFIXED_VERSION: ${{ needs.versioning.outputs.UNPREFIXED_VERSION }} - name: Set version string - run: sed -i "s/0.0.0/${{ env.ARTIFACT_VERSION }}/g" element-call-swift/Sources/EmbeddedElementCall/EmbeddedElementCall.swift + run: sed -i "s/0.0.0/${ARTIFACT_VERSION}/g" element-call-swift/Sources/EmbeddedElementCall/EmbeddedElementCall.swift - name: Test build working-directory: element-call-swift @@ -235,17 +251,22 @@ jobs: git config --global user.email "ci@element.io" git config --global user.name "Element CI" git add -A - git commit -am "Release ${{ needs.versioning.outputs.PREFIXED_VERSION }}" - git tag -a ${{ env.ARTIFACT_VERSION }} -m "${{ github.event.release.html_url }}" + git commit -am "Release ${NEEDS_VERSIONING_OUTPUTS_PREFIXED_VERSION}" + git tag -a ${ARTIFACT_VERSION} -m "${GITHUB_EVENT_RELEASE_HTML_URL}" + env: + NEEDS_VERSIONING_OUTPUTS_PREFIXED_VERSION: ${{ needs.versioning.outputs.PREFIXED_VERSION }} + GITHUB_EVENT_RELEASE_HTML_URL: ${{ github.event.release.html_url }} - name: Push working-directory: element-call-swift run: | - git push --tags ${{ needs.versioning.outputs.DRY_RUN == 'true' && '--dry-run' || '' }} + git push "https://x-access-token:${SWIFT_RELEASE_TOKEN}@github.com/element-hq/element-call-swift.git" --tags ${{ needs.versioning.outputs.DRY_RUN == 'true' && '--dry-run' || '' }} + env: + SWIFT_RELEASE_TOKEN: ${{ secrets.SWIFT_RELEASE_TOKEN }} - id: artifact_version name: Output artifact version - run: echo "ARTIFACT_VERSION=${{env.ARTIFACT_VERSION}}" >> "$GITHUB_OUTPUT" + run: echo "ARTIFACT_VERSION=${ARTIFACT_VERSION}" >> "$GITHUB_OUTPUT" release_notes: needs: [versioning, publish_npm, publish_android, publish_ios] @@ -257,9 +278,13 @@ jobs: steps: - name: Log versions run: | - echo "NPM: ${{ needs.publish_npm.outputs.ARTIFACT_VERSION }}" - echo "Android: ${{ needs.publish_android.outputs.ARTIFACT_VERSION }}" - echo "iOS: ${{ needs.publish_ios.outputs.ARTIFACT_VERSION }}" + echo "NPM: ${NEEDS_PUBLISH_NPM_OUTPUTS_ARTIFACT_VERSION}" + echo "Android: ${NEEDS_PUBLISH_ANDROID_OUTPUTS_ARTIFACT_VERSION}" + echo "iOS: ${NEEDS_PUBLISH_IOS_OUTPUTS_ARTIFACT_VERSION}" + env: + NEEDS_PUBLISH_NPM_OUTPUTS_ARTIFACT_VERSION: ${{ needs.publish_npm.outputs.ARTIFACT_VERSION }} + NEEDS_PUBLISH_ANDROID_OUTPUTS_ARTIFACT_VERSION: ${{ needs.publish_android.outputs.ARTIFACT_VERSION }} + NEEDS_PUBLISH_IOS_OUTPUTS_ARTIFACT_VERSION: ${{ needs.publish_ios.outputs.ARTIFACT_VERSION }} - name: Add release notes if: ${{ needs.versioning.outputs.DRY_RUN == 'false' }} uses: softprops/action-gh-release@a06a81a03ee405af7f2048a818ed3f03bbf83c7b # v2 diff --git a/.github/workflows/publish.yaml b/.github/workflows/publish.yaml index ceedf7813..0675b1b1e 100644 --- a/.github/workflows/publish.yaml +++ b/.github/workflows/publish.yaml @@ -38,9 +38,9 @@ jobs: name: build-output-full path: ${{ env.FILENAME_PREFIX }} - name: Create Tarball - run: tar --numeric-owner --transform "s/dist/${{ env.FILENAME_PREFIX }}/" -cvzf ${{ env.FILENAME_PREFIX }}.tar.gz ${{ env.FILENAME_PREFIX }} + run: tar --numeric-owner --transform "s/dist/${FILENAME_PREFIX}/" -cvzf ${FILENAME_PREFIX}.tar.gz ${FILENAME_PREFIX} - name: Create Checksum - run: find ${{ env.FILENAME_PREFIX }} -type f -print0 | sort -z | xargs -0 sha256sum | tee ${{ env.FILENAME_PREFIX }}.sha256 + run: find ${FILENAME_PREFIX} -type f -print0 | sort -z | xargs -0 sha256sum | tee ${FILENAME_PREFIX}.sha256 - name: Upload uses: softprops/action-gh-release@a06a81a03ee405af7f2048a818ed3f03bbf83c7b # v2 with: diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml index 012de7cb8..cd1c94c56 100644 --- a/.github/workflows/test.yaml +++ b/.github/workflows/test.yaml @@ -10,6 +10,8 @@ jobs: steps: - name: Checkout code uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 + with: + persist-credentials: false - name: Enable Corepack run: corepack enable - name: Yarn cache @@ -34,6 +36,8 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 + with: + persist-credentials: false - name: Enable Corepack run: corepack enable - uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4 diff --git a/.github/workflows/translations-download.yaml b/.github/workflows/translations-download.yaml index 45f366cdd..ad9f46526 100644 --- a/.github/workflows/translations-download.yaml +++ b/.github/workflows/translations-download.yaml @@ -14,6 +14,8 @@ jobs: steps: - name: Checkout the code uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 + with: + persist-credentials: false - name: Enable Corepack run: corepack enable diff --git a/.github/workflows/translations-upload.yaml b/.github/workflows/translations-upload.yaml index 4c0625131..daf968958 100644 --- a/.github/workflows/translations-upload.yaml +++ b/.github/workflows/translations-upload.yaml @@ -15,6 +15,8 @@ jobs: steps: - name: Checkout the code uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 + with: + persist-credentials: false - name: Upload uses: localazy/upload@27e6b5c0fddf4551596b42226b1c24124335d24a # v1 diff --git a/.github/workflows/zizmor.yml b/.github/workflows/zizmor.yml new file mode 100644 index 000000000..612adbd14 --- /dev/null +++ b/.github/workflows/zizmor.yml @@ -0,0 +1,23 @@ +name: GitHub Actions Security Analysis with zizmor 🌈 + +on: + push: + branches: ["livekit", "full-mesh"] + pull_request: {} + +permissions: {} + +jobs: + zizmor: + name: Run zizmor 🌈 + runs-on: ubuntu-latest + permissions: + security-events: write # Required for upload-sarif (used by zizmor-action) to upload SARIF files. + steps: + - name: Checkout repository + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + with: + persist-credentials: false + + - name: Run zizmor 🌈 + uses: zizmorcore/zizmor-action@0dce2577a4760a2749d8cfb7a84b7d5585ebcb7d # v0.5.0 From 839c4dd7388640e2a7796bd5db3deefa326270b1 Mon Sep 17 00:00:00 2001 From: fkwp Date: Wed, 11 Mar 2026 15:17:12 +0100 Subject: [PATCH 360/748] fix: OCI image push to element registry (#3795) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Push docker images to oci.element.io * prettier * add id-token permission as its required by tailscale login * pass secrets to reusable workflows * change secret path team -> voip * Update .github/workflows/build-and-publish-docker.yaml Co-authored-by: Gaël Goinvic <97093369+gaelgatelement@users.noreply.github.com> --------- Co-authored-by: Gaël Goinvic <97093369+gaelgatelement@users.noreply.github.com> --- .github/workflows/build-and-publish-docker.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build-and-publish-docker.yaml b/.github/workflows/build-and-publish-docker.yaml index 65d499f75..a3a5cba77 100644 --- a/.github/workflows/build-and-publish-docker.yaml +++ b/.github/workflows/build-and-publish-docker.yaml @@ -68,8 +68,8 @@ jobs: jwtGithubAudience: https://vault.infra.ci.i.element.dev method: jwt secrets: | - services/-repositories/secret/data/oci.element.io username | OCI_USERNAME ; - services/-repositories/secret/data/oci.element.io password | OCI_PASSWORD ; + services/voip-repositories/secret/data/oci.element.io username | OCI_USERNAME ; + services/voip-repositories/secret/data/oci.element.io password | OCI_PASSWORD ; - name: Login to oci.element.io Registry uses: docker/login-action@c94ce9fb468520275223c153574b00df6fe4bcc9 # v3 From d00ff78d65ee7583578147e268bbf52c12106b5e Mon Sep 17 00:00:00 2001 From: Timo K Date: Wed, 11 Mar 2026 15:21:36 +0100 Subject: [PATCH 361/748] fix pip interaction test (button presses) --- .../pip-call-button-interaction.test.ts | 35 +++++++++++++------ 1 file changed, 24 insertions(+), 11 deletions(-) diff --git a/playwright/widget/pip-call-button-interaction.test.ts b/playwright/widget/pip-call-button-interaction.test.ts index a646db2f1..f798545d4 100644 --- a/playwright/widget/pip-call-button-interaction.test.ts +++ b/playwright/widget/pip-call-button-interaction.test.ts @@ -19,7 +19,7 @@ widgetTest("Footer interaction in PiP", async ({ addUser, browserName }) => { test.slow(); const valere = await addUser("Valere", HOST1); - await valere.page.pause(); + const callRoom = "CallRoom"; await TestHelpers.createRoom("CallRoom", valere.page); @@ -48,20 +48,33 @@ widgetTest("Footer interaction in PiP", async ({ addUser, browserName }) => { { // Check for a bug where the video had the wrong fit in PIP const hangupButton = iFrame.getByRole("button", { name: "End call" }); - const videoMuteButton = iFrame.getByRole("button", { - name: "Stop video", - }); - const audioMuteButton = iFrame.getByRole("button", { - name: "Mute microphone", - }); + const audioMuteButton = iFrame.getByTestId("incall_mute"); + const videoMuteButton = iFrame.getByTestId("incall_videomute"); await expect(hangupButton).toBeVisible(); - await expect(videoMuteButton).toBeVisible(); await expect(audioMuteButton).toBeVisible(); - + await expect(videoMuteButton).toBeVisible(); + await expect(audioMuteButton).toHaveCSS( + "background-color", + "rgb(255, 255, 255)", + ); + await expect(videoMuteButton).toHaveCSS( + "background-color", + "rgb(255, 255, 255)", + ); await videoMuteButton.click(); await audioMuteButton.click(); + // stop hovering on any of the buttons + await iFrame.getByTestId("videoTile").hover(); + await valere.page.pause(); - await expect(videoMuteButton).toHaveCSS("disabled", "true"); - await expect(audioMuteButton).toHaveCSS("disabled", "true"); + await expect(audioMuteButton).toHaveCSS( + "background-color", + "rgb(27, 29, 34)", + ); + + await expect(videoMuteButton).toHaveCSS( + "background-color", + "rgb(27, 29, 34)", + ); } }); From a20edca9a12a711777e2cc952b7cd90681b9a973 Mon Sep 17 00:00:00 2001 From: Timo K Date: Wed, 11 Mar 2026 15:36:37 +0100 Subject: [PATCH 362/748] fix pip container query --- playwright/widget/pip-call.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/playwright/widget/pip-call.test.ts b/playwright/widget/pip-call.test.ts index 49ebec524..d57befc1a 100644 --- a/playwright/widget/pip-call.test.ts +++ b/playwright/widget/pip-call.test.ts @@ -55,7 +55,7 @@ widgetTest("Put call in PIP", async ({ addUser, browserName }) => { await TestHelpers.switchToRoomNamed(valere.page, "DoubleTask"); // We should see the PIP overlay - await expect(valere.page.locator(".mx_WidgetPip_overlay")).toBeVisible(); + await expect(valere.page.getByTestId("widget-pip-container")).toBeVisible(); { // wait a bit so that the PIP has rendered the video From c7f25feb662c82182c494d79cba09fb184edd31d Mon Sep 17 00:00:00 2001 From: Timo K Date: Wed, 11 Mar 2026 15:44:47 +0100 Subject: [PATCH 363/748] use better test condition for mute buttons --- .../pip-call-button-interaction.test.ts | 40 +++++++------------ 1 file changed, 14 insertions(+), 26 deletions(-) diff --git a/playwright/widget/pip-call-button-interaction.test.ts b/playwright/widget/pip-call-button-interaction.test.ts index f798545d4..1dda652df 100644 --- a/playwright/widget/pip-call-button-interaction.test.ts +++ b/playwright/widget/pip-call-button-interaction.test.ts @@ -47,34 +47,22 @@ widgetTest("Footer interaction in PiP", async ({ addUser, browserName }) => { { // Check for a bug where the video had the wrong fit in PIP - const hangupButton = iFrame.getByRole("button", { name: "End call" }); - const audioMuteButton = iFrame.getByTestId("incall_mute"); - const videoMuteButton = iFrame.getByTestId("incall_videomute"); - await expect(hangupButton).toBeVisible(); - await expect(audioMuteButton).toBeVisible(); - await expect(videoMuteButton).toBeVisible(); - await expect(audioMuteButton).toHaveCSS( - "background-color", - "rgb(255, 255, 255)", - ); - await expect(videoMuteButton).toHaveCSS( - "background-color", - "rgb(255, 255, 255)", - ); - await videoMuteButton.click(); - await audioMuteButton.click(); + const hangupBtn = iFrame.getByRole("button", { name: "End call" }); + const audioBtn = iFrame.getByTestId("incall_mute"); + const videoBtn = iFrame.getByTestId("incall_videomute"); + await expect(hangupBtn).toBeVisible(); + await expect(audioBtn).toBeVisible(); + await expect(videoBtn).toBeVisible(); + await expect(audioBtn).toHaveAttribute("aria-label", /^Mute microphone$/); + await expect(videoBtn).toHaveAttribute("aria-label", /^Stop video$/); + + await videoBtn.click(); + await audioBtn.click(); + // stop hovering on any of the buttons await iFrame.getByTestId("videoTile").hover(); - await valere.page.pause(); - await expect(audioMuteButton).toHaveCSS( - "background-color", - "rgb(27, 29, 34)", - ); - - await expect(videoMuteButton).toHaveCSS( - "background-color", - "rgb(27, 29, 34)", - ); + await expect(audioBtn).toHaveAttribute("aria-label", /^Unmute microphone$/); + await expect(videoBtn).toHaveAttribute("aria-label", /^Start video$/); } }); From af54b396985ceca538619d9313dc952b9cc32b67 Mon Sep 17 00:00:00 2001 From: fkwp Date: Wed, 11 Mar 2026 16:09:02 +0100 Subject: [PATCH 364/748] fix: typo pushing element registry OCI images now to the correct target (#3796) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Push docker images to oci.element.io * prettier * add id-token permission as its required by tailscale login * pass secrets to reusable workflows * change secret path team -> voip * Update .github/workflows/build-and-publish-docker.yaml Co-authored-by: Gaël Goinvic <97093369+gaelgatelement@users.noreply.github.com> * typo --------- Co-authored-by: Gaël Goinvic <97093369+gaelgatelement@users.noreply.github.com> --- .github/workflows/build-and-publish-docker.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build-and-publish-docker.yaml b/.github/workflows/build-and-publish-docker.yaml index a3a5cba77..6447c094c 100644 --- a/.github/workflows/build-and-publish-docker.yaml +++ b/.github/workflows/build-and-publish-docker.yaml @@ -85,7 +85,7 @@ jobs: with: images: | ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} - oci-push.vpn.infra.element.io/element-web + oci-push.vpn.infra.element.io/element-call tags: ${{ inputs.docker_tags }} labels: | org.opencontainers.image.licenses=AGPL-3.0-only OR LicenseRef-Element-Commercial From 6b8f6e940538893149b73164c8f650cf8c74e5d1 Mon Sep 17 00:00:00 2001 From: Timo K Date: Thu, 12 Mar 2026 12:10:17 +0100 Subject: [PATCH 365/748] update vite vitest and rollup (rollup needs updating to fix a security alert) --- package.json | 7 +- src/livekit/MatrixAudioRenderer.test.tsx | 8 +- src/useAudioContext.test.tsx | 11 +- src/utils/test.ts | 4 +- yarn.lock | 537 +++++++++++------------ 5 files changed, 267 insertions(+), 300 deletions(-) diff --git a/package.json b/package.json index 9ee0ad263..30d63a2ed 100644 --- a/package.json +++ b/package.json @@ -128,17 +128,18 @@ "unique-names-generator": "^4.6.0", "uuid": "^13.0.0", "vaul": "^1.0.0", - "vite": "^7.0.0", + "vite": "^7.3.0", "vite-plugin-generate-file": "^0.3.0", "vite-plugin-html": "^3.2.2", "vite-plugin-node-stdlib-browser": "^0.2.1", "vite-plugin-svgr": "^4.0.0", - "vitest": "^3.0.0", + "vitest": "^4.0.18", "vitest-axe": "^1.0.0-pre.3" }, "resolutions": { "@livekit/components-core/rxjs": "^7.8.1", - "@livekit/track-processors/@mediapipe/tasks-vision": "^0.10.18" + "@livekit/track-processors/@mediapipe/tasks-vision": "^0.10.18", + "rollup": "4.59.0" }, "packageManager": "yarn@4.7.0" } diff --git a/src/livekit/MatrixAudioRenderer.test.tsx b/src/livekit/MatrixAudioRenderer.test.tsx index c6122b4bf..bc6ef6687 100644 --- a/src/livekit/MatrixAudioRenderer.test.tsx +++ b/src/livekit/MatrixAudioRenderer.test.tsx @@ -30,7 +30,13 @@ import { } from "../utils/test"; import { initializeWidget } from "../widget"; initializeWidget(); -export const TestAudioContextConstructor = vi.fn(() => testAudioContext); +export const TestAudioContextConstructor = vi.fn( + class { + public constructor() { + return testAudioContext; + } + }, +); const MediaDevicesProvider = MediaDevicesContext.MediaDevicesContext.Provider; diff --git a/src/useAudioContext.test.tsx b/src/useAudioContext.test.tsx index f74cf0160..97bfff5cb 100644 --- a/src/useAudioContext.test.tsx +++ b/src/useAudioContext.test.tsx @@ -90,11 +90,18 @@ export const testAudioContext = { createStereoPanner: vi.fn().mockReturnValue(panNode), close: vi.fn().mockResolvedValue(undefined), }; -export const TestAudioContextConstructor = vi.fn(() => testAudioContext); + +const TestAudioContext = vi.fn( + class { + public constructor() { + return testAudioContext; + } + }, +); let user: UserEvent; beforeEach(() => { - vi.stubGlobal("AudioContext", TestAudioContextConstructor); + vi.stubGlobal("AudioContext", TestAudioContext); user = userEvent.setup(); }); diff --git a/src/utils/test.ts b/src/utils/test.ts index b99bfa885..f8d420cf2 100644 --- a/src/utils/test.ts +++ b/src/utils/test.ts @@ -443,10 +443,10 @@ export class MockRTCSession extends TypedEventEmitter< public asMockedSession(): MockedObject { const session = this as unknown as MockedObject; - vi.mocked(session).reemitEncryptionKeys = vi + session.reemitEncryptionKeys = vi .fn<() => void>() .mockReturnValue(undefined); - vi.mocked(session).getOldestMembership = vi + session.getOldestMembership = vi .fn<() => CallMembership | undefined>() .mockReturnValue(this.memberships[0]); diff --git a/yarn.lock b/yarn.lock index bd90ded3e..552e77688 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5085,149 +5085,177 @@ __metadata: languageName: node linkType: hard -"@rollup/rollup-android-arm-eabi@npm:4.50.1": - version: 4.50.1 - resolution: "@rollup/rollup-android-arm-eabi@npm:4.50.1" +"@rollup/rollup-android-arm-eabi@npm:4.59.0": + version: 4.59.0 + resolution: "@rollup/rollup-android-arm-eabi@npm:4.59.0" conditions: os=android & cpu=arm languageName: node linkType: hard -"@rollup/rollup-android-arm64@npm:4.50.1": - version: 4.50.1 - resolution: "@rollup/rollup-android-arm64@npm:4.50.1" +"@rollup/rollup-android-arm64@npm:4.59.0": + version: 4.59.0 + resolution: "@rollup/rollup-android-arm64@npm:4.59.0" conditions: os=android & cpu=arm64 languageName: node linkType: hard -"@rollup/rollup-darwin-arm64@npm:4.50.1": - version: 4.50.1 - resolution: "@rollup/rollup-darwin-arm64@npm:4.50.1" +"@rollup/rollup-darwin-arm64@npm:4.59.0": + version: 4.59.0 + resolution: "@rollup/rollup-darwin-arm64@npm:4.59.0" conditions: os=darwin & cpu=arm64 languageName: node linkType: hard -"@rollup/rollup-darwin-x64@npm:4.50.1": - version: 4.50.1 - resolution: "@rollup/rollup-darwin-x64@npm:4.50.1" +"@rollup/rollup-darwin-x64@npm:4.59.0": + version: 4.59.0 + resolution: "@rollup/rollup-darwin-x64@npm:4.59.0" conditions: os=darwin & cpu=x64 languageName: node linkType: hard -"@rollup/rollup-freebsd-arm64@npm:4.50.1": - version: 4.50.1 - resolution: "@rollup/rollup-freebsd-arm64@npm:4.50.1" +"@rollup/rollup-freebsd-arm64@npm:4.59.0": + version: 4.59.0 + resolution: "@rollup/rollup-freebsd-arm64@npm:4.59.0" conditions: os=freebsd & cpu=arm64 languageName: node linkType: hard -"@rollup/rollup-freebsd-x64@npm:4.50.1": - version: 4.50.1 - resolution: "@rollup/rollup-freebsd-x64@npm:4.50.1" +"@rollup/rollup-freebsd-x64@npm:4.59.0": + version: 4.59.0 + resolution: "@rollup/rollup-freebsd-x64@npm:4.59.0" conditions: os=freebsd & cpu=x64 languageName: node linkType: hard -"@rollup/rollup-linux-arm-gnueabihf@npm:4.50.1": - version: 4.50.1 - resolution: "@rollup/rollup-linux-arm-gnueabihf@npm:4.50.1" +"@rollup/rollup-linux-arm-gnueabihf@npm:4.59.0": + version: 4.59.0 + resolution: "@rollup/rollup-linux-arm-gnueabihf@npm:4.59.0" conditions: os=linux & cpu=arm & libc=glibc languageName: node linkType: hard -"@rollup/rollup-linux-arm-musleabihf@npm:4.50.1": - version: 4.50.1 - resolution: "@rollup/rollup-linux-arm-musleabihf@npm:4.50.1" +"@rollup/rollup-linux-arm-musleabihf@npm:4.59.0": + version: 4.59.0 + resolution: "@rollup/rollup-linux-arm-musleabihf@npm:4.59.0" conditions: os=linux & cpu=arm & libc=musl languageName: node linkType: hard -"@rollup/rollup-linux-arm64-gnu@npm:4.50.1": - version: 4.50.1 - resolution: "@rollup/rollup-linux-arm64-gnu@npm:4.50.1" +"@rollup/rollup-linux-arm64-gnu@npm:4.59.0": + version: 4.59.0 + resolution: "@rollup/rollup-linux-arm64-gnu@npm:4.59.0" conditions: os=linux & cpu=arm64 & libc=glibc languageName: node linkType: hard -"@rollup/rollup-linux-arm64-musl@npm:4.50.1": - version: 4.50.1 - resolution: "@rollup/rollup-linux-arm64-musl@npm:4.50.1" +"@rollup/rollup-linux-arm64-musl@npm:4.59.0": + version: 4.59.0 + resolution: "@rollup/rollup-linux-arm64-musl@npm:4.59.0" conditions: os=linux & cpu=arm64 & libc=musl languageName: node linkType: hard -"@rollup/rollup-linux-loongarch64-gnu@npm:4.50.1": - version: 4.50.1 - resolution: "@rollup/rollup-linux-loongarch64-gnu@npm:4.50.1" +"@rollup/rollup-linux-loong64-gnu@npm:4.59.0": + version: 4.59.0 + resolution: "@rollup/rollup-linux-loong64-gnu@npm:4.59.0" conditions: os=linux & cpu=loong64 & libc=glibc languageName: node linkType: hard -"@rollup/rollup-linux-ppc64-gnu@npm:4.50.1": - version: 4.50.1 - resolution: "@rollup/rollup-linux-ppc64-gnu@npm:4.50.1" +"@rollup/rollup-linux-loong64-musl@npm:4.59.0": + version: 4.59.0 + resolution: "@rollup/rollup-linux-loong64-musl@npm:4.59.0" + conditions: os=linux & cpu=loong64 & libc=musl + languageName: node + linkType: hard + +"@rollup/rollup-linux-ppc64-gnu@npm:4.59.0": + version: 4.59.0 + resolution: "@rollup/rollup-linux-ppc64-gnu@npm:4.59.0" conditions: os=linux & cpu=ppc64 & libc=glibc languageName: node linkType: hard -"@rollup/rollup-linux-riscv64-gnu@npm:4.50.1": - version: 4.50.1 - resolution: "@rollup/rollup-linux-riscv64-gnu@npm:4.50.1" +"@rollup/rollup-linux-ppc64-musl@npm:4.59.0": + version: 4.59.0 + resolution: "@rollup/rollup-linux-ppc64-musl@npm:4.59.0" + conditions: os=linux & cpu=ppc64 & libc=musl + languageName: node + linkType: hard + +"@rollup/rollup-linux-riscv64-gnu@npm:4.59.0": + version: 4.59.0 + resolution: "@rollup/rollup-linux-riscv64-gnu@npm:4.59.0" conditions: os=linux & cpu=riscv64 & libc=glibc languageName: node linkType: hard -"@rollup/rollup-linux-riscv64-musl@npm:4.50.1": - version: 4.50.1 - resolution: "@rollup/rollup-linux-riscv64-musl@npm:4.50.1" +"@rollup/rollup-linux-riscv64-musl@npm:4.59.0": + version: 4.59.0 + resolution: "@rollup/rollup-linux-riscv64-musl@npm:4.59.0" conditions: os=linux & cpu=riscv64 & libc=musl languageName: node linkType: hard -"@rollup/rollup-linux-s390x-gnu@npm:4.50.1": - version: 4.50.1 - resolution: "@rollup/rollup-linux-s390x-gnu@npm:4.50.1" +"@rollup/rollup-linux-s390x-gnu@npm:4.59.0": + version: 4.59.0 + resolution: "@rollup/rollup-linux-s390x-gnu@npm:4.59.0" conditions: os=linux & cpu=s390x & libc=glibc languageName: node linkType: hard -"@rollup/rollup-linux-x64-gnu@npm:4.50.1": - version: 4.50.1 - resolution: "@rollup/rollup-linux-x64-gnu@npm:4.50.1" +"@rollup/rollup-linux-x64-gnu@npm:4.59.0": + version: 4.59.0 + resolution: "@rollup/rollup-linux-x64-gnu@npm:4.59.0" conditions: os=linux & cpu=x64 & libc=glibc languageName: node linkType: hard -"@rollup/rollup-linux-x64-musl@npm:4.50.1": - version: 4.50.1 - resolution: "@rollup/rollup-linux-x64-musl@npm:4.50.1" +"@rollup/rollup-linux-x64-musl@npm:4.59.0": + version: 4.59.0 + resolution: "@rollup/rollup-linux-x64-musl@npm:4.59.0" conditions: os=linux & cpu=x64 & libc=musl languageName: node linkType: hard -"@rollup/rollup-openharmony-arm64@npm:4.50.1": - version: 4.50.1 - resolution: "@rollup/rollup-openharmony-arm64@npm:4.50.1" +"@rollup/rollup-openbsd-x64@npm:4.59.0": + version: 4.59.0 + resolution: "@rollup/rollup-openbsd-x64@npm:4.59.0" + conditions: os=openbsd & cpu=x64 + languageName: node + linkType: hard + +"@rollup/rollup-openharmony-arm64@npm:4.59.0": + version: 4.59.0 + resolution: "@rollup/rollup-openharmony-arm64@npm:4.59.0" conditions: os=openharmony & cpu=arm64 languageName: node linkType: hard -"@rollup/rollup-win32-arm64-msvc@npm:4.50.1": - version: 4.50.1 - resolution: "@rollup/rollup-win32-arm64-msvc@npm:4.50.1" +"@rollup/rollup-win32-arm64-msvc@npm:4.59.0": + version: 4.59.0 + resolution: "@rollup/rollup-win32-arm64-msvc@npm:4.59.0" conditions: os=win32 & cpu=arm64 languageName: node linkType: hard -"@rollup/rollup-win32-ia32-msvc@npm:4.50.1": - version: 4.50.1 - resolution: "@rollup/rollup-win32-ia32-msvc@npm:4.50.1" +"@rollup/rollup-win32-ia32-msvc@npm:4.59.0": + version: 4.59.0 + resolution: "@rollup/rollup-win32-ia32-msvc@npm:4.59.0" conditions: os=win32 & cpu=ia32 languageName: node linkType: hard -"@rollup/rollup-win32-x64-msvc@npm:4.50.1": - version: 4.50.1 - resolution: "@rollup/rollup-win32-x64-msvc@npm:4.50.1" +"@rollup/rollup-win32-x64-gnu@npm:4.59.0": + version: 4.59.0 + resolution: "@rollup/rollup-win32-x64-gnu@npm:4.59.0" + conditions: os=win32 & cpu=x64 + languageName: node + linkType: hard + +"@rollup/rollup-win32-x64-msvc@npm:4.59.0": + version: 4.59.0 + resolution: "@rollup/rollup-win32-x64-msvc@npm:4.59.0" conditions: os=win32 & cpu=x64 languageName: node linkType: hard @@ -5446,6 +5474,13 @@ __metadata: languageName: node linkType: hard +"@standard-schema/spec@npm:^1.0.0": + version: 1.1.0 + resolution: "@standard-schema/spec@npm:1.1.0" + checksum: 10c0/d90f55acde4b2deb983529c87e8025fa693de1a5e8b49ecc6eb84d1fd96328add0e03d7d551442156c7432fd78165b2c26ff561b970a9a881f046abb78d6a526 + languageName: node + linkType: hard + "@stylistic/eslint-plugin@npm:^3.0.0": version: 3.1.0 resolution: "@stylistic/eslint-plugin@npm:3.1.0" @@ -6298,44 +6333,45 @@ __metadata: languageName: node linkType: hard -"@vitest/expect@npm:3.2.4": - version: 3.2.4 - resolution: "@vitest/expect@npm:3.2.4" +"@vitest/expect@npm:4.0.18": + version: 4.0.18 + resolution: "@vitest/expect@npm:4.0.18" dependencies: + "@standard-schema/spec": "npm:^1.0.0" "@types/chai": "npm:^5.2.2" - "@vitest/spy": "npm:3.2.4" - "@vitest/utils": "npm:3.2.4" - chai: "npm:^5.2.0" - tinyrainbow: "npm:^2.0.0" - checksum: 10c0/7586104e3fd31dbe1e6ecaafb9a70131e4197dce2940f727b6a84131eee3decac7b10f9c7c72fa5edbdb68b6f854353bd4c0fa84779e274207fb7379563b10db + "@vitest/spy": "npm:4.0.18" + "@vitest/utils": "npm:4.0.18" + chai: "npm:^6.2.1" + tinyrainbow: "npm:^3.0.3" + checksum: 10c0/123b0aa111682e82ec5289186df18037b1a1768700e468ee0f9879709aaa320cf790463c15c0d8ee10df92b402f4394baf5d27797e604d78e674766d87bcaadc languageName: node linkType: hard -"@vitest/mocker@npm:3.2.4": - version: 3.2.4 - resolution: "@vitest/mocker@npm:3.2.4" +"@vitest/mocker@npm:4.0.18": + version: 4.0.18 + resolution: "@vitest/mocker@npm:4.0.18" dependencies: - "@vitest/spy": "npm:3.2.4" + "@vitest/spy": "npm:4.0.18" estree-walker: "npm:^3.0.3" - magic-string: "npm:^0.30.17" + magic-string: "npm:^0.30.21" peerDependencies: msw: ^2.4.9 - vite: ^5.0.0 || ^6.0.0 || ^7.0.0-0 + vite: ^6.0.0 || ^7.0.0-0 peerDependenciesMeta: msw: optional: true vite: optional: true - checksum: 10c0/f7a4aea19bbbf8f15905847ee9143b6298b2c110f8b64789224cb0ffdc2e96f9802876aa2ca83f1ec1b6e1ff45e822abb34f0054c24d57b29ab18add06536ccd + checksum: 10c0/fb0a257e7e167759d4ad228d53fa7bad2267586459c4a62188f2043dd7163b4b02e1e496dc3c227837f776e7d73d6c4343613e89e7da379d9d30de8260f1ee4b languageName: node linkType: hard -"@vitest/pretty-format@npm:3.2.4, @vitest/pretty-format@npm:^3.2.4": - version: 3.2.4 - resolution: "@vitest/pretty-format@npm:3.2.4" +"@vitest/pretty-format@npm:4.0.18": + version: 4.0.18 + resolution: "@vitest/pretty-format@npm:4.0.18" dependencies: - tinyrainbow: "npm:^2.0.0" - checksum: 10c0/5ad7d4278e067390d7d633e307fee8103958806a419ca380aec0e33fae71b44a64415f7a9b4bc11635d3c13d4a9186111c581d3cef9c65cc317e68f077456887 + tinyrainbow: "npm:^3.0.3" + checksum: 10c0/0086b8c88eeca896d8e4b98fcdef452c8041a1b63eb9e85d3e0bcc96c8aa76d8e9e0b6990ebb0bb0a697c4ebab347e7735888b24f507dbff2742ddce7723fd94 languageName: node linkType: hard @@ -6348,45 +6384,41 @@ __metadata: languageName: node linkType: hard -"@vitest/runner@npm:3.2.4": - version: 3.2.4 - resolution: "@vitest/runner@npm:3.2.4" +"@vitest/runner@npm:4.0.18": + version: 4.0.18 + resolution: "@vitest/runner@npm:4.0.18" dependencies: - "@vitest/utils": "npm:3.2.4" + "@vitest/utils": "npm:4.0.18" pathe: "npm:^2.0.3" - strip-literal: "npm:^3.0.0" - checksum: 10c0/e8be51666c72b3668ae3ea348b0196656a4a5adb836cb5e270720885d9517421815b0d6c98bfdf1795ed02b994b7bfb2b21566ee356a40021f5bf4f6ed4e418a + checksum: 10c0/fdb4afa411475133c05ba266c8092eaf1e56cbd5fb601f92ec6ccb9bab7ca52e06733ee8626599355cba4ee71cb3a8f28c84d3b69dc972e41047edc50229bc01 languageName: node linkType: hard -"@vitest/snapshot@npm:3.2.4": - version: 3.2.4 - resolution: "@vitest/snapshot@npm:3.2.4" +"@vitest/snapshot@npm:4.0.18": + version: 4.0.18 + resolution: "@vitest/snapshot@npm:4.0.18" dependencies: - "@vitest/pretty-format": "npm:3.2.4" - magic-string: "npm:^0.30.17" + "@vitest/pretty-format": "npm:4.0.18" + magic-string: "npm:^0.30.21" pathe: "npm:^2.0.3" - checksum: 10c0/f8301a3d7d1559fd3d59ed51176dd52e1ed5c2d23aa6d8d6aa18787ef46e295056bc726a021698d8454c16ed825ecba163362f42fa90258bb4a98cfd2c9424fc + checksum: 10c0/d3bfefa558db9a69a66886ace6575eb96903a5ba59f4d9a5d0fecb4acc2bb8dbb443ef409f5ac1475f2e1add30bd1d71280f98912da35e89c75829df9e84ea43 languageName: node linkType: hard -"@vitest/spy@npm:3.2.4": - version: 3.2.4 - resolution: "@vitest/spy@npm:3.2.4" - dependencies: - tinyspy: "npm:^4.0.3" - checksum: 10c0/6ebf0b4697dc238476d6b6a60c76ba9eb1dd8167a307e30f08f64149612fd50227682b876420e4c2e09a76334e73f72e3ebf0e350714dc22474258292e202024 +"@vitest/spy@npm:4.0.18": + version: 4.0.18 + resolution: "@vitest/spy@npm:4.0.18" + checksum: 10c0/6de537890b3994fcadb8e8d8ac05942320ae184f071ec395d978a5fba7fa928cbb0c5de85af86a1c165706c466e840de8779eaff8c93450c511c7abaeb9b8a4e languageName: node linkType: hard -"@vitest/utils@npm:3.2.4": - version: 3.2.4 - resolution: "@vitest/utils@npm:3.2.4" +"@vitest/utils@npm:4.0.18": + version: 4.0.18 + resolution: "@vitest/utils@npm:4.0.18" dependencies: - "@vitest/pretty-format": "npm:3.2.4" - loupe: "npm:^3.1.4" - tinyrainbow: "npm:^2.0.0" - checksum: 10c0/024a9b8c8bcc12cf40183c246c244b52ecff861c6deb3477cbf487ac8781ad44c68a9c5fd69f8c1361878e55b97c10d99d511f2597f1f7244b5e5101d028ba64 + "@vitest/pretty-format": "npm:4.0.18" + tinyrainbow: "npm:^3.0.3" + checksum: 10c0/4a3c43c1421eb90f38576926496f6c80056167ba111e63f77cf118983902673737a1a38880b890d7c06ec0a12475024587344ee502b3c43093781533022f2aeb languageName: node linkType: hard @@ -6736,13 +6768,6 @@ __metadata: languageName: node linkType: hard -"assertion-error@npm:^2.0.1": - version: 2.0.1 - resolution: "assertion-error@npm:2.0.1" - checksum: 10c0/bbbcb117ac6480138f8c93cf7f535614282dea9dc828f540cdece85e3c665e8f78958b96afac52f29ff883c72638e6a87d469ecc9fe5bc902df03ed24a55dba8 - languageName: node - linkType: hard - "ast-types-flow@npm:^0.0.8": version: 0.0.8 resolution: "ast-types-flow@npm:0.0.8" @@ -7222,13 +7247,6 @@ __metadata: languageName: node linkType: hard -"cac@npm:^6.7.14": - version: 6.7.14 - resolution: "cac@npm:6.7.14" - checksum: 10c0/4ee06aaa7bab8981f0d54e5f5f9d4adcd64058e9697563ce336d8a3878ed018ee18ebe5359b2430eceae87e0758e62ea2019c3f52ae6e211b1bd2e133856cd10 - languageName: node - linkType: hard - "cacache@npm:^19.0.1": version: 19.0.1 resolution: "cacache@npm:19.0.1" @@ -7353,16 +7371,10 @@ __metadata: languageName: node linkType: hard -"chai@npm:^5.2.0": - version: 5.2.0 - resolution: "chai@npm:5.2.0" - dependencies: - assertion-error: "npm:^2.0.1" - check-error: "npm:^2.1.1" - deep-eql: "npm:^5.0.1" - loupe: "npm:^3.1.0" - pathval: "npm:^2.0.0" - checksum: 10c0/dfd1cb719c7cebb051b727672d382a35338af1470065cb12adb01f4ee451bbf528e0e0f9ab2016af5fc1eea4df6e7f4504dc8443f8f00bd8fb87ad32dc516f7d +"chai@npm:^6.2.1": + version: 6.2.2 + resolution: "chai@npm:6.2.2" + checksum: 10c0/e6c69e5f0c11dffe6ea13d0290936ebb68fcc1ad688b8e952e131df6a6d5797d5e860bc55cef1aca2e950c3e1f96daf79e9d5a70fb7dbaab4e46355e2635ed53 languageName: node linkType: hard @@ -7394,13 +7406,6 @@ __metadata: languageName: node linkType: hard -"check-error@npm:^2.1.1": - version: 2.1.1 - resolution: "check-error@npm:2.1.1" - checksum: 10c0/979f13eccab306cf1785fa10941a590b4e7ea9916ea2a4f8c87f0316fc3eab07eabefb6e587424ef0f88cbcd3805791f172ea739863ca3d7ce2afc54641c7f0e - languageName: node - linkType: hard - "cheerio-select@npm:^2.1.0": version: 2.1.0 resolution: "cheerio-select@npm:2.1.0" @@ -8086,13 +8091,6 @@ __metadata: languageName: node linkType: hard -"deep-eql@npm:^5.0.1": - version: 5.0.2 - resolution: "deep-eql@npm:5.0.2" - checksum: 10c0/7102cf3b7bb719c6b9c0db2e19bf0aa9318d141581befe8c7ce8ccd39af9eaa4346e5e05adef7f9bd7015da0f13a3a25dcfe306ef79dc8668aedbecb658dd247 - languageName: node - linkType: hard - "deep-is@npm:^0.1.3": version: 0.1.4 resolution: "deep-is@npm:0.1.4" @@ -8460,12 +8458,12 @@ __metadata: unique-names-generator: "npm:^4.6.0" uuid: "npm:^13.0.0" vaul: "npm:^1.0.0" - vite: "npm:^7.0.0" + vite: "npm:^7.3.0" vite-plugin-generate-file: "npm:^0.3.0" vite-plugin-html: "npm:^3.2.2" vite-plugin-node-stdlib-browser: "npm:^0.2.1" vite-plugin-svgr: "npm:^4.0.0" - vitest: "npm:^3.0.0" + vitest: "npm:^4.0.18" vitest-axe: "npm:^1.0.0-pre.3" languageName: unknown linkType: soft @@ -9447,10 +9445,10 @@ __metadata: languageName: node linkType: hard -"expect-type@npm:^1.2.1": - version: 1.2.1 - resolution: "expect-type@npm:1.2.1" - checksum: 10c0/b775c9adab3c190dd0d398c722531726cdd6022849b4adba19dceab58dda7e000a7c6c872408cd73d665baa20d381eca36af4f7b393a4ba60dd10232d1fb8898 +"expect-type@npm:^1.2.2": + version: 1.3.0 + resolution: "expect-type@npm:1.3.0" + checksum: 10c0/8412b3fe4f392c420ab41dae220b09700e4e47c639a29ba7ba2e83cc6cffd2b4926f7ac9e47d7e277e8f4f02acda76fd6931cb81fd2b382fa9477ef9ada953fd languageName: node linkType: hard @@ -9533,18 +9531,6 @@ __metadata: languageName: node linkType: hard -"fdir@npm:^6.4.4": - version: 6.4.5 - resolution: "fdir@npm:6.4.5" - peerDependencies: - picomatch: ^3 || ^4 - peerDependenciesMeta: - picomatch: - optional: true - checksum: 10c0/5d63330a1b97165e9b0fb20369fafc7cf826bc4b3e374efcb650bc77d7145ac01193b5da1a7591eab89ae6fd6b15cdd414085910b2a2b42296b1480c9f2677af - languageName: node - linkType: hard - "fdir@npm:^6.5.0": version: 6.5.0 resolution: "fdir@npm:6.5.0" @@ -11379,20 +11365,6 @@ __metadata: languageName: node linkType: hard -"loupe@npm:^3.1.0": - version: 3.1.3 - resolution: "loupe@npm:3.1.3" - checksum: 10c0/f5dab4144254677de83a35285be1b8aba58b3861439ce4ba65875d0d5f3445a4a496daef63100ccf02b2dbc25bf58c6db84c9cb0b96d6435331e9d0a33b48541 - languageName: node - linkType: hard - -"loupe@npm:^3.1.4": - version: 3.1.4 - resolution: "loupe@npm:3.1.4" - checksum: 10c0/5c2e6aefaad25f812d361c750b8cf4ff91d68de289f141d7c85c2ce9bb79eeefa06a93c85f7b87cba940531ed8f15e492f32681d47eed23842ad1963eb3a154d - languageName: node - linkType: hard - "lower-case@npm:^2.0.2": version: 2.0.2 resolution: "lower-case@npm:2.0.2" @@ -11452,7 +11424,7 @@ __metadata: languageName: node linkType: hard -"magic-string@npm:^0.30.3": +"magic-string@npm:^0.30.21, magic-string@npm:^0.30.3": version: 0.30.21 resolution: "magic-string@npm:0.30.21" dependencies: @@ -12113,6 +12085,13 @@ __metadata: languageName: node linkType: hard +"obug@npm:^2.1.1": + version: 2.1.1 + resolution: "obug@npm:2.1.1" + checksum: 10c0/59dccd7de72a047e08f8649e94c1015ec72f94eefb6ddb57fb4812c4b425a813bc7e7cd30c9aca20db3c59abc3c85cc7a62bb656a968741d770f4e8e02bc2e78 + languageName: node + linkType: hard + "oidc-client-ts@npm:^3.0.1": version: 3.1.0 resolution: "oidc-client-ts@npm:3.1.0" @@ -12483,13 +12462,6 @@ __metadata: languageName: node linkType: hard -"pathval@npm:^2.0.0": - version: 2.0.0 - resolution: "pathval@npm:2.0.0" - checksum: 10c0/602e4ee347fba8a599115af2ccd8179836a63c925c23e04bd056d0674a64b39e3a081b643cc7bc0b84390517df2d800a46fcc5598d42c155fe4977095c2f77c5 - languageName: node - linkType: hard - "pbkdf2@npm:^3.1.2, pbkdf2@npm:^3.1.5": version: 3.1.5 resolution: "pbkdf2@npm:3.1.5" @@ -13797,31 +13769,35 @@ __metadata: languageName: node linkType: hard -"rollup@npm:^4.43.0": - version: 4.50.1 - resolution: "rollup@npm:4.50.1" +"rollup@npm:4.59.0": + version: 4.59.0 + resolution: "rollup@npm:4.59.0" dependencies: - "@rollup/rollup-android-arm-eabi": "npm:4.50.1" - "@rollup/rollup-android-arm64": "npm:4.50.1" - "@rollup/rollup-darwin-arm64": "npm:4.50.1" - "@rollup/rollup-darwin-x64": "npm:4.50.1" - "@rollup/rollup-freebsd-arm64": "npm:4.50.1" - "@rollup/rollup-freebsd-x64": "npm:4.50.1" - "@rollup/rollup-linux-arm-gnueabihf": "npm:4.50.1" - "@rollup/rollup-linux-arm-musleabihf": "npm:4.50.1" - "@rollup/rollup-linux-arm64-gnu": "npm:4.50.1" - "@rollup/rollup-linux-arm64-musl": "npm:4.50.1" - "@rollup/rollup-linux-loongarch64-gnu": "npm:4.50.1" - "@rollup/rollup-linux-ppc64-gnu": "npm:4.50.1" - "@rollup/rollup-linux-riscv64-gnu": "npm:4.50.1" - "@rollup/rollup-linux-riscv64-musl": "npm:4.50.1" - "@rollup/rollup-linux-s390x-gnu": "npm:4.50.1" - "@rollup/rollup-linux-x64-gnu": "npm:4.50.1" - "@rollup/rollup-linux-x64-musl": "npm:4.50.1" - "@rollup/rollup-openharmony-arm64": "npm:4.50.1" - "@rollup/rollup-win32-arm64-msvc": "npm:4.50.1" - "@rollup/rollup-win32-ia32-msvc": "npm:4.50.1" - "@rollup/rollup-win32-x64-msvc": "npm:4.50.1" + "@rollup/rollup-android-arm-eabi": "npm:4.59.0" + "@rollup/rollup-android-arm64": "npm:4.59.0" + "@rollup/rollup-darwin-arm64": "npm:4.59.0" + "@rollup/rollup-darwin-x64": "npm:4.59.0" + "@rollup/rollup-freebsd-arm64": "npm:4.59.0" + "@rollup/rollup-freebsd-x64": "npm:4.59.0" + "@rollup/rollup-linux-arm-gnueabihf": "npm:4.59.0" + "@rollup/rollup-linux-arm-musleabihf": "npm:4.59.0" + "@rollup/rollup-linux-arm64-gnu": "npm:4.59.0" + "@rollup/rollup-linux-arm64-musl": "npm:4.59.0" + "@rollup/rollup-linux-loong64-gnu": "npm:4.59.0" + "@rollup/rollup-linux-loong64-musl": "npm:4.59.0" + "@rollup/rollup-linux-ppc64-gnu": "npm:4.59.0" + "@rollup/rollup-linux-ppc64-musl": "npm:4.59.0" + "@rollup/rollup-linux-riscv64-gnu": "npm:4.59.0" + "@rollup/rollup-linux-riscv64-musl": "npm:4.59.0" + "@rollup/rollup-linux-s390x-gnu": "npm:4.59.0" + "@rollup/rollup-linux-x64-gnu": "npm:4.59.0" + "@rollup/rollup-linux-x64-musl": "npm:4.59.0" + "@rollup/rollup-openbsd-x64": "npm:4.59.0" + "@rollup/rollup-openharmony-arm64": "npm:4.59.0" + "@rollup/rollup-win32-arm64-msvc": "npm:4.59.0" + "@rollup/rollup-win32-ia32-msvc": "npm:4.59.0" + "@rollup/rollup-win32-x64-gnu": "npm:4.59.0" + "@rollup/rollup-win32-x64-msvc": "npm:4.59.0" "@types/estree": "npm:1.0.8" fsevents: "npm:~2.3.2" dependenciesMeta: @@ -13845,10 +13821,14 @@ __metadata: optional: true "@rollup/rollup-linux-arm64-musl": optional: true - "@rollup/rollup-linux-loongarch64-gnu": + "@rollup/rollup-linux-loong64-gnu": + optional: true + "@rollup/rollup-linux-loong64-musl": optional: true "@rollup/rollup-linux-ppc64-gnu": optional: true + "@rollup/rollup-linux-ppc64-musl": + optional: true "@rollup/rollup-linux-riscv64-gnu": optional: true "@rollup/rollup-linux-riscv64-musl": @@ -13859,19 +13839,23 @@ __metadata: optional: true "@rollup/rollup-linux-x64-musl": optional: true + "@rollup/rollup-openbsd-x64": + optional: true "@rollup/rollup-openharmony-arm64": optional: true "@rollup/rollup-win32-arm64-msvc": optional: true "@rollup/rollup-win32-ia32-msvc": optional: true + "@rollup/rollup-win32-x64-gnu": + optional: true "@rollup/rollup-win32-x64-msvc": optional: true fsevents: optional: true bin: rollup: dist/bin/rollup - checksum: 10c0/2029282826d5fb4e308be261b2c28329a4d2bd34304cc3960da69fd21d5acccd0267d6770b1656ffc8f166203ef7e865b4583d5f842a519c8ef059ac71854205 + checksum: 10c0/f38742da34cfee5e899302615fa157aa77cb6a2a1495e5e3ce4cc9c540d3262e235bbe60caa31562bbfe492b01fdb3e7a8c43c39d842d3293bcf843123b766fc languageName: node linkType: hard @@ -14397,6 +14381,13 @@ __metadata: languageName: node linkType: hard +"std-env@npm:^3.10.0": + version: 3.10.0 + resolution: "std-env@npm:3.10.0" + checksum: 10c0/1814927a45004d36dde6707eaf17552a546769bc79a6421be2c16ce77d238158dfe5de30910b78ec30d95135cc1c59ea73ee22d2ca170f8b9753f84da34c427f + languageName: node + linkType: hard + "std-env@npm:^3.9.0": version: 3.9.0 resolution: "std-env@npm:3.9.0" @@ -14627,15 +14618,6 @@ __metadata: languageName: node linkType: hard -"strip-literal@npm:^3.0.0": - version: 3.0.0 - resolution: "strip-literal@npm:3.0.0" - dependencies: - js-tokens: "npm:^9.0.1" - checksum: 10c0/d81657f84aba42d4bbaf2a677f7e7f34c1f3de5a6726db8bc1797f9c0b303ba54d4660383a74bde43df401cf37cce1dff2c842c55b077a4ceee11f9e31fba828 - languageName: node - linkType: hard - "supports-color@npm:^5.3.0": version: 5.5.0 resolution: "supports-color@npm:5.5.0" @@ -14779,20 +14761,10 @@ __metadata: languageName: node linkType: hard -"tinyexec@npm:^0.3.2": - version: 0.3.2 - resolution: "tinyexec@npm:0.3.2" - checksum: 10c0/3efbf791a911be0bf0821eab37a3445c2ba07acc1522b1fa84ae1e55f10425076f1290f680286345ed919549ad67527d07281f1c19d584df3b74326909eb1f90 - languageName: node - linkType: hard - -"tinyglobby@npm:^0.2.14": - version: 0.2.14 - resolution: "tinyglobby@npm:0.2.14" - dependencies: - fdir: "npm:^6.4.4" - picomatch: "npm:^4.0.2" - checksum: 10c0/f789ed6c924287a9b7d3612056ed0cda67306cd2c80c249fd280cf1504742b12583a2089b61f4abbd24605f390809017240e250241f09938054c9b363e51c0a6 +"tinyexec@npm:^1.0.2": + version: 1.0.2 + resolution: "tinyexec@npm:1.0.2" + checksum: 10c0/1261a8e34c9b539a9aae3b7f0bb5372045ff28ee1eba035a2a059e532198fe1a182ec61ac60fa0b4a4129f0c4c4b1d2d57355b5cb9aa2d17ac9454ecace502ee languageName: node linkType: hard @@ -14806,13 +14778,6 @@ __metadata: languageName: node linkType: hard -"tinypool@npm:^1.1.1": - version: 1.1.1 - resolution: "tinypool@npm:1.1.1" - checksum: 10c0/bf26727d01443061b04fa863f571016950888ea994ba0cd8cba3a1c51e2458d84574341ab8dbc3664f1c3ab20885c8cf9ff1cc4b18201f04c2cde7d317fff69b - languageName: node - linkType: hard - "tinyrainbow@npm:^2.0.0": version: 2.0.0 resolution: "tinyrainbow@npm:2.0.0" @@ -14820,10 +14785,10 @@ __metadata: languageName: node linkType: hard -"tinyspy@npm:^4.0.3": - version: 4.0.3 - resolution: "tinyspy@npm:4.0.3" - checksum: 10c0/0a92a18b5350945cc8a1da3a22c9ad9f4e2945df80aaa0c43e1b3a3cfb64d8501e607ebf0305e048e3c3d3e0e7f8eb10cea27dc17c21effb73e66c4a3be36373 +"tinyrainbow@npm:^3.0.3": + version: 3.1.0 + resolution: "tinyrainbow@npm:3.1.0" + checksum: 10c0/f11cf387a26c5c9255bec141a90ac511b26172981b10c3e50053bc6700ea7d2336edcc4a3a21dbb8412fe7c013477d2ba4d7e4877800f3f8107be5105aad6511 languageName: node linkType: hard @@ -15530,21 +15495,6 @@ __metadata: languageName: node linkType: hard -"vite-node@npm:3.2.4": - version: 3.2.4 - resolution: "vite-node@npm:3.2.4" - dependencies: - cac: "npm:^6.7.14" - debug: "npm:^4.4.1" - es-module-lexer: "npm:^1.7.0" - pathe: "npm:^2.0.3" - vite: "npm:^5.0.0 || ^6.0.0 || ^7.0.0-0" - bin: - vite-node: vite-node.mjs - checksum: 10c0/6ceca67c002f8ef6397d58b9539f80f2b5d79e103a18367288b3f00a8ab55affa3d711d86d9112fce5a7fa658a212a087a005a045eb8f4758947dd99af2a6c6b - languageName: node - linkType: hard - "vite-plugin-generate-file@npm:^0.3.0": version: 0.3.1 resolution: "vite-plugin-generate-file@npm:0.3.1" @@ -15604,7 +15554,7 @@ __metadata: languageName: node linkType: hard -"vite@npm:^5.0.0 || ^6.0.0 || ^7.0.0-0, vite@npm:^7.0.0": +"vite@npm:^6.0.0 || ^7.0.0, vite@npm:^7.3.0": version: 7.3.1 resolution: "vite@npm:7.3.1" dependencies: @@ -15673,49 +15623,52 @@ __metadata: languageName: node linkType: hard -"vitest@npm:^3.0.0": - version: 3.2.4 - resolution: "vitest@npm:3.2.4" +"vitest@npm:^4.0.18": + version: 4.0.18 + resolution: "vitest@npm:4.0.18" dependencies: - "@types/chai": "npm:^5.2.2" - "@vitest/expect": "npm:3.2.4" - "@vitest/mocker": "npm:3.2.4" - "@vitest/pretty-format": "npm:^3.2.4" - "@vitest/runner": "npm:3.2.4" - "@vitest/snapshot": "npm:3.2.4" - "@vitest/spy": "npm:3.2.4" - "@vitest/utils": "npm:3.2.4" - chai: "npm:^5.2.0" - debug: "npm:^4.4.1" - expect-type: "npm:^1.2.1" - magic-string: "npm:^0.30.17" + "@vitest/expect": "npm:4.0.18" + "@vitest/mocker": "npm:4.0.18" + "@vitest/pretty-format": "npm:4.0.18" + "@vitest/runner": "npm:4.0.18" + "@vitest/snapshot": "npm:4.0.18" + "@vitest/spy": "npm:4.0.18" + "@vitest/utils": "npm:4.0.18" + es-module-lexer: "npm:^1.7.0" + expect-type: "npm:^1.2.2" + magic-string: "npm:^0.30.21" + obug: "npm:^2.1.1" pathe: "npm:^2.0.3" - picomatch: "npm:^4.0.2" - std-env: "npm:^3.9.0" + picomatch: "npm:^4.0.3" + std-env: "npm:^3.10.0" tinybench: "npm:^2.9.0" - tinyexec: "npm:^0.3.2" - tinyglobby: "npm:^0.2.14" - tinypool: "npm:^1.1.1" - tinyrainbow: "npm:^2.0.0" - vite: "npm:^5.0.0 || ^6.0.0 || ^7.0.0-0" - vite-node: "npm:3.2.4" + tinyexec: "npm:^1.0.2" + tinyglobby: "npm:^0.2.15" + tinyrainbow: "npm:^3.0.3" + vite: "npm:^6.0.0 || ^7.0.0" why-is-node-running: "npm:^2.3.0" peerDependencies: "@edge-runtime/vm": "*" - "@types/debug": ^4.1.12 - "@types/node": ^18.0.0 || ^20.0.0 || >=22.0.0 - "@vitest/browser": 3.2.4 - "@vitest/ui": 3.2.4 + "@opentelemetry/api": ^1.9.0 + "@types/node": ^20.0.0 || ^22.0.0 || >=24.0.0 + "@vitest/browser-playwright": 4.0.18 + "@vitest/browser-preview": 4.0.18 + "@vitest/browser-webdriverio": 4.0.18 + "@vitest/ui": 4.0.18 happy-dom: "*" jsdom: "*" peerDependenciesMeta: "@edge-runtime/vm": optional: true - "@types/debug": + "@opentelemetry/api": optional: true "@types/node": optional: true - "@vitest/browser": + "@vitest/browser-playwright": + optional: true + "@vitest/browser-preview": + optional: true + "@vitest/browser-webdriverio": optional: true "@vitest/ui": optional: true @@ -15725,7 +15678,7 @@ __metadata: optional: true bin: vitest: vitest.mjs - checksum: 10c0/5bf53ede3ae6a0e08956d72dab279ae90503f6b5a05298a6a5e6ef47d2fd1ab386aaf48fafa61ed07a0ebfe9e371772f1ccbe5c258dd765206a8218bf2eb79eb + checksum: 10c0/b913cd32032c95f29ff08c931f4b4c6fd6d2da498908d6770952c561a1b8d75c62499a1f04cadf82fb89cc0f9a33f29fb5dfdb899f6dbb27686a9d91571be5fa languageName: node linkType: hard From 413329cd261e4f1a579a5c0a2333954933ab0af8 Mon Sep 17 00:00:00 2001 From: fkwp Date: Thu, 12 Mar 2026 13:30:45 +0100 Subject: [PATCH 366/748] Fix: zizmor findings (#3797) * zizmor auto fixes * add github action for security analysis with zizmor * add access token to iOS push action * fix zizmor findings * add exceptions for dangerous-triggers including comments for reasoning * improve comments * prettier --- .github/workflows/blocked.yaml | 9 +++++++++ .github/workflows/build-element-call.yaml | 4 +++- .github/workflows/changelog-label.yml | 8 ++++++++ .github/workflows/pr-deploy.yaml | 11 ++++++++++- .github/workflows/publish-embedded-packages.yaml | 14 ++++++++++++-- 5 files changed, 42 insertions(+), 4 deletions(-) diff --git a/.github/workflows/blocked.yaml b/.github/workflows/blocked.yaml index 12a4b0204..cc7db7477 100644 --- a/.github/workflows/blocked.yaml +++ b/.github/workflows/blocked.yaml @@ -1,7 +1,16 @@ name: Prevent blocked on: + # zizmor: ignore[dangerous-triggers] + # Reason: This workflow does not checkout code or use secrets. + # It only reads labels to set a failure status on the PR. pull_request_target: types: [opened, labeled, unlabeled, synchronize] + +permissions: + pull-requests: read + # Required to fail the check on the PR + statuses: write + jobs: prevent-blocked: name: Prevent blocked diff --git a/.github/workflows/build-element-call.yaml b/.github/workflows/build-element-call.yaml index 300138e0a..3ddabb0b6 100644 --- a/.github/workflows/build-element-call.yaml +++ b/.github/workflows/build-element-call.yaml @@ -45,7 +45,7 @@ jobs: - name: Install dependencies run: "yarn install --immutable" - name: Build Element Call - run: ${{ format('yarn run build:{0}:{1}', inputs.package, inputs.build_mode) }} + run: yarn run build:"$PACKAGE":"$BUILD_MODE" env: SENTRY_ORG: ${{ secrets.SENTRY_ORG }} SENTRY_PROJECT: ${{ secrets.SENTRY_PROJECT }} @@ -54,6 +54,8 @@ jobs: CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} VITE_APP_VERSION: ${{ inputs.vite_app_version }} NODE_OPTIONS: "--max-old-space-size=4096" + PACKAGE: ${{ inputs.package }} + BUILD_MODE: ${{ inputs.build_mode }} - name: Upload Artifact uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4 with: diff --git a/.github/workflows/changelog-label.yml b/.github/workflows/changelog-label.yml index 8d9acbc2a..f11d3130a 100644 --- a/.github/workflows/changelog-label.yml +++ b/.github/workflows/changelog-label.yml @@ -1,8 +1,16 @@ name: PR changelog label on: + # zizmor: ignore[dangerous-triggers] + # This is safe because we do not use actions/checkout or execute untrusted code. + # Using pull_request_target is necessary to allow status writes for PRs from forks. pull_request_target: types: [labeled, unlabeled, opened] + +permissions: + pull-requests: read + statuses: write + jobs: pr-changelog-label: runs-on: ubuntu-latest diff --git a/.github/workflows/pr-deploy.yaml b/.github/workflows/pr-deploy.yaml index 138ab2b5f..0084b76b9 100644 --- a/.github/workflows/pr-deploy.yaml +++ b/.github/workflows/pr-deploy.yaml @@ -1,5 +1,7 @@ name: Deploy previews for PRs on: + # zizmor: ignore[dangerous-triggers] + # Reason: This is now restricted to internal PRs only using the 'if' condition below. workflow_run: workflows: ["Build"] types: @@ -7,7 +9,14 @@ on: jobs: prdetails: - if: ${{ github.event.workflow_run.conclusion == 'success' && github.event.workflow_run.event == 'pull_request' }} + # Logic: + # 1. Build must be successful + # 2. Event must be a pull_request + # 3. Head repository must be the SAME as the base repository (No Forks!) + if: > + github.event.workflow_run.conclusion == 'success' && + github.event.workflow_run.event == 'pull_request' && + github.event.workflow_run.head_repository.full_name == github.repository runs-on: ubuntu-latest outputs: pr_number: ${{ steps.prdetails.outputs.pr_id }} diff --git a/.github/workflows/publish-embedded-packages.yaml b/.github/workflows/publish-embedded-packages.yaml index 1c6cd7b1c..3ab275a5d 100644 --- a/.github/workflows/publish-embedded-packages.yaml +++ b/.github/workflows/publish-embedded-packages.yaml @@ -22,8 +22,18 @@ jobs: TAG: ${{ steps.tag.outputs.TAG }} steps: - name: Calculate VERSION - # We should only use the hard coded test value for a dry run - run: echo "VERSION=${{ github.event_name == 'release' && github.event.release.tag_name || 'v0.0.0-pre.0' }}" >> "$GITHUB_ENV" + # Safely store dynamic values in environment variables + # to prevent shell injection (template-injection) + run: | + # The logic is executed within the shell using the env variables + if [ "$EVENT_NAME" = "release" ]; then + echo "VERSION=$RELEASE_TAG" >> "$GITHUB_ENV" + else + echo "VERSION=v0.0.0-pre.0" >> "$GITHUB_ENV" + fi + env: + RELEASE_TAG: ${{ github.event.release.tag_name }} + EVENT_NAME: ${{ github.event_name }} - id: dry_run name: Set DRY_RUN # We perform a dry run for all events except releases. From 3e171d963948976159597761a6232339ce13f25d Mon Sep 17 00:00:00 2001 From: Timo K Date: Thu, 12 Mar 2026 12:25:58 +0100 Subject: [PATCH 367/748] bump tar, minimatch security alert --- package.json | 4 +- yarn.lock | 106 +++++++++------------------------------------------ 2 files changed, 21 insertions(+), 89 deletions(-) diff --git a/package.json b/package.json index 9ee0ad263..da0861729 100644 --- a/package.json +++ b/package.json @@ -138,7 +138,9 @@ }, "resolutions": { "@livekit/components-core/rxjs": "^7.8.1", - "@livekit/track-processors/@mediapipe/tasks-vision": "^0.10.18" + "@livekit/track-processors/@mediapipe/tasks-vision": "^0.10.18", + "minimatch": "^10.2.3", + "tar": "^7.5.11" }, "packageManager": "yarn@4.7.0" } diff --git a/yarn.lock b/yarn.lock index bd90ded3e..b15aeefcd 100644 --- a/yarn.lock +++ b/yarn.lock @@ -6861,13 +6861,6 @@ __metadata: languageName: node linkType: hard -"balanced-match@npm:^1.0.0": - version: 1.0.2 - resolution: "balanced-match@npm:1.0.2" - checksum: 10c0/9308baf0a7e4838a82bbfd11e01b1cb0f0cf2893bc1676c27c2a8c0e70cbae1c59120c3268517a8ae7fb6376b4639ef81ca22582611dbee4ed28df945134aaee - languageName: node - linkType: hard - "balanced-match@npm:^4.0.2": version: 4.0.4 resolution: "balanced-match@npm:4.0.4" @@ -6962,25 +6955,6 @@ __metadata: languageName: node linkType: hard -"brace-expansion@npm:^1.1.7": - version: 1.1.11 - resolution: "brace-expansion@npm:1.1.11" - dependencies: - balanced-match: "npm:^1.0.0" - concat-map: "npm:0.0.1" - checksum: 10c0/695a56cd058096a7cb71fb09d9d6a7070113c7be516699ed361317aca2ec169f618e28b8af352e02ab4233fb54eb0168460a40dc320bab0034b36ab59aaad668 - languageName: node - linkType: hard - -"brace-expansion@npm:^2.0.1": - version: 2.0.1 - resolution: "brace-expansion@npm:2.0.1" - dependencies: - balanced-match: "npm:^1.0.0" - checksum: 10c0/b358f2fe060e2d7a87aa015979ecea07f3c37d4018f8d6deb5bd4c229ad3a0384fe6029bb76cd8be63c81e516ee52d1a0673edbe2023d53a5191732ae3c3e49f - languageName: node - linkType: hard - "brace-expansion@npm:^5.0.2": version: 5.0.3 resolution: "brace-expansion@npm:5.0.3" @@ -7636,13 +7610,6 @@ __metadata: languageName: node linkType: hard -"concat-map@npm:0.0.1": - version: 0.0.1 - resolution: "concat-map@npm:0.0.1" - checksum: 10c0/c996b1cfdf95b6c90fee4dae37e332c8b6eb7d106430c17d538034c0ad9a1630cb194d2ab37293b1bdd4d779494beee7786d586a50bd9376fd6f7bcc2bd4c98f - languageName: node - linkType: hard - "connect-history-api-fallback@npm:^1.6.0": version: 1.6.0 resolution: "connect-history-api-fallback@npm:1.6.0" @@ -10447,9 +10414,9 @@ __metadata: linkType: hard "immutable@npm:^5.0.2": - version: 5.0.3 - resolution: "immutable@npm:5.0.3" - checksum: 10c0/3269827789e1026cd25c2ea97f0b2c19be852ffd49eda1b674b20178f73d84fa8d945ad6f5ac5bc4545c2b4170af9f6e1f77129bc1cae7974a4bf9b04a9cdfb9 + version: 5.1.5 + resolution: "immutable@npm:5.1.5" + checksum: 10c0/8017ece1578e3c5939ba3305176aee059def1b8a90c7fa2a347ef583ebbd38cbe77ce1bbd786a5fab57e2da00bbcb0493b92e4332cdc4e1fe5cfb09a4688df31 languageName: node linkType: hard @@ -11633,48 +11600,12 @@ __metadata: languageName: node linkType: hard -"minimatch@npm:^10.2.2": - version: 10.2.3 - resolution: "minimatch@npm:10.2.3" +"minimatch@npm:^10.2.3": + version: 10.2.4 + resolution: "minimatch@npm:10.2.4" dependencies: brace-expansion: "npm:^5.0.2" - checksum: 10c0/d9ae5f355e8bb77a42dd8c20b950141cec8773ef8716a2bb6df7a6840cc44a00ed828883884e4f1c7b5cb505fa06a17e3ea9ca2edb18fd1dec865ea7f9fcf0e5 - languageName: node - linkType: hard - -"minimatch@npm:^3.0.2, minimatch@npm:^3.0.4, minimatch@npm:^3.0.5, minimatch@npm:^3.1.1, minimatch@npm:^3.1.2": - version: 3.1.2 - resolution: "minimatch@npm:3.1.2" - dependencies: - brace-expansion: "npm:^1.1.7" - checksum: 10c0/0262810a8fc2e72cca45d6fd86bd349eee435eb95ac6aa45c9ea2180e7ee875ef44c32b55b5973ceabe95ea12682f6e3725cbb63d7a2d1da3ae1163c8b210311 - languageName: node - linkType: hard - -"minimatch@npm:^5.0.1": - version: 5.1.6 - resolution: "minimatch@npm:5.1.6" - dependencies: - brace-expansion: "npm:^2.0.1" - checksum: 10c0/3defdfd230914f22a8da203747c42ee3c405c39d4d37ffda284dac5e45b7e1f6c49aa8be606509002898e73091ff2a3bbfc59c2c6c71d4660609f63aa92f98e3 - languageName: node - linkType: hard - -"minimatch@npm:^8.0.2": - version: 8.0.4 - resolution: "minimatch@npm:8.0.4" - dependencies: - brace-expansion: "npm:^2.0.1" - checksum: 10c0/a0a394c356dd5b4cb7f821720841a82fa6f07c9c562c5b716909d1b6ec5e56a7e4c4b5029da26dd256b7d2b3a3f38cbf9ddd8680e887b9b5282b09c05501c1ca - languageName: node - linkType: hard - -"minimatch@npm:^9.0.4": - version: 9.0.5 - resolution: "minimatch@npm:9.0.5" - dependencies: - brace-expansion: "npm:^2.0.1" - checksum: 10c0/de96cf5e35bdf0eab3e2c853522f98ffbe9a36c37797778d2665231ec1f20a9447a7e567cb640901f89e4daaa95ae5d70c65a9e8aa2bb0019b6facbc3c0575ed + checksum: 10c0/35f3dfb7b99b51efd46afd378486889f590e7efb10e0f6a10ba6800428cf65c9a8dedb74427d0570b318d749b543dc4e85f06d46d2858bc8cac7e1eb49a95945 languageName: node linkType: hard @@ -11769,12 +11700,12 @@ __metadata: languageName: node linkType: hard -"mkdirp@npm:^3.0.1": - version: 3.0.1 - resolution: "mkdirp@npm:3.0.1" - bin: - mkdirp: dist/cjs/src/bin.js - checksum: 10c0/9f2b975e9246351f5e3a40dcfac99fcd0baa31fbfab615fe059fb11e51f10e4803c63de1f384c54d656e4db31d000e4767e9ef076a22e12a641357602e31d57d +"minizlib@npm:^3.1.0": + version: 3.1.0 + resolution: "minizlib@npm:3.1.0" + dependencies: + minipass: "npm:^7.1.2" + checksum: 10c0/5aad75ab0090b8266069c9aabe582c021ae53eb33c6c691054a13a45db3b4f91a7fb1bd79151e6b4e9e9a86727b522527c0a06ec7d45206b745d54cd3097bcec languageName: node linkType: hard @@ -14689,17 +14620,16 @@ __metadata: languageName: node linkType: hard -"tar@npm:^7.4.3": - version: 7.4.3 - resolution: "tar@npm:7.4.3" +"tar@npm:^7.5.11": + version: 7.5.11 + resolution: "tar@npm:7.5.11" dependencies: "@isaacs/fs-minipass": "npm:^4.0.0" chownr: "npm:^3.0.0" minipass: "npm:^7.1.2" - minizlib: "npm:^3.0.1" - mkdirp: "npm:^3.0.1" + minizlib: "npm:^3.1.0" yallist: "npm:^5.0.0" - checksum: 10c0/d4679609bb2a9b48eeaf84632b6d844128d2412b95b6de07d53d8ee8baf4ca0857c9331dfa510390a0727b550fd543d4d1a10995ad86cdf078423fbb8d99831d + checksum: 10c0/b6bb420550ef50ef23356018155e956cd83282c97b6128d8d5cfe5740c57582d806a244b2ef0bf686a74ce526babe8b8b9061527623e935e850008d86d838929 languageName: node linkType: hard From a0d5c7999932683e844d50387bb8939fbf039687 Mon Sep 17 00:00:00 2001 From: Timo K Date: Thu, 12 Mar 2026 14:52:16 +0100 Subject: [PATCH 368/748] also update coverage --- package.json | 5 +- yarn.lock | 170 +++++++++++++++++---------------------------------- 2 files changed, 57 insertions(+), 118 deletions(-) diff --git a/package.json b/package.json index 30d63a2ed..19c74d605 100644 --- a/package.json +++ b/package.json @@ -79,7 +79,7 @@ "@vector-im/compound-design-tokens": "^6.0.0", "@vector-im/compound-web": "^8.0.0", "@vitejs/plugin-react": "^4.0.1", - "@vitest/coverage-v8": "^3.0.0", + "@vitest/coverage-v8": "^4.0.18", "babel-plugin-transform-vite-meta-env": "^1.0.3", "classnames": "^2.3.1", "copy-to-clipboard": "^3.3.3", @@ -138,8 +138,7 @@ }, "resolutions": { "@livekit/components-core/rxjs": "^7.8.1", - "@livekit/track-processors/@mediapipe/tasks-vision": "^0.10.18", - "rollup": "4.59.0" + "@livekit/track-processors/@mediapipe/tasks-vision": "^0.10.18" }, "packageManager": "yarn@4.7.0" } diff --git a/yarn.lock b/yarn.lock index 552e77688..38c2e7aca 100644 --- a/yarn.lock +++ b/yarn.lock @@ -60,16 +60,6 @@ __metadata: languageName: node linkType: hard -"@ampproject/remapping@npm:^2.3.0": - version: 2.3.0 - resolution: "@ampproject/remapping@npm:2.3.0" - dependencies: - "@jridgewell/gen-mapping": "npm:^0.3.5" - "@jridgewell/trace-mapping": "npm:^0.3.24" - checksum: 10c0/81d63cca5443e0f0c72ae18b544cc28c7c0ec2cea46e7cb888bb0e0f411a1191d0d6b7af798d54e30777d8d1488b2ec0732aac2be342d3d7d3ffd271c6f489ed - languageName: node - linkType: hard - "@asamuzakjp/css-color@npm:^2.8.2": version: 2.8.2 resolution: "@asamuzakjp/css-color@npm:2.8.2" @@ -585,7 +575,7 @@ __metadata: languageName: node linkType: hard -"@babel/parser@npm:^7.25.4, @babel/parser@npm:^7.25.9, @babel/parser@npm:^7.26.9": +"@babel/parser@npm:^7.25.9, @babel/parser@npm:^7.26.9": version: 7.26.9 resolution: "@babel/parser@npm:7.26.9" dependencies: @@ -1743,7 +1733,7 @@ __metadata: languageName: node linkType: hard -"@babel/types@npm:^7.25.4, @babel/types@npm:^7.25.9, @babel/types@npm:^7.26.5, @babel/types@npm:^7.26.9, @babel/types@npm:^7.4.4": +"@babel/types@npm:^7.25.9, @babel/types@npm:^7.26.5, @babel/types@npm:^7.26.9, @babel/types@npm:^7.4.4": version: 7.26.9 resolution: "@babel/types@npm:7.26.9" dependencies: @@ -3188,13 +3178,6 @@ __metadata: languageName: node linkType: hard -"@istanbuljs/schema@npm:^0.1.2": - version: 0.1.3 - resolution: "@istanbuljs/schema@npm:0.1.3" - checksum: 10c0/61c5286771676c9ca3eb2bd8a7310a9c063fb6e0e9712225c8471c582d157392c88f5353581c8c9adbe0dff98892317d2fdfc56c3499aa42e0194405206a963a - languageName: node - linkType: hard - "@jridgewell/gen-mapping@npm:^0.3.12": version: 0.3.12 resolution: "@jridgewell/gen-mapping@npm:0.3.12" @@ -3264,7 +3247,7 @@ __metadata: languageName: node linkType: hard -"@jridgewell/trace-mapping@npm:^0.3.23, @jridgewell/trace-mapping@npm:^0.3.24, @jridgewell/trace-mapping@npm:^0.3.25": +"@jridgewell/trace-mapping@npm:^0.3.24, @jridgewell/trace-mapping@npm:^0.3.25": version: 0.3.25 resolution: "@jridgewell/trace-mapping@npm:0.3.25" dependencies: @@ -3284,6 +3267,16 @@ __metadata: languageName: node linkType: hard +"@jridgewell/trace-mapping@npm:^0.3.31": + version: 0.3.31 + resolution: "@jridgewell/trace-mapping@npm:0.3.31" + dependencies: + "@jridgewell/resolve-uri": "npm:^3.1.0" + "@jridgewell/sourcemap-codec": "npm:^1.4.14" + checksum: 10c0/4b30ec8cd56c5fd9a661f088230af01e0c1a3888d11ffb6b47639700f71225be21d1f7e168048d6d4f9449207b978a235c07c8f15c07705685d16dc06280e9d9 + languageName: node + linkType: hard + "@livekit/components-core@npm:0.12.12, @livekit/components-core@npm:^0.12.0": version: 0.12.12 resolution: "@livekit/components-core@npm:0.12.12" @@ -6306,30 +6299,27 @@ __metadata: languageName: node linkType: hard -"@vitest/coverage-v8@npm:^3.0.0": - version: 3.2.4 - resolution: "@vitest/coverage-v8@npm:3.2.4" +"@vitest/coverage-v8@npm:^4.0.18": + version: 4.0.18 + resolution: "@vitest/coverage-v8@npm:4.0.18" dependencies: - "@ampproject/remapping": "npm:^2.3.0" "@bcoe/v8-coverage": "npm:^1.0.2" - ast-v8-to-istanbul: "npm:^0.3.3" - debug: "npm:^4.4.1" + "@vitest/utils": "npm:4.0.18" + ast-v8-to-istanbul: "npm:^0.3.10" istanbul-lib-coverage: "npm:^3.2.2" istanbul-lib-report: "npm:^3.0.1" - istanbul-lib-source-maps: "npm:^5.0.6" - istanbul-reports: "npm:^3.1.7" - magic-string: "npm:^0.30.17" - magicast: "npm:^0.3.5" - std-env: "npm:^3.9.0" - test-exclude: "npm:^7.0.1" - tinyrainbow: "npm:^2.0.0" + istanbul-reports: "npm:^3.2.0" + magicast: "npm:^0.5.1" + obug: "npm:^2.1.1" + std-env: "npm:^3.10.0" + tinyrainbow: "npm:^3.0.3" peerDependencies: - "@vitest/browser": 3.2.4 - vitest: 3.2.4 + "@vitest/browser": 4.0.18 + vitest: 4.0.18 peerDependenciesMeta: "@vitest/browser": optional: true - checksum: 10c0/cae3e58d81d56e7e1cdecd7b5baab7edd0ad9dee8dec9353c52796e390e452377d3f04174d40b6986b17c73241a5e773e422931eaa8102dcba0605ff24b25193 + checksum: 10c0/e23e0da86f0b2a020c51562bc40ebdc7fc7553c24f8071dfb39a6df0161badbd5eaf2eebbf8ceaef18933a18c1934ff52d1c0c4bde77bb87e0c1feb0c8cbee4d languageName: node linkType: hard @@ -6775,14 +6765,14 @@ __metadata: languageName: node linkType: hard -"ast-v8-to-istanbul@npm:^0.3.3": - version: 0.3.3 - resolution: "ast-v8-to-istanbul@npm:0.3.3" +"ast-v8-to-istanbul@npm:^0.3.10": + version: 0.3.12 + resolution: "ast-v8-to-istanbul@npm:0.3.12" dependencies: - "@jridgewell/trace-mapping": "npm:^0.3.25" + "@jridgewell/trace-mapping": "npm:^0.3.31" estree-walker: "npm:^3.0.3" - js-tokens: "npm:^9.0.1" - checksum: 10c0/ffc39bc3ab4b8c1f7aea945960ce6b1e518bab3da7c800277eab2da07d397eeae4a2cb8a5a5f817225646c8ea495c1e4434fbe082c84bae8042abddef53f50b2 + js-tokens: "npm:^10.0.0" + checksum: 10c0/bad6ba222b1073c165c8d65dbf366193d4a90536dabe37f93a3df162269b1c9473975756e4c048f708c235efccc26f8e5321c547b7e9563b64b21b2e0f27cbc9 languageName: node linkType: hard @@ -7990,7 +7980,7 @@ __metadata: languageName: node linkType: hard -"debug@npm:4, debug@npm:^4.1.0, debug@npm:^4.1.1, debug@npm:^4.3.1, debug@npm:^4.3.4": +"debug@npm:4, debug@npm:^4.1.0, debug@npm:^4.3.1, debug@npm:^4.3.4": version: 4.4.0 resolution: "debug@npm:4.4.0" dependencies: @@ -8032,18 +8022,6 @@ __metadata: languageName: node linkType: hard -"debug@npm:^4.4.1": - version: 4.4.1 - resolution: "debug@npm:4.4.1" - dependencies: - ms: "npm:^2.1.3" - peerDependenciesMeta: - supports-color: - optional: true - checksum: 10c0/d2b44bc1afd912b49bb7ebb0d50a860dc93a4dd7d946e8de94abc957bb63726b7dd5aa48c18c2386c379ec024c46692e15ed3ed97d481729f929201e671fcd55 - languageName: node - linkType: hard - "debug@npm:^4.4.3": version: 4.4.3 resolution: "debug@npm:4.4.3" @@ -8409,7 +8387,7 @@ __metadata: "@vector-im/compound-design-tokens": "npm:^6.0.0" "@vector-im/compound-web": "npm:^8.0.0" "@vitejs/plugin-react": "npm:^4.0.1" - "@vitest/coverage-v8": "npm:^3.0.0" + "@vitest/coverage-v8": "npm:^4.0.18" babel-plugin-transform-vite-meta-env: "npm:^1.0.3" classnames: "npm:^2.3.1" copy-to-clipboard: "npm:^3.3.3" @@ -9954,7 +9932,7 @@ __metadata: languageName: node linkType: hard -"glob@npm:^10.2.2, glob@npm:^10.3.10, glob@npm:^10.3.7, glob@npm:^10.4.1": +"glob@npm:^10.2.2, glob@npm:^10.3.10, glob@npm:^10.3.7": version: 10.4.5 resolution: "glob@npm:10.4.5" dependencies: @@ -10915,24 +10893,13 @@ __metadata: languageName: node linkType: hard -"istanbul-lib-source-maps@npm:^5.0.6": - version: 5.0.6 - resolution: "istanbul-lib-source-maps@npm:5.0.6" - dependencies: - "@jridgewell/trace-mapping": "npm:^0.3.23" - debug: "npm:^4.1.1" - istanbul-lib-coverage: "npm:^3.0.0" - checksum: 10c0/ffe75d70b303a3621ee4671554f306e0831b16f39ab7f4ab52e54d356a5d33e534d97563e318f1333a6aae1d42f91ec49c76b6cd3f3fb378addcb5c81da0255f - languageName: node - linkType: hard - -"istanbul-reports@npm:^3.1.7": - version: 3.1.7 - resolution: "istanbul-reports@npm:3.1.7" +"istanbul-reports@npm:^3.2.0": + version: 3.2.0 + resolution: "istanbul-reports@npm:3.2.0" dependencies: html-escaper: "npm:^2.0.0" istanbul-lib-report: "npm:^3.0.0" - checksum: 10c0/a379fadf9cf8dc5dfe25568115721d4a7eb82fbd50b005a6672aff9c6989b20cc9312d7865814e0859cd8df58cbf664482e1d3604be0afde1f7fc3ccc1394a51 + checksum: 10c0/d596317cfd9c22e1394f22a8d8ba0303d2074fe2e971887b32d870e4b33f8464b10f8ccbe6847808f7db485f084eba09e6c2ed706b3a978e4b52f07085b8f9bc languageName: node linkType: hard @@ -11000,6 +10967,13 @@ __metadata: languageName: node linkType: hard +"js-tokens@npm:^10.0.0": + version: 10.0.0 + resolution: "js-tokens@npm:10.0.0" + checksum: 10c0/a93498747812ba3e0c8626f95f75ab29319f2a13613a0de9e610700405760931624433a0de59eb7c27ff8836e526768fb20783861b86ef89be96676f2c996b64 + languageName: node + linkType: hard + "js-tokens@npm:^3.0.0 || ^4.0.0, js-tokens@npm:^4.0.0": version: 4.0.0 resolution: "js-tokens@npm:4.0.0" @@ -11007,13 +10981,6 @@ __metadata: languageName: node linkType: hard -"js-tokens@npm:^9.0.1": - version: 9.0.1 - resolution: "js-tokens@npm:9.0.1" - checksum: 10c0/68dcab8f233dde211a6b5fd98079783cbcd04b53617c1250e3553ee16ab3e6134f5e65478e41d82f6d351a052a63d71024553933808570f04dbf828d7921e80e - languageName: node - linkType: hard - "js-yaml@npm:^4.1.0": version: 4.1.0 resolution: "js-yaml@npm:4.1.0" @@ -11415,15 +11382,6 @@ __metadata: languageName: node linkType: hard -"magic-string@npm:^0.30.17": - version: 0.30.17 - resolution: "magic-string@npm:0.30.17" - dependencies: - "@jridgewell/sourcemap-codec": "npm:^1.5.0" - checksum: 10c0/16826e415d04b88378f200fe022b53e638e3838b9e496edda6c0e086d7753a44a6ed187adc72d19f3623810589bf139af1a315541cd6a26ae0771a0193eaf7b8 - languageName: node - linkType: hard - "magic-string@npm:^0.30.21, magic-string@npm:^0.30.3": version: 0.30.21 resolution: "magic-string@npm:0.30.21" @@ -11433,14 +11391,14 @@ __metadata: languageName: node linkType: hard -"magicast@npm:^0.3.5": - version: 0.3.5 - resolution: "magicast@npm:0.3.5" +"magicast@npm:^0.5.1": + version: 0.5.2 + resolution: "magicast@npm:0.5.2" dependencies: - "@babel/parser": "npm:^7.25.4" - "@babel/types": "npm:^7.25.4" - source-map-js: "npm:^1.2.0" - checksum: 10c0/a6cacc0a848af84f03e3f5bda7b0de75e4d0aa9ddce5517fd23ed0f31b5ddd51b2d0ff0b7e09b51f7de0f4053c7a1107117edda6b0732dca3e9e39e6c5a68c64 + "@babel/parser": "npm:^7.29.0" + "@babel/types": "npm:^7.29.0" + source-map-js: "npm:^1.2.1" + checksum: 10c0/924af677643c5a0a7d6cdb3247c0eb96fa7611b2ba6a5e720d35d81c503d3d9f5948eb5227f80f90f82ea3e7d38cffd10bb988f3fc09020db428e14f26e960d7 languageName: node linkType: hard @@ -13769,7 +13727,7 @@ __metadata: languageName: node linkType: hard -"rollup@npm:4.59.0": +"rollup@npm:^4.43.0": version: 4.59.0 resolution: "rollup@npm:4.59.0" dependencies: @@ -14290,7 +14248,7 @@ __metadata: languageName: node linkType: hard -"source-map-js@npm:>=0.6.2 <2.0.0, source-map-js@npm:^1.2.0, source-map-js@npm:^1.2.1": +"source-map-js@npm:>=0.6.2 <2.0.0, source-map-js@npm:^1.2.1": version: 1.2.1 resolution: "source-map-js@npm:1.2.1" checksum: 10c0/7bda1fc4c197e3c6ff17de1b8b2c20e60af81b63a52cb32ec5a5d67a20a7d42651e2cb34ebe93833c5a2a084377e17455854fee3e21e7925c64a51b6a52b0faf @@ -14388,13 +14346,6 @@ __metadata: languageName: node linkType: hard -"std-env@npm:^3.9.0": - version: 3.9.0 - resolution: "std-env@npm:3.9.0" - checksum: 10c0/4a6f9218aef3f41046c3c7ecf1f98df00b30a07f4f35c6d47b28329bc2531eef820828951c7d7b39a1c5eb19ad8a46e3ddfc7deb28f0a2f3ceebee11bab7ba50 - languageName: node - linkType: hard - "stop-iteration-iterator@npm:^1.1.0": version: 1.1.0 resolution: "stop-iteration-iterator@npm:1.1.0" @@ -14708,17 +14659,6 @@ __metadata: languageName: node linkType: hard -"test-exclude@npm:^7.0.1": - version: 7.0.1 - resolution: "test-exclude@npm:7.0.1" - dependencies: - "@istanbuljs/schema": "npm:^0.1.2" - glob: "npm:^10.4.1" - minimatch: "npm:^9.0.4" - checksum: 10c0/6d67b9af4336a2e12b26a68c83308c7863534c65f27ed4ff7068a56f5a58f7ac703e8fc80f698a19bb154fd8f705cdf7ec347d9512b2c522c737269507e7b263 - languageName: node - linkType: hard - "text-decoder@npm:^1.1.0": version: 1.2.3 resolution: "text-decoder@npm:1.2.3" From 8ecb1b3dbf2dacc95ea20a731b6367ab81e510aa Mon Sep 17 00:00:00 2001 From: JephDiel Date: Thu, 12 Mar 2026 22:18:38 -0500 Subject: [PATCH 369/748] Simplify widget detection Use the exists check for the widget API directly instead of a feature flag. --- src/Avatar.test.tsx | 21 ++++++++------------- src/Avatar.tsx | 16 ++++++++-------- src/ClientContext.tsx | 8 -------- src/settings/useSubmitRageshake.test.tsx | 1 - 4 files changed, 16 insertions(+), 30 deletions(-) diff --git a/src/Avatar.test.tsx b/src/Avatar.test.tsx index 3d75d4c12..debff26a2 100644 --- a/src/Avatar.test.tsx +++ b/src/Avatar.test.tsx @@ -13,19 +13,14 @@ import { type FC, type PropsWithChildren } from "react"; import { ClientContextProvider } from "./ClientContext"; import { Avatar } from "./Avatar"; import { mockMatrixRoomMember, mockRtcMembership } from "./utils/test"; -import EventEmitter from "events"; import { widget } from "./widget"; +import { WidgetApi } from "matrix-widget-api"; const TestComponent: FC< PropsWithChildren<{ client: MatrixClient; - supportsAuthenticatedMedia?: boolean; }> -> = ({ - client, - children, - supportsAuthenticatedMedia: supportsAuthenticatedMedia, -}) => { +> = ({ client, children }) => { return ( ({ widget: { - api: { downloadFile: vi.fn() }, + api: null, // Ideally we'd only mock this in the as a widget test so the whole module is otherwise null, but just nulling `api` by default works well enough }, })); @@ -88,7 +82,7 @@ test("should just render a placeholder when the user has no avatar", () => { expect(client.mxcUrlToHttp).toBeCalledTimes(0); }); -test("should attempt to fetch authenticated media if supported", async () => { +test("should attempt to fetch authenticated media from the server", async () => { const expectedAuthUrl = "http://example.org/media/alice-avatar"; const expectedObjectURL = "my-object-url"; const accessToken = "my-access-token"; @@ -120,7 +114,7 @@ test("should attempt to fetch authenticated media if supported", async () => { ); const displayName = "Alice"; render( - + { }); }); -test("should attempt to use widget API if authenticate media is not supported", async () => { +test("should attempt to use widget API if running as a widget", async () => { const expectedMXCUrl = "mxc://example.org/alice-avatar"; const expectedObjectURL = "my-object-url"; const theBlob = new Blob([]); @@ -157,6 +151,7 @@ test("should attempt to use widget API if authenticate media is not supported", getAccessToken: () => undefined, } as unknown as MatrixClient); + widget!.api = { downloadFile: vi.fn() } as unknown as WidgetApi; vi.spyOn(widget!.api, "downloadFile").mockResolvedValue({ file: theBlob }); const member = mockMatrixRoomMember( mockRtcMembership("@alice:example.org", "AAAA"), @@ -166,7 +161,7 @@ test("should attempt to use widget API if authenticate media is not supported", ); const displayName = "Alice"; render( - + = ({ const [avatarUrl, setAvatarUrl] = useState(undefined); + // In theory, a change in `clientState` or `sizePx` could run extra getAvatarFromWidgetAPI calls, but in practice they should be stable long before this code runs. useEffect(() => { - if (!src || clientState?.state !== "valid") { + if (!src) { setAvatarUrl(undefined); return; } - const { authenticated, supportedFeatures } = clientState; let blob: Promise; - if ( - supportedFeatures.authenticatedMedia && - authenticated?.client && + if (widget?.api) { + blob = getAvatarFromWidgetAPI(widget.api, src); + } else if ( + clientState?.state === "valid" && + clientState.authenticated?.client && sizePx ) { - blob = getAvatarFromServer(authenticated.client, src, sizePx); - } else if (widget?.api) { - blob = getAvatarFromWidgetAPI(widget.api, src); + blob = getAvatarFromServer(clientState.authenticated.client, src, sizePx); } else { setAvatarUrl(undefined); return; diff --git a/src/ClientContext.tsx b/src/ClientContext.tsx index 7059cd693..f2ff3dd4b 100644 --- a/src/ClientContext.tsx +++ b/src/ClientContext.tsx @@ -48,7 +48,6 @@ export type ValidClientState = { disconnected: boolean; supportedFeatures: { reactions: boolean; - authenticatedMedia: boolean; }; setClient: (client: MatrixClient, session: Session) => void; }; @@ -249,8 +248,6 @@ export const ClientProvider: FC = ({ children }) => { const [isDisconnected, setIsDisconnected] = useState(false); const [supportsReactions, setSupportsReactions] = useState(false); - const [supportsAuthenticatedMedia, setSupportsAuthenticatedMedia] = - useState(false); const state: ClientState | undefined = useMemo(() => { if (alreadyOpenedErr) { @@ -276,7 +273,6 @@ export const ClientProvider: FC = ({ children }) => { disconnected: isDisconnected, supportedFeatures: { reactions: supportsReactions, - authenticatedMedia: supportsAuthenticatedMedia, }, }; }, [ @@ -287,7 +283,6 @@ export const ClientProvider: FC = ({ children }) => { setClient, isDisconnected, supportsReactions, - supportsAuthenticatedMedia, ]); const onSync = useCallback( @@ -313,8 +308,6 @@ export const ClientProvider: FC = ({ children }) => { } if (initClientState.widgetApi) { - // There is currently no way for widgets to request authenticated media directly from the server. - setSupportsAuthenticatedMedia(false); const reactSend = initClientState.widgetApi.hasCapability( "org.matrix.msc2762.send.event:m.reaction", ); @@ -336,7 +329,6 @@ export const ClientProvider: FC = ({ children }) => { } } else { setSupportsReactions(true); - setSupportsAuthenticatedMedia(true); } return (): void => { diff --git a/src/settings/useSubmitRageshake.test.tsx b/src/settings/useSubmitRageshake.test.tsx index d69255e03..b5d075532 100644 --- a/src/settings/useSubmitRageshake.test.tsx +++ b/src/settings/useSubmitRageshake.test.tsx @@ -78,7 +78,6 @@ function renderWithMockClient( disconnected: false, supportedFeatures: { reactions: true, - authenticatedMedia: true, }, setClient: vi.fn(), authenticated: { From b1987219690ff9b36bb9c213e1e71e44fd5c66fa Mon Sep 17 00:00:00 2001 From: JephDiel Date: Thu, 12 Mar 2026 22:20:19 -0500 Subject: [PATCH 370/748] Ignore stale downloads If src or sizePx changes while we're downloading, discard the now-stale fetch result so we don't override the fresh one. --- src/Avatar.tsx | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/Avatar.tsx b/src/Avatar.tsx index 8d89865e2..d7768d6f5 100644 --- a/src/Avatar.tsx +++ b/src/Avatar.tsx @@ -110,16 +110,24 @@ export const Avatar: FC = ({ } let objectUrl: string | undefined; + let stale = false; blob .then((blob) => { + if (stale) { + return; + } objectUrl = URL.createObjectURL(blob); setAvatarUrl(objectUrl); }) .catch((ex) => { + if (stale) { + return; + } setAvatarUrl(undefined); }); return (): void => { + stale = true; if (objectUrl) { URL.revokeObjectURL(objectUrl); } From 7da9bca08c5c50ae41478296837ab688658510ef Mon Sep 17 00:00:00 2001 From: Timo K Date: Fri, 13 Mar 2026 07:59:49 +0100 Subject: [PATCH 371/748] update qs, js-yaml, glob for security patches --- package.json | 5 +- yarn.lock | 164 ++++++++++++++------------------------------------- 2 files changed, 49 insertions(+), 120 deletions(-) diff --git a/package.json b/package.json index 04a48dc2b..cc8a36eb1 100644 --- a/package.json +++ b/package.json @@ -140,7 +140,10 @@ "@livekit/components-core/rxjs": "^7.8.1", "@livekit/track-processors/@mediapipe/tasks-vision": "^0.10.18", "minimatch": "^10.2.3", - "tar": "^7.5.11" + "tar": "^7.5.11", + "glob": "^10.5.0", + "qs": "^6.14.1", + "js-yaml": "^4.1.1" }, "packageManager": "yarn@4.7.0" } diff --git a/yarn.lock b/yarn.lock index a3f6b921b..12e1b8578 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2901,20 +2901,13 @@ __metadata: languageName: node linkType: hard -"@eslint-community/regexpp@npm:^4.12.2": +"@eslint-community/regexpp@npm:^4.12.2, @eslint-community/regexpp@npm:^4.6.1": version: 4.12.2 resolution: "@eslint-community/regexpp@npm:4.12.2" checksum: 10c0/fddcbc66851b308478d04e302a4d771d6917a0b3740dc351513c0da9ca2eab8a1adf99f5e0aa7ab8b13fa0df005c81adeee7e63a92f3effd7d367a163b721c2d languageName: node linkType: hard -"@eslint-community/regexpp@npm:^4.6.1": - version: 4.11.1 - resolution: "@eslint-community/regexpp@npm:4.11.1" - checksum: 10c0/fbcc1cb65ef5ed5b92faa8dc542e035269065e7ebcc0b39c81a4fe98ad35cfff20b3c8df048641de15a7757e07d69f85e2579c1a5055f993413ba18c055654f8 - languageName: node - linkType: hard - "@eslint/eslintrc@npm:^2.1.4": version: 2.1.4 resolution: "@eslint/eslintrc@npm:2.1.4" @@ -6218,9 +6211,9 @@ __metadata: linkType: hard "@ungap/structured-clone@npm:^1.2.0": - version: 1.2.0 - resolution: "@ungap/structured-clone@npm:1.2.0" - checksum: 10c0/8209c937cb39119f44eb63cf90c0b73e7c754209a6411c707be08e50e29ee81356dca1a848a405c8bdeebfe2f5e4f831ad310ae1689eeef65e7445c090c6657d + version: 1.3.0 + resolution: "@ungap/structured-clone@npm:1.3.0" + checksum: 10c0/0fc3097c2540ada1fc340ee56d58d96b5b536a2a0dab6e3ec17d4bfc8c4c86db345f61a375a8185f9da96f01c69678f836a2b57eeaa9e4b8eeafd26428e57b0a languageName: node linkType: hard @@ -6437,7 +6430,7 @@ __metadata: languageName: node linkType: hard -"acorn@npm:^8.16.0": +"acorn@npm:^8.16.0, acorn@npm:^8.9.0": version: 8.16.0 resolution: "acorn@npm:8.16.0" bin: @@ -6446,15 +6439,6 @@ __metadata: languageName: node linkType: hard -"acorn@npm:^8.9.0": - version: 8.12.1 - resolution: "acorn@npm:8.12.1" - bin: - acorn: bin/acorn - checksum: 10c0/51fb26cd678f914e13287e886da2d7021f8c2bc0ccc95e03d3e0447ee278dd3b40b9c57dc222acd5881adcf26f3edc40901a4953403232129e3876793cd17386 - languageName: node - linkType: hard - "agent-base@npm:6": version: 6.0.2 resolution: "agent-base@npm:6.0.2" @@ -6481,14 +6465,14 @@ __metadata: linkType: hard "ajv@npm:^6.12.4": - version: 6.12.6 - resolution: "ajv@npm:6.12.6" + version: 6.14.0 + resolution: "ajv@npm:6.14.0" dependencies: fast-deep-equal: "npm:^3.1.1" fast-json-stable-stringify: "npm:^2.0.0" json-schema-traverse: "npm:^0.4.1" uri-js: "npm:^4.2.2" - checksum: 10c0/41e23642cbe545889245b9d2a45854ebba51cda6c778ebced9649420d9205f2efb39cb43dbc41e358409223b1ea43303ae4839db682c848b891e4811da1a5a71 + checksum: 10c0/a2bc39b0555dc9802c899f86990eb8eed6e366cddbf65be43d5aa7e4f3c4e1a199d5460fd7ca4fb3d864000dbbc049253b72faa83b3b30e641ca52cb29a68c22 languageName: node linkType: hard @@ -7749,18 +7733,7 @@ __metadata: languageName: node linkType: hard -"cross-spawn@npm:^7.0.2": - version: 7.0.3 - resolution: "cross-spawn@npm:7.0.3" - dependencies: - path-key: "npm:^3.1.0" - shebang-command: "npm:^2.0.0" - which: "npm:^2.0.1" - checksum: 10c0/5738c312387081c98d69c98e105b6327b069197f864a60593245d64c8089c8a0a744e16349281210d56835bb9274130d825a78b2ad6853ca13cfbeffc0c31750 - languageName: node - linkType: hard - -"cross-spawn@npm:^7.0.6": +"cross-spawn@npm:^7.0.2, cross-spawn@npm:^7.0.6": version: 7.0.6 resolution: "cross-spawn@npm:7.0.6" dependencies: @@ -9308,16 +9281,7 @@ __metadata: languageName: node linkType: hard -"esquery@npm:^1.4.2, esquery@npm:^1.6.0": - version: 1.6.0 - resolution: "esquery@npm:1.6.0" - dependencies: - estraverse: "npm:^5.1.0" - checksum: 10c0/cb9065ec605f9da7a76ca6dadb0619dfb611e37a81e318732977d90fab50a256b95fee2d925fba7c2f3f0523aa16f91587246693bc09bc34d5a59575fe6e93d2 - languageName: node - linkType: hard - -"esquery@npm:^1.7.0": +"esquery@npm:^1.4.2, esquery@npm:^1.7.0": version: 1.7.0 resolution: "esquery@npm:1.7.0" dependencies: @@ -9326,6 +9290,15 @@ __metadata: languageName: node linkType: hard +"esquery@npm:^1.6.0": + version: 1.6.0 + resolution: "esquery@npm:1.6.0" + dependencies: + estraverse: "npm:^5.1.0" + checksum: 10c0/cb9065ec605f9da7a76ca6dadb0619dfb611e37a81e318732977d90fab50a256b95fee2d925fba7c2f3f0523aa16f91587246693bc09bc34d5a59575fe6e93d2 + languageName: node + linkType: hard + "esrecurse@npm:^4.3.0": version: 4.3.0 resolution: "esrecurse@npm:4.3.0" @@ -9700,13 +9673,6 @@ __metadata: languageName: node linkType: hard -"fs.realpath@npm:^1.0.0": - version: 1.0.0 - resolution: "fs.realpath@npm:1.0.0" - checksum: 10c0/444cf1291d997165dfd4c0d58b69f0e4782bfd9149fd72faa4fe299e68e0e93d6db941660b37dd29153bf7186672ececa3b50b7e7249477b03fdf850f287c948 - languageName: node - linkType: hard - "fsevents@npm:2.3.2": version: 2.3.2 resolution: "fsevents@npm:2.3.2" @@ -9899,9 +9865,9 @@ __metadata: languageName: node linkType: hard -"glob@npm:^10.2.2, glob@npm:^10.3.10, glob@npm:^10.3.7": - version: 10.4.5 - resolution: "glob@npm:10.4.5" +"glob@npm:^10.5.0": + version: 10.5.0 + resolution: "glob@npm:10.5.0" dependencies: foreground-child: "npm:^3.1.0" jackspeak: "npm:^3.1.2" @@ -9911,33 +9877,7 @@ __metadata: path-scurry: "npm:^1.11.1" bin: glob: dist/esm/bin.mjs - checksum: 10c0/19a9759ea77b8e3ca0a43c2f07ecddc2ad46216b786bb8f993c445aee80d345925a21e5280c7b7c6c59e860a0154b84e4b2b60321fea92cd3c56b4a7489f160e - languageName: node - linkType: hard - -"glob@npm:^7.1.3, glob@npm:~7.2.0": - version: 7.2.3 - resolution: "glob@npm:7.2.3" - dependencies: - fs.realpath: "npm:^1.0.0" - inflight: "npm:^1.0.4" - inherits: "npm:2" - minimatch: "npm:^3.1.1" - once: "npm:^1.3.0" - path-is-absolute: "npm:^1.0.0" - checksum: 10c0/65676153e2b0c9095100fe7f25a778bf45608eeb32c6048cf307f579649bcc30353277b3b898a3792602c65764e5baa4f643714dfbdfd64ea271d210c7a425fe - languageName: node - linkType: hard - -"glob@npm:^9.3.2": - version: 9.3.5 - resolution: "glob@npm:9.3.5" - dependencies: - fs.realpath: "npm:^1.0.0" - minimatch: "npm:^8.0.2" - minipass: "npm:^4.2.4" - path-scurry: "npm:^1.6.1" - checksum: 10c0/2f6c2b9ee019ee21dc258ae97a88719614591e4c979cb4580b1b9df6f0f778a3cb38b4bdaf18dfa584637ea10f89a3c5f2533a5e449cf8741514ad18b0951f2e + checksum: 10c0/100705eddbde6323e7b35e1d1ac28bcb58322095bd8e63a7d0bef1a2cdafe0d0f7922a981b2b48369a4f8c1b077be5c171804534c3509dfe950dde15fbe6d828 languageName: node linkType: hard @@ -10384,7 +10324,17 @@ __metadata: languageName: node linkType: hard -"import-fresh@npm:^3.2.1, import-fresh@npm:^3.3.0": +"import-fresh@npm:^3.2.1": + version: 3.3.1 + resolution: "import-fresh@npm:3.3.1" + dependencies: + parent-module: "npm:^1.0.0" + resolve-from: "npm:^4.0.0" + checksum: 10c0/bf8cc494872fef783249709385ae883b447e3eb09db0ebd15dcead7d9afe7224dad7bd7591c6b73b0b19b3c0f9640eb8ee884f01cfaf2887ab995b0b36a0cbec + languageName: node + linkType: hard + +"import-fresh@npm:^3.3.0": version: 3.3.0 resolution: "import-fresh@npm:3.3.0" dependencies: @@ -10408,17 +10358,7 @@ __metadata: languageName: node linkType: hard -"inflight@npm:^1.0.4": - version: 1.0.6 - resolution: "inflight@npm:1.0.6" - dependencies: - once: "npm:^1.3.0" - wrappy: "npm:1" - checksum: 10c0/7faca22584600a9dc5b9fca2cd5feb7135ac8c935449837b315676b4c90aa4f391ec4f42240178244b5a34e8bede1948627fda392ca3191522fc46b34e985ab2 - languageName: node - linkType: hard - -"inherits@npm:2, inherits@npm:^2.0.1, inherits@npm:^2.0.3, inherits@npm:^2.0.4, inherits@npm:~2.0.3, inherits@npm:~2.0.4": +"inherits@npm:^2.0.1, inherits@npm:^2.0.3, inherits@npm:^2.0.4, inherits@npm:~2.0.3, inherits@npm:~2.0.4": version: 2.0.4 resolution: "inherits@npm:2.0.4" checksum: 10c0/4e531f648b29039fb7426fb94075e6545faa1eb9fe83c29f0b6d9e7263aceb4289d2d4557db0d428188eeb449cc7c5e77b0a0b2c4e248ff2a65933a0dee49ef2 @@ -10948,14 +10888,14 @@ __metadata: languageName: node linkType: hard -"js-yaml@npm:^4.1.0": - version: 4.1.0 - resolution: "js-yaml@npm:4.1.0" +"js-yaml@npm:^4.1.1": + version: 4.1.1 + resolution: "js-yaml@npm:4.1.1" dependencies: argparse: "npm:^2.0.1" bin: js-yaml: bin/js-yaml.js - checksum: 10c0/184a24b4eaacfce40ad9074c64fd42ac83cf74d8c8cd137718d456ced75051229e5061b8633c3366b8aada17945a7a356b337828c19da92b51ae62126575018f + checksum: 10c0/561c7d7088c40a9bb53cc75becbfb1df6ae49b34b5e6e5a81744b14ae8667ec564ad2527709d1a6e7d5e5fa6d483aa0f373a50ad98d42fde368ec4a190d4fae7 languageName: node linkType: hard @@ -11606,13 +11546,6 @@ __metadata: languageName: node linkType: hard -"minipass@npm:^4.2.4": - version: 4.2.8 - resolution: "minipass@npm:4.2.8" - checksum: 10c0/4ea76b030d97079f4429d6e8a8affd90baf1b6a1898977c8ccce4701c5a2ba2792e033abc6709373f25c2c4d4d95440d9d5e9464b46b7b76ca44d2ce26d939ce - languageName: node - linkType: hard - "minipass@npm:^5.0.0 || ^6.0.2 || ^7.0.0, minipass@npm:^7.0.2, minipass@npm:^7.0.3, minipass@npm:^7.0.4, minipass@npm:^7.1.2": version: 7.1.2 resolution: "minipass@npm:7.1.2" @@ -11990,7 +11923,7 @@ __metadata: languageName: node linkType: hard -"once@npm:^1.3.0, once@npm:^1.4.0": +"once@npm:^1.4.0": version: 1.4.0 resolution: "once@npm:1.4.0" dependencies: @@ -12292,13 +12225,6 @@ __metadata: languageName: node linkType: hard -"path-is-absolute@npm:^1.0.0": - version: 1.0.1 - resolution: "path-is-absolute@npm:1.0.1" - checksum: 10c0/127da03c82172a2a50099cddbf02510c1791fc2cc5f7713ddb613a56838db1e8168b121a920079d052e0936c23005562059756d653b7c544c53185efe53be078 - languageName: node - linkType: hard - "path-key@npm:^3.1.0": version: 3.1.1 resolution: "path-key@npm:3.1.1" @@ -12320,7 +12246,7 @@ __metadata: languageName: node linkType: hard -"path-scurry@npm:^1.11.1, path-scurry@npm:^1.6.1": +"path-scurry@npm:^1.11.1": version: 1.11.1 resolution: "path-scurry@npm:1.11.1" dependencies: @@ -13005,12 +12931,12 @@ __metadata: languageName: node linkType: hard -"qs@npm:^6.12.3": - version: 6.14.0 - resolution: "qs@npm:6.14.0" +"qs@npm:^6.14.1": + version: 6.15.0 + resolution: "qs@npm:6.15.0" dependencies: side-channel: "npm:^1.1.0" - checksum: 10c0/8ea5d91bf34f440598ee389d4a7d95820e3b837d3fd9f433871f7924801becaa0cd3b3b4628d49a7784d06a8aea9bc4554d2b6d8d584e2d221dc06238a42909c + checksum: 10c0/ff341078a78a991d8a48b4524d52949211447b4b1ad907f489cac0770cbc346a28e47304455c0320e5fb000f8762d64b03331e3b71865f663bf351bcba8cdb4b languageName: node linkType: hard From bf8bf80417483d22dc0a9bce19e9affe332e3fcd Mon Sep 17 00:00:00 2001 From: Timo K Date: Fri, 13 Mar 2026 08:01:08 +0100 Subject: [PATCH 372/748] Revert "update qs, js-yaml, glob for security patches" This reverts commit 7da9bca08c5c50ae41478296837ab688658510ef. --- package.json | 5 +- yarn.lock | 164 +++++++++++++++++++++++++++++++++++++-------------- 2 files changed, 120 insertions(+), 49 deletions(-) diff --git a/package.json b/package.json index cc8a36eb1..04a48dc2b 100644 --- a/package.json +++ b/package.json @@ -140,10 +140,7 @@ "@livekit/components-core/rxjs": "^7.8.1", "@livekit/track-processors/@mediapipe/tasks-vision": "^0.10.18", "minimatch": "^10.2.3", - "tar": "^7.5.11", - "glob": "^10.5.0", - "qs": "^6.14.1", - "js-yaml": "^4.1.1" + "tar": "^7.5.11" }, "packageManager": "yarn@4.7.0" } diff --git a/yarn.lock b/yarn.lock index 12e1b8578..a3f6b921b 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2901,13 +2901,20 @@ __metadata: languageName: node linkType: hard -"@eslint-community/regexpp@npm:^4.12.2, @eslint-community/regexpp@npm:^4.6.1": +"@eslint-community/regexpp@npm:^4.12.2": version: 4.12.2 resolution: "@eslint-community/regexpp@npm:4.12.2" checksum: 10c0/fddcbc66851b308478d04e302a4d771d6917a0b3740dc351513c0da9ca2eab8a1adf99f5e0aa7ab8b13fa0df005c81adeee7e63a92f3effd7d367a163b721c2d languageName: node linkType: hard +"@eslint-community/regexpp@npm:^4.6.1": + version: 4.11.1 + resolution: "@eslint-community/regexpp@npm:4.11.1" + checksum: 10c0/fbcc1cb65ef5ed5b92faa8dc542e035269065e7ebcc0b39c81a4fe98ad35cfff20b3c8df048641de15a7757e07d69f85e2579c1a5055f993413ba18c055654f8 + languageName: node + linkType: hard + "@eslint/eslintrc@npm:^2.1.4": version: 2.1.4 resolution: "@eslint/eslintrc@npm:2.1.4" @@ -6211,9 +6218,9 @@ __metadata: linkType: hard "@ungap/structured-clone@npm:^1.2.0": - version: 1.3.0 - resolution: "@ungap/structured-clone@npm:1.3.0" - checksum: 10c0/0fc3097c2540ada1fc340ee56d58d96b5b536a2a0dab6e3ec17d4bfc8c4c86db345f61a375a8185f9da96f01c69678f836a2b57eeaa9e4b8eeafd26428e57b0a + version: 1.2.0 + resolution: "@ungap/structured-clone@npm:1.2.0" + checksum: 10c0/8209c937cb39119f44eb63cf90c0b73e7c754209a6411c707be08e50e29ee81356dca1a848a405c8bdeebfe2f5e4f831ad310ae1689eeef65e7445c090c6657d languageName: node linkType: hard @@ -6430,7 +6437,7 @@ __metadata: languageName: node linkType: hard -"acorn@npm:^8.16.0, acorn@npm:^8.9.0": +"acorn@npm:^8.16.0": version: 8.16.0 resolution: "acorn@npm:8.16.0" bin: @@ -6439,6 +6446,15 @@ __metadata: languageName: node linkType: hard +"acorn@npm:^8.9.0": + version: 8.12.1 + resolution: "acorn@npm:8.12.1" + bin: + acorn: bin/acorn + checksum: 10c0/51fb26cd678f914e13287e886da2d7021f8c2bc0ccc95e03d3e0447ee278dd3b40b9c57dc222acd5881adcf26f3edc40901a4953403232129e3876793cd17386 + languageName: node + linkType: hard + "agent-base@npm:6": version: 6.0.2 resolution: "agent-base@npm:6.0.2" @@ -6465,14 +6481,14 @@ __metadata: linkType: hard "ajv@npm:^6.12.4": - version: 6.14.0 - resolution: "ajv@npm:6.14.0" + version: 6.12.6 + resolution: "ajv@npm:6.12.6" dependencies: fast-deep-equal: "npm:^3.1.1" fast-json-stable-stringify: "npm:^2.0.0" json-schema-traverse: "npm:^0.4.1" uri-js: "npm:^4.2.2" - checksum: 10c0/a2bc39b0555dc9802c899f86990eb8eed6e366cddbf65be43d5aa7e4f3c4e1a199d5460fd7ca4fb3d864000dbbc049253b72faa83b3b30e641ca52cb29a68c22 + checksum: 10c0/41e23642cbe545889245b9d2a45854ebba51cda6c778ebced9649420d9205f2efb39cb43dbc41e358409223b1ea43303ae4839db682c848b891e4811da1a5a71 languageName: node linkType: hard @@ -7733,7 +7749,18 @@ __metadata: languageName: node linkType: hard -"cross-spawn@npm:^7.0.2, cross-spawn@npm:^7.0.6": +"cross-spawn@npm:^7.0.2": + version: 7.0.3 + resolution: "cross-spawn@npm:7.0.3" + dependencies: + path-key: "npm:^3.1.0" + shebang-command: "npm:^2.0.0" + which: "npm:^2.0.1" + checksum: 10c0/5738c312387081c98d69c98e105b6327b069197f864a60593245d64c8089c8a0a744e16349281210d56835bb9274130d825a78b2ad6853ca13cfbeffc0c31750 + languageName: node + linkType: hard + +"cross-spawn@npm:^7.0.6": version: 7.0.6 resolution: "cross-spawn@npm:7.0.6" dependencies: @@ -9281,16 +9308,7 @@ __metadata: languageName: node linkType: hard -"esquery@npm:^1.4.2, esquery@npm:^1.7.0": - version: 1.7.0 - resolution: "esquery@npm:1.7.0" - dependencies: - estraverse: "npm:^5.1.0" - checksum: 10c0/77d5173db450b66f3bc685d11af4c90cffeedb340f34a39af96d43509a335ce39c894fd79233df32d38f5e4e219fa0f7076f6ec90bae8320170ba082c0db4793 - languageName: node - linkType: hard - -"esquery@npm:^1.6.0": +"esquery@npm:^1.4.2, esquery@npm:^1.6.0": version: 1.6.0 resolution: "esquery@npm:1.6.0" dependencies: @@ -9299,6 +9317,15 @@ __metadata: languageName: node linkType: hard +"esquery@npm:^1.7.0": + version: 1.7.0 + resolution: "esquery@npm:1.7.0" + dependencies: + estraverse: "npm:^5.1.0" + checksum: 10c0/77d5173db450b66f3bc685d11af4c90cffeedb340f34a39af96d43509a335ce39c894fd79233df32d38f5e4e219fa0f7076f6ec90bae8320170ba082c0db4793 + languageName: node + linkType: hard + "esrecurse@npm:^4.3.0": version: 4.3.0 resolution: "esrecurse@npm:4.3.0" @@ -9673,6 +9700,13 @@ __metadata: languageName: node linkType: hard +"fs.realpath@npm:^1.0.0": + version: 1.0.0 + resolution: "fs.realpath@npm:1.0.0" + checksum: 10c0/444cf1291d997165dfd4c0d58b69f0e4782bfd9149fd72faa4fe299e68e0e93d6db941660b37dd29153bf7186672ececa3b50b7e7249477b03fdf850f287c948 + languageName: node + linkType: hard + "fsevents@npm:2.3.2": version: 2.3.2 resolution: "fsevents@npm:2.3.2" @@ -9865,9 +9899,9 @@ __metadata: languageName: node linkType: hard -"glob@npm:^10.5.0": - version: 10.5.0 - resolution: "glob@npm:10.5.0" +"glob@npm:^10.2.2, glob@npm:^10.3.10, glob@npm:^10.3.7": + version: 10.4.5 + resolution: "glob@npm:10.4.5" dependencies: foreground-child: "npm:^3.1.0" jackspeak: "npm:^3.1.2" @@ -9877,7 +9911,33 @@ __metadata: path-scurry: "npm:^1.11.1" bin: glob: dist/esm/bin.mjs - checksum: 10c0/100705eddbde6323e7b35e1d1ac28bcb58322095bd8e63a7d0bef1a2cdafe0d0f7922a981b2b48369a4f8c1b077be5c171804534c3509dfe950dde15fbe6d828 + checksum: 10c0/19a9759ea77b8e3ca0a43c2f07ecddc2ad46216b786bb8f993c445aee80d345925a21e5280c7b7c6c59e860a0154b84e4b2b60321fea92cd3c56b4a7489f160e + languageName: node + linkType: hard + +"glob@npm:^7.1.3, glob@npm:~7.2.0": + version: 7.2.3 + resolution: "glob@npm:7.2.3" + dependencies: + fs.realpath: "npm:^1.0.0" + inflight: "npm:^1.0.4" + inherits: "npm:2" + minimatch: "npm:^3.1.1" + once: "npm:^1.3.0" + path-is-absolute: "npm:^1.0.0" + checksum: 10c0/65676153e2b0c9095100fe7f25a778bf45608eeb32c6048cf307f579649bcc30353277b3b898a3792602c65764e5baa4f643714dfbdfd64ea271d210c7a425fe + languageName: node + linkType: hard + +"glob@npm:^9.3.2": + version: 9.3.5 + resolution: "glob@npm:9.3.5" + dependencies: + fs.realpath: "npm:^1.0.0" + minimatch: "npm:^8.0.2" + minipass: "npm:^4.2.4" + path-scurry: "npm:^1.6.1" + checksum: 10c0/2f6c2b9ee019ee21dc258ae97a88719614591e4c979cb4580b1b9df6f0f778a3cb38b4bdaf18dfa584637ea10f89a3c5f2533a5e449cf8741514ad18b0951f2e languageName: node linkType: hard @@ -10324,17 +10384,7 @@ __metadata: languageName: node linkType: hard -"import-fresh@npm:^3.2.1": - version: 3.3.1 - resolution: "import-fresh@npm:3.3.1" - dependencies: - parent-module: "npm:^1.0.0" - resolve-from: "npm:^4.0.0" - checksum: 10c0/bf8cc494872fef783249709385ae883b447e3eb09db0ebd15dcead7d9afe7224dad7bd7591c6b73b0b19b3c0f9640eb8ee884f01cfaf2887ab995b0b36a0cbec - languageName: node - linkType: hard - -"import-fresh@npm:^3.3.0": +"import-fresh@npm:^3.2.1, import-fresh@npm:^3.3.0": version: 3.3.0 resolution: "import-fresh@npm:3.3.0" dependencies: @@ -10358,7 +10408,17 @@ __metadata: languageName: node linkType: hard -"inherits@npm:^2.0.1, inherits@npm:^2.0.3, inherits@npm:^2.0.4, inherits@npm:~2.0.3, inherits@npm:~2.0.4": +"inflight@npm:^1.0.4": + version: 1.0.6 + resolution: "inflight@npm:1.0.6" + dependencies: + once: "npm:^1.3.0" + wrappy: "npm:1" + checksum: 10c0/7faca22584600a9dc5b9fca2cd5feb7135ac8c935449837b315676b4c90aa4f391ec4f42240178244b5a34e8bede1948627fda392ca3191522fc46b34e985ab2 + languageName: node + linkType: hard + +"inherits@npm:2, inherits@npm:^2.0.1, inherits@npm:^2.0.3, inherits@npm:^2.0.4, inherits@npm:~2.0.3, inherits@npm:~2.0.4": version: 2.0.4 resolution: "inherits@npm:2.0.4" checksum: 10c0/4e531f648b29039fb7426fb94075e6545faa1eb9fe83c29f0b6d9e7263aceb4289d2d4557db0d428188eeb449cc7c5e77b0a0b2c4e248ff2a65933a0dee49ef2 @@ -10888,14 +10948,14 @@ __metadata: languageName: node linkType: hard -"js-yaml@npm:^4.1.1": - version: 4.1.1 - resolution: "js-yaml@npm:4.1.1" +"js-yaml@npm:^4.1.0": + version: 4.1.0 + resolution: "js-yaml@npm:4.1.0" dependencies: argparse: "npm:^2.0.1" bin: js-yaml: bin/js-yaml.js - checksum: 10c0/561c7d7088c40a9bb53cc75becbfb1df6ae49b34b5e6e5a81744b14ae8667ec564ad2527709d1a6e7d5e5fa6d483aa0f373a50ad98d42fde368ec4a190d4fae7 + checksum: 10c0/184a24b4eaacfce40ad9074c64fd42ac83cf74d8c8cd137718d456ced75051229e5061b8633c3366b8aada17945a7a356b337828c19da92b51ae62126575018f languageName: node linkType: hard @@ -11546,6 +11606,13 @@ __metadata: languageName: node linkType: hard +"minipass@npm:^4.2.4": + version: 4.2.8 + resolution: "minipass@npm:4.2.8" + checksum: 10c0/4ea76b030d97079f4429d6e8a8affd90baf1b6a1898977c8ccce4701c5a2ba2792e033abc6709373f25c2c4d4d95440d9d5e9464b46b7b76ca44d2ce26d939ce + languageName: node + linkType: hard + "minipass@npm:^5.0.0 || ^6.0.2 || ^7.0.0, minipass@npm:^7.0.2, minipass@npm:^7.0.3, minipass@npm:^7.0.4, minipass@npm:^7.1.2": version: 7.1.2 resolution: "minipass@npm:7.1.2" @@ -11923,7 +11990,7 @@ __metadata: languageName: node linkType: hard -"once@npm:^1.4.0": +"once@npm:^1.3.0, once@npm:^1.4.0": version: 1.4.0 resolution: "once@npm:1.4.0" dependencies: @@ -12225,6 +12292,13 @@ __metadata: languageName: node linkType: hard +"path-is-absolute@npm:^1.0.0": + version: 1.0.1 + resolution: "path-is-absolute@npm:1.0.1" + checksum: 10c0/127da03c82172a2a50099cddbf02510c1791fc2cc5f7713ddb613a56838db1e8168b121a920079d052e0936c23005562059756d653b7c544c53185efe53be078 + languageName: node + linkType: hard + "path-key@npm:^3.1.0": version: 3.1.1 resolution: "path-key@npm:3.1.1" @@ -12246,7 +12320,7 @@ __metadata: languageName: node linkType: hard -"path-scurry@npm:^1.11.1": +"path-scurry@npm:^1.11.1, path-scurry@npm:^1.6.1": version: 1.11.1 resolution: "path-scurry@npm:1.11.1" dependencies: @@ -12931,12 +13005,12 @@ __metadata: languageName: node linkType: hard -"qs@npm:^6.14.1": - version: 6.15.0 - resolution: "qs@npm:6.15.0" +"qs@npm:^6.12.3": + version: 6.14.0 + resolution: "qs@npm:6.14.0" dependencies: side-channel: "npm:^1.1.0" - checksum: 10c0/ff341078a78a991d8a48b4524d52949211447b4b1ad907f489cac0770cbc346a28e47304455c0320e5fb000f8762d64b03331e3b71865f663bf351bcba8cdb4b + checksum: 10c0/8ea5d91bf34f440598ee389d4a7d95820e3b837d3fd9f433871f7924801becaa0cd3b3b4628d49a7784d06a8aea9bc4554d2b6d8d584e2d221dc06238a42909c languageName: node linkType: hard From 78240c2ec802ef3f7d2ee9f07ab41f9e8c517bf2 Mon Sep 17 00:00:00 2001 From: Timo K Date: Fri, 13 Mar 2026 07:59:49 +0100 Subject: [PATCH 373/748] update qs, js-yaml, glob for security patches --- package.json | 5 +- yarn.lock | 164 ++++++++++++++------------------------------------- 2 files changed, 49 insertions(+), 120 deletions(-) diff --git a/package.json b/package.json index 04a48dc2b..cc8a36eb1 100644 --- a/package.json +++ b/package.json @@ -140,7 +140,10 @@ "@livekit/components-core/rxjs": "^7.8.1", "@livekit/track-processors/@mediapipe/tasks-vision": "^0.10.18", "minimatch": "^10.2.3", - "tar": "^7.5.11" + "tar": "^7.5.11", + "glob": "^10.5.0", + "qs": "^6.14.1", + "js-yaml": "^4.1.1" }, "packageManager": "yarn@4.7.0" } diff --git a/yarn.lock b/yarn.lock index a3f6b921b..12e1b8578 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2901,20 +2901,13 @@ __metadata: languageName: node linkType: hard -"@eslint-community/regexpp@npm:^4.12.2": +"@eslint-community/regexpp@npm:^4.12.2, @eslint-community/regexpp@npm:^4.6.1": version: 4.12.2 resolution: "@eslint-community/regexpp@npm:4.12.2" checksum: 10c0/fddcbc66851b308478d04e302a4d771d6917a0b3740dc351513c0da9ca2eab8a1adf99f5e0aa7ab8b13fa0df005c81adeee7e63a92f3effd7d367a163b721c2d languageName: node linkType: hard -"@eslint-community/regexpp@npm:^4.6.1": - version: 4.11.1 - resolution: "@eslint-community/regexpp@npm:4.11.1" - checksum: 10c0/fbcc1cb65ef5ed5b92faa8dc542e035269065e7ebcc0b39c81a4fe98ad35cfff20b3c8df048641de15a7757e07d69f85e2579c1a5055f993413ba18c055654f8 - languageName: node - linkType: hard - "@eslint/eslintrc@npm:^2.1.4": version: 2.1.4 resolution: "@eslint/eslintrc@npm:2.1.4" @@ -6218,9 +6211,9 @@ __metadata: linkType: hard "@ungap/structured-clone@npm:^1.2.0": - version: 1.2.0 - resolution: "@ungap/structured-clone@npm:1.2.0" - checksum: 10c0/8209c937cb39119f44eb63cf90c0b73e7c754209a6411c707be08e50e29ee81356dca1a848a405c8bdeebfe2f5e4f831ad310ae1689eeef65e7445c090c6657d + version: 1.3.0 + resolution: "@ungap/structured-clone@npm:1.3.0" + checksum: 10c0/0fc3097c2540ada1fc340ee56d58d96b5b536a2a0dab6e3ec17d4bfc8c4c86db345f61a375a8185f9da96f01c69678f836a2b57eeaa9e4b8eeafd26428e57b0a languageName: node linkType: hard @@ -6437,7 +6430,7 @@ __metadata: languageName: node linkType: hard -"acorn@npm:^8.16.0": +"acorn@npm:^8.16.0, acorn@npm:^8.9.0": version: 8.16.0 resolution: "acorn@npm:8.16.0" bin: @@ -6446,15 +6439,6 @@ __metadata: languageName: node linkType: hard -"acorn@npm:^8.9.0": - version: 8.12.1 - resolution: "acorn@npm:8.12.1" - bin: - acorn: bin/acorn - checksum: 10c0/51fb26cd678f914e13287e886da2d7021f8c2bc0ccc95e03d3e0447ee278dd3b40b9c57dc222acd5881adcf26f3edc40901a4953403232129e3876793cd17386 - languageName: node - linkType: hard - "agent-base@npm:6": version: 6.0.2 resolution: "agent-base@npm:6.0.2" @@ -6481,14 +6465,14 @@ __metadata: linkType: hard "ajv@npm:^6.12.4": - version: 6.12.6 - resolution: "ajv@npm:6.12.6" + version: 6.14.0 + resolution: "ajv@npm:6.14.0" dependencies: fast-deep-equal: "npm:^3.1.1" fast-json-stable-stringify: "npm:^2.0.0" json-schema-traverse: "npm:^0.4.1" uri-js: "npm:^4.2.2" - checksum: 10c0/41e23642cbe545889245b9d2a45854ebba51cda6c778ebced9649420d9205f2efb39cb43dbc41e358409223b1ea43303ae4839db682c848b891e4811da1a5a71 + checksum: 10c0/a2bc39b0555dc9802c899f86990eb8eed6e366cddbf65be43d5aa7e4f3c4e1a199d5460fd7ca4fb3d864000dbbc049253b72faa83b3b30e641ca52cb29a68c22 languageName: node linkType: hard @@ -7749,18 +7733,7 @@ __metadata: languageName: node linkType: hard -"cross-spawn@npm:^7.0.2": - version: 7.0.3 - resolution: "cross-spawn@npm:7.0.3" - dependencies: - path-key: "npm:^3.1.0" - shebang-command: "npm:^2.0.0" - which: "npm:^2.0.1" - checksum: 10c0/5738c312387081c98d69c98e105b6327b069197f864a60593245d64c8089c8a0a744e16349281210d56835bb9274130d825a78b2ad6853ca13cfbeffc0c31750 - languageName: node - linkType: hard - -"cross-spawn@npm:^7.0.6": +"cross-spawn@npm:^7.0.2, cross-spawn@npm:^7.0.6": version: 7.0.6 resolution: "cross-spawn@npm:7.0.6" dependencies: @@ -9308,16 +9281,7 @@ __metadata: languageName: node linkType: hard -"esquery@npm:^1.4.2, esquery@npm:^1.6.0": - version: 1.6.0 - resolution: "esquery@npm:1.6.0" - dependencies: - estraverse: "npm:^5.1.0" - checksum: 10c0/cb9065ec605f9da7a76ca6dadb0619dfb611e37a81e318732977d90fab50a256b95fee2d925fba7c2f3f0523aa16f91587246693bc09bc34d5a59575fe6e93d2 - languageName: node - linkType: hard - -"esquery@npm:^1.7.0": +"esquery@npm:^1.4.2, esquery@npm:^1.7.0": version: 1.7.0 resolution: "esquery@npm:1.7.0" dependencies: @@ -9326,6 +9290,15 @@ __metadata: languageName: node linkType: hard +"esquery@npm:^1.6.0": + version: 1.6.0 + resolution: "esquery@npm:1.6.0" + dependencies: + estraverse: "npm:^5.1.0" + checksum: 10c0/cb9065ec605f9da7a76ca6dadb0619dfb611e37a81e318732977d90fab50a256b95fee2d925fba7c2f3f0523aa16f91587246693bc09bc34d5a59575fe6e93d2 + languageName: node + linkType: hard + "esrecurse@npm:^4.3.0": version: 4.3.0 resolution: "esrecurse@npm:4.3.0" @@ -9700,13 +9673,6 @@ __metadata: languageName: node linkType: hard -"fs.realpath@npm:^1.0.0": - version: 1.0.0 - resolution: "fs.realpath@npm:1.0.0" - checksum: 10c0/444cf1291d997165dfd4c0d58b69f0e4782bfd9149fd72faa4fe299e68e0e93d6db941660b37dd29153bf7186672ececa3b50b7e7249477b03fdf850f287c948 - languageName: node - linkType: hard - "fsevents@npm:2.3.2": version: 2.3.2 resolution: "fsevents@npm:2.3.2" @@ -9899,9 +9865,9 @@ __metadata: languageName: node linkType: hard -"glob@npm:^10.2.2, glob@npm:^10.3.10, glob@npm:^10.3.7": - version: 10.4.5 - resolution: "glob@npm:10.4.5" +"glob@npm:^10.5.0": + version: 10.5.0 + resolution: "glob@npm:10.5.0" dependencies: foreground-child: "npm:^3.1.0" jackspeak: "npm:^3.1.2" @@ -9911,33 +9877,7 @@ __metadata: path-scurry: "npm:^1.11.1" bin: glob: dist/esm/bin.mjs - checksum: 10c0/19a9759ea77b8e3ca0a43c2f07ecddc2ad46216b786bb8f993c445aee80d345925a21e5280c7b7c6c59e860a0154b84e4b2b60321fea92cd3c56b4a7489f160e - languageName: node - linkType: hard - -"glob@npm:^7.1.3, glob@npm:~7.2.0": - version: 7.2.3 - resolution: "glob@npm:7.2.3" - dependencies: - fs.realpath: "npm:^1.0.0" - inflight: "npm:^1.0.4" - inherits: "npm:2" - minimatch: "npm:^3.1.1" - once: "npm:^1.3.0" - path-is-absolute: "npm:^1.0.0" - checksum: 10c0/65676153e2b0c9095100fe7f25a778bf45608eeb32c6048cf307f579649bcc30353277b3b898a3792602c65764e5baa4f643714dfbdfd64ea271d210c7a425fe - languageName: node - linkType: hard - -"glob@npm:^9.3.2": - version: 9.3.5 - resolution: "glob@npm:9.3.5" - dependencies: - fs.realpath: "npm:^1.0.0" - minimatch: "npm:^8.0.2" - minipass: "npm:^4.2.4" - path-scurry: "npm:^1.6.1" - checksum: 10c0/2f6c2b9ee019ee21dc258ae97a88719614591e4c979cb4580b1b9df6f0f778a3cb38b4bdaf18dfa584637ea10f89a3c5f2533a5e449cf8741514ad18b0951f2e + checksum: 10c0/100705eddbde6323e7b35e1d1ac28bcb58322095bd8e63a7d0bef1a2cdafe0d0f7922a981b2b48369a4f8c1b077be5c171804534c3509dfe950dde15fbe6d828 languageName: node linkType: hard @@ -10384,7 +10324,17 @@ __metadata: languageName: node linkType: hard -"import-fresh@npm:^3.2.1, import-fresh@npm:^3.3.0": +"import-fresh@npm:^3.2.1": + version: 3.3.1 + resolution: "import-fresh@npm:3.3.1" + dependencies: + parent-module: "npm:^1.0.0" + resolve-from: "npm:^4.0.0" + checksum: 10c0/bf8cc494872fef783249709385ae883b447e3eb09db0ebd15dcead7d9afe7224dad7bd7591c6b73b0b19b3c0f9640eb8ee884f01cfaf2887ab995b0b36a0cbec + languageName: node + linkType: hard + +"import-fresh@npm:^3.3.0": version: 3.3.0 resolution: "import-fresh@npm:3.3.0" dependencies: @@ -10408,17 +10358,7 @@ __metadata: languageName: node linkType: hard -"inflight@npm:^1.0.4": - version: 1.0.6 - resolution: "inflight@npm:1.0.6" - dependencies: - once: "npm:^1.3.0" - wrappy: "npm:1" - checksum: 10c0/7faca22584600a9dc5b9fca2cd5feb7135ac8c935449837b315676b4c90aa4f391ec4f42240178244b5a34e8bede1948627fda392ca3191522fc46b34e985ab2 - languageName: node - linkType: hard - -"inherits@npm:2, inherits@npm:^2.0.1, inherits@npm:^2.0.3, inherits@npm:^2.0.4, inherits@npm:~2.0.3, inherits@npm:~2.0.4": +"inherits@npm:^2.0.1, inherits@npm:^2.0.3, inherits@npm:^2.0.4, inherits@npm:~2.0.3, inherits@npm:~2.0.4": version: 2.0.4 resolution: "inherits@npm:2.0.4" checksum: 10c0/4e531f648b29039fb7426fb94075e6545faa1eb9fe83c29f0b6d9e7263aceb4289d2d4557db0d428188eeb449cc7c5e77b0a0b2c4e248ff2a65933a0dee49ef2 @@ -10948,14 +10888,14 @@ __metadata: languageName: node linkType: hard -"js-yaml@npm:^4.1.0": - version: 4.1.0 - resolution: "js-yaml@npm:4.1.0" +"js-yaml@npm:^4.1.1": + version: 4.1.1 + resolution: "js-yaml@npm:4.1.1" dependencies: argparse: "npm:^2.0.1" bin: js-yaml: bin/js-yaml.js - checksum: 10c0/184a24b4eaacfce40ad9074c64fd42ac83cf74d8c8cd137718d456ced75051229e5061b8633c3366b8aada17945a7a356b337828c19da92b51ae62126575018f + checksum: 10c0/561c7d7088c40a9bb53cc75becbfb1df6ae49b34b5e6e5a81744b14ae8667ec564ad2527709d1a6e7d5e5fa6d483aa0f373a50ad98d42fde368ec4a190d4fae7 languageName: node linkType: hard @@ -11606,13 +11546,6 @@ __metadata: languageName: node linkType: hard -"minipass@npm:^4.2.4": - version: 4.2.8 - resolution: "minipass@npm:4.2.8" - checksum: 10c0/4ea76b030d97079f4429d6e8a8affd90baf1b6a1898977c8ccce4701c5a2ba2792e033abc6709373f25c2c4d4d95440d9d5e9464b46b7b76ca44d2ce26d939ce - languageName: node - linkType: hard - "minipass@npm:^5.0.0 || ^6.0.2 || ^7.0.0, minipass@npm:^7.0.2, minipass@npm:^7.0.3, minipass@npm:^7.0.4, minipass@npm:^7.1.2": version: 7.1.2 resolution: "minipass@npm:7.1.2" @@ -11990,7 +11923,7 @@ __metadata: languageName: node linkType: hard -"once@npm:^1.3.0, once@npm:^1.4.0": +"once@npm:^1.4.0": version: 1.4.0 resolution: "once@npm:1.4.0" dependencies: @@ -12292,13 +12225,6 @@ __metadata: languageName: node linkType: hard -"path-is-absolute@npm:^1.0.0": - version: 1.0.1 - resolution: "path-is-absolute@npm:1.0.1" - checksum: 10c0/127da03c82172a2a50099cddbf02510c1791fc2cc5f7713ddb613a56838db1e8168b121a920079d052e0936c23005562059756d653b7c544c53185efe53be078 - languageName: node - linkType: hard - "path-key@npm:^3.1.0": version: 3.1.1 resolution: "path-key@npm:3.1.1" @@ -12320,7 +12246,7 @@ __metadata: languageName: node linkType: hard -"path-scurry@npm:^1.11.1, path-scurry@npm:^1.6.1": +"path-scurry@npm:^1.11.1": version: 1.11.1 resolution: "path-scurry@npm:1.11.1" dependencies: @@ -13005,12 +12931,12 @@ __metadata: languageName: node linkType: hard -"qs@npm:^6.12.3": - version: 6.14.0 - resolution: "qs@npm:6.14.0" +"qs@npm:^6.14.1": + version: 6.15.0 + resolution: "qs@npm:6.15.0" dependencies: side-channel: "npm:^1.1.0" - checksum: 10c0/8ea5d91bf34f440598ee389d4a7d95820e3b837d3fd9f433871f7924801becaa0cd3b3b4628d49a7784d06a8aea9bc4554d2b6d8d584e2d221dc06238a42909c + checksum: 10c0/ff341078a78a991d8a48b4524d52949211447b4b1ad907f489cac0770cbc346a28e47304455c0320e5fb000f8762d64b03331e3b71865f663bf351bcba8cdb4b languageName: node linkType: hard From af807489f94c21a957480b8b18d492438c9e388f Mon Sep 17 00:00:00 2001 From: JephDiel Date: Fri, 13 Mar 2026 11:31:55 -0500 Subject: [PATCH 374/748] Import order lint fixes Co-authored-by: Timo <16718859+toger5@users.noreply.github.com> --- src/Avatar.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Avatar.tsx b/src/Avatar.tsx index d7768d6f5..d0cb243cb 100644 --- a/src/Avatar.tsx +++ b/src/Avatar.tsx @@ -14,10 +14,10 @@ import { } from "react"; import { Avatar as CompoundAvatar } from "@vector-im/compound-web"; import { type MatrixClient } from "matrix-js-sdk"; +import { type WidgetApi } from "matrix-widget-api"; import { useClientState } from "./ClientContext"; import { widget } from "./widget"; -import { WidgetApi } from "matrix-widget-api"; export enum Size { XS = "xs", From fa74aaa81e663ccf355c9d5e3d8a09aaf3689788 Mon Sep 17 00:00:00 2001 From: JephDiel Date: Fri, 13 Mar 2026 11:33:07 -0500 Subject: [PATCH 375/748] Import order lint fixes Co-authored-by: Timo <16718859+toger5@users.noreply.github.com> --- src/Avatar.test.tsx | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/Avatar.test.tsx b/src/Avatar.test.tsx index debff26a2..672aff3bb 100644 --- a/src/Avatar.test.tsx +++ b/src/Avatar.test.tsx @@ -14,7 +14,13 @@ import { ClientContextProvider } from "./ClientContext"; import { Avatar } from "./Avatar"; import { mockMatrixRoomMember, mockRtcMembership } from "./utils/test"; import { widget } from "./widget"; -import { WidgetApi } from "matrix-widget-api"; +import { type FC, type PropsWithChildren } from "react"; +import { type WidgetApi } from "matrix-widget-api"; + +import { ClientContextProvider } from "./ClientContext"; +import { Avatar } from "./Avatar"; +import { mockMatrixRoomMember, mockRtcMembership } from "./utils/test"; +import { widget } from "./widget"; const TestComponent: FC< PropsWithChildren<{ From 997cc9bb2717cf7254fbf31bf771f1af780d8f48 Mon Sep 17 00:00:00 2001 From: JephDiel Date: Fri, 13 Mar 2026 11:41:58 -0500 Subject: [PATCH 376/748] Lint fixes v2 --- src/Avatar.test.tsx | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/Avatar.test.tsx b/src/Avatar.test.tsx index 672aff3bb..25d2c42b8 100644 --- a/src/Avatar.test.tsx +++ b/src/Avatar.test.tsx @@ -9,12 +9,6 @@ import { afterEach, expect, test, vi } from "vitest"; import { render, screen } from "@testing-library/react"; import { type MatrixClient } from "matrix-js-sdk"; import { type FC, type PropsWithChildren } from "react"; - -import { ClientContextProvider } from "./ClientContext"; -import { Avatar } from "./Avatar"; -import { mockMatrixRoomMember, mockRtcMembership } from "./utils/test"; -import { widget } from "./widget"; -import { type FC, type PropsWithChildren } from "react"; import { type WidgetApi } from "matrix-widget-api"; import { ClientContextProvider } from "./ClientContext"; From 6d14f1d06ff007ce8a98f8e4e467fbb650da3796 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Sat, 14 Mar 2026 14:48:44 +0000 Subject: [PATCH 377/748] Update GitHub Actions (#3804) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/workflows/build-and-publish-docker.yaml | 2 +- .github/workflows/zizmor.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build-and-publish-docker.yaml b/.github/workflows/build-and-publish-docker.yaml index 6447c094c..3b18b133b 100644 --- a/.github/workflows/build-and-publish-docker.yaml +++ b/.github/workflows/build-and-publish-docker.yaml @@ -44,7 +44,7 @@ jobs: password: ${{ secrets.GITHUB_TOKEN }} - name: Connect to Tailscale - uses: tailscale/github-action@53acf823325fe9ca47f4cdaa951f90b4b0de5bb9 # v4 + uses: tailscale/github-action@306e68a486fd2350f2bfc3b19fcd143891a4a2d8 # v4 if: github.event_name != 'pull_request' with: oauth-client-id: ${{ secrets.TS_OAUTH_CLIENT_ID }} diff --git a/.github/workflows/zizmor.yml b/.github/workflows/zizmor.yml index 612adbd14..d3b6e9698 100644 --- a/.github/workflows/zizmor.yml +++ b/.github/workflows/zizmor.yml @@ -20,4 +20,4 @@ jobs: persist-credentials: false - name: Run zizmor 🌈 - uses: zizmorcore/zizmor-action@0dce2577a4760a2749d8cfb7a84b7d5585ebcb7d # v0.5.0 + uses: zizmorcore/zizmor-action@71321a20a9ded102f6e9ce5718a2fcec2c4f70d8 # v0.5.2 From 32ea8f522c0c753ee41e2a61f0ff9f0f960da92e Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Sun, 15 Mar 2026 01:47:49 +0000 Subject: [PATCH 378/748] Update Compound --- yarn.lock | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/yarn.lock b/yarn.lock index 12e1b8578..cbbbf32f6 100644 --- a/yarn.lock +++ b/yarn.lock @@ -6236,8 +6236,8 @@ __metadata: linkType: hard "@vector-im/compound-design-tokens@npm:^6.0.0": - version: 6.6.0 - resolution: "@vector-im/compound-design-tokens@npm:6.6.0" + version: 6.10.2 + resolution: "@vector-im/compound-design-tokens@npm:6.10.2" peerDependencies: "@types/react": "*" react: ^17 || ^18 || ^19.0.0 @@ -6246,13 +6246,13 @@ __metadata: optional: true react: optional: true - checksum: 10c0/93b152dd1de96371f9b6b1f7dbcc381d7ab598031dbc900f52d610f015766c0d4426ae6e47d417e723bfb62d1a53099155b4d788848b78232916ba132c03c2fe + checksum: 10c0/bcac6d79fcfb8cc1356d65dff576bdad217edd0df189a5dea032b0fd57cef335b73ad6d8e395709245bc1c6a8c672a83144ecea48550ca560544d2399af8f2d3 languageName: node linkType: hard "@vector-im/compound-web@npm:^8.0.0": - version: 8.3.4 - resolution: "@vector-im/compound-web@npm:8.3.4" + version: 8.4.0 + resolution: "@vector-im/compound-web@npm:8.4.0" dependencies: "@floating-ui/react": "npm:^0.27.0" "@radix-ui/react-context-menu": "npm:^2.2.16" @@ -6272,7 +6272,7 @@ __metadata: peerDependenciesMeta: "@types/react": optional: true - checksum: 10c0/44764fa64b5fce2e7181e25b50ee970eda4d921cf650b92bd5e88df0eb60872f3086b8702d18f55c3e39b3751ac19f10bafda8c4306df65c3605bd44b297d95c + checksum: 10c0/31b73555c47b373d4250872bfe863a030b487197bf1198e3cf3a1ec344f2b02f0c72c1513bb598c1cbd7a91d3c6a334d0c8ae37bd7c90d4859c864fc223e059a languageName: node linkType: hard From 9dfade68eed85e8a6df6c4ca1664b897fbdf1de7 Mon Sep 17 00:00:00 2001 From: Robin Date: Mon, 16 Mar 2026 13:12:49 +0100 Subject: [PATCH 379/748] New ringing UI This implements the new ringing UI by showing a placeholder tile for the participant being dialed, rather than an overlay. --- locales/en/app.json | 2 + playwright/widget/voice-call-dm.spec.ts | 21 +- src/grid/OneOnOneLayout.tsx | 8 +- src/room/InCallView.tsx | 76 ++--- src/room/WaitingForJoin.module.css | 61 ---- .../CallNotificationLifecycle.ts | 11 +- src/state/CallViewModel/CallViewModel.test.ts | 174 +++++------ src/state/CallViewModel/CallViewModel.ts | 274 ++++++++++-------- .../CallViewModel/CallViewModelTestUtils.ts | 22 +- .../remoteMembers/MatrixMemberMetadata.ts | 25 -- src/state/OneOnOneLayout.ts | 8 +- src/state/TileStore.ts | 19 +- src/state/TileViewModel.ts | 7 +- src/state/layout-types.ts | 10 +- src/state/media/MediaViewModel.ts | 6 +- src/state/media/MemberMediaViewModel.ts | 13 +- src/state/media/RingingMediaViewModel.ts | 51 ++++ src/state/media/ScreenShareViewModel.ts | 4 +- src/state/media/UserMediaViewModel.ts | 4 +- ...iaItem.ts => WrappedUserMediaViewModel.ts} | 2 - src/tile/GridTile.test.tsx | 89 ++++-- src/tile/GridTile.tsx | 70 ++++- src/tile/MediaView.module.css | 28 +- src/tile/MediaView.test.tsx | 2 - src/tile/MediaView.tsx | 27 +- src/tile/SpotlightTile.test.tsx | 46 ++- src/tile/SpotlightTile.tsx | 121 ++++++-- 27 files changed, 703 insertions(+), 478 deletions(-) delete mode 100644 src/room/WaitingForJoin.module.css create mode 100644 src/state/media/RingingMediaViewModel.ts rename src/state/media/{MediaItem.ts => WrappedUserMediaViewModel.ts} (98%) diff --git a/locales/en/app.json b/locales/en/app.json index 9b1a56750..f5749cf70 100644 --- a/locales/en/app.json +++ b/locales/en/app.json @@ -249,6 +249,8 @@ "version": "{{productName}} version: {{version}}", "video_tile": { "always_show": "Always show", + "call_ended": "Call ended", + "calling": "Calling…", "camera_starting": "Video loading...", "collapse": "Collapse", "expand": "Expand", diff --git a/playwright/widget/voice-call-dm.spec.ts b/playwright/widget/voice-call-dm.spec.ts index 6a8473cfc..cc0b4e537 100644 --- a/playwright/widget/voice-call-dm.spec.ts +++ b/playwright/widget/voice-call-dm.spec.ts @@ -34,9 +34,12 @@ widgetTest( .locator('iframe[title="Element Call"]') .contentFrame(); - // We should show a ringing overlay, let's check for that + // We should show a ringing tile, let's check for that await expect( - brooksFrame.getByText(`Waiting for ${whistler.displayName} to join…`), + brooksFrame + .getByTestId("videoTile") + .filter({ has: brooksFrame.getByText(whistler.displayName) }) + .filter({ has: brooksFrame.getByText("Calling…") }), ).toBeVisible(); await expect(whistler.page.getByText("Incoming voice call")).toBeVisible(); @@ -125,9 +128,12 @@ widgetTest( .locator('iframe[title="Element Call"]') .contentFrame(); - // We should show a ringing overlay, let's check for that + // We should show a ringing tile, let's check for that await expect( - brooksFrame.getByText(`Waiting for ${whistler.displayName} to join…`), + brooksFrame + .getByTestId("videoTile") + .filter({ has: brooksFrame.getByText(whistler.displayName) }) + .filter({ has: brooksFrame.getByText("Calling…") }), ).toBeVisible(); await expect(whistler.page.getByText("Incoming video call")).toBeVisible(); @@ -216,9 +222,12 @@ widgetTest( .locator('iframe[title="Element Call"]') .contentFrame(); - // We should show a ringing overlay, let's check for that + // We should show a ringing tile, let's check for that await expect( - brooksFrame.getByText(`Waiting for ${whistler.displayName} to join…`), + brooksFrame + .getByTestId("videoTile") + .filter({ has: brooksFrame.getByText(whistler.displayName) }) + .filter({ has: brooksFrame.getByText("Calling…") }), ).toBeVisible(); await expect(whistler.page.getByText("Incoming video call")).toBeVisible(); diff --git a/src/grid/OneOnOneLayout.tsx b/src/grid/OneOnOneLayout.tsx index 6c5ae69f6..fd9c0a65d 100644 --- a/src/grid/OneOnOneLayout.tsx +++ b/src/grid/OneOnOneLayout.tsx @@ -51,15 +51,15 @@ export const makeOneOnOneLayout: CallLayout = ({ return (
= ({ const { showControls } = useUrlParams(); const muteAllAudio = useBehavior(muteAllAudio$); - // Call pickup state and display names are needed for waiting overlay/sounds - const callPickupState = useBehavior(vm.callPickupState$); // Preload a waiting and decline sounds const pickupPhaseSoundCache = useInitial(async () => { @@ -239,6 +236,7 @@ export const InCallView: FC = ({ latencyHint: "interactive", muted: muteAllAudio, }); + const latestPickupPhaseAudio = useLatest(pickupPhaseAudio); const audioEnabled = useBehavior(muteStates.audio.enabled$); const videoEnabled = useBehavior(muteStates.video.enabled$); @@ -257,6 +255,7 @@ export const InCallView: FC = ({ () => void toggleRaisedHand(), ); + const ringing = useBehavior(vm.ringing$); const audioParticipants = useBehavior(vm.livekitRoomItems$); const participantCount = useBehavior(vm.participantCount$); const reconnecting = useBehavior(vm.reconnecting$); @@ -271,7 +270,6 @@ export const InCallView: FC = ({ const audioOutputSwitcher = useBehavior(vm.audioOutputSwitcher$); const sharingScreen = useBehavior(vm.sharingScreen$); - const ringOverlay = useBehavior(vm.ringOverlay$); const fatalCallError = useBehavior(vm.fatalError$); // Stop the rendering and throw for the error boundary if (fatalCallError) { @@ -279,58 +277,21 @@ export const InCallView: FC = ({ throw fatalCallError; } - // We need to set the proper timings on the animation based upon the sound length. - const ringDuration = pickupPhaseAudio?.soundDuration["waiting"] ?? 1; - useEffect((): (() => void) => { - // The CSS animation includes the delay, so we must double the length of the sound. - window.document.body.style.setProperty( - "--call-ring-duration-s", - `${ringDuration * 2}s`, - ); - window.document.body.style.setProperty( - "--call-ring-delay-s", - `${ringDuration}s`, - ); - // Remove properties when we unload. - return () => { - window.document.body.style.removeProperty("--call-ring-duration-s"); - window.document.body.style.removeProperty("--call-ring-delay-s"); - }; - }, [pickupPhaseAudio?.soundDuration, ringDuration]); - - // When waiting for pickup, loop a waiting sound + // While ringing, loop the ringtone useEffect((): void | (() => void) => { - if (callPickupState !== "ringing" || !pickupPhaseAudio) return; - const endSound = pickupPhaseAudio.playSoundLooping("waiting", ringDuration); - return () => { - void endSound().catch((e) => { - logger.error("Failed to stop ringing sound", e); - }); - }; - }, [callPickupState, pickupPhaseAudio, ringDuration]); - - // Waiting UI overlay - const waitingOverlay: JSX.Element | null = useMemo(() => { - return ringOverlay ? ( -
-
-
- -
- - {ringOverlay.text} - -
-
- ) : null; - }, [ringOverlay]); + const audio = latestPickupPhaseAudio.current; + if (ringing && audio) { + const endSound = audio.playSoundLooping( + "waiting", + audio.soundDuration["waiting"] ?? 1, + ); + return () => { + void endSound().catch((e) => { + logger.error("Failed to stop ringing sound", e); + }); + }; + } + }, [ringing, latestPickupPhaseAudio]); const onViewClick = useCallback( (e: ReactMouseEvent) => { @@ -764,7 +725,6 @@ export const InCallView: FC = ({ {reconnectingToast} {earpieceOverlay} - {waitingOverlay} {footer} {layout.type !== "pip" && ( <> diff --git a/src/room/WaitingForJoin.module.css b/src/room/WaitingForJoin.module.css deleted file mode 100644 index a598e4820..000000000 --- a/src/room/WaitingForJoin.module.css +++ /dev/null @@ -1,61 +0,0 @@ -.overlay { - position: absolute; - inset: 0; - display: flex; - align-items: center; - justify-content: center; - pointer-events: none; -} - -.content { - display: flex; - flex-direction: column; - align-items: center; - gap: 16px; -} - -.pulse { - position: relative; - height: 90px; -} - -.pulse::before { - content: ""; - position: absolute; - inset: -12px; - border-radius: 9999px; - border: 12px solid rgba(255, 255, 255, 0.6); - animation: pulse var(--call-ring-duration-s) ease-out infinite; - animation-delay: 1s; - opacity: 0; -} - -.text { - color: var(--cpd-color-text-on-solid-primary); -} - -@keyframes pulse { - 0% { - transform: scale(0.95); - opacity: 0.7; - transform: scale(0); - opacity: 1; - } - 35% { - transform: scale(1.15); - opacity: 0.15; - } - 50% { - transform: scale(1.2); - opacity: 0; - } - 50.01% { - transform: scale(0); - } - 85% { - transform: scale(0); - } - 100% { - transform: scale(0); - } -} diff --git a/src/state/CallViewModel/CallNotificationLifecycle.ts b/src/state/CallViewModel/CallNotificationLifecycle.ts index 44ce2e430..3e06108f3 100644 --- a/src/state/CallViewModel/CallNotificationLifecycle.ts +++ b/src/state/CallViewModel/CallNotificationLifecycle.ts @@ -89,7 +89,6 @@ export interface Props { * `callPickupState$` The current call pickup state of the call. * - "unknown": The client has not yet sent the notification event. We don't know if it will because it first needs to send its own membership. * Then we can conclude if we were the first one to join or not. - * This may also be set if we are disconnected. * - "ringing": The call is ringing on other devices in this room (This client should give audiovisual feedback that this is happening). * - "timeout": No-one picked up in the defined time this call should be ringing on others devices. * The call failed. If desired this can be used as a trigger to exit the call. @@ -131,15 +130,9 @@ export function createCallNotificationLifecycle$({ ) as Behavior>; /** - * Whenever the RTC session tells us that it intends to ring the remote - * participant's devices, this emits an Observable tracking the current state of - * that ringing process. + * The state of the current ringing attempt, if the RTC session is indeed + * ringing the remote participant's devices. Otherwise `null`. */ - // This is a behavior since we need to store the latest state for when we subscribe to this after `didSendCallNotification$` - // has already emitted but we still need the latest observable with a timeout timer that only gets created on after receiving `notificationEvent`. - // A behavior will emit the latest observable with the running timer to new subscribers. - // see also: callPickupState$ and in particular the line: `return this.ring$.pipe(mergeAll());` here we otherwise might get an EMPTY observable if - // `ring$` would not be a behavior. const remoteRingState$: Behavior<"ringing" | "timeout" | "decline" | null> = scope.behavior( sentCallNotification$.pipe( diff --git a/src/state/CallViewModel/CallViewModel.test.ts b/src/state/CallViewModel/CallViewModel.test.ts index 5ee679b0e..aca3ee7b9 100644 --- a/src/state/CallViewModel/CallViewModel.test.ts +++ b/src/state/CallViewModel/CallViewModel.test.ts @@ -46,9 +46,11 @@ import { } from "../../utils/test.ts"; import { E2eeType } from "../../e2ee/e2eeType.ts"; import { + alice, aliceId, aliceParticipant, aliceRtcMember, + aliceUserId, bobId, bobRtcMember, local, @@ -140,8 +142,8 @@ export interface SpotlightExpandedLayoutSummary { export interface OneOnOneLayoutSummary { type: "one-on-one"; - local: string; - remote: string; + spotlight: string; + pip: string; } export interface PipLayoutSummary { @@ -194,11 +196,11 @@ function summarizeLayout$(l$: Observable): Observable { ); case "one-on-one": return combineLatest( - [l.local.media$, l.remote.media$], - (local, remote) => ({ + [l.spotlight.media$, l.pip.media$], + (spotlight, pip) => ({ type: l.type, - local: local.id, - remote: remote.id, + spotlight: spotlight.id, + pip: pip.id, }), ); case "pip": @@ -537,8 +539,8 @@ describe.each([ b: { // In a larger window, expect the normal one-on-one layout type: "one-on-one", - local: `${localId}:0`, - remote: `${aliceId}:0`, + pip: `${localId}:0`, + spotlight: `${aliceId}:0`, }, c: { // In a PiP-sized window, we of course expect a PiP layout @@ -840,8 +842,8 @@ describe.each([ }, b: { type: "one-on-one", - local: `${localId}:0`, - remote: `${aliceId}:0`, + pip: `${localId}:0`, + spotlight: `${aliceId}:0`, }, c: { type: "grid", @@ -883,8 +885,8 @@ describe.each([ }, b: { type: "one-on-one", - local: `${localId}:0`, - remote: `${aliceId}:0`, + pip: `${localId}:0`, + spotlight: `${aliceId}:0`, }, c: { type: "grid", @@ -893,8 +895,8 @@ describe.each([ }, d: { type: "one-on-one", - local: `${localId}:0`, - remote: `${daveId}:0`, + pip: `${localId}:0`, + spotlight: `${daveId}:0`, }, }, ); @@ -1087,83 +1089,81 @@ describe.each([ }); }); - describe("waitForCallPickup$", () => { - it.skip("regression test: does stop ringing in case livekitConnectionState$ emits after didSendCallNotification$ has already emitted", () => { - withTestScheduler(({ schedule, expectObservable, behavior }) => { - withCallViewModel( - { - livekitConnectionState$: behavior("d 9ms c", { - d: ConnectionState.Disconnected, - c: ConnectionState.Connected, - }), - }, - (vm, rtcSession) => { - // Fire a call notification IMMEDIATELY (its important for this test, that this happens before the livekitConnectionState$ emits) - schedule("n", { - n: () => { - rtcSession.emit( - MatrixRTCSessionEvent.DidSendCallNotification, - mockRingEvent("$notif1", 30), - ); - }, - }); + test("recipient has placeholder tile while ringing or timed out", () => { + withTestScheduler(({ schedule, expectObservable }) => { + withCallViewModel( + { + roomMembers: [alice, local], // Simulate a DM + }, + (vm, rtcSession) => { + // Fire a ringing notification + schedule("n", { + n: () => { + rtcSession.emit( + MatrixRTCSessionEvent.DidSendCallNotification, + mockRingEvent("$notif1", 30), + ); + }, + }); - expectObservable(vm.callPickupState$).toBe("a 9ms b 19ms c", { - a: "unknown", - b: "ringing", - c: "timeout", - }); - }, - { - waitForCallPickup: true, - encryptionSystem: { kind: E2eeType.PER_PARTICIPANT }, - }, - ); - }); + // Should ring for 30ms and then time out + expectObservable(vm.ringing$).toBe("(ny) 26ms n", yesNo); + // Layout should show placeholder media for the participant we're + // ringing the entire time (even once timed out) + expectObservable(summarizeLayout$(vm.layout$)).toBe("a", { + a: { + type: "one-on-one", + spotlight: `${localId}:0`, + pip: `ringing:${aliceUserId}`, + }, + }); + }, + { waitForCallPickup: true }, + ); }); + }); - it.skip("ringing -> unknown if we get disconnected", () => { - withTestScheduler(({ behavior, schedule, expectObservable }) => { - const connectionState$ = new BehaviorSubject(ConnectionState.Connected); - // Someone joins at 20ms (both LiveKit participant and MatrixRTC member) - withCallViewModel( - { - remoteParticipants$: behavior("a 19ms b", { - a: [], - b: [aliceParticipant], - }), - rtcMembers$: behavior("a 19ms b", { - a: [localRtcMember], - b: [localRtcMember, aliceRtcMember], - }), - livekitConnectionState$: connectionState$, - }, - (vm, rtcSession) => { - // Notify at 5ms so we enter ringing, then get disconnected 5ms later - schedule(" 5ms r 5ms d", { - r: () => { - rtcSession.emit( - MatrixRTCSessionEvent.DidSendCallNotification, - mockRingEvent("$notif2", 100), - ); - }, - d: () => { - connectionState$.next(ConnectionState.Disconnected); - }, - }); + test("recipient's placeholder tile is replaced by their real tile once they answer", () => { + withTestScheduler(({ behavior, schedule, expectObservable }) => { + withCallViewModel( + { + // Alice answers after 20ms + rtcMembers$: behavior("a 20ms b", { + a: [localRtcMember], + b: [localRtcMember, aliceRtcMember], + }), + roomMembers: [alice, local], // Simulate a DM + }, + (vm, rtcSession) => { + // Fire a ringing notification + schedule("n", { + n: () => { + rtcSession.emit( + MatrixRTCSessionEvent.DidSendCallNotification, + mockRingEvent("$notif1", 30), + ); + }, + }); - expectObservable(vm.callPickupState$).toBe("a 4ms b 5ms c", { - a: "unknown", - b: "ringing", - c: "unknown", - }); - }, - { - waitForCallPickup: true, - encryptionSystem: { kind: E2eeType.PER_PARTICIPANT }, - }, - ); - }); + // Should ring until Alice joins + expectObservable(vm.ringing$).toBe("(ny) 17ms n", yesNo); + // Layout should show placeholder media for the participant we're + // ringing the entire time + expectObservable(summarizeLayout$(vm.layout$)).toBe("a 20ms b", { + a: { + type: "one-on-one", + spotlight: `${localId}:0`, + pip: `ringing:${aliceUserId}`, + }, + b: { + type: "one-on-one", + spotlight: `${aliceId}:0`, + pip: `${localId}:0`, + }, + }); + }, + { waitForCallPickup: true }, + ); }); }); diff --git a/src/state/CallViewModel/CallViewModel.ts b/src/state/CallViewModel/CallViewModel.ts index 18e49d0a9..8b4d19fbf 100644 --- a/src/state/CallViewModel/CallViewModel.ts +++ b/src/state/CallViewModel/CallViewModel.ts @@ -128,7 +128,6 @@ import { createSentCallNotification$, } from "./CallNotificationLifecycle.ts"; import { - createDMMember$, createMatrixMemberMetadata$, createRoomMembers$, } from "./remoteMembers/MatrixMemberMetadata.ts"; @@ -137,12 +136,17 @@ import { type Connection } from "./remoteMembers/Connection.ts"; import { createLayoutModeSwitch } from "./LayoutSwitch.ts"; import { createWrappedUserMedia, - type MediaItem, type WrappedUserMediaViewModel, -} from "../media/MediaItem.ts"; +} from "../media/WrappedUserMediaViewModel.ts"; import { type ScreenShareViewModel } from "../media/ScreenShareViewModel.ts"; import { type UserMediaViewModel } from "../media/UserMediaViewModel.ts"; import { type MediaViewModel } from "../media/MediaViewModel.ts"; +import { type LocalUserMediaViewModel } from "../media/LocalUserMediaViewModel.ts"; +import { type RemoteUserMediaViewModel } from "../media/RemoteUserMediaViewModel.ts"; +import { + createRingingMedia, + type RingingMediaViewModel, +} from "../media/RingingMediaViewModel.ts"; const logger = rootLogger.getChild("[CallViewModel]"); //TODO @@ -210,11 +214,10 @@ export type LivekitRoomItem = { export interface CallViewModel { // lifecycle autoLeave$: Observable; - // TODO if we are in "unknown" state we need a loading rendering (or empty screen) - // Otherwise it looks like we already connected and only than the ringing starts which is weird. - callPickupState$: Behavior< - "unknown" | "ringing" | "timeout" | "decline" | "success" | null - >; + /** + * Whether we are ringing a call recipient. + */ + ringing$: Behavior; /** Observable that emits when the user should leave the call (hangup pressed, widget action, error). * THIS DOES NOT LEAVE THE CALL YET. The only way to leave the call (send the hangup event) is * - by ending the scope @@ -289,13 +292,6 @@ export interface CallViewModel { /** List of reactions. Keys are: membership.membershipId (currently predefined as: `${membershipEvent.userId}:${membershipEvent.deviceId}`)*/ reactions$: Behavior>; - ringOverlay$: Behavior; // sounds and events joinSoundEffect$: Observable; leaveSoundEffect$: Observable; @@ -611,40 +607,6 @@ export function createCallViewModel$( matrixRoomMembers$, ); - const dmMember$ = createDMMember$(scope, matrixRoomMembers$, matrixRoom); - const noUserToCallInRoom$ = scope.behavior( - matrixRoomMembers$.pipe( - map( - (roomMembersMap) => - roomMembersMap.size === 1 && roomMembersMap.get(userId) !== undefined, - ), - ), - ); - - const ringOverlay$ = scope.behavior( - combineLatest([noUserToCallInRoom$, dmMember$, callPickupState$]).pipe( - map(([noUserToCallInRoom, dmMember, callPickupState]) => { - // No overlay if not in ringing state - if (callPickupState !== "ringing" || noUserToCallInRoom) return null; - - const name = dmMember ? dmMember.rawDisplayName : matrixRoom.name; - const id = dmMember ? dmMember.userId : matrixRoom.roomId; - const text = dmMember - ? `Waiting for ${name} to join…` - : "Waiting for other participants…"; - const avatarMxc = dmMember - ? (dmMember.getMxcAvatarUrl?.() ?? undefined) - : (matrixRoom.getMxcAvatarUrl() ?? undefined); - return { - name: name ?? id, - idForAvatar: id, - text, - avatarMxc, - }; - }), - ), - ); - const allConnections$ = scope.behavior( connectionManager.connectionManagerData$.pipe(map((d) => d.value)), ); @@ -720,7 +682,7 @@ export function createCallViewModel$( matrixLivekitMembers$, duplicateTiles.value$, ]).pipe( - // Generate a collection of MediaItems from the list of expected (whether + // Generate a collection of user media from the list of expected (whether // present or missing) LiveKit participants. generateItems( "CallViewModel userMedia$", @@ -793,32 +755,67 @@ export function createCallViewModel$( ), ); + const ringingMedia$ = scope.behavior( + combineLatest([userMedia$, matrixRoomMembers$, callPickupState$]).pipe( + generateItems( + "CallViewModel ringingMedia$", + function* ([userMedia, roomMembers, callPickupState]) { + if ( + callPickupState === "ringing" || + callPickupState === "timeout" || + callPickupState === "decline" + ) { + for (const member of roomMembers.values()) { + if (!userMedia.some((vm) => vm.userId === member.userId)) + yield { + keys: [member.userId], + data: callPickupState, + }; + } + } + }, + (scope, pickupState$, userId) => + createRingingMedia({ + id: `ringing:${userId}`, + userId, + displayName$: scope.behavior( + matrixRoomMembers$.pipe( + map((members) => members.get(userId)?.rawDisplayName || userId), + ), + ), + mxcAvatarUrl$: + matrixMemberMetadataStore.createAvatarUrlBehavior$(userId), + pickupState$, + muteStates, + }), + ), + distinctUntilChanged(shallowEquals), + tap((ringingMedia) => { + if (ringingMedia.length > 1) + // Warn that UI may do something unexpected in this case + logger.warn( + `Ringing more than one participant is not supported (ringing ${ringingMedia.map((vm) => vm.userId).join(", ")})`, + ); + }), + ), + ); + /** - * List of all media items (user media and screen share media) that we want - * tiles for. + * All screen share media that we want to display. */ - const mediaItems$ = scope.behavior( + const screenShares$ = scope.behavior( userMedia$.pipe( switchMap((userMedia) => userMedia.length === 0 ? of([]) : combineLatest( userMedia.map((m) => m.screenShares$), - (...screenShares) => [...userMedia, ...screenShares.flat(1)], + (...screenShares) => screenShares.flat(1), ), ), ), ); - /** - * List of MediaItems that we want to display, that are of type ScreenShare - */ - const screenShares$ = scope.behavior( - mediaItems$.pipe( - map((mediaItems) => mediaItems.filter((m) => m.type === "screen share")), - ), - ); - const joinSoundEffect$ = userMedia$.pipe( pairwise(), filter( @@ -931,40 +928,20 @@ export function createCallViewModel$( ), ); - const spotlight$ = scope.behavior( - screenShares$.pipe( - switchMap((screenShares) => { - if (screenShares.length > 0) return of(screenShares); - - return spotlightSpeaker$.pipe( - map((speaker) => (speaker ? [speaker] : [])), + /** + * Local user media suitable for displaying in a PiP (undefined if not found + * or if user prefers to not see themselves). + */ + const localUserMediaForPip$ = scope.behavior< + LocalUserMediaViewModel | undefined + >( + userMedia$.pipe( + switchMap((userMedia) => { + const localUserMedia = userMedia.find( + (m): m is WrappedUserMediaViewModel & LocalUserMediaViewModel => + m.type === "user" && m.local, ); - }), - distinctUntilChanged(shallowEquals), - ), - ); - - const pip$ = scope.behavior( - combineLatest([ - // TODO This also needs epoch logic to dedupe the screenshares and mediaItems emits - screenShares$, - spotlightSpeaker$, - mediaItems$, - ]).pipe( - switchMap(([screenShares, spotlight, mediaItems]) => { - if (screenShares.length > 0) { - return spotlightSpeaker$; - } - if (!spotlight || spotlight.local) { - return of(undefined); - } - - const localUserMedia = mediaItems.find( - (m) => m.type === "user" && m.local, - ); - if (!localUserMedia) { - return of(undefined); - } + if (!localUserMedia) return of(undefined); return localUserMedia.alwaysShow$.pipe( map((alwaysShow) => (alwaysShow ? localUserMedia : undefined)), ); @@ -972,6 +949,39 @@ export function createCallViewModel$( ), ); + const spotlightAndPip$ = scope.behavior<{ + spotlight: MediaViewModel[]; + pip$: Behavior; + }>( + ringingMedia$.pipe( + switchMap((ringingMedia) => { + if (ringingMedia.length > 0) + return of({ spotlight: ringingMedia, pip$: localUserMediaForPip$ }); + + return screenShares$.pipe( + switchMap((screenShares) => { + if (screenShares.length > 0) + return of({ spotlight: screenShares, pip$: spotlightSpeaker$ }); + + return spotlightSpeaker$.pipe( + map((speaker) => ({ + spotlight: speaker ? [speaker] : [], + pip$: localUserMediaForPip$, + })), + ); + }), + ); + }), + ), + ); + + const spotlight$ = scope.behavior( + spotlightAndPip$.pipe( + map(({ spotlight }) => spotlight), + distinctUntilChanged(shallowEquals), + ), + ); + const hasRemoteScreenShares$ = scope.behavior( spotlight$.pipe( map((spotlight) => @@ -1054,24 +1064,61 @@ export function createCallViewModel$( })); const spotlightExpandedLayoutMedia$: Observable = - combineLatest([spotlight$, pip$], (spotlight, pip) => ({ - type: "spotlight-expanded", - spotlight, - pip: pip ?? undefined, - })); + spotlightAndPip$.pipe( + switchMap(({ spotlight, pip$ }) => + pip$.pipe( + map((pip) => ({ + type: "spotlight-expanded" as const, + spotlight, + pip: pip ?? undefined, + })), + ), + ), + ); const oneOnOneLayoutMedia$: Observable = - mediaItems$.pipe( - map((mediaItems) => { - if (mediaItems.length !== 2) return null; - const local = mediaItems.find((vm) => vm.type === "user" && vm.local); - const remote = mediaItems.find((vm) => vm.type === "user" && !vm.local); - // There might not be a remote tile if there are screen shares, or if - // only the local user is in the call and they're using the duplicate - // tiles option - if (!remote || !local) return null; + userMedia$.pipe( + switchMap((userMedia) => { + if (userMedia.length <= 2) { + const local = userMedia.find( + (vm): vm is WrappedUserMediaViewModel & LocalUserMediaViewModel => + vm.type === "user" && vm.local, + ); - return { type: "one-on-one", local, remote }; + if (local !== undefined) { + const remote = userMedia.find( + ( + vm, + ): vm is WrappedUserMediaViewModel & RemoteUserMediaViewModel => + vm.type === "user" && !vm.local, + ); + + if (remote !== undefined) + return of({ + type: "one-on-one" as const, + spotlight: remote, + pip: local, + }); + + // If there's no other user media in the call (could still happen in + // this branch due to the duplicate tiles option), we could possibly + // show ringing media instead + if (userMedia.length === 1) + return ringingMedia$.pipe( + map((ringingMedia) => { + return ringingMedia.length === 1 + ? { + type: "one-on-one" as const, + spotlight: local, + pip: ringingMedia[0], + } + : null; + }), + ); + } + } + + return of(null); }), ); @@ -1482,8 +1529,9 @@ export function createCallViewModel$( return { autoLeave$: autoLeave$, - callPickupState$: callPickupState$, - ringOverlay$: ringOverlay$, + ringing$: scope.behavior( + callPickupState$.pipe(map((state) => state === "ringing")), + ), leave$: leave$, hangup: (): void => userHangup$.next(), join: localMembership.requestJoinAndPublish, diff --git a/src/state/CallViewModel/CallViewModelTestUtils.ts b/src/state/CallViewModel/CallViewModelTestUtils.ts index b6f532751..b6bf8a9a1 100644 --- a/src/state/CallViewModel/CallViewModelTestUtils.ts +++ b/src/state/CallViewModel/CallViewModelTestUtils.ts @@ -17,7 +17,7 @@ import { import { SyncState } from "matrix-js-sdk/lib/sync"; import { BehaviorSubject, type Observable, map, of } from "rxjs"; import { onTestFinished, vi } from "vitest"; -import { ClientEvent, type MatrixClient } from "matrix-js-sdk"; +import { ClientEvent, type RoomMember, type MatrixClient } from "matrix-js-sdk"; import EventEmitter from "events"; import * as ComponentsCore from "@livekit/components-core"; @@ -63,15 +63,10 @@ const carol = local; const dave = mockMatrixRoomMember(daveRTLRtcMember, { rawDisplayName: "Dave" }); -const roomMembers = new Map( - [alice, aliceDoppelganger, bob, bobZeroWidthSpace, carol, dave, daveRTL].map( - (p) => [p.userId, p], - ), -); - export interface CallViewModelInputs { remoteParticipants$: Behavior; rtcMembers$: Behavior[]>; + roomMembers: RoomMember[]; livekitConnectionState$: Behavior; speaking: Map>; mediaDevices: MediaDevices; @@ -86,6 +81,15 @@ export function withCallViewModel(mode: MatrixRTCMode) { { remoteParticipants$ = constant([]), rtcMembers$ = constant([localRtcMember]), + roomMembers = [ + alice, + aliceDoppelganger, + bob, + bobZeroWidthSpace, + carol, + dave, + daveRTL, + ], livekitConnectionState$: connectionState$ = constant( ConnectionState.Connected, ), @@ -128,8 +132,8 @@ export function withCallViewModel(mode: MatrixRTCMode) { return syncState; } })() as Partial as MatrixClient, - getMembers: () => Array.from(roomMembers.values()), - getMembersWithMembership: () => Array.from(roomMembers.values()), + getMembers: () => roomMembers, + getMembersWithMembership: () => roomMembers, }); const rtcSession = new MockRTCSession(room, []).withMemberships( rtcMembers$, diff --git a/src/state/CallViewModel/remoteMembers/MatrixMemberMetadata.ts b/src/state/CallViewModel/remoteMembers/MatrixMemberMetadata.ts index c1a7a499f..d9be2d350 100644 --- a/src/state/CallViewModel/remoteMembers/MatrixMemberMetadata.ts +++ b/src/state/CallViewModel/remoteMembers/MatrixMemberMetadata.ts @@ -54,31 +54,6 @@ export function createRoomMembers$( ); } -/** - * creates the member that this DM is with in case it is a DM (two members) otherwise null - */ -export function createDMMember$( - scope: ObservableScope, - roomMembers$: Behavior, - matrixRoom: MatrixRoom, -): Behavior | null> { - // We cannot use the normal direct check from matrix since we do not have access to the account data. - // use primitive member count === 2 check instead. - return scope.behavior( - roomMembers$.pipe( - map((membersMap) => { - // primitive appraoch do to no access to account data. - const isDM = membersMap.size === 2; - if (!isDM) return null; - return matrixRoom.getMember(matrixRoom.guessDMUserId()); - }), - ), - ); -} - /** * Displayname for each member of the call. This will disambiguate * any displayname that clashes with another member. Only members diff --git a/src/state/OneOnOneLayout.ts b/src/state/OneOnOneLayout.ts index 102689450..27fa4439e 100644 --- a/src/state/OneOnOneLayout.ts +++ b/src/state/OneOnOneLayout.ts @@ -16,14 +16,14 @@ export function oneOnOneLayout( prevTiles: TileStore, ): [OneOnOneLayout, TileStore] { const update = prevTiles.from(2); - update.registerGridTile(media.local); - update.registerGridTile(media.remote); + update.registerGridTile(media.pip); + update.registerGridTile(media.spotlight); const tiles = update.build(); return [ { type: media.type, - local: tiles.gridTilesByMedia.get(media.local)!, - remote: tiles.gridTilesByMedia.get(media.remote)!, + spotlight: tiles.gridTilesByMedia.get(media.spotlight)!, + pip: tiles.gridTilesByMedia.get(media.pip)!, }, tiles, ]; diff --git a/src/state/TileStore.ts b/src/state/TileStore.ts index a954eb4e1..300e6bd2f 100644 --- a/src/state/TileStore.ts +++ b/src/state/TileStore.ts @@ -13,6 +13,7 @@ import { fillGaps } from "../utils/iter"; import { debugTileLayout } from "../settings/settings"; import { type MediaViewModel } from "./media/MediaViewModel"; import { type UserMediaViewModel } from "./media/UserMediaViewModel"; +import { type RingingMediaViewModel } from "./media/RingingMediaViewModel"; function debugEntries(entries: GridTileData[]): string[] { return entries.map((e) => e.media.displayName$.value); @@ -48,8 +49,10 @@ class SpotlightTileData { } class GridTileData { - private readonly media$: BehaviorSubject; - public get media(): UserMediaViewModel { + private readonly media$: BehaviorSubject< + UserMediaViewModel | RingingMediaViewModel + >; + public get media(): UserMediaViewModel | RingingMediaViewModel { return this.media$.value; } public set media(value: UserMediaViewModel) { @@ -58,7 +61,7 @@ class GridTileData { public readonly vm: GridTileViewModel; - public constructor(media: UserMediaViewModel) { + public constructor(media: UserMediaViewModel | RingingMediaViewModel) { this.media$ = new BehaviorSubject(media); this.vm = new GridTileViewModel(this.media$); } @@ -178,7 +181,9 @@ export class TileStoreBuilder { * Sets up a grid tile for the given media. If this is never called for some * media, then that media will have no grid tile. */ - public registerGridTile(media: UserMediaViewModel): void { + public registerGridTile( + media: UserMediaViewModel | RingingMediaViewModel, + ): void { if (DEBUG_ENABLED) logger.debug( `[TileStore, ${this.generation}] register grid tile: ${media.displayName$.value}`, @@ -187,7 +192,11 @@ export class TileStoreBuilder { if (this.spotlight !== null) { // We actually *don't* want spotlight speakers to appear in both the // spotlight and the grid, so they're filtered out here - if (!media.local && this.spotlight.media.includes(media)) return; + if ( + !(media.type === "user" && media.local) && + this.spotlight.media.includes(media) + ) + return; // When the spotlight speaker changes, we would see one grid tile appear // and another grid tile disappear. This would be an undesirable layout // shift, so instead what we do is take the speaker's grid tile and swap diff --git a/src/state/TileViewModel.ts b/src/state/TileViewModel.ts index 8b13c685a..eeec0c889 100644 --- a/src/state/TileViewModel.ts +++ b/src/state/TileViewModel.ts @@ -7,6 +7,7 @@ Please see LICENSE in the repository root for full details. import { type Behavior } from "./Behavior"; import { type MediaViewModel } from "./media/MediaViewModel"; +import { type RingingMediaViewModel } from "./media/RingingMediaViewModel"; import { type UserMediaViewModel } from "./media/UserMediaViewModel"; let nextId = 0; @@ -17,7 +18,11 @@ function createId(): string { export class GridTileViewModel { public readonly id = createId(); - public constructor(public readonly media$: Behavior) {} + public constructor( + public readonly media$: Behavior< + UserMediaViewModel | RingingMediaViewModel + >, + ) {} } export class SpotlightTileViewModel { diff --git a/src/state/layout-types.ts b/src/state/layout-types.ts index 33796f668..2e779057d 100644 --- a/src/state/layout-types.ts +++ b/src/state/layout-types.ts @@ -7,7 +7,7 @@ Please see LICENSE in the repository root for full details. import { type LocalUserMediaViewModel } from "./media/LocalUserMediaViewModel.ts"; import { type MediaViewModel } from "./media/MediaViewModel.ts"; -import { type RemoteUserMediaViewModel } from "./media/RemoteUserMediaViewModel.ts"; +import { type RingingMediaViewModel } from "./media/RingingMediaViewModel.ts"; import { type UserMediaViewModel } from "./media/UserMediaViewModel.ts"; import { type GridTileViewModel, @@ -40,8 +40,8 @@ export interface SpotlightExpandedLayoutMedia { export interface OneOnOneLayoutMedia { type: "one-on-one"; - local: LocalUserMediaViewModel; - remote: RemoteUserMediaViewModel; + spotlight: UserMediaViewModel; + pip: LocalUserMediaViewModel | RingingMediaViewModel; } export interface PipLayoutMedia { @@ -86,8 +86,8 @@ export interface SpotlightExpandedLayout { export interface OneOnOneLayout { type: "one-on-one"; - local: GridTileViewModel; - remote: GridTileViewModel; + spotlight: GridTileViewModel; + pip: GridTileViewModel; } export interface PipLayout { diff --git a/src/state/media/MediaViewModel.ts b/src/state/media/MediaViewModel.ts index bdc4875b7..9a253d811 100644 --- a/src/state/media/MediaViewModel.ts +++ b/src/state/media/MediaViewModel.ts @@ -7,13 +7,17 @@ Please see LICENSE in the repository root for full details. */ import { type Behavior } from "../Behavior"; +import { type RingingMediaViewModel } from "./RingingMediaViewModel"; import { type ScreenShareViewModel } from "./ScreenShareViewModel"; import { type UserMediaViewModel } from "./UserMediaViewModel"; /** * A participant's media. */ -export type MediaViewModel = UserMediaViewModel | ScreenShareViewModel; +export type MediaViewModel = + | UserMediaViewModel + | ScreenShareViewModel + | RingingMediaViewModel; /** * Properties which are common to all MediaViewModels. diff --git a/src/state/media/MemberMediaViewModel.ts b/src/state/media/MemberMediaViewModel.ts index e7f57b59e..969da8996 100644 --- a/src/state/media/MemberMediaViewModel.ts +++ b/src/state/media/MemberMediaViewModel.ts @@ -38,6 +38,8 @@ import { type ObservableScope } from "../ObservableScope"; import { observeTrackReference$ } from "../observeTrackReference"; import { E2eeType } from "../../e2ee/e2eeType"; import { observeInboundRtpStreamStats$ } from "./observeRtpStreamStats"; +import { type UserMediaViewModel } from "./UserMediaViewModel"; +import { type ScreenShareViewModel } from "./ScreenShareViewModel"; // TODO: Encryption status is kinda broken and thus unused right now. Remove? export enum EncryptionStatus { @@ -49,9 +51,9 @@ export enum EncryptionStatus { } /** - * Media belonging to an active member of the RTC session. + * Properties common to all MemberMediaViewModels. */ -export interface MemberMediaViewModel extends BaseMediaViewModel { +export interface BaseMemberMediaViewModel extends BaseMediaViewModel { /** * The LiveKit video track for this media. */ @@ -88,7 +90,7 @@ export function createMemberMedia( encryptionSystem, ...inputs }: MemberMediaInputs, -): MemberMediaViewModel { +): BaseMemberMediaViewModel { const trackBehavior$ = ( source: Track.Source, ): Behavior => @@ -270,3 +272,8 @@ function observeRemoteTrackReceivingOkay$( startWith(undefined), ); } + +/** + * Media belonging to an active member of the call. + */ +export type MemberMediaViewModel = UserMediaViewModel | ScreenShareViewModel; diff --git a/src/state/media/RingingMediaViewModel.ts b/src/state/media/RingingMediaViewModel.ts new file mode 100644 index 000000000..23291723e --- /dev/null +++ b/src/state/media/RingingMediaViewModel.ts @@ -0,0 +1,51 @@ +/* +Copyright 2026 Element Creations Ltd. + +SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial +Please see LICENSE in the repository root for full details. +*/ + +import { type Behavior } from "../Behavior"; +import { type MuteStates } from "../MuteStates"; +import { + type BaseMediaInputs, + type BaseMediaViewModel, + createBaseMedia, +} from "./MediaViewModel"; + +/** + * Media representing a user who is not yet part of the call — one that we are + * *ringing*. + */ +export interface RingingMediaViewModel extends BaseMediaViewModel { + type: "ringing"; + pickupState$: Behavior<"ringing" | "timeout" | "decline">; + /** + * Whether this media would be expected to have video, were it not simply a + * placeholder. + */ + videoEnabled$: Behavior; +} + +export interface RingingMediaInputs extends BaseMediaInputs { + pickupState$: Behavior<"ringing" | "timeout" | "decline">; + /** + * The local user's own mute states. + */ + muteStates: MuteStates; +} + +export function createRingingMedia({ + pickupState$, + muteStates, + ...inputs +}: RingingMediaInputs): RingingMediaViewModel { + return { + ...createBaseMedia(inputs), + type: "ringing", + pickupState$, + // If our own video is enabled, then this is a video call and we would + // expect remote media to have video as well + videoEnabled$: muteStates.video.enabled$, + }; +} diff --git a/src/state/media/ScreenShareViewModel.ts b/src/state/media/ScreenShareViewModel.ts index 36cd94404..8336f0a6b 100644 --- a/src/state/media/ScreenShareViewModel.ts +++ b/src/state/media/ScreenShareViewModel.ts @@ -13,7 +13,7 @@ import { type LocalScreenShareViewModel } from "./LocalScreenShareViewModel"; import { createMemberMedia, type MemberMediaInputs, - type MemberMediaViewModel, + type BaseMemberMediaViewModel, } from "./MemberMediaViewModel"; import { type RemoteScreenShareViewModel } from "./RemoteScreenShareViewModel"; @@ -27,7 +27,7 @@ export type ScreenShareViewModel = /** * Properties which are common to all ScreenShareViewModels. */ -export interface BaseScreenShareViewModel extends MemberMediaViewModel { +export interface BaseScreenShareViewModel extends BaseMemberMediaViewModel { type: "screen share"; } diff --git a/src/state/media/UserMediaViewModel.ts b/src/state/media/UserMediaViewModel.ts index 16af7f262..a20c489e6 100644 --- a/src/state/media/UserMediaViewModel.ts +++ b/src/state/media/UserMediaViewModel.ts @@ -27,7 +27,7 @@ import { type LocalUserMediaViewModel } from "./LocalUserMediaViewModel"; import { createMemberMedia, type MemberMediaInputs, - type MemberMediaViewModel, + type BaseMemberMediaViewModel, } from "./MemberMediaViewModel"; import { type RemoteUserMediaViewModel } from "./RemoteUserMediaViewModel"; import { type ObservableScope } from "../ObservableScope"; @@ -42,7 +42,7 @@ export type UserMediaViewModel = | LocalUserMediaViewModel | RemoteUserMediaViewModel; -export interface BaseUserMediaViewModel extends MemberMediaViewModel { +export interface BaseUserMediaViewModel extends BaseMemberMediaViewModel { type: "user"; speaking$: Behavior; audioEnabled$: Behavior; diff --git a/src/state/media/MediaItem.ts b/src/state/media/WrappedUserMediaViewModel.ts similarity index 98% rename from src/state/media/MediaItem.ts rename to src/state/media/WrappedUserMediaViewModel.ts index 6cd80045a..e9575d0c0 100644 --- a/src/state/media/MediaItem.ts +++ b/src/state/media/WrappedUserMediaViewModel.ts @@ -194,5 +194,3 @@ export function createWrappedUserMedia( ), }; } - -export type MediaItem = WrappedUserMediaViewModel | ScreenShareViewModel; diff --git a/src/tile/GridTile.test.tsx b/src/tile/GridTile.test.tsx index 02f09a17b..501f440c7 100644 --- a/src/tile/GridTile.test.tsx +++ b/src/tile/GridTile.test.tsx @@ -7,9 +7,10 @@ Please see LICENSE in the repository root for full details. import { type RemoteTrackPublication } from "livekit-client"; import { test, expect } from "vitest"; -import { render, screen } from "@testing-library/react"; +import { act, render, screen } from "@testing-library/react"; import { axe } from "vitest-axe"; import { type MatrixRTCSession } from "matrix-js-sdk/lib/matrixrtc"; +import { BehaviorSubject } from "rxjs"; import { GridTile } from "./GridTile"; import { @@ -21,6 +22,11 @@ import { GridTileViewModel } from "../state/TileViewModel"; import { ReactionsSenderProvider } from "../reactions/useReactionsSender"; import type { CallViewModel } from "../state/CallViewModel/CallViewModel"; import { constant } from "../state/Behavior"; +import { + createRingingMedia, + type RingingMediaViewModel, +} from "../state/media/RingingMediaViewModel"; +import { type MuteStates } from "../state/MuteStates"; global.IntersectionObserver = class MockIntersectionObserver { public observe(): void {} @@ -28,6 +34,27 @@ global.IntersectionObserver = class MockIntersectionObserver { public disconnect(): void {} } as unknown as typeof IntersectionObserver; +const fakeRtcSession = { + on: () => {}, + off: () => {}, + room: { + on: () => {}, + off: () => {}, + client: { + getUserId: () => null, + getDeviceId: () => null, + on: () => {}, + off: () => {}, + }, + }, + memberships: [], +} as unknown as MatrixRTCSession; + +const callVm = { + reactions$: constant({}), + handsRaised$: constant({}), +} as Partial as CallViewModel; + test("GridTile is accessible", async () => { const vm = mockRemoteMedia( mockRtcMembership("@alice:example.org", "AAAA"), @@ -42,34 +69,15 @@ test("GridTile is accessible", async () => { }), ); - const fakeRtcSession = { - on: () => {}, - off: () => {}, - room: { - on: () => {}, - off: () => {}, - client: { - getUserId: () => null, - getDeviceId: () => null, - on: () => {}, - off: () => {}, - }, - }, - memberships: [], - } as unknown as MatrixRTCSession; - const cVm = { - reactions$: constant({}), - handsRaised$: constant({}), - } as Partial as CallViewModel; const { container } = render( - + {}} targetWidth={300} targetHeight={200} showSpeakingIndicators - focusable={true} + focusable /> , ); @@ -77,3 +85,40 @@ test("GridTile is accessible", async () => { // Name should be visible screen.getByText("Alice"); }); + +test("GridTile displays ringing media", async () => { + const pickupState$ = new BehaviorSubject< + RingingMediaViewModel["pickupState$"]["value"] + >("ringing"); + const vm = createRingingMedia({ + pickupState$, + muteStates: { + video: { enabled$: constant(false) }, + } as unknown as MuteStates, + id: "test", + userId: "@alice:example.org", + displayName$: constant("Alice"), + mxcAvatarUrl$: constant(undefined), + }); + + const { container } = render( + + {}} + targetWidth={300} + targetHeight={200} + showSpeakingIndicators + focusable + /> + , + ); + expect(await axe(container)).toHaveNoViolations(); + // Name and status should be visible + screen.getByText("Alice"); + screen.getByText("Calling…"); + + // Alice declines the call + act(() => pickupState$.next("decline")); + screen.getByText("Call ended"); +}); diff --git a/src/tile/GridTile.tsx b/src/tile/GridTile.tsx index c8052a659..13cf677f3 100644 --- a/src/tile/GridTile.tsx +++ b/src/tile/GridTile.tsx @@ -29,6 +29,9 @@ import { UserProfileIcon, VolumeOffSolidIcon, SwitchCameraSolidIcon, + VideoCallSolidIcon, + VoiceCallSolidIcon, + EndCallIcon, } from "@vector-im/compound-design-tokens/assets/web/icons"; import { ContextMenu, @@ -49,6 +52,7 @@ import { useBehavior } from "../useBehavior"; import { type LocalUserMediaViewModel } from "../state/media/LocalUserMediaViewModel"; import { type RemoteUserMediaViewModel } from "../state/media/RemoteUserMediaViewModel"; import { type UserMediaViewModel } from "../state/media/UserMediaViewModel"; +import { type RingingMediaViewModel } from "../state/media/RingingMediaViewModel"; interface TileProps { ref?: Ref; @@ -56,21 +60,56 @@ interface TileProps { style?: ComponentProps["style"]; targetWidth: number; targetHeight: number; - focusUrl: string | undefined; displayName: string; mxcAvatarUrl: string | undefined; - showSpeakingIndicators: boolean; focusable: boolean; } +interface RingingMediaTileProps extends TileProps { + vm: RingingMediaViewModel; +} + +const RingingMediaTile: FC = ({ + vm, + className, + ...props +}) => { + const { t } = useTranslation(); + const pickupState = useBehavior(vm.pickupState$); + const videoEnabled = useBehavior(vm.videoEnabled$); + + return ( + + ); +}; + interface UserMediaTileProps extends TileProps { vm: UserMediaViewModel; + showSpeakingIndicators: boolean; mirror: boolean; playbackMuted: boolean; waitingForMedia?: boolean; primaryButton?: ReactNode; menuStart?: ReactNode; menuEnd?: ReactNode; + focusUrl: string | undefined; } const UserMediaTile: FC = ({ @@ -95,7 +134,6 @@ const UserMediaTile: FC = ({ const { t } = useTranslation(); const video = useBehavior(vm.video$); const unencryptedWarning = useBehavior(vm.unencryptedWarning$); - const encryptionStatus = useBehavior(vm.encryptionStatus$); const audioStreamStats = useObservableEagerState< RTCInboundRtpStreamStats | RTCOutboundRtpStreamStats | undefined >(vm.audioStreamStats$); @@ -153,7 +191,6 @@ const UserMediaTile: FC = ({ video={video} userId={vm.userId} unencryptedWarning={unencryptedWarning} - encryptionStatus={encryptionStatus} videoEnabled={videoEnabled} videoFit={videoFit} className={classNames(className, styles.tile, { @@ -218,6 +255,7 @@ UserMediaTile.displayName = "UserMediaTile"; interface LocalUserMediaTileProps extends TileProps { vm: LocalUserMediaViewModel; + showSpeakingIndicators: boolean; onOpenProfile: (() => void) | null; } @@ -232,6 +270,7 @@ const LocalUserMediaTile: FC = ({ const mirror = useBehavior(vm.mirror$); const alwaysShow = useBehavior(vm.alwaysShow$); const switchCamera = useBehavior(vm.switchCamera$); + const focusUrl = useBehavior(vm.focusUrl$); const latestAlwaysShow = useLatest(alwaysShow); const onSelectAlwaysShow = useCallback( @@ -278,6 +317,7 @@ const LocalUserMediaTile: FC = ({ ) } focusable={focusable} + focusUrl={focusUrl} {...props} /> ); @@ -287,6 +327,7 @@ LocalUserMediaTile.displayName = "LocalUserMediaTile"; interface RemoteUserMediaTileProps extends TileProps { vm: RemoteUserMediaViewModel; + showSpeakingIndicators: boolean; } const RemoteUserMediaTile: FC = ({ @@ -298,6 +339,8 @@ const RemoteUserMediaTile: FC = ({ const waitingForMedia = useBehavior(vm.waitingForMedia$); const playbackMuted = useBehavior(vm.playbackMuted$); const playbackVolume = useBehavior(vm.playbackVolume$); + const focusUrl = useBehavior(vm.focusUrl$); + const onSelectMute = useCallback( (e: Event) => { e.preventDefault(); @@ -338,6 +381,7 @@ const RemoteUserMediaTile: FC = ({ } + focusUrl={focusUrl} {...props} /> ); @@ -360,23 +404,33 @@ interface GridTileProps { export const GridTile: FC = ({ ref: theirRef, vm, + showSpeakingIndicators, onOpenProfile, ...props }) => { const ourRef = useRef(null); const ref = useMergedRefs(ourRef, theirRef); const media = useBehavior(vm.media$); - const focusUrl = useBehavior(media.focusUrl$); const displayName = useBehavior(media.displayName$); const mxcAvatarUrl = useBehavior(media.mxcAvatarUrl$); - if (media.local) { + if (media.type === "ringing") { + return ( + + ); + } else if (media.local) { return ( = ({ 0) { @@ -71,14 +76,15 @@ unconditionally select the container so we can use cqmin units */ .fg { position: absolute; - inset: var( + --fg-inset: var( --media-view-fg-inset, calc(var(--media-view-border-radius) - var(--cpd-space-3x)) ); + inset: var(--fg-inset); display: grid; grid-template-columns: 30px 1fr 30px; grid-template-rows: 1fr auto; - grid-template-areas: "reactions status ." "nameTag nameTag button"; + grid-template-areas: "status status reactions" "nameTag nameTag button"; gap: var(--cpd-space-1x); place-items: start; } @@ -102,21 +108,19 @@ unconditionally select the container so we can use cqmin units */ .status { grid-area: status; - justify-self: center; - align-self: start; - padding: var(--cpd-space-2x); - padding-block: var(--cpd-space-2x); color: var(--cpd-color-text-primary); - background-color: var(--cpd-color-bg-canvas-default); display: flex; + flex-wrap: none; align-items: center; - border-radius: var(--cpd-radius-pill-effect); + gap: 3px; user-select: none; overflow: hidden; - box-shadow: var(--small-drop-shadow); - box-sizing: border-box; - max-inline-size: 100%; - text-align: center; + margin-block-start: calc(var(--cpd-space-3x) - var(--fg-inset)); + margin-inline-start: calc(var(--cpd-space-4x) - var(--fg-inset)); +} + +.status svg { + color: var(--cpd-color-icon-tertiary); } .reactions { diff --git a/src/tile/MediaView.test.tsx b/src/tile/MediaView.test.tsx index a509d3a5a..6ef5eb7eb 100644 --- a/src/tile/MediaView.test.tsx +++ b/src/tile/MediaView.test.tsx @@ -18,7 +18,6 @@ import { TrackInfo } from "@livekit/protocol"; import { type ComponentProps } from "react"; import { MediaView } from "./MediaView"; -import { EncryptionStatus } from "../state/media/MemberMediaViewModel"; import { mockLocalParticipant } from "../utils/test"; describe("MediaView", () => { @@ -41,7 +40,6 @@ describe("MediaView", () => { videoFit: "contain", targetWidth: 300, targetHeight: 200, - encryptionStatus: EncryptionStatus.Connecting, mirror: false, unencryptedWarning: false, video: trackReference, diff --git a/src/tile/MediaView.tsx b/src/tile/MediaView.tsx index f912c069f..eb6cc6b44 100644 --- a/src/tile/MediaView.tsx +++ b/src/tile/MediaView.tsx @@ -7,7 +7,13 @@ Please see LICENSE in the repository root for full details. import { type TrackReferenceOrPlaceholder } from "@livekit/components-core"; import { animated } from "@react-spring/web"; -import { type FC, type ComponentProps, type ReactNode } from "react"; +import { + type FC, + type ComponentProps, + type ReactNode, + type ComponentType, + type SVGAttributes, +} from "react"; import { useTranslation } from "react-i18next"; import classNames from "classnames"; import { VideoTrack } from "@livekit/components-react"; @@ -16,7 +22,6 @@ import { ErrorSolidIcon } from "@vector-im/compound-design-tokens/assets/web/ico import styles from "./MediaView.module.css"; import { Avatar } from "../Avatar"; -import { type EncryptionStatus } from "../state/media/MemberMediaViewModel"; import { RaisedHandIndicator } from "../reactions/RaisedHandIndicator"; import { showConnectionStats as showConnectionStatsSetting, @@ -38,7 +43,7 @@ interface Props extends ComponentProps { userId: string; videoEnabled: boolean; unencryptedWarning: boolean; - encryptionStatus: EncryptionStatus; + status?: { text: string; Icon: ComponentType> }; nameTagLeadingIcon?: ReactNode; displayName: string; mxcAvatarUrl: string | undefined; @@ -72,7 +77,7 @@ export const MediaView: FC = ({ mxcAvatarUrl, focusable, primaryButton, - encryptionStatus, + status, raisedHandTime, currentReaction, raisedHandOnClick, @@ -106,7 +111,11 @@ export const MediaView: FC = ({ name={displayName} size={avatarSize} src={mxcAvatarUrl} - className={styles.avatar} + className={classNames(styles.avatar, { + // When the avatar is overlaid with a status, make it translucent + // for readability + [styles.translucent]: status, + })} style={{ display: video && videoEnabled ? "none" : "initial" }} /> {video?.publication !== undefined && ( @@ -152,6 +161,14 @@ export const MediaView: FC = ({ /> )} + {status && ( +
+ + + {status.text} + +
+ )} {/* TODO: Bring this back once encryption status is less broken */} {/*encryptionStatus !== EncryptionStatus.Okay && (
diff --git a/src/tile/SpotlightTile.test.tsx b/src/tile/SpotlightTile.test.tsx index aac81b9cd..533c3b2f5 100644 --- a/src/tile/SpotlightTile.test.tsx +++ b/src/tile/SpotlightTile.test.tsx @@ -6,10 +6,11 @@ Please see LICENSE in the repository root for full details. */ import { test, expect, vi } from "vitest"; -import { isInaccessible, render, screen } from "@testing-library/react"; +import { act, isInaccessible, render, screen } from "@testing-library/react"; import { axe } from "vitest-axe"; import userEvent from "@testing-library/user-event"; import { TooltipProvider } from "@vector-im/compound-web"; +import { BehaviorSubject } from "rxjs"; import { SpotlightTile } from "./SpotlightTile"; import { @@ -23,6 +24,11 @@ import { } from "../utils/test"; import { SpotlightTileViewModel } from "../state/TileViewModel"; import { constant } from "../state/Behavior"; +import { + createRingingMedia, + type RingingMediaViewModel, +} from "../state/media/RingingMediaViewModel"; +import { type MuteStates } from "../state/MuteStates"; global.IntersectionObserver = class MockIntersectionObserver { public observe(): void {} @@ -140,3 +146,41 @@ test("Screen share volume UI is hidden when screen share has no audio", async () screen.queryByRole("button", { name: /volume/i }), ).not.toBeInTheDocument(); }); + +test("SpotlightTile displays ringing media", async () => { + const pickupState$ = new BehaviorSubject< + RingingMediaViewModel["pickupState$"]["value"] + >("ringing"); + const vm = createRingingMedia({ + pickupState$, + muteStates: { + video: { enabled$: constant(false) }, + } as unknown as MuteStates, + id: "test", + userId: "@alice:example.org", + displayName$: constant("Alice"), + mxcAvatarUrl$: constant(undefined), + }); + + const toggleExpanded = vi.fn(); + const { container } = render( + , + ); + + expect(await axe(container)).toHaveNoViolations(); + // Alice should be in the spotlight with the right status + screen.getByText("Alice"); + screen.getByText("Calling…"); + + // Now we time out ringing to Alice + act(() => pickupState$.next("timeout")); + screen.getByText("Call ended"); +}); diff --git a/src/tile/SpotlightTile.tsx b/src/tile/SpotlightTile.tsx index aa66d6b60..c5faba400 100644 --- a/src/tile/SpotlightTile.tsx +++ b/src/tile/SpotlightTile.tsx @@ -24,6 +24,9 @@ import { VolumeOnIcon, VolumeOffSolidIcon, VolumeOnSolidIcon, + VideoCallSolidIcon, + VoiceCallSolidIcon, + EndCallIcon, } from "@vector-im/compound-design-tokens/assets/web/icons"; import { animated } from "@react-spring/web"; import { type Observable, map } from "rxjs"; @@ -43,7 +46,7 @@ import { useReactiveState } from "../useReactiveState"; import { useLatest } from "../useLatest"; import { type SpotlightTileViewModel } from "../state/TileViewModel"; import { useBehavior } from "../useBehavior"; -import { type EncryptionStatus } from "../state/media/MemberMediaViewModel"; +import { type MemberMediaViewModel } from "../state/media/MemberMediaViewModel"; import { type LocalUserMediaViewModel } from "../state/media/LocalUserMediaViewModel"; import { type RemoteUserMediaViewModel } from "../state/media/RemoteUserMediaViewModel"; import { type UserMediaViewModel } from "../state/media/UserMediaViewModel"; @@ -52,6 +55,7 @@ import { type RemoteScreenShareViewModel } from "../state/media/RemoteScreenShar import { type MediaViewModel } from "../state/media/MediaViewModel"; import { Slider } from "../Slider"; import { platform } from "../Platform"; +import { type RingingMediaViewModel } from "../state/media/RingingMediaViewModel"; interface SpotlightItemBaseProps { ref?: Ref; @@ -59,18 +63,20 @@ interface SpotlightItemBaseProps { "data-id": string; targetWidth: number; targetHeight: number; - video: TrackReferenceOrPlaceholder | undefined; userId: string; - unencryptedWarning: boolean; - encryptionStatus: EncryptionStatus; - focusUrl: string | undefined; displayName: string; mxcAvatarUrl: string | undefined; focusable: boolean; "aria-hidden"?: boolean; } -interface SpotlightUserMediaItemBaseProps extends SpotlightItemBaseProps { +interface SpotlightMemberMediaItemBaseProps extends SpotlightItemBaseProps { + video: TrackReferenceOrPlaceholder | undefined; + unencryptedWarning: boolean; + focusUrl: string | undefined; +} + +interface SpotlightUserMediaItemBaseProps extends SpotlightMemberMediaItemBaseProps { videoFit: "contain" | "cover"; videoEnabled: boolean; } @@ -103,21 +109,32 @@ const SpotlightRemoteUserMediaItem: FC = ({ ); }; -interface SpotlightUserMediaItemProps extends SpotlightItemBaseProps { +interface SpotlightUserMediaItemProps extends SpotlightMemberMediaItemBaseProps { vm: UserMediaViewModel; } const SpotlightUserMediaItem: FC = ({ vm, + targetWidth, + targetHeight, ...props }) => { const videoFit = useBehavior(vm.videoFit$); const videoEnabled = useBehavior(vm.videoEnabled$); + // Whenever target bounds change, inform the viewModel + useEffect(() => { + if (targetWidth > 0 && targetHeight > 0) { + vm.setTargetDimensions(targetWidth, targetHeight); + } + }, [targetWidth, targetHeight, vm]); + const baseProps: SpotlightUserMediaItemBaseProps & RefAttributes = { videoFit, videoEnabled, + targetWidth, + targetHeight, ...props, }; @@ -130,7 +147,7 @@ const SpotlightUserMediaItem: FC = ({ SpotlightUserMediaItem.displayName = "SpotlightUserMediaItem"; -interface SpotlightScreenShareItemProps extends SpotlightItemBaseProps { +interface SpotlightScreenShareItemProps extends SpotlightMemberMediaItemBaseProps { vm: ScreenShareViewModel; videoEnabled: boolean; } @@ -142,7 +159,7 @@ const SpotlightScreenShareItem: FC = ({ return ; }; -interface SpotlightRemoteScreenShareItemProps extends SpotlightItemBaseProps { +interface SpotlightRemoteScreenShareItemProps extends SpotlightMemberMediaItemBaseProps { vm: RemoteScreenShareViewModel; } @@ -155,6 +172,67 @@ const SpotlightRemoteScreenShareItem: FC< ); }; +interface SpotlightMemberMediaItemProps extends SpotlightItemBaseProps { + vm: MemberMediaViewModel; +} + +const SpotlightMemberMediaItem: FC = ({ + vm, + ...props +}) => { + const video = useBehavior(vm.video$); + const unencryptedWarning = useBehavior(vm.unencryptedWarning$); + const focusUrl = useBehavior(vm.focusUrl$); + + const baseProps: SpotlightMemberMediaItemBaseProps & + RefAttributes = { + video: video ?? undefined, + unencryptedWarning, + focusUrl, + ...props, + }; + + if (vm.type === "user") + return ; + return vm.local ? ( + + ) : ( + + ); +}; + +interface SpotlightRingingMediaItemProps extends SpotlightItemBaseProps { + vm: RingingMediaViewModel; +} + +const SpotlightRingingMediaItem: FC = ({ + vm, + ...props +}) => { + const { t } = useTranslation(); + const pickupState = useBehavior(vm.pickupState$); + const videoEnabled = useBehavior(vm.videoEnabled$); + + return ( + + ); +}; + interface SpotlightItemProps { ref?: Ref; vm: MediaViewModel; @@ -187,22 +265,9 @@ const SpotlightItem: FC = ({ }) => { const ourRef = useRef(null); - // Whenever target bounds change, inform the viewModel - useEffect(() => { - if (targetWidth > 0 && targetHeight > 0) { - if (vm.type != "screen share") { - vm.setTargetDimensions(targetWidth, targetHeight); - } - } - }, [targetWidth, targetHeight, vm]); - const ref = useMergedRefs(ourRef, theirRef); - const focusUrl = useBehavior(vm.focusUrl$); const displayName = useBehavior(vm.displayName$); const mxcAvatarUrl = useBehavior(vm.mxcAvatarUrl$); - const video = useBehavior(vm.video$); - const unencryptedWarning = useBehavior(vm.unencryptedWarning$); - const encryptionStatus = useBehavior(vm.encryptionStatus$); // Hook this item up to the intersection observer useEffect(() => { @@ -225,23 +290,17 @@ const SpotlightItem: FC = ({ className: classNames(styles.item, { [styles.snap]: snap }), targetWidth, targetHeight, - video: video ?? undefined, userId: vm.userId, - unencryptedWarning, - focusUrl, displayName, mxcAvatarUrl, focusable, - encryptionStatus, "aria-hidden": ariaHidden, }; - if (vm.type === "user") - return ; - return vm.local ? ( - + return vm.type === "ringing" ? ( + ) : ( - + ); }; From fa844446b6a745731ceb20178314bf8ba0b0ca41 Mon Sep 17 00:00:00 2001 From: Robin Date: Wed, 18 Mar 2026 11:29:55 +0100 Subject: [PATCH 380/748] Invert the colors of the camera and microphone buttons So that they use primary color tokens when unmuted, and secondary color tokens when muted. This makes them work like the screen sharing button. --- src/button/Button.tsx | 28 +++++++++---------- src/room/InCallView.tsx | 4 +-- src/room/LobbyView.tsx | 4 +-- .../__snapshots__/InCallView.test.tsx.snap | 4 +-- 4 files changed, 20 insertions(+), 20 deletions(-) diff --git a/src/button/Button.tsx b/src/button/Button.tsx index 00d803f1f..1aff9fa31 100644 --- a/src/button/Button.tsx +++ b/src/button/Button.tsx @@ -22,16 +22,16 @@ import { import styles from "./Button.module.css"; interface MicButtonProps extends ComponentPropsWithoutRef<"button"> { - muted: boolean; + enabled: boolean; size?: "sm" | "lg"; } -export const MicButton: FC = ({ muted, ...props }) => { +export const MicButton: FC = ({ enabled, ...props }) => { const { t } = useTranslation(); - const Icon = muted ? MicOffSolidIcon : MicOnSolidIcon; - const label = muted - ? t("unmute_microphone_button_label") - : t("mute_microphone_button_label"); + const Icon = enabled ? MicOnSolidIcon : MicOffSolidIcon; + const label = enabled + ? t("mute_microphone_button_label") + : t("unmute_microphone_button_label"); return ( @@ -39,7 +39,7 @@ export const MicButton: FC = ({ muted, ...props }) => { iconOnly aria-label={label} Icon={Icon} - kind={muted ? "primary" : "secondary"} + kind={enabled ? "primary" : "secondary"} {...props} /> @@ -47,16 +47,16 @@ export const MicButton: FC = ({ muted, ...props }) => { }; interface VideoButtonProps extends ComponentPropsWithoutRef<"button"> { - muted: boolean; + enabled: boolean; size?: "sm" | "lg"; } -export const VideoButton: FC = ({ muted, ...props }) => { +export const VideoButton: FC = ({ enabled, ...props }) => { const { t } = useTranslation(); - const Icon = muted ? VideoCallOffSolidIcon : VideoCallSolidIcon; - const label = muted - ? t("start_video_button_label") - : t("stop_video_button_label"); + const Icon = enabled ? VideoCallSolidIcon : VideoCallOffSolidIcon; + const label = enabled + ? t("stop_video_button_label") + : t("start_video_button_label"); return ( @@ -64,7 +64,7 @@ export const VideoButton: FC = ({ muted, ...props }) => { iconOnly aria-label={label} Icon={Icon} - kind={muted ? "primary" : "secondary"} + kind={enabled ? "primary" : "secondary"} {...props} /> diff --git a/src/room/InCallView.tsx b/src/room/InCallView.tsx index f1a872a08..ff221329a 100644 --- a/src/room/InCallView.tsx +++ b/src/room/InCallView.tsx @@ -645,7 +645,7 @@ export const InCallView: FC = ({ = ({ = ({ {recentsButtonInFooter && recentsButton}
diff --git a/src/room/__snapshots__/InCallView.test.tsx.snap b/src/room/__snapshots__/InCallView.test.tsx.snap index e4707c5cd..1188d0ccd 100644 --- a/src/room/__snapshots__/InCallView.test.tsx.snap +++ b/src/room/__snapshots__/InCallView.test.tsx.snap @@ -289,7 +289,7 @@ exports[`InCallView > rendering > renders 1`] = ` aria-label="Unmute microphone" aria-labelledby="_r_8_" class="_button_13vu4_8 _has-icon_13vu4_60 _icon-only_13vu4_53" - data-kind="primary" + data-kind="secondary" data-size="lg" data-testid="incall_mute" role="button" @@ -313,7 +313,7 @@ exports[`InCallView > rendering > renders 1`] = ` aria-label="Start video" aria-labelledby="_r_d_" class="_button_13vu4_8 _has-icon_13vu4_60 _icon-only_13vu4_53" - data-kind="primary" + data-kind="secondary" data-size="lg" data-testid="incall_videomute" role="button" From 4be2bc75609e7155ebc0dc4c1eab02f1a51ffec2 Mon Sep 17 00:00:00 2001 From: Valere Date: Thu, 12 Mar 2026 19:00:09 +0100 Subject: [PATCH 381/748] android: Select default output device based on callIntent Add comments on existing code Extracted a specific android controller for isolation and better testing lint fixes Fix device update logic and more tests better typescript --- src/controls.ts | 63 +- src/main.tsx | 2 +- .../AndroidControlledAudioOutput.test.ts | 563 ++++++++++++++++++ src/state/AndroidControlledAudioOutput.ts | 358 +++++++++++ src/state/MediaDevices.ts | 123 +++- 5 files changed, 1073 insertions(+), 36 deletions(-) create mode 100644 src/state/AndroidControlledAudioOutput.test.ts create mode 100644 src/state/AndroidControlledAudioOutput.ts diff --git a/src/controls.ts b/src/controls.ts index 6a050cb06..86de0ace0 100644 --- a/src/controls.ts +++ b/src/controls.ts @@ -33,12 +33,36 @@ export interface Controls { showNativeOutputDevicePicker?: () => void; } +/** + * Output Audio device when using the controlled audio output mode (mobile). + */ export interface OutputDevice { id: string; name: string; + /** + * Reverse engineered: + * - on iOS always true if output is routed to speaker. In other case iOS on declare a `dummy` id device. + * In that case then ElementCalls manually append a earpiece device with id `EARPIECE_CONFIG_ID` anb `{ type: "earpiece" }` + * - on Android this is unused. + */ forEarpiece?: boolean; + /** + * Reverse engineered: + * - on iOS always undefined + * - on Android true for the `TYPE_BUILTIN_EARPIECE` + */ isEarpiece?: boolean; + /** + * Reverse engineered: + * - on iOS always true if output is routed to speaker. In other case iOS on declare a `dummy` id device. + * - on Android true for the `TYPE_BUILTIN_SPEAKER` + */ isSpeaker?: boolean; + /** + * Reverse engineered: + * - on iOS always undefined. + * - on Android true for the `TYPE_BLUETOOTH_SCO` + */ isExternalHeadset?: boolean; } @@ -47,8 +71,16 @@ export interface OutputDevice { */ export const setPipEnabled$ = new Subject(); +/** + * Stores the list of available controlled audio output devices. + * This is set when the native code calls `setAvailableAudioDevices` with the list of available audio output devices. + */ export const availableOutputDevices$ = new Subject(); +/** + * Stores the current audio output device id. + * This is set when the native code calls `setAudioDevice` + */ export const outputDevice$ = new Subject(); /** @@ -80,16 +112,41 @@ window.controls = { setPipEnabled$.next(false); }, + /** + * Reverse engineered: + * + * - on iOS: + * This always a list of one thing. If current route output is speaker it returns + * the single `{"id":"Speaker","name":"Speaker","forEarpiece":true,"isSpeaker":true}` Notice that EC will + * also manually add a virtual earpiece device with id `EARPIECE_CONFIG_ID` and `{ type: "earpiece" }`. + * If the route output is not speaker then it will be `{id: 'dummy', name: 'dummy'}` + * + * + * - on Android: + * This is a list of all available output audio devices. The `id` is the Android AudioDeviceInfo.getId() + * and the `name` is based the Android AudioDeviceInfo.productName (mapped to static strings for known types) + * The `isEarpiece`, `isSpeaker` and `isExternalHeadset` are set based on the Android AudioDeviceInfo.type + * matching the corresponding types for earpiece, speaker and bluetooth headset. + */ setAvailableAudioDevices(devices: OutputDevice[]): void { - logger.info("setAvailableAudioDevices called from native:", devices); + logger.info( + "[MediaDevices controls] setAvailableAudioDevices called from native:", + devices, + ); availableOutputDevices$.next(devices); }, setAudioDevice(id: string): void { - logger.info("setAudioDevice called from native", id); + logger.info( + "[MediaDevices controls] setAudioDevice called from native", + id, + ); outputDevice$.next(id); }, setAudioEnabled(enabled: boolean): void { - logger.info("setAudioEnabled called from native:", enabled); + logger.info( + "[MediaDevices controls] setAudioEnabled called from native:", + enabled, + ); if (!setAudioEnabled$.observed) throw new Error( "Output controls are disabled. No setAudioEnabled$ observer", diff --git a/src/main.tsx b/src/main.tsx index 946e02389..6cbf75fab 100644 --- a/src/main.tsx +++ b/src/main.tsx @@ -67,6 +67,6 @@ Initializer.initBeforeReact() ); }) .catch((e) => { - logger.error("Failed to initialize app", e); + logger.error(`Failed to initialize app ${e.message}`, e); root.render(e.message); }); diff --git a/src/state/AndroidControlledAudioOutput.test.ts b/src/state/AndroidControlledAudioOutput.test.ts new file mode 100644 index 000000000..12b74052d --- /dev/null +++ b/src/state/AndroidControlledAudioOutput.test.ts @@ -0,0 +1,563 @@ +/* +Copyright 2026 Element Corp. + +SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial +Please see LICENSE in the repository root for full details. +*/ + +import { it, vi, expect, beforeEach, afterEach, describe } from "vitest"; +import { firstValueFrom, of, Subject, take, toArray } from "rxjs"; +import { type RTCCallIntent } from "matrix-js-sdk/lib/matrixrtc"; + +import { AndroidControlledAudioOutput } from "./AndroidControlledAudioOutput.ts"; +import type { Controls, OutputDevice } from "../controls"; +import { ObservableScope } from "./ObservableScope"; +import { withTestScheduler } from "../utils/test"; + +// All the following device types are real device types that have been observed in the wild on Android devices, +// gathered from logs. +// There are no BT Speakers because they are currently filtered out by EXA (native layer) + +// A device type describing the speaker system (i.e. a mono speaker or stereo speakers) built in a device. +const SPEAKER_DEVICE: OutputDevice = { + id: "3", + name: "Built-in speaker", + isEarpiece: false, + isSpeaker: true, + isExternalHeadset: false, +}; + +// A device type describing the attached earphone speaker. +const EARPIECE_DEVICE: OutputDevice = { + id: "2", + name: "Built-in earpiece", + isEarpiece: true, + isSpeaker: false, + isExternalHeadset: false, +}; + +// A device type describing a Bluetooth device typically used for telephony +const BT_HEADSET_DEVICE: OutputDevice = { + id: "2226", + name: "Bluetooth - OpenMove by Shokz", + isEarpiece: false, + isSpeaker: false, + isExternalHeadset: true, +}; + +// A device type describing a USB audio headset. +const USB_HEADSET_DEVICE: OutputDevice = { + id: "29440", + name: "USB headset - USB-Audio - AB13X USB Audio", + isEarpiece: false, + isSpeaker: false, + isExternalHeadset: false, +}; + +// A device type describing a headset, which is the combination of a headphones and microphone +const WIRED_HEADSET_DEVICE: OutputDevice = { + id: "54509", + name: "Wired headset - 23117RA68G", + isEarpiece: false, + isSpeaker: false, + isExternalHeadset: false, +}; + +// A device type describing a pair of wired headphones +const WIRED_HEADPHONE_DEVICE: OutputDevice = { + id: "679", + name: "Wired headphones - TB02", + isEarpiece: false, + isSpeaker: false, + isExternalHeadset: false, +}; + +/** + * The base device list that is always present on Android devices. + * This list is ordered by the OS, the speaker is listed before the earpiece. + */ +const BASE_DEVICE_LIST = [SPEAKER_DEVICE, EARPIECE_DEVICE]; + +const BT_HEADSET_BASE_DEVICE_LIST = [BT_HEADSET_DEVICE, ...BASE_DEVICE_LIST]; + +const WIRED_HEADSET_BASE_DEVICE_LIST = [ + WIRED_HEADSET_DEVICE, + ...BASE_DEVICE_LIST, +]; + +/** + * A full device list containing all the observed device types in the wild on Android devices. + * Ordered as they would be ordered by the OS. + */ +const FULL_DEVICE_LIST = [ + BT_HEADSET_DEVICE, + USB_HEADSET_DEVICE, + WIRED_HEADSET_DEVICE, + WIRED_HEADPHONE_DEVICE, + ...BASE_DEVICE_LIST, +]; + +let testScope: ObservableScope; +let mockControls: Controls; + +beforeEach(() => { + testScope = new ObservableScope(); + mockControls = { + onAudioDeviceSelect: vi.fn(), + onOutputDeviceSelect: vi.fn(), + } as unknown as Controls; +}); + +afterEach(() => { + testScope.end(); +}); + +describe("Default selection", () => { + it("Default to speaker for video calls", async () => { + const controlledAudioOutput = new AndroidControlledAudioOutput( + of(BASE_DEVICE_LIST), + testScope, + "video", + mockControls, + ); + + const emissions = await firstValueFrom( + controlledAudioOutput.selected$.pipe(take(1), toArray()), + ); + + expect(emissions).toEqual([ + { id: SPEAKER_DEVICE.id, virtualEarpiece: false }, + ]); + + [ + mockControls.onAudioDeviceSelect, + mockControls.onOutputDeviceSelect, + ].forEach((mockFn) => { + expect(mockFn).toHaveBeenCalledTimes(1); + expect(mockFn).toHaveBeenCalledWith(SPEAKER_DEVICE.id); + }); + }); + + it("Default to earpiece for audio calls for base config", async () => { + const controlledAudioOutput = new AndroidControlledAudioOutput( + of(BASE_DEVICE_LIST), + testScope, + "audio", + mockControls, + ); + + const emissions = await firstValueFrom( + controlledAudioOutput.selected$.pipe(take(1), toArray()), + ); + + expect(emissions).toEqual([ + { id: EARPIECE_DEVICE.id, virtualEarpiece: false }, + ]); + + [ + mockControls.onAudioDeviceSelect, + mockControls.onOutputDeviceSelect, + ].forEach((mockFn) => { + expect(mockFn).toHaveBeenCalledTimes(1); + expect(mockFn).toHaveBeenCalledWith(EARPIECE_DEVICE.id); + }); + }); + + ["audio", "video"].forEach((callIntent) => { + it(`Default to BT headset for ${callIntent} calls if present`, async () => { + const controlledAudioOutput = new AndroidControlledAudioOutput( + of(BT_HEADSET_BASE_DEVICE_LIST), + testScope, + callIntent, + mockControls, + ); + + const emissions = await firstValueFrom( + controlledAudioOutput.selected$.pipe(take(1), toArray()), + ); + + expect(emissions).toEqual([ + { id: BT_HEADSET_DEVICE.id, virtualEarpiece: false }, + ]); + + [ + mockControls.onAudioDeviceSelect, + mockControls.onOutputDeviceSelect, + ].forEach((mockFn) => { + expect(mockFn).toHaveBeenCalledTimes(1); + expect(mockFn).toHaveBeenCalledWith(BT_HEADSET_DEVICE.id); + }); + }); + }); + + ["audio", "video"].forEach((callIntent) => { + it(`Default to wired headset for ${callIntent} calls if present`, async () => { + const controlledAudioOutput = new AndroidControlledAudioOutput( + of(WIRED_HEADSET_BASE_DEVICE_LIST), + testScope, + callIntent, + mockControls, + ); + + const emissions = await firstValueFrom( + controlledAudioOutput.selected$.pipe(take(1), toArray()), + ); + + expect(emissions).toEqual([ + { id: WIRED_HEADSET_DEVICE.id, virtualEarpiece: false }, + ]); + + expect(mockControls.onAudioDeviceSelect).toHaveBeenCalledExactlyOnceWith( + WIRED_HEADSET_DEVICE.id, + ); + expect(mockControls.onOutputDeviceSelect).toHaveBeenCalledExactlyOnceWith( + WIRED_HEADSET_DEVICE.id, + ); + }); + }); +}); + +describe("Test mappings", () => { + it("Should map output device to correct AudioDeviceLabel", async () => { + const controlledAudioOutput = new AndroidControlledAudioOutput( + of(FULL_DEVICE_LIST), + testScope, + undefined, + mockControls, + ); + + const availableDevices = await firstValueFrom( + controlledAudioOutput.available$.pipe(take(1)), + ); + + expect(availableDevices).toEqual( + new Map([ + [BT_HEADSET_DEVICE.id, { type: "name", name: BT_HEADSET_DEVICE.name }], + [ + USB_HEADSET_DEVICE.id, + { type: "name", name: USB_HEADSET_DEVICE.name }, + ], + [ + WIRED_HEADSET_DEVICE.id, + { type: "name", name: WIRED_HEADSET_DEVICE.name }, + ], + [ + WIRED_HEADPHONE_DEVICE.id, + { type: "name", name: WIRED_HEADPHONE_DEVICE.name }, + ], + [SPEAKER_DEVICE.id, { type: "speaker" }], + [EARPIECE_DEVICE.id, { type: "earpiece" }], + ]), + ); + }); +}); + +describe("Test select a device", () => { + it(`Switch to correct device `, () => { + withTestScheduler(({ cold, schedule, expectObservable, flush }) => { + const controlledAudioOutput = new AndroidControlledAudioOutput( + cold("a", { a: FULL_DEVICE_LIST }), + testScope, + undefined, + mockControls, + ); + + schedule("-abc", { + a: () => controlledAudioOutput.select(EARPIECE_DEVICE.id), + b: () => controlledAudioOutput.select(USB_HEADSET_DEVICE.id), + c: () => controlledAudioOutput.select(SPEAKER_DEVICE.id), + }); + + expectObservable(controlledAudioOutput.selected$).toBe("abcd", { + // virtualEarpiece is always false on android. + // Initially the BT_HEADSET is selected. + a: { id: BT_HEADSET_DEVICE.id, virtualEarpiece: false }, + b: { id: EARPIECE_DEVICE.id, virtualEarpiece: false }, + c: { id: USB_HEADSET_DEVICE.id, virtualEarpiece: false }, + d: { id: SPEAKER_DEVICE.id, virtualEarpiece: false }, + }); + + flush(); + + [ + mockControls.onOutputDeviceSelect, + mockControls.onAudioDeviceSelect, + ].forEach((mockFn) => { + expect(mockFn).toHaveBeenCalledTimes(4); + expect(mockFn).toHaveBeenNthCalledWith(1, BT_HEADSET_DEVICE.id); + expect(mockFn).toHaveBeenNthCalledWith(2, EARPIECE_DEVICE.id); + expect(mockFn).toHaveBeenNthCalledWith(3, USB_HEADSET_DEVICE.id); + expect(mockFn).toHaveBeenNthCalledWith(4, SPEAKER_DEVICE.id); + }); + }); + }); + + it(`manually switch then a bt headset is added`, () => { + withTestScheduler(({ cold, schedule, expectObservable, flush }) => { + const controlledAudioOutput = new AndroidControlledAudioOutput( + cold("a--b", { + a: BASE_DEVICE_LIST, + b: BT_HEADSET_BASE_DEVICE_LIST, + }), + testScope, + "audio", + mockControls, + ); + + // Default was earpiece (audio call), let's switch to speaker + schedule("-a--", { + a: () => controlledAudioOutput.select(SPEAKER_DEVICE.id), + }); + + expectObservable(controlledAudioOutput.selected$).toBe("ab-c", { + // virtualEarpiece is always false on android. + // Initially the BT_HEADSET is selected. + a: { id: EARPIECE_DEVICE.id, virtualEarpiece: false }, + b: { id: SPEAKER_DEVICE.id, virtualEarpiece: false }, + c: { id: BT_HEADSET_DEVICE.id, virtualEarpiece: false }, + }); + + flush(); + + [ + mockControls.onOutputDeviceSelect, + mockControls.onAudioDeviceSelect, + ].forEach((mockFn) => { + expect(mockFn).toHaveBeenCalledTimes(3); + expect(mockFn).toHaveBeenNthCalledWith(1, EARPIECE_DEVICE.id); + expect(mockFn).toHaveBeenNthCalledWith(2, SPEAKER_DEVICE.id); + expect(mockFn).toHaveBeenNthCalledWith(3, BT_HEADSET_DEVICE.id); + }); + }); + }); + + it(`Go back to the previously selected after the auto-switch device goes away`, () => { + withTestScheduler(({ cold, schedule, expectObservable, flush }) => { + const controlledAudioOutput = new AndroidControlledAudioOutput( + cold("a--b-c", { + a: BASE_DEVICE_LIST, + b: BT_HEADSET_BASE_DEVICE_LIST, + c: BASE_DEVICE_LIST, + }), + testScope, + "audio", + mockControls, + ); + + // Default was earpiece (audio call), let's switch to speaker + schedule("-a---", { + a: () => controlledAudioOutput.select(SPEAKER_DEVICE.id), + }); + + expectObservable(controlledAudioOutput.selected$).toBe("ab-c-d", { + // virtualEarpiece is always false on android. + // Initially the BT_HEADSET is selected. + a: { id: EARPIECE_DEVICE.id, virtualEarpiece: false }, + b: { id: SPEAKER_DEVICE.id, virtualEarpiece: false }, + c: { id: BT_HEADSET_DEVICE.id, virtualEarpiece: false }, + d: { id: SPEAKER_DEVICE.id, virtualEarpiece: false }, + }); + + flush(); + + [ + mockControls.onOutputDeviceSelect, + mockControls.onAudioDeviceSelect, + ].forEach((mockFn) => { + expect(mockFn).toHaveBeenCalledTimes(4); + expect(mockFn).toHaveBeenNthCalledWith(1, EARPIECE_DEVICE.id); + expect(mockFn).toHaveBeenNthCalledWith(2, SPEAKER_DEVICE.id); + expect(mockFn).toHaveBeenNthCalledWith(3, BT_HEADSET_DEVICE.id); + expect(mockFn).toHaveBeenNthCalledWith(4, SPEAKER_DEVICE.id); + }); + }); + }); +}); + +describe("Available device changes", () => { + let availableSource$: Subject; + + const createAudioControlledOutput = ( + intent: RTCCallIntent, + ): AndroidControlledAudioOutput => { + return new AndroidControlledAudioOutput( + availableSource$, + testScope, + intent, + mockControls, + ); + }; + + beforeEach(() => { + availableSource$ = new Subject(); + }); + + it("When a BT headset is added, control should switch to use it", () => { + createAudioControlledOutput("video"); + + // Emit the base device list, the speaker should be selected + availableSource$.next(BASE_DEVICE_LIST); + // Initially speaker would be selected + [ + mockControls.onOutputDeviceSelect, + mockControls.onAudioDeviceSelect, + ].forEach((mockFn) => { + expect(mockFn).toHaveBeenCalledTimes(1); + expect(mockFn).toHaveBeenCalledWith(SPEAKER_DEVICE.id); + }); + + // Emit a new device list with a BT device, the control should switch to it + availableSource$.next([BT_HEADSET_DEVICE, ...BASE_DEVICE_LIST]); + [ + mockControls.onOutputDeviceSelect, + mockControls.onAudioDeviceSelect, + ].forEach((mockFn) => { + expect(mockFn).toHaveBeenCalledTimes(2); + expect(mockFn).toHaveBeenLastCalledWith(BT_HEADSET_DEVICE.id); + }); + }); + + // Android does not set `isExternalHeadset` to true for wired headphones, so we can't test this case.' + it.skip("When a wired headset is added, control should switch to use it", async () => { + const controlledAudioOutput = createAudioControlledOutput("video"); + + // Emit the base device list, the speaker should be selected + availableSource$.next(BASE_DEVICE_LIST); + + await firstValueFrom(controlledAudioOutput.selected$.pipe(take(1))); + // Initially speaker would be selected + [ + mockControls.onOutputDeviceSelect, + mockControls.onAudioDeviceSelect, + ].forEach((mockFn) => { + expect(mockFn).toHaveBeenCalledTimes(1); + expect(mockFn).toHaveBeenCalledWith(SPEAKER_DEVICE.id); + }); + + // Emit a new device list with a wired headset, the control should switch to it + availableSource$.next([WIRED_HEADPHONE_DEVICE, ...BASE_DEVICE_LIST]); + [ + mockControls.onOutputDeviceSelect, + mockControls.onAudioDeviceSelect, + ].forEach((mockFn) => { + expect(mockFn).toHaveBeenCalledTimes(2); + expect(mockFn).toHaveBeenLastCalledWith(WIRED_HEADPHONE_DEVICE.id); + }); + }); + + it("When the active bt headset is removed on audio call, control should switch to earpiece", () => { + createAudioControlledOutput("audio"); + + // Emit the BT headset device list, the BT headset should be selected + availableSource$.next(BT_HEADSET_BASE_DEVICE_LIST); + // Initially speaker would be selected + [ + mockControls.onOutputDeviceSelect, + mockControls.onAudioDeviceSelect, + ].forEach((mockFn) => { + expect(mockFn).toHaveBeenCalledTimes(1); + expect(mockFn).toHaveBeenCalledWith(BT_HEADSET_DEVICE.id); + }); + + // Emit a new device list without the BT headset, the control should switch to the earpiece for + // audio calls + availableSource$.next(BASE_DEVICE_LIST); + [ + mockControls.onOutputDeviceSelect, + mockControls.onAudioDeviceSelect, + ].forEach((mockFn) => { + expect(mockFn).toHaveBeenCalledTimes(2); + expect(mockFn).toHaveBeenLastCalledWith(EARPIECE_DEVICE.id); + }); + }); + + it("When the active bt headset is removed on video call, control should switch to speaker", () => { + createAudioControlledOutput("video"); + + availableSource$.next(BT_HEADSET_BASE_DEVICE_LIST); + + // Initially bt headset would be selected + [ + mockControls.onOutputDeviceSelect, + mockControls.onAudioDeviceSelect, + ].forEach((mockFn) => { + expect(mockFn).toHaveBeenCalledTimes(1); + expect(mockFn).toHaveBeenCalledWith(BT_HEADSET_DEVICE.id); + }); + + // Emit a new device list without the BT headset, the control should switch to speaker for video call + availableSource$.next(BASE_DEVICE_LIST); + [ + mockControls.onOutputDeviceSelect, + mockControls.onAudioDeviceSelect, + ].forEach((mockFn) => { + expect(mockFn).toHaveBeenCalledTimes(2); + expect(mockFn).toHaveBeenLastCalledWith(SPEAKER_DEVICE.id); + }); + }); + + it("Do not repeatidly set the same device", () => { + createAudioControlledOutput("video"); + + availableSource$.next(BT_HEADSET_BASE_DEVICE_LIST); + availableSource$.next(BT_HEADSET_BASE_DEVICE_LIST); + availableSource$.next(BT_HEADSET_BASE_DEVICE_LIST); + availableSource$.next(BT_HEADSET_BASE_DEVICE_LIST); + availableSource$.next(BT_HEADSET_BASE_DEVICE_LIST); + + // Initially bt headset would be selected + [ + mockControls.onOutputDeviceSelect, + mockControls.onAudioDeviceSelect, + ].forEach((mockFn) => { + expect(mockFn).toHaveBeenCalledTimes(1); + expect(mockFn).toHaveBeenCalledWith(BT_HEADSET_DEVICE.id); + }); + }); +}); + +describe("Scope management", () => { + it("Should stop emitting when scope ends", () => { + const aScope = new ObservableScope(); + const controlledAudioOutput = new AndroidControlledAudioOutput( + of(BASE_DEVICE_LIST), + aScope, + undefined, + mockControls, + ); + + expect(mockControls.onAudioDeviceSelect).toHaveBeenCalledOnce(); + + aScope.end(); + + controlledAudioOutput.select(EARPIECE_DEVICE.id); + + expect(mockControls.onAudioDeviceSelect).not.toHaveBeenCalledTimes(2); + expect(mockControls.onAudioDeviceSelect).toHaveBeenCalledOnce(); + }); + + it("Should stop updating when scope ends", () => { + const aScope = new ObservableScope(); + const availableSource$ = new Subject(); + new AndroidControlledAudioOutput( + availableSource$, + aScope, + undefined, + mockControls, + ); + + availableSource$.next(BT_HEADSET_BASE_DEVICE_LIST); + expect(mockControls.onAudioDeviceSelect).toHaveBeenCalledOnce(); + expect(mockControls.onAudioDeviceSelect).toHaveBeenCalledWith( + BT_HEADSET_DEVICE.id, + ); + + aScope.end(); + + availableSource$.next(BASE_DEVICE_LIST); + + expect(mockControls.onAudioDeviceSelect).not.toHaveBeenCalledTimes(2); + // Should have been called only once with the initial BT_HEADSET_DEVICE.id + expect(mockControls.onAudioDeviceSelect).toHaveBeenCalledOnce(); + }); +}); diff --git a/src/state/AndroidControlledAudioOutput.ts b/src/state/AndroidControlledAudioOutput.ts new file mode 100644 index 000000000..ce4974ff1 --- /dev/null +++ b/src/state/AndroidControlledAudioOutput.ts @@ -0,0 +1,358 @@ +/* +Copyright 2026 Element Corp. + +SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial +Please see LICENSE in the repository root for full details. +*/ +import { logger as rootLogger } from "matrix-js-sdk/lib/logger"; +import { + distinctUntilChanged, + map, + merge, + type Observable, + scan, + startWith, + Subject, + tap, +} from "rxjs"; + +import { + type AudioOutputDeviceLabel, + type MediaDevice, + type SelectedAudioOutputDevice, +} from "./MediaDevices.ts"; +import type { ObservableScope } from "./ObservableScope.ts"; +import type { RTCCallIntent } from "matrix-js-sdk/lib/matrixrtc"; +import { type Controls, type OutputDevice } from "../controls.ts"; +import { type Behavior } from "./Behavior.ts"; + +type ControllerState = { + /** + * The list of available output devices, ordered by preference order (most preferred first). + */ + devices: OutputDevice[]; + /** + * Explicit user preference for the selected device. + */ + preferredDeviceId: string | undefined; + /** + * The effective selected device, always valid against available devices. + */ + selectedDeviceId: string | undefined; +}; + +/** + * The possible actions that can be performed on the controller, + * either by the user or by the system. + */ +type ControllerAction = + | { type: "selectDevice"; deviceId: string | undefined } + | { type: "deviceUpdated"; devices: OutputDevice[] }; +/** + * The implementation of the audio output media device for Android when using the controlled audio output mode. + * + * In this mode, the hosting application (e.g. Element Mobile) is responsible for providing the list of available audio output devices. + * There are some android specific logic compared to others: + * - AndroidControlledAudioOutput is the only one responsible for selecting the best output device. + * - On android, we don't listen to the selected device from native code (control.setAudioDevice). + * - If a new device is added or removed, this controller will determine the new selected device based + * on the available devices (that is ordered by preference order) and the user's selection (if any). + * + * Given the differences in how the native code is handling the audio routing on Android compared to iOS, + * we have this separate implementation. It allows us to have proper testing and avoid side effects + * from platform specific logic breaking the other platform's implementation. + */ +export class AndroidControlledAudioOutput implements MediaDevice< + AudioOutputDeviceLabel, + SelectedAudioOutputDevice +> { + private logger = rootLogger.getChild( + "[MediaDevices AndroidControlledAudioOutput]", + ); + + // STATE stream: the current state of the controller, including the list of available devices and the selected device. + private readonly controllerState$: Behavior; + + /** + * @inheritdoc + */ + public readonly available$: Behavior>; + + /** + * Effective selected device, always valid against available devices. + * + * On android, we don't listen to the selected device from native code (control.setAudioDevice). + * Instead, we determine the selected device ourselves based on the available devices and the user's selection (if any). + */ + public readonly selected$: Behavior; + + // COMMAND stream: user asks to select a device + private readonly selectDeviceCommand$ = new Subject(); + + public select(id: string): void { + this.logger.info(`select device: ${id}`); + this.selectDeviceCommand$.next(id); + } + + /** + * Creates an instance of AndroidControlledAudioOutput. + * + * @constructor + * @param controlledDevices$ - The list of available output devices coming from the hosting application, ordered by preference order (most preferred first). + * @param scope - The ObservableScope to create the Behaviors in. + * @param initialIntent - The initial call intent (e.g. "audio" or "video") that can be used to determine the default audio routing (e.g. default to earpiece for audio calls and speaker for video calls). + * @param controls - The controls provided by the hosting application to control the audio routing and notify of user actions. + */ + public constructor( + private readonly controlledDevices$: Observable, + private readonly scope: ObservableScope, + private initialIntent: RTCCallIntent | undefined = undefined, + controls: Controls, + ) { + this.controllerState$ = this.startObservingState$(); + + this.selected$ = this.effectiveSelectionFromState$(this.controllerState$); + + this.available$ = scope.behavior( + this.controllerState$.pipe( + map((state) => { + this.logger.info("available devices updated:", state.devices); + + return new Map( + state.devices.map((outputDevice) => { + return [outputDevice.id, mapDeviceToLabel(outputDevice)]; + }), + ); + }), + ), + ); + + // Effect 1: notify host when effective selection changes + this.selected$ + // It is a behavior so it has built-in distinct until change + .pipe(scope.bind()) + .subscribe((device) => { + // Let the hosting application know which output device has been selected. + if (device !== undefined) { + this.logger.info("onAudioDeviceSelect called:", device); + controls.onAudioDeviceSelect?.(device.id); + // Also invoke the deprecated callback for backward compatibility + // TODO: it appears that on Android the hosting application is only using the deprecated callback (onOutputDeviceSelect) + // and not the new one (onAudioDeviceSelect), we should clean this up and only have one callback for audio device selection. + controls.onOutputDeviceSelect?.(device.id); + } + }); + } + + private startObservingState$(): Behavior { + const initialState: ControllerState = { + devices: [], + preferredDeviceId: undefined, + selectedDeviceId: undefined, + }; + + // Merge the two possible inputs observable as a single + // stream of actions that will update the state of the controller. + const actions$: Observable = merge( + this.controlledDevices$.pipe( + map( + (devices) => + ({ type: "deviceUpdated", devices }) satisfies ControllerAction, + ), + ), + this.selectDeviceCommand$.pipe( + map( + (deviceId) => + ({ type: "selectDevice", deviceId }) satisfies ControllerAction, + ), + ), + ); + + const initialAction: ControllerAction = { + type: "deviceUpdated", + devices: [], + }; + + return this.scope.behavior( + actions$.pipe( + startWith(initialAction), + scan((state, action): ControllerState => { + switch (action.type) { + case "deviceUpdated": { + const chosenDevice = this.chooseEffectiveSelection({ + previousDevices: state.devices, + availableDevices: action.devices, + currentSelectedId: state.selectedDeviceId, + preferredDeviceId: state.preferredDeviceId, + }); + + return { + ...state, + devices: action.devices, + selectedDeviceId: chosenDevice, + }; + } + case "selectDevice": { + const chosenDevice = this.chooseEffectiveSelection({ + previousDevices: state.devices, + availableDevices: state.devices, + currentSelectedId: state.selectedDeviceId, + preferredDeviceId: action.deviceId, + }); + + return { + ...state, + preferredDeviceId: action.deviceId, + selectedDeviceId: chosenDevice, + }; + } + } + }, initialState), + ), + ); + } + + private effectiveSelectionFromState$( + state$: Observable, + ): Behavior { + return this.scope.behavior( + state$ + .pipe( + map((state) => { + if (state.selectedDeviceId) { + return { + id: state.selectedDeviceId, + /** This is an iOS thing, always false for android*/ + virtualEarpiece: false, + }; + } + return undefined; + }), + distinctUntilChanged((a, b) => a?.id === b?.id), + ) + .pipe( + tap((selected) => { + this.logger.debug(`selected device: ${selected?.id}`); + }), + ), + ); + } + + private chooseEffectiveSelection(args: { + previousDevices: OutputDevice[]; + availableDevices: OutputDevice[]; + currentSelectedId: string | undefined; + preferredDeviceId: string | undefined; + }): string | undefined { + const { + previousDevices, + availableDevices, + currentSelectedId, + preferredDeviceId, + } = args; + + this.logger.debug(`chooseEffectiveSelection with args:`, args); + + // Take preferredDeviceId in priority or default to the last effective selection. + const activeSelectedDeviceId = preferredDeviceId || currentSelectedId; + const isAvailable = availableDevices.some( + (device) => device.id === activeSelectedDeviceId, + ); + + // If there is no current device, or it is not available anymore, + // choose the default device selection logic. + if (activeSelectedDeviceId === undefined || !isAvailable) { + this.logger.debug( + `No current device or it is not available, using default selection logic.`, + ); + // use the default selection logic + return this.chooseDefaultDeviceId(availableDevices); + } + + // Is there a new added device? + // If a device is added, we might want to switch to it if it's more preferred than the currently selected device. + const newDeviceWasAdded = availableDevices.some( + (device) => !previousDevices.some((d) => d.id === device.id), + ); + + if (newDeviceWasAdded) { + // TODO only want to check from the added device, not all devices.? + // check if the currently selected device is the most preferred one, if not switch to the most preferred one. + const mostPreferredDevice = availableDevices[0]; + this.logger.debug( + `A new device was added, checking if we should switch to it.`, + mostPreferredDevice, + ); + if (mostPreferredDevice.id !== activeSelectedDeviceId) { + // Given this is automatic switching, we want to be careful and only switch to a more private device + // (e.g. from speaker to a BT headset) but not switch from a more private device to a less private one + // (e.g. from a BT headset to the speaker), as that can be disruptive for the user if it happens unexpectedly. + if (mostPreferredDevice.isExternalHeadset == true) { + this.logger.info( + `The currently selected device ${mostPreferredDevice.id} is not the most preferred one, switching to the most preferred one ${activeSelectedDeviceId} instead.`, + ); + // Let's switch as it is a more private device. + return mostPreferredDevice.id; + } + } + } + + // no changes + return activeSelectedDeviceId; + } + + /** + * The logic for the default is different based on the call type. + * For example for a voice call we want to default to the earpiece if it's available, + * but for a video call we want to default to the speaker. + * If the user is using a BT headset we want to default to that, as it's likely what they want to use for both video and voice calls. + * + * @param available the available audio output devices to choose from, keyed by their id, sorted by likelihood of it being used for communication. + * + */ + private chooseDefaultDeviceId(available: OutputDevice[]): string | undefined { + this.logger.debug( + `Android routing logic intent: ${this.initialIntent} finding best default...`, + ); + if (this.initialIntent === "audio") { + const systemProposed = available[0]; + // If no headset is connected, android will route to the speaker by default, + // but for a voice call we want to route to the earpiece instead, + // so override the system proposed routing in that case. + if (systemProposed?.isSpeaker == true) { + // search for the earpiece + const earpieceDevice = available.find( + (device) => device.isEarpiece == true, + ); + if (earpieceDevice) { + this.logger.debug( + `Android routing: Switch to earpiece instead of speaker for voice call`, + ); + return earpieceDevice.id; + } else { + this.logger.debug( + `Android routing: no earpiece found, cannot switch, use system proposed routing`, + ); + return systemProposed.id; + } + } else { + this.logger.debug( + `Android routing: Use system proposed routing `, + systemProposed, + ); + return systemProposed?.id; + } + } else { + // Use the system best proposed best routing. + return available[0]?.id; + } + } +} + +// Utilities +function mapDeviceToLabel(device: OutputDevice): AudioOutputDeviceLabel { + const { name, isEarpiece, isSpeaker } = device; + if (isEarpiece) return { type: "earpiece" }; + else if (isSpeaker) return { type: "speaker" }; + else return { type: "name", name }; +} diff --git a/src/state/MediaDevices.ts b/src/state/MediaDevices.ts index cea975198..cf578fb43 100644 --- a/src/state/MediaDevices.ts +++ b/src/state/MediaDevices.ts @@ -15,6 +15,7 @@ import { Subject, switchMap, type Observable, + tap, } from "rxjs"; import { createMediaDeviceObserver } from "@livekit/components-core"; import { type Logger, logger as rootLogger } from "matrix-js-sdk/lib/logger"; @@ -34,6 +35,7 @@ import { getUrlParams } from "../UrlParams"; import { platform } from "../Platform"; import { switchWhen } from "../utils/observable"; import { type Behavior, constant } from "./Behavior"; +import { AndroidControlledAudioOutput } from "./AndroidControlledAudioOutput.ts"; // This hardcoded id is used in EX ios! It can only be changed in coordination with // the ios swift team. @@ -49,10 +51,18 @@ export type AudioOutputDeviceLabel = | { type: "earpiece" } | { type: "default"; name: string | null }; +/** + * Base selected-device value shared by all media kinds. + * + * `id` is the effective device identifier used by browser media APIs. + */ export interface SelectedDevice { id: string; } +/** + * Selected audio input value with audio-input-specific metadata. + */ export interface SelectedAudioInputDevice extends SelectedDevice { /** * Emits whenever we think that this audio input device has logically changed @@ -61,6 +71,9 @@ export interface SelectedAudioInputDevice extends SelectedDevice { hardwareDeviceChange$: Observable; } +/** + * Selected audio output value with output-routing-specific metadata. + */ export interface SelectedAudioOutputDevice extends SelectedDevice { /** * Whether this device is a "virtual earpiece" device. If so, we should output @@ -69,23 +82,42 @@ export interface SelectedAudioOutputDevice extends SelectedDevice { virtualEarpiece: boolean; } +/** + * Common reactive contract for selectable input/output media devices (mic, speaker, camera). + * + * `Label` is the type used to represent a device in UI lists. + * `Selected` is the type used to represent the active selection for a device kind. + */ export interface MediaDevice { /** - * A map from available device IDs to labels. + * Reactive map of currently available devices keyed by device ID. + * + * `Label` defines the UI-facing label data structure for each device type. */ available$: Behavior>; + /** - * The selected device. + * The active device selection. + * Can be `undefined` when no device is yet selected. + * + * When defined, `Selected` contains the selected device ID plus any + * type-specific metadata. */ selected$: Behavior; + /** - * Selects a new device. + * Requests selection of a device by ID. + * + * Implementations typically persist this preference and let `selected$` + * converge to the effective device (which may differ if the requested ID is + * unavailable). */ select(id: string): void; } /** * An observable that represents if we should display the devices menu for iOS. + * * This implies the following * - hide any input devices (they do not work anyhow on ios) * - Show a button to show the native output picker instead. @@ -143,19 +175,29 @@ function buildDeviceMap( function selectDevice$

renders and matches snapshot 1`] = ` class="_inline-field-control_19upo_44" >
renders and matches snapshot 1`] = ` value="legacy" />
@@ -275,11 +275,11 @@ exports[`DeveloperSettingsTab > renders and matches snapshot 1`] = ` class="_inline-field-control_19upo_44" >
renders and matches snapshot 1`] = ` value="compatibility" />
@@ -315,11 +315,11 @@ exports[`DeveloperSettingsTab > renders and matches snapshot 1`] = ` class="_inline-field-control_19upo_44" >
renders and matches snapshot 1`] = ` value="matrix_2_0" />
From c60ed50a9ddcde1eec6090a3c29cb57a454a7d61 Mon Sep 17 00:00:00 2001 From: Robin Date: Tue, 24 Mar 2026 17:04:28 +0100 Subject: [PATCH 387/748] Attempt to fix end-to-end widget tests --- playwright/widget/test-helpers.ts | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/playwright/widget/test-helpers.ts b/playwright/widget/test-helpers.ts index 4562ba5a1..5cdd55067 100644 --- a/playwright/widget/test-helpers.ts +++ b/playwright/widget/test-helpers.ts @@ -152,6 +152,22 @@ export class TestHelpers { } } + private static async maybeDismissKeyBackupToast(page: Page): Promise { + const toast = page + .locator(".mx_Toast_toast") + .getByText("Back up your chats"); + + try { + await expect(toast).toBeVisible({ timeout: 700 }); + await page + .locator(".mx_Toast_toast") + .getByRole("button", { name: "Dismiss" }) + .click(); + } catch { + // toast not visible, continue as normal + } + } + public static async createRoom( name: string, page: Page, @@ -167,6 +183,7 @@ export class TestHelpers { await page.getByRole("button", { name: "Create room" }).click(); await expect(page.getByText("You created this room.")).toBeVisible(); await expect(page.getByText("Encryption enabled")).toBeVisible(); + await TestHelpers.maybeDismissKeyBackupToast(page); // Invite users if any if (andInvite.length > 0) { @@ -201,6 +218,7 @@ export class TestHelpers { await expect( page.getByRole("main").getByRole("heading", { name: roomName }), ).toBeVisible(); + await TestHelpers.maybeDismissKeyBackupToast(page); } /** From 4f518819d387283f99b77a2af9b914532d019029 Mon Sep 17 00:00:00 2001 From: Valere Date: Tue, 24 Mar 2026 18:02:27 +0100 Subject: [PATCH 388/748] review: extract ControlledAudioOutput in its own file --- src/state/ControlledAudioOutput.ts | 132 +++++++++++++++++++++++++++++ src/state/MediaDevices.ts | 129 ++-------------------------- 2 files changed, 138 insertions(+), 123 deletions(-) create mode 100644 src/state/ControlledAudioOutput.ts diff --git a/src/state/ControlledAudioOutput.ts b/src/state/ControlledAudioOutput.ts new file mode 100644 index 000000000..a3fe9387e --- /dev/null +++ b/src/state/ControlledAudioOutput.ts @@ -0,0 +1,132 @@ +/* +Copyright 2026 Element Corp. + +SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial +Please see LICENSE in the repository root for full details. +*/ + +import { logger as rootLogger } from "matrix-js-sdk/lib/logger"; +import { combineLatest, merge, startWith, Subject, tap } from "rxjs"; + +import { + availableOutputDevices$ as controlledAvailableOutputDevices$, + outputDevice$ as controlledOutputSelection$, +} from "../controls.ts"; +import type { Behavior } from "./Behavior.ts"; +import type { ObservableScope } from "./ObservableScope.ts"; +import { + type AudioOutputDeviceLabel, + availableRawDevices$, + iosDeviceMenu$, + type MediaDevice, + type SelectedAudioOutputDevice, +} from "./MediaDevices.ts"; + +// This hardcoded id is used in EX ios! It can only be changed in coordination with +// the ios swift team. +const EARPIECE_CONFIG_ID = "earpiece-id"; + +/** + * A special implementation of audio output that allows the hosting application + * to have more control over the device selection process. This is used when the + * `controlledAudioDevices` URL parameter is set, which is currently only true on mobile. + */ +export class ControlledAudioOutput implements MediaDevice< + AudioOutputDeviceLabel, + SelectedAudioOutputDevice +> { + private logger = rootLogger.getChild("[MediaDevices ControlledAudioOutput]"); + // We need to subscribe to the raw devices so that the OS does update the input + // back to what it was before. otherwise we will switch back to the default + // whenever we allocate a new stream. + public readonly availableRaw$ = availableRawDevices$( + "audiooutput", + this.usingNames$, + this.scope, + this.logger, + ); + + public readonly available$ = this.scope.behavior( + combineLatest( + [controlledAvailableOutputDevices$.pipe(startWith([])), iosDeviceMenu$], + (availableRaw, iosDeviceMenu) => { + const available = new Map( + availableRaw.map( + ({ id, name, isEarpiece, isSpeaker /*,isExternalHeadset*/ }) => { + let deviceLabel: AudioOutputDeviceLabel; + // if (isExternalHeadset) // Do we want this? + if (isEarpiece) deviceLabel = { type: "earpiece" }; + else if (isSpeaker) deviceLabel = { type: "speaker" }; + else deviceLabel = { type: "name", name }; + return [id, deviceLabel]; + }, + ), + ); + + // Create a virtual earpiece device in case a non-earpiece device is + // designated for this purpose + if (iosDeviceMenu && availableRaw.some((d) => d.forEarpiece)) { + this.logger.info( + `IOS Add virtual earpiece device with id ${EARPIECE_CONFIG_ID}`, + ); + available.set(EARPIECE_CONFIG_ID, { type: "earpiece" }); + } + + return available; + }, + ), + ); + + private readonly deviceSelection$ = new Subject(); + + public select(id: string): void { + this.logger.info(`select device: ${id}`); + this.deviceSelection$.next(id); + } + + public readonly selected$ = this.scope.behavior( + combineLatest( + [ + this.available$, + merge( + controlledOutputSelection$.pipe(startWith(undefined)), + this.deviceSelection$, + ), + ], + (available, preferredId) => { + const id = preferredId ?? available.keys().next().value; + return id === undefined + ? undefined + : { id, virtualEarpiece: id === EARPIECE_CONFIG_ID }; + }, + ).pipe( + tap((selected) => { + this.logger.debug(`selected device: ${selected?.id}`); + }), + ), + ); + + public constructor( + private readonly usingNames$: Behavior, + private readonly scope: ObservableScope, + ) { + this.selected$.subscribe((device) => { + // Let the hosting application know which output device has been selected. + // This information is probably only of interest if the earpiece mode has + // been selected - for example, Element X iOS listens to this to determine + // whether it should enable the proximity sensor. + if (device !== undefined) { + this.logger.info("onAudioDeviceSelect called:", device); + window.controls.onAudioDeviceSelect?.(device.id); + // Also invoke the deprecated callback for backward compatibility + window.controls.onOutputDeviceSelect?.(device.id); + } + }); + this.available$.subscribe((available) => { + this.logger.debug("available devices:", available); + }); + this.availableRaw$.subscribe((availableRaw) => { + this.logger.debug("available raw devices:", availableRaw); + }); + } +} diff --git a/src/state/MediaDevices.ts b/src/state/MediaDevices.ts index 052f55e6c..d74002b5e 100644 --- a/src/state/MediaDevices.ts +++ b/src/state/MediaDevices.ts @@ -9,37 +9,28 @@ import { combineLatest, filter, map, - merge, + type Observable, pairwise, - startWith, Subject, switchMap, - type Observable, - tap, } from "rxjs"; import { createMediaDeviceObserver } from "@livekit/components-core"; import { type Logger, logger as rootLogger } from "matrix-js-sdk/lib/logger"; import { + alwaysShowIphoneEarpiece as alwaysShowIphoneEarpieceSetting, audioInput as audioInputSetting, audioOutput as audioOutputSetting, videoInput as videoInputSetting, - alwaysShowIphoneEarpiece as alwaysShowIphoneEarpieceSetting, } from "../settings/settings"; import { type ObservableScope } from "./ObservableScope"; -import { - outputDevice$ as controlledOutputSelection$, - availableOutputDevices$ as controlledAvailableOutputDevices$, -} from "../controls"; +import { availableOutputDevices$ as controlledAvailableOutputDevices$ } from "../controls"; import { getUrlParams } from "../UrlParams"; import { platform } from "../Platform"; import { switchWhen } from "../utils/observable"; import { type Behavior, constant } from "./Behavior"; import { AndroidControlledAudioOutput } from "./AndroidControlledAudioOutput.ts"; - -// This hardcoded id is used in EX ios! It can only be changed in coordination with -// the ios swift team. -const EARPIECE_CONFIG_ID = "earpiece-id"; +import { ControlledAudioOutput } from "./ControlledAudioOutput.ts"; export type DeviceLabel = | { type: "name"; name: string } @@ -127,7 +118,7 @@ export interface MediaDevice { export const iosDeviceMenu$ = platform === "ios" ? constant(true) : alwaysShowIphoneEarpieceSetting.value$; -function availableRawDevices$( +export function availableRawDevices$( kind: MediaDeviceKind, usingNames$: Behavior, scope: ObservableScope, @@ -175,9 +166,6 @@ function buildDeviceMap( function selectDevice$

rendering > renders 1`] = ` class="footer" >
rendering > renders 1`] = ` - +
{children} diff --git a/src/button/Button.tsx b/src/button/Button.tsx index a3cb39101..313353705 100644 --- a/src/button/Button.tsx +++ b/src/button/Button.tsx @@ -160,26 +160,33 @@ export const LoudspeakerButton: FC = (props) => { interface SettingsButtonProps extends ComponentPropsWithoutRef<"button"> { size?: "sm" | "lg"; - /** If the button should be styled so it fits into the footer center buttons group - * This implies the button will be hidden unless we are on very small screens. - */ + /** If the button should be styled so it fits into the footer center buttons group */ forButtonsBar?: boolean; + /** If this buttons should be setup to be used in the app bar */ + showForScreenWidth?: "wide" | "narrow"; } -export const SettingsButton: FC = (props) => { +export const SettingsButton: FC = ({ + showForScreenWidth, + forButtonsBar, + className, + ...props +}) => { const { t } = useTranslation(); return ( diff --git a/src/components/InCallFooter.module.css b/src/components/InCallFooter.module.css index 9db32db37..da96af5f1 100644 --- a/src/components/InCallFooter.module.css +++ b/src/components/InCallFooter.module.css @@ -78,17 +78,10 @@ Please see LICENSE in the repository root for full details. } } -.settingForButtonsBar { - /* - never show the settings button for the buttons bar - show the settings button in the Buttons bar on width < 500px - */ +.settingsOnlyShowNarrow { display: none; } -.settingForBottomLeftCorner { - /* - show the settings button in the bottom left corner by default (will be hidden on width < 500px) - */ +.settingsOnlyShowWide { display: inherit; } @@ -101,12 +94,13 @@ Once we exceed 500 we hide everything except the buttons. grid-template-areas: "buttons buttons buttons"; } - .settingForButtonsBar { + .settingsOnlyShowNarrow { display: inherit; } - .settingForBottomLeftCorner { + .settingsOnlyShowWide { display: none; } + .settingsLogoContainer { display: none; } diff --git a/src/components/InCallFooter.tsx b/src/components/InCallFooter.tsx index d0906305e..cbc346cc6 100644 --- a/src/components/InCallFooter.tsx +++ b/src/components/InCallFooter.tsx @@ -94,7 +94,12 @@ export const InCallFooter: FC = ({ // add the settings button to the center group of buttons, so it will be visible on small screens. // On larger screens, it will be hidden and the one without `forButtonsBar` in the `settingsLogoContainer` will be visible. buttons.push( - , + , ); } @@ -157,8 +162,7 @@ export const InCallFooter: FC = ({ if (audioOutputButton) buttons.push(audioOutputButton); useAppBarSecondaryButton( - // , -
, + , ); buttons.push( @@ -196,7 +200,11 @@ export const InCallFooter: FC = ({ >
{showSettingsButton && ( - + )} {showLogoDebugContainer && logoDebugContainer} From 9ac42b240e303aac9d899f13eac7610496bdc954 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 13 Apr 2026 01:27:40 +0000 Subject: [PATCH 463/748] Update Compound --- package.json | 4 ++-- yarn.lock | 22 +++++++++++----------- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/package.json b/package.json index 8aa374991..32476d104 100644 --- a/package.json +++ b/package.json @@ -80,8 +80,8 @@ "@typescript-eslint/eslint-plugin": "^8.31.0", "@typescript-eslint/parser": "^8.31.0", "@use-gesture/react": "^10.2.11", - "@vector-im/compound-design-tokens": "^9.0.0", - "@vector-im/compound-web": "^8.0.0", + "@vector-im/compound-design-tokens": "^10.0.0", + "@vector-im/compound-web": "^9.0.0", "@vitejs/plugin-react": "^4.0.1", "@vitest/coverage-v8": "^4.0.18", "babel-plugin-transform-vite-meta-env": "^1.0.3", diff --git a/yarn.lock b/yarn.lock index 25fecdea1..3b0572369 100644 --- a/yarn.lock +++ b/yarn.lock @@ -6455,9 +6455,9 @@ __metadata: languageName: node linkType: hard -"@vector-im/compound-design-tokens@npm:^9.0.0": - version: 9.0.0 - resolution: "@vector-im/compound-design-tokens@npm:9.0.0" +"@vector-im/compound-design-tokens@npm:^10.0.0": + version: 10.1.0 + resolution: "@vector-im/compound-design-tokens@npm:10.1.0" peerDependencies: "@types/react": "*" react: ^17 || ^18 || ^19.0.0 @@ -6466,13 +6466,13 @@ __metadata: optional: true react: optional: true - checksum: 10c0/6c53770bfba512d8a9f330ca2d0c481806e35f40d98f53815716e41ddac74d6fc3c4788fcda2e33907d62d2c5c04e64db62176c04513fbee41c7c436730081ce + checksum: 10c0/ffd8223195eac66bcddd85eb5d6cf64ba5ffa521d3673c1caa5346d0346cfe165819d4744b7c1ad6289f8074684a4c4e8f972a54d34ffa91625f1e377e732ad5 languageName: node linkType: hard -"@vector-im/compound-web@npm:^8.0.0": - version: 8.4.0 - resolution: "@vector-im/compound-web@npm:8.4.0" +"@vector-im/compound-web@npm:^9.0.0": + version: 9.0.1 + resolution: "@vector-im/compound-web@npm:9.0.1" dependencies: "@floating-ui/react": "npm:^0.27.0" "@radix-ui/react-context-menu": "npm:^2.2.16" @@ -6487,12 +6487,12 @@ __metadata: "@fontsource/inconsolata": ^5 "@fontsource/inter": ^5 "@types/react": "*" - "@vector-im/compound-design-tokens": ">=1.6.1 <7.0.0" + "@vector-im/compound-design-tokens": ">=1.6.1 <11.0.0" react: ^18 || ^19.0.0 peerDependenciesMeta: "@types/react": optional: true - checksum: 10c0/31b73555c47b373d4250872bfe863a030b487197bf1198e3cf3a1ec344f2b02f0c72c1513bb598c1cbd7a91d3c6a334d0c8ae37bd7c90d4859c864fc223e059a + checksum: 10c0/4ae90e1518001a8a4a2a76e86cfc4fc2bba9b2e556c6e4b56df2c7b04e0e2cdb213b70ee7c7ba4288250c726e8182a473d3d5fdf95890451675239c957251eee languageName: node linkType: hard @@ -8666,8 +8666,8 @@ __metadata: "@typescript-eslint/eslint-plugin": "npm:^8.31.0" "@typescript-eslint/parser": "npm:^8.31.0" "@use-gesture/react": "npm:^10.2.11" - "@vector-im/compound-design-tokens": "npm:^9.0.0" - "@vector-im/compound-web": "npm:^8.0.0" + "@vector-im/compound-design-tokens": "npm:^10.0.0" + "@vector-im/compound-web": "npm:^9.0.0" "@vitejs/plugin-react": "npm:^4.0.1" "@vitest/coverage-v8": "npm:^4.0.18" babel-plugin-transform-vite-meta-env: "npm:^1.0.3" From 1b67f3d8874ac511c27cda9c93a21641195787a0 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 25 Feb 2026 20:34:17 +0000 Subject: [PATCH 464/748] Update dependency livekit-client to v2.17.2 --- yarn.lock | 23 +++++++---------------- 1 file changed, 7 insertions(+), 16 deletions(-) diff --git a/yarn.lock b/yarn.lock index 25fecdea1..0d5f59781 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3331,18 +3331,9 @@ __metadata: languageName: node linkType: hard -"@livekit/protocol@npm:1.42.2": - version: 1.42.2 - resolution: "@livekit/protocol@npm:1.42.2" - dependencies: - "@bufbuild/protobuf": "npm:^1.10.0" - checksum: 10c0/73e77e0975d4d8ca0baa23ad03cb9ac3a844e8d89e9cefbd17343131a774c7aeb4d190fd0397152fcf5a396d921af3eb83e83e660a4aa12215d9ac4e52bf037a - languageName: node - linkType: hard - -"@livekit/protocol@npm:^1.42.2": - version: 1.45.1 - resolution: "@livekit/protocol@npm:1.45.1" +"@livekit/protocol@npm:1.44.0, @livekit/protocol@npm:^1.42.2": + version: 1.44.0 + resolution: "@livekit/protocol@npm:1.44.0" dependencies: "@bufbuild/protobuf": "npm:^1.10.0" checksum: 10c0/f249d8501c0021475c4a0a063af5e5d55469fb889b7df4a14a86d347893133bdc8639a8270d80863fe3b8090a3cebf02e7fdc8e4a55aa3985e41ba8e50a2d078 @@ -11678,11 +11669,11 @@ __metadata: linkType: hard "livekit-client@npm:^2.13.0": - version: 2.16.0 - resolution: "livekit-client@npm:2.16.0" + version: 2.17.2 + resolution: "livekit-client@npm:2.17.2" dependencies: "@livekit/mutex": "npm:1.1.1" - "@livekit/protocol": "npm:1.42.2" + "@livekit/protocol": "npm:1.44.0" events: "npm:^3.3.0" jose: "npm:^6.1.0" loglevel: "npm:^1.9.2" @@ -11693,7 +11684,7 @@ __metadata: webrtc-adapter: "npm:^9.0.1" peerDependencies: "@types/dom-mediacapture-record": ^1 - checksum: 10c0/5d03adc5d09efde343ab894db397529dff26117598e773b23a5df90a4fb166bde12c6bb1f2cfd1d28dbaf93fe9f275026d7abb75f2ffd2ba816393a2d58e6c7e + checksum: 10c0/3fd39eaeab405f3df1ceb5737bf57097f7c0e20b7d0b12d684720cf0a920e0268a26ab0b79d2cb74799cd1a50cc7fe96526956b64d6bca7c7c8deefb94adf78a languageName: node linkType: hard From 79de8dffffd6a6d4a6be53a02c9993ed565e7a49 Mon Sep 17 00:00:00 2001 From: fkwp Date: Thu, 26 Feb 2026 11:20:36 +0100 Subject: [PATCH 465/748] fix test as with the recent version of livekit-client the URL format changed --- playwright/errors.spec.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/playwright/errors.spec.ts b/playwright/errors.spec.ts index 085fb0b4a..23f6e29f3 100644 --- a/playwright/errors.spec.ts +++ b/playwright/errors.spec.ts @@ -102,8 +102,10 @@ test("Should show error screen if call creation is restricted", async ({ // Then if the socket connection fails, livekit will try to validate the token! // Livekit will not auto_create anymore and will return a 404 error. + // Note the regex is required as livekit-client is nowasays trying two + // differnt APIs await page.route( - "**/badurltotricktest/livekit/sfu/rtc/validate?**", + /.*\/badurltotricktest\/livekit\/sfu\/rtc(\/v1)?\/validate?.*/, async (route) => await route.fulfill({ status: 404, From dbeae383ebed76b361f37693a8917fb422bfa013 Mon Sep 17 00:00:00 2001 From: Valere Date: Mon, 13 Apr 2026 09:35:08 +0200 Subject: [PATCH 466/748] update livekit again --- yarn.lock | 47 ++++++++++++++++++++++++----------------------- 1 file changed, 24 insertions(+), 23 deletions(-) diff --git a/yarn.lock b/yarn.lock index 0d5f59781..41f82ba5c 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3288,39 +3288,39 @@ __metadata: languageName: node linkType: hard -"@livekit/components-core@npm:0.12.12, @livekit/components-core@npm:^0.12.0": - version: 0.12.12 - resolution: "@livekit/components-core@npm:0.12.12" +"@livekit/components-core@npm:0.12.13, @livekit/components-core@npm:^0.12.0": + version: 0.12.13 + resolution: "@livekit/components-core@npm:0.12.13" dependencies: "@floating-ui/dom": "npm:1.7.4" loglevel: "npm:1.9.1" rxjs: "npm:7.8.2" peerDependencies: - livekit-client: ^2.15.14 + livekit-client: ^2.17.2 tslib: ^2.6.2 - checksum: 10c0/788ae01fa6c58a0edbd629f4195f2f3a7bc94660d2fb729af8b27cab2b151abe36cd0a666989811c6187e51d32c847119853010a82be55844750ab3978079c38 + checksum: 10c0/d6e0b897e4eaeacf42b2845ddcebd03b35c3877ab99ed92152f58ee46b4f334e540542ef35846718a39fe51fbad4264e91f2c1264f0e42a083c261c510013f91 languageName: node linkType: hard "@livekit/components-react@npm:^2.0.0": - version: 2.9.17 - resolution: "@livekit/components-react@npm:2.9.17" + version: 2.9.20 + resolution: "@livekit/components-react@npm:2.9.20" dependencies: - "@livekit/components-core": "npm:0.12.12" + "@livekit/components-core": "npm:0.12.13" clsx: "npm:2.1.1" events: "npm:^3.3.0" jose: "npm:^6.0.12" usehooks-ts: "npm:3.1.1" peerDependencies: "@livekit/krisp-noise-filter": ^0.2.12 || ^0.3.0 - livekit-client: ^2.15.14 + livekit-client: ^2.17.2 react: ">=18" react-dom: ">=18" tslib: ^2.6.2 peerDependenciesMeta: "@livekit/krisp-noise-filter": optional: true - checksum: 10c0/ba64ada37d4b3ce4d5ee7c5b2a6bddbffc17c2e641e95881aac9f02b4ff7428105e0a372d364e50ff124e988b7426d322d94caabdb55b634aebf0144d7e37f99 + checksum: 10c0/ce00fb59446804571ad5534cdd7ce18315f96daab491ab60b7f7b27d26978f7a06a23495b89578385cd0d42b99a1ddbbd8699d0a3a82f00b2e77875f460387af languageName: node linkType: hard @@ -3331,12 +3331,21 @@ __metadata: languageName: node linkType: hard -"@livekit/protocol@npm:1.44.0, @livekit/protocol@npm:^1.42.2": +"@livekit/protocol@npm:1.44.0": version: 1.44.0 resolution: "@livekit/protocol@npm:1.44.0" dependencies: "@bufbuild/protobuf": "npm:^1.10.0" - checksum: 10c0/f249d8501c0021475c4a0a063af5e5d55469fb889b7df4a14a86d347893133bdc8639a8270d80863fe3b8090a3cebf02e7fdc8e4a55aa3985e41ba8e50a2d078 + checksum: 10c0/f547a5ee586cae002ed2834f0a823573e38887562dbc793e261791b0572472c6732262a5466c96082464575a3248a4c6cb0428420418e834cdbef1b202cddedf + languageName: node + linkType: hard + +"@livekit/protocol@npm:^1.42.2": + version: 1.45.3 + resolution: "@livekit/protocol@npm:1.45.3" + dependencies: + "@bufbuild/protobuf": "npm:^1.10.0" + checksum: 10c0/8c9c889d9042d3b27acc0dd537df36e0c804c1d205741e2d3789111c728d840933ab0743655cb81df52c7715210db193c1fc8e2e223d765d05537c502918299b languageName: node linkType: hard @@ -11669,8 +11678,8 @@ __metadata: linkType: hard "livekit-client@npm:^2.13.0": - version: 2.17.2 - resolution: "livekit-client@npm:2.17.2" + version: 2.18.1 + resolution: "livekit-client@npm:2.18.1" dependencies: "@livekit/mutex": "npm:1.1.1" "@livekit/protocol": "npm:1.44.0" @@ -11678,13 +11687,12 @@ __metadata: jose: "npm:^6.1.0" loglevel: "npm:^1.9.2" sdp-transform: "npm:^2.15.0" - ts-debounce: "npm:^4.0.0" tslib: "npm:2.8.1" typed-emitter: "npm:^2.1.0" webrtc-adapter: "npm:^9.0.1" peerDependencies: "@types/dom-mediacapture-record": ^1 - checksum: 10c0/3fd39eaeab405f3df1ceb5737bf57097f7c0e20b7d0b12d684720cf0a920e0268a26ab0b79d2cb74799cd1a50cc7fe96526956b64d6bca7c7c8deefb94adf78a + checksum: 10c0/087ffebf3265b1bae2d3346af46c6b03b693e6226dc8b28618de5784979db5354bd17d992589ac9e18a014ef38f05ee8d77aa108fe0638b325cefd23ea8675ba languageName: node linkType: hard @@ -15313,13 +15321,6 @@ __metadata: languageName: node linkType: hard -"ts-debounce@npm:^4.0.0": - version: 4.0.0 - resolution: "ts-debounce@npm:4.0.0" - checksum: 10c0/1dfac630127d6982b4ad5114a12bd3e8febfd7a34615e6bf388eaf3a5c355f9ab2ef688688bb7e789bc9f0cabfd82e0a6b363efc451ee626b5722919f7f567cd - languageName: node - linkType: hard - "ts-dedent@npm:^2.0.0": version: 2.2.0 resolution: "ts-dedent@npm:2.2.0" From 07e3dc1ca4d6239c7a8a490379e6e1a8e4c87f82 Mon Sep 17 00:00:00 2001 From: Valere Date: Mon, 13 Apr 2026 10:02:54 +0200 Subject: [PATCH 467/748] Update livekit to 2.18.1 Fix mocking in a test Also add "skipLibCheck": true in tsconfig --- package.json | 2 +- src/state/CallViewModel/localMember/Publisher.test.ts | 1 + tsconfig.json | 1 + yarn.lock | 4 ++-- 4 files changed, 5 insertions(+), 3 deletions(-) diff --git a/package.json b/package.json index 8aa374991..68efcfaf1 100644 --- a/package.json +++ b/package.json @@ -107,7 +107,7 @@ "i18next-parser": "^9.1.0", "jsdom": "^26.0.0", "knip": "^5.86.0", - "livekit-client": "^2.13.0", + "livekit-client": "^2.18.1", "lodash-es": "^4.17.21", "loglevel": "^1.9.1", "matrix-js-sdk": "matrix-org/matrix-js-sdk#6e3efef0c5f660df47cf00874927dec1c75cc3cf", diff --git a/src/state/CallViewModel/localMember/Publisher.test.ts b/src/state/CallViewModel/localMember/Publisher.test.ts index a0eaa2fd6..e54e706ff 100644 --- a/src/state/CallViewModel/localMember/Publisher.test.ts +++ b/src/state/CallViewModel/localMember/Publisher.test.ts @@ -131,6 +131,7 @@ beforeEach(() => { }, new Map(), {}, + {}, ); vi.mocked(localParticipant).createTracks = vi diff --git a/tsconfig.json b/tsconfig.json index 0f9e7c663..7539e850c 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -4,6 +4,7 @@ "module": "es2022", "jsx": "react-jsx", "lib": ["es2024", "dom", "dom.iterable"], + "skipLibCheck": true, // From Matrix-JS-SDK "strict": true, diff --git a/yarn.lock b/yarn.lock index 41f82ba5c..14e0bb9be 100644 --- a/yarn.lock +++ b/yarn.lock @@ -8693,7 +8693,7 @@ __metadata: i18next-parser: "npm:^9.1.0" jsdom: "npm:^26.0.0" knip: "npm:^5.86.0" - livekit-client: "npm:^2.13.0" + livekit-client: "npm:^2.18.1" lodash-es: "npm:^4.17.21" loglevel: "npm:^1.9.1" matrix-js-sdk: "matrix-org/matrix-js-sdk#6e3efef0c5f660df47cf00874927dec1c75cc3cf" @@ -11677,7 +11677,7 @@ __metadata: languageName: node linkType: hard -"livekit-client@npm:^2.13.0": +"livekit-client@npm:^2.18.1": version: 2.18.1 resolution: "livekit-client@npm:2.18.1" dependencies: From 0842b2b472c0d4885ea71359777454d7fa65a71b Mon Sep 17 00:00:00 2001 From: Robin Date: Mon, 13 Apr 2026 13:02:15 +0200 Subject: [PATCH 468/748] Fix placement of reaction and raised hand indicators --- src/tile/MediaView.module.css | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/tile/MediaView.module.css b/src/tile/MediaView.module.css index 1183f7c53..e972443f5 100644 --- a/src/tile/MediaView.module.css +++ b/src/tile/MediaView.module.css @@ -82,9 +82,9 @@ unconditionally select the container so we can use cqmin units */ ); inset: var(--fg-inset); display: grid; - grid-template-columns: 30px 1fr 30px; + grid-template-columns: 1fr auto; grid-template-rows: 1fr auto; - grid-template-areas: "status status reactions" "nameTag nameTag button"; + grid-template-areas: "status reactions" "nameTag button"; gap: var(--cpd-space-1x); place-items: start; } @@ -125,6 +125,7 @@ unconditionally select the container so we can use cqmin units */ .reactions { grid-area: reactions; + place-self: start end; display: flex; gap: var(--cpd-space-1x); } @@ -192,4 +193,5 @@ unconditionally select the container so we can use cqmin units */ .fg > button:first-of-type { grid-area: button; + place-self: end; } From 5daa110f7ee9127d104c2bd65c37d53d616f5ff7 Mon Sep 17 00:00:00 2001 From: Robin Date: Mon, 13 Apr 2026 13:13:09 +0200 Subject: [PATCH 469/748] Make the footer move floating tiles out of the way when shown If you manage to move your floating video tile to the bottom of the screen in a small landscape window, the footer obscures the tile when shown. The designs want us to smoothly move the floating tile out of the way in this case. --- src/room/InCallView.module.css | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/room/InCallView.module.css b/src/room/InCallView.module.css index 70f7c73a4..685cc35c4 100644 --- a/src/room/InCallView.module.css +++ b/src/room/InCallView.module.css @@ -55,9 +55,8 @@ Please see LICENSE in the repository root for full details. } .footer.overlay { - position: absolute; - inset-block-end: 0; - inset-inline: 0; + /* Note that the footer is still position: sticky in this case so that certain + tiles can move up out of the way of the footer when visible. */ opacity: 1; transition: opacity 0.15s; } @@ -66,6 +65,11 @@ Please see LICENSE in the repository root for full details. display: grid; opacity: 0; pointer-events: none; + /* Switch to position: absolute so the footer takes up no space in the layout + when hidden. */ + position: absolute; + inset-block-end: 0; + inset-inline: 0; } .footer.overlay:has(:focus-visible) { From 270726d4464dc9cee547d0e18b7837861b955ac6 Mon Sep 17 00:00:00 2001 From: Timo K Date: Mon, 13 Apr 2026 13:38:35 +0200 Subject: [PATCH 470/748] Add tests --- src/analytics/PosthogEvents.test.ts | 162 ++++++++++++++++++++++++++++ 1 file changed, 162 insertions(+) create mode 100644 src/analytics/PosthogEvents.test.ts diff --git a/src/analytics/PosthogEvents.test.ts b/src/analytics/PosthogEvents.test.ts new file mode 100644 index 000000000..35b86f5d4 --- /dev/null +++ b/src/analytics/PosthogEvents.test.ts @@ -0,0 +1,162 @@ +/* +Copyright 2025 New Vector Ltd. + +SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial +Please see LICENSE in the repository root for full details. +*/ + +import { + expect, + describe, + it, + vi, + beforeEach, + beforeAll, + afterAll, +} from "vitest"; +import { logger } from "matrix-js-sdk/lib/logger"; +import { type MatrixRTCSession } from "matrix-js-sdk/lib/matrixrtc"; + +import { PosthogAnalytics } from "./PosthogAnalytics"; +import { CallEndedTracker } from "./PosthogEvents"; +import { mockConfig } from "../utils/test"; + +const defaultCounters = { + roomEventEncryptionKeysSent: 10, + roomEventEncryptionKeysReceived: 5, +}; + +const defaultTotals = { + roomEventEncryptionKeysReceivedTotalAge: 500, +}; + +function createMockRtcSession(overrides?: { + counters?: Partial; + totals?: Partial; +}): MatrixRTCSession { + return { + statistics: { + counters: { ...defaultCounters, ...overrides?.counters }, + totals: { ...defaultTotals, ...overrides?.totals }, + }, + } as unknown as MatrixRTCSession; +} + +describe("CallEnded", () => { + beforeAll(() => { + mockConfig(); + }); + + beforeEach(() => { + vi.restoreAllMocks(); + vi.spyOn(PosthogAnalytics.instance, "trackEvent").mockImplementation( + () => {}, + ); + }); + + afterAll(() => { + PosthogAnalytics.resetInstance(); + }); + + it("warns if startTime is missing when track is called", () => { + const warnSpy = vi.spyOn(logger, "warn"); + const tracker = new CallEndedTracker(); + const mockSession = createMockRtcSession(); + + tracker.track("test-call-id", 2, false, mockSession); + + expect(warnSpy).toHaveBeenCalledWith( + "[PosthogEvents] Failed to send posthog callEnded event due to missing startTime", + ); + expect(PosthogAnalytics.instance.trackEvent).not.toHaveBeenCalled(); + }); + + it("tracks event with correct properties when startTime is set", () => { + const tracker = new CallEndedTracker(); + const mockSession = createMockRtcSession(); + + tracker.cacheStartCall(new Date(Date.now() - 60000)); + tracker.cacheParticipantCountChanged(5); + tracker.track("test-call-id", 3, true, mockSession); + + expect(PosthogAnalytics.instance.trackEvent).toHaveBeenCalledWith( + { + eventName: "CallEnded", + callId: "test-call-id", + callParticipantsMax: 5, + callParticipantsOnLeave: 3, + callDuration: expect.closeTo(60, 1), + roomEventEncryptionKeysSent: 10, + roomEventEncryptionKeysReceived: 5, + roomEventEncryptionKeysReceivedAverageAge: 100, + }, + { send_instantly: true }, + ); + }); + + it("tracks maxParticipantsCount correctly across multiple changes", () => { + const tracker = new CallEndedTracker(); + const mockSession = createMockRtcSession(); + + tracker.cacheStartCall(new Date()); + tracker.cacheParticipantCountChanged(3); + tracker.cacheParticipantCountChanged(7); + tracker.cacheParticipantCountChanged(2); + tracker.track("test-call-id", 1, false, mockSession); + + expect(PosthogAnalytics.instance.trackEvent).toHaveBeenCalledWith( + expect.objectContaining({ + callParticipantsMax: 7, + }), + expect.anything(), + ); + }); + + it("computes roomEventEncryptionKeysReceivedAverageAge as 0 when no keys received", () => { + const tracker = new CallEndedTracker(); + const mockSession = createMockRtcSession({ + counters: { roomEventEncryptionKeysReceived: 0 }, + }); + + tracker.cacheStartCall(new Date()); + tracker.track("test-call-id", 1, false, mockSession); + + expect(PosthogAnalytics.instance.trackEvent).toHaveBeenCalledWith( + expect.objectContaining({ + roomEventEncryptionKeysReceivedAverageAge: 0, + }), + expect.anything(), + ); + }); + + it("computes roomEventEncryptionKeysReceivedAverageAge correctly when keys are received", () => { + const tracker = new CallEndedTracker(); + const mockSession = createMockRtcSession({ + counters: { roomEventEncryptionKeysReceived: 4 }, + totals: { roomEventEncryptionKeysReceivedTotalAge: 200 }, + }); + + tracker.cacheStartCall(new Date()); + tracker.track("test-call-id", 1, false, mockSession); + + expect(PosthogAnalytics.instance.trackEvent).toHaveBeenCalledWith( + expect.objectContaining({ + roomEventEncryptionKeysReceivedAverageAge: 50, + }), + expect.anything(), + ); + }); + + it("passes send_instantly option correctly", () => { + const tracker = new CallEndedTracker(); + const mockSession = createMockRtcSession(); + + tracker.cacheStartCall(new Date()); + tracker.track("test-call-id", 1, false, mockSession); + + expect(PosthogAnalytics.instance.trackEvent).toHaveBeenCalledWith( + expect.anything(), + { send_instantly: false }, + ); + }); +}); From 4d1fbf050254436970c1005833d9d458eb2de9a8 Mon Sep 17 00:00:00 2001 From: Robin Date: Mon, 13 Apr 2026 15:08:40 +0200 Subject: [PATCH 471/748] Delete unused CSS file Seems this was mistakenly committed during initial development of the Grid component. src/grid/Grid.module.css is the one that's actually used. --- src/grid/Grid.css | 22 ---------------------- 1 file changed, 22 deletions(-) delete mode 100644 src/grid/Grid.css diff --git a/src/grid/Grid.css b/src/grid/Grid.css deleted file mode 100644 index 1e7710ddf..000000000 --- a/src/grid/Grid.css +++ /dev/null @@ -1,22 +0,0 @@ -/* -Copyright 2023, 2024 New Vector Ltd. - -SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial -Please see LICENSE in the repository root for full details. -*/ - -.grid { - contain: layout style; - position: relative; - flex-grow: 1; - margin-inline: var(--inline-content-inset); - margin-block: var(--cpd-space-4x); -} - -.slots { - position: relative; -} - -.slot { - contain: strict; -} From 9df60310e44a2da0c4d623827f950f6d594672d7 Mon Sep 17 00:00:00 2001 From: Robin Date: Mon, 13 Apr 2026 15:13:19 +0200 Subject: [PATCH 472/748] Update test snapshots --- .../GroupCallErrorBoundary.test.tsx.snap | 35 +++++++++++-------- .../__snapshots__/InCallView.test.tsx.snap | 7 ++-- 2 files changed, 25 insertions(+), 17 deletions(-) diff --git a/src/room/__snapshots__/GroupCallErrorBoundary.test.tsx.snap b/src/room/__snapshots__/GroupCallErrorBoundary.test.tsx.snap index 3f02a49af..0d2d39bce 100644 --- a/src/room/__snapshots__/GroupCallErrorBoundary.test.tsx.snap +++ b/src/room/__snapshots__/GroupCallErrorBoundary.test.tsx.snap @@ -108,8 +108,9 @@ exports[`ConnectionLostError: Action handling should reset error state 1`] = ` class="error" >
rendering > renders 1`] = ` data-show="false" >
+
= ({ layout, setLayout, className }) => { /> -
+ ); }; From 400259207e805276dd0e12d7adb67b6c90616cc6 Mon Sep 17 00:00:00 2001 From: Timo K Date: Tue, 14 Apr 2026 13:25:33 +0200 Subject: [PATCH 478/748] Also use CallFooter for lobby --- .storybook/main.ts | 4 +- playwright/mobile/create-call-mobile.spec.ts | 2 +- src/button/Button.tsx | 6 +- src/components/CallFooter.mdx | 31 +++ ...ooter.module.css => CallFooter.module.css} | 1 + src/components/CallFooter.stories.tsx | 232 ++++++++++++++++++ .../{InCallFooter.tsx => CallFooter.tsx} | 131 ++++++---- src/components/InCallFooter.stories.tsx | 132 ---------- src/reactions/useReactionsSender.tsx | 2 +- src/room/InCallView.test.tsx | 6 +- src/room/InCallView.tsx | 23 +- src/room/LobbyView.tsx | 30 +-- 12 files changed, 370 insertions(+), 230 deletions(-) create mode 100644 src/components/CallFooter.mdx rename src/components/{InCallFooter.module.css => CallFooter.module.css} (99%) create mode 100644 src/components/CallFooter.stories.tsx rename src/components/{InCallFooter.tsx => CallFooter.tsx} (63%) delete mode 100644 src/components/InCallFooter.stories.tsx diff --git a/.storybook/main.ts b/.storybook/main.ts index 9be416768..9a3f0b539 100644 --- a/.storybook/main.ts +++ b/.storybook/main.ts @@ -8,8 +8,8 @@ Please see LICENSE in the repository root for full details. import type { StorybookConfig } from "@storybook/react-vite"; const config: StorybookConfig = { - stories: ["../src/**/*.stories.@(js|jsx|mjs|ts|tsx)"], - addons: ["@storybook/addon-docs"], + stories: ["../src/**/*.mdx", "../src/**/*.stories.@(js|jsx|mjs|ts|tsx)"], + addons: ["@storybook/addon-docs", "@storybook/addon-vitest"], framework: "@storybook/react-vite", }; export default config; diff --git a/playwright/mobile/create-call-mobile.spec.ts b/playwright/mobile/create-call-mobile.spec.ts index de1e65d10..c208c6b5f 100644 --- a/playwright/mobile/create-call-mobile.spec.ts +++ b/playwright/mobile/create-call-mobile.spec.ts @@ -109,7 +109,7 @@ mobileTest( .click(); // dismiss settings - await guestPage.locator("#root").getByLabel("Settings").press("Escape"); + await guestPage.locator("#root").press("Escape"); await guestPage.pause(); await expect( diff --git a/src/button/Button.tsx b/src/button/Button.tsx index 261c013c1..98b377cec 100644 --- a/src/button/Button.tsx +++ b/src/button/Button.tsx @@ -22,7 +22,7 @@ import { } from "@vector-im/compound-design-tokens/assets/web/icons"; import styles from "./Button.module.css"; -import inCallFooterStyles from "../components/InCallFooter.module.css"; +import callFooterStyles from "../components/CallFooter.module.css"; import { platform } from "../Platform"; interface MicButtonProps extends ComponentPropsWithoutRef<"button"> { @@ -177,9 +177,9 @@ export const SettingsButton: FC = ({ + + Call Footer + +The footer compoentn contains all main interactions needed for a call. + + Mobile layouts + +This component is reactive. To properly check the mobile layout, you will need to click on the stories in the left sidebar to see the +component on a mobile screen. +The story summary here does not render the mobile layouts correctly. + + + + diff --git a/src/components/InCallFooter.module.css b/src/components/CallFooter.module.css similarity index 99% rename from src/components/InCallFooter.module.css rename to src/components/CallFooter.module.css index 563d27d23..79682ce80 100644 --- a/src/components/InCallFooter.module.css +++ b/src/components/CallFooter.module.css @@ -51,6 +51,7 @@ Please see LICENSE in the repository root for full details. .settingsLogoContainer { display: flex; + align-items: center; gap: var(--cpd-space-4x); flex-direction: row; } diff --git a/src/components/CallFooter.stories.tsx b/src/components/CallFooter.stories.tsx new file mode 100644 index 000000000..fcf0be3d5 --- /dev/null +++ b/src/components/CallFooter.stories.tsx @@ -0,0 +1,232 @@ +/* +Copyright 2026 Element Creations Ltd. + +SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial +Please see LICENSE in the repository root for full details. +*/ + +import { fn } from "storybook/test"; +import { BehaviorSubject } from "rxjs"; +import { type ReactNode } from "react"; +import { Link } from "@vector-im/compound-web"; + +import type { Meta, StoryObj } from "@storybook/react-vite"; +import { CallFooter, type FooterProps } from "./CallFooter"; +import inCallViewStyles from "../room/InCallView.module.css"; +import { ReactionsSenderContext } from "../reactions/useReactionsSender"; +import { type ReactionOption } from "../reactions"; + +function CallFooterWrapper(props: FooterProps): ReactNode { + return ( +
+ Promise.resolve(), + sendReaction: async (reaction: ReactionOption) => Promise.resolve(), + }} + > + + +
+ ); +} + +const meta = { + component: CallFooterWrapper, +} satisfies Meta; + +export default meta; +type Story = StoryObj; + +const reactionIdentifier = "@user:example.com:DEVICE"; +const reactionData = { + handsRaised$: new BehaviorSubject({}), + reactions$: new BehaviorSubject({}), +}; + +const fnArgType = { + control: { type: "select" as const }, + options: ["MockedCallback", "undefined"], + mapping: { MockedCallback: fn(), undefined: undefined }, +}; +export const Default: Story = { + args: { + hideLogo: true, + layoutMode: "grid", + setLayoutMode: fn(), + openSettings: fn(), + toggleAudio: fn(), + toggleVideo: fn(), + toggleScreenSharing: fn(), + hangup: fn(), + }, + parameters: { + layout: "fullscreen", + }, + argTypes: { + layoutMode: { control: "radio", options: ["grid", "spotlight"] }, + audioOutputSwitcher: { + control: "select", + options: ["NoOutputCallback", "speaker", "earpiece"], + table: { defaultValue: { summary: "NoOutputCallback" } }, + mapping: { + NoOutputCallback: undefined, + // This is inverersed (speaker<->earpice) because the switcher object stores the target output, not the current one. + speaker: { targetOutput: "speaker", switch: fn() }, + earpiece: { targetOutput: "earpiece", switch: fn() }, + }, + }, + toggleScreenSharing: fnArgType, + setLayoutMode: fnArgType, + openSettings: fnArgType, + toggleAudio: fnArgType, + toggleVideo: fnArgType, + hangup: fnArgType, + }, +}; + +export const WithLogo: Story = { + ...Default, + args: { + ...Default.args, + hideLogo: false, + }, +}; + +export const AudioVideoEnabled: Story = { + ...Default, + args: { + ...Default.args, + audioEnabled: true, + videoEnabled: true, + }, +}; +export const WithAudioOutput: Story = { + ...Default, + args: { + ...Default.args, + audioOutputSwitcher: { targetOutput: "speaker", switch: fn() }, + }, +}; +export const WithReactions: Story = { + ...Default, + args: { + ...Default.args, + reactionIdentifier, + reactionData, + }, +}; +export const Pip: Story = { + ...Default, + args: { + ...Default.args, + asPip: true, + }, +}; + +export const NoControlsWithLogo: Story = { + ...Default, + args: { + ...Default.args, + hideControls: true, + hideLogo: false, + }, +}; + +export const DebugData: Story = { + ...Default, + args: { + ...Default.args, + debugTileLayout: true, + tileStoreGeneration: 74, + }, +}; + +export const UnavailableMediaDevices: Story = { + ...Default, + args: { + ...Default.args, + toggleAudio: undefined, + toggleVideo: undefined, + audioOutputSwitcher: undefined, + }, +}; + +export const MobileLayout: Story = { + ...Default, + args: { + ...Default.args, + hideLogo: true, + + audioOutputSwitcher: { targetOutput: "speaker", switch: fn() }, + }, + globals: { + viewport: { value: "mobile2", isRotated: false }, + }, + parameters: { + ...Default.parameters, + }, +}; + +export const Lobby: Story = { + ...Default, + args: { + ...Default.args, + hideLogo: true, + openSettings: undefined, + setLayoutMode: undefined, + toggleScreenSharing: undefined, + }, + parameters: { + ...Default.parameters, + }, +}; + +export const LobbyMobile: Story = { + ...Default, + args: { + ...Default.args, + hideLogo: true, + + setLayoutMode: undefined, + toggleScreenSharing: undefined, + }, + globals: { + viewport: { value: "mobile2", isRotated: false }, + }, + parameters: { + ...Default.parameters, + }, +}; + +export const LobbyRecentButton: Story = { + ...Default, + args: { + ...Default.args, + children: Back To Recents, + hideLogo: true, + setLayoutMode: undefined, + toggleScreenSharing: undefined, + }, + parameters: { + ...Default.parameters, + }, +}; + +export const LobbyRecentButtonMobile: Story = { + ...Default, + args: { + ...Default.args, + children: Back To Recents, + hideLogo: true, + setLayoutMode: undefined, + toggleScreenSharing: undefined, + }, + globals: { + viewport: { value: "mobile2", isRotated: false }, + }, + parameters: { + ...Default.parameters, + }, +}; diff --git a/src/components/InCallFooter.tsx b/src/components/CallFooter.tsx similarity index 63% rename from src/components/InCallFooter.tsx rename to src/components/CallFooter.tsx index 00bf937c2..3bc3e34bf 100644 --- a/src/components/InCallFooter.tsx +++ b/src/components/CallFooter.tsx @@ -7,6 +7,7 @@ Please see LICENSE in the repository root for full details. import { type FC, type JSX, type Ref, useMemo } from "react"; import classNames from "classnames"; +import { BehaviorSubject } from "rxjs"; import LogoMark from "../icons/LogoMark.svg?react"; import LogoType from "../icons/LogoType.svg?react"; @@ -19,7 +20,7 @@ import { ReactionToggleButton, LoudspeakerButton, } from "../button"; -import styles from "./InCallFooter.module.css"; +import styles from "./CallFooter.module.css"; import { LayoutToggle } from "../room/LayoutToggle"; import { type CallViewModel, @@ -32,44 +33,60 @@ export interface AudioOutputSwitcher { switch: () => void; } -export interface InCallFooterProps { +export interface FooterProps { ref?: Ref; + /** Children will only be visible if the component is wider than 5*/ + children?: JSX.Element | JSX.Element[] | false; /* This is needed for WindowMode = "flat" */ - asOverlay: boolean; - showFooter: boolean; - showControls: boolean; - hideSettingsButton: boolean; - hideLogo: boolean; + hideControls?: boolean; + /** hide the entire footer*/ + hidden?: boolean; /** Pip controls buttonSize and hides: settings button, layout switcher and logo */ - asPip: boolean; - gridMode: GridMode; - setGridMode: (mode: GridMode) => void; - openSettings: () => void; - audioEnabled: boolean; - videoEnabled: boolean; + asPip?: boolean; + /** The footer should be used as an overlay. + * (Over the Call Grid) This saves spaces on small screens.*/ + asOverlay?: boolean; + + layoutMode?: GridMode; + /** Also controls if the layout button is visible */ + setLayoutMode?: (mode: GridMode) => void; + + audioEnabled?: boolean; + /** Also controls if the audioMute button is disabled */ toggleAudio?: () => void; + videoEnabled?: boolean; + /** Also controls if the videoMute button is disabled */ toggleVideo?: () => void; - sharingScreen: boolean; + + sharingScreen?: boolean; toggleScreenSharing?: () => void; - supportsReactions: boolean; - reactionIdentifier: string; - reactionData: Pick; - audioOutputSwitcher: AudioOutputSwitcher | null; - hangup: () => void; - debugTileLayout: boolean; - tileStoreGeneration: number; + + /** Also controls if the audio button is visible */ + audioOutputSwitcher?: AudioOutputSwitcher; + /** Also controls if the settings button is visible */ + openSettings?: () => void; + /** Also controls if the hangup button is visible */ + hangup?: () => void; + + reactionIdentifier?: string; + reactionData?: Pick; + + hideLogo?: boolean; + // debug stuff + debugTileLayout?: boolean; + tileStoreGeneration?: number; } -export const InCallFooter: FC = ({ +export const CallFooter: FC = ({ ref, + children, asOverlay, - showFooter, - showControls, - hideSettingsButton, + hidden, + hideControls, hideLogo, asPip, - gridMode, - setGridMode, + layoutMode, + setLayoutMode, openSettings, audioEnabled, videoEnabled, @@ -77,7 +94,6 @@ export const InCallFooter: FC = ({ toggleVideo, sharingScreen, toggleScreenSharing, - supportsReactions, reactionIdentifier, reactionData, audioOutputSwitcher, @@ -87,8 +103,9 @@ export const InCallFooter: FC = ({ }) => { const buttons: JSX.Element[] = []; const buttonSize = asPip ? "sm" : "lg"; - const showSettingsButton = !hideSettingsButton && !asPip && showControls; - const showLayoutSwitcher = !asPip && showControls; + const showSettingsButton = + openSettings !== undefined && !asPip && !hideControls; + const showLayoutSwitcher = !asPip && !hideControls; const showLogoDebugContainer = !asPip || (!hideLogo && !debugTileLayout); const showLogo = !hideLogo && !asPip; if (showSettingsButton) { @@ -108,39 +125,45 @@ export const InCallFooter: FC = ({ , , ); - if (toggleScreenSharing !== null) { + if (toggleScreenSharing !== undefined) { buttons.push( , ); } - if (supportsReactions) { + if (reactionIdentifier) { buttons.push( ) + } key="raise_hand" className={styles.raiseHand} identifier={reactionIdentifier} @@ -150,7 +173,7 @@ export const InCallFooter: FC = ({ // In this PR we just move the button to the bottom bar. We do not yet update its appearance const audioOutputButton = useMemo(() => { - if (audioOutputSwitcher === null) return null; + if (audioOutputSwitcher === undefined) return null; return ( = ({ , ); - buttons.push( - , - ); + if (hangup) + buttons.push( + , + ); const logoDebugContainer = (
@@ -196,7 +220,7 @@ export const InCallFooter: FC = ({ ref={ref} className={classNames(styles.footer, { [styles.overlay]: asOverlay, - [styles.hidden]: !showFooter, + [styles.hidden]: hidden, })} >
@@ -207,16 +231,15 @@ export const InCallFooter: FC = ({ onClick={openSettings} /> )} - + {children} {showLogoDebugContainer && logoDebugContainer}
- - {showControls &&
{buttons}
} - {showLayoutSwitcher && ( + {!hideControls &&
{buttons}
} + {setLayoutMode && layoutMode && showLayoutSwitcher && ( )}
diff --git a/src/components/InCallFooter.stories.tsx b/src/components/InCallFooter.stories.tsx deleted file mode 100644 index f73184c09..000000000 --- a/src/components/InCallFooter.stories.tsx +++ /dev/null @@ -1,132 +0,0 @@ -/* -Copyright 2026 Element Creations Ltd. - -SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial -Please see LICENSE in the repository root for full details. -*/ - -import { fn } from "storybook/test"; -import { BehaviorSubject } from "rxjs"; -import { type ReactNode } from "react"; - -import type { Meta, StoryObj } from "@storybook/react-vite"; -import { InCallFooter, type InCallFooterProps } from "./InCallFooter"; -import inCallViewStyles from "../room/InCallView.module.css"; - -function InCallFooterWrapper(props: InCallFooterProps): ReactNode { - return ( -
- -
- ); -} - -const meta = { - component: InCallFooterWrapper, -} satisfies Meta; - -export default meta; -type Story = StoryObj; - -export const Default: Story = { - args: { - asOverlay: false, - showFooter: true, - showControls: true, - hideSettingsButton: false, - hideLogo: true, - asPip: false, - gridMode: "grid", - audioEnabled: true, - videoEnabled: true, - sharingScreen: false, - supportsReactions: false, - audioOutputSwitcher: null, - debugTileLayout: false, - tileStoreGeneration: 0, - reactionData: { - handsRaised$: new BehaviorSubject({}), - reactions$: new BehaviorSubject({}), - }, - reactionIdentifier: "@user:example.com:DEVICE", - setGridMode: fn(), - openSettings: fn(), - toggleAudio: fn(), - toggleVideo: fn(), - toggleScreenSharing: fn(), - hangup: fn(), - }, - parameters: { - layout: "fullscreen", - }, - argTypes: { - gridMode: { control: "radio", options: ["grid", "spotlight"] }, - audioOutputSwitcher: { - control: "radio", - options: ["noOutputSwitcher", "earpiece", "speaker"], - mapping: { - noOutputSwitcher: null, - // This is inverersed (speaker<->earpice) because the switcher object stores the target output, not the current one. - earpiece: { targetOutput: "speaker", switch: fn() }, - speaker: { targetOutput: "earpiece", switch: fn() }, - }, - }, - }, -}; - -export const WithLogo: Story = { - ...Default, - args: { - ...Default.args, - hideLogo: false, - }, -}; -export const WithAudioOutput: Story = { - ...Default, - args: { - ...Default.args, - audioOutputSwitcher: { targetOutput: "speaker", switch: fn() }, - }, -}; -export const Pip: Story = { - ...Default, - args: { - ...Default.args, - asPip: true, - }, -}; - -export const NoControlsWithLogo: Story = { - ...Default, - args: { - ...Default.args, - showControls: false, - hideLogo: false, - }, -}; - -export const DebugData: Story = { - ...Default, - args: { - ...Default.args, - debugTileLayout: true, - tileStoreGeneration: 74, - audioOutputSwitcher: null, - }, -}; -export const MobileLayout: Story = { - ...Default, - args: { - ...Default.args, - hideLogo: true, - debugTileLayout: true, - tileStoreGeneration: 74, - audioOutputSwitcher: null, - }, - globals: { - viewport: { value: "mobile2", isRotated: false }, - }, - parameters: { - ...Default.parameters, - }, -}; diff --git a/src/reactions/useReactionsSender.tsx b/src/reactions/useReactionsSender.tsx index afb9b7897..1b7e099a2 100644 --- a/src/reactions/useReactionsSender.tsx +++ b/src/reactions/useReactionsSender.tsx @@ -29,7 +29,7 @@ interface ReactionsSenderContextType { sendReaction: (reaction: ReactionOption) => Promise; } -const ReactionsSenderContext = createContext< +export const ReactionsSenderContext = createContext< ReactionsSenderContextType | undefined >(undefined); diff --git a/src/room/InCallView.test.tsx b/src/room/InCallView.test.tsx index 5748397ae..e37ad27c8 100644 --- a/src/room/InCallView.test.tsx +++ b/src/room/InCallView.test.tsx @@ -44,7 +44,7 @@ import { type MediaDevices as ECMediaDevices } from "../state/MediaDevices"; import { constant } from "../state/Behavior"; import { AppBar } from "../AppBar"; import { initializeWidget } from "../widget"; -import inCallFooterStyles from "../components/InCallFooter.module.css"; +import callFooterStyles from "../components/CallFooter.module.css"; initializeWidget(); vi.hoisted( @@ -211,9 +211,9 @@ describe("InCallView", () => { // Their visibility uses @media css queries, which cannot be tested in JSDOM, // but we can at least check that both buttons are rendered and have the correct classes. expect(btnA).toBeInTheDocument(); - expect(btnA).toHaveClass(inCallFooterStyles.settingsOnlyShowWide); + expect(btnA).toHaveClass(callFooterStyles.settingsOnlyShowWide); expect(btnB).toBeInTheDocument(); - expect(btnB).toHaveClass(inCallFooterStyles.settingsOnlyShowNarrow); + expect(btnB).toHaveClass(callFooterStyles.settingsOnlyShowNarrow); }); it("is accessible when showHeader is true", () => { diff --git a/src/room/InCallView.tsx b/src/room/InCallView.tsx index 87be44644..5ad1634a7 100644 --- a/src/room/InCallView.tsx +++ b/src/room/InCallView.tsx @@ -90,7 +90,7 @@ import { useTrackProcessorObservable$ } from "../livekit/TrackProcessorContext.t import { type Layout } from "../state/layout-types.ts"; import { ObservableScope } from "../state/ObservableScope.ts"; import { useLatest } from "../useLatest.ts"; -import { InCallFooter } from "../components/InCallFooter.tsx"; +import { CallFooter } from "../components/CallFooter.tsx"; const logger = rootLogger.getChild("[InCallView]"); @@ -562,30 +562,29 @@ export const InCallView: FC = ({ matrixRoom.roomId, ); + // Only hide the settings button if we have an AppBar header and we are showing the header + const hideSettings = headerStyle === HeaderStyle.AppBar && showHeader; const footer = ( -
-
+ {recentsButtonInFooter && recentsButton} - -
- - - {!confineToRoom && } -
-
+
{client && ( Date: Tue, 14 Apr 2026 14:04:29 +0200 Subject: [PATCH 479/748] Breaking changes detected by snapshot tests. Add screenshare button back to snapshot test. Remove reaction button. --- src/components/CallFooter.tsx | 2 +- src/room/InCallView.test.tsx | 5 ++++- src/room/InCallView.tsx | 9 +++++---- src/room/__snapshots__/InCallView.test.tsx.snap | 4 ++-- src/state/CallViewModel/CallViewModel.ts | 5 ++++- 5 files changed, 16 insertions(+), 9 deletions(-) diff --git a/src/components/CallFooter.tsx b/src/components/CallFooter.tsx index 3bc3e34bf..815411a11 100644 --- a/src/components/CallFooter.tsx +++ b/src/components/CallFooter.tsx @@ -153,7 +153,7 @@ export const CallFooter: FC = ({ ); } - if (reactionIdentifier) { + if (reactionIdentifier && reactionData) { buttons.push( {}, + ...args.callViewModelOptions, + }, args.mediaDevices, ); diff --git a/src/room/InCallView.tsx b/src/room/InCallView.tsx index 5ad1634a7..6b1e57f84 100644 --- a/src/room/InCallView.tsx +++ b/src/room/InCallView.tsx @@ -567,25 +567,26 @@ export const InCallView: FC = ({ const footer = (
-
rendering > renders 1`] = ` d="M4 11a.97.97 0 0 1-.712-.287A.97.97 0 0 1 3 10V4q0-.424.288-.712A.97.97 0 0 1 4 3h6q.424 0 .713.288Q11 3.575 11 4v6q0 .424-.287.713A.97.97 0 0 1 10 11zm5-2V5H5v4zm5 12a.97.97 0 0 1-.713-.288A.97.97 0 0 1 13 20v-6q0-.424.287-.713A.97.97 0 0 1 14 13h6q.424 0 .712.287.288.288.288.713v6q0 .424-.288.712A.97.97 0 0 1 20 21zm5-2v-4h-4v4zM4 21a.97.97 0 0 1-.712-.288A.97.97 0 0 1 3 20v-6q0-.424.288-.713A.97.97 0 0 1 4 13h6q.424 0 .713.287.287.288.287.713v6q0 .424-.287.712A.97.97 0 0 1 10 21zm5-2v-4H5v4zm5-8a.97.97 0 0 1-.713-.287A.97.97 0 0 1 13 10V4q0-.424.287-.712A.97.97 0 0 1 14 3h6q.424 0 .712.288Q21 3.575 21 4v6q0 .424-.288.713A.97.97 0 0 1 20 11zm5-2V5h-4v4z" /> -
+
diff --git a/src/state/CallViewModel/CallViewModel.ts b/src/state/CallViewModel/CallViewModel.ts index fe65b68a6..7bfe46305 100644 --- a/src/state/CallViewModel/CallViewModel.ts +++ b/src/state/CallViewModel/CallViewModel.ts @@ -173,6 +173,8 @@ export interface CallViewModelOptions { windowSize$?: Behavior<{ width: number; height: number }>; /** The version & compatibility mode of MatrixRTC that we should use. */ matrixRTCMode$?: Behavior; + /** Optional behavior overriding for the screensharing, for testing */ + toggleScreensharing?: () => void; } // Do not play any sounds if the participant count has exceeded this @@ -1506,7 +1508,8 @@ export function createCallViewModel$( * Callback to toggle screen sharing. If null, screen sharing is not possible. */ // reassigned here to make it publicly accessible - const toggleScreenSharing = localMembership.toggleScreenSharing; + const toggleScreenSharing = + options.toggleScreensharing ?? localMembership.toggleScreenSharing; const errors$ = scope.behavior<{ transportError?: ElementCallError; From 3c039be7f2727a16af72a3d58343a31abd8f1908 Mon Sep 17 00:00:00 2001 From: Timo K Date: Tue, 14 Apr 2026 14:11:08 +0200 Subject: [PATCH 480/748] lint --- src/components/CallFooter.mdx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/CallFooter.mdx b/src/components/CallFooter.mdx index 4a69939b6..a8b960d4c 100644 --- a/src/components/CallFooter.mdx +++ b/src/components/CallFooter.mdx @@ -11,9 +11,9 @@ This can be done by using the same filename as the component With the help of Primary, Controls,Stories the overhead is minimal */} -import { Meta,Primary,Controls,Stories,Title,Subtitle } from '@storybook/addon-docs/blocks'; +import { Meta, Primary, Controls, Stories, Title, Subtitle } from '@storybook/addon-docs/blocks'; import * as CallFooterStories from './CallFooter.stories'; - + Call Footer From 2d5de234d2c6a69cd50604742c881cf5757c3775 Mon Sep 17 00:00:00 2001 From: Timo K Date: Tue, 14 Apr 2026 14:26:00 +0200 Subject: [PATCH 481/748] prettier --- src/components/CallFooter.mdx | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/src/components/CallFooter.mdx b/src/components/CallFooter.mdx index a8b960d4c..b94131a00 100644 --- a/src/components/CallFooter.mdx +++ b/src/components/CallFooter.mdx @@ -1,18 +1,24 @@ -{/* +{/** Copyright 2026 Element Creations Ltd. - SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial Please see LICENSE in the repository root for full details. -*/} +**/} -{/* +{/** This is a custom doc page overwriting the default autodocs tag. This can be done by using the same filename as the component With the help of Primary, Controls,Stories the overhead is minimal -*/} +**/} -import { Meta, Primary, Controls, Stories, Title, Subtitle } from '@storybook/addon-docs/blocks'; -import * as CallFooterStories from './CallFooter.stories'; +import { + Meta, + Primary, + Controls, + Stories, + Title, + Subtitle, +} from "@storybook/addon-docs/blocks"; +import * as CallFooterStories from "./CallFooter.stories"; @@ -28,4 +34,4 @@ The story summary here does not render the mobile layouts correctly. - + From 2ae1df467daa79addd0c603b1c07773363e33e4a Mon Sep 17 00:00:00 2001 From: Timo K Date: Tue, 14 Apr 2026 14:30:46 +0200 Subject: [PATCH 482/748] knip --- .storybook/main.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.storybook/main.ts b/.storybook/main.ts index 9a3f0b539..977eca73d 100644 --- a/.storybook/main.ts +++ b/.storybook/main.ts @@ -9,7 +9,7 @@ import type { StorybookConfig } from "@storybook/react-vite"; const config: StorybookConfig = { stories: ["../src/**/*.mdx", "../src/**/*.stories.@(js|jsx|mjs|ts|tsx)"], - addons: ["@storybook/addon-docs", "@storybook/addon-vitest"], + addons: ["@storybook/addon-docs"], framework: "@storybook/react-vite", }; export default config; From 57f12d3d1c5dc6af0815d8a593fa4d4c953d4935 Mon Sep 17 00:00:00 2001 From: Timo K Date: Tue, 14 Apr 2026 16:23:05 +0200 Subject: [PATCH 483/748] fix race in playwright sticky test --- playwright/reconnect.spec.ts | 2 +- playwright/spa-call-sticky.spec.ts | 13 +++++++++++++ 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/playwright/reconnect.spec.ts b/playwright/reconnect.spec.ts index 1a8f2c28d..e6d5f7150 100644 --- a/playwright/reconnect.spec.ts +++ b/playwright/reconnect.spec.ts @@ -13,7 +13,7 @@ test.skip( 'This test is not working on firefox, page.keyboard.press("Tab") not reliable in headless mode', ); -test("can only interact with header and footer while reconnecting", async ({ +test("can not interact with media tiles while reconnecting (only with header and footer)", async ({ page, }) => { await page.goto("/"); diff --git a/playwright/spa-call-sticky.spec.ts b/playwright/spa-call-sticky.spec.ts index 246b4a73a..65cf06ed1 100644 --- a/playwright/spa-call-sticky.spec.ts +++ b/playwright/spa-call-sticky.spec.ts @@ -29,6 +29,9 @@ async function setupTwoUserSpaCall( let androlHasSentStickyEvent = false; + const { promise: stickyAndrolPromise, resolve: stickyAndrolResolve } = + Promise.withResolvers(); + await interceptEventSend( page, // This room is not encrypted, so the event is sent in clear @@ -36,6 +39,9 @@ async function setupTwoUserSpaCall( (req) => { androlHasSentStickyEvent = androlHasSentStickyEvent || isStickySend(req.url()); + if (androlHasSentStickyEvent) { + stickyAndrolResolve(); + } }, ); @@ -53,6 +59,8 @@ async function setupTwoUserSpaCall( let pevaraHasSentStickyEvent = false; + const { promise: stickyPevaraPromise, resolve: stickyPevaraResolve } = + Promise.withResolvers(); await interceptEventSend( guestPage, // This room is not encrypted, so the event is sent in clear @@ -60,6 +68,9 @@ async function setupTwoUserSpaCall( (req) => { pevaraHasSentStickyEvent = pevaraHasSentStickyEvent || isStickySend(req.url()); + if (pevaraHasSentStickyEvent) { + stickyPevaraResolve(); + } }, ); @@ -70,7 +81,9 @@ async function setupTwoUserSpaCall( "2_0", ); // Assert both sides have sent sticky membership events + await stickyAndrolPromise; expect(androlHasSentStickyEvent).toEqual(true); + await stickyPevaraPromise; expect(pevaraHasSentStickyEvent).toEqual(true); return { guestPage }; From ed83672720415d812bc800a63f4af00de22fb8e0 Mon Sep 17 00:00:00 2001 From: Timo <16718859+toger5@users.noreply.github.com> Date: Tue, 14 Apr 2026 17:43:05 +0200 Subject: [PATCH 484/748] Update src/room/InCallView.tsx Co-authored-by: Robin --- src/room/InCallView.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/src/room/InCallView.tsx b/src/room/InCallView.tsx index cf445170c..2b13e08f3 100644 --- a/src/room/InCallView.tsx +++ b/src/room/InCallView.tsx @@ -683,6 +683,7 @@ export const InCallView: FC = ({ >
{showControls && + // Settings button is also shown in the app bar if present headerStyle !== HeaderStyle.AppBar && layout.type !== "pip" && ( From a069d28f3adb5179171bc7e62b601b8a094d587e Mon Sep 17 00:00:00 2001 From: Timo K Date: Tue, 14 Apr 2026 17:05:56 +0200 Subject: [PATCH 485/748] review: make appBar styling use IconButton (fix margins) --- src/AppBar.tsx | 11 ++++------- src/button/Button.tsx | 26 ++++++++++++++++---------- src/room/InCallView.tsx | 2 +- 3 files changed, 21 insertions(+), 18 deletions(-) diff --git a/src/AppBar.tsx b/src/AppBar.tsx index 72ee9285f..95cdb32be 100644 --- a/src/AppBar.tsx +++ b/src/AppBar.tsx @@ -16,7 +16,7 @@ import { useMemo, useState, } from "react"; -import { Button, Heading, Tooltip } from "@vector-im/compound-web"; +import { Button, Heading, IconButton, Tooltip } from "@vector-im/compound-web"; import { CollapseIcon } from "@vector-im/compound-design-tokens/assets/web/icons"; import { useTranslation } from "react-i18next"; @@ -68,12 +68,9 @@ export const AppBar: FC = ({ children }) => { > -
{recentsButtonInFooter && recentsButton} - +
; /** The version & compatibility mode of MatrixRTC that we should use. */ matrixRTCMode$?: Behavior; + mediaDeviceOverride?: MediaDevices; } // Do not play any sounds if the participant count has exceeded this diff --git a/src/utils/test-viewmodel.ts b/src/utils/test-viewmodel.ts index 8ab3c8870..6d77a802f 100644 --- a/src/utils/test-viewmodel.ts +++ b/src/utils/test-viewmodel.ts @@ -34,7 +34,6 @@ import { MockRTCSession, testScope, } from "./test"; -import { type MediaDevices } from "../state/MediaDevices"; import { aliceRtcMember, localRtcMember } from "./test-fixtures"; import { type RaisedHandInfo, type ReactionInfo } from "../reactions"; import { constant } from "../state/Behavior"; @@ -133,7 +132,6 @@ export function getBasicCallViewModelEnvironment( members: RoomMember[], initialRtcMemberships: CallMembership[] = [localRtcMember, aliceRtcMember], callViewModelOptions: Partial = {}, - mediaDevicesOverride?: MediaDevices, ): { vm: CallViewModel; rtcMemberships$: BehaviorSubject; @@ -154,7 +152,7 @@ export function getBasicCallViewModelEnvironment( testScope(), rtcSession.asMockedSession(), matrixRoom, - mediaDevicesOverride ?? mockMediaDevices({}), + callViewModelOptions.mediaDeviceOverride ?? mockMediaDevices({}), mockMuteStates(), { encryptionSystem: { kind: E2eeType.PER_PARTICIPANT }, From 32823aef926bff3c76375ac76c681759ae43fe8f Mon Sep 17 00:00:00 2001 From: Timo K Date: Tue, 14 Apr 2026 18:15:20 +0200 Subject: [PATCH 488/748] test and lints --- src/__snapshots__/AppBar.test.tsx.snap | 32 +++++++++++-------- src/button/Button.tsx | 26 +++++++-------- .../__snapshots__/InCallView.test.tsx.snap | 32 +++++++++++-------- 3 files changed, 49 insertions(+), 41 deletions(-) diff --git a/src/__snapshots__/AppBar.test.tsx.snap b/src/__snapshots__/AppBar.test.tsx.snap index 2dd608a60..7247c6b99 100644 --- a/src/__snapshots__/AppBar.test.tsx.snap +++ b/src/__snapshots__/AppBar.test.tsx.snap @@ -14,24 +14,28 @@ exports[`AppBar > renders 1`] = ` >
= (props) => { ); }; -interface SettingsButtonProps extends ComponentPropsWithoutRef<"button"> { - size?: "sm" | "lg"; -} -export const SettingsButton: FC = (props) => { - const { t } = useTranslation(); - const Icon = - platform === "android" ? OverflowVerticalIcon : OverflowHorizontalIcon; - return ( - - - - ); -}; +// interface SettingsButtonProps extends ComponentPropsWithoutRef<"button"> { +// size?: "sm" | "lg"; +// } +// const SettingsButton: FC = (props) => { +// const { t } = useTranslation(); +// const Icon = +// platform === "android" ? OverflowVerticalIcon : OverflowHorizontalIcon; +// return ( +// +// +// +// ); +// }; diff --git a/src/room/__snapshots__/InCallView.test.tsx.snap b/src/room/__snapshots__/InCallView.test.tsx.snap index 7ef7298b1..dafc85647 100644 --- a/src/room/__snapshots__/InCallView.test.tsx.snap +++ b/src/room/__snapshots__/InCallView.test.tsx.snap @@ -170,24 +170,28 @@ exports[`InCallView > rendering > renders 1`] = ` >
Date: Wed, 15 Apr 2026 14:43:02 +0000 Subject: [PATCH 504/748] Update dependency livekit-client to v2.18.2 --- yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/yarn.lock b/yarn.lock index cbb6b8ea1..ebb160949 100644 --- a/yarn.lock +++ b/yarn.lock @@ -11678,8 +11678,8 @@ __metadata: linkType: hard "livekit-client@npm:^2.18.1": - version: 2.18.1 - resolution: "livekit-client@npm:2.18.1" + version: 2.18.2 + resolution: "livekit-client@npm:2.18.2" dependencies: "@livekit/mutex": "npm:1.1.1" "@livekit/protocol": "npm:1.44.0" @@ -11692,7 +11692,7 @@ __metadata: webrtc-adapter: "npm:^9.0.1" peerDependencies: "@types/dom-mediacapture-record": ^1 - checksum: 10c0/087ffebf3265b1bae2d3346af46c6b03b693e6226dc8b28618de5784979db5354bd17d992589ac9e18a014ef38f05ee8d77aa108fe0638b325cefd23ea8675ba + checksum: 10c0/1a2cad00d23e35be2ff20272783d627b2ef1a3a418445eb6965e4003657ae3ff25e9af894ca01177e02b5481e686448420794ed0612beb713fb7c316c93b3635 languageName: node linkType: hard From cea32b86a3eae279b7b4728d99691c3451918189 Mon Sep 17 00:00:00 2001 From: Timo K Date: Wed, 15 Apr 2026 16:46:42 +0200 Subject: [PATCH 505/748] remove reactive url param for showFooter --- src/UrlParams.ts | 20 -------------------- src/state/CallViewModel/CallViewModel.ts | 17 +++++++---------- 2 files changed, 7 insertions(+), 30 deletions(-) diff --git a/src/UrlParams.ts b/src/UrlParams.ts index a256e0a43..3a9721198 100644 --- a/src/UrlParams.ts +++ b/src/UrlParams.ts @@ -14,13 +14,11 @@ import { type RTCNotificationType, } from "matrix-js-sdk/lib/matrixrtc"; import { pickBy } from "lodash-es"; -import { BehaviorSubject } from "rxjs"; import { Config } from "./config/Config"; import { type EncryptionSystem } from "./e2ee/sharedKeyManagement"; import { E2eeType } from "./e2ee/e2eeType"; import { platform } from "./Platform"; -import { type ObservableScope } from "./state/ObservableScope"; interface RoomIdentifier { roomAlias: string | null; @@ -620,24 +618,6 @@ export const useRoomIdentifier = (): RoomIdentifier => { ); }; -let urlParams$ = undefined as BehaviorSubject | undefined; -export const observerUrlParams$ = ( - scope: ObservableScope, -): BehaviorSubject => { - if (urlParams$ !== undefined) return urlParams$; - function updateUrlParams(): void { - console.log("[observerUrlParams$] update urlParams$"); - urlParams$!.next(getUrlParams()); - } - - urlParams$ = new BehaviorSubject(getUrlParams()); - window.addEventListener("hashchange", updateUrlParams); - scope.onEnd(() => { - window.removeEventListener("hashchange", updateUrlParams); - }); - return urlParams$; -}; - export function generateUrlSearchParams( roomId: string, encryptionSystem: EncryptionSystem, diff --git a/src/state/CallViewModel/CallViewModel.ts b/src/state/CallViewModel/CallViewModel.ts index 7bfe46305..28de16475 100644 --- a/src/state/CallViewModel/CallViewModel.ts +++ b/src/state/CallViewModel/CallViewModel.ts @@ -51,7 +51,6 @@ import { v4 as uuidv4 } from "uuid"; import { type IMembershipManager } from "matrix-js-sdk/lib/matrixrtc/IMembershipManager"; import { - and$, createToggle$, filterBehavior, generateItem, @@ -83,7 +82,7 @@ import { constant, type Behavior } from "../Behavior"; import { E2eeType } from "../../e2ee/e2eeType"; import { MatrixKeyProvider } from "../../e2ee/matrixKeyProvider"; import { type MuteStates } from "../MuteStates"; -import { getUrlParams, HeaderStyle, observerUrlParams$ } from "../../UrlParams"; +import { getUrlParams, HeaderStyle } from "../../UrlParams"; import { type ProcessorState } from "../../livekit/TrackProcessorContext"; import { ElementWidgetActions, widget } from "../../widget"; import { @@ -1317,13 +1316,9 @@ export function createCallViewModel$( windowMode$.pipe(map((mode) => mode !== "pip" && mode !== "flat")), ); - const urlParams$ = observerUrlParams$(scope); - const showFooterUrlParams$ = urlParams$.pipe( - map( - ({ header, showControls }) => - // with no header and no controls we always set showFooter to false. - !(header === HeaderStyle.None && showControls === false), - ), + const urlParams = getUrlParams(); + const showFooterUrlParams = !( + urlParams.header === HeaderStyle.None && urlParams.showControls === false ); const showFooterLayout$ = scope.behavior( windowMode$.pipe( @@ -1380,7 +1375,9 @@ export function createCallViewModel$( ), ); const showFooter$ = scope.behavior( - and$(showFooterLayout$, showFooterUrlParams$), + showFooterLayout$.pipe( + map((showFooter) => showFooter && showFooterUrlParams), + ), ); /** * Whether audio is currently being output through the earpiece. From 832c5784d4d4191adc317fa4ac744f4c06f0d214 Mon Sep 17 00:00:00 2001 From: Robin Date: Wed, 15 Apr 2026 19:51:13 +0200 Subject: [PATCH 506/748] Fix local screen share not appearing in one-on-one calls This was regressed by 9dfade68eed85e8a6df6c4ca1664b897fbdf1de7. --- src/state/CallViewModel/CallViewModel.ts | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/state/CallViewModel/CallViewModel.ts b/src/state/CallViewModel/CallViewModel.ts index 711e5e7e9..e0c55ee02 100644 --- a/src/state/CallViewModel/CallViewModel.ts +++ b/src/state/CallViewModel/CallViewModel.ts @@ -1078,9 +1078,10 @@ export function createCallViewModel$( ); const oneOnOneLayoutMedia$: Observable = - userMedia$.pipe( - switchMap((userMedia) => { - if (userMedia.length <= 2) { + combineLatest([userMedia$, screenShares$]).pipe( + switchMap(([userMedia, screenShares]) => { + // One-on-one layout only supports 2 user media, no screen shares + if (userMedia.length <= 2 && screenShares.length === 0) { const local = userMedia.find( (vm): vm is WrappedUserMediaViewModel & LocalUserMediaViewModel => vm.type === "user" && vm.local, From b03524e25f0a29ed35e4ffcb1dc6fadd51229b31 Mon Sep 17 00:00:00 2001 From: Robin Date: Wed, 15 Apr 2026 17:56:57 +0200 Subject: [PATCH 507/748] Make screen sharing work more like speaking marbles in tests This approach is more flexible in that it allows even the local participant to share their screen in CallViewModel tests, and more rigorous in that it ensures that application code is reacting specifically to track publications. --- src/state/CallViewModel/CallViewModel.test.ts | 39 +++++++++---------- .../CallViewModel/CallViewModelTestUtils.ts | 26 ++++++++----- 2 files changed, 35 insertions(+), 30 deletions(-) diff --git a/src/state/CallViewModel/CallViewModel.test.ts b/src/state/CallViewModel/CallViewModel.test.ts index 1fecd112f..93e1d991d 100644 --- a/src/state/CallViewModel/CallViewModel.test.ts +++ b/src/state/CallViewModel/CallViewModel.test.ts @@ -105,15 +105,7 @@ const dave = mockMatrixRoomMember(daveRtcMember, { rawDisplayName: "Dave" }); const daveId = `${dave.userId}:${daveRtcMember.deviceId}`; const localParticipant = mockLocalParticipant({ identity: "" }); -const aliceSharingScreen = mockRemoteParticipant({ - identity: aliceId, - isScreenShareEnabled: true, -}); const bobParticipant = mockRemoteParticipant({ identity: bobId }); -const bobSharingScreen = mockRemoteParticipant({ - identity: bobId, - isScreenShareEnabled: true, -}); const daveParticipant = mockRemoteParticipant({ identity: daveId }); export interface GridLayoutSummary { @@ -281,7 +273,8 @@ describe.each([ withTestScheduler(({ behavior, schedule, expectObservable }) => { // Start with no screen shares, then have Alice and Bob share their screens, // then return to no screen shares, then have just Alice share for a bit - const participantInputMarbles = " abcda-ba"; + const aliceSharingInputMarbles = " ny-n--yn"; + const bobSharingInputMarbles = " n-y-n---"; // While there are no screen shares, switch to spotlight manually, and then // switch back to grid at the end const modeInputMarbles = " -----s--g"; @@ -292,13 +285,12 @@ describe.each([ const expectedShowSpeakingMarbles = "y----nyny"; withCallViewModel( { - remoteParticipants$: behavior(participantInputMarbles, { - a: [aliceParticipant, bobParticipant], - b: [aliceSharingScreen, bobParticipant], - c: [aliceSharingScreen, bobSharingScreen], - d: [aliceParticipant, bobSharingScreen], - }), + remoteParticipants$: constant([aliceParticipant, bobParticipant]), rtcMembers$: constant([localRtcMember, aliceRtcMember, bobRtcMember]), + sharingScreen: new Map([ + [aliceParticipant, behavior(aliceSharingInputMarbles, yesNo)], + [bobParticipant, behavior(bobSharingInputMarbles, yesNo)], + ]), }, (vm) => { schedule(modeInputMarbles, { @@ -688,7 +680,7 @@ describe.each([ withCallViewModel( { remoteParticipants$: constant([ - aliceSharingScreen, + aliceParticipant, bobParticipant, daveParticipant, ]), @@ -702,6 +694,7 @@ describe.each([ [bobParticipant, behavior(bSpeakingInputMarbles, yesNo)], [daveParticipant, behavior(dSpeakingInputMarbles, yesNo)], ]), + sharingScreen: new Map([[aliceParticipant, constant(true)]]), }, (vm) => { schedule(modeInputMarbles, { @@ -856,26 +849,30 @@ describe.each([ withTestScheduler(({ behavior, expectObservable }) => { // iterate through a number of combinations of participants and MatrixRTC memberships // Bob never has an MatrixRTC membership - const scenarioInputMarbles = " abcdec"; + const participantInputMarbles = "abcd-c"; + // Bob even tries to share his screen at the end + const bobSharingInputMarbles = " n---yn"; // Bob should never be visible - const expectedLayoutMarbles = "a-bc-b"; + const expectedLayoutMarbles = " a-bc-b"; withCallViewModel( { - remoteParticipants$: behavior(scenarioInputMarbles, { + remoteParticipants$: behavior(participantInputMarbles, { a: [], b: [bobParticipant], c: [aliceParticipant, bobParticipant], d: [aliceParticipant, daveParticipant, bobParticipant], - e: [aliceParticipant, daveParticipant, bobSharingScreen], }), - rtcMembers$: behavior(scenarioInputMarbles, { + rtcMembers$: behavior(participantInputMarbles, { a: [localRtcMember], b: [localRtcMember], c: [localRtcMember, aliceRtcMember], d: [localRtcMember, aliceRtcMember, daveRtcMember], e: [localRtcMember, aliceRtcMember, daveRtcMember], }), + sharingScreen: new Map([ + [bobParticipant, behavior(bobSharingInputMarbles, yesNo)], + ]), }, (vm) => { vm.setGridMode("grid"); diff --git a/src/state/CallViewModel/CallViewModelTestUtils.ts b/src/state/CallViewModel/CallViewModelTestUtils.ts index 09a43fc30..431e691db 100644 --- a/src/state/CallViewModel/CallViewModelTestUtils.ts +++ b/src/state/CallViewModel/CallViewModelTestUtils.ts @@ -15,7 +15,7 @@ import { type Room as LivekitRoom, } from "livekit-client"; import { SyncState } from "matrix-js-sdk/lib/sync"; -import { BehaviorSubject, type Observable, map, of } from "rxjs"; +import { BehaviorSubject, combineLatest, map, of } from "rxjs"; import { onTestFinished, vi } from "vitest"; import { ClientEvent, type RoomMember, type MatrixClient } from "matrix-js-sdk"; import EventEmitter from "events"; @@ -68,7 +68,8 @@ export interface CallViewModelInputs { rtcMembers$: Behavior[]>; roomMembers: RoomMember[]; livekitConnectionState$: Behavior; - speaking: Map>; + speaking: Map>; + sharingScreen: Map>; mediaDevices: MediaDevices; initialSyncState: SyncState; windowSize$: Behavior<{ width: number; height: number }>; @@ -94,6 +95,7 @@ export function withCallViewModel(mode: MatrixRTCMode) { ConnectionState.Connected, ), speaking = new Map(), + sharingScreen = new Map(), mediaDevices = mockMediaDevices({}), initialSyncState = SyncState.Syncing, windowSize$ = constant({ width: 1000, height: 800 }), @@ -154,13 +156,19 @@ export function withCallViewModel(mode: MatrixRTCMode) { const eventsSpy = vi .spyOn(ComponentsCore, "observeParticipantEvents") .mockImplementation((p, ...eventTypes) => { - if (eventTypes.includes(ParticipantEvent.IsSpeakingChanged)) { - return (speaking.get(p) ?? of(false)).pipe( - map((s): Participant => ({ ...p, isSpeaking: s }) as Participant), - ); - } else { - return of(p); - } + return combineLatest([ + (eventTypes.includes(ParticipantEvent.IsSpeakingChanged) && + speaking.get(p)) || + constant(false), + (eventTypes.includes(ParticipantEvent.TrackPublished) && + sharingScreen.get(p)) || + constant(false), + ]).pipe( + map( + ([isSpeaking, isScreenShareEnabled]) => + ({ ...p, isSpeaking, isScreenShareEnabled }) as Participant, + ), + ); }); const roomEventSelectorSpy = vi From e8963effe2ff08a1aa81fa87bbab2228e22a9aa5 Mon Sep 17 00:00:00 2001 From: Robin Date: Wed, 15 Apr 2026 19:53:11 +0200 Subject: [PATCH 508/748] Test that the local user can see their own screen share To make this test work I had to extend the mocking of the CallViewModel tests to make a local connection object exist. --- src/initializer.test.ts | 2 +- src/state/CallViewModel/CallViewModel.test.ts | 79 ++++++++++++++++++- src/state/CallViewModel/CallViewModel.ts | 35 +++++--- .../CallViewModel/CallViewModelTestUtils.ts | 48 +++++++++-- src/utils/test.ts | 14 ++++ 5 files changed, 154 insertions(+), 24 deletions(-) diff --git a/src/initializer.test.ts b/src/initializer.test.ts index 0e43ed1f6..6439c015c 100644 --- a/src/initializer.test.ts +++ b/src/initializer.test.ts @@ -18,7 +18,7 @@ import { import { mockConfig } from "./utils/test"; -const sentryInitSpy = vi.fn(); +const sentryInitSpy = vi.hoisted(() => vi.fn()); // Place the mock after the spy is defined vi.mock("@sentry/react", () => ({ diff --git a/src/state/CallViewModel/CallViewModel.test.ts b/src/state/CallViewModel/CallViewModel.test.ts index 93e1d991d..cb528f684 100644 --- a/src/state/CallViewModel/CallViewModel.test.ts +++ b/src/state/CallViewModel/CallViewModel.test.ts @@ -36,7 +36,6 @@ import { deepCompare } from "matrix-js-sdk/lib/utils"; import { type Layout } from "../layout-types.ts"; import { - mockLocalParticipant, mockMatrixRoomMember, mockRemoteParticipant, withTestScheduler, @@ -61,7 +60,10 @@ import { import { MediaDevices } from "../MediaDevices.ts"; import { getValue } from "../../utils/observable.ts"; import { type Behavior, constant } from "../Behavior.ts"; -import { withCallViewModel as withCallViewModelInMode } from "./CallViewModelTestUtils.ts"; +import { + localParticipant, + withCallViewModel as withCallViewModelInMode, +} from "./CallViewModelTestUtils.ts"; import { MatrixRTCMode } from "../../settings/settings.ts"; import { initializeWidget } from "../../widget.ts"; @@ -104,7 +106,6 @@ const dave = mockMatrixRoomMember(daveRtcMember, { rawDisplayName: "Dave" }); const daveId = `${dave.userId}:${daveRtcMember.deviceId}`; -const localParticipant = mockLocalParticipant({ identity: "" }); const bobParticipant = mockRemoteParticipant({ identity: bobId }); const daveParticipant = mockRemoteParticipant({ identity: daveId }); @@ -269,7 +270,7 @@ describe.each([ }); }); - test("screen sharing activates spotlight layout", () => { + test("remote screen sharing activates spotlight layout", () => { withTestScheduler(({ behavior, schedule, expectObservable }) => { // Start with no screen shares, then have Alice and Bob share their screens, // then return to no screen shares, then have just Alice share for a bit @@ -350,6 +351,76 @@ describe.each([ }); }); + test("local screen sharing stays in grid layout", () => { + withTestScheduler(({ behavior, expectObservable }) => { + // Local participant shares their screen, then stops sharing + const sharingInputMarbles = " nyn"; + // Layout should show the screen share but stay in type: "grid" + const expectedLayoutMarbles = "aba"; + withCallViewModel( + { + remoteParticipants$: constant([aliceParticipant, bobParticipant]), + rtcMembers$: constant([localRtcMember, aliceRtcMember, bobRtcMember]), + sharingScreen: new Map([ + [localParticipant, behavior(sharingInputMarbles, yesNo)], + ]), + }, + (vm) => { + expectObservable(summarizeLayout$(vm.layout$)).toBe( + expectedLayoutMarbles, + { + a: { + type: "grid", + spotlight: undefined, + grid: [`${localId}:0`, `${aliceId}:0`, `${bobId}:0`], + }, + b: { + type: "grid", + spotlight: [`${localId}:0:screen-share`], + grid: [`${localId}:0`, `${aliceId}:0`, `${bobId}:0`], + }, + }, + ); + }, + ); + }); + }); + + test("local screen sharing in one-on-one call activates grid layout", () => { + withTestScheduler(({ behavior, expectObservable }) => { + // Local participant shares their screen, then stops sharing + const sharingInputMarbles = " nyn"; + // Layout should switch to grid layout then back to one-on-one layout + const expectedLayoutMarbles = "aba"; + withCallViewModel( + { + remoteParticipants$: constant([aliceParticipant]), + rtcMembers$: constant([localRtcMember, aliceRtcMember]), + sharingScreen: new Map([ + [localParticipant, behavior(sharingInputMarbles, yesNo)], + ]), + }, + (vm) => { + expectObservable(summarizeLayout$(vm.layout$)).toBe( + expectedLayoutMarbles, + { + a: { + type: "one-on-one", + pip: `${localId}:0`, + spotlight: `${aliceId}:0`, + }, + b: { + type: "grid", + spotlight: [`${localId}:0:screen-share`], + grid: [`${localId}:0`, `${aliceId}:0`], + }, + }, + ); + }, + ); + }); + }); + test("participants stay in the same order unless to appear/disappear", () => { withTestScheduler(({ behavior, schedule, expectObservable }) => { const visibilityInputMarbles = "a"; diff --git a/src/state/CallViewModel/CallViewModel.ts b/src/state/CallViewModel/CallViewModel.ts index e0c55ee02..d33392e6a 100644 --- a/src/state/CallViewModel/CallViewModel.ts +++ b/src/state/CallViewModel/CallViewModel.ts @@ -105,12 +105,16 @@ import { import { createLocalTransport$, JwtEndpointVersion, + type LocalTransport, } from "./localMember/LocalTransport.ts"; import { createMemberships$, membershipsAndTransports$, } from "../SessionBehaviors.ts"; -import { ECConnectionFactory } from "./remoteMembers/ConnectionFactory.ts"; +import { + type ConnectionFactory, + ECConnectionFactory, +} from "./remoteMembers/ConnectionFactory.ts"; import { type ConnectionManagerData, createConnectionManager$, @@ -170,6 +174,10 @@ export interface CallViewModelOptions { connectionState$?: Behavior; /** Optional behavior overriding the computed window size, mainly for testing purposes. */ windowSize$?: Behavior<{ width: number; height: number }>; + /** Optional value overriding the local transport, for testing purposes. */ + localTransport?: LocalTransport; + /** Optional value overriding the connection factory, for testing purposes. */ + connectionFactory?: ConnectionFactory; /** The version & compatibility mode of MatrixRTC that we should use. */ matrixRTCMode$?: Behavior; } @@ -441,6 +449,7 @@ export function createCallViewModel$( // Re-create LocalTransport whenever the mode changes (mode) => ({ keys: [mode], data: undefined }), (scope, _data$, mode) => + options.localTransport ?? createLocalTransport$({ scope: scope, memberships$: memberships$, @@ -467,17 +476,19 @@ export function createCallViewModel$( ), ); - const connectionFactory = new ECConnectionFactory( - client, - matrixRoom.roomId, - mediaDevices, - trackProcessorState$, - livekitKeyProvider, - getUrlParams().controlledAudioDevices, - options.livekitRoomFactory, - getUrlParams().echoCancellation, - getUrlParams().noiseSuppression, - ); + const connectionFactory = + options.connectionFactory ?? + new ECConnectionFactory( + client, + matrixRoom.roomId, + mediaDevices, + trackProcessorState$, + livekitKeyProvider, + getUrlParams().controlledAudioDevices, + options.livekitRoomFactory, + getUrlParams().echoCancellation, + getUrlParams().noiseSuppression, + ); const connectionManager = createConnectionManager$({ scope: scope, diff --git a/src/state/CallViewModel/CallViewModelTestUtils.ts b/src/state/CallViewModel/CallViewModelTestUtils.ts index 431e691db..9685c709d 100644 --- a/src/state/CallViewModel/CallViewModelTestUtils.ts +++ b/src/state/CallViewModel/CallViewModelTestUtils.ts @@ -30,7 +30,10 @@ import { type CallViewModelOptions, } from "./CallViewModel"; import { + exampleSfuConfig, + exampleTransport, mockConfig, + MockConnection, mockLivekitRoom, mockLocalParticipant, mockMatrixRoom, @@ -75,7 +78,7 @@ export interface CallViewModelInputs { windowSize$: Behavior<{ width: number; height: number }>; } -const localParticipant = mockLocalParticipant({ identity: "" }); +export const localParticipant = mockLocalParticipant({ identity: "" }); export function withCallViewModel(mode: MatrixRTCMode) { return ( @@ -180,6 +183,13 @@ export function withCallViewModel(mode: MatrixRTCMode) { ); const reactions$ = new BehaviorSubject>({}); + const livekitRoomFactory = (): LivekitRoom => + mockLivekitRoom({ + localParticipant, + disconnect: async () => Promise.resolve(), + setE2EEEnabled: async () => Promise.resolve(), + }); + const vm = createCallViewModel$( testScope(), rtcSession.asMockedSession(), @@ -189,14 +199,38 @@ export function withCallViewModel(mode: MatrixRTCMode) { { encryptionSystem: { kind: E2eeType.PER_PARTICIPANT }, autoLeaveWhenOthersLeft: false, - livekitRoomFactory: (): LivekitRoom => - mockLivekitRoom({ - localParticipant, - disconnect: async () => Promise.resolve(), - setE2EEEnabled: async () => Promise.resolve(), - }), + livekitRoomFactory, connectionState$, windowSize$, + localTransport: { + active$: constant({ + transport: exampleTransport, + sfuConfig: exampleSfuConfig, + }), + advertised$: constant(exampleTransport), + }, + connectionFactory: { + createConnection( + scope, + transport, + ownMembershipIdentity, + logger, + sfuConfig, + ) { + return new MockConnection( + { + scope, + transport, + ownMembershipIdentity, + existingSFUConfig: sfuConfig, + client: room.client, + roomId: room.roomId, + livekitRoomFactory, + }, + logger, + ); + }, + }, matrixRTCMode$: constant(mode), ...options, }, diff --git a/src/utils/test.ts b/src/utils/test.ts index f8d420cf2..af372bfb6 100644 --- a/src/utils/test.ts +++ b/src/utils/test.ts @@ -74,6 +74,8 @@ import { createRemoteScreenShare, type RemoteScreenShareViewModel, } from "../state/media/RemoteScreenShareViewModel"; +import { Connection } from "../state/CallViewModel/remoteMembers/Connection"; +import { type SFUConfig } from "../livekit/openIDSFU"; export function withFakeTimers(continuation: () => void): void { vi.useFakeTimers(); @@ -210,6 +212,13 @@ export const exampleTransport: LivekitTransport = { livekit_alias: "!alias:example.org", }; +export const exampleSfuConfig: SFUConfig = { + jwt: "foo", + livekitAlias: "bar", + livekitIdentity: "baz", + url: "bro", +}; + export function mockRtcMembership( user: string | RoomMember, deviceId: string, @@ -564,3 +573,8 @@ export function mockMuteStates( videoEnabled: false, }); } + +export class MockConnection extends Connection { + public async start(): Promise {} + public async stop(): Promise {} +} From d31a2a4fdddcd176ed188d3d77bf3447bff85c04 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 16 Apr 2026 07:29:49 +0000 Subject: [PATCH 509/748] Update dependency livekit-client to v2.18.3 (#3883) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- yarn.lock | 19 +++++-------------- 1 file changed, 5 insertions(+), 14 deletions(-) diff --git a/yarn.lock b/yarn.lock index ebb160949..484f052ab 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3331,16 +3331,7 @@ __metadata: languageName: node linkType: hard -"@livekit/protocol@npm:1.44.0": - version: 1.44.0 - resolution: "@livekit/protocol@npm:1.44.0" - dependencies: - "@bufbuild/protobuf": "npm:^1.10.0" - checksum: 10c0/f547a5ee586cae002ed2834f0a823573e38887562dbc793e261791b0572472c6732262a5466c96082464575a3248a4c6cb0428420418e834cdbef1b202cddedf - languageName: node - linkType: hard - -"@livekit/protocol@npm:^1.42.2": +"@livekit/protocol@npm:1.45.3, @livekit/protocol@npm:^1.42.2": version: 1.45.3 resolution: "@livekit/protocol@npm:1.45.3" dependencies: @@ -11678,11 +11669,11 @@ __metadata: linkType: hard "livekit-client@npm:^2.18.1": - version: 2.18.2 - resolution: "livekit-client@npm:2.18.2" + version: 2.18.3 + resolution: "livekit-client@npm:2.18.3" dependencies: "@livekit/mutex": "npm:1.1.1" - "@livekit/protocol": "npm:1.44.0" + "@livekit/protocol": "npm:1.45.3" events: "npm:^3.3.0" jose: "npm:^6.1.0" loglevel: "npm:^1.9.2" @@ -11692,7 +11683,7 @@ __metadata: webrtc-adapter: "npm:^9.0.1" peerDependencies: "@types/dom-mediacapture-record": ^1 - checksum: 10c0/1a2cad00d23e35be2ff20272783d627b2ef1a3a418445eb6965e4003657ae3ff25e9af894ca01177e02b5481e686448420794ed0612beb713fb7c316c93b3635 + checksum: 10c0/8240e0f971f50dcf96a65938208769fac79da8da944e30a63d2c358ae090c0c66f0363201aed5d772c43a67276cf2a4b33dfc2d8c12460f5ef4611f97d7596fc languageName: node linkType: hard From 0dcd7610807685eeffc79176d835759895708929 Mon Sep 17 00:00:00 2001 From: Timo K Date: Thu, 16 Apr 2026 11:20:24 +0200 Subject: [PATCH 510/748] only warn about app bar provider missing on mobile --- src/AppBar.tsx | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/AppBar.tsx b/src/AppBar.tsx index 6135a3a89..9939f9505 100644 --- a/src/AppBar.tsx +++ b/src/AppBar.tsx @@ -117,6 +117,10 @@ export function useAppBarHidden(hidden: boolean): void { if (setHidden !== undefined) { setHidden(hidden); return (): void => setHidden(false); + } else if (platform !== "desktop") { + logger.warn( + "[AppBar] useAppBarHidden called without AppBarContext provider, this will have no effect", + ); } }, [setHidden, hidden]); } @@ -132,7 +136,7 @@ export function useAppBarSecondaryButton(button: ReactNode): void { if (setSecondaryButton !== undefined) { setSecondaryButton(button); return (): void => setSecondaryButton(""); - } else { + } else if (platform !== "desktop") { logger.warn( "[AppBar] useAppBarSecondaryButton called without AppBarContext provider, this will have no effect", ); From 5657036f2fb410d168767736651907526c9a5d87 Mon Sep 17 00:00:00 2001 From: fkwp Date: Thu, 16 Apr 2026 17:02:07 +0200 Subject: [PATCH 511/748] Bump matrix js-sdk to support latest MSC4195 update --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index e4abd723e..4d1f7f14c 100644 --- a/package.json +++ b/package.json @@ -110,7 +110,7 @@ "livekit-client": "^2.18.1", "lodash-es": "^4.17.21", "loglevel": "^1.9.1", - "matrix-js-sdk": "matrix-org/matrix-js-sdk#6e3efef0c5f660df47cf00874927dec1c75cc3cf", + "matrix-js-sdk": "matrix-org/matrix-js-sdk#ca5655bced1cbb215ac1c18e179384a069d98b0a", "matrix-widget-api": "^1.16.1", "node-stdlib-browser": "^1.3.1", "normalize.css": "^8.0.1", From 17ad20cd09b73cb6d07de5c7f87884203983440f Mon Sep 17 00:00:00 2001 From: fkwp Date: Fri, 17 Apr 2026 11:07:31 +0200 Subject: [PATCH 512/748] switching from yarn to pnpm --- .github/workflows/build-element-call.yaml | 8 +- .github/workflows/lint.yaml | 16 +- .github/workflows/test.yaml | 16 +- .github/workflows/translations-download.yaml | 6 +- .yarn/plugins/linker.cjs | 91 - .yarnrc.yml | 3 - package.json | 45 +- pnpm-lock.yaml | 17484 +++++++++++++++++ scripts/dockerbuild.sh | 4 +- scripts/playwright-webserver-command.sh | 4 +- yarn.lock | 16635 ---------------- 11 files changed, 17535 insertions(+), 16777 deletions(-) delete mode 100644 .yarn/plugins/linker.cjs delete mode 100644 .yarnrc.yml create mode 100644 pnpm-lock.yaml delete mode 100644 yarn.lock diff --git a/.github/workflows/build-element-call.yaml b/.github/workflows/build-element-call.yaml index 3ddabb0b6..190cdfdb1 100644 --- a/.github/workflows/build-element-call.yaml +++ b/.github/workflows/build-element-call.yaml @@ -37,15 +37,15 @@ jobs: persist-credentials: false - name: Enable Corepack run: corepack enable - - name: Yarn cache + - name: pnpm cache uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4 with: - cache: "yarn" + cache: "pnpm" node-version-file: ".node-version" - name: Install dependencies - run: "yarn install --immutable" + run: "pnpm install --frozen-lockfile" - name: Build Element Call - run: yarn run build:"$PACKAGE":"$BUILD_MODE" + run: pnpm run build:"$PACKAGE":"$BUILD_MODE" env: SENTRY_ORG: ${{ secrets.SENTRY_ORG }} SENTRY_PROJECT: ${{ secrets.SENTRY_PROJECT }} diff --git a/.github/workflows/lint.yaml b/.github/workflows/lint.yaml index 763d2eacb..60b9095eb 100644 --- a/.github/workflows/lint.yaml +++ b/.github/workflows/lint.yaml @@ -12,20 +12,20 @@ jobs: persist-credentials: false - name: Enable Corepack run: corepack enable - - name: Yarn cache + - name: pnpm cache uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4 with: - cache: "yarn" + cache: "pnpm" node-version-file: ".node-version" - name: Install dependencies - run: "yarn install --immutable" + run: "pnpm install --frozen-lockfile" - name: Prettier - run: "yarn run prettier:check" + run: "pnpm run prettier:check" - name: i18n - run: "yarn run i18n:check" + run: "pnpm run i18n:check" - name: ESLint - run: "yarn run lint:eslint" + run: "pnpm run lint:eslint" - name: Type check - run: "yarn run lint:types" + run: "pnpm run lint:types" - name: Dead code analysis - run: "yarn run lint:knip" + run: "pnpm run lint:knip" diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml index 9848dc1d1..c436c5eed 100644 --- a/.github/workflows/test.yaml +++ b/.github/workflows/test.yaml @@ -14,15 +14,15 @@ jobs: persist-credentials: false - name: Enable Corepack run: corepack enable - - name: Yarn cache + - name: pnpm cache uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4 with: - cache: "yarn" + cache: "pnpm" node-version-file: ".node-version" - name: Install dependencies - run: "yarn install --immutable" + run: "pnpm install --frozen-lockfile" - name: Vitest - run: "yarn run test:coverage" + run: "pnpm run test:coverage" - name: Upload to codecov uses: codecov/codecov-action@75cd11691c0faa626561e295848008c8a7dddffe # v5 env: @@ -42,12 +42,12 @@ jobs: run: corepack enable - uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4 with: - cache: "yarn" + cache: "pnpm" node-version-file: ".node-version" - name: Install dependencies - run: yarn install --immutable + run: pnpm install --frozen-lockfile - name: Install Playwright Browsers - run: yarn playwright install --with-deps + run: pnpm exec playwright install --with-deps - name: Run backend components run: | docker compose -f playwright-backend-docker-compose.yml -f playwright-backend-docker-compose.override.yml pull @@ -56,7 +56,7 @@ jobs: - name: Run Playwright tests env: USE_DOCKER: 1 - run: yarn playwright test + run: pnpm exec playwright test - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 if: ${{ !cancelled() }} with: diff --git a/.github/workflows/translations-download.yaml b/.github/workflows/translations-download.yaml index ad9f46526..6339e378d 100644 --- a/.github/workflows/translations-download.yaml +++ b/.github/workflows/translations-download.yaml @@ -22,11 +22,11 @@ jobs: - uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4 with: - cache: "yarn" + cache: "pnpm" node-version-file: ".node-version" - name: Install Deps - run: "yarn install --immutable" + run: "pnpm install --frozen-lockfile" - name: Prune i18n run: "rm -R locales" @@ -40,7 +40,7 @@ jobs: run: "sudo chown runner:docker -R locales" - name: Prettier - run: yarn prettier:format + run: pnpm prettier:format - name: Create Pull Request id: cpr diff --git a/.yarn/plugins/linker.cjs b/.yarn/plugins/linker.cjs deleted file mode 100644 index cf7181f9a..000000000 --- a/.yarn/plugins/linker.cjs +++ /dev/null @@ -1,91 +0,0 @@ -/* -Copyright 2025 New Vector Ltd. - -SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial -Please see LICENSE in the repository root for full details. -*/ - -module.exports = { - name: "linker", - factory: (require) => ({ - hooks: { - // Yarn's plugin system is very light on documentation. The best we have - // for this hook is simply the type definition in - // https://github.com/yarnpkg/berry/blob/master/packages/yarnpkg-core/sources/Plugin.ts - registerPackageExtensions: async (config, registerPackageExtension) => { - const { structUtils } = require("@yarnpkg/core"); - const { parseSyml } = require("@yarnpkg/parsers"); - const path = require("path"); - const fs = require("fs"); - const process = require("process"); - - // Create a descriptor that we can use to target our direct dependencies - const projectPath = config.projectCwd - .replace(/\\/g, "/") - .replace("/C:/", "C:/"); - const manifestPath = path.join(projectPath, "package.json"); - const manifest = JSON.parse(fs.readFileSync(manifestPath, "utf8")); - const selfDescriptor = structUtils.parseDescriptor( - `${manifest.name}@*`, - true, - ); - - // Load the list of linked packages - const linksPath = path.join(projectPath, ".links.yaml"); - let linksFile; - try { - linksFile = fs.readFileSync(linksPath, "utf8"); - } catch (e) { - return; // File doesn't exist, there's nothing to link - } - let links; - try { - links = parseSyml(linksFile); - } catch (e) { - console.error(".links.yaml has invalid syntax", e); - process.exit(1); - } - - // Resolve paths and turn them into a Yarn package extension - const overrides = Object.fromEntries( - Object.entries(links).map(([name, link]) => [ - name, - `portal:${path.resolve(config.projectCwd, link)}`, - ]), - ); - const overrideIdentHashes = new Set(); - for (const name of Object.keys(overrides)) - overrideIdentHashes.add( - structUtils.parseDescriptor(`${name}@*`, true).identHash, - ); - - // Extend our own package's dependencies with these local overrides - registerPackageExtension(selfDescriptor, { dependencies: overrides }); - - // Filter out the original dependencies from the package spec so Yarn - // actually respects the overrides - const filterDependencies = (original) => { - const pkg = structUtils.copyPackage(original); - pkg.dependencies = new Map( - Array.from(pkg.dependencies.entries()).filter( - ([, value]) => !overrideIdentHashes.has(value.identHash), - ), - ); - return pkg; - }; - - // Patch Yarn's own normalizePackage method to use the above filter - const originalNormalizePackage = config.normalizePackage; - config.normalizePackage = function (pkg, extensions) { - return originalNormalizePackage.call( - this, - pkg.identHash === selfDescriptor.identHash - ? filterDependencies(pkg) - : pkg, - extensions, - ); - }; - }, - }, - }), -}; diff --git a/.yarnrc.yml b/.yarnrc.yml deleted file mode 100644 index 538de0e70..000000000 --- a/.yarnrc.yml +++ /dev/null @@ -1,3 +0,0 @@ -nodeLinker: node-modules -plugins: - - .yarn/plugins/linker.cjs diff --git a/package.json b/package.json index 4d1f7f14c..8225419ba 100644 --- a/package.json +++ b/package.json @@ -3,23 +3,23 @@ "version": "0.0.0", "type": "module", "scripts": { - "dev": "yarn dev:full", + "dev": "pnpm dev:full", "dev:full": "vite", "dev:embedded": "vite --config vite-embedded.config.js", - "build": "yarn build:full", + "build": "pnpm build:full", "build:full": "NODE_OPTIONS=--max-old-space-size=16384 vite build", - "build:full:production": "yarn build:full", - "build:full:development": "yarn build:full --mode development", - "build:embedded": "yarn build:full --config vite-embedded.config.js", - "build:embedded:production": "yarn build:embedded", - "build:embedded:development": "yarn build:embedded --mode development", - "build:sdk:development": "yarn build:sdk --mode development", - "build:sdk": "yarn build:full --config vite-sdk.config.js", - "build:sdk:production": "yarn build:sdk", + "build:full:production": "pnpm build:full", + "build:full:development": "pnpm build:full --mode development", + "build:embedded": "pnpm build:full --config vite-embedded.config.js", + "build:embedded:production": "pnpm build:embedded", + "build:embedded:development": "pnpm build:embedded --mode development", + "build:sdk:development": "pnpm build:sdk --mode development", + "build:sdk": "pnpm build:full --config vite-sdk.config.js", + "build:sdk:production": "pnpm build:sdk", "serve": "vite preview", "prettier:check": "prettier -c .", "prettier:format": "prettier -w .", - "lint": "yarn lint:types && yarn lint:eslint && yarn lint:knip", + "lint": "pnpm lint:types && pnpm lint:eslint && pnpm lint:knip", "lint:eslint": "eslint --max-warnings 0 src playwright", "lint:eslint-fix": "eslint --max-warnings 0 src playwright --fix", "lint:knip": "knip", @@ -31,7 +31,7 @@ "backend": "docker-compose -f dev-backend-docker-compose.yml up", "backend-playwright": "docker-compose -f playwright-backend-docker-compose.yml -f playwright-backend-docker-compose.override.yml up", "test:playwright": "playwright test", - "test:playwright:open": "yarn test:playwright --ui", + "test:playwright:open": "pnpm test:playwright --ui", "links:enable": "mv .links.disabled.yaml .links.yaml & touch .links.yaml", "links:disable": "mv .links.yaml .links.disabled.yaml", "storybook": "storybook dev -p 6006", @@ -142,14 +142,17 @@ "vitest": "^4.0.18", "vitest-axe": "^1.0.0-pre.3" }, - "resolutions": { - "@livekit/components-core/rxjs": "^7.8.1", - "@livekit/track-processors/@mediapipe/tasks-vision": "^0.10.18", - "minimatch": "^10.2.3", - "tar": "^7.5.11", - "glob": "^10.5.0", - "qs": "^6.14.1", - "js-yaml": "^4.1.1" + "pnpm": { + "overrides": { + "@livekit/components-core>rxjs": "^7.8.1", + "@livekit/track-processors>@mediapipe/tasks-vision": "^0.10.18", + "minimatch": "^10.2.3", + "tar": "^7.5.11", + "glob": "^10.5.0", + "qs": "^6.14.1", + "js-yaml": "^4.1.1", + "esbuild": "^0.27.7" + } }, - "packageManager": "yarn@4.7.0" + "packageManager": "pnpm@9.0.0" } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml new file mode 100644 index 000000000..16eaa2c90 --- /dev/null +++ b/pnpm-lock.yaml @@ -0,0 +1,17484 @@ +lockfileVersion: "9.0" + +settings: + autoInstallPeers: true + excludeLinksFromLockfile: false + +overrides: + "@livekit/components-core>rxjs": ^7.8.1 + "@livekit/track-processors>@mediapipe/tasks-vision": ^0.10.18 + minimatch: ^10.2.3 + tar: ^7.5.11 + glob: ^10.5.0 + qs: ^6.14.1 + js-yaml: ^4.1.1 + esbuild: ^0.27.7 + +importers: + .: + devDependencies: + "@babel/core": + specifier: ^7.16.5 + version: 7.29.0 + "@babel/preset-env": + specifier: ^7.22.20 + version: 7.29.2(@babel/core@7.29.0) + "@babel/preset-react": + specifier: ^7.22.15 + version: 7.28.5(@babel/core@7.29.0) + "@babel/preset-typescript": + specifier: ^7.23.0 + version: 7.28.5(@babel/core@7.29.0) + "@codecov/vite-plugin": + specifier: ^1.3.0 + version: 1.9.1(vite@8.0.8(@types/node@24.12.2)(esbuild@0.27.7)(jiti@2.6.1)(sass@1.99.0)(terser@5.46.1)(yaml@2.8.3)) + "@fontsource/inconsolata": + specifier: ^5.1.0 + version: 5.2.8 + "@fontsource/inter": + specifier: ^5.1.0 + version: 5.2.8 + "@formatjs/intl-durationformat": + specifier: ^0.10.0 + version: 0.10.4 + "@formatjs/intl-segmenter": + specifier: ^11.7.3 + version: 11.7.12 + "@livekit/components-core": + specifier: ^0.12.0 + version: 0.12.13(livekit-client@2.18.3(@types/dom-mediacapture-record@1.0.22))(tslib@2.8.1) + "@livekit/components-react": + specifier: ^2.0.0 + version: 2.9.20(livekit-client@2.18.3(@types/dom-mediacapture-record@1.0.22))(react-dom@19.2.5(react@19.2.5))(react@19.2.5)(tslib@2.8.1) + "@livekit/protocol": + specifier: ^1.42.2 + version: 1.45.3 + "@livekit/track-processors": + specifier: ^0.7.1 + version: 0.7.2(@types/dom-mediacapture-transform@0.1.11)(livekit-client@2.18.3(@types/dom-mediacapture-record@1.0.22)) + "@mediapipe/tasks-vision": + specifier: ^0.10.18 + version: 0.10.34 + "@playwright/test": + specifier: ^1.57.0 + version: 1.59.1 + "@radix-ui/react-dialog": + specifier: ^1.0.4 + version: 1.1.15(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5) + "@radix-ui/react-slider": + specifier: ^1.1.2 + version: 1.3.6(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5) + "@radix-ui/react-visually-hidden": + specifier: ^1.0.3 + version: 1.2.4(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5) + "@react-spring/web": + specifier: ^10.0.0 + version: 10.0.3(react-dom@19.2.5(react@19.2.5))(react@19.2.5) + "@sentry/react": + specifier: ^8.0.0 + version: 8.55.1(react@19.2.5) + "@sentry/vite-plugin": + specifier: ^3.0.0 + version: 3.6.1 + "@storybook/addon-docs": + specifier: ^10.3.3 + version: 10.3.5(@types/react@19.2.14)(esbuild@0.27.7)(storybook@10.3.5(@testing-library/dom@10.4.1)(prettier@3.8.3)(react-dom@19.2.5(react@19.2.5))(react@19.2.5))(vite@8.0.8(@types/node@24.12.2)(esbuild@0.27.7)(jiti@2.6.1)(sass@1.99.0)(terser@5.46.1)(yaml@2.8.3)) + "@storybook/react-vite": + specifier: ^10.3.3 + version: 10.3.5(esbuild@0.27.7)(react-dom@19.2.5(react@19.2.5))(react@19.2.5)(storybook@10.3.5(@testing-library/dom@10.4.1)(prettier@3.8.3)(react-dom@19.2.5(react@19.2.5))(react@19.2.5))(typescript@5.9.3)(vite@8.0.8(@types/node@24.12.2)(esbuild@0.27.7)(jiti@2.6.1)(sass@1.99.0)(terser@5.46.1)(yaml@2.8.3)) + "@stylistic/eslint-plugin": + specifier: ^3.0.0 + version: 3.1.0(eslint@8.57.1)(typescript@5.9.3) + "@testing-library/dom": + specifier: ^10.1.0 + version: 10.4.1 + "@testing-library/jest-dom": + specifier: ^6.6.3 + version: 6.9.1 + "@testing-library/react": + specifier: ^16.0.0 + version: 16.3.2(@testing-library/dom@10.4.1)(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5) + "@testing-library/user-event": + specifier: ^14.5.1 + version: 14.6.1(@testing-library/dom@10.4.1) + "@types/content-type": + specifier: ^1.1.5 + version: 1.1.9 + "@types/grecaptcha": + specifier: ^3.0.9 + version: 3.0.9 + "@types/jsdom": + specifier: ^21.1.7 + version: 21.1.7 + "@types/lodash-es": + specifier: ^4.17.12 + version: 4.17.12 + "@types/node": + specifier: ^24.0.0 + version: 24.12.2 + "@types/pako": + specifier: ^2.0.3 + version: 2.0.4 + "@types/qrcode": + specifier: ^1.5.5 + version: 1.5.6 + "@types/react": + specifier: ^19.0.0 + version: 19.2.14 + "@types/react-dom": + specifier: ^19.0.0 + version: 19.2.3(@types/react@19.2.14) + "@types/sdp-transform": + specifier: ^2.4.5 + version: 2.15.0 + "@types/uuid": + specifier: "10" + version: 10.0.0 + "@typescript-eslint/eslint-plugin": + specifier: ^8.31.0 + version: 8.58.2(@typescript-eslint/parser@8.58.2(eslint@8.57.1)(typescript@5.9.3))(eslint@8.57.1)(typescript@5.9.3) + "@typescript-eslint/parser": + specifier: ^8.31.0 + version: 8.58.2(eslint@8.57.1)(typescript@5.9.3) + "@use-gesture/react": + specifier: ^10.2.11 + version: 10.3.1(react@19.2.5) + "@vector-im/compound-design-tokens": + specifier: ^10.0.0 + version: 10.1.0(@types/react@19.2.14)(react@19.2.5) + "@vector-im/compound-web": + specifier: ^9.0.0 + version: 9.2.0(@fontsource/inconsolata@5.2.8)(@fontsource/inter@5.2.8)(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(@vector-im/compound-design-tokens@10.1.0(@types/react@19.2.14)(react@19.2.5))(react-dom@19.2.5(react@19.2.5))(react@19.2.5) + "@vitejs/plugin-react": + specifier: ^4.0.1 + version: 4.7.0(vite@8.0.8(@types/node@24.12.2)(esbuild@0.27.7)(jiti@2.6.1)(sass@1.99.0)(terser@5.46.1)(yaml@2.8.3)) + "@vitest/coverage-v8": + specifier: ^4.0.18 + version: 4.1.4(vitest@4.1.4) + babel-plugin-transform-vite-meta-env: + specifier: ^1.0.3 + version: 1.0.3 + classnames: + specifier: ^2.3.1 + version: 2.5.1 + copy-to-clipboard: + specifier: ^3.3.3 + version: 3.3.3 + eslint: + specifier: ^8.14.0 + version: 8.57.1 + eslint-config-google: + specifier: ^0.14.0 + version: 0.14.0(eslint@8.57.1) + eslint-config-prettier: + specifier: ^10.0.0 + version: 10.1.8(eslint@8.57.1) + eslint-plugin-deprecate: + specifier: ^0.9.0 + version: 0.9.0(eslint@8.57.1) + eslint-plugin-import: + specifier: ^2.26.0 + version: 2.32.0(@typescript-eslint/parser@8.58.2(eslint@8.57.1)(typescript@5.9.3))(eslint@8.57.1) + eslint-plugin-jsdoc: + specifier: ^61.5.0 + version: 61.7.1(eslint@8.57.1) + eslint-plugin-jsx-a11y: + specifier: ^6.5.1 + version: 6.10.2(eslint@8.57.1) + eslint-plugin-matrix-org: + specifier: 2.1.0 + version: 2.1.0(@babel/core@7.29.0)(@babel/eslint-parser@7.28.6(@babel/core@7.29.0)(eslint@8.57.1))(@babel/eslint-plugin@7.27.1(@babel/eslint-parser@7.28.6(@babel/core@7.29.0)(eslint@8.57.1))(eslint@8.57.1))(@stylistic/eslint-plugin@3.1.0(eslint@8.57.1)(typescript@5.9.3))(@typescript-eslint/eslint-plugin@8.58.2(@typescript-eslint/parser@8.58.2(eslint@8.57.1)(typescript@5.9.3))(eslint@8.57.1)(typescript@5.9.3))(@typescript-eslint/parser@8.58.2(eslint@8.57.1)(typescript@5.9.3))(eslint-config-google@0.14.0(eslint@8.57.1))(eslint-config-prettier@10.1.8(eslint@8.57.1))(eslint-plugin-deprecate@0.9.0(eslint@8.57.1))(eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.58.2(eslint@8.57.1)(typescript@5.9.3))(eslint@8.57.1))(eslint-plugin-jest@29.15.2(@typescript-eslint/eslint-plugin@8.58.2(@typescript-eslint/parser@8.58.2(eslint@8.57.1)(typescript@5.9.3))(eslint@8.57.1)(typescript@5.9.3))(eslint@8.57.1)(typescript@5.9.3))(eslint-plugin-jsx-a11y@6.10.2(eslint@8.57.1))(eslint-plugin-react-hooks@5.2.0(eslint@8.57.1))(eslint-plugin-react@7.37.5(eslint@8.57.1))(eslint-plugin-unicorn@56.0.1(eslint@8.57.1))(eslint@8.57.1)(prettier@3.8.3)(typescript@5.9.3) + eslint-plugin-react: + specifier: ^7.29.4 + version: 7.37.5(eslint@8.57.1) + eslint-plugin-react-hooks: + specifier: ^5.0.0 + version: 5.2.0(eslint@8.57.1) + eslint-plugin-rxjs: + specifier: ^5.0.3 + version: 5.0.3(eslint@8.57.1)(typescript@5.9.3) + eslint-plugin-storybook: + specifier: ^10.3.3 + version: 10.3.5(eslint@8.57.1)(storybook@10.3.5(@testing-library/dom@10.4.1)(prettier@3.8.3)(react-dom@19.2.5(react@19.2.5))(react@19.2.5))(typescript@5.9.3) + eslint-plugin-unicorn: + specifier: ^56.0.0 + version: 56.0.1(eslint@8.57.1) + fetch-mock: + specifier: 11.1.5 + version: 11.1.5 + global-jsdom: + specifier: ^26.0.0 + version: 26.0.0(jsdom@26.1.0) + i18next: + specifier: ^25.0.0 + version: 25.10.10(typescript@5.9.3) + i18next-browser-languagedetector: + specifier: ^8.0.0 + version: 8.2.1 + i18next-parser: + specifier: ^9.1.0 + version: 9.4.0 + jsdom: + specifier: ^26.0.0 + version: 26.1.0 + knip: + specifier: ^5.86.0 + version: 5.88.1(@emnapi/core@1.9.2)(@emnapi/runtime@1.9.2)(@types/node@24.12.2)(typescript@5.9.3) + livekit-client: + specifier: ^2.18.1 + version: 2.18.3(@types/dom-mediacapture-record@1.0.22) + lodash-es: + specifier: ^4.17.21 + version: 4.18.1 + loglevel: + specifier: ^1.9.1 + version: 1.9.2 + matrix-js-sdk: + specifier: matrix-org/matrix-js-sdk#ca5655bced1cbb215ac1c18e179384a069d98b0a + version: https://codeload.github.com/matrix-org/matrix-js-sdk/tar.gz/ca5655bced1cbb215ac1c18e179384a069d98b0a + matrix-widget-api: + specifier: ^1.16.1 + version: 1.17.0 + node-stdlib-browser: + specifier: ^1.3.1 + version: 1.3.1 + normalize.css: + specifier: ^8.0.1 + version: 8.0.1 + observable-hooks: + specifier: ^4.2.3 + version: 4.2.4(react-dom@19.2.5(react@19.2.5))(react@19.2.5)(rxjs@7.8.2) + pako: + specifier: ^2.0.4 + version: 2.1.0 + postcss: + specifier: ^8.4.41 + version: 8.5.10 + postcss-preset-env: + specifier: ^10.0.0 + version: 10.6.1(postcss@8.5.10) + posthog-js: + specifier: 1.160.3 + version: 1.160.3 + prettier: + specifier: ^3.0.0 + version: 3.8.3 + qrcode: + specifier: ^1.5.4 + version: 1.5.4 + react: + specifier: "19" + version: 19.2.5 + react-dom: + specifier: "19" + version: 19.2.5(react@19.2.5) + react-i18next: + specifier: ^16.0.0 <16.7.0 + version: 16.6.6(i18next@25.10.10(typescript@5.9.3))(react-dom@19.2.5(react@19.2.5))(react@19.2.5)(typescript@5.9.3) + react-router-dom: + specifier: ^7.0.0 + version: 7.14.1(react-dom@19.2.5(react@19.2.5))(react@19.2.5) + react-use-measure: + specifier: ^2.1.1 + version: 2.1.7(react-dom@19.2.5(react@19.2.5))(react@19.2.5) + rxjs: + specifier: ^7.8.1 + version: 7.8.2 + sass: + specifier: ^1.42.1 + version: 1.99.0 + storybook: + specifier: ^10.3.3 + version: 10.3.5(@testing-library/dom@10.4.1)(prettier@3.8.3)(react-dom@19.2.5(react@19.2.5))(react@19.2.5) + typescript: + specifier: ^5.8.3 + version: 5.9.3 + typescript-eslint-language-service: + specifier: ^5.0.5 + version: 5.0.5(@typescript-eslint/parser@8.58.2(eslint@8.57.1)(typescript@5.9.3))(eslint@8.57.1)(typescript@5.9.3) + unique-names-generator: + specifier: ^4.6.0 + version: 4.7.1 + uuid: + specifier: ^13.0.0 + version: 13.0.0 + vaul: + specifier: ^1.0.0 + version: 1.1.2(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5) + vite: + specifier: ^8.0.0 + version: 8.0.8(@types/node@24.12.2)(esbuild@0.27.7)(jiti@2.6.1)(sass@1.99.0)(terser@5.46.1)(yaml@2.8.3) + vite-plugin-generate-file: + specifier: ^0.3.0 + version: 0.3.1 + vite-plugin-html: + specifier: ^3.2.2 + version: 3.2.2(vite@8.0.8(@types/node@24.12.2)(esbuild@0.27.7)(jiti@2.6.1)(sass@1.99.0)(terser@5.46.1)(yaml@2.8.3)) + vite-plugin-node-stdlib-browser: + specifier: ^0.2.1 + version: 0.2.1(node-stdlib-browser@1.3.1)(vite@8.0.8(@types/node@24.12.2)(esbuild@0.27.7)(jiti@2.6.1)(sass@1.99.0)(terser@5.46.1)(yaml@2.8.3)) + vite-plugin-svgr: + specifier: ^4.0.0 + version: 4.5.0(typescript@5.9.3)(vite@8.0.8(@types/node@24.12.2)(esbuild@0.27.7)(jiti@2.6.1)(sass@1.99.0)(terser@5.46.1)(yaml@2.8.3)) + vitest: + specifier: ^4.0.18 + version: 4.1.4(@types/node@24.12.2)(@vitest/coverage-v8@4.1.4)(jsdom@26.1.0)(vite@8.0.8(@types/node@24.12.2)(esbuild@0.27.7)(jiti@2.6.1)(sass@1.99.0)(terser@5.46.1)(yaml@2.8.3)) + vitest-axe: + specifier: ^1.0.0-pre.3 + version: 1.0.0-pre.5(vitest@4.1.4(@types/node@24.12.2)(@vitest/coverage-v8@4.1.4)(jsdom@26.1.0)(vite@8.0.8(@types/node@24.12.2)(esbuild@0.27.7)(jiti@2.6.1)(sass@1.99.0)(terser@5.46.1)(yaml@2.8.3))) + +packages: + "@actions/core@1.11.1": + resolution: + { + integrity: sha512-hXJCSrkwfA46Vd9Z3q4cpEpHB1rL5NG04+/rbqW9d3+CSvtB1tYe8UTpAlixa1vj0m/ULglfEK2UKxMGxCxv5A==, + } + + "@actions/exec@1.1.1": + resolution: + { + integrity: sha512-+sCcHHbVdk93a0XT19ECtO/gIXoxvdsgQLzb2fE2/5sIZmWQuluYyjPQtrtTHdU1YzTZ7bAPN4sITq2xi1679w==, + } + + "@actions/github@6.0.1": + resolution: + { + integrity: sha512-xbZVcaqD4XnQAe35qSQqskb3SqIAfRyLBrHMd/8TuL7hJSz2QtbDwnNM8zWx4zO5l2fnGtseNE3MbEvD7BxVMw==, + } + + "@actions/http-client@2.2.3": + resolution: + { + integrity: sha512-mx8hyJi/hjFvbPokCg4uRd4ZX78t+YyRPtnKWwIl+RzNaVuFpQHfmlGVfsKEJN8LwTCvL+DfVgAM04XaHkm6bA==, + } + + "@actions/io@1.1.3": + resolution: + { + integrity: sha512-wi9JjgKLYS7U/z8PPbco+PvTb/nRWjeoFlJ1Qer83k/3C5PHQi28hiVdeE2kHXmIL99mQFawx8qt/JPjZilJ8Q==, + } + + "@adobe/css-tools@4.4.4": + resolution: + { + integrity: sha512-Elp+iwUx5rN5+Y8xLt5/GRoG20WGoDCQ/1Fb+1LiGtvwbDavuSk0jhD/eZdckHAuzcDzccnkv+rEjyWfRx18gg==, + } + + "@asamuzakjp/css-color@3.2.0": + resolution: + { + integrity: sha512-K1A6z8tS3XsmCMM86xoWdn7Fkdn9m6RSVtocUrJYIwZnFVkng/PvkEoWtOWmP+Scc6saYWHWZYbndEEXxl24jw==, + } + + "@babel/code-frame@7.29.0": + resolution: + { + integrity: sha512-9NhCeYjq9+3uxgdtp20LSiJXJvN0FeCtNGpJxuMFZ1Kv3cWUNb6DOhJwUvcVCzKGR66cw4njwM6hrJLqgOwbcw==, + } + engines: { node: ">=6.9.0" } + + "@babel/compat-data@7.29.0": + resolution: + { + integrity: sha512-T1NCJqT/j9+cn8fvkt7jtwbLBfLC/1y1c7NtCeXFRgzGTsafi68MRv8yzkYSapBnFA6L3U2VSc02ciDzoAJhJg==, + } + engines: { node: ">=6.9.0" } + + "@babel/core@7.29.0": + resolution: + { + integrity: sha512-CGOfOJqWjg2qW/Mb6zNsDm+u5vFQ8DxXfbM09z69p5Z6+mE1ikP2jUXw+j42Pf1XTYED2Rni5f95npYeuwMDQA==, + } + engines: { node: ">=6.9.0" } + + "@babel/eslint-parser@7.28.6": + resolution: + { + integrity: sha512-QGmsKi2PBO/MHSQk+AAgA9R6OHQr+VqnniFE0eMWZcVcfBZoA2dKn2hUsl3Csg/Plt9opRUWdY7//VXsrIlEiA==, + } + engines: { node: ^10.13.0 || ^12.13.0 || >=14.0.0 } + peerDependencies: + "@babel/core": ^7.11.0 + eslint: ^7.5.0 || ^8.0.0 || ^9.0.0 + + "@babel/eslint-plugin@7.27.1": + resolution: + { + integrity: sha512-vOG/EipZbIAcREK6XI4JRO3B3uZr70/KIhsrNLO9RXcgLMaW0sTsBpNeTpQUyelB0HsbWd45NIsuTgD3mqr/Og==, + } + engines: { node: ^10.13.0 || ^12.13.0 || >=14.0.0 } + peerDependencies: + "@babel/eslint-parser": ^7.11.0 + eslint: ^7.5.0 || ^8.0.0 || ^9.0.0 + + "@babel/generator@7.29.1": + resolution: + { + integrity: sha512-qsaF+9Qcm2Qv8SRIMMscAvG4O3lJ0F1GuMo5HR/Bp02LopNgnZBC/EkbevHFeGs4ls/oPz9v+Bsmzbkbe+0dUw==, + } + engines: { node: ">=6.9.0" } + + "@babel/helper-annotate-as-pure@7.27.3": + resolution: + { + integrity: sha512-fXSwMQqitTGeHLBC08Eq5yXz2m37E4pJX1qAU1+2cNedz/ifv/bVXft90VeSav5nFO61EcNgwr0aJxbyPaWBPg==, + } + engines: { node: ">=6.9.0" } + + "@babel/helper-compilation-targets@7.28.6": + resolution: + { + integrity: sha512-JYtls3hqi15fcx5GaSNL7SCTJ2MNmjrkHXg4FSpOA/grxK8KwyZ5bubHsCq8FXCkua6xhuaaBit+3b7+VZRfcA==, + } + engines: { node: ">=6.9.0" } + + "@babel/helper-create-class-features-plugin@7.28.6": + resolution: + { + integrity: sha512-dTOdvsjnG3xNT9Y0AUg1wAl38y+4Rl4sf9caSQZOXdNqVn+H+HbbJ4IyyHaIqNR6SW9oJpA/RuRjsjCw2IdIow==, + } + engines: { node: ">=6.9.0" } + peerDependencies: + "@babel/core": ^7.0.0 + + "@babel/helper-create-regexp-features-plugin@7.28.5": + resolution: + { + integrity: sha512-N1EhvLtHzOvj7QQOUCCS3NrPJP8c5W6ZXCHDn7Yialuy1iu4r5EmIYkXlKNqT99Ciw+W0mDqWoR6HWMZlFP3hw==, + } + engines: { node: ">=6.9.0" } + peerDependencies: + "@babel/core": ^7.0.0 + + "@babel/helper-define-polyfill-provider@0.6.8": + resolution: + { + integrity: sha512-47UwBLPpQi1NoWzLuHNjRoHlYXMwIJoBf7MFou6viC/sIHWYygpvr0B6IAyh5sBdA2nr2LPIRww8lfaUVQINBA==, + } + peerDependencies: + "@babel/core": ^7.4.0 || ^8.0.0-0 <8.0.0 + + "@babel/helper-globals@7.28.0": + resolution: + { + integrity: sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw==, + } + engines: { node: ">=6.9.0" } + + "@babel/helper-member-expression-to-functions@7.28.5": + resolution: + { + integrity: sha512-cwM7SBRZcPCLgl8a7cY0soT1SptSzAlMH39vwiRpOQkJlh53r5hdHwLSCZpQdVLT39sZt+CRpNwYG4Y2v77atg==, + } + engines: { node: ">=6.9.0" } + + "@babel/helper-module-imports@7.28.6": + resolution: + { + integrity: sha512-l5XkZK7r7wa9LucGw9LwZyyCUscb4x37JWTPz7swwFE/0FMQAGpiWUZn8u9DzkSBWEcK25jmvubfpw2dnAMdbw==, + } + engines: { node: ">=6.9.0" } + + "@babel/helper-module-transforms@7.28.6": + resolution: + { + integrity: sha512-67oXFAYr2cDLDVGLXTEABjdBJZ6drElUSI7WKp70NrpyISso3plG9SAGEF6y7zbha/wOzUByWWTJvEDVNIUGcA==, + } + engines: { node: ">=6.9.0" } + peerDependencies: + "@babel/core": ^7.0.0 + + "@babel/helper-optimise-call-expression@7.27.1": + resolution: + { + integrity: sha512-URMGH08NzYFhubNSGJrpUEphGKQwMQYBySzat5cAByY1/YgIRkULnIy3tAMeszlL/so2HbeilYloUmSpd7GdVw==, + } + engines: { node: ">=6.9.0" } + + "@babel/helper-plugin-utils@7.28.6": + resolution: + { + integrity: sha512-S9gzZ/bz83GRysI7gAD4wPT/AI3uCnY+9xn+Mx/KPs2JwHJIz1W8PZkg2cqyt3RNOBM8ejcXhV6y8Og7ly/Dug==, + } + engines: { node: ">=6.9.0" } + + "@babel/helper-remap-async-to-generator@7.27.1": + resolution: + { + integrity: sha512-7fiA521aVw8lSPeI4ZOD3vRFkoqkJcS+z4hFo82bFSH/2tNd6eJ5qCVMS5OzDmZh/kaHQeBaeyxK6wljcPtveA==, + } + engines: { node: ">=6.9.0" } + peerDependencies: + "@babel/core": ^7.0.0 + + "@babel/helper-replace-supers@7.28.6": + resolution: + { + integrity: sha512-mq8e+laIk94/yFec3DxSjCRD2Z0TAjhVbEJY3UQrlwVo15Lmt7C2wAUbK4bjnTs4APkwsYLTahXRraQXhb1WCg==, + } + engines: { node: ">=6.9.0" } + peerDependencies: + "@babel/core": ^7.0.0 + + "@babel/helper-skip-transparent-expression-wrappers@7.27.1": + resolution: + { + integrity: sha512-Tub4ZKEXqbPjXgWLl2+3JpQAYBJ8+ikpQ2Ocj/q/r0LwE3UhENh7EUabyHjz2kCEsrRY83ew2DQdHluuiDQFzg==, + } + engines: { node: ">=6.9.0" } + + "@babel/helper-string-parser@7.27.1": + resolution: + { + integrity: sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==, + } + engines: { node: ">=6.9.0" } + + "@babel/helper-validator-identifier@7.28.5": + resolution: + { + integrity: sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==, + } + engines: { node: ">=6.9.0" } + + "@babel/helper-validator-option@7.27.1": + resolution: + { + integrity: sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg==, + } + engines: { node: ">=6.9.0" } + + "@babel/helper-wrap-function@7.28.6": + resolution: + { + integrity: sha512-z+PwLziMNBeSQJonizz2AGnndLsP2DeGHIxDAn+wdHOGuo4Fo1x1HBPPXeE9TAOPHNNWQKCSlA2VZyYyyibDnQ==, + } + engines: { node: ">=6.9.0" } + + "@babel/helpers@7.29.2": + resolution: + { + integrity: sha512-HoGuUs4sCZNezVEKdVcwqmZN8GoHirLUcLaYVNBK2J0DadGtdcqgr3BCbvH8+XUo4NGjNl3VOtSjEKNzqfFgKw==, + } + engines: { node: ">=6.9.0" } + + "@babel/parser@7.29.2": + resolution: + { + integrity: sha512-4GgRzy/+fsBa72/RZVJmGKPmZu9Byn8o4MoLpmNe1m8ZfYnz5emHLQz3U4gLud6Zwl0RZIcgiLD7Uq7ySFuDLA==, + } + engines: { node: ">=6.0.0" } + hasBin: true + + "@babel/plugin-bugfix-firefox-class-in-computed-class-key@7.28.5": + resolution: + { + integrity: sha512-87GDMS3tsmMSi/3bWOte1UblL+YUTFMV8SZPZ2eSEL17s74Cw/l63rR6NmGVKMYW2GYi85nE+/d6Hw5N0bEk2Q==, + } + engines: { node: ">=6.9.0" } + peerDependencies: + "@babel/core": ^7.0.0 + + "@babel/plugin-bugfix-safari-class-field-initializer-scope@7.27.1": + resolution: + { + integrity: sha512-qNeq3bCKnGgLkEXUuFry6dPlGfCdQNZbn7yUAPCInwAJHMU7THJfrBSozkcWq5sNM6RcF3S8XyQL2A52KNR9IA==, + } + engines: { node: ">=6.9.0" } + peerDependencies: + "@babel/core": ^7.0.0 + + "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@7.27.1": + resolution: + { + integrity: sha512-g4L7OYun04N1WyqMNjldFwlfPCLVkgB54A/YCXICZYBsvJJE3kByKv9c9+R/nAfmIfjl2rKYLNyMHboYbZaWaA==, + } + engines: { node: ">=6.9.0" } + peerDependencies: + "@babel/core": ^7.0.0 + + "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@7.27.1": + resolution: + { + integrity: sha512-oO02gcONcD5O1iTLi/6frMJBIwWEHceWGSGqrpCmEL8nogiS6J9PBlE48CaK20/Jx1LuRml9aDftLgdjXT8+Cw==, + } + engines: { node: ">=6.9.0" } + peerDependencies: + "@babel/core": ^7.13.0 + + "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly@7.28.6": + resolution: + { + integrity: sha512-a0aBScVTlNaiUe35UtfxAN7A/tehvvG4/ByO6+46VPKTRSlfnAFsgKy0FUh+qAkQrDTmhDkT+IBOKlOoMUxQ0g==, + } + engines: { node: ">=6.9.0" } + peerDependencies: + "@babel/core": ^7.0.0 + + "@babel/plugin-proposal-private-property-in-object@7.21.0-placeholder-for-preset-env.2": + resolution: + { + integrity: sha512-SOSkfJDddaM7mak6cPEpswyTRnuRltl429hMraQEglW+OkovnCzsiszTmsrlY//qLFjCpQDFRvjdm2wA5pPm9w==, + } + engines: { node: ">=6.9.0" } + peerDependencies: + "@babel/core": ^7.0.0-0 + + "@babel/plugin-syntax-import-assertions@7.28.6": + resolution: + { + integrity: sha512-pSJUpFHdx9z5nqTSirOCMtYVP2wFgoWhP0p3g8ONK/4IHhLIBd0B9NYqAvIUAhq+OkhO4VM1tENCt0cjlsNShw==, + } + engines: { node: ">=6.9.0" } + peerDependencies: + "@babel/core": ^7.0.0-0 + + "@babel/plugin-syntax-import-attributes@7.28.6": + resolution: + { + integrity: sha512-jiLC0ma9XkQT3TKJ9uYvlakm66Pamywo+qwL+oL8HJOvc6TWdZXVfhqJr8CCzbSGUAbDOzlGHJC1U+vRfLQDvw==, + } + engines: { node: ">=6.9.0" } + peerDependencies: + "@babel/core": ^7.0.0-0 + + "@babel/plugin-syntax-jsx@7.28.6": + resolution: + { + integrity: sha512-wgEmr06G6sIpqr8YDwA2dSRTE3bJ+V0IfpzfSY3Lfgd7YWOaAdlykvJi13ZKBt8cZHfgH1IXN+CL656W3uUa4w==, + } + engines: { node: ">=6.9.0" } + peerDependencies: + "@babel/core": ^7.0.0-0 + + "@babel/plugin-syntax-typescript@7.28.6": + resolution: + { + integrity: sha512-+nDNmQye7nlnuuHDboPbGm00Vqg3oO8niRRL27/4LYHUsHYh0zJ1xWOz0uRwNFmM1Avzk8wZbc6rdiYhomzv/A==, + } + engines: { node: ">=6.9.0" } + peerDependencies: + "@babel/core": ^7.0.0-0 + + "@babel/plugin-syntax-unicode-sets-regex@7.18.6": + resolution: + { + integrity: sha512-727YkEAPwSIQTv5im8QHz3upqp92JTWhidIC81Tdx4VJYIte/VndKf1qKrfnnhPLiPghStWfvC/iFaMCQu7Nqg==, + } + engines: { node: ">=6.9.0" } + peerDependencies: + "@babel/core": ^7.0.0 + + "@babel/plugin-transform-arrow-functions@7.27.1": + resolution: + { + integrity: sha512-8Z4TGic6xW70FKThA5HYEKKyBpOOsucTOD1DjU3fZxDg+K3zBJcXMFnt/4yQiZnf5+MiOMSXQ9PaEK/Ilh1DeA==, + } + engines: { node: ">=6.9.0" } + peerDependencies: + "@babel/core": ^7.0.0-0 + + "@babel/plugin-transform-async-generator-functions@7.29.0": + resolution: + { + integrity: sha512-va0VdWro4zlBr2JsXC+ofCPB2iG12wPtVGTWFx2WLDOM3nYQZZIGP82qku2eW/JR83sD+k2k+CsNtyEbUqhU6w==, + } + engines: { node: ">=6.9.0" } + peerDependencies: + "@babel/core": ^7.0.0-0 + + "@babel/plugin-transform-async-to-generator@7.28.6": + resolution: + { + integrity: sha512-ilTRcmbuXjsMmcZ3HASTe4caH5Tpo93PkTxF9oG2VZsSWsahydmcEHhix9Ik122RcTnZnUzPbmux4wh1swfv7g==, + } + engines: { node: ">=6.9.0" } + peerDependencies: + "@babel/core": ^7.0.0-0 + + "@babel/plugin-transform-block-scoped-functions@7.27.1": + resolution: + { + integrity: sha512-cnqkuOtZLapWYZUYM5rVIdv1nXYuFVIltZ6ZJ7nIj585QsjKM5dhL2Fu/lICXZ1OyIAFc7Qy+bvDAtTXqGrlhg==, + } + engines: { node: ">=6.9.0" } + peerDependencies: + "@babel/core": ^7.0.0-0 + + "@babel/plugin-transform-block-scoping@7.28.6": + resolution: + { + integrity: sha512-tt/7wOtBmwHPNMPu7ax4pdPz6shjFrmHDghvNC+FG9Qvj7D6mJcoRQIF5dy4njmxR941l6rgtvfSB2zX3VlUIw==, + } + engines: { node: ">=6.9.0" } + peerDependencies: + "@babel/core": ^7.0.0-0 + + "@babel/plugin-transform-class-properties@7.28.6": + resolution: + { + integrity: sha512-dY2wS3I2G7D697VHndN91TJr8/AAfXQNt5ynCTI/MpxMsSzHp+52uNivYT5wCPax3whc47DR8Ba7cmlQMg24bw==, + } + engines: { node: ">=6.9.0" } + peerDependencies: + "@babel/core": ^7.0.0-0 + + "@babel/plugin-transform-class-static-block@7.28.6": + resolution: + { + integrity: sha512-rfQ++ghVwTWTqQ7w8qyDxL1XGihjBss4CmTgGRCTAC9RIbhVpyp4fOeZtta0Lbf+dTNIVJer6ych2ibHwkZqsQ==, + } + engines: { node: ">=6.9.0" } + peerDependencies: + "@babel/core": ^7.12.0 + + "@babel/plugin-transform-classes@7.28.6": + resolution: + { + integrity: sha512-EF5KONAqC5zAqT783iMGuM2ZtmEBy+mJMOKl2BCvPZ2lVrwvXnB6o+OBWCS+CoeCCpVRF2sA2RBKUxvT8tQT5Q==, + } + engines: { node: ">=6.9.0" } + peerDependencies: + "@babel/core": ^7.0.0-0 + + "@babel/plugin-transform-computed-properties@7.28.6": + resolution: + { + integrity: sha512-bcc3k0ijhHbc2lEfpFHgx7eYw9KNXqOerKWfzbxEHUGKnS3sz9C4CNL9OiFN1297bDNfUiSO7DaLzbvHQQQ1BQ==, + } + engines: { node: ">=6.9.0" } + peerDependencies: + "@babel/core": ^7.0.0-0 + + "@babel/plugin-transform-destructuring@7.28.5": + resolution: + { + integrity: sha512-Kl9Bc6D0zTUcFUvkNuQh4eGXPKKNDOJQXVyyM4ZAQPMveniJdxi8XMJwLo+xSoW3MIq81bD33lcUe9kZpl0MCw==, + } + engines: { node: ">=6.9.0" } + peerDependencies: + "@babel/core": ^7.0.0-0 + + "@babel/plugin-transform-dotall-regex@7.28.6": + resolution: + { + integrity: sha512-SljjowuNKB7q5Oayv4FoPzeB74g3QgLt8IVJw9ADvWy3QnUb/01aw8I4AVv8wYnPvQz2GDDZ/g3GhcNyDBI4Bg==, + } + engines: { node: ">=6.9.0" } + peerDependencies: + "@babel/core": ^7.0.0-0 + + "@babel/plugin-transform-duplicate-keys@7.27.1": + resolution: + { + integrity: sha512-MTyJk98sHvSs+cvZ4nOauwTTG1JeonDjSGvGGUNHreGQns+Mpt6WX/dVzWBHgg+dYZhkC4X+zTDfkTU+Vy9y7Q==, + } + engines: { node: ">=6.9.0" } + peerDependencies: + "@babel/core": ^7.0.0-0 + + "@babel/plugin-transform-duplicate-named-capturing-groups-regex@7.29.0": + resolution: + { + integrity: sha512-zBPcW2lFGxdiD8PUnPwJjag2J9otbcLQzvbiOzDxpYXyCuYX9agOwMPGn1prVH0a4qzhCKu24rlH4c1f7yA8rw==, + } + engines: { node: ">=6.9.0" } + peerDependencies: + "@babel/core": ^7.0.0 + + "@babel/plugin-transform-dynamic-import@7.27.1": + resolution: + { + integrity: sha512-MHzkWQcEmjzzVW9j2q8LGjwGWpG2mjwaaB0BNQwst3FIjqsg8Ct/mIZlvSPJvfi9y2AC8mi/ktxbFVL9pZ1I4A==, + } + engines: { node: ">=6.9.0" } + peerDependencies: + "@babel/core": ^7.0.0-0 + + "@babel/plugin-transform-explicit-resource-management@7.28.6": + resolution: + { + integrity: sha512-Iao5Konzx2b6g7EPqTy40UZbcdXE126tTxVFr/nAIj+WItNxjKSYTEw3RC+A2/ZetmdJsgueL1KhaMCQHkLPIg==, + } + engines: { node: ">=6.9.0" } + peerDependencies: + "@babel/core": ^7.0.0-0 + + "@babel/plugin-transform-exponentiation-operator@7.28.6": + resolution: + { + integrity: sha512-WitabqiGjV/vJ0aPOLSFfNY1u9U3R7W36B03r5I2KoNix+a3sOhJ3pKFB3R5It9/UiK78NiO0KE9P21cMhlPkw==, + } + engines: { node: ">=6.9.0" } + peerDependencies: + "@babel/core": ^7.0.0-0 + + "@babel/plugin-transform-export-namespace-from@7.27.1": + resolution: + { + integrity: sha512-tQvHWSZ3/jH2xuq/vZDy0jNn+ZdXJeM8gHvX4lnJmsc3+50yPlWdZXIc5ay+umX+2/tJIqHqiEqcJvxlmIvRvQ==, + } + engines: { node: ">=6.9.0" } + peerDependencies: + "@babel/core": ^7.0.0-0 + + "@babel/plugin-transform-for-of@7.27.1": + resolution: + { + integrity: sha512-BfbWFFEJFQzLCQ5N8VocnCtA8J1CLkNTe2Ms2wocj75dd6VpiqS5Z5quTYcUoo4Yq+DN0rtikODccuv7RU81sw==, + } + engines: { node: ">=6.9.0" } + peerDependencies: + "@babel/core": ^7.0.0-0 + + "@babel/plugin-transform-function-name@7.27.1": + resolution: + { + integrity: sha512-1bQeydJF9Nr1eBCMMbC+hdwmRlsv5XYOMu03YSWFwNs0HsAmtSxxF1fyuYPqemVldVyFmlCU7w8UE14LupUSZQ==, + } + engines: { node: ">=6.9.0" } + peerDependencies: + "@babel/core": ^7.0.0-0 + + "@babel/plugin-transform-json-strings@7.28.6": + resolution: + { + integrity: sha512-Nr+hEN+0geQkzhbdgQVPoqr47lZbm+5fCUmO70722xJZd0Mvb59+33QLImGj6F+DkK3xgDi1YVysP8whD6FQAw==, + } + engines: { node: ">=6.9.0" } + peerDependencies: + "@babel/core": ^7.0.0-0 + + "@babel/plugin-transform-literals@7.27.1": + resolution: + { + integrity: sha512-0HCFSepIpLTkLcsi86GG3mTUzxV5jpmbv97hTETW3yzrAij8aqlD36toB1D0daVFJM8NK6GvKO0gslVQmm+zZA==, + } + engines: { node: ">=6.9.0" } + peerDependencies: + "@babel/core": ^7.0.0-0 + + "@babel/plugin-transform-logical-assignment-operators@7.28.6": + resolution: + { + integrity: sha512-+anKKair6gpi8VsM/95kmomGNMD0eLz1NQ8+Pfw5sAwWH9fGYXT50E55ZpV0pHUHWf6IUTWPM+f/7AAff+wr9A==, + } + engines: { node: ">=6.9.0" } + peerDependencies: + "@babel/core": ^7.0.0-0 + + "@babel/plugin-transform-member-expression-literals@7.27.1": + resolution: + { + integrity: sha512-hqoBX4dcZ1I33jCSWcXrP+1Ku7kdqXf1oeah7ooKOIiAdKQ+uqftgCFNOSzA5AMS2XIHEYeGFg4cKRCdpxzVOQ==, + } + engines: { node: ">=6.9.0" } + peerDependencies: + "@babel/core": ^7.0.0-0 + + "@babel/plugin-transform-modules-amd@7.27.1": + resolution: + { + integrity: sha512-iCsytMg/N9/oFq6n+gFTvUYDZQOMK5kEdeYxmxt91fcJGycfxVP9CnrxoliM0oumFERba2i8ZtwRUCMhvP1LnA==, + } + engines: { node: ">=6.9.0" } + peerDependencies: + "@babel/core": ^7.0.0-0 + + "@babel/plugin-transform-modules-commonjs@7.28.6": + resolution: + { + integrity: sha512-jppVbf8IV9iWWwWTQIxJMAJCWBuuKx71475wHwYytrRGQ2CWiDvYlADQno3tcYpS/T2UUWFQp3nVtYfK/YBQrA==, + } + engines: { node: ">=6.9.0" } + peerDependencies: + "@babel/core": ^7.0.0-0 + + "@babel/plugin-transform-modules-systemjs@7.29.0": + resolution: + { + integrity: sha512-PrujnVFbOdUpw4UHiVwKvKRLMMic8+eC0CuNlxjsyZUiBjhFdPsewdXCkveh2KqBA9/waD0W1b4hXSOBQJezpQ==, + } + engines: { node: ">=6.9.0" } + peerDependencies: + "@babel/core": ^7.0.0-0 + + "@babel/plugin-transform-modules-umd@7.27.1": + resolution: + { + integrity: sha512-iQBE/xC5BV1OxJbp6WG7jq9IWiD+xxlZhLrdwpPkTX3ydmXdvoCpyfJN7acaIBZaOqTfr76pgzqBJflNbeRK+w==, + } + engines: { node: ">=6.9.0" } + peerDependencies: + "@babel/core": ^7.0.0-0 + + "@babel/plugin-transform-named-capturing-groups-regex@7.29.0": + resolution: + { + integrity: sha512-1CZQA5KNAD6ZYQLPw7oi5ewtDNxH/2vuCh+6SmvgDfhumForvs8a1o9n0UrEoBD8HU4djO2yWngTQlXl1NDVEQ==, + } + engines: { node: ">=6.9.0" } + peerDependencies: + "@babel/core": ^7.0.0 + + "@babel/plugin-transform-new-target@7.27.1": + resolution: + { + integrity: sha512-f6PiYeqXQ05lYq3TIfIDu/MtliKUbNwkGApPUvyo6+tc7uaR4cPjPe7DFPr15Uyycg2lZU6btZ575CuQoYh7MQ==, + } + engines: { node: ">=6.9.0" } + peerDependencies: + "@babel/core": ^7.0.0-0 + + "@babel/plugin-transform-nullish-coalescing-operator@7.28.6": + resolution: + { + integrity: sha512-3wKbRgmzYbw24mDJXT7N+ADXw8BC/imU9yo9c9X9NKaLF1fW+e5H1U5QjMUBe4Qo4Ox/o++IyUkl1sVCLgevKg==, + } + engines: { node: ">=6.9.0" } + peerDependencies: + "@babel/core": ^7.0.0-0 + + "@babel/plugin-transform-numeric-separator@7.28.6": + resolution: + { + integrity: sha512-SJR8hPynj8outz+SlStQSwvziMN4+Bq99it4tMIf5/Caq+3iOc0JtKyse8puvyXkk3eFRIA5ID/XfunGgO5i6w==, + } + engines: { node: ">=6.9.0" } + peerDependencies: + "@babel/core": ^7.0.0-0 + + "@babel/plugin-transform-object-rest-spread@7.28.6": + resolution: + { + integrity: sha512-5rh+JR4JBC4pGkXLAcYdLHZjXudVxWMXbB6u6+E9lRL5TrGVbHt1TjxGbZ8CkmYw9zjkB7jutzOROArsqtncEA==, + } + engines: { node: ">=6.9.0" } + peerDependencies: + "@babel/core": ^7.0.0-0 + + "@babel/plugin-transform-object-super@7.27.1": + resolution: + { + integrity: sha512-SFy8S9plRPbIcxlJ8A6mT/CxFdJx/c04JEctz4jf8YZaVS2px34j7NXRrlGlHkN/M2gnpL37ZpGRGVFLd3l8Ng==, + } + engines: { node: ">=6.9.0" } + peerDependencies: + "@babel/core": ^7.0.0-0 + + "@babel/plugin-transform-optional-catch-binding@7.28.6": + resolution: + { + integrity: sha512-R8ja/Pyrv0OGAvAXQhSTmWyPJPml+0TMqXlO5w+AsMEiwb2fg3WkOvob7UxFSL3OIttFSGSRFKQsOhJ/X6HQdQ==, + } + engines: { node: ">=6.9.0" } + peerDependencies: + "@babel/core": ^7.0.0-0 + + "@babel/plugin-transform-optional-chaining@7.28.6": + resolution: + { + integrity: sha512-A4zobikRGJTsX9uqVFdafzGkqD30t26ck2LmOzAuLL8b2x6k3TIqRiT2xVvA9fNmFeTX484VpsdgmKNA0bS23w==, + } + engines: { node: ">=6.9.0" } + peerDependencies: + "@babel/core": ^7.0.0-0 + + "@babel/plugin-transform-parameters@7.27.7": + resolution: + { + integrity: sha512-qBkYTYCb76RRxUM6CcZA5KRu8K4SM8ajzVeUgVdMVO9NN9uI/GaVmBg/WKJJGnNokV9SY8FxNOVWGXzqzUidBg==, + } + engines: { node: ">=6.9.0" } + peerDependencies: + "@babel/core": ^7.0.0-0 + + "@babel/plugin-transform-private-methods@7.28.6": + resolution: + { + integrity: sha512-piiuapX9CRv7+0st8lmuUlRSmX6mBcVeNQ1b4AYzJxfCMuBfB0vBXDiGSmm03pKJw1v6cZ8KSeM+oUnM6yAExg==, + } + engines: { node: ">=6.9.0" } + peerDependencies: + "@babel/core": ^7.0.0-0 + + "@babel/plugin-transform-private-property-in-object@7.28.6": + resolution: + { + integrity: sha512-b97jvNSOb5+ehyQmBpmhOCiUC5oVK4PMnpRvO7+ymFBoqYjeDHIU9jnrNUuwHOiL9RpGDoKBpSViarV+BU+eVA==, + } + engines: { node: ">=6.9.0" } + peerDependencies: + "@babel/core": ^7.0.0-0 + + "@babel/plugin-transform-property-literals@7.27.1": + resolution: + { + integrity: sha512-oThy3BCuCha8kDZ8ZkgOg2exvPYUlprMukKQXI1r1pJ47NCvxfkEy8vK+r/hT9nF0Aa4H1WUPZZjHTFtAhGfmQ==, + } + engines: { node: ">=6.9.0" } + peerDependencies: + "@babel/core": ^7.0.0-0 + + "@babel/plugin-transform-react-display-name@7.28.0": + resolution: + { + integrity: sha512-D6Eujc2zMxKjfa4Zxl4GHMsmhKKZ9VpcqIchJLvwTxad9zWIYulwYItBovpDOoNLISpcZSXoDJ5gaGbQUDqViA==, + } + engines: { node: ">=6.9.0" } + peerDependencies: + "@babel/core": ^7.0.0-0 + + "@babel/plugin-transform-react-jsx-development@7.27.1": + resolution: + { + integrity: sha512-ykDdF5yI4f1WrAolLqeF3hmYU12j9ntLQl/AOG1HAS21jxyg1Q0/J/tpREuYLfatGdGmXp/3yS0ZA76kOlVq9Q==, + } + engines: { node: ">=6.9.0" } + peerDependencies: + "@babel/core": ^7.0.0-0 + + "@babel/plugin-transform-react-jsx-self@7.27.1": + resolution: + { + integrity: sha512-6UzkCs+ejGdZ5mFFC/OCUrv028ab2fp1znZmCZjAOBKiBK2jXD1O+BPSfX8X2qjJ75fZBMSnQn3Rq2mrBJK2mw==, + } + engines: { node: ">=6.9.0" } + peerDependencies: + "@babel/core": ^7.0.0-0 + + "@babel/plugin-transform-react-jsx-source@7.27.1": + resolution: + { + integrity: sha512-zbwoTsBruTeKB9hSq73ha66iFeJHuaFkUbwvqElnygoNbj/jHRsSeokowZFN3CZ64IvEqcmmkVe89OPXc7ldAw==, + } + engines: { node: ">=6.9.0" } + peerDependencies: + "@babel/core": ^7.0.0-0 + + "@babel/plugin-transform-react-jsx@7.28.6": + resolution: + { + integrity: sha512-61bxqhiRfAACulXSLd/GxqmAedUSrRZIu/cbaT18T1CetkTmtDN15it7i80ru4DVqRK1WMxQhXs+Lf9kajm5Ow==, + } + engines: { node: ">=6.9.0" } + peerDependencies: + "@babel/core": ^7.0.0-0 + + "@babel/plugin-transform-react-pure-annotations@7.27.1": + resolution: + { + integrity: sha512-JfuinvDOsD9FVMTHpzA/pBLisxpv1aSf+OIV8lgH3MuWrks19R27e6a6DipIg4aX1Zm9Wpb04p8wljfKrVSnPA==, + } + engines: { node: ">=6.9.0" } + peerDependencies: + "@babel/core": ^7.0.0-0 + + "@babel/plugin-transform-regenerator@7.29.0": + resolution: + { + integrity: sha512-FijqlqMA7DmRdg/aINBSs04y8XNTYw/lr1gJ2WsmBnnaNw1iS43EPkJW+zK7z65auG3AWRFXWj+NcTQwYptUog==, + } + engines: { node: ">=6.9.0" } + peerDependencies: + "@babel/core": ^7.0.0-0 + + "@babel/plugin-transform-regexp-modifiers@7.28.6": + resolution: + { + integrity: sha512-QGWAepm9qxpaIs7UM9FvUSnCGlb8Ua1RhyM4/veAxLwt3gMat/LSGrZixyuj4I6+Kn9iwvqCyPTtbdxanYoWYg==, + } + engines: { node: ">=6.9.0" } + peerDependencies: + "@babel/core": ^7.0.0 + + "@babel/plugin-transform-reserved-words@7.27.1": + resolution: + { + integrity: sha512-V2ABPHIJX4kC7HegLkYoDpfg9PVmuWy/i6vUM5eGK22bx4YVFD3M5F0QQnWQoDs6AGsUWTVOopBiMFQgHaSkVw==, + } + engines: { node: ">=6.9.0" } + peerDependencies: + "@babel/core": ^7.0.0-0 + + "@babel/plugin-transform-shorthand-properties@7.27.1": + resolution: + { + integrity: sha512-N/wH1vcn4oYawbJ13Y/FxcQrWk63jhfNa7jef0ih7PHSIHX2LB7GWE1rkPrOnka9kwMxb6hMl19p7lidA+EHmQ==, + } + engines: { node: ">=6.9.0" } + peerDependencies: + "@babel/core": ^7.0.0-0 + + "@babel/plugin-transform-spread@7.28.6": + resolution: + { + integrity: sha512-9U4QObUC0FtJl05AsUcodau/RWDytrU6uKgkxu09mLR9HLDAtUMoPuuskm5huQsoktmsYpI+bGmq+iapDcriKA==, + } + engines: { node: ">=6.9.0" } + peerDependencies: + "@babel/core": ^7.0.0-0 + + "@babel/plugin-transform-sticky-regex@7.27.1": + resolution: + { + integrity: sha512-lhInBO5bi/Kowe2/aLdBAawijx+q1pQzicSgnkB6dUPc1+RC8QmJHKf2OjvU+NZWitguJHEaEmbV6VWEouT58g==, + } + engines: { node: ">=6.9.0" } + peerDependencies: + "@babel/core": ^7.0.0-0 + + "@babel/plugin-transform-template-literals@7.27.1": + resolution: + { + integrity: sha512-fBJKiV7F2DxZUkg5EtHKXQdbsbURW3DZKQUWphDum0uRP6eHGGa/He9mc0mypL680pb+e/lDIthRohlv8NCHkg==, + } + engines: { node: ">=6.9.0" } + peerDependencies: + "@babel/core": ^7.0.0-0 + + "@babel/plugin-transform-typeof-symbol@7.27.1": + resolution: + { + integrity: sha512-RiSILC+nRJM7FY5srIyc4/fGIwUhyDuuBSdWn4y6yT6gm652DpCHZjIipgn6B7MQ1ITOUnAKWixEUjQRIBIcLw==, + } + engines: { node: ">=6.9.0" } + peerDependencies: + "@babel/core": ^7.0.0-0 + + "@babel/plugin-transform-typescript@7.28.6": + resolution: + { + integrity: sha512-0YWL2RFxOqEm9Efk5PvreamxPME8OyY0wM5wh5lHjF+VtVhdneCWGzZeSqzOfiobVqQaNCd2z0tQvnI9DaPWPw==, + } + engines: { node: ">=6.9.0" } + peerDependencies: + "@babel/core": ^7.0.0-0 + + "@babel/plugin-transform-unicode-escapes@7.27.1": + resolution: + { + integrity: sha512-Ysg4v6AmF26k9vpfFuTZg8HRfVWzsh1kVfowA23y9j/Gu6dOuahdUVhkLqpObp3JIv27MLSii6noRnuKN8H0Mg==, + } + engines: { node: ">=6.9.0" } + peerDependencies: + "@babel/core": ^7.0.0-0 + + "@babel/plugin-transform-unicode-property-regex@7.28.6": + resolution: + { + integrity: sha512-4Wlbdl/sIZjzi/8St0evF0gEZrgOswVO6aOzqxh1kDZOl9WmLrHq2HtGhnOJZmHZYKP8WZ1MDLCt5DAWwRo57A==, + } + engines: { node: ">=6.9.0" } + peerDependencies: + "@babel/core": ^7.0.0-0 + + "@babel/plugin-transform-unicode-regex@7.27.1": + resolution: + { + integrity: sha512-xvINq24TRojDuyt6JGtHmkVkrfVV3FPT16uytxImLeBZqW3/H52yN+kM1MGuyPkIQxrzKwPHs5U/MP3qKyzkGw==, + } + engines: { node: ">=6.9.0" } + peerDependencies: + "@babel/core": ^7.0.0-0 + + "@babel/plugin-transform-unicode-sets-regex@7.28.6": + resolution: + { + integrity: sha512-/wHc/paTUmsDYN7SZkpWxogTOBNnlx7nBQYfy6JJlCT7G3mVhltk3e++N7zV0XfgGsrqBxd4rJQt9H16I21Y1Q==, + } + engines: { node: ">=6.9.0" } + peerDependencies: + "@babel/core": ^7.0.0 + + "@babel/preset-env@7.29.2": + resolution: + { + integrity: sha512-DYD23veRYGvBFhcTY1iUvJnDNpuqNd/BzBwCvzOTKUnJjKg5kpUBh3/u9585Agdkgj+QuygG7jLfOPWMa2KVNw==, + } + engines: { node: ">=6.9.0" } + peerDependencies: + "@babel/core": ^7.0.0-0 + + "@babel/preset-modules@0.1.6-no-external-plugins": + resolution: + { + integrity: sha512-HrcgcIESLm9aIR842yhJ5RWan/gebQUJ6E/E5+rf0y9o6oj7w0Br+sWuL6kEQ/o/AdfvR1Je9jG18/gnpwjEyA==, + } + peerDependencies: + "@babel/core": ^7.0.0-0 || ^8.0.0-0 <8.0.0 + + "@babel/preset-react@7.28.5": + resolution: + { + integrity: sha512-Z3J8vhRq7CeLjdC58jLv4lnZ5RKFUJWqH5emvxmv9Hv3BD1T9R/Im713R4MTKwvFaV74ejZ3sM01LyEKk4ugNQ==, + } + engines: { node: ">=6.9.0" } + peerDependencies: + "@babel/core": ^7.0.0-0 + + "@babel/preset-typescript@7.28.5": + resolution: + { + integrity: sha512-+bQy5WOI2V6LJZpPVxY+yp66XdZ2yifu0Mc1aP5CQKgjn4QM5IN2i5fAZ4xKop47pr8rpVhiAeu+nDQa12C8+g==, + } + engines: { node: ">=6.9.0" } + peerDependencies: + "@babel/core": ^7.0.0-0 + + "@babel/runtime@7.29.2": + resolution: + { + integrity: sha512-JiDShH45zKHWyGe4ZNVRrCjBz8Nh9TMmZG1kh4QTK8hCBTWBi8Da+i7s1fJw7/lYpM4ccepSNfqzZ/QvABBi5g==, + } + engines: { node: ">=6.9.0" } + + "@babel/template@7.28.6": + resolution: + { + integrity: sha512-YA6Ma2KsCdGb+WC6UpBVFJGXL58MDA6oyONbjyF/+5sBgxY/dwkhLogbMT2GXXyU84/IhRw/2D1Os1B/giz+BQ==, + } + engines: { node: ">=6.9.0" } + + "@babel/traverse@7.29.0": + resolution: + { + integrity: sha512-4HPiQr0X7+waHfyXPZpWPfWL/J7dcN1mx9gL6WdQVMbPnF3+ZhSMs8tCxN7oHddJE9fhNE7+lxdnlyemKfJRuA==, + } + engines: { node: ">=6.9.0" } + + "@babel/types@7.29.0": + resolution: + { + integrity: sha512-LwdZHpScM4Qz8Xw2iKSzS+cfglZzJGvofQICy7W7v4caru4EaAmyUuO6BGrbyQ2mYV11W0U8j5mBhd14dd3B0A==, + } + engines: { node: ">=6.9.0" } + + "@bcoe/v8-coverage@1.0.2": + resolution: + { + integrity: sha512-6zABk/ECA/QYSCQ1NGiVwwbQerUCZ+TQbp64Q3AgmfNvurHH0j8TtXa1qbShXA6qqkpAj4V5W8pP6mLe1mcMqA==, + } + engines: { node: ">=18" } + + "@bufbuild/protobuf@1.10.1": + resolution: + { + integrity: sha512-wJ8ReQbHxsAfXhrf9ixl0aYbZorRuOWpBNzm8pL8ftmSxQx/wnJD5Eg861NwJU/czy2VXFIebCeZnZrI9rktIQ==, + } + + "@codecov/bundler-plugin-core@1.9.1": + resolution: + { + integrity: sha512-dt3ic7gMswz4p/qdkYPVJwXlLiLsz55rBBn2I7mr0HTG8pCoLRqnANJIwo5WrqGBZgPyVSMPBqBra6VxLWfDyA==, + } + engines: { node: ">=18.0.0" } + + "@codecov/vite-plugin@1.9.1": + resolution: + { + integrity: sha512-S6Yne7comVulJ1jD3T7rCfYFHPR0zUjAYoLjUDPXNJCUrdzWJdf/ak/UepE7TicqQG+yBa6eb5WusqcPgg+1AQ==, + } + engines: { node: ">=18.0.0" } + peerDependencies: + vite: 4.x || 5.x || 6.x + + "@csstools/cascade-layer-name-parser@2.0.5": + resolution: + { + integrity: sha512-p1ko5eHgV+MgXFVa4STPKpvPxr6ReS8oS2jzTukjR74i5zJNyWO1ZM1m8YKBXnzDKWfBN1ztLYlHxbVemDD88A==, + } + engines: { node: ">=18" } + peerDependencies: + "@csstools/css-parser-algorithms": ^3.0.5 + "@csstools/css-tokenizer": ^3.0.4 + + "@csstools/color-helpers@5.1.0": + resolution: + { + integrity: sha512-S11EXWJyy0Mz5SYvRmY8nJYTFFd1LCNV+7cXyAgQtOOuzb4EsgfqDufL+9esx72/eLhsRdGZwaldu/h+E4t4BA==, + } + engines: { node: ">=18" } + + "@csstools/css-calc@2.1.4": + resolution: + { + integrity: sha512-3N8oaj+0juUw/1H3YwmDDJXCgTB1gKU6Hc/bB502u9zR0q2vd786XJH9QfrKIEgFlZmhZiq6epXl4rHqhzsIgQ==, + } + engines: { node: ">=18" } + peerDependencies: + "@csstools/css-parser-algorithms": ^3.0.5 + "@csstools/css-tokenizer": ^3.0.4 + + "@csstools/css-color-parser@3.1.0": + resolution: + { + integrity: sha512-nbtKwh3a6xNVIp/VRuXV64yTKnb1IjTAEEh3irzS+HkKjAOYLTGNb9pmVNntZ8iVBHcWDA2Dof0QtPgFI1BaTA==, + } + engines: { node: ">=18" } + peerDependencies: + "@csstools/css-parser-algorithms": ^3.0.5 + "@csstools/css-tokenizer": ^3.0.4 + + "@csstools/css-parser-algorithms@3.0.5": + resolution: + { + integrity: sha512-DaDeUkXZKjdGhgYaHNJTV9pV7Y9B3b644jCLs9Upc3VeNGg6LWARAT6O+Q+/COo+2gg/bM5rhpMAtf70WqfBdQ==, + } + engines: { node: ">=18" } + peerDependencies: + "@csstools/css-tokenizer": ^3.0.4 + + "@csstools/css-tokenizer@3.0.4": + resolution: + { + integrity: sha512-Vd/9EVDiu6PPJt9yAh6roZP6El1xHrdvIVGjyBsHR0RYwNHgL7FJPyIIW4fANJNG6FtyZfvlRPpFI4ZM/lubvw==, + } + engines: { node: ">=18" } + + "@csstools/media-query-list-parser@4.0.3": + resolution: + { + integrity: sha512-HAYH7d3TLRHDOUQK4mZKf9k9Ph/m8Akstg66ywKR4SFAigjs3yBiUeZtFxywiTm5moZMAp/5W/ZuFnNXXYLuuQ==, + } + engines: { node: ">=18" } + peerDependencies: + "@csstools/css-parser-algorithms": ^3.0.5 + "@csstools/css-tokenizer": ^3.0.4 + + "@csstools/postcss-alpha-function@1.0.1": + resolution: + { + integrity: sha512-isfLLwksH3yHkFXfCI2Gcaqg7wGGHZZwunoJzEZk0yKYIokgre6hYVFibKL3SYAoR1kBXova8LB+JoO5vZzi9w==, + } + engines: { node: ">=18" } + peerDependencies: + postcss: ^8.4 + + "@csstools/postcss-cascade-layers@5.0.2": + resolution: + { + integrity: sha512-nWBE08nhO8uWl6kSAeCx4im7QfVko3zLrtgWZY4/bP87zrSPpSyN/3W3TDqz1jJuH+kbKOHXg5rJnK+ZVYcFFg==, + } + engines: { node: ">=18" } + peerDependencies: + postcss: ^8.4 + + "@csstools/postcss-color-function-display-p3-linear@1.0.1": + resolution: + { + integrity: sha512-E5qusdzhlmO1TztYzDIi8XPdPoYOjoTY6HBYBCYSj+Gn4gQRBlvjgPQXzfzuPQqt8EhkC/SzPKObg4Mbn8/xMg==, + } + engines: { node: ">=18" } + peerDependencies: + postcss: ^8.4 + + "@csstools/postcss-color-function@4.0.12": + resolution: + { + integrity: sha512-yx3cljQKRaSBc2hfh8rMZFZzChaFgwmO2JfFgFr1vMcF3C/uyy5I4RFIBOIWGq1D+XbKCG789CGkG6zzkLpagA==, + } + engines: { node: ">=18" } + peerDependencies: + postcss: ^8.4 + + "@csstools/postcss-color-mix-function@3.0.12": + resolution: + { + integrity: sha512-4STERZfCP5Jcs13P1U5pTvI9SkgLgfMUMhdXW8IlJWkzOOOqhZIjcNhWtNJZes2nkBDsIKJ0CJtFtuaZ00moag==, + } + engines: { node: ">=18" } + peerDependencies: + postcss: ^8.4 + + "@csstools/postcss-color-mix-variadic-function-arguments@1.0.2": + resolution: + { + integrity: sha512-rM67Gp9lRAkTo+X31DUqMEq+iK+EFqsidfecmhrteErxJZb6tUoJBVQca1Vn1GpDql1s1rD1pKcuYzMsg7Z1KQ==, + } + engines: { node: ">=18" } + peerDependencies: + postcss: ^8.4 + + "@csstools/postcss-content-alt-text@2.0.8": + resolution: + { + integrity: sha512-9SfEW9QCxEpTlNMnpSqFaHyzsiRpZ5J5+KqCu1u5/eEJAWsMhzT40qf0FIbeeglEvrGRMdDzAxMIz3wqoGSb+Q==, + } + engines: { node: ">=18" } + peerDependencies: + postcss: ^8.4 + + "@csstools/postcss-contrast-color-function@2.0.12": + resolution: + { + integrity: sha512-YbwWckjK3qwKjeYz/CijgcS7WDUCtKTd8ShLztm3/i5dhh4NaqzsbYnhm4bjrpFpnLZ31jVcbK8YL77z3GBPzA==, + } + engines: { node: ">=18" } + peerDependencies: + postcss: ^8.4 + + "@csstools/postcss-exponential-functions@2.0.9": + resolution: + { + integrity: sha512-abg2W/PI3HXwS/CZshSa79kNWNZHdJPMBXeZNyPQFbbj8sKO3jXxOt/wF7juJVjyDTc6JrvaUZYFcSBZBhaxjw==, + } + engines: { node: ">=18" } + peerDependencies: + postcss: ^8.4 + + "@csstools/postcss-font-format-keywords@4.0.0": + resolution: + { + integrity: sha512-usBzw9aCRDvchpok6C+4TXC57btc4bJtmKQWOHQxOVKen1ZfVqBUuCZ/wuqdX5GHsD0NRSr9XTP+5ID1ZZQBXw==, + } + engines: { node: ">=18" } + peerDependencies: + postcss: ^8.4 + + "@csstools/postcss-gamut-mapping@2.0.11": + resolution: + { + integrity: sha512-fCpCUgZNE2piVJKC76zFsgVW1apF6dpYsqGyH8SIeCcM4pTEsRTWTLCaJIMKFEundsCKwY1rwfhtrio04RJ4Dw==, + } + engines: { node: ">=18" } + peerDependencies: + postcss: ^8.4 + + "@csstools/postcss-gradients-interpolation-method@5.0.12": + resolution: + { + integrity: sha512-jugzjwkUY0wtNrZlFeyXzimUL3hN4xMvoPnIXxoZqxDvjZRiSh+itgHcVUWzJ2VwD/VAMEgCLvtaJHX+4Vj3Ow==, + } + engines: { node: ">=18" } + peerDependencies: + postcss: ^8.4 + + "@csstools/postcss-hwb-function@4.0.12": + resolution: + { + integrity: sha512-mL/+88Z53KrE4JdePYFJAQWFrcADEqsLprExCM04GDNgHIztwFzj0Mbhd/yxMBngq0NIlz58VVxjt5abNs1VhA==, + } + engines: { node: ">=18" } + peerDependencies: + postcss: ^8.4 + + "@csstools/postcss-ic-unit@4.0.4": + resolution: + { + integrity: sha512-yQ4VmossuOAql65sCPppVO1yfb7hDscf4GseF0VCA/DTDaBc0Wtf8MTqVPfjGYlT5+2buokG0Gp7y0atYZpwjg==, + } + engines: { node: ">=18" } + peerDependencies: + postcss: ^8.4 + + "@csstools/postcss-initial@2.0.1": + resolution: + { + integrity: sha512-L1wLVMSAZ4wovznquK0xmC7QSctzO4D0Is590bxpGqhqjboLXYA16dWZpfwImkdOgACdQ9PqXsuRroW6qPlEsg==, + } + engines: { node: ">=18" } + peerDependencies: + postcss: ^8.4 + + "@csstools/postcss-is-pseudo-class@5.0.3": + resolution: + { + integrity: sha512-jS/TY4SpG4gszAtIg7Qnf3AS2pjcUM5SzxpApOrlndMeGhIbaTzWBzzP/IApXoNWEW7OhcjkRT48jnAUIFXhAQ==, + } + engines: { node: ">=18" } + peerDependencies: + postcss: ^8.4 + + "@csstools/postcss-light-dark-function@2.0.11": + resolution: + { + integrity: sha512-fNJcKXJdPM3Lyrbmgw2OBbaioU7yuKZtiXClf4sGdQttitijYlZMD5K7HrC/eF83VRWRrYq6OZ0Lx92leV2LFA==, + } + engines: { node: ">=18" } + peerDependencies: + postcss: ^8.4 + + "@csstools/postcss-logical-float-and-clear@3.0.0": + resolution: + { + integrity: sha512-SEmaHMszwakI2rqKRJgE+8rpotFfne1ZS6bZqBoQIicFyV+xT1UF42eORPxJkVJVrH9C0ctUgwMSn3BLOIZldQ==, + } + engines: { node: ">=18" } + peerDependencies: + postcss: ^8.4 + + "@csstools/postcss-logical-overflow@2.0.0": + resolution: + { + integrity: sha512-spzR1MInxPuXKEX2csMamshR4LRaSZ3UXVaRGjeQxl70ySxOhMpP2252RAFsg8QyyBXBzuVOOdx1+bVO5bPIzA==, + } + engines: { node: ">=18" } + peerDependencies: + postcss: ^8.4 + + "@csstools/postcss-logical-overscroll-behavior@2.0.0": + resolution: + { + integrity: sha512-e/webMjoGOSYfqLunyzByZj5KKe5oyVg/YSbie99VEaSDE2kimFm0q1f6t/6Jo+VVCQ/jbe2Xy+uX+C4xzWs4w==, + } + engines: { node: ">=18" } + peerDependencies: + postcss: ^8.4 + + "@csstools/postcss-logical-resize@3.0.0": + resolution: + { + integrity: sha512-DFbHQOFW/+I+MY4Ycd/QN6Dg4Hcbb50elIJCfnwkRTCX05G11SwViI5BbBlg9iHRl4ytB7pmY5ieAFk3ws7yyg==, + } + engines: { node: ">=18" } + peerDependencies: + postcss: ^8.4 + + "@csstools/postcss-logical-viewport-units@3.0.4": + resolution: + { + integrity: sha512-q+eHV1haXA4w9xBwZLKjVKAWn3W2CMqmpNpZUk5kRprvSiBEGMgrNH3/sJZ8UA3JgyHaOt3jwT9uFa4wLX4EqQ==, + } + engines: { node: ">=18" } + peerDependencies: + postcss: ^8.4 + + "@csstools/postcss-media-minmax@2.0.9": + resolution: + { + integrity: sha512-af9Qw3uS3JhYLnCbqtZ9crTvvkR+0Se+bBqSr7ykAnl9yKhk6895z9rf+2F4dClIDJWxgn0iZZ1PSdkhrbs2ig==, + } + engines: { node: ">=18" } + peerDependencies: + postcss: ^8.4 + + "@csstools/postcss-media-queries-aspect-ratio-number-values@3.0.5": + resolution: + { + integrity: sha512-zhAe31xaaXOY2Px8IYfoVTB3wglbJUVigGphFLj6exb7cjZRH9A6adyE22XfFK3P2PzwRk0VDeTJmaxpluyrDg==, + } + engines: { node: ">=18" } + peerDependencies: + postcss: ^8.4 + + "@csstools/postcss-nested-calc@4.0.0": + resolution: + { + integrity: sha512-jMYDdqrQQxE7k9+KjstC3NbsmC063n1FTPLCgCRS2/qHUbHM0mNy9pIn4QIiQGs9I/Bg98vMqw7mJXBxa0N88A==, + } + engines: { node: ">=18" } + peerDependencies: + postcss: ^8.4 + + "@csstools/postcss-normalize-display-values@4.0.1": + resolution: + { + integrity: sha512-TQUGBuRvxdc7TgNSTevYqrL8oItxiwPDixk20qCB5me/W8uF7BPbhRrAvFuhEoywQp/woRsUZ6SJ+sU5idZAIA==, + } + engines: { node: ">=18" } + peerDependencies: + postcss: ^8.4 + + "@csstools/postcss-oklab-function@4.0.12": + resolution: + { + integrity: sha512-HhlSmnE1NKBhXsTnNGjxvhryKtO7tJd1w42DKOGFD6jSHtYOrsJTQDKPMwvOfrzUAk8t7GcpIfRyM7ssqHpFjg==, + } + engines: { node: ">=18" } + peerDependencies: + postcss: ^8.4 + + "@csstools/postcss-position-area-property@1.0.0": + resolution: + { + integrity: sha512-fUP6KR8qV2NuUZV3Cw8itx0Ep90aRjAZxAEzC3vrl6yjFv+pFsQbR18UuQctEKmA72K9O27CoYiKEgXxkqjg8Q==, + } + engines: { node: ">=18" } + peerDependencies: + postcss: ^8.4 + + "@csstools/postcss-progressive-custom-properties@4.2.1": + resolution: + { + integrity: sha512-uPiiXf7IEKtUQXsxu6uWtOlRMXd2QWWy5fhxHDnPdXKCQckPP3E34ZgDoZ62r2iT+UOgWsSbM4NvHE5m3mAEdw==, + } + engines: { node: ">=18" } + peerDependencies: + postcss: ^8.4 + + "@csstools/postcss-property-rule-prelude-list@1.0.0": + resolution: + { + integrity: sha512-IxuQjUXq19fobgmSSvUDO7fVwijDJaZMvWQugxfEUxmjBeDCVaDuMpsZ31MsTm5xbnhA+ElDi0+rQ7sQQGisFA==, + } + engines: { node: ">=18" } + peerDependencies: + postcss: ^8.4 + + "@csstools/postcss-random-function@2.0.1": + resolution: + { + integrity: sha512-q+FQaNiRBhnoSNo+GzqGOIBKoHQ43lYz0ICrV+UudfWnEF6ksS6DsBIJSISKQT2Bvu3g4k6r7t0zYrk5pDlo8w==, + } + engines: { node: ">=18" } + peerDependencies: + postcss: ^8.4 + + "@csstools/postcss-relative-color-syntax@3.0.12": + resolution: + { + integrity: sha512-0RLIeONxu/mtxRtf3o41Lq2ghLimw0w9ByLWnnEVuy89exmEEq8bynveBxNW3nyHqLAFEeNtVEmC1QK9MZ8Huw==, + } + engines: { node: ">=18" } + peerDependencies: + postcss: ^8.4 + + "@csstools/postcss-scope-pseudo-class@4.0.1": + resolution: + { + integrity: sha512-IMi9FwtH6LMNuLea1bjVMQAsUhFxJnyLSgOp/cpv5hrzWmrUYU5fm0EguNDIIOHUqzXode8F/1qkC/tEo/qN8Q==, + } + engines: { node: ">=18" } + peerDependencies: + postcss: ^8.4 + + "@csstools/postcss-sign-functions@1.1.4": + resolution: + { + integrity: sha512-P97h1XqRPcfcJndFdG95Gv/6ZzxUBBISem0IDqPZ7WMvc/wlO+yU0c5D/OCpZ5TJoTt63Ok3knGk64N+o6L2Pg==, + } + engines: { node: ">=18" } + peerDependencies: + postcss: ^8.4 + + "@csstools/postcss-stepped-value-functions@4.0.9": + resolution: + { + integrity: sha512-h9btycWrsex4dNLeQfyU3y3w40LMQooJWFMm/SK9lrKguHDcFl4VMkncKKoXi2z5rM9YGWbUQABI8BT2UydIcA==, + } + engines: { node: ">=18" } + peerDependencies: + postcss: ^8.4 + + "@csstools/postcss-syntax-descriptor-syntax-production@1.0.1": + resolution: + { + integrity: sha512-GneqQWefjM//f4hJ/Kbox0C6f2T7+pi4/fqTqOFGTL3EjnvOReTqO1qUQ30CaUjkwjYq9qZ41hzarrAxCc4gow==, + } + engines: { node: ">=18" } + peerDependencies: + postcss: ^8.4 + + "@csstools/postcss-system-ui-font-family@1.0.0": + resolution: + { + integrity: sha512-s3xdBvfWYfoPSBsikDXbuorcMG1nN1M6GdU0qBsGfcmNR0A/qhloQZpTxjA3Xsyrk1VJvwb2pOfiOT3at/DuIQ==, + } + engines: { node: ">=18" } + peerDependencies: + postcss: ^8.4 + + "@csstools/postcss-text-decoration-shorthand@4.0.3": + resolution: + { + integrity: sha512-KSkGgZfx0kQjRIYnpsD7X2Om9BUXX/Kii77VBifQW9Ih929hK0KNjVngHDH0bFB9GmfWcR9vJYJJRvw/NQjkrA==, + } + engines: { node: ">=18" } + peerDependencies: + postcss: ^8.4 + + "@csstools/postcss-trigonometric-functions@4.0.9": + resolution: + { + integrity: sha512-Hnh5zJUdpNrJqK9v1/E3BbrQhaDTj5YiX7P61TOvUhoDHnUmsNNxcDAgkQ32RrcWx9GVUvfUNPcUkn8R3vIX6A==, + } + engines: { node: ">=18" } + peerDependencies: + postcss: ^8.4 + + "@csstools/postcss-unset-value@4.0.0": + resolution: + { + integrity: sha512-cBz3tOCI5Fw6NIFEwU3RiwK6mn3nKegjpJuzCndoGq3BZPkUjnsq7uQmIeMNeMbMk7YD2MfKcgCpZwX5jyXqCA==, + } + engines: { node: ">=18" } + peerDependencies: + postcss: ^8.4 + + "@csstools/selector-resolve-nested@3.1.0": + resolution: + { + integrity: sha512-mf1LEW0tJLKfWyvn5KdDrhpxHyuxpbNwTIwOYLIvsTffeyOf85j5oIzfG0yosxDgx/sswlqBnESYUcQH0vgZ0g==, + } + engines: { node: ">=18" } + peerDependencies: + postcss-selector-parser: ^7.0.0 + + "@csstools/selector-specificity@5.0.0": + resolution: + { + integrity: sha512-PCqQV3c4CoVm3kdPhyeZ07VmBRdH2EpMFA/pd9OASpOEC3aXNGoqPDAZ80D0cLpMBxnmk0+yNhGsEx31hq7Gtw==, + } + engines: { node: ">=18" } + peerDependencies: + postcss-selector-parser: ^7.0.0 + + "@csstools/utilities@2.0.0": + resolution: + { + integrity: sha512-5VdOr0Z71u+Yp3ozOx8T11N703wIFGVRgOWbOZMKgglPJsWA54MRIoMNVMa7shUToIhx5J8vX4sOZgD2XiihiQ==, + } + engines: { node: ">=18" } + peerDependencies: + postcss: ^8.4 + + "@emnapi/core@1.9.2": + resolution: + { + integrity: sha512-UC+ZhH3XtczQYfOlu3lNEkdW/p4dsJ1r/bP7H8+rhao3TTTMO1ATq/4DdIi23XuGoFY+Cz0JmCbdVl0hz9jZcA==, + } + + "@emnapi/runtime@1.9.2": + resolution: + { + integrity: sha512-3U4+MIWHImeyu1wnmVygh5WlgfYDtyf0k8AbLhMFxOipihf6nrWC4syIm/SwEeec0mNSafiiNnMJwbza/Is6Lw==, + } + + "@emnapi/wasi-threads@1.2.1": + resolution: + { + integrity: sha512-uTII7OYF+/Mes/MrcIOYp5yOtSMLBWSIoLPpcgwipoiKbli6k322tcoFsxoIIxPDqW01SQGAgko4EzZi2BNv2w==, + } + + "@es-joy/jsdoccomment@0.78.0": + resolution: + { + integrity: sha512-rQkU5u8hNAq2NVRzHnIUUvR6arbO0b6AOlvpTNS48CkiKSn/xtNfOzBK23JE4SiW89DgvU7GtxLVgV4Vn2HBAw==, + } + engines: { node: ">=20.11.0" } + + "@es-joy/resolve.exports@1.2.0": + resolution: + { + integrity: sha512-Q9hjxWI5xBM+qW2enxfe8wDKdFWMfd0Z29k5ZJnuBqD/CasY5Zryj09aCA6owbGATWz+39p5uIdaHXpopOcG8g==, + } + engines: { node: ">=10" } + + "@esbuild/aix-ppc64@0.27.7": + resolution: + { + integrity: sha512-EKX3Qwmhz1eMdEJokhALr0YiD0lhQNwDqkPYyPhiSwKrh7/4KRjQc04sZ8db+5DVVnZ1LmbNDI1uAMPEUBnQPg==, + } + engines: { node: ">=18" } + cpu: [ppc64] + os: [aix] + + "@esbuild/android-arm64@0.27.7": + resolution: + { + integrity: sha512-62dPZHpIXzvChfvfLJow3q5dDtiNMkwiRzPylSCfriLvZeq0a1bWChrGx/BbUbPwOrsWKMn8idSllklzBy+dgQ==, + } + engines: { node: ">=18" } + cpu: [arm64] + os: [android] + + "@esbuild/android-arm@0.27.7": + resolution: + { + integrity: sha512-jbPXvB4Yj2yBV7HUfE2KHe4GJX51QplCN1pGbYjvsyCZbQmies29EoJbkEc+vYuU5o45AfQn37vZlyXy4YJ8RQ==, + } + engines: { node: ">=18" } + cpu: [arm] + os: [android] + + "@esbuild/android-x64@0.27.7": + resolution: + { + integrity: sha512-x5VpMODneVDb70PYV2VQOmIUUiBtY3D3mPBG8NxVk5CogneYhkR7MmM3yR/uMdITLrC1ml/NV1rj4bMJuy9MCg==, + } + engines: { node: ">=18" } + cpu: [x64] + os: [android] + + "@esbuild/darwin-arm64@0.27.7": + resolution: + { + integrity: sha512-5lckdqeuBPlKUwvoCXIgI2D9/ABmPq3Rdp7IfL70393YgaASt7tbju3Ac+ePVi3KDH6N2RqePfHnXkaDtY9fkw==, + } + engines: { node: ">=18" } + cpu: [arm64] + os: [darwin] + + "@esbuild/darwin-x64@0.27.7": + resolution: + { + integrity: sha512-rYnXrKcXuT7Z+WL5K980jVFdvVKhCHhUwid+dDYQpH+qu+TefcomiMAJpIiC2EM3Rjtq0sO3StMV/+3w3MyyqQ==, + } + engines: { node: ">=18" } + cpu: [x64] + os: [darwin] + + "@esbuild/freebsd-arm64@0.27.7": + resolution: + { + integrity: sha512-B48PqeCsEgOtzME2GbNM2roU29AMTuOIN91dsMO30t+Ydis3z/3Ngoj5hhnsOSSwNzS+6JppqWsuhTp6E82l2w==, + } + engines: { node: ">=18" } + cpu: [arm64] + os: [freebsd] + + "@esbuild/freebsd-x64@0.27.7": + resolution: + { + integrity: sha512-jOBDK5XEjA4m5IJK3bpAQF9/Lelu/Z9ZcdhTRLf4cajlB+8VEhFFRjWgfy3M1O4rO2GQ/b2dLwCUGpiF/eATNQ==, + } + engines: { node: ">=18" } + cpu: [x64] + os: [freebsd] + + "@esbuild/linux-arm64@0.27.7": + resolution: + { + integrity: sha512-RZPHBoxXuNnPQO9rvjh5jdkRmVizktkT7TCDkDmQ0W2SwHInKCAV95GRuvdSvA7w4VMwfCjUiPwDi0ZO6Nfe9A==, + } + engines: { node: ">=18" } + cpu: [arm64] + os: [linux] + + "@esbuild/linux-arm@0.27.7": + resolution: + { + integrity: sha512-RkT/YXYBTSULo3+af8Ib0ykH8u2MBh57o7q/DAs3lTJlyVQkgQvlrPTnjIzzRPQyavxtPtfg0EopvDyIt0j1rA==, + } + engines: { node: ">=18" } + cpu: [arm] + os: [linux] + + "@esbuild/linux-ia32@0.27.7": + resolution: + { + integrity: sha512-GA48aKNkyQDbd3KtkplYWT102C5sn/EZTY4XROkxONgruHPU72l+gW+FfF8tf2cFjeHaRbWpOYa/uRBz/Xq1Pg==, + } + engines: { node: ">=18" } + cpu: [ia32] + os: [linux] + + "@esbuild/linux-loong64@0.27.7": + resolution: + { + integrity: sha512-a4POruNM2oWsD4WKvBSEKGIiWQF8fZOAsycHOt6JBpZ+JN2n2JH9WAv56SOyu9X5IqAjqSIPTaJkqN8F7XOQ5Q==, + } + engines: { node: ">=18" } + cpu: [loong64] + os: [linux] + + "@esbuild/linux-mips64el@0.27.7": + resolution: + { + integrity: sha512-KabT5I6StirGfIz0FMgl1I+R1H73Gp0ofL9A3nG3i/cYFJzKHhouBV5VWK1CSgKvVaG4q1RNpCTR2LuTVB3fIw==, + } + engines: { node: ">=18" } + cpu: [mips64el] + os: [linux] + + "@esbuild/linux-ppc64@0.27.7": + resolution: + { + integrity: sha512-gRsL4x6wsGHGRqhtI+ifpN/vpOFTQtnbsupUF5R5YTAg+y/lKelYR1hXbnBdzDjGbMYjVJLJTd2OFmMewAgwlQ==, + } + engines: { node: ">=18" } + cpu: [ppc64] + os: [linux] + + "@esbuild/linux-riscv64@0.27.7": + resolution: + { + integrity: sha512-hL25LbxO1QOngGzu2U5xeXtxXcW+/GvMN3ejANqXkxZ/opySAZMrc+9LY/WyjAan41unrR3YrmtTsUpwT66InQ==, + } + engines: { node: ">=18" } + cpu: [riscv64] + os: [linux] + + "@esbuild/linux-s390x@0.27.7": + resolution: + { + integrity: sha512-2k8go8Ycu1Kb46vEelhu1vqEP+UeRVj2zY1pSuPdgvbd5ykAw82Lrro28vXUrRmzEsUV0NzCf54yARIK8r0fdw==, + } + engines: { node: ">=18" } + cpu: [s390x] + os: [linux] + + "@esbuild/linux-x64@0.27.7": + resolution: + { + integrity: sha512-hzznmADPt+OmsYzw1EE33ccA+HPdIqiCRq7cQeL1Jlq2gb1+OyWBkMCrYGBJ+sxVzve2ZJEVeePbLM2iEIZSxA==, + } + engines: { node: ">=18" } + cpu: [x64] + os: [linux] + + "@esbuild/netbsd-arm64@0.27.7": + resolution: + { + integrity: sha512-b6pqtrQdigZBwZxAn1UpazEisvwaIDvdbMbmrly7cDTMFnw/+3lVxxCTGOrkPVnsYIosJJXAsILG9XcQS+Yu6w==, + } + engines: { node: ">=18" } + cpu: [arm64] + os: [netbsd] + + "@esbuild/netbsd-x64@0.27.7": + resolution: + { + integrity: sha512-OfatkLojr6U+WN5EDYuoQhtM+1xco+/6FSzJJnuWiUw5eVcicbyK3dq5EeV/QHT1uy6GoDhGbFpprUiHUYggrw==, + } + engines: { node: ">=18" } + cpu: [x64] + os: [netbsd] + + "@esbuild/openbsd-arm64@0.27.7": + resolution: + { + integrity: sha512-AFuojMQTxAz75Fo8idVcqoQWEHIXFRbOc1TrVcFSgCZtQfSdc1RXgB3tjOn/krRHENUB4j00bfGjyl2mJrU37A==, + } + engines: { node: ">=18" } + cpu: [arm64] + os: [openbsd] + + "@esbuild/openbsd-x64@0.27.7": + resolution: + { + integrity: sha512-+A1NJmfM8WNDv5CLVQYJ5PshuRm/4cI6WMZRg1by1GwPIQPCTs1GLEUHwiiQGT5zDdyLiRM/l1G0Pv54gvtKIg==, + } + engines: { node: ">=18" } + cpu: [x64] + os: [openbsd] + + "@esbuild/openharmony-arm64@0.27.7": + resolution: + { + integrity: sha512-+KrvYb/C8zA9CU/g0sR6w2RBw7IGc5J2BPnc3dYc5VJxHCSF1yNMxTV5LQ7GuKteQXZtspjFbiuW5/dOj7H4Yw==, + } + engines: { node: ">=18" } + cpu: [arm64] + os: [openharmony] + + "@esbuild/sunos-x64@0.27.7": + resolution: + { + integrity: sha512-ikktIhFBzQNt/QDyOL580ti9+5mL/YZeUPKU2ivGtGjdTYoqz6jObj6nOMfhASpS4GU4Q/Clh1QtxWAvcYKamA==, + } + engines: { node: ">=18" } + cpu: [x64] + os: [sunos] + + "@esbuild/win32-arm64@0.27.7": + resolution: + { + integrity: sha512-7yRhbHvPqSpRUV7Q20VuDwbjW5kIMwTHpptuUzV+AA46kiPze5Z7qgt6CLCK3pWFrHeNfDd1VKgyP4O+ng17CA==, + } + engines: { node: ">=18" } + cpu: [arm64] + os: [win32] + + "@esbuild/win32-ia32@0.27.7": + resolution: + { + integrity: sha512-SmwKXe6VHIyZYbBLJrhOoCJRB/Z1tckzmgTLfFYOfpMAx63BJEaL9ExI8x7v0oAO3Zh6D/Oi1gVxEYr5oUCFhw==, + } + engines: { node: ">=18" } + cpu: [ia32] + os: [win32] + + "@esbuild/win32-x64@0.27.7": + resolution: + { + integrity: sha512-56hiAJPhwQ1R4i+21FVF7V8kSD5zZTdHcVuRFMW0hn753vVfQN8xlx4uOPT4xoGH0Z/oVATuR82AiqSTDIpaHg==, + } + engines: { node: ">=18" } + cpu: [x64] + os: [win32] + + "@eslint-community/eslint-utils@4.9.1": + resolution: + { + integrity: sha512-phrYmNiYppR7znFEdqgfWHXR6NCkZEK7hwWDHZUjit/2/U0r6XvkDl0SYnoM51Hq7FhCGdLDT6zxCCOY1hexsQ==, + } + engines: { node: ^12.22.0 || ^14.17.0 || >=16.0.0 } + peerDependencies: + eslint: ^6.0.0 || ^7.0.0 || >=8.0.0 + + "@eslint-community/regexpp@4.12.2": + resolution: + { + integrity: sha512-EriSTlt5OC9/7SXkRSCAhfSxxoSUgBm33OH+IkwbdpgoqsSsUg7y3uh+IICI/Qg4BBWr3U2i39RpmycbxMq4ew==, + } + engines: { node: ^12.0.0 || ^14.0.0 || >=16.0.0 } + + "@eslint/eslintrc@2.1.4": + resolution: + { + integrity: sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==, + } + engines: { node: ^12.22.0 || ^14.17.0 || >=16.0.0 } + + "@eslint/js@8.57.1": + resolution: + { + integrity: sha512-d9zaMRSTIKDLhctzH12MtXvJKSSUhaHcjV+2Z+GK+EEY7XKpP5yR4x+N3TAcHTcu963nIr+TMcCb4DBCYX1z6Q==, + } + engines: { node: ^12.22.0 || ^14.17.0 || >=16.0.0 } + + "@fastify/busboy@2.1.1": + resolution: + { + integrity: sha512-vBZP4NlzfOlerQTnba4aqZoMhE/a9HY7HRqoOPaETQcSQuWEIyZMHGfVu6w9wGtGK5fED5qRs2DteVCjOH60sA==, + } + engines: { node: ">=14" } + + "@floating-ui/core@1.7.5": + resolution: + { + integrity: sha512-1Ih4WTWyw0+lKyFMcBHGbb5U5FtuHJuujoyyr5zTaWS5EYMeT6Jb2AuDeftsCsEuchO+mM2ij5+q9crhydzLhQ==, + } + + "@floating-ui/dom@1.7.4": + resolution: + { + integrity: sha512-OOchDgh4F2CchOX94cRVqhvy7b3AFb+/rQXyswmzmGakRfkMgoWVjfnLWkRirfLEfuD4ysVW16eXzwt3jHIzKA==, + } + + "@floating-ui/dom@1.7.6": + resolution: + { + integrity: sha512-9gZSAI5XM36880PPMm//9dfiEngYoC6Am2izES1FF406YFsjvyBMmeJ2g4SAju3xWwtuynNRFL2s9hgxpLI5SQ==, + } + + "@floating-ui/react-dom@2.1.8": + resolution: + { + integrity: sha512-cC52bHwM/n/CxS87FH0yWdngEZrjdtLW/qVruo68qg+prK7ZQ4YGdut2GyDVpoGeAYe/h899rVeOVm6Oi40k2A==, + } + peerDependencies: + react: ">=16.8.0" + react-dom: ">=16.8.0" + + "@floating-ui/react@0.27.19": + resolution: + { + integrity: sha512-31B8h5mm8YxotlE7/AU/PhNAl8eWxAmjL/v2QOxroDNkTFLk3Uu82u63N3b6TXa4EGJeeZLVcd/9AlNlVqzeog==, + } + peerDependencies: + react: ">=17.0.0" + react-dom: ">=17.0.0" + + "@floating-ui/utils@0.2.11": + resolution: + { + integrity: sha512-RiB/yIh78pcIxl6lLMG0CgBXAZ2Y0eVHqMPYugu+9U0AeT6YBeiJpf7lbdJNIugFP5SIjwNRgo4DhR1Qxi26Gg==, + } + + "@fontsource/inconsolata@5.2.8": + resolution: + { + integrity: sha512-lIZW+WOZYpUH91g9r6rYYhfTmptF3YPPM54ZOs8IYVeeL4SeiAu4tfj7mdr8llYEq31DLYgi6JtGIJa192gB0Q==, + } + + "@fontsource/inter@5.2.8": + resolution: + { + integrity: sha512-P6r5WnJoKiNVV+zvW2xM13gNdFhAEpQ9dQJHt3naLvfg+LkF2ldgSLiF4T41lf1SQCM9QmkqPTn4TH568IRagg==, + } + + "@formatjs/ecma402-abstract@2.3.6": + resolution: + { + integrity: sha512-HJnTFeRM2kVFVr5gr5kH1XP6K0JcJtE7Lzvtr3FS/so5f1kpsqqqxy5JF+FRaO6H2qmcMfAUIox7AJteieRtVw==, + } + + "@formatjs/fast-memoize@2.2.7": + resolution: + { + integrity: sha512-Yabmi9nSvyOMrlSeGGWDiH7rf3a7sIwplbvo/dlz9WCIjzIQAfy1RMf4S0X3yG724n5Ghu2GmEl5NJIV6O9sZQ==, + } + + "@formatjs/fast-memoize@3.1.2": + resolution: + { + integrity: sha512-vPnriihkfK0lzoQGaXq+qXH23VsYyansRTkTgo2aTG0k1NjLFyZimFVdfj4C9JkSE5dm7CEngcQ5TTc1yAyBfQ==, + } + + "@formatjs/intl-durationformat@0.10.4": + resolution: + { + integrity: sha512-SUS4xT3GX43/thXTZojOXMNMB1zUIlLC+3mdyJga7evrgV4jvmgycX9bXfmMNDu7c2TC9gnXySUpUcxMghZrKg==, + } + + "@formatjs/intl-localematcher@0.6.2": + resolution: + { + integrity: sha512-XOMO2Hupl0wdd172Y06h6kLpBz6Dv+J4okPLl4LPtzbr8f66WbIoy4ev98EBuZ6ZK4h5ydTN6XneT4QVpD7cdA==, + } + + "@formatjs/intl-localematcher@0.8.3": + resolution: + { + integrity: sha512-pHUjWb9NuhnMs8+PxQdzBtZRFJHlGhrURGAbm6Ltwl82BFajeuiIR3jblSa7ia3r62rXe/0YtVpUG3xWr5bFCA==, + } + + "@formatjs/intl-segmenter@11.7.12": + resolution: + { + integrity: sha512-3QefVKh5HvaKU80lAFmqUsWmKYWcpiDymsc0HwFvhuVl0dAnMhtbNmzMN50UiC7ZsnbybelNGrm9GZPp4kbbZA==, + } + + "@gulpjs/to-absolute-glob@4.0.0": + resolution: + { + integrity: sha512-kjotm7XJrJ6v+7knhPaRgaT6q8F8K2jiafwYdNHLzmV0uGLuZY43FK6smNSHUPrhq5kX2slCUy+RGG/xGqmIKA==, + } + engines: { node: ">=10.13.0" } + + "@humanwhocodes/config-array@0.13.0": + resolution: + { + integrity: sha512-DZLEEqFWQFiyK6h5YIeynKx7JlvCYWL0cImfSRXZ9l4Sg2efkFGTuFf6vzXjK1cq6IYkU+Eg/JizXw+TD2vRNw==, + } + engines: { node: ">=10.10.0" } + deprecated: Use @eslint/config-array instead + + "@humanwhocodes/module-importer@1.0.1": + resolution: + { + integrity: sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==, + } + engines: { node: ">=12.22" } + + "@humanwhocodes/object-schema@2.0.3": + resolution: + { + integrity: sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==, + } + deprecated: Use @eslint/object-schema instead + + "@isaacs/cliui@8.0.2": + resolution: + { + integrity: sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==, + } + engines: { node: ">=12" } + + "@joshwooding/vite-plugin-react-docgen-typescript@0.7.0": + resolution: + { + integrity: sha512-qvsTEwEFefhdirGOPnu9Wp6ChfIwy2dBCRuETU3uE+4cC+PFoxMSiiEhxk4lOluA34eARHA0OxqsEUYDqRMgeQ==, + } + peerDependencies: + typescript: ">= 4.3.x" + vite: ^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0 + peerDependenciesMeta: + typescript: + optional: true + + "@jridgewell/gen-mapping@0.3.13": + resolution: + { + integrity: sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==, + } + + "@jridgewell/remapping@2.3.5": + resolution: + { + integrity: sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==, + } + + "@jridgewell/resolve-uri@3.1.2": + resolution: + { + integrity: sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==, + } + engines: { node: ">=6.0.0" } + + "@jridgewell/source-map@0.3.11": + resolution: + { + integrity: sha512-ZMp1V8ZFcPG5dIWnQLr3NSI1MiCU7UETdS/A0G8V/XWHvJv3ZsFqutJn1Y5RPmAPX6F3BiE397OqveU/9NCuIA==, + } + + "@jridgewell/sourcemap-codec@1.5.5": + resolution: + { + integrity: sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==, + } + + "@jridgewell/trace-mapping@0.3.31": + resolution: + { + integrity: sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==, + } + + "@livekit/components-core@0.12.13": + resolution: + { + integrity: sha512-DQmi84afHoHjZ62wm8y+XPNIDHTwFHAltjd3lmyXj8UZHOY7wcza4vFt1xnghJOD5wLRY58L1dkAgAw59MgWvw==, + } + engines: { node: ">=18" } + peerDependencies: + livekit-client: ^2.17.2 + tslib: ^2.6.2 + + "@livekit/components-react@2.9.20": + resolution: + { + integrity: sha512-hjkYOsJj9Jbghb7wM5cI8HoVisKeL6Zcy1VnRWTLm0sqVbto8GJp/17T4Udx85mCPY6Jgh8I1Cv0yVzgz7CQtg==, + } + engines: { node: ">=18" } + peerDependencies: + "@livekit/krisp-noise-filter": ^0.2.12 || ^0.3.0 + livekit-client: ^2.17.2 + react: ">=18" + react-dom: ">=18" + tslib: ^2.6.2 + peerDependenciesMeta: + "@livekit/krisp-noise-filter": + optional: true + + "@livekit/mutex@1.1.1": + resolution: + { + integrity: sha512-EsshAucklmpuUAfkABPxJNhzj9v2sG7JuzFDL4ML1oJQSV14sqrpTYnsaOudMAw9yOaW53NU3QQTlUQoRs4czw==, + } + + "@livekit/protocol@1.45.3": + resolution: + { + integrity: sha512-WmMxBTsy4dRBqcrswFwUUlgq3Z0nnhOqKR6tX749Rb/PcB1yBMUtrHxZvcsS6qi3/5+86zHeVG+exmu1sZqfJg==, + } + + "@livekit/track-processors@0.7.2": + resolution: + { + integrity: sha512-lzARBKTbBwqycdR/SwTu6//N0l20BzfDd7grxCXl07676SwRApNtZAK1GJjL1m3dCM3KBqH1aVxjMpNcbOw5uQ==, + } + peerDependencies: + "@types/dom-mediacapture-transform": ^0.1.9 + livekit-client: ^1.12.0 || ^2.1.0 + + "@matrix-org/matrix-sdk-crypto-wasm@18.0.0": + resolution: + { + integrity: sha512-88+n+dvxLI1cjS10UIlKXVYK7TGWbpAnnaDC9fow7ch/hCvdu3dFhJ3tS3/13N9s9+1QFXB4FFuommj+tHJPhQ==, + } + engines: { node: ">= 18" } + + "@mdx-js/react@3.1.1": + resolution: + { + integrity: sha512-f++rKLQgUVYDAtECQ6fn/is15GkEH9+nZPM3MS0RcxVqoTfawHvDlSCH7JbMhAM6uJ32v3eXLvLmLvjGu7PTQw==, + } + peerDependencies: + "@types/react": ">=16" + react: ">=16" + + "@mediapipe/tasks-vision@0.10.34": + resolution: + { + integrity: sha512-KFGyhDsjJ+9WUMcMfjTOpcEp3LJNS3KwC7BfvKrCYELn/7G/5kmwnU7z6Spps+iWQoTGL8xW8i68r65OTa3DwA==, + } + + "@napi-rs/wasm-runtime@1.1.4": + resolution: + { + integrity: sha512-3NQNNgA1YSlJb/kMH1ildASP9HW7/7kYnRI2szWJaofaS1hWmbGI4H+d3+22aGzXXN9IJ+n+GiFVcGipJP18ow==, + } + peerDependencies: + "@emnapi/core": ^1.7.1 + "@emnapi/runtime": ^1.7.1 + + "@nicolo-ribaudo/eslint-scope-5-internals@5.1.1-v1": + resolution: + { + integrity: sha512-54/JRvkLIzzDWshCWfuhadfrfZVPiElY8Fcgmg1HroEly/EDSszzhBAsarCux+D/kOslTRquNzuyGSmUSTTHGg==, + } + + "@nodelib/fs.scandir@2.1.5": + resolution: + { + integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==, + } + engines: { node: ">= 8" } + + "@nodelib/fs.stat@2.0.5": + resolution: + { + integrity: sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==, + } + engines: { node: ">= 8" } + + "@nodelib/fs.walk@1.2.8": + resolution: + { + integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==, + } + engines: { node: ">= 8" } + + "@octokit/auth-token@4.0.0": + resolution: + { + integrity: sha512-tY/msAuJo6ARbK6SPIxZrPBms3xPbfwBrulZe0Wtr/DIY9lje2HeV1uoebShn6mx7SjCHif6EjMvoREj+gZ+SA==, + } + engines: { node: ">= 18" } + + "@octokit/core@5.2.2": + resolution: + { + integrity: sha512-/g2d4sW9nUDJOMz3mabVQvOGhVa4e/BN/Um7yca9Bb2XTzPPnfTWHWQg+IsEYO7M3Vx+EXvaM/I2pJWIMun1bg==, + } + engines: { node: ">= 18" } + + "@octokit/endpoint@9.0.6": + resolution: + { + integrity: sha512-H1fNTMA57HbkFESSt3Y9+FBICv+0jFceJFPWDePYlR/iMGrwM5ph+Dd4XRQs+8X+PUFURLQgX9ChPfhJ/1uNQw==, + } + engines: { node: ">= 18" } + + "@octokit/graphql@7.1.1": + resolution: + { + integrity: sha512-3mkDltSfcDUoa176nlGoA32RGjeWjl3K7F/BwHwRMJUW/IteSa4bnSV8p2ThNkcIcZU2umkZWxwETSSCJf2Q7g==, + } + engines: { node: ">= 18" } + + "@octokit/openapi-types@20.0.0": + resolution: + { + integrity: sha512-EtqRBEjp1dL/15V7WiX5LJMIxxkdiGJnabzYx5Apx4FkQIFgAfKumXeYAqqJCj1s+BMX4cPFIFC4OLCR6stlnA==, + } + + "@octokit/openapi-types@24.2.0": + resolution: + { + integrity: sha512-9sIH3nSUttelJSXUrmGzl7QUBFul0/mB8HRYl3fOlgHbIWG+WnYDXU3v/2zMtAvuzZ/ed00Ei6on975FhBfzrg==, + } + + "@octokit/plugin-paginate-rest@9.2.2": + resolution: + { + integrity: sha512-u3KYkGF7GcZnSD/3UP0S7K5XUFT2FkOQdcfXZGZQPGv3lm4F2Xbf71lvjldr8c1H3nNbF+33cLEkWYbokGWqiQ==, + } + engines: { node: ">= 18" } + peerDependencies: + "@octokit/core": "5" + + "@octokit/plugin-rest-endpoint-methods@10.4.1": + resolution: + { + integrity: sha512-xV1b+ceKV9KytQe3zCVqjg+8GTGfDYwaT1ATU5isiUyVtlVAO3HNdzpS4sr4GBx4hxQ46s7ITtZrAsxG22+rVg==, + } + engines: { node: ">= 18" } + peerDependencies: + "@octokit/core": "5" + + "@octokit/request-error@5.1.1": + resolution: + { + integrity: sha512-v9iyEQJH6ZntoENr9/yXxjuezh4My67CBSu9r6Ve/05Iu5gNgnisNWOsoJHTP6k0Rr0+HQIpnH+kyammu90q/g==, + } + engines: { node: ">= 18" } + + "@octokit/request@8.4.1": + resolution: + { + integrity: sha512-qnB2+SY3hkCmBxZsR/MPCybNmbJe4KAlfWErXq+rBKkQJlbjdJeS85VI9r8UqeLYLvnAenU8Q1okM/0MBsAGXw==, + } + engines: { node: ">= 18" } + + "@octokit/types@12.6.0": + resolution: + { + integrity: sha512-1rhSOfRa6H9w4YwK0yrf5faDaDTb+yLyBUKOCV4xtCDB5VmIPqd/v9yr9o6SAzOAlRxMiRiCic6JVM1/kunVkw==, + } + + "@octokit/types@13.10.0": + resolution: + { + integrity: sha512-ifLaO34EbbPj0Xgro4G5lP5asESjwHracYJvVaPIyXMuiuXLlhic3S47cBdTb+jfODkTE5YtGCLt3Ay3+J97sA==, + } + + "@oxc-project/types@0.124.0": + resolution: + { + integrity: sha512-VBFWMTBvHxS11Z5Lvlr3IWgrwhMTXV+Md+EQF0Xf60+wAdsGFTBx7X7K/hP4pi8N7dcm1RvcHwDxZ16Qx8keUg==, + } + + "@oxc-resolver/binding-android-arm-eabi@11.19.1": + resolution: + { + integrity: sha512-aUs47y+xyXHUKlbhqHUjBABjvycq6YSD7bpxSW7vplUmdzAlJ93yXY6ZR0c1o1x5A/QKbENCvs3+NlY8IpIVzg==, + } + cpu: [arm] + os: [android] + + "@oxc-resolver/binding-android-arm64@11.19.1": + resolution: + { + integrity: sha512-oolbkRX+m7Pq2LNjr/kKgYeC7bRDMVTWPgxBGMjSpZi/+UskVo4jsMU3MLheZV55jL6c3rNelPl4oD60ggYmqA==, + } + cpu: [arm64] + os: [android] + + "@oxc-resolver/binding-darwin-arm64@11.19.1": + resolution: + { + integrity: sha512-nUC6d2i3R5B12sUW4O646qD5cnMXf2oBGPLIIeaRfU9doJRORAbE2SGv4eW6rMqhD+G7nf2Y8TTJTLiiO3Q/dQ==, + } + cpu: [arm64] + os: [darwin] + + "@oxc-resolver/binding-darwin-x64@11.19.1": + resolution: + { + integrity: sha512-cV50vE5+uAgNcFa3QY1JOeKDSkM/9ReIcc/9wn4TavhW/itkDGrXhw9jaKnkQnGbjJ198Yh5nbX/Gr2mr4Z5jQ==, + } + cpu: [x64] + os: [darwin] + + "@oxc-resolver/binding-freebsd-x64@11.19.1": + resolution: + { + integrity: sha512-xZOQiYGFxtk48PBKff+Zwoym7ScPAIVp4c14lfLxizO2LTTTJe5sx9vQNGrBymrf/vatSPNMD4FgsaaRigPkqw==, + } + cpu: [x64] + os: [freebsd] + + "@oxc-resolver/binding-linux-arm-gnueabihf@11.19.1": + resolution: + { + integrity: sha512-lXZYWAC6kaGe/ky2su94e9jN9t6M0/6c+GrSlCqL//XO1cxi5lpAhnJYdyrKfm0ZEr/c7RNyAx3P7FSBcBd5+A==, + } + cpu: [arm] + os: [linux] + + "@oxc-resolver/binding-linux-arm-musleabihf@11.19.1": + resolution: + { + integrity: sha512-veG1kKsuK5+t2IsO9q0DErYVSw2azvCVvWHnfTOS73WE0STdLLB7Q1bB9WR+yHPQM76ASkFyRbogWo1GR1+WbQ==, + } + cpu: [arm] + os: [linux] + + "@oxc-resolver/binding-linux-arm64-gnu@11.19.1": + resolution: + { + integrity: sha512-heV2+jmXyYnUrpUXSPugqWDRpnsQcDm2AX4wzTuvgdlZfoNYO0O3W2AVpJYaDn9AG4JdM6Kxom8+foE7/BcSig==, + } + cpu: [arm64] + os: [linux] + + "@oxc-resolver/binding-linux-arm64-musl@11.19.1": + resolution: + { + integrity: sha512-jvo2Pjs1c9KPxMuMPIeQsgu0mOJF9rEb3y3TdpsrqwxRM+AN6/nDDwv45n5ZrUnQMsdBy5gIabioMKnQfWo9ew==, + } + cpu: [arm64] + os: [linux] + + "@oxc-resolver/binding-linux-ppc64-gnu@11.19.1": + resolution: + { + integrity: sha512-vLmdNxWCdN7Uo5suays6A/+ywBby2PWBBPXctWPg5V0+eVuzsJxgAn6MMB4mPlshskYbppjpN2Zg83ArHze9gQ==, + } + cpu: [ppc64] + os: [linux] + + "@oxc-resolver/binding-linux-riscv64-gnu@11.19.1": + resolution: + { + integrity: sha512-/b+WgR+VTSBxzgOhDO7TlMXC1ufPIMR6Vj1zN+/x+MnyXGW7prTLzU9eW85Aj7Th7CCEG9ArCbTeqxCzFWdg2w==, + } + cpu: [riscv64] + os: [linux] + + "@oxc-resolver/binding-linux-riscv64-musl@11.19.1": + resolution: + { + integrity: sha512-YlRdeWb9j42p29ROh+h4eg/OQ3dTJlpHSa+84pUM9+p6i3djtPz1q55yLJhgW9XfDch7FN1pQ/Vd6YP+xfRIuw==, + } + cpu: [riscv64] + os: [linux] + + "@oxc-resolver/binding-linux-s390x-gnu@11.19.1": + resolution: + { + integrity: sha512-EDpafVOQWF8/MJynsjOGFThcqhRHy417sRyLfQmeiamJ8qVhSKAn2Dn2VVKUGCjVB9C46VGjhNo7nOPUi1x6uA==, + } + cpu: [s390x] + os: [linux] + + "@oxc-resolver/binding-linux-x64-gnu@11.19.1": + resolution: + { + integrity: sha512-NxjZe+rqWhr+RT8/Ik+5ptA3oz7tUw361Wa5RWQXKnfqwSSHdHyrw6IdcTfYuml9dM856AlKWZIUXDmA9kkiBQ==, + } + cpu: [x64] + os: [linux] + + "@oxc-resolver/binding-linux-x64-musl@11.19.1": + resolution: + { + integrity: sha512-cM/hQwsO3ReJg5kR+SpI69DMfvNCp+A/eVR4b4YClE5bVZwz8rh2Nh05InhwI5HR/9cArbEkzMjcKgTHS6UaNw==, + } + cpu: [x64] + os: [linux] + + "@oxc-resolver/binding-openharmony-arm64@11.19.1": + resolution: + { + integrity: sha512-QF080IowFB0+9Rh6RcD19bdgh49BpQHUW5TajG1qvWHvmrQznTZZjYlgE2ltLXyKY+qs4F/v5xuX1XS7Is+3qA==, + } + cpu: [arm64] + os: [openharmony] + + "@oxc-resolver/binding-wasm32-wasi@11.19.1": + resolution: + { + integrity: sha512-w8UCKhX826cP/ZLokXDS6+milN8y4X7zidsAttEdWlVoamTNf6lhBJldaWr3ukTDiye7s4HRcuPEPOXNC432Vg==, + } + engines: { node: ">=14.0.0" } + cpu: [wasm32] + + "@oxc-resolver/binding-win32-arm64-msvc@11.19.1": + resolution: + { + integrity: sha512-nJ4AsUVZrVKwnU/QRdzPCCrO0TrabBqgJ8pJhXITdZGYOV28TIYystV1VFLbQ7DtAcaBHpocT5/ZJnF78YJPtQ==, + } + cpu: [arm64] + os: [win32] + + "@oxc-resolver/binding-win32-ia32-msvc@11.19.1": + resolution: + { + integrity: sha512-EW+ND5q2Tl+a3pH81l1QbfgbF3HmqgwLfDfVithRFheac8OTcnbXt/JxqD2GbDkb7xYEqy1zNaVFRr3oeG8npA==, + } + cpu: [ia32] + os: [win32] + + "@oxc-resolver/binding-win32-x64-msvc@11.19.1": + resolution: + { + integrity: sha512-6hIU3RQu45B+VNTY4Ru8ppFwjVS/S5qwYyGhBotmjxfEKk41I2DlGtRfGJndZ5+6lneE2pwloqunlOyZuX/XAw==, + } + cpu: [x64] + os: [win32] + + "@parcel/watcher-android-arm64@2.5.6": + resolution: + { + integrity: sha512-YQxSS34tPF/6ZG7r/Ih9xy+kP/WwediEUsqmtf0cuCV5TPPKw/PQHRhueUo6JdeFJaqV3pyjm0GdYjZotbRt/A==, + } + engines: { node: ">= 10.0.0" } + cpu: [arm64] + os: [android] + + "@parcel/watcher-darwin-arm64@2.5.6": + resolution: + { + integrity: sha512-Z2ZdrnwyXvvvdtRHLmM4knydIdU9adO3D4n/0cVipF3rRiwP+3/sfzpAwA/qKFL6i1ModaabkU7IbpeMBgiVEA==, + } + engines: { node: ">= 10.0.0" } + cpu: [arm64] + os: [darwin] + + "@parcel/watcher-darwin-x64@2.5.6": + resolution: + { + integrity: sha512-HgvOf3W9dhithcwOWX9uDZyn1lW9R+7tPZ4sug+NGrGIo4Rk1hAXLEbcH1TQSqxts0NYXXlOWqVpvS1SFS4fRg==, + } + engines: { node: ">= 10.0.0" } + cpu: [x64] + os: [darwin] + + "@parcel/watcher-freebsd-x64@2.5.6": + resolution: + { + integrity: sha512-vJVi8yd/qzJxEKHkeemh7w3YAn6RJCtYlE4HPMoVnCpIXEzSrxErBW5SJBgKLbXU3WdIpkjBTeUNtyBVn8TRng==, + } + engines: { node: ">= 10.0.0" } + cpu: [x64] + os: [freebsd] + + "@parcel/watcher-linux-arm-glibc@2.5.6": + resolution: + { + integrity: sha512-9JiYfB6h6BgV50CCfasfLf/uvOcJskMSwcdH1PHH9rvS1IrNy8zad6IUVPVUfmXr+u+Km9IxcfMLzgdOudz9EQ==, + } + engines: { node: ">= 10.0.0" } + cpu: [arm] + os: [linux] + + "@parcel/watcher-linux-arm-musl@2.5.6": + resolution: + { + integrity: sha512-Ve3gUCG57nuUUSyjBq/MAM0CzArtuIOxsBdQ+ftz6ho8n7s1i9E1Nmk/xmP323r2YL0SONs1EuwqBp2u1k5fxg==, + } + engines: { node: ">= 10.0.0" } + cpu: [arm] + os: [linux] + + "@parcel/watcher-linux-arm64-glibc@2.5.6": + resolution: + { + integrity: sha512-f2g/DT3NhGPdBmMWYoxixqYr3v/UXcmLOYy16Bx0TM20Tchduwr4EaCbmxh1321TABqPGDpS8D/ggOTaljijOA==, + } + engines: { node: ">= 10.0.0" } + cpu: [arm64] + os: [linux] + + "@parcel/watcher-linux-arm64-musl@2.5.6": + resolution: + { + integrity: sha512-qb6naMDGlbCwdhLj6hgoVKJl2odL34z2sqkC7Z6kzir8b5W65WYDpLB6R06KabvZdgoHI/zxke4b3zR0wAbDTA==, + } + engines: { node: ">= 10.0.0" } + cpu: [arm64] + os: [linux] + + "@parcel/watcher-linux-x64-glibc@2.5.6": + resolution: + { + integrity: sha512-kbT5wvNQlx7NaGjzPFu8nVIW1rWqV780O7ZtkjuWaPUgpv2NMFpjYERVi0UYj1msZNyCzGlaCWEtzc+exjMGbQ==, + } + engines: { node: ">= 10.0.0" } + cpu: [x64] + os: [linux] + + "@parcel/watcher-linux-x64-musl@2.5.6": + resolution: + { + integrity: sha512-1JRFeC+h7RdXwldHzTsmdtYR/Ku8SylLgTU/reMuqdVD7CtLwf0VR1FqeprZ0eHQkO0vqsbvFLXUmYm/uNKJBg==, + } + engines: { node: ">= 10.0.0" } + cpu: [x64] + os: [linux] + + "@parcel/watcher-win32-arm64@2.5.6": + resolution: + { + integrity: sha512-3ukyebjc6eGlw9yRt678DxVF7rjXatWiHvTXqphZLvo7aC5NdEgFufVwjFfY51ijYEWpXbqF5jtrK275z52D4Q==, + } + engines: { node: ">= 10.0.0" } + cpu: [arm64] + os: [win32] + + "@parcel/watcher-win32-ia32@2.5.6": + resolution: + { + integrity: sha512-k35yLp1ZMwwee3Ez/pxBi5cf4AoBKYXj00CZ80jUz5h8prpiaQsiRPKQMxoLstNuqe2vR4RNPEAEcjEFzhEz/g==, + } + engines: { node: ">= 10.0.0" } + cpu: [ia32] + os: [win32] + + "@parcel/watcher-win32-x64@2.5.6": + resolution: + { + integrity: sha512-hbQlYcCq5dlAX9Qx+kFb0FHue6vbjlf0FrNzSKdYK2APUf7tGfGxQCk2ihEREmbR6ZMc0MVAD5RIX/41gpUzTw==, + } + engines: { node: ">= 10.0.0" } + cpu: [x64] + os: [win32] + + "@parcel/watcher@2.5.6": + resolution: + { + integrity: sha512-tmmZ3lQxAe/k/+rNnXQRawJ4NjxO2hqiOLTHvWchtGZULp4RyFeh6aU4XdOYBFe2KE1oShQTv4AblOs2iOrNnQ==, + } + engines: { node: ">= 10.0.0" } + + "@pkgjs/parseargs@0.11.0": + resolution: + { + integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==, + } + engines: { node: ">=14" } + + "@playwright/test@1.59.1": + resolution: + { + integrity: sha512-PG6q63nQg5c9rIi4/Z5lR5IVF7yU5MqmKaPOe0HSc0O2cX1fPi96sUQu5j7eo4gKCkB2AnNGoWt7y4/Xx3Kcqg==, + } + engines: { node: ">=18" } + hasBin: true + + "@radix-ui/number@1.1.1": + resolution: + { + integrity: sha512-MkKCwxlXTgz6CFoJx3pCwn07GKp36+aZyu/u2Ln2VrA5DcdyCZkASEDBTd8x5whTQQL5CiYf4prXKLcgQdv29g==, + } + + "@radix-ui/primitive@1.1.3": + resolution: + { + integrity: sha512-JTF99U/6XIjCBo0wqkU5sK10glYe27MRRsfwoiq5zzOEZLHU3A3KCMa5X/azekYRCJ0HlwI0crAXS/5dEHTzDg==, + } + + "@radix-ui/react-arrow@1.1.7": + resolution: + { + integrity: sha512-F+M1tLhO+mlQaOWspE8Wstg+z6PwxwRd8oQ8IXceWz92kfAmalTRf0EjrouQeo7QssEPfCn05B4Ihs1K9WQ/7w==, + } + peerDependencies: + "@types/react": "*" + "@types/react-dom": "*" + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + "@types/react": + optional: true + "@types/react-dom": + optional: true + + "@radix-ui/react-collection@1.1.7": + resolution: + { + integrity: sha512-Fh9rGN0MoI4ZFUNyfFVNU4y9LUz93u9/0K+yLgA2bwRojxM8JU1DyvvMBabnZPBgMWREAJvU2jjVzq+LrFUglw==, + } + peerDependencies: + "@types/react": "*" + "@types/react-dom": "*" + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + "@types/react": + optional: true + "@types/react-dom": + optional: true + + "@radix-ui/react-compose-refs@1.1.2": + resolution: + { + integrity: sha512-z4eqJvfiNnFMHIIvXP3CY57y2WJs5g2v3X0zm9mEJkrkNv4rDxu+sg9Jh8EkXyeqBkB7SOcboo9dMVqhyrACIg==, + } + peerDependencies: + "@types/react": "*" + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + "@types/react": + optional: true + + "@radix-ui/react-context-menu@2.2.16": + resolution: + { + integrity: sha512-O8morBEW+HsVG28gYDZPTrT9UUovQUlJue5YO836tiTJhuIWBm/zQHc7j388sHWtdH/xUZurK9olD2+pcqx5ww==, + } + peerDependencies: + "@types/react": "*" + "@types/react-dom": "*" + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + "@types/react": + optional: true + "@types/react-dom": + optional: true + + "@radix-ui/react-context@1.1.2": + resolution: + { + integrity: sha512-jCi/QKUM2r1Ju5a3J64TH2A5SpKAgh0LpknyqdQ4m6DCV0xJ2HG1xARRwNGPQfi1SLdLWZ1OJz6F4OMBBNiGJA==, + } + peerDependencies: + "@types/react": "*" + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + "@types/react": + optional: true + + "@radix-ui/react-context@1.1.3": + resolution: + { + integrity: sha512-ieIFACdMpYfMEjF0rEf5KLvfVyIkOz6PDGyNnP+u+4xQ6jny3VCgA4OgXOwNx2aUkxn8zx9fiVcM8CfFYv9Lxw==, + } + peerDependencies: + "@types/react": "*" + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + "@types/react": + optional: true + + "@radix-ui/react-dialog@1.1.15": + resolution: + { + integrity: sha512-TCglVRtzlffRNxRMEyR36DGBLJpeusFcgMVD9PZEzAKnUs1lKCgX5u9BmC2Yg+LL9MgZDugFFs1Vl+Jp4t/PGw==, + } + peerDependencies: + "@types/react": "*" + "@types/react-dom": "*" + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + "@types/react": + optional: true + "@types/react-dom": + optional: true + + "@radix-ui/react-direction@1.1.1": + resolution: + { + integrity: sha512-1UEWRX6jnOA2y4H5WczZ44gOOjTEmlqv1uNW4GAJEO5+bauCBhv8snY65Iw5/VOS/ghKN9gr2KjnLKxrsvoMVw==, + } + peerDependencies: + "@types/react": "*" + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + "@types/react": + optional: true + + "@radix-ui/react-dismissable-layer@1.1.11": + resolution: + { + integrity: sha512-Nqcp+t5cTB8BinFkZgXiMJniQH0PsUt2k51FUhbdfeKvc4ACcG2uQniY/8+h1Yv6Kza4Q7lD7PQV0z0oicE0Mg==, + } + peerDependencies: + "@types/react": "*" + "@types/react-dom": "*" + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + "@types/react": + optional: true + "@types/react-dom": + optional: true + + "@radix-ui/react-dropdown-menu@2.1.16": + resolution: + { + integrity: sha512-1PLGQEynI/3OX/ftV54COn+3Sud/Mn8vALg2rWnBLnRaGtJDduNW/22XjlGgPdpcIbiQxjKtb7BkcjP00nqfJw==, + } + peerDependencies: + "@types/react": "*" + "@types/react-dom": "*" + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + "@types/react": + optional: true + "@types/react-dom": + optional: true + + "@radix-ui/react-focus-guards@1.1.3": + resolution: + { + integrity: sha512-0rFg/Rj2Q62NCm62jZw0QX7a3sz6QCQU0LpZdNrJX8byRGaGVTqbrW9jAoIAHyMQqsNpeZ81YgSizOt5WXq0Pw==, + } + peerDependencies: + "@types/react": "*" + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + "@types/react": + optional: true + + "@radix-ui/react-focus-scope@1.1.7": + resolution: + { + integrity: sha512-t2ODlkXBQyn7jkl6TNaw/MtVEVvIGelJDCG41Okq/KwUsJBwQ4XVZsHAVUkK4mBv3ewiAS3PGuUWuY2BoK4ZUw==, + } + peerDependencies: + "@types/react": "*" + "@types/react-dom": "*" + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + "@types/react": + optional: true + "@types/react-dom": + optional: true + + "@radix-ui/react-form@0.1.8": + resolution: + { + integrity: sha512-QM70k4Zwjttifr5a4sZFts9fn8FzHYvQ5PiB19O2HsYibaHSVt9fH9rzB0XZo/YcM+b7t/p7lYCT/F5eOeF5yQ==, + } + peerDependencies: + "@types/react": "*" + "@types/react-dom": "*" + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + "@types/react": + optional: true + "@types/react-dom": + optional: true + + "@radix-ui/react-id@1.1.1": + resolution: + { + integrity: sha512-kGkGegYIdQsOb4XjsfM97rXsiHaBwco+hFI66oO4s9LU+PLAC5oJ7khdOVFxkhsmlbpUqDAvXw11CluXP+jkHg==, + } + peerDependencies: + "@types/react": "*" + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + "@types/react": + optional: true + + "@radix-ui/react-label@2.1.7": + resolution: + { + integrity: sha512-YT1GqPSL8kJn20djelMX7/cTRp/Y9w5IZHvfxQTVHrOqa2yMl7i/UfMqKRU5V7mEyKTrUVgJXhNQPVCG8PBLoQ==, + } + peerDependencies: + "@types/react": "*" + "@types/react-dom": "*" + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + "@types/react": + optional: true + "@types/react-dom": + optional: true + + "@radix-ui/react-menu@2.1.16": + resolution: + { + integrity: sha512-72F2T+PLlphrqLcAotYPp0uJMr5SjP5SL01wfEspJbru5Zs5vQaSHb4VB3ZMJPimgHHCHG7gMOeOB9H3Hdmtxg==, + } + peerDependencies: + "@types/react": "*" + "@types/react-dom": "*" + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + "@types/react": + optional: true + "@types/react-dom": + optional: true + + "@radix-ui/react-popper@1.2.8": + resolution: + { + integrity: sha512-0NJQ4LFFUuWkE7Oxf0htBKS6zLkkjBH+hM1uk7Ng705ReR8m/uelduy1DBo0PyBXPKVnBA6YBlU94MBGXrSBCw==, + } + peerDependencies: + "@types/react": "*" + "@types/react-dom": "*" + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + "@types/react": + optional: true + "@types/react-dom": + optional: true + + "@radix-ui/react-portal@1.1.9": + resolution: + { + integrity: sha512-bpIxvq03if6UNwXZ+HTK71JLh4APvnXntDc6XOX8UVq4XQOVl7lwok0AvIl+b8zgCw3fSaVTZMpAPPagXbKmHQ==, + } + peerDependencies: + "@types/react": "*" + "@types/react-dom": "*" + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + "@types/react": + optional: true + "@types/react-dom": + optional: true + + "@radix-ui/react-presence@1.1.5": + resolution: + { + integrity: sha512-/jfEwNDdQVBCNvjkGit4h6pMOzq8bHkopq458dPt2lMjx+eBQUohZNG9A7DtO/O5ukSbxuaNGXMjHicgwy6rQQ==, + } + peerDependencies: + "@types/react": "*" + "@types/react-dom": "*" + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + "@types/react": + optional: true + "@types/react-dom": + optional: true + + "@radix-ui/react-primitive@2.1.3": + resolution: + { + integrity: sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ==, + } + peerDependencies: + "@types/react": "*" + "@types/react-dom": "*" + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + "@types/react": + optional: true + "@types/react-dom": + optional: true + + "@radix-ui/react-primitive@2.1.4": + resolution: + { + integrity: sha512-9hQc4+GNVtJAIEPEqlYqW5RiYdrr8ea5XQ0ZOnD6fgru+83kqT15mq2OCcbe8KnjRZl5vF3ks69AKz3kh1jrhg==, + } + peerDependencies: + "@types/react": "*" + "@types/react-dom": "*" + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + "@types/react": + optional: true + "@types/react-dom": + optional: true + + "@radix-ui/react-progress@1.1.8": + resolution: + { + integrity: sha512-+gISHcSPUJ7ktBy9RnTqbdKW78bcGke3t6taawyZ71pio1JewwGSJizycs7rLhGTvMJYCQB1DBK4KQsxs7U8dA==, + } + peerDependencies: + "@types/react": "*" + "@types/react-dom": "*" + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + "@types/react": + optional: true + "@types/react-dom": + optional: true + + "@radix-ui/react-roving-focus@1.1.11": + resolution: + { + integrity: sha512-7A6S9jSgm/S+7MdtNDSb+IU859vQqJ/QAtcYQcfFC6W8RS4IxIZDldLR0xqCFZ6DCyrQLjLPsxtTNch5jVA4lA==, + } + peerDependencies: + "@types/react": "*" + "@types/react-dom": "*" + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + "@types/react": + optional: true + "@types/react-dom": + optional: true + + "@radix-ui/react-separator@1.1.8": + resolution: + { + integrity: sha512-sDvqVY4itsKwwSMEe0jtKgfTh+72Sy3gPmQpjqcQneqQ4PFmr/1I0YA+2/puilhggCe2gJcx5EBAYFkWkdpa5g==, + } + peerDependencies: + "@types/react": "*" + "@types/react-dom": "*" + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + "@types/react": + optional: true + "@types/react-dom": + optional: true + + "@radix-ui/react-slider@1.3.6": + resolution: + { + integrity: sha512-JPYb1GuM1bxfjMRlNLE+BcmBC8onfCi60Blk7OBqi2MLTFdS+8401U4uFjnwkOr49BLmXxLC6JHkvAsx5OJvHw==, + } + peerDependencies: + "@types/react": "*" + "@types/react-dom": "*" + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + "@types/react": + optional: true + "@types/react-dom": + optional: true + + "@radix-ui/react-slot@1.2.3": + resolution: + { + integrity: sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A==, + } + peerDependencies: + "@types/react": "*" + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + "@types/react": + optional: true + + "@radix-ui/react-slot@1.2.4": + resolution: + { + integrity: sha512-Jl+bCv8HxKnlTLVrcDE8zTMJ09R9/ukw4qBs/oZClOfoQk/cOTbDn+NceXfV7j09YPVQUryJPHurafcSg6EVKA==, + } + peerDependencies: + "@types/react": "*" + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + "@types/react": + optional: true + + "@radix-ui/react-use-callback-ref@1.1.1": + resolution: + { + integrity: sha512-FkBMwD+qbGQeMu1cOHnuGB6x4yzPjho8ap5WtbEJ26umhgqVXbhekKUQO+hZEL1vU92a3wHwdp0HAcqAUF5iDg==, + } + peerDependencies: + "@types/react": "*" + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + "@types/react": + optional: true + + "@radix-ui/react-use-controllable-state@1.2.2": + resolution: + { + integrity: sha512-BjasUjixPFdS+NKkypcyyN5Pmg83Olst0+c6vGov0diwTEo6mgdqVR6hxcEgFuh4QrAs7Rc+9KuGJ9TVCj0Zzg==, + } + peerDependencies: + "@types/react": "*" + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + "@types/react": + optional: true + + "@radix-ui/react-use-effect-event@0.0.2": + resolution: + { + integrity: sha512-Qp8WbZOBe+blgpuUT+lw2xheLP8q0oatc9UpmiemEICxGvFLYmHm9QowVZGHtJlGbS6A6yJ3iViad/2cVjnOiA==, + } + peerDependencies: + "@types/react": "*" + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + "@types/react": + optional: true + + "@radix-ui/react-use-escape-keydown@1.1.1": + resolution: + { + integrity: sha512-Il0+boE7w/XebUHyBjroE+DbByORGR9KKmITzbR7MyQ4akpORYP/ZmbhAr0DG7RmmBqoOnZdy2QlvajJ2QA59g==, + } + peerDependencies: + "@types/react": "*" + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + "@types/react": + optional: true + + "@radix-ui/react-use-layout-effect@1.1.1": + resolution: + { + integrity: sha512-RbJRS4UWQFkzHTTwVymMTUv8EqYhOp8dOOviLj2ugtTiXRaRQS7GLGxZTLL1jWhMeoSCf5zmcZkqTl9IiYfXcQ==, + } + peerDependencies: + "@types/react": "*" + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + "@types/react": + optional: true + + "@radix-ui/react-use-previous@1.1.1": + resolution: + { + integrity: sha512-2dHfToCj/pzca2Ck724OZ5L0EVrr3eHRNsG/b3xQJLA2hZpVCS99bLAX+hm1IHXDEnzU6by5z/5MIY794/a8NQ==, + } + peerDependencies: + "@types/react": "*" + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + "@types/react": + optional: true + + "@radix-ui/react-use-rect@1.1.1": + resolution: + { + integrity: sha512-QTYuDesS0VtuHNNvMh+CjlKJ4LJickCMUAqjlE3+j8w+RlRpwyX3apEQKGFzbZGdo7XNG1tXa+bQqIE7HIXT2w==, + } + peerDependencies: + "@types/react": "*" + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + "@types/react": + optional: true + + "@radix-ui/react-use-size@1.1.1": + resolution: + { + integrity: sha512-ewrXRDTAqAXlkl6t/fkXWNAhFX9I+CkKlw6zjEwk86RSPKwZr3xpBRso655aqYafwtnbpHLj6toFzmd6xdVptQ==, + } + peerDependencies: + "@types/react": "*" + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + "@types/react": + optional: true + + "@radix-ui/react-visually-hidden@1.2.4": + resolution: + { + integrity: sha512-kaeiyGCe844dkb9AVF+rb4yTyb1LiLN/e3es3nLiRyN4dC8AduBYPMnnNlDjX2VDOcvDEiPnRNMJeWCfsX0txg==, + } + peerDependencies: + "@types/react": "*" + "@types/react-dom": "*" + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + "@types/react": + optional: true + "@types/react-dom": + optional: true + + "@radix-ui/rect@1.1.1": + resolution: + { + integrity: sha512-HPwpGIzkl28mWyZqG52jiqDJ12waP11Pa1lGoiyUkIEuMLBP0oeK/C89esbXrxsky5we7dfd8U58nm0SgAWpVw==, + } + + "@react-spring/animated@10.0.3": + resolution: + { + integrity: sha512-7MrxADV3vaUADn2V9iYhaIL6iOWRx9nCJjYrsk2AHD2kwPr6fg7Pt0v+deX5RnCDmCKNnD6W5fasiyM8D+wzJQ==, + } + peerDependencies: + react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 + + "@react-spring/core@10.0.3": + resolution: + { + integrity: sha512-D4DwNO68oohDf/0HG2G0Uragzb9IA1oXblxrd6MZAcBcUQG2EHUWXewjdECMPLNmQvlYVyyBRH6gPxXM5DX7DQ==, + } + peerDependencies: + react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 + + "@react-spring/rafz@10.0.3": + resolution: + { + integrity: sha512-Ri2/xqt8OnQ2iFKkxKMSF4Nqv0LSWnxXT4jXFzBDsHgeeH/cHxTLupAWUwmV9hAGgmEhBmh5aONtj3J6R/18wg==, + } + + "@react-spring/shared@10.0.3": + resolution: + { + integrity: sha512-geCal66nrkaQzUVhPkGomylo+Jpd5VPK8tPMEDevQEfNSWAQP15swHm+MCRG4wVQrQlTi9lOzKzpRoTL3CA84Q==, + } + peerDependencies: + react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 + + "@react-spring/types@10.0.3": + resolution: + { + integrity: sha512-H5Ixkd2OuSIgHtxuHLTt7aJYfhMXKXT/rK32HPD/kSrOB6q6ooeiWAXkBy7L8F3ZxdkBb9ini9zP9UwnEFzWgQ==, + } + + "@react-spring/web@10.0.3": + resolution: + { + integrity: sha512-ndU+kWY81rHsT7gTFtCJ6mrVhaJ6grFmgTnENipzmKqot4HGf5smPNK+cZZJqoGeDsj9ZsiWPW4geT/NyD484A==, + } + peerDependencies: + react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 + react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 + + "@rolldown/binding-android-arm64@1.0.0-rc.15": + resolution: + { + integrity: sha512-YYe6aWruPZDtHNpwu7+qAHEMbQ/yRl6atqb/AhznLTnD3UY99Q1jE7ihLSahNWkF4EqRPVC4SiR4O0UkLK02tA==, + } + engines: { node: ^20.19.0 || >=22.12.0 } + cpu: [arm64] + os: [android] + + "@rolldown/binding-darwin-arm64@1.0.0-rc.15": + resolution: + { + integrity: sha512-oArR/ig8wNTPYsXL+Mzhs0oxhxfuHRfG7Ikw7jXsw8mYOtk71W0OkF2VEVh699pdmzjPQsTjlD1JIOoHkLP1Fg==, + } + engines: { node: ^20.19.0 || >=22.12.0 } + cpu: [arm64] + os: [darwin] + + "@rolldown/binding-darwin-x64@1.0.0-rc.15": + resolution: + { + integrity: sha512-YzeVqOqjPYvUbJSWJ4EDL8ahbmsIXQpgL3JVipmN+MX0XnXMeWomLN3Fb+nwCmP/jfyqte5I3XRSm7OfQrbyxw==, + } + engines: { node: ^20.19.0 || >=22.12.0 } + cpu: [x64] + os: [darwin] + + "@rolldown/binding-freebsd-x64@1.0.0-rc.15": + resolution: + { + integrity: sha512-9Erhx956jeQ0nNTyif1+QWAXDRD38ZNjr//bSHrt6wDwB+QkAfl2q6Mn1k6OBPerznjRmbM10lgRb1Pli4xZPw==, + } + engines: { node: ^20.19.0 || >=22.12.0 } + cpu: [x64] + os: [freebsd] + + "@rolldown/binding-linux-arm-gnueabihf@1.0.0-rc.15": + resolution: + { + integrity: sha512-cVwk0w8QbZJGTnP/AHQBs5yNwmpgGYStL88t4UIaqcvYJWBfS0s3oqVLZPwsPU6M0zlW4GqjP0Zq5MnAGwFeGA==, + } + engines: { node: ^20.19.0 || >=22.12.0 } + cpu: [arm] + os: [linux] + + "@rolldown/binding-linux-arm64-gnu@1.0.0-rc.15": + resolution: + { + integrity: sha512-eBZ/u8iAK9SoHGanqe/jrPnY0JvBN6iXbVOsbO38mbz+ZJsaobExAm1Iu+rxa4S1l2FjG0qEZn4Rc6X8n+9M+w==, + } + engines: { node: ^20.19.0 || >=22.12.0 } + cpu: [arm64] + os: [linux] + + "@rolldown/binding-linux-arm64-musl@1.0.0-rc.15": + resolution: + { + integrity: sha512-ZvRYMGrAklV9PEkgt4LQM6MjQX2P58HPAuecwYObY2DhS2t35R0I810bKi0wmaYORt6m/2Sm+Z+nFgb0WhXNcQ==, + } + engines: { node: ^20.19.0 || >=22.12.0 } + cpu: [arm64] + os: [linux] + + "@rolldown/binding-linux-ppc64-gnu@1.0.0-rc.15": + resolution: + { + integrity: sha512-VDpgGBzgfg5hLg+uBpCLoFG5kVvEyafmfxGUV0UHLcL5irxAK7PKNeC2MwClgk6ZAiNhmo9FLhRYgvMmedLtnQ==, + } + engines: { node: ^20.19.0 || >=22.12.0 } + cpu: [ppc64] + os: [linux] + + "@rolldown/binding-linux-s390x-gnu@1.0.0-rc.15": + resolution: + { + integrity: sha512-y1uXY3qQWCzcPgRJATPSOUP4tCemh4uBdY7e3EZbVwCJTY3gLJWnQABgeUetvED+bt1FQ01OeZwvhLS2bpNrAQ==, + } + engines: { node: ^20.19.0 || >=22.12.0 } + cpu: [s390x] + os: [linux] + + "@rolldown/binding-linux-x64-gnu@1.0.0-rc.15": + resolution: + { + integrity: sha512-023bTPBod7J3Y/4fzAN6QtpkSABR0rigtrwaP+qSEabUh5zf6ELr9Nc7GujaROuPY3uwdSIXWrvhn1KxOvurWA==, + } + engines: { node: ^20.19.0 || >=22.12.0 } + cpu: [x64] + os: [linux] + + "@rolldown/binding-linux-x64-musl@1.0.0-rc.15": + resolution: + { + integrity: sha512-witB2O0/hU4CgfOOKUoeFgQ4GktPi1eEbAhaLAIpgD6+ZnhcPkUtPsoKKHRzmOoWPZue46IThdSgdo4XneOLYw==, + } + engines: { node: ^20.19.0 || >=22.12.0 } + cpu: [x64] + os: [linux] + + "@rolldown/binding-openharmony-arm64@1.0.0-rc.15": + resolution: + { + integrity: sha512-UCL68NJ0Ud5zRipXZE9dF5PmirzJE4E4BCIOOssEnM7wLDsxjc6Qb0sGDxTNRTP53I6MZpygyCpY8Aa8sPfKPg==, + } + engines: { node: ^20.19.0 || >=22.12.0 } + cpu: [arm64] + os: [openharmony] + + "@rolldown/binding-wasm32-wasi@1.0.0-rc.15": + resolution: + { + integrity: sha512-ApLruZq/ig+nhaE7OJm4lDjayUnOHVUa77zGeqnqZ9pn0ovdVbbNPerVibLXDmWeUZXjIYIT8V3xkT58Rm9u5Q==, + } + engines: { node: ">=14.0.0" } + cpu: [wasm32] + + "@rolldown/binding-win32-arm64-msvc@1.0.0-rc.15": + resolution: + { + integrity: sha512-KmoUoU7HnN+Si5YWJigfTws1jz1bKBYDQKdbLspz0UaqjjFkddHsqorgiW1mxcAj88lYUE6NC/zJNwT+SloqtA==, + } + engines: { node: ^20.19.0 || >=22.12.0 } + cpu: [arm64] + os: [win32] + + "@rolldown/binding-win32-x64-msvc@1.0.0-rc.15": + resolution: + { + integrity: sha512-3P2A8L+x75qavWLe/Dll3EYBJLQmtkJN8rfh+U/eR3MqMgL/h98PhYI+JFfXuDPgPeCB7iZAKiqii5vqOvnA0g==, + } + engines: { node: ^20.19.0 || >=22.12.0 } + cpu: [x64] + os: [win32] + + "@rolldown/pluginutils@1.0.0-beta.27": + resolution: + { + integrity: sha512-+d0F4MKMCbeVUJwG96uQ4SgAznZNSq93I3V+9NHA4OpvqG8mRCpGdKmK8l/dl02h2CCDHwW2FqilnTyDcAnqjA==, + } + + "@rolldown/pluginutils@1.0.0-rc.15": + resolution: + { + integrity: sha512-UromN0peaE53IaBRe9W7CjrZgXl90fqGpK+mIZbA3qSTeYqg3pqpROBdIPvOG3F5ereDHNwoHBI2e50n1BDr1g==, + } + + "@rollup/plugin-inject@5.0.5": + resolution: + { + integrity: sha512-2+DEJbNBoPROPkgTDNe8/1YXWcqxbN5DTjASVIOx8HS+pITXushyNiBV56RB08zuptzz8gT3YfkqriTBVycepg==, + } + engines: { node: ">=14.0.0" } + peerDependencies: + rollup: ^1.20.0||^2.0.0||^3.0.0||^4.0.0 + peerDependenciesMeta: + rollup: + optional: true + + "@rollup/pluginutils@4.2.1": + resolution: + { + integrity: sha512-iKnFXr7NkdZAIHiIWE+BX5ULi/ucVFYWD6TbAV+rZctiRTY2PL6tsIKhoIOaoskiWAkgu+VsbXgUVDNLHf+InQ==, + } + engines: { node: ">= 8.0.0" } + + "@rollup/pluginutils@5.3.0": + resolution: + { + integrity: sha512-5EdhGZtnu3V88ces7s53hhfK5KSASnJZv8Lulpc04cWO3REESroJXg73DFsOmgbU2BhwV0E20bu2IDZb3VKW4Q==, + } + engines: { node: ">=14.0.0" } + peerDependencies: + rollup: ^1.20.0||^2.0.0||^3.0.0||^4.0.0 + peerDependenciesMeta: + rollup: + optional: true + + "@rtsao/scc@1.1.0": + resolution: + { + integrity: sha512-zt6OdqaDoOnJ1ZYsCYGt9YmWzDXl4vQdKTyJev62gFhRGKdx7mcT54V9KIjg+d2wi9EXsPvAPKe7i7WjfVWB8g==, + } + + "@sentry-internal/browser-utils@8.55.1": + resolution: + { + integrity: sha512-SipXiwVhJrxzy3/4kf+YIFmpYlLKtGSRD+er7SBCcuSBtv31Fee8IXMDvk+bq24gRXxyjOLUmT//GGXjy2LL6w==, + } + engines: { node: ">=14.18" } + + "@sentry-internal/feedback@8.55.1": + resolution: + { + integrity: sha512-9iFHaT/ijtzB0ffZhXMnt2rPNIXO/dDiCL1G1Bc55rQMPXgawR9AIaAWciyqQjYcbL1DDOhWbzdVqB+kVs5gXw==, + } + engines: { node: ">=14.18" } + + "@sentry-internal/replay-canvas@8.55.1": + resolution: + { + integrity: sha512-2sKRu96Qe70y6TiYdYbwkhg4um2prgzH/ZJRItuoSEAjPjoFYYlP+1qjE2CcBw4RPS8/PimV7SFheSaeZs2GCw==, + } + engines: { node: ">=14.18" } + + "@sentry-internal/replay@8.55.1": + resolution: + { + integrity: sha512-XaX6r8pXeX47rfiQrSQUwkgxHsDkOKzIT++zfTwrmveVlYSqAhp3x+AKhxAXGmKG62wlmAKQz54GJKcG4cgyKQ==, + } + engines: { node: ">=14.18" } + + "@sentry/babel-plugin-component-annotate@3.6.1": + resolution: + { + integrity: sha512-zmvUa4RpzDG3LQJFpGCE8lniz8Rk1Wa6ZvvK+yEH+snZeaHHRbSnAQBMR607GOClP+euGHNO2YtaY4UAdNTYbg==, + } + engines: { node: ">= 14" } + + "@sentry/browser@8.55.1": + resolution: + { + integrity: sha512-OEn2eg8h3Mr7BmBGQ28BqbWehYA/NklZ0pAZB1FypPPl+kMd85AbaRdGTnaSjgmpc8bKbBO64edq4Y14sbCs5w==, + } + engines: { node: ">=14.18" } + + "@sentry/bundler-plugin-core@3.6.1": + resolution: + { + integrity: sha512-/ubWjPwgLep84sUPzHfKL2Ns9mK9aQrEX4aBFztru7ygiJidKJTxYGtvjh4dL2M1aZ0WRQYp+7PF6+VKwdZXcQ==, + } + engines: { node: ">= 14" } + + "@sentry/cli-darwin@2.58.5": + resolution: + { + integrity: sha512-lYrNzenZFJftfwSya7gwrHGxtE+Kob/e1sr9lmHMFOd4utDlmq0XFDllmdZAMf21fxcPRI1GL28ejZ3bId01fQ==, + } + engines: { node: ">=10" } + os: [darwin] + + "@sentry/cli-linux-arm64@2.58.5": + resolution: + { + integrity: sha512-/4gywFeBqRB6tR/iGMRAJ3HRqY6Z7Yp4l8ZCbl0TDLAfHNxu7schEw4tSnm2/Hh9eNMiOVy4z58uzAWlZXAYBQ==, + } + engines: { node: ">=10" } + cpu: [arm64] + os: [linux, freebsd, android] + + "@sentry/cli-linux-arm@2.58.5": + resolution: + { + integrity: sha512-KtHweSIomYL4WVDrBrYSYJricKAAzxUgX86kc6OnlikbyOhoK6Fy8Vs6vwd52P6dvWPjgrMpUYjW2M5pYXQDUw==, + } + engines: { node: ">=10" } + cpu: [arm] + os: [linux, freebsd, android] + + "@sentry/cli-linux-i686@2.58.5": + resolution: + { + integrity: sha512-G7261dkmyxqlMdyvyP06b+RTIVzp1gZNgglj5UksxSouSUqRd/46W/2pQeOMPhloDYo9yLtCN2YFb3Mw4aUsWw==, + } + engines: { node: ">=10" } + cpu: [x86, ia32] + os: [linux, freebsd, android] + + "@sentry/cli-linux-x64@2.58.5": + resolution: + { + integrity: sha512-rP04494RSmt86xChkQ+ecBNRYSPbyXc4u0IA7R7N1pSLCyO74e5w5Al+LnAq35cMfVbZgz5Sm0iGLjyiUu4I1g==, + } + engines: { node: ">=10" } + cpu: [x64] + os: [linux, freebsd, android] + + "@sentry/cli-win32-arm64@2.58.5": + resolution: + { + integrity: sha512-AOJ2nCXlQL1KBaCzv38m3i2VmSHNurUpm7xVKd6yAHX+ZoVBI8VT0EgvwmtJR2TY2N2hNCC7UrgRmdUsQ152bA==, + } + engines: { node: ">=10" } + cpu: [arm64] + os: [win32] + + "@sentry/cli-win32-i686@2.58.5": + resolution: + { + integrity: sha512-EsuboLSOnlrN7MMPJ1eFvfMDm+BnzOaSWl8eYhNo8W/BIrmNgpRUdBwnWn9Q2UOjJj5ZopukmsiMYtU/D7ml9g==, + } + engines: { node: ">=10" } + cpu: [x86, ia32] + os: [win32] + + "@sentry/cli-win32-x64@2.58.5": + resolution: + { + integrity: sha512-IZf+XIMiQwj+5NzqbOQfywlOitmCV424Vtf9c+ep61AaVScUFD1TSrQbOcJJv5xGxhlxNOMNgMeZhdexdzrKZg==, + } + engines: { node: ">=10" } + cpu: [x64] + os: [win32] + + "@sentry/cli@2.58.5": + resolution: + { + integrity: sha512-tavJ7yGUZV+z3Ct2/ZB6mg339i08sAk6HDkgqmSRuQEu2iLS5sl9HIvuXfM6xjv8fwlgFOSy++WNABNAcGHUbg==, + } + engines: { node: ">= 10" } + hasBin: true + + "@sentry/core@8.55.1": + resolution: + { + integrity: sha512-0ea+yDOgaijR3ba2al1QZxY0bZ9MBZq2a0G+2A0uCBpBkiXnpLFGVAo9UAlEikN1C4M8ROZYiuFU7yZCqacgLQ==, + } + engines: { node: ">=14.18" } + + "@sentry/react@8.55.1": + resolution: + { + integrity: sha512-vrqEI1EVRMaeUluHSt84//WFuMecqAfwS+t2SojhvXtsSP6BbaCHd0jt7til5MBzI9kWAQjIxsUUr3pbFAviVg==, + } + engines: { node: ">=14.18" } + peerDependencies: + react: ^16.14.0 || 17.x || 18.x || 19.x + + "@sentry/vite-plugin@3.6.1": + resolution: + { + integrity: sha512-x8WMdv2K2HcGS2ezEUIEZXpT/fNeWQ9rsEeF0K9DfKXK8Z9lzRmCr6TVA6I9+yW39Is+1/0cv1Rsu0LhO7lHzg==, + } + engines: { node: ">= 14" } + + "@sindresorhus/base62@1.0.0": + resolution: + { + integrity: sha512-TeheYy0ILzBEI/CO55CP6zJCSdSWeRtGnHy8U8dWSUH4I68iqTsy7HkMktR4xakThc9jotkPQUXT4ITdbV7cHA==, + } + engines: { node: ">=18" } + + "@standard-schema/spec@1.1.0": + resolution: + { + integrity: sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w==, + } + + "@storybook/addon-docs@10.3.5": + resolution: + { + integrity: sha512-WuHbxia/o5TX4Rg/IFD0641K5qId/Nk0dxhmAUNoFs5L0+yfZUwh65XOBbzXqrkYmYmcVID4v7cgDRmzstQNkA==, + } + peerDependencies: + storybook: ^10.3.5 + + "@storybook/builder-vite@10.3.5": + resolution: + { + integrity: sha512-i4KwCOKbhtlbQIbhm53+Kk7bMnxa0cwTn1pxmtA/x5wm1Qu7FrrBQV0V0DNjkUqzcSKo1CjspASJV/HlY0zYlw==, + } + peerDependencies: + storybook: ^10.3.5 + vite: ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0 + + "@storybook/csf-plugin@10.3.5": + resolution: + { + integrity: sha512-qlEzNKxOjq86pvrbuMwiGD/bylnsXk1dg7ve0j77YFjEEchqtl7qTlrXvFdNaLA89GhW6D/EV6eOCu/eobPDgw==, + } + peerDependencies: + esbuild: ^0.27.7 + rollup: "*" + storybook: ^10.3.5 + vite: "*" + webpack: "*" + peerDependenciesMeta: + esbuild: + optional: true + rollup: + optional: true + vite: + optional: true + webpack: + optional: true + + "@storybook/global@5.0.0": + resolution: + { + integrity: sha512-FcOqPAXACP0I3oJ/ws6/rrPT9WGhu915Cg8D02a9YxLo0DE9zI+a9A5gRGvmQ09fiWPukqI8ZAEoQEdWUKMQdQ==, + } + + "@storybook/icons@2.0.1": + resolution: + { + integrity: sha512-/smVjw88yK3CKsiuR71vNgWQ9+NuY2L+e8X7IMrFjexjm6ZR8ULrV2DRkTA61aV6ryefslzHEGDInGpnNeIocg==, + } + peerDependencies: + react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 + react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 + + "@storybook/react-dom-shim@10.3.5": + resolution: + { + integrity: sha512-Gw8R7XZm0zSUH0XAuxlQJhmizsLzyD6x00KOlP6l7oW9eQHXGfxg3seNDG3WrSAcW07iP1/P422kuiriQlOv7g==, + } + peerDependencies: + react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 + react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 + storybook: ^10.3.5 + + "@storybook/react-vite@10.3.5": + resolution: + { + integrity: sha512-UB5sJHeh26bfd8sNMx2YPGYRYmErIdTRaLOT28m4bykQIa1l9IgVktsYg/geW7KsJU0lXd3oTbnUjLD+enpi3w==, + } + peerDependencies: + react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 + react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 + storybook: ^10.3.5 + vite: ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0 + + "@storybook/react@10.3.5": + resolution: + { + integrity: sha512-tpLTLaVGoA6fLK3ReyGzZUricq7lyPaV2hLPpj5wqdXLV/LpRtAHClUpNoPDYSBjlnSjL81hMZijbkGC3mA+gw==, + } + peerDependencies: + react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 + react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 + storybook: ^10.3.5 + typescript: ">= 4.9.x" + peerDependenciesMeta: + typescript: + optional: true + + "@stylistic/eslint-plugin@3.1.0": + resolution: + { + integrity: sha512-pA6VOrOqk0+S8toJYhQGv2MWpQQR0QpeUo9AhNkC49Y26nxBQ/nH1rta9bUU1rPw2fJ1zZEMV5oCX5AazT7J2g==, + } + engines: { node: ^18.18.0 || ^20.9.0 || >=21.1.0 } + peerDependencies: + eslint: ">=8.40.0" + + "@svgr/babel-plugin-add-jsx-attribute@8.0.0": + resolution: + { + integrity: sha512-b9MIk7yhdS1pMCZM8VeNfUlSKVRhsHZNMl5O9SfaX0l0t5wjdgu4IDzGB8bpnGBBOjGST3rRFVsaaEtI4W6f7g==, + } + engines: { node: ">=14" } + peerDependencies: + "@babel/core": ^7.0.0-0 + + "@svgr/babel-plugin-remove-jsx-attribute@8.0.0": + resolution: + { + integrity: sha512-BcCkm/STipKvbCl6b7QFrMh/vx00vIP63k2eM66MfHJzPr6O2U0jYEViXkHJWqXqQYjdeA9cuCl5KWmlwjDvbA==, + } + engines: { node: ">=14" } + peerDependencies: + "@babel/core": ^7.0.0-0 + + "@svgr/babel-plugin-remove-jsx-empty-expression@8.0.0": + resolution: + { + integrity: sha512-5BcGCBfBxB5+XSDSWnhTThfI9jcO5f0Ai2V24gZpG+wXF14BzwxxdDb4g6trdOux0rhibGs385BeFMSmxtS3uA==, + } + engines: { node: ">=14" } + peerDependencies: + "@babel/core": ^7.0.0-0 + + "@svgr/babel-plugin-replace-jsx-attribute-value@8.0.0": + resolution: + { + integrity: sha512-KVQ+PtIjb1BuYT3ht8M5KbzWBhdAjjUPdlMtpuw/VjT8coTrItWX6Qafl9+ji831JaJcu6PJNKCV0bp01lBNzQ==, + } + engines: { node: ">=14" } + peerDependencies: + "@babel/core": ^7.0.0-0 + + "@svgr/babel-plugin-svg-dynamic-title@8.0.0": + resolution: + { + integrity: sha512-omNiKqwjNmOQJ2v6ge4SErBbkooV2aAWwaPFs2vUY7p7GhVkzRkJ00kILXQvRhA6miHnNpXv7MRnnSjdRjK8og==, + } + engines: { node: ">=14" } + peerDependencies: + "@babel/core": ^7.0.0-0 + + "@svgr/babel-plugin-svg-em-dimensions@8.0.0": + resolution: + { + integrity: sha512-mURHYnu6Iw3UBTbhGwE/vsngtCIbHE43xCRK7kCw4t01xyGqb2Pd+WXekRRoFOBIY29ZoOhUCTEweDMdrjfi9g==, + } + engines: { node: ">=14" } + peerDependencies: + "@babel/core": ^7.0.0-0 + + "@svgr/babel-plugin-transform-react-native-svg@8.1.0": + resolution: + { + integrity: sha512-Tx8T58CHo+7nwJ+EhUwx3LfdNSG9R2OKfaIXXs5soiy5HtgoAEkDay9LIimLOcG8dJQH1wPZp/cnAv6S9CrR1Q==, + } + engines: { node: ">=14" } + peerDependencies: + "@babel/core": ^7.0.0-0 + + "@svgr/babel-plugin-transform-svg-component@8.0.0": + resolution: + { + integrity: sha512-DFx8xa3cZXTdb/k3kfPeaixecQLgKh5NVBMwD0AQxOzcZawK4oo1Jh9LbrcACUivsCA7TLG8eeWgrDXjTMhRmw==, + } + engines: { node: ">=12" } + peerDependencies: + "@babel/core": ^7.0.0-0 + + "@svgr/babel-preset@8.1.0": + resolution: + { + integrity: sha512-7EYDbHE7MxHpv4sxvnVPngw5fuR6pw79SkcrILHJ/iMpuKySNCl5W1qcwPEpU+LgyRXOaAFgH0KhwD18wwg6ug==, + } + engines: { node: ">=14" } + peerDependencies: + "@babel/core": ^7.0.0-0 + + "@svgr/core@8.1.0": + resolution: + { + integrity: sha512-8QqtOQT5ACVlmsvKOJNEaWmRPmcojMOzCz4Hs2BGG/toAp/K38LcsMRyLp349glq5AzJbCEeimEoxaX6v/fLrA==, + } + engines: { node: ">=14" } + + "@svgr/hast-util-to-babel-ast@8.0.0": + resolution: + { + integrity: sha512-EbDKwO9GpfWP4jN9sGdYwPBU0kdomaPIL2Eu4YwmgP+sJeXT+L7bMwJUBnhzfH8Q2qMBqZ4fJwpCyYsAN3mt2Q==, + } + engines: { node: ">=14" } + + "@svgr/plugin-jsx@8.1.0": + resolution: + { + integrity: sha512-0xiIyBsLlr8quN+WyuxooNW9RJ0Dpr8uOnH/xrCVO8GLUcwHISwj1AG0k+LFzteTkAA0GbX0kj9q6Dk70PTiPA==, + } + engines: { node: ">=14" } + peerDependencies: + "@svgr/core": "*" + + "@testing-library/dom@10.4.1": + resolution: + { + integrity: sha512-o4PXJQidqJl82ckFaXUeoAW+XysPLauYI43Abki5hABd853iMhitooc6znOnczgbTYmEP6U6/y1ZyKAIsvMKGg==, + } + engines: { node: ">=18" } + + "@testing-library/jest-dom@6.9.1": + resolution: + { + integrity: sha512-zIcONa+hVtVSSep9UT3jZ5rizo2BsxgyDYU7WFD5eICBE7no3881HGeb/QkGfsJs6JTkY1aQhT7rIPC7e+0nnA==, + } + engines: { node: ">=14", npm: ">=6", yarn: ">=1" } + + "@testing-library/react@16.3.2": + resolution: + { + integrity: sha512-XU5/SytQM+ykqMnAnvB2umaJNIOsLF3PVv//1Ew4CTcpz0/BRyy/af40qqrt7SjKpDdT1saBMc42CUok5gaw+g==, + } + engines: { node: ">=18" } + peerDependencies: + "@testing-library/dom": ^10.0.0 + "@types/react": ^18.0.0 || ^19.0.0 + "@types/react-dom": ^18.0.0 || ^19.0.0 + react: ^18.0.0 || ^19.0.0 + react-dom: ^18.0.0 || ^19.0.0 + peerDependenciesMeta: + "@types/react": + optional: true + "@types/react-dom": + optional: true + + "@testing-library/user-event@14.6.1": + resolution: + { + integrity: sha512-vq7fv0rnt+QTXgPxr5Hjc210p6YKq2kmdziLgnsZGgLJ9e6VAShx1pACLuRjd/AS/sr7phAR58OIIpf0LlmQNw==, + } + engines: { node: ">=12", npm: ">=6" } + peerDependencies: + "@testing-library/dom": ">=7.21.4" + + "@tybys/wasm-util@0.10.1": + resolution: + { + integrity: sha512-9tTaPJLSiejZKx+Bmog4uSubteqTvFrVrURwkmHixBo0G4seD0zUxp98E1DzUBJxLQ3NPwXrGKDiVjwx/DpPsg==, + } + + "@types/aria-query@5.0.4": + resolution: + { + integrity: sha512-rfT93uj5s0PRL7EzccGMs3brplhcrghnDoV26NqKhCAS1hVo+WdNsPvE/yb6ilfr5hi2MEk6d5EWJTKdxg8jVw==, + } + + "@types/babel__core@7.20.5": + resolution: + { + integrity: sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==, + } + + "@types/babel__generator@7.27.0": + resolution: + { + integrity: sha512-ufFd2Xi92OAVPYsy+P4n7/U7e68fex0+Ee8gSG9KX7eo084CWiQ4sdxktvdl0bOPupXtVJPY19zk6EwWqUQ8lg==, + } + + "@types/babel__template@7.4.4": + resolution: + { + integrity: sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==, + } + + "@types/babel__traverse@7.28.0": + resolution: + { + integrity: sha512-8PvcXf70gTDZBgt9ptxJ8elBeBjcLOAcOtoO/mPJjtji1+CdGbHgm77om1GrsPxsiE+uXIpNSK64UYaIwQXd4Q==, + } + + "@types/chai@5.2.3": + resolution: + { + integrity: sha512-Mw558oeA9fFbv65/y4mHtXDs9bPnFMZAL/jxdPFUpOHHIXX91mcgEHbS5Lahr+pwZFR8A7GQleRWeI6cGFC2UA==, + } + + "@types/content-type@1.1.9": + resolution: + { + integrity: sha512-Hq9IMnfekuOCsEmYl4QX2HBrT+XsfXiupfrLLY8Dcf3Puf4BkBOxSbWYTITSOQAhJoYPBez+b4MJRpIYL65z8A==, + } + + "@types/deep-eql@4.0.2": + resolution: + { + integrity: sha512-c9h9dVVMigMPc4bwTvC5dxqtqJZwQPePsWjPlpSOnojbor6pGqdk541lfA7AqFQr5pB1BRdq0juY9db81BwyFw==, + } + + "@types/doctrine@0.0.9": + resolution: + { + integrity: sha512-eOIHzCUSH7SMfonMG1LsC2f8vxBFtho6NGBznK41R84YzPuvSBzrhEps33IsQiOW9+VL6NQ9DbjQJznk/S4uRA==, + } + + "@types/dom-mediacapture-record@1.0.22": + resolution: + { + integrity: sha512-mUMZLK3NvwRLcAAT9qmcK+9p7tpU2FHdDsntR3YI4+GY88XrgG4XiE7u1Q2LAN2/FZOz/tdMDC3GQCR4T8nFuw==, + } + + "@types/dom-mediacapture-transform@0.1.11": + resolution: + { + integrity: sha512-Y2p+nGf1bF2XMttBnsVPHUWzRRZzqUoJAKmiP10b5umnO6DDrWI0BrGDJy1pOHoOULVmGSfFNkQrAlC5dcj6nQ==, + } + + "@types/dom-webcodecs@0.1.18": + resolution: + { + integrity: sha512-vAvE8C9DGWR+tkb19xyjk1TSUlJ7RUzzp4a9Anu7mwBT+fpyePWK1UxmH14tMO5zHmrnrRIMg5NutnnDztLxgg==, + } + + "@types/estree@1.0.8": + resolution: + { + integrity: sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==, + } + + "@types/events@3.0.3": + resolution: + { + integrity: sha512-trOc4AAUThEz9hapPtSd7wf5tiQKvTtu5b371UxXdTuqzIh0ArcRspRP0i0Viu+LXstIQ1z96t1nsPxT9ol01g==, + } + + "@types/glob-to-regexp@0.4.4": + resolution: + { + integrity: sha512-nDKoaKJYbnn1MZxUY0cA1bPmmgZbg0cTq7Rh13d0KWYNOiKbqoR+2d89SnRPszGh7ROzSwZ/GOjZ4jPbmmZ6Eg==, + } + + "@types/grecaptcha@3.0.9": + resolution: + { + integrity: sha512-fFxMtjAvXXMYTzDFK5NpcVB7WHnrHVLl00QzEGpuFxSAC789io6M+vjcn+g5FTEamIJtJr/IHkCDsqvJxeWDyw==, + } + + "@types/jsdom@21.1.7": + resolution: + { + integrity: sha512-yOriVnggzrnQ3a9OKOCxaVuSug3w3/SbOj5i7VwXWZEyUNl3bLF9V3MfxGbZKuwqJOQyRfqXyROBB1CoZLFWzA==, + } + + "@types/json-schema@7.0.15": + resolution: + { + integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==, + } + + "@types/json5@0.0.29": + resolution: + { + integrity: sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==, + } + + "@types/lodash-es@4.17.12": + resolution: + { + integrity: sha512-0NgftHUcV4v34VhXm8QBSftKVXtbkBG3ViCjs6+eJ5a6y6Mi/jiFGPc1sC7QK+9BFhWrURE3EOggmWaSxL9OzQ==, + } + + "@types/lodash@4.17.24": + resolution: + { + integrity: sha512-gIW7lQLZbue7lRSWEFql49QJJWThrTFFeIMJdp3eH4tKoxm1OvEPg02rm4wCCSHS0cL3/Fizimb35b7k8atwsQ==, + } + + "@types/mdx@2.0.13": + resolution: + { + integrity: sha512-+OWZQfAYyio6YkJb3HLxDrvnx6SWWDbC0zVPfBRzUk0/nqoDyf6dNxQi3eArPe8rJ473nobTMQ/8Zk+LxJ+Yuw==, + } + + "@types/minimatch@3.0.5": + resolution: + { + integrity: sha512-Klz949h02Gz2uZCMGwDUSDS1YBlTdDDgbWHi+81l29tQALUtvz4rAYi5uoVhE5Lagoq6DeqAUlbrHvW/mXDgdQ==, + } + + "@types/node@24.12.2": + resolution: + { + integrity: sha512-A1sre26ke7HDIuY/M23nd9gfB+nrmhtYyMINbjI1zHJxYteKR6qSMX56FsmjMcDb3SMcjJg5BiRRgOCC/yBD0g==, + } + + "@types/normalize-package-data@2.4.4": + resolution: + { + integrity: sha512-37i+OaWTh9qeK4LSHPsyRC7NahnGotNuZvjLSgcPzblpHB3rrCJxAOgI5gCdKm7coonsaX1Of0ILiTcnZjbfxA==, + } + + "@types/pako@2.0.4": + resolution: + { + integrity: sha512-VWDCbrLeVXJM9fihYodcLiIv0ku+AlOa/TQ1SvYOaBuyrSKgEcro95LJyIsJ4vSo6BXIxOKxiJAat04CmST9Fw==, + } + + "@types/qrcode@1.5.6": + resolution: + { + integrity: sha512-te7NQcV2BOvdj2b1hCAHzAoMNuj65kNBMz0KBaxM6c3VGBOhU0dURQKOtH8CFNI/dsKkwlv32p26qYQTWoB5bw==, + } + + "@types/react-dom@19.2.3": + resolution: + { + integrity: sha512-jp2L/eY6fn+KgVVQAOqYItbF0VY/YApe5Mz2F0aykSO8gx31bYCZyvSeYxCHKvzHG5eZjc+zyaS5BrBWya2+kQ==, + } + peerDependencies: + "@types/react": ^19.2.0 + + "@types/react@19.2.14": + resolution: + { + integrity: sha512-ilcTH/UniCkMdtexkoCN0bI7pMcJDvmQFPvuPvmEaYA/NSfFTAgdUSLAoVjaRJm7+6PvcM+q1zYOwS4wTYMF9w==, + } + + "@types/resolve@1.20.6": + resolution: + { + integrity: sha512-A4STmOXPhMUtHH+S6ymgE2GiBSMqf4oTvcQZMcHzokuTLVYzXTB8ttjcgxOVaAp2lGwEdzZ0J+cRbbeevQj1UQ==, + } + + "@types/sdp-transform@2.15.0": + resolution: + { + integrity: sha512-ikIFF0EaYt/2XetIYYVeMj6SB52oVXFasJUXDzWHgzNJS5ep2Pbsu7f8f3Za+dEie8HQtt3Zr9mHYBpWT0XgxQ==, + } + + "@types/semver@7.7.1": + resolution: + { + integrity: sha512-FmgJfu+MOcQ370SD0ev7EI8TlCAfKYU+B4m5T3yXc1CiRN94g/SZPtsCkk506aUDtlMnFZvasDwHHUcZUEaYuA==, + } + + "@types/symlink-or-copy@1.2.2": + resolution: + { + integrity: sha512-MQ1AnmTLOncwEf9IVU+B2e4Hchrku5N67NkgcAHW0p3sdzPe0FNMANxEm6OJUzPniEQGkeT3OROLlCwZJLWFZA==, + } + + "@types/tough-cookie@4.0.5": + resolution: + { + integrity: sha512-/Ad8+nIOV7Rl++6f1BdKxFSMgmoqEoYbHRpPcx3JEfv8VRsQe9Z4mCXeJBzxs7mbHY/XOZZuXlRNfhpVPbs6ZA==, + } + + "@types/uuid@10.0.0": + resolution: + { + integrity: sha512-7gqG38EyHgyP1S+7+xomFtL+ZNHcKv6DwNaCZmJmo1vgMugyF3TCnXVg4t1uk89mLNwnLtnY3TpOpCOyp1/xHQ==, + } + + "@types/yargs-parser@21.0.3": + resolution: + { + integrity: sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ==, + } + + "@types/yargs@17.0.35": + resolution: + { + integrity: sha512-qUHkeCyQFxMXg79wQfTtfndEC+N9ZZg76HJftDJp+qH2tV7Gj4OJi7l+PiWwJ+pWtW8GwSmqsDj/oymhrTWXjg==, + } + + "@typescript-eslint/eslint-plugin@8.58.2": + resolution: + { + integrity: sha512-aC2qc5thQahutKjP+cl8cgN9DWe3ZUqVko30CMSZHnFEHyhOYoZSzkGtAI2mcwZ38xeImDucI4dnqsHiOYuuCw==, + } + engines: { node: ^18.18.0 || ^20.9.0 || >=21.1.0 } + peerDependencies: + "@typescript-eslint/parser": ^8.58.2 + eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 + typescript: ">=4.8.4 <6.1.0" + + "@typescript-eslint/experimental-utils@5.62.0": + resolution: + { + integrity: sha512-RTXpeB3eMkpoclG3ZHft6vG/Z30azNHuqY6wKPBHlVMZFuEvrtlEDe8gMqDb+SO+9hjC/pLekeSCryf9vMZlCw==, + } + engines: { node: ^12.22.0 || ^14.17.0 || >=16.0.0 } + peerDependencies: + eslint: ^6.0.0 || ^7.0.0 || ^8.0.0 + + "@typescript-eslint/parser@8.58.2": + resolution: + { + integrity: sha512-/Zb/xaIDfxeJnvishjGdcR4jmr7S+bda8PKNhRGdljDM+elXhlvN0FyPSsMnLmJUrVG9aPO6dof80wjMawsASg==, + } + engines: { node: ^18.18.0 || ^20.9.0 || >=21.1.0 } + peerDependencies: + eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 + typescript: ">=4.8.4 <6.1.0" + + "@typescript-eslint/project-service@8.58.2": + resolution: + { + integrity: sha512-Cq6UfpZZk15+r87BkIh5rDpi38W4b+Sjnb8wQCPPDDweS/LRCFjCyViEbzHk5Ck3f2QDfgmlxqSa7S7clDtlfg==, + } + engines: { node: ^18.18.0 || ^20.9.0 || >=21.1.0 } + peerDependencies: + typescript: ">=4.8.4 <6.1.0" + + "@typescript-eslint/scope-manager@5.62.0": + resolution: + { + integrity: sha512-VXuvVvZeQCQb5Zgf4HAxc04q5j+WrNAtNh9OwCsCgpKqESMTu3tF/jhZ3xG6T4NZwWl65Bg8KuS2uEvhSfLl0w==, + } + engines: { node: ^12.22.0 || ^14.17.0 || >=16.0.0 } + + "@typescript-eslint/scope-manager@8.58.2": + resolution: + { + integrity: sha512-SgmyvDPexWETQek+qzZnrG6844IaO02UVyOLhI4wpo82dpZJY9+6YZCKAMFzXb7qhx37mFK1QcPQ18tud+vo6Q==, + } + engines: { node: ^18.18.0 || ^20.9.0 || >=21.1.0 } + + "@typescript-eslint/tsconfig-utils@8.58.2": + resolution: + { + integrity: sha512-3SR+RukipDvkkKp/d0jP0dyzuls3DbGmwDpVEc5wqk5f38KFThakqAAO0XMirWAE+kT00oTauTbzMFGPoAzB0A==, + } + engines: { node: ^18.18.0 || ^20.9.0 || >=21.1.0 } + peerDependencies: + typescript: ">=4.8.4 <6.1.0" + + "@typescript-eslint/type-utils@8.58.2": + resolution: + { + integrity: sha512-Z7EloNR/B389FvabdGeTo2XMs4W9TjtPiO9DAsmT0yom0bwlPyRjkJ1uCdW1DvrrrYP50AJZ9Xc3sByZA9+dcg==, + } + engines: { node: ^18.18.0 || ^20.9.0 || >=21.1.0 } + peerDependencies: + eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 + typescript: ">=4.8.4 <6.1.0" + + "@typescript-eslint/types@5.62.0": + resolution: + { + integrity: sha512-87NVngcbVXUahrRTqIK27gD2t5Cu1yuCXxbLcFtCzZGlfyVWWh8mLHkoxzjsB6DDNnvdL+fW8MiwPEJyGJQDgQ==, + } + engines: { node: ^12.22.0 || ^14.17.0 || >=16.0.0 } + + "@typescript-eslint/types@8.58.2": + resolution: + { + integrity: sha512-9TukXyATBQf/Jq9AMQXfvurk+G5R2MwfqQGDR2GzGz28HvY/lXNKGhkY+6IOubwcquikWk5cjlgPvD2uAA7htQ==, + } + engines: { node: ^18.18.0 || ^20.9.0 || >=21.1.0 } + + "@typescript-eslint/typescript-estree@5.62.0": + resolution: + { + integrity: sha512-CmcQ6uY7b9y694lKdRB8FEel7JbU/40iSAPomu++SjLMntB+2Leay2LO6i8VnJk58MtE9/nQSFIH6jpyRWyYzA==, + } + engines: { node: ^12.22.0 || ^14.17.0 || >=16.0.0 } + peerDependencies: + typescript: "*" + peerDependenciesMeta: + typescript: + optional: true + + "@typescript-eslint/typescript-estree@8.58.2": + resolution: + { + integrity: sha512-ELGuoofuhhoCvNbQjFFiobFcGgcDCEm0ThWdmO4Z0UzLqPXS3KFvnEZ+SHewwOYHjM09tkzOWXNTv9u6Gqtyuw==, + } + engines: { node: ^18.18.0 || ^20.9.0 || >=21.1.0 } + peerDependencies: + typescript: ">=4.8.4 <6.1.0" + + "@typescript-eslint/utils@5.62.0": + resolution: + { + integrity: sha512-n8oxjeb5aIbPFEtmQxQYOLI0i9n5ySBEY/ZEHHZqKQSFnxio1rv6dthascc9dLuwrL0RC5mPCxB7vnAVGAYWAQ==, + } + engines: { node: ^12.22.0 || ^14.17.0 || >=16.0.0 } + peerDependencies: + eslint: ^6.0.0 || ^7.0.0 || ^8.0.0 + + "@typescript-eslint/utils@8.58.2": + resolution: + { + integrity: sha512-QZfjHNEzPY8+l0+fIXMvuQ2sJlplB4zgDZvA+NmvZsZv3EQwOcc1DuIU1VJUTWZ/RKouBMhDyNaBMx4sWvrzRA==, + } + engines: { node: ^18.18.0 || ^20.9.0 || >=21.1.0 } + peerDependencies: + eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 + typescript: ">=4.8.4 <6.1.0" + + "@typescript-eslint/visitor-keys@5.62.0": + resolution: + { + integrity: sha512-07ny+LHRzQXepkGg6w0mFY41fVUNBrL2Roj/++7V1txKugfjm/Ci/qSND03r2RhlJhJYMcTn9AhhSSqQp0Ysyw==, + } + engines: { node: ^12.22.0 || ^14.17.0 || >=16.0.0 } + + "@typescript-eslint/visitor-keys@8.58.2": + resolution: + { + integrity: sha512-f1WO2Lx8a9t8DARmcWAUPJbu0G20bJlj8L4z72K00TMeJAoyLr/tHhI/pzYBLrR4dXWkcxO1cWYZEOX8DKHTqA==, + } + engines: { node: ^18.18.0 || ^20.9.0 || >=21.1.0 } + + "@ungap/structured-clone@1.3.0": + resolution: + { + integrity: sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g==, + } + + "@use-gesture/core@10.3.1": + resolution: + { + integrity: sha512-WcINiDt8WjqBdUXye25anHiNxPc0VOrlT8F6LLkU6cycrOGUDyY/yyFmsg3k8i5OLvv25llc0QC45GhR/C8llw==, + } + + "@use-gesture/react@10.3.1": + resolution: + { + integrity: sha512-Yy19y6O2GJq8f7CHf7L0nxL8bf4PZCPaVOCgJrusOeFHY1LvHgYXnmnXg6N5iwAnbgbZCDjo60SiM6IPJi9C5g==, + } + peerDependencies: + react: ">= 16.8.0" + + "@vector-im/compound-design-tokens@10.1.0": + resolution: + { + integrity: sha512-o+7DGx+NygpT2NPE1Jo//7NZDuyjzRH06eRchS0ZlkJicKx/impEmShmHU/XiE4P84BIFOo9eZ1Ws+rAym6Tuw==, + } + peerDependencies: + "@types/react": "*" + react: ^17 || ^18 || ^19.0.0 + peerDependenciesMeta: + "@types/react": + optional: true + react: + optional: true + + "@vector-im/compound-web@9.2.0": + resolution: + { + integrity: sha512-jHbABGEQ2yqNtm5xRIkklQs198VEfSk9AJQolI+e4WSJ0xg8Ozyv9t9KIuKQAmjdSV9aow5G6hDE861XB6DQgw==, + } + peerDependencies: + "@fontsource/inconsolata": ^5 + "@fontsource/inter": ^5 + "@types/react": "*" + "@vector-im/compound-design-tokens": ">=1.6.1 <11.0.0" + react: ^18 || ^19.0.0 + peerDependenciesMeta: + "@types/react": + optional: true + + "@vitejs/plugin-react@4.7.0": + resolution: + { + integrity: sha512-gUu9hwfWvvEDBBmgtAowQCojwZmJ5mcLn3aufeCsitijs3+f2NsrPtlAWIR6OPiqljl96GVCUbLe0HyqIpVaoA==, + } + engines: { node: ^14.18.0 || >=16.0.0 } + peerDependencies: + vite: ^4.2.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 + + "@vitest/coverage-v8@4.1.4": + resolution: + { + integrity: sha512-x7FptB5oDruxNPDNY2+S8tCh0pcq7ymCe1gTHcsp733jYjrJl8V1gMUlVysuCD9Kz46Xz9t1akkv08dPcYDs1w==, + } + peerDependencies: + "@vitest/browser": 4.1.4 + vitest: 4.1.4 + peerDependenciesMeta: + "@vitest/browser": + optional: true + + "@vitest/expect@3.2.4": + resolution: + { + integrity: sha512-Io0yyORnB6sikFlt8QW5K7slY4OjqNX9jmJQ02QDda8lyM6B5oNgVWoSoKPac8/kgnCUzuHQKrSLtu/uOqqrig==, + } + + "@vitest/expect@4.1.4": + resolution: + { + integrity: sha512-iPBpra+VDuXmBFI3FMKHSFXp3Gx5HfmSCE8X67Dn+bwephCnQCaB7qWK2ldHa+8ncN8hJU8VTMcxjPpyMkUjww==, + } + + "@vitest/mocker@4.1.4": + resolution: + { + integrity: sha512-R9HTZBhW6yCSGbGQnDnH3QHfJxokKN4KB+Yvk9Q1le7eQNYwiCyKxmLmurSpFy6BzJanSLuEUDrD+j97Q+ZLPg==, + } + peerDependencies: + msw: ^2.4.9 + vite: ^6.0.0 || ^7.0.0 || ^8.0.0 + peerDependenciesMeta: + msw: + optional: true + vite: + optional: true + + "@vitest/pretty-format@3.2.4": + resolution: + { + integrity: sha512-IVNZik8IVRJRTr9fxlitMKeJeXFFFN0JaB9PHPGQ8NKQbGpfjlTx9zO4RefN8gp7eqjNy8nyK3NZmBzOPeIxtA==, + } + + "@vitest/pretty-format@4.1.4": + resolution: + { + integrity: sha512-ddmDHU0gjEUyEVLxtZa7xamrpIefdEETu3nZjWtHeZX4QxqJ7tRxSteHVXJOcr8jhiLoGAhkK4WJ3WqBpjx42A==, + } + + "@vitest/runner@4.1.4": + resolution: + { + integrity: sha512-xTp7VZ5aXP5ZJrn15UtJUWlx6qXLnGtF6jNxHepdPHpMfz/aVPx+htHtgcAL2mDXJgKhpoo2e9/hVJsIeFbytQ==, + } + + "@vitest/snapshot@4.1.4": + resolution: + { + integrity: sha512-MCjCFgaS8aZz+m5nTcEcgk/xhWv0rEH4Yl53PPlMXOZ1/Ka2VcZU6CJ+MgYCZbcJvzGhQRjVrGQNZqkGPttIKw==, + } + + "@vitest/spy@3.2.4": + resolution: + { + integrity: sha512-vAfasCOe6AIK70iP5UD11Ac4siNUNJ9i/9PZ3NKx07sG6sUxeag1LWdNrMWeKKYBLlzuK+Gn65Yd5nyL6ds+nw==, + } + + "@vitest/spy@4.1.4": + resolution: + { + integrity: sha512-XxNdAsKW7C+FLydqFJLb5KhJtl3PGCMmYwFRfhvIgxJvLSXhhVI1zM8f1qD3Zg7RCjTSzDVyct6sghs9UEgBEQ==, + } + + "@vitest/utils@3.2.4": + resolution: + { + integrity: sha512-fB2V0JFrQSMsCo9HiSq3Ezpdv4iYaXRG1Sx8edX3MwxfyNn83mKiGzOcH+Fkxt4MHxr3y42fQi1oeAInqgX2QA==, + } + + "@vitest/utils@4.1.4": + resolution: + { + integrity: sha512-13QMT+eysM5uVGa1rG4kegGYNp6cnQcsTc67ELFbhNLQO+vgsygtYJx2khvdt4gVQqSSpC/KT5FZZxUpP3Oatw==, + } + + "@webcontainer/env@1.1.1": + resolution: + { + integrity: sha512-6aN99yL695Hi9SuIk1oC88l9o0gmxL1nGWWQ/kNy81HigJ0FoaoTXpytCj6ItzgyCEwA9kF1wixsTuv5cjsgng==, + } + + acorn-jsx@5.3.2: + resolution: + { + integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==, + } + peerDependencies: + acorn: ^6.0.0 || ^7.0.0 || ^8.0.0 + + acorn@8.16.0: + resolution: + { + integrity: sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw==, + } + engines: { node: ">=0.4.0" } + hasBin: true + + agent-base@6.0.2: + resolution: + { + integrity: sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==, + } + engines: { node: ">= 6.0.0" } + + agent-base@7.1.4: + resolution: + { + integrity: sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ==, + } + engines: { node: ">= 14" } + + ajv@6.14.0: + resolution: + { + integrity: sha512-IWrosm/yrn43eiKqkfkHis7QioDleaXQHdDVPKg0FSwwd/DuvyX79TZnFOnYpB7dcsFAMmtFztZuXPDvSePkFw==, + } + + another-json@0.2.0: + resolution: + { + integrity: sha512-/Ndrl68UQLhnCdsAzEXLMFuOR546o2qbYRqCglaNHbjXrwG1ayTcdwr3zkSGOGtGXDyR5X9nCFfnyG2AFJIsqg==, + } + + ansi-regex@5.0.1: + resolution: + { + integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==, + } + engines: { node: ">=8" } + + ansi-regex@6.2.2: + resolution: + { + integrity: sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==, + } + engines: { node: ">=12" } + + ansi-styles@4.3.0: + resolution: + { + integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==, + } + engines: { node: ">=8" } + + ansi-styles@5.2.0: + resolution: + { + integrity: sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==, + } + engines: { node: ">=10" } + + ansi-styles@6.2.3: + resolution: + { + integrity: sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==, + } + engines: { node: ">=12" } + + anymatch@3.1.3: + resolution: + { + integrity: sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==, + } + engines: { node: ">= 8" } + + are-docs-informative@0.0.2: + resolution: + { + integrity: sha512-ixiS0nLNNG5jNQzgZJNoUpBKdo9yTYZMGJ+QgT2jmjR7G7+QHRCc4v6LQ3NgE7EBJq+o0ams3waJwkrlBom8Ig==, + } + engines: { node: ">=14" } + + argparse@2.0.1: + resolution: + { + integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==, + } + + aria-hidden@1.2.6: + resolution: + { + integrity: sha512-ik3ZgC9dY/lYVVM++OISsaYDeg1tb0VtP5uL3ouh1koGOaUMDPpbFIei4JkFimWUFPn90sbMNMXQAIVOlnYKJA==, + } + engines: { node: ">=10" } + + aria-query@5.3.0: + resolution: + { + integrity: sha512-b0P0sZPKtyu8HkeRAfCq0IfURZK+SuwMjY1UXGBU27wpAiTwQAIlq56IbIO+ytk/JjS1fMR14ee5WBBfKi5J6A==, + } + + aria-query@5.3.2: + resolution: + { + integrity: sha512-COROpnaoap1E2F000S62r6A60uHZnmlvomhfyT2DlTcrY1OrBKn2UhH7qn5wTC9zMvD0AY7csdPSNwKP+7WiQw==, + } + engines: { node: ">= 0.4" } + + array-buffer-byte-length@1.0.2: + resolution: + { + integrity: sha512-LHE+8BuR7RYGDKvnrmcuSq3tDcKv9OFEXQt/HpbZhY7V6h0zlUXutnAD82GiFx9rdieCMjkvtcsPqBwgUl1Iiw==, + } + engines: { node: ">= 0.4" } + + array-includes@3.1.9: + resolution: + { + integrity: sha512-FmeCCAenzH0KH381SPT5FZmiA/TmpndpcaShhfgEN9eCVjnFBqq3l1xrI42y8+PPLI6hypzou4GXw00WHmPBLQ==, + } + engines: { node: ">= 0.4" } + + array-union@2.1.0: + resolution: + { + integrity: sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==, + } + engines: { node: ">=8" } + + array.prototype.findlast@1.2.5: + resolution: + { + integrity: sha512-CVvd6FHg1Z3POpBLxO6E6zr+rSKEQ9L6rZHAaY7lLfhKsWYUBBOuMs0e9o24oopj6H+geRCX0YJ+TJLBK2eHyQ==, + } + engines: { node: ">= 0.4" } + + array.prototype.findlastindex@1.2.6: + resolution: + { + integrity: sha512-F/TKATkzseUExPlfvmwQKGITM3DGTK+vkAsCZoDc5daVygbJBnjEUCbgkAvVFsgfXfX4YIqZ/27G3k3tdXrTxQ==, + } + engines: { node: ">= 0.4" } + + array.prototype.flat@1.3.3: + resolution: + { + integrity: sha512-rwG/ja1neyLqCuGZ5YYrznA62D4mZXg0i1cIskIUKSiqF3Cje9/wXAls9B9s1Wa2fomMsIv8czB8jZcPmxCXFg==, + } + engines: { node: ">= 0.4" } + + array.prototype.flatmap@1.3.3: + resolution: + { + integrity: sha512-Y7Wt51eKJSyi80hFrJCePGGNo5ktJCslFuboqJsbf57CCPcm5zztluPlc4/aD8sWsKvlwatezpV4U1efk8kpjg==, + } + engines: { node: ">= 0.4" } + + array.prototype.tosorted@1.1.4: + resolution: + { + integrity: sha512-p6Fx8B7b7ZhL/gmUsAy0D15WhvDccw3mnGNbZpi3pmeJdxtWsj2jEaI4Y6oo3XiHfzuSgPwKc04MYt6KgvC/wA==, + } + engines: { node: ">= 0.4" } + + arraybuffer.prototype.slice@1.0.4: + resolution: + { + integrity: sha512-BNoCY6SXXPQ7gF2opIP4GBE+Xw7U+pHMYKuzjgCN3GwiaIR09UUeKfheyIry77QtrCBlC0KK0q5/TER/tYh3PQ==, + } + engines: { node: ">= 0.4" } + + asn1.js@4.10.1: + resolution: + { + integrity: sha512-p32cOF5q0Zqs9uBiONKYLm6BClCoBCM5O9JfeUSlnQLBTxYdTK+pW+nXflm8UkKd2UYlEbYz5qEi0JuZR9ckSw==, + } + + assert@2.1.0: + resolution: + { + integrity: sha512-eLHpSK/Y4nhMJ07gDaAzoX/XAKS8PSaojml3M0DM4JpV1LAi5JOJ/p6H/XWrl8L+DzVEvVCW1z3vWAaB9oTsQw==, + } + + assertion-error@2.0.1: + resolution: + { + integrity: sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==, + } + engines: { node: ">=12" } + + ast-types-flow@0.0.8: + resolution: + { + integrity: sha512-OH/2E5Fg20h2aPrbe+QL8JZQFko0YZaF+j4mnQ7BGhfavO7OpSLa8a0y9sBwomHdSbkhTS8TQNayBfnW5DwbvQ==, + } + + ast-types@0.16.1: + resolution: + { + integrity: sha512-6t10qk83GOG8p0vKmaCr8eiilZwO171AvbROMtvvNiwrTly62t+7XkA8RdIIVbpMhCASAsxgAzdRSwh6nw/5Dg==, + } + engines: { node: ">=4" } + + ast-v8-to-istanbul@1.0.0: + resolution: + { + integrity: sha512-1fSfIwuDICFA4LKkCzRPO7F0hzFf0B7+Xqrl27ynQaa+Rh0e1Es0v6kWHPott3lU10AyAr7oKHa65OppjLn3Rg==, + } + + async-function@1.0.0: + resolution: + { + integrity: sha512-hsU18Ae8CDTR6Kgu9DYf0EbCr/a5iGL0rytQDobUcdpYOKokk8LEjVphnXkDkgpi0wYVsqrXuP0bZxJaTqdgoA==, + } + engines: { node: ">= 0.4" } + + async@3.2.6: + resolution: + { + integrity: sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA==, + } + + autoprefixer@10.5.0: + resolution: + { + integrity: sha512-FMhOoZV4+qR6aTUALKX2rEqGG+oyATvwBt9IIzVR5rMa2HRWPkxf+P+PAJLD1I/H5/II+HuZcBJYEFBpq39ong==, + } + engines: { node: ^10 || ^12 || >=14 } + hasBin: true + peerDependencies: + postcss: ^8.1.0 + + available-typed-arrays@1.0.7: + resolution: + { + integrity: sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==, + } + engines: { node: ">= 0.4" } + + axe-core@4.11.3: + resolution: + { + integrity: sha512-zBQouZixDTbo3jMGqHKyePxYxr1e5W8UdTmBQ7sNtaA9M2bE32daxxPLS/jojhKOHxQ7LWwPjfiwf/fhaJWzlg==, + } + engines: { node: ">=4" } + + axobject-query@4.1.0: + resolution: + { + integrity: sha512-qIj0G9wZbMGNLjLmg1PT6v2mE9AH2zlnADJD/2tC6E00hgmhUOfEB6greHPAfLRSufHqROIUTkw6E+M3lH0PTQ==, + } + engines: { node: ">= 0.4" } + + b4a@1.8.0: + resolution: + { + integrity: sha512-qRuSmNSkGQaHwNbM7J78Wwy+ghLEYF1zNrSeMxj4Kgw6y33O3mXcQ6Ie9fRvfU/YnxWkOchPXbaLb73TkIsfdg==, + } + peerDependencies: + react-native-b4a: "*" + peerDependenciesMeta: + react-native-b4a: + optional: true + + babel-plugin-polyfill-corejs2@0.4.17: + resolution: + { + integrity: sha512-aTyf30K/rqAsNwN76zYrdtx8obu0E4KoUME29B1xj+B3WxgvWkp943vYQ+z8Mv3lw9xHXMHpvSPOBxzAkIa94w==, + } + peerDependencies: + "@babel/core": ^7.4.0 || ^8.0.0-0 <8.0.0 + + babel-plugin-polyfill-corejs3@0.14.2: + resolution: + { + integrity: sha512-coWpDLJ410R781Npmn/SIBZEsAetR4xVi0SxLMXPaMO4lSf1MwnkGYMtkFxew0Dn8B3/CpbpYxN0JCgg8mn67g==, + } + peerDependencies: + "@babel/core": ^7.4.0 || ^8.0.0-0 <8.0.0 + + babel-plugin-polyfill-regenerator@0.6.8: + resolution: + { + integrity: sha512-M762rNHfSF1EV3SLtnCJXFoQbbIIz0OyRwnCmV0KPC7qosSfCO0QLTSuJX3ayAebubhE6oYBAYPrBA5ljowaZg==, + } + peerDependencies: + "@babel/core": ^7.4.0 || ^8.0.0-0 <8.0.0 + + babel-plugin-transform-vite-meta-env@1.0.3: + resolution: + { + integrity: sha512-eyfuDEXrMu667TQpmctHeTlJrZA6jXYHyEJFjcM0yEa60LS/LXlOg2PBbMb8DVS+V9CnTj/j9itdlDVMcY2zEg==, + } + + balanced-match@4.0.4: + resolution: + { + integrity: sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==, + } + engines: { node: 18 || 20 || >=22 } + + bare-events@2.8.2: + resolution: + { + integrity: sha512-riJjyv1/mHLIPX4RwiK+oW9/4c3TEUeORHKefKAKnZ5kyslbN+HXowtbaVEqt4IMUB7OXlfixcs6gsFeo/jhiQ==, + } + peerDependencies: + bare-abort-controller: "*" + peerDependenciesMeta: + bare-abort-controller: + optional: true + + base-x@5.0.1: + resolution: + { + integrity: sha512-M7uio8Zt++eg3jPj+rHMfCC+IuygQHHCOU+IYsVtik6FWjuYpVt/+MRKcgsAMHh8mMFAwnB+Bs+mTrFiXjMzKg==, + } + + base64-js@1.5.1: + resolution: + { + integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==, + } + + baseline-browser-mapping@2.10.19: + resolution: + { + integrity: sha512-qCkNLi2sfBOn8XhZQ0FXsT1Ki/Yo5P90hrkRamVFRS7/KV9hpfA4HkoWNU152+8w0zPjnxo5psx5NL3PSGgv5g==, + } + engines: { node: ">=6.0.0" } + hasBin: true + + before-after-hook@2.2.3: + resolution: + { + integrity: sha512-NzUnlZexiaH/46WDhANlyR2bXRopNg4F/zuSA3OpZnllCUgRaOF2znDioDWrmbNVsuZk6l9pMquQB38cfBZwkQ==, + } + + bent@7.3.12: + resolution: + { + integrity: sha512-T3yrKnVGB63zRuoco/7Ybl7BwwGZR0lceoVG5XmQyMIH9s19SV5m+a8qam4if0zQuAmOQTyPTPmsQBdAorGK3w==, + } + + binary-extensions@2.3.0: + resolution: + { + integrity: sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==, + } + engines: { node: ">=8" } + + bl@5.1.0: + resolution: + { + integrity: sha512-tv1ZJHLfTDnXE6tMHv73YgSJaWR2AFuPwMntBe7XL/GBFHnT0CLnsHMogfk5+GzCDC5ZWarSCYaIGATZt9dNsQ==, + } + + bn.js@4.12.3: + resolution: + { + integrity: sha512-fGTi3gxV/23FTYdAoUtLYp6qySe2KE3teyZitipKNRuVYcBkoP/bB3guXN/XVKUe9mxCHXnc9C4ocyz8OmgN0g==, + } + + bn.js@5.2.3: + resolution: + { + integrity: sha512-EAcmnPkxpntVL+DS7bO1zhcZNvCkxqtkd0ZY53h06GNQ3DEkkGZ/gKgmDv6DdZQGj9BgfSPKtJJ7Dp1GPP8f7w==, + } + + boolbase@1.0.0: + resolution: + { + integrity: sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==, + } + + brace-expansion@5.0.5: + resolution: + { + integrity: sha512-VZznLgtwhn+Mact9tfiwx64fA9erHH/MCXEUfB/0bX/6Fz6ny5EGTXYltMocqg4xFAQZtnO3DHWWXi8RiuN7cQ==, + } + engines: { node: 18 || 20 || >=22 } + + braces@3.0.3: + resolution: + { + integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==, + } + engines: { node: ">=8" } + + broccoli-node-api@1.7.0: + resolution: + { + integrity: sha512-QIqLSVJWJUVOhclmkmypJJH9u9s/aWH4+FH6Q6Ju5l+Io4dtwqdPUNmDfw40o6sxhbZHhqGujDJuHTML1wG8Yw==, + } + + broccoli-node-info@2.2.0: + resolution: + { + integrity: sha512-VabSGRpKIzpmC+r+tJueCE5h8k6vON7EIMMWu6d/FyPdtijwLQ7QvzShEw+m3mHoDzUaj/kiZsDYrS8X2adsBg==, + } + engines: { node: 8.* || >= 10.* } + + broccoli-output-wrapper@3.2.5: + resolution: + { + integrity: sha512-bQAtwjSrF4Nu0CK0JOy5OZqw9t5U0zzv2555EA/cF8/a8SLDTIetk9UgrtMVw7qKLKdSpOZ2liZNeZZDaKgayw==, + } + engines: { node: 10.* || >= 12.* } + + broccoli-plugin@4.0.7: + resolution: + { + integrity: sha512-a4zUsWtA1uns1K7p9rExYVYG99rdKeGRymW0qOCNkvDPHQxVi3yVyJHhQbM3EZwdt2E0mnhr5e0c/bPpJ7p3Wg==, + } + engines: { node: 10.* || >= 12.* } + + brorand@1.1.0: + resolution: + { + integrity: sha512-cKV8tMCEpQs4hK/ik71d6LrPOnpkpGBR0wzxqr68g2m/LB2GxVYQroAjMJZRVM1Y4BCjCKc3vAamxSzOY2RP+w==, + } + + browser-resolve@2.0.0: + resolution: + { + integrity: sha512-7sWsQlYL2rGLy2IWm8WL8DCTJvYLc/qlOnsakDac87SOoCd16WLsaAMdCiAqsTNHIe+SXfaqyxyo6THoWqs8WQ==, + } + + browserify-aes@1.2.0: + resolution: + { + integrity: sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA==, + } + + browserify-cipher@1.0.1: + resolution: + { + integrity: sha512-sPhkz0ARKbf4rRQt2hTpAHqn47X3llLkUGn+xEJzLjwY8LRs2p0v7ljvI5EyoRO/mexrNunNECisZs+gw2zz1w==, + } + + browserify-des@1.0.2: + resolution: + { + integrity: sha512-BioO1xf3hFwz4kc6iBhI3ieDFompMhrMlnDFC4/0/vd5MokpuAc3R+LYbwTA9A5Yc9pq9UYPqffKpW2ObuwX5A==, + } + + browserify-rsa@4.1.1: + resolution: + { + integrity: sha512-YBjSAiTqM04ZVei6sXighu679a3SqWORA3qZTEqZImnlkDIFtKc6pNutpjyZ8RJTjQtuYfeetkxM11GwoYXMIQ==, + } + engines: { node: ">= 0.10" } + + browserify-sign@4.2.5: + resolution: + { + integrity: sha512-C2AUdAJg6rlM2W5QMp2Q4KGQMVBwR1lIimTsUnutJ8bMpW5B52pGpR2gEnNBNwijumDo5FojQ0L9JrXA8m4YEw==, + } + engines: { node: ">= 0.10" } + + browserify-zlib@0.2.0: + resolution: + { + integrity: sha512-Z942RysHXmJrhqk88FmKBVq/v5tqmSkDz7p54G/MGyjMnCFFnC79XWNbg+Vta8W6Wb2qtSZTSxIGkJrRpCFEiA==, + } + + browserslist@4.28.2: + resolution: + { + integrity: sha512-48xSriZYYg+8qXna9kwqjIVzuQxi+KYWp2+5nCYnYKPTr0LvD89Jqk2Or5ogxz0NUMfIjhh2lIUX/LyX9B4oIg==, + } + engines: { node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7 } + hasBin: true + + bs58@6.0.0: + resolution: + { + integrity: sha512-PD0wEnEYg6ijszw/u8s+iI3H17cTymlrwkKhDhPZq+Sokl3AU4htyBFTjAeNAlCCmg0f53g6ih3jATyCKftTfw==, + } + + buffer-from@1.1.2: + resolution: + { + integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==, + } + + buffer-xor@1.0.3: + resolution: + { + integrity: sha512-571s0T7nZWK6vB67HI5dyUF7wXiNcfaPPPTl6zYCNApANjIvYJTg7hlud/+cJpdAhS7dVzqMLmfhfHR3rAcOjQ==, + } + + buffer@5.7.1: + resolution: + { + integrity: sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==, + } + + buffer@6.0.3: + resolution: + { + integrity: sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==, + } + + builtin-modules@3.3.0: + resolution: + { + integrity: sha512-zhaCDicdLuWN5UbN5IMnFqNMhNfo919sH85y2/ea+5Yg9TsTkeZxpL+JLbp6cgYFS4sRLp3YV4S6yDuqVWHYOw==, + } + engines: { node: ">=6" } + + builtin-status-codes@3.0.0: + resolution: + { + integrity: sha512-HpGFw18DgFWlncDfjTa2rcQ4W88O1mC8e8yZ2AvQY5KDaktSTwo+KRf6nHK6FRI5FyRyb/5T6+TSxfP7QyGsmQ==, + } + + bundle-name@4.1.0: + resolution: + { + integrity: sha512-tjwM5exMg6BGRI+kNmTntNsvdZS1X8BFYS6tnJ2hdH0kVxM6/eVZ2xy+FqStSWvYmtfFMDLIxurorHwDKfDz5Q==, + } + engines: { node: ">=18" } + + bytesish@0.4.4: + resolution: + { + integrity: sha512-i4uu6M4zuMUiyfZN4RU2+i9+peJh//pXhd9x1oSe1LBkZ3LEbCoygu8W0bXTukU1Jme2txKuotpCZRaC3FLxcQ==, + } + + call-bind-apply-helpers@1.0.2: + resolution: + { + integrity: sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==, + } + engines: { node: ">= 0.4" } + + call-bind@1.0.9: + resolution: + { + integrity: sha512-a/hy+pNsFUTR+Iz8TCJvXudKVLAnz/DyeSUo10I5yvFDQJBFU2s9uqQpoSrJlroHUKoKqzg+epxyP9lqFdzfBQ==, + } + engines: { node: ">= 0.4" } + + call-bound@1.0.4: + resolution: + { + integrity: sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==, + } + engines: { node: ">= 0.4" } + + callsites@3.1.0: + resolution: + { + integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==, + } + engines: { node: ">=6" } + + camel-case@4.1.2: + resolution: + { + integrity: sha512-gxGWBrTT1JuMx6R+o5PTXMmUnhnVzLQ9SNutD4YqKtI6ap897t3tKECYla6gCWEkplXnlNybEkZg9GEGxKFCgw==, + } + + camelcase@5.3.1: + resolution: + { + integrity: sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==, + } + engines: { node: ">=6" } + + camelcase@6.3.0: + resolution: + { + integrity: sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==, + } + engines: { node: ">=10" } + + caniuse-lite@1.0.30001788: + resolution: + { + integrity: sha512-6q8HFp+lOQtcf7wBK+uEenxymVWkGKkjFpCvw5W25cmMwEDU45p1xQFBQv8JDlMMry7eNxyBaR+qxgmTUZkIRQ==, + } + + caseless@0.12.0: + resolution: + { + integrity: sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw==, + } + + chai@5.3.3: + resolution: + { + integrity: sha512-4zNhdJD/iOjSH0A05ea+Ke6MU5mmpQcbQsSOkgdaUMJ9zTlDTD/GYlwohmIE2u0gaxHYiVHEn1Fw9mZ/ktJWgw==, + } + engines: { node: ">=18" } + + chai@6.2.2: + resolution: + { + integrity: sha512-NUPRluOfOiTKBKvWPtSD4PhFvWCqOi0BGStNWs57X9js7XGTprSmFoz5F0tWhR4WPjNeR9jXqdC7/UpSJTnlRg==, + } + engines: { node: ">=18" } + + chalk@4.1.2: + resolution: + { + integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==, + } + engines: { node: ">=10" } + + chalk@5.6.2: + resolution: + { + integrity: sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA==, + } + engines: { node: ^12.17.0 || ^14.13 || >=16.0.0 } + + check-error@2.1.3: + resolution: + { + integrity: sha512-PAJdDJusoxnwm1VwW07VWwUN1sl7smmC3OKggvndJFadxxDRyFJBX/ggnu/KE4kQAB7a3Dp8f/YXC1FlUprWmA==, + } + engines: { node: ">= 16" } + + cheerio-select@2.1.0: + resolution: + { + integrity: sha512-9v9kG0LvzrlcungtnJtpGNxY+fzECQKhK4EGJX2vByejiMX84MFNQw4UxPJl3bFbTMw+Dfs37XaIkCwTZfLh4g==, + } + + cheerio@1.2.0: + resolution: + { + integrity: sha512-WDrybc/gKFpTYQutKIK6UvfcuxijIZfMfXaYm8NMsPQxSYvf+13fXUJ4rztGGbJcBQ/GF55gvrZ0Bc0bj/mqvg==, + } + engines: { node: ">=20.18.1" } + + chokidar@3.6.0: + resolution: + { + integrity: sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==, + } + engines: { node: ">= 8.10.0" } + + chokidar@4.0.3: + resolution: + { + integrity: sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==, + } + engines: { node: ">= 14.16.0" } + + ci-info@4.4.0: + resolution: + { + integrity: sha512-77PSwercCZU2Fc4sX94eF8k8Pxte6JAwL4/ICZLFjJLqegs7kCuAsqqj/70NQF6TvDpgFjkubQB2FW2ZZddvQg==, + } + engines: { node: ">=8" } + + cipher-base@1.0.7: + resolution: + { + integrity: sha512-Mz9QMT5fJe7bKI7MH31UilT5cEK5EHHRCccw/YRFsRY47AuNgaV6HY3rscp0/I4Q+tTW/5zoqpSeRRI54TkDWA==, + } + engines: { node: ">= 0.10" } + + classnames@2.5.1: + resolution: + { + integrity: sha512-saHYOzhIQs6wy2sVxTM6bUDsQO4F50V9RQ22qBpEdCW+I+/Wmke2HOl6lS6dTpdxVhb88/I6+Hs+438c3lfUow==, + } + + clean-css@5.3.3: + resolution: + { + integrity: sha512-D5J+kHaVb/wKSFcyyV75uCn8fiY4sV38XJoe4CUyGQ+mOU/fMVYUdH1hJC+CJQ5uY3EnW27SbJYS4X8BiLrAFg==, + } + engines: { node: ">= 10.0" } + + clean-regexp@1.0.0: + resolution: + { + integrity: sha512-GfisEZEJvzKrmGWkvfhgzcz/BllN1USeqD2V6tg14OAOgaCD2Z/PUEuxnAZ/nPvmaHRG7a8y77p1T/IRQ4D1Hw==, + } + engines: { node: ">=4" } + + cliui@6.0.0: + resolution: + { + integrity: sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==, + } + + cliui@8.0.1: + resolution: + { + integrity: sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==, + } + engines: { node: ">=12" } + + clone@2.1.2: + resolution: + { + integrity: sha512-3Pe/CF1Nn94hyhIYpjtiLhdCoEoz0DqQ+988E9gmeEdQZlojxnOb74wctFyuwWQHzqyf9X7C7MG8juUpqBJT8w==, + } + engines: { node: ">=0.8" } + + clsx@2.1.1: + resolution: + { + integrity: sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==, + } + engines: { node: ">=6" } + + color-convert@2.0.1: + resolution: + { + integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==, + } + engines: { node: ">=7.0.0" } + + color-name@1.1.4: + resolution: + { + integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==, + } + + colorette@2.0.20: + resolution: + { + integrity: sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==, + } + + colors@1.4.0: + resolution: + { + integrity: sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA==, + } + engines: { node: ">=0.1.90" } + + commander@12.1.0: + resolution: + { + integrity: sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA==, + } + engines: { node: ">=18" } + + commander@2.20.3: + resolution: + { + integrity: sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==, + } + + commander@8.3.0: + resolution: + { + integrity: sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==, + } + engines: { node: ">= 12" } + + comment-parser@1.4.1: + resolution: + { + integrity: sha512-buhp5kePrmda3vhc5B9t7pUQXAb2Tnd0qgpkIhPhkHXxJpiPJ11H0ZEU0oBpJ2QztSbzG/ZxMj/CHsYJqRHmyg==, + } + engines: { node: ">= 12.0.0" } + + common-tags@1.8.2: + resolution: + { + integrity: sha512-gk/Z852D2Wtb//0I+kRFNKKE9dIIVirjoqPoA1wJU+XePVXZfGeBpk45+A1rKO4Q43prqWBNY/MiIeRLbPWUaA==, + } + engines: { node: ">=4.0.0" } + + connect-history-api-fallback@1.6.0: + resolution: + { + integrity: sha512-e54B99q/OUoH64zYYRf3HBP5z24G38h5D3qXu23JGRoigpX5Ss4r9ZnDk3g0Z8uQC2x2lPaJ+UlWBc1ZWBWdLg==, + } + engines: { node: ">=0.8" } + + consola@2.15.3: + resolution: + { + integrity: sha512-9vAdYbHj6x2fLKC4+oPH0kFzY/orMZyG2Aj+kNylHxKGJ/Ed4dpNyAQYwJOdqO4zdM7XpVHmyejQDcQHrnuXbw==, + } + + console-browserify@1.2.0: + resolution: + { + integrity: sha512-ZMkYO/LkF17QvCPqM0gxw8yUzigAOZOSWSHg91FH6orS7vcEj5dVZTidN2fQ14yBSdg97RqhSNwLUXInd52OTA==, + } + + constants-browserify@1.0.0: + resolution: + { + integrity: sha512-xFxOwqIzR/e1k1gLiWEophSCMqXcwVHIH7akf7b/vxcUeGunlj3hvZaaqxwHsTgn+IndtkQJgSztIDWeumWJDQ==, + } + + content-type@1.0.5: + resolution: + { + integrity: sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==, + } + engines: { node: ">= 0.6" } + + convert-source-map@2.0.0: + resolution: + { + integrity: sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==, + } + + cookie@1.1.1: + resolution: + { + integrity: sha512-ei8Aos7ja0weRpFzJnEA9UHJ/7XQmqglbRwnf2ATjcB9Wq874VKH9kfjjirM6UhU2/E5fFYadylyhFldcqSidQ==, + } + engines: { node: ">=18" } + + copy-to-clipboard@3.3.3: + resolution: + { + integrity: sha512-2KV8NhB5JqC3ky0r9PMCAZKbUHSwtEo4CwCs0KXgruG43gX5PMqDEBbVU4OUzw2MuAWUfsuFmWvEKG5QRfSnJA==, + } + + core-js-compat@3.49.0: + resolution: + { + integrity: sha512-VQXt1jr9cBz03b331DFDCCP90b3fanciLkgiOoy8SBHy06gNf+vQ1A3WFLqG7I8TipYIKeYK9wxd0tUrvHcOZA==, + } + + core-util-is@1.0.3: + resolution: + { + integrity: sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==, + } + + cosmiconfig@8.3.6: + resolution: + { + integrity: sha512-kcZ6+W5QzcJ3P1Mt+83OUv/oHFqZHIx8DuxG6eZ5RGMERoLqp4BuGjhHLYGK+Kf5XVkQvqBSmAy/nGWN3qDgEA==, + } + engines: { node: ">=14" } + peerDependencies: + typescript: ">=4.9.5" + peerDependenciesMeta: + typescript: + optional: true + + create-ecdh@4.0.4: + resolution: + { + integrity: sha512-mf+TCx8wWc9VpuxfP2ht0iSISLZnt0JgWlrOKZiNqyUZWnjIaCIVNQArMHnCZKfEYRg6IM7A+NeJoN8gf/Ws0A==, + } + + create-hash@1.2.0: + resolution: + { + integrity: sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==, + } + + create-hmac@1.1.7: + resolution: + { + integrity: sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg==, + } + + create-require@1.1.1: + resolution: + { + integrity: sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==, + } + + cross-spawn@7.0.6: + resolution: + { + integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==, + } + engines: { node: ">= 8" } + + crypto-browserify@3.12.1: + resolution: + { + integrity: sha512-r4ESw/IlusD17lgQi1O20Fa3qNnsckR126TdUuBgAu7GBYSIPvdNyONd3Zrxh0xCwA4+6w/TDArBPsMvhur+KQ==, + } + engines: { node: ">= 0.10" } + + css-blank-pseudo@7.0.1: + resolution: + { + integrity: sha512-jf+twWGDf6LDoXDUode+nc7ZlrqfaNphrBIBrcmeP3D8yw1uPaix1gCC8LUQUGQ6CycuK2opkbFFWFuq/a94ag==, + } + engines: { node: ">=18" } + peerDependencies: + postcss: ^8.4 + + css-has-pseudo@7.0.3: + resolution: + { + integrity: sha512-oG+vKuGyqe/xvEMoxAQrhi7uY16deJR3i7wwhBerVrGQKSqUC5GiOVxTpM9F9B9hw0J+eKeOWLH7E9gZ1Dr5rA==, + } + engines: { node: ">=18" } + peerDependencies: + postcss: ^8.4 + + css-prefers-color-scheme@10.0.0: + resolution: + { + integrity: sha512-VCtXZAWivRglTZditUfB4StnsWr6YVZ2PRtuxQLKTNRdtAf8tpzaVPE9zXIF3VaSc7O70iK/j1+NXxyQCqdPjQ==, + } + engines: { node: ">=18" } + peerDependencies: + postcss: ^8.4 + + css-select@4.3.0: + resolution: + { + integrity: sha512-wPpOYtnsVontu2mODhA19JrqWxNsfdatRKd64kmpRbQgh1KtItko5sTnEpPdpSaJszTOhEMlF/RPz28qj4HqhQ==, + } + + css-select@5.2.2: + resolution: + { + integrity: sha512-TizTzUddG/xYLA3NXodFM0fSbNizXjOKhqiQQwvhlspadZokn1KDy0NZFS0wuEubIYAV5/c1/lAr0TaaFXEXzw==, + } + + css-what@6.2.2: + resolution: + { + integrity: sha512-u/O3vwbptzhMs3L1fQE82ZSLHQQfto5gyZzwteVIEyeaY5Fc7R4dapF/BvRoSYFeqfBk4m0V1Vafq5Pjv25wvA==, + } + engines: { node: ">= 6" } + + css.escape@1.5.1: + resolution: + { + integrity: sha512-YUifsXXuknHlUsmlgyY0PKzgPOr7/FjCePfHNt0jxm83wHZi44VDMQ7/fGNkjY3/jV1MC+1CmZbaHzugyeRtpg==, + } + + cssdb@8.8.0: + resolution: + { + integrity: sha512-QbLeyz2Bgso1iRlh7IpWk6OKa3lLNGXsujVjDMPl9rOZpxKeiG69icLpbLCFxeURwmcdIfZqQyhlooKJYM4f8Q==, + } + + cssesc@3.0.0: + resolution: + { + integrity: sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==, + } + engines: { node: ">=4" } + hasBin: true + + cssstyle@4.6.0: + resolution: + { + integrity: sha512-2z+rWdzbbSZv6/rhtvzvqeZQHrBaqgogqt85sqFNbabZOuFbCVFb8kPeEtZjiKkbrm395irpNKiYeFeLiQnFPg==, + } + engines: { node: ">=18" } + + csstype@3.2.3: + resolution: + { + integrity: sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==, + } + + damerau-levenshtein@1.0.8: + resolution: + { + integrity: sha512-sdQSFB7+llfUcQHUQO3+B8ERRj0Oa4w9POWMI/puGtuf7gFywGmkaLCElnudfTiKZV+NvHqL0ifzdrI8Ro7ESA==, + } + + data-urls@5.0.0: + resolution: + { + integrity: sha512-ZYP5VBHshaDAiVZxjbRVcFJpc+4xGgT0bK3vzy1HLN8jTO975HEbuYzZJcHoQEY5K1a0z8YayJkyVETa08eNTg==, + } + engines: { node: ">=18" } + + data-view-buffer@1.0.2: + resolution: + { + integrity: sha512-EmKO5V3OLXh1rtK2wgXRansaK1/mtVdTUEiEI0W8RkvgT05kfxaH29PliLnpLP73yYO6142Q72QNa8Wx/A5CqQ==, + } + engines: { node: ">= 0.4" } + + data-view-byte-length@1.0.2: + resolution: + { + integrity: sha512-tuhGbE6CfTM9+5ANGf+oQb72Ky/0+s3xKUpHvShfiz2RxMFgFPjsXuRLBVMtvMs15awe45SRb83D6wH4ew6wlQ==, + } + engines: { node: ">= 0.4" } + + data-view-byte-offset@1.0.1: + resolution: + { + integrity: sha512-BS8PfmtDGnrgYdOonGZQdLZslWIeCGFP9tpan0hi1Co2Zr2NKADsvGYA8XxuG/4UWgJ6Cjtv+YJnB6MM69QGlQ==, + } + engines: { node: ">= 0.4" } + + debug@2.6.9: + resolution: + { + integrity: sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==, + } + peerDependencies: + supports-color: "*" + peerDependenciesMeta: + supports-color: + optional: true + + debug@3.2.7: + resolution: + { + integrity: sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==, + } + peerDependencies: + supports-color: "*" + peerDependenciesMeta: + supports-color: + optional: true + + debug@4.4.3: + resolution: + { + integrity: sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==, + } + engines: { node: ">=6.0" } + peerDependencies: + supports-color: "*" + peerDependenciesMeta: + supports-color: + optional: true + + decamelize@1.2.0: + resolution: + { + integrity: sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==, + } + engines: { node: ">=0.10.0" } + + decamelize@5.0.1: + resolution: + { + integrity: sha512-VfxadyCECXgQlkoEAjeghAr5gY3Hf+IKjKb+X8tGVDtveCjN+USwprd2q3QXBR9T1+x2DG0XZF5/w+7HAtSaXA==, + } + engines: { node: ">=10" } + + decimal.js@10.6.0: + resolution: + { + integrity: sha512-YpgQiITW3JXGntzdUmyUR1V812Hn8T1YVXhCu+wO3OpS4eU9l4YdD3qjyiKdV6mvV29zapkMeD390UVEf2lkUg==, + } + + deep-eql@5.0.2: + resolution: + { + integrity: sha512-h5k/5U50IJJFpzfL6nO9jaaumfjO/f2NjK/oYB2Djzm4p9L+3T9qWpZqZ2hAbLPuuYq9wrU08WQyBTL5GbPk5Q==, + } + engines: { node: ">=6" } + + deep-is@0.1.4: + resolution: + { + integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==, + } + + default-browser-id@5.0.1: + resolution: + { + integrity: sha512-x1VCxdX4t+8wVfd1so/9w+vQ4vx7lKd2Qp5tDRutErwmR85OgmfX7RlLRMWafRMY7hbEiXIbudNrjOAPa/hL8Q==, + } + engines: { node: ">=18" } + + default-browser@5.5.0: + resolution: + { + integrity: sha512-H9LMLr5zwIbSxrmvikGuI/5KGhZ8E2zH3stkMgM5LpOWDutGM2JZaj460Udnf1a+946zc7YBgrqEWwbk7zHvGw==, + } + engines: { node: ">=18" } + + define-data-property@1.1.4: + resolution: + { + integrity: sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==, + } + engines: { node: ">= 0.4" } + + define-lazy-prop@3.0.0: + resolution: + { + integrity: sha512-N+MeXYoqr3pOgn8xfyRPREN7gHakLYjhsHhWGT3fWAiL4IkAt0iDw14QiiEm2bE30c5XX5q0FtAA3CK5f9/BUg==, + } + engines: { node: ">=12" } + + define-properties@1.2.1: + resolution: + { + integrity: sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==, + } + engines: { node: ">= 0.4" } + + deprecation@2.3.1: + resolution: + { + integrity: sha512-xmHIy4F3scKVwMsQ4WnVaS8bHOx0DmVwRywosKhaILI0ywMDWPtBSku2HNxRvF7jtwDRsoEwYQSfbxj8b7RlJQ==, + } + + dequal@2.0.3: + resolution: + { + integrity: sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==, + } + engines: { node: ">=6" } + + des.js@1.1.0: + resolution: + { + integrity: sha512-r17GxjhUCjSRy8aiJpr8/UadFIzMzJGexI3Nmz4ADi9LYSFx4gTBp80+NaX/YsXWWLhpZ7v/v/ubEc/bCNfKwg==, + } + + detect-libc@2.1.2: + resolution: + { + integrity: sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==, + } + engines: { node: ">=8" } + + detect-node-es@1.1.0: + resolution: + { + integrity: sha512-ypdmJU/TbBby2Dxibuv7ZLW3Bs1QEmM7nHjEANfohJLvE0XVujisn1qPJcZxg+qDucsr+bP6fLD1rPS3AhJ7EQ==, + } + + diffie-hellman@5.0.3: + resolution: + { + integrity: sha512-kqag/Nl+f3GwyK25fhUMYj81BUOrZ9IuJsjIcDE5icNM9FJHAVm3VcUDxdLPoQtTuUylWm6ZIknYJwwaPxsUzg==, + } + + dijkstrajs@1.0.3: + resolution: + { + integrity: sha512-qiSlmBq9+BCdCA/L46dw8Uy93mloxsPSbwnm5yrKn2vMPiy8KyAskTF6zuV/j5BMsmOGZDPs7KjU+mjb670kfA==, + } + + dir-glob@3.0.1: + resolution: + { + integrity: sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==, + } + engines: { node: ">=8" } + + doctrine@2.1.0: + resolution: + { + integrity: sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==, + } + engines: { node: ">=0.10.0" } + + doctrine@3.0.0: + resolution: + { + integrity: sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==, + } + engines: { node: ">=6.0.0" } + + dom-accessibility-api@0.5.16: + resolution: + { + integrity: sha512-X7BJ2yElsnOJ30pZF4uIIDfBEVgF4XEBxL9Bxhy6dnrm5hkzqmsWHGTiHqRiITNhMyFLyAiWndIJP7Z1NTteDg==, + } + + dom-accessibility-api@0.6.3: + resolution: + { + integrity: sha512-7ZgogeTnjuHbo+ct10G9Ffp0mif17idi0IyWNVA/wcwcm7NPOD/WEHVP3n7n3MhXqxoIYm8d6MuZohYWIZ4T3w==, + } + + dom-serializer@1.4.1: + resolution: + { + integrity: sha512-VHwB3KfrcOOkelEG2ZOfxqLZdfkil8PtJi4P8N2MMXucZq2yLp75ClViUlOVwyoHEDjYU433Aq+5zWP61+RGag==, + } + + dom-serializer@2.0.0: + resolution: + { + integrity: sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==, + } + + domain-browser@4.22.0: + resolution: + { + integrity: sha512-IGBwjF7tNk3cwypFNH/7bfzBcgSCbaMOD3GsaY1AU/JRrnHnYgEM0+9kQt52iZxjNsjBtJYtao146V+f8jFZNw==, + } + engines: { node: ">=10" } + + domelementtype@2.3.0: + resolution: + { + integrity: sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==, + } + + domhandler@4.3.1: + resolution: + { + integrity: sha512-GrwoxYN+uWlzO8uhUXRl0P+kHE4GtVPfYzVLcUxPL7KNdHKj66vvlhiweIHqYYXWlw+T8iLMp42Lm67ghw4WMQ==, + } + engines: { node: ">= 4" } + + domhandler@5.0.3: + resolution: + { + integrity: sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==, + } + engines: { node: ">= 4" } + + domutils@2.8.0: + resolution: + { + integrity: sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==, + } + + domutils@3.2.2: + resolution: + { + integrity: sha512-6kZKyUajlDuqlHKVX1w7gyslj9MPIXzIFiz/rGu35uC1wMi+kMhQwGhl4lt9unC9Vb9INnY9Z3/ZA3+FhASLaw==, + } + + dot-case@3.0.4: + resolution: + { + integrity: sha512-Kv5nKlh6yRrdrGvxeJ2e5y2eRUpkUosIW4A2AS38zwSz27zu7ufDwQPi5Jhs3XAlGNetl3bmnGhQsMtkKJnj3w==, + } + + dotenv-expand@8.0.3: + resolution: + { + integrity: sha512-SErOMvge0ZUyWd5B0NXMQlDkN+8r+HhVUsxgOO7IoPDOdDRD2JjExpN6y3KnFR66jsJMwSn1pqIivhU5rcJiNg==, + } + engines: { node: ">=12" } + + dotenv@16.6.1: + resolution: + { + integrity: sha512-uBq4egWHTcTt33a72vpSG0z3HnPuIl6NqYcTrKEg2azoEyl2hpW0zqlxysq2pK9HlDIHyHyakeYaYnSAwd8bow==, + } + engines: { node: ">=12" } + + dunder-proto@1.0.1: + resolution: + { + integrity: sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==, + } + engines: { node: ">= 0.4" } + + eastasianwidth@0.2.0: + resolution: + { + integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==, + } + + ejs@3.1.10: + resolution: + { + integrity: sha512-UeJmFfOrAQS8OJWPZ4qtgHyWExa088/MtK5UEyoJGFH67cDEXkZSviOiKRCZ4Xij0zxI3JECgYs3oKx+AizQBA==, + } + engines: { node: ">=0.10.0" } + hasBin: true + + electron-to-chromium@1.5.339: + resolution: + { + integrity: sha512-Is+0BBHJ4NrdpAYiperrmp53pLywG/yV/6lIMTAnhxvzj/Cmn5Q/ogSHC6AKe7X+8kPLxxFk0cs5oc/3j/fxIg==, + } + + elliptic@6.6.1: + resolution: + { + integrity: sha512-RaddvvMatK2LJHqFJ+YA4WysVN5Ita9E35botqIYspQ4TkRAlCicdzKOjlyv/1Za5RyTNn7di//eEV0uTAfe3g==, + } + + emoji-regex@8.0.0: + resolution: + { + integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==, + } + + emoji-regex@9.2.2: + resolution: + { + integrity: sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==, + } + + empathic@2.0.0: + resolution: + { + integrity: sha512-i6UzDscO/XfAcNYD75CfICkmfLedpyPDdozrLMmQc5ORaQcdMoc21OnlEylMIqI7U8eniKrPMxxtj8k0vhmJhA==, + } + engines: { node: ">=14" } + + encoding-sniffer@0.2.1: + resolution: + { + integrity: sha512-5gvq20T6vfpekVtqrYQsSCFZ1wEg5+wW0/QaZMWkFr6BqD3NfKs0rLCx4rrVlSWJeZb5NBJgVLswK/w2MWU+Gw==, + } + + ensure-posix-path@1.1.1: + resolution: + { + integrity: sha512-VWU0/zXzVbeJNXvME/5EmLuEj2TauvoaTz6aFYK1Z92JCBlDlZ3Gu0tuGR42kpW1754ywTs+QB0g5TP0oj9Zaw==, + } + + entities@2.2.0: + resolution: + { + integrity: sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==, + } + + entities@4.5.0: + resolution: + { + integrity: sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==, + } + engines: { node: ">=0.12" } + + entities@6.0.1: + resolution: + { + integrity: sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g==, + } + engines: { node: ">=0.12" } + + entities@7.0.1: + resolution: + { + integrity: sha512-TWrgLOFUQTH994YUyl1yT4uyavY5nNB5muff+RtWaqNVCAK408b5ZnnbNAUEWLTCpum9w6arT70i1XdQ4UeOPA==, + } + engines: { node: ">=0.12" } + + eol@0.9.1: + resolution: + { + integrity: sha512-Ds/TEoZjwggRoz/Q2O7SE3i4Jm66mqTDfmdHdq/7DKVk3bro9Q8h6WdXKdPqFLMoqxrDK5SVRzHVPOS6uuGtrg==, + } + + error-ex@1.3.4: + resolution: + { + integrity: sha512-sqQamAnR14VgCr1A618A3sGrygcpK+HEbenA/HiEAkkUwcZIIB/tgWqHFxWgOyDh4nB4JCRimh79dR5Ywc9MDQ==, + } + + es-abstract@1.24.2: + resolution: + { + integrity: sha512-2FpH9Q5i2RRwyEP1AylXe6nYLR5OhaJTZwmlcP0dL/+JCbgg7yyEo/sEK6HeGZRf3dFpWwThaRHVApXSkW3xeg==, + } + engines: { node: ">= 0.4" } + + es-define-property@1.0.1: + resolution: + { + integrity: sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==, + } + engines: { node: ">= 0.4" } + + es-errors@1.3.0: + resolution: + { + integrity: sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==, + } + engines: { node: ">= 0.4" } + + es-iterator-helpers@1.3.2: + resolution: + { + integrity: sha512-HVLACW1TppGYjJ8H6/jqH/pqOtKRw6wMlrB23xfExmFWxFquAIWCmwoLsOyN96K4a5KbmOf5At9ZUO3GZbetAw==, + } + engines: { node: ">= 0.4" } + + es-module-lexer@2.0.0: + resolution: + { + integrity: sha512-5POEcUuZybH7IdmGsD8wlf0AI55wMecM9rVBTI/qEAy2c1kTOm3DjFYjrBdI2K3BaJjJYfYFeRtM0t9ssnRuxw==, + } + + es-object-atoms@1.1.1: + resolution: + { + integrity: sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==, + } + engines: { node: ">= 0.4" } + + es-set-tostringtag@2.1.0: + resolution: + { + integrity: sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==, + } + engines: { node: ">= 0.4" } + + es-shim-unscopables@1.1.0: + resolution: + { + integrity: sha512-d9T8ucsEhh8Bi1woXCf+TIKDIROLG5WCkxg8geBCbvk22kzwC5G2OnXVMO6FUsvQlgUUXQ2itephWDLqDzbeCw==, + } + engines: { node: ">= 0.4" } + + es-to-primitive@1.3.0: + resolution: + { + integrity: sha512-w+5mJ3GuFL+NjVtJlvydShqE1eN3h3PbI7/5LAsYJP/2qtuMXjfL2LpHSRqo4b4eSF5K/DH1JXKUAHSB2UW50g==, + } + engines: { node: ">= 0.4" } + + esbuild@0.27.7: + resolution: + { + integrity: sha512-IxpibTjyVnmrIQo5aqNpCgoACA/dTKLTlhMHihVHhdkxKyPO1uBBthumT0rdHmcsk9uMonIWS0m4FljWzILh3w==, + } + engines: { node: ">=18" } + hasBin: true + + escalade@3.2.0: + resolution: + { + integrity: sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==, + } + engines: { node: ">=6" } + + escape-string-regexp@1.0.5: + resolution: + { + integrity: sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==, + } + engines: { node: ">=0.8.0" } + + escape-string-regexp@4.0.0: + resolution: + { + integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==, + } + engines: { node: ">=10" } + + eslint-config-google@0.14.0: + resolution: + { + integrity: sha512-WsbX4WbjuMvTdeVL6+J3rK1RGhCTqjsFjX7UMSMgZiyxxaNLkoJENbrGExzERFeoTpGw3F3FypTiWAP9ZXzkEw==, + } + engines: { node: ">=0.10.0" } + peerDependencies: + eslint: ">=5.16.0" + + eslint-config-prettier@10.1.8: + resolution: + { + integrity: sha512-82GZUjRS0p/jganf6q1rEO25VSoHH0hKPCTrgillPjdI/3bgBhAE1QzHrHTizjpRvy6pGAvKjDJtk2pF9NDq8w==, + } + hasBin: true + peerDependencies: + eslint: ">=7.0.0" + + eslint-etc@5.2.1: + resolution: + { + integrity: sha512-lFJBSiIURdqQKq9xJhvSJFyPA+VeTh5xvk24e8pxVL7bwLBtGF60C/KRkLTMrvCZ6DA3kbPuYhLWY0TZMlqTsg==, + } + peerDependencies: + eslint: ^8.0.0 + typescript: ">=4.0.0" + + eslint-import-resolver-node@0.3.10: + resolution: + { + integrity: sha512-tRrKqFyCaKict5hOd244sL6EQFNycnMQnBe+j8uqGNXYzsImGbGUU4ibtoaBmv5FLwJwcFJNeg1GeVjQfbMrDQ==, + } + + eslint-module-utils@2.12.1: + resolution: + { + integrity: sha512-L8jSWTze7K2mTg0vos/RuLRS5soomksDPoJLXIslC7c8Wmut3bx7CPpJijDcBZtxQ5lrbUdM+s0OlNbz0DCDNw==, + } + engines: { node: ">=4" } + peerDependencies: + "@typescript-eslint/parser": "*" + eslint: "*" + eslint-import-resolver-node: "*" + eslint-import-resolver-typescript: "*" + eslint-import-resolver-webpack: "*" + peerDependenciesMeta: + "@typescript-eslint/parser": + optional: true + eslint: + optional: true + eslint-import-resolver-node: + optional: true + eslint-import-resolver-typescript: + optional: true + eslint-import-resolver-webpack: + optional: true + + eslint-plugin-deprecate@0.9.0: + resolution: + { + integrity: sha512-M4rP6pRQcvM/LxafQ0PzNKYkfuDn06pOW2uRB2e2WFJiE2KvQqFspxo2Rta3ee6NatHzqDQ4q8UPnaxGMtn5Zw==, + } + engines: { node: ">=18.18.0" } + peerDependencies: + eslint: ^8.0.0 || ^9.0.0 + + eslint-plugin-import@2.32.0: + resolution: + { + integrity: sha512-whOE1HFo/qJDyX4SnXzP4N6zOWn79WhnCUY/iDR0mPfQZO8wcYE4JClzI2oZrhBnnMUCBCHZhO6VQyoBU95mZA==, + } + engines: { node: ">=4" } + peerDependencies: + "@typescript-eslint/parser": "*" + eslint: ^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8 || ^9 + peerDependenciesMeta: + "@typescript-eslint/parser": + optional: true + + eslint-plugin-jest@29.15.2: + resolution: + { + integrity: sha512-kEN4r9RZl1xcsb4arGq89LrcVdOUFII/JSCwtTPJyv16mDwmPrcuEQwpxqZHeINvcsd7oK5O/rhdGlxFRaZwvQ==, + } + engines: { node: ^20.12.0 || ^22.0.0 || >=24.0.0 } + peerDependencies: + "@typescript-eslint/eslint-plugin": ^8.0.0 + eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 + jest: "*" + typescript: ">=4.8.4 <7.0.0" + peerDependenciesMeta: + "@typescript-eslint/eslint-plugin": + optional: true + jest: + optional: true + typescript: + optional: true + + eslint-plugin-jsdoc@61.7.1: + resolution: + { + integrity: sha512-36DpldF95MlTX//n3/naULFVt8d1cV4jmSkx7ZKrE9ikkKHAgMLesuWp1SmwpVwAs5ndIM6abKd6PeOYZUgdWg==, + } + engines: { node: ">=20.11.0" } + peerDependencies: + eslint: ^7.0.0 || ^8.0.0 || ^9.0.0 + + eslint-plugin-jsx-a11y@6.10.2: + resolution: + { + integrity: sha512-scB3nz4WmG75pV8+3eRUQOHZlNSUhFNq37xnpgRkCCELU3XMvXAxLk1eqWWyE22Ki4Q01Fnsw9BA3cJHDPgn2Q==, + } + engines: { node: ">=4.0" } + peerDependencies: + eslint: ^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9 + + eslint-plugin-matrix-org@2.1.0: + resolution: + { + integrity: sha512-YjVQ0qunzVV34tpUchLWhOrOalGfRLm0tclS4dPYnXS8Ui+p12o/YtRHt+26Mg5tJ0QH76HsGC0LJKLVLNoqfg==, + } + peerDependencies: + "@babel/core": "*" + "@babel/eslint-parser": "*" + "@babel/eslint-plugin": "*" + "@stylistic/eslint-plugin": "*" + "@typescript-eslint/eslint-plugin": "*" + "@typescript-eslint/parser": "*" + eslint: "*" + eslint-config-google: "*" + eslint-config-prettier: "*" + eslint-plugin-deprecate: "*" + eslint-plugin-import: "*" + eslint-plugin-jest: "*" + eslint-plugin-jsx-a11y: "*" + eslint-plugin-react: "*" + eslint-plugin-react-hooks: "*" + eslint-plugin-unicorn: "*" + prettier: "*" + typescript: "*" + + eslint-plugin-react-hooks@5.2.0: + resolution: + { + integrity: sha512-+f15FfK64YQwZdJNELETdn5ibXEUQmW1DZL6KXhNnc2heoy/sg9VJJeT7n8TlMWouzWqSWavFkIhHyIbIAEapg==, + } + engines: { node: ">=10" } + peerDependencies: + eslint: ^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0 || ^9.0.0 + + eslint-plugin-react@7.37.5: + resolution: + { + integrity: sha512-Qteup0SqU15kdocexFNAJMvCJEfa2xUKNV4CC1xsVMrIIqEy3SQ/rqyxCWNzfrd3/ldy6HMlD2e0JDVpDg2qIA==, + } + engines: { node: ">=4" } + peerDependencies: + eslint: ^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9.7 + + eslint-plugin-rxjs@5.0.3: + resolution: + { + integrity: sha512-fcVkqLmYLRfRp+ShafjpUKuaZ+cw/sXAvM5dfSxiEr7M28QZ/NY7vaOr09FB4rSaZsQyLBnNPh5SL+4EgKjh8Q==, + } + peerDependencies: + eslint: ^8.0.0 + typescript: ">=4.0.0" + + eslint-plugin-storybook@10.3.5: + resolution: + { + integrity: sha512-rEFkfU3ypF44GpB4tiJ9EFDItueoGvGi3+weLHZax2ON2MB7VIDsxdSUGvIU5tMURg+oWYlpzCyLm4TpDq2deA==, + } + peerDependencies: + eslint: ">=8" + storybook: ^10.3.5 + + eslint-plugin-unicorn@56.0.1: + resolution: + { + integrity: sha512-FwVV0Uwf8XPfVnKSGpMg7NtlZh0G0gBarCaFcMUOoqPxXryxdYxTRRv4kH6B9TFCVIrjRXG+emcxIk2ayZilog==, + } + engines: { node: ">=18.18" } + peerDependencies: + eslint: ">=8.56.0" + + eslint-rule-composer@0.3.0: + resolution: + { + integrity: sha512-bt+Sh8CtDmn2OajxvNO+BX7Wn4CIWMpTRm3MaiKPCQcnnlm0CS2mhui6QaoeQugs+3Kj2ESKEEGJUdVafwhiCg==, + } + engines: { node: ">=4.0.0" } + + eslint-scope@5.1.1: + resolution: + { + integrity: sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==, + } + engines: { node: ">=8.0.0" } + + eslint-scope@7.2.2: + resolution: + { + integrity: sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==, + } + engines: { node: ^12.22.0 || ^14.17.0 || >=16.0.0 } + + eslint-visitor-keys@2.1.0: + resolution: + { + integrity: sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==, + } + engines: { node: ">=10" } + + eslint-visitor-keys@3.4.3: + resolution: + { + integrity: sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==, + } + engines: { node: ^12.22.0 || ^14.17.0 || >=16.0.0 } + + eslint-visitor-keys@4.2.1: + resolution: + { + integrity: sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==, + } + engines: { node: ^18.18.0 || ^20.9.0 || >=21.1.0 } + + eslint-visitor-keys@5.0.1: + resolution: + { + integrity: sha512-tD40eHxA35h0PEIZNeIjkHoDR4YjjJp34biM0mDvplBe//mB+IHCqHDGV7pxF+7MklTvighcCPPZC7ynWyjdTA==, + } + engines: { node: ^20.19.0 || ^22.13.0 || >=24 } + + eslint@8.57.1: + resolution: + { + integrity: sha512-ypowyDxpVSYpkXr9WPv2PAZCtNip1Mv5KTW0SCurXv/9iOpcrH9PaqUElksqEB6pChqHGDRCFTyrZlGhnLNGiA==, + } + engines: { node: ^12.22.0 || ^14.17.0 || >=16.0.0 } + deprecated: This version is no longer supported. Please see https://eslint.org/version-support for other options. + hasBin: true + + espree@10.4.0: + resolution: + { + integrity: sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ==, + } + engines: { node: ^18.18.0 || ^20.9.0 || >=21.1.0 } + + espree@11.2.0: + resolution: + { + integrity: sha512-7p3DrVEIopW1B1avAGLuCSh1jubc01H2JHc8B4qqGblmg5gI9yumBgACjWo4JlIc04ufug4xJ3SQI8HkS/Rgzw==, + } + engines: { node: ^20.19.0 || ^22.13.0 || >=24 } + + espree@9.6.1: + resolution: + { + integrity: sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==, + } + engines: { node: ^12.22.0 || ^14.17.0 || >=16.0.0 } + + esprima@4.0.1: + resolution: + { + integrity: sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==, + } + engines: { node: ">=4" } + hasBin: true + + esquery@1.7.0: + resolution: + { + integrity: sha512-Ap6G0WQwcU/LHsvLwON1fAQX9Zp0A2Y6Y/cJBl9r/JbW90Zyg4/zbG6zzKa2OTALELarYHmKu0GhpM5EO+7T0g==, + } + engines: { node: ">=0.10" } + + esrecurse@4.3.0: + resolution: + { + integrity: sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==, + } + engines: { node: ">=4.0" } + + estraverse@4.3.0: + resolution: + { + integrity: sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==, + } + engines: { node: ">=4.0" } + + estraverse@5.3.0: + resolution: + { + integrity: sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==, + } + engines: { node: ">=4.0" } + + estree-walker@2.0.2: + resolution: + { + integrity: sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==, + } + + estree-walker@3.0.3: + resolution: + { + integrity: sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==, + } + + esutils@2.0.3: + resolution: + { + integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==, + } + engines: { node: ">=0.10.0" } + + events-universal@1.0.1: + resolution: + { + integrity: sha512-LUd5euvbMLpwOF8m6ivPCbhQeSiYVNb8Vs0fQ8QjXo0JTkEHpz8pxdQf0gStltaPpw0Cca8b39KxvK9cfKRiAw==, + } + + events@3.3.0: + resolution: + { + integrity: sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==, + } + engines: { node: ">=0.8.x" } + + evp_bytestokey@1.0.3: + resolution: + { + integrity: sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA==, + } + + expect-type@1.3.0: + resolution: + { + integrity: sha512-knvyeauYhqjOYvQ66MznSMs83wmHrCycNEN6Ao+2AeYEfxUIkuiVxdEa1qlGEPK+We3n0THiDciYSsCcgW/DoA==, + } + engines: { node: ">=12.0.0" } + + fast-deep-equal@3.1.3: + resolution: + { + integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==, + } + + fast-fifo@1.3.2: + resolution: + { + integrity: sha512-/d9sfos4yxzpwkDkuN7k2SqFKtYNmCTzgfEpz82x34IM9/zc8KGxQoXg1liNC/izpRM/MBdt44Nmx41ZWqk+FQ==, + } + + fast-glob@3.3.3: + resolution: + { + integrity: sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==, + } + engines: { node: ">=8.6.0" } + + fast-json-stable-stringify@2.1.0: + resolution: + { + integrity: sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==, + } + + fast-levenshtein@2.0.6: + resolution: + { + integrity: sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==, + } + + fastq@1.20.1: + resolution: + { + integrity: sha512-GGToxJ/w1x32s/D2EKND7kTil4n8OVk/9mycTc4VDza13lOvpUZTGX3mFSCtV9ksdGBVzvsyAVLM6mHFThxXxw==, + } + + fd-package-json@2.0.0: + resolution: + { + integrity: sha512-jKmm9YtsNXN789RS/0mSzOC1NUq9mkVd65vbSSVsKdjGvYXBuE4oWe2QOEoFeRmJg+lPuZxpmrfFclNhoRMneQ==, + } + + fdir@6.5.0: + resolution: + { + integrity: sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==, + } + engines: { node: ">=12.0.0" } + peerDependencies: + picomatch: ^3 || ^4 + peerDependenciesMeta: + picomatch: + optional: true + + fetch-mock@11.1.5: + resolution: + { + integrity: sha512-KHmZDnZ1ry0pCTrX4YG5DtThHi0MH+GNI9caESnzX/nMJBrvppUHMvLx47M0WY9oAtKOMiPfZDRpxhlHg89BOA==, + } + engines: { node: ">=8.0.0" } + peerDependencies: + node-fetch: "*" + peerDependenciesMeta: + node-fetch: + optional: true + + fflate@0.4.8: + resolution: + { + integrity: sha512-FJqqoDBR00Mdj9ppamLa/Y7vxm+PRmNWA67N846RvsoYVMKB4q3y/de5PA7gUmRMYK/8CMz2GDZQmCRN1wBcWA==, + } + + file-entry-cache@6.0.1: + resolution: + { + integrity: sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==, + } + engines: { node: ^10.12.0 || >=12.0.0 } + + filelist@1.0.6: + resolution: + { + integrity: sha512-5giy2PkLYY1cP39p17Ech+2xlpTRL9HLspOfEgm0L6CwBXBTgsK5ou0JtzYuepxkaQ/tvhCFIJ5uXo0OrM2DxA==, + } + + fill-range@7.1.1: + resolution: + { + integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==, + } + engines: { node: ">=8" } + + find-up@4.1.0: + resolution: + { + integrity: sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==, + } + engines: { node: ">=8" } + + find-up@5.0.0: + resolution: + { + integrity: sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==, + } + engines: { node: ">=10" } + + flat-cache@3.2.0: + resolution: + { + integrity: sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==, + } + engines: { node: ^10.12.0 || >=12.0.0 } + + flatted@3.4.2: + resolution: + { + integrity: sha512-PjDse7RzhcPkIJwy5t7KPWQSZ9cAbzQXcafsetQoD7sOJRQlGikNbx7yZp2OotDnJyrDcbyRq3Ttb18iYOqkxA==, + } + + for-each@0.3.5: + resolution: + { + integrity: sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg==, + } + engines: { node: ">= 0.4" } + + foreground-child@3.3.1: + resolution: + { + integrity: sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==, + } + engines: { node: ">=14" } + + formatly@0.3.0: + resolution: + { + integrity: sha512-9XNj/o4wrRFyhSMJOvsuyMwy8aUfBaZ1VrqHVfohyXf0Sw0e+yfKG+xZaY3arGCOMdwFsqObtzVOc1gU9KiT9w==, + } + engines: { node: ">=18.3.0" } + hasBin: true + + fraction.js@5.3.4: + resolution: + { + integrity: sha512-1X1NTtiJphryn/uLQz3whtY6jK3fTqoE3ohKs0tT+Ujr1W59oopxmoEh7Lu5p6vBaPbgoM0bzveAW4Qi5RyWDQ==, + } + + fs-extra@10.1.0: + resolution: + { + integrity: sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==, + } + engines: { node: ">=12" } + + fs-extra@11.3.4: + resolution: + { + integrity: sha512-CTXd6rk/M3/ULNQj8FBqBWHYBVYybQ3VPBw0xGKFe3tuH7ytT6ACnvzpIQ3UZtB8yvUKC2cXn1a+x+5EVQLovA==, + } + engines: { node: ">=14.14" } + + fs-extra@8.1.0: + resolution: + { + integrity: sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==, + } + engines: { node: ">=6 <7 || >=8" } + + fs-merger@3.2.1: + resolution: + { + integrity: sha512-AN6sX12liy0JE7C2evclwoo0aCG3PFulLjrTLsJpWh/2mM+DinhpSGqYLbHBBbIW1PLRNcFhJG8Axtz8mQW3ug==, + } + + fs-mkdirp-stream@2.0.1: + resolution: + { + integrity: sha512-UTOY+59K6IA94tec8Wjqm0FSh5OVudGNB0NL/P6fB3HiE3bYOY3VYBGijsnOHNkQSwC1FKkU77pmq7xp9CskLw==, + } + engines: { node: ">=10.13.0" } + + fs-tree-diff@2.0.1: + resolution: + { + integrity: sha512-x+CfAZ/lJHQqwlD64pYM5QxWjzWhSjroaVsr8PW831zOApL55qPibed0c+xebaLWVr2BnHFoHdrwOv8pzt8R5A==, + } + engines: { node: 6.* || 8.* || >= 10.* } + + fsevents@2.3.2: + resolution: + { + integrity: sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==, + } + engines: { node: ^8.16.0 || ^10.6.0 || >=11.0.0 } + os: [darwin] + + fsevents@2.3.3: + resolution: + { + integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==, + } + engines: { node: ^8.16.0 || ^10.6.0 || >=11.0.0 } + os: [darwin] + + function-bind@1.1.2: + resolution: + { + integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==, + } + + function.prototype.name@1.1.8: + resolution: + { + integrity: sha512-e5iwyodOHhbMr/yNrc7fDYG4qlbIvI5gajyzPnb5TCwyhjApznQh1BMFou9b30SevY43gCJKXycoCBjMbsuW0Q==, + } + engines: { node: ">= 0.4" } + + functions-have-names@1.2.3: + resolution: + { + integrity: sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==, + } + + generator-function@2.0.1: + resolution: + { + integrity: sha512-SFdFmIJi+ybC0vjlHN0ZGVGHc3lgE0DxPAT0djjVg+kjOnSqclqmj0KQ7ykTOLP6YxoqOvuAODGdcHJn+43q3g==, + } + engines: { node: ">= 0.4" } + + gensync@1.0.0-beta.2: + resolution: + { + integrity: sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==, + } + engines: { node: ">=6.9.0" } + + get-caller-file@2.0.5: + resolution: + { + integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==, + } + engines: { node: 6.* || 8.* || >= 10.* } + + get-intrinsic@1.3.0: + resolution: + { + integrity: sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==, + } + engines: { node: ">= 0.4" } + + get-nonce@1.0.1: + resolution: + { + integrity: sha512-FJhYRoDaiatfEkUK8HKlicmu/3SGFD51q3itKDGoSTysQJBnfOcxU5GxnhE1E6soB76MbT0MBtnKJuXyAx+96Q==, + } + engines: { node: ">=6" } + + get-proto@1.0.1: + resolution: + { + integrity: sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==, + } + engines: { node: ">= 0.4" } + + get-symbol-description@1.1.0: + resolution: + { + integrity: sha512-w9UMqWwJxHNOvoNzSJ2oPF5wvYcvP7jUvYzhp67yEhTi17ZDBBC1z9pTdGuzjD+EFIqLSYRweZjqfiPzQ06Ebg==, + } + engines: { node: ">= 0.4" } + + glob-parent@5.1.2: + resolution: + { + integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==, + } + engines: { node: ">= 6" } + + glob-parent@6.0.2: + resolution: + { + integrity: sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==, + } + engines: { node: ">=10.13.0" } + + glob-stream@8.0.3: + resolution: + { + integrity: sha512-fqZVj22LtFJkHODT+M4N1RJQ3TjnnQhfE9GwZI8qXscYarnhpip70poMldRnP8ipQ/w0B621kOhfc53/J9bd/A==, + } + engines: { node: ">=10.13.0" } + + glob-to-regexp@0.4.1: + resolution: + { + integrity: sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==, + } + + glob@10.5.0: + resolution: + { + integrity: sha512-DfXN8DfhJ7NH3Oe7cFmu3NCu1wKbkReJ8TorzSAFbSKrlNaQSKfIzqYqVY8zlbs2NLBbWpRiU52GX2PbaBVNkg==, + } + deprecated: Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me + hasBin: true + + global-jsdom@26.0.0: + resolution: + { + integrity: sha512-BqXpTNZFjP40N+s4k8Bk9HS8GFVPJB/+TKtwcShM84wLv6C5dH9o1dydI3pL6potanhfDiIAVDbaaGj/uSdRSA==, + } + engines: { node: ">=18" } + peerDependencies: + jsdom: ">=26 <27" + + globals@13.24.0: + resolution: + { + integrity: sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==, + } + engines: { node: ">=8" } + + globals@15.15.0: + resolution: + { + integrity: sha512-7ACyT3wmyp3I61S4fG682L0VA2RGD9otkqGJIwNUMF1SWUombIIk+af1unuDYgMm082aHYwD+mzJvv9Iu8dsgg==, + } + engines: { node: ">=18" } + + globalthis@1.0.4: + resolution: + { + integrity: sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==, + } + engines: { node: ">= 0.4" } + + globby@11.1.0: + resolution: + { + integrity: sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==, + } + engines: { node: ">=10" } + + gopd@1.2.0: + resolution: + { + integrity: sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==, + } + engines: { node: ">= 0.4" } + + graceful-fs@4.2.11: + resolution: + { + integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==, + } + + graphemer@1.4.0: + resolution: + { + integrity: sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==, + } + + gulp-sort@2.0.0: + resolution: + { + integrity: sha512-MyTel3FXOdh1qhw1yKhpimQrAmur9q1X0ZigLmCOxouQD+BD3za9/89O+HfbgBQvvh4igEbp0/PUWO+VqGYG1g==, + } + + has-bigints@1.1.0: + resolution: + { + integrity: sha512-R3pbpkcIqv2Pm3dUwgjclDRVmWpTJW2DcMzcIhEXEx1oh/CEMObMm3KLmRJOdvhM7o4uQBnwr8pzRK2sJWIqfg==, + } + engines: { node: ">= 0.4" } + + has-flag@4.0.0: + resolution: + { + integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==, + } + engines: { node: ">=8" } + + has-property-descriptors@1.0.2: + resolution: + { + integrity: sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==, + } + + has-proto@1.2.0: + resolution: + { + integrity: sha512-KIL7eQPfHQRC8+XluaIw7BHUwwqL19bQn4hzNgdr+1wXoU0KKj6rufu47lhY7KbJR2C6T6+PfyN0Ea7wkSS+qQ==, + } + engines: { node: ">= 0.4" } + + has-symbols@1.1.0: + resolution: + { + integrity: sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==, + } + engines: { node: ">= 0.4" } + + has-tostringtag@1.0.2: + resolution: + { + integrity: sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==, + } + engines: { node: ">= 0.4" } + + hash-base@3.0.5: + resolution: + { + integrity: sha512-vXm0l45VbcHEVlTCzs8M+s0VeYsB2lnlAaThoLKGXr3bE/VWDOelNUnycUPEhKEaXARL2TEFjBOyUiM6+55KBg==, + } + engines: { node: ">= 0.10" } + + hash-base@3.1.2: + resolution: + { + integrity: sha512-Bb33KbowVTIj5s7Ked1OsqHUeCpz//tPwR+E2zJgJKo9Z5XolZ9b6bdUgjmYlwnWhoOQKoTd1TYToZGn5mAYOg==, + } + engines: { node: ">= 0.8" } + + hash.js@1.1.7: + resolution: + { + integrity: sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA==, + } + + hasown@2.0.2: + resolution: + { + integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==, + } + engines: { node: ">= 0.4" } + + he@1.2.0: + resolution: + { + integrity: sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==, + } + hasBin: true + + heimdalljs-logger@0.1.10: + resolution: + { + integrity: sha512-pO++cJbhIufVI/fmB/u2Yty3KJD0TqNPecehFae0/eps0hkZ3b4Zc/PezUMOpYuHFQbA7FxHZxa305EhmjLj4g==, + } + + heimdalljs@0.2.6: + resolution: + { + integrity: sha512-o9bd30+5vLBvBtzCPwwGqpry2+n0Hi6H1+qwt6y+0kwRHGGF8TFIhJPmnuM0xO97zaKrDZMwO/V56fAnn8m/tA==, + } + + hmac-drbg@1.0.1: + resolution: + { + integrity: sha512-Tti3gMqLdZfhOQY1Mzf/AanLiqh1WTiJgEj26ZuYQ9fbkLomzGchCws4FyrSd4VkpBfiNhaE1On+lOz894jvXg==, + } + + hoist-non-react-statics@3.3.2: + resolution: + { + integrity: sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==, + } + + hosted-git-info@2.8.9: + resolution: + { + integrity: sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==, + } + + html-encoding-sniffer@4.0.0: + resolution: + { + integrity: sha512-Y22oTqIU4uuPgEemfz7NDJz6OeKf12Lsu+QC+s3BVpda64lTiMYCyGwg5ki4vFxkMwQdeZDl2adZoqUgdFuTgQ==, + } + engines: { node: ">=18" } + + html-entities@2.6.0: + resolution: + { + integrity: sha512-kig+rMn/QOVRvr7c86gQ8lWXq+Hkv6CbAH1hLu+RG338StTpE8Z0b44SDVaqVu7HGKf27frdmUYEs9hTUX/cLQ==, + } + + html-escaper@2.0.2: + resolution: + { + integrity: sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==, + } + + html-minifier-terser@6.1.0: + resolution: + { + integrity: sha512-YXxSlJBZTP7RS3tWnQw74ooKa6L9b9i9QYXY21eUEvhZ3u9XLfv6OnFsQq6RxkhHygsaUMvYsZRV5rU/OVNZxw==, + } + engines: { node: ">=12" } + hasBin: true + + html-parse-stringify@3.0.1: + resolution: + { + integrity: sha512-KknJ50kTInJ7qIScF3jeaFRpMpE8/lfiTdzf/twXyPBLAGrLRTmkz3AdTnKeh40X8k9L2fdYwEp/42WGXIRGcg==, + } + + htmlparser2@10.1.0: + resolution: + { + integrity: sha512-VTZkM9GWRAtEpveh7MSF6SjjrpNVNNVJfFup7xTY3UpFtm67foy9HDVXneLtFVt4pMz5kZtgNcvCniNFb1hlEQ==, + } + + http-proxy-agent@7.0.2: + resolution: + { + integrity: sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==, + } + engines: { node: ">= 14" } + + https-browserify@1.0.0: + resolution: + { + integrity: sha512-J+FkSdyD+0mA0N+81tMotaRMfSL9SGi+xpD3T6YApKsc3bGSXJlfXri3VyFOeYkfLRQisDk1W+jIFFKBeUBbBg==, + } + + https-proxy-agent@5.0.1: + resolution: + { + integrity: sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==, + } + engines: { node: ">= 6" } + + https-proxy-agent@7.0.6: + resolution: + { + integrity: sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==, + } + engines: { node: ">= 14" } + + i18next-browser-languagedetector@8.2.1: + resolution: + { + integrity: sha512-bZg8+4bdmaOiApD7N7BPT9W8MLZG+nPTOFlLiJiT8uzKXFjhxw4v2ierCXOwB5sFDMtuA5G4kgYZ0AznZxQ/cw==, + } + + i18next-parser@9.4.0: + resolution: + { + integrity: sha512-SLQJGDj/baBIB9ALmJVXSOXWh3Zn9+wH7J2IuQ4rvx8yuQYpUWitmt8cHFjj6FExjgr8dHfd1SGeQgkowXDO1Q==, + } + engines: { node: ^18.0.0 || ^20.0.0 || ^22.0.0, npm: ">=6", yarn: ">=1" } + deprecated: Project is deprecated, use i18next-cli instead + hasBin: true + + i18next@24.2.3: + resolution: + { + integrity: sha512-lfbf80OzkocvX7nmZtu7nSTNbrTYR52sLWxPtlXX1zAhVw8WEnFk4puUkCR4B1dNQwbSpEHHHemcZu//7EcB7A==, + } + peerDependencies: + typescript: ^5 + peerDependenciesMeta: + typescript: + optional: true + + i18next@25.10.10: + resolution: + { + integrity: sha512-cqUW2Z3EkRx7NqSyywjkgCLK7KLCL6IFVFcONG7nVYIJ3ekZ1/N5jUsihHV6Bq37NfhgtczxJcxduELtjTwkuQ==, + } + peerDependencies: + typescript: ^5 || ^6 + peerDependenciesMeta: + typescript: + optional: true + + iconv-lite@0.6.3: + resolution: + { + integrity: sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==, + } + engines: { node: ">=0.10.0" } + + ieee754@1.2.1: + resolution: + { + integrity: sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==, + } + + ignore@5.3.2: + resolution: + { + integrity: sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==, + } + engines: { node: ">= 4" } + + ignore@7.0.5: + resolution: + { + integrity: sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==, + } + engines: { node: ">= 4" } + + immutable@5.1.5: + resolution: + { + integrity: sha512-t7xcm2siw+hlUM68I+UEOK+z84RzmN59as9DZ7P1l0994DKUWV7UXBMQZVxaoMSRQ+PBZbHCOoBt7a2wxOMt+A==, + } + + import-fresh@3.3.1: + resolution: + { + integrity: sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==, + } + engines: { node: ">=6" } + + imurmurhash@0.1.4: + resolution: + { + integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==, + } + engines: { node: ">=0.8.19" } + + indent-string@4.0.0: + resolution: + { + integrity: sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==, + } + engines: { node: ">=8" } + + inherits@2.0.4: + resolution: + { + integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==, + } + + internal-slot@1.1.0: + resolution: + { + integrity: sha512-4gd7VpWNQNB4UKKCFFVcp1AVv+FMOgs9NKzjHKusc8jTMhd5eL1NqQqOpE0KzMds804/yHlglp3uxgluOqAPLw==, + } + engines: { node: ">= 0.4" } + + is-arguments@1.2.0: + resolution: + { + integrity: sha512-7bVbi0huj/wrIAOzb8U1aszg9kdi3KN/CyU19CTI7tAoZYEZoL9yCDXpbXN+uPsuWnP02cyug1gleqq+TU+YCA==, + } + engines: { node: ">= 0.4" } + + is-array-buffer@3.0.5: + resolution: + { + integrity: sha512-DDfANUiiG2wC1qawP66qlTugJeL5HyzMpfr8lLK+jMQirGzNod0B12cFB/9q838Ru27sBwfw78/rdoU7RERz6A==, + } + engines: { node: ">= 0.4" } + + is-arrayish@0.2.1: + resolution: + { + integrity: sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==, + } + + is-async-function@2.1.1: + resolution: + { + integrity: sha512-9dgM/cZBnNvjzaMYHVoxxfPj2QXt22Ev7SuuPrs+xav0ukGB0S6d4ydZdEiM48kLx5kDV+QBPrpVnFyefL8kkQ==, + } + engines: { node: ">= 0.4" } + + is-bigint@1.1.0: + resolution: + { + integrity: sha512-n4ZT37wG78iz03xPRKJrHTdZbe3IicyucEtdRsV5yglwc3GyUfbAfpSeD0FJ41NbUNSt5wbhqfp1fS+BgnvDFQ==, + } + engines: { node: ">= 0.4" } + + is-binary-path@2.1.0: + resolution: + { + integrity: sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==, + } + engines: { node: ">=8" } + + is-boolean-object@1.2.2: + resolution: + { + integrity: sha512-wa56o2/ElJMYqjCjGkXri7it5FbebW5usLw/nPmCMs5DeZ7eziSYZhSmPRn0txqeW4LnAmQQU7FgqLpsEFKM4A==, + } + engines: { node: ">= 0.4" } + + is-builtin-module@3.2.1: + resolution: + { + integrity: sha512-BSLE3HnV2syZ0FK0iMA/yUGplUeMmNz4AW5fnTunbCIqZi4vG3WjJT9FHMy5D69xmAYBHXQhJdALdpwVxV501A==, + } + engines: { node: ">=6" } + + is-callable@1.2.7: + resolution: + { + integrity: sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==, + } + engines: { node: ">= 0.4" } + + is-core-module@2.16.1: + resolution: + { + integrity: sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==, + } + engines: { node: ">= 0.4" } + + is-data-view@1.0.2: + resolution: + { + integrity: sha512-RKtWF8pGmS87i2D6gqQu/l7EYRlVdfzemCJN/P3UOs//x1QE7mfhvzHIApBTRf7axvT6DMGwSwBXYCT0nfB9xw==, + } + engines: { node: ">= 0.4" } + + is-date-object@1.1.0: + resolution: + { + integrity: sha512-PwwhEakHVKTdRNVOw+/Gyh0+MzlCl4R6qKvkhuvLtPMggI1WAHt9sOwZxQLSGpUaDnrdyDsomoRgNnCfKNSXXg==, + } + engines: { node: ">= 0.4" } + + is-docker@3.0.0: + resolution: + { + integrity: sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ==, + } + engines: { node: ^12.20.0 || ^14.13.1 || >=16.0.0 } + hasBin: true + + is-extglob@2.1.1: + resolution: + { + integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==, + } + engines: { node: ">=0.10.0" } + + is-finalizationregistry@1.1.1: + resolution: + { + integrity: sha512-1pC6N8qWJbWoPtEjgcL2xyhQOP491EQjeUo3qTKcmV8YSDDJrOepfG8pcC7h/QgnQHYSv0mJ3Z/ZWxmatVrysg==, + } + engines: { node: ">= 0.4" } + + is-fullwidth-code-point@3.0.0: + resolution: + { + integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==, + } + engines: { node: ">=8" } + + is-generator-function@1.1.2: + resolution: + { + integrity: sha512-upqt1SkGkODW9tsGNG5mtXTXtECizwtS2kA161M+gJPc1xdb/Ax629af6YrTwcOeQHbewrPNlE5Dx7kzvXTizA==, + } + engines: { node: ">= 0.4" } + + is-glob@4.0.3: + resolution: + { + integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==, + } + engines: { node: ">=0.10.0" } + + is-inside-container@1.0.0: + resolution: + { + integrity: sha512-KIYLCCJghfHZxqjYBE7rEy0OBuTd5xCHS7tHVgvCLkx7StIoaxwNW3hCALgEUjFfeRk+MG/Qxmp/vtETEF3tRA==, + } + engines: { node: ">=14.16" } + hasBin: true + + is-map@2.0.3: + resolution: + { + integrity: sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw==, + } + engines: { node: ">= 0.4" } + + is-nan@1.3.2: + resolution: + { + integrity: sha512-E+zBKpQ2t6MEo1VsonYmluk9NxGrbzpeeLC2xIViuO2EjU2xsXsBPwTr3Ykv9l08UYEVEdWeRZNouaZqF6RN0w==, + } + engines: { node: ">= 0.4" } + + is-negated-glob@1.0.0: + resolution: + { + integrity: sha512-czXVVn/QEmgvej1f50BZ648vUI+em0xqMq2Sn+QncCLN4zj1UAxlT+kw/6ggQTOaZPd1HqKQGEqbpQVtJucWug==, + } + engines: { node: ">=0.10.0" } + + is-negative-zero@2.0.3: + resolution: + { + integrity: sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw==, + } + engines: { node: ">= 0.4" } + + is-network-error@1.3.1: + resolution: + { + integrity: sha512-6QCxa49rQbmUWLfk0nuGqzql9U8uaV2H6279bRErPBHe/109hCzsLUBUHfbEtvLIHBd6hyXbgedBSHevm43Edw==, + } + engines: { node: ">=16" } + + is-number-object@1.1.1: + resolution: + { + integrity: sha512-lZhclumE1G6VYD8VHe35wFaIif+CTy5SJIi5+3y4psDgWu4wPDoBhF8NxUOinEc7pHgiTsT6MaBb92rKhhD+Xw==, + } + engines: { node: ">= 0.4" } + + is-number@7.0.0: + resolution: + { + integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==, + } + engines: { node: ">=0.12.0" } + + is-path-inside@3.0.3: + resolution: + { + integrity: sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==, + } + engines: { node: ">=8" } + + is-plain-obj@4.1.0: + resolution: + { + integrity: sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg==, + } + engines: { node: ">=12" } + + is-potential-custom-element-name@1.0.1: + resolution: + { + integrity: sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==, + } + + is-regex@1.2.1: + resolution: + { + integrity: sha512-MjYsKHO5O7mCsmRGxWcLWheFqN9DJ/2TmngvjKXihe6efViPqc274+Fx/4fYj/r03+ESvBdTXK0V6tA3rgez1g==, + } + engines: { node: ">= 0.4" } + + is-set@2.0.3: + resolution: + { + integrity: sha512-iPAjerrse27/ygGLxw+EBR9agv9Y6uLeYVJMu+QNCoouJ1/1ri0mGrcWpfCqFZuzzx3WjtwxG098X+n4OuRkPg==, + } + engines: { node: ">= 0.4" } + + is-shared-array-buffer@1.0.4: + resolution: + { + integrity: sha512-ISWac8drv4ZGfwKl5slpHG9OwPNty4jOWPRIhBpxOoD+hqITiwuipOQ2bNthAzwA3B4fIjO4Nln74N0S9byq8A==, + } + engines: { node: ">= 0.4" } + + is-stream@2.0.1: + resolution: + { + integrity: sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==, + } + engines: { node: ">=8" } + + is-string@1.1.1: + resolution: + { + integrity: sha512-BtEeSsoaQjlSPBemMQIrY1MY0uM6vnS1g5fmufYOtnxLGUZM2178PKbhsk7Ffv58IX+ZtcvoGwccYsh0PglkAA==, + } + engines: { node: ">= 0.4" } + + is-subset@0.1.1: + resolution: + { + integrity: sha512-6Ybun0IkarhmEqxXCNw/C0bna6Zb/TkfUX9UbwJtK6ObwAVCxmAP308WWTHviM/zAqXk05cdhYsUsZeGQh99iw==, + } + + is-symbol@1.1.1: + resolution: + { + integrity: sha512-9gGx6GTtCQM73BgmHQXfDmLtfjjTUDSyoxTCbp5WtoixAhfgsDirWIcVQ/IHpvI5Vgd5i/J5F7B9cN/WlVbC/w==, + } + engines: { node: ">= 0.4" } + + is-typed-array@1.1.15: + resolution: + { + integrity: sha512-p3EcsicXjit7SaskXHs1hA91QxgTw46Fv6EFKKGS5DRFLD8yKnohjF3hxoju94b/OcMZoQukzpPpBE9uLVKzgQ==, + } + engines: { node: ">= 0.4" } + + is-valid-glob@1.0.0: + resolution: + { + integrity: sha512-AhiROmoEFDSsjx8hW+5sGwgKVIORcXnrlAx/R0ZSeaPw70Vw0CqkGBBhHGL58Uox2eXnU1AnvXJl1XlyedO5bA==, + } + engines: { node: ">=0.10.0" } + + is-weakmap@2.0.2: + resolution: + { + integrity: sha512-K5pXYOm9wqY1RgjpL3YTkF39tni1XajUIkawTLUo9EZEVUFga5gSQJF8nNS7ZwJQ02y+1YCNYcMh+HIf1ZqE+w==, + } + engines: { node: ">= 0.4" } + + is-weakref@1.1.1: + resolution: + { + integrity: sha512-6i9mGWSlqzNMEqpCp93KwRS1uUOodk2OJ6b+sq7ZPDSy2WuI5NFIxp/254TytR8ftefexkWn5xNiHUNpPOfSew==, + } + engines: { node: ">= 0.4" } + + is-weakset@2.0.4: + resolution: + { + integrity: sha512-mfcwb6IzQyOKTs84CQMrOwW4gQcaTOAWJ0zzJCl2WSPDrWk/OzDaImWFH3djXhb24g4eudZfLRozAvPGw4d9hQ==, + } + engines: { node: ">= 0.4" } + + is-wsl@3.1.1: + resolution: + { + integrity: sha512-e6rvdUCiQCAuumZslxRJWR/Doq4VpPR82kqclvcS0efgt430SlGIk05vdCN58+VrzgtIcfNODjozVielycD4Sw==, + } + engines: { node: ">=16" } + + isarray@1.0.0: + resolution: + { + integrity: sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==, + } + + isarray@2.0.5: + resolution: + { + integrity: sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==, + } + + isexe@2.0.0: + resolution: + { + integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==, + } + + isomorphic-timers-promises@1.0.1: + resolution: + { + integrity: sha512-u4sej9B1LPSxTGKB/HiuzvEQnXH0ECYkSVQU39koSwmFAxhlEAFl9RdTvLv4TOTQUgBS5O3O5fwUxk6byBZ+IQ==, + } + engines: { node: ">=10" } + + istanbul-lib-coverage@3.2.2: + resolution: + { + integrity: sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==, + } + engines: { node: ">=8" } + + istanbul-lib-report@3.0.1: + resolution: + { + integrity: sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==, + } + engines: { node: ">=10" } + + istanbul-reports@3.2.0: + resolution: + { + integrity: sha512-HGYWWS/ehqTV3xN10i23tkPkpH46MLCIMFNCaaKNavAXTF1RkqxawEPtnjnGZ6XKSInBKkiOA5BKS+aZiY3AvA==, + } + engines: { node: ">=8" } + + iterator.prototype@1.1.5: + resolution: + { + integrity: sha512-H0dkQoCa3b2VEeKQBOxFph+JAbcrQdE7KC0UkqwpLmv2EC4P41QXP+rqo9wYodACiG5/WM5s9oDApTU8utwj9g==, + } + engines: { node: ">= 0.4" } + + jackspeak@3.4.3: + resolution: + { + integrity: sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==, + } + + jake@10.9.4: + resolution: + { + integrity: sha512-wpHYzhxiVQL+IV05BLE2Xn34zW1S223hvjtqk0+gsPrwd/8JNLXJgZZM/iPFsYc1xyphF+6M6EvdE5E9MBGkDA==, + } + engines: { node: ">=10" } + hasBin: true + + jiti@2.6.1: + resolution: + { + integrity: sha512-ekilCSN1jwRvIbgeg/57YFh8qQDNbwDb9xT/qu2DAHbFFZUicIl4ygVaAvzveMhMVr3LnpSKTNnwt8PoOfmKhQ==, + } + hasBin: true + + jose@6.2.2: + resolution: + { + integrity: sha512-d7kPDd34KO/YnzaDOlikGpOurfF0ByC2sEV4cANCtdqLlTfBlw2p14O/5d/zv40gJPbIQxfES3nSx1/oYNyuZQ==, + } + + js-tokens@10.0.0: + resolution: + { + integrity: sha512-lM/UBzQmfJRo9ABXbPWemivdCW8V2G8FHaHdypQaIy523snUjog0W71ayWXTjiR+ixeMyVHN2XcpnTd/liPg/Q==, + } + + js-tokens@4.0.0: + resolution: + { + integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==, + } + + js-yaml@4.1.1: + resolution: + { + integrity: sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==, + } + hasBin: true + + jsdoc-type-pratt-parser@7.0.0: + resolution: + { + integrity: sha512-c7YbokssPOSHmqTbSAmTtnVgAVa/7lumWNYqomgd5KOMyPrRve2anx6lonfOsXEQacqF9FKVUj7bLg4vRSvdYA==, + } + engines: { node: ">=20.0.0" } + + jsdom@26.1.0: + resolution: + { + integrity: sha512-Cvc9WUhxSMEo4McES3P7oK3QaXldCfNWp7pl2NNeiIFlCoLr3kfq9kb1fxftiwk1FLV7CvpvDfonxtzUDeSOPg==, + } + engines: { node: ">=18" } + peerDependencies: + canvas: ^3.0.0 + peerDependenciesMeta: + canvas: + optional: true + + jsesc@0.5.0: + resolution: + { + integrity: sha512-uZz5UnB7u4T9LvwmFqXii7pZSouaRPorGs5who1Ip7VO0wxanFvBL7GkM6dTHlgX+jhBApRetaWpnDabOeTcnA==, + } + hasBin: true + + jsesc@3.1.0: + resolution: + { + integrity: sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==, + } + engines: { node: ">=6" } + hasBin: true + + json-buffer@3.0.1: + resolution: + { + integrity: sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==, + } + + json-parse-even-better-errors@2.3.1: + resolution: + { + integrity: sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==, + } + + json-schema-traverse@0.4.1: + resolution: + { + integrity: sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==, + } + + json-stable-stringify-without-jsonify@1.0.1: + resolution: + { + integrity: sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==, + } + + json5@1.0.2: + resolution: + { + integrity: sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==, + } + hasBin: true + + json5@2.2.3: + resolution: + { + integrity: sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==, + } + engines: { node: ">=6" } + hasBin: true + + jsonfile@4.0.0: + resolution: + { + integrity: sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==, + } + + jsonfile@6.2.0: + resolution: + { + integrity: sha512-FGuPw30AdOIUTRMC2OMRtQV+jkVj2cfPqSeWXv1NEAJ1qZ5zb1X6z1mFhbfOB/iy3ssJCD+3KuZ8r8C3uVFlAg==, + } + + jsx-ast-utils@3.3.5: + resolution: + { + integrity: sha512-ZZow9HBI5O6EPgSJLUb8n2NKgmVWTwCvHGwFuJlMjvLFqlGG6pjirPhtdsseaLZjSibD8eegzmYpUZwoIlj2cQ==, + } + engines: { node: ">=4.0" } + + jwt-decode@4.0.0: + resolution: + { + integrity: sha512-+KJGIyHgkGuIq3IEBNftfhW/LfWhXUIY6OmyVWjliu5KH1y0fw7VQ8YndE2O4qZdMSd9SqbnC8GOcZEy0Om7sA==, + } + engines: { node: ">=18" } + + keyv@4.5.4: + resolution: + { + integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==, + } + + kleur@3.0.3: + resolution: + { + integrity: sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==, + } + engines: { node: ">=6" } + + knip@5.88.1: + resolution: + { + integrity: sha512-tpy5o7zu1MjawVkLPuahymVJekYY3kYjvzcoInhIchgePxTlo+api90tBv2KfhAIe5uXh+mez1tAfmbv8/TiZg==, + } + engines: { node: ">=18.18.0" } + hasBin: true + peerDependencies: + "@types/node": ">=18" + typescript: ">=5.0.4 <7" + + language-subtag-registry@0.3.23: + resolution: + { + integrity: sha512-0K65Lea881pHotoGEa5gDlMxt3pctLi2RplBb7Ezh4rRdLEOtgi7n4EwK9lamnUCkKBqaeKRVebTq6BAxSkpXQ==, + } + + language-tags@1.0.9: + resolution: + { + integrity: sha512-MbjN408fEndfiQXbFQ1vnd+1NoLDsnQW41410oQBXiyXDMYH5z505juWa4KUE1LqxRC7DgOgZDbKLxHIwm27hA==, + } + engines: { node: ">=0.10" } + + lead@4.0.0: + resolution: + { + integrity: sha512-DpMa59o5uGUWWjruMp71e6knmwKU3jRBBn1kjuLWN9EeIOxNeSAwvHf03WIl8g/ZMR2oSQC9ej3yeLBwdDc/pg==, + } + engines: { node: ">=10.13.0" } + + levn@0.4.1: + resolution: + { + integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==, + } + engines: { node: ">= 0.8.0" } + + lightningcss-android-arm64@1.32.0: + resolution: + { + integrity: sha512-YK7/ClTt4kAK0vo6w3X+Pnm0D2cf2vPHbhOXdoNti1Ga0al1P4TBZhwjATvjNwLEBCnKvjJc2jQgHXH0NEwlAg==, + } + engines: { node: ">= 12.0.0" } + cpu: [arm64] + os: [android] + + lightningcss-darwin-arm64@1.32.0: + resolution: + { + integrity: sha512-RzeG9Ju5bag2Bv1/lwlVJvBE3q6TtXskdZLLCyfg5pt+HLz9BqlICO7LZM7VHNTTn/5PRhHFBSjk5lc4cmscPQ==, + } + engines: { node: ">= 12.0.0" } + cpu: [arm64] + os: [darwin] + + lightningcss-darwin-x64@1.32.0: + resolution: + { + integrity: sha512-U+QsBp2m/s2wqpUYT/6wnlagdZbtZdndSmut/NJqlCcMLTWp5muCrID+K5UJ6jqD2BFshejCYXniPDbNh73V8w==, + } + engines: { node: ">= 12.0.0" } + cpu: [x64] + os: [darwin] + + lightningcss-freebsd-x64@1.32.0: + resolution: + { + integrity: sha512-JCTigedEksZk3tHTTthnMdVfGf61Fky8Ji2E4YjUTEQX14xiy/lTzXnu1vwiZe3bYe0q+SpsSH/CTeDXK6WHig==, + } + engines: { node: ">= 12.0.0" } + cpu: [x64] + os: [freebsd] + + lightningcss-linux-arm-gnueabihf@1.32.0: + resolution: + { + integrity: sha512-x6rnnpRa2GL0zQOkt6rts3YDPzduLpWvwAF6EMhXFVZXD4tPrBkEFqzGowzCsIWsPjqSK+tyNEODUBXeeVHSkw==, + } + engines: { node: ">= 12.0.0" } + cpu: [arm] + os: [linux] + + lightningcss-linux-arm64-gnu@1.32.0: + resolution: + { + integrity: sha512-0nnMyoyOLRJXfbMOilaSRcLH3Jw5z9HDNGfT/gwCPgaDjnx0i8w7vBzFLFR1f6CMLKF8gVbebmkUN3fa/kQJpQ==, + } + engines: { node: ">= 12.0.0" } + cpu: [arm64] + os: [linux] + + lightningcss-linux-arm64-musl@1.32.0: + resolution: + { + integrity: sha512-UpQkoenr4UJEzgVIYpI80lDFvRmPVg6oqboNHfoH4CQIfNA+HOrZ7Mo7KZP02dC6LjghPQJeBsvXhJod/wnIBg==, + } + engines: { node: ">= 12.0.0" } + cpu: [arm64] + os: [linux] + + lightningcss-linux-x64-gnu@1.32.0: + resolution: + { + integrity: sha512-V7Qr52IhZmdKPVr+Vtw8o+WLsQJYCTd8loIfpDaMRWGUZfBOYEJeyJIkqGIDMZPwPx24pUMfwSxxI8phr/MbOA==, + } + engines: { node: ">= 12.0.0" } + cpu: [x64] + os: [linux] + + lightningcss-linux-x64-musl@1.32.0: + resolution: + { + integrity: sha512-bYcLp+Vb0awsiXg/80uCRezCYHNg1/l3mt0gzHnWV9XP1W5sKa5/TCdGWaR/zBM2PeF/HbsQv/j2URNOiVuxWg==, + } + engines: { node: ">= 12.0.0" } + cpu: [x64] + os: [linux] + + lightningcss-win32-arm64-msvc@1.32.0: + resolution: + { + integrity: sha512-8SbC8BR40pS6baCM8sbtYDSwEVQd4JlFTOlaD3gWGHfThTcABnNDBda6eTZeqbofalIJhFx0qKzgHJmcPTnGdw==, + } + engines: { node: ">= 12.0.0" } + cpu: [arm64] + os: [win32] + + lightningcss-win32-x64-msvc@1.32.0: + resolution: + { + integrity: sha512-Amq9B/SoZYdDi1kFrojnoqPLxYhQ4Wo5XiL8EVJrVsB8ARoC1PWW6VGtT0WKCemjy8aC+louJnjS7U18x3b06Q==, + } + engines: { node: ">= 12.0.0" } + cpu: [x64] + os: [win32] + + lightningcss@1.32.0: + resolution: + { + integrity: sha512-NXYBzinNrblfraPGyrbPoD19C1h9lfI/1mzgWYvXUTe414Gz/X1FD2XBZSZM7rRTrMA8JL3OtAaGifrIKhQ5yQ==, + } + engines: { node: ">= 12.0.0" } + + lilconfig@3.1.3: + resolution: + { + integrity: sha512-/vlFKAoH5Cgt3Ie+JLhRbwOsCQePABiU3tJ1egGvyQ+33R/vcwM2Zl2QR/LzjsBeItPt3oSVXapn+m4nQDvpzw==, + } + engines: { node: ">=14" } + + lines-and-columns@1.2.4: + resolution: + { + integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==, + } + + livekit-client@2.18.3: + resolution: + { + integrity: sha512-A8QDaVPo+Ye35bJFyKe6PjMOtY33dmdRXGKP/3+BG48ynEES3YwFzHbsPHJiScgI4OZouNef3Ew/BPazXKwo8Q==, + } + peerDependencies: + "@types/dom-mediacapture-record": ^1 + + locate-path@5.0.0: + resolution: + { + integrity: sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==, + } + engines: { node: ">=8" } + + locate-path@6.0.0: + resolution: + { + integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==, + } + engines: { node: ">=10" } + + lodash-es@4.18.1: + resolution: + { + integrity: sha512-J8xewKD/Gk22OZbhpOVSwcs60zhd95ESDwezOFuA3/099925PdHJ7OFHNTGtajL3AlZkykD32HykiMo+BIBI8A==, + } + + lodash.debounce@4.0.8: + resolution: + { + integrity: sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==, + } + + lodash.merge@4.6.2: + resolution: + { + integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==, + } + + loglevel@1.9.1: + resolution: + { + integrity: sha512-hP3I3kCrDIMuRwAwHltphhDM1r8i55H33GgqjXbrisuJhF4kRhW1dNuxsRklp4bXl8DSdLaNLuiL4A/LWRfxvg==, + } + engines: { node: ">= 0.6.0" } + + loglevel@1.9.2: + resolution: + { + integrity: sha512-HgMmCqIJSAKqo68l0rS2AanEWfkxaZ5wNiEFb5ggm08lDs9Xl2KxBlX3PTcaD2chBM1gXAYf491/M2Rv8Jwayg==, + } + engines: { node: ">= 0.6.0" } + + loose-envify@1.4.0: + resolution: + { + integrity: sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==, + } + hasBin: true + + loupe@3.2.1: + resolution: + { + integrity: sha512-CdzqowRJCeLU72bHvWqwRBBlLcMEtIvGrlvef74kMnV2AolS9Y8xUv1I0U/MNAWMhBlKIoyuEgoJ0t/bbwHbLQ==, + } + + lower-case@2.0.2: + resolution: + { + integrity: sha512-7fm3l3NAF9WfN6W3JOmf5drwpVqX78JtoGJ3A6W0a6ZnldM41w2fV5D490psKFTpMds8TJse/eHLFFsNHHjHgg==, + } + + lru-cache@10.4.3: + resolution: + { + integrity: sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==, + } + + lru-cache@5.1.1: + resolution: + { + integrity: sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==, + } + + lz-string@1.5.0: + resolution: + { + integrity: sha512-h5bgJWpxJNswbU7qCrV0tIKQCaS3blPDrqKWx+QxzuzL1zGUzij9XCWLrSLsJPu5t+eWA/ycetzYAO5IOMcWAQ==, + } + hasBin: true + + magic-string@0.30.21: + resolution: + { + integrity: sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==, + } + + magic-string@0.30.8: + resolution: + { + integrity: sha512-ISQTe55T2ao7XtlAStud6qwYPZjE4GK1S/BeVPus4jrq6JuOnQ00YKQC581RWhR122W7msZV263KzVeLoqidyQ==, + } + engines: { node: ">=12" } + + magicast@0.5.2: + resolution: + { + integrity: sha512-E3ZJh4J3S9KfwdjZhe2afj6R9lGIN5Pher1pF39UGrXRqq/VDaGVIGN13BjHd2u8B61hArAGOnso7nBOouW3TQ==, + } + + make-dir@4.0.0: + resolution: + { + integrity: sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==, + } + engines: { node: ">=10" } + + matcher-collection@2.0.1: + resolution: + { + integrity: sha512-daE62nS2ZQsDg9raM0IlZzLmI2u+7ZapXBwdoeBUKAYERPDDIc0qNqA8E0Rp2D+gspKR7BgIFP52GeujaGXWeQ==, + } + engines: { node: 6.* || 8.* || >= 10.* } + + math-intrinsics@1.1.0: + resolution: + { + integrity: sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==, + } + engines: { node: ">= 0.4" } + + matrix-events-sdk@0.0.1: + resolution: + { + integrity: sha512-1QEOsXO+bhyCroIe2/A5OwaxHvBm7EsSQ46DEDn8RBIfQwN5HWBpFvyWWR4QY0KHPPnnJdI99wgRiAl7Ad5qaA==, + } + + matrix-js-sdk@https://codeload.github.com/matrix-org/matrix-js-sdk/tar.gz/ca5655bced1cbb215ac1c18e179384a069d98b0a: + resolution: + { + tarball: https://codeload.github.com/matrix-org/matrix-js-sdk/tar.gz/ca5655bced1cbb215ac1c18e179384a069d98b0a, + } + version: 41.3.0 + engines: { node: ">=22.0.0" } + + matrix-widget-api@1.17.0: + resolution: + { + integrity: sha512-5FHoo3iEP3Bdlv5jsYPWOqj+pGdFQNLWnJLiB0V7Ygne7bb+Gsj3ibyFyHWC6BVw+Z+tSW4ljHpO17I9TwStwQ==, + } + + md5.js@1.3.5: + resolution: + { + integrity: sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg==, + } + + merge2@1.4.1: + resolution: + { + integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==, + } + engines: { node: ">= 8" } + + micromatch@4.0.8: + resolution: + { + integrity: sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==, + } + engines: { node: ">=8.6" } + + miller-rabin@4.0.1: + resolution: + { + integrity: sha512-115fLhvZVqWwHPbClyntxEVfVDfl9DLLTuJvq3g2O/Oxi8AiNouAHvDSzHS0viUJc+V5vm3eq91Xwqn9dp4jRA==, + } + hasBin: true + + mime-db@1.52.0: + resolution: + { + integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==, + } + engines: { node: ">= 0.6" } + + mime-types@2.1.35: + resolution: + { + integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==, + } + engines: { node: ">= 0.6" } + + min-indent@1.0.1: + resolution: + { + integrity: sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==, + } + engines: { node: ">=4" } + + minimalistic-assert@1.0.1: + resolution: + { + integrity: sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==, + } + + minimalistic-crypto-utils@1.0.1: + resolution: + { + integrity: sha512-JIYlbt6g8i5jKfJ3xz7rF0LXmv2TkDxBLUkiBeZ7bAx4GnnNMr8xFpGnOxn6GhTEHx3SjRrZEoU+j04prX1ktg==, + } + + minimatch@10.2.5: + resolution: + { + integrity: sha512-MULkVLfKGYDFYejP07QOurDLLQpcjk7Fw+7jXS2R2czRQzR56yHRveU5NDJEOviH+hETZKSkIk5c+T23GjFUMg==, + } + engines: { node: 18 || 20 || >=22 } + + minimist@1.2.8: + resolution: + { + integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==, + } + + minipass@7.1.3: + resolution: + { + integrity: sha512-tEBHqDnIoM/1rXME1zgka9g6Q2lcoCkxHLuc7ODJ5BxbP5d4c2Z5cGgtXAku59200Cx7diuHTOYfSBD8n6mm8A==, + } + engines: { node: ">=16 || 14 >=14.17" } + + mktemp@2.0.2: + resolution: + { + integrity: sha512-Q9wJ/xhzeD9Wua1MwDN2v3ah3HENsUVSlzzL9Qw149cL9hHZkXtQGl3Eq36BbdLV+/qUwaP1WtJQ+H/+Oxso8g==, + } + engines: { node: 20 || 22 || 24 } + + ms@2.0.0: + resolution: + { + integrity: sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==, + } + + ms@2.1.3: + resolution: + { + integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==, + } + + nanoid@3.3.11: + resolution: + { + integrity: sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==, + } + engines: { node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1 } + hasBin: true + + natural-compare@1.4.0: + resolution: + { + integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==, + } + + no-case@3.0.4: + resolution: + { + integrity: sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg==, + } + + node-addon-api@7.1.1: + resolution: + { + integrity: sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ==, + } + + node-exports-info@1.6.0: + resolution: + { + integrity: sha512-pyFS63ptit/P5WqUkt+UUfe+4oevH+bFeIiPPdfb0pFeYEu/1ELnJu5l+5EcTKYL5M7zaAa7S8ddywgXypqKCw==, + } + engines: { node: ">= 0.4" } + + node-fetch@2.7.0: + resolution: + { + integrity: sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==, + } + engines: { node: 4.x || >=6.0.0 } + peerDependencies: + encoding: ^0.1.0 + peerDependenciesMeta: + encoding: + optional: true + + node-html-parser@5.4.2: + resolution: + { + integrity: sha512-RaBPP3+51hPne/OolXxcz89iYvQvKOydaqoePpOgXcrOKZhjVIzmpKZz+Hd/RBO2/zN2q6CNJhQzucVz+u3Jyw==, + } + + node-releases@2.0.37: + resolution: + { + integrity: sha512-1h5gKZCF+pO/o3Iqt5Jp7wc9rH3eJJ0+nh/CIoiRwjRxde/hAHyLPXYN4V3CqKAbiZPSeJFSWHmJsbkicta0Eg==, + } + + node-stdlib-browser@1.3.1: + resolution: + { + integrity: sha512-X75ZN8DCLftGM5iKwoYLA3rjnrAEs97MkzvSd4q2746Tgpg8b8XWiBGiBG4ZpgcAqBgtgPHTiAc8ZMCvZuikDw==, + } + engines: { node: ">=10" } + + normalize-package-data@2.5.0: + resolution: + { + integrity: sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==, + } + + normalize-path@3.0.0: + resolution: + { + integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==, + } + engines: { node: ">=0.10.0" } + + normalize.css@8.0.1: + resolution: + { + integrity: sha512-qizSNPO93t1YUuUhP22btGOo3chcvDFqFaj2TRybP0DMxkHOCTYwp3n34fel4a31ORXy4m1Xq0Gyqpb5m33qIg==, + } + + now-and-later@3.0.0: + resolution: + { + integrity: sha512-pGO4pzSdaxhWTGkfSfHx3hVzJVslFPwBp2Myq9MYN/ChfJZF87ochMAXnvz6/58RJSf5ik2q9tXprBBrk2cpcg==, + } + engines: { node: ">= 10.13.0" } + + nth-check@2.1.1: + resolution: + { + integrity: sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==, + } + + nwsapi@2.2.23: + resolution: + { + integrity: sha512-7wfH4sLbt4M0gCDzGE6vzQBo0bfTKjU7Sfpqy/7gs1qBfYz2vEJH6vXcBKpO3+6Yu1telwd0t9HpyOoLEQQbIQ==, + } + + object-assign@4.1.1: + resolution: + { + integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==, + } + engines: { node: ">=0.10.0" } + + object-deep-merge@2.0.0: + resolution: + { + integrity: sha512-3DC3UMpeffLTHiuXSy/UG4NOIYTLlY9u3V82+djSCLYClWobZiS4ivYzpIUWrRY/nfsJ8cWsKyG3QfyLePmhvg==, + } + + object-inspect@1.13.4: + resolution: + { + integrity: sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==, + } + engines: { node: ">= 0.4" } + + object-is@1.1.6: + resolution: + { + integrity: sha512-F8cZ+KfGlSGi09lJT7/Nd6KJZ9ygtvYC0/UYYLI9nmQKLMnydpB9yvbv9K1uSkEu7FU9vYPmVwLg328tX+ot3Q==, + } + engines: { node: ">= 0.4" } + + object-keys@1.1.1: + resolution: + { + integrity: sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==, + } + engines: { node: ">= 0.4" } + + object.assign@4.1.7: + resolution: + { + integrity: sha512-nK28WOo+QIjBkDduTINE4JkF/UJJKyf2EJxvJKfblDpyg0Q+pkOHNTL0Qwy6NP6FhE/EnzV73BxxqcJaXY9anw==, + } + engines: { node: ">= 0.4" } + + object.entries@1.1.9: + resolution: + { + integrity: sha512-8u/hfXFRBD1O0hPUjioLhoWFHRmt6tKA4/vZPyckBr18l1KE9uHrFaFaUi8MDRTpi4uak2goyPTSNJLXX2k2Hw==, + } + engines: { node: ">= 0.4" } + + object.fromentries@2.0.8: + resolution: + { + integrity: sha512-k6E21FzySsSK5a21KRADBd/NGneRegFO5pLHfdQLpRDETUNJueLXs3WCzyQ3tFRDYgbq3KHGXfTbi2bs8WQ6rQ==, + } + engines: { node: ">= 0.4" } + + object.groupby@1.0.3: + resolution: + { + integrity: sha512-+Lhy3TQTuzXI5hevh8sBGqbmurHbbIjAi0Z4S63nthVLmLxfbj4T54a4CfZrXIrt9iP4mVAPYMo/v99taj3wjQ==, + } + engines: { node: ">= 0.4" } + + object.values@1.2.1: + resolution: + { + integrity: sha512-gXah6aZrcUxjWg2zR2MwouP2eHlCBzdV4pygudehaKXSGW4v2AsRQUK+lwwXhii6KFZcunEnmSUoYp5CXibxtA==, + } + engines: { node: ">= 0.4" } + + observable-hooks@4.2.4: + resolution: + { + integrity: sha512-FdTQgyw1h5bG/QHCBIqctdBSnv9VARJCEilgpV6L2qlw1yeLqFIwPm4U15dMtl5kDmNN0hSt+Nl6iYbLFwEcQA==, + } + peerDependencies: + react: ">=16.8.0" + react-dom: ">=16.8.0" + rxjs: ">=6.0.0" + + obug@2.1.1: + resolution: + { + integrity: sha512-uTqF9MuPraAQ+IsnPf366RG4cP9RtUi7MLO1N3KEc+wb0a6yKpeL0lmk2IB1jY5KHPAlTc6T/JRdC/YqxHNwkQ==, + } + + oidc-client-ts@3.5.0: + resolution: + { + integrity: sha512-l2q8l9CTCTOlbX+AnK4p3M+4CEpKpyQhle6blQkdFhm0IsBqsxm15bYaSa11G7pWdsYr6epdsRZxJpCyCRbT8A==, + } + engines: { node: ">=18" } + + once@1.4.0: + resolution: + { + integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==, + } + + open@10.2.0: + resolution: + { + integrity: sha512-YgBpdJHPyQ2UE5x+hlSXcnejzAvD0b22U2OuAP+8OnlJT+PjWPxtgmGqKKc+RgTM63U9gN0YzrYc71R2WT/hTA==, + } + engines: { node: ">=18" } + + optionator@0.9.4: + resolution: + { + integrity: sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==, + } + engines: { node: ">= 0.8.0" } + + os-browserify@0.3.0: + resolution: + { + integrity: sha512-gjcpUc3clBf9+210TRaDWbf+rZZZEshZ+DlXMRCeAjp0xhTrnQsKHypIy1J3d5hKdUzj69t708EHtU8P6bUn0A==, + } + + own-keys@1.0.1: + resolution: + { + integrity: sha512-qFOyK5PjiWZd+QQIh+1jhdb9LpxTF0qs7Pm8o5QHYZ0M3vKqSqzsZaEB6oWlxZ+q2sJBMI/Ktgd2N5ZwQoRHfg==, + } + engines: { node: ">= 0.4" } + + oxc-resolver@11.19.1: + resolution: + { + integrity: sha512-qE/CIg/spwrTBFt5aKmwe3ifeDdLfA2NESN30E42X/lII5ClF8V7Wt6WIJhcGZjp0/Q+nQ+9vgxGk//xZNX2hg==, + } + + p-limit@2.3.0: + resolution: + { + integrity: sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==, + } + engines: { node: ">=6" } + + p-limit@3.1.0: + resolution: + { + integrity: sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==, + } + engines: { node: ">=10" } + + p-locate@4.1.0: + resolution: + { + integrity: sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==, + } + engines: { node: ">=8" } + + p-locate@5.0.0: + resolution: + { + integrity: sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==, + } + engines: { node: ">=10" } + + p-retry@8.0.0: + resolution: + { + integrity: sha512-kFVqH1HxOHp8LupNsOys7bSV09VYTRLxarH/mokO4Rqhk6wGi70E0jh4VzvVGXfEVNggHoHLAMWsQqHyU1Ey9A==, + } + engines: { node: ">=22" } + + p-try@2.2.0: + resolution: + { + integrity: sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==, + } + engines: { node: ">=6" } + + package-json-from-dist@1.0.1: + resolution: + { + integrity: sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==, + } + + pako@1.0.11: + resolution: + { + integrity: sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==, + } + + pako@2.1.0: + resolution: + { + integrity: sha512-w+eufiZ1WuJYgPXbV/PO3NCMEc3xqylkKHzp8bxp1uW4qaSNQUkwmLLEc3kKsfz8lpV1F8Ht3U1Cm+9Srog2ug==, + } + + param-case@3.0.4: + resolution: + { + integrity: sha512-RXlj7zCYokReqWpOPH9oYivUzLYZ5vAPIfEmCTNViosC78F8F0H9y7T7gG2M39ymgutxF5gcFEsyZQSph9Bp3A==, + } + + parent-module@1.0.1: + resolution: + { + integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==, + } + engines: { node: ">=6" } + + parse-asn1@5.1.9: + resolution: + { + integrity: sha512-fIYNuZ/HastSb80baGOuPRo1O9cf4baWw5WsAp7dBuUzeTD/BoaG8sVTdlPFksBE2lF21dN+A1AnrpIjSWqHHg==, + } + engines: { node: ">= 0.10" } + + parse-imports-exports@0.2.4: + resolution: + { + integrity: sha512-4s6vd6dx1AotCx/RCI2m7t7GCh5bDRUtGNvRfHSP2wbBQdMi67pPe7mtzmgwcaQ8VKK/6IB7Glfyu3qdZJPybQ==, + } + + parse-json@5.2.0: + resolution: + { + integrity: sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==, + } + engines: { node: ">=8" } + + parse-statements@1.0.11: + resolution: + { + integrity: sha512-HlsyYdMBnbPQ9Jr/VgJ1YF4scnldvJpJxCVx6KgqPL4dxppsWrJHCIIxQXMJrqGnsRkNPATbeMJ8Yxu7JMsYcA==, + } + + parse5-htmlparser2-tree-adapter@7.1.0: + resolution: + { + integrity: sha512-ruw5xyKs6lrpo9x9rCZqZZnIUntICjQAd0Wsmp396Ul9lN/h+ifgVV1x1gZHi8euej6wTfpqX8j+BFQxF0NS/g==, + } + + parse5-parser-stream@7.1.2: + resolution: + { + integrity: sha512-JyeQc9iwFLn5TbvvqACIF/VXG6abODeB3Fwmv/TGdLk2LfbWkaySGY72at4+Ty7EkPZj854u4CrICqNk2qIbow==, + } + + parse5@7.3.0: + resolution: + { + integrity: sha512-IInvU7fabl34qmi9gY8XOVxhYyMyuH2xUNpb2q8/Y+7552KlejkRvqvD19nMoUW/uQGGbqNpA6Tufu5FL5BZgw==, + } + + pascal-case@3.1.2: + resolution: + { + integrity: sha512-uWlGT3YSnK9x3BQJaOdcZwrnV6hPpd8jFH1/ucpiLRPh/2zCVJKS19E4GvYHvaCcACn3foXZ0cLB9Wrx1KGe5g==, + } + + path-browserify@1.0.1: + resolution: + { + integrity: sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g==, + } + + path-exists@4.0.0: + resolution: + { + integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==, + } + engines: { node: ">=8" } + + path-key@3.1.1: + resolution: + { + integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==, + } + engines: { node: ">=8" } + + path-parse@1.0.7: + resolution: + { + integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==, + } + + path-posix@1.0.0: + resolution: + { + integrity: sha512-1gJ0WpNIiYcQydgg3Ed8KzvIqTsDpNwq+cjBCssvBtuTWjEqY1AW+i+OepiEMqDCzyro9B2sLAe4RBPajMYFiA==, + } + + path-scurry@1.11.1: + resolution: + { + integrity: sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==, + } + engines: { node: ">=16 || 14 >=14.18" } + + path-type@4.0.0: + resolution: + { + integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==, + } + engines: { node: ">=8" } + + pathe@0.2.0: + resolution: + { + integrity: sha512-sTitTPYnn23esFR3RlqYBWn4c45WGeLcsKzQiUpXJAyfcWkolvlYpV8FLo7JishK946oQwMFUCHXQ9AjGPKExw==, + } + + pathe@2.0.3: + resolution: + { + integrity: sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==, + } + + pathval@2.0.1: + resolution: + { + integrity: sha512-//nshmD55c46FuFw26xV/xFAaB5HF9Xdap7HJBBnrKdAd6/GxDBaNA1870O79+9ueg61cZLSVc+OaFlfmObYVQ==, + } + engines: { node: ">= 14.16" } + + pbkdf2@3.1.5: + resolution: + { + integrity: sha512-Q3CG/cYvCO1ye4QKkuH7EXxs3VC/rI1/trd+qX2+PolbaKG0H+bgcZzrTt96mMyRtejk+JMCiLUn3y29W8qmFQ==, + } + engines: { node: ">= 0.10" } + + picocolors@1.1.1: + resolution: + { + integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==, + } + + picomatch@2.3.2: + resolution: + { + integrity: sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA==, + } + engines: { node: ">=8.6" } + + picomatch@4.0.4: + resolution: + { + integrity: sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==, + } + engines: { node: ">=12" } + + pkg-dir@5.0.0: + resolution: + { + integrity: sha512-NPE8TDbzl/3YQYY7CSS228s3g2ollTFnc+Qi3tqmqJp9Vg2ovUpixcJEo2HJScN2Ez+kEaal6y70c0ehqJBJeA==, + } + engines: { node: ">=10" } + + playwright-core@1.59.1: + resolution: + { + integrity: sha512-HBV/RJg81z5BiiZ9yPzIiClYV/QMsDCKUyogwH9p3MCP6IYjUFu/MActgYAvK0oWyV9NlwM3GLBjADyWgydVyg==, + } + engines: { node: ">=18" } + hasBin: true + + playwright@1.59.1: + resolution: + { + integrity: sha512-C8oWjPR3F81yljW9o5OxcWzfh6avkVwDD2VYdwIGqTkl+OGFISgypqzfu7dOe4QNLL2aqcWBmI3PMtLIK233lw==, + } + engines: { node: ">=18" } + hasBin: true + + pluralize@8.0.0: + resolution: + { + integrity: sha512-Nc3IT5yHzflTfbjgqWcCPpo7DaKy4FnpB0l/zCAW0Tc7jxAiuqSxHasntB3D7887LSrA93kDJ9IXovxJYxyLCA==, + } + engines: { node: ">=4" } + + pngjs@5.0.0: + resolution: + { + integrity: sha512-40QW5YalBNfQo5yRYmiw7Yz6TKKVr3h6970B2YE+3fQpsWcrbj1PzJgxeJ19DRQjhMbKPIuMY8rFaXc8moolVw==, + } + engines: { node: ">=10.13.0" } + + possible-typed-array-names@1.1.0: + resolution: + { + integrity: sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg==, + } + engines: { node: ">= 0.4" } + + postcss-attribute-case-insensitive@7.0.1: + resolution: + { + integrity: sha512-Uai+SupNSqzlschRyNx3kbCTWgY/2hcwtHEI/ej2LJWc9JJ77qKgGptd8DHwY1mXtZ7Aoh4z4yxfwMBue9eNgw==, + } + engines: { node: ">=18" } + peerDependencies: + postcss: ^8.4 + + postcss-clamp@4.1.0: + resolution: + { + integrity: sha512-ry4b1Llo/9zz+PKC+030KUnPITTJAHeOwjfAyyB60eT0AorGLdzp52s31OsPRHRf8NchkgFoG2y6fCfn1IV1Ow==, + } + engines: { node: ">=7.6.0" } + peerDependencies: + postcss: ^8.4.6 + + postcss-color-functional-notation@7.0.12: + resolution: + { + integrity: sha512-TLCW9fN5kvO/u38/uesdpbx3e8AkTYhMvDZYa9JpmImWuTE99bDQ7GU7hdOADIZsiI9/zuxfAJxny/khknp1Zw==, + } + engines: { node: ">=18" } + peerDependencies: + postcss: ^8.4 + + postcss-color-hex-alpha@10.0.0: + resolution: + { + integrity: sha512-1kervM2cnlgPs2a8Vt/Qbe5cQ++N7rkYo/2rz2BkqJZIHQwaVuJgQH38REHrAi4uM0b1fqxMkWYmese94iMp3w==, + } + engines: { node: ">=18" } + peerDependencies: + postcss: ^8.4 + + postcss-color-rebeccapurple@10.0.0: + resolution: + { + integrity: sha512-JFta737jSP+hdAIEhk1Vs0q0YF5P8fFcj+09pweS8ktuGuZ8pPlykHsk6mPxZ8awDl4TrcxUqJo9l1IhVr/OjQ==, + } + engines: { node: ">=18" } + peerDependencies: + postcss: ^8.4 + + postcss-custom-media@11.0.6: + resolution: + { + integrity: sha512-C4lD4b7mUIw+RZhtY7qUbf4eADmb7Ey8BFA2px9jUbwg7pjTZDl4KY4bvlUV+/vXQvzQRfiGEVJyAbtOsCMInw==, + } + engines: { node: ">=18" } + peerDependencies: + postcss: ^8.4 + + postcss-custom-properties@14.0.6: + resolution: + { + integrity: sha512-fTYSp3xuk4BUeVhxCSJdIPhDLpJfNakZKoiTDx7yRGCdlZrSJR7mWKVOBS4sBF+5poPQFMj2YdXx1VHItBGihQ==, + } + engines: { node: ">=18" } + peerDependencies: + postcss: ^8.4 + + postcss-custom-selectors@8.0.5: + resolution: + { + integrity: sha512-9PGmckHQswiB2usSO6XMSswO2yFWVoCAuih1yl9FVcwkscLjRKjwsjM3t+NIWpSU2Jx3eOiK2+t4vVTQaoCHHg==, + } + engines: { node: ">=18" } + peerDependencies: + postcss: ^8.4 + + postcss-dir-pseudo-class@9.0.1: + resolution: + { + integrity: sha512-tRBEK0MHYvcMUrAuYMEOa0zg9APqirBcgzi6P21OhxtJyJADo/SWBwY1CAwEohQ/6HDaa9jCjLRG7K3PVQYHEA==, + } + engines: { node: ">=18" } + peerDependencies: + postcss: ^8.4 + + postcss-double-position-gradients@6.0.4: + resolution: + { + integrity: sha512-m6IKmxo7FxSP5nF2l63QbCC3r+bWpFUWmZXZf096WxG0m7Vl1Q1+ruFOhpdDRmKrRS+S3Jtk+TVk/7z0+BVK6g==, + } + engines: { node: ">=18" } + peerDependencies: + postcss: ^8.4 + + postcss-focus-visible@10.0.1: + resolution: + { + integrity: sha512-U58wyjS/I1GZgjRok33aE8juW9qQgQUNwTSdxQGuShHzwuYdcklnvK/+qOWX1Q9kr7ysbraQ6ht6r+udansalA==, + } + engines: { node: ">=18" } + peerDependencies: + postcss: ^8.4 + + postcss-focus-within@9.0.1: + resolution: + { + integrity: sha512-fzNUyS1yOYa7mOjpci/bR+u+ESvdar6hk8XNK/TRR0fiGTp2QT5N+ducP0n3rfH/m9I7H/EQU6lsa2BrgxkEjw==, + } + engines: { node: ">=18" } + peerDependencies: + postcss: ^8.4 + + postcss-font-variant@5.0.0: + resolution: + { + integrity: sha512-1fmkBaCALD72CK2a9i468mA/+tr9/1cBxRRMXOUaZqO43oWPR5imcyPjXwuv7PXbCid4ndlP5zWhidQVVa3hmA==, + } + peerDependencies: + postcss: ^8.1.0 + + postcss-gap-properties@6.0.0: + resolution: + { + integrity: sha512-Om0WPjEwiM9Ru+VhfEDPZJAKWUd0mV1HmNXqp2C29z80aQ2uP9UVhLc7e3aYMIor/S5cVhoPgYQ7RtfeZpYTRw==, + } + engines: { node: ">=18" } + peerDependencies: + postcss: ^8.4 + + postcss-image-set-function@7.0.0: + resolution: + { + integrity: sha512-QL7W7QNlZuzOwBTeXEmbVckNt1FSmhQtbMRvGGqqU4Nf4xk6KUEQhAoWuMzwbSv5jxiRiSZ5Tv7eiDB9U87znA==, + } + engines: { node: ">=18" } + peerDependencies: + postcss: ^8.4 + + postcss-lab-function@7.0.12: + resolution: + { + integrity: sha512-tUcyRk1ZTPec3OuKFsqtRzW2Go5lehW29XA21lZ65XmzQkz43VY2tyWEC202F7W3mILOjw0voOiuxRGTsN+J9w==, + } + engines: { node: ">=18" } + peerDependencies: + postcss: ^8.4 + + postcss-logical@8.1.0: + resolution: + { + integrity: sha512-pL1hXFQ2fEXNKiNiAgtfA005T9FBxky5zkX6s4GZM2D8RkVgRqz3f4g1JUoq925zXv495qk8UNldDwh8uGEDoA==, + } + engines: { node: ">=18" } + peerDependencies: + postcss: ^8.4 + + postcss-nesting@13.0.2: + resolution: + { + integrity: sha512-1YCI290TX+VP0U/K/aFxzHzQWHWURL+CtHMSbex1lCdpXD1SoR2sYuxDu5aNI9lPoXpKTCggFZiDJbwylU0LEQ==, + } + engines: { node: ">=18" } + peerDependencies: + postcss: ^8.4 + + postcss-opacity-percentage@3.0.0: + resolution: + { + integrity: sha512-K6HGVzyxUxd/VgZdX04DCtdwWJ4NGLG212US4/LA1TLAbHgmAsTWVR86o+gGIbFtnTkfOpb9sCRBx8K7HO66qQ==, + } + engines: { node: ">=18" } + peerDependencies: + postcss: ^8.4 + + postcss-overflow-shorthand@6.0.0: + resolution: + { + integrity: sha512-BdDl/AbVkDjoTofzDQnwDdm/Ym6oS9KgmO7Gr+LHYjNWJ6ExORe4+3pcLQsLA9gIROMkiGVjjwZNoL/mpXHd5Q==, + } + engines: { node: ">=18" } + peerDependencies: + postcss: ^8.4 + + postcss-page-break@3.0.4: + resolution: + { + integrity: sha512-1JGu8oCjVXLa9q9rFTo4MbeeA5FMe00/9C7lN4va606Rdb+HkxXtXsmEDrIraQ11fGz/WvKWa8gMuCKkrXpTsQ==, + } + peerDependencies: + postcss: ^8 + + postcss-place@10.0.0: + resolution: + { + integrity: sha512-5EBrMzat2pPAxQNWYavwAfoKfYcTADJ8AXGVPcUZ2UkNloUTWzJQExgrzrDkh3EKzmAx1evfTAzF9I8NGcc+qw==, + } + engines: { node: ">=18" } + peerDependencies: + postcss: ^8.4 + + postcss-preset-env@10.6.1: + resolution: + { + integrity: sha512-yrk74d9EvY+W7+lO9Aj1QmjWY9q5NsKjK2V9drkOPZB/X6KZ0B3igKsHUYakb7oYVhnioWypQX3xGuePf89f3g==, + } + engines: { node: ">=18" } + peerDependencies: + postcss: ^8.4 + + postcss-pseudo-class-any-link@10.0.1: + resolution: + { + integrity: sha512-3el9rXlBOqTFaMFkWDOkHUTQekFIYnaQY55Rsp8As8QQkpiSgIYEcF/6Ond93oHiDsGb4kad8zjt+NPlOC1H0Q==, + } + engines: { node: ">=18" } + peerDependencies: + postcss: ^8.4 + + postcss-replace-overflow-wrap@4.0.0: + resolution: + { + integrity: sha512-KmF7SBPphT4gPPcKZc7aDkweHiKEEO8cla/GjcBK+ckKxiZslIu3C4GCRW3DNfL0o7yW7kMQu9xlZ1kXRXLXtw==, + } + peerDependencies: + postcss: ^8.0.3 + + postcss-selector-not@8.0.1: + resolution: + { + integrity: sha512-kmVy/5PYVb2UOhy0+LqUYAhKj7DUGDpSWa5LZqlkWJaaAV+dxxsOG3+St0yNLu6vsKD7Dmqx+nWQt0iil89+WA==, + } + engines: { node: ">=18" } + peerDependencies: + postcss: ^8.4 + + postcss-selector-parser@7.1.1: + resolution: + { + integrity: sha512-orRsuYpJVw8LdAwqqLykBj9ecS5/cRHlI5+nvTo8LcCKmzDmqVORXtOIYEEQuL9D4BxtA1lm5isAqzQZCoQ6Eg==, + } + engines: { node: ">=4" } + + postcss-value-parser@4.2.0: + resolution: + { + integrity: sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==, + } + + postcss@8.5.10: + resolution: + { + integrity: sha512-pMMHxBOZKFU6HgAZ4eyGnwXF/EvPGGqUr0MnZ5+99485wwW41kW91A4LOGxSHhgugZmSChL5AlElNdwlNgcnLQ==, + } + engines: { node: ^10 || ^12 || >=14 } + + posthog-js@1.160.3: + resolution: + { + integrity: sha512-mGvxOIlWPtdPx8EI0MQ81wNKlnH2K0n4RqwQOl044b34BCKiFVzZ7Hc7geMuZNaRAvCi5/5zyGeWHcAYZQxiMQ==, + } + + preact@10.29.1: + resolution: + { + integrity: sha512-gQCLc/vWroE8lIpleXtdJhTFDogTdZG9AjMUpVkDf2iTCNwYNWA+u16dL41TqUDJO4gm2IgrcMv3uTpjd4Pwmg==, + } + + prelude-ls@1.2.1: + resolution: + { + integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==, + } + engines: { node: ">= 0.8.0" } + + prettier@3.8.3: + resolution: + { + integrity: sha512-7igPTM53cGHMW8xWuVTydi2KO233VFiTNyF5hLJqpilHfmn8C8gPf+PS7dUT64YcXFbiMGZxS9pCSxL/Dxm/Jw==, + } + engines: { node: ">=14" } + hasBin: true + + pretty-format@27.5.1: + resolution: + { + integrity: sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==, + } + engines: { node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0 } + + process-nextick-args@2.0.1: + resolution: + { + integrity: sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==, + } + + process@0.11.10: + resolution: + { + integrity: sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==, + } + engines: { node: ">= 0.6.0" } + + progress@2.0.3: + resolution: + { + integrity: sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==, + } + engines: { node: ">=0.4.0" } + + promise-map-series@0.3.0: + resolution: + { + integrity: sha512-3npG2NGhTc8BWBolLLf8l/92OxMGaRLbqvIh9wjCHhDXNvk4zsxaTaCpiCunW09qWPrN2zeNSNwRLVBrQQtutA==, + } + engines: { node: 10.* || >= 12.* } + + prompts@2.4.2: + resolution: + { + integrity: sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==, + } + engines: { node: ">= 6" } + + prop-types@15.8.1: + resolution: + { + integrity: sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==, + } + + proxy-from-env@1.1.0: + resolution: + { + integrity: sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==, + } + + public-encrypt@4.0.3: + resolution: + { + integrity: sha512-zVpa8oKZSz5bTMTFClc1fQOnyyEzpl5ozpi1B5YcvBrdohMjH2rfsBtyXcuNuwjsDIXmBYlF2N5FlJYhR29t8Q==, + } + + punycode@1.4.1: + resolution: + { + integrity: sha512-jmYNElW7yvO7TV33CjSmvSiE2yco3bV2czu/OzDKdMNVZQWfxCblURLhf+47syQRBntjfLdd/H0egrzIG+oaFQ==, + } + + punycode@2.3.1: + resolution: + { + integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==, + } + engines: { node: ">=6" } + + qrcode@1.5.4: + resolution: + { + integrity: sha512-1ca71Zgiu6ORjHqFBDpnSMTR2ReToX4l1Au1VFLyVeBTFavzQnv5JxMFr3ukHVKpSrSA2MCk0lNJSykjUfz7Zg==, + } + engines: { node: ">=10.13.0" } + hasBin: true + + qs@6.15.1: + resolution: + { + integrity: sha512-6YHEFRL9mfgcAvql/XhwTvf5jKcOiiupt2FiJxHkiX1z4j7WL8J/jRHYLluORvc1XxB5rV20KoeK00gVJamspg==, + } + engines: { node: ">=0.6" } + + querystring-es3@0.2.1: + resolution: + { + integrity: sha512-773xhDQnZBMFobEiztv8LIl70ch5MSF/jUQVlhwFyBILqq96anmoctVIYz+ZRp0qbCKATTn6ev02M3r7Ga5vqA==, + } + engines: { node: ">=0.4.x" } + + queue-microtask@1.2.3: + resolution: + { + integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==, + } + + quick-temp@0.1.9: + resolution: + { + integrity: sha512-yI0h7tIhKVObn03kD+Ln9JFi4OljD28lfaOsTdfpTR0xzrhGOod+q66CjGafUqYX2juUfT9oHIGrTBBo22mkRA==, + } + + randombytes@2.1.0: + resolution: + { + integrity: sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==, + } + + randomfill@1.0.4: + resolution: + { + integrity: sha512-87lcbR8+MhcWcUiQ+9e+Rwx8MyR2P7qnt15ynUlbm3TU/fjbgz4GsvfSUDTemtCCtVCqb4ZcEFlyPNTh9bBTLw==, + } + + react-docgen-typescript@2.4.0: + resolution: + { + integrity: sha512-ZtAp5XTO5HRzQctjPU0ybY0RRCQO19X/8fxn3w7y2VVTUbGHDKULPTL4ky3vB05euSgG5NpALhEhDPvQ56wvXg==, + } + peerDependencies: + typescript: ">= 4.3.x" + + react-docgen@8.0.3: + resolution: + { + integrity: sha512-aEZ9qP+/M+58x2qgfSFEWH1BxLyHe5+qkLNJOZQb5iGS017jpbRnoKhNRrXPeA6RfBrZO5wZrT9DMC1UqE1f1w==, + } + engines: { node: ^20.9.0 || >=22 } + + react-dom@19.2.5: + resolution: + { + integrity: sha512-J5bAZz+DXMMwW/wV3xzKke59Af6CHY7G4uYLN1OvBcKEsWOs4pQExj86BBKamxl/Ik5bx9whOrvBlSDfWzgSag==, + } + peerDependencies: + react: ^19.2.5 + + react-i18next@16.6.6: + resolution: + { + integrity: sha512-ZgL2HUoW34UKUkOV7uSQFE1CDnRPD+tCR3ywSuWH7u2iapnz86U8Bi3Vrs620qNDzCf1F47NxglCEkchCTDOHw==, + } + peerDependencies: + i18next: ">= 25.10.9" + react: ">= 16.8.0" + react-dom: "*" + react-native: "*" + typescript: ^5 || ^6 + peerDependenciesMeta: + react-dom: + optional: true + react-native: + optional: true + typescript: + optional: true + + react-is@16.13.1: + resolution: + { + integrity: sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==, + } + + react-is@17.0.2: + resolution: + { + integrity: sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==, + } + + react-refresh@0.17.0: + resolution: + { + integrity: sha512-z6F7K9bV85EfseRCp2bzrpyQ0Gkw1uLoCel9XBVWPg/TjRj94SkJzUTGfOa4bs7iJvBWtQG0Wq7wnI0syw3EBQ==, + } + engines: { node: ">=0.10.0" } + + react-remove-scroll-bar@2.3.8: + resolution: + { + integrity: sha512-9r+yi9+mgU33AKcj6IbT9oRCO78WriSj6t/cF8DWBZJ9aOGPOTEDvdUDz1FwKim7QXWwmHqtdHnRJfhAxEG46Q==, + } + engines: { node: ">=10" } + peerDependencies: + "@types/react": "*" + react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 + peerDependenciesMeta: + "@types/react": + optional: true + + react-remove-scroll@2.7.2: + resolution: + { + integrity: sha512-Iqb9NjCCTt6Hf+vOdNIZGdTiH1QSqr27H/Ek9sv/a97gfueI/5h1s3yRi1nngzMUaOOToin5dI1dXKdXiF+u0Q==, + } + engines: { node: ">=10" } + peerDependencies: + "@types/react": "*" + react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc + peerDependenciesMeta: + "@types/react": + optional: true + + react-router-dom@7.14.1: + resolution: + { + integrity: sha512-ZkrQuwwhGibjQLqH1eCdyiZyLWglPxzxdl5tgwgKEyCSGC76vmAjleGocRe3J/MLfzMUIKwaFJWpFVJhK3d2xA==, + } + engines: { node: ">=20.0.0" } + peerDependencies: + react: ">=18" + react-dom: ">=18" + + react-router@7.14.1: + resolution: + { + integrity: sha512-5BCvFskyAAVumqhEKh/iPhLOIkfxcEUz8WqFIARCkMg8hZZzDYX9CtwxXA0e+qT8zAxmMC0x3Ckb9iMONwc5jg==, + } + engines: { node: ">=20.0.0" } + peerDependencies: + react: ">=18" + react-dom: ">=18" + peerDependenciesMeta: + react-dom: + optional: true + + react-style-singleton@2.2.3: + resolution: + { + integrity: sha512-b6jSvxvVnyptAiLjbkWLE/lOnR4lfTtDAl+eUC7RZy+QQWc6wRzIV2CE6xBuMmDxc2qIihtDCZD5NPOFl7fRBQ==, + } + engines: { node: ">=10" } + peerDependencies: + "@types/react": "*" + react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc + peerDependenciesMeta: + "@types/react": + optional: true + + react-use-measure@2.1.7: + resolution: + { + integrity: sha512-KrvcAo13I/60HpwGO5jpW7E9DfusKyLPLvuHlUyP5zqnmAPhNc6qTRjUQrdTADl0lpPpDVU2/Gg51UlOGHXbdg==, + } + peerDependencies: + react: ">=16.13" + react-dom: ">=16.13" + peerDependenciesMeta: + react-dom: + optional: true + + react@19.2.5: + resolution: + { + integrity: sha512-llUJLzz1zTUBrskt2pwZgLq59AemifIftw4aB7JxOqf1HY2FDaGDxgwpAPVzHU1kdWabH7FauP4i1oEeer2WCA==, + } + engines: { node: ">=0.10.0" } + + read-pkg-up@7.0.1: + resolution: + { + integrity: sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg==, + } + engines: { node: ">=8" } + + read-pkg@5.2.0: + resolution: + { + integrity: sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg==, + } + engines: { node: ">=8" } + + readable-stream@2.3.8: + resolution: + { + integrity: sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==, + } + + readable-stream@3.6.2: + resolution: + { + integrity: sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==, + } + engines: { node: ">= 6" } + + readdirp@3.6.0: + resolution: + { + integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==, + } + engines: { node: ">=8.10.0" } + + readdirp@4.1.2: + resolution: + { + integrity: sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==, + } + engines: { node: ">= 14.18.0" } + + recast@0.23.11: + resolution: + { + integrity: sha512-YTUo+Flmw4ZXiWfQKGcwwc11KnoRAYgzAE2E7mXKCjSviTKShtxBsN6YUUBB2gtaBzKzeKunxhUwNHQuRryhWA==, + } + engines: { node: ">= 4" } + + redent@3.0.0: + resolution: + { + integrity: sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg==, + } + engines: { node: ">=8" } + + reflect.getprototypeof@1.0.10: + resolution: + { + integrity: sha512-00o4I+DVrefhv+nX0ulyi3biSHCPDe+yLv5o/p6d/UVlirijB8E16FtfwSAi4g3tcqrQ4lRAqQSoFEZJehYEcw==, + } + engines: { node: ">= 0.4" } + + regenerate-unicode-properties@10.2.2: + resolution: + { + integrity: sha512-m03P+zhBeQd1RGnYxrGyDAPpWX/epKirLrp8e3qevZdVkKtnCrjjWczIbYc8+xd6vcTStVlqfycTx1KR4LOr0g==, + } + engines: { node: ">=4" } + + regenerate@1.4.2: + resolution: + { + integrity: sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A==, + } + + regexp-tree@0.1.27: + resolution: + { + integrity: sha512-iETxpjK6YoRWJG5o6hXLwvjYAoW+FEZn9os0PD/b6AP6xQwsa/Y7lCVgIixBbUPMfhu+i2LtdeAqVTgGlQarfA==, + } + hasBin: true + + regexp.prototype.flags@1.5.4: + resolution: + { + integrity: sha512-dYqgNSZbDwkaJ2ceRd9ojCGjBq+mOm9LmtXnAnEGyHhN/5R7iDW2TRw3h+o/jCFxus3P2LfWIIiwowAjANm7IA==, + } + engines: { node: ">= 0.4" } + + regexparam@3.0.0: + resolution: + { + integrity: sha512-RSYAtP31mvYLkAHrOlh25pCNQ5hWnT106VukGaaFfuJrZFkGRX5GhUAdPqpSDXxOhA2c4akmRuplv1mRqnBn6Q==, + } + engines: { node: ">=8" } + + regexpu-core@6.4.0: + resolution: + { + integrity: sha512-0ghuzq67LI9bLXpOX/ISfve/Mq33a4aFRzoQYhnnok1JOFpmE/A2TBGkNVenOGEeSBCjIiWcc6MVOG5HEQv0sA==, + } + engines: { node: ">=4" } + + regjsgen@0.8.0: + resolution: + { + integrity: sha512-RvwtGe3d7LvWiDQXeQw8p5asZUmfU1G/l6WbUXeHta7Y2PEIvBTwH6E2EfmYUK8pxcxEdEmaomqyp0vZZ7C+3Q==, + } + + regjsparser@0.10.0: + resolution: + { + integrity: sha512-qx+xQGZVsy55CH0a1hiVwHmqjLryfh7wQyF5HO07XJ9f7dQMY/gPQHhlyDkIzJKC+x2fUCpCcUODUUUFrm7SHA==, + } + hasBin: true + + regjsparser@0.13.1: + resolution: + { + integrity: sha512-dLsljMd9sqwRkby8zhO1gSg3PnJIBFid8f4CQj/sXx+7cKx+E7u0PKhZ+U4wmhx7EfmtvnA318oVaIkAB1lRJw==, + } + hasBin: true + + relateurl@0.2.7: + resolution: + { + integrity: sha512-G08Dxvm4iDN3MLM0EsP62EDV9IuhXPR6blNz6Utcp7zyV3tr4HVNINt6MpaRWbxoOHT3Q7YN2P+jaHX8vUbgog==, + } + engines: { node: ">= 0.10" } + + remove-trailing-separator@1.1.0: + resolution: + { + integrity: sha512-/hS+Y0u3aOfIETiaiirUFwDBDzmXPvO+jAfKTitUngIPzdKc6Z0LoFjM/CK5PL4C+eKwHohlHAb6H0VFfmmUsw==, + } + + replace-ext@2.0.0: + resolution: + { + integrity: sha512-UszKE5KVK6JvyD92nzMn9cDapSk6w/CaFZ96CnmDMUqH9oowfxF/ZjRITD25H4DnOQClLA4/j7jLGXXLVKxAug==, + } + engines: { node: ">= 10" } + + require-directory@2.1.1: + resolution: + { + integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==, + } + engines: { node: ">=0.10.0" } + + require-main-filename@2.0.0: + resolution: + { + integrity: sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==, + } + + requireindex@1.2.0: + resolution: + { + integrity: sha512-L9jEkOi3ASd9PYit2cwRfyppc9NoABujTP8/5gFcbERmo5jUoAKovIC3fsF17pkTnGsrByysqX+Kxd2OTNI1ww==, + } + engines: { node: ">=0.10.5" } + + reserved-identifiers@1.2.0: + resolution: + { + integrity: sha512-yE7KUfFvaBFzGPs5H3Ops1RevfUEsDc5Iz65rOwWg4lE8HJSYtle77uul3+573457oHvBKuHYDl/xqUkKpEEdw==, + } + engines: { node: ">=18" } + + resolve-from@4.0.0: + resolution: + { + integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==, + } + engines: { node: ">=4" } + + resolve-options@2.0.0: + resolution: + { + integrity: sha512-/FopbmmFOQCfsCx77BRFdKOniglTiHumLgwvd6IDPihy1GKkadZbgQJBcTb2lMzSR1pndzd96b1nZrreZ7+9/A==, + } + engines: { node: ">= 10.13.0" } + + resolve@1.22.12: + resolution: + { + integrity: sha512-TyeJ1zif53BPfHootBGwPRYT1RUt6oGWsaQr8UyZW/eAm9bKoijtvruSDEmZHm92CwS9nj7/fWttqPCgzep8CA==, + } + engines: { node: ">= 0.4" } + hasBin: true + + resolve@2.0.0-next.6: + resolution: + { + integrity: sha512-3JmVl5hMGtJ3kMmB3zi3DL25KfkCEyy3Tw7Gmw7z5w8M9WlwoPFnIvwChzu1+cF3iaK3sp18hhPz8ANeimdJfA==, + } + engines: { node: ">= 0.4" } + hasBin: true + + reusify@1.1.0: + resolution: + { + integrity: sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==, + } + engines: { iojs: ">=1.0.0", node: ">=0.10.0" } + + rimraf@3.0.2: + resolution: + { + integrity: sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==, + } + deprecated: Rimraf versions prior to v4 are no longer supported + hasBin: true + + rimraf@5.0.10: + resolution: + { + integrity: sha512-l0OE8wL34P4nJH/H2ffoaniAokM2qSmrtXHmlpvYr5AVVX8msAyW0l8NVJFDxlSK4u3Uh/f41cQheDVdnYijwQ==, + } + hasBin: true + + ripemd160@2.0.3: + resolution: + { + integrity: sha512-5Di9UC0+8h1L6ZD2d7awM7E/T4uA1fJRlx6zk/NvdCCVEoAnFqvHmCuNeIKoCeIixBX/q8uM+6ycDvF8woqosA==, + } + engines: { node: ">= 0.8" } + + rolldown@1.0.0-rc.15: + resolution: + { + integrity: sha512-Ff31guA5zT6WjnGp0SXw76X6hzGRk/OQq2hE+1lcDe+lJdHSgnSX6nK3erbONHyCbpSj9a9E+uX/OvytZoWp2g==, + } + engines: { node: ^20.19.0 || >=22.12.0 } + hasBin: true + + rrweb-cssom@0.8.0: + resolution: + { + integrity: sha512-guoltQEx+9aMf2gDZ0s62EcV8lsXR+0w8915TC3ITdn2YueuNjdAYh/levpU9nFaoChh9RUS5ZdQMrKfVEN9tw==, + } + + rsvp@3.2.1: + resolution: + { + integrity: sha512-Rf4YVNYpKjZ6ASAmibcwTNciQ5Co5Ztq6iZPEykHpkoflnD/K5ryE/rHehFsTm4NJj8nKDhbi3eKBWGogmNnkg==, + } + + rsvp@4.8.5: + resolution: + { + integrity: sha512-nfMOlASu9OnRJo1mbEk2cz0D56a1MBNrJ7orjRZQG10XDyuvwksKbuXNp6qa+kbn839HwjwhBzhFmdsaEAfauA==, + } + engines: { node: 6.* || >= 7.* } + + run-applescript@7.1.0: + resolution: + { + integrity: sha512-DPe5pVFaAsinSaV6QjQ6gdiedWDcRCbUuiQfQa2wmWV7+xC9bGulGI8+TdRmoFkAPaBXk8CrAbnlY2ISniJ47Q==, + } + engines: { node: ">=18" } + + run-parallel@1.2.0: + resolution: + { + integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==, + } + + rxjs-report-usage@1.0.6: + resolution: + { + integrity: sha512-omv1DIv5z1kV+zDAEjaDjWSkx8w5TbFp5NZoPwUipwzYVcor/4So9ZU3bUyQ1c8lxY5Q0Es/ztWW7PGjY7to0Q==, + } + hasBin: true + + rxjs@7.8.2: + resolution: + { + integrity: sha512-dhKf903U/PQZY6boNNtAGdWbG85WAbjT/1xYoZIC7FAY0yWapOBQVsVrDl58W86//e1VpMNBtRV4MaXfdMySFA==, + } + + safe-array-concat@1.1.3: + resolution: + { + integrity: sha512-AURm5f0jYEOydBj7VQlVvDrjeFgthDdEF5H1dP+6mNpoXOMo1quQqJ4wvJDyRZ9+pO3kGWoOdmV08cSv2aJV6Q==, + } + engines: { node: ">=0.4" } + + safe-buffer@5.1.2: + resolution: + { + integrity: sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==, + } + + safe-buffer@5.2.1: + resolution: + { + integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==, + } + + safe-push-apply@1.0.0: + resolution: + { + integrity: sha512-iKE9w/Z7xCzUMIZqdBsp6pEQvwuEebH4vdpjcDWnyzaI6yl6O9FHvVpmGelvEHNsoY6wGblkxR6Zty/h00WiSA==, + } + engines: { node: ">= 0.4" } + + safe-regex-test@1.1.0: + resolution: + { + integrity: sha512-x/+Cz4YrimQxQccJf5mKEbIa1NzeCRNI5Ecl/ekmlYaampdNLPalVyIcCZNNH3MvmqBugV5TMYZXv0ljslUlaw==, + } + engines: { node: ">= 0.4" } + + safer-buffer@2.1.2: + resolution: + { + integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==, + } + + sass@1.99.0: + resolution: + { + integrity: sha512-kgW13M54DUB7IsIRM5LvJkNlpH+WhMpooUcaWGFARkF1Tc82v9mIWkCbCYf+MBvpIUBSeSOTilpZjEPr2VYE6Q==, + } + engines: { node: ">=14.0.0" } + hasBin: true + + saxes@6.0.0: + resolution: + { + integrity: sha512-xAg7SOnEhrm5zI3puOOKyy1OMcMlIJZYNJY7xLBwSze0UjhPLnWfj2GF2EpT0jmzaJKIWKHLsaSSajf35bcYnA==, + } + engines: { node: ">=v12.22.7" } + + scheduler@0.27.0: + resolution: + { + integrity: sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q==, + } + + sdp-transform@2.15.0: + resolution: + { + integrity: sha512-KrOH82c/W+GYQ0LHqtr3caRpM3ITglq3ljGUIb8LTki7ByacJZ9z+piSGiwZDsRyhQbYBOBJgr2k6X4BZXi3Kw==, + } + hasBin: true + + sdp-transform@3.0.0: + resolution: + { + integrity: sha512-gfYVRGxjHkGF2NPeUWHw5u6T/KGFtS5/drPms73gaSuMaVHKCY3lpLnGDfswVQO0kddeePoti09AwhYP4zA8dQ==, + } + hasBin: true + + sdp@3.2.2: + resolution: + { + integrity: sha512-xZocWwfyp4hkbN4hLWxMjmv2Q8aNa9MhmOZ7L9aCZPT+dZsgRr6wZRrSYE3HTdyk/2pZKPSgqI7ns7Een1xMSA==, + } + + semver@5.7.2: + resolution: + { + integrity: sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==, + } + hasBin: true + + semver@6.3.1: + resolution: + { + integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==, + } + hasBin: true + + semver@7.7.4: + resolution: + { + integrity: sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==, + } + engines: { node: ">=10" } + hasBin: true + + set-blocking@2.0.0: + resolution: + { + integrity: sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==, + } + + set-cookie-parser@2.7.2: + resolution: + { + integrity: sha512-oeM1lpU/UvhTxw+g3cIfxXHyJRc/uidd3yK1P242gzHds0udQBYzs3y8j4gCCW+ZJ7ad0yctld8RYO+bdurlvw==, + } + + set-function-length@1.2.2: + resolution: + { + integrity: sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==, + } + engines: { node: ">= 0.4" } + + set-function-name@2.0.2: + resolution: + { + integrity: sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==, + } + engines: { node: ">= 0.4" } + + set-proto@1.0.0: + resolution: + { + integrity: sha512-RJRdvCo6IAnPdsvP/7m6bsQqNnn1FCBX5ZNtFL98MmFF/4xAIJTIg1YbHW5DC2W5SKZanrC6i4HsJqlajw/dZw==, + } + engines: { node: ">= 0.4" } + + setimmediate@1.0.5: + resolution: + { + integrity: sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA==, + } + + sha.js@2.4.12: + resolution: + { + integrity: sha512-8LzC5+bvI45BjpfXU8V5fdU2mfeKiQe1D1gIMn7XUlF3OTUrpdJpPPH4EMAnF0DsHHdSZqCdSss5qCmJKuiO3w==, + } + engines: { node: ">= 0.10" } + hasBin: true + + shebang-command@2.0.0: + resolution: + { + integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==, + } + engines: { node: ">=8" } + + shebang-regex@3.0.0: + resolution: + { + integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==, + } + engines: { node: ">=8" } + + side-channel-list@1.0.1: + resolution: + { + integrity: sha512-mjn/0bi/oUURjc5Xl7IaWi/OJJJumuoJFQJfDDyO46+hBWsfaVM65TBHq2eoZBhzl9EchxOijpkbRC8SVBQU0w==, + } + engines: { node: ">= 0.4" } + + side-channel-map@1.0.1: + resolution: + { + integrity: sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==, + } + engines: { node: ">= 0.4" } + + side-channel-weakmap@1.0.2: + resolution: + { + integrity: sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==, + } + engines: { node: ">= 0.4" } + + side-channel@1.1.0: + resolution: + { + integrity: sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==, + } + engines: { node: ">= 0.4" } + + siginfo@2.0.0: + resolution: + { + integrity: sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==, + } + + signal-exit@4.1.0: + resolution: + { + integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==, + } + engines: { node: ">=14" } + + sisteransi@1.0.5: + resolution: + { + integrity: sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==, + } + + slash@3.0.0: + resolution: + { + integrity: sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==, + } + engines: { node: ">=8" } + + smol-toml@1.6.1: + resolution: + { + integrity: sha512-dWUG8F5sIIARXih1DTaQAX4SsiTXhInKf1buxdY9DIg4ZYPZK5nGM1VRIYmEbDbsHt7USo99xSLFu5Q1IqTmsg==, + } + engines: { node: ">= 18" } + + snake-case@3.0.4: + resolution: + { + integrity: sha512-LAOh4z89bGQvl9pFfNF8V146i7o7/CqFPbqzYgP+yYzDIDeS9HaNFtXABamRW+AQzEVODcvE79ljJ+8a9YSdMg==, + } + + sort-keys@5.1.0: + resolution: + { + integrity: sha512-aSbHV0DaBcr7u0PVHXzM6NbZNAtrr9sF6+Qfs9UUVG7Ll3jQ6hHi8F/xqIIcn2rvIVbr0v/2zyjSdwSV47AgLQ==, + } + engines: { node: ">=12" } + + source-map-js@1.2.1: + resolution: + { + integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==, + } + engines: { node: ">=0.10.0" } + + source-map-support@0.5.21: + resolution: + { + integrity: sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==, + } + + source-map@0.6.1: + resolution: + { + integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==, + } + engines: { node: ">=0.10.0" } + + spdx-correct@3.2.0: + resolution: + { + integrity: sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA==, + } + + spdx-exceptions@2.5.0: + resolution: + { + integrity: sha512-PiU42r+xO4UbUS1buo3LPJkjlO7430Xn5SVAhdpzzsPHsjbYVflnnFdATgabnLude+Cqu25p6N+g2lw/PFsa4w==, + } + + spdx-expression-parse@3.0.1: + resolution: + { + integrity: sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==, + } + + spdx-expression-parse@4.0.0: + resolution: + { + integrity: sha512-Clya5JIij/7C6bRR22+tnGXbc4VKlibKSVj2iHvVeX5iMW7s1SIQlqu699JkODJJIhh/pUu8L0/VLh8xflD+LQ==, + } + + spdx-license-ids@3.0.23: + resolution: + { + integrity: sha512-CWLcCCH7VLu13TgOH+r8p1O/Znwhqv/dbb6lqWy67G+pT1kHmeD/+V36AVb/vq8QMIQwVShJ6Ssl5FPh0fuSdw==, + } + + sprintf-js@1.1.3: + resolution: + { + integrity: sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA==, + } + + stackback@0.0.2: + resolution: + { + integrity: sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==, + } + + std-env@4.1.0: + resolution: + { + integrity: sha512-Rq7ybcX2RuC55r9oaPVEW7/xu3tj8u4GeBYHBWCychFtzMIr86A7e3PPEBPT37sHStKX3+TiX/Fr/ACmJLVlLQ==, + } + + stop-iteration-iterator@1.1.0: + resolution: + { + integrity: sha512-eLoXW/DHyl62zxY4SCaIgnRhuMr6ri4juEYARS8E6sCEqzKpOiE521Ucofdx+KnDZl5xmvGYaaKCk5FEOxJCoQ==, + } + engines: { node: ">= 0.4" } + + storybook@10.3.5: + resolution: + { + integrity: sha512-uBSZu/GZa9aEIW3QMGvdQPMZWhGxSe4dyRWU8B3/Vd47Gy/XLC7tsBxRr13txmmPOEDHZR94uLuq0H50fvuqBw==, + } + hasBin: true + peerDependencies: + prettier: ^2 || ^3 + peerDependenciesMeta: + prettier: + optional: true + + stream-browserify@3.0.0: + resolution: + { + integrity: sha512-H73RAHsVBapbim0tU2JwwOiXUj+fikfiaoYAKHF3VJfA0pe2BCzkhAHBlLG6REzE+2WNZcxOXjK7lkso+9euLA==, + } + + stream-composer@1.0.2: + resolution: + { + integrity: sha512-bnBselmwfX5K10AH6L4c8+S5lgZMWI7ZYrz2rvYjCPB2DIMC4Ig8OpxGpNJSxRZ58oti7y1IcNvjBAz9vW5m4w==, + } + + stream-http@3.2.0: + resolution: + { + integrity: sha512-Oq1bLqisTyK3TSCXpPbT4sdeYNdmyZJv1LxpEm2vu1ZhK89kSE5YXwZc3cWk0MagGaKriBh9mCFbVGtO+vY29A==, + } + + streamx@2.25.0: + resolution: + { + integrity: sha512-0nQuG6jf1w+wddNEEXCF4nTg3LtufWINB5eFEN+5TNZW7KWJp6x87+JFL43vaAUPyCfH1wID+mNVyW6OHtFamg==, + } + + string-width@4.2.3: + resolution: + { + integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==, + } + engines: { node: ">=8" } + + string-width@5.1.2: + resolution: + { + integrity: sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==, + } + engines: { node: ">=12" } + + string.prototype.includes@2.0.1: + resolution: + { + integrity: sha512-o7+c9bW6zpAdJHTtujeePODAhkuicdAryFsfVKwA+wGw89wJ4GTY484WTucM9hLtDEOpOvI+aHnzqnC5lHp4Rg==, + } + engines: { node: ">= 0.4" } + + string.prototype.matchall@4.0.12: + resolution: + { + integrity: sha512-6CC9uyBL+/48dYizRf7H7VAYCMCNTBeM78x/VTUe9bFEaxBepPJDa1Ow99LqI/1yF7kuy7Q3cQsYMrcjGUcskA==, + } + engines: { node: ">= 0.4" } + + string.prototype.repeat@1.0.0: + resolution: + { + integrity: sha512-0u/TldDbKD8bFCQ/4f5+mNRrXwZ8hg2w7ZR8wa16e8z9XpePWl3eGEcUD0OXpEH/VJH/2G3gjUtR3ZOiBe2S/w==, + } + + string.prototype.trim@1.2.10: + resolution: + { + integrity: sha512-Rs66F0P/1kedk5lyYyH9uBzuiI/kNRmwJAR9quK6VOtIpZ2G+hMZd+HQbbv25MgCA6gEffoMZYxlTod4WcdrKA==, + } + engines: { node: ">= 0.4" } + + string.prototype.trimend@1.0.9: + resolution: + { + integrity: sha512-G7Ok5C6E/j4SGfyLCloXTrngQIQU3PWtXGst3yM7Bea9FRURf1S42ZHlZZtsNque2FN2PoUhfZXYLNWwEr4dLQ==, + } + engines: { node: ">= 0.4" } + + string.prototype.trimstart@1.0.8: + resolution: + { + integrity: sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg==, + } + engines: { node: ">= 0.4" } + + string_decoder@1.1.1: + resolution: + { + integrity: sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==, + } + + string_decoder@1.3.0: + resolution: + { + integrity: sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==, + } + + strip-ansi@6.0.1: + resolution: + { + integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==, + } + engines: { node: ">=8" } + + strip-ansi@7.2.0: + resolution: + { + integrity: sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w==, + } + engines: { node: ">=12" } + + strip-bom@3.0.0: + resolution: + { + integrity: sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==, + } + engines: { node: ">=4" } + + strip-indent@3.0.0: + resolution: + { + integrity: sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==, + } + engines: { node: ">=8" } + + strip-indent@4.1.1: + resolution: + { + integrity: sha512-SlyRoSkdh1dYP0PzclLE7r0M9sgbFKKMFXpFRUMNuKhQSbC6VQIGzq3E0qsfvGJaUFJPGv6Ws1NZ/haTAjfbMA==, + } + engines: { node: ">=12" } + + strip-json-comments@3.1.1: + resolution: + { + integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==, + } + engines: { node: ">=8" } + + strip-json-comments@5.0.3: + resolution: + { + integrity: sha512-1tB5mhVo7U+ETBKNf92xT4hrQa3pm0MZ0PQvuDnWgAAGHDsfp4lPSpiS6psrSiet87wyGPh9ft6wmhOMQ0hDiw==, + } + engines: { node: ">=14.16" } + + supports-color@7.2.0: + resolution: + { + integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==, + } + engines: { node: ">=8" } + + supports-preserve-symlinks-flag@1.0.0: + resolution: + { + integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==, + } + engines: { node: ">= 0.4" } + + svg-parser@2.0.4: + resolution: + { + integrity: sha512-e4hG1hRwoOdRb37cIMSgzNsxyzKfayW6VOflrwvR+/bzrkyxY/31WkbgnQpgtrNp1SdpJvpUAGTa/ZoiPNDuRQ==, + } + + symbol-tree@3.2.4: + resolution: + { + integrity: sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==, + } + + symlink-or-copy@1.3.1: + resolution: + { + integrity: sha512-0K91MEXFpBUaywiwSSkmKjnGcasG/rVBXFLJz5DrgGabpYD6N+3yZrfD6uUIfpuTu65DZLHi7N8CizHc07BPZA==, + } + + tabbable@6.4.0: + resolution: + { + integrity: sha512-05PUHKSNE8ou2dwIxTngl4EzcnsCDZGJ/iCLtDflR/SHB/ny14rXc+qU5P4mG9JkusiV7EivzY9Mhm55AzAvCg==, + } + + teex@1.0.1: + resolution: + { + integrity: sha512-eYE6iEI62Ni1H8oIa7KlDU6uQBtqr4Eajni3wX7rpfXD8ysFx8z0+dri+KWEPWpBsxXfxu58x/0jvTVT1ekOSg==, + } + + terser@5.46.1: + resolution: + { + integrity: sha512-vzCjQO/rgUuK9sf8VJZvjqiqiHFaZLnOiimmUuOKODxWL8mm/xua7viT7aqX7dgPY60otQjUotzFMmCB4VdmqQ==, + } + engines: { node: ">=10" } + hasBin: true + + text-decoder@1.2.7: + resolution: + { + integrity: sha512-vlLytXkeP4xvEq2otHeJfSQIRyWxo/oZGEbXrtEEF9Hnmrdly59sUbzZ/QgyWuLYHctCHxFF4tRQZNQ9k60ExQ==, + } + + text-table@0.2.0: + resolution: + { + integrity: sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==, + } + + through2@2.0.5: + resolution: + { + integrity: sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==, + } + + timers-browserify@2.0.12: + resolution: + { + integrity: sha512-9phl76Cqm6FhSX9Xe1ZUAMLtm1BLkKj2Qd5ApyWkXzsMRaA7dgr81kf4wJmQf/hAvg8EEyJxDo3du/0KlhPiKQ==, + } + engines: { node: ">=0.6.0" } + + tiny-invariant@1.3.3: + resolution: + { + integrity: sha512-+FbBPE1o9QAYvviau/qC5SE3caw21q3xkvWKBtja5vgqOWIHHJ3ioaq1VPfn/Szqctz2bU/oYeKd9/z5BL+PVg==, + } + + tinybench@2.9.0: + resolution: + { + integrity: sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==, + } + + tinyexec@1.1.1: + resolution: + { + integrity: sha512-VKS/ZaQhhkKFMANmAOhhXVoIfBXblQxGX1myCQ2faQrfmobMftXeJPcZGp0gS07ocvGJWDLZGyOZDadDBqYIJg==, + } + engines: { node: ">=18" } + + tinyglobby@0.2.16: + resolution: + { + integrity: sha512-pn99VhoACYR8nFHhxqix+uvsbXineAasWm5ojXoN8xEwK5Kd3/TrhNn1wByuD52UxWRLy8pu+kRMniEi6Eq9Zg==, + } + engines: { node: ">=12.0.0" } + + tinyrainbow@2.0.0: + resolution: + { + integrity: sha512-op4nsTR47R6p0vMUUoYl/a+ljLFVtlfaXkLQmqfLR1qHma1h/ysYk4hEXZ880bf2CYgTskvTa/e196Vd5dDQXw==, + } + engines: { node: ">=14.0.0" } + + tinyrainbow@3.1.0: + resolution: + { + integrity: sha512-Bf+ILmBgretUrdJxzXM0SgXLZ3XfiaUuOj/IKQHuTXip+05Xn+uyEYdVg0kYDipTBcLrCVyUzAPz7QmArb0mmw==, + } + engines: { node: ">=14.0.0" } + + tinyspy@4.0.4: + resolution: + { + integrity: sha512-azl+t0z7pw/z958Gy9svOTuzqIk6xq+NSheJzn5MMWtWTFywIacg2wUlzKFGtt3cthx0r2SxMK0yzJOR0IES7Q==, + } + engines: { node: ">=14.0.0" } + + tldts-core@6.1.86: + resolution: + { + integrity: sha512-Je6p7pkk+KMzMv2XXKmAE3McmolOQFdxkKw0R8EYNr7sELW46JqnNeTX8ybPiQgvg1ymCoF8LXs5fzFaZvJPTA==, + } + + tldts@6.1.86: + resolution: + { + integrity: sha512-WMi/OQ2axVTf/ykqCQgXiIct+mSQDFdH2fkwhPwgEwvJ1kSzZRiinb0zF2Xb8u4+OqPChmyI6MEu4EezNJz+FQ==, + } + hasBin: true + + to-buffer@1.2.2: + resolution: + { + integrity: sha512-db0E3UJjcFhpDhAF4tLo03oli3pwl3dbnzXOUIlRKrp+ldk/VUxzpWYZENsw2SZiuBjHAk7DfB0VU7NKdpb6sw==, + } + engines: { node: ">= 0.4" } + + to-regex-range@5.0.1: + resolution: + { + integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==, + } + engines: { node: ">=8.0" } + + to-through@3.0.0: + resolution: + { + integrity: sha512-y8MN937s/HVhEoBU1SxfHC+wxCHkV1a9gW8eAdTadYh/bGyesZIVcbjI+mSpFbSVwQici/XjBjuUyri1dnXwBw==, + } + engines: { node: ">=10.13.0" } + + to-valid-identifier@1.0.0: + resolution: + { + integrity: sha512-41wJyvKep3yT2tyPqX/4blcfybknGB4D+oETKLs7Q76UiPqRpUJK3hr1nxelyYO0PHKVzJwlu0aCeEAsGI6rpw==, + } + engines: { node: ">=20" } + + toggle-selection@1.0.6: + resolution: + { + integrity: sha512-BiZS+C1OS8g/q2RRbJmy59xpyghNBqrr6k5L/uKBGRsTfxmu3ffiRnd8mlGPUVayg8pvfi5urfnu8TU7DVOkLQ==, + } + + tough-cookie@5.1.2: + resolution: + { + integrity: sha512-FVDYdxtnj0G6Qm/DhNPSb8Ju59ULcup3tuJxkFb5K8Bv2pUXILbf0xZWU8PX8Ov19OXljbUyveOFwRMwkXzO+A==, + } + engines: { node: ">=16" } + + tr46@0.0.3: + resolution: + { + integrity: sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==, + } + + tr46@5.1.1: + resolution: + { + integrity: sha512-hdF5ZgjTqgAntKkklYw0R03MG2x/bSzTtkxmIRw/sTNV8YXsCJ1tfLAX23lhxhHJlEf3CRCOCGGWw3vI3GaSPw==, + } + engines: { node: ">=18" } + + ts-api-utils@2.5.0: + resolution: + { + integrity: sha512-OJ/ibxhPlqrMM0UiNHJ/0CKQkoKF243/AEmplt3qpRgkW8VG7IfOS41h7V8TjITqdByHzrjcS/2si+y4lIh8NA==, + } + engines: { node: ">=18.12" } + peerDependencies: + typescript: ">=4.8.4" + + ts-dedent@2.2.0: + resolution: + { + integrity: sha512-q5W7tVM71e2xjHZTlgfTDoPF/SmqKG5hddq9SzR49CH2hayqRKJtQ4mtRlSxKaJlR/+9rEM+mnBHf7I2/BQcpQ==, + } + engines: { node: ">=6.10" } + + tsconfig-paths@3.15.0: + resolution: + { + integrity: sha512-2Ac2RgzDe/cn48GvOe3M+o82pEFewD3UPbyoUHHdKasHwJKjds4fLXWf/Ux5kATBKN20oaFGu+jbElp1pos0mg==, + } + + tsconfig-paths@4.2.0: + resolution: + { + integrity: sha512-NoZ4roiN7LnbKn9QqE1amc9DJfzvZXxF4xDavcOWt1BPkdx+m+0gJuPM+S0vCe7zTJMYUP0R8pO2XMr+Y8oLIg==, + } + engines: { node: ">=6" } + + tslib@1.14.1: + resolution: + { + integrity: sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==, + } + + tslib@2.8.1: + resolution: + { + integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==, + } + + tsutils-etc@1.4.2: + resolution: + { + integrity: sha512-2Dn5SxTDOu6YWDNKcx1xu2YUy6PUeKrWZB/x2cQ8vY2+iz3JRembKn/iZ0JLT1ZudGNwQQvtFX9AwvRHbXuPUg==, + } + hasBin: true + peerDependencies: + tsutils: ^3.0.0 + typescript: ">=4.0.0" + + tsutils@3.21.0: + resolution: + { + integrity: sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==, + } + engines: { node: ">= 6" } + peerDependencies: + typescript: ">=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta" + + tty-browserify@0.0.1: + resolution: + { + integrity: sha512-C3TaO7K81YvjCgQH9Q1S3R3P3BtN3RIM8n+OvX4il1K1zgE8ZhI0op7kClgkxtutIE8hQrcrHBXvIheqKUUCxw==, + } + + tunnel@0.0.6: + resolution: + { + integrity: sha512-1h/Lnq9yajKY2PEbBadPXj3VxsDDu844OnaAo52UVmIzIvwwtBPIuNvkjuzBlTWpfJyUbG3ez0KSBibQkj4ojg==, + } + engines: { node: ">=0.6.11 <=0.7.0 || >=0.7.3" } + + type-check@0.4.0: + resolution: + { + integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==, + } + engines: { node: ">= 0.8.0" } + + type-fest@0.20.2: + resolution: + { + integrity: sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==, + } + engines: { node: ">=10" } + + type-fest@0.6.0: + resolution: + { + integrity: sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg==, + } + engines: { node: ">=8" } + + type-fest@0.8.1: + resolution: + { + integrity: sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==, + } + engines: { node: ">=8" } + + typed-array-buffer@1.0.3: + resolution: + { + integrity: sha512-nAYYwfY3qnzX30IkA6AQZjVbtK6duGontcQm1WSG1MD94YLqK0515GNApXkoxKOWMusVssAHWLh9SeaoefYFGw==, + } + engines: { node: ">= 0.4" } + + typed-array-byte-length@1.0.3: + resolution: + { + integrity: sha512-BaXgOuIxz8n8pIq3e7Atg/7s+DpiYrxn4vdot3w9KbnBhcRQq6o3xemQdIfynqSeXeDrF32x+WvfzmOjPiY9lg==, + } + engines: { node: ">= 0.4" } + + typed-array-byte-offset@1.0.4: + resolution: + { + integrity: sha512-bTlAFB/FBYMcuX81gbL4OcpH5PmlFHqlCCpAl8AlEzMz5k53oNDvN8p1PNOWLEmI2x4orp3raOFB51tv9X+MFQ==, + } + engines: { node: ">= 0.4" } + + typed-array-length@1.0.7: + resolution: + { + integrity: sha512-3KS2b+kL7fsuk/eJZ7EQdnEmQoaho/r6KUef7hxvltNA5DR8NAUM+8wJMbJyZ4G9/7i3v5zPBIMN5aybAh2/Jg==, + } + engines: { node: ">= 0.4" } + + typed-emitter@2.1.0: + resolution: + { + integrity: sha512-g/KzbYKbH5C2vPkaXGu8DJlHrGKHLsM25Zg9WuC9pMGfuvT+X25tZQWo5fK1BjBm8+UrVE9LDCvaY0CQk+fXDA==, + } + + typescript-eslint-language-service@5.0.5: + resolution: + { + integrity: sha512-b7gWXpwSTqMVKpPX3WttNZEyVAMKs/2jsHKF79H+qaD6mjzCyU5jboJe/lOZgLJD+QRsXCr0GjIVxvl5kI1NMw==, + } + peerDependencies: + "@typescript-eslint/parser": ">= 5.0.0" + eslint: ">= 8.0.0" + typescript: ">= 4.0.0" + + typescript@5.9.3: + resolution: + { + integrity: sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==, + } + engines: { node: ">=14.17" } + hasBin: true + + unbash@2.2.0: + resolution: + { + integrity: sha512-X2wH19RAPZE3+ldGicOkoj/SIA83OIxcJ6Cuaw23hf8Xc6fQpvZXY0SftE2JgS0QhYLUG4uwodSI3R53keyh7w==, + } + engines: { node: ">=14" } + + unbox-primitive@1.1.0: + resolution: + { + integrity: sha512-nWJ91DjeOkej/TA8pXQ3myruKpKEYgqvpw9lz4OPHj/NWFNluYrjbz9j01CJ8yKQd2g4jFoOkINCTW2I5LEEyw==, + } + engines: { node: ">= 0.4" } + + underscore.string@3.3.6: + resolution: + { + integrity: sha512-VoC83HWXmCrF6rgkyxS9GHv8W9Q5nhMKho+OadDJGzL2oDYbYEppBaCMH6pFlwLeqj2QS+hhkw2kpXkSdD1JxQ==, + } + + undici-types@7.16.0: + resolution: + { + integrity: sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw==, + } + + undici@5.29.0: + resolution: + { + integrity: sha512-raqeBD6NQK4SkWhQzeYKd1KmIG6dllBOTt55Rmkt4HtI9mwdWtJljnrXjAFUBLTSN67HWrOIZ3EPF4kjUw80Bg==, + } + engines: { node: ">=14.0" } + + undici@7.25.0: + resolution: + { + integrity: sha512-xXnp4kTyor2Zq+J1FfPI6Eq3ew5h6Vl0F/8d9XU5zZQf1tX9s2Su1/3PiMmUANFULpmksxkClamIZcaUqryHsQ==, + } + engines: { node: ">=20.18.1" } + + unhomoglyph@1.0.6: + resolution: + { + integrity: sha512-7uvcWI3hWshSADBu4JpnyYbTVc7YlhF5GDW/oPD5AxIxl34k4wXR3WDkPnzLxkN32LiTCTKMQLtKVZiwki3zGg==, + } + + unicode-canonical-property-names-ecmascript@2.0.1: + resolution: + { + integrity: sha512-dA8WbNeb2a6oQzAQ55YlT5vQAWGV9WXOsi3SskE3bcCdM0P4SDd+24zS/OCacdRq5BkdsRj9q3Pg6YyQoxIGqg==, + } + engines: { node: ">=4" } + + unicode-match-property-ecmascript@2.0.0: + resolution: + { + integrity: sha512-5kaZCrbp5mmbz5ulBkDkbY0SsPOjKqVS35VpL9ulMPfSl0J0Xsm+9Evphv9CoIZFwre7aJoa94AY6seMKGVN5Q==, + } + engines: { node: ">=4" } + + unicode-match-property-value-ecmascript@2.2.1: + resolution: + { + integrity: sha512-JQ84qTuMg4nVkx8ga4A16a1epI9H6uTXAknqxkGF/aFfRLw1xC/Bp24HNLaZhHSkWd3+84t8iXnp1J0kYcZHhg==, + } + engines: { node: ">=4" } + + unicode-property-aliases-ecmascript@2.2.0: + resolution: + { + integrity: sha512-hpbDzxUY9BFwX+UeBnxv3Sh1q7HFxj48DTmXchNgRa46lO8uj3/1iEn3MiNUYTg1g9ctIqXCCERn8gYZhHC5lQ==, + } + engines: { node: ">=4" } + + unique-names-generator@4.7.1: + resolution: + { + integrity: sha512-lMx9dX+KRmG8sq6gulYYpKWZc9RlGsgBR6aoO8Qsm3qvkSJ+3rAymr+TnV8EDMrIrwuFJ4kruzMWM/OpYzPoow==, + } + engines: { node: ">=8" } + + universal-user-agent@6.0.1: + resolution: + { + integrity: sha512-yCzhz6FN2wU1NiiQRogkTQszlQSlpWaw8SvVegAc+bDxbzHgh1vX8uIe8OYyMH6DwH+sdTJsgMl36+mSMdRJIQ==, + } + + universalify@0.1.2: + resolution: + { + integrity: sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==, + } + engines: { node: ">= 4.0.0" } + + universalify@2.0.1: + resolution: + { + integrity: sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==, + } + engines: { node: ">= 10.0.0" } + + unplugin@1.0.1: + resolution: + { + integrity: sha512-aqrHaVBWW1JVKBHmGo33T5TxeL0qWzfvjWokObHA9bYmN7eNDkwOxmLjhioHl9878qDFMAaT51XNroRyuz7WxA==, + } + + unplugin@1.16.1: + resolution: + { + integrity: sha512-4/u/j4FrCKdi17jaxuJA0jClGxB1AvU2hw/IuayPc4ay1XGaJs/rbb4v5WKwAjNifjmXK9PIFyuPiaK8azyR9w==, + } + engines: { node: ">=14.0.0" } + + unplugin@2.3.11: + resolution: + { + integrity: sha512-5uKD0nqiYVzlmCRs01Fhs2BdkEgBS3SAVP6ndrBsuK42iC2+JHyxM05Rm9G8+5mkmRtzMZGY8Ct5+mliZxU/Ww==, + } + engines: { node: ">=18.12.0" } + + update-browserslist-db@1.2.3: + resolution: + { + integrity: sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w==, + } + hasBin: true + peerDependencies: + browserslist: ">= 4.21.0" + + uri-js@4.4.1: + resolution: + { + integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==, + } + + url@0.11.4: + resolution: + { + integrity: sha512-oCwdVC7mTuWiPyjLUz/COz5TLk6wgp0RCsN+wHZ2Ekneac9w8uuV0njcbbie2ME+Vs+d6duwmYuR3HgQXs1fOg==, + } + engines: { node: ">= 0.4" } + + use-callback-ref@1.3.3: + resolution: + { + integrity: sha512-jQL3lRnocaFtu3V00JToYz/4QkNWswxijDaCVNZRiRTO3HQDLsdu1ZtmIUvV4yPp+rvWm5j0y0TG/S61cuijTg==, + } + engines: { node: ">=10" } + peerDependencies: + "@types/react": "*" + react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc + peerDependenciesMeta: + "@types/react": + optional: true + + use-sidecar@1.1.3: + resolution: + { + integrity: sha512-Fedw0aZvkhynoPYlA5WXrMCAMm+nSWdZt6lzJQ7Ok8S6Q+VsHmHpRWndVRJ8Be0ZbkfPc5LRYH+5XrzXcEeLRQ==, + } + engines: { node: ">=10" } + peerDependencies: + "@types/react": "*" + react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc + peerDependenciesMeta: + "@types/react": + optional: true + + use-sync-external-store@1.6.0: + resolution: + { + integrity: sha512-Pp6GSwGP/NrPIrxVFAIkOQeyw8lFenOHijQWkUTrDvrF4ALqylP2C/KCkeS9dpUM3KvYRQhna5vt7IL95+ZQ9w==, + } + peerDependencies: + react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 + + usehooks-ts@3.1.1: + resolution: + { + integrity: sha512-I4diPp9Cq6ieSUH2wu+fDAVQO43xwtulo+fKEidHUwZPnYImbtkTjzIJYcDcJqxgmX31GVqNFURodvcgHcW0pA==, + } + engines: { node: ">=16.15.0" } + peerDependencies: + react: ^16.8.0 || ^17 || ^18 || ^19 || ^19.0.0-rc + + util-deprecate@1.0.2: + resolution: + { + integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==, + } + + util@0.12.5: + resolution: + { + integrity: sha512-kZf/K6hEIrWHI6XqOFUiiMa+79wE/D8Q+NCNAWclkyg3b4d2k7s0QGepNjiABc+aR3N1PAyHL7p6UcLY6LmrnA==, + } + + uuid@13.0.0: + resolution: + { + integrity: sha512-XQegIaBTVUjSHliKqcnFqYypAd4S+WCYt5NIeRs6w/UAry7z8Y9j5ZwRRL4kzq9U3sD6v+85er9FvkEaBpji2w==, + } + hasBin: true + + validate-npm-package-license@3.0.4: + resolution: + { + integrity: sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==, + } + + value-or-function@4.0.0: + resolution: + { + integrity: sha512-aeVK81SIuT6aMJfNo9Vte8Dw0/FZINGBV8BfCraGtqVxIeLAEhJyoWs8SmvRVmXfGss2PmmOwZCuBPbZR+IYWg==, + } + engines: { node: ">= 10.13.0" } + + vaul@1.1.2: + resolution: + { + integrity: sha512-ZFkClGpWyI2WUQjdLJ/BaGuV6AVQiJ3uELGk3OYtP+B6yCO7Cmn9vPFXVJkRaGkOJu3m8bQMgtyzNHixULceQA==, + } + peerDependencies: + react: ^16.8 || ^17.0 || ^18.0 || ^19.0.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0.0 || ^19.0.0-rc + + vinyl-contents@2.0.0: + resolution: + { + integrity: sha512-cHq6NnGyi2pZ7xwdHSW1v4Jfnho4TEGtxZHw01cmnc8+i7jgR6bRnED/LbrKan/Q7CvVLbnvA5OepnhbpjBZ5Q==, + } + engines: { node: ">=10.13.0" } + + vinyl-fs@4.0.2: + resolution: + { + integrity: sha512-XRFwBLLTl8lRAOYiBqxY279wY46tVxLaRhSwo3GzKEuLz1giffsOquWWboD/haGf5lx+JyTigCFfe7DWHoARIA==, + } + engines: { node: ">=10.13.0" } + + vinyl-sourcemap@2.0.0: + resolution: + { + integrity: sha512-BAEvWxbBUXvlNoFQVFVHpybBbjW1r03WhohJzJDSfgrrK5xVYIDTan6xN14DlyImShgDRv2gl9qhM6irVMsV0Q==, + } + engines: { node: ">=10.13.0" } + + vinyl@3.0.1: + resolution: + { + integrity: sha512-0QwqXteBNXgnLCdWdvPQBX6FXRHtIH3VhJPTd5Lwn28tJXc34YqSCWUmkOvtJHBmB3gGoPtrOKk3Ts8/kEZ9aA==, + } + engines: { node: ">=10.13.0" } + + vite-plugin-generate-file@0.3.1: + resolution: + { + integrity: sha512-tiA3gkPM21MS2+RyqsBMT33GSlM9LM1TJjf6vGvV/e/ml3e3vTKfuH3l2N0NpUgcayvj1fXnmlo5YBuahA6bsg==, + } + + vite-plugin-html@3.2.2: + resolution: + { + integrity: sha512-vb9C9kcdzcIo/Oc3CLZVS03dL5pDlOFuhGlZYDCJ840BhWl/0nGeZWf3Qy7NlOayscY4Cm/QRgULCQkEZige5Q==, + } + peerDependencies: + vite: ">=2.0.0" + + vite-plugin-node-stdlib-browser@0.2.1: + resolution: + { + integrity: sha512-6u2i613Dkqj5KaTNIrnZvE6y3/awWAp0S5TjucTvGxdhetftB1Mgvblc+nwYzlw6sntPlac8UOC7ttXNh+LZKA==, + } + peerDependencies: + node-stdlib-browser: ^1.2.0 + vite: ^2.0.0 || ^3.0.0 || ^4.0.0 + + vite-plugin-svgr@4.5.0: + resolution: + { + integrity: sha512-W+uoSpmVkSmNOGPSsDCWVW/DDAyv+9fap9AZXBvWiQqrboJ08j2vh0tFxTD/LjwqwAd3yYSVJgm54S/1GhbdnA==, + } + peerDependencies: + vite: ">=2.6.0" + + vite@8.0.8: + resolution: + { + integrity: sha512-dbU7/iLVa8KZALJyLOBOQ88nOXtNG8vxKuOT4I2mD+Ya70KPceF4IAmDsmU0h1Qsn5bPrvsY9HJstCRh3hG6Uw==, + } + engines: { node: ^20.19.0 || >=22.12.0 } + hasBin: true + peerDependencies: + "@types/node": ^20.19.0 || >=22.12.0 + "@vitejs/devtools": ^0.1.0 + esbuild: ^0.27.7 + jiti: ">=1.21.0" + less: ^4.0.0 + sass: ^1.70.0 + sass-embedded: ^1.70.0 + stylus: ">=0.54.8" + sugarss: ^5.0.0 + terser: ^5.16.0 + tsx: ^4.8.1 + yaml: ^2.4.2 + peerDependenciesMeta: + "@types/node": + optional: true + "@vitejs/devtools": + optional: true + esbuild: + optional: true + jiti: + optional: true + less: + optional: true + sass: + optional: true + sass-embedded: + optional: true + stylus: + optional: true + sugarss: + optional: true + terser: + optional: true + tsx: + optional: true + yaml: + optional: true + + vitest-axe@1.0.0-pre.5: + resolution: + { + integrity: sha512-eUGxjpXnceha9lkqIVyMgOUeDmWU9LVjNiLTjAjDtMew0WbaBDtixoUvdftOhZfqRI03G2Ay4ZxaU1KG6jNCiQ==, + } + peerDependencies: + vitest: ">=1" + + vitest@4.1.4: + resolution: + { + integrity: sha512-tFuJqTxKb8AvfyqMfnavXdzfy3h3sWZRWwfluGbkeR7n0HUev+FmNgZ8SDrRBTVrVCjgH5cA21qGbCffMNtWvg==, + } + engines: { node: ^20.0.0 || ^22.0.0 || >=24.0.0 } + hasBin: true + peerDependencies: + "@edge-runtime/vm": "*" + "@opentelemetry/api": ^1.9.0 + "@types/node": ^20.0.0 || ^22.0.0 || >=24.0.0 + "@vitest/browser-playwright": 4.1.4 + "@vitest/browser-preview": 4.1.4 + "@vitest/browser-webdriverio": 4.1.4 + "@vitest/coverage-istanbul": 4.1.4 + "@vitest/coverage-v8": 4.1.4 + "@vitest/ui": 4.1.4 + happy-dom: "*" + jsdom: "*" + vite: ^6.0.0 || ^7.0.0 || ^8.0.0 + peerDependenciesMeta: + "@edge-runtime/vm": + optional: true + "@opentelemetry/api": + optional: true + "@types/node": + optional: true + "@vitest/browser-playwright": + optional: true + "@vitest/browser-preview": + optional: true + "@vitest/browser-webdriverio": + optional: true + "@vitest/coverage-istanbul": + optional: true + "@vitest/coverage-v8": + optional: true + "@vitest/ui": + optional: true + happy-dom: + optional: true + jsdom: + optional: true + + vm-browserify@1.1.2: + resolution: + { + integrity: sha512-2ham8XPWTONajOR0ohOKOHXkm3+gaBmGut3SRuu75xLd/RRaY6vqgh8NBYYk7+RW3u5AtzPQZG8F10LHkl0lAQ==, + } + + void-elements@3.1.0: + resolution: + { + integrity: sha512-Dhxzh5HZuiHQhbvTW9AMetFfBHDMYpo23Uo9btPXgdYP+3T5S+p+jgNy7spra+veYhBP2dCSgxR/i2Y02h5/6w==, + } + engines: { node: ">=0.10.0" } + + w3c-xmlserializer@5.0.0: + resolution: + { + integrity: sha512-o8qghlI8NZHU1lLPrpi2+Uq7abh4GGPpYANlalzWxyWteJOCsr/P+oPBA49TOLu5FTZO4d3F9MnWJfiMo4BkmA==, + } + engines: { node: ">=18" } + + walk-sync@2.2.0: + resolution: + { + integrity: sha512-IC8sL7aB4/ZgFcGI2T1LczZeFWZ06b3zoHH7jBPyHxOtIIz1jppWHjjEXkOFvFojBVAK9pV7g47xOZ4LW3QLfg==, + } + engines: { node: 8.* || >= 10.* } + + walk-up-path@4.0.0: + resolution: + { + integrity: sha512-3hu+tD8YzSLGuFYtPRb48vdhKMi0KQV5sn+uWr8+7dMEq/2G/dtLrdDinkLjqq5TIbIBjYJ4Ax/n3YiaW7QM8A==, + } + engines: { node: 20 || >=22 } + + web-vitals@4.2.4: + resolution: + { + integrity: sha512-r4DIlprAGwJ7YM11VZp4R884m0Vmgr6EAKe3P+kO0PPj3Unqyvv59rczf6UiGcb9Z8QxZVcqKNwv/g0WNdWwsw==, + } + + webidl-conversions@3.0.1: + resolution: + { + integrity: sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==, + } + + webidl-conversions@7.0.0: + resolution: + { + integrity: sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==, + } + engines: { node: ">=12" } + + webpack-sources@3.3.4: + resolution: + { + integrity: sha512-7tP1PdV4vF+lYPnkMR0jMY5/la2ub5Fc/8VQrrU+lXkiM6C4TjVfGw7iKfyhnTQOsD+6Q/iKw0eFciziRgD58Q==, + } + engines: { node: ">=10.13.0" } + + webpack-virtual-modules@0.5.0: + resolution: + { + integrity: sha512-kyDivFZ7ZM0BVOUteVbDFhlRt7Ah/CSPwJdi8hBpkK7QLumUqdLtVfm/PX/hkcnrvr0i77fO5+TjZ94Pe+C9iw==, + } + + webpack-virtual-modules@0.6.2: + resolution: + { + integrity: sha512-66/V2i5hQanC51vBQKPH4aI8NMAcBW59FVBs+rC7eGHupMyfn34q7rZIE+ETlJ+XTevqfUhVVBgSUNSW2flEUQ==, + } + + webrtc-adapter@9.0.4: + resolution: + { + integrity: sha512-5ZZY1+lGq8LEKuDlg9M2RPJHlH3R7OVwyHqMcUsLKCgd9Wvf+QrFTCItkXXYPmrJn8H6gRLXbSgxLLdexiqHxw==, + } + engines: { node: ">=6.0.0", npm: ">=3.10.0" } + + whatwg-encoding@3.1.1: + resolution: + { + integrity: sha512-6qN4hJdMwfYBtE3YBTTHhoeuUrDBPZmbQaxWAqSALV/MeEnR5z1xd8UKud2RAkFoPkmB+hli1TZSnyi84xz1vQ==, + } + engines: { node: ">=18" } + deprecated: Use @exodus/bytes instead for a more spec-conformant and faster implementation + + whatwg-mimetype@4.0.0: + resolution: + { + integrity: sha512-QaKxh0eNIi2mE9p2vEdzfagOKHCcj1pJ56EEHGQOVxp8r9/iszLUUV7v89x9O1p/T+NlTM5W7jW6+cz4Fq1YVg==, + } + engines: { node: ">=18" } + + whatwg-url@14.2.0: + resolution: + { + integrity: sha512-De72GdQZzNTUBBChsXueQUnPKDkg/5A5zp7pFDuQAj5UFoENpiACU0wlCvzpAGnTkj++ihpKwKyYewn/XNUbKw==, + } + engines: { node: ">=18" } + + whatwg-url@5.0.0: + resolution: + { + integrity: sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==, + } + + which-boxed-primitive@1.1.1: + resolution: + { + integrity: sha512-TbX3mj8n0odCBFVlY8AxkqcHASw3L60jIuF8jFP78az3C2YhmGvqbHBpAjTRH2/xqYunrJ9g1jSyjCjpoWzIAA==, + } + engines: { node: ">= 0.4" } + + which-builtin-type@1.2.1: + resolution: + { + integrity: sha512-6iBczoX+kDQ7a3+YJBnh3T+KZRxM/iYNPXicqk66/Qfm1b93iu+yOImkg0zHbj5LNOcNv1TEADiZ0xa34B4q6Q==, + } + engines: { node: ">= 0.4" } + + which-collection@1.0.2: + resolution: + { + integrity: sha512-K4jVyjnBdgvc86Y6BkaLZEN933SwYOuBFkdmBu9ZfkcAbdVbpITnDmjvZ/aQjRXQrv5EPkTnD1s39GiiqbngCw==, + } + engines: { node: ">= 0.4" } + + which-module@2.0.1: + resolution: + { + integrity: sha512-iBdZ57RDvnOR9AGBhML2vFZf7h8vmBjhoaZqODJBFWHVtKkDmKuHai3cx5PgVMrX5YDNp27AofYbAwctSS+vhQ==, + } + + which-typed-array@1.1.20: + resolution: + { + integrity: sha512-LYfpUkmqwl0h9A2HL09Mms427Q1RZWuOHsukfVcKRq9q95iQxdw0ix1JQrqbcDR9PH1QDwf5Qo8OZb5lksZ8Xg==, + } + engines: { node: ">= 0.4" } + + which@2.0.2: + resolution: + { + integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==, + } + engines: { node: ">= 8" } + hasBin: true + + why-is-node-running@2.3.0: + resolution: + { + integrity: sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w==, + } + engines: { node: ">=8" } + hasBin: true + + word-wrap@1.2.5: + resolution: + { + integrity: sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==, + } + engines: { node: ">=0.10.0" } + + wrap-ansi@6.2.0: + resolution: + { + integrity: sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==, + } + engines: { node: ">=8" } + + wrap-ansi@7.0.0: + resolution: + { + integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==, + } + engines: { node: ">=10" } + + wrap-ansi@8.1.0: + resolution: + { + integrity: sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==, + } + engines: { node: ">=12" } + + wrappy@1.0.2: + resolution: + { + integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==, + } + + ws@8.20.0: + resolution: + { + integrity: sha512-sAt8BhgNbzCtgGbt2OxmpuryO63ZoDk/sqaB/znQm94T4fCEsy/yV+7CdC1kJhOU9lboAEU7R3kquuycDoibVA==, + } + engines: { node: ">=10.0.0" } + peerDependencies: + bufferutil: ^4.0.1 + utf-8-validate: ">=5.0.2" + peerDependenciesMeta: + bufferutil: + optional: true + utf-8-validate: + optional: true + + wsl-utils@0.1.0: + resolution: + { + integrity: sha512-h3Fbisa2nKGPxCpm89Hk33lBLsnaGBvctQopaBSOW/uIs6FTe1ATyAnKFJrzVs9vpGdsTe73WF3V4lIsk4Gacw==, + } + engines: { node: ">=18" } + + xml-name-validator@5.0.0: + resolution: + { + integrity: sha512-EvGK8EJ3DhaHfbRlETOWAS5pO9MZITeauHKJyb8wyajUfQUenkIg2MvLDTZ4T/TgIcm3HU0TFBgWWboAZ30UHg==, + } + engines: { node: ">=18" } + + xmlchars@2.2.0: + resolution: + { + integrity: sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==, + } + + xtend@4.0.2: + resolution: + { + integrity: sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==, + } + engines: { node: ">=0.4" } + + y18n@4.0.3: + resolution: + { + integrity: sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==, + } + + y18n@5.0.8: + resolution: + { + integrity: sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==, + } + engines: { node: ">=10" } + + yallist@3.1.1: + resolution: + { + integrity: sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==, + } + + yaml@2.8.3: + resolution: + { + integrity: sha512-AvbaCLOO2Otw/lW5bmh9d/WEdcDFdQp2Z2ZUH3pX9U2ihyUY0nvLv7J6TrWowklRGPYbB/IuIMfYgxaCPg5Bpg==, + } + engines: { node: ">= 14.6" } + hasBin: true + + yargs-parser@18.1.3: + resolution: + { + integrity: sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==, + } + engines: { node: ">=6" } + + yargs-parser@21.1.1: + resolution: + { + integrity: sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==, + } + engines: { node: ">=12" } + + yargs@15.4.1: + resolution: + { + integrity: sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==, + } + engines: { node: ">=8" } + + yargs@17.7.2: + resolution: + { + integrity: sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==, + } + engines: { node: ">=12" } + + yocto-queue@0.1.0: + resolution: + { + integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==, + } + engines: { node: ">=10" } + + zod@3.25.76: + resolution: + { + integrity: sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==, + } + + zod@4.3.6: + resolution: + { + integrity: sha512-rftlrkhHZOcjDwkGlnUtZZkvaPHCsDATp4pGpuOOMDaTdDDXF91wuVDJoWoPsKX/3YPQ5fHuF3STjcYyKr+Qhg==, + } + +snapshots: + "@actions/core@1.11.1": + dependencies: + "@actions/exec": 1.1.1 + "@actions/http-client": 2.2.3 + + "@actions/exec@1.1.1": + dependencies: + "@actions/io": 1.1.3 + + "@actions/github@6.0.1": + dependencies: + "@actions/http-client": 2.2.3 + "@octokit/core": 5.2.2 + "@octokit/plugin-paginate-rest": 9.2.2(@octokit/core@5.2.2) + "@octokit/plugin-rest-endpoint-methods": 10.4.1(@octokit/core@5.2.2) + "@octokit/request": 8.4.1 + "@octokit/request-error": 5.1.1 + undici: 5.29.0 + + "@actions/http-client@2.2.3": + dependencies: + tunnel: 0.0.6 + undici: 5.29.0 + + "@actions/io@1.1.3": {} + + "@adobe/css-tools@4.4.4": {} + + "@asamuzakjp/css-color@3.2.0": + dependencies: + "@csstools/css-calc": 2.1.4(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4) + "@csstools/css-color-parser": 3.1.0(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4) + "@csstools/css-parser-algorithms": 3.0.5(@csstools/css-tokenizer@3.0.4) + "@csstools/css-tokenizer": 3.0.4 + lru-cache: 10.4.3 + + "@babel/code-frame@7.29.0": + dependencies: + "@babel/helper-validator-identifier": 7.28.5 + js-tokens: 4.0.0 + picocolors: 1.1.1 + + "@babel/compat-data@7.29.0": {} + + "@babel/core@7.29.0": + dependencies: + "@babel/code-frame": 7.29.0 + "@babel/generator": 7.29.1 + "@babel/helper-compilation-targets": 7.28.6 + "@babel/helper-module-transforms": 7.28.6(@babel/core@7.29.0) + "@babel/helpers": 7.29.2 + "@babel/parser": 7.29.2 + "@babel/template": 7.28.6 + "@babel/traverse": 7.29.0 + "@babel/types": 7.29.0 + "@jridgewell/remapping": 2.3.5 + convert-source-map: 2.0.0 + debug: 4.4.3 + gensync: 1.0.0-beta.2 + json5: 2.2.3 + semver: 6.3.1 + transitivePeerDependencies: + - supports-color + + "@babel/eslint-parser@7.28.6(@babel/core@7.29.0)(eslint@8.57.1)": + dependencies: + "@babel/core": 7.29.0 + "@nicolo-ribaudo/eslint-scope-5-internals": 5.1.1-v1 + eslint: 8.57.1 + eslint-visitor-keys: 2.1.0 + semver: 6.3.1 + + "@babel/eslint-plugin@7.27.1(@babel/eslint-parser@7.28.6(@babel/core@7.29.0)(eslint@8.57.1))(eslint@8.57.1)": + dependencies: + "@babel/eslint-parser": 7.28.6(@babel/core@7.29.0)(eslint@8.57.1) + eslint: 8.57.1 + eslint-rule-composer: 0.3.0 + + "@babel/generator@7.29.1": + dependencies: + "@babel/parser": 7.29.2 + "@babel/types": 7.29.0 + "@jridgewell/gen-mapping": 0.3.13 + "@jridgewell/trace-mapping": 0.3.31 + jsesc: 3.1.0 + + "@babel/helper-annotate-as-pure@7.27.3": + dependencies: + "@babel/types": 7.29.0 + + "@babel/helper-compilation-targets@7.28.6": + dependencies: + "@babel/compat-data": 7.29.0 + "@babel/helper-validator-option": 7.27.1 + browserslist: 4.28.2 + lru-cache: 5.1.1 + semver: 6.3.1 + + "@babel/helper-create-class-features-plugin@7.28.6(@babel/core@7.29.0)": + dependencies: + "@babel/core": 7.29.0 + "@babel/helper-annotate-as-pure": 7.27.3 + "@babel/helper-member-expression-to-functions": 7.28.5 + "@babel/helper-optimise-call-expression": 7.27.1 + "@babel/helper-replace-supers": 7.28.6(@babel/core@7.29.0) + "@babel/helper-skip-transparent-expression-wrappers": 7.27.1 + "@babel/traverse": 7.29.0 + semver: 6.3.1 + transitivePeerDependencies: + - supports-color + + "@babel/helper-create-regexp-features-plugin@7.28.5(@babel/core@7.29.0)": + dependencies: + "@babel/core": 7.29.0 + "@babel/helper-annotate-as-pure": 7.27.3 + regexpu-core: 6.4.0 + semver: 6.3.1 + + "@babel/helper-define-polyfill-provider@0.6.8(@babel/core@7.29.0)": + dependencies: + "@babel/core": 7.29.0 + "@babel/helper-compilation-targets": 7.28.6 + "@babel/helper-plugin-utils": 7.28.6 + debug: 4.4.3 + lodash.debounce: 4.0.8 + resolve: 1.22.12 + transitivePeerDependencies: + - supports-color + + "@babel/helper-globals@7.28.0": {} + + "@babel/helper-member-expression-to-functions@7.28.5": + dependencies: + "@babel/traverse": 7.29.0 + "@babel/types": 7.29.0 + transitivePeerDependencies: + - supports-color + + "@babel/helper-module-imports@7.28.6": + dependencies: + "@babel/traverse": 7.29.0 + "@babel/types": 7.29.0 + transitivePeerDependencies: + - supports-color + + "@babel/helper-module-transforms@7.28.6(@babel/core@7.29.0)": + dependencies: + "@babel/core": 7.29.0 + "@babel/helper-module-imports": 7.28.6 + "@babel/helper-validator-identifier": 7.28.5 + "@babel/traverse": 7.29.0 + transitivePeerDependencies: + - supports-color + + "@babel/helper-optimise-call-expression@7.27.1": + dependencies: + "@babel/types": 7.29.0 + + "@babel/helper-plugin-utils@7.28.6": {} + + "@babel/helper-remap-async-to-generator@7.27.1(@babel/core@7.29.0)": + dependencies: + "@babel/core": 7.29.0 + "@babel/helper-annotate-as-pure": 7.27.3 + "@babel/helper-wrap-function": 7.28.6 + "@babel/traverse": 7.29.0 + transitivePeerDependencies: + - supports-color + + "@babel/helper-replace-supers@7.28.6(@babel/core@7.29.0)": + dependencies: + "@babel/core": 7.29.0 + "@babel/helper-member-expression-to-functions": 7.28.5 + "@babel/helper-optimise-call-expression": 7.27.1 + "@babel/traverse": 7.29.0 + transitivePeerDependencies: + - supports-color + + "@babel/helper-skip-transparent-expression-wrappers@7.27.1": + dependencies: + "@babel/traverse": 7.29.0 + "@babel/types": 7.29.0 + transitivePeerDependencies: + - supports-color + + "@babel/helper-string-parser@7.27.1": {} + + "@babel/helper-validator-identifier@7.28.5": {} + + "@babel/helper-validator-option@7.27.1": {} + + "@babel/helper-wrap-function@7.28.6": + dependencies: + "@babel/template": 7.28.6 + "@babel/traverse": 7.29.0 + "@babel/types": 7.29.0 + transitivePeerDependencies: + - supports-color + + "@babel/helpers@7.29.2": + dependencies: + "@babel/template": 7.28.6 + "@babel/types": 7.29.0 + + "@babel/parser@7.29.2": + dependencies: + "@babel/types": 7.29.0 + + "@babel/plugin-bugfix-firefox-class-in-computed-class-key@7.28.5(@babel/core@7.29.0)": + dependencies: + "@babel/core": 7.29.0 + "@babel/helper-plugin-utils": 7.28.6 + "@babel/traverse": 7.29.0 + transitivePeerDependencies: + - supports-color + + "@babel/plugin-bugfix-safari-class-field-initializer-scope@7.27.1(@babel/core@7.29.0)": + dependencies: + "@babel/core": 7.29.0 + "@babel/helper-plugin-utils": 7.28.6 + + "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@7.27.1(@babel/core@7.29.0)": + dependencies: + "@babel/core": 7.29.0 + "@babel/helper-plugin-utils": 7.28.6 + + "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@7.27.1(@babel/core@7.29.0)": + dependencies: + "@babel/core": 7.29.0 + "@babel/helper-plugin-utils": 7.28.6 + "@babel/helper-skip-transparent-expression-wrappers": 7.27.1 + "@babel/plugin-transform-optional-chaining": 7.28.6(@babel/core@7.29.0) + transitivePeerDependencies: + - supports-color + + "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly@7.28.6(@babel/core@7.29.0)": + dependencies: + "@babel/core": 7.29.0 + "@babel/helper-plugin-utils": 7.28.6 + "@babel/traverse": 7.29.0 + transitivePeerDependencies: + - supports-color + + "@babel/plugin-proposal-private-property-in-object@7.21.0-placeholder-for-preset-env.2(@babel/core@7.29.0)": + dependencies: + "@babel/core": 7.29.0 + + "@babel/plugin-syntax-import-assertions@7.28.6(@babel/core@7.29.0)": + dependencies: + "@babel/core": 7.29.0 + "@babel/helper-plugin-utils": 7.28.6 + + "@babel/plugin-syntax-import-attributes@7.28.6(@babel/core@7.29.0)": + dependencies: + "@babel/core": 7.29.0 + "@babel/helper-plugin-utils": 7.28.6 + + "@babel/plugin-syntax-jsx@7.28.6(@babel/core@7.29.0)": + dependencies: + "@babel/core": 7.29.0 + "@babel/helper-plugin-utils": 7.28.6 + + "@babel/plugin-syntax-typescript@7.28.6(@babel/core@7.29.0)": + dependencies: + "@babel/core": 7.29.0 + "@babel/helper-plugin-utils": 7.28.6 + + "@babel/plugin-syntax-unicode-sets-regex@7.18.6(@babel/core@7.29.0)": + dependencies: + "@babel/core": 7.29.0 + "@babel/helper-create-regexp-features-plugin": 7.28.5(@babel/core@7.29.0) + "@babel/helper-plugin-utils": 7.28.6 + + "@babel/plugin-transform-arrow-functions@7.27.1(@babel/core@7.29.0)": + dependencies: + "@babel/core": 7.29.0 + "@babel/helper-plugin-utils": 7.28.6 + + "@babel/plugin-transform-async-generator-functions@7.29.0(@babel/core@7.29.0)": + dependencies: + "@babel/core": 7.29.0 + "@babel/helper-plugin-utils": 7.28.6 + "@babel/helper-remap-async-to-generator": 7.27.1(@babel/core@7.29.0) + "@babel/traverse": 7.29.0 + transitivePeerDependencies: + - supports-color + + "@babel/plugin-transform-async-to-generator@7.28.6(@babel/core@7.29.0)": + dependencies: + "@babel/core": 7.29.0 + "@babel/helper-module-imports": 7.28.6 + "@babel/helper-plugin-utils": 7.28.6 + "@babel/helper-remap-async-to-generator": 7.27.1(@babel/core@7.29.0) + transitivePeerDependencies: + - supports-color + + "@babel/plugin-transform-block-scoped-functions@7.27.1(@babel/core@7.29.0)": + dependencies: + "@babel/core": 7.29.0 + "@babel/helper-plugin-utils": 7.28.6 + + "@babel/plugin-transform-block-scoping@7.28.6(@babel/core@7.29.0)": + dependencies: + "@babel/core": 7.29.0 + "@babel/helper-plugin-utils": 7.28.6 + + "@babel/plugin-transform-class-properties@7.28.6(@babel/core@7.29.0)": + dependencies: + "@babel/core": 7.29.0 + "@babel/helper-create-class-features-plugin": 7.28.6(@babel/core@7.29.0) + "@babel/helper-plugin-utils": 7.28.6 + transitivePeerDependencies: + - supports-color + + "@babel/plugin-transform-class-static-block@7.28.6(@babel/core@7.29.0)": + dependencies: + "@babel/core": 7.29.0 + "@babel/helper-create-class-features-plugin": 7.28.6(@babel/core@7.29.0) + "@babel/helper-plugin-utils": 7.28.6 + transitivePeerDependencies: + - supports-color + + "@babel/plugin-transform-classes@7.28.6(@babel/core@7.29.0)": + dependencies: + "@babel/core": 7.29.0 + "@babel/helper-annotate-as-pure": 7.27.3 + "@babel/helper-compilation-targets": 7.28.6 + "@babel/helper-globals": 7.28.0 + "@babel/helper-plugin-utils": 7.28.6 + "@babel/helper-replace-supers": 7.28.6(@babel/core@7.29.0) + "@babel/traverse": 7.29.0 + transitivePeerDependencies: + - supports-color + + "@babel/plugin-transform-computed-properties@7.28.6(@babel/core@7.29.0)": + dependencies: + "@babel/core": 7.29.0 + "@babel/helper-plugin-utils": 7.28.6 + "@babel/template": 7.28.6 + + "@babel/plugin-transform-destructuring@7.28.5(@babel/core@7.29.0)": + dependencies: + "@babel/core": 7.29.0 + "@babel/helper-plugin-utils": 7.28.6 + "@babel/traverse": 7.29.0 + transitivePeerDependencies: + - supports-color + + "@babel/plugin-transform-dotall-regex@7.28.6(@babel/core@7.29.0)": + dependencies: + "@babel/core": 7.29.0 + "@babel/helper-create-regexp-features-plugin": 7.28.5(@babel/core@7.29.0) + "@babel/helper-plugin-utils": 7.28.6 + + "@babel/plugin-transform-duplicate-keys@7.27.1(@babel/core@7.29.0)": + dependencies: + "@babel/core": 7.29.0 + "@babel/helper-plugin-utils": 7.28.6 + + "@babel/plugin-transform-duplicate-named-capturing-groups-regex@7.29.0(@babel/core@7.29.0)": + dependencies: + "@babel/core": 7.29.0 + "@babel/helper-create-regexp-features-plugin": 7.28.5(@babel/core@7.29.0) + "@babel/helper-plugin-utils": 7.28.6 + + "@babel/plugin-transform-dynamic-import@7.27.1(@babel/core@7.29.0)": + dependencies: + "@babel/core": 7.29.0 + "@babel/helper-plugin-utils": 7.28.6 + + "@babel/plugin-transform-explicit-resource-management@7.28.6(@babel/core@7.29.0)": + dependencies: + "@babel/core": 7.29.0 + "@babel/helper-plugin-utils": 7.28.6 + "@babel/plugin-transform-destructuring": 7.28.5(@babel/core@7.29.0) + transitivePeerDependencies: + - supports-color + + "@babel/plugin-transform-exponentiation-operator@7.28.6(@babel/core@7.29.0)": + dependencies: + "@babel/core": 7.29.0 + "@babel/helper-plugin-utils": 7.28.6 + + "@babel/plugin-transform-export-namespace-from@7.27.1(@babel/core@7.29.0)": + dependencies: + "@babel/core": 7.29.0 + "@babel/helper-plugin-utils": 7.28.6 + + "@babel/plugin-transform-for-of@7.27.1(@babel/core@7.29.0)": + dependencies: + "@babel/core": 7.29.0 + "@babel/helper-plugin-utils": 7.28.6 + "@babel/helper-skip-transparent-expression-wrappers": 7.27.1 + transitivePeerDependencies: + - supports-color + + "@babel/plugin-transform-function-name@7.27.1(@babel/core@7.29.0)": + dependencies: + "@babel/core": 7.29.0 + "@babel/helper-compilation-targets": 7.28.6 + "@babel/helper-plugin-utils": 7.28.6 + "@babel/traverse": 7.29.0 + transitivePeerDependencies: + - supports-color + + "@babel/plugin-transform-json-strings@7.28.6(@babel/core@7.29.0)": + dependencies: + "@babel/core": 7.29.0 + "@babel/helper-plugin-utils": 7.28.6 + + "@babel/plugin-transform-literals@7.27.1(@babel/core@7.29.0)": + dependencies: + "@babel/core": 7.29.0 + "@babel/helper-plugin-utils": 7.28.6 + + "@babel/plugin-transform-logical-assignment-operators@7.28.6(@babel/core@7.29.0)": + dependencies: + "@babel/core": 7.29.0 + "@babel/helper-plugin-utils": 7.28.6 + + "@babel/plugin-transform-member-expression-literals@7.27.1(@babel/core@7.29.0)": + dependencies: + "@babel/core": 7.29.0 + "@babel/helper-plugin-utils": 7.28.6 + + "@babel/plugin-transform-modules-amd@7.27.1(@babel/core@7.29.0)": + dependencies: + "@babel/core": 7.29.0 + "@babel/helper-module-transforms": 7.28.6(@babel/core@7.29.0) + "@babel/helper-plugin-utils": 7.28.6 + transitivePeerDependencies: + - supports-color + + "@babel/plugin-transform-modules-commonjs@7.28.6(@babel/core@7.29.0)": + dependencies: + "@babel/core": 7.29.0 + "@babel/helper-module-transforms": 7.28.6(@babel/core@7.29.0) + "@babel/helper-plugin-utils": 7.28.6 + transitivePeerDependencies: + - supports-color + + "@babel/plugin-transform-modules-systemjs@7.29.0(@babel/core@7.29.0)": + dependencies: + "@babel/core": 7.29.0 + "@babel/helper-module-transforms": 7.28.6(@babel/core@7.29.0) + "@babel/helper-plugin-utils": 7.28.6 + "@babel/helper-validator-identifier": 7.28.5 + "@babel/traverse": 7.29.0 + transitivePeerDependencies: + - supports-color + + "@babel/plugin-transform-modules-umd@7.27.1(@babel/core@7.29.0)": + dependencies: + "@babel/core": 7.29.0 + "@babel/helper-module-transforms": 7.28.6(@babel/core@7.29.0) + "@babel/helper-plugin-utils": 7.28.6 + transitivePeerDependencies: + - supports-color + + "@babel/plugin-transform-named-capturing-groups-regex@7.29.0(@babel/core@7.29.0)": + dependencies: + "@babel/core": 7.29.0 + "@babel/helper-create-regexp-features-plugin": 7.28.5(@babel/core@7.29.0) + "@babel/helper-plugin-utils": 7.28.6 + + "@babel/plugin-transform-new-target@7.27.1(@babel/core@7.29.0)": + dependencies: + "@babel/core": 7.29.0 + "@babel/helper-plugin-utils": 7.28.6 + + "@babel/plugin-transform-nullish-coalescing-operator@7.28.6(@babel/core@7.29.0)": + dependencies: + "@babel/core": 7.29.0 + "@babel/helper-plugin-utils": 7.28.6 + + "@babel/plugin-transform-numeric-separator@7.28.6(@babel/core@7.29.0)": + dependencies: + "@babel/core": 7.29.0 + "@babel/helper-plugin-utils": 7.28.6 + + "@babel/plugin-transform-object-rest-spread@7.28.6(@babel/core@7.29.0)": + dependencies: + "@babel/core": 7.29.0 + "@babel/helper-compilation-targets": 7.28.6 + "@babel/helper-plugin-utils": 7.28.6 + "@babel/plugin-transform-destructuring": 7.28.5(@babel/core@7.29.0) + "@babel/plugin-transform-parameters": 7.27.7(@babel/core@7.29.0) + "@babel/traverse": 7.29.0 + transitivePeerDependencies: + - supports-color + + "@babel/plugin-transform-object-super@7.27.1(@babel/core@7.29.0)": + dependencies: + "@babel/core": 7.29.0 + "@babel/helper-plugin-utils": 7.28.6 + "@babel/helper-replace-supers": 7.28.6(@babel/core@7.29.0) + transitivePeerDependencies: + - supports-color + + "@babel/plugin-transform-optional-catch-binding@7.28.6(@babel/core@7.29.0)": + dependencies: + "@babel/core": 7.29.0 + "@babel/helper-plugin-utils": 7.28.6 + + "@babel/plugin-transform-optional-chaining@7.28.6(@babel/core@7.29.0)": + dependencies: + "@babel/core": 7.29.0 + "@babel/helper-plugin-utils": 7.28.6 + "@babel/helper-skip-transparent-expression-wrappers": 7.27.1 + transitivePeerDependencies: + - supports-color + + "@babel/plugin-transform-parameters@7.27.7(@babel/core@7.29.0)": + dependencies: + "@babel/core": 7.29.0 + "@babel/helper-plugin-utils": 7.28.6 + + "@babel/plugin-transform-private-methods@7.28.6(@babel/core@7.29.0)": + dependencies: + "@babel/core": 7.29.0 + "@babel/helper-create-class-features-plugin": 7.28.6(@babel/core@7.29.0) + "@babel/helper-plugin-utils": 7.28.6 + transitivePeerDependencies: + - supports-color + + "@babel/plugin-transform-private-property-in-object@7.28.6(@babel/core@7.29.0)": + dependencies: + "@babel/core": 7.29.0 + "@babel/helper-annotate-as-pure": 7.27.3 + "@babel/helper-create-class-features-plugin": 7.28.6(@babel/core@7.29.0) + "@babel/helper-plugin-utils": 7.28.6 + transitivePeerDependencies: + - supports-color + + "@babel/plugin-transform-property-literals@7.27.1(@babel/core@7.29.0)": + dependencies: + "@babel/core": 7.29.0 + "@babel/helper-plugin-utils": 7.28.6 + + "@babel/plugin-transform-react-display-name@7.28.0(@babel/core@7.29.0)": + dependencies: + "@babel/core": 7.29.0 + "@babel/helper-plugin-utils": 7.28.6 + + "@babel/plugin-transform-react-jsx-development@7.27.1(@babel/core@7.29.0)": + dependencies: + "@babel/core": 7.29.0 + "@babel/plugin-transform-react-jsx": 7.28.6(@babel/core@7.29.0) + transitivePeerDependencies: + - supports-color + + "@babel/plugin-transform-react-jsx-self@7.27.1(@babel/core@7.29.0)": + dependencies: + "@babel/core": 7.29.0 + "@babel/helper-plugin-utils": 7.28.6 + + "@babel/plugin-transform-react-jsx-source@7.27.1(@babel/core@7.29.0)": + dependencies: + "@babel/core": 7.29.0 + "@babel/helper-plugin-utils": 7.28.6 + + "@babel/plugin-transform-react-jsx@7.28.6(@babel/core@7.29.0)": + dependencies: + "@babel/core": 7.29.0 + "@babel/helper-annotate-as-pure": 7.27.3 + "@babel/helper-module-imports": 7.28.6 + "@babel/helper-plugin-utils": 7.28.6 + "@babel/plugin-syntax-jsx": 7.28.6(@babel/core@7.29.0) + "@babel/types": 7.29.0 + transitivePeerDependencies: + - supports-color + + "@babel/plugin-transform-react-pure-annotations@7.27.1(@babel/core@7.29.0)": + dependencies: + "@babel/core": 7.29.0 + "@babel/helper-annotate-as-pure": 7.27.3 + "@babel/helper-plugin-utils": 7.28.6 + + "@babel/plugin-transform-regenerator@7.29.0(@babel/core@7.29.0)": + dependencies: + "@babel/core": 7.29.0 + "@babel/helper-plugin-utils": 7.28.6 + + "@babel/plugin-transform-regexp-modifiers@7.28.6(@babel/core@7.29.0)": + dependencies: + "@babel/core": 7.29.0 + "@babel/helper-create-regexp-features-plugin": 7.28.5(@babel/core@7.29.0) + "@babel/helper-plugin-utils": 7.28.6 + + "@babel/plugin-transform-reserved-words@7.27.1(@babel/core@7.29.0)": + dependencies: + "@babel/core": 7.29.0 + "@babel/helper-plugin-utils": 7.28.6 + + "@babel/plugin-transform-shorthand-properties@7.27.1(@babel/core@7.29.0)": + dependencies: + "@babel/core": 7.29.0 + "@babel/helper-plugin-utils": 7.28.6 + + "@babel/plugin-transform-spread@7.28.6(@babel/core@7.29.0)": + dependencies: + "@babel/core": 7.29.0 + "@babel/helper-plugin-utils": 7.28.6 + "@babel/helper-skip-transparent-expression-wrappers": 7.27.1 + transitivePeerDependencies: + - supports-color + + "@babel/plugin-transform-sticky-regex@7.27.1(@babel/core@7.29.0)": + dependencies: + "@babel/core": 7.29.0 + "@babel/helper-plugin-utils": 7.28.6 + + "@babel/plugin-transform-template-literals@7.27.1(@babel/core@7.29.0)": + dependencies: + "@babel/core": 7.29.0 + "@babel/helper-plugin-utils": 7.28.6 + + "@babel/plugin-transform-typeof-symbol@7.27.1(@babel/core@7.29.0)": + dependencies: + "@babel/core": 7.29.0 + "@babel/helper-plugin-utils": 7.28.6 + + "@babel/plugin-transform-typescript@7.28.6(@babel/core@7.29.0)": + dependencies: + "@babel/core": 7.29.0 + "@babel/helper-annotate-as-pure": 7.27.3 + "@babel/helper-create-class-features-plugin": 7.28.6(@babel/core@7.29.0) + "@babel/helper-plugin-utils": 7.28.6 + "@babel/helper-skip-transparent-expression-wrappers": 7.27.1 + "@babel/plugin-syntax-typescript": 7.28.6(@babel/core@7.29.0) + transitivePeerDependencies: + - supports-color + + "@babel/plugin-transform-unicode-escapes@7.27.1(@babel/core@7.29.0)": + dependencies: + "@babel/core": 7.29.0 + "@babel/helper-plugin-utils": 7.28.6 + + "@babel/plugin-transform-unicode-property-regex@7.28.6(@babel/core@7.29.0)": + dependencies: + "@babel/core": 7.29.0 + "@babel/helper-create-regexp-features-plugin": 7.28.5(@babel/core@7.29.0) + "@babel/helper-plugin-utils": 7.28.6 + + "@babel/plugin-transform-unicode-regex@7.27.1(@babel/core@7.29.0)": + dependencies: + "@babel/core": 7.29.0 + "@babel/helper-create-regexp-features-plugin": 7.28.5(@babel/core@7.29.0) + "@babel/helper-plugin-utils": 7.28.6 + + "@babel/plugin-transform-unicode-sets-regex@7.28.6(@babel/core@7.29.0)": + dependencies: + "@babel/core": 7.29.0 + "@babel/helper-create-regexp-features-plugin": 7.28.5(@babel/core@7.29.0) + "@babel/helper-plugin-utils": 7.28.6 + + "@babel/preset-env@7.29.2(@babel/core@7.29.0)": + dependencies: + "@babel/compat-data": 7.29.0 + "@babel/core": 7.29.0 + "@babel/helper-compilation-targets": 7.28.6 + "@babel/helper-plugin-utils": 7.28.6 + "@babel/helper-validator-option": 7.27.1 + "@babel/plugin-bugfix-firefox-class-in-computed-class-key": 7.28.5(@babel/core@7.29.0) + "@babel/plugin-bugfix-safari-class-field-initializer-scope": 7.27.1(@babel/core@7.29.0) + "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": 7.27.1(@babel/core@7.29.0) + "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": 7.27.1(@babel/core@7.29.0) + "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": 7.28.6(@babel/core@7.29.0) + "@babel/plugin-proposal-private-property-in-object": 7.21.0-placeholder-for-preset-env.2(@babel/core@7.29.0) + "@babel/plugin-syntax-import-assertions": 7.28.6(@babel/core@7.29.0) + "@babel/plugin-syntax-import-attributes": 7.28.6(@babel/core@7.29.0) + "@babel/plugin-syntax-unicode-sets-regex": 7.18.6(@babel/core@7.29.0) + "@babel/plugin-transform-arrow-functions": 7.27.1(@babel/core@7.29.0) + "@babel/plugin-transform-async-generator-functions": 7.29.0(@babel/core@7.29.0) + "@babel/plugin-transform-async-to-generator": 7.28.6(@babel/core@7.29.0) + "@babel/plugin-transform-block-scoped-functions": 7.27.1(@babel/core@7.29.0) + "@babel/plugin-transform-block-scoping": 7.28.6(@babel/core@7.29.0) + "@babel/plugin-transform-class-properties": 7.28.6(@babel/core@7.29.0) + "@babel/plugin-transform-class-static-block": 7.28.6(@babel/core@7.29.0) + "@babel/plugin-transform-classes": 7.28.6(@babel/core@7.29.0) + "@babel/plugin-transform-computed-properties": 7.28.6(@babel/core@7.29.0) + "@babel/plugin-transform-destructuring": 7.28.5(@babel/core@7.29.0) + "@babel/plugin-transform-dotall-regex": 7.28.6(@babel/core@7.29.0) + "@babel/plugin-transform-duplicate-keys": 7.27.1(@babel/core@7.29.0) + "@babel/plugin-transform-duplicate-named-capturing-groups-regex": 7.29.0(@babel/core@7.29.0) + "@babel/plugin-transform-dynamic-import": 7.27.1(@babel/core@7.29.0) + "@babel/plugin-transform-explicit-resource-management": 7.28.6(@babel/core@7.29.0) + "@babel/plugin-transform-exponentiation-operator": 7.28.6(@babel/core@7.29.0) + "@babel/plugin-transform-export-namespace-from": 7.27.1(@babel/core@7.29.0) + "@babel/plugin-transform-for-of": 7.27.1(@babel/core@7.29.0) + "@babel/plugin-transform-function-name": 7.27.1(@babel/core@7.29.0) + "@babel/plugin-transform-json-strings": 7.28.6(@babel/core@7.29.0) + "@babel/plugin-transform-literals": 7.27.1(@babel/core@7.29.0) + "@babel/plugin-transform-logical-assignment-operators": 7.28.6(@babel/core@7.29.0) + "@babel/plugin-transform-member-expression-literals": 7.27.1(@babel/core@7.29.0) + "@babel/plugin-transform-modules-amd": 7.27.1(@babel/core@7.29.0) + "@babel/plugin-transform-modules-commonjs": 7.28.6(@babel/core@7.29.0) + "@babel/plugin-transform-modules-systemjs": 7.29.0(@babel/core@7.29.0) + "@babel/plugin-transform-modules-umd": 7.27.1(@babel/core@7.29.0) + "@babel/plugin-transform-named-capturing-groups-regex": 7.29.0(@babel/core@7.29.0) + "@babel/plugin-transform-new-target": 7.27.1(@babel/core@7.29.0) + "@babel/plugin-transform-nullish-coalescing-operator": 7.28.6(@babel/core@7.29.0) + "@babel/plugin-transform-numeric-separator": 7.28.6(@babel/core@7.29.0) + "@babel/plugin-transform-object-rest-spread": 7.28.6(@babel/core@7.29.0) + "@babel/plugin-transform-object-super": 7.27.1(@babel/core@7.29.0) + "@babel/plugin-transform-optional-catch-binding": 7.28.6(@babel/core@7.29.0) + "@babel/plugin-transform-optional-chaining": 7.28.6(@babel/core@7.29.0) + "@babel/plugin-transform-parameters": 7.27.7(@babel/core@7.29.0) + "@babel/plugin-transform-private-methods": 7.28.6(@babel/core@7.29.0) + "@babel/plugin-transform-private-property-in-object": 7.28.6(@babel/core@7.29.0) + "@babel/plugin-transform-property-literals": 7.27.1(@babel/core@7.29.0) + "@babel/plugin-transform-regenerator": 7.29.0(@babel/core@7.29.0) + "@babel/plugin-transform-regexp-modifiers": 7.28.6(@babel/core@7.29.0) + "@babel/plugin-transform-reserved-words": 7.27.1(@babel/core@7.29.0) + "@babel/plugin-transform-shorthand-properties": 7.27.1(@babel/core@7.29.0) + "@babel/plugin-transform-spread": 7.28.6(@babel/core@7.29.0) + "@babel/plugin-transform-sticky-regex": 7.27.1(@babel/core@7.29.0) + "@babel/plugin-transform-template-literals": 7.27.1(@babel/core@7.29.0) + "@babel/plugin-transform-typeof-symbol": 7.27.1(@babel/core@7.29.0) + "@babel/plugin-transform-unicode-escapes": 7.27.1(@babel/core@7.29.0) + "@babel/plugin-transform-unicode-property-regex": 7.28.6(@babel/core@7.29.0) + "@babel/plugin-transform-unicode-regex": 7.27.1(@babel/core@7.29.0) + "@babel/plugin-transform-unicode-sets-regex": 7.28.6(@babel/core@7.29.0) + "@babel/preset-modules": 0.1.6-no-external-plugins(@babel/core@7.29.0) + babel-plugin-polyfill-corejs2: 0.4.17(@babel/core@7.29.0) + babel-plugin-polyfill-corejs3: 0.14.2(@babel/core@7.29.0) + babel-plugin-polyfill-regenerator: 0.6.8(@babel/core@7.29.0) + core-js-compat: 3.49.0 + semver: 6.3.1 + transitivePeerDependencies: + - supports-color + + "@babel/preset-modules@0.1.6-no-external-plugins(@babel/core@7.29.0)": + dependencies: + "@babel/core": 7.29.0 + "@babel/helper-plugin-utils": 7.28.6 + "@babel/types": 7.29.0 + esutils: 2.0.3 + + "@babel/preset-react@7.28.5(@babel/core@7.29.0)": + dependencies: + "@babel/core": 7.29.0 + "@babel/helper-plugin-utils": 7.28.6 + "@babel/helper-validator-option": 7.27.1 + "@babel/plugin-transform-react-display-name": 7.28.0(@babel/core@7.29.0) + "@babel/plugin-transform-react-jsx": 7.28.6(@babel/core@7.29.0) + "@babel/plugin-transform-react-jsx-development": 7.27.1(@babel/core@7.29.0) + "@babel/plugin-transform-react-pure-annotations": 7.27.1(@babel/core@7.29.0) + transitivePeerDependencies: + - supports-color + + "@babel/preset-typescript@7.28.5(@babel/core@7.29.0)": + dependencies: + "@babel/core": 7.29.0 + "@babel/helper-plugin-utils": 7.28.6 + "@babel/helper-validator-option": 7.27.1 + "@babel/plugin-syntax-jsx": 7.28.6(@babel/core@7.29.0) + "@babel/plugin-transform-modules-commonjs": 7.28.6(@babel/core@7.29.0) + "@babel/plugin-transform-typescript": 7.28.6(@babel/core@7.29.0) + transitivePeerDependencies: + - supports-color + + "@babel/runtime@7.29.2": {} + + "@babel/template@7.28.6": + dependencies: + "@babel/code-frame": 7.29.0 + "@babel/parser": 7.29.2 + "@babel/types": 7.29.0 + + "@babel/traverse@7.29.0": + dependencies: + "@babel/code-frame": 7.29.0 + "@babel/generator": 7.29.1 + "@babel/helper-globals": 7.28.0 + "@babel/parser": 7.29.2 + "@babel/template": 7.28.6 + "@babel/types": 7.29.0 + debug: 4.4.3 + transitivePeerDependencies: + - supports-color + + "@babel/types@7.29.0": + dependencies: + "@babel/helper-string-parser": 7.27.1 + "@babel/helper-validator-identifier": 7.28.5 + + "@bcoe/v8-coverage@1.0.2": {} + + "@bufbuild/protobuf@1.10.1": {} + + "@codecov/bundler-plugin-core@1.9.1": + dependencies: + "@actions/core": 1.11.1 + "@actions/github": 6.0.1 + chalk: 4.1.2 + semver: 7.7.4 + unplugin: 1.16.1 + zod: 3.25.76 + + "@codecov/vite-plugin@1.9.1(vite@8.0.8(@types/node@24.12.2)(esbuild@0.27.7)(jiti@2.6.1)(sass@1.99.0)(terser@5.46.1)(yaml@2.8.3))": + dependencies: + "@codecov/bundler-plugin-core": 1.9.1 + unplugin: 1.16.1 + vite: 8.0.8(@types/node@24.12.2)(esbuild@0.27.7)(jiti@2.6.1)(sass@1.99.0)(terser@5.46.1)(yaml@2.8.3) + + "@csstools/cascade-layer-name-parser@2.0.5(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4)": + dependencies: + "@csstools/css-parser-algorithms": 3.0.5(@csstools/css-tokenizer@3.0.4) + "@csstools/css-tokenizer": 3.0.4 + + "@csstools/color-helpers@5.1.0": {} + + "@csstools/css-calc@2.1.4(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4)": + dependencies: + "@csstools/css-parser-algorithms": 3.0.5(@csstools/css-tokenizer@3.0.4) + "@csstools/css-tokenizer": 3.0.4 + + "@csstools/css-color-parser@3.1.0(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4)": + dependencies: + "@csstools/color-helpers": 5.1.0 + "@csstools/css-calc": 2.1.4(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4) + "@csstools/css-parser-algorithms": 3.0.5(@csstools/css-tokenizer@3.0.4) + "@csstools/css-tokenizer": 3.0.4 + + "@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4)": + dependencies: + "@csstools/css-tokenizer": 3.0.4 + + "@csstools/css-tokenizer@3.0.4": {} + + "@csstools/media-query-list-parser@4.0.3(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4)": + dependencies: + "@csstools/css-parser-algorithms": 3.0.5(@csstools/css-tokenizer@3.0.4) + "@csstools/css-tokenizer": 3.0.4 + + "@csstools/postcss-alpha-function@1.0.1(postcss@8.5.10)": + dependencies: + "@csstools/css-color-parser": 3.1.0(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4) + "@csstools/css-parser-algorithms": 3.0.5(@csstools/css-tokenizer@3.0.4) + "@csstools/css-tokenizer": 3.0.4 + "@csstools/postcss-progressive-custom-properties": 4.2.1(postcss@8.5.10) + "@csstools/utilities": 2.0.0(postcss@8.5.10) + postcss: 8.5.10 + + "@csstools/postcss-cascade-layers@5.0.2(postcss@8.5.10)": + dependencies: + "@csstools/selector-specificity": 5.0.0(postcss-selector-parser@7.1.1) + postcss: 8.5.10 + postcss-selector-parser: 7.1.1 + + "@csstools/postcss-color-function-display-p3-linear@1.0.1(postcss@8.5.10)": + dependencies: + "@csstools/css-color-parser": 3.1.0(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4) + "@csstools/css-parser-algorithms": 3.0.5(@csstools/css-tokenizer@3.0.4) + "@csstools/css-tokenizer": 3.0.4 + "@csstools/postcss-progressive-custom-properties": 4.2.1(postcss@8.5.10) + "@csstools/utilities": 2.0.0(postcss@8.5.10) + postcss: 8.5.10 + + "@csstools/postcss-color-function@4.0.12(postcss@8.5.10)": + dependencies: + "@csstools/css-color-parser": 3.1.0(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4) + "@csstools/css-parser-algorithms": 3.0.5(@csstools/css-tokenizer@3.0.4) + "@csstools/css-tokenizer": 3.0.4 + "@csstools/postcss-progressive-custom-properties": 4.2.1(postcss@8.5.10) + "@csstools/utilities": 2.0.0(postcss@8.5.10) + postcss: 8.5.10 + + "@csstools/postcss-color-mix-function@3.0.12(postcss@8.5.10)": + dependencies: + "@csstools/css-color-parser": 3.1.0(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4) + "@csstools/css-parser-algorithms": 3.0.5(@csstools/css-tokenizer@3.0.4) + "@csstools/css-tokenizer": 3.0.4 + "@csstools/postcss-progressive-custom-properties": 4.2.1(postcss@8.5.10) + "@csstools/utilities": 2.0.0(postcss@8.5.10) + postcss: 8.5.10 + + "@csstools/postcss-color-mix-variadic-function-arguments@1.0.2(postcss@8.5.10)": + dependencies: + "@csstools/css-color-parser": 3.1.0(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4) + "@csstools/css-parser-algorithms": 3.0.5(@csstools/css-tokenizer@3.0.4) + "@csstools/css-tokenizer": 3.0.4 + "@csstools/postcss-progressive-custom-properties": 4.2.1(postcss@8.5.10) + "@csstools/utilities": 2.0.0(postcss@8.5.10) + postcss: 8.5.10 + + "@csstools/postcss-content-alt-text@2.0.8(postcss@8.5.10)": + dependencies: + "@csstools/css-parser-algorithms": 3.0.5(@csstools/css-tokenizer@3.0.4) + "@csstools/css-tokenizer": 3.0.4 + "@csstools/postcss-progressive-custom-properties": 4.2.1(postcss@8.5.10) + "@csstools/utilities": 2.0.0(postcss@8.5.10) + postcss: 8.5.10 + + "@csstools/postcss-contrast-color-function@2.0.12(postcss@8.5.10)": + dependencies: + "@csstools/css-color-parser": 3.1.0(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4) + "@csstools/css-parser-algorithms": 3.0.5(@csstools/css-tokenizer@3.0.4) + "@csstools/css-tokenizer": 3.0.4 + "@csstools/postcss-progressive-custom-properties": 4.2.1(postcss@8.5.10) + "@csstools/utilities": 2.0.0(postcss@8.5.10) + postcss: 8.5.10 + + "@csstools/postcss-exponential-functions@2.0.9(postcss@8.5.10)": + dependencies: + "@csstools/css-calc": 2.1.4(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4) + "@csstools/css-parser-algorithms": 3.0.5(@csstools/css-tokenizer@3.0.4) + "@csstools/css-tokenizer": 3.0.4 + postcss: 8.5.10 + + "@csstools/postcss-font-format-keywords@4.0.0(postcss@8.5.10)": + dependencies: + "@csstools/utilities": 2.0.0(postcss@8.5.10) + postcss: 8.5.10 + postcss-value-parser: 4.2.0 + + "@csstools/postcss-gamut-mapping@2.0.11(postcss@8.5.10)": + dependencies: + "@csstools/css-color-parser": 3.1.0(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4) + "@csstools/css-parser-algorithms": 3.0.5(@csstools/css-tokenizer@3.0.4) + "@csstools/css-tokenizer": 3.0.4 + postcss: 8.5.10 + + "@csstools/postcss-gradients-interpolation-method@5.0.12(postcss@8.5.10)": + dependencies: + "@csstools/css-color-parser": 3.1.0(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4) + "@csstools/css-parser-algorithms": 3.0.5(@csstools/css-tokenizer@3.0.4) + "@csstools/css-tokenizer": 3.0.4 + "@csstools/postcss-progressive-custom-properties": 4.2.1(postcss@8.5.10) + "@csstools/utilities": 2.0.0(postcss@8.5.10) + postcss: 8.5.10 + + "@csstools/postcss-hwb-function@4.0.12(postcss@8.5.10)": + dependencies: + "@csstools/css-color-parser": 3.1.0(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4) + "@csstools/css-parser-algorithms": 3.0.5(@csstools/css-tokenizer@3.0.4) + "@csstools/css-tokenizer": 3.0.4 + "@csstools/postcss-progressive-custom-properties": 4.2.1(postcss@8.5.10) + "@csstools/utilities": 2.0.0(postcss@8.5.10) + postcss: 8.5.10 + + "@csstools/postcss-ic-unit@4.0.4(postcss@8.5.10)": + dependencies: + "@csstools/postcss-progressive-custom-properties": 4.2.1(postcss@8.5.10) + "@csstools/utilities": 2.0.0(postcss@8.5.10) + postcss: 8.5.10 + postcss-value-parser: 4.2.0 + + "@csstools/postcss-initial@2.0.1(postcss@8.5.10)": + dependencies: + postcss: 8.5.10 + + "@csstools/postcss-is-pseudo-class@5.0.3(postcss@8.5.10)": + dependencies: + "@csstools/selector-specificity": 5.0.0(postcss-selector-parser@7.1.1) + postcss: 8.5.10 + postcss-selector-parser: 7.1.1 + + "@csstools/postcss-light-dark-function@2.0.11(postcss@8.5.10)": + dependencies: + "@csstools/css-parser-algorithms": 3.0.5(@csstools/css-tokenizer@3.0.4) + "@csstools/css-tokenizer": 3.0.4 + "@csstools/postcss-progressive-custom-properties": 4.2.1(postcss@8.5.10) + "@csstools/utilities": 2.0.0(postcss@8.5.10) + postcss: 8.5.10 + + "@csstools/postcss-logical-float-and-clear@3.0.0(postcss@8.5.10)": + dependencies: + postcss: 8.5.10 + + "@csstools/postcss-logical-overflow@2.0.0(postcss@8.5.10)": + dependencies: + postcss: 8.5.10 + + "@csstools/postcss-logical-overscroll-behavior@2.0.0(postcss@8.5.10)": + dependencies: + postcss: 8.5.10 + + "@csstools/postcss-logical-resize@3.0.0(postcss@8.5.10)": + dependencies: + postcss: 8.5.10 + postcss-value-parser: 4.2.0 + + "@csstools/postcss-logical-viewport-units@3.0.4(postcss@8.5.10)": + dependencies: + "@csstools/css-tokenizer": 3.0.4 + "@csstools/utilities": 2.0.0(postcss@8.5.10) + postcss: 8.5.10 + + "@csstools/postcss-media-minmax@2.0.9(postcss@8.5.10)": + dependencies: + "@csstools/css-calc": 2.1.4(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4) + "@csstools/css-parser-algorithms": 3.0.5(@csstools/css-tokenizer@3.0.4) + "@csstools/css-tokenizer": 3.0.4 + "@csstools/media-query-list-parser": 4.0.3(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4) + postcss: 8.5.10 + + "@csstools/postcss-media-queries-aspect-ratio-number-values@3.0.5(postcss@8.5.10)": + dependencies: + "@csstools/css-parser-algorithms": 3.0.5(@csstools/css-tokenizer@3.0.4) + "@csstools/css-tokenizer": 3.0.4 + "@csstools/media-query-list-parser": 4.0.3(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4) + postcss: 8.5.10 + + "@csstools/postcss-nested-calc@4.0.0(postcss@8.5.10)": + dependencies: + "@csstools/utilities": 2.0.0(postcss@8.5.10) + postcss: 8.5.10 + postcss-value-parser: 4.2.0 + + "@csstools/postcss-normalize-display-values@4.0.1(postcss@8.5.10)": + dependencies: + postcss: 8.5.10 + postcss-value-parser: 4.2.0 + + "@csstools/postcss-oklab-function@4.0.12(postcss@8.5.10)": + dependencies: + "@csstools/css-color-parser": 3.1.0(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4) + "@csstools/css-parser-algorithms": 3.0.5(@csstools/css-tokenizer@3.0.4) + "@csstools/css-tokenizer": 3.0.4 + "@csstools/postcss-progressive-custom-properties": 4.2.1(postcss@8.5.10) + "@csstools/utilities": 2.0.0(postcss@8.5.10) + postcss: 8.5.10 + + "@csstools/postcss-position-area-property@1.0.0(postcss@8.5.10)": + dependencies: + postcss: 8.5.10 + + "@csstools/postcss-progressive-custom-properties@4.2.1(postcss@8.5.10)": + dependencies: + postcss: 8.5.10 + postcss-value-parser: 4.2.0 + + "@csstools/postcss-property-rule-prelude-list@1.0.0(postcss@8.5.10)": + dependencies: + "@csstools/css-parser-algorithms": 3.0.5(@csstools/css-tokenizer@3.0.4) + "@csstools/css-tokenizer": 3.0.4 + postcss: 8.5.10 + + "@csstools/postcss-random-function@2.0.1(postcss@8.5.10)": + dependencies: + "@csstools/css-calc": 2.1.4(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4) + "@csstools/css-parser-algorithms": 3.0.5(@csstools/css-tokenizer@3.0.4) + "@csstools/css-tokenizer": 3.0.4 + postcss: 8.5.10 + + "@csstools/postcss-relative-color-syntax@3.0.12(postcss@8.5.10)": + dependencies: + "@csstools/css-color-parser": 3.1.0(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4) + "@csstools/css-parser-algorithms": 3.0.5(@csstools/css-tokenizer@3.0.4) + "@csstools/css-tokenizer": 3.0.4 + "@csstools/postcss-progressive-custom-properties": 4.2.1(postcss@8.5.10) + "@csstools/utilities": 2.0.0(postcss@8.5.10) + postcss: 8.5.10 + + "@csstools/postcss-scope-pseudo-class@4.0.1(postcss@8.5.10)": + dependencies: + postcss: 8.5.10 + postcss-selector-parser: 7.1.1 + + "@csstools/postcss-sign-functions@1.1.4(postcss@8.5.10)": + dependencies: + "@csstools/css-calc": 2.1.4(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4) + "@csstools/css-parser-algorithms": 3.0.5(@csstools/css-tokenizer@3.0.4) + "@csstools/css-tokenizer": 3.0.4 + postcss: 8.5.10 + + "@csstools/postcss-stepped-value-functions@4.0.9(postcss@8.5.10)": + dependencies: + "@csstools/css-calc": 2.1.4(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4) + "@csstools/css-parser-algorithms": 3.0.5(@csstools/css-tokenizer@3.0.4) + "@csstools/css-tokenizer": 3.0.4 + postcss: 8.5.10 + + "@csstools/postcss-syntax-descriptor-syntax-production@1.0.1(postcss@8.5.10)": + dependencies: + "@csstools/css-tokenizer": 3.0.4 + postcss: 8.5.10 + + "@csstools/postcss-system-ui-font-family@1.0.0(postcss@8.5.10)": + dependencies: + "@csstools/css-parser-algorithms": 3.0.5(@csstools/css-tokenizer@3.0.4) + "@csstools/css-tokenizer": 3.0.4 + postcss: 8.5.10 + + "@csstools/postcss-text-decoration-shorthand@4.0.3(postcss@8.5.10)": + dependencies: + "@csstools/color-helpers": 5.1.0 + postcss: 8.5.10 + postcss-value-parser: 4.2.0 + + "@csstools/postcss-trigonometric-functions@4.0.9(postcss@8.5.10)": + dependencies: + "@csstools/css-calc": 2.1.4(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4) + "@csstools/css-parser-algorithms": 3.0.5(@csstools/css-tokenizer@3.0.4) + "@csstools/css-tokenizer": 3.0.4 + postcss: 8.5.10 + + "@csstools/postcss-unset-value@4.0.0(postcss@8.5.10)": + dependencies: + postcss: 8.5.10 + + "@csstools/selector-resolve-nested@3.1.0(postcss-selector-parser@7.1.1)": + dependencies: + postcss-selector-parser: 7.1.1 + + "@csstools/selector-specificity@5.0.0(postcss-selector-parser@7.1.1)": + dependencies: + postcss-selector-parser: 7.1.1 + + "@csstools/utilities@2.0.0(postcss@8.5.10)": + dependencies: + postcss: 8.5.10 + + "@emnapi/core@1.9.2": + dependencies: + "@emnapi/wasi-threads": 1.2.1 + tslib: 2.8.1 + optional: true + + "@emnapi/runtime@1.9.2": + dependencies: + tslib: 2.8.1 + optional: true + + "@emnapi/wasi-threads@1.2.1": + dependencies: + tslib: 2.8.1 + optional: true + + "@es-joy/jsdoccomment@0.78.0": + dependencies: + "@types/estree": 1.0.8 + "@typescript-eslint/types": 8.58.2 + comment-parser: 1.4.1 + esquery: 1.7.0 + jsdoc-type-pratt-parser: 7.0.0 + + "@es-joy/resolve.exports@1.2.0": {} + + "@esbuild/aix-ppc64@0.27.7": + optional: true + + "@esbuild/android-arm64@0.27.7": + optional: true + + "@esbuild/android-arm@0.27.7": + optional: true + + "@esbuild/android-x64@0.27.7": + optional: true + + "@esbuild/darwin-arm64@0.27.7": + optional: true + + "@esbuild/darwin-x64@0.27.7": + optional: true + + "@esbuild/freebsd-arm64@0.27.7": + optional: true + + "@esbuild/freebsd-x64@0.27.7": + optional: true + + "@esbuild/linux-arm64@0.27.7": + optional: true + + "@esbuild/linux-arm@0.27.7": + optional: true + + "@esbuild/linux-ia32@0.27.7": + optional: true + + "@esbuild/linux-loong64@0.27.7": + optional: true + + "@esbuild/linux-mips64el@0.27.7": + optional: true + + "@esbuild/linux-ppc64@0.27.7": + optional: true + + "@esbuild/linux-riscv64@0.27.7": + optional: true + + "@esbuild/linux-s390x@0.27.7": + optional: true + + "@esbuild/linux-x64@0.27.7": + optional: true + + "@esbuild/netbsd-arm64@0.27.7": + optional: true + + "@esbuild/netbsd-x64@0.27.7": + optional: true + + "@esbuild/openbsd-arm64@0.27.7": + optional: true + + "@esbuild/openbsd-x64@0.27.7": + optional: true + + "@esbuild/openharmony-arm64@0.27.7": + optional: true + + "@esbuild/sunos-x64@0.27.7": + optional: true + + "@esbuild/win32-arm64@0.27.7": + optional: true + + "@esbuild/win32-ia32@0.27.7": + optional: true + + "@esbuild/win32-x64@0.27.7": + optional: true + + "@eslint-community/eslint-utils@4.9.1(eslint@8.57.1)": + dependencies: + eslint: 8.57.1 + eslint-visitor-keys: 3.4.3 + + "@eslint-community/regexpp@4.12.2": {} + + "@eslint/eslintrc@2.1.4": + dependencies: + ajv: 6.14.0 + debug: 4.4.3 + espree: 9.6.1 + globals: 13.24.0 + ignore: 5.3.2 + import-fresh: 3.3.1 + js-yaml: 4.1.1 + minimatch: 10.2.5 + strip-json-comments: 3.1.1 + transitivePeerDependencies: + - supports-color + + "@eslint/js@8.57.1": {} + + "@fastify/busboy@2.1.1": {} + + "@floating-ui/core@1.7.5": + dependencies: + "@floating-ui/utils": 0.2.11 + + "@floating-ui/dom@1.7.4": + dependencies: + "@floating-ui/core": 1.7.5 + "@floating-ui/utils": 0.2.11 + + "@floating-ui/dom@1.7.6": + dependencies: + "@floating-ui/core": 1.7.5 + "@floating-ui/utils": 0.2.11 + + "@floating-ui/react-dom@2.1.8(react-dom@19.2.5(react@19.2.5))(react@19.2.5)": + dependencies: + "@floating-ui/dom": 1.7.6 + react: 19.2.5 + react-dom: 19.2.5(react@19.2.5) + + "@floating-ui/react@0.27.19(react-dom@19.2.5(react@19.2.5))(react@19.2.5)": + dependencies: + "@floating-ui/react-dom": 2.1.8(react-dom@19.2.5(react@19.2.5))(react@19.2.5) + "@floating-ui/utils": 0.2.11 + react: 19.2.5 + react-dom: 19.2.5(react@19.2.5) + tabbable: 6.4.0 + + "@floating-ui/utils@0.2.11": {} + + "@fontsource/inconsolata@5.2.8": {} + + "@fontsource/inter@5.2.8": {} + + "@formatjs/ecma402-abstract@2.3.6": + dependencies: + "@formatjs/fast-memoize": 2.2.7 + "@formatjs/intl-localematcher": 0.6.2 + decimal.js: 10.6.0 + tslib: 2.8.1 + + "@formatjs/fast-memoize@2.2.7": + dependencies: + tslib: 2.8.1 + + "@formatjs/fast-memoize@3.1.2": {} + + "@formatjs/intl-durationformat@0.10.4": + dependencies: + "@formatjs/intl-localematcher": 0.8.3 + + "@formatjs/intl-localematcher@0.6.2": + dependencies: + tslib: 2.8.1 + + "@formatjs/intl-localematcher@0.8.3": + dependencies: + "@formatjs/fast-memoize": 3.1.2 + + "@formatjs/intl-segmenter@11.7.12": + dependencies: + "@formatjs/ecma402-abstract": 2.3.6 + "@formatjs/intl-localematcher": 0.6.2 + tslib: 2.8.1 + + "@gulpjs/to-absolute-glob@4.0.0": + dependencies: + is-negated-glob: 1.0.0 + + "@humanwhocodes/config-array@0.13.0": + dependencies: + "@humanwhocodes/object-schema": 2.0.3 + debug: 4.4.3 + minimatch: 10.2.5 + transitivePeerDependencies: + - supports-color + + "@humanwhocodes/module-importer@1.0.1": {} + + "@humanwhocodes/object-schema@2.0.3": {} + + "@isaacs/cliui@8.0.2": + dependencies: + string-width: 5.1.2 + string-width-cjs: string-width@4.2.3 + strip-ansi: 7.2.0 + strip-ansi-cjs: strip-ansi@6.0.1 + wrap-ansi: 8.1.0 + wrap-ansi-cjs: wrap-ansi@7.0.0 + + "@joshwooding/vite-plugin-react-docgen-typescript@0.7.0(typescript@5.9.3)(vite@8.0.8(@types/node@24.12.2)(esbuild@0.27.7)(jiti@2.6.1)(sass@1.99.0)(terser@5.46.1)(yaml@2.8.3))": + dependencies: + glob: 10.5.0 + react-docgen-typescript: 2.4.0(typescript@5.9.3) + vite: 8.0.8(@types/node@24.12.2)(esbuild@0.27.7)(jiti@2.6.1)(sass@1.99.0)(terser@5.46.1)(yaml@2.8.3) + optionalDependencies: + typescript: 5.9.3 + + "@jridgewell/gen-mapping@0.3.13": + dependencies: + "@jridgewell/sourcemap-codec": 1.5.5 + "@jridgewell/trace-mapping": 0.3.31 + + "@jridgewell/remapping@2.3.5": + dependencies: + "@jridgewell/gen-mapping": 0.3.13 + "@jridgewell/trace-mapping": 0.3.31 + + "@jridgewell/resolve-uri@3.1.2": {} + + "@jridgewell/source-map@0.3.11": + dependencies: + "@jridgewell/gen-mapping": 0.3.13 + "@jridgewell/trace-mapping": 0.3.31 + + "@jridgewell/sourcemap-codec@1.5.5": {} + + "@jridgewell/trace-mapping@0.3.31": + dependencies: + "@jridgewell/resolve-uri": 3.1.2 + "@jridgewell/sourcemap-codec": 1.5.5 + + "@livekit/components-core@0.12.13(livekit-client@2.18.3(@types/dom-mediacapture-record@1.0.22))(tslib@2.8.1)": + dependencies: + "@floating-ui/dom": 1.7.4 + livekit-client: 2.18.3(@types/dom-mediacapture-record@1.0.22) + loglevel: 1.9.1 + rxjs: 7.8.2 + tslib: 2.8.1 + + "@livekit/components-react@2.9.20(livekit-client@2.18.3(@types/dom-mediacapture-record@1.0.22))(react-dom@19.2.5(react@19.2.5))(react@19.2.5)(tslib@2.8.1)": + dependencies: + "@livekit/components-core": 0.12.13(livekit-client@2.18.3(@types/dom-mediacapture-record@1.0.22))(tslib@2.8.1) + clsx: 2.1.1 + events: 3.3.0 + jose: 6.2.2 + livekit-client: 2.18.3(@types/dom-mediacapture-record@1.0.22) + react: 19.2.5 + react-dom: 19.2.5(react@19.2.5) + tslib: 2.8.1 + usehooks-ts: 3.1.1(react@19.2.5) + + "@livekit/mutex@1.1.1": {} + + "@livekit/protocol@1.45.3": + dependencies: + "@bufbuild/protobuf": 1.10.1 + + "@livekit/track-processors@0.7.2(@types/dom-mediacapture-transform@0.1.11)(livekit-client@2.18.3(@types/dom-mediacapture-record@1.0.22))": + dependencies: + "@mediapipe/tasks-vision": 0.10.34 + "@types/dom-mediacapture-transform": 0.1.11 + livekit-client: 2.18.3(@types/dom-mediacapture-record@1.0.22) + + "@matrix-org/matrix-sdk-crypto-wasm@18.0.0": {} + + "@mdx-js/react@3.1.1(@types/react@19.2.14)(react@19.2.5)": + dependencies: + "@types/mdx": 2.0.13 + "@types/react": 19.2.14 + react: 19.2.5 + + "@mediapipe/tasks-vision@0.10.34": {} + + "@napi-rs/wasm-runtime@1.1.4(@emnapi/core@1.9.2)(@emnapi/runtime@1.9.2)": + dependencies: + "@emnapi/core": 1.9.2 + "@emnapi/runtime": 1.9.2 + "@tybys/wasm-util": 0.10.1 + optional: true + + "@nicolo-ribaudo/eslint-scope-5-internals@5.1.1-v1": + dependencies: + eslint-scope: 5.1.1 + + "@nodelib/fs.scandir@2.1.5": + dependencies: + "@nodelib/fs.stat": 2.0.5 + run-parallel: 1.2.0 + + "@nodelib/fs.stat@2.0.5": {} + + "@nodelib/fs.walk@1.2.8": + dependencies: + "@nodelib/fs.scandir": 2.1.5 + fastq: 1.20.1 + + "@octokit/auth-token@4.0.0": {} + + "@octokit/core@5.2.2": + dependencies: + "@octokit/auth-token": 4.0.0 + "@octokit/graphql": 7.1.1 + "@octokit/request": 8.4.1 + "@octokit/request-error": 5.1.1 + "@octokit/types": 13.10.0 + before-after-hook: 2.2.3 + universal-user-agent: 6.0.1 + + "@octokit/endpoint@9.0.6": + dependencies: + "@octokit/types": 13.10.0 + universal-user-agent: 6.0.1 + + "@octokit/graphql@7.1.1": + dependencies: + "@octokit/request": 8.4.1 + "@octokit/types": 13.10.0 + universal-user-agent: 6.0.1 + + "@octokit/openapi-types@20.0.0": {} + + "@octokit/openapi-types@24.2.0": {} + + "@octokit/plugin-paginate-rest@9.2.2(@octokit/core@5.2.2)": + dependencies: + "@octokit/core": 5.2.2 + "@octokit/types": 12.6.0 + + "@octokit/plugin-rest-endpoint-methods@10.4.1(@octokit/core@5.2.2)": + dependencies: + "@octokit/core": 5.2.2 + "@octokit/types": 12.6.0 + + "@octokit/request-error@5.1.1": + dependencies: + "@octokit/types": 13.10.0 + deprecation: 2.3.1 + once: 1.4.0 + + "@octokit/request@8.4.1": + dependencies: + "@octokit/endpoint": 9.0.6 + "@octokit/request-error": 5.1.1 + "@octokit/types": 13.10.0 + universal-user-agent: 6.0.1 + + "@octokit/types@12.6.0": + dependencies: + "@octokit/openapi-types": 20.0.0 + + "@octokit/types@13.10.0": + dependencies: + "@octokit/openapi-types": 24.2.0 + + "@oxc-project/types@0.124.0": {} + + "@oxc-resolver/binding-android-arm-eabi@11.19.1": + optional: true + + "@oxc-resolver/binding-android-arm64@11.19.1": + optional: true + + "@oxc-resolver/binding-darwin-arm64@11.19.1": + optional: true + + "@oxc-resolver/binding-darwin-x64@11.19.1": + optional: true + + "@oxc-resolver/binding-freebsd-x64@11.19.1": + optional: true + + "@oxc-resolver/binding-linux-arm-gnueabihf@11.19.1": + optional: true + + "@oxc-resolver/binding-linux-arm-musleabihf@11.19.1": + optional: true + + "@oxc-resolver/binding-linux-arm64-gnu@11.19.1": + optional: true + + "@oxc-resolver/binding-linux-arm64-musl@11.19.1": + optional: true + + "@oxc-resolver/binding-linux-ppc64-gnu@11.19.1": + optional: true + + "@oxc-resolver/binding-linux-riscv64-gnu@11.19.1": + optional: true + + "@oxc-resolver/binding-linux-riscv64-musl@11.19.1": + optional: true + + "@oxc-resolver/binding-linux-s390x-gnu@11.19.1": + optional: true + + "@oxc-resolver/binding-linux-x64-gnu@11.19.1": + optional: true + + "@oxc-resolver/binding-linux-x64-musl@11.19.1": + optional: true + + "@oxc-resolver/binding-openharmony-arm64@11.19.1": + optional: true + + "@oxc-resolver/binding-wasm32-wasi@11.19.1(@emnapi/core@1.9.2)(@emnapi/runtime@1.9.2)": + dependencies: + "@napi-rs/wasm-runtime": 1.1.4(@emnapi/core@1.9.2)(@emnapi/runtime@1.9.2) + transitivePeerDependencies: + - "@emnapi/core" + - "@emnapi/runtime" + optional: true + + "@oxc-resolver/binding-win32-arm64-msvc@11.19.1": + optional: true + + "@oxc-resolver/binding-win32-ia32-msvc@11.19.1": + optional: true + + "@oxc-resolver/binding-win32-x64-msvc@11.19.1": + optional: true + + "@parcel/watcher-android-arm64@2.5.6": + optional: true + + "@parcel/watcher-darwin-arm64@2.5.6": + optional: true + + "@parcel/watcher-darwin-x64@2.5.6": + optional: true + + "@parcel/watcher-freebsd-x64@2.5.6": + optional: true + + "@parcel/watcher-linux-arm-glibc@2.5.6": + optional: true + + "@parcel/watcher-linux-arm-musl@2.5.6": + optional: true + + "@parcel/watcher-linux-arm64-glibc@2.5.6": + optional: true + + "@parcel/watcher-linux-arm64-musl@2.5.6": + optional: true + + "@parcel/watcher-linux-x64-glibc@2.5.6": + optional: true + + "@parcel/watcher-linux-x64-musl@2.5.6": + optional: true + + "@parcel/watcher-win32-arm64@2.5.6": + optional: true + + "@parcel/watcher-win32-ia32@2.5.6": + optional: true + + "@parcel/watcher-win32-x64@2.5.6": + optional: true + + "@parcel/watcher@2.5.6": + dependencies: + detect-libc: 2.1.2 + is-glob: 4.0.3 + node-addon-api: 7.1.1 + picomatch: 4.0.4 + optionalDependencies: + "@parcel/watcher-android-arm64": 2.5.6 + "@parcel/watcher-darwin-arm64": 2.5.6 + "@parcel/watcher-darwin-x64": 2.5.6 + "@parcel/watcher-freebsd-x64": 2.5.6 + "@parcel/watcher-linux-arm-glibc": 2.5.6 + "@parcel/watcher-linux-arm-musl": 2.5.6 + "@parcel/watcher-linux-arm64-glibc": 2.5.6 + "@parcel/watcher-linux-arm64-musl": 2.5.6 + "@parcel/watcher-linux-x64-glibc": 2.5.6 + "@parcel/watcher-linux-x64-musl": 2.5.6 + "@parcel/watcher-win32-arm64": 2.5.6 + "@parcel/watcher-win32-ia32": 2.5.6 + "@parcel/watcher-win32-x64": 2.5.6 + optional: true + + "@pkgjs/parseargs@0.11.0": + optional: true + + "@playwright/test@1.59.1": + dependencies: + playwright: 1.59.1 + + "@radix-ui/number@1.1.1": {} + + "@radix-ui/primitive@1.1.3": {} + + "@radix-ui/react-arrow@1.1.7(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5)": + dependencies: + "@radix-ui/react-primitive": 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5) + react: 19.2.5 + react-dom: 19.2.5(react@19.2.5) + optionalDependencies: + "@types/react": 19.2.14 + "@types/react-dom": 19.2.3(@types/react@19.2.14) + + "@radix-ui/react-collection@1.1.7(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5)": + dependencies: + "@radix-ui/react-compose-refs": 1.1.2(@types/react@19.2.14)(react@19.2.5) + "@radix-ui/react-context": 1.1.2(@types/react@19.2.14)(react@19.2.5) + "@radix-ui/react-primitive": 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5) + "@radix-ui/react-slot": 1.2.3(@types/react@19.2.14)(react@19.2.5) + react: 19.2.5 + react-dom: 19.2.5(react@19.2.5) + optionalDependencies: + "@types/react": 19.2.14 + "@types/react-dom": 19.2.3(@types/react@19.2.14) + + "@radix-ui/react-compose-refs@1.1.2(@types/react@19.2.14)(react@19.2.5)": + dependencies: + react: 19.2.5 + optionalDependencies: + "@types/react": 19.2.14 + + "@radix-ui/react-context-menu@2.2.16(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5)": + dependencies: + "@radix-ui/primitive": 1.1.3 + "@radix-ui/react-context": 1.1.2(@types/react@19.2.14)(react@19.2.5) + "@radix-ui/react-menu": 2.1.16(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5) + "@radix-ui/react-primitive": 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5) + "@radix-ui/react-use-callback-ref": 1.1.1(@types/react@19.2.14)(react@19.2.5) + "@radix-ui/react-use-controllable-state": 1.2.2(@types/react@19.2.14)(react@19.2.5) + react: 19.2.5 + react-dom: 19.2.5(react@19.2.5) + optionalDependencies: + "@types/react": 19.2.14 + "@types/react-dom": 19.2.3(@types/react@19.2.14) + + "@radix-ui/react-context@1.1.2(@types/react@19.2.14)(react@19.2.5)": + dependencies: + react: 19.2.5 + optionalDependencies: + "@types/react": 19.2.14 + + "@radix-ui/react-context@1.1.3(@types/react@19.2.14)(react@19.2.5)": + dependencies: + react: 19.2.5 + optionalDependencies: + "@types/react": 19.2.14 + + "@radix-ui/react-dialog@1.1.15(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5)": + dependencies: + "@radix-ui/primitive": 1.1.3 + "@radix-ui/react-compose-refs": 1.1.2(@types/react@19.2.14)(react@19.2.5) + "@radix-ui/react-context": 1.1.2(@types/react@19.2.14)(react@19.2.5) + "@radix-ui/react-dismissable-layer": 1.1.11(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5) + "@radix-ui/react-focus-guards": 1.1.3(@types/react@19.2.14)(react@19.2.5) + "@radix-ui/react-focus-scope": 1.1.7(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5) + "@radix-ui/react-id": 1.1.1(@types/react@19.2.14)(react@19.2.5) + "@radix-ui/react-portal": 1.1.9(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5) + "@radix-ui/react-presence": 1.1.5(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5) + "@radix-ui/react-primitive": 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5) + "@radix-ui/react-slot": 1.2.3(@types/react@19.2.14)(react@19.2.5) + "@radix-ui/react-use-controllable-state": 1.2.2(@types/react@19.2.14)(react@19.2.5) + aria-hidden: 1.2.6 + react: 19.2.5 + react-dom: 19.2.5(react@19.2.5) + react-remove-scroll: 2.7.2(@types/react@19.2.14)(react@19.2.5) + optionalDependencies: + "@types/react": 19.2.14 + "@types/react-dom": 19.2.3(@types/react@19.2.14) + + "@radix-ui/react-direction@1.1.1(@types/react@19.2.14)(react@19.2.5)": + dependencies: + react: 19.2.5 + optionalDependencies: + "@types/react": 19.2.14 + + "@radix-ui/react-dismissable-layer@1.1.11(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5)": + dependencies: + "@radix-ui/primitive": 1.1.3 + "@radix-ui/react-compose-refs": 1.1.2(@types/react@19.2.14)(react@19.2.5) + "@radix-ui/react-primitive": 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5) + "@radix-ui/react-use-callback-ref": 1.1.1(@types/react@19.2.14)(react@19.2.5) + "@radix-ui/react-use-escape-keydown": 1.1.1(@types/react@19.2.14)(react@19.2.5) + react: 19.2.5 + react-dom: 19.2.5(react@19.2.5) + optionalDependencies: + "@types/react": 19.2.14 + "@types/react-dom": 19.2.3(@types/react@19.2.14) + + "@radix-ui/react-dropdown-menu@2.1.16(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5)": + dependencies: + "@radix-ui/primitive": 1.1.3 + "@radix-ui/react-compose-refs": 1.1.2(@types/react@19.2.14)(react@19.2.5) + "@radix-ui/react-context": 1.1.2(@types/react@19.2.14)(react@19.2.5) + "@radix-ui/react-id": 1.1.1(@types/react@19.2.14)(react@19.2.5) + "@radix-ui/react-menu": 2.1.16(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5) + "@radix-ui/react-primitive": 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5) + "@radix-ui/react-use-controllable-state": 1.2.2(@types/react@19.2.14)(react@19.2.5) + react: 19.2.5 + react-dom: 19.2.5(react@19.2.5) + optionalDependencies: + "@types/react": 19.2.14 + "@types/react-dom": 19.2.3(@types/react@19.2.14) + + "@radix-ui/react-focus-guards@1.1.3(@types/react@19.2.14)(react@19.2.5)": + dependencies: + react: 19.2.5 + optionalDependencies: + "@types/react": 19.2.14 + + "@radix-ui/react-focus-scope@1.1.7(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5)": + dependencies: + "@radix-ui/react-compose-refs": 1.1.2(@types/react@19.2.14)(react@19.2.5) + "@radix-ui/react-primitive": 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5) + "@radix-ui/react-use-callback-ref": 1.1.1(@types/react@19.2.14)(react@19.2.5) + react: 19.2.5 + react-dom: 19.2.5(react@19.2.5) + optionalDependencies: + "@types/react": 19.2.14 + "@types/react-dom": 19.2.3(@types/react@19.2.14) + + "@radix-ui/react-form@0.1.8(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5)": + dependencies: + "@radix-ui/primitive": 1.1.3 + "@radix-ui/react-compose-refs": 1.1.2(@types/react@19.2.14)(react@19.2.5) + "@radix-ui/react-context": 1.1.2(@types/react@19.2.14)(react@19.2.5) + "@radix-ui/react-id": 1.1.1(@types/react@19.2.14)(react@19.2.5) + "@radix-ui/react-label": 2.1.7(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5) + "@radix-ui/react-primitive": 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5) + react: 19.2.5 + react-dom: 19.2.5(react@19.2.5) + optionalDependencies: + "@types/react": 19.2.14 + "@types/react-dom": 19.2.3(@types/react@19.2.14) + + "@radix-ui/react-id@1.1.1(@types/react@19.2.14)(react@19.2.5)": + dependencies: + "@radix-ui/react-use-layout-effect": 1.1.1(@types/react@19.2.14)(react@19.2.5) + react: 19.2.5 + optionalDependencies: + "@types/react": 19.2.14 + + "@radix-ui/react-label@2.1.7(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5)": + dependencies: + "@radix-ui/react-primitive": 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5) + react: 19.2.5 + react-dom: 19.2.5(react@19.2.5) + optionalDependencies: + "@types/react": 19.2.14 + "@types/react-dom": 19.2.3(@types/react@19.2.14) + + "@radix-ui/react-menu@2.1.16(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5)": + dependencies: + "@radix-ui/primitive": 1.1.3 + "@radix-ui/react-collection": 1.1.7(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5) + "@radix-ui/react-compose-refs": 1.1.2(@types/react@19.2.14)(react@19.2.5) + "@radix-ui/react-context": 1.1.2(@types/react@19.2.14)(react@19.2.5) + "@radix-ui/react-direction": 1.1.1(@types/react@19.2.14)(react@19.2.5) + "@radix-ui/react-dismissable-layer": 1.1.11(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5) + "@radix-ui/react-focus-guards": 1.1.3(@types/react@19.2.14)(react@19.2.5) + "@radix-ui/react-focus-scope": 1.1.7(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5) + "@radix-ui/react-id": 1.1.1(@types/react@19.2.14)(react@19.2.5) + "@radix-ui/react-popper": 1.2.8(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5) + "@radix-ui/react-portal": 1.1.9(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5) + "@radix-ui/react-presence": 1.1.5(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5) + "@radix-ui/react-primitive": 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5) + "@radix-ui/react-roving-focus": 1.1.11(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5) + "@radix-ui/react-slot": 1.2.3(@types/react@19.2.14)(react@19.2.5) + "@radix-ui/react-use-callback-ref": 1.1.1(@types/react@19.2.14)(react@19.2.5) + aria-hidden: 1.2.6 + react: 19.2.5 + react-dom: 19.2.5(react@19.2.5) + react-remove-scroll: 2.7.2(@types/react@19.2.14)(react@19.2.5) + optionalDependencies: + "@types/react": 19.2.14 + "@types/react-dom": 19.2.3(@types/react@19.2.14) + + "@radix-ui/react-popper@1.2.8(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5)": + dependencies: + "@floating-ui/react-dom": 2.1.8(react-dom@19.2.5(react@19.2.5))(react@19.2.5) + "@radix-ui/react-arrow": 1.1.7(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5) + "@radix-ui/react-compose-refs": 1.1.2(@types/react@19.2.14)(react@19.2.5) + "@radix-ui/react-context": 1.1.2(@types/react@19.2.14)(react@19.2.5) + "@radix-ui/react-primitive": 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5) + "@radix-ui/react-use-callback-ref": 1.1.1(@types/react@19.2.14)(react@19.2.5) + "@radix-ui/react-use-layout-effect": 1.1.1(@types/react@19.2.14)(react@19.2.5) + "@radix-ui/react-use-rect": 1.1.1(@types/react@19.2.14)(react@19.2.5) + "@radix-ui/react-use-size": 1.1.1(@types/react@19.2.14)(react@19.2.5) + "@radix-ui/rect": 1.1.1 + react: 19.2.5 + react-dom: 19.2.5(react@19.2.5) + optionalDependencies: + "@types/react": 19.2.14 + "@types/react-dom": 19.2.3(@types/react@19.2.14) + + "@radix-ui/react-portal@1.1.9(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5)": + dependencies: + "@radix-ui/react-primitive": 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5) + "@radix-ui/react-use-layout-effect": 1.1.1(@types/react@19.2.14)(react@19.2.5) + react: 19.2.5 + react-dom: 19.2.5(react@19.2.5) + optionalDependencies: + "@types/react": 19.2.14 + "@types/react-dom": 19.2.3(@types/react@19.2.14) + + "@radix-ui/react-presence@1.1.5(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5)": + dependencies: + "@radix-ui/react-compose-refs": 1.1.2(@types/react@19.2.14)(react@19.2.5) + "@radix-ui/react-use-layout-effect": 1.1.1(@types/react@19.2.14)(react@19.2.5) + react: 19.2.5 + react-dom: 19.2.5(react@19.2.5) + optionalDependencies: + "@types/react": 19.2.14 + "@types/react-dom": 19.2.3(@types/react@19.2.14) + + "@radix-ui/react-primitive@2.1.3(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5)": + dependencies: + "@radix-ui/react-slot": 1.2.3(@types/react@19.2.14)(react@19.2.5) + react: 19.2.5 + react-dom: 19.2.5(react@19.2.5) + optionalDependencies: + "@types/react": 19.2.14 + "@types/react-dom": 19.2.3(@types/react@19.2.14) + + "@radix-ui/react-primitive@2.1.4(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5)": + dependencies: + "@radix-ui/react-slot": 1.2.4(@types/react@19.2.14)(react@19.2.5) + react: 19.2.5 + react-dom: 19.2.5(react@19.2.5) + optionalDependencies: + "@types/react": 19.2.14 + "@types/react-dom": 19.2.3(@types/react@19.2.14) + + "@radix-ui/react-progress@1.1.8(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5)": + dependencies: + "@radix-ui/react-context": 1.1.3(@types/react@19.2.14)(react@19.2.5) + "@radix-ui/react-primitive": 2.1.4(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5) + react: 19.2.5 + react-dom: 19.2.5(react@19.2.5) + optionalDependencies: + "@types/react": 19.2.14 + "@types/react-dom": 19.2.3(@types/react@19.2.14) + + "@radix-ui/react-roving-focus@1.1.11(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5)": + dependencies: + "@radix-ui/primitive": 1.1.3 + "@radix-ui/react-collection": 1.1.7(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5) + "@radix-ui/react-compose-refs": 1.1.2(@types/react@19.2.14)(react@19.2.5) + "@radix-ui/react-context": 1.1.2(@types/react@19.2.14)(react@19.2.5) + "@radix-ui/react-direction": 1.1.1(@types/react@19.2.14)(react@19.2.5) + "@radix-ui/react-id": 1.1.1(@types/react@19.2.14)(react@19.2.5) + "@radix-ui/react-primitive": 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5) + "@radix-ui/react-use-callback-ref": 1.1.1(@types/react@19.2.14)(react@19.2.5) + "@radix-ui/react-use-controllable-state": 1.2.2(@types/react@19.2.14)(react@19.2.5) + react: 19.2.5 + react-dom: 19.2.5(react@19.2.5) + optionalDependencies: + "@types/react": 19.2.14 + "@types/react-dom": 19.2.3(@types/react@19.2.14) + + "@radix-ui/react-separator@1.1.8(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5)": + dependencies: + "@radix-ui/react-primitive": 2.1.4(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5) + react: 19.2.5 + react-dom: 19.2.5(react@19.2.5) + optionalDependencies: + "@types/react": 19.2.14 + "@types/react-dom": 19.2.3(@types/react@19.2.14) + + "@radix-ui/react-slider@1.3.6(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5)": + dependencies: + "@radix-ui/number": 1.1.1 + "@radix-ui/primitive": 1.1.3 + "@radix-ui/react-collection": 1.1.7(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5) + "@radix-ui/react-compose-refs": 1.1.2(@types/react@19.2.14)(react@19.2.5) + "@radix-ui/react-context": 1.1.2(@types/react@19.2.14)(react@19.2.5) + "@radix-ui/react-direction": 1.1.1(@types/react@19.2.14)(react@19.2.5) + "@radix-ui/react-primitive": 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5) + "@radix-ui/react-use-controllable-state": 1.2.2(@types/react@19.2.14)(react@19.2.5) + "@radix-ui/react-use-layout-effect": 1.1.1(@types/react@19.2.14)(react@19.2.5) + "@radix-ui/react-use-previous": 1.1.1(@types/react@19.2.14)(react@19.2.5) + "@radix-ui/react-use-size": 1.1.1(@types/react@19.2.14)(react@19.2.5) + react: 19.2.5 + react-dom: 19.2.5(react@19.2.5) + optionalDependencies: + "@types/react": 19.2.14 + "@types/react-dom": 19.2.3(@types/react@19.2.14) + + "@radix-ui/react-slot@1.2.3(@types/react@19.2.14)(react@19.2.5)": + dependencies: + "@radix-ui/react-compose-refs": 1.1.2(@types/react@19.2.14)(react@19.2.5) + react: 19.2.5 + optionalDependencies: + "@types/react": 19.2.14 + + "@radix-ui/react-slot@1.2.4(@types/react@19.2.14)(react@19.2.5)": + dependencies: + "@radix-ui/react-compose-refs": 1.1.2(@types/react@19.2.14)(react@19.2.5) + react: 19.2.5 + optionalDependencies: + "@types/react": 19.2.14 + + "@radix-ui/react-use-callback-ref@1.1.1(@types/react@19.2.14)(react@19.2.5)": + dependencies: + react: 19.2.5 + optionalDependencies: + "@types/react": 19.2.14 + + "@radix-ui/react-use-controllable-state@1.2.2(@types/react@19.2.14)(react@19.2.5)": + dependencies: + "@radix-ui/react-use-effect-event": 0.0.2(@types/react@19.2.14)(react@19.2.5) + "@radix-ui/react-use-layout-effect": 1.1.1(@types/react@19.2.14)(react@19.2.5) + react: 19.2.5 + optionalDependencies: + "@types/react": 19.2.14 + + "@radix-ui/react-use-effect-event@0.0.2(@types/react@19.2.14)(react@19.2.5)": + dependencies: + "@radix-ui/react-use-layout-effect": 1.1.1(@types/react@19.2.14)(react@19.2.5) + react: 19.2.5 + optionalDependencies: + "@types/react": 19.2.14 + + "@radix-ui/react-use-escape-keydown@1.1.1(@types/react@19.2.14)(react@19.2.5)": + dependencies: + "@radix-ui/react-use-callback-ref": 1.1.1(@types/react@19.2.14)(react@19.2.5) + react: 19.2.5 + optionalDependencies: + "@types/react": 19.2.14 + + "@radix-ui/react-use-layout-effect@1.1.1(@types/react@19.2.14)(react@19.2.5)": + dependencies: + react: 19.2.5 + optionalDependencies: + "@types/react": 19.2.14 + + "@radix-ui/react-use-previous@1.1.1(@types/react@19.2.14)(react@19.2.5)": + dependencies: + react: 19.2.5 + optionalDependencies: + "@types/react": 19.2.14 + + "@radix-ui/react-use-rect@1.1.1(@types/react@19.2.14)(react@19.2.5)": + dependencies: + "@radix-ui/rect": 1.1.1 + react: 19.2.5 + optionalDependencies: + "@types/react": 19.2.14 + + "@radix-ui/react-use-size@1.1.1(@types/react@19.2.14)(react@19.2.5)": + dependencies: + "@radix-ui/react-use-layout-effect": 1.1.1(@types/react@19.2.14)(react@19.2.5) + react: 19.2.5 + optionalDependencies: + "@types/react": 19.2.14 + + "@radix-ui/react-visually-hidden@1.2.4(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5)": + dependencies: + "@radix-ui/react-primitive": 2.1.4(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5) + react: 19.2.5 + react-dom: 19.2.5(react@19.2.5) + optionalDependencies: + "@types/react": 19.2.14 + "@types/react-dom": 19.2.3(@types/react@19.2.14) + + "@radix-ui/rect@1.1.1": {} + + "@react-spring/animated@10.0.3(react@19.2.5)": + dependencies: + "@react-spring/shared": 10.0.3(react@19.2.5) + "@react-spring/types": 10.0.3 + react: 19.2.5 + + "@react-spring/core@10.0.3(react@19.2.5)": + dependencies: + "@react-spring/animated": 10.0.3(react@19.2.5) + "@react-spring/shared": 10.0.3(react@19.2.5) + "@react-spring/types": 10.0.3 + react: 19.2.5 + + "@react-spring/rafz@10.0.3": {} + + "@react-spring/shared@10.0.3(react@19.2.5)": + dependencies: + "@react-spring/rafz": 10.0.3 + "@react-spring/types": 10.0.3 + react: 19.2.5 + + "@react-spring/types@10.0.3": {} + + "@react-spring/web@10.0.3(react-dom@19.2.5(react@19.2.5))(react@19.2.5)": + dependencies: + "@react-spring/animated": 10.0.3(react@19.2.5) + "@react-spring/core": 10.0.3(react@19.2.5) + "@react-spring/shared": 10.0.3(react@19.2.5) + "@react-spring/types": 10.0.3 + react: 19.2.5 + react-dom: 19.2.5(react@19.2.5) + + "@rolldown/binding-android-arm64@1.0.0-rc.15": + optional: true + + "@rolldown/binding-darwin-arm64@1.0.0-rc.15": + optional: true + + "@rolldown/binding-darwin-x64@1.0.0-rc.15": + optional: true + + "@rolldown/binding-freebsd-x64@1.0.0-rc.15": + optional: true + + "@rolldown/binding-linux-arm-gnueabihf@1.0.0-rc.15": + optional: true + + "@rolldown/binding-linux-arm64-gnu@1.0.0-rc.15": + optional: true + + "@rolldown/binding-linux-arm64-musl@1.0.0-rc.15": + optional: true + + "@rolldown/binding-linux-ppc64-gnu@1.0.0-rc.15": + optional: true + + "@rolldown/binding-linux-s390x-gnu@1.0.0-rc.15": + optional: true + + "@rolldown/binding-linux-x64-gnu@1.0.0-rc.15": + optional: true + + "@rolldown/binding-linux-x64-musl@1.0.0-rc.15": + optional: true + + "@rolldown/binding-openharmony-arm64@1.0.0-rc.15": + optional: true + + "@rolldown/binding-wasm32-wasi@1.0.0-rc.15": + dependencies: + "@emnapi/core": 1.9.2 + "@emnapi/runtime": 1.9.2 + "@napi-rs/wasm-runtime": 1.1.4(@emnapi/core@1.9.2)(@emnapi/runtime@1.9.2) + optional: true + + "@rolldown/binding-win32-arm64-msvc@1.0.0-rc.15": + optional: true + + "@rolldown/binding-win32-x64-msvc@1.0.0-rc.15": + optional: true + + "@rolldown/pluginutils@1.0.0-beta.27": {} + + "@rolldown/pluginutils@1.0.0-rc.15": {} + + "@rollup/plugin-inject@5.0.5": + dependencies: + "@rollup/pluginutils": 5.3.0 + estree-walker: 2.0.2 + magic-string: 0.30.21 + + "@rollup/pluginutils@4.2.1": + dependencies: + estree-walker: 2.0.2 + picomatch: 2.3.2 + + "@rollup/pluginutils@5.3.0": + dependencies: + "@types/estree": 1.0.8 + estree-walker: 2.0.2 + picomatch: 4.0.4 + + "@rtsao/scc@1.1.0": {} + + "@sentry-internal/browser-utils@8.55.1": + dependencies: + "@sentry/core": 8.55.1 + + "@sentry-internal/feedback@8.55.1": + dependencies: + "@sentry/core": 8.55.1 + + "@sentry-internal/replay-canvas@8.55.1": + dependencies: + "@sentry-internal/replay": 8.55.1 + "@sentry/core": 8.55.1 + + "@sentry-internal/replay@8.55.1": + dependencies: + "@sentry-internal/browser-utils": 8.55.1 + "@sentry/core": 8.55.1 + + "@sentry/babel-plugin-component-annotate@3.6.1": {} + + "@sentry/browser@8.55.1": + dependencies: + "@sentry-internal/browser-utils": 8.55.1 + "@sentry-internal/feedback": 8.55.1 + "@sentry-internal/replay": 8.55.1 + "@sentry-internal/replay-canvas": 8.55.1 + "@sentry/core": 8.55.1 + + "@sentry/bundler-plugin-core@3.6.1": + dependencies: + "@babel/core": 7.29.0 + "@sentry/babel-plugin-component-annotate": 3.6.1 + "@sentry/cli": 2.58.5 + dotenv: 16.6.1 + find-up: 5.0.0 + glob: 10.5.0 + magic-string: 0.30.8 + unplugin: 1.0.1 + transitivePeerDependencies: + - encoding + - supports-color + + "@sentry/cli-darwin@2.58.5": + optional: true + + "@sentry/cli-linux-arm64@2.58.5": + optional: true + + "@sentry/cli-linux-arm@2.58.5": + optional: true + + "@sentry/cli-linux-i686@2.58.5": + optional: true + + "@sentry/cli-linux-x64@2.58.5": + optional: true + + "@sentry/cli-win32-arm64@2.58.5": + optional: true + + "@sentry/cli-win32-i686@2.58.5": + optional: true + + "@sentry/cli-win32-x64@2.58.5": + optional: true + + "@sentry/cli@2.58.5": + dependencies: + https-proxy-agent: 5.0.1 + node-fetch: 2.7.0 + progress: 2.0.3 + proxy-from-env: 1.1.0 + which: 2.0.2 + optionalDependencies: + "@sentry/cli-darwin": 2.58.5 + "@sentry/cli-linux-arm": 2.58.5 + "@sentry/cli-linux-arm64": 2.58.5 + "@sentry/cli-linux-i686": 2.58.5 + "@sentry/cli-linux-x64": 2.58.5 + "@sentry/cli-win32-arm64": 2.58.5 + "@sentry/cli-win32-i686": 2.58.5 + "@sentry/cli-win32-x64": 2.58.5 + transitivePeerDependencies: + - encoding + - supports-color + + "@sentry/core@8.55.1": {} + + "@sentry/react@8.55.1(react@19.2.5)": + dependencies: + "@sentry/browser": 8.55.1 + "@sentry/core": 8.55.1 + hoist-non-react-statics: 3.3.2 + react: 19.2.5 + + "@sentry/vite-plugin@3.6.1": + dependencies: + "@sentry/bundler-plugin-core": 3.6.1 + unplugin: 1.0.1 + transitivePeerDependencies: + - encoding + - supports-color + + "@sindresorhus/base62@1.0.0": {} + + "@standard-schema/spec@1.1.0": {} + + "@storybook/addon-docs@10.3.5(@types/react@19.2.14)(esbuild@0.27.7)(storybook@10.3.5(@testing-library/dom@10.4.1)(prettier@3.8.3)(react-dom@19.2.5(react@19.2.5))(react@19.2.5))(vite@8.0.8(@types/node@24.12.2)(esbuild@0.27.7)(jiti@2.6.1)(sass@1.99.0)(terser@5.46.1)(yaml@2.8.3))": + dependencies: + "@mdx-js/react": 3.1.1(@types/react@19.2.14)(react@19.2.5) + "@storybook/csf-plugin": 10.3.5(esbuild@0.27.7)(storybook@10.3.5(@testing-library/dom@10.4.1)(prettier@3.8.3)(react-dom@19.2.5(react@19.2.5))(react@19.2.5))(vite@8.0.8(@types/node@24.12.2)(esbuild@0.27.7)(jiti@2.6.1)(sass@1.99.0)(terser@5.46.1)(yaml@2.8.3)) + "@storybook/icons": 2.0.1(react-dom@19.2.5(react@19.2.5))(react@19.2.5) + "@storybook/react-dom-shim": 10.3.5(react-dom@19.2.5(react@19.2.5))(react@19.2.5)(storybook@10.3.5(@testing-library/dom@10.4.1)(prettier@3.8.3)(react-dom@19.2.5(react@19.2.5))(react@19.2.5)) + react: 19.2.5 + react-dom: 19.2.5(react@19.2.5) + storybook: 10.3.5(@testing-library/dom@10.4.1)(prettier@3.8.3)(react-dom@19.2.5(react@19.2.5))(react@19.2.5) + ts-dedent: 2.2.0 + transitivePeerDependencies: + - "@types/react" + - esbuild + - rollup + - vite + - webpack + + "@storybook/builder-vite@10.3.5(esbuild@0.27.7)(storybook@10.3.5(@testing-library/dom@10.4.1)(prettier@3.8.3)(react-dom@19.2.5(react@19.2.5))(react@19.2.5))(vite@8.0.8(@types/node@24.12.2)(esbuild@0.27.7)(jiti@2.6.1)(sass@1.99.0)(terser@5.46.1)(yaml@2.8.3))": + dependencies: + "@storybook/csf-plugin": 10.3.5(esbuild@0.27.7)(storybook@10.3.5(@testing-library/dom@10.4.1)(prettier@3.8.3)(react-dom@19.2.5(react@19.2.5))(react@19.2.5))(vite@8.0.8(@types/node@24.12.2)(esbuild@0.27.7)(jiti@2.6.1)(sass@1.99.0)(terser@5.46.1)(yaml@2.8.3)) + storybook: 10.3.5(@testing-library/dom@10.4.1)(prettier@3.8.3)(react-dom@19.2.5(react@19.2.5))(react@19.2.5) + ts-dedent: 2.2.0 + vite: 8.0.8(@types/node@24.12.2)(esbuild@0.27.7)(jiti@2.6.1)(sass@1.99.0)(terser@5.46.1)(yaml@2.8.3) + transitivePeerDependencies: + - esbuild + - rollup + - webpack + + "@storybook/csf-plugin@10.3.5(esbuild@0.27.7)(storybook@10.3.5(@testing-library/dom@10.4.1)(prettier@3.8.3)(react-dom@19.2.5(react@19.2.5))(react@19.2.5))(vite@8.0.8(@types/node@24.12.2)(esbuild@0.27.7)(jiti@2.6.1)(sass@1.99.0)(terser@5.46.1)(yaml@2.8.3))": + dependencies: + storybook: 10.3.5(@testing-library/dom@10.4.1)(prettier@3.8.3)(react-dom@19.2.5(react@19.2.5))(react@19.2.5) + unplugin: 2.3.11 + optionalDependencies: + esbuild: 0.27.7 + vite: 8.0.8(@types/node@24.12.2)(esbuild@0.27.7)(jiti@2.6.1)(sass@1.99.0)(terser@5.46.1)(yaml@2.8.3) + + "@storybook/global@5.0.0": {} + + "@storybook/icons@2.0.1(react-dom@19.2.5(react@19.2.5))(react@19.2.5)": + dependencies: + react: 19.2.5 + react-dom: 19.2.5(react@19.2.5) + + "@storybook/react-dom-shim@10.3.5(react-dom@19.2.5(react@19.2.5))(react@19.2.5)(storybook@10.3.5(@testing-library/dom@10.4.1)(prettier@3.8.3)(react-dom@19.2.5(react@19.2.5))(react@19.2.5))": + dependencies: + react: 19.2.5 + react-dom: 19.2.5(react@19.2.5) + storybook: 10.3.5(@testing-library/dom@10.4.1)(prettier@3.8.3)(react-dom@19.2.5(react@19.2.5))(react@19.2.5) + + "@storybook/react-vite@10.3.5(esbuild@0.27.7)(react-dom@19.2.5(react@19.2.5))(react@19.2.5)(storybook@10.3.5(@testing-library/dom@10.4.1)(prettier@3.8.3)(react-dom@19.2.5(react@19.2.5))(react@19.2.5))(typescript@5.9.3)(vite@8.0.8(@types/node@24.12.2)(esbuild@0.27.7)(jiti@2.6.1)(sass@1.99.0)(terser@5.46.1)(yaml@2.8.3))": + dependencies: + "@joshwooding/vite-plugin-react-docgen-typescript": 0.7.0(typescript@5.9.3)(vite@8.0.8(@types/node@24.12.2)(esbuild@0.27.7)(jiti@2.6.1)(sass@1.99.0)(terser@5.46.1)(yaml@2.8.3)) + "@rollup/pluginutils": 5.3.0 + "@storybook/builder-vite": 10.3.5(esbuild@0.27.7)(storybook@10.3.5(@testing-library/dom@10.4.1)(prettier@3.8.3)(react-dom@19.2.5(react@19.2.5))(react@19.2.5))(vite@8.0.8(@types/node@24.12.2)(esbuild@0.27.7)(jiti@2.6.1)(sass@1.99.0)(terser@5.46.1)(yaml@2.8.3)) + "@storybook/react": 10.3.5(react-dom@19.2.5(react@19.2.5))(react@19.2.5)(storybook@10.3.5(@testing-library/dom@10.4.1)(prettier@3.8.3)(react-dom@19.2.5(react@19.2.5))(react@19.2.5))(typescript@5.9.3) + empathic: 2.0.0 + magic-string: 0.30.21 + react: 19.2.5 + react-docgen: 8.0.3 + react-dom: 19.2.5(react@19.2.5) + resolve: 1.22.12 + storybook: 10.3.5(@testing-library/dom@10.4.1)(prettier@3.8.3)(react-dom@19.2.5(react@19.2.5))(react@19.2.5) + tsconfig-paths: 4.2.0 + vite: 8.0.8(@types/node@24.12.2)(esbuild@0.27.7)(jiti@2.6.1)(sass@1.99.0)(terser@5.46.1)(yaml@2.8.3) + transitivePeerDependencies: + - esbuild + - rollup + - supports-color + - typescript + - webpack + + "@storybook/react@10.3.5(react-dom@19.2.5(react@19.2.5))(react@19.2.5)(storybook@10.3.5(@testing-library/dom@10.4.1)(prettier@3.8.3)(react-dom@19.2.5(react@19.2.5))(react@19.2.5))(typescript@5.9.3)": + dependencies: + "@storybook/global": 5.0.0 + "@storybook/react-dom-shim": 10.3.5(react-dom@19.2.5(react@19.2.5))(react@19.2.5)(storybook@10.3.5(@testing-library/dom@10.4.1)(prettier@3.8.3)(react-dom@19.2.5(react@19.2.5))(react@19.2.5)) + react: 19.2.5 + react-docgen: 8.0.3 + react-docgen-typescript: 2.4.0(typescript@5.9.3) + react-dom: 19.2.5(react@19.2.5) + storybook: 10.3.5(@testing-library/dom@10.4.1)(prettier@3.8.3)(react-dom@19.2.5(react@19.2.5))(react@19.2.5) + optionalDependencies: + typescript: 5.9.3 + transitivePeerDependencies: + - supports-color + + "@stylistic/eslint-plugin@3.1.0(eslint@8.57.1)(typescript@5.9.3)": + dependencies: + "@typescript-eslint/utils": 8.58.2(eslint@8.57.1)(typescript@5.9.3) + eslint: 8.57.1 + eslint-visitor-keys: 4.2.1 + espree: 10.4.0 + estraverse: 5.3.0 + picomatch: 4.0.4 + transitivePeerDependencies: + - supports-color + - typescript + + "@svgr/babel-plugin-add-jsx-attribute@8.0.0(@babel/core@7.29.0)": + dependencies: + "@babel/core": 7.29.0 + + "@svgr/babel-plugin-remove-jsx-attribute@8.0.0(@babel/core@7.29.0)": + dependencies: + "@babel/core": 7.29.0 + + "@svgr/babel-plugin-remove-jsx-empty-expression@8.0.0(@babel/core@7.29.0)": + dependencies: + "@babel/core": 7.29.0 + + "@svgr/babel-plugin-replace-jsx-attribute-value@8.0.0(@babel/core@7.29.0)": + dependencies: + "@babel/core": 7.29.0 + + "@svgr/babel-plugin-svg-dynamic-title@8.0.0(@babel/core@7.29.0)": + dependencies: + "@babel/core": 7.29.0 + + "@svgr/babel-plugin-svg-em-dimensions@8.0.0(@babel/core@7.29.0)": + dependencies: + "@babel/core": 7.29.0 + + "@svgr/babel-plugin-transform-react-native-svg@8.1.0(@babel/core@7.29.0)": + dependencies: + "@babel/core": 7.29.0 + + "@svgr/babel-plugin-transform-svg-component@8.0.0(@babel/core@7.29.0)": + dependencies: + "@babel/core": 7.29.0 + + "@svgr/babel-preset@8.1.0(@babel/core@7.29.0)": + dependencies: + "@babel/core": 7.29.0 + "@svgr/babel-plugin-add-jsx-attribute": 8.0.0(@babel/core@7.29.0) + "@svgr/babel-plugin-remove-jsx-attribute": 8.0.0(@babel/core@7.29.0) + "@svgr/babel-plugin-remove-jsx-empty-expression": 8.0.0(@babel/core@7.29.0) + "@svgr/babel-plugin-replace-jsx-attribute-value": 8.0.0(@babel/core@7.29.0) + "@svgr/babel-plugin-svg-dynamic-title": 8.0.0(@babel/core@7.29.0) + "@svgr/babel-plugin-svg-em-dimensions": 8.0.0(@babel/core@7.29.0) + "@svgr/babel-plugin-transform-react-native-svg": 8.1.0(@babel/core@7.29.0) + "@svgr/babel-plugin-transform-svg-component": 8.0.0(@babel/core@7.29.0) + + "@svgr/core@8.1.0(typescript@5.9.3)": + dependencies: + "@babel/core": 7.29.0 + "@svgr/babel-preset": 8.1.0(@babel/core@7.29.0) + camelcase: 6.3.0 + cosmiconfig: 8.3.6(typescript@5.9.3) + snake-case: 3.0.4 + transitivePeerDependencies: + - supports-color + - typescript + + "@svgr/hast-util-to-babel-ast@8.0.0": + dependencies: + "@babel/types": 7.29.0 + entities: 4.5.0 + + "@svgr/plugin-jsx@8.1.0(@svgr/core@8.1.0(typescript@5.9.3))": + dependencies: + "@babel/core": 7.29.0 + "@svgr/babel-preset": 8.1.0(@babel/core@7.29.0) + "@svgr/core": 8.1.0(typescript@5.9.3) + "@svgr/hast-util-to-babel-ast": 8.0.0 + svg-parser: 2.0.4 + transitivePeerDependencies: + - supports-color + + "@testing-library/dom@10.4.1": + dependencies: + "@babel/code-frame": 7.29.0 + "@babel/runtime": 7.29.2 + "@types/aria-query": 5.0.4 + aria-query: 5.3.0 + dom-accessibility-api: 0.5.16 + lz-string: 1.5.0 + picocolors: 1.1.1 + pretty-format: 27.5.1 + + "@testing-library/jest-dom@6.9.1": + dependencies: + "@adobe/css-tools": 4.4.4 + aria-query: 5.3.2 + css.escape: 1.5.1 + dom-accessibility-api: 0.6.3 + picocolors: 1.1.1 + redent: 3.0.0 + + "@testing-library/react@16.3.2(@testing-library/dom@10.4.1)(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5)": + dependencies: + "@babel/runtime": 7.29.2 + "@testing-library/dom": 10.4.1 + react: 19.2.5 + react-dom: 19.2.5(react@19.2.5) + optionalDependencies: + "@types/react": 19.2.14 + "@types/react-dom": 19.2.3(@types/react@19.2.14) + + "@testing-library/user-event@14.6.1(@testing-library/dom@10.4.1)": + dependencies: + "@testing-library/dom": 10.4.1 + + "@tybys/wasm-util@0.10.1": + dependencies: + tslib: 2.8.1 + optional: true + + "@types/aria-query@5.0.4": {} + + "@types/babel__core@7.20.5": + dependencies: + "@babel/parser": 7.29.2 + "@babel/types": 7.29.0 + "@types/babel__generator": 7.27.0 + "@types/babel__template": 7.4.4 + "@types/babel__traverse": 7.28.0 + + "@types/babel__generator@7.27.0": + dependencies: + "@babel/types": 7.29.0 + + "@types/babel__template@7.4.4": + dependencies: + "@babel/parser": 7.29.2 + "@babel/types": 7.29.0 + + "@types/babel__traverse@7.28.0": + dependencies: + "@babel/types": 7.29.0 + + "@types/chai@5.2.3": + dependencies: + "@types/deep-eql": 4.0.2 + assertion-error: 2.0.1 + + "@types/content-type@1.1.9": {} + + "@types/deep-eql@4.0.2": {} + + "@types/doctrine@0.0.9": {} + + "@types/dom-mediacapture-record@1.0.22": {} + + "@types/dom-mediacapture-transform@0.1.11": + dependencies: + "@types/dom-webcodecs": 0.1.18 + + "@types/dom-webcodecs@0.1.18": {} + + "@types/estree@1.0.8": {} + + "@types/events@3.0.3": {} + + "@types/glob-to-regexp@0.4.4": {} + + "@types/grecaptcha@3.0.9": {} + + "@types/jsdom@21.1.7": + dependencies: + "@types/node": 24.12.2 + "@types/tough-cookie": 4.0.5 + parse5: 7.3.0 + + "@types/json-schema@7.0.15": {} + + "@types/json5@0.0.29": {} + + "@types/lodash-es@4.17.12": + dependencies: + "@types/lodash": 4.17.24 + + "@types/lodash@4.17.24": {} + + "@types/mdx@2.0.13": {} + + "@types/minimatch@3.0.5": {} + + "@types/node@24.12.2": + dependencies: + undici-types: 7.16.0 + + "@types/normalize-package-data@2.4.4": {} + + "@types/pako@2.0.4": {} + + "@types/qrcode@1.5.6": + dependencies: + "@types/node": 24.12.2 + + "@types/react-dom@19.2.3(@types/react@19.2.14)": + dependencies: + "@types/react": 19.2.14 + + "@types/react@19.2.14": + dependencies: + csstype: 3.2.3 + + "@types/resolve@1.20.6": {} + + "@types/sdp-transform@2.15.0": {} + + "@types/semver@7.7.1": {} + + "@types/symlink-or-copy@1.2.2": {} + + "@types/tough-cookie@4.0.5": {} + + "@types/uuid@10.0.0": {} + + "@types/yargs-parser@21.0.3": {} + + "@types/yargs@17.0.35": + dependencies: + "@types/yargs-parser": 21.0.3 + + "@typescript-eslint/eslint-plugin@8.58.2(@typescript-eslint/parser@8.58.2(eslint@8.57.1)(typescript@5.9.3))(eslint@8.57.1)(typescript@5.9.3)": + dependencies: + "@eslint-community/regexpp": 4.12.2 + "@typescript-eslint/parser": 8.58.2(eslint@8.57.1)(typescript@5.9.3) + "@typescript-eslint/scope-manager": 8.58.2 + "@typescript-eslint/type-utils": 8.58.2(eslint@8.57.1)(typescript@5.9.3) + "@typescript-eslint/utils": 8.58.2(eslint@8.57.1)(typescript@5.9.3) + "@typescript-eslint/visitor-keys": 8.58.2 + eslint: 8.57.1 + ignore: 7.0.5 + natural-compare: 1.4.0 + ts-api-utils: 2.5.0(typescript@5.9.3) + typescript: 5.9.3 + transitivePeerDependencies: + - supports-color + + "@typescript-eslint/experimental-utils@5.62.0(eslint@8.57.1)(typescript@5.9.3)": + dependencies: + "@typescript-eslint/utils": 5.62.0(eslint@8.57.1)(typescript@5.9.3) + eslint: 8.57.1 + transitivePeerDependencies: + - supports-color + - typescript + + "@typescript-eslint/parser@8.58.2(eslint@8.57.1)(typescript@5.9.3)": + dependencies: + "@typescript-eslint/scope-manager": 8.58.2 + "@typescript-eslint/types": 8.58.2 + "@typescript-eslint/typescript-estree": 8.58.2(typescript@5.9.3) + "@typescript-eslint/visitor-keys": 8.58.2 + debug: 4.4.3 + eslint: 8.57.1 + typescript: 5.9.3 + transitivePeerDependencies: + - supports-color + + "@typescript-eslint/project-service@8.58.2(typescript@5.9.3)": + dependencies: + "@typescript-eslint/tsconfig-utils": 8.58.2(typescript@5.9.3) + "@typescript-eslint/types": 8.58.2 + debug: 4.4.3 + typescript: 5.9.3 + transitivePeerDependencies: + - supports-color + + "@typescript-eslint/scope-manager@5.62.0": + dependencies: + "@typescript-eslint/types": 5.62.0 + "@typescript-eslint/visitor-keys": 5.62.0 + + "@typescript-eslint/scope-manager@8.58.2": + dependencies: + "@typescript-eslint/types": 8.58.2 + "@typescript-eslint/visitor-keys": 8.58.2 + + "@typescript-eslint/tsconfig-utils@8.58.2(typescript@5.9.3)": + dependencies: + typescript: 5.9.3 + + "@typescript-eslint/type-utils@8.58.2(eslint@8.57.1)(typescript@5.9.3)": + dependencies: + "@typescript-eslint/types": 8.58.2 + "@typescript-eslint/typescript-estree": 8.58.2(typescript@5.9.3) + "@typescript-eslint/utils": 8.58.2(eslint@8.57.1)(typescript@5.9.3) + debug: 4.4.3 + eslint: 8.57.1 + ts-api-utils: 2.5.0(typescript@5.9.3) + typescript: 5.9.3 + transitivePeerDependencies: + - supports-color + + "@typescript-eslint/types@5.62.0": {} + + "@typescript-eslint/types@8.58.2": {} + + "@typescript-eslint/typescript-estree@5.62.0(typescript@5.9.3)": + dependencies: + "@typescript-eslint/types": 5.62.0 + "@typescript-eslint/visitor-keys": 5.62.0 + debug: 4.4.3 + globby: 11.1.0 + is-glob: 4.0.3 + semver: 7.7.4 + tsutils: 3.21.0(typescript@5.9.3) + optionalDependencies: + typescript: 5.9.3 + transitivePeerDependencies: + - supports-color + + "@typescript-eslint/typescript-estree@8.58.2(typescript@5.9.3)": + dependencies: + "@typescript-eslint/project-service": 8.58.2(typescript@5.9.3) + "@typescript-eslint/tsconfig-utils": 8.58.2(typescript@5.9.3) + "@typescript-eslint/types": 8.58.2 + "@typescript-eslint/visitor-keys": 8.58.2 + debug: 4.4.3 + minimatch: 10.2.5 + semver: 7.7.4 + tinyglobby: 0.2.16 + ts-api-utils: 2.5.0(typescript@5.9.3) + typescript: 5.9.3 + transitivePeerDependencies: + - supports-color + + "@typescript-eslint/utils@5.62.0(eslint@8.57.1)(typescript@5.9.3)": + dependencies: + "@eslint-community/eslint-utils": 4.9.1(eslint@8.57.1) + "@types/json-schema": 7.0.15 + "@types/semver": 7.7.1 + "@typescript-eslint/scope-manager": 5.62.0 + "@typescript-eslint/types": 5.62.0 + "@typescript-eslint/typescript-estree": 5.62.0(typescript@5.9.3) + eslint: 8.57.1 + eslint-scope: 5.1.1 + semver: 7.7.4 + transitivePeerDependencies: + - supports-color + - typescript + + "@typescript-eslint/utils@8.58.2(eslint@8.57.1)(typescript@5.9.3)": + dependencies: + "@eslint-community/eslint-utils": 4.9.1(eslint@8.57.1) + "@typescript-eslint/scope-manager": 8.58.2 + "@typescript-eslint/types": 8.58.2 + "@typescript-eslint/typescript-estree": 8.58.2(typescript@5.9.3) + eslint: 8.57.1 + typescript: 5.9.3 + transitivePeerDependencies: + - supports-color + + "@typescript-eslint/visitor-keys@5.62.0": + dependencies: + "@typescript-eslint/types": 5.62.0 + eslint-visitor-keys: 3.4.3 + + "@typescript-eslint/visitor-keys@8.58.2": + dependencies: + "@typescript-eslint/types": 8.58.2 + eslint-visitor-keys: 5.0.1 + + "@ungap/structured-clone@1.3.0": {} + + "@use-gesture/core@10.3.1": {} + + "@use-gesture/react@10.3.1(react@19.2.5)": + dependencies: + "@use-gesture/core": 10.3.1 + react: 19.2.5 + + "@vector-im/compound-design-tokens@10.1.0(@types/react@19.2.14)(react@19.2.5)": + optionalDependencies: + "@types/react": 19.2.14 + react: 19.2.5 + + "@vector-im/compound-web@9.2.0(@fontsource/inconsolata@5.2.8)(@fontsource/inter@5.2.8)(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(@vector-im/compound-design-tokens@10.1.0(@types/react@19.2.14)(react@19.2.5))(react-dom@19.2.5(react@19.2.5))(react@19.2.5)": + dependencies: + "@floating-ui/react": 0.27.19(react-dom@19.2.5(react@19.2.5))(react@19.2.5) + "@fontsource/inconsolata": 5.2.8 + "@fontsource/inter": 5.2.8 + "@radix-ui/react-context-menu": 2.2.16(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5) + "@radix-ui/react-dropdown-menu": 2.1.16(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5) + "@radix-ui/react-form": 0.1.8(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5) + "@radix-ui/react-progress": 1.1.8(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5) + "@radix-ui/react-separator": 1.1.8(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5) + "@radix-ui/react-slot": 1.2.4(@types/react@19.2.14)(react@19.2.5) + "@vector-im/compound-design-tokens": 10.1.0(@types/react@19.2.14)(react@19.2.5) + classnames: 2.5.1 + react: 19.2.5 + vaul: 1.1.2(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5) + optionalDependencies: + "@types/react": 19.2.14 + transitivePeerDependencies: + - "@types/react-dom" + - react-dom + + "@vitejs/plugin-react@4.7.0(vite@8.0.8(@types/node@24.12.2)(esbuild@0.27.7)(jiti@2.6.1)(sass@1.99.0)(terser@5.46.1)(yaml@2.8.3))": + dependencies: + "@babel/core": 7.29.0 + "@babel/plugin-transform-react-jsx-self": 7.27.1(@babel/core@7.29.0) + "@babel/plugin-transform-react-jsx-source": 7.27.1(@babel/core@7.29.0) + "@rolldown/pluginutils": 1.0.0-beta.27 + "@types/babel__core": 7.20.5 + react-refresh: 0.17.0 + vite: 8.0.8(@types/node@24.12.2)(esbuild@0.27.7)(jiti@2.6.1)(sass@1.99.0)(terser@5.46.1)(yaml@2.8.3) + transitivePeerDependencies: + - supports-color + + "@vitest/coverage-v8@4.1.4(vitest@4.1.4)": + dependencies: + "@bcoe/v8-coverage": 1.0.2 + "@vitest/utils": 4.1.4 + ast-v8-to-istanbul: 1.0.0 + istanbul-lib-coverage: 3.2.2 + istanbul-lib-report: 3.0.1 + istanbul-reports: 3.2.0 + magicast: 0.5.2 + obug: 2.1.1 + std-env: 4.1.0 + tinyrainbow: 3.1.0 + vitest: 4.1.4(@types/node@24.12.2)(@vitest/coverage-v8@4.1.4)(jsdom@26.1.0)(vite@8.0.8(@types/node@24.12.2)(esbuild@0.27.7)(jiti@2.6.1)(sass@1.99.0)(terser@5.46.1)(yaml@2.8.3)) + + "@vitest/expect@3.2.4": + dependencies: + "@types/chai": 5.2.3 + "@vitest/spy": 3.2.4 + "@vitest/utils": 3.2.4 + chai: 5.3.3 + tinyrainbow: 2.0.0 + + "@vitest/expect@4.1.4": + dependencies: + "@standard-schema/spec": 1.1.0 + "@types/chai": 5.2.3 + "@vitest/spy": 4.1.4 + "@vitest/utils": 4.1.4 + chai: 6.2.2 + tinyrainbow: 3.1.0 + + "@vitest/mocker@4.1.4(vite@8.0.8(@types/node@24.12.2)(esbuild@0.27.7)(jiti@2.6.1)(sass@1.99.0)(terser@5.46.1)(yaml@2.8.3))": + dependencies: + "@vitest/spy": 4.1.4 + estree-walker: 3.0.3 + magic-string: 0.30.21 + optionalDependencies: + vite: 8.0.8(@types/node@24.12.2)(esbuild@0.27.7)(jiti@2.6.1)(sass@1.99.0)(terser@5.46.1)(yaml@2.8.3) + + "@vitest/pretty-format@3.2.4": + dependencies: + tinyrainbow: 2.0.0 + + "@vitest/pretty-format@4.1.4": + dependencies: + tinyrainbow: 3.1.0 + + "@vitest/runner@4.1.4": + dependencies: + "@vitest/utils": 4.1.4 + pathe: 2.0.3 + + "@vitest/snapshot@4.1.4": + dependencies: + "@vitest/pretty-format": 4.1.4 + "@vitest/utils": 4.1.4 + magic-string: 0.30.21 + pathe: 2.0.3 + + "@vitest/spy@3.2.4": + dependencies: + tinyspy: 4.0.4 + + "@vitest/spy@4.1.4": {} + + "@vitest/utils@3.2.4": + dependencies: + "@vitest/pretty-format": 3.2.4 + loupe: 3.2.1 + tinyrainbow: 2.0.0 + + "@vitest/utils@4.1.4": + dependencies: + "@vitest/pretty-format": 4.1.4 + convert-source-map: 2.0.0 + tinyrainbow: 3.1.0 + + "@webcontainer/env@1.1.1": {} + + acorn-jsx@5.3.2(acorn@8.16.0): + dependencies: + acorn: 8.16.0 + + acorn@8.16.0: {} + + agent-base@6.0.2: + dependencies: + debug: 4.4.3 + transitivePeerDependencies: + - supports-color + + agent-base@7.1.4: {} + + ajv@6.14.0: + dependencies: + fast-deep-equal: 3.1.3 + fast-json-stable-stringify: 2.1.0 + json-schema-traverse: 0.4.1 + uri-js: 4.4.1 + + another-json@0.2.0: {} + + ansi-regex@5.0.1: {} + + ansi-regex@6.2.2: {} + + ansi-styles@4.3.0: + dependencies: + color-convert: 2.0.1 + + ansi-styles@5.2.0: {} + + ansi-styles@6.2.3: {} + + anymatch@3.1.3: + dependencies: + normalize-path: 3.0.0 + picomatch: 2.3.2 + + are-docs-informative@0.0.2: {} + + argparse@2.0.1: {} + + aria-hidden@1.2.6: + dependencies: + tslib: 2.8.1 + + aria-query@5.3.0: + dependencies: + dequal: 2.0.3 + + aria-query@5.3.2: {} + + array-buffer-byte-length@1.0.2: + dependencies: + call-bound: 1.0.4 + is-array-buffer: 3.0.5 + + array-includes@3.1.9: + dependencies: + call-bind: 1.0.9 + call-bound: 1.0.4 + define-properties: 1.2.1 + es-abstract: 1.24.2 + es-object-atoms: 1.1.1 + get-intrinsic: 1.3.0 + is-string: 1.1.1 + math-intrinsics: 1.1.0 + + array-union@2.1.0: {} + + array.prototype.findlast@1.2.5: + dependencies: + call-bind: 1.0.9 + define-properties: 1.2.1 + es-abstract: 1.24.2 + es-errors: 1.3.0 + es-object-atoms: 1.1.1 + es-shim-unscopables: 1.1.0 + + array.prototype.findlastindex@1.2.6: + dependencies: + call-bind: 1.0.9 + call-bound: 1.0.4 + define-properties: 1.2.1 + es-abstract: 1.24.2 + es-errors: 1.3.0 + es-object-atoms: 1.1.1 + es-shim-unscopables: 1.1.0 + + array.prototype.flat@1.3.3: + dependencies: + call-bind: 1.0.9 + define-properties: 1.2.1 + es-abstract: 1.24.2 + es-shim-unscopables: 1.1.0 + + array.prototype.flatmap@1.3.3: + dependencies: + call-bind: 1.0.9 + define-properties: 1.2.1 + es-abstract: 1.24.2 + es-shim-unscopables: 1.1.0 + + array.prototype.tosorted@1.1.4: + dependencies: + call-bind: 1.0.9 + define-properties: 1.2.1 + es-abstract: 1.24.2 + es-errors: 1.3.0 + es-shim-unscopables: 1.1.0 + + arraybuffer.prototype.slice@1.0.4: + dependencies: + array-buffer-byte-length: 1.0.2 + call-bind: 1.0.9 + define-properties: 1.2.1 + es-abstract: 1.24.2 + es-errors: 1.3.0 + get-intrinsic: 1.3.0 + is-array-buffer: 3.0.5 + + asn1.js@4.10.1: + dependencies: + bn.js: 4.12.3 + inherits: 2.0.4 + minimalistic-assert: 1.0.1 + + assert@2.1.0: + dependencies: + call-bind: 1.0.9 + is-nan: 1.3.2 + object-is: 1.1.6 + object.assign: 4.1.7 + util: 0.12.5 + + assertion-error@2.0.1: {} + + ast-types-flow@0.0.8: {} + + ast-types@0.16.1: + dependencies: + tslib: 2.8.1 + + ast-v8-to-istanbul@1.0.0: + dependencies: + "@jridgewell/trace-mapping": 0.3.31 + estree-walker: 3.0.3 + js-tokens: 10.0.0 + + async-function@1.0.0: {} + + async@3.2.6: {} + + autoprefixer@10.5.0(postcss@8.5.10): + dependencies: + browserslist: 4.28.2 + caniuse-lite: 1.0.30001788 + fraction.js: 5.3.4 + picocolors: 1.1.1 + postcss: 8.5.10 + postcss-value-parser: 4.2.0 + + available-typed-arrays@1.0.7: + dependencies: + possible-typed-array-names: 1.1.0 + + axe-core@4.11.3: {} + + axobject-query@4.1.0: {} + + b4a@1.8.0: {} + + babel-plugin-polyfill-corejs2@0.4.17(@babel/core@7.29.0): + dependencies: + "@babel/compat-data": 7.29.0 + "@babel/core": 7.29.0 + "@babel/helper-define-polyfill-provider": 0.6.8(@babel/core@7.29.0) + semver: 6.3.1 + transitivePeerDependencies: + - supports-color + + babel-plugin-polyfill-corejs3@0.14.2(@babel/core@7.29.0): + dependencies: + "@babel/core": 7.29.0 + "@babel/helper-define-polyfill-provider": 0.6.8(@babel/core@7.29.0) + core-js-compat: 3.49.0 + transitivePeerDependencies: + - supports-color + + babel-plugin-polyfill-regenerator@0.6.8(@babel/core@7.29.0): + dependencies: + "@babel/core": 7.29.0 + "@babel/helper-define-polyfill-provider": 0.6.8(@babel/core@7.29.0) + transitivePeerDependencies: + - supports-color + + babel-plugin-transform-vite-meta-env@1.0.3: + dependencies: + "@babel/runtime": 7.29.2 + "@types/babel__core": 7.20.5 + + balanced-match@4.0.4: {} + + bare-events@2.8.2: {} + + base-x@5.0.1: {} + + base64-js@1.5.1: {} + + baseline-browser-mapping@2.10.19: {} + + before-after-hook@2.2.3: {} + + bent@7.3.12: + dependencies: + bytesish: 0.4.4 + caseless: 0.12.0 + is-stream: 2.0.1 + + binary-extensions@2.3.0: {} + + bl@5.1.0: + dependencies: + buffer: 6.0.3 + inherits: 2.0.4 + readable-stream: 3.6.2 + + bn.js@4.12.3: {} + + bn.js@5.2.3: {} + + boolbase@1.0.0: {} + + brace-expansion@5.0.5: + dependencies: + balanced-match: 4.0.4 + + braces@3.0.3: + dependencies: + fill-range: 7.1.1 + + broccoli-node-api@1.7.0: {} + + broccoli-node-info@2.2.0: {} + + broccoli-output-wrapper@3.2.5: + dependencies: + fs-extra: 8.1.0 + heimdalljs-logger: 0.1.10 + symlink-or-copy: 1.3.1 + transitivePeerDependencies: + - supports-color + + broccoli-plugin@4.0.7: + dependencies: + broccoli-node-api: 1.7.0 + broccoli-output-wrapper: 3.2.5 + fs-merger: 3.2.1 + promise-map-series: 0.3.0 + quick-temp: 0.1.9 + rimraf: 3.0.2 + symlink-or-copy: 1.3.1 + transitivePeerDependencies: + - supports-color + + brorand@1.1.0: {} + + browser-resolve@2.0.0: + dependencies: + resolve: 1.22.12 + + browserify-aes@1.2.0: + dependencies: + buffer-xor: 1.0.3 + cipher-base: 1.0.7 + create-hash: 1.2.0 + evp_bytestokey: 1.0.3 + inherits: 2.0.4 + safe-buffer: 5.2.1 + + browserify-cipher@1.0.1: + dependencies: + browserify-aes: 1.2.0 + browserify-des: 1.0.2 + evp_bytestokey: 1.0.3 + + browserify-des@1.0.2: + dependencies: + cipher-base: 1.0.7 + des.js: 1.1.0 + inherits: 2.0.4 + safe-buffer: 5.2.1 + + browserify-rsa@4.1.1: + dependencies: + bn.js: 5.2.3 + randombytes: 2.1.0 + safe-buffer: 5.2.1 + + browserify-sign@4.2.5: + dependencies: + bn.js: 5.2.3 + browserify-rsa: 4.1.1 + create-hash: 1.2.0 + create-hmac: 1.1.7 + elliptic: 6.6.1 + inherits: 2.0.4 + parse-asn1: 5.1.9 + readable-stream: 2.3.8 + safe-buffer: 5.2.1 + + browserify-zlib@0.2.0: + dependencies: + pako: 1.0.11 + + browserslist@4.28.2: + dependencies: + baseline-browser-mapping: 2.10.19 + caniuse-lite: 1.0.30001788 + electron-to-chromium: 1.5.339 + node-releases: 2.0.37 + update-browserslist-db: 1.2.3(browserslist@4.28.2) + + bs58@6.0.0: + dependencies: + base-x: 5.0.1 + + buffer-from@1.1.2: {} + + buffer-xor@1.0.3: {} + + buffer@5.7.1: + dependencies: + base64-js: 1.5.1 + ieee754: 1.2.1 + + buffer@6.0.3: + dependencies: + base64-js: 1.5.1 + ieee754: 1.2.1 + + builtin-modules@3.3.0: {} + + builtin-status-codes@3.0.0: {} + + bundle-name@4.1.0: + dependencies: + run-applescript: 7.1.0 + + bytesish@0.4.4: {} + + call-bind-apply-helpers@1.0.2: + dependencies: + es-errors: 1.3.0 + function-bind: 1.1.2 + + call-bind@1.0.9: + dependencies: + call-bind-apply-helpers: 1.0.2 + es-define-property: 1.0.1 + get-intrinsic: 1.3.0 + set-function-length: 1.2.2 + + call-bound@1.0.4: + dependencies: + call-bind-apply-helpers: 1.0.2 + get-intrinsic: 1.3.0 + + callsites@3.1.0: {} + + camel-case@4.1.2: + dependencies: + pascal-case: 3.1.2 + tslib: 2.8.1 + + camelcase@5.3.1: {} + + camelcase@6.3.0: {} + + caniuse-lite@1.0.30001788: {} + + caseless@0.12.0: {} + + chai@5.3.3: + dependencies: + assertion-error: 2.0.1 + check-error: 2.1.3 + deep-eql: 5.0.2 + loupe: 3.2.1 + pathval: 2.0.1 + + chai@6.2.2: {} + + chalk@4.1.2: + dependencies: + ansi-styles: 4.3.0 + supports-color: 7.2.0 + + chalk@5.6.2: {} + + check-error@2.1.3: {} + + cheerio-select@2.1.0: + dependencies: + boolbase: 1.0.0 + css-select: 5.2.2 + css-what: 6.2.2 + domelementtype: 2.3.0 + domhandler: 5.0.3 + domutils: 3.2.2 + + cheerio@1.2.0: + dependencies: + cheerio-select: 2.1.0 + dom-serializer: 2.0.0 + domhandler: 5.0.3 + domutils: 3.2.2 + encoding-sniffer: 0.2.1 + htmlparser2: 10.1.0 + parse5: 7.3.0 + parse5-htmlparser2-tree-adapter: 7.1.0 + parse5-parser-stream: 7.1.2 + undici: 7.25.0 + whatwg-mimetype: 4.0.0 + + chokidar@3.6.0: + dependencies: + anymatch: 3.1.3 + braces: 3.0.3 + glob-parent: 5.1.2 + is-binary-path: 2.1.0 + is-glob: 4.0.3 + normalize-path: 3.0.0 + readdirp: 3.6.0 + optionalDependencies: + fsevents: 2.3.3 + + chokidar@4.0.3: + dependencies: + readdirp: 4.1.2 + + ci-info@4.4.0: {} + + cipher-base@1.0.7: + dependencies: + inherits: 2.0.4 + safe-buffer: 5.2.1 + to-buffer: 1.2.2 + + classnames@2.5.1: {} + + clean-css@5.3.3: + dependencies: + source-map: 0.6.1 + + clean-regexp@1.0.0: + dependencies: + escape-string-regexp: 1.0.5 + + cliui@6.0.0: + dependencies: + string-width: 4.2.3 + strip-ansi: 6.0.1 + wrap-ansi: 6.2.0 + + cliui@8.0.1: + dependencies: + string-width: 4.2.3 + strip-ansi: 6.0.1 + wrap-ansi: 7.0.0 + + clone@2.1.2: {} + + clsx@2.1.1: {} + + color-convert@2.0.1: + dependencies: + color-name: 1.1.4 + + color-name@1.1.4: {} + + colorette@2.0.20: {} + + colors@1.4.0: {} + + commander@12.1.0: {} + + commander@2.20.3: {} + + commander@8.3.0: {} + + comment-parser@1.4.1: {} + + common-tags@1.8.2: {} + + connect-history-api-fallback@1.6.0: {} + + consola@2.15.3: {} + + console-browserify@1.2.0: {} + + constants-browserify@1.0.0: {} + + content-type@1.0.5: {} + + convert-source-map@2.0.0: {} + + cookie@1.1.1: {} + + copy-to-clipboard@3.3.3: + dependencies: + toggle-selection: 1.0.6 + + core-js-compat@3.49.0: + dependencies: + browserslist: 4.28.2 + + core-util-is@1.0.3: {} + + cosmiconfig@8.3.6(typescript@5.9.3): + dependencies: + import-fresh: 3.3.1 + js-yaml: 4.1.1 + parse-json: 5.2.0 + path-type: 4.0.0 + optionalDependencies: + typescript: 5.9.3 + + create-ecdh@4.0.4: + dependencies: + bn.js: 4.12.3 + elliptic: 6.6.1 + + create-hash@1.2.0: + dependencies: + cipher-base: 1.0.7 + inherits: 2.0.4 + md5.js: 1.3.5 + ripemd160: 2.0.3 + sha.js: 2.4.12 + + create-hmac@1.1.7: + dependencies: + cipher-base: 1.0.7 + create-hash: 1.2.0 + inherits: 2.0.4 + ripemd160: 2.0.3 + safe-buffer: 5.2.1 + sha.js: 2.4.12 + + create-require@1.1.1: {} + + cross-spawn@7.0.6: + dependencies: + path-key: 3.1.1 + shebang-command: 2.0.0 + which: 2.0.2 + + crypto-browserify@3.12.1: + dependencies: + browserify-cipher: 1.0.1 + browserify-sign: 4.2.5 + create-ecdh: 4.0.4 + create-hash: 1.2.0 + create-hmac: 1.1.7 + diffie-hellman: 5.0.3 + hash-base: 3.0.5 + inherits: 2.0.4 + pbkdf2: 3.1.5 + public-encrypt: 4.0.3 + randombytes: 2.1.0 + randomfill: 1.0.4 + + css-blank-pseudo@7.0.1(postcss@8.5.10): + dependencies: + postcss: 8.5.10 + postcss-selector-parser: 7.1.1 + + css-has-pseudo@7.0.3(postcss@8.5.10): + dependencies: + "@csstools/selector-specificity": 5.0.0(postcss-selector-parser@7.1.1) + postcss: 8.5.10 + postcss-selector-parser: 7.1.1 + postcss-value-parser: 4.2.0 + + css-prefers-color-scheme@10.0.0(postcss@8.5.10): + dependencies: + postcss: 8.5.10 + + css-select@4.3.0: + dependencies: + boolbase: 1.0.0 + css-what: 6.2.2 + domhandler: 4.3.1 + domutils: 2.8.0 + nth-check: 2.1.1 + + css-select@5.2.2: + dependencies: + boolbase: 1.0.0 + css-what: 6.2.2 + domhandler: 5.0.3 + domutils: 3.2.2 + nth-check: 2.1.1 + + css-what@6.2.2: {} + + css.escape@1.5.1: {} + + cssdb@8.8.0: {} + + cssesc@3.0.0: {} + + cssstyle@4.6.0: + dependencies: + "@asamuzakjp/css-color": 3.2.0 + rrweb-cssom: 0.8.0 + + csstype@3.2.3: {} + + damerau-levenshtein@1.0.8: {} + + data-urls@5.0.0: + dependencies: + whatwg-mimetype: 4.0.0 + whatwg-url: 14.2.0 + + data-view-buffer@1.0.2: + dependencies: + call-bound: 1.0.4 + es-errors: 1.3.0 + is-data-view: 1.0.2 + + data-view-byte-length@1.0.2: + dependencies: + call-bound: 1.0.4 + es-errors: 1.3.0 + is-data-view: 1.0.2 + + data-view-byte-offset@1.0.1: + dependencies: + call-bound: 1.0.4 + es-errors: 1.3.0 + is-data-view: 1.0.2 + + debug@2.6.9: + dependencies: + ms: 2.0.0 + + debug@3.2.7: + dependencies: + ms: 2.1.3 + + debug@4.4.3: + dependencies: + ms: 2.1.3 + + decamelize@1.2.0: {} + + decamelize@5.0.1: {} + + decimal.js@10.6.0: {} + + deep-eql@5.0.2: {} + + deep-is@0.1.4: {} + + default-browser-id@5.0.1: {} + + default-browser@5.5.0: + dependencies: + bundle-name: 4.1.0 + default-browser-id: 5.0.1 + + define-data-property@1.1.4: + dependencies: + es-define-property: 1.0.1 + es-errors: 1.3.0 + gopd: 1.2.0 + + define-lazy-prop@3.0.0: {} + + define-properties@1.2.1: + dependencies: + define-data-property: 1.1.4 + has-property-descriptors: 1.0.2 + object-keys: 1.1.1 + + deprecation@2.3.1: {} + + dequal@2.0.3: {} + + des.js@1.1.0: + dependencies: + inherits: 2.0.4 + minimalistic-assert: 1.0.1 + + detect-libc@2.1.2: {} + + detect-node-es@1.1.0: {} + + diffie-hellman@5.0.3: + dependencies: + bn.js: 4.12.3 + miller-rabin: 4.0.1 + randombytes: 2.1.0 + + dijkstrajs@1.0.3: {} + + dir-glob@3.0.1: + dependencies: + path-type: 4.0.0 + + doctrine@2.1.0: + dependencies: + esutils: 2.0.3 + + doctrine@3.0.0: + dependencies: + esutils: 2.0.3 + + dom-accessibility-api@0.5.16: {} + + dom-accessibility-api@0.6.3: {} + + dom-serializer@1.4.1: + dependencies: + domelementtype: 2.3.0 + domhandler: 4.3.1 + entities: 2.2.0 + + dom-serializer@2.0.0: + dependencies: + domelementtype: 2.3.0 + domhandler: 5.0.3 + entities: 4.5.0 + + domain-browser@4.22.0: {} + + domelementtype@2.3.0: {} + + domhandler@4.3.1: + dependencies: + domelementtype: 2.3.0 + + domhandler@5.0.3: + dependencies: + domelementtype: 2.3.0 + + domutils@2.8.0: + dependencies: + dom-serializer: 1.4.1 + domelementtype: 2.3.0 + domhandler: 4.3.1 + + domutils@3.2.2: + dependencies: + dom-serializer: 2.0.0 + domelementtype: 2.3.0 + domhandler: 5.0.3 + + dot-case@3.0.4: + dependencies: + no-case: 3.0.4 + tslib: 2.8.1 + + dotenv-expand@8.0.3: {} + + dotenv@16.6.1: {} + + dunder-proto@1.0.1: + dependencies: + call-bind-apply-helpers: 1.0.2 + es-errors: 1.3.0 + gopd: 1.2.0 + + eastasianwidth@0.2.0: {} + + ejs@3.1.10: + dependencies: + jake: 10.9.4 + + electron-to-chromium@1.5.339: {} + + elliptic@6.6.1: + dependencies: + bn.js: 4.12.3 + brorand: 1.1.0 + hash.js: 1.1.7 + hmac-drbg: 1.0.1 + inherits: 2.0.4 + minimalistic-assert: 1.0.1 + minimalistic-crypto-utils: 1.0.1 + + emoji-regex@8.0.0: {} + + emoji-regex@9.2.2: {} + + empathic@2.0.0: {} + + encoding-sniffer@0.2.1: + dependencies: + iconv-lite: 0.6.3 + whatwg-encoding: 3.1.1 + + ensure-posix-path@1.1.1: {} + + entities@2.2.0: {} + + entities@4.5.0: {} + + entities@6.0.1: {} + + entities@7.0.1: {} + + eol@0.9.1: {} + + error-ex@1.3.4: + dependencies: + is-arrayish: 0.2.1 + + es-abstract@1.24.2: + dependencies: + array-buffer-byte-length: 1.0.2 + arraybuffer.prototype.slice: 1.0.4 + available-typed-arrays: 1.0.7 + call-bind: 1.0.9 + call-bound: 1.0.4 + data-view-buffer: 1.0.2 + data-view-byte-length: 1.0.2 + data-view-byte-offset: 1.0.1 + es-define-property: 1.0.1 + es-errors: 1.3.0 + es-object-atoms: 1.1.1 + es-set-tostringtag: 2.1.0 + es-to-primitive: 1.3.0 + function.prototype.name: 1.1.8 + get-intrinsic: 1.3.0 + get-proto: 1.0.1 + get-symbol-description: 1.1.0 + globalthis: 1.0.4 + gopd: 1.2.0 + has-property-descriptors: 1.0.2 + has-proto: 1.2.0 + has-symbols: 1.1.0 + hasown: 2.0.2 + internal-slot: 1.1.0 + is-array-buffer: 3.0.5 + is-callable: 1.2.7 + is-data-view: 1.0.2 + is-negative-zero: 2.0.3 + is-regex: 1.2.1 + is-set: 2.0.3 + is-shared-array-buffer: 1.0.4 + is-string: 1.1.1 + is-typed-array: 1.1.15 + is-weakref: 1.1.1 + math-intrinsics: 1.1.0 + object-inspect: 1.13.4 + object-keys: 1.1.1 + object.assign: 4.1.7 + own-keys: 1.0.1 + regexp.prototype.flags: 1.5.4 + safe-array-concat: 1.1.3 + safe-push-apply: 1.0.0 + safe-regex-test: 1.1.0 + set-proto: 1.0.0 + stop-iteration-iterator: 1.1.0 + string.prototype.trim: 1.2.10 + string.prototype.trimend: 1.0.9 + string.prototype.trimstart: 1.0.8 + typed-array-buffer: 1.0.3 + typed-array-byte-length: 1.0.3 + typed-array-byte-offset: 1.0.4 + typed-array-length: 1.0.7 + unbox-primitive: 1.1.0 + which-typed-array: 1.1.20 + + es-define-property@1.0.1: {} + + es-errors@1.3.0: {} + + es-iterator-helpers@1.3.2: + dependencies: + call-bind: 1.0.9 + call-bound: 1.0.4 + define-properties: 1.2.1 + es-abstract: 1.24.2 + es-errors: 1.3.0 + es-set-tostringtag: 2.1.0 + function-bind: 1.1.2 + get-intrinsic: 1.3.0 + globalthis: 1.0.4 + gopd: 1.2.0 + has-property-descriptors: 1.0.2 + has-proto: 1.2.0 + has-symbols: 1.1.0 + internal-slot: 1.1.0 + iterator.prototype: 1.1.5 + math-intrinsics: 1.1.0 + + es-module-lexer@2.0.0: {} + + es-object-atoms@1.1.1: + dependencies: + es-errors: 1.3.0 + + es-set-tostringtag@2.1.0: + dependencies: + es-errors: 1.3.0 + get-intrinsic: 1.3.0 + has-tostringtag: 1.0.2 + hasown: 2.0.2 + + es-shim-unscopables@1.1.0: + dependencies: + hasown: 2.0.2 + + es-to-primitive@1.3.0: + dependencies: + is-callable: 1.2.7 + is-date-object: 1.1.0 + is-symbol: 1.1.1 + + esbuild@0.27.7: + optionalDependencies: + "@esbuild/aix-ppc64": 0.27.7 + "@esbuild/android-arm": 0.27.7 + "@esbuild/android-arm64": 0.27.7 + "@esbuild/android-x64": 0.27.7 + "@esbuild/darwin-arm64": 0.27.7 + "@esbuild/darwin-x64": 0.27.7 + "@esbuild/freebsd-arm64": 0.27.7 + "@esbuild/freebsd-x64": 0.27.7 + "@esbuild/linux-arm": 0.27.7 + "@esbuild/linux-arm64": 0.27.7 + "@esbuild/linux-ia32": 0.27.7 + "@esbuild/linux-loong64": 0.27.7 + "@esbuild/linux-mips64el": 0.27.7 + "@esbuild/linux-ppc64": 0.27.7 + "@esbuild/linux-riscv64": 0.27.7 + "@esbuild/linux-s390x": 0.27.7 + "@esbuild/linux-x64": 0.27.7 + "@esbuild/netbsd-arm64": 0.27.7 + "@esbuild/netbsd-x64": 0.27.7 + "@esbuild/openbsd-arm64": 0.27.7 + "@esbuild/openbsd-x64": 0.27.7 + "@esbuild/openharmony-arm64": 0.27.7 + "@esbuild/sunos-x64": 0.27.7 + "@esbuild/win32-arm64": 0.27.7 + "@esbuild/win32-ia32": 0.27.7 + "@esbuild/win32-x64": 0.27.7 + + escalade@3.2.0: {} + + escape-string-regexp@1.0.5: {} + + escape-string-regexp@4.0.0: {} + + eslint-config-google@0.14.0(eslint@8.57.1): + dependencies: + eslint: 8.57.1 + + eslint-config-prettier@10.1.8(eslint@8.57.1): + dependencies: + eslint: 8.57.1 + + eslint-etc@5.2.1(eslint@8.57.1)(typescript@5.9.3): + dependencies: + "@typescript-eslint/experimental-utils": 5.62.0(eslint@8.57.1)(typescript@5.9.3) + eslint: 8.57.1 + tsutils: 3.21.0(typescript@5.9.3) + tsutils-etc: 1.4.2(tsutils@3.21.0(typescript@5.9.3))(typescript@5.9.3) + typescript: 5.9.3 + transitivePeerDependencies: + - supports-color + + eslint-import-resolver-node@0.3.10: + dependencies: + debug: 3.2.7 + is-core-module: 2.16.1 + resolve: 2.0.0-next.6 + transitivePeerDependencies: + - supports-color + + eslint-module-utils@2.12.1(@typescript-eslint/parser@8.58.2(eslint@8.57.1)(typescript@5.9.3))(eslint-import-resolver-node@0.3.10)(eslint@8.57.1): + dependencies: + debug: 3.2.7 + optionalDependencies: + "@typescript-eslint/parser": 8.58.2(eslint@8.57.1)(typescript@5.9.3) + eslint: 8.57.1 + eslint-import-resolver-node: 0.3.10 + transitivePeerDependencies: + - supports-color + + eslint-plugin-deprecate@0.9.0(eslint@8.57.1): + dependencies: + eslint: 8.57.1 + + eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.58.2(eslint@8.57.1)(typescript@5.9.3))(eslint@8.57.1): + dependencies: + "@rtsao/scc": 1.1.0 + array-includes: 3.1.9 + array.prototype.findlastindex: 1.2.6 + array.prototype.flat: 1.3.3 + array.prototype.flatmap: 1.3.3 + debug: 3.2.7 + doctrine: 2.1.0 + eslint: 8.57.1 + eslint-import-resolver-node: 0.3.10 + eslint-module-utils: 2.12.1(@typescript-eslint/parser@8.58.2(eslint@8.57.1)(typescript@5.9.3))(eslint-import-resolver-node@0.3.10)(eslint@8.57.1) + hasown: 2.0.2 + is-core-module: 2.16.1 + is-glob: 4.0.3 + minimatch: 10.2.5 + object.fromentries: 2.0.8 + object.groupby: 1.0.3 + object.values: 1.2.1 + semver: 6.3.1 + string.prototype.trimend: 1.0.9 + tsconfig-paths: 3.15.0 + optionalDependencies: + "@typescript-eslint/parser": 8.58.2(eslint@8.57.1)(typescript@5.9.3) + transitivePeerDependencies: + - eslint-import-resolver-typescript + - eslint-import-resolver-webpack + - supports-color + + eslint-plugin-jest@29.15.2(@typescript-eslint/eslint-plugin@8.58.2(@typescript-eslint/parser@8.58.2(eslint@8.57.1)(typescript@5.9.3))(eslint@8.57.1)(typescript@5.9.3))(eslint@8.57.1)(typescript@5.9.3): + dependencies: + "@typescript-eslint/utils": 8.58.2(eslint@8.57.1)(typescript@5.9.3) + eslint: 8.57.1 + optionalDependencies: + "@typescript-eslint/eslint-plugin": 8.58.2(@typescript-eslint/parser@8.58.2(eslint@8.57.1)(typescript@5.9.3))(eslint@8.57.1)(typescript@5.9.3) + typescript: 5.9.3 + transitivePeerDependencies: + - supports-color + + eslint-plugin-jsdoc@61.7.1(eslint@8.57.1): + dependencies: + "@es-joy/jsdoccomment": 0.78.0 + "@es-joy/resolve.exports": 1.2.0 + are-docs-informative: 0.0.2 + comment-parser: 1.4.1 + debug: 4.4.3 + escape-string-regexp: 4.0.0 + eslint: 8.57.1 + espree: 11.2.0 + esquery: 1.7.0 + html-entities: 2.6.0 + object-deep-merge: 2.0.0 + parse-imports-exports: 0.2.4 + semver: 7.7.4 + spdx-expression-parse: 4.0.0 + to-valid-identifier: 1.0.0 + transitivePeerDependencies: + - supports-color + + eslint-plugin-jsx-a11y@6.10.2(eslint@8.57.1): + dependencies: + aria-query: 5.3.2 + array-includes: 3.1.9 + array.prototype.flatmap: 1.3.3 + ast-types-flow: 0.0.8 + axe-core: 4.11.3 + axobject-query: 4.1.0 + damerau-levenshtein: 1.0.8 + emoji-regex: 9.2.2 + eslint: 8.57.1 + hasown: 2.0.2 + jsx-ast-utils: 3.3.5 + language-tags: 1.0.9 + minimatch: 10.2.5 + object.fromentries: 2.0.8 + safe-regex-test: 1.1.0 + string.prototype.includes: 2.0.1 + + eslint-plugin-matrix-org@2.1.0(@babel/core@7.29.0)(@babel/eslint-parser@7.28.6(@babel/core@7.29.0)(eslint@8.57.1))(@babel/eslint-plugin@7.27.1(@babel/eslint-parser@7.28.6(@babel/core@7.29.0)(eslint@8.57.1))(eslint@8.57.1))(@stylistic/eslint-plugin@3.1.0(eslint@8.57.1)(typescript@5.9.3))(@typescript-eslint/eslint-plugin@8.58.2(@typescript-eslint/parser@8.58.2(eslint@8.57.1)(typescript@5.9.3))(eslint@8.57.1)(typescript@5.9.3))(@typescript-eslint/parser@8.58.2(eslint@8.57.1)(typescript@5.9.3))(eslint-config-google@0.14.0(eslint@8.57.1))(eslint-config-prettier@10.1.8(eslint@8.57.1))(eslint-plugin-deprecate@0.9.0(eslint@8.57.1))(eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.58.2(eslint@8.57.1)(typescript@5.9.3))(eslint@8.57.1))(eslint-plugin-jest@29.15.2(@typescript-eslint/eslint-plugin@8.58.2(@typescript-eslint/parser@8.58.2(eslint@8.57.1)(typescript@5.9.3))(eslint@8.57.1)(typescript@5.9.3))(eslint@8.57.1)(typescript@5.9.3))(eslint-plugin-jsx-a11y@6.10.2(eslint@8.57.1))(eslint-plugin-react-hooks@5.2.0(eslint@8.57.1))(eslint-plugin-react@7.37.5(eslint@8.57.1))(eslint-plugin-unicorn@56.0.1(eslint@8.57.1))(eslint@8.57.1)(prettier@3.8.3)(typescript@5.9.3): + dependencies: + "@babel/core": 7.29.0 + "@babel/eslint-parser": 7.28.6(@babel/core@7.29.0)(eslint@8.57.1) + "@babel/eslint-plugin": 7.27.1(@babel/eslint-parser@7.28.6(@babel/core@7.29.0)(eslint@8.57.1))(eslint@8.57.1) + "@stylistic/eslint-plugin": 3.1.0(eslint@8.57.1)(typescript@5.9.3) + "@typescript-eslint/eslint-plugin": 8.58.2(@typescript-eslint/parser@8.58.2(eslint@8.57.1)(typescript@5.9.3))(eslint@8.57.1)(typescript@5.9.3) + "@typescript-eslint/parser": 8.58.2(eslint@8.57.1)(typescript@5.9.3) + eslint: 8.57.1 + eslint-config-google: 0.14.0(eslint@8.57.1) + eslint-config-prettier: 10.1.8(eslint@8.57.1) + eslint-plugin-deprecate: 0.9.0(eslint@8.57.1) + eslint-plugin-import: 2.32.0(@typescript-eslint/parser@8.58.2(eslint@8.57.1)(typescript@5.9.3))(eslint@8.57.1) + eslint-plugin-jest: 29.15.2(@typescript-eslint/eslint-plugin@8.58.2(@typescript-eslint/parser@8.58.2(eslint@8.57.1)(typescript@5.9.3))(eslint@8.57.1)(typescript@5.9.3))(eslint@8.57.1)(typescript@5.9.3) + eslint-plugin-jsx-a11y: 6.10.2(eslint@8.57.1) + eslint-plugin-react: 7.37.5(eslint@8.57.1) + eslint-plugin-react-hooks: 5.2.0(eslint@8.57.1) + eslint-plugin-unicorn: 56.0.1(eslint@8.57.1) + prettier: 3.8.3 + typescript: 5.9.3 + + eslint-plugin-react-hooks@5.2.0(eslint@8.57.1): + dependencies: + eslint: 8.57.1 + + eslint-plugin-react@7.37.5(eslint@8.57.1): + dependencies: + array-includes: 3.1.9 + array.prototype.findlast: 1.2.5 + array.prototype.flatmap: 1.3.3 + array.prototype.tosorted: 1.1.4 + doctrine: 2.1.0 + es-iterator-helpers: 1.3.2 + eslint: 8.57.1 + estraverse: 5.3.0 + hasown: 2.0.2 + jsx-ast-utils: 3.3.5 + minimatch: 10.2.5 + object.entries: 1.1.9 + object.fromentries: 2.0.8 + object.values: 1.2.1 + prop-types: 15.8.1 + resolve: 2.0.0-next.6 + semver: 6.3.1 + string.prototype.matchall: 4.0.12 + string.prototype.repeat: 1.0.0 + + eslint-plugin-rxjs@5.0.3(eslint@8.57.1)(typescript@5.9.3): + dependencies: + "@typescript-eslint/experimental-utils": 5.62.0(eslint@8.57.1)(typescript@5.9.3) + common-tags: 1.8.2 + decamelize: 5.0.1 + eslint: 8.57.1 + eslint-etc: 5.2.1(eslint@8.57.1)(typescript@5.9.3) + requireindex: 1.2.0 + rxjs-report-usage: 1.0.6 + tslib: 2.8.1 + tsutils: 3.21.0(typescript@5.9.3) + tsutils-etc: 1.4.2(tsutils@3.21.0(typescript@5.9.3))(typescript@5.9.3) + typescript: 5.9.3 + transitivePeerDependencies: + - supports-color + + eslint-plugin-storybook@10.3.5(eslint@8.57.1)(storybook@10.3.5(@testing-library/dom@10.4.1)(prettier@3.8.3)(react-dom@19.2.5(react@19.2.5))(react@19.2.5))(typescript@5.9.3): + dependencies: + "@typescript-eslint/utils": 8.58.2(eslint@8.57.1)(typescript@5.9.3) + eslint: 8.57.1 + storybook: 10.3.5(@testing-library/dom@10.4.1)(prettier@3.8.3)(react-dom@19.2.5(react@19.2.5))(react@19.2.5) + transitivePeerDependencies: + - supports-color + - typescript + + eslint-plugin-unicorn@56.0.1(eslint@8.57.1): + dependencies: + "@babel/helper-validator-identifier": 7.28.5 + "@eslint-community/eslint-utils": 4.9.1(eslint@8.57.1) + ci-info: 4.4.0 + clean-regexp: 1.0.0 + core-js-compat: 3.49.0 + eslint: 8.57.1 + esquery: 1.7.0 + globals: 15.15.0 + indent-string: 4.0.0 + is-builtin-module: 3.2.1 + jsesc: 3.1.0 + pluralize: 8.0.0 + read-pkg-up: 7.0.1 + regexp-tree: 0.1.27 + regjsparser: 0.10.0 + semver: 7.7.4 + strip-indent: 3.0.0 + + eslint-rule-composer@0.3.0: {} + + eslint-scope@5.1.1: + dependencies: + esrecurse: 4.3.0 + estraverse: 4.3.0 + + eslint-scope@7.2.2: + dependencies: + esrecurse: 4.3.0 + estraverse: 5.3.0 + + eslint-visitor-keys@2.1.0: {} + + eslint-visitor-keys@3.4.3: {} + + eslint-visitor-keys@4.2.1: {} + + eslint-visitor-keys@5.0.1: {} + + eslint@8.57.1: + dependencies: + "@eslint-community/eslint-utils": 4.9.1(eslint@8.57.1) + "@eslint-community/regexpp": 4.12.2 + "@eslint/eslintrc": 2.1.4 + "@eslint/js": 8.57.1 + "@humanwhocodes/config-array": 0.13.0 + "@humanwhocodes/module-importer": 1.0.1 + "@nodelib/fs.walk": 1.2.8 + "@ungap/structured-clone": 1.3.0 + ajv: 6.14.0 + chalk: 4.1.2 + cross-spawn: 7.0.6 + debug: 4.4.3 + doctrine: 3.0.0 + escape-string-regexp: 4.0.0 + eslint-scope: 7.2.2 + eslint-visitor-keys: 3.4.3 + espree: 9.6.1 + esquery: 1.7.0 + esutils: 2.0.3 + fast-deep-equal: 3.1.3 + file-entry-cache: 6.0.1 + find-up: 5.0.0 + glob-parent: 6.0.2 + globals: 13.24.0 + graphemer: 1.4.0 + ignore: 5.3.2 + imurmurhash: 0.1.4 + is-glob: 4.0.3 + is-path-inside: 3.0.3 + js-yaml: 4.1.1 + json-stable-stringify-without-jsonify: 1.0.1 + levn: 0.4.1 + lodash.merge: 4.6.2 + minimatch: 10.2.5 + natural-compare: 1.4.0 + optionator: 0.9.4 + strip-ansi: 6.0.1 + text-table: 0.2.0 + transitivePeerDependencies: + - supports-color + + espree@10.4.0: + dependencies: + acorn: 8.16.0 + acorn-jsx: 5.3.2(acorn@8.16.0) + eslint-visitor-keys: 4.2.1 + + espree@11.2.0: + dependencies: + acorn: 8.16.0 + acorn-jsx: 5.3.2(acorn@8.16.0) + eslint-visitor-keys: 5.0.1 + + espree@9.6.1: + dependencies: + acorn: 8.16.0 + acorn-jsx: 5.3.2(acorn@8.16.0) + eslint-visitor-keys: 3.4.3 + + esprima@4.0.1: {} + + esquery@1.7.0: + dependencies: + estraverse: 5.3.0 + + esrecurse@4.3.0: + dependencies: + estraverse: 5.3.0 + + estraverse@4.3.0: {} + + estraverse@5.3.0: {} + + estree-walker@2.0.2: {} + + estree-walker@3.0.3: + dependencies: + "@types/estree": 1.0.8 + + esutils@2.0.3: {} + + events-universal@1.0.1: + dependencies: + bare-events: 2.8.2 + transitivePeerDependencies: + - bare-abort-controller + + events@3.3.0: {} + + evp_bytestokey@1.0.3: + dependencies: + md5.js: 1.3.5 + safe-buffer: 5.2.1 + + expect-type@1.3.0: {} + + fast-deep-equal@3.1.3: {} + + fast-fifo@1.3.2: {} + + fast-glob@3.3.3: + dependencies: + "@nodelib/fs.stat": 2.0.5 + "@nodelib/fs.walk": 1.2.8 + glob-parent: 5.1.2 + merge2: 1.4.1 + micromatch: 4.0.8 + + fast-json-stable-stringify@2.1.0: {} + + fast-levenshtein@2.0.6: {} + + fastq@1.20.1: + dependencies: + reusify: 1.1.0 + + fd-package-json@2.0.0: + dependencies: + walk-up-path: 4.0.0 + + fdir@6.5.0(picomatch@4.0.4): + optionalDependencies: + picomatch: 4.0.4 + + fetch-mock@11.1.5: + dependencies: + "@types/glob-to-regexp": 0.4.4 + dequal: 2.0.3 + glob-to-regexp: 0.4.1 + is-subset: 0.1.1 + regexparam: 3.0.0 + + fflate@0.4.8: {} + + file-entry-cache@6.0.1: + dependencies: + flat-cache: 3.2.0 + + filelist@1.0.6: + dependencies: + minimatch: 10.2.5 + + fill-range@7.1.1: + dependencies: + to-regex-range: 5.0.1 + + find-up@4.1.0: + dependencies: + locate-path: 5.0.0 + path-exists: 4.0.0 + + find-up@5.0.0: + dependencies: + locate-path: 6.0.0 + path-exists: 4.0.0 + + flat-cache@3.2.0: + dependencies: + flatted: 3.4.2 + keyv: 4.5.4 + rimraf: 3.0.2 + + flatted@3.4.2: {} + + for-each@0.3.5: + dependencies: + is-callable: 1.2.7 + + foreground-child@3.3.1: + dependencies: + cross-spawn: 7.0.6 + signal-exit: 4.1.0 + + formatly@0.3.0: + dependencies: + fd-package-json: 2.0.0 + + fraction.js@5.3.4: {} + + fs-extra@10.1.0: + dependencies: + graceful-fs: 4.2.11 + jsonfile: 6.2.0 + universalify: 2.0.1 + + fs-extra@11.3.4: + dependencies: + graceful-fs: 4.2.11 + jsonfile: 6.2.0 + universalify: 2.0.1 + + fs-extra@8.1.0: + dependencies: + graceful-fs: 4.2.11 + jsonfile: 4.0.0 + universalify: 0.1.2 + + fs-merger@3.2.1: + dependencies: + broccoli-node-api: 1.7.0 + broccoli-node-info: 2.2.0 + fs-extra: 8.1.0 + fs-tree-diff: 2.0.1 + walk-sync: 2.2.0 + transitivePeerDependencies: + - supports-color + + fs-mkdirp-stream@2.0.1: + dependencies: + graceful-fs: 4.2.11 + streamx: 2.25.0 + transitivePeerDependencies: + - bare-abort-controller + - react-native-b4a + + fs-tree-diff@2.0.1: + dependencies: + "@types/symlink-or-copy": 1.2.2 + heimdalljs-logger: 0.1.10 + object-assign: 4.1.1 + path-posix: 1.0.0 + symlink-or-copy: 1.3.1 + transitivePeerDependencies: + - supports-color + + fsevents@2.3.2: + optional: true + + fsevents@2.3.3: + optional: true + + function-bind@1.1.2: {} + + function.prototype.name@1.1.8: + dependencies: + call-bind: 1.0.9 + call-bound: 1.0.4 + define-properties: 1.2.1 + functions-have-names: 1.2.3 + hasown: 2.0.2 + is-callable: 1.2.7 + + functions-have-names@1.2.3: {} + + generator-function@2.0.1: {} + + gensync@1.0.0-beta.2: {} + + get-caller-file@2.0.5: {} + + get-intrinsic@1.3.0: + dependencies: + call-bind-apply-helpers: 1.0.2 + es-define-property: 1.0.1 + es-errors: 1.3.0 + es-object-atoms: 1.1.1 + function-bind: 1.1.2 + get-proto: 1.0.1 + gopd: 1.2.0 + has-symbols: 1.1.0 + hasown: 2.0.2 + math-intrinsics: 1.1.0 + + get-nonce@1.0.1: {} + + get-proto@1.0.1: + dependencies: + dunder-proto: 1.0.1 + es-object-atoms: 1.1.1 + + get-symbol-description@1.1.0: + dependencies: + call-bound: 1.0.4 + es-errors: 1.3.0 + get-intrinsic: 1.3.0 + + glob-parent@5.1.2: + dependencies: + is-glob: 4.0.3 + + glob-parent@6.0.2: + dependencies: + is-glob: 4.0.3 + + glob-stream@8.0.3: + dependencies: + "@gulpjs/to-absolute-glob": 4.0.0 + anymatch: 3.1.3 + fastq: 1.20.1 + glob-parent: 6.0.2 + is-glob: 4.0.3 + is-negated-glob: 1.0.0 + normalize-path: 3.0.0 + streamx: 2.25.0 + transitivePeerDependencies: + - bare-abort-controller + - react-native-b4a + + glob-to-regexp@0.4.1: {} + + glob@10.5.0: + dependencies: + foreground-child: 3.3.1 + jackspeak: 3.4.3 + minimatch: 10.2.5 + minipass: 7.1.3 + package-json-from-dist: 1.0.1 + path-scurry: 1.11.1 + + global-jsdom@26.0.0(jsdom@26.1.0): + dependencies: + jsdom: 26.1.0 + + globals@13.24.0: + dependencies: + type-fest: 0.20.2 + + globals@15.15.0: {} + + globalthis@1.0.4: + dependencies: + define-properties: 1.2.1 + gopd: 1.2.0 + + globby@11.1.0: + dependencies: + array-union: 2.1.0 + dir-glob: 3.0.1 + fast-glob: 3.3.3 + ignore: 5.3.2 + merge2: 1.4.1 + slash: 3.0.0 + + gopd@1.2.0: {} + + graceful-fs@4.2.11: {} + + graphemer@1.4.0: {} + + gulp-sort@2.0.0: + dependencies: + through2: 2.0.5 + + has-bigints@1.1.0: {} + + has-flag@4.0.0: {} + + has-property-descriptors@1.0.2: + dependencies: + es-define-property: 1.0.1 + + has-proto@1.2.0: + dependencies: + dunder-proto: 1.0.1 + + has-symbols@1.1.0: {} + + has-tostringtag@1.0.2: + dependencies: + has-symbols: 1.1.0 + + hash-base@3.0.5: + dependencies: + inherits: 2.0.4 + safe-buffer: 5.2.1 + + hash-base@3.1.2: + dependencies: + inherits: 2.0.4 + readable-stream: 2.3.8 + safe-buffer: 5.2.1 + to-buffer: 1.2.2 + + hash.js@1.1.7: + dependencies: + inherits: 2.0.4 + minimalistic-assert: 1.0.1 + + hasown@2.0.2: + dependencies: + function-bind: 1.1.2 + + he@1.2.0: {} + + heimdalljs-logger@0.1.10: + dependencies: + debug: 2.6.9 + heimdalljs: 0.2.6 + transitivePeerDependencies: + - supports-color + + heimdalljs@0.2.6: + dependencies: + rsvp: 3.2.1 + + hmac-drbg@1.0.1: + dependencies: + hash.js: 1.1.7 + minimalistic-assert: 1.0.1 + minimalistic-crypto-utils: 1.0.1 + + hoist-non-react-statics@3.3.2: + dependencies: + react-is: 16.13.1 + + hosted-git-info@2.8.9: {} + + html-encoding-sniffer@4.0.0: + dependencies: + whatwg-encoding: 3.1.1 + + html-entities@2.6.0: {} + + html-escaper@2.0.2: {} + + html-minifier-terser@6.1.0: + dependencies: + camel-case: 4.1.2 + clean-css: 5.3.3 + commander: 8.3.0 + he: 1.2.0 + param-case: 3.0.4 + relateurl: 0.2.7 + terser: 5.46.1 + + html-parse-stringify@3.0.1: + dependencies: + void-elements: 3.1.0 + + htmlparser2@10.1.0: + dependencies: + domelementtype: 2.3.0 + domhandler: 5.0.3 + domutils: 3.2.2 + entities: 7.0.1 + + http-proxy-agent@7.0.2: + dependencies: + agent-base: 7.1.4 + debug: 4.4.3 + transitivePeerDependencies: + - supports-color + + https-browserify@1.0.0: {} + + https-proxy-agent@5.0.1: + dependencies: + agent-base: 6.0.2 + debug: 4.4.3 + transitivePeerDependencies: + - supports-color + + https-proxy-agent@7.0.6: + dependencies: + agent-base: 7.1.4 + debug: 4.4.3 + transitivePeerDependencies: + - supports-color + + i18next-browser-languagedetector@8.2.1: + dependencies: + "@babel/runtime": 7.29.2 + + i18next-parser@9.4.0: + dependencies: + "@babel/runtime": 7.29.2 + broccoli-plugin: 4.0.7 + cheerio: 1.2.0 + colors: 1.4.0 + commander: 12.1.0 + eol: 0.9.1 + esbuild: 0.27.7 + fs-extra: 11.3.4 + gulp-sort: 2.0.0 + i18next: 24.2.3(typescript@5.9.3) + js-yaml: 4.1.1 + lilconfig: 3.1.3 + rsvp: 4.8.5 + sort-keys: 5.1.0 + typescript: 5.9.3 + vinyl: 3.0.1 + vinyl-fs: 4.0.2 + transitivePeerDependencies: + - bare-abort-controller + - react-native-b4a + - supports-color + + i18next@24.2.3(typescript@5.9.3): + dependencies: + "@babel/runtime": 7.29.2 + optionalDependencies: + typescript: 5.9.3 + + i18next@25.10.10(typescript@5.9.3): + dependencies: + "@babel/runtime": 7.29.2 + optionalDependencies: + typescript: 5.9.3 + + iconv-lite@0.6.3: + dependencies: + safer-buffer: 2.1.2 + + ieee754@1.2.1: {} + + ignore@5.3.2: {} + + ignore@7.0.5: {} + + immutable@5.1.5: {} + + import-fresh@3.3.1: + dependencies: + parent-module: 1.0.1 + resolve-from: 4.0.0 + + imurmurhash@0.1.4: {} + + indent-string@4.0.0: {} + + inherits@2.0.4: {} + + internal-slot@1.1.0: + dependencies: + es-errors: 1.3.0 + hasown: 2.0.2 + side-channel: 1.1.0 + + is-arguments@1.2.0: + dependencies: + call-bound: 1.0.4 + has-tostringtag: 1.0.2 + + is-array-buffer@3.0.5: + dependencies: + call-bind: 1.0.9 + call-bound: 1.0.4 + get-intrinsic: 1.3.0 + + is-arrayish@0.2.1: {} + + is-async-function@2.1.1: + dependencies: + async-function: 1.0.0 + call-bound: 1.0.4 + get-proto: 1.0.1 + has-tostringtag: 1.0.2 + safe-regex-test: 1.1.0 + + is-bigint@1.1.0: + dependencies: + has-bigints: 1.1.0 + + is-binary-path@2.1.0: + dependencies: + binary-extensions: 2.3.0 + + is-boolean-object@1.2.2: + dependencies: + call-bound: 1.0.4 + has-tostringtag: 1.0.2 + + is-builtin-module@3.2.1: + dependencies: + builtin-modules: 3.3.0 + + is-callable@1.2.7: {} + + is-core-module@2.16.1: + dependencies: + hasown: 2.0.2 + + is-data-view@1.0.2: + dependencies: + call-bound: 1.0.4 + get-intrinsic: 1.3.0 + is-typed-array: 1.1.15 + + is-date-object@1.1.0: + dependencies: + call-bound: 1.0.4 + has-tostringtag: 1.0.2 + + is-docker@3.0.0: {} + + is-extglob@2.1.1: {} + + is-finalizationregistry@1.1.1: + dependencies: + call-bound: 1.0.4 + + is-fullwidth-code-point@3.0.0: {} + + is-generator-function@1.1.2: + dependencies: + call-bound: 1.0.4 + generator-function: 2.0.1 + get-proto: 1.0.1 + has-tostringtag: 1.0.2 + safe-regex-test: 1.1.0 + + is-glob@4.0.3: + dependencies: + is-extglob: 2.1.1 + + is-inside-container@1.0.0: + dependencies: + is-docker: 3.0.0 + + is-map@2.0.3: {} + + is-nan@1.3.2: + dependencies: + call-bind: 1.0.9 + define-properties: 1.2.1 + + is-negated-glob@1.0.0: {} + + is-negative-zero@2.0.3: {} + + is-network-error@1.3.1: {} + + is-number-object@1.1.1: + dependencies: + call-bound: 1.0.4 + has-tostringtag: 1.0.2 + + is-number@7.0.0: {} + + is-path-inside@3.0.3: {} + + is-plain-obj@4.1.0: {} + + is-potential-custom-element-name@1.0.1: {} + + is-regex@1.2.1: + dependencies: + call-bound: 1.0.4 + gopd: 1.2.0 + has-tostringtag: 1.0.2 + hasown: 2.0.2 + + is-set@2.0.3: {} + + is-shared-array-buffer@1.0.4: + dependencies: + call-bound: 1.0.4 + + is-stream@2.0.1: {} + + is-string@1.1.1: + dependencies: + call-bound: 1.0.4 + has-tostringtag: 1.0.2 + + is-subset@0.1.1: {} + + is-symbol@1.1.1: + dependencies: + call-bound: 1.0.4 + has-symbols: 1.1.0 + safe-regex-test: 1.1.0 + + is-typed-array@1.1.15: + dependencies: + which-typed-array: 1.1.20 + + is-valid-glob@1.0.0: {} + + is-weakmap@2.0.2: {} + + is-weakref@1.1.1: + dependencies: + call-bound: 1.0.4 + + is-weakset@2.0.4: + dependencies: + call-bound: 1.0.4 + get-intrinsic: 1.3.0 + + is-wsl@3.1.1: + dependencies: + is-inside-container: 1.0.0 + + isarray@1.0.0: {} + + isarray@2.0.5: {} + + isexe@2.0.0: {} + + isomorphic-timers-promises@1.0.1: {} + + istanbul-lib-coverage@3.2.2: {} + + istanbul-lib-report@3.0.1: + dependencies: + istanbul-lib-coverage: 3.2.2 + make-dir: 4.0.0 + supports-color: 7.2.0 + + istanbul-reports@3.2.0: + dependencies: + html-escaper: 2.0.2 + istanbul-lib-report: 3.0.1 + + iterator.prototype@1.1.5: + dependencies: + define-data-property: 1.1.4 + es-object-atoms: 1.1.1 + get-intrinsic: 1.3.0 + get-proto: 1.0.1 + has-symbols: 1.1.0 + set-function-name: 2.0.2 + + jackspeak@3.4.3: + dependencies: + "@isaacs/cliui": 8.0.2 + optionalDependencies: + "@pkgjs/parseargs": 0.11.0 + + jake@10.9.4: + dependencies: + async: 3.2.6 + filelist: 1.0.6 + picocolors: 1.1.1 + + jiti@2.6.1: {} + + jose@6.2.2: {} + + js-tokens@10.0.0: {} + + js-tokens@4.0.0: {} + + js-yaml@4.1.1: + dependencies: + argparse: 2.0.1 + + jsdoc-type-pratt-parser@7.0.0: {} + + jsdom@26.1.0: + dependencies: + cssstyle: 4.6.0 + data-urls: 5.0.0 + decimal.js: 10.6.0 + html-encoding-sniffer: 4.0.0 + http-proxy-agent: 7.0.2 + https-proxy-agent: 7.0.6 + is-potential-custom-element-name: 1.0.1 + nwsapi: 2.2.23 + parse5: 7.3.0 + rrweb-cssom: 0.8.0 + saxes: 6.0.0 + symbol-tree: 3.2.4 + tough-cookie: 5.1.2 + w3c-xmlserializer: 5.0.0 + webidl-conversions: 7.0.0 + whatwg-encoding: 3.1.1 + whatwg-mimetype: 4.0.0 + whatwg-url: 14.2.0 + ws: 8.20.0 + xml-name-validator: 5.0.0 + transitivePeerDependencies: + - bufferutil + - supports-color + - utf-8-validate + + jsesc@0.5.0: {} + + jsesc@3.1.0: {} + + json-buffer@3.0.1: {} + + json-parse-even-better-errors@2.3.1: {} + + json-schema-traverse@0.4.1: {} + + json-stable-stringify-without-jsonify@1.0.1: {} + + json5@1.0.2: + dependencies: + minimist: 1.2.8 + + json5@2.2.3: {} + + jsonfile@4.0.0: + optionalDependencies: + graceful-fs: 4.2.11 + + jsonfile@6.2.0: + dependencies: + universalify: 2.0.1 + optionalDependencies: + graceful-fs: 4.2.11 + + jsx-ast-utils@3.3.5: + dependencies: + array-includes: 3.1.9 + array.prototype.flat: 1.3.3 + object.assign: 4.1.7 + object.values: 1.2.1 + + jwt-decode@4.0.0: {} + + keyv@4.5.4: + dependencies: + json-buffer: 3.0.1 + + kleur@3.0.3: {} + + knip@5.88.1(@emnapi/core@1.9.2)(@emnapi/runtime@1.9.2)(@types/node@24.12.2)(typescript@5.9.3): + dependencies: + "@nodelib/fs.walk": 1.2.8 + "@types/node": 24.12.2 + fast-glob: 3.3.3 + formatly: 0.3.0 + jiti: 2.6.1 + minimist: 1.2.8 + oxc-resolver: 11.19.1(@emnapi/core@1.9.2)(@emnapi/runtime@1.9.2) + picocolors: 1.1.1 + picomatch: 4.0.4 + smol-toml: 1.6.1 + strip-json-comments: 5.0.3 + typescript: 5.9.3 + unbash: 2.2.0 + yaml: 2.8.3 + zod: 4.3.6 + transitivePeerDependencies: + - "@emnapi/core" + - "@emnapi/runtime" + + language-subtag-registry@0.3.23: {} + + language-tags@1.0.9: + dependencies: + language-subtag-registry: 0.3.23 + + lead@4.0.0: {} + + levn@0.4.1: + dependencies: + prelude-ls: 1.2.1 + type-check: 0.4.0 + + lightningcss-android-arm64@1.32.0: + optional: true + + lightningcss-darwin-arm64@1.32.0: + optional: true + + lightningcss-darwin-x64@1.32.0: + optional: true + + lightningcss-freebsd-x64@1.32.0: + optional: true + + lightningcss-linux-arm-gnueabihf@1.32.0: + optional: true + + lightningcss-linux-arm64-gnu@1.32.0: + optional: true + + lightningcss-linux-arm64-musl@1.32.0: + optional: true + + lightningcss-linux-x64-gnu@1.32.0: + optional: true + + lightningcss-linux-x64-musl@1.32.0: + optional: true + + lightningcss-win32-arm64-msvc@1.32.0: + optional: true + + lightningcss-win32-x64-msvc@1.32.0: + optional: true + + lightningcss@1.32.0: + dependencies: + detect-libc: 2.1.2 + optionalDependencies: + lightningcss-android-arm64: 1.32.0 + lightningcss-darwin-arm64: 1.32.0 + lightningcss-darwin-x64: 1.32.0 + lightningcss-freebsd-x64: 1.32.0 + lightningcss-linux-arm-gnueabihf: 1.32.0 + lightningcss-linux-arm64-gnu: 1.32.0 + lightningcss-linux-arm64-musl: 1.32.0 + lightningcss-linux-x64-gnu: 1.32.0 + lightningcss-linux-x64-musl: 1.32.0 + lightningcss-win32-arm64-msvc: 1.32.0 + lightningcss-win32-x64-msvc: 1.32.0 + + lilconfig@3.1.3: {} + + lines-and-columns@1.2.4: {} + + livekit-client@2.18.3(@types/dom-mediacapture-record@1.0.22): + dependencies: + "@livekit/mutex": 1.1.1 + "@livekit/protocol": 1.45.3 + "@types/dom-mediacapture-record": 1.0.22 + events: 3.3.0 + jose: 6.2.2 + loglevel: 1.9.2 + sdp-transform: 2.15.0 + tslib: 2.8.1 + typed-emitter: 2.1.0 + webrtc-adapter: 9.0.4 + + locate-path@5.0.0: + dependencies: + p-locate: 4.1.0 + + locate-path@6.0.0: + dependencies: + p-locate: 5.0.0 + + lodash-es@4.18.1: {} + + lodash.debounce@4.0.8: {} + + lodash.merge@4.6.2: {} + + loglevel@1.9.1: {} + + loglevel@1.9.2: {} + + loose-envify@1.4.0: + dependencies: + js-tokens: 4.0.0 + + loupe@3.2.1: {} + + lower-case@2.0.2: + dependencies: + tslib: 2.8.1 + + lru-cache@10.4.3: {} + + lru-cache@5.1.1: + dependencies: + yallist: 3.1.1 + + lz-string@1.5.0: {} + + magic-string@0.30.21: + dependencies: + "@jridgewell/sourcemap-codec": 1.5.5 + + magic-string@0.30.8: + dependencies: + "@jridgewell/sourcemap-codec": 1.5.5 + + magicast@0.5.2: + dependencies: + "@babel/parser": 7.29.2 + "@babel/types": 7.29.0 + source-map-js: 1.2.1 + + make-dir@4.0.0: + dependencies: + semver: 7.7.4 + + matcher-collection@2.0.1: + dependencies: + "@types/minimatch": 3.0.5 + minimatch: 10.2.5 + + math-intrinsics@1.1.0: {} + + matrix-events-sdk@0.0.1: {} + + matrix-js-sdk@https://codeload.github.com/matrix-org/matrix-js-sdk/tar.gz/ca5655bced1cbb215ac1c18e179384a069d98b0a: + dependencies: + "@babel/runtime": 7.29.2 + "@matrix-org/matrix-sdk-crypto-wasm": 18.0.0 + another-json: 0.2.0 + bs58: 6.0.0 + content-type: 1.0.5 + jwt-decode: 4.0.0 + loglevel: 1.9.2 + matrix-events-sdk: 0.0.1 + matrix-widget-api: 1.17.0 + oidc-client-ts: 3.5.0 + p-retry: 8.0.0 + sdp-transform: 3.0.0 + unhomoglyph: 1.0.6 + uuid: 13.0.0 + + matrix-widget-api@1.17.0: + dependencies: + "@types/events": 3.0.3 + events: 3.3.0 + + md5.js@1.3.5: + dependencies: + hash-base: 3.0.5 + inherits: 2.0.4 + safe-buffer: 5.2.1 + + merge2@1.4.1: {} + + micromatch@4.0.8: + dependencies: + braces: 3.0.3 + picomatch: 2.3.2 + + miller-rabin@4.0.1: + dependencies: + bn.js: 4.12.3 + brorand: 1.1.0 + + mime-db@1.52.0: {} + + mime-types@2.1.35: + dependencies: + mime-db: 1.52.0 + + min-indent@1.0.1: {} + + minimalistic-assert@1.0.1: {} + + minimalistic-crypto-utils@1.0.1: {} + + minimatch@10.2.5: + dependencies: + brace-expansion: 5.0.5 + + minimist@1.2.8: {} + + minipass@7.1.3: {} + + mktemp@2.0.2: {} + + ms@2.0.0: {} + + ms@2.1.3: {} + + nanoid@3.3.11: {} + + natural-compare@1.4.0: {} + + no-case@3.0.4: + dependencies: + lower-case: 2.0.2 + tslib: 2.8.1 + + node-addon-api@7.1.1: + optional: true + + node-exports-info@1.6.0: + dependencies: + array.prototype.flatmap: 1.3.3 + es-errors: 1.3.0 + object.entries: 1.1.9 + semver: 6.3.1 + + node-fetch@2.7.0: + dependencies: + whatwg-url: 5.0.0 + + node-html-parser@5.4.2: + dependencies: + css-select: 4.3.0 + he: 1.2.0 + + node-releases@2.0.37: {} + + node-stdlib-browser@1.3.1: + dependencies: + assert: 2.1.0 + browser-resolve: 2.0.0 + browserify-zlib: 0.2.0 + buffer: 5.7.1 + console-browserify: 1.2.0 + constants-browserify: 1.0.0 + create-require: 1.1.1 + crypto-browserify: 3.12.1 + domain-browser: 4.22.0 + events: 3.3.0 + https-browserify: 1.0.0 + isomorphic-timers-promises: 1.0.1 + os-browserify: 0.3.0 + path-browserify: 1.0.1 + pkg-dir: 5.0.0 + process: 0.11.10 + punycode: 1.4.1 + querystring-es3: 0.2.1 + readable-stream: 3.6.2 + stream-browserify: 3.0.0 + stream-http: 3.2.0 + string_decoder: 1.3.0 + timers-browserify: 2.0.12 + tty-browserify: 0.0.1 + url: 0.11.4 + util: 0.12.5 + vm-browserify: 1.1.2 + + normalize-package-data@2.5.0: + dependencies: + hosted-git-info: 2.8.9 + resolve: 1.22.12 + semver: 5.7.2 + validate-npm-package-license: 3.0.4 + + normalize-path@3.0.0: {} + + normalize.css@8.0.1: {} + + now-and-later@3.0.0: + dependencies: + once: 1.4.0 + + nth-check@2.1.1: + dependencies: + boolbase: 1.0.0 + + nwsapi@2.2.23: {} + + object-assign@4.1.1: {} + + object-deep-merge@2.0.0: {} + + object-inspect@1.13.4: {} + + object-is@1.1.6: + dependencies: + call-bind: 1.0.9 + define-properties: 1.2.1 + + object-keys@1.1.1: {} + + object.assign@4.1.7: + dependencies: + call-bind: 1.0.9 + call-bound: 1.0.4 + define-properties: 1.2.1 + es-object-atoms: 1.1.1 + has-symbols: 1.1.0 + object-keys: 1.1.1 + + object.entries@1.1.9: + dependencies: + call-bind: 1.0.9 + call-bound: 1.0.4 + define-properties: 1.2.1 + es-object-atoms: 1.1.1 + + object.fromentries@2.0.8: + dependencies: + call-bind: 1.0.9 + define-properties: 1.2.1 + es-abstract: 1.24.2 + es-object-atoms: 1.1.1 + + object.groupby@1.0.3: + dependencies: + call-bind: 1.0.9 + define-properties: 1.2.1 + es-abstract: 1.24.2 + + object.values@1.2.1: + dependencies: + call-bind: 1.0.9 + call-bound: 1.0.4 + define-properties: 1.2.1 + es-object-atoms: 1.1.1 + + observable-hooks@4.2.4(react-dom@19.2.5(react@19.2.5))(react@19.2.5)(rxjs@7.8.2): + dependencies: + react: 19.2.5 + react-dom: 19.2.5(react@19.2.5) + rxjs: 7.8.2 + + obug@2.1.1: {} + + oidc-client-ts@3.5.0: + dependencies: + jwt-decode: 4.0.0 + + once@1.4.0: + dependencies: + wrappy: 1.0.2 + + open@10.2.0: + dependencies: + default-browser: 5.5.0 + define-lazy-prop: 3.0.0 + is-inside-container: 1.0.0 + wsl-utils: 0.1.0 + + optionator@0.9.4: + dependencies: + deep-is: 0.1.4 + fast-levenshtein: 2.0.6 + levn: 0.4.1 + prelude-ls: 1.2.1 + type-check: 0.4.0 + word-wrap: 1.2.5 + + os-browserify@0.3.0: {} + + own-keys@1.0.1: + dependencies: + get-intrinsic: 1.3.0 + object-keys: 1.1.1 + safe-push-apply: 1.0.0 + + oxc-resolver@11.19.1(@emnapi/core@1.9.2)(@emnapi/runtime@1.9.2): + optionalDependencies: + "@oxc-resolver/binding-android-arm-eabi": 11.19.1 + "@oxc-resolver/binding-android-arm64": 11.19.1 + "@oxc-resolver/binding-darwin-arm64": 11.19.1 + "@oxc-resolver/binding-darwin-x64": 11.19.1 + "@oxc-resolver/binding-freebsd-x64": 11.19.1 + "@oxc-resolver/binding-linux-arm-gnueabihf": 11.19.1 + "@oxc-resolver/binding-linux-arm-musleabihf": 11.19.1 + "@oxc-resolver/binding-linux-arm64-gnu": 11.19.1 + "@oxc-resolver/binding-linux-arm64-musl": 11.19.1 + "@oxc-resolver/binding-linux-ppc64-gnu": 11.19.1 + "@oxc-resolver/binding-linux-riscv64-gnu": 11.19.1 + "@oxc-resolver/binding-linux-riscv64-musl": 11.19.1 + "@oxc-resolver/binding-linux-s390x-gnu": 11.19.1 + "@oxc-resolver/binding-linux-x64-gnu": 11.19.1 + "@oxc-resolver/binding-linux-x64-musl": 11.19.1 + "@oxc-resolver/binding-openharmony-arm64": 11.19.1 + "@oxc-resolver/binding-wasm32-wasi": 11.19.1(@emnapi/core@1.9.2)(@emnapi/runtime@1.9.2) + "@oxc-resolver/binding-win32-arm64-msvc": 11.19.1 + "@oxc-resolver/binding-win32-ia32-msvc": 11.19.1 + "@oxc-resolver/binding-win32-x64-msvc": 11.19.1 + transitivePeerDependencies: + - "@emnapi/core" + - "@emnapi/runtime" + + p-limit@2.3.0: + dependencies: + p-try: 2.2.0 + + p-limit@3.1.0: + dependencies: + yocto-queue: 0.1.0 + + p-locate@4.1.0: + dependencies: + p-limit: 2.3.0 + + p-locate@5.0.0: + dependencies: + p-limit: 3.1.0 + + p-retry@8.0.0: + dependencies: + is-network-error: 1.3.1 + + p-try@2.2.0: {} + + package-json-from-dist@1.0.1: {} + + pako@1.0.11: {} + + pako@2.1.0: {} + + param-case@3.0.4: + dependencies: + dot-case: 3.0.4 + tslib: 2.8.1 + + parent-module@1.0.1: + dependencies: + callsites: 3.1.0 + + parse-asn1@5.1.9: + dependencies: + asn1.js: 4.10.1 + browserify-aes: 1.2.0 + evp_bytestokey: 1.0.3 + pbkdf2: 3.1.5 + safe-buffer: 5.2.1 + + parse-imports-exports@0.2.4: + dependencies: + parse-statements: 1.0.11 + + parse-json@5.2.0: + dependencies: + "@babel/code-frame": 7.29.0 + error-ex: 1.3.4 + json-parse-even-better-errors: 2.3.1 + lines-and-columns: 1.2.4 + + parse-statements@1.0.11: {} + + parse5-htmlparser2-tree-adapter@7.1.0: + dependencies: + domhandler: 5.0.3 + parse5: 7.3.0 + + parse5-parser-stream@7.1.2: + dependencies: + parse5: 7.3.0 + + parse5@7.3.0: + dependencies: + entities: 6.0.1 + + pascal-case@3.1.2: + dependencies: + no-case: 3.0.4 + tslib: 2.8.1 + + path-browserify@1.0.1: {} + + path-exists@4.0.0: {} + + path-key@3.1.1: {} + + path-parse@1.0.7: {} + + path-posix@1.0.0: {} + + path-scurry@1.11.1: + dependencies: + lru-cache: 10.4.3 + minipass: 7.1.3 + + path-type@4.0.0: {} + + pathe@0.2.0: {} + + pathe@2.0.3: {} + + pathval@2.0.1: {} + + pbkdf2@3.1.5: + dependencies: + create-hash: 1.2.0 + create-hmac: 1.1.7 + ripemd160: 2.0.3 + safe-buffer: 5.2.1 + sha.js: 2.4.12 + to-buffer: 1.2.2 + + picocolors@1.1.1: {} + + picomatch@2.3.2: {} + + picomatch@4.0.4: {} + + pkg-dir@5.0.0: + dependencies: + find-up: 5.0.0 + + playwright-core@1.59.1: {} + + playwright@1.59.1: + dependencies: + playwright-core: 1.59.1 + optionalDependencies: + fsevents: 2.3.2 + + pluralize@8.0.0: {} + + pngjs@5.0.0: {} + + possible-typed-array-names@1.1.0: {} + + postcss-attribute-case-insensitive@7.0.1(postcss@8.5.10): + dependencies: + postcss: 8.5.10 + postcss-selector-parser: 7.1.1 + + postcss-clamp@4.1.0(postcss@8.5.10): + dependencies: + postcss: 8.5.10 + postcss-value-parser: 4.2.0 + + postcss-color-functional-notation@7.0.12(postcss@8.5.10): + dependencies: + "@csstools/css-color-parser": 3.1.0(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4) + "@csstools/css-parser-algorithms": 3.0.5(@csstools/css-tokenizer@3.0.4) + "@csstools/css-tokenizer": 3.0.4 + "@csstools/postcss-progressive-custom-properties": 4.2.1(postcss@8.5.10) + "@csstools/utilities": 2.0.0(postcss@8.5.10) + postcss: 8.5.10 + + postcss-color-hex-alpha@10.0.0(postcss@8.5.10): + dependencies: + "@csstools/utilities": 2.0.0(postcss@8.5.10) + postcss: 8.5.10 + postcss-value-parser: 4.2.0 + + postcss-color-rebeccapurple@10.0.0(postcss@8.5.10): + dependencies: + "@csstools/utilities": 2.0.0(postcss@8.5.10) + postcss: 8.5.10 + postcss-value-parser: 4.2.0 + + postcss-custom-media@11.0.6(postcss@8.5.10): + dependencies: + "@csstools/cascade-layer-name-parser": 2.0.5(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4) + "@csstools/css-parser-algorithms": 3.0.5(@csstools/css-tokenizer@3.0.4) + "@csstools/css-tokenizer": 3.0.4 + "@csstools/media-query-list-parser": 4.0.3(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4) + postcss: 8.5.10 + + postcss-custom-properties@14.0.6(postcss@8.5.10): + dependencies: + "@csstools/cascade-layer-name-parser": 2.0.5(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4) + "@csstools/css-parser-algorithms": 3.0.5(@csstools/css-tokenizer@3.0.4) + "@csstools/css-tokenizer": 3.0.4 + "@csstools/utilities": 2.0.0(postcss@8.5.10) + postcss: 8.5.10 + postcss-value-parser: 4.2.0 + + postcss-custom-selectors@8.0.5(postcss@8.5.10): + dependencies: + "@csstools/cascade-layer-name-parser": 2.0.5(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4) + "@csstools/css-parser-algorithms": 3.0.5(@csstools/css-tokenizer@3.0.4) + "@csstools/css-tokenizer": 3.0.4 + postcss: 8.5.10 + postcss-selector-parser: 7.1.1 + + postcss-dir-pseudo-class@9.0.1(postcss@8.5.10): + dependencies: + postcss: 8.5.10 + postcss-selector-parser: 7.1.1 + + postcss-double-position-gradients@6.0.4(postcss@8.5.10): + dependencies: + "@csstools/postcss-progressive-custom-properties": 4.2.1(postcss@8.5.10) + "@csstools/utilities": 2.0.0(postcss@8.5.10) + postcss: 8.5.10 + postcss-value-parser: 4.2.0 + + postcss-focus-visible@10.0.1(postcss@8.5.10): + dependencies: + postcss: 8.5.10 + postcss-selector-parser: 7.1.1 + + postcss-focus-within@9.0.1(postcss@8.5.10): + dependencies: + postcss: 8.5.10 + postcss-selector-parser: 7.1.1 + + postcss-font-variant@5.0.0(postcss@8.5.10): + dependencies: + postcss: 8.5.10 + + postcss-gap-properties@6.0.0(postcss@8.5.10): + dependencies: + postcss: 8.5.10 + + postcss-image-set-function@7.0.0(postcss@8.5.10): + dependencies: + "@csstools/utilities": 2.0.0(postcss@8.5.10) + postcss: 8.5.10 + postcss-value-parser: 4.2.0 + + postcss-lab-function@7.0.12(postcss@8.5.10): + dependencies: + "@csstools/css-color-parser": 3.1.0(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4) + "@csstools/css-parser-algorithms": 3.0.5(@csstools/css-tokenizer@3.0.4) + "@csstools/css-tokenizer": 3.0.4 + "@csstools/postcss-progressive-custom-properties": 4.2.1(postcss@8.5.10) + "@csstools/utilities": 2.0.0(postcss@8.5.10) + postcss: 8.5.10 + + postcss-logical@8.1.0(postcss@8.5.10): + dependencies: + postcss: 8.5.10 + postcss-value-parser: 4.2.0 + + postcss-nesting@13.0.2(postcss@8.5.10): + dependencies: + "@csstools/selector-resolve-nested": 3.1.0(postcss-selector-parser@7.1.1) + "@csstools/selector-specificity": 5.0.0(postcss-selector-parser@7.1.1) + postcss: 8.5.10 + postcss-selector-parser: 7.1.1 + + postcss-opacity-percentage@3.0.0(postcss@8.5.10): + dependencies: + postcss: 8.5.10 + + postcss-overflow-shorthand@6.0.0(postcss@8.5.10): + dependencies: + postcss: 8.5.10 + postcss-value-parser: 4.2.0 + + postcss-page-break@3.0.4(postcss@8.5.10): + dependencies: + postcss: 8.5.10 + + postcss-place@10.0.0(postcss@8.5.10): + dependencies: + postcss: 8.5.10 + postcss-value-parser: 4.2.0 + + postcss-preset-env@10.6.1(postcss@8.5.10): + dependencies: + "@csstools/postcss-alpha-function": 1.0.1(postcss@8.5.10) + "@csstools/postcss-cascade-layers": 5.0.2(postcss@8.5.10) + "@csstools/postcss-color-function": 4.0.12(postcss@8.5.10) + "@csstools/postcss-color-function-display-p3-linear": 1.0.1(postcss@8.5.10) + "@csstools/postcss-color-mix-function": 3.0.12(postcss@8.5.10) + "@csstools/postcss-color-mix-variadic-function-arguments": 1.0.2(postcss@8.5.10) + "@csstools/postcss-content-alt-text": 2.0.8(postcss@8.5.10) + "@csstools/postcss-contrast-color-function": 2.0.12(postcss@8.5.10) + "@csstools/postcss-exponential-functions": 2.0.9(postcss@8.5.10) + "@csstools/postcss-font-format-keywords": 4.0.0(postcss@8.5.10) + "@csstools/postcss-gamut-mapping": 2.0.11(postcss@8.5.10) + "@csstools/postcss-gradients-interpolation-method": 5.0.12(postcss@8.5.10) + "@csstools/postcss-hwb-function": 4.0.12(postcss@8.5.10) + "@csstools/postcss-ic-unit": 4.0.4(postcss@8.5.10) + "@csstools/postcss-initial": 2.0.1(postcss@8.5.10) + "@csstools/postcss-is-pseudo-class": 5.0.3(postcss@8.5.10) + "@csstools/postcss-light-dark-function": 2.0.11(postcss@8.5.10) + "@csstools/postcss-logical-float-and-clear": 3.0.0(postcss@8.5.10) + "@csstools/postcss-logical-overflow": 2.0.0(postcss@8.5.10) + "@csstools/postcss-logical-overscroll-behavior": 2.0.0(postcss@8.5.10) + "@csstools/postcss-logical-resize": 3.0.0(postcss@8.5.10) + "@csstools/postcss-logical-viewport-units": 3.0.4(postcss@8.5.10) + "@csstools/postcss-media-minmax": 2.0.9(postcss@8.5.10) + "@csstools/postcss-media-queries-aspect-ratio-number-values": 3.0.5(postcss@8.5.10) + "@csstools/postcss-nested-calc": 4.0.0(postcss@8.5.10) + "@csstools/postcss-normalize-display-values": 4.0.1(postcss@8.5.10) + "@csstools/postcss-oklab-function": 4.0.12(postcss@8.5.10) + "@csstools/postcss-position-area-property": 1.0.0(postcss@8.5.10) + "@csstools/postcss-progressive-custom-properties": 4.2.1(postcss@8.5.10) + "@csstools/postcss-property-rule-prelude-list": 1.0.0(postcss@8.5.10) + "@csstools/postcss-random-function": 2.0.1(postcss@8.5.10) + "@csstools/postcss-relative-color-syntax": 3.0.12(postcss@8.5.10) + "@csstools/postcss-scope-pseudo-class": 4.0.1(postcss@8.5.10) + "@csstools/postcss-sign-functions": 1.1.4(postcss@8.5.10) + "@csstools/postcss-stepped-value-functions": 4.0.9(postcss@8.5.10) + "@csstools/postcss-syntax-descriptor-syntax-production": 1.0.1(postcss@8.5.10) + "@csstools/postcss-system-ui-font-family": 1.0.0(postcss@8.5.10) + "@csstools/postcss-text-decoration-shorthand": 4.0.3(postcss@8.5.10) + "@csstools/postcss-trigonometric-functions": 4.0.9(postcss@8.5.10) + "@csstools/postcss-unset-value": 4.0.0(postcss@8.5.10) + autoprefixer: 10.5.0(postcss@8.5.10) + browserslist: 4.28.2 + css-blank-pseudo: 7.0.1(postcss@8.5.10) + css-has-pseudo: 7.0.3(postcss@8.5.10) + css-prefers-color-scheme: 10.0.0(postcss@8.5.10) + cssdb: 8.8.0 + postcss: 8.5.10 + postcss-attribute-case-insensitive: 7.0.1(postcss@8.5.10) + postcss-clamp: 4.1.0(postcss@8.5.10) + postcss-color-functional-notation: 7.0.12(postcss@8.5.10) + postcss-color-hex-alpha: 10.0.0(postcss@8.5.10) + postcss-color-rebeccapurple: 10.0.0(postcss@8.5.10) + postcss-custom-media: 11.0.6(postcss@8.5.10) + postcss-custom-properties: 14.0.6(postcss@8.5.10) + postcss-custom-selectors: 8.0.5(postcss@8.5.10) + postcss-dir-pseudo-class: 9.0.1(postcss@8.5.10) + postcss-double-position-gradients: 6.0.4(postcss@8.5.10) + postcss-focus-visible: 10.0.1(postcss@8.5.10) + postcss-focus-within: 9.0.1(postcss@8.5.10) + postcss-font-variant: 5.0.0(postcss@8.5.10) + postcss-gap-properties: 6.0.0(postcss@8.5.10) + postcss-image-set-function: 7.0.0(postcss@8.5.10) + postcss-lab-function: 7.0.12(postcss@8.5.10) + postcss-logical: 8.1.0(postcss@8.5.10) + postcss-nesting: 13.0.2(postcss@8.5.10) + postcss-opacity-percentage: 3.0.0(postcss@8.5.10) + postcss-overflow-shorthand: 6.0.0(postcss@8.5.10) + postcss-page-break: 3.0.4(postcss@8.5.10) + postcss-place: 10.0.0(postcss@8.5.10) + postcss-pseudo-class-any-link: 10.0.1(postcss@8.5.10) + postcss-replace-overflow-wrap: 4.0.0(postcss@8.5.10) + postcss-selector-not: 8.0.1(postcss@8.5.10) + + postcss-pseudo-class-any-link@10.0.1(postcss@8.5.10): + dependencies: + postcss: 8.5.10 + postcss-selector-parser: 7.1.1 + + postcss-replace-overflow-wrap@4.0.0(postcss@8.5.10): + dependencies: + postcss: 8.5.10 + + postcss-selector-not@8.0.1(postcss@8.5.10): + dependencies: + postcss: 8.5.10 + postcss-selector-parser: 7.1.1 + + postcss-selector-parser@7.1.1: + dependencies: + cssesc: 3.0.0 + util-deprecate: 1.0.2 + + postcss-value-parser@4.2.0: {} + + postcss@8.5.10: + dependencies: + nanoid: 3.3.11 + picocolors: 1.1.1 + source-map-js: 1.2.1 + + posthog-js@1.160.3: + dependencies: + fflate: 0.4.8 + preact: 10.29.1 + web-vitals: 4.2.4 + + preact@10.29.1: {} + + prelude-ls@1.2.1: {} + + prettier@3.8.3: {} + + pretty-format@27.5.1: + dependencies: + ansi-regex: 5.0.1 + ansi-styles: 5.2.0 + react-is: 17.0.2 + + process-nextick-args@2.0.1: {} + + process@0.11.10: {} + + progress@2.0.3: {} + + promise-map-series@0.3.0: {} + + prompts@2.4.2: + dependencies: + kleur: 3.0.3 + sisteransi: 1.0.5 + + prop-types@15.8.1: + dependencies: + loose-envify: 1.4.0 + object-assign: 4.1.1 + react-is: 16.13.1 + + proxy-from-env@1.1.0: {} + + public-encrypt@4.0.3: + dependencies: + bn.js: 4.12.3 + browserify-rsa: 4.1.1 + create-hash: 1.2.0 + parse-asn1: 5.1.9 + randombytes: 2.1.0 + safe-buffer: 5.2.1 + + punycode@1.4.1: {} + + punycode@2.3.1: {} + + qrcode@1.5.4: + dependencies: + dijkstrajs: 1.0.3 + pngjs: 5.0.0 + yargs: 15.4.1 + + qs@6.15.1: + dependencies: + side-channel: 1.1.0 + + querystring-es3@0.2.1: {} + + queue-microtask@1.2.3: {} + + quick-temp@0.1.9: + dependencies: + mktemp: 2.0.2 + rimraf: 5.0.10 + underscore.string: 3.3.6 + + randombytes@2.1.0: + dependencies: + safe-buffer: 5.2.1 + + randomfill@1.0.4: + dependencies: + randombytes: 2.1.0 + safe-buffer: 5.2.1 + + react-docgen-typescript@2.4.0(typescript@5.9.3): + dependencies: + typescript: 5.9.3 + + react-docgen@8.0.3: + dependencies: + "@babel/core": 7.29.0 + "@babel/traverse": 7.29.0 + "@babel/types": 7.29.0 + "@types/babel__core": 7.20.5 + "@types/babel__traverse": 7.28.0 + "@types/doctrine": 0.0.9 + "@types/resolve": 1.20.6 + doctrine: 3.0.0 + resolve: 1.22.12 + strip-indent: 4.1.1 + transitivePeerDependencies: + - supports-color + + react-dom@19.2.5(react@19.2.5): + dependencies: + react: 19.2.5 + scheduler: 0.27.0 + + react-i18next@16.6.6(i18next@25.10.10(typescript@5.9.3))(react-dom@19.2.5(react@19.2.5))(react@19.2.5)(typescript@5.9.3): + dependencies: + "@babel/runtime": 7.29.2 + html-parse-stringify: 3.0.1 + i18next: 25.10.10(typescript@5.9.3) + react: 19.2.5 + use-sync-external-store: 1.6.0(react@19.2.5) + optionalDependencies: + react-dom: 19.2.5(react@19.2.5) + typescript: 5.9.3 + + react-is@16.13.1: {} + + react-is@17.0.2: {} + + react-refresh@0.17.0: {} + + react-remove-scroll-bar@2.3.8(@types/react@19.2.14)(react@19.2.5): + dependencies: + react: 19.2.5 + react-style-singleton: 2.2.3(@types/react@19.2.14)(react@19.2.5) + tslib: 2.8.1 + optionalDependencies: + "@types/react": 19.2.14 + + react-remove-scroll@2.7.2(@types/react@19.2.14)(react@19.2.5): + dependencies: + react: 19.2.5 + react-remove-scroll-bar: 2.3.8(@types/react@19.2.14)(react@19.2.5) + react-style-singleton: 2.2.3(@types/react@19.2.14)(react@19.2.5) + tslib: 2.8.1 + use-callback-ref: 1.3.3(@types/react@19.2.14)(react@19.2.5) + use-sidecar: 1.1.3(@types/react@19.2.14)(react@19.2.5) + optionalDependencies: + "@types/react": 19.2.14 + + react-router-dom@7.14.1(react-dom@19.2.5(react@19.2.5))(react@19.2.5): + dependencies: + react: 19.2.5 + react-dom: 19.2.5(react@19.2.5) + react-router: 7.14.1(react-dom@19.2.5(react@19.2.5))(react@19.2.5) + + react-router@7.14.1(react-dom@19.2.5(react@19.2.5))(react@19.2.5): + dependencies: + cookie: 1.1.1 + react: 19.2.5 + set-cookie-parser: 2.7.2 + optionalDependencies: + react-dom: 19.2.5(react@19.2.5) + + react-style-singleton@2.2.3(@types/react@19.2.14)(react@19.2.5): + dependencies: + get-nonce: 1.0.1 + react: 19.2.5 + tslib: 2.8.1 + optionalDependencies: + "@types/react": 19.2.14 + + react-use-measure@2.1.7(react-dom@19.2.5(react@19.2.5))(react@19.2.5): + dependencies: + react: 19.2.5 + optionalDependencies: + react-dom: 19.2.5(react@19.2.5) + + react@19.2.5: {} + + read-pkg-up@7.0.1: + dependencies: + find-up: 4.1.0 + read-pkg: 5.2.0 + type-fest: 0.8.1 + + read-pkg@5.2.0: + dependencies: + "@types/normalize-package-data": 2.4.4 + normalize-package-data: 2.5.0 + parse-json: 5.2.0 + type-fest: 0.6.0 + + readable-stream@2.3.8: + dependencies: + core-util-is: 1.0.3 + inherits: 2.0.4 + isarray: 1.0.0 + process-nextick-args: 2.0.1 + safe-buffer: 5.1.2 + string_decoder: 1.1.1 + util-deprecate: 1.0.2 + + readable-stream@3.6.2: + dependencies: + inherits: 2.0.4 + string_decoder: 1.3.0 + util-deprecate: 1.0.2 + + readdirp@3.6.0: + dependencies: + picomatch: 2.3.2 + + readdirp@4.1.2: {} + + recast@0.23.11: + dependencies: + ast-types: 0.16.1 + esprima: 4.0.1 + source-map: 0.6.1 + tiny-invariant: 1.3.3 + tslib: 2.8.1 + + redent@3.0.0: + dependencies: + indent-string: 4.0.0 + strip-indent: 3.0.0 + + reflect.getprototypeof@1.0.10: + dependencies: + call-bind: 1.0.9 + define-properties: 1.2.1 + es-abstract: 1.24.2 + es-errors: 1.3.0 + es-object-atoms: 1.1.1 + get-intrinsic: 1.3.0 + get-proto: 1.0.1 + which-builtin-type: 1.2.1 + + regenerate-unicode-properties@10.2.2: + dependencies: + regenerate: 1.4.2 + + regenerate@1.4.2: {} + + regexp-tree@0.1.27: {} + + regexp.prototype.flags@1.5.4: + dependencies: + call-bind: 1.0.9 + define-properties: 1.2.1 + es-errors: 1.3.0 + get-proto: 1.0.1 + gopd: 1.2.0 + set-function-name: 2.0.2 + + regexparam@3.0.0: {} + + regexpu-core@6.4.0: + dependencies: + regenerate: 1.4.2 + regenerate-unicode-properties: 10.2.2 + regjsgen: 0.8.0 + regjsparser: 0.13.1 + unicode-match-property-ecmascript: 2.0.0 + unicode-match-property-value-ecmascript: 2.2.1 + + regjsgen@0.8.0: {} + + regjsparser@0.10.0: + dependencies: + jsesc: 0.5.0 + + regjsparser@0.13.1: + dependencies: + jsesc: 3.1.0 + + relateurl@0.2.7: {} + + remove-trailing-separator@1.1.0: {} + + replace-ext@2.0.0: {} + + require-directory@2.1.1: {} + + require-main-filename@2.0.0: {} + + requireindex@1.2.0: {} + + reserved-identifiers@1.2.0: {} + + resolve-from@4.0.0: {} + + resolve-options@2.0.0: + dependencies: + value-or-function: 4.0.0 + + resolve@1.22.12: + dependencies: + es-errors: 1.3.0 + is-core-module: 2.16.1 + path-parse: 1.0.7 + supports-preserve-symlinks-flag: 1.0.0 + + resolve@2.0.0-next.6: + dependencies: + es-errors: 1.3.0 + is-core-module: 2.16.1 + node-exports-info: 1.6.0 + object-keys: 1.1.1 + path-parse: 1.0.7 + supports-preserve-symlinks-flag: 1.0.0 + + reusify@1.1.0: {} + + rimraf@3.0.2: + dependencies: + glob: 10.5.0 + + rimraf@5.0.10: + dependencies: + glob: 10.5.0 + + ripemd160@2.0.3: + dependencies: + hash-base: 3.1.2 + inherits: 2.0.4 + + rolldown@1.0.0-rc.15: + dependencies: + "@oxc-project/types": 0.124.0 + "@rolldown/pluginutils": 1.0.0-rc.15 + optionalDependencies: + "@rolldown/binding-android-arm64": 1.0.0-rc.15 + "@rolldown/binding-darwin-arm64": 1.0.0-rc.15 + "@rolldown/binding-darwin-x64": 1.0.0-rc.15 + "@rolldown/binding-freebsd-x64": 1.0.0-rc.15 + "@rolldown/binding-linux-arm-gnueabihf": 1.0.0-rc.15 + "@rolldown/binding-linux-arm64-gnu": 1.0.0-rc.15 + "@rolldown/binding-linux-arm64-musl": 1.0.0-rc.15 + "@rolldown/binding-linux-ppc64-gnu": 1.0.0-rc.15 + "@rolldown/binding-linux-s390x-gnu": 1.0.0-rc.15 + "@rolldown/binding-linux-x64-gnu": 1.0.0-rc.15 + "@rolldown/binding-linux-x64-musl": 1.0.0-rc.15 + "@rolldown/binding-openharmony-arm64": 1.0.0-rc.15 + "@rolldown/binding-wasm32-wasi": 1.0.0-rc.15 + "@rolldown/binding-win32-arm64-msvc": 1.0.0-rc.15 + "@rolldown/binding-win32-x64-msvc": 1.0.0-rc.15 + + rrweb-cssom@0.8.0: {} + + rsvp@3.2.1: {} + + rsvp@4.8.5: {} + + run-applescript@7.1.0: {} + + run-parallel@1.2.0: + dependencies: + queue-microtask: 1.2.3 + + rxjs-report-usage@1.0.6: + dependencies: + "@babel/parser": 7.29.2 + "@babel/traverse": 7.29.0 + "@babel/types": 7.29.0 + bent: 7.3.12 + chalk: 4.1.2 + glob: 10.5.0 + prompts: 2.4.2 + transitivePeerDependencies: + - supports-color + + rxjs@7.8.2: + dependencies: + tslib: 2.8.1 + + safe-array-concat@1.1.3: + dependencies: + call-bind: 1.0.9 + call-bound: 1.0.4 + get-intrinsic: 1.3.0 + has-symbols: 1.1.0 + isarray: 2.0.5 + + safe-buffer@5.1.2: {} + + safe-buffer@5.2.1: {} + + safe-push-apply@1.0.0: + dependencies: + es-errors: 1.3.0 + isarray: 2.0.5 + + safe-regex-test@1.1.0: + dependencies: + call-bound: 1.0.4 + es-errors: 1.3.0 + is-regex: 1.2.1 + + safer-buffer@2.1.2: {} + + sass@1.99.0: + dependencies: + chokidar: 4.0.3 + immutable: 5.1.5 + source-map-js: 1.2.1 + optionalDependencies: + "@parcel/watcher": 2.5.6 + + saxes@6.0.0: + dependencies: + xmlchars: 2.2.0 + + scheduler@0.27.0: {} + + sdp-transform@2.15.0: {} + + sdp-transform@3.0.0: {} + + sdp@3.2.2: {} + + semver@5.7.2: {} + + semver@6.3.1: {} + + semver@7.7.4: {} + + set-blocking@2.0.0: {} + + set-cookie-parser@2.7.2: {} + + set-function-length@1.2.2: + dependencies: + define-data-property: 1.1.4 + es-errors: 1.3.0 + function-bind: 1.1.2 + get-intrinsic: 1.3.0 + gopd: 1.2.0 + has-property-descriptors: 1.0.2 + + set-function-name@2.0.2: + dependencies: + define-data-property: 1.1.4 + es-errors: 1.3.0 + functions-have-names: 1.2.3 + has-property-descriptors: 1.0.2 + + set-proto@1.0.0: + dependencies: + dunder-proto: 1.0.1 + es-errors: 1.3.0 + es-object-atoms: 1.1.1 + + setimmediate@1.0.5: {} + + sha.js@2.4.12: + dependencies: + inherits: 2.0.4 + safe-buffer: 5.2.1 + to-buffer: 1.2.2 + + shebang-command@2.0.0: + dependencies: + shebang-regex: 3.0.0 + + shebang-regex@3.0.0: {} + + side-channel-list@1.0.1: + dependencies: + es-errors: 1.3.0 + object-inspect: 1.13.4 + + side-channel-map@1.0.1: + dependencies: + call-bound: 1.0.4 + es-errors: 1.3.0 + get-intrinsic: 1.3.0 + object-inspect: 1.13.4 + + side-channel-weakmap@1.0.2: + dependencies: + call-bound: 1.0.4 + es-errors: 1.3.0 + get-intrinsic: 1.3.0 + object-inspect: 1.13.4 + side-channel-map: 1.0.1 + + side-channel@1.1.0: + dependencies: + es-errors: 1.3.0 + object-inspect: 1.13.4 + side-channel-list: 1.0.1 + side-channel-map: 1.0.1 + side-channel-weakmap: 1.0.2 + + siginfo@2.0.0: {} + + signal-exit@4.1.0: {} + + sisteransi@1.0.5: {} + + slash@3.0.0: {} + + smol-toml@1.6.1: {} + + snake-case@3.0.4: + dependencies: + dot-case: 3.0.4 + tslib: 2.8.1 + + sort-keys@5.1.0: + dependencies: + is-plain-obj: 4.1.0 + + source-map-js@1.2.1: {} + + source-map-support@0.5.21: + dependencies: + buffer-from: 1.1.2 + source-map: 0.6.1 + + source-map@0.6.1: {} + + spdx-correct@3.2.0: + dependencies: + spdx-expression-parse: 3.0.1 + spdx-license-ids: 3.0.23 + + spdx-exceptions@2.5.0: {} + + spdx-expression-parse@3.0.1: + dependencies: + spdx-exceptions: 2.5.0 + spdx-license-ids: 3.0.23 + + spdx-expression-parse@4.0.0: + dependencies: + spdx-exceptions: 2.5.0 + spdx-license-ids: 3.0.23 + + spdx-license-ids@3.0.23: {} + + sprintf-js@1.1.3: {} + + stackback@0.0.2: {} + + std-env@4.1.0: {} + + stop-iteration-iterator@1.1.0: + dependencies: + es-errors: 1.3.0 + internal-slot: 1.1.0 + + storybook@10.3.5(@testing-library/dom@10.4.1)(prettier@3.8.3)(react-dom@19.2.5(react@19.2.5))(react@19.2.5): + dependencies: + "@storybook/global": 5.0.0 + "@storybook/icons": 2.0.1(react-dom@19.2.5(react@19.2.5))(react@19.2.5) + "@testing-library/jest-dom": 6.9.1 + "@testing-library/user-event": 14.6.1(@testing-library/dom@10.4.1) + "@vitest/expect": 3.2.4 + "@vitest/spy": 3.2.4 + "@webcontainer/env": 1.1.1 + esbuild: 0.27.7 + open: 10.2.0 + recast: 0.23.11 + semver: 7.7.4 + use-sync-external-store: 1.6.0(react@19.2.5) + ws: 8.20.0 + optionalDependencies: + prettier: 3.8.3 + transitivePeerDependencies: + - "@testing-library/dom" + - bufferutil + - react + - react-dom + - utf-8-validate + + stream-browserify@3.0.0: + dependencies: + inherits: 2.0.4 + readable-stream: 3.6.2 + + stream-composer@1.0.2: + dependencies: + streamx: 2.25.0 + transitivePeerDependencies: + - bare-abort-controller + - react-native-b4a + + stream-http@3.2.0: + dependencies: + builtin-status-codes: 3.0.0 + inherits: 2.0.4 + readable-stream: 3.6.2 + xtend: 4.0.2 + + streamx@2.25.0: + dependencies: + events-universal: 1.0.1 + fast-fifo: 1.3.2 + text-decoder: 1.2.7 + transitivePeerDependencies: + - bare-abort-controller + - react-native-b4a + + string-width@4.2.3: + dependencies: + emoji-regex: 8.0.0 + is-fullwidth-code-point: 3.0.0 + strip-ansi: 6.0.1 + + string-width@5.1.2: + dependencies: + eastasianwidth: 0.2.0 + emoji-regex: 9.2.2 + strip-ansi: 7.2.0 + + string.prototype.includes@2.0.1: + dependencies: + call-bind: 1.0.9 + define-properties: 1.2.1 + es-abstract: 1.24.2 + + string.prototype.matchall@4.0.12: + dependencies: + call-bind: 1.0.9 + call-bound: 1.0.4 + define-properties: 1.2.1 + es-abstract: 1.24.2 + es-errors: 1.3.0 + es-object-atoms: 1.1.1 + get-intrinsic: 1.3.0 + gopd: 1.2.0 + has-symbols: 1.1.0 + internal-slot: 1.1.0 + regexp.prototype.flags: 1.5.4 + set-function-name: 2.0.2 + side-channel: 1.1.0 + + string.prototype.repeat@1.0.0: + dependencies: + define-properties: 1.2.1 + es-abstract: 1.24.2 + + string.prototype.trim@1.2.10: + dependencies: + call-bind: 1.0.9 + call-bound: 1.0.4 + define-data-property: 1.1.4 + define-properties: 1.2.1 + es-abstract: 1.24.2 + es-object-atoms: 1.1.1 + has-property-descriptors: 1.0.2 + + string.prototype.trimend@1.0.9: + dependencies: + call-bind: 1.0.9 + call-bound: 1.0.4 + define-properties: 1.2.1 + es-object-atoms: 1.1.1 + + string.prototype.trimstart@1.0.8: + dependencies: + call-bind: 1.0.9 + define-properties: 1.2.1 + es-object-atoms: 1.1.1 + + string_decoder@1.1.1: + dependencies: + safe-buffer: 5.1.2 + + string_decoder@1.3.0: + dependencies: + safe-buffer: 5.2.1 + + strip-ansi@6.0.1: + dependencies: + ansi-regex: 5.0.1 + + strip-ansi@7.2.0: + dependencies: + ansi-regex: 6.2.2 + + strip-bom@3.0.0: {} + + strip-indent@3.0.0: + dependencies: + min-indent: 1.0.1 + + strip-indent@4.1.1: {} + + strip-json-comments@3.1.1: {} + + strip-json-comments@5.0.3: {} + + supports-color@7.2.0: + dependencies: + has-flag: 4.0.0 + + supports-preserve-symlinks-flag@1.0.0: {} + + svg-parser@2.0.4: {} + + symbol-tree@3.2.4: {} + + symlink-or-copy@1.3.1: {} + + tabbable@6.4.0: {} + + teex@1.0.1: + dependencies: + streamx: 2.25.0 + transitivePeerDependencies: + - bare-abort-controller + - react-native-b4a + + terser@5.46.1: + dependencies: + "@jridgewell/source-map": 0.3.11 + acorn: 8.16.0 + commander: 2.20.3 + source-map-support: 0.5.21 + + text-decoder@1.2.7: + dependencies: + b4a: 1.8.0 + transitivePeerDependencies: + - react-native-b4a + + text-table@0.2.0: {} + + through2@2.0.5: + dependencies: + readable-stream: 2.3.8 + xtend: 4.0.2 + + timers-browserify@2.0.12: + dependencies: + setimmediate: 1.0.5 + + tiny-invariant@1.3.3: {} + + tinybench@2.9.0: {} + + tinyexec@1.1.1: {} + + tinyglobby@0.2.16: + dependencies: + fdir: 6.5.0(picomatch@4.0.4) + picomatch: 4.0.4 + + tinyrainbow@2.0.0: {} + + tinyrainbow@3.1.0: {} + + tinyspy@4.0.4: {} + + tldts-core@6.1.86: {} + + tldts@6.1.86: + dependencies: + tldts-core: 6.1.86 + + to-buffer@1.2.2: + dependencies: + isarray: 2.0.5 + safe-buffer: 5.2.1 + typed-array-buffer: 1.0.3 + + to-regex-range@5.0.1: + dependencies: + is-number: 7.0.0 + + to-through@3.0.0: + dependencies: + streamx: 2.25.0 + transitivePeerDependencies: + - bare-abort-controller + - react-native-b4a + + to-valid-identifier@1.0.0: + dependencies: + "@sindresorhus/base62": 1.0.0 + reserved-identifiers: 1.2.0 + + toggle-selection@1.0.6: {} + + tough-cookie@5.1.2: + dependencies: + tldts: 6.1.86 + + tr46@0.0.3: {} + + tr46@5.1.1: + dependencies: + punycode: 2.3.1 + + ts-api-utils@2.5.0(typescript@5.9.3): + dependencies: + typescript: 5.9.3 + + ts-dedent@2.2.0: {} + + tsconfig-paths@3.15.0: + dependencies: + "@types/json5": 0.0.29 + json5: 1.0.2 + minimist: 1.2.8 + strip-bom: 3.0.0 + + tsconfig-paths@4.2.0: + dependencies: + json5: 2.2.3 + minimist: 1.2.8 + strip-bom: 3.0.0 + + tslib@1.14.1: {} + + tslib@2.8.1: {} + + tsutils-etc@1.4.2(tsutils@3.21.0(typescript@5.9.3))(typescript@5.9.3): + dependencies: + "@types/yargs": 17.0.35 + tsutils: 3.21.0(typescript@5.9.3) + typescript: 5.9.3 + yargs: 17.7.2 + + tsutils@3.21.0(typescript@5.9.3): + dependencies: + tslib: 1.14.1 + typescript: 5.9.3 + + tty-browserify@0.0.1: {} + + tunnel@0.0.6: {} + + type-check@0.4.0: + dependencies: + prelude-ls: 1.2.1 + + type-fest@0.20.2: {} + + type-fest@0.6.0: {} + + type-fest@0.8.1: {} + + typed-array-buffer@1.0.3: + dependencies: + call-bound: 1.0.4 + es-errors: 1.3.0 + is-typed-array: 1.1.15 + + typed-array-byte-length@1.0.3: + dependencies: + call-bind: 1.0.9 + for-each: 0.3.5 + gopd: 1.2.0 + has-proto: 1.2.0 + is-typed-array: 1.1.15 + + typed-array-byte-offset@1.0.4: + dependencies: + available-typed-arrays: 1.0.7 + call-bind: 1.0.9 + for-each: 0.3.5 + gopd: 1.2.0 + has-proto: 1.2.0 + is-typed-array: 1.1.15 + reflect.getprototypeof: 1.0.10 + + typed-array-length@1.0.7: + dependencies: + call-bind: 1.0.9 + for-each: 0.3.5 + gopd: 1.2.0 + is-typed-array: 1.1.15 + possible-typed-array-names: 1.1.0 + reflect.getprototypeof: 1.0.10 + + typed-emitter@2.1.0: + optionalDependencies: + rxjs: 7.8.2 + + typescript-eslint-language-service@5.0.5(@typescript-eslint/parser@8.58.2(eslint@8.57.1)(typescript@5.9.3))(eslint@8.57.1)(typescript@5.9.3): + dependencies: + "@typescript-eslint/parser": 8.58.2(eslint@8.57.1)(typescript@5.9.3) + eslint: 8.57.1 + typescript: 5.9.3 + + typescript@5.9.3: {} + + unbash@2.2.0: {} + + unbox-primitive@1.1.0: + dependencies: + call-bound: 1.0.4 + has-bigints: 1.1.0 + has-symbols: 1.1.0 + which-boxed-primitive: 1.1.1 + + underscore.string@3.3.6: + dependencies: + sprintf-js: 1.1.3 + util-deprecate: 1.0.2 + + undici-types@7.16.0: {} + + undici@5.29.0: + dependencies: + "@fastify/busboy": 2.1.1 + + undici@7.25.0: {} + + unhomoglyph@1.0.6: {} + + unicode-canonical-property-names-ecmascript@2.0.1: {} + + unicode-match-property-ecmascript@2.0.0: + dependencies: + unicode-canonical-property-names-ecmascript: 2.0.1 + unicode-property-aliases-ecmascript: 2.2.0 + + unicode-match-property-value-ecmascript@2.2.1: {} + + unicode-property-aliases-ecmascript@2.2.0: {} + + unique-names-generator@4.7.1: {} + + universal-user-agent@6.0.1: {} + + universalify@0.1.2: {} + + universalify@2.0.1: {} + + unplugin@1.0.1: + dependencies: + acorn: 8.16.0 + chokidar: 3.6.0 + webpack-sources: 3.3.4 + webpack-virtual-modules: 0.5.0 + + unplugin@1.16.1: + dependencies: + acorn: 8.16.0 + webpack-virtual-modules: 0.6.2 + + unplugin@2.3.11: + dependencies: + "@jridgewell/remapping": 2.3.5 + acorn: 8.16.0 + picomatch: 4.0.4 + webpack-virtual-modules: 0.6.2 + + update-browserslist-db@1.2.3(browserslist@4.28.2): + dependencies: + browserslist: 4.28.2 + escalade: 3.2.0 + picocolors: 1.1.1 + + uri-js@4.4.1: + dependencies: + punycode: 2.3.1 + + url@0.11.4: + dependencies: + punycode: 1.4.1 + qs: 6.15.1 + + use-callback-ref@1.3.3(@types/react@19.2.14)(react@19.2.5): + dependencies: + react: 19.2.5 + tslib: 2.8.1 + optionalDependencies: + "@types/react": 19.2.14 + + use-sidecar@1.1.3(@types/react@19.2.14)(react@19.2.5): + dependencies: + detect-node-es: 1.1.0 + react: 19.2.5 + tslib: 2.8.1 + optionalDependencies: + "@types/react": 19.2.14 + + use-sync-external-store@1.6.0(react@19.2.5): + dependencies: + react: 19.2.5 + + usehooks-ts@3.1.1(react@19.2.5): + dependencies: + lodash.debounce: 4.0.8 + react: 19.2.5 + + util-deprecate@1.0.2: {} + + util@0.12.5: + dependencies: + inherits: 2.0.4 + is-arguments: 1.2.0 + is-generator-function: 1.1.2 + is-typed-array: 1.1.15 + which-typed-array: 1.1.20 + + uuid@13.0.0: {} + + validate-npm-package-license@3.0.4: + dependencies: + spdx-correct: 3.2.0 + spdx-expression-parse: 3.0.1 + + value-or-function@4.0.0: {} + + vaul@1.1.2(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5): + dependencies: + "@radix-ui/react-dialog": 1.1.15(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5) + react: 19.2.5 + react-dom: 19.2.5(react@19.2.5) + transitivePeerDependencies: + - "@types/react" + - "@types/react-dom" + + vinyl-contents@2.0.0: + dependencies: + bl: 5.1.0 + vinyl: 3.0.1 + transitivePeerDependencies: + - bare-abort-controller + - react-native-b4a + + vinyl-fs@4.0.2: + dependencies: + fs-mkdirp-stream: 2.0.1 + glob-stream: 8.0.3 + graceful-fs: 4.2.11 + iconv-lite: 0.6.3 + is-valid-glob: 1.0.0 + lead: 4.0.0 + normalize-path: 3.0.0 + resolve-options: 2.0.0 + stream-composer: 1.0.2 + streamx: 2.25.0 + to-through: 3.0.0 + value-or-function: 4.0.0 + vinyl: 3.0.1 + vinyl-sourcemap: 2.0.0 + transitivePeerDependencies: + - bare-abort-controller + - react-native-b4a + + vinyl-sourcemap@2.0.0: + dependencies: + convert-source-map: 2.0.0 + graceful-fs: 4.2.11 + now-and-later: 3.0.0 + streamx: 2.25.0 + vinyl: 3.0.1 + vinyl-contents: 2.0.0 + transitivePeerDependencies: + - bare-abort-controller + - react-native-b4a + + vinyl@3.0.1: + dependencies: + clone: 2.1.2 + remove-trailing-separator: 1.1.0 + replace-ext: 2.0.0 + teex: 1.0.1 + transitivePeerDependencies: + - bare-abort-controller + - react-native-b4a + + vite-plugin-generate-file@0.3.1: + dependencies: + ejs: 3.1.10 + js-yaml: 4.1.1 + mime-types: 2.1.35 + picocolors: 1.1.1 + + vite-plugin-html@3.2.2(vite@8.0.8(@types/node@24.12.2)(esbuild@0.27.7)(jiti@2.6.1)(sass@1.99.0)(terser@5.46.1)(yaml@2.8.3)): + dependencies: + "@rollup/pluginutils": 4.2.1 + colorette: 2.0.20 + connect-history-api-fallback: 1.6.0 + consola: 2.15.3 + dotenv: 16.6.1 + dotenv-expand: 8.0.3 + ejs: 3.1.10 + fast-glob: 3.3.3 + fs-extra: 10.1.0 + html-minifier-terser: 6.1.0 + node-html-parser: 5.4.2 + pathe: 0.2.0 + vite: 8.0.8(@types/node@24.12.2)(esbuild@0.27.7)(jiti@2.6.1)(sass@1.99.0)(terser@5.46.1)(yaml@2.8.3) + + vite-plugin-node-stdlib-browser@0.2.1(node-stdlib-browser@1.3.1)(vite@8.0.8(@types/node@24.12.2)(esbuild@0.27.7)(jiti@2.6.1)(sass@1.99.0)(terser@5.46.1)(yaml@2.8.3)): + dependencies: + "@rollup/plugin-inject": 5.0.5 + node-stdlib-browser: 1.3.1 + vite: 8.0.8(@types/node@24.12.2)(esbuild@0.27.7)(jiti@2.6.1)(sass@1.99.0)(terser@5.46.1)(yaml@2.8.3) + transitivePeerDependencies: + - rollup + + vite-plugin-svgr@4.5.0(typescript@5.9.3)(vite@8.0.8(@types/node@24.12.2)(esbuild@0.27.7)(jiti@2.6.1)(sass@1.99.0)(terser@5.46.1)(yaml@2.8.3)): + dependencies: + "@rollup/pluginutils": 5.3.0 + "@svgr/core": 8.1.0(typescript@5.9.3) + "@svgr/plugin-jsx": 8.1.0(@svgr/core@8.1.0(typescript@5.9.3)) + vite: 8.0.8(@types/node@24.12.2)(esbuild@0.27.7)(jiti@2.6.1)(sass@1.99.0)(terser@5.46.1)(yaml@2.8.3) + transitivePeerDependencies: + - rollup + - supports-color + - typescript + + vite@8.0.8(@types/node@24.12.2)(esbuild@0.27.7)(jiti@2.6.1)(sass@1.99.0)(terser@5.46.1)(yaml@2.8.3): + dependencies: + lightningcss: 1.32.0 + picomatch: 4.0.4 + postcss: 8.5.10 + rolldown: 1.0.0-rc.15 + tinyglobby: 0.2.16 + optionalDependencies: + "@types/node": 24.12.2 + esbuild: 0.27.7 + fsevents: 2.3.3 + jiti: 2.6.1 + sass: 1.99.0 + terser: 5.46.1 + yaml: 2.8.3 + + vitest-axe@1.0.0-pre.5(vitest@4.1.4(@types/node@24.12.2)(@vitest/coverage-v8@4.1.4)(jsdom@26.1.0)(vite@8.0.8(@types/node@24.12.2)(esbuild@0.27.7)(jiti@2.6.1)(sass@1.99.0)(terser@5.46.1)(yaml@2.8.3))): + dependencies: + "@vitest/pretty-format": 3.2.4 + axe-core: 4.11.3 + chalk: 5.6.2 + lodash-es: 4.18.1 + vitest: 4.1.4(@types/node@24.12.2)(@vitest/coverage-v8@4.1.4)(jsdom@26.1.0)(vite@8.0.8(@types/node@24.12.2)(esbuild@0.27.7)(jiti@2.6.1)(sass@1.99.0)(terser@5.46.1)(yaml@2.8.3)) + + vitest@4.1.4(@types/node@24.12.2)(@vitest/coverage-v8@4.1.4)(jsdom@26.1.0)(vite@8.0.8(@types/node@24.12.2)(esbuild@0.27.7)(jiti@2.6.1)(sass@1.99.0)(terser@5.46.1)(yaml@2.8.3)): + dependencies: + "@vitest/expect": 4.1.4 + "@vitest/mocker": 4.1.4(vite@8.0.8(@types/node@24.12.2)(esbuild@0.27.7)(jiti@2.6.1)(sass@1.99.0)(terser@5.46.1)(yaml@2.8.3)) + "@vitest/pretty-format": 4.1.4 + "@vitest/runner": 4.1.4 + "@vitest/snapshot": 4.1.4 + "@vitest/spy": 4.1.4 + "@vitest/utils": 4.1.4 + es-module-lexer: 2.0.0 + expect-type: 1.3.0 + magic-string: 0.30.21 + obug: 2.1.1 + pathe: 2.0.3 + picomatch: 4.0.4 + std-env: 4.1.0 + tinybench: 2.9.0 + tinyexec: 1.1.1 + tinyglobby: 0.2.16 + tinyrainbow: 3.1.0 + vite: 8.0.8(@types/node@24.12.2)(esbuild@0.27.7)(jiti@2.6.1)(sass@1.99.0)(terser@5.46.1)(yaml@2.8.3) + why-is-node-running: 2.3.0 + optionalDependencies: + "@types/node": 24.12.2 + "@vitest/coverage-v8": 4.1.4(vitest@4.1.4) + jsdom: 26.1.0 + transitivePeerDependencies: + - msw + + vm-browserify@1.1.2: {} + + void-elements@3.1.0: {} + + w3c-xmlserializer@5.0.0: + dependencies: + xml-name-validator: 5.0.0 + + walk-sync@2.2.0: + dependencies: + "@types/minimatch": 3.0.5 + ensure-posix-path: 1.1.1 + matcher-collection: 2.0.1 + minimatch: 10.2.5 + + walk-up-path@4.0.0: {} + + web-vitals@4.2.4: {} + + webidl-conversions@3.0.1: {} + + webidl-conversions@7.0.0: {} + + webpack-sources@3.3.4: {} + + webpack-virtual-modules@0.5.0: {} + + webpack-virtual-modules@0.6.2: {} + + webrtc-adapter@9.0.4: + dependencies: + sdp: 3.2.2 + + whatwg-encoding@3.1.1: + dependencies: + iconv-lite: 0.6.3 + + whatwg-mimetype@4.0.0: {} + + whatwg-url@14.2.0: + dependencies: + tr46: 5.1.1 + webidl-conversions: 7.0.0 + + whatwg-url@5.0.0: + dependencies: + tr46: 0.0.3 + webidl-conversions: 3.0.1 + + which-boxed-primitive@1.1.1: + dependencies: + is-bigint: 1.1.0 + is-boolean-object: 1.2.2 + is-number-object: 1.1.1 + is-string: 1.1.1 + is-symbol: 1.1.1 + + which-builtin-type@1.2.1: + dependencies: + call-bound: 1.0.4 + function.prototype.name: 1.1.8 + has-tostringtag: 1.0.2 + is-async-function: 2.1.1 + is-date-object: 1.1.0 + is-finalizationregistry: 1.1.1 + is-generator-function: 1.1.2 + is-regex: 1.2.1 + is-weakref: 1.1.1 + isarray: 2.0.5 + which-boxed-primitive: 1.1.1 + which-collection: 1.0.2 + which-typed-array: 1.1.20 + + which-collection@1.0.2: + dependencies: + is-map: 2.0.3 + is-set: 2.0.3 + is-weakmap: 2.0.2 + is-weakset: 2.0.4 + + which-module@2.0.1: {} + + which-typed-array@1.1.20: + dependencies: + available-typed-arrays: 1.0.7 + call-bind: 1.0.9 + call-bound: 1.0.4 + for-each: 0.3.5 + get-proto: 1.0.1 + gopd: 1.2.0 + has-tostringtag: 1.0.2 + + which@2.0.2: + dependencies: + isexe: 2.0.0 + + why-is-node-running@2.3.0: + dependencies: + siginfo: 2.0.0 + stackback: 0.0.2 + + word-wrap@1.2.5: {} + + wrap-ansi@6.2.0: + dependencies: + ansi-styles: 4.3.0 + string-width: 4.2.3 + strip-ansi: 6.0.1 + + wrap-ansi@7.0.0: + dependencies: + ansi-styles: 4.3.0 + string-width: 4.2.3 + strip-ansi: 6.0.1 + + wrap-ansi@8.1.0: + dependencies: + ansi-styles: 6.2.3 + string-width: 5.1.2 + strip-ansi: 7.2.0 + + wrappy@1.0.2: {} + + ws@8.20.0: {} + + wsl-utils@0.1.0: + dependencies: + is-wsl: 3.1.1 + + xml-name-validator@5.0.0: {} + + xmlchars@2.2.0: {} + + xtend@4.0.2: {} + + y18n@4.0.3: {} + + y18n@5.0.8: {} + + yallist@3.1.1: {} + + yaml@2.8.3: {} + + yargs-parser@18.1.3: + dependencies: + camelcase: 5.3.1 + decamelize: 1.2.0 + + yargs-parser@21.1.1: {} + + yargs@15.4.1: + dependencies: + cliui: 6.0.0 + decamelize: 1.2.0 + find-up: 4.1.0 + get-caller-file: 2.0.5 + require-directory: 2.1.1 + require-main-filename: 2.0.0 + set-blocking: 2.0.0 + string-width: 4.2.3 + which-module: 2.0.1 + y18n: 4.0.3 + yargs-parser: 18.1.3 + + yargs@17.7.2: + dependencies: + cliui: 8.0.1 + escalade: 3.2.0 + get-caller-file: 2.0.5 + require-directory: 2.1.1 + string-width: 4.2.3 + y18n: 5.0.8 + yargs-parser: 21.1.1 + + yocto-queue@0.1.0: {} + + zod@3.25.76: {} + + zod@4.3.6: {} diff --git a/scripts/dockerbuild.sh b/scripts/dockerbuild.sh index ceabde8e2..5cf4c71ef 100755 --- a/scripts/dockerbuild.sh +++ b/scripts/dockerbuild.sh @@ -5,5 +5,5 @@ set -ex export VITE_APP_VERSION=$(git describe --tags --abbrev=0) corepack enable -yarn install -yarn run build +pnpm install +pnpm run build diff --git a/scripts/playwright-webserver-command.sh b/scripts/playwright-webserver-command.sh index 8c00909b4..8cea50e34 100755 --- a/scripts/playwright-webserver-command.sh +++ b/scripts/playwright-webserver-command.sh @@ -1,10 +1,10 @@ #!/bin/sh if [ -n "$USE_DOCKER" ]; then set -ex - yarn build + pnpm build docker build -t element-call:testing . exec docker run --rm --name element-call-testing -p 8080:8080 -v ./config/config.devenv.json:/app/config.json:ro,Z element-call:testing else cp config/config.devenv.json public/config.json - exec yarn dev + exec pnpm dev fi diff --git a/yarn.lock b/yarn.lock deleted file mode 100644 index 484f052ab..000000000 --- a/yarn.lock +++ /dev/null @@ -1,16635 +0,0 @@ -# This file is generated by running "yarn install" inside your project. -# Manual changes might be lost - proceed with caution! - -__metadata: - version: 8 - cacheKey: 10c0 - -"@actions/core@npm:^1.10.1": - version: 1.11.1 - resolution: "@actions/core@npm:1.11.1" - dependencies: - "@actions/exec": "npm:^1.1.1" - "@actions/http-client": "npm:^2.0.1" - checksum: 10c0/9aa30b397d8d0dbc74e69fe46b23fb105cab989beb420c57eacbfc51c6804abe8da0f46973ca9f639d532ea4c096d0f4d37da0223fbe94f304fa3c5f53537c30 - languageName: node - linkType: hard - -"@actions/exec@npm:^1.1.1": - version: 1.1.1 - resolution: "@actions/exec@npm:1.1.1" - dependencies: - "@actions/io": "npm:^1.0.1" - checksum: 10c0/4a09f6bdbe50ce68b5cf8a7254d176230d6a74bccf6ecc3857feee209a8c950ba9adec87cc5ecceb04110182d1c17117234e45557d72fde6229b7fd3a395322a - languageName: node - linkType: hard - -"@actions/github@npm:^6.0.0": - version: 6.0.0 - resolution: "@actions/github@npm:6.0.0" - dependencies: - "@actions/http-client": "npm:^2.2.0" - "@octokit/core": "npm:^5.0.1" - "@octokit/plugin-paginate-rest": "npm:^9.0.0" - "@octokit/plugin-rest-endpoint-methods": "npm:^10.0.0" - checksum: 10c0/6f86f564e6ec5873c69ff23bed308cef5f964dbdb559c5415c1ba479517bf18352713a2a757c27f8f67a3d675fdd78446cf142b27762489f697edf9c58e72378 - languageName: node - linkType: hard - -"@actions/http-client@npm:^2.0.1, @actions/http-client@npm:^2.2.0": - version: 2.2.3 - resolution: "@actions/http-client@npm:2.2.3" - dependencies: - tunnel: "npm:^0.0.6" - undici: "npm:^5.25.4" - checksum: 10c0/13141b66a42aa4afd8c50f7479e13a5cdb5084ccb3c73ec48894b8029743389a3d2bf8cdc18e23fb70cd33995740526dd308815613907571e897c3aa1e5eada6 - languageName: node - linkType: hard - -"@actions/io@npm:^1.0.1": - version: 1.1.3 - resolution: "@actions/io@npm:1.1.3" - checksum: 10c0/5b8751918e5bf0bebd923ba917fb1c0e294401e7ff0037f32c92a4efa4215550df1f6633c63fd4efb2bdaae8711e69b9e36925857db1f38935ff62a5c92ec29e - languageName: node - linkType: hard - -"@adobe/css-tools@npm:^4.4.0": - version: 4.4.1 - resolution: "@adobe/css-tools@npm:4.4.1" - checksum: 10c0/1a68ad9af490f45fce7b6e50dd2d8ac0c546d74431649c0d42ee4ceb1a9fa057fae0a7ef1e148effa12d84ec00ed71869ebfe0fb1dcdcc80bfcb6048c12abcc0 - languageName: node - linkType: hard - -"@asamuzakjp/css-color@npm:^2.8.2": - version: 2.8.2 - resolution: "@asamuzakjp/css-color@npm:2.8.2" - dependencies: - "@csstools/css-calc": "npm:^2.1.1" - "@csstools/css-color-parser": "npm:^3.0.7" - "@csstools/css-parser-algorithms": "npm:^3.0.4" - "@csstools/css-tokenizer": "npm:^3.0.3" - lru-cache: "npm:^11.0.2" - checksum: 10c0/352b91ca7741876e459cd3cb350a969e842da1e532577157d38365a6da89b7d6e6944249489366ee61b8a225ede1b521e7ab305b70ad4c688b01404061eecca8 - languageName: node - linkType: hard - -"@babel/code-frame@npm:^7.0.0, @babel/code-frame@npm:^7.25.9, @babel/code-frame@npm:^7.26.2": - version: 7.26.2 - resolution: "@babel/code-frame@npm:7.26.2" - dependencies: - "@babel/helper-validator-identifier": "npm:^7.25.9" - js-tokens: "npm:^4.0.0" - picocolors: "npm:^1.0.0" - checksum: 10c0/7d79621a6849183c415486af99b1a20b84737e8c11cd55b6544f688c51ce1fd710e6d869c3dd21232023da272a79b91efb3e83b5bc2dc65c1187c5fcd1b72ea8 - languageName: node - linkType: hard - -"@babel/code-frame@npm:^7.10.4": - version: 7.24.7 - resolution: "@babel/code-frame@npm:7.24.7" - dependencies: - "@babel/highlight": "npm:^7.24.7" - picocolors: "npm:^1.0.0" - checksum: 10c0/ab0af539473a9f5aeaac7047e377cb4f4edd255a81d84a76058595f8540784cc3fbe8acf73f1e073981104562490aabfb23008cd66dc677a456a4ed5390fdde6 - languageName: node - linkType: hard - -"@babel/code-frame@npm:^7.27.1": - version: 7.27.1 - resolution: "@babel/code-frame@npm:7.27.1" - dependencies: - "@babel/helper-validator-identifier": "npm:^7.27.1" - js-tokens: "npm:^4.0.0" - picocolors: "npm:^1.1.1" - checksum: 10c0/5dd9a18baa5fce4741ba729acc3a3272c49c25cb8736c4b18e113099520e7ef7b545a4096a26d600e4416157e63e87d66db46aa3fbf0a5f2286da2705c12da00 - languageName: node - linkType: hard - -"@babel/code-frame@npm:^7.28.6, @babel/code-frame@npm:^7.29.0": - version: 7.29.0 - resolution: "@babel/code-frame@npm:7.29.0" - dependencies: - "@babel/helper-validator-identifier": "npm:^7.28.5" - js-tokens: "npm:^4.0.0" - picocolors: "npm:^1.1.1" - checksum: 10c0/d34cc504e7765dfb576a663d97067afb614525806b5cad1a5cc1a7183b916fec8ff57fa233585e3926fd5a9e6b31aae6df91aa81ae9775fb7a28f658d3346f0d - languageName: node - linkType: hard - -"@babel/compat-data@npm:^7.27.2": - version: 7.27.3 - resolution: "@babel/compat-data@npm:7.27.3" - checksum: 10c0/5736c42c98e38c788c1c53e9bc7c1aa42cb3dd907f3fa2c26c5a123bc957eb3df69acb2f4e96c2f208eb164410d5beddd8b4249353a7ef6e5d6e6eb4292c3587 - languageName: node - linkType: hard - -"@babel/compat-data@npm:^7.28.6, @babel/compat-data@npm:^7.29.0": - version: 7.29.0 - resolution: "@babel/compat-data@npm:7.29.0" - checksum: 10c0/08f348554989d23aa801bf1405aa34b15e841c0d52d79da7e524285c77a5f9d298e70e11d91cc578d8e2c9542efc586d50c5f5cf8e1915b254a9dcf786913a94 - languageName: node - linkType: hard - -"@babel/core@npm:^7.16.5, @babel/core@npm:^7.18.5, @babel/core@npm:^7.21.3, @babel/core@npm:^7.28.0": - version: 7.29.0 - resolution: "@babel/core@npm:7.29.0" - dependencies: - "@babel/code-frame": "npm:^7.29.0" - "@babel/generator": "npm:^7.29.0" - "@babel/helper-compilation-targets": "npm:^7.28.6" - "@babel/helper-module-transforms": "npm:^7.28.6" - "@babel/helpers": "npm:^7.28.6" - "@babel/parser": "npm:^7.29.0" - "@babel/template": "npm:^7.28.6" - "@babel/traverse": "npm:^7.29.0" - "@babel/types": "npm:^7.29.0" - "@jridgewell/remapping": "npm:^2.3.5" - convert-source-map: "npm:^2.0.0" - debug: "npm:^4.1.0" - gensync: "npm:^1.0.0-beta.2" - json5: "npm:^2.2.3" - semver: "npm:^6.3.1" - checksum: 10c0/5127d2e8e842ae409e11bcbb5c2dff9874abf5415e8026925af7308e903f4f43397341467a130490d1a39884f461bc2b67f3063bce0be44340db89687fd852aa - languageName: node - linkType: hard - -"@babel/generator@npm:^7.25.9": - version: 7.26.3 - resolution: "@babel/generator@npm:7.26.3" - dependencies: - "@babel/parser": "npm:^7.26.3" - "@babel/types": "npm:^7.26.3" - "@jridgewell/gen-mapping": "npm:^0.3.5" - "@jridgewell/trace-mapping": "npm:^0.3.25" - jsesc: "npm:^3.0.2" - checksum: 10c0/54f260558e3e4ec8942da3cde607c35349bb983c3a7c5121243f96893fba3e8cd62e1f1773b2051f936f8c8a10987b758d5c7d76dbf2784e95bb63ab4843fa00 - languageName: node - linkType: hard - -"@babel/generator@npm:^7.27.3": - version: 7.27.3 - resolution: "@babel/generator@npm:7.27.3" - dependencies: - "@babel/parser": "npm:^7.27.3" - "@babel/types": "npm:^7.27.3" - "@jridgewell/gen-mapping": "npm:^0.3.5" - "@jridgewell/trace-mapping": "npm:^0.3.25" - jsesc: "npm:^3.0.2" - checksum: 10c0/341622e17c61d008fc746b655ab95ef7febb543df8efb4148f57cf06e60ade1abe091ed7d6811df17b064d04d64f69bb7f35ab0654137116d55c54a73145a61a - languageName: node - linkType: hard - -"@babel/generator@npm:^7.28.5": - version: 7.28.5 - resolution: "@babel/generator@npm:7.28.5" - dependencies: - "@babel/parser": "npm:^7.28.5" - "@babel/types": "npm:^7.28.5" - "@jridgewell/gen-mapping": "npm:^0.3.12" - "@jridgewell/trace-mapping": "npm:^0.3.28" - jsesc: "npm:^3.0.2" - checksum: 10c0/9f219fe1d5431b6919f1a5c60db8d5d34fe546c0d8f5a8511b32f847569234ffc8032beb9e7404649a143f54e15224ecb53a3d11b6bb85c3203e573d91fca752 - languageName: node - linkType: hard - -"@babel/generator@npm:^7.29.0": - version: 7.29.1 - resolution: "@babel/generator@npm:7.29.1" - dependencies: - "@babel/parser": "npm:^7.29.0" - "@babel/types": "npm:^7.29.0" - "@jridgewell/gen-mapping": "npm:^0.3.12" - "@jridgewell/trace-mapping": "npm:^0.3.28" - jsesc: "npm:^3.0.2" - checksum: 10c0/349086e6876258ef3fb2823030fee0f6c0eb9c3ebe35fc572e16997f8c030d765f636ddc6299edae63e760ea6658f8ee9a2edfa6d6b24c9a80c917916b973551 - languageName: node - linkType: hard - -"@babel/helper-annotate-as-pure@npm:^7.25.9": - version: 7.25.9 - resolution: "@babel/helper-annotate-as-pure@npm:7.25.9" - dependencies: - "@babel/types": "npm:^7.25.9" - checksum: 10c0/095b6ba50489d797733abebc4596a81918316a99e3632755c9f02508882912b00c2ae5e468532a25a5c2108d109ddbe9b7da78333ee7cc13817fc50c00cf06fe - languageName: node - linkType: hard - -"@babel/helper-annotate-as-pure@npm:^7.27.1, @babel/helper-annotate-as-pure@npm:^7.27.3": - version: 7.27.3 - resolution: "@babel/helper-annotate-as-pure@npm:7.27.3" - dependencies: - "@babel/types": "npm:^7.27.3" - checksum: 10c0/94996ce0a05b7229f956033e6dcd69393db2b0886d0db6aff41e704390402b8cdcca11f61449cb4f86cfd9e61b5ad3a73e4fa661eeed7846b125bd1c33dbc633 - languageName: node - linkType: hard - -"@babel/helper-compilation-targets@npm:^7.27.1": - version: 7.27.2 - resolution: "@babel/helper-compilation-targets@npm:7.27.2" - dependencies: - "@babel/compat-data": "npm:^7.27.2" - "@babel/helper-validator-option": "npm:^7.27.1" - browserslist: "npm:^4.24.0" - lru-cache: "npm:^5.1.1" - semver: "npm:^6.3.1" - checksum: 10c0/f338fa00dcfea931804a7c55d1a1c81b6f0a09787e528ec580d5c21b3ecb3913f6cb0f361368973ce953b824d910d3ac3e8a8ee15192710d3563826447193ad1 - languageName: node - linkType: hard - -"@babel/helper-compilation-targets@npm:^7.28.6": - version: 7.28.6 - resolution: "@babel/helper-compilation-targets@npm:7.28.6" - dependencies: - "@babel/compat-data": "npm:^7.28.6" - "@babel/helper-validator-option": "npm:^7.27.1" - browserslist: "npm:^4.24.0" - lru-cache: "npm:^5.1.1" - semver: "npm:^6.3.1" - checksum: 10c0/3fcdf3b1b857a1578e99d20508859dbd3f22f3c87b8a0f3dc540627b4be539bae7f6e61e49d931542fe5b557545347272bbdacd7f58a5c77025a18b745593a50 - languageName: node - linkType: hard - -"@babel/helper-create-class-features-plugin@npm:^7.28.5": - version: 7.28.5 - resolution: "@babel/helper-create-class-features-plugin@npm:7.28.5" - dependencies: - "@babel/helper-annotate-as-pure": "npm:^7.27.3" - "@babel/helper-member-expression-to-functions": "npm:^7.28.5" - "@babel/helper-optimise-call-expression": "npm:^7.27.1" - "@babel/helper-replace-supers": "npm:^7.27.1" - "@babel/helper-skip-transparent-expression-wrappers": "npm:^7.27.1" - "@babel/traverse": "npm:^7.28.5" - semver: "npm:^6.3.1" - peerDependencies: - "@babel/core": ^7.0.0 - checksum: 10c0/786a6514efcf4514aaad85beed419b9184d059f4c9a9a95108f320142764999827252a851f7071de19f29424d369616573ecbaa347f1ce23fb12fc6827d9ff56 - languageName: node - linkType: hard - -"@babel/helper-create-class-features-plugin@npm:^7.28.6": - version: 7.28.6 - resolution: "@babel/helper-create-class-features-plugin@npm:7.28.6" - dependencies: - "@babel/helper-annotate-as-pure": "npm:^7.27.3" - "@babel/helper-member-expression-to-functions": "npm:^7.28.5" - "@babel/helper-optimise-call-expression": "npm:^7.27.1" - "@babel/helper-replace-supers": "npm:^7.28.6" - "@babel/helper-skip-transparent-expression-wrappers": "npm:^7.27.1" - "@babel/traverse": "npm:^7.28.6" - semver: "npm:^6.3.1" - peerDependencies: - "@babel/core": ^7.0.0 - checksum: 10c0/0b62b46717891f4366006b88c9b7f277980d4f578c4c3789b7a4f5a2e09e121de4cda9a414ab403986745cd3ad1af3fe2d948c9f78ab80d4dc085afc9602af50 - languageName: node - linkType: hard - -"@babel/helper-create-regexp-features-plugin@npm:^7.18.6": - version: 7.26.3 - resolution: "@babel/helper-create-regexp-features-plugin@npm:7.26.3" - dependencies: - "@babel/helper-annotate-as-pure": "npm:^7.25.9" - regexpu-core: "npm:^6.2.0" - semver: "npm:^6.3.1" - peerDependencies: - "@babel/core": ^7.0.0 - checksum: 10c0/266f30b99af621559467ed67634cb653408a9262930c0627c3d17691a9d477329fb4dabe4b1785cbf0490e892513d247836674271842d6a8da49fd0afae7d435 - languageName: node - linkType: hard - -"@babel/helper-create-regexp-features-plugin@npm:^7.27.1": - version: 7.27.1 - resolution: "@babel/helper-create-regexp-features-plugin@npm:7.27.1" - dependencies: - "@babel/helper-annotate-as-pure": "npm:^7.27.1" - regexpu-core: "npm:^6.2.0" - semver: "npm:^6.3.1" - peerDependencies: - "@babel/core": ^7.0.0 - checksum: 10c0/591fe8bd3bb39679cc49588889b83bd628d8c4b99c55bafa81e80b1e605a348b64da955e3fd891c4ba3f36fd015367ba2eadea22af6a7de1610fbb5bcc2d3df0 - languageName: node - linkType: hard - -"@babel/helper-create-regexp-features-plugin@npm:^7.28.5": - version: 7.28.5 - resolution: "@babel/helper-create-regexp-features-plugin@npm:7.28.5" - dependencies: - "@babel/helper-annotate-as-pure": "npm:^7.27.3" - regexpu-core: "npm:^6.3.1" - semver: "npm:^6.3.1" - peerDependencies: - "@babel/core": ^7.0.0 - checksum: 10c0/7af3d604cadecdb2b0d2cedd696507f02a53a58be0523281c2d6766211443b55161dde1e6c0d96ab16ddfd82a2607a2f792390caa24797e9733631f8aa86859f - languageName: node - linkType: hard - -"@babel/helper-define-polyfill-provider@npm:^0.6.6": - version: 0.6.6 - resolution: "@babel/helper-define-polyfill-provider@npm:0.6.6" - dependencies: - "@babel/helper-compilation-targets": "npm:^7.28.6" - "@babel/helper-plugin-utils": "npm:^7.28.6" - debug: "npm:^4.4.3" - lodash.debounce: "npm:^4.0.8" - resolve: "npm:^1.22.11" - peerDependencies: - "@babel/core": ^7.4.0 || ^8.0.0-0 <8.0.0 - checksum: 10c0/1293d6f54d4ebb10c9e947e54de1aaa23b00233e19aca9790072f1893bf143af01442613f7b413300be7016d8e41b550af77acab28e7fa5fb796b2a175c528a1 - languageName: node - linkType: hard - -"@babel/helper-globals@npm:^7.28.0": - version: 7.28.0 - resolution: "@babel/helper-globals@npm:7.28.0" - checksum: 10c0/5a0cd0c0e8c764b5f27f2095e4243e8af6fa145daea2b41b53c0c1414fe6ff139e3640f4e2207ae2b3d2153a1abd346f901c26c290ee7cb3881dd922d4ee9232 - languageName: node - linkType: hard - -"@babel/helper-member-expression-to-functions@npm:^7.27.1": - version: 7.27.1 - resolution: "@babel/helper-member-expression-to-functions@npm:7.27.1" - dependencies: - "@babel/traverse": "npm:^7.27.1" - "@babel/types": "npm:^7.27.1" - checksum: 10c0/5762ad009b6a3d8b0e6e79ff6011b3b8fdda0fefad56cfa8bfbe6aa02d5a8a8a9680a45748fe3ac47e735a03d2d88c0a676e3f9f59f20ae9fadcc8d51ccd5a53 - languageName: node - linkType: hard - -"@babel/helper-member-expression-to-functions@npm:^7.28.5": - version: 7.28.5 - resolution: "@babel/helper-member-expression-to-functions@npm:7.28.5" - dependencies: - "@babel/traverse": "npm:^7.28.5" - "@babel/types": "npm:^7.28.5" - checksum: 10c0/4e6e05fbf4dffd0bc3e55e28fcaab008850be6de5a7013994ce874ec2beb90619cda4744b11607a60f8aae0227694502908add6188ceb1b5223596e765b44814 - languageName: node - linkType: hard - -"@babel/helper-module-imports@npm:^7.27.1": - version: 7.27.1 - resolution: "@babel/helper-module-imports@npm:7.27.1" - dependencies: - "@babel/traverse": "npm:^7.27.1" - "@babel/types": "npm:^7.27.1" - checksum: 10c0/e00aace096e4e29290ff8648455c2bc4ed982f0d61dbf2db1b5e750b9b98f318bf5788d75a4f974c151bd318fd549e81dbcab595f46b14b81c12eda3023f51e8 - languageName: node - linkType: hard - -"@babel/helper-module-imports@npm:^7.28.6": - version: 7.28.6 - resolution: "@babel/helper-module-imports@npm:7.28.6" - dependencies: - "@babel/traverse": "npm:^7.28.6" - "@babel/types": "npm:^7.28.6" - checksum: 10c0/b49d8d8f204d9dbfd5ac70c54e533e5269afb3cea966a9d976722b13e9922cc773a653405f53c89acb247d5aebdae4681d631a3ae3df77ec046b58da76eda2ac - languageName: node - linkType: hard - -"@babel/helper-module-transforms@npm:^7.27.1": - version: 7.27.3 - resolution: "@babel/helper-module-transforms@npm:7.27.3" - dependencies: - "@babel/helper-module-imports": "npm:^7.27.1" - "@babel/helper-validator-identifier": "npm:^7.27.1" - "@babel/traverse": "npm:^7.27.3" - peerDependencies: - "@babel/core": ^7.0.0 - checksum: 10c0/fccb4f512a13b4c069af51e1b56b20f54024bcf1591e31e978a30f3502567f34f90a80da6a19a6148c249216292a8074a0121f9e52602510ef0f32dbce95ca01 - languageName: node - linkType: hard - -"@babel/helper-module-transforms@npm:^7.28.6": - version: 7.28.6 - resolution: "@babel/helper-module-transforms@npm:7.28.6" - dependencies: - "@babel/helper-module-imports": "npm:^7.28.6" - "@babel/helper-validator-identifier": "npm:^7.28.5" - "@babel/traverse": "npm:^7.28.6" - peerDependencies: - "@babel/core": ^7.0.0 - checksum: 10c0/6f03e14fc30b287ce0b839474b5f271e72837d0cafe6b172d759184d998fbee3903a035e81e07c2c596449e504f453463d58baa65b6f40a37ded5bec74620b2b - languageName: node - linkType: hard - -"@babel/helper-optimise-call-expression@npm:^7.27.1": - version: 7.27.1 - resolution: "@babel/helper-optimise-call-expression@npm:7.27.1" - dependencies: - "@babel/types": "npm:^7.27.1" - checksum: 10c0/6b861e7fcf6031b9c9fc2de3cd6c005e94a459d6caf3621d93346b52774925800ca29d4f64595a5ceacf4d161eb0d27649ae385110ed69491d9776686fa488e6 - languageName: node - linkType: hard - -"@babel/helper-plugin-utils@npm:^7.0.0, @babel/helper-plugin-utils@npm:^7.18.6": - version: 7.26.5 - resolution: "@babel/helper-plugin-utils@npm:7.26.5" - checksum: 10c0/cdaba71d4b891aa6a8dfbe5bac2f94effb13e5fa4c2c487667fdbaa04eae059b78b28d85a885071f45f7205aeb56d16759e1bed9c118b94b16e4720ef1ab0f65 - languageName: node - linkType: hard - -"@babel/helper-plugin-utils@npm:^7.27.1": - version: 7.27.1 - resolution: "@babel/helper-plugin-utils@npm:7.27.1" - checksum: 10c0/94cf22c81a0c11a09b197b41ab488d416ff62254ce13c57e62912c85700dc2e99e555225787a4099ff6bae7a1812d622c80fbaeda824b79baa10a6c5ac4cf69b - languageName: node - linkType: hard - -"@babel/helper-plugin-utils@npm:^7.28.6": - version: 7.28.6 - resolution: "@babel/helper-plugin-utils@npm:7.28.6" - checksum: 10c0/3f5f8acc152fdbb69a84b8624145ff4f9b9f6e776cb989f9f968f8606eb7185c5c3cfcf3ba08534e37e1e0e1c118ac67080610333f56baa4f7376c99b5f1143d - languageName: node - linkType: hard - -"@babel/helper-remap-async-to-generator@npm:^7.27.1": - version: 7.27.1 - resolution: "@babel/helper-remap-async-to-generator@npm:7.27.1" - dependencies: - "@babel/helper-annotate-as-pure": "npm:^7.27.1" - "@babel/helper-wrap-function": "npm:^7.27.1" - "@babel/traverse": "npm:^7.27.1" - peerDependencies: - "@babel/core": ^7.0.0 - checksum: 10c0/5ba6258f4bb57c7c9fa76b55f416b2d18c867b48c1af4f9f2f7cd7cc933fe6da7514811d08ceb4972f1493be46f4b69c40282b811d1397403febae13c2ec57b5 - languageName: node - linkType: hard - -"@babel/helper-replace-supers@npm:^7.27.1": - version: 7.27.1 - resolution: "@babel/helper-replace-supers@npm:7.27.1" - dependencies: - "@babel/helper-member-expression-to-functions": "npm:^7.27.1" - "@babel/helper-optimise-call-expression": "npm:^7.27.1" - "@babel/traverse": "npm:^7.27.1" - peerDependencies: - "@babel/core": ^7.0.0 - checksum: 10c0/4f2eaaf5fcc196580221a7ccd0f8873447b5d52745ad4096418f6101a1d2e712e9f93722c9a32bc9769a1dc197e001f60d6f5438d4dfde4b9c6a9e4df719354c - languageName: node - linkType: hard - -"@babel/helper-replace-supers@npm:^7.28.6": - version: 7.28.6 - resolution: "@babel/helper-replace-supers@npm:7.28.6" - dependencies: - "@babel/helper-member-expression-to-functions": "npm:^7.28.5" - "@babel/helper-optimise-call-expression": "npm:^7.27.1" - "@babel/traverse": "npm:^7.28.6" - peerDependencies: - "@babel/core": ^7.0.0 - checksum: 10c0/04663c6389551b99b8c3e7ba4e2638b8ca2a156418c26771516124c53083aa8e74b6a45abe5dd46360af79709a0e9c6b72c076d0eab9efecdd5aaf836e79d8d5 - languageName: node - linkType: hard - -"@babel/helper-skip-transparent-expression-wrappers@npm:^7.27.1": - version: 7.27.1 - resolution: "@babel/helper-skip-transparent-expression-wrappers@npm:7.27.1" - dependencies: - "@babel/traverse": "npm:^7.27.1" - "@babel/types": "npm:^7.27.1" - checksum: 10c0/f625013bcdea422c470223a2614e90d2c1cc9d832e97f32ca1b4f82b34bb4aa67c3904cb4b116375d3b5b753acfb3951ed50835a1e832e7225295c7b0c24dff7 - languageName: node - linkType: hard - -"@babel/helper-string-parser@npm:^7.25.9": - version: 7.25.9 - resolution: "@babel/helper-string-parser@npm:7.25.9" - checksum: 10c0/7244b45d8e65f6b4338a6a68a8556f2cb161b782343e97281a5f2b9b93e420cad0d9f5773a59d79f61d0c448913d06f6a2358a87f2e203cf112e3c5b53522ee6 - languageName: node - linkType: hard - -"@babel/helper-string-parser@npm:^7.27.1": - version: 7.27.1 - resolution: "@babel/helper-string-parser@npm:7.27.1" - checksum: 10c0/8bda3448e07b5583727c103560bcf9c4c24b3c1051a4c516d4050ef69df37bb9a4734a585fe12725b8c2763de0a265aa1e909b485a4e3270b7cfd3e4dbe4b602 - languageName: node - linkType: hard - -"@babel/helper-validator-identifier@npm:^7.24.7, @babel/helper-validator-identifier@npm:^7.25.9": - version: 7.25.9 - resolution: "@babel/helper-validator-identifier@npm:7.25.9" - checksum: 10c0/4fc6f830177b7b7e887ad3277ddb3b91d81e6c4a24151540d9d1023e8dc6b1c0505f0f0628ae653601eb4388a8db45c1c14b2c07a9173837aef7e4116456259d - languageName: node - linkType: hard - -"@babel/helper-validator-identifier@npm:^7.27.1": - version: 7.27.1 - resolution: "@babel/helper-validator-identifier@npm:7.27.1" - checksum: 10c0/c558f11c4871d526498e49d07a84752d1800bf72ac0d3dad100309a2eaba24efbf56ea59af5137ff15e3a00280ebe588560534b0e894a4750f8b1411d8f78b84 - languageName: node - linkType: hard - -"@babel/helper-validator-identifier@npm:^7.28.5": - version: 7.28.5 - resolution: "@babel/helper-validator-identifier@npm:7.28.5" - checksum: 10c0/42aaebed91f739a41f3d80b72752d1f95fd7c72394e8e4bd7cdd88817e0774d80a432451bcba17c2c642c257c483bf1d409dd4548883429ea9493a3bc4ab0847 - languageName: node - linkType: hard - -"@babel/helper-validator-option@npm:^7.27.1": - version: 7.27.1 - resolution: "@babel/helper-validator-option@npm:7.27.1" - checksum: 10c0/6fec5f006eba40001a20f26b1ef5dbbda377b7b68c8ad518c05baa9af3f396e780bdfded24c4eef95d14bb7b8fd56192a6ed38d5d439b97d10efc5f1a191d148 - languageName: node - linkType: hard - -"@babel/helper-wrap-function@npm:^7.27.1": - version: 7.27.1 - resolution: "@babel/helper-wrap-function@npm:7.27.1" - dependencies: - "@babel/template": "npm:^7.27.1" - "@babel/traverse": "npm:^7.27.1" - "@babel/types": "npm:^7.27.1" - checksum: 10c0/c472f75c0951bc657ab0a117538c7c116566ae7579ed47ac3f572c42dc78bd6f1e18f52ebe80d38300c991c3fcaa06979e2f8864ee919369dabd59072288de30 - languageName: node - linkType: hard - -"@babel/helpers@npm:^7.28.6": - version: 7.28.6 - resolution: "@babel/helpers@npm:7.28.6" - dependencies: - "@babel/template": "npm:^7.28.6" - "@babel/types": "npm:^7.28.6" - checksum: 10c0/c4a779c66396bb0cf619402d92f1610601ff3832db2d3b86b9c9dd10983bf79502270e97ac6d5280cea1b1a37de2f06ecbac561bd2271545270407fbe64027cb - languageName: node - linkType: hard - -"@babel/highlight@npm:^7.24.7": - version: 7.24.7 - resolution: "@babel/highlight@npm:7.24.7" - dependencies: - "@babel/helper-validator-identifier": "npm:^7.24.7" - chalk: "npm:^2.4.2" - js-tokens: "npm:^4.0.0" - picocolors: "npm:^1.0.0" - checksum: 10c0/674334c571d2bb9d1c89bdd87566383f59231e16bcdcf5bb7835babdf03c9ae585ca0887a7b25bdf78f303984af028df52831c7989fecebb5101cc132da9393a - languageName: node - linkType: hard - -"@babel/parser@npm:^7.1.0, @babel/parser@npm:^7.10.3, @babel/parser@npm:^7.20.7": - version: 7.26.2 - resolution: "@babel/parser@npm:7.26.2" - dependencies: - "@babel/types": "npm:^7.26.0" - bin: - parser: ./bin/babel-parser.js - checksum: 10c0/751a743087b3a9172a7599f1421830d44c38f065ef781588d2bfb1c98f9b461719a226feb13c868d7a284783eee120c88ea522593118f2668f46ebfb1105c4d7 - languageName: node - linkType: hard - -"@babel/parser@npm:^7.25.9, @babel/parser@npm:^7.26.9": - version: 7.26.9 - resolution: "@babel/parser@npm:7.26.9" - dependencies: - "@babel/types": "npm:^7.26.9" - bin: - parser: ./bin/babel-parser.js - checksum: 10c0/4b9ef3c9a0d4c328e5e5544f50fe8932c36f8a2c851e7f14a85401487cd3da75cad72c2e1bcec1eac55599a6bbb2fdc091f274c4fcafa6bdd112d4915ff087fc - languageName: node - linkType: hard - -"@babel/parser@npm:^7.26.3": - version: 7.26.5 - resolution: "@babel/parser@npm:7.26.5" - dependencies: - "@babel/types": "npm:^7.26.5" - bin: - parser: ./bin/babel-parser.js - checksum: 10c0/2e77dd99ee028ee3c10fa03517ae1169f2432751adf71315e4dc0d90b61639d51760d622f418f6ac665ae4ea65f8485232a112ea0e76f18e5900225d3d19a61e - languageName: node - linkType: hard - -"@babel/parser@npm:^7.27.2, @babel/parser@npm:^7.27.3": - version: 7.27.3 - resolution: "@babel/parser@npm:7.27.3" - dependencies: - "@babel/types": "npm:^7.27.3" - bin: - parser: ./bin/babel-parser.js - checksum: 10c0/d96363c7548710ab9c28649cee752e2d0713ed25bf910923da45d2fbc67fed5bbdfb867274fec7d72437f4e910577d27c04e160da52d95f1b63fdf0b19035d26 - languageName: node - linkType: hard - -"@babel/parser@npm:^7.28.5": - version: 7.28.5 - resolution: "@babel/parser@npm:7.28.5" - dependencies: - "@babel/types": "npm:^7.28.5" - bin: - parser: ./bin/babel-parser.js - checksum: 10c0/5bbe48bf2c79594ac02b490a41ffde7ef5aa22a9a88ad6bcc78432a6ba8a9d638d531d868bd1f104633f1f6bba9905746e15185b8276a3756c42b765d131b1ef - languageName: node - linkType: hard - -"@babel/parser@npm:^7.28.6, @babel/parser@npm:^7.29.0": - version: 7.29.0 - resolution: "@babel/parser@npm:7.29.0" - dependencies: - "@babel/types": "npm:^7.29.0" - bin: - parser: ./bin/babel-parser.js - checksum: 10c0/333b2aa761264b91577a74bee86141ef733f9f9f6d4fc52548e4847dc35dfbf821f58c46832c637bfa761a6d9909d6a68f7d1ed59e17e4ffbb958dc510c17b62 - languageName: node - linkType: hard - -"@babel/plugin-bugfix-firefox-class-in-computed-class-key@npm:^7.28.5": - version: 7.28.5 - resolution: "@babel/plugin-bugfix-firefox-class-in-computed-class-key@npm:7.28.5" - dependencies: - "@babel/helper-plugin-utils": "npm:^7.27.1" - "@babel/traverse": "npm:^7.28.5" - peerDependencies: - "@babel/core": ^7.0.0 - checksum: 10c0/844b7c7e9eec6d858262b2f3d5af75d3a6bbd9d3ecc740d95271fbdd84985731674536f5d8ac98f2dc0e8872698b516e406636e4d0cb04b50afe471172095a53 - languageName: node - linkType: hard - -"@babel/plugin-bugfix-safari-class-field-initializer-scope@npm:^7.27.1": - version: 7.27.1 - resolution: "@babel/plugin-bugfix-safari-class-field-initializer-scope@npm:7.27.1" - dependencies: - "@babel/helper-plugin-utils": "npm:^7.27.1" - peerDependencies: - "@babel/core": ^7.0.0 - checksum: 10c0/2cd7a55a856e5e59bbd9484247c092a41e0d9f966778e7019da324d9e0928892d26afc4fbb2ac3d76a3c5a631cd3cf0d72dd2653b44f634f6c663b9e6f80aacd - languageName: node - linkType: hard - -"@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@npm:^7.27.1": - version: 7.27.1 - resolution: "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@npm:7.27.1" - dependencies: - "@babel/helper-plugin-utils": "npm:^7.27.1" - peerDependencies: - "@babel/core": ^7.0.0 - checksum: 10c0/cf29835498c4a25bd470908528919729a0799b2ec94e89004929a5532c94a5e4b1a49bc5d6673a22e5afe05d08465873e14ee3b28c42eb3db489cdf5ca47c680 - languageName: node - linkType: hard - -"@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@npm:^7.27.1": - version: 7.27.1 - resolution: "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@npm:7.27.1" - dependencies: - "@babel/helper-plugin-utils": "npm:^7.27.1" - "@babel/helper-skip-transparent-expression-wrappers": "npm:^7.27.1" - "@babel/plugin-transform-optional-chaining": "npm:^7.27.1" - peerDependencies: - "@babel/core": ^7.13.0 - checksum: 10c0/eddcd056f76e198868cbff883eb148acfade8f0890973ab545295df0c08e39573a72e65372bcc0b0bfadba1b043fe1aea6b0907d0b4889453ac154c404194ebc - languageName: node - linkType: hard - -"@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly@npm:^7.28.6": - version: 7.28.6 - resolution: "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly@npm:7.28.6" - dependencies: - "@babel/helper-plugin-utils": "npm:^7.28.6" - "@babel/traverse": "npm:^7.28.6" - peerDependencies: - "@babel/core": ^7.0.0 - checksum: 10c0/f1a9194e8d1742081def7af748e9249eb5082c25d0ced292720a1f054895f99041c764a05f45af669a2c8898aeb79266058aedb0d3e1038963ad49be8288918a - languageName: node - linkType: hard - -"@babel/plugin-proposal-private-property-in-object@npm:7.21.0-placeholder-for-preset-env.2": - version: 7.21.0-placeholder-for-preset-env.2 - resolution: "@babel/plugin-proposal-private-property-in-object@npm:7.21.0-placeholder-for-preset-env.2" - peerDependencies: - "@babel/core": ^7.0.0-0 - checksum: 10c0/e605e0070da087f6c35579499e65801179a521b6842c15181a1e305c04fded2393f11c1efd09b087be7f8b083d1b75e8f3efcbc1292b4f60d3369e14812cff63 - languageName: node - linkType: hard - -"@babel/plugin-syntax-import-assertions@npm:^7.28.6": - version: 7.28.6 - resolution: "@babel/plugin-syntax-import-assertions@npm:7.28.6" - dependencies: - "@babel/helper-plugin-utils": "npm:^7.28.6" - peerDependencies: - "@babel/core": ^7.0.0-0 - checksum: 10c0/f3b8bdccb9b4d3e3b9226684ca518e055399d05579da97dfe0160a38d65198cfe7dce809e73179d6463a863a040f980de32425a876d88efe4eda933d0d95982c - languageName: node - linkType: hard - -"@babel/plugin-syntax-import-attributes@npm:^7.28.6": - version: 7.28.6 - resolution: "@babel/plugin-syntax-import-attributes@npm:7.28.6" - dependencies: - "@babel/helper-plugin-utils": "npm:^7.28.6" - peerDependencies: - "@babel/core": ^7.0.0-0 - checksum: 10c0/1be160e2c426faa74e5be2e30e39e8d0d8c543063bd5d06cd804f8751b8fbcb82ce824ca7f9ce4b09c003693f6c06a11ce503b7e34d85e1a259631e4c3f72ad2 - languageName: node - linkType: hard - -"@babel/plugin-syntax-jsx@npm:^7.27.1": - version: 7.27.1 - resolution: "@babel/plugin-syntax-jsx@npm:7.27.1" - dependencies: - "@babel/helper-plugin-utils": "npm:^7.27.1" - peerDependencies: - "@babel/core": ^7.0.0-0 - checksum: 10c0/bc5afe6a458d5f0492c02a54ad98c5756a0c13bd6d20609aae65acd560a9e141b0876da5f358dce34ea136f271c1016df58b461184d7ae9c4321e0f98588bc84 - languageName: node - linkType: hard - -"@babel/plugin-syntax-typescript@npm:^7.27.1": - version: 7.27.1 - resolution: "@babel/plugin-syntax-typescript@npm:7.27.1" - dependencies: - "@babel/helper-plugin-utils": "npm:^7.27.1" - peerDependencies: - "@babel/core": ^7.0.0-0 - checksum: 10c0/11589b4c89c66ef02d57bf56c6246267851ec0c361f58929327dc3e070b0dab644be625bbe7fb4c4df30c3634bfdfe31244e1f517be397d2def1487dbbe3c37d - languageName: node - linkType: hard - -"@babel/plugin-syntax-unicode-sets-regex@npm:^7.18.6": - version: 7.18.6 - resolution: "@babel/plugin-syntax-unicode-sets-regex@npm:7.18.6" - dependencies: - "@babel/helper-create-regexp-features-plugin": "npm:^7.18.6" - "@babel/helper-plugin-utils": "npm:^7.18.6" - peerDependencies: - "@babel/core": ^7.0.0 - checksum: 10c0/9144e5b02a211a4fb9a0ce91063f94fbe1004e80bde3485a0910c9f14897cf83fabd8c21267907cff25db8e224858178df0517f14333cfcf3380ad9a4139cb50 - languageName: node - linkType: hard - -"@babel/plugin-transform-arrow-functions@npm:^7.27.1": - version: 7.27.1 - resolution: "@babel/plugin-transform-arrow-functions@npm:7.27.1" - dependencies: - "@babel/helper-plugin-utils": "npm:^7.27.1" - peerDependencies: - "@babel/core": ^7.0.0-0 - checksum: 10c0/19abd7a7d11eef58c9340408a4c2594503f6c4eaea1baa7b0e5fbdda89df097e50663edb3448ad2300170b39efca98a75e5767af05cad3b0facb4944326896a3 - languageName: node - linkType: hard - -"@babel/plugin-transform-async-generator-functions@npm:^7.29.0": - version: 7.29.0 - resolution: "@babel/plugin-transform-async-generator-functions@npm:7.29.0" - dependencies: - "@babel/helper-plugin-utils": "npm:^7.28.6" - "@babel/helper-remap-async-to-generator": "npm:^7.27.1" - "@babel/traverse": "npm:^7.29.0" - peerDependencies: - "@babel/core": ^7.0.0-0 - checksum: 10c0/4080fc5e7dad7761bfebbb4fbe06bdfeb3a8bf0c027bcb4373e59e6b3dc7c5002eca7cbb1afba801d6439df8f92f7bcb3fb862e8fbbe43a9e59bb5653dcc0568 - languageName: node - linkType: hard - -"@babel/plugin-transform-async-to-generator@npm:^7.28.6": - version: 7.28.6 - resolution: "@babel/plugin-transform-async-to-generator@npm:7.28.6" - dependencies: - "@babel/helper-module-imports": "npm:^7.28.6" - "@babel/helper-plugin-utils": "npm:^7.28.6" - "@babel/helper-remap-async-to-generator": "npm:^7.27.1" - peerDependencies: - "@babel/core": ^7.0.0-0 - checksum: 10c0/2eb0826248587df6e50038f36194a138771a7df22581020451c7779edeaf9ef39bf47c5b7a20ae2645af6416e8c896feeca273317329652e84abd79a4ab920ad - languageName: node - linkType: hard - -"@babel/plugin-transform-block-scoped-functions@npm:^7.27.1": - version: 7.27.1 - resolution: "@babel/plugin-transform-block-scoped-functions@npm:7.27.1" - dependencies: - "@babel/helper-plugin-utils": "npm:^7.27.1" - peerDependencies: - "@babel/core": ^7.0.0-0 - checksum: 10c0/3313130ba3bf0699baad0e60da1c8c3c2f0c2c0a7039cd0063e54e72e739c33f1baadfc9d8c73b3fea8c85dd7250c3964fb09c8e1fa62ba0b24a9fefe0a8dbde - languageName: node - linkType: hard - -"@babel/plugin-transform-block-scoping@npm:^7.28.6": - version: 7.28.6 - resolution: "@babel/plugin-transform-block-scoping@npm:7.28.6" - dependencies: - "@babel/helper-plugin-utils": "npm:^7.28.6" - peerDependencies: - "@babel/core": ^7.0.0-0 - checksum: 10c0/2e3e09e1f9770b56cef4dcbffddf262508fd03416072f815ac66b2b224a3a12cd285cfec12fc067f1add414e7db5ce6dafb5164a6e0fb1a728e6a97d0c6f6e9d - languageName: node - linkType: hard - -"@babel/plugin-transform-class-properties@npm:^7.28.6": - version: 7.28.6 - resolution: "@babel/plugin-transform-class-properties@npm:7.28.6" - dependencies: - "@babel/helper-create-class-features-plugin": "npm:^7.28.6" - "@babel/helper-plugin-utils": "npm:^7.28.6" - peerDependencies: - "@babel/core": ^7.0.0-0 - checksum: 10c0/c4327fcd730c239d9f173f9b695b57b801729e273b4848aef1f75818069dfd31d985d75175db188d947b9b1bbe5353dae298849042026a5e4fcf07582ff3f9f1 - languageName: node - linkType: hard - -"@babel/plugin-transform-class-static-block@npm:^7.28.6": - version: 7.28.6 - resolution: "@babel/plugin-transform-class-static-block@npm:7.28.6" - dependencies: - "@babel/helper-create-class-features-plugin": "npm:^7.28.6" - "@babel/helper-plugin-utils": "npm:^7.28.6" - peerDependencies: - "@babel/core": ^7.12.0 - checksum: 10c0/dbe9b1fd302ae41b73186e17ac8d8ecf625ebc2416a91f2dc8013977a1bdf21e6ea288a83f084752b412242f3866e789d4fddeb428af323fe35b60e0fae4f98c - languageName: node - linkType: hard - -"@babel/plugin-transform-classes@npm:^7.28.6": - version: 7.28.6 - resolution: "@babel/plugin-transform-classes@npm:7.28.6" - dependencies: - "@babel/helper-annotate-as-pure": "npm:^7.27.3" - "@babel/helper-compilation-targets": "npm:^7.28.6" - "@babel/helper-globals": "npm:^7.28.0" - "@babel/helper-plugin-utils": "npm:^7.28.6" - "@babel/helper-replace-supers": "npm:^7.28.6" - "@babel/traverse": "npm:^7.28.6" - peerDependencies: - "@babel/core": ^7.0.0-0 - checksum: 10c0/dc22f1f6eadab17305128fbf9cc5f30e87a51a77dd0a6d5498097994e8a9b9a90ab298c11edf2342acbeaac9edc9c601cad72eedcf4b592cd465a787d7f41490 - languageName: node - linkType: hard - -"@babel/plugin-transform-computed-properties@npm:^7.28.6": - version: 7.28.6 - resolution: "@babel/plugin-transform-computed-properties@npm:7.28.6" - dependencies: - "@babel/helper-plugin-utils": "npm:^7.28.6" - "@babel/template": "npm:^7.28.6" - peerDependencies: - "@babel/core": ^7.0.0-0 - checksum: 10c0/1e9893503ae6d651125701cc29450e87c0b873c8febebff19da75da9c40cfb7968c52c28bf948244e461110aeb7b3591f2cc199b7406ff74a24c50c7a5729f39 - languageName: node - linkType: hard - -"@babel/plugin-transform-destructuring@npm:^7.28.5": - version: 7.28.5 - resolution: "@babel/plugin-transform-destructuring@npm:7.28.5" - dependencies: - "@babel/helper-plugin-utils": "npm:^7.27.1" - "@babel/traverse": "npm:^7.28.5" - peerDependencies: - "@babel/core": ^7.0.0-0 - checksum: 10c0/288207f488412b23bb206c7c01ba143714e2506b72a9ec09e993f28366cc8188d121bde714659b3437984a86d2881d9b1b06de3089d5582823ccf2f3b3eaa2c4 - languageName: node - linkType: hard - -"@babel/plugin-transform-dotall-regex@npm:^7.28.6": - version: 7.28.6 - resolution: "@babel/plugin-transform-dotall-regex@npm:7.28.6" - dependencies: - "@babel/helper-create-regexp-features-plugin": "npm:^7.28.5" - "@babel/helper-plugin-utils": "npm:^7.28.6" - peerDependencies: - "@babel/core": ^7.0.0-0 - checksum: 10c0/e2fb76b7ae99087cf4212013a3ca9dee07048f90f98fd6264855080fb6c3f169be11c9b8c9d8b26cf9a407e4d0a5fa6e103f7cef433a542b75cf7127c99d4f97 - languageName: node - linkType: hard - -"@babel/plugin-transform-duplicate-keys@npm:^7.27.1": - version: 7.27.1 - resolution: "@babel/plugin-transform-duplicate-keys@npm:7.27.1" - dependencies: - "@babel/helper-plugin-utils": "npm:^7.27.1" - peerDependencies: - "@babel/core": ^7.0.0-0 - checksum: 10c0/22a822e5342b7066f83eaedc4fd9bb044ac6bc68725484690b33ba04a7104980e43ea3229de439286cb8db8e7db4a865733a3f05123ab58a10f189f03553746f - languageName: node - linkType: hard - -"@babel/plugin-transform-duplicate-named-capturing-groups-regex@npm:^7.29.0": - version: 7.29.0 - resolution: "@babel/plugin-transform-duplicate-named-capturing-groups-regex@npm:7.29.0" - dependencies: - "@babel/helper-create-regexp-features-plugin": "npm:^7.28.5" - "@babel/helper-plugin-utils": "npm:^7.28.6" - peerDependencies: - "@babel/core": ^7.0.0 - checksum: 10c0/6f03d9e5e31a05b28555541be6e283407e08447a36be6ddf8068b3efa970411d832e04b1282e2b894baf89a3864ff7e7f1e36346652a8d983170c6d548555167 - languageName: node - linkType: hard - -"@babel/plugin-transform-dynamic-import@npm:^7.27.1": - version: 7.27.1 - resolution: "@babel/plugin-transform-dynamic-import@npm:7.27.1" - dependencies: - "@babel/helper-plugin-utils": "npm:^7.27.1" - peerDependencies: - "@babel/core": ^7.0.0-0 - checksum: 10c0/8dcd3087aca134b064fc361d2cc34eec1f900f6be039b6368104afcef10bb75dea726bb18cabd046716b89b0edaa771f50189fa16bc5c5914a38cbcf166350f7 - languageName: node - linkType: hard - -"@babel/plugin-transform-explicit-resource-management@npm:^7.28.6": - version: 7.28.6 - resolution: "@babel/plugin-transform-explicit-resource-management@npm:7.28.6" - dependencies: - "@babel/helper-plugin-utils": "npm:^7.28.6" - "@babel/plugin-transform-destructuring": "npm:^7.28.5" - peerDependencies: - "@babel/core": ^7.0.0-0 - checksum: 10c0/e6ea28c26e058fe61ada3e70b0def1992dd5a44f5fc14d8e2c6a3a512fb4d4c6dc96a3e1d0b466d83db32a9101e0b02df94051e48d3140da115b8ea9f8a31f37 - languageName: node - linkType: hard - -"@babel/plugin-transform-exponentiation-operator@npm:^7.28.6": - version: 7.28.6 - resolution: "@babel/plugin-transform-exponentiation-operator@npm:7.28.6" - dependencies: - "@babel/helper-plugin-utils": "npm:^7.28.6" - peerDependencies: - "@babel/core": ^7.0.0-0 - checksum: 10c0/4572d955a50dbc9a652a19431b4bb822cb479ee6045f4e6df72659c499c13036da0a2adf650b07ca995f2781e80aa868943bea1e7bff1de3169ec3f0a73a902e - languageName: node - linkType: hard - -"@babel/plugin-transform-export-namespace-from@npm:^7.27.1": - version: 7.27.1 - resolution: "@babel/plugin-transform-export-namespace-from@npm:7.27.1" - dependencies: - "@babel/helper-plugin-utils": "npm:^7.27.1" - peerDependencies: - "@babel/core": ^7.0.0-0 - checksum: 10c0/d7165cad11f571a54c8d9263d6c6bf2b817aff4874f747cb51e6e49efb32f2c9b37a6850cdb5e3b81e0b638141bb77dc782a6ec1a94128859fbdf7767581e07c - languageName: node - linkType: hard - -"@babel/plugin-transform-for-of@npm:^7.27.1": - version: 7.27.1 - resolution: "@babel/plugin-transform-for-of@npm:7.27.1" - dependencies: - "@babel/helper-plugin-utils": "npm:^7.27.1" - "@babel/helper-skip-transparent-expression-wrappers": "npm:^7.27.1" - peerDependencies: - "@babel/core": ^7.0.0-0 - checksum: 10c0/4635763173a23aae24480681f2b0996b4f54a0cb2368880301a1801638242e263132d1e8adbe112ab272913d1d900ee0d6f7dea79443aef9d3325168cd88b3fb - languageName: node - linkType: hard - -"@babel/plugin-transform-function-name@npm:^7.27.1": - version: 7.27.1 - resolution: "@babel/plugin-transform-function-name@npm:7.27.1" - dependencies: - "@babel/helper-compilation-targets": "npm:^7.27.1" - "@babel/helper-plugin-utils": "npm:^7.27.1" - "@babel/traverse": "npm:^7.27.1" - peerDependencies: - "@babel/core": ^7.0.0-0 - checksum: 10c0/5abdc7b5945fbd807269dcc6e76e52b69235056023b0b35d311e8f5dfd6c09d9f225839798998fc3b663f50cf701457ddb76517025a0d7a5474f3fe56e567a4c - languageName: node - linkType: hard - -"@babel/plugin-transform-json-strings@npm:^7.28.6": - version: 7.28.6 - resolution: "@babel/plugin-transform-json-strings@npm:7.28.6" - dependencies: - "@babel/helper-plugin-utils": "npm:^7.28.6" - peerDependencies: - "@babel/core": ^7.0.0-0 - checksum: 10c0/ab1091798c58e6c0bb8a864ee2b727c400924592c6ed69797a26b4c205f850a935de77ad516570be0419c279a3d9f7740c2aa448762eb8364ea77a6a357a9653 - languageName: node - linkType: hard - -"@babel/plugin-transform-literals@npm:^7.27.1": - version: 7.27.1 - resolution: "@babel/plugin-transform-literals@npm:7.27.1" - dependencies: - "@babel/helper-plugin-utils": "npm:^7.27.1" - peerDependencies: - "@babel/core": ^7.0.0-0 - checksum: 10c0/c40dc3eb2f45a92ee476412314a40e471af51a0f51a24e91b85cef5fc59f4fe06758088f541643f07f949d2c67ee7bdce10e11c5ec56791ae09b15c3b451eeca - languageName: node - linkType: hard - -"@babel/plugin-transform-logical-assignment-operators@npm:^7.28.6": - version: 7.28.6 - resolution: "@babel/plugin-transform-logical-assignment-operators@npm:7.28.6" - dependencies: - "@babel/helper-plugin-utils": "npm:^7.28.6" - peerDependencies: - "@babel/core": ^7.0.0-0 - checksum: 10c0/4632a35453d2131f0be466681d0a33e3db44d868ff51ec46cd87e0ebd1e47c6a39b894f7d1c9b06f931addf6efa9d30e60c4cdedeb4f69d426f683e11f8490cf - languageName: node - linkType: hard - -"@babel/plugin-transform-member-expression-literals@npm:^7.27.1": - version: 7.27.1 - resolution: "@babel/plugin-transform-member-expression-literals@npm:7.27.1" - dependencies: - "@babel/helper-plugin-utils": "npm:^7.27.1" - peerDependencies: - "@babel/core": ^7.0.0-0 - checksum: 10c0/0874ccebbd1c6a155e5f6b3b29729fade1221b73152567c1af1e1a7c12848004dffecbd7eded6dc463955120040ae57c17cb586b53fb5a7a27fcd88177034c30 - languageName: node - linkType: hard - -"@babel/plugin-transform-modules-amd@npm:^7.27.1": - version: 7.27.1 - resolution: "@babel/plugin-transform-modules-amd@npm:7.27.1" - dependencies: - "@babel/helper-module-transforms": "npm:^7.27.1" - "@babel/helper-plugin-utils": "npm:^7.27.1" - peerDependencies: - "@babel/core": ^7.0.0-0 - checksum: 10c0/76e86cd278b6a3c5b8cca8dfb3428e9cd0c81a5df7096e04c783c506696b916a9561386d610a9d846ef64804640e0bd818ea47455fed0ee89b7f66c555b29537 - languageName: node - linkType: hard - -"@babel/plugin-transform-modules-commonjs@npm:^7.27.1": - version: 7.27.1 - resolution: "@babel/plugin-transform-modules-commonjs@npm:7.27.1" - dependencies: - "@babel/helper-module-transforms": "npm:^7.27.1" - "@babel/helper-plugin-utils": "npm:^7.27.1" - peerDependencies: - "@babel/core": ^7.0.0-0 - checksum: 10c0/4def972dcd23375a266ea1189115a4ff61744b2c9366fc1de648b3fab2c650faf1a94092de93a33ff18858d2e6c4dddeeee5384cb42ba0129baeab01a5cdf1e2 - languageName: node - linkType: hard - -"@babel/plugin-transform-modules-commonjs@npm:^7.28.6": - version: 7.28.6 - resolution: "@babel/plugin-transform-modules-commonjs@npm:7.28.6" - dependencies: - "@babel/helper-module-transforms": "npm:^7.28.6" - "@babel/helper-plugin-utils": "npm:^7.28.6" - peerDependencies: - "@babel/core": ^7.0.0-0 - checksum: 10c0/7c45992797c6150644c8552feff4a016ba7bd6d59ff2b039ed969a9c5b20a6804cd9d21db5045fc8cca8ca7f08262497e354e93f8f2be6a1cdf3fbfa8c31a9b6 - languageName: node - linkType: hard - -"@babel/plugin-transform-modules-systemjs@npm:^7.29.0": - version: 7.29.0 - resolution: "@babel/plugin-transform-modules-systemjs@npm:7.29.0" - dependencies: - "@babel/helper-module-transforms": "npm:^7.28.6" - "@babel/helper-plugin-utils": "npm:^7.28.6" - "@babel/helper-validator-identifier": "npm:^7.28.5" - "@babel/traverse": "npm:^7.29.0" - peerDependencies: - "@babel/core": ^7.0.0-0 - checksum: 10c0/44ea502f2c990398b7d9adc5b44d9e1810a0a5e86eebc05c92d039458f0b3994fe243efa9353b90f8a648d8a91b79845fb353d8679d7324cc9de0162d732771d - languageName: node - linkType: hard - -"@babel/plugin-transform-modules-umd@npm:^7.27.1": - version: 7.27.1 - resolution: "@babel/plugin-transform-modules-umd@npm:7.27.1" - dependencies: - "@babel/helper-module-transforms": "npm:^7.27.1" - "@babel/helper-plugin-utils": "npm:^7.27.1" - peerDependencies: - "@babel/core": ^7.0.0-0 - checksum: 10c0/e5962a8874889da2ab1aa32eb93ec21d419c7423c766e4befb39b4bb512b9ad44b47837b6cd1c8f1065445cbbcc6dc2be10298ac6e734e5ca1059fc23698daed - languageName: node - linkType: hard - -"@babel/plugin-transform-named-capturing-groups-regex@npm:^7.29.0": - version: 7.29.0 - resolution: "@babel/plugin-transform-named-capturing-groups-regex@npm:7.29.0" - dependencies: - "@babel/helper-create-regexp-features-plugin": "npm:^7.28.5" - "@babel/helper-plugin-utils": "npm:^7.28.6" - peerDependencies: - "@babel/core": ^7.0.0 - checksum: 10c0/1904db22da7f2bc3e380cd2c0786bda330ee1b1b3efa3f5203d980708c4bfeb5daa4dff48d01692193040bcc5f275dbdc0c2eadc8b1eb1b6dfe363564ad6e898 - languageName: node - linkType: hard - -"@babel/plugin-transform-new-target@npm:^7.27.1": - version: 7.27.1 - resolution: "@babel/plugin-transform-new-target@npm:7.27.1" - dependencies: - "@babel/helper-plugin-utils": "npm:^7.27.1" - peerDependencies: - "@babel/core": ^7.0.0-0 - checksum: 10c0/9b0581412fcc5ab1b9a2d86a0c5407bd959391f0a1e77a46953fef9f7a57f3f4020d75f71098c5f9e5dcc680a87f9fd99b3205ab12e25ef8c19eed038c1e4b28 - languageName: node - linkType: hard - -"@babel/plugin-transform-nullish-coalescing-operator@npm:^7.28.6": - version: 7.28.6 - resolution: "@babel/plugin-transform-nullish-coalescing-operator@npm:7.28.6" - dependencies: - "@babel/helper-plugin-utils": "npm:^7.28.6" - peerDependencies: - "@babel/core": ^7.0.0-0 - checksum: 10c0/6607f2201d66ccb688f0b1db09475ef995837df19f14705da41f693b669f834c206147a854864ab107913d7b4f4748878b0cd9fe9ca8bfd1bee0c206fc027b49 - languageName: node - linkType: hard - -"@babel/plugin-transform-numeric-separator@npm:^7.28.6": - version: 7.28.6 - resolution: "@babel/plugin-transform-numeric-separator@npm:7.28.6" - dependencies: - "@babel/helper-plugin-utils": "npm:^7.28.6" - peerDependencies: - "@babel/core": ^7.0.0-0 - checksum: 10c0/191097d8d2753cdd16d1acca65a945d1645ab20b65655c2f5b030a9e38967a52e093dcb21ebf391e342222705c6ffe5dea15dafd6257f7b51b77fb64a830b637 - languageName: node - linkType: hard - -"@babel/plugin-transform-object-rest-spread@npm:^7.28.6": - version: 7.28.6 - resolution: "@babel/plugin-transform-object-rest-spread@npm:7.28.6" - dependencies: - "@babel/helper-compilation-targets": "npm:^7.28.6" - "@babel/helper-plugin-utils": "npm:^7.28.6" - "@babel/plugin-transform-destructuring": "npm:^7.28.5" - "@babel/plugin-transform-parameters": "npm:^7.27.7" - "@babel/traverse": "npm:^7.28.6" - peerDependencies: - "@babel/core": ^7.0.0-0 - checksum: 10c0/f55334352d4fcde385f2e8a58836687e71ff668c9b6e4c34d52575bf2789cdde92d9d3116edba13647ac0bc3e51fb2a6d1e8fb822dce7e8123334b82600bc4c3 - languageName: node - linkType: hard - -"@babel/plugin-transform-object-super@npm:^7.27.1": - version: 7.27.1 - resolution: "@babel/plugin-transform-object-super@npm:7.27.1" - dependencies: - "@babel/helper-plugin-utils": "npm:^7.27.1" - "@babel/helper-replace-supers": "npm:^7.27.1" - peerDependencies: - "@babel/core": ^7.0.0-0 - checksum: 10c0/efa2d092ef55105deb06d30aff4e460c57779b94861188128489b72378bf1f0ab0f06a4a4d68b9ae2a59a79719fbb2d148b9a3dca19ceff9c73b1f1a95e0527c - languageName: node - linkType: hard - -"@babel/plugin-transform-optional-catch-binding@npm:^7.28.6": - version: 7.28.6 - resolution: "@babel/plugin-transform-optional-catch-binding@npm:7.28.6" - dependencies: - "@babel/helper-plugin-utils": "npm:^7.28.6" - peerDependencies: - "@babel/core": ^7.0.0-0 - checksum: 10c0/36e8face000ee65e478a55febf687ce9be7513ad498c60dfe585851555565e0c28e7cb891b3c59709318539ce46f7697d5f42130eb18f385cd47e47cfa297446 - languageName: node - linkType: hard - -"@babel/plugin-transform-optional-chaining@npm:^7.27.1": - version: 7.27.1 - resolution: "@babel/plugin-transform-optional-chaining@npm:7.27.1" - dependencies: - "@babel/helper-plugin-utils": "npm:^7.27.1" - "@babel/helper-skip-transparent-expression-wrappers": "npm:^7.27.1" - peerDependencies: - "@babel/core": ^7.0.0-0 - checksum: 10c0/5b18ff5124e503f0a25d6b195be7351a028b3992d6f2a91fb4037e2a2c386400d66bc1df8f6df0a94c708524f318729e81a95c41906e5a7919a06a43e573a525 - languageName: node - linkType: hard - -"@babel/plugin-transform-optional-chaining@npm:^7.28.6": - version: 7.28.6 - resolution: "@babel/plugin-transform-optional-chaining@npm:7.28.6" - dependencies: - "@babel/helper-plugin-utils": "npm:^7.28.6" - "@babel/helper-skip-transparent-expression-wrappers": "npm:^7.27.1" - peerDependencies: - "@babel/core": ^7.0.0-0 - checksum: 10c0/c159cc74115c2266be21791f192dd079e2aeb65c8731157e53b80fcefa41e8e28ad370021d4dfbdb31f25e5afa0322669a8eb2d032cd96e65ac37e020324c763 - languageName: node - linkType: hard - -"@babel/plugin-transform-parameters@npm:^7.27.7": - version: 7.27.7 - resolution: "@babel/plugin-transform-parameters@npm:7.27.7" - dependencies: - "@babel/helper-plugin-utils": "npm:^7.27.1" - peerDependencies: - "@babel/core": ^7.0.0-0 - checksum: 10c0/f2da3804e047d9f1cfb27be6c014e2c7f6cf5e1e38290d1cb3cb2607859e3d6facb4ee8c8c1e336e9fbb440091a174ce95ce156582d7e8bf9c0e735d11681f0f - languageName: node - linkType: hard - -"@babel/plugin-transform-private-methods@npm:^7.28.6": - version: 7.28.6 - resolution: "@babel/plugin-transform-private-methods@npm:7.28.6" - dependencies: - "@babel/helper-create-class-features-plugin": "npm:^7.28.6" - "@babel/helper-plugin-utils": "npm:^7.28.6" - peerDependencies: - "@babel/core": ^7.0.0-0 - checksum: 10c0/fb504e2bfdcf3f734d2a90ab20d61427c58385f57f950d3de6ff4e6d12dd4aa7d552147312d218367e129b7920dccfc3230ba554de861986cda38921bad84067 - languageName: node - linkType: hard - -"@babel/plugin-transform-private-property-in-object@npm:^7.28.6": - version: 7.28.6 - resolution: "@babel/plugin-transform-private-property-in-object@npm:7.28.6" - dependencies: - "@babel/helper-annotate-as-pure": "npm:^7.27.3" - "@babel/helper-create-class-features-plugin": "npm:^7.28.6" - "@babel/helper-plugin-utils": "npm:^7.28.6" - peerDependencies: - "@babel/core": ^7.0.0-0 - checksum: 10c0/0f6bbc6ec3f93b556d3de7d56bf49335255fc4c43488e51a5025d6ee0286183fd3cf950ffcac1bbeed8a45777f860a49996455c8d3b4a04c3b1a5f28e697fe31 - languageName: node - linkType: hard - -"@babel/plugin-transform-property-literals@npm:^7.27.1": - version: 7.27.1 - resolution: "@babel/plugin-transform-property-literals@npm:7.27.1" - dependencies: - "@babel/helper-plugin-utils": "npm:^7.27.1" - peerDependencies: - "@babel/core": ^7.0.0-0 - checksum: 10c0/15713a87edd6db620d6e66eb551b4fbfff5b8232c460c7c76cedf98efdc5cd21080c97040231e19e06594c6d7dfa66e1ab3d0951e29d5814fb25e813f6d6209c - languageName: node - linkType: hard - -"@babel/plugin-transform-react-display-name@npm:^7.28.0": - version: 7.28.0 - resolution: "@babel/plugin-transform-react-display-name@npm:7.28.0" - dependencies: - "@babel/helper-plugin-utils": "npm:^7.27.1" - peerDependencies: - "@babel/core": ^7.0.0-0 - checksum: 10c0/f5f86d2ad92be3e962158f344c2e385e23e2dfae7c8c7dc32138fb2cc46f63f5e50386c9f6c6fc16dbf1792c7bb650ad92c18203d0c2c0bd875bc28b0b80ef30 - languageName: node - linkType: hard - -"@babel/plugin-transform-react-jsx-development@npm:^7.27.1": - version: 7.27.1 - resolution: "@babel/plugin-transform-react-jsx-development@npm:7.27.1" - dependencies: - "@babel/plugin-transform-react-jsx": "npm:^7.27.1" - peerDependencies: - "@babel/core": ^7.0.0-0 - checksum: 10c0/eb8c4b6a79dc5c49b41e928e2037e1ee0bbfa722e4fd74c0b7c0d11103c82c2c25c434000e1b051d534c7261ab5c92b6d1e85313bf1b26e37db3f051ae217b58 - languageName: node - linkType: hard - -"@babel/plugin-transform-react-jsx-self@npm:^7.27.1": - version: 7.27.1 - resolution: "@babel/plugin-transform-react-jsx-self@npm:7.27.1" - dependencies: - "@babel/helper-plugin-utils": "npm:^7.27.1" - peerDependencies: - "@babel/core": ^7.0.0-0 - checksum: 10c0/00a4f917b70a608f9aca2fb39aabe04a60aa33165a7e0105fd44b3a8531630eb85bf5572e9f242f51e6ad2fa38c2e7e780902176c863556c58b5ba6f6e164031 - languageName: node - linkType: hard - -"@babel/plugin-transform-react-jsx-source@npm:^7.27.1": - version: 7.27.1 - resolution: "@babel/plugin-transform-react-jsx-source@npm:7.27.1" - dependencies: - "@babel/helper-plugin-utils": "npm:^7.27.1" - peerDependencies: - "@babel/core": ^7.0.0-0 - checksum: 10c0/5e67b56c39c4d03e59e03ba80692b24c5a921472079b63af711b1d250fc37c1733a17069b63537f750f3e937ec44a42b1ee6a46cd23b1a0df5163b17f741f7f2 - languageName: node - linkType: hard - -"@babel/plugin-transform-react-jsx@npm:^7.27.1": - version: 7.27.1 - resolution: "@babel/plugin-transform-react-jsx@npm:7.27.1" - dependencies: - "@babel/helper-annotate-as-pure": "npm:^7.27.1" - "@babel/helper-module-imports": "npm:^7.27.1" - "@babel/helper-plugin-utils": "npm:^7.27.1" - "@babel/plugin-syntax-jsx": "npm:^7.27.1" - "@babel/types": "npm:^7.27.1" - peerDependencies: - "@babel/core": ^7.0.0-0 - checksum: 10c0/1a08637c39fc78c9760dd4a3ed363fdbc762994bf83ed7872ad5bda0232fcd0fc557332f2ce36b522c0226dfd9cc8faac6b88eddda535f24825198a689e571af - languageName: node - linkType: hard - -"@babel/plugin-transform-react-pure-annotations@npm:^7.27.1": - version: 7.27.1 - resolution: "@babel/plugin-transform-react-pure-annotations@npm:7.27.1" - dependencies: - "@babel/helper-annotate-as-pure": "npm:^7.27.1" - "@babel/helper-plugin-utils": "npm:^7.27.1" - peerDependencies: - "@babel/core": ^7.0.0-0 - checksum: 10c0/34bc090f4a7e460d82a851971b4d0f32e4bb519bafb927154f4174506283fe02b0f471fc20655c6050a8bf7b748bfa31c7e8f7d688849476d8266623554fbb28 - languageName: node - linkType: hard - -"@babel/plugin-transform-regenerator@npm:^7.29.0": - version: 7.29.0 - resolution: "@babel/plugin-transform-regenerator@npm:7.29.0" - dependencies: - "@babel/helper-plugin-utils": "npm:^7.28.6" - peerDependencies: - "@babel/core": ^7.0.0-0 - checksum: 10c0/86c7db9b97f85ee47c0fae0528802cbc06e5775e61580ee905335c16bb971270086764a3859873d9adcd7d0f913a5b93eb0dc271aec8fb9e93e090e4ac95e29e - languageName: node - linkType: hard - -"@babel/plugin-transform-regexp-modifiers@npm:^7.28.6": - version: 7.28.6 - resolution: "@babel/plugin-transform-regexp-modifiers@npm:7.28.6" - dependencies: - "@babel/helper-create-regexp-features-plugin": "npm:^7.28.5" - "@babel/helper-plugin-utils": "npm:^7.28.6" - peerDependencies: - "@babel/core": ^7.0.0 - checksum: 10c0/97e36b086800f71694fa406abc00192e3833662f2bdd5f51c018bd0c95eef247c4ae187417c207d03a9c5374342eac0bb65a39112c431a9b23b09b1eda1562e5 - languageName: node - linkType: hard - -"@babel/plugin-transform-reserved-words@npm:^7.27.1": - version: 7.27.1 - resolution: "@babel/plugin-transform-reserved-words@npm:7.27.1" - dependencies: - "@babel/helper-plugin-utils": "npm:^7.27.1" - peerDependencies: - "@babel/core": ^7.0.0-0 - checksum: 10c0/e1a87691cce21a644a474d7c9a8107d4486c062957be32042d40f0a3d0cc66e00a3150989655019c255ff020d2640ac16aaf544792717d586f219f3bad295567 - languageName: node - linkType: hard - -"@babel/plugin-transform-shorthand-properties@npm:^7.27.1": - version: 7.27.1 - resolution: "@babel/plugin-transform-shorthand-properties@npm:7.27.1" - dependencies: - "@babel/helper-plugin-utils": "npm:^7.27.1" - peerDependencies: - "@babel/core": ^7.0.0-0 - checksum: 10c0/bd5544b89520a22c41a6df5ddac9039821d3334c0ef364d18b0ba9674c5071c223bcc98be5867dc3865cb10796882b7594e2c40dedaff38e1b1273913fe353e1 - languageName: node - linkType: hard - -"@babel/plugin-transform-spread@npm:^7.28.6": - version: 7.28.6 - resolution: "@babel/plugin-transform-spread@npm:7.28.6" - dependencies: - "@babel/helper-plugin-utils": "npm:^7.28.6" - "@babel/helper-skip-transparent-expression-wrappers": "npm:^7.27.1" - peerDependencies: - "@babel/core": ^7.0.0-0 - checksum: 10c0/bcac50e558d6f0c501cbce19ec197af558cef51fe3b3a6eba27276e323e57a5be28109b4264a5425ac12a67bf95d6af9c2a42b05e79c522ce913fb9529259d76 - languageName: node - linkType: hard - -"@babel/plugin-transform-sticky-regex@npm:^7.27.1": - version: 7.27.1 - resolution: "@babel/plugin-transform-sticky-regex@npm:7.27.1" - dependencies: - "@babel/helper-plugin-utils": "npm:^7.27.1" - peerDependencies: - "@babel/core": ^7.0.0-0 - checksum: 10c0/5698df2d924f0b1b7bdb7ef370e83f99ed3f0964eb3b9c27d774d021bee7f6d45f9a73e2be369d90b4aff1603ce29827f8743f091789960e7669daf9c3cda850 - languageName: node - linkType: hard - -"@babel/plugin-transform-template-literals@npm:^7.27.1": - version: 7.27.1 - resolution: "@babel/plugin-transform-template-literals@npm:7.27.1" - dependencies: - "@babel/helper-plugin-utils": "npm:^7.27.1" - peerDependencies: - "@babel/core": ^7.0.0-0 - checksum: 10c0/c90f403e42ef062b60654d1c122c70f3ec6f00c2f304b0931ebe6d0b432498ef8a5ef9266ddf00debc535f8390842207e44d3900eff1d2bab0cc1a700f03e083 - languageName: node - linkType: hard - -"@babel/plugin-transform-typeof-symbol@npm:^7.27.1": - version: 7.27.1 - resolution: "@babel/plugin-transform-typeof-symbol@npm:7.27.1" - dependencies: - "@babel/helper-plugin-utils": "npm:^7.27.1" - peerDependencies: - "@babel/core": ^7.0.0-0 - checksum: 10c0/a13c68015311fefa06a51830bc69d5badd06c881b13d5cf9ba04bf7c73e3fc6311cc889e18d9645ce2a64a79456dc9c7be88476c0b6802f62a686cb6f662ecd6 - languageName: node - linkType: hard - -"@babel/plugin-transform-typescript@npm:^7.28.5": - version: 7.28.5 - resolution: "@babel/plugin-transform-typescript@npm:7.28.5" - dependencies: - "@babel/helper-annotate-as-pure": "npm:^7.27.3" - "@babel/helper-create-class-features-plugin": "npm:^7.28.5" - "@babel/helper-plugin-utils": "npm:^7.27.1" - "@babel/helper-skip-transparent-expression-wrappers": "npm:^7.27.1" - "@babel/plugin-syntax-typescript": "npm:^7.27.1" - peerDependencies: - "@babel/core": ^7.0.0-0 - checksum: 10c0/09e574ba5462e56452b4ceecae65e53c8e697a2d3559ce5d210bed10ac28a18aa69377e7550c30520eb29b40c417ee61997d5d58112657f22983244b78915a7c - languageName: node - linkType: hard - -"@babel/plugin-transform-unicode-escapes@npm:^7.27.1": - version: 7.27.1 - resolution: "@babel/plugin-transform-unicode-escapes@npm:7.27.1" - dependencies: - "@babel/helper-plugin-utils": "npm:^7.27.1" - peerDependencies: - "@babel/core": ^7.0.0-0 - checksum: 10c0/a6809e0ca69d77ee9804e0c1164e8a2dea5e40718f6dcf234aeddf7292e7414f7ee331d87f17eb6f160823a329d1d6751bd49b35b392ac4a6efc032e4d3038d8 - languageName: node - linkType: hard - -"@babel/plugin-transform-unicode-property-regex@npm:^7.28.6": - version: 7.28.6 - resolution: "@babel/plugin-transform-unicode-property-regex@npm:7.28.6" - dependencies: - "@babel/helper-create-regexp-features-plugin": "npm:^7.28.5" - "@babel/helper-plugin-utils": "npm:^7.28.6" - peerDependencies: - "@babel/core": ^7.0.0-0 - checksum: 10c0/b25f8cde643f4f47e0fa4f7b5c552e2dfbb6ad0ce07cf40f7e8ae40daa9855ad855d76d4d6d010153b74e48c8794685955c92ca637c0da152ce5f0fa9e7c90fa - languageName: node - linkType: hard - -"@babel/plugin-transform-unicode-regex@npm:^7.27.1": - version: 7.27.1 - resolution: "@babel/plugin-transform-unicode-regex@npm:7.27.1" - dependencies: - "@babel/helper-create-regexp-features-plugin": "npm:^7.27.1" - "@babel/helper-plugin-utils": "npm:^7.27.1" - peerDependencies: - "@babel/core": ^7.0.0-0 - checksum: 10c0/6abda1bcffb79feba6f5c691859cdbe984cc96481ea65d5af5ba97c2e843154005f0886e25006a37a2d213c0243506a06eaeafd93a040dbe1f79539016a0d17a - languageName: node - linkType: hard - -"@babel/plugin-transform-unicode-sets-regex@npm:^7.28.6": - version: 7.28.6 - resolution: "@babel/plugin-transform-unicode-sets-regex@npm:7.28.6" - dependencies: - "@babel/helper-create-regexp-features-plugin": "npm:^7.28.5" - "@babel/helper-plugin-utils": "npm:^7.28.6" - peerDependencies: - "@babel/core": ^7.0.0 - checksum: 10c0/c03c8818736b138db73d1f7a96fbfa22d1994639164d743f0f00e6383d3b7b3144d333de960ff4afad0bddd0baaac257295e3316969eba995b1b6a1b4dec933e - languageName: node - linkType: hard - -"@babel/preset-env@npm:^7.22.20": - version: 7.29.2 - resolution: "@babel/preset-env@npm:7.29.2" - dependencies: - "@babel/compat-data": "npm:^7.29.0" - "@babel/helper-compilation-targets": "npm:^7.28.6" - "@babel/helper-plugin-utils": "npm:^7.28.6" - "@babel/helper-validator-option": "npm:^7.27.1" - "@babel/plugin-bugfix-firefox-class-in-computed-class-key": "npm:^7.28.5" - "@babel/plugin-bugfix-safari-class-field-initializer-scope": "npm:^7.27.1" - "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "npm:^7.27.1" - "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "npm:^7.27.1" - "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": "npm:^7.28.6" - "@babel/plugin-proposal-private-property-in-object": "npm:7.21.0-placeholder-for-preset-env.2" - "@babel/plugin-syntax-import-assertions": "npm:^7.28.6" - "@babel/plugin-syntax-import-attributes": "npm:^7.28.6" - "@babel/plugin-syntax-unicode-sets-regex": "npm:^7.18.6" - "@babel/plugin-transform-arrow-functions": "npm:^7.27.1" - "@babel/plugin-transform-async-generator-functions": "npm:^7.29.0" - "@babel/plugin-transform-async-to-generator": "npm:^7.28.6" - "@babel/plugin-transform-block-scoped-functions": "npm:^7.27.1" - "@babel/plugin-transform-block-scoping": "npm:^7.28.6" - "@babel/plugin-transform-class-properties": "npm:^7.28.6" - "@babel/plugin-transform-class-static-block": "npm:^7.28.6" - "@babel/plugin-transform-classes": "npm:^7.28.6" - "@babel/plugin-transform-computed-properties": "npm:^7.28.6" - "@babel/plugin-transform-destructuring": "npm:^7.28.5" - "@babel/plugin-transform-dotall-regex": "npm:^7.28.6" - "@babel/plugin-transform-duplicate-keys": "npm:^7.27.1" - "@babel/plugin-transform-duplicate-named-capturing-groups-regex": "npm:^7.29.0" - "@babel/plugin-transform-dynamic-import": "npm:^7.27.1" - "@babel/plugin-transform-explicit-resource-management": "npm:^7.28.6" - "@babel/plugin-transform-exponentiation-operator": "npm:^7.28.6" - "@babel/plugin-transform-export-namespace-from": "npm:^7.27.1" - "@babel/plugin-transform-for-of": "npm:^7.27.1" - "@babel/plugin-transform-function-name": "npm:^7.27.1" - "@babel/plugin-transform-json-strings": "npm:^7.28.6" - "@babel/plugin-transform-literals": "npm:^7.27.1" - "@babel/plugin-transform-logical-assignment-operators": "npm:^7.28.6" - "@babel/plugin-transform-member-expression-literals": "npm:^7.27.1" - "@babel/plugin-transform-modules-amd": "npm:^7.27.1" - "@babel/plugin-transform-modules-commonjs": "npm:^7.28.6" - "@babel/plugin-transform-modules-systemjs": "npm:^7.29.0" - "@babel/plugin-transform-modules-umd": "npm:^7.27.1" - "@babel/plugin-transform-named-capturing-groups-regex": "npm:^7.29.0" - "@babel/plugin-transform-new-target": "npm:^7.27.1" - "@babel/plugin-transform-nullish-coalescing-operator": "npm:^7.28.6" - "@babel/plugin-transform-numeric-separator": "npm:^7.28.6" - "@babel/plugin-transform-object-rest-spread": "npm:^7.28.6" - "@babel/plugin-transform-object-super": "npm:^7.27.1" - "@babel/plugin-transform-optional-catch-binding": "npm:^7.28.6" - "@babel/plugin-transform-optional-chaining": "npm:^7.28.6" - "@babel/plugin-transform-parameters": "npm:^7.27.7" - "@babel/plugin-transform-private-methods": "npm:^7.28.6" - "@babel/plugin-transform-private-property-in-object": "npm:^7.28.6" - "@babel/plugin-transform-property-literals": "npm:^7.27.1" - "@babel/plugin-transform-regenerator": "npm:^7.29.0" - "@babel/plugin-transform-regexp-modifiers": "npm:^7.28.6" - "@babel/plugin-transform-reserved-words": "npm:^7.27.1" - "@babel/plugin-transform-shorthand-properties": "npm:^7.27.1" - "@babel/plugin-transform-spread": "npm:^7.28.6" - "@babel/plugin-transform-sticky-regex": "npm:^7.27.1" - "@babel/plugin-transform-template-literals": "npm:^7.27.1" - "@babel/plugin-transform-typeof-symbol": "npm:^7.27.1" - "@babel/plugin-transform-unicode-escapes": "npm:^7.27.1" - "@babel/plugin-transform-unicode-property-regex": "npm:^7.28.6" - "@babel/plugin-transform-unicode-regex": "npm:^7.27.1" - "@babel/plugin-transform-unicode-sets-regex": "npm:^7.28.6" - "@babel/preset-modules": "npm:0.1.6-no-external-plugins" - babel-plugin-polyfill-corejs2: "npm:^0.4.15" - babel-plugin-polyfill-corejs3: "npm:^0.14.0" - babel-plugin-polyfill-regenerator: "npm:^0.6.6" - core-js-compat: "npm:^3.48.0" - semver: "npm:^6.3.1" - peerDependencies: - "@babel/core": ^7.0.0-0 - checksum: 10c0/d49cb005f2dbc3f2293ab6d80ee8f1380e6215af5518fe26b087c8961c1ea8ebaa554dfce589abe1fbebac25ad7c2515d943dec3859ea2d4981a3f8f4711c580 - languageName: node - linkType: hard - -"@babel/preset-modules@npm:0.1.6-no-external-plugins": - version: 0.1.6-no-external-plugins - resolution: "@babel/preset-modules@npm:0.1.6-no-external-plugins" - dependencies: - "@babel/helper-plugin-utils": "npm:^7.0.0" - "@babel/types": "npm:^7.4.4" - esutils: "npm:^2.0.2" - peerDependencies: - "@babel/core": ^7.0.0-0 || ^8.0.0-0 <8.0.0 - checksum: 10c0/9d02f70d7052446c5f3a4fb39e6b632695fb6801e46d31d7f7c5001f7c18d31d1ea8369212331ca7ad4e7877b73231f470b0d559162624128f1b80fe591409e6 - languageName: node - linkType: hard - -"@babel/preset-react@npm:^7.22.15": - version: 7.28.5 - resolution: "@babel/preset-react@npm:7.28.5" - dependencies: - "@babel/helper-plugin-utils": "npm:^7.27.1" - "@babel/helper-validator-option": "npm:^7.27.1" - "@babel/plugin-transform-react-display-name": "npm:^7.28.0" - "@babel/plugin-transform-react-jsx": "npm:^7.27.1" - "@babel/plugin-transform-react-jsx-development": "npm:^7.27.1" - "@babel/plugin-transform-react-pure-annotations": "npm:^7.27.1" - peerDependencies: - "@babel/core": ^7.0.0-0 - checksum: 10c0/0d785e708ff301f4102bd4738b77e550e32f981e54dfd3de1191b4d68306bbb934d2d465fc78a6bc22fff0a6b3ce3195a53984f52755c4349e7264c7e01e8c7c - languageName: node - linkType: hard - -"@babel/preset-typescript@npm:^7.23.0": - version: 7.28.5 - resolution: "@babel/preset-typescript@npm:7.28.5" - dependencies: - "@babel/helper-plugin-utils": "npm:^7.27.1" - "@babel/helper-validator-option": "npm:^7.27.1" - "@babel/plugin-syntax-jsx": "npm:^7.27.1" - "@babel/plugin-transform-modules-commonjs": "npm:^7.27.1" - "@babel/plugin-transform-typescript": "npm:^7.28.5" - peerDependencies: - "@babel/core": ^7.0.0-0 - checksum: 10c0/b3d55548854c105085dd80f638147aa8295bc186d70492289242d6c857cb03a6c61ec15186440ea10ed4a71cdde7d495f5eb3feda46273f36b0ac926e8409629 - languageName: node - linkType: hard - -"@babel/runtime@npm:^7.12.5": - version: 7.26.0 - resolution: "@babel/runtime@npm:7.26.0" - dependencies: - regenerator-runtime: "npm:^0.14.0" - checksum: 10c0/12c01357e0345f89f4f7e8c0e81921f2a3e3e101f06e8eaa18a382b517376520cd2fa8c237726eb094dab25532855df28a7baaf1c26342b52782f6936b07c287 - languageName: node - linkType: hard - -"@babel/runtime@npm:^7.13.9": - version: 7.19.4 - resolution: "@babel/runtime@npm:7.19.4" - dependencies: - regenerator-runtime: "npm:^0.13.4" - checksum: 10c0/3ad7f298262cf1f060a3bf2be9f65afa3c034c9c7a2e7c9d3ec41ab58c944c86756d0e0fdfc08d178f983f48d6b5613c15253d83216fbe02b6141c13d28f12e5 - languageName: node - linkType: hard - -"@babel/runtime@npm:^7.23.2, @babel/runtime@npm:^7.25.0": - version: 7.26.9 - resolution: "@babel/runtime@npm:7.26.9" - dependencies: - regenerator-runtime: "npm:^0.14.0" - checksum: 10c0/e8517131110a6ec3a7360881438b85060e49824e007f4a64b5dfa9192cf2bb5c01e84bfc109f02d822c7edb0db926928dd6b991e3ee460b483fb0fac43152d9b - languageName: node - linkType: hard - -"@babel/runtime@npm:^7.26.10": - version: 7.27.4 - resolution: "@babel/runtime@npm:7.27.4" - checksum: 10c0/ca99e964179c31615e1352e058cc9024df7111c829631c90eec84caba6703cc32acc81503771847c306b3c70b815609fe82dde8682936debe295b0b283b2dc6e - languageName: node - linkType: hard - -"@babel/runtime@npm:^7.29.2": - version: 7.29.2 - resolution: "@babel/runtime@npm:7.29.2" - checksum: 10c0/30b80a0140d16467792e1bbeb06f655b0dab70407da38dfac7fedae9c859f9ae9d846ef14ad77bd3814c064295fe9b1bc551f1541ea14646ae9f22b71a8bc17a - languageName: node - linkType: hard - -"@babel/template@npm:^7.25.9": - version: 7.26.9 - resolution: "@babel/template@npm:7.26.9" - dependencies: - "@babel/code-frame": "npm:^7.26.2" - "@babel/parser": "npm:^7.26.9" - "@babel/types": "npm:^7.26.9" - checksum: 10c0/019b1c4129cc01ad63e17529089c2c559c74709d225f595eee017af227fee11ae8a97a6ab19ae6768b8aa22d8d75dcb60a00b28f52e9fa78140672d928bc1ae9 - languageName: node - linkType: hard - -"@babel/template@npm:^7.27.1, @babel/template@npm:^7.27.2": - version: 7.27.2 - resolution: "@babel/template@npm:7.27.2" - dependencies: - "@babel/code-frame": "npm:^7.27.1" - "@babel/parser": "npm:^7.27.2" - "@babel/types": "npm:^7.27.1" - checksum: 10c0/ed9e9022651e463cc5f2cc21942f0e74544f1754d231add6348ff1b472985a3b3502041c0be62dc99ed2d12cfae0c51394bf827452b98a2f8769c03b87aadc81 - languageName: node - linkType: hard - -"@babel/template@npm:^7.28.6": - version: 7.28.6 - resolution: "@babel/template@npm:7.28.6" - dependencies: - "@babel/code-frame": "npm:^7.28.6" - "@babel/parser": "npm:^7.28.6" - "@babel/types": "npm:^7.28.6" - checksum: 10c0/66d87225ed0bc77f888181ae2d97845021838c619944877f7c4398c6748bcf611f216dfd6be74d39016af502bca876e6ce6873db3c49e4ac354c56d34d57e9f5 - languageName: node - linkType: hard - -"@babel/traverse@npm:^7.10.3": - version: 7.25.9 - resolution: "@babel/traverse@npm:7.25.9" - dependencies: - "@babel/code-frame": "npm:^7.25.9" - "@babel/generator": "npm:^7.25.9" - "@babel/parser": "npm:^7.25.9" - "@babel/template": "npm:^7.25.9" - "@babel/types": "npm:^7.25.9" - debug: "npm:^4.3.1" - globals: "npm:^11.1.0" - checksum: 10c0/e90be586a714da4adb80e6cb6a3c5cfcaa9b28148abdafb065e34cc109676fc3db22cf98cd2b2fff66ffb9b50c0ef882cab0f466b6844be0f6c637b82719bba1 - languageName: node - linkType: hard - -"@babel/traverse@npm:^7.27.1, @babel/traverse@npm:^7.27.3": - version: 7.27.3 - resolution: "@babel/traverse@npm:7.27.3" - dependencies: - "@babel/code-frame": "npm:^7.27.1" - "@babel/generator": "npm:^7.27.3" - "@babel/parser": "npm:^7.27.3" - "@babel/template": "npm:^7.27.2" - "@babel/types": "npm:^7.27.3" - debug: "npm:^4.3.1" - globals: "npm:^11.1.0" - checksum: 10c0/63edf0755cc7307470fefeca69c5205b259eaf45df79a4f7be0f28d8937d916bfb090ad9ffbc62edd7e1bbc4309c1f202a9a6904ed3af847504bcefd5ac58c16 - languageName: node - linkType: hard - -"@babel/traverse@npm:^7.28.0, @babel/traverse@npm:^7.28.6, @babel/traverse@npm:^7.29.0": - version: 7.29.0 - resolution: "@babel/traverse@npm:7.29.0" - dependencies: - "@babel/code-frame": "npm:^7.29.0" - "@babel/generator": "npm:^7.29.0" - "@babel/helper-globals": "npm:^7.28.0" - "@babel/parser": "npm:^7.29.0" - "@babel/template": "npm:^7.28.6" - "@babel/types": "npm:^7.29.0" - debug: "npm:^4.3.1" - checksum: 10c0/f63ef6e58d02a9fbf3c0e2e5f1c877da3e0bc57f91a19d2223d53e356a76859cbaf51171c9211c71816d94a0e69efa2732fd27ffc0e1bbc84b636e60932333eb - languageName: node - linkType: hard - -"@babel/traverse@npm:^7.28.5": - version: 7.28.5 - resolution: "@babel/traverse@npm:7.28.5" - dependencies: - "@babel/code-frame": "npm:^7.27.1" - "@babel/generator": "npm:^7.28.5" - "@babel/helper-globals": "npm:^7.28.0" - "@babel/parser": "npm:^7.28.5" - "@babel/template": "npm:^7.27.2" - "@babel/types": "npm:^7.28.5" - debug: "npm:^4.3.1" - checksum: 10c0/f6c4a595993ae2b73f2d4cd9c062f2e232174d293edd4abe1d715bd6281da8d99e47c65857e8d0917d9384c65972f4acdebc6749a7c40a8fcc38b3c7fb3e706f - languageName: node - linkType: hard - -"@babel/types@npm:^7.0.0, @babel/types@npm:^7.10.3, @babel/types@npm:^7.20.7, @babel/types@npm:^7.21.3": - version: 7.26.0 - resolution: "@babel/types@npm:7.26.0" - dependencies: - "@babel/helper-string-parser": "npm:^7.25.9" - "@babel/helper-validator-identifier": "npm:^7.25.9" - checksum: 10c0/b694f41ad1597127e16024d766c33a641508aad037abd08d0d1f73af753e1119fa03b4a107d04b5f92cc19c095a594660547ae9bead1db2299212d644b0a5cb8 - languageName: node - linkType: hard - -"@babel/types@npm:^7.25.9, @babel/types@npm:^7.26.5, @babel/types@npm:^7.26.9, @babel/types@npm:^7.4.4": - version: 7.26.9 - resolution: "@babel/types@npm:7.26.9" - dependencies: - "@babel/helper-string-parser": "npm:^7.25.9" - "@babel/helper-validator-identifier": "npm:^7.25.9" - checksum: 10c0/999c56269ba00e5c57aa711fbe7ff071cd6990bafd1b978341ea7572cc78919986e2aa6ee51dacf4b6a7a6fa63ba4eb3f1a03cf55eee31b896a56d068b895964 - languageName: node - linkType: hard - -"@babel/types@npm:^7.26.0, @babel/types@npm:^7.26.3": - version: 7.26.5 - resolution: "@babel/types@npm:7.26.5" - dependencies: - "@babel/helper-string-parser": "npm:^7.25.9" - "@babel/helper-validator-identifier": "npm:^7.25.9" - checksum: 10c0/0278053b69d7c2b8573aa36dc5242cad95f0d965e1c0ed21ccacac6330092e59ba5949753448f6d6eccf6ad59baaef270295cc05218352e060ea8c68388638c4 - languageName: node - linkType: hard - -"@babel/types@npm:^7.27.1, @babel/types@npm:^7.27.3": - version: 7.27.3 - resolution: "@babel/types@npm:7.27.3" - dependencies: - "@babel/helper-string-parser": "npm:^7.27.1" - "@babel/helper-validator-identifier": "npm:^7.27.1" - checksum: 10c0/bafdfc98e722a6b91a783b6f24388f478fd775f0c0652e92220e08be2cc33e02d42088542f1953ac5e5ece2ac052172b3dadedf12bec9aae57899e92fb9a9757 - languageName: node - linkType: hard - -"@babel/types@npm:^7.28.2, @babel/types@npm:^7.28.6, @babel/types@npm:^7.29.0": - version: 7.29.0 - resolution: "@babel/types@npm:7.29.0" - dependencies: - "@babel/helper-string-parser": "npm:^7.27.1" - "@babel/helper-validator-identifier": "npm:^7.28.5" - checksum: 10c0/23cc3466e83bcbfab8b9bd0edaafdb5d4efdb88b82b3be6728bbade5ba2f0996f84f63b1c5f7a8c0d67efded28300898a5f930b171bb40b311bca2029c4e9b4f - languageName: node - linkType: hard - -"@babel/types@npm:^7.28.5": - version: 7.28.5 - resolution: "@babel/types@npm:7.28.5" - dependencies: - "@babel/helper-string-parser": "npm:^7.27.1" - "@babel/helper-validator-identifier": "npm:^7.28.5" - checksum: 10c0/a5a483d2100befbf125793640dec26b90b95fd233a94c19573325898a5ce1e52cdfa96e495c7dcc31b5eca5b66ce3e6d4a0f5a4a62daec271455959f208ab08a - languageName: node - linkType: hard - -"@bcoe/v8-coverage@npm:^1.0.2": - version: 1.0.2 - resolution: "@bcoe/v8-coverage@npm:1.0.2" - checksum: 10c0/1eb1dc93cc17fb7abdcef21a6e7b867d6aa99a7ec88ec8207402b23d9083ab22a8011213f04b2cf26d535f1d22dc26139b7929e6c2134c254bd1e14ba5e678c3 - languageName: node - linkType: hard - -"@bufbuild/protobuf@npm:^1.10.0": - version: 1.10.0 - resolution: "@bufbuild/protobuf@npm:1.10.0" - checksum: 10c0/5487b9c2e63846d0e3bde4d025cc77ae44a22166a5d6c184df0da5581e1ab6d66dd115af0ccad814576dcd011bb1b93989fb0ac1eb4ae452979bb8b186693ba0 - languageName: node - linkType: hard - -"@codecov/bundler-plugin-core@npm:^1.9.1": - version: 1.9.1 - resolution: "@codecov/bundler-plugin-core@npm:1.9.1" - dependencies: - "@actions/core": "npm:^1.10.1" - "@actions/github": "npm:^6.0.0" - chalk: "npm:4.1.2" - semver: "npm:^7.5.4" - unplugin: "npm:^1.10.1" - zod: "npm:^3.22.4" - checksum: 10c0/82366e6a0c7ee1c1c810b71c1773ea12ba3c395d812d3172f3155cf2930eae1bb8d2fe660be3d0c2e60eb0f6db2bbf4b5d327344d846523d3e54848549b55aee - languageName: node - linkType: hard - -"@codecov/vite-plugin@npm:^1.3.0": - version: 1.9.1 - resolution: "@codecov/vite-plugin@npm:1.9.1" - dependencies: - "@codecov/bundler-plugin-core": "npm:^1.9.1" - unplugin: "npm:^1.10.1" - peerDependencies: - vite: 4.x || 5.x || 6.x - checksum: 10c0/b4e640a23f4af4a140038a68a1fbc8d4de555d7064c68d8f5dbd0d99c983a66113f9262035f98f4fd8ecadf93f4d7daf1aafd1f138f947edf4f6c24c26475571 - languageName: node - linkType: hard - -"@csstools/cascade-layer-name-parser@npm:^2.0.5": - version: 2.0.5 - resolution: "@csstools/cascade-layer-name-parser@npm:2.0.5" - peerDependencies: - "@csstools/css-parser-algorithms": ^3.0.5 - "@csstools/css-tokenizer": ^3.0.4 - checksum: 10c0/b6c73d5c8132f922edc88b9df5272c93c9753945f1e1077b80d03b314076ffe03c2cc9bf6cbc85501ee7c7f27e477263df96997c9125fd2fd0cfe82fe2d7c141 - languageName: node - linkType: hard - -"@csstools/color-helpers@npm:^5.0.1": - version: 5.0.1 - resolution: "@csstools/color-helpers@npm:5.0.1" - checksum: 10c0/77fa3b7236eaa3f36dea24708ac0d5e53168903624ac5aed54615752a0730cd20773fda50e742ce868012eca8c000cc39688e05869e79f34714230ab6968d1e6 - languageName: node - linkType: hard - -"@csstools/color-helpers@npm:^5.1.0": - version: 5.1.0 - resolution: "@csstools/color-helpers@npm:5.1.0" - checksum: 10c0/b7f99d2e455cf1c9b41a67a5327d5d02888cd5c8802a68b1887dffef537d9d4bc66b3c10c1e62b40bbed638b6c1d60b85a232f904ed7b39809c4029cb36567db - languageName: node - linkType: hard - -"@csstools/css-calc@npm:^2.1.1": - version: 2.1.1 - resolution: "@csstools/css-calc@npm:2.1.1" - peerDependencies: - "@csstools/css-parser-algorithms": ^3.0.4 - "@csstools/css-tokenizer": ^3.0.3 - checksum: 10c0/857c8dac40eb6ba8810408dad141bbcad060b28bce69dfd3bcf095a060fcaa23d5c4dbf52be88fcb57e12ce32c666e855dc68de1d8020851f6b432e3f9b29950 - languageName: node - linkType: hard - -"@csstools/css-calc@npm:^2.1.4": - version: 2.1.4 - resolution: "@csstools/css-calc@npm:2.1.4" - peerDependencies: - "@csstools/css-parser-algorithms": ^3.0.5 - "@csstools/css-tokenizer": ^3.0.4 - checksum: 10c0/42ce5793e55ec4d772083808a11e9fb2dfe36db3ec168713069a276b4c3882205b3507c4680224c28a5d35fe0bc2d308c77f8f2c39c7c09aad8747708eb8ddd8 - languageName: node - linkType: hard - -"@csstools/css-color-parser@npm:^3.0.7": - version: 3.0.7 - resolution: "@csstools/css-color-parser@npm:3.0.7" - dependencies: - "@csstools/color-helpers": "npm:^5.0.1" - "@csstools/css-calc": "npm:^2.1.1" - peerDependencies: - "@csstools/css-parser-algorithms": ^3.0.4 - "@csstools/css-tokenizer": ^3.0.3 - checksum: 10c0/b81780e6c50f0b0605776bd39bbd6203780231a561601853a9835cc70788560e7a281d0fbfe47ebe8affcb07dd64b0b1dcd4b67552520cfbe0e5088df158f12c - languageName: node - linkType: hard - -"@csstools/css-color-parser@npm:^3.1.0": - version: 3.1.0 - resolution: "@csstools/css-color-parser@npm:3.1.0" - dependencies: - "@csstools/color-helpers": "npm:^5.1.0" - "@csstools/css-calc": "npm:^2.1.4" - peerDependencies: - "@csstools/css-parser-algorithms": ^3.0.5 - "@csstools/css-tokenizer": ^3.0.4 - checksum: 10c0/0e0c670ad54ec8ec4d9b07568b80defd83b9482191f5e8ca84ab546b7be6db5d7cc2ba7ac9fae54488b129a4be235d6183d3aab4416fec5e89351f73af4222c5 - languageName: node - linkType: hard - -"@csstools/css-parser-algorithms@npm:^3.0.4": - version: 3.0.4 - resolution: "@csstools/css-parser-algorithms@npm:3.0.4" - peerDependencies: - "@csstools/css-tokenizer": ^3.0.3 - checksum: 10c0/d411f07765e14eede17bccc6bd4f90ff303694df09aabfede3fd104b2dfacfd4fe3697cd25ddad14684c850328f3f9420ebfa9f78380892492974db24ae47dbd - languageName: node - linkType: hard - -"@csstools/css-parser-algorithms@npm:^3.0.5": - version: 3.0.5 - resolution: "@csstools/css-parser-algorithms@npm:3.0.5" - peerDependencies: - "@csstools/css-tokenizer": ^3.0.4 - checksum: 10c0/d9a1c888bd43849ae3437ca39251d5c95d2c8fd6b5ccdb7c45491dfd2c1cbdc3075645e80901d120e4d2c1993db9a5b2d83793b779dbbabcfb132adb142eb7f7 - languageName: node - linkType: hard - -"@csstools/css-tokenizer@npm:^3.0.3": - version: 3.0.3 - resolution: "@csstools/css-tokenizer@npm:3.0.3" - checksum: 10c0/c31bf410e1244b942e71798e37c54639d040cb59e0121b21712b40015fced2b0fb1ffe588434c5f8923c9cd0017cfc1c1c8f3921abc94c96edf471aac2eba5e5 - languageName: node - linkType: hard - -"@csstools/css-tokenizer@npm:^3.0.4": - version: 3.0.4 - resolution: "@csstools/css-tokenizer@npm:3.0.4" - checksum: 10c0/3b589f8e9942075a642213b389bab75a2d50d05d203727fcdac6827648a5572674caff07907eff3f9a2389d86a4ee47308fafe4f8588f4a77b7167c588d2559f - languageName: node - linkType: hard - -"@csstools/media-query-list-parser@npm:^4.0.3": - version: 4.0.3 - resolution: "@csstools/media-query-list-parser@npm:4.0.3" - peerDependencies: - "@csstools/css-parser-algorithms": ^3.0.5 - "@csstools/css-tokenizer": ^3.0.4 - checksum: 10c0/e29d856d57e9a036694662163179fc061a99579f05e7c3c35438b3e063790ae8a9ee9f1fb4b4693d8fc7672ae0801764fe83762ab7b9df2921fcc6172cfd5584 - languageName: node - linkType: hard - -"@csstools/postcss-alpha-function@npm:^1.0.1": - version: 1.0.1 - resolution: "@csstools/postcss-alpha-function@npm:1.0.1" - dependencies: - "@csstools/css-color-parser": "npm:^3.1.0" - "@csstools/css-parser-algorithms": "npm:^3.0.5" - "@csstools/css-tokenizer": "npm:^3.0.4" - "@csstools/postcss-progressive-custom-properties": "npm:^4.2.1" - "@csstools/utilities": "npm:^2.0.0" - peerDependencies: - postcss: ^8.4 - checksum: 10c0/35ca209e572534ade21ac5c18aad702aa492eb39e2d0e475f441371063418fe9650554e6a59b1318d3a615da83ef54d9a588faa27063ecc0a568ef7290a6b488 - languageName: node - linkType: hard - -"@csstools/postcss-cascade-layers@npm:^5.0.2": - version: 5.0.2 - resolution: "@csstools/postcss-cascade-layers@npm:5.0.2" - dependencies: - "@csstools/selector-specificity": "npm:^5.0.0" - postcss-selector-parser: "npm:^7.0.0" - peerDependencies: - postcss: ^8.4 - checksum: 10c0/dd8e29cfd3a93932fa35e3a59aa62fd2e720772d450f40f38f65ce1e736e2fe839635eb6f033abcc8ee8bc2856161a297f4458b352b26d2216856feb03176612 - languageName: node - linkType: hard - -"@csstools/postcss-color-function-display-p3-linear@npm:^1.0.1": - version: 1.0.1 - resolution: "@csstools/postcss-color-function-display-p3-linear@npm:1.0.1" - dependencies: - "@csstools/css-color-parser": "npm:^3.1.0" - "@csstools/css-parser-algorithms": "npm:^3.0.5" - "@csstools/css-tokenizer": "npm:^3.0.4" - "@csstools/postcss-progressive-custom-properties": "npm:^4.2.1" - "@csstools/utilities": "npm:^2.0.0" - peerDependencies: - postcss: ^8.4 - checksum: 10c0/d02d45410c9257f5620c766f861f8fa3762b74ef01fdba8060b33a4c98f929e2219cd476b25bd4181ac186158a4d99a0da555c0b6ba45a7ac4a3a5885baad1f5 - languageName: node - linkType: hard - -"@csstools/postcss-color-function@npm:^4.0.12": - version: 4.0.12 - resolution: "@csstools/postcss-color-function@npm:4.0.12" - dependencies: - "@csstools/css-color-parser": "npm:^3.1.0" - "@csstools/css-parser-algorithms": "npm:^3.0.5" - "@csstools/css-tokenizer": "npm:^3.0.4" - "@csstools/postcss-progressive-custom-properties": "npm:^4.2.1" - "@csstools/utilities": "npm:^2.0.0" - peerDependencies: - postcss: ^8.4 - checksum: 10c0/a355b04d90f89c8e37a4a23543151558060acc68fb2e7d1c3549bebeeae2b147eec26af1fbc6ee690f0ba4830263f2d181f5331d16d3483b5542be46996fa755 - languageName: node - linkType: hard - -"@csstools/postcss-color-mix-function@npm:^3.0.12": - version: 3.0.12 - resolution: "@csstools/postcss-color-mix-function@npm:3.0.12" - dependencies: - "@csstools/css-color-parser": "npm:^3.1.0" - "@csstools/css-parser-algorithms": "npm:^3.0.5" - "@csstools/css-tokenizer": "npm:^3.0.4" - "@csstools/postcss-progressive-custom-properties": "npm:^4.2.1" - "@csstools/utilities": "npm:^2.0.0" - peerDependencies: - postcss: ^8.4 - checksum: 10c0/3e98a5118852083d1f87a3f842f78088192b1f9f08fdf1f3b3ef1e8969e18fdadc1e3bcac3d113a07c8917a7e8fa65fdec55a31df9a1b726c8d7ae89db86e8e5 - languageName: node - linkType: hard - -"@csstools/postcss-color-mix-variadic-function-arguments@npm:^1.0.2": - version: 1.0.2 - resolution: "@csstools/postcss-color-mix-variadic-function-arguments@npm:1.0.2" - dependencies: - "@csstools/css-color-parser": "npm:^3.1.0" - "@csstools/css-parser-algorithms": "npm:^3.0.5" - "@csstools/css-tokenizer": "npm:^3.0.4" - "@csstools/postcss-progressive-custom-properties": "npm:^4.2.1" - "@csstools/utilities": "npm:^2.0.0" - peerDependencies: - postcss: ^8.4 - checksum: 10c0/34073f0f0d33e4958f90763e692955a8e8c678b74284234497c4aa0d2143756e1b3616e0c09832caad498870e227ca0a681316afe3a71224fc40ade0ead1bdd9 - languageName: node - linkType: hard - -"@csstools/postcss-content-alt-text@npm:^2.0.8": - version: 2.0.8 - resolution: "@csstools/postcss-content-alt-text@npm:2.0.8" - dependencies: - "@csstools/css-parser-algorithms": "npm:^3.0.5" - "@csstools/css-tokenizer": "npm:^3.0.4" - "@csstools/postcss-progressive-custom-properties": "npm:^4.2.1" - "@csstools/utilities": "npm:^2.0.0" - peerDependencies: - postcss: ^8.4 - checksum: 10c0/4c330cc2a1e434688a62613ecceb1434cd725ce024c1ad8d4a4c76b9839d1f3ea8566a8c6494921e2b46ec7feef6af8ed6548c216dcb8f0feab4b1d52c96228e - languageName: node - linkType: hard - -"@csstools/postcss-contrast-color-function@npm:^2.0.12": - version: 2.0.12 - resolution: "@csstools/postcss-contrast-color-function@npm:2.0.12" - dependencies: - "@csstools/css-color-parser": "npm:^3.1.0" - "@csstools/css-parser-algorithms": "npm:^3.0.5" - "@csstools/css-tokenizer": "npm:^3.0.4" - "@csstools/postcss-progressive-custom-properties": "npm:^4.2.1" - "@csstools/utilities": "npm:^2.0.0" - peerDependencies: - postcss: ^8.4 - checksum: 10c0/b783ce948cdf1513ee238e9115b42881a8d3e5d13c16038601b1c470d661cfaeeece4eea29904fb9fcae878bad86f766810fa798a703ab9ad4b0cf276b173f8f - languageName: node - linkType: hard - -"@csstools/postcss-exponential-functions@npm:^2.0.9": - version: 2.0.9 - resolution: "@csstools/postcss-exponential-functions@npm:2.0.9" - dependencies: - "@csstools/css-calc": "npm:^2.1.4" - "@csstools/css-parser-algorithms": "npm:^3.0.5" - "@csstools/css-tokenizer": "npm:^3.0.4" - peerDependencies: - postcss: ^8.4 - checksum: 10c0/78ea627a87fb23e12616c4e54150363b0e8793064634983dbe0368a0aca1ff73206c2d1f29845773daaf42787e7d1f180ce1b57c43e2b0d10da450101f9f34b6 - languageName: node - linkType: hard - -"@csstools/postcss-font-format-keywords@npm:^4.0.0": - version: 4.0.0 - resolution: "@csstools/postcss-font-format-keywords@npm:4.0.0" - dependencies: - "@csstools/utilities": "npm:^2.0.0" - postcss-value-parser: "npm:^4.2.0" - peerDependencies: - postcss: ^8.4 - checksum: 10c0/eb794fb95fefcac75e606d185255e601636af177866a317b0c6b6c375055e7240be53918229fd8d4bba00df01bedd2256bdac2b0ad4a4c2ec64f9d27cd6ff639 - languageName: node - linkType: hard - -"@csstools/postcss-gamut-mapping@npm:^2.0.11": - version: 2.0.11 - resolution: "@csstools/postcss-gamut-mapping@npm:2.0.11" - dependencies: - "@csstools/css-color-parser": "npm:^3.1.0" - "@csstools/css-parser-algorithms": "npm:^3.0.5" - "@csstools/css-tokenizer": "npm:^3.0.4" - peerDependencies: - postcss: ^8.4 - checksum: 10c0/490b8ccf10e30879a4415afbdd3646e1cdac3671586b7916855cf47a536f3be75eed014396056bde6528e0cb76d904e79bad78afc0b499e837264cf22519d145 - languageName: node - linkType: hard - -"@csstools/postcss-gradients-interpolation-method@npm:^5.0.12": - version: 5.0.12 - resolution: "@csstools/postcss-gradients-interpolation-method@npm:5.0.12" - dependencies: - "@csstools/css-color-parser": "npm:^3.1.0" - "@csstools/css-parser-algorithms": "npm:^3.0.5" - "@csstools/css-tokenizer": "npm:^3.0.4" - "@csstools/postcss-progressive-custom-properties": "npm:^4.2.1" - "@csstools/utilities": "npm:^2.0.0" - peerDependencies: - postcss: ^8.4 - checksum: 10c0/70b3d6c7050ce882ed2281e71eb4493531ae8d55d21899920eeeb6c205d90aaf430419a66235484ccce3a1a1891367dfc0ef772f3866ae3a9d8ec5ddd0cfe894 - languageName: node - linkType: hard - -"@csstools/postcss-hwb-function@npm:^4.0.12": - version: 4.0.12 - resolution: "@csstools/postcss-hwb-function@npm:4.0.12" - dependencies: - "@csstools/css-color-parser": "npm:^3.1.0" - "@csstools/css-parser-algorithms": "npm:^3.0.5" - "@csstools/css-tokenizer": "npm:^3.0.4" - "@csstools/postcss-progressive-custom-properties": "npm:^4.2.1" - "@csstools/utilities": "npm:^2.0.0" - peerDependencies: - postcss: ^8.4 - checksum: 10c0/d0dac34da9d7ac654060b6b27690a419718e990b21ff3e63266ea59934a865bc6aeae8eb8e1ca3e227a8b2a208657e3ab70ccdf0437f1f09d21ab848bbffcaa2 - languageName: node - linkType: hard - -"@csstools/postcss-ic-unit@npm:^4.0.4": - version: 4.0.4 - resolution: "@csstools/postcss-ic-unit@npm:4.0.4" - dependencies: - "@csstools/postcss-progressive-custom-properties": "npm:^4.2.1" - "@csstools/utilities": "npm:^2.0.0" - postcss-value-parser: "npm:^4.2.0" - peerDependencies: - postcss: ^8.4 - checksum: 10c0/20168e70ecb4abf7a69e407d653b6c7c9c82f2c7b1da0920e1d035f62b5ef8552cc7f1b62e0dca318df13c348e79fba862e1a4bb0e9432119a82b10aeb511752 - languageName: node - linkType: hard - -"@csstools/postcss-initial@npm:^2.0.1": - version: 2.0.1 - resolution: "@csstools/postcss-initial@npm:2.0.1" - peerDependencies: - postcss: ^8.4 - checksum: 10c0/dbff7084ef4f1c4647efe2b147001daf172003c15b5e22689f0540d03c8d362f2a332cd9cf136e6c8dcda7564ee30492a4267ea188f72cb9c1000fb9bcfbfef8 - languageName: node - linkType: hard - -"@csstools/postcss-is-pseudo-class@npm:^5.0.3": - version: 5.0.3 - resolution: "@csstools/postcss-is-pseudo-class@npm:5.0.3" - dependencies: - "@csstools/selector-specificity": "npm:^5.0.0" - postcss-selector-parser: "npm:^7.0.0" - peerDependencies: - postcss: ^8.4 - checksum: 10c0/7980f1cabf32850bac72552e4e9de47412359e36e259a92b9b9af25dae4cce42bbcc5fdca8f384a589565bf383ecb23dec3af9f084d8df18b82552318b2841b6 - languageName: node - linkType: hard - -"@csstools/postcss-light-dark-function@npm:^2.0.11": - version: 2.0.11 - resolution: "@csstools/postcss-light-dark-function@npm:2.0.11" - dependencies: - "@csstools/css-parser-algorithms": "npm:^3.0.5" - "@csstools/css-tokenizer": "npm:^3.0.4" - "@csstools/postcss-progressive-custom-properties": "npm:^4.2.1" - "@csstools/utilities": "npm:^2.0.0" - peerDependencies: - postcss: ^8.4 - checksum: 10c0/0175be41bb0044a48bc98d5c55cce41ed6b9ada88253c5f20d0ca17287cba4b429742b458ac5744675b9a286109e13ac51d64e226ab16040d7b051ba64c0c77b - languageName: node - linkType: hard - -"@csstools/postcss-logical-float-and-clear@npm:^3.0.0": - version: 3.0.0 - resolution: "@csstools/postcss-logical-float-and-clear@npm:3.0.0" - peerDependencies: - postcss: ^8.4 - checksum: 10c0/71a20e8c37877bf68ae615d7bb93fc11b4f8da8be8b1dc1a6e0fc69e27f189712ed71436b8ed51fa69fdb98b8e6718df2b5f42f246c4d39badaf0e43020fcfd4 - languageName: node - linkType: hard - -"@csstools/postcss-logical-overflow@npm:^2.0.0": - version: 2.0.0 - resolution: "@csstools/postcss-logical-overflow@npm:2.0.0" - peerDependencies: - postcss: ^8.4 - checksum: 10c0/0e103343d3ff8b34eef01b02355c5e010d272fd12d149a242026bb13ab1577b7f3a11fd4514be9342d96f73d61dac1f093a9bd36ece591753ed09a84eb7fca0a - languageName: node - linkType: hard - -"@csstools/postcss-logical-overscroll-behavior@npm:^2.0.0": - version: 2.0.0 - resolution: "@csstools/postcss-logical-overscroll-behavior@npm:2.0.0" - peerDependencies: - postcss: ^8.4 - checksum: 10c0/1649601bb26f04d760fb5ebc42cdf414fa2a380b8ec22fe1c117f664c286665a786bd7bbda01b7e7567eaf3cc018a4f36a5c9805f6751cc497da223e0ffe9524 - languageName: node - linkType: hard - -"@csstools/postcss-logical-resize@npm:^3.0.0": - version: 3.0.0 - resolution: "@csstools/postcss-logical-resize@npm:3.0.0" - dependencies: - postcss-value-parser: "npm:^4.2.0" - peerDependencies: - postcss: ^8.4 - checksum: 10c0/4f12efcaf5468ff359bb3f32f0f66034b9acc9b3ac21fcd2f30a1c8998fc653ebac0091f35c8b7e8dbfe6ccf595aee67f9b06a67adf45a8844e49a82d98b4386 - languageName: node - linkType: hard - -"@csstools/postcss-logical-viewport-units@npm:^3.0.4": - version: 3.0.4 - resolution: "@csstools/postcss-logical-viewport-units@npm:3.0.4" - dependencies: - "@csstools/css-tokenizer": "npm:^3.0.4" - "@csstools/utilities": "npm:^2.0.0" - peerDependencies: - postcss: ^8.4 - checksum: 10c0/f0b5ba38acde3bf0ca880c6e0a883950c99fa9919b0e6290c894d5716569663590f26aa1170fd9483ce14544e46afac006ab3b02781410d5e7c8dd1467c674ce - languageName: node - linkType: hard - -"@csstools/postcss-media-minmax@npm:^2.0.9": - version: 2.0.9 - resolution: "@csstools/postcss-media-minmax@npm:2.0.9" - dependencies: - "@csstools/css-calc": "npm:^2.1.4" - "@csstools/css-parser-algorithms": "npm:^3.0.5" - "@csstools/css-tokenizer": "npm:^3.0.4" - "@csstools/media-query-list-parser": "npm:^4.0.3" - peerDependencies: - postcss: ^8.4 - checksum: 10c0/d82622ee9de6eacba1abbf31718cd58759d158ed8a575f36f08e982d07a7d83e51fb184178b96c6f7b76cb333bb33cac04d06a750b6b9c5c43ae1c56232880f9 - languageName: node - linkType: hard - -"@csstools/postcss-media-queries-aspect-ratio-number-values@npm:^3.0.5": - version: 3.0.5 - resolution: "@csstools/postcss-media-queries-aspect-ratio-number-values@npm:3.0.5" - dependencies: - "@csstools/css-parser-algorithms": "npm:^3.0.5" - "@csstools/css-tokenizer": "npm:^3.0.4" - "@csstools/media-query-list-parser": "npm:^4.0.3" - peerDependencies: - postcss: ^8.4 - checksum: 10c0/a47abdaa7f4b26596bd9d6bb77aed872a232fc12bd144d2c062d9da626e8dfd8336e2fff67617dba61a1666c2b8027145b390d70d5cd4d4f608604e077cfb04e - languageName: node - linkType: hard - -"@csstools/postcss-nested-calc@npm:^4.0.0": - version: 4.0.0 - resolution: "@csstools/postcss-nested-calc@npm:4.0.0" - dependencies: - "@csstools/utilities": "npm:^2.0.0" - postcss-value-parser: "npm:^4.2.0" - peerDependencies: - postcss: ^8.4 - checksum: 10c0/fb61512fa4909bdf0ee32a23e771145086c445f2208a737b52093c8adfab7362c56d3aeaf2a6e33ffcec067e99a07219775465d2fbb1a3ac30cdcfb278b218b7 - languageName: node - linkType: hard - -"@csstools/postcss-normalize-display-values@npm:^4.0.1": - version: 4.0.1 - resolution: "@csstools/postcss-normalize-display-values@npm:4.0.1" - dependencies: - postcss-value-parser: "npm:^4.2.0" - peerDependencies: - postcss: ^8.4 - checksum: 10c0/5d19364bad8554b047cebd94ad7e203723ed76abaf690e4b92c74e6fc7c3642cb8858ade3263da61aff26d97bb258af567b1036e97865b7aa3b17522241fd1e1 - languageName: node - linkType: hard - -"@csstools/postcss-oklab-function@npm:^4.0.12": - version: 4.0.12 - resolution: "@csstools/postcss-oklab-function@npm:4.0.12" - dependencies: - "@csstools/css-color-parser": "npm:^3.1.0" - "@csstools/css-parser-algorithms": "npm:^3.0.5" - "@csstools/css-tokenizer": "npm:^3.0.4" - "@csstools/postcss-progressive-custom-properties": "npm:^4.2.1" - "@csstools/utilities": "npm:^2.0.0" - peerDependencies: - postcss: ^8.4 - checksum: 10c0/40d4f51b568c8299c054f8971d0e85fa7da609ba23ce6c84dc17e16bc3838640ed6da75c3886dc9a96a11005773c6e23cba13a5510c781b2d633d07ad7bda6b7 - languageName: node - linkType: hard - -"@csstools/postcss-position-area-property@npm:^1.0.0": - version: 1.0.0 - resolution: "@csstools/postcss-position-area-property@npm:1.0.0" - peerDependencies: - postcss: ^8.4 - checksum: 10c0/38f770454d46bfed01d43a3f5e7ac07d3111399b374a7198ae6503cdb6288e410c7b4199f5a7af8f16aeb688216445ade97be417c084313d6c56f55e50d34559 - languageName: node - linkType: hard - -"@csstools/postcss-progressive-custom-properties@npm:^4.2.1": - version: 4.2.1 - resolution: "@csstools/postcss-progressive-custom-properties@npm:4.2.1" - dependencies: - postcss-value-parser: "npm:^4.2.0" - peerDependencies: - postcss: ^8.4 - checksum: 10c0/56e9a147799719fd5c550c035437693dd50cdfef46d66a4f2ce8f196e1006a096aa47d412710a89c3dc9808068a0a101c7f607a507ed68e925580c6f921e84d5 - languageName: node - linkType: hard - -"@csstools/postcss-property-rule-prelude-list@npm:^1.0.0": - version: 1.0.0 - resolution: "@csstools/postcss-property-rule-prelude-list@npm:1.0.0" - dependencies: - "@csstools/css-parser-algorithms": "npm:^3.0.5" - "@csstools/css-tokenizer": "npm:^3.0.4" - peerDependencies: - postcss: ^8.4 - checksum: 10c0/ae8bbca3a77ca59c21c11899a904f9d9417a19a3359d01dee042e0489b7ddfe7cea13ae275b7e7936d9b0b99c0a13f7f685f962cd63ca3d3d2b6e5eacc293a0d - languageName: node - linkType: hard - -"@csstools/postcss-random-function@npm:^2.0.1": - version: 2.0.1 - resolution: "@csstools/postcss-random-function@npm:2.0.1" - dependencies: - "@csstools/css-calc": "npm:^2.1.4" - "@csstools/css-parser-algorithms": "npm:^3.0.5" - "@csstools/css-tokenizer": "npm:^3.0.4" - peerDependencies: - postcss: ^8.4 - checksum: 10c0/475bacf685b8bb82942d388e9e3b95f4156800f370299f19f5acc490475dc2813100de81a5a6bf48b696b4d83247622005b616af3166a668556b4b1aceded70d - languageName: node - linkType: hard - -"@csstools/postcss-relative-color-syntax@npm:^3.0.12": - version: 3.0.12 - resolution: "@csstools/postcss-relative-color-syntax@npm:3.0.12" - dependencies: - "@csstools/css-color-parser": "npm:^3.1.0" - "@csstools/css-parser-algorithms": "npm:^3.0.5" - "@csstools/css-tokenizer": "npm:^3.0.4" - "@csstools/postcss-progressive-custom-properties": "npm:^4.2.1" - "@csstools/utilities": "npm:^2.0.0" - peerDependencies: - postcss: ^8.4 - checksum: 10c0/11af386c8193e22c148ac034eee94c56da3060bdbde3196d2d641b088e12de35bef187bcd7d421f9e4d49c4f1cfc28b24e136e62107e02ed7007a3a28f635d06 - languageName: node - linkType: hard - -"@csstools/postcss-scope-pseudo-class@npm:^4.0.1": - version: 4.0.1 - resolution: "@csstools/postcss-scope-pseudo-class@npm:4.0.1" - dependencies: - postcss-selector-parser: "npm:^7.0.0" - peerDependencies: - postcss: ^8.4 - checksum: 10c0/6a0ca50fae655f4498200d1ce298ca794c85fbe2e3fd5d6419843254f055df5007a973e09b5f1e78e376c02b54278e411516c8d824300c68b265d3e5b311d7ee - languageName: node - linkType: hard - -"@csstools/postcss-sign-functions@npm:^1.1.4": - version: 1.1.4 - resolution: "@csstools/postcss-sign-functions@npm:1.1.4" - dependencies: - "@csstools/css-calc": "npm:^2.1.4" - "@csstools/css-parser-algorithms": "npm:^3.0.5" - "@csstools/css-tokenizer": "npm:^3.0.4" - peerDependencies: - postcss: ^8.4 - checksum: 10c0/ff58108b2527832a84c571a1f40224b5c8d2afa8db2fe3b1e3599ff6f3469d9f4c528a70eb3c25c5d7801e30474fabfec04e7c23bfdad8572ad492053cd4f899 - languageName: node - linkType: hard - -"@csstools/postcss-stepped-value-functions@npm:^4.0.9": - version: 4.0.9 - resolution: "@csstools/postcss-stepped-value-functions@npm:4.0.9" - dependencies: - "@csstools/css-calc": "npm:^2.1.4" - "@csstools/css-parser-algorithms": "npm:^3.0.5" - "@csstools/css-tokenizer": "npm:^3.0.4" - peerDependencies: - postcss: ^8.4 - checksum: 10c0/f143ca06338c30abb2aa37adc3d7e43a78f3b4493093160cb5babe3ec8cf6b86d83876746ee8e162db87b5e9af6e0066958d89fe8b4a503a29568e5c57c1bf8a - languageName: node - linkType: hard - -"@csstools/postcss-syntax-descriptor-syntax-production@npm:^1.0.1": - version: 1.0.1 - resolution: "@csstools/postcss-syntax-descriptor-syntax-production@npm:1.0.1" - dependencies: - "@csstools/css-tokenizer": "npm:^3.0.4" - peerDependencies: - postcss: ^8.4 - checksum: 10c0/b9b3d84a50b86b1af1b8b7e56a64d5eebc1c89c323a5263306c5c69ddb05a4d468d7072a7786b0ea6601629035df0089565e9d98d55d0f4eb7201cf7ed1bb3e9 - languageName: node - linkType: hard - -"@csstools/postcss-system-ui-font-family@npm:^1.0.0": - version: 1.0.0 - resolution: "@csstools/postcss-system-ui-font-family@npm:1.0.0" - dependencies: - "@csstools/css-parser-algorithms": "npm:^3.0.5" - "@csstools/css-tokenizer": "npm:^3.0.4" - peerDependencies: - postcss: ^8.4 - checksum: 10c0/6a81761ae3cae643659b1416a7a892cf1505474896193b8abc26cff319cb6b1a20b64c5330d64019fba458e058da3abc9407d0ebf0c102289c0b79ef99b4c6d6 - languageName: node - linkType: hard - -"@csstools/postcss-text-decoration-shorthand@npm:^4.0.3": - version: 4.0.3 - resolution: "@csstools/postcss-text-decoration-shorthand@npm:4.0.3" - dependencies: - "@csstools/color-helpers": "npm:^5.1.0" - postcss-value-parser: "npm:^4.2.0" - peerDependencies: - postcss: ^8.4 - checksum: 10c0/f6af7d5dcf599edcf76c5e396ef2d372bbe1c1f3fbaaccd91e91049e64b6ff68b44f459277aef0a8110baca3eaa21275012adc52ccb8c0fc526a4c35577f8fce - languageName: node - linkType: hard - -"@csstools/postcss-trigonometric-functions@npm:^4.0.9": - version: 4.0.9 - resolution: "@csstools/postcss-trigonometric-functions@npm:4.0.9" - dependencies: - "@csstools/css-calc": "npm:^2.1.4" - "@csstools/css-parser-algorithms": "npm:^3.0.5" - "@csstools/css-tokenizer": "npm:^3.0.4" - peerDependencies: - postcss: ^8.4 - checksum: 10c0/6ba3d381c977c224f01d47a36f78c9b99d3b89d060a357a9f8840537fdf497d9587a28165dc74e96abdf02f8db0a277d3558646355085a74c8915ee73c6780d1 - languageName: node - linkType: hard - -"@csstools/postcss-unset-value@npm:^4.0.0": - version: 4.0.0 - resolution: "@csstools/postcss-unset-value@npm:4.0.0" - peerDependencies: - postcss: ^8.4 - checksum: 10c0/8424ac700ded5bf59d49310335896f10c069e2c3fc6a676b5d13ca5a6fb78689b948f50494df875da284c4c76651deb005eafba70d87e693274628c5a685abfa - languageName: node - linkType: hard - -"@csstools/selector-resolve-nested@npm:^3.1.0": - version: 3.1.0 - resolution: "@csstools/selector-resolve-nested@npm:3.1.0" - peerDependencies: - postcss-selector-parser: ^7.0.0 - checksum: 10c0/c2b1a930ad03c1427ab90b28c4940424fb39e8175130148f16209be3a3937f7a146d5483ca1da1dfc100aa7ae86df713f0ee82d4bbaa9b986e7f47f35cb67cca - languageName: node - linkType: hard - -"@csstools/selector-specificity@npm:^5.0.0": - version: 5.0.0 - resolution: "@csstools/selector-specificity@npm:5.0.0" - peerDependencies: - postcss-selector-parser: ^7.0.0 - checksum: 10c0/186b444cabcdcdeb553bfe021f80c58bfe9ef38dcc444f2b1f34a5aab9be063ab4e753022b2d5792049c041c28cfbb78e4b707ec398459300e402030d35c07eb - languageName: node - linkType: hard - -"@csstools/utilities@npm:^2.0.0": - version: 2.0.0 - resolution: "@csstools/utilities@npm:2.0.0" - peerDependencies: - postcss: ^8.4 - checksum: 10c0/be5c31437b726928f64cd4bb3e47f5b90bfd2e2a69a8eaabd8e89cc6c0977e4f0f7ee48de50c8ed8b07e04e3956a02293247e0da3236d521fb2e836f88f65822 - languageName: node - linkType: hard - -"@emnapi/core@npm:^1.7.1": - version: 1.8.0 - resolution: "@emnapi/core@npm:1.8.0" - dependencies: - "@emnapi/wasi-threads": "npm:1.1.0" - tslib: "npm:^2.4.0" - checksum: 10c0/4bb07df0a6ba6478bd4bee2a3609df1f9ef835588227261e9d8ef40f25a9e7596d837f663a4b2c2193d7e8a130370cab5a8063255d81c30903a8c167435d2687 - languageName: node - linkType: hard - -"@emnapi/runtime@npm:^1.7.1": - version: 1.8.0 - resolution: "@emnapi/runtime@npm:1.8.0" - dependencies: - tslib: "npm:^2.4.0" - checksum: 10c0/25330ade92c48d19f4dc896ecfe906a45c95bd2d3d4155fcf4934e796703f90f23c8f2e7466be44ec734b68ea3e50f64831647d75e1bd44aebbbe1ca870f932a - languageName: node - linkType: hard - -"@emnapi/wasi-threads@npm:1.1.0": - version: 1.1.0 - resolution: "@emnapi/wasi-threads@npm:1.1.0" - dependencies: - tslib: "npm:^2.4.0" - checksum: 10c0/e6d54bf2b1e64cdd83d2916411e44e579b6ae35d5def0dea61a3c452d9921373044dff32a8b8473ae60c80692bdc39323e98b96a3f3d87ba6886b24dd0ef7ca1 - languageName: node - linkType: hard - -"@es-joy/jsdoccomment@npm:~0.78.0": - version: 0.78.0 - resolution: "@es-joy/jsdoccomment@npm:0.78.0" - dependencies: - "@types/estree": "npm:^1.0.8" - "@typescript-eslint/types": "npm:^8.46.4" - comment-parser: "npm:1.4.1" - esquery: "npm:^1.6.0" - jsdoc-type-pratt-parser: "npm:~7.0.0" - checksum: 10c0/be18b8149303e8e7c9414b0b0453a0fa959c1c8db6f721b75178336e01b65a9f251db98ecfedfb1b3cfa5e717f3e2abdb06a0f8dbe45d3330a62262c5331c327 - languageName: node - linkType: hard - -"@es-joy/resolve.exports@npm:1.2.0": - version: 1.2.0 - resolution: "@es-joy/resolve.exports@npm:1.2.0" - checksum: 10c0/7e4713471f5eccb17a925a12415a2d9e372a42376813a19f6abd9c35e8d01ab1403777265817da67c6150cffd4f558d9ad51e26a8de6911dad89d9cb7eedacd8 - languageName: node - linkType: hard - -"@esbuild/aix-ppc64@npm:0.25.1": - version: 0.25.1 - resolution: "@esbuild/aix-ppc64@npm:0.25.1" - conditions: os=aix & cpu=ppc64 - languageName: node - linkType: hard - -"@esbuild/aix-ppc64@npm:0.27.4": - version: 0.27.4 - resolution: "@esbuild/aix-ppc64@npm:0.27.4" - conditions: os=aix & cpu=ppc64 - languageName: node - linkType: hard - -"@esbuild/android-arm64@npm:0.25.1": - version: 0.25.1 - resolution: "@esbuild/android-arm64@npm:0.25.1" - conditions: os=android & cpu=arm64 - languageName: node - linkType: hard - -"@esbuild/android-arm64@npm:0.27.4": - version: 0.27.4 - resolution: "@esbuild/android-arm64@npm:0.27.4" - conditions: os=android & cpu=arm64 - languageName: node - linkType: hard - -"@esbuild/android-arm@npm:0.25.1": - version: 0.25.1 - resolution: "@esbuild/android-arm@npm:0.25.1" - conditions: os=android & cpu=arm - languageName: node - linkType: hard - -"@esbuild/android-arm@npm:0.27.4": - version: 0.27.4 - resolution: "@esbuild/android-arm@npm:0.27.4" - conditions: os=android & cpu=arm - languageName: node - linkType: hard - -"@esbuild/android-x64@npm:0.25.1": - version: 0.25.1 - resolution: "@esbuild/android-x64@npm:0.25.1" - conditions: os=android & cpu=x64 - languageName: node - linkType: hard - -"@esbuild/android-x64@npm:0.27.4": - version: 0.27.4 - resolution: "@esbuild/android-x64@npm:0.27.4" - conditions: os=android & cpu=x64 - languageName: node - linkType: hard - -"@esbuild/darwin-arm64@npm:0.25.1": - version: 0.25.1 - resolution: "@esbuild/darwin-arm64@npm:0.25.1" - conditions: os=darwin & cpu=arm64 - languageName: node - linkType: hard - -"@esbuild/darwin-arm64@npm:0.27.4": - version: 0.27.4 - resolution: "@esbuild/darwin-arm64@npm:0.27.4" - conditions: os=darwin & cpu=arm64 - languageName: node - linkType: hard - -"@esbuild/darwin-x64@npm:0.25.1": - version: 0.25.1 - resolution: "@esbuild/darwin-x64@npm:0.25.1" - conditions: os=darwin & cpu=x64 - languageName: node - linkType: hard - -"@esbuild/darwin-x64@npm:0.27.4": - version: 0.27.4 - resolution: "@esbuild/darwin-x64@npm:0.27.4" - conditions: os=darwin & cpu=x64 - languageName: node - linkType: hard - -"@esbuild/freebsd-arm64@npm:0.25.1": - version: 0.25.1 - resolution: "@esbuild/freebsd-arm64@npm:0.25.1" - conditions: os=freebsd & cpu=arm64 - languageName: node - linkType: hard - -"@esbuild/freebsd-arm64@npm:0.27.4": - version: 0.27.4 - resolution: "@esbuild/freebsd-arm64@npm:0.27.4" - conditions: os=freebsd & cpu=arm64 - languageName: node - linkType: hard - -"@esbuild/freebsd-x64@npm:0.25.1": - version: 0.25.1 - resolution: "@esbuild/freebsd-x64@npm:0.25.1" - conditions: os=freebsd & cpu=x64 - languageName: node - linkType: hard - -"@esbuild/freebsd-x64@npm:0.27.4": - version: 0.27.4 - resolution: "@esbuild/freebsd-x64@npm:0.27.4" - conditions: os=freebsd & cpu=x64 - languageName: node - linkType: hard - -"@esbuild/linux-arm64@npm:0.25.1": - version: 0.25.1 - resolution: "@esbuild/linux-arm64@npm:0.25.1" - conditions: os=linux & cpu=arm64 - languageName: node - linkType: hard - -"@esbuild/linux-arm64@npm:0.27.4": - version: 0.27.4 - resolution: "@esbuild/linux-arm64@npm:0.27.4" - conditions: os=linux & cpu=arm64 - languageName: node - linkType: hard - -"@esbuild/linux-arm@npm:0.25.1": - version: 0.25.1 - resolution: "@esbuild/linux-arm@npm:0.25.1" - conditions: os=linux & cpu=arm - languageName: node - linkType: hard - -"@esbuild/linux-arm@npm:0.27.4": - version: 0.27.4 - resolution: "@esbuild/linux-arm@npm:0.27.4" - conditions: os=linux & cpu=arm - languageName: node - linkType: hard - -"@esbuild/linux-ia32@npm:0.25.1": - version: 0.25.1 - resolution: "@esbuild/linux-ia32@npm:0.25.1" - conditions: os=linux & cpu=ia32 - languageName: node - linkType: hard - -"@esbuild/linux-ia32@npm:0.27.4": - version: 0.27.4 - resolution: "@esbuild/linux-ia32@npm:0.27.4" - conditions: os=linux & cpu=ia32 - languageName: node - linkType: hard - -"@esbuild/linux-loong64@npm:0.25.1": - version: 0.25.1 - resolution: "@esbuild/linux-loong64@npm:0.25.1" - conditions: os=linux & cpu=loong64 - languageName: node - linkType: hard - -"@esbuild/linux-loong64@npm:0.27.4": - version: 0.27.4 - resolution: "@esbuild/linux-loong64@npm:0.27.4" - conditions: os=linux & cpu=loong64 - languageName: node - linkType: hard - -"@esbuild/linux-mips64el@npm:0.25.1": - version: 0.25.1 - resolution: "@esbuild/linux-mips64el@npm:0.25.1" - conditions: os=linux & cpu=mips64el - languageName: node - linkType: hard - -"@esbuild/linux-mips64el@npm:0.27.4": - version: 0.27.4 - resolution: "@esbuild/linux-mips64el@npm:0.27.4" - conditions: os=linux & cpu=mips64el - languageName: node - linkType: hard - -"@esbuild/linux-ppc64@npm:0.25.1": - version: 0.25.1 - resolution: "@esbuild/linux-ppc64@npm:0.25.1" - conditions: os=linux & cpu=ppc64 - languageName: node - linkType: hard - -"@esbuild/linux-ppc64@npm:0.27.4": - version: 0.27.4 - resolution: "@esbuild/linux-ppc64@npm:0.27.4" - conditions: os=linux & cpu=ppc64 - languageName: node - linkType: hard - -"@esbuild/linux-riscv64@npm:0.25.1": - version: 0.25.1 - resolution: "@esbuild/linux-riscv64@npm:0.25.1" - conditions: os=linux & cpu=riscv64 - languageName: node - linkType: hard - -"@esbuild/linux-riscv64@npm:0.27.4": - version: 0.27.4 - resolution: "@esbuild/linux-riscv64@npm:0.27.4" - conditions: os=linux & cpu=riscv64 - languageName: node - linkType: hard - -"@esbuild/linux-s390x@npm:0.25.1": - version: 0.25.1 - resolution: "@esbuild/linux-s390x@npm:0.25.1" - conditions: os=linux & cpu=s390x - languageName: node - linkType: hard - -"@esbuild/linux-s390x@npm:0.27.4": - version: 0.27.4 - resolution: "@esbuild/linux-s390x@npm:0.27.4" - conditions: os=linux & cpu=s390x - languageName: node - linkType: hard - -"@esbuild/linux-x64@npm:0.25.1": - version: 0.25.1 - resolution: "@esbuild/linux-x64@npm:0.25.1" - conditions: os=linux & cpu=x64 - languageName: node - linkType: hard - -"@esbuild/linux-x64@npm:0.27.4": - version: 0.27.4 - resolution: "@esbuild/linux-x64@npm:0.27.4" - conditions: os=linux & cpu=x64 - languageName: node - linkType: hard - -"@esbuild/netbsd-arm64@npm:0.25.1": - version: 0.25.1 - resolution: "@esbuild/netbsd-arm64@npm:0.25.1" - conditions: os=netbsd & cpu=arm64 - languageName: node - linkType: hard - -"@esbuild/netbsd-arm64@npm:0.27.4": - version: 0.27.4 - resolution: "@esbuild/netbsd-arm64@npm:0.27.4" - conditions: os=netbsd & cpu=arm64 - languageName: node - linkType: hard - -"@esbuild/netbsd-x64@npm:0.25.1": - version: 0.25.1 - resolution: "@esbuild/netbsd-x64@npm:0.25.1" - conditions: os=netbsd & cpu=x64 - languageName: node - linkType: hard - -"@esbuild/netbsd-x64@npm:0.27.4": - version: 0.27.4 - resolution: "@esbuild/netbsd-x64@npm:0.27.4" - conditions: os=netbsd & cpu=x64 - languageName: node - linkType: hard - -"@esbuild/openbsd-arm64@npm:0.25.1": - version: 0.25.1 - resolution: "@esbuild/openbsd-arm64@npm:0.25.1" - conditions: os=openbsd & cpu=arm64 - languageName: node - linkType: hard - -"@esbuild/openbsd-arm64@npm:0.27.4": - version: 0.27.4 - resolution: "@esbuild/openbsd-arm64@npm:0.27.4" - conditions: os=openbsd & cpu=arm64 - languageName: node - linkType: hard - -"@esbuild/openbsd-x64@npm:0.25.1": - version: 0.25.1 - resolution: "@esbuild/openbsd-x64@npm:0.25.1" - conditions: os=openbsd & cpu=x64 - languageName: node - linkType: hard - -"@esbuild/openbsd-x64@npm:0.27.4": - version: 0.27.4 - resolution: "@esbuild/openbsd-x64@npm:0.27.4" - conditions: os=openbsd & cpu=x64 - languageName: node - linkType: hard - -"@esbuild/openharmony-arm64@npm:0.27.4": - version: 0.27.4 - resolution: "@esbuild/openharmony-arm64@npm:0.27.4" - conditions: os=openharmony & cpu=arm64 - languageName: node - linkType: hard - -"@esbuild/sunos-x64@npm:0.25.1": - version: 0.25.1 - resolution: "@esbuild/sunos-x64@npm:0.25.1" - conditions: os=sunos & cpu=x64 - languageName: node - linkType: hard - -"@esbuild/sunos-x64@npm:0.27.4": - version: 0.27.4 - resolution: "@esbuild/sunos-x64@npm:0.27.4" - conditions: os=sunos & cpu=x64 - languageName: node - linkType: hard - -"@esbuild/win32-arm64@npm:0.25.1": - version: 0.25.1 - resolution: "@esbuild/win32-arm64@npm:0.25.1" - conditions: os=win32 & cpu=arm64 - languageName: node - linkType: hard - -"@esbuild/win32-arm64@npm:0.27.4": - version: 0.27.4 - resolution: "@esbuild/win32-arm64@npm:0.27.4" - conditions: os=win32 & cpu=arm64 - languageName: node - linkType: hard - -"@esbuild/win32-ia32@npm:0.25.1": - version: 0.25.1 - resolution: "@esbuild/win32-ia32@npm:0.25.1" - conditions: os=win32 & cpu=ia32 - languageName: node - linkType: hard - -"@esbuild/win32-ia32@npm:0.27.4": - version: 0.27.4 - resolution: "@esbuild/win32-ia32@npm:0.27.4" - conditions: os=win32 & cpu=ia32 - languageName: node - linkType: hard - -"@esbuild/win32-x64@npm:0.25.1": - version: 0.25.1 - resolution: "@esbuild/win32-x64@npm:0.25.1" - conditions: os=win32 & cpu=x64 - languageName: node - linkType: hard - -"@esbuild/win32-x64@npm:0.27.4": - version: 0.27.4 - resolution: "@esbuild/win32-x64@npm:0.27.4" - conditions: os=win32 & cpu=x64 - languageName: node - linkType: hard - -"@eslint-community/eslint-utils@npm:^4.2.0": - version: 4.4.0 - resolution: "@eslint-community/eslint-utils@npm:4.4.0" - dependencies: - eslint-visitor-keys: "npm:^3.3.0" - peerDependencies: - eslint: ^6.0.0 || ^7.0.0 || >=8.0.0 - checksum: 10c0/7e559c4ce59cd3a06b1b5a517b593912e680a7f981ae7affab0d01d709e99cd5647019be8fafa38c350305bc32f1f7d42c7073edde2ab536c745e365f37b607e - languageName: node - linkType: hard - -"@eslint-community/eslint-utils@npm:^4.4.0": - version: 4.4.1 - resolution: "@eslint-community/eslint-utils@npm:4.4.1" - dependencies: - eslint-visitor-keys: "npm:^3.4.3" - peerDependencies: - eslint: ^6.0.0 || ^7.0.0 || >=8.0.0 - checksum: 10c0/2aa0ac2fc50ff3f234408b10900ed4f1a0b19352f21346ad4cc3d83a1271481bdda11097baa45d484dd564c895e0762a27a8240be7a256b3ad47129e96528252 - languageName: node - linkType: hard - -"@eslint-community/eslint-utils@npm:^4.9.1": - version: 4.9.1 - resolution: "@eslint-community/eslint-utils@npm:4.9.1" - dependencies: - eslint-visitor-keys: "npm:^3.4.3" - peerDependencies: - eslint: ^6.0.0 || ^7.0.0 || >=8.0.0 - checksum: 10c0/dc4ab5e3e364ef27e33666b11f4b86e1a6c1d7cbf16f0c6ff87b1619b3562335e9201a3d6ce806221887ff780ec9d828962a290bb910759fd40a674686503f02 - languageName: node - linkType: hard - -"@eslint-community/regexpp@npm:^4.12.2, @eslint-community/regexpp@npm:^4.6.1": - version: 4.12.2 - resolution: "@eslint-community/regexpp@npm:4.12.2" - checksum: 10c0/fddcbc66851b308478d04e302a4d771d6917a0b3740dc351513c0da9ca2eab8a1adf99f5e0aa7ab8b13fa0df005c81adeee7e63a92f3effd7d367a163b721c2d - languageName: node - linkType: hard - -"@eslint/eslintrc@npm:^2.1.4": - version: 2.1.4 - resolution: "@eslint/eslintrc@npm:2.1.4" - dependencies: - ajv: "npm:^6.12.4" - debug: "npm:^4.3.2" - espree: "npm:^9.6.0" - globals: "npm:^13.19.0" - ignore: "npm:^5.2.0" - import-fresh: "npm:^3.2.1" - js-yaml: "npm:^4.1.0" - minimatch: "npm:^3.1.2" - strip-json-comments: "npm:^3.1.1" - checksum: 10c0/32f67052b81768ae876c84569ffd562491ec5a5091b0c1e1ca1e0f3c24fb42f804952fdd0a137873bc64303ba368a71ba079a6f691cee25beee9722d94cc8573 - languageName: node - linkType: hard - -"@eslint/js@npm:8.57.1": - version: 8.57.1 - resolution: "@eslint/js@npm:8.57.1" - checksum: 10c0/b489c474a3b5b54381c62e82b3f7f65f4b8a5eaaed126546520bf2fede5532a8ed53212919fed1e9048dcf7f37167c8561d58d0ba4492a4244004e7793805223 - languageName: node - linkType: hard - -"@fastify/busboy@npm:^2.0.0": - version: 2.1.1 - resolution: "@fastify/busboy@npm:2.1.1" - checksum: 10c0/6f8027a8cba7f8f7b736718b013f5a38c0476eea67034c94a0d3c375e2b114366ad4419e6a6fa7ffc2ef9c6d3e0435d76dd584a7a1cbac23962fda7650b579e3 - languageName: node - linkType: hard - -"@floating-ui/core@npm:^1.6.0": - version: 1.6.9 - resolution: "@floating-ui/core@npm:1.6.9" - dependencies: - "@floating-ui/utils": "npm:^0.2.9" - checksum: 10c0/77debdfc26bc36c6f5ae1f26ab3c15468215738b3f5682af4e1915602fa21ba33ad210273f31c9d2da1c531409929e1afb1138b1608c6b54a0f5853ee84c340d - languageName: node - linkType: hard - -"@floating-ui/core@npm:^1.7.3": - version: 1.7.3 - resolution: "@floating-ui/core@npm:1.7.3" - dependencies: - "@floating-ui/utils": "npm:^0.2.10" - checksum: 10c0/edfc23800122d81df0df0fb780b7328ae6c5f00efbb55bd48ea340f4af8c5b3b121ceb4bb81220966ab0f87b443204d37105abdd93d94846468be3243984144c - languageName: node - linkType: hard - -"@floating-ui/dom@npm:1.7.4": - version: 1.7.4 - resolution: "@floating-ui/dom@npm:1.7.4" - dependencies: - "@floating-ui/core": "npm:^1.7.3" - "@floating-ui/utils": "npm:^0.2.10" - checksum: 10c0/da6166c25f9b0729caa9f498685a73a0e28251613b35d27db8de8014bc9d045158a23c092b405321a3d67c2064909b6e2a7e6c1c9cc0f62967dca5779f5aef30 - languageName: node - linkType: hard - -"@floating-ui/dom@npm:^1.0.0": - version: 1.6.13 - resolution: "@floating-ui/dom@npm:1.6.13" - dependencies: - "@floating-ui/core": "npm:^1.6.0" - "@floating-ui/utils": "npm:^0.2.9" - checksum: 10c0/272242d2eb6238ffcee0cb1f3c66e0eafae804d5d7b449db5ecf904bc37d31ad96cf575a9e650b93c1190f64f49a684b1559d10e05ed3ec210628b19116991a9 - languageName: node - linkType: hard - -"@floating-ui/react-dom@npm:^2.0.0, @floating-ui/react-dom@npm:^2.1.2": - version: 2.1.2 - resolution: "@floating-ui/react-dom@npm:2.1.2" - dependencies: - "@floating-ui/dom": "npm:^1.0.0" - peerDependencies: - react: ">=16.8.0" - react-dom: ">=16.8.0" - checksum: 10c0/e855131c74e68cab505f7f44f92cd4e2efab1c125796db3116c54c0859323adae4bf697bf292ee83ac77b9335a41ad67852193d7aeace90aa2e1c4a640cafa60 - languageName: node - linkType: hard - -"@floating-ui/react@npm:^0.27.0": - version: 0.27.3 - resolution: "@floating-ui/react@npm:0.27.3" - dependencies: - "@floating-ui/react-dom": "npm:^2.1.2" - "@floating-ui/utils": "npm:^0.2.9" - tabbable: "npm:^6.0.0" - peerDependencies: - react: ">=17.0.0" - react-dom: ">=17.0.0" - checksum: 10c0/9ebc4e82af905cfafeb5cde1dfbc15a2541d4eaaf1e13fb6b8acbb9f0c3535a7c331b8dee3ab5bb03acb21716ee2ab155629a6c14c3227cf959bf8ad92594539 - languageName: node - linkType: hard - -"@floating-ui/utils@npm:^0.2.10": - version: 0.2.10 - resolution: "@floating-ui/utils@npm:0.2.10" - checksum: 10c0/e9bc2a1730ede1ee25843937e911ab6e846a733a4488623cd353f94721b05ec2c9ec6437613a2ac9379a94c2fd40c797a2ba6fa1df2716f5ce4aa6ddb1cf9ea4 - languageName: node - linkType: hard - -"@floating-ui/utils@npm:^0.2.9": - version: 0.2.9 - resolution: "@floating-ui/utils@npm:0.2.9" - checksum: 10c0/48bbed10f91cb7863a796cc0d0e917c78d11aeb89f98d03fc38d79e7eb792224a79f538ed8a2d5d5584511d4ca6354ef35f1712659fd569868e342df4398ad6f - languageName: node - linkType: hard - -"@fontsource/inconsolata@npm:^5.1.0": - version: 5.2.8 - resolution: "@fontsource/inconsolata@npm:5.2.8" - checksum: 10c0/2d5788a41bc60d7d00e5ba75689241a5146a4f60a3ec79d14dd2a0a5aa1ec2e697aa6aed3d1c0564208d32916aea588535f16a57f7a775b554d7f9adb03ad64a - languageName: node - linkType: hard - -"@fontsource/inter@npm:^5.1.0": - version: 5.2.8 - resolution: "@fontsource/inter@npm:5.2.8" - checksum: 10c0/f737dd50005e4809887ba55ae0c9b7174216d6d14875d17a4fbb9a0ad75dec4265928b805a43fe16a23f14a878f1974a398bbfc84ad65c79fc4d4b9c3ea154e1 - languageName: node - linkType: hard - -"@formatjs/bigdecimal@npm:0.2.0": - version: 0.2.0 - resolution: "@formatjs/bigdecimal@npm:0.2.0" - checksum: 10c0/dec607e3d9d4b8c5d0474862e867726cbf322a24d543d5b2cbc3cab6fea187ac787a8e1a0e3df5ceef85a1ab9d58112a08bb7af40b1b3a3b00670431b0603510 - languageName: node - linkType: hard - -"@formatjs/ecma402-abstract@npm:2.3.6": - version: 2.3.6 - resolution: "@formatjs/ecma402-abstract@npm:2.3.6" - dependencies: - "@formatjs/fast-memoize": "npm:2.2.7" - "@formatjs/intl-localematcher": "npm:0.6.2" - decimal.js: "npm:^10.4.3" - tslib: "npm:^2.8.0" - checksum: 10c0/63be2a73d3168bf45ab5d50db58376e852db5652d89511ae6e44f1fa03ad96ebbfe9b06a1dfaa743db06e40eb7f33bd77530b9388289855cca79a0e3fc29eacf - languageName: node - linkType: hard - -"@formatjs/ecma402-abstract@npm:3.2.0": - version: 3.2.0 - resolution: "@formatjs/ecma402-abstract@npm:3.2.0" - dependencies: - "@formatjs/bigdecimal": "npm:0.2.0" - "@formatjs/fast-memoize": "npm:3.1.1" - "@formatjs/intl-localematcher": "npm:0.8.2" - checksum: 10c0/b3c8ac881c3d7533fb4127ca3d771d2a32cb89e6efbbcc72d80b1dcc6a798494ace9ca5ee822b25eb08ebdc7ee2885a9e33496a436b40271ffc915ece605a3ce - languageName: node - linkType: hard - -"@formatjs/fast-memoize@npm:2.2.7": - version: 2.2.7 - resolution: "@formatjs/fast-memoize@npm:2.2.7" - dependencies: - tslib: "npm:^2.8.0" - checksum: 10c0/f5eabb0e4ab7162297df8252b4cfde194b23248120d9df267592eae2be2d2f7c4f670b5a70523d91b4ecdc35d40e65823bb8eeba8dd79fbf8601a972bf3b8866 - languageName: node - linkType: hard - -"@formatjs/fast-memoize@npm:3.1.1": - version: 3.1.1 - resolution: "@formatjs/fast-memoize@npm:3.1.1" - checksum: 10c0/79b24dc1389a49b2b2fb9e90a2ba922a4057d4b74e7bc33a3811f0dc94a5a868d28e8e37917b68c2f831070d11dfd0889de686f269bf5214085a44efc1c25a8c - languageName: node - linkType: hard - -"@formatjs/intl-durationformat@npm:^0.10.0": - version: 0.10.3 - resolution: "@formatjs/intl-durationformat@npm:0.10.3" - dependencies: - "@formatjs/ecma402-abstract": "npm:3.2.0" - "@formatjs/intl-localematcher": "npm:0.8.2" - checksum: 10c0/dced7b22ad11b83955a3cf60bfcad8b1853ea522cefa70f20c3e1c3607df839f7e388c1f0294fc15375b777ddd0a1d9828e9a19691c4593bb331a6a30d28882e - languageName: node - linkType: hard - -"@formatjs/intl-localematcher@npm:0.6.2": - version: 0.6.2 - resolution: "@formatjs/intl-localematcher@npm:0.6.2" - dependencies: - tslib: "npm:^2.8.0" - checksum: 10c0/22a17a4c67160b6c9f52667914acfb7b79cd6d80630d4ac6d4599ce447cb89d2a64f7d58fa35c3145ddb37fef893f0a45b9a55e663a4eb1f2ae8b10a89fac235 - languageName: node - linkType: hard - -"@formatjs/intl-localematcher@npm:0.8.2": - version: 0.8.2 - resolution: "@formatjs/intl-localematcher@npm:0.8.2" - dependencies: - "@formatjs/fast-memoize": "npm:3.1.1" - checksum: 10c0/3bf838a018184837b167964849dafdcdeac95531a24f4df7d868638d4ad716854a250e9bccac9ab4568264c0db7470e70b99363da1db308fdc882b87f3eca651 - languageName: node - linkType: hard - -"@formatjs/intl-segmenter@npm:^11.7.3": - version: 11.7.12 - resolution: "@formatjs/intl-segmenter@npm:11.7.12" - dependencies: - "@formatjs/ecma402-abstract": "npm:2.3.6" - "@formatjs/intl-localematcher": "npm:0.6.2" - tslib: "npm:^2.8.0" - checksum: 10c0/5ab30a9b9e9a63b9c29c3b90a94e7e5eef958829ed0b03a0117998fe0c1e213546eeebe0636b4559d27db86868bffc5311e3619248a2416045c99de6982fa46a - languageName: node - linkType: hard - -"@gulpjs/to-absolute-glob@npm:^4.0.0": - version: 4.0.0 - resolution: "@gulpjs/to-absolute-glob@npm:4.0.0" - dependencies: - is-negated-glob: "npm:^1.0.0" - checksum: 10c0/acddf10466bfff672e7d09d5b7d9fb2d9d50dff3bcf6d4cc3b3df364ea0ccad6e7a8d8ba0f474f880ff18a76ebbcc09b3f4d6d12d2913e3469361d5539a72110 - languageName: node - linkType: hard - -"@humanwhocodes/config-array@npm:^0.13.0": - version: 0.13.0 - resolution: "@humanwhocodes/config-array@npm:0.13.0" - dependencies: - "@humanwhocodes/object-schema": "npm:^2.0.3" - debug: "npm:^4.3.1" - minimatch: "npm:^3.0.5" - checksum: 10c0/205c99e756b759f92e1f44a3dc6292b37db199beacba8f26c2165d4051fe73a4ae52fdcfd08ffa93e7e5cb63da7c88648f0e84e197d154bbbbe137b2e0dd332e - languageName: node - linkType: hard - -"@humanwhocodes/module-importer@npm:^1.0.1": - version: 1.0.1 - resolution: "@humanwhocodes/module-importer@npm:1.0.1" - checksum: 10c0/909b69c3b86d482c26b3359db16e46a32e0fb30bd306a3c176b8313b9e7313dba0f37f519de6aa8b0a1921349e505f259d19475e123182416a506d7f87e7f529 - languageName: node - linkType: hard - -"@humanwhocodes/object-schema@npm:^2.0.3": - version: 2.0.3 - resolution: "@humanwhocodes/object-schema@npm:2.0.3" - checksum: 10c0/80520eabbfc2d32fe195a93557cef50dfe8c8905de447f022675aaf66abc33ae54098f5ea78548d925aa671cd4ab7c7daa5ad704fe42358c9b5e7db60f80696c - languageName: node - linkType: hard - -"@isaacs/cliui@npm:^8.0.2": - version: 8.0.2 - resolution: "@isaacs/cliui@npm:8.0.2" - dependencies: - string-width: "npm:^5.1.2" - string-width-cjs: "npm:string-width@^4.2.0" - strip-ansi: "npm:^7.0.1" - strip-ansi-cjs: "npm:strip-ansi@^6.0.1" - wrap-ansi: "npm:^8.1.0" - wrap-ansi-cjs: "npm:wrap-ansi@^7.0.0" - checksum: 10c0/b1bf42535d49f11dc137f18d5e4e63a28c5569de438a221c369483731e9dac9fb797af554e8bf02b6192d1e5eba6e6402cf93900c3d0ac86391d00d04876789e - languageName: node - linkType: hard - -"@isaacs/fs-minipass@npm:^4.0.0": - version: 4.0.1 - resolution: "@isaacs/fs-minipass@npm:4.0.1" - dependencies: - minipass: "npm:^7.0.4" - checksum: 10c0/c25b6dc1598790d5b55c0947a9b7d111cfa92594db5296c3b907e2f533c033666f692a3939eadac17b1c7c40d362d0b0635dc874cbfe3e70db7c2b07cc97a5d2 - languageName: node - linkType: hard - -"@joshwooding/vite-plugin-react-docgen-typescript@npm:^0.6.4": - version: 0.6.4 - resolution: "@joshwooding/vite-plugin-react-docgen-typescript@npm:0.6.4" - dependencies: - glob: "npm:^13.0.1" - react-docgen-typescript: "npm:^2.2.2" - peerDependencies: - typescript: ">= 4.3.x" - vite: ^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 - peerDependenciesMeta: - typescript: - optional: true - checksum: 10c0/73149b2d41d5b8eff7dfe4d037a6903fe4123ae46f3928d88535020539f44159c4ea1b342e6a77d4c14219f2f743fea0ef96e81279cce8b6d247dc4d582e27ed - languageName: node - linkType: hard - -"@jridgewell/gen-mapping@npm:^0.3.12": - version: 0.3.12 - resolution: "@jridgewell/gen-mapping@npm:0.3.12" - dependencies: - "@jridgewell/sourcemap-codec": "npm:^1.5.0" - "@jridgewell/trace-mapping": "npm:^0.3.24" - checksum: 10c0/32f771ae2467e4d440be609581f7338d786d3d621bac3469e943b9d6d116c23c4becb36f84898a92bbf2f3c0511365c54a945a3b86a83141547a2a360a5ec0c7 - languageName: node - linkType: hard - -"@jridgewell/gen-mapping@npm:^0.3.5": - version: 0.3.8 - resolution: "@jridgewell/gen-mapping@npm:0.3.8" - dependencies: - "@jridgewell/set-array": "npm:^1.2.1" - "@jridgewell/sourcemap-codec": "npm:^1.4.10" - "@jridgewell/trace-mapping": "npm:^0.3.24" - checksum: 10c0/c668feaf86c501d7c804904a61c23c67447b2137b813b9ce03eca82cb9d65ac7006d766c218685d76e3d72828279b6ee26c347aa1119dab23fbaf36aed51585a - languageName: node - linkType: hard - -"@jridgewell/remapping@npm:^2.3.5": - version: 2.3.5 - resolution: "@jridgewell/remapping@npm:2.3.5" - dependencies: - "@jridgewell/gen-mapping": "npm:^0.3.5" - "@jridgewell/trace-mapping": "npm:^0.3.24" - checksum: 10c0/3de494219ffeb2c5c38711d0d7bb128097edf91893090a2dbc8ee0b55d092bb7347b1fd0f478486c5eab010e855c73927b1666f2107516d472d24a73017d1194 - languageName: node - linkType: hard - -"@jridgewell/resolve-uri@npm:^3.1.0": - version: 3.1.2 - resolution: "@jridgewell/resolve-uri@npm:3.1.2" - checksum: 10c0/d502e6fb516b35032331406d4e962c21fe77cdf1cbdb49c6142bcbd9e30507094b18972778a6e27cbad756209cfe34b1a27729e6fa08a2eb92b33943f680cf1e - languageName: node - linkType: hard - -"@jridgewell/set-array@npm:^1.2.1": - version: 1.2.1 - resolution: "@jridgewell/set-array@npm:1.2.1" - checksum: 10c0/2a5aa7b4b5c3464c895c802d8ae3f3d2b92fcbe84ad12f8d0bfbb1f5ad006717e7577ee1fd2eac00c088abe486c7adb27976f45d2941ff6b0b92b2c3302c60f4 - languageName: node - linkType: hard - -"@jridgewell/source-map@npm:^0.3.3": - version: 0.3.6 - resolution: "@jridgewell/source-map@npm:0.3.6" - dependencies: - "@jridgewell/gen-mapping": "npm:^0.3.5" - "@jridgewell/trace-mapping": "npm:^0.3.25" - checksum: 10c0/6a4ecc713ed246ff8e5bdcc1ef7c49aaa93f7463d948ba5054dda18b02dcc6a055e2828c577bcceee058f302ce1fc95595713d44f5c45e43d459f88d267f2f04 - languageName: node - linkType: hard - -"@jridgewell/sourcemap-codec@npm:^1.4.10, @jridgewell/sourcemap-codec@npm:^1.4.14, @jridgewell/sourcemap-codec@npm:^1.4.15, @jridgewell/sourcemap-codec@npm:^1.5.0": - version: 1.5.0 - resolution: "@jridgewell/sourcemap-codec@npm:1.5.0" - checksum: 10c0/2eb864f276eb1096c3c11da3e9bb518f6d9fc0023c78344cdc037abadc725172c70314bdb360f2d4b7bffec7f5d657ce006816bc5d4ecb35e61b66132db00c18 - languageName: node - linkType: hard - -"@jridgewell/sourcemap-codec@npm:^1.5.5": - version: 1.5.5 - resolution: "@jridgewell/sourcemap-codec@npm:1.5.5" - checksum: 10c0/f9e538f302b63c0ebc06eecb1dd9918dd4289ed36147a0ddce35d6ea4d7ebbda243cda7b2213b6a5e1d8087a298d5cf630fb2bd39329cdecb82017023f6081a0 - languageName: node - linkType: hard - -"@jridgewell/trace-mapping@npm:^0.3.24, @jridgewell/trace-mapping@npm:^0.3.25": - version: 0.3.25 - resolution: "@jridgewell/trace-mapping@npm:0.3.25" - dependencies: - "@jridgewell/resolve-uri": "npm:^3.1.0" - "@jridgewell/sourcemap-codec": "npm:^1.4.14" - checksum: 10c0/3d1ce6ebc69df9682a5a8896b414c6537e428a1d68b02fcc8363b04284a8ca0df04d0ee3013132252ab14f2527bc13bea6526a912ecb5658f0e39fd2860b4df4 - languageName: node - linkType: hard - -"@jridgewell/trace-mapping@npm:^0.3.28": - version: 0.3.29 - resolution: "@jridgewell/trace-mapping@npm:0.3.29" - dependencies: - "@jridgewell/resolve-uri": "npm:^3.1.0" - "@jridgewell/sourcemap-codec": "npm:^1.4.14" - checksum: 10c0/fb547ba31658c4d74eb17e7389f4908bf7c44cef47acb4c5baa57289daf68e6fe53c639f41f751b3923aca67010501264f70e7b49978ad1f040294b22c37b333 - languageName: node - linkType: hard - -"@jridgewell/trace-mapping@npm:^0.3.31": - version: 0.3.31 - resolution: "@jridgewell/trace-mapping@npm:0.3.31" - dependencies: - "@jridgewell/resolve-uri": "npm:^3.1.0" - "@jridgewell/sourcemap-codec": "npm:^1.4.14" - checksum: 10c0/4b30ec8cd56c5fd9a661f088230af01e0c1a3888d11ffb6b47639700f71225be21d1f7e168048d6d4f9449207b978a235c07c8f15c07705685d16dc06280e9d9 - languageName: node - linkType: hard - -"@livekit/components-core@npm:0.12.13, @livekit/components-core@npm:^0.12.0": - version: 0.12.13 - resolution: "@livekit/components-core@npm:0.12.13" - dependencies: - "@floating-ui/dom": "npm:1.7.4" - loglevel: "npm:1.9.1" - rxjs: "npm:7.8.2" - peerDependencies: - livekit-client: ^2.17.2 - tslib: ^2.6.2 - checksum: 10c0/d6e0b897e4eaeacf42b2845ddcebd03b35c3877ab99ed92152f58ee46b4f334e540542ef35846718a39fe51fbad4264e91f2c1264f0e42a083c261c510013f91 - languageName: node - linkType: hard - -"@livekit/components-react@npm:^2.0.0": - version: 2.9.20 - resolution: "@livekit/components-react@npm:2.9.20" - dependencies: - "@livekit/components-core": "npm:0.12.13" - clsx: "npm:2.1.1" - events: "npm:^3.3.0" - jose: "npm:^6.0.12" - usehooks-ts: "npm:3.1.1" - peerDependencies: - "@livekit/krisp-noise-filter": ^0.2.12 || ^0.3.0 - livekit-client: ^2.17.2 - react: ">=18" - react-dom: ">=18" - tslib: ^2.6.2 - peerDependenciesMeta: - "@livekit/krisp-noise-filter": - optional: true - checksum: 10c0/ce00fb59446804571ad5534cdd7ce18315f96daab491ab60b7f7b27d26978f7a06a23495b89578385cd0d42b99a1ddbbd8699d0a3a82f00b2e77875f460387af - languageName: node - linkType: hard - -"@livekit/mutex@npm:1.1.1": - version: 1.1.1 - resolution: "@livekit/mutex@npm:1.1.1" - checksum: 10c0/d4bb1bd34e20939dfc8af0ae10b86918f3944336d0236d219e80a8c554207e8bfaf21e86794f0c56d2c28b43d74ca966111172a95eacb0e12b72133dd184d49a - languageName: node - linkType: hard - -"@livekit/protocol@npm:1.45.3, @livekit/protocol@npm:^1.42.2": - version: 1.45.3 - resolution: "@livekit/protocol@npm:1.45.3" - dependencies: - "@bufbuild/protobuf": "npm:^1.10.0" - checksum: 10c0/8c9c889d9042d3b27acc0dd537df36e0c804c1d205741e2d3789111c728d840933ab0743655cb81df52c7715210db193c1fc8e2e223d765d05537c502918299b - languageName: node - linkType: hard - -"@livekit/track-processors@npm:^0.7.1": - version: 0.7.2 - resolution: "@livekit/track-processors@npm:0.7.2" - dependencies: - "@mediapipe/tasks-vision": "npm:0.10.14" - peerDependencies: - "@types/dom-mediacapture-transform": ^0.1.9 - livekit-client: ^1.12.0 || ^2.1.0 - checksum: 10c0/d5638942205ea05a507254f61157696881332b866ff538d1e93bd2267c31ce80c9a81dfc4f8c4b7c96910452b13511ee06be1ae7ab30c299b73fe04baf80a673 - languageName: node - linkType: hard - -"@matrix-org/matrix-sdk-crypto-wasm@npm:^17.0.0": - version: 17.0.0 - resolution: "@matrix-org/matrix-sdk-crypto-wasm@npm:17.0.0" - checksum: 10c0/fa97e3111099057e0953e7550d6556b6e7553f3badd5b25a6988d2fcc94d22288a27e63cb204771b74ff24388d770c83f2cf5aec583f05c6ecf46509b8020570 - languageName: node - linkType: hard - -"@mdx-js/react@npm:^3.0.0": - version: 3.1.1 - resolution: "@mdx-js/react@npm:3.1.1" - dependencies: - "@types/mdx": "npm:^2.0.0" - peerDependencies: - "@types/react": ">=16" - react: ">=16" - checksum: 10c0/34ca98bc2a0f969894ea144dc5c8a5294690505458cd24965cd9be854d779c193ad9192bf9143c4c18438fafd1902e100d99067e045c69319288562d497558c6 - languageName: node - linkType: hard - -"@mediapipe/tasks-vision@npm:^0.10.18": - version: 0.10.34 - resolution: "@mediapipe/tasks-vision@npm:0.10.34" - checksum: 10c0/7acc1028be2384d0e90dc96e303f01fc5c072d9a25d39a8d157b8576de15ec6e1bf28e31a5f38279fba5aec99197b4be75c058c219d83b5e7aaf85ee0413f124 - languageName: node - linkType: hard - -"@napi-rs/wasm-runtime@npm:^1.1.1": - version: 1.1.1 - resolution: "@napi-rs/wasm-runtime@npm:1.1.1" - dependencies: - "@emnapi/core": "npm:^1.7.1" - "@emnapi/runtime": "npm:^1.7.1" - "@tybys/wasm-util": "npm:^0.10.1" - checksum: 10c0/04d57b67e80736e41fe44674a011878db0a8ad893f4d44abb9d3608debb7c174224cba2796ed5b0c1d367368159f3ca6be45f1c59222f70e32ddc880f803d447 - languageName: node - linkType: hard - -"@nodelib/fs.scandir@npm:2.1.5": - version: 2.1.5 - resolution: "@nodelib/fs.scandir@npm:2.1.5" - dependencies: - "@nodelib/fs.stat": "npm:2.0.5" - run-parallel: "npm:^1.1.9" - checksum: 10c0/732c3b6d1b1e967440e65f284bd06e5821fedf10a1bea9ed2bb75956ea1f30e08c44d3def9d6a230666574edbaf136f8cfd319c14fd1f87c66e6a44449afb2eb - languageName: node - linkType: hard - -"@nodelib/fs.stat@npm:2.0.5, @nodelib/fs.stat@npm:^2.0.2": - version: 2.0.5 - resolution: "@nodelib/fs.stat@npm:2.0.5" - checksum: 10c0/88dafe5e3e29a388b07264680dc996c17f4bda48d163a9d4f5c1112979f0ce8ec72aa7116122c350b4e7976bc5566dc3ddb579be1ceaacc727872eb4ed93926d - languageName: node - linkType: hard - -"@nodelib/fs.walk@npm:^1.2.3, @nodelib/fs.walk@npm:^1.2.8": - version: 1.2.8 - resolution: "@nodelib/fs.walk@npm:1.2.8" - dependencies: - "@nodelib/fs.scandir": "npm:2.1.5" - fastq: "npm:^1.6.0" - checksum: 10c0/db9de047c3bb9b51f9335a7bb46f4fcfb6829fb628318c12115fbaf7d369bfce71c15b103d1fc3b464812d936220ee9bc1c8f762d032c9f6be9acc99249095b1 - languageName: node - linkType: hard - -"@npmcli/agent@npm:^3.0.0": - version: 3.0.0 - resolution: "@npmcli/agent@npm:3.0.0" - dependencies: - agent-base: "npm:^7.1.0" - http-proxy-agent: "npm:^7.0.0" - https-proxy-agent: "npm:^7.0.1" - lru-cache: "npm:^10.0.1" - socks-proxy-agent: "npm:^8.0.3" - checksum: 10c0/efe37b982f30740ee77696a80c196912c274ecd2cb243bc6ae7053a50c733ce0f6c09fda085145f33ecf453be19654acca74b69e81eaad4c90f00ccffe2f9271 - languageName: node - linkType: hard - -"@npmcli/fs@npm:^4.0.0": - version: 4.0.0 - resolution: "@npmcli/fs@npm:4.0.0" - dependencies: - semver: "npm:^7.3.5" - checksum: 10c0/c90935d5ce670c87b6b14fab04a965a3b8137e585f8b2a6257263bd7f97756dd736cb165bb470e5156a9e718ecd99413dccc54b1138c1a46d6ec7cf325982fe5 - languageName: node - linkType: hard - -"@octokit/auth-token@npm:^4.0.0": - version: 4.0.0 - resolution: "@octokit/auth-token@npm:4.0.0" - checksum: 10c0/57acaa6c394c5abab2f74e8e1dcf4e7a16b236f713c77a54b8f08e2d14114de94b37946259e33ec2aab0566b26f724c2b71d2602352b59e541a9854897618f3c - languageName: node - linkType: hard - -"@octokit/core@npm:^5.0.1": - version: 5.2.0 - resolution: "@octokit/core@npm:5.2.0" - dependencies: - "@octokit/auth-token": "npm:^4.0.0" - "@octokit/graphql": "npm:^7.1.0" - "@octokit/request": "npm:^8.3.1" - "@octokit/request-error": "npm:^5.1.0" - "@octokit/types": "npm:^13.0.0" - before-after-hook: "npm:^2.2.0" - universal-user-agent: "npm:^6.0.0" - checksum: 10c0/9dc5cf55b335da382f340ef74c8009c06a1f7157b0530d3ff6cacf179887811352dcd405448e37849d73f17b28970b7817995be2260ce902dad52b91905542f0 - languageName: node - linkType: hard - -"@octokit/endpoint@npm:^9.0.6": - version: 9.0.6 - resolution: "@octokit/endpoint@npm:9.0.6" - dependencies: - "@octokit/types": "npm:^13.1.0" - universal-user-agent: "npm:^6.0.0" - checksum: 10c0/8e06197b21869aeb498e0315093ca6fbee12bd1bdcfc1667fcd7d79d827d84f2c5a30702ffd28bba7879780e367d14c30df5b20d47fcaed5de5fdc05f5d4e013 - languageName: node - linkType: hard - -"@octokit/graphql@npm:^7.1.0": - version: 7.1.1 - resolution: "@octokit/graphql@npm:7.1.1" - dependencies: - "@octokit/request": "npm:^8.4.1" - "@octokit/types": "npm:^13.0.0" - universal-user-agent: "npm:^6.0.0" - checksum: 10c0/c27216200f3f4ce7ce2a694fb7ea43f8ea4a807fbee3a423c41ed137dd7948dfc0bbf6ea1656f029a7625c84b583acdef740a7032266d0eff55305c91c3a1ed6 - languageName: node - linkType: hard - -"@octokit/openapi-types@npm:^20.0.0": - version: 20.0.0 - resolution: "@octokit/openapi-types@npm:20.0.0" - checksum: 10c0/5176dcc3b9d182ede3d446750cfa5cf31139624785a73fcf3511e3102a802b4d7cc45e999c27ed91d73fe8b7d718c8c406facb48688926921a71fe603b7db95d - languageName: node - linkType: hard - -"@octokit/openapi-types@npm:^23.0.1": - version: 23.0.1 - resolution: "@octokit/openapi-types@npm:23.0.1" - checksum: 10c0/ab734ceb26343d9f051a59503b8cb5bdc7fec9ca044b60511b227179bec73141dd9144a6b2d68bcd737741881b136c1b7d5392da89ae2e35e39acc489e5eb4c1 - languageName: node - linkType: hard - -"@octokit/plugin-paginate-rest@npm:^9.0.0": - version: 9.2.2 - resolution: "@octokit/plugin-paginate-rest@npm:9.2.2" - dependencies: - "@octokit/types": "npm:^12.6.0" - peerDependencies: - "@octokit/core": 5 - checksum: 10c0/e9c85b17064fe6b62f9af88dba008f3daef456b1195340ea0831990e9c4dbabe89be950b6e5dc924ebcca18ad1aaa0cf6df7d824dc8be26ce9a55f20336ff815 - languageName: node - linkType: hard - -"@octokit/plugin-rest-endpoint-methods@npm:^10.0.0": - version: 10.4.1 - resolution: "@octokit/plugin-rest-endpoint-methods@npm:10.4.1" - dependencies: - "@octokit/types": "npm:^12.6.0" - peerDependencies: - "@octokit/core": 5 - checksum: 10c0/4b8f64c0f7fa12464546ad312a5289c2a799967e01e90e2c4923ec6e9604cf212dcb50d9795c9a688867f973c9c529c5950368564c560406c652bcd298f090af - languageName: node - linkType: hard - -"@octokit/request-error@npm:^5.1.0, @octokit/request-error@npm:^5.1.1": - version: 5.1.1 - resolution: "@octokit/request-error@npm:5.1.1" - dependencies: - "@octokit/types": "npm:^13.1.0" - deprecation: "npm:^2.0.0" - once: "npm:^1.4.0" - checksum: 10c0/dc9fc76ea5e4199273e4665ce9ddf345fe8f25578d9999c9a16f276298e61ee6fe0e6f5a6147b91ba3b34fdf5b9e6b7af6ae13d6333175e95b30c574088f7a2d - languageName: node - linkType: hard - -"@octokit/request@npm:^8.3.1, @octokit/request@npm:^8.4.1": - version: 8.4.1 - resolution: "@octokit/request@npm:8.4.1" - dependencies: - "@octokit/endpoint": "npm:^9.0.6" - "@octokit/request-error": "npm:^5.1.1" - "@octokit/types": "npm:^13.1.0" - universal-user-agent: "npm:^6.0.0" - checksum: 10c0/1a69dcb7336de708a296db9e9a58040e5b284a87495a63112f80eb0007da3fc96a9fadecb9e875fc63cf179c23a0f81031fbef2a6f610a219e45805ead03fcf3 - languageName: node - linkType: hard - -"@octokit/types@npm:^12.6.0": - version: 12.6.0 - resolution: "@octokit/types@npm:12.6.0" - dependencies: - "@octokit/openapi-types": "npm:^20.0.0" - checksum: 10c0/0bea58bda46c93287f5a80a0e52bc60e7dc7136b8a38c3569d63d073fb9df4a56acdb9d9bdba9978f37c374a4a6e3e52886ef5b08cace048adb0012cacef942c - languageName: node - linkType: hard - -"@octokit/types@npm:^13.0.0, @octokit/types@npm:^13.1.0": - version: 13.8.0 - resolution: "@octokit/types@npm:13.8.0" - dependencies: - "@octokit/openapi-types": "npm:^23.0.1" - checksum: 10c0/e08c2fcf10e374f18e4c9fa12a6ada33a40f112d1209012a39f0ce40ae7aa9dcf0598b6007b467f63cc4a97e7b1388d6eed34ddef61494655e08b5a95afaad97 - languageName: node - linkType: hard - -"@oxc-project/types@npm:=0.122.0": - version: 0.122.0 - resolution: "@oxc-project/types@npm:0.122.0" - checksum: 10c0/2c64dd0db949426fd0c86d4f61eded5902e7b7b166356a825bd3a248aeaa29a495f78918f66ab78e99644b67bd7556096e2a8123cec74ca4141c604f424f4f74 - languageName: node - linkType: hard - -"@oxc-resolver/binding-android-arm-eabi@npm:11.19.1": - version: 11.19.1 - resolution: "@oxc-resolver/binding-android-arm-eabi@npm:11.19.1" - conditions: os=android & cpu=arm - languageName: node - linkType: hard - -"@oxc-resolver/binding-android-arm64@npm:11.19.1": - version: 11.19.1 - resolution: "@oxc-resolver/binding-android-arm64@npm:11.19.1" - conditions: os=android & cpu=arm64 - languageName: node - linkType: hard - -"@oxc-resolver/binding-darwin-arm64@npm:11.19.1": - version: 11.19.1 - resolution: "@oxc-resolver/binding-darwin-arm64@npm:11.19.1" - conditions: os=darwin & cpu=arm64 - languageName: node - linkType: hard - -"@oxc-resolver/binding-darwin-x64@npm:11.19.1": - version: 11.19.1 - resolution: "@oxc-resolver/binding-darwin-x64@npm:11.19.1" - conditions: os=darwin & cpu=x64 - languageName: node - linkType: hard - -"@oxc-resolver/binding-freebsd-x64@npm:11.19.1": - version: 11.19.1 - resolution: "@oxc-resolver/binding-freebsd-x64@npm:11.19.1" - conditions: os=freebsd & cpu=x64 - languageName: node - linkType: hard - -"@oxc-resolver/binding-linux-arm-gnueabihf@npm:11.19.1": - version: 11.19.1 - resolution: "@oxc-resolver/binding-linux-arm-gnueabihf@npm:11.19.1" - conditions: os=linux & cpu=arm - languageName: node - linkType: hard - -"@oxc-resolver/binding-linux-arm-musleabihf@npm:11.19.1": - version: 11.19.1 - resolution: "@oxc-resolver/binding-linux-arm-musleabihf@npm:11.19.1" - conditions: os=linux & cpu=arm - languageName: node - linkType: hard - -"@oxc-resolver/binding-linux-arm64-gnu@npm:11.19.1": - version: 11.19.1 - resolution: "@oxc-resolver/binding-linux-arm64-gnu@npm:11.19.1" - conditions: os=linux & cpu=arm64 & libc=glibc - languageName: node - linkType: hard - -"@oxc-resolver/binding-linux-arm64-musl@npm:11.19.1": - version: 11.19.1 - resolution: "@oxc-resolver/binding-linux-arm64-musl@npm:11.19.1" - conditions: os=linux & cpu=arm64 & libc=musl - languageName: node - linkType: hard - -"@oxc-resolver/binding-linux-ppc64-gnu@npm:11.19.1": - version: 11.19.1 - resolution: "@oxc-resolver/binding-linux-ppc64-gnu@npm:11.19.1" - conditions: os=linux & cpu=ppc64 & libc=glibc - languageName: node - linkType: hard - -"@oxc-resolver/binding-linux-riscv64-gnu@npm:11.19.1": - version: 11.19.1 - resolution: "@oxc-resolver/binding-linux-riscv64-gnu@npm:11.19.1" - conditions: os=linux & cpu=riscv64 & libc=glibc - languageName: node - linkType: hard - -"@oxc-resolver/binding-linux-riscv64-musl@npm:11.19.1": - version: 11.19.1 - resolution: "@oxc-resolver/binding-linux-riscv64-musl@npm:11.19.1" - conditions: os=linux & cpu=riscv64 & libc=musl - languageName: node - linkType: hard - -"@oxc-resolver/binding-linux-s390x-gnu@npm:11.19.1": - version: 11.19.1 - resolution: "@oxc-resolver/binding-linux-s390x-gnu@npm:11.19.1" - conditions: os=linux & cpu=s390x & libc=glibc - languageName: node - linkType: hard - -"@oxc-resolver/binding-linux-x64-gnu@npm:11.19.1": - version: 11.19.1 - resolution: "@oxc-resolver/binding-linux-x64-gnu@npm:11.19.1" - conditions: os=linux & cpu=x64 & libc=glibc - languageName: node - linkType: hard - -"@oxc-resolver/binding-linux-x64-musl@npm:11.19.1": - version: 11.19.1 - resolution: "@oxc-resolver/binding-linux-x64-musl@npm:11.19.1" - conditions: os=linux & cpu=x64 & libc=musl - languageName: node - linkType: hard - -"@oxc-resolver/binding-openharmony-arm64@npm:11.19.1": - version: 11.19.1 - resolution: "@oxc-resolver/binding-openharmony-arm64@npm:11.19.1" - conditions: os=openharmony & cpu=arm64 - languageName: node - linkType: hard - -"@oxc-resolver/binding-wasm32-wasi@npm:11.19.1": - version: 11.19.1 - resolution: "@oxc-resolver/binding-wasm32-wasi@npm:11.19.1" - dependencies: - "@napi-rs/wasm-runtime": "npm:^1.1.1" - conditions: cpu=wasm32 - languageName: node - linkType: hard - -"@oxc-resolver/binding-win32-arm64-msvc@npm:11.19.1": - version: 11.19.1 - resolution: "@oxc-resolver/binding-win32-arm64-msvc@npm:11.19.1" - conditions: os=win32 & cpu=arm64 - languageName: node - linkType: hard - -"@oxc-resolver/binding-win32-ia32-msvc@npm:11.19.1": - version: 11.19.1 - resolution: "@oxc-resolver/binding-win32-ia32-msvc@npm:11.19.1" - conditions: os=win32 & cpu=ia32 - languageName: node - linkType: hard - -"@oxc-resolver/binding-win32-x64-msvc@npm:11.19.1": - version: 11.19.1 - resolution: "@oxc-resolver/binding-win32-x64-msvc@npm:11.19.1" - conditions: os=win32 & cpu=x64 - languageName: node - linkType: hard - -"@parcel/watcher-android-arm64@npm:2.5.1": - version: 2.5.1 - resolution: "@parcel/watcher-android-arm64@npm:2.5.1" - conditions: os=android & cpu=arm64 - languageName: node - linkType: hard - -"@parcel/watcher-darwin-arm64@npm:2.5.1": - version: 2.5.1 - resolution: "@parcel/watcher-darwin-arm64@npm:2.5.1" - conditions: os=darwin & cpu=arm64 - languageName: node - linkType: hard - -"@parcel/watcher-darwin-x64@npm:2.5.1": - version: 2.5.1 - resolution: "@parcel/watcher-darwin-x64@npm:2.5.1" - conditions: os=darwin & cpu=x64 - languageName: node - linkType: hard - -"@parcel/watcher-freebsd-x64@npm:2.5.1": - version: 2.5.1 - resolution: "@parcel/watcher-freebsd-x64@npm:2.5.1" - conditions: os=freebsd & cpu=x64 - languageName: node - linkType: hard - -"@parcel/watcher-linux-arm-glibc@npm:2.5.1": - version: 2.5.1 - resolution: "@parcel/watcher-linux-arm-glibc@npm:2.5.1" - conditions: os=linux & cpu=arm & libc=glibc - languageName: node - linkType: hard - -"@parcel/watcher-linux-arm-musl@npm:2.5.1": - version: 2.5.1 - resolution: "@parcel/watcher-linux-arm-musl@npm:2.5.1" - conditions: os=linux & cpu=arm & libc=musl - languageName: node - linkType: hard - -"@parcel/watcher-linux-arm64-glibc@npm:2.5.1": - version: 2.5.1 - resolution: "@parcel/watcher-linux-arm64-glibc@npm:2.5.1" - conditions: os=linux & cpu=arm64 & libc=glibc - languageName: node - linkType: hard - -"@parcel/watcher-linux-arm64-musl@npm:2.5.1": - version: 2.5.1 - resolution: "@parcel/watcher-linux-arm64-musl@npm:2.5.1" - conditions: os=linux & cpu=arm64 & libc=musl - languageName: node - linkType: hard - -"@parcel/watcher-linux-x64-glibc@npm:2.5.1": - version: 2.5.1 - resolution: "@parcel/watcher-linux-x64-glibc@npm:2.5.1" - conditions: os=linux & cpu=x64 & libc=glibc - languageName: node - linkType: hard - -"@parcel/watcher-linux-x64-musl@npm:2.5.1": - version: 2.5.1 - resolution: "@parcel/watcher-linux-x64-musl@npm:2.5.1" - conditions: os=linux & cpu=x64 & libc=musl - languageName: node - linkType: hard - -"@parcel/watcher-win32-arm64@npm:2.5.1": - version: 2.5.1 - resolution: "@parcel/watcher-win32-arm64@npm:2.5.1" - conditions: os=win32 & cpu=arm64 - languageName: node - linkType: hard - -"@parcel/watcher-win32-ia32@npm:2.5.1": - version: 2.5.1 - resolution: "@parcel/watcher-win32-ia32@npm:2.5.1" - conditions: os=win32 & cpu=ia32 - languageName: node - linkType: hard - -"@parcel/watcher-win32-x64@npm:2.5.1": - version: 2.5.1 - resolution: "@parcel/watcher-win32-x64@npm:2.5.1" - conditions: os=win32 & cpu=x64 - languageName: node - linkType: hard - -"@parcel/watcher@npm:^2.4.1": - version: 2.5.1 - resolution: "@parcel/watcher@npm:2.5.1" - dependencies: - "@parcel/watcher-android-arm64": "npm:2.5.1" - "@parcel/watcher-darwin-arm64": "npm:2.5.1" - "@parcel/watcher-darwin-x64": "npm:2.5.1" - "@parcel/watcher-freebsd-x64": "npm:2.5.1" - "@parcel/watcher-linux-arm-glibc": "npm:2.5.1" - "@parcel/watcher-linux-arm-musl": "npm:2.5.1" - "@parcel/watcher-linux-arm64-glibc": "npm:2.5.1" - "@parcel/watcher-linux-arm64-musl": "npm:2.5.1" - "@parcel/watcher-linux-x64-glibc": "npm:2.5.1" - "@parcel/watcher-linux-x64-musl": "npm:2.5.1" - "@parcel/watcher-win32-arm64": "npm:2.5.1" - "@parcel/watcher-win32-ia32": "npm:2.5.1" - "@parcel/watcher-win32-x64": "npm:2.5.1" - detect-libc: "npm:^1.0.3" - is-glob: "npm:^4.0.3" - micromatch: "npm:^4.0.5" - node-addon-api: "npm:^7.0.0" - node-gyp: "npm:latest" - dependenciesMeta: - "@parcel/watcher-android-arm64": - optional: true - "@parcel/watcher-darwin-arm64": - optional: true - "@parcel/watcher-darwin-x64": - optional: true - "@parcel/watcher-freebsd-x64": - optional: true - "@parcel/watcher-linux-arm-glibc": - optional: true - "@parcel/watcher-linux-arm-musl": - optional: true - "@parcel/watcher-linux-arm64-glibc": - optional: true - "@parcel/watcher-linux-arm64-musl": - optional: true - "@parcel/watcher-linux-x64-glibc": - optional: true - "@parcel/watcher-linux-x64-musl": - optional: true - "@parcel/watcher-win32-arm64": - optional: true - "@parcel/watcher-win32-ia32": - optional: true - "@parcel/watcher-win32-x64": - optional: true - checksum: 10c0/8f35073d0c0b34a63d4c8d2213482f0ebc6a25de7b2cdd415d19cb929964a793cb285b68d1d50bfb732b070b3c82a2fdb4eb9c250eab709a1cd9d63345455a82 - languageName: node - linkType: hard - -"@pkgjs/parseargs@npm:^0.11.0": - version: 0.11.0 - resolution: "@pkgjs/parseargs@npm:0.11.0" - checksum: 10c0/5bd7576bb1b38a47a7fc7b51ac9f38748e772beebc56200450c4a817d712232b8f1d3ef70532c80840243c657d491cf6a6be1e3a214cff907645819fdc34aadd - languageName: node - linkType: hard - -"@playwright/test@npm:^1.57.0": - version: 1.58.2 - resolution: "@playwright/test@npm:1.58.2" - dependencies: - playwright: "npm:1.58.2" - bin: - playwright: cli.js - checksum: 10c0/2164c03ad97c3653ff02e8818a71f3b2bbc344ac07924c9d8e31cd57505d6d37596015a41f51396b3ed8de6840f59143eaa9c21bf65515963da20740119811da - languageName: node - linkType: hard - -"@radix-ui/number@npm:1.1.1": - version: 1.1.1 - resolution: "@radix-ui/number@npm:1.1.1" - checksum: 10c0/0570ad92287398e8a7910786d7cee0a998174cdd6637ba61571992897c13204adf70b9ed02d0da2af554119411128e701d9c6b893420612897b438dc91db712b - languageName: node - linkType: hard - -"@radix-ui/primitive@npm:1.1.1": - version: 1.1.1 - resolution: "@radix-ui/primitive@npm:1.1.1" - checksum: 10c0/6457bd8d1aa4ecb948e5d2a2484fc570698b2ab472db6d915a8f1eec04823f80423efa60b5ba840f0693bec2ca380333cc5f3b52586b40f407d9f572f9261f8d - languageName: node - linkType: hard - -"@radix-ui/primitive@npm:1.1.3": - version: 1.1.3 - resolution: "@radix-ui/primitive@npm:1.1.3" - checksum: 10c0/88860165ee7066fa2c179f32ffcd3ee6d527d9dcdc0e8be85e9cb0e2c84834be8e3c1a976c74ba44b193f709544e12f54455d892b28e32f0708d89deda6b9f1d - languageName: node - linkType: hard - -"@radix-ui/react-arrow@npm:1.1.1": - version: 1.1.1 - resolution: "@radix-ui/react-arrow@npm:1.1.1" - dependencies: - "@radix-ui/react-primitive": "npm:2.0.1" - peerDependencies: - "@types/react": "*" - "@types/react-dom": "*" - react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - peerDependenciesMeta: - "@types/react": - optional: true - "@types/react-dom": - optional: true - checksum: 10c0/714c8420ee4497775a1119ceba1391a9e4fed07185ba903ade571251400fd25cedb7bebf2292ce778e74956dfa079078b2afbb67d12001c6ea5080997bcf3612 - languageName: node - linkType: hard - -"@radix-ui/react-arrow@npm:1.1.7": - version: 1.1.7 - resolution: "@radix-ui/react-arrow@npm:1.1.7" - dependencies: - "@radix-ui/react-primitive": "npm:2.1.3" - peerDependencies: - "@types/react": "*" - "@types/react-dom": "*" - react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - peerDependenciesMeta: - "@types/react": - optional: true - "@types/react-dom": - optional: true - checksum: 10c0/c3b46766238b3ee2a394d8806a5141432361bf1425110c9f0dcf480bda4ebd304453a53f294b5399c6ee3ccfcae6fd544921fd01ddc379cf5942acdd7168664b - languageName: node - linkType: hard - -"@radix-ui/react-collection@npm:1.1.1": - version: 1.1.1 - resolution: "@radix-ui/react-collection@npm:1.1.1" - dependencies: - "@radix-ui/react-compose-refs": "npm:1.1.1" - "@radix-ui/react-context": "npm:1.1.1" - "@radix-ui/react-primitive": "npm:2.0.1" - "@radix-ui/react-slot": "npm:1.1.1" - peerDependencies: - "@types/react": "*" - "@types/react-dom": "*" - react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - peerDependenciesMeta: - "@types/react": - optional: true - "@types/react-dom": - optional: true - checksum: 10c0/f01bba02e11944fa98f588a0c8dc7657228c9e7dd32ef66acdec6a540385c1e9471ef9e7dfa6184b524fdf923cf5a08892ffda3fe6d60cee34c690d9914373ce - languageName: node - linkType: hard - -"@radix-ui/react-collection@npm:1.1.7": - version: 1.1.7 - resolution: "@radix-ui/react-collection@npm:1.1.7" - dependencies: - "@radix-ui/react-compose-refs": "npm:1.1.2" - "@radix-ui/react-context": "npm:1.1.2" - "@radix-ui/react-primitive": "npm:2.1.3" - "@radix-ui/react-slot": "npm:1.2.3" - peerDependencies: - "@types/react": "*" - "@types/react-dom": "*" - react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - peerDependenciesMeta: - "@types/react": - optional: true - "@types/react-dom": - optional: true - checksum: 10c0/fa321a7300095508491f75414f02b243f0c3f179dc0728cfd115e2ea9f6f48f1516532b59f526d9ac81bbab63cd98a052074b4703ec0b9428fac945ebabec5fd - languageName: node - linkType: hard - -"@radix-ui/react-compose-refs@npm:1.1.1": - version: 1.1.1 - resolution: "@radix-ui/react-compose-refs@npm:1.1.1" - peerDependencies: - "@types/react": "*" - react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - peerDependenciesMeta: - "@types/react": - optional: true - checksum: 10c0/3e84580024e66e3cc5b9ae79355e787815c1d2a3c7d46e7f47900a29c33751ca24cf4ac8903314957ab1f7788aebe1687e2258641c188cf94653f7ddf8f70627 - languageName: node - linkType: hard - -"@radix-ui/react-compose-refs@npm:1.1.2": - version: 1.1.2 - resolution: "@radix-ui/react-compose-refs@npm:1.1.2" - peerDependencies: - "@types/react": "*" - react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - peerDependenciesMeta: - "@types/react": - optional: true - checksum: 10c0/d36a9c589eb75d634b9b139c80f916aadaf8a68a7c1c4b8c6c6b88755af1a92f2e343457042089f04cc3f23073619d08bb65419ced1402e9d4e299576d970771 - languageName: node - linkType: hard - -"@radix-ui/react-context-menu@npm:^2.2.16": - version: 2.2.16 - resolution: "@radix-ui/react-context-menu@npm:2.2.16" - dependencies: - "@radix-ui/primitive": "npm:1.1.3" - "@radix-ui/react-context": "npm:1.1.2" - "@radix-ui/react-menu": "npm:2.1.16" - "@radix-ui/react-primitive": "npm:2.1.3" - "@radix-ui/react-use-callback-ref": "npm:1.1.1" - "@radix-ui/react-use-controllable-state": "npm:1.2.2" - peerDependencies: - "@types/react": "*" - "@types/react-dom": "*" - react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - peerDependenciesMeta: - "@types/react": - optional: true - "@types/react-dom": - optional: true - checksum: 10c0/950f7559e65474a19145238cf44d744cb1e49be2221ff18436ba49b496b05ccf93bd3906aaa2c7ab76bc77daf694911a78442801e0053f57d2e57ebbfd281c49 - languageName: node - linkType: hard - -"@radix-ui/react-context@npm:1.1.1": - version: 1.1.1 - resolution: "@radix-ui/react-context@npm:1.1.1" - peerDependencies: - "@types/react": "*" - react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - peerDependenciesMeta: - "@types/react": - optional: true - checksum: 10c0/fc4ace9d79d7954c715ade765e06c95d7e1b12a63a536bcbe842fb904f03f88fc5bd6e38d44bd23243d37a270b4c44380fedddaeeae2d274f0b898a20665aba2 - languageName: node - linkType: hard - -"@radix-ui/react-context@npm:1.1.2": - version: 1.1.2 - resolution: "@radix-ui/react-context@npm:1.1.2" - peerDependencies: - "@types/react": "*" - react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - peerDependenciesMeta: - "@types/react": - optional: true - checksum: 10c0/cece731f8cc25d494c6589cc681e5c01a93867d895c75889973afa1a255f163c286e390baa7bc028858eaabe9f6b57270d0ca6377356f652c5557c1c7a41ccce - languageName: node - linkType: hard - -"@radix-ui/react-dialog@npm:^1.0.4, @radix-ui/react-dialog@npm:^1.1.1": - version: 1.1.15 - resolution: "@radix-ui/react-dialog@npm:1.1.15" - dependencies: - "@radix-ui/primitive": "npm:1.1.3" - "@radix-ui/react-compose-refs": "npm:1.1.2" - "@radix-ui/react-context": "npm:1.1.2" - "@radix-ui/react-dismissable-layer": "npm:1.1.11" - "@radix-ui/react-focus-guards": "npm:1.1.3" - "@radix-ui/react-focus-scope": "npm:1.1.7" - "@radix-ui/react-id": "npm:1.1.1" - "@radix-ui/react-portal": "npm:1.1.9" - "@radix-ui/react-presence": "npm:1.1.5" - "@radix-ui/react-primitive": "npm:2.1.3" - "@radix-ui/react-slot": "npm:1.2.3" - "@radix-ui/react-use-controllable-state": "npm:1.2.2" - aria-hidden: "npm:^1.2.4" - react-remove-scroll: "npm:^2.6.3" - peerDependencies: - "@types/react": "*" - "@types/react-dom": "*" - react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - peerDependenciesMeta: - "@types/react": - optional: true - "@types/react-dom": - optional: true - checksum: 10c0/2f2c88e3c281acaea2fd9b96fa82132d59177d3aa5da2e7c045596fd4028e84e44ac52ac28f4f236910605dd7d9338c2858ba44a9ced2af2e3e523abbfd33014 - languageName: node - linkType: hard - -"@radix-ui/react-direction@npm:1.1.0": - version: 1.1.0 - resolution: "@radix-ui/react-direction@npm:1.1.0" - peerDependencies: - "@types/react": "*" - react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - peerDependenciesMeta: - "@types/react": - optional: true - checksum: 10c0/eb07d8cc3ae2388b824e0a11ae0e3b71fb0c49972b506e249cec9f27a5b7ef4305ee668c98b674833c92e842163549a83beb0a197dec1ec65774bdeeb61f932c - languageName: node - linkType: hard - -"@radix-ui/react-direction@npm:1.1.1": - version: 1.1.1 - resolution: "@radix-ui/react-direction@npm:1.1.1" - peerDependencies: - "@types/react": "*" - react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - peerDependenciesMeta: - "@types/react": - optional: true - checksum: 10c0/7a89d9291f846a3105e45f4df98d6b7a08f8d7b30acdcd253005dc9db107ee83cbbebc9e47a9af1e400bcd47697f1511ceab23a399b0da854488fc7220482ac9 - languageName: node - linkType: hard - -"@radix-ui/react-dismissable-layer@npm:1.1.11": - version: 1.1.11 - resolution: "@radix-ui/react-dismissable-layer@npm:1.1.11" - dependencies: - "@radix-ui/primitive": "npm:1.1.3" - "@radix-ui/react-compose-refs": "npm:1.1.2" - "@radix-ui/react-primitive": "npm:2.1.3" - "@radix-ui/react-use-callback-ref": "npm:1.1.1" - "@radix-ui/react-use-escape-keydown": "npm:1.1.1" - peerDependencies: - "@types/react": "*" - "@types/react-dom": "*" - react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - peerDependenciesMeta: - "@types/react": - optional: true - "@types/react-dom": - optional: true - checksum: 10c0/c825572a64073c4d3853702029979f6658770ffd6a98eabc4984e1dee1b226b4078a2a4dc7003f96475b438985e9b21a58e75f51db74dd06848dcae1f2d395dc - languageName: node - linkType: hard - -"@radix-ui/react-dismissable-layer@npm:1.1.3": - version: 1.1.3 - resolution: "@radix-ui/react-dismissable-layer@npm:1.1.3" - dependencies: - "@radix-ui/primitive": "npm:1.1.1" - "@radix-ui/react-compose-refs": "npm:1.1.1" - "@radix-ui/react-primitive": "npm:2.0.1" - "@radix-ui/react-use-callback-ref": "npm:1.1.0" - "@radix-ui/react-use-escape-keydown": "npm:1.1.0" - peerDependencies: - "@types/react": "*" - "@types/react-dom": "*" - react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - peerDependenciesMeta: - "@types/react": - optional: true - "@types/react-dom": - optional: true - checksum: 10c0/1ab2ebddf3d450bf4efb1e846894824a0056d3fa3deec0858206bc7547857fe5fe37e42f0a34918072702ead6dedc388a5770c060b2596cd408e20db86c54253 - languageName: node - linkType: hard - -"@radix-ui/react-dropdown-menu@npm:^2.1.1": - version: 2.1.4 - resolution: "@radix-ui/react-dropdown-menu@npm:2.1.4" - dependencies: - "@radix-ui/primitive": "npm:1.1.1" - "@radix-ui/react-compose-refs": "npm:1.1.1" - "@radix-ui/react-context": "npm:1.1.1" - "@radix-ui/react-id": "npm:1.1.0" - "@radix-ui/react-menu": "npm:2.1.4" - "@radix-ui/react-primitive": "npm:2.0.1" - "@radix-ui/react-use-controllable-state": "npm:1.1.0" - peerDependencies: - "@types/react": "*" - "@types/react-dom": "*" - react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - peerDependenciesMeta: - "@types/react": - optional: true - "@types/react-dom": - optional: true - checksum: 10c0/90ff1f27288b73d000be904773705bbbe4c31204380d4bee55fcd24d82da7638fe29f9577e4cd5d962607927eba4aad6e5600a9bd5e0ee7924a5a1b5e542b437 - languageName: node - linkType: hard - -"@radix-ui/react-focus-guards@npm:1.1.1": - version: 1.1.1 - resolution: "@radix-ui/react-focus-guards@npm:1.1.1" - peerDependencies: - "@types/react": "*" - react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - peerDependenciesMeta: - "@types/react": - optional: true - checksum: 10c0/2e99750ca593083a530542a185d656b45b100752353a7a193a67566e3c256414a76fa9171d152f8c0167b8d6c1fdf62b2e07750d7af2974bf8ef39eb204aa537 - languageName: node - linkType: hard - -"@radix-ui/react-focus-guards@npm:1.1.3": - version: 1.1.3 - resolution: "@radix-ui/react-focus-guards@npm:1.1.3" - peerDependencies: - "@types/react": "*" - react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - peerDependenciesMeta: - "@types/react": - optional: true - checksum: 10c0/0bab65eb8d7e4f72f685d63de7fbba2450e3cb15ad6a20a16b42195e9d335c576356f5a47cb58d1ffc115393e46d7b14b12c5d4b10029b0ec090861255866985 - languageName: node - linkType: hard - -"@radix-ui/react-focus-scope@npm:1.1.1": - version: 1.1.1 - resolution: "@radix-ui/react-focus-scope@npm:1.1.1" - dependencies: - "@radix-ui/react-compose-refs": "npm:1.1.1" - "@radix-ui/react-primitive": "npm:2.0.1" - "@radix-ui/react-use-callback-ref": "npm:1.1.0" - peerDependencies: - "@types/react": "*" - "@types/react-dom": "*" - react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - peerDependenciesMeta: - "@types/react": - optional: true - "@types/react-dom": - optional: true - checksum: 10c0/a430264a32e358c05dfa1c3abcf6c3d0481cbcbb2547532324c6d69fa7f9e3ed77b5eb2dd64d42808ec62c8d69abb573d6076907764af126d14ea18febf45d7b - languageName: node - linkType: hard - -"@radix-ui/react-focus-scope@npm:1.1.7": - version: 1.1.7 - resolution: "@radix-ui/react-focus-scope@npm:1.1.7" - dependencies: - "@radix-ui/react-compose-refs": "npm:1.1.2" - "@radix-ui/react-primitive": "npm:2.1.3" - "@radix-ui/react-use-callback-ref": "npm:1.1.1" - peerDependencies: - "@types/react": "*" - "@types/react-dom": "*" - react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - peerDependenciesMeta: - "@types/react": - optional: true - "@types/react-dom": - optional: true - checksum: 10c0/8a6071331bdeeb79b223463de75caf759b8ad19339cab838e537b8dbb2db236891a1f4df252445c854d375d43d9d315dfcce0a6b01553a2984ec372bb8f1300e - languageName: node - linkType: hard - -"@radix-ui/react-form@npm:^0.1.0": - version: 0.1.1 - resolution: "@radix-ui/react-form@npm:0.1.1" - dependencies: - "@radix-ui/primitive": "npm:1.1.1" - "@radix-ui/react-compose-refs": "npm:1.1.1" - "@radix-ui/react-context": "npm:1.1.1" - "@radix-ui/react-id": "npm:1.1.0" - "@radix-ui/react-label": "npm:2.1.1" - "@radix-ui/react-primitive": "npm:2.0.1" - peerDependencies: - "@types/react": "*" - "@types/react-dom": "*" - react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - peerDependenciesMeta: - "@types/react": - optional: true - "@types/react-dom": - optional: true - checksum: 10c0/78c41d03abab2744fd4026c1b365b8977b00749b86085db5579eed3a57c91748b344d64014a4437204f3eecd334e8284b25f85b24192c9100178559bf3797d05 - languageName: node - linkType: hard - -"@radix-ui/react-id@npm:1.1.0": - version: 1.1.0 - resolution: "@radix-ui/react-id@npm:1.1.0" - dependencies: - "@radix-ui/react-use-layout-effect": "npm:1.1.0" - peerDependencies: - "@types/react": "*" - react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - peerDependenciesMeta: - "@types/react": - optional: true - checksum: 10c0/acf13e29e51ee96336837fc0cfecc306328b20b0e0070f6f0f7aa7a621ded4a1ee5537cfad58456f64bae76caa7f8769231e88dc7dc106197347ee433c275a79 - languageName: node - linkType: hard - -"@radix-ui/react-id@npm:1.1.1": - version: 1.1.1 - resolution: "@radix-ui/react-id@npm:1.1.1" - dependencies: - "@radix-ui/react-use-layout-effect": "npm:1.1.1" - peerDependencies: - "@types/react": "*" - react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - peerDependenciesMeta: - "@types/react": - optional: true - checksum: 10c0/7d12e76818763d592c331277ef62b197e2e64945307e650bd058f0090e5ae48bbd07691b23b7e9e977901ef4eadcb3e2d5eaeb17a13859083384be83fc1292c7 - languageName: node - linkType: hard - -"@radix-ui/react-label@npm:2.1.1": - version: 2.1.1 - resolution: "@radix-ui/react-label@npm:2.1.1" - dependencies: - "@radix-ui/react-primitive": "npm:2.0.1" - peerDependencies: - "@types/react": "*" - "@types/react-dom": "*" - react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - peerDependenciesMeta: - "@types/react": - optional: true - "@types/react-dom": - optional: true - checksum: 10c0/902628dc2c05610462a264feedc8c548d7ecad7f000efb9a4190e365ee2b7f75eccf98b43925fac6e1fa940c437abbce03ecc6868e06e0a197c779973ccc839d - languageName: node - linkType: hard - -"@radix-ui/react-menu@npm:2.1.16": - version: 2.1.16 - resolution: "@radix-ui/react-menu@npm:2.1.16" - dependencies: - "@radix-ui/primitive": "npm:1.1.3" - "@radix-ui/react-collection": "npm:1.1.7" - "@radix-ui/react-compose-refs": "npm:1.1.2" - "@radix-ui/react-context": "npm:1.1.2" - "@radix-ui/react-direction": "npm:1.1.1" - "@radix-ui/react-dismissable-layer": "npm:1.1.11" - "@radix-ui/react-focus-guards": "npm:1.1.3" - "@radix-ui/react-focus-scope": "npm:1.1.7" - "@radix-ui/react-id": "npm:1.1.1" - "@radix-ui/react-popper": "npm:1.2.8" - "@radix-ui/react-portal": "npm:1.1.9" - "@radix-ui/react-presence": "npm:1.1.5" - "@radix-ui/react-primitive": "npm:2.1.3" - "@radix-ui/react-roving-focus": "npm:1.1.11" - "@radix-ui/react-slot": "npm:1.2.3" - "@radix-ui/react-use-callback-ref": "npm:1.1.1" - aria-hidden: "npm:^1.2.4" - react-remove-scroll: "npm:^2.6.3" - peerDependencies: - "@types/react": "*" - "@types/react-dom": "*" - react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - peerDependenciesMeta: - "@types/react": - optional: true - "@types/react-dom": - optional: true - checksum: 10c0/27516b2b987fa9181c4da8645000af8f60691866a349d7a46b9505fa7d2e9d92b9e364db4f7305d08e9e57d0e1afc8df8354f8ee3c12aa05c0100c16b0e76c27 - languageName: node - linkType: hard - -"@radix-ui/react-menu@npm:2.1.4": - version: 2.1.4 - resolution: "@radix-ui/react-menu@npm:2.1.4" - dependencies: - "@radix-ui/primitive": "npm:1.1.1" - "@radix-ui/react-collection": "npm:1.1.1" - "@radix-ui/react-compose-refs": "npm:1.1.1" - "@radix-ui/react-context": "npm:1.1.1" - "@radix-ui/react-direction": "npm:1.1.0" - "@radix-ui/react-dismissable-layer": "npm:1.1.3" - "@radix-ui/react-focus-guards": "npm:1.1.1" - "@radix-ui/react-focus-scope": "npm:1.1.1" - "@radix-ui/react-id": "npm:1.1.0" - "@radix-ui/react-popper": "npm:1.2.1" - "@radix-ui/react-portal": "npm:1.1.3" - "@radix-ui/react-presence": "npm:1.1.2" - "@radix-ui/react-primitive": "npm:2.0.1" - "@radix-ui/react-roving-focus": "npm:1.1.1" - "@radix-ui/react-slot": "npm:1.1.1" - "@radix-ui/react-use-callback-ref": "npm:1.1.0" - aria-hidden: "npm:^1.1.1" - react-remove-scroll: "npm:^2.6.1" - peerDependencies: - "@types/react": "*" - "@types/react-dom": "*" - react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - peerDependenciesMeta: - "@types/react": - optional: true - "@types/react-dom": - optional: true - checksum: 10c0/617b167d110a6866184a562cecd052eef9de3e6f9bfa0780d954629f6a1d09c9dd43cb3f803e3987214f79031a67410fd4d6036c4a4581909edd4bb224ec0f7f - languageName: node - linkType: hard - -"@radix-ui/react-popper@npm:1.2.1": - version: 1.2.1 - resolution: "@radix-ui/react-popper@npm:1.2.1" - dependencies: - "@floating-ui/react-dom": "npm:^2.0.0" - "@radix-ui/react-arrow": "npm:1.1.1" - "@radix-ui/react-compose-refs": "npm:1.1.1" - "@radix-ui/react-context": "npm:1.1.1" - "@radix-ui/react-primitive": "npm:2.0.1" - "@radix-ui/react-use-callback-ref": "npm:1.1.0" - "@radix-ui/react-use-layout-effect": "npm:1.1.0" - "@radix-ui/react-use-rect": "npm:1.1.0" - "@radix-ui/react-use-size": "npm:1.1.0" - "@radix-ui/rect": "npm:1.1.0" - peerDependencies: - "@types/react": "*" - "@types/react-dom": "*" - react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - peerDependenciesMeta: - "@types/react": - optional: true - "@types/react-dom": - optional: true - checksum: 10c0/514468b51e66ff2da3400fa782f4b52f9bad60517e3047cccf56488aa17a3c3f62ff2650b0216be31345dc3be6035999c7160788c92e35c7f8d53ddde2fb92f1 - languageName: node - linkType: hard - -"@radix-ui/react-popper@npm:1.2.8": - version: 1.2.8 - resolution: "@radix-ui/react-popper@npm:1.2.8" - dependencies: - "@floating-ui/react-dom": "npm:^2.0.0" - "@radix-ui/react-arrow": "npm:1.1.7" - "@radix-ui/react-compose-refs": "npm:1.1.2" - "@radix-ui/react-context": "npm:1.1.2" - "@radix-ui/react-primitive": "npm:2.1.3" - "@radix-ui/react-use-callback-ref": "npm:1.1.1" - "@radix-ui/react-use-layout-effect": "npm:1.1.1" - "@radix-ui/react-use-rect": "npm:1.1.1" - "@radix-ui/react-use-size": "npm:1.1.1" - "@radix-ui/rect": "npm:1.1.1" - peerDependencies: - "@types/react": "*" - "@types/react-dom": "*" - react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - peerDependenciesMeta: - "@types/react": - optional: true - "@types/react-dom": - optional: true - checksum: 10c0/48e3f13eac3b8c13aca8ded37d74db17e1bb294da8d69f142ab6b8719a06c3f90051668bed64520bf9f3abdd77b382ce7ce209d056bb56137cecc949b69b421c - languageName: node - linkType: hard - -"@radix-ui/react-portal@npm:1.1.3": - version: 1.1.3 - resolution: "@radix-ui/react-portal@npm:1.1.3" - dependencies: - "@radix-ui/react-primitive": "npm:2.0.1" - "@radix-ui/react-use-layout-effect": "npm:1.1.0" - peerDependencies: - "@types/react": "*" - "@types/react-dom": "*" - react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - peerDependenciesMeta: - "@types/react": - optional: true - "@types/react-dom": - optional: true - checksum: 10c0/b3cd1a81513e528d261599cffda8d7d6094a8598750eaa32bac0d64dbc9a3b4d4e1c10f5bdadf7051b5fd77033b759dbeb4838dae325b94bf8251804c61508c5 - languageName: node - linkType: hard - -"@radix-ui/react-portal@npm:1.1.9": - version: 1.1.9 - resolution: "@radix-ui/react-portal@npm:1.1.9" - dependencies: - "@radix-ui/react-primitive": "npm:2.1.3" - "@radix-ui/react-use-layout-effect": "npm:1.1.1" - peerDependencies: - "@types/react": "*" - "@types/react-dom": "*" - react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - peerDependenciesMeta: - "@types/react": - optional: true - "@types/react-dom": - optional: true - checksum: 10c0/45b432497c722720c72c493a29ef6085bc84b50eafe79d48b45c553121b63e94f9cdb77a3a74b9c49126f8feb3feee009fe400d48b7759d3552396356b192cd7 - languageName: node - linkType: hard - -"@radix-ui/react-presence@npm:1.1.2": - version: 1.1.2 - resolution: "@radix-ui/react-presence@npm:1.1.2" - dependencies: - "@radix-ui/react-compose-refs": "npm:1.1.1" - "@radix-ui/react-use-layout-effect": "npm:1.1.0" - peerDependencies: - "@types/react": "*" - "@types/react-dom": "*" - react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - peerDependenciesMeta: - "@types/react": - optional: true - "@types/react-dom": - optional: true - checksum: 10c0/0c6fa281368636308044df3be4c1f02733094b5e35ba04f26e610dd1c4315a245ffc758e0e176c444742a7a46f4328af1a9d8181e860175ec39338d06525a78d - languageName: node - linkType: hard - -"@radix-ui/react-presence@npm:1.1.5": - version: 1.1.5 - resolution: "@radix-ui/react-presence@npm:1.1.5" - dependencies: - "@radix-ui/react-compose-refs": "npm:1.1.2" - "@radix-ui/react-use-layout-effect": "npm:1.1.1" - peerDependencies: - "@types/react": "*" - "@types/react-dom": "*" - react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - peerDependenciesMeta: - "@types/react": - optional: true - "@types/react-dom": - optional: true - checksum: 10c0/d0e61d314250eeaef5369983cb790701d667f51734bafd98cf759072755562018052c594e6cdc5389789f4543cb0a4d98f03ff4e8f37338d6b5bf51a1700c1d1 - languageName: node - linkType: hard - -"@radix-ui/react-primitive@npm:2.0.1": - version: 2.0.1 - resolution: "@radix-ui/react-primitive@npm:2.0.1" - dependencies: - "@radix-ui/react-slot": "npm:1.1.1" - peerDependencies: - "@types/react": "*" - "@types/react-dom": "*" - react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - peerDependenciesMeta: - "@types/react": - optional: true - "@types/react-dom": - optional: true - checksum: 10c0/6a562bec14f8e9fbfe0012d6c2932b0e54518fed898fa0622300c463611e77a4ca28a969f0cd484efd6570c01c5665dd6151f736262317d01715bc4da1a7dea6 - languageName: node - linkType: hard - -"@radix-ui/react-primitive@npm:2.1.3": - version: 2.1.3 - resolution: "@radix-ui/react-primitive@npm:2.1.3" - dependencies: - "@radix-ui/react-slot": "npm:1.2.3" - peerDependencies: - "@types/react": "*" - "@types/react-dom": "*" - react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - peerDependenciesMeta: - "@types/react": - optional: true - "@types/react-dom": - optional: true - checksum: 10c0/fdff9b84913bb4172ef6d3af7442fca5f9bba5f2709cba08950071f819d7057aec3a4a2d9ef44cf9cbfb8014d02573c6884a04cff175895823aaef809ebdb034 - languageName: node - linkType: hard - -"@radix-ui/react-primitive@npm:2.1.4": - version: 2.1.4 - resolution: "@radix-ui/react-primitive@npm:2.1.4" - dependencies: - "@radix-ui/react-slot": "npm:1.2.4" - peerDependencies: - "@types/react": "*" - "@types/react-dom": "*" - react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - peerDependenciesMeta: - "@types/react": - optional: true - "@types/react-dom": - optional: true - checksum: 10c0/90d687b222a25975371ed1f9f08648d75237214b8dec4cbaf09ec9ac951339b17421278f1aff2fb7c5672ba8bd03774a94904efdba73805dd5cc947ce5be8c4a - languageName: node - linkType: hard - -"@radix-ui/react-progress@npm:^1.1.0": - version: 1.1.1 - resolution: "@radix-ui/react-progress@npm:1.1.1" - dependencies: - "@radix-ui/react-context": "npm:1.1.1" - "@radix-ui/react-primitive": "npm:2.0.1" - peerDependencies: - "@types/react": "*" - "@types/react-dom": "*" - react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - peerDependenciesMeta: - "@types/react": - optional: true - "@types/react-dom": - optional: true - checksum: 10c0/dcf4ab20ff3a19a4be5a6e2502c42cd2c2770c6356b86301a548f725d33b8054dafe411b3c0f2b0b9465b225a31e8eb9f6bcc338d1936fb89312b517e1e7f2ec - languageName: node - linkType: hard - -"@radix-ui/react-roving-focus@npm:1.1.1": - version: 1.1.1 - resolution: "@radix-ui/react-roving-focus@npm:1.1.1" - dependencies: - "@radix-ui/primitive": "npm:1.1.1" - "@radix-ui/react-collection": "npm:1.1.1" - "@radix-ui/react-compose-refs": "npm:1.1.1" - "@radix-ui/react-context": "npm:1.1.1" - "@radix-ui/react-direction": "npm:1.1.0" - "@radix-ui/react-id": "npm:1.1.0" - "@radix-ui/react-primitive": "npm:2.0.1" - "@radix-ui/react-use-callback-ref": "npm:1.1.0" - "@radix-ui/react-use-controllable-state": "npm:1.1.0" - peerDependencies: - "@types/react": "*" - "@types/react-dom": "*" - react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - peerDependenciesMeta: - "@types/react": - optional: true - "@types/react-dom": - optional: true - checksum: 10c0/ee41eb60b0c300ef3bb130f7ca6c7333148669f2a50b841027910158c06be215967880da932ac14b83d130a9ca5ffb33d6a1a0f067d5048f8db2c3884bbd9b85 - languageName: node - linkType: hard - -"@radix-ui/react-roving-focus@npm:1.1.11": - version: 1.1.11 - resolution: "@radix-ui/react-roving-focus@npm:1.1.11" - dependencies: - "@radix-ui/primitive": "npm:1.1.3" - "@radix-ui/react-collection": "npm:1.1.7" - "@radix-ui/react-compose-refs": "npm:1.1.2" - "@radix-ui/react-context": "npm:1.1.2" - "@radix-ui/react-direction": "npm:1.1.1" - "@radix-ui/react-id": "npm:1.1.1" - "@radix-ui/react-primitive": "npm:2.1.3" - "@radix-ui/react-use-callback-ref": "npm:1.1.1" - "@radix-ui/react-use-controllable-state": "npm:1.2.2" - peerDependencies: - "@types/react": "*" - "@types/react-dom": "*" - react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - peerDependenciesMeta: - "@types/react": - optional: true - "@types/react-dom": - optional: true - checksum: 10c0/2cd43339c36e89a3bf1db8aab34b939113dfbde56bf3a33df2d74757c78c9489b847b1962f1e2441c67e41817d120cb6177943e0f655f47bc1ff8e44fd55b1a2 - languageName: node - linkType: hard - -"@radix-ui/react-separator@npm:^1.1.0": - version: 1.1.1 - resolution: "@radix-ui/react-separator@npm:1.1.1" - dependencies: - "@radix-ui/react-primitive": "npm:2.0.1" - peerDependencies: - "@types/react": "*" - "@types/react-dom": "*" - react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - peerDependenciesMeta: - "@types/react": - optional: true - "@types/react-dom": - optional: true - checksum: 10c0/4b0dc0db4e31d4d71a2a688581707dedb19a9e13378e86dbbab467970c5b271afc189ebba0e340495e15ce0fbbc42445d0be43ff8104de5f5c96cf3b822e801d - languageName: node - linkType: hard - -"@radix-ui/react-slider@npm:^1.1.2": - version: 1.3.6 - resolution: "@radix-ui/react-slider@npm:1.3.6" - dependencies: - "@radix-ui/number": "npm:1.1.1" - "@radix-ui/primitive": "npm:1.1.3" - "@radix-ui/react-collection": "npm:1.1.7" - "@radix-ui/react-compose-refs": "npm:1.1.2" - "@radix-ui/react-context": "npm:1.1.2" - "@radix-ui/react-direction": "npm:1.1.1" - "@radix-ui/react-primitive": "npm:2.1.3" - "@radix-ui/react-use-controllable-state": "npm:1.2.2" - "@radix-ui/react-use-layout-effect": "npm:1.1.1" - "@radix-ui/react-use-previous": "npm:1.1.1" - "@radix-ui/react-use-size": "npm:1.1.1" - peerDependencies: - "@types/react": "*" - "@types/react-dom": "*" - react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - peerDependenciesMeta: - "@types/react": - optional: true - "@types/react-dom": - optional: true - checksum: 10c0/a53d7854e28c5ef3d29b76c8d04cc3c723b982b643152cd5a8fefc7a8359180f8fd21753e5a08302a290bc837e7be04f2efad9d308b7a4a23326df6a6b1ac882 - languageName: node - linkType: hard - -"@radix-ui/react-slot@npm:1.1.1, @radix-ui/react-slot@npm:^1.1.0": - version: 1.1.1 - resolution: "@radix-ui/react-slot@npm:1.1.1" - dependencies: - "@radix-ui/react-compose-refs": "npm:1.1.1" - peerDependencies: - "@types/react": "*" - react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - peerDependenciesMeta: - "@types/react": - optional: true - checksum: 10c0/f3cc71c16529c67a8407a89e0ac13a868cafa0cd05ca185b464db609aa5996a3f00588695518e420bd47ffdb4cc2f76c14cc12ea5a38fc2ca3578a30d2ca58b9 - languageName: node - linkType: hard - -"@radix-ui/react-slot@npm:1.2.3": - version: 1.2.3 - resolution: "@radix-ui/react-slot@npm:1.2.3" - dependencies: - "@radix-ui/react-compose-refs": "npm:1.1.2" - peerDependencies: - "@types/react": "*" - react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - peerDependenciesMeta: - "@types/react": - optional: true - checksum: 10c0/5913aa0d760f505905779515e4b1f0f71a422350f077cc8d26d1aafe53c97f177fec0e6d7fbbb50d8b5e498aa9df9f707ca75ae3801540c283b26b0136138eef - languageName: node - linkType: hard - -"@radix-ui/react-slot@npm:1.2.4": - version: 1.2.4 - resolution: "@radix-ui/react-slot@npm:1.2.4" - dependencies: - "@radix-ui/react-compose-refs": "npm:1.1.2" - peerDependencies: - "@types/react": "*" - react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - peerDependenciesMeta: - "@types/react": - optional: true - checksum: 10c0/8b719bb934f1ae5ac0e37214783085c17c2f1080217caf514c1c6cc3d9ca56c7e19d25470b26da79aa6e605ab36589edaade149b76f5fc0666f1063e2fc0a0dc - languageName: node - linkType: hard - -"@radix-ui/react-use-callback-ref@npm:1.1.0": - version: 1.1.0 - resolution: "@radix-ui/react-use-callback-ref@npm:1.1.0" - peerDependencies: - "@types/react": "*" - react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - peerDependenciesMeta: - "@types/react": - optional: true - checksum: 10c0/e954863f3baa151faf89ac052a5468b42650efca924417470efd1bd254b411a94c69c30de2fdbb90187b38cb984795978e12e30423dc41e4309d93d53b66d819 - languageName: node - linkType: hard - -"@radix-ui/react-use-callback-ref@npm:1.1.1": - version: 1.1.1 - resolution: "@radix-ui/react-use-callback-ref@npm:1.1.1" - peerDependencies: - "@types/react": "*" - react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - peerDependenciesMeta: - "@types/react": - optional: true - checksum: 10c0/5f6aff8592dea6a7e46589808912aba3fb3b626cf6edd2b14f01638b61dbbe49eeb9f67cd5601f4c15b2fb547b9a7e825f7c4961acd4dd70176c969ae405f8d8 - languageName: node - linkType: hard - -"@radix-ui/react-use-controllable-state@npm:1.1.0": - version: 1.1.0 - resolution: "@radix-ui/react-use-controllable-state@npm:1.1.0" - dependencies: - "@radix-ui/react-use-callback-ref": "npm:1.1.0" - peerDependencies: - "@types/react": "*" - react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - peerDependenciesMeta: - "@types/react": - optional: true - checksum: 10c0/2af883b5b25822ac226e60a6bfde647c0123a76345052a90219026059b3f7225844b2c13a9a16fba859c1cda5fb3d057f2a04503f71780e607516492db4eb3a1 - languageName: node - linkType: hard - -"@radix-ui/react-use-controllable-state@npm:1.2.2": - version: 1.2.2 - resolution: "@radix-ui/react-use-controllable-state@npm:1.2.2" - dependencies: - "@radix-ui/react-use-effect-event": "npm:0.0.2" - "@radix-ui/react-use-layout-effect": "npm:1.1.1" - peerDependencies: - "@types/react": "*" - react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - peerDependenciesMeta: - "@types/react": - optional: true - checksum: 10c0/f55c4b06e895293aed4b44c9ef26fb24432539f5346fcd6519c7745800535b571058685314e83486a45bf61dc83887e24826490d3068acc317fb0a9010516e63 - languageName: node - linkType: hard - -"@radix-ui/react-use-effect-event@npm:0.0.2": - version: 0.0.2 - resolution: "@radix-ui/react-use-effect-event@npm:0.0.2" - dependencies: - "@radix-ui/react-use-layout-effect": "npm:1.1.1" - peerDependencies: - "@types/react": "*" - react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - peerDependenciesMeta: - "@types/react": - optional: true - checksum: 10c0/e84ff72a3e76c5ae9c94941028bb4b6472f17d4104481b9eab773deab3da640ecea035e54da9d6f4df8d84c18ef6913baf92b7511bee06930dc58bd0c0add417 - languageName: node - linkType: hard - -"@radix-ui/react-use-escape-keydown@npm:1.1.0": - version: 1.1.0 - resolution: "@radix-ui/react-use-escape-keydown@npm:1.1.0" - dependencies: - "@radix-ui/react-use-callback-ref": "npm:1.1.0" - peerDependencies: - "@types/react": "*" - react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - peerDependenciesMeta: - "@types/react": - optional: true - checksum: 10c0/910fd696e5a0994b0e06b9cb68def8a865f47951a013ec240c77db2a9e1e726105602700ef5e5f01af49f2f18fe0e73164f9a9651021f28538ef8a30d91f3fbb - languageName: node - linkType: hard - -"@radix-ui/react-use-escape-keydown@npm:1.1.1": - version: 1.1.1 - resolution: "@radix-ui/react-use-escape-keydown@npm:1.1.1" - dependencies: - "@radix-ui/react-use-callback-ref": "npm:1.1.1" - peerDependencies: - "@types/react": "*" - react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - peerDependenciesMeta: - "@types/react": - optional: true - checksum: 10c0/bff53be99e940fef1d3c4df7d560e1d9133182e5a98336255d3063327d1d3dd4ec54a95dc5afe15cca4fb6c184f0a956c70de2815578c318cf995a7f9beabaa1 - languageName: node - linkType: hard - -"@radix-ui/react-use-layout-effect@npm:1.1.0": - version: 1.1.0 - resolution: "@radix-ui/react-use-layout-effect@npm:1.1.0" - peerDependencies: - "@types/react": "*" - react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - peerDependenciesMeta: - "@types/react": - optional: true - checksum: 10c0/9bf87ece1845c038ed95863cfccf9d75f557c2400d606343bab0ab3192b9806b9840e6aa0a0333fdf3e83cf9982632852192f3e68d7d8367bc8c788dfdf8e62b - languageName: node - linkType: hard - -"@radix-ui/react-use-layout-effect@npm:1.1.1": - version: 1.1.1 - resolution: "@radix-ui/react-use-layout-effect@npm:1.1.1" - peerDependencies: - "@types/react": "*" - react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - peerDependenciesMeta: - "@types/react": - optional: true - checksum: 10c0/9f98fdaba008dfc58050de60a77670b885792df473cf82c1cef8daee919a5dd5a77d270209f5f0b0abfaac78cb1627396e3ff56c81b735be550409426fe8b040 - languageName: node - linkType: hard - -"@radix-ui/react-use-previous@npm:1.1.1": - version: 1.1.1 - resolution: "@radix-ui/react-use-previous@npm:1.1.1" - peerDependencies: - "@types/react": "*" - react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - peerDependenciesMeta: - "@types/react": - optional: true - checksum: 10c0/52f1089d941491cd59b7f52a5679a14e9381711419a0557ce0f3bc9a4c117078224efec54dcced41a3653a13a386a7b6ec75435d61a273e8b9f5d00235f2b182 - languageName: node - linkType: hard - -"@radix-ui/react-use-rect@npm:1.1.0": - version: 1.1.0 - resolution: "@radix-ui/react-use-rect@npm:1.1.0" - dependencies: - "@radix-ui/rect": "npm:1.1.0" - peerDependencies: - "@types/react": "*" - react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - peerDependenciesMeta: - "@types/react": - optional: true - checksum: 10c0/c2e30150ab49e2cec238cda306fd748c3d47fb96dcff69a3b08e1d19108d80bac239d48f1747a25dadca614e3e967267d43b91e60ea59db2befbc7bea913ff84 - languageName: node - linkType: hard - -"@radix-ui/react-use-rect@npm:1.1.1": - version: 1.1.1 - resolution: "@radix-ui/react-use-rect@npm:1.1.1" - dependencies: - "@radix-ui/rect": "npm:1.1.1" - peerDependencies: - "@types/react": "*" - react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - peerDependenciesMeta: - "@types/react": - optional: true - checksum: 10c0/271711404c05c589c8dbdaa748749e7daf44bcc6bffc9ecd910821c3ebca0ee245616cf5b39653ce690f53f875c3836fd3f36f51ab1c628273b6db599eee4864 - languageName: node - linkType: hard - -"@radix-ui/react-use-size@npm:1.1.0": - version: 1.1.0 - resolution: "@radix-ui/react-use-size@npm:1.1.0" - dependencies: - "@radix-ui/react-use-layout-effect": "npm:1.1.0" - peerDependencies: - "@types/react": "*" - react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - peerDependenciesMeta: - "@types/react": - optional: true - checksum: 10c0/4c8b89037597fdc1824d009e0c941b510c7c6c30f83024cc02c934edd748886786e7d9f36f57323b02ad29833e7fa7e8974d81969b4ab33d8f41661afa4f30a6 - languageName: node - linkType: hard - -"@radix-ui/react-use-size@npm:1.1.1": - version: 1.1.1 - resolution: "@radix-ui/react-use-size@npm:1.1.1" - dependencies: - "@radix-ui/react-use-layout-effect": "npm:1.1.1" - peerDependencies: - "@types/react": "*" - react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - peerDependenciesMeta: - "@types/react": - optional: true - checksum: 10c0/851d09a816f44282e0e9e2147b1b571410174cc048703a50c4fa54d672de994fd1dfff1da9d480ecfd12c77ae8f48d74f01adaf668f074156b8cd0043c6c21d8 - languageName: node - linkType: hard - -"@radix-ui/react-visually-hidden@npm:^1.0.3": - version: 1.2.4 - resolution: "@radix-ui/react-visually-hidden@npm:1.2.4" - dependencies: - "@radix-ui/react-primitive": "npm:2.1.4" - peerDependencies: - "@types/react": "*" - "@types/react-dom": "*" - react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - peerDependenciesMeta: - "@types/react": - optional: true - "@types/react-dom": - optional: true - checksum: 10c0/cca313cd3268f483612da1ab91c4cca55a54d24963dd543154f2d043bfdca21a96ab0582152ae473de44769474867d5433dbadae799a42932e6204fd2d5fa889 - languageName: node - linkType: hard - -"@radix-ui/rect@npm:1.1.0": - version: 1.1.0 - resolution: "@radix-ui/rect@npm:1.1.0" - checksum: 10c0/a26ff7f8708fb5f2f7949baad70a6b2a597d761ee4dd4aadaf1c1a33ea82ea23dfef6ce6366a08310c5d008cdd60b2e626e4ee03fa342bd5f246ddd9d427f6be - languageName: node - linkType: hard - -"@radix-ui/rect@npm:1.1.1": - version: 1.1.1 - resolution: "@radix-ui/rect@npm:1.1.1" - checksum: 10c0/0dac4f0f15691199abe6a0e067821ddd9d0349c0c05f39834e4eafc8403caf724106884035ae91bbc826e10367e6a5672e7bec4d4243860fa7649de246b1f60b - languageName: node - linkType: hard - -"@react-spring/animated@npm:~10.0.3": - version: 10.0.3 - resolution: "@react-spring/animated@npm:10.0.3" - dependencies: - "@react-spring/shared": "npm:~10.0.3" - "@react-spring/types": "npm:~10.0.3" - peerDependencies: - react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 - checksum: 10c0/6142522f310926729a92009a108ec1bd0d1fe3dca7e9aa0c49692c82fbed28f70c0ea9808fc7452f04bb688ae34333e780f794495906fa4b0efbfc7d53a19b6b - languageName: node - linkType: hard - -"@react-spring/core@npm:~10.0.3": - version: 10.0.3 - resolution: "@react-spring/core@npm:10.0.3" - dependencies: - "@react-spring/animated": "npm:~10.0.3" - "@react-spring/shared": "npm:~10.0.3" - "@react-spring/types": "npm:~10.0.3" - peerDependencies: - react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 - checksum: 10c0/d941541d4a40a5229f488e78b414149d54238065178fdd14db307a851d285d521ab1914c0d426b102e0190651dbe752aeb743cee4cd497f5c066be937f2d1790 - languageName: node - linkType: hard - -"@react-spring/rafz@npm:~10.0.3": - version: 10.0.3 - resolution: "@react-spring/rafz@npm:10.0.3" - checksum: 10c0/4cf6f710e2be64a3d94e90a20a24a93c68a89b618538d32aaf0079217f9fbed610395051a181d2d010c7ed6898cb7239a3f2ced1d91dd93e4138563ffd2d44ce - languageName: node - linkType: hard - -"@react-spring/shared@npm:~10.0.3": - version: 10.0.3 - resolution: "@react-spring/shared@npm:10.0.3" - dependencies: - "@react-spring/rafz": "npm:~10.0.3" - "@react-spring/types": "npm:~10.0.3" - peerDependencies: - react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 - checksum: 10c0/d8b33b2390792924d0ff2b57b3098d1c6b688a788fc67e83b168928659aad7435dd2c399925a765ffa5080182634dde8f9f76c919f2c259a33af15319187f72f - languageName: node - linkType: hard - -"@react-spring/types@npm:~10.0.3": - version: 10.0.3 - resolution: "@react-spring/types@npm:10.0.3" - checksum: 10c0/f9bc2619dc9997fe93ebab90fd98118106e53bc45c9c279caaa7081b69d3ed0186d603d5ed445e56bb8ad0075553d15908a2a54e3a0a36ef7cd43a03c1650b02 - languageName: node - linkType: hard - -"@react-spring/web@npm:^10.0.0": - version: 10.0.3 - resolution: "@react-spring/web@npm:10.0.3" - dependencies: - "@react-spring/animated": "npm:~10.0.3" - "@react-spring/core": "npm:~10.0.3" - "@react-spring/shared": "npm:~10.0.3" - "@react-spring/types": "npm:~10.0.3" - peerDependencies: - react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 - react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 - checksum: 10c0/cafbf55991d68920e94419b5b081cfb0aea2ddfa193e984861ab53306365bf81152bce2861370f9b26d4027dd714e8acc0dfbd57bd2eda99e827c3212e22a51c - languageName: node - linkType: hard - -"@rolldown/binding-android-arm64@npm:1.0.0-rc.12": - version: 1.0.0-rc.12 - resolution: "@rolldown/binding-android-arm64@npm:1.0.0-rc.12" - conditions: os=android & cpu=arm64 - languageName: node - linkType: hard - -"@rolldown/binding-darwin-arm64@npm:1.0.0-rc.12": - version: 1.0.0-rc.12 - resolution: "@rolldown/binding-darwin-arm64@npm:1.0.0-rc.12" - conditions: os=darwin & cpu=arm64 - languageName: node - linkType: hard - -"@rolldown/binding-darwin-x64@npm:1.0.0-rc.12": - version: 1.0.0-rc.12 - resolution: "@rolldown/binding-darwin-x64@npm:1.0.0-rc.12" - conditions: os=darwin & cpu=x64 - languageName: node - linkType: hard - -"@rolldown/binding-freebsd-x64@npm:1.0.0-rc.12": - version: 1.0.0-rc.12 - resolution: "@rolldown/binding-freebsd-x64@npm:1.0.0-rc.12" - conditions: os=freebsd & cpu=x64 - languageName: node - linkType: hard - -"@rolldown/binding-linux-arm-gnueabihf@npm:1.0.0-rc.12": - version: 1.0.0-rc.12 - resolution: "@rolldown/binding-linux-arm-gnueabihf@npm:1.0.0-rc.12" - conditions: os=linux & cpu=arm - languageName: node - linkType: hard - -"@rolldown/binding-linux-arm64-gnu@npm:1.0.0-rc.12": - version: 1.0.0-rc.12 - resolution: "@rolldown/binding-linux-arm64-gnu@npm:1.0.0-rc.12" - conditions: os=linux & cpu=arm64 & libc=glibc - languageName: node - linkType: hard - -"@rolldown/binding-linux-arm64-musl@npm:1.0.0-rc.12": - version: 1.0.0-rc.12 - resolution: "@rolldown/binding-linux-arm64-musl@npm:1.0.0-rc.12" - conditions: os=linux & cpu=arm64 & libc=musl - languageName: node - linkType: hard - -"@rolldown/binding-linux-ppc64-gnu@npm:1.0.0-rc.12": - version: 1.0.0-rc.12 - resolution: "@rolldown/binding-linux-ppc64-gnu@npm:1.0.0-rc.12" - conditions: os=linux & cpu=ppc64 & libc=glibc - languageName: node - linkType: hard - -"@rolldown/binding-linux-s390x-gnu@npm:1.0.0-rc.12": - version: 1.0.0-rc.12 - resolution: "@rolldown/binding-linux-s390x-gnu@npm:1.0.0-rc.12" - conditions: os=linux & cpu=s390x & libc=glibc - languageName: node - linkType: hard - -"@rolldown/binding-linux-x64-gnu@npm:1.0.0-rc.12": - version: 1.0.0-rc.12 - resolution: "@rolldown/binding-linux-x64-gnu@npm:1.0.0-rc.12" - conditions: os=linux & cpu=x64 & libc=glibc - languageName: node - linkType: hard - -"@rolldown/binding-linux-x64-musl@npm:1.0.0-rc.12": - version: 1.0.0-rc.12 - resolution: "@rolldown/binding-linux-x64-musl@npm:1.0.0-rc.12" - conditions: os=linux & cpu=x64 & libc=musl - languageName: node - linkType: hard - -"@rolldown/binding-openharmony-arm64@npm:1.0.0-rc.12": - version: 1.0.0-rc.12 - resolution: "@rolldown/binding-openharmony-arm64@npm:1.0.0-rc.12" - conditions: os=openharmony & cpu=arm64 - languageName: node - linkType: hard - -"@rolldown/binding-wasm32-wasi@npm:1.0.0-rc.12": - version: 1.0.0-rc.12 - resolution: "@rolldown/binding-wasm32-wasi@npm:1.0.0-rc.12" - dependencies: - "@napi-rs/wasm-runtime": "npm:^1.1.1" - conditions: cpu=wasm32 - languageName: node - linkType: hard - -"@rolldown/binding-win32-arm64-msvc@npm:1.0.0-rc.12": - version: 1.0.0-rc.12 - resolution: "@rolldown/binding-win32-arm64-msvc@npm:1.0.0-rc.12" - conditions: os=win32 & cpu=arm64 - languageName: node - linkType: hard - -"@rolldown/binding-win32-x64-msvc@npm:1.0.0-rc.12": - version: 1.0.0-rc.12 - resolution: "@rolldown/binding-win32-x64-msvc@npm:1.0.0-rc.12" - conditions: os=win32 & cpu=x64 - languageName: node - linkType: hard - -"@rolldown/pluginutils@npm:1.0.0-beta.27": - version: 1.0.0-beta.27 - resolution: "@rolldown/pluginutils@npm:1.0.0-beta.27" - checksum: 10c0/9658f235b345201d4f6bfb1f32da9754ca164f892d1cb68154fe5f53c1df42bd675ecd409836dff46884a7847d6c00bdc38af870f7c81e05bba5c2645eb4ab9c - languageName: node - linkType: hard - -"@rolldown/pluginutils@npm:1.0.0-rc.12": - version: 1.0.0-rc.12 - resolution: "@rolldown/pluginutils@npm:1.0.0-rc.12" - checksum: 10c0/f785d1180ea4876bf6a6a67135822808d1c07f902409524ff1088779f7d5318f6e603d281fb107a5145c1ca54b7cabebd359629ec474ebbc2812f2cf53db4023 - languageName: node - linkType: hard - -"@rollup/plugin-inject@npm:^5.0.3": - version: 5.0.5 - resolution: "@rollup/plugin-inject@npm:5.0.5" - dependencies: - "@rollup/pluginutils": "npm:^5.0.1" - estree-walker: "npm:^2.0.2" - magic-string: "npm:^0.30.3" - peerDependencies: - rollup: ^1.20.0||^2.0.0||^3.0.0||^4.0.0 - peerDependenciesMeta: - rollup: - optional: true - checksum: 10c0/22d10cf44fa56a6683d5ac4df24a9003379b3dcaae9897f5c30c844afc2ebca83cfaa5557f13a1399b1c8a0d312c3217bcacd508b7ebc4b2cbee401bd1ec8be2 - languageName: node - linkType: hard - -"@rollup/pluginutils@npm:^4.2.0": - version: 4.2.1 - resolution: "@rollup/pluginutils@npm:4.2.1" - dependencies: - estree-walker: "npm:^2.0.1" - picomatch: "npm:^2.2.2" - checksum: 10c0/3ee56b2c8f1ed8dfd0a92631da1af3a2dfdd0321948f089b3752b4de1b54dc5076701eadd0e5fc18bd191b77af594ac1db6279e83951238ba16bf8a414c64c48 - languageName: node - linkType: hard - -"@rollup/pluginutils@npm:^5.0.1, @rollup/pluginutils@npm:^5.0.2, @rollup/pluginutils@npm:^5.2.0": - version: 5.3.0 - resolution: "@rollup/pluginutils@npm:5.3.0" - dependencies: - "@types/estree": "npm:^1.0.0" - estree-walker: "npm:^2.0.2" - picomatch: "npm:^4.0.2" - peerDependencies: - rollup: ^1.20.0||^2.0.0||^3.0.0||^4.0.0 - peerDependenciesMeta: - rollup: - optional: true - checksum: 10c0/001834bf62d7cf5bac424d2617c113f7f7d3b2bf3c1778cbcccb72cdc957b68989f8e7747c782c2b911f1dde8257f56f8ac1e779e29e74e638e3f1e2cac2bcd0 - languageName: node - linkType: hard - -"@rtsao/scc@npm:^1.1.0": - version: 1.1.0 - resolution: "@rtsao/scc@npm:1.1.0" - checksum: 10c0/b5bcfb0d87f7d1c1c7c0f7693f53b07866ed9fec4c34a97a8c948fb9a7c0082e416ce4d3b60beb4f5e167cbe04cdeefbf6771320f3ede059b9ce91188c409a5b - languageName: node - linkType: hard - -"@sentry-internal/browser-utils@npm:8.55.1": - version: 8.55.1 - resolution: "@sentry-internal/browser-utils@npm:8.55.1" - dependencies: - "@sentry/core": "npm:8.55.1" - checksum: 10c0/161991035e0ffd728f9bbeb7da547cc0cea94e327400beb1b9ed6071ee53387f85adbeefe34d8415a1b8872c1b0e212b955f7951aac18731970fd68c34279597 - languageName: node - linkType: hard - -"@sentry-internal/feedback@npm:8.55.1": - version: 8.55.1 - resolution: "@sentry-internal/feedback@npm:8.55.1" - dependencies: - "@sentry/core": "npm:8.55.1" - checksum: 10c0/d96c7bdebfe65d079d9eb623d89645e045f3836d7d3a5819b8017939b11f1717a008a97a2bded4869ed7d24d260a18c7d6aeea937e4775c8ad3956e82e532f64 - languageName: node - linkType: hard - -"@sentry-internal/replay-canvas@npm:8.55.1": - version: 8.55.1 - resolution: "@sentry-internal/replay-canvas@npm:8.55.1" - dependencies: - "@sentry-internal/replay": "npm:8.55.1" - "@sentry/core": "npm:8.55.1" - checksum: 10c0/f385c9501c5c2e6a7683e15d26f42b3e08cb5ab7dcdf94a7b4fd58ef9a6d849d3aaaf7b32b15cfbf66d5477b6b79ed8b257784cc7ebc21b99c1d27e47dae55bd - languageName: node - linkType: hard - -"@sentry-internal/replay@npm:8.55.1": - version: 8.55.1 - resolution: "@sentry-internal/replay@npm:8.55.1" - dependencies: - "@sentry-internal/browser-utils": "npm:8.55.1" - "@sentry/core": "npm:8.55.1" - checksum: 10c0/65f3ba885a4349530ca42cd3d57fc0dca61c2333b633786a5a818d0b5e59c4dd950aedfd197fa0e9a7f8c7f0ff2ad6caf5a3c030b6cc9671f32c1dd8c4cc4275 - languageName: node - linkType: hard - -"@sentry/babel-plugin-component-annotate@npm:3.6.1": - version: 3.6.1 - resolution: "@sentry/babel-plugin-component-annotate@npm:3.6.1" - checksum: 10c0/e8876cd4c370ad24d148bbce4f2bda53f35a7a4bd4209c543e9448f0d2577245fb1fa20a7742e50c6171dbc78158fc36fbc53e23939d492abad4e7c8752a962f - languageName: node - linkType: hard - -"@sentry/browser@npm:8.55.1": - version: 8.55.1 - resolution: "@sentry/browser@npm:8.55.1" - dependencies: - "@sentry-internal/browser-utils": "npm:8.55.1" - "@sentry-internal/feedback": "npm:8.55.1" - "@sentry-internal/replay": "npm:8.55.1" - "@sentry-internal/replay-canvas": "npm:8.55.1" - "@sentry/core": "npm:8.55.1" - checksum: 10c0/5b25013f7a5b57aab4c9d4d3a36aaa0076c0cabf3d2d5f2f01bbef9363aaff5b02e75c7ea48043f3204b97967707a553b78cdb0846a8131cb6c95dde3dfa9843 - languageName: node - linkType: hard - -"@sentry/bundler-plugin-core@npm:3.6.1": - version: 3.6.1 - resolution: "@sentry/bundler-plugin-core@npm:3.6.1" - dependencies: - "@babel/core": "npm:^7.18.5" - "@sentry/babel-plugin-component-annotate": "npm:3.6.1" - "@sentry/cli": "npm:^2.49.0" - dotenv: "npm:^16.3.1" - find-up: "npm:^5.0.0" - glob: "npm:^9.3.2" - magic-string: "npm:0.30.8" - unplugin: "npm:1.0.1" - checksum: 10c0/64db0123db0c6e4f31be09cc7fb4b5b8ef4721d693f40d852d3e8e9f1e1e1c4289491a1c3d656603c0b422da836161a3ca2042ee7ee96f284cef52e1c4d407ae - languageName: node - linkType: hard - -"@sentry/cli-darwin@npm:2.50.2": - version: 2.50.2 - resolution: "@sentry/cli-darwin@npm:2.50.2" - conditions: os=darwin - languageName: node - linkType: hard - -"@sentry/cli-linux-arm64@npm:2.50.2": - version: 2.50.2 - resolution: "@sentry/cli-linux-arm64@npm:2.50.2" - conditions: (os=linux | os=freebsd | os=android) & cpu=arm64 - languageName: node - linkType: hard - -"@sentry/cli-linux-arm@npm:2.50.2": - version: 2.50.2 - resolution: "@sentry/cli-linux-arm@npm:2.50.2" - conditions: (os=linux | os=freebsd | os=android) & cpu=arm - languageName: node - linkType: hard - -"@sentry/cli-linux-i686@npm:2.50.2": - version: 2.50.2 - resolution: "@sentry/cli-linux-i686@npm:2.50.2" - conditions: (os=linux | os=freebsd | os=android) & (cpu=x86 | cpu=ia32) - languageName: node - linkType: hard - -"@sentry/cli-linux-x64@npm:2.50.2": - version: 2.50.2 - resolution: "@sentry/cli-linux-x64@npm:2.50.2" - conditions: (os=linux | os=freebsd | os=android) & cpu=x64 - languageName: node - linkType: hard - -"@sentry/cli-win32-arm64@npm:2.50.2": - version: 2.50.2 - resolution: "@sentry/cli-win32-arm64@npm:2.50.2" - conditions: os=win32 & cpu=arm64 - languageName: node - linkType: hard - -"@sentry/cli-win32-i686@npm:2.50.2": - version: 2.50.2 - resolution: "@sentry/cli-win32-i686@npm:2.50.2" - conditions: os=win32 & (cpu=x86 | cpu=ia32) - languageName: node - linkType: hard - -"@sentry/cli-win32-x64@npm:2.50.2": - version: 2.50.2 - resolution: "@sentry/cli-win32-x64@npm:2.50.2" - conditions: os=win32 & cpu=x64 - languageName: node - linkType: hard - -"@sentry/cli@npm:^2.49.0": - version: 2.50.2 - resolution: "@sentry/cli@npm:2.50.2" - dependencies: - "@sentry/cli-darwin": "npm:2.50.2" - "@sentry/cli-linux-arm": "npm:2.50.2" - "@sentry/cli-linux-arm64": "npm:2.50.2" - "@sentry/cli-linux-i686": "npm:2.50.2" - "@sentry/cli-linux-x64": "npm:2.50.2" - "@sentry/cli-win32-arm64": "npm:2.50.2" - "@sentry/cli-win32-i686": "npm:2.50.2" - "@sentry/cli-win32-x64": "npm:2.50.2" - https-proxy-agent: "npm:^5.0.0" - node-fetch: "npm:^2.6.7" - progress: "npm:^2.0.3" - proxy-from-env: "npm:^1.1.0" - which: "npm:^2.0.2" - dependenciesMeta: - "@sentry/cli-darwin": - optional: true - "@sentry/cli-linux-arm": - optional: true - "@sentry/cli-linux-arm64": - optional: true - "@sentry/cli-linux-i686": - optional: true - "@sentry/cli-linux-x64": - optional: true - "@sentry/cli-win32-arm64": - optional: true - "@sentry/cli-win32-i686": - optional: true - "@sentry/cli-win32-x64": - optional: true - bin: - sentry-cli: bin/sentry-cli - checksum: 10c0/10e834e58f655ba27462ac80bc847f31c9ef37b0e82e872475397bca10f35dcb85978877da007d65b2e6977a5852dd1d7d05eef9951ec526ff1d85c162fed119 - languageName: node - linkType: hard - -"@sentry/core@npm:8.55.1": - version: 8.55.1 - resolution: "@sentry/core@npm:8.55.1" - checksum: 10c0/4672f1bb4d3f0fe5aa816d38ee28cd42a19fc66f2cdadbb9b2170e8bb10c7edf3521237cacc81a8ed155c6c68f30ba6922e380401276bf11a6baa1b081542602 - languageName: node - linkType: hard - -"@sentry/react@npm:^8.0.0": - version: 8.55.1 - resolution: "@sentry/react@npm:8.55.1" - dependencies: - "@sentry/browser": "npm:8.55.1" - "@sentry/core": "npm:8.55.1" - hoist-non-react-statics: "npm:^3.3.2" - peerDependencies: - react: ^16.14.0 || 17.x || 18.x || 19.x - checksum: 10c0/7fe204425117090169c62986e54b9b0da7ea0ef2a9fc1a4e9164d7fe75737208733b95a71f2bd4b5a3b7c4326f3a954b03bd2f69ee7b6b2fac75c751b033c1c8 - languageName: node - linkType: hard - -"@sentry/vite-plugin@npm:^3.0.0": - version: 3.6.1 - resolution: "@sentry/vite-plugin@npm:3.6.1" - dependencies: - "@sentry/bundler-plugin-core": "npm:3.6.1" - unplugin: "npm:1.0.1" - checksum: 10c0/407c5d4fab3bb118e39c4068e3c16fbda0c94e06b3a0df8cbbe8a474771adabbf5f97a46774108b9df142d56b34f5dfc1d6292df03375ab0b29210b8b402d83a - languageName: node - linkType: hard - -"@sindresorhus/base62@npm:^1.0.0": - version: 1.0.0 - resolution: "@sindresorhus/base62@npm:1.0.0" - checksum: 10c0/9a14df0f058fdf4731c30f0f05728a4822144ee42236030039d7fa5a1a1072c2879feba8091fd4a17c8922d1056bc07bada77c31fddc3e15836fc05a266fd918 - languageName: node - linkType: hard - -"@standard-schema/spec@npm:^1.1.0": - version: 1.1.0 - resolution: "@standard-schema/spec@npm:1.1.0" - checksum: 10c0/d90f55acde4b2deb983529c87e8025fa693de1a5e8b49ecc6eb84d1fd96328add0e03d7d551442156c7432fd78165b2c26ff561b970a9a881f046abb78d6a526 - languageName: node - linkType: hard - -"@storybook/addon-docs@npm:^10.3.3": - version: 10.3.3 - resolution: "@storybook/addon-docs@npm:10.3.3" - dependencies: - "@mdx-js/react": "npm:^3.0.0" - "@storybook/csf-plugin": "npm:10.3.3" - "@storybook/icons": "npm:^2.0.1" - "@storybook/react-dom-shim": "npm:10.3.3" - react: "npm:^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" - react-dom: "npm:^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" - ts-dedent: "npm:^2.0.0" - peerDependencies: - storybook: ^10.3.3 - checksum: 10c0/19a98f3e8fcf97d35bb25f6cda49708e56006e445d9f04cd80eb697ee452c158203af1f4f3e71358e47a2e257d7fdb85c29ece5f4b36f71dff95070ca4a85af2 - languageName: node - linkType: hard - -"@storybook/builder-vite@npm:10.3.3": - version: 10.3.3 - resolution: "@storybook/builder-vite@npm:10.3.3" - dependencies: - "@storybook/csf-plugin": "npm:10.3.3" - ts-dedent: "npm:^2.0.0" - peerDependencies: - storybook: ^10.3.3 - vite: ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0 - checksum: 10c0/90b002777ff4b0b31ea4bc8d4f6e13f4d4c35a51c2bad7cf0b2e0a3a2f4ec3aa387f87ed174f7589d29842564f61346415dc0c919819e9ab45827c2c0f6141f2 - languageName: node - linkType: hard - -"@storybook/csf-plugin@npm:10.3.3": - version: 10.3.3 - resolution: "@storybook/csf-plugin@npm:10.3.3" - dependencies: - unplugin: "npm:^2.3.5" - peerDependencies: - esbuild: "*" - rollup: "*" - storybook: ^10.3.3 - vite: "*" - webpack: "*" - peerDependenciesMeta: - esbuild: - optional: true - rollup: - optional: true - vite: - optional: true - webpack: - optional: true - checksum: 10c0/62d52c50555ca0f18907962179aa90287e6b95ba6b31cbbeb071842f1580491ff8578cc628f9fd1809a0ef48e2b23164657204c2de16a3f7c9830c4b69c822aa - languageName: node - linkType: hard - -"@storybook/global@npm:^5.0.0": - version: 5.0.0 - resolution: "@storybook/global@npm:5.0.0" - checksum: 10c0/8f1b61dcdd3a89584540896e659af2ecc700bc740c16909a7be24ac19127ea213324de144a141f7caf8affaed017d064fea0618d453afbe027cf60f54b4a6d0b - languageName: node - linkType: hard - -"@storybook/icons@npm:^2.0.1": - version: 2.0.1 - resolution: "@storybook/icons@npm:2.0.1" - peerDependencies: - react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 - react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 - checksum: 10c0/df2bbf1a5b50f12ab1bf78cae6de4dbf7c49df0e3a5f845553b51b20adbe8386a09fd172ea60342379f9284bb528cba2d0e2659cae6eb8d015cf92c8b32f1222 - languageName: node - linkType: hard - -"@storybook/react-dom-shim@npm:10.3.3": - version: 10.3.3 - resolution: "@storybook/react-dom-shim@npm:10.3.3" - peerDependencies: - react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 - react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 - storybook: ^10.3.3 - checksum: 10c0/d4018e1e2acf64d521a13b2190d263b2e873ac65172facda7e443716ede593195e21bb9e0cd288e785a25a5973527813a5ccdb069881a2bc22e490342237d026 - languageName: node - linkType: hard - -"@storybook/react-vite@npm:^10.3.3": - version: 10.3.3 - resolution: "@storybook/react-vite@npm:10.3.3" - dependencies: - "@joshwooding/vite-plugin-react-docgen-typescript": "npm:^0.6.4" - "@rollup/pluginutils": "npm:^5.0.2" - "@storybook/builder-vite": "npm:10.3.3" - "@storybook/react": "npm:10.3.3" - empathic: "npm:^2.0.0" - magic-string: "npm:^0.30.0" - react-docgen: "npm:^8.0.0" - resolve: "npm:^1.22.8" - tsconfig-paths: "npm:^4.2.0" - peerDependencies: - react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 - react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 - storybook: ^10.3.3 - vite: ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0 - checksum: 10c0/6c044a398201ee35d973269c8d47def841caba628b20df95c316d0723a02b798167366de26281ce2c934a844d69c5a51f1e1bc6d11d7ee20219e3cd59d3c9343 - languageName: node - linkType: hard - -"@storybook/react@npm:10.3.3": - version: 10.3.3 - resolution: "@storybook/react@npm:10.3.3" - dependencies: - "@storybook/global": "npm:^5.0.0" - "@storybook/react-dom-shim": "npm:10.3.3" - react-docgen: "npm:^8.0.2" - react-docgen-typescript: "npm:^2.2.2" - peerDependencies: - react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 - react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 - storybook: ^10.3.3 - typescript: ">= 4.9.x" - peerDependenciesMeta: - typescript: - optional: true - checksum: 10c0/a6c36e4e14685348faf50b74de43603d23e0d18aaa21d16e91f6e0b274b1ab689033a8a42b424d776dcdfefa744a6d919a2f509dae8e0520a19b0b20503a1fa7 - languageName: node - linkType: hard - -"@stylistic/eslint-plugin@npm:^3.0.0": - version: 3.1.0 - resolution: "@stylistic/eslint-plugin@npm:3.1.0" - dependencies: - "@typescript-eslint/utils": "npm:^8.13.0" - eslint-visitor-keys: "npm:^4.2.0" - espree: "npm:^10.3.0" - estraverse: "npm:^5.3.0" - picomatch: "npm:^4.0.2" - peerDependencies: - eslint: ">=8.40.0" - checksum: 10c0/e593d78103a89e0555c119625c0ba8c80c8d2c7add0e85215f6be9929002207067df53714785c2c75b8b9e6df774d25c7dead211aed89a57cb45b5cec902a19e - languageName: node - linkType: hard - -"@svgr/babel-plugin-add-jsx-attribute@npm:8.0.0": - version: 8.0.0 - resolution: "@svgr/babel-plugin-add-jsx-attribute@npm:8.0.0" - peerDependencies: - "@babel/core": ^7.0.0-0 - checksum: 10c0/a50bd0baa34faf16bcba712091f94c7f0e230431fe99a9dfc3401fa92823ad3f68495b86ab9bf9044b53839e8c416cfbb37eb3f246ff33f261e0fa9ee1779c5b - languageName: node - linkType: hard - -"@svgr/babel-plugin-remove-jsx-attribute@npm:8.0.0": - version: 8.0.0 - resolution: "@svgr/babel-plugin-remove-jsx-attribute@npm:8.0.0" - peerDependencies: - "@babel/core": ^7.0.0-0 - checksum: 10c0/8a98e59bd9971e066815b4129409932f7a4db4866834fe75677ea6d517972fb40b380a69a4413189f20e7947411f9ab1b0f029dd5e8068686a5a0188d3ccd4c7 - languageName: node - linkType: hard - -"@svgr/babel-plugin-remove-jsx-empty-expression@npm:8.0.0": - version: 8.0.0 - resolution: "@svgr/babel-plugin-remove-jsx-empty-expression@npm:8.0.0" - peerDependencies: - "@babel/core": ^7.0.0-0 - checksum: 10c0/517dcca75223bd05d3f056a8514dbba3031278bea4eadf0842c576d84f4651e7a4e0e7082d3ee4ef42456de0f9c4531d8a1917c04876ca64b014b859ca8f1bde - languageName: node - linkType: hard - -"@svgr/babel-plugin-replace-jsx-attribute-value@npm:8.0.0": - version: 8.0.0 - resolution: "@svgr/babel-plugin-replace-jsx-attribute-value@npm:8.0.0" - peerDependencies: - "@babel/core": ^7.0.0-0 - checksum: 10c0/004bd1892053b7e9c1b0bb14acc44e77634ec393722b87b1e4fae53e2c35122a2dd0d5c15e9070dbeec274e22e7693a2b8b48506733a8009ee92b12946fcb10a - languageName: node - linkType: hard - -"@svgr/babel-plugin-svg-dynamic-title@npm:8.0.0": - version: 8.0.0 - resolution: "@svgr/babel-plugin-svg-dynamic-title@npm:8.0.0" - peerDependencies: - "@babel/core": ^7.0.0-0 - checksum: 10c0/80e0a7fcf902f984c705051ca5c82ea6050ccbb70b651a8fea6d0eb5809e4dac274b49ea6be2d87f1eb9dfc0e2d6cdfffe1669ec2117f44b67a60a07d4c0b8b8 - languageName: node - linkType: hard - -"@svgr/babel-plugin-svg-em-dimensions@npm:8.0.0": - version: 8.0.0 - resolution: "@svgr/babel-plugin-svg-em-dimensions@npm:8.0.0" - peerDependencies: - "@babel/core": ^7.0.0-0 - checksum: 10c0/73e92c8277a89279745c0c500f59f083279a8dc30cd552b22981fade2a77628fb2bd2819ee505725fcd2e93f923e3790b52efcff409a159e657b46604a0b9a21 - languageName: node - linkType: hard - -"@svgr/babel-plugin-transform-react-native-svg@npm:8.1.0": - version: 8.1.0 - resolution: "@svgr/babel-plugin-transform-react-native-svg@npm:8.1.0" - peerDependencies: - "@babel/core": ^7.0.0-0 - checksum: 10c0/655ed6bc7a208ceaa4ecff0a54ccc36008c3cb31efa90d11e171cab325ebbb21aa78f09c7b65f9b3ddeda3a85f348c0c862902c48be13c14b4de165c847974e3 - languageName: node - linkType: hard - -"@svgr/babel-plugin-transform-svg-component@npm:8.0.0": - version: 8.0.0 - resolution: "@svgr/babel-plugin-transform-svg-component@npm:8.0.0" - peerDependencies: - "@babel/core": ^7.0.0-0 - checksum: 10c0/4ac00bb99a3db4ef05e4362f116a3c608ee365a2d26cf7318d8d41a4a5b30a02c80455cce0e62c65b60ed815b5d632bedabac2ccd4b56f998fadef5286e3ded4 - languageName: node - linkType: hard - -"@svgr/babel-preset@npm:8.1.0": - version: 8.1.0 - resolution: "@svgr/babel-preset@npm:8.1.0" - dependencies: - "@svgr/babel-plugin-add-jsx-attribute": "npm:8.0.0" - "@svgr/babel-plugin-remove-jsx-attribute": "npm:8.0.0" - "@svgr/babel-plugin-remove-jsx-empty-expression": "npm:8.0.0" - "@svgr/babel-plugin-replace-jsx-attribute-value": "npm:8.0.0" - "@svgr/babel-plugin-svg-dynamic-title": "npm:8.0.0" - "@svgr/babel-plugin-svg-em-dimensions": "npm:8.0.0" - "@svgr/babel-plugin-transform-react-native-svg": "npm:8.1.0" - "@svgr/babel-plugin-transform-svg-component": "npm:8.0.0" - peerDependencies: - "@babel/core": ^7.0.0-0 - checksum: 10c0/49367d3ad0831f79b1056871b91766246f449d4d1168623af5e283fbaefce4a01d77ab00de6b045b55e956f9aae27895823198493cd232d88d3435ea4517ffc5 - languageName: node - linkType: hard - -"@svgr/core@npm:^8.1.0": - version: 8.1.0 - resolution: "@svgr/core@npm:8.1.0" - dependencies: - "@babel/core": "npm:^7.21.3" - "@svgr/babel-preset": "npm:8.1.0" - camelcase: "npm:^6.2.0" - cosmiconfig: "npm:^8.1.3" - snake-case: "npm:^3.0.4" - checksum: 10c0/6a2f6b1bc79bce39f66f088d468985d518005fc5147ebf4f108570a933818b5951c2cb7da230ddff4b7c8028b5a672b2d33aa2acce012b8b9770073aa5a2d041 - languageName: node - linkType: hard - -"@svgr/hast-util-to-babel-ast@npm:8.0.0": - version: 8.0.0 - resolution: "@svgr/hast-util-to-babel-ast@npm:8.0.0" - dependencies: - "@babel/types": "npm:^7.21.3" - entities: "npm:^4.4.0" - checksum: 10c0/f4165b583ba9eaf6719e598977a7b3ed182f177983e55f9eb55a6a73982d81277510e9eb7ab41f255151fb9ed4edd11ac4bef95dd872f04ed64966d8c85e0f79 - languageName: node - linkType: hard - -"@svgr/plugin-jsx@npm:^8.1.0": - version: 8.1.0 - resolution: "@svgr/plugin-jsx@npm:8.1.0" - dependencies: - "@babel/core": "npm:^7.21.3" - "@svgr/babel-preset": "npm:8.1.0" - "@svgr/hast-util-to-babel-ast": "npm:8.0.0" - svg-parser: "npm:^2.0.4" - peerDependencies: - "@svgr/core": "*" - checksum: 10c0/07b4d9e00de795540bf70556fa2cc258774d01e97a12a26234c6fdf42b309beb7c10f31ee24d1a71137239347b1547b8bb5587d3a6de10669f95dcfe99cddc56 - languageName: node - linkType: hard - -"@testing-library/dom@npm:^10.1.0": - version: 10.4.1 - resolution: "@testing-library/dom@npm:10.4.1" - dependencies: - "@babel/code-frame": "npm:^7.10.4" - "@babel/runtime": "npm:^7.12.5" - "@types/aria-query": "npm:^5.0.1" - aria-query: "npm:5.3.0" - dom-accessibility-api: "npm:^0.5.9" - lz-string: "npm:^1.5.0" - picocolors: "npm:1.1.1" - pretty-format: "npm:^27.0.2" - checksum: 10c0/19ce048012d395ad0468b0dbcc4d0911f6f9e39464d7a8464a587b29707eed5482000dad728f5acc4ed314d2f4d54f34982999a114d2404f36d048278db815b1 - languageName: node - linkType: hard - -"@testing-library/jest-dom@npm:^6.6.3, @testing-library/jest-dom@npm:^6.9.1": - version: 6.9.1 - resolution: "@testing-library/jest-dom@npm:6.9.1" - dependencies: - "@adobe/css-tools": "npm:^4.4.0" - aria-query: "npm:^5.0.0" - css.escape: "npm:^1.5.1" - dom-accessibility-api: "npm:^0.6.3" - picocolors: "npm:^1.1.1" - redent: "npm:^3.0.0" - checksum: 10c0/4291ebd2f0f38d14cefac142c56c337941775a5807e2a3d6f1a14c2fbd6be76a18e498ed189e95bedc97d9e8cf1738049bc76c85b5bc5e23fae7c9e10f7b3a12 - languageName: node - linkType: hard - -"@testing-library/react@npm:^16.0.0": - version: 16.3.2 - resolution: "@testing-library/react@npm:16.3.2" - dependencies: - "@babel/runtime": "npm:^7.12.5" - peerDependencies: - "@testing-library/dom": ^10.0.0 - "@types/react": ^18.0.0 || ^19.0.0 - "@types/react-dom": ^18.0.0 || ^19.0.0 - react: ^18.0.0 || ^19.0.0 - react-dom: ^18.0.0 || ^19.0.0 - peerDependenciesMeta: - "@types/react": - optional: true - "@types/react-dom": - optional: true - checksum: 10c0/f9c7f0915e1b5f7b750e6c7d8b51f091b8ae7ea99bacb761d7b8505ba25de9cfcb749a0f779f1650fb268b499dd79165dc7e1ee0b8b4cb63430d3ddc81ffe044 - languageName: node - linkType: hard - -"@testing-library/user-event@npm:^14.5.1, @testing-library/user-event@npm:^14.6.1": - version: 14.6.1 - resolution: "@testing-library/user-event@npm:14.6.1" - peerDependencies: - "@testing-library/dom": ">=7.21.4" - checksum: 10c0/75fea130a52bf320d35d46ed54f3eec77e71a56911b8b69a3fe29497b0b9947b2dc80d30f04054ad4ce7f577856ae3e5397ea7dff0ef14944d3909784c7a93fe - languageName: node - linkType: hard - -"@tybys/wasm-util@npm:^0.10.1": - version: 0.10.1 - resolution: "@tybys/wasm-util@npm:0.10.1" - dependencies: - tslib: "npm:^2.4.0" - checksum: 10c0/b255094f293794c6d2289300c5fbcafbb5532a3aed3a5ffd2f8dc1828e639b88d75f6a376dd8f94347a44813fd7a7149d8463477a9a49525c8b2dcaa38c2d1e8 - languageName: node - linkType: hard - -"@types/aria-query@npm:^5.0.1": - version: 5.0.4 - resolution: "@types/aria-query@npm:5.0.4" - checksum: 10c0/dc667bc6a3acc7bba2bccf8c23d56cb1f2f4defaa704cfef595437107efaa972d3b3db9ec1d66bc2711bfc35086821edd32c302bffab36f2e79b97f312069f08 - languageName: node - linkType: hard - -"@types/babel__core@npm:^7.1.12, @types/babel__core@npm:^7.20.5": - version: 7.20.5 - resolution: "@types/babel__core@npm:7.20.5" - dependencies: - "@babel/parser": "npm:^7.20.7" - "@babel/types": "npm:^7.20.7" - "@types/babel__generator": "npm:*" - "@types/babel__template": "npm:*" - "@types/babel__traverse": "npm:*" - checksum: 10c0/bdee3bb69951e833a4b811b8ee9356b69a61ed5b7a23e1a081ec9249769117fa83aaaf023bb06562a038eb5845155ff663e2d5c75dd95c1d5ccc91db012868ff - languageName: node - linkType: hard - -"@types/babel__generator@npm:*": - version: 7.6.8 - resolution: "@types/babel__generator@npm:7.6.8" - dependencies: - "@babel/types": "npm:^7.0.0" - checksum: 10c0/f0ba105e7d2296bf367d6e055bb22996886c114261e2cb70bf9359556d0076c7a57239d019dee42bb063f565bade5ccb46009bce2044b2952d964bf9a454d6d2 - languageName: node - linkType: hard - -"@types/babel__template@npm:*": - version: 7.4.4 - resolution: "@types/babel__template@npm:7.4.4" - dependencies: - "@babel/parser": "npm:^7.1.0" - "@babel/types": "npm:^7.0.0" - checksum: 10c0/cc84f6c6ab1eab1427e90dd2b76ccee65ce940b778a9a67be2c8c39e1994e6f5bbc8efa309f6cea8dc6754994524cd4d2896558df76d92e7a1f46ecffee7112b - languageName: node - linkType: hard - -"@types/babel__traverse@npm:*": - version: 7.20.6 - resolution: "@types/babel__traverse@npm:7.20.6" - dependencies: - "@babel/types": "npm:^7.20.7" - checksum: 10c0/7ba7db61a53e28cac955aa99af280d2600f15a8c056619c05b6fc911cbe02c61aa4f2823299221b23ce0cce00b294c0e5f618ec772aa3f247523c2e48cf7b888 - languageName: node - linkType: hard - -"@types/babel__traverse@npm:^7.20.7": - version: 7.28.0 - resolution: "@types/babel__traverse@npm:7.28.0" - dependencies: - "@babel/types": "npm:^7.28.2" - checksum: 10c0/b52d7d4e8fc6a9018fe7361c4062c1c190f5778cf2466817cb9ed19d69fbbb54f9a85ffedeb748ed8062d2cf7d4cc088ee739848f47c57740de1c48cbf0d0994 - languageName: node - linkType: hard - -"@types/chai@npm:^5.2.2": - version: 5.2.2 - resolution: "@types/chai@npm:5.2.2" - dependencies: - "@types/deep-eql": "npm:*" - checksum: 10c0/49282bf0e8246800ebb36f17256f97bd3a8c4fb31f92ad3c0eaa7623518d7e87f1eaad4ad206960fcaf7175854bdff4cb167e4fe96811e0081b4ada83dd533ec - languageName: node - linkType: hard - -"@types/content-type@npm:^1.1.5": - version: 1.1.9 - resolution: "@types/content-type@npm:1.1.9" - checksum: 10c0/d8b198257862991880d38985ad9871241db18b21ec728bddc78e4c61e0f987cc037dae6c5f9bd2bcc08f41de74ad371180af2fcdefeafe25d0ccae0c3fceb7fd - languageName: node - linkType: hard - -"@types/deep-eql@npm:*": - version: 4.0.2 - resolution: "@types/deep-eql@npm:4.0.2" - checksum: 10c0/bf3f811843117900d7084b9d0c852da9a044d12eb40e6de73b552598a6843c21291a8a381b0532644574beecd5e3491c5ff3a0365ab86b15d59862c025384844 - languageName: node - linkType: hard - -"@types/doctrine@npm:^0.0.9": - version: 0.0.9 - resolution: "@types/doctrine@npm:0.0.9" - checksum: 10c0/cdaca493f13c321cf0cacd1973efc0ae74569633145d9e6fc1128f32217a6968c33bea1f858275239fe90c98f3be57ec8f452b416a9ff48b8e8c1098b20fa51c - languageName: node - linkType: hard - -"@types/estree@npm:^1.0.0": - version: 1.0.6 - resolution: "@types/estree@npm:1.0.6" - checksum: 10c0/cdfd751f6f9065442cd40957c07fd80361c962869aa853c1c2fd03e101af8b9389d8ff4955a43a6fcfa223dd387a089937f95be0f3eec21ca527039fd2d9859a - languageName: node - linkType: hard - -"@types/estree@npm:^1.0.8": - version: 1.0.8 - resolution: "@types/estree@npm:1.0.8" - checksum: 10c0/39d34d1afaa338ab9763f37ad6066e3f349444f9052b9676a7cc0252ef9485a41c6d81c9c4e0d26e9077993354edf25efc853f3224dd4b447175ef62bdcc86a5 - languageName: node - linkType: hard - -"@types/events@npm:^3.0.0": - version: 3.0.3 - resolution: "@types/events@npm:3.0.3" - checksum: 10c0/3a56f8c51eb4ebc0d05dcadca0c6636c816acc10216ce36c976fad11e54a01f4bb979a07211355686015884753b37f17d74bfdc7aaf4ebb027c1e8a501c7b21d - languageName: node - linkType: hard - -"@types/glob-to-regexp@npm:^0.4.4": - version: 0.4.4 - resolution: "@types/glob-to-regexp@npm:0.4.4" - checksum: 10c0/7288ff853850d8302a8770a3698b187fc3970ad12ee6427f0b3758a3e7a0ebb0bd993abc6ebaaa979d09695b4194157d2bfaa7601b0fb9ed72c688b4c1298b88 - languageName: node - linkType: hard - -"@types/grecaptcha@npm:^3.0.9": - version: 3.0.9 - resolution: "@types/grecaptcha@npm:3.0.9" - checksum: 10c0/65986cd1d060309ca0eaa1ab5a758ba0203f09c20941534d05b5dfe0fb6fd258ea0e20fa77980d5abf741ba98846e874fd7d2f883aead65dedfa56b278a811e9 - languageName: node - linkType: hard - -"@types/jsdom@npm:^21.1.7": - version: 21.1.7 - resolution: "@types/jsdom@npm:21.1.7" - dependencies: - "@types/node": "npm:*" - "@types/tough-cookie": "npm:*" - parse5: "npm:^7.0.0" - checksum: 10c0/c0c0025adc2b193e85453eeeea168bb909f0ebad08d6552be7474a407e9c163db8f696dcf1e3cbe8cb9c9d970ba45f4386171794509c1a0fe5d1fed72c91679d - languageName: node - linkType: hard - -"@types/json-schema@npm:^7.0.9": - version: 7.0.15 - resolution: "@types/json-schema@npm:7.0.15" - checksum: 10c0/a996a745e6c5d60292f36731dd41341339d4eeed8180bb09226e5c8d23759067692b1d88e5d91d72ee83dfc00d3aca8e7bd43ea120516c17922cbcb7c3e252db - languageName: node - linkType: hard - -"@types/json5@npm:^0.0.29": - version: 0.0.29 - resolution: "@types/json5@npm:0.0.29" - checksum: 10c0/6bf5337bc447b706bb5b4431d37686aa2ea6d07cfd6f79cc31de80170d6ff9b1c7384a9c0ccbc45b3f512bae9e9f75c2e12109806a15331dc94e8a8db6dbb4ac - languageName: node - linkType: hard - -"@types/lodash-es@npm:^4.17.12": - version: 4.17.12 - resolution: "@types/lodash-es@npm:4.17.12" - dependencies: - "@types/lodash": "npm:*" - checksum: 10c0/5d12d2cede07f07ab067541371ed1b838a33edb3c35cb81b73284e93c6fd0c4bbeaefee984e69294bffb53f62d7272c5d679fdba8e595ff71e11d00f2601dde0 - languageName: node - linkType: hard - -"@types/lodash@npm:*": - version: 4.17.13 - resolution: "@types/lodash@npm:4.17.13" - checksum: 10c0/c3d0b7efe7933ac0369b99f2f7bff9240d960680fdb74b41ed4bd1b3ca60cca1e31fe4046d9abbde778f941a41bc2a75eb629abf8659fa6c27b66efbbb0802a9 - languageName: node - linkType: hard - -"@types/mdx@npm:^2.0.0": - version: 2.0.13 - resolution: "@types/mdx@npm:2.0.13" - checksum: 10c0/5edf1099505ac568da55f9ae8a93e7e314e8cbc13d3445d0be61b75941226b005e1390d9b95caecf5dcb00c9d1bab2f1f60f6ff9876dc091a48b547495007720 - languageName: node - linkType: hard - -"@types/minimatch@npm:^3.0.3": - version: 3.0.5 - resolution: "@types/minimatch@npm:3.0.5" - checksum: 10c0/a1a19ba342d6f39b569510f621ae4bbe972dc9378d15e9a5e47904c440ee60744f5b09225bc73be1c6490e3a9c938eee69eb53debf55ce1f15761201aa965f97 - languageName: node - linkType: hard - -"@types/node@npm:*": - version: 25.5.0 - resolution: "@types/node@npm:25.5.0" - dependencies: - undici-types: "npm:~7.18.0" - checksum: 10c0/70c508165b6758c4f88d4f91abca526c3985eee1985503d4c2bd994dbaf588e52ac57e571160f18f117d76e963570ac82bd20e743c18987e82564312b3b62119 - languageName: node - linkType: hard - -"@types/node@npm:^24.0.0": - version: 24.12.0 - resolution: "@types/node@npm:24.12.0" - dependencies: - undici-types: "npm:~7.16.0" - checksum: 10c0/8b31c0af5b5474f13048a4e77c57f22cd4f8fe6e58c4b6fde9456b0c13f46a5bfaf5744ff88fd089581de9f0d6e99c584e022681de7acb26a58d258c654c4843 - languageName: node - linkType: hard - -"@types/normalize-package-data@npm:^2.4.0": - version: 2.4.4 - resolution: "@types/normalize-package-data@npm:2.4.4" - checksum: 10c0/aef7bb9b015883d6f4119c423dd28c4bdc17b0e8a0ccf112c78b4fe0e91fbc4af7c6204b04bba0e199a57d2f3fbbd5b4a14bf8739bf9d2a39b2a0aad545e0f86 - languageName: node - linkType: hard - -"@types/pako@npm:^2.0.3": - version: 2.0.4 - resolution: "@types/pako@npm:2.0.4" - checksum: 10c0/5765bf8bc7e77ee141c454118f03e544b8f6cb51eb257d82dc5830feeab8cd00818af3a1eabefdfbe8dd3ae9916ed5403937bf1031a0ee51deea27fdf4dccdfb - languageName: node - linkType: hard - -"@types/qrcode@npm:^1.5.5": - version: 1.5.6 - resolution: "@types/qrcode@npm:1.5.6" - dependencies: - "@types/node": "npm:*" - checksum: 10c0/84844ca63e5f32bc47d44dda0f8a6f7cdcc7ce44e7b24f10f19d50796f31d12c058f702a8f7d352c9e82a023a9abc36fa1ad01ddf0a209dd8ed4562ea76481fc - languageName: node - linkType: hard - -"@types/react-dom@npm:^19.0.0": - version: 19.2.3 - resolution: "@types/react-dom@npm:19.2.3" - peerDependencies: - "@types/react": ^19.2.0 - checksum: 10c0/b486ebe0f4e2fb35e2e108df1d8fc0927ca5d6002d5771e8a739de11239fe62d0e207c50886185253c99eb9dedfeeb956ea7429e5ba17f6693c7acb4c02f8cd1 - languageName: node - linkType: hard - -"@types/react@npm:^19.0.0": - version: 19.2.14 - resolution: "@types/react@npm:19.2.14" - dependencies: - csstype: "npm:^3.2.2" - checksum: 10c0/7d25bf41b57719452d86d2ac0570b659210402707313a36ee612666bf11275a1c69824f8c3ee1fdca077ccfe15452f6da8f1224529b917050eb2d861e52b59b7 - languageName: node - linkType: hard - -"@types/resolve@npm:^1.20.2": - version: 1.20.6 - resolution: "@types/resolve@npm:1.20.6" - checksum: 10c0/a9b0549d816ff2c353077365d865a33655a141d066d0f5a3ba6fd4b28bc2f4188a510079f7c1f715b3e7af505a27374adce2a5140a3ece2a059aab3d6e1a4244 - languageName: node - linkType: hard - -"@types/sdp-transform@npm:^2.4.5": - version: 2.15.0 - resolution: "@types/sdp-transform@npm:2.15.0" - checksum: 10c0/8740a51ef3478dcc560952d815edb650680f924e00fcb19eea74a8422640e9a1e18a63d9dda750576598cb1c15b8bb6a68bd5076a9e9ac170d828cb97fa1ff26 - languageName: node - linkType: hard - -"@types/semver@npm:^7.3.12": - version: 7.5.8 - resolution: "@types/semver@npm:7.5.8" - checksum: 10c0/8663ff927234d1c5fcc04b33062cb2b9fcfbe0f5f351ed26c4d1e1581657deebd506b41ff7fdf89e787e3d33ce05854bc01686379b89e9c49b564c4cfa988efa - languageName: node - linkType: hard - -"@types/symlink-or-copy@npm:^1.2.0": - version: 1.2.2 - resolution: "@types/symlink-or-copy@npm:1.2.2" - checksum: 10c0/09ee39bd319f39c775c4e2049fc4018212b9b6043736bd2046537acbb59c98af7aa725c539f32672cd2ca27144073fa1f1101b4c0ed7db3fbddb305b638895b2 - languageName: node - linkType: hard - -"@types/tough-cookie@npm:*": - version: 4.0.5 - resolution: "@types/tough-cookie@npm:4.0.5" - checksum: 10c0/68c6921721a3dcb40451543db2174a145ef915bc8bcbe7ad4e59194a0238e776e782b896c7a59f4b93ac6acefca9161fccb31d1ce3b3445cb6faa467297fb473 - languageName: node - linkType: hard - -"@types/uuid@npm:10": - version: 10.0.0 - resolution: "@types/uuid@npm:10.0.0" - checksum: 10c0/9a1404bf287164481cb9b97f6bb638f78f955be57c40c6513b7655160beb29df6f84c915aaf4089a1559c216557dc4d2f79b48d978742d3ae10b937420ddac60 - languageName: node - linkType: hard - -"@types/yargs-parser@npm:*": - version: 21.0.3 - resolution: "@types/yargs-parser@npm:21.0.3" - checksum: 10c0/e71c3bd9d0b73ca82e10bee2064c384ab70f61034bbfb78e74f5206283fc16a6d85267b606b5c22cb2a3338373586786fed595b2009825d6a9115afba36560a0 - languageName: node - linkType: hard - -"@types/yargs@npm:^17.0.0": - version: 17.0.33 - resolution: "@types/yargs@npm:17.0.33" - dependencies: - "@types/yargs-parser": "npm:*" - checksum: 10c0/d16937d7ac30dff697801c3d6f235be2166df42e4a88bf730fa6dc09201de3727c0a9500c59a672122313341de5f24e45ee0ff579c08ce91928e519090b7906b - languageName: node - linkType: hard - -"@typescript-eslint/eslint-plugin@npm:^8.31.0": - version: 8.58.0 - resolution: "@typescript-eslint/eslint-plugin@npm:8.58.0" - dependencies: - "@eslint-community/regexpp": "npm:^4.12.2" - "@typescript-eslint/scope-manager": "npm:8.58.0" - "@typescript-eslint/type-utils": "npm:8.58.0" - "@typescript-eslint/utils": "npm:8.58.0" - "@typescript-eslint/visitor-keys": "npm:8.58.0" - ignore: "npm:^7.0.5" - natural-compare: "npm:^1.4.0" - ts-api-utils: "npm:^2.5.0" - peerDependencies: - "@typescript-eslint/parser": ^8.58.0 - eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 - typescript: ">=4.8.4 <6.1.0" - checksum: 10c0/ac45c30f6ba9e188a01144708aa845e7ee8bb8a4d4f9aa6d2dce7784852d0821d42b031fee6832069935c3b885feff6d4014e30145b99693d25d7f563266a9f8 - languageName: node - linkType: hard - -"@typescript-eslint/experimental-utils@npm:^5.0.0": - version: 5.62.0 - resolution: "@typescript-eslint/experimental-utils@npm:5.62.0" - dependencies: - "@typescript-eslint/utils": "npm:5.62.0" - peerDependencies: - eslint: ^6.0.0 || ^7.0.0 || ^8.0.0 - checksum: 10c0/f7037977e00849cd8c03677a88b0659a4f0e0b1e0151aebb47c49c92b8e57408578142df598eac08b364623d926343c724f42494f87662e437b1c89f0b2e815b - languageName: node - linkType: hard - -"@typescript-eslint/parser@npm:^8.31.0": - version: 8.58.0 - resolution: "@typescript-eslint/parser@npm:8.58.0" - dependencies: - "@typescript-eslint/scope-manager": "npm:8.58.0" - "@typescript-eslint/types": "npm:8.58.0" - "@typescript-eslint/typescript-estree": "npm:8.58.0" - "@typescript-eslint/visitor-keys": "npm:8.58.0" - debug: "npm:^4.4.3" - peerDependencies: - eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 - typescript: ">=4.8.4 <6.1.0" - checksum: 10c0/56c7ec21675cec4730760bfa37c29e42e80b4d6444e2beca55fad9ef53731392270d142797482ea798405be0d7e28ec6c9c16a1ee2ee1c94f73d3bf0ed29763c - languageName: node - linkType: hard - -"@typescript-eslint/project-service@npm:8.57.2": - version: 8.57.2 - resolution: "@typescript-eslint/project-service@npm:8.57.2" - dependencies: - "@typescript-eslint/tsconfig-utils": "npm:^8.57.2" - "@typescript-eslint/types": "npm:^8.57.2" - debug: "npm:^4.4.3" - peerDependencies: - typescript: ">=4.8.4 <6.0.0" - checksum: 10c0/f84e3165b0a214318d4bc119018b87c044170d7638945e84bd4cee2d752b62c1797ce722ca1161cd06f48512d0115ef75500e6c8fc01005ad4bb39fb48dd77bf - languageName: node - linkType: hard - -"@typescript-eslint/project-service@npm:8.58.0": - version: 8.58.0 - resolution: "@typescript-eslint/project-service@npm:8.58.0" - dependencies: - "@typescript-eslint/tsconfig-utils": "npm:^8.58.0" - "@typescript-eslint/types": "npm:^8.58.0" - debug: "npm:^4.4.3" - peerDependencies: - typescript: ">=4.8.4 <6.1.0" - checksum: 10c0/e6d0cb2f7708ccb31a2ff9eb35817d4999c26e1f1cd3c607539e21d0c73a234daa77c73ee1163bc4e8b139252d619823c444759f1ddabdd138cab4885e9c9794 - languageName: node - linkType: hard - -"@typescript-eslint/scope-manager@npm:5.62.0": - version: 5.62.0 - resolution: "@typescript-eslint/scope-manager@npm:5.62.0" - dependencies: - "@typescript-eslint/types": "npm:5.62.0" - "@typescript-eslint/visitor-keys": "npm:5.62.0" - checksum: 10c0/861253235576c1c5c1772d23cdce1418c2da2618a479a7de4f6114a12a7ca853011a1e530525d0931c355a8fd237b9cd828fac560f85f9623e24054fd024726f - languageName: node - linkType: hard - -"@typescript-eslint/scope-manager@npm:8.25.0": - version: 8.25.0 - resolution: "@typescript-eslint/scope-manager@npm:8.25.0" - dependencies: - "@typescript-eslint/types": "npm:8.25.0" - "@typescript-eslint/visitor-keys": "npm:8.25.0" - checksum: 10c0/0a53a07873bdb569be38053ec006009cc8ba6b12c538b6df0935afd18e431cb17da1eb15b0c9cd267ac211c47aaa44fbc8d7ff3b7b44ff711621ff305fa3b355 - languageName: node - linkType: hard - -"@typescript-eslint/scope-manager@npm:8.57.2": - version: 8.57.2 - resolution: "@typescript-eslint/scope-manager@npm:8.57.2" - dependencies: - "@typescript-eslint/types": "npm:8.57.2" - "@typescript-eslint/visitor-keys": "npm:8.57.2" - checksum: 10c0/532b1a97a5c2fce51400fa1a94e09615b4df84ce1f2d107206a3f3935074cada396a3e30f155582a698981832868e1afea1641ff779ad9456fdc94169b7def64 - languageName: node - linkType: hard - -"@typescript-eslint/scope-manager@npm:8.58.0": - version: 8.58.0 - resolution: "@typescript-eslint/scope-manager@npm:8.58.0" - dependencies: - "@typescript-eslint/types": "npm:8.58.0" - "@typescript-eslint/visitor-keys": "npm:8.58.0" - checksum: 10c0/bd5c16780f22d62359af0f69909f38a15fa3c55e609124a7cd5c2a04322fe41e586d81066f3ad1dcc3c1eff24dbcb48b78d099626d611fbd680c20c005d48f1d - languageName: node - linkType: hard - -"@typescript-eslint/tsconfig-utils@npm:8.57.2, @typescript-eslint/tsconfig-utils@npm:^8.57.2": - version: 8.57.2 - resolution: "@typescript-eslint/tsconfig-utils@npm:8.57.2" - peerDependencies: - typescript: ">=4.8.4 <6.0.0" - checksum: 10c0/199dad2d96efc88ce94f5f3e12e97205537bf7a7152e56ef1d84dfbe7bd1babebea9b9f396c01b6c447505a4eb02c1cbbd2c28828c587b51b41b15d017a11d2f - languageName: node - linkType: hard - -"@typescript-eslint/tsconfig-utils@npm:8.58.0, @typescript-eslint/tsconfig-utils@npm:^8.58.0": - version: 8.58.0 - resolution: "@typescript-eslint/tsconfig-utils@npm:8.58.0" - peerDependencies: - typescript: ">=4.8.4 <6.1.0" - checksum: 10c0/0a07fe1a28b2513e625882bc8d4c4e0c5a105cdbcb987beae12fc66dbe71dc9638013e4d1fa8ad10d828a2acd5e3fed987c189c00d41fed0e880009f99adf1b2 - languageName: node - linkType: hard - -"@typescript-eslint/type-utils@npm:8.58.0": - version: 8.58.0 - resolution: "@typescript-eslint/type-utils@npm:8.58.0" - dependencies: - "@typescript-eslint/types": "npm:8.58.0" - "@typescript-eslint/typescript-estree": "npm:8.58.0" - "@typescript-eslint/utils": "npm:8.58.0" - debug: "npm:^4.4.3" - ts-api-utils: "npm:^2.5.0" - peerDependencies: - eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 - typescript: ">=4.8.4 <6.1.0" - checksum: 10c0/1223733d41f8463be92ef1ad048d546f9663152212b22dc968abbd9f8e4486bd4082e16baa51d2d281e0d4815563bc4b1ecf01684e2940b7897ba17aa26d1196 - languageName: node - linkType: hard - -"@typescript-eslint/types@npm:5.62.0": - version: 5.62.0 - resolution: "@typescript-eslint/types@npm:5.62.0" - checksum: 10c0/7febd3a7f0701c0b927e094f02e82d8ee2cada2b186fcb938bc2b94ff6fbad88237afc304cbaf33e82797078bbbb1baf91475f6400912f8b64c89be79bfa4ddf - languageName: node - linkType: hard - -"@typescript-eslint/types@npm:8.25.0": - version: 8.25.0 - resolution: "@typescript-eslint/types@npm:8.25.0" - checksum: 10c0/b39addbee4be4d66e3089c2d01f9f1d69cedc13bff20e4fa9ed0ca5a0e7591d7c6e41ab3763c8c35404f971bc0fbf9f7867dbc2832740e5b63ee0049d60289f5 - languageName: node - linkType: hard - -"@typescript-eslint/types@npm:8.57.2, @typescript-eslint/types@npm:^8.57.2": - version: 8.57.2 - resolution: "@typescript-eslint/types@npm:8.57.2" - checksum: 10c0/3cd87dd77d28b3ac2fed56a17909b0d11633628d4d733aa148dfd7af72e2cc3ec0e6114b72fac0ff538e8a47e907b4b10dab4095170ae1bd73719ef0b8eaf2e7 - languageName: node - linkType: hard - -"@typescript-eslint/types@npm:8.58.0, @typescript-eslint/types@npm:^8.58.0": - version: 8.58.0 - resolution: "@typescript-eslint/types@npm:8.58.0" - checksum: 10c0/f2fe1321758a04591c20d77caba956ae76b77cff0b976a0224b37077d80b1ebd826874d15ec79c3a3b7d57ee5679e5d10756db1b082bde3d51addbd3a8431d38 - languageName: node - linkType: hard - -"@typescript-eslint/types@npm:^8.46.4": - version: 8.56.1 - resolution: "@typescript-eslint/types@npm:8.56.1" - checksum: 10c0/e5a0318abddf0c4f98da3039cb10b3c0601c8601f7a9f7043630f0d622dabfe83a4cd833545ad3531fc846e46ca2874377277b392c2490dffec279d9242d827b - languageName: node - linkType: hard - -"@typescript-eslint/typescript-estree@npm:5.62.0": - version: 5.62.0 - resolution: "@typescript-eslint/typescript-estree@npm:5.62.0" - dependencies: - "@typescript-eslint/types": "npm:5.62.0" - "@typescript-eslint/visitor-keys": "npm:5.62.0" - debug: "npm:^4.3.4" - globby: "npm:^11.1.0" - is-glob: "npm:^4.0.3" - semver: "npm:^7.3.7" - tsutils: "npm:^3.21.0" - peerDependenciesMeta: - typescript: - optional: true - checksum: 10c0/d7984a3e9d56897b2481940ec803cb8e7ead03df8d9cfd9797350be82ff765dfcf3cfec04e7355e1779e948da8f02bc5e11719d07a596eb1cb995c48a95e38cf - languageName: node - linkType: hard - -"@typescript-eslint/typescript-estree@npm:8.25.0": - version: 8.25.0 - resolution: "@typescript-eslint/typescript-estree@npm:8.25.0" - dependencies: - "@typescript-eslint/types": "npm:8.25.0" - "@typescript-eslint/visitor-keys": "npm:8.25.0" - debug: "npm:^4.3.4" - fast-glob: "npm:^3.3.2" - is-glob: "npm:^4.0.3" - minimatch: "npm:^9.0.4" - semver: "npm:^7.6.0" - ts-api-utils: "npm:^2.0.1" - peerDependencies: - typescript: ">=4.8.4 <5.8.0" - checksum: 10c0/fc9de1c4f6ab81fb80b632dedef84d1ecf4c0abdc5f5246698deb6d86d5c6b5d582ef8a44fdef445bf7fbfa6658db516fe875c9d7c984bf4802e3a508b061856 - languageName: node - linkType: hard - -"@typescript-eslint/typescript-estree@npm:8.57.2": - version: 8.57.2 - resolution: "@typescript-eslint/typescript-estree@npm:8.57.2" - dependencies: - "@typescript-eslint/project-service": "npm:8.57.2" - "@typescript-eslint/tsconfig-utils": "npm:8.57.2" - "@typescript-eslint/types": "npm:8.57.2" - "@typescript-eslint/visitor-keys": "npm:8.57.2" - debug: "npm:^4.4.3" - minimatch: "npm:^10.2.2" - semver: "npm:^7.7.3" - tinyglobby: "npm:^0.2.15" - ts-api-utils: "npm:^2.4.0" - peerDependencies: - typescript: ">=4.8.4 <6.0.0" - checksum: 10c0/2c5d143f0abbafd07a45f0b956aab5d6487b27f74fe93bee93e0a3f8edc8913f1522faf8d7d5215f3809a8d12f5729910ea522156552f2481b66e6d05ab311ae - languageName: node - linkType: hard - -"@typescript-eslint/typescript-estree@npm:8.58.0": - version: 8.58.0 - resolution: "@typescript-eslint/typescript-estree@npm:8.58.0" - dependencies: - "@typescript-eslint/project-service": "npm:8.58.0" - "@typescript-eslint/tsconfig-utils": "npm:8.58.0" - "@typescript-eslint/types": "npm:8.58.0" - "@typescript-eslint/visitor-keys": "npm:8.58.0" - debug: "npm:^4.4.3" - minimatch: "npm:^10.2.2" - semver: "npm:^7.7.3" - tinyglobby: "npm:^0.2.15" - ts-api-utils: "npm:^2.5.0" - peerDependencies: - typescript: ">=4.8.4 <6.1.0" - checksum: 10c0/a8cb94cb765b27740a54f9b5378bd8f0dc49e301ceed99a0791dc9d1f61c2a54e3212f7ed9120c8c2df80104ad3117150cf5e7fe8a0b7eec3ed04969a79b103e - languageName: node - linkType: hard - -"@typescript-eslint/utils@npm:5.62.0": - version: 5.62.0 - resolution: "@typescript-eslint/utils@npm:5.62.0" - dependencies: - "@eslint-community/eslint-utils": "npm:^4.2.0" - "@types/json-schema": "npm:^7.0.9" - "@types/semver": "npm:^7.3.12" - "@typescript-eslint/scope-manager": "npm:5.62.0" - "@typescript-eslint/types": "npm:5.62.0" - "@typescript-eslint/typescript-estree": "npm:5.62.0" - eslint-scope: "npm:^5.1.1" - semver: "npm:^7.3.7" - peerDependencies: - eslint: ^6.0.0 || ^7.0.0 || ^8.0.0 - checksum: 10c0/f09b7d9952e4a205eb1ced31d7684dd55cee40bf8c2d78e923aa8a255318d97279825733902742c09d8690f37a50243f4c4d383ab16bd7aefaf9c4b438f785e1 - languageName: node - linkType: hard - -"@typescript-eslint/utils@npm:8.58.0": - version: 8.58.0 - resolution: "@typescript-eslint/utils@npm:8.58.0" - dependencies: - "@eslint-community/eslint-utils": "npm:^4.9.1" - "@typescript-eslint/scope-manager": "npm:8.58.0" - "@typescript-eslint/types": "npm:8.58.0" - "@typescript-eslint/typescript-estree": "npm:8.58.0" - peerDependencies: - eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 - typescript: ">=4.8.4 <6.1.0" - checksum: 10c0/457e01a6e6d954dbfe13c49ece3cf8a55e5d8cf19ea9ae7086c0e205d89e3cdbb91153062ab440d2e78ad3f077b174adc42bfb1b6fc24299020a0733e7f9c11c - languageName: node - linkType: hard - -"@typescript-eslint/utils@npm:^8.13.0": - version: 8.25.0 - resolution: "@typescript-eslint/utils@npm:8.25.0" - dependencies: - "@eslint-community/eslint-utils": "npm:^4.4.0" - "@typescript-eslint/scope-manager": "npm:8.25.0" - "@typescript-eslint/types": "npm:8.25.0" - "@typescript-eslint/typescript-estree": "npm:8.25.0" - peerDependencies: - eslint: ^8.57.0 || ^9.0.0 - typescript: ">=4.8.4 <5.8.0" - checksum: 10c0/cd15c4919f02899fd3975049a0a051a1455332a108c085a3e90ae9872e2cddac7f20a9a2c616f1366fca84274649e836ad6a437c9c5ead0bdabf5a123d12403f - languageName: node - linkType: hard - -"@typescript-eslint/utils@npm:^8.48.0": - version: 8.57.2 - resolution: "@typescript-eslint/utils@npm:8.57.2" - dependencies: - "@eslint-community/eslint-utils": "npm:^4.9.1" - "@typescript-eslint/scope-manager": "npm:8.57.2" - "@typescript-eslint/types": "npm:8.57.2" - "@typescript-eslint/typescript-estree": "npm:8.57.2" - peerDependencies: - eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 - typescript: ">=4.8.4 <6.0.0" - checksum: 10c0/5771f3d4206004cc817a6556a472926b4c1c885dc448049c10ffab1d5aac7bd59450a391fb57ce8ef31a8367e9c8ddb3bc9370c4e83fc8b61f50fd5189390e8f - languageName: node - linkType: hard - -"@typescript-eslint/visitor-keys@npm:5.62.0": - version: 5.62.0 - resolution: "@typescript-eslint/visitor-keys@npm:5.62.0" - dependencies: - "@typescript-eslint/types": "npm:5.62.0" - eslint-visitor-keys: "npm:^3.3.0" - checksum: 10c0/7c3b8e4148e9b94d9b7162a596a1260d7a3efc4e65199693b8025c71c4652b8042501c0bc9f57654c1e2943c26da98c0f77884a746c6ae81389fcb0b513d995d - languageName: node - linkType: hard - -"@typescript-eslint/visitor-keys@npm:8.25.0": - version: 8.25.0 - resolution: "@typescript-eslint/visitor-keys@npm:8.25.0" - dependencies: - "@typescript-eslint/types": "npm:8.25.0" - eslint-visitor-keys: "npm:^4.2.0" - checksum: 10c0/7eb84c5899a25b1eb89d3c3f4be3ff18171f934669c57e2530b6dfa5fdd6eaae60629f3c89d06f4c8075fd1c701de76c0b9194e2922895c661ab6091e48f7db9 - languageName: node - linkType: hard - -"@typescript-eslint/visitor-keys@npm:8.57.2": - version: 8.57.2 - resolution: "@typescript-eslint/visitor-keys@npm:8.57.2" - dependencies: - "@typescript-eslint/types": "npm:8.57.2" - eslint-visitor-keys: "npm:^5.0.0" - checksum: 10c0/8ceb8c228bf97b3e4b343bf6e42a91998d2522f459eb6b53c6bfad4898a9df74295660893dee6b698bdbbda537e968bfc13a3c56fc341089ebfba13db766a574 - languageName: node - linkType: hard - -"@typescript-eslint/visitor-keys@npm:8.58.0": - version: 8.58.0 - resolution: "@typescript-eslint/visitor-keys@npm:8.58.0" - dependencies: - "@typescript-eslint/types": "npm:8.58.0" - eslint-visitor-keys: "npm:^5.0.0" - checksum: 10c0/75f3c9c097a308cc6450822a0f81d44c8b79b524e99dd2c41ded347b12f148ab3bd459ce9cc6bd00f8f0725c5831baab6d2561596ead3394ab76dddbeb32cce1 - languageName: node - linkType: hard - -"@ungap/structured-clone@npm:^1.2.0": - version: 1.3.0 - resolution: "@ungap/structured-clone@npm:1.3.0" - checksum: 10c0/0fc3097c2540ada1fc340ee56d58d96b5b536a2a0dab6e3ec17d4bfc8c4c86db345f61a375a8185f9da96f01c69678f836a2b57eeaa9e4b8eeafd26428e57b0a - languageName: node - linkType: hard - -"@use-gesture/core@npm:10.3.1": - version: 10.3.1 - resolution: "@use-gesture/core@npm:10.3.1" - checksum: 10c0/2e3b5c0f7fe26cdb47be3a9c2a58a6a9edafc5b2895b07d2898eda9ab5a2b29fb0098b15597baa0856907b593075cd44cc69bba4785c9cfb7b6fabaa3b52cd3e - languageName: node - linkType: hard - -"@use-gesture/react@npm:^10.2.11": - version: 10.3.1 - resolution: "@use-gesture/react@npm:10.3.1" - dependencies: - "@use-gesture/core": "npm:10.3.1" - peerDependencies: - react: ">= 16.8.0" - checksum: 10c0/978da66e4e7c424866ad52eba8fdf0ce93a4c8fc44f8837c7043e68c6a6107cd67e817fffb27f7db2ae871ef2f6addb0c8ddf1586f24c67b7e6aef1646c668cf - languageName: node - linkType: hard - -"@vector-im/compound-design-tokens@npm:^10.0.0": - version: 10.1.0 - resolution: "@vector-im/compound-design-tokens@npm:10.1.0" - peerDependencies: - "@types/react": "*" - react: ^17 || ^18 || ^19.0.0 - peerDependenciesMeta: - "@types/react": - optional: true - react: - optional: true - checksum: 10c0/ffd8223195eac66bcddd85eb5d6cf64ba5ffa521d3673c1caa5346d0346cfe165819d4744b7c1ad6289f8074684a4c4e8f972a54d34ffa91625f1e377e732ad5 - languageName: node - linkType: hard - -"@vector-im/compound-web@npm:^9.0.0": - version: 9.0.1 - resolution: "@vector-im/compound-web@npm:9.0.1" - dependencies: - "@floating-ui/react": "npm:^0.27.0" - "@radix-ui/react-context-menu": "npm:^2.2.16" - "@radix-ui/react-dropdown-menu": "npm:^2.1.1" - "@radix-ui/react-form": "npm:^0.1.0" - "@radix-ui/react-progress": "npm:^1.1.0" - "@radix-ui/react-separator": "npm:^1.1.0" - "@radix-ui/react-slot": "npm:^1.1.0" - classnames: "npm:^2.5.1" - vaul: "npm:^1.0.0" - peerDependencies: - "@fontsource/inconsolata": ^5 - "@fontsource/inter": ^5 - "@types/react": "*" - "@vector-im/compound-design-tokens": ">=1.6.1 <11.0.0" - react: ^18 || ^19.0.0 - peerDependenciesMeta: - "@types/react": - optional: true - checksum: 10c0/4ae90e1518001a8a4a2a76e86cfc4fc2bba9b2e556c6e4b56df2c7b04e0e2cdb213b70ee7c7ba4288250c726e8182a473d3d5fdf95890451675239c957251eee - languageName: node - linkType: hard - -"@vitejs/plugin-react@npm:^4.0.1": - version: 4.7.0 - resolution: "@vitejs/plugin-react@npm:4.7.0" - dependencies: - "@babel/core": "npm:^7.28.0" - "@babel/plugin-transform-react-jsx-self": "npm:^7.27.1" - "@babel/plugin-transform-react-jsx-source": "npm:^7.27.1" - "@rolldown/pluginutils": "npm:1.0.0-beta.27" - "@types/babel__core": "npm:^7.20.5" - react-refresh: "npm:^0.17.0" - peerDependencies: - vite: ^4.2.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 - checksum: 10c0/692f23960972879485d647713663ec299c478222c96567d60285acf7c7dc5c178e71abfe9d2eefddef1eeb01514dacbc2ed68aad84628debf9c7116134734253 - languageName: node - linkType: hard - -"@vitest/coverage-v8@npm:^4.0.18": - version: 4.1.2 - resolution: "@vitest/coverage-v8@npm:4.1.2" - dependencies: - "@bcoe/v8-coverage": "npm:^1.0.2" - "@vitest/utils": "npm:4.1.2" - ast-v8-to-istanbul: "npm:^1.0.0" - istanbul-lib-coverage: "npm:^3.2.2" - istanbul-lib-report: "npm:^3.0.1" - istanbul-reports: "npm:^3.2.0" - magicast: "npm:^0.5.2" - obug: "npm:^2.1.1" - std-env: "npm:^4.0.0-rc.1" - tinyrainbow: "npm:^3.1.0" - peerDependencies: - "@vitest/browser": 4.1.2 - vitest: 4.1.2 - peerDependenciesMeta: - "@vitest/browser": - optional: true - checksum: 10c0/2f4488efb34a5d9e3a70631ba263e153eecba8ec0da52cb874cdc674c88369061706572b9fc0c302376fd1de58aedc86a2f9f75e5a521084e31a1446c85f2c40 - languageName: node - linkType: hard - -"@vitest/expect@npm:3.2.4": - version: 3.2.4 - resolution: "@vitest/expect@npm:3.2.4" - dependencies: - "@types/chai": "npm:^5.2.2" - "@vitest/spy": "npm:3.2.4" - "@vitest/utils": "npm:3.2.4" - chai: "npm:^5.2.0" - tinyrainbow: "npm:^2.0.0" - checksum: 10c0/7586104e3fd31dbe1e6ecaafb9a70131e4197dce2940f727b6a84131eee3decac7b10f9c7c72fa5edbdb68b6f854353bd4c0fa84779e274207fb7379563b10db - languageName: node - linkType: hard - -"@vitest/expect@npm:4.1.2": - version: 4.1.2 - resolution: "@vitest/expect@npm:4.1.2" - dependencies: - "@standard-schema/spec": "npm:^1.1.0" - "@types/chai": "npm:^5.2.2" - "@vitest/spy": "npm:4.1.2" - "@vitest/utils": "npm:4.1.2" - chai: "npm:^6.2.2" - tinyrainbow: "npm:^3.1.0" - checksum: 10c0/e238c833b5555d31b074545807956d5e874a1ef725525ecc99f1885b71b230b2127d40d8d142a7253666b8565d5806723853e85e0e99265520ec7506fdc5890c - languageName: node - linkType: hard - -"@vitest/mocker@npm:4.1.2": - version: 4.1.2 - resolution: "@vitest/mocker@npm:4.1.2" - dependencies: - "@vitest/spy": "npm:4.1.2" - estree-walker: "npm:^3.0.3" - magic-string: "npm:^0.30.21" - peerDependencies: - msw: ^2.4.9 - vite: ^6.0.0 || ^7.0.0 || ^8.0.0 - peerDependenciesMeta: - msw: - optional: true - vite: - optional: true - checksum: 10c0/f23094f3c7e1e5af42e6a468f0815c1ecdcab85cb3a56ab6f3f214a9808a40271467d4352cae972482b9738cc31c62c7312d8b0da227d6ea03d2b3aacb8d385f - languageName: node - linkType: hard - -"@vitest/pretty-format@npm:3.2.4": - version: 3.2.4 - resolution: "@vitest/pretty-format@npm:3.2.4" - dependencies: - tinyrainbow: "npm:^2.0.0" - checksum: 10c0/5ad7d4278e067390d7d633e307fee8103958806a419ca380aec0e33fae71b44a64415f7a9b4bc11635d3c13d4a9186111c581d3cef9c65cc317e68f077456887 - languageName: node - linkType: hard - -"@vitest/pretty-format@npm:4.1.2": - version: 4.1.2 - resolution: "@vitest/pretty-format@npm:4.1.2" - dependencies: - tinyrainbow: "npm:^3.1.0" - checksum: 10c0/6f57519c707e6a3d1ff8630ca87ce78fda9bf7bb33f6e4a0c775a8b510f2a6cee109849e2cdb736b0280681c567bd03e4cff724cbf0962950c9ff81377f0b2bc - languageName: node - linkType: hard - -"@vitest/pretty-format@npm:^3.0.3": - version: 3.0.3 - resolution: "@vitest/pretty-format@npm:3.0.3" - dependencies: - tinyrainbow: "npm:^2.0.0" - checksum: 10c0/f69a95bda27dc5428fffc42e99188d08107b862093b066989b601d15e5a37e065f1c978d3fd6cb4713b2537104ecb3d29916598c92a86ee76f6dda684c8612df - languageName: node - linkType: hard - -"@vitest/runner@npm:4.1.2": - version: 4.1.2 - resolution: "@vitest/runner@npm:4.1.2" - dependencies: - "@vitest/utils": "npm:4.1.2" - pathe: "npm:^2.0.3" - checksum: 10c0/35654a87bd27983443adc24d68529d624f7d70e0386176741dc5bcc4188b86a70af2c512405d7e97aa45c16d83e1c8566c1f99c8440430f95557275f18612d21 - languageName: node - linkType: hard - -"@vitest/snapshot@npm:4.1.2": - version: 4.1.2 - resolution: "@vitest/snapshot@npm:4.1.2" - dependencies: - "@vitest/pretty-format": "npm:4.1.2" - "@vitest/utils": "npm:4.1.2" - magic-string: "npm:^0.30.21" - pathe: "npm:^2.0.3" - checksum: 10c0/6d20e92386937afddbc81344211e554b83a559e20fb10c1deb0b1c3532994dc9fc62d816706ac835bdb737eb1ab02e9c0bc9de80dd8316060e1e0aaa447ba48f - languageName: node - linkType: hard - -"@vitest/spy@npm:3.2.4": - version: 3.2.4 - resolution: "@vitest/spy@npm:3.2.4" - dependencies: - tinyspy: "npm:^4.0.3" - checksum: 10c0/6ebf0b4697dc238476d6b6a60c76ba9eb1dd8167a307e30f08f64149612fd50227682b876420e4c2e09a76334e73f72e3ebf0e350714dc22474258292e202024 - languageName: node - linkType: hard - -"@vitest/spy@npm:4.1.2": - version: 4.1.2 - resolution: "@vitest/spy@npm:4.1.2" - checksum: 10c0/2b5888d536d3e2083c5f8939763e6d780c2c03cc60e1ab45f9d04eacf14467acb9724cae1c4778e4c06426d49d04517e190122882953054a4b13fda44780bb14 - languageName: node - linkType: hard - -"@vitest/utils@npm:3.2.4": - version: 3.2.4 - resolution: "@vitest/utils@npm:3.2.4" - dependencies: - "@vitest/pretty-format": "npm:3.2.4" - loupe: "npm:^3.1.4" - tinyrainbow: "npm:^2.0.0" - checksum: 10c0/024a9b8c8bcc12cf40183c246c244b52ecff861c6deb3477cbf487ac8781ad44c68a9c5fd69f8c1361878e55b97c10d99d511f2597f1f7244b5e5101d028ba64 - languageName: node - linkType: hard - -"@vitest/utils@npm:4.1.2": - version: 4.1.2 - resolution: "@vitest/utils@npm:4.1.2" - dependencies: - "@vitest/pretty-format": "npm:4.1.2" - convert-source-map: "npm:^2.0.0" - tinyrainbow: "npm:^3.1.0" - checksum: 10c0/d96475e0703b6e5208c6c0f570c1235278cbac3f3913a9aa4203a3e617c9eaca85a184bfd5d13cf366b84754df787ab8bc85242c5e0c63105ee7176c186a2136 - languageName: node - linkType: hard - -"abbrev@npm:^3.0.0": - version: 3.0.0 - resolution: "abbrev@npm:3.0.0" - checksum: 10c0/049704186396f571650eb7b22ed3627b77a5aedf98bb83caf2eac81ca2a3e25e795394b0464cfb2d6076df3db6a5312139eac5b6a126ca296ac53c5008069c28 - languageName: node - linkType: hard - -"acorn-jsx@npm:^5.3.2": - version: 5.3.2 - resolution: "acorn-jsx@npm:5.3.2" - peerDependencies: - acorn: ^6.0.0 || ^7.0.0 || ^8.0.0 - checksum: 10c0/4c54868fbef3b8d58927d5e33f0a4de35f59012fe7b12cf9dfbb345fb8f46607709e1c4431be869a23fb63c151033d84c4198fa9f79385cec34fcb1dd53974c1 - languageName: node - linkType: hard - -"acorn@npm:^8.14.0, acorn@npm:^8.8.1, acorn@npm:^8.8.2": - version: 8.14.0 - resolution: "acorn@npm:8.14.0" - bin: - acorn: bin/acorn - checksum: 10c0/6d4ee461a7734b2f48836ee0fbb752903606e576cc100eb49340295129ca0b452f3ba91ddd4424a1d4406a98adfb2ebb6bd0ff4c49d7a0930c10e462719bbfd7 - languageName: node - linkType: hard - -"acorn@npm:^8.15.0, acorn@npm:^8.16.0, acorn@npm:^8.9.0": - version: 8.16.0 - resolution: "acorn@npm:8.16.0" - bin: - acorn: bin/acorn - checksum: 10c0/c9c52697227661b68d0debaf972222d4f622aa06b185824164e153438afa7b08273432ca43ea792cadb24dada1d46f6f6bb1ef8de9956979288cc1b96bf9914e - languageName: node - linkType: hard - -"agent-base@npm:6": - version: 6.0.2 - resolution: "agent-base@npm:6.0.2" - dependencies: - debug: "npm:4" - checksum: 10c0/dc4f757e40b5f3e3d674bc9beb4f1048f4ee83af189bae39be99f57bf1f48dde166a8b0a5342a84b5944ee8e6ed1e5a9d801858f4ad44764e84957122fe46261 - languageName: node - linkType: hard - -"agent-base@npm:^7.1.0": - version: 7.1.1 - resolution: "agent-base@npm:7.1.1" - dependencies: - debug: "npm:^4.3.4" - checksum: 10c0/e59ce7bed9c63bf071a30cc471f2933862044c97fd9958967bfe22521d7a0f601ce4ed5a8c011799d0c726ca70312142ae193bbebb60f576b52be19d4a363b50 - languageName: node - linkType: hard - -"agent-base@npm:^7.1.2": - version: 7.1.3 - resolution: "agent-base@npm:7.1.3" - checksum: 10c0/6192b580c5b1d8fb399b9c62bf8343d76654c2dd62afcb9a52b2cf44a8b6ace1e3b704d3fe3547d91555c857d3df02603341ff2cb961b9cfe2b12f9f3c38ee11 - languageName: node - linkType: hard - -"ajv@npm:^6.12.4": - version: 6.14.0 - resolution: "ajv@npm:6.14.0" - dependencies: - fast-deep-equal: "npm:^3.1.1" - fast-json-stable-stringify: "npm:^2.0.0" - json-schema-traverse: "npm:^0.4.1" - uri-js: "npm:^4.2.2" - checksum: 10c0/a2bc39b0555dc9802c899f86990eb8eed6e366cddbf65be43d5aa7e4f3c4e1a199d5460fd7ca4fb3d864000dbbc049253b72faa83b3b30e641ca52cb29a68c22 - languageName: node - linkType: hard - -"another-json@npm:^0.2.0": - version: 0.2.0 - resolution: "another-json@npm:0.2.0" - checksum: 10c0/c13a8fcb3b692c998fa81f88053971c9019766d6ab95f0fb2e03462de56ceffa63b08d85944662f9d490c51cfd1abb4eb71abb72a003f4c4b9ae4b58339aa397 - languageName: node - linkType: hard - -"ansi-regex@npm:^5.0.1": - version: 5.0.1 - resolution: "ansi-regex@npm:5.0.1" - checksum: 10c0/9a64bb8627b434ba9327b60c027742e5d17ac69277960d041898596271d992d4d52ba7267a63ca10232e29f6107fc8a835f6ce8d719b88c5f8493f8254813737 - languageName: node - linkType: hard - -"ansi-regex@npm:^6.0.1": - version: 6.1.0 - resolution: "ansi-regex@npm:6.1.0" - checksum: 10c0/a91daeddd54746338478eef88af3439a7edf30f8e23196e2d6ed182da9add559c601266dbef01c2efa46a958ad6f1f8b176799657616c702b5b02e799e7fd8dc - languageName: node - linkType: hard - -"ansi-styles@npm:^3.2.1": - version: 3.2.1 - resolution: "ansi-styles@npm:3.2.1" - dependencies: - color-convert: "npm:^1.9.0" - checksum: 10c0/ece5a8ef069fcc5298f67e3f4771a663129abd174ea2dfa87923a2be2abf6cd367ef72ac87942da00ce85bd1d651d4cd8595aebdb1b385889b89b205860e977b - languageName: node - linkType: hard - -"ansi-styles@npm:^4.0.0, ansi-styles@npm:^4.1.0": - version: 4.3.0 - resolution: "ansi-styles@npm:4.3.0" - dependencies: - color-convert: "npm:^2.0.1" - checksum: 10c0/895a23929da416f2bd3de7e9cb4eabd340949328ab85ddd6e484a637d8f6820d485f53933446f5291c3b760cbc488beb8e88573dd0f9c7daf83dccc8fe81b041 - languageName: node - linkType: hard - -"ansi-styles@npm:^5.0.0": - version: 5.2.0 - resolution: "ansi-styles@npm:5.2.0" - checksum: 10c0/9c4ca80eb3c2fb7b33841c210d2f20807f40865d27008d7c3f707b7f95cab7d67462a565e2388ac3285b71cb3d9bb2173de8da37c57692a362885ec34d6e27df - languageName: node - linkType: hard - -"ansi-styles@npm:^6.1.0": - version: 6.2.1 - resolution: "ansi-styles@npm:6.2.1" - checksum: 10c0/5d1ec38c123984bcedd996eac680d548f31828bd679a66db2bdf11844634dde55fec3efa9c6bb1d89056a5e79c1ac540c4c784d592ea1d25028a92227d2f2d5c - languageName: node - linkType: hard - -"anymatch@npm:^3.1.3, anymatch@npm:~3.1.2": - version: 3.1.3 - resolution: "anymatch@npm:3.1.3" - dependencies: - normalize-path: "npm:^3.0.0" - picomatch: "npm:^2.0.4" - checksum: 10c0/57b06ae984bc32a0d22592c87384cd88fe4511b1dd7581497831c56d41939c8a001b28e7b853e1450f2bf61992dfcaa8ae2d0d161a0a90c4fb631ef07098fbac - languageName: node - linkType: hard - -"are-docs-informative@npm:^0.0.2": - version: 0.0.2 - resolution: "are-docs-informative@npm:0.0.2" - checksum: 10c0/f0326981bd699c372d268b526b170a28f2e1aec2cf99d7de0686083528427ecdf6ae41fef5d9988e224a5616298af747ad8a76e7306b0a7c97cc085a99636d60 - languageName: node - linkType: hard - -"argparse@npm:^2.0.1": - version: 2.0.1 - resolution: "argparse@npm:2.0.1" - checksum: 10c0/c5640c2d89045371c7cedd6a70212a04e360fd34d6edeae32f6952c63949e3525ea77dbec0289d8213a99bbaeab5abfa860b5c12cf88a2e6cf8106e90dd27a7e - languageName: node - linkType: hard - -"aria-hidden@npm:^1.1.1, aria-hidden@npm:^1.2.4": - version: 1.2.4 - resolution: "aria-hidden@npm:1.2.4" - dependencies: - tslib: "npm:^2.0.0" - checksum: 10c0/8abcab2e1432efc4db415e97cb3959649ddf52c8fc815d7384f43f3d3abf56f1c12852575d00df9a8927f421d7e0712652dd5f8db244ea57634344e29ecfc74a - languageName: node - linkType: hard - -"aria-query@npm:5.3.0": - version: 5.3.0 - resolution: "aria-query@npm:5.3.0" - dependencies: - dequal: "npm:^2.0.3" - checksum: 10c0/2bff0d4eba5852a9dd578ecf47eaef0e82cc52569b48469b0aac2db5145db0b17b7a58d9e01237706d1e14b7a1b0ac9b78e9c97027ad97679dd8f91b85da1469 - languageName: node - linkType: hard - -"aria-query@npm:^5.0.0, aria-query@npm:^5.3.2": - version: 5.3.2 - resolution: "aria-query@npm:5.3.2" - checksum: 10c0/003c7e3e2cff5540bf7a7893775fc614de82b0c5dde8ae823d47b7a28a9d4da1f7ed85f340bdb93d5649caa927755f0e31ecc7ab63edfdfc00c8ef07e505e03e - languageName: node - linkType: hard - -"array-buffer-byte-length@npm:^1.0.1, array-buffer-byte-length@npm:^1.0.2": - version: 1.0.2 - resolution: "array-buffer-byte-length@npm:1.0.2" - dependencies: - call-bound: "npm:^1.0.3" - is-array-buffer: "npm:^3.0.5" - checksum: 10c0/74e1d2d996941c7a1badda9cabb7caab8c449db9086407cad8a1b71d2604cc8abf105db8ca4e02c04579ec58b7be40279ddb09aea4784832984485499f48432d - languageName: node - linkType: hard - -"array-includes@npm:^3.1.6, array-includes@npm:^3.1.8": - version: 3.1.8 - resolution: "array-includes@npm:3.1.8" - dependencies: - call-bind: "npm:^1.0.7" - define-properties: "npm:^1.2.1" - es-abstract: "npm:^1.23.2" - es-object-atoms: "npm:^1.0.0" - get-intrinsic: "npm:^1.2.4" - is-string: "npm:^1.0.7" - checksum: 10c0/5b1004d203e85873b96ddc493f090c9672fd6c80d7a60b798da8a14bff8a670ff95db5aafc9abc14a211943f05220dacf8ea17638ae0af1a6a47b8c0b48ce370 - languageName: node - linkType: hard - -"array-includes@npm:^3.1.9": - version: 3.1.9 - resolution: "array-includes@npm:3.1.9" - dependencies: - call-bind: "npm:^1.0.8" - call-bound: "npm:^1.0.4" - define-properties: "npm:^1.2.1" - es-abstract: "npm:^1.24.0" - es-object-atoms: "npm:^1.1.1" - get-intrinsic: "npm:^1.3.0" - is-string: "npm:^1.1.1" - math-intrinsics: "npm:^1.1.0" - checksum: 10c0/0235fa69078abeac05ac4250699c44996bc6f774a9cbe45db48674ce6bd142f09b327d31482ff75cf03344db4ea03eae23edb862d59378b484b47ed842574856 - languageName: node - linkType: hard - -"array-union@npm:^2.1.0": - version: 2.1.0 - resolution: "array-union@npm:2.1.0" - checksum: 10c0/429897e68110374f39b771ec47a7161fc6a8fc33e196857c0a396dc75df0b5f65e4d046674db764330b6bb66b39ef48dd7c53b6a2ee75cfb0681e0c1a7033962 - languageName: node - linkType: hard - -"array.prototype.findlast@npm:^1.2.5": - version: 1.2.5 - resolution: "array.prototype.findlast@npm:1.2.5" - dependencies: - call-bind: "npm:^1.0.7" - define-properties: "npm:^1.2.1" - es-abstract: "npm:^1.23.2" - es-errors: "npm:^1.3.0" - es-object-atoms: "npm:^1.0.0" - es-shim-unscopables: "npm:^1.0.2" - checksum: 10c0/ddc952b829145ab45411b9d6adcb51a8c17c76bf89c9dd64b52d5dffa65d033da8c076ed2e17091779e83bc892b9848188d7b4b33453c5565e65a92863cb2775 - languageName: node - linkType: hard - -"array.prototype.findlastindex@npm:^1.2.6": - version: 1.2.6 - resolution: "array.prototype.findlastindex@npm:1.2.6" - dependencies: - call-bind: "npm:^1.0.8" - call-bound: "npm:^1.0.4" - define-properties: "npm:^1.2.1" - es-abstract: "npm:^1.23.9" - es-errors: "npm:^1.3.0" - es-object-atoms: "npm:^1.1.1" - es-shim-unscopables: "npm:^1.1.0" - checksum: 10c0/82559310d2e57ec5f8fc53d7df420e3abf0ba497935de0a5570586035478ba7d07618cb18e2d4ada2da514c8fb98a034aaf5c06caa0a57e2f7f4c4adedef5956 - languageName: node - linkType: hard - -"array.prototype.flat@npm:^1.3.1, array.prototype.flat@npm:^1.3.3": - version: 1.3.3 - resolution: "array.prototype.flat@npm:1.3.3" - dependencies: - call-bind: "npm:^1.0.8" - define-properties: "npm:^1.2.1" - es-abstract: "npm:^1.23.5" - es-shim-unscopables: "npm:^1.0.2" - checksum: 10c0/d90e04dfbc43bb96b3d2248576753d1fb2298d2d972e29ca7ad5ec621f0d9e16ff8074dae647eac4f31f4fb7d3f561a7ac005fb01a71f51705a13b5af06a7d8a - languageName: node - linkType: hard - -"array.prototype.flatmap@npm:^1.3.2": - version: 1.3.2 - resolution: "array.prototype.flatmap@npm:1.3.2" - dependencies: - call-bind: "npm:^1.0.2" - define-properties: "npm:^1.2.0" - es-abstract: "npm:^1.22.1" - es-shim-unscopables: "npm:^1.0.0" - checksum: 10c0/67b3f1d602bb73713265145853128b1ad77cc0f9b833c7e1e056b323fbeac41a4ff1c9c99c7b9445903caea924d9ca2450578d9011913191aa88cc3c3a4b54f4 - languageName: node - linkType: hard - -"array.prototype.flatmap@npm:^1.3.3": - version: 1.3.3 - resolution: "array.prototype.flatmap@npm:1.3.3" - dependencies: - call-bind: "npm:^1.0.8" - define-properties: "npm:^1.2.1" - es-abstract: "npm:^1.23.5" - es-shim-unscopables: "npm:^1.0.2" - checksum: 10c0/ba899ea22b9dc9bf276e773e98ac84638ed5e0236de06f13d63a90b18ca9e0ec7c97d622d899796e3773930b946cd2413d098656c0c5d8cc58c6f25c21e6bd54 - languageName: node - linkType: hard - -"array.prototype.tosorted@npm:^1.1.4": - version: 1.1.4 - resolution: "array.prototype.tosorted@npm:1.1.4" - dependencies: - call-bind: "npm:^1.0.7" - define-properties: "npm:^1.2.1" - es-abstract: "npm:^1.23.3" - es-errors: "npm:^1.3.0" - es-shim-unscopables: "npm:^1.0.2" - checksum: 10c0/eb3c4c4fc0381b0bf6dba2ea4d48d367c2827a0d4236a5718d97caaccc6b78f11f4cadf090736e86301d295a6aa4967ed45568f92ced51be8cbbacd9ca410943 - languageName: node - linkType: hard - -"arraybuffer.prototype.slice@npm:^1.0.4": - version: 1.0.4 - resolution: "arraybuffer.prototype.slice@npm:1.0.4" - dependencies: - array-buffer-byte-length: "npm:^1.0.1" - call-bind: "npm:^1.0.8" - define-properties: "npm:^1.2.1" - es-abstract: "npm:^1.23.5" - es-errors: "npm:^1.3.0" - get-intrinsic: "npm:^1.2.6" - is-array-buffer: "npm:^3.0.4" - checksum: 10c0/2f2459caa06ae0f7f615003f9104b01f6435cc803e11bd2a655107d52a1781dc040532dc44d93026b694cc18793993246237423e13a5337e86b43ed604932c06 - languageName: node - linkType: hard - -"asn1.js@npm:^4.10.1": - version: 4.10.1 - resolution: "asn1.js@npm:4.10.1" - dependencies: - bn.js: "npm:^4.0.0" - inherits: "npm:^2.0.1" - minimalistic-assert: "npm:^1.0.0" - checksum: 10c0/afa7f3ab9e31566c80175a75b182e5dba50589dcc738aa485be42bdd787e2a07246a4b034d481861123cbe646a7656f318f4f1cad2e9e5e808a210d5d6feaa88 - languageName: node - linkType: hard - -"assert@npm:^2.0.0": - version: 2.1.0 - resolution: "assert@npm:2.1.0" - dependencies: - call-bind: "npm:^1.0.2" - is-nan: "npm:^1.3.2" - object-is: "npm:^1.1.5" - object.assign: "npm:^4.1.4" - util: "npm:^0.12.5" - checksum: 10c0/7271a5da883c256a1fa690677bf1dd9d6aa882139f2bed1cd15da4f9e7459683e1da8e32a203d6cc6767e5e0f730c77a9532a87b896b4b0af0dd535f668775f0 - languageName: node - linkType: hard - -"assertion-error@npm:^2.0.1": - version: 2.0.1 - resolution: "assertion-error@npm:2.0.1" - checksum: 10c0/bbbcb117ac6480138f8c93cf7f535614282dea9dc828f540cdece85e3c665e8f78958b96afac52f29ff883c72638e6a87d469ecc9fe5bc902df03ed24a55dba8 - languageName: node - linkType: hard - -"ast-types-flow@npm:^0.0.8": - version: 0.0.8 - resolution: "ast-types-flow@npm:0.0.8" - checksum: 10c0/f2a0ba8055353b743c41431974521e5e852a9824870cd6fce2db0e538ac7bf4da406bbd018d109af29ff3f8f0993f6a730c9eddbd0abd031fbcb29ca75c1014e - languageName: node - linkType: hard - -"ast-types@npm:^0.16.1": - version: 0.16.1 - resolution: "ast-types@npm:0.16.1" - dependencies: - tslib: "npm:^2.0.1" - checksum: 10c0/abcc49e42eb921a7ebc013d5bec1154651fb6dbc3f497541d488859e681256901b2990b954d530ba0da4d0851271d484f7057d5eff5e07cb73e8b10909f711bf - languageName: node - linkType: hard - -"ast-v8-to-istanbul@npm:^1.0.0": - version: 1.0.0 - resolution: "ast-v8-to-istanbul@npm:1.0.0" - dependencies: - "@jridgewell/trace-mapping": "npm:^0.3.31" - estree-walker: "npm:^3.0.3" - js-tokens: "npm:^10.0.0" - checksum: 10c0/35e57b754ba63287358094d4f7ae8de2de27286fb4e76a1fbf28b2e67e3b670b59c3f511882473d0fd2cdbaa260062e3cd4f216b724c70032e2b09e5cebbd618 - languageName: node - linkType: hard - -"async@npm:^3.2.3": - version: 3.2.6 - resolution: "async@npm:3.2.6" - checksum: 10c0/36484bb15ceddf07078688d95e27076379cc2f87b10c03b6dd8a83e89475a3c8df5848859dd06a4c95af1e4c16fc973de0171a77f18ea00be899aca2a4f85e70 - languageName: node - linkType: hard - -"autoprefixer@npm:^10.4.23": - version: 10.4.23 - resolution: "autoprefixer@npm:10.4.23" - dependencies: - browserslist: "npm:^4.28.1" - caniuse-lite: "npm:^1.0.30001760" - fraction.js: "npm:^5.3.4" - picocolors: "npm:^1.1.1" - postcss-value-parser: "npm:^4.2.0" - peerDependencies: - postcss: ^8.1.0 - bin: - autoprefixer: bin/autoprefixer - checksum: 10c0/3765c5d0fa3e95fb2ebe9d5a6d4da0156f5d346c7ec9ac0fbf5c97c8139d0ca1e8743bf5dc1b4aa954467be6929fddf8498a3b6202d468d70b5f359f3b6af90f - languageName: node - linkType: hard - -"available-typed-arrays@npm:^1.0.7": - version: 1.0.7 - resolution: "available-typed-arrays@npm:1.0.7" - dependencies: - possible-typed-array-names: "npm:^1.0.0" - checksum: 10c0/d07226ef4f87daa01bd0fe80f8f310982e345f372926da2e5296aecc25c41cab440916bbaa4c5e1034b453af3392f67df5961124e4b586df1e99793a1374bdb2 - languageName: node - linkType: hard - -"axe-core@npm:^4.10.0, axe-core@npm:^4.10.2": - version: 4.10.2 - resolution: "axe-core@npm:4.10.2" - checksum: 10c0/0e20169077de96946a547fce0df39d9aeebe0077f9d3eeff4896518b96fde857f80b98f0d4279274a7178791744dd5a54bb4f322de45b4f561ffa2586ff9a09d - languageName: node - linkType: hard - -"axobject-query@npm:^4.1.0": - version: 4.1.0 - resolution: "axobject-query@npm:4.1.0" - checksum: 10c0/c470e4f95008f232eadd755b018cb55f16c03ccf39c027b941cd8820ac6b68707ce5d7368a46756db4256fbc91bb4ead368f84f7fb034b2b7932f082f6dc0775 - languageName: node - linkType: hard - -"b4a@npm:^1.6.4": - version: 1.6.7 - resolution: "b4a@npm:1.6.7" - checksum: 10c0/ec2f004d1daae04be8c5a1f8aeb7fea213c34025e279db4958eb0b82c1729ee25f7c6e89f92a5f65c8a9cf2d017ce27e3dda912403341d1781bd74528a4849d4 - languageName: node - linkType: hard - -"babel-plugin-polyfill-corejs2@npm:^0.4.15": - version: 0.4.15 - resolution: "babel-plugin-polyfill-corejs2@npm:0.4.15" - dependencies: - "@babel/compat-data": "npm:^7.28.6" - "@babel/helper-define-polyfill-provider": "npm:^0.6.6" - semver: "npm:^6.3.1" - peerDependencies: - "@babel/core": ^7.4.0 || ^8.0.0-0 <8.0.0 - checksum: 10c0/5e3ff853a5056bdc0816320523057b45d52c9ea01c847fd07886a4202b0c1324dc97eda4b777c98387927ff02d913fedbe9ba9943c0d4030714048e0b9e61682 - languageName: node - linkType: hard - -"babel-plugin-polyfill-corejs3@npm:^0.14.0": - version: 0.14.0 - resolution: "babel-plugin-polyfill-corejs3@npm:0.14.0" - dependencies: - "@babel/helper-define-polyfill-provider": "npm:^0.6.6" - core-js-compat: "npm:^3.48.0" - peerDependencies: - "@babel/core": ^7.4.0 || ^8.0.0-0 <8.0.0 - checksum: 10c0/db7f530752a2bcb891c0dc80c3d025a48d49c78d41b0ad91cc853669460cd9e3107857a3667f645f0e25c2af9fc3d1e38d5b1c4e3e60aa22e7df9d68550712a4 - languageName: node - linkType: hard - -"babel-plugin-polyfill-regenerator@npm:^0.6.6": - version: 0.6.6 - resolution: "babel-plugin-polyfill-regenerator@npm:0.6.6" - dependencies: - "@babel/helper-define-polyfill-provider": "npm:^0.6.6" - peerDependencies: - "@babel/core": ^7.4.0 || ^8.0.0-0 <8.0.0 - checksum: 10c0/0ef91d8361c118e7b16d8592c053707325b8168638ea4636b76530c8bc6a1b5aac5c6ca5140e8f3fcdb634a7a2e636133e6b9ef70a75e6417a258a7fddc04bd7 - languageName: node - linkType: hard - -"babel-plugin-transform-vite-meta-env@npm:^1.0.3": - version: 1.0.3 - resolution: "babel-plugin-transform-vite-meta-env@npm:1.0.3" - dependencies: - "@babel/runtime": "npm:^7.13.9" - "@types/babel__core": "npm:^7.1.12" - checksum: 10c0/fd602e8e9b64b06c93106b295a75f41a89a527d825ac3984baafab428108d3b1a12b6280e0bf19a58bda25e65e839a67f71bf1d916424fc81201dc14de241b64 - languageName: node - linkType: hard - -"balanced-match@npm:^4.0.2": - version: 4.0.4 - resolution: "balanced-match@npm:4.0.4" - checksum: 10c0/07e86102a3eb2ee2a6a1a89164f29d0dbaebd28f2ca3f5ca786f36b8b23d9e417eb3be45a4acf754f837be5ac0a2317de90d3fcb7f4f4dc95720a1f36b26a17b - languageName: node - linkType: hard - -"bare-events@npm:^2.2.0": - version: 2.5.4 - resolution: "bare-events@npm:2.5.4" - checksum: 10c0/877a9cea73d545e2588cdbd6fd01653e27dac48ad6b44985cdbae73e1f57f292d4ba52e25d1fba53674c1053c463d159f3d5c7bc36a2e6e192e389b499ddd627 - languageName: node - linkType: hard - -"base-x@npm:^5.0.0": - version: 5.0.1 - resolution: "base-x@npm:5.0.1" - checksum: 10c0/4ab6b02262b4fd499b147656f63ce7328bd5f895450401ce58a2f9e87828aea507cf0c320a6d8725389f86e8a48397562661c0bca28ef3276a22821b30f7a713 - languageName: node - linkType: hard - -"base64-js@npm:^1.3.1": - version: 1.5.1 - resolution: "base64-js@npm:1.5.1" - checksum: 10c0/f23823513b63173a001030fae4f2dabe283b99a9d324ade3ad3d148e218134676f1ee8568c877cd79ec1c53158dcf2d2ba527a97c606618928ba99dd930102bf - languageName: node - linkType: hard - -"baseline-browser-mapping@npm:^2.9.0": - version: 2.9.11 - resolution: "baseline-browser-mapping@npm:2.9.11" - bin: - baseline-browser-mapping: dist/cli.js - checksum: 10c0/eba49fcc1b33ab994aeeb73a4848f2670e06a0886dd5b903689ae6f60d47e7f1bea9262dbb2548c48179e858f7eda2b82ddf941ae783b862f4dcc51085a246f2 - languageName: node - linkType: hard - -"before-after-hook@npm:^2.2.0": - version: 2.2.3 - resolution: "before-after-hook@npm:2.2.3" - checksum: 10c0/0488c4ae12df758ca9d49b3bb27b47fd559677965c52cae7b335784724fb8bf96c42b6e5ba7d7afcbc31facb0e294c3ef717cc41c5bc2f7bd9e76f8b90acd31c - languageName: node - linkType: hard - -"bent@npm:~7.3.6": - version: 7.3.12 - resolution: "bent@npm:7.3.12" - dependencies: - bytesish: "npm:^0.4.1" - caseless: "npm:~0.12.0" - is-stream: "npm:^2.0.0" - checksum: 10c0/20f77364bcb462a6eb0ea7322442a1125ca6181ea6b94ad498b8348c678a2adf56c231a653bcac016c5d017aee91ff55b2169b69d8263a4b3c710f4121cbe615 - languageName: node - linkType: hard - -"binary-extensions@npm:^2.0.0": - version: 2.3.0 - resolution: "binary-extensions@npm:2.3.0" - checksum: 10c0/75a59cafc10fb12a11d510e77110c6c7ae3f4ca22463d52487709ca7f18f69d886aa387557cc9864fbdb10153d0bdb4caacabf11541f55e89ed6e18d12ece2b5 - languageName: node - linkType: hard - -"bl@npm:^5.0.0": - version: 5.1.0 - resolution: "bl@npm:5.1.0" - dependencies: - buffer: "npm:^6.0.3" - inherits: "npm:^2.0.4" - readable-stream: "npm:^3.4.0" - checksum: 10c0/528a9c3d7d6b87af98c46f10a887654d027c28c503c7f7de87440e643f0056d7a2319a967762b8ec18150c64799d2825a277147a752a0570a7407c0b705b0d01 - languageName: node - linkType: hard - -"bn.js@npm:^4.0.0, bn.js@npm:^4.1.0, bn.js@npm:^4.11.9": - version: 4.12.2 - resolution: "bn.js@npm:4.12.2" - checksum: 10c0/09a249faa416a9a1ce68b5f5ec8bbca87fe54e5dd4ef8b1cc8a4969147b80035592bddcb1e9cc814c3ba79e573503d5c5178664b722b509fb36d93620dba9b57 - languageName: node - linkType: hard - -"bn.js@npm:^5.2.1, bn.js@npm:^5.2.2": - version: 5.2.2 - resolution: "bn.js@npm:5.2.2" - checksum: 10c0/cb97827d476aab1a0194df33cd84624952480d92da46e6b4a19c32964aa01553a4a613502396712704da2ec8f831cf98d02e74ca03398404bd78a037ba93f2ab - languageName: node - linkType: hard - -"boolbase@npm:^1.0.0": - version: 1.0.0 - resolution: "boolbase@npm:1.0.0" - checksum: 10c0/e4b53deb4f2b85c52be0e21a273f2045c7b6a6ea002b0e139c744cb6f95e9ec044439a52883b0d74dedd1ff3da55ed140cfdddfed7fb0cccbed373de5dce1bcf - languageName: node - linkType: hard - -"brace-expansion@npm:^5.0.2": - version: 5.0.3 - resolution: "brace-expansion@npm:5.0.3" - dependencies: - balanced-match: "npm:^4.0.2" - checksum: 10c0/e474d300e581ec56851b3863ff1cf18573170c6d06deb199ccbd03b2119c36975f6ce2abc7b770f5bebddc1ab022661a9fea9b4d56f33315d7bef54d8793869e - languageName: node - linkType: hard - -"braces@npm:^3.0.3, braces@npm:~3.0.2": - version: 3.0.3 - resolution: "braces@npm:3.0.3" - dependencies: - fill-range: "npm:^7.1.1" - checksum: 10c0/7c6dfd30c338d2997ba77500539227b9d1f85e388a5f43220865201e407e076783d0881f2d297b9f80951b4c957fcf0b51c1d2d24227631643c3f7c284b0aa04 - languageName: node - linkType: hard - -"broccoli-node-api@npm:^1.7.0": - version: 1.7.0 - resolution: "broccoli-node-api@npm:1.7.0" - checksum: 10c0/7ea3e32847c32c9017f7e9def8d80e02070b80dad3608a37d8472c0f535a768b9b1fe71afd2153a7c927fe59a724bc688e591b17666f86a8fc2bc4ec74a50532 - languageName: node - linkType: hard - -"broccoli-node-info@npm:^2.1.0": - version: 2.2.0 - resolution: "broccoli-node-info@npm:2.2.0" - checksum: 10c0/d904e31772e4f7a2af442dd3edc2232753d97ab68be5bd1b4f3b11f39e80b6f21e2b89204717a6d8815b530883a2c9054a6ce2c96a6e16f9aba9b0cb4eb2af7a - languageName: node - linkType: hard - -"broccoli-output-wrapper@npm:^3.2.5": - version: 3.2.5 - resolution: "broccoli-output-wrapper@npm:3.2.5" - dependencies: - fs-extra: "npm:^8.1.0" - heimdalljs-logger: "npm:^0.1.10" - symlink-or-copy: "npm:^1.2.0" - checksum: 10c0/7e17524277cc9d1349967d329c2d7ec4a05eca5164e566948cf36043f5332581c7c76466b43d36b46e404403558f02930e89a7586f27e6312814e5ec4d130154 - languageName: node - linkType: hard - -"broccoli-plugin@npm:^4.0.7": - version: 4.0.7 - resolution: "broccoli-plugin@npm:4.0.7" - dependencies: - broccoli-node-api: "npm:^1.7.0" - broccoli-output-wrapper: "npm:^3.2.5" - fs-merger: "npm:^3.2.1" - promise-map-series: "npm:^0.3.0" - quick-temp: "npm:^0.1.8" - rimraf: "npm:^3.0.2" - symlink-or-copy: "npm:^1.3.1" - checksum: 10c0/5599a53ca43c18f2c763d05d8feda3fe0cb1f24194c6309fa316a53b67001d6215b7f99611011bb92843d2ff792345cec7b9a1947bfd728a4196a8057e3fe051 - languageName: node - linkType: hard - -"brorand@npm:^1.0.1, brorand@npm:^1.1.0": - version: 1.1.0 - resolution: "brorand@npm:1.1.0" - checksum: 10c0/6f366d7c4990f82c366e3878492ba9a372a73163c09871e80d82fb4ae0d23f9f8924cb8a662330308206e6b3b76ba1d528b4601c9ef73c2166b440b2ea3b7571 - languageName: node - linkType: hard - -"browser-resolve@npm:^2.0.0": - version: 2.0.0 - resolution: "browser-resolve@npm:2.0.0" - dependencies: - resolve: "npm:^1.17.0" - checksum: 10c0/06c43adf3cb1939825ab9a4ac355b23272820ee421a20d04f62e0dabd9ea305e497b97f3ac027f87d53c366483aafe8673bbe1aaa5e41cd69eeafa65ac5fda6e - languageName: node - linkType: hard - -"browserify-aes@npm:^1.0.4, browserify-aes@npm:^1.2.0": - version: 1.2.0 - resolution: "browserify-aes@npm:1.2.0" - dependencies: - buffer-xor: "npm:^1.0.3" - cipher-base: "npm:^1.0.0" - create-hash: "npm:^1.1.0" - evp_bytestokey: "npm:^1.0.3" - inherits: "npm:^2.0.1" - safe-buffer: "npm:^5.0.1" - checksum: 10c0/967f2ae60d610b7b252a4cbb55a7a3331c78293c94b4dd9c264d384ca93354c089b3af9c0dd023534efdc74ffbc82510f7ad4399cf82bc37bc07052eea485f18 - languageName: node - linkType: hard - -"browserify-cipher@npm:^1.0.1": - version: 1.0.1 - resolution: "browserify-cipher@npm:1.0.1" - dependencies: - browserify-aes: "npm:^1.0.4" - browserify-des: "npm:^1.0.0" - evp_bytestokey: "npm:^1.0.0" - checksum: 10c0/aa256dcb42bc53a67168bbc94ab85d243b0a3b56109dee3b51230b7d010d9b78985ffc1fb36e145c6e4db151f888076c1cfc207baf1525d3e375cbe8187fe27d - languageName: node - linkType: hard - -"browserify-des@npm:^1.0.0": - version: 1.0.2 - resolution: "browserify-des@npm:1.0.2" - dependencies: - cipher-base: "npm:^1.0.1" - des.js: "npm:^1.0.0" - inherits: "npm:^2.0.1" - safe-buffer: "npm:^5.1.2" - checksum: 10c0/943eb5d4045eff80a6cde5be4e5fbb1f2d5002126b5a4789c3c1aae3cdddb1eb92b00fb92277f512288e5c6af330730b1dbabcf7ce0923e749e151fcee5a074d - languageName: node - linkType: hard - -"browserify-rsa@npm:^4.0.0, browserify-rsa@npm:^4.1.1": - version: 4.1.1 - resolution: "browserify-rsa@npm:4.1.1" - dependencies: - bn.js: "npm:^5.2.1" - randombytes: "npm:^2.1.0" - safe-buffer: "npm:^5.2.1" - checksum: 10c0/b650ee1192e3d7f3d779edc06dd96ed8720362e72ac310c367b9d7fe35f7e8dbb983c1829142b2b3215458be8bf17c38adc7224920843024ed8cf39e19c513c0 - languageName: node - linkType: hard - -"browserify-sign@npm:^4.2.3": - version: 4.2.5 - resolution: "browserify-sign@npm:4.2.5" - dependencies: - bn.js: "npm:^5.2.2" - browserify-rsa: "npm:^4.1.1" - create-hash: "npm:^1.2.0" - create-hmac: "npm:^1.1.7" - elliptic: "npm:^6.6.1" - inherits: "npm:^2.0.4" - parse-asn1: "npm:^5.1.9" - readable-stream: "npm:^2.3.8" - safe-buffer: "npm:^5.2.1" - checksum: 10c0/6192f9696934bbba58932d098face34c2ab9cac09feed826618b86b8c00a897dab7324cd9aa7d6cb1597064f197264ad72fa5418d4d52bf3c8f9b9e0e124655e - languageName: node - linkType: hard - -"browserify-zlib@npm:^0.2.0": - version: 0.2.0 - resolution: "browserify-zlib@npm:0.2.0" - dependencies: - pako: "npm:~1.0.5" - checksum: 10c0/9ab10b6dc732c6c5ec8ebcbe5cb7fe1467f97402c9b2140113f47b5f187b9438f93a8e065d8baf8b929323c18324fbf1105af479ee86d9d36cab7d7ef3424ad9 - languageName: node - linkType: hard - -"browserslist@npm:^4.24.0, browserslist@npm:^4.24.3": - version: 4.24.4 - resolution: "browserslist@npm:4.24.4" - dependencies: - caniuse-lite: "npm:^1.0.30001688" - electron-to-chromium: "npm:^1.5.73" - node-releases: "npm:^2.0.19" - update-browserslist-db: "npm:^1.1.1" - bin: - browserslist: cli.js - checksum: 10c0/db7ebc1733cf471e0b490b4f47e3e2ea2947ce417192c9246644e92c667dd56a71406cc58f62ca7587caf828364892e9952904a02b7aead752bc65b62a37cfe9 - languageName: node - linkType: hard - -"browserslist@npm:^4.28.1": - version: 4.28.1 - resolution: "browserslist@npm:4.28.1" - dependencies: - baseline-browser-mapping: "npm:^2.9.0" - caniuse-lite: "npm:^1.0.30001759" - electron-to-chromium: "npm:^1.5.263" - node-releases: "npm:^2.0.27" - update-browserslist-db: "npm:^1.2.0" - bin: - browserslist: cli.js - checksum: 10c0/545a5fa9d7234e3777a7177ec1e9134bb2ba60a69e6b95683f6982b1473aad347c77c1264ccf2ac5dea609a9731fbfbda6b85782bdca70f80f86e28a402504bd - languageName: node - linkType: hard - -"bs58@npm:^6.0.0": - version: 6.0.0 - resolution: "bs58@npm:6.0.0" - dependencies: - base-x: "npm:^5.0.0" - checksum: 10c0/61910839746625ee4f69369f80e2634e2123726caaa1da6b3bcefcf7efcd9bdca86603360fed9664ffdabe0038c51e542c02581c72ca8d44f60329fe1a6bc8f4 - languageName: node - linkType: hard - -"buffer-from@npm:^1.0.0": - version: 1.1.2 - resolution: "buffer-from@npm:1.1.2" - checksum: 10c0/124fff9d66d691a86d3b062eff4663fe437a9d9ee4b47b1b9e97f5a5d14f6d5399345db80f796827be7c95e70a8e765dd404b7c3ff3b3324f98e9b0c8826cc34 - languageName: node - linkType: hard - -"buffer-xor@npm:^1.0.3": - version: 1.0.3 - resolution: "buffer-xor@npm:1.0.3" - checksum: 10c0/fd269d0e0bf71ecac3146187cfc79edc9dbb054e2ee69b4d97dfb857c6d997c33de391696d04bdd669272751fa48e7872a22f3a6c7b07d6c0bc31dbe02a4075c - languageName: node - linkType: hard - -"buffer@npm:^5.7.1": - version: 5.7.1 - resolution: "buffer@npm:5.7.1" - dependencies: - base64-js: "npm:^1.3.1" - ieee754: "npm:^1.1.13" - checksum: 10c0/27cac81cff434ed2876058d72e7c4789d11ff1120ef32c9de48f59eab58179b66710c488987d295ae89a228f835fc66d088652dffeb8e3ba8659f80eb091d55e - languageName: node - linkType: hard - -"buffer@npm:^6.0.3": - version: 6.0.3 - resolution: "buffer@npm:6.0.3" - dependencies: - base64-js: "npm:^1.3.1" - ieee754: "npm:^1.2.1" - checksum: 10c0/2a905fbbcde73cc5d8bd18d1caa23715d5f83a5935867c2329f0ac06104204ba7947be098fe1317fbd8830e26090ff8e764f08cd14fefc977bb248c3487bcbd0 - languageName: node - linkType: hard - -"builtin-modules@npm:^3.3.0": - version: 3.3.0 - resolution: "builtin-modules@npm:3.3.0" - checksum: 10c0/2cb3448b4f7306dc853632a4fcddc95e8d4e4b9868c139400027b71938fc6806d4ff44007deffb362ac85724bd40c2c6452fb6a0aa4531650eeddb98d8e5ee8a - languageName: node - linkType: hard - -"builtin-status-codes@npm:^3.0.0": - version: 3.0.0 - resolution: "builtin-status-codes@npm:3.0.0" - checksum: 10c0/c37bbba11a34c4431e56bd681b175512e99147defbe2358318d8152b3a01df7bf25e0305873947e5b350073d5ef41a364a22b37e48f1fb6d2fe6d5286a0f348c - languageName: node - linkType: hard - -"bundle-name@npm:^4.1.0": - version: 4.1.0 - resolution: "bundle-name@npm:4.1.0" - dependencies: - run-applescript: "npm:^7.0.0" - checksum: 10c0/8e575981e79c2bcf14d8b1c027a3775c095d362d1382312f444a7c861b0e21513c0bd8db5bd2b16e50ba0709fa622d4eab6b53192d222120305e68359daece29 - languageName: node - linkType: hard - -"bytesish@npm:^0.4.1": - version: 0.4.4 - resolution: "bytesish@npm:0.4.4" - checksum: 10c0/469088f0020797dfbb61b6ce3972c91d95d79df8aacca55841ea93ac59ef3209bb04be8212b6265dfbafb7583a58dd73ca2f14e4feae36d3333a4f1509dd2eef - languageName: node - linkType: hard - -"cacache@npm:^19.0.1": - version: 19.0.1 - resolution: "cacache@npm:19.0.1" - dependencies: - "@npmcli/fs": "npm:^4.0.0" - fs-minipass: "npm:^3.0.0" - glob: "npm:^10.2.2" - lru-cache: "npm:^10.0.1" - minipass: "npm:^7.0.3" - minipass-collect: "npm:^2.0.1" - minipass-flush: "npm:^1.0.5" - minipass-pipeline: "npm:^1.2.4" - p-map: "npm:^7.0.2" - ssri: "npm:^12.0.0" - tar: "npm:^7.4.3" - unique-filename: "npm:^4.0.0" - checksum: 10c0/01f2134e1bd7d3ab68be851df96c8d63b492b1853b67f2eecb2c37bb682d37cb70bb858a16f2f0554d3c0071be6dfe21456a1ff6fa4b7eed996570d6a25ffe9c - languageName: node - linkType: hard - -"call-bind-apply-helpers@npm:^1.0.0, call-bind-apply-helpers@npm:^1.0.1": - version: 1.0.1 - resolution: "call-bind-apply-helpers@npm:1.0.1" - dependencies: - es-errors: "npm:^1.3.0" - function-bind: "npm:^1.1.2" - checksum: 10c0/acb2ab68bf2718e68a3e895f0d0b73ccc9e45b9b6f210f163512ba76f91dab409eb8792f6dae188356f9095747512a3101646b3dea9d37fb8c7c6bf37796d18c - languageName: node - linkType: hard - -"call-bind-apply-helpers@npm:^1.0.2": - version: 1.0.2 - resolution: "call-bind-apply-helpers@npm:1.0.2" - dependencies: - es-errors: "npm:^1.3.0" - function-bind: "npm:^1.1.2" - checksum: 10c0/47bd9901d57b857590431243fea704ff18078b16890a6b3e021e12d279bbf211d039155e27d7566b374d49ee1f8189344bac9833dec7a20cdec370506361c938 - languageName: node - linkType: hard - -"call-bind@npm:^1.0.0, call-bind@npm:^1.0.2, call-bind@npm:^1.0.7, call-bind@npm:^1.0.8": - version: 1.0.8 - resolution: "call-bind@npm:1.0.8" - dependencies: - call-bind-apply-helpers: "npm:^1.0.0" - es-define-property: "npm:^1.0.0" - get-intrinsic: "npm:^1.2.4" - set-function-length: "npm:^1.2.2" - checksum: 10c0/a13819be0681d915144467741b69875ae5f4eba8961eb0bf322aab63ec87f8250eb6d6b0dcbb2e1349876412a56129ca338592b3829ef4343527f5f18a0752d4 - languageName: node - linkType: hard - -"call-bound@npm:^1.0.2, call-bound@npm:^1.0.3": - version: 1.0.3 - resolution: "call-bound@npm:1.0.3" - dependencies: - call-bind-apply-helpers: "npm:^1.0.1" - get-intrinsic: "npm:^1.2.6" - checksum: 10c0/45257b8e7621067304b30dbd638e856cac913d31e8e00a80d6cf172911acd057846572d0b256b45e652d515db6601e2974a1b1a040e91b4fc36fb3dd86fa69cf - languageName: node - linkType: hard - -"call-bound@npm:^1.0.4": - version: 1.0.4 - resolution: "call-bound@npm:1.0.4" - dependencies: - call-bind-apply-helpers: "npm:^1.0.2" - get-intrinsic: "npm:^1.3.0" - checksum: 10c0/f4796a6a0941e71c766aea672f63b72bc61234c4f4964dc6d7606e3664c307e7d77845328a8f3359ce39ddb377fed67318f9ee203dea1d47e46165dcf2917644 - languageName: node - linkType: hard - -"callsites@npm:^3.0.0": - version: 3.1.0 - resolution: "callsites@npm:3.1.0" - checksum: 10c0/fff92277400eb06c3079f9e74f3af120db9f8ea03bad0e84d9aede54bbe2d44a56cccb5f6cf12211f93f52306df87077ecec5b712794c5a9b5dac6d615a3f301 - languageName: node - linkType: hard - -"camel-case@npm:^4.1.2": - version: 4.1.2 - resolution: "camel-case@npm:4.1.2" - dependencies: - pascal-case: "npm:^3.1.2" - tslib: "npm:^2.0.3" - checksum: 10c0/bf9eefaee1f20edbed2e9a442a226793bc72336e2b99e5e48c6b7252b6f70b080fc46d8246ab91939e2af91c36cdd422e0af35161e58dd089590f302f8f64c8a - languageName: node - linkType: hard - -"camelcase@npm:^5.0.0": - version: 5.3.1 - resolution: "camelcase@npm:5.3.1" - checksum: 10c0/92ff9b443bfe8abb15f2b1513ca182d16126359ad4f955ebc83dc4ddcc4ef3fdd2c078bc223f2673dc223488e75c99b16cc4d056624374b799e6a1555cf61b23 - languageName: node - linkType: hard - -"camelcase@npm:^6.2.0": - version: 6.3.0 - resolution: "camelcase@npm:6.3.0" - checksum: 10c0/0d701658219bd3116d12da3eab31acddb3f9440790c0792e0d398f0a520a6a4058018e546862b6fba89d7ae990efaeb97da71e1913e9ebf5a8b5621a3d55c710 - languageName: node - linkType: hard - -"caniuse-lite@npm:^1.0.30001688": - version: 1.0.30001757 - resolution: "caniuse-lite@npm:1.0.30001757" - checksum: 10c0/3ccb71fa2bf1f8c96ff1bf9b918b08806fed33307e20a3ce3259155fda131eaf96cfcd88d3d309c8fd7f8285cc71d89a3b93648a1c04814da31c301f98508d42 - languageName: node - linkType: hard - -"caniuse-lite@npm:^1.0.30001759, caniuse-lite@npm:^1.0.30001760": - version: 1.0.30001762 - resolution: "caniuse-lite@npm:1.0.30001762" - checksum: 10c0/93707eac5b0240af3f2ce6e2d7ab504a6fefcf9c2f9cd8fb9d488e496a333c61e557dab0472c1b00c17bc386a5dbb792aa4c778cda2d768e17f986617d7aec53 - languageName: node - linkType: hard - -"caseless@npm:~0.12.0": - version: 0.12.0 - resolution: "caseless@npm:0.12.0" - checksum: 10c0/ccf64bcb6c0232cdc5b7bd91ddd06e23a4b541f138336d4725233ac538041fb2f29c2e86c3c4a7a61ef990b665348db23a047060b9414c3a6603e9fa61ad4626 - languageName: node - linkType: hard - -"chai@npm:^5.2.0": - version: 5.3.3 - resolution: "chai@npm:5.3.3" - dependencies: - assertion-error: "npm:^2.0.1" - check-error: "npm:^2.1.1" - deep-eql: "npm:^5.0.1" - loupe: "npm:^3.1.0" - pathval: "npm:^2.0.0" - checksum: 10c0/b360fd4d38861622e5010c2f709736988b05c7f31042305fa3f4e9911f6adb80ccfb4e302068bf8ed10e835c2e2520cba0f5edc13d878b886987e5aa62483f53 - languageName: node - linkType: hard - -"chai@npm:^6.2.2": - version: 6.2.2 - resolution: "chai@npm:6.2.2" - checksum: 10c0/e6c69e5f0c11dffe6ea13d0290936ebb68fcc1ad688b8e952e131df6a6d5797d5e860bc55cef1aca2e950c3e1f96daf79e9d5a70fb7dbaab4e46355e2635ed53 - languageName: node - linkType: hard - -"chalk@npm:4.1.2, chalk@npm:^4.0.0, chalk@npm:^4.0.2, chalk@npm:~4.1.0": - version: 4.1.2 - resolution: "chalk@npm:4.1.2" - dependencies: - ansi-styles: "npm:^4.1.0" - supports-color: "npm:^7.1.0" - checksum: 10c0/4a3fef5cc34975c898ffe77141450f679721df9dde00f6c304353fa9c8b571929123b26a0e4617bde5018977eb655b31970c297b91b63ee83bb82aeb04666880 - languageName: node - linkType: hard - -"chalk@npm:^2.4.2": - version: 2.4.2 - resolution: "chalk@npm:2.4.2" - dependencies: - ansi-styles: "npm:^3.2.1" - escape-string-regexp: "npm:^1.0.5" - supports-color: "npm:^5.3.0" - checksum: 10c0/e6543f02ec877732e3a2d1c3c3323ddb4d39fbab687c23f526e25bd4c6a9bf3b83a696e8c769d078e04e5754921648f7821b2a2acfd16c550435fd630026e073 - languageName: node - linkType: hard - -"chalk@npm:^5.4.1": - version: 5.4.1 - resolution: "chalk@npm:5.4.1" - checksum: 10c0/b23e88132c702f4855ca6d25cb5538b1114343e41472d5263ee8a37cccfccd9c4216d111e1097c6a27830407a1dc81fecdf2a56f2c63033d4dbbd88c10b0dcef - languageName: node - linkType: hard - -"check-error@npm:^2.1.1": - version: 2.1.3 - resolution: "check-error@npm:2.1.3" - checksum: 10c0/878e99038fb6476316b74668cd6a498c7e66df3efe48158fa40db80a06ba4258742ac3ee2229c4a2a98c5e73f5dff84eb3e50ceb6b65bbd8f831eafc8338607d - languageName: node - linkType: hard - -"cheerio-select@npm:^2.1.0": - version: 2.1.0 - resolution: "cheerio-select@npm:2.1.0" - dependencies: - boolbase: "npm:^1.0.0" - css-select: "npm:^5.1.0" - css-what: "npm:^6.1.0" - domelementtype: "npm:^2.3.0" - domhandler: "npm:^5.0.3" - domutils: "npm:^3.0.1" - checksum: 10c0/2242097e593919dba4aacb97d7b8275def8b9ec70b00aa1f43335456870cfc9e284eae2080bdc832ed232dabb9eefcf56c722d152da4a154813fb8814a55d282 - languageName: node - linkType: hard - -"cheerio@npm:^1.0.0": - version: 1.0.0 - resolution: "cheerio@npm:1.0.0" - dependencies: - cheerio-select: "npm:^2.1.0" - dom-serializer: "npm:^2.0.0" - domhandler: "npm:^5.0.3" - domutils: "npm:^3.1.0" - encoding-sniffer: "npm:^0.2.0" - htmlparser2: "npm:^9.1.0" - parse5: "npm:^7.1.2" - parse5-htmlparser2-tree-adapter: "npm:^7.0.0" - parse5-parser-stream: "npm:^7.1.2" - undici: "npm:^6.19.5" - whatwg-mimetype: "npm:^4.0.0" - checksum: 10c0/d0e16925d9c36c879edfaef1c0244c866375a4c7b8d6ccd7ae0ad42da7d26263ea1a3c17b9a1aa5965918deeff2d40ac2e7223824f8e6eca972df3b81316a09f - languageName: node - linkType: hard - -"chokidar@npm:^3.5.3": - version: 3.6.0 - resolution: "chokidar@npm:3.6.0" - dependencies: - anymatch: "npm:~3.1.2" - braces: "npm:~3.0.2" - fsevents: "npm:~2.3.2" - glob-parent: "npm:~5.1.2" - is-binary-path: "npm:~2.1.0" - is-glob: "npm:~4.0.1" - normalize-path: "npm:~3.0.0" - readdirp: "npm:~3.6.0" - dependenciesMeta: - fsevents: - optional: true - checksum: 10c0/8361dcd013f2ddbe260eacb1f3cb2f2c6f2b0ad118708a343a5ed8158941a39cb8fb1d272e0f389712e74ee90ce8ba864eece9e0e62b9705cb468a2f6d917462 - languageName: node - linkType: hard - -"chokidar@npm:^4.0.0": - version: 4.0.3 - resolution: "chokidar@npm:4.0.3" - dependencies: - readdirp: "npm:^4.0.1" - checksum: 10c0/a58b9df05bb452f7d105d9e7229ac82fa873741c0c40ddcc7bb82f8a909fbe3f7814c9ebe9bc9a2bef9b737c0ec6e2d699d179048ef06ad3ec46315df0ebe6ad - languageName: node - linkType: hard - -"chownr@npm:^3.0.0": - version: 3.0.0 - resolution: "chownr@npm:3.0.0" - checksum: 10c0/43925b87700f7e3893296c8e9c56cc58f926411cce3a6e5898136daaf08f08b9a8eb76d37d3267e707d0dcc17aed2e2ebdf5848c0c3ce95cf910a919935c1b10 - languageName: node - linkType: hard - -"ci-info@npm:^4.0.0": - version: 4.1.0 - resolution: "ci-info@npm:4.1.0" - checksum: 10c0/0f969ce32a974c542bc8abe4454b220d9d9323bb9415054c92a900faa5fdda0bb222eda68c490127c1d78503510d46b6aca614ecaba5a60515b8ac7e170119e6 - languageName: node - linkType: hard - -"cipher-base@npm:^1.0.0, cipher-base@npm:^1.0.1, cipher-base@npm:^1.0.3": - version: 1.0.7 - resolution: "cipher-base@npm:1.0.7" - dependencies: - inherits: "npm:^2.0.4" - safe-buffer: "npm:^5.2.1" - to-buffer: "npm:^1.2.2" - checksum: 10c0/53c5046a9d9b60c586479b8f13fde263c3f905e13f11e8e04c7a311ce399c91d9c3ec96642332e0de077d356e1014ee12bba96f74fbaad0de750f49122258836 - languageName: node - linkType: hard - -"classnames@npm:^2.3.1, classnames@npm:^2.5.1": - version: 2.5.1 - resolution: "classnames@npm:2.5.1" - checksum: 10c0/afff4f77e62cea2d79c39962980bf316bacb0d7c49e13a21adaadb9221e1c6b9d3cdb829d8bb1b23c406f4e740507f37e1dcf506f7e3b7113d17c5bab787aa69 - languageName: node - linkType: hard - -"clean-css@npm:^5.2.2": - version: 5.3.3 - resolution: "clean-css@npm:5.3.3" - dependencies: - source-map: "npm:~0.6.0" - checksum: 10c0/381de7523e23f3762eb180e327dcc0cedafaf8cb1cd8c26b7cc1fc56e0829a92e734729c4f955394d65ed72fb62f82d8baf78af34b33b8a7d41ebad2accdd6fb - languageName: node - linkType: hard - -"clean-regexp@npm:^1.0.0": - version: 1.0.0 - resolution: "clean-regexp@npm:1.0.0" - dependencies: - escape-string-regexp: "npm:^1.0.5" - checksum: 10c0/fd9c7446551b8fc536f95e8a286d431017cd4ba1ec2e53997ec9159385e9c317672f6dfc4d49fdb97449fdb53b0bacd0a8bab9343b8fdd2e46c7ddf6173d0db7 - languageName: node - linkType: hard - -"cliui@npm:^6.0.0": - version: 6.0.0 - resolution: "cliui@npm:6.0.0" - dependencies: - string-width: "npm:^4.2.0" - strip-ansi: "npm:^6.0.0" - wrap-ansi: "npm:^6.2.0" - checksum: 10c0/35229b1bb48647e882104cac374c9a18e34bbf0bace0e2cf03000326b6ca3050d6b59545d91e17bfe3705f4a0e2988787aa5cde6331bf5cbbf0164732cef6492 - languageName: node - linkType: hard - -"cliui@npm:^8.0.1": - version: 8.0.1 - resolution: "cliui@npm:8.0.1" - dependencies: - string-width: "npm:^4.2.0" - strip-ansi: "npm:^6.0.1" - wrap-ansi: "npm:^7.0.0" - checksum: 10c0/4bda0f09c340cbb6dfdc1ed508b3ca080f12992c18d68c6be4d9cf51756033d5266e61ec57529e610dacbf4da1c634423b0c1b11037709cc6b09045cbd815df5 - languageName: node - linkType: hard - -"clone-stats@npm:^1.0.0": - version: 1.0.0 - resolution: "clone-stats@npm:1.0.0" - checksum: 10c0/bb1e05991e034e1eb104173c25bb652ea5b2b4dad5a49057a857e00f8d1da39de3bd689128a25bab8cbdfbea8ae8f6066030d106ed5c299a7d92be7967c50217 - languageName: node - linkType: hard - -"clone@npm:^2.1.2": - version: 2.1.2 - resolution: "clone@npm:2.1.2" - checksum: 10c0/ed0601cd0b1606bc7d82ee7175b97e68d1dd9b91fd1250a3617b38d34a095f8ee0431d40a1a611122dcccb4f93295b4fdb94942aa763392b5fe44effa50c2d5e - languageName: node - linkType: hard - -"clsx@npm:2.1.1": - version: 2.1.1 - resolution: "clsx@npm:2.1.1" - checksum: 10c0/c4c8eb865f8c82baab07e71bfa8897c73454881c4f99d6bc81585aecd7c441746c1399d08363dc096c550cceaf97bd4ce1e8854e1771e9998d9f94c4fe075839 - languageName: node - linkType: hard - -"color-convert@npm:^1.9.0": - version: 1.9.3 - resolution: "color-convert@npm:1.9.3" - dependencies: - color-name: "npm:1.1.3" - checksum: 10c0/5ad3c534949a8c68fca8fbc6f09068f435f0ad290ab8b2f76841b9e6af7e0bb57b98cb05b0e19fe33f5d91e5a8611ad457e5f69e0a484caad1f7487fd0e8253c - languageName: node - linkType: hard - -"color-convert@npm:^2.0.1": - version: 2.0.1 - resolution: "color-convert@npm:2.0.1" - dependencies: - color-name: "npm:~1.1.4" - checksum: 10c0/37e1150172f2e311fe1b2df62c6293a342ee7380da7b9cfdba67ea539909afbd74da27033208d01d6d5cfc65ee7868a22e18d7e7648e004425441c0f8a15a7d7 - languageName: node - linkType: hard - -"color-name@npm:1.1.3": - version: 1.1.3 - resolution: "color-name@npm:1.1.3" - checksum: 10c0/566a3d42cca25b9b3cd5528cd7754b8e89c0eb646b7f214e8e2eaddb69994ac5f0557d9c175eb5d8f0ad73531140d9c47525085ee752a91a2ab15ab459caf6d6 - languageName: node - linkType: hard - -"color-name@npm:~1.1.4": - version: 1.1.4 - resolution: "color-name@npm:1.1.4" - checksum: 10c0/a1a3f914156960902f46f7f56bc62effc6c94e84b2cae157a526b1c1f74b677a47ec602bf68a61abfa2b42d15b7c5651c6dbe72a43af720bc588dff885b10f95 - languageName: node - linkType: hard - -"colorette@npm:^2.0.16": - version: 2.0.20 - resolution: "colorette@npm:2.0.20" - checksum: 10c0/e94116ff33b0ff56f3b83b9ace895e5bf87c2a7a47b3401b8c3f3226e050d5ef76cf4072fb3325f9dc24d1698f9b730baf4e05eeaf861d74a1883073f4c98a40 - languageName: node - linkType: hard - -"colors@npm:^1.4.0": - version: 1.4.0 - resolution: "colors@npm:1.4.0" - checksum: 10c0/9af357c019da3c5a098a301cf64e3799d27549d8f185d86f79af23069e4f4303110d115da98483519331f6fb71c8568d5688fa1c6523600044fd4a54e97c4efb - languageName: node - linkType: hard - -"commander@npm:^12.1.0": - version: 12.1.0 - resolution: "commander@npm:12.1.0" - checksum: 10c0/6e1996680c083b3b897bfc1cfe1c58dfbcd9842fd43e1aaf8a795fbc237f65efcc860a3ef457b318e73f29a4f4a28f6403c3d653d021d960e4632dd45bde54a9 - languageName: node - linkType: hard - -"commander@npm:^2.20.0": - version: 2.20.3 - resolution: "commander@npm:2.20.3" - checksum: 10c0/74c781a5248c2402a0a3e966a0a2bba3c054aad144f5c023364be83265e796b20565aa9feff624132ff629aa64e16999fa40a743c10c12f7c61e96a794b99288 - languageName: node - linkType: hard - -"commander@npm:^8.3.0": - version: 8.3.0 - resolution: "commander@npm:8.3.0" - checksum: 10c0/8b043bb8322ea1c39664a1598a95e0495bfe4ca2fad0d84a92d7d1d8d213e2a155b441d2470c8e08de7c4a28cf2bc6e169211c49e1b21d9f7edc6ae4d9356060 - languageName: node - linkType: hard - -"comment-parser@npm:1.4.1": - version: 1.4.1 - resolution: "comment-parser@npm:1.4.1" - checksum: 10c0/d6c4be3f5be058f98b24f2d557f745d8fe1cc9eb75bebbdccabd404a0e1ed41563171b16285f593011f8b6a5ec81f564fb1f2121418ac5cbf0f49255bf0840dd - languageName: node - linkType: hard - -"common-tags@npm:^1.8.0": - version: 1.8.2 - resolution: "common-tags@npm:1.8.2" - checksum: 10c0/23efe47ff0a1a7c91489271b3a1e1d2a171c12ec7f9b35b29b2fce51270124aff0ec890087e2bc2182c1cb746e232ab7561aaafe05f1e7452aea733d2bfe3f63 - languageName: node - linkType: hard - -"connect-history-api-fallback@npm:^1.6.0": - version: 1.6.0 - resolution: "connect-history-api-fallback@npm:1.6.0" - checksum: 10c0/6d59c68070fcb2f6d981992f88d050d7544e8e1af6600c23ad680d955e316216794a742a1669d1f14ed5171fc628b916f8a4e15c5a1e55bffc8ccc60bfeb0b2c - languageName: node - linkType: hard - -"consola@npm:^2.15.3": - version: 2.15.3 - resolution: "consola@npm:2.15.3" - checksum: 10c0/34a337e6b4a1349ee4d7b4c568484344418da8fdb829d7d71bfefcd724f608f273987633b6eef465e8de510929907a092e13cb7a28a5d3acb3be446fcc79fd5e - languageName: node - linkType: hard - -"console-browserify@npm:^1.1.0": - version: 1.2.0 - resolution: "console-browserify@npm:1.2.0" - checksum: 10c0/89b99a53b7d6cee54e1e64fa6b1f7ac24b844b4019c5d39db298637e55c1f4ffa5c165457ad984864de1379df2c8e1886cbbdac85d9dbb6876a9f26c3106f226 - languageName: node - linkType: hard - -"constants-browserify@npm:^1.0.0": - version: 1.0.0 - resolution: "constants-browserify@npm:1.0.0" - checksum: 10c0/ab49b1d59a433ed77c964d90d19e08b2f77213fb823da4729c0baead55e3c597f8f97ebccfdfc47bd896d43854a117d114c849a6f659d9986420e97da0f83ac5 - languageName: node - linkType: hard - -"content-type@npm:^1.0.4": - version: 1.0.5 - resolution: "content-type@npm:1.0.5" - checksum: 10c0/b76ebed15c000aee4678c3707e0860cb6abd4e680a598c0a26e17f0bfae723ec9cc2802f0ff1bc6e4d80603719010431d2231018373d4dde10f9ccff9dadf5af - languageName: node - linkType: hard - -"convert-source-map@npm:^2.0.0": - version: 2.0.0 - resolution: "convert-source-map@npm:2.0.0" - checksum: 10c0/8f2f7a27a1a011cc6cc88cc4da2d7d0cfa5ee0369508baae3d98c260bb3ac520691464e5bbe4ae7cdf09860c1d69ecc6f70c63c6e7c7f7e3f18ec08484dc7d9b - languageName: node - linkType: hard - -"cookie@npm:^1.0.1": - version: 1.0.2 - resolution: "cookie@npm:1.0.2" - checksum: 10c0/fd25fe79e8fbcfcaf6aa61cd081c55d144eeeba755206c058682257cb38c4bd6795c6620de3f064c740695bb65b7949ebb1db7a95e4636efb8357a335ad3f54b - languageName: node - linkType: hard - -"copy-to-clipboard@npm:^3.3.3": - version: 3.3.3 - resolution: "copy-to-clipboard@npm:3.3.3" - dependencies: - toggle-selection: "npm:^1.0.6" - checksum: 10c0/3ebf5e8ee00601f8c440b83ec08d838e8eabb068c1fae94a9cda6b42f288f7e1b552f3463635f419af44bf7675afc8d0390d30876cf5c2d5d35f86d9c56a3e5f - languageName: node - linkType: hard - -"core-js-compat@npm:^3.38.1": - version: 3.40.0 - resolution: "core-js-compat@npm:3.40.0" - dependencies: - browserslist: "npm:^4.24.3" - checksum: 10c0/44f6e88726fe266a5be9581a79766800478a8d5c492885f2d4c2a4e2babd9b06bc1689d5340d3a61ae7332f990aff2e83b6203ff8773137a627cfedfbeefabeb - languageName: node - linkType: hard - -"core-js-compat@npm:^3.48.0": - version: 3.48.0 - resolution: "core-js-compat@npm:3.48.0" - dependencies: - browserslist: "npm:^4.28.1" - checksum: 10c0/7bb6522127928fff5d56c7050f379a034de85fe2d5c6e6925308090d4b51fb0cb88e0db99619c932ee84d8756d531bf851232948fe1ad18598cb1e7278e8db13 - languageName: node - linkType: hard - -"core-util-is@npm:~1.0.0": - version: 1.0.3 - resolution: "core-util-is@npm:1.0.3" - checksum: 10c0/90a0e40abbddfd7618f8ccd63a74d88deea94e77d0e8dbbea059fa7ebebb8fbb4e2909667fe26f3a467073de1a542ebe6ae4c73a73745ac5833786759cd906c9 - languageName: node - linkType: hard - -"cosmiconfig@npm:^8.1.3": - version: 8.3.6 - resolution: "cosmiconfig@npm:8.3.6" - dependencies: - import-fresh: "npm:^3.3.0" - js-yaml: "npm:^4.1.0" - parse-json: "npm:^5.2.0" - path-type: "npm:^4.0.0" - peerDependencies: - typescript: ">=4.9.5" - peerDependenciesMeta: - typescript: - optional: true - checksum: 10c0/0382a9ed13208f8bfc22ca2f62b364855207dffdb73dc26e150ade78c3093f1cf56172df2dd460c8caf2afa91c0ed4ec8a88c62f8f9cd1cf423d26506aa8797a - languageName: node - linkType: hard - -"create-ecdh@npm:^4.0.4": - version: 4.0.4 - resolution: "create-ecdh@npm:4.0.4" - dependencies: - bn.js: "npm:^4.1.0" - elliptic: "npm:^6.5.3" - checksum: 10c0/77b11a51360fec9c3bce7a76288fc0deba4b9c838d5fb354b3e40c59194d23d66efe6355fd4b81df7580da0661e1334a235a2a5c040b7569ba97db428d466e7f - languageName: node - linkType: hard - -"create-hash@npm:^1.1.0, create-hash@npm:^1.2.0": - version: 1.2.0 - resolution: "create-hash@npm:1.2.0" - dependencies: - cipher-base: "npm:^1.0.1" - inherits: "npm:^2.0.1" - md5.js: "npm:^1.3.4" - ripemd160: "npm:^2.0.1" - sha.js: "npm:^2.4.0" - checksum: 10c0/d402e60e65e70e5083cb57af96d89567954d0669e90550d7cec58b56d49c4b193d35c43cec8338bc72358198b8cbf2f0cac14775b651e99238e1cf411490f915 - languageName: node - linkType: hard - -"create-hmac@npm:^1.1.7": - version: 1.1.7 - resolution: "create-hmac@npm:1.1.7" - dependencies: - cipher-base: "npm:^1.0.3" - create-hash: "npm:^1.1.0" - inherits: "npm:^2.0.1" - ripemd160: "npm:^2.0.0" - safe-buffer: "npm:^5.0.1" - sha.js: "npm:^2.4.8" - checksum: 10c0/24332bab51011652a9a0a6d160eed1e8caa091b802335324ae056b0dcb5acbc9fcf173cf10d128eba8548c3ce98dfa4eadaa01bd02f44a34414baee26b651835 - languageName: node - linkType: hard - -"create-require@npm:^1.1.1": - version: 1.1.1 - resolution: "create-require@npm:1.1.1" - checksum: 10c0/157cbc59b2430ae9a90034a5f3a1b398b6738bf510f713edc4d4e45e169bc514d3d99dd34d8d01ca7ae7830b5b8b537e46ae8f3c8f932371b0875c0151d7ec91 - languageName: node - linkType: hard - -"cross-spawn@npm:^7.0.2, cross-spawn@npm:^7.0.6": - version: 7.0.6 - resolution: "cross-spawn@npm:7.0.6" - dependencies: - path-key: "npm:^3.1.0" - shebang-command: "npm:^2.0.0" - which: "npm:^2.0.1" - checksum: 10c0/053ea8b2135caff68a9e81470e845613e374e7309a47731e81639de3eaeb90c3d01af0e0b44d2ab9d50b43467223b88567dfeb3262db942dc063b9976718ffc1 - languageName: node - linkType: hard - -"crypto-browserify@npm:^3.12.1": - version: 3.12.1 - resolution: "crypto-browserify@npm:3.12.1" - dependencies: - browserify-cipher: "npm:^1.0.1" - browserify-sign: "npm:^4.2.3" - create-ecdh: "npm:^4.0.4" - create-hash: "npm:^1.2.0" - create-hmac: "npm:^1.1.7" - diffie-hellman: "npm:^5.0.3" - hash-base: "npm:~3.0.4" - inherits: "npm:^2.0.4" - pbkdf2: "npm:^3.1.2" - public-encrypt: "npm:^4.0.3" - randombytes: "npm:^2.1.0" - randomfill: "npm:^1.0.4" - checksum: 10c0/184a2def7b16628e79841243232ab5497f18d8e158ac21b7ce90ab172427d0a892a561280adc08f9d4d517bce8db2a5b335dc21abb970f787f8e874bd7b9db7d - languageName: node - linkType: hard - -"css-blank-pseudo@npm:^7.0.1": - version: 7.0.1 - resolution: "css-blank-pseudo@npm:7.0.1" - dependencies: - postcss-selector-parser: "npm:^7.0.0" - peerDependencies: - postcss: ^8.4 - checksum: 10c0/46c3d3a611972fdb0c264db7c0b34fe437bc4300961d11945145cf04962f52a545a6ef55bc8ff4afd82b605bd692b4970f2b54582616dea00441105e725d4618 - languageName: node - linkType: hard - -"css-has-pseudo@npm:^7.0.3": - version: 7.0.3 - resolution: "css-has-pseudo@npm:7.0.3" - dependencies: - "@csstools/selector-specificity": "npm:^5.0.0" - postcss-selector-parser: "npm:^7.0.0" - postcss-value-parser: "npm:^4.2.0" - peerDependencies: - postcss: ^8.4 - checksum: 10c0/c89f68e17bed229e9a3e98da5032e1360c83d45d974bc3fb8d6b5358399bca80cce7929e4a621a516a75536edb78678dc486eb41841eeed28cca79e3be4bdc27 - languageName: node - linkType: hard - -"css-prefers-color-scheme@npm:^10.0.0": - version: 10.0.0 - resolution: "css-prefers-color-scheme@npm:10.0.0" - peerDependencies: - postcss: ^8.4 - checksum: 10c0/a66c727bb2455328b18862f720819fc98ff5c1486b69f758bdb5c66f46cc6d484f9fc0bfa4f00f2693c5da6707ad136ca789496982f713ade693f08af624930e - languageName: node - linkType: hard - -"css-select@npm:^4.2.1": - version: 4.3.0 - resolution: "css-select@npm:4.3.0" - dependencies: - boolbase: "npm:^1.0.0" - css-what: "npm:^6.0.1" - domhandler: "npm:^4.3.1" - domutils: "npm:^2.8.0" - nth-check: "npm:^2.0.1" - checksum: 10c0/a489d8e5628e61063d5a8fe0fa1cc7ae2478cb334a388a354e91cf2908154be97eac9fa7ed4dffe87a3e06cf6fcaa6016553115335c4fd3377e13dac7bd5a8e1 - languageName: node - linkType: hard - -"css-select@npm:^5.1.0": - version: 5.1.0 - resolution: "css-select@npm:5.1.0" - dependencies: - boolbase: "npm:^1.0.0" - css-what: "npm:^6.1.0" - domhandler: "npm:^5.0.2" - domutils: "npm:^3.0.1" - nth-check: "npm:^2.0.1" - checksum: 10c0/551c60dba5b54054741032c1793b5734f6ba45e23ae9e82761a3c0ed1acbb8cfedfa443aaba3a3c1a54cac12b456d2012a09d2cd5f0e82e430454c1b9d84d500 - languageName: node - linkType: hard - -"css-what@npm:^6.0.1, css-what@npm:^6.1.0": - version: 6.1.0 - resolution: "css-what@npm:6.1.0" - checksum: 10c0/a09f5a6b14ba8dcf57ae9a59474722e80f20406c53a61e9aedb0eedc693b135113ffe2983f4efc4b5065ae639442e9ae88df24941ef159c218b231011d733746 - languageName: node - linkType: hard - -"css.escape@npm:^1.5.1": - version: 1.5.1 - resolution: "css.escape@npm:1.5.1" - checksum: 10c0/5e09035e5bf6c2c422b40c6df2eb1529657a17df37fda5d0433d722609527ab98090baf25b13970ca754079a0f3161dd3dfc0e743563ded8cfa0749d861c1525 - languageName: node - linkType: hard - -"cssdb@npm:^8.6.0": - version: 8.6.0 - resolution: "cssdb@npm:8.6.0" - checksum: 10c0/4bb7b77ba24902e8d481e9514ec0be56e205186a2b7d9f5027fedfe718952c559c62acfd2859f92869f8090da7c2170f83d68170db5058a6ba8d9d5e8ded3b3e - languageName: node - linkType: hard - -"cssesc@npm:^3.0.0": - version: 3.0.0 - resolution: "cssesc@npm:3.0.0" - bin: - cssesc: bin/cssesc - checksum: 10c0/6bcfd898662671be15ae7827120472c5667afb3d7429f1f917737f3bf84c4176003228131b643ae74543f17a394446247df090c597bb9a728cce298606ed0aa7 - languageName: node - linkType: hard - -"cssstyle@npm:^4.2.1": - version: 4.2.1 - resolution: "cssstyle@npm:4.2.1" - dependencies: - "@asamuzakjp/css-color": "npm:^2.8.2" - rrweb-cssom: "npm:^0.8.0" - checksum: 10c0/02ba8c47c0caaab57acadacb3eb6c0f5f009000f55d61f6563670e07d389b26edefeed497e6c1847fcd2e6bbe0b6974c2d4291f97fa0c6ec6add13a7fa926d84 - languageName: node - linkType: hard - -"csstype@npm:^3.2.2": - version: 3.2.3 - resolution: "csstype@npm:3.2.3" - checksum: 10c0/cd29c51e70fa822f1cecd8641a1445bed7063697469d35633b516e60fe8c1bde04b08f6c5b6022136bb669b64c63d4173af54864510fbb4ee23281801841a3ce - languageName: node - linkType: hard - -"damerau-levenshtein@npm:^1.0.8": - version: 1.0.8 - resolution: "damerau-levenshtein@npm:1.0.8" - checksum: 10c0/4c2647e0f42acaee7d068756c1d396e296c3556f9c8314bac1ac63ffb236217ef0e7e58602b18bb2173deec7ec8e0cac8e27cccf8f5526666b4ff11a13ad54a3 - languageName: node - linkType: hard - -"data-urls@npm:^5.0.0": - version: 5.0.0 - resolution: "data-urls@npm:5.0.0" - dependencies: - whatwg-mimetype: "npm:^4.0.0" - whatwg-url: "npm:^14.0.0" - checksum: 10c0/1b894d7d41c861f3a4ed2ae9b1c3f0909d4575ada02e36d3d3bc584bdd84278e20709070c79c3b3bff7ac98598cb191eb3e86a89a79ea4ee1ef360e1694f92ad - languageName: node - linkType: hard - -"data-view-buffer@npm:^1.0.2": - version: 1.0.2 - resolution: "data-view-buffer@npm:1.0.2" - dependencies: - call-bound: "npm:^1.0.3" - es-errors: "npm:^1.3.0" - is-data-view: "npm:^1.0.2" - checksum: 10c0/7986d40fc7979e9e6241f85db8d17060dd9a71bd53c894fa29d126061715e322a4cd47a00b0b8c710394854183d4120462b980b8554012acc1c0fa49df7ad38c - languageName: node - linkType: hard - -"data-view-byte-length@npm:^1.0.2": - version: 1.0.2 - resolution: "data-view-byte-length@npm:1.0.2" - dependencies: - call-bound: "npm:^1.0.3" - es-errors: "npm:^1.3.0" - is-data-view: "npm:^1.0.2" - checksum: 10c0/f8a4534b5c69384d95ac18137d381f18a5cfae1f0fc1df0ef6feef51ef0d568606d970b69e02ea186c6c0f0eac77fe4e6ad96fec2569cc86c3afcc7475068c55 - languageName: node - linkType: hard - -"data-view-byte-offset@npm:^1.0.1": - version: 1.0.1 - resolution: "data-view-byte-offset@npm:1.0.1" - dependencies: - call-bound: "npm:^1.0.2" - es-errors: "npm:^1.3.0" - is-data-view: "npm:^1.0.1" - checksum: 10c0/fa7aa40078025b7810dcffc16df02c480573b7b53ef1205aa6a61533011005c1890e5ba17018c692ce7c900212b547262d33279fde801ad9843edc0863bf78c4 - languageName: node - linkType: hard - -"debug@npm:4, debug@npm:^4.1.0, debug@npm:^4.3.1, debug@npm:^4.3.4": - version: 4.4.0 - resolution: "debug@npm:4.4.0" - dependencies: - ms: "npm:^2.1.3" - peerDependenciesMeta: - supports-color: - optional: true - checksum: 10c0/db94f1a182bf886f57b4755f85b3a74c39b5114b9377b7ab375dc2cfa3454f09490cc6c30f829df3fc8042bc8b8995f6567ce5cd96f3bc3688bd24027197d9de - languageName: node - linkType: hard - -"debug@npm:^2.2.0": - version: 2.6.9 - resolution: "debug@npm:2.6.9" - dependencies: - ms: "npm:2.0.0" - checksum: 10c0/121908fb839f7801180b69a7e218a40b5a0b718813b886b7d6bdb82001b931c938e2941d1e4450f33a1b1df1da653f5f7a0440c197f29fbf8a6e9d45ff6ef589 - languageName: node - linkType: hard - -"debug@npm:^3.2.7": - version: 3.2.7 - resolution: "debug@npm:3.2.7" - dependencies: - ms: "npm:^2.1.1" - checksum: 10c0/37d96ae42cbc71c14844d2ae3ba55adf462ec89fd3a999459dec3833944cd999af6007ff29c780f1c61153bcaaf2c842d1e4ce1ec621e4fc4923244942e4a02a - languageName: node - linkType: hard - -"debug@npm:^4.3.2": - version: 4.3.7 - resolution: "debug@npm:4.3.7" - dependencies: - ms: "npm:^2.1.3" - peerDependenciesMeta: - supports-color: - optional: true - checksum: 10c0/1471db19c3b06d485a622d62f65947a19a23fbd0dd73f7fd3eafb697eec5360cde447fb075919987899b1a2096e85d35d4eb5a4de09a57600ac9cf7e6c8e768b - languageName: node - linkType: hard - -"debug@npm:^4.4.3": - version: 4.4.3 - resolution: "debug@npm:4.4.3" - dependencies: - ms: "npm:^2.1.3" - peerDependenciesMeta: - supports-color: - optional: true - checksum: 10c0/d79136ec6c83ecbefd0f6a5593da6a9c91ec4d7ddc4b54c883d6e71ec9accb5f67a1a5e96d00a328196b5b5c86d365e98d8a3a70856aaf16b4e7b1985e67f5a6 - languageName: node - linkType: hard - -"decamelize@npm:^1.2.0": - version: 1.2.0 - resolution: "decamelize@npm:1.2.0" - checksum: 10c0/85c39fe8fbf0482d4a1e224ef0119db5c1897f8503bcef8b826adff7a1b11414972f6fef2d7dec2ee0b4be3863cf64ac1439137ae9e6af23a3d8dcbe26a5b4b2 - languageName: node - linkType: hard - -"decamelize@npm:^5.0.0": - version: 5.0.1 - resolution: "decamelize@npm:5.0.1" - checksum: 10c0/3da71022bc1e85487810fa0833138effb599fa331ca21e179650e93a765d0c4dabeb1ecdd6ad1474fa0bacd2457953c63ea335afb6e53b35f2b4bf779514e2a3 - languageName: node - linkType: hard - -"decimal.js@npm:^10.4.3": - version: 10.4.3 - resolution: "decimal.js@npm:10.4.3" - checksum: 10c0/6d60206689ff0911f0ce968d40f163304a6c1bc739927758e6efc7921cfa630130388966f16bf6ef6b838cb33679fbe8e7a78a2f3c478afce841fd55ac8fb8ee - languageName: node - linkType: hard - -"decimal.js@npm:^10.5.0": - version: 10.5.0 - resolution: "decimal.js@npm:10.5.0" - checksum: 10c0/785c35279df32762143914668df35948920b6c1c259b933e0519a69b7003fc0a5ed2a766b1e1dda02574450c566b21738a45f15e274b47c2ac02072c0d1f3ac3 - languageName: node - linkType: hard - -"deep-eql@npm:^5.0.1": - version: 5.0.2 - resolution: "deep-eql@npm:5.0.2" - checksum: 10c0/7102cf3b7bb719c6b9c0db2e19bf0aa9318d141581befe8c7ce8ccd39af9eaa4346e5e05adef7f9bd7015da0f13a3a25dcfe306ef79dc8668aedbecb658dd247 - languageName: node - linkType: hard - -"deep-is@npm:^0.1.3": - version: 0.1.4 - resolution: "deep-is@npm:0.1.4" - checksum: 10c0/7f0ee496e0dff14a573dc6127f14c95061b448b87b995fc96c017ce0a1e66af1675e73f1d6064407975bc4ea6ab679497a29fff7b5b9c4e99cb10797c1ad0b4c - languageName: node - linkType: hard - -"default-browser-id@npm:^5.0.0": - version: 5.0.1 - resolution: "default-browser-id@npm:5.0.1" - checksum: 10c0/5288b3094c740ef3a86df9b999b04ff5ba4dee6b64e7b355c0fff5217752c8c86908d67f32f6cba9bb4f9b7b61a1b640c0a4f9e34c57e0ff3493559a625245ee - languageName: node - linkType: hard - -"default-browser@npm:^5.2.1": - version: 5.5.0 - resolution: "default-browser@npm:5.5.0" - dependencies: - bundle-name: "npm:^4.1.0" - default-browser-id: "npm:^5.0.0" - checksum: 10c0/576593b617b17a7223014b4571bfe1c06a2581a4eb8b130985d90d253afa3f40999caec70eb0e5776e80d4af6a41cce91018cd3f86e57ad578bf59e46fb19abe - languageName: node - linkType: hard - -"define-data-property@npm:^1.0.1, define-data-property@npm:^1.1.4": - version: 1.1.4 - resolution: "define-data-property@npm:1.1.4" - dependencies: - es-define-property: "npm:^1.0.0" - es-errors: "npm:^1.3.0" - gopd: "npm:^1.0.1" - checksum: 10c0/dea0606d1483eb9db8d930d4eac62ca0fa16738b0b3e07046cddfacf7d8c868bbe13fa0cb263eb91c7d0d527960dc3f2f2471a69ed7816210307f6744fe62e37 - languageName: node - linkType: hard - -"define-lazy-prop@npm:^3.0.0": - version: 3.0.0 - resolution: "define-lazy-prop@npm:3.0.0" - checksum: 10c0/5ab0b2bf3fa58b3a443140bbd4cd3db1f91b985cc8a246d330b9ac3fc0b6a325a6d82bddc0b055123d745b3f9931afeea74a5ec545439a1630b9c8512b0eeb49 - languageName: node - linkType: hard - -"define-properties@npm:^1.1.3, define-properties@npm:^1.2.0, define-properties@npm:^1.2.1": - version: 1.2.1 - resolution: "define-properties@npm:1.2.1" - dependencies: - define-data-property: "npm:^1.0.1" - has-property-descriptors: "npm:^1.0.0" - object-keys: "npm:^1.1.1" - checksum: 10c0/88a152319ffe1396ccc6ded510a3896e77efac7a1bfbaa174a7b00414a1747377e0bb525d303794a47cf30e805c2ec84e575758512c6e44a993076d29fd4e6c3 - languageName: node - linkType: hard - -"deprecation@npm:^2.0.0": - version: 2.3.1 - resolution: "deprecation@npm:2.3.1" - checksum: 10c0/23d688ba66b74d09b908c40a76179418acbeeb0bfdf218c8075c58ad8d0c315130cb91aa3dffb623aa3a411a3569ce56c6460de6c8d69071c17fe6dd2442f032 - languageName: node - linkType: hard - -"dequal@npm:^2.0.3": - version: 2.0.3 - resolution: "dequal@npm:2.0.3" - checksum: 10c0/f98860cdf58b64991ae10205137c0e97d384c3a4edc7f807603887b7c4b850af1224a33d88012009f150861cbee4fa2d322c4cc04b9313bee312e47f6ecaa888 - languageName: node - linkType: hard - -"des.js@npm:^1.0.0": - version: 1.1.0 - resolution: "des.js@npm:1.1.0" - dependencies: - inherits: "npm:^2.0.1" - minimalistic-assert: "npm:^1.0.0" - checksum: 10c0/671354943ad67493e49eb4c555480ab153edd7cee3a51c658082fcde539d2690ed2a4a0b5d1f401f9cde822edf3939a6afb2585f32c091f2d3a1b1665cd45236 - languageName: node - linkType: hard - -"detect-libc@npm:^1.0.3": - version: 1.0.3 - resolution: "detect-libc@npm:1.0.3" - bin: - detect-libc: ./bin/detect-libc.js - checksum: 10c0/4da0deae9f69e13bc37a0902d78bf7169480004b1fed3c19722d56cff578d16f0e11633b7fbf5fb6249181236c72e90024cbd68f0b9558ae06e281f47326d50d - languageName: node - linkType: hard - -"detect-libc@npm:^2.0.3": - version: 2.1.2 - resolution: "detect-libc@npm:2.1.2" - checksum: 10c0/acc675c29a5649fa1fb6e255f993b8ee829e510b6b56b0910666949c80c364738833417d0edb5f90e4e46be17228b0f2b66a010513984e18b15deeeac49369c4 - languageName: node - linkType: hard - -"detect-node-es@npm:^1.1.0": - version: 1.1.0 - resolution: "detect-node-es@npm:1.1.0" - checksum: 10c0/e562f00de23f10c27d7119e1af0e7388407eb4b06596a25f6d79a360094a109ff285de317f02b090faae093d314cf6e73ac3214f8a5bb3a0def5bece94557fbe - languageName: node - linkType: hard - -"diffie-hellman@npm:^5.0.3": - version: 5.0.3 - resolution: "diffie-hellman@npm:5.0.3" - dependencies: - bn.js: "npm:^4.1.0" - miller-rabin: "npm:^4.0.0" - randombytes: "npm:^2.0.0" - checksum: 10c0/ce53ccafa9ca544b7fc29b08a626e23a9b6562efc2a98559a0c97b4718937cebaa9b5d7d0a05032cc9c1435e9b3c1532b9e9bf2e0ede868525922807ad6e1ecf - languageName: node - linkType: hard - -"dijkstrajs@npm:^1.0.1": - version: 1.0.3 - resolution: "dijkstrajs@npm:1.0.3" - checksum: 10c0/2183d61ac1f25062f3c3773f3ea8d9f45ba164a00e77e07faf8cc5750da966222d1e2ce6299c875a80f969190c71a0973042192c5624d5223e4ed196ff584c99 - languageName: node - linkType: hard - -"dir-glob@npm:^3.0.1": - version: 3.0.1 - resolution: "dir-glob@npm:3.0.1" - dependencies: - path-type: "npm:^4.0.0" - checksum: 10c0/dcac00920a4d503e38bb64001acb19df4efc14536ada475725e12f52c16777afdee4db827f55f13a908ee7efc0cb282e2e3dbaeeb98c0993dd93d1802d3bf00c - languageName: node - linkType: hard - -"doctrine@npm:^2.1.0": - version: 2.1.0 - resolution: "doctrine@npm:2.1.0" - dependencies: - esutils: "npm:^2.0.2" - checksum: 10c0/b6416aaff1f380bf56c3b552f31fdf7a69b45689368deca72d28636f41c16bb28ec3ebc40ace97db4c1afc0ceeb8120e8492fe0046841c94c2933b2e30a7d5ac - languageName: node - linkType: hard - -"doctrine@npm:^3.0.0": - version: 3.0.0 - resolution: "doctrine@npm:3.0.0" - dependencies: - esutils: "npm:^2.0.2" - checksum: 10c0/c96bdccabe9d62ab6fea9399fdff04a66e6563c1d6fb3a3a063e8d53c3bb136ba63e84250bbf63d00086a769ad53aef92d2bd483f03f837fc97b71cbee6b2520 - languageName: node - linkType: hard - -"dom-accessibility-api@npm:^0.5.9": - version: 0.5.16 - resolution: "dom-accessibility-api@npm:0.5.16" - checksum: 10c0/b2c2eda4fae568977cdac27a9f0c001edf4f95a6a6191dfa611e3721db2478d1badc01db5bb4fa8a848aeee13e442a6c2a4386d65ec65a1436f24715a2f8d053 - languageName: node - linkType: hard - -"dom-accessibility-api@npm:^0.6.3": - version: 0.6.3 - resolution: "dom-accessibility-api@npm:0.6.3" - checksum: 10c0/10bee5aa514b2a9a37c87cd81268db607a2e933a050074abc2f6fa3da9080ebed206a320cbc123567f2c3087d22292853bdfdceaffdd4334ffe2af9510b29360 - languageName: node - linkType: hard - -"dom-serializer@npm:^1.0.1": - version: 1.4.1 - resolution: "dom-serializer@npm:1.4.1" - dependencies: - domelementtype: "npm:^2.0.1" - domhandler: "npm:^4.2.0" - entities: "npm:^2.0.0" - checksum: 10c0/67d775fa1ea3de52035c98168ddcd59418356943b5eccb80e3c8b3da53adb8e37edb2cc2f885802b7b1765bf5022aec21dfc32910d7f9e6de4c3148f095ab5e0 - languageName: node - linkType: hard - -"dom-serializer@npm:^2.0.0": - version: 2.0.0 - resolution: "dom-serializer@npm:2.0.0" - dependencies: - domelementtype: "npm:^2.3.0" - domhandler: "npm:^5.0.2" - entities: "npm:^4.2.0" - checksum: 10c0/d5ae2b7110ca3746b3643d3ef60ef823f5f078667baf530cec096433f1627ec4b6fa8c072f09d079d7cda915fd2c7bc1b7b935681e9b09e591e1e15f4040b8e2 - languageName: node - linkType: hard - -"domain-browser@npm:4.22.0": - version: 4.22.0 - resolution: "domain-browser@npm:4.22.0" - checksum: 10c0/2ef7eda6d2161038fda0c9aa4c9e18cc7a0baa89ea6be975d449527c2eefd4b608425db88508e2859acc472f46f402079274b24bd75e3fb506f28c5dba203129 - languageName: node - linkType: hard - -"domelementtype@npm:^2.0.1, domelementtype@npm:^2.2.0, domelementtype@npm:^2.3.0": - version: 2.3.0 - resolution: "domelementtype@npm:2.3.0" - checksum: 10c0/686f5a9ef0fff078c1412c05db73a0dce096190036f33e400a07e2a4518e9f56b1e324f5c576a0a747ef0e75b5d985c040b0d51945ce780c0dd3c625a18cd8c9 - languageName: node - linkType: hard - -"domhandler@npm:^4.2.0, domhandler@npm:^4.3.1": - version: 4.3.1 - resolution: "domhandler@npm:4.3.1" - dependencies: - domelementtype: "npm:^2.2.0" - checksum: 10c0/5c199c7468cb052a8b5ab80b13528f0db3d794c64fc050ba793b574e158e67c93f8336e87fd81e9d5ee43b0e04aea4d8b93ed7be4899cb726a1601b3ba18538b - languageName: node - linkType: hard - -"domhandler@npm:^5.0.2, domhandler@npm:^5.0.3": - version: 5.0.3 - resolution: "domhandler@npm:5.0.3" - dependencies: - domelementtype: "npm:^2.3.0" - checksum: 10c0/bba1e5932b3e196ad6862286d76adc89a0dbf0c773e5ced1eb01f9af930c50093a084eff14b8de5ea60b895c56a04d5de8bbc4930c5543d029091916770b2d2a - languageName: node - linkType: hard - -"domutils@npm:^2.8.0": - version: 2.8.0 - resolution: "domutils@npm:2.8.0" - dependencies: - dom-serializer: "npm:^1.0.1" - domelementtype: "npm:^2.2.0" - domhandler: "npm:^4.2.0" - checksum: 10c0/d58e2ae01922f0dd55894e61d18119924d88091837887bf1438f2327f32c65eb76426bd9384f81e7d6dcfb048e0f83c19b222ad7101176ad68cdc9c695b563db - languageName: node - linkType: hard - -"domutils@npm:^3.0.1, domutils@npm:^3.1.0": - version: 3.2.2 - resolution: "domutils@npm:3.2.2" - dependencies: - dom-serializer: "npm:^2.0.0" - domelementtype: "npm:^2.3.0" - domhandler: "npm:^5.0.3" - checksum: 10c0/47938f473b987ea71cd59e59626eb8666d3aa8feba5266e45527f3b636c7883cca7e582d901531961f742c519d7514636b7973353b648762b2e3bedbf235fada - languageName: node - linkType: hard - -"dot-case@npm:^3.0.4": - version: 3.0.4 - resolution: "dot-case@npm:3.0.4" - dependencies: - no-case: "npm:^3.0.4" - tslib: "npm:^2.0.3" - checksum: 10c0/5b859ea65097a7ea870e2c91b5768b72ddf7fa947223fd29e167bcdff58fe731d941c48e47a38ec8aa8e43044c8fbd15cd8fa21689a526bc34b6548197cd5b05 - languageName: node - linkType: hard - -"dotenv-expand@npm:^8.0.2": - version: 8.0.3 - resolution: "dotenv-expand@npm:8.0.3" - checksum: 10c0/bf928bdd75ec632918e41fc5822d507dcf4081ae1d07b47aaee086141f6bbdc202add9f214b4064e118db1ca343b59f3924b0721327954a7af46897069271672 - languageName: node - linkType: hard - -"dotenv@npm:^16.0.0, dotenv@npm:^16.3.1": - version: 16.4.7 - resolution: "dotenv@npm:16.4.7" - checksum: 10c0/be9f597e36a8daf834452daa1f4cc30e5375a5968f98f46d89b16b983c567398a330580c88395069a77473943c06b877d1ca25b4afafcdd6d4adb549e8293462 - languageName: node - linkType: hard - -"dunder-proto@npm:^1.0.0, dunder-proto@npm:^1.0.1": - version: 1.0.1 - resolution: "dunder-proto@npm:1.0.1" - dependencies: - call-bind-apply-helpers: "npm:^1.0.1" - es-errors: "npm:^1.3.0" - gopd: "npm:^1.2.0" - checksum: 10c0/199f2a0c1c16593ca0a145dbf76a962f8033ce3129f01284d48c45ed4e14fea9bbacd7b3610b6cdc33486cef20385ac054948fefc6272fcce645c09468f93031 - languageName: node - linkType: hard - -"eastasianwidth@npm:^0.2.0": - version: 0.2.0 - resolution: "eastasianwidth@npm:0.2.0" - checksum: 10c0/26f364ebcdb6395f95124fda411f63137a4bfb5d3a06453f7f23dfe52502905bd84e0488172e0f9ec295fdc45f05c23d5d91baf16bd26f0fe9acd777a188dc39 - languageName: node - linkType: hard - -"ejs@npm:^3.1.6, ejs@npm:^3.1.9": - version: 3.1.10 - resolution: "ejs@npm:3.1.10" - dependencies: - jake: "npm:^10.8.5" - bin: - ejs: bin/cli.js - checksum: 10c0/52eade9e68416ed04f7f92c492183340582a36482836b11eab97b159fcdcfdedc62233a1bf0bf5e5e1851c501f2dca0e2e9afd111db2599e4e7f53ee29429ae1 - languageName: node - linkType: hard - -"electron-to-chromium@npm:^1.5.263": - version: 1.5.267 - resolution: "electron-to-chromium@npm:1.5.267" - checksum: 10c0/0732bdb891b657f2e43266a3db8cf86fff6cecdcc8d693a92beff214e136cb5c2ee7dc5945ed75fa1db16e16bad0c38695527a020d15f39e79084e0b2e447621 - languageName: node - linkType: hard - -"electron-to-chromium@npm:^1.5.73": - version: 1.5.109 - resolution: "electron-to-chromium@npm:1.5.109" - checksum: 10c0/19d86b95b1288b2e73d9d6084f64b14d4ef2c51d8551d85697ea68da690542d26e6d07878ff053f137e561e3e6c8c2b062d0353bc159930569831f7960bb6ed7 - languageName: node - linkType: hard - -"element-call@workspace:.": - version: 0.0.0-use.local - resolution: "element-call@workspace:." - dependencies: - "@babel/core": "npm:^7.16.5" - "@babel/preset-env": "npm:^7.22.20" - "@babel/preset-react": "npm:^7.22.15" - "@babel/preset-typescript": "npm:^7.23.0" - "@codecov/vite-plugin": "npm:^1.3.0" - "@fontsource/inconsolata": "npm:^5.1.0" - "@fontsource/inter": "npm:^5.1.0" - "@formatjs/intl-durationformat": "npm:^0.10.0" - "@formatjs/intl-segmenter": "npm:^11.7.3" - "@livekit/components-core": "npm:^0.12.0" - "@livekit/components-react": "npm:^2.0.0" - "@livekit/protocol": "npm:^1.42.2" - "@livekit/track-processors": "npm:^0.7.1" - "@mediapipe/tasks-vision": "npm:^0.10.18" - "@playwright/test": "npm:^1.57.0" - "@radix-ui/react-dialog": "npm:^1.0.4" - "@radix-ui/react-slider": "npm:^1.1.2" - "@radix-ui/react-visually-hidden": "npm:^1.0.3" - "@react-spring/web": "npm:^10.0.0" - "@sentry/react": "npm:^8.0.0" - "@sentry/vite-plugin": "npm:^3.0.0" - "@storybook/addon-docs": "npm:^10.3.3" - "@storybook/react-vite": "npm:^10.3.3" - "@stylistic/eslint-plugin": "npm:^3.0.0" - "@testing-library/dom": "npm:^10.1.0" - "@testing-library/jest-dom": "npm:^6.6.3" - "@testing-library/react": "npm:^16.0.0" - "@testing-library/user-event": "npm:^14.5.1" - "@types/content-type": "npm:^1.1.5" - "@types/grecaptcha": "npm:^3.0.9" - "@types/jsdom": "npm:^21.1.7" - "@types/lodash-es": "npm:^4.17.12" - "@types/node": "npm:^24.0.0" - "@types/pako": "npm:^2.0.3" - "@types/qrcode": "npm:^1.5.5" - "@types/react": "npm:^19.0.0" - "@types/react-dom": "npm:^19.0.0" - "@types/sdp-transform": "npm:^2.4.5" - "@types/uuid": "npm:10" - "@typescript-eslint/eslint-plugin": "npm:^8.31.0" - "@typescript-eslint/parser": "npm:^8.31.0" - "@use-gesture/react": "npm:^10.2.11" - "@vector-im/compound-design-tokens": "npm:^10.0.0" - "@vector-im/compound-web": "npm:^9.0.0" - "@vitejs/plugin-react": "npm:^4.0.1" - "@vitest/coverage-v8": "npm:^4.0.18" - babel-plugin-transform-vite-meta-env: "npm:^1.0.3" - classnames: "npm:^2.3.1" - copy-to-clipboard: "npm:^3.3.3" - eslint: "npm:^8.14.0" - eslint-config-google: "npm:^0.14.0" - eslint-config-prettier: "npm:^10.0.0" - eslint-plugin-deprecate: "npm:^0.9.0" - eslint-plugin-import: "npm:^2.26.0" - eslint-plugin-jsdoc: "npm:^61.5.0" - eslint-plugin-jsx-a11y: "npm:^6.5.1" - eslint-plugin-matrix-org: "npm:2.1.0" - eslint-plugin-react: "npm:^7.29.4" - eslint-plugin-react-hooks: "npm:^5.0.0" - eslint-plugin-rxjs: "npm:^5.0.3" - eslint-plugin-storybook: "npm:^10.3.3" - eslint-plugin-unicorn: "npm:^56.0.0" - fetch-mock: "npm:11.1.5" - global-jsdom: "npm:^26.0.0" - i18next: "npm:^25.0.0" - i18next-browser-languagedetector: "npm:^8.0.0" - i18next-parser: "npm:^9.1.0" - jsdom: "npm:^26.0.0" - knip: "npm:^5.86.0" - livekit-client: "npm:^2.18.1" - lodash-es: "npm:^4.17.21" - loglevel: "npm:^1.9.1" - matrix-js-sdk: "matrix-org/matrix-js-sdk#6e3efef0c5f660df47cf00874927dec1c75cc3cf" - matrix-widget-api: "npm:^1.16.1" - node-stdlib-browser: "npm:^1.3.1" - normalize.css: "npm:^8.0.1" - observable-hooks: "npm:^4.2.3" - pako: "npm:^2.0.4" - postcss: "npm:^8.4.41" - postcss-preset-env: "npm:^10.0.0" - posthog-js: "npm:1.160.3" - prettier: "npm:^3.0.0" - qrcode: "npm:^1.5.4" - react: "npm:19" - react-dom: "npm:19" - react-i18next: "npm:^16.0.0 <16.7.0" - react-router-dom: "npm:^7.0.0" - react-use-measure: "npm:^2.1.1" - rxjs: "npm:^7.8.1" - sass: "npm:^1.42.1" - storybook: "npm:^10.3.3" - typescript: "npm:^5.8.3" - typescript-eslint-language-service: "npm:^5.0.5" - unique-names-generator: "npm:^4.6.0" - uuid: "npm:^13.0.0" - vaul: "npm:^1.0.0" - vite: "npm:^8.0.0" - vite-plugin-generate-file: "npm:^0.3.0" - vite-plugin-html: "npm:^3.2.2" - vite-plugin-node-stdlib-browser: "npm:^0.2.1" - vite-plugin-svgr: "npm:^4.0.0" - vitest: "npm:^4.0.18" - vitest-axe: "npm:^1.0.0-pre.3" - languageName: unknown - linkType: soft - -"elliptic@npm:^6.5.3, elliptic@npm:^6.6.1": - version: 6.6.1 - resolution: "elliptic@npm:6.6.1" - dependencies: - bn.js: "npm:^4.11.9" - brorand: "npm:^1.1.0" - hash.js: "npm:^1.0.0" - hmac-drbg: "npm:^1.0.1" - inherits: "npm:^2.0.4" - minimalistic-assert: "npm:^1.0.1" - minimalistic-crypto-utils: "npm:^1.0.1" - checksum: 10c0/8b24ef782eec8b472053793ea1e91ae6bee41afffdfcb78a81c0a53b191e715cbe1292aa07165958a9bbe675bd0955142560b1a007ffce7d6c765bcaf951a867 - languageName: node - linkType: hard - -"emoji-regex@npm:^8.0.0": - version: 8.0.0 - resolution: "emoji-regex@npm:8.0.0" - checksum: 10c0/b6053ad39951c4cf338f9092d7bfba448cdfd46fe6a2a034700b149ac9ffbc137e361cbd3c442297f86bed2e5f7576c1b54cc0a6bf8ef5106cc62f496af35010 - languageName: node - linkType: hard - -"emoji-regex@npm:^9.2.2": - version: 9.2.2 - resolution: "emoji-regex@npm:9.2.2" - checksum: 10c0/af014e759a72064cf66e6e694a7fc6b0ed3d8db680427b021a89727689671cefe9d04151b2cad51dbaf85d5ba790d061cd167f1cf32eb7b281f6368b3c181639 - languageName: node - linkType: hard - -"empathic@npm:^2.0.0": - version: 2.0.0 - resolution: "empathic@npm:2.0.0" - checksum: 10c0/7d3b14b04a93b35c47bcc950467ec914fd241cd9acc0269b0ea160f13026ec110f520c90fae64720fde72cc1757b57f3f292fb606617b7fccac1f4d008a76506 - languageName: node - linkType: hard - -"encoding-sniffer@npm:^0.2.0": - version: 0.2.0 - resolution: "encoding-sniffer@npm:0.2.0" - dependencies: - iconv-lite: "npm:^0.6.3" - whatwg-encoding: "npm:^3.1.1" - checksum: 10c0/b312e0d67f339bec44e021e5210ee8ee90d7b8f9975eb2c79a36fd467eb07709e88dcf62ee20f62ee0d74a13874307d99557852a2de9b448f1e3fb991fc68257 - languageName: node - linkType: hard - -"encoding@npm:^0.1.13": - version: 0.1.13 - resolution: "encoding@npm:0.1.13" - dependencies: - iconv-lite: "npm:^0.6.2" - checksum: 10c0/36d938712ff00fe1f4bac88b43bcffb5930c1efa57bbcdca9d67e1d9d6c57cfb1200fb01efe0f3109b2ce99b231f90779532814a81370a1bd3274a0f58585039 - languageName: node - linkType: hard - -"ensure-posix-path@npm:^1.1.0": - version: 1.1.1 - resolution: "ensure-posix-path@npm:1.1.1" - checksum: 10c0/17133fad88bac9b76e5a0690192d5c7bd6f08bdef618e2c1c0c1fcd3b0960f298a4226af5fe6401e729fc09534d0bb68b9e6f388e92d8a140a9d4a61a97e9641 - languageName: node - linkType: hard - -"entities@npm:^2.0.0": - version: 2.2.0 - resolution: "entities@npm:2.2.0" - checksum: 10c0/7fba6af1f116300d2ba1c5673fc218af1961b20908638391b4e1e6d5850314ee2ac3ec22d741b3a8060479911c99305164aed19b6254bde75e7e6b1b2c3f3aa3 - languageName: node - linkType: hard - -"entities@npm:^4.2.0, entities@npm:^4.4.0, entities@npm:^4.5.0": - version: 4.5.0 - resolution: "entities@npm:4.5.0" - checksum: 10c0/5b039739f7621f5d1ad996715e53d964035f75ad3b9a4d38c6b3804bb226e282ffeae2443624d8fdd9c47d8e926ae9ac009c54671243f0c3294c26af7cc85250 - languageName: node - linkType: hard - -"env-paths@npm:^2.2.0": - version: 2.2.1 - resolution: "env-paths@npm:2.2.1" - checksum: 10c0/285325677bf00e30845e330eec32894f5105529db97496ee3f598478e50f008c5352a41a30e5e72ec9de8a542b5a570b85699cd63bd2bc646dbcb9f311d83bc4 - languageName: node - linkType: hard - -"eol@npm:^0.9.1": - version: 0.9.1 - resolution: "eol@npm:0.9.1" - checksum: 10c0/5a6654ca1961529429f4eab4473e6d9351969f25baa30de7232e862c6c5f9037fc0ff044a526fe9cdd6ae65bb1b0db7775bf1d4f342f485c10c34b1444bfb7ab - languageName: node - linkType: hard - -"err-code@npm:^2.0.2": - version: 2.0.3 - resolution: "err-code@npm:2.0.3" - checksum: 10c0/b642f7b4dd4a376e954947550a3065a9ece6733ab8e51ad80db727aaae0817c2e99b02a97a3d6cecc648a97848305e728289cf312d09af395403a90c9d4d8a66 - languageName: node - linkType: hard - -"error-ex@npm:^1.3.1": - version: 1.3.2 - resolution: "error-ex@npm:1.3.2" - dependencies: - is-arrayish: "npm:^0.2.1" - checksum: 10c0/ba827f89369b4c93382cfca5a264d059dfefdaa56ecc5e338ffa58a6471f5ed93b71a20add1d52290a4873d92381174382658c885ac1a2305f7baca363ce9cce - languageName: node - linkType: hard - -"es-abstract@npm:^1.17.5, es-abstract@npm:^1.22.1, es-abstract@npm:^1.23.2, es-abstract@npm:^1.23.3, es-abstract@npm:^1.23.5, es-abstract@npm:^1.23.6, es-abstract@npm:^1.23.9": - version: 1.23.9 - resolution: "es-abstract@npm:1.23.9" - dependencies: - array-buffer-byte-length: "npm:^1.0.2" - arraybuffer.prototype.slice: "npm:^1.0.4" - available-typed-arrays: "npm:^1.0.7" - call-bind: "npm:^1.0.8" - call-bound: "npm:^1.0.3" - data-view-buffer: "npm:^1.0.2" - data-view-byte-length: "npm:^1.0.2" - data-view-byte-offset: "npm:^1.0.1" - es-define-property: "npm:^1.0.1" - es-errors: "npm:^1.3.0" - es-object-atoms: "npm:^1.0.0" - es-set-tostringtag: "npm:^2.1.0" - es-to-primitive: "npm:^1.3.0" - function.prototype.name: "npm:^1.1.8" - get-intrinsic: "npm:^1.2.7" - get-proto: "npm:^1.0.0" - get-symbol-description: "npm:^1.1.0" - globalthis: "npm:^1.0.4" - gopd: "npm:^1.2.0" - has-property-descriptors: "npm:^1.0.2" - has-proto: "npm:^1.2.0" - has-symbols: "npm:^1.1.0" - hasown: "npm:^2.0.2" - internal-slot: "npm:^1.1.0" - is-array-buffer: "npm:^3.0.5" - is-callable: "npm:^1.2.7" - is-data-view: "npm:^1.0.2" - is-regex: "npm:^1.2.1" - is-shared-array-buffer: "npm:^1.0.4" - is-string: "npm:^1.1.1" - is-typed-array: "npm:^1.1.15" - is-weakref: "npm:^1.1.0" - math-intrinsics: "npm:^1.1.0" - object-inspect: "npm:^1.13.3" - object-keys: "npm:^1.1.1" - object.assign: "npm:^4.1.7" - own-keys: "npm:^1.0.1" - regexp.prototype.flags: "npm:^1.5.3" - safe-array-concat: "npm:^1.1.3" - safe-push-apply: "npm:^1.0.0" - safe-regex-test: "npm:^1.1.0" - set-proto: "npm:^1.0.0" - string.prototype.trim: "npm:^1.2.10" - string.prototype.trimend: "npm:^1.0.9" - string.prototype.trimstart: "npm:^1.0.8" - typed-array-buffer: "npm:^1.0.3" - typed-array-byte-length: "npm:^1.0.3" - typed-array-byte-offset: "npm:^1.0.4" - typed-array-length: "npm:^1.0.7" - unbox-primitive: "npm:^1.1.0" - which-typed-array: "npm:^1.1.18" - checksum: 10c0/1de229c9e08fe13c17fe5abaec8221545dfcd57e51f64909599a6ae896df84b8fd2f7d16c60cb00d7bf495b9298ca3581aded19939d4b7276854a4b066f8422b - languageName: node - linkType: hard - -"es-abstract@npm:^1.24.0": - version: 1.24.0 - resolution: "es-abstract@npm:1.24.0" - dependencies: - array-buffer-byte-length: "npm:^1.0.2" - arraybuffer.prototype.slice: "npm:^1.0.4" - available-typed-arrays: "npm:^1.0.7" - call-bind: "npm:^1.0.8" - call-bound: "npm:^1.0.4" - data-view-buffer: "npm:^1.0.2" - data-view-byte-length: "npm:^1.0.2" - data-view-byte-offset: "npm:^1.0.1" - es-define-property: "npm:^1.0.1" - es-errors: "npm:^1.3.0" - es-object-atoms: "npm:^1.1.1" - es-set-tostringtag: "npm:^2.1.0" - es-to-primitive: "npm:^1.3.0" - function.prototype.name: "npm:^1.1.8" - get-intrinsic: "npm:^1.3.0" - get-proto: "npm:^1.0.1" - get-symbol-description: "npm:^1.1.0" - globalthis: "npm:^1.0.4" - gopd: "npm:^1.2.0" - has-property-descriptors: "npm:^1.0.2" - has-proto: "npm:^1.2.0" - has-symbols: "npm:^1.1.0" - hasown: "npm:^2.0.2" - internal-slot: "npm:^1.1.0" - is-array-buffer: "npm:^3.0.5" - is-callable: "npm:^1.2.7" - is-data-view: "npm:^1.0.2" - is-negative-zero: "npm:^2.0.3" - is-regex: "npm:^1.2.1" - is-set: "npm:^2.0.3" - is-shared-array-buffer: "npm:^1.0.4" - is-string: "npm:^1.1.1" - is-typed-array: "npm:^1.1.15" - is-weakref: "npm:^1.1.1" - math-intrinsics: "npm:^1.1.0" - object-inspect: "npm:^1.13.4" - object-keys: "npm:^1.1.1" - object.assign: "npm:^4.1.7" - own-keys: "npm:^1.0.1" - regexp.prototype.flags: "npm:^1.5.4" - safe-array-concat: "npm:^1.1.3" - safe-push-apply: "npm:^1.0.0" - safe-regex-test: "npm:^1.1.0" - set-proto: "npm:^1.0.0" - stop-iteration-iterator: "npm:^1.1.0" - string.prototype.trim: "npm:^1.2.10" - string.prototype.trimend: "npm:^1.0.9" - string.prototype.trimstart: "npm:^1.0.8" - typed-array-buffer: "npm:^1.0.3" - typed-array-byte-length: "npm:^1.0.3" - typed-array-byte-offset: "npm:^1.0.4" - typed-array-length: "npm:^1.0.7" - unbox-primitive: "npm:^1.1.0" - which-typed-array: "npm:^1.1.19" - checksum: 10c0/b256e897be32df5d382786ce8cce29a1dd8c97efbab77a26609bd70f2ed29fbcfc7a31758cb07488d532e7ccccdfca76c1118f2afe5a424cdc05ca007867c318 - languageName: node - linkType: hard - -"es-define-property@npm:^1.0.0, es-define-property@npm:^1.0.1": - version: 1.0.1 - resolution: "es-define-property@npm:1.0.1" - checksum: 10c0/3f54eb49c16c18707949ff25a1456728c883e81259f045003499efba399c08bad00deebf65cccde8c0e07908c1a225c9d472b7107e558f2a48e28d530e34527c - languageName: node - linkType: hard - -"es-errors@npm:^1.3.0": - version: 1.3.0 - resolution: "es-errors@npm:1.3.0" - checksum: 10c0/0a61325670072f98d8ae3b914edab3559b6caa980f08054a3b872052640d91da01d38df55df797fcc916389d77fc92b8d5906cf028f4db46d7e3003abecbca85 - languageName: node - linkType: hard - -"es-iterator-helpers@npm:^1.2.1": - version: 1.2.1 - resolution: "es-iterator-helpers@npm:1.2.1" - dependencies: - call-bind: "npm:^1.0.8" - call-bound: "npm:^1.0.3" - define-properties: "npm:^1.2.1" - es-abstract: "npm:^1.23.6" - es-errors: "npm:^1.3.0" - es-set-tostringtag: "npm:^2.0.3" - function-bind: "npm:^1.1.2" - get-intrinsic: "npm:^1.2.6" - globalthis: "npm:^1.0.4" - gopd: "npm:^1.2.0" - has-property-descriptors: "npm:^1.0.2" - has-proto: "npm:^1.2.0" - has-symbols: "npm:^1.1.0" - internal-slot: "npm:^1.1.0" - iterator.prototype: "npm:^1.1.4" - safe-array-concat: "npm:^1.1.3" - checksum: 10c0/97e3125ca472d82d8aceea11b790397648b52c26d8768ea1c1ee6309ef45a8755bb63225a43f3150c7591cffc17caf5752459f1e70d583b4184370a8f04ebd2f - languageName: node - linkType: hard - -"es-module-lexer@npm:^2.0.0": - version: 2.0.0 - resolution: "es-module-lexer@npm:2.0.0" - checksum: 10c0/ae78dbbd43035a4b972c46cfb6877e374ea290adfc62bc2f5a083fea242c0b2baaab25c5886af86be55f092f4a326741cb94334cd3c478c383fdc8a9ec5ff817 - languageName: node - linkType: hard - -"es-object-atoms@npm:^1.0.0": - version: 1.0.0 - resolution: "es-object-atoms@npm:1.0.0" - dependencies: - es-errors: "npm:^1.3.0" - checksum: 10c0/1fed3d102eb27ab8d983337bb7c8b159dd2a1e63ff833ec54eea1311c96d5b08223b433060ba240541ca8adba9eee6b0a60cdbf2f80634b784febc9cc8b687b4 - languageName: node - linkType: hard - -"es-object-atoms@npm:^1.1.1": - version: 1.1.1 - resolution: "es-object-atoms@npm:1.1.1" - dependencies: - es-errors: "npm:^1.3.0" - checksum: 10c0/65364812ca4daf48eb76e2a3b7a89b3f6a2e62a1c420766ce9f692665a29d94fe41fe88b65f24106f449859549711e4b40d9fb8002d862dfd7eb1c512d10be0c - languageName: node - linkType: hard - -"es-set-tostringtag@npm:^2.0.3, es-set-tostringtag@npm:^2.1.0": - version: 2.1.0 - resolution: "es-set-tostringtag@npm:2.1.0" - dependencies: - es-errors: "npm:^1.3.0" - get-intrinsic: "npm:^1.2.6" - has-tostringtag: "npm:^1.0.2" - hasown: "npm:^2.0.2" - checksum: 10c0/ef2ca9ce49afe3931cb32e35da4dcb6d86ab02592cfc2ce3e49ced199d9d0bb5085fc7e73e06312213765f5efa47cc1df553a6a5154584b21448e9fb8355b1af - languageName: node - linkType: hard - -"es-shim-unscopables@npm:^1.0.0, es-shim-unscopables@npm:^1.0.2": - version: 1.0.2 - resolution: "es-shim-unscopables@npm:1.0.2" - dependencies: - hasown: "npm:^2.0.0" - checksum: 10c0/f495af7b4b7601a4c0cfb893581c352636e5c08654d129590386a33a0432cf13a7bdc7b6493801cadd990d838e2839b9013d1de3b880440cb537825e834fe783 - languageName: node - linkType: hard - -"es-shim-unscopables@npm:^1.1.0": - version: 1.1.0 - resolution: "es-shim-unscopables@npm:1.1.0" - dependencies: - hasown: "npm:^2.0.2" - checksum: 10c0/1b9702c8a1823fc3ef39035a4e958802cf294dd21e917397c561d0b3e195f383b978359816b1732d02b255ccf63e1e4815da0065b95db8d7c992037be3bbbcdb - languageName: node - linkType: hard - -"es-to-primitive@npm:^1.3.0": - version: 1.3.0 - resolution: "es-to-primitive@npm:1.3.0" - dependencies: - is-callable: "npm:^1.2.7" - is-date-object: "npm:^1.0.5" - is-symbol: "npm:^1.0.4" - checksum: 10c0/c7e87467abb0b438639baa8139f701a06537d2b9bc758f23e8622c3b42fd0fdb5bde0f535686119e446dd9d5e4c0f238af4e14960f4771877cf818d023f6730b - languageName: node - linkType: hard - -"esbuild@npm:^0.18.0 || ^0.19.0 || ^0.20.0 || ^0.21.0 || ^0.22.0 || ^0.23.0 || ^0.24.0 || ^0.25.0 || ^0.26.0 || ^0.27.0": - version: 0.27.4 - resolution: "esbuild@npm:0.27.4" - dependencies: - "@esbuild/aix-ppc64": "npm:0.27.4" - "@esbuild/android-arm": "npm:0.27.4" - "@esbuild/android-arm64": "npm:0.27.4" - "@esbuild/android-x64": "npm:0.27.4" - "@esbuild/darwin-arm64": "npm:0.27.4" - "@esbuild/darwin-x64": "npm:0.27.4" - "@esbuild/freebsd-arm64": "npm:0.27.4" - "@esbuild/freebsd-x64": "npm:0.27.4" - "@esbuild/linux-arm": "npm:0.27.4" - "@esbuild/linux-arm64": "npm:0.27.4" - "@esbuild/linux-ia32": "npm:0.27.4" - "@esbuild/linux-loong64": "npm:0.27.4" - "@esbuild/linux-mips64el": "npm:0.27.4" - "@esbuild/linux-ppc64": "npm:0.27.4" - "@esbuild/linux-riscv64": "npm:0.27.4" - "@esbuild/linux-s390x": "npm:0.27.4" - "@esbuild/linux-x64": "npm:0.27.4" - "@esbuild/netbsd-arm64": "npm:0.27.4" - "@esbuild/netbsd-x64": "npm:0.27.4" - "@esbuild/openbsd-arm64": "npm:0.27.4" - "@esbuild/openbsd-x64": "npm:0.27.4" - "@esbuild/openharmony-arm64": "npm:0.27.4" - "@esbuild/sunos-x64": "npm:0.27.4" - "@esbuild/win32-arm64": "npm:0.27.4" - "@esbuild/win32-ia32": "npm:0.27.4" - "@esbuild/win32-x64": "npm:0.27.4" - dependenciesMeta: - "@esbuild/aix-ppc64": - optional: true - "@esbuild/android-arm": - optional: true - "@esbuild/android-arm64": - optional: true - "@esbuild/android-x64": - optional: true - "@esbuild/darwin-arm64": - optional: true - "@esbuild/darwin-x64": - optional: true - "@esbuild/freebsd-arm64": - optional: true - "@esbuild/freebsd-x64": - optional: true - "@esbuild/linux-arm": - optional: true - "@esbuild/linux-arm64": - optional: true - "@esbuild/linux-ia32": - optional: true - "@esbuild/linux-loong64": - optional: true - "@esbuild/linux-mips64el": - optional: true - "@esbuild/linux-ppc64": - optional: true - "@esbuild/linux-riscv64": - optional: true - "@esbuild/linux-s390x": - optional: true - "@esbuild/linux-x64": - optional: true - "@esbuild/netbsd-arm64": - optional: true - "@esbuild/netbsd-x64": - optional: true - "@esbuild/openbsd-arm64": - optional: true - "@esbuild/openbsd-x64": - optional: true - "@esbuild/openharmony-arm64": - optional: true - "@esbuild/sunos-x64": - optional: true - "@esbuild/win32-arm64": - optional: true - "@esbuild/win32-ia32": - optional: true - "@esbuild/win32-x64": - optional: true - bin: - esbuild: bin/esbuild - checksum: 10c0/2a1c2bcccda279f2afd72a7f8259860cb4483b32453d17878e1ecb4ac416b9e7c1001e7aa0a25ba4c29c1e250a3ceaae5d8bb72a119815bc8db4e9b5f5321490 - languageName: node - linkType: hard - -"esbuild@npm:^0.25.0": - version: 0.25.1 - resolution: "esbuild@npm:0.25.1" - dependencies: - "@esbuild/aix-ppc64": "npm:0.25.1" - "@esbuild/android-arm": "npm:0.25.1" - "@esbuild/android-arm64": "npm:0.25.1" - "@esbuild/android-x64": "npm:0.25.1" - "@esbuild/darwin-arm64": "npm:0.25.1" - "@esbuild/darwin-x64": "npm:0.25.1" - "@esbuild/freebsd-arm64": "npm:0.25.1" - "@esbuild/freebsd-x64": "npm:0.25.1" - "@esbuild/linux-arm": "npm:0.25.1" - "@esbuild/linux-arm64": "npm:0.25.1" - "@esbuild/linux-ia32": "npm:0.25.1" - "@esbuild/linux-loong64": "npm:0.25.1" - "@esbuild/linux-mips64el": "npm:0.25.1" - "@esbuild/linux-ppc64": "npm:0.25.1" - "@esbuild/linux-riscv64": "npm:0.25.1" - "@esbuild/linux-s390x": "npm:0.25.1" - "@esbuild/linux-x64": "npm:0.25.1" - "@esbuild/netbsd-arm64": "npm:0.25.1" - "@esbuild/netbsd-x64": "npm:0.25.1" - "@esbuild/openbsd-arm64": "npm:0.25.1" - "@esbuild/openbsd-x64": "npm:0.25.1" - "@esbuild/sunos-x64": "npm:0.25.1" - "@esbuild/win32-arm64": "npm:0.25.1" - "@esbuild/win32-ia32": "npm:0.25.1" - "@esbuild/win32-x64": "npm:0.25.1" - dependenciesMeta: - "@esbuild/aix-ppc64": - optional: true - "@esbuild/android-arm": - optional: true - "@esbuild/android-arm64": - optional: true - "@esbuild/android-x64": - optional: true - "@esbuild/darwin-arm64": - optional: true - "@esbuild/darwin-x64": - optional: true - "@esbuild/freebsd-arm64": - optional: true - "@esbuild/freebsd-x64": - optional: true - "@esbuild/linux-arm": - optional: true - "@esbuild/linux-arm64": - optional: true - "@esbuild/linux-ia32": - optional: true - "@esbuild/linux-loong64": - optional: true - "@esbuild/linux-mips64el": - optional: true - "@esbuild/linux-ppc64": - optional: true - "@esbuild/linux-riscv64": - optional: true - "@esbuild/linux-s390x": - optional: true - "@esbuild/linux-x64": - optional: true - "@esbuild/netbsd-arm64": - optional: true - "@esbuild/netbsd-x64": - optional: true - "@esbuild/openbsd-arm64": - optional: true - "@esbuild/openbsd-x64": - optional: true - "@esbuild/sunos-x64": - optional: true - "@esbuild/win32-arm64": - optional: true - "@esbuild/win32-ia32": - optional: true - "@esbuild/win32-x64": - optional: true - bin: - esbuild: bin/esbuild - checksum: 10c0/80fca30dd0f21aec23fdfab34f0a8d5f55df5097dd7f475f2ab561d45662c32ee306f5649071cd1a0ba0614b164c48ca3dc3ee1551a4daf204b8af90e4d893f5 - languageName: node - linkType: hard - -"escalade@npm:^3.1.1, escalade@npm:^3.2.0": - version: 3.2.0 - resolution: "escalade@npm:3.2.0" - checksum: 10c0/ced4dd3a78e15897ed3be74e635110bbf3b08877b0a41be50dcb325ee0e0b5f65fc2d50e9845194d7c4633f327e2e1c6cce00a71b617c5673df0374201d67f65 - languageName: node - linkType: hard - -"escape-string-regexp@npm:^1.0.5": - version: 1.0.5 - resolution: "escape-string-regexp@npm:1.0.5" - checksum: 10c0/a968ad453dd0c2724e14a4f20e177aaf32bb384ab41b674a8454afe9a41c5e6fe8903323e0a1052f56289d04bd600f81278edf140b0fcc02f5cac98d0f5b5371 - languageName: node - linkType: hard - -"escape-string-regexp@npm:^4.0.0": - version: 4.0.0 - resolution: "escape-string-regexp@npm:4.0.0" - checksum: 10c0/9497d4dd307d845bd7f75180d8188bb17ea8c151c1edbf6b6717c100e104d629dc2dfb687686181b0f4b7d732c7dfdc4d5e7a8ff72de1b0ca283a75bbb3a9cd9 - languageName: node - linkType: hard - -"eslint-config-google@npm:^0.14.0": - version: 0.14.0 - resolution: "eslint-config-google@npm:0.14.0" - peerDependencies: - eslint: ">=5.16.0" - checksum: 10c0/b714c8c45ab1743002f69aa419ad5b39bab00e89484f4e30c33f79f9de031349613f73c9dd4c3a10f40b89a3a43618d4be29df15ab3b96e761f2b705e7293345 - languageName: node - linkType: hard - -"eslint-config-prettier@npm:^10.0.0": - version: 10.1.8 - resolution: "eslint-config-prettier@npm:10.1.8" - peerDependencies: - eslint: ">=7.0.0" - bin: - eslint-config-prettier: bin/cli.js - checksum: 10c0/e1bcfadc9eccd526c240056b1e59c5cd26544fe59feb85f38f4f1f116caed96aea0b3b87868e68b3099e55caaac3f2e5b9f58110f85db893e83a332751192682 - languageName: node - linkType: hard - -"eslint-etc@npm:^5.1.0": - version: 5.2.1 - resolution: "eslint-etc@npm:5.2.1" - dependencies: - "@typescript-eslint/experimental-utils": "npm:^5.0.0" - tsutils: "npm:^3.17.1" - tsutils-etc: "npm:^1.4.1" - peerDependencies: - eslint: ^8.0.0 - typescript: ">=4.0.0" - checksum: 10c0/628f9d65e16f7c7d06c663256d39f5e72f508a515d2712b0bcb329dbb9e7a1a4f175292c3477c83be9cc8a75deea5f050a00c3dc9b084af6b651d46ee8360a9e - languageName: node - linkType: hard - -"eslint-import-resolver-node@npm:^0.3.9": - version: 0.3.9 - resolution: "eslint-import-resolver-node@npm:0.3.9" - dependencies: - debug: "npm:^3.2.7" - is-core-module: "npm:^2.13.0" - resolve: "npm:^1.22.4" - checksum: 10c0/0ea8a24a72328a51fd95aa8f660dcca74c1429806737cf10261ab90cfcaaf62fd1eff664b76a44270868e0a932711a81b250053942595bcd00a93b1c1575dd61 - languageName: node - linkType: hard - -"eslint-module-utils@npm:^2.12.1": - version: 2.12.1 - resolution: "eslint-module-utils@npm:2.12.1" - dependencies: - debug: "npm:^3.2.7" - peerDependenciesMeta: - eslint: - optional: true - checksum: 10c0/6f4efbe7a91ae49bf67b4ab3644cb60bc5bd7db4cb5521de1b65be0847ffd3fb6bce0dd68f0995e1b312d137f768e2a1f842ee26fe73621afa05f850628fdc40 - languageName: node - linkType: hard - -"eslint-plugin-deprecate@npm:^0.9.0": - version: 0.9.0 - resolution: "eslint-plugin-deprecate@npm:0.9.0" - peerDependencies: - eslint: ^8.0.0 || ^9.0.0 - checksum: 10c0/a1be5d100b48220bbe8692fca3671db7218cb86b636f7403542f524e1a075bc1ed2c42b15b2fd0bb096b07180c08e5d8e5467ef6e19676edadde36b0c35785d0 - languageName: node - linkType: hard - -"eslint-plugin-import@npm:^2.26.0": - version: 2.32.0 - resolution: "eslint-plugin-import@npm:2.32.0" - dependencies: - "@rtsao/scc": "npm:^1.1.0" - array-includes: "npm:^3.1.9" - array.prototype.findlastindex: "npm:^1.2.6" - array.prototype.flat: "npm:^1.3.3" - array.prototype.flatmap: "npm:^1.3.3" - debug: "npm:^3.2.7" - doctrine: "npm:^2.1.0" - eslint-import-resolver-node: "npm:^0.3.9" - eslint-module-utils: "npm:^2.12.1" - hasown: "npm:^2.0.2" - is-core-module: "npm:^2.16.1" - is-glob: "npm:^4.0.3" - minimatch: "npm:^3.1.2" - object.fromentries: "npm:^2.0.8" - object.groupby: "npm:^1.0.3" - object.values: "npm:^1.2.1" - semver: "npm:^6.3.1" - string.prototype.trimend: "npm:^1.0.9" - tsconfig-paths: "npm:^3.15.0" - peerDependencies: - eslint: ^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8 || ^9 - checksum: 10c0/bfb1b8fc8800398e62ddfefbf3638d185286edfed26dfe00875cc2846d954491b4f5112457831588b757fa789384e1ae585f812614c4797f0499fa234fd4a48b - languageName: node - linkType: hard - -"eslint-plugin-jsdoc@npm:^61.5.0": - version: 61.7.1 - resolution: "eslint-plugin-jsdoc@npm:61.7.1" - dependencies: - "@es-joy/jsdoccomment": "npm:~0.78.0" - "@es-joy/resolve.exports": "npm:1.2.0" - are-docs-informative: "npm:^0.0.2" - comment-parser: "npm:1.4.1" - debug: "npm:^4.4.3" - escape-string-regexp: "npm:^4.0.0" - espree: "npm:^11.0.0" - esquery: "npm:^1.7.0" - html-entities: "npm:^2.6.0" - object-deep-merge: "npm:^2.0.0" - parse-imports-exports: "npm:^0.2.4" - semver: "npm:^7.7.3" - spdx-expression-parse: "npm:^4.0.0" - to-valid-identifier: "npm:^1.0.0" - peerDependencies: - eslint: ^7.0.0 || ^8.0.0 || ^9.0.0 - checksum: 10c0/d0904b923f68a4e9e6da156316a4e2a972445bf79118bde9618ad80b4ef5927fc2c9dd597b22b776742ef548d65914e75fca190ab3be942385f268a3b83c1087 - languageName: node - linkType: hard - -"eslint-plugin-jsx-a11y@npm:^6.5.1": - version: 6.10.2 - resolution: "eslint-plugin-jsx-a11y@npm:6.10.2" - dependencies: - aria-query: "npm:^5.3.2" - array-includes: "npm:^3.1.8" - array.prototype.flatmap: "npm:^1.3.2" - ast-types-flow: "npm:^0.0.8" - axe-core: "npm:^4.10.0" - axobject-query: "npm:^4.1.0" - damerau-levenshtein: "npm:^1.0.8" - emoji-regex: "npm:^9.2.2" - hasown: "npm:^2.0.2" - jsx-ast-utils: "npm:^3.3.5" - language-tags: "npm:^1.0.9" - minimatch: "npm:^3.1.2" - object.fromentries: "npm:^2.0.8" - safe-regex-test: "npm:^1.0.3" - string.prototype.includes: "npm:^2.0.1" - peerDependencies: - eslint: ^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9 - checksum: 10c0/d93354e03b0cf66f018d5c50964e074dffe4ddf1f9b535fa020d19c4ae45f89c1a16e9391ca61ac3b19f7042c751ac0d361a056a65cbd1de24718a53ff8daa6e - languageName: node - linkType: hard - -"eslint-plugin-matrix-org@npm:2.1.0": - version: 2.1.0 - resolution: "eslint-plugin-matrix-org@npm:2.1.0" - peerDependencies: - "@babel/core": "*" - "@babel/eslint-parser": "*" - "@babel/eslint-plugin": "*" - "@stylistic/eslint-plugin": "*" - "@typescript-eslint/eslint-plugin": "*" - "@typescript-eslint/parser": "*" - eslint: "*" - eslint-config-google: "*" - eslint-config-prettier: "*" - eslint-plugin-deprecate: "*" - eslint-plugin-import: "*" - eslint-plugin-jest: "*" - eslint-plugin-jsx-a11y: "*" - eslint-plugin-react: "*" - eslint-plugin-react-hooks: "*" - eslint-plugin-unicorn: "*" - prettier: "*" - typescript: "*" - checksum: 10c0/ca3c727a12829bd58455ab32894118625fd0d208314aebc95b319aef9fa2881e53178853132327664fa1e62e0f9a0946295e195d21c3fa5235a240852f2a070a - languageName: node - linkType: hard - -"eslint-plugin-react-hooks@npm:^5.0.0": - version: 5.2.0 - resolution: "eslint-plugin-react-hooks@npm:5.2.0" - peerDependencies: - eslint: ^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0 || ^9.0.0 - checksum: 10c0/1c8d50fa5984c6dea32470651807d2922cc3934cf3425e78f84a24c2dfd972e7f019bee84aefb27e0cf2c13fea0ac1d4473267727408feeb1c56333ca1489385 - languageName: node - linkType: hard - -"eslint-plugin-react@npm:^7.29.4": - version: 7.37.5 - resolution: "eslint-plugin-react@npm:7.37.5" - dependencies: - array-includes: "npm:^3.1.8" - array.prototype.findlast: "npm:^1.2.5" - array.prototype.flatmap: "npm:^1.3.3" - array.prototype.tosorted: "npm:^1.1.4" - doctrine: "npm:^2.1.0" - es-iterator-helpers: "npm:^1.2.1" - estraverse: "npm:^5.3.0" - hasown: "npm:^2.0.2" - jsx-ast-utils: "npm:^2.4.1 || ^3.0.0" - minimatch: "npm:^3.1.2" - object.entries: "npm:^1.1.9" - object.fromentries: "npm:^2.0.8" - object.values: "npm:^1.2.1" - prop-types: "npm:^15.8.1" - resolve: "npm:^2.0.0-next.5" - semver: "npm:^6.3.1" - string.prototype.matchall: "npm:^4.0.12" - string.prototype.repeat: "npm:^1.0.0" - peerDependencies: - eslint: ^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9.7 - checksum: 10c0/c850bfd556291d4d9234f5ca38db1436924a1013627c8ab1853f77cac73ec19b020e861e6c7b783436a48b6ffcdfba4547598235a37ad4611b6739f65fd8ad57 - languageName: node - linkType: hard - -"eslint-plugin-rxjs@npm:^5.0.3": - version: 5.0.3 - resolution: "eslint-plugin-rxjs@npm:5.0.3" - dependencies: - "@typescript-eslint/experimental-utils": "npm:^5.0.0" - common-tags: "npm:^1.8.0" - decamelize: "npm:^5.0.0" - eslint-etc: "npm:^5.1.0" - requireindex: "npm:~1.2.0" - rxjs-report-usage: "npm:^1.0.4" - tslib: "npm:^2.0.0" - tsutils: "npm:^3.0.0" - tsutils-etc: "npm:^1.4.1" - peerDependencies: - eslint: ^8.0.0 - typescript: ">=4.0.0" - checksum: 10c0/bba2048a6772ec017e63c9201642c90043365308f2d386b448a28b91f7195a7f65ebb39705bb886f89bcc4fe1ffbd18bd2b25bf8f389bc5cae592828dbfe9d58 - languageName: node - linkType: hard - -"eslint-plugin-storybook@npm:^10.3.3": - version: 10.3.3 - resolution: "eslint-plugin-storybook@npm:10.3.3" - dependencies: - "@typescript-eslint/utils": "npm:^8.48.0" - peerDependencies: - eslint: ">=8" - storybook: ^10.3.3 - checksum: 10c0/501a07db230aefa5bb76882fe7b0a3e9a5db87fc29bbcc96b25e880a2ee97a81ff871cf364cb09e9ed9b67bc7d6cd0541755fd0ac778d3b68124289a4fdecde4 - languageName: node - linkType: hard - -"eslint-plugin-unicorn@npm:^56.0.0": - version: 56.0.1 - resolution: "eslint-plugin-unicorn@npm:56.0.1" - dependencies: - "@babel/helper-validator-identifier": "npm:^7.24.7" - "@eslint-community/eslint-utils": "npm:^4.4.0" - ci-info: "npm:^4.0.0" - clean-regexp: "npm:^1.0.0" - core-js-compat: "npm:^3.38.1" - esquery: "npm:^1.6.0" - globals: "npm:^15.9.0" - indent-string: "npm:^4.0.0" - is-builtin-module: "npm:^3.2.1" - jsesc: "npm:^3.0.2" - pluralize: "npm:^8.0.0" - read-pkg-up: "npm:^7.0.1" - regexp-tree: "npm:^0.1.27" - regjsparser: "npm:^0.10.0" - semver: "npm:^7.6.3" - strip-indent: "npm:^3.0.0" - peerDependencies: - eslint: ">=8.56.0" - checksum: 10c0/3b853ecde6ab597b12e28b962ba6ad7d3594f7f066d90135db2d3366ac13361c72500119163e13e1c38ca6fbdd331b1cc31dce9e8673880bff050fe51d6c64db - languageName: node - linkType: hard - -"eslint-scope@npm:^5.1.1": - version: 5.1.1 - resolution: "eslint-scope@npm:5.1.1" - dependencies: - esrecurse: "npm:^4.3.0" - estraverse: "npm:^4.1.1" - checksum: 10c0/d30ef9dc1c1cbdece34db1539a4933fe3f9b14e1ffb27ecc85987902ee663ad7c9473bbd49a9a03195a373741e62e2f807c4938992e019b511993d163450e70a - languageName: node - linkType: hard - -"eslint-scope@npm:^7.2.2": - version: 7.2.2 - resolution: "eslint-scope@npm:7.2.2" - dependencies: - esrecurse: "npm:^4.3.0" - estraverse: "npm:^5.2.0" - checksum: 10c0/613c267aea34b5a6d6c00514e8545ef1f1433108097e857225fed40d397dd6b1809dffd11c2fde23b37ca53d7bf935fe04d2a18e6fc932b31837b6ad67e1c116 - languageName: node - linkType: hard - -"eslint-visitor-keys@npm:^3.3.0, eslint-visitor-keys@npm:^3.4.1, eslint-visitor-keys@npm:^3.4.3": - version: 3.4.3 - resolution: "eslint-visitor-keys@npm:3.4.3" - checksum: 10c0/92708e882c0a5ffd88c23c0b404ac1628cf20104a108c745f240a13c332a11aac54f49a22d5762efbffc18ecbc9a580d1b7ad034bf5f3cc3307e5cbff2ec9820 - languageName: node - linkType: hard - -"eslint-visitor-keys@npm:^4.2.0": - version: 4.2.0 - resolution: "eslint-visitor-keys@npm:4.2.0" - checksum: 10c0/2ed81c663b147ca6f578312919483eb040295bbab759e5a371953456c636c5b49a559883e2677112453728d66293c0a4c90ab11cab3428cf02a0236d2e738269 - languageName: node - linkType: hard - -"eslint-visitor-keys@npm:^5.0.0, eslint-visitor-keys@npm:^5.0.1": - version: 5.0.1 - resolution: "eslint-visitor-keys@npm:5.0.1" - checksum: 10c0/16190bdf2cbae40a1109384c94450c526a79b0b9c3cb21e544256ed85ac48a4b84db66b74a6561d20fe6ab77447f150d711c2ad5ad74df4fcc133736bce99678 - languageName: node - linkType: hard - -"eslint@npm:^8.14.0": - version: 8.57.1 - resolution: "eslint@npm:8.57.1" - dependencies: - "@eslint-community/eslint-utils": "npm:^4.2.0" - "@eslint-community/regexpp": "npm:^4.6.1" - "@eslint/eslintrc": "npm:^2.1.4" - "@eslint/js": "npm:8.57.1" - "@humanwhocodes/config-array": "npm:^0.13.0" - "@humanwhocodes/module-importer": "npm:^1.0.1" - "@nodelib/fs.walk": "npm:^1.2.8" - "@ungap/structured-clone": "npm:^1.2.0" - ajv: "npm:^6.12.4" - chalk: "npm:^4.0.0" - cross-spawn: "npm:^7.0.2" - debug: "npm:^4.3.2" - doctrine: "npm:^3.0.0" - escape-string-regexp: "npm:^4.0.0" - eslint-scope: "npm:^7.2.2" - eslint-visitor-keys: "npm:^3.4.3" - espree: "npm:^9.6.1" - esquery: "npm:^1.4.2" - esutils: "npm:^2.0.2" - fast-deep-equal: "npm:^3.1.3" - file-entry-cache: "npm:^6.0.1" - find-up: "npm:^5.0.0" - glob-parent: "npm:^6.0.2" - globals: "npm:^13.19.0" - graphemer: "npm:^1.4.0" - ignore: "npm:^5.2.0" - imurmurhash: "npm:^0.1.4" - is-glob: "npm:^4.0.0" - is-path-inside: "npm:^3.0.3" - js-yaml: "npm:^4.1.0" - json-stable-stringify-without-jsonify: "npm:^1.0.1" - levn: "npm:^0.4.1" - lodash.merge: "npm:^4.6.2" - minimatch: "npm:^3.1.2" - natural-compare: "npm:^1.4.0" - optionator: "npm:^0.9.3" - strip-ansi: "npm:^6.0.1" - text-table: "npm:^0.2.0" - bin: - eslint: bin/eslint.js - checksum: 10c0/1fd31533086c1b72f86770a4d9d7058ee8b4643fd1cfd10c7aac1ecb8725698e88352a87805cf4b2ce890aa35947df4b4da9655fb7fdfa60dbb448a43f6ebcf1 - languageName: node - linkType: hard - -"espree@npm:^10.3.0": - version: 10.3.0 - resolution: "espree@npm:10.3.0" - dependencies: - acorn: "npm:^8.14.0" - acorn-jsx: "npm:^5.3.2" - eslint-visitor-keys: "npm:^4.2.0" - checksum: 10c0/272beeaca70d0a1a047d61baff64db04664a33d7cfb5d144f84bc8a5c6194c6c8ebe9cc594093ca53add88baa23e59b01e69e8a0160ab32eac570482e165c462 - languageName: node - linkType: hard - -"espree@npm:^11.0.0": - version: 11.1.1 - resolution: "espree@npm:11.1.1" - dependencies: - acorn: "npm:^8.16.0" - acorn-jsx: "npm:^5.3.2" - eslint-visitor-keys: "npm:^5.0.1" - checksum: 10c0/2feae74efdfb037b9e9fcb30506799845cf20900de5e441ed03e5c51aaa249f85ea5818ff177682acc0c9bfb4ac97e1965c238ee44ac7c305aab8747177bab69 - languageName: node - linkType: hard - -"espree@npm:^9.6.0, espree@npm:^9.6.1": - version: 9.6.1 - resolution: "espree@npm:9.6.1" - dependencies: - acorn: "npm:^8.9.0" - acorn-jsx: "npm:^5.3.2" - eslint-visitor-keys: "npm:^3.4.1" - checksum: 10c0/1a2e9b4699b715347f62330bcc76aee224390c28bb02b31a3752e9d07549c473f5f986720483c6469cf3cfb3c9d05df612ffc69eb1ee94b54b739e67de9bb460 - languageName: node - linkType: hard - -"esprima@npm:~4.0.0": - version: 4.0.1 - resolution: "esprima@npm:4.0.1" - bin: - esparse: ./bin/esparse.js - esvalidate: ./bin/esvalidate.js - checksum: 10c0/ad4bab9ead0808cf56501750fd9d3fb276f6b105f987707d059005d57e182d18a7c9ec7f3a01794ebddcca676773e42ca48a32d67a250c9d35e009ca613caba3 - languageName: node - linkType: hard - -"esquery@npm:^1.4.2, esquery@npm:^1.7.0": - version: 1.7.0 - resolution: "esquery@npm:1.7.0" - dependencies: - estraverse: "npm:^5.1.0" - checksum: 10c0/77d5173db450b66f3bc685d11af4c90cffeedb340f34a39af96d43509a335ce39c894fd79233df32d38f5e4e219fa0f7076f6ec90bae8320170ba082c0db4793 - languageName: node - linkType: hard - -"esquery@npm:^1.6.0": - version: 1.6.0 - resolution: "esquery@npm:1.6.0" - dependencies: - estraverse: "npm:^5.1.0" - checksum: 10c0/cb9065ec605f9da7a76ca6dadb0619dfb611e37a81e318732977d90fab50a256b95fee2d925fba7c2f3f0523aa16f91587246693bc09bc34d5a59575fe6e93d2 - languageName: node - linkType: hard - -"esrecurse@npm:^4.3.0": - version: 4.3.0 - resolution: "esrecurse@npm:4.3.0" - dependencies: - estraverse: "npm:^5.2.0" - checksum: 10c0/81a37116d1408ded88ada45b9fb16dbd26fba3aadc369ce50fcaf82a0bac12772ebd7b24cd7b91fc66786bf2c1ac7b5f196bc990a473efff972f5cb338877cf5 - languageName: node - linkType: hard - -"estraverse@npm:^4.1.1": - version: 4.3.0 - resolution: "estraverse@npm:4.3.0" - checksum: 10c0/9cb46463ef8a8a4905d3708a652d60122a0c20bb58dec7e0e12ab0e7235123d74214fc0141d743c381813e1b992767e2708194f6f6e0f9fd00c1b4e0887b8b6d - languageName: node - linkType: hard - -"estraverse@npm:^5.1.0, estraverse@npm:^5.2.0, estraverse@npm:^5.3.0": - version: 5.3.0 - resolution: "estraverse@npm:5.3.0" - checksum: 10c0/1ff9447b96263dec95d6d67431c5e0771eb9776427421260a3e2f0fdd5d6bd4f8e37a7338f5ad2880c9f143450c9b1e4fc2069060724570a49cf9cf0312bd107 - languageName: node - linkType: hard - -"estree-walker@npm:^2.0.1, estree-walker@npm:^2.0.2": - version: 2.0.2 - resolution: "estree-walker@npm:2.0.2" - checksum: 10c0/53a6c54e2019b8c914dc395890153ffdc2322781acf4bd7d1a32d7aedc1710807bdcd866ac133903d5629ec601fbb50abe8c2e5553c7f5a0afdd9b6af6c945af - languageName: node - linkType: hard - -"estree-walker@npm:^3.0.3": - version: 3.0.3 - resolution: "estree-walker@npm:3.0.3" - dependencies: - "@types/estree": "npm:^1.0.0" - checksum: 10c0/c12e3c2b2642d2bcae7d5aa495c60fa2f299160946535763969a1c83fc74518ffa9c2cd3a8b69ac56aea547df6a8aac25f729a342992ef0bbac5f1c73e78995d - languageName: node - linkType: hard - -"esutils@npm:^2.0.2": - version: 2.0.3 - resolution: "esutils@npm:2.0.3" - checksum: 10c0/9a2fe69a41bfdade834ba7c42de4723c97ec776e40656919c62cbd13607c45e127a003f05f724a1ea55e5029a4cf2de444b13009f2af71271e42d93a637137c7 - languageName: node - linkType: hard - -"events@npm:^3.0.0, events@npm:^3.2.0, events@npm:^3.3.0": - version: 3.3.0 - resolution: "events@npm:3.3.0" - checksum: 10c0/d6b6f2adbccbcda74ddbab52ed07db727ef52e31a61ed26db9feb7dc62af7fc8e060defa65e5f8af9449b86b52cc1a1f6a79f2eafcf4e62add2b7a1fa4a432f6 - languageName: node - linkType: hard - -"evp_bytestokey@npm:^1.0.0, evp_bytestokey@npm:^1.0.3": - version: 1.0.3 - resolution: "evp_bytestokey@npm:1.0.3" - dependencies: - md5.js: "npm:^1.3.4" - node-gyp: "npm:latest" - safe-buffer: "npm:^5.1.1" - checksum: 10c0/77fbe2d94a902a80e9b8f5a73dcd695d9c14899c5e82967a61b1fc6cbbb28c46552d9b127cff47c45fcf684748bdbcfa0a50410349109de87ceb4b199ef6ee99 - languageName: node - linkType: hard - -"expect-type@npm:^1.3.0": - version: 1.3.0 - resolution: "expect-type@npm:1.3.0" - checksum: 10c0/8412b3fe4f392c420ab41dae220b09700e4e47c639a29ba7ba2e83cc6cffd2b4926f7ac9e47d7e277e8f4f02acda76fd6931cb81fd2b382fa9477ef9ada953fd - languageName: node - linkType: hard - -"exponential-backoff@npm:^3.1.1": - version: 3.1.2 - resolution: "exponential-backoff@npm:3.1.2" - checksum: 10c0/d9d3e1eafa21b78464297df91f1776f7fbaa3d5e3f7f0995648ca5b89c069d17055033817348d9f4a43d1c20b0eab84f75af6991751e839df53e4dfd6f22e844 - languageName: node - linkType: hard - -"fast-deep-equal@npm:^3.1.1, fast-deep-equal@npm:^3.1.3": - version: 3.1.3 - resolution: "fast-deep-equal@npm:3.1.3" - checksum: 10c0/40dedc862eb8992c54579c66d914635afbec43350afbbe991235fdcb4e3a8d5af1b23ae7e79bef7d4882d0ecee06c3197488026998fb19f72dc95acff1d1b1d0 - languageName: node - linkType: hard - -"fast-fifo@npm:^1.3.2": - version: 1.3.2 - resolution: "fast-fifo@npm:1.3.2" - checksum: 10c0/d53f6f786875e8b0529f784b59b4b05d4b5c31c651710496440006a398389a579c8dbcd2081311478b5bf77f4b0b21de69109c5a4eabea9d8e8783d1eb864e4c - languageName: node - linkType: hard - -"fast-glob@npm:^3.2.11, fast-glob@npm:^3.3.2, fast-glob@npm:^3.3.3": - version: 3.3.3 - resolution: "fast-glob@npm:3.3.3" - dependencies: - "@nodelib/fs.stat": "npm:^2.0.2" - "@nodelib/fs.walk": "npm:^1.2.3" - glob-parent: "npm:^5.1.2" - merge2: "npm:^1.3.0" - micromatch: "npm:^4.0.8" - checksum: 10c0/f6aaa141d0d3384cf73cbcdfc52f475ed293f6d5b65bfc5def368b09163a9f7e5ec2b3014d80f733c405f58e470ee0cc451c2937685045cddcdeaa24199c43fe - languageName: node - linkType: hard - -"fast-glob@npm:^3.2.9": - version: 3.3.2 - resolution: "fast-glob@npm:3.3.2" - dependencies: - "@nodelib/fs.stat": "npm:^2.0.2" - "@nodelib/fs.walk": "npm:^1.2.3" - glob-parent: "npm:^5.1.2" - merge2: "npm:^1.3.0" - micromatch: "npm:^4.0.4" - checksum: 10c0/42baad7b9cd40b63e42039132bde27ca2cb3a4950d0a0f9abe4639ea1aa9d3e3b40f98b1fe31cbc0cc17b664c9ea7447d911a152fa34ec5b72977b125a6fc845 - languageName: node - linkType: hard - -"fast-json-stable-stringify@npm:^2.0.0": - version: 2.1.0 - resolution: "fast-json-stable-stringify@npm:2.1.0" - checksum: 10c0/7f081eb0b8a64e0057b3bb03f974b3ef00135fbf36c1c710895cd9300f13c94ba809bb3a81cf4e1b03f6e5285610a61abbd7602d0652de423144dfee5a389c9b - languageName: node - linkType: hard - -"fast-levenshtein@npm:^2.0.6": - version: 2.0.6 - resolution: "fast-levenshtein@npm:2.0.6" - checksum: 10c0/111972b37338bcb88f7d9e2c5907862c280ebf4234433b95bc611e518d192ccb2d38119c4ac86e26b668d75f7f3894f4ff5c4982899afced7ca78633b08287c4 - languageName: node - linkType: hard - -"fastq@npm:^1.13.0, fastq@npm:^1.6.0": - version: 1.19.1 - resolution: "fastq@npm:1.19.1" - dependencies: - reusify: "npm:^1.0.4" - checksum: 10c0/ebc6e50ac7048daaeb8e64522a1ea7a26e92b3cee5cd1c7f2316cdca81ba543aa40a136b53891446ea5c3a67ec215fbaca87ad405f102dd97012f62916905630 - languageName: node - linkType: hard - -"fd-package-json@npm:^2.0.0": - version: 2.0.0 - resolution: "fd-package-json@npm:2.0.0" - dependencies: - walk-up-path: "npm:^4.0.0" - checksum: 10c0/a0a48745257bc09c939486608dad9f2ced238f0c64266222cc881618ed4c8f6aa0ccfe45a1e6d4f9ce828509e8d617cec60e2a114851bebb1ff4886dc5ed5112 - languageName: node - linkType: hard - -"fdir@npm:^6.5.0": - version: 6.5.0 - resolution: "fdir@npm:6.5.0" - peerDependencies: - picomatch: ^3 || ^4 - peerDependenciesMeta: - picomatch: - optional: true - checksum: 10c0/e345083c4306b3aed6cb8ec551e26c36bab5c511e99ea4576a16750ddc8d3240e63826cc624f5ae17ad4dc82e68a253213b60d556c11bfad064b7607847ed07f - languageName: node - linkType: hard - -"fetch-mock@npm:11.1.5": - version: 11.1.5 - resolution: "fetch-mock@npm:11.1.5" - dependencies: - "@types/glob-to-regexp": "npm:^0.4.4" - dequal: "npm:^2.0.3" - glob-to-regexp: "npm:^0.4.1" - is-subset: "npm:^0.1.1" - regexparam: "npm:^3.0.0" - peerDependenciesMeta: - node-fetch: - optional: true - checksum: 10c0/f32f1d7879b654a3fab7c3576901193ddd4c63cb9aeae2ed66ff42062400c0937d4696b1a5171e739d5f62470e6554e190f14816789f5e3b2bf1ad90208222e6 - languageName: node - linkType: hard - -"fflate@npm:^0.4.8": - version: 0.4.8 - resolution: "fflate@npm:0.4.8" - checksum: 10c0/29d1eddaaa5deab61b1c6b0d21282adacadbc4d2c01e94d8b1ee784398151673b9c563e53f97a801bc410a1ae55e8de5378114a743430e643e7a0644ba8e5a42 - languageName: node - linkType: hard - -"file-entry-cache@npm:^6.0.1": - version: 6.0.1 - resolution: "file-entry-cache@npm:6.0.1" - dependencies: - flat-cache: "npm:^3.0.4" - checksum: 10c0/58473e8a82794d01b38e5e435f6feaf648e3f36fdb3a56e98f417f4efae71ad1c0d4ebd8a9a7c50c3ad085820a93fc7494ad721e0e4ebc1da3573f4e1c3c7cdd - languageName: node - linkType: hard - -"filelist@npm:^1.0.4": - version: 1.0.4 - resolution: "filelist@npm:1.0.4" - dependencies: - minimatch: "npm:^5.0.1" - checksum: 10c0/426b1de3944a3d153b053f1c0ebfd02dccd0308a4f9e832ad220707a6d1f1b3c9784d6cadf6b2f68f09a57565f63ebc7bcdc913ccf8012d834f472c46e596f41 - languageName: node - linkType: hard - -"fill-range@npm:^7.1.1": - version: 7.1.1 - resolution: "fill-range@npm:7.1.1" - dependencies: - to-regex-range: "npm:^5.0.1" - checksum: 10c0/b75b691bbe065472f38824f694c2f7449d7f5004aa950426a2c28f0306c60db9b880c0b0e4ed819997ffb882d1da02cfcfc819bddc94d71627f5269682edf018 - languageName: node - linkType: hard - -"find-up@npm:^4.1.0": - version: 4.1.0 - resolution: "find-up@npm:4.1.0" - dependencies: - locate-path: "npm:^5.0.0" - path-exists: "npm:^4.0.0" - checksum: 10c0/0406ee89ebeefa2d507feb07ec366bebd8a6167ae74aa4e34fb4c4abd06cf782a3ce26ae4194d70706f72182841733f00551c209fe575cb00bd92104056e78c1 - languageName: node - linkType: hard - -"find-up@npm:^5.0.0": - version: 5.0.0 - resolution: "find-up@npm:5.0.0" - dependencies: - locate-path: "npm:^6.0.0" - path-exists: "npm:^4.0.0" - checksum: 10c0/062c5a83a9c02f53cdd6d175a37ecf8f87ea5bbff1fdfb828f04bfa021441bc7583e8ebc0872a4c1baab96221fb8a8a275a19809fb93fbc40bd69ec35634069a - languageName: node - linkType: hard - -"flat-cache@npm:^3.0.4": - version: 3.2.0 - resolution: "flat-cache@npm:3.2.0" - dependencies: - flatted: "npm:^3.2.9" - keyv: "npm:^4.5.3" - rimraf: "npm:^3.0.2" - checksum: 10c0/b76f611bd5f5d68f7ae632e3ae503e678d205cf97a17c6ab5b12f6ca61188b5f1f7464503efae6dc18683ed8f0b41460beb48ac4b9ac63fe6201296a91ba2f75 - languageName: node - linkType: hard - -"flatted@npm:^3.2.9": - version: 3.3.1 - resolution: "flatted@npm:3.3.1" - checksum: 10c0/324166b125ee07d4ca9bcf3a5f98d915d5db4f39d711fba640a3178b959919aae1f7cfd8aabcfef5826ed8aa8a2aa14cc85b2d7d18ff638ddf4ae3df39573eaf - languageName: node - linkType: hard - -"for-each@npm:^0.3.3": - version: 0.3.3 - resolution: "for-each@npm:0.3.3" - dependencies: - is-callable: "npm:^1.1.3" - checksum: 10c0/22330d8a2db728dbf003ec9182c2d421fbcd2969b02b4f97ec288721cda63eb28f2c08585ddccd0f77cb2930af8d958005c9e72f47141dc51816127a118f39aa - languageName: node - linkType: hard - -"for-each@npm:^0.3.5": - version: 0.3.5 - resolution: "for-each@npm:0.3.5" - dependencies: - is-callable: "npm:^1.2.7" - checksum: 10c0/0e0b50f6a843a282637d43674d1fb278dda1dd85f4f99b640024cfb10b85058aac0cc781bf689d5fe50b4b7f638e91e548560723a4e76e04fe96ae35ef039cee - languageName: node - linkType: hard - -"foreground-child@npm:^3.1.0": - version: 3.3.1 - resolution: "foreground-child@npm:3.3.1" - dependencies: - cross-spawn: "npm:^7.0.6" - signal-exit: "npm:^4.0.1" - checksum: 10c0/8986e4af2430896e65bc2788d6679067294d6aee9545daefc84923a0a4b399ad9c7a3ea7bd8c0b2b80fdf4a92de4c69df3f628233ff3224260e9c1541a9e9ed3 - languageName: node - linkType: hard - -"formatly@npm:^0.3.0": - version: 0.3.0 - resolution: "formatly@npm:0.3.0" - dependencies: - fd-package-json: "npm:^2.0.0" - bin: - formatly: bin/index.mjs - checksum: 10c0/ef9dbd3cdaee649e9604ea060d8d62d8131eb81117634336592ee2193fc7c98a3f1f1b5d09a045dbd36287ba88edf868ef179d39fbda2f34fbe2be70c42dd014 - languageName: node - linkType: hard - -"fraction.js@npm:^5.3.4": - version: 5.3.4 - resolution: "fraction.js@npm:5.3.4" - checksum: 10c0/f90079fe9bfc665e0a07079938e8ff71115bce9462f17b32fc283f163b0540ec34dc33df8ed41bb56f028316b04361b9a9995b9ee9258617f8338e0b05c5f95a - languageName: node - linkType: hard - -"fs-extra@npm:^10.0.1": - version: 10.1.0 - resolution: "fs-extra@npm:10.1.0" - dependencies: - graceful-fs: "npm:^4.2.0" - jsonfile: "npm:^6.0.1" - universalify: "npm:^2.0.0" - checksum: 10c0/5f579466e7109719d162a9249abbeffe7f426eb133ea486e020b89bc6d67a741134076bf439983f2eb79276ceaf6bd7b7c1e43c3fd67fe889863e69072fb0a5e - languageName: node - linkType: hard - -"fs-extra@npm:^11.2.0": - version: 11.3.0 - resolution: "fs-extra@npm:11.3.0" - dependencies: - graceful-fs: "npm:^4.2.0" - jsonfile: "npm:^6.0.1" - universalify: "npm:^2.0.0" - checksum: 10c0/5f95e996186ff45463059feb115a22fb048bdaf7e487ecee8a8646c78ed8fdca63630e3077d4c16ce677051f5e60d3355a06f3cd61f3ca43f48cc58822a44d0a - languageName: node - linkType: hard - -"fs-extra@npm:^8.0.1, fs-extra@npm:^8.1.0": - version: 8.1.0 - resolution: "fs-extra@npm:8.1.0" - dependencies: - graceful-fs: "npm:^4.2.0" - jsonfile: "npm:^4.0.0" - universalify: "npm:^0.1.0" - checksum: 10c0/259f7b814d9e50d686899550c4f9ded85c46c643f7fe19be69504888e007fcbc08f306fae8ec495b8b998635e997c9e3e175ff2eeed230524ef1c1684cc96423 - languageName: node - linkType: hard - -"fs-merger@npm:^3.2.1": - version: 3.2.1 - resolution: "fs-merger@npm:3.2.1" - dependencies: - broccoli-node-api: "npm:^1.7.0" - broccoli-node-info: "npm:^2.1.0" - fs-extra: "npm:^8.0.1" - fs-tree-diff: "npm:^2.0.1" - walk-sync: "npm:^2.2.0" - checksum: 10c0/54a2a5ebf5cecaadff329752a9f67c1025f9f12afcdea97bf44b1625283ead2379bcefadab9d4ee96e15eb5870c97ac34e60eba2982c91e4bc508ed35a31d154 - languageName: node - linkType: hard - -"fs-minipass@npm:^3.0.0": - version: 3.0.3 - resolution: "fs-minipass@npm:3.0.3" - dependencies: - minipass: "npm:^7.0.3" - checksum: 10c0/63e80da2ff9b621e2cb1596abcb9207f1cf82b968b116ccd7b959e3323144cce7fb141462200971c38bbf2ecca51695069db45265705bed09a7cd93ae5b89f94 - languageName: node - linkType: hard - -"fs-mkdirp-stream@npm:^2.0.1": - version: 2.0.1 - resolution: "fs-mkdirp-stream@npm:2.0.1" - dependencies: - graceful-fs: "npm:^4.2.8" - streamx: "npm:^2.12.0" - checksum: 10c0/57d25f59a15acd7a1c5d0c9fc0fee08f9e1224a3010e21eecedf1e6d42672b3e377d10ea41cf8fc86ceb2651601648156af615fd18216318435be48031001ec8 - languageName: node - linkType: hard - -"fs-tree-diff@npm:^2.0.1": - version: 2.0.1 - resolution: "fs-tree-diff@npm:2.0.1" - dependencies: - "@types/symlink-or-copy": "npm:^1.2.0" - heimdalljs-logger: "npm:^0.1.7" - object-assign: "npm:^4.1.0" - path-posix: "npm:^1.0.0" - symlink-or-copy: "npm:^1.1.8" - checksum: 10c0/3e5dd4007a24b90a135a1f58be63b03e6c265f15ce2b9f987bf966d04bac3697931aa0329a575ebe5e57ddb44112644b581ce82ef1183fa1e914cee410e8e9ef - languageName: node - linkType: hard - -"fsevents@npm:2.3.2": - version: 2.3.2 - resolution: "fsevents@npm:2.3.2" - dependencies: - node-gyp: "npm:latest" - checksum: 10c0/be78a3efa3e181cda3cf7a4637cb527bcebb0bd0ea0440105a3bb45b86f9245b307dc10a2507e8f4498a7d4ec349d1910f4d73e4d4495b16103106e07eee735b - conditions: os=darwin - languageName: node - linkType: hard - -"fsevents@npm:~2.3.2, fsevents@npm:~2.3.3": - version: 2.3.3 - resolution: "fsevents@npm:2.3.3" - dependencies: - node-gyp: "npm:latest" - checksum: 10c0/a1f0c44595123ed717febbc478aa952e47adfc28e2092be66b8ab1635147254ca6cfe1df792a8997f22716d4cbafc73309899ff7bfac2ac3ad8cf2e4ecc3ec60 - conditions: os=darwin - languageName: node - linkType: hard - -"fsevents@patch:fsevents@npm%3A2.3.2#optional!builtin": - version: 2.3.2 - resolution: "fsevents@patch:fsevents@npm%3A2.3.2#optional!builtin::version=2.3.2&hash=df0bf1" - dependencies: - node-gyp: "npm:latest" - conditions: os=darwin - languageName: node - linkType: hard - -"fsevents@patch:fsevents@npm%3A~2.3.2#optional!builtin, fsevents@patch:fsevents@npm%3A~2.3.3#optional!builtin": - version: 2.3.3 - resolution: "fsevents@patch:fsevents@npm%3A2.3.3#optional!builtin::version=2.3.3&hash=df0bf1" - dependencies: - node-gyp: "npm:latest" - conditions: os=darwin - languageName: node - linkType: hard - -"function-bind@npm:^1.1.2": - version: 1.1.2 - resolution: "function-bind@npm:1.1.2" - checksum: 10c0/d8680ee1e5fcd4c197e4ac33b2b4dce03c71f4d91717292785703db200f5c21f977c568d28061226f9b5900cbcd2c84463646134fd5337e7925e0942bc3f46d5 - languageName: node - linkType: hard - -"function.prototype.name@npm:^1.1.6, function.prototype.name@npm:^1.1.8": - version: 1.1.8 - resolution: "function.prototype.name@npm:1.1.8" - dependencies: - call-bind: "npm:^1.0.8" - call-bound: "npm:^1.0.3" - define-properties: "npm:^1.2.1" - functions-have-names: "npm:^1.2.3" - hasown: "npm:^2.0.2" - is-callable: "npm:^1.2.7" - checksum: 10c0/e920a2ab52663005f3cbe7ee3373e3c71c1fb5558b0b0548648cdf3e51961085032458e26c71ff1a8c8c20e7ee7caeb03d43a5d1fa8610c459333323a2e71253 - languageName: node - linkType: hard - -"functions-have-names@npm:^1.2.3": - version: 1.2.3 - resolution: "functions-have-names@npm:1.2.3" - checksum: 10c0/33e77fd29bddc2d9bb78ab3eb854c165909201f88c75faa8272e35899e2d35a8a642a15e7420ef945e1f64a9670d6aa3ec744106b2aa42be68ca5114025954ca - languageName: node - linkType: hard - -"generator-function@npm:^2.0.0": - version: 2.0.1 - resolution: "generator-function@npm:2.0.1" - checksum: 10c0/8a9f59df0f01cfefafdb3b451b80555e5cf6d76487095db91ac461a0e682e4ff7a9dbce15f4ecec191e53586d59eece01949e05a4b4492879600bbbe8e28d6b8 - languageName: node - linkType: hard - -"gensync@npm:^1.0.0-beta.2": - version: 1.0.0-beta.2 - resolution: "gensync@npm:1.0.0-beta.2" - checksum: 10c0/782aba6cba65b1bb5af3b095d96249d20edbe8df32dbf4696fd49be2583faf676173bf4809386588828e4dd76a3354fcbeb577bab1c833ccd9fc4577f26103f8 - languageName: node - linkType: hard - -"get-caller-file@npm:^2.0.1, get-caller-file@npm:^2.0.5": - version: 2.0.5 - resolution: "get-caller-file@npm:2.0.5" - checksum: 10c0/c6c7b60271931fa752aeb92f2b47e355eac1af3a2673f47c9589e8f8a41adc74d45551c1bc57b5e66a80609f10ffb72b6f575e4370d61cc3f7f3aaff01757cde - languageName: node - linkType: hard - -"get-intrinsic@npm:^1.2.4, get-intrinsic@npm:^1.2.5, get-intrinsic@npm:^1.2.6, get-intrinsic@npm:^1.2.7": - version: 1.2.7 - resolution: "get-intrinsic@npm:1.2.7" - dependencies: - call-bind-apply-helpers: "npm:^1.0.1" - es-define-property: "npm:^1.0.1" - es-errors: "npm:^1.3.0" - es-object-atoms: "npm:^1.0.0" - function-bind: "npm:^1.1.2" - get-proto: "npm:^1.0.0" - gopd: "npm:^1.2.0" - has-symbols: "npm:^1.1.0" - hasown: "npm:^2.0.2" - math-intrinsics: "npm:^1.1.0" - checksum: 10c0/b475dec9f8bff6f7422f51ff4b7b8d0b68e6776ee83a753c1d627e3008c3442090992788038b37eff72e93e43dceed8c1acbdf2d6751672687ec22127933080d - languageName: node - linkType: hard - -"get-intrinsic@npm:^1.3.0": - version: 1.3.0 - resolution: "get-intrinsic@npm:1.3.0" - dependencies: - call-bind-apply-helpers: "npm:^1.0.2" - es-define-property: "npm:^1.0.1" - es-errors: "npm:^1.3.0" - es-object-atoms: "npm:^1.1.1" - function-bind: "npm:^1.1.2" - get-proto: "npm:^1.0.1" - gopd: "npm:^1.2.0" - has-symbols: "npm:^1.1.0" - hasown: "npm:^2.0.2" - math-intrinsics: "npm:^1.1.0" - checksum: 10c0/52c81808af9a8130f581e6a6a83e1ba4a9f703359e7a438d1369a5267a25412322f03dcbd7c549edaef0b6214a0630a28511d7df0130c93cfd380f4fa0b5b66a - languageName: node - linkType: hard - -"get-nonce@npm:^1.0.0": - version: 1.0.1 - resolution: "get-nonce@npm:1.0.1" - checksum: 10c0/2d7df55279060bf0568549e1ffc9b84bc32a32b7541675ca092dce56317cdd1a59a98dcc4072c9f6a980779440139a3221d7486f52c488e69dc0fd27b1efb162 - languageName: node - linkType: hard - -"get-proto@npm:^1.0.0, get-proto@npm:^1.0.1": - version: 1.0.1 - resolution: "get-proto@npm:1.0.1" - dependencies: - dunder-proto: "npm:^1.0.1" - es-object-atoms: "npm:^1.0.0" - checksum: 10c0/9224acb44603c5526955e83510b9da41baf6ae73f7398875fba50edc5e944223a89c4a72b070fcd78beb5f7bdda58ecb6294adc28f7acfc0da05f76a2399643c - languageName: node - linkType: hard - -"get-symbol-description@npm:^1.1.0": - version: 1.1.0 - resolution: "get-symbol-description@npm:1.1.0" - dependencies: - call-bound: "npm:^1.0.3" - es-errors: "npm:^1.3.0" - get-intrinsic: "npm:^1.2.6" - checksum: 10c0/d6a7d6afca375779a4b307738c9e80dbf7afc0bdbe5948768d54ab9653c865523d8920e670991a925936eb524b7cb6a6361d199a760b21d0ca7620194455aa4b - languageName: node - linkType: hard - -"glob-parent@npm:^5.1.2, glob-parent@npm:~5.1.2": - version: 5.1.2 - resolution: "glob-parent@npm:5.1.2" - dependencies: - is-glob: "npm:^4.0.1" - checksum: 10c0/cab87638e2112bee3f839ef5f6e0765057163d39c66be8ec1602f3823da4692297ad4e972de876ea17c44d652978638d2fd583c6713d0eb6591706825020c9ee - languageName: node - linkType: hard - -"glob-parent@npm:^6.0.2": - version: 6.0.2 - resolution: "glob-parent@npm:6.0.2" - dependencies: - is-glob: "npm:^4.0.3" - checksum: 10c0/317034d88654730230b3f43bb7ad4f7c90257a426e872ea0bf157473ac61c99bf5d205fad8f0185f989be8d2fa6d3c7dce1645d99d545b6ea9089c39f838e7f8 - languageName: node - linkType: hard - -"glob-stream@npm:^8.0.0": - version: 8.0.2 - resolution: "glob-stream@npm:8.0.2" - dependencies: - "@gulpjs/to-absolute-glob": "npm:^4.0.0" - anymatch: "npm:^3.1.3" - fastq: "npm:^1.13.0" - glob-parent: "npm:^6.0.2" - is-glob: "npm:^4.0.3" - is-negated-glob: "npm:^1.0.0" - normalize-path: "npm:^3.0.0" - streamx: "npm:^2.12.5" - checksum: 10c0/ba93be61b85d2143d2b21f35caaf5cb8450c5b72fa377353afabb4922862368be2366c45a998662eaa0098957bf1cc599e546a975767a32758c259093f5b069e - languageName: node - linkType: hard - -"glob-to-regexp@npm:^0.4.1": - version: 0.4.1 - resolution: "glob-to-regexp@npm:0.4.1" - checksum: 10c0/0486925072d7a916f052842772b61c3e86247f0a80cc0deb9b5a3e8a1a9faad5b04fb6f58986a09f34d3e96cd2a22a24b7e9882fb1cf904c31e9a310de96c429 - languageName: node - linkType: hard - -"glob@npm:^10.5.0": - version: 10.5.0 - resolution: "glob@npm:10.5.0" - dependencies: - foreground-child: "npm:^3.1.0" - jackspeak: "npm:^3.1.2" - minimatch: "npm:^9.0.4" - minipass: "npm:^7.1.2" - package-json-from-dist: "npm:^1.0.0" - path-scurry: "npm:^1.11.1" - bin: - glob: dist/esm/bin.mjs - checksum: 10c0/100705eddbde6323e7b35e1d1ac28bcb58322095bd8e63a7d0bef1a2cdafe0d0f7922a981b2b48369a4f8c1b077be5c171804534c3509dfe950dde15fbe6d828 - languageName: node - linkType: hard - -"global-jsdom@npm:^26.0.0": - version: 26.0.0 - resolution: "global-jsdom@npm:26.0.0" - peerDependencies: - jsdom: ">=26 <27" - checksum: 10c0/96b2069eb13e81d3cfe6049b4aabbf84839a171b695bec100cb770fb7196f957578e2068b10d9fd381a0db2a5ac22c37dd5c7a9cf29bd806e843e107b00fba36 - languageName: node - linkType: hard - -"globals@npm:^11.1.0": - version: 11.12.0 - resolution: "globals@npm:11.12.0" - checksum: 10c0/758f9f258e7b19226bd8d4af5d3b0dcf7038780fb23d82e6f98932c44e239f884847f1766e8fa9cc5635ccb3204f7fa7314d4408dd4002a5e8ea827b4018f0a1 - languageName: node - linkType: hard - -"globals@npm:^13.19.0": - version: 13.24.0 - resolution: "globals@npm:13.24.0" - dependencies: - type-fest: "npm:^0.20.2" - checksum: 10c0/d3c11aeea898eb83d5ec7a99508600fbe8f83d2cf00cbb77f873dbf2bcb39428eff1b538e4915c993d8a3b3473fa71eeebfe22c9bb3a3003d1e26b1f2c8a42cd - languageName: node - linkType: hard - -"globals@npm:^15.9.0": - version: 15.12.0 - resolution: "globals@npm:15.12.0" - checksum: 10c0/f34e0a1845b694f45188331742af9f488b07ba7440a06e9d2039fce0386fbbfc24afdbb9846ebdccd4092d03644e43081c49eb27b30f4b88e43af156e1c1dc34 - languageName: node - linkType: hard - -"globalthis@npm:^1.0.4": - version: 1.0.4 - resolution: "globalthis@npm:1.0.4" - dependencies: - define-properties: "npm:^1.2.1" - gopd: "npm:^1.0.1" - checksum: 10c0/9d156f313af79d80b1566b93e19285f481c591ad6d0d319b4be5e03750d004dde40a39a0f26f7e635f9007a3600802f53ecd85a759b86f109e80a5f705e01846 - languageName: node - linkType: hard - -"globby@npm:^11.1.0": - version: 11.1.0 - resolution: "globby@npm:11.1.0" - dependencies: - array-union: "npm:^2.1.0" - dir-glob: "npm:^3.0.1" - fast-glob: "npm:^3.2.9" - ignore: "npm:^5.2.0" - merge2: "npm:^1.4.1" - slash: "npm:^3.0.0" - checksum: 10c0/b39511b4afe4bd8a7aead3a27c4ade2b9968649abab0a6c28b1a90141b96ca68ca5db1302f7c7bd29eab66bf51e13916b8e0a3d0ac08f75e1e84a39b35691189 - languageName: node - linkType: hard - -"gopd@npm:^1.0.1, gopd@npm:^1.2.0": - version: 1.2.0 - resolution: "gopd@npm:1.2.0" - checksum: 10c0/50fff1e04ba2b7737c097358534eacadad1e68d24cccee3272e04e007bed008e68d2614f3987788428fd192a5ae3889d08fb2331417e4fc4a9ab366b2043cead - languageName: node - linkType: hard - -"graceful-fs@npm:^4.1.6, graceful-fs@npm:^4.2.0, graceful-fs@npm:^4.2.10, graceful-fs@npm:^4.2.11, graceful-fs@npm:^4.2.6, graceful-fs@npm:^4.2.8": - version: 4.2.11 - resolution: "graceful-fs@npm:4.2.11" - checksum: 10c0/386d011a553e02bc594ac2ca0bd6d9e4c22d7fa8cfbfc448a6d148c59ea881b092db9dbe3547ae4b88e55f1b01f7c4a2ecc53b310c042793e63aa44cf6c257f2 - languageName: node - linkType: hard - -"graphemer@npm:^1.4.0": - version: 1.4.0 - resolution: "graphemer@npm:1.4.0" - checksum: 10c0/e951259d8cd2e0d196c72ec711add7115d42eb9a8146c8eeda5b8d3ac91e5dd816b9cd68920726d9fd4490368e7ed86e9c423f40db87e2d8dfafa00fa17c3a31 - languageName: node - linkType: hard - -"gulp-sort@npm:^2.0.0": - version: 2.0.0 - resolution: "gulp-sort@npm:2.0.0" - dependencies: - through2: "npm:^2.0.1" - checksum: 10c0/86aeb1d4222c0bec79a1cb4579a56ad18e507f708d13bba58e8497bd2341ffc9e0deed4d2f0ddc132b4d0a23f0e78e5673477ded6ea7e85c4974ef0447606e58 - languageName: node - linkType: hard - -"has-bigints@npm:^1.0.2": - version: 1.1.0 - resolution: "has-bigints@npm:1.1.0" - checksum: 10c0/2de0cdc4a1ccf7a1e75ffede1876994525ac03cc6f5ae7392d3415dd475cd9eee5bceec63669ab61aa997ff6cceebb50ef75561c7002bed8988de2b9d1b40788 - languageName: node - linkType: hard - -"has-flag@npm:^3.0.0": - version: 3.0.0 - resolution: "has-flag@npm:3.0.0" - checksum: 10c0/1c6c83b14b8b1b3c25b0727b8ba3e3b647f99e9e6e13eb7322107261de07a4c1be56fc0d45678fc376e09772a3a1642ccdaf8fc69bdf123b6c086598397ce473 - languageName: node - linkType: hard - -"has-flag@npm:^4.0.0": - version: 4.0.0 - resolution: "has-flag@npm:4.0.0" - checksum: 10c0/2e789c61b7888d66993e14e8331449e525ef42aac53c627cc53d1c3334e768bcb6abdc4f5f0de1478a25beec6f0bd62c7549058b7ac53e924040d4f301f02fd1 - languageName: node - linkType: hard - -"has-property-descriptors@npm:^1.0.0, has-property-descriptors@npm:^1.0.2": - version: 1.0.2 - resolution: "has-property-descriptors@npm:1.0.2" - dependencies: - es-define-property: "npm:^1.0.0" - checksum: 10c0/253c1f59e80bb476cf0dde8ff5284505d90c3bdb762983c3514d36414290475fe3fd6f574929d84de2a8eec00d35cf07cb6776205ff32efd7c50719125f00236 - languageName: node - linkType: hard - -"has-proto@npm:^1.2.0": - version: 1.2.0 - resolution: "has-proto@npm:1.2.0" - dependencies: - dunder-proto: "npm:^1.0.0" - checksum: 10c0/46538dddab297ec2f43923c3d35237df45d8c55a6fc1067031e04c13ed8a9a8f94954460632fd4da84c31a1721eefee16d901cbb1ae9602bab93bb6e08f93b95 - languageName: node - linkType: hard - -"has-symbols@npm:^1.0.3, has-symbols@npm:^1.1.0": - version: 1.1.0 - resolution: "has-symbols@npm:1.1.0" - checksum: 10c0/dde0a734b17ae51e84b10986e651c664379018d10b91b6b0e9b293eddb32f0f069688c841fb40f19e9611546130153e0a2a48fd7f512891fb000ddfa36f5a20e - languageName: node - linkType: hard - -"has-tostringtag@npm:^1.0.2": - version: 1.0.2 - resolution: "has-tostringtag@npm:1.0.2" - dependencies: - has-symbols: "npm:^1.0.3" - checksum: 10c0/a8b166462192bafe3d9b6e420a1d581d93dd867adb61be223a17a8d6dad147aa77a8be32c961bb2f27b3ef893cae8d36f564ab651f5e9b7938ae86f74027c48c - languageName: node - linkType: hard - -"hash-base@npm:^3.0.0, hash-base@npm:^3.1.2": - version: 3.1.2 - resolution: "hash-base@npm:3.1.2" - dependencies: - inherits: "npm:^2.0.4" - readable-stream: "npm:^2.3.8" - safe-buffer: "npm:^5.2.1" - to-buffer: "npm:^1.2.1" - checksum: 10c0/f3b7fae1853b31340048dd659f40f5260ca6f3ff53b932f807f4ab701ee09039f6e9dbe1841723ff61e20f3f69d6387a352e4ccc5f997dedb0d375c7d88bc15e - languageName: node - linkType: hard - -"hash-base@npm:~3.0.4": - version: 3.0.5 - resolution: "hash-base@npm:3.0.5" - dependencies: - inherits: "npm:^2.0.4" - safe-buffer: "npm:^5.2.1" - checksum: 10c0/6dc185b79bad9b6d525cd132a588e4215380fdc36fec6f7a8a58c5db8e3b642557d02ad9c367f5e476c7c3ad3ccffa3607f308b124e1ed80e3b80a1b254db61e - languageName: node - linkType: hard - -"hash.js@npm:^1.0.0, hash.js@npm:^1.0.3": - version: 1.1.7 - resolution: "hash.js@npm:1.1.7" - dependencies: - inherits: "npm:^2.0.3" - minimalistic-assert: "npm:^1.0.1" - checksum: 10c0/41ada59494eac5332cfc1ce6b7ebdd7b88a3864a6d6b08a3ea8ef261332ed60f37f10877e0c825aaa4bddebf164fbffa618286aeeec5296675e2671cbfa746c4 - languageName: node - linkType: hard - -"hasown@npm:^2.0.0, hasown@npm:^2.0.2": - version: 2.0.2 - resolution: "hasown@npm:2.0.2" - dependencies: - function-bind: "npm:^1.1.2" - checksum: 10c0/3769d434703b8ac66b209a4cca0737519925bbdb61dd887f93a16372b14694c63ff4e797686d87c90f08168e81082248b9b028bad60d4da9e0d1148766f56eb9 - languageName: node - linkType: hard - -"he@npm:1.2.0, he@npm:^1.2.0": - version: 1.2.0 - resolution: "he@npm:1.2.0" - bin: - he: bin/he - checksum: 10c0/a27d478befe3c8192f006cdd0639a66798979dfa6e2125c6ac582a19a5ebfec62ad83e8382e6036170d873f46e4536a7e795bf8b95bf7c247f4cc0825ccc8c17 - languageName: node - linkType: hard - -"heimdalljs-logger@npm:^0.1.10, heimdalljs-logger@npm:^0.1.7": - version: 0.1.10 - resolution: "heimdalljs-logger@npm:0.1.10" - dependencies: - debug: "npm:^2.2.0" - heimdalljs: "npm:^0.2.6" - checksum: 10c0/f67da38fde8a399f826f1327c735133eea752e1626c9668694624c321eb715d97b39b244bf420a6dca595f78609f1bd604b33d6d39446a8c985dd02131a22645 - languageName: node - linkType: hard - -"heimdalljs@npm:^0.2.6": - version: 0.2.6 - resolution: "heimdalljs@npm:0.2.6" - dependencies: - rsvp: "npm:~3.2.1" - checksum: 10c0/20c9d9cce7983683a6423720387af0701de8c50660734899bf68a2d862535414e463ac69fd6423875ab3ace8f83ae4b490f18e047c5b3db8e5ab64da1b7aedc3 - languageName: node - linkType: hard - -"hmac-drbg@npm:^1.0.1": - version: 1.0.1 - resolution: "hmac-drbg@npm:1.0.1" - dependencies: - hash.js: "npm:^1.0.3" - minimalistic-assert: "npm:^1.0.0" - minimalistic-crypto-utils: "npm:^1.0.1" - checksum: 10c0/f3d9ba31b40257a573f162176ac5930109816036c59a09f901eb2ffd7e5e705c6832bedfff507957125f2086a0ab8f853c0df225642a88bf1fcaea945f20600d - languageName: node - linkType: hard - -"hoist-non-react-statics@npm:^3.3.2": - version: 3.3.2 - resolution: "hoist-non-react-statics@npm:3.3.2" - dependencies: - react-is: "npm:^16.7.0" - checksum: 10c0/fe0889169e845d738b59b64badf5e55fa3cf20454f9203d1eb088df322d49d4318df774828e789898dcb280e8a5521bb59b3203385662ca5e9218a6ca5820e74 - languageName: node - linkType: hard - -"hosted-git-info@npm:^2.1.4": - version: 2.8.9 - resolution: "hosted-git-info@npm:2.8.9" - checksum: 10c0/317cbc6b1bbbe23c2a40ae23f3dafe9fa349ce42a89a36f930e3f9c0530c179a3882d2ef1e4141a4c3674d6faaea862138ec55b43ad6f75e387fda2483a13c70 - languageName: node - linkType: hard - -"html-encoding-sniffer@npm:^4.0.0": - version: 4.0.0 - resolution: "html-encoding-sniffer@npm:4.0.0" - dependencies: - whatwg-encoding: "npm:^3.1.1" - checksum: 10c0/523398055dc61ac9b34718a719cb4aa691e4166f29187e211e1607de63dc25ac7af52ca7c9aead0c4b3c0415ffecb17326396e1202e2e86ff4bca4c0ee4c6140 - languageName: node - linkType: hard - -"html-entities@npm:^2.6.0": - version: 2.6.0 - resolution: "html-entities@npm:2.6.0" - checksum: 10c0/7c8b15d9ea0cd00dc9279f61bab002ba6ca8a7a0f3c36ed2db3530a67a9621c017830d1d2c1c65beb9b8e3436ea663e9cf8b230472e0e413359399413b27c8b7 - languageName: node - linkType: hard - -"html-escaper@npm:^2.0.0": - version: 2.0.2 - resolution: "html-escaper@npm:2.0.2" - checksum: 10c0/208e8a12de1a6569edbb14544f4567e6ce8ecc30b9394fcaa4e7bb1e60c12a7c9a1ed27e31290817157e8626f3a4f29e76c8747030822eb84a6abb15c255f0a0 - languageName: node - linkType: hard - -"html-minifier-terser@npm:^6.1.0": - version: 6.1.0 - resolution: "html-minifier-terser@npm:6.1.0" - dependencies: - camel-case: "npm:^4.1.2" - clean-css: "npm:^5.2.2" - commander: "npm:^8.3.0" - he: "npm:^1.2.0" - param-case: "npm:^3.0.4" - relateurl: "npm:^0.2.7" - terser: "npm:^5.10.0" - bin: - html-minifier-terser: cli.js - checksum: 10c0/1aa4e4f01cf7149e3ac5ea84fb7a1adab86da40d38d77a6fff42852b5ee3daccb78b615df97264e3a6a5c33e57f0c77f471d607ca1e1debd1dab9b58286f4b5a - languageName: node - linkType: hard - -"html-parse-stringify@npm:^3.0.1": - version: 3.0.1 - resolution: "html-parse-stringify@npm:3.0.1" - dependencies: - void-elements: "npm:3.1.0" - checksum: 10c0/159292753d48b84d216d61121054ae5a33466b3db5b446e2ffc093ac077a411a99ce6cbe0d18e55b87cf25fa3c5a86c4d8b130b9719ec9b66623259000c72c15 - languageName: node - linkType: hard - -"htmlparser2@npm:^9.1.0": - version: 9.1.0 - resolution: "htmlparser2@npm:9.1.0" - dependencies: - domelementtype: "npm:^2.3.0" - domhandler: "npm:^5.0.3" - domutils: "npm:^3.1.0" - entities: "npm:^4.5.0" - checksum: 10c0/394f6323efc265bbc791d8c0d96bfe95984e0407565248521ab92e2dc7668e5ceeca7bc6ed18d408b9ee3b25032c5743368a4280d280332d782821d5d467ad8f - languageName: node - linkType: hard - -"http-cache-semantics@npm:^4.1.1": - version: 4.1.1 - resolution: "http-cache-semantics@npm:4.1.1" - checksum: 10c0/ce1319b8a382eb3cbb4a37c19f6bfe14e5bb5be3d09079e885e8c513ab2d3cd9214902f8a31c9dc4e37022633ceabfc2d697405deeaf1b8f3552bb4ed996fdfc - languageName: node - linkType: hard - -"http-proxy-agent@npm:^7.0.0, http-proxy-agent@npm:^7.0.2": - version: 7.0.2 - resolution: "http-proxy-agent@npm:7.0.2" - dependencies: - agent-base: "npm:^7.1.0" - debug: "npm:^4.3.4" - checksum: 10c0/4207b06a4580fb85dd6dff521f0abf6db517489e70863dca1a0291daa7f2d3d2d6015a57bd702af068ea5cf9f1f6ff72314f5f5b4228d299c0904135d2aef921 - languageName: node - linkType: hard - -"https-browserify@npm:^1.0.0": - version: 1.0.0 - resolution: "https-browserify@npm:1.0.0" - checksum: 10c0/e17b6943bc24ea9b9a7da5714645d808670af75a425f29baffc3284962626efdc1eb3aa9bbffaa6e64028a6ad98af5b09fabcb454a8f918fb686abfdc9e9b8ae - languageName: node - linkType: hard - -"https-proxy-agent@npm:^5.0.0": - version: 5.0.1 - resolution: "https-proxy-agent@npm:5.0.1" - dependencies: - agent-base: "npm:6" - debug: "npm:4" - checksum: 10c0/6dd639f03434003577c62b27cafdb864784ef19b2de430d8ae2a1d45e31c4fd60719e5637b44db1a88a046934307da7089e03d6089ec3ddacc1189d8de8897d1 - languageName: node - linkType: hard - -"https-proxy-agent@npm:^7.0.1, https-proxy-agent@npm:^7.0.6": - version: 7.0.6 - resolution: "https-proxy-agent@npm:7.0.6" - dependencies: - agent-base: "npm:^7.1.2" - debug: "npm:4" - checksum: 10c0/f729219bc735edb621fa30e6e84e60ee5d00802b8247aac0d7b79b0bd6d4b3294737a337b93b86a0bd9e68099d031858a39260c976dc14cdbba238ba1f8779ac - languageName: node - linkType: hard - -"i18next-browser-languagedetector@npm:^8.0.0": - version: 8.2.1 - resolution: "i18next-browser-languagedetector@npm:8.2.1" - dependencies: - "@babel/runtime": "npm:^7.23.2" - checksum: 10c0/d200847a79b4cb2764ef59b33e5399085d4d56b2b038e884bb54fffe17953b467899142a6ef6e985592234f10049d14d06b80f2c56441ae80648c5a6717704f3 - languageName: node - linkType: hard - -"i18next-parser@npm:^9.1.0": - version: 9.4.0 - resolution: "i18next-parser@npm:9.4.0" - dependencies: - "@babel/runtime": "npm:^7.25.0" - broccoli-plugin: "npm:^4.0.7" - cheerio: "npm:^1.0.0" - colors: "npm:^1.4.0" - commander: "npm:^12.1.0" - eol: "npm:^0.9.1" - esbuild: "npm:^0.25.0" - fs-extra: "npm:^11.2.0" - gulp-sort: "npm:^2.0.0" - i18next: "npm:^23.5.1 || ^24.2.0" - js-yaml: "npm:^4.1.0" - lilconfig: "npm:^3.1.3" - rsvp: "npm:^4.8.5" - sort-keys: "npm:^5.0.0" - typescript: "npm:^5.0.4" - vinyl: "npm:^3.0.0" - vinyl-fs: "npm:^4.0.0" - bin: - i18next: bin/cli.js - checksum: 10c0/4a9c94d16ea0869e58cd600216d56e6ccb2d815bf5acdb96df1aba0750d053514abd52136434681de3601bc0f5324464b8a42f608bfe6c95961f5c2a2e38e3da - languageName: node - linkType: hard - -"i18next@npm:^23.5.1 || ^24.2.0": - version: 24.2.3 - resolution: "i18next@npm:24.2.3" - dependencies: - "@babel/runtime": "npm:^7.26.10" - peerDependencies: - typescript: ^5 - peerDependenciesMeta: - typescript: - optional: true - checksum: 10c0/7ac11a67d618ec714beef303aa497c1249bf5f1977dd3ebe9ca2673dfa6cadbba9e2d39ec1337688903ae3866ce9c1bc22cd6b265e66cce54c5db3a9bbedd390 - languageName: node - linkType: hard - -"i18next@npm:^25.0.0": - version: 25.10.10 - resolution: "i18next@npm:25.10.10" - dependencies: - "@babel/runtime": "npm:^7.29.2" - peerDependencies: - typescript: ^5 || ^6 - peerDependenciesMeta: - typescript: - optional: true - checksum: 10c0/6ff601b52363c9c974ef293af4a6de04d9f76b4bf2ad9a56c8546235aaf19ff1a7c2109ddba3a73922d418e208ec5b688e5afb323eba6e27c75d629e93827ae1 - languageName: node - linkType: hard - -"iconv-lite@npm:0.6.3, iconv-lite@npm:^0.6.2, iconv-lite@npm:^0.6.3": - version: 0.6.3 - resolution: "iconv-lite@npm:0.6.3" - dependencies: - safer-buffer: "npm:>= 2.1.2 < 3.0.0" - checksum: 10c0/98102bc66b33fcf5ac044099d1257ba0b7ad5e3ccd3221f34dd508ab4070edff183276221684e1e0555b145fce0850c9f7d2b60a9fcac50fbb4ea0d6e845a3b1 - languageName: node - linkType: hard - -"ieee754@npm:^1.1.13, ieee754@npm:^1.2.1": - version: 1.2.1 - resolution: "ieee754@npm:1.2.1" - checksum: 10c0/b0782ef5e0935b9f12883a2e2aa37baa75da6e66ce6515c168697b42160807d9330de9a32ec1ed73149aea02e0d822e572bca6f1e22bdcbd2149e13b050b17bb - languageName: node - linkType: hard - -"ignore@npm:^5.2.0": - version: 5.3.2 - resolution: "ignore@npm:5.3.2" - checksum: 10c0/f9f652c957983634ded1e7f02da3b559a0d4cc210fca3792cb67f1b153623c9c42efdc1c4121af171e295444459fc4a9201101fb041b1104a3c000bccb188337 - languageName: node - linkType: hard - -"ignore@npm:^7.0.5": - version: 7.0.5 - resolution: "ignore@npm:7.0.5" - checksum: 10c0/ae00db89fe873064a093b8999fe4cc284b13ef2a178636211842cceb650b9c3e390d3339191acb145d81ed5379d2074840cf0c33a20bdbd6f32821f79eb4ad5d - languageName: node - linkType: hard - -"immutable@npm:^5.1.5": - version: 5.1.5 - resolution: "immutable@npm:5.1.5" - checksum: 10c0/8017ece1578e3c5939ba3305176aee059def1b8a90c7fa2a347ef583ebbd38cbe77ce1bbd786a5fab57e2da00bbcb0493b92e4332cdc4e1fe5cfb09a4688df31 - languageName: node - linkType: hard - -"import-fresh@npm:^3.2.1": - version: 3.3.1 - resolution: "import-fresh@npm:3.3.1" - dependencies: - parent-module: "npm:^1.0.0" - resolve-from: "npm:^4.0.0" - checksum: 10c0/bf8cc494872fef783249709385ae883b447e3eb09db0ebd15dcead7d9afe7224dad7bd7591c6b73b0b19b3c0f9640eb8ee884f01cfaf2887ab995b0b36a0cbec - languageName: node - linkType: hard - -"import-fresh@npm:^3.3.0": - version: 3.3.0 - resolution: "import-fresh@npm:3.3.0" - dependencies: - parent-module: "npm:^1.0.0" - resolve-from: "npm:^4.0.0" - checksum: 10c0/7f882953aa6b740d1f0e384d0547158bc86efbf2eea0f1483b8900a6f65c5a5123c2cf09b0d542cc419d0b98a759ecaeb394237e97ea427f2da221dc3cd80cc3 - languageName: node - linkType: hard - -"imurmurhash@npm:^0.1.4": - version: 0.1.4 - resolution: "imurmurhash@npm:0.1.4" - checksum: 10c0/8b51313850dd33605c6c9d3fd9638b714f4c4c40250cff658209f30d40da60f78992fb2df5dabee4acf589a6a82bbc79ad5486550754bd9ec4e3fc0d4a57d6a6 - languageName: node - linkType: hard - -"indent-string@npm:^4.0.0": - version: 4.0.0 - resolution: "indent-string@npm:4.0.0" - checksum: 10c0/1e1904ddb0cb3d6cce7cd09e27a90184908b7a5d5c21b92e232c93579d314f0b83c246ffb035493d0504b1e9147ba2c9b21df0030f48673fba0496ecd698161f - languageName: node - linkType: hard - -"inherits@npm:^2.0.1, inherits@npm:^2.0.3, inherits@npm:^2.0.4, inherits@npm:~2.0.3, inherits@npm:~2.0.4": - version: 2.0.4 - resolution: "inherits@npm:2.0.4" - checksum: 10c0/4e531f648b29039fb7426fb94075e6545faa1eb9fe83c29f0b6d9e7263aceb4289d2d4557db0d428188eeb449cc7c5e77b0a0b2c4e248ff2a65933a0dee49ef2 - languageName: node - linkType: hard - -"internal-slot@npm:^1.1.0": - version: 1.1.0 - resolution: "internal-slot@npm:1.1.0" - dependencies: - es-errors: "npm:^1.3.0" - hasown: "npm:^2.0.2" - side-channel: "npm:^1.1.0" - checksum: 10c0/03966f5e259b009a9bf1a78d60da920df198af4318ec004f57b8aef1dd3fe377fbc8cce63a96e8c810010302654de89f9e19de1cd8ad0061d15be28a695465c7 - languageName: node - linkType: hard - -"ip-address@npm:^9.0.5": - version: 9.0.5 - resolution: "ip-address@npm:9.0.5" - dependencies: - jsbn: "npm:1.1.0" - sprintf-js: "npm:^1.1.3" - checksum: 10c0/331cd07fafcb3b24100613e4b53e1a2b4feab11e671e655d46dc09ee233da5011284d09ca40c4ecbdfe1d0004f462958675c224a804259f2f78d2465a87824bc - languageName: node - linkType: hard - -"is-arguments@npm:^1.0.4": - version: 1.2.0 - resolution: "is-arguments@npm:1.2.0" - dependencies: - call-bound: "npm:^1.0.2" - has-tostringtag: "npm:^1.0.2" - checksum: 10c0/6377344b31e9fcb707c6751ee89b11f132f32338e6a782ec2eac9393b0cbd32235dad93052998cda778ee058754860738341d8114910d50ada5615912bb929fc - languageName: node - linkType: hard - -"is-array-buffer@npm:^3.0.4, is-array-buffer@npm:^3.0.5": - version: 3.0.5 - resolution: "is-array-buffer@npm:3.0.5" - dependencies: - call-bind: "npm:^1.0.8" - call-bound: "npm:^1.0.3" - get-intrinsic: "npm:^1.2.6" - checksum: 10c0/c5c9f25606e86dbb12e756694afbbff64bc8b348d1bc989324c037e1068695131930199d6ad381952715dad3a9569333817f0b1a72ce5af7f883ce802e49c83d - languageName: node - linkType: hard - -"is-arrayish@npm:^0.2.1": - version: 0.2.1 - resolution: "is-arrayish@npm:0.2.1" - checksum: 10c0/e7fb686a739068bb70f860b39b67afc62acc62e36bb61c5f965768abce1873b379c563e61dd2adad96ebb7edf6651111b385e490cf508378959b0ed4cac4e729 - languageName: node - linkType: hard - -"is-async-function@npm:^2.0.0": - version: 2.1.0 - resolution: "is-async-function@npm:2.1.0" - dependencies: - call-bound: "npm:^1.0.3" - get-proto: "npm:^1.0.1" - has-tostringtag: "npm:^1.0.2" - safe-regex-test: "npm:^1.1.0" - checksum: 10c0/5209b858c6d18d88a9fb56dea202a050d53d4b722448cc439fdca859b36e23edf27ee8c18958ba49330f1a71b8846576273f4581e1c0bb9d403738129d852fdb - languageName: node - linkType: hard - -"is-bigint@npm:^1.1.0": - version: 1.1.0 - resolution: "is-bigint@npm:1.1.0" - dependencies: - has-bigints: "npm:^1.0.2" - checksum: 10c0/f4f4b905ceb195be90a6ea7f34323bf1c18e3793f18922e3e9a73c684c29eeeeff5175605c3a3a74cc38185fe27758f07efba3dbae812e5c5afbc0d2316b40e4 - languageName: node - linkType: hard - -"is-binary-path@npm:~2.1.0": - version: 2.1.0 - resolution: "is-binary-path@npm:2.1.0" - dependencies: - binary-extensions: "npm:^2.0.0" - checksum: 10c0/a16eaee59ae2b315ba36fad5c5dcaf8e49c3e27318f8ab8fa3cdb8772bf559c8d1ba750a589c2ccb096113bb64497084361a25960899cb6172a6925ab6123d38 - languageName: node - linkType: hard - -"is-boolean-object@npm:^1.2.1": - version: 1.2.1 - resolution: "is-boolean-object@npm:1.2.1" - dependencies: - call-bound: "npm:^1.0.2" - has-tostringtag: "npm:^1.0.2" - checksum: 10c0/2ef601d255a39fdbde79cfe6be80c27b47430ed6712407f29b17d002e20f64c1e3d6692f1d842ba16bf1e9d8ddf1c4f13cac3ed7d9a4a21290f44879ebb4e8f5 - languageName: node - linkType: hard - -"is-builtin-module@npm:^3.2.1": - version: 3.2.1 - resolution: "is-builtin-module@npm:3.2.1" - dependencies: - builtin-modules: "npm:^3.3.0" - checksum: 10c0/5a66937a03f3b18803381518f0ef679752ac18cdb7dd53b5e23ee8df8d440558737bd8dcc04d2aae555909d2ecb4a81b5c0d334d119402584b61e6a003e31af1 - languageName: node - linkType: hard - -"is-callable@npm:^1.1.3, is-callable@npm:^1.2.7": - version: 1.2.7 - resolution: "is-callable@npm:1.2.7" - checksum: 10c0/ceebaeb9d92e8adee604076971dd6000d38d6afc40bb843ea8e45c5579b57671c3f3b50d7f04869618242c6cee08d1b67806a8cb8edaaaf7c0748b3720d6066f - languageName: node - linkType: hard - -"is-core-module@npm:^2.13.0, is-core-module@npm:^2.16.1": - version: 2.16.1 - resolution: "is-core-module@npm:2.16.1" - dependencies: - hasown: "npm:^2.0.2" - checksum: 10c0/898443c14780a577e807618aaae2b6f745c8538eca5c7bc11388a3f2dc6de82b9902bcc7eb74f07be672b11bbe82dd6a6edded44a00cb3d8f933d0459905eedd - languageName: node - linkType: hard - -"is-data-view@npm:^1.0.1, is-data-view@npm:^1.0.2": - version: 1.0.2 - resolution: "is-data-view@npm:1.0.2" - dependencies: - call-bound: "npm:^1.0.2" - get-intrinsic: "npm:^1.2.6" - is-typed-array: "npm:^1.1.13" - checksum: 10c0/ef3548a99d7e7f1370ce21006baca6d40c73e9f15c941f89f0049c79714c873d03b02dae1c64b3f861f55163ecc16da06506c5b8a1d4f16650b3d9351c380153 - languageName: node - linkType: hard - -"is-date-object@npm:^1.0.5, is-date-object@npm:^1.1.0": - version: 1.1.0 - resolution: "is-date-object@npm:1.1.0" - dependencies: - call-bound: "npm:^1.0.2" - has-tostringtag: "npm:^1.0.2" - checksum: 10c0/1a4d199c8e9e9cac5128d32e6626fa7805175af9df015620ac0d5d45854ccf348ba494679d872d37301032e35a54fc7978fba1687e8721b2139aea7870cafa2f - languageName: node - linkType: hard - -"is-docker@npm:^3.0.0": - version: 3.0.0 - resolution: "is-docker@npm:3.0.0" - bin: - is-docker: cli.js - checksum: 10c0/d2c4f8e6d3e34df75a5defd44991b6068afad4835bb783b902fa12d13ebdb8f41b2a199dcb0b5ed2cb78bfee9e4c0bbdb69c2d9646f4106464674d3e697a5856 - languageName: node - linkType: hard - -"is-extglob@npm:^2.1.1": - version: 2.1.1 - resolution: "is-extglob@npm:2.1.1" - checksum: 10c0/5487da35691fbc339700bbb2730430b07777a3c21b9ebaecb3072512dfd7b4ba78ac2381a87e8d78d20ea08affb3f1971b4af629173a6bf435ff8a4c47747912 - languageName: node - linkType: hard - -"is-finalizationregistry@npm:^1.1.0": - version: 1.1.1 - resolution: "is-finalizationregistry@npm:1.1.1" - dependencies: - call-bound: "npm:^1.0.3" - checksum: 10c0/818dff679b64f19e228a8205a1e2d09989a98e98def3a817f889208cfcbf918d321b251aadf2c05918194803ebd2eb01b14fc9d0b2bea53d984f4137bfca5e97 - languageName: node - linkType: hard - -"is-fullwidth-code-point@npm:^3.0.0": - version: 3.0.0 - resolution: "is-fullwidth-code-point@npm:3.0.0" - checksum: 10c0/bb11d825e049f38e04c06373a8d72782eee0205bda9d908cc550ccb3c59b99d750ff9537982e01733c1c94a58e35400661f57042158ff5e8f3e90cf936daf0fc - languageName: node - linkType: hard - -"is-generator-function@npm:^1.0.10": - version: 1.1.0 - resolution: "is-generator-function@npm:1.1.0" - dependencies: - call-bound: "npm:^1.0.3" - get-proto: "npm:^1.0.0" - has-tostringtag: "npm:^1.0.2" - safe-regex-test: "npm:^1.1.0" - checksum: 10c0/fdfa96c8087bf36fc4cd514b474ba2ff404219a4dd4cfa6cf5426404a1eed259bdcdb98f082a71029a48d01f27733e3436ecc6690129a7ec09cb0434bee03a2a - languageName: node - linkType: hard - -"is-generator-function@npm:^1.0.7": - version: 1.1.2 - resolution: "is-generator-function@npm:1.1.2" - dependencies: - call-bound: "npm:^1.0.4" - generator-function: "npm:^2.0.0" - get-proto: "npm:^1.0.1" - has-tostringtag: "npm:^1.0.2" - safe-regex-test: "npm:^1.1.0" - checksum: 10c0/83da102e89c3e3b71d67b51d47c9f9bc862bceb58f87201727e27f7fa19d1d90b0ab223644ecaee6fc6e3d2d622bb25c966fbdaf87c59158b01ce7c0fe2fa372 - languageName: node - linkType: hard - -"is-glob@npm:^4.0.0, is-glob@npm:^4.0.1, is-glob@npm:^4.0.3, is-glob@npm:~4.0.1": - version: 4.0.3 - resolution: "is-glob@npm:4.0.3" - dependencies: - is-extglob: "npm:^2.1.1" - checksum: 10c0/17fb4014e22be3bbecea9b2e3a76e9e34ff645466be702f1693e8f1ee1adac84710d0be0bd9f967d6354036fd51ab7c2741d954d6e91dae6bb69714de92c197a - languageName: node - linkType: hard - -"is-inside-container@npm:^1.0.0": - version: 1.0.0 - resolution: "is-inside-container@npm:1.0.0" - dependencies: - is-docker: "npm:^3.0.0" - bin: - is-inside-container: cli.js - checksum: 10c0/a8efb0e84f6197e6ff5c64c52890fa9acb49b7b74fed4da7c95383965da6f0fa592b4dbd5e38a79f87fc108196937acdbcd758fcefc9b140e479b39ce1fcd1cd - languageName: node - linkType: hard - -"is-map@npm:^2.0.3": - version: 2.0.3 - resolution: "is-map@npm:2.0.3" - checksum: 10c0/2c4d431b74e00fdda7162cd8e4b763d6f6f217edf97d4f8538b94b8702b150610e2c64961340015fe8df5b1fcee33ccd2e9b62619c4a8a3a155f8de6d6d355fc - languageName: node - linkType: hard - -"is-nan@npm:^1.3.2": - version: 1.3.2 - resolution: "is-nan@npm:1.3.2" - dependencies: - call-bind: "npm:^1.0.0" - define-properties: "npm:^1.1.3" - checksum: 10c0/8bfb286f85763f9c2e28ea32e9127702fe980ffd15fa5d63ade3be7786559e6e21355d3625dd364c769c033c5aedf0a2ed3d4025d336abf1b9241e3d9eddc5b0 - languageName: node - linkType: hard - -"is-negated-glob@npm:^1.0.0": - version: 1.0.0 - resolution: "is-negated-glob@npm:1.0.0" - checksum: 10c0/f9d4fb2effd7a6d0e4770463e4cf708fbff2d5b660ab2043e5703e21e3234dfbe9974fdd8c08eb80f9898d5dd3d21b020e8d07fce387cd394a79991f01cd8d1c - languageName: node - linkType: hard - -"is-negative-zero@npm:^2.0.3": - version: 2.0.3 - resolution: "is-negative-zero@npm:2.0.3" - checksum: 10c0/bcdcf6b8b9714063ffcfa9929c575ac69bfdabb8f4574ff557dfc086df2836cf07e3906f5bbc4f2a5c12f8f3ba56af640c843cdfc74da8caed86c7c7d66fd08e - languageName: node - linkType: hard - -"is-network-error@npm:^1.1.0": - version: 1.3.0 - resolution: "is-network-error@npm:1.3.0" - checksum: 10c0/3e85a69e957988db66d5af5412efdd531a5a63e150d1bdd5647cfd4dc54fd89b1dbdd472621f8915233c3176ba1e6922afa8a51a9e363ba4693edf96a294f898 - languageName: node - linkType: hard - -"is-number-object@npm:^1.1.1": - version: 1.1.1 - resolution: "is-number-object@npm:1.1.1" - dependencies: - call-bound: "npm:^1.0.3" - has-tostringtag: "npm:^1.0.2" - checksum: 10c0/97b451b41f25135ff021d85c436ff0100d84a039bb87ffd799cbcdbea81ef30c464ced38258cdd34f080be08fc3b076ca1f472086286d2aa43521d6ec6a79f53 - languageName: node - linkType: hard - -"is-number@npm:^7.0.0": - version: 7.0.0 - resolution: "is-number@npm:7.0.0" - checksum: 10c0/b4686d0d3053146095ccd45346461bc8e53b80aeb7671cc52a4de02dbbf7dc0d1d2a986e2fe4ae206984b4d34ef37e8b795ebc4f4295c978373e6575e295d811 - languageName: node - linkType: hard - -"is-path-inside@npm:^3.0.3": - version: 3.0.3 - resolution: "is-path-inside@npm:3.0.3" - checksum: 10c0/cf7d4ac35fb96bab6a1d2c3598fe5ebb29aafb52c0aaa482b5a3ed9d8ba3edc11631e3ec2637660c44b3ce0e61a08d54946e8af30dec0b60a7c27296c68ffd05 - languageName: node - linkType: hard - -"is-plain-obj@npm:^4.0.0": - version: 4.1.0 - resolution: "is-plain-obj@npm:4.1.0" - checksum: 10c0/32130d651d71d9564dc88ba7e6fda0e91a1010a3694648e9f4f47bb6080438140696d3e3e15c741411d712e47ac9edc1a8a9de1fe76f3487b0d90be06ac9975e - languageName: node - linkType: hard - -"is-potential-custom-element-name@npm:^1.0.1": - version: 1.0.1 - resolution: "is-potential-custom-element-name@npm:1.0.1" - checksum: 10c0/b73e2f22bc863b0939941d369486d308b43d7aef1f9439705e3582bfccaa4516406865e32c968a35f97a99396dac84e2624e67b0a16b0a15086a785e16ce7db9 - languageName: node - linkType: hard - -"is-regex@npm:^1.2.1": - version: 1.2.1 - resolution: "is-regex@npm:1.2.1" - dependencies: - call-bound: "npm:^1.0.2" - gopd: "npm:^1.2.0" - has-tostringtag: "npm:^1.0.2" - hasown: "npm:^2.0.2" - checksum: 10c0/1d3715d2b7889932349241680032e85d0b492cfcb045acb75ffc2c3085e8d561184f1f7e84b6f8321935b4aea39bc9c6ba74ed595b57ce4881a51dfdbc214e04 - languageName: node - linkType: hard - -"is-set@npm:^2.0.3": - version: 2.0.3 - resolution: "is-set@npm:2.0.3" - checksum: 10c0/f73732e13f099b2dc879c2a12341cfc22ccaca8dd504e6edae26484bd5707a35d503fba5b4daad530a9b088ced1ae6c9d8200fd92e09b428fe14ea79ce8080b7 - languageName: node - linkType: hard - -"is-shared-array-buffer@npm:^1.0.4": - version: 1.0.4 - resolution: "is-shared-array-buffer@npm:1.0.4" - dependencies: - call-bound: "npm:^1.0.3" - checksum: 10c0/65158c2feb41ff1edd6bbd6fd8403a69861cf273ff36077982b5d4d68e1d59278c71691216a4a64632bd76d4792d4d1d2553901b6666d84ade13bba5ea7bc7db - languageName: node - linkType: hard - -"is-stream@npm:^2.0.0": - version: 2.0.1 - resolution: "is-stream@npm:2.0.1" - checksum: 10c0/7c284241313fc6efc329b8d7f08e16c0efeb6baab1b4cd0ba579eb78e5af1aa5da11e68559896a2067cd6c526bd29241dda4eb1225e627d5aa1a89a76d4635a5 - languageName: node - linkType: hard - -"is-string@npm:^1.0.7, is-string@npm:^1.1.1": - version: 1.1.1 - resolution: "is-string@npm:1.1.1" - dependencies: - call-bound: "npm:^1.0.3" - has-tostringtag: "npm:^1.0.2" - checksum: 10c0/2f518b4e47886bb81567faba6ffd0d8a8333cf84336e2e78bf160693972e32ad00fe84b0926491cc598dee576fdc55642c92e62d0cbe96bf36f643b6f956f94d - languageName: node - linkType: hard - -"is-subset@npm:^0.1.1": - version: 0.1.1 - resolution: "is-subset@npm:0.1.1" - checksum: 10c0/d8125598ab9077a76684e18726fb915f5cea7a7358ed0c6ff723f4484d71a0a9981ee5aae06c44de99cfdef0fefce37438c6257ab129e53c82045ea0c2acdebf - languageName: node - linkType: hard - -"is-symbol@npm:^1.0.4, is-symbol@npm:^1.1.1": - version: 1.1.1 - resolution: "is-symbol@npm:1.1.1" - dependencies: - call-bound: "npm:^1.0.2" - has-symbols: "npm:^1.1.0" - safe-regex-test: "npm:^1.1.0" - checksum: 10c0/f08f3e255c12442e833f75a9e2b84b2d4882fdfd920513cf2a4a2324f0a5b076c8fd913778e3ea5d258d5183e9d92c0cd20e04b03ab3df05316b049b2670af1e - languageName: node - linkType: hard - -"is-typed-array@npm:^1.1.13, is-typed-array@npm:^1.1.14, is-typed-array@npm:^1.1.15, is-typed-array@npm:^1.1.3": - version: 1.1.15 - resolution: "is-typed-array@npm:1.1.15" - dependencies: - which-typed-array: "npm:^1.1.16" - checksum: 10c0/415511da3669e36e002820584e264997ffe277ff136643a3126cc949197e6ca3334d0f12d084e83b1994af2e9c8141275c741cf2b7da5a2ff62dd0cac26f76c4 - languageName: node - linkType: hard - -"is-valid-glob@npm:^1.0.0": - version: 1.0.0 - resolution: "is-valid-glob@npm:1.0.0" - checksum: 10c0/73aef3a2dc218b677362c876d1bc69699e10cfb50ecae6ac5fa946d7f5bb783721e81d9383bd120e4fb7bcfaa7ebe1edab0b707fd93051cc6e04f90f02d689b6 - languageName: node - linkType: hard - -"is-weakmap@npm:^2.0.2": - version: 2.0.2 - resolution: "is-weakmap@npm:2.0.2" - checksum: 10c0/443c35bb86d5e6cc5929cd9c75a4024bb0fff9586ed50b092f94e700b89c43a33b186b76dbc6d54f3d3d09ece689ab38dcdc1af6a482cbe79c0f2da0a17f1299 - languageName: node - linkType: hard - -"is-weakref@npm:^1.0.2, is-weakref@npm:^1.1.0": - version: 1.1.0 - resolution: "is-weakref@npm:1.1.0" - dependencies: - call-bound: "npm:^1.0.2" - checksum: 10c0/aa835f62e29cb60132ecb3ec7d11bd0f39ec7322325abe8412b805aef47153ec2daefdb21759b049711c674f49b13202a31d8d126bcdff7d8671c78babd4ae5b - languageName: node - linkType: hard - -"is-weakref@npm:^1.1.1": - version: 1.1.1 - resolution: "is-weakref@npm:1.1.1" - dependencies: - call-bound: "npm:^1.0.3" - checksum: 10c0/8e0a9c07b0c780949a100e2cab2b5560a48ecd4c61726923c1a9b77b6ab0aa0046c9e7fb2206042296817045376dee2c8ab1dabe08c7c3dfbf195b01275a085b - languageName: node - linkType: hard - -"is-weakset@npm:^2.0.3": - version: 2.0.4 - resolution: "is-weakset@npm:2.0.4" - dependencies: - call-bound: "npm:^1.0.3" - get-intrinsic: "npm:^1.2.6" - checksum: 10c0/6491eba08acb8dc9532da23cb226b7d0192ede0b88f16199e592e4769db0a077119c1f5d2283d1e0d16d739115f70046e887e477eb0e66cd90e1bb29f28ba647 - languageName: node - linkType: hard - -"is-wsl@npm:^3.1.0": - version: 3.1.1 - resolution: "is-wsl@npm:3.1.1" - dependencies: - is-inside-container: "npm:^1.0.0" - checksum: 10c0/7e5023522bfb8f27de4de960b0d82c4a8146c0bddb186529a3616d78b5bbbfc19ef0c5fc60d0b3a3cc0bf95a415fbdedc18454310ea3049587c879b07ace5107 - languageName: node - linkType: hard - -"isarray@npm:^2.0.5": - version: 2.0.5 - resolution: "isarray@npm:2.0.5" - checksum: 10c0/4199f14a7a13da2177c66c31080008b7124331956f47bca57dd0b6ea9f11687aa25e565a2c7a2b519bc86988d10398e3049a1f5df13c9f6b7664154690ae79fd - languageName: node - linkType: hard - -"isarray@npm:~1.0.0": - version: 1.0.0 - resolution: "isarray@npm:1.0.0" - checksum: 10c0/18b5be6669be53425f0b84098732670ed4e727e3af33bc7f948aac01782110eb9a18b3b329c5323bcdd3acdaae547ee077d3951317e7f133bff7105264b3003d - languageName: node - linkType: hard - -"isexe@npm:^2.0.0": - version: 2.0.0 - resolution: "isexe@npm:2.0.0" - checksum: 10c0/228cfa503fadc2c31596ab06ed6aa82c9976eec2bfd83397e7eaf06d0ccf42cd1dfd6743bf9aeb01aebd4156d009994c5f76ea898d2832c1fe342da923ca457d - languageName: node - linkType: hard - -"isexe@npm:^3.1.1": - version: 3.1.1 - resolution: "isexe@npm:3.1.1" - checksum: 10c0/9ec257654093443eb0a528a9c8cbba9c0ca7616ccb40abd6dde7202734d96bb86e4ac0d764f0f8cd965856aacbff2f4ce23e730dc19dfb41e3b0d865ca6fdcc7 - languageName: node - linkType: hard - -"isomorphic-timers-promises@npm:^1.0.1": - version: 1.0.1 - resolution: "isomorphic-timers-promises@npm:1.0.1" - checksum: 10c0/3b4761d0012ebe6b6382246079fc667f3513f36fe4042638f2bfb7db1557e4f1acd33a9c9907706c04270890ec6434120f132f3f300161a42a7dd8628926c8a4 - languageName: node - linkType: hard - -"istanbul-lib-coverage@npm:^3.0.0, istanbul-lib-coverage@npm:^3.2.2": - version: 3.2.2 - resolution: "istanbul-lib-coverage@npm:3.2.2" - checksum: 10c0/6c7ff2106769e5f592ded1fb418f9f73b4411fd5a084387a5410538332b6567cd1763ff6b6cadca9b9eb2c443cce2f7ea7d7f1b8d315f9ce58539793b1e0922b - languageName: node - linkType: hard - -"istanbul-lib-report@npm:^3.0.0, istanbul-lib-report@npm:^3.0.1": - version: 3.0.1 - resolution: "istanbul-lib-report@npm:3.0.1" - dependencies: - istanbul-lib-coverage: "npm:^3.0.0" - make-dir: "npm:^4.0.0" - supports-color: "npm:^7.1.0" - checksum: 10c0/84323afb14392de8b6a5714bd7e9af845cfbd56cfe71ed276cda2f5f1201aea673c7111901227ee33e68e4364e288d73861eb2ed48f6679d1e69a43b6d9b3ba7 - languageName: node - linkType: hard - -"istanbul-reports@npm:^3.2.0": - version: 3.2.0 - resolution: "istanbul-reports@npm:3.2.0" - dependencies: - html-escaper: "npm:^2.0.0" - istanbul-lib-report: "npm:^3.0.0" - checksum: 10c0/d596317cfd9c22e1394f22a8d8ba0303d2074fe2e971887b32d870e4b33f8464b10f8ccbe6847808f7db485f084eba09e6c2ed706b3a978e4b52f07085b8f9bc - languageName: node - linkType: hard - -"iterator.prototype@npm:^1.1.4": - version: 1.1.5 - resolution: "iterator.prototype@npm:1.1.5" - dependencies: - define-data-property: "npm:^1.1.4" - es-object-atoms: "npm:^1.0.0" - get-intrinsic: "npm:^1.2.6" - get-proto: "npm:^1.0.0" - has-symbols: "npm:^1.1.0" - set-function-name: "npm:^2.0.2" - checksum: 10c0/f7a262808e1b41049ab55f1e9c29af7ec1025a000d243b83edf34ce2416eedd56079b117fa59376bb4a724110690f13aa8427f2ee29a09eec63a7e72367626d0 - languageName: node - linkType: hard - -"jackspeak@npm:^3.1.2": - version: 3.4.3 - resolution: "jackspeak@npm:3.4.3" - dependencies: - "@isaacs/cliui": "npm:^8.0.2" - "@pkgjs/parseargs": "npm:^0.11.0" - dependenciesMeta: - "@pkgjs/parseargs": - optional: true - checksum: 10c0/6acc10d139eaefdbe04d2f679e6191b3abf073f111edf10b1de5302c97ec93fffeb2fdd8681ed17f16268aa9dd4f8c588ed9d1d3bffbbfa6e8bf897cbb3149b9 - languageName: node - linkType: hard - -"jake@npm:^10.8.5": - version: 10.9.2 - resolution: "jake@npm:10.9.2" - dependencies: - async: "npm:^3.2.3" - chalk: "npm:^4.0.2" - filelist: "npm:^1.0.4" - minimatch: "npm:^3.1.2" - bin: - jake: bin/cli.js - checksum: 10c0/c4597b5ed9b6a908252feab296485a4f87cba9e26d6c20e0ca144fb69e0c40203d34a2efddb33b3d297b8bd59605e6c1f44f6221ca1e10e69175ecbf3ff5fe31 - languageName: node - linkType: hard - -"jiti@npm:^2.6.0": - version: 2.6.1 - resolution: "jiti@npm:2.6.1" - bin: - jiti: lib/jiti-cli.mjs - checksum: 10c0/79b2e96a8e623f66c1b703b98ec1b8be4500e1d217e09b09e343471bbb9c105381b83edbb979d01cef18318cc45ce6e153571b6c83122170eefa531c64b6789b - languageName: node - linkType: hard - -"jose@npm:^6.0.12": - version: 6.1.2 - resolution: "jose@npm:6.1.2" - checksum: 10c0/55f79426f43e652ed6d5de938d50f66bb0a10dcae078db81a23f8d3303e889ce226f000e815f3211f9956bb84badce10da892d130d40fe2eca658045a6f1778e - languageName: node - linkType: hard - -"jose@npm:^6.1.0": - version: 6.1.0 - resolution: "jose@npm:6.1.0" - checksum: 10c0/f4518579e907317e144facd15c7627acd06097bbea17735097437217498aa419564c039dd4020f6af5f2d024a7cee6b7be4648ccbbdc238aedb80a47c061217d - languageName: node - linkType: hard - -"js-tokens@npm:^10.0.0": - version: 10.0.0 - resolution: "js-tokens@npm:10.0.0" - checksum: 10c0/a93498747812ba3e0c8626f95f75ab29319f2a13613a0de9e610700405760931624433a0de59eb7c27ff8836e526768fb20783861b86ef89be96676f2c996b64 - languageName: node - linkType: hard - -"js-tokens@npm:^3.0.0 || ^4.0.0, js-tokens@npm:^4.0.0": - version: 4.0.0 - resolution: "js-tokens@npm:4.0.0" - checksum: 10c0/e248708d377aa058eacf2037b07ded847790e6de892bbad3dac0abba2e759cb9f121b00099a65195616badcb6eca8d14d975cb3e89eb1cfda644756402c8aeed - languageName: node - linkType: hard - -"js-yaml@npm:^4.1.1": - version: 4.1.1 - resolution: "js-yaml@npm:4.1.1" - dependencies: - argparse: "npm:^2.0.1" - bin: - js-yaml: bin/js-yaml.js - checksum: 10c0/561c7d7088c40a9bb53cc75becbfb1df6ae49b34b5e6e5a81744b14ae8667ec564ad2527709d1a6e7d5e5fa6d483aa0f373a50ad98d42fde368ec4a190d4fae7 - languageName: node - linkType: hard - -"jsbn@npm:1.1.0": - version: 1.1.0 - resolution: "jsbn@npm:1.1.0" - checksum: 10c0/4f907fb78d7b712e11dea8c165fe0921f81a657d3443dde75359ed52eb2b5d33ce6773d97985a089f09a65edd80b11cb75c767b57ba47391fee4c969f7215c96 - languageName: node - linkType: hard - -"jsdoc-type-pratt-parser@npm:~7.0.0": - version: 7.0.0 - resolution: "jsdoc-type-pratt-parser@npm:7.0.0" - checksum: 10c0/3ede53c80dddf940a51dcdc79e3923537650f6fb6e9001fc76023c2d5cb0195cc8b24b7eebf9b3f20a7bc00d5e6b7f70318f0b8cb5972f6aff884152e6698014 - languageName: node - linkType: hard - -"jsdom@npm:^26.0.0": - version: 26.1.0 - resolution: "jsdom@npm:26.1.0" - dependencies: - cssstyle: "npm:^4.2.1" - data-urls: "npm:^5.0.0" - decimal.js: "npm:^10.5.0" - html-encoding-sniffer: "npm:^4.0.0" - http-proxy-agent: "npm:^7.0.2" - https-proxy-agent: "npm:^7.0.6" - is-potential-custom-element-name: "npm:^1.0.1" - nwsapi: "npm:^2.2.16" - parse5: "npm:^7.2.1" - rrweb-cssom: "npm:^0.8.0" - saxes: "npm:^6.0.0" - symbol-tree: "npm:^3.2.4" - tough-cookie: "npm:^5.1.1" - w3c-xmlserializer: "npm:^5.0.0" - webidl-conversions: "npm:^7.0.0" - whatwg-encoding: "npm:^3.1.1" - whatwg-mimetype: "npm:^4.0.0" - whatwg-url: "npm:^14.1.1" - ws: "npm:^8.18.0" - xml-name-validator: "npm:^5.0.0" - peerDependencies: - canvas: ^3.0.0 - peerDependenciesMeta: - canvas: - optional: true - checksum: 10c0/5b14a5bc32ce077a06fb42d1ab95b1191afa5cbbce8859e3b96831c5143becbbcbf0511d4d4934e922d2901443ced2cdc3b734c1cf30b5f73b3e067ce457d0f4 - languageName: node - linkType: hard - -"jsesc@npm:^3.0.2, jsesc@npm:~3.1.0": - version: 3.1.0 - resolution: "jsesc@npm:3.1.0" - bin: - jsesc: bin/jsesc - checksum: 10c0/531779df5ec94f47e462da26b4cbf05eb88a83d9f08aac2ba04206508fc598527a153d08bd462bae82fc78b3eaa1a908e1a4a79f886e9238641c4cdefaf118b1 - languageName: node - linkType: hard - -"jsesc@npm:~0.5.0": - version: 0.5.0 - resolution: "jsesc@npm:0.5.0" - bin: - jsesc: bin/jsesc - checksum: 10c0/f93792440ae1d80f091b65f8ceddf8e55c4bb7f1a09dee5dcbdb0db5612c55c0f6045625aa6b7e8edb2e0a4feabd80ee48616dbe2d37055573a84db3d24f96d9 - languageName: node - linkType: hard - -"jsesc@npm:~3.0.2": - version: 3.0.2 - resolution: "jsesc@npm:3.0.2" - bin: - jsesc: bin/jsesc - checksum: 10c0/ef22148f9e793180b14d8a145ee6f9f60f301abf443288117b4b6c53d0ecd58354898dc506ccbb553a5f7827965cd38bc5fb726575aae93c5e8915e2de8290e1 - languageName: node - linkType: hard - -"json-buffer@npm:3.0.1": - version: 3.0.1 - resolution: "json-buffer@npm:3.0.1" - checksum: 10c0/0d1c91569d9588e7eef2b49b59851f297f3ab93c7b35c7c221e288099322be6b562767d11e4821da500f3219542b9afd2e54c5dc573107c1126ed1080f8e96d7 - languageName: node - linkType: hard - -"json-parse-even-better-errors@npm:^2.3.0": - version: 2.3.1 - resolution: "json-parse-even-better-errors@npm:2.3.1" - checksum: 10c0/140932564c8f0b88455432e0f33c4cb4086b8868e37524e07e723f4eaedb9425bdc2bafd71bd1d9765bd15fd1e2d126972bc83990f55c467168c228c24d665f3 - languageName: node - linkType: hard - -"json-schema-traverse@npm:^0.4.1": - version: 0.4.1 - resolution: "json-schema-traverse@npm:0.4.1" - checksum: 10c0/108fa90d4cc6f08243aedc6da16c408daf81793bf903e9fd5ab21983cda433d5d2da49e40711da016289465ec2e62e0324dcdfbc06275a607fe3233fde4942ce - languageName: node - linkType: hard - -"json-stable-stringify-without-jsonify@npm:^1.0.1": - version: 1.0.1 - resolution: "json-stable-stringify-without-jsonify@npm:1.0.1" - checksum: 10c0/cb168b61fd4de83e58d09aaa6425ef71001bae30d260e2c57e7d09a5fd82223e2f22a042dedaab8db23b7d9ae46854b08bb1f91675a8be11c5cffebef5fb66a5 - languageName: node - linkType: hard - -"json5@npm:^1.0.2": - version: 1.0.2 - resolution: "json5@npm:1.0.2" - dependencies: - minimist: "npm:^1.2.0" - bin: - json5: lib/cli.js - checksum: 10c0/9ee316bf21f000b00752e6c2a3b79ecf5324515a5c60ee88983a1910a45426b643a4f3461657586e8aeca87aaf96f0a519b0516d2ae527a6c3e7eed80f68717f - languageName: node - linkType: hard - -"json5@npm:^2.2.2, json5@npm:^2.2.3": - version: 2.2.3 - resolution: "json5@npm:2.2.3" - bin: - json5: lib/cli.js - checksum: 10c0/5a04eed94810fa55c5ea138b2f7a5c12b97c3750bc63d11e511dcecbfef758003861522a070c2272764ee0f4e3e323862f386945aeb5b85b87ee43f084ba586c - languageName: node - linkType: hard - -"jsonfile@npm:^4.0.0": - version: 4.0.0 - resolution: "jsonfile@npm:4.0.0" - dependencies: - graceful-fs: "npm:^4.1.6" - dependenciesMeta: - graceful-fs: - optional: true - checksum: 10c0/7dc94b628d57a66b71fb1b79510d460d662eb975b5f876d723f81549c2e9cd316d58a2ddf742b2b93a4fa6b17b2accaf1a738a0e2ea114bdfb13a32e5377e480 - languageName: node - linkType: hard - -"jsonfile@npm:^6.0.1": - version: 6.1.0 - resolution: "jsonfile@npm:6.1.0" - dependencies: - graceful-fs: "npm:^4.1.6" - universalify: "npm:^2.0.0" - dependenciesMeta: - graceful-fs: - optional: true - checksum: 10c0/4f95b5e8a5622b1e9e8f33c96b7ef3158122f595998114d1e7f03985649ea99cb3cd99ce1ed1831ae94c8c8543ab45ebd044207612f31a56fd08462140e46865 - languageName: node - linkType: hard - -"jsx-ast-utils@npm:^2.4.1 || ^3.0.0, jsx-ast-utils@npm:^3.3.5": - version: 3.3.5 - resolution: "jsx-ast-utils@npm:3.3.5" - dependencies: - array-includes: "npm:^3.1.6" - array.prototype.flat: "npm:^1.3.1" - object.assign: "npm:^4.1.4" - object.values: "npm:^1.1.6" - checksum: 10c0/a32679e9cb55469cb6d8bbc863f7d631b2c98b7fc7bf172629261751a6e7bc8da6ae374ddb74d5fbd8b06cf0eb4572287b259813d92b36e384024ed35e4c13e1 - languageName: node - linkType: hard - -"jwt-decode@npm:^4.0.0": - version: 4.0.0 - resolution: "jwt-decode@npm:4.0.0" - checksum: 10c0/de75bbf89220746c388cf6a7b71e56080437b77d2edb29bae1c2155048b02c6b8c59a3e5e8d6ccdfd54f0b8bda25226e491a4f1b55ac5f8da04cfbadec4e546c - languageName: node - linkType: hard - -"keyv@npm:^4.5.3": - version: 4.5.4 - resolution: "keyv@npm:4.5.4" - dependencies: - json-buffer: "npm:3.0.1" - checksum: 10c0/aa52f3c5e18e16bb6324876bb8b59dd02acf782a4b789c7b2ae21107fab95fab3890ed448d4f8dba80ce05391eeac4bfabb4f02a20221342982f806fa2cf271e - languageName: node - linkType: hard - -"kleur@npm:^3.0.3": - version: 3.0.3 - resolution: "kleur@npm:3.0.3" - checksum: 10c0/cd3a0b8878e7d6d3799e54340efe3591ca787d9f95f109f28129bdd2915e37807bf8918bb295ab86afb8c82196beec5a1adcaf29042ce3f2bd932b038fe3aa4b - languageName: node - linkType: hard - -"knip@npm:^5.86.0": - version: 5.88.1 - resolution: "knip@npm:5.88.1" - dependencies: - "@nodelib/fs.walk": "npm:^1.2.3" - fast-glob: "npm:^3.3.3" - formatly: "npm:^0.3.0" - jiti: "npm:^2.6.0" - minimist: "npm:^1.2.8" - oxc-resolver: "npm:^11.19.1" - picocolors: "npm:^1.1.1" - picomatch: "npm:^4.0.1" - smol-toml: "npm:^1.5.2" - strip-json-comments: "npm:5.0.3" - unbash: "npm:^2.2.0" - yaml: "npm:^2.8.2" - zod: "npm:^4.1.11" - peerDependencies: - "@types/node": ">=18" - typescript: ">=5.0.4 <7" - bin: - knip: bin/knip.js - knip-bun: bin/knip-bun.js - checksum: 10c0/79a34e1d8e5bf5ead2b98a83159ce897e87c0de136a30eebe34ac61c6c465a61d0f6d1177cd76f69bda7939248d5c56611f8c52e8bcb5400d93964b908968ced - languageName: node - linkType: hard - -"language-subtag-registry@npm:^0.3.20": - version: 0.3.23 - resolution: "language-subtag-registry@npm:0.3.23" - checksum: 10c0/e9b05190421d2cd36dd6c95c28673019c927947cb6d94f40ba7e77a838629ee9675c94accf897fbebb07923187deb843b8fbb8935762df6edafe6c28dcb0b86c - languageName: node - linkType: hard - -"language-tags@npm:^1.0.9": - version: 1.0.9 - resolution: "language-tags@npm:1.0.9" - dependencies: - language-subtag-registry: "npm:^0.3.20" - checksum: 10c0/9ab911213c4bd8bd583c850201c17794e52cb0660d1ab6e32558aadc8324abebf6844e46f92b80a5d600d0fbba7eface2c207bfaf270a1c7fd539e4c3a880bff - languageName: node - linkType: hard - -"lead@npm:^4.0.0": - version: 4.0.0 - resolution: "lead@npm:4.0.0" - checksum: 10c0/71d2509b3c921dc74c47561a3c7bf0b76ecb530af178c3e0f469f3bdf20940ca08bcb4f18bbcfde0619706c1e550d3ba67ea187407722304db8fd3bc13a4405d - languageName: node - linkType: hard - -"levn@npm:^0.4.1": - version: 0.4.1 - resolution: "levn@npm:0.4.1" - dependencies: - prelude-ls: "npm:^1.2.1" - type-check: "npm:~0.4.0" - checksum: 10c0/effb03cad7c89dfa5bd4f6989364bfc79994c2042ec5966cb9b95990e2edee5cd8969ddf42616a0373ac49fac1403437deaf6e9050fbbaa3546093a59b9ac94e - languageName: node - linkType: hard - -"lightningcss-android-arm64@npm:1.32.0": - version: 1.32.0 - resolution: "lightningcss-android-arm64@npm:1.32.0" - conditions: os=android & cpu=arm64 - languageName: node - linkType: hard - -"lightningcss-darwin-arm64@npm:1.32.0": - version: 1.32.0 - resolution: "lightningcss-darwin-arm64@npm:1.32.0" - conditions: os=darwin & cpu=arm64 - languageName: node - linkType: hard - -"lightningcss-darwin-x64@npm:1.32.0": - version: 1.32.0 - resolution: "lightningcss-darwin-x64@npm:1.32.0" - conditions: os=darwin & cpu=x64 - languageName: node - linkType: hard - -"lightningcss-freebsd-x64@npm:1.32.0": - version: 1.32.0 - resolution: "lightningcss-freebsd-x64@npm:1.32.0" - conditions: os=freebsd & cpu=x64 - languageName: node - linkType: hard - -"lightningcss-linux-arm-gnueabihf@npm:1.32.0": - version: 1.32.0 - resolution: "lightningcss-linux-arm-gnueabihf@npm:1.32.0" - conditions: os=linux & cpu=arm - languageName: node - linkType: hard - -"lightningcss-linux-arm64-gnu@npm:1.32.0": - version: 1.32.0 - resolution: "lightningcss-linux-arm64-gnu@npm:1.32.0" - conditions: os=linux & cpu=arm64 & libc=glibc - languageName: node - linkType: hard - -"lightningcss-linux-arm64-musl@npm:1.32.0": - version: 1.32.0 - resolution: "lightningcss-linux-arm64-musl@npm:1.32.0" - conditions: os=linux & cpu=arm64 & libc=musl - languageName: node - linkType: hard - -"lightningcss-linux-x64-gnu@npm:1.32.0": - version: 1.32.0 - resolution: "lightningcss-linux-x64-gnu@npm:1.32.0" - conditions: os=linux & cpu=x64 & libc=glibc - languageName: node - linkType: hard - -"lightningcss-linux-x64-musl@npm:1.32.0": - version: 1.32.0 - resolution: "lightningcss-linux-x64-musl@npm:1.32.0" - conditions: os=linux & cpu=x64 & libc=musl - languageName: node - linkType: hard - -"lightningcss-win32-arm64-msvc@npm:1.32.0": - version: 1.32.0 - resolution: "lightningcss-win32-arm64-msvc@npm:1.32.0" - conditions: os=win32 & cpu=arm64 - languageName: node - linkType: hard - -"lightningcss-win32-x64-msvc@npm:1.32.0": - version: 1.32.0 - resolution: "lightningcss-win32-x64-msvc@npm:1.32.0" - conditions: os=win32 & cpu=x64 - languageName: node - linkType: hard - -"lightningcss@npm:^1.32.0": - version: 1.32.0 - resolution: "lightningcss@npm:1.32.0" - dependencies: - detect-libc: "npm:^2.0.3" - lightningcss-android-arm64: "npm:1.32.0" - lightningcss-darwin-arm64: "npm:1.32.0" - lightningcss-darwin-x64: "npm:1.32.0" - lightningcss-freebsd-x64: "npm:1.32.0" - lightningcss-linux-arm-gnueabihf: "npm:1.32.0" - lightningcss-linux-arm64-gnu: "npm:1.32.0" - lightningcss-linux-arm64-musl: "npm:1.32.0" - lightningcss-linux-x64-gnu: "npm:1.32.0" - lightningcss-linux-x64-musl: "npm:1.32.0" - lightningcss-win32-arm64-msvc: "npm:1.32.0" - lightningcss-win32-x64-msvc: "npm:1.32.0" - dependenciesMeta: - lightningcss-android-arm64: - optional: true - lightningcss-darwin-arm64: - optional: true - lightningcss-darwin-x64: - optional: true - lightningcss-freebsd-x64: - optional: true - lightningcss-linux-arm-gnueabihf: - optional: true - lightningcss-linux-arm64-gnu: - optional: true - lightningcss-linux-arm64-musl: - optional: true - lightningcss-linux-x64-gnu: - optional: true - lightningcss-linux-x64-musl: - optional: true - lightningcss-win32-arm64-msvc: - optional: true - lightningcss-win32-x64-msvc: - optional: true - checksum: 10c0/70945bd55097af46fc9fab7f5ed09cd5869d85940a2acab7ee06d0117004a1d68155708a2d462531cea2fc3c67aefc9333a7068c80b0b78dd404c16838809e03 - languageName: node - linkType: hard - -"lilconfig@npm:^3.1.3": - version: 3.1.3 - resolution: "lilconfig@npm:3.1.3" - checksum: 10c0/f5604e7240c5c275743561442fbc5abf2a84ad94da0f5adc71d25e31fa8483048de3dcedcb7a44112a942fed305fd75841cdf6c9681c7f640c63f1049e9a5dcc - languageName: node - linkType: hard - -"lines-and-columns@npm:^1.1.6": - version: 1.2.4 - resolution: "lines-and-columns@npm:1.2.4" - checksum: 10c0/3da6ee62d4cd9f03f5dc90b4df2540fb85b352081bee77fe4bbcd12c9000ead7f35e0a38b8d09a9bb99b13223446dd8689ff3c4959807620726d788701a83d2d - languageName: node - linkType: hard - -"livekit-client@npm:^2.18.1": - version: 2.18.3 - resolution: "livekit-client@npm:2.18.3" - dependencies: - "@livekit/mutex": "npm:1.1.1" - "@livekit/protocol": "npm:1.45.3" - events: "npm:^3.3.0" - jose: "npm:^6.1.0" - loglevel: "npm:^1.9.2" - sdp-transform: "npm:^2.15.0" - tslib: "npm:2.8.1" - typed-emitter: "npm:^2.1.0" - webrtc-adapter: "npm:^9.0.1" - peerDependencies: - "@types/dom-mediacapture-record": ^1 - checksum: 10c0/8240e0f971f50dcf96a65938208769fac79da8da944e30a63d2c358ae090c0c66f0363201aed5d772c43a67276cf2a4b33dfc2d8c12460f5ef4611f97d7596fc - languageName: node - linkType: hard - -"locate-path@npm:^5.0.0": - version: 5.0.0 - resolution: "locate-path@npm:5.0.0" - dependencies: - p-locate: "npm:^4.1.0" - checksum: 10c0/33a1c5247e87e022f9713e6213a744557a3e9ec32c5d0b5efb10aa3a38177615bf90221a5592674857039c1a0fd2063b82f285702d37b792d973e9e72ace6c59 - languageName: node - linkType: hard - -"locate-path@npm:^6.0.0": - version: 6.0.0 - resolution: "locate-path@npm:6.0.0" - dependencies: - p-locate: "npm:^5.0.0" - checksum: 10c0/d3972ab70dfe58ce620e64265f90162d247e87159b6126b01314dd67be43d50e96a50b517bce2d9452a79409c7614054c277b5232377de50416564a77ac7aad3 - languageName: node - linkType: hard - -"lodash-es@npm:^4.17.21": - version: 4.18.1 - resolution: "lodash-es@npm:4.18.1" - checksum: 10c0/35d4dcf87ef07f8d090f409447575800108057e360b445f590d0d25d09e3d1e33a163d2fc100d4d072b0f901d5e2fc533cd7c4bfd8eeb38a06abec693823c8b8 - languageName: node - linkType: hard - -"lodash.debounce@npm:^4.0.8": - version: 4.0.8 - resolution: "lodash.debounce@npm:4.0.8" - checksum: 10c0/762998a63e095412b6099b8290903e0a8ddcb353ac6e2e0f2d7e7d03abd4275fe3c689d88960eb90b0dde4f177554d51a690f22a343932ecbc50a5d111849987 - languageName: node - linkType: hard - -"lodash.merge@npm:^4.6.2": - version: 4.6.2 - resolution: "lodash.merge@npm:4.6.2" - checksum: 10c0/402fa16a1edd7538de5b5903a90228aa48eb5533986ba7fa26606a49db2572bf414ff73a2c9f5d5fd36b31c46a5d5c7e1527749c07cbcf965ccff5fbdf32c506 - languageName: node - linkType: hard - -"loglevel@npm:1.9.1": - version: 1.9.1 - resolution: "loglevel@npm:1.9.1" - checksum: 10c0/152f0501cea367cf998c844a38b19f0b5af555756ad7d8650214a1f8c6a5b045e31b8cf5dae27d28339a061624ce3f618aadb333aed386cac041d6ddc5101a39 - languageName: node - linkType: hard - -"loglevel@npm:^1.9.1, loglevel@npm:^1.9.2": - version: 1.9.2 - resolution: "loglevel@npm:1.9.2" - checksum: 10c0/1e317fa4648fe0b4a4cffef6de037340592cee8547b07d4ce97a487abe9153e704b98451100c799b032c72bb89c9366d71c9fb8192ada8703269263ae77acdc7 - languageName: node - linkType: hard - -"loose-envify@npm:^1.4.0": - version: 1.4.0 - resolution: "loose-envify@npm:1.4.0" - dependencies: - js-tokens: "npm:^3.0.0 || ^4.0.0" - bin: - loose-envify: cli.js - checksum: 10c0/655d110220983c1a4b9c0c679a2e8016d4b67f6e9c7b5435ff5979ecdb20d0813f4dec0a08674fcbdd4846a3f07edbb50a36811fd37930b94aaa0d9daceb017e - languageName: node - linkType: hard - -"loupe@npm:^3.1.0, loupe@npm:^3.1.4": - version: 3.2.1 - resolution: "loupe@npm:3.2.1" - checksum: 10c0/910c872cba291309664c2d094368d31a68907b6f5913e989d301b5c25f30e97d76d77f23ab3bf3b46d0f601ff0b6af8810c10c31b91d2c6b2f132809ca2cc705 - languageName: node - linkType: hard - -"lower-case@npm:^2.0.2": - version: 2.0.2 - resolution: "lower-case@npm:2.0.2" - dependencies: - tslib: "npm:^2.0.3" - checksum: 10c0/3d925e090315cf7dc1caa358e0477e186ffa23947740e4314a7429b6e62d72742e0bbe7536a5ae56d19d7618ce998aba05caca53c2902bd5742fdca5fc57fd7b - languageName: node - linkType: hard - -"lru-cache@npm:^10.0.1, lru-cache@npm:^10.2.0": - version: 10.4.3 - resolution: "lru-cache@npm:10.4.3" - checksum: 10c0/ebd04fbca961e6c1d6c0af3799adcc966a1babe798f685bb84e6599266599cd95d94630b10262f5424539bc4640107e8a33aa28585374abf561d30d16f4b39fb - languageName: node - linkType: hard - -"lru-cache@npm:^11.0.2": - version: 11.0.2 - resolution: "lru-cache@npm:11.0.2" - checksum: 10c0/c993b8e06ead0b24b969c1dbb5b301716aed66e320e9014a80012f5febe280b438f28ff50046b2c55ff404e889351ccb332ff91f8dd175a21f5eae80e3fb155f - languageName: node - linkType: hard - -"lru-cache@npm:^5.1.1": - version: 5.1.1 - resolution: "lru-cache@npm:5.1.1" - dependencies: - yallist: "npm:^3.0.2" - checksum: 10c0/89b2ef2ef45f543011e38737b8a8622a2f8998cddf0e5437174ef8f1f70a8b9d14a918ab3e232cb3ba343b7abddffa667f0b59075b2b80e6b4d63c3de6127482 - languageName: node - linkType: hard - -"lz-string@npm:^1.5.0": - version: 1.5.0 - resolution: "lz-string@npm:1.5.0" - bin: - lz-string: bin/bin.js - checksum: 10c0/36128e4de34791838abe979b19927c26e67201ca5acf00880377af7d765b38d1c60847e01c5ec61b1a260c48029084ab3893a3925fd6e48a04011364b089991b - languageName: node - linkType: hard - -"magic-string@npm:0.30.8": - version: 0.30.8 - resolution: "magic-string@npm:0.30.8" - dependencies: - "@jridgewell/sourcemap-codec": "npm:^1.4.15" - checksum: 10c0/51a1f06f678c082aceddfb5943de9b6bdb88f2ea1385a1c2adf116deb73dfcfa50df6c222901d691b529455222d4d68d0b28be5689ac6f69b3baa3462861f922 - languageName: node - linkType: hard - -"magic-string@npm:^0.30.0, magic-string@npm:^0.30.21, magic-string@npm:^0.30.3": - version: 0.30.21 - resolution: "magic-string@npm:0.30.21" - dependencies: - "@jridgewell/sourcemap-codec": "npm:^1.5.5" - checksum: 10c0/299378e38f9a270069fc62358522ddfb44e94244baa0d6a8980ab2a9b2490a1d03b236b447eee309e17eb3bddfa482c61259d47960eb018a904f0ded52780c4a - languageName: node - linkType: hard - -"magicast@npm:^0.5.2": - version: 0.5.2 - resolution: "magicast@npm:0.5.2" - dependencies: - "@babel/parser": "npm:^7.29.0" - "@babel/types": "npm:^7.29.0" - source-map-js: "npm:^1.2.1" - checksum: 10c0/924af677643c5a0a7d6cdb3247c0eb96fa7611b2ba6a5e720d35d81c503d3d9f5948eb5227f80f90f82ea3e7d38cffd10bb988f3fc09020db428e14f26e960d7 - languageName: node - linkType: hard - -"make-dir@npm:^4.0.0": - version: 4.0.0 - resolution: "make-dir@npm:4.0.0" - dependencies: - semver: "npm:^7.5.3" - checksum: 10c0/69b98a6c0b8e5c4fe9acb61608a9fbcfca1756d910f51e5dbe7a9e5cfb74fca9b8a0c8a0ffdf1294a740826c1ab4871d5bf3f62f72a3049e5eac6541ddffed68 - languageName: node - linkType: hard - -"make-fetch-happen@npm:^14.0.3": - version: 14.0.3 - resolution: "make-fetch-happen@npm:14.0.3" - dependencies: - "@npmcli/agent": "npm:^3.0.0" - cacache: "npm:^19.0.1" - http-cache-semantics: "npm:^4.1.1" - minipass: "npm:^7.0.2" - minipass-fetch: "npm:^4.0.0" - minipass-flush: "npm:^1.0.5" - minipass-pipeline: "npm:^1.2.4" - negotiator: "npm:^1.0.0" - proc-log: "npm:^5.0.0" - promise-retry: "npm:^2.0.1" - ssri: "npm:^12.0.0" - checksum: 10c0/c40efb5e5296e7feb8e37155bde8eb70bc57d731b1f7d90e35a092fde403d7697c56fb49334d92d330d6f1ca29a98142036d6480a12681133a0a1453164cb2f0 - languageName: node - linkType: hard - -"matcher-collection@npm:^2.0.0": - version: 2.0.1 - resolution: "matcher-collection@npm:2.0.1" - dependencies: - "@types/minimatch": "npm:^3.0.3" - minimatch: "npm:^3.0.2" - checksum: 10c0/409aad220000e2041672f900883ec66ffdd04814b133b428a8d35e055495fc09bb9024ca6ad7a63ebe6ed9e480e01db02c3edf3587ae1ba2627727a3d896ff96 - languageName: node - linkType: hard - -"math-intrinsics@npm:^1.1.0": - version: 1.1.0 - resolution: "math-intrinsics@npm:1.1.0" - checksum: 10c0/7579ff94e899e2f76ab64491d76cf606274c874d8f2af4a442c016bd85688927fcfca157ba6bf74b08e9439dc010b248ce05b96cc7c126a354c3bae7fcb48b7f - languageName: node - linkType: hard - -"matrix-events-sdk@npm:0.0.1": - version: 0.0.1 - resolution: "matrix-events-sdk@npm:0.0.1" - checksum: 10c0/b2a248b669f88426e08e19ad105ba7f8ae404fae0e1c6d778e7c95e80aa4b29a77ef76d55513765b0ec7cf3942380cd03604618816f625469ea07661ceca1292 - languageName: node - linkType: hard - -"matrix-js-sdk@matrix-org/matrix-js-sdk#6e3efef0c5f660df47cf00874927dec1c75cc3cf": - version: 40.1.0 - resolution: "matrix-js-sdk@https://github.com/matrix-org/matrix-js-sdk.git#commit=6e3efef0c5f660df47cf00874927dec1c75cc3cf" - dependencies: - "@babel/runtime": "npm:^7.12.5" - "@matrix-org/matrix-sdk-crypto-wasm": "npm:^17.0.0" - another-json: "npm:^0.2.0" - bs58: "npm:^6.0.0" - content-type: "npm:^1.0.4" - jwt-decode: "npm:^4.0.0" - loglevel: "npm:^1.9.2" - matrix-events-sdk: "npm:0.0.1" - matrix-widget-api: "npm:^1.16.1" - oidc-client-ts: "npm:^3.0.1" - p-retry: "npm:7" - sdp-transform: "npm:^3.0.0" - unhomoglyph: "npm:^1.0.6" - uuid: "npm:13" - checksum: 10c0/2c4db56fd0164d801c2f125ab2a442e3659314d4cc2fd640ea152b829d0db8b05ff808020e387a761afde4ff7a07b271c25431337de9f7c765c523c8cd837e36 - languageName: node - linkType: hard - -"matrix-widget-api@npm:^1.16.1": - version: 1.17.0 - resolution: "matrix-widget-api@npm:1.17.0" - dependencies: - "@types/events": "npm:^3.0.0" - events: "npm:^3.2.0" - checksum: 10c0/3651c860900149ecc2fe74640b47687bab8a347eb718a522085189e2b84efe462c9d81c1e8caff08d122f0b3e9cef8303a5802837673e5c9b465f7624c56a8f3 - languageName: node - linkType: hard - -"md5.js@npm:^1.3.4": - version: 1.3.5 - resolution: "md5.js@npm:1.3.5" - dependencies: - hash-base: "npm:^3.0.0" - inherits: "npm:^2.0.1" - safe-buffer: "npm:^5.1.2" - checksum: 10c0/b7bd75077f419c8e013fc4d4dada48be71882e37d69a44af65a2f2804b91e253441eb43a0614423a1c91bb830b8140b0dc906bc797245e2e275759584f4efcc5 - languageName: node - linkType: hard - -"merge2@npm:^1.3.0, merge2@npm:^1.4.1": - version: 1.4.1 - resolution: "merge2@npm:1.4.1" - checksum: 10c0/254a8a4605b58f450308fc474c82ac9a094848081bf4c06778200207820e5193726dc563a0d2c16468810516a5c97d9d3ea0ca6585d23c58ccfff2403e8dbbeb - languageName: node - linkType: hard - -"micromatch@npm:^4.0.4, micromatch@npm:^4.0.5, micromatch@npm:^4.0.8": - version: 4.0.8 - resolution: "micromatch@npm:4.0.8" - dependencies: - braces: "npm:^3.0.3" - picomatch: "npm:^2.3.1" - checksum: 10c0/166fa6eb926b9553f32ef81f5f531d27b4ce7da60e5baf8c021d043b27a388fb95e46a8038d5045877881e673f8134122b59624d5cecbd16eb50a42e7a6b5ca8 - languageName: node - linkType: hard - -"miller-rabin@npm:^4.0.0": - version: 4.0.1 - resolution: "miller-rabin@npm:4.0.1" - dependencies: - bn.js: "npm:^4.0.0" - brorand: "npm:^1.0.1" - bin: - miller-rabin: bin/miller-rabin - checksum: 10c0/26b2b96f6e49dbcff7faebb78708ed2f5f9ae27ac8cbbf1d7c08f83cf39bed3d418c0c11034dce997da70d135cc0ff6f3a4c15dc452f8e114c11986388a64346 - languageName: node - linkType: hard - -"mime-db@npm:1.52.0": - version: 1.52.0 - resolution: "mime-db@npm:1.52.0" - checksum: 10c0/0557a01deebf45ac5f5777fe7740b2a5c309c6d62d40ceab4e23da9f821899ce7a900b7ac8157d4548ddbb7beffe9abc621250e6d182b0397ec7f10c7b91a5aa - languageName: node - linkType: hard - -"mime-types@npm:^2.1.35": - version: 2.1.35 - resolution: "mime-types@npm:2.1.35" - dependencies: - mime-db: "npm:1.52.0" - checksum: 10c0/82fb07ec56d8ff1fc999a84f2f217aa46cb6ed1033fefaabd5785b9a974ed225c90dc72fff460259e66b95b73648596dbcc50d51ed69cdf464af2d237d3149b2 - languageName: node - linkType: hard - -"min-indent@npm:^1.0.0": - version: 1.0.1 - resolution: "min-indent@npm:1.0.1" - checksum: 10c0/7e207bd5c20401b292de291f02913230cb1163abca162044f7db1d951fa245b174dc00869d40dd9a9f32a885ad6a5f3e767ee104cf278f399cb4e92d3f582d5c - languageName: node - linkType: hard - -"minimalistic-assert@npm:^1.0.0, minimalistic-assert@npm:^1.0.1": - version: 1.0.1 - resolution: "minimalistic-assert@npm:1.0.1" - checksum: 10c0/96730e5601cd31457f81a296f521eb56036e6f69133c0b18c13fe941109d53ad23a4204d946a0d638d7f3099482a0cec8c9bb6d642604612ce43ee536be3dddd - languageName: node - linkType: hard - -"minimalistic-crypto-utils@npm:^1.0.1": - version: 1.0.1 - resolution: "minimalistic-crypto-utils@npm:1.0.1" - checksum: 10c0/790ecec8c5c73973a4fbf2c663d911033e8494d5fb0960a4500634766ab05d6107d20af896ca2132e7031741f19888154d44b2408ada0852446705441383e9f8 - languageName: node - linkType: hard - -"minimatch@npm:^10.2.3": - version: 10.2.4 - resolution: "minimatch@npm:10.2.4" - dependencies: - brace-expansion: "npm:^5.0.2" - checksum: 10c0/35f3dfb7b99b51efd46afd378486889f590e7efb10e0f6a10ba6800428cf65c9a8dedb74427d0570b318d749b543dc4e85f06d46d2858bc8cac7e1eb49a95945 - languageName: node - linkType: hard - -"minimist@npm:^1.2.0, minimist@npm:^1.2.6, minimist@npm:^1.2.8": - version: 1.2.8 - resolution: "minimist@npm:1.2.8" - checksum: 10c0/19d3fcdca050087b84c2029841a093691a91259a47def2f18222f41e7645a0b7c44ef4b40e88a1e58a40c84d2ef0ee6047c55594d298146d0eb3f6b737c20ce6 - languageName: node - linkType: hard - -"minipass-collect@npm:^2.0.1": - version: 2.0.1 - resolution: "minipass-collect@npm:2.0.1" - dependencies: - minipass: "npm:^7.0.3" - checksum: 10c0/5167e73f62bb74cc5019594709c77e6a742051a647fe9499abf03c71dca75515b7959d67a764bdc4f8b361cf897fbf25e2d9869ee039203ed45240f48b9aa06e - languageName: node - linkType: hard - -"minipass-fetch@npm:^4.0.0": - version: 4.0.1 - resolution: "minipass-fetch@npm:4.0.1" - dependencies: - encoding: "npm:^0.1.13" - minipass: "npm:^7.0.3" - minipass-sized: "npm:^1.0.3" - minizlib: "npm:^3.0.1" - dependenciesMeta: - encoding: - optional: true - checksum: 10c0/a3147b2efe8e078c9bf9d024a0059339c5a09c5b1dded6900a219c218cc8b1b78510b62dae556b507304af226b18c3f1aeb1d48660283602d5b6586c399eed5c - languageName: node - linkType: hard - -"minipass-flush@npm:^1.0.5": - version: 1.0.5 - resolution: "minipass-flush@npm:1.0.5" - dependencies: - minipass: "npm:^3.0.0" - checksum: 10c0/2a51b63feb799d2bb34669205eee7c0eaf9dce01883261a5b77410c9408aa447e478efd191b4de6fc1101e796ff5892f8443ef20d9544385819093dbb32d36bd - languageName: node - linkType: hard - -"minipass-pipeline@npm:^1.2.4": - version: 1.2.4 - resolution: "minipass-pipeline@npm:1.2.4" - dependencies: - minipass: "npm:^3.0.0" - checksum: 10c0/cbda57cea20b140b797505dc2cac71581a70b3247b84480c1fed5ca5ba46c25ecc25f68bfc9e6dcb1a6e9017dab5c7ada5eab73ad4f0a49d84e35093e0c643f2 - languageName: node - linkType: hard - -"minipass-sized@npm:^1.0.3": - version: 1.0.3 - resolution: "minipass-sized@npm:1.0.3" - dependencies: - minipass: "npm:^3.0.0" - checksum: 10c0/298f124753efdc745cfe0f2bdfdd81ba25b9f4e753ca4a2066eb17c821f25d48acea607dfc997633ee5bf7b6dfffb4eee4f2051eb168663f0b99fad2fa4829cb - languageName: node - linkType: hard - -"minipass@npm:^3.0.0": - version: 3.3.6 - resolution: "minipass@npm:3.3.6" - dependencies: - yallist: "npm:^4.0.0" - checksum: 10c0/a114746943afa1dbbca8249e706d1d38b85ed1298b530f5808ce51f8e9e941962e2a5ad2e00eae7dd21d8a4aae6586a66d4216d1a259385e9d0358f0c1eba16c - languageName: node - linkType: hard - -"minipass@npm:^5.0.0 || ^6.0.2 || ^7.0.0, minipass@npm:^7.0.2, minipass@npm:^7.0.3, minipass@npm:^7.0.4, minipass@npm:^7.1.2": - version: 7.1.2 - resolution: "minipass@npm:7.1.2" - checksum: 10c0/b0fd20bb9fb56e5fa9a8bfac539e8915ae07430a619e4b86ff71f5fc757ef3924b23b2c4230393af1eda647ed3d75739e4e0acb250a6b1eb277cf7f8fe449557 - languageName: node - linkType: hard - -"minizlib@npm:^3.0.1": - version: 3.0.1 - resolution: "minizlib@npm:3.0.1" - dependencies: - minipass: "npm:^7.0.4" - rimraf: "npm:^5.0.5" - checksum: 10c0/82f8bf70da8af656909a8ee299d7ed3b3372636749d29e105f97f20e88971be31f5ed7642f2e898f00283b68b701cc01307401cdc209b0efc5dd3818220e5093 - languageName: node - linkType: hard - -"minizlib@npm:^3.1.0": - version: 3.1.0 - resolution: "minizlib@npm:3.1.0" - dependencies: - minipass: "npm:^7.1.2" - checksum: 10c0/5aad75ab0090b8266069c9aabe582c021ae53eb33c6c691054a13a45db3b4f91a7fb1bd79151e6b4e9e9a86727b522527c0a06ec7d45206b745d54cd3097bcec - languageName: node - linkType: hard - -"mktemp@npm:~0.4.0": - version: 0.4.0 - resolution: "mktemp@npm:0.4.0" - checksum: 10c0/c3777c23492673668a82838f41485531b7b3c9a4430e9daef469371092f9a8d4df84cab05af07c8ab08a407466baf348566c5fd9da702d6f9d917526a6c02809 - languageName: node - linkType: hard - -"ms@npm:2.0.0": - version: 2.0.0 - resolution: "ms@npm:2.0.0" - checksum: 10c0/f8fda810b39fd7255bbdc451c46286e549794fcc700dc9cd1d25658bbc4dc2563a5de6fe7c60f798a16a60c6ceb53f033cb353f493f0cf63e5199b702943159d - languageName: node - linkType: hard - -"ms@npm:^2.1.1, ms@npm:^2.1.3": - version: 2.1.3 - resolution: "ms@npm:2.1.3" - checksum: 10c0/d924b57e7312b3b63ad21fc5b3dc0af5e78d61a1fc7cfb5457edaf26326bf62be5307cc87ffb6862ef1c2b33b0233cdb5d4f01c4c958cc0d660948b65a287a48 - languageName: node - linkType: hard - -"nanoid@npm:^3.3.11": - version: 3.3.11 - resolution: "nanoid@npm:3.3.11" - bin: - nanoid: bin/nanoid.cjs - checksum: 10c0/40e7f70b3d15f725ca072dfc4f74e81fcf1fbb02e491cf58ac0c79093adc9b0a73b152bcde57df4b79cd097e13023d7504acb38404a4da7bc1cd8e887b82fe0b - languageName: node - linkType: hard - -"natural-compare@npm:^1.4.0": - version: 1.4.0 - resolution: "natural-compare@npm:1.4.0" - checksum: 10c0/f5f9a7974bfb28a91afafa254b197f0f22c684d4a1731763dda960d2c8e375b36c7d690e0d9dc8fba774c537af14a7e979129bca23d88d052fbeb9466955e447 - languageName: node - linkType: hard - -"negotiator@npm:^1.0.0": - version: 1.0.0 - resolution: "negotiator@npm:1.0.0" - checksum: 10c0/4c559dd52669ea48e1914f9d634227c561221dd54734070791f999c52ed0ff36e437b2e07d5c1f6e32909fc625fe46491c16e4a8f0572567d4dd15c3a4fda04b - languageName: node - linkType: hard - -"no-case@npm:^3.0.4": - version: 3.0.4 - resolution: "no-case@npm:3.0.4" - dependencies: - lower-case: "npm:^2.0.2" - tslib: "npm:^2.0.3" - checksum: 10c0/8ef545f0b3f8677c848f86ecbd42ca0ff3cd9dd71c158527b344c69ba14710d816d8489c746b6ca225e7b615108938a0bda0a54706f8c255933703ac1cf8e703 - languageName: node - linkType: hard - -"node-addon-api@npm:^7.0.0": - version: 7.1.1 - resolution: "node-addon-api@npm:7.1.1" - dependencies: - node-gyp: "npm:latest" - checksum: 10c0/fb32a206276d608037fa1bcd7e9921e177fe992fc610d098aa3128baca3c0050fc1e014fa007e9b3874cf865ddb4f5bd9f43ccb7cbbbe4efaff6a83e920b17e9 - languageName: node - linkType: hard - -"node-fetch@npm:^2.6.7": - version: 2.7.0 - resolution: "node-fetch@npm:2.7.0" - dependencies: - whatwg-url: "npm:^5.0.0" - peerDependencies: - encoding: ^0.1.0 - peerDependenciesMeta: - encoding: - optional: true - checksum: 10c0/b55786b6028208e6fbe594ccccc213cab67a72899c9234eb59dba51062a299ea853210fcf526998eaa2867b0963ad72338824450905679ff0fa304b8c5093ae8 - languageName: node - linkType: hard - -"node-gyp@npm:latest": - version: 11.1.0 - resolution: "node-gyp@npm:11.1.0" - dependencies: - env-paths: "npm:^2.2.0" - exponential-backoff: "npm:^3.1.1" - glob: "npm:^10.3.10" - graceful-fs: "npm:^4.2.6" - make-fetch-happen: "npm:^14.0.3" - nopt: "npm:^8.0.0" - proc-log: "npm:^5.0.0" - semver: "npm:^7.3.5" - tar: "npm:^7.4.3" - which: "npm:^5.0.0" - bin: - node-gyp: bin/node-gyp.js - checksum: 10c0/c38977ce502f1ea41ba2b8721bd5b49bc3d5b3f813eabfac8414082faf0620ccb5211e15c4daecc23ed9f5e3e9cc4da00e575a0bcfc2a95a069294f2afa1e0cd - languageName: node - linkType: hard - -"node-html-parser@npm:^5.3.3": - version: 5.4.2 - resolution: "node-html-parser@npm:5.4.2" - dependencies: - css-select: "npm:^4.2.1" - he: "npm:1.2.0" - checksum: 10c0/5a46ce4dc29dcb656067a977ef977d09328b21d1e26e6105176230bb151970cf7deb2db0dd084abeb98106ac79a83102232ad0d9a45d0a686f3eb6931a048663 - languageName: node - linkType: hard - -"node-releases@npm:^2.0.19": - version: 2.0.19 - resolution: "node-releases@npm:2.0.19" - checksum: 10c0/52a0dbd25ccf545892670d1551690fe0facb6a471e15f2cfa1b20142a5b255b3aa254af5f59d6ecb69c2bec7390bc643c43aa63b13bf5e64b6075952e716b1aa - languageName: node - linkType: hard - -"node-releases@npm:^2.0.27": - version: 2.0.27 - resolution: "node-releases@npm:2.0.27" - checksum: 10c0/f1e6583b7833ea81880627748d28a3a7ff5703d5409328c216ae57befbced10ce2c991bea86434e8ec39003bd017f70481e2e5f8c1f7e0a7663241f81d6e00e2 - languageName: node - linkType: hard - -"node-stdlib-browser@npm:^1.3.1": - version: 1.3.1 - resolution: "node-stdlib-browser@npm:1.3.1" - dependencies: - assert: "npm:^2.0.0" - browser-resolve: "npm:^2.0.0" - browserify-zlib: "npm:^0.2.0" - buffer: "npm:^5.7.1" - console-browserify: "npm:^1.1.0" - constants-browserify: "npm:^1.0.0" - create-require: "npm:^1.1.1" - crypto-browserify: "npm:^3.12.1" - domain-browser: "npm:4.22.0" - events: "npm:^3.0.0" - https-browserify: "npm:^1.0.0" - isomorphic-timers-promises: "npm:^1.0.1" - os-browserify: "npm:^0.3.0" - path-browserify: "npm:^1.0.1" - pkg-dir: "npm:^5.0.0" - process: "npm:^0.11.10" - punycode: "npm:^1.4.1" - querystring-es3: "npm:^0.2.1" - readable-stream: "npm:^3.6.0" - stream-browserify: "npm:^3.0.0" - stream-http: "npm:^3.2.0" - string_decoder: "npm:^1.0.0" - timers-browserify: "npm:^2.0.4" - tty-browserify: "npm:0.0.1" - url: "npm:^0.11.4" - util: "npm:^0.12.4" - vm-browserify: "npm:^1.0.1" - checksum: 10c0/5b0cb5d4499b1b1c73f54db3e9e69b2a3a8aebe2ead2e356b0a03c1dfca6b5c5d2f6516e24301e76dc7b68999b9d0ae3da6c3f1dec421eed80ad6cb9eec0f356 - languageName: node - linkType: hard - -"nopt@npm:^8.0.0": - version: 8.1.0 - resolution: "nopt@npm:8.1.0" - dependencies: - abbrev: "npm:^3.0.0" - bin: - nopt: bin/nopt.js - checksum: 10c0/62e9ea70c7a3eb91d162d2c706b6606c041e4e7b547cbbb48f8b3695af457dd6479904d7ace600856bf923dd8d1ed0696f06195c8c20f02ac87c1da0e1d315ef - languageName: node - linkType: hard - -"normalize-package-data@npm:^2.5.0": - version: 2.5.0 - resolution: "normalize-package-data@npm:2.5.0" - dependencies: - hosted-git-info: "npm:^2.1.4" - resolve: "npm:^1.10.0" - semver: "npm:2 || 3 || 4 || 5" - validate-npm-package-license: "npm:^3.0.1" - checksum: 10c0/357cb1646deb42f8eb4c7d42c4edf0eec312f3628c2ef98501963cc4bbe7277021b2b1d977f982b2edce78f5a1014613ce9cf38085c3df2d76730481357ca504 - languageName: node - linkType: hard - -"normalize-path@npm:3.0.0, normalize-path@npm:^3.0.0, normalize-path@npm:~3.0.0": - version: 3.0.0 - resolution: "normalize-path@npm:3.0.0" - checksum: 10c0/e008c8142bcc335b5e38cf0d63cfd39d6cf2d97480af9abdbe9a439221fd4d749763bab492a8ee708ce7a194bb00c9da6d0a115018672310850489137b3da046 - languageName: node - linkType: hard - -"normalize.css@npm:^8.0.1": - version: 8.0.1 - resolution: "normalize.css@npm:8.0.1" - checksum: 10c0/4ddf56d1af5ca755fa5e692e718316d8758ecb792aa96e1ad206824b5810a043763d681d6f7697d46573515f5e9690038b4c91a95c1997567128815545fb8cd7 - languageName: node - linkType: hard - -"now-and-later@npm:^3.0.0": - version: 3.0.0 - resolution: "now-and-later@npm:3.0.0" - dependencies: - once: "npm:^1.4.0" - checksum: 10c0/9ed96bae9f4bf66c01704a59aa5b6a8aa26bd65445133a08a2b867470c1705ae746f7261e4676b2ae6fc9dce0dc778055b816218bdeb1efbf610e0c95a83711b - languageName: node - linkType: hard - -"nth-check@npm:^2.0.1": - version: 2.1.1 - resolution: "nth-check@npm:2.1.1" - dependencies: - boolbase: "npm:^1.0.0" - checksum: 10c0/5fee7ff309727763689cfad844d979aedd2204a817fbaaf0e1603794a7c20db28548d7b024692f953557df6ce4a0ee4ae46cd8ebd9b36cfb300b9226b567c479 - languageName: node - linkType: hard - -"nwsapi@npm:^2.2.16": - version: 2.2.16 - resolution: "nwsapi@npm:2.2.16" - checksum: 10c0/0aa0637f4d51043d0183d994e08336bae996b03b42984381bf09ebdf3ff4909c018eda6b2a8aba0a08f3ea8303db8a0dad0608b38dc0bff15fd87017286ae21a - languageName: node - linkType: hard - -"object-assign@npm:^4.1.0, object-assign@npm:^4.1.1": - version: 4.1.1 - resolution: "object-assign@npm:4.1.1" - checksum: 10c0/1f4df9945120325d041ccf7b86f31e8bcc14e73d29171e37a7903050e96b81323784ec59f93f102ec635bcf6fa8034ba3ea0a8c7e69fa202b87ae3b6cec5a414 - languageName: node - linkType: hard - -"object-deep-merge@npm:^2.0.0": - version: 2.0.0 - resolution: "object-deep-merge@npm:2.0.0" - checksum: 10c0/69e8741131ad49fa8720fb96007a3c82dca1119b5d874151d2ecbcc3b44ccd46e8553c7a30b0abcba752c099ba361bbba97f33a68c9ae54c57eed7be116ffc97 - languageName: node - linkType: hard - -"object-inspect@npm:^1.13.3": - version: 1.13.3 - resolution: "object-inspect@npm:1.13.3" - checksum: 10c0/cc3f15213406be89ffdc54b525e115156086796a515410a8d390215915db9f23c8eab485a06f1297402f440a33715fe8f71a528c1dcbad6e1a3bcaf5a46921d4 - languageName: node - linkType: hard - -"object-inspect@npm:^1.13.4": - version: 1.13.4 - resolution: "object-inspect@npm:1.13.4" - checksum: 10c0/d7f8711e803b96ea3191c745d6f8056ce1f2496e530e6a19a0e92d89b0fa3c76d910c31f0aa270432db6bd3b2f85500a376a83aaba849a8d518c8845b3211692 - languageName: node - linkType: hard - -"object-is@npm:^1.1.5": - version: 1.1.6 - resolution: "object-is@npm:1.1.6" - dependencies: - call-bind: "npm:^1.0.7" - define-properties: "npm:^1.2.1" - checksum: 10c0/506af444c4dce7f8e31f34fc549e2fb8152d6b9c4a30c6e62852badd7f520b579c679af433e7a072f9d78eb7808d230dc12e1cf58da9154dfbf8813099ea0fe0 - languageName: node - linkType: hard - -"object-keys@npm:^1.1.1": - version: 1.1.1 - resolution: "object-keys@npm:1.1.1" - checksum: 10c0/b11f7ccdbc6d406d1f186cdadb9d54738e347b2692a14439ca5ac70c225fa6db46db809711b78589866d47b25fc3e8dee0b4c722ac751e11180f9380e3d8601d - languageName: node - linkType: hard - -"object.assign@npm:^4.1.4, object.assign@npm:^4.1.7": - version: 4.1.7 - resolution: "object.assign@npm:4.1.7" - dependencies: - call-bind: "npm:^1.0.8" - call-bound: "npm:^1.0.3" - define-properties: "npm:^1.2.1" - es-object-atoms: "npm:^1.0.0" - has-symbols: "npm:^1.1.0" - object-keys: "npm:^1.1.1" - checksum: 10c0/3b2732bd860567ea2579d1567525168de925a8d852638612846bd8082b3a1602b7b89b67b09913cbb5b9bd6e95923b2ae73580baa9d99cb4e990564e8cbf5ddc - languageName: node - linkType: hard - -"object.entries@npm:^1.1.9": - version: 1.1.9 - resolution: "object.entries@npm:1.1.9" - dependencies: - call-bind: "npm:^1.0.8" - call-bound: "npm:^1.0.4" - define-properties: "npm:^1.2.1" - es-object-atoms: "npm:^1.1.1" - checksum: 10c0/d4b8c1e586650407da03370845f029aa14076caca4e4d4afadbc69cfb5b78035fd3ee7be417141abdb0258fa142e59b11923b4c44d8b1255b28f5ffcc50da7db - languageName: node - linkType: hard - -"object.fromentries@npm:^2.0.8": - version: 2.0.8 - resolution: "object.fromentries@npm:2.0.8" - dependencies: - call-bind: "npm:^1.0.7" - define-properties: "npm:^1.2.1" - es-abstract: "npm:^1.23.2" - es-object-atoms: "npm:^1.0.0" - checksum: 10c0/cd4327e6c3369cfa805deb4cbbe919bfb7d3aeebf0bcaba291bb568ea7169f8f8cdbcabe2f00b40db0c20cd20f08e11b5f3a5a36fb7dd3fe04850c50db3bf83b - languageName: node - linkType: hard - -"object.groupby@npm:^1.0.3": - version: 1.0.3 - resolution: "object.groupby@npm:1.0.3" - dependencies: - call-bind: "npm:^1.0.7" - define-properties: "npm:^1.2.1" - es-abstract: "npm:^1.23.2" - checksum: 10c0/60d0455c85c736fbfeda0217d1a77525956f76f7b2495edeca9e9bbf8168a45783199e77b894d30638837c654d0cc410e0e02cbfcf445bc8de71c3da1ede6a9c - languageName: node - linkType: hard - -"object.values@npm:^1.1.6, object.values@npm:^1.2.1": - version: 1.2.1 - resolution: "object.values@npm:1.2.1" - dependencies: - call-bind: "npm:^1.0.8" - call-bound: "npm:^1.0.3" - define-properties: "npm:^1.2.1" - es-object-atoms: "npm:^1.0.0" - checksum: 10c0/3c47814fdc64842ae3d5a74bc9d06bdd8d21563c04d9939bf6716a9c00596a4ebc342552f8934013d1ec991c74e3671b26710a0c51815f0b603795605ab6b2c9 - languageName: node - linkType: hard - -"observable-hooks@npm:^4.2.3": - version: 4.2.4 - resolution: "observable-hooks@npm:4.2.4" - peerDependencies: - react: ">=16.8.0" - react-dom: ">=16.8.0" - rxjs: ">=6.0.0" - checksum: 10c0/2b2d4f2197c835fc175d110d3397a037c9dcbede7b31ceed383deccf717035d849652e376c24ea1185d244ad2b098c332efa6e4c04025ee89d1a63f790b7df60 - languageName: node - linkType: hard - -"obug@npm:^2.1.1": - version: 2.1.1 - resolution: "obug@npm:2.1.1" - checksum: 10c0/59dccd7de72a047e08f8649e94c1015ec72f94eefb6ddb57fb4812c4b425a813bc7e7cd30c9aca20db3c59abc3c85cc7a62bb656a968741d770f4e8e02bc2e78 - languageName: node - linkType: hard - -"oidc-client-ts@npm:^3.0.1": - version: 3.1.0 - resolution: "oidc-client-ts@npm:3.1.0" - dependencies: - jwt-decode: "npm:^4.0.0" - checksum: 10c0/302442a8c5456a6127887c86009548b59394c25e9b6e75ef7c8743c64e951e8efa3f967b481dc5013900c48827a46fbbd5c328be50ae7b9fa5f3aceb528ec2b2 - languageName: node - linkType: hard - -"once@npm:^1.4.0": - version: 1.4.0 - resolution: "once@npm:1.4.0" - dependencies: - wrappy: "npm:1" - checksum: 10c0/5d48aca287dfefabd756621c5dfce5c91a549a93e9fdb7b8246bc4c4790aa2ec17b34a260530474635147aeb631a2dcc8b32c613df0675f96041cbb8244517d0 - languageName: node - linkType: hard - -"open@npm:^10.2.0": - version: 10.2.0 - resolution: "open@npm:10.2.0" - dependencies: - default-browser: "npm:^5.2.1" - define-lazy-prop: "npm:^3.0.0" - is-inside-container: "npm:^1.0.0" - wsl-utils: "npm:^0.1.0" - checksum: 10c0/5a36d0c1fd2f74ce553beb427ca8b8494b623fc22c6132d0c1688f246a375e24584ea0b44c67133d9ab774fa69be8e12fbe1ff12504b1142bd960fb09671948f - languageName: node - linkType: hard - -"optionator@npm:^0.9.3": - version: 0.9.4 - resolution: "optionator@npm:0.9.4" - dependencies: - deep-is: "npm:^0.1.3" - fast-levenshtein: "npm:^2.0.6" - levn: "npm:^0.4.1" - prelude-ls: "npm:^1.2.1" - type-check: "npm:^0.4.0" - word-wrap: "npm:^1.2.5" - checksum: 10c0/4afb687a059ee65b61df74dfe87d8d6815cd6883cb8b3d5883a910df72d0f5d029821f37025e4bccf4048873dbdb09acc6d303d27b8f76b1a80dd5a7d5334675 - languageName: node - linkType: hard - -"os-browserify@npm:^0.3.0": - version: 0.3.0 - resolution: "os-browserify@npm:0.3.0" - checksum: 10c0/6ff32cb1efe2bc6930ad0fd4c50e30c38010aee909eba8d65be60af55efd6cbb48f0287e3649b4e3f3a63dce5a667b23c187c4293a75e557f0d5489d735bcf52 - languageName: node - linkType: hard - -"own-keys@npm:^1.0.1": - version: 1.0.1 - resolution: "own-keys@npm:1.0.1" - dependencies: - get-intrinsic: "npm:^1.2.6" - object-keys: "npm:^1.1.1" - safe-push-apply: "npm:^1.0.0" - checksum: 10c0/6dfeb3455bff92ec3f16a982d4e3e65676345f6902d9f5ded1d8265a6318d0200ce461956d6d1c70053c7fe9f9fe65e552faac03f8140d37ef0fdd108e67013a - languageName: node - linkType: hard - -"oxc-resolver@npm:^11.19.1": - version: 11.19.1 - resolution: "oxc-resolver@npm:11.19.1" - dependencies: - "@oxc-resolver/binding-android-arm-eabi": "npm:11.19.1" - "@oxc-resolver/binding-android-arm64": "npm:11.19.1" - "@oxc-resolver/binding-darwin-arm64": "npm:11.19.1" - "@oxc-resolver/binding-darwin-x64": "npm:11.19.1" - "@oxc-resolver/binding-freebsd-x64": "npm:11.19.1" - "@oxc-resolver/binding-linux-arm-gnueabihf": "npm:11.19.1" - "@oxc-resolver/binding-linux-arm-musleabihf": "npm:11.19.1" - "@oxc-resolver/binding-linux-arm64-gnu": "npm:11.19.1" - "@oxc-resolver/binding-linux-arm64-musl": "npm:11.19.1" - "@oxc-resolver/binding-linux-ppc64-gnu": "npm:11.19.1" - "@oxc-resolver/binding-linux-riscv64-gnu": "npm:11.19.1" - "@oxc-resolver/binding-linux-riscv64-musl": "npm:11.19.1" - "@oxc-resolver/binding-linux-s390x-gnu": "npm:11.19.1" - "@oxc-resolver/binding-linux-x64-gnu": "npm:11.19.1" - "@oxc-resolver/binding-linux-x64-musl": "npm:11.19.1" - "@oxc-resolver/binding-openharmony-arm64": "npm:11.19.1" - "@oxc-resolver/binding-wasm32-wasi": "npm:11.19.1" - "@oxc-resolver/binding-win32-arm64-msvc": "npm:11.19.1" - "@oxc-resolver/binding-win32-ia32-msvc": "npm:11.19.1" - "@oxc-resolver/binding-win32-x64-msvc": "npm:11.19.1" - dependenciesMeta: - "@oxc-resolver/binding-android-arm-eabi": - optional: true - "@oxc-resolver/binding-android-arm64": - optional: true - "@oxc-resolver/binding-darwin-arm64": - optional: true - "@oxc-resolver/binding-darwin-x64": - optional: true - "@oxc-resolver/binding-freebsd-x64": - optional: true - "@oxc-resolver/binding-linux-arm-gnueabihf": - optional: true - "@oxc-resolver/binding-linux-arm-musleabihf": - optional: true - "@oxc-resolver/binding-linux-arm64-gnu": - optional: true - "@oxc-resolver/binding-linux-arm64-musl": - optional: true - "@oxc-resolver/binding-linux-ppc64-gnu": - optional: true - "@oxc-resolver/binding-linux-riscv64-gnu": - optional: true - "@oxc-resolver/binding-linux-riscv64-musl": - optional: true - "@oxc-resolver/binding-linux-s390x-gnu": - optional: true - "@oxc-resolver/binding-linux-x64-gnu": - optional: true - "@oxc-resolver/binding-linux-x64-musl": - optional: true - "@oxc-resolver/binding-openharmony-arm64": - optional: true - "@oxc-resolver/binding-wasm32-wasi": - optional: true - "@oxc-resolver/binding-win32-arm64-msvc": - optional: true - "@oxc-resolver/binding-win32-ia32-msvc": - optional: true - "@oxc-resolver/binding-win32-x64-msvc": - optional: true - checksum: 10c0/8ac4eaffa9c0bcbb9f4f4a2b43786457ec5a68684d8776cb78b5a15ce3d1a79d3e67262aa3c635f98a0c1cd6cd56a31fcb05bffb9a286100056e4ab06b928833 - languageName: node - linkType: hard - -"p-limit@npm:^2.2.0": - version: 2.3.0 - resolution: "p-limit@npm:2.3.0" - dependencies: - p-try: "npm:^2.0.0" - checksum: 10c0/8da01ac53efe6a627080fafc127c873da40c18d87b3f5d5492d465bb85ec7207e153948df6b9cbaeb130be70152f874229b8242ee2be84c0794082510af97f12 - languageName: node - linkType: hard - -"p-limit@npm:^3.0.2": - version: 3.1.0 - resolution: "p-limit@npm:3.1.0" - dependencies: - yocto-queue: "npm:^0.1.0" - checksum: 10c0/9db675949dbdc9c3763c89e748d0ef8bdad0afbb24d49ceaf4c46c02c77d30db4e0652ed36d0a0a7a95154335fab810d95c86153105bb73b3a90448e2bb14e1a - languageName: node - linkType: hard - -"p-locate@npm:^4.1.0": - version: 4.1.0 - resolution: "p-locate@npm:4.1.0" - dependencies: - p-limit: "npm:^2.2.0" - checksum: 10c0/1b476ad69ad7f6059744f343b26d51ce091508935c1dbb80c4e0a2f397ffce0ca3a1f9f5cd3c7ce19d7929a09719d5c65fe70d8ee289c3f267cd36f2881813e9 - languageName: node - linkType: hard - -"p-locate@npm:^5.0.0": - version: 5.0.0 - resolution: "p-locate@npm:5.0.0" - dependencies: - p-limit: "npm:^3.0.2" - checksum: 10c0/2290d627ab7903b8b70d11d384fee714b797f6040d9278932754a6860845c4d3190603a0772a663c8cb5a7b21d1b16acb3a6487ebcafa9773094edc3dfe6009a - languageName: node - linkType: hard - -"p-map@npm:^7.0.2": - version: 7.0.3 - resolution: "p-map@npm:7.0.3" - checksum: 10c0/46091610da2b38ce47bcd1d8b4835a6fa4e832848a6682cf1652bc93915770f4617afc844c10a77d1b3e56d2472bb2d5622353fa3ead01a7f42b04fc8e744a5c - languageName: node - linkType: hard - -"p-retry@npm:7": - version: 7.0.0 - resolution: "p-retry@npm:7.0.0" - dependencies: - is-network-error: "npm:^1.1.0" - checksum: 10c0/3c090ac72bbe00fd2f062ee6178c44f7302f298936ab2290a458575e73650e7834b556beb2b09fa9fbebedab2ec3358cb474c09710cf828972b670c3c0cb89e4 - languageName: node - linkType: hard - -"p-try@npm:^2.0.0": - version: 2.2.0 - resolution: "p-try@npm:2.2.0" - checksum: 10c0/c36c19907734c904b16994e6535b02c36c2224d433e01a2f1ab777237f4d86e6289fd5fd464850491e940379d4606ed850c03e0f9ab600b0ebddb511312e177f - languageName: node - linkType: hard - -"package-json-from-dist@npm:^1.0.0": - version: 1.0.1 - resolution: "package-json-from-dist@npm:1.0.1" - checksum: 10c0/62ba2785eb655fec084a257af34dbe24292ab74516d6aecef97ef72d4897310bc6898f6c85b5cd22770eaa1ce60d55a0230e150fb6a966e3ecd6c511e23d164b - languageName: node - linkType: hard - -"pako@npm:^2.0.4": - version: 2.1.0 - resolution: "pako@npm:2.1.0" - checksum: 10c0/8e8646581410654b50eb22a5dfd71159cae98145bd5086c9a7a816ec0370b5f72b4648d08674624b3870a521e6a3daffd6c2f7bc00fdefc7063c9d8232ff5116 - languageName: node - linkType: hard - -"pako@npm:~1.0.5": - version: 1.0.11 - resolution: "pako@npm:1.0.11" - checksum: 10c0/86dd99d8b34c3930345b8bbeb5e1cd8a05f608eeb40967b293f72fe469d0e9c88b783a8777e4cc7dc7c91ce54c5e93d88ff4b4f060e6ff18408fd21030d9ffbe - languageName: node - linkType: hard - -"param-case@npm:^3.0.4": - version: 3.0.4 - resolution: "param-case@npm:3.0.4" - dependencies: - dot-case: "npm:^3.0.4" - tslib: "npm:^2.0.3" - checksum: 10c0/ccc053f3019f878eca10e70ec546d92f51a592f762917dafab11c8b532715dcff58356118a6f350976e4ab109e321756f05739643ed0ca94298e82291e6f9e76 - languageName: node - linkType: hard - -"parent-module@npm:^1.0.0": - version: 1.0.1 - resolution: "parent-module@npm:1.0.1" - dependencies: - callsites: "npm:^3.0.0" - checksum: 10c0/c63d6e80000d4babd11978e0d3fee386ca7752a02b035fd2435960ffaa7219dc42146f07069fb65e6e8bf1caef89daf9af7535a39bddf354d78bf50d8294f556 - languageName: node - linkType: hard - -"parse-asn1@npm:^5.0.0, parse-asn1@npm:^5.1.9": - version: 5.1.9 - resolution: "parse-asn1@npm:5.1.9" - dependencies: - asn1.js: "npm:^4.10.1" - browserify-aes: "npm:^1.2.0" - evp_bytestokey: "npm:^1.0.3" - pbkdf2: "npm:^3.1.5" - safe-buffer: "npm:^5.2.1" - checksum: 10c0/6dfe27c121be3d63ebbf95f03d2ae0a07dd716d44b70b0bd3458790a822a80de05361c62147271fd7b845dcc2d37755d9c9c393064a3438fe633779df0bc07e7 - languageName: node - linkType: hard - -"parse-imports-exports@npm:^0.2.4": - version: 0.2.4 - resolution: "parse-imports-exports@npm:0.2.4" - dependencies: - parse-statements: "npm:1.0.11" - checksum: 10c0/51b729037208abdf65c4a1f8e9ed06f4e7ccd907c17c668a64db54b37d95bb9e92081f8b16e4133e14102af3cb4e89870975b6ad661b4d654e9ec8f4fb5c77d6 - languageName: node - linkType: hard - -"parse-json@npm:^5.0.0, parse-json@npm:^5.2.0": - version: 5.2.0 - resolution: "parse-json@npm:5.2.0" - dependencies: - "@babel/code-frame": "npm:^7.0.0" - error-ex: "npm:^1.3.1" - json-parse-even-better-errors: "npm:^2.3.0" - lines-and-columns: "npm:^1.1.6" - checksum: 10c0/77947f2253005be7a12d858aedbafa09c9ae39eb4863adf330f7b416ca4f4a08132e453e08de2db46459256fb66afaac5ee758b44fe6541b7cdaf9d252e59585 - languageName: node - linkType: hard - -"parse-statements@npm:1.0.11": - version: 1.0.11 - resolution: "parse-statements@npm:1.0.11" - checksum: 10c0/48960e085019068a5f5242e875fd9d21ec87df2e291acf5ad4e4887b40eab6929a8c8d59542acb85a6497e870c5c6a24f5ab7f980ef5f907c14cc5f7984a93f3 - languageName: node - linkType: hard - -"parse5-htmlparser2-tree-adapter@npm:^7.0.0": - version: 7.1.0 - resolution: "parse5-htmlparser2-tree-adapter@npm:7.1.0" - dependencies: - domhandler: "npm:^5.0.3" - parse5: "npm:^7.0.0" - checksum: 10c0/e5a4e0b834c84c9e244b5749f8d007f4baaeafac7a1da2c54be3421ffd9ef8fdec4f198bf55cda22e88e6ba95e9943f6ed5aa3ae5900b39972ebf5dc8c3f4722 - languageName: node - linkType: hard - -"parse5-parser-stream@npm:^7.1.2": - version: 7.1.2 - resolution: "parse5-parser-stream@npm:7.1.2" - dependencies: - parse5: "npm:^7.0.0" - checksum: 10c0/e236c61000d38ecad369e725a48506b051cebad8abb00e6d4e8bff7aa85c183820fcb45db1559cc90955bdbbdbd665ea94c41259594e74566fff411478dc7fcb - languageName: node - linkType: hard - -"parse5@npm:^7.0.0, parse5@npm:^7.1.2, parse5@npm:^7.2.1": - version: 7.2.1 - resolution: "parse5@npm:7.2.1" - dependencies: - entities: "npm:^4.5.0" - checksum: 10c0/829d37a0c709215a887e410a7118d754f8e1afd7edb529db95bc7bbf8045fb0266a7b67801331d8e8d9d073ea75793624ec27ce9ff3b96862c3b9008f4d68e80 - languageName: node - linkType: hard - -"pascal-case@npm:^3.1.2": - version: 3.1.2 - resolution: "pascal-case@npm:3.1.2" - dependencies: - no-case: "npm:^3.0.4" - tslib: "npm:^2.0.3" - checksum: 10c0/05ff7c344809fd272fc5030ae0ee3da8e4e63f36d47a1e0a4855ca59736254192c5a27b5822ed4bae96e54048eec5f6907713cfcfff7cdf7a464eaf7490786d8 - languageName: node - linkType: hard - -"path-browserify@npm:^1.0.1": - version: 1.0.1 - resolution: "path-browserify@npm:1.0.1" - checksum: 10c0/8b8c3fd5c66bd340272180590ae4ff139769e9ab79522e2eb82e3d571a89b8117c04147f65ad066dccfb42fcad902e5b7d794b3d35e0fd840491a8ddbedf8c66 - languageName: node - linkType: hard - -"path-exists@npm:^4.0.0": - version: 4.0.0 - resolution: "path-exists@npm:4.0.0" - checksum: 10c0/8c0bd3f5238188197dc78dced15207a4716c51cc4e3624c44fc97acf69558f5ebb9a2afff486fe1b4ee148e0c133e96c5e11a9aa5c48a3006e3467da070e5e1b - languageName: node - linkType: hard - -"path-key@npm:^3.1.0": - version: 3.1.1 - resolution: "path-key@npm:3.1.1" - checksum: 10c0/748c43efd5a569c039d7a00a03b58eecd1d75f3999f5a28303d75f521288df4823bc057d8784eb72358b2895a05f29a070bc9f1f17d28226cc4e62494cc58c4c - languageName: node - linkType: hard - -"path-parse@npm:^1.0.7": - version: 1.0.7 - resolution: "path-parse@npm:1.0.7" - checksum: 10c0/11ce261f9d294cc7a58d6a574b7f1b935842355ec66fba3c3fd79e0f036462eaf07d0aa95bb74ff432f9afef97ce1926c720988c6a7451d8a584930ae7de86e1 - languageName: node - linkType: hard - -"path-posix@npm:^1.0.0": - version: 1.0.0 - resolution: "path-posix@npm:1.0.0" - checksum: 10c0/00fbadb9b60fb513f316f92e0b5535e55d832f4f20067586d151f6d7bed57178dec31b1a0f514694500a9a1f2b69798c066a3cdcf0b0289cfee63e39845bfd02 - languageName: node - linkType: hard - -"path-scurry@npm:^1.11.1": - version: 1.11.1 - resolution: "path-scurry@npm:1.11.1" - dependencies: - lru-cache: "npm:^10.2.0" - minipass: "npm:^5.0.0 || ^6.0.2 || ^7.0.0" - checksum: 10c0/32a13711a2a505616ae1cc1b5076801e453e7aae6ac40ab55b388bb91b9d0547a52f5aaceff710ea400205f18691120d4431e520afbe4266b836fadede15872d - languageName: node - linkType: hard - -"path-type@npm:^4.0.0": - version: 4.0.0 - resolution: "path-type@npm:4.0.0" - checksum: 10c0/666f6973f332f27581371efaf303fd6c272cc43c2057b37aa99e3643158c7e4b2626549555d88626e99ea9e046f82f32e41bbde5f1508547e9a11b149b52387c - languageName: node - linkType: hard - -"pathe@npm:^0.2.0": - version: 0.2.0 - resolution: "pathe@npm:0.2.0" - checksum: 10c0/4ea3bc19d421926d1e6b767ca5dc62fd8d053791f5f93b806ef64ea9c7c21071385429e12c0b1838129ae53904bfc6a243ac6890d3189fa5f45c417db49507cf - languageName: node - linkType: hard - -"pathe@npm:^2.0.3": - version: 2.0.3 - resolution: "pathe@npm:2.0.3" - checksum: 10c0/c118dc5a8b5c4166011b2b70608762e260085180bb9e33e80a50dcdb1e78c010b1624f4280c492c92b05fc276715a4c357d1f9edc570f8f1b3d90b6839ebaca1 - languageName: node - linkType: hard - -"pathval@npm:^2.0.0": - version: 2.0.1 - resolution: "pathval@npm:2.0.1" - checksum: 10c0/460f4709479fbf2c45903a65655fc8f0a5f6d808f989173aeef5fdea4ff4f303dc13f7870303999add60ec49d4c14733895c0a869392e9866f1091fa64fd7581 - languageName: node - linkType: hard - -"pbkdf2@npm:^3.1.2, pbkdf2@npm:^3.1.5": - version: 3.1.5 - resolution: "pbkdf2@npm:3.1.5" - dependencies: - create-hash: "npm:^1.2.0" - create-hmac: "npm:^1.1.7" - ripemd160: "npm:^2.0.3" - safe-buffer: "npm:^5.2.1" - sha.js: "npm:^2.4.12" - to-buffer: "npm:^1.2.1" - checksum: 10c0/ea42e8695e49417eefabb19a08ab19a602cc6cc72d2df3f109c39309600230dee3083a6f678d5d42fe035d6ae780038b80ace0e68f9792ee2839bf081fe386f3 - languageName: node - linkType: hard - -"picocolors@npm:1.1.1, picocolors@npm:^1.0.0, picocolors@npm:^1.1.1": - version: 1.1.1 - resolution: "picocolors@npm:1.1.1" - checksum: 10c0/e2e3e8170ab9d7c7421969adaa7e1b31434f789afb9b3f115f6b96d91945041ac3ceb02e9ec6fe6510ff036bcc0bf91e69a1772edc0b707e12b19c0f2d6bcf58 - languageName: node - linkType: hard - -"picomatch@npm:^2.0.4, picomatch@npm:^2.2.1, picomatch@npm:^2.2.2, picomatch@npm:^2.3.1": - version: 2.3.1 - resolution: "picomatch@npm:2.3.1" - checksum: 10c0/26c02b8d06f03206fc2ab8d16f19960f2ff9e81a658f831ecb656d8f17d9edc799e8364b1f4a7873e89d9702dff96204be0fa26fe4181f6843f040f819dac4be - languageName: node - linkType: hard - -"picomatch@npm:^4.0.1, picomatch@npm:^4.0.2": - version: 4.0.2 - resolution: "picomatch@npm:4.0.2" - checksum: 10c0/7c51f3ad2bb42c776f49ebf964c644958158be30d0a510efd5a395e8d49cb5acfed5b82c0c5b365523ce18e6ab85013c9ebe574f60305892ec3fa8eee8304ccc - languageName: node - linkType: hard - -"picomatch@npm:^4.0.3": - version: 4.0.3 - resolution: "picomatch@npm:4.0.3" - checksum: 10c0/9582c951e95eebee5434f59e426cddd228a7b97a0161a375aed4be244bd3fe8e3a31b846808ea14ef2c8a2527a6eeab7b3946a67d5979e81694654f939473ae2 - languageName: node - linkType: hard - -"picomatch@npm:^4.0.4": - version: 4.0.4 - resolution: "picomatch@npm:4.0.4" - checksum: 10c0/e2c6023372cc7b5764719a5ffb9da0f8e781212fa7ca4bd0562db929df8e117460f00dff3cb7509dacfc06b86de924b247f504d0ce1806a37fac4633081466b0 - languageName: node - linkType: hard - -"pkg-dir@npm:^5.0.0": - version: 5.0.0 - resolution: "pkg-dir@npm:5.0.0" - dependencies: - find-up: "npm:^5.0.0" - checksum: 10c0/793a496d685dc55bbbdbbb22d884535c3b29241e48e3e8d37e448113a71b9e42f5481a61fdc672d7322de12fbb2c584dd3a68bf89b18fffce5c48a390f911bc5 - languageName: node - linkType: hard - -"playwright-core@npm:1.58.2": - version: 1.58.2 - resolution: "playwright-core@npm:1.58.2" - bin: - playwright-core: cli.js - checksum: 10c0/5aa15b2b764e6ffe738293a09081a6f7023847a0dbf4cd05fe10eed2e25450d321baf7482f938f2d2eb330291e197fa23e57b29a5b552b89927ceb791266225b - languageName: node - linkType: hard - -"playwright@npm:1.58.2": - version: 1.58.2 - resolution: "playwright@npm:1.58.2" - dependencies: - fsevents: "npm:2.3.2" - playwright-core: "npm:1.58.2" - dependenciesMeta: - fsevents: - optional: true - bin: - playwright: cli.js - checksum: 10c0/d060d9b7cc124bd8b5dffebaab5e84f6b34654a553758fe7b19cc598dfbee93f6ecfbdc1832b40a6380ae04eade86ef3285ba03aa0b136799e83402246dc0727 - languageName: node - linkType: hard - -"pluralize@npm:^8.0.0": - version: 8.0.0 - resolution: "pluralize@npm:8.0.0" - checksum: 10c0/2044cfc34b2e8c88b73379ea4a36fc577db04f651c2909041b054c981cd863dd5373ebd030123ab058d194ae615d3a97cfdac653991e499d10caf592e8b3dc33 - languageName: node - linkType: hard - -"pngjs@npm:^5.0.0": - version: 5.0.0 - resolution: "pngjs@npm:5.0.0" - checksum: 10c0/c074d8a94fb75e2defa8021e85356bf7849688af7d8ce9995b7394d57cd1a777b272cfb7c4bce08b8d10e71e708e7717c81fd553a413f21840c548ec9d4893c6 - languageName: node - linkType: hard - -"possible-typed-array-names@npm:^1.0.0": - version: 1.0.0 - resolution: "possible-typed-array-names@npm:1.0.0" - checksum: 10c0/d9aa22d31f4f7680e20269db76791b41c3a32c01a373e25f8a4813b4d45f7456bfc2b6d68f752dc4aab0e0bb0721cb3d76fb678c9101cb7a16316664bc2c73fd - languageName: node - linkType: hard - -"postcss-attribute-case-insensitive@npm:^7.0.1": - version: 7.0.1 - resolution: "postcss-attribute-case-insensitive@npm:7.0.1" - dependencies: - postcss-selector-parser: "npm:^7.0.0" - peerDependencies: - postcss: ^8.4 - checksum: 10c0/48945abe2024e2d2e4c37d30b8c1aaf37af720f24f6a996f7ea7e7ed33621f5c22cf247ed22028c0c922de040c58c0802729bc39b903cb1693f4b63c0b49da34 - languageName: node - linkType: hard - -"postcss-clamp@npm:^4.1.0": - version: 4.1.0 - resolution: "postcss-clamp@npm:4.1.0" - dependencies: - postcss-value-parser: "npm:^4.2.0" - peerDependencies: - postcss: ^8.4.6 - checksum: 10c0/701261026b38a4c27b3c3711635fac96005f36d3270adb76dbdb1eebc950fc841db45283ee66068a7121565592e9d7967d5534e15b6e4dd266afcabf9eafa905 - languageName: node - linkType: hard - -"postcss-color-functional-notation@npm:^7.0.12": - version: 7.0.12 - resolution: "postcss-color-functional-notation@npm:7.0.12" - dependencies: - "@csstools/css-color-parser": "npm:^3.1.0" - "@csstools/css-parser-algorithms": "npm:^3.0.5" - "@csstools/css-tokenizer": "npm:^3.0.4" - "@csstools/postcss-progressive-custom-properties": "npm:^4.2.1" - "@csstools/utilities": "npm:^2.0.0" - peerDependencies: - postcss: ^8.4 - checksum: 10c0/dc80ba1a956ae9b396596bda72d9bdb92de96874378a38ba4e2177ffa35339dc76d894920bb013b6f10c9b75cfb41778e09956a438c2e9ea41b684f766c55f4a - languageName: node - linkType: hard - -"postcss-color-hex-alpha@npm:^10.0.0": - version: 10.0.0 - resolution: "postcss-color-hex-alpha@npm:10.0.0" - dependencies: - "@csstools/utilities": "npm:^2.0.0" - postcss-value-parser: "npm:^4.2.0" - peerDependencies: - postcss: ^8.4 - checksum: 10c0/8a6dcb27403d04b55d6de88bf3074622bcea537fc4436bbcb346e92289c4d17059444e2e6c3554c325e7a777bb4cdc711e764a83123b4000aec211052e957d5b - languageName: node - linkType: hard - -"postcss-color-rebeccapurple@npm:^10.0.0": - version: 10.0.0 - resolution: "postcss-color-rebeccapurple@npm:10.0.0" - dependencies: - "@csstools/utilities": "npm:^2.0.0" - postcss-value-parser: "npm:^4.2.0" - peerDependencies: - postcss: ^8.4 - checksum: 10c0/308e33f76f2b48c1c2121d4502fc053e869f3415898de7d30314353df680e79b37497e7b628e3447edc1049091da3672f7d891e45604f238598e846e06b893ed - languageName: node - linkType: hard - -"postcss-custom-media@npm:^11.0.6": - version: 11.0.6 - resolution: "postcss-custom-media@npm:11.0.6" - dependencies: - "@csstools/cascade-layer-name-parser": "npm:^2.0.5" - "@csstools/css-parser-algorithms": "npm:^3.0.5" - "@csstools/css-tokenizer": "npm:^3.0.4" - "@csstools/media-query-list-parser": "npm:^4.0.3" - peerDependencies: - postcss: ^8.4 - checksum: 10c0/62dcb2858fd490d90aab32062621d58892a7b2a54948ee63af81a2cd61807a11815d28d4ef6bc800c5e142ac73098f7e56822c7cc63192eb20d5b16071543a73 - languageName: node - linkType: hard - -"postcss-custom-properties@npm:^14.0.6": - version: 14.0.6 - resolution: "postcss-custom-properties@npm:14.0.6" - dependencies: - "@csstools/cascade-layer-name-parser": "npm:^2.0.5" - "@csstools/css-parser-algorithms": "npm:^3.0.5" - "@csstools/css-tokenizer": "npm:^3.0.4" - "@csstools/utilities": "npm:^2.0.0" - postcss-value-parser: "npm:^4.2.0" - peerDependencies: - postcss: ^8.4 - checksum: 10c0/0eeef77bc713551f5cb8fa5982d24da4e854075f3af020f1c94366c47a23a4cc225ebfecc978bdb17f00ee0bdee9d2c784e0d01adc64a447321e408abbe2c83b - languageName: node - linkType: hard - -"postcss-custom-selectors@npm:^8.0.5": - version: 8.0.5 - resolution: "postcss-custom-selectors@npm:8.0.5" - dependencies: - "@csstools/cascade-layer-name-parser": "npm:^2.0.5" - "@csstools/css-parser-algorithms": "npm:^3.0.5" - "@csstools/css-tokenizer": "npm:^3.0.4" - postcss-selector-parser: "npm:^7.0.0" - peerDependencies: - postcss: ^8.4 - checksum: 10c0/bd8f2f85bbec4bd56ff408cb699d9fe649e2af0db82d5752eee05481ae522f06f5a47950ca22fcb4c8601071c03346df67cf20b0b0bcade32ce58d07ebaf9b32 - languageName: node - linkType: hard - -"postcss-dir-pseudo-class@npm:^9.0.1": - version: 9.0.1 - resolution: "postcss-dir-pseudo-class@npm:9.0.1" - dependencies: - postcss-selector-parser: "npm:^7.0.0" - peerDependencies: - postcss: ^8.4 - checksum: 10c0/da9d3387648c5c3161a653d354c8f3e70a299108df3977e8aa65cf10793e4dd58a2711b3426cd63716245b13584ca8d95adcd6e10e3c9adbc61d08743e2d8690 - languageName: node - linkType: hard - -"postcss-double-position-gradients@npm:^6.0.4": - version: 6.0.4 - resolution: "postcss-double-position-gradients@npm:6.0.4" - dependencies: - "@csstools/postcss-progressive-custom-properties": "npm:^4.2.1" - "@csstools/utilities": "npm:^2.0.0" - postcss-value-parser: "npm:^4.2.0" - peerDependencies: - postcss: ^8.4 - checksum: 10c0/6dbbe7a3855e84a9319df434e210225f6dfa7262e5959611355f1769c2c9d30d37a19737712f20eac6354876fff4ba556d8d0b12a90c78d8ab97c9a8da534a7c - languageName: node - linkType: hard - -"postcss-focus-visible@npm:^10.0.1": - version: 10.0.1 - resolution: "postcss-focus-visible@npm:10.0.1" - dependencies: - postcss-selector-parser: "npm:^7.0.0" - peerDependencies: - postcss: ^8.4 - checksum: 10c0/c5ecc8536a708a49a99d0abd68a88a160664e6c832c808db8edd9f0221e7017a258daa87e49daf2cb098cb037005d46cf492403c8c9c92ad8835d30adaccf665 - languageName: node - linkType: hard - -"postcss-focus-within@npm:^9.0.1": - version: 9.0.1 - resolution: "postcss-focus-within@npm:9.0.1" - dependencies: - postcss-selector-parser: "npm:^7.0.0" - peerDependencies: - postcss: ^8.4 - checksum: 10c0/d6ab49d2a7f33485a9e137dc77ec92c5619a3ec92e1e672734fc604853ff1f3c0c189085c12461614be4fcb03ea0347d91791a45986a18d50b5228d161eda57a - languageName: node - linkType: hard - -"postcss-font-variant@npm:^5.0.0": - version: 5.0.0 - resolution: "postcss-font-variant@npm:5.0.0" - peerDependencies: - postcss: ^8.1.0 - checksum: 10c0/ccc96460cf6a52b5439c26c9a5ea0589882e46161e3c2331d4353de7574448f5feef667d1a68f7f39b9fe3ee75d85957383ae82bbfcf87c3162c7345df4a444e - languageName: node - linkType: hard - -"postcss-gap-properties@npm:^6.0.0": - version: 6.0.0 - resolution: "postcss-gap-properties@npm:6.0.0" - peerDependencies: - postcss: ^8.4 - checksum: 10c0/4e07e0d3927d0e65d67eaf047ac39e08d39cb1bf74e16e10c7df7f0d01b184a77ea59f63fd5691b5ed6df159970b972db28cb784d883e26e981137696460897d - languageName: node - linkType: hard - -"postcss-image-set-function@npm:^7.0.0": - version: 7.0.0 - resolution: "postcss-image-set-function@npm:7.0.0" - dependencies: - "@csstools/utilities": "npm:^2.0.0" - postcss-value-parser: "npm:^4.2.0" - peerDependencies: - postcss: ^8.4 - checksum: 10c0/913fd9492f00122aa0c2550fb0d72130428cbe1e6465bc65e8fe71e9deb10ac0c01d7caceb68b560da759139e8cbc6c90ed22dfe6cf34949af49bb86bcbf4d3a - languageName: node - linkType: hard - -"postcss-lab-function@npm:^7.0.12": - version: 7.0.12 - resolution: "postcss-lab-function@npm:7.0.12" - dependencies: - "@csstools/css-color-parser": "npm:^3.1.0" - "@csstools/css-parser-algorithms": "npm:^3.0.5" - "@csstools/css-tokenizer": "npm:^3.0.4" - "@csstools/postcss-progressive-custom-properties": "npm:^4.2.1" - "@csstools/utilities": "npm:^2.0.0" - peerDependencies: - postcss: ^8.4 - checksum: 10c0/de39b59da3b97c18d055d81fba68993e93253184ed76f103c888273584f868c551d047814dd54445980a1bdc5987e8f8af141383d84ecc641e5a6ee7bd901095 - languageName: node - linkType: hard - -"postcss-logical@npm:^8.1.0": - version: 8.1.0 - resolution: "postcss-logical@npm:8.1.0" - dependencies: - postcss-value-parser: "npm:^4.2.0" - peerDependencies: - postcss: ^8.4 - checksum: 10c0/0e2e9e901d8a550db7f682d46b1f7e4f363c1ada061dc8e4548e2b563c5e39f3684a2d7c3f11fe061188782bca37874e34967fc6179fa6d98a49ff66a0076d27 - languageName: node - linkType: hard - -"postcss-nesting@npm:^13.0.2": - version: 13.0.2 - resolution: "postcss-nesting@npm:13.0.2" - dependencies: - "@csstools/selector-resolve-nested": "npm:^3.1.0" - "@csstools/selector-specificity": "npm:^5.0.0" - postcss-selector-parser: "npm:^7.0.0" - peerDependencies: - postcss: ^8.4 - checksum: 10c0/bfa0578b3b686c6374f5a7b2f6ef955cb7e13400de95a919975a982ae43c1e25db37385618f210715ff15393dc7ff8c26c7b156f06b8fb3118a426099cf7f1f2 - languageName: node - linkType: hard - -"postcss-opacity-percentage@npm:^3.0.0": - version: 3.0.0 - resolution: "postcss-opacity-percentage@npm:3.0.0" - peerDependencies: - postcss: ^8.4 - checksum: 10c0/15c7d66036fa966d265c8737196646b3f93deb83d4eea0b17ed5033460599afc31d3a989345e4d7c472963b2a2bb75c83d06979d5d30d6a60fcc7f74cb6d8d40 - languageName: node - linkType: hard - -"postcss-overflow-shorthand@npm:^6.0.0": - version: 6.0.0 - resolution: "postcss-overflow-shorthand@npm:6.0.0" - dependencies: - postcss-value-parser: "npm:^4.2.0" - peerDependencies: - postcss: ^8.4 - checksum: 10c0/6598321b2ed0b68461135395bba9c7f76a4672617770df1e8487f459bc975f4ded6c3d37b6f72a44f4f77f7b6789e0c6f927e66dbbf1bcde1537167dbea39968 - languageName: node - linkType: hard - -"postcss-page-break@npm:^3.0.4": - version: 3.0.4 - resolution: "postcss-page-break@npm:3.0.4" - peerDependencies: - postcss: ^8 - checksum: 10c0/eaaf4d8922b35f2acd637eb059f7e2510b24d65eb8f31424799dd5a98447b6ef010b41880c26e78f818e00f842295638ec75f89d5d489067f53e3dd3db74a00f - languageName: node - linkType: hard - -"postcss-place@npm:^10.0.0": - version: 10.0.0 - resolution: "postcss-place@npm:10.0.0" - dependencies: - postcss-value-parser: "npm:^4.2.0" - peerDependencies: - postcss: ^8.4 - checksum: 10c0/ebb13deaac7648ba6042622375a31f78fbcc5209b7d196e478debbdf94525963fe621c932f4737a5b6b3d487af3b5ed6d059ed6193fdcbff6d3d5b150886ccc1 - languageName: node - linkType: hard - -"postcss-preset-env@npm:^10.0.0": - version: 10.6.1 - resolution: "postcss-preset-env@npm:10.6.1" - dependencies: - "@csstools/postcss-alpha-function": "npm:^1.0.1" - "@csstools/postcss-cascade-layers": "npm:^5.0.2" - "@csstools/postcss-color-function": "npm:^4.0.12" - "@csstools/postcss-color-function-display-p3-linear": "npm:^1.0.1" - "@csstools/postcss-color-mix-function": "npm:^3.0.12" - "@csstools/postcss-color-mix-variadic-function-arguments": "npm:^1.0.2" - "@csstools/postcss-content-alt-text": "npm:^2.0.8" - "@csstools/postcss-contrast-color-function": "npm:^2.0.12" - "@csstools/postcss-exponential-functions": "npm:^2.0.9" - "@csstools/postcss-font-format-keywords": "npm:^4.0.0" - "@csstools/postcss-gamut-mapping": "npm:^2.0.11" - "@csstools/postcss-gradients-interpolation-method": "npm:^5.0.12" - "@csstools/postcss-hwb-function": "npm:^4.0.12" - "@csstools/postcss-ic-unit": "npm:^4.0.4" - "@csstools/postcss-initial": "npm:^2.0.1" - "@csstools/postcss-is-pseudo-class": "npm:^5.0.3" - "@csstools/postcss-light-dark-function": "npm:^2.0.11" - "@csstools/postcss-logical-float-and-clear": "npm:^3.0.0" - "@csstools/postcss-logical-overflow": "npm:^2.0.0" - "@csstools/postcss-logical-overscroll-behavior": "npm:^2.0.0" - "@csstools/postcss-logical-resize": "npm:^3.0.0" - "@csstools/postcss-logical-viewport-units": "npm:^3.0.4" - "@csstools/postcss-media-minmax": "npm:^2.0.9" - "@csstools/postcss-media-queries-aspect-ratio-number-values": "npm:^3.0.5" - "@csstools/postcss-nested-calc": "npm:^4.0.0" - "@csstools/postcss-normalize-display-values": "npm:^4.0.1" - "@csstools/postcss-oklab-function": "npm:^4.0.12" - "@csstools/postcss-position-area-property": "npm:^1.0.0" - "@csstools/postcss-progressive-custom-properties": "npm:^4.2.1" - "@csstools/postcss-property-rule-prelude-list": "npm:^1.0.0" - "@csstools/postcss-random-function": "npm:^2.0.1" - "@csstools/postcss-relative-color-syntax": "npm:^3.0.12" - "@csstools/postcss-scope-pseudo-class": "npm:^4.0.1" - "@csstools/postcss-sign-functions": "npm:^1.1.4" - "@csstools/postcss-stepped-value-functions": "npm:^4.0.9" - "@csstools/postcss-syntax-descriptor-syntax-production": "npm:^1.0.1" - "@csstools/postcss-system-ui-font-family": "npm:^1.0.0" - "@csstools/postcss-text-decoration-shorthand": "npm:^4.0.3" - "@csstools/postcss-trigonometric-functions": "npm:^4.0.9" - "@csstools/postcss-unset-value": "npm:^4.0.0" - autoprefixer: "npm:^10.4.23" - browserslist: "npm:^4.28.1" - css-blank-pseudo: "npm:^7.0.1" - css-has-pseudo: "npm:^7.0.3" - css-prefers-color-scheme: "npm:^10.0.0" - cssdb: "npm:^8.6.0" - postcss-attribute-case-insensitive: "npm:^7.0.1" - postcss-clamp: "npm:^4.1.0" - postcss-color-functional-notation: "npm:^7.0.12" - postcss-color-hex-alpha: "npm:^10.0.0" - postcss-color-rebeccapurple: "npm:^10.0.0" - postcss-custom-media: "npm:^11.0.6" - postcss-custom-properties: "npm:^14.0.6" - postcss-custom-selectors: "npm:^8.0.5" - postcss-dir-pseudo-class: "npm:^9.0.1" - postcss-double-position-gradients: "npm:^6.0.4" - postcss-focus-visible: "npm:^10.0.1" - postcss-focus-within: "npm:^9.0.1" - postcss-font-variant: "npm:^5.0.0" - postcss-gap-properties: "npm:^6.0.0" - postcss-image-set-function: "npm:^7.0.0" - postcss-lab-function: "npm:^7.0.12" - postcss-logical: "npm:^8.1.0" - postcss-nesting: "npm:^13.0.2" - postcss-opacity-percentage: "npm:^3.0.0" - postcss-overflow-shorthand: "npm:^6.0.0" - postcss-page-break: "npm:^3.0.4" - postcss-place: "npm:^10.0.0" - postcss-pseudo-class-any-link: "npm:^10.0.1" - postcss-replace-overflow-wrap: "npm:^4.0.0" - postcss-selector-not: "npm:^8.0.1" - peerDependencies: - postcss: ^8.4 - checksum: 10c0/e8da96f208918ebc0dc9acc8ba8961a92569f1d130b29abe25adaf7dbd56ef29fc6f778b75964c80fe7f3469012c763ea9447e5c2f559a002a155bc0462cce35 - languageName: node - linkType: hard - -"postcss-pseudo-class-any-link@npm:^10.0.1": - version: 10.0.1 - resolution: "postcss-pseudo-class-any-link@npm:10.0.1" - dependencies: - postcss-selector-parser: "npm:^7.0.0" - peerDependencies: - postcss: ^8.4 - checksum: 10c0/95e883996e87baf14fc09d25f9a763a2e9d599eb3b9c6b736e83a8c3d0b55841bcb886bccdf51b5b7fefc128cbd0187ad8841f59878f85bd1613642e592d7673 - languageName: node - linkType: hard - -"postcss-replace-overflow-wrap@npm:^4.0.0": - version: 4.0.0 - resolution: "postcss-replace-overflow-wrap@npm:4.0.0" - peerDependencies: - postcss: ^8.0.3 - checksum: 10c0/451361b714528cd3632951256ef073769cde725a46cda642a6864f666fb144921fa55e614aec1bcf5946f37d6ffdcca3b932b76f3d997c07b076e8db152b128d - languageName: node - linkType: hard - -"postcss-selector-not@npm:^8.0.1": - version: 8.0.1 - resolution: "postcss-selector-not@npm:8.0.1" - dependencies: - postcss-selector-parser: "npm:^7.0.0" - peerDependencies: - postcss: ^8.4 - checksum: 10c0/491ea3dcc421cd90135be786078521605e2062fb93624ea8813cfd5ba0d35143f931e2e608d5f20effd5ea7d3f4786d2afea2afa42d117779a0288e135f132b6 - languageName: node - linkType: hard - -"postcss-selector-parser@npm:^7.0.0": - version: 7.1.0 - resolution: "postcss-selector-parser@npm:7.1.0" - dependencies: - cssesc: "npm:^3.0.0" - util-deprecate: "npm:^1.0.2" - checksum: 10c0/0fef257cfd1c0fe93c18a3f8a6e739b4438b527054fd77e9a62730a89b2d0ded1b59314a7e4aaa55bc256204f40830fecd2eb50f20f8cb7ab3a10b52aa06c8aa - languageName: node - linkType: hard - -"postcss-value-parser@npm:^4.2.0": - version: 4.2.0 - resolution: "postcss-value-parser@npm:4.2.0" - checksum: 10c0/f4142a4f56565f77c1831168e04e3effd9ffcc5aebaf0f538eee4b2d465adfd4b85a44257bb48418202a63806a7da7fe9f56c330aebb3cac898e46b4cbf49161 - languageName: node - linkType: hard - -"postcss@npm:^8.4.41, postcss@npm:^8.5.8": - version: 8.5.8 - resolution: "postcss@npm:8.5.8" - dependencies: - nanoid: "npm:^3.3.11" - picocolors: "npm:^1.1.1" - source-map-js: "npm:^1.2.1" - checksum: 10c0/dd918f7127ee7c60a0295bae2e72b3787892296e1d1c3c564d7a2a00c68d8df83cadc3178491259daa19ccc54804fb71ed8c937c6787e08d8bd4bedf8d17044c - languageName: node - linkType: hard - -"posthog-js@npm:1.160.3": - version: 1.160.3 - resolution: "posthog-js@npm:1.160.3" - dependencies: - fflate: "npm:^0.4.8" - preact: "npm:^10.19.3" - web-vitals: "npm:^4.0.1" - checksum: 10c0/88865776ee8fbdf71ae045181a8bdfc811bdc57cb66daae2eda9605102d4ec05bd41f85479ab23ae59e84c24a8e8ff2600b238033cee6fe18701c24a3e3ee712 - languageName: node - linkType: hard - -"preact@npm:^10.19.3": - version: 10.24.1 - resolution: "preact@npm:10.24.1" - checksum: 10c0/f9bc8b2f88d340f1b8f854208889244059c46916449b8f8f2174fcacbc0904c445c5870896fb0cfeaf442eeade975857e8e03f0785135c41d63cd32d9414c9c6 - languageName: node - linkType: hard - -"prelude-ls@npm:^1.2.1": - version: 1.2.1 - resolution: "prelude-ls@npm:1.2.1" - checksum: 10c0/b00d617431e7886c520a6f498a2e14c75ec58f6d93ba48c3b639cf241b54232d90daa05d83a9e9b9fef6baa63cb7e1e4602c2372fea5bc169668401eb127d0cd - languageName: node - linkType: hard - -"prettier@npm:^3.0.0": - version: 3.8.1 - resolution: "prettier@npm:3.8.1" - bin: - prettier: bin/prettier.cjs - checksum: 10c0/33169b594009e48f570471271be7eac7cdcf88a209eed39ac3b8d6d78984039bfa9132f82b7e6ba3b06711f3bfe0222a62a1bfb87c43f50c25a83df1b78a2c42 - languageName: node - linkType: hard - -"pretty-format@npm:^27.0.2": - version: 27.5.1 - resolution: "pretty-format@npm:27.5.1" - dependencies: - ansi-regex: "npm:^5.0.1" - ansi-styles: "npm:^5.0.0" - react-is: "npm:^17.0.1" - checksum: 10c0/0cbda1031aa30c659e10921fa94e0dd3f903ecbbbe7184a729ad66f2b6e7f17891e8c7d7654c458fa4ccb1a411ffb695b4f17bbcd3fe075fabe181027c4040ed - languageName: node - linkType: hard - -"proc-log@npm:^5.0.0": - version: 5.0.0 - resolution: "proc-log@npm:5.0.0" - checksum: 10c0/bbe5edb944b0ad63387a1d5b1911ae93e05ce8d0f60de1035b218cdcceedfe39dbd2c697853355b70f1a090f8f58fe90da487c85216bf9671f9499d1a897e9e3 - languageName: node - linkType: hard - -"process-nextick-args@npm:~2.0.0": - version: 2.0.1 - resolution: "process-nextick-args@npm:2.0.1" - checksum: 10c0/bec089239487833d46b59d80327a1605e1c5287eaad770a291add7f45fda1bb5e28b38e0e061add0a1d0ee0984788ce74fa394d345eed1c420cacf392c554367 - languageName: node - linkType: hard - -"process@npm:^0.11.10": - version: 0.11.10 - resolution: "process@npm:0.11.10" - checksum: 10c0/40c3ce4b7e6d4b8c3355479df77aeed46f81b279818ccdc500124e6a5ab882c0cc81ff7ea16384873a95a74c4570b01b120f287abbdd4c877931460eca6084b3 - languageName: node - linkType: hard - -"progress@npm:^2.0.3": - version: 2.0.3 - resolution: "progress@npm:2.0.3" - checksum: 10c0/1697e07cb1068055dbe9fe858d242368ff5d2073639e652b75a7eb1f2a1a8d4afd404d719de23c7b48481a6aa0040686310e2dac2f53d776daa2176d3f96369c - languageName: node - linkType: hard - -"promise-map-series@npm:^0.3.0": - version: 0.3.0 - resolution: "promise-map-series@npm:0.3.0" - checksum: 10c0/dc69dc6efc26f0325a42df873552fc5d6007a4738ec23af8e84432e581ff77d4b26345fe028faba5a8f153c8ba47a37ba33a58e329c6d04cafb3c397fbc09aab - languageName: node - linkType: hard - -"promise-retry@npm:^2.0.1": - version: 2.0.1 - resolution: "promise-retry@npm:2.0.1" - dependencies: - err-code: "npm:^2.0.2" - retry: "npm:^0.12.0" - checksum: 10c0/9c7045a1a2928094b5b9b15336dcd2a7b1c052f674550df63cc3f36cd44028e5080448175b6f6ca32b642de81150f5e7b1a98b728f15cb069f2dd60ac2616b96 - languageName: node - linkType: hard - -"prompts@npm:~2.4.2": - version: 2.4.2 - resolution: "prompts@npm:2.4.2" - dependencies: - kleur: "npm:^3.0.3" - sisteransi: "npm:^1.0.5" - checksum: 10c0/16f1ac2977b19fe2cf53f8411cc98db7a3c8b115c479b2ca5c82b5527cd937aa405fa04f9a5960abeb9daef53191b53b4d13e35c1f5d50e8718c76917c5f1ea4 - languageName: node - linkType: hard - -"prop-types@npm:^15.8.1": - version: 15.8.1 - resolution: "prop-types@npm:15.8.1" - dependencies: - loose-envify: "npm:^1.4.0" - object-assign: "npm:^4.1.1" - react-is: "npm:^16.13.1" - checksum: 10c0/59ece7ca2fb9838031d73a48d4becb9a7cc1ed10e610517c7d8f19a1e02fa47f7c27d557d8a5702bec3cfeccddc853579832b43f449e54635803f277b1c78077 - languageName: node - linkType: hard - -"proxy-from-env@npm:^1.1.0": - version: 1.1.0 - resolution: "proxy-from-env@npm:1.1.0" - checksum: 10c0/fe7dd8b1bdbbbea18d1459107729c3e4a2243ca870d26d34c2c1bcd3e4425b7bcc5112362df2d93cc7fb9746f6142b5e272fd1cc5c86ddf8580175186f6ad42b - languageName: node - linkType: hard - -"public-encrypt@npm:^4.0.3": - version: 4.0.3 - resolution: "public-encrypt@npm:4.0.3" - dependencies: - bn.js: "npm:^4.1.0" - browserify-rsa: "npm:^4.0.0" - create-hash: "npm:^1.1.0" - parse-asn1: "npm:^5.0.0" - randombytes: "npm:^2.0.1" - safe-buffer: "npm:^5.1.2" - checksum: 10c0/6c2cc19fbb554449e47f2175065d6b32f828f9b3badbee4c76585ac28ae8641aafb9bb107afc430c33c5edd6b05dbe318df4f7d6d7712b1093407b11c4280700 - languageName: node - linkType: hard - -"punycode@npm:^1.4.1": - version: 1.4.1 - resolution: "punycode@npm:1.4.1" - checksum: 10c0/354b743320518aef36f77013be6e15da4db24c2b4f62c5f1eb0529a6ed02fbaf1cb52925785f6ab85a962f2b590d9cd5ad730b70da72b5f180e2556b8bd3ca08 - languageName: node - linkType: hard - -"punycode@npm:^2.1.0, punycode@npm:^2.3.1": - version: 2.3.1 - resolution: "punycode@npm:2.3.1" - checksum: 10c0/14f76a8206bc3464f794fb2e3d3cc665ae416c01893ad7a02b23766eb07159144ee612ad67af5e84fa4479ccfe67678c4feb126b0485651b302babf66f04f9e9 - languageName: node - linkType: hard - -"qrcode@npm:^1.5.4": - version: 1.5.4 - resolution: "qrcode@npm:1.5.4" - dependencies: - dijkstrajs: "npm:^1.0.1" - pngjs: "npm:^5.0.0" - yargs: "npm:^15.3.1" - bin: - qrcode: bin/qrcode - checksum: 10c0/ae1d57c9cff6099639a590b432c71b15e3bd3905ce4353e6d00c95dee6bb769a8f773f6a7575ecc1b8ed476bf79c5138a4a65cb380c682de3b926d7205d34d10 - languageName: node - linkType: hard - -"qs@npm:^6.14.1": - version: 6.15.0 - resolution: "qs@npm:6.15.0" - dependencies: - side-channel: "npm:^1.1.0" - checksum: 10c0/ff341078a78a991d8a48b4524d52949211447b4b1ad907f489cac0770cbc346a28e47304455c0320e5fb000f8762d64b03331e3b71865f663bf351bcba8cdb4b - languageName: node - linkType: hard - -"querystring-es3@npm:^0.2.1": - version: 0.2.1 - resolution: "querystring-es3@npm:0.2.1" - checksum: 10c0/476938c1adb45c141f024fccd2ffd919a3746e79ed444d00e670aad68532977b793889648980e7ca7ff5ffc7bfece623118d0fbadcaf217495eeb7059ae51580 - languageName: node - linkType: hard - -"queue-microtask@npm:^1.2.2": - version: 1.2.3 - resolution: "queue-microtask@npm:1.2.3" - checksum: 10c0/900a93d3cdae3acd7d16f642c29a642aea32c2026446151f0778c62ac089d4b8e6c986811076e1ae180a694cedf077d453a11b58ff0a865629a4f82ab558e102 - languageName: node - linkType: hard - -"quick-temp@npm:^0.1.8": - version: 0.1.8 - resolution: "quick-temp@npm:0.1.8" - dependencies: - mktemp: "npm:~0.4.0" - rimraf: "npm:^2.5.4" - underscore.string: "npm:~3.3.4" - checksum: 10c0/3e8277a2e37db8e101fdefd59dc62050681b46d82f0c617eb700e2ef54f1c4985eff79985a24ef61834fd4c758050dbecfec7f34ed7caa6717f96de03ed9063c - languageName: node - linkType: hard - -"randombytes@npm:^2.0.0, randombytes@npm:^2.0.1, randombytes@npm:^2.0.5, randombytes@npm:^2.1.0": - version: 2.1.0 - resolution: "randombytes@npm:2.1.0" - dependencies: - safe-buffer: "npm:^5.1.0" - checksum: 10c0/50395efda7a8c94f5dffab564f9ff89736064d32addf0cc7e8bf5e4166f09f8ded7a0849ca6c2d2a59478f7d90f78f20d8048bca3cdf8be09d8e8a10790388f3 - languageName: node - linkType: hard - -"randomfill@npm:^1.0.4": - version: 1.0.4 - resolution: "randomfill@npm:1.0.4" - dependencies: - randombytes: "npm:^2.0.5" - safe-buffer: "npm:^5.1.0" - checksum: 10c0/11aeed35515872e8f8a2edec306734e6b74c39c46653607f03c68385ab8030e2adcc4215f76b5e4598e028c4750d820afd5c65202527d831d2a5f207fe2bc87c - languageName: node - linkType: hard - -"react-docgen-typescript@npm:^2.2.2": - version: 2.4.0 - resolution: "react-docgen-typescript@npm:2.4.0" - peerDependencies: - typescript: ">= 4.3.x" - checksum: 10c0/18e3e1c80d28abcdd72e62261d2f70b0904d9b088f9c2ebe485ffee5e46f5735208bc174a20ed2772112b3ca6432b5f3d5f0ac345872fe76e541f84543e49e50 - languageName: node - linkType: hard - -"react-docgen@npm:^8.0.0, react-docgen@npm:^8.0.2": - version: 8.0.3 - resolution: "react-docgen@npm:8.0.3" - dependencies: - "@babel/core": "npm:^7.28.0" - "@babel/traverse": "npm:^7.28.0" - "@babel/types": "npm:^7.28.2" - "@types/babel__core": "npm:^7.20.5" - "@types/babel__traverse": "npm:^7.20.7" - "@types/doctrine": "npm:^0.0.9" - "@types/resolve": "npm:^1.20.2" - doctrine: "npm:^3.0.0" - resolve: "npm:^1.22.1" - strip-indent: "npm:^4.0.0" - checksum: 10c0/0231fb9177bc7c633f3d1f228eebb0ee90a2f0feac50b1869ef70b0a3683b400d7875547a2d5168f2619b63d4cc29d7c45ae33d3f621fc67a7fa6790ac2049f6 - languageName: node - linkType: hard - -"react-dom@npm:19, react-dom@npm:^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0": - version: 19.2.4 - resolution: "react-dom@npm:19.2.4" - dependencies: - scheduler: "npm:^0.27.0" - peerDependencies: - react: ^19.2.4 - checksum: 10c0/f0c63f1794dedb154136d4d0f59af00b41907f4859571c155940296808f4b94bf9c0c20633db75b5b2112ec13d8d7dd4f9bf57362ed48782f317b11d05a44f35 - languageName: node - linkType: hard - -"react-i18next@npm:^16.0.0 <16.7.0": - version: 16.6.6 - resolution: "react-i18next@npm:16.6.6" - dependencies: - "@babel/runtime": "npm:^7.29.2" - html-parse-stringify: "npm:^3.0.1" - use-sync-external-store: "npm:^1.6.0" - peerDependencies: - i18next: ">= 25.10.9" - react: ">= 16.8.0" - typescript: ^5 || ^6 - peerDependenciesMeta: - react-dom: - optional: true - react-native: - optional: true - typescript: - optional: true - checksum: 10c0/7d6660d382a529d4dc56e7a7bbab59689ac0f435b3a18bba81d6bbf52c87b2a41fd5d1bffcf60b92b5e6e2a1ad9443949fcf16329d9c63d582316557199a7d32 - languageName: node - linkType: hard - -"react-is@npm:^16.13.1, react-is@npm:^16.7.0": - version: 16.13.1 - resolution: "react-is@npm:16.13.1" - checksum: 10c0/33977da7a5f1a287936a0c85639fec6ca74f4f15ef1e59a6bc20338fc73dc69555381e211f7a3529b8150a1f71e4225525b41b60b52965bda53ce7d47377ada1 - languageName: node - linkType: hard - -"react-is@npm:^17.0.1": - version: 17.0.2 - resolution: "react-is@npm:17.0.2" - checksum: 10c0/2bdb6b93fbb1820b024b496042cce405c57e2f85e777c9aabd55f9b26d145408f9f74f5934676ffdc46f3dcff656d78413a6e43968e7b3f92eea35b3052e9053 - languageName: node - linkType: hard - -"react-refresh@npm:^0.17.0": - version: 0.17.0 - resolution: "react-refresh@npm:0.17.0" - checksum: 10c0/002cba940384c9930008c0bce26cac97a9d5682bc623112c2268ba0c155127d9c178a9a5cc2212d560088d60dfd503edd808669a25f9b377f316a32361d0b23c - languageName: node - linkType: hard - -"react-remove-scroll-bar@npm:^2.3.7": - version: 2.3.8 - resolution: "react-remove-scroll-bar@npm:2.3.8" - dependencies: - react-style-singleton: "npm:^2.2.2" - tslib: "npm:^2.0.0" - peerDependencies: - "@types/react": "*" - react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 - peerDependenciesMeta: - "@types/react": - optional: true - checksum: 10c0/9a0675c66cbb52c325bdbfaed80987a829c4504cefd8ff2dd3b6b3afc9a1500b8ec57b212e92c1fb654396d07bbe18830a8146fe77677d2a29ce40b5e1f78654 - languageName: node - linkType: hard - -"react-remove-scroll@npm:^2.6.1": - version: 2.6.2 - resolution: "react-remove-scroll@npm:2.6.2" - dependencies: - react-remove-scroll-bar: "npm:^2.3.7" - react-style-singleton: "npm:^2.2.1" - tslib: "npm:^2.1.0" - use-callback-ref: "npm:^1.3.3" - use-sidecar: "npm:^1.1.2" - peerDependencies: - "@types/react": "*" - react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc - peerDependenciesMeta: - "@types/react": - optional: true - checksum: 10c0/8273e3f67a460af84b3387c93459b33920d48be15091c5ea10e8c1c4f514ad41f71dad028ee13df25370e5de16cadf02697fe28adaacbdacdf8b57bbf03ee559 - languageName: node - linkType: hard - -"react-remove-scroll@npm:^2.6.3": - version: 2.6.3 - resolution: "react-remove-scroll@npm:2.6.3" - dependencies: - react-remove-scroll-bar: "npm:^2.3.7" - react-style-singleton: "npm:^2.2.3" - tslib: "npm:^2.1.0" - use-callback-ref: "npm:^1.3.3" - use-sidecar: "npm:^1.1.3" - peerDependencies: - "@types/react": "*" - react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc - peerDependenciesMeta: - "@types/react": - optional: true - checksum: 10c0/068e9704ff26816fffc4c8903e2c6c8df7291ee08615d7c1ab0cf8751f7080e2c5a5d78ef5d908b11b9cfc189f176d312e44cb02ea291ca0466d8283b479b438 - languageName: node - linkType: hard - -"react-router-dom@npm:^7.0.0": - version: 7.13.2 - resolution: "react-router-dom@npm:7.13.2" - dependencies: - react-router: "npm:7.13.2" - peerDependencies: - react: ">=18" - react-dom: ">=18" - checksum: 10c0/ce9e5d47ba8accb7aa40272f83a98c3372634d0216ec92c8b20d52765ca62db06b4fde5284a4bd37cef2279b9767a45927f3b074e74e2c9b462c8599427bbfef - languageName: node - linkType: hard - -"react-router@npm:7.13.2": - version: 7.13.2 - resolution: "react-router@npm:7.13.2" - dependencies: - cookie: "npm:^1.0.1" - set-cookie-parser: "npm:^2.6.0" - peerDependencies: - react: ">=18" - react-dom: ">=18" - peerDependenciesMeta: - react-dom: - optional: true - checksum: 10c0/c7620565df0b444507cfceb76733adbd26e28a72fc4d52d344190bcb2e6483427313a3b6076c53d362e2682ccdb1262731bcaa6c3577cbbeea130291a38715f1 - languageName: node - linkType: hard - -"react-style-singleton@npm:^2.2.1, react-style-singleton@npm:^2.2.2, react-style-singleton@npm:^2.2.3": - version: 2.2.3 - resolution: "react-style-singleton@npm:2.2.3" - dependencies: - get-nonce: "npm:^1.0.0" - tslib: "npm:^2.0.0" - peerDependencies: - "@types/react": "*" - react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc - peerDependenciesMeta: - "@types/react": - optional: true - checksum: 10c0/841938ff16d16a6b76895f4cb2e1fea957e5fe3b30febbf03a54892dae1c9153f2383e231dea0b3ba41192ad2f2849448fa859caccd288943bce32639e971bee - languageName: node - linkType: hard - -"react-use-measure@npm:^2.1.1": - version: 2.1.7 - resolution: "react-use-measure@npm:2.1.7" - peerDependencies: - react: ">=16.13" - react-dom: ">=16.13" - peerDependenciesMeta: - react-dom: - optional: true - checksum: 10c0/ff24130e6f95e853feb6892fb74af08dbc5aae3574b701169e3bc3adb392c3162f51a58ddfe39bb7337db13ae609bbec0bb51a9de8b5fae5420f9d17e1f8b542 - languageName: node - linkType: hard - -"react@npm:19, react@npm:^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0": - version: 19.2.4 - resolution: "react@npm:19.2.4" - checksum: 10c0/cd2c9ff67a720799cc3b38a516009986f7fc4cb8d3e15716c6211cf098d1357ee3e348ab05ad0600042bbb0fd888530ba92e329198c92eafa0994f5213396596 - languageName: node - linkType: hard - -"read-pkg-up@npm:^7.0.1": - version: 7.0.1 - resolution: "read-pkg-up@npm:7.0.1" - dependencies: - find-up: "npm:^4.1.0" - read-pkg: "npm:^5.2.0" - type-fest: "npm:^0.8.1" - checksum: 10c0/82b3ac9fd7c6ca1bdc1d7253eb1091a98ff3d195ee0a45386582ce3e69f90266163c34121e6a0a02f1630073a6c0585f7880b3865efcae9c452fa667f02ca385 - languageName: node - linkType: hard - -"read-pkg@npm:^5.2.0": - version: 5.2.0 - resolution: "read-pkg@npm:5.2.0" - dependencies: - "@types/normalize-package-data": "npm:^2.4.0" - normalize-package-data: "npm:^2.5.0" - parse-json: "npm:^5.0.0" - type-fest: "npm:^0.6.0" - checksum: 10c0/b51a17d4b51418e777029e3a7694c9bd6c578a5ab99db544764a0b0f2c7c0f58f8a6bc101f86a6fceb8ba6d237d67c89acf6170f6b98695d0420ddc86cf109fb - languageName: node - linkType: hard - -"readable-stream@npm:^2.3.8, readable-stream@npm:~2.3.6": - version: 2.3.8 - resolution: "readable-stream@npm:2.3.8" - dependencies: - core-util-is: "npm:~1.0.0" - inherits: "npm:~2.0.3" - isarray: "npm:~1.0.0" - process-nextick-args: "npm:~2.0.0" - safe-buffer: "npm:~5.1.1" - string_decoder: "npm:~1.1.1" - util-deprecate: "npm:~1.0.1" - checksum: 10c0/7efdb01f3853bc35ac62ea25493567bf588773213f5f4a79f9c365e1ad13bab845ac0dae7bc946270dc40c3929483228415e92a3fc600cc7e4548992f41ee3fa - languageName: node - linkType: hard - -"readable-stream@npm:^3.4.0, readable-stream@npm:^3.5.0, readable-stream@npm:^3.6.0": - version: 3.6.2 - resolution: "readable-stream@npm:3.6.2" - dependencies: - inherits: "npm:^2.0.3" - string_decoder: "npm:^1.1.1" - util-deprecate: "npm:^1.0.1" - checksum: 10c0/e37be5c79c376fdd088a45fa31ea2e423e5d48854be7a22a58869b4e84d25047b193f6acb54f1012331e1bcd667ffb569c01b99d36b0bd59658fb33f513511b7 - languageName: node - linkType: hard - -"readdirp@npm:^4.0.1": - version: 4.1.2 - resolution: "readdirp@npm:4.1.2" - checksum: 10c0/60a14f7619dec48c9c850255cd523e2717001b0e179dc7037cfa0895da7b9e9ab07532d324bfb118d73a710887d1e35f79c495fa91582784493e085d18c72c62 - languageName: node - linkType: hard - -"readdirp@npm:~3.6.0": - version: 3.6.0 - resolution: "readdirp@npm:3.6.0" - dependencies: - picomatch: "npm:^2.2.1" - checksum: 10c0/6fa848cf63d1b82ab4e985f4cf72bd55b7dcfd8e0a376905804e48c3634b7e749170940ba77b32804d5fe93b3cc521aa95a8d7e7d725f830da6d93f3669ce66b - languageName: node - linkType: hard - -"recast@npm:^0.23.5": - version: 0.23.11 - resolution: "recast@npm:0.23.11" - dependencies: - ast-types: "npm:^0.16.1" - esprima: "npm:~4.0.0" - source-map: "npm:~0.6.1" - tiny-invariant: "npm:^1.3.3" - tslib: "npm:^2.0.1" - checksum: 10c0/45b520a8f0868a5a24ecde495be9de3c48e69a54295d82a7331106554b75cfba75d16c909959d056e9ceed47a1be5e061e2db8b9ecbcd6ba44c2f3ef9a47bd18 - languageName: node - linkType: hard - -"redent@npm:^3.0.0": - version: 3.0.0 - resolution: "redent@npm:3.0.0" - dependencies: - indent-string: "npm:^4.0.0" - strip-indent: "npm:^3.0.0" - checksum: 10c0/d64a6b5c0b50eb3ddce3ab770f866658a2b9998c678f797919ceb1b586bab9259b311407280bd80b804e2a7c7539b19238ae6a2a20c843f1a7fcff21d48c2eae - languageName: node - linkType: hard - -"reflect.getprototypeof@npm:^1.0.6, reflect.getprototypeof@npm:^1.0.9": - version: 1.0.10 - resolution: "reflect.getprototypeof@npm:1.0.10" - dependencies: - call-bind: "npm:^1.0.8" - define-properties: "npm:^1.2.1" - es-abstract: "npm:^1.23.9" - es-errors: "npm:^1.3.0" - es-object-atoms: "npm:^1.0.0" - get-intrinsic: "npm:^1.2.7" - get-proto: "npm:^1.0.1" - which-builtin-type: "npm:^1.2.1" - checksum: 10c0/7facec28c8008876f8ab98e80b7b9cb4b1e9224353fd4756dda5f2a4ab0d30fa0a5074777c6df24e1e0af463a2697513b0a11e548d99cf52f21f7bc6ba48d3ac - languageName: node - linkType: hard - -"regenerate-unicode-properties@npm:^10.2.0": - version: 10.2.0 - resolution: "regenerate-unicode-properties@npm:10.2.0" - dependencies: - regenerate: "npm:^1.4.2" - checksum: 10c0/5510785eeaf56bbfdf4e663d6753f125c08d2a372d4107bc1b756b7bf142e2ed80c2733a8b54e68fb309ba37690e66a0362699b0e21d5c1f0255dea1b00e6460 - languageName: node - linkType: hard - -"regenerate-unicode-properties@npm:^10.2.2": - version: 10.2.2 - resolution: "regenerate-unicode-properties@npm:10.2.2" - dependencies: - regenerate: "npm:^1.4.2" - checksum: 10c0/66a1d6a1dbacdfc49afd88f20b2319a4c33cee56d245163e4d8f5f283e0f45d1085a78f7f7406dd19ea3a5dd7a7799cd020cd817c97464a7507f9d10fbdce87c - languageName: node - linkType: hard - -"regenerate@npm:^1.4.2": - version: 1.4.2 - resolution: "regenerate@npm:1.4.2" - checksum: 10c0/f73c9eba5d398c818edc71d1c6979eaa05af7a808682749dd079f8df2a6d91a9b913db216c2c9b03e0a8ba2bba8701244a93f45211afbff691c32c7b275db1b8 - languageName: node - linkType: hard - -"regenerator-runtime@npm:^0.13.4": - version: 0.13.11 - resolution: "regenerator-runtime@npm:0.13.11" - checksum: 10c0/12b069dc774001fbb0014f6a28f11c09ebfe3c0d984d88c9bced77fdb6fedbacbca434d24da9ae9371bfbf23f754869307fb51a4c98a8b8b18e5ef748677ca24 - languageName: node - linkType: hard - -"regenerator-runtime@npm:^0.14.0": - version: 0.14.1 - resolution: "regenerator-runtime@npm:0.14.1" - checksum: 10c0/1b16eb2c4bceb1665c89de70dcb64126a22bc8eb958feef3cd68fe11ac6d2a4899b5cd1b80b0774c7c03591dc57d16631a7f69d2daa2ec98100e2f29f7ec4cc4 - languageName: node - linkType: hard - -"regexp-tree@npm:^0.1.27": - version: 0.1.27 - resolution: "regexp-tree@npm:0.1.27" - bin: - regexp-tree: bin/regexp-tree - checksum: 10c0/f636f44b4a0d93d7d6926585ecd81f63e4ce2ac895bc417b2ead0874cd36b337dcc3d0fedc63f69bf5aaeaa4340f36ca7e750c9687cceaf8087374e5284e843c - languageName: node - linkType: hard - -"regexp.prototype.flags@npm:^1.5.3, regexp.prototype.flags@npm:^1.5.4": - version: 1.5.4 - resolution: "regexp.prototype.flags@npm:1.5.4" - dependencies: - call-bind: "npm:^1.0.8" - define-properties: "npm:^1.2.1" - es-errors: "npm:^1.3.0" - get-proto: "npm:^1.0.1" - gopd: "npm:^1.2.0" - set-function-name: "npm:^2.0.2" - checksum: 10c0/83b88e6115b4af1c537f8dabf5c3744032cb875d63bc05c288b1b8c0ef37cbe55353f95d8ca817e8843806e3e150b118bc624e4279b24b4776b4198232735a77 - languageName: node - linkType: hard - -"regexparam@npm:^3.0.0": - version: 3.0.0 - resolution: "regexparam@npm:3.0.0" - checksum: 10c0/a6430d7b97d5a7d5518f37a850b6b73aab479029d02f46af4fa0e8e4a1d7aad05b7a0d2d10c86ded21a14d5f0fa4c68525f873a5fca2efeefcccd93c36627459 - languageName: node - linkType: hard - -"regexpu-core@npm:^6.2.0": - version: 6.2.0 - resolution: "regexpu-core@npm:6.2.0" - dependencies: - regenerate: "npm:^1.4.2" - regenerate-unicode-properties: "npm:^10.2.0" - regjsgen: "npm:^0.8.0" - regjsparser: "npm:^0.12.0" - unicode-match-property-ecmascript: "npm:^2.0.0" - unicode-match-property-value-ecmascript: "npm:^2.1.0" - checksum: 10c0/bbcb83a854bf96ce4005ee4e4618b71c889cda72674ce6092432f0039b47890c2d0dfeb9057d08d440999d9ea03879ebbb7f26ca005ccf94390e55c348859b98 - languageName: node - linkType: hard - -"regexpu-core@npm:^6.3.1": - version: 6.4.0 - resolution: "regexpu-core@npm:6.4.0" - dependencies: - regenerate: "npm:^1.4.2" - regenerate-unicode-properties: "npm:^10.2.2" - regjsgen: "npm:^0.8.0" - regjsparser: "npm:^0.13.0" - unicode-match-property-ecmascript: "npm:^2.0.0" - unicode-match-property-value-ecmascript: "npm:^2.2.1" - checksum: 10c0/1eed9783c023dd06fb1f3ce4b6e3fdf0bc1e30cb036f30aeb2019b351e5e0b74355b40462282ea5db092c79a79331c374c7e9897e44a5ca4509e9f0b570263de - languageName: node - linkType: hard - -"regjsgen@npm:^0.8.0": - version: 0.8.0 - resolution: "regjsgen@npm:0.8.0" - checksum: 10c0/44f526c4fdbf0b29286101a282189e4dbb303f4013cf3fea058668d96d113b9180d3d03d1e13f6d4cbde38b7728bf951aecd9dc199938c080093a9a6f0d7a6bd - languageName: node - linkType: hard - -"regjsparser@npm:^0.10.0": - version: 0.10.0 - resolution: "regjsparser@npm:0.10.0" - dependencies: - jsesc: "npm:~0.5.0" - bin: - regjsparser: bin/parser - checksum: 10c0/0f0508c142eddbceae55dab9715e714305c19e1e130db53168e8fa5f9f7ff9a4901f674cf6f71e04a0973b2f883882ba05808c80778b2d52b053d925050010f4 - languageName: node - linkType: hard - -"regjsparser@npm:^0.12.0": - version: 0.12.0 - resolution: "regjsparser@npm:0.12.0" - dependencies: - jsesc: "npm:~3.0.2" - bin: - regjsparser: bin/parser - checksum: 10c0/99d3e4e10c8c7732eb7aa843b8da2fd8b647fe144d3711b480e4647dc3bff4b1e96691ccf17f3ace24aa866a50b064236177cb25e6e4fbbb18285d99edaed83b - languageName: node - linkType: hard - -"regjsparser@npm:^0.13.0": - version: 0.13.0 - resolution: "regjsparser@npm:0.13.0" - dependencies: - jsesc: "npm:~3.1.0" - bin: - regjsparser: bin/parser - checksum: 10c0/4702f85cda09f67747c1b2fb673a0f0e5d1ba39d55f177632265a0be471ba59e3f320623f411649141f752b126b8126eac3ff4c62d317921e430b0472bfc6071 - languageName: node - linkType: hard - -"relateurl@npm:^0.2.7": - version: 0.2.7 - resolution: "relateurl@npm:0.2.7" - checksum: 10c0/c248b4e3b32474f116a804b537fa6343d731b80056fb506dffd91e737eef4cac6be47a65aae39b522b0db9d0b1011d1a12e288d82a109ecd94a5299d82f6573a - languageName: node - linkType: hard - -"remove-trailing-separator@npm:^1.1.0": - version: 1.1.0 - resolution: "remove-trailing-separator@npm:1.1.0" - checksum: 10c0/3568f9f8f5af3737b4aee9e6e1e8ec4be65a92da9cb27f989e0893714d50aa95ed2ff02d40d1fa35e1b1a234dc9c2437050ef356704a3999feaca6667d9e9bfc - languageName: node - linkType: hard - -"replace-ext@npm:^2.0.0": - version: 2.0.0 - resolution: "replace-ext@npm:2.0.0" - checksum: 10c0/52cb1006f83c5f07ef2c76b070c58bdeca1b67beded57d60593d1af8cd8ee731501d0433645cea8e9a4bf57a7018f47c9a3928c0463496cad1946fa85907aa47 - languageName: node - linkType: hard - -"require-directory@npm:^2.1.1": - version: 2.1.1 - resolution: "require-directory@npm:2.1.1" - checksum: 10c0/83aa76a7bc1531f68d92c75a2ca2f54f1b01463cb566cf3fbc787d0de8be30c9dbc211d1d46be3497dac5785fe296f2dd11d531945ac29730643357978966e99 - languageName: node - linkType: hard - -"require-main-filename@npm:^2.0.0": - version: 2.0.0 - resolution: "require-main-filename@npm:2.0.0" - checksum: 10c0/db91467d9ead311b4111cbd73a4e67fa7820daed2989a32f7023785a2659008c6d119752d9c4ac011ae07e537eb86523adff99804c5fdb39cd3a017f9b401bb6 - languageName: node - linkType: hard - -"requireindex@npm:~1.2.0": - version: 1.2.0 - resolution: "requireindex@npm:1.2.0" - checksum: 10c0/7fb42aed73bf8de9acc4d6716cf07acc7fbe180e58729433bafcf702e76e7bb10e54f8266c06bfec62d752e0ac14d50e8758833de539e6f4e2cd642077866153 - languageName: node - linkType: hard - -"reserved-identifiers@npm:^1.0.0": - version: 1.2.0 - resolution: "reserved-identifiers@npm:1.2.0" - checksum: 10c0/b82651b12e6c608e80463c3753d275bc20fd89294d0415f04e670aeec3611ae3582ddc19e8fedd497e7d0bcbfaddab6a12823ec86e855b1e6a245e0a734eb43d - languageName: node - linkType: hard - -"resolve-from@npm:^4.0.0": - version: 4.0.0 - resolution: "resolve-from@npm:4.0.0" - checksum: 10c0/8408eec31a3112ef96e3746c37be7d64020cda07c03a920f5024e77290a218ea758b26ca9529fd7b1ad283947f34b2291c1c0f6aa0ed34acfdda9c6014c8d190 - languageName: node - linkType: hard - -"resolve-options@npm:^2.0.0": - version: 2.0.0 - resolution: "resolve-options@npm:2.0.0" - dependencies: - value-or-function: "npm:^4.0.0" - checksum: 10c0/108f22186cad8748f1f0263944702a9949a12074e49442827845a52048f9156290781ceab8aee3e26ad868347266746704ee59a83a8f2fe2ce35228d054e325e - languageName: node - linkType: hard - -"resolve@npm:^1.10.0, resolve@npm:^1.22.4": - version: 1.22.8 - resolution: "resolve@npm:1.22.8" - dependencies: - is-core-module: "npm:^2.13.0" - path-parse: "npm:^1.0.7" - supports-preserve-symlinks-flag: "npm:^1.0.0" - bin: - resolve: bin/resolve - checksum: 10c0/07e179f4375e1fd072cfb72ad66d78547f86e6196c4014b31cb0b8bb1db5f7ca871f922d08da0fbc05b94e9fd42206f819648fa3b5b873ebbc8e1dc68fec433a - languageName: node - linkType: hard - -"resolve@npm:^1.17.0, resolve@npm:^1.22.1, resolve@npm:^1.22.11, resolve@npm:^1.22.8": - version: 1.22.11 - resolution: "resolve@npm:1.22.11" - dependencies: - is-core-module: "npm:^2.16.1" - path-parse: "npm:^1.0.7" - supports-preserve-symlinks-flag: "npm:^1.0.0" - bin: - resolve: bin/resolve - checksum: 10c0/f657191507530f2cbecb5815b1ee99b20741ea6ee02a59c57028e9ec4c2c8d7681afcc35febbd554ac0ded459db6f2d8153382c53a2f266cee2575e512674409 - languageName: node - linkType: hard - -"resolve@npm:^2.0.0-next.5": - version: 2.0.0-next.5 - resolution: "resolve@npm:2.0.0-next.5" - dependencies: - is-core-module: "npm:^2.13.0" - path-parse: "npm:^1.0.7" - supports-preserve-symlinks-flag: "npm:^1.0.0" - bin: - resolve: bin/resolve - checksum: 10c0/a6c33555e3482ea2ec4c6e3d3bf0d78128abf69dca99ae468e64f1e30acaa318fd267fb66c8836b04d558d3e2d6ed875fe388067e7d8e0de647d3c21af21c43a - languageName: node - linkType: hard - -"resolve@patch:resolve@npm%3A^1.10.0#optional!builtin, resolve@patch:resolve@npm%3A^1.22.4#optional!builtin": - version: 1.22.8 - resolution: "resolve@patch:resolve@npm%3A1.22.8#optional!builtin::version=1.22.8&hash=c3c19d" - dependencies: - is-core-module: "npm:^2.13.0" - path-parse: "npm:^1.0.7" - supports-preserve-symlinks-flag: "npm:^1.0.0" - bin: - resolve: bin/resolve - checksum: 10c0/0446f024439cd2e50c6c8fa8ba77eaa8370b4180f401a96abf3d1ebc770ac51c1955e12764cde449fde3fff480a61f84388e3505ecdbab778f4bef5f8212c729 - languageName: node - linkType: hard - -"resolve@patch:resolve@npm%3A^1.17.0#optional!builtin, resolve@patch:resolve@npm%3A^1.22.1#optional!builtin, resolve@patch:resolve@npm%3A^1.22.11#optional!builtin, resolve@patch:resolve@npm%3A^1.22.8#optional!builtin": - version: 1.22.11 - resolution: "resolve@patch:resolve@npm%3A1.22.11#optional!builtin::version=1.22.11&hash=c3c19d" - dependencies: - is-core-module: "npm:^2.16.1" - path-parse: "npm:^1.0.7" - supports-preserve-symlinks-flag: "npm:^1.0.0" - bin: - resolve: bin/resolve - checksum: 10c0/ee5b182f2e37cb1165465e58c6abc797fec0a80b5ba3231607beb4677db0c9291ac010c47cf092b6daa2b7f518d69a0e21888e7e2b633f68d501a874212a8c63 - languageName: node - linkType: hard - -"resolve@patch:resolve@npm%3A^2.0.0-next.5#optional!builtin": - version: 2.0.0-next.5 - resolution: "resolve@patch:resolve@npm%3A2.0.0-next.5#optional!builtin::version=2.0.0-next.5&hash=c3c19d" - dependencies: - is-core-module: "npm:^2.13.0" - path-parse: "npm:^1.0.7" - supports-preserve-symlinks-flag: "npm:^1.0.0" - bin: - resolve: bin/resolve - checksum: 10c0/78ad6edb8309a2bfb720c2c1898f7907a37f858866ce11a5974643af1203a6a6e05b2fa9c53d8064a673a447b83d42569260c306d43628bff5bb101969708355 - languageName: node - linkType: hard - -"retry@npm:^0.12.0": - version: 0.12.0 - resolution: "retry@npm:0.12.0" - checksum: 10c0/59933e8501727ba13ad73ef4a04d5280b3717fd650408460c987392efe9d7be2040778ed8ebe933c5cbd63da3dcc37919c141ef8af0a54a6e4fca5a2af177bfe - languageName: node - linkType: hard - -"reusify@npm:^1.0.4": - version: 1.1.0 - resolution: "reusify@npm:1.1.0" - checksum: 10c0/4eff0d4a5f9383566c7d7ec437b671cc51b25963bd61bf127c3f3d3f68e44a026d99b8d2f1ad344afff8d278a8fe70a8ea092650a716d22287e8bef7126bb2fa - languageName: node - linkType: hard - -"rimraf@npm:^2.5.4": - version: 2.7.1 - resolution: "rimraf@npm:2.7.1" - dependencies: - glob: "npm:^7.1.3" - bin: - rimraf: ./bin.js - checksum: 10c0/4eef73d406c6940927479a3a9dee551e14a54faf54b31ef861250ac815172bade86cc6f7d64a4dc5e98b65e4b18a2e1c9ff3b68d296be0c748413f092bb0dd40 - languageName: node - linkType: hard - -"rimraf@npm:^3.0.2": - version: 3.0.2 - resolution: "rimraf@npm:3.0.2" - dependencies: - glob: "npm:^7.1.3" - bin: - rimraf: bin.js - checksum: 10c0/9cb7757acb489bd83757ba1a274ab545eafd75598a9d817e0c3f8b164238dd90eba50d6b848bd4dcc5f3040912e882dc7ba71653e35af660d77b25c381d402e8 - languageName: node - linkType: hard - -"rimraf@npm:^5.0.5": - version: 5.0.10 - resolution: "rimraf@npm:5.0.10" - dependencies: - glob: "npm:^10.3.7" - bin: - rimraf: dist/esm/bin.mjs - checksum: 10c0/7da4fd0e15118ee05b918359462cfa1e7fe4b1228c7765195a45b55576e8c15b95db513b8466ec89129666f4af45ad978a3057a02139afba1a63512a2d9644cc - languageName: node - linkType: hard - -"ripemd160@npm:^2.0.0, ripemd160@npm:^2.0.1, ripemd160@npm:^2.0.3": - version: 2.0.3 - resolution: "ripemd160@npm:2.0.3" - dependencies: - hash-base: "npm:^3.1.2" - inherits: "npm:^2.0.4" - checksum: 10c0/3f472fb453241cfe692a77349accafca38dbcdc9d96d5848c088b2932ba41eb968630ecff7b175d291c7487a4945aee5a81e30c064d1f94e36070f7e0c37ed6c - languageName: node - linkType: hard - -"rolldown@npm:1.0.0-rc.12": - version: 1.0.0-rc.12 - resolution: "rolldown@npm:1.0.0-rc.12" - dependencies: - "@oxc-project/types": "npm:=0.122.0" - "@rolldown/binding-android-arm64": "npm:1.0.0-rc.12" - "@rolldown/binding-darwin-arm64": "npm:1.0.0-rc.12" - "@rolldown/binding-darwin-x64": "npm:1.0.0-rc.12" - "@rolldown/binding-freebsd-x64": "npm:1.0.0-rc.12" - "@rolldown/binding-linux-arm-gnueabihf": "npm:1.0.0-rc.12" - "@rolldown/binding-linux-arm64-gnu": "npm:1.0.0-rc.12" - "@rolldown/binding-linux-arm64-musl": "npm:1.0.0-rc.12" - "@rolldown/binding-linux-ppc64-gnu": "npm:1.0.0-rc.12" - "@rolldown/binding-linux-s390x-gnu": "npm:1.0.0-rc.12" - "@rolldown/binding-linux-x64-gnu": "npm:1.0.0-rc.12" - "@rolldown/binding-linux-x64-musl": "npm:1.0.0-rc.12" - "@rolldown/binding-openharmony-arm64": "npm:1.0.0-rc.12" - "@rolldown/binding-wasm32-wasi": "npm:1.0.0-rc.12" - "@rolldown/binding-win32-arm64-msvc": "npm:1.0.0-rc.12" - "@rolldown/binding-win32-x64-msvc": "npm:1.0.0-rc.12" - "@rolldown/pluginutils": "npm:1.0.0-rc.12" - dependenciesMeta: - "@rolldown/binding-android-arm64": - optional: true - "@rolldown/binding-darwin-arm64": - optional: true - "@rolldown/binding-darwin-x64": - optional: true - "@rolldown/binding-freebsd-x64": - optional: true - "@rolldown/binding-linux-arm-gnueabihf": - optional: true - "@rolldown/binding-linux-arm64-gnu": - optional: true - "@rolldown/binding-linux-arm64-musl": - optional: true - "@rolldown/binding-linux-ppc64-gnu": - optional: true - "@rolldown/binding-linux-s390x-gnu": - optional: true - "@rolldown/binding-linux-x64-gnu": - optional: true - "@rolldown/binding-linux-x64-musl": - optional: true - "@rolldown/binding-openharmony-arm64": - optional: true - "@rolldown/binding-wasm32-wasi": - optional: true - "@rolldown/binding-win32-arm64-msvc": - optional: true - "@rolldown/binding-win32-x64-msvc": - optional: true - bin: - rolldown: bin/cli.mjs - checksum: 10c0/0c4e5e3cdcdddce282cb2d84e1c98d6ad8d4e452d5c1402e498b35ec1060026e552dd783efc9f4ba876d7c0863b5973edc79b6a546f565e9832dc1077ec18c2c - languageName: node - linkType: hard - -"rrweb-cssom@npm:^0.8.0": - version: 0.8.0 - resolution: "rrweb-cssom@npm:0.8.0" - checksum: 10c0/56f2bfd56733adb92c0b56e274c43f864b8dd48784d6fe946ef5ff8d438234015e59ad837fc2ad54714b6421384141c1add4eb569e72054e350d1f8a50b8ac7b - languageName: node - linkType: hard - -"rsvp@npm:^4.8.5": - version: 4.8.5 - resolution: "rsvp@npm:4.8.5" - checksum: 10c0/7978f01060a48204506a8ebe15cdbd468498f5ae538b1d7ee3e7630375ba7cb2f98df2f596c12d3f4d5d5c21badc1c6ca8009f5142baded8511609a28eabd19a - languageName: node - linkType: hard - -"rsvp@npm:~3.2.1": - version: 3.2.1 - resolution: "rsvp@npm:3.2.1" - checksum: 10c0/7c075134976d0e95710ed62f87eaf01fa7dc1068357c9988f224e53509ac152ddeb1781cfd7784f13e2cc084c8dee71ad12317b758687b7ea107af2f8588704d - languageName: node - linkType: hard - -"run-applescript@npm:^7.0.0": - version: 7.1.0 - resolution: "run-applescript@npm:7.1.0" - checksum: 10c0/ab826c57c20f244b2ee807704b1ef4ba7f566aa766481ae5922aac785e2570809e297c69afcccc3593095b538a8a77d26f2b2e9a1d9dffee24e0e039502d1a03 - languageName: node - linkType: hard - -"run-parallel@npm:^1.1.9": - version: 1.2.0 - resolution: "run-parallel@npm:1.2.0" - dependencies: - queue-microtask: "npm:^1.2.2" - checksum: 10c0/200b5ab25b5b8b7113f9901bfe3afc347e19bb7475b267d55ad0eb86a62a46d77510cb0f232507c9e5d497ebda569a08a9867d0d14f57a82ad5564d991588b39 - languageName: node - linkType: hard - -"rxjs-report-usage@npm:^1.0.4": - version: 1.0.6 - resolution: "rxjs-report-usage@npm:1.0.6" - dependencies: - "@babel/parser": "npm:^7.10.3" - "@babel/traverse": "npm:^7.10.3" - "@babel/types": "npm:^7.10.3" - bent: "npm:~7.3.6" - chalk: "npm:~4.1.0" - glob: "npm:~7.2.0" - prompts: "npm:~2.4.2" - bin: - rxjs-report-usage: bin/rxjs-report-usage - checksum: 10c0/f87af567fcce83644cd028de6aaba5ee7555c85fc5b7f075068c4e48088b220721548c1b0cef9e8452def26257a098e732e062e82e494f236cf9ed5748bd8e5b - languageName: node - linkType: hard - -"rxjs@npm:*, rxjs@npm:^7.8.1": - version: 7.8.2 - resolution: "rxjs@npm:7.8.2" - dependencies: - tslib: "npm:^2.1.0" - checksum: 10c0/1fcd33d2066ada98ba8f21fcbbcaee9f0b271de1d38dc7f4e256bfbc6ffcdde68c8bfb69093de7eeb46f24b1fb820620bf0223706cff26b4ab99a7ff7b2e2c45 - languageName: node - linkType: hard - -"safe-array-concat@npm:^1.1.3": - version: 1.1.3 - resolution: "safe-array-concat@npm:1.1.3" - dependencies: - call-bind: "npm:^1.0.8" - call-bound: "npm:^1.0.2" - get-intrinsic: "npm:^1.2.6" - has-symbols: "npm:^1.1.0" - isarray: "npm:^2.0.5" - checksum: 10c0/43c86ffdddc461fb17ff8a17c5324f392f4868f3c7dd2c6a5d9f5971713bc5fd755667212c80eab9567595f9a7509cc2f83e590ddaebd1bd19b780f9c79f9a8d - languageName: node - linkType: hard - -"safe-buffer@npm:^5.0.1, safe-buffer@npm:^5.1.0, safe-buffer@npm:^5.1.1, safe-buffer@npm:^5.1.2, safe-buffer@npm:^5.2.1, safe-buffer@npm:~5.2.0": - version: 5.2.1 - resolution: "safe-buffer@npm:5.2.1" - checksum: 10c0/6501914237c0a86e9675d4e51d89ca3c21ffd6a31642efeba25ad65720bce6921c9e7e974e5be91a786b25aa058b5303285d3c15dbabf983a919f5f630d349f3 - languageName: node - linkType: hard - -"safe-buffer@npm:~5.1.0, safe-buffer@npm:~5.1.1": - version: 5.1.2 - resolution: "safe-buffer@npm:5.1.2" - checksum: 10c0/780ba6b5d99cc9a40f7b951d47152297d0e260f0df01472a1b99d4889679a4b94a13d644f7dbc4f022572f09ae9005fa2fbb93bbbd83643316f365a3e9a45b21 - languageName: node - linkType: hard - -"safe-push-apply@npm:^1.0.0": - version: 1.0.0 - resolution: "safe-push-apply@npm:1.0.0" - dependencies: - es-errors: "npm:^1.3.0" - isarray: "npm:^2.0.5" - checksum: 10c0/831f1c9aae7436429e7862c7e46f847dfe490afac20d0ee61bae06108dbf5c745a0de3568ada30ccdd3eeb0864ca8331b2eef703abd69bfea0745b21fd320750 - languageName: node - linkType: hard - -"safe-regex-test@npm:^1.0.3, safe-regex-test@npm:^1.1.0": - version: 1.1.0 - resolution: "safe-regex-test@npm:1.1.0" - dependencies: - call-bound: "npm:^1.0.2" - es-errors: "npm:^1.3.0" - is-regex: "npm:^1.2.1" - checksum: 10c0/f2c25281bbe5d39cddbbce7f86fca5ea9b3ce3354ea6cd7c81c31b006a5a9fff4286acc5450a3b9122c56c33eba69c56b9131ad751457b2b4a585825e6a10665 - languageName: node - linkType: hard - -"safer-buffer@npm:>= 2.1.2 < 3.0.0": - version: 2.1.2 - resolution: "safer-buffer@npm:2.1.2" - checksum: 10c0/7e3c8b2e88a1841c9671094bbaeebd94448111dd90a81a1f606f3f67708a6ec57763b3b47f06da09fc6054193e0e6709e77325415dc8422b04497a8070fa02d4 - languageName: node - linkType: hard - -"sass@npm:^1.42.1": - version: 1.98.0 - resolution: "sass@npm:1.98.0" - dependencies: - "@parcel/watcher": "npm:^2.4.1" - chokidar: "npm:^4.0.0" - immutable: "npm:^5.1.5" - source-map-js: "npm:>=0.6.2 <2.0.0" - dependenciesMeta: - "@parcel/watcher": - optional: true - bin: - sass: sass.js - checksum: 10c0/9e91daa20f970fefb364ac31289f070636da7aa7eaeb43e371ea98fa98085a6dbc2d3d058504226a02d07717faf0a4ce8d41b579ecb428c4a9d96b4dc1944a95 - languageName: node - linkType: hard - -"saxes@npm:^6.0.0": - version: 6.0.0 - resolution: "saxes@npm:6.0.0" - dependencies: - xmlchars: "npm:^2.2.0" - checksum: 10c0/3847b839f060ef3476eb8623d099aa502ad658f5c40fd60c105ebce86d244389b0d76fcae30f4d0c728d7705ceb2f7e9b34bb54717b6a7dbedaf5dad2d9a4b74 - languageName: node - linkType: hard - -"scheduler@npm:^0.27.0": - version: 0.27.0 - resolution: "scheduler@npm:0.27.0" - checksum: 10c0/4f03048cb05a3c8fddc45813052251eca00688f413a3cee236d984a161da28db28ba71bd11e7a3dd02f7af84ab28d39fb311431d3b3772fed557945beb00c452 - languageName: node - linkType: hard - -"sdp-transform@npm:^2.15.0": - version: 2.15.0 - resolution: "sdp-transform@npm:2.15.0" - bin: - sdp-verify: checker.js - checksum: 10c0/96c060f113a3d5418defa168db609f7e23e5bd7954fa1cf7784f103dbe702e24d667e5310d2ac6d88abdb32322af83d6ebd0df08e07f4f172d5ed5888f921386 - languageName: node - linkType: hard - -"sdp-transform@npm:^3.0.0": - version: 3.0.0 - resolution: "sdp-transform@npm:3.0.0" - bin: - sdp-verify: checker.js - checksum: 10c0/828a4595041ba64c86b29075aa4007ab384519b1fa29882db59ccb83b54b2b2a33b60848293f8da537fe151c52f5844fc17c8325396cac309fb19e2e81ec5bf4 - languageName: node - linkType: hard - -"sdp@npm:^3.2.0": - version: 3.2.0 - resolution: "sdp@npm:3.2.0" - checksum: 10c0/fa0146132b4c9185f276b80e09f52259b103e609565ac40c560250dbe7fc47723d30530c0db9cac6217c83153944a71af81fa70dc0367f195aabcf110f8185fd - languageName: node - linkType: hard - -"semver@npm:2 || 3 || 4 || 5": - version: 5.7.2 - resolution: "semver@npm:5.7.2" - bin: - semver: bin/semver - checksum: 10c0/e4cf10f86f168db772ae95d86ba65b3fd6c5967c94d97c708ccb463b778c2ee53b914cd7167620950fc07faf5a564e6efe903836639e512a1aa15fbc9667fa25 - languageName: node - linkType: hard - -"semver@npm:^6.3.1": - version: 6.3.1 - resolution: "semver@npm:6.3.1" - bin: - semver: bin/semver.js - checksum: 10c0/e3d79b609071caa78bcb6ce2ad81c7966a46a7431d9d58b8800cfa9cb6a63699b3899a0e4bcce36167a284578212d9ae6942b6929ba4aa5015c079a67751d42d - languageName: node - linkType: hard - -"semver@npm:^7.3.5, semver@npm:^7.5.3, semver@npm:^7.5.4, semver@npm:^7.6.0": - version: 7.7.1 - resolution: "semver@npm:7.7.1" - bin: - semver: bin/semver.js - checksum: 10c0/fd603a6fb9c399c6054015433051bdbe7b99a940a8fb44b85c2b524c4004b023d7928d47cb22154f8d054ea7ee8597f586605e05b52047f048278e4ac56ae958 - languageName: node - linkType: hard - -"semver@npm:^7.3.7, semver@npm:^7.6.3": - version: 7.6.3 - resolution: "semver@npm:7.6.3" - bin: - semver: bin/semver.js - checksum: 10c0/88f33e148b210c153873cb08cfe1e281d518aaa9a666d4d148add6560db5cd3c582f3a08ccb91f38d5f379ead256da9931234ed122057f40bb5766e65e58adaf - languageName: node - linkType: hard - -"semver@npm:^7.7.3": - version: 7.7.3 - resolution: "semver@npm:7.7.3" - bin: - semver: bin/semver.js - checksum: 10c0/4afe5c986567db82f44c8c6faef8fe9df2a9b1d98098fc1721f57c696c4c21cebd572f297fc21002f81889492345b8470473bc6f4aff5fb032a6ea59ea2bc45e - languageName: node - linkType: hard - -"set-blocking@npm:^2.0.0": - version: 2.0.0 - resolution: "set-blocking@npm:2.0.0" - checksum: 10c0/9f8c1b2d800800d0b589de1477c753492de5c1548d4ade52f57f1d1f5e04af5481554d75ce5e5c43d4004b80a3eb714398d6907027dc0534177b7539119f4454 - languageName: node - linkType: hard - -"set-cookie-parser@npm:^2.6.0": - version: 2.7.1 - resolution: "set-cookie-parser@npm:2.7.1" - checksum: 10c0/060c198c4c92547ac15988256f445eae523f57f2ceefeccf52d30d75dedf6bff22b9c26f756bd44e8e560d44ff4ab2130b178bd2e52ef5571bf7be3bd7632d9a - languageName: node - linkType: hard - -"set-function-length@npm:^1.2.2": - version: 1.2.2 - resolution: "set-function-length@npm:1.2.2" - dependencies: - define-data-property: "npm:^1.1.4" - es-errors: "npm:^1.3.0" - function-bind: "npm:^1.1.2" - get-intrinsic: "npm:^1.2.4" - gopd: "npm:^1.0.1" - has-property-descriptors: "npm:^1.0.2" - checksum: 10c0/82850e62f412a258b71e123d4ed3873fa9377c216809551192bb6769329340176f109c2eeae8c22a8d386c76739855f78e8716515c818bcaef384b51110f0f3c - languageName: node - linkType: hard - -"set-function-name@npm:^2.0.2": - version: 2.0.2 - resolution: "set-function-name@npm:2.0.2" - dependencies: - define-data-property: "npm:^1.1.4" - es-errors: "npm:^1.3.0" - functions-have-names: "npm:^1.2.3" - has-property-descriptors: "npm:^1.0.2" - checksum: 10c0/fce59f90696c450a8523e754abb305e2b8c73586452619c2bad5f7bf38c7b6b4651895c9db895679c5bef9554339cf3ef1c329b66ece3eda7255785fbe299316 - languageName: node - linkType: hard - -"set-proto@npm:^1.0.0": - version: 1.0.0 - resolution: "set-proto@npm:1.0.0" - dependencies: - dunder-proto: "npm:^1.0.1" - es-errors: "npm:^1.3.0" - es-object-atoms: "npm:^1.0.0" - checksum: 10c0/ca5c3ccbba479d07c30460e367e66337cec825560b11e8ba9c5ebe13a2a0d6021ae34eddf94ff3dfe17a3104dc1f191519cb6c48378b503e5c3f36393938776a - languageName: node - linkType: hard - -"setimmediate@npm:^1.0.4": - version: 1.0.5 - resolution: "setimmediate@npm:1.0.5" - checksum: 10c0/5bae81bfdbfbd0ce992893286d49c9693c82b1bcc00dcaaf3a09c8f428fdeacf4190c013598b81875dfac2b08a572422db7df779a99332d0fce186d15a3e4d49 - languageName: node - linkType: hard - -"sha.js@npm:^2.4.0, sha.js@npm:^2.4.12, sha.js@npm:^2.4.8": - version: 2.4.12 - resolution: "sha.js@npm:2.4.12" - dependencies: - inherits: "npm:^2.0.4" - safe-buffer: "npm:^5.2.1" - to-buffer: "npm:^1.2.0" - bin: - sha.js: bin.js - checksum: 10c0/9d36bdd76202c8116abbe152a00055ccd8a0099cb28fc17c01fa7bb2c8cffb9ca60e2ab0fe5f274ed6c45dc2633d8c39cf7ab050306c231904512ba9da4d8ab1 - languageName: node - linkType: hard - -"shebang-command@npm:^2.0.0": - version: 2.0.0 - resolution: "shebang-command@npm:2.0.0" - dependencies: - shebang-regex: "npm:^3.0.0" - checksum: 10c0/a41692e7d89a553ef21d324a5cceb5f686d1f3c040759c50aab69688634688c5c327f26f3ecf7001ebfd78c01f3c7c0a11a7c8bfd0a8bc9f6240d4f40b224e4e - languageName: node - linkType: hard - -"shebang-regex@npm:^3.0.0": - version: 3.0.0 - resolution: "shebang-regex@npm:3.0.0" - checksum: 10c0/1dbed0726dd0e1152a92696c76c7f06084eb32a90f0528d11acd764043aacf76994b2fb30aa1291a21bd019d6699164d048286309a278855ee7bec06cf6fb690 - languageName: node - linkType: hard - -"side-channel-list@npm:^1.0.0": - version: 1.0.0 - resolution: "side-channel-list@npm:1.0.0" - dependencies: - es-errors: "npm:^1.3.0" - object-inspect: "npm:^1.13.3" - checksum: 10c0/644f4ac893456c9490ff388bf78aea9d333d5e5bfc64cfb84be8f04bf31ddc111a8d4b83b85d7e7e8a7b845bc185a9ad02c052d20e086983cf59f0be517d9b3d - languageName: node - linkType: hard - -"side-channel-map@npm:^1.0.1": - version: 1.0.1 - resolution: "side-channel-map@npm:1.0.1" - dependencies: - call-bound: "npm:^1.0.2" - es-errors: "npm:^1.3.0" - get-intrinsic: "npm:^1.2.5" - object-inspect: "npm:^1.13.3" - checksum: 10c0/010584e6444dd8a20b85bc926d934424bd809e1a3af941cace229f7fdcb751aada0fb7164f60c2e22292b7fa3c0ff0bce237081fd4cdbc80de1dc68e95430672 - languageName: node - linkType: hard - -"side-channel-weakmap@npm:^1.0.2": - version: 1.0.2 - resolution: "side-channel-weakmap@npm:1.0.2" - dependencies: - call-bound: "npm:^1.0.2" - es-errors: "npm:^1.3.0" - get-intrinsic: "npm:^1.2.5" - object-inspect: "npm:^1.13.3" - side-channel-map: "npm:^1.0.1" - checksum: 10c0/71362709ac233e08807ccd980101c3e2d7efe849edc51455030327b059f6c4d292c237f94dc0685031dd11c07dd17a68afde235d6cf2102d949567f98ab58185 - languageName: node - linkType: hard - -"side-channel@npm:^1.1.0": - version: 1.1.0 - resolution: "side-channel@npm:1.1.0" - dependencies: - es-errors: "npm:^1.3.0" - object-inspect: "npm:^1.13.3" - side-channel-list: "npm:^1.0.0" - side-channel-map: "npm:^1.0.1" - side-channel-weakmap: "npm:^1.0.2" - checksum: 10c0/cb20dad41eb032e6c24c0982e1e5a24963a28aa6122b4f05b3f3d6bf8ae7fd5474ef382c8f54a6a3ab86e0cac4d41a23bd64ede3970e5bfb50326ba02a7996e6 - languageName: node - linkType: hard - -"siginfo@npm:^2.0.0": - version: 2.0.0 - resolution: "siginfo@npm:2.0.0" - checksum: 10c0/3def8f8e516fbb34cb6ae415b07ccc5d9c018d85b4b8611e3dc6f8be6d1899f693a4382913c9ed51a06babb5201639d76453ab297d1c54a456544acf5c892e34 - languageName: node - linkType: hard - -"signal-exit@npm:^4.0.1": - version: 4.1.0 - resolution: "signal-exit@npm:4.1.0" - checksum: 10c0/41602dce540e46d599edba9d9860193398d135f7ff72cab629db5171516cfae628d21e7bfccde1bbfdf11c48726bc2a6d1a8fb8701125852fbfda7cf19c6aa83 - languageName: node - linkType: hard - -"sisteransi@npm:^1.0.5": - version: 1.0.5 - resolution: "sisteransi@npm:1.0.5" - checksum: 10c0/230ac975cca485b7f6fe2b96a711aa62a6a26ead3e6fb8ba17c5a00d61b8bed0d7adc21f5626b70d7c33c62ff4e63933017a6462942c719d1980bb0b1207ad46 - languageName: node - linkType: hard - -"slash@npm:^3.0.0": - version: 3.0.0 - resolution: "slash@npm:3.0.0" - checksum: 10c0/e18488c6a42bdfd4ac5be85b2ced3ccd0224773baae6ad42cfbb9ec74fc07f9fa8396bd35ee638084ead7a2a0818eb5e7151111544d4731ce843019dab4be47b - languageName: node - linkType: hard - -"smart-buffer@npm:^4.2.0": - version: 4.2.0 - resolution: "smart-buffer@npm:4.2.0" - checksum: 10c0/a16775323e1404dd43fabafe7460be13a471e021637bc7889468eb45ce6a6b207261f454e4e530a19500cc962c4cc5348583520843b363f4193cee5c00e1e539 - languageName: node - linkType: hard - -"smol-toml@npm:^1.5.2": - version: 1.6.0 - resolution: "smol-toml@npm:1.6.0" - checksum: 10c0/baf33bb6cd914d481329e31998a12829cd126541458ba400791212c80f1245d5b27dac04a56a52c02b287d2a494f1628c05fc19643286b258b2e0bb9fe67747c - languageName: node - linkType: hard - -"snake-case@npm:^3.0.4": - version: 3.0.4 - resolution: "snake-case@npm:3.0.4" - dependencies: - dot-case: "npm:^3.0.4" - tslib: "npm:^2.0.3" - checksum: 10c0/ab19a913969f58f4474fe9f6e8a026c8a2142a01f40b52b79368068343177f818cdfef0b0c6b9558f298782441d5ca8ed5932eb57822439fad791d866e62cecd - languageName: node - linkType: hard - -"socks-proxy-agent@npm:^8.0.3": - version: 8.0.5 - resolution: "socks-proxy-agent@npm:8.0.5" - dependencies: - agent-base: "npm:^7.1.2" - debug: "npm:^4.3.4" - socks: "npm:^2.8.3" - checksum: 10c0/5d2c6cecba6821389aabf18728325730504bf9bb1d9e342e7987a5d13badd7a98838cc9a55b8ed3cb866ad37cc23e1086f09c4d72d93105ce9dfe76330e9d2a6 - languageName: node - linkType: hard - -"socks@npm:^2.8.3": - version: 2.8.4 - resolution: "socks@npm:2.8.4" - dependencies: - ip-address: "npm:^9.0.5" - smart-buffer: "npm:^4.2.0" - checksum: 10c0/00c3271e233ccf1fb83a3dd2060b94cc37817e0f797a93c560b9a7a86c4a0ec2961fb31263bdd24a3c28945e24868b5f063cd98744171d9e942c513454b50ae5 - languageName: node - linkType: hard - -"sort-keys@npm:^5.0.0": - version: 5.1.0 - resolution: "sort-keys@npm:5.1.0" - dependencies: - is-plain-obj: "npm:^4.0.0" - checksum: 10c0/fdb7aeb02368ad91b2ea947b59f3c95d80f8c71bbcb5741ebd55852994f54a129af3b3663b280951566fe5897de056428810dbb58c61db831e588c0ac110f2b0 - languageName: node - linkType: hard - -"source-map-js@npm:>=0.6.2 <2.0.0, source-map-js@npm:^1.2.1": - version: 1.2.1 - resolution: "source-map-js@npm:1.2.1" - checksum: 10c0/7bda1fc4c197e3c6ff17de1b8b2c20e60af81b63a52cb32ec5a5d67a20a7d42651e2cb34ebe93833c5a2a084377e17455854fee3e21e7925c64a51b6a52b0faf - languageName: node - linkType: hard - -"source-map-support@npm:~0.5.20": - version: 0.5.21 - resolution: "source-map-support@npm:0.5.21" - dependencies: - buffer-from: "npm:^1.0.0" - source-map: "npm:^0.6.0" - checksum: 10c0/9ee09942f415e0f721d6daad3917ec1516af746a8120bba7bb56278707a37f1eb8642bde456e98454b8a885023af81a16e646869975f06afc1a711fb90484e7d - languageName: node - linkType: hard - -"source-map@npm:^0.6.0, source-map@npm:~0.6.0, source-map@npm:~0.6.1": - version: 0.6.1 - resolution: "source-map@npm:0.6.1" - checksum: 10c0/ab55398007c5e5532957cb0beee2368529618ac0ab372d789806f5718123cc4367d57de3904b4e6a4170eb5a0b0f41373066d02ca0735a0c4d75c7d328d3e011 - languageName: node - linkType: hard - -"spdx-correct@npm:^3.0.0": - version: 3.2.0 - resolution: "spdx-correct@npm:3.2.0" - dependencies: - spdx-expression-parse: "npm:^3.0.0" - spdx-license-ids: "npm:^3.0.0" - checksum: 10c0/49208f008618b9119208b0dadc9208a3a55053f4fd6a0ae8116861bd22696fc50f4142a35ebfdb389e05ccf2de8ad142573fefc9e26f670522d899f7b2fe7386 - languageName: node - linkType: hard - -"spdx-exceptions@npm:^2.1.0": - version: 2.5.0 - resolution: "spdx-exceptions@npm:2.5.0" - checksum: 10c0/37217b7762ee0ea0d8b7d0c29fd48b7e4dfb94096b109d6255b589c561f57da93bf4e328c0290046115961b9209a8051ad9f525e48d433082fc79f496a4ea940 - languageName: node - linkType: hard - -"spdx-expression-parse@npm:^3.0.0": - version: 3.0.1 - resolution: "spdx-expression-parse@npm:3.0.1" - dependencies: - spdx-exceptions: "npm:^2.1.0" - spdx-license-ids: "npm:^3.0.0" - checksum: 10c0/6f8a41c87759fa184a58713b86c6a8b028250f158159f1d03ed9d1b6ee4d9eefdc74181c8ddc581a341aa971c3e7b79e30b59c23b05d2436d5de1c30bdef7171 - languageName: node - linkType: hard - -"spdx-expression-parse@npm:^4.0.0": - version: 4.0.0 - resolution: "spdx-expression-parse@npm:4.0.0" - dependencies: - spdx-exceptions: "npm:^2.1.0" - spdx-license-ids: "npm:^3.0.0" - checksum: 10c0/965c487e77f4fb173f1c471f3eef4eb44b9f0321adc7f93d95e7620da31faa67d29356eb02523cd7df8a7fc1ec8238773cdbf9e45bd050329d2b26492771b736 - languageName: node - linkType: hard - -"spdx-license-ids@npm:^3.0.0": - version: 3.0.20 - resolution: "spdx-license-ids@npm:3.0.20" - checksum: 10c0/bdff7534fad6ef59be49becda1edc3fb7f5b3d6f296a715516ab9d972b8ad59af2c34b2003e01db8970d4c673d185ff696ba74c6b61d3bf327e2b3eac22c297c - languageName: node - linkType: hard - -"sprintf-js@npm:^1.1.1, sprintf-js@npm:^1.1.3": - version: 1.1.3 - resolution: "sprintf-js@npm:1.1.3" - checksum: 10c0/09270dc4f30d479e666aee820eacd9e464215cdff53848b443964202bf4051490538e5dd1b42e1a65cf7296916ca17640aebf63dae9812749c7542ee5f288dec - languageName: node - linkType: hard - -"ssri@npm:^12.0.0": - version: 12.0.0 - resolution: "ssri@npm:12.0.0" - dependencies: - minipass: "npm:^7.0.3" - checksum: 10c0/caddd5f544b2006e88fa6b0124d8d7b28208b83c72d7672d5ade44d794525d23b540f3396108c4eb9280dcb7c01f0bef50682f5b4b2c34291f7c5e211fd1417d - languageName: node - linkType: hard - -"stackback@npm:0.0.2": - version: 0.0.2 - resolution: "stackback@npm:0.0.2" - checksum: 10c0/89a1416668f950236dd5ac9f9a6b2588e1b9b62b1b6ad8dff1bfc5d1a15dbf0aafc9b52d2226d00c28dffff212da464eaeebfc6b7578b9d180cef3e3782c5983 - languageName: node - linkType: hard - -"std-env@npm:^4.0.0-rc.1": - version: 4.0.0 - resolution: "std-env@npm:4.0.0" - checksum: 10c0/63b1716eae27947adde49e21b7225a0f75fb2c3d410273ae9de8333c07c7d5fc7a0628ae4c8af6b4b49b4274ed46c2bf118ed69b64f1261c9d8213d76ed1c16c - languageName: node - linkType: hard - -"stop-iteration-iterator@npm:^1.1.0": - version: 1.1.0 - resolution: "stop-iteration-iterator@npm:1.1.0" - dependencies: - es-errors: "npm:^1.3.0" - internal-slot: "npm:^1.1.0" - checksum: 10c0/de4e45706bb4c0354a4b1122a2b8cc45a639e86206807ce0baf390ee9218d3ef181923fa4d2b67443367c491aa255c5fbaa64bb74648e3c5b48299928af86c09 - languageName: node - linkType: hard - -"storybook@npm:^10.3.3": - version: 10.3.3 - resolution: "storybook@npm:10.3.3" - dependencies: - "@storybook/global": "npm:^5.0.0" - "@storybook/icons": "npm:^2.0.1" - "@testing-library/jest-dom": "npm:^6.9.1" - "@testing-library/user-event": "npm:^14.6.1" - "@vitest/expect": "npm:3.2.4" - "@vitest/spy": "npm:3.2.4" - esbuild: "npm:^0.18.0 || ^0.19.0 || ^0.20.0 || ^0.21.0 || ^0.22.0 || ^0.23.0 || ^0.24.0 || ^0.25.0 || ^0.26.0 || ^0.27.0" - open: "npm:^10.2.0" - recast: "npm:^0.23.5" - semver: "npm:^7.7.3" - use-sync-external-store: "npm:^1.5.0" - ws: "npm:^8.18.0" - peerDependencies: - prettier: ^2 || ^3 - peerDependenciesMeta: - prettier: - optional: true - bin: - storybook: ./dist/bin/dispatcher.js - checksum: 10c0/f61e199dfb11a02be6004a3d72c0ecd062f1770d60d480ecf42a6af8a6c49f9082b17c37fde2eea58ed53de35e7b190c95bcad8c8e4d47f9419d577826e0c00c - languageName: node - linkType: hard - -"stream-browserify@npm:^3.0.0": - version: 3.0.0 - resolution: "stream-browserify@npm:3.0.0" - dependencies: - inherits: "npm:~2.0.4" - readable-stream: "npm:^3.5.0" - checksum: 10c0/ec3b975a4e0aa4b3dc5e70ffae3fc8fd29ac725353a14e72f213dff477b00330140ad014b163a8cbb9922dfe90803f81a5ea2b269e1bbfd8bd71511b88f889ad - languageName: node - linkType: hard - -"stream-composer@npm:^1.0.2": - version: 1.0.2 - resolution: "stream-composer@npm:1.0.2" - dependencies: - streamx: "npm:^2.13.2" - checksum: 10c0/00b7c63e67dffa1f7d7149f47072e61e3e788aa1221a6116cac0186f387650816927e41b0934e615f47fec6d8d9c5b93cc85952748ed0238975090dfabf17fa7 - languageName: node - linkType: hard - -"stream-http@npm:^3.2.0": - version: 3.2.0 - resolution: "stream-http@npm:3.2.0" - dependencies: - builtin-status-codes: "npm:^3.0.0" - inherits: "npm:^2.0.4" - readable-stream: "npm:^3.6.0" - xtend: "npm:^4.0.2" - checksum: 10c0/f128fb8076d60cd548f229554b6a1a70c08a04b7b2afd4dbe7811d20f27f7d4112562eb8bce86d72a8691df3b50573228afcf1271e55e81f981536c67498bc41 - languageName: node - linkType: hard - -"streamx@npm:^2.12.0, streamx@npm:^2.12.5, streamx@npm:^2.13.2, streamx@npm:^2.14.0": - version: 2.22.0 - resolution: "streamx@npm:2.22.0" - dependencies: - bare-events: "npm:^2.2.0" - fast-fifo: "npm:^1.3.2" - text-decoder: "npm:^1.1.0" - dependenciesMeta: - bare-events: - optional: true - checksum: 10c0/f5017998a5b6360ba652599d20ef308c8c8ab0e26c8e5f624f0706f0ea12624e94fdf1ec18318124498529a1b106a1ab1c94a1b1e1ad6c2eec7cb9c8ac1b9198 - languageName: node - linkType: hard - -"string-width-cjs@npm:string-width@^4.2.0, string-width@npm:^4.1.0, string-width@npm:^4.2.0, string-width@npm:^4.2.3": - version: 4.2.3 - resolution: "string-width@npm:4.2.3" - dependencies: - emoji-regex: "npm:^8.0.0" - is-fullwidth-code-point: "npm:^3.0.0" - strip-ansi: "npm:^6.0.1" - checksum: 10c0/1e525e92e5eae0afd7454086eed9c818ee84374bb80328fc41217ae72ff5f065ef1c9d7f72da41de40c75fa8bb3dee63d92373fd492c84260a552c636392a47b - languageName: node - linkType: hard - -"string-width@npm:^5.0.1, string-width@npm:^5.1.2": - version: 5.1.2 - resolution: "string-width@npm:5.1.2" - dependencies: - eastasianwidth: "npm:^0.2.0" - emoji-regex: "npm:^9.2.2" - strip-ansi: "npm:^7.0.1" - checksum: 10c0/ab9c4264443d35b8b923cbdd513a089a60de339216d3b0ed3be3ba57d6880e1a192b70ae17225f764d7adbf5994e9bb8df253a944736c15a0240eff553c678ca - languageName: node - linkType: hard - -"string.prototype.includes@npm:^2.0.1": - version: 2.0.1 - resolution: "string.prototype.includes@npm:2.0.1" - dependencies: - call-bind: "npm:^1.0.7" - define-properties: "npm:^1.2.1" - es-abstract: "npm:^1.23.3" - checksum: 10c0/25ce9c9b49128352a2618fbe8758b46f945817a58a4420f4799419e40a8d28f116e176c7590d767d5327a61e75c8f32c86171063f48e389b9fdd325f1bd04ee5 - languageName: node - linkType: hard - -"string.prototype.matchall@npm:^4.0.12": - version: 4.0.12 - resolution: "string.prototype.matchall@npm:4.0.12" - dependencies: - call-bind: "npm:^1.0.8" - call-bound: "npm:^1.0.3" - define-properties: "npm:^1.2.1" - es-abstract: "npm:^1.23.6" - es-errors: "npm:^1.3.0" - es-object-atoms: "npm:^1.0.0" - get-intrinsic: "npm:^1.2.6" - gopd: "npm:^1.2.0" - has-symbols: "npm:^1.1.0" - internal-slot: "npm:^1.1.0" - regexp.prototype.flags: "npm:^1.5.3" - set-function-name: "npm:^2.0.2" - side-channel: "npm:^1.1.0" - checksum: 10c0/1a53328ada73f4a77f1fdf1c79414700cf718d0a8ef6672af5603e709d26a24f2181208144aed7e858b1bcc1a0d08567a570abfb45567db4ae47637ed2c2f85c - languageName: node - linkType: hard - -"string.prototype.repeat@npm:^1.0.0": - version: 1.0.0 - resolution: "string.prototype.repeat@npm:1.0.0" - dependencies: - define-properties: "npm:^1.1.3" - es-abstract: "npm:^1.17.5" - checksum: 10c0/94c7978566cffa1327d470fd924366438af9b04b497c43a9805e476e2e908aa37a1fd34cc0911156c17556dab62159d12c7b92b3cc304c3e1281fe4c8e668f40 - languageName: node - linkType: hard - -"string.prototype.trim@npm:^1.2.10": - version: 1.2.10 - resolution: "string.prototype.trim@npm:1.2.10" - dependencies: - call-bind: "npm:^1.0.8" - call-bound: "npm:^1.0.2" - define-data-property: "npm:^1.1.4" - define-properties: "npm:^1.2.1" - es-abstract: "npm:^1.23.5" - es-object-atoms: "npm:^1.0.0" - has-property-descriptors: "npm:^1.0.2" - checksum: 10c0/8a8854241c4b54a948e992eb7dd6b8b3a97185112deb0037a134f5ba57541d8248dd610c966311887b6c2fd1181a3877bffb14d873ce937a344535dabcc648f8 - languageName: node - linkType: hard - -"string.prototype.trimend@npm:^1.0.9": - version: 1.0.9 - resolution: "string.prototype.trimend@npm:1.0.9" - dependencies: - call-bind: "npm:^1.0.8" - call-bound: "npm:^1.0.2" - define-properties: "npm:^1.2.1" - es-object-atoms: "npm:^1.0.0" - checksum: 10c0/59e1a70bf9414cb4c536a6e31bef5553c8ceb0cf44d8b4d0ed65c9653358d1c64dd0ec203b100df83d0413bbcde38b8c5d49e14bc4b86737d74adc593a0d35b6 - languageName: node - linkType: hard - -"string.prototype.trimstart@npm:^1.0.8": - version: 1.0.8 - resolution: "string.prototype.trimstart@npm:1.0.8" - dependencies: - call-bind: "npm:^1.0.7" - define-properties: "npm:^1.2.1" - es-object-atoms: "npm:^1.0.0" - checksum: 10c0/d53af1899959e53c83b64a5fd120be93e067da740e7e75acb433849aa640782fb6c7d4cd5b84c954c84413745a3764df135a8afeb22908b86a835290788d8366 - languageName: node - linkType: hard - -"string_decoder@npm:^1.0.0, string_decoder@npm:^1.1.1": - version: 1.3.0 - resolution: "string_decoder@npm:1.3.0" - dependencies: - safe-buffer: "npm:~5.2.0" - checksum: 10c0/810614ddb030e271cd591935dcd5956b2410dd079d64ff92a1844d6b7588bf992b3e1b69b0f4d34a3e06e0bd73046ac646b5264c1987b20d0601f81ef35d731d - languageName: node - linkType: hard - -"string_decoder@npm:~1.1.1": - version: 1.1.1 - resolution: "string_decoder@npm:1.1.1" - dependencies: - safe-buffer: "npm:~5.1.0" - checksum: 10c0/b4f89f3a92fd101b5653ca3c99550e07bdf9e13b35037e9e2a1c7b47cec4e55e06ff3fc468e314a0b5e80bfbaf65c1ca5a84978764884ae9413bec1fc6ca924e - languageName: node - linkType: hard - -"strip-ansi-cjs@npm:strip-ansi@^6.0.1, strip-ansi@npm:^6.0.0, strip-ansi@npm:^6.0.1": - version: 6.0.1 - resolution: "strip-ansi@npm:6.0.1" - dependencies: - ansi-regex: "npm:^5.0.1" - checksum: 10c0/1ae5f212a126fe5b167707f716942490e3933085a5ff6c008ab97ab2f272c8025d3aa218b7bd6ab25729ca20cc81cddb252102f8751e13482a5199e873680952 - languageName: node - linkType: hard - -"strip-ansi@npm:^7.0.1": - version: 7.1.0 - resolution: "strip-ansi@npm:7.1.0" - dependencies: - ansi-regex: "npm:^6.0.1" - checksum: 10c0/a198c3762e8832505328cbf9e8c8381de14a4fa50a4f9b2160138158ea88c0f5549fb50cb13c651c3088f47e63a108b34622ec18c0499b6c8c3a5ddf6b305ac4 - languageName: node - linkType: hard - -"strip-bom@npm:^3.0.0": - version: 3.0.0 - resolution: "strip-bom@npm:3.0.0" - checksum: 10c0/51201f50e021ef16672593d7434ca239441b7b760e905d9f33df6e4f3954ff54ec0e0a06f100d028af0982d6f25c35cd5cda2ce34eaebccd0250b8befb90d8f1 - languageName: node - linkType: hard - -"strip-indent@npm:^3.0.0": - version: 3.0.0 - resolution: "strip-indent@npm:3.0.0" - dependencies: - min-indent: "npm:^1.0.0" - checksum: 10c0/ae0deaf41c8d1001c5d4fbe16cb553865c1863da4fae036683b474fa926af9fc121e155cb3fc57a68262b2ae7d5b8420aa752c97a6428c315d00efe2a3875679 - languageName: node - linkType: hard - -"strip-indent@npm:^4.0.0": - version: 4.1.1 - resolution: "strip-indent@npm:4.1.1" - checksum: 10c0/5b23dd5934be0ef6b6fe1b802887f83e56ad9dcd9f6c3896a637da2c6c3a6da3fdf3e51354a98e6cccb6f1c41863e7b9b9deaa348639dfd35f71f3549edb4dff - languageName: node - linkType: hard - -"strip-json-comments@npm:5.0.3": - version: 5.0.3 - resolution: "strip-json-comments@npm:5.0.3" - checksum: 10c0/daaf20b29f69fb51112698f4a9a662490dbb78d5baf6127c75a0a83c2ac6c078a8c0f74b389ad5e0519d6fc359c4a57cb9971b1ae201aef62ce45a13247791e0 - languageName: node - linkType: hard - -"strip-json-comments@npm:^3.1.1": - version: 3.1.1 - resolution: "strip-json-comments@npm:3.1.1" - checksum: 10c0/9681a6257b925a7fa0f285851c0e613cc934a50661fa7bb41ca9cbbff89686bb4a0ee366e6ecedc4daafd01e83eee0720111ab294366fe7c185e935475ebcecd - languageName: node - linkType: hard - -"supports-color@npm:^5.3.0": - version: 5.5.0 - resolution: "supports-color@npm:5.5.0" - dependencies: - has-flag: "npm:^3.0.0" - checksum: 10c0/6ae5ff319bfbb021f8a86da8ea1f8db52fac8bd4d499492e30ec17095b58af11f0c55f8577390a749b1c4dde691b6a0315dab78f5f54c9b3d83f8fb5905c1c05 - languageName: node - linkType: hard - -"supports-color@npm:^7.1.0": - version: 7.2.0 - resolution: "supports-color@npm:7.2.0" - dependencies: - has-flag: "npm:^4.0.0" - checksum: 10c0/afb4c88521b8b136b5f5f95160c98dee7243dc79d5432db7efc27efb219385bbc7d9427398e43dd6cc730a0f87d5085ce1652af7efbe391327bc0a7d0f7fc124 - languageName: node - linkType: hard - -"supports-preserve-symlinks-flag@npm:^1.0.0": - version: 1.0.0 - resolution: "supports-preserve-symlinks-flag@npm:1.0.0" - checksum: 10c0/6c4032340701a9950865f7ae8ef38578d8d7053f5e10518076e6554a9381fa91bd9c6850193695c141f32b21f979c985db07265a758867bac95de05f7d8aeb39 - languageName: node - linkType: hard - -"svg-parser@npm:^2.0.4": - version: 2.0.4 - resolution: "svg-parser@npm:2.0.4" - checksum: 10c0/02f6cb155dd7b63ebc2f44f36365bc294543bebb81b614b7628f1af3c54ab64f7e1cec20f06e252bf95bdde78441ae295a412c68ad1678f16a6907d924512b7a - languageName: node - linkType: hard - -"symbol-tree@npm:^3.2.4": - version: 3.2.4 - resolution: "symbol-tree@npm:3.2.4" - checksum: 10c0/dfbe201ae09ac6053d163578778c53aa860a784147ecf95705de0cd23f42c851e1be7889241495e95c37cabb058edb1052f141387bef68f705afc8f9dd358509 - languageName: node - linkType: hard - -"symlink-or-copy@npm:^1.1.8, symlink-or-copy@npm:^1.2.0, symlink-or-copy@npm:^1.3.1": - version: 1.3.1 - resolution: "symlink-or-copy@npm:1.3.1" - checksum: 10c0/0d3842c359ce56991e912623fb75e76843e71a828c72f16024d717c842954c84086d90776738a6f0d5a4314f14b56580cfa48facba6b26b4da06aa7e80595931 - languageName: node - linkType: hard - -"tabbable@npm:^6.0.0": - version: 6.2.0 - resolution: "tabbable@npm:6.2.0" - checksum: 10c0/ced8b38f05f2de62cd46836d77c2646c42b8c9713f5bd265daf0e78ff5ac73d3ba48a7ca45f348bafeef29b23da7187c72250742d37627883ef89cbd7fa76898 - languageName: node - linkType: hard - -"tar@npm:^7.5.11": - version: 7.5.13 - resolution: "tar@npm:7.5.13" - dependencies: - "@isaacs/fs-minipass": "npm:^4.0.0" - chownr: "npm:^3.0.0" - minipass: "npm:^7.1.2" - minizlib: "npm:^3.1.0" - yallist: "npm:^5.0.0" - checksum: 10c0/5c65b8084799bde7a791593a1c1a45d3d6ee98182e3700b24c247b7b8f8654df4191642abbdb07ff25043d45dcff35620827c3997b88ae6c12040f64bed5076b - languageName: node - linkType: hard - -"teex@npm:^1.0.1": - version: 1.0.1 - resolution: "teex@npm:1.0.1" - dependencies: - streamx: "npm:^2.12.5" - checksum: 10c0/8df9166c037ba694b49d32a49858e314c60e513d55ac5e084dbf1ddbb827c5fa43cc389a81e87684419c21283308e9d68bb068798189c767ec4c252f890b8a77 - languageName: node - linkType: hard - -"terser@npm:^5.10.0": - version: 5.39.0 - resolution: "terser@npm:5.39.0" - dependencies: - "@jridgewell/source-map": "npm:^0.3.3" - acorn: "npm:^8.8.2" - commander: "npm:^2.20.0" - source-map-support: "npm:~0.5.20" - bin: - terser: bin/terser - checksum: 10c0/83326545ea1aecd6261030568b6191ccfa4cb6aa61d9ea41746a52479f50017a78b77e4725fbbc207c5df841ffa66a773c5ac33636e95c7ab94fe7e0379ae5c7 - languageName: node - linkType: hard - -"text-decoder@npm:^1.1.0": - version: 1.2.3 - resolution: "text-decoder@npm:1.2.3" - dependencies: - b4a: "npm:^1.6.4" - checksum: 10c0/569d776b9250158681c83656ef2c3e0a5d5c660c27ca69f87eedef921749a4fbf02095e5f9a0f862a25cf35258379b06e31dee9c125c9f72e273b7ca1a6d1977 - languageName: node - linkType: hard - -"text-table@npm:^0.2.0": - version: 0.2.0 - resolution: "text-table@npm:0.2.0" - checksum: 10c0/02805740c12851ea5982686810702e2f14369a5f4c5c40a836821e3eefc65ffeec3131ba324692a37608294b0fd8c1e55a2dd571ffed4909822787668ddbee5c - languageName: node - linkType: hard - -"through2@npm:^2.0.1": - version: 2.0.5 - resolution: "through2@npm:2.0.5" - dependencies: - readable-stream: "npm:~2.3.6" - xtend: "npm:~4.0.1" - checksum: 10c0/cbfe5b57943fa12b4f8c043658c2a00476216d79c014895cef1ac7a1d9a8b31f6b438d0e53eecbb81054b93128324a82ecd59ec1a4f91f01f7ac113dcb14eade - languageName: node - linkType: hard - -"timers-browserify@npm:^2.0.4": - version: 2.0.12 - resolution: "timers-browserify@npm:2.0.12" - dependencies: - setimmediate: "npm:^1.0.4" - checksum: 10c0/98e84db1a685bc8827c117a8bc62aac811ad56a995d07938fc7ed8cdc5bf3777bfe2d4e5da868847194e771aac3749a20f6cdd22091300fe889a76fe214a4641 - languageName: node - linkType: hard - -"tiny-invariant@npm:^1.3.3": - version: 1.3.3 - resolution: "tiny-invariant@npm:1.3.3" - checksum: 10c0/65af4a07324b591a059b35269cd696aba21bef2107f29b9f5894d83cc143159a204b299553435b03874ebb5b94d019afa8b8eff241c8a4cfee95872c2e1c1c4a - languageName: node - linkType: hard - -"tinybench@npm:^2.9.0": - version: 2.9.0 - resolution: "tinybench@npm:2.9.0" - checksum: 10c0/c3500b0f60d2eb8db65250afe750b66d51623057ee88720b7f064894a6cb7eb93360ca824a60a31ab16dab30c7b1f06efe0795b352e37914a9d4bad86386a20c - languageName: node - linkType: hard - -"tinyexec@npm:^1.0.2": - version: 1.0.2 - resolution: "tinyexec@npm:1.0.2" - checksum: 10c0/1261a8e34c9b539a9aae3b7f0bb5372045ff28ee1eba035a2a059e532198fe1a182ec61ac60fa0b4a4129f0c4c4b1d2d57355b5cb9aa2d17ac9454ecace502ee - languageName: node - linkType: hard - -"tinyglobby@npm:^0.2.15": - version: 0.2.15 - resolution: "tinyglobby@npm:0.2.15" - dependencies: - fdir: "npm:^6.5.0" - picomatch: "npm:^4.0.3" - checksum: 10c0/869c31490d0d88eedb8305d178d4c75e7463e820df5a9b9d388291daf93e8b1eb5de1dad1c1e139767e4269fe75f3b10d5009b2cc14db96ff98986920a186844 - languageName: node - linkType: hard - -"tinyrainbow@npm:^2.0.0": - version: 2.0.0 - resolution: "tinyrainbow@npm:2.0.0" - checksum: 10c0/c83c52bef4e0ae7fb8ec6a722f70b5b6fa8d8be1c85792e829f56c0e1be94ab70b293c032dc5048d4d37cfe678f1f5babb04bdc65fd123098800148ca989184f - languageName: node - linkType: hard - -"tinyrainbow@npm:^3.1.0": - version: 3.1.0 - resolution: "tinyrainbow@npm:3.1.0" - checksum: 10c0/f11cf387a26c5c9255bec141a90ac511b26172981b10c3e50053bc6700ea7d2336edcc4a3a21dbb8412fe7c013477d2ba4d7e4877800f3f8107be5105aad6511 - languageName: node - linkType: hard - -"tinyspy@npm:^4.0.3": - version: 4.0.4 - resolution: "tinyspy@npm:4.0.4" - checksum: 10c0/a8020fc17799251e06a8398dcc352601d2770aa91c556b9531ecd7a12581161fd1c14e81cbdaff0c1306c93bfdde8ff6d1c1a3f9bbe6d91604f0fd4e01e2f1eb - languageName: node - linkType: hard - -"tldts-core@npm:^6.1.48": - version: 6.1.48 - resolution: "tldts-core@npm:6.1.48" - checksum: 10c0/3e635ff51848e2f1bf4f325f1e8c627943c8615cf47e5d5301744798ded49df51d72288f27964ea06e9e0c02f05d75c98d5e89fa468663d315cd80b1d66687b1 - languageName: node - linkType: hard - -"tldts@npm:^6.1.32": - version: 6.1.48 - resolution: "tldts@npm:6.1.48" - dependencies: - tldts-core: "npm:^6.1.48" - bin: - tldts: bin/cli.js - checksum: 10c0/eefa0f871df25159faebcb79e0ae2de83f3fd6bd1f0d19ec87a15d69017a8c887a68eacfdf85d84f36b7a3aaf6583bf2337d22edb1406df7d5dc0aaffb2444f7 - languageName: node - linkType: hard - -"to-buffer@npm:^1.2.0, to-buffer@npm:^1.2.1, to-buffer@npm:^1.2.2": - version: 1.2.2 - resolution: "to-buffer@npm:1.2.2" - dependencies: - isarray: "npm:^2.0.5" - safe-buffer: "npm:^5.2.1" - typed-array-buffer: "npm:^1.0.3" - checksum: 10c0/56bc56352f14a2c4a0ab6277c5fc19b51e9534882b98eb068b39e14146591e62fa5b06bf70f7fed1626230463d7e60dca81e815096656e5e01c195c593873d12 - languageName: node - linkType: hard - -"to-regex-range@npm:^5.0.1": - version: 5.0.1 - resolution: "to-regex-range@npm:5.0.1" - dependencies: - is-number: "npm:^7.0.0" - checksum: 10c0/487988b0a19c654ff3e1961b87f471702e708fa8a8dd02a298ef16da7206692e8552a0250e8b3e8759270f62e9d8314616f6da274734d3b558b1fc7b7724e892 - languageName: node - linkType: hard - -"to-through@npm:^3.0.0": - version: 3.0.0 - resolution: "to-through@npm:3.0.0" - dependencies: - streamx: "npm:^2.12.5" - checksum: 10c0/9b1a6eb85ceff159db21678b7d9aec1d8b99a63dae01ce95b074df1f37f9d92e3ed7d5284f394917a079dda37d53f8eeef8fc74ef506b97cc35629925f29b464 - languageName: node - linkType: hard - -"to-valid-identifier@npm:^1.0.0": - version: 1.0.0 - resolution: "to-valid-identifier@npm:1.0.0" - dependencies: - "@sindresorhus/base62": "npm:^1.0.0" - reserved-identifiers: "npm:^1.0.0" - checksum: 10c0/569b49f43b5aaaa20677e67f0f1cdcff344855149934cfb80c793c7ac7c30e191b224bc81cab40fb57641af9ca73795c78053c164a2addc617671e2d22c13a4a - languageName: node - linkType: hard - -"toggle-selection@npm:^1.0.6": - version: 1.0.6 - resolution: "toggle-selection@npm:1.0.6" - checksum: 10c0/f2cf1f2c70f374fd87b0cdc8007453ba9e981c4305a8bf4eac10a30e62ecdfd28bca7d18f8f15b15a506bf8a7bfb20dbe3539f0fcf2a2c8396c1a78d53e1f179 - languageName: node - linkType: hard - -"tough-cookie@npm:^5.1.1": - version: 5.1.2 - resolution: "tough-cookie@npm:5.1.2" - dependencies: - tldts: "npm:^6.1.32" - checksum: 10c0/5f95023a47de0f30a902bba951664b359725597d8adeabc66a0b93a931c3af801e1e697dae4b8c21a012056c0ea88bd2bf4dfe66b2adcf8e2f42cd9796fe0626 - languageName: node - linkType: hard - -"tr46@npm:^5.0.0": - version: 5.0.0 - resolution: "tr46@npm:5.0.0" - dependencies: - punycode: "npm:^2.3.1" - checksum: 10c0/1521b6e7bbc8adc825c4561480f9fe48eb2276c81335eed9fa610aa4c44a48a3221f78b10e5f18b875769eb3413e30efbf209ed556a17a42aa8d690df44b7bee - languageName: node - linkType: hard - -"tr46@npm:^5.1.0": - version: 5.1.1 - resolution: "tr46@npm:5.1.1" - dependencies: - punycode: "npm:^2.3.1" - checksum: 10c0/ae270e194d52ec67ebd695c1a42876e0f19b96e4aca2ab464ab1d9d17dc3acd3e18764f5034c93897db73421563be27c70c98359c4501136a497e46deda5d5ec - languageName: node - linkType: hard - -"tr46@npm:~0.0.3": - version: 0.0.3 - resolution: "tr46@npm:0.0.3" - checksum: 10c0/047cb209a6b60c742f05c9d3ace8fa510bff609995c129a37ace03476a9b12db4dbf975e74600830ef0796e18882b2381fb5fb1f6b4f96b832c374de3ab91a11 - languageName: node - linkType: hard - -"ts-api-utils@npm:^2.0.1": - version: 2.0.1 - resolution: "ts-api-utils@npm:2.0.1" - peerDependencies: - typescript: ">=4.8.4" - checksum: 10c0/23fd56a958b332cac00150a652e4c84730df30571bd2faa1ba6d7b511356d1a61656621492bb6c7f15dd6e18847a1408357a0e406671d358115369a17f5bfedd - languageName: node - linkType: hard - -"ts-api-utils@npm:^2.4.0, ts-api-utils@npm:^2.5.0": - version: 2.5.0 - resolution: "ts-api-utils@npm:2.5.0" - peerDependencies: - typescript: ">=4.8.4" - checksum: 10c0/767849383c114e7f1971fa976b20e73ac28fd0c70d8d65c0004790bf4d8f89888c7e4cf6d5949f9c1beae9bc3c64835bef77bbe27fddf45a3c7b60cebcf85c8c - languageName: node - linkType: hard - -"ts-dedent@npm:^2.0.0": - version: 2.2.0 - resolution: "ts-dedent@npm:2.2.0" - checksum: 10c0/175adea838468cc2ff7d5e97f970dcb798bbcb623f29c6088cb21aa2880d207c5784be81ab1741f56b9ac37840cbaba0c0d79f7f8b67ffe61c02634cafa5c303 - languageName: node - linkType: hard - -"tsconfig-paths@npm:^3.15.0": - version: 3.15.0 - resolution: "tsconfig-paths@npm:3.15.0" - dependencies: - "@types/json5": "npm:^0.0.29" - json5: "npm:^1.0.2" - minimist: "npm:^1.2.6" - strip-bom: "npm:^3.0.0" - checksum: 10c0/5b4f301a2b7a3766a986baf8fc0e177eb80bdba6e396792ff92dc23b5bca8bb279fc96517dcaaef63a3b49bebc6c4c833653ec58155780bc906bdbcf7dda0ef5 - languageName: node - linkType: hard - -"tsconfig-paths@npm:^4.2.0": - version: 4.2.0 - resolution: "tsconfig-paths@npm:4.2.0" - dependencies: - json5: "npm:^2.2.2" - minimist: "npm:^1.2.6" - strip-bom: "npm:^3.0.0" - checksum: 10c0/09a5877402d082bb1134930c10249edeebc0211f36150c35e1c542e5b91f1047b1ccf7da1e59babca1ef1f014c525510f4f870de7c9bda470c73bb4e2721b3ea - languageName: node - linkType: hard - -"tslib@npm:2.8.1, tslib@npm:^2.0.0, tslib@npm:^2.0.1, tslib@npm:^2.0.3, tslib@npm:^2.1.0, tslib@npm:^2.4.0, tslib@npm:^2.8.0": - version: 2.8.1 - resolution: "tslib@npm:2.8.1" - checksum: 10c0/9c4759110a19c53f992d9aae23aac5ced636e99887b51b9e61def52611732872ff7668757d4e4c61f19691e36f4da981cd9485e869b4a7408d689f6bf1f14e62 - languageName: node - linkType: hard - -"tslib@npm:^1.8.1": - version: 1.14.1 - resolution: "tslib@npm:1.14.1" - checksum: 10c0/69ae09c49eea644bc5ebe1bca4fa4cc2c82b7b3e02f43b84bd891504edf66dbc6b2ec0eef31a957042de2269139e4acff911e6d186a258fb14069cd7f6febce2 - languageName: node - linkType: hard - -"tsutils-etc@npm:^1.4.1": - version: 1.4.2 - resolution: "tsutils-etc@npm:1.4.2" - dependencies: - "@types/yargs": "npm:^17.0.0" - yargs: "npm:^17.0.0" - peerDependencies: - tsutils: ^3.0.0 - typescript: ">=4.0.0" - bin: - ts-flags: bin/ts-flags - ts-kind: bin/ts-kind - checksum: 10c0/7b07273627f2f4af2a785a073d0fead7c0c0d1133fee68e5de19f2aca4b01ea35a08de2c97e75f58fb6ba6ddb03ad490abf056bb8b71fb01e84bfed1b8a24a0d - languageName: node - linkType: hard - -"tsutils@npm:^3.0.0, tsutils@npm:^3.17.1, tsutils@npm:^3.21.0": - version: 3.21.0 - resolution: "tsutils@npm:3.21.0" - dependencies: - tslib: "npm:^1.8.1" - peerDependencies: - typescript: ">=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta" - checksum: 10c0/02f19e458ec78ead8fffbf711f834ad8ecd2cc6ade4ec0320790713dccc0a412b99e7fd907c4cda2a1dc602c75db6f12e0108e87a5afad4b2f9e90a24cabd5a2 - languageName: node - linkType: hard - -"tty-browserify@npm:0.0.1": - version: 0.0.1 - resolution: "tty-browserify@npm:0.0.1" - checksum: 10c0/5e34883388eb5f556234dae75b08e069b9e62de12bd6d87687f7817f5569430a6dfef550b51dbc961715ae0cd0eb5a059e6e3fc34dc127ea164aa0f9b5bb033d - languageName: node - linkType: hard - -"tunnel@npm:^0.0.6": - version: 0.0.6 - resolution: "tunnel@npm:0.0.6" - checksum: 10c0/e27e7e896f2426c1c747325b5f54efebc1a004647d853fad892b46d64e37591ccd0b97439470795e5262b5c0748d22beb4489a04a0a448029636670bfd801b75 - languageName: node - linkType: hard - -"type-check@npm:^0.4.0, type-check@npm:~0.4.0": - version: 0.4.0 - resolution: "type-check@npm:0.4.0" - dependencies: - prelude-ls: "npm:^1.2.1" - checksum: 10c0/7b3fd0ed43891e2080bf0c5c504b418fbb3e5c7b9708d3d015037ba2e6323a28152ec163bcb65212741fa5d2022e3075ac3c76440dbd344c9035f818e8ecee58 - languageName: node - linkType: hard - -"type-fest@npm:^0.20.2": - version: 0.20.2 - resolution: "type-fest@npm:0.20.2" - checksum: 10c0/dea9df45ea1f0aaa4e2d3bed3f9a0bfe9e5b2592bddb92eb1bf06e50bcf98dbb78189668cd8bc31a0511d3fc25539b4cd5c704497e53e93e2d40ca764b10bfc3 - languageName: node - linkType: hard - -"type-fest@npm:^0.6.0": - version: 0.6.0 - resolution: "type-fest@npm:0.6.0" - checksum: 10c0/0c585c26416fce9ecb5691873a1301b5aff54673c7999b6f925691ed01f5b9232db408cdbb0bd003d19f5ae284322523f44092d1f81ca0a48f11f7cf0be8cd38 - languageName: node - linkType: hard - -"type-fest@npm:^0.8.1": - version: 0.8.1 - resolution: "type-fest@npm:0.8.1" - checksum: 10c0/dffbb99329da2aa840f506d376c863bd55f5636f4741ad6e65e82f5ce47e6914108f44f340a0b74009b0cb5d09d6752ae83203e53e98b1192cf80ecee5651636 - languageName: node - linkType: hard - -"typed-array-buffer@npm:^1.0.3": - version: 1.0.3 - resolution: "typed-array-buffer@npm:1.0.3" - dependencies: - call-bound: "npm:^1.0.3" - es-errors: "npm:^1.3.0" - is-typed-array: "npm:^1.1.14" - checksum: 10c0/1105071756eb248774bc71646bfe45b682efcad93b55532c6ffa4518969fb6241354e4aa62af679ae83899ec296d69ef88f1f3763657cdb3a4d29321f7b83079 - languageName: node - linkType: hard - -"typed-array-byte-length@npm:^1.0.3": - version: 1.0.3 - resolution: "typed-array-byte-length@npm:1.0.3" - dependencies: - call-bind: "npm:^1.0.8" - for-each: "npm:^0.3.3" - gopd: "npm:^1.2.0" - has-proto: "npm:^1.2.0" - is-typed-array: "npm:^1.1.14" - checksum: 10c0/6ae083c6f0354f1fce18b90b243343b9982affd8d839c57bbd2c174a5d5dc71be9eb7019ffd12628a96a4815e7afa85d718d6f1e758615151d5f35df841ffb3e - languageName: node - linkType: hard - -"typed-array-byte-offset@npm:^1.0.4": - version: 1.0.4 - resolution: "typed-array-byte-offset@npm:1.0.4" - dependencies: - available-typed-arrays: "npm:^1.0.7" - call-bind: "npm:^1.0.8" - for-each: "npm:^0.3.3" - gopd: "npm:^1.2.0" - has-proto: "npm:^1.2.0" - is-typed-array: "npm:^1.1.15" - reflect.getprototypeof: "npm:^1.0.9" - checksum: 10c0/3d805b050c0c33b51719ee52de17c1cd8e6a571abdf0fffb110e45e8dd87a657e8b56eee94b776b13006d3d347a0c18a730b903cf05293ab6d92e99ff8f77e53 - languageName: node - linkType: hard - -"typed-array-length@npm:^1.0.7": - version: 1.0.7 - resolution: "typed-array-length@npm:1.0.7" - dependencies: - call-bind: "npm:^1.0.7" - for-each: "npm:^0.3.3" - gopd: "npm:^1.0.1" - is-typed-array: "npm:^1.1.13" - possible-typed-array-names: "npm:^1.0.0" - reflect.getprototypeof: "npm:^1.0.6" - checksum: 10c0/e38f2ae3779584c138a2d8adfa8ecf749f494af3cd3cdafe4e688ce51418c7d2c5c88df1bd6be2bbea099c3f7cea58c02ca02ed438119e91f162a9de23f61295 - languageName: node - linkType: hard - -"typed-emitter@npm:^2.1.0": - version: 2.1.0 - resolution: "typed-emitter@npm:2.1.0" - dependencies: - rxjs: "npm:*" - dependenciesMeta: - rxjs: - optional: true - checksum: 10c0/01fc354ba8e87bd39b1bf4fe1c96fe7ecff7fde83161003b0f8c7f4b285a368052e185ba655dd8c102c4445301b7a1e032c8972f181b440fc95bd810450f1314 - languageName: node - linkType: hard - -"typescript-eslint-language-service@npm:^5.0.5": - version: 5.0.5 - resolution: "typescript-eslint-language-service@npm:5.0.5" - peerDependencies: - "@typescript-eslint/parser": ">= 5.0.0" - eslint: ">= 8.0.0" - typescript: ">= 4.0.0" - checksum: 10c0/61b3ce5a124ad3b2ea6ac06b19e8192b1f3f5db01ecaf3009302979172b2eeaee78f9051fd4a687230b55acadc5272ecf90297d57b09078c97a271016ccbcf07 - languageName: node - linkType: hard - -"typescript@npm:^5.0.4, typescript@npm:^5.8.3": - version: 5.9.3 - resolution: "typescript@npm:5.9.3" - bin: - tsc: bin/tsc - tsserver: bin/tsserver - checksum: 10c0/6bd7552ce39f97e711db5aa048f6f9995b53f1c52f7d8667c1abdc1700c68a76a308f579cd309ce6b53646deb4e9a1be7c813a93baaf0a28ccd536a30270e1c5 - languageName: node - linkType: hard - -"typescript@patch:typescript@npm%3A^5.0.4#optional!builtin, typescript@patch:typescript@npm%3A^5.8.3#optional!builtin": - version: 5.9.3 - resolution: "typescript@patch:typescript@npm%3A5.9.3#optional!builtin::version=5.9.3&hash=5786d5" - bin: - tsc: bin/tsc - tsserver: bin/tsserver - checksum: 10c0/ad09fdf7a756814dce65bc60c1657b40d44451346858eea230e10f2e95a289d9183b6e32e5c11e95acc0ccc214b4f36289dcad4bf1886b0adb84d711d336a430 - languageName: node - linkType: hard - -"unbash@npm:^2.2.0": - version: 2.2.0 - resolution: "unbash@npm:2.2.0" - checksum: 10c0/f218a30e2b65147dba16fcea5d9cbfe5af9d9518e98083b9790b9884959c82c5c8f85e7feeea717430e2ea6b352a1d57ad98e90fe488638606de12c9254cbf35 - languageName: node - linkType: hard - -"unbox-primitive@npm:^1.1.0": - version: 1.1.0 - resolution: "unbox-primitive@npm:1.1.0" - dependencies: - call-bound: "npm:^1.0.3" - has-bigints: "npm:^1.0.2" - has-symbols: "npm:^1.1.0" - which-boxed-primitive: "npm:^1.1.1" - checksum: 10c0/7dbd35ab02b0e05fe07136c72cb9355091242455473ec15057c11430129bab38b7b3624019b8778d02a881c13de44d63cd02d122ee782fb519e1de7775b5b982 - languageName: node - linkType: hard - -"underscore.string@npm:~3.3.4": - version: 3.3.6 - resolution: "underscore.string@npm:3.3.6" - dependencies: - sprintf-js: "npm:^1.1.1" - util-deprecate: "npm:^1.0.2" - checksum: 10c0/172319c7ef5436587e6f0fb5afe0b2e6b50f723a4070c7fb3454c5dfa5398ed3b7042c049eac2826bdd44d37cbd16b2b965d0ccc1597fde354b1d3a846fd4a39 - languageName: node - linkType: hard - -"undici-types@npm:~7.16.0": - version: 7.16.0 - resolution: "undici-types@npm:7.16.0" - checksum: 10c0/3033e2f2b5c9f1504bdc5934646cb54e37ecaca0f9249c983f7b1fc2e87c6d18399ebb05dc7fd5419e02b2e915f734d872a65da2e3eeed1813951c427d33cc9a - languageName: node - linkType: hard - -"undici-types@npm:~7.18.0": - version: 7.18.2 - resolution: "undici-types@npm:7.18.2" - checksum: 10c0/85a79189113a238959d7a647368e4f7c5559c3a404ebdb8fc4488145ce9426fcd82252a844a302798dfc0e37e6fb178ff481ed03bc4caf634c5757d9ef43521d - languageName: node - linkType: hard - -"undici@npm:^5.25.4": - version: 5.29.0 - resolution: "undici@npm:5.29.0" - dependencies: - "@fastify/busboy": "npm:^2.0.0" - checksum: 10c0/e4e4d631ca54ee0ad82d2e90e7798fa00a106e27e6c880687e445cc2f13b4bc87c5eba2a88c266c3eecffb18f26e227b778412da74a23acc374fca7caccec49b - languageName: node - linkType: hard - -"undici@npm:^6.19.5": - version: 6.21.3 - resolution: "undici@npm:6.21.3" - checksum: 10c0/294da109853fad7a6ef5a172ad0ca3fb3f1f60cf34703d062a5ec967daf69ad8c03b52e6d536c5cba3bb65615769bf08e5b30798915cbccdddaca01045173dda - languageName: node - linkType: hard - -"unhomoglyph@npm:^1.0.6": - version: 1.0.6 - resolution: "unhomoglyph@npm:1.0.6" - checksum: 10c0/a720b7eadf3d756351eb66971d10e07c5b4a93fb930d0322604d0ba125dea752f6e2d38959bdc493dc7d50f12df6bb369d14e7e41dffed55602cae10d66c3b29 - languageName: node - linkType: hard - -"unicode-canonical-property-names-ecmascript@npm:^2.0.0": - version: 2.0.1 - resolution: "unicode-canonical-property-names-ecmascript@npm:2.0.1" - checksum: 10c0/f83bc492fdbe662860795ef37a85910944df7310cac91bd778f1c19ebc911e8b9cde84e703de631e5a2fcca3905e39896f8fc5fc6a44ddaf7f4aff1cda24f381 - languageName: node - linkType: hard - -"unicode-match-property-ecmascript@npm:^2.0.0": - version: 2.0.0 - resolution: "unicode-match-property-ecmascript@npm:2.0.0" - dependencies: - unicode-canonical-property-names-ecmascript: "npm:^2.0.0" - unicode-property-aliases-ecmascript: "npm:^2.0.0" - checksum: 10c0/4d05252cecaf5c8e36d78dc5332e03b334c6242faf7cf16b3658525441386c0a03b5f603d42cbec0f09bb63b9fd25c9b3b09667aee75463cac3efadae2cd17ec - languageName: node - linkType: hard - -"unicode-match-property-value-ecmascript@npm:^2.1.0": - version: 2.2.0 - resolution: "unicode-match-property-value-ecmascript@npm:2.2.0" - checksum: 10c0/1d0a2deefd97974ddff5b7cb84f9884177f4489928dfcebb4b2b091d6124f2739df51fc6ea15958e1b5637ac2a24cff9bf21ea81e45335086ac52c0b4c717d6d - languageName: node - linkType: hard - -"unicode-match-property-value-ecmascript@npm:^2.2.1": - version: 2.2.1 - resolution: "unicode-match-property-value-ecmascript@npm:2.2.1" - checksum: 10c0/93acd1ad9496b600e5379d1aaca154cf551c5d6d4a0aefaf0984fc2e6288e99220adbeb82c935cde461457fb6af0264a1774b8dfd4d9a9e31548df3352a4194d - languageName: node - linkType: hard - -"unicode-property-aliases-ecmascript@npm:^2.0.0": - version: 2.1.0 - resolution: "unicode-property-aliases-ecmascript@npm:2.1.0" - checksum: 10c0/50ded3f8c963c7785e48c510a3b7c6bc4e08a579551489aa0349680a35b1ceceec122e33b2b6c1b579d0be2250f34bb163ac35f5f8695fe10bbc67fb757f0af8 - languageName: node - linkType: hard - -"unique-filename@npm:^4.0.0": - version: 4.0.0 - resolution: "unique-filename@npm:4.0.0" - dependencies: - unique-slug: "npm:^5.0.0" - checksum: 10c0/38ae681cceb1408ea0587b6b01e29b00eee3c84baee1e41fd5c16b9ed443b80fba90c40e0ba69627e30855570a34ba8b06702d4a35035d4b5e198bf5a64c9ddc - languageName: node - linkType: hard - -"unique-names-generator@npm:^4.6.0": - version: 4.7.1 - resolution: "unique-names-generator@npm:4.7.1" - checksum: 10c0/db07b9a0fee6eac4a21cf567c9744ee97895aa744d51ec913557205173a65c1a7a4d12470295796acb7247e6646e7975c340bb634c7adf41e5d950fa5cf94375 - languageName: node - linkType: hard - -"unique-slug@npm:^5.0.0": - version: 5.0.0 - resolution: "unique-slug@npm:5.0.0" - dependencies: - imurmurhash: "npm:^0.1.4" - checksum: 10c0/d324c5a44887bd7e105ce800fcf7533d43f29c48757ac410afd42975de82cc38ea2035c0483f4de82d186691bf3208ef35c644f73aa2b1b20b8e651be5afd293 - languageName: node - linkType: hard - -"universal-user-agent@npm:^6.0.0": - version: 6.0.1 - resolution: "universal-user-agent@npm:6.0.1" - checksum: 10c0/5c9c46ffe19a975e11e6443640ed4c9e0ce48fcc7203325757a8414ac49940ebb0f4667f2b1fa561489d1eb22cb2d05a0f7c82ec20c5cba42e58e188fb19b187 - languageName: node - linkType: hard - -"universalify@npm:^0.1.0": - version: 0.1.2 - resolution: "universalify@npm:0.1.2" - checksum: 10c0/e70e0339f6b36f34c9816f6bf9662372bd241714dc77508d231d08386d94f2c4aa1ba1318614f92015f40d45aae1b9075cd30bd490efbe39387b60a76ca3f045 - languageName: node - linkType: hard - -"universalify@npm:^2.0.0": - version: 2.0.1 - resolution: "universalify@npm:2.0.1" - checksum: 10c0/73e8ee3809041ca8b818efb141801a1004e3fc0002727f1531f4de613ea281b494a40909596dae4a042a4fb6cd385af5d4db2e137b1362e0e91384b828effd3a - languageName: node - linkType: hard - -"unplugin@npm:1.0.1": - version: 1.0.1 - resolution: "unplugin@npm:1.0.1" - dependencies: - acorn: "npm:^8.8.1" - chokidar: "npm:^3.5.3" - webpack-sources: "npm:^3.2.3" - webpack-virtual-modules: "npm:^0.5.0" - checksum: 10c0/7d59b5a28abc1cdbd6356a10f273d1266f59c3be083ab0e659a37d02d047d5df1b435e0f40f5ec97517e8fc910d314592f0d197ccceb75ef47c71c1898ec7a05 - languageName: node - linkType: hard - -"unplugin@npm:^1.10.1": - version: 1.16.1 - resolution: "unplugin@npm:1.16.1" - dependencies: - acorn: "npm:^8.14.0" - webpack-virtual-modules: "npm:^0.6.2" - checksum: 10c0/dd5f8c5727d0135847da73cf03fb199107f1acf458167034886fda3405737dab871ad3926431b4f70e1e82cdac482ac1383cea4019d782a68515c8e3e611b6cc - languageName: node - linkType: hard - -"unplugin@npm:^2.3.5": - version: 2.3.11 - resolution: "unplugin@npm:2.3.11" - dependencies: - "@jridgewell/remapping": "npm:^2.3.5" - acorn: "npm:^8.15.0" - picomatch: "npm:^4.0.3" - webpack-virtual-modules: "npm:^0.6.2" - checksum: 10c0/273c1eab0eca4470c7317428689295c31dbe8ab0b306504de9f03cd20c156debb4131bef24b27ac615862958c5dd950a3951d26c0723ea774652ab3624149cff - languageName: node - linkType: hard - -"update-browserslist-db@npm:^1.1.1": - version: 1.1.3 - resolution: "update-browserslist-db@npm:1.1.3" - dependencies: - escalade: "npm:^3.2.0" - picocolors: "npm:^1.1.1" - peerDependencies: - browserslist: ">= 4.21.0" - bin: - update-browserslist-db: cli.js - checksum: 10c0/682e8ecbf9de474a626f6462aa85927936cdd256fe584c6df2508b0df9f7362c44c957e9970df55dfe44d3623807d26316ea2c7d26b80bb76a16c56c37233c32 - languageName: node - linkType: hard - -"update-browserslist-db@npm:^1.2.0": - version: 1.2.3 - resolution: "update-browserslist-db@npm:1.2.3" - dependencies: - escalade: "npm:^3.2.0" - picocolors: "npm:^1.1.1" - peerDependencies: - browserslist: ">= 4.21.0" - bin: - update-browserslist-db: cli.js - checksum: 10c0/13a00355ea822388f68af57410ce3255941d5fb9b7c49342c4709a07c9f230bbef7f7499ae0ca7e0de532e79a82cc0c4edbd125f1a323a1845bf914efddf8bec - languageName: node - linkType: hard - -"uri-js@npm:^4.2.2": - version: 4.4.1 - resolution: "uri-js@npm:4.4.1" - dependencies: - punycode: "npm:^2.1.0" - checksum: 10c0/4ef57b45aa820d7ac6496e9208559986c665e49447cb072744c13b66925a362d96dd5a46c4530a6b8e203e5db5fe849369444440cb22ecfc26c679359e5dfa3c - languageName: node - linkType: hard - -"url@npm:^0.11.4": - version: 0.11.4 - resolution: "url@npm:0.11.4" - dependencies: - punycode: "npm:^1.4.1" - qs: "npm:^6.12.3" - checksum: 10c0/cc93405ae4a9b97a2aa60ca67f1cb1481c0221cb4725a7341d149be5e2f9cfda26fd432d64dbbec693d16593b68b8a46aad8e5eab21f814932134c9d8620c662 - languageName: node - linkType: hard - -"use-callback-ref@npm:^1.3.3": - version: 1.3.3 - resolution: "use-callback-ref@npm:1.3.3" - dependencies: - tslib: "npm:^2.0.0" - peerDependencies: - "@types/react": "*" - react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc - peerDependenciesMeta: - "@types/react": - optional: true - checksum: 10c0/f887488c6e6075cdad4962979da1714b217bcb1ee009a9e57ce9a844bcfc4c3a99e93983dfc2e5af9e0913824d24e730090ff255e902c516dcb58d2d3837e01c - languageName: node - linkType: hard - -"use-sidecar@npm:^1.1.2, use-sidecar@npm:^1.1.3": - version: 1.1.3 - resolution: "use-sidecar@npm:1.1.3" - dependencies: - detect-node-es: "npm:^1.1.0" - tslib: "npm:^2.0.0" - peerDependencies: - "@types/react": "*" - react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc - peerDependenciesMeta: - "@types/react": - optional: true - checksum: 10c0/161599bf921cfaa41c85d2b01c871975ee99260f3e874c2d41c05890d41170297bdcf314bc5185e7a700de2034ac5b888e3efc8e9f35724f4918f53538d717c9 - languageName: node - linkType: hard - -"use-sync-external-store@npm:^1.5.0, use-sync-external-store@npm:^1.6.0": - version: 1.6.0 - resolution: "use-sync-external-store@npm:1.6.0" - peerDependencies: - react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 - checksum: 10c0/35e1179f872a53227bdf8a827f7911da4c37c0f4091c29b76b1e32473d1670ebe7bcd880b808b7549ba9a5605c233350f800ffab963ee4a4ee346ee983b6019b - languageName: node - linkType: hard - -"usehooks-ts@npm:3.1.1": - version: 3.1.1 - resolution: "usehooks-ts@npm:3.1.1" - dependencies: - lodash.debounce: "npm:^4.0.8" - peerDependencies: - react: ^16.8.0 || ^17 || ^18 || ^19 || ^19.0.0-rc - checksum: 10c0/8bbebf52b063f2e705eb27364f08ec2eff987b9e8d28d82a28248652dd89ef53cb514e1f2ee1cbc6ac6e083a8dce86310301c3e92a99902b98c32a26381202d7 - languageName: node - linkType: hard - -"util-deprecate@npm:^1.0.1, util-deprecate@npm:^1.0.2, util-deprecate@npm:~1.0.1": - version: 1.0.2 - resolution: "util-deprecate@npm:1.0.2" - checksum: 10c0/41a5bdd214df2f6c3ecf8622745e4a366c4adced864bc3c833739791aeeeb1838119af7daed4ba36428114b5c67dcda034a79c882e97e43c03e66a4dd7389942 - languageName: node - linkType: hard - -"util@npm:^0.12.4, util@npm:^0.12.5": - version: 0.12.5 - resolution: "util@npm:0.12.5" - dependencies: - inherits: "npm:^2.0.3" - is-arguments: "npm:^1.0.4" - is-generator-function: "npm:^1.0.7" - is-typed-array: "npm:^1.1.3" - which-typed-array: "npm:^1.1.2" - checksum: 10c0/c27054de2cea2229a66c09522d0fa1415fb12d861d08523a8846bf2e4cbf0079d4c3f725f09dcb87493549bcbf05f5798dce1688b53c6c17201a45759e7253f3 - languageName: node - linkType: hard - -"uuid@npm:13, uuid@npm:^13.0.0": - version: 13.0.0 - resolution: "uuid@npm:13.0.0" - bin: - uuid: dist-node/bin/uuid - checksum: 10c0/950e4c18d57fef6c69675344f5700a08af21e26b9eff2bf2180427564297368c538ea11ac9fb2e6528b17fc3966a9fd2c5049361b0b63c7d654f3c550c9b3d67 - languageName: node - linkType: hard - -"validate-npm-package-license@npm:^3.0.1": - version: 3.0.4 - resolution: "validate-npm-package-license@npm:3.0.4" - dependencies: - spdx-correct: "npm:^3.0.0" - spdx-expression-parse: "npm:^3.0.0" - checksum: 10c0/7b91e455a8de9a0beaa9fe961e536b677da7f48c9a493edf4d4d4a87fd80a7a10267d438723364e432c2fcd00b5650b5378275cded362383ef570276e6312f4f - languageName: node - linkType: hard - -"value-or-function@npm:^4.0.0": - version: 4.0.0 - resolution: "value-or-function@npm:4.0.0" - checksum: 10c0/1ac6f3ce4c2d811f9fb99a50a69df1d3960376cd1d8fa89106f746a251cb7a0bccb62199972c00beecb5f4911b7a65465b6624d198108ca90dc95cfbf1643230 - languageName: node - linkType: hard - -"vaul@npm:^1.0.0": - version: 1.1.2 - resolution: "vaul@npm:1.1.2" - dependencies: - "@radix-ui/react-dialog": "npm:^1.1.1" - peerDependencies: - react: ^16.8 || ^17.0 || ^18.0 || ^19.0.0 || ^19.0.0-rc - react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0.0 || ^19.0.0-rc - checksum: 10c0/a6da539eb5576c0004a6b17e3673ea1db2c34e80355860131183abf53279ce025bbd016d542c345d1cc8464ad12f9dc9860949c751055d8a84961e8472a53707 - languageName: node - linkType: hard - -"vinyl-contents@npm:^2.0.0": - version: 2.0.0 - resolution: "vinyl-contents@npm:2.0.0" - dependencies: - bl: "npm:^5.0.0" - vinyl: "npm:^3.0.0" - checksum: 10c0/b50ddf02c48fa5f89fc14bce470a375cfe74ffd6f8081836ee22f3b731e37bf1ef56761eea73377037325c79784ddc5b90000f8bddd418b87b75ea3f6320f16b - languageName: node - linkType: hard - -"vinyl-fs@npm:^4.0.0": - version: 4.0.0 - resolution: "vinyl-fs@npm:4.0.0" - dependencies: - fs-mkdirp-stream: "npm:^2.0.1" - glob-stream: "npm:^8.0.0" - graceful-fs: "npm:^4.2.11" - iconv-lite: "npm:^0.6.3" - is-valid-glob: "npm:^1.0.0" - lead: "npm:^4.0.0" - normalize-path: "npm:3.0.0" - resolve-options: "npm:^2.0.0" - stream-composer: "npm:^1.0.2" - streamx: "npm:^2.14.0" - to-through: "npm:^3.0.0" - value-or-function: "npm:^4.0.0" - vinyl: "npm:^3.0.0" - vinyl-sourcemap: "npm:^2.0.0" - checksum: 10c0/c68a86ec8b48e60c5b31a881d2f39cebfe104518a1895f38ba658cfd890673a6cfa5d55de58eb15264fd2333e5b26099989e1de4e14aa6a8ad0f04529ff46a34 - languageName: node - linkType: hard - -"vinyl-sourcemap@npm:^2.0.0": - version: 2.0.0 - resolution: "vinyl-sourcemap@npm:2.0.0" - dependencies: - convert-source-map: "npm:^2.0.0" - graceful-fs: "npm:^4.2.10" - now-and-later: "npm:^3.0.0" - streamx: "npm:^2.12.5" - vinyl: "npm:^3.0.0" - vinyl-contents: "npm:^2.0.0" - checksum: 10c0/073f3f7dac1fcbf75a5ef22dac1ad18a6a299a761ff1b897455177403141935a1a909fec4540434e5b6344f9d25b962efe49fce5e82fd9e3219d4865e7688e9a - languageName: node - linkType: hard - -"vinyl@npm:^3.0.0": - version: 3.0.0 - resolution: "vinyl@npm:3.0.0" - dependencies: - clone: "npm:^2.1.2" - clone-stats: "npm:^1.0.0" - remove-trailing-separator: "npm:^1.1.0" - replace-ext: "npm:^2.0.0" - teex: "npm:^1.0.1" - checksum: 10c0/566ab41a84c1a167023a07cb94110d40a07835a5239297e3266a11b0e9c522969a1e623ec2a4f9b05ac7fef596cf47685b410359e5b2ca00bd77400657808816 - languageName: node - linkType: hard - -"vite-plugin-generate-file@npm:^0.3.0": - version: 0.3.1 - resolution: "vite-plugin-generate-file@npm:0.3.1" - dependencies: - ejs: "npm:^3.1.9" - js-yaml: "npm:^4.1.0" - mime-types: "npm:^2.1.35" - picocolors: "npm:^1.0.0" - checksum: 10c0/c2ca100c64c0620766bfcf5fe281202e7110ba5cc0651f4ac19de7b6bcd9aa2bda1c6590190101859ba1b0a54d3c6a05d4780a5c545c0b81fdcc2975adcebfc9 - languageName: node - linkType: hard - -"vite-plugin-html@npm:^3.2.2": - version: 3.2.2 - resolution: "vite-plugin-html@npm:3.2.2" - dependencies: - "@rollup/pluginutils": "npm:^4.2.0" - colorette: "npm:^2.0.16" - connect-history-api-fallback: "npm:^1.6.0" - consola: "npm:^2.15.3" - dotenv: "npm:^16.0.0" - dotenv-expand: "npm:^8.0.2" - ejs: "npm:^3.1.6" - fast-glob: "npm:^3.2.11" - fs-extra: "npm:^10.0.1" - html-minifier-terser: "npm:^6.1.0" - node-html-parser: "npm:^5.3.3" - pathe: "npm:^0.2.0" - peerDependencies: - vite: ">=2.0.0" - checksum: 10c0/34628f44f07a9656875c66ba0c4dbe6be39646c50f961cb771179b930dd5727281836ee4293d7e89fe36043703a0ff40df06b15b90260d48a642420e008eb76a - languageName: node - linkType: hard - -"vite-plugin-node-stdlib-browser@npm:^0.2.1": - version: 0.2.1 - resolution: "vite-plugin-node-stdlib-browser@npm:0.2.1" - dependencies: - "@rollup/plugin-inject": "npm:^5.0.3" - peerDependencies: - node-stdlib-browser: ^1.2.0 - vite: ^2.0.0 || ^3.0.0 || ^4.0.0 - checksum: 10c0/4686bde59d0396d8684433e1a14ddce868dc422f80e306a0c1cb5e86564d9f7c38a67865ca339e4ff57784ec4bada149034038cad6911a2dfcac8debfc9bd20a - languageName: node - linkType: hard - -"vite-plugin-svgr@npm:^4.0.0": - version: 4.5.0 - resolution: "vite-plugin-svgr@npm:4.5.0" - dependencies: - "@rollup/pluginutils": "npm:^5.2.0" - "@svgr/core": "npm:^8.1.0" - "@svgr/plugin-jsx": "npm:^8.1.0" - peerDependencies: - vite: ">=2.6.0" - checksum: 10c0/3e1959fec626bb4f5a8ec13ff15bc40ffbc1c0ff38149bebe3f37dc2d67ed1f276f129ff7983e06946cf712e19996affd9d6868aa7d20d8921d1fe4449109b55 - languageName: node - linkType: hard - -"vite@npm:^6.0.0 || ^7.0.0 || ^8.0.0": - version: 8.0.3 - resolution: "vite@npm:8.0.3" - dependencies: - fsevents: "npm:~2.3.3" - lightningcss: "npm:^1.32.0" - picomatch: "npm:^4.0.4" - postcss: "npm:^8.5.8" - rolldown: "npm:1.0.0-rc.12" - tinyglobby: "npm:^0.2.15" - peerDependencies: - "@types/node": ^20.19.0 || >=22.12.0 - "@vitejs/devtools": ^0.1.0 - esbuild: ^0.27.0 - jiti: ">=1.21.0" - less: ^4.0.0 - sass: ^1.70.0 - sass-embedded: ^1.70.0 - stylus: ">=0.54.8" - sugarss: ^5.0.0 - terser: ^5.16.0 - tsx: ^4.8.1 - yaml: ^2.4.2 - dependenciesMeta: - fsevents: - optional: true - peerDependenciesMeta: - "@types/node": - optional: true - "@vitejs/devtools": - optional: true - esbuild: - optional: true - jiti: - optional: true - less: - optional: true - sass: - optional: true - sass-embedded: - optional: true - stylus: - optional: true - sugarss: - optional: true - terser: - optional: true - tsx: - optional: true - yaml: - optional: true - bin: - vite: bin/vite.js - checksum: 10c0/bed9520358080393a02fe22565b3309b4b3b8f916afe4c97577528f3efb05c1bf4b29f7b552179bc5b3938629e50fbd316231727457411dbc96648fa5c9d14bf - languageName: node - linkType: hard - -"vite@npm:^8.0.0": - version: 8.0.5 - resolution: "vite@npm:8.0.5" - dependencies: - fsevents: "npm:~2.3.3" - lightningcss: "npm:^1.32.0" - picomatch: "npm:^4.0.4" - postcss: "npm:^8.5.8" - rolldown: "npm:1.0.0-rc.12" - tinyglobby: "npm:^0.2.15" - peerDependencies: - "@types/node": ^20.19.0 || >=22.12.0 - "@vitejs/devtools": ^0.1.0 - esbuild: ^0.27.0 || ^0.28.0 - jiti: ">=1.21.0" - less: ^4.0.0 - sass: ^1.70.0 - sass-embedded: ^1.70.0 - stylus: ">=0.54.8" - sugarss: ^5.0.0 - terser: ^5.16.0 - tsx: ^4.8.1 - yaml: ^2.4.2 - dependenciesMeta: - fsevents: - optional: true - peerDependenciesMeta: - "@types/node": - optional: true - "@vitejs/devtools": - optional: true - esbuild: - optional: true - jiti: - optional: true - less: - optional: true - sass: - optional: true - sass-embedded: - optional: true - stylus: - optional: true - sugarss: - optional: true - terser: - optional: true - tsx: - optional: true - yaml: - optional: true - bin: - vite: bin/vite.js - checksum: 10c0/bfc22896b2661753c01c398a058f1859bdbd3ebe55f3d8505ab629b39e5f68790c0a6f55f8644b6692b0b9b8e210f698082ef9f4fd0d76509f4a46762fbfbba2 - languageName: node - linkType: hard - -"vitest-axe@npm:^1.0.0-pre.3": - version: 1.0.0-pre.5 - resolution: "vitest-axe@npm:1.0.0-pre.5" - dependencies: - "@vitest/pretty-format": "npm:^3.0.3" - axe-core: "npm:^4.10.2" - chalk: "npm:^5.4.1" - lodash-es: "npm:^4.17.21" - peerDependencies: - vitest: ">=1" - checksum: 10c0/e76bd339ac7f7a492f3429b1b056ddbf3595d3880fa89f93ce7c2cd0de01c98e618009058fa3296d08d3d315ceb35c99d5cb63766e9c5a3bd3e05c8c3f34a4e1 - languageName: node - linkType: hard - -"vitest@npm:^4.0.18": - version: 4.1.2 - resolution: "vitest@npm:4.1.2" - dependencies: - "@vitest/expect": "npm:4.1.2" - "@vitest/mocker": "npm:4.1.2" - "@vitest/pretty-format": "npm:4.1.2" - "@vitest/runner": "npm:4.1.2" - "@vitest/snapshot": "npm:4.1.2" - "@vitest/spy": "npm:4.1.2" - "@vitest/utils": "npm:4.1.2" - es-module-lexer: "npm:^2.0.0" - expect-type: "npm:^1.3.0" - magic-string: "npm:^0.30.21" - obug: "npm:^2.1.1" - pathe: "npm:^2.0.3" - picomatch: "npm:^4.0.3" - std-env: "npm:^4.0.0-rc.1" - tinybench: "npm:^2.9.0" - tinyexec: "npm:^1.0.2" - tinyglobby: "npm:^0.2.15" - tinyrainbow: "npm:^3.1.0" - vite: "npm:^6.0.0 || ^7.0.0 || ^8.0.0" - why-is-node-running: "npm:^2.3.0" - peerDependencies: - "@edge-runtime/vm": "*" - "@opentelemetry/api": ^1.9.0 - "@types/node": ^20.0.0 || ^22.0.0 || >=24.0.0 - "@vitest/browser-playwright": 4.1.2 - "@vitest/browser-preview": 4.1.2 - "@vitest/browser-webdriverio": 4.1.2 - "@vitest/ui": 4.1.2 - happy-dom: "*" - jsdom: "*" - vite: ^6.0.0 || ^7.0.0 || ^8.0.0 - peerDependenciesMeta: - "@edge-runtime/vm": - optional: true - "@opentelemetry/api": - optional: true - "@types/node": - optional: true - "@vitest/browser-playwright": - optional: true - "@vitest/browser-preview": - optional: true - "@vitest/browser-webdriverio": - optional: true - "@vitest/ui": - optional: true - happy-dom: - optional: true - jsdom: - optional: true - vite: - optional: false - bin: - vitest: vitest.mjs - checksum: 10c0/061fdd0319ba533c926b139b9377a7dbf91e63d815d86fe318a207bd19842b74ca6f6402ea61b26ed9d2924306bdb4d0b13f69c29e2a2a89b3b67602bcccb54c - languageName: node - linkType: hard - -"vm-browserify@npm:^1.0.1": - version: 1.1.2 - resolution: "vm-browserify@npm:1.1.2" - checksum: 10c0/0cc1af6e0d880deb58bc974921320c187f9e0a94f25570fca6b1bd64e798ce454ab87dfd797551b1b0cc1849307421aae0193cedf5f06bdb5680476780ee344b - languageName: node - linkType: hard - -"void-elements@npm:3.1.0": - version: 3.1.0 - resolution: "void-elements@npm:3.1.0" - checksum: 10c0/0b8686f9f9aa44012e9bd5eabf287ae0cde409b9a2854c5a2335cb83920c957668ac5876e3f0d158dd424744ac411a7270e64128556b451ed3bec875ef18534d - languageName: node - linkType: hard - -"w3c-xmlserializer@npm:^5.0.0": - version: 5.0.0 - resolution: "w3c-xmlserializer@npm:5.0.0" - dependencies: - xml-name-validator: "npm:^5.0.0" - checksum: 10c0/8712774c1aeb62dec22928bf1cdfd11426c2c9383a1a63f2bcae18db87ca574165a0fbe96b312b73652149167ac6c7f4cf5409f2eb101d9c805efe0e4bae798b - languageName: node - linkType: hard - -"walk-sync@npm:^2.2.0": - version: 2.2.0 - resolution: "walk-sync@npm:2.2.0" - dependencies: - "@types/minimatch": "npm:^3.0.3" - ensure-posix-path: "npm:^1.1.0" - matcher-collection: "npm:^2.0.0" - minimatch: "npm:^3.0.4" - checksum: 10c0/45fe284ffa28440f0d3d0a136b3c3fe2a0f55bf207db22c481eea9e7ab7cef6d820491485d76e9f1af9dab7489c6d7a0efbd1ebf45b43dbf871f046f0b4760bd - languageName: node - linkType: hard - -"walk-up-path@npm:^4.0.0": - version: 4.0.0 - resolution: "walk-up-path@npm:4.0.0" - checksum: 10c0/fabe344f91387d1d41df230af962ef18bf703dd4178006d55cd6412caacd187b54440002d4d53a982d4f7f0455567dcffb6d3884533c8b2268928eca3ebd8a19 - languageName: node - linkType: hard - -"web-vitals@npm:^4.0.1": - version: 4.2.3 - resolution: "web-vitals@npm:4.2.3" - checksum: 10c0/905bdb9434f365435c3c00e5f473ce088980fcd61068906e20a575bae9590e1cc28dab0f90958c66717591e2f4c9b809ec8025cef5796fa4bc1304d50332f125 - languageName: node - linkType: hard - -"webidl-conversions@npm:^3.0.0": - version: 3.0.1 - resolution: "webidl-conversions@npm:3.0.1" - checksum: 10c0/5612d5f3e54760a797052eb4927f0ddc01383550f542ccd33d5238cfd65aeed392a45ad38364970d0a0f4fea32e1f4d231b3d8dac4a3bdd385e5cf802ae097db - languageName: node - linkType: hard - -"webidl-conversions@npm:^7.0.0": - version: 7.0.0 - resolution: "webidl-conversions@npm:7.0.0" - checksum: 10c0/228d8cb6d270c23b0720cb2d95c579202db3aaf8f633b4e9dd94ec2000a04e7e6e43b76a94509cdb30479bd00ae253ab2371a2da9f81446cc313f89a4213a2c4 - languageName: node - linkType: hard - -"webpack-sources@npm:^3.2.3": - version: 3.2.3 - resolution: "webpack-sources@npm:3.2.3" - checksum: 10c0/2ef63d77c4fad39de4a6db17323d75eb92897b32674e97d76f0a1e87c003882fc038571266ad0ef581ac734cbe20952912aaa26155f1905e96ce251adbb1eb4e - languageName: node - linkType: hard - -"webpack-virtual-modules@npm:^0.5.0": - version: 0.5.0 - resolution: "webpack-virtual-modules@npm:0.5.0" - checksum: 10c0/0742e069cd49d91ccd0b59431b3666903d321582c1b1062fa6bdae005c3538af55ff8787ea5eafbf72662f3496d3a879e2c705d55ca0af8283548a925be18484 - languageName: node - linkType: hard - -"webpack-virtual-modules@npm:^0.6.2": - version: 0.6.2 - resolution: "webpack-virtual-modules@npm:0.6.2" - checksum: 10c0/5ffbddf0e84bf1562ff86cf6fcf039c74edf09d78358a6904a09bbd4484e8bb6812dc385fe14330b715031892dcd8423f7a88278b57c9f5002c84c2860179add - languageName: node - linkType: hard - -"webrtc-adapter@npm:^9.0.1": - version: 9.0.1 - resolution: "webrtc-adapter@npm:9.0.1" - dependencies: - sdp: "npm:^3.2.0" - checksum: 10c0/09286adf351b3aff6eadf7942de7f153072a946fd815450e23505e39181c332d0552f4d27a99c5d7258efa3bd70a12949fe043fd8dc6acc03507b4448d7a597e - languageName: node - linkType: hard - -"whatwg-encoding@npm:^3.1.1": - version: 3.1.1 - resolution: "whatwg-encoding@npm:3.1.1" - dependencies: - iconv-lite: "npm:0.6.3" - checksum: 10c0/273b5f441c2f7fda3368a496c3009edbaa5e43b71b09728f90425e7f487e5cef9eb2b846a31bd760dd8077739c26faf6b5ca43a5f24033172b003b72cf61a93e - languageName: node - linkType: hard - -"whatwg-mimetype@npm:^4.0.0": - version: 4.0.0 - resolution: "whatwg-mimetype@npm:4.0.0" - checksum: 10c0/a773cdc8126b514d790bdae7052e8bf242970cebd84af62fb2f35a33411e78e981f6c0ab9ed1fe6ec5071b09d5340ac9178e05b52d35a9c4bcf558ba1b1551df - languageName: node - linkType: hard - -"whatwg-url@npm:^14.0.0": - version: 14.0.0 - resolution: "whatwg-url@npm:14.0.0" - dependencies: - tr46: "npm:^5.0.0" - webidl-conversions: "npm:^7.0.0" - checksum: 10c0/ac32e9ba9d08744605519bbe9e1371174d36229689ecc099157b6ba102d4251a95e81d81f3d80271eb8da182eccfa65653f07f0ab43ea66a6934e643fd091ba9 - languageName: node - linkType: hard - -"whatwg-url@npm:^14.1.1": - version: 14.2.0 - resolution: "whatwg-url@npm:14.2.0" - dependencies: - tr46: "npm:^5.1.0" - webidl-conversions: "npm:^7.0.0" - checksum: 10c0/f746fc2f4c906607d09537de1227b13f9494c171141e5427ed7d2c0dd0b6a48b43d8e71abaae57d368d0c06b673fd8ec63550b32ad5ed64990c7b0266c2b4272 - languageName: node - linkType: hard - -"whatwg-url@npm:^5.0.0": - version: 5.0.0 - resolution: "whatwg-url@npm:5.0.0" - dependencies: - tr46: "npm:~0.0.3" - webidl-conversions: "npm:^3.0.0" - checksum: 10c0/1588bed84d10b72d5eec1d0faa0722ba1962f1821e7539c535558fb5398d223b0c50d8acab950b8c488b4ba69043fd833cc2697056b167d8ad46fac3995a55d5 - languageName: node - linkType: hard - -"which-boxed-primitive@npm:^1.1.0, which-boxed-primitive@npm:^1.1.1": - version: 1.1.1 - resolution: "which-boxed-primitive@npm:1.1.1" - dependencies: - is-bigint: "npm:^1.1.0" - is-boolean-object: "npm:^1.2.1" - is-number-object: "npm:^1.1.1" - is-string: "npm:^1.1.1" - is-symbol: "npm:^1.1.1" - checksum: 10c0/aceea8ede3b08dede7dce168f3883323f7c62272b49801716e8332ff750e7ae59a511ae088840bc6874f16c1b7fd296c05c949b0e5b357bfe3c431b98c417abe - languageName: node - linkType: hard - -"which-builtin-type@npm:^1.2.1": - version: 1.2.1 - resolution: "which-builtin-type@npm:1.2.1" - dependencies: - call-bound: "npm:^1.0.2" - function.prototype.name: "npm:^1.1.6" - has-tostringtag: "npm:^1.0.2" - is-async-function: "npm:^2.0.0" - is-date-object: "npm:^1.1.0" - is-finalizationregistry: "npm:^1.1.0" - is-generator-function: "npm:^1.0.10" - is-regex: "npm:^1.2.1" - is-weakref: "npm:^1.0.2" - isarray: "npm:^2.0.5" - which-boxed-primitive: "npm:^1.1.0" - which-collection: "npm:^1.0.2" - which-typed-array: "npm:^1.1.16" - checksum: 10c0/8dcf323c45e5c27887800df42fbe0431d0b66b1163849bb7d46b5a730ad6a96ee8bfe827d078303f825537844ebf20c02459de41239a0a9805e2fcb3cae0d471 - languageName: node - linkType: hard - -"which-collection@npm:^1.0.2": - version: 1.0.2 - resolution: "which-collection@npm:1.0.2" - dependencies: - is-map: "npm:^2.0.3" - is-set: "npm:^2.0.3" - is-weakmap: "npm:^2.0.2" - is-weakset: "npm:^2.0.3" - checksum: 10c0/3345fde20964525a04cdf7c4a96821f85f0cc198f1b2ecb4576e08096746d129eb133571998fe121c77782ac8f21cbd67745a3d35ce100d26d4e684c142ea1f2 - languageName: node - linkType: hard - -"which-module@npm:^2.0.0": - version: 2.0.1 - resolution: "which-module@npm:2.0.1" - checksum: 10c0/087038e7992649eaffa6c7a4f3158d5b53b14cf5b6c1f0e043dccfacb1ba179d12f17545d5b85ebd94a42ce280a6fe65d0cbcab70f4fc6daad1dfae85e0e6a3e - languageName: node - linkType: hard - -"which-typed-array@npm:^1.1.16, which-typed-array@npm:^1.1.18": - version: 1.1.18 - resolution: "which-typed-array@npm:1.1.18" - dependencies: - available-typed-arrays: "npm:^1.0.7" - call-bind: "npm:^1.0.8" - call-bound: "npm:^1.0.3" - for-each: "npm:^0.3.3" - gopd: "npm:^1.2.0" - has-tostringtag: "npm:^1.0.2" - checksum: 10c0/0412f4a91880ca1a2a63056187c2e3de6b129b2b5b6c17bc3729f0f7041047ae48fb7424813e51506addb2c97320003ee18b8c57469d2cde37983ef62126143c - languageName: node - linkType: hard - -"which-typed-array@npm:^1.1.19, which-typed-array@npm:^1.1.2": - version: 1.1.19 - resolution: "which-typed-array@npm:1.1.19" - dependencies: - available-typed-arrays: "npm:^1.0.7" - call-bind: "npm:^1.0.8" - call-bound: "npm:^1.0.4" - for-each: "npm:^0.3.5" - get-proto: "npm:^1.0.1" - gopd: "npm:^1.2.0" - has-tostringtag: "npm:^1.0.2" - checksum: 10c0/702b5dc878addafe6c6300c3d0af5983b175c75fcb4f2a72dfc3dd38d93cf9e89581e4b29c854b16ea37e50a7d7fca5ae42ece5c273d8060dcd603b2404bbb3f - languageName: node - linkType: hard - -"which@npm:^2.0.1, which@npm:^2.0.2": - version: 2.0.2 - resolution: "which@npm:2.0.2" - dependencies: - isexe: "npm:^2.0.0" - bin: - node-which: ./bin/node-which - checksum: 10c0/66522872a768b60c2a65a57e8ad184e5372f5b6a9ca6d5f033d4b0dc98aff63995655a7503b9c0a2598936f532120e81dd8cc155e2e92ed662a2b9377cc4374f - languageName: node - linkType: hard - -"which@npm:^5.0.0": - version: 5.0.0 - resolution: "which@npm:5.0.0" - dependencies: - isexe: "npm:^3.1.1" - bin: - node-which: bin/which.js - checksum: 10c0/e556e4cd8b7dbf5df52408c9a9dd5ac6518c8c5267c8953f5b0564073c66ed5bf9503b14d876d0e9c7844d4db9725fb0dcf45d6e911e17e26ab363dc3965ae7b - languageName: node - linkType: hard - -"why-is-node-running@npm:^2.3.0": - version: 2.3.0 - resolution: "why-is-node-running@npm:2.3.0" - dependencies: - siginfo: "npm:^2.0.0" - stackback: "npm:0.0.2" - bin: - why-is-node-running: cli.js - checksum: 10c0/1cde0b01b827d2cf4cb11db962f3958b9175d5d9e7ac7361d1a7b0e2dc6069a263e69118bd974c4f6d0a890ef4eedfe34cf3d5167ec14203dbc9a18620537054 - languageName: node - linkType: hard - -"word-wrap@npm:^1.2.5": - version: 1.2.5 - resolution: "word-wrap@npm:1.2.5" - checksum: 10c0/e0e4a1ca27599c92a6ca4c32260e8a92e8a44f4ef6ef93f803f8ed823f486e0889fc0b93be4db59c8d51b3064951d25e43d434e95dc8c960cc3a63d65d00ba20 - languageName: node - linkType: hard - -"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0, wrap-ansi@npm:^7.0.0": - version: 7.0.0 - resolution: "wrap-ansi@npm:7.0.0" - dependencies: - ansi-styles: "npm:^4.0.0" - string-width: "npm:^4.1.0" - strip-ansi: "npm:^6.0.0" - checksum: 10c0/d15fc12c11e4cbc4044a552129ebc75ee3f57aa9c1958373a4db0292d72282f54373b536103987a4a7594db1ef6a4f10acf92978f79b98c49306a4b58c77d4da - languageName: node - linkType: hard - -"wrap-ansi@npm:^6.2.0": - version: 6.2.0 - resolution: "wrap-ansi@npm:6.2.0" - dependencies: - ansi-styles: "npm:^4.0.0" - string-width: "npm:^4.1.0" - strip-ansi: "npm:^6.0.0" - checksum: 10c0/baad244e6e33335ea24e86e51868fe6823626e3a3c88d9a6674642afff1d34d9a154c917e74af8d845fd25d170c4ea9cf69a47133c3f3656e1252b3d462d9f6c - languageName: node - linkType: hard - -"wrap-ansi@npm:^8.1.0": - version: 8.1.0 - resolution: "wrap-ansi@npm:8.1.0" - dependencies: - ansi-styles: "npm:^6.1.0" - string-width: "npm:^5.0.1" - strip-ansi: "npm:^7.0.1" - checksum: 10c0/138ff58a41d2f877eae87e3282c0630fc2789012fc1af4d6bd626eeb9a2f9a65ca92005e6e69a75c7b85a68479fe7443c7dbe1eb8fbaa681a4491364b7c55c60 - languageName: node - linkType: hard - -"wrappy@npm:1": - version: 1.0.2 - resolution: "wrappy@npm:1.0.2" - checksum: 10c0/56fece1a4018c6a6c8e28fbc88c87e0fbf4ea8fd64fc6c63b18f4acc4bd13e0ad2515189786dd2c30d3eec9663d70f4ecf699330002f8ccb547e4a18231fc9f0 - languageName: node - linkType: hard - -"ws@npm:^8.18.0": - version: 8.18.0 - resolution: "ws@npm:8.18.0" - peerDependencies: - bufferutil: ^4.0.1 - utf-8-validate: ">=5.0.2" - peerDependenciesMeta: - bufferutil: - optional: true - utf-8-validate: - optional: true - checksum: 10c0/25eb33aff17edcb90721ed6b0eb250976328533ad3cd1a28a274bd263682e7296a6591ff1436d6cbc50fa67463158b062f9d1122013b361cec99a05f84680e06 - languageName: node - linkType: hard - -"wsl-utils@npm:^0.1.0": - version: 0.1.0 - resolution: "wsl-utils@npm:0.1.0" - dependencies: - is-wsl: "npm:^3.1.0" - checksum: 10c0/44318f3585eb97be994fc21a20ddab2649feaf1fbe893f1f866d936eea3d5f8c743bec6dc02e49fbdd3c0e69e9b36f449d90a0b165a4f47dd089747af4cf2377 - languageName: node - linkType: hard - -"xml-name-validator@npm:^5.0.0": - version: 5.0.0 - resolution: "xml-name-validator@npm:5.0.0" - checksum: 10c0/3fcf44e7b73fb18be917fdd4ccffff3639373c7cb83f8fc35df6001fecba7942f1dbead29d91ebb8315e2f2ff786b508f0c9dc0215b6353f9983c6b7d62cb1f5 - languageName: node - linkType: hard - -"xmlchars@npm:^2.2.0": - version: 2.2.0 - resolution: "xmlchars@npm:2.2.0" - checksum: 10c0/b64b535861a6f310c5d9bfa10834cf49127c71922c297da9d4d1b45eeaae40bf9b4363275876088fbe2667e5db028d2cd4f8ee72eed9bede840a67d57dab7593 - languageName: node - linkType: hard - -"xtend@npm:^4.0.2, xtend@npm:~4.0.1": - version: 4.0.2 - resolution: "xtend@npm:4.0.2" - checksum: 10c0/366ae4783eec6100f8a02dff02ac907bf29f9a00b82ac0264b4d8b832ead18306797e283cf19de776538babfdcb2101375ec5646b59f08c52128ac4ab812ed0e - languageName: node - linkType: hard - -"y18n@npm:^4.0.0": - version: 4.0.3 - resolution: "y18n@npm:4.0.3" - checksum: 10c0/308a2efd7cc296ab2c0f3b9284fd4827be01cfeb647b3ba18230e3a416eb1bc887ac050de9f8c4fd9e7856b2e8246e05d190b53c96c5ad8d8cb56dffb6f81024 - languageName: node - linkType: hard - -"y18n@npm:^5.0.5": - version: 5.0.8 - resolution: "y18n@npm:5.0.8" - checksum: 10c0/4df2842c36e468590c3691c894bc9cdbac41f520566e76e24f59401ba7d8b4811eb1e34524d57e54bc6d864bcb66baab7ffd9ca42bf1eda596618f9162b91249 - languageName: node - linkType: hard - -"yallist@npm:^3.0.2": - version: 3.1.1 - resolution: "yallist@npm:3.1.1" - checksum: 10c0/c66a5c46bc89af1625476f7f0f2ec3653c1a1791d2f9407cfb4c2ba812a1e1c9941416d71ba9719876530e3340a99925f697142989371b72d93b9ee628afd8c1 - languageName: node - linkType: hard - -"yallist@npm:^4.0.0": - version: 4.0.0 - resolution: "yallist@npm:4.0.0" - checksum: 10c0/2286b5e8dbfe22204ab66e2ef5cc9bbb1e55dfc873bbe0d568aa943eb255d131890dfd5bf243637273d31119b870f49c18fcde2c6ffbb7a7a092b870dc90625a - languageName: node - linkType: hard - -"yallist@npm:^5.0.0": - version: 5.0.0 - resolution: "yallist@npm:5.0.0" - checksum: 10c0/a499c81ce6d4a1d260d4ea0f6d49ab4da09681e32c3f0472dee16667ed69d01dae63a3b81745a24bd78476ec4fcf856114cb4896ace738e01da34b2c42235416 - languageName: node - linkType: hard - -"yaml@npm:^2.8.2": - version: 2.8.2 - resolution: "yaml@npm:2.8.2" - bin: - yaml: bin.mjs - checksum: 10c0/703e4dc1e34b324aa66876d63618dcacb9ed49f7e7fe9b70f1e703645be8d640f68ab84f12b86df8ac960bac37acf5513e115de7c970940617ce0343c8c9cd96 - languageName: node - linkType: hard - -"yargs-parser@npm:^18.1.2": - version: 18.1.3 - resolution: "yargs-parser@npm:18.1.3" - dependencies: - camelcase: "npm:^5.0.0" - decamelize: "npm:^1.2.0" - checksum: 10c0/25df918833592a83f52e7e4f91ba7d7bfaa2b891ebf7fe901923c2ee797534f23a176913ff6ff7ebbc1cc1725a044cc6a6539fed8bfd4e13b5b16376875f9499 - languageName: node - linkType: hard - -"yargs-parser@npm:^21.1.1": - version: 21.1.1 - resolution: "yargs-parser@npm:21.1.1" - checksum: 10c0/f84b5e48169479d2f402239c59f084cfd1c3acc197a05c59b98bab067452e6b3ea46d4dd8ba2985ba7b3d32a343d77df0debd6b343e5dae3da2aab2cdf5886b2 - languageName: node - linkType: hard - -"yargs@npm:^15.3.1": - version: 15.4.1 - resolution: "yargs@npm:15.4.1" - dependencies: - cliui: "npm:^6.0.0" - decamelize: "npm:^1.2.0" - find-up: "npm:^4.1.0" - get-caller-file: "npm:^2.0.1" - require-directory: "npm:^2.1.1" - require-main-filename: "npm:^2.0.0" - set-blocking: "npm:^2.0.0" - string-width: "npm:^4.2.0" - which-module: "npm:^2.0.0" - y18n: "npm:^4.0.0" - yargs-parser: "npm:^18.1.2" - checksum: 10c0/f1ca680c974333a5822732825cca7e95306c5a1e7750eb7b973ce6dc4f97a6b0a8837203c8b194f461969bfe1fb1176d1d423036635285f6010b392fa498ab2d - languageName: node - linkType: hard - -"yargs@npm:^17.0.0": - version: 17.7.2 - resolution: "yargs@npm:17.7.2" - dependencies: - cliui: "npm:^8.0.1" - escalade: "npm:^3.1.1" - get-caller-file: "npm:^2.0.5" - require-directory: "npm:^2.1.1" - string-width: "npm:^4.2.3" - y18n: "npm:^5.0.5" - yargs-parser: "npm:^21.1.1" - checksum: 10c0/ccd7e723e61ad5965fffbb791366db689572b80cca80e0f96aad968dfff4156cd7cd1ad18607afe1046d8241e6fb2d6c08bf7fa7bfb5eaec818735d8feac8f05 - languageName: node - linkType: hard - -"yocto-queue@npm:^0.1.0": - version: 0.1.0 - resolution: "yocto-queue@npm:0.1.0" - checksum: 10c0/dceb44c28578b31641e13695d200d34ec4ab3966a5729814d5445b194933c096b7ced71494ce53a0e8820685d1d010df8b2422e5bf2cdea7e469d97ffbea306f - languageName: node - linkType: hard - -"zod@npm:^3.22.4": - version: 3.24.2 - resolution: "zod@npm:3.24.2" - checksum: 10c0/c638c7220150847f13ad90635b3e7d0321b36cce36f3fc6050ed960689594c949c326dfe2c6fa87c14b126ee5d370ccdebd6efb304f41ef5557a4aaca2824565 - languageName: node - linkType: hard - -"zod@npm:^4.1.11": - version: 4.3.4 - resolution: "zod@npm:4.3.4" - checksum: 10c0/a096102c8b31ecdb913bacb08d5a0fe8447bbe4f54cff421a0c5830a5552da76aae9fd8a01f2e9fdeaae35da1a73762551bc9d14cfedb13a44056de1ed2eb76f - languageName: node - linkType: hard From 9c1719a22f5fe33d41246183c540c00261c2f7f7 Mon Sep 17 00:00:00 2001 From: fkwp Date: Fri, 17 Apr 2026 11:08:25 +0200 Subject: [PATCH 513/748] Switching to pnpm caused module resolution errors because some dependencies rely on being hoisted to the root. This flag restores the flat node_modules structure temporarily. --- .npmrc | 1 + 1 file changed, 1 insertion(+) create mode 100644 .npmrc diff --git a/.npmrc b/.npmrc new file mode 100644 index 000000000..bf2e7648b --- /dev/null +++ b/.npmrc @@ -0,0 +1 @@ +shamefully-hoist=true From 8eccb95fd3dff9990954200e14cdb4509f513cab Mon Sep 17 00:00:00 2001 From: Jake Janicke <37964537+JakeTripplJ@users.noreply.github.com> Date: Fri, 17 Apr 2026 04:10:12 -0500 Subject: [PATCH 514/748] Merge pull request #3859 from JakeTripplJ/screenshare-audio-filtering-removal Remove unneeded filtering from screen share audio --- src/state/CallViewModel/localMember/LocalMember.ts | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/state/CallViewModel/localMember/LocalMember.ts b/src/state/CallViewModel/localMember/LocalMember.ts index 188dc5434..f0c54f5f3 100644 --- a/src/state/CallViewModel/localMember/LocalMember.ts +++ b/src/state/CallViewModel/localMember/LocalMember.ts @@ -662,7 +662,15 @@ export const createLocalMembership$ = ({ ) { toggleScreenSharing = (): void => { const screenshareSettings: ScreenShareCaptureOptions = { - audio: true, + // Screen share audio shouldn't have any filtering. + // "echoCancellation" is purposely excluded, as setting it to + // false causes the screen share audio track to include + // an echo of the incoming participant's voice + audio: { + autoGainControl: false, + noiseSuppression: false, + voiceIsolation: false, + }, selfBrowserSurface: "include", surfaceSwitching: "include", systemAudio: "include", From 2b42b2bdc1a25ab627fc53d55c8ba33a6b2db357 Mon Sep 17 00:00:00 2001 From: fkwp Date: Fri, 17 Apr 2026 11:13:41 +0200 Subject: [PATCH 515/748] fix tests after moving to pnpm --- .../__snapshots__/InCallView.test.tsx.snap | 2 +- .../DeveloperSettingsTab.test.tsx.snap | 2 +- .../CallViewModel/localMember/LocalMember.ts | 1 - src/useAudioContext.test.tsx | 21 +++++++- src/utils/test.ts | 8 ++- vitest.config.ts | 5 +- vitest.setup.ts | 51 +++++++++++++++++++ 7 files changed, 82 insertions(+), 8 deletions(-) create mode 100644 vitest.setup.ts diff --git a/src/room/__snapshots__/InCallView.test.tsx.snap b/src/room/__snapshots__/InCallView.test.tsx.snap index 955c061e4..99f194433 100644 --- a/src/room/__snapshots__/InCallView.test.tsx.snap +++ b/src/room/__snapshots__/InCallView.test.tsx.snap @@ -17,7 +17,7 @@ exports[`InCallView > rendering > renders 1`] = ` > renders and matches snapshot 1`] = ` > testAudioContext);` */ -export const testAudioContext = { +export const testAudioContext: Partial & { + gain: ReturnType< + typeof vi.mocked<{ + connect: (node: AudioNode) => AudioNode; + gain: { setValueAtTime: ReturnType; value: number }; + }> + >; + pan: ReturnType< + typeof vi.mocked<{ + connect: (node: AudioNode) => AudioNode; + pan: { setValueAtTime: ReturnType; value: number }; + }> + >; + setSinkId: ReturnType; + decodeAudioData: ReturnType; + createBufferSource: ReturnType; + createGain: ReturnType; + createStereoPanner: ReturnType; + close: ReturnType; +} = { gain: gainNode, pan: panNode, setSinkId: vi.fn().mockResolvedValue(undefined), diff --git a/src/utils/test.ts b/src/utils/test.ts index af372bfb6..695dd0462 100644 --- a/src/utils/test.ts +++ b/src/utils/test.ts @@ -15,6 +15,7 @@ import { vitest, } from "vitest"; import { + EventType, MatrixEvent, type Room as MatrixRoom, type Room, @@ -255,6 +256,7 @@ export function mockRtcMembership( const event = new MatrixEvent({ sender: userId, event_id: `$-ev-${randomUUID()}:example.org`, + type: EventType.GroupCallMemberPrefix, content: data, }); @@ -466,7 +468,9 @@ export class MockRTCSession extends TypedEventEmitter< counters: {}, }; - public leaveRoomSession = vitest.fn().mockResolvedValue(undefined); + public leaveRoomSession: ReturnType = vitest + .fn() + .mockResolvedValue(undefined); public constructor( public readonly room: Room, @@ -496,7 +500,7 @@ export class MockRTCSession extends TypedEventEmitter< return this; } - public updateCallIntent = vitest + public updateCallIntent: ReturnType = vitest .fn() .mockImplementation(async () => Promise.resolve()); diff --git a/vitest.config.ts b/vitest.config.ts index c89957c61..7f449f459 100644 --- a/vitest.config.ts +++ b/vitest.config.ts @@ -13,12 +13,13 @@ export default defineConfig((configEnv) => classNameStrategy: "non-scoped", }, }, - setupFiles: ["src/vitest.setup.ts"], + setupFiles: ["vitest.setup.ts"], include: ["src/**/*.test.ts", "src/**/*.test.tsx"], coverage: { reporter: ["html", "json"], - include: ["src/"], + include: ["src/**/*.{ts,tsx,js,jsx}"], exclude: [ + "src/**/*.md", "src/**/*.{d,test,stories}.{ts,tsx}", "src/utils/test.ts", "src/utils/test-viewmodel.ts", diff --git a/vitest.setup.ts b/vitest.setup.ts new file mode 100644 index 000000000..cff3a2344 --- /dev/null +++ b/vitest.setup.ts @@ -0,0 +1,51 @@ +const storage: Record = {}; +const localStoragePolyfill = { + getItem(key: string) { + return Object.prototype.hasOwnProperty.call(storage, key) + ? storage[key] + : null; + }, + setItem(key: string, value: string) { + storage[key] = String(value); + }, + removeItem(key: string) { + delete storage[key]; + }, + clear() { + for (const key in storage) { + delete storage[key]; + } + }, + key(index: number) { + const keys = Object.keys(storage); + return keys[index] ?? null; + }, + get length() { + return Object.keys(storage).length; + }, +} as unknown as Storage; + +if ( + typeof globalThis.localStorage === "undefined" || + typeof globalThis.localStorage.clear !== "function" +) { + Object.defineProperty(globalThis, "localStorage", { + value: localStoragePolyfill, + writable: true, + configurable: true, + }); +} + +if ( + typeof window !== "undefined" && + (typeof window.localStorage === "undefined" || + typeof window.localStorage.clear !== "function") +) { + Object.defineProperty(window, "localStorage", { + value: localStoragePolyfill, + writable: true, + configurable: true, + }); +} + +import "./src/vitest.setup.ts"; From b58ad639c11af9438707280df641573bb432e329 Mon Sep 17 00:00:00 2001 From: fkwp Date: Fri, 17 Apr 2026 11:14:21 +0200 Subject: [PATCH 516/748] Prevents Prettier from formatting the lockfile to avoid conflicts with pnpm's internal formatting --- .prettierignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.prettierignore b/.prettierignore index f06235c46..31e6cd83b 100644 --- a/.prettierignore +++ b/.prettierignore @@ -1,2 +1,3 @@ +pnpm-lock.yaml node_modules dist From 96b343effcbde69136599a014e6434d004f9f2c8 Mon Sep 17 00:00:00 2001 From: Robin Date: Fri, 17 Apr 2026 12:20:07 +0200 Subject: [PATCH 517/748] Fix forward/back buttons not showing up on desktop for multiple screen shares 6667fc54c0a758531476f697022a0001654e1f17 changed this CSS selector that shows buttons on hover to only target the buttons in the bottom right corner of the spotlight tile, causing the forward/back buttons to stay invisible. --- src/tile/SpotlightTile.module.css | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/tile/SpotlightTile.module.css b/src/tile/SpotlightTile.module.css index af0e0add5..5448a155b 100644 --- a/src/tile/SpotlightTile.module.css +++ b/src/tile/SpotlightTile.module.css @@ -153,10 +153,10 @@ Please see LICENSE in the repository root for full details. } @media (hover) { - .tile > div > button { + .tile button { opacity: 0; } - .tile:hover > div > button { + .tile:hover button { opacity: 1; } } From 7e39889f788d094068676f8f2a5819c6b6b5f8ec Mon Sep 17 00:00:00 2001 From: Robin Date: Fri, 17 Apr 2026 12:21:39 +0200 Subject: [PATCH 518/748] Fix name tags appearing in the wrong place with multiple screen shares They were not properly being contained to where the MediaView is supposed to appear, causing them to all stack up on the first screen share in the spotlight tile. --- src/tile/MediaView.module.css | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/tile/MediaView.module.css b/src/tile/MediaView.module.css index e972443f5..491992532 100644 --- a/src/tile/MediaView.module.css +++ b/src/tile/MediaView.module.css @@ -11,6 +11,9 @@ Please see LICENSE in the repository root for full details. border-radius: var(--media-view-border-radius); /*Add spacing for the hover boarder. Otherwise it might get clipped.*/ margin: var(--hover-space-margin); + display: grid; + grid-template-areas: "content"; + place-items: stretch; } .media video { @@ -37,6 +40,7 @@ Please see LICENSE in the repository root for full details. } .bg { + grid-area: content; background-color: var(--video-tile-background); inline-size: 100%; block-size: 100%; @@ -75,18 +79,19 @@ unconditionally select the container so we can use cqmin units */ } .fg { - position: absolute; + grid-area: content; --fg-inset: var( --media-view-fg-inset, calc(var(--media-view-border-radius) - var(--cpd-space-3x)) ); - inset: var(--fg-inset); + padding: var(--fg-inset); display: grid; grid-template-columns: 1fr auto; grid-template-rows: 1fr auto; grid-template-areas: "status reactions" "nameTag button"; gap: var(--cpd-space-1x); place-items: start; + contain: strict; } .nameTag { From eeafd81d311fbd8061423923e6370b36b34919ae Mon Sep 17 00:00:00 2001 From: Valere Date: Fri, 17 Apr 2026 14:58:10 +0200 Subject: [PATCH 519/748] test: add a screenshare test --- playwright/widget/screen-share.test.ts | 150 +++++++++++++++++++++++++ src/tile/SpotlightTile.tsx | 1 + 2 files changed, 151 insertions(+) create mode 100644 playwright/widget/screen-share.test.ts diff --git a/playwright/widget/screen-share.test.ts b/playwright/widget/screen-share.test.ts new file mode 100644 index 000000000..dc11dc276 --- /dev/null +++ b/playwright/widget/screen-share.test.ts @@ -0,0 +1,150 @@ +/* +Copyright 2026 Element Creations Ltd. + +SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial +Please see LICENSE in the repository root for full details. +*/ + +import { expect, test } from "@playwright/test"; + +import { widgetTest } from "../fixtures/widget-user.ts"; +import { HOST1, TestHelpers } from "./test-helpers.ts"; + +widgetTest("Sharing screen in group call", async ({ addUser, browserName }) => { + test.skip( + browserName === "firefox", + "The is test is not working on firefox CI environment. No mic/audio device inputs so cam/mic are disabled", + ); + + test.slow(); // We are registering multiple users here, give it more time + + const alice = await addUser("Alice", HOST1); + const bob = await addUser("Bob", HOST1); + const carol = await addUser("Carol", HOST1); + + const roomName = "Meeting Room"; + await TestHelpers.createRoom(roomName, alice.page, [bob.mxId, carol.mxId]); + + for (const user of [bob, carol]) { + // Accept the invite + // This isn't super stable to get this as this super generic locator, + // but it works for now. + await TestHelpers.acceptRoomInvite(roomName, user.page); + } + + await TestHelpers.startCallInCurrentRoom(alice.page, false); + await expect( + alice.page.locator('iframe[title="Element Call"]'), + ).toBeVisible(); + + await TestHelpers.joinCallFromLobby(alice.page); + + for (const user of [bob, carol]) { + await TestHelpers.joinCallInCurrentRoom(user.page); + } + + for (const user of [alice, bob, carol]) { + const frame = user.page + .locator('iframe[title="Element Call"]') + .contentFrame(); + + // Expect 3 video tiles + await expect(frame.locator("video")).toHaveCount(3, { + timeout: 5000, + }); + } + + // await alice.page.pause(); + + await alice.page + .locator('iframe[title="Element Call"]') + .contentFrame() + .getByTestId("incall_screenshare") + .click(); + + // await alice.page.pause(); + + for (const user of [alice, bob, carol]) { + const frame = user.page + .locator('iframe[title="Element Call"]') + .contentFrame(); + + // Expect 4 (3 + screen share) video tiles + await expect(frame.locator("video")).toHaveCount(4, { + timeout: 5000, + }); + + await expect( + frame.locator('video[data-lk-source="screen_share"]'), + ).toHaveCount(1); + } + + // Alice should be in grid mode as she is local sharing + { + const frame = alice.page + .locator('iframe[title="Element Call"]') + .contentFrame(); + await expect(frame.getByRole("radio", { name: "Grid" })).toBeChecked(); + } + + // Others should have switched to spotlight + for (const user of [bob, carol]) { + const frame = user.page + .locator('iframe[title="Element Call"]') + .contentFrame(); + + await expect(frame.getByRole("radio", { name: "Spotlight" })).toBeChecked(); + } + // await alice.page.pause(); + // await bob.page.pause(); + + // Let's start another screen share from bob + await bob.page + .locator('iframe[title="Element Call"]') + .contentFrame() + .getByTestId("incall_screenshare") + .click(); + + { + const frame = carol.page + .locator('iframe[title="Element Call"]') + .contentFrame(); + + // Expect 5 (2 + screen share) video tiles + await expect(frame.locator("video")).toHaveCount(5, { + timeout: 5000, + }); + + await expect( + frame.locator('video[data-lk-source="screen_share"]'), + ).toHaveCount(2); + + // Expect 2 indicators at the bottom + await expect(frame.getByTestId("screenshare-indicator")).toHaveCount(2); + + // Check the first indicator is visible + await expect( + frame.getByTestId("screenshare-indicator").first(), + ).toHaveAttribute("data-visible", "true"); + + await carol.page.pause(); + + // now click on next + await expect(frame.getByRole("button", { name: "Next" })).toBeVisible(); + await frame.getByRole("button", { name: "Next" }).click(); + + // Check the second indicator is visible + await expect( + frame.getByTestId("screenshare-indicator").nth(1), + ).toHaveAttribute("data-visible", "true"); + // the first one should be grayed out + await expect( + frame.getByTestId("screenshare-indicator").first(), + ).toHaveAttribute("data-visible", "false"); + + // There should be a prev button now + await expect(frame.getByRole("button", { name: "Back" })).toBeVisible(); + + // await carol.page.pause(); + } +}); diff --git a/src/tile/SpotlightTile.tsx b/src/tile/SpotlightTile.tsx index c5faba400..808773b02 100644 --- a/src/tile/SpotlightTile.tsx +++ b/src/tile/SpotlightTile.tsx @@ -562,6 +562,7 @@ export const SpotlightTile: FC = ({ > {media.map((vm) => (
Date: Fri, 17 Apr 2026 17:29:35 +0200 Subject: [PATCH 520/748] review: use role locator instead of testID --- playwright/widget/screen-share.test.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/playwright/widget/screen-share.test.ts b/playwright/widget/screen-share.test.ts index dc11dc276..c60ef6976 100644 --- a/playwright/widget/screen-share.test.ts +++ b/playwright/widget/screen-share.test.ts @@ -59,7 +59,7 @@ widgetTest("Sharing screen in group call", async ({ addUser, browserName }) => { await alice.page .locator('iframe[title="Element Call"]') .contentFrame() - .getByTestId("incall_screenshare") + .getByRole("switch", { name: "Share screen" }) .click(); // await alice.page.pause(); @@ -102,7 +102,7 @@ widgetTest("Sharing screen in group call", async ({ addUser, browserName }) => { await bob.page .locator('iframe[title="Element Call"]') .contentFrame() - .getByTestId("incall_screenshare") + .getByRole("switch", { name: "Share screen" }) .click(); { From 938a03d0c1e05267b2af4326f073aaa91a5c5a6f Mon Sep 17 00:00:00 2001 From: fkwp Date: Fri, 17 Apr 2026 18:21:48 +0200 Subject: [PATCH 521/748] address review comments --- package.json | 2 +- src/vitest.setup.ts | 50 ++++++++++++++++++++++++++++++++++++++++++++ vitest.config.ts | 2 +- vitest.setup.ts | 51 --------------------------------------------- 4 files changed, 52 insertions(+), 53 deletions(-) delete mode 100644 vitest.setup.ts diff --git a/package.json b/package.json index 8225419ba..9dbc7e735 100644 --- a/package.json +++ b/package.json @@ -110,7 +110,7 @@ "livekit-client": "^2.18.1", "lodash-es": "^4.17.21", "loglevel": "^1.9.1", - "matrix-js-sdk": "matrix-org/matrix-js-sdk#ca5655bced1cbb215ac1c18e179384a069d98b0a", + "matrix-js-sdk": "matrix-org/matrix-js-sdk#develop", "matrix-widget-api": "^1.16.1", "node-stdlib-browser": "^1.3.1", "normalize.css": "^8.0.1", diff --git a/src/vitest.setup.ts b/src/vitest.setup.ts index f3f5928b6..ca65006e2 100644 --- a/src/vitest.setup.ts +++ b/src/vitest.setup.ts @@ -51,3 +51,53 @@ window.matchMedia = global.matchMedia = (): MediaQueryList => addEventListener: () => {}, removeEventListener: () => {}, }) as Partial as MediaQueryList; + +const storage: Record = {}; +const localStoragePolyfill = { + getItem(key: string) { + return Object.prototype.hasOwnProperty.call(storage, key) + ? storage[key] + : null; + }, + setItem(key: string, value: string) { + storage[key] = String(value); + }, + removeItem(key: string) { + delete storage[key]; + }, + clear() { + for (const key in storage) { + delete storage[key]; + } + }, + key(index: number) { + const keys = Object.keys(storage); + return keys[index] ?? null; + }, + get length() { + return Object.keys(storage).length; + }, +} as unknown as Storage; + +if ( + typeof globalThis.localStorage === "undefined" || + typeof globalThis.localStorage.clear !== "function" +) { + Object.defineProperty(globalThis, "localStorage", { + value: localStoragePolyfill, + writable: true, + configurable: true, + }); +} + +if ( + typeof window !== "undefined" && + (typeof window.localStorage === "undefined" || + typeof window.localStorage.clear !== "function") +) { + Object.defineProperty(window, "localStorage", { + value: localStoragePolyfill, + writable: true, + configurable: true, + }); +} \ No newline at end of file diff --git a/vitest.config.ts b/vitest.config.ts index 7f449f459..90082f582 100644 --- a/vitest.config.ts +++ b/vitest.config.ts @@ -13,7 +13,7 @@ export default defineConfig((configEnv) => classNameStrategy: "non-scoped", }, }, - setupFiles: ["vitest.setup.ts"], + setupFiles: ["src/vitest.setup.ts"], include: ["src/**/*.test.ts", "src/**/*.test.tsx"], coverage: { reporter: ["html", "json"], diff --git a/vitest.setup.ts b/vitest.setup.ts deleted file mode 100644 index cff3a2344..000000000 --- a/vitest.setup.ts +++ /dev/null @@ -1,51 +0,0 @@ -const storage: Record = {}; -const localStoragePolyfill = { - getItem(key: string) { - return Object.prototype.hasOwnProperty.call(storage, key) - ? storage[key] - : null; - }, - setItem(key: string, value: string) { - storage[key] = String(value); - }, - removeItem(key: string) { - delete storage[key]; - }, - clear() { - for (const key in storage) { - delete storage[key]; - } - }, - key(index: number) { - const keys = Object.keys(storage); - return keys[index] ?? null; - }, - get length() { - return Object.keys(storage).length; - }, -} as unknown as Storage; - -if ( - typeof globalThis.localStorage === "undefined" || - typeof globalThis.localStorage.clear !== "function" -) { - Object.defineProperty(globalThis, "localStorage", { - value: localStoragePolyfill, - writable: true, - configurable: true, - }); -} - -if ( - typeof window !== "undefined" && - (typeof window.localStorage === "undefined" || - typeof window.localStorage.clear !== "function") -) { - Object.defineProperty(window, "localStorage", { - value: localStoragePolyfill, - writable: true, - configurable: true, - }); -} - -import "./src/vitest.setup.ts"; From d75f2563c6fa2a8baf9eaae05c2c753bdb19f00d Mon Sep 17 00:00:00 2001 From: fkwp Date: Fri, 17 Apr 2026 18:23:32 +0200 Subject: [PATCH 522/748] getting ride of `shamefully-hoist=true` --- .npmrc | 1 - package.json | 2 + pnpm-lock.yaml | 13926 +++++++++++++++++------------------------------ vite.config.ts | 15 +- 4 files changed, 5109 insertions(+), 8835 deletions(-) delete mode 100644 .npmrc diff --git a/.npmrc b/.npmrc deleted file mode 100644 index bf2e7648b..000000000 --- a/.npmrc +++ /dev/null @@ -1 +0,0 @@ -shamefully-hoist=true diff --git a/package.json b/package.json index 9dbc7e735..65c0f4690 100644 --- a/package.json +++ b/package.json @@ -137,8 +137,10 @@ "vite": "^8.0.0", "vite-plugin-generate-file": "^0.3.0", "vite-plugin-html": "^3.2.2", + "vite-plugin-node-polyfills": "^0.26.0", "vite-plugin-node-stdlib-browser": "^0.2.1", "vite-plugin-svgr": "^4.0.0", + "vite-plugin-wasm": "^3.6.0", "vitest": "^4.0.18", "vitest-axe": "^1.0.0-pre.3" }, diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 16eaa2c90..01c59c965 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -1,12 +1,12 @@ -lockfileVersion: "9.0" +lockfileVersion: '9.0' settings: autoInstallPeers: true excludeLinksFromLockfile: false overrides: - "@livekit/components-core>rxjs": ^7.8.1 - "@livekit/track-processors>@mediapipe/tasks-vision": ^0.10.18 + '@livekit/components-core>rxjs': ^7.8.1 + '@livekit/track-processors>@mediapipe/tasks-vision': ^0.10.18 minimatch: ^10.2.3 tar: ^7.5.11 glob: ^10.5.0 @@ -15,144 +15,145 @@ overrides: esbuild: ^0.27.7 importers: + .: devDependencies: - "@babel/core": + '@babel/core': specifier: ^7.16.5 version: 7.29.0 - "@babel/preset-env": + '@babel/preset-env': specifier: ^7.22.20 version: 7.29.2(@babel/core@7.29.0) - "@babel/preset-react": + '@babel/preset-react': specifier: ^7.22.15 version: 7.28.5(@babel/core@7.29.0) - "@babel/preset-typescript": + '@babel/preset-typescript': specifier: ^7.23.0 version: 7.28.5(@babel/core@7.29.0) - "@codecov/vite-plugin": + '@codecov/vite-plugin': specifier: ^1.3.0 version: 1.9.1(vite@8.0.8(@types/node@24.12.2)(esbuild@0.27.7)(jiti@2.6.1)(sass@1.99.0)(terser@5.46.1)(yaml@2.8.3)) - "@fontsource/inconsolata": + '@fontsource/inconsolata': specifier: ^5.1.0 version: 5.2.8 - "@fontsource/inter": + '@fontsource/inter': specifier: ^5.1.0 version: 5.2.8 - "@formatjs/intl-durationformat": + '@formatjs/intl-durationformat': specifier: ^0.10.0 version: 0.10.4 - "@formatjs/intl-segmenter": + '@formatjs/intl-segmenter': specifier: ^11.7.3 version: 11.7.12 - "@livekit/components-core": + '@livekit/components-core': specifier: ^0.12.0 version: 0.12.13(livekit-client@2.18.3(@types/dom-mediacapture-record@1.0.22))(tslib@2.8.1) - "@livekit/components-react": + '@livekit/components-react': specifier: ^2.0.0 version: 2.9.20(livekit-client@2.18.3(@types/dom-mediacapture-record@1.0.22))(react-dom@19.2.5(react@19.2.5))(react@19.2.5)(tslib@2.8.1) - "@livekit/protocol": + '@livekit/protocol': specifier: ^1.42.2 version: 1.45.3 - "@livekit/track-processors": + '@livekit/track-processors': specifier: ^0.7.1 version: 0.7.2(@types/dom-mediacapture-transform@0.1.11)(livekit-client@2.18.3(@types/dom-mediacapture-record@1.0.22)) - "@mediapipe/tasks-vision": + '@mediapipe/tasks-vision': specifier: ^0.10.18 version: 0.10.34 - "@playwright/test": + '@playwright/test': specifier: ^1.57.0 version: 1.59.1 - "@radix-ui/react-dialog": + '@radix-ui/react-dialog': specifier: ^1.0.4 version: 1.1.15(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5) - "@radix-ui/react-slider": + '@radix-ui/react-slider': specifier: ^1.1.2 version: 1.3.6(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5) - "@radix-ui/react-visually-hidden": + '@radix-ui/react-visually-hidden': specifier: ^1.0.3 version: 1.2.4(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5) - "@react-spring/web": + '@react-spring/web': specifier: ^10.0.0 version: 10.0.3(react-dom@19.2.5(react@19.2.5))(react@19.2.5) - "@sentry/react": + '@sentry/react': specifier: ^8.0.0 version: 8.55.1(react@19.2.5) - "@sentry/vite-plugin": + '@sentry/vite-plugin': specifier: ^3.0.0 version: 3.6.1 - "@storybook/addon-docs": + '@storybook/addon-docs': specifier: ^10.3.3 - version: 10.3.5(@types/react@19.2.14)(esbuild@0.27.7)(storybook@10.3.5(@testing-library/dom@10.4.1)(prettier@3.8.3)(react-dom@19.2.5(react@19.2.5))(react@19.2.5))(vite@8.0.8(@types/node@24.12.2)(esbuild@0.27.7)(jiti@2.6.1)(sass@1.99.0)(terser@5.46.1)(yaml@2.8.3)) - "@storybook/react-vite": + version: 10.3.5(@types/react@19.2.14)(esbuild@0.27.7)(rollup@4.60.1)(storybook@10.3.5(@testing-library/dom@10.4.1)(prettier@3.8.3)(react-dom@19.2.5(react@19.2.5))(react@19.2.5))(vite@8.0.8(@types/node@24.12.2)(esbuild@0.27.7)(jiti@2.6.1)(sass@1.99.0)(terser@5.46.1)(yaml@2.8.3)) + '@storybook/react-vite': specifier: ^10.3.3 - version: 10.3.5(esbuild@0.27.7)(react-dom@19.2.5(react@19.2.5))(react@19.2.5)(storybook@10.3.5(@testing-library/dom@10.4.1)(prettier@3.8.3)(react-dom@19.2.5(react@19.2.5))(react@19.2.5))(typescript@5.9.3)(vite@8.0.8(@types/node@24.12.2)(esbuild@0.27.7)(jiti@2.6.1)(sass@1.99.0)(terser@5.46.1)(yaml@2.8.3)) - "@stylistic/eslint-plugin": + version: 10.3.5(esbuild@0.27.7)(react-dom@19.2.5(react@19.2.5))(react@19.2.5)(rollup@4.60.1)(storybook@10.3.5(@testing-library/dom@10.4.1)(prettier@3.8.3)(react-dom@19.2.5(react@19.2.5))(react@19.2.5))(typescript@5.9.3)(vite@8.0.8(@types/node@24.12.2)(esbuild@0.27.7)(jiti@2.6.1)(sass@1.99.0)(terser@5.46.1)(yaml@2.8.3)) + '@stylistic/eslint-plugin': specifier: ^3.0.0 version: 3.1.0(eslint@8.57.1)(typescript@5.9.3) - "@testing-library/dom": + '@testing-library/dom': specifier: ^10.1.0 version: 10.4.1 - "@testing-library/jest-dom": + '@testing-library/jest-dom': specifier: ^6.6.3 version: 6.9.1 - "@testing-library/react": + '@testing-library/react': specifier: ^16.0.0 version: 16.3.2(@testing-library/dom@10.4.1)(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5) - "@testing-library/user-event": + '@testing-library/user-event': specifier: ^14.5.1 version: 14.6.1(@testing-library/dom@10.4.1) - "@types/content-type": + '@types/content-type': specifier: ^1.1.5 version: 1.1.9 - "@types/grecaptcha": + '@types/grecaptcha': specifier: ^3.0.9 version: 3.0.9 - "@types/jsdom": + '@types/jsdom': specifier: ^21.1.7 version: 21.1.7 - "@types/lodash-es": + '@types/lodash-es': specifier: ^4.17.12 version: 4.17.12 - "@types/node": + '@types/node': specifier: ^24.0.0 version: 24.12.2 - "@types/pako": + '@types/pako': specifier: ^2.0.3 version: 2.0.4 - "@types/qrcode": + '@types/qrcode': specifier: ^1.5.5 version: 1.5.6 - "@types/react": + '@types/react': specifier: ^19.0.0 version: 19.2.14 - "@types/react-dom": + '@types/react-dom': specifier: ^19.0.0 version: 19.2.3(@types/react@19.2.14) - "@types/sdp-transform": + '@types/sdp-transform': specifier: ^2.4.5 version: 2.15.0 - "@types/uuid": - specifier: "10" + '@types/uuid': + specifier: '10' version: 10.0.0 - "@typescript-eslint/eslint-plugin": + '@typescript-eslint/eslint-plugin': specifier: ^8.31.0 version: 8.58.2(@typescript-eslint/parser@8.58.2(eslint@8.57.1)(typescript@5.9.3))(eslint@8.57.1)(typescript@5.9.3) - "@typescript-eslint/parser": + '@typescript-eslint/parser': specifier: ^8.31.0 version: 8.58.2(eslint@8.57.1)(typescript@5.9.3) - "@use-gesture/react": + '@use-gesture/react': specifier: ^10.2.11 version: 10.3.1(react@19.2.5) - "@vector-im/compound-design-tokens": + '@vector-im/compound-design-tokens': specifier: ^10.0.0 version: 10.1.0(@types/react@19.2.14)(react@19.2.5) - "@vector-im/compound-web": + '@vector-im/compound-web': specifier: ^9.0.0 version: 9.2.0(@fontsource/inconsolata@5.2.8)(@fontsource/inter@5.2.8)(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(@vector-im/compound-design-tokens@10.1.0(@types/react@19.2.14)(react@19.2.5))(react-dom@19.2.5(react@19.2.5))(react@19.2.5) - "@vitejs/plugin-react": + '@vitejs/plugin-react': specifier: ^4.0.1 version: 4.7.0(vite@8.0.8(@types/node@24.12.2)(esbuild@0.27.7)(jiti@2.6.1)(sass@1.99.0)(terser@5.46.1)(yaml@2.8.3)) - "@vitest/coverage-v8": + '@vitest/coverage-v8': specifier: ^4.0.18 version: 4.1.4(vitest@4.1.4) babel-plugin-transform-vite-meta-env: @@ -234,8 +235,8 @@ importers: specifier: ^1.9.1 version: 1.9.2 matrix-js-sdk: - specifier: matrix-org/matrix-js-sdk#ca5655bced1cbb215ac1c18e179384a069d98b0a - version: https://codeload.github.com/matrix-org/matrix-js-sdk/tar.gz/ca5655bced1cbb215ac1c18e179384a069d98b0a + specifier: matrix-org/matrix-js-sdk#develop + version: https://codeload.github.com/matrix-org/matrix-js-sdk/tar.gz/fd01b172368e0ac5479d4830f92ad261a7eccc6c matrix-widget-api: specifier: ^1.16.1 version: 1.17.0 @@ -267,10 +268,10 @@ importers: specifier: ^1.5.4 version: 1.5.4 react: - specifier: "19" + specifier: '19' version: 19.2.5 react-dom: - specifier: "19" + specifier: '19' version: 19.2.5(react@19.2.5) react-i18next: specifier: ^16.0.0 <16.7.0 @@ -314,12 +315,18 @@ importers: vite-plugin-html: specifier: ^3.2.2 version: 3.2.2(vite@8.0.8(@types/node@24.12.2)(esbuild@0.27.7)(jiti@2.6.1)(sass@1.99.0)(terser@5.46.1)(yaml@2.8.3)) + vite-plugin-node-polyfills: + specifier: ^0.26.0 + version: 0.26.0(rollup@4.60.1)(vite@8.0.8(@types/node@24.12.2)(esbuild@0.27.7)(jiti@2.6.1)(sass@1.99.0)(terser@5.46.1)(yaml@2.8.3)) vite-plugin-node-stdlib-browser: specifier: ^0.2.1 - version: 0.2.1(node-stdlib-browser@1.3.1)(vite@8.0.8(@types/node@24.12.2)(esbuild@0.27.7)(jiti@2.6.1)(sass@1.99.0)(terser@5.46.1)(yaml@2.8.3)) + version: 0.2.1(node-stdlib-browser@1.3.1)(rollup@4.60.1)(vite@8.0.8(@types/node@24.12.2)(esbuild@0.27.7)(jiti@2.6.1)(sass@1.99.0)(terser@5.46.1)(yaml@2.8.3)) vite-plugin-svgr: specifier: ^4.0.0 - version: 4.5.0(typescript@5.9.3)(vite@8.0.8(@types/node@24.12.2)(esbuild@0.27.7)(jiti@2.6.1)(sass@1.99.0)(terser@5.46.1)(yaml@2.8.3)) + version: 4.5.0(rollup@4.60.1)(typescript@5.9.3)(vite@8.0.8(@types/node@24.12.2)(esbuild@0.27.7)(jiti@2.6.1)(sass@1.99.0)(terser@5.46.1)(yaml@2.8.3)) + vite-plugin-wasm: + specifier: ^3.6.0 + version: 3.6.0(vite@8.0.8(@types/node@24.12.2)(esbuild@0.27.7)(jiti@2.6.1)(sass@1.99.0)(terser@5.46.1)(yaml@2.8.3)) vitest: specifier: ^4.0.18 version: 4.1.4(@types/node@24.12.2)(@vitest/coverage-v8@4.1.4)(jsdom@26.1.0)(vite@8.0.8(@types/node@24.12.2)(esbuild@0.27.7)(jiti@2.6.1)(sass@1.99.0)(terser@5.46.1)(yaml@2.8.3)) @@ -328,3339 +335,2328 @@ importers: version: 1.0.0-pre.5(vitest@4.1.4(@types/node@24.12.2)(@vitest/coverage-v8@4.1.4)(jsdom@26.1.0)(vite@8.0.8(@types/node@24.12.2)(esbuild@0.27.7)(jiti@2.6.1)(sass@1.99.0)(terser@5.46.1)(yaml@2.8.3))) packages: - "@actions/core@1.11.1": - resolution: - { - integrity: sha512-hXJCSrkwfA46Vd9Z3q4cpEpHB1rL5NG04+/rbqW9d3+CSvtB1tYe8UTpAlixa1vj0m/ULglfEK2UKxMGxCxv5A==, - } - "@actions/exec@1.1.1": - resolution: - { - integrity: sha512-+sCcHHbVdk93a0XT19ECtO/gIXoxvdsgQLzb2fE2/5sIZmWQuluYyjPQtrtTHdU1YzTZ7bAPN4sITq2xi1679w==, - } + '@actions/core@1.11.1': + resolution: {integrity: sha512-hXJCSrkwfA46Vd9Z3q4cpEpHB1rL5NG04+/rbqW9d3+CSvtB1tYe8UTpAlixa1vj0m/ULglfEK2UKxMGxCxv5A==} - "@actions/github@6.0.1": - resolution: - { - integrity: sha512-xbZVcaqD4XnQAe35qSQqskb3SqIAfRyLBrHMd/8TuL7hJSz2QtbDwnNM8zWx4zO5l2fnGtseNE3MbEvD7BxVMw==, - } + '@actions/exec@1.1.1': + resolution: {integrity: sha512-+sCcHHbVdk93a0XT19ECtO/gIXoxvdsgQLzb2fE2/5sIZmWQuluYyjPQtrtTHdU1YzTZ7bAPN4sITq2xi1679w==} - "@actions/http-client@2.2.3": - resolution: - { - integrity: sha512-mx8hyJi/hjFvbPokCg4uRd4ZX78t+YyRPtnKWwIl+RzNaVuFpQHfmlGVfsKEJN8LwTCvL+DfVgAM04XaHkm6bA==, - } + '@actions/github@6.0.1': + resolution: {integrity: sha512-xbZVcaqD4XnQAe35qSQqskb3SqIAfRyLBrHMd/8TuL7hJSz2QtbDwnNM8zWx4zO5l2fnGtseNE3MbEvD7BxVMw==} - "@actions/io@1.1.3": - resolution: - { - integrity: sha512-wi9JjgKLYS7U/z8PPbco+PvTb/nRWjeoFlJ1Qer83k/3C5PHQi28hiVdeE2kHXmIL99mQFawx8qt/JPjZilJ8Q==, - } + '@actions/http-client@2.2.3': + resolution: {integrity: sha512-mx8hyJi/hjFvbPokCg4uRd4ZX78t+YyRPtnKWwIl+RzNaVuFpQHfmlGVfsKEJN8LwTCvL+DfVgAM04XaHkm6bA==} - "@adobe/css-tools@4.4.4": - resolution: - { - integrity: sha512-Elp+iwUx5rN5+Y8xLt5/GRoG20WGoDCQ/1Fb+1LiGtvwbDavuSk0jhD/eZdckHAuzcDzccnkv+rEjyWfRx18gg==, - } + '@actions/io@1.1.3': + resolution: {integrity: sha512-wi9JjgKLYS7U/z8PPbco+PvTb/nRWjeoFlJ1Qer83k/3C5PHQi28hiVdeE2kHXmIL99mQFawx8qt/JPjZilJ8Q==} - "@asamuzakjp/css-color@3.2.0": - resolution: - { - integrity: sha512-K1A6z8tS3XsmCMM86xoWdn7Fkdn9m6RSVtocUrJYIwZnFVkng/PvkEoWtOWmP+Scc6saYWHWZYbndEEXxl24jw==, - } + '@adobe/css-tools@4.4.4': + resolution: {integrity: sha512-Elp+iwUx5rN5+Y8xLt5/GRoG20WGoDCQ/1Fb+1LiGtvwbDavuSk0jhD/eZdckHAuzcDzccnkv+rEjyWfRx18gg==} - "@babel/code-frame@7.29.0": - resolution: - { - integrity: sha512-9NhCeYjq9+3uxgdtp20LSiJXJvN0FeCtNGpJxuMFZ1Kv3cWUNb6DOhJwUvcVCzKGR66cw4njwM6hrJLqgOwbcw==, - } - engines: { node: ">=6.9.0" } + '@asamuzakjp/css-color@3.2.0': + resolution: {integrity: sha512-K1A6z8tS3XsmCMM86xoWdn7Fkdn9m6RSVtocUrJYIwZnFVkng/PvkEoWtOWmP+Scc6saYWHWZYbndEEXxl24jw==} - "@babel/compat-data@7.29.0": - resolution: - { - integrity: sha512-T1NCJqT/j9+cn8fvkt7jtwbLBfLC/1y1c7NtCeXFRgzGTsafi68MRv8yzkYSapBnFA6L3U2VSc02ciDzoAJhJg==, - } - engines: { node: ">=6.9.0" } + '@babel/code-frame@7.29.0': + resolution: {integrity: sha512-9NhCeYjq9+3uxgdtp20LSiJXJvN0FeCtNGpJxuMFZ1Kv3cWUNb6DOhJwUvcVCzKGR66cw4njwM6hrJLqgOwbcw==} + engines: {node: '>=6.9.0'} - "@babel/core@7.29.0": - resolution: - { - integrity: sha512-CGOfOJqWjg2qW/Mb6zNsDm+u5vFQ8DxXfbM09z69p5Z6+mE1ikP2jUXw+j42Pf1XTYED2Rni5f95npYeuwMDQA==, - } - engines: { node: ">=6.9.0" } + '@babel/compat-data@7.29.0': + resolution: {integrity: sha512-T1NCJqT/j9+cn8fvkt7jtwbLBfLC/1y1c7NtCeXFRgzGTsafi68MRv8yzkYSapBnFA6L3U2VSc02ciDzoAJhJg==} + engines: {node: '>=6.9.0'} - "@babel/eslint-parser@7.28.6": - resolution: - { - integrity: sha512-QGmsKi2PBO/MHSQk+AAgA9R6OHQr+VqnniFE0eMWZcVcfBZoA2dKn2hUsl3Csg/Plt9opRUWdY7//VXsrIlEiA==, - } - engines: { node: ^10.13.0 || ^12.13.0 || >=14.0.0 } + '@babel/core@7.29.0': + resolution: {integrity: sha512-CGOfOJqWjg2qW/Mb6zNsDm+u5vFQ8DxXfbM09z69p5Z6+mE1ikP2jUXw+j42Pf1XTYED2Rni5f95npYeuwMDQA==} + engines: {node: '>=6.9.0'} + + '@babel/eslint-parser@7.28.6': + resolution: {integrity: sha512-QGmsKi2PBO/MHSQk+AAgA9R6OHQr+VqnniFE0eMWZcVcfBZoA2dKn2hUsl3Csg/Plt9opRUWdY7//VXsrIlEiA==} + engines: {node: ^10.13.0 || ^12.13.0 || >=14.0.0} peerDependencies: - "@babel/core": ^7.11.0 + '@babel/core': ^7.11.0 eslint: ^7.5.0 || ^8.0.0 || ^9.0.0 - "@babel/eslint-plugin@7.27.1": - resolution: - { - integrity: sha512-vOG/EipZbIAcREK6XI4JRO3B3uZr70/KIhsrNLO9RXcgLMaW0sTsBpNeTpQUyelB0HsbWd45NIsuTgD3mqr/Og==, - } - engines: { node: ^10.13.0 || ^12.13.0 || >=14.0.0 } + '@babel/eslint-plugin@7.27.1': + resolution: {integrity: sha512-vOG/EipZbIAcREK6XI4JRO3B3uZr70/KIhsrNLO9RXcgLMaW0sTsBpNeTpQUyelB0HsbWd45NIsuTgD3mqr/Og==} + engines: {node: ^10.13.0 || ^12.13.0 || >=14.0.0} peerDependencies: - "@babel/eslint-parser": ^7.11.0 + '@babel/eslint-parser': ^7.11.0 eslint: ^7.5.0 || ^8.0.0 || ^9.0.0 - "@babel/generator@7.29.1": - resolution: - { - integrity: sha512-qsaF+9Qcm2Qv8SRIMMscAvG4O3lJ0F1GuMo5HR/Bp02LopNgnZBC/EkbevHFeGs4ls/oPz9v+Bsmzbkbe+0dUw==, - } - engines: { node: ">=6.9.0" } + '@babel/generator@7.29.1': + resolution: {integrity: sha512-qsaF+9Qcm2Qv8SRIMMscAvG4O3lJ0F1GuMo5HR/Bp02LopNgnZBC/EkbevHFeGs4ls/oPz9v+Bsmzbkbe+0dUw==} + engines: {node: '>=6.9.0'} - "@babel/helper-annotate-as-pure@7.27.3": - resolution: - { - integrity: sha512-fXSwMQqitTGeHLBC08Eq5yXz2m37E4pJX1qAU1+2cNedz/ifv/bVXft90VeSav5nFO61EcNgwr0aJxbyPaWBPg==, - } - engines: { node: ">=6.9.0" } + '@babel/helper-annotate-as-pure@7.27.3': + resolution: {integrity: sha512-fXSwMQqitTGeHLBC08Eq5yXz2m37E4pJX1qAU1+2cNedz/ifv/bVXft90VeSav5nFO61EcNgwr0aJxbyPaWBPg==} + engines: {node: '>=6.9.0'} - "@babel/helper-compilation-targets@7.28.6": - resolution: - { - integrity: sha512-JYtls3hqi15fcx5GaSNL7SCTJ2MNmjrkHXg4FSpOA/grxK8KwyZ5bubHsCq8FXCkua6xhuaaBit+3b7+VZRfcA==, - } - engines: { node: ">=6.9.0" } + '@babel/helper-compilation-targets@7.28.6': + resolution: {integrity: sha512-JYtls3hqi15fcx5GaSNL7SCTJ2MNmjrkHXg4FSpOA/grxK8KwyZ5bubHsCq8FXCkua6xhuaaBit+3b7+VZRfcA==} + engines: {node: '>=6.9.0'} - "@babel/helper-create-class-features-plugin@7.28.6": - resolution: - { - integrity: sha512-dTOdvsjnG3xNT9Y0AUg1wAl38y+4Rl4sf9caSQZOXdNqVn+H+HbbJ4IyyHaIqNR6SW9oJpA/RuRjsjCw2IdIow==, - } - engines: { node: ">=6.9.0" } + '@babel/helper-create-class-features-plugin@7.28.6': + resolution: {integrity: sha512-dTOdvsjnG3xNT9Y0AUg1wAl38y+4Rl4sf9caSQZOXdNqVn+H+HbbJ4IyyHaIqNR6SW9oJpA/RuRjsjCw2IdIow==} + engines: {node: '>=6.9.0'} peerDependencies: - "@babel/core": ^7.0.0 + '@babel/core': ^7.0.0 - "@babel/helper-create-regexp-features-plugin@7.28.5": - resolution: - { - integrity: sha512-N1EhvLtHzOvj7QQOUCCS3NrPJP8c5W6ZXCHDn7Yialuy1iu4r5EmIYkXlKNqT99Ciw+W0mDqWoR6HWMZlFP3hw==, - } - engines: { node: ">=6.9.0" } + '@babel/helper-create-regexp-features-plugin@7.28.5': + resolution: {integrity: sha512-N1EhvLtHzOvj7QQOUCCS3NrPJP8c5W6ZXCHDn7Yialuy1iu4r5EmIYkXlKNqT99Ciw+W0mDqWoR6HWMZlFP3hw==} + engines: {node: '>=6.9.0'} peerDependencies: - "@babel/core": ^7.0.0 + '@babel/core': ^7.0.0 - "@babel/helper-define-polyfill-provider@0.6.8": - resolution: - { - integrity: sha512-47UwBLPpQi1NoWzLuHNjRoHlYXMwIJoBf7MFou6viC/sIHWYygpvr0B6IAyh5sBdA2nr2LPIRww8lfaUVQINBA==, - } + '@babel/helper-define-polyfill-provider@0.6.8': + resolution: {integrity: sha512-47UwBLPpQi1NoWzLuHNjRoHlYXMwIJoBf7MFou6viC/sIHWYygpvr0B6IAyh5sBdA2nr2LPIRww8lfaUVQINBA==} peerDependencies: - "@babel/core": ^7.4.0 || ^8.0.0-0 <8.0.0 + '@babel/core': ^7.4.0 || ^8.0.0-0 <8.0.0 - "@babel/helper-globals@7.28.0": - resolution: - { - integrity: sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw==, - } - engines: { node: ">=6.9.0" } + '@babel/helper-globals@7.28.0': + resolution: {integrity: sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw==} + engines: {node: '>=6.9.0'} - "@babel/helper-member-expression-to-functions@7.28.5": - resolution: - { - integrity: sha512-cwM7SBRZcPCLgl8a7cY0soT1SptSzAlMH39vwiRpOQkJlh53r5hdHwLSCZpQdVLT39sZt+CRpNwYG4Y2v77atg==, - } - engines: { node: ">=6.9.0" } + '@babel/helper-member-expression-to-functions@7.28.5': + resolution: {integrity: sha512-cwM7SBRZcPCLgl8a7cY0soT1SptSzAlMH39vwiRpOQkJlh53r5hdHwLSCZpQdVLT39sZt+CRpNwYG4Y2v77atg==} + engines: {node: '>=6.9.0'} - "@babel/helper-module-imports@7.28.6": - resolution: - { - integrity: sha512-l5XkZK7r7wa9LucGw9LwZyyCUscb4x37JWTPz7swwFE/0FMQAGpiWUZn8u9DzkSBWEcK25jmvubfpw2dnAMdbw==, - } - engines: { node: ">=6.9.0" } + '@babel/helper-module-imports@7.28.6': + resolution: {integrity: sha512-l5XkZK7r7wa9LucGw9LwZyyCUscb4x37JWTPz7swwFE/0FMQAGpiWUZn8u9DzkSBWEcK25jmvubfpw2dnAMdbw==} + engines: {node: '>=6.9.0'} - "@babel/helper-module-transforms@7.28.6": - resolution: - { - integrity: sha512-67oXFAYr2cDLDVGLXTEABjdBJZ6drElUSI7WKp70NrpyISso3plG9SAGEF6y7zbha/wOzUByWWTJvEDVNIUGcA==, - } - engines: { node: ">=6.9.0" } + '@babel/helper-module-transforms@7.28.6': + resolution: {integrity: sha512-67oXFAYr2cDLDVGLXTEABjdBJZ6drElUSI7WKp70NrpyISso3plG9SAGEF6y7zbha/wOzUByWWTJvEDVNIUGcA==} + engines: {node: '>=6.9.0'} peerDependencies: - "@babel/core": ^7.0.0 + '@babel/core': ^7.0.0 - "@babel/helper-optimise-call-expression@7.27.1": - resolution: - { - integrity: sha512-URMGH08NzYFhubNSGJrpUEphGKQwMQYBySzat5cAByY1/YgIRkULnIy3tAMeszlL/so2HbeilYloUmSpd7GdVw==, - } - engines: { node: ">=6.9.0" } + '@babel/helper-optimise-call-expression@7.27.1': + resolution: {integrity: sha512-URMGH08NzYFhubNSGJrpUEphGKQwMQYBySzat5cAByY1/YgIRkULnIy3tAMeszlL/so2HbeilYloUmSpd7GdVw==} + engines: {node: '>=6.9.0'} - "@babel/helper-plugin-utils@7.28.6": - resolution: - { - integrity: sha512-S9gzZ/bz83GRysI7gAD4wPT/AI3uCnY+9xn+Mx/KPs2JwHJIz1W8PZkg2cqyt3RNOBM8ejcXhV6y8Og7ly/Dug==, - } - engines: { node: ">=6.9.0" } + '@babel/helper-plugin-utils@7.28.6': + resolution: {integrity: sha512-S9gzZ/bz83GRysI7gAD4wPT/AI3uCnY+9xn+Mx/KPs2JwHJIz1W8PZkg2cqyt3RNOBM8ejcXhV6y8Og7ly/Dug==} + engines: {node: '>=6.9.0'} - "@babel/helper-remap-async-to-generator@7.27.1": - resolution: - { - integrity: sha512-7fiA521aVw8lSPeI4ZOD3vRFkoqkJcS+z4hFo82bFSH/2tNd6eJ5qCVMS5OzDmZh/kaHQeBaeyxK6wljcPtveA==, - } - engines: { node: ">=6.9.0" } + '@babel/helper-remap-async-to-generator@7.27.1': + resolution: {integrity: sha512-7fiA521aVw8lSPeI4ZOD3vRFkoqkJcS+z4hFo82bFSH/2tNd6eJ5qCVMS5OzDmZh/kaHQeBaeyxK6wljcPtveA==} + engines: {node: '>=6.9.0'} peerDependencies: - "@babel/core": ^7.0.0 + '@babel/core': ^7.0.0 - "@babel/helper-replace-supers@7.28.6": - resolution: - { - integrity: sha512-mq8e+laIk94/yFec3DxSjCRD2Z0TAjhVbEJY3UQrlwVo15Lmt7C2wAUbK4bjnTs4APkwsYLTahXRraQXhb1WCg==, - } - engines: { node: ">=6.9.0" } + '@babel/helper-replace-supers@7.28.6': + resolution: {integrity: sha512-mq8e+laIk94/yFec3DxSjCRD2Z0TAjhVbEJY3UQrlwVo15Lmt7C2wAUbK4bjnTs4APkwsYLTahXRraQXhb1WCg==} + engines: {node: '>=6.9.0'} peerDependencies: - "@babel/core": ^7.0.0 + '@babel/core': ^7.0.0 - "@babel/helper-skip-transparent-expression-wrappers@7.27.1": - resolution: - { - integrity: sha512-Tub4ZKEXqbPjXgWLl2+3JpQAYBJ8+ikpQ2Ocj/q/r0LwE3UhENh7EUabyHjz2kCEsrRY83ew2DQdHluuiDQFzg==, - } - engines: { node: ">=6.9.0" } + '@babel/helper-skip-transparent-expression-wrappers@7.27.1': + resolution: {integrity: sha512-Tub4ZKEXqbPjXgWLl2+3JpQAYBJ8+ikpQ2Ocj/q/r0LwE3UhENh7EUabyHjz2kCEsrRY83ew2DQdHluuiDQFzg==} + engines: {node: '>=6.9.0'} - "@babel/helper-string-parser@7.27.1": - resolution: - { - integrity: sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==, - } - engines: { node: ">=6.9.0" } + '@babel/helper-string-parser@7.27.1': + resolution: {integrity: sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==} + engines: {node: '>=6.9.0'} - "@babel/helper-validator-identifier@7.28.5": - resolution: - { - integrity: sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==, - } - engines: { node: ">=6.9.0" } + '@babel/helper-validator-identifier@7.28.5': + resolution: {integrity: sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==} + engines: {node: '>=6.9.0'} - "@babel/helper-validator-option@7.27.1": - resolution: - { - integrity: sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg==, - } - engines: { node: ">=6.9.0" } + '@babel/helper-validator-option@7.27.1': + resolution: {integrity: sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg==} + engines: {node: '>=6.9.0'} - "@babel/helper-wrap-function@7.28.6": - resolution: - { - integrity: sha512-z+PwLziMNBeSQJonizz2AGnndLsP2DeGHIxDAn+wdHOGuo4Fo1x1HBPPXeE9TAOPHNNWQKCSlA2VZyYyyibDnQ==, - } - engines: { node: ">=6.9.0" } + '@babel/helper-wrap-function@7.28.6': + resolution: {integrity: sha512-z+PwLziMNBeSQJonizz2AGnndLsP2DeGHIxDAn+wdHOGuo4Fo1x1HBPPXeE9TAOPHNNWQKCSlA2VZyYyyibDnQ==} + engines: {node: '>=6.9.0'} - "@babel/helpers@7.29.2": - resolution: - { - integrity: sha512-HoGuUs4sCZNezVEKdVcwqmZN8GoHirLUcLaYVNBK2J0DadGtdcqgr3BCbvH8+XUo4NGjNl3VOtSjEKNzqfFgKw==, - } - engines: { node: ">=6.9.0" } + '@babel/helpers@7.29.2': + resolution: {integrity: sha512-HoGuUs4sCZNezVEKdVcwqmZN8GoHirLUcLaYVNBK2J0DadGtdcqgr3BCbvH8+XUo4NGjNl3VOtSjEKNzqfFgKw==} + engines: {node: '>=6.9.0'} - "@babel/parser@7.29.2": - resolution: - { - integrity: sha512-4GgRzy/+fsBa72/RZVJmGKPmZu9Byn8o4MoLpmNe1m8ZfYnz5emHLQz3U4gLud6Zwl0RZIcgiLD7Uq7ySFuDLA==, - } - engines: { node: ">=6.0.0" } + '@babel/parser@7.29.2': + resolution: {integrity: sha512-4GgRzy/+fsBa72/RZVJmGKPmZu9Byn8o4MoLpmNe1m8ZfYnz5emHLQz3U4gLud6Zwl0RZIcgiLD7Uq7ySFuDLA==} + engines: {node: '>=6.0.0'} hasBin: true - "@babel/plugin-bugfix-firefox-class-in-computed-class-key@7.28.5": - resolution: - { - integrity: sha512-87GDMS3tsmMSi/3bWOte1UblL+YUTFMV8SZPZ2eSEL17s74Cw/l63rR6NmGVKMYW2GYi85nE+/d6Hw5N0bEk2Q==, - } - engines: { node: ">=6.9.0" } - peerDependencies: - "@babel/core": ^7.0.0 - - "@babel/plugin-bugfix-safari-class-field-initializer-scope@7.27.1": - resolution: - { - integrity: sha512-qNeq3bCKnGgLkEXUuFry6dPlGfCdQNZbn7yUAPCInwAJHMU7THJfrBSozkcWq5sNM6RcF3S8XyQL2A52KNR9IA==, - } - engines: { node: ">=6.9.0" } - peerDependencies: - "@babel/core": ^7.0.0 - - "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@7.27.1": - resolution: - { - integrity: sha512-g4L7OYun04N1WyqMNjldFwlfPCLVkgB54A/YCXICZYBsvJJE3kByKv9c9+R/nAfmIfjl2rKYLNyMHboYbZaWaA==, - } - engines: { node: ">=6.9.0" } - peerDependencies: - "@babel/core": ^7.0.0 - - "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@7.27.1": - resolution: - { - integrity: sha512-oO02gcONcD5O1iTLi/6frMJBIwWEHceWGSGqrpCmEL8nogiS6J9PBlE48CaK20/Jx1LuRml9aDftLgdjXT8+Cw==, - } - engines: { node: ">=6.9.0" } - peerDependencies: - "@babel/core": ^7.13.0 - - "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly@7.28.6": - resolution: - { - integrity: sha512-a0aBScVTlNaiUe35UtfxAN7A/tehvvG4/ByO6+46VPKTRSlfnAFsgKy0FUh+qAkQrDTmhDkT+IBOKlOoMUxQ0g==, - } - engines: { node: ">=6.9.0" } - peerDependencies: - "@babel/core": ^7.0.0 - - "@babel/plugin-proposal-private-property-in-object@7.21.0-placeholder-for-preset-env.2": - resolution: - { - integrity: sha512-SOSkfJDddaM7mak6cPEpswyTRnuRltl429hMraQEglW+OkovnCzsiszTmsrlY//qLFjCpQDFRvjdm2wA5pPm9w==, - } - engines: { node: ">=6.9.0" } - peerDependencies: - "@babel/core": ^7.0.0-0 - - "@babel/plugin-syntax-import-assertions@7.28.6": - resolution: - { - integrity: sha512-pSJUpFHdx9z5nqTSirOCMtYVP2wFgoWhP0p3g8ONK/4IHhLIBd0B9NYqAvIUAhq+OkhO4VM1tENCt0cjlsNShw==, - } - engines: { node: ">=6.9.0" } - peerDependencies: - "@babel/core": ^7.0.0-0 - - "@babel/plugin-syntax-import-attributes@7.28.6": - resolution: - { - integrity: sha512-jiLC0ma9XkQT3TKJ9uYvlakm66Pamywo+qwL+oL8HJOvc6TWdZXVfhqJr8CCzbSGUAbDOzlGHJC1U+vRfLQDvw==, - } - engines: { node: ">=6.9.0" } - peerDependencies: - "@babel/core": ^7.0.0-0 - - "@babel/plugin-syntax-jsx@7.28.6": - resolution: - { - integrity: sha512-wgEmr06G6sIpqr8YDwA2dSRTE3bJ+V0IfpzfSY3Lfgd7YWOaAdlykvJi13ZKBt8cZHfgH1IXN+CL656W3uUa4w==, - } - engines: { node: ">=6.9.0" } - peerDependencies: - "@babel/core": ^7.0.0-0 - - "@babel/plugin-syntax-typescript@7.28.6": - resolution: - { - integrity: sha512-+nDNmQye7nlnuuHDboPbGm00Vqg3oO8niRRL27/4LYHUsHYh0zJ1xWOz0uRwNFmM1Avzk8wZbc6rdiYhomzv/A==, - } - engines: { node: ">=6.9.0" } - peerDependencies: - "@babel/core": ^7.0.0-0 - - "@babel/plugin-syntax-unicode-sets-regex@7.18.6": - resolution: - { - integrity: sha512-727YkEAPwSIQTv5im8QHz3upqp92JTWhidIC81Tdx4VJYIte/VndKf1qKrfnnhPLiPghStWfvC/iFaMCQu7Nqg==, - } - engines: { node: ">=6.9.0" } - peerDependencies: - "@babel/core": ^7.0.0 - - "@babel/plugin-transform-arrow-functions@7.27.1": - resolution: - { - integrity: sha512-8Z4TGic6xW70FKThA5HYEKKyBpOOsucTOD1DjU3fZxDg+K3zBJcXMFnt/4yQiZnf5+MiOMSXQ9PaEK/Ilh1DeA==, - } - engines: { node: ">=6.9.0" } - peerDependencies: - "@babel/core": ^7.0.0-0 - - "@babel/plugin-transform-async-generator-functions@7.29.0": - resolution: - { - integrity: sha512-va0VdWro4zlBr2JsXC+ofCPB2iG12wPtVGTWFx2WLDOM3nYQZZIGP82qku2eW/JR83sD+k2k+CsNtyEbUqhU6w==, - } - engines: { node: ">=6.9.0" } - peerDependencies: - "@babel/core": ^7.0.0-0 - - "@babel/plugin-transform-async-to-generator@7.28.6": - resolution: - { - integrity: sha512-ilTRcmbuXjsMmcZ3HASTe4caH5Tpo93PkTxF9oG2VZsSWsahydmcEHhix9Ik122RcTnZnUzPbmux4wh1swfv7g==, - } - engines: { node: ">=6.9.0" } - peerDependencies: - "@babel/core": ^7.0.0-0 - - "@babel/plugin-transform-block-scoped-functions@7.27.1": - resolution: - { - integrity: sha512-cnqkuOtZLapWYZUYM5rVIdv1nXYuFVIltZ6ZJ7nIj585QsjKM5dhL2Fu/lICXZ1OyIAFc7Qy+bvDAtTXqGrlhg==, - } - engines: { node: ">=6.9.0" } - peerDependencies: - "@babel/core": ^7.0.0-0 - - "@babel/plugin-transform-block-scoping@7.28.6": - resolution: - { - integrity: sha512-tt/7wOtBmwHPNMPu7ax4pdPz6shjFrmHDghvNC+FG9Qvj7D6mJcoRQIF5dy4njmxR941l6rgtvfSB2zX3VlUIw==, - } - engines: { node: ">=6.9.0" } - peerDependencies: - "@babel/core": ^7.0.0-0 - - "@babel/plugin-transform-class-properties@7.28.6": - resolution: - { - integrity: sha512-dY2wS3I2G7D697VHndN91TJr8/AAfXQNt5ynCTI/MpxMsSzHp+52uNivYT5wCPax3whc47DR8Ba7cmlQMg24bw==, - } - engines: { node: ">=6.9.0" } - peerDependencies: - "@babel/core": ^7.0.0-0 - - "@babel/plugin-transform-class-static-block@7.28.6": - resolution: - { - integrity: sha512-rfQ++ghVwTWTqQ7w8qyDxL1XGihjBss4CmTgGRCTAC9RIbhVpyp4fOeZtta0Lbf+dTNIVJer6ych2ibHwkZqsQ==, - } - engines: { node: ">=6.9.0" } - peerDependencies: - "@babel/core": ^7.12.0 - - "@babel/plugin-transform-classes@7.28.6": - resolution: - { - integrity: sha512-EF5KONAqC5zAqT783iMGuM2ZtmEBy+mJMOKl2BCvPZ2lVrwvXnB6o+OBWCS+CoeCCpVRF2sA2RBKUxvT8tQT5Q==, - } - engines: { node: ">=6.9.0" } - peerDependencies: - "@babel/core": ^7.0.0-0 - - "@babel/plugin-transform-computed-properties@7.28.6": - resolution: - { - integrity: sha512-bcc3k0ijhHbc2lEfpFHgx7eYw9KNXqOerKWfzbxEHUGKnS3sz9C4CNL9OiFN1297bDNfUiSO7DaLzbvHQQQ1BQ==, - } - engines: { node: ">=6.9.0" } - peerDependencies: - "@babel/core": ^7.0.0-0 - - "@babel/plugin-transform-destructuring@7.28.5": - resolution: - { - integrity: sha512-Kl9Bc6D0zTUcFUvkNuQh4eGXPKKNDOJQXVyyM4ZAQPMveniJdxi8XMJwLo+xSoW3MIq81bD33lcUe9kZpl0MCw==, - } - engines: { node: ">=6.9.0" } - peerDependencies: - "@babel/core": ^7.0.0-0 - - "@babel/plugin-transform-dotall-regex@7.28.6": - resolution: - { - integrity: sha512-SljjowuNKB7q5Oayv4FoPzeB74g3QgLt8IVJw9ADvWy3QnUb/01aw8I4AVv8wYnPvQz2GDDZ/g3GhcNyDBI4Bg==, - } - engines: { node: ">=6.9.0" } - peerDependencies: - "@babel/core": ^7.0.0-0 - - "@babel/plugin-transform-duplicate-keys@7.27.1": - resolution: - { - integrity: sha512-MTyJk98sHvSs+cvZ4nOauwTTG1JeonDjSGvGGUNHreGQns+Mpt6WX/dVzWBHgg+dYZhkC4X+zTDfkTU+Vy9y7Q==, - } - engines: { node: ">=6.9.0" } - peerDependencies: - "@babel/core": ^7.0.0-0 - - "@babel/plugin-transform-duplicate-named-capturing-groups-regex@7.29.0": - resolution: - { - integrity: sha512-zBPcW2lFGxdiD8PUnPwJjag2J9otbcLQzvbiOzDxpYXyCuYX9agOwMPGn1prVH0a4qzhCKu24rlH4c1f7yA8rw==, - } - engines: { node: ">=6.9.0" } - peerDependencies: - "@babel/core": ^7.0.0 - - "@babel/plugin-transform-dynamic-import@7.27.1": - resolution: - { - integrity: sha512-MHzkWQcEmjzzVW9j2q8LGjwGWpG2mjwaaB0BNQwst3FIjqsg8Ct/mIZlvSPJvfi9y2AC8mi/ktxbFVL9pZ1I4A==, - } - engines: { node: ">=6.9.0" } - peerDependencies: - "@babel/core": ^7.0.0-0 - - "@babel/plugin-transform-explicit-resource-management@7.28.6": - resolution: - { - integrity: sha512-Iao5Konzx2b6g7EPqTy40UZbcdXE126tTxVFr/nAIj+WItNxjKSYTEw3RC+A2/ZetmdJsgueL1KhaMCQHkLPIg==, - } - engines: { node: ">=6.9.0" } - peerDependencies: - "@babel/core": ^7.0.0-0 - - "@babel/plugin-transform-exponentiation-operator@7.28.6": - resolution: - { - integrity: sha512-WitabqiGjV/vJ0aPOLSFfNY1u9U3R7W36B03r5I2KoNix+a3sOhJ3pKFB3R5It9/UiK78NiO0KE9P21cMhlPkw==, - } - engines: { node: ">=6.9.0" } - peerDependencies: - "@babel/core": ^7.0.0-0 - - "@babel/plugin-transform-export-namespace-from@7.27.1": - resolution: - { - integrity: sha512-tQvHWSZ3/jH2xuq/vZDy0jNn+ZdXJeM8gHvX4lnJmsc3+50yPlWdZXIc5ay+umX+2/tJIqHqiEqcJvxlmIvRvQ==, - } - engines: { node: ">=6.9.0" } - peerDependencies: - "@babel/core": ^7.0.0-0 - - "@babel/plugin-transform-for-of@7.27.1": - resolution: - { - integrity: sha512-BfbWFFEJFQzLCQ5N8VocnCtA8J1CLkNTe2Ms2wocj75dd6VpiqS5Z5quTYcUoo4Yq+DN0rtikODccuv7RU81sw==, - } - engines: { node: ">=6.9.0" } - peerDependencies: - "@babel/core": ^7.0.0-0 - - "@babel/plugin-transform-function-name@7.27.1": - resolution: - { - integrity: sha512-1bQeydJF9Nr1eBCMMbC+hdwmRlsv5XYOMu03YSWFwNs0HsAmtSxxF1fyuYPqemVldVyFmlCU7w8UE14LupUSZQ==, - } - engines: { node: ">=6.9.0" } - peerDependencies: - "@babel/core": ^7.0.0-0 - - "@babel/plugin-transform-json-strings@7.28.6": - resolution: - { - integrity: sha512-Nr+hEN+0geQkzhbdgQVPoqr47lZbm+5fCUmO70722xJZd0Mvb59+33QLImGj6F+DkK3xgDi1YVysP8whD6FQAw==, - } - engines: { node: ">=6.9.0" } - peerDependencies: - "@babel/core": ^7.0.0-0 - - "@babel/plugin-transform-literals@7.27.1": - resolution: - { - integrity: sha512-0HCFSepIpLTkLcsi86GG3mTUzxV5jpmbv97hTETW3yzrAij8aqlD36toB1D0daVFJM8NK6GvKO0gslVQmm+zZA==, - } - engines: { node: ">=6.9.0" } - peerDependencies: - "@babel/core": ^7.0.0-0 - - "@babel/plugin-transform-logical-assignment-operators@7.28.6": - resolution: - { - integrity: sha512-+anKKair6gpi8VsM/95kmomGNMD0eLz1NQ8+Pfw5sAwWH9fGYXT50E55ZpV0pHUHWf6IUTWPM+f/7AAff+wr9A==, - } - engines: { node: ">=6.9.0" } - peerDependencies: - "@babel/core": ^7.0.0-0 - - "@babel/plugin-transform-member-expression-literals@7.27.1": - resolution: - { - integrity: sha512-hqoBX4dcZ1I33jCSWcXrP+1Ku7kdqXf1oeah7ooKOIiAdKQ+uqftgCFNOSzA5AMS2XIHEYeGFg4cKRCdpxzVOQ==, - } - engines: { node: ">=6.9.0" } - peerDependencies: - "@babel/core": ^7.0.0-0 - - "@babel/plugin-transform-modules-amd@7.27.1": - resolution: - { - integrity: sha512-iCsytMg/N9/oFq6n+gFTvUYDZQOMK5kEdeYxmxt91fcJGycfxVP9CnrxoliM0oumFERba2i8ZtwRUCMhvP1LnA==, - } - engines: { node: ">=6.9.0" } - peerDependencies: - "@babel/core": ^7.0.0-0 - - "@babel/plugin-transform-modules-commonjs@7.28.6": - resolution: - { - integrity: sha512-jppVbf8IV9iWWwWTQIxJMAJCWBuuKx71475wHwYytrRGQ2CWiDvYlADQno3tcYpS/T2UUWFQp3nVtYfK/YBQrA==, - } - engines: { node: ">=6.9.0" } - peerDependencies: - "@babel/core": ^7.0.0-0 - - "@babel/plugin-transform-modules-systemjs@7.29.0": - resolution: - { - integrity: sha512-PrujnVFbOdUpw4UHiVwKvKRLMMic8+eC0CuNlxjsyZUiBjhFdPsewdXCkveh2KqBA9/waD0W1b4hXSOBQJezpQ==, - } - engines: { node: ">=6.9.0" } - peerDependencies: - "@babel/core": ^7.0.0-0 - - "@babel/plugin-transform-modules-umd@7.27.1": - resolution: - { - integrity: sha512-iQBE/xC5BV1OxJbp6WG7jq9IWiD+xxlZhLrdwpPkTX3ydmXdvoCpyfJN7acaIBZaOqTfr76pgzqBJflNbeRK+w==, - } - engines: { node: ">=6.9.0" } - peerDependencies: - "@babel/core": ^7.0.0-0 - - "@babel/plugin-transform-named-capturing-groups-regex@7.29.0": - resolution: - { - integrity: sha512-1CZQA5KNAD6ZYQLPw7oi5ewtDNxH/2vuCh+6SmvgDfhumForvs8a1o9n0UrEoBD8HU4djO2yWngTQlXl1NDVEQ==, - } - engines: { node: ">=6.9.0" } - peerDependencies: - "@babel/core": ^7.0.0 - - "@babel/plugin-transform-new-target@7.27.1": - resolution: - { - integrity: sha512-f6PiYeqXQ05lYq3TIfIDu/MtliKUbNwkGApPUvyo6+tc7uaR4cPjPe7DFPr15Uyycg2lZU6btZ575CuQoYh7MQ==, - } - engines: { node: ">=6.9.0" } - peerDependencies: - "@babel/core": ^7.0.0-0 - - "@babel/plugin-transform-nullish-coalescing-operator@7.28.6": - resolution: - { - integrity: sha512-3wKbRgmzYbw24mDJXT7N+ADXw8BC/imU9yo9c9X9NKaLF1fW+e5H1U5QjMUBe4Qo4Ox/o++IyUkl1sVCLgevKg==, - } - engines: { node: ">=6.9.0" } - peerDependencies: - "@babel/core": ^7.0.0-0 - - "@babel/plugin-transform-numeric-separator@7.28.6": - resolution: - { - integrity: sha512-SJR8hPynj8outz+SlStQSwvziMN4+Bq99it4tMIf5/Caq+3iOc0JtKyse8puvyXkk3eFRIA5ID/XfunGgO5i6w==, - } - engines: { node: ">=6.9.0" } - peerDependencies: - "@babel/core": ^7.0.0-0 - - "@babel/plugin-transform-object-rest-spread@7.28.6": - resolution: - { - integrity: sha512-5rh+JR4JBC4pGkXLAcYdLHZjXudVxWMXbB6u6+E9lRL5TrGVbHt1TjxGbZ8CkmYw9zjkB7jutzOROArsqtncEA==, - } - engines: { node: ">=6.9.0" } - peerDependencies: - "@babel/core": ^7.0.0-0 - - "@babel/plugin-transform-object-super@7.27.1": - resolution: - { - integrity: sha512-SFy8S9plRPbIcxlJ8A6mT/CxFdJx/c04JEctz4jf8YZaVS2px34j7NXRrlGlHkN/M2gnpL37ZpGRGVFLd3l8Ng==, - } - engines: { node: ">=6.9.0" } - peerDependencies: - "@babel/core": ^7.0.0-0 - - "@babel/plugin-transform-optional-catch-binding@7.28.6": - resolution: - { - integrity: sha512-R8ja/Pyrv0OGAvAXQhSTmWyPJPml+0TMqXlO5w+AsMEiwb2fg3WkOvob7UxFSL3OIttFSGSRFKQsOhJ/X6HQdQ==, - } - engines: { node: ">=6.9.0" } - peerDependencies: - "@babel/core": ^7.0.0-0 - - "@babel/plugin-transform-optional-chaining@7.28.6": - resolution: - { - integrity: sha512-A4zobikRGJTsX9uqVFdafzGkqD30t26ck2LmOzAuLL8b2x6k3TIqRiT2xVvA9fNmFeTX484VpsdgmKNA0bS23w==, - } - engines: { node: ">=6.9.0" } - peerDependencies: - "@babel/core": ^7.0.0-0 - - "@babel/plugin-transform-parameters@7.27.7": - resolution: - { - integrity: sha512-qBkYTYCb76RRxUM6CcZA5KRu8K4SM8ajzVeUgVdMVO9NN9uI/GaVmBg/WKJJGnNokV9SY8FxNOVWGXzqzUidBg==, - } - engines: { node: ">=6.9.0" } - peerDependencies: - "@babel/core": ^7.0.0-0 - - "@babel/plugin-transform-private-methods@7.28.6": - resolution: - { - integrity: sha512-piiuapX9CRv7+0st8lmuUlRSmX6mBcVeNQ1b4AYzJxfCMuBfB0vBXDiGSmm03pKJw1v6cZ8KSeM+oUnM6yAExg==, - } - engines: { node: ">=6.9.0" } - peerDependencies: - "@babel/core": ^7.0.0-0 - - "@babel/plugin-transform-private-property-in-object@7.28.6": - resolution: - { - integrity: sha512-b97jvNSOb5+ehyQmBpmhOCiUC5oVK4PMnpRvO7+ymFBoqYjeDHIU9jnrNUuwHOiL9RpGDoKBpSViarV+BU+eVA==, - } - engines: { node: ">=6.9.0" } - peerDependencies: - "@babel/core": ^7.0.0-0 - - "@babel/plugin-transform-property-literals@7.27.1": - resolution: - { - integrity: sha512-oThy3BCuCha8kDZ8ZkgOg2exvPYUlprMukKQXI1r1pJ47NCvxfkEy8vK+r/hT9nF0Aa4H1WUPZZjHTFtAhGfmQ==, - } - engines: { node: ">=6.9.0" } - peerDependencies: - "@babel/core": ^7.0.0-0 - - "@babel/plugin-transform-react-display-name@7.28.0": - resolution: - { - integrity: sha512-D6Eujc2zMxKjfa4Zxl4GHMsmhKKZ9VpcqIchJLvwTxad9zWIYulwYItBovpDOoNLISpcZSXoDJ5gaGbQUDqViA==, - } - engines: { node: ">=6.9.0" } - peerDependencies: - "@babel/core": ^7.0.0-0 - - "@babel/plugin-transform-react-jsx-development@7.27.1": - resolution: - { - integrity: sha512-ykDdF5yI4f1WrAolLqeF3hmYU12j9ntLQl/AOG1HAS21jxyg1Q0/J/tpREuYLfatGdGmXp/3yS0ZA76kOlVq9Q==, - } - engines: { node: ">=6.9.0" } - peerDependencies: - "@babel/core": ^7.0.0-0 - - "@babel/plugin-transform-react-jsx-self@7.27.1": - resolution: - { - integrity: sha512-6UzkCs+ejGdZ5mFFC/OCUrv028ab2fp1znZmCZjAOBKiBK2jXD1O+BPSfX8X2qjJ75fZBMSnQn3Rq2mrBJK2mw==, - } - engines: { node: ">=6.9.0" } - peerDependencies: - "@babel/core": ^7.0.0-0 - - "@babel/plugin-transform-react-jsx-source@7.27.1": - resolution: - { - integrity: sha512-zbwoTsBruTeKB9hSq73ha66iFeJHuaFkUbwvqElnygoNbj/jHRsSeokowZFN3CZ64IvEqcmmkVe89OPXc7ldAw==, - } - engines: { node: ">=6.9.0" } - peerDependencies: - "@babel/core": ^7.0.0-0 - - "@babel/plugin-transform-react-jsx@7.28.6": - resolution: - { - integrity: sha512-61bxqhiRfAACulXSLd/GxqmAedUSrRZIu/cbaT18T1CetkTmtDN15it7i80ru4DVqRK1WMxQhXs+Lf9kajm5Ow==, - } - engines: { node: ">=6.9.0" } - peerDependencies: - "@babel/core": ^7.0.0-0 - - "@babel/plugin-transform-react-pure-annotations@7.27.1": - resolution: - { - integrity: sha512-JfuinvDOsD9FVMTHpzA/pBLisxpv1aSf+OIV8lgH3MuWrks19R27e6a6DipIg4aX1Zm9Wpb04p8wljfKrVSnPA==, - } - engines: { node: ">=6.9.0" } - peerDependencies: - "@babel/core": ^7.0.0-0 - - "@babel/plugin-transform-regenerator@7.29.0": - resolution: - { - integrity: sha512-FijqlqMA7DmRdg/aINBSs04y8XNTYw/lr1gJ2WsmBnnaNw1iS43EPkJW+zK7z65auG3AWRFXWj+NcTQwYptUog==, - } - engines: { node: ">=6.9.0" } - peerDependencies: - "@babel/core": ^7.0.0-0 - - "@babel/plugin-transform-regexp-modifiers@7.28.6": - resolution: - { - integrity: sha512-QGWAepm9qxpaIs7UM9FvUSnCGlb8Ua1RhyM4/veAxLwt3gMat/LSGrZixyuj4I6+Kn9iwvqCyPTtbdxanYoWYg==, - } - engines: { node: ">=6.9.0" } - peerDependencies: - "@babel/core": ^7.0.0 - - "@babel/plugin-transform-reserved-words@7.27.1": - resolution: - { - integrity: sha512-V2ABPHIJX4kC7HegLkYoDpfg9PVmuWy/i6vUM5eGK22bx4YVFD3M5F0QQnWQoDs6AGsUWTVOopBiMFQgHaSkVw==, - } - engines: { node: ">=6.9.0" } - peerDependencies: - "@babel/core": ^7.0.0-0 - - "@babel/plugin-transform-shorthand-properties@7.27.1": - resolution: - { - integrity: sha512-N/wH1vcn4oYawbJ13Y/FxcQrWk63jhfNa7jef0ih7PHSIHX2LB7GWE1rkPrOnka9kwMxb6hMl19p7lidA+EHmQ==, - } - engines: { node: ">=6.9.0" } - peerDependencies: - "@babel/core": ^7.0.0-0 - - "@babel/plugin-transform-spread@7.28.6": - resolution: - { - integrity: sha512-9U4QObUC0FtJl05AsUcodau/RWDytrU6uKgkxu09mLR9HLDAtUMoPuuskm5huQsoktmsYpI+bGmq+iapDcriKA==, - } - engines: { node: ">=6.9.0" } - peerDependencies: - "@babel/core": ^7.0.0-0 - - "@babel/plugin-transform-sticky-regex@7.27.1": - resolution: - { - integrity: sha512-lhInBO5bi/Kowe2/aLdBAawijx+q1pQzicSgnkB6dUPc1+RC8QmJHKf2OjvU+NZWitguJHEaEmbV6VWEouT58g==, - } - engines: { node: ">=6.9.0" } - peerDependencies: - "@babel/core": ^7.0.0-0 - - "@babel/plugin-transform-template-literals@7.27.1": - resolution: - { - integrity: sha512-fBJKiV7F2DxZUkg5EtHKXQdbsbURW3DZKQUWphDum0uRP6eHGGa/He9mc0mypL680pb+e/lDIthRohlv8NCHkg==, - } - engines: { node: ">=6.9.0" } - peerDependencies: - "@babel/core": ^7.0.0-0 - - "@babel/plugin-transform-typeof-symbol@7.27.1": - resolution: - { - integrity: sha512-RiSILC+nRJM7FY5srIyc4/fGIwUhyDuuBSdWn4y6yT6gm652DpCHZjIipgn6B7MQ1ITOUnAKWixEUjQRIBIcLw==, - } - engines: { node: ">=6.9.0" } - peerDependencies: - "@babel/core": ^7.0.0-0 - - "@babel/plugin-transform-typescript@7.28.6": - resolution: - { - integrity: sha512-0YWL2RFxOqEm9Efk5PvreamxPME8OyY0wM5wh5lHjF+VtVhdneCWGzZeSqzOfiobVqQaNCd2z0tQvnI9DaPWPw==, - } - engines: { node: ">=6.9.0" } - peerDependencies: - "@babel/core": ^7.0.0-0 - - "@babel/plugin-transform-unicode-escapes@7.27.1": - resolution: - { - integrity: sha512-Ysg4v6AmF26k9vpfFuTZg8HRfVWzsh1kVfowA23y9j/Gu6dOuahdUVhkLqpObp3JIv27MLSii6noRnuKN8H0Mg==, - } - engines: { node: ">=6.9.0" } - peerDependencies: - "@babel/core": ^7.0.0-0 - - "@babel/plugin-transform-unicode-property-regex@7.28.6": - resolution: - { - integrity: sha512-4Wlbdl/sIZjzi/8St0evF0gEZrgOswVO6aOzqxh1kDZOl9WmLrHq2HtGhnOJZmHZYKP8WZ1MDLCt5DAWwRo57A==, - } - engines: { node: ">=6.9.0" } - peerDependencies: - "@babel/core": ^7.0.0-0 - - "@babel/plugin-transform-unicode-regex@7.27.1": - resolution: - { - integrity: sha512-xvINq24TRojDuyt6JGtHmkVkrfVV3FPT16uytxImLeBZqW3/H52yN+kM1MGuyPkIQxrzKwPHs5U/MP3qKyzkGw==, - } - engines: { node: ">=6.9.0" } - peerDependencies: - "@babel/core": ^7.0.0-0 - - "@babel/plugin-transform-unicode-sets-regex@7.28.6": - resolution: - { - integrity: sha512-/wHc/paTUmsDYN7SZkpWxogTOBNnlx7nBQYfy6JJlCT7G3mVhltk3e++N7zV0XfgGsrqBxd4rJQt9H16I21Y1Q==, - } - engines: { node: ">=6.9.0" } - peerDependencies: - "@babel/core": ^7.0.0 - - "@babel/preset-env@7.29.2": - resolution: - { - integrity: sha512-DYD23veRYGvBFhcTY1iUvJnDNpuqNd/BzBwCvzOTKUnJjKg5kpUBh3/u9585Agdkgj+QuygG7jLfOPWMa2KVNw==, - } - engines: { node: ">=6.9.0" } - peerDependencies: - "@babel/core": ^7.0.0-0 - - "@babel/preset-modules@0.1.6-no-external-plugins": - resolution: - { - integrity: sha512-HrcgcIESLm9aIR842yhJ5RWan/gebQUJ6E/E5+rf0y9o6oj7w0Br+sWuL6kEQ/o/AdfvR1Je9jG18/gnpwjEyA==, - } - peerDependencies: - "@babel/core": ^7.0.0-0 || ^8.0.0-0 <8.0.0 - - "@babel/preset-react@7.28.5": - resolution: - { - integrity: sha512-Z3J8vhRq7CeLjdC58jLv4lnZ5RKFUJWqH5emvxmv9Hv3BD1T9R/Im713R4MTKwvFaV74ejZ3sM01LyEKk4ugNQ==, - } - engines: { node: ">=6.9.0" } - peerDependencies: - "@babel/core": ^7.0.0-0 - - "@babel/preset-typescript@7.28.5": - resolution: - { - integrity: sha512-+bQy5WOI2V6LJZpPVxY+yp66XdZ2yifu0Mc1aP5CQKgjn4QM5IN2i5fAZ4xKop47pr8rpVhiAeu+nDQa12C8+g==, - } - engines: { node: ">=6.9.0" } - peerDependencies: - "@babel/core": ^7.0.0-0 - - "@babel/runtime@7.29.2": - resolution: - { - integrity: sha512-JiDShH45zKHWyGe4ZNVRrCjBz8Nh9TMmZG1kh4QTK8hCBTWBi8Da+i7s1fJw7/lYpM4ccepSNfqzZ/QvABBi5g==, - } - engines: { node: ">=6.9.0" } - - "@babel/template@7.28.6": - resolution: - { - integrity: sha512-YA6Ma2KsCdGb+WC6UpBVFJGXL58MDA6oyONbjyF/+5sBgxY/dwkhLogbMT2GXXyU84/IhRw/2D1Os1B/giz+BQ==, - } - engines: { node: ">=6.9.0" } - - "@babel/traverse@7.29.0": - resolution: - { - integrity: sha512-4HPiQr0X7+waHfyXPZpWPfWL/J7dcN1mx9gL6WdQVMbPnF3+ZhSMs8tCxN7oHddJE9fhNE7+lxdnlyemKfJRuA==, - } - engines: { node: ">=6.9.0" } - - "@babel/types@7.29.0": - resolution: - { - integrity: sha512-LwdZHpScM4Qz8Xw2iKSzS+cfglZzJGvofQICy7W7v4caru4EaAmyUuO6BGrbyQ2mYV11W0U8j5mBhd14dd3B0A==, - } - engines: { node: ">=6.9.0" } - - "@bcoe/v8-coverage@1.0.2": - resolution: - { - integrity: sha512-6zABk/ECA/QYSCQ1NGiVwwbQerUCZ+TQbp64Q3AgmfNvurHH0j8TtXa1qbShXA6qqkpAj4V5W8pP6mLe1mcMqA==, - } - engines: { node: ">=18" } - - "@bufbuild/protobuf@1.10.1": - resolution: - { - integrity: sha512-wJ8ReQbHxsAfXhrf9ixl0aYbZorRuOWpBNzm8pL8ftmSxQx/wnJD5Eg861NwJU/czy2VXFIebCeZnZrI9rktIQ==, - } - - "@codecov/bundler-plugin-core@1.9.1": - resolution: - { - integrity: sha512-dt3ic7gMswz4p/qdkYPVJwXlLiLsz55rBBn2I7mr0HTG8pCoLRqnANJIwo5WrqGBZgPyVSMPBqBra6VxLWfDyA==, - } - engines: { node: ">=18.0.0" } - - "@codecov/vite-plugin@1.9.1": - resolution: - { - integrity: sha512-S6Yne7comVulJ1jD3T7rCfYFHPR0zUjAYoLjUDPXNJCUrdzWJdf/ak/UepE7TicqQG+yBa6eb5WusqcPgg+1AQ==, - } - engines: { node: ">=18.0.0" } + '@babel/plugin-bugfix-firefox-class-in-computed-class-key@7.28.5': + resolution: {integrity: sha512-87GDMS3tsmMSi/3bWOte1UblL+YUTFMV8SZPZ2eSEL17s74Cw/l63rR6NmGVKMYW2GYi85nE+/d6Hw5N0bEk2Q==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + + '@babel/plugin-bugfix-safari-class-field-initializer-scope@7.27.1': + resolution: {integrity: sha512-qNeq3bCKnGgLkEXUuFry6dPlGfCdQNZbn7yUAPCInwAJHMU7THJfrBSozkcWq5sNM6RcF3S8XyQL2A52KNR9IA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + + '@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@7.27.1': + resolution: {integrity: sha512-g4L7OYun04N1WyqMNjldFwlfPCLVkgB54A/YCXICZYBsvJJE3kByKv9c9+R/nAfmIfjl2rKYLNyMHboYbZaWaA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + + '@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@7.27.1': + resolution: {integrity: sha512-oO02gcONcD5O1iTLi/6frMJBIwWEHceWGSGqrpCmEL8nogiS6J9PBlE48CaK20/Jx1LuRml9aDftLgdjXT8+Cw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.13.0 + + '@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly@7.28.6': + resolution: {integrity: sha512-a0aBScVTlNaiUe35UtfxAN7A/tehvvG4/ByO6+46VPKTRSlfnAFsgKy0FUh+qAkQrDTmhDkT+IBOKlOoMUxQ0g==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + + '@babel/plugin-proposal-private-property-in-object@7.21.0-placeholder-for-preset-env.2': + resolution: {integrity: sha512-SOSkfJDddaM7mak6cPEpswyTRnuRltl429hMraQEglW+OkovnCzsiszTmsrlY//qLFjCpQDFRvjdm2wA5pPm9w==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-import-assertions@7.28.6': + resolution: {integrity: sha512-pSJUpFHdx9z5nqTSirOCMtYVP2wFgoWhP0p3g8ONK/4IHhLIBd0B9NYqAvIUAhq+OkhO4VM1tENCt0cjlsNShw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-import-attributes@7.28.6': + resolution: {integrity: sha512-jiLC0ma9XkQT3TKJ9uYvlakm66Pamywo+qwL+oL8HJOvc6TWdZXVfhqJr8CCzbSGUAbDOzlGHJC1U+vRfLQDvw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-jsx@7.28.6': + resolution: {integrity: sha512-wgEmr06G6sIpqr8YDwA2dSRTE3bJ+V0IfpzfSY3Lfgd7YWOaAdlykvJi13ZKBt8cZHfgH1IXN+CL656W3uUa4w==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-typescript@7.28.6': + resolution: {integrity: sha512-+nDNmQye7nlnuuHDboPbGm00Vqg3oO8niRRL27/4LYHUsHYh0zJ1xWOz0uRwNFmM1Avzk8wZbc6rdiYhomzv/A==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-unicode-sets-regex@7.18.6': + resolution: {integrity: sha512-727YkEAPwSIQTv5im8QHz3upqp92JTWhidIC81Tdx4VJYIte/VndKf1qKrfnnhPLiPghStWfvC/iFaMCQu7Nqg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + + '@babel/plugin-transform-arrow-functions@7.27.1': + resolution: {integrity: sha512-8Z4TGic6xW70FKThA5HYEKKyBpOOsucTOD1DjU3fZxDg+K3zBJcXMFnt/4yQiZnf5+MiOMSXQ9PaEK/Ilh1DeA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-async-generator-functions@7.29.0': + resolution: {integrity: sha512-va0VdWro4zlBr2JsXC+ofCPB2iG12wPtVGTWFx2WLDOM3nYQZZIGP82qku2eW/JR83sD+k2k+CsNtyEbUqhU6w==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-async-to-generator@7.28.6': + resolution: {integrity: sha512-ilTRcmbuXjsMmcZ3HASTe4caH5Tpo93PkTxF9oG2VZsSWsahydmcEHhix9Ik122RcTnZnUzPbmux4wh1swfv7g==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-block-scoped-functions@7.27.1': + resolution: {integrity: sha512-cnqkuOtZLapWYZUYM5rVIdv1nXYuFVIltZ6ZJ7nIj585QsjKM5dhL2Fu/lICXZ1OyIAFc7Qy+bvDAtTXqGrlhg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-block-scoping@7.28.6': + resolution: {integrity: sha512-tt/7wOtBmwHPNMPu7ax4pdPz6shjFrmHDghvNC+FG9Qvj7D6mJcoRQIF5dy4njmxR941l6rgtvfSB2zX3VlUIw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-class-properties@7.28.6': + resolution: {integrity: sha512-dY2wS3I2G7D697VHndN91TJr8/AAfXQNt5ynCTI/MpxMsSzHp+52uNivYT5wCPax3whc47DR8Ba7cmlQMg24bw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-class-static-block@7.28.6': + resolution: {integrity: sha512-rfQ++ghVwTWTqQ7w8qyDxL1XGihjBss4CmTgGRCTAC9RIbhVpyp4fOeZtta0Lbf+dTNIVJer6ych2ibHwkZqsQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.12.0 + + '@babel/plugin-transform-classes@7.28.6': + resolution: {integrity: sha512-EF5KONAqC5zAqT783iMGuM2ZtmEBy+mJMOKl2BCvPZ2lVrwvXnB6o+OBWCS+CoeCCpVRF2sA2RBKUxvT8tQT5Q==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-computed-properties@7.28.6': + resolution: {integrity: sha512-bcc3k0ijhHbc2lEfpFHgx7eYw9KNXqOerKWfzbxEHUGKnS3sz9C4CNL9OiFN1297bDNfUiSO7DaLzbvHQQQ1BQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-destructuring@7.28.5': + resolution: {integrity: sha512-Kl9Bc6D0zTUcFUvkNuQh4eGXPKKNDOJQXVyyM4ZAQPMveniJdxi8XMJwLo+xSoW3MIq81bD33lcUe9kZpl0MCw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-dotall-regex@7.28.6': + resolution: {integrity: sha512-SljjowuNKB7q5Oayv4FoPzeB74g3QgLt8IVJw9ADvWy3QnUb/01aw8I4AVv8wYnPvQz2GDDZ/g3GhcNyDBI4Bg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-duplicate-keys@7.27.1': + resolution: {integrity: sha512-MTyJk98sHvSs+cvZ4nOauwTTG1JeonDjSGvGGUNHreGQns+Mpt6WX/dVzWBHgg+dYZhkC4X+zTDfkTU+Vy9y7Q==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-duplicate-named-capturing-groups-regex@7.29.0': + resolution: {integrity: sha512-zBPcW2lFGxdiD8PUnPwJjag2J9otbcLQzvbiOzDxpYXyCuYX9agOwMPGn1prVH0a4qzhCKu24rlH4c1f7yA8rw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + + '@babel/plugin-transform-dynamic-import@7.27.1': + resolution: {integrity: sha512-MHzkWQcEmjzzVW9j2q8LGjwGWpG2mjwaaB0BNQwst3FIjqsg8Ct/mIZlvSPJvfi9y2AC8mi/ktxbFVL9pZ1I4A==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-explicit-resource-management@7.28.6': + resolution: {integrity: sha512-Iao5Konzx2b6g7EPqTy40UZbcdXE126tTxVFr/nAIj+WItNxjKSYTEw3RC+A2/ZetmdJsgueL1KhaMCQHkLPIg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-exponentiation-operator@7.28.6': + resolution: {integrity: sha512-WitabqiGjV/vJ0aPOLSFfNY1u9U3R7W36B03r5I2KoNix+a3sOhJ3pKFB3R5It9/UiK78NiO0KE9P21cMhlPkw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-export-namespace-from@7.27.1': + resolution: {integrity: sha512-tQvHWSZ3/jH2xuq/vZDy0jNn+ZdXJeM8gHvX4lnJmsc3+50yPlWdZXIc5ay+umX+2/tJIqHqiEqcJvxlmIvRvQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-for-of@7.27.1': + resolution: {integrity: sha512-BfbWFFEJFQzLCQ5N8VocnCtA8J1CLkNTe2Ms2wocj75dd6VpiqS5Z5quTYcUoo4Yq+DN0rtikODccuv7RU81sw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-function-name@7.27.1': + resolution: {integrity: sha512-1bQeydJF9Nr1eBCMMbC+hdwmRlsv5XYOMu03YSWFwNs0HsAmtSxxF1fyuYPqemVldVyFmlCU7w8UE14LupUSZQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-json-strings@7.28.6': + resolution: {integrity: sha512-Nr+hEN+0geQkzhbdgQVPoqr47lZbm+5fCUmO70722xJZd0Mvb59+33QLImGj6F+DkK3xgDi1YVysP8whD6FQAw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-literals@7.27.1': + resolution: {integrity: sha512-0HCFSepIpLTkLcsi86GG3mTUzxV5jpmbv97hTETW3yzrAij8aqlD36toB1D0daVFJM8NK6GvKO0gslVQmm+zZA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-logical-assignment-operators@7.28.6': + resolution: {integrity: sha512-+anKKair6gpi8VsM/95kmomGNMD0eLz1NQ8+Pfw5sAwWH9fGYXT50E55ZpV0pHUHWf6IUTWPM+f/7AAff+wr9A==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-member-expression-literals@7.27.1': + resolution: {integrity: sha512-hqoBX4dcZ1I33jCSWcXrP+1Ku7kdqXf1oeah7ooKOIiAdKQ+uqftgCFNOSzA5AMS2XIHEYeGFg4cKRCdpxzVOQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-modules-amd@7.27.1': + resolution: {integrity: sha512-iCsytMg/N9/oFq6n+gFTvUYDZQOMK5kEdeYxmxt91fcJGycfxVP9CnrxoliM0oumFERba2i8ZtwRUCMhvP1LnA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-modules-commonjs@7.28.6': + resolution: {integrity: sha512-jppVbf8IV9iWWwWTQIxJMAJCWBuuKx71475wHwYytrRGQ2CWiDvYlADQno3tcYpS/T2UUWFQp3nVtYfK/YBQrA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-modules-systemjs@7.29.0': + resolution: {integrity: sha512-PrujnVFbOdUpw4UHiVwKvKRLMMic8+eC0CuNlxjsyZUiBjhFdPsewdXCkveh2KqBA9/waD0W1b4hXSOBQJezpQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-modules-umd@7.27.1': + resolution: {integrity: sha512-iQBE/xC5BV1OxJbp6WG7jq9IWiD+xxlZhLrdwpPkTX3ydmXdvoCpyfJN7acaIBZaOqTfr76pgzqBJflNbeRK+w==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-named-capturing-groups-regex@7.29.0': + resolution: {integrity: sha512-1CZQA5KNAD6ZYQLPw7oi5ewtDNxH/2vuCh+6SmvgDfhumForvs8a1o9n0UrEoBD8HU4djO2yWngTQlXl1NDVEQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + + '@babel/plugin-transform-new-target@7.27.1': + resolution: {integrity: sha512-f6PiYeqXQ05lYq3TIfIDu/MtliKUbNwkGApPUvyo6+tc7uaR4cPjPe7DFPr15Uyycg2lZU6btZ575CuQoYh7MQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-nullish-coalescing-operator@7.28.6': + resolution: {integrity: sha512-3wKbRgmzYbw24mDJXT7N+ADXw8BC/imU9yo9c9X9NKaLF1fW+e5H1U5QjMUBe4Qo4Ox/o++IyUkl1sVCLgevKg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-numeric-separator@7.28.6': + resolution: {integrity: sha512-SJR8hPynj8outz+SlStQSwvziMN4+Bq99it4tMIf5/Caq+3iOc0JtKyse8puvyXkk3eFRIA5ID/XfunGgO5i6w==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-object-rest-spread@7.28.6': + resolution: {integrity: sha512-5rh+JR4JBC4pGkXLAcYdLHZjXudVxWMXbB6u6+E9lRL5TrGVbHt1TjxGbZ8CkmYw9zjkB7jutzOROArsqtncEA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-object-super@7.27.1': + resolution: {integrity: sha512-SFy8S9plRPbIcxlJ8A6mT/CxFdJx/c04JEctz4jf8YZaVS2px34j7NXRrlGlHkN/M2gnpL37ZpGRGVFLd3l8Ng==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-optional-catch-binding@7.28.6': + resolution: {integrity: sha512-R8ja/Pyrv0OGAvAXQhSTmWyPJPml+0TMqXlO5w+AsMEiwb2fg3WkOvob7UxFSL3OIttFSGSRFKQsOhJ/X6HQdQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-optional-chaining@7.28.6': + resolution: {integrity: sha512-A4zobikRGJTsX9uqVFdafzGkqD30t26ck2LmOzAuLL8b2x6k3TIqRiT2xVvA9fNmFeTX484VpsdgmKNA0bS23w==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-parameters@7.27.7': + resolution: {integrity: sha512-qBkYTYCb76RRxUM6CcZA5KRu8K4SM8ajzVeUgVdMVO9NN9uI/GaVmBg/WKJJGnNokV9SY8FxNOVWGXzqzUidBg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-private-methods@7.28.6': + resolution: {integrity: sha512-piiuapX9CRv7+0st8lmuUlRSmX6mBcVeNQ1b4AYzJxfCMuBfB0vBXDiGSmm03pKJw1v6cZ8KSeM+oUnM6yAExg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-private-property-in-object@7.28.6': + resolution: {integrity: sha512-b97jvNSOb5+ehyQmBpmhOCiUC5oVK4PMnpRvO7+ymFBoqYjeDHIU9jnrNUuwHOiL9RpGDoKBpSViarV+BU+eVA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-property-literals@7.27.1': + resolution: {integrity: sha512-oThy3BCuCha8kDZ8ZkgOg2exvPYUlprMukKQXI1r1pJ47NCvxfkEy8vK+r/hT9nF0Aa4H1WUPZZjHTFtAhGfmQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-react-display-name@7.28.0': + resolution: {integrity: sha512-D6Eujc2zMxKjfa4Zxl4GHMsmhKKZ9VpcqIchJLvwTxad9zWIYulwYItBovpDOoNLISpcZSXoDJ5gaGbQUDqViA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-react-jsx-development@7.27.1': + resolution: {integrity: sha512-ykDdF5yI4f1WrAolLqeF3hmYU12j9ntLQl/AOG1HAS21jxyg1Q0/J/tpREuYLfatGdGmXp/3yS0ZA76kOlVq9Q==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-react-jsx-self@7.27.1': + resolution: {integrity: sha512-6UzkCs+ejGdZ5mFFC/OCUrv028ab2fp1znZmCZjAOBKiBK2jXD1O+BPSfX8X2qjJ75fZBMSnQn3Rq2mrBJK2mw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-react-jsx-source@7.27.1': + resolution: {integrity: sha512-zbwoTsBruTeKB9hSq73ha66iFeJHuaFkUbwvqElnygoNbj/jHRsSeokowZFN3CZ64IvEqcmmkVe89OPXc7ldAw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-react-jsx@7.28.6': + resolution: {integrity: sha512-61bxqhiRfAACulXSLd/GxqmAedUSrRZIu/cbaT18T1CetkTmtDN15it7i80ru4DVqRK1WMxQhXs+Lf9kajm5Ow==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-react-pure-annotations@7.27.1': + resolution: {integrity: sha512-JfuinvDOsD9FVMTHpzA/pBLisxpv1aSf+OIV8lgH3MuWrks19R27e6a6DipIg4aX1Zm9Wpb04p8wljfKrVSnPA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-regenerator@7.29.0': + resolution: {integrity: sha512-FijqlqMA7DmRdg/aINBSs04y8XNTYw/lr1gJ2WsmBnnaNw1iS43EPkJW+zK7z65auG3AWRFXWj+NcTQwYptUog==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-regexp-modifiers@7.28.6': + resolution: {integrity: sha512-QGWAepm9qxpaIs7UM9FvUSnCGlb8Ua1RhyM4/veAxLwt3gMat/LSGrZixyuj4I6+Kn9iwvqCyPTtbdxanYoWYg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + + '@babel/plugin-transform-reserved-words@7.27.1': + resolution: {integrity: sha512-V2ABPHIJX4kC7HegLkYoDpfg9PVmuWy/i6vUM5eGK22bx4YVFD3M5F0QQnWQoDs6AGsUWTVOopBiMFQgHaSkVw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-shorthand-properties@7.27.1': + resolution: {integrity: sha512-N/wH1vcn4oYawbJ13Y/FxcQrWk63jhfNa7jef0ih7PHSIHX2LB7GWE1rkPrOnka9kwMxb6hMl19p7lidA+EHmQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-spread@7.28.6': + resolution: {integrity: sha512-9U4QObUC0FtJl05AsUcodau/RWDytrU6uKgkxu09mLR9HLDAtUMoPuuskm5huQsoktmsYpI+bGmq+iapDcriKA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-sticky-regex@7.27.1': + resolution: {integrity: sha512-lhInBO5bi/Kowe2/aLdBAawijx+q1pQzicSgnkB6dUPc1+RC8QmJHKf2OjvU+NZWitguJHEaEmbV6VWEouT58g==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-template-literals@7.27.1': + resolution: {integrity: sha512-fBJKiV7F2DxZUkg5EtHKXQdbsbURW3DZKQUWphDum0uRP6eHGGa/He9mc0mypL680pb+e/lDIthRohlv8NCHkg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-typeof-symbol@7.27.1': + resolution: {integrity: sha512-RiSILC+nRJM7FY5srIyc4/fGIwUhyDuuBSdWn4y6yT6gm652DpCHZjIipgn6B7MQ1ITOUnAKWixEUjQRIBIcLw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-typescript@7.28.6': + resolution: {integrity: sha512-0YWL2RFxOqEm9Efk5PvreamxPME8OyY0wM5wh5lHjF+VtVhdneCWGzZeSqzOfiobVqQaNCd2z0tQvnI9DaPWPw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-unicode-escapes@7.27.1': + resolution: {integrity: sha512-Ysg4v6AmF26k9vpfFuTZg8HRfVWzsh1kVfowA23y9j/Gu6dOuahdUVhkLqpObp3JIv27MLSii6noRnuKN8H0Mg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-unicode-property-regex@7.28.6': + resolution: {integrity: sha512-4Wlbdl/sIZjzi/8St0evF0gEZrgOswVO6aOzqxh1kDZOl9WmLrHq2HtGhnOJZmHZYKP8WZ1MDLCt5DAWwRo57A==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-unicode-regex@7.27.1': + resolution: {integrity: sha512-xvINq24TRojDuyt6JGtHmkVkrfVV3FPT16uytxImLeBZqW3/H52yN+kM1MGuyPkIQxrzKwPHs5U/MP3qKyzkGw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-unicode-sets-regex@7.28.6': + resolution: {integrity: sha512-/wHc/paTUmsDYN7SZkpWxogTOBNnlx7nBQYfy6JJlCT7G3mVhltk3e++N7zV0XfgGsrqBxd4rJQt9H16I21Y1Q==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + + '@babel/preset-env@7.29.2': + resolution: {integrity: sha512-DYD23veRYGvBFhcTY1iUvJnDNpuqNd/BzBwCvzOTKUnJjKg5kpUBh3/u9585Agdkgj+QuygG7jLfOPWMa2KVNw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/preset-modules@0.1.6-no-external-plugins': + resolution: {integrity: sha512-HrcgcIESLm9aIR842yhJ5RWan/gebQUJ6E/E5+rf0y9o6oj7w0Br+sWuL6kEQ/o/AdfvR1Je9jG18/gnpwjEyA==} + peerDependencies: + '@babel/core': ^7.0.0-0 || ^8.0.0-0 <8.0.0 + + '@babel/preset-react@7.28.5': + resolution: {integrity: sha512-Z3J8vhRq7CeLjdC58jLv4lnZ5RKFUJWqH5emvxmv9Hv3BD1T9R/Im713R4MTKwvFaV74ejZ3sM01LyEKk4ugNQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/preset-typescript@7.28.5': + resolution: {integrity: sha512-+bQy5WOI2V6LJZpPVxY+yp66XdZ2yifu0Mc1aP5CQKgjn4QM5IN2i5fAZ4xKop47pr8rpVhiAeu+nDQa12C8+g==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/runtime@7.29.2': + resolution: {integrity: sha512-JiDShH45zKHWyGe4ZNVRrCjBz8Nh9TMmZG1kh4QTK8hCBTWBi8Da+i7s1fJw7/lYpM4ccepSNfqzZ/QvABBi5g==} + engines: {node: '>=6.9.0'} + + '@babel/template@7.28.6': + resolution: {integrity: sha512-YA6Ma2KsCdGb+WC6UpBVFJGXL58MDA6oyONbjyF/+5sBgxY/dwkhLogbMT2GXXyU84/IhRw/2D1Os1B/giz+BQ==} + engines: {node: '>=6.9.0'} + + '@babel/traverse@7.29.0': + resolution: {integrity: sha512-4HPiQr0X7+waHfyXPZpWPfWL/J7dcN1mx9gL6WdQVMbPnF3+ZhSMs8tCxN7oHddJE9fhNE7+lxdnlyemKfJRuA==} + engines: {node: '>=6.9.0'} + + '@babel/types@7.29.0': + resolution: {integrity: sha512-LwdZHpScM4Qz8Xw2iKSzS+cfglZzJGvofQICy7W7v4caru4EaAmyUuO6BGrbyQ2mYV11W0U8j5mBhd14dd3B0A==} + engines: {node: '>=6.9.0'} + + '@bcoe/v8-coverage@1.0.2': + resolution: {integrity: sha512-6zABk/ECA/QYSCQ1NGiVwwbQerUCZ+TQbp64Q3AgmfNvurHH0j8TtXa1qbShXA6qqkpAj4V5W8pP6mLe1mcMqA==} + engines: {node: '>=18'} + + '@bufbuild/protobuf@1.10.1': + resolution: {integrity: sha512-wJ8ReQbHxsAfXhrf9ixl0aYbZorRuOWpBNzm8pL8ftmSxQx/wnJD5Eg861NwJU/czy2VXFIebCeZnZrI9rktIQ==} + + '@codecov/bundler-plugin-core@1.9.1': + resolution: {integrity: sha512-dt3ic7gMswz4p/qdkYPVJwXlLiLsz55rBBn2I7mr0HTG8pCoLRqnANJIwo5WrqGBZgPyVSMPBqBra6VxLWfDyA==} + engines: {node: '>=18.0.0'} + + '@codecov/vite-plugin@1.9.1': + resolution: {integrity: sha512-S6Yne7comVulJ1jD3T7rCfYFHPR0zUjAYoLjUDPXNJCUrdzWJdf/ak/UepE7TicqQG+yBa6eb5WusqcPgg+1AQ==} + engines: {node: '>=18.0.0'} peerDependencies: vite: 4.x || 5.x || 6.x - "@csstools/cascade-layer-name-parser@2.0.5": - resolution: - { - integrity: sha512-p1ko5eHgV+MgXFVa4STPKpvPxr6ReS8oS2jzTukjR74i5zJNyWO1ZM1m8YKBXnzDKWfBN1ztLYlHxbVemDD88A==, - } - engines: { node: ">=18" } + '@csstools/cascade-layer-name-parser@2.0.5': + resolution: {integrity: sha512-p1ko5eHgV+MgXFVa4STPKpvPxr6ReS8oS2jzTukjR74i5zJNyWO1ZM1m8YKBXnzDKWfBN1ztLYlHxbVemDD88A==} + engines: {node: '>=18'} peerDependencies: - "@csstools/css-parser-algorithms": ^3.0.5 - "@csstools/css-tokenizer": ^3.0.4 + '@csstools/css-parser-algorithms': ^3.0.5 + '@csstools/css-tokenizer': ^3.0.4 - "@csstools/color-helpers@5.1.0": - resolution: - { - integrity: sha512-S11EXWJyy0Mz5SYvRmY8nJYTFFd1LCNV+7cXyAgQtOOuzb4EsgfqDufL+9esx72/eLhsRdGZwaldu/h+E4t4BA==, - } - engines: { node: ">=18" } + '@csstools/color-helpers@5.1.0': + resolution: {integrity: sha512-S11EXWJyy0Mz5SYvRmY8nJYTFFd1LCNV+7cXyAgQtOOuzb4EsgfqDufL+9esx72/eLhsRdGZwaldu/h+E4t4BA==} + engines: {node: '>=18'} - "@csstools/css-calc@2.1.4": - resolution: - { - integrity: sha512-3N8oaj+0juUw/1H3YwmDDJXCgTB1gKU6Hc/bB502u9zR0q2vd786XJH9QfrKIEgFlZmhZiq6epXl4rHqhzsIgQ==, - } - engines: { node: ">=18" } + '@csstools/css-calc@2.1.4': + resolution: {integrity: sha512-3N8oaj+0juUw/1H3YwmDDJXCgTB1gKU6Hc/bB502u9zR0q2vd786XJH9QfrKIEgFlZmhZiq6epXl4rHqhzsIgQ==} + engines: {node: '>=18'} peerDependencies: - "@csstools/css-parser-algorithms": ^3.0.5 - "@csstools/css-tokenizer": ^3.0.4 + '@csstools/css-parser-algorithms': ^3.0.5 + '@csstools/css-tokenizer': ^3.0.4 - "@csstools/css-color-parser@3.1.0": - resolution: - { - integrity: sha512-nbtKwh3a6xNVIp/VRuXV64yTKnb1IjTAEEh3irzS+HkKjAOYLTGNb9pmVNntZ8iVBHcWDA2Dof0QtPgFI1BaTA==, - } - engines: { node: ">=18" } + '@csstools/css-color-parser@3.1.0': + resolution: {integrity: sha512-nbtKwh3a6xNVIp/VRuXV64yTKnb1IjTAEEh3irzS+HkKjAOYLTGNb9pmVNntZ8iVBHcWDA2Dof0QtPgFI1BaTA==} + engines: {node: '>=18'} peerDependencies: - "@csstools/css-parser-algorithms": ^3.0.5 - "@csstools/css-tokenizer": ^3.0.4 + '@csstools/css-parser-algorithms': ^3.0.5 + '@csstools/css-tokenizer': ^3.0.4 - "@csstools/css-parser-algorithms@3.0.5": - resolution: - { - integrity: sha512-DaDeUkXZKjdGhgYaHNJTV9pV7Y9B3b644jCLs9Upc3VeNGg6LWARAT6O+Q+/COo+2gg/bM5rhpMAtf70WqfBdQ==, - } - engines: { node: ">=18" } + '@csstools/css-parser-algorithms@3.0.5': + resolution: {integrity: sha512-DaDeUkXZKjdGhgYaHNJTV9pV7Y9B3b644jCLs9Upc3VeNGg6LWARAT6O+Q+/COo+2gg/bM5rhpMAtf70WqfBdQ==} + engines: {node: '>=18'} peerDependencies: - "@csstools/css-tokenizer": ^3.0.4 + '@csstools/css-tokenizer': ^3.0.4 - "@csstools/css-tokenizer@3.0.4": - resolution: - { - integrity: sha512-Vd/9EVDiu6PPJt9yAh6roZP6El1xHrdvIVGjyBsHR0RYwNHgL7FJPyIIW4fANJNG6FtyZfvlRPpFI4ZM/lubvw==, - } - engines: { node: ">=18" } + '@csstools/css-tokenizer@3.0.4': + resolution: {integrity: sha512-Vd/9EVDiu6PPJt9yAh6roZP6El1xHrdvIVGjyBsHR0RYwNHgL7FJPyIIW4fANJNG6FtyZfvlRPpFI4ZM/lubvw==} + engines: {node: '>=18'} - "@csstools/media-query-list-parser@4.0.3": - resolution: - { - integrity: sha512-HAYH7d3TLRHDOUQK4mZKf9k9Ph/m8Akstg66ywKR4SFAigjs3yBiUeZtFxywiTm5moZMAp/5W/ZuFnNXXYLuuQ==, - } - engines: { node: ">=18" } + '@csstools/media-query-list-parser@4.0.3': + resolution: {integrity: sha512-HAYH7d3TLRHDOUQK4mZKf9k9Ph/m8Akstg66ywKR4SFAigjs3yBiUeZtFxywiTm5moZMAp/5W/ZuFnNXXYLuuQ==} + engines: {node: '>=18'} peerDependencies: - "@csstools/css-parser-algorithms": ^3.0.5 - "@csstools/css-tokenizer": ^3.0.4 + '@csstools/css-parser-algorithms': ^3.0.5 + '@csstools/css-tokenizer': ^3.0.4 - "@csstools/postcss-alpha-function@1.0.1": - resolution: - { - integrity: sha512-isfLLwksH3yHkFXfCI2Gcaqg7wGGHZZwunoJzEZk0yKYIokgre6hYVFibKL3SYAoR1kBXova8LB+JoO5vZzi9w==, - } - engines: { node: ">=18" } + '@csstools/postcss-alpha-function@1.0.1': + resolution: {integrity: sha512-isfLLwksH3yHkFXfCI2Gcaqg7wGGHZZwunoJzEZk0yKYIokgre6hYVFibKL3SYAoR1kBXova8LB+JoO5vZzi9w==} + engines: {node: '>=18'} peerDependencies: postcss: ^8.4 - "@csstools/postcss-cascade-layers@5.0.2": - resolution: - { - integrity: sha512-nWBE08nhO8uWl6kSAeCx4im7QfVko3zLrtgWZY4/bP87zrSPpSyN/3W3TDqz1jJuH+kbKOHXg5rJnK+ZVYcFFg==, - } - engines: { node: ">=18" } + '@csstools/postcss-cascade-layers@5.0.2': + resolution: {integrity: sha512-nWBE08nhO8uWl6kSAeCx4im7QfVko3zLrtgWZY4/bP87zrSPpSyN/3W3TDqz1jJuH+kbKOHXg5rJnK+ZVYcFFg==} + engines: {node: '>=18'} peerDependencies: postcss: ^8.4 - "@csstools/postcss-color-function-display-p3-linear@1.0.1": - resolution: - { - integrity: sha512-E5qusdzhlmO1TztYzDIi8XPdPoYOjoTY6HBYBCYSj+Gn4gQRBlvjgPQXzfzuPQqt8EhkC/SzPKObg4Mbn8/xMg==, - } - engines: { node: ">=18" } + '@csstools/postcss-color-function-display-p3-linear@1.0.1': + resolution: {integrity: sha512-E5qusdzhlmO1TztYzDIi8XPdPoYOjoTY6HBYBCYSj+Gn4gQRBlvjgPQXzfzuPQqt8EhkC/SzPKObg4Mbn8/xMg==} + engines: {node: '>=18'} peerDependencies: postcss: ^8.4 - "@csstools/postcss-color-function@4.0.12": - resolution: - { - integrity: sha512-yx3cljQKRaSBc2hfh8rMZFZzChaFgwmO2JfFgFr1vMcF3C/uyy5I4RFIBOIWGq1D+XbKCG789CGkG6zzkLpagA==, - } - engines: { node: ">=18" } + '@csstools/postcss-color-function@4.0.12': + resolution: {integrity: sha512-yx3cljQKRaSBc2hfh8rMZFZzChaFgwmO2JfFgFr1vMcF3C/uyy5I4RFIBOIWGq1D+XbKCG789CGkG6zzkLpagA==} + engines: {node: '>=18'} peerDependencies: postcss: ^8.4 - "@csstools/postcss-color-mix-function@3.0.12": - resolution: - { - integrity: sha512-4STERZfCP5Jcs13P1U5pTvI9SkgLgfMUMhdXW8IlJWkzOOOqhZIjcNhWtNJZes2nkBDsIKJ0CJtFtuaZ00moag==, - } - engines: { node: ">=18" } + '@csstools/postcss-color-mix-function@3.0.12': + resolution: {integrity: sha512-4STERZfCP5Jcs13P1U5pTvI9SkgLgfMUMhdXW8IlJWkzOOOqhZIjcNhWtNJZes2nkBDsIKJ0CJtFtuaZ00moag==} + engines: {node: '>=18'} peerDependencies: postcss: ^8.4 - "@csstools/postcss-color-mix-variadic-function-arguments@1.0.2": - resolution: - { - integrity: sha512-rM67Gp9lRAkTo+X31DUqMEq+iK+EFqsidfecmhrteErxJZb6tUoJBVQca1Vn1GpDql1s1rD1pKcuYzMsg7Z1KQ==, - } - engines: { node: ">=18" } + '@csstools/postcss-color-mix-variadic-function-arguments@1.0.2': + resolution: {integrity: sha512-rM67Gp9lRAkTo+X31DUqMEq+iK+EFqsidfecmhrteErxJZb6tUoJBVQca1Vn1GpDql1s1rD1pKcuYzMsg7Z1KQ==} + engines: {node: '>=18'} peerDependencies: postcss: ^8.4 - "@csstools/postcss-content-alt-text@2.0.8": - resolution: - { - integrity: sha512-9SfEW9QCxEpTlNMnpSqFaHyzsiRpZ5J5+KqCu1u5/eEJAWsMhzT40qf0FIbeeglEvrGRMdDzAxMIz3wqoGSb+Q==, - } - engines: { node: ">=18" } + '@csstools/postcss-content-alt-text@2.0.8': + resolution: {integrity: sha512-9SfEW9QCxEpTlNMnpSqFaHyzsiRpZ5J5+KqCu1u5/eEJAWsMhzT40qf0FIbeeglEvrGRMdDzAxMIz3wqoGSb+Q==} + engines: {node: '>=18'} peerDependencies: postcss: ^8.4 - "@csstools/postcss-contrast-color-function@2.0.12": - resolution: - { - integrity: sha512-YbwWckjK3qwKjeYz/CijgcS7WDUCtKTd8ShLztm3/i5dhh4NaqzsbYnhm4bjrpFpnLZ31jVcbK8YL77z3GBPzA==, - } - engines: { node: ">=18" } + '@csstools/postcss-contrast-color-function@2.0.12': + resolution: {integrity: sha512-YbwWckjK3qwKjeYz/CijgcS7WDUCtKTd8ShLztm3/i5dhh4NaqzsbYnhm4bjrpFpnLZ31jVcbK8YL77z3GBPzA==} + engines: {node: '>=18'} peerDependencies: postcss: ^8.4 - "@csstools/postcss-exponential-functions@2.0.9": - resolution: - { - integrity: sha512-abg2W/PI3HXwS/CZshSa79kNWNZHdJPMBXeZNyPQFbbj8sKO3jXxOt/wF7juJVjyDTc6JrvaUZYFcSBZBhaxjw==, - } - engines: { node: ">=18" } + '@csstools/postcss-exponential-functions@2.0.9': + resolution: {integrity: sha512-abg2W/PI3HXwS/CZshSa79kNWNZHdJPMBXeZNyPQFbbj8sKO3jXxOt/wF7juJVjyDTc6JrvaUZYFcSBZBhaxjw==} + engines: {node: '>=18'} peerDependencies: postcss: ^8.4 - "@csstools/postcss-font-format-keywords@4.0.0": - resolution: - { - integrity: sha512-usBzw9aCRDvchpok6C+4TXC57btc4bJtmKQWOHQxOVKen1ZfVqBUuCZ/wuqdX5GHsD0NRSr9XTP+5ID1ZZQBXw==, - } - engines: { node: ">=18" } + '@csstools/postcss-font-format-keywords@4.0.0': + resolution: {integrity: sha512-usBzw9aCRDvchpok6C+4TXC57btc4bJtmKQWOHQxOVKen1ZfVqBUuCZ/wuqdX5GHsD0NRSr9XTP+5ID1ZZQBXw==} + engines: {node: '>=18'} peerDependencies: postcss: ^8.4 - "@csstools/postcss-gamut-mapping@2.0.11": - resolution: - { - integrity: sha512-fCpCUgZNE2piVJKC76zFsgVW1apF6dpYsqGyH8SIeCcM4pTEsRTWTLCaJIMKFEundsCKwY1rwfhtrio04RJ4Dw==, - } - engines: { node: ">=18" } + '@csstools/postcss-gamut-mapping@2.0.11': + resolution: {integrity: sha512-fCpCUgZNE2piVJKC76zFsgVW1apF6dpYsqGyH8SIeCcM4pTEsRTWTLCaJIMKFEundsCKwY1rwfhtrio04RJ4Dw==} + engines: {node: '>=18'} peerDependencies: postcss: ^8.4 - "@csstools/postcss-gradients-interpolation-method@5.0.12": - resolution: - { - integrity: sha512-jugzjwkUY0wtNrZlFeyXzimUL3hN4xMvoPnIXxoZqxDvjZRiSh+itgHcVUWzJ2VwD/VAMEgCLvtaJHX+4Vj3Ow==, - } - engines: { node: ">=18" } + '@csstools/postcss-gradients-interpolation-method@5.0.12': + resolution: {integrity: sha512-jugzjwkUY0wtNrZlFeyXzimUL3hN4xMvoPnIXxoZqxDvjZRiSh+itgHcVUWzJ2VwD/VAMEgCLvtaJHX+4Vj3Ow==} + engines: {node: '>=18'} peerDependencies: postcss: ^8.4 - "@csstools/postcss-hwb-function@4.0.12": - resolution: - { - integrity: sha512-mL/+88Z53KrE4JdePYFJAQWFrcADEqsLprExCM04GDNgHIztwFzj0Mbhd/yxMBngq0NIlz58VVxjt5abNs1VhA==, - } - engines: { node: ">=18" } + '@csstools/postcss-hwb-function@4.0.12': + resolution: {integrity: sha512-mL/+88Z53KrE4JdePYFJAQWFrcADEqsLprExCM04GDNgHIztwFzj0Mbhd/yxMBngq0NIlz58VVxjt5abNs1VhA==} + engines: {node: '>=18'} peerDependencies: postcss: ^8.4 - "@csstools/postcss-ic-unit@4.0.4": - resolution: - { - integrity: sha512-yQ4VmossuOAql65sCPppVO1yfb7hDscf4GseF0VCA/DTDaBc0Wtf8MTqVPfjGYlT5+2buokG0Gp7y0atYZpwjg==, - } - engines: { node: ">=18" } + '@csstools/postcss-ic-unit@4.0.4': + resolution: {integrity: sha512-yQ4VmossuOAql65sCPppVO1yfb7hDscf4GseF0VCA/DTDaBc0Wtf8MTqVPfjGYlT5+2buokG0Gp7y0atYZpwjg==} + engines: {node: '>=18'} peerDependencies: postcss: ^8.4 - "@csstools/postcss-initial@2.0.1": - resolution: - { - integrity: sha512-L1wLVMSAZ4wovznquK0xmC7QSctzO4D0Is590bxpGqhqjboLXYA16dWZpfwImkdOgACdQ9PqXsuRroW6qPlEsg==, - } - engines: { node: ">=18" } + '@csstools/postcss-initial@2.0.1': + resolution: {integrity: sha512-L1wLVMSAZ4wovznquK0xmC7QSctzO4D0Is590bxpGqhqjboLXYA16dWZpfwImkdOgACdQ9PqXsuRroW6qPlEsg==} + engines: {node: '>=18'} peerDependencies: postcss: ^8.4 - "@csstools/postcss-is-pseudo-class@5.0.3": - resolution: - { - integrity: sha512-jS/TY4SpG4gszAtIg7Qnf3AS2pjcUM5SzxpApOrlndMeGhIbaTzWBzzP/IApXoNWEW7OhcjkRT48jnAUIFXhAQ==, - } - engines: { node: ">=18" } + '@csstools/postcss-is-pseudo-class@5.0.3': + resolution: {integrity: sha512-jS/TY4SpG4gszAtIg7Qnf3AS2pjcUM5SzxpApOrlndMeGhIbaTzWBzzP/IApXoNWEW7OhcjkRT48jnAUIFXhAQ==} + engines: {node: '>=18'} peerDependencies: postcss: ^8.4 - "@csstools/postcss-light-dark-function@2.0.11": - resolution: - { - integrity: sha512-fNJcKXJdPM3Lyrbmgw2OBbaioU7yuKZtiXClf4sGdQttitijYlZMD5K7HrC/eF83VRWRrYq6OZ0Lx92leV2LFA==, - } - engines: { node: ">=18" } + '@csstools/postcss-light-dark-function@2.0.11': + resolution: {integrity: sha512-fNJcKXJdPM3Lyrbmgw2OBbaioU7yuKZtiXClf4sGdQttitijYlZMD5K7HrC/eF83VRWRrYq6OZ0Lx92leV2LFA==} + engines: {node: '>=18'} peerDependencies: postcss: ^8.4 - "@csstools/postcss-logical-float-and-clear@3.0.0": - resolution: - { - integrity: sha512-SEmaHMszwakI2rqKRJgE+8rpotFfne1ZS6bZqBoQIicFyV+xT1UF42eORPxJkVJVrH9C0ctUgwMSn3BLOIZldQ==, - } - engines: { node: ">=18" } + '@csstools/postcss-logical-float-and-clear@3.0.0': + resolution: {integrity: sha512-SEmaHMszwakI2rqKRJgE+8rpotFfne1ZS6bZqBoQIicFyV+xT1UF42eORPxJkVJVrH9C0ctUgwMSn3BLOIZldQ==} + engines: {node: '>=18'} peerDependencies: postcss: ^8.4 - "@csstools/postcss-logical-overflow@2.0.0": - resolution: - { - integrity: sha512-spzR1MInxPuXKEX2csMamshR4LRaSZ3UXVaRGjeQxl70ySxOhMpP2252RAFsg8QyyBXBzuVOOdx1+bVO5bPIzA==, - } - engines: { node: ">=18" } + '@csstools/postcss-logical-overflow@2.0.0': + resolution: {integrity: sha512-spzR1MInxPuXKEX2csMamshR4LRaSZ3UXVaRGjeQxl70ySxOhMpP2252RAFsg8QyyBXBzuVOOdx1+bVO5bPIzA==} + engines: {node: '>=18'} peerDependencies: postcss: ^8.4 - "@csstools/postcss-logical-overscroll-behavior@2.0.0": - resolution: - { - integrity: sha512-e/webMjoGOSYfqLunyzByZj5KKe5oyVg/YSbie99VEaSDE2kimFm0q1f6t/6Jo+VVCQ/jbe2Xy+uX+C4xzWs4w==, - } - engines: { node: ">=18" } + '@csstools/postcss-logical-overscroll-behavior@2.0.0': + resolution: {integrity: sha512-e/webMjoGOSYfqLunyzByZj5KKe5oyVg/YSbie99VEaSDE2kimFm0q1f6t/6Jo+VVCQ/jbe2Xy+uX+C4xzWs4w==} + engines: {node: '>=18'} peerDependencies: postcss: ^8.4 - "@csstools/postcss-logical-resize@3.0.0": - resolution: - { - integrity: sha512-DFbHQOFW/+I+MY4Ycd/QN6Dg4Hcbb50elIJCfnwkRTCX05G11SwViI5BbBlg9iHRl4ytB7pmY5ieAFk3ws7yyg==, - } - engines: { node: ">=18" } + '@csstools/postcss-logical-resize@3.0.0': + resolution: {integrity: sha512-DFbHQOFW/+I+MY4Ycd/QN6Dg4Hcbb50elIJCfnwkRTCX05G11SwViI5BbBlg9iHRl4ytB7pmY5ieAFk3ws7yyg==} + engines: {node: '>=18'} peerDependencies: postcss: ^8.4 - "@csstools/postcss-logical-viewport-units@3.0.4": - resolution: - { - integrity: sha512-q+eHV1haXA4w9xBwZLKjVKAWn3W2CMqmpNpZUk5kRprvSiBEGMgrNH3/sJZ8UA3JgyHaOt3jwT9uFa4wLX4EqQ==, - } - engines: { node: ">=18" } + '@csstools/postcss-logical-viewport-units@3.0.4': + resolution: {integrity: sha512-q+eHV1haXA4w9xBwZLKjVKAWn3W2CMqmpNpZUk5kRprvSiBEGMgrNH3/sJZ8UA3JgyHaOt3jwT9uFa4wLX4EqQ==} + engines: {node: '>=18'} peerDependencies: postcss: ^8.4 - "@csstools/postcss-media-minmax@2.0.9": - resolution: - { - integrity: sha512-af9Qw3uS3JhYLnCbqtZ9crTvvkR+0Se+bBqSr7ykAnl9yKhk6895z9rf+2F4dClIDJWxgn0iZZ1PSdkhrbs2ig==, - } - engines: { node: ">=18" } + '@csstools/postcss-media-minmax@2.0.9': + resolution: {integrity: sha512-af9Qw3uS3JhYLnCbqtZ9crTvvkR+0Se+bBqSr7ykAnl9yKhk6895z9rf+2F4dClIDJWxgn0iZZ1PSdkhrbs2ig==} + engines: {node: '>=18'} peerDependencies: postcss: ^8.4 - "@csstools/postcss-media-queries-aspect-ratio-number-values@3.0.5": - resolution: - { - integrity: sha512-zhAe31xaaXOY2Px8IYfoVTB3wglbJUVigGphFLj6exb7cjZRH9A6adyE22XfFK3P2PzwRk0VDeTJmaxpluyrDg==, - } - engines: { node: ">=18" } + '@csstools/postcss-media-queries-aspect-ratio-number-values@3.0.5': + resolution: {integrity: sha512-zhAe31xaaXOY2Px8IYfoVTB3wglbJUVigGphFLj6exb7cjZRH9A6adyE22XfFK3P2PzwRk0VDeTJmaxpluyrDg==} + engines: {node: '>=18'} peerDependencies: postcss: ^8.4 - "@csstools/postcss-nested-calc@4.0.0": - resolution: - { - integrity: sha512-jMYDdqrQQxE7k9+KjstC3NbsmC063n1FTPLCgCRS2/qHUbHM0mNy9pIn4QIiQGs9I/Bg98vMqw7mJXBxa0N88A==, - } - engines: { node: ">=18" } + '@csstools/postcss-nested-calc@4.0.0': + resolution: {integrity: sha512-jMYDdqrQQxE7k9+KjstC3NbsmC063n1FTPLCgCRS2/qHUbHM0mNy9pIn4QIiQGs9I/Bg98vMqw7mJXBxa0N88A==} + engines: {node: '>=18'} peerDependencies: postcss: ^8.4 - "@csstools/postcss-normalize-display-values@4.0.1": - resolution: - { - integrity: sha512-TQUGBuRvxdc7TgNSTevYqrL8oItxiwPDixk20qCB5me/W8uF7BPbhRrAvFuhEoywQp/woRsUZ6SJ+sU5idZAIA==, - } - engines: { node: ">=18" } + '@csstools/postcss-normalize-display-values@4.0.1': + resolution: {integrity: sha512-TQUGBuRvxdc7TgNSTevYqrL8oItxiwPDixk20qCB5me/W8uF7BPbhRrAvFuhEoywQp/woRsUZ6SJ+sU5idZAIA==} + engines: {node: '>=18'} peerDependencies: postcss: ^8.4 - "@csstools/postcss-oklab-function@4.0.12": - resolution: - { - integrity: sha512-HhlSmnE1NKBhXsTnNGjxvhryKtO7tJd1w42DKOGFD6jSHtYOrsJTQDKPMwvOfrzUAk8t7GcpIfRyM7ssqHpFjg==, - } - engines: { node: ">=18" } + '@csstools/postcss-oklab-function@4.0.12': + resolution: {integrity: sha512-HhlSmnE1NKBhXsTnNGjxvhryKtO7tJd1w42DKOGFD6jSHtYOrsJTQDKPMwvOfrzUAk8t7GcpIfRyM7ssqHpFjg==} + engines: {node: '>=18'} peerDependencies: postcss: ^8.4 - "@csstools/postcss-position-area-property@1.0.0": - resolution: - { - integrity: sha512-fUP6KR8qV2NuUZV3Cw8itx0Ep90aRjAZxAEzC3vrl6yjFv+pFsQbR18UuQctEKmA72K9O27CoYiKEgXxkqjg8Q==, - } - engines: { node: ">=18" } + '@csstools/postcss-position-area-property@1.0.0': + resolution: {integrity: sha512-fUP6KR8qV2NuUZV3Cw8itx0Ep90aRjAZxAEzC3vrl6yjFv+pFsQbR18UuQctEKmA72K9O27CoYiKEgXxkqjg8Q==} + engines: {node: '>=18'} peerDependencies: postcss: ^8.4 - "@csstools/postcss-progressive-custom-properties@4.2.1": - resolution: - { - integrity: sha512-uPiiXf7IEKtUQXsxu6uWtOlRMXd2QWWy5fhxHDnPdXKCQckPP3E34ZgDoZ62r2iT+UOgWsSbM4NvHE5m3mAEdw==, - } - engines: { node: ">=18" } + '@csstools/postcss-progressive-custom-properties@4.2.1': + resolution: {integrity: sha512-uPiiXf7IEKtUQXsxu6uWtOlRMXd2QWWy5fhxHDnPdXKCQckPP3E34ZgDoZ62r2iT+UOgWsSbM4NvHE5m3mAEdw==} + engines: {node: '>=18'} peerDependencies: postcss: ^8.4 - "@csstools/postcss-property-rule-prelude-list@1.0.0": - resolution: - { - integrity: sha512-IxuQjUXq19fobgmSSvUDO7fVwijDJaZMvWQugxfEUxmjBeDCVaDuMpsZ31MsTm5xbnhA+ElDi0+rQ7sQQGisFA==, - } - engines: { node: ">=18" } + '@csstools/postcss-property-rule-prelude-list@1.0.0': + resolution: {integrity: sha512-IxuQjUXq19fobgmSSvUDO7fVwijDJaZMvWQugxfEUxmjBeDCVaDuMpsZ31MsTm5xbnhA+ElDi0+rQ7sQQGisFA==} + engines: {node: '>=18'} peerDependencies: postcss: ^8.4 - "@csstools/postcss-random-function@2.0.1": - resolution: - { - integrity: sha512-q+FQaNiRBhnoSNo+GzqGOIBKoHQ43lYz0ICrV+UudfWnEF6ksS6DsBIJSISKQT2Bvu3g4k6r7t0zYrk5pDlo8w==, - } - engines: { node: ">=18" } + '@csstools/postcss-random-function@2.0.1': + resolution: {integrity: sha512-q+FQaNiRBhnoSNo+GzqGOIBKoHQ43lYz0ICrV+UudfWnEF6ksS6DsBIJSISKQT2Bvu3g4k6r7t0zYrk5pDlo8w==} + engines: {node: '>=18'} peerDependencies: postcss: ^8.4 - "@csstools/postcss-relative-color-syntax@3.0.12": - resolution: - { - integrity: sha512-0RLIeONxu/mtxRtf3o41Lq2ghLimw0w9ByLWnnEVuy89exmEEq8bynveBxNW3nyHqLAFEeNtVEmC1QK9MZ8Huw==, - } - engines: { node: ">=18" } + '@csstools/postcss-relative-color-syntax@3.0.12': + resolution: {integrity: sha512-0RLIeONxu/mtxRtf3o41Lq2ghLimw0w9ByLWnnEVuy89exmEEq8bynveBxNW3nyHqLAFEeNtVEmC1QK9MZ8Huw==} + engines: {node: '>=18'} peerDependencies: postcss: ^8.4 - "@csstools/postcss-scope-pseudo-class@4.0.1": - resolution: - { - integrity: sha512-IMi9FwtH6LMNuLea1bjVMQAsUhFxJnyLSgOp/cpv5hrzWmrUYU5fm0EguNDIIOHUqzXode8F/1qkC/tEo/qN8Q==, - } - engines: { node: ">=18" } + '@csstools/postcss-scope-pseudo-class@4.0.1': + resolution: {integrity: sha512-IMi9FwtH6LMNuLea1bjVMQAsUhFxJnyLSgOp/cpv5hrzWmrUYU5fm0EguNDIIOHUqzXode8F/1qkC/tEo/qN8Q==} + engines: {node: '>=18'} peerDependencies: postcss: ^8.4 - "@csstools/postcss-sign-functions@1.1.4": - resolution: - { - integrity: sha512-P97h1XqRPcfcJndFdG95Gv/6ZzxUBBISem0IDqPZ7WMvc/wlO+yU0c5D/OCpZ5TJoTt63Ok3knGk64N+o6L2Pg==, - } - engines: { node: ">=18" } + '@csstools/postcss-sign-functions@1.1.4': + resolution: {integrity: sha512-P97h1XqRPcfcJndFdG95Gv/6ZzxUBBISem0IDqPZ7WMvc/wlO+yU0c5D/OCpZ5TJoTt63Ok3knGk64N+o6L2Pg==} + engines: {node: '>=18'} peerDependencies: postcss: ^8.4 - "@csstools/postcss-stepped-value-functions@4.0.9": - resolution: - { - integrity: sha512-h9btycWrsex4dNLeQfyU3y3w40LMQooJWFMm/SK9lrKguHDcFl4VMkncKKoXi2z5rM9YGWbUQABI8BT2UydIcA==, - } - engines: { node: ">=18" } + '@csstools/postcss-stepped-value-functions@4.0.9': + resolution: {integrity: sha512-h9btycWrsex4dNLeQfyU3y3w40LMQooJWFMm/SK9lrKguHDcFl4VMkncKKoXi2z5rM9YGWbUQABI8BT2UydIcA==} + engines: {node: '>=18'} peerDependencies: postcss: ^8.4 - "@csstools/postcss-syntax-descriptor-syntax-production@1.0.1": - resolution: - { - integrity: sha512-GneqQWefjM//f4hJ/Kbox0C6f2T7+pi4/fqTqOFGTL3EjnvOReTqO1qUQ30CaUjkwjYq9qZ41hzarrAxCc4gow==, - } - engines: { node: ">=18" } + '@csstools/postcss-syntax-descriptor-syntax-production@1.0.1': + resolution: {integrity: sha512-GneqQWefjM//f4hJ/Kbox0C6f2T7+pi4/fqTqOFGTL3EjnvOReTqO1qUQ30CaUjkwjYq9qZ41hzarrAxCc4gow==} + engines: {node: '>=18'} peerDependencies: postcss: ^8.4 - "@csstools/postcss-system-ui-font-family@1.0.0": - resolution: - { - integrity: sha512-s3xdBvfWYfoPSBsikDXbuorcMG1nN1M6GdU0qBsGfcmNR0A/qhloQZpTxjA3Xsyrk1VJvwb2pOfiOT3at/DuIQ==, - } - engines: { node: ">=18" } + '@csstools/postcss-system-ui-font-family@1.0.0': + resolution: {integrity: sha512-s3xdBvfWYfoPSBsikDXbuorcMG1nN1M6GdU0qBsGfcmNR0A/qhloQZpTxjA3Xsyrk1VJvwb2pOfiOT3at/DuIQ==} + engines: {node: '>=18'} peerDependencies: postcss: ^8.4 - "@csstools/postcss-text-decoration-shorthand@4.0.3": - resolution: - { - integrity: sha512-KSkGgZfx0kQjRIYnpsD7X2Om9BUXX/Kii77VBifQW9Ih929hK0KNjVngHDH0bFB9GmfWcR9vJYJJRvw/NQjkrA==, - } - engines: { node: ">=18" } + '@csstools/postcss-text-decoration-shorthand@4.0.3': + resolution: {integrity: sha512-KSkGgZfx0kQjRIYnpsD7X2Om9BUXX/Kii77VBifQW9Ih929hK0KNjVngHDH0bFB9GmfWcR9vJYJJRvw/NQjkrA==} + engines: {node: '>=18'} peerDependencies: postcss: ^8.4 - "@csstools/postcss-trigonometric-functions@4.0.9": - resolution: - { - integrity: sha512-Hnh5zJUdpNrJqK9v1/E3BbrQhaDTj5YiX7P61TOvUhoDHnUmsNNxcDAgkQ32RrcWx9GVUvfUNPcUkn8R3vIX6A==, - } - engines: { node: ">=18" } + '@csstools/postcss-trigonometric-functions@4.0.9': + resolution: {integrity: sha512-Hnh5zJUdpNrJqK9v1/E3BbrQhaDTj5YiX7P61TOvUhoDHnUmsNNxcDAgkQ32RrcWx9GVUvfUNPcUkn8R3vIX6A==} + engines: {node: '>=18'} peerDependencies: postcss: ^8.4 - "@csstools/postcss-unset-value@4.0.0": - resolution: - { - integrity: sha512-cBz3tOCI5Fw6NIFEwU3RiwK6mn3nKegjpJuzCndoGq3BZPkUjnsq7uQmIeMNeMbMk7YD2MfKcgCpZwX5jyXqCA==, - } - engines: { node: ">=18" } + '@csstools/postcss-unset-value@4.0.0': + resolution: {integrity: sha512-cBz3tOCI5Fw6NIFEwU3RiwK6mn3nKegjpJuzCndoGq3BZPkUjnsq7uQmIeMNeMbMk7YD2MfKcgCpZwX5jyXqCA==} + engines: {node: '>=18'} peerDependencies: postcss: ^8.4 - "@csstools/selector-resolve-nested@3.1.0": - resolution: - { - integrity: sha512-mf1LEW0tJLKfWyvn5KdDrhpxHyuxpbNwTIwOYLIvsTffeyOf85j5oIzfG0yosxDgx/sswlqBnESYUcQH0vgZ0g==, - } - engines: { node: ">=18" } + '@csstools/selector-resolve-nested@3.1.0': + resolution: {integrity: sha512-mf1LEW0tJLKfWyvn5KdDrhpxHyuxpbNwTIwOYLIvsTffeyOf85j5oIzfG0yosxDgx/sswlqBnESYUcQH0vgZ0g==} + engines: {node: '>=18'} peerDependencies: postcss-selector-parser: ^7.0.0 - "@csstools/selector-specificity@5.0.0": - resolution: - { - integrity: sha512-PCqQV3c4CoVm3kdPhyeZ07VmBRdH2EpMFA/pd9OASpOEC3aXNGoqPDAZ80D0cLpMBxnmk0+yNhGsEx31hq7Gtw==, - } - engines: { node: ">=18" } + '@csstools/selector-specificity@5.0.0': + resolution: {integrity: sha512-PCqQV3c4CoVm3kdPhyeZ07VmBRdH2EpMFA/pd9OASpOEC3aXNGoqPDAZ80D0cLpMBxnmk0+yNhGsEx31hq7Gtw==} + engines: {node: '>=18'} peerDependencies: postcss-selector-parser: ^7.0.0 - "@csstools/utilities@2.0.0": - resolution: - { - integrity: sha512-5VdOr0Z71u+Yp3ozOx8T11N703wIFGVRgOWbOZMKgglPJsWA54MRIoMNVMa7shUToIhx5J8vX4sOZgD2XiihiQ==, - } - engines: { node: ">=18" } + '@csstools/utilities@2.0.0': + resolution: {integrity: sha512-5VdOr0Z71u+Yp3ozOx8T11N703wIFGVRgOWbOZMKgglPJsWA54MRIoMNVMa7shUToIhx5J8vX4sOZgD2XiihiQ==} + engines: {node: '>=18'} peerDependencies: postcss: ^8.4 - "@emnapi/core@1.9.2": - resolution: - { - integrity: sha512-UC+ZhH3XtczQYfOlu3lNEkdW/p4dsJ1r/bP7H8+rhao3TTTMO1ATq/4DdIi23XuGoFY+Cz0JmCbdVl0hz9jZcA==, - } + '@emnapi/core@1.9.2': + resolution: {integrity: sha512-UC+ZhH3XtczQYfOlu3lNEkdW/p4dsJ1r/bP7H8+rhao3TTTMO1ATq/4DdIi23XuGoFY+Cz0JmCbdVl0hz9jZcA==} - "@emnapi/runtime@1.9.2": - resolution: - { - integrity: sha512-3U4+MIWHImeyu1wnmVygh5WlgfYDtyf0k8AbLhMFxOipihf6nrWC4syIm/SwEeec0mNSafiiNnMJwbza/Is6Lw==, - } + '@emnapi/runtime@1.9.2': + resolution: {integrity: sha512-3U4+MIWHImeyu1wnmVygh5WlgfYDtyf0k8AbLhMFxOipihf6nrWC4syIm/SwEeec0mNSafiiNnMJwbza/Is6Lw==} - "@emnapi/wasi-threads@1.2.1": - resolution: - { - integrity: sha512-uTII7OYF+/Mes/MrcIOYp5yOtSMLBWSIoLPpcgwipoiKbli6k322tcoFsxoIIxPDqW01SQGAgko4EzZi2BNv2w==, - } + '@emnapi/wasi-threads@1.2.1': + resolution: {integrity: sha512-uTII7OYF+/Mes/MrcIOYp5yOtSMLBWSIoLPpcgwipoiKbli6k322tcoFsxoIIxPDqW01SQGAgko4EzZi2BNv2w==} - "@es-joy/jsdoccomment@0.78.0": - resolution: - { - integrity: sha512-rQkU5u8hNAq2NVRzHnIUUvR6arbO0b6AOlvpTNS48CkiKSn/xtNfOzBK23JE4SiW89DgvU7GtxLVgV4Vn2HBAw==, - } - engines: { node: ">=20.11.0" } + '@es-joy/jsdoccomment@0.78.0': + resolution: {integrity: sha512-rQkU5u8hNAq2NVRzHnIUUvR6arbO0b6AOlvpTNS48CkiKSn/xtNfOzBK23JE4SiW89DgvU7GtxLVgV4Vn2HBAw==} + engines: {node: '>=20.11.0'} - "@es-joy/resolve.exports@1.2.0": - resolution: - { - integrity: sha512-Q9hjxWI5xBM+qW2enxfe8wDKdFWMfd0Z29k5ZJnuBqD/CasY5Zryj09aCA6owbGATWz+39p5uIdaHXpopOcG8g==, - } - engines: { node: ">=10" } + '@es-joy/resolve.exports@1.2.0': + resolution: {integrity: sha512-Q9hjxWI5xBM+qW2enxfe8wDKdFWMfd0Z29k5ZJnuBqD/CasY5Zryj09aCA6owbGATWz+39p5uIdaHXpopOcG8g==} + engines: {node: '>=10'} - "@esbuild/aix-ppc64@0.27.7": - resolution: - { - integrity: sha512-EKX3Qwmhz1eMdEJokhALr0YiD0lhQNwDqkPYyPhiSwKrh7/4KRjQc04sZ8db+5DVVnZ1LmbNDI1uAMPEUBnQPg==, - } - engines: { node: ">=18" } + '@esbuild/aix-ppc64@0.27.7': + resolution: {integrity: sha512-EKX3Qwmhz1eMdEJokhALr0YiD0lhQNwDqkPYyPhiSwKrh7/4KRjQc04sZ8db+5DVVnZ1LmbNDI1uAMPEUBnQPg==} + engines: {node: '>=18'} cpu: [ppc64] os: [aix] - "@esbuild/android-arm64@0.27.7": - resolution: - { - integrity: sha512-62dPZHpIXzvChfvfLJow3q5dDtiNMkwiRzPylSCfriLvZeq0a1bWChrGx/BbUbPwOrsWKMn8idSllklzBy+dgQ==, - } - engines: { node: ">=18" } + '@esbuild/android-arm64@0.27.7': + resolution: {integrity: sha512-62dPZHpIXzvChfvfLJow3q5dDtiNMkwiRzPylSCfriLvZeq0a1bWChrGx/BbUbPwOrsWKMn8idSllklzBy+dgQ==} + engines: {node: '>=18'} cpu: [arm64] os: [android] - "@esbuild/android-arm@0.27.7": - resolution: - { - integrity: sha512-jbPXvB4Yj2yBV7HUfE2KHe4GJX51QplCN1pGbYjvsyCZbQmies29EoJbkEc+vYuU5o45AfQn37vZlyXy4YJ8RQ==, - } - engines: { node: ">=18" } + '@esbuild/android-arm@0.27.7': + resolution: {integrity: sha512-jbPXvB4Yj2yBV7HUfE2KHe4GJX51QplCN1pGbYjvsyCZbQmies29EoJbkEc+vYuU5o45AfQn37vZlyXy4YJ8RQ==} + engines: {node: '>=18'} cpu: [arm] os: [android] - "@esbuild/android-x64@0.27.7": - resolution: - { - integrity: sha512-x5VpMODneVDb70PYV2VQOmIUUiBtY3D3mPBG8NxVk5CogneYhkR7MmM3yR/uMdITLrC1ml/NV1rj4bMJuy9MCg==, - } - engines: { node: ">=18" } + '@esbuild/android-x64@0.27.7': + resolution: {integrity: sha512-x5VpMODneVDb70PYV2VQOmIUUiBtY3D3mPBG8NxVk5CogneYhkR7MmM3yR/uMdITLrC1ml/NV1rj4bMJuy9MCg==} + engines: {node: '>=18'} cpu: [x64] os: [android] - "@esbuild/darwin-arm64@0.27.7": - resolution: - { - integrity: sha512-5lckdqeuBPlKUwvoCXIgI2D9/ABmPq3Rdp7IfL70393YgaASt7tbju3Ac+ePVi3KDH6N2RqePfHnXkaDtY9fkw==, - } - engines: { node: ">=18" } + '@esbuild/darwin-arm64@0.27.7': + resolution: {integrity: sha512-5lckdqeuBPlKUwvoCXIgI2D9/ABmPq3Rdp7IfL70393YgaASt7tbju3Ac+ePVi3KDH6N2RqePfHnXkaDtY9fkw==} + engines: {node: '>=18'} cpu: [arm64] os: [darwin] - "@esbuild/darwin-x64@0.27.7": - resolution: - { - integrity: sha512-rYnXrKcXuT7Z+WL5K980jVFdvVKhCHhUwid+dDYQpH+qu+TefcomiMAJpIiC2EM3Rjtq0sO3StMV/+3w3MyyqQ==, - } - engines: { node: ">=18" } + '@esbuild/darwin-x64@0.27.7': + resolution: {integrity: sha512-rYnXrKcXuT7Z+WL5K980jVFdvVKhCHhUwid+dDYQpH+qu+TefcomiMAJpIiC2EM3Rjtq0sO3StMV/+3w3MyyqQ==} + engines: {node: '>=18'} cpu: [x64] os: [darwin] - "@esbuild/freebsd-arm64@0.27.7": - resolution: - { - integrity: sha512-B48PqeCsEgOtzME2GbNM2roU29AMTuOIN91dsMO30t+Ydis3z/3Ngoj5hhnsOSSwNzS+6JppqWsuhTp6E82l2w==, - } - engines: { node: ">=18" } + '@esbuild/freebsd-arm64@0.27.7': + resolution: {integrity: sha512-B48PqeCsEgOtzME2GbNM2roU29AMTuOIN91dsMO30t+Ydis3z/3Ngoj5hhnsOSSwNzS+6JppqWsuhTp6E82l2w==} + engines: {node: '>=18'} cpu: [arm64] os: [freebsd] - "@esbuild/freebsd-x64@0.27.7": - resolution: - { - integrity: sha512-jOBDK5XEjA4m5IJK3bpAQF9/Lelu/Z9ZcdhTRLf4cajlB+8VEhFFRjWgfy3M1O4rO2GQ/b2dLwCUGpiF/eATNQ==, - } - engines: { node: ">=18" } + '@esbuild/freebsd-x64@0.27.7': + resolution: {integrity: sha512-jOBDK5XEjA4m5IJK3bpAQF9/Lelu/Z9ZcdhTRLf4cajlB+8VEhFFRjWgfy3M1O4rO2GQ/b2dLwCUGpiF/eATNQ==} + engines: {node: '>=18'} cpu: [x64] os: [freebsd] - "@esbuild/linux-arm64@0.27.7": - resolution: - { - integrity: sha512-RZPHBoxXuNnPQO9rvjh5jdkRmVizktkT7TCDkDmQ0W2SwHInKCAV95GRuvdSvA7w4VMwfCjUiPwDi0ZO6Nfe9A==, - } - engines: { node: ">=18" } + '@esbuild/linux-arm64@0.27.7': + resolution: {integrity: sha512-RZPHBoxXuNnPQO9rvjh5jdkRmVizktkT7TCDkDmQ0W2SwHInKCAV95GRuvdSvA7w4VMwfCjUiPwDi0ZO6Nfe9A==} + engines: {node: '>=18'} cpu: [arm64] os: [linux] - "@esbuild/linux-arm@0.27.7": - resolution: - { - integrity: sha512-RkT/YXYBTSULo3+af8Ib0ykH8u2MBh57o7q/DAs3lTJlyVQkgQvlrPTnjIzzRPQyavxtPtfg0EopvDyIt0j1rA==, - } - engines: { node: ">=18" } + '@esbuild/linux-arm@0.27.7': + resolution: {integrity: sha512-RkT/YXYBTSULo3+af8Ib0ykH8u2MBh57o7q/DAs3lTJlyVQkgQvlrPTnjIzzRPQyavxtPtfg0EopvDyIt0j1rA==} + engines: {node: '>=18'} cpu: [arm] os: [linux] - "@esbuild/linux-ia32@0.27.7": - resolution: - { - integrity: sha512-GA48aKNkyQDbd3KtkplYWT102C5sn/EZTY4XROkxONgruHPU72l+gW+FfF8tf2cFjeHaRbWpOYa/uRBz/Xq1Pg==, - } - engines: { node: ">=18" } + '@esbuild/linux-ia32@0.27.7': + resolution: {integrity: sha512-GA48aKNkyQDbd3KtkplYWT102C5sn/EZTY4XROkxONgruHPU72l+gW+FfF8tf2cFjeHaRbWpOYa/uRBz/Xq1Pg==} + engines: {node: '>=18'} cpu: [ia32] os: [linux] - "@esbuild/linux-loong64@0.27.7": - resolution: - { - integrity: sha512-a4POruNM2oWsD4WKvBSEKGIiWQF8fZOAsycHOt6JBpZ+JN2n2JH9WAv56SOyu9X5IqAjqSIPTaJkqN8F7XOQ5Q==, - } - engines: { node: ">=18" } + '@esbuild/linux-loong64@0.27.7': + resolution: {integrity: sha512-a4POruNM2oWsD4WKvBSEKGIiWQF8fZOAsycHOt6JBpZ+JN2n2JH9WAv56SOyu9X5IqAjqSIPTaJkqN8F7XOQ5Q==} + engines: {node: '>=18'} cpu: [loong64] os: [linux] - "@esbuild/linux-mips64el@0.27.7": - resolution: - { - integrity: sha512-KabT5I6StirGfIz0FMgl1I+R1H73Gp0ofL9A3nG3i/cYFJzKHhouBV5VWK1CSgKvVaG4q1RNpCTR2LuTVB3fIw==, - } - engines: { node: ">=18" } + '@esbuild/linux-mips64el@0.27.7': + resolution: {integrity: sha512-KabT5I6StirGfIz0FMgl1I+R1H73Gp0ofL9A3nG3i/cYFJzKHhouBV5VWK1CSgKvVaG4q1RNpCTR2LuTVB3fIw==} + engines: {node: '>=18'} cpu: [mips64el] os: [linux] - "@esbuild/linux-ppc64@0.27.7": - resolution: - { - integrity: sha512-gRsL4x6wsGHGRqhtI+ifpN/vpOFTQtnbsupUF5R5YTAg+y/lKelYR1hXbnBdzDjGbMYjVJLJTd2OFmMewAgwlQ==, - } - engines: { node: ">=18" } + '@esbuild/linux-ppc64@0.27.7': + resolution: {integrity: sha512-gRsL4x6wsGHGRqhtI+ifpN/vpOFTQtnbsupUF5R5YTAg+y/lKelYR1hXbnBdzDjGbMYjVJLJTd2OFmMewAgwlQ==} + engines: {node: '>=18'} cpu: [ppc64] os: [linux] - "@esbuild/linux-riscv64@0.27.7": - resolution: - { - integrity: sha512-hL25LbxO1QOngGzu2U5xeXtxXcW+/GvMN3ejANqXkxZ/opySAZMrc+9LY/WyjAan41unrR3YrmtTsUpwT66InQ==, - } - engines: { node: ">=18" } + '@esbuild/linux-riscv64@0.27.7': + resolution: {integrity: sha512-hL25LbxO1QOngGzu2U5xeXtxXcW+/GvMN3ejANqXkxZ/opySAZMrc+9LY/WyjAan41unrR3YrmtTsUpwT66InQ==} + engines: {node: '>=18'} cpu: [riscv64] os: [linux] - "@esbuild/linux-s390x@0.27.7": - resolution: - { - integrity: sha512-2k8go8Ycu1Kb46vEelhu1vqEP+UeRVj2zY1pSuPdgvbd5ykAw82Lrro28vXUrRmzEsUV0NzCf54yARIK8r0fdw==, - } - engines: { node: ">=18" } + '@esbuild/linux-s390x@0.27.7': + resolution: {integrity: sha512-2k8go8Ycu1Kb46vEelhu1vqEP+UeRVj2zY1pSuPdgvbd5ykAw82Lrro28vXUrRmzEsUV0NzCf54yARIK8r0fdw==} + engines: {node: '>=18'} cpu: [s390x] os: [linux] - "@esbuild/linux-x64@0.27.7": - resolution: - { - integrity: sha512-hzznmADPt+OmsYzw1EE33ccA+HPdIqiCRq7cQeL1Jlq2gb1+OyWBkMCrYGBJ+sxVzve2ZJEVeePbLM2iEIZSxA==, - } - engines: { node: ">=18" } + '@esbuild/linux-x64@0.27.7': + resolution: {integrity: sha512-hzznmADPt+OmsYzw1EE33ccA+HPdIqiCRq7cQeL1Jlq2gb1+OyWBkMCrYGBJ+sxVzve2ZJEVeePbLM2iEIZSxA==} + engines: {node: '>=18'} cpu: [x64] os: [linux] - "@esbuild/netbsd-arm64@0.27.7": - resolution: - { - integrity: sha512-b6pqtrQdigZBwZxAn1UpazEisvwaIDvdbMbmrly7cDTMFnw/+3lVxxCTGOrkPVnsYIosJJXAsILG9XcQS+Yu6w==, - } - engines: { node: ">=18" } + '@esbuild/netbsd-arm64@0.27.7': + resolution: {integrity: sha512-b6pqtrQdigZBwZxAn1UpazEisvwaIDvdbMbmrly7cDTMFnw/+3lVxxCTGOrkPVnsYIosJJXAsILG9XcQS+Yu6w==} + engines: {node: '>=18'} cpu: [arm64] os: [netbsd] - "@esbuild/netbsd-x64@0.27.7": - resolution: - { - integrity: sha512-OfatkLojr6U+WN5EDYuoQhtM+1xco+/6FSzJJnuWiUw5eVcicbyK3dq5EeV/QHT1uy6GoDhGbFpprUiHUYggrw==, - } - engines: { node: ">=18" } + '@esbuild/netbsd-x64@0.27.7': + resolution: {integrity: sha512-OfatkLojr6U+WN5EDYuoQhtM+1xco+/6FSzJJnuWiUw5eVcicbyK3dq5EeV/QHT1uy6GoDhGbFpprUiHUYggrw==} + engines: {node: '>=18'} cpu: [x64] os: [netbsd] - "@esbuild/openbsd-arm64@0.27.7": - resolution: - { - integrity: sha512-AFuojMQTxAz75Fo8idVcqoQWEHIXFRbOc1TrVcFSgCZtQfSdc1RXgB3tjOn/krRHENUB4j00bfGjyl2mJrU37A==, - } - engines: { node: ">=18" } + '@esbuild/openbsd-arm64@0.27.7': + resolution: {integrity: sha512-AFuojMQTxAz75Fo8idVcqoQWEHIXFRbOc1TrVcFSgCZtQfSdc1RXgB3tjOn/krRHENUB4j00bfGjyl2mJrU37A==} + engines: {node: '>=18'} cpu: [arm64] os: [openbsd] - "@esbuild/openbsd-x64@0.27.7": - resolution: - { - integrity: sha512-+A1NJmfM8WNDv5CLVQYJ5PshuRm/4cI6WMZRg1by1GwPIQPCTs1GLEUHwiiQGT5zDdyLiRM/l1G0Pv54gvtKIg==, - } - engines: { node: ">=18" } + '@esbuild/openbsd-x64@0.27.7': + resolution: {integrity: sha512-+A1NJmfM8WNDv5CLVQYJ5PshuRm/4cI6WMZRg1by1GwPIQPCTs1GLEUHwiiQGT5zDdyLiRM/l1G0Pv54gvtKIg==} + engines: {node: '>=18'} cpu: [x64] os: [openbsd] - "@esbuild/openharmony-arm64@0.27.7": - resolution: - { - integrity: sha512-+KrvYb/C8zA9CU/g0sR6w2RBw7IGc5J2BPnc3dYc5VJxHCSF1yNMxTV5LQ7GuKteQXZtspjFbiuW5/dOj7H4Yw==, - } - engines: { node: ">=18" } + '@esbuild/openharmony-arm64@0.27.7': + resolution: {integrity: sha512-+KrvYb/C8zA9CU/g0sR6w2RBw7IGc5J2BPnc3dYc5VJxHCSF1yNMxTV5LQ7GuKteQXZtspjFbiuW5/dOj7H4Yw==} + engines: {node: '>=18'} cpu: [arm64] os: [openharmony] - "@esbuild/sunos-x64@0.27.7": - resolution: - { - integrity: sha512-ikktIhFBzQNt/QDyOL580ti9+5mL/YZeUPKU2ivGtGjdTYoqz6jObj6nOMfhASpS4GU4Q/Clh1QtxWAvcYKamA==, - } - engines: { node: ">=18" } + '@esbuild/sunos-x64@0.27.7': + resolution: {integrity: sha512-ikktIhFBzQNt/QDyOL580ti9+5mL/YZeUPKU2ivGtGjdTYoqz6jObj6nOMfhASpS4GU4Q/Clh1QtxWAvcYKamA==} + engines: {node: '>=18'} cpu: [x64] os: [sunos] - "@esbuild/win32-arm64@0.27.7": - resolution: - { - integrity: sha512-7yRhbHvPqSpRUV7Q20VuDwbjW5kIMwTHpptuUzV+AA46kiPze5Z7qgt6CLCK3pWFrHeNfDd1VKgyP4O+ng17CA==, - } - engines: { node: ">=18" } + '@esbuild/win32-arm64@0.27.7': + resolution: {integrity: sha512-7yRhbHvPqSpRUV7Q20VuDwbjW5kIMwTHpptuUzV+AA46kiPze5Z7qgt6CLCK3pWFrHeNfDd1VKgyP4O+ng17CA==} + engines: {node: '>=18'} cpu: [arm64] os: [win32] - "@esbuild/win32-ia32@0.27.7": - resolution: - { - integrity: sha512-SmwKXe6VHIyZYbBLJrhOoCJRB/Z1tckzmgTLfFYOfpMAx63BJEaL9ExI8x7v0oAO3Zh6D/Oi1gVxEYr5oUCFhw==, - } - engines: { node: ">=18" } + '@esbuild/win32-ia32@0.27.7': + resolution: {integrity: sha512-SmwKXe6VHIyZYbBLJrhOoCJRB/Z1tckzmgTLfFYOfpMAx63BJEaL9ExI8x7v0oAO3Zh6D/Oi1gVxEYr5oUCFhw==} + engines: {node: '>=18'} cpu: [ia32] os: [win32] - "@esbuild/win32-x64@0.27.7": - resolution: - { - integrity: sha512-56hiAJPhwQ1R4i+21FVF7V8kSD5zZTdHcVuRFMW0hn753vVfQN8xlx4uOPT4xoGH0Z/oVATuR82AiqSTDIpaHg==, - } - engines: { node: ">=18" } + '@esbuild/win32-x64@0.27.7': + resolution: {integrity: sha512-56hiAJPhwQ1R4i+21FVF7V8kSD5zZTdHcVuRFMW0hn753vVfQN8xlx4uOPT4xoGH0Z/oVATuR82AiqSTDIpaHg==} + engines: {node: '>=18'} cpu: [x64] os: [win32] - "@eslint-community/eslint-utils@4.9.1": - resolution: - { - integrity: sha512-phrYmNiYppR7znFEdqgfWHXR6NCkZEK7hwWDHZUjit/2/U0r6XvkDl0SYnoM51Hq7FhCGdLDT6zxCCOY1hexsQ==, - } - engines: { node: ^12.22.0 || ^14.17.0 || >=16.0.0 } + '@eslint-community/eslint-utils@4.9.1': + resolution: {integrity: sha512-phrYmNiYppR7znFEdqgfWHXR6NCkZEK7hwWDHZUjit/2/U0r6XvkDl0SYnoM51Hq7FhCGdLDT6zxCCOY1hexsQ==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} peerDependencies: eslint: ^6.0.0 || ^7.0.0 || >=8.0.0 - "@eslint-community/regexpp@4.12.2": - resolution: - { - integrity: sha512-EriSTlt5OC9/7SXkRSCAhfSxxoSUgBm33OH+IkwbdpgoqsSsUg7y3uh+IICI/Qg4BBWr3U2i39RpmycbxMq4ew==, - } - engines: { node: ^12.0.0 || ^14.0.0 || >=16.0.0 } + '@eslint-community/regexpp@4.12.2': + resolution: {integrity: sha512-EriSTlt5OC9/7SXkRSCAhfSxxoSUgBm33OH+IkwbdpgoqsSsUg7y3uh+IICI/Qg4BBWr3U2i39RpmycbxMq4ew==} + engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0} - "@eslint/eslintrc@2.1.4": - resolution: - { - integrity: sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==, - } - engines: { node: ^12.22.0 || ^14.17.0 || >=16.0.0 } + '@eslint/eslintrc@2.1.4': + resolution: {integrity: sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - "@eslint/js@8.57.1": - resolution: - { - integrity: sha512-d9zaMRSTIKDLhctzH12MtXvJKSSUhaHcjV+2Z+GK+EEY7XKpP5yR4x+N3TAcHTcu963nIr+TMcCb4DBCYX1z6Q==, - } - engines: { node: ^12.22.0 || ^14.17.0 || >=16.0.0 } + '@eslint/js@8.57.1': + resolution: {integrity: sha512-d9zaMRSTIKDLhctzH12MtXvJKSSUhaHcjV+2Z+GK+EEY7XKpP5yR4x+N3TAcHTcu963nIr+TMcCb4DBCYX1z6Q==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - "@fastify/busboy@2.1.1": - resolution: - { - integrity: sha512-vBZP4NlzfOlerQTnba4aqZoMhE/a9HY7HRqoOPaETQcSQuWEIyZMHGfVu6w9wGtGK5fED5qRs2DteVCjOH60sA==, - } - engines: { node: ">=14" } + '@fastify/busboy@2.1.1': + resolution: {integrity: sha512-vBZP4NlzfOlerQTnba4aqZoMhE/a9HY7HRqoOPaETQcSQuWEIyZMHGfVu6w9wGtGK5fED5qRs2DteVCjOH60sA==} + engines: {node: '>=14'} - "@floating-ui/core@1.7.5": - resolution: - { - integrity: sha512-1Ih4WTWyw0+lKyFMcBHGbb5U5FtuHJuujoyyr5zTaWS5EYMeT6Jb2AuDeftsCsEuchO+mM2ij5+q9crhydzLhQ==, - } + '@floating-ui/core@1.7.5': + resolution: {integrity: sha512-1Ih4WTWyw0+lKyFMcBHGbb5U5FtuHJuujoyyr5zTaWS5EYMeT6Jb2AuDeftsCsEuchO+mM2ij5+q9crhydzLhQ==} - "@floating-ui/dom@1.7.4": - resolution: - { - integrity: sha512-OOchDgh4F2CchOX94cRVqhvy7b3AFb+/rQXyswmzmGakRfkMgoWVjfnLWkRirfLEfuD4ysVW16eXzwt3jHIzKA==, - } + '@floating-ui/dom@1.7.4': + resolution: {integrity: sha512-OOchDgh4F2CchOX94cRVqhvy7b3AFb+/rQXyswmzmGakRfkMgoWVjfnLWkRirfLEfuD4ysVW16eXzwt3jHIzKA==} - "@floating-ui/dom@1.7.6": - resolution: - { - integrity: sha512-9gZSAI5XM36880PPMm//9dfiEngYoC6Am2izES1FF406YFsjvyBMmeJ2g4SAju3xWwtuynNRFL2s9hgxpLI5SQ==, - } + '@floating-ui/dom@1.7.6': + resolution: {integrity: sha512-9gZSAI5XM36880PPMm//9dfiEngYoC6Am2izES1FF406YFsjvyBMmeJ2g4SAju3xWwtuynNRFL2s9hgxpLI5SQ==} - "@floating-ui/react-dom@2.1.8": - resolution: - { - integrity: sha512-cC52bHwM/n/CxS87FH0yWdngEZrjdtLW/qVruo68qg+prK7ZQ4YGdut2GyDVpoGeAYe/h899rVeOVm6Oi40k2A==, - } + '@floating-ui/react-dom@2.1.8': + resolution: {integrity: sha512-cC52bHwM/n/CxS87FH0yWdngEZrjdtLW/qVruo68qg+prK7ZQ4YGdut2GyDVpoGeAYe/h899rVeOVm6Oi40k2A==} peerDependencies: - react: ">=16.8.0" - react-dom: ">=16.8.0" + react: '>=16.8.0' + react-dom: '>=16.8.0' - "@floating-ui/react@0.27.19": - resolution: - { - integrity: sha512-31B8h5mm8YxotlE7/AU/PhNAl8eWxAmjL/v2QOxroDNkTFLk3Uu82u63N3b6TXa4EGJeeZLVcd/9AlNlVqzeog==, - } + '@floating-ui/react@0.27.19': + resolution: {integrity: sha512-31B8h5mm8YxotlE7/AU/PhNAl8eWxAmjL/v2QOxroDNkTFLk3Uu82u63N3b6TXa4EGJeeZLVcd/9AlNlVqzeog==} peerDependencies: - react: ">=17.0.0" - react-dom: ">=17.0.0" + react: '>=17.0.0' + react-dom: '>=17.0.0' - "@floating-ui/utils@0.2.11": - resolution: - { - integrity: sha512-RiB/yIh78pcIxl6lLMG0CgBXAZ2Y0eVHqMPYugu+9U0AeT6YBeiJpf7lbdJNIugFP5SIjwNRgo4DhR1Qxi26Gg==, - } + '@floating-ui/utils@0.2.11': + resolution: {integrity: sha512-RiB/yIh78pcIxl6lLMG0CgBXAZ2Y0eVHqMPYugu+9U0AeT6YBeiJpf7lbdJNIugFP5SIjwNRgo4DhR1Qxi26Gg==} - "@fontsource/inconsolata@5.2.8": - resolution: - { - integrity: sha512-lIZW+WOZYpUH91g9r6rYYhfTmptF3YPPM54ZOs8IYVeeL4SeiAu4tfj7mdr8llYEq31DLYgi6JtGIJa192gB0Q==, - } + '@fontsource/inconsolata@5.2.8': + resolution: {integrity: sha512-lIZW+WOZYpUH91g9r6rYYhfTmptF3YPPM54ZOs8IYVeeL4SeiAu4tfj7mdr8llYEq31DLYgi6JtGIJa192gB0Q==} - "@fontsource/inter@5.2.8": - resolution: - { - integrity: sha512-P6r5WnJoKiNVV+zvW2xM13gNdFhAEpQ9dQJHt3naLvfg+LkF2ldgSLiF4T41lf1SQCM9QmkqPTn4TH568IRagg==, - } + '@fontsource/inter@5.2.8': + resolution: {integrity: sha512-P6r5WnJoKiNVV+zvW2xM13gNdFhAEpQ9dQJHt3naLvfg+LkF2ldgSLiF4T41lf1SQCM9QmkqPTn4TH568IRagg==} - "@formatjs/ecma402-abstract@2.3.6": - resolution: - { - integrity: sha512-HJnTFeRM2kVFVr5gr5kH1XP6K0JcJtE7Lzvtr3FS/so5f1kpsqqqxy5JF+FRaO6H2qmcMfAUIox7AJteieRtVw==, - } + '@formatjs/ecma402-abstract@2.3.6': + resolution: {integrity: sha512-HJnTFeRM2kVFVr5gr5kH1XP6K0JcJtE7Lzvtr3FS/so5f1kpsqqqxy5JF+FRaO6H2qmcMfAUIox7AJteieRtVw==} - "@formatjs/fast-memoize@2.2.7": - resolution: - { - integrity: sha512-Yabmi9nSvyOMrlSeGGWDiH7rf3a7sIwplbvo/dlz9WCIjzIQAfy1RMf4S0X3yG724n5Ghu2GmEl5NJIV6O9sZQ==, - } + '@formatjs/fast-memoize@2.2.7': + resolution: {integrity: sha512-Yabmi9nSvyOMrlSeGGWDiH7rf3a7sIwplbvo/dlz9WCIjzIQAfy1RMf4S0X3yG724n5Ghu2GmEl5NJIV6O9sZQ==} - "@formatjs/fast-memoize@3.1.2": - resolution: - { - integrity: sha512-vPnriihkfK0lzoQGaXq+qXH23VsYyansRTkTgo2aTG0k1NjLFyZimFVdfj4C9JkSE5dm7CEngcQ5TTc1yAyBfQ==, - } + '@formatjs/fast-memoize@3.1.2': + resolution: {integrity: sha512-vPnriihkfK0lzoQGaXq+qXH23VsYyansRTkTgo2aTG0k1NjLFyZimFVdfj4C9JkSE5dm7CEngcQ5TTc1yAyBfQ==} - "@formatjs/intl-durationformat@0.10.4": - resolution: - { - integrity: sha512-SUS4xT3GX43/thXTZojOXMNMB1zUIlLC+3mdyJga7evrgV4jvmgycX9bXfmMNDu7c2TC9gnXySUpUcxMghZrKg==, - } + '@formatjs/intl-durationformat@0.10.4': + resolution: {integrity: sha512-SUS4xT3GX43/thXTZojOXMNMB1zUIlLC+3mdyJga7evrgV4jvmgycX9bXfmMNDu7c2TC9gnXySUpUcxMghZrKg==} - "@formatjs/intl-localematcher@0.6.2": - resolution: - { - integrity: sha512-XOMO2Hupl0wdd172Y06h6kLpBz6Dv+J4okPLl4LPtzbr8f66WbIoy4ev98EBuZ6ZK4h5ydTN6XneT4QVpD7cdA==, - } + '@formatjs/intl-localematcher@0.6.2': + resolution: {integrity: sha512-XOMO2Hupl0wdd172Y06h6kLpBz6Dv+J4okPLl4LPtzbr8f66WbIoy4ev98EBuZ6ZK4h5ydTN6XneT4QVpD7cdA==} - "@formatjs/intl-localematcher@0.8.3": - resolution: - { - integrity: sha512-pHUjWb9NuhnMs8+PxQdzBtZRFJHlGhrURGAbm6Ltwl82BFajeuiIR3jblSa7ia3r62rXe/0YtVpUG3xWr5bFCA==, - } + '@formatjs/intl-localematcher@0.8.3': + resolution: {integrity: sha512-pHUjWb9NuhnMs8+PxQdzBtZRFJHlGhrURGAbm6Ltwl82BFajeuiIR3jblSa7ia3r62rXe/0YtVpUG3xWr5bFCA==} - "@formatjs/intl-segmenter@11.7.12": - resolution: - { - integrity: sha512-3QefVKh5HvaKU80lAFmqUsWmKYWcpiDymsc0HwFvhuVl0dAnMhtbNmzMN50UiC7ZsnbybelNGrm9GZPp4kbbZA==, - } + '@formatjs/intl-segmenter@11.7.12': + resolution: {integrity: sha512-3QefVKh5HvaKU80lAFmqUsWmKYWcpiDymsc0HwFvhuVl0dAnMhtbNmzMN50UiC7ZsnbybelNGrm9GZPp4kbbZA==} - "@gulpjs/to-absolute-glob@4.0.0": - resolution: - { - integrity: sha512-kjotm7XJrJ6v+7knhPaRgaT6q8F8K2jiafwYdNHLzmV0uGLuZY43FK6smNSHUPrhq5kX2slCUy+RGG/xGqmIKA==, - } - engines: { node: ">=10.13.0" } + '@gulpjs/to-absolute-glob@4.0.0': + resolution: {integrity: sha512-kjotm7XJrJ6v+7knhPaRgaT6q8F8K2jiafwYdNHLzmV0uGLuZY43FK6smNSHUPrhq5kX2slCUy+RGG/xGqmIKA==} + engines: {node: '>=10.13.0'} - "@humanwhocodes/config-array@0.13.0": - resolution: - { - integrity: sha512-DZLEEqFWQFiyK6h5YIeynKx7JlvCYWL0cImfSRXZ9l4Sg2efkFGTuFf6vzXjK1cq6IYkU+Eg/JizXw+TD2vRNw==, - } - engines: { node: ">=10.10.0" } + '@humanwhocodes/config-array@0.13.0': + resolution: {integrity: sha512-DZLEEqFWQFiyK6h5YIeynKx7JlvCYWL0cImfSRXZ9l4Sg2efkFGTuFf6vzXjK1cq6IYkU+Eg/JizXw+TD2vRNw==} + engines: {node: '>=10.10.0'} deprecated: Use @eslint/config-array instead - "@humanwhocodes/module-importer@1.0.1": - resolution: - { - integrity: sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==, - } - engines: { node: ">=12.22" } + '@humanwhocodes/module-importer@1.0.1': + resolution: {integrity: sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==} + engines: {node: '>=12.22'} - "@humanwhocodes/object-schema@2.0.3": - resolution: - { - integrity: sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==, - } + '@humanwhocodes/object-schema@2.0.3': + resolution: {integrity: sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==} deprecated: Use @eslint/object-schema instead - "@isaacs/cliui@8.0.2": - resolution: - { - integrity: sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==, - } - engines: { node: ">=12" } + '@isaacs/cliui@8.0.2': + resolution: {integrity: sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==} + engines: {node: '>=12'} - "@joshwooding/vite-plugin-react-docgen-typescript@0.7.0": - resolution: - { - integrity: sha512-qvsTEwEFefhdirGOPnu9Wp6ChfIwy2dBCRuETU3uE+4cC+PFoxMSiiEhxk4lOluA34eARHA0OxqsEUYDqRMgeQ==, - } + '@joshwooding/vite-plugin-react-docgen-typescript@0.7.0': + resolution: {integrity: sha512-qvsTEwEFefhdirGOPnu9Wp6ChfIwy2dBCRuETU3uE+4cC+PFoxMSiiEhxk4lOluA34eARHA0OxqsEUYDqRMgeQ==} peerDependencies: - typescript: ">= 4.3.x" + typescript: '>= 4.3.x' vite: ^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0 peerDependenciesMeta: typescript: optional: true - "@jridgewell/gen-mapping@0.3.13": - resolution: - { - integrity: sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==, - } + '@jridgewell/gen-mapping@0.3.13': + resolution: {integrity: sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==} - "@jridgewell/remapping@2.3.5": - resolution: - { - integrity: sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==, - } + '@jridgewell/remapping@2.3.5': + resolution: {integrity: sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==} - "@jridgewell/resolve-uri@3.1.2": - resolution: - { - integrity: sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==, - } - engines: { node: ">=6.0.0" } + '@jridgewell/resolve-uri@3.1.2': + resolution: {integrity: sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==} + engines: {node: '>=6.0.0'} - "@jridgewell/source-map@0.3.11": - resolution: - { - integrity: sha512-ZMp1V8ZFcPG5dIWnQLr3NSI1MiCU7UETdS/A0G8V/XWHvJv3ZsFqutJn1Y5RPmAPX6F3BiE397OqveU/9NCuIA==, - } + '@jridgewell/source-map@0.3.11': + resolution: {integrity: sha512-ZMp1V8ZFcPG5dIWnQLr3NSI1MiCU7UETdS/A0G8V/XWHvJv3ZsFqutJn1Y5RPmAPX6F3BiE397OqveU/9NCuIA==} - "@jridgewell/sourcemap-codec@1.5.5": - resolution: - { - integrity: sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==, - } + '@jridgewell/sourcemap-codec@1.5.5': + resolution: {integrity: sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==} - "@jridgewell/trace-mapping@0.3.31": - resolution: - { - integrity: sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==, - } + '@jridgewell/trace-mapping@0.3.31': + resolution: {integrity: sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==} - "@livekit/components-core@0.12.13": - resolution: - { - integrity: sha512-DQmi84afHoHjZ62wm8y+XPNIDHTwFHAltjd3lmyXj8UZHOY7wcza4vFt1xnghJOD5wLRY58L1dkAgAw59MgWvw==, - } - engines: { node: ">=18" } + '@livekit/components-core@0.12.13': + resolution: {integrity: sha512-DQmi84afHoHjZ62wm8y+XPNIDHTwFHAltjd3lmyXj8UZHOY7wcza4vFt1xnghJOD5wLRY58L1dkAgAw59MgWvw==} + engines: {node: '>=18'} peerDependencies: livekit-client: ^2.17.2 tslib: ^2.6.2 - "@livekit/components-react@2.9.20": - resolution: - { - integrity: sha512-hjkYOsJj9Jbghb7wM5cI8HoVisKeL6Zcy1VnRWTLm0sqVbto8GJp/17T4Udx85mCPY6Jgh8I1Cv0yVzgz7CQtg==, - } - engines: { node: ">=18" } + '@livekit/components-react@2.9.20': + resolution: {integrity: sha512-hjkYOsJj9Jbghb7wM5cI8HoVisKeL6Zcy1VnRWTLm0sqVbto8GJp/17T4Udx85mCPY6Jgh8I1Cv0yVzgz7CQtg==} + engines: {node: '>=18'} peerDependencies: - "@livekit/krisp-noise-filter": ^0.2.12 || ^0.3.0 + '@livekit/krisp-noise-filter': ^0.2.12 || ^0.3.0 livekit-client: ^2.17.2 - react: ">=18" - react-dom: ">=18" + react: '>=18' + react-dom: '>=18' tslib: ^2.6.2 peerDependenciesMeta: - "@livekit/krisp-noise-filter": + '@livekit/krisp-noise-filter': optional: true - "@livekit/mutex@1.1.1": - resolution: - { - integrity: sha512-EsshAucklmpuUAfkABPxJNhzj9v2sG7JuzFDL4ML1oJQSV14sqrpTYnsaOudMAw9yOaW53NU3QQTlUQoRs4czw==, - } + '@livekit/mutex@1.1.1': + resolution: {integrity: sha512-EsshAucklmpuUAfkABPxJNhzj9v2sG7JuzFDL4ML1oJQSV14sqrpTYnsaOudMAw9yOaW53NU3QQTlUQoRs4czw==} - "@livekit/protocol@1.45.3": - resolution: - { - integrity: sha512-WmMxBTsy4dRBqcrswFwUUlgq3Z0nnhOqKR6tX749Rb/PcB1yBMUtrHxZvcsS6qi3/5+86zHeVG+exmu1sZqfJg==, - } + '@livekit/protocol@1.45.3': + resolution: {integrity: sha512-WmMxBTsy4dRBqcrswFwUUlgq3Z0nnhOqKR6tX749Rb/PcB1yBMUtrHxZvcsS6qi3/5+86zHeVG+exmu1sZqfJg==} - "@livekit/track-processors@0.7.2": - resolution: - { - integrity: sha512-lzARBKTbBwqycdR/SwTu6//N0l20BzfDd7grxCXl07676SwRApNtZAK1GJjL1m3dCM3KBqH1aVxjMpNcbOw5uQ==, - } + '@livekit/track-processors@0.7.2': + resolution: {integrity: sha512-lzARBKTbBwqycdR/SwTu6//N0l20BzfDd7grxCXl07676SwRApNtZAK1GJjL1m3dCM3KBqH1aVxjMpNcbOw5uQ==} peerDependencies: - "@types/dom-mediacapture-transform": ^0.1.9 + '@types/dom-mediacapture-transform': ^0.1.9 livekit-client: ^1.12.0 || ^2.1.0 - "@matrix-org/matrix-sdk-crypto-wasm@18.0.0": - resolution: - { - integrity: sha512-88+n+dvxLI1cjS10UIlKXVYK7TGWbpAnnaDC9fow7ch/hCvdu3dFhJ3tS3/13N9s9+1QFXB4FFuommj+tHJPhQ==, - } - engines: { node: ">= 18" } + '@matrix-org/matrix-sdk-crypto-wasm@18.0.0': + resolution: {integrity: sha512-88+n+dvxLI1cjS10UIlKXVYK7TGWbpAnnaDC9fow7ch/hCvdu3dFhJ3tS3/13N9s9+1QFXB4FFuommj+tHJPhQ==} + engines: {node: '>= 18'} - "@mdx-js/react@3.1.1": - resolution: - { - integrity: sha512-f++rKLQgUVYDAtECQ6fn/is15GkEH9+nZPM3MS0RcxVqoTfawHvDlSCH7JbMhAM6uJ32v3eXLvLmLvjGu7PTQw==, - } + '@mdx-js/react@3.1.1': + resolution: {integrity: sha512-f++rKLQgUVYDAtECQ6fn/is15GkEH9+nZPM3MS0RcxVqoTfawHvDlSCH7JbMhAM6uJ32v3eXLvLmLvjGu7PTQw==} peerDependencies: - "@types/react": ">=16" - react: ">=16" + '@types/react': '>=16' + react: '>=16' - "@mediapipe/tasks-vision@0.10.34": - resolution: - { - integrity: sha512-KFGyhDsjJ+9WUMcMfjTOpcEp3LJNS3KwC7BfvKrCYELn/7G/5kmwnU7z6Spps+iWQoTGL8xW8i68r65OTa3DwA==, - } + '@mediapipe/tasks-vision@0.10.34': + resolution: {integrity: sha512-KFGyhDsjJ+9WUMcMfjTOpcEp3LJNS3KwC7BfvKrCYELn/7G/5kmwnU7z6Spps+iWQoTGL8xW8i68r65OTa3DwA==} - "@napi-rs/wasm-runtime@1.1.4": - resolution: - { - integrity: sha512-3NQNNgA1YSlJb/kMH1ildASP9HW7/7kYnRI2szWJaofaS1hWmbGI4H+d3+22aGzXXN9IJ+n+GiFVcGipJP18ow==, - } + '@napi-rs/wasm-runtime@1.1.4': + resolution: {integrity: sha512-3NQNNgA1YSlJb/kMH1ildASP9HW7/7kYnRI2szWJaofaS1hWmbGI4H+d3+22aGzXXN9IJ+n+GiFVcGipJP18ow==} peerDependencies: - "@emnapi/core": ^1.7.1 - "@emnapi/runtime": ^1.7.1 + '@emnapi/core': ^1.7.1 + '@emnapi/runtime': ^1.7.1 - "@nicolo-ribaudo/eslint-scope-5-internals@5.1.1-v1": - resolution: - { - integrity: sha512-54/JRvkLIzzDWshCWfuhadfrfZVPiElY8Fcgmg1HroEly/EDSszzhBAsarCux+D/kOslTRquNzuyGSmUSTTHGg==, - } + '@nicolo-ribaudo/eslint-scope-5-internals@5.1.1-v1': + resolution: {integrity: sha512-54/JRvkLIzzDWshCWfuhadfrfZVPiElY8Fcgmg1HroEly/EDSszzhBAsarCux+D/kOslTRquNzuyGSmUSTTHGg==} - "@nodelib/fs.scandir@2.1.5": - resolution: - { - integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==, - } - engines: { node: ">= 8" } + '@nodelib/fs.scandir@2.1.5': + resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} + engines: {node: '>= 8'} - "@nodelib/fs.stat@2.0.5": - resolution: - { - integrity: sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==, - } - engines: { node: ">= 8" } + '@nodelib/fs.stat@2.0.5': + resolution: {integrity: sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==} + engines: {node: '>= 8'} - "@nodelib/fs.walk@1.2.8": - resolution: - { - integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==, - } - engines: { node: ">= 8" } + '@nodelib/fs.walk@1.2.8': + resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==} + engines: {node: '>= 8'} - "@octokit/auth-token@4.0.0": - resolution: - { - integrity: sha512-tY/msAuJo6ARbK6SPIxZrPBms3xPbfwBrulZe0Wtr/DIY9lje2HeV1uoebShn6mx7SjCHif6EjMvoREj+gZ+SA==, - } - engines: { node: ">= 18" } + '@octokit/auth-token@4.0.0': + resolution: {integrity: sha512-tY/msAuJo6ARbK6SPIxZrPBms3xPbfwBrulZe0Wtr/DIY9lje2HeV1uoebShn6mx7SjCHif6EjMvoREj+gZ+SA==} + engines: {node: '>= 18'} - "@octokit/core@5.2.2": - resolution: - { - integrity: sha512-/g2d4sW9nUDJOMz3mabVQvOGhVa4e/BN/Um7yca9Bb2XTzPPnfTWHWQg+IsEYO7M3Vx+EXvaM/I2pJWIMun1bg==, - } - engines: { node: ">= 18" } + '@octokit/core@5.2.2': + resolution: {integrity: sha512-/g2d4sW9nUDJOMz3mabVQvOGhVa4e/BN/Um7yca9Bb2XTzPPnfTWHWQg+IsEYO7M3Vx+EXvaM/I2pJWIMun1bg==} + engines: {node: '>= 18'} - "@octokit/endpoint@9.0.6": - resolution: - { - integrity: sha512-H1fNTMA57HbkFESSt3Y9+FBICv+0jFceJFPWDePYlR/iMGrwM5ph+Dd4XRQs+8X+PUFURLQgX9ChPfhJ/1uNQw==, - } - engines: { node: ">= 18" } + '@octokit/endpoint@9.0.6': + resolution: {integrity: sha512-H1fNTMA57HbkFESSt3Y9+FBICv+0jFceJFPWDePYlR/iMGrwM5ph+Dd4XRQs+8X+PUFURLQgX9ChPfhJ/1uNQw==} + engines: {node: '>= 18'} - "@octokit/graphql@7.1.1": - resolution: - { - integrity: sha512-3mkDltSfcDUoa176nlGoA32RGjeWjl3K7F/BwHwRMJUW/IteSa4bnSV8p2ThNkcIcZU2umkZWxwETSSCJf2Q7g==, - } - engines: { node: ">= 18" } + '@octokit/graphql@7.1.1': + resolution: {integrity: sha512-3mkDltSfcDUoa176nlGoA32RGjeWjl3K7F/BwHwRMJUW/IteSa4bnSV8p2ThNkcIcZU2umkZWxwETSSCJf2Q7g==} + engines: {node: '>= 18'} - "@octokit/openapi-types@20.0.0": - resolution: - { - integrity: sha512-EtqRBEjp1dL/15V7WiX5LJMIxxkdiGJnabzYx5Apx4FkQIFgAfKumXeYAqqJCj1s+BMX4cPFIFC4OLCR6stlnA==, - } + '@octokit/openapi-types@20.0.0': + resolution: {integrity: sha512-EtqRBEjp1dL/15V7WiX5LJMIxxkdiGJnabzYx5Apx4FkQIFgAfKumXeYAqqJCj1s+BMX4cPFIFC4OLCR6stlnA==} - "@octokit/openapi-types@24.2.0": - resolution: - { - integrity: sha512-9sIH3nSUttelJSXUrmGzl7QUBFul0/mB8HRYl3fOlgHbIWG+WnYDXU3v/2zMtAvuzZ/ed00Ei6on975FhBfzrg==, - } + '@octokit/openapi-types@24.2.0': + resolution: {integrity: sha512-9sIH3nSUttelJSXUrmGzl7QUBFul0/mB8HRYl3fOlgHbIWG+WnYDXU3v/2zMtAvuzZ/ed00Ei6on975FhBfzrg==} - "@octokit/plugin-paginate-rest@9.2.2": - resolution: - { - integrity: sha512-u3KYkGF7GcZnSD/3UP0S7K5XUFT2FkOQdcfXZGZQPGv3lm4F2Xbf71lvjldr8c1H3nNbF+33cLEkWYbokGWqiQ==, - } - engines: { node: ">= 18" } + '@octokit/plugin-paginate-rest@9.2.2': + resolution: {integrity: sha512-u3KYkGF7GcZnSD/3UP0S7K5XUFT2FkOQdcfXZGZQPGv3lm4F2Xbf71lvjldr8c1H3nNbF+33cLEkWYbokGWqiQ==} + engines: {node: '>= 18'} peerDependencies: - "@octokit/core": "5" + '@octokit/core': '5' - "@octokit/plugin-rest-endpoint-methods@10.4.1": - resolution: - { - integrity: sha512-xV1b+ceKV9KytQe3zCVqjg+8GTGfDYwaT1ATU5isiUyVtlVAO3HNdzpS4sr4GBx4hxQ46s7ITtZrAsxG22+rVg==, - } - engines: { node: ">= 18" } + '@octokit/plugin-rest-endpoint-methods@10.4.1': + resolution: {integrity: sha512-xV1b+ceKV9KytQe3zCVqjg+8GTGfDYwaT1ATU5isiUyVtlVAO3HNdzpS4sr4GBx4hxQ46s7ITtZrAsxG22+rVg==} + engines: {node: '>= 18'} peerDependencies: - "@octokit/core": "5" + '@octokit/core': '5' - "@octokit/request-error@5.1.1": - resolution: - { - integrity: sha512-v9iyEQJH6ZntoENr9/yXxjuezh4My67CBSu9r6Ve/05Iu5gNgnisNWOsoJHTP6k0Rr0+HQIpnH+kyammu90q/g==, - } - engines: { node: ">= 18" } + '@octokit/request-error@5.1.1': + resolution: {integrity: sha512-v9iyEQJH6ZntoENr9/yXxjuezh4My67CBSu9r6Ve/05Iu5gNgnisNWOsoJHTP6k0Rr0+HQIpnH+kyammu90q/g==} + engines: {node: '>= 18'} - "@octokit/request@8.4.1": - resolution: - { - integrity: sha512-qnB2+SY3hkCmBxZsR/MPCybNmbJe4KAlfWErXq+rBKkQJlbjdJeS85VI9r8UqeLYLvnAenU8Q1okM/0MBsAGXw==, - } - engines: { node: ">= 18" } + '@octokit/request@8.4.1': + resolution: {integrity: sha512-qnB2+SY3hkCmBxZsR/MPCybNmbJe4KAlfWErXq+rBKkQJlbjdJeS85VI9r8UqeLYLvnAenU8Q1okM/0MBsAGXw==} + engines: {node: '>= 18'} - "@octokit/types@12.6.0": - resolution: - { - integrity: sha512-1rhSOfRa6H9w4YwK0yrf5faDaDTb+yLyBUKOCV4xtCDB5VmIPqd/v9yr9o6SAzOAlRxMiRiCic6JVM1/kunVkw==, - } + '@octokit/types@12.6.0': + resolution: {integrity: sha512-1rhSOfRa6H9w4YwK0yrf5faDaDTb+yLyBUKOCV4xtCDB5VmIPqd/v9yr9o6SAzOAlRxMiRiCic6JVM1/kunVkw==} - "@octokit/types@13.10.0": - resolution: - { - integrity: sha512-ifLaO34EbbPj0Xgro4G5lP5asESjwHracYJvVaPIyXMuiuXLlhic3S47cBdTb+jfODkTE5YtGCLt3Ay3+J97sA==, - } + '@octokit/types@13.10.0': + resolution: {integrity: sha512-ifLaO34EbbPj0Xgro4G5lP5asESjwHracYJvVaPIyXMuiuXLlhic3S47cBdTb+jfODkTE5YtGCLt3Ay3+J97sA==} - "@oxc-project/types@0.124.0": - resolution: - { - integrity: sha512-VBFWMTBvHxS11Z5Lvlr3IWgrwhMTXV+Md+EQF0Xf60+wAdsGFTBx7X7K/hP4pi8N7dcm1RvcHwDxZ16Qx8keUg==, - } + '@oxc-project/types@0.124.0': + resolution: {integrity: sha512-VBFWMTBvHxS11Z5Lvlr3IWgrwhMTXV+Md+EQF0Xf60+wAdsGFTBx7X7K/hP4pi8N7dcm1RvcHwDxZ16Qx8keUg==} - "@oxc-resolver/binding-android-arm-eabi@11.19.1": - resolution: - { - integrity: sha512-aUs47y+xyXHUKlbhqHUjBABjvycq6YSD7bpxSW7vplUmdzAlJ93yXY6ZR0c1o1x5A/QKbENCvs3+NlY8IpIVzg==, - } + '@oxc-resolver/binding-android-arm-eabi@11.19.1': + resolution: {integrity: sha512-aUs47y+xyXHUKlbhqHUjBABjvycq6YSD7bpxSW7vplUmdzAlJ93yXY6ZR0c1o1x5A/QKbENCvs3+NlY8IpIVzg==} cpu: [arm] os: [android] - "@oxc-resolver/binding-android-arm64@11.19.1": - resolution: - { - integrity: sha512-oolbkRX+m7Pq2LNjr/kKgYeC7bRDMVTWPgxBGMjSpZi/+UskVo4jsMU3MLheZV55jL6c3rNelPl4oD60ggYmqA==, - } + '@oxc-resolver/binding-android-arm64@11.19.1': + resolution: {integrity: sha512-oolbkRX+m7Pq2LNjr/kKgYeC7bRDMVTWPgxBGMjSpZi/+UskVo4jsMU3MLheZV55jL6c3rNelPl4oD60ggYmqA==} cpu: [arm64] os: [android] - "@oxc-resolver/binding-darwin-arm64@11.19.1": - resolution: - { - integrity: sha512-nUC6d2i3R5B12sUW4O646qD5cnMXf2oBGPLIIeaRfU9doJRORAbE2SGv4eW6rMqhD+G7nf2Y8TTJTLiiO3Q/dQ==, - } + '@oxc-resolver/binding-darwin-arm64@11.19.1': + resolution: {integrity: sha512-nUC6d2i3R5B12sUW4O646qD5cnMXf2oBGPLIIeaRfU9doJRORAbE2SGv4eW6rMqhD+G7nf2Y8TTJTLiiO3Q/dQ==} cpu: [arm64] os: [darwin] - "@oxc-resolver/binding-darwin-x64@11.19.1": - resolution: - { - integrity: sha512-cV50vE5+uAgNcFa3QY1JOeKDSkM/9ReIcc/9wn4TavhW/itkDGrXhw9jaKnkQnGbjJ198Yh5nbX/Gr2mr4Z5jQ==, - } + '@oxc-resolver/binding-darwin-x64@11.19.1': + resolution: {integrity: sha512-cV50vE5+uAgNcFa3QY1JOeKDSkM/9ReIcc/9wn4TavhW/itkDGrXhw9jaKnkQnGbjJ198Yh5nbX/Gr2mr4Z5jQ==} cpu: [x64] os: [darwin] - "@oxc-resolver/binding-freebsd-x64@11.19.1": - resolution: - { - integrity: sha512-xZOQiYGFxtk48PBKff+Zwoym7ScPAIVp4c14lfLxizO2LTTTJe5sx9vQNGrBymrf/vatSPNMD4FgsaaRigPkqw==, - } + '@oxc-resolver/binding-freebsd-x64@11.19.1': + resolution: {integrity: sha512-xZOQiYGFxtk48PBKff+Zwoym7ScPAIVp4c14lfLxizO2LTTTJe5sx9vQNGrBymrf/vatSPNMD4FgsaaRigPkqw==} cpu: [x64] os: [freebsd] - "@oxc-resolver/binding-linux-arm-gnueabihf@11.19.1": - resolution: - { - integrity: sha512-lXZYWAC6kaGe/ky2su94e9jN9t6M0/6c+GrSlCqL//XO1cxi5lpAhnJYdyrKfm0ZEr/c7RNyAx3P7FSBcBd5+A==, - } + '@oxc-resolver/binding-linux-arm-gnueabihf@11.19.1': + resolution: {integrity: sha512-lXZYWAC6kaGe/ky2su94e9jN9t6M0/6c+GrSlCqL//XO1cxi5lpAhnJYdyrKfm0ZEr/c7RNyAx3P7FSBcBd5+A==} cpu: [arm] os: [linux] - "@oxc-resolver/binding-linux-arm-musleabihf@11.19.1": - resolution: - { - integrity: sha512-veG1kKsuK5+t2IsO9q0DErYVSw2azvCVvWHnfTOS73WE0STdLLB7Q1bB9WR+yHPQM76ASkFyRbogWo1GR1+WbQ==, - } + '@oxc-resolver/binding-linux-arm-musleabihf@11.19.1': + resolution: {integrity: sha512-veG1kKsuK5+t2IsO9q0DErYVSw2azvCVvWHnfTOS73WE0STdLLB7Q1bB9WR+yHPQM76ASkFyRbogWo1GR1+WbQ==} cpu: [arm] os: [linux] - "@oxc-resolver/binding-linux-arm64-gnu@11.19.1": - resolution: - { - integrity: sha512-heV2+jmXyYnUrpUXSPugqWDRpnsQcDm2AX4wzTuvgdlZfoNYO0O3W2AVpJYaDn9AG4JdM6Kxom8+foE7/BcSig==, - } + '@oxc-resolver/binding-linux-arm64-gnu@11.19.1': + resolution: {integrity: sha512-heV2+jmXyYnUrpUXSPugqWDRpnsQcDm2AX4wzTuvgdlZfoNYO0O3W2AVpJYaDn9AG4JdM6Kxom8+foE7/BcSig==} cpu: [arm64] os: [linux] - "@oxc-resolver/binding-linux-arm64-musl@11.19.1": - resolution: - { - integrity: sha512-jvo2Pjs1c9KPxMuMPIeQsgu0mOJF9rEb3y3TdpsrqwxRM+AN6/nDDwv45n5ZrUnQMsdBy5gIabioMKnQfWo9ew==, - } + '@oxc-resolver/binding-linux-arm64-musl@11.19.1': + resolution: {integrity: sha512-jvo2Pjs1c9KPxMuMPIeQsgu0mOJF9rEb3y3TdpsrqwxRM+AN6/nDDwv45n5ZrUnQMsdBy5gIabioMKnQfWo9ew==} cpu: [arm64] os: [linux] - "@oxc-resolver/binding-linux-ppc64-gnu@11.19.1": - resolution: - { - integrity: sha512-vLmdNxWCdN7Uo5suays6A/+ywBby2PWBBPXctWPg5V0+eVuzsJxgAn6MMB4mPlshskYbppjpN2Zg83ArHze9gQ==, - } + '@oxc-resolver/binding-linux-ppc64-gnu@11.19.1': + resolution: {integrity: sha512-vLmdNxWCdN7Uo5suays6A/+ywBby2PWBBPXctWPg5V0+eVuzsJxgAn6MMB4mPlshskYbppjpN2Zg83ArHze9gQ==} cpu: [ppc64] os: [linux] - "@oxc-resolver/binding-linux-riscv64-gnu@11.19.1": - resolution: - { - integrity: sha512-/b+WgR+VTSBxzgOhDO7TlMXC1ufPIMR6Vj1zN+/x+MnyXGW7prTLzU9eW85Aj7Th7CCEG9ArCbTeqxCzFWdg2w==, - } + '@oxc-resolver/binding-linux-riscv64-gnu@11.19.1': + resolution: {integrity: sha512-/b+WgR+VTSBxzgOhDO7TlMXC1ufPIMR6Vj1zN+/x+MnyXGW7prTLzU9eW85Aj7Th7CCEG9ArCbTeqxCzFWdg2w==} cpu: [riscv64] os: [linux] - "@oxc-resolver/binding-linux-riscv64-musl@11.19.1": - resolution: - { - integrity: sha512-YlRdeWb9j42p29ROh+h4eg/OQ3dTJlpHSa+84pUM9+p6i3djtPz1q55yLJhgW9XfDch7FN1pQ/Vd6YP+xfRIuw==, - } + '@oxc-resolver/binding-linux-riscv64-musl@11.19.1': + resolution: {integrity: sha512-YlRdeWb9j42p29ROh+h4eg/OQ3dTJlpHSa+84pUM9+p6i3djtPz1q55yLJhgW9XfDch7FN1pQ/Vd6YP+xfRIuw==} cpu: [riscv64] os: [linux] - "@oxc-resolver/binding-linux-s390x-gnu@11.19.1": - resolution: - { - integrity: sha512-EDpafVOQWF8/MJynsjOGFThcqhRHy417sRyLfQmeiamJ8qVhSKAn2Dn2VVKUGCjVB9C46VGjhNo7nOPUi1x6uA==, - } + '@oxc-resolver/binding-linux-s390x-gnu@11.19.1': + resolution: {integrity: sha512-EDpafVOQWF8/MJynsjOGFThcqhRHy417sRyLfQmeiamJ8qVhSKAn2Dn2VVKUGCjVB9C46VGjhNo7nOPUi1x6uA==} cpu: [s390x] os: [linux] - "@oxc-resolver/binding-linux-x64-gnu@11.19.1": - resolution: - { - integrity: sha512-NxjZe+rqWhr+RT8/Ik+5ptA3oz7tUw361Wa5RWQXKnfqwSSHdHyrw6IdcTfYuml9dM856AlKWZIUXDmA9kkiBQ==, - } + '@oxc-resolver/binding-linux-x64-gnu@11.19.1': + resolution: {integrity: sha512-NxjZe+rqWhr+RT8/Ik+5ptA3oz7tUw361Wa5RWQXKnfqwSSHdHyrw6IdcTfYuml9dM856AlKWZIUXDmA9kkiBQ==} cpu: [x64] os: [linux] - "@oxc-resolver/binding-linux-x64-musl@11.19.1": - resolution: - { - integrity: sha512-cM/hQwsO3ReJg5kR+SpI69DMfvNCp+A/eVR4b4YClE5bVZwz8rh2Nh05InhwI5HR/9cArbEkzMjcKgTHS6UaNw==, - } + '@oxc-resolver/binding-linux-x64-musl@11.19.1': + resolution: {integrity: sha512-cM/hQwsO3ReJg5kR+SpI69DMfvNCp+A/eVR4b4YClE5bVZwz8rh2Nh05InhwI5HR/9cArbEkzMjcKgTHS6UaNw==} cpu: [x64] os: [linux] - "@oxc-resolver/binding-openharmony-arm64@11.19.1": - resolution: - { - integrity: sha512-QF080IowFB0+9Rh6RcD19bdgh49BpQHUW5TajG1qvWHvmrQznTZZjYlgE2ltLXyKY+qs4F/v5xuX1XS7Is+3qA==, - } + '@oxc-resolver/binding-openharmony-arm64@11.19.1': + resolution: {integrity: sha512-QF080IowFB0+9Rh6RcD19bdgh49BpQHUW5TajG1qvWHvmrQznTZZjYlgE2ltLXyKY+qs4F/v5xuX1XS7Is+3qA==} cpu: [arm64] os: [openharmony] - "@oxc-resolver/binding-wasm32-wasi@11.19.1": - resolution: - { - integrity: sha512-w8UCKhX826cP/ZLokXDS6+milN8y4X7zidsAttEdWlVoamTNf6lhBJldaWr3ukTDiye7s4HRcuPEPOXNC432Vg==, - } - engines: { node: ">=14.0.0" } + '@oxc-resolver/binding-wasm32-wasi@11.19.1': + resolution: {integrity: sha512-w8UCKhX826cP/ZLokXDS6+milN8y4X7zidsAttEdWlVoamTNf6lhBJldaWr3ukTDiye7s4HRcuPEPOXNC432Vg==} + engines: {node: '>=14.0.0'} cpu: [wasm32] - "@oxc-resolver/binding-win32-arm64-msvc@11.19.1": - resolution: - { - integrity: sha512-nJ4AsUVZrVKwnU/QRdzPCCrO0TrabBqgJ8pJhXITdZGYOV28TIYystV1VFLbQ7DtAcaBHpocT5/ZJnF78YJPtQ==, - } + '@oxc-resolver/binding-win32-arm64-msvc@11.19.1': + resolution: {integrity: sha512-nJ4AsUVZrVKwnU/QRdzPCCrO0TrabBqgJ8pJhXITdZGYOV28TIYystV1VFLbQ7DtAcaBHpocT5/ZJnF78YJPtQ==} cpu: [arm64] os: [win32] - "@oxc-resolver/binding-win32-ia32-msvc@11.19.1": - resolution: - { - integrity: sha512-EW+ND5q2Tl+a3pH81l1QbfgbF3HmqgwLfDfVithRFheac8OTcnbXt/JxqD2GbDkb7xYEqy1zNaVFRr3oeG8npA==, - } + '@oxc-resolver/binding-win32-ia32-msvc@11.19.1': + resolution: {integrity: sha512-EW+ND5q2Tl+a3pH81l1QbfgbF3HmqgwLfDfVithRFheac8OTcnbXt/JxqD2GbDkb7xYEqy1zNaVFRr3oeG8npA==} cpu: [ia32] os: [win32] - "@oxc-resolver/binding-win32-x64-msvc@11.19.1": - resolution: - { - integrity: sha512-6hIU3RQu45B+VNTY4Ru8ppFwjVS/S5qwYyGhBotmjxfEKk41I2DlGtRfGJndZ5+6lneE2pwloqunlOyZuX/XAw==, - } + '@oxc-resolver/binding-win32-x64-msvc@11.19.1': + resolution: {integrity: sha512-6hIU3RQu45B+VNTY4Ru8ppFwjVS/S5qwYyGhBotmjxfEKk41I2DlGtRfGJndZ5+6lneE2pwloqunlOyZuX/XAw==} cpu: [x64] os: [win32] - "@parcel/watcher-android-arm64@2.5.6": - resolution: - { - integrity: sha512-YQxSS34tPF/6ZG7r/Ih9xy+kP/WwediEUsqmtf0cuCV5TPPKw/PQHRhueUo6JdeFJaqV3pyjm0GdYjZotbRt/A==, - } - engines: { node: ">= 10.0.0" } + '@parcel/watcher-android-arm64@2.5.6': + resolution: {integrity: sha512-YQxSS34tPF/6ZG7r/Ih9xy+kP/WwediEUsqmtf0cuCV5TPPKw/PQHRhueUo6JdeFJaqV3pyjm0GdYjZotbRt/A==} + engines: {node: '>= 10.0.0'} cpu: [arm64] os: [android] - "@parcel/watcher-darwin-arm64@2.5.6": - resolution: - { - integrity: sha512-Z2ZdrnwyXvvvdtRHLmM4knydIdU9adO3D4n/0cVipF3rRiwP+3/sfzpAwA/qKFL6i1ModaabkU7IbpeMBgiVEA==, - } - engines: { node: ">= 10.0.0" } + '@parcel/watcher-darwin-arm64@2.5.6': + resolution: {integrity: sha512-Z2ZdrnwyXvvvdtRHLmM4knydIdU9adO3D4n/0cVipF3rRiwP+3/sfzpAwA/qKFL6i1ModaabkU7IbpeMBgiVEA==} + engines: {node: '>= 10.0.0'} cpu: [arm64] os: [darwin] - "@parcel/watcher-darwin-x64@2.5.6": - resolution: - { - integrity: sha512-HgvOf3W9dhithcwOWX9uDZyn1lW9R+7tPZ4sug+NGrGIo4Rk1hAXLEbcH1TQSqxts0NYXXlOWqVpvS1SFS4fRg==, - } - engines: { node: ">= 10.0.0" } + '@parcel/watcher-darwin-x64@2.5.6': + resolution: {integrity: sha512-HgvOf3W9dhithcwOWX9uDZyn1lW9R+7tPZ4sug+NGrGIo4Rk1hAXLEbcH1TQSqxts0NYXXlOWqVpvS1SFS4fRg==} + engines: {node: '>= 10.0.0'} cpu: [x64] os: [darwin] - "@parcel/watcher-freebsd-x64@2.5.6": - resolution: - { - integrity: sha512-vJVi8yd/qzJxEKHkeemh7w3YAn6RJCtYlE4HPMoVnCpIXEzSrxErBW5SJBgKLbXU3WdIpkjBTeUNtyBVn8TRng==, - } - engines: { node: ">= 10.0.0" } + '@parcel/watcher-freebsd-x64@2.5.6': + resolution: {integrity: sha512-vJVi8yd/qzJxEKHkeemh7w3YAn6RJCtYlE4HPMoVnCpIXEzSrxErBW5SJBgKLbXU3WdIpkjBTeUNtyBVn8TRng==} + engines: {node: '>= 10.0.0'} cpu: [x64] os: [freebsd] - "@parcel/watcher-linux-arm-glibc@2.5.6": - resolution: - { - integrity: sha512-9JiYfB6h6BgV50CCfasfLf/uvOcJskMSwcdH1PHH9rvS1IrNy8zad6IUVPVUfmXr+u+Km9IxcfMLzgdOudz9EQ==, - } - engines: { node: ">= 10.0.0" } + '@parcel/watcher-linux-arm-glibc@2.5.6': + resolution: {integrity: sha512-9JiYfB6h6BgV50CCfasfLf/uvOcJskMSwcdH1PHH9rvS1IrNy8zad6IUVPVUfmXr+u+Km9IxcfMLzgdOudz9EQ==} + engines: {node: '>= 10.0.0'} cpu: [arm] os: [linux] - "@parcel/watcher-linux-arm-musl@2.5.6": - resolution: - { - integrity: sha512-Ve3gUCG57nuUUSyjBq/MAM0CzArtuIOxsBdQ+ftz6ho8n7s1i9E1Nmk/xmP323r2YL0SONs1EuwqBp2u1k5fxg==, - } - engines: { node: ">= 10.0.0" } + '@parcel/watcher-linux-arm-musl@2.5.6': + resolution: {integrity: sha512-Ve3gUCG57nuUUSyjBq/MAM0CzArtuIOxsBdQ+ftz6ho8n7s1i9E1Nmk/xmP323r2YL0SONs1EuwqBp2u1k5fxg==} + engines: {node: '>= 10.0.0'} cpu: [arm] os: [linux] - "@parcel/watcher-linux-arm64-glibc@2.5.6": - resolution: - { - integrity: sha512-f2g/DT3NhGPdBmMWYoxixqYr3v/UXcmLOYy16Bx0TM20Tchduwr4EaCbmxh1321TABqPGDpS8D/ggOTaljijOA==, - } - engines: { node: ">= 10.0.0" } + '@parcel/watcher-linux-arm64-glibc@2.5.6': + resolution: {integrity: sha512-f2g/DT3NhGPdBmMWYoxixqYr3v/UXcmLOYy16Bx0TM20Tchduwr4EaCbmxh1321TABqPGDpS8D/ggOTaljijOA==} + engines: {node: '>= 10.0.0'} cpu: [arm64] os: [linux] - "@parcel/watcher-linux-arm64-musl@2.5.6": - resolution: - { - integrity: sha512-qb6naMDGlbCwdhLj6hgoVKJl2odL34z2sqkC7Z6kzir8b5W65WYDpLB6R06KabvZdgoHI/zxke4b3zR0wAbDTA==, - } - engines: { node: ">= 10.0.0" } + '@parcel/watcher-linux-arm64-musl@2.5.6': + resolution: {integrity: sha512-qb6naMDGlbCwdhLj6hgoVKJl2odL34z2sqkC7Z6kzir8b5W65WYDpLB6R06KabvZdgoHI/zxke4b3zR0wAbDTA==} + engines: {node: '>= 10.0.0'} cpu: [arm64] os: [linux] - "@parcel/watcher-linux-x64-glibc@2.5.6": - resolution: - { - integrity: sha512-kbT5wvNQlx7NaGjzPFu8nVIW1rWqV780O7ZtkjuWaPUgpv2NMFpjYERVi0UYj1msZNyCzGlaCWEtzc+exjMGbQ==, - } - engines: { node: ">= 10.0.0" } + '@parcel/watcher-linux-x64-glibc@2.5.6': + resolution: {integrity: sha512-kbT5wvNQlx7NaGjzPFu8nVIW1rWqV780O7ZtkjuWaPUgpv2NMFpjYERVi0UYj1msZNyCzGlaCWEtzc+exjMGbQ==} + engines: {node: '>= 10.0.0'} cpu: [x64] os: [linux] - "@parcel/watcher-linux-x64-musl@2.5.6": - resolution: - { - integrity: sha512-1JRFeC+h7RdXwldHzTsmdtYR/Ku8SylLgTU/reMuqdVD7CtLwf0VR1FqeprZ0eHQkO0vqsbvFLXUmYm/uNKJBg==, - } - engines: { node: ">= 10.0.0" } + '@parcel/watcher-linux-x64-musl@2.5.6': + resolution: {integrity: sha512-1JRFeC+h7RdXwldHzTsmdtYR/Ku8SylLgTU/reMuqdVD7CtLwf0VR1FqeprZ0eHQkO0vqsbvFLXUmYm/uNKJBg==} + engines: {node: '>= 10.0.0'} cpu: [x64] os: [linux] - "@parcel/watcher-win32-arm64@2.5.6": - resolution: - { - integrity: sha512-3ukyebjc6eGlw9yRt678DxVF7rjXatWiHvTXqphZLvo7aC5NdEgFufVwjFfY51ijYEWpXbqF5jtrK275z52D4Q==, - } - engines: { node: ">= 10.0.0" } + '@parcel/watcher-win32-arm64@2.5.6': + resolution: {integrity: sha512-3ukyebjc6eGlw9yRt678DxVF7rjXatWiHvTXqphZLvo7aC5NdEgFufVwjFfY51ijYEWpXbqF5jtrK275z52D4Q==} + engines: {node: '>= 10.0.0'} cpu: [arm64] os: [win32] - "@parcel/watcher-win32-ia32@2.5.6": - resolution: - { - integrity: sha512-k35yLp1ZMwwee3Ez/pxBi5cf4AoBKYXj00CZ80jUz5h8prpiaQsiRPKQMxoLstNuqe2vR4RNPEAEcjEFzhEz/g==, - } - engines: { node: ">= 10.0.0" } + '@parcel/watcher-win32-ia32@2.5.6': + resolution: {integrity: sha512-k35yLp1ZMwwee3Ez/pxBi5cf4AoBKYXj00CZ80jUz5h8prpiaQsiRPKQMxoLstNuqe2vR4RNPEAEcjEFzhEz/g==} + engines: {node: '>= 10.0.0'} cpu: [ia32] os: [win32] - "@parcel/watcher-win32-x64@2.5.6": - resolution: - { - integrity: sha512-hbQlYcCq5dlAX9Qx+kFb0FHue6vbjlf0FrNzSKdYK2APUf7tGfGxQCk2ihEREmbR6ZMc0MVAD5RIX/41gpUzTw==, - } - engines: { node: ">= 10.0.0" } + '@parcel/watcher-win32-x64@2.5.6': + resolution: {integrity: sha512-hbQlYcCq5dlAX9Qx+kFb0FHue6vbjlf0FrNzSKdYK2APUf7tGfGxQCk2ihEREmbR6ZMc0MVAD5RIX/41gpUzTw==} + engines: {node: '>= 10.0.0'} cpu: [x64] os: [win32] - "@parcel/watcher@2.5.6": - resolution: - { - integrity: sha512-tmmZ3lQxAe/k/+rNnXQRawJ4NjxO2hqiOLTHvWchtGZULp4RyFeh6aU4XdOYBFe2KE1oShQTv4AblOs2iOrNnQ==, - } - engines: { node: ">= 10.0.0" } + '@parcel/watcher@2.5.6': + resolution: {integrity: sha512-tmmZ3lQxAe/k/+rNnXQRawJ4NjxO2hqiOLTHvWchtGZULp4RyFeh6aU4XdOYBFe2KE1oShQTv4AblOs2iOrNnQ==} + engines: {node: '>= 10.0.0'} - "@pkgjs/parseargs@0.11.0": - resolution: - { - integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==, - } - engines: { node: ">=14" } + '@pkgjs/parseargs@0.11.0': + resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==} + engines: {node: '>=14'} - "@playwright/test@1.59.1": - resolution: - { - integrity: sha512-PG6q63nQg5c9rIi4/Z5lR5IVF7yU5MqmKaPOe0HSc0O2cX1fPi96sUQu5j7eo4gKCkB2AnNGoWt7y4/Xx3Kcqg==, - } - engines: { node: ">=18" } + '@playwright/test@1.59.1': + resolution: {integrity: sha512-PG6q63nQg5c9rIi4/Z5lR5IVF7yU5MqmKaPOe0HSc0O2cX1fPi96sUQu5j7eo4gKCkB2AnNGoWt7y4/Xx3Kcqg==} + engines: {node: '>=18'} hasBin: true - "@radix-ui/number@1.1.1": - resolution: - { - integrity: sha512-MkKCwxlXTgz6CFoJx3pCwn07GKp36+aZyu/u2Ln2VrA5DcdyCZkASEDBTd8x5whTQQL5CiYf4prXKLcgQdv29g==, - } + '@radix-ui/number@1.1.1': + resolution: {integrity: sha512-MkKCwxlXTgz6CFoJx3pCwn07GKp36+aZyu/u2Ln2VrA5DcdyCZkASEDBTd8x5whTQQL5CiYf4prXKLcgQdv29g==} - "@radix-ui/primitive@1.1.3": - resolution: - { - integrity: sha512-JTF99U/6XIjCBo0wqkU5sK10glYe27MRRsfwoiq5zzOEZLHU3A3KCMa5X/azekYRCJ0HlwI0crAXS/5dEHTzDg==, - } + '@radix-ui/primitive@1.1.3': + resolution: {integrity: sha512-JTF99U/6XIjCBo0wqkU5sK10glYe27MRRsfwoiq5zzOEZLHU3A3KCMa5X/azekYRCJ0HlwI0crAXS/5dEHTzDg==} - "@radix-ui/react-arrow@1.1.7": - resolution: - { - integrity: sha512-F+M1tLhO+mlQaOWspE8Wstg+z6PwxwRd8oQ8IXceWz92kfAmalTRf0EjrouQeo7QssEPfCn05B4Ihs1K9WQ/7w==, - } + '@radix-ui/react-arrow@1.1.7': + resolution: {integrity: sha512-F+M1tLhO+mlQaOWspE8Wstg+z6PwxwRd8oQ8IXceWz92kfAmalTRf0EjrouQeo7QssEPfCn05B4Ihs1K9WQ/7w==} peerDependencies: - "@types/react": "*" - "@types/react-dom": "*" + '@types/react': '*' + '@types/react-dom': '*' react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc peerDependenciesMeta: - "@types/react": + '@types/react': optional: true - "@types/react-dom": + '@types/react-dom': optional: true - "@radix-ui/react-collection@1.1.7": - resolution: - { - integrity: sha512-Fh9rGN0MoI4ZFUNyfFVNU4y9LUz93u9/0K+yLgA2bwRojxM8JU1DyvvMBabnZPBgMWREAJvU2jjVzq+LrFUglw==, - } + '@radix-ui/react-collection@1.1.7': + resolution: {integrity: sha512-Fh9rGN0MoI4ZFUNyfFVNU4y9LUz93u9/0K+yLgA2bwRojxM8JU1DyvvMBabnZPBgMWREAJvU2jjVzq+LrFUglw==} peerDependencies: - "@types/react": "*" - "@types/react-dom": "*" + '@types/react': '*' + '@types/react-dom': '*' react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc peerDependenciesMeta: - "@types/react": + '@types/react': optional: true - "@types/react-dom": + '@types/react-dom': optional: true - "@radix-ui/react-compose-refs@1.1.2": - resolution: - { - integrity: sha512-z4eqJvfiNnFMHIIvXP3CY57y2WJs5g2v3X0zm9mEJkrkNv4rDxu+sg9Jh8EkXyeqBkB7SOcboo9dMVqhyrACIg==, - } + '@radix-ui/react-compose-refs@1.1.2': + resolution: {integrity: sha512-z4eqJvfiNnFMHIIvXP3CY57y2WJs5g2v3X0zm9mEJkrkNv4rDxu+sg9Jh8EkXyeqBkB7SOcboo9dMVqhyrACIg==} peerDependencies: - "@types/react": "*" + '@types/react': '*' react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc peerDependenciesMeta: - "@types/react": + '@types/react': optional: true - "@radix-ui/react-context-menu@2.2.16": - resolution: - { - integrity: sha512-O8morBEW+HsVG28gYDZPTrT9UUovQUlJue5YO836tiTJhuIWBm/zQHc7j388sHWtdH/xUZurK9olD2+pcqx5ww==, - } + '@radix-ui/react-context-menu@2.2.16': + resolution: {integrity: sha512-O8morBEW+HsVG28gYDZPTrT9UUovQUlJue5YO836tiTJhuIWBm/zQHc7j388sHWtdH/xUZurK9olD2+pcqx5ww==} peerDependencies: - "@types/react": "*" - "@types/react-dom": "*" + '@types/react': '*' + '@types/react-dom': '*' react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc peerDependenciesMeta: - "@types/react": + '@types/react': optional: true - "@types/react-dom": + '@types/react-dom': optional: true - "@radix-ui/react-context@1.1.2": - resolution: - { - integrity: sha512-jCi/QKUM2r1Ju5a3J64TH2A5SpKAgh0LpknyqdQ4m6DCV0xJ2HG1xARRwNGPQfi1SLdLWZ1OJz6F4OMBBNiGJA==, - } + '@radix-ui/react-context@1.1.2': + resolution: {integrity: sha512-jCi/QKUM2r1Ju5a3J64TH2A5SpKAgh0LpknyqdQ4m6DCV0xJ2HG1xARRwNGPQfi1SLdLWZ1OJz6F4OMBBNiGJA==} peerDependencies: - "@types/react": "*" + '@types/react': '*' react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc peerDependenciesMeta: - "@types/react": + '@types/react': optional: true - "@radix-ui/react-context@1.1.3": - resolution: - { - integrity: sha512-ieIFACdMpYfMEjF0rEf5KLvfVyIkOz6PDGyNnP+u+4xQ6jny3VCgA4OgXOwNx2aUkxn8zx9fiVcM8CfFYv9Lxw==, - } + '@radix-ui/react-context@1.1.3': + resolution: {integrity: sha512-ieIFACdMpYfMEjF0rEf5KLvfVyIkOz6PDGyNnP+u+4xQ6jny3VCgA4OgXOwNx2aUkxn8zx9fiVcM8CfFYv9Lxw==} peerDependencies: - "@types/react": "*" + '@types/react': '*' react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc peerDependenciesMeta: - "@types/react": + '@types/react': optional: true - "@radix-ui/react-dialog@1.1.15": - resolution: - { - integrity: sha512-TCglVRtzlffRNxRMEyR36DGBLJpeusFcgMVD9PZEzAKnUs1lKCgX5u9BmC2Yg+LL9MgZDugFFs1Vl+Jp4t/PGw==, - } + '@radix-ui/react-dialog@1.1.15': + resolution: {integrity: sha512-TCglVRtzlffRNxRMEyR36DGBLJpeusFcgMVD9PZEzAKnUs1lKCgX5u9BmC2Yg+LL9MgZDugFFs1Vl+Jp4t/PGw==} peerDependencies: - "@types/react": "*" - "@types/react-dom": "*" + '@types/react': '*' + '@types/react-dom': '*' react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc peerDependenciesMeta: - "@types/react": + '@types/react': optional: true - "@types/react-dom": + '@types/react-dom': optional: true - "@radix-ui/react-direction@1.1.1": - resolution: - { - integrity: sha512-1UEWRX6jnOA2y4H5WczZ44gOOjTEmlqv1uNW4GAJEO5+bauCBhv8snY65Iw5/VOS/ghKN9gr2KjnLKxrsvoMVw==, - } + '@radix-ui/react-direction@1.1.1': + resolution: {integrity: sha512-1UEWRX6jnOA2y4H5WczZ44gOOjTEmlqv1uNW4GAJEO5+bauCBhv8snY65Iw5/VOS/ghKN9gr2KjnLKxrsvoMVw==} peerDependencies: - "@types/react": "*" + '@types/react': '*' react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc peerDependenciesMeta: - "@types/react": + '@types/react': optional: true - "@radix-ui/react-dismissable-layer@1.1.11": - resolution: - { - integrity: sha512-Nqcp+t5cTB8BinFkZgXiMJniQH0PsUt2k51FUhbdfeKvc4ACcG2uQniY/8+h1Yv6Kza4Q7lD7PQV0z0oicE0Mg==, - } + '@radix-ui/react-dismissable-layer@1.1.11': + resolution: {integrity: sha512-Nqcp+t5cTB8BinFkZgXiMJniQH0PsUt2k51FUhbdfeKvc4ACcG2uQniY/8+h1Yv6Kza4Q7lD7PQV0z0oicE0Mg==} peerDependencies: - "@types/react": "*" - "@types/react-dom": "*" + '@types/react': '*' + '@types/react-dom': '*' react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc peerDependenciesMeta: - "@types/react": + '@types/react': optional: true - "@types/react-dom": + '@types/react-dom': optional: true - "@radix-ui/react-dropdown-menu@2.1.16": - resolution: - { - integrity: sha512-1PLGQEynI/3OX/ftV54COn+3Sud/Mn8vALg2rWnBLnRaGtJDduNW/22XjlGgPdpcIbiQxjKtb7BkcjP00nqfJw==, - } + '@radix-ui/react-dropdown-menu@2.1.16': + resolution: {integrity: sha512-1PLGQEynI/3OX/ftV54COn+3Sud/Mn8vALg2rWnBLnRaGtJDduNW/22XjlGgPdpcIbiQxjKtb7BkcjP00nqfJw==} peerDependencies: - "@types/react": "*" - "@types/react-dom": "*" + '@types/react': '*' + '@types/react-dom': '*' react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc peerDependenciesMeta: - "@types/react": + '@types/react': optional: true - "@types/react-dom": + '@types/react-dom': optional: true - "@radix-ui/react-focus-guards@1.1.3": - resolution: - { - integrity: sha512-0rFg/Rj2Q62NCm62jZw0QX7a3sz6QCQU0LpZdNrJX8byRGaGVTqbrW9jAoIAHyMQqsNpeZ81YgSizOt5WXq0Pw==, - } + '@radix-ui/react-focus-guards@1.1.3': + resolution: {integrity: sha512-0rFg/Rj2Q62NCm62jZw0QX7a3sz6QCQU0LpZdNrJX8byRGaGVTqbrW9jAoIAHyMQqsNpeZ81YgSizOt5WXq0Pw==} peerDependencies: - "@types/react": "*" + '@types/react': '*' react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc peerDependenciesMeta: - "@types/react": + '@types/react': optional: true - "@radix-ui/react-focus-scope@1.1.7": - resolution: - { - integrity: sha512-t2ODlkXBQyn7jkl6TNaw/MtVEVvIGelJDCG41Okq/KwUsJBwQ4XVZsHAVUkK4mBv3ewiAS3PGuUWuY2BoK4ZUw==, - } + '@radix-ui/react-focus-scope@1.1.7': + resolution: {integrity: sha512-t2ODlkXBQyn7jkl6TNaw/MtVEVvIGelJDCG41Okq/KwUsJBwQ4XVZsHAVUkK4mBv3ewiAS3PGuUWuY2BoK4ZUw==} peerDependencies: - "@types/react": "*" - "@types/react-dom": "*" + '@types/react': '*' + '@types/react-dom': '*' react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc peerDependenciesMeta: - "@types/react": + '@types/react': optional: true - "@types/react-dom": + '@types/react-dom': optional: true - "@radix-ui/react-form@0.1.8": - resolution: - { - integrity: sha512-QM70k4Zwjttifr5a4sZFts9fn8FzHYvQ5PiB19O2HsYibaHSVt9fH9rzB0XZo/YcM+b7t/p7lYCT/F5eOeF5yQ==, - } + '@radix-ui/react-form@0.1.8': + resolution: {integrity: sha512-QM70k4Zwjttifr5a4sZFts9fn8FzHYvQ5PiB19O2HsYibaHSVt9fH9rzB0XZo/YcM+b7t/p7lYCT/F5eOeF5yQ==} peerDependencies: - "@types/react": "*" - "@types/react-dom": "*" + '@types/react': '*' + '@types/react-dom': '*' react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc peerDependenciesMeta: - "@types/react": + '@types/react': optional: true - "@types/react-dom": + '@types/react-dom': optional: true - "@radix-ui/react-id@1.1.1": - resolution: - { - integrity: sha512-kGkGegYIdQsOb4XjsfM97rXsiHaBwco+hFI66oO4s9LU+PLAC5oJ7khdOVFxkhsmlbpUqDAvXw11CluXP+jkHg==, - } + '@radix-ui/react-id@1.1.1': + resolution: {integrity: sha512-kGkGegYIdQsOb4XjsfM97rXsiHaBwco+hFI66oO4s9LU+PLAC5oJ7khdOVFxkhsmlbpUqDAvXw11CluXP+jkHg==} peerDependencies: - "@types/react": "*" + '@types/react': '*' react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc peerDependenciesMeta: - "@types/react": + '@types/react': optional: true - "@radix-ui/react-label@2.1.7": - resolution: - { - integrity: sha512-YT1GqPSL8kJn20djelMX7/cTRp/Y9w5IZHvfxQTVHrOqa2yMl7i/UfMqKRU5V7mEyKTrUVgJXhNQPVCG8PBLoQ==, - } + '@radix-ui/react-label@2.1.7': + resolution: {integrity: sha512-YT1GqPSL8kJn20djelMX7/cTRp/Y9w5IZHvfxQTVHrOqa2yMl7i/UfMqKRU5V7mEyKTrUVgJXhNQPVCG8PBLoQ==} peerDependencies: - "@types/react": "*" - "@types/react-dom": "*" + '@types/react': '*' + '@types/react-dom': '*' react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc peerDependenciesMeta: - "@types/react": + '@types/react': optional: true - "@types/react-dom": + '@types/react-dom': optional: true - "@radix-ui/react-menu@2.1.16": - resolution: - { - integrity: sha512-72F2T+PLlphrqLcAotYPp0uJMr5SjP5SL01wfEspJbru5Zs5vQaSHb4VB3ZMJPimgHHCHG7gMOeOB9H3Hdmtxg==, - } + '@radix-ui/react-menu@2.1.16': + resolution: {integrity: sha512-72F2T+PLlphrqLcAotYPp0uJMr5SjP5SL01wfEspJbru5Zs5vQaSHb4VB3ZMJPimgHHCHG7gMOeOB9H3Hdmtxg==} peerDependencies: - "@types/react": "*" - "@types/react-dom": "*" + '@types/react': '*' + '@types/react-dom': '*' react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc peerDependenciesMeta: - "@types/react": + '@types/react': optional: true - "@types/react-dom": + '@types/react-dom': optional: true - "@radix-ui/react-popper@1.2.8": - resolution: - { - integrity: sha512-0NJQ4LFFUuWkE7Oxf0htBKS6zLkkjBH+hM1uk7Ng705ReR8m/uelduy1DBo0PyBXPKVnBA6YBlU94MBGXrSBCw==, - } + '@radix-ui/react-popper@1.2.8': + resolution: {integrity: sha512-0NJQ4LFFUuWkE7Oxf0htBKS6zLkkjBH+hM1uk7Ng705ReR8m/uelduy1DBo0PyBXPKVnBA6YBlU94MBGXrSBCw==} peerDependencies: - "@types/react": "*" - "@types/react-dom": "*" + '@types/react': '*' + '@types/react-dom': '*' react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc peerDependenciesMeta: - "@types/react": + '@types/react': optional: true - "@types/react-dom": + '@types/react-dom': optional: true - "@radix-ui/react-portal@1.1.9": - resolution: - { - integrity: sha512-bpIxvq03if6UNwXZ+HTK71JLh4APvnXntDc6XOX8UVq4XQOVl7lwok0AvIl+b8zgCw3fSaVTZMpAPPagXbKmHQ==, - } + '@radix-ui/react-portal@1.1.9': + resolution: {integrity: sha512-bpIxvq03if6UNwXZ+HTK71JLh4APvnXntDc6XOX8UVq4XQOVl7lwok0AvIl+b8zgCw3fSaVTZMpAPPagXbKmHQ==} peerDependencies: - "@types/react": "*" - "@types/react-dom": "*" + '@types/react': '*' + '@types/react-dom': '*' react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc peerDependenciesMeta: - "@types/react": + '@types/react': optional: true - "@types/react-dom": + '@types/react-dom': optional: true - "@radix-ui/react-presence@1.1.5": - resolution: - { - integrity: sha512-/jfEwNDdQVBCNvjkGit4h6pMOzq8bHkopq458dPt2lMjx+eBQUohZNG9A7DtO/O5ukSbxuaNGXMjHicgwy6rQQ==, - } + '@radix-ui/react-presence@1.1.5': + resolution: {integrity: sha512-/jfEwNDdQVBCNvjkGit4h6pMOzq8bHkopq458dPt2lMjx+eBQUohZNG9A7DtO/O5ukSbxuaNGXMjHicgwy6rQQ==} peerDependencies: - "@types/react": "*" - "@types/react-dom": "*" + '@types/react': '*' + '@types/react-dom': '*' react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc peerDependenciesMeta: - "@types/react": + '@types/react': optional: true - "@types/react-dom": + '@types/react-dom': optional: true - "@radix-ui/react-primitive@2.1.3": - resolution: - { - integrity: sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ==, - } + '@radix-ui/react-primitive@2.1.3': + resolution: {integrity: sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ==} peerDependencies: - "@types/react": "*" - "@types/react-dom": "*" + '@types/react': '*' + '@types/react-dom': '*' react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc peerDependenciesMeta: - "@types/react": + '@types/react': optional: true - "@types/react-dom": + '@types/react-dom': optional: true - "@radix-ui/react-primitive@2.1.4": - resolution: - { - integrity: sha512-9hQc4+GNVtJAIEPEqlYqW5RiYdrr8ea5XQ0ZOnD6fgru+83kqT15mq2OCcbe8KnjRZl5vF3ks69AKz3kh1jrhg==, - } + '@radix-ui/react-primitive@2.1.4': + resolution: {integrity: sha512-9hQc4+GNVtJAIEPEqlYqW5RiYdrr8ea5XQ0ZOnD6fgru+83kqT15mq2OCcbe8KnjRZl5vF3ks69AKz3kh1jrhg==} peerDependencies: - "@types/react": "*" - "@types/react-dom": "*" + '@types/react': '*' + '@types/react-dom': '*' react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc peerDependenciesMeta: - "@types/react": + '@types/react': optional: true - "@types/react-dom": + '@types/react-dom': optional: true - "@radix-ui/react-progress@1.1.8": - resolution: - { - integrity: sha512-+gISHcSPUJ7ktBy9RnTqbdKW78bcGke3t6taawyZ71pio1JewwGSJizycs7rLhGTvMJYCQB1DBK4KQsxs7U8dA==, - } + '@radix-ui/react-progress@1.1.8': + resolution: {integrity: sha512-+gISHcSPUJ7ktBy9RnTqbdKW78bcGke3t6taawyZ71pio1JewwGSJizycs7rLhGTvMJYCQB1DBK4KQsxs7U8dA==} peerDependencies: - "@types/react": "*" - "@types/react-dom": "*" + '@types/react': '*' + '@types/react-dom': '*' react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc peerDependenciesMeta: - "@types/react": + '@types/react': optional: true - "@types/react-dom": + '@types/react-dom': optional: true - "@radix-ui/react-roving-focus@1.1.11": - resolution: - { - integrity: sha512-7A6S9jSgm/S+7MdtNDSb+IU859vQqJ/QAtcYQcfFC6W8RS4IxIZDldLR0xqCFZ6DCyrQLjLPsxtTNch5jVA4lA==, - } + '@radix-ui/react-roving-focus@1.1.11': + resolution: {integrity: sha512-7A6S9jSgm/S+7MdtNDSb+IU859vQqJ/QAtcYQcfFC6W8RS4IxIZDldLR0xqCFZ6DCyrQLjLPsxtTNch5jVA4lA==} peerDependencies: - "@types/react": "*" - "@types/react-dom": "*" + '@types/react': '*' + '@types/react-dom': '*' react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc peerDependenciesMeta: - "@types/react": + '@types/react': optional: true - "@types/react-dom": + '@types/react-dom': optional: true - "@radix-ui/react-separator@1.1.8": - resolution: - { - integrity: sha512-sDvqVY4itsKwwSMEe0jtKgfTh+72Sy3gPmQpjqcQneqQ4PFmr/1I0YA+2/puilhggCe2gJcx5EBAYFkWkdpa5g==, - } + '@radix-ui/react-separator@1.1.8': + resolution: {integrity: sha512-sDvqVY4itsKwwSMEe0jtKgfTh+72Sy3gPmQpjqcQneqQ4PFmr/1I0YA+2/puilhggCe2gJcx5EBAYFkWkdpa5g==} peerDependencies: - "@types/react": "*" - "@types/react-dom": "*" + '@types/react': '*' + '@types/react-dom': '*' react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc peerDependenciesMeta: - "@types/react": + '@types/react': optional: true - "@types/react-dom": + '@types/react-dom': optional: true - "@radix-ui/react-slider@1.3.6": - resolution: - { - integrity: sha512-JPYb1GuM1bxfjMRlNLE+BcmBC8onfCi60Blk7OBqi2MLTFdS+8401U4uFjnwkOr49BLmXxLC6JHkvAsx5OJvHw==, - } + '@radix-ui/react-slider@1.3.6': + resolution: {integrity: sha512-JPYb1GuM1bxfjMRlNLE+BcmBC8onfCi60Blk7OBqi2MLTFdS+8401U4uFjnwkOr49BLmXxLC6JHkvAsx5OJvHw==} peerDependencies: - "@types/react": "*" - "@types/react-dom": "*" + '@types/react': '*' + '@types/react-dom': '*' react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc peerDependenciesMeta: - "@types/react": + '@types/react': optional: true - "@types/react-dom": + '@types/react-dom': optional: true - "@radix-ui/react-slot@1.2.3": - resolution: - { - integrity: sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A==, - } + '@radix-ui/react-slot@1.2.3': + resolution: {integrity: sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A==} peerDependencies: - "@types/react": "*" + '@types/react': '*' react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc peerDependenciesMeta: - "@types/react": + '@types/react': optional: true - "@radix-ui/react-slot@1.2.4": - resolution: - { - integrity: sha512-Jl+bCv8HxKnlTLVrcDE8zTMJ09R9/ukw4qBs/oZClOfoQk/cOTbDn+NceXfV7j09YPVQUryJPHurafcSg6EVKA==, - } + '@radix-ui/react-slot@1.2.4': + resolution: {integrity: sha512-Jl+bCv8HxKnlTLVrcDE8zTMJ09R9/ukw4qBs/oZClOfoQk/cOTbDn+NceXfV7j09YPVQUryJPHurafcSg6EVKA==} peerDependencies: - "@types/react": "*" + '@types/react': '*' react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc peerDependenciesMeta: - "@types/react": + '@types/react': optional: true - "@radix-ui/react-use-callback-ref@1.1.1": - resolution: - { - integrity: sha512-FkBMwD+qbGQeMu1cOHnuGB6x4yzPjho8ap5WtbEJ26umhgqVXbhekKUQO+hZEL1vU92a3wHwdp0HAcqAUF5iDg==, - } + '@radix-ui/react-use-callback-ref@1.1.1': + resolution: {integrity: sha512-FkBMwD+qbGQeMu1cOHnuGB6x4yzPjho8ap5WtbEJ26umhgqVXbhekKUQO+hZEL1vU92a3wHwdp0HAcqAUF5iDg==} peerDependencies: - "@types/react": "*" + '@types/react': '*' react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc peerDependenciesMeta: - "@types/react": + '@types/react': optional: true - "@radix-ui/react-use-controllable-state@1.2.2": - resolution: - { - integrity: sha512-BjasUjixPFdS+NKkypcyyN5Pmg83Olst0+c6vGov0diwTEo6mgdqVR6hxcEgFuh4QrAs7Rc+9KuGJ9TVCj0Zzg==, - } + '@radix-ui/react-use-controllable-state@1.2.2': + resolution: {integrity: sha512-BjasUjixPFdS+NKkypcyyN5Pmg83Olst0+c6vGov0diwTEo6mgdqVR6hxcEgFuh4QrAs7Rc+9KuGJ9TVCj0Zzg==} peerDependencies: - "@types/react": "*" + '@types/react': '*' react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc peerDependenciesMeta: - "@types/react": + '@types/react': optional: true - "@radix-ui/react-use-effect-event@0.0.2": - resolution: - { - integrity: sha512-Qp8WbZOBe+blgpuUT+lw2xheLP8q0oatc9UpmiemEICxGvFLYmHm9QowVZGHtJlGbS6A6yJ3iViad/2cVjnOiA==, - } + '@radix-ui/react-use-effect-event@0.0.2': + resolution: {integrity: sha512-Qp8WbZOBe+blgpuUT+lw2xheLP8q0oatc9UpmiemEICxGvFLYmHm9QowVZGHtJlGbS6A6yJ3iViad/2cVjnOiA==} peerDependencies: - "@types/react": "*" + '@types/react': '*' react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc peerDependenciesMeta: - "@types/react": + '@types/react': optional: true - "@radix-ui/react-use-escape-keydown@1.1.1": - resolution: - { - integrity: sha512-Il0+boE7w/XebUHyBjroE+DbByORGR9KKmITzbR7MyQ4akpORYP/ZmbhAr0DG7RmmBqoOnZdy2QlvajJ2QA59g==, - } + '@radix-ui/react-use-escape-keydown@1.1.1': + resolution: {integrity: sha512-Il0+boE7w/XebUHyBjroE+DbByORGR9KKmITzbR7MyQ4akpORYP/ZmbhAr0DG7RmmBqoOnZdy2QlvajJ2QA59g==} peerDependencies: - "@types/react": "*" + '@types/react': '*' react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc peerDependenciesMeta: - "@types/react": + '@types/react': optional: true - "@radix-ui/react-use-layout-effect@1.1.1": - resolution: - { - integrity: sha512-RbJRS4UWQFkzHTTwVymMTUv8EqYhOp8dOOviLj2ugtTiXRaRQS7GLGxZTLL1jWhMeoSCf5zmcZkqTl9IiYfXcQ==, - } + '@radix-ui/react-use-layout-effect@1.1.1': + resolution: {integrity: sha512-RbJRS4UWQFkzHTTwVymMTUv8EqYhOp8dOOviLj2ugtTiXRaRQS7GLGxZTLL1jWhMeoSCf5zmcZkqTl9IiYfXcQ==} peerDependencies: - "@types/react": "*" + '@types/react': '*' react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc peerDependenciesMeta: - "@types/react": + '@types/react': optional: true - "@radix-ui/react-use-previous@1.1.1": - resolution: - { - integrity: sha512-2dHfToCj/pzca2Ck724OZ5L0EVrr3eHRNsG/b3xQJLA2hZpVCS99bLAX+hm1IHXDEnzU6by5z/5MIY794/a8NQ==, - } + '@radix-ui/react-use-previous@1.1.1': + resolution: {integrity: sha512-2dHfToCj/pzca2Ck724OZ5L0EVrr3eHRNsG/b3xQJLA2hZpVCS99bLAX+hm1IHXDEnzU6by5z/5MIY794/a8NQ==} peerDependencies: - "@types/react": "*" + '@types/react': '*' react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc peerDependenciesMeta: - "@types/react": + '@types/react': optional: true - "@radix-ui/react-use-rect@1.1.1": - resolution: - { - integrity: sha512-QTYuDesS0VtuHNNvMh+CjlKJ4LJickCMUAqjlE3+j8w+RlRpwyX3apEQKGFzbZGdo7XNG1tXa+bQqIE7HIXT2w==, - } + '@radix-ui/react-use-rect@1.1.1': + resolution: {integrity: sha512-QTYuDesS0VtuHNNvMh+CjlKJ4LJickCMUAqjlE3+j8w+RlRpwyX3apEQKGFzbZGdo7XNG1tXa+bQqIE7HIXT2w==} peerDependencies: - "@types/react": "*" + '@types/react': '*' react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc peerDependenciesMeta: - "@types/react": + '@types/react': optional: true - "@radix-ui/react-use-size@1.1.1": - resolution: - { - integrity: sha512-ewrXRDTAqAXlkl6t/fkXWNAhFX9I+CkKlw6zjEwk86RSPKwZr3xpBRso655aqYafwtnbpHLj6toFzmd6xdVptQ==, - } + '@radix-ui/react-use-size@1.1.1': + resolution: {integrity: sha512-ewrXRDTAqAXlkl6t/fkXWNAhFX9I+CkKlw6zjEwk86RSPKwZr3xpBRso655aqYafwtnbpHLj6toFzmd6xdVptQ==} peerDependencies: - "@types/react": "*" + '@types/react': '*' react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc peerDependenciesMeta: - "@types/react": + '@types/react': optional: true - "@radix-ui/react-visually-hidden@1.2.4": - resolution: - { - integrity: sha512-kaeiyGCe844dkb9AVF+rb4yTyb1LiLN/e3es3nLiRyN4dC8AduBYPMnnNlDjX2VDOcvDEiPnRNMJeWCfsX0txg==, - } + '@radix-ui/react-visually-hidden@1.2.4': + resolution: {integrity: sha512-kaeiyGCe844dkb9AVF+rb4yTyb1LiLN/e3es3nLiRyN4dC8AduBYPMnnNlDjX2VDOcvDEiPnRNMJeWCfsX0txg==} peerDependencies: - "@types/react": "*" - "@types/react-dom": "*" + '@types/react': '*' + '@types/react-dom': '*' react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc peerDependenciesMeta: - "@types/react": + '@types/react': optional: true - "@types/react-dom": + '@types/react-dom': optional: true - "@radix-ui/rect@1.1.1": - resolution: - { - integrity: sha512-HPwpGIzkl28mWyZqG52jiqDJ12waP11Pa1lGoiyUkIEuMLBP0oeK/C89esbXrxsky5we7dfd8U58nm0SgAWpVw==, - } + '@radix-ui/rect@1.1.1': + resolution: {integrity: sha512-HPwpGIzkl28mWyZqG52jiqDJ12waP11Pa1lGoiyUkIEuMLBP0oeK/C89esbXrxsky5we7dfd8U58nm0SgAWpVw==} - "@react-spring/animated@10.0.3": - resolution: - { - integrity: sha512-7MrxADV3vaUADn2V9iYhaIL6iOWRx9nCJjYrsk2AHD2kwPr6fg7Pt0v+deX5RnCDmCKNnD6W5fasiyM8D+wzJQ==, - } + '@react-spring/animated@10.0.3': + resolution: {integrity: sha512-7MrxADV3vaUADn2V9iYhaIL6iOWRx9nCJjYrsk2AHD2kwPr6fg7Pt0v+deX5RnCDmCKNnD6W5fasiyM8D+wzJQ==} peerDependencies: react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 - "@react-spring/core@10.0.3": - resolution: - { - integrity: sha512-D4DwNO68oohDf/0HG2G0Uragzb9IA1oXblxrd6MZAcBcUQG2EHUWXewjdECMPLNmQvlYVyyBRH6gPxXM5DX7DQ==, - } + '@react-spring/core@10.0.3': + resolution: {integrity: sha512-D4DwNO68oohDf/0HG2G0Uragzb9IA1oXblxrd6MZAcBcUQG2EHUWXewjdECMPLNmQvlYVyyBRH6gPxXM5DX7DQ==} peerDependencies: react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 - "@react-spring/rafz@10.0.3": - resolution: - { - integrity: sha512-Ri2/xqt8OnQ2iFKkxKMSF4Nqv0LSWnxXT4jXFzBDsHgeeH/cHxTLupAWUwmV9hAGgmEhBmh5aONtj3J6R/18wg==, - } + '@react-spring/rafz@10.0.3': + resolution: {integrity: sha512-Ri2/xqt8OnQ2iFKkxKMSF4Nqv0LSWnxXT4jXFzBDsHgeeH/cHxTLupAWUwmV9hAGgmEhBmh5aONtj3J6R/18wg==} - "@react-spring/shared@10.0.3": - resolution: - { - integrity: sha512-geCal66nrkaQzUVhPkGomylo+Jpd5VPK8tPMEDevQEfNSWAQP15swHm+MCRG4wVQrQlTi9lOzKzpRoTL3CA84Q==, - } + '@react-spring/shared@10.0.3': + resolution: {integrity: sha512-geCal66nrkaQzUVhPkGomylo+Jpd5VPK8tPMEDevQEfNSWAQP15swHm+MCRG4wVQrQlTi9lOzKzpRoTL3CA84Q==} peerDependencies: react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 - "@react-spring/types@10.0.3": - resolution: - { - integrity: sha512-H5Ixkd2OuSIgHtxuHLTt7aJYfhMXKXT/rK32HPD/kSrOB6q6ooeiWAXkBy7L8F3ZxdkBb9ini9zP9UwnEFzWgQ==, - } + '@react-spring/types@10.0.3': + resolution: {integrity: sha512-H5Ixkd2OuSIgHtxuHLTt7aJYfhMXKXT/rK32HPD/kSrOB6q6ooeiWAXkBy7L8F3ZxdkBb9ini9zP9UwnEFzWgQ==} - "@react-spring/web@10.0.3": - resolution: - { - integrity: sha512-ndU+kWY81rHsT7gTFtCJ6mrVhaJ6grFmgTnENipzmKqot4HGf5smPNK+cZZJqoGeDsj9ZsiWPW4geT/NyD484A==, - } + '@react-spring/web@10.0.3': + resolution: {integrity: sha512-ndU+kWY81rHsT7gTFtCJ6mrVhaJ6grFmgTnENipzmKqot4HGf5smPNK+cZZJqoGeDsj9ZsiWPW4geT/NyD484A==} peerDependencies: react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 - "@rolldown/binding-android-arm64@1.0.0-rc.15": - resolution: - { - integrity: sha512-YYe6aWruPZDtHNpwu7+qAHEMbQ/yRl6atqb/AhznLTnD3UY99Q1jE7ihLSahNWkF4EqRPVC4SiR4O0UkLK02tA==, - } - engines: { node: ^20.19.0 || >=22.12.0 } + '@rolldown/binding-android-arm64@1.0.0-rc.15': + resolution: {integrity: sha512-YYe6aWruPZDtHNpwu7+qAHEMbQ/yRl6atqb/AhznLTnD3UY99Q1jE7ihLSahNWkF4EqRPVC4SiR4O0UkLK02tA==} + engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [android] - "@rolldown/binding-darwin-arm64@1.0.0-rc.15": - resolution: - { - integrity: sha512-oArR/ig8wNTPYsXL+Mzhs0oxhxfuHRfG7Ikw7jXsw8mYOtk71W0OkF2VEVh699pdmzjPQsTjlD1JIOoHkLP1Fg==, - } - engines: { node: ^20.19.0 || >=22.12.0 } + '@rolldown/binding-darwin-arm64@1.0.0-rc.15': + resolution: {integrity: sha512-oArR/ig8wNTPYsXL+Mzhs0oxhxfuHRfG7Ikw7jXsw8mYOtk71W0OkF2VEVh699pdmzjPQsTjlD1JIOoHkLP1Fg==} + engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [darwin] - "@rolldown/binding-darwin-x64@1.0.0-rc.15": - resolution: - { - integrity: sha512-YzeVqOqjPYvUbJSWJ4EDL8ahbmsIXQpgL3JVipmN+MX0XnXMeWomLN3Fb+nwCmP/jfyqte5I3XRSm7OfQrbyxw==, - } - engines: { node: ^20.19.0 || >=22.12.0 } + '@rolldown/binding-darwin-x64@1.0.0-rc.15': + resolution: {integrity: sha512-YzeVqOqjPYvUbJSWJ4EDL8ahbmsIXQpgL3JVipmN+MX0XnXMeWomLN3Fb+nwCmP/jfyqte5I3XRSm7OfQrbyxw==} + engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [darwin] - "@rolldown/binding-freebsd-x64@1.0.0-rc.15": - resolution: - { - integrity: sha512-9Erhx956jeQ0nNTyif1+QWAXDRD38ZNjr//bSHrt6wDwB+QkAfl2q6Mn1k6OBPerznjRmbM10lgRb1Pli4xZPw==, - } - engines: { node: ^20.19.0 || >=22.12.0 } + '@rolldown/binding-freebsd-x64@1.0.0-rc.15': + resolution: {integrity: sha512-9Erhx956jeQ0nNTyif1+QWAXDRD38ZNjr//bSHrt6wDwB+QkAfl2q6Mn1k6OBPerznjRmbM10lgRb1Pli4xZPw==} + engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [freebsd] - "@rolldown/binding-linux-arm-gnueabihf@1.0.0-rc.15": - resolution: - { - integrity: sha512-cVwk0w8QbZJGTnP/AHQBs5yNwmpgGYStL88t4UIaqcvYJWBfS0s3oqVLZPwsPU6M0zlW4GqjP0Zq5MnAGwFeGA==, - } - engines: { node: ^20.19.0 || >=22.12.0 } + '@rolldown/binding-linux-arm-gnueabihf@1.0.0-rc.15': + resolution: {integrity: sha512-cVwk0w8QbZJGTnP/AHQBs5yNwmpgGYStL88t4UIaqcvYJWBfS0s3oqVLZPwsPU6M0zlW4GqjP0Zq5MnAGwFeGA==} + engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm] os: [linux] - "@rolldown/binding-linux-arm64-gnu@1.0.0-rc.15": - resolution: - { - integrity: sha512-eBZ/u8iAK9SoHGanqe/jrPnY0JvBN6iXbVOsbO38mbz+ZJsaobExAm1Iu+rxa4S1l2FjG0qEZn4Rc6X8n+9M+w==, - } - engines: { node: ^20.19.0 || >=22.12.0 } + '@rolldown/binding-linux-arm64-gnu@1.0.0-rc.15': + resolution: {integrity: sha512-eBZ/u8iAK9SoHGanqe/jrPnY0JvBN6iXbVOsbO38mbz+ZJsaobExAm1Iu+rxa4S1l2FjG0qEZn4Rc6X8n+9M+w==} + engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [linux] - "@rolldown/binding-linux-arm64-musl@1.0.0-rc.15": - resolution: - { - integrity: sha512-ZvRYMGrAklV9PEkgt4LQM6MjQX2P58HPAuecwYObY2DhS2t35R0I810bKi0wmaYORt6m/2Sm+Z+nFgb0WhXNcQ==, - } - engines: { node: ^20.19.0 || >=22.12.0 } + '@rolldown/binding-linux-arm64-musl@1.0.0-rc.15': + resolution: {integrity: sha512-ZvRYMGrAklV9PEkgt4LQM6MjQX2P58HPAuecwYObY2DhS2t35R0I810bKi0wmaYORt6m/2Sm+Z+nFgb0WhXNcQ==} + engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [linux] - "@rolldown/binding-linux-ppc64-gnu@1.0.0-rc.15": - resolution: - { - integrity: sha512-VDpgGBzgfg5hLg+uBpCLoFG5kVvEyafmfxGUV0UHLcL5irxAK7PKNeC2MwClgk6ZAiNhmo9FLhRYgvMmedLtnQ==, - } - engines: { node: ^20.19.0 || >=22.12.0 } + '@rolldown/binding-linux-ppc64-gnu@1.0.0-rc.15': + resolution: {integrity: sha512-VDpgGBzgfg5hLg+uBpCLoFG5kVvEyafmfxGUV0UHLcL5irxAK7PKNeC2MwClgk6ZAiNhmo9FLhRYgvMmedLtnQ==} + engines: {node: ^20.19.0 || >=22.12.0} cpu: [ppc64] os: [linux] - "@rolldown/binding-linux-s390x-gnu@1.0.0-rc.15": - resolution: - { - integrity: sha512-y1uXY3qQWCzcPgRJATPSOUP4tCemh4uBdY7e3EZbVwCJTY3gLJWnQABgeUetvED+bt1FQ01OeZwvhLS2bpNrAQ==, - } - engines: { node: ^20.19.0 || >=22.12.0 } + '@rolldown/binding-linux-s390x-gnu@1.0.0-rc.15': + resolution: {integrity: sha512-y1uXY3qQWCzcPgRJATPSOUP4tCemh4uBdY7e3EZbVwCJTY3gLJWnQABgeUetvED+bt1FQ01OeZwvhLS2bpNrAQ==} + engines: {node: ^20.19.0 || >=22.12.0} cpu: [s390x] os: [linux] - "@rolldown/binding-linux-x64-gnu@1.0.0-rc.15": - resolution: - { - integrity: sha512-023bTPBod7J3Y/4fzAN6QtpkSABR0rigtrwaP+qSEabUh5zf6ELr9Nc7GujaROuPY3uwdSIXWrvhn1KxOvurWA==, - } - engines: { node: ^20.19.0 || >=22.12.0 } + '@rolldown/binding-linux-x64-gnu@1.0.0-rc.15': + resolution: {integrity: sha512-023bTPBod7J3Y/4fzAN6QtpkSABR0rigtrwaP+qSEabUh5zf6ELr9Nc7GujaROuPY3uwdSIXWrvhn1KxOvurWA==} + engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [linux] - "@rolldown/binding-linux-x64-musl@1.0.0-rc.15": - resolution: - { - integrity: sha512-witB2O0/hU4CgfOOKUoeFgQ4GktPi1eEbAhaLAIpgD6+ZnhcPkUtPsoKKHRzmOoWPZue46IThdSgdo4XneOLYw==, - } - engines: { node: ^20.19.0 || >=22.12.0 } + '@rolldown/binding-linux-x64-musl@1.0.0-rc.15': + resolution: {integrity: sha512-witB2O0/hU4CgfOOKUoeFgQ4GktPi1eEbAhaLAIpgD6+ZnhcPkUtPsoKKHRzmOoWPZue46IThdSgdo4XneOLYw==} + engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [linux] - "@rolldown/binding-openharmony-arm64@1.0.0-rc.15": - resolution: - { - integrity: sha512-UCL68NJ0Ud5zRipXZE9dF5PmirzJE4E4BCIOOssEnM7wLDsxjc6Qb0sGDxTNRTP53I6MZpygyCpY8Aa8sPfKPg==, - } - engines: { node: ^20.19.0 || >=22.12.0 } + '@rolldown/binding-openharmony-arm64@1.0.0-rc.15': + resolution: {integrity: sha512-UCL68NJ0Ud5zRipXZE9dF5PmirzJE4E4BCIOOssEnM7wLDsxjc6Qb0sGDxTNRTP53I6MZpygyCpY8Aa8sPfKPg==} + engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [openharmony] - "@rolldown/binding-wasm32-wasi@1.0.0-rc.15": - resolution: - { - integrity: sha512-ApLruZq/ig+nhaE7OJm4lDjayUnOHVUa77zGeqnqZ9pn0ovdVbbNPerVibLXDmWeUZXjIYIT8V3xkT58Rm9u5Q==, - } - engines: { node: ">=14.0.0" } + '@rolldown/binding-wasm32-wasi@1.0.0-rc.15': + resolution: {integrity: sha512-ApLruZq/ig+nhaE7OJm4lDjayUnOHVUa77zGeqnqZ9pn0ovdVbbNPerVibLXDmWeUZXjIYIT8V3xkT58Rm9u5Q==} + engines: {node: '>=14.0.0'} cpu: [wasm32] - "@rolldown/binding-win32-arm64-msvc@1.0.0-rc.15": - resolution: - { - integrity: sha512-KmoUoU7HnN+Si5YWJigfTws1jz1bKBYDQKdbLspz0UaqjjFkddHsqorgiW1mxcAj88lYUE6NC/zJNwT+SloqtA==, - } - engines: { node: ^20.19.0 || >=22.12.0 } + '@rolldown/binding-win32-arm64-msvc@1.0.0-rc.15': + resolution: {integrity: sha512-KmoUoU7HnN+Si5YWJigfTws1jz1bKBYDQKdbLspz0UaqjjFkddHsqorgiW1mxcAj88lYUE6NC/zJNwT+SloqtA==} + engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [win32] - "@rolldown/binding-win32-x64-msvc@1.0.0-rc.15": - resolution: - { - integrity: sha512-3P2A8L+x75qavWLe/Dll3EYBJLQmtkJN8rfh+U/eR3MqMgL/h98PhYI+JFfXuDPgPeCB7iZAKiqii5vqOvnA0g==, - } - engines: { node: ^20.19.0 || >=22.12.0 } + '@rolldown/binding-win32-x64-msvc@1.0.0-rc.15': + resolution: {integrity: sha512-3P2A8L+x75qavWLe/Dll3EYBJLQmtkJN8rfh+U/eR3MqMgL/h98PhYI+JFfXuDPgPeCB7iZAKiqii5vqOvnA0g==} + engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [win32] - "@rolldown/pluginutils@1.0.0-beta.27": - resolution: - { - integrity: sha512-+d0F4MKMCbeVUJwG96uQ4SgAznZNSq93I3V+9NHA4OpvqG8mRCpGdKmK8l/dl02h2CCDHwW2FqilnTyDcAnqjA==, - } + '@rolldown/pluginutils@1.0.0-beta.27': + resolution: {integrity: sha512-+d0F4MKMCbeVUJwG96uQ4SgAznZNSq93I3V+9NHA4OpvqG8mRCpGdKmK8l/dl02h2CCDHwW2FqilnTyDcAnqjA==} - "@rolldown/pluginutils@1.0.0-rc.15": - resolution: - { - integrity: sha512-UromN0peaE53IaBRe9W7CjrZgXl90fqGpK+mIZbA3qSTeYqg3pqpROBdIPvOG3F5ereDHNwoHBI2e50n1BDr1g==, - } + '@rolldown/pluginutils@1.0.0-rc.15': + resolution: {integrity: sha512-UromN0peaE53IaBRe9W7CjrZgXl90fqGpK+mIZbA3qSTeYqg3pqpROBdIPvOG3F5ereDHNwoHBI2e50n1BDr1g==} - "@rollup/plugin-inject@5.0.5": - resolution: - { - integrity: sha512-2+DEJbNBoPROPkgTDNe8/1YXWcqxbN5DTjASVIOx8HS+pITXushyNiBV56RB08zuptzz8gT3YfkqriTBVycepg==, - } - engines: { node: ">=14.0.0" } + '@rollup/plugin-inject@5.0.5': + resolution: {integrity: sha512-2+DEJbNBoPROPkgTDNe8/1YXWcqxbN5DTjASVIOx8HS+pITXushyNiBV56RB08zuptzz8gT3YfkqriTBVycepg==} + engines: {node: '>=14.0.0'} peerDependencies: rollup: ^1.20.0||^2.0.0||^3.0.0||^4.0.0 peerDependenciesMeta: rollup: optional: true - "@rollup/pluginutils@4.2.1": - resolution: - { - integrity: sha512-iKnFXr7NkdZAIHiIWE+BX5ULi/ucVFYWD6TbAV+rZctiRTY2PL6tsIKhoIOaoskiWAkgu+VsbXgUVDNLHf+InQ==, - } - engines: { node: ">= 8.0.0" } + '@rollup/pluginutils@4.2.1': + resolution: {integrity: sha512-iKnFXr7NkdZAIHiIWE+BX5ULi/ucVFYWD6TbAV+rZctiRTY2PL6tsIKhoIOaoskiWAkgu+VsbXgUVDNLHf+InQ==} + engines: {node: '>= 8.0.0'} - "@rollup/pluginutils@5.3.0": - resolution: - { - integrity: sha512-5EdhGZtnu3V88ces7s53hhfK5KSASnJZv8Lulpc04cWO3REESroJXg73DFsOmgbU2BhwV0E20bu2IDZb3VKW4Q==, - } - engines: { node: ">=14.0.0" } + '@rollup/pluginutils@5.3.0': + resolution: {integrity: sha512-5EdhGZtnu3V88ces7s53hhfK5KSASnJZv8Lulpc04cWO3REESroJXg73DFsOmgbU2BhwV0E20bu2IDZb3VKW4Q==} + engines: {node: '>=14.0.0'} peerDependencies: rollup: ^1.20.0||^2.0.0||^3.0.0||^4.0.0 peerDependenciesMeta: rollup: optional: true - "@rtsao/scc@1.1.0": - resolution: - { - integrity: sha512-zt6OdqaDoOnJ1ZYsCYGt9YmWzDXl4vQdKTyJev62gFhRGKdx7mcT54V9KIjg+d2wi9EXsPvAPKe7i7WjfVWB8g==, - } + '@rollup/rollup-android-arm-eabi@4.60.1': + resolution: {integrity: sha512-d6FinEBLdIiK+1uACUttJKfgZREXrF0Qc2SmLII7W2AD8FfiZ9Wjd+rD/iRuf5s5dWrr1GgwXCvPqOuDquOowA==} + cpu: [arm] + os: [android] - "@sentry-internal/browser-utils@8.55.1": - resolution: - { - integrity: sha512-SipXiwVhJrxzy3/4kf+YIFmpYlLKtGSRD+er7SBCcuSBtv31Fee8IXMDvk+bq24gRXxyjOLUmT//GGXjy2LL6w==, - } - engines: { node: ">=14.18" } + '@rollup/rollup-android-arm64@4.60.1': + resolution: {integrity: sha512-YjG/EwIDvvYI1YvYbHvDz/BYHtkY4ygUIXHnTdLhG+hKIQFBiosfWiACWortsKPKU/+dUwQQCKQM3qrDe8c9BA==} + cpu: [arm64] + os: [android] - "@sentry-internal/feedback@8.55.1": - resolution: - { - integrity: sha512-9iFHaT/ijtzB0ffZhXMnt2rPNIXO/dDiCL1G1Bc55rQMPXgawR9AIaAWciyqQjYcbL1DDOhWbzdVqB+kVs5gXw==, - } - engines: { node: ">=14.18" } - - "@sentry-internal/replay-canvas@8.55.1": - resolution: - { - integrity: sha512-2sKRu96Qe70y6TiYdYbwkhg4um2prgzH/ZJRItuoSEAjPjoFYYlP+1qjE2CcBw4RPS8/PimV7SFheSaeZs2GCw==, - } - engines: { node: ">=14.18" } - - "@sentry-internal/replay@8.55.1": - resolution: - { - integrity: sha512-XaX6r8pXeX47rfiQrSQUwkgxHsDkOKzIT++zfTwrmveVlYSqAhp3x+AKhxAXGmKG62wlmAKQz54GJKcG4cgyKQ==, - } - engines: { node: ">=14.18" } - - "@sentry/babel-plugin-component-annotate@3.6.1": - resolution: - { - integrity: sha512-zmvUa4RpzDG3LQJFpGCE8lniz8Rk1Wa6ZvvK+yEH+snZeaHHRbSnAQBMR607GOClP+euGHNO2YtaY4UAdNTYbg==, - } - engines: { node: ">= 14" } - - "@sentry/browser@8.55.1": - resolution: - { - integrity: sha512-OEn2eg8h3Mr7BmBGQ28BqbWehYA/NklZ0pAZB1FypPPl+kMd85AbaRdGTnaSjgmpc8bKbBO64edq4Y14sbCs5w==, - } - engines: { node: ">=14.18" } - - "@sentry/bundler-plugin-core@3.6.1": - resolution: - { - integrity: sha512-/ubWjPwgLep84sUPzHfKL2Ns9mK9aQrEX4aBFztru7ygiJidKJTxYGtvjh4dL2M1aZ0WRQYp+7PF6+VKwdZXcQ==, - } - engines: { node: ">= 14" } - - "@sentry/cli-darwin@2.58.5": - resolution: - { - integrity: sha512-lYrNzenZFJftfwSya7gwrHGxtE+Kob/e1sr9lmHMFOd4utDlmq0XFDllmdZAMf21fxcPRI1GL28ejZ3bId01fQ==, - } - engines: { node: ">=10" } + '@rollup/rollup-darwin-arm64@4.60.1': + resolution: {integrity: sha512-mjCpF7GmkRtSJwon+Rq1N8+pI+8l7w5g9Z3vWj4T7abguC4Czwi3Yu/pFaLvA3TTeMVjnu3ctigusqWUfjZzvw==} + cpu: [arm64] os: [darwin] - "@sentry/cli-linux-arm64@2.58.5": - resolution: - { - integrity: sha512-/4gywFeBqRB6tR/iGMRAJ3HRqY6Z7Yp4l8ZCbl0TDLAfHNxu7schEw4tSnm2/Hh9eNMiOVy4z58uzAWlZXAYBQ==, - } - engines: { node: ">=10" } + '@rollup/rollup-darwin-x64@4.60.1': + resolution: {integrity: sha512-haZ7hJ1JT4e9hqkoT9R/19XW2QKqjfJVv+i5AGg57S+nLk9lQnJ1F/eZloRO3o9Scy9CM3wQ9l+dkXtcBgN5Ew==} + cpu: [x64] + os: [darwin] + + '@rollup/rollup-freebsd-arm64@4.60.1': + resolution: {integrity: sha512-czw90wpQq3ZsAVBlinZjAYTKduOjTywlG7fEeWKUA7oCmpA8xdTkxZZlwNJKWqILlq0wehoZcJYfBvOyhPTQ6w==} + cpu: [arm64] + os: [freebsd] + + '@rollup/rollup-freebsd-x64@4.60.1': + resolution: {integrity: sha512-KVB2rqsxTHuBtfOeySEyzEOB7ltlB/ux38iu2rBQzkjbwRVlkhAGIEDiiYnO2kFOkJp+Z7pUXKyrRRFuFUKt+g==} + cpu: [x64] + os: [freebsd] + + '@rollup/rollup-linux-arm-gnueabihf@4.60.1': + resolution: {integrity: sha512-L+34Qqil+v5uC0zEubW7uByo78WOCIrBvci69E7sFASRl0X7b/MB6Cqd1lky/CtcSVTydWa2WZwFuWexjS5o6g==} + cpu: [arm] + os: [linux] + + '@rollup/rollup-linux-arm-musleabihf@4.60.1': + resolution: {integrity: sha512-n83O8rt4v34hgFzlkb1ycniJh7IR5RCIqt6mz1VRJD6pmhRi0CXdmfnLu9dIUS6buzh60IvACM842Ffb3xd6Gg==} + cpu: [arm] + os: [linux] + + '@rollup/rollup-linux-arm64-gnu@4.60.1': + resolution: {integrity: sha512-Nql7sTeAzhTAja3QXeAI48+/+GjBJ+QmAH13snn0AJSNL50JsDqotyudHyMbO2RbJkskbMbFJfIJKWA6R1LCJQ==} + cpu: [arm64] + os: [linux] + + '@rollup/rollup-linux-arm64-musl@4.60.1': + resolution: {integrity: sha512-+pUymDhd0ys9GcKZPPWlFiZ67sTWV5UU6zOJat02M1+PiuSGDziyRuI/pPue3hoUwm2uGfxdL+trT6Z9rxnlMA==} + cpu: [arm64] + os: [linux] + + '@rollup/rollup-linux-loong64-gnu@4.60.1': + resolution: {integrity: sha512-VSvgvQeIcsEvY4bKDHEDWcpW4Yw7BtlKG1GUT4FzBUlEKQK0rWHYBqQt6Fm2taXS+1bXvJT6kICu5ZwqKCnvlQ==} + cpu: [loong64] + os: [linux] + + '@rollup/rollup-linux-loong64-musl@4.60.1': + resolution: {integrity: sha512-4LqhUomJqwe641gsPp6xLfhqWMbQV04KtPp7/dIp0nzPxAkNY1AbwL5W0MQpcalLYk07vaW9Kp1PBhdpZYYcEw==} + cpu: [loong64] + os: [linux] + + '@rollup/rollup-linux-ppc64-gnu@4.60.1': + resolution: {integrity: sha512-tLQQ9aPvkBxOc/EUT6j3pyeMD6Hb8QF2BTBnCQWP/uu1lhc9AIrIjKnLYMEroIz/JvtGYgI9dF3AxHZNaEH0rw==} + cpu: [ppc64] + os: [linux] + + '@rollup/rollup-linux-ppc64-musl@4.60.1': + resolution: {integrity: sha512-RMxFhJwc9fSXP6PqmAz4cbv3kAyvD1etJFjTx4ONqFP9DkTkXsAMU4v3Vyc5BgzC+anz7nS/9tp4obsKfqkDHg==} + cpu: [ppc64] + os: [linux] + + '@rollup/rollup-linux-riscv64-gnu@4.60.1': + resolution: {integrity: sha512-QKgFl+Yc1eEk6MmOBfRHYF6lTxiiiV3/z/BRrbSiW2I7AFTXoBFvdMEyglohPj//2mZS4hDOqeB0H1ACh3sBbg==} + cpu: [riscv64] + os: [linux] + + '@rollup/rollup-linux-riscv64-musl@4.60.1': + resolution: {integrity: sha512-RAjXjP/8c6ZtzatZcA1RaQr6O1TRhzC+adn8YZDnChliZHviqIjmvFwHcxi4JKPSDAt6Uhf/7vqcBzQJy0PDJg==} + cpu: [riscv64] + os: [linux] + + '@rollup/rollup-linux-s390x-gnu@4.60.1': + resolution: {integrity: sha512-wcuocpaOlaL1COBYiA89O6yfjlp3RwKDeTIA0hM7OpmhR1Bjo9j31G1uQVpDlTvwxGn2nQs65fBFL5UFd76FcQ==} + cpu: [s390x] + os: [linux] + + '@rollup/rollup-linux-x64-gnu@4.60.1': + resolution: {integrity: sha512-77PpsFQUCOiZR9+LQEFg9GClyfkNXj1MP6wRnzYs0EeWbPcHs02AXu4xuUbM1zhwn3wqaizle3AEYg5aeoohhg==} + cpu: [x64] + os: [linux] + + '@rollup/rollup-linux-x64-musl@4.60.1': + resolution: {integrity: sha512-5cIATbk5vynAjqqmyBjlciMJl1+R/CwX9oLk/EyiFXDWd95KpHdrOJT//rnUl4cUcskrd0jCCw3wpZnhIHdD9w==} + cpu: [x64] + os: [linux] + + '@rollup/rollup-openbsd-x64@4.60.1': + resolution: {integrity: sha512-cl0w09WsCi17mcmWqqglez9Gk8isgeWvoUZ3WiJFYSR3zjBQc2J5/ihSjpl+VLjPqjQ/1hJRcqBfLjssREQILw==} + cpu: [x64] + os: [openbsd] + + '@rollup/rollup-openharmony-arm64@4.60.1': + resolution: {integrity: sha512-4Cv23ZrONRbNtbZa37mLSueXUCtN7MXccChtKpUnQNgF010rjrjfHx3QxkS2PI7LqGT5xXyYs1a7LbzAwT0iCA==} + cpu: [arm64] + os: [openharmony] + + '@rollup/rollup-win32-arm64-msvc@4.60.1': + resolution: {integrity: sha512-i1okWYkA4FJICtr7KpYzFpRTHgy5jdDbZiWfvny21iIKky5YExiDXP+zbXzm3dUcFpkEeYNHgQ5fuG236JPq0g==} + cpu: [arm64] + os: [win32] + + '@rollup/rollup-win32-ia32-msvc@4.60.1': + resolution: {integrity: sha512-u09m3CuwLzShA0EYKMNiFgcjjzwqtUMLmuCJLeZWjjOYA3IT2Di09KaxGBTP9xVztWyIWjVdsB2E9goMjZvTQg==} + cpu: [ia32] + os: [win32] + + '@rollup/rollup-win32-x64-gnu@4.60.1': + resolution: {integrity: sha512-k+600V9Zl1CM7eZxJgMyTUzmrmhB/0XZnF4pRypKAlAgxmedUA+1v9R+XOFv56W4SlHEzfeMtzujLJD22Uz5zg==} + cpu: [x64] + os: [win32] + + '@rollup/rollup-win32-x64-msvc@4.60.1': + resolution: {integrity: sha512-lWMnixq/QzxyhTV6NjQJ4SFo1J6PvOX8vUx5Wb4bBPsEb+8xZ89Bz6kOXpfXj9ak9AHTQVQzlgzBEc1SyM27xQ==} + cpu: [x64] + os: [win32] + + '@rtsao/scc@1.1.0': + resolution: {integrity: sha512-zt6OdqaDoOnJ1ZYsCYGt9YmWzDXl4vQdKTyJev62gFhRGKdx7mcT54V9KIjg+d2wi9EXsPvAPKe7i7WjfVWB8g==} + + '@sentry-internal/browser-utils@8.55.1': + resolution: {integrity: sha512-SipXiwVhJrxzy3/4kf+YIFmpYlLKtGSRD+er7SBCcuSBtv31Fee8IXMDvk+bq24gRXxyjOLUmT//GGXjy2LL6w==} + engines: {node: '>=14.18'} + + '@sentry-internal/feedback@8.55.1': + resolution: {integrity: sha512-9iFHaT/ijtzB0ffZhXMnt2rPNIXO/dDiCL1G1Bc55rQMPXgawR9AIaAWciyqQjYcbL1DDOhWbzdVqB+kVs5gXw==} + engines: {node: '>=14.18'} + + '@sentry-internal/replay-canvas@8.55.1': + resolution: {integrity: sha512-2sKRu96Qe70y6TiYdYbwkhg4um2prgzH/ZJRItuoSEAjPjoFYYlP+1qjE2CcBw4RPS8/PimV7SFheSaeZs2GCw==} + engines: {node: '>=14.18'} + + '@sentry-internal/replay@8.55.1': + resolution: {integrity: sha512-XaX6r8pXeX47rfiQrSQUwkgxHsDkOKzIT++zfTwrmveVlYSqAhp3x+AKhxAXGmKG62wlmAKQz54GJKcG4cgyKQ==} + engines: {node: '>=14.18'} + + '@sentry/babel-plugin-component-annotate@3.6.1': + resolution: {integrity: sha512-zmvUa4RpzDG3LQJFpGCE8lniz8Rk1Wa6ZvvK+yEH+snZeaHHRbSnAQBMR607GOClP+euGHNO2YtaY4UAdNTYbg==} + engines: {node: '>= 14'} + + '@sentry/browser@8.55.1': + resolution: {integrity: sha512-OEn2eg8h3Mr7BmBGQ28BqbWehYA/NklZ0pAZB1FypPPl+kMd85AbaRdGTnaSjgmpc8bKbBO64edq4Y14sbCs5w==} + engines: {node: '>=14.18'} + + '@sentry/bundler-plugin-core@3.6.1': + resolution: {integrity: sha512-/ubWjPwgLep84sUPzHfKL2Ns9mK9aQrEX4aBFztru7ygiJidKJTxYGtvjh4dL2M1aZ0WRQYp+7PF6+VKwdZXcQ==} + engines: {node: '>= 14'} + + '@sentry/cli-darwin@2.58.5': + resolution: {integrity: sha512-lYrNzenZFJftfwSya7gwrHGxtE+Kob/e1sr9lmHMFOd4utDlmq0XFDllmdZAMf21fxcPRI1GL28ejZ3bId01fQ==} + engines: {node: '>=10'} + os: [darwin] + + '@sentry/cli-linux-arm64@2.58.5': + resolution: {integrity: sha512-/4gywFeBqRB6tR/iGMRAJ3HRqY6Z7Yp4l8ZCbl0TDLAfHNxu7schEw4tSnm2/Hh9eNMiOVy4z58uzAWlZXAYBQ==} + engines: {node: '>=10'} cpu: [arm64] os: [linux, freebsd, android] - "@sentry/cli-linux-arm@2.58.5": - resolution: - { - integrity: sha512-KtHweSIomYL4WVDrBrYSYJricKAAzxUgX86kc6OnlikbyOhoK6Fy8Vs6vwd52P6dvWPjgrMpUYjW2M5pYXQDUw==, - } - engines: { node: ">=10" } + '@sentry/cli-linux-arm@2.58.5': + resolution: {integrity: sha512-KtHweSIomYL4WVDrBrYSYJricKAAzxUgX86kc6OnlikbyOhoK6Fy8Vs6vwd52P6dvWPjgrMpUYjW2M5pYXQDUw==} + engines: {node: '>=10'} cpu: [arm] os: [linux, freebsd, android] - "@sentry/cli-linux-i686@2.58.5": - resolution: - { - integrity: sha512-G7261dkmyxqlMdyvyP06b+RTIVzp1gZNgglj5UksxSouSUqRd/46W/2pQeOMPhloDYo9yLtCN2YFb3Mw4aUsWw==, - } - engines: { node: ">=10" } + '@sentry/cli-linux-i686@2.58.5': + resolution: {integrity: sha512-G7261dkmyxqlMdyvyP06b+RTIVzp1gZNgglj5UksxSouSUqRd/46W/2pQeOMPhloDYo9yLtCN2YFb3Mw4aUsWw==} + engines: {node: '>=10'} cpu: [x86, ia32] os: [linux, freebsd, android] - "@sentry/cli-linux-x64@2.58.5": - resolution: - { - integrity: sha512-rP04494RSmt86xChkQ+ecBNRYSPbyXc4u0IA7R7N1pSLCyO74e5w5Al+LnAq35cMfVbZgz5Sm0iGLjyiUu4I1g==, - } - engines: { node: ">=10" } + '@sentry/cli-linux-x64@2.58.5': + resolution: {integrity: sha512-rP04494RSmt86xChkQ+ecBNRYSPbyXc4u0IA7R7N1pSLCyO74e5w5Al+LnAq35cMfVbZgz5Sm0iGLjyiUu4I1g==} + engines: {node: '>=10'} cpu: [x64] os: [linux, freebsd, android] - "@sentry/cli-win32-arm64@2.58.5": - resolution: - { - integrity: sha512-AOJ2nCXlQL1KBaCzv38m3i2VmSHNurUpm7xVKd6yAHX+ZoVBI8VT0EgvwmtJR2TY2N2hNCC7UrgRmdUsQ152bA==, - } - engines: { node: ">=10" } + '@sentry/cli-win32-arm64@2.58.5': + resolution: {integrity: sha512-AOJ2nCXlQL1KBaCzv38m3i2VmSHNurUpm7xVKd6yAHX+ZoVBI8VT0EgvwmtJR2TY2N2hNCC7UrgRmdUsQ152bA==} + engines: {node: '>=10'} cpu: [arm64] os: [win32] - "@sentry/cli-win32-i686@2.58.5": - resolution: - { - integrity: sha512-EsuboLSOnlrN7MMPJ1eFvfMDm+BnzOaSWl8eYhNo8W/BIrmNgpRUdBwnWn9Q2UOjJj5ZopukmsiMYtU/D7ml9g==, - } - engines: { node: ">=10" } + '@sentry/cli-win32-i686@2.58.5': + resolution: {integrity: sha512-EsuboLSOnlrN7MMPJ1eFvfMDm+BnzOaSWl8eYhNo8W/BIrmNgpRUdBwnWn9Q2UOjJj5ZopukmsiMYtU/D7ml9g==} + engines: {node: '>=10'} cpu: [x86, ia32] os: [win32] - "@sentry/cli-win32-x64@2.58.5": - resolution: - { - integrity: sha512-IZf+XIMiQwj+5NzqbOQfywlOitmCV424Vtf9c+ep61AaVScUFD1TSrQbOcJJv5xGxhlxNOMNgMeZhdexdzrKZg==, - } - engines: { node: ">=10" } + '@sentry/cli-win32-x64@2.58.5': + resolution: {integrity: sha512-IZf+XIMiQwj+5NzqbOQfywlOitmCV424Vtf9c+ep61AaVScUFD1TSrQbOcJJv5xGxhlxNOMNgMeZhdexdzrKZg==} + engines: {node: '>=10'} cpu: [x64] os: [win32] - "@sentry/cli@2.58.5": - resolution: - { - integrity: sha512-tavJ7yGUZV+z3Ct2/ZB6mg339i08sAk6HDkgqmSRuQEu2iLS5sl9HIvuXfM6xjv8fwlgFOSy++WNABNAcGHUbg==, - } - engines: { node: ">= 10" } + '@sentry/cli@2.58.5': + resolution: {integrity: sha512-tavJ7yGUZV+z3Ct2/ZB6mg339i08sAk6HDkgqmSRuQEu2iLS5sl9HIvuXfM6xjv8fwlgFOSy++WNABNAcGHUbg==} + engines: {node: '>= 10'} hasBin: true - "@sentry/core@8.55.1": - resolution: - { - integrity: sha512-0ea+yDOgaijR3ba2al1QZxY0bZ9MBZq2a0G+2A0uCBpBkiXnpLFGVAo9UAlEikN1C4M8ROZYiuFU7yZCqacgLQ==, - } - engines: { node: ">=14.18" } + '@sentry/core@8.55.1': + resolution: {integrity: sha512-0ea+yDOgaijR3ba2al1QZxY0bZ9MBZq2a0G+2A0uCBpBkiXnpLFGVAo9UAlEikN1C4M8ROZYiuFU7yZCqacgLQ==} + engines: {node: '>=14.18'} - "@sentry/react@8.55.1": - resolution: - { - integrity: sha512-vrqEI1EVRMaeUluHSt84//WFuMecqAfwS+t2SojhvXtsSP6BbaCHd0jt7til5MBzI9kWAQjIxsUUr3pbFAviVg==, - } - engines: { node: ">=14.18" } + '@sentry/react@8.55.1': + resolution: {integrity: sha512-vrqEI1EVRMaeUluHSt84//WFuMecqAfwS+t2SojhvXtsSP6BbaCHd0jt7til5MBzI9kWAQjIxsUUr3pbFAviVg==} + engines: {node: '>=14.18'} peerDependencies: react: ^16.14.0 || 17.x || 18.x || 19.x - "@sentry/vite-plugin@3.6.1": - resolution: - { - integrity: sha512-x8WMdv2K2HcGS2ezEUIEZXpT/fNeWQ9rsEeF0K9DfKXK8Z9lzRmCr6TVA6I9+yW39Is+1/0cv1Rsu0LhO7lHzg==, - } - engines: { node: ">= 14" } + '@sentry/vite-plugin@3.6.1': + resolution: {integrity: sha512-x8WMdv2K2HcGS2ezEUIEZXpT/fNeWQ9rsEeF0K9DfKXK8Z9lzRmCr6TVA6I9+yW39Is+1/0cv1Rsu0LhO7lHzg==} + engines: {node: '>= 14'} - "@sindresorhus/base62@1.0.0": - resolution: - { - integrity: sha512-TeheYy0ILzBEI/CO55CP6zJCSdSWeRtGnHy8U8dWSUH4I68iqTsy7HkMktR4xakThc9jotkPQUXT4ITdbV7cHA==, - } - engines: { node: ">=18" } + '@sindresorhus/base62@1.0.0': + resolution: {integrity: sha512-TeheYy0ILzBEI/CO55CP6zJCSdSWeRtGnHy8U8dWSUH4I68iqTsy7HkMktR4xakThc9jotkPQUXT4ITdbV7cHA==} + engines: {node: '>=18'} - "@standard-schema/spec@1.1.0": - resolution: - { - integrity: sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w==, - } + '@standard-schema/spec@1.1.0': + resolution: {integrity: sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w==} - "@storybook/addon-docs@10.3.5": - resolution: - { - integrity: sha512-WuHbxia/o5TX4Rg/IFD0641K5qId/Nk0dxhmAUNoFs5L0+yfZUwh65XOBbzXqrkYmYmcVID4v7cgDRmzstQNkA==, - } + '@storybook/addon-docs@10.3.5': + resolution: {integrity: sha512-WuHbxia/o5TX4Rg/IFD0641K5qId/Nk0dxhmAUNoFs5L0+yfZUwh65XOBbzXqrkYmYmcVID4v7cgDRmzstQNkA==} peerDependencies: storybook: ^10.3.5 - "@storybook/builder-vite@10.3.5": - resolution: - { - integrity: sha512-i4KwCOKbhtlbQIbhm53+Kk7bMnxa0cwTn1pxmtA/x5wm1Qu7FrrBQV0V0DNjkUqzcSKo1CjspASJV/HlY0zYlw==, - } + '@storybook/builder-vite@10.3.5': + resolution: {integrity: sha512-i4KwCOKbhtlbQIbhm53+Kk7bMnxa0cwTn1pxmtA/x5wm1Qu7FrrBQV0V0DNjkUqzcSKo1CjspASJV/HlY0zYlw==} peerDependencies: storybook: ^10.3.5 vite: ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0 - "@storybook/csf-plugin@10.3.5": - resolution: - { - integrity: sha512-qlEzNKxOjq86pvrbuMwiGD/bylnsXk1dg7ve0j77YFjEEchqtl7qTlrXvFdNaLA89GhW6D/EV6eOCu/eobPDgw==, - } + '@storybook/csf-plugin@10.3.5': + resolution: {integrity: sha512-qlEzNKxOjq86pvrbuMwiGD/bylnsXk1dg7ve0j77YFjEEchqtl7qTlrXvFdNaLA89GhW6D/EV6eOCu/eobPDgw==} peerDependencies: esbuild: ^0.27.7 - rollup: "*" + rollup: '*' storybook: ^10.3.5 - vite: "*" - webpack: "*" + vite: '*' + webpack: '*' peerDependenciesMeta: esbuild: optional: true @@ -3671,667 +2667,409 @@ packages: webpack: optional: true - "@storybook/global@5.0.0": - resolution: - { - integrity: sha512-FcOqPAXACP0I3oJ/ws6/rrPT9WGhu915Cg8D02a9YxLo0DE9zI+a9A5gRGvmQ09fiWPukqI8ZAEoQEdWUKMQdQ==, - } + '@storybook/global@5.0.0': + resolution: {integrity: sha512-FcOqPAXACP0I3oJ/ws6/rrPT9WGhu915Cg8D02a9YxLo0DE9zI+a9A5gRGvmQ09fiWPukqI8ZAEoQEdWUKMQdQ==} - "@storybook/icons@2.0.1": - resolution: - { - integrity: sha512-/smVjw88yK3CKsiuR71vNgWQ9+NuY2L+e8X7IMrFjexjm6ZR8ULrV2DRkTA61aV6ryefslzHEGDInGpnNeIocg==, - } + '@storybook/icons@2.0.1': + resolution: {integrity: sha512-/smVjw88yK3CKsiuR71vNgWQ9+NuY2L+e8X7IMrFjexjm6ZR8ULrV2DRkTA61aV6ryefslzHEGDInGpnNeIocg==} peerDependencies: react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 - "@storybook/react-dom-shim@10.3.5": - resolution: - { - integrity: sha512-Gw8R7XZm0zSUH0XAuxlQJhmizsLzyD6x00KOlP6l7oW9eQHXGfxg3seNDG3WrSAcW07iP1/P422kuiriQlOv7g==, - } + '@storybook/react-dom-shim@10.3.5': + resolution: {integrity: sha512-Gw8R7XZm0zSUH0XAuxlQJhmizsLzyD6x00KOlP6l7oW9eQHXGfxg3seNDG3WrSAcW07iP1/P422kuiriQlOv7g==} peerDependencies: react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 storybook: ^10.3.5 - "@storybook/react-vite@10.3.5": - resolution: - { - integrity: sha512-UB5sJHeh26bfd8sNMx2YPGYRYmErIdTRaLOT28m4bykQIa1l9IgVktsYg/geW7KsJU0lXd3oTbnUjLD+enpi3w==, - } + '@storybook/react-vite@10.3.5': + resolution: {integrity: sha512-UB5sJHeh26bfd8sNMx2YPGYRYmErIdTRaLOT28m4bykQIa1l9IgVktsYg/geW7KsJU0lXd3oTbnUjLD+enpi3w==} peerDependencies: react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 storybook: ^10.3.5 vite: ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0 - "@storybook/react@10.3.5": - resolution: - { - integrity: sha512-tpLTLaVGoA6fLK3ReyGzZUricq7lyPaV2hLPpj5wqdXLV/LpRtAHClUpNoPDYSBjlnSjL81hMZijbkGC3mA+gw==, - } + '@storybook/react@10.3.5': + resolution: {integrity: sha512-tpLTLaVGoA6fLK3ReyGzZUricq7lyPaV2hLPpj5wqdXLV/LpRtAHClUpNoPDYSBjlnSjL81hMZijbkGC3mA+gw==} peerDependencies: react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 storybook: ^10.3.5 - typescript: ">= 4.9.x" + typescript: '>= 4.9.x' peerDependenciesMeta: typescript: optional: true - "@stylistic/eslint-plugin@3.1.0": - resolution: - { - integrity: sha512-pA6VOrOqk0+S8toJYhQGv2MWpQQR0QpeUo9AhNkC49Y26nxBQ/nH1rta9bUU1rPw2fJ1zZEMV5oCX5AazT7J2g==, - } - engines: { node: ^18.18.0 || ^20.9.0 || >=21.1.0 } + '@stylistic/eslint-plugin@3.1.0': + resolution: {integrity: sha512-pA6VOrOqk0+S8toJYhQGv2MWpQQR0QpeUo9AhNkC49Y26nxBQ/nH1rta9bUU1rPw2fJ1zZEMV5oCX5AazT7J2g==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: - eslint: ">=8.40.0" + eslint: '>=8.40.0' - "@svgr/babel-plugin-add-jsx-attribute@8.0.0": - resolution: - { - integrity: sha512-b9MIk7yhdS1pMCZM8VeNfUlSKVRhsHZNMl5O9SfaX0l0t5wjdgu4IDzGB8bpnGBBOjGST3rRFVsaaEtI4W6f7g==, - } - engines: { node: ">=14" } + '@svgr/babel-plugin-add-jsx-attribute@8.0.0': + resolution: {integrity: sha512-b9MIk7yhdS1pMCZM8VeNfUlSKVRhsHZNMl5O9SfaX0l0t5wjdgu4IDzGB8bpnGBBOjGST3rRFVsaaEtI4W6f7g==} + engines: {node: '>=14'} peerDependencies: - "@babel/core": ^7.0.0-0 + '@babel/core': ^7.0.0-0 - "@svgr/babel-plugin-remove-jsx-attribute@8.0.0": - resolution: - { - integrity: sha512-BcCkm/STipKvbCl6b7QFrMh/vx00vIP63k2eM66MfHJzPr6O2U0jYEViXkHJWqXqQYjdeA9cuCl5KWmlwjDvbA==, - } - engines: { node: ">=14" } + '@svgr/babel-plugin-remove-jsx-attribute@8.0.0': + resolution: {integrity: sha512-BcCkm/STipKvbCl6b7QFrMh/vx00vIP63k2eM66MfHJzPr6O2U0jYEViXkHJWqXqQYjdeA9cuCl5KWmlwjDvbA==} + engines: {node: '>=14'} peerDependencies: - "@babel/core": ^7.0.0-0 + '@babel/core': ^7.0.0-0 - "@svgr/babel-plugin-remove-jsx-empty-expression@8.0.0": - resolution: - { - integrity: sha512-5BcGCBfBxB5+XSDSWnhTThfI9jcO5f0Ai2V24gZpG+wXF14BzwxxdDb4g6trdOux0rhibGs385BeFMSmxtS3uA==, - } - engines: { node: ">=14" } + '@svgr/babel-plugin-remove-jsx-empty-expression@8.0.0': + resolution: {integrity: sha512-5BcGCBfBxB5+XSDSWnhTThfI9jcO5f0Ai2V24gZpG+wXF14BzwxxdDb4g6trdOux0rhibGs385BeFMSmxtS3uA==} + engines: {node: '>=14'} peerDependencies: - "@babel/core": ^7.0.0-0 + '@babel/core': ^7.0.0-0 - "@svgr/babel-plugin-replace-jsx-attribute-value@8.0.0": - resolution: - { - integrity: sha512-KVQ+PtIjb1BuYT3ht8M5KbzWBhdAjjUPdlMtpuw/VjT8coTrItWX6Qafl9+ji831JaJcu6PJNKCV0bp01lBNzQ==, - } - engines: { node: ">=14" } + '@svgr/babel-plugin-replace-jsx-attribute-value@8.0.0': + resolution: {integrity: sha512-KVQ+PtIjb1BuYT3ht8M5KbzWBhdAjjUPdlMtpuw/VjT8coTrItWX6Qafl9+ji831JaJcu6PJNKCV0bp01lBNzQ==} + engines: {node: '>=14'} peerDependencies: - "@babel/core": ^7.0.0-0 + '@babel/core': ^7.0.0-0 - "@svgr/babel-plugin-svg-dynamic-title@8.0.0": - resolution: - { - integrity: sha512-omNiKqwjNmOQJ2v6ge4SErBbkooV2aAWwaPFs2vUY7p7GhVkzRkJ00kILXQvRhA6miHnNpXv7MRnnSjdRjK8og==, - } - engines: { node: ">=14" } + '@svgr/babel-plugin-svg-dynamic-title@8.0.0': + resolution: {integrity: sha512-omNiKqwjNmOQJ2v6ge4SErBbkooV2aAWwaPFs2vUY7p7GhVkzRkJ00kILXQvRhA6miHnNpXv7MRnnSjdRjK8og==} + engines: {node: '>=14'} peerDependencies: - "@babel/core": ^7.0.0-0 + '@babel/core': ^7.0.0-0 - "@svgr/babel-plugin-svg-em-dimensions@8.0.0": - resolution: - { - integrity: sha512-mURHYnu6Iw3UBTbhGwE/vsngtCIbHE43xCRK7kCw4t01xyGqb2Pd+WXekRRoFOBIY29ZoOhUCTEweDMdrjfi9g==, - } - engines: { node: ">=14" } + '@svgr/babel-plugin-svg-em-dimensions@8.0.0': + resolution: {integrity: sha512-mURHYnu6Iw3UBTbhGwE/vsngtCIbHE43xCRK7kCw4t01xyGqb2Pd+WXekRRoFOBIY29ZoOhUCTEweDMdrjfi9g==} + engines: {node: '>=14'} peerDependencies: - "@babel/core": ^7.0.0-0 + '@babel/core': ^7.0.0-0 - "@svgr/babel-plugin-transform-react-native-svg@8.1.0": - resolution: - { - integrity: sha512-Tx8T58CHo+7nwJ+EhUwx3LfdNSG9R2OKfaIXXs5soiy5HtgoAEkDay9LIimLOcG8dJQH1wPZp/cnAv6S9CrR1Q==, - } - engines: { node: ">=14" } + '@svgr/babel-plugin-transform-react-native-svg@8.1.0': + resolution: {integrity: sha512-Tx8T58CHo+7nwJ+EhUwx3LfdNSG9R2OKfaIXXs5soiy5HtgoAEkDay9LIimLOcG8dJQH1wPZp/cnAv6S9CrR1Q==} + engines: {node: '>=14'} peerDependencies: - "@babel/core": ^7.0.0-0 + '@babel/core': ^7.0.0-0 - "@svgr/babel-plugin-transform-svg-component@8.0.0": - resolution: - { - integrity: sha512-DFx8xa3cZXTdb/k3kfPeaixecQLgKh5NVBMwD0AQxOzcZawK4oo1Jh9LbrcACUivsCA7TLG8eeWgrDXjTMhRmw==, - } - engines: { node: ">=12" } + '@svgr/babel-plugin-transform-svg-component@8.0.0': + resolution: {integrity: sha512-DFx8xa3cZXTdb/k3kfPeaixecQLgKh5NVBMwD0AQxOzcZawK4oo1Jh9LbrcACUivsCA7TLG8eeWgrDXjTMhRmw==} + engines: {node: '>=12'} peerDependencies: - "@babel/core": ^7.0.0-0 + '@babel/core': ^7.0.0-0 - "@svgr/babel-preset@8.1.0": - resolution: - { - integrity: sha512-7EYDbHE7MxHpv4sxvnVPngw5fuR6pw79SkcrILHJ/iMpuKySNCl5W1qcwPEpU+LgyRXOaAFgH0KhwD18wwg6ug==, - } - engines: { node: ">=14" } + '@svgr/babel-preset@8.1.0': + resolution: {integrity: sha512-7EYDbHE7MxHpv4sxvnVPngw5fuR6pw79SkcrILHJ/iMpuKySNCl5W1qcwPEpU+LgyRXOaAFgH0KhwD18wwg6ug==} + engines: {node: '>=14'} peerDependencies: - "@babel/core": ^7.0.0-0 + '@babel/core': ^7.0.0-0 - "@svgr/core@8.1.0": - resolution: - { - integrity: sha512-8QqtOQT5ACVlmsvKOJNEaWmRPmcojMOzCz4Hs2BGG/toAp/K38LcsMRyLp349glq5AzJbCEeimEoxaX6v/fLrA==, - } - engines: { node: ">=14" } + '@svgr/core@8.1.0': + resolution: {integrity: sha512-8QqtOQT5ACVlmsvKOJNEaWmRPmcojMOzCz4Hs2BGG/toAp/K38LcsMRyLp349glq5AzJbCEeimEoxaX6v/fLrA==} + engines: {node: '>=14'} - "@svgr/hast-util-to-babel-ast@8.0.0": - resolution: - { - integrity: sha512-EbDKwO9GpfWP4jN9sGdYwPBU0kdomaPIL2Eu4YwmgP+sJeXT+L7bMwJUBnhzfH8Q2qMBqZ4fJwpCyYsAN3mt2Q==, - } - engines: { node: ">=14" } + '@svgr/hast-util-to-babel-ast@8.0.0': + resolution: {integrity: sha512-EbDKwO9GpfWP4jN9sGdYwPBU0kdomaPIL2Eu4YwmgP+sJeXT+L7bMwJUBnhzfH8Q2qMBqZ4fJwpCyYsAN3mt2Q==} + engines: {node: '>=14'} - "@svgr/plugin-jsx@8.1.0": - resolution: - { - integrity: sha512-0xiIyBsLlr8quN+WyuxooNW9RJ0Dpr8uOnH/xrCVO8GLUcwHISwj1AG0k+LFzteTkAA0GbX0kj9q6Dk70PTiPA==, - } - engines: { node: ">=14" } + '@svgr/plugin-jsx@8.1.0': + resolution: {integrity: sha512-0xiIyBsLlr8quN+WyuxooNW9RJ0Dpr8uOnH/xrCVO8GLUcwHISwj1AG0k+LFzteTkAA0GbX0kj9q6Dk70PTiPA==} + engines: {node: '>=14'} peerDependencies: - "@svgr/core": "*" + '@svgr/core': '*' - "@testing-library/dom@10.4.1": - resolution: - { - integrity: sha512-o4PXJQidqJl82ckFaXUeoAW+XysPLauYI43Abki5hABd853iMhitooc6znOnczgbTYmEP6U6/y1ZyKAIsvMKGg==, - } - engines: { node: ">=18" } + '@testing-library/dom@10.4.1': + resolution: {integrity: sha512-o4PXJQidqJl82ckFaXUeoAW+XysPLauYI43Abki5hABd853iMhitooc6znOnczgbTYmEP6U6/y1ZyKAIsvMKGg==} + engines: {node: '>=18'} - "@testing-library/jest-dom@6.9.1": - resolution: - { - integrity: sha512-zIcONa+hVtVSSep9UT3jZ5rizo2BsxgyDYU7WFD5eICBE7no3881HGeb/QkGfsJs6JTkY1aQhT7rIPC7e+0nnA==, - } - engines: { node: ">=14", npm: ">=6", yarn: ">=1" } + '@testing-library/jest-dom@6.9.1': + resolution: {integrity: sha512-zIcONa+hVtVSSep9UT3jZ5rizo2BsxgyDYU7WFD5eICBE7no3881HGeb/QkGfsJs6JTkY1aQhT7rIPC7e+0nnA==} + engines: {node: '>=14', npm: '>=6', yarn: '>=1'} - "@testing-library/react@16.3.2": - resolution: - { - integrity: sha512-XU5/SytQM+ykqMnAnvB2umaJNIOsLF3PVv//1Ew4CTcpz0/BRyy/af40qqrt7SjKpDdT1saBMc42CUok5gaw+g==, - } - engines: { node: ">=18" } + '@testing-library/react@16.3.2': + resolution: {integrity: sha512-XU5/SytQM+ykqMnAnvB2umaJNIOsLF3PVv//1Ew4CTcpz0/BRyy/af40qqrt7SjKpDdT1saBMc42CUok5gaw+g==} + engines: {node: '>=18'} peerDependencies: - "@testing-library/dom": ^10.0.0 - "@types/react": ^18.0.0 || ^19.0.0 - "@types/react-dom": ^18.0.0 || ^19.0.0 + '@testing-library/dom': ^10.0.0 + '@types/react': ^18.0.0 || ^19.0.0 + '@types/react-dom': ^18.0.0 || ^19.0.0 react: ^18.0.0 || ^19.0.0 react-dom: ^18.0.0 || ^19.0.0 peerDependenciesMeta: - "@types/react": + '@types/react': optional: true - "@types/react-dom": + '@types/react-dom': optional: true - "@testing-library/user-event@14.6.1": - resolution: - { - integrity: sha512-vq7fv0rnt+QTXgPxr5Hjc210p6YKq2kmdziLgnsZGgLJ9e6VAShx1pACLuRjd/AS/sr7phAR58OIIpf0LlmQNw==, - } - engines: { node: ">=12", npm: ">=6" } + '@testing-library/user-event@14.6.1': + resolution: {integrity: sha512-vq7fv0rnt+QTXgPxr5Hjc210p6YKq2kmdziLgnsZGgLJ9e6VAShx1pACLuRjd/AS/sr7phAR58OIIpf0LlmQNw==} + engines: {node: '>=12', npm: '>=6'} peerDependencies: - "@testing-library/dom": ">=7.21.4" + '@testing-library/dom': '>=7.21.4' - "@tybys/wasm-util@0.10.1": - resolution: - { - integrity: sha512-9tTaPJLSiejZKx+Bmog4uSubteqTvFrVrURwkmHixBo0G4seD0zUxp98E1DzUBJxLQ3NPwXrGKDiVjwx/DpPsg==, - } + '@tybys/wasm-util@0.10.1': + resolution: {integrity: sha512-9tTaPJLSiejZKx+Bmog4uSubteqTvFrVrURwkmHixBo0G4seD0zUxp98E1DzUBJxLQ3NPwXrGKDiVjwx/DpPsg==} - "@types/aria-query@5.0.4": - resolution: - { - integrity: sha512-rfT93uj5s0PRL7EzccGMs3brplhcrghnDoV26NqKhCAS1hVo+WdNsPvE/yb6ilfr5hi2MEk6d5EWJTKdxg8jVw==, - } + '@types/aria-query@5.0.4': + resolution: {integrity: sha512-rfT93uj5s0PRL7EzccGMs3brplhcrghnDoV26NqKhCAS1hVo+WdNsPvE/yb6ilfr5hi2MEk6d5EWJTKdxg8jVw==} - "@types/babel__core@7.20.5": - resolution: - { - integrity: sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==, - } + '@types/babel__core@7.20.5': + resolution: {integrity: sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==} - "@types/babel__generator@7.27.0": - resolution: - { - integrity: sha512-ufFd2Xi92OAVPYsy+P4n7/U7e68fex0+Ee8gSG9KX7eo084CWiQ4sdxktvdl0bOPupXtVJPY19zk6EwWqUQ8lg==, - } + '@types/babel__generator@7.27.0': + resolution: {integrity: sha512-ufFd2Xi92OAVPYsy+P4n7/U7e68fex0+Ee8gSG9KX7eo084CWiQ4sdxktvdl0bOPupXtVJPY19zk6EwWqUQ8lg==} - "@types/babel__template@7.4.4": - resolution: - { - integrity: sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==, - } + '@types/babel__template@7.4.4': + resolution: {integrity: sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==} - "@types/babel__traverse@7.28.0": - resolution: - { - integrity: sha512-8PvcXf70gTDZBgt9ptxJ8elBeBjcLOAcOtoO/mPJjtji1+CdGbHgm77om1GrsPxsiE+uXIpNSK64UYaIwQXd4Q==, - } + '@types/babel__traverse@7.28.0': + resolution: {integrity: sha512-8PvcXf70gTDZBgt9ptxJ8elBeBjcLOAcOtoO/mPJjtji1+CdGbHgm77om1GrsPxsiE+uXIpNSK64UYaIwQXd4Q==} - "@types/chai@5.2.3": - resolution: - { - integrity: sha512-Mw558oeA9fFbv65/y4mHtXDs9bPnFMZAL/jxdPFUpOHHIXX91mcgEHbS5Lahr+pwZFR8A7GQleRWeI6cGFC2UA==, - } + '@types/chai@5.2.3': + resolution: {integrity: sha512-Mw558oeA9fFbv65/y4mHtXDs9bPnFMZAL/jxdPFUpOHHIXX91mcgEHbS5Lahr+pwZFR8A7GQleRWeI6cGFC2UA==} - "@types/content-type@1.1.9": - resolution: - { - integrity: sha512-Hq9IMnfekuOCsEmYl4QX2HBrT+XsfXiupfrLLY8Dcf3Puf4BkBOxSbWYTITSOQAhJoYPBez+b4MJRpIYL65z8A==, - } + '@types/content-type@1.1.9': + resolution: {integrity: sha512-Hq9IMnfekuOCsEmYl4QX2HBrT+XsfXiupfrLLY8Dcf3Puf4BkBOxSbWYTITSOQAhJoYPBez+b4MJRpIYL65z8A==} - "@types/deep-eql@4.0.2": - resolution: - { - integrity: sha512-c9h9dVVMigMPc4bwTvC5dxqtqJZwQPePsWjPlpSOnojbor6pGqdk541lfA7AqFQr5pB1BRdq0juY9db81BwyFw==, - } + '@types/deep-eql@4.0.2': + resolution: {integrity: sha512-c9h9dVVMigMPc4bwTvC5dxqtqJZwQPePsWjPlpSOnojbor6pGqdk541lfA7AqFQr5pB1BRdq0juY9db81BwyFw==} - "@types/doctrine@0.0.9": - resolution: - { - integrity: sha512-eOIHzCUSH7SMfonMG1LsC2f8vxBFtho6NGBznK41R84YzPuvSBzrhEps33IsQiOW9+VL6NQ9DbjQJznk/S4uRA==, - } + '@types/doctrine@0.0.9': + resolution: {integrity: sha512-eOIHzCUSH7SMfonMG1LsC2f8vxBFtho6NGBznK41R84YzPuvSBzrhEps33IsQiOW9+VL6NQ9DbjQJznk/S4uRA==} - "@types/dom-mediacapture-record@1.0.22": - resolution: - { - integrity: sha512-mUMZLK3NvwRLcAAT9qmcK+9p7tpU2FHdDsntR3YI4+GY88XrgG4XiE7u1Q2LAN2/FZOz/tdMDC3GQCR4T8nFuw==, - } + '@types/dom-mediacapture-record@1.0.22': + resolution: {integrity: sha512-mUMZLK3NvwRLcAAT9qmcK+9p7tpU2FHdDsntR3YI4+GY88XrgG4XiE7u1Q2LAN2/FZOz/tdMDC3GQCR4T8nFuw==} - "@types/dom-mediacapture-transform@0.1.11": - resolution: - { - integrity: sha512-Y2p+nGf1bF2XMttBnsVPHUWzRRZzqUoJAKmiP10b5umnO6DDrWI0BrGDJy1pOHoOULVmGSfFNkQrAlC5dcj6nQ==, - } + '@types/dom-mediacapture-transform@0.1.11': + resolution: {integrity: sha512-Y2p+nGf1bF2XMttBnsVPHUWzRRZzqUoJAKmiP10b5umnO6DDrWI0BrGDJy1pOHoOULVmGSfFNkQrAlC5dcj6nQ==} - "@types/dom-webcodecs@0.1.18": - resolution: - { - integrity: sha512-vAvE8C9DGWR+tkb19xyjk1TSUlJ7RUzzp4a9Anu7mwBT+fpyePWK1UxmH14tMO5zHmrnrRIMg5NutnnDztLxgg==, - } + '@types/dom-webcodecs@0.1.18': + resolution: {integrity: sha512-vAvE8C9DGWR+tkb19xyjk1TSUlJ7RUzzp4a9Anu7mwBT+fpyePWK1UxmH14tMO5zHmrnrRIMg5NutnnDztLxgg==} - "@types/estree@1.0.8": - resolution: - { - integrity: sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==, - } + '@types/estree@1.0.8': + resolution: {integrity: sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==} - "@types/events@3.0.3": - resolution: - { - integrity: sha512-trOc4AAUThEz9hapPtSd7wf5tiQKvTtu5b371UxXdTuqzIh0ArcRspRP0i0Viu+LXstIQ1z96t1nsPxT9ol01g==, - } + '@types/events@3.0.3': + resolution: {integrity: sha512-trOc4AAUThEz9hapPtSd7wf5tiQKvTtu5b371UxXdTuqzIh0ArcRspRP0i0Viu+LXstIQ1z96t1nsPxT9ol01g==} - "@types/glob-to-regexp@0.4.4": - resolution: - { - integrity: sha512-nDKoaKJYbnn1MZxUY0cA1bPmmgZbg0cTq7Rh13d0KWYNOiKbqoR+2d89SnRPszGh7ROzSwZ/GOjZ4jPbmmZ6Eg==, - } + '@types/glob-to-regexp@0.4.4': + resolution: {integrity: sha512-nDKoaKJYbnn1MZxUY0cA1bPmmgZbg0cTq7Rh13d0KWYNOiKbqoR+2d89SnRPszGh7ROzSwZ/GOjZ4jPbmmZ6Eg==} - "@types/grecaptcha@3.0.9": - resolution: - { - integrity: sha512-fFxMtjAvXXMYTzDFK5NpcVB7WHnrHVLl00QzEGpuFxSAC789io6M+vjcn+g5FTEamIJtJr/IHkCDsqvJxeWDyw==, - } + '@types/grecaptcha@3.0.9': + resolution: {integrity: sha512-fFxMtjAvXXMYTzDFK5NpcVB7WHnrHVLl00QzEGpuFxSAC789io6M+vjcn+g5FTEamIJtJr/IHkCDsqvJxeWDyw==} - "@types/jsdom@21.1.7": - resolution: - { - integrity: sha512-yOriVnggzrnQ3a9OKOCxaVuSug3w3/SbOj5i7VwXWZEyUNl3bLF9V3MfxGbZKuwqJOQyRfqXyROBB1CoZLFWzA==, - } + '@types/jsdom@21.1.7': + resolution: {integrity: sha512-yOriVnggzrnQ3a9OKOCxaVuSug3w3/SbOj5i7VwXWZEyUNl3bLF9V3MfxGbZKuwqJOQyRfqXyROBB1CoZLFWzA==} - "@types/json-schema@7.0.15": - resolution: - { - integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==, - } + '@types/json-schema@7.0.15': + resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==} - "@types/json5@0.0.29": - resolution: - { - integrity: sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==, - } + '@types/json5@0.0.29': + resolution: {integrity: sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==} - "@types/lodash-es@4.17.12": - resolution: - { - integrity: sha512-0NgftHUcV4v34VhXm8QBSftKVXtbkBG3ViCjs6+eJ5a6y6Mi/jiFGPc1sC7QK+9BFhWrURE3EOggmWaSxL9OzQ==, - } + '@types/lodash-es@4.17.12': + resolution: {integrity: sha512-0NgftHUcV4v34VhXm8QBSftKVXtbkBG3ViCjs6+eJ5a6y6Mi/jiFGPc1sC7QK+9BFhWrURE3EOggmWaSxL9OzQ==} - "@types/lodash@4.17.24": - resolution: - { - integrity: sha512-gIW7lQLZbue7lRSWEFql49QJJWThrTFFeIMJdp3eH4tKoxm1OvEPg02rm4wCCSHS0cL3/Fizimb35b7k8atwsQ==, - } + '@types/lodash@4.17.24': + resolution: {integrity: sha512-gIW7lQLZbue7lRSWEFql49QJJWThrTFFeIMJdp3eH4tKoxm1OvEPg02rm4wCCSHS0cL3/Fizimb35b7k8atwsQ==} - "@types/mdx@2.0.13": - resolution: - { - integrity: sha512-+OWZQfAYyio6YkJb3HLxDrvnx6SWWDbC0zVPfBRzUk0/nqoDyf6dNxQi3eArPe8rJ473nobTMQ/8Zk+LxJ+Yuw==, - } + '@types/mdx@2.0.13': + resolution: {integrity: sha512-+OWZQfAYyio6YkJb3HLxDrvnx6SWWDbC0zVPfBRzUk0/nqoDyf6dNxQi3eArPe8rJ473nobTMQ/8Zk+LxJ+Yuw==} - "@types/minimatch@3.0.5": - resolution: - { - integrity: sha512-Klz949h02Gz2uZCMGwDUSDS1YBlTdDDgbWHi+81l29tQALUtvz4rAYi5uoVhE5Lagoq6DeqAUlbrHvW/mXDgdQ==, - } + '@types/minimatch@3.0.5': + resolution: {integrity: sha512-Klz949h02Gz2uZCMGwDUSDS1YBlTdDDgbWHi+81l29tQALUtvz4rAYi5uoVhE5Lagoq6DeqAUlbrHvW/mXDgdQ==} - "@types/node@24.12.2": - resolution: - { - integrity: sha512-A1sre26ke7HDIuY/M23nd9gfB+nrmhtYyMINbjI1zHJxYteKR6qSMX56FsmjMcDb3SMcjJg5BiRRgOCC/yBD0g==, - } + '@types/node@24.12.2': + resolution: {integrity: sha512-A1sre26ke7HDIuY/M23nd9gfB+nrmhtYyMINbjI1zHJxYteKR6qSMX56FsmjMcDb3SMcjJg5BiRRgOCC/yBD0g==} - "@types/normalize-package-data@2.4.4": - resolution: - { - integrity: sha512-37i+OaWTh9qeK4LSHPsyRC7NahnGotNuZvjLSgcPzblpHB3rrCJxAOgI5gCdKm7coonsaX1Of0ILiTcnZjbfxA==, - } + '@types/normalize-package-data@2.4.4': + resolution: {integrity: sha512-37i+OaWTh9qeK4LSHPsyRC7NahnGotNuZvjLSgcPzblpHB3rrCJxAOgI5gCdKm7coonsaX1Of0ILiTcnZjbfxA==} - "@types/pako@2.0.4": - resolution: - { - integrity: sha512-VWDCbrLeVXJM9fihYodcLiIv0ku+AlOa/TQ1SvYOaBuyrSKgEcro95LJyIsJ4vSo6BXIxOKxiJAat04CmST9Fw==, - } + '@types/pako@2.0.4': + resolution: {integrity: sha512-VWDCbrLeVXJM9fihYodcLiIv0ku+AlOa/TQ1SvYOaBuyrSKgEcro95LJyIsJ4vSo6BXIxOKxiJAat04CmST9Fw==} - "@types/qrcode@1.5.6": - resolution: - { - integrity: sha512-te7NQcV2BOvdj2b1hCAHzAoMNuj65kNBMz0KBaxM6c3VGBOhU0dURQKOtH8CFNI/dsKkwlv32p26qYQTWoB5bw==, - } + '@types/qrcode@1.5.6': + resolution: {integrity: sha512-te7NQcV2BOvdj2b1hCAHzAoMNuj65kNBMz0KBaxM6c3VGBOhU0dURQKOtH8CFNI/dsKkwlv32p26qYQTWoB5bw==} - "@types/react-dom@19.2.3": - resolution: - { - integrity: sha512-jp2L/eY6fn+KgVVQAOqYItbF0VY/YApe5Mz2F0aykSO8gx31bYCZyvSeYxCHKvzHG5eZjc+zyaS5BrBWya2+kQ==, - } + '@types/react-dom@19.2.3': + resolution: {integrity: sha512-jp2L/eY6fn+KgVVQAOqYItbF0VY/YApe5Mz2F0aykSO8gx31bYCZyvSeYxCHKvzHG5eZjc+zyaS5BrBWya2+kQ==} peerDependencies: - "@types/react": ^19.2.0 + '@types/react': ^19.2.0 - "@types/react@19.2.14": - resolution: - { - integrity: sha512-ilcTH/UniCkMdtexkoCN0bI7pMcJDvmQFPvuPvmEaYA/NSfFTAgdUSLAoVjaRJm7+6PvcM+q1zYOwS4wTYMF9w==, - } + '@types/react@19.2.14': + resolution: {integrity: sha512-ilcTH/UniCkMdtexkoCN0bI7pMcJDvmQFPvuPvmEaYA/NSfFTAgdUSLAoVjaRJm7+6PvcM+q1zYOwS4wTYMF9w==} - "@types/resolve@1.20.6": - resolution: - { - integrity: sha512-A4STmOXPhMUtHH+S6ymgE2GiBSMqf4oTvcQZMcHzokuTLVYzXTB8ttjcgxOVaAp2lGwEdzZ0J+cRbbeevQj1UQ==, - } + '@types/resolve@1.20.6': + resolution: {integrity: sha512-A4STmOXPhMUtHH+S6ymgE2GiBSMqf4oTvcQZMcHzokuTLVYzXTB8ttjcgxOVaAp2lGwEdzZ0J+cRbbeevQj1UQ==} - "@types/sdp-transform@2.15.0": - resolution: - { - integrity: sha512-ikIFF0EaYt/2XetIYYVeMj6SB52oVXFasJUXDzWHgzNJS5ep2Pbsu7f8f3Za+dEie8HQtt3Zr9mHYBpWT0XgxQ==, - } + '@types/sdp-transform@2.15.0': + resolution: {integrity: sha512-ikIFF0EaYt/2XetIYYVeMj6SB52oVXFasJUXDzWHgzNJS5ep2Pbsu7f8f3Za+dEie8HQtt3Zr9mHYBpWT0XgxQ==} - "@types/semver@7.7.1": - resolution: - { - integrity: sha512-FmgJfu+MOcQ370SD0ev7EI8TlCAfKYU+B4m5T3yXc1CiRN94g/SZPtsCkk506aUDtlMnFZvasDwHHUcZUEaYuA==, - } + '@types/semver@7.7.1': + resolution: {integrity: sha512-FmgJfu+MOcQ370SD0ev7EI8TlCAfKYU+B4m5T3yXc1CiRN94g/SZPtsCkk506aUDtlMnFZvasDwHHUcZUEaYuA==} - "@types/symlink-or-copy@1.2.2": - resolution: - { - integrity: sha512-MQ1AnmTLOncwEf9IVU+B2e4Hchrku5N67NkgcAHW0p3sdzPe0FNMANxEm6OJUzPniEQGkeT3OROLlCwZJLWFZA==, - } + '@types/symlink-or-copy@1.2.2': + resolution: {integrity: sha512-MQ1AnmTLOncwEf9IVU+B2e4Hchrku5N67NkgcAHW0p3sdzPe0FNMANxEm6OJUzPniEQGkeT3OROLlCwZJLWFZA==} - "@types/tough-cookie@4.0.5": - resolution: - { - integrity: sha512-/Ad8+nIOV7Rl++6f1BdKxFSMgmoqEoYbHRpPcx3JEfv8VRsQe9Z4mCXeJBzxs7mbHY/XOZZuXlRNfhpVPbs6ZA==, - } + '@types/tough-cookie@4.0.5': + resolution: {integrity: sha512-/Ad8+nIOV7Rl++6f1BdKxFSMgmoqEoYbHRpPcx3JEfv8VRsQe9Z4mCXeJBzxs7mbHY/XOZZuXlRNfhpVPbs6ZA==} - "@types/uuid@10.0.0": - resolution: - { - integrity: sha512-7gqG38EyHgyP1S+7+xomFtL+ZNHcKv6DwNaCZmJmo1vgMugyF3TCnXVg4t1uk89mLNwnLtnY3TpOpCOyp1/xHQ==, - } + '@types/uuid@10.0.0': + resolution: {integrity: sha512-7gqG38EyHgyP1S+7+xomFtL+ZNHcKv6DwNaCZmJmo1vgMugyF3TCnXVg4t1uk89mLNwnLtnY3TpOpCOyp1/xHQ==} - "@types/yargs-parser@21.0.3": - resolution: - { - integrity: sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ==, - } + '@types/yargs-parser@21.0.3': + resolution: {integrity: sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ==} - "@types/yargs@17.0.35": - resolution: - { - integrity: sha512-qUHkeCyQFxMXg79wQfTtfndEC+N9ZZg76HJftDJp+qH2tV7Gj4OJi7l+PiWwJ+pWtW8GwSmqsDj/oymhrTWXjg==, - } + '@types/yargs@17.0.35': + resolution: {integrity: sha512-qUHkeCyQFxMXg79wQfTtfndEC+N9ZZg76HJftDJp+qH2tV7Gj4OJi7l+PiWwJ+pWtW8GwSmqsDj/oymhrTWXjg==} - "@typescript-eslint/eslint-plugin@8.58.2": - resolution: - { - integrity: sha512-aC2qc5thQahutKjP+cl8cgN9DWe3ZUqVko30CMSZHnFEHyhOYoZSzkGtAI2mcwZ38xeImDucI4dnqsHiOYuuCw==, - } - engines: { node: ^18.18.0 || ^20.9.0 || >=21.1.0 } + '@typescript-eslint/eslint-plugin@8.58.2': + resolution: {integrity: sha512-aC2qc5thQahutKjP+cl8cgN9DWe3ZUqVko30CMSZHnFEHyhOYoZSzkGtAI2mcwZ38xeImDucI4dnqsHiOYuuCw==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: - "@typescript-eslint/parser": ^8.58.2 + '@typescript-eslint/parser': ^8.58.2 eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 - typescript: ">=4.8.4 <6.1.0" + typescript: '>=4.8.4 <6.1.0' - "@typescript-eslint/experimental-utils@5.62.0": - resolution: - { - integrity: sha512-RTXpeB3eMkpoclG3ZHft6vG/Z30azNHuqY6wKPBHlVMZFuEvrtlEDe8gMqDb+SO+9hjC/pLekeSCryf9vMZlCw==, - } - engines: { node: ^12.22.0 || ^14.17.0 || >=16.0.0 } + '@typescript-eslint/experimental-utils@5.62.0': + resolution: {integrity: sha512-RTXpeB3eMkpoclG3ZHft6vG/Z30azNHuqY6wKPBHlVMZFuEvrtlEDe8gMqDb+SO+9hjC/pLekeSCryf9vMZlCw==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} peerDependencies: eslint: ^6.0.0 || ^7.0.0 || ^8.0.0 - "@typescript-eslint/parser@8.58.2": - resolution: - { - integrity: sha512-/Zb/xaIDfxeJnvishjGdcR4jmr7S+bda8PKNhRGdljDM+elXhlvN0FyPSsMnLmJUrVG9aPO6dof80wjMawsASg==, - } - engines: { node: ^18.18.0 || ^20.9.0 || >=21.1.0 } + '@typescript-eslint/parser@8.58.2': + resolution: {integrity: sha512-/Zb/xaIDfxeJnvishjGdcR4jmr7S+bda8PKNhRGdljDM+elXhlvN0FyPSsMnLmJUrVG9aPO6dof80wjMawsASg==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 - typescript: ">=4.8.4 <6.1.0" + typescript: '>=4.8.4 <6.1.0' - "@typescript-eslint/project-service@8.58.2": - resolution: - { - integrity: sha512-Cq6UfpZZk15+r87BkIh5rDpi38W4b+Sjnb8wQCPPDDweS/LRCFjCyViEbzHk5Ck3f2QDfgmlxqSa7S7clDtlfg==, - } - engines: { node: ^18.18.0 || ^20.9.0 || >=21.1.0 } + '@typescript-eslint/project-service@8.58.2': + resolution: {integrity: sha512-Cq6UfpZZk15+r87BkIh5rDpi38W4b+Sjnb8wQCPPDDweS/LRCFjCyViEbzHk5Ck3f2QDfgmlxqSa7S7clDtlfg==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: - typescript: ">=4.8.4 <6.1.0" + typescript: '>=4.8.4 <6.1.0' - "@typescript-eslint/scope-manager@5.62.0": - resolution: - { - integrity: sha512-VXuvVvZeQCQb5Zgf4HAxc04q5j+WrNAtNh9OwCsCgpKqESMTu3tF/jhZ3xG6T4NZwWl65Bg8KuS2uEvhSfLl0w==, - } - engines: { node: ^12.22.0 || ^14.17.0 || >=16.0.0 } + '@typescript-eslint/scope-manager@5.62.0': + resolution: {integrity: sha512-VXuvVvZeQCQb5Zgf4HAxc04q5j+WrNAtNh9OwCsCgpKqESMTu3tF/jhZ3xG6T4NZwWl65Bg8KuS2uEvhSfLl0w==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - "@typescript-eslint/scope-manager@8.58.2": - resolution: - { - integrity: sha512-SgmyvDPexWETQek+qzZnrG6844IaO02UVyOLhI4wpo82dpZJY9+6YZCKAMFzXb7qhx37mFK1QcPQ18tud+vo6Q==, - } - engines: { node: ^18.18.0 || ^20.9.0 || >=21.1.0 } + '@typescript-eslint/scope-manager@8.58.2': + resolution: {integrity: sha512-SgmyvDPexWETQek+qzZnrG6844IaO02UVyOLhI4wpo82dpZJY9+6YZCKAMFzXb7qhx37mFK1QcPQ18tud+vo6Q==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - "@typescript-eslint/tsconfig-utils@8.58.2": - resolution: - { - integrity: sha512-3SR+RukipDvkkKp/d0jP0dyzuls3DbGmwDpVEc5wqk5f38KFThakqAAO0XMirWAE+kT00oTauTbzMFGPoAzB0A==, - } - engines: { node: ^18.18.0 || ^20.9.0 || >=21.1.0 } + '@typescript-eslint/tsconfig-utils@8.58.2': + resolution: {integrity: sha512-3SR+RukipDvkkKp/d0jP0dyzuls3DbGmwDpVEc5wqk5f38KFThakqAAO0XMirWAE+kT00oTauTbzMFGPoAzB0A==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: - typescript: ">=4.8.4 <6.1.0" + typescript: '>=4.8.4 <6.1.0' - "@typescript-eslint/type-utils@8.58.2": - resolution: - { - integrity: sha512-Z7EloNR/B389FvabdGeTo2XMs4W9TjtPiO9DAsmT0yom0bwlPyRjkJ1uCdW1DvrrrYP50AJZ9Xc3sByZA9+dcg==, - } - engines: { node: ^18.18.0 || ^20.9.0 || >=21.1.0 } + '@typescript-eslint/type-utils@8.58.2': + resolution: {integrity: sha512-Z7EloNR/B389FvabdGeTo2XMs4W9TjtPiO9DAsmT0yom0bwlPyRjkJ1uCdW1DvrrrYP50AJZ9Xc3sByZA9+dcg==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 - typescript: ">=4.8.4 <6.1.0" + typescript: '>=4.8.4 <6.1.0' - "@typescript-eslint/types@5.62.0": - resolution: - { - integrity: sha512-87NVngcbVXUahrRTqIK27gD2t5Cu1yuCXxbLcFtCzZGlfyVWWh8mLHkoxzjsB6DDNnvdL+fW8MiwPEJyGJQDgQ==, - } - engines: { node: ^12.22.0 || ^14.17.0 || >=16.0.0 } + '@typescript-eslint/types@5.62.0': + resolution: {integrity: sha512-87NVngcbVXUahrRTqIK27gD2t5Cu1yuCXxbLcFtCzZGlfyVWWh8mLHkoxzjsB6DDNnvdL+fW8MiwPEJyGJQDgQ==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - "@typescript-eslint/types@8.58.2": - resolution: - { - integrity: sha512-9TukXyATBQf/Jq9AMQXfvurk+G5R2MwfqQGDR2GzGz28HvY/lXNKGhkY+6IOubwcquikWk5cjlgPvD2uAA7htQ==, - } - engines: { node: ^18.18.0 || ^20.9.0 || >=21.1.0 } + '@typescript-eslint/types@8.58.2': + resolution: {integrity: sha512-9TukXyATBQf/Jq9AMQXfvurk+G5R2MwfqQGDR2GzGz28HvY/lXNKGhkY+6IOubwcquikWk5cjlgPvD2uAA7htQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - "@typescript-eslint/typescript-estree@5.62.0": - resolution: - { - integrity: sha512-CmcQ6uY7b9y694lKdRB8FEel7JbU/40iSAPomu++SjLMntB+2Leay2LO6i8VnJk58MtE9/nQSFIH6jpyRWyYzA==, - } - engines: { node: ^12.22.0 || ^14.17.0 || >=16.0.0 } + '@typescript-eslint/typescript-estree@5.62.0': + resolution: {integrity: sha512-CmcQ6uY7b9y694lKdRB8FEel7JbU/40iSAPomu++SjLMntB+2Leay2LO6i8VnJk58MtE9/nQSFIH6jpyRWyYzA==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} peerDependencies: - typescript: "*" + typescript: '*' peerDependenciesMeta: typescript: optional: true - "@typescript-eslint/typescript-estree@8.58.2": - resolution: - { - integrity: sha512-ELGuoofuhhoCvNbQjFFiobFcGgcDCEm0ThWdmO4Z0UzLqPXS3KFvnEZ+SHewwOYHjM09tkzOWXNTv9u6Gqtyuw==, - } - engines: { node: ^18.18.0 || ^20.9.0 || >=21.1.0 } + '@typescript-eslint/typescript-estree@8.58.2': + resolution: {integrity: sha512-ELGuoofuhhoCvNbQjFFiobFcGgcDCEm0ThWdmO4Z0UzLqPXS3KFvnEZ+SHewwOYHjM09tkzOWXNTv9u6Gqtyuw==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: - typescript: ">=4.8.4 <6.1.0" + typescript: '>=4.8.4 <6.1.0' - "@typescript-eslint/utils@5.62.0": - resolution: - { - integrity: sha512-n8oxjeb5aIbPFEtmQxQYOLI0i9n5ySBEY/ZEHHZqKQSFnxio1rv6dthascc9dLuwrL0RC5mPCxB7vnAVGAYWAQ==, - } - engines: { node: ^12.22.0 || ^14.17.0 || >=16.0.0 } + '@typescript-eslint/utils@5.62.0': + resolution: {integrity: sha512-n8oxjeb5aIbPFEtmQxQYOLI0i9n5ySBEY/ZEHHZqKQSFnxio1rv6dthascc9dLuwrL0RC5mPCxB7vnAVGAYWAQ==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} peerDependencies: eslint: ^6.0.0 || ^7.0.0 || ^8.0.0 - "@typescript-eslint/utils@8.58.2": - resolution: - { - integrity: sha512-QZfjHNEzPY8+l0+fIXMvuQ2sJlplB4zgDZvA+NmvZsZv3EQwOcc1DuIU1VJUTWZ/RKouBMhDyNaBMx4sWvrzRA==, - } - engines: { node: ^18.18.0 || ^20.9.0 || >=21.1.0 } + '@typescript-eslint/utils@8.58.2': + resolution: {integrity: sha512-QZfjHNEzPY8+l0+fIXMvuQ2sJlplB4zgDZvA+NmvZsZv3EQwOcc1DuIU1VJUTWZ/RKouBMhDyNaBMx4sWvrzRA==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 - typescript: ">=4.8.4 <6.1.0" + typescript: '>=4.8.4 <6.1.0' - "@typescript-eslint/visitor-keys@5.62.0": - resolution: - { - integrity: sha512-07ny+LHRzQXepkGg6w0mFY41fVUNBrL2Roj/++7V1txKugfjm/Ci/qSND03r2RhlJhJYMcTn9AhhSSqQp0Ysyw==, - } - engines: { node: ^12.22.0 || ^14.17.0 || >=16.0.0 } + '@typescript-eslint/visitor-keys@5.62.0': + resolution: {integrity: sha512-07ny+LHRzQXepkGg6w0mFY41fVUNBrL2Roj/++7V1txKugfjm/Ci/qSND03r2RhlJhJYMcTn9AhhSSqQp0Ysyw==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - "@typescript-eslint/visitor-keys@8.58.2": - resolution: - { - integrity: sha512-f1WO2Lx8a9t8DARmcWAUPJbu0G20bJlj8L4z72K00TMeJAoyLr/tHhI/pzYBLrR4dXWkcxO1cWYZEOX8DKHTqA==, - } - engines: { node: ^18.18.0 || ^20.9.0 || >=21.1.0 } + '@typescript-eslint/visitor-keys@8.58.2': + resolution: {integrity: sha512-f1WO2Lx8a9t8DARmcWAUPJbu0G20bJlj8L4z72K00TMeJAoyLr/tHhI/pzYBLrR4dXWkcxO1cWYZEOX8DKHTqA==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - "@ungap/structured-clone@1.3.0": - resolution: - { - integrity: sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g==, - } + '@ungap/structured-clone@1.3.0': + resolution: {integrity: sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g==} - "@use-gesture/core@10.3.1": - resolution: - { - integrity: sha512-WcINiDt8WjqBdUXye25anHiNxPc0VOrlT8F6LLkU6cycrOGUDyY/yyFmsg3k8i5OLvv25llc0QC45GhR/C8llw==, - } + '@use-gesture/core@10.3.1': + resolution: {integrity: sha512-WcINiDt8WjqBdUXye25anHiNxPc0VOrlT8F6LLkU6cycrOGUDyY/yyFmsg3k8i5OLvv25llc0QC45GhR/C8llw==} - "@use-gesture/react@10.3.1": - resolution: - { - integrity: sha512-Yy19y6O2GJq8f7CHf7L0nxL8bf4PZCPaVOCgJrusOeFHY1LvHgYXnmnXg6N5iwAnbgbZCDjo60SiM6IPJi9C5g==, - } + '@use-gesture/react@10.3.1': + resolution: {integrity: sha512-Yy19y6O2GJq8f7CHf7L0nxL8bf4PZCPaVOCgJrusOeFHY1LvHgYXnmnXg6N5iwAnbgbZCDjo60SiM6IPJi9C5g==} peerDependencies: - react: ">= 16.8.0" + react: '>= 16.8.0' - "@vector-im/compound-design-tokens@10.1.0": - resolution: - { - integrity: sha512-o+7DGx+NygpT2NPE1Jo//7NZDuyjzRH06eRchS0ZlkJicKx/impEmShmHU/XiE4P84BIFOo9eZ1Ws+rAym6Tuw==, - } + '@vector-im/compound-design-tokens@10.1.0': + resolution: {integrity: sha512-o+7DGx+NygpT2NPE1Jo//7NZDuyjzRH06eRchS0ZlkJicKx/impEmShmHU/XiE4P84BIFOo9eZ1Ws+rAym6Tuw==} peerDependencies: - "@types/react": "*" + '@types/react': '*' react: ^17 || ^18 || ^19.0.0 peerDependenciesMeta: - "@types/react": + '@types/react': optional: true react: optional: true - "@vector-im/compound-web@9.2.0": - resolution: - { - integrity: sha512-jHbABGEQ2yqNtm5xRIkklQs198VEfSk9AJQolI+e4WSJ0xg8Ozyv9t9KIuKQAmjdSV9aow5G6hDE861XB6DQgw==, - } + '@vector-im/compound-web@9.2.0': + resolution: {integrity: sha512-jHbABGEQ2yqNtm5xRIkklQs198VEfSk9AJQolI+e4WSJ0xg8Ozyv9t9KIuKQAmjdSV9aow5G6hDE861XB6DQgw==} peerDependencies: - "@fontsource/inconsolata": ^5 - "@fontsource/inter": ^5 - "@types/react": "*" - "@vector-im/compound-design-tokens": ">=1.6.1 <11.0.0" + '@fontsource/inconsolata': ^5 + '@fontsource/inter': ^5 + '@types/react': '*' + '@vector-im/compound-design-tokens': '>=1.6.1 <11.0.0' react: ^18 || ^19.0.0 peerDependenciesMeta: - "@types/react": + '@types/react': optional: true - "@vitejs/plugin-react@4.7.0": - resolution: - { - integrity: sha512-gUu9hwfWvvEDBBmgtAowQCojwZmJ5mcLn3aufeCsitijs3+f2NsrPtlAWIR6OPiqljl96GVCUbLe0HyqIpVaoA==, - } - engines: { node: ^14.18.0 || >=16.0.0 } + '@vitejs/plugin-react@4.7.0': + resolution: {integrity: sha512-gUu9hwfWvvEDBBmgtAowQCojwZmJ5mcLn3aufeCsitijs3+f2NsrPtlAWIR6OPiqljl96GVCUbLe0HyqIpVaoA==} + engines: {node: ^14.18.0 || >=16.0.0} peerDependencies: vite: ^4.2.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 - "@vitest/coverage-v8@4.1.4": - resolution: - { - integrity: sha512-x7FptB5oDruxNPDNY2+S8tCh0pcq7ymCe1gTHcsp733jYjrJl8V1gMUlVysuCD9Kz46Xz9t1akkv08dPcYDs1w==, - } + '@vitest/coverage-v8@4.1.4': + resolution: {integrity: sha512-x7FptB5oDruxNPDNY2+S8tCh0pcq7ymCe1gTHcsp733jYjrJl8V1gMUlVysuCD9Kz46Xz9t1akkv08dPcYDs1w==} peerDependencies: - "@vitest/browser": 4.1.4 + '@vitest/browser': 4.1.4 vitest: 4.1.4 peerDependenciesMeta: - "@vitest/browser": + '@vitest/browser': optional: true - "@vitest/expect@3.2.4": - resolution: - { - integrity: sha512-Io0yyORnB6sikFlt8QW5K7slY4OjqNX9jmJQ02QDda8lyM6B5oNgVWoSoKPac8/kgnCUzuHQKrSLtu/uOqqrig==, - } + '@vitest/expect@3.2.4': + resolution: {integrity: sha512-Io0yyORnB6sikFlt8QW5K7slY4OjqNX9jmJQ02QDda8lyM6B5oNgVWoSoKPac8/kgnCUzuHQKrSLtu/uOqqrig==} - "@vitest/expect@4.1.4": - resolution: - { - integrity: sha512-iPBpra+VDuXmBFI3FMKHSFXp3Gx5HfmSCE8X67Dn+bwephCnQCaB7qWK2ldHa+8ncN8hJU8VTMcxjPpyMkUjww==, - } + '@vitest/expect@4.1.4': + resolution: {integrity: sha512-iPBpra+VDuXmBFI3FMKHSFXp3Gx5HfmSCE8X67Dn+bwephCnQCaB7qWK2ldHa+8ncN8hJU8VTMcxjPpyMkUjww==} - "@vitest/mocker@4.1.4": - resolution: - { - integrity: sha512-R9HTZBhW6yCSGbGQnDnH3QHfJxokKN4KB+Yvk9Q1le7eQNYwiCyKxmLmurSpFy6BzJanSLuEUDrD+j97Q+ZLPg==, - } + '@vitest/mocker@4.1.4': + resolution: {integrity: sha512-R9HTZBhW6yCSGbGQnDnH3QHfJxokKN4KB+Yvk9Q1le7eQNYwiCyKxmLmurSpFy6BzJanSLuEUDrD+j97Q+ZLPg==} peerDependencies: msw: ^2.4.9 vite: ^6.0.0 || ^7.0.0 || ^8.0.0 @@ -4341,1559 +3079,878 @@ packages: vite: optional: true - "@vitest/pretty-format@3.2.4": - resolution: - { - integrity: sha512-IVNZik8IVRJRTr9fxlitMKeJeXFFFN0JaB9PHPGQ8NKQbGpfjlTx9zO4RefN8gp7eqjNy8nyK3NZmBzOPeIxtA==, - } + '@vitest/pretty-format@3.2.4': + resolution: {integrity: sha512-IVNZik8IVRJRTr9fxlitMKeJeXFFFN0JaB9PHPGQ8NKQbGpfjlTx9zO4RefN8gp7eqjNy8nyK3NZmBzOPeIxtA==} - "@vitest/pretty-format@4.1.4": - resolution: - { - integrity: sha512-ddmDHU0gjEUyEVLxtZa7xamrpIefdEETu3nZjWtHeZX4QxqJ7tRxSteHVXJOcr8jhiLoGAhkK4WJ3WqBpjx42A==, - } + '@vitest/pretty-format@4.1.4': + resolution: {integrity: sha512-ddmDHU0gjEUyEVLxtZa7xamrpIefdEETu3nZjWtHeZX4QxqJ7tRxSteHVXJOcr8jhiLoGAhkK4WJ3WqBpjx42A==} - "@vitest/runner@4.1.4": - resolution: - { - integrity: sha512-xTp7VZ5aXP5ZJrn15UtJUWlx6qXLnGtF6jNxHepdPHpMfz/aVPx+htHtgcAL2mDXJgKhpoo2e9/hVJsIeFbytQ==, - } + '@vitest/runner@4.1.4': + resolution: {integrity: sha512-xTp7VZ5aXP5ZJrn15UtJUWlx6qXLnGtF6jNxHepdPHpMfz/aVPx+htHtgcAL2mDXJgKhpoo2e9/hVJsIeFbytQ==} - "@vitest/snapshot@4.1.4": - resolution: - { - integrity: sha512-MCjCFgaS8aZz+m5nTcEcgk/xhWv0rEH4Yl53PPlMXOZ1/Ka2VcZU6CJ+MgYCZbcJvzGhQRjVrGQNZqkGPttIKw==, - } + '@vitest/snapshot@4.1.4': + resolution: {integrity: sha512-MCjCFgaS8aZz+m5nTcEcgk/xhWv0rEH4Yl53PPlMXOZ1/Ka2VcZU6CJ+MgYCZbcJvzGhQRjVrGQNZqkGPttIKw==} - "@vitest/spy@3.2.4": - resolution: - { - integrity: sha512-vAfasCOe6AIK70iP5UD11Ac4siNUNJ9i/9PZ3NKx07sG6sUxeag1LWdNrMWeKKYBLlzuK+Gn65Yd5nyL6ds+nw==, - } + '@vitest/spy@3.2.4': + resolution: {integrity: sha512-vAfasCOe6AIK70iP5UD11Ac4siNUNJ9i/9PZ3NKx07sG6sUxeag1LWdNrMWeKKYBLlzuK+Gn65Yd5nyL6ds+nw==} - "@vitest/spy@4.1.4": - resolution: - { - integrity: sha512-XxNdAsKW7C+FLydqFJLb5KhJtl3PGCMmYwFRfhvIgxJvLSXhhVI1zM8f1qD3Zg7RCjTSzDVyct6sghs9UEgBEQ==, - } + '@vitest/spy@4.1.4': + resolution: {integrity: sha512-XxNdAsKW7C+FLydqFJLb5KhJtl3PGCMmYwFRfhvIgxJvLSXhhVI1zM8f1qD3Zg7RCjTSzDVyct6sghs9UEgBEQ==} - "@vitest/utils@3.2.4": - resolution: - { - integrity: sha512-fB2V0JFrQSMsCo9HiSq3Ezpdv4iYaXRG1Sx8edX3MwxfyNn83mKiGzOcH+Fkxt4MHxr3y42fQi1oeAInqgX2QA==, - } + '@vitest/utils@3.2.4': + resolution: {integrity: sha512-fB2V0JFrQSMsCo9HiSq3Ezpdv4iYaXRG1Sx8edX3MwxfyNn83mKiGzOcH+Fkxt4MHxr3y42fQi1oeAInqgX2QA==} - "@vitest/utils@4.1.4": - resolution: - { - integrity: sha512-13QMT+eysM5uVGa1rG4kegGYNp6cnQcsTc67ELFbhNLQO+vgsygtYJx2khvdt4gVQqSSpC/KT5FZZxUpP3Oatw==, - } + '@vitest/utils@4.1.4': + resolution: {integrity: sha512-13QMT+eysM5uVGa1rG4kegGYNp6cnQcsTc67ELFbhNLQO+vgsygtYJx2khvdt4gVQqSSpC/KT5FZZxUpP3Oatw==} - "@webcontainer/env@1.1.1": - resolution: - { - integrity: sha512-6aN99yL695Hi9SuIk1oC88l9o0gmxL1nGWWQ/kNy81HigJ0FoaoTXpytCj6ItzgyCEwA9kF1wixsTuv5cjsgng==, - } + '@webcontainer/env@1.1.1': + resolution: {integrity: sha512-6aN99yL695Hi9SuIk1oC88l9o0gmxL1nGWWQ/kNy81HigJ0FoaoTXpytCj6ItzgyCEwA9kF1wixsTuv5cjsgng==} acorn-jsx@5.3.2: - resolution: - { - integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==, - } + resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==} peerDependencies: acorn: ^6.0.0 || ^7.0.0 || ^8.0.0 acorn@8.16.0: - resolution: - { - integrity: sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw==, - } - engines: { node: ">=0.4.0" } + resolution: {integrity: sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw==} + engines: {node: '>=0.4.0'} hasBin: true agent-base@6.0.2: - resolution: - { - integrity: sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==, - } - engines: { node: ">= 6.0.0" } + resolution: {integrity: sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==} + engines: {node: '>= 6.0.0'} agent-base@7.1.4: - resolution: - { - integrity: sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ==, - } - engines: { node: ">= 14" } + resolution: {integrity: sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ==} + engines: {node: '>= 14'} ajv@6.14.0: - resolution: - { - integrity: sha512-IWrosm/yrn43eiKqkfkHis7QioDleaXQHdDVPKg0FSwwd/DuvyX79TZnFOnYpB7dcsFAMmtFztZuXPDvSePkFw==, - } + resolution: {integrity: sha512-IWrosm/yrn43eiKqkfkHis7QioDleaXQHdDVPKg0FSwwd/DuvyX79TZnFOnYpB7dcsFAMmtFztZuXPDvSePkFw==} another-json@0.2.0: - resolution: - { - integrity: sha512-/Ndrl68UQLhnCdsAzEXLMFuOR546o2qbYRqCglaNHbjXrwG1ayTcdwr3zkSGOGtGXDyR5X9nCFfnyG2AFJIsqg==, - } + resolution: {integrity: sha512-/Ndrl68UQLhnCdsAzEXLMFuOR546o2qbYRqCglaNHbjXrwG1ayTcdwr3zkSGOGtGXDyR5X9nCFfnyG2AFJIsqg==} ansi-regex@5.0.1: - resolution: - { - integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==, - } - engines: { node: ">=8" } + resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} + engines: {node: '>=8'} ansi-regex@6.2.2: - resolution: - { - integrity: sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==, - } - engines: { node: ">=12" } + resolution: {integrity: sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==} + engines: {node: '>=12'} ansi-styles@4.3.0: - resolution: - { - integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==, - } - engines: { node: ">=8" } + resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} + engines: {node: '>=8'} ansi-styles@5.2.0: - resolution: - { - integrity: sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==, - } - engines: { node: ">=10" } + resolution: {integrity: sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==} + engines: {node: '>=10'} ansi-styles@6.2.3: - resolution: - { - integrity: sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==, - } - engines: { node: ">=12" } + resolution: {integrity: sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==} + engines: {node: '>=12'} anymatch@3.1.3: - resolution: - { - integrity: sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==, - } - engines: { node: ">= 8" } + resolution: {integrity: sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==} + engines: {node: '>= 8'} are-docs-informative@0.0.2: - resolution: - { - integrity: sha512-ixiS0nLNNG5jNQzgZJNoUpBKdo9yTYZMGJ+QgT2jmjR7G7+QHRCc4v6LQ3NgE7EBJq+o0ams3waJwkrlBom8Ig==, - } - engines: { node: ">=14" } + resolution: {integrity: sha512-ixiS0nLNNG5jNQzgZJNoUpBKdo9yTYZMGJ+QgT2jmjR7G7+QHRCc4v6LQ3NgE7EBJq+o0ams3waJwkrlBom8Ig==} + engines: {node: '>=14'} argparse@2.0.1: - resolution: - { - integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==, - } + resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} aria-hidden@1.2.6: - resolution: - { - integrity: sha512-ik3ZgC9dY/lYVVM++OISsaYDeg1tb0VtP5uL3ouh1koGOaUMDPpbFIei4JkFimWUFPn90sbMNMXQAIVOlnYKJA==, - } - engines: { node: ">=10" } + resolution: {integrity: sha512-ik3ZgC9dY/lYVVM++OISsaYDeg1tb0VtP5uL3ouh1koGOaUMDPpbFIei4JkFimWUFPn90sbMNMXQAIVOlnYKJA==} + engines: {node: '>=10'} aria-query@5.3.0: - resolution: - { - integrity: sha512-b0P0sZPKtyu8HkeRAfCq0IfURZK+SuwMjY1UXGBU27wpAiTwQAIlq56IbIO+ytk/JjS1fMR14ee5WBBfKi5J6A==, - } + resolution: {integrity: sha512-b0P0sZPKtyu8HkeRAfCq0IfURZK+SuwMjY1UXGBU27wpAiTwQAIlq56IbIO+ytk/JjS1fMR14ee5WBBfKi5J6A==} aria-query@5.3.2: - resolution: - { - integrity: sha512-COROpnaoap1E2F000S62r6A60uHZnmlvomhfyT2DlTcrY1OrBKn2UhH7qn5wTC9zMvD0AY7csdPSNwKP+7WiQw==, - } - engines: { node: ">= 0.4" } + resolution: {integrity: sha512-COROpnaoap1E2F000S62r6A60uHZnmlvomhfyT2DlTcrY1OrBKn2UhH7qn5wTC9zMvD0AY7csdPSNwKP+7WiQw==} + engines: {node: '>= 0.4'} array-buffer-byte-length@1.0.2: - resolution: - { - integrity: sha512-LHE+8BuR7RYGDKvnrmcuSq3tDcKv9OFEXQt/HpbZhY7V6h0zlUXutnAD82GiFx9rdieCMjkvtcsPqBwgUl1Iiw==, - } - engines: { node: ">= 0.4" } + resolution: {integrity: sha512-LHE+8BuR7RYGDKvnrmcuSq3tDcKv9OFEXQt/HpbZhY7V6h0zlUXutnAD82GiFx9rdieCMjkvtcsPqBwgUl1Iiw==} + engines: {node: '>= 0.4'} array-includes@3.1.9: - resolution: - { - integrity: sha512-FmeCCAenzH0KH381SPT5FZmiA/TmpndpcaShhfgEN9eCVjnFBqq3l1xrI42y8+PPLI6hypzou4GXw00WHmPBLQ==, - } - engines: { node: ">= 0.4" } + resolution: {integrity: sha512-FmeCCAenzH0KH381SPT5FZmiA/TmpndpcaShhfgEN9eCVjnFBqq3l1xrI42y8+PPLI6hypzou4GXw00WHmPBLQ==} + engines: {node: '>= 0.4'} array-union@2.1.0: - resolution: - { - integrity: sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==, - } - engines: { node: ">=8" } + resolution: {integrity: sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==} + engines: {node: '>=8'} array.prototype.findlast@1.2.5: - resolution: - { - integrity: sha512-CVvd6FHg1Z3POpBLxO6E6zr+rSKEQ9L6rZHAaY7lLfhKsWYUBBOuMs0e9o24oopj6H+geRCX0YJ+TJLBK2eHyQ==, - } - engines: { node: ">= 0.4" } + resolution: {integrity: sha512-CVvd6FHg1Z3POpBLxO6E6zr+rSKEQ9L6rZHAaY7lLfhKsWYUBBOuMs0e9o24oopj6H+geRCX0YJ+TJLBK2eHyQ==} + engines: {node: '>= 0.4'} array.prototype.findlastindex@1.2.6: - resolution: - { - integrity: sha512-F/TKATkzseUExPlfvmwQKGITM3DGTK+vkAsCZoDc5daVygbJBnjEUCbgkAvVFsgfXfX4YIqZ/27G3k3tdXrTxQ==, - } - engines: { node: ">= 0.4" } + resolution: {integrity: sha512-F/TKATkzseUExPlfvmwQKGITM3DGTK+vkAsCZoDc5daVygbJBnjEUCbgkAvVFsgfXfX4YIqZ/27G3k3tdXrTxQ==} + engines: {node: '>= 0.4'} array.prototype.flat@1.3.3: - resolution: - { - integrity: sha512-rwG/ja1neyLqCuGZ5YYrznA62D4mZXg0i1cIskIUKSiqF3Cje9/wXAls9B9s1Wa2fomMsIv8czB8jZcPmxCXFg==, - } - engines: { node: ">= 0.4" } + resolution: {integrity: sha512-rwG/ja1neyLqCuGZ5YYrznA62D4mZXg0i1cIskIUKSiqF3Cje9/wXAls9B9s1Wa2fomMsIv8czB8jZcPmxCXFg==} + engines: {node: '>= 0.4'} array.prototype.flatmap@1.3.3: - resolution: - { - integrity: sha512-Y7Wt51eKJSyi80hFrJCePGGNo5ktJCslFuboqJsbf57CCPcm5zztluPlc4/aD8sWsKvlwatezpV4U1efk8kpjg==, - } - engines: { node: ">= 0.4" } + resolution: {integrity: sha512-Y7Wt51eKJSyi80hFrJCePGGNo5ktJCslFuboqJsbf57CCPcm5zztluPlc4/aD8sWsKvlwatezpV4U1efk8kpjg==} + engines: {node: '>= 0.4'} array.prototype.tosorted@1.1.4: - resolution: - { - integrity: sha512-p6Fx8B7b7ZhL/gmUsAy0D15WhvDccw3mnGNbZpi3pmeJdxtWsj2jEaI4Y6oo3XiHfzuSgPwKc04MYt6KgvC/wA==, - } - engines: { node: ">= 0.4" } + resolution: {integrity: sha512-p6Fx8B7b7ZhL/gmUsAy0D15WhvDccw3mnGNbZpi3pmeJdxtWsj2jEaI4Y6oo3XiHfzuSgPwKc04MYt6KgvC/wA==} + engines: {node: '>= 0.4'} arraybuffer.prototype.slice@1.0.4: - resolution: - { - integrity: sha512-BNoCY6SXXPQ7gF2opIP4GBE+Xw7U+pHMYKuzjgCN3GwiaIR09UUeKfheyIry77QtrCBlC0KK0q5/TER/tYh3PQ==, - } - engines: { node: ">= 0.4" } + resolution: {integrity: sha512-BNoCY6SXXPQ7gF2opIP4GBE+Xw7U+pHMYKuzjgCN3GwiaIR09UUeKfheyIry77QtrCBlC0KK0q5/TER/tYh3PQ==} + engines: {node: '>= 0.4'} asn1.js@4.10.1: - resolution: - { - integrity: sha512-p32cOF5q0Zqs9uBiONKYLm6BClCoBCM5O9JfeUSlnQLBTxYdTK+pW+nXflm8UkKd2UYlEbYz5qEi0JuZR9ckSw==, - } + resolution: {integrity: sha512-p32cOF5q0Zqs9uBiONKYLm6BClCoBCM5O9JfeUSlnQLBTxYdTK+pW+nXflm8UkKd2UYlEbYz5qEi0JuZR9ckSw==} assert@2.1.0: - resolution: - { - integrity: sha512-eLHpSK/Y4nhMJ07gDaAzoX/XAKS8PSaojml3M0DM4JpV1LAi5JOJ/p6H/XWrl8L+DzVEvVCW1z3vWAaB9oTsQw==, - } + resolution: {integrity: sha512-eLHpSK/Y4nhMJ07gDaAzoX/XAKS8PSaojml3M0DM4JpV1LAi5JOJ/p6H/XWrl8L+DzVEvVCW1z3vWAaB9oTsQw==} assertion-error@2.0.1: - resolution: - { - integrity: sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==, - } - engines: { node: ">=12" } + resolution: {integrity: sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==} + engines: {node: '>=12'} ast-types-flow@0.0.8: - resolution: - { - integrity: sha512-OH/2E5Fg20h2aPrbe+QL8JZQFko0YZaF+j4mnQ7BGhfavO7OpSLa8a0y9sBwomHdSbkhTS8TQNayBfnW5DwbvQ==, - } + resolution: {integrity: sha512-OH/2E5Fg20h2aPrbe+QL8JZQFko0YZaF+j4mnQ7BGhfavO7OpSLa8a0y9sBwomHdSbkhTS8TQNayBfnW5DwbvQ==} ast-types@0.16.1: - resolution: - { - integrity: sha512-6t10qk83GOG8p0vKmaCr8eiilZwO171AvbROMtvvNiwrTly62t+7XkA8RdIIVbpMhCASAsxgAzdRSwh6nw/5Dg==, - } - engines: { node: ">=4" } + resolution: {integrity: sha512-6t10qk83GOG8p0vKmaCr8eiilZwO171AvbROMtvvNiwrTly62t+7XkA8RdIIVbpMhCASAsxgAzdRSwh6nw/5Dg==} + engines: {node: '>=4'} ast-v8-to-istanbul@1.0.0: - resolution: - { - integrity: sha512-1fSfIwuDICFA4LKkCzRPO7F0hzFf0B7+Xqrl27ynQaa+Rh0e1Es0v6kWHPott3lU10AyAr7oKHa65OppjLn3Rg==, - } + resolution: {integrity: sha512-1fSfIwuDICFA4LKkCzRPO7F0hzFf0B7+Xqrl27ynQaa+Rh0e1Es0v6kWHPott3lU10AyAr7oKHa65OppjLn3Rg==} async-function@1.0.0: - resolution: - { - integrity: sha512-hsU18Ae8CDTR6Kgu9DYf0EbCr/a5iGL0rytQDobUcdpYOKokk8LEjVphnXkDkgpi0wYVsqrXuP0bZxJaTqdgoA==, - } - engines: { node: ">= 0.4" } + resolution: {integrity: sha512-hsU18Ae8CDTR6Kgu9DYf0EbCr/a5iGL0rytQDobUcdpYOKokk8LEjVphnXkDkgpi0wYVsqrXuP0bZxJaTqdgoA==} + engines: {node: '>= 0.4'} async@3.2.6: - resolution: - { - integrity: sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA==, - } + resolution: {integrity: sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA==} autoprefixer@10.5.0: - resolution: - { - integrity: sha512-FMhOoZV4+qR6aTUALKX2rEqGG+oyATvwBt9IIzVR5rMa2HRWPkxf+P+PAJLD1I/H5/II+HuZcBJYEFBpq39ong==, - } - engines: { node: ^10 || ^12 || >=14 } + resolution: {integrity: sha512-FMhOoZV4+qR6aTUALKX2rEqGG+oyATvwBt9IIzVR5rMa2HRWPkxf+P+PAJLD1I/H5/II+HuZcBJYEFBpq39ong==} + engines: {node: ^10 || ^12 || >=14} hasBin: true peerDependencies: postcss: ^8.1.0 available-typed-arrays@1.0.7: - resolution: - { - integrity: sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==, - } - engines: { node: ">= 0.4" } + resolution: {integrity: sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==} + engines: {node: '>= 0.4'} axe-core@4.11.3: - resolution: - { - integrity: sha512-zBQouZixDTbo3jMGqHKyePxYxr1e5W8UdTmBQ7sNtaA9M2bE32daxxPLS/jojhKOHxQ7LWwPjfiwf/fhaJWzlg==, - } - engines: { node: ">=4" } + resolution: {integrity: sha512-zBQouZixDTbo3jMGqHKyePxYxr1e5W8UdTmBQ7sNtaA9M2bE32daxxPLS/jojhKOHxQ7LWwPjfiwf/fhaJWzlg==} + engines: {node: '>=4'} axobject-query@4.1.0: - resolution: - { - integrity: sha512-qIj0G9wZbMGNLjLmg1PT6v2mE9AH2zlnADJD/2tC6E00hgmhUOfEB6greHPAfLRSufHqROIUTkw6E+M3lH0PTQ==, - } - engines: { node: ">= 0.4" } + resolution: {integrity: sha512-qIj0G9wZbMGNLjLmg1PT6v2mE9AH2zlnADJD/2tC6E00hgmhUOfEB6greHPAfLRSufHqROIUTkw6E+M3lH0PTQ==} + engines: {node: '>= 0.4'} b4a@1.8.0: - resolution: - { - integrity: sha512-qRuSmNSkGQaHwNbM7J78Wwy+ghLEYF1zNrSeMxj4Kgw6y33O3mXcQ6Ie9fRvfU/YnxWkOchPXbaLb73TkIsfdg==, - } + resolution: {integrity: sha512-qRuSmNSkGQaHwNbM7J78Wwy+ghLEYF1zNrSeMxj4Kgw6y33O3mXcQ6Ie9fRvfU/YnxWkOchPXbaLb73TkIsfdg==} peerDependencies: - react-native-b4a: "*" + react-native-b4a: '*' peerDependenciesMeta: react-native-b4a: optional: true babel-plugin-polyfill-corejs2@0.4.17: - resolution: - { - integrity: sha512-aTyf30K/rqAsNwN76zYrdtx8obu0E4KoUME29B1xj+B3WxgvWkp943vYQ+z8Mv3lw9xHXMHpvSPOBxzAkIa94w==, - } + resolution: {integrity: sha512-aTyf30K/rqAsNwN76zYrdtx8obu0E4KoUME29B1xj+B3WxgvWkp943vYQ+z8Mv3lw9xHXMHpvSPOBxzAkIa94w==} peerDependencies: - "@babel/core": ^7.4.0 || ^8.0.0-0 <8.0.0 + '@babel/core': ^7.4.0 || ^8.0.0-0 <8.0.0 babel-plugin-polyfill-corejs3@0.14.2: - resolution: - { - integrity: sha512-coWpDLJ410R781Npmn/SIBZEsAetR4xVi0SxLMXPaMO4lSf1MwnkGYMtkFxew0Dn8B3/CpbpYxN0JCgg8mn67g==, - } + resolution: {integrity: sha512-coWpDLJ410R781Npmn/SIBZEsAetR4xVi0SxLMXPaMO4lSf1MwnkGYMtkFxew0Dn8B3/CpbpYxN0JCgg8mn67g==} peerDependencies: - "@babel/core": ^7.4.0 || ^8.0.0-0 <8.0.0 + '@babel/core': ^7.4.0 || ^8.0.0-0 <8.0.0 babel-plugin-polyfill-regenerator@0.6.8: - resolution: - { - integrity: sha512-M762rNHfSF1EV3SLtnCJXFoQbbIIz0OyRwnCmV0KPC7qosSfCO0QLTSuJX3ayAebubhE6oYBAYPrBA5ljowaZg==, - } + resolution: {integrity: sha512-M762rNHfSF1EV3SLtnCJXFoQbbIIz0OyRwnCmV0KPC7qosSfCO0QLTSuJX3ayAebubhE6oYBAYPrBA5ljowaZg==} peerDependencies: - "@babel/core": ^7.4.0 || ^8.0.0-0 <8.0.0 + '@babel/core': ^7.4.0 || ^8.0.0-0 <8.0.0 babel-plugin-transform-vite-meta-env@1.0.3: - resolution: - { - integrity: sha512-eyfuDEXrMu667TQpmctHeTlJrZA6jXYHyEJFjcM0yEa60LS/LXlOg2PBbMb8DVS+V9CnTj/j9itdlDVMcY2zEg==, - } + resolution: {integrity: sha512-eyfuDEXrMu667TQpmctHeTlJrZA6jXYHyEJFjcM0yEa60LS/LXlOg2PBbMb8DVS+V9CnTj/j9itdlDVMcY2zEg==} balanced-match@4.0.4: - resolution: - { - integrity: sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==, - } - engines: { node: 18 || 20 || >=22 } + resolution: {integrity: sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==} + engines: {node: 18 || 20 || >=22} bare-events@2.8.2: - resolution: - { - integrity: sha512-riJjyv1/mHLIPX4RwiK+oW9/4c3TEUeORHKefKAKnZ5kyslbN+HXowtbaVEqt4IMUB7OXlfixcs6gsFeo/jhiQ==, - } + resolution: {integrity: sha512-riJjyv1/mHLIPX4RwiK+oW9/4c3TEUeORHKefKAKnZ5kyslbN+HXowtbaVEqt4IMUB7OXlfixcs6gsFeo/jhiQ==} peerDependencies: - bare-abort-controller: "*" + bare-abort-controller: '*' peerDependenciesMeta: bare-abort-controller: optional: true base-x@5.0.1: - resolution: - { - integrity: sha512-M7uio8Zt++eg3jPj+rHMfCC+IuygQHHCOU+IYsVtik6FWjuYpVt/+MRKcgsAMHh8mMFAwnB+Bs+mTrFiXjMzKg==, - } + resolution: {integrity: sha512-M7uio8Zt++eg3jPj+rHMfCC+IuygQHHCOU+IYsVtik6FWjuYpVt/+MRKcgsAMHh8mMFAwnB+Bs+mTrFiXjMzKg==} base64-js@1.5.1: - resolution: - { - integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==, - } + resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==} baseline-browser-mapping@2.10.19: - resolution: - { - integrity: sha512-qCkNLi2sfBOn8XhZQ0FXsT1Ki/Yo5P90hrkRamVFRS7/KV9hpfA4HkoWNU152+8w0zPjnxo5psx5NL3PSGgv5g==, - } - engines: { node: ">=6.0.0" } + resolution: {integrity: sha512-qCkNLi2sfBOn8XhZQ0FXsT1Ki/Yo5P90hrkRamVFRS7/KV9hpfA4HkoWNU152+8w0zPjnxo5psx5NL3PSGgv5g==} + engines: {node: '>=6.0.0'} hasBin: true before-after-hook@2.2.3: - resolution: - { - integrity: sha512-NzUnlZexiaH/46WDhANlyR2bXRopNg4F/zuSA3OpZnllCUgRaOF2znDioDWrmbNVsuZk6l9pMquQB38cfBZwkQ==, - } + resolution: {integrity: sha512-NzUnlZexiaH/46WDhANlyR2bXRopNg4F/zuSA3OpZnllCUgRaOF2znDioDWrmbNVsuZk6l9pMquQB38cfBZwkQ==} bent@7.3.12: - resolution: - { - integrity: sha512-T3yrKnVGB63zRuoco/7Ybl7BwwGZR0lceoVG5XmQyMIH9s19SV5m+a8qam4if0zQuAmOQTyPTPmsQBdAorGK3w==, - } + resolution: {integrity: sha512-T3yrKnVGB63zRuoco/7Ybl7BwwGZR0lceoVG5XmQyMIH9s19SV5m+a8qam4if0zQuAmOQTyPTPmsQBdAorGK3w==} binary-extensions@2.3.0: - resolution: - { - integrity: sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==, - } - engines: { node: ">=8" } + resolution: {integrity: sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==} + engines: {node: '>=8'} bl@5.1.0: - resolution: - { - integrity: sha512-tv1ZJHLfTDnXE6tMHv73YgSJaWR2AFuPwMntBe7XL/GBFHnT0CLnsHMogfk5+GzCDC5ZWarSCYaIGATZt9dNsQ==, - } + resolution: {integrity: sha512-tv1ZJHLfTDnXE6tMHv73YgSJaWR2AFuPwMntBe7XL/GBFHnT0CLnsHMogfk5+GzCDC5ZWarSCYaIGATZt9dNsQ==} bn.js@4.12.3: - resolution: - { - integrity: sha512-fGTi3gxV/23FTYdAoUtLYp6qySe2KE3teyZitipKNRuVYcBkoP/bB3guXN/XVKUe9mxCHXnc9C4ocyz8OmgN0g==, - } + resolution: {integrity: sha512-fGTi3gxV/23FTYdAoUtLYp6qySe2KE3teyZitipKNRuVYcBkoP/bB3guXN/XVKUe9mxCHXnc9C4ocyz8OmgN0g==} bn.js@5.2.3: - resolution: - { - integrity: sha512-EAcmnPkxpntVL+DS7bO1zhcZNvCkxqtkd0ZY53h06GNQ3DEkkGZ/gKgmDv6DdZQGj9BgfSPKtJJ7Dp1GPP8f7w==, - } + resolution: {integrity: sha512-EAcmnPkxpntVL+DS7bO1zhcZNvCkxqtkd0ZY53h06GNQ3DEkkGZ/gKgmDv6DdZQGj9BgfSPKtJJ7Dp1GPP8f7w==} boolbase@1.0.0: - resolution: - { - integrity: sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==, - } + resolution: {integrity: sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==} brace-expansion@5.0.5: - resolution: - { - integrity: sha512-VZznLgtwhn+Mact9tfiwx64fA9erHH/MCXEUfB/0bX/6Fz6ny5EGTXYltMocqg4xFAQZtnO3DHWWXi8RiuN7cQ==, - } - engines: { node: 18 || 20 || >=22 } + resolution: {integrity: sha512-VZznLgtwhn+Mact9tfiwx64fA9erHH/MCXEUfB/0bX/6Fz6ny5EGTXYltMocqg4xFAQZtnO3DHWWXi8RiuN7cQ==} + engines: {node: 18 || 20 || >=22} braces@3.0.3: - resolution: - { - integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==, - } - engines: { node: ">=8" } + resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==} + engines: {node: '>=8'} broccoli-node-api@1.7.0: - resolution: - { - integrity: sha512-QIqLSVJWJUVOhclmkmypJJH9u9s/aWH4+FH6Q6Ju5l+Io4dtwqdPUNmDfw40o6sxhbZHhqGujDJuHTML1wG8Yw==, - } + resolution: {integrity: sha512-QIqLSVJWJUVOhclmkmypJJH9u9s/aWH4+FH6Q6Ju5l+Io4dtwqdPUNmDfw40o6sxhbZHhqGujDJuHTML1wG8Yw==} broccoli-node-info@2.2.0: - resolution: - { - integrity: sha512-VabSGRpKIzpmC+r+tJueCE5h8k6vON7EIMMWu6d/FyPdtijwLQ7QvzShEw+m3mHoDzUaj/kiZsDYrS8X2adsBg==, - } - engines: { node: 8.* || >= 10.* } + resolution: {integrity: sha512-VabSGRpKIzpmC+r+tJueCE5h8k6vON7EIMMWu6d/FyPdtijwLQ7QvzShEw+m3mHoDzUaj/kiZsDYrS8X2adsBg==} + engines: {node: 8.* || >= 10.*} broccoli-output-wrapper@3.2.5: - resolution: - { - integrity: sha512-bQAtwjSrF4Nu0CK0JOy5OZqw9t5U0zzv2555EA/cF8/a8SLDTIetk9UgrtMVw7qKLKdSpOZ2liZNeZZDaKgayw==, - } - engines: { node: 10.* || >= 12.* } + resolution: {integrity: sha512-bQAtwjSrF4Nu0CK0JOy5OZqw9t5U0zzv2555EA/cF8/a8SLDTIetk9UgrtMVw7qKLKdSpOZ2liZNeZZDaKgayw==} + engines: {node: 10.* || >= 12.*} broccoli-plugin@4.0.7: - resolution: - { - integrity: sha512-a4zUsWtA1uns1K7p9rExYVYG99rdKeGRymW0qOCNkvDPHQxVi3yVyJHhQbM3EZwdt2E0mnhr5e0c/bPpJ7p3Wg==, - } - engines: { node: 10.* || >= 12.* } + resolution: {integrity: sha512-a4zUsWtA1uns1K7p9rExYVYG99rdKeGRymW0qOCNkvDPHQxVi3yVyJHhQbM3EZwdt2E0mnhr5e0c/bPpJ7p3Wg==} + engines: {node: 10.* || >= 12.*} brorand@1.1.0: - resolution: - { - integrity: sha512-cKV8tMCEpQs4hK/ik71d6LrPOnpkpGBR0wzxqr68g2m/LB2GxVYQroAjMJZRVM1Y4BCjCKc3vAamxSzOY2RP+w==, - } + resolution: {integrity: sha512-cKV8tMCEpQs4hK/ik71d6LrPOnpkpGBR0wzxqr68g2m/LB2GxVYQroAjMJZRVM1Y4BCjCKc3vAamxSzOY2RP+w==} browser-resolve@2.0.0: - resolution: - { - integrity: sha512-7sWsQlYL2rGLy2IWm8WL8DCTJvYLc/qlOnsakDac87SOoCd16WLsaAMdCiAqsTNHIe+SXfaqyxyo6THoWqs8WQ==, - } + resolution: {integrity: sha512-7sWsQlYL2rGLy2IWm8WL8DCTJvYLc/qlOnsakDac87SOoCd16WLsaAMdCiAqsTNHIe+SXfaqyxyo6THoWqs8WQ==} browserify-aes@1.2.0: - resolution: - { - integrity: sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA==, - } + resolution: {integrity: sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA==} browserify-cipher@1.0.1: - resolution: - { - integrity: sha512-sPhkz0ARKbf4rRQt2hTpAHqn47X3llLkUGn+xEJzLjwY8LRs2p0v7ljvI5EyoRO/mexrNunNECisZs+gw2zz1w==, - } + resolution: {integrity: sha512-sPhkz0ARKbf4rRQt2hTpAHqn47X3llLkUGn+xEJzLjwY8LRs2p0v7ljvI5EyoRO/mexrNunNECisZs+gw2zz1w==} browserify-des@1.0.2: - resolution: - { - integrity: sha512-BioO1xf3hFwz4kc6iBhI3ieDFompMhrMlnDFC4/0/vd5MokpuAc3R+LYbwTA9A5Yc9pq9UYPqffKpW2ObuwX5A==, - } + resolution: {integrity: sha512-BioO1xf3hFwz4kc6iBhI3ieDFompMhrMlnDFC4/0/vd5MokpuAc3R+LYbwTA9A5Yc9pq9UYPqffKpW2ObuwX5A==} browserify-rsa@4.1.1: - resolution: - { - integrity: sha512-YBjSAiTqM04ZVei6sXighu679a3SqWORA3qZTEqZImnlkDIFtKc6pNutpjyZ8RJTjQtuYfeetkxM11GwoYXMIQ==, - } - engines: { node: ">= 0.10" } + resolution: {integrity: sha512-YBjSAiTqM04ZVei6sXighu679a3SqWORA3qZTEqZImnlkDIFtKc6pNutpjyZ8RJTjQtuYfeetkxM11GwoYXMIQ==} + engines: {node: '>= 0.10'} browserify-sign@4.2.5: - resolution: - { - integrity: sha512-C2AUdAJg6rlM2W5QMp2Q4KGQMVBwR1lIimTsUnutJ8bMpW5B52pGpR2gEnNBNwijumDo5FojQ0L9JrXA8m4YEw==, - } - engines: { node: ">= 0.10" } + resolution: {integrity: sha512-C2AUdAJg6rlM2W5QMp2Q4KGQMVBwR1lIimTsUnutJ8bMpW5B52pGpR2gEnNBNwijumDo5FojQ0L9JrXA8m4YEw==} + engines: {node: '>= 0.10'} browserify-zlib@0.2.0: - resolution: - { - integrity: sha512-Z942RysHXmJrhqk88FmKBVq/v5tqmSkDz7p54G/MGyjMnCFFnC79XWNbg+Vta8W6Wb2qtSZTSxIGkJrRpCFEiA==, - } + resolution: {integrity: sha512-Z942RysHXmJrhqk88FmKBVq/v5tqmSkDz7p54G/MGyjMnCFFnC79XWNbg+Vta8W6Wb2qtSZTSxIGkJrRpCFEiA==} browserslist@4.28.2: - resolution: - { - integrity: sha512-48xSriZYYg+8qXna9kwqjIVzuQxi+KYWp2+5nCYnYKPTr0LvD89Jqk2Or5ogxz0NUMfIjhh2lIUX/LyX9B4oIg==, - } - engines: { node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7 } + resolution: {integrity: sha512-48xSriZYYg+8qXna9kwqjIVzuQxi+KYWp2+5nCYnYKPTr0LvD89Jqk2Or5ogxz0NUMfIjhh2lIUX/LyX9B4oIg==} + engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} hasBin: true bs58@6.0.0: - resolution: - { - integrity: sha512-PD0wEnEYg6ijszw/u8s+iI3H17cTymlrwkKhDhPZq+Sokl3AU4htyBFTjAeNAlCCmg0f53g6ih3jATyCKftTfw==, - } + resolution: {integrity: sha512-PD0wEnEYg6ijszw/u8s+iI3H17cTymlrwkKhDhPZq+Sokl3AU4htyBFTjAeNAlCCmg0f53g6ih3jATyCKftTfw==} buffer-from@1.1.2: - resolution: - { - integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==, - } + resolution: {integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==} buffer-xor@1.0.3: - resolution: - { - integrity: sha512-571s0T7nZWK6vB67HI5dyUF7wXiNcfaPPPTl6zYCNApANjIvYJTg7hlud/+cJpdAhS7dVzqMLmfhfHR3rAcOjQ==, - } + resolution: {integrity: sha512-571s0T7nZWK6vB67HI5dyUF7wXiNcfaPPPTl6zYCNApANjIvYJTg7hlud/+cJpdAhS7dVzqMLmfhfHR3rAcOjQ==} buffer@5.7.1: - resolution: - { - integrity: sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==, - } + resolution: {integrity: sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==} buffer@6.0.3: - resolution: - { - integrity: sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==, - } + resolution: {integrity: sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==} builtin-modules@3.3.0: - resolution: - { - integrity: sha512-zhaCDicdLuWN5UbN5IMnFqNMhNfo919sH85y2/ea+5Yg9TsTkeZxpL+JLbp6cgYFS4sRLp3YV4S6yDuqVWHYOw==, - } - engines: { node: ">=6" } + resolution: {integrity: sha512-zhaCDicdLuWN5UbN5IMnFqNMhNfo919sH85y2/ea+5Yg9TsTkeZxpL+JLbp6cgYFS4sRLp3YV4S6yDuqVWHYOw==} + engines: {node: '>=6'} builtin-status-codes@3.0.0: - resolution: - { - integrity: sha512-HpGFw18DgFWlncDfjTa2rcQ4W88O1mC8e8yZ2AvQY5KDaktSTwo+KRf6nHK6FRI5FyRyb/5T6+TSxfP7QyGsmQ==, - } + resolution: {integrity: sha512-HpGFw18DgFWlncDfjTa2rcQ4W88O1mC8e8yZ2AvQY5KDaktSTwo+KRf6nHK6FRI5FyRyb/5T6+TSxfP7QyGsmQ==} bundle-name@4.1.0: - resolution: - { - integrity: sha512-tjwM5exMg6BGRI+kNmTntNsvdZS1X8BFYS6tnJ2hdH0kVxM6/eVZ2xy+FqStSWvYmtfFMDLIxurorHwDKfDz5Q==, - } - engines: { node: ">=18" } + resolution: {integrity: sha512-tjwM5exMg6BGRI+kNmTntNsvdZS1X8BFYS6tnJ2hdH0kVxM6/eVZ2xy+FqStSWvYmtfFMDLIxurorHwDKfDz5Q==} + engines: {node: '>=18'} bytesish@0.4.4: - resolution: - { - integrity: sha512-i4uu6M4zuMUiyfZN4RU2+i9+peJh//pXhd9x1oSe1LBkZ3LEbCoygu8W0bXTukU1Jme2txKuotpCZRaC3FLxcQ==, - } + resolution: {integrity: sha512-i4uu6M4zuMUiyfZN4RU2+i9+peJh//pXhd9x1oSe1LBkZ3LEbCoygu8W0bXTukU1Jme2txKuotpCZRaC3FLxcQ==} call-bind-apply-helpers@1.0.2: - resolution: - { - integrity: sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==, - } - engines: { node: ">= 0.4" } + resolution: {integrity: sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==} + engines: {node: '>= 0.4'} call-bind@1.0.9: - resolution: - { - integrity: sha512-a/hy+pNsFUTR+Iz8TCJvXudKVLAnz/DyeSUo10I5yvFDQJBFU2s9uqQpoSrJlroHUKoKqzg+epxyP9lqFdzfBQ==, - } - engines: { node: ">= 0.4" } + resolution: {integrity: sha512-a/hy+pNsFUTR+Iz8TCJvXudKVLAnz/DyeSUo10I5yvFDQJBFU2s9uqQpoSrJlroHUKoKqzg+epxyP9lqFdzfBQ==} + engines: {node: '>= 0.4'} call-bound@1.0.4: - resolution: - { - integrity: sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==, - } - engines: { node: ">= 0.4" } + resolution: {integrity: sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==} + engines: {node: '>= 0.4'} callsites@3.1.0: - resolution: - { - integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==, - } - engines: { node: ">=6" } + resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==} + engines: {node: '>=6'} camel-case@4.1.2: - resolution: - { - integrity: sha512-gxGWBrTT1JuMx6R+o5PTXMmUnhnVzLQ9SNutD4YqKtI6ap897t3tKECYla6gCWEkplXnlNybEkZg9GEGxKFCgw==, - } + resolution: {integrity: sha512-gxGWBrTT1JuMx6R+o5PTXMmUnhnVzLQ9SNutD4YqKtI6ap897t3tKECYla6gCWEkplXnlNybEkZg9GEGxKFCgw==} camelcase@5.3.1: - resolution: - { - integrity: sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==, - } - engines: { node: ">=6" } + resolution: {integrity: sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==} + engines: {node: '>=6'} camelcase@6.3.0: - resolution: - { - integrity: sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==, - } - engines: { node: ">=10" } + resolution: {integrity: sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==} + engines: {node: '>=10'} caniuse-lite@1.0.30001788: - resolution: - { - integrity: sha512-6q8HFp+lOQtcf7wBK+uEenxymVWkGKkjFpCvw5W25cmMwEDU45p1xQFBQv8JDlMMry7eNxyBaR+qxgmTUZkIRQ==, - } + resolution: {integrity: sha512-6q8HFp+lOQtcf7wBK+uEenxymVWkGKkjFpCvw5W25cmMwEDU45p1xQFBQv8JDlMMry7eNxyBaR+qxgmTUZkIRQ==} caseless@0.12.0: - resolution: - { - integrity: sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw==, - } + resolution: {integrity: sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw==} chai@5.3.3: - resolution: - { - integrity: sha512-4zNhdJD/iOjSH0A05ea+Ke6MU5mmpQcbQsSOkgdaUMJ9zTlDTD/GYlwohmIE2u0gaxHYiVHEn1Fw9mZ/ktJWgw==, - } - engines: { node: ">=18" } + resolution: {integrity: sha512-4zNhdJD/iOjSH0A05ea+Ke6MU5mmpQcbQsSOkgdaUMJ9zTlDTD/GYlwohmIE2u0gaxHYiVHEn1Fw9mZ/ktJWgw==} + engines: {node: '>=18'} chai@6.2.2: - resolution: - { - integrity: sha512-NUPRluOfOiTKBKvWPtSD4PhFvWCqOi0BGStNWs57X9js7XGTprSmFoz5F0tWhR4WPjNeR9jXqdC7/UpSJTnlRg==, - } - engines: { node: ">=18" } + resolution: {integrity: sha512-NUPRluOfOiTKBKvWPtSD4PhFvWCqOi0BGStNWs57X9js7XGTprSmFoz5F0tWhR4WPjNeR9jXqdC7/UpSJTnlRg==} + engines: {node: '>=18'} chalk@4.1.2: - resolution: - { - integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==, - } - engines: { node: ">=10" } + resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} + engines: {node: '>=10'} chalk@5.6.2: - resolution: - { - integrity: sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA==, - } - engines: { node: ^12.17.0 || ^14.13 || >=16.0.0 } + resolution: {integrity: sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA==} + engines: {node: ^12.17.0 || ^14.13 || >=16.0.0} check-error@2.1.3: - resolution: - { - integrity: sha512-PAJdDJusoxnwm1VwW07VWwUN1sl7smmC3OKggvndJFadxxDRyFJBX/ggnu/KE4kQAB7a3Dp8f/YXC1FlUprWmA==, - } - engines: { node: ">= 16" } + resolution: {integrity: sha512-PAJdDJusoxnwm1VwW07VWwUN1sl7smmC3OKggvndJFadxxDRyFJBX/ggnu/KE4kQAB7a3Dp8f/YXC1FlUprWmA==} + engines: {node: '>= 16'} cheerio-select@2.1.0: - resolution: - { - integrity: sha512-9v9kG0LvzrlcungtnJtpGNxY+fzECQKhK4EGJX2vByejiMX84MFNQw4UxPJl3bFbTMw+Dfs37XaIkCwTZfLh4g==, - } + resolution: {integrity: sha512-9v9kG0LvzrlcungtnJtpGNxY+fzECQKhK4EGJX2vByejiMX84MFNQw4UxPJl3bFbTMw+Dfs37XaIkCwTZfLh4g==} cheerio@1.2.0: - resolution: - { - integrity: sha512-WDrybc/gKFpTYQutKIK6UvfcuxijIZfMfXaYm8NMsPQxSYvf+13fXUJ4rztGGbJcBQ/GF55gvrZ0Bc0bj/mqvg==, - } - engines: { node: ">=20.18.1" } + resolution: {integrity: sha512-WDrybc/gKFpTYQutKIK6UvfcuxijIZfMfXaYm8NMsPQxSYvf+13fXUJ4rztGGbJcBQ/GF55gvrZ0Bc0bj/mqvg==} + engines: {node: '>=20.18.1'} chokidar@3.6.0: - resolution: - { - integrity: sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==, - } - engines: { node: ">= 8.10.0" } + resolution: {integrity: sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==} + engines: {node: '>= 8.10.0'} chokidar@4.0.3: - resolution: - { - integrity: sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==, - } - engines: { node: ">= 14.16.0" } + resolution: {integrity: sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==} + engines: {node: '>= 14.16.0'} ci-info@4.4.0: - resolution: - { - integrity: sha512-77PSwercCZU2Fc4sX94eF8k8Pxte6JAwL4/ICZLFjJLqegs7kCuAsqqj/70NQF6TvDpgFjkubQB2FW2ZZddvQg==, - } - engines: { node: ">=8" } + resolution: {integrity: sha512-77PSwercCZU2Fc4sX94eF8k8Pxte6JAwL4/ICZLFjJLqegs7kCuAsqqj/70NQF6TvDpgFjkubQB2FW2ZZddvQg==} + engines: {node: '>=8'} cipher-base@1.0.7: - resolution: - { - integrity: sha512-Mz9QMT5fJe7bKI7MH31UilT5cEK5EHHRCccw/YRFsRY47AuNgaV6HY3rscp0/I4Q+tTW/5zoqpSeRRI54TkDWA==, - } - engines: { node: ">= 0.10" } + resolution: {integrity: sha512-Mz9QMT5fJe7bKI7MH31UilT5cEK5EHHRCccw/YRFsRY47AuNgaV6HY3rscp0/I4Q+tTW/5zoqpSeRRI54TkDWA==} + engines: {node: '>= 0.10'} classnames@2.5.1: - resolution: - { - integrity: sha512-saHYOzhIQs6wy2sVxTM6bUDsQO4F50V9RQ22qBpEdCW+I+/Wmke2HOl6lS6dTpdxVhb88/I6+Hs+438c3lfUow==, - } + resolution: {integrity: sha512-saHYOzhIQs6wy2sVxTM6bUDsQO4F50V9RQ22qBpEdCW+I+/Wmke2HOl6lS6dTpdxVhb88/I6+Hs+438c3lfUow==} clean-css@5.3.3: - resolution: - { - integrity: sha512-D5J+kHaVb/wKSFcyyV75uCn8fiY4sV38XJoe4CUyGQ+mOU/fMVYUdH1hJC+CJQ5uY3EnW27SbJYS4X8BiLrAFg==, - } - engines: { node: ">= 10.0" } + resolution: {integrity: sha512-D5J+kHaVb/wKSFcyyV75uCn8fiY4sV38XJoe4CUyGQ+mOU/fMVYUdH1hJC+CJQ5uY3EnW27SbJYS4X8BiLrAFg==} + engines: {node: '>= 10.0'} clean-regexp@1.0.0: - resolution: - { - integrity: sha512-GfisEZEJvzKrmGWkvfhgzcz/BllN1USeqD2V6tg14OAOgaCD2Z/PUEuxnAZ/nPvmaHRG7a8y77p1T/IRQ4D1Hw==, - } - engines: { node: ">=4" } + resolution: {integrity: sha512-GfisEZEJvzKrmGWkvfhgzcz/BllN1USeqD2V6tg14OAOgaCD2Z/PUEuxnAZ/nPvmaHRG7a8y77p1T/IRQ4D1Hw==} + engines: {node: '>=4'} cliui@6.0.0: - resolution: - { - integrity: sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==, - } + resolution: {integrity: sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==} cliui@8.0.1: - resolution: - { - integrity: sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==, - } - engines: { node: ">=12" } + resolution: {integrity: sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==} + engines: {node: '>=12'} clone@2.1.2: - resolution: - { - integrity: sha512-3Pe/CF1Nn94hyhIYpjtiLhdCoEoz0DqQ+988E9gmeEdQZlojxnOb74wctFyuwWQHzqyf9X7C7MG8juUpqBJT8w==, - } - engines: { node: ">=0.8" } + resolution: {integrity: sha512-3Pe/CF1Nn94hyhIYpjtiLhdCoEoz0DqQ+988E9gmeEdQZlojxnOb74wctFyuwWQHzqyf9X7C7MG8juUpqBJT8w==} + engines: {node: '>=0.8'} clsx@2.1.1: - resolution: - { - integrity: sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==, - } - engines: { node: ">=6" } + resolution: {integrity: sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==} + engines: {node: '>=6'} color-convert@2.0.1: - resolution: - { - integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==, - } - engines: { node: ">=7.0.0" } + resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} + engines: {node: '>=7.0.0'} color-name@1.1.4: - resolution: - { - integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==, - } + resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} colorette@2.0.20: - resolution: - { - integrity: sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==, - } + resolution: {integrity: sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==} colors@1.4.0: - resolution: - { - integrity: sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA==, - } - engines: { node: ">=0.1.90" } + resolution: {integrity: sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA==} + engines: {node: '>=0.1.90'} commander@12.1.0: - resolution: - { - integrity: sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA==, - } - engines: { node: ">=18" } + resolution: {integrity: sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA==} + engines: {node: '>=18'} commander@2.20.3: - resolution: - { - integrity: sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==, - } + resolution: {integrity: sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==} commander@8.3.0: - resolution: - { - integrity: sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==, - } - engines: { node: ">= 12" } + resolution: {integrity: sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==} + engines: {node: '>= 12'} comment-parser@1.4.1: - resolution: - { - integrity: sha512-buhp5kePrmda3vhc5B9t7pUQXAb2Tnd0qgpkIhPhkHXxJpiPJ11H0ZEU0oBpJ2QztSbzG/ZxMj/CHsYJqRHmyg==, - } - engines: { node: ">= 12.0.0" } + resolution: {integrity: sha512-buhp5kePrmda3vhc5B9t7pUQXAb2Tnd0qgpkIhPhkHXxJpiPJ11H0ZEU0oBpJ2QztSbzG/ZxMj/CHsYJqRHmyg==} + engines: {node: '>= 12.0.0'} common-tags@1.8.2: - resolution: - { - integrity: sha512-gk/Z852D2Wtb//0I+kRFNKKE9dIIVirjoqPoA1wJU+XePVXZfGeBpk45+A1rKO4Q43prqWBNY/MiIeRLbPWUaA==, - } - engines: { node: ">=4.0.0" } + resolution: {integrity: sha512-gk/Z852D2Wtb//0I+kRFNKKE9dIIVirjoqPoA1wJU+XePVXZfGeBpk45+A1rKO4Q43prqWBNY/MiIeRLbPWUaA==} + engines: {node: '>=4.0.0'} connect-history-api-fallback@1.6.0: - resolution: - { - integrity: sha512-e54B99q/OUoH64zYYRf3HBP5z24G38h5D3qXu23JGRoigpX5Ss4r9ZnDk3g0Z8uQC2x2lPaJ+UlWBc1ZWBWdLg==, - } - engines: { node: ">=0.8" } + resolution: {integrity: sha512-e54B99q/OUoH64zYYRf3HBP5z24G38h5D3qXu23JGRoigpX5Ss4r9ZnDk3g0Z8uQC2x2lPaJ+UlWBc1ZWBWdLg==} + engines: {node: '>=0.8'} consola@2.15.3: - resolution: - { - integrity: sha512-9vAdYbHj6x2fLKC4+oPH0kFzY/orMZyG2Aj+kNylHxKGJ/Ed4dpNyAQYwJOdqO4zdM7XpVHmyejQDcQHrnuXbw==, - } + resolution: {integrity: sha512-9vAdYbHj6x2fLKC4+oPH0kFzY/orMZyG2Aj+kNylHxKGJ/Ed4dpNyAQYwJOdqO4zdM7XpVHmyejQDcQHrnuXbw==} console-browserify@1.2.0: - resolution: - { - integrity: sha512-ZMkYO/LkF17QvCPqM0gxw8yUzigAOZOSWSHg91FH6orS7vcEj5dVZTidN2fQ14yBSdg97RqhSNwLUXInd52OTA==, - } + resolution: {integrity: sha512-ZMkYO/LkF17QvCPqM0gxw8yUzigAOZOSWSHg91FH6orS7vcEj5dVZTidN2fQ14yBSdg97RqhSNwLUXInd52OTA==} constants-browserify@1.0.0: - resolution: - { - integrity: sha512-xFxOwqIzR/e1k1gLiWEophSCMqXcwVHIH7akf7b/vxcUeGunlj3hvZaaqxwHsTgn+IndtkQJgSztIDWeumWJDQ==, - } + resolution: {integrity: sha512-xFxOwqIzR/e1k1gLiWEophSCMqXcwVHIH7akf7b/vxcUeGunlj3hvZaaqxwHsTgn+IndtkQJgSztIDWeumWJDQ==} content-type@1.0.5: - resolution: - { - integrity: sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==, - } - engines: { node: ">= 0.6" } + resolution: {integrity: sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==} + engines: {node: '>= 0.6'} convert-source-map@2.0.0: - resolution: - { - integrity: sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==, - } + resolution: {integrity: sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==} cookie@1.1.1: - resolution: - { - integrity: sha512-ei8Aos7ja0weRpFzJnEA9UHJ/7XQmqglbRwnf2ATjcB9Wq874VKH9kfjjirM6UhU2/E5fFYadylyhFldcqSidQ==, - } - engines: { node: ">=18" } + resolution: {integrity: sha512-ei8Aos7ja0weRpFzJnEA9UHJ/7XQmqglbRwnf2ATjcB9Wq874VKH9kfjjirM6UhU2/E5fFYadylyhFldcqSidQ==} + engines: {node: '>=18'} copy-to-clipboard@3.3.3: - resolution: - { - integrity: sha512-2KV8NhB5JqC3ky0r9PMCAZKbUHSwtEo4CwCs0KXgruG43gX5PMqDEBbVU4OUzw2MuAWUfsuFmWvEKG5QRfSnJA==, - } + resolution: {integrity: sha512-2KV8NhB5JqC3ky0r9PMCAZKbUHSwtEo4CwCs0KXgruG43gX5PMqDEBbVU4OUzw2MuAWUfsuFmWvEKG5QRfSnJA==} core-js-compat@3.49.0: - resolution: - { - integrity: sha512-VQXt1jr9cBz03b331DFDCCP90b3fanciLkgiOoy8SBHy06gNf+vQ1A3WFLqG7I8TipYIKeYK9wxd0tUrvHcOZA==, - } + resolution: {integrity: sha512-VQXt1jr9cBz03b331DFDCCP90b3fanciLkgiOoy8SBHy06gNf+vQ1A3WFLqG7I8TipYIKeYK9wxd0tUrvHcOZA==} core-util-is@1.0.3: - resolution: - { - integrity: sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==, - } + resolution: {integrity: sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==} cosmiconfig@8.3.6: - resolution: - { - integrity: sha512-kcZ6+W5QzcJ3P1Mt+83OUv/oHFqZHIx8DuxG6eZ5RGMERoLqp4BuGjhHLYGK+Kf5XVkQvqBSmAy/nGWN3qDgEA==, - } - engines: { node: ">=14" } + resolution: {integrity: sha512-kcZ6+W5QzcJ3P1Mt+83OUv/oHFqZHIx8DuxG6eZ5RGMERoLqp4BuGjhHLYGK+Kf5XVkQvqBSmAy/nGWN3qDgEA==} + engines: {node: '>=14'} peerDependencies: - typescript: ">=4.9.5" + typescript: '>=4.9.5' peerDependenciesMeta: typescript: optional: true create-ecdh@4.0.4: - resolution: - { - integrity: sha512-mf+TCx8wWc9VpuxfP2ht0iSISLZnt0JgWlrOKZiNqyUZWnjIaCIVNQArMHnCZKfEYRg6IM7A+NeJoN8gf/Ws0A==, - } + resolution: {integrity: sha512-mf+TCx8wWc9VpuxfP2ht0iSISLZnt0JgWlrOKZiNqyUZWnjIaCIVNQArMHnCZKfEYRg6IM7A+NeJoN8gf/Ws0A==} create-hash@1.2.0: - resolution: - { - integrity: sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==, - } + resolution: {integrity: sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==} create-hmac@1.1.7: - resolution: - { - integrity: sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg==, - } + resolution: {integrity: sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg==} create-require@1.1.1: - resolution: - { - integrity: sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==, - } + resolution: {integrity: sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==} cross-spawn@7.0.6: - resolution: - { - integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==, - } - engines: { node: ">= 8" } + resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==} + engines: {node: '>= 8'} crypto-browserify@3.12.1: - resolution: - { - integrity: sha512-r4ESw/IlusD17lgQi1O20Fa3qNnsckR126TdUuBgAu7GBYSIPvdNyONd3Zrxh0xCwA4+6w/TDArBPsMvhur+KQ==, - } - engines: { node: ">= 0.10" } + resolution: {integrity: sha512-r4ESw/IlusD17lgQi1O20Fa3qNnsckR126TdUuBgAu7GBYSIPvdNyONd3Zrxh0xCwA4+6w/TDArBPsMvhur+KQ==} + engines: {node: '>= 0.10'} css-blank-pseudo@7.0.1: - resolution: - { - integrity: sha512-jf+twWGDf6LDoXDUode+nc7ZlrqfaNphrBIBrcmeP3D8yw1uPaix1gCC8LUQUGQ6CycuK2opkbFFWFuq/a94ag==, - } - engines: { node: ">=18" } + resolution: {integrity: sha512-jf+twWGDf6LDoXDUode+nc7ZlrqfaNphrBIBrcmeP3D8yw1uPaix1gCC8LUQUGQ6CycuK2opkbFFWFuq/a94ag==} + engines: {node: '>=18'} peerDependencies: postcss: ^8.4 css-has-pseudo@7.0.3: - resolution: - { - integrity: sha512-oG+vKuGyqe/xvEMoxAQrhi7uY16deJR3i7wwhBerVrGQKSqUC5GiOVxTpM9F9B9hw0J+eKeOWLH7E9gZ1Dr5rA==, - } - engines: { node: ">=18" } + resolution: {integrity: sha512-oG+vKuGyqe/xvEMoxAQrhi7uY16deJR3i7wwhBerVrGQKSqUC5GiOVxTpM9F9B9hw0J+eKeOWLH7E9gZ1Dr5rA==} + engines: {node: '>=18'} peerDependencies: postcss: ^8.4 css-prefers-color-scheme@10.0.0: - resolution: - { - integrity: sha512-VCtXZAWivRglTZditUfB4StnsWr6YVZ2PRtuxQLKTNRdtAf8tpzaVPE9zXIF3VaSc7O70iK/j1+NXxyQCqdPjQ==, - } - engines: { node: ">=18" } + resolution: {integrity: sha512-VCtXZAWivRglTZditUfB4StnsWr6YVZ2PRtuxQLKTNRdtAf8tpzaVPE9zXIF3VaSc7O70iK/j1+NXxyQCqdPjQ==} + engines: {node: '>=18'} peerDependencies: postcss: ^8.4 css-select@4.3.0: - resolution: - { - integrity: sha512-wPpOYtnsVontu2mODhA19JrqWxNsfdatRKd64kmpRbQgh1KtItko5sTnEpPdpSaJszTOhEMlF/RPz28qj4HqhQ==, - } + resolution: {integrity: sha512-wPpOYtnsVontu2mODhA19JrqWxNsfdatRKd64kmpRbQgh1KtItko5sTnEpPdpSaJszTOhEMlF/RPz28qj4HqhQ==} css-select@5.2.2: - resolution: - { - integrity: sha512-TizTzUddG/xYLA3NXodFM0fSbNizXjOKhqiQQwvhlspadZokn1KDy0NZFS0wuEubIYAV5/c1/lAr0TaaFXEXzw==, - } + resolution: {integrity: sha512-TizTzUddG/xYLA3NXodFM0fSbNizXjOKhqiQQwvhlspadZokn1KDy0NZFS0wuEubIYAV5/c1/lAr0TaaFXEXzw==} css-what@6.2.2: - resolution: - { - integrity: sha512-u/O3vwbptzhMs3L1fQE82ZSLHQQfto5gyZzwteVIEyeaY5Fc7R4dapF/BvRoSYFeqfBk4m0V1Vafq5Pjv25wvA==, - } - engines: { node: ">= 6" } + resolution: {integrity: sha512-u/O3vwbptzhMs3L1fQE82ZSLHQQfto5gyZzwteVIEyeaY5Fc7R4dapF/BvRoSYFeqfBk4m0V1Vafq5Pjv25wvA==} + engines: {node: '>= 6'} css.escape@1.5.1: - resolution: - { - integrity: sha512-YUifsXXuknHlUsmlgyY0PKzgPOr7/FjCePfHNt0jxm83wHZi44VDMQ7/fGNkjY3/jV1MC+1CmZbaHzugyeRtpg==, - } + resolution: {integrity: sha512-YUifsXXuknHlUsmlgyY0PKzgPOr7/FjCePfHNt0jxm83wHZi44VDMQ7/fGNkjY3/jV1MC+1CmZbaHzugyeRtpg==} cssdb@8.8.0: - resolution: - { - integrity: sha512-QbLeyz2Bgso1iRlh7IpWk6OKa3lLNGXsujVjDMPl9rOZpxKeiG69icLpbLCFxeURwmcdIfZqQyhlooKJYM4f8Q==, - } + resolution: {integrity: sha512-QbLeyz2Bgso1iRlh7IpWk6OKa3lLNGXsujVjDMPl9rOZpxKeiG69icLpbLCFxeURwmcdIfZqQyhlooKJYM4f8Q==} cssesc@3.0.0: - resolution: - { - integrity: sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==, - } - engines: { node: ">=4" } + resolution: {integrity: sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==} + engines: {node: '>=4'} hasBin: true cssstyle@4.6.0: - resolution: - { - integrity: sha512-2z+rWdzbbSZv6/rhtvzvqeZQHrBaqgogqt85sqFNbabZOuFbCVFb8kPeEtZjiKkbrm395irpNKiYeFeLiQnFPg==, - } - engines: { node: ">=18" } + resolution: {integrity: sha512-2z+rWdzbbSZv6/rhtvzvqeZQHrBaqgogqt85sqFNbabZOuFbCVFb8kPeEtZjiKkbrm395irpNKiYeFeLiQnFPg==} + engines: {node: '>=18'} csstype@3.2.3: - resolution: - { - integrity: sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==, - } + resolution: {integrity: sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==} damerau-levenshtein@1.0.8: - resolution: - { - integrity: sha512-sdQSFB7+llfUcQHUQO3+B8ERRj0Oa4w9POWMI/puGtuf7gFywGmkaLCElnudfTiKZV+NvHqL0ifzdrI8Ro7ESA==, - } + resolution: {integrity: sha512-sdQSFB7+llfUcQHUQO3+B8ERRj0Oa4w9POWMI/puGtuf7gFywGmkaLCElnudfTiKZV+NvHqL0ifzdrI8Ro7ESA==} data-urls@5.0.0: - resolution: - { - integrity: sha512-ZYP5VBHshaDAiVZxjbRVcFJpc+4xGgT0bK3vzy1HLN8jTO975HEbuYzZJcHoQEY5K1a0z8YayJkyVETa08eNTg==, - } - engines: { node: ">=18" } + resolution: {integrity: sha512-ZYP5VBHshaDAiVZxjbRVcFJpc+4xGgT0bK3vzy1HLN8jTO975HEbuYzZJcHoQEY5K1a0z8YayJkyVETa08eNTg==} + engines: {node: '>=18'} data-view-buffer@1.0.2: - resolution: - { - integrity: sha512-EmKO5V3OLXh1rtK2wgXRansaK1/mtVdTUEiEI0W8RkvgT05kfxaH29PliLnpLP73yYO6142Q72QNa8Wx/A5CqQ==, - } - engines: { node: ">= 0.4" } + resolution: {integrity: sha512-EmKO5V3OLXh1rtK2wgXRansaK1/mtVdTUEiEI0W8RkvgT05kfxaH29PliLnpLP73yYO6142Q72QNa8Wx/A5CqQ==} + engines: {node: '>= 0.4'} data-view-byte-length@1.0.2: - resolution: - { - integrity: sha512-tuhGbE6CfTM9+5ANGf+oQb72Ky/0+s3xKUpHvShfiz2RxMFgFPjsXuRLBVMtvMs15awe45SRb83D6wH4ew6wlQ==, - } - engines: { node: ">= 0.4" } + resolution: {integrity: sha512-tuhGbE6CfTM9+5ANGf+oQb72Ky/0+s3xKUpHvShfiz2RxMFgFPjsXuRLBVMtvMs15awe45SRb83D6wH4ew6wlQ==} + engines: {node: '>= 0.4'} data-view-byte-offset@1.0.1: - resolution: - { - integrity: sha512-BS8PfmtDGnrgYdOonGZQdLZslWIeCGFP9tpan0hi1Co2Zr2NKADsvGYA8XxuG/4UWgJ6Cjtv+YJnB6MM69QGlQ==, - } - engines: { node: ">= 0.4" } + resolution: {integrity: sha512-BS8PfmtDGnrgYdOonGZQdLZslWIeCGFP9tpan0hi1Co2Zr2NKADsvGYA8XxuG/4UWgJ6Cjtv+YJnB6MM69QGlQ==} + engines: {node: '>= 0.4'} debug@2.6.9: - resolution: - { - integrity: sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==, - } + resolution: {integrity: sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==} peerDependencies: - supports-color: "*" + supports-color: '*' peerDependenciesMeta: supports-color: optional: true debug@3.2.7: - resolution: - { - integrity: sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==, - } + resolution: {integrity: sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==} peerDependencies: - supports-color: "*" + supports-color: '*' peerDependenciesMeta: supports-color: optional: true debug@4.4.3: - resolution: - { - integrity: sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==, - } - engines: { node: ">=6.0" } + resolution: {integrity: sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==} + engines: {node: '>=6.0'} peerDependencies: - supports-color: "*" + supports-color: '*' peerDependenciesMeta: supports-color: optional: true decamelize@1.2.0: - resolution: - { - integrity: sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==, - } - engines: { node: ">=0.10.0" } + resolution: {integrity: sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==} + engines: {node: '>=0.10.0'} decamelize@5.0.1: - resolution: - { - integrity: sha512-VfxadyCECXgQlkoEAjeghAr5gY3Hf+IKjKb+X8tGVDtveCjN+USwprd2q3QXBR9T1+x2DG0XZF5/w+7HAtSaXA==, - } - engines: { node: ">=10" } + resolution: {integrity: sha512-VfxadyCECXgQlkoEAjeghAr5gY3Hf+IKjKb+X8tGVDtveCjN+USwprd2q3QXBR9T1+x2DG0XZF5/w+7HAtSaXA==} + engines: {node: '>=10'} decimal.js@10.6.0: - resolution: - { - integrity: sha512-YpgQiITW3JXGntzdUmyUR1V812Hn8T1YVXhCu+wO3OpS4eU9l4YdD3qjyiKdV6mvV29zapkMeD390UVEf2lkUg==, - } + resolution: {integrity: sha512-YpgQiITW3JXGntzdUmyUR1V812Hn8T1YVXhCu+wO3OpS4eU9l4YdD3qjyiKdV6mvV29zapkMeD390UVEf2lkUg==} deep-eql@5.0.2: - resolution: - { - integrity: sha512-h5k/5U50IJJFpzfL6nO9jaaumfjO/f2NjK/oYB2Djzm4p9L+3T9qWpZqZ2hAbLPuuYq9wrU08WQyBTL5GbPk5Q==, - } - engines: { node: ">=6" } + resolution: {integrity: sha512-h5k/5U50IJJFpzfL6nO9jaaumfjO/f2NjK/oYB2Djzm4p9L+3T9qWpZqZ2hAbLPuuYq9wrU08WQyBTL5GbPk5Q==} + engines: {node: '>=6'} deep-is@0.1.4: - resolution: - { - integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==, - } + resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==} default-browser-id@5.0.1: - resolution: - { - integrity: sha512-x1VCxdX4t+8wVfd1so/9w+vQ4vx7lKd2Qp5tDRutErwmR85OgmfX7RlLRMWafRMY7hbEiXIbudNrjOAPa/hL8Q==, - } - engines: { node: ">=18" } + resolution: {integrity: sha512-x1VCxdX4t+8wVfd1so/9w+vQ4vx7lKd2Qp5tDRutErwmR85OgmfX7RlLRMWafRMY7hbEiXIbudNrjOAPa/hL8Q==} + engines: {node: '>=18'} default-browser@5.5.0: - resolution: - { - integrity: sha512-H9LMLr5zwIbSxrmvikGuI/5KGhZ8E2zH3stkMgM5LpOWDutGM2JZaj460Udnf1a+946zc7YBgrqEWwbk7zHvGw==, - } - engines: { node: ">=18" } + resolution: {integrity: sha512-H9LMLr5zwIbSxrmvikGuI/5KGhZ8E2zH3stkMgM5LpOWDutGM2JZaj460Udnf1a+946zc7YBgrqEWwbk7zHvGw==} + engines: {node: '>=18'} define-data-property@1.1.4: - resolution: - { - integrity: sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==, - } - engines: { node: ">= 0.4" } + resolution: {integrity: sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==} + engines: {node: '>= 0.4'} define-lazy-prop@3.0.0: - resolution: - { - integrity: sha512-N+MeXYoqr3pOgn8xfyRPREN7gHakLYjhsHhWGT3fWAiL4IkAt0iDw14QiiEm2bE30c5XX5q0FtAA3CK5f9/BUg==, - } - engines: { node: ">=12" } + resolution: {integrity: sha512-N+MeXYoqr3pOgn8xfyRPREN7gHakLYjhsHhWGT3fWAiL4IkAt0iDw14QiiEm2bE30c5XX5q0FtAA3CK5f9/BUg==} + engines: {node: '>=12'} define-properties@1.2.1: - resolution: - { - integrity: sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==, - } - engines: { node: ">= 0.4" } + resolution: {integrity: sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==} + engines: {node: '>= 0.4'} deprecation@2.3.1: - resolution: - { - integrity: sha512-xmHIy4F3scKVwMsQ4WnVaS8bHOx0DmVwRywosKhaILI0ywMDWPtBSku2HNxRvF7jtwDRsoEwYQSfbxj8b7RlJQ==, - } + resolution: {integrity: sha512-xmHIy4F3scKVwMsQ4WnVaS8bHOx0DmVwRywosKhaILI0ywMDWPtBSku2HNxRvF7jtwDRsoEwYQSfbxj8b7RlJQ==} dequal@2.0.3: - resolution: - { - integrity: sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==, - } - engines: { node: ">=6" } + resolution: {integrity: sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==} + engines: {node: '>=6'} des.js@1.1.0: - resolution: - { - integrity: sha512-r17GxjhUCjSRy8aiJpr8/UadFIzMzJGexI3Nmz4ADi9LYSFx4gTBp80+NaX/YsXWWLhpZ7v/v/ubEc/bCNfKwg==, - } + resolution: {integrity: sha512-r17GxjhUCjSRy8aiJpr8/UadFIzMzJGexI3Nmz4ADi9LYSFx4gTBp80+NaX/YsXWWLhpZ7v/v/ubEc/bCNfKwg==} detect-libc@2.1.2: - resolution: - { - integrity: sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==, - } - engines: { node: ">=8" } + resolution: {integrity: sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==} + engines: {node: '>=8'} detect-node-es@1.1.0: - resolution: - { - integrity: sha512-ypdmJU/TbBby2Dxibuv7ZLW3Bs1QEmM7nHjEANfohJLvE0XVujisn1qPJcZxg+qDucsr+bP6fLD1rPS3AhJ7EQ==, - } + resolution: {integrity: sha512-ypdmJU/TbBby2Dxibuv7ZLW3Bs1QEmM7nHjEANfohJLvE0XVujisn1qPJcZxg+qDucsr+bP6fLD1rPS3AhJ7EQ==} diffie-hellman@5.0.3: - resolution: - { - integrity: sha512-kqag/Nl+f3GwyK25fhUMYj81BUOrZ9IuJsjIcDE5icNM9FJHAVm3VcUDxdLPoQtTuUylWm6ZIknYJwwaPxsUzg==, - } + resolution: {integrity: sha512-kqag/Nl+f3GwyK25fhUMYj81BUOrZ9IuJsjIcDE5icNM9FJHAVm3VcUDxdLPoQtTuUylWm6ZIknYJwwaPxsUzg==} dijkstrajs@1.0.3: - resolution: - { - integrity: sha512-qiSlmBq9+BCdCA/L46dw8Uy93mloxsPSbwnm5yrKn2vMPiy8KyAskTF6zuV/j5BMsmOGZDPs7KjU+mjb670kfA==, - } + resolution: {integrity: sha512-qiSlmBq9+BCdCA/L46dw8Uy93mloxsPSbwnm5yrKn2vMPiy8KyAskTF6zuV/j5BMsmOGZDPs7KjU+mjb670kfA==} dir-glob@3.0.1: - resolution: - { - integrity: sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==, - } - engines: { node: ">=8" } + resolution: {integrity: sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==} + engines: {node: '>=8'} doctrine@2.1.0: - resolution: - { - integrity: sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==, - } - engines: { node: ">=0.10.0" } + resolution: {integrity: sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==} + engines: {node: '>=0.10.0'} doctrine@3.0.0: - resolution: - { - integrity: sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==, - } - engines: { node: ">=6.0.0" } + resolution: {integrity: sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==} + engines: {node: '>=6.0.0'} dom-accessibility-api@0.5.16: - resolution: - { - integrity: sha512-X7BJ2yElsnOJ30pZF4uIIDfBEVgF4XEBxL9Bxhy6dnrm5hkzqmsWHGTiHqRiITNhMyFLyAiWndIJP7Z1NTteDg==, - } + resolution: {integrity: sha512-X7BJ2yElsnOJ30pZF4uIIDfBEVgF4XEBxL9Bxhy6dnrm5hkzqmsWHGTiHqRiITNhMyFLyAiWndIJP7Z1NTteDg==} dom-accessibility-api@0.6.3: - resolution: - { - integrity: sha512-7ZgogeTnjuHbo+ct10G9Ffp0mif17idi0IyWNVA/wcwcm7NPOD/WEHVP3n7n3MhXqxoIYm8d6MuZohYWIZ4T3w==, - } + resolution: {integrity: sha512-7ZgogeTnjuHbo+ct10G9Ffp0mif17idi0IyWNVA/wcwcm7NPOD/WEHVP3n7n3MhXqxoIYm8d6MuZohYWIZ4T3w==} dom-serializer@1.4.1: - resolution: - { - integrity: sha512-VHwB3KfrcOOkelEG2ZOfxqLZdfkil8PtJi4P8N2MMXucZq2yLp75ClViUlOVwyoHEDjYU433Aq+5zWP61+RGag==, - } + resolution: {integrity: sha512-VHwB3KfrcOOkelEG2ZOfxqLZdfkil8PtJi4P8N2MMXucZq2yLp75ClViUlOVwyoHEDjYU433Aq+5zWP61+RGag==} dom-serializer@2.0.0: - resolution: - { - integrity: sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==, - } + resolution: {integrity: sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==} domain-browser@4.22.0: - resolution: - { - integrity: sha512-IGBwjF7tNk3cwypFNH/7bfzBcgSCbaMOD3GsaY1AU/JRrnHnYgEM0+9kQt52iZxjNsjBtJYtao146V+f8jFZNw==, - } - engines: { node: ">=10" } + resolution: {integrity: sha512-IGBwjF7tNk3cwypFNH/7bfzBcgSCbaMOD3GsaY1AU/JRrnHnYgEM0+9kQt52iZxjNsjBtJYtao146V+f8jFZNw==} + engines: {node: '>=10'} domelementtype@2.3.0: - resolution: - { - integrity: sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==, - } + resolution: {integrity: sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==} domhandler@4.3.1: - resolution: - { - integrity: sha512-GrwoxYN+uWlzO8uhUXRl0P+kHE4GtVPfYzVLcUxPL7KNdHKj66vvlhiweIHqYYXWlw+T8iLMp42Lm67ghw4WMQ==, - } - engines: { node: ">= 4" } + resolution: {integrity: sha512-GrwoxYN+uWlzO8uhUXRl0P+kHE4GtVPfYzVLcUxPL7KNdHKj66vvlhiweIHqYYXWlw+T8iLMp42Lm67ghw4WMQ==} + engines: {node: '>= 4'} domhandler@5.0.3: - resolution: - { - integrity: sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==, - } - engines: { node: ">= 4" } + resolution: {integrity: sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==} + engines: {node: '>= 4'} domutils@2.8.0: - resolution: - { - integrity: sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==, - } + resolution: {integrity: sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==} domutils@3.2.2: - resolution: - { - integrity: sha512-6kZKyUajlDuqlHKVX1w7gyslj9MPIXzIFiz/rGu35uC1wMi+kMhQwGhl4lt9unC9Vb9INnY9Z3/ZA3+FhASLaw==, - } + resolution: {integrity: sha512-6kZKyUajlDuqlHKVX1w7gyslj9MPIXzIFiz/rGu35uC1wMi+kMhQwGhl4lt9unC9Vb9INnY9Z3/ZA3+FhASLaw==} dot-case@3.0.4: - resolution: - { - integrity: sha512-Kv5nKlh6yRrdrGvxeJ2e5y2eRUpkUosIW4A2AS38zwSz27zu7ufDwQPi5Jhs3XAlGNetl3bmnGhQsMtkKJnj3w==, - } + resolution: {integrity: sha512-Kv5nKlh6yRrdrGvxeJ2e5y2eRUpkUosIW4A2AS38zwSz27zu7ufDwQPi5Jhs3XAlGNetl3bmnGhQsMtkKJnj3w==} dotenv-expand@8.0.3: - resolution: - { - integrity: sha512-SErOMvge0ZUyWd5B0NXMQlDkN+8r+HhVUsxgOO7IoPDOdDRD2JjExpN6y3KnFR66jsJMwSn1pqIivhU5rcJiNg==, - } - engines: { node: ">=12" } + resolution: {integrity: sha512-SErOMvge0ZUyWd5B0NXMQlDkN+8r+HhVUsxgOO7IoPDOdDRD2JjExpN6y3KnFR66jsJMwSn1pqIivhU5rcJiNg==} + engines: {node: '>=12'} dotenv@16.6.1: - resolution: - { - integrity: sha512-uBq4egWHTcTt33a72vpSG0z3HnPuIl6NqYcTrKEg2azoEyl2hpW0zqlxysq2pK9HlDIHyHyakeYaYnSAwd8bow==, - } - engines: { node: ">=12" } + resolution: {integrity: sha512-uBq4egWHTcTt33a72vpSG0z3HnPuIl6NqYcTrKEg2azoEyl2hpW0zqlxysq2pK9HlDIHyHyakeYaYnSAwd8bow==} + engines: {node: '>=12'} dunder-proto@1.0.1: - resolution: - { - integrity: sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==, - } - engines: { node: ">= 0.4" } + resolution: {integrity: sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==} + engines: {node: '>= 0.4'} eastasianwidth@0.2.0: - resolution: - { - integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==, - } + resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==} ejs@3.1.10: - resolution: - { - integrity: sha512-UeJmFfOrAQS8OJWPZ4qtgHyWExa088/MtK5UEyoJGFH67cDEXkZSviOiKRCZ4Xij0zxI3JECgYs3oKx+AizQBA==, - } - engines: { node: ">=0.10.0" } + resolution: {integrity: sha512-UeJmFfOrAQS8OJWPZ4qtgHyWExa088/MtK5UEyoJGFH67cDEXkZSviOiKRCZ4Xij0zxI3JECgYs3oKx+AizQBA==} + engines: {node: '>=0.10.0'} hasBin: true electron-to-chromium@1.5.339: - resolution: - { - integrity: sha512-Is+0BBHJ4NrdpAYiperrmp53pLywG/yV/6lIMTAnhxvzj/Cmn5Q/ogSHC6AKe7X+8kPLxxFk0cs5oc/3j/fxIg==, - } + resolution: {integrity: sha512-Is+0BBHJ4NrdpAYiperrmp53pLywG/yV/6lIMTAnhxvzj/Cmn5Q/ogSHC6AKe7X+8kPLxxFk0cs5oc/3j/fxIg==} elliptic@6.6.1: - resolution: - { - integrity: sha512-RaddvvMatK2LJHqFJ+YA4WysVN5Ita9E35botqIYspQ4TkRAlCicdzKOjlyv/1Za5RyTNn7di//eEV0uTAfe3g==, - } + resolution: {integrity: sha512-RaddvvMatK2LJHqFJ+YA4WysVN5Ita9E35botqIYspQ4TkRAlCicdzKOjlyv/1Za5RyTNn7di//eEV0uTAfe3g==} emoji-regex@8.0.0: - resolution: - { - integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==, - } + resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} emoji-regex@9.2.2: - resolution: - { - integrity: sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==, - } + resolution: {integrity: sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==} empathic@2.0.0: - resolution: - { - integrity: sha512-i6UzDscO/XfAcNYD75CfICkmfLedpyPDdozrLMmQc5ORaQcdMoc21OnlEylMIqI7U8eniKrPMxxtj8k0vhmJhA==, - } - engines: { node: ">=14" } + resolution: {integrity: sha512-i6UzDscO/XfAcNYD75CfICkmfLedpyPDdozrLMmQc5ORaQcdMoc21OnlEylMIqI7U8eniKrPMxxtj8k0vhmJhA==} + engines: {node: '>=14'} encoding-sniffer@0.2.1: - resolution: - { - integrity: sha512-5gvq20T6vfpekVtqrYQsSCFZ1wEg5+wW0/QaZMWkFr6BqD3NfKs0rLCx4rrVlSWJeZb5NBJgVLswK/w2MWU+Gw==, - } + resolution: {integrity: sha512-5gvq20T6vfpekVtqrYQsSCFZ1wEg5+wW0/QaZMWkFr6BqD3NfKs0rLCx4rrVlSWJeZb5NBJgVLswK/w2MWU+Gw==} ensure-posix-path@1.1.1: - resolution: - { - integrity: sha512-VWU0/zXzVbeJNXvME/5EmLuEj2TauvoaTz6aFYK1Z92JCBlDlZ3Gu0tuGR42kpW1754ywTs+QB0g5TP0oj9Zaw==, - } + resolution: {integrity: sha512-VWU0/zXzVbeJNXvME/5EmLuEj2TauvoaTz6aFYK1Z92JCBlDlZ3Gu0tuGR42kpW1754ywTs+QB0g5TP0oj9Zaw==} entities@2.2.0: - resolution: - { - integrity: sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==, - } + resolution: {integrity: sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==} entities@4.5.0: - resolution: - { - integrity: sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==, - } - engines: { node: ">=0.12" } + resolution: {integrity: sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==} + engines: {node: '>=0.12'} entities@6.0.1: - resolution: - { - integrity: sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g==, - } - engines: { node: ">=0.12" } + resolution: {integrity: sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g==} + engines: {node: '>=0.12'} entities@7.0.1: - resolution: - { - integrity: sha512-TWrgLOFUQTH994YUyl1yT4uyavY5nNB5muff+RtWaqNVCAK408b5ZnnbNAUEWLTCpum9w6arT70i1XdQ4UeOPA==, - } - engines: { node: ">=0.12" } + resolution: {integrity: sha512-TWrgLOFUQTH994YUyl1yT4uyavY5nNB5muff+RtWaqNVCAK408b5ZnnbNAUEWLTCpum9w6arT70i1XdQ4UeOPA==} + engines: {node: '>=0.12'} eol@0.9.1: - resolution: - { - integrity: sha512-Ds/TEoZjwggRoz/Q2O7SE3i4Jm66mqTDfmdHdq/7DKVk3bro9Q8h6WdXKdPqFLMoqxrDK5SVRzHVPOS6uuGtrg==, - } + resolution: {integrity: sha512-Ds/TEoZjwggRoz/Q2O7SE3i4Jm66mqTDfmdHdq/7DKVk3bro9Q8h6WdXKdPqFLMoqxrDK5SVRzHVPOS6uuGtrg==} error-ex@1.3.4: - resolution: - { - integrity: sha512-sqQamAnR14VgCr1A618A3sGrygcpK+HEbenA/HiEAkkUwcZIIB/tgWqHFxWgOyDh4nB4JCRimh79dR5Ywc9MDQ==, - } + resolution: {integrity: sha512-sqQamAnR14VgCr1A618A3sGrygcpK+HEbenA/HiEAkkUwcZIIB/tgWqHFxWgOyDh4nB4JCRimh79dR5Ywc9MDQ==} es-abstract@1.24.2: - resolution: - { - integrity: sha512-2FpH9Q5i2RRwyEP1AylXe6nYLR5OhaJTZwmlcP0dL/+JCbgg7yyEo/sEK6HeGZRf3dFpWwThaRHVApXSkW3xeg==, - } - engines: { node: ">= 0.4" } + resolution: {integrity: sha512-2FpH9Q5i2RRwyEP1AylXe6nYLR5OhaJTZwmlcP0dL/+JCbgg7yyEo/sEK6HeGZRf3dFpWwThaRHVApXSkW3xeg==} + engines: {node: '>= 0.4'} es-define-property@1.0.1: - resolution: - { - integrity: sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==, - } - engines: { node: ">= 0.4" } + resolution: {integrity: sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==} + engines: {node: '>= 0.4'} es-errors@1.3.0: - resolution: - { - integrity: sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==, - } - engines: { node: ">= 0.4" } + resolution: {integrity: sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==} + engines: {node: '>= 0.4'} es-iterator-helpers@1.3.2: - resolution: - { - integrity: sha512-HVLACW1TppGYjJ8H6/jqH/pqOtKRw6wMlrB23xfExmFWxFquAIWCmwoLsOyN96K4a5KbmOf5At9ZUO3GZbetAw==, - } - engines: { node: ">= 0.4" } + resolution: {integrity: sha512-HVLACW1TppGYjJ8H6/jqH/pqOtKRw6wMlrB23xfExmFWxFquAIWCmwoLsOyN96K4a5KbmOf5At9ZUO3GZbetAw==} + engines: {node: '>= 0.4'} es-module-lexer@2.0.0: - resolution: - { - integrity: sha512-5POEcUuZybH7IdmGsD8wlf0AI55wMecM9rVBTI/qEAy2c1kTOm3DjFYjrBdI2K3BaJjJYfYFeRtM0t9ssnRuxw==, - } + resolution: {integrity: sha512-5POEcUuZybH7IdmGsD8wlf0AI55wMecM9rVBTI/qEAy2c1kTOm3DjFYjrBdI2K3BaJjJYfYFeRtM0t9ssnRuxw==} es-object-atoms@1.1.1: - resolution: - { - integrity: sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==, - } - engines: { node: ">= 0.4" } + resolution: {integrity: sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==} + engines: {node: '>= 0.4'} es-set-tostringtag@2.1.0: - resolution: - { - integrity: sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==, - } - engines: { node: ">= 0.4" } + resolution: {integrity: sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==} + engines: {node: '>= 0.4'} es-shim-unscopables@1.1.0: - resolution: - { - integrity: sha512-d9T8ucsEhh8Bi1woXCf+TIKDIROLG5WCkxg8geBCbvk22kzwC5G2OnXVMO6FUsvQlgUUXQ2itephWDLqDzbeCw==, - } - engines: { node: ">= 0.4" } + resolution: {integrity: sha512-d9T8ucsEhh8Bi1woXCf+TIKDIROLG5WCkxg8geBCbvk22kzwC5G2OnXVMO6FUsvQlgUUXQ2itephWDLqDzbeCw==} + engines: {node: '>= 0.4'} es-to-primitive@1.3.0: - resolution: - { - integrity: sha512-w+5mJ3GuFL+NjVtJlvydShqE1eN3h3PbI7/5LAsYJP/2qtuMXjfL2LpHSRqo4b4eSF5K/DH1JXKUAHSB2UW50g==, - } - engines: { node: ">= 0.4" } + resolution: {integrity: sha512-w+5mJ3GuFL+NjVtJlvydShqE1eN3h3PbI7/5LAsYJP/2qtuMXjfL2LpHSRqo4b4eSF5K/DH1JXKUAHSB2UW50g==} + engines: {node: '>= 0.4'} esbuild@0.27.7: - resolution: - { - integrity: sha512-IxpibTjyVnmrIQo5aqNpCgoACA/dTKLTlhMHihVHhdkxKyPO1uBBthumT0rdHmcsk9uMonIWS0m4FljWzILh3w==, - } - engines: { node: ">=18" } + resolution: {integrity: sha512-IxpibTjyVnmrIQo5aqNpCgoACA/dTKLTlhMHihVHhdkxKyPO1uBBthumT0rdHmcsk9uMonIWS0m4FljWzILh3w==} + engines: {node: '>=18'} hasBin: true escalade@3.2.0: - resolution: - { - integrity: sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==, - } - engines: { node: ">=6" } + resolution: {integrity: sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==} + engines: {node: '>=6'} escape-string-regexp@1.0.5: - resolution: - { - integrity: sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==, - } - engines: { node: ">=0.8.0" } + resolution: {integrity: sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==} + engines: {node: '>=0.8.0'} escape-string-regexp@4.0.0: - resolution: - { - integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==, - } - engines: { node: ">=10" } + resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==} + engines: {node: '>=10'} eslint-config-google@0.14.0: - resolution: - { - integrity: sha512-WsbX4WbjuMvTdeVL6+J3rK1RGhCTqjsFjX7UMSMgZiyxxaNLkoJENbrGExzERFeoTpGw3F3FypTiWAP9ZXzkEw==, - } - engines: { node: ">=0.10.0" } + resolution: {integrity: sha512-WsbX4WbjuMvTdeVL6+J3rK1RGhCTqjsFjX7UMSMgZiyxxaNLkoJENbrGExzERFeoTpGw3F3FypTiWAP9ZXzkEw==} + engines: {node: '>=0.10.0'} peerDependencies: - eslint: ">=5.16.0" + eslint: '>=5.16.0' eslint-config-prettier@10.1.8: - resolution: - { - integrity: sha512-82GZUjRS0p/jganf6q1rEO25VSoHH0hKPCTrgillPjdI/3bgBhAE1QzHrHTizjpRvy6pGAvKjDJtk2pF9NDq8w==, - } + resolution: {integrity: sha512-82GZUjRS0p/jganf6q1rEO25VSoHH0hKPCTrgillPjdI/3bgBhAE1QzHrHTizjpRvy6pGAvKjDJtk2pF9NDq8w==} hasBin: true peerDependencies: - eslint: ">=7.0.0" + eslint: '>=7.0.0' eslint-etc@5.2.1: - resolution: - { - integrity: sha512-lFJBSiIURdqQKq9xJhvSJFyPA+VeTh5xvk24e8pxVL7bwLBtGF60C/KRkLTMrvCZ6DA3kbPuYhLWY0TZMlqTsg==, - } + resolution: {integrity: sha512-lFJBSiIURdqQKq9xJhvSJFyPA+VeTh5xvk24e8pxVL7bwLBtGF60C/KRkLTMrvCZ6DA3kbPuYhLWY0TZMlqTsg==} peerDependencies: eslint: ^8.0.0 - typescript: ">=4.0.0" + typescript: '>=4.0.0' eslint-import-resolver-node@0.3.10: - resolution: - { - integrity: sha512-tRrKqFyCaKict5hOd244sL6EQFNycnMQnBe+j8uqGNXYzsImGbGUU4ibtoaBmv5FLwJwcFJNeg1GeVjQfbMrDQ==, - } + resolution: {integrity: sha512-tRrKqFyCaKict5hOd244sL6EQFNycnMQnBe+j8uqGNXYzsImGbGUU4ibtoaBmv5FLwJwcFJNeg1GeVjQfbMrDQ==} eslint-module-utils@2.12.1: - resolution: - { - integrity: sha512-L8jSWTze7K2mTg0vos/RuLRS5soomksDPoJLXIslC7c8Wmut3bx7CPpJijDcBZtxQ5lrbUdM+s0OlNbz0DCDNw==, - } - engines: { node: ">=4" } + resolution: {integrity: sha512-L8jSWTze7K2mTg0vos/RuLRS5soomksDPoJLXIslC7c8Wmut3bx7CPpJijDcBZtxQ5lrbUdM+s0OlNbz0DCDNw==} + engines: {node: '>=4'} peerDependencies: - "@typescript-eslint/parser": "*" - eslint: "*" - eslint-import-resolver-node: "*" - eslint-import-resolver-typescript: "*" - eslint-import-resolver-webpack: "*" + '@typescript-eslint/parser': '*' + eslint: '*' + eslint-import-resolver-node: '*' + eslint-import-resolver-typescript: '*' + eslint-import-resolver-webpack: '*' peerDependenciesMeta: - "@typescript-eslint/parser": + '@typescript-eslint/parser': optional: true eslint: optional: true @@ -5905,40 +3962,31 @@ packages: optional: true eslint-plugin-deprecate@0.9.0: - resolution: - { - integrity: sha512-M4rP6pRQcvM/LxafQ0PzNKYkfuDn06pOW2uRB2e2WFJiE2KvQqFspxo2Rta3ee6NatHzqDQ4q8UPnaxGMtn5Zw==, - } - engines: { node: ">=18.18.0" } + resolution: {integrity: sha512-M4rP6pRQcvM/LxafQ0PzNKYkfuDn06pOW2uRB2e2WFJiE2KvQqFspxo2Rta3ee6NatHzqDQ4q8UPnaxGMtn5Zw==} + engines: {node: '>=18.18.0'} peerDependencies: eslint: ^8.0.0 || ^9.0.0 eslint-plugin-import@2.32.0: - resolution: - { - integrity: sha512-whOE1HFo/qJDyX4SnXzP4N6zOWn79WhnCUY/iDR0mPfQZO8wcYE4JClzI2oZrhBnnMUCBCHZhO6VQyoBU95mZA==, - } - engines: { node: ">=4" } + resolution: {integrity: sha512-whOE1HFo/qJDyX4SnXzP4N6zOWn79WhnCUY/iDR0mPfQZO8wcYE4JClzI2oZrhBnnMUCBCHZhO6VQyoBU95mZA==} + engines: {node: '>=4'} peerDependencies: - "@typescript-eslint/parser": "*" + '@typescript-eslint/parser': '*' eslint: ^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8 || ^9 peerDependenciesMeta: - "@typescript-eslint/parser": + '@typescript-eslint/parser': optional: true eslint-plugin-jest@29.15.2: - resolution: - { - integrity: sha512-kEN4r9RZl1xcsb4arGq89LrcVdOUFII/JSCwtTPJyv16mDwmPrcuEQwpxqZHeINvcsd7oK5O/rhdGlxFRaZwvQ==, - } - engines: { node: ^20.12.0 || ^22.0.0 || >=24.0.0 } + resolution: {integrity: sha512-kEN4r9RZl1xcsb4arGq89LrcVdOUFII/JSCwtTPJyv16mDwmPrcuEQwpxqZHeINvcsd7oK5O/rhdGlxFRaZwvQ==} + engines: {node: ^20.12.0 || ^22.0.0 || >=24.0.0} peerDependencies: - "@typescript-eslint/eslint-plugin": ^8.0.0 + '@typescript-eslint/eslint-plugin': ^8.0.0 eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 - jest: "*" - typescript: ">=4.8.4 <7.0.0" + jest: '*' + typescript: '>=4.8.4 <7.0.0' peerDependenciesMeta: - "@typescript-eslint/eslint-plugin": + '@typescript-eslint/eslint-plugin': optional: true jest: optional: true @@ -5946,302 +3994,185 @@ packages: optional: true eslint-plugin-jsdoc@61.7.1: - resolution: - { - integrity: sha512-36DpldF95MlTX//n3/naULFVt8d1cV4jmSkx7ZKrE9ikkKHAgMLesuWp1SmwpVwAs5ndIM6abKd6PeOYZUgdWg==, - } - engines: { node: ">=20.11.0" } + resolution: {integrity: sha512-36DpldF95MlTX//n3/naULFVt8d1cV4jmSkx7ZKrE9ikkKHAgMLesuWp1SmwpVwAs5ndIM6abKd6PeOYZUgdWg==} + engines: {node: '>=20.11.0'} peerDependencies: eslint: ^7.0.0 || ^8.0.0 || ^9.0.0 eslint-plugin-jsx-a11y@6.10.2: - resolution: - { - integrity: sha512-scB3nz4WmG75pV8+3eRUQOHZlNSUhFNq37xnpgRkCCELU3XMvXAxLk1eqWWyE22Ki4Q01Fnsw9BA3cJHDPgn2Q==, - } - engines: { node: ">=4.0" } + resolution: {integrity: sha512-scB3nz4WmG75pV8+3eRUQOHZlNSUhFNq37xnpgRkCCELU3XMvXAxLk1eqWWyE22Ki4Q01Fnsw9BA3cJHDPgn2Q==} + engines: {node: '>=4.0'} peerDependencies: eslint: ^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9 eslint-plugin-matrix-org@2.1.0: - resolution: - { - integrity: sha512-YjVQ0qunzVV34tpUchLWhOrOalGfRLm0tclS4dPYnXS8Ui+p12o/YtRHt+26Mg5tJ0QH76HsGC0LJKLVLNoqfg==, - } + resolution: {integrity: sha512-YjVQ0qunzVV34tpUchLWhOrOalGfRLm0tclS4dPYnXS8Ui+p12o/YtRHt+26Mg5tJ0QH76HsGC0LJKLVLNoqfg==} peerDependencies: - "@babel/core": "*" - "@babel/eslint-parser": "*" - "@babel/eslint-plugin": "*" - "@stylistic/eslint-plugin": "*" - "@typescript-eslint/eslint-plugin": "*" - "@typescript-eslint/parser": "*" - eslint: "*" - eslint-config-google: "*" - eslint-config-prettier: "*" - eslint-plugin-deprecate: "*" - eslint-plugin-import: "*" - eslint-plugin-jest: "*" - eslint-plugin-jsx-a11y: "*" - eslint-plugin-react: "*" - eslint-plugin-react-hooks: "*" - eslint-plugin-unicorn: "*" - prettier: "*" - typescript: "*" + '@babel/core': '*' + '@babel/eslint-parser': '*' + '@babel/eslint-plugin': '*' + '@stylistic/eslint-plugin': '*' + '@typescript-eslint/eslint-plugin': '*' + '@typescript-eslint/parser': '*' + eslint: '*' + eslint-config-google: '*' + eslint-config-prettier: '*' + eslint-plugin-deprecate: '*' + eslint-plugin-import: '*' + eslint-plugin-jest: '*' + eslint-plugin-jsx-a11y: '*' + eslint-plugin-react: '*' + eslint-plugin-react-hooks: '*' + eslint-plugin-unicorn: '*' + prettier: '*' + typescript: '*' eslint-plugin-react-hooks@5.2.0: - resolution: - { - integrity: sha512-+f15FfK64YQwZdJNELETdn5ibXEUQmW1DZL6KXhNnc2heoy/sg9VJJeT7n8TlMWouzWqSWavFkIhHyIbIAEapg==, - } - engines: { node: ">=10" } + resolution: {integrity: sha512-+f15FfK64YQwZdJNELETdn5ibXEUQmW1DZL6KXhNnc2heoy/sg9VJJeT7n8TlMWouzWqSWavFkIhHyIbIAEapg==} + engines: {node: '>=10'} peerDependencies: eslint: ^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0 || ^9.0.0 eslint-plugin-react@7.37.5: - resolution: - { - integrity: sha512-Qteup0SqU15kdocexFNAJMvCJEfa2xUKNV4CC1xsVMrIIqEy3SQ/rqyxCWNzfrd3/ldy6HMlD2e0JDVpDg2qIA==, - } - engines: { node: ">=4" } + resolution: {integrity: sha512-Qteup0SqU15kdocexFNAJMvCJEfa2xUKNV4CC1xsVMrIIqEy3SQ/rqyxCWNzfrd3/ldy6HMlD2e0JDVpDg2qIA==} + engines: {node: '>=4'} peerDependencies: eslint: ^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9.7 eslint-plugin-rxjs@5.0.3: - resolution: - { - integrity: sha512-fcVkqLmYLRfRp+ShafjpUKuaZ+cw/sXAvM5dfSxiEr7M28QZ/NY7vaOr09FB4rSaZsQyLBnNPh5SL+4EgKjh8Q==, - } + resolution: {integrity: sha512-fcVkqLmYLRfRp+ShafjpUKuaZ+cw/sXAvM5dfSxiEr7M28QZ/NY7vaOr09FB4rSaZsQyLBnNPh5SL+4EgKjh8Q==} peerDependencies: eslint: ^8.0.0 - typescript: ">=4.0.0" + typescript: '>=4.0.0' eslint-plugin-storybook@10.3.5: - resolution: - { - integrity: sha512-rEFkfU3ypF44GpB4tiJ9EFDItueoGvGi3+weLHZax2ON2MB7VIDsxdSUGvIU5tMURg+oWYlpzCyLm4TpDq2deA==, - } + resolution: {integrity: sha512-rEFkfU3ypF44GpB4tiJ9EFDItueoGvGi3+weLHZax2ON2MB7VIDsxdSUGvIU5tMURg+oWYlpzCyLm4TpDq2deA==} peerDependencies: - eslint: ">=8" + eslint: '>=8' storybook: ^10.3.5 eslint-plugin-unicorn@56.0.1: - resolution: - { - integrity: sha512-FwVV0Uwf8XPfVnKSGpMg7NtlZh0G0gBarCaFcMUOoqPxXryxdYxTRRv4kH6B9TFCVIrjRXG+emcxIk2ayZilog==, - } - engines: { node: ">=18.18" } + resolution: {integrity: sha512-FwVV0Uwf8XPfVnKSGpMg7NtlZh0G0gBarCaFcMUOoqPxXryxdYxTRRv4kH6B9TFCVIrjRXG+emcxIk2ayZilog==} + engines: {node: '>=18.18'} peerDependencies: - eslint: ">=8.56.0" + eslint: '>=8.56.0' eslint-rule-composer@0.3.0: - resolution: - { - integrity: sha512-bt+Sh8CtDmn2OajxvNO+BX7Wn4CIWMpTRm3MaiKPCQcnnlm0CS2mhui6QaoeQugs+3Kj2ESKEEGJUdVafwhiCg==, - } - engines: { node: ">=4.0.0" } + resolution: {integrity: sha512-bt+Sh8CtDmn2OajxvNO+BX7Wn4CIWMpTRm3MaiKPCQcnnlm0CS2mhui6QaoeQugs+3Kj2ESKEEGJUdVafwhiCg==} + engines: {node: '>=4.0.0'} eslint-scope@5.1.1: - resolution: - { - integrity: sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==, - } - engines: { node: ">=8.0.0" } + resolution: {integrity: sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==} + engines: {node: '>=8.0.0'} eslint-scope@7.2.2: - resolution: - { - integrity: sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==, - } - engines: { node: ^12.22.0 || ^14.17.0 || >=16.0.0 } + resolution: {integrity: sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} eslint-visitor-keys@2.1.0: - resolution: - { - integrity: sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==, - } - engines: { node: ">=10" } + resolution: {integrity: sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==} + engines: {node: '>=10'} eslint-visitor-keys@3.4.3: - resolution: - { - integrity: sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==, - } - engines: { node: ^12.22.0 || ^14.17.0 || >=16.0.0 } + resolution: {integrity: sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} eslint-visitor-keys@4.2.1: - resolution: - { - integrity: sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==, - } - engines: { node: ^18.18.0 || ^20.9.0 || >=21.1.0 } + resolution: {integrity: sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} eslint-visitor-keys@5.0.1: - resolution: - { - integrity: sha512-tD40eHxA35h0PEIZNeIjkHoDR4YjjJp34biM0mDvplBe//mB+IHCqHDGV7pxF+7MklTvighcCPPZC7ynWyjdTA==, - } - engines: { node: ^20.19.0 || ^22.13.0 || >=24 } + resolution: {integrity: sha512-tD40eHxA35h0PEIZNeIjkHoDR4YjjJp34biM0mDvplBe//mB+IHCqHDGV7pxF+7MklTvighcCPPZC7ynWyjdTA==} + engines: {node: ^20.19.0 || ^22.13.0 || >=24} eslint@8.57.1: - resolution: - { - integrity: sha512-ypowyDxpVSYpkXr9WPv2PAZCtNip1Mv5KTW0SCurXv/9iOpcrH9PaqUElksqEB6pChqHGDRCFTyrZlGhnLNGiA==, - } - engines: { node: ^12.22.0 || ^14.17.0 || >=16.0.0 } + resolution: {integrity: sha512-ypowyDxpVSYpkXr9WPv2PAZCtNip1Mv5KTW0SCurXv/9iOpcrH9PaqUElksqEB6pChqHGDRCFTyrZlGhnLNGiA==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} deprecated: This version is no longer supported. Please see https://eslint.org/version-support for other options. hasBin: true espree@10.4.0: - resolution: - { - integrity: sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ==, - } - engines: { node: ^18.18.0 || ^20.9.0 || >=21.1.0 } + resolution: {integrity: sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} espree@11.2.0: - resolution: - { - integrity: sha512-7p3DrVEIopW1B1avAGLuCSh1jubc01H2JHc8B4qqGblmg5gI9yumBgACjWo4JlIc04ufug4xJ3SQI8HkS/Rgzw==, - } - engines: { node: ^20.19.0 || ^22.13.0 || >=24 } + resolution: {integrity: sha512-7p3DrVEIopW1B1avAGLuCSh1jubc01H2JHc8B4qqGblmg5gI9yumBgACjWo4JlIc04ufug4xJ3SQI8HkS/Rgzw==} + engines: {node: ^20.19.0 || ^22.13.0 || >=24} espree@9.6.1: - resolution: - { - integrity: sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==, - } - engines: { node: ^12.22.0 || ^14.17.0 || >=16.0.0 } + resolution: {integrity: sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} esprima@4.0.1: - resolution: - { - integrity: sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==, - } - engines: { node: ">=4" } + resolution: {integrity: sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==} + engines: {node: '>=4'} hasBin: true esquery@1.7.0: - resolution: - { - integrity: sha512-Ap6G0WQwcU/LHsvLwON1fAQX9Zp0A2Y6Y/cJBl9r/JbW90Zyg4/zbG6zzKa2OTALELarYHmKu0GhpM5EO+7T0g==, - } - engines: { node: ">=0.10" } + resolution: {integrity: sha512-Ap6G0WQwcU/LHsvLwON1fAQX9Zp0A2Y6Y/cJBl9r/JbW90Zyg4/zbG6zzKa2OTALELarYHmKu0GhpM5EO+7T0g==} + engines: {node: '>=0.10'} esrecurse@4.3.0: - resolution: - { - integrity: sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==, - } - engines: { node: ">=4.0" } + resolution: {integrity: sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==} + engines: {node: '>=4.0'} estraverse@4.3.0: - resolution: - { - integrity: sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==, - } - engines: { node: ">=4.0" } + resolution: {integrity: sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==} + engines: {node: '>=4.0'} estraverse@5.3.0: - resolution: - { - integrity: sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==, - } - engines: { node: ">=4.0" } + resolution: {integrity: sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==} + engines: {node: '>=4.0'} estree-walker@2.0.2: - resolution: - { - integrity: sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==, - } + resolution: {integrity: sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==} estree-walker@3.0.3: - resolution: - { - integrity: sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==, - } + resolution: {integrity: sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==} esutils@2.0.3: - resolution: - { - integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==, - } - engines: { node: ">=0.10.0" } + resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==} + engines: {node: '>=0.10.0'} events-universal@1.0.1: - resolution: - { - integrity: sha512-LUd5euvbMLpwOF8m6ivPCbhQeSiYVNb8Vs0fQ8QjXo0JTkEHpz8pxdQf0gStltaPpw0Cca8b39KxvK9cfKRiAw==, - } + resolution: {integrity: sha512-LUd5euvbMLpwOF8m6ivPCbhQeSiYVNb8Vs0fQ8QjXo0JTkEHpz8pxdQf0gStltaPpw0Cca8b39KxvK9cfKRiAw==} events@3.3.0: - resolution: - { - integrity: sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==, - } - engines: { node: ">=0.8.x" } + resolution: {integrity: sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==} + engines: {node: '>=0.8.x'} evp_bytestokey@1.0.3: - resolution: - { - integrity: sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA==, - } + resolution: {integrity: sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA==} expect-type@1.3.0: - resolution: - { - integrity: sha512-knvyeauYhqjOYvQ66MznSMs83wmHrCycNEN6Ao+2AeYEfxUIkuiVxdEa1qlGEPK+We3n0THiDciYSsCcgW/DoA==, - } - engines: { node: ">=12.0.0" } + resolution: {integrity: sha512-knvyeauYhqjOYvQ66MznSMs83wmHrCycNEN6Ao+2AeYEfxUIkuiVxdEa1qlGEPK+We3n0THiDciYSsCcgW/DoA==} + engines: {node: '>=12.0.0'} fast-deep-equal@3.1.3: - resolution: - { - integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==, - } + resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} fast-fifo@1.3.2: - resolution: - { - integrity: sha512-/d9sfos4yxzpwkDkuN7k2SqFKtYNmCTzgfEpz82x34IM9/zc8KGxQoXg1liNC/izpRM/MBdt44Nmx41ZWqk+FQ==, - } + resolution: {integrity: sha512-/d9sfos4yxzpwkDkuN7k2SqFKtYNmCTzgfEpz82x34IM9/zc8KGxQoXg1liNC/izpRM/MBdt44Nmx41ZWqk+FQ==} fast-glob@3.3.3: - resolution: - { - integrity: sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==, - } - engines: { node: ">=8.6.0" } + resolution: {integrity: sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==} + engines: {node: '>=8.6.0'} fast-json-stable-stringify@2.1.0: - resolution: - { - integrity: sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==, - } + resolution: {integrity: sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==} fast-levenshtein@2.0.6: - resolution: - { - integrity: sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==, - } + resolution: {integrity: sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==} fastq@1.20.1: - resolution: - { - integrity: sha512-GGToxJ/w1x32s/D2EKND7kTil4n8OVk/9mycTc4VDza13lOvpUZTGX3mFSCtV9ksdGBVzvsyAVLM6mHFThxXxw==, - } + resolution: {integrity: sha512-GGToxJ/w1x32s/D2EKND7kTil4n8OVk/9mycTc4VDza13lOvpUZTGX3mFSCtV9ksdGBVzvsyAVLM6mHFThxXxw==} fd-package-json@2.0.0: - resolution: - { - integrity: sha512-jKmm9YtsNXN789RS/0mSzOC1NUq9mkVd65vbSSVsKdjGvYXBuE4oWe2QOEoFeRmJg+lPuZxpmrfFclNhoRMneQ==, - } + resolution: {integrity: sha512-jKmm9YtsNXN789RS/0mSzOC1NUq9mkVd65vbSSVsKdjGvYXBuE4oWe2QOEoFeRmJg+lPuZxpmrfFclNhoRMneQ==} fdir@6.5.0: - resolution: - { - integrity: sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==, - } - engines: { node: ">=12.0.0" } + resolution: {integrity: sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==} + engines: {node: '>=12.0.0'} peerDependencies: picomatch: ^3 || ^4 peerDependenciesMeta: @@ -6249,511 +4180,289 @@ packages: optional: true fetch-mock@11.1.5: - resolution: - { - integrity: sha512-KHmZDnZ1ry0pCTrX4YG5DtThHi0MH+GNI9caESnzX/nMJBrvppUHMvLx47M0WY9oAtKOMiPfZDRpxhlHg89BOA==, - } - engines: { node: ">=8.0.0" } + resolution: {integrity: sha512-KHmZDnZ1ry0pCTrX4YG5DtThHi0MH+GNI9caESnzX/nMJBrvppUHMvLx47M0WY9oAtKOMiPfZDRpxhlHg89BOA==} + engines: {node: '>=8.0.0'} peerDependencies: - node-fetch: "*" + node-fetch: '*' peerDependenciesMeta: node-fetch: optional: true fflate@0.4.8: - resolution: - { - integrity: sha512-FJqqoDBR00Mdj9ppamLa/Y7vxm+PRmNWA67N846RvsoYVMKB4q3y/de5PA7gUmRMYK/8CMz2GDZQmCRN1wBcWA==, - } + resolution: {integrity: sha512-FJqqoDBR00Mdj9ppamLa/Y7vxm+PRmNWA67N846RvsoYVMKB4q3y/de5PA7gUmRMYK/8CMz2GDZQmCRN1wBcWA==} file-entry-cache@6.0.1: - resolution: - { - integrity: sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==, - } - engines: { node: ^10.12.0 || >=12.0.0 } + resolution: {integrity: sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==} + engines: {node: ^10.12.0 || >=12.0.0} filelist@1.0.6: - resolution: - { - integrity: sha512-5giy2PkLYY1cP39p17Ech+2xlpTRL9HLspOfEgm0L6CwBXBTgsK5ou0JtzYuepxkaQ/tvhCFIJ5uXo0OrM2DxA==, - } + resolution: {integrity: sha512-5giy2PkLYY1cP39p17Ech+2xlpTRL9HLspOfEgm0L6CwBXBTgsK5ou0JtzYuepxkaQ/tvhCFIJ5uXo0OrM2DxA==} fill-range@7.1.1: - resolution: - { - integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==, - } - engines: { node: ">=8" } + resolution: {integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==} + engines: {node: '>=8'} find-up@4.1.0: - resolution: - { - integrity: sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==, - } - engines: { node: ">=8" } + resolution: {integrity: sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==} + engines: {node: '>=8'} find-up@5.0.0: - resolution: - { - integrity: sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==, - } - engines: { node: ">=10" } + resolution: {integrity: sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==} + engines: {node: '>=10'} flat-cache@3.2.0: - resolution: - { - integrity: sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==, - } - engines: { node: ^10.12.0 || >=12.0.0 } + resolution: {integrity: sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==} + engines: {node: ^10.12.0 || >=12.0.0} flatted@3.4.2: - resolution: - { - integrity: sha512-PjDse7RzhcPkIJwy5t7KPWQSZ9cAbzQXcafsetQoD7sOJRQlGikNbx7yZp2OotDnJyrDcbyRq3Ttb18iYOqkxA==, - } + resolution: {integrity: sha512-PjDse7RzhcPkIJwy5t7KPWQSZ9cAbzQXcafsetQoD7sOJRQlGikNbx7yZp2OotDnJyrDcbyRq3Ttb18iYOqkxA==} for-each@0.3.5: - resolution: - { - integrity: sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg==, - } - engines: { node: ">= 0.4" } + resolution: {integrity: sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg==} + engines: {node: '>= 0.4'} foreground-child@3.3.1: - resolution: - { - integrity: sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==, - } - engines: { node: ">=14" } + resolution: {integrity: sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==} + engines: {node: '>=14'} formatly@0.3.0: - resolution: - { - integrity: sha512-9XNj/o4wrRFyhSMJOvsuyMwy8aUfBaZ1VrqHVfohyXf0Sw0e+yfKG+xZaY3arGCOMdwFsqObtzVOc1gU9KiT9w==, - } - engines: { node: ">=18.3.0" } + resolution: {integrity: sha512-9XNj/o4wrRFyhSMJOvsuyMwy8aUfBaZ1VrqHVfohyXf0Sw0e+yfKG+xZaY3arGCOMdwFsqObtzVOc1gU9KiT9w==} + engines: {node: '>=18.3.0'} hasBin: true fraction.js@5.3.4: - resolution: - { - integrity: sha512-1X1NTtiJphryn/uLQz3whtY6jK3fTqoE3ohKs0tT+Ujr1W59oopxmoEh7Lu5p6vBaPbgoM0bzveAW4Qi5RyWDQ==, - } + resolution: {integrity: sha512-1X1NTtiJphryn/uLQz3whtY6jK3fTqoE3ohKs0tT+Ujr1W59oopxmoEh7Lu5p6vBaPbgoM0bzveAW4Qi5RyWDQ==} fs-extra@10.1.0: - resolution: - { - integrity: sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==, - } - engines: { node: ">=12" } + resolution: {integrity: sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==} + engines: {node: '>=12'} fs-extra@11.3.4: - resolution: - { - integrity: sha512-CTXd6rk/M3/ULNQj8FBqBWHYBVYybQ3VPBw0xGKFe3tuH7ytT6ACnvzpIQ3UZtB8yvUKC2cXn1a+x+5EVQLovA==, - } - engines: { node: ">=14.14" } + resolution: {integrity: sha512-CTXd6rk/M3/ULNQj8FBqBWHYBVYybQ3VPBw0xGKFe3tuH7ytT6ACnvzpIQ3UZtB8yvUKC2cXn1a+x+5EVQLovA==} + engines: {node: '>=14.14'} fs-extra@8.1.0: - resolution: - { - integrity: sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==, - } - engines: { node: ">=6 <7 || >=8" } + resolution: {integrity: sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==} + engines: {node: '>=6 <7 || >=8'} fs-merger@3.2.1: - resolution: - { - integrity: sha512-AN6sX12liy0JE7C2evclwoo0aCG3PFulLjrTLsJpWh/2mM+DinhpSGqYLbHBBbIW1PLRNcFhJG8Axtz8mQW3ug==, - } + resolution: {integrity: sha512-AN6sX12liy0JE7C2evclwoo0aCG3PFulLjrTLsJpWh/2mM+DinhpSGqYLbHBBbIW1PLRNcFhJG8Axtz8mQW3ug==} fs-mkdirp-stream@2.0.1: - resolution: - { - integrity: sha512-UTOY+59K6IA94tec8Wjqm0FSh5OVudGNB0NL/P6fB3HiE3bYOY3VYBGijsnOHNkQSwC1FKkU77pmq7xp9CskLw==, - } - engines: { node: ">=10.13.0" } + resolution: {integrity: sha512-UTOY+59K6IA94tec8Wjqm0FSh5OVudGNB0NL/P6fB3HiE3bYOY3VYBGijsnOHNkQSwC1FKkU77pmq7xp9CskLw==} + engines: {node: '>=10.13.0'} fs-tree-diff@2.0.1: - resolution: - { - integrity: sha512-x+CfAZ/lJHQqwlD64pYM5QxWjzWhSjroaVsr8PW831zOApL55qPibed0c+xebaLWVr2BnHFoHdrwOv8pzt8R5A==, - } - engines: { node: 6.* || 8.* || >= 10.* } + resolution: {integrity: sha512-x+CfAZ/lJHQqwlD64pYM5QxWjzWhSjroaVsr8PW831zOApL55qPibed0c+xebaLWVr2BnHFoHdrwOv8pzt8R5A==} + engines: {node: 6.* || 8.* || >= 10.*} fsevents@2.3.2: - resolution: - { - integrity: sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==, - } - engines: { node: ^8.16.0 || ^10.6.0 || >=11.0.0 } + resolution: {integrity: sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==} + engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} os: [darwin] fsevents@2.3.3: - resolution: - { - integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==, - } - engines: { node: ^8.16.0 || ^10.6.0 || >=11.0.0 } + resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==} + engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} os: [darwin] function-bind@1.1.2: - resolution: - { - integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==, - } + resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==} function.prototype.name@1.1.8: - resolution: - { - integrity: sha512-e5iwyodOHhbMr/yNrc7fDYG4qlbIvI5gajyzPnb5TCwyhjApznQh1BMFou9b30SevY43gCJKXycoCBjMbsuW0Q==, - } - engines: { node: ">= 0.4" } + resolution: {integrity: sha512-e5iwyodOHhbMr/yNrc7fDYG4qlbIvI5gajyzPnb5TCwyhjApznQh1BMFou9b30SevY43gCJKXycoCBjMbsuW0Q==} + engines: {node: '>= 0.4'} functions-have-names@1.2.3: - resolution: - { - integrity: sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==, - } + resolution: {integrity: sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==} generator-function@2.0.1: - resolution: - { - integrity: sha512-SFdFmIJi+ybC0vjlHN0ZGVGHc3lgE0DxPAT0djjVg+kjOnSqclqmj0KQ7ykTOLP6YxoqOvuAODGdcHJn+43q3g==, - } - engines: { node: ">= 0.4" } + resolution: {integrity: sha512-SFdFmIJi+ybC0vjlHN0ZGVGHc3lgE0DxPAT0djjVg+kjOnSqclqmj0KQ7ykTOLP6YxoqOvuAODGdcHJn+43q3g==} + engines: {node: '>= 0.4'} gensync@1.0.0-beta.2: - resolution: - { - integrity: sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==, - } - engines: { node: ">=6.9.0" } + resolution: {integrity: sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==} + engines: {node: '>=6.9.0'} get-caller-file@2.0.5: - resolution: - { - integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==, - } - engines: { node: 6.* || 8.* || >= 10.* } + resolution: {integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==} + engines: {node: 6.* || 8.* || >= 10.*} get-intrinsic@1.3.0: - resolution: - { - integrity: sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==, - } - engines: { node: ">= 0.4" } + resolution: {integrity: sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==} + engines: {node: '>= 0.4'} get-nonce@1.0.1: - resolution: - { - integrity: sha512-FJhYRoDaiatfEkUK8HKlicmu/3SGFD51q3itKDGoSTysQJBnfOcxU5GxnhE1E6soB76MbT0MBtnKJuXyAx+96Q==, - } - engines: { node: ">=6" } + resolution: {integrity: sha512-FJhYRoDaiatfEkUK8HKlicmu/3SGFD51q3itKDGoSTysQJBnfOcxU5GxnhE1E6soB76MbT0MBtnKJuXyAx+96Q==} + engines: {node: '>=6'} get-proto@1.0.1: - resolution: - { - integrity: sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==, - } - engines: { node: ">= 0.4" } + resolution: {integrity: sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==} + engines: {node: '>= 0.4'} get-symbol-description@1.1.0: - resolution: - { - integrity: sha512-w9UMqWwJxHNOvoNzSJ2oPF5wvYcvP7jUvYzhp67yEhTi17ZDBBC1z9pTdGuzjD+EFIqLSYRweZjqfiPzQ06Ebg==, - } - engines: { node: ">= 0.4" } + resolution: {integrity: sha512-w9UMqWwJxHNOvoNzSJ2oPF5wvYcvP7jUvYzhp67yEhTi17ZDBBC1z9pTdGuzjD+EFIqLSYRweZjqfiPzQ06Ebg==} + engines: {node: '>= 0.4'} glob-parent@5.1.2: - resolution: - { - integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==, - } - engines: { node: ">= 6" } + resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} + engines: {node: '>= 6'} glob-parent@6.0.2: - resolution: - { - integrity: sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==, - } - engines: { node: ">=10.13.0" } + resolution: {integrity: sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==} + engines: {node: '>=10.13.0'} glob-stream@8.0.3: - resolution: - { - integrity: sha512-fqZVj22LtFJkHODT+M4N1RJQ3TjnnQhfE9GwZI8qXscYarnhpip70poMldRnP8ipQ/w0B621kOhfc53/J9bd/A==, - } - engines: { node: ">=10.13.0" } + resolution: {integrity: sha512-fqZVj22LtFJkHODT+M4N1RJQ3TjnnQhfE9GwZI8qXscYarnhpip70poMldRnP8ipQ/w0B621kOhfc53/J9bd/A==} + engines: {node: '>=10.13.0'} glob-to-regexp@0.4.1: - resolution: - { - integrity: sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==, - } + resolution: {integrity: sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==} glob@10.5.0: - resolution: - { - integrity: sha512-DfXN8DfhJ7NH3Oe7cFmu3NCu1wKbkReJ8TorzSAFbSKrlNaQSKfIzqYqVY8zlbs2NLBbWpRiU52GX2PbaBVNkg==, - } + resolution: {integrity: sha512-DfXN8DfhJ7NH3Oe7cFmu3NCu1wKbkReJ8TorzSAFbSKrlNaQSKfIzqYqVY8zlbs2NLBbWpRiU52GX2PbaBVNkg==} deprecated: Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me hasBin: true global-jsdom@26.0.0: - resolution: - { - integrity: sha512-BqXpTNZFjP40N+s4k8Bk9HS8GFVPJB/+TKtwcShM84wLv6C5dH9o1dydI3pL6potanhfDiIAVDbaaGj/uSdRSA==, - } - engines: { node: ">=18" } + resolution: {integrity: sha512-BqXpTNZFjP40N+s4k8Bk9HS8GFVPJB/+TKtwcShM84wLv6C5dH9o1dydI3pL6potanhfDiIAVDbaaGj/uSdRSA==} + engines: {node: '>=18'} peerDependencies: - jsdom: ">=26 <27" + jsdom: '>=26 <27' globals@13.24.0: - resolution: - { - integrity: sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==, - } - engines: { node: ">=8" } + resolution: {integrity: sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==} + engines: {node: '>=8'} globals@15.15.0: - resolution: - { - integrity: sha512-7ACyT3wmyp3I61S4fG682L0VA2RGD9otkqGJIwNUMF1SWUombIIk+af1unuDYgMm082aHYwD+mzJvv9Iu8dsgg==, - } - engines: { node: ">=18" } + resolution: {integrity: sha512-7ACyT3wmyp3I61S4fG682L0VA2RGD9otkqGJIwNUMF1SWUombIIk+af1unuDYgMm082aHYwD+mzJvv9Iu8dsgg==} + engines: {node: '>=18'} globalthis@1.0.4: - resolution: - { - integrity: sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==, - } - engines: { node: ">= 0.4" } + resolution: {integrity: sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==} + engines: {node: '>= 0.4'} globby@11.1.0: - resolution: - { - integrity: sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==, - } - engines: { node: ">=10" } + resolution: {integrity: sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==} + engines: {node: '>=10'} gopd@1.2.0: - resolution: - { - integrity: sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==, - } - engines: { node: ">= 0.4" } + resolution: {integrity: sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==} + engines: {node: '>= 0.4'} graceful-fs@4.2.11: - resolution: - { - integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==, - } + resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==} graphemer@1.4.0: - resolution: - { - integrity: sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==, - } + resolution: {integrity: sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==} gulp-sort@2.0.0: - resolution: - { - integrity: sha512-MyTel3FXOdh1qhw1yKhpimQrAmur9q1X0ZigLmCOxouQD+BD3za9/89O+HfbgBQvvh4igEbp0/PUWO+VqGYG1g==, - } + resolution: {integrity: sha512-MyTel3FXOdh1qhw1yKhpimQrAmur9q1X0ZigLmCOxouQD+BD3za9/89O+HfbgBQvvh4igEbp0/PUWO+VqGYG1g==} has-bigints@1.1.0: - resolution: - { - integrity: sha512-R3pbpkcIqv2Pm3dUwgjclDRVmWpTJW2DcMzcIhEXEx1oh/CEMObMm3KLmRJOdvhM7o4uQBnwr8pzRK2sJWIqfg==, - } - engines: { node: ">= 0.4" } + resolution: {integrity: sha512-R3pbpkcIqv2Pm3dUwgjclDRVmWpTJW2DcMzcIhEXEx1oh/CEMObMm3KLmRJOdvhM7o4uQBnwr8pzRK2sJWIqfg==} + engines: {node: '>= 0.4'} has-flag@4.0.0: - resolution: - { - integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==, - } - engines: { node: ">=8" } + resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} + engines: {node: '>=8'} has-property-descriptors@1.0.2: - resolution: - { - integrity: sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==, - } + resolution: {integrity: sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==} has-proto@1.2.0: - resolution: - { - integrity: sha512-KIL7eQPfHQRC8+XluaIw7BHUwwqL19bQn4hzNgdr+1wXoU0KKj6rufu47lhY7KbJR2C6T6+PfyN0Ea7wkSS+qQ==, - } - engines: { node: ">= 0.4" } + resolution: {integrity: sha512-KIL7eQPfHQRC8+XluaIw7BHUwwqL19bQn4hzNgdr+1wXoU0KKj6rufu47lhY7KbJR2C6T6+PfyN0Ea7wkSS+qQ==} + engines: {node: '>= 0.4'} has-symbols@1.1.0: - resolution: - { - integrity: sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==, - } - engines: { node: ">= 0.4" } + resolution: {integrity: sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==} + engines: {node: '>= 0.4'} has-tostringtag@1.0.2: - resolution: - { - integrity: sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==, - } - engines: { node: ">= 0.4" } + resolution: {integrity: sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==} + engines: {node: '>= 0.4'} hash-base@3.0.5: - resolution: - { - integrity: sha512-vXm0l45VbcHEVlTCzs8M+s0VeYsB2lnlAaThoLKGXr3bE/VWDOelNUnycUPEhKEaXARL2TEFjBOyUiM6+55KBg==, - } - engines: { node: ">= 0.10" } + resolution: {integrity: sha512-vXm0l45VbcHEVlTCzs8M+s0VeYsB2lnlAaThoLKGXr3bE/VWDOelNUnycUPEhKEaXARL2TEFjBOyUiM6+55KBg==} + engines: {node: '>= 0.10'} hash-base@3.1.2: - resolution: - { - integrity: sha512-Bb33KbowVTIj5s7Ked1OsqHUeCpz//tPwR+E2zJgJKo9Z5XolZ9b6bdUgjmYlwnWhoOQKoTd1TYToZGn5mAYOg==, - } - engines: { node: ">= 0.8" } + resolution: {integrity: sha512-Bb33KbowVTIj5s7Ked1OsqHUeCpz//tPwR+E2zJgJKo9Z5XolZ9b6bdUgjmYlwnWhoOQKoTd1TYToZGn5mAYOg==} + engines: {node: '>= 0.8'} hash.js@1.1.7: - resolution: - { - integrity: sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA==, - } + resolution: {integrity: sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA==} hasown@2.0.2: - resolution: - { - integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==, - } - engines: { node: ">= 0.4" } + resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==} + engines: {node: '>= 0.4'} he@1.2.0: - resolution: - { - integrity: sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==, - } + resolution: {integrity: sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==} hasBin: true heimdalljs-logger@0.1.10: - resolution: - { - integrity: sha512-pO++cJbhIufVI/fmB/u2Yty3KJD0TqNPecehFae0/eps0hkZ3b4Zc/PezUMOpYuHFQbA7FxHZxa305EhmjLj4g==, - } + resolution: {integrity: sha512-pO++cJbhIufVI/fmB/u2Yty3KJD0TqNPecehFae0/eps0hkZ3b4Zc/PezUMOpYuHFQbA7FxHZxa305EhmjLj4g==} heimdalljs@0.2.6: - resolution: - { - integrity: sha512-o9bd30+5vLBvBtzCPwwGqpry2+n0Hi6H1+qwt6y+0kwRHGGF8TFIhJPmnuM0xO97zaKrDZMwO/V56fAnn8m/tA==, - } + resolution: {integrity: sha512-o9bd30+5vLBvBtzCPwwGqpry2+n0Hi6H1+qwt6y+0kwRHGGF8TFIhJPmnuM0xO97zaKrDZMwO/V56fAnn8m/tA==} hmac-drbg@1.0.1: - resolution: - { - integrity: sha512-Tti3gMqLdZfhOQY1Mzf/AanLiqh1WTiJgEj26ZuYQ9fbkLomzGchCws4FyrSd4VkpBfiNhaE1On+lOz894jvXg==, - } + resolution: {integrity: sha512-Tti3gMqLdZfhOQY1Mzf/AanLiqh1WTiJgEj26ZuYQ9fbkLomzGchCws4FyrSd4VkpBfiNhaE1On+lOz894jvXg==} hoist-non-react-statics@3.3.2: - resolution: - { - integrity: sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==, - } + resolution: {integrity: sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==} hosted-git-info@2.8.9: - resolution: - { - integrity: sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==, - } + resolution: {integrity: sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==} html-encoding-sniffer@4.0.0: - resolution: - { - integrity: sha512-Y22oTqIU4uuPgEemfz7NDJz6OeKf12Lsu+QC+s3BVpda64lTiMYCyGwg5ki4vFxkMwQdeZDl2adZoqUgdFuTgQ==, - } - engines: { node: ">=18" } + resolution: {integrity: sha512-Y22oTqIU4uuPgEemfz7NDJz6OeKf12Lsu+QC+s3BVpda64lTiMYCyGwg5ki4vFxkMwQdeZDl2adZoqUgdFuTgQ==} + engines: {node: '>=18'} html-entities@2.6.0: - resolution: - { - integrity: sha512-kig+rMn/QOVRvr7c86gQ8lWXq+Hkv6CbAH1hLu+RG338StTpE8Z0b44SDVaqVu7HGKf27frdmUYEs9hTUX/cLQ==, - } + resolution: {integrity: sha512-kig+rMn/QOVRvr7c86gQ8lWXq+Hkv6CbAH1hLu+RG338StTpE8Z0b44SDVaqVu7HGKf27frdmUYEs9hTUX/cLQ==} html-escaper@2.0.2: - resolution: - { - integrity: sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==, - } + resolution: {integrity: sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==} html-minifier-terser@6.1.0: - resolution: - { - integrity: sha512-YXxSlJBZTP7RS3tWnQw74ooKa6L9b9i9QYXY21eUEvhZ3u9XLfv6OnFsQq6RxkhHygsaUMvYsZRV5rU/OVNZxw==, - } - engines: { node: ">=12" } + resolution: {integrity: sha512-YXxSlJBZTP7RS3tWnQw74ooKa6L9b9i9QYXY21eUEvhZ3u9XLfv6OnFsQq6RxkhHygsaUMvYsZRV5rU/OVNZxw==} + engines: {node: '>=12'} hasBin: true html-parse-stringify@3.0.1: - resolution: - { - integrity: sha512-KknJ50kTInJ7qIScF3jeaFRpMpE8/lfiTdzf/twXyPBLAGrLRTmkz3AdTnKeh40X8k9L2fdYwEp/42WGXIRGcg==, - } + resolution: {integrity: sha512-KknJ50kTInJ7qIScF3jeaFRpMpE8/lfiTdzf/twXyPBLAGrLRTmkz3AdTnKeh40X8k9L2fdYwEp/42WGXIRGcg==} htmlparser2@10.1.0: - resolution: - { - integrity: sha512-VTZkM9GWRAtEpveh7MSF6SjjrpNVNNVJfFup7xTY3UpFtm67foy9HDVXneLtFVt4pMz5kZtgNcvCniNFb1hlEQ==, - } + resolution: {integrity: sha512-VTZkM9GWRAtEpveh7MSF6SjjrpNVNNVJfFup7xTY3UpFtm67foy9HDVXneLtFVt4pMz5kZtgNcvCniNFb1hlEQ==} http-proxy-agent@7.0.2: - resolution: - { - integrity: sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==, - } - engines: { node: ">= 14" } + resolution: {integrity: sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==} + engines: {node: '>= 14'} https-browserify@1.0.0: - resolution: - { - integrity: sha512-J+FkSdyD+0mA0N+81tMotaRMfSL9SGi+xpD3T6YApKsc3bGSXJlfXri3VyFOeYkfLRQisDk1W+jIFFKBeUBbBg==, - } + resolution: {integrity: sha512-J+FkSdyD+0mA0N+81tMotaRMfSL9SGi+xpD3T6YApKsc3bGSXJlfXri3VyFOeYkfLRQisDk1W+jIFFKBeUBbBg==} https-proxy-agent@5.0.1: - resolution: - { - integrity: sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==, - } - engines: { node: ">= 6" } + resolution: {integrity: sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==} + engines: {node: '>= 6'} https-proxy-agent@7.0.6: - resolution: - { - integrity: sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==, - } - engines: { node: ">= 14" } + resolution: {integrity: sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==} + engines: {node: '>= 14'} i18next-browser-languagedetector@8.2.1: - resolution: - { - integrity: sha512-bZg8+4bdmaOiApD7N7BPT9W8MLZG+nPTOFlLiJiT8uzKXFjhxw4v2ierCXOwB5sFDMtuA5G4kgYZ0AznZxQ/cw==, - } + resolution: {integrity: sha512-bZg8+4bdmaOiApD7N7BPT9W8MLZG+nPTOFlLiJiT8uzKXFjhxw4v2ierCXOwB5sFDMtuA5G4kgYZ0AznZxQ/cw==} i18next-parser@9.4.0: - resolution: - { - integrity: sha512-SLQJGDj/baBIB9ALmJVXSOXWh3Zn9+wH7J2IuQ4rvx8yuQYpUWitmt8cHFjj6FExjgr8dHfd1SGeQgkowXDO1Q==, - } - engines: { node: ^18.0.0 || ^20.0.0 || ^22.0.0, npm: ">=6", yarn: ">=1" } + resolution: {integrity: sha512-SLQJGDj/baBIB9ALmJVXSOXWh3Zn9+wH7J2IuQ4rvx8yuQYpUWitmt8cHFjj6FExjgr8dHfd1SGeQgkowXDO1Q==} + engines: {node: ^18.0.0 || ^20.0.0 || ^22.0.0, npm: '>=6', yarn: '>=1'} deprecated: Project is deprecated, use i18next-cli instead hasBin: true i18next@24.2.3: - resolution: - { - integrity: sha512-lfbf80OzkocvX7nmZtu7nSTNbrTYR52sLWxPtlXX1zAhVw8WEnFk4puUkCR4B1dNQwbSpEHHHemcZu//7EcB7A==, - } + resolution: {integrity: sha512-lfbf80OzkocvX7nmZtu7nSTNbrTYR52sLWxPtlXX1zAhVw8WEnFk4puUkCR4B1dNQwbSpEHHHemcZu//7EcB7A==} peerDependencies: typescript: ^5 peerDependenciesMeta: @@ -6761,10 +4470,7 @@ packages: optional: true i18next@25.10.10: - resolution: - { - integrity: sha512-cqUW2Z3EkRx7NqSyywjkgCLK7KLCL6IFVFcONG7nVYIJ3ekZ1/N5jUsihHV6Bq37NfhgtczxJcxduELtjTwkuQ==, - } + resolution: {integrity: sha512-cqUW2Z3EkRx7NqSyywjkgCLK7KLCL6IFVFcONG7nVYIJ3ekZ1/N5jUsihHV6Bq37NfhgtczxJcxduELtjTwkuQ==} peerDependencies: typescript: ^5 || ^6 peerDependenciesMeta: @@ -6772,477 +4478,270 @@ packages: optional: true iconv-lite@0.6.3: - resolution: - { - integrity: sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==, - } - engines: { node: ">=0.10.0" } + resolution: {integrity: sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==} + engines: {node: '>=0.10.0'} ieee754@1.2.1: - resolution: - { - integrity: sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==, - } + resolution: {integrity: sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==} ignore@5.3.2: - resolution: - { - integrity: sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==, - } - engines: { node: ">= 4" } + resolution: {integrity: sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==} + engines: {node: '>= 4'} ignore@7.0.5: - resolution: - { - integrity: sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==, - } - engines: { node: ">= 4" } + resolution: {integrity: sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==} + engines: {node: '>= 4'} immutable@5.1.5: - resolution: - { - integrity: sha512-t7xcm2siw+hlUM68I+UEOK+z84RzmN59as9DZ7P1l0994DKUWV7UXBMQZVxaoMSRQ+PBZbHCOoBt7a2wxOMt+A==, - } + resolution: {integrity: sha512-t7xcm2siw+hlUM68I+UEOK+z84RzmN59as9DZ7P1l0994DKUWV7UXBMQZVxaoMSRQ+PBZbHCOoBt7a2wxOMt+A==} import-fresh@3.3.1: - resolution: - { - integrity: sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==, - } - engines: { node: ">=6" } + resolution: {integrity: sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==} + engines: {node: '>=6'} imurmurhash@0.1.4: - resolution: - { - integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==, - } - engines: { node: ">=0.8.19" } + resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==} + engines: {node: '>=0.8.19'} indent-string@4.0.0: - resolution: - { - integrity: sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==, - } - engines: { node: ">=8" } + resolution: {integrity: sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==} + engines: {node: '>=8'} inherits@2.0.4: - resolution: - { - integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==, - } + resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} internal-slot@1.1.0: - resolution: - { - integrity: sha512-4gd7VpWNQNB4UKKCFFVcp1AVv+FMOgs9NKzjHKusc8jTMhd5eL1NqQqOpE0KzMds804/yHlglp3uxgluOqAPLw==, - } - engines: { node: ">= 0.4" } + resolution: {integrity: sha512-4gd7VpWNQNB4UKKCFFVcp1AVv+FMOgs9NKzjHKusc8jTMhd5eL1NqQqOpE0KzMds804/yHlglp3uxgluOqAPLw==} + engines: {node: '>= 0.4'} is-arguments@1.2.0: - resolution: - { - integrity: sha512-7bVbi0huj/wrIAOzb8U1aszg9kdi3KN/CyU19CTI7tAoZYEZoL9yCDXpbXN+uPsuWnP02cyug1gleqq+TU+YCA==, - } - engines: { node: ">= 0.4" } + resolution: {integrity: sha512-7bVbi0huj/wrIAOzb8U1aszg9kdi3KN/CyU19CTI7tAoZYEZoL9yCDXpbXN+uPsuWnP02cyug1gleqq+TU+YCA==} + engines: {node: '>= 0.4'} is-array-buffer@3.0.5: - resolution: - { - integrity: sha512-DDfANUiiG2wC1qawP66qlTugJeL5HyzMpfr8lLK+jMQirGzNod0B12cFB/9q838Ru27sBwfw78/rdoU7RERz6A==, - } - engines: { node: ">= 0.4" } + resolution: {integrity: sha512-DDfANUiiG2wC1qawP66qlTugJeL5HyzMpfr8lLK+jMQirGzNod0B12cFB/9q838Ru27sBwfw78/rdoU7RERz6A==} + engines: {node: '>= 0.4'} is-arrayish@0.2.1: - resolution: - { - integrity: sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==, - } + resolution: {integrity: sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==} is-async-function@2.1.1: - resolution: - { - integrity: sha512-9dgM/cZBnNvjzaMYHVoxxfPj2QXt22Ev7SuuPrs+xav0ukGB0S6d4ydZdEiM48kLx5kDV+QBPrpVnFyefL8kkQ==, - } - engines: { node: ">= 0.4" } + resolution: {integrity: sha512-9dgM/cZBnNvjzaMYHVoxxfPj2QXt22Ev7SuuPrs+xav0ukGB0S6d4ydZdEiM48kLx5kDV+QBPrpVnFyefL8kkQ==} + engines: {node: '>= 0.4'} is-bigint@1.1.0: - resolution: - { - integrity: sha512-n4ZT37wG78iz03xPRKJrHTdZbe3IicyucEtdRsV5yglwc3GyUfbAfpSeD0FJ41NbUNSt5wbhqfp1fS+BgnvDFQ==, - } - engines: { node: ">= 0.4" } + resolution: {integrity: sha512-n4ZT37wG78iz03xPRKJrHTdZbe3IicyucEtdRsV5yglwc3GyUfbAfpSeD0FJ41NbUNSt5wbhqfp1fS+BgnvDFQ==} + engines: {node: '>= 0.4'} is-binary-path@2.1.0: - resolution: - { - integrity: sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==, - } - engines: { node: ">=8" } + resolution: {integrity: sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==} + engines: {node: '>=8'} is-boolean-object@1.2.2: - resolution: - { - integrity: sha512-wa56o2/ElJMYqjCjGkXri7it5FbebW5usLw/nPmCMs5DeZ7eziSYZhSmPRn0txqeW4LnAmQQU7FgqLpsEFKM4A==, - } - engines: { node: ">= 0.4" } + resolution: {integrity: sha512-wa56o2/ElJMYqjCjGkXri7it5FbebW5usLw/nPmCMs5DeZ7eziSYZhSmPRn0txqeW4LnAmQQU7FgqLpsEFKM4A==} + engines: {node: '>= 0.4'} is-builtin-module@3.2.1: - resolution: - { - integrity: sha512-BSLE3HnV2syZ0FK0iMA/yUGplUeMmNz4AW5fnTunbCIqZi4vG3WjJT9FHMy5D69xmAYBHXQhJdALdpwVxV501A==, - } - engines: { node: ">=6" } + resolution: {integrity: sha512-BSLE3HnV2syZ0FK0iMA/yUGplUeMmNz4AW5fnTunbCIqZi4vG3WjJT9FHMy5D69xmAYBHXQhJdALdpwVxV501A==} + engines: {node: '>=6'} is-callable@1.2.7: - resolution: - { - integrity: sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==, - } - engines: { node: ">= 0.4" } + resolution: {integrity: sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==} + engines: {node: '>= 0.4'} is-core-module@2.16.1: - resolution: - { - integrity: sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==, - } - engines: { node: ">= 0.4" } + resolution: {integrity: sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==} + engines: {node: '>= 0.4'} is-data-view@1.0.2: - resolution: - { - integrity: sha512-RKtWF8pGmS87i2D6gqQu/l7EYRlVdfzemCJN/P3UOs//x1QE7mfhvzHIApBTRf7axvT6DMGwSwBXYCT0nfB9xw==, - } - engines: { node: ">= 0.4" } + resolution: {integrity: sha512-RKtWF8pGmS87i2D6gqQu/l7EYRlVdfzemCJN/P3UOs//x1QE7mfhvzHIApBTRf7axvT6DMGwSwBXYCT0nfB9xw==} + engines: {node: '>= 0.4'} is-date-object@1.1.0: - resolution: - { - integrity: sha512-PwwhEakHVKTdRNVOw+/Gyh0+MzlCl4R6qKvkhuvLtPMggI1WAHt9sOwZxQLSGpUaDnrdyDsomoRgNnCfKNSXXg==, - } - engines: { node: ">= 0.4" } + resolution: {integrity: sha512-PwwhEakHVKTdRNVOw+/Gyh0+MzlCl4R6qKvkhuvLtPMggI1WAHt9sOwZxQLSGpUaDnrdyDsomoRgNnCfKNSXXg==} + engines: {node: '>= 0.4'} is-docker@3.0.0: - resolution: - { - integrity: sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ==, - } - engines: { node: ^12.20.0 || ^14.13.1 || >=16.0.0 } + resolution: {integrity: sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} hasBin: true is-extglob@2.1.1: - resolution: - { - integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==, - } - engines: { node: ">=0.10.0" } + resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} + engines: {node: '>=0.10.0'} is-finalizationregistry@1.1.1: - resolution: - { - integrity: sha512-1pC6N8qWJbWoPtEjgcL2xyhQOP491EQjeUo3qTKcmV8YSDDJrOepfG8pcC7h/QgnQHYSv0mJ3Z/ZWxmatVrysg==, - } - engines: { node: ">= 0.4" } + resolution: {integrity: sha512-1pC6N8qWJbWoPtEjgcL2xyhQOP491EQjeUo3qTKcmV8YSDDJrOepfG8pcC7h/QgnQHYSv0mJ3Z/ZWxmatVrysg==} + engines: {node: '>= 0.4'} is-fullwidth-code-point@3.0.0: - resolution: - { - integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==, - } - engines: { node: ">=8" } + resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==} + engines: {node: '>=8'} is-generator-function@1.1.2: - resolution: - { - integrity: sha512-upqt1SkGkODW9tsGNG5mtXTXtECizwtS2kA161M+gJPc1xdb/Ax629af6YrTwcOeQHbewrPNlE5Dx7kzvXTizA==, - } - engines: { node: ">= 0.4" } + resolution: {integrity: sha512-upqt1SkGkODW9tsGNG5mtXTXtECizwtS2kA161M+gJPc1xdb/Ax629af6YrTwcOeQHbewrPNlE5Dx7kzvXTizA==} + engines: {node: '>= 0.4'} is-glob@4.0.3: - resolution: - { - integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==, - } - engines: { node: ">=0.10.0" } + resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} + engines: {node: '>=0.10.0'} is-inside-container@1.0.0: - resolution: - { - integrity: sha512-KIYLCCJghfHZxqjYBE7rEy0OBuTd5xCHS7tHVgvCLkx7StIoaxwNW3hCALgEUjFfeRk+MG/Qxmp/vtETEF3tRA==, - } - engines: { node: ">=14.16" } + resolution: {integrity: sha512-KIYLCCJghfHZxqjYBE7rEy0OBuTd5xCHS7tHVgvCLkx7StIoaxwNW3hCALgEUjFfeRk+MG/Qxmp/vtETEF3tRA==} + engines: {node: '>=14.16'} hasBin: true is-map@2.0.3: - resolution: - { - integrity: sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw==, - } - engines: { node: ">= 0.4" } + resolution: {integrity: sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw==} + engines: {node: '>= 0.4'} is-nan@1.3.2: - resolution: - { - integrity: sha512-E+zBKpQ2t6MEo1VsonYmluk9NxGrbzpeeLC2xIViuO2EjU2xsXsBPwTr3Ykv9l08UYEVEdWeRZNouaZqF6RN0w==, - } - engines: { node: ">= 0.4" } + resolution: {integrity: sha512-E+zBKpQ2t6MEo1VsonYmluk9NxGrbzpeeLC2xIViuO2EjU2xsXsBPwTr3Ykv9l08UYEVEdWeRZNouaZqF6RN0w==} + engines: {node: '>= 0.4'} is-negated-glob@1.0.0: - resolution: - { - integrity: sha512-czXVVn/QEmgvej1f50BZ648vUI+em0xqMq2Sn+QncCLN4zj1UAxlT+kw/6ggQTOaZPd1HqKQGEqbpQVtJucWug==, - } - engines: { node: ">=0.10.0" } + resolution: {integrity: sha512-czXVVn/QEmgvej1f50BZ648vUI+em0xqMq2Sn+QncCLN4zj1UAxlT+kw/6ggQTOaZPd1HqKQGEqbpQVtJucWug==} + engines: {node: '>=0.10.0'} is-negative-zero@2.0.3: - resolution: - { - integrity: sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw==, - } - engines: { node: ">= 0.4" } + resolution: {integrity: sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw==} + engines: {node: '>= 0.4'} is-network-error@1.3.1: - resolution: - { - integrity: sha512-6QCxa49rQbmUWLfk0nuGqzql9U8uaV2H6279bRErPBHe/109hCzsLUBUHfbEtvLIHBd6hyXbgedBSHevm43Edw==, - } - engines: { node: ">=16" } + resolution: {integrity: sha512-6QCxa49rQbmUWLfk0nuGqzql9U8uaV2H6279bRErPBHe/109hCzsLUBUHfbEtvLIHBd6hyXbgedBSHevm43Edw==} + engines: {node: '>=16'} is-number-object@1.1.1: - resolution: - { - integrity: sha512-lZhclumE1G6VYD8VHe35wFaIif+CTy5SJIi5+3y4psDgWu4wPDoBhF8NxUOinEc7pHgiTsT6MaBb92rKhhD+Xw==, - } - engines: { node: ">= 0.4" } + resolution: {integrity: sha512-lZhclumE1G6VYD8VHe35wFaIif+CTy5SJIi5+3y4psDgWu4wPDoBhF8NxUOinEc7pHgiTsT6MaBb92rKhhD+Xw==} + engines: {node: '>= 0.4'} is-number@7.0.0: - resolution: - { - integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==, - } - engines: { node: ">=0.12.0" } + resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} + engines: {node: '>=0.12.0'} is-path-inside@3.0.3: - resolution: - { - integrity: sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==, - } - engines: { node: ">=8" } + resolution: {integrity: sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==} + engines: {node: '>=8'} is-plain-obj@4.1.0: - resolution: - { - integrity: sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg==, - } - engines: { node: ">=12" } + resolution: {integrity: sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg==} + engines: {node: '>=12'} is-potential-custom-element-name@1.0.1: - resolution: - { - integrity: sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==, - } + resolution: {integrity: sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==} is-regex@1.2.1: - resolution: - { - integrity: sha512-MjYsKHO5O7mCsmRGxWcLWheFqN9DJ/2TmngvjKXihe6efViPqc274+Fx/4fYj/r03+ESvBdTXK0V6tA3rgez1g==, - } - engines: { node: ">= 0.4" } + resolution: {integrity: sha512-MjYsKHO5O7mCsmRGxWcLWheFqN9DJ/2TmngvjKXihe6efViPqc274+Fx/4fYj/r03+ESvBdTXK0V6tA3rgez1g==} + engines: {node: '>= 0.4'} is-set@2.0.3: - resolution: - { - integrity: sha512-iPAjerrse27/ygGLxw+EBR9agv9Y6uLeYVJMu+QNCoouJ1/1ri0mGrcWpfCqFZuzzx3WjtwxG098X+n4OuRkPg==, - } - engines: { node: ">= 0.4" } + resolution: {integrity: sha512-iPAjerrse27/ygGLxw+EBR9agv9Y6uLeYVJMu+QNCoouJ1/1ri0mGrcWpfCqFZuzzx3WjtwxG098X+n4OuRkPg==} + engines: {node: '>= 0.4'} is-shared-array-buffer@1.0.4: - resolution: - { - integrity: sha512-ISWac8drv4ZGfwKl5slpHG9OwPNty4jOWPRIhBpxOoD+hqITiwuipOQ2bNthAzwA3B4fIjO4Nln74N0S9byq8A==, - } - engines: { node: ">= 0.4" } + resolution: {integrity: sha512-ISWac8drv4ZGfwKl5slpHG9OwPNty4jOWPRIhBpxOoD+hqITiwuipOQ2bNthAzwA3B4fIjO4Nln74N0S9byq8A==} + engines: {node: '>= 0.4'} is-stream@2.0.1: - resolution: - { - integrity: sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==, - } - engines: { node: ">=8" } + resolution: {integrity: sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==} + engines: {node: '>=8'} is-string@1.1.1: - resolution: - { - integrity: sha512-BtEeSsoaQjlSPBemMQIrY1MY0uM6vnS1g5fmufYOtnxLGUZM2178PKbhsk7Ffv58IX+ZtcvoGwccYsh0PglkAA==, - } - engines: { node: ">= 0.4" } + resolution: {integrity: sha512-BtEeSsoaQjlSPBemMQIrY1MY0uM6vnS1g5fmufYOtnxLGUZM2178PKbhsk7Ffv58IX+ZtcvoGwccYsh0PglkAA==} + engines: {node: '>= 0.4'} is-subset@0.1.1: - resolution: - { - integrity: sha512-6Ybun0IkarhmEqxXCNw/C0bna6Zb/TkfUX9UbwJtK6ObwAVCxmAP308WWTHviM/zAqXk05cdhYsUsZeGQh99iw==, - } + resolution: {integrity: sha512-6Ybun0IkarhmEqxXCNw/C0bna6Zb/TkfUX9UbwJtK6ObwAVCxmAP308WWTHviM/zAqXk05cdhYsUsZeGQh99iw==} is-symbol@1.1.1: - resolution: - { - integrity: sha512-9gGx6GTtCQM73BgmHQXfDmLtfjjTUDSyoxTCbp5WtoixAhfgsDirWIcVQ/IHpvI5Vgd5i/J5F7B9cN/WlVbC/w==, - } - engines: { node: ">= 0.4" } + resolution: {integrity: sha512-9gGx6GTtCQM73BgmHQXfDmLtfjjTUDSyoxTCbp5WtoixAhfgsDirWIcVQ/IHpvI5Vgd5i/J5F7B9cN/WlVbC/w==} + engines: {node: '>= 0.4'} is-typed-array@1.1.15: - resolution: - { - integrity: sha512-p3EcsicXjit7SaskXHs1hA91QxgTw46Fv6EFKKGS5DRFLD8yKnohjF3hxoju94b/OcMZoQukzpPpBE9uLVKzgQ==, - } - engines: { node: ">= 0.4" } + resolution: {integrity: sha512-p3EcsicXjit7SaskXHs1hA91QxgTw46Fv6EFKKGS5DRFLD8yKnohjF3hxoju94b/OcMZoQukzpPpBE9uLVKzgQ==} + engines: {node: '>= 0.4'} is-valid-glob@1.0.0: - resolution: - { - integrity: sha512-AhiROmoEFDSsjx8hW+5sGwgKVIORcXnrlAx/R0ZSeaPw70Vw0CqkGBBhHGL58Uox2eXnU1AnvXJl1XlyedO5bA==, - } - engines: { node: ">=0.10.0" } + resolution: {integrity: sha512-AhiROmoEFDSsjx8hW+5sGwgKVIORcXnrlAx/R0ZSeaPw70Vw0CqkGBBhHGL58Uox2eXnU1AnvXJl1XlyedO5bA==} + engines: {node: '>=0.10.0'} is-weakmap@2.0.2: - resolution: - { - integrity: sha512-K5pXYOm9wqY1RgjpL3YTkF39tni1XajUIkawTLUo9EZEVUFga5gSQJF8nNS7ZwJQ02y+1YCNYcMh+HIf1ZqE+w==, - } - engines: { node: ">= 0.4" } + resolution: {integrity: sha512-K5pXYOm9wqY1RgjpL3YTkF39tni1XajUIkawTLUo9EZEVUFga5gSQJF8nNS7ZwJQ02y+1YCNYcMh+HIf1ZqE+w==} + engines: {node: '>= 0.4'} is-weakref@1.1.1: - resolution: - { - integrity: sha512-6i9mGWSlqzNMEqpCp93KwRS1uUOodk2OJ6b+sq7ZPDSy2WuI5NFIxp/254TytR8ftefexkWn5xNiHUNpPOfSew==, - } - engines: { node: ">= 0.4" } + resolution: {integrity: sha512-6i9mGWSlqzNMEqpCp93KwRS1uUOodk2OJ6b+sq7ZPDSy2WuI5NFIxp/254TytR8ftefexkWn5xNiHUNpPOfSew==} + engines: {node: '>= 0.4'} is-weakset@2.0.4: - resolution: - { - integrity: sha512-mfcwb6IzQyOKTs84CQMrOwW4gQcaTOAWJ0zzJCl2WSPDrWk/OzDaImWFH3djXhb24g4eudZfLRozAvPGw4d9hQ==, - } - engines: { node: ">= 0.4" } + resolution: {integrity: sha512-mfcwb6IzQyOKTs84CQMrOwW4gQcaTOAWJ0zzJCl2WSPDrWk/OzDaImWFH3djXhb24g4eudZfLRozAvPGw4d9hQ==} + engines: {node: '>= 0.4'} is-wsl@3.1.1: - resolution: - { - integrity: sha512-e6rvdUCiQCAuumZslxRJWR/Doq4VpPR82kqclvcS0efgt430SlGIk05vdCN58+VrzgtIcfNODjozVielycD4Sw==, - } - engines: { node: ">=16" } + resolution: {integrity: sha512-e6rvdUCiQCAuumZslxRJWR/Doq4VpPR82kqclvcS0efgt430SlGIk05vdCN58+VrzgtIcfNODjozVielycD4Sw==} + engines: {node: '>=16'} isarray@1.0.0: - resolution: - { - integrity: sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==, - } + resolution: {integrity: sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==} isarray@2.0.5: - resolution: - { - integrity: sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==, - } + resolution: {integrity: sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==} isexe@2.0.0: - resolution: - { - integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==, - } + resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} isomorphic-timers-promises@1.0.1: - resolution: - { - integrity: sha512-u4sej9B1LPSxTGKB/HiuzvEQnXH0ECYkSVQU39koSwmFAxhlEAFl9RdTvLv4TOTQUgBS5O3O5fwUxk6byBZ+IQ==, - } - engines: { node: ">=10" } + resolution: {integrity: sha512-u4sej9B1LPSxTGKB/HiuzvEQnXH0ECYkSVQU39koSwmFAxhlEAFl9RdTvLv4TOTQUgBS5O3O5fwUxk6byBZ+IQ==} + engines: {node: '>=10'} istanbul-lib-coverage@3.2.2: - resolution: - { - integrity: sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==, - } - engines: { node: ">=8" } + resolution: {integrity: sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==} + engines: {node: '>=8'} istanbul-lib-report@3.0.1: - resolution: - { - integrity: sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==, - } - engines: { node: ">=10" } + resolution: {integrity: sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==} + engines: {node: '>=10'} istanbul-reports@3.2.0: - resolution: - { - integrity: sha512-HGYWWS/ehqTV3xN10i23tkPkpH46MLCIMFNCaaKNavAXTF1RkqxawEPtnjnGZ6XKSInBKkiOA5BKS+aZiY3AvA==, - } - engines: { node: ">=8" } + resolution: {integrity: sha512-HGYWWS/ehqTV3xN10i23tkPkpH46MLCIMFNCaaKNavAXTF1RkqxawEPtnjnGZ6XKSInBKkiOA5BKS+aZiY3AvA==} + engines: {node: '>=8'} iterator.prototype@1.1.5: - resolution: - { - integrity: sha512-H0dkQoCa3b2VEeKQBOxFph+JAbcrQdE7KC0UkqwpLmv2EC4P41QXP+rqo9wYodACiG5/WM5s9oDApTU8utwj9g==, - } - engines: { node: ">= 0.4" } + resolution: {integrity: sha512-H0dkQoCa3b2VEeKQBOxFph+JAbcrQdE7KC0UkqwpLmv2EC4P41QXP+rqo9wYodACiG5/WM5s9oDApTU8utwj9g==} + engines: {node: '>= 0.4'} jackspeak@3.4.3: - resolution: - { - integrity: sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==, - } + resolution: {integrity: sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==} jake@10.9.4: - resolution: - { - integrity: sha512-wpHYzhxiVQL+IV05BLE2Xn34zW1S223hvjtqk0+gsPrwd/8JNLXJgZZM/iPFsYc1xyphF+6M6EvdE5E9MBGkDA==, - } - engines: { node: ">=10" } + resolution: {integrity: sha512-wpHYzhxiVQL+IV05BLE2Xn34zW1S223hvjtqk0+gsPrwd/8JNLXJgZZM/iPFsYc1xyphF+6M6EvdE5E9MBGkDA==} + engines: {node: '>=10'} hasBin: true jiti@2.6.1: - resolution: - { - integrity: sha512-ekilCSN1jwRvIbgeg/57YFh8qQDNbwDb9xT/qu2DAHbFFZUicIl4ygVaAvzveMhMVr3LnpSKTNnwt8PoOfmKhQ==, - } + resolution: {integrity: sha512-ekilCSN1jwRvIbgeg/57YFh8qQDNbwDb9xT/qu2DAHbFFZUicIl4ygVaAvzveMhMVr3LnpSKTNnwt8PoOfmKhQ==} hasBin: true jose@6.2.2: - resolution: - { - integrity: sha512-d7kPDd34KO/YnzaDOlikGpOurfF0ByC2sEV4cANCtdqLlTfBlw2p14O/5d/zv40gJPbIQxfES3nSx1/oYNyuZQ==, - } + resolution: {integrity: sha512-d7kPDd34KO/YnzaDOlikGpOurfF0ByC2sEV4cANCtdqLlTfBlw2p14O/5d/zv40gJPbIQxfES3nSx1/oYNyuZQ==} js-tokens@10.0.0: - resolution: - { - integrity: sha512-lM/UBzQmfJRo9ABXbPWemivdCW8V2G8FHaHdypQaIy523snUjog0W71ayWXTjiR+ixeMyVHN2XcpnTd/liPg/Q==, - } + resolution: {integrity: sha512-lM/UBzQmfJRo9ABXbPWemivdCW8V2G8FHaHdypQaIy523snUjog0W71ayWXTjiR+ixeMyVHN2XcpnTd/liPg/Q==} js-tokens@4.0.0: - resolution: - { - integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==, - } + resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} js-yaml@4.1.1: - resolution: - { - integrity: sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==, - } + resolution: {integrity: sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==} hasBin: true jsdoc-type-pratt-parser@7.0.0: - resolution: - { - integrity: sha512-c7YbokssPOSHmqTbSAmTtnVgAVa/7lumWNYqomgd5KOMyPrRve2anx6lonfOsXEQacqF9FKVUj7bLg4vRSvdYA==, - } - engines: { node: ">=20.0.0" } + resolution: {integrity: sha512-c7YbokssPOSHmqTbSAmTtnVgAVa/7lumWNYqomgd5KOMyPrRve2anx6lonfOsXEQacqF9FKVUj7bLg4vRSvdYA==} + engines: {node: '>=20.0.0'} jsdom@26.1.0: - resolution: - { - integrity: sha512-Cvc9WUhxSMEo4McES3P7oK3QaXldCfNWp7pl2NNeiIFlCoLr3kfq9kb1fxftiwk1FLV7CvpvDfonxtzUDeSOPg==, - } - engines: { node: ">=18" } + resolution: {integrity: sha512-Cvc9WUhxSMEo4McES3P7oK3QaXldCfNWp7pl2NNeiIFlCoLr3kfq9kb1fxftiwk1FLV7CvpvDfonxtzUDeSOPg==} + engines: {node: '>=18'} peerDependencies: canvas: ^3.0.0 peerDependenciesMeta: @@ -7250,545 +4749,314 @@ packages: optional: true jsesc@0.5.0: - resolution: - { - integrity: sha512-uZz5UnB7u4T9LvwmFqXii7pZSouaRPorGs5who1Ip7VO0wxanFvBL7GkM6dTHlgX+jhBApRetaWpnDabOeTcnA==, - } + resolution: {integrity: sha512-uZz5UnB7u4T9LvwmFqXii7pZSouaRPorGs5who1Ip7VO0wxanFvBL7GkM6dTHlgX+jhBApRetaWpnDabOeTcnA==} hasBin: true jsesc@3.1.0: - resolution: - { - integrity: sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==, - } - engines: { node: ">=6" } + resolution: {integrity: sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==} + engines: {node: '>=6'} hasBin: true json-buffer@3.0.1: - resolution: - { - integrity: sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==, - } + resolution: {integrity: sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==} json-parse-even-better-errors@2.3.1: - resolution: - { - integrity: sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==, - } + resolution: {integrity: sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==} json-schema-traverse@0.4.1: - resolution: - { - integrity: sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==, - } + resolution: {integrity: sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==} json-stable-stringify-without-jsonify@1.0.1: - resolution: - { - integrity: sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==, - } + resolution: {integrity: sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==} json5@1.0.2: - resolution: - { - integrity: sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==, - } + resolution: {integrity: sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==} hasBin: true json5@2.2.3: - resolution: - { - integrity: sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==, - } - engines: { node: ">=6" } + resolution: {integrity: sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==} + engines: {node: '>=6'} hasBin: true jsonfile@4.0.0: - resolution: - { - integrity: sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==, - } + resolution: {integrity: sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==} jsonfile@6.2.0: - resolution: - { - integrity: sha512-FGuPw30AdOIUTRMC2OMRtQV+jkVj2cfPqSeWXv1NEAJ1qZ5zb1X6z1mFhbfOB/iy3ssJCD+3KuZ8r8C3uVFlAg==, - } + resolution: {integrity: sha512-FGuPw30AdOIUTRMC2OMRtQV+jkVj2cfPqSeWXv1NEAJ1qZ5zb1X6z1mFhbfOB/iy3ssJCD+3KuZ8r8C3uVFlAg==} jsx-ast-utils@3.3.5: - resolution: - { - integrity: sha512-ZZow9HBI5O6EPgSJLUb8n2NKgmVWTwCvHGwFuJlMjvLFqlGG6pjirPhtdsseaLZjSibD8eegzmYpUZwoIlj2cQ==, - } - engines: { node: ">=4.0" } + resolution: {integrity: sha512-ZZow9HBI5O6EPgSJLUb8n2NKgmVWTwCvHGwFuJlMjvLFqlGG6pjirPhtdsseaLZjSibD8eegzmYpUZwoIlj2cQ==} + engines: {node: '>=4.0'} jwt-decode@4.0.0: - resolution: - { - integrity: sha512-+KJGIyHgkGuIq3IEBNftfhW/LfWhXUIY6OmyVWjliu5KH1y0fw7VQ8YndE2O4qZdMSd9SqbnC8GOcZEy0Om7sA==, - } - engines: { node: ">=18" } + resolution: {integrity: sha512-+KJGIyHgkGuIq3IEBNftfhW/LfWhXUIY6OmyVWjliu5KH1y0fw7VQ8YndE2O4qZdMSd9SqbnC8GOcZEy0Om7sA==} + engines: {node: '>=18'} keyv@4.5.4: - resolution: - { - integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==, - } + resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==} kleur@3.0.3: - resolution: - { - integrity: sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==, - } - engines: { node: ">=6" } + resolution: {integrity: sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==} + engines: {node: '>=6'} knip@5.88.1: - resolution: - { - integrity: sha512-tpy5o7zu1MjawVkLPuahymVJekYY3kYjvzcoInhIchgePxTlo+api90tBv2KfhAIe5uXh+mez1tAfmbv8/TiZg==, - } - engines: { node: ">=18.18.0" } + resolution: {integrity: sha512-tpy5o7zu1MjawVkLPuahymVJekYY3kYjvzcoInhIchgePxTlo+api90tBv2KfhAIe5uXh+mez1tAfmbv8/TiZg==} + engines: {node: '>=18.18.0'} hasBin: true peerDependencies: - "@types/node": ">=18" - typescript: ">=5.0.4 <7" + '@types/node': '>=18' + typescript: '>=5.0.4 <7' language-subtag-registry@0.3.23: - resolution: - { - integrity: sha512-0K65Lea881pHotoGEa5gDlMxt3pctLi2RplBb7Ezh4rRdLEOtgi7n4EwK9lamnUCkKBqaeKRVebTq6BAxSkpXQ==, - } + resolution: {integrity: sha512-0K65Lea881pHotoGEa5gDlMxt3pctLi2RplBb7Ezh4rRdLEOtgi7n4EwK9lamnUCkKBqaeKRVebTq6BAxSkpXQ==} language-tags@1.0.9: - resolution: - { - integrity: sha512-MbjN408fEndfiQXbFQ1vnd+1NoLDsnQW41410oQBXiyXDMYH5z505juWa4KUE1LqxRC7DgOgZDbKLxHIwm27hA==, - } - engines: { node: ">=0.10" } + resolution: {integrity: sha512-MbjN408fEndfiQXbFQ1vnd+1NoLDsnQW41410oQBXiyXDMYH5z505juWa4KUE1LqxRC7DgOgZDbKLxHIwm27hA==} + engines: {node: '>=0.10'} lead@4.0.0: - resolution: - { - integrity: sha512-DpMa59o5uGUWWjruMp71e6knmwKU3jRBBn1kjuLWN9EeIOxNeSAwvHf03WIl8g/ZMR2oSQC9ej3yeLBwdDc/pg==, - } - engines: { node: ">=10.13.0" } + resolution: {integrity: sha512-DpMa59o5uGUWWjruMp71e6knmwKU3jRBBn1kjuLWN9EeIOxNeSAwvHf03WIl8g/ZMR2oSQC9ej3yeLBwdDc/pg==} + engines: {node: '>=10.13.0'} levn@0.4.1: - resolution: - { - integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==, - } - engines: { node: ">= 0.8.0" } + resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==} + engines: {node: '>= 0.8.0'} lightningcss-android-arm64@1.32.0: - resolution: - { - integrity: sha512-YK7/ClTt4kAK0vo6w3X+Pnm0D2cf2vPHbhOXdoNti1Ga0al1P4TBZhwjATvjNwLEBCnKvjJc2jQgHXH0NEwlAg==, - } - engines: { node: ">= 12.0.0" } + resolution: {integrity: sha512-YK7/ClTt4kAK0vo6w3X+Pnm0D2cf2vPHbhOXdoNti1Ga0al1P4TBZhwjATvjNwLEBCnKvjJc2jQgHXH0NEwlAg==} + engines: {node: '>= 12.0.0'} cpu: [arm64] os: [android] lightningcss-darwin-arm64@1.32.0: - resolution: - { - integrity: sha512-RzeG9Ju5bag2Bv1/lwlVJvBE3q6TtXskdZLLCyfg5pt+HLz9BqlICO7LZM7VHNTTn/5PRhHFBSjk5lc4cmscPQ==, - } - engines: { node: ">= 12.0.0" } + resolution: {integrity: sha512-RzeG9Ju5bag2Bv1/lwlVJvBE3q6TtXskdZLLCyfg5pt+HLz9BqlICO7LZM7VHNTTn/5PRhHFBSjk5lc4cmscPQ==} + engines: {node: '>= 12.0.0'} cpu: [arm64] os: [darwin] lightningcss-darwin-x64@1.32.0: - resolution: - { - integrity: sha512-U+QsBp2m/s2wqpUYT/6wnlagdZbtZdndSmut/NJqlCcMLTWp5muCrID+K5UJ6jqD2BFshejCYXniPDbNh73V8w==, - } - engines: { node: ">= 12.0.0" } + resolution: {integrity: sha512-U+QsBp2m/s2wqpUYT/6wnlagdZbtZdndSmut/NJqlCcMLTWp5muCrID+K5UJ6jqD2BFshejCYXniPDbNh73V8w==} + engines: {node: '>= 12.0.0'} cpu: [x64] os: [darwin] lightningcss-freebsd-x64@1.32.0: - resolution: - { - integrity: sha512-JCTigedEksZk3tHTTthnMdVfGf61Fky8Ji2E4YjUTEQX14xiy/lTzXnu1vwiZe3bYe0q+SpsSH/CTeDXK6WHig==, - } - engines: { node: ">= 12.0.0" } + resolution: {integrity: sha512-JCTigedEksZk3tHTTthnMdVfGf61Fky8Ji2E4YjUTEQX14xiy/lTzXnu1vwiZe3bYe0q+SpsSH/CTeDXK6WHig==} + engines: {node: '>= 12.0.0'} cpu: [x64] os: [freebsd] lightningcss-linux-arm-gnueabihf@1.32.0: - resolution: - { - integrity: sha512-x6rnnpRa2GL0zQOkt6rts3YDPzduLpWvwAF6EMhXFVZXD4tPrBkEFqzGowzCsIWsPjqSK+tyNEODUBXeeVHSkw==, - } - engines: { node: ">= 12.0.0" } + resolution: {integrity: sha512-x6rnnpRa2GL0zQOkt6rts3YDPzduLpWvwAF6EMhXFVZXD4tPrBkEFqzGowzCsIWsPjqSK+tyNEODUBXeeVHSkw==} + engines: {node: '>= 12.0.0'} cpu: [arm] os: [linux] lightningcss-linux-arm64-gnu@1.32.0: - resolution: - { - integrity: sha512-0nnMyoyOLRJXfbMOilaSRcLH3Jw5z9HDNGfT/gwCPgaDjnx0i8w7vBzFLFR1f6CMLKF8gVbebmkUN3fa/kQJpQ==, - } - engines: { node: ">= 12.0.0" } + resolution: {integrity: sha512-0nnMyoyOLRJXfbMOilaSRcLH3Jw5z9HDNGfT/gwCPgaDjnx0i8w7vBzFLFR1f6CMLKF8gVbebmkUN3fa/kQJpQ==} + engines: {node: '>= 12.0.0'} cpu: [arm64] os: [linux] lightningcss-linux-arm64-musl@1.32.0: - resolution: - { - integrity: sha512-UpQkoenr4UJEzgVIYpI80lDFvRmPVg6oqboNHfoH4CQIfNA+HOrZ7Mo7KZP02dC6LjghPQJeBsvXhJod/wnIBg==, - } - engines: { node: ">= 12.0.0" } + resolution: {integrity: sha512-UpQkoenr4UJEzgVIYpI80lDFvRmPVg6oqboNHfoH4CQIfNA+HOrZ7Mo7KZP02dC6LjghPQJeBsvXhJod/wnIBg==} + engines: {node: '>= 12.0.0'} cpu: [arm64] os: [linux] lightningcss-linux-x64-gnu@1.32.0: - resolution: - { - integrity: sha512-V7Qr52IhZmdKPVr+Vtw8o+WLsQJYCTd8loIfpDaMRWGUZfBOYEJeyJIkqGIDMZPwPx24pUMfwSxxI8phr/MbOA==, - } - engines: { node: ">= 12.0.0" } + resolution: {integrity: sha512-V7Qr52IhZmdKPVr+Vtw8o+WLsQJYCTd8loIfpDaMRWGUZfBOYEJeyJIkqGIDMZPwPx24pUMfwSxxI8phr/MbOA==} + engines: {node: '>= 12.0.0'} cpu: [x64] os: [linux] lightningcss-linux-x64-musl@1.32.0: - resolution: - { - integrity: sha512-bYcLp+Vb0awsiXg/80uCRezCYHNg1/l3mt0gzHnWV9XP1W5sKa5/TCdGWaR/zBM2PeF/HbsQv/j2URNOiVuxWg==, - } - engines: { node: ">= 12.0.0" } + resolution: {integrity: sha512-bYcLp+Vb0awsiXg/80uCRezCYHNg1/l3mt0gzHnWV9XP1W5sKa5/TCdGWaR/zBM2PeF/HbsQv/j2URNOiVuxWg==} + engines: {node: '>= 12.0.0'} cpu: [x64] os: [linux] lightningcss-win32-arm64-msvc@1.32.0: - resolution: - { - integrity: sha512-8SbC8BR40pS6baCM8sbtYDSwEVQd4JlFTOlaD3gWGHfThTcABnNDBda6eTZeqbofalIJhFx0qKzgHJmcPTnGdw==, - } - engines: { node: ">= 12.0.0" } + resolution: {integrity: sha512-8SbC8BR40pS6baCM8sbtYDSwEVQd4JlFTOlaD3gWGHfThTcABnNDBda6eTZeqbofalIJhFx0qKzgHJmcPTnGdw==} + engines: {node: '>= 12.0.0'} cpu: [arm64] os: [win32] lightningcss-win32-x64-msvc@1.32.0: - resolution: - { - integrity: sha512-Amq9B/SoZYdDi1kFrojnoqPLxYhQ4Wo5XiL8EVJrVsB8ARoC1PWW6VGtT0WKCemjy8aC+louJnjS7U18x3b06Q==, - } - engines: { node: ">= 12.0.0" } + resolution: {integrity: sha512-Amq9B/SoZYdDi1kFrojnoqPLxYhQ4Wo5XiL8EVJrVsB8ARoC1PWW6VGtT0WKCemjy8aC+louJnjS7U18x3b06Q==} + engines: {node: '>= 12.0.0'} cpu: [x64] os: [win32] lightningcss@1.32.0: - resolution: - { - integrity: sha512-NXYBzinNrblfraPGyrbPoD19C1h9lfI/1mzgWYvXUTe414Gz/X1FD2XBZSZM7rRTrMA8JL3OtAaGifrIKhQ5yQ==, - } - engines: { node: ">= 12.0.0" } + resolution: {integrity: sha512-NXYBzinNrblfraPGyrbPoD19C1h9lfI/1mzgWYvXUTe414Gz/X1FD2XBZSZM7rRTrMA8JL3OtAaGifrIKhQ5yQ==} + engines: {node: '>= 12.0.0'} lilconfig@3.1.3: - resolution: - { - integrity: sha512-/vlFKAoH5Cgt3Ie+JLhRbwOsCQePABiU3tJ1egGvyQ+33R/vcwM2Zl2QR/LzjsBeItPt3oSVXapn+m4nQDvpzw==, - } - engines: { node: ">=14" } + resolution: {integrity: sha512-/vlFKAoH5Cgt3Ie+JLhRbwOsCQePABiU3tJ1egGvyQ+33R/vcwM2Zl2QR/LzjsBeItPt3oSVXapn+m4nQDvpzw==} + engines: {node: '>=14'} lines-and-columns@1.2.4: - resolution: - { - integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==, - } + resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==} livekit-client@2.18.3: - resolution: - { - integrity: sha512-A8QDaVPo+Ye35bJFyKe6PjMOtY33dmdRXGKP/3+BG48ynEES3YwFzHbsPHJiScgI4OZouNef3Ew/BPazXKwo8Q==, - } + resolution: {integrity: sha512-A8QDaVPo+Ye35bJFyKe6PjMOtY33dmdRXGKP/3+BG48ynEES3YwFzHbsPHJiScgI4OZouNef3Ew/BPazXKwo8Q==} peerDependencies: - "@types/dom-mediacapture-record": ^1 + '@types/dom-mediacapture-record': ^1 locate-path@5.0.0: - resolution: - { - integrity: sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==, - } - engines: { node: ">=8" } + resolution: {integrity: sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==} + engines: {node: '>=8'} locate-path@6.0.0: - resolution: - { - integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==, - } - engines: { node: ">=10" } + resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==} + engines: {node: '>=10'} lodash-es@4.18.1: - resolution: - { - integrity: sha512-J8xewKD/Gk22OZbhpOVSwcs60zhd95ESDwezOFuA3/099925PdHJ7OFHNTGtajL3AlZkykD32HykiMo+BIBI8A==, - } + resolution: {integrity: sha512-J8xewKD/Gk22OZbhpOVSwcs60zhd95ESDwezOFuA3/099925PdHJ7OFHNTGtajL3AlZkykD32HykiMo+BIBI8A==} lodash.debounce@4.0.8: - resolution: - { - integrity: sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==, - } + resolution: {integrity: sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==} lodash.merge@4.6.2: - resolution: - { - integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==, - } + resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==} loglevel@1.9.1: - resolution: - { - integrity: sha512-hP3I3kCrDIMuRwAwHltphhDM1r8i55H33GgqjXbrisuJhF4kRhW1dNuxsRklp4bXl8DSdLaNLuiL4A/LWRfxvg==, - } - engines: { node: ">= 0.6.0" } + resolution: {integrity: sha512-hP3I3kCrDIMuRwAwHltphhDM1r8i55H33GgqjXbrisuJhF4kRhW1dNuxsRklp4bXl8DSdLaNLuiL4A/LWRfxvg==} + engines: {node: '>= 0.6.0'} loglevel@1.9.2: - resolution: - { - integrity: sha512-HgMmCqIJSAKqo68l0rS2AanEWfkxaZ5wNiEFb5ggm08lDs9Xl2KxBlX3PTcaD2chBM1gXAYf491/M2Rv8Jwayg==, - } - engines: { node: ">= 0.6.0" } + resolution: {integrity: sha512-HgMmCqIJSAKqo68l0rS2AanEWfkxaZ5wNiEFb5ggm08lDs9Xl2KxBlX3PTcaD2chBM1gXAYf491/M2Rv8Jwayg==} + engines: {node: '>= 0.6.0'} loose-envify@1.4.0: - resolution: - { - integrity: sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==, - } + resolution: {integrity: sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==} hasBin: true loupe@3.2.1: - resolution: - { - integrity: sha512-CdzqowRJCeLU72bHvWqwRBBlLcMEtIvGrlvef74kMnV2AolS9Y8xUv1I0U/MNAWMhBlKIoyuEgoJ0t/bbwHbLQ==, - } + resolution: {integrity: sha512-CdzqowRJCeLU72bHvWqwRBBlLcMEtIvGrlvef74kMnV2AolS9Y8xUv1I0U/MNAWMhBlKIoyuEgoJ0t/bbwHbLQ==} lower-case@2.0.2: - resolution: - { - integrity: sha512-7fm3l3NAF9WfN6W3JOmf5drwpVqX78JtoGJ3A6W0a6ZnldM41w2fV5D490psKFTpMds8TJse/eHLFFsNHHjHgg==, - } + resolution: {integrity: sha512-7fm3l3NAF9WfN6W3JOmf5drwpVqX78JtoGJ3A6W0a6ZnldM41w2fV5D490psKFTpMds8TJse/eHLFFsNHHjHgg==} lru-cache@10.4.3: - resolution: - { - integrity: sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==, - } + resolution: {integrity: sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==} lru-cache@5.1.1: - resolution: - { - integrity: sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==, - } + resolution: {integrity: sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==} lz-string@1.5.0: - resolution: - { - integrity: sha512-h5bgJWpxJNswbU7qCrV0tIKQCaS3blPDrqKWx+QxzuzL1zGUzij9XCWLrSLsJPu5t+eWA/ycetzYAO5IOMcWAQ==, - } + resolution: {integrity: sha512-h5bgJWpxJNswbU7qCrV0tIKQCaS3blPDrqKWx+QxzuzL1zGUzij9XCWLrSLsJPu5t+eWA/ycetzYAO5IOMcWAQ==} hasBin: true magic-string@0.30.21: - resolution: - { - integrity: sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==, - } + resolution: {integrity: sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==} magic-string@0.30.8: - resolution: - { - integrity: sha512-ISQTe55T2ao7XtlAStud6qwYPZjE4GK1S/BeVPus4jrq6JuOnQ00YKQC581RWhR122W7msZV263KzVeLoqidyQ==, - } - engines: { node: ">=12" } + resolution: {integrity: sha512-ISQTe55T2ao7XtlAStud6qwYPZjE4GK1S/BeVPus4jrq6JuOnQ00YKQC581RWhR122W7msZV263KzVeLoqidyQ==} + engines: {node: '>=12'} magicast@0.5.2: - resolution: - { - integrity: sha512-E3ZJh4J3S9KfwdjZhe2afj6R9lGIN5Pher1pF39UGrXRqq/VDaGVIGN13BjHd2u8B61hArAGOnso7nBOouW3TQ==, - } + resolution: {integrity: sha512-E3ZJh4J3S9KfwdjZhe2afj6R9lGIN5Pher1pF39UGrXRqq/VDaGVIGN13BjHd2u8B61hArAGOnso7nBOouW3TQ==} make-dir@4.0.0: - resolution: - { - integrity: sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==, - } - engines: { node: ">=10" } + resolution: {integrity: sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==} + engines: {node: '>=10'} matcher-collection@2.0.1: - resolution: - { - integrity: sha512-daE62nS2ZQsDg9raM0IlZzLmI2u+7ZapXBwdoeBUKAYERPDDIc0qNqA8E0Rp2D+gspKR7BgIFP52GeujaGXWeQ==, - } - engines: { node: 6.* || 8.* || >= 10.* } + resolution: {integrity: sha512-daE62nS2ZQsDg9raM0IlZzLmI2u+7ZapXBwdoeBUKAYERPDDIc0qNqA8E0Rp2D+gspKR7BgIFP52GeujaGXWeQ==} + engines: {node: 6.* || 8.* || >= 10.*} math-intrinsics@1.1.0: - resolution: - { - integrity: sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==, - } - engines: { node: ">= 0.4" } + resolution: {integrity: sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==} + engines: {node: '>= 0.4'} matrix-events-sdk@0.0.1: - resolution: - { - integrity: sha512-1QEOsXO+bhyCroIe2/A5OwaxHvBm7EsSQ46DEDn8RBIfQwN5HWBpFvyWWR4QY0KHPPnnJdI99wgRiAl7Ad5qaA==, - } + resolution: {integrity: sha512-1QEOsXO+bhyCroIe2/A5OwaxHvBm7EsSQ46DEDn8RBIfQwN5HWBpFvyWWR4QY0KHPPnnJdI99wgRiAl7Ad5qaA==} - matrix-js-sdk@https://codeload.github.com/matrix-org/matrix-js-sdk/tar.gz/ca5655bced1cbb215ac1c18e179384a069d98b0a: - resolution: - { - tarball: https://codeload.github.com/matrix-org/matrix-js-sdk/tar.gz/ca5655bced1cbb215ac1c18e179384a069d98b0a, - } + matrix-js-sdk@https://codeload.github.com/matrix-org/matrix-js-sdk/tar.gz/fd01b172368e0ac5479d4830f92ad261a7eccc6c: + resolution: {tarball: https://codeload.github.com/matrix-org/matrix-js-sdk/tar.gz/fd01b172368e0ac5479d4830f92ad261a7eccc6c} version: 41.3.0 - engines: { node: ">=22.0.0" } + engines: {node: '>=22.0.0'} matrix-widget-api@1.17.0: - resolution: - { - integrity: sha512-5FHoo3iEP3Bdlv5jsYPWOqj+pGdFQNLWnJLiB0V7Ygne7bb+Gsj3ibyFyHWC6BVw+Z+tSW4ljHpO17I9TwStwQ==, - } + resolution: {integrity: sha512-5FHoo3iEP3Bdlv5jsYPWOqj+pGdFQNLWnJLiB0V7Ygne7bb+Gsj3ibyFyHWC6BVw+Z+tSW4ljHpO17I9TwStwQ==} md5.js@1.3.5: - resolution: - { - integrity: sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg==, - } + resolution: {integrity: sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg==} merge2@1.4.1: - resolution: - { - integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==, - } - engines: { node: ">= 8" } + resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==} + engines: {node: '>= 8'} micromatch@4.0.8: - resolution: - { - integrity: sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==, - } - engines: { node: ">=8.6" } + resolution: {integrity: sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==} + engines: {node: '>=8.6'} miller-rabin@4.0.1: - resolution: - { - integrity: sha512-115fLhvZVqWwHPbClyntxEVfVDfl9DLLTuJvq3g2O/Oxi8AiNouAHvDSzHS0viUJc+V5vm3eq91Xwqn9dp4jRA==, - } + resolution: {integrity: sha512-115fLhvZVqWwHPbClyntxEVfVDfl9DLLTuJvq3g2O/Oxi8AiNouAHvDSzHS0viUJc+V5vm3eq91Xwqn9dp4jRA==} hasBin: true mime-db@1.52.0: - resolution: - { - integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==, - } - engines: { node: ">= 0.6" } + resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==} + engines: {node: '>= 0.6'} mime-types@2.1.35: - resolution: - { - integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==, - } - engines: { node: ">= 0.6" } + resolution: {integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==} + engines: {node: '>= 0.6'} min-indent@1.0.1: - resolution: - { - integrity: sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==, - } - engines: { node: ">=4" } + resolution: {integrity: sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==} + engines: {node: '>=4'} minimalistic-assert@1.0.1: - resolution: - { - integrity: sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==, - } + resolution: {integrity: sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==} minimalistic-crypto-utils@1.0.1: - resolution: - { - integrity: sha512-JIYlbt6g8i5jKfJ3xz7rF0LXmv2TkDxBLUkiBeZ7bAx4GnnNMr8xFpGnOxn6GhTEHx3SjRrZEoU+j04prX1ktg==, - } + resolution: {integrity: sha512-JIYlbt6g8i5jKfJ3xz7rF0LXmv2TkDxBLUkiBeZ7bAx4GnnNMr8xFpGnOxn6GhTEHx3SjRrZEoU+j04prX1ktg==} minimatch@10.2.5: - resolution: - { - integrity: sha512-MULkVLfKGYDFYejP07QOurDLLQpcjk7Fw+7jXS2R2czRQzR56yHRveU5NDJEOviH+hETZKSkIk5c+T23GjFUMg==, - } - engines: { node: 18 || 20 || >=22 } + resolution: {integrity: sha512-MULkVLfKGYDFYejP07QOurDLLQpcjk7Fw+7jXS2R2czRQzR56yHRveU5NDJEOviH+hETZKSkIk5c+T23GjFUMg==} + engines: {node: 18 || 20 || >=22} minimist@1.2.8: - resolution: - { - integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==, - } + resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==} minipass@7.1.3: - resolution: - { - integrity: sha512-tEBHqDnIoM/1rXME1zgka9g6Q2lcoCkxHLuc7ODJ5BxbP5d4c2Z5cGgtXAku59200Cx7diuHTOYfSBD8n6mm8A==, - } - engines: { node: ">=16 || 14 >=14.17" } + resolution: {integrity: sha512-tEBHqDnIoM/1rXME1zgka9g6Q2lcoCkxHLuc7ODJ5BxbP5d4c2Z5cGgtXAku59200Cx7diuHTOYfSBD8n6mm8A==} + engines: {node: '>=16 || 14 >=14.17'} mktemp@2.0.2: - resolution: - { - integrity: sha512-Q9wJ/xhzeD9Wua1MwDN2v3ah3HENsUVSlzzL9Qw149cL9hHZkXtQGl3Eq36BbdLV+/qUwaP1WtJQ+H/+Oxso8g==, - } - engines: { node: 20 || 22 || 24 } + resolution: {integrity: sha512-Q9wJ/xhzeD9Wua1MwDN2v3ah3HENsUVSlzzL9Qw149cL9hHZkXtQGl3Eq36BbdLV+/qUwaP1WtJQ+H/+Oxso8g==} + engines: {node: 20 || 22 || 24} ms@2.0.0: - resolution: - { - integrity: sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==, - } + resolution: {integrity: sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==} ms@2.1.3: - resolution: - { - integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==, - } + resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} nanoid@3.3.11: - resolution: - { - integrity: sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==, - } - engines: { node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1 } + resolution: {integrity: sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==} + engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} hasBin: true natural-compare@1.4.0: - resolution: - { - integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==, - } + resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==} no-case@3.0.4: - resolution: - { - integrity: sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg==, - } + resolution: {integrity: sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg==} node-addon-api@7.1.1: - resolution: - { - integrity: sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ==, - } + resolution: {integrity: sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ==} node-exports-info@1.6.0: - resolution: - { - integrity: sha512-pyFS63ptit/P5WqUkt+UUfe+4oevH+bFeIiPPdfb0pFeYEu/1ELnJu5l+5EcTKYL5M7zaAa7S8ddywgXypqKCw==, - } - engines: { node: ">= 0.4" } + resolution: {integrity: sha512-pyFS63ptit/P5WqUkt+UUfe+4oevH+bFeIiPPdfb0pFeYEu/1ELnJu5l+5EcTKYL5M7zaAa7S8ddywgXypqKCw==} + engines: {node: '>= 0.4'} node-fetch@2.7.0: - resolution: - { - integrity: sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==, - } - engines: { node: 4.x || >=6.0.0 } + resolution: {integrity: sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==} + engines: {node: 4.x || >=6.0.0} peerDependencies: encoding: ^0.1.0 peerDependenciesMeta: @@ -7796,881 +5064,515 @@ packages: optional: true node-html-parser@5.4.2: - resolution: - { - integrity: sha512-RaBPP3+51hPne/OolXxcz89iYvQvKOydaqoePpOgXcrOKZhjVIzmpKZz+Hd/RBO2/zN2q6CNJhQzucVz+u3Jyw==, - } + resolution: {integrity: sha512-RaBPP3+51hPne/OolXxcz89iYvQvKOydaqoePpOgXcrOKZhjVIzmpKZz+Hd/RBO2/zN2q6CNJhQzucVz+u3Jyw==} node-releases@2.0.37: - resolution: - { - integrity: sha512-1h5gKZCF+pO/o3Iqt5Jp7wc9rH3eJJ0+nh/CIoiRwjRxde/hAHyLPXYN4V3CqKAbiZPSeJFSWHmJsbkicta0Eg==, - } + resolution: {integrity: sha512-1h5gKZCF+pO/o3Iqt5Jp7wc9rH3eJJ0+nh/CIoiRwjRxde/hAHyLPXYN4V3CqKAbiZPSeJFSWHmJsbkicta0Eg==} node-stdlib-browser@1.3.1: - resolution: - { - integrity: sha512-X75ZN8DCLftGM5iKwoYLA3rjnrAEs97MkzvSd4q2746Tgpg8b8XWiBGiBG4ZpgcAqBgtgPHTiAc8ZMCvZuikDw==, - } - engines: { node: ">=10" } + resolution: {integrity: sha512-X75ZN8DCLftGM5iKwoYLA3rjnrAEs97MkzvSd4q2746Tgpg8b8XWiBGiBG4ZpgcAqBgtgPHTiAc8ZMCvZuikDw==} + engines: {node: '>=10'} normalize-package-data@2.5.0: - resolution: - { - integrity: sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==, - } + resolution: {integrity: sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==} normalize-path@3.0.0: - resolution: - { - integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==, - } - engines: { node: ">=0.10.0" } + resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==} + engines: {node: '>=0.10.0'} normalize.css@8.0.1: - resolution: - { - integrity: sha512-qizSNPO93t1YUuUhP22btGOo3chcvDFqFaj2TRybP0DMxkHOCTYwp3n34fel4a31ORXy4m1Xq0Gyqpb5m33qIg==, - } + resolution: {integrity: sha512-qizSNPO93t1YUuUhP22btGOo3chcvDFqFaj2TRybP0DMxkHOCTYwp3n34fel4a31ORXy4m1Xq0Gyqpb5m33qIg==} now-and-later@3.0.0: - resolution: - { - integrity: sha512-pGO4pzSdaxhWTGkfSfHx3hVzJVslFPwBp2Myq9MYN/ChfJZF87ochMAXnvz6/58RJSf5ik2q9tXprBBrk2cpcg==, - } - engines: { node: ">= 10.13.0" } + resolution: {integrity: sha512-pGO4pzSdaxhWTGkfSfHx3hVzJVslFPwBp2Myq9MYN/ChfJZF87ochMAXnvz6/58RJSf5ik2q9tXprBBrk2cpcg==} + engines: {node: '>= 10.13.0'} nth-check@2.1.1: - resolution: - { - integrity: sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==, - } + resolution: {integrity: sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==} nwsapi@2.2.23: - resolution: - { - integrity: sha512-7wfH4sLbt4M0gCDzGE6vzQBo0bfTKjU7Sfpqy/7gs1qBfYz2vEJH6vXcBKpO3+6Yu1telwd0t9HpyOoLEQQbIQ==, - } + resolution: {integrity: sha512-7wfH4sLbt4M0gCDzGE6vzQBo0bfTKjU7Sfpqy/7gs1qBfYz2vEJH6vXcBKpO3+6Yu1telwd0t9HpyOoLEQQbIQ==} object-assign@4.1.1: - resolution: - { - integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==, - } - engines: { node: ">=0.10.0" } + resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==} + engines: {node: '>=0.10.0'} object-deep-merge@2.0.0: - resolution: - { - integrity: sha512-3DC3UMpeffLTHiuXSy/UG4NOIYTLlY9u3V82+djSCLYClWobZiS4ivYzpIUWrRY/nfsJ8cWsKyG3QfyLePmhvg==, - } + resolution: {integrity: sha512-3DC3UMpeffLTHiuXSy/UG4NOIYTLlY9u3V82+djSCLYClWobZiS4ivYzpIUWrRY/nfsJ8cWsKyG3QfyLePmhvg==} object-inspect@1.13.4: - resolution: - { - integrity: sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==, - } - engines: { node: ">= 0.4" } + resolution: {integrity: sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==} + engines: {node: '>= 0.4'} object-is@1.1.6: - resolution: - { - integrity: sha512-F8cZ+KfGlSGi09lJT7/Nd6KJZ9ygtvYC0/UYYLI9nmQKLMnydpB9yvbv9K1uSkEu7FU9vYPmVwLg328tX+ot3Q==, - } - engines: { node: ">= 0.4" } + resolution: {integrity: sha512-F8cZ+KfGlSGi09lJT7/Nd6KJZ9ygtvYC0/UYYLI9nmQKLMnydpB9yvbv9K1uSkEu7FU9vYPmVwLg328tX+ot3Q==} + engines: {node: '>= 0.4'} object-keys@1.1.1: - resolution: - { - integrity: sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==, - } - engines: { node: ">= 0.4" } + resolution: {integrity: sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==} + engines: {node: '>= 0.4'} object.assign@4.1.7: - resolution: - { - integrity: sha512-nK28WOo+QIjBkDduTINE4JkF/UJJKyf2EJxvJKfblDpyg0Q+pkOHNTL0Qwy6NP6FhE/EnzV73BxxqcJaXY9anw==, - } - engines: { node: ">= 0.4" } + resolution: {integrity: sha512-nK28WOo+QIjBkDduTINE4JkF/UJJKyf2EJxvJKfblDpyg0Q+pkOHNTL0Qwy6NP6FhE/EnzV73BxxqcJaXY9anw==} + engines: {node: '>= 0.4'} object.entries@1.1.9: - resolution: - { - integrity: sha512-8u/hfXFRBD1O0hPUjioLhoWFHRmt6tKA4/vZPyckBr18l1KE9uHrFaFaUi8MDRTpi4uak2goyPTSNJLXX2k2Hw==, - } - engines: { node: ">= 0.4" } + resolution: {integrity: sha512-8u/hfXFRBD1O0hPUjioLhoWFHRmt6tKA4/vZPyckBr18l1KE9uHrFaFaUi8MDRTpi4uak2goyPTSNJLXX2k2Hw==} + engines: {node: '>= 0.4'} object.fromentries@2.0.8: - resolution: - { - integrity: sha512-k6E21FzySsSK5a21KRADBd/NGneRegFO5pLHfdQLpRDETUNJueLXs3WCzyQ3tFRDYgbq3KHGXfTbi2bs8WQ6rQ==, - } - engines: { node: ">= 0.4" } + resolution: {integrity: sha512-k6E21FzySsSK5a21KRADBd/NGneRegFO5pLHfdQLpRDETUNJueLXs3WCzyQ3tFRDYgbq3KHGXfTbi2bs8WQ6rQ==} + engines: {node: '>= 0.4'} object.groupby@1.0.3: - resolution: - { - integrity: sha512-+Lhy3TQTuzXI5hevh8sBGqbmurHbbIjAi0Z4S63nthVLmLxfbj4T54a4CfZrXIrt9iP4mVAPYMo/v99taj3wjQ==, - } - engines: { node: ">= 0.4" } + resolution: {integrity: sha512-+Lhy3TQTuzXI5hevh8sBGqbmurHbbIjAi0Z4S63nthVLmLxfbj4T54a4CfZrXIrt9iP4mVAPYMo/v99taj3wjQ==} + engines: {node: '>= 0.4'} object.values@1.2.1: - resolution: - { - integrity: sha512-gXah6aZrcUxjWg2zR2MwouP2eHlCBzdV4pygudehaKXSGW4v2AsRQUK+lwwXhii6KFZcunEnmSUoYp5CXibxtA==, - } - engines: { node: ">= 0.4" } + resolution: {integrity: sha512-gXah6aZrcUxjWg2zR2MwouP2eHlCBzdV4pygudehaKXSGW4v2AsRQUK+lwwXhii6KFZcunEnmSUoYp5CXibxtA==} + engines: {node: '>= 0.4'} observable-hooks@4.2.4: - resolution: - { - integrity: sha512-FdTQgyw1h5bG/QHCBIqctdBSnv9VARJCEilgpV6L2qlw1yeLqFIwPm4U15dMtl5kDmNN0hSt+Nl6iYbLFwEcQA==, - } + resolution: {integrity: sha512-FdTQgyw1h5bG/QHCBIqctdBSnv9VARJCEilgpV6L2qlw1yeLqFIwPm4U15dMtl5kDmNN0hSt+Nl6iYbLFwEcQA==} peerDependencies: - react: ">=16.8.0" - react-dom: ">=16.8.0" - rxjs: ">=6.0.0" + react: '>=16.8.0' + react-dom: '>=16.8.0' + rxjs: '>=6.0.0' obug@2.1.1: - resolution: - { - integrity: sha512-uTqF9MuPraAQ+IsnPf366RG4cP9RtUi7MLO1N3KEc+wb0a6yKpeL0lmk2IB1jY5KHPAlTc6T/JRdC/YqxHNwkQ==, - } + resolution: {integrity: sha512-uTqF9MuPraAQ+IsnPf366RG4cP9RtUi7MLO1N3KEc+wb0a6yKpeL0lmk2IB1jY5KHPAlTc6T/JRdC/YqxHNwkQ==} oidc-client-ts@3.5.0: - resolution: - { - integrity: sha512-l2q8l9CTCTOlbX+AnK4p3M+4CEpKpyQhle6blQkdFhm0IsBqsxm15bYaSa11G7pWdsYr6epdsRZxJpCyCRbT8A==, - } - engines: { node: ">=18" } + resolution: {integrity: sha512-l2q8l9CTCTOlbX+AnK4p3M+4CEpKpyQhle6blQkdFhm0IsBqsxm15bYaSa11G7pWdsYr6epdsRZxJpCyCRbT8A==} + engines: {node: '>=18'} once@1.4.0: - resolution: - { - integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==, - } + resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} open@10.2.0: - resolution: - { - integrity: sha512-YgBpdJHPyQ2UE5x+hlSXcnejzAvD0b22U2OuAP+8OnlJT+PjWPxtgmGqKKc+RgTM63U9gN0YzrYc71R2WT/hTA==, - } - engines: { node: ">=18" } + resolution: {integrity: sha512-YgBpdJHPyQ2UE5x+hlSXcnejzAvD0b22U2OuAP+8OnlJT+PjWPxtgmGqKKc+RgTM63U9gN0YzrYc71R2WT/hTA==} + engines: {node: '>=18'} optionator@0.9.4: - resolution: - { - integrity: sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==, - } - engines: { node: ">= 0.8.0" } + resolution: {integrity: sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==} + engines: {node: '>= 0.8.0'} os-browserify@0.3.0: - resolution: - { - integrity: sha512-gjcpUc3clBf9+210TRaDWbf+rZZZEshZ+DlXMRCeAjp0xhTrnQsKHypIy1J3d5hKdUzj69t708EHtU8P6bUn0A==, - } + resolution: {integrity: sha512-gjcpUc3clBf9+210TRaDWbf+rZZZEshZ+DlXMRCeAjp0xhTrnQsKHypIy1J3d5hKdUzj69t708EHtU8P6bUn0A==} own-keys@1.0.1: - resolution: - { - integrity: sha512-qFOyK5PjiWZd+QQIh+1jhdb9LpxTF0qs7Pm8o5QHYZ0M3vKqSqzsZaEB6oWlxZ+q2sJBMI/Ktgd2N5ZwQoRHfg==, - } - engines: { node: ">= 0.4" } + resolution: {integrity: sha512-qFOyK5PjiWZd+QQIh+1jhdb9LpxTF0qs7Pm8o5QHYZ0M3vKqSqzsZaEB6oWlxZ+q2sJBMI/Ktgd2N5ZwQoRHfg==} + engines: {node: '>= 0.4'} oxc-resolver@11.19.1: - resolution: - { - integrity: sha512-qE/CIg/spwrTBFt5aKmwe3ifeDdLfA2NESN30E42X/lII5ClF8V7Wt6WIJhcGZjp0/Q+nQ+9vgxGk//xZNX2hg==, - } + resolution: {integrity: sha512-qE/CIg/spwrTBFt5aKmwe3ifeDdLfA2NESN30E42X/lII5ClF8V7Wt6WIJhcGZjp0/Q+nQ+9vgxGk//xZNX2hg==} p-limit@2.3.0: - resolution: - { - integrity: sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==, - } - engines: { node: ">=6" } + resolution: {integrity: sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==} + engines: {node: '>=6'} p-limit@3.1.0: - resolution: - { - integrity: sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==, - } - engines: { node: ">=10" } + resolution: {integrity: sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==} + engines: {node: '>=10'} p-locate@4.1.0: - resolution: - { - integrity: sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==, - } - engines: { node: ">=8" } + resolution: {integrity: sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==} + engines: {node: '>=8'} p-locate@5.0.0: - resolution: - { - integrity: sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==, - } - engines: { node: ">=10" } + resolution: {integrity: sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==} + engines: {node: '>=10'} p-retry@8.0.0: - resolution: - { - integrity: sha512-kFVqH1HxOHp8LupNsOys7bSV09VYTRLxarH/mokO4Rqhk6wGi70E0jh4VzvVGXfEVNggHoHLAMWsQqHyU1Ey9A==, - } - engines: { node: ">=22" } + resolution: {integrity: sha512-kFVqH1HxOHp8LupNsOys7bSV09VYTRLxarH/mokO4Rqhk6wGi70E0jh4VzvVGXfEVNggHoHLAMWsQqHyU1Ey9A==} + engines: {node: '>=22'} p-try@2.2.0: - resolution: - { - integrity: sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==, - } - engines: { node: ">=6" } + resolution: {integrity: sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==} + engines: {node: '>=6'} package-json-from-dist@1.0.1: - resolution: - { - integrity: sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==, - } + resolution: {integrity: sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==} pako@1.0.11: - resolution: - { - integrity: sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==, - } + resolution: {integrity: sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==} pako@2.1.0: - resolution: - { - integrity: sha512-w+eufiZ1WuJYgPXbV/PO3NCMEc3xqylkKHzp8bxp1uW4qaSNQUkwmLLEc3kKsfz8lpV1F8Ht3U1Cm+9Srog2ug==, - } + resolution: {integrity: sha512-w+eufiZ1WuJYgPXbV/PO3NCMEc3xqylkKHzp8bxp1uW4qaSNQUkwmLLEc3kKsfz8lpV1F8Ht3U1Cm+9Srog2ug==} param-case@3.0.4: - resolution: - { - integrity: sha512-RXlj7zCYokReqWpOPH9oYivUzLYZ5vAPIfEmCTNViosC78F8F0H9y7T7gG2M39ymgutxF5gcFEsyZQSph9Bp3A==, - } + resolution: {integrity: sha512-RXlj7zCYokReqWpOPH9oYivUzLYZ5vAPIfEmCTNViosC78F8F0H9y7T7gG2M39ymgutxF5gcFEsyZQSph9Bp3A==} parent-module@1.0.1: - resolution: - { - integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==, - } - engines: { node: ">=6" } + resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==} + engines: {node: '>=6'} parse-asn1@5.1.9: - resolution: - { - integrity: sha512-fIYNuZ/HastSb80baGOuPRo1O9cf4baWw5WsAp7dBuUzeTD/BoaG8sVTdlPFksBE2lF21dN+A1AnrpIjSWqHHg==, - } - engines: { node: ">= 0.10" } + resolution: {integrity: sha512-fIYNuZ/HastSb80baGOuPRo1O9cf4baWw5WsAp7dBuUzeTD/BoaG8sVTdlPFksBE2lF21dN+A1AnrpIjSWqHHg==} + engines: {node: '>= 0.10'} parse-imports-exports@0.2.4: - resolution: - { - integrity: sha512-4s6vd6dx1AotCx/RCI2m7t7GCh5bDRUtGNvRfHSP2wbBQdMi67pPe7mtzmgwcaQ8VKK/6IB7Glfyu3qdZJPybQ==, - } + resolution: {integrity: sha512-4s6vd6dx1AotCx/RCI2m7t7GCh5bDRUtGNvRfHSP2wbBQdMi67pPe7mtzmgwcaQ8VKK/6IB7Glfyu3qdZJPybQ==} parse-json@5.2.0: - resolution: - { - integrity: sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==, - } - engines: { node: ">=8" } + resolution: {integrity: sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==} + engines: {node: '>=8'} parse-statements@1.0.11: - resolution: - { - integrity: sha512-HlsyYdMBnbPQ9Jr/VgJ1YF4scnldvJpJxCVx6KgqPL4dxppsWrJHCIIxQXMJrqGnsRkNPATbeMJ8Yxu7JMsYcA==, - } + resolution: {integrity: sha512-HlsyYdMBnbPQ9Jr/VgJ1YF4scnldvJpJxCVx6KgqPL4dxppsWrJHCIIxQXMJrqGnsRkNPATbeMJ8Yxu7JMsYcA==} parse5-htmlparser2-tree-adapter@7.1.0: - resolution: - { - integrity: sha512-ruw5xyKs6lrpo9x9rCZqZZnIUntICjQAd0Wsmp396Ul9lN/h+ifgVV1x1gZHi8euej6wTfpqX8j+BFQxF0NS/g==, - } + resolution: {integrity: sha512-ruw5xyKs6lrpo9x9rCZqZZnIUntICjQAd0Wsmp396Ul9lN/h+ifgVV1x1gZHi8euej6wTfpqX8j+BFQxF0NS/g==} parse5-parser-stream@7.1.2: - resolution: - { - integrity: sha512-JyeQc9iwFLn5TbvvqACIF/VXG6abODeB3Fwmv/TGdLk2LfbWkaySGY72at4+Ty7EkPZj854u4CrICqNk2qIbow==, - } + resolution: {integrity: sha512-JyeQc9iwFLn5TbvvqACIF/VXG6abODeB3Fwmv/TGdLk2LfbWkaySGY72at4+Ty7EkPZj854u4CrICqNk2qIbow==} parse5@7.3.0: - resolution: - { - integrity: sha512-IInvU7fabl34qmi9gY8XOVxhYyMyuH2xUNpb2q8/Y+7552KlejkRvqvD19nMoUW/uQGGbqNpA6Tufu5FL5BZgw==, - } + resolution: {integrity: sha512-IInvU7fabl34qmi9gY8XOVxhYyMyuH2xUNpb2q8/Y+7552KlejkRvqvD19nMoUW/uQGGbqNpA6Tufu5FL5BZgw==} pascal-case@3.1.2: - resolution: - { - integrity: sha512-uWlGT3YSnK9x3BQJaOdcZwrnV6hPpd8jFH1/ucpiLRPh/2zCVJKS19E4GvYHvaCcACn3foXZ0cLB9Wrx1KGe5g==, - } + resolution: {integrity: sha512-uWlGT3YSnK9x3BQJaOdcZwrnV6hPpd8jFH1/ucpiLRPh/2zCVJKS19E4GvYHvaCcACn3foXZ0cLB9Wrx1KGe5g==} path-browserify@1.0.1: - resolution: - { - integrity: sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g==, - } + resolution: {integrity: sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g==} path-exists@4.0.0: - resolution: - { - integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==, - } - engines: { node: ">=8" } + resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==} + engines: {node: '>=8'} path-key@3.1.1: - resolution: - { - integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==, - } - engines: { node: ">=8" } + resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} + engines: {node: '>=8'} path-parse@1.0.7: - resolution: - { - integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==, - } + resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==} path-posix@1.0.0: - resolution: - { - integrity: sha512-1gJ0WpNIiYcQydgg3Ed8KzvIqTsDpNwq+cjBCssvBtuTWjEqY1AW+i+OepiEMqDCzyro9B2sLAe4RBPajMYFiA==, - } + resolution: {integrity: sha512-1gJ0WpNIiYcQydgg3Ed8KzvIqTsDpNwq+cjBCssvBtuTWjEqY1AW+i+OepiEMqDCzyro9B2sLAe4RBPajMYFiA==} path-scurry@1.11.1: - resolution: - { - integrity: sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==, - } - engines: { node: ">=16 || 14 >=14.18" } + resolution: {integrity: sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==} + engines: {node: '>=16 || 14 >=14.18'} path-type@4.0.0: - resolution: - { - integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==, - } - engines: { node: ">=8" } + resolution: {integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==} + engines: {node: '>=8'} pathe@0.2.0: - resolution: - { - integrity: sha512-sTitTPYnn23esFR3RlqYBWn4c45WGeLcsKzQiUpXJAyfcWkolvlYpV8FLo7JishK946oQwMFUCHXQ9AjGPKExw==, - } + resolution: {integrity: sha512-sTitTPYnn23esFR3RlqYBWn4c45WGeLcsKzQiUpXJAyfcWkolvlYpV8FLo7JishK946oQwMFUCHXQ9AjGPKExw==} pathe@2.0.3: - resolution: - { - integrity: sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==, - } + resolution: {integrity: sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==} pathval@2.0.1: - resolution: - { - integrity: sha512-//nshmD55c46FuFw26xV/xFAaB5HF9Xdap7HJBBnrKdAd6/GxDBaNA1870O79+9ueg61cZLSVc+OaFlfmObYVQ==, - } - engines: { node: ">= 14.16" } + resolution: {integrity: sha512-//nshmD55c46FuFw26xV/xFAaB5HF9Xdap7HJBBnrKdAd6/GxDBaNA1870O79+9ueg61cZLSVc+OaFlfmObYVQ==} + engines: {node: '>= 14.16'} pbkdf2@3.1.5: - resolution: - { - integrity: sha512-Q3CG/cYvCO1ye4QKkuH7EXxs3VC/rI1/trd+qX2+PolbaKG0H+bgcZzrTt96mMyRtejk+JMCiLUn3y29W8qmFQ==, - } - engines: { node: ">= 0.10" } + resolution: {integrity: sha512-Q3CG/cYvCO1ye4QKkuH7EXxs3VC/rI1/trd+qX2+PolbaKG0H+bgcZzrTt96mMyRtejk+JMCiLUn3y29W8qmFQ==} + engines: {node: '>= 0.10'} picocolors@1.1.1: - resolution: - { - integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==, - } + resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==} picomatch@2.3.2: - resolution: - { - integrity: sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA==, - } - engines: { node: ">=8.6" } + resolution: {integrity: sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA==} + engines: {node: '>=8.6'} picomatch@4.0.4: - resolution: - { - integrity: sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==, - } - engines: { node: ">=12" } + resolution: {integrity: sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==} + engines: {node: '>=12'} pkg-dir@5.0.0: - resolution: - { - integrity: sha512-NPE8TDbzl/3YQYY7CSS228s3g2ollTFnc+Qi3tqmqJp9Vg2ovUpixcJEo2HJScN2Ez+kEaal6y70c0ehqJBJeA==, - } - engines: { node: ">=10" } + resolution: {integrity: sha512-NPE8TDbzl/3YQYY7CSS228s3g2ollTFnc+Qi3tqmqJp9Vg2ovUpixcJEo2HJScN2Ez+kEaal6y70c0ehqJBJeA==} + engines: {node: '>=10'} playwright-core@1.59.1: - resolution: - { - integrity: sha512-HBV/RJg81z5BiiZ9yPzIiClYV/QMsDCKUyogwH9p3MCP6IYjUFu/MActgYAvK0oWyV9NlwM3GLBjADyWgydVyg==, - } - engines: { node: ">=18" } + resolution: {integrity: sha512-HBV/RJg81z5BiiZ9yPzIiClYV/QMsDCKUyogwH9p3MCP6IYjUFu/MActgYAvK0oWyV9NlwM3GLBjADyWgydVyg==} + engines: {node: '>=18'} hasBin: true playwright@1.59.1: - resolution: - { - integrity: sha512-C8oWjPR3F81yljW9o5OxcWzfh6avkVwDD2VYdwIGqTkl+OGFISgypqzfu7dOe4QNLL2aqcWBmI3PMtLIK233lw==, - } - engines: { node: ">=18" } + resolution: {integrity: sha512-C8oWjPR3F81yljW9o5OxcWzfh6avkVwDD2VYdwIGqTkl+OGFISgypqzfu7dOe4QNLL2aqcWBmI3PMtLIK233lw==} + engines: {node: '>=18'} hasBin: true pluralize@8.0.0: - resolution: - { - integrity: sha512-Nc3IT5yHzflTfbjgqWcCPpo7DaKy4FnpB0l/zCAW0Tc7jxAiuqSxHasntB3D7887LSrA93kDJ9IXovxJYxyLCA==, - } - engines: { node: ">=4" } + resolution: {integrity: sha512-Nc3IT5yHzflTfbjgqWcCPpo7DaKy4FnpB0l/zCAW0Tc7jxAiuqSxHasntB3D7887LSrA93kDJ9IXovxJYxyLCA==} + engines: {node: '>=4'} pngjs@5.0.0: - resolution: - { - integrity: sha512-40QW5YalBNfQo5yRYmiw7Yz6TKKVr3h6970B2YE+3fQpsWcrbj1PzJgxeJ19DRQjhMbKPIuMY8rFaXc8moolVw==, - } - engines: { node: ">=10.13.0" } + resolution: {integrity: sha512-40QW5YalBNfQo5yRYmiw7Yz6TKKVr3h6970B2YE+3fQpsWcrbj1PzJgxeJ19DRQjhMbKPIuMY8rFaXc8moolVw==} + engines: {node: '>=10.13.0'} possible-typed-array-names@1.1.0: - resolution: - { - integrity: sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg==, - } - engines: { node: ">= 0.4" } + resolution: {integrity: sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg==} + engines: {node: '>= 0.4'} postcss-attribute-case-insensitive@7.0.1: - resolution: - { - integrity: sha512-Uai+SupNSqzlschRyNx3kbCTWgY/2hcwtHEI/ej2LJWc9JJ77qKgGptd8DHwY1mXtZ7Aoh4z4yxfwMBue9eNgw==, - } - engines: { node: ">=18" } + resolution: {integrity: sha512-Uai+SupNSqzlschRyNx3kbCTWgY/2hcwtHEI/ej2LJWc9JJ77qKgGptd8DHwY1mXtZ7Aoh4z4yxfwMBue9eNgw==} + engines: {node: '>=18'} peerDependencies: postcss: ^8.4 postcss-clamp@4.1.0: - resolution: - { - integrity: sha512-ry4b1Llo/9zz+PKC+030KUnPITTJAHeOwjfAyyB60eT0AorGLdzp52s31OsPRHRf8NchkgFoG2y6fCfn1IV1Ow==, - } - engines: { node: ">=7.6.0" } + resolution: {integrity: sha512-ry4b1Llo/9zz+PKC+030KUnPITTJAHeOwjfAyyB60eT0AorGLdzp52s31OsPRHRf8NchkgFoG2y6fCfn1IV1Ow==} + engines: {node: '>=7.6.0'} peerDependencies: postcss: ^8.4.6 postcss-color-functional-notation@7.0.12: - resolution: - { - integrity: sha512-TLCW9fN5kvO/u38/uesdpbx3e8AkTYhMvDZYa9JpmImWuTE99bDQ7GU7hdOADIZsiI9/zuxfAJxny/khknp1Zw==, - } - engines: { node: ">=18" } + resolution: {integrity: sha512-TLCW9fN5kvO/u38/uesdpbx3e8AkTYhMvDZYa9JpmImWuTE99bDQ7GU7hdOADIZsiI9/zuxfAJxny/khknp1Zw==} + engines: {node: '>=18'} peerDependencies: postcss: ^8.4 postcss-color-hex-alpha@10.0.0: - resolution: - { - integrity: sha512-1kervM2cnlgPs2a8Vt/Qbe5cQ++N7rkYo/2rz2BkqJZIHQwaVuJgQH38REHrAi4uM0b1fqxMkWYmese94iMp3w==, - } - engines: { node: ">=18" } + resolution: {integrity: sha512-1kervM2cnlgPs2a8Vt/Qbe5cQ++N7rkYo/2rz2BkqJZIHQwaVuJgQH38REHrAi4uM0b1fqxMkWYmese94iMp3w==} + engines: {node: '>=18'} peerDependencies: postcss: ^8.4 postcss-color-rebeccapurple@10.0.0: - resolution: - { - integrity: sha512-JFta737jSP+hdAIEhk1Vs0q0YF5P8fFcj+09pweS8ktuGuZ8pPlykHsk6mPxZ8awDl4TrcxUqJo9l1IhVr/OjQ==, - } - engines: { node: ">=18" } + resolution: {integrity: sha512-JFta737jSP+hdAIEhk1Vs0q0YF5P8fFcj+09pweS8ktuGuZ8pPlykHsk6mPxZ8awDl4TrcxUqJo9l1IhVr/OjQ==} + engines: {node: '>=18'} peerDependencies: postcss: ^8.4 postcss-custom-media@11.0.6: - resolution: - { - integrity: sha512-C4lD4b7mUIw+RZhtY7qUbf4eADmb7Ey8BFA2px9jUbwg7pjTZDl4KY4bvlUV+/vXQvzQRfiGEVJyAbtOsCMInw==, - } - engines: { node: ">=18" } + resolution: {integrity: sha512-C4lD4b7mUIw+RZhtY7qUbf4eADmb7Ey8BFA2px9jUbwg7pjTZDl4KY4bvlUV+/vXQvzQRfiGEVJyAbtOsCMInw==} + engines: {node: '>=18'} peerDependencies: postcss: ^8.4 postcss-custom-properties@14.0.6: - resolution: - { - integrity: sha512-fTYSp3xuk4BUeVhxCSJdIPhDLpJfNakZKoiTDx7yRGCdlZrSJR7mWKVOBS4sBF+5poPQFMj2YdXx1VHItBGihQ==, - } - engines: { node: ">=18" } + resolution: {integrity: sha512-fTYSp3xuk4BUeVhxCSJdIPhDLpJfNakZKoiTDx7yRGCdlZrSJR7mWKVOBS4sBF+5poPQFMj2YdXx1VHItBGihQ==} + engines: {node: '>=18'} peerDependencies: postcss: ^8.4 postcss-custom-selectors@8.0.5: - resolution: - { - integrity: sha512-9PGmckHQswiB2usSO6XMSswO2yFWVoCAuih1yl9FVcwkscLjRKjwsjM3t+NIWpSU2Jx3eOiK2+t4vVTQaoCHHg==, - } - engines: { node: ">=18" } + resolution: {integrity: sha512-9PGmckHQswiB2usSO6XMSswO2yFWVoCAuih1yl9FVcwkscLjRKjwsjM3t+NIWpSU2Jx3eOiK2+t4vVTQaoCHHg==} + engines: {node: '>=18'} peerDependencies: postcss: ^8.4 postcss-dir-pseudo-class@9.0.1: - resolution: - { - integrity: sha512-tRBEK0MHYvcMUrAuYMEOa0zg9APqirBcgzi6P21OhxtJyJADo/SWBwY1CAwEohQ/6HDaa9jCjLRG7K3PVQYHEA==, - } - engines: { node: ">=18" } + resolution: {integrity: sha512-tRBEK0MHYvcMUrAuYMEOa0zg9APqirBcgzi6P21OhxtJyJADo/SWBwY1CAwEohQ/6HDaa9jCjLRG7K3PVQYHEA==} + engines: {node: '>=18'} peerDependencies: postcss: ^8.4 postcss-double-position-gradients@6.0.4: - resolution: - { - integrity: sha512-m6IKmxo7FxSP5nF2l63QbCC3r+bWpFUWmZXZf096WxG0m7Vl1Q1+ruFOhpdDRmKrRS+S3Jtk+TVk/7z0+BVK6g==, - } - engines: { node: ">=18" } + resolution: {integrity: sha512-m6IKmxo7FxSP5nF2l63QbCC3r+bWpFUWmZXZf096WxG0m7Vl1Q1+ruFOhpdDRmKrRS+S3Jtk+TVk/7z0+BVK6g==} + engines: {node: '>=18'} peerDependencies: postcss: ^8.4 postcss-focus-visible@10.0.1: - resolution: - { - integrity: sha512-U58wyjS/I1GZgjRok33aE8juW9qQgQUNwTSdxQGuShHzwuYdcklnvK/+qOWX1Q9kr7ysbraQ6ht6r+udansalA==, - } - engines: { node: ">=18" } + resolution: {integrity: sha512-U58wyjS/I1GZgjRok33aE8juW9qQgQUNwTSdxQGuShHzwuYdcklnvK/+qOWX1Q9kr7ysbraQ6ht6r+udansalA==} + engines: {node: '>=18'} peerDependencies: postcss: ^8.4 postcss-focus-within@9.0.1: - resolution: - { - integrity: sha512-fzNUyS1yOYa7mOjpci/bR+u+ESvdar6hk8XNK/TRR0fiGTp2QT5N+ducP0n3rfH/m9I7H/EQU6lsa2BrgxkEjw==, - } - engines: { node: ">=18" } + resolution: {integrity: sha512-fzNUyS1yOYa7mOjpci/bR+u+ESvdar6hk8XNK/TRR0fiGTp2QT5N+ducP0n3rfH/m9I7H/EQU6lsa2BrgxkEjw==} + engines: {node: '>=18'} peerDependencies: postcss: ^8.4 postcss-font-variant@5.0.0: - resolution: - { - integrity: sha512-1fmkBaCALD72CK2a9i468mA/+tr9/1cBxRRMXOUaZqO43oWPR5imcyPjXwuv7PXbCid4ndlP5zWhidQVVa3hmA==, - } + resolution: {integrity: sha512-1fmkBaCALD72CK2a9i468mA/+tr9/1cBxRRMXOUaZqO43oWPR5imcyPjXwuv7PXbCid4ndlP5zWhidQVVa3hmA==} peerDependencies: postcss: ^8.1.0 postcss-gap-properties@6.0.0: - resolution: - { - integrity: sha512-Om0WPjEwiM9Ru+VhfEDPZJAKWUd0mV1HmNXqp2C29z80aQ2uP9UVhLc7e3aYMIor/S5cVhoPgYQ7RtfeZpYTRw==, - } - engines: { node: ">=18" } + resolution: {integrity: sha512-Om0WPjEwiM9Ru+VhfEDPZJAKWUd0mV1HmNXqp2C29z80aQ2uP9UVhLc7e3aYMIor/S5cVhoPgYQ7RtfeZpYTRw==} + engines: {node: '>=18'} peerDependencies: postcss: ^8.4 postcss-image-set-function@7.0.0: - resolution: - { - integrity: sha512-QL7W7QNlZuzOwBTeXEmbVckNt1FSmhQtbMRvGGqqU4Nf4xk6KUEQhAoWuMzwbSv5jxiRiSZ5Tv7eiDB9U87znA==, - } - engines: { node: ">=18" } + resolution: {integrity: sha512-QL7W7QNlZuzOwBTeXEmbVckNt1FSmhQtbMRvGGqqU4Nf4xk6KUEQhAoWuMzwbSv5jxiRiSZ5Tv7eiDB9U87znA==} + engines: {node: '>=18'} peerDependencies: postcss: ^8.4 postcss-lab-function@7.0.12: - resolution: - { - integrity: sha512-tUcyRk1ZTPec3OuKFsqtRzW2Go5lehW29XA21lZ65XmzQkz43VY2tyWEC202F7W3mILOjw0voOiuxRGTsN+J9w==, - } - engines: { node: ">=18" } + resolution: {integrity: sha512-tUcyRk1ZTPec3OuKFsqtRzW2Go5lehW29XA21lZ65XmzQkz43VY2tyWEC202F7W3mILOjw0voOiuxRGTsN+J9w==} + engines: {node: '>=18'} peerDependencies: postcss: ^8.4 postcss-logical@8.1.0: - resolution: - { - integrity: sha512-pL1hXFQ2fEXNKiNiAgtfA005T9FBxky5zkX6s4GZM2D8RkVgRqz3f4g1JUoq925zXv495qk8UNldDwh8uGEDoA==, - } - engines: { node: ">=18" } + resolution: {integrity: sha512-pL1hXFQ2fEXNKiNiAgtfA005T9FBxky5zkX6s4GZM2D8RkVgRqz3f4g1JUoq925zXv495qk8UNldDwh8uGEDoA==} + engines: {node: '>=18'} peerDependencies: postcss: ^8.4 postcss-nesting@13.0.2: - resolution: - { - integrity: sha512-1YCI290TX+VP0U/K/aFxzHzQWHWURL+CtHMSbex1lCdpXD1SoR2sYuxDu5aNI9lPoXpKTCggFZiDJbwylU0LEQ==, - } - engines: { node: ">=18" } + resolution: {integrity: sha512-1YCI290TX+VP0U/K/aFxzHzQWHWURL+CtHMSbex1lCdpXD1SoR2sYuxDu5aNI9lPoXpKTCggFZiDJbwylU0LEQ==} + engines: {node: '>=18'} peerDependencies: postcss: ^8.4 postcss-opacity-percentage@3.0.0: - resolution: - { - integrity: sha512-K6HGVzyxUxd/VgZdX04DCtdwWJ4NGLG212US4/LA1TLAbHgmAsTWVR86o+gGIbFtnTkfOpb9sCRBx8K7HO66qQ==, - } - engines: { node: ">=18" } + resolution: {integrity: sha512-K6HGVzyxUxd/VgZdX04DCtdwWJ4NGLG212US4/LA1TLAbHgmAsTWVR86o+gGIbFtnTkfOpb9sCRBx8K7HO66qQ==} + engines: {node: '>=18'} peerDependencies: postcss: ^8.4 postcss-overflow-shorthand@6.0.0: - resolution: - { - integrity: sha512-BdDl/AbVkDjoTofzDQnwDdm/Ym6oS9KgmO7Gr+LHYjNWJ6ExORe4+3pcLQsLA9gIROMkiGVjjwZNoL/mpXHd5Q==, - } - engines: { node: ">=18" } + resolution: {integrity: sha512-BdDl/AbVkDjoTofzDQnwDdm/Ym6oS9KgmO7Gr+LHYjNWJ6ExORe4+3pcLQsLA9gIROMkiGVjjwZNoL/mpXHd5Q==} + engines: {node: '>=18'} peerDependencies: postcss: ^8.4 postcss-page-break@3.0.4: - resolution: - { - integrity: sha512-1JGu8oCjVXLa9q9rFTo4MbeeA5FMe00/9C7lN4va606Rdb+HkxXtXsmEDrIraQ11fGz/WvKWa8gMuCKkrXpTsQ==, - } + resolution: {integrity: sha512-1JGu8oCjVXLa9q9rFTo4MbeeA5FMe00/9C7lN4va606Rdb+HkxXtXsmEDrIraQ11fGz/WvKWa8gMuCKkrXpTsQ==} peerDependencies: postcss: ^8 postcss-place@10.0.0: - resolution: - { - integrity: sha512-5EBrMzat2pPAxQNWYavwAfoKfYcTADJ8AXGVPcUZ2UkNloUTWzJQExgrzrDkh3EKzmAx1evfTAzF9I8NGcc+qw==, - } - engines: { node: ">=18" } + resolution: {integrity: sha512-5EBrMzat2pPAxQNWYavwAfoKfYcTADJ8AXGVPcUZ2UkNloUTWzJQExgrzrDkh3EKzmAx1evfTAzF9I8NGcc+qw==} + engines: {node: '>=18'} peerDependencies: postcss: ^8.4 postcss-preset-env@10.6.1: - resolution: - { - integrity: sha512-yrk74d9EvY+W7+lO9Aj1QmjWY9q5NsKjK2V9drkOPZB/X6KZ0B3igKsHUYakb7oYVhnioWypQX3xGuePf89f3g==, - } - engines: { node: ">=18" } + resolution: {integrity: sha512-yrk74d9EvY+W7+lO9Aj1QmjWY9q5NsKjK2V9drkOPZB/X6KZ0B3igKsHUYakb7oYVhnioWypQX3xGuePf89f3g==} + engines: {node: '>=18'} peerDependencies: postcss: ^8.4 postcss-pseudo-class-any-link@10.0.1: - resolution: - { - integrity: sha512-3el9rXlBOqTFaMFkWDOkHUTQekFIYnaQY55Rsp8As8QQkpiSgIYEcF/6Ond93oHiDsGb4kad8zjt+NPlOC1H0Q==, - } - engines: { node: ">=18" } + resolution: {integrity: sha512-3el9rXlBOqTFaMFkWDOkHUTQekFIYnaQY55Rsp8As8QQkpiSgIYEcF/6Ond93oHiDsGb4kad8zjt+NPlOC1H0Q==} + engines: {node: '>=18'} peerDependencies: postcss: ^8.4 postcss-replace-overflow-wrap@4.0.0: - resolution: - { - integrity: sha512-KmF7SBPphT4gPPcKZc7aDkweHiKEEO8cla/GjcBK+ckKxiZslIu3C4GCRW3DNfL0o7yW7kMQu9xlZ1kXRXLXtw==, - } + resolution: {integrity: sha512-KmF7SBPphT4gPPcKZc7aDkweHiKEEO8cla/GjcBK+ckKxiZslIu3C4GCRW3DNfL0o7yW7kMQu9xlZ1kXRXLXtw==} peerDependencies: postcss: ^8.0.3 postcss-selector-not@8.0.1: - resolution: - { - integrity: sha512-kmVy/5PYVb2UOhy0+LqUYAhKj7DUGDpSWa5LZqlkWJaaAV+dxxsOG3+St0yNLu6vsKD7Dmqx+nWQt0iil89+WA==, - } - engines: { node: ">=18" } + resolution: {integrity: sha512-kmVy/5PYVb2UOhy0+LqUYAhKj7DUGDpSWa5LZqlkWJaaAV+dxxsOG3+St0yNLu6vsKD7Dmqx+nWQt0iil89+WA==} + engines: {node: '>=18'} peerDependencies: postcss: ^8.4 postcss-selector-parser@7.1.1: - resolution: - { - integrity: sha512-orRsuYpJVw8LdAwqqLykBj9ecS5/cRHlI5+nvTo8LcCKmzDmqVORXtOIYEEQuL9D4BxtA1lm5isAqzQZCoQ6Eg==, - } - engines: { node: ">=4" } + resolution: {integrity: sha512-orRsuYpJVw8LdAwqqLykBj9ecS5/cRHlI5+nvTo8LcCKmzDmqVORXtOIYEEQuL9D4BxtA1lm5isAqzQZCoQ6Eg==} + engines: {node: '>=4'} postcss-value-parser@4.2.0: - resolution: - { - integrity: sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==, - } + resolution: {integrity: sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==} postcss@8.5.10: - resolution: - { - integrity: sha512-pMMHxBOZKFU6HgAZ4eyGnwXF/EvPGGqUr0MnZ5+99485wwW41kW91A4LOGxSHhgugZmSChL5AlElNdwlNgcnLQ==, - } - engines: { node: ^10 || ^12 || >=14 } + resolution: {integrity: sha512-pMMHxBOZKFU6HgAZ4eyGnwXF/EvPGGqUr0MnZ5+99485wwW41kW91A4LOGxSHhgugZmSChL5AlElNdwlNgcnLQ==} + engines: {node: ^10 || ^12 || >=14} posthog-js@1.160.3: - resolution: - { - integrity: sha512-mGvxOIlWPtdPx8EI0MQ81wNKlnH2K0n4RqwQOl044b34BCKiFVzZ7Hc7geMuZNaRAvCi5/5zyGeWHcAYZQxiMQ==, - } + resolution: {integrity: sha512-mGvxOIlWPtdPx8EI0MQ81wNKlnH2K0n4RqwQOl044b34BCKiFVzZ7Hc7geMuZNaRAvCi5/5zyGeWHcAYZQxiMQ==} preact@10.29.1: - resolution: - { - integrity: sha512-gQCLc/vWroE8lIpleXtdJhTFDogTdZG9AjMUpVkDf2iTCNwYNWA+u16dL41TqUDJO4gm2IgrcMv3uTpjd4Pwmg==, - } + resolution: {integrity: sha512-gQCLc/vWroE8lIpleXtdJhTFDogTdZG9AjMUpVkDf2iTCNwYNWA+u16dL41TqUDJO4gm2IgrcMv3uTpjd4Pwmg==} prelude-ls@1.2.1: - resolution: - { - integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==, - } - engines: { node: ">= 0.8.0" } + resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==} + engines: {node: '>= 0.8.0'} prettier@3.8.3: - resolution: - { - integrity: sha512-7igPTM53cGHMW8xWuVTydi2KO233VFiTNyF5hLJqpilHfmn8C8gPf+PS7dUT64YcXFbiMGZxS9pCSxL/Dxm/Jw==, - } - engines: { node: ">=14" } + resolution: {integrity: sha512-7igPTM53cGHMW8xWuVTydi2KO233VFiTNyF5hLJqpilHfmn8C8gPf+PS7dUT64YcXFbiMGZxS9pCSxL/Dxm/Jw==} + engines: {node: '>=14'} hasBin: true pretty-format@27.5.1: - resolution: - { - integrity: sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==, - } - engines: { node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0 } + resolution: {integrity: sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==} + engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} process-nextick-args@2.0.1: - resolution: - { - integrity: sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==, - } + resolution: {integrity: sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==} process@0.11.10: - resolution: - { - integrity: sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==, - } - engines: { node: ">= 0.6.0" } + resolution: {integrity: sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==} + engines: {node: '>= 0.6.0'} progress@2.0.3: - resolution: - { - integrity: sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==, - } - engines: { node: ">=0.4.0" } + resolution: {integrity: sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==} + engines: {node: '>=0.4.0'} promise-map-series@0.3.0: - resolution: - { - integrity: sha512-3npG2NGhTc8BWBolLLf8l/92OxMGaRLbqvIh9wjCHhDXNvk4zsxaTaCpiCunW09qWPrN2zeNSNwRLVBrQQtutA==, - } - engines: { node: 10.* || >= 12.* } + resolution: {integrity: sha512-3npG2NGhTc8BWBolLLf8l/92OxMGaRLbqvIh9wjCHhDXNvk4zsxaTaCpiCunW09qWPrN2zeNSNwRLVBrQQtutA==} + engines: {node: 10.* || >= 12.*} prompts@2.4.2: - resolution: - { - integrity: sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==, - } - engines: { node: ">= 6" } + resolution: {integrity: sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==} + engines: {node: '>= 6'} prop-types@15.8.1: - resolution: - { - integrity: sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==, - } + resolution: {integrity: sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==} proxy-from-env@1.1.0: - resolution: - { - integrity: sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==, - } + resolution: {integrity: sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==} public-encrypt@4.0.3: - resolution: - { - integrity: sha512-zVpa8oKZSz5bTMTFClc1fQOnyyEzpl5ozpi1B5YcvBrdohMjH2rfsBtyXcuNuwjsDIXmBYlF2N5FlJYhR29t8Q==, - } + resolution: {integrity: sha512-zVpa8oKZSz5bTMTFClc1fQOnyyEzpl5ozpi1B5YcvBrdohMjH2rfsBtyXcuNuwjsDIXmBYlF2N5FlJYhR29t8Q==} punycode@1.4.1: - resolution: - { - integrity: sha512-jmYNElW7yvO7TV33CjSmvSiE2yco3bV2czu/OzDKdMNVZQWfxCblURLhf+47syQRBntjfLdd/H0egrzIG+oaFQ==, - } + resolution: {integrity: sha512-jmYNElW7yvO7TV33CjSmvSiE2yco3bV2czu/OzDKdMNVZQWfxCblURLhf+47syQRBntjfLdd/H0egrzIG+oaFQ==} punycode@2.3.1: - resolution: - { - integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==, - } - engines: { node: ">=6" } + resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==} + engines: {node: '>=6'} qrcode@1.5.4: - resolution: - { - integrity: sha512-1ca71Zgiu6ORjHqFBDpnSMTR2ReToX4l1Au1VFLyVeBTFavzQnv5JxMFr3ukHVKpSrSA2MCk0lNJSykjUfz7Zg==, - } - engines: { node: ">=10.13.0" } + resolution: {integrity: sha512-1ca71Zgiu6ORjHqFBDpnSMTR2ReToX4l1Au1VFLyVeBTFavzQnv5JxMFr3ukHVKpSrSA2MCk0lNJSykjUfz7Zg==} + engines: {node: '>=10.13.0'} hasBin: true qs@6.15.1: - resolution: - { - integrity: sha512-6YHEFRL9mfgcAvql/XhwTvf5jKcOiiupt2FiJxHkiX1z4j7WL8J/jRHYLluORvc1XxB5rV20KoeK00gVJamspg==, - } - engines: { node: ">=0.6" } + resolution: {integrity: sha512-6YHEFRL9mfgcAvql/XhwTvf5jKcOiiupt2FiJxHkiX1z4j7WL8J/jRHYLluORvc1XxB5rV20KoeK00gVJamspg==} + engines: {node: '>=0.6'} querystring-es3@0.2.1: - resolution: - { - integrity: sha512-773xhDQnZBMFobEiztv8LIl70ch5MSF/jUQVlhwFyBILqq96anmoctVIYz+ZRp0qbCKATTn6ev02M3r7Ga5vqA==, - } - engines: { node: ">=0.4.x" } + resolution: {integrity: sha512-773xhDQnZBMFobEiztv8LIl70ch5MSF/jUQVlhwFyBILqq96anmoctVIYz+ZRp0qbCKATTn6ev02M3r7Ga5vqA==} + engines: {node: '>=0.4.x'} queue-microtask@1.2.3: - resolution: - { - integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==, - } + resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} quick-temp@0.1.9: - resolution: - { - integrity: sha512-yI0h7tIhKVObn03kD+Ln9JFi4OljD28lfaOsTdfpTR0xzrhGOod+q66CjGafUqYX2juUfT9oHIGrTBBo22mkRA==, - } + resolution: {integrity: sha512-yI0h7tIhKVObn03kD+Ln9JFi4OljD28lfaOsTdfpTR0xzrhGOod+q66CjGafUqYX2juUfT9oHIGrTBBo22mkRA==} randombytes@2.1.0: - resolution: - { - integrity: sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==, - } + resolution: {integrity: sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==} randomfill@1.0.4: - resolution: - { - integrity: sha512-87lcbR8+MhcWcUiQ+9e+Rwx8MyR2P7qnt15ynUlbm3TU/fjbgz4GsvfSUDTemtCCtVCqb4ZcEFlyPNTh9bBTLw==, - } + resolution: {integrity: sha512-87lcbR8+MhcWcUiQ+9e+Rwx8MyR2P7qnt15ynUlbm3TU/fjbgz4GsvfSUDTemtCCtVCqb4ZcEFlyPNTh9bBTLw==} react-docgen-typescript@2.4.0: - resolution: - { - integrity: sha512-ZtAp5XTO5HRzQctjPU0ybY0RRCQO19X/8fxn3w7y2VVTUbGHDKULPTL4ky3vB05euSgG5NpALhEhDPvQ56wvXg==, - } + resolution: {integrity: sha512-ZtAp5XTO5HRzQctjPU0ybY0RRCQO19X/8fxn3w7y2VVTUbGHDKULPTL4ky3vB05euSgG5NpALhEhDPvQ56wvXg==} peerDependencies: - typescript: ">= 4.3.x" + typescript: '>= 4.3.x' react-docgen@8.0.3: - resolution: - { - integrity: sha512-aEZ9qP+/M+58x2qgfSFEWH1BxLyHe5+qkLNJOZQb5iGS017jpbRnoKhNRrXPeA6RfBrZO5wZrT9DMC1UqE1f1w==, - } - engines: { node: ^20.9.0 || >=22 } + resolution: {integrity: sha512-aEZ9qP+/M+58x2qgfSFEWH1BxLyHe5+qkLNJOZQb5iGS017jpbRnoKhNRrXPeA6RfBrZO5wZrT9DMC1UqE1f1w==} + engines: {node: ^20.9.0 || >=22} react-dom@19.2.5: - resolution: - { - integrity: sha512-J5bAZz+DXMMwW/wV3xzKke59Af6CHY7G4uYLN1OvBcKEsWOs4pQExj86BBKamxl/Ik5bx9whOrvBlSDfWzgSag==, - } + resolution: {integrity: sha512-J5bAZz+DXMMwW/wV3xzKke59Af6CHY7G4uYLN1OvBcKEsWOs4pQExj86BBKamxl/Ik5bx9whOrvBlSDfWzgSag==} peerDependencies: react: ^19.2.5 react-i18next@16.6.6: - resolution: - { - integrity: sha512-ZgL2HUoW34UKUkOV7uSQFE1CDnRPD+tCR3ywSuWH7u2iapnz86U8Bi3Vrs620qNDzCf1F47NxglCEkchCTDOHw==, - } + resolution: {integrity: sha512-ZgL2HUoW34UKUkOV7uSQFE1CDnRPD+tCR3ywSuWH7u2iapnz86U8Bi3Vrs620qNDzCf1F47NxglCEkchCTDOHw==} peerDependencies: - i18next: ">= 25.10.9" - react: ">= 16.8.0" - react-dom: "*" - react-native: "*" + i18next: '>= 25.10.9' + react: '>= 16.8.0' + react-dom: '*' + react-native: '*' typescript: ^5 || ^6 peerDependenciesMeta: react-dom: @@ -8681,704 +5583,412 @@ packages: optional: true react-is@16.13.1: - resolution: - { - integrity: sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==, - } + resolution: {integrity: sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==} react-is@17.0.2: - resolution: - { - integrity: sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==, - } + resolution: {integrity: sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==} react-refresh@0.17.0: - resolution: - { - integrity: sha512-z6F7K9bV85EfseRCp2bzrpyQ0Gkw1uLoCel9XBVWPg/TjRj94SkJzUTGfOa4bs7iJvBWtQG0Wq7wnI0syw3EBQ==, - } - engines: { node: ">=0.10.0" } + resolution: {integrity: sha512-z6F7K9bV85EfseRCp2bzrpyQ0Gkw1uLoCel9XBVWPg/TjRj94SkJzUTGfOa4bs7iJvBWtQG0Wq7wnI0syw3EBQ==} + engines: {node: '>=0.10.0'} react-remove-scroll-bar@2.3.8: - resolution: - { - integrity: sha512-9r+yi9+mgU33AKcj6IbT9oRCO78WriSj6t/cF8DWBZJ9aOGPOTEDvdUDz1FwKim7QXWwmHqtdHnRJfhAxEG46Q==, - } - engines: { node: ">=10" } + resolution: {integrity: sha512-9r+yi9+mgU33AKcj6IbT9oRCO78WriSj6t/cF8DWBZJ9aOGPOTEDvdUDz1FwKim7QXWwmHqtdHnRJfhAxEG46Q==} + engines: {node: '>=10'} peerDependencies: - "@types/react": "*" + '@types/react': '*' react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 peerDependenciesMeta: - "@types/react": + '@types/react': optional: true react-remove-scroll@2.7.2: - resolution: - { - integrity: sha512-Iqb9NjCCTt6Hf+vOdNIZGdTiH1QSqr27H/Ek9sv/a97gfueI/5h1s3yRi1nngzMUaOOToin5dI1dXKdXiF+u0Q==, - } - engines: { node: ">=10" } + resolution: {integrity: sha512-Iqb9NjCCTt6Hf+vOdNIZGdTiH1QSqr27H/Ek9sv/a97gfueI/5h1s3yRi1nngzMUaOOToin5dI1dXKdXiF+u0Q==} + engines: {node: '>=10'} peerDependencies: - "@types/react": "*" + '@types/react': '*' react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc peerDependenciesMeta: - "@types/react": + '@types/react': optional: true react-router-dom@7.14.1: - resolution: - { - integrity: sha512-ZkrQuwwhGibjQLqH1eCdyiZyLWglPxzxdl5tgwgKEyCSGC76vmAjleGocRe3J/MLfzMUIKwaFJWpFVJhK3d2xA==, - } - engines: { node: ">=20.0.0" } + resolution: {integrity: sha512-ZkrQuwwhGibjQLqH1eCdyiZyLWglPxzxdl5tgwgKEyCSGC76vmAjleGocRe3J/MLfzMUIKwaFJWpFVJhK3d2xA==} + engines: {node: '>=20.0.0'} peerDependencies: - react: ">=18" - react-dom: ">=18" + react: '>=18' + react-dom: '>=18' react-router@7.14.1: - resolution: - { - integrity: sha512-5BCvFskyAAVumqhEKh/iPhLOIkfxcEUz8WqFIARCkMg8hZZzDYX9CtwxXA0e+qT8zAxmMC0x3Ckb9iMONwc5jg==, - } - engines: { node: ">=20.0.0" } + resolution: {integrity: sha512-5BCvFskyAAVumqhEKh/iPhLOIkfxcEUz8WqFIARCkMg8hZZzDYX9CtwxXA0e+qT8zAxmMC0x3Ckb9iMONwc5jg==} + engines: {node: '>=20.0.0'} peerDependencies: - react: ">=18" - react-dom: ">=18" + react: '>=18' + react-dom: '>=18' peerDependenciesMeta: react-dom: optional: true react-style-singleton@2.2.3: - resolution: - { - integrity: sha512-b6jSvxvVnyptAiLjbkWLE/lOnR4lfTtDAl+eUC7RZy+QQWc6wRzIV2CE6xBuMmDxc2qIihtDCZD5NPOFl7fRBQ==, - } - engines: { node: ">=10" } + resolution: {integrity: sha512-b6jSvxvVnyptAiLjbkWLE/lOnR4lfTtDAl+eUC7RZy+QQWc6wRzIV2CE6xBuMmDxc2qIihtDCZD5NPOFl7fRBQ==} + engines: {node: '>=10'} peerDependencies: - "@types/react": "*" + '@types/react': '*' react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc peerDependenciesMeta: - "@types/react": + '@types/react': optional: true react-use-measure@2.1.7: - resolution: - { - integrity: sha512-KrvcAo13I/60HpwGO5jpW7E9DfusKyLPLvuHlUyP5zqnmAPhNc6qTRjUQrdTADl0lpPpDVU2/Gg51UlOGHXbdg==, - } + resolution: {integrity: sha512-KrvcAo13I/60HpwGO5jpW7E9DfusKyLPLvuHlUyP5zqnmAPhNc6qTRjUQrdTADl0lpPpDVU2/Gg51UlOGHXbdg==} peerDependencies: - react: ">=16.13" - react-dom: ">=16.13" + react: '>=16.13' + react-dom: '>=16.13' peerDependenciesMeta: react-dom: optional: true react@19.2.5: - resolution: - { - integrity: sha512-llUJLzz1zTUBrskt2pwZgLq59AemifIftw4aB7JxOqf1HY2FDaGDxgwpAPVzHU1kdWabH7FauP4i1oEeer2WCA==, - } - engines: { node: ">=0.10.0" } + resolution: {integrity: sha512-llUJLzz1zTUBrskt2pwZgLq59AemifIftw4aB7JxOqf1HY2FDaGDxgwpAPVzHU1kdWabH7FauP4i1oEeer2WCA==} + engines: {node: '>=0.10.0'} read-pkg-up@7.0.1: - resolution: - { - integrity: sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg==, - } - engines: { node: ">=8" } + resolution: {integrity: sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg==} + engines: {node: '>=8'} read-pkg@5.2.0: - resolution: - { - integrity: sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg==, - } - engines: { node: ">=8" } + resolution: {integrity: sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg==} + engines: {node: '>=8'} readable-stream@2.3.8: - resolution: - { - integrity: sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==, - } + resolution: {integrity: sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==} readable-stream@3.6.2: - resolution: - { - integrity: sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==, - } - engines: { node: ">= 6" } + resolution: {integrity: sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==} + engines: {node: '>= 6'} readdirp@3.6.0: - resolution: - { - integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==, - } - engines: { node: ">=8.10.0" } + resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==} + engines: {node: '>=8.10.0'} readdirp@4.1.2: - resolution: - { - integrity: sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==, - } - engines: { node: ">= 14.18.0" } + resolution: {integrity: sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==} + engines: {node: '>= 14.18.0'} recast@0.23.11: - resolution: - { - integrity: sha512-YTUo+Flmw4ZXiWfQKGcwwc11KnoRAYgzAE2E7mXKCjSviTKShtxBsN6YUUBB2gtaBzKzeKunxhUwNHQuRryhWA==, - } - engines: { node: ">= 4" } + resolution: {integrity: sha512-YTUo+Flmw4ZXiWfQKGcwwc11KnoRAYgzAE2E7mXKCjSviTKShtxBsN6YUUBB2gtaBzKzeKunxhUwNHQuRryhWA==} + engines: {node: '>= 4'} redent@3.0.0: - resolution: - { - integrity: sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg==, - } - engines: { node: ">=8" } + resolution: {integrity: sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg==} + engines: {node: '>=8'} reflect.getprototypeof@1.0.10: - resolution: - { - integrity: sha512-00o4I+DVrefhv+nX0ulyi3biSHCPDe+yLv5o/p6d/UVlirijB8E16FtfwSAi4g3tcqrQ4lRAqQSoFEZJehYEcw==, - } - engines: { node: ">= 0.4" } + resolution: {integrity: sha512-00o4I+DVrefhv+nX0ulyi3biSHCPDe+yLv5o/p6d/UVlirijB8E16FtfwSAi4g3tcqrQ4lRAqQSoFEZJehYEcw==} + engines: {node: '>= 0.4'} regenerate-unicode-properties@10.2.2: - resolution: - { - integrity: sha512-m03P+zhBeQd1RGnYxrGyDAPpWX/epKirLrp8e3qevZdVkKtnCrjjWczIbYc8+xd6vcTStVlqfycTx1KR4LOr0g==, - } - engines: { node: ">=4" } + resolution: {integrity: sha512-m03P+zhBeQd1RGnYxrGyDAPpWX/epKirLrp8e3qevZdVkKtnCrjjWczIbYc8+xd6vcTStVlqfycTx1KR4LOr0g==} + engines: {node: '>=4'} regenerate@1.4.2: - resolution: - { - integrity: sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A==, - } + resolution: {integrity: sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A==} regexp-tree@0.1.27: - resolution: - { - integrity: sha512-iETxpjK6YoRWJG5o6hXLwvjYAoW+FEZn9os0PD/b6AP6xQwsa/Y7lCVgIixBbUPMfhu+i2LtdeAqVTgGlQarfA==, - } + resolution: {integrity: sha512-iETxpjK6YoRWJG5o6hXLwvjYAoW+FEZn9os0PD/b6AP6xQwsa/Y7lCVgIixBbUPMfhu+i2LtdeAqVTgGlQarfA==} hasBin: true regexp.prototype.flags@1.5.4: - resolution: - { - integrity: sha512-dYqgNSZbDwkaJ2ceRd9ojCGjBq+mOm9LmtXnAnEGyHhN/5R7iDW2TRw3h+o/jCFxus3P2LfWIIiwowAjANm7IA==, - } - engines: { node: ">= 0.4" } + resolution: {integrity: sha512-dYqgNSZbDwkaJ2ceRd9ojCGjBq+mOm9LmtXnAnEGyHhN/5R7iDW2TRw3h+o/jCFxus3P2LfWIIiwowAjANm7IA==} + engines: {node: '>= 0.4'} regexparam@3.0.0: - resolution: - { - integrity: sha512-RSYAtP31mvYLkAHrOlh25pCNQ5hWnT106VukGaaFfuJrZFkGRX5GhUAdPqpSDXxOhA2c4akmRuplv1mRqnBn6Q==, - } - engines: { node: ">=8" } + resolution: {integrity: sha512-RSYAtP31mvYLkAHrOlh25pCNQ5hWnT106VukGaaFfuJrZFkGRX5GhUAdPqpSDXxOhA2c4akmRuplv1mRqnBn6Q==} + engines: {node: '>=8'} regexpu-core@6.4.0: - resolution: - { - integrity: sha512-0ghuzq67LI9bLXpOX/ISfve/Mq33a4aFRzoQYhnnok1JOFpmE/A2TBGkNVenOGEeSBCjIiWcc6MVOG5HEQv0sA==, - } - engines: { node: ">=4" } + resolution: {integrity: sha512-0ghuzq67LI9bLXpOX/ISfve/Mq33a4aFRzoQYhnnok1JOFpmE/A2TBGkNVenOGEeSBCjIiWcc6MVOG5HEQv0sA==} + engines: {node: '>=4'} regjsgen@0.8.0: - resolution: - { - integrity: sha512-RvwtGe3d7LvWiDQXeQw8p5asZUmfU1G/l6WbUXeHta7Y2PEIvBTwH6E2EfmYUK8pxcxEdEmaomqyp0vZZ7C+3Q==, - } + resolution: {integrity: sha512-RvwtGe3d7LvWiDQXeQw8p5asZUmfU1G/l6WbUXeHta7Y2PEIvBTwH6E2EfmYUK8pxcxEdEmaomqyp0vZZ7C+3Q==} regjsparser@0.10.0: - resolution: - { - integrity: sha512-qx+xQGZVsy55CH0a1hiVwHmqjLryfh7wQyF5HO07XJ9f7dQMY/gPQHhlyDkIzJKC+x2fUCpCcUODUUUFrm7SHA==, - } + resolution: {integrity: sha512-qx+xQGZVsy55CH0a1hiVwHmqjLryfh7wQyF5HO07XJ9f7dQMY/gPQHhlyDkIzJKC+x2fUCpCcUODUUUFrm7SHA==} hasBin: true regjsparser@0.13.1: - resolution: - { - integrity: sha512-dLsljMd9sqwRkby8zhO1gSg3PnJIBFid8f4CQj/sXx+7cKx+E7u0PKhZ+U4wmhx7EfmtvnA318oVaIkAB1lRJw==, - } + resolution: {integrity: sha512-dLsljMd9sqwRkby8zhO1gSg3PnJIBFid8f4CQj/sXx+7cKx+E7u0PKhZ+U4wmhx7EfmtvnA318oVaIkAB1lRJw==} hasBin: true relateurl@0.2.7: - resolution: - { - integrity: sha512-G08Dxvm4iDN3MLM0EsP62EDV9IuhXPR6blNz6Utcp7zyV3tr4HVNINt6MpaRWbxoOHT3Q7YN2P+jaHX8vUbgog==, - } - engines: { node: ">= 0.10" } + resolution: {integrity: sha512-G08Dxvm4iDN3MLM0EsP62EDV9IuhXPR6blNz6Utcp7zyV3tr4HVNINt6MpaRWbxoOHT3Q7YN2P+jaHX8vUbgog==} + engines: {node: '>= 0.10'} remove-trailing-separator@1.1.0: - resolution: - { - integrity: sha512-/hS+Y0u3aOfIETiaiirUFwDBDzmXPvO+jAfKTitUngIPzdKc6Z0LoFjM/CK5PL4C+eKwHohlHAb6H0VFfmmUsw==, - } + resolution: {integrity: sha512-/hS+Y0u3aOfIETiaiirUFwDBDzmXPvO+jAfKTitUngIPzdKc6Z0LoFjM/CK5PL4C+eKwHohlHAb6H0VFfmmUsw==} replace-ext@2.0.0: - resolution: - { - integrity: sha512-UszKE5KVK6JvyD92nzMn9cDapSk6w/CaFZ96CnmDMUqH9oowfxF/ZjRITD25H4DnOQClLA4/j7jLGXXLVKxAug==, - } - engines: { node: ">= 10" } + resolution: {integrity: sha512-UszKE5KVK6JvyD92nzMn9cDapSk6w/CaFZ96CnmDMUqH9oowfxF/ZjRITD25H4DnOQClLA4/j7jLGXXLVKxAug==} + engines: {node: '>= 10'} require-directory@2.1.1: - resolution: - { - integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==, - } - engines: { node: ">=0.10.0" } + resolution: {integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==} + engines: {node: '>=0.10.0'} require-main-filename@2.0.0: - resolution: - { - integrity: sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==, - } + resolution: {integrity: sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==} requireindex@1.2.0: - resolution: - { - integrity: sha512-L9jEkOi3ASd9PYit2cwRfyppc9NoABujTP8/5gFcbERmo5jUoAKovIC3fsF17pkTnGsrByysqX+Kxd2OTNI1ww==, - } - engines: { node: ">=0.10.5" } + resolution: {integrity: sha512-L9jEkOi3ASd9PYit2cwRfyppc9NoABujTP8/5gFcbERmo5jUoAKovIC3fsF17pkTnGsrByysqX+Kxd2OTNI1ww==} + engines: {node: '>=0.10.5'} reserved-identifiers@1.2.0: - resolution: - { - integrity: sha512-yE7KUfFvaBFzGPs5H3Ops1RevfUEsDc5Iz65rOwWg4lE8HJSYtle77uul3+573457oHvBKuHYDl/xqUkKpEEdw==, - } - engines: { node: ">=18" } + resolution: {integrity: sha512-yE7KUfFvaBFzGPs5H3Ops1RevfUEsDc5Iz65rOwWg4lE8HJSYtle77uul3+573457oHvBKuHYDl/xqUkKpEEdw==} + engines: {node: '>=18'} resolve-from@4.0.0: - resolution: - { - integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==, - } - engines: { node: ">=4" } + resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==} + engines: {node: '>=4'} resolve-options@2.0.0: - resolution: - { - integrity: sha512-/FopbmmFOQCfsCx77BRFdKOniglTiHumLgwvd6IDPihy1GKkadZbgQJBcTb2lMzSR1pndzd96b1nZrreZ7+9/A==, - } - engines: { node: ">= 10.13.0" } + resolution: {integrity: sha512-/FopbmmFOQCfsCx77BRFdKOniglTiHumLgwvd6IDPihy1GKkadZbgQJBcTb2lMzSR1pndzd96b1nZrreZ7+9/A==} + engines: {node: '>= 10.13.0'} resolve@1.22.12: - resolution: - { - integrity: sha512-TyeJ1zif53BPfHootBGwPRYT1RUt6oGWsaQr8UyZW/eAm9bKoijtvruSDEmZHm92CwS9nj7/fWttqPCgzep8CA==, - } - engines: { node: ">= 0.4" } + resolution: {integrity: sha512-TyeJ1zif53BPfHootBGwPRYT1RUt6oGWsaQr8UyZW/eAm9bKoijtvruSDEmZHm92CwS9nj7/fWttqPCgzep8CA==} + engines: {node: '>= 0.4'} hasBin: true resolve@2.0.0-next.6: - resolution: - { - integrity: sha512-3JmVl5hMGtJ3kMmB3zi3DL25KfkCEyy3Tw7Gmw7z5w8M9WlwoPFnIvwChzu1+cF3iaK3sp18hhPz8ANeimdJfA==, - } - engines: { node: ">= 0.4" } + resolution: {integrity: sha512-3JmVl5hMGtJ3kMmB3zi3DL25KfkCEyy3Tw7Gmw7z5w8M9WlwoPFnIvwChzu1+cF3iaK3sp18hhPz8ANeimdJfA==} + engines: {node: '>= 0.4'} hasBin: true reusify@1.1.0: - resolution: - { - integrity: sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==, - } - engines: { iojs: ">=1.0.0", node: ">=0.10.0" } + resolution: {integrity: sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==} + engines: {iojs: '>=1.0.0', node: '>=0.10.0'} rimraf@3.0.2: - resolution: - { - integrity: sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==, - } + resolution: {integrity: sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==} deprecated: Rimraf versions prior to v4 are no longer supported hasBin: true rimraf@5.0.10: - resolution: - { - integrity: sha512-l0OE8wL34P4nJH/H2ffoaniAokM2qSmrtXHmlpvYr5AVVX8msAyW0l8NVJFDxlSK4u3Uh/f41cQheDVdnYijwQ==, - } + resolution: {integrity: sha512-l0OE8wL34P4nJH/H2ffoaniAokM2qSmrtXHmlpvYr5AVVX8msAyW0l8NVJFDxlSK4u3Uh/f41cQheDVdnYijwQ==} hasBin: true ripemd160@2.0.3: - resolution: - { - integrity: sha512-5Di9UC0+8h1L6ZD2d7awM7E/T4uA1fJRlx6zk/NvdCCVEoAnFqvHmCuNeIKoCeIixBX/q8uM+6ycDvF8woqosA==, - } - engines: { node: ">= 0.8" } + resolution: {integrity: sha512-5Di9UC0+8h1L6ZD2d7awM7E/T4uA1fJRlx6zk/NvdCCVEoAnFqvHmCuNeIKoCeIixBX/q8uM+6ycDvF8woqosA==} + engines: {node: '>= 0.8'} rolldown@1.0.0-rc.15: - resolution: - { - integrity: sha512-Ff31guA5zT6WjnGp0SXw76X6hzGRk/OQq2hE+1lcDe+lJdHSgnSX6nK3erbONHyCbpSj9a9E+uX/OvytZoWp2g==, - } - engines: { node: ^20.19.0 || >=22.12.0 } + resolution: {integrity: sha512-Ff31guA5zT6WjnGp0SXw76X6hzGRk/OQq2hE+1lcDe+lJdHSgnSX6nK3erbONHyCbpSj9a9E+uX/OvytZoWp2g==} + engines: {node: ^20.19.0 || >=22.12.0} + hasBin: true + + rollup@4.60.1: + resolution: {integrity: sha512-VmtB2rFU/GroZ4oL8+ZqXgSA38O6GR8KSIvWmEFv63pQ0G6KaBH9s07PO8XTXP4vI+3UJUEypOfjkGfmSBBR0w==} + engines: {node: '>=18.0.0', npm: '>=8.0.0'} hasBin: true rrweb-cssom@0.8.0: - resolution: - { - integrity: sha512-guoltQEx+9aMf2gDZ0s62EcV8lsXR+0w8915TC3ITdn2YueuNjdAYh/levpU9nFaoChh9RUS5ZdQMrKfVEN9tw==, - } + resolution: {integrity: sha512-guoltQEx+9aMf2gDZ0s62EcV8lsXR+0w8915TC3ITdn2YueuNjdAYh/levpU9nFaoChh9RUS5ZdQMrKfVEN9tw==} rsvp@3.2.1: - resolution: - { - integrity: sha512-Rf4YVNYpKjZ6ASAmibcwTNciQ5Co5Ztq6iZPEykHpkoflnD/K5ryE/rHehFsTm4NJj8nKDhbi3eKBWGogmNnkg==, - } + resolution: {integrity: sha512-Rf4YVNYpKjZ6ASAmibcwTNciQ5Co5Ztq6iZPEykHpkoflnD/K5ryE/rHehFsTm4NJj8nKDhbi3eKBWGogmNnkg==} rsvp@4.8.5: - resolution: - { - integrity: sha512-nfMOlASu9OnRJo1mbEk2cz0D56a1MBNrJ7orjRZQG10XDyuvwksKbuXNp6qa+kbn839HwjwhBzhFmdsaEAfauA==, - } - engines: { node: 6.* || >= 7.* } + resolution: {integrity: sha512-nfMOlASu9OnRJo1mbEk2cz0D56a1MBNrJ7orjRZQG10XDyuvwksKbuXNp6qa+kbn839HwjwhBzhFmdsaEAfauA==} + engines: {node: 6.* || >= 7.*} run-applescript@7.1.0: - resolution: - { - integrity: sha512-DPe5pVFaAsinSaV6QjQ6gdiedWDcRCbUuiQfQa2wmWV7+xC9bGulGI8+TdRmoFkAPaBXk8CrAbnlY2ISniJ47Q==, - } - engines: { node: ">=18" } + resolution: {integrity: sha512-DPe5pVFaAsinSaV6QjQ6gdiedWDcRCbUuiQfQa2wmWV7+xC9bGulGI8+TdRmoFkAPaBXk8CrAbnlY2ISniJ47Q==} + engines: {node: '>=18'} run-parallel@1.2.0: - resolution: - { - integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==, - } + resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} rxjs-report-usage@1.0.6: - resolution: - { - integrity: sha512-omv1DIv5z1kV+zDAEjaDjWSkx8w5TbFp5NZoPwUipwzYVcor/4So9ZU3bUyQ1c8lxY5Q0Es/ztWW7PGjY7to0Q==, - } + resolution: {integrity: sha512-omv1DIv5z1kV+zDAEjaDjWSkx8w5TbFp5NZoPwUipwzYVcor/4So9ZU3bUyQ1c8lxY5Q0Es/ztWW7PGjY7to0Q==} hasBin: true rxjs@7.8.2: - resolution: - { - integrity: sha512-dhKf903U/PQZY6boNNtAGdWbG85WAbjT/1xYoZIC7FAY0yWapOBQVsVrDl58W86//e1VpMNBtRV4MaXfdMySFA==, - } + resolution: {integrity: sha512-dhKf903U/PQZY6boNNtAGdWbG85WAbjT/1xYoZIC7FAY0yWapOBQVsVrDl58W86//e1VpMNBtRV4MaXfdMySFA==} safe-array-concat@1.1.3: - resolution: - { - integrity: sha512-AURm5f0jYEOydBj7VQlVvDrjeFgthDdEF5H1dP+6mNpoXOMo1quQqJ4wvJDyRZ9+pO3kGWoOdmV08cSv2aJV6Q==, - } - engines: { node: ">=0.4" } + resolution: {integrity: sha512-AURm5f0jYEOydBj7VQlVvDrjeFgthDdEF5H1dP+6mNpoXOMo1quQqJ4wvJDyRZ9+pO3kGWoOdmV08cSv2aJV6Q==} + engines: {node: '>=0.4'} safe-buffer@5.1.2: - resolution: - { - integrity: sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==, - } + resolution: {integrity: sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==} safe-buffer@5.2.1: - resolution: - { - integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==, - } + resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==} safe-push-apply@1.0.0: - resolution: - { - integrity: sha512-iKE9w/Z7xCzUMIZqdBsp6pEQvwuEebH4vdpjcDWnyzaI6yl6O9FHvVpmGelvEHNsoY6wGblkxR6Zty/h00WiSA==, - } - engines: { node: ">= 0.4" } + resolution: {integrity: sha512-iKE9w/Z7xCzUMIZqdBsp6pEQvwuEebH4vdpjcDWnyzaI6yl6O9FHvVpmGelvEHNsoY6wGblkxR6Zty/h00WiSA==} + engines: {node: '>= 0.4'} safe-regex-test@1.1.0: - resolution: - { - integrity: sha512-x/+Cz4YrimQxQccJf5mKEbIa1NzeCRNI5Ecl/ekmlYaampdNLPalVyIcCZNNH3MvmqBugV5TMYZXv0ljslUlaw==, - } - engines: { node: ">= 0.4" } + resolution: {integrity: sha512-x/+Cz4YrimQxQccJf5mKEbIa1NzeCRNI5Ecl/ekmlYaampdNLPalVyIcCZNNH3MvmqBugV5TMYZXv0ljslUlaw==} + engines: {node: '>= 0.4'} safer-buffer@2.1.2: - resolution: - { - integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==, - } + resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==} sass@1.99.0: - resolution: - { - integrity: sha512-kgW13M54DUB7IsIRM5LvJkNlpH+WhMpooUcaWGFARkF1Tc82v9mIWkCbCYf+MBvpIUBSeSOTilpZjEPr2VYE6Q==, - } - engines: { node: ">=14.0.0" } + resolution: {integrity: sha512-kgW13M54DUB7IsIRM5LvJkNlpH+WhMpooUcaWGFARkF1Tc82v9mIWkCbCYf+MBvpIUBSeSOTilpZjEPr2VYE6Q==} + engines: {node: '>=14.0.0'} hasBin: true saxes@6.0.0: - resolution: - { - integrity: sha512-xAg7SOnEhrm5zI3puOOKyy1OMcMlIJZYNJY7xLBwSze0UjhPLnWfj2GF2EpT0jmzaJKIWKHLsaSSajf35bcYnA==, - } - engines: { node: ">=v12.22.7" } + resolution: {integrity: sha512-xAg7SOnEhrm5zI3puOOKyy1OMcMlIJZYNJY7xLBwSze0UjhPLnWfj2GF2EpT0jmzaJKIWKHLsaSSajf35bcYnA==} + engines: {node: '>=v12.22.7'} scheduler@0.27.0: - resolution: - { - integrity: sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q==, - } + resolution: {integrity: sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q==} sdp-transform@2.15.0: - resolution: - { - integrity: sha512-KrOH82c/W+GYQ0LHqtr3caRpM3ITglq3ljGUIb8LTki7ByacJZ9z+piSGiwZDsRyhQbYBOBJgr2k6X4BZXi3Kw==, - } + resolution: {integrity: sha512-KrOH82c/W+GYQ0LHqtr3caRpM3ITglq3ljGUIb8LTki7ByacJZ9z+piSGiwZDsRyhQbYBOBJgr2k6X4BZXi3Kw==} hasBin: true sdp-transform@3.0.0: - resolution: - { - integrity: sha512-gfYVRGxjHkGF2NPeUWHw5u6T/KGFtS5/drPms73gaSuMaVHKCY3lpLnGDfswVQO0kddeePoti09AwhYP4zA8dQ==, - } + resolution: {integrity: sha512-gfYVRGxjHkGF2NPeUWHw5u6T/KGFtS5/drPms73gaSuMaVHKCY3lpLnGDfswVQO0kddeePoti09AwhYP4zA8dQ==} hasBin: true sdp@3.2.2: - resolution: - { - integrity: sha512-xZocWwfyp4hkbN4hLWxMjmv2Q8aNa9MhmOZ7L9aCZPT+dZsgRr6wZRrSYE3HTdyk/2pZKPSgqI7ns7Een1xMSA==, - } + resolution: {integrity: sha512-xZocWwfyp4hkbN4hLWxMjmv2Q8aNa9MhmOZ7L9aCZPT+dZsgRr6wZRrSYE3HTdyk/2pZKPSgqI7ns7Een1xMSA==} semver@5.7.2: - resolution: - { - integrity: sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==, - } + resolution: {integrity: sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==} hasBin: true semver@6.3.1: - resolution: - { - integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==, - } + resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==} hasBin: true semver@7.7.4: - resolution: - { - integrity: sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==, - } - engines: { node: ">=10" } + resolution: {integrity: sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==} + engines: {node: '>=10'} hasBin: true set-blocking@2.0.0: - resolution: - { - integrity: sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==, - } + resolution: {integrity: sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==} set-cookie-parser@2.7.2: - resolution: - { - integrity: sha512-oeM1lpU/UvhTxw+g3cIfxXHyJRc/uidd3yK1P242gzHds0udQBYzs3y8j4gCCW+ZJ7ad0yctld8RYO+bdurlvw==, - } + resolution: {integrity: sha512-oeM1lpU/UvhTxw+g3cIfxXHyJRc/uidd3yK1P242gzHds0udQBYzs3y8j4gCCW+ZJ7ad0yctld8RYO+bdurlvw==} set-function-length@1.2.2: - resolution: - { - integrity: sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==, - } - engines: { node: ">= 0.4" } + resolution: {integrity: sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==} + engines: {node: '>= 0.4'} set-function-name@2.0.2: - resolution: - { - integrity: sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==, - } - engines: { node: ">= 0.4" } + resolution: {integrity: sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==} + engines: {node: '>= 0.4'} set-proto@1.0.0: - resolution: - { - integrity: sha512-RJRdvCo6IAnPdsvP/7m6bsQqNnn1FCBX5ZNtFL98MmFF/4xAIJTIg1YbHW5DC2W5SKZanrC6i4HsJqlajw/dZw==, - } - engines: { node: ">= 0.4" } + resolution: {integrity: sha512-RJRdvCo6IAnPdsvP/7m6bsQqNnn1FCBX5ZNtFL98MmFF/4xAIJTIg1YbHW5DC2W5SKZanrC6i4HsJqlajw/dZw==} + engines: {node: '>= 0.4'} setimmediate@1.0.5: - resolution: - { - integrity: sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA==, - } + resolution: {integrity: sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA==} sha.js@2.4.12: - resolution: - { - integrity: sha512-8LzC5+bvI45BjpfXU8V5fdU2mfeKiQe1D1gIMn7XUlF3OTUrpdJpPPH4EMAnF0DsHHdSZqCdSss5qCmJKuiO3w==, - } - engines: { node: ">= 0.10" } + resolution: {integrity: sha512-8LzC5+bvI45BjpfXU8V5fdU2mfeKiQe1D1gIMn7XUlF3OTUrpdJpPPH4EMAnF0DsHHdSZqCdSss5qCmJKuiO3w==} + engines: {node: '>= 0.10'} hasBin: true shebang-command@2.0.0: - resolution: - { - integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==, - } - engines: { node: ">=8" } + resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==} + engines: {node: '>=8'} shebang-regex@3.0.0: - resolution: - { - integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==, - } - engines: { node: ">=8" } + resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} + engines: {node: '>=8'} side-channel-list@1.0.1: - resolution: - { - integrity: sha512-mjn/0bi/oUURjc5Xl7IaWi/OJJJumuoJFQJfDDyO46+hBWsfaVM65TBHq2eoZBhzl9EchxOijpkbRC8SVBQU0w==, - } - engines: { node: ">= 0.4" } + resolution: {integrity: sha512-mjn/0bi/oUURjc5Xl7IaWi/OJJJumuoJFQJfDDyO46+hBWsfaVM65TBHq2eoZBhzl9EchxOijpkbRC8SVBQU0w==} + engines: {node: '>= 0.4'} side-channel-map@1.0.1: - resolution: - { - integrity: sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==, - } - engines: { node: ">= 0.4" } + resolution: {integrity: sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==} + engines: {node: '>= 0.4'} side-channel-weakmap@1.0.2: - resolution: - { - integrity: sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==, - } - engines: { node: ">= 0.4" } + resolution: {integrity: sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==} + engines: {node: '>= 0.4'} side-channel@1.1.0: - resolution: - { - integrity: sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==, - } - engines: { node: ">= 0.4" } + resolution: {integrity: sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==} + engines: {node: '>= 0.4'} siginfo@2.0.0: - resolution: - { - integrity: sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==, - } + resolution: {integrity: sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==} signal-exit@4.1.0: - resolution: - { - integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==, - } - engines: { node: ">=14" } + resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==} + engines: {node: '>=14'} sisteransi@1.0.5: - resolution: - { - integrity: sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==, - } + resolution: {integrity: sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==} slash@3.0.0: - resolution: - { - integrity: sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==, - } - engines: { node: ">=8" } + resolution: {integrity: sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==} + engines: {node: '>=8'} smol-toml@1.6.1: - resolution: - { - integrity: sha512-dWUG8F5sIIARXih1DTaQAX4SsiTXhInKf1buxdY9DIg4ZYPZK5nGM1VRIYmEbDbsHt7USo99xSLFu5Q1IqTmsg==, - } - engines: { node: ">= 18" } + resolution: {integrity: sha512-dWUG8F5sIIARXih1DTaQAX4SsiTXhInKf1buxdY9DIg4ZYPZK5nGM1VRIYmEbDbsHt7USo99xSLFu5Q1IqTmsg==} + engines: {node: '>= 18'} snake-case@3.0.4: - resolution: - { - integrity: sha512-LAOh4z89bGQvl9pFfNF8V146i7o7/CqFPbqzYgP+yYzDIDeS9HaNFtXABamRW+AQzEVODcvE79ljJ+8a9YSdMg==, - } + resolution: {integrity: sha512-LAOh4z89bGQvl9pFfNF8V146i7o7/CqFPbqzYgP+yYzDIDeS9HaNFtXABamRW+AQzEVODcvE79ljJ+8a9YSdMg==} sort-keys@5.1.0: - resolution: - { - integrity: sha512-aSbHV0DaBcr7u0PVHXzM6NbZNAtrr9sF6+Qfs9UUVG7Ll3jQ6hHi8F/xqIIcn2rvIVbr0v/2zyjSdwSV47AgLQ==, - } - engines: { node: ">=12" } + resolution: {integrity: sha512-aSbHV0DaBcr7u0PVHXzM6NbZNAtrr9sF6+Qfs9UUVG7Ll3jQ6hHi8F/xqIIcn2rvIVbr0v/2zyjSdwSV47AgLQ==} + engines: {node: '>=12'} source-map-js@1.2.1: - resolution: - { - integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==, - } - engines: { node: ">=0.10.0" } + resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==} + engines: {node: '>=0.10.0'} source-map-support@0.5.21: - resolution: - { - integrity: sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==, - } + resolution: {integrity: sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==} source-map@0.6.1: - resolution: - { - integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==, - } - engines: { node: ">=0.10.0" } + resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==} + engines: {node: '>=0.10.0'} spdx-correct@3.2.0: - resolution: - { - integrity: sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA==, - } + resolution: {integrity: sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA==} spdx-exceptions@2.5.0: - resolution: - { - integrity: sha512-PiU42r+xO4UbUS1buo3LPJkjlO7430Xn5SVAhdpzzsPHsjbYVflnnFdATgabnLude+Cqu25p6N+g2lw/PFsa4w==, - } + resolution: {integrity: sha512-PiU42r+xO4UbUS1buo3LPJkjlO7430Xn5SVAhdpzzsPHsjbYVflnnFdATgabnLude+Cqu25p6N+g2lw/PFsa4w==} spdx-expression-parse@3.0.1: - resolution: - { - integrity: sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==, - } + resolution: {integrity: sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==} spdx-expression-parse@4.0.0: - resolution: - { - integrity: sha512-Clya5JIij/7C6bRR22+tnGXbc4VKlibKSVj2iHvVeX5iMW7s1SIQlqu699JkODJJIhh/pUu8L0/VLh8xflD+LQ==, - } + resolution: {integrity: sha512-Clya5JIij/7C6bRR22+tnGXbc4VKlibKSVj2iHvVeX5iMW7s1SIQlqu699JkODJJIhh/pUu8L0/VLh8xflD+LQ==} spdx-license-ids@3.0.23: - resolution: - { - integrity: sha512-CWLcCCH7VLu13TgOH+r8p1O/Znwhqv/dbb6lqWy67G+pT1kHmeD/+V36AVb/vq8QMIQwVShJ6Ssl5FPh0fuSdw==, - } + resolution: {integrity: sha512-CWLcCCH7VLu13TgOH+r8p1O/Znwhqv/dbb6lqWy67G+pT1kHmeD/+V36AVb/vq8QMIQwVShJ6Ssl5FPh0fuSdw==} sprintf-js@1.1.3: - resolution: - { - integrity: sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA==, - } + resolution: {integrity: sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA==} stackback@0.0.2: - resolution: - { - integrity: sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==, - } + resolution: {integrity: sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==} std-env@4.1.0: - resolution: - { - integrity: sha512-Rq7ybcX2RuC55r9oaPVEW7/xu3tj8u4GeBYHBWCychFtzMIr86A7e3PPEBPT37sHStKX3+TiX/Fr/ACmJLVlLQ==, - } + resolution: {integrity: sha512-Rq7ybcX2RuC55r9oaPVEW7/xu3tj8u4GeBYHBWCychFtzMIr86A7e3PPEBPT37sHStKX3+TiX/Fr/ACmJLVlLQ==} stop-iteration-iterator@1.1.0: - resolution: - { - integrity: sha512-eLoXW/DHyl62zxY4SCaIgnRhuMr6ri4juEYARS8E6sCEqzKpOiE521Ucofdx+KnDZl5xmvGYaaKCk5FEOxJCoQ==, - } - engines: { node: ">= 0.4" } + resolution: {integrity: sha512-eLoXW/DHyl62zxY4SCaIgnRhuMr6ri4juEYARS8E6sCEqzKpOiE521Ucofdx+KnDZl5xmvGYaaKCk5FEOxJCoQ==} + engines: {node: '>= 0.4'} storybook@10.3.5: - resolution: - { - integrity: sha512-uBSZu/GZa9aEIW3QMGvdQPMZWhGxSe4dyRWU8B3/Vd47Gy/XLC7tsBxRr13txmmPOEDHZR94uLuq0H50fvuqBw==, - } + resolution: {integrity: sha512-uBSZu/GZa9aEIW3QMGvdQPMZWhGxSe4dyRWU8B3/Vd47Gy/XLC7tsBxRr13txmmPOEDHZR94uLuq0H50fvuqBw==} hasBin: true peerDependencies: prettier: ^2 || ^3 @@ -9387,799 +5997,476 @@ packages: optional: true stream-browserify@3.0.0: - resolution: - { - integrity: sha512-H73RAHsVBapbim0tU2JwwOiXUj+fikfiaoYAKHF3VJfA0pe2BCzkhAHBlLG6REzE+2WNZcxOXjK7lkso+9euLA==, - } + resolution: {integrity: sha512-H73RAHsVBapbim0tU2JwwOiXUj+fikfiaoYAKHF3VJfA0pe2BCzkhAHBlLG6REzE+2WNZcxOXjK7lkso+9euLA==} stream-composer@1.0.2: - resolution: - { - integrity: sha512-bnBselmwfX5K10AH6L4c8+S5lgZMWI7ZYrz2rvYjCPB2DIMC4Ig8OpxGpNJSxRZ58oti7y1IcNvjBAz9vW5m4w==, - } + resolution: {integrity: sha512-bnBselmwfX5K10AH6L4c8+S5lgZMWI7ZYrz2rvYjCPB2DIMC4Ig8OpxGpNJSxRZ58oti7y1IcNvjBAz9vW5m4w==} stream-http@3.2.0: - resolution: - { - integrity: sha512-Oq1bLqisTyK3TSCXpPbT4sdeYNdmyZJv1LxpEm2vu1ZhK89kSE5YXwZc3cWk0MagGaKriBh9mCFbVGtO+vY29A==, - } + resolution: {integrity: sha512-Oq1bLqisTyK3TSCXpPbT4sdeYNdmyZJv1LxpEm2vu1ZhK89kSE5YXwZc3cWk0MagGaKriBh9mCFbVGtO+vY29A==} streamx@2.25.0: - resolution: - { - integrity: sha512-0nQuG6jf1w+wddNEEXCF4nTg3LtufWINB5eFEN+5TNZW7KWJp6x87+JFL43vaAUPyCfH1wID+mNVyW6OHtFamg==, - } + resolution: {integrity: sha512-0nQuG6jf1w+wddNEEXCF4nTg3LtufWINB5eFEN+5TNZW7KWJp6x87+JFL43vaAUPyCfH1wID+mNVyW6OHtFamg==} string-width@4.2.3: - resolution: - { - integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==, - } - engines: { node: ">=8" } + resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} + engines: {node: '>=8'} string-width@5.1.2: - resolution: - { - integrity: sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==, - } - engines: { node: ">=12" } + resolution: {integrity: sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==} + engines: {node: '>=12'} string.prototype.includes@2.0.1: - resolution: - { - integrity: sha512-o7+c9bW6zpAdJHTtujeePODAhkuicdAryFsfVKwA+wGw89wJ4GTY484WTucM9hLtDEOpOvI+aHnzqnC5lHp4Rg==, - } - engines: { node: ">= 0.4" } + resolution: {integrity: sha512-o7+c9bW6zpAdJHTtujeePODAhkuicdAryFsfVKwA+wGw89wJ4GTY484WTucM9hLtDEOpOvI+aHnzqnC5lHp4Rg==} + engines: {node: '>= 0.4'} string.prototype.matchall@4.0.12: - resolution: - { - integrity: sha512-6CC9uyBL+/48dYizRf7H7VAYCMCNTBeM78x/VTUe9bFEaxBepPJDa1Ow99LqI/1yF7kuy7Q3cQsYMrcjGUcskA==, - } - engines: { node: ">= 0.4" } + resolution: {integrity: sha512-6CC9uyBL+/48dYizRf7H7VAYCMCNTBeM78x/VTUe9bFEaxBepPJDa1Ow99LqI/1yF7kuy7Q3cQsYMrcjGUcskA==} + engines: {node: '>= 0.4'} string.prototype.repeat@1.0.0: - resolution: - { - integrity: sha512-0u/TldDbKD8bFCQ/4f5+mNRrXwZ8hg2w7ZR8wa16e8z9XpePWl3eGEcUD0OXpEH/VJH/2G3gjUtR3ZOiBe2S/w==, - } + resolution: {integrity: sha512-0u/TldDbKD8bFCQ/4f5+mNRrXwZ8hg2w7ZR8wa16e8z9XpePWl3eGEcUD0OXpEH/VJH/2G3gjUtR3ZOiBe2S/w==} string.prototype.trim@1.2.10: - resolution: - { - integrity: sha512-Rs66F0P/1kedk5lyYyH9uBzuiI/kNRmwJAR9quK6VOtIpZ2G+hMZd+HQbbv25MgCA6gEffoMZYxlTod4WcdrKA==, - } - engines: { node: ">= 0.4" } + resolution: {integrity: sha512-Rs66F0P/1kedk5lyYyH9uBzuiI/kNRmwJAR9quK6VOtIpZ2G+hMZd+HQbbv25MgCA6gEffoMZYxlTod4WcdrKA==} + engines: {node: '>= 0.4'} string.prototype.trimend@1.0.9: - resolution: - { - integrity: sha512-G7Ok5C6E/j4SGfyLCloXTrngQIQU3PWtXGst3yM7Bea9FRURf1S42ZHlZZtsNque2FN2PoUhfZXYLNWwEr4dLQ==, - } - engines: { node: ">= 0.4" } + resolution: {integrity: sha512-G7Ok5C6E/j4SGfyLCloXTrngQIQU3PWtXGst3yM7Bea9FRURf1S42ZHlZZtsNque2FN2PoUhfZXYLNWwEr4dLQ==} + engines: {node: '>= 0.4'} string.prototype.trimstart@1.0.8: - resolution: - { - integrity: sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg==, - } - engines: { node: ">= 0.4" } + resolution: {integrity: sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg==} + engines: {node: '>= 0.4'} string_decoder@1.1.1: - resolution: - { - integrity: sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==, - } + resolution: {integrity: sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==} string_decoder@1.3.0: - resolution: - { - integrity: sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==, - } + resolution: {integrity: sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==} strip-ansi@6.0.1: - resolution: - { - integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==, - } - engines: { node: ">=8" } + resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} + engines: {node: '>=8'} strip-ansi@7.2.0: - resolution: - { - integrity: sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w==, - } - engines: { node: ">=12" } + resolution: {integrity: sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w==} + engines: {node: '>=12'} strip-bom@3.0.0: - resolution: - { - integrity: sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==, - } - engines: { node: ">=4" } + resolution: {integrity: sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==} + engines: {node: '>=4'} strip-indent@3.0.0: - resolution: - { - integrity: sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==, - } - engines: { node: ">=8" } + resolution: {integrity: sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==} + engines: {node: '>=8'} strip-indent@4.1.1: - resolution: - { - integrity: sha512-SlyRoSkdh1dYP0PzclLE7r0M9sgbFKKMFXpFRUMNuKhQSbC6VQIGzq3E0qsfvGJaUFJPGv6Ws1NZ/haTAjfbMA==, - } - engines: { node: ">=12" } + resolution: {integrity: sha512-SlyRoSkdh1dYP0PzclLE7r0M9sgbFKKMFXpFRUMNuKhQSbC6VQIGzq3E0qsfvGJaUFJPGv6Ws1NZ/haTAjfbMA==} + engines: {node: '>=12'} strip-json-comments@3.1.1: - resolution: - { - integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==, - } - engines: { node: ">=8" } + resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==} + engines: {node: '>=8'} strip-json-comments@5.0.3: - resolution: - { - integrity: sha512-1tB5mhVo7U+ETBKNf92xT4hrQa3pm0MZ0PQvuDnWgAAGHDsfp4lPSpiS6psrSiet87wyGPh9ft6wmhOMQ0hDiw==, - } - engines: { node: ">=14.16" } + resolution: {integrity: sha512-1tB5mhVo7U+ETBKNf92xT4hrQa3pm0MZ0PQvuDnWgAAGHDsfp4lPSpiS6psrSiet87wyGPh9ft6wmhOMQ0hDiw==} + engines: {node: '>=14.16'} supports-color@7.2.0: - resolution: - { - integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==, - } - engines: { node: ">=8" } + resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==} + engines: {node: '>=8'} supports-preserve-symlinks-flag@1.0.0: - resolution: - { - integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==, - } - engines: { node: ">= 0.4" } + resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} + engines: {node: '>= 0.4'} svg-parser@2.0.4: - resolution: - { - integrity: sha512-e4hG1hRwoOdRb37cIMSgzNsxyzKfayW6VOflrwvR+/bzrkyxY/31WkbgnQpgtrNp1SdpJvpUAGTa/ZoiPNDuRQ==, - } + resolution: {integrity: sha512-e4hG1hRwoOdRb37cIMSgzNsxyzKfayW6VOflrwvR+/bzrkyxY/31WkbgnQpgtrNp1SdpJvpUAGTa/ZoiPNDuRQ==} symbol-tree@3.2.4: - resolution: - { - integrity: sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==, - } + resolution: {integrity: sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==} symlink-or-copy@1.3.1: - resolution: - { - integrity: sha512-0K91MEXFpBUaywiwSSkmKjnGcasG/rVBXFLJz5DrgGabpYD6N+3yZrfD6uUIfpuTu65DZLHi7N8CizHc07BPZA==, - } + resolution: {integrity: sha512-0K91MEXFpBUaywiwSSkmKjnGcasG/rVBXFLJz5DrgGabpYD6N+3yZrfD6uUIfpuTu65DZLHi7N8CizHc07BPZA==} tabbable@6.4.0: - resolution: - { - integrity: sha512-05PUHKSNE8ou2dwIxTngl4EzcnsCDZGJ/iCLtDflR/SHB/ny14rXc+qU5P4mG9JkusiV7EivzY9Mhm55AzAvCg==, - } + resolution: {integrity: sha512-05PUHKSNE8ou2dwIxTngl4EzcnsCDZGJ/iCLtDflR/SHB/ny14rXc+qU5P4mG9JkusiV7EivzY9Mhm55AzAvCg==} teex@1.0.1: - resolution: - { - integrity: sha512-eYE6iEI62Ni1H8oIa7KlDU6uQBtqr4Eajni3wX7rpfXD8ysFx8z0+dri+KWEPWpBsxXfxu58x/0jvTVT1ekOSg==, - } + resolution: {integrity: sha512-eYE6iEI62Ni1H8oIa7KlDU6uQBtqr4Eajni3wX7rpfXD8ysFx8z0+dri+KWEPWpBsxXfxu58x/0jvTVT1ekOSg==} terser@5.46.1: - resolution: - { - integrity: sha512-vzCjQO/rgUuK9sf8VJZvjqiqiHFaZLnOiimmUuOKODxWL8mm/xua7viT7aqX7dgPY60otQjUotzFMmCB4VdmqQ==, - } - engines: { node: ">=10" } + resolution: {integrity: sha512-vzCjQO/rgUuK9sf8VJZvjqiqiHFaZLnOiimmUuOKODxWL8mm/xua7viT7aqX7dgPY60otQjUotzFMmCB4VdmqQ==} + engines: {node: '>=10'} hasBin: true text-decoder@1.2.7: - resolution: - { - integrity: sha512-vlLytXkeP4xvEq2otHeJfSQIRyWxo/oZGEbXrtEEF9Hnmrdly59sUbzZ/QgyWuLYHctCHxFF4tRQZNQ9k60ExQ==, - } + resolution: {integrity: sha512-vlLytXkeP4xvEq2otHeJfSQIRyWxo/oZGEbXrtEEF9Hnmrdly59sUbzZ/QgyWuLYHctCHxFF4tRQZNQ9k60ExQ==} text-table@0.2.0: - resolution: - { - integrity: sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==, - } + resolution: {integrity: sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==} through2@2.0.5: - resolution: - { - integrity: sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==, - } + resolution: {integrity: sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==} timers-browserify@2.0.12: - resolution: - { - integrity: sha512-9phl76Cqm6FhSX9Xe1ZUAMLtm1BLkKj2Qd5ApyWkXzsMRaA7dgr81kf4wJmQf/hAvg8EEyJxDo3du/0KlhPiKQ==, - } - engines: { node: ">=0.6.0" } + resolution: {integrity: sha512-9phl76Cqm6FhSX9Xe1ZUAMLtm1BLkKj2Qd5ApyWkXzsMRaA7dgr81kf4wJmQf/hAvg8EEyJxDo3du/0KlhPiKQ==} + engines: {node: '>=0.6.0'} tiny-invariant@1.3.3: - resolution: - { - integrity: sha512-+FbBPE1o9QAYvviau/qC5SE3caw21q3xkvWKBtja5vgqOWIHHJ3ioaq1VPfn/Szqctz2bU/oYeKd9/z5BL+PVg==, - } + resolution: {integrity: sha512-+FbBPE1o9QAYvviau/qC5SE3caw21q3xkvWKBtja5vgqOWIHHJ3ioaq1VPfn/Szqctz2bU/oYeKd9/z5BL+PVg==} tinybench@2.9.0: - resolution: - { - integrity: sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==, - } + resolution: {integrity: sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==} tinyexec@1.1.1: - resolution: - { - integrity: sha512-VKS/ZaQhhkKFMANmAOhhXVoIfBXblQxGX1myCQ2faQrfmobMftXeJPcZGp0gS07ocvGJWDLZGyOZDadDBqYIJg==, - } - engines: { node: ">=18" } + resolution: {integrity: sha512-VKS/ZaQhhkKFMANmAOhhXVoIfBXblQxGX1myCQ2faQrfmobMftXeJPcZGp0gS07ocvGJWDLZGyOZDadDBqYIJg==} + engines: {node: '>=18'} tinyglobby@0.2.16: - resolution: - { - integrity: sha512-pn99VhoACYR8nFHhxqix+uvsbXineAasWm5ojXoN8xEwK5Kd3/TrhNn1wByuD52UxWRLy8pu+kRMniEi6Eq9Zg==, - } - engines: { node: ">=12.0.0" } + resolution: {integrity: sha512-pn99VhoACYR8nFHhxqix+uvsbXineAasWm5ojXoN8xEwK5Kd3/TrhNn1wByuD52UxWRLy8pu+kRMniEi6Eq9Zg==} + engines: {node: '>=12.0.0'} tinyrainbow@2.0.0: - resolution: - { - integrity: sha512-op4nsTR47R6p0vMUUoYl/a+ljLFVtlfaXkLQmqfLR1qHma1h/ysYk4hEXZ880bf2CYgTskvTa/e196Vd5dDQXw==, - } - engines: { node: ">=14.0.0" } + resolution: {integrity: sha512-op4nsTR47R6p0vMUUoYl/a+ljLFVtlfaXkLQmqfLR1qHma1h/ysYk4hEXZ880bf2CYgTskvTa/e196Vd5dDQXw==} + engines: {node: '>=14.0.0'} tinyrainbow@3.1.0: - resolution: - { - integrity: sha512-Bf+ILmBgretUrdJxzXM0SgXLZ3XfiaUuOj/IKQHuTXip+05Xn+uyEYdVg0kYDipTBcLrCVyUzAPz7QmArb0mmw==, - } - engines: { node: ">=14.0.0" } + resolution: {integrity: sha512-Bf+ILmBgretUrdJxzXM0SgXLZ3XfiaUuOj/IKQHuTXip+05Xn+uyEYdVg0kYDipTBcLrCVyUzAPz7QmArb0mmw==} + engines: {node: '>=14.0.0'} tinyspy@4.0.4: - resolution: - { - integrity: sha512-azl+t0z7pw/z958Gy9svOTuzqIk6xq+NSheJzn5MMWtWTFywIacg2wUlzKFGtt3cthx0r2SxMK0yzJOR0IES7Q==, - } - engines: { node: ">=14.0.0" } + resolution: {integrity: sha512-azl+t0z7pw/z958Gy9svOTuzqIk6xq+NSheJzn5MMWtWTFywIacg2wUlzKFGtt3cthx0r2SxMK0yzJOR0IES7Q==} + engines: {node: '>=14.0.0'} tldts-core@6.1.86: - resolution: - { - integrity: sha512-Je6p7pkk+KMzMv2XXKmAE3McmolOQFdxkKw0R8EYNr7sELW46JqnNeTX8ybPiQgvg1ymCoF8LXs5fzFaZvJPTA==, - } + resolution: {integrity: sha512-Je6p7pkk+KMzMv2XXKmAE3McmolOQFdxkKw0R8EYNr7sELW46JqnNeTX8ybPiQgvg1ymCoF8LXs5fzFaZvJPTA==} tldts@6.1.86: - resolution: - { - integrity: sha512-WMi/OQ2axVTf/ykqCQgXiIct+mSQDFdH2fkwhPwgEwvJ1kSzZRiinb0zF2Xb8u4+OqPChmyI6MEu4EezNJz+FQ==, - } + resolution: {integrity: sha512-WMi/OQ2axVTf/ykqCQgXiIct+mSQDFdH2fkwhPwgEwvJ1kSzZRiinb0zF2Xb8u4+OqPChmyI6MEu4EezNJz+FQ==} hasBin: true to-buffer@1.2.2: - resolution: - { - integrity: sha512-db0E3UJjcFhpDhAF4tLo03oli3pwl3dbnzXOUIlRKrp+ldk/VUxzpWYZENsw2SZiuBjHAk7DfB0VU7NKdpb6sw==, - } - engines: { node: ">= 0.4" } + resolution: {integrity: sha512-db0E3UJjcFhpDhAF4tLo03oli3pwl3dbnzXOUIlRKrp+ldk/VUxzpWYZENsw2SZiuBjHAk7DfB0VU7NKdpb6sw==} + engines: {node: '>= 0.4'} to-regex-range@5.0.1: - resolution: - { - integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==, - } - engines: { node: ">=8.0" } + resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} + engines: {node: '>=8.0'} to-through@3.0.0: - resolution: - { - integrity: sha512-y8MN937s/HVhEoBU1SxfHC+wxCHkV1a9gW8eAdTadYh/bGyesZIVcbjI+mSpFbSVwQici/XjBjuUyri1dnXwBw==, - } - engines: { node: ">=10.13.0" } + resolution: {integrity: sha512-y8MN937s/HVhEoBU1SxfHC+wxCHkV1a9gW8eAdTadYh/bGyesZIVcbjI+mSpFbSVwQici/XjBjuUyri1dnXwBw==} + engines: {node: '>=10.13.0'} to-valid-identifier@1.0.0: - resolution: - { - integrity: sha512-41wJyvKep3yT2tyPqX/4blcfybknGB4D+oETKLs7Q76UiPqRpUJK3hr1nxelyYO0PHKVzJwlu0aCeEAsGI6rpw==, - } - engines: { node: ">=20" } + resolution: {integrity: sha512-41wJyvKep3yT2tyPqX/4blcfybknGB4D+oETKLs7Q76UiPqRpUJK3hr1nxelyYO0PHKVzJwlu0aCeEAsGI6rpw==} + engines: {node: '>=20'} toggle-selection@1.0.6: - resolution: - { - integrity: sha512-BiZS+C1OS8g/q2RRbJmy59xpyghNBqrr6k5L/uKBGRsTfxmu3ffiRnd8mlGPUVayg8pvfi5urfnu8TU7DVOkLQ==, - } + resolution: {integrity: sha512-BiZS+C1OS8g/q2RRbJmy59xpyghNBqrr6k5L/uKBGRsTfxmu3ffiRnd8mlGPUVayg8pvfi5urfnu8TU7DVOkLQ==} tough-cookie@5.1.2: - resolution: - { - integrity: sha512-FVDYdxtnj0G6Qm/DhNPSb8Ju59ULcup3tuJxkFb5K8Bv2pUXILbf0xZWU8PX8Ov19OXljbUyveOFwRMwkXzO+A==, - } - engines: { node: ">=16" } + resolution: {integrity: sha512-FVDYdxtnj0G6Qm/DhNPSb8Ju59ULcup3tuJxkFb5K8Bv2pUXILbf0xZWU8PX8Ov19OXljbUyveOFwRMwkXzO+A==} + engines: {node: '>=16'} tr46@0.0.3: - resolution: - { - integrity: sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==, - } + resolution: {integrity: sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==} tr46@5.1.1: - resolution: - { - integrity: sha512-hdF5ZgjTqgAntKkklYw0R03MG2x/bSzTtkxmIRw/sTNV8YXsCJ1tfLAX23lhxhHJlEf3CRCOCGGWw3vI3GaSPw==, - } - engines: { node: ">=18" } + resolution: {integrity: sha512-hdF5ZgjTqgAntKkklYw0R03MG2x/bSzTtkxmIRw/sTNV8YXsCJ1tfLAX23lhxhHJlEf3CRCOCGGWw3vI3GaSPw==} + engines: {node: '>=18'} ts-api-utils@2.5.0: - resolution: - { - integrity: sha512-OJ/ibxhPlqrMM0UiNHJ/0CKQkoKF243/AEmplt3qpRgkW8VG7IfOS41h7V8TjITqdByHzrjcS/2si+y4lIh8NA==, - } - engines: { node: ">=18.12" } + resolution: {integrity: sha512-OJ/ibxhPlqrMM0UiNHJ/0CKQkoKF243/AEmplt3qpRgkW8VG7IfOS41h7V8TjITqdByHzrjcS/2si+y4lIh8NA==} + engines: {node: '>=18.12'} peerDependencies: - typescript: ">=4.8.4" + typescript: '>=4.8.4' ts-dedent@2.2.0: - resolution: - { - integrity: sha512-q5W7tVM71e2xjHZTlgfTDoPF/SmqKG5hddq9SzR49CH2hayqRKJtQ4mtRlSxKaJlR/+9rEM+mnBHf7I2/BQcpQ==, - } - engines: { node: ">=6.10" } + resolution: {integrity: sha512-q5W7tVM71e2xjHZTlgfTDoPF/SmqKG5hddq9SzR49CH2hayqRKJtQ4mtRlSxKaJlR/+9rEM+mnBHf7I2/BQcpQ==} + engines: {node: '>=6.10'} tsconfig-paths@3.15.0: - resolution: - { - integrity: sha512-2Ac2RgzDe/cn48GvOe3M+o82pEFewD3UPbyoUHHdKasHwJKjds4fLXWf/Ux5kATBKN20oaFGu+jbElp1pos0mg==, - } + resolution: {integrity: sha512-2Ac2RgzDe/cn48GvOe3M+o82pEFewD3UPbyoUHHdKasHwJKjds4fLXWf/Ux5kATBKN20oaFGu+jbElp1pos0mg==} tsconfig-paths@4.2.0: - resolution: - { - integrity: sha512-NoZ4roiN7LnbKn9QqE1amc9DJfzvZXxF4xDavcOWt1BPkdx+m+0gJuPM+S0vCe7zTJMYUP0R8pO2XMr+Y8oLIg==, - } - engines: { node: ">=6" } + resolution: {integrity: sha512-NoZ4roiN7LnbKn9QqE1amc9DJfzvZXxF4xDavcOWt1BPkdx+m+0gJuPM+S0vCe7zTJMYUP0R8pO2XMr+Y8oLIg==} + engines: {node: '>=6'} tslib@1.14.1: - resolution: - { - integrity: sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==, - } + resolution: {integrity: sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==} tslib@2.8.1: - resolution: - { - integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==, - } + resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==} tsutils-etc@1.4.2: - resolution: - { - integrity: sha512-2Dn5SxTDOu6YWDNKcx1xu2YUy6PUeKrWZB/x2cQ8vY2+iz3JRembKn/iZ0JLT1ZudGNwQQvtFX9AwvRHbXuPUg==, - } + resolution: {integrity: sha512-2Dn5SxTDOu6YWDNKcx1xu2YUy6PUeKrWZB/x2cQ8vY2+iz3JRembKn/iZ0JLT1ZudGNwQQvtFX9AwvRHbXuPUg==} hasBin: true peerDependencies: tsutils: ^3.0.0 - typescript: ">=4.0.0" + typescript: '>=4.0.0' tsutils@3.21.0: - resolution: - { - integrity: sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==, - } - engines: { node: ">= 6" } + resolution: {integrity: sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==} + engines: {node: '>= 6'} peerDependencies: - typescript: ">=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta" + typescript: '>=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta' tty-browserify@0.0.1: - resolution: - { - integrity: sha512-C3TaO7K81YvjCgQH9Q1S3R3P3BtN3RIM8n+OvX4il1K1zgE8ZhI0op7kClgkxtutIE8hQrcrHBXvIheqKUUCxw==, - } + resolution: {integrity: sha512-C3TaO7K81YvjCgQH9Q1S3R3P3BtN3RIM8n+OvX4il1K1zgE8ZhI0op7kClgkxtutIE8hQrcrHBXvIheqKUUCxw==} tunnel@0.0.6: - resolution: - { - integrity: sha512-1h/Lnq9yajKY2PEbBadPXj3VxsDDu844OnaAo52UVmIzIvwwtBPIuNvkjuzBlTWpfJyUbG3ez0KSBibQkj4ojg==, - } - engines: { node: ">=0.6.11 <=0.7.0 || >=0.7.3" } + resolution: {integrity: sha512-1h/Lnq9yajKY2PEbBadPXj3VxsDDu844OnaAo52UVmIzIvwwtBPIuNvkjuzBlTWpfJyUbG3ez0KSBibQkj4ojg==} + engines: {node: '>=0.6.11 <=0.7.0 || >=0.7.3'} type-check@0.4.0: - resolution: - { - integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==, - } - engines: { node: ">= 0.8.0" } + resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==} + engines: {node: '>= 0.8.0'} type-fest@0.20.2: - resolution: - { - integrity: sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==, - } - engines: { node: ">=10" } + resolution: {integrity: sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==} + engines: {node: '>=10'} type-fest@0.6.0: - resolution: - { - integrity: sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg==, - } - engines: { node: ">=8" } + resolution: {integrity: sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg==} + engines: {node: '>=8'} type-fest@0.8.1: - resolution: - { - integrity: sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==, - } - engines: { node: ">=8" } + resolution: {integrity: sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==} + engines: {node: '>=8'} typed-array-buffer@1.0.3: - resolution: - { - integrity: sha512-nAYYwfY3qnzX30IkA6AQZjVbtK6duGontcQm1WSG1MD94YLqK0515GNApXkoxKOWMusVssAHWLh9SeaoefYFGw==, - } - engines: { node: ">= 0.4" } + resolution: {integrity: sha512-nAYYwfY3qnzX30IkA6AQZjVbtK6duGontcQm1WSG1MD94YLqK0515GNApXkoxKOWMusVssAHWLh9SeaoefYFGw==} + engines: {node: '>= 0.4'} typed-array-byte-length@1.0.3: - resolution: - { - integrity: sha512-BaXgOuIxz8n8pIq3e7Atg/7s+DpiYrxn4vdot3w9KbnBhcRQq6o3xemQdIfynqSeXeDrF32x+WvfzmOjPiY9lg==, - } - engines: { node: ">= 0.4" } + resolution: {integrity: sha512-BaXgOuIxz8n8pIq3e7Atg/7s+DpiYrxn4vdot3w9KbnBhcRQq6o3xemQdIfynqSeXeDrF32x+WvfzmOjPiY9lg==} + engines: {node: '>= 0.4'} typed-array-byte-offset@1.0.4: - resolution: - { - integrity: sha512-bTlAFB/FBYMcuX81gbL4OcpH5PmlFHqlCCpAl8AlEzMz5k53oNDvN8p1PNOWLEmI2x4orp3raOFB51tv9X+MFQ==, - } - engines: { node: ">= 0.4" } + resolution: {integrity: sha512-bTlAFB/FBYMcuX81gbL4OcpH5PmlFHqlCCpAl8AlEzMz5k53oNDvN8p1PNOWLEmI2x4orp3raOFB51tv9X+MFQ==} + engines: {node: '>= 0.4'} typed-array-length@1.0.7: - resolution: - { - integrity: sha512-3KS2b+kL7fsuk/eJZ7EQdnEmQoaho/r6KUef7hxvltNA5DR8NAUM+8wJMbJyZ4G9/7i3v5zPBIMN5aybAh2/Jg==, - } - engines: { node: ">= 0.4" } + resolution: {integrity: sha512-3KS2b+kL7fsuk/eJZ7EQdnEmQoaho/r6KUef7hxvltNA5DR8NAUM+8wJMbJyZ4G9/7i3v5zPBIMN5aybAh2/Jg==} + engines: {node: '>= 0.4'} typed-emitter@2.1.0: - resolution: - { - integrity: sha512-g/KzbYKbH5C2vPkaXGu8DJlHrGKHLsM25Zg9WuC9pMGfuvT+X25tZQWo5fK1BjBm8+UrVE9LDCvaY0CQk+fXDA==, - } + resolution: {integrity: sha512-g/KzbYKbH5C2vPkaXGu8DJlHrGKHLsM25Zg9WuC9pMGfuvT+X25tZQWo5fK1BjBm8+UrVE9LDCvaY0CQk+fXDA==} typescript-eslint-language-service@5.0.5: - resolution: - { - integrity: sha512-b7gWXpwSTqMVKpPX3WttNZEyVAMKs/2jsHKF79H+qaD6mjzCyU5jboJe/lOZgLJD+QRsXCr0GjIVxvl5kI1NMw==, - } + resolution: {integrity: sha512-b7gWXpwSTqMVKpPX3WttNZEyVAMKs/2jsHKF79H+qaD6mjzCyU5jboJe/lOZgLJD+QRsXCr0GjIVxvl5kI1NMw==} peerDependencies: - "@typescript-eslint/parser": ">= 5.0.0" - eslint: ">= 8.0.0" - typescript: ">= 4.0.0" + '@typescript-eslint/parser': '>= 5.0.0' + eslint: '>= 8.0.0' + typescript: '>= 4.0.0' typescript@5.9.3: - resolution: - { - integrity: sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==, - } - engines: { node: ">=14.17" } + resolution: {integrity: sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==} + engines: {node: '>=14.17'} hasBin: true unbash@2.2.0: - resolution: - { - integrity: sha512-X2wH19RAPZE3+ldGicOkoj/SIA83OIxcJ6Cuaw23hf8Xc6fQpvZXY0SftE2JgS0QhYLUG4uwodSI3R53keyh7w==, - } - engines: { node: ">=14" } + resolution: {integrity: sha512-X2wH19RAPZE3+ldGicOkoj/SIA83OIxcJ6Cuaw23hf8Xc6fQpvZXY0SftE2JgS0QhYLUG4uwodSI3R53keyh7w==} + engines: {node: '>=14'} unbox-primitive@1.1.0: - resolution: - { - integrity: sha512-nWJ91DjeOkej/TA8pXQ3myruKpKEYgqvpw9lz4OPHj/NWFNluYrjbz9j01CJ8yKQd2g4jFoOkINCTW2I5LEEyw==, - } - engines: { node: ">= 0.4" } + resolution: {integrity: sha512-nWJ91DjeOkej/TA8pXQ3myruKpKEYgqvpw9lz4OPHj/NWFNluYrjbz9j01CJ8yKQd2g4jFoOkINCTW2I5LEEyw==} + engines: {node: '>= 0.4'} underscore.string@3.3.6: - resolution: - { - integrity: sha512-VoC83HWXmCrF6rgkyxS9GHv8W9Q5nhMKho+OadDJGzL2oDYbYEppBaCMH6pFlwLeqj2QS+hhkw2kpXkSdD1JxQ==, - } + resolution: {integrity: sha512-VoC83HWXmCrF6rgkyxS9GHv8W9Q5nhMKho+OadDJGzL2oDYbYEppBaCMH6pFlwLeqj2QS+hhkw2kpXkSdD1JxQ==} undici-types@7.16.0: - resolution: - { - integrity: sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw==, - } + resolution: {integrity: sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw==} undici@5.29.0: - resolution: - { - integrity: sha512-raqeBD6NQK4SkWhQzeYKd1KmIG6dllBOTt55Rmkt4HtI9mwdWtJljnrXjAFUBLTSN67HWrOIZ3EPF4kjUw80Bg==, - } - engines: { node: ">=14.0" } + resolution: {integrity: sha512-raqeBD6NQK4SkWhQzeYKd1KmIG6dllBOTt55Rmkt4HtI9mwdWtJljnrXjAFUBLTSN67HWrOIZ3EPF4kjUw80Bg==} + engines: {node: '>=14.0'} undici@7.25.0: - resolution: - { - integrity: sha512-xXnp4kTyor2Zq+J1FfPI6Eq3ew5h6Vl0F/8d9XU5zZQf1tX9s2Su1/3PiMmUANFULpmksxkClamIZcaUqryHsQ==, - } - engines: { node: ">=20.18.1" } + resolution: {integrity: sha512-xXnp4kTyor2Zq+J1FfPI6Eq3ew5h6Vl0F/8d9XU5zZQf1tX9s2Su1/3PiMmUANFULpmksxkClamIZcaUqryHsQ==} + engines: {node: '>=20.18.1'} unhomoglyph@1.0.6: - resolution: - { - integrity: sha512-7uvcWI3hWshSADBu4JpnyYbTVc7YlhF5GDW/oPD5AxIxl34k4wXR3WDkPnzLxkN32LiTCTKMQLtKVZiwki3zGg==, - } + resolution: {integrity: sha512-7uvcWI3hWshSADBu4JpnyYbTVc7YlhF5GDW/oPD5AxIxl34k4wXR3WDkPnzLxkN32LiTCTKMQLtKVZiwki3zGg==} unicode-canonical-property-names-ecmascript@2.0.1: - resolution: - { - integrity: sha512-dA8WbNeb2a6oQzAQ55YlT5vQAWGV9WXOsi3SskE3bcCdM0P4SDd+24zS/OCacdRq5BkdsRj9q3Pg6YyQoxIGqg==, - } - engines: { node: ">=4" } + resolution: {integrity: sha512-dA8WbNeb2a6oQzAQ55YlT5vQAWGV9WXOsi3SskE3bcCdM0P4SDd+24zS/OCacdRq5BkdsRj9q3Pg6YyQoxIGqg==} + engines: {node: '>=4'} unicode-match-property-ecmascript@2.0.0: - resolution: - { - integrity: sha512-5kaZCrbp5mmbz5ulBkDkbY0SsPOjKqVS35VpL9ulMPfSl0J0Xsm+9Evphv9CoIZFwre7aJoa94AY6seMKGVN5Q==, - } - engines: { node: ">=4" } + resolution: {integrity: sha512-5kaZCrbp5mmbz5ulBkDkbY0SsPOjKqVS35VpL9ulMPfSl0J0Xsm+9Evphv9CoIZFwre7aJoa94AY6seMKGVN5Q==} + engines: {node: '>=4'} unicode-match-property-value-ecmascript@2.2.1: - resolution: - { - integrity: sha512-JQ84qTuMg4nVkx8ga4A16a1epI9H6uTXAknqxkGF/aFfRLw1xC/Bp24HNLaZhHSkWd3+84t8iXnp1J0kYcZHhg==, - } - engines: { node: ">=4" } + resolution: {integrity: sha512-JQ84qTuMg4nVkx8ga4A16a1epI9H6uTXAknqxkGF/aFfRLw1xC/Bp24HNLaZhHSkWd3+84t8iXnp1J0kYcZHhg==} + engines: {node: '>=4'} unicode-property-aliases-ecmascript@2.2.0: - resolution: - { - integrity: sha512-hpbDzxUY9BFwX+UeBnxv3Sh1q7HFxj48DTmXchNgRa46lO8uj3/1iEn3MiNUYTg1g9ctIqXCCERn8gYZhHC5lQ==, - } - engines: { node: ">=4" } + resolution: {integrity: sha512-hpbDzxUY9BFwX+UeBnxv3Sh1q7HFxj48DTmXchNgRa46lO8uj3/1iEn3MiNUYTg1g9ctIqXCCERn8gYZhHC5lQ==} + engines: {node: '>=4'} unique-names-generator@4.7.1: - resolution: - { - integrity: sha512-lMx9dX+KRmG8sq6gulYYpKWZc9RlGsgBR6aoO8Qsm3qvkSJ+3rAymr+TnV8EDMrIrwuFJ4kruzMWM/OpYzPoow==, - } - engines: { node: ">=8" } + resolution: {integrity: sha512-lMx9dX+KRmG8sq6gulYYpKWZc9RlGsgBR6aoO8Qsm3qvkSJ+3rAymr+TnV8EDMrIrwuFJ4kruzMWM/OpYzPoow==} + engines: {node: '>=8'} universal-user-agent@6.0.1: - resolution: - { - integrity: sha512-yCzhz6FN2wU1NiiQRogkTQszlQSlpWaw8SvVegAc+bDxbzHgh1vX8uIe8OYyMH6DwH+sdTJsgMl36+mSMdRJIQ==, - } + resolution: {integrity: sha512-yCzhz6FN2wU1NiiQRogkTQszlQSlpWaw8SvVegAc+bDxbzHgh1vX8uIe8OYyMH6DwH+sdTJsgMl36+mSMdRJIQ==} universalify@0.1.2: - resolution: - { - integrity: sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==, - } - engines: { node: ">= 4.0.0" } + resolution: {integrity: sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==} + engines: {node: '>= 4.0.0'} universalify@2.0.1: - resolution: - { - integrity: sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==, - } - engines: { node: ">= 10.0.0" } + resolution: {integrity: sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==} + engines: {node: '>= 10.0.0'} unplugin@1.0.1: - resolution: - { - integrity: sha512-aqrHaVBWW1JVKBHmGo33T5TxeL0qWzfvjWokObHA9bYmN7eNDkwOxmLjhioHl9878qDFMAaT51XNroRyuz7WxA==, - } + resolution: {integrity: sha512-aqrHaVBWW1JVKBHmGo33T5TxeL0qWzfvjWokObHA9bYmN7eNDkwOxmLjhioHl9878qDFMAaT51XNroRyuz7WxA==} unplugin@1.16.1: - resolution: - { - integrity: sha512-4/u/j4FrCKdi17jaxuJA0jClGxB1AvU2hw/IuayPc4ay1XGaJs/rbb4v5WKwAjNifjmXK9PIFyuPiaK8azyR9w==, - } - engines: { node: ">=14.0.0" } + resolution: {integrity: sha512-4/u/j4FrCKdi17jaxuJA0jClGxB1AvU2hw/IuayPc4ay1XGaJs/rbb4v5WKwAjNifjmXK9PIFyuPiaK8azyR9w==} + engines: {node: '>=14.0.0'} unplugin@2.3.11: - resolution: - { - integrity: sha512-5uKD0nqiYVzlmCRs01Fhs2BdkEgBS3SAVP6ndrBsuK42iC2+JHyxM05Rm9G8+5mkmRtzMZGY8Ct5+mliZxU/Ww==, - } - engines: { node: ">=18.12.0" } + resolution: {integrity: sha512-5uKD0nqiYVzlmCRs01Fhs2BdkEgBS3SAVP6ndrBsuK42iC2+JHyxM05Rm9G8+5mkmRtzMZGY8Ct5+mliZxU/Ww==} + engines: {node: '>=18.12.0'} update-browserslist-db@1.2.3: - resolution: - { - integrity: sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w==, - } + resolution: {integrity: sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w==} hasBin: true peerDependencies: - browserslist: ">= 4.21.0" + browserslist: '>= 4.21.0' uri-js@4.4.1: - resolution: - { - integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==, - } + resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==} url@0.11.4: - resolution: - { - integrity: sha512-oCwdVC7mTuWiPyjLUz/COz5TLk6wgp0RCsN+wHZ2Ekneac9w8uuV0njcbbie2ME+Vs+d6duwmYuR3HgQXs1fOg==, - } - engines: { node: ">= 0.4" } + resolution: {integrity: sha512-oCwdVC7mTuWiPyjLUz/COz5TLk6wgp0RCsN+wHZ2Ekneac9w8uuV0njcbbie2ME+Vs+d6duwmYuR3HgQXs1fOg==} + engines: {node: '>= 0.4'} use-callback-ref@1.3.3: - resolution: - { - integrity: sha512-jQL3lRnocaFtu3V00JToYz/4QkNWswxijDaCVNZRiRTO3HQDLsdu1ZtmIUvV4yPp+rvWm5j0y0TG/S61cuijTg==, - } - engines: { node: ">=10" } + resolution: {integrity: sha512-jQL3lRnocaFtu3V00JToYz/4QkNWswxijDaCVNZRiRTO3HQDLsdu1ZtmIUvV4yPp+rvWm5j0y0TG/S61cuijTg==} + engines: {node: '>=10'} peerDependencies: - "@types/react": "*" + '@types/react': '*' react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc peerDependenciesMeta: - "@types/react": + '@types/react': optional: true use-sidecar@1.1.3: - resolution: - { - integrity: sha512-Fedw0aZvkhynoPYlA5WXrMCAMm+nSWdZt6lzJQ7Ok8S6Q+VsHmHpRWndVRJ8Be0ZbkfPc5LRYH+5XrzXcEeLRQ==, - } - engines: { node: ">=10" } + resolution: {integrity: sha512-Fedw0aZvkhynoPYlA5WXrMCAMm+nSWdZt6lzJQ7Ok8S6Q+VsHmHpRWndVRJ8Be0ZbkfPc5LRYH+5XrzXcEeLRQ==} + engines: {node: '>=10'} peerDependencies: - "@types/react": "*" + '@types/react': '*' react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc peerDependenciesMeta: - "@types/react": + '@types/react': optional: true use-sync-external-store@1.6.0: - resolution: - { - integrity: sha512-Pp6GSwGP/NrPIrxVFAIkOQeyw8lFenOHijQWkUTrDvrF4ALqylP2C/KCkeS9dpUM3KvYRQhna5vt7IL95+ZQ9w==, - } + resolution: {integrity: sha512-Pp6GSwGP/NrPIrxVFAIkOQeyw8lFenOHijQWkUTrDvrF4ALqylP2C/KCkeS9dpUM3KvYRQhna5vt7IL95+ZQ9w==} peerDependencies: react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 usehooks-ts@3.1.1: - resolution: - { - integrity: sha512-I4diPp9Cq6ieSUH2wu+fDAVQO43xwtulo+fKEidHUwZPnYImbtkTjzIJYcDcJqxgmX31GVqNFURodvcgHcW0pA==, - } - engines: { node: ">=16.15.0" } + resolution: {integrity: sha512-I4diPp9Cq6ieSUH2wu+fDAVQO43xwtulo+fKEidHUwZPnYImbtkTjzIJYcDcJqxgmX31GVqNFURodvcgHcW0pA==} + engines: {node: '>=16.15.0'} peerDependencies: react: ^16.8.0 || ^17 || ^18 || ^19 || ^19.0.0-rc util-deprecate@1.0.2: - resolution: - { - integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==, - } + resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} util@0.12.5: - resolution: - { - integrity: sha512-kZf/K6hEIrWHI6XqOFUiiMa+79wE/D8Q+NCNAWclkyg3b4d2k7s0QGepNjiABc+aR3N1PAyHL7p6UcLY6LmrnA==, - } + resolution: {integrity: sha512-kZf/K6hEIrWHI6XqOFUiiMa+79wE/D8Q+NCNAWclkyg3b4d2k7s0QGepNjiABc+aR3N1PAyHL7p6UcLY6LmrnA==} uuid@13.0.0: - resolution: - { - integrity: sha512-XQegIaBTVUjSHliKqcnFqYypAd4S+WCYt5NIeRs6w/UAry7z8Y9j5ZwRRL4kzq9U3sD6v+85er9FvkEaBpji2w==, - } + resolution: {integrity: sha512-XQegIaBTVUjSHliKqcnFqYypAd4S+WCYt5NIeRs6w/UAry7z8Y9j5ZwRRL4kzq9U3sD6v+85er9FvkEaBpji2w==} hasBin: true validate-npm-package-license@3.0.4: - resolution: - { - integrity: sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==, - } + resolution: {integrity: sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==} value-or-function@4.0.0: - resolution: - { - integrity: sha512-aeVK81SIuT6aMJfNo9Vte8Dw0/FZINGBV8BfCraGtqVxIeLAEhJyoWs8SmvRVmXfGss2PmmOwZCuBPbZR+IYWg==, - } - engines: { node: ">= 10.13.0" } + resolution: {integrity: sha512-aeVK81SIuT6aMJfNo9Vte8Dw0/FZINGBV8BfCraGtqVxIeLAEhJyoWs8SmvRVmXfGss2PmmOwZCuBPbZR+IYWg==} + engines: {node: '>= 10.13.0'} vaul@1.1.2: - resolution: - { - integrity: sha512-ZFkClGpWyI2WUQjdLJ/BaGuV6AVQiJ3uELGk3OYtP+B6yCO7Cmn9vPFXVJkRaGkOJu3m8bQMgtyzNHixULceQA==, - } + resolution: {integrity: sha512-ZFkClGpWyI2WUQjdLJ/BaGuV6AVQiJ3uELGk3OYtP+B6yCO7Cmn9vPFXVJkRaGkOJu3m8bQMgtyzNHixULceQA==} peerDependencies: react: ^16.8 || ^17.0 || ^18.0 || ^19.0.0 || ^19.0.0-rc react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0.0 || ^19.0.0-rc vinyl-contents@2.0.0: - resolution: - { - integrity: sha512-cHq6NnGyi2pZ7xwdHSW1v4Jfnho4TEGtxZHw01cmnc8+i7jgR6bRnED/LbrKan/Q7CvVLbnvA5OepnhbpjBZ5Q==, - } - engines: { node: ">=10.13.0" } + resolution: {integrity: sha512-cHq6NnGyi2pZ7xwdHSW1v4Jfnho4TEGtxZHw01cmnc8+i7jgR6bRnED/LbrKan/Q7CvVLbnvA5OepnhbpjBZ5Q==} + engines: {node: '>=10.13.0'} vinyl-fs@4.0.2: - resolution: - { - integrity: sha512-XRFwBLLTl8lRAOYiBqxY279wY46tVxLaRhSwo3GzKEuLz1giffsOquWWboD/haGf5lx+JyTigCFfe7DWHoARIA==, - } - engines: { node: ">=10.13.0" } + resolution: {integrity: sha512-XRFwBLLTl8lRAOYiBqxY279wY46tVxLaRhSwo3GzKEuLz1giffsOquWWboD/haGf5lx+JyTigCFfe7DWHoARIA==} + engines: {node: '>=10.13.0'} vinyl-sourcemap@2.0.0: - resolution: - { - integrity: sha512-BAEvWxbBUXvlNoFQVFVHpybBbjW1r03WhohJzJDSfgrrK5xVYIDTan6xN14DlyImShgDRv2gl9qhM6irVMsV0Q==, - } - engines: { node: ">=10.13.0" } + resolution: {integrity: sha512-BAEvWxbBUXvlNoFQVFVHpybBbjW1r03WhohJzJDSfgrrK5xVYIDTan6xN14DlyImShgDRv2gl9qhM6irVMsV0Q==} + engines: {node: '>=10.13.0'} vinyl@3.0.1: - resolution: - { - integrity: sha512-0QwqXteBNXgnLCdWdvPQBX6FXRHtIH3VhJPTd5Lwn28tJXc34YqSCWUmkOvtJHBmB3gGoPtrOKk3Ts8/kEZ9aA==, - } - engines: { node: ">=10.13.0" } + resolution: {integrity: sha512-0QwqXteBNXgnLCdWdvPQBX6FXRHtIH3VhJPTd5Lwn28tJXc34YqSCWUmkOvtJHBmB3gGoPtrOKk3Ts8/kEZ9aA==} + engines: {node: '>=10.13.0'} vite-plugin-generate-file@0.3.1: - resolution: - { - integrity: sha512-tiA3gkPM21MS2+RyqsBMT33GSlM9LM1TJjf6vGvV/e/ml3e3vTKfuH3l2N0NpUgcayvj1fXnmlo5YBuahA6bsg==, - } + resolution: {integrity: sha512-tiA3gkPM21MS2+RyqsBMT33GSlM9LM1TJjf6vGvV/e/ml3e3vTKfuH3l2N0NpUgcayvj1fXnmlo5YBuahA6bsg==} vite-plugin-html@3.2.2: - resolution: - { - integrity: sha512-vb9C9kcdzcIo/Oc3CLZVS03dL5pDlOFuhGlZYDCJ840BhWl/0nGeZWf3Qy7NlOayscY4Cm/QRgULCQkEZige5Q==, - } + resolution: {integrity: sha512-vb9C9kcdzcIo/Oc3CLZVS03dL5pDlOFuhGlZYDCJ840BhWl/0nGeZWf3Qy7NlOayscY4Cm/QRgULCQkEZige5Q==} peerDependencies: - vite: ">=2.0.0" + vite: '>=2.0.0' + + vite-plugin-node-polyfills@0.26.0: + resolution: {integrity: sha512-BAe5YzJf368XGev02hDvioidx4uVH8dqEJlG73bjQSxM26/AQnGcKFomq9n3vGq5yqpSHKN4h1XQNxx9l98mBg==} + peerDependencies: + vite: ^2.0.0 || ^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0 vite-plugin-node-stdlib-browser@0.2.1: - resolution: - { - integrity: sha512-6u2i613Dkqj5KaTNIrnZvE6y3/awWAp0S5TjucTvGxdhetftB1Mgvblc+nwYzlw6sntPlac8UOC7ttXNh+LZKA==, - } + resolution: {integrity: sha512-6u2i613Dkqj5KaTNIrnZvE6y3/awWAp0S5TjucTvGxdhetftB1Mgvblc+nwYzlw6sntPlac8UOC7ttXNh+LZKA==} peerDependencies: node-stdlib-browser: ^1.2.0 vite: ^2.0.0 || ^3.0.0 || ^4.0.0 vite-plugin-svgr@4.5.0: - resolution: - { - integrity: sha512-W+uoSpmVkSmNOGPSsDCWVW/DDAyv+9fap9AZXBvWiQqrboJ08j2vh0tFxTD/LjwqwAd3yYSVJgm54S/1GhbdnA==, - } + resolution: {integrity: sha512-W+uoSpmVkSmNOGPSsDCWVW/DDAyv+9fap9AZXBvWiQqrboJ08j2vh0tFxTD/LjwqwAd3yYSVJgm54S/1GhbdnA==} peerDependencies: - vite: ">=2.6.0" + vite: '>=2.6.0' + + vite-plugin-wasm@3.6.0: + resolution: {integrity: sha512-mL/QPziiIA4RAA6DkaZZzOstdwbW5jO4Vz7Zenj0wieKWBlNvIvX5L5ljum9lcUX0ShNfBgCNLKTjNkRVVqcsw==} + peerDependencies: + vite: ^2 || ^3 || ^4 || ^5 || ^6 || ^7 || ^8 vite@8.0.8: - resolution: - { - integrity: sha512-dbU7/iLVa8KZALJyLOBOQ88nOXtNG8vxKuOT4I2mD+Ya70KPceF4IAmDsmU0h1Qsn5bPrvsY9HJstCRh3hG6Uw==, - } - engines: { node: ^20.19.0 || >=22.12.0 } + resolution: {integrity: sha512-dbU7/iLVa8KZALJyLOBOQ88nOXtNG8vxKuOT4I2mD+Ya70KPceF4IAmDsmU0h1Qsn5bPrvsY9HJstCRh3hG6Uw==} + engines: {node: ^20.19.0 || >=22.12.0} hasBin: true peerDependencies: - "@types/node": ^20.19.0 || >=22.12.0 - "@vitejs/devtools": ^0.1.0 + '@types/node': ^20.19.0 || >=22.12.0 + '@vitejs/devtools': ^0.1.0 esbuild: ^0.27.7 - jiti: ">=1.21.0" + jiti: '>=1.21.0' less: ^4.0.0 sass: ^1.70.0 sass-embedded: ^1.70.0 - stylus: ">=0.54.8" + stylus: '>=0.54.8' sugarss: ^5.0.0 terser: ^5.16.0 tsx: ^4.8.1 yaml: ^2.4.2 peerDependenciesMeta: - "@types/node": + '@types/node': optional: true - "@vitejs/devtools": + '@vitejs/devtools': optional: true esbuild: optional: true @@ -10203,51 +6490,45 @@ packages: optional: true vitest-axe@1.0.0-pre.5: - resolution: - { - integrity: sha512-eUGxjpXnceha9lkqIVyMgOUeDmWU9LVjNiLTjAjDtMew0WbaBDtixoUvdftOhZfqRI03G2Ay4ZxaU1KG6jNCiQ==, - } + resolution: {integrity: sha512-eUGxjpXnceha9lkqIVyMgOUeDmWU9LVjNiLTjAjDtMew0WbaBDtixoUvdftOhZfqRI03G2Ay4ZxaU1KG6jNCiQ==} peerDependencies: - vitest: ">=1" + vitest: '>=1' vitest@4.1.4: - resolution: - { - integrity: sha512-tFuJqTxKb8AvfyqMfnavXdzfy3h3sWZRWwfluGbkeR7n0HUev+FmNgZ8SDrRBTVrVCjgH5cA21qGbCffMNtWvg==, - } - engines: { node: ^20.0.0 || ^22.0.0 || >=24.0.0 } + resolution: {integrity: sha512-tFuJqTxKb8AvfyqMfnavXdzfy3h3sWZRWwfluGbkeR7n0HUev+FmNgZ8SDrRBTVrVCjgH5cA21qGbCffMNtWvg==} + engines: {node: ^20.0.0 || ^22.0.0 || >=24.0.0} hasBin: true peerDependencies: - "@edge-runtime/vm": "*" - "@opentelemetry/api": ^1.9.0 - "@types/node": ^20.0.0 || ^22.0.0 || >=24.0.0 - "@vitest/browser-playwright": 4.1.4 - "@vitest/browser-preview": 4.1.4 - "@vitest/browser-webdriverio": 4.1.4 - "@vitest/coverage-istanbul": 4.1.4 - "@vitest/coverage-v8": 4.1.4 - "@vitest/ui": 4.1.4 - happy-dom: "*" - jsdom: "*" + '@edge-runtime/vm': '*' + '@opentelemetry/api': ^1.9.0 + '@types/node': ^20.0.0 || ^22.0.0 || >=24.0.0 + '@vitest/browser-playwright': 4.1.4 + '@vitest/browser-preview': 4.1.4 + '@vitest/browser-webdriverio': 4.1.4 + '@vitest/coverage-istanbul': 4.1.4 + '@vitest/coverage-v8': 4.1.4 + '@vitest/ui': 4.1.4 + happy-dom: '*' + jsdom: '*' vite: ^6.0.0 || ^7.0.0 || ^8.0.0 peerDependenciesMeta: - "@edge-runtime/vm": + '@edge-runtime/vm': optional: true - "@opentelemetry/api": + '@opentelemetry/api': optional: true - "@types/node": + '@types/node': optional: true - "@vitest/browser-playwright": + '@vitest/browser-playwright': optional: true - "@vitest/browser-preview": + '@vitest/browser-preview': optional: true - "@vitest/browser-webdriverio": + '@vitest/browser-webdriverio': optional: true - "@vitest/coverage-istanbul": + '@vitest/coverage-istanbul': optional: true - "@vitest/coverage-v8": + '@vitest/coverage-v8': optional: true - "@vitest/ui": + '@vitest/ui': optional: true happy-dom: optional: true @@ -10255,205 +6536,118 @@ packages: optional: true vm-browserify@1.1.2: - resolution: - { - integrity: sha512-2ham8XPWTONajOR0ohOKOHXkm3+gaBmGut3SRuu75xLd/RRaY6vqgh8NBYYk7+RW3u5AtzPQZG8F10LHkl0lAQ==, - } + resolution: {integrity: sha512-2ham8XPWTONajOR0ohOKOHXkm3+gaBmGut3SRuu75xLd/RRaY6vqgh8NBYYk7+RW3u5AtzPQZG8F10LHkl0lAQ==} void-elements@3.1.0: - resolution: - { - integrity: sha512-Dhxzh5HZuiHQhbvTW9AMetFfBHDMYpo23Uo9btPXgdYP+3T5S+p+jgNy7spra+veYhBP2dCSgxR/i2Y02h5/6w==, - } - engines: { node: ">=0.10.0" } + resolution: {integrity: sha512-Dhxzh5HZuiHQhbvTW9AMetFfBHDMYpo23Uo9btPXgdYP+3T5S+p+jgNy7spra+veYhBP2dCSgxR/i2Y02h5/6w==} + engines: {node: '>=0.10.0'} w3c-xmlserializer@5.0.0: - resolution: - { - integrity: sha512-o8qghlI8NZHU1lLPrpi2+Uq7abh4GGPpYANlalzWxyWteJOCsr/P+oPBA49TOLu5FTZO4d3F9MnWJfiMo4BkmA==, - } - engines: { node: ">=18" } + resolution: {integrity: sha512-o8qghlI8NZHU1lLPrpi2+Uq7abh4GGPpYANlalzWxyWteJOCsr/P+oPBA49TOLu5FTZO4d3F9MnWJfiMo4BkmA==} + engines: {node: '>=18'} walk-sync@2.2.0: - resolution: - { - integrity: sha512-IC8sL7aB4/ZgFcGI2T1LczZeFWZ06b3zoHH7jBPyHxOtIIz1jppWHjjEXkOFvFojBVAK9pV7g47xOZ4LW3QLfg==, - } - engines: { node: 8.* || >= 10.* } + resolution: {integrity: sha512-IC8sL7aB4/ZgFcGI2T1LczZeFWZ06b3zoHH7jBPyHxOtIIz1jppWHjjEXkOFvFojBVAK9pV7g47xOZ4LW3QLfg==} + engines: {node: 8.* || >= 10.*} walk-up-path@4.0.0: - resolution: - { - integrity: sha512-3hu+tD8YzSLGuFYtPRb48vdhKMi0KQV5sn+uWr8+7dMEq/2G/dtLrdDinkLjqq5TIbIBjYJ4Ax/n3YiaW7QM8A==, - } - engines: { node: 20 || >=22 } + resolution: {integrity: sha512-3hu+tD8YzSLGuFYtPRb48vdhKMi0KQV5sn+uWr8+7dMEq/2G/dtLrdDinkLjqq5TIbIBjYJ4Ax/n3YiaW7QM8A==} + engines: {node: 20 || >=22} web-vitals@4.2.4: - resolution: - { - integrity: sha512-r4DIlprAGwJ7YM11VZp4R884m0Vmgr6EAKe3P+kO0PPj3Unqyvv59rczf6UiGcb9Z8QxZVcqKNwv/g0WNdWwsw==, - } + resolution: {integrity: sha512-r4DIlprAGwJ7YM11VZp4R884m0Vmgr6EAKe3P+kO0PPj3Unqyvv59rczf6UiGcb9Z8QxZVcqKNwv/g0WNdWwsw==} webidl-conversions@3.0.1: - resolution: - { - integrity: sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==, - } + resolution: {integrity: sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==} webidl-conversions@7.0.0: - resolution: - { - integrity: sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==, - } - engines: { node: ">=12" } + resolution: {integrity: sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==} + engines: {node: '>=12'} webpack-sources@3.3.4: - resolution: - { - integrity: sha512-7tP1PdV4vF+lYPnkMR0jMY5/la2ub5Fc/8VQrrU+lXkiM6C4TjVfGw7iKfyhnTQOsD+6Q/iKw0eFciziRgD58Q==, - } - engines: { node: ">=10.13.0" } + resolution: {integrity: sha512-7tP1PdV4vF+lYPnkMR0jMY5/la2ub5Fc/8VQrrU+lXkiM6C4TjVfGw7iKfyhnTQOsD+6Q/iKw0eFciziRgD58Q==} + engines: {node: '>=10.13.0'} webpack-virtual-modules@0.5.0: - resolution: - { - integrity: sha512-kyDivFZ7ZM0BVOUteVbDFhlRt7Ah/CSPwJdi8hBpkK7QLumUqdLtVfm/PX/hkcnrvr0i77fO5+TjZ94Pe+C9iw==, - } + resolution: {integrity: sha512-kyDivFZ7ZM0BVOUteVbDFhlRt7Ah/CSPwJdi8hBpkK7QLumUqdLtVfm/PX/hkcnrvr0i77fO5+TjZ94Pe+C9iw==} webpack-virtual-modules@0.6.2: - resolution: - { - integrity: sha512-66/V2i5hQanC51vBQKPH4aI8NMAcBW59FVBs+rC7eGHupMyfn34q7rZIE+ETlJ+XTevqfUhVVBgSUNSW2flEUQ==, - } + resolution: {integrity: sha512-66/V2i5hQanC51vBQKPH4aI8NMAcBW59FVBs+rC7eGHupMyfn34q7rZIE+ETlJ+XTevqfUhVVBgSUNSW2flEUQ==} webrtc-adapter@9.0.4: - resolution: - { - integrity: sha512-5ZZY1+lGq8LEKuDlg9M2RPJHlH3R7OVwyHqMcUsLKCgd9Wvf+QrFTCItkXXYPmrJn8H6gRLXbSgxLLdexiqHxw==, - } - engines: { node: ">=6.0.0", npm: ">=3.10.0" } + resolution: {integrity: sha512-5ZZY1+lGq8LEKuDlg9M2RPJHlH3R7OVwyHqMcUsLKCgd9Wvf+QrFTCItkXXYPmrJn8H6gRLXbSgxLLdexiqHxw==} + engines: {node: '>=6.0.0', npm: '>=3.10.0'} whatwg-encoding@3.1.1: - resolution: - { - integrity: sha512-6qN4hJdMwfYBtE3YBTTHhoeuUrDBPZmbQaxWAqSALV/MeEnR5z1xd8UKud2RAkFoPkmB+hli1TZSnyi84xz1vQ==, - } - engines: { node: ">=18" } + resolution: {integrity: sha512-6qN4hJdMwfYBtE3YBTTHhoeuUrDBPZmbQaxWAqSALV/MeEnR5z1xd8UKud2RAkFoPkmB+hli1TZSnyi84xz1vQ==} + engines: {node: '>=18'} deprecated: Use @exodus/bytes instead for a more spec-conformant and faster implementation whatwg-mimetype@4.0.0: - resolution: - { - integrity: sha512-QaKxh0eNIi2mE9p2vEdzfagOKHCcj1pJ56EEHGQOVxp8r9/iszLUUV7v89x9O1p/T+NlTM5W7jW6+cz4Fq1YVg==, - } - engines: { node: ">=18" } + resolution: {integrity: sha512-QaKxh0eNIi2mE9p2vEdzfagOKHCcj1pJ56EEHGQOVxp8r9/iszLUUV7v89x9O1p/T+NlTM5W7jW6+cz4Fq1YVg==} + engines: {node: '>=18'} whatwg-url@14.2.0: - resolution: - { - integrity: sha512-De72GdQZzNTUBBChsXueQUnPKDkg/5A5zp7pFDuQAj5UFoENpiACU0wlCvzpAGnTkj++ihpKwKyYewn/XNUbKw==, - } - engines: { node: ">=18" } + resolution: {integrity: sha512-De72GdQZzNTUBBChsXueQUnPKDkg/5A5zp7pFDuQAj5UFoENpiACU0wlCvzpAGnTkj++ihpKwKyYewn/XNUbKw==} + engines: {node: '>=18'} whatwg-url@5.0.0: - resolution: - { - integrity: sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==, - } + resolution: {integrity: sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==} which-boxed-primitive@1.1.1: - resolution: - { - integrity: sha512-TbX3mj8n0odCBFVlY8AxkqcHASw3L60jIuF8jFP78az3C2YhmGvqbHBpAjTRH2/xqYunrJ9g1jSyjCjpoWzIAA==, - } - engines: { node: ">= 0.4" } + resolution: {integrity: sha512-TbX3mj8n0odCBFVlY8AxkqcHASw3L60jIuF8jFP78az3C2YhmGvqbHBpAjTRH2/xqYunrJ9g1jSyjCjpoWzIAA==} + engines: {node: '>= 0.4'} which-builtin-type@1.2.1: - resolution: - { - integrity: sha512-6iBczoX+kDQ7a3+YJBnh3T+KZRxM/iYNPXicqk66/Qfm1b93iu+yOImkg0zHbj5LNOcNv1TEADiZ0xa34B4q6Q==, - } - engines: { node: ">= 0.4" } + resolution: {integrity: sha512-6iBczoX+kDQ7a3+YJBnh3T+KZRxM/iYNPXicqk66/Qfm1b93iu+yOImkg0zHbj5LNOcNv1TEADiZ0xa34B4q6Q==} + engines: {node: '>= 0.4'} which-collection@1.0.2: - resolution: - { - integrity: sha512-K4jVyjnBdgvc86Y6BkaLZEN933SwYOuBFkdmBu9ZfkcAbdVbpITnDmjvZ/aQjRXQrv5EPkTnD1s39GiiqbngCw==, - } - engines: { node: ">= 0.4" } + resolution: {integrity: sha512-K4jVyjnBdgvc86Y6BkaLZEN933SwYOuBFkdmBu9ZfkcAbdVbpITnDmjvZ/aQjRXQrv5EPkTnD1s39GiiqbngCw==} + engines: {node: '>= 0.4'} which-module@2.0.1: - resolution: - { - integrity: sha512-iBdZ57RDvnOR9AGBhML2vFZf7h8vmBjhoaZqODJBFWHVtKkDmKuHai3cx5PgVMrX5YDNp27AofYbAwctSS+vhQ==, - } + resolution: {integrity: sha512-iBdZ57RDvnOR9AGBhML2vFZf7h8vmBjhoaZqODJBFWHVtKkDmKuHai3cx5PgVMrX5YDNp27AofYbAwctSS+vhQ==} which-typed-array@1.1.20: - resolution: - { - integrity: sha512-LYfpUkmqwl0h9A2HL09Mms427Q1RZWuOHsukfVcKRq9q95iQxdw0ix1JQrqbcDR9PH1QDwf5Qo8OZb5lksZ8Xg==, - } - engines: { node: ">= 0.4" } + resolution: {integrity: sha512-LYfpUkmqwl0h9A2HL09Mms427Q1RZWuOHsukfVcKRq9q95iQxdw0ix1JQrqbcDR9PH1QDwf5Qo8OZb5lksZ8Xg==} + engines: {node: '>= 0.4'} which@2.0.2: - resolution: - { - integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==, - } - engines: { node: ">= 8" } + resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} + engines: {node: '>= 8'} hasBin: true why-is-node-running@2.3.0: - resolution: - { - integrity: sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w==, - } - engines: { node: ">=8" } + resolution: {integrity: sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w==} + engines: {node: '>=8'} hasBin: true word-wrap@1.2.5: - resolution: - { - integrity: sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==, - } - engines: { node: ">=0.10.0" } + resolution: {integrity: sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==} + engines: {node: '>=0.10.0'} wrap-ansi@6.2.0: - resolution: - { - integrity: sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==, - } - engines: { node: ">=8" } + resolution: {integrity: sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==} + engines: {node: '>=8'} wrap-ansi@7.0.0: - resolution: - { - integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==, - } - engines: { node: ">=10" } + resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==} + engines: {node: '>=10'} wrap-ansi@8.1.0: - resolution: - { - integrity: sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==, - } - engines: { node: ">=12" } + resolution: {integrity: sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==} + engines: {node: '>=12'} wrappy@1.0.2: - resolution: - { - integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==, - } + resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} ws@8.20.0: - resolution: - { - integrity: sha512-sAt8BhgNbzCtgGbt2OxmpuryO63ZoDk/sqaB/znQm94T4fCEsy/yV+7CdC1kJhOU9lboAEU7R3kquuycDoibVA==, - } - engines: { node: ">=10.0.0" } + resolution: {integrity: sha512-sAt8BhgNbzCtgGbt2OxmpuryO63ZoDk/sqaB/znQm94T4fCEsy/yV+7CdC1kJhOU9lboAEU7R3kquuycDoibVA==} + engines: {node: '>=10.0.0'} peerDependencies: bufferutil: ^4.0.1 - utf-8-validate: ">=5.0.2" + utf-8-validate: '>=5.0.2' peerDependenciesMeta: bufferutil: optional: true @@ -10461,163 +6655,119 @@ packages: optional: true wsl-utils@0.1.0: - resolution: - { - integrity: sha512-h3Fbisa2nKGPxCpm89Hk33lBLsnaGBvctQopaBSOW/uIs6FTe1ATyAnKFJrzVs9vpGdsTe73WF3V4lIsk4Gacw==, - } - engines: { node: ">=18" } + resolution: {integrity: sha512-h3Fbisa2nKGPxCpm89Hk33lBLsnaGBvctQopaBSOW/uIs6FTe1ATyAnKFJrzVs9vpGdsTe73WF3V4lIsk4Gacw==} + engines: {node: '>=18'} xml-name-validator@5.0.0: - resolution: - { - integrity: sha512-EvGK8EJ3DhaHfbRlETOWAS5pO9MZITeauHKJyb8wyajUfQUenkIg2MvLDTZ4T/TgIcm3HU0TFBgWWboAZ30UHg==, - } - engines: { node: ">=18" } + resolution: {integrity: sha512-EvGK8EJ3DhaHfbRlETOWAS5pO9MZITeauHKJyb8wyajUfQUenkIg2MvLDTZ4T/TgIcm3HU0TFBgWWboAZ30UHg==} + engines: {node: '>=18'} xmlchars@2.2.0: - resolution: - { - integrity: sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==, - } + resolution: {integrity: sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==} xtend@4.0.2: - resolution: - { - integrity: sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==, - } - engines: { node: ">=0.4" } + resolution: {integrity: sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==} + engines: {node: '>=0.4'} y18n@4.0.3: - resolution: - { - integrity: sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==, - } + resolution: {integrity: sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==} y18n@5.0.8: - resolution: - { - integrity: sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==, - } - engines: { node: ">=10" } + resolution: {integrity: sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==} + engines: {node: '>=10'} yallist@3.1.1: - resolution: - { - integrity: sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==, - } + resolution: {integrity: sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==} yaml@2.8.3: - resolution: - { - integrity: sha512-AvbaCLOO2Otw/lW5bmh9d/WEdcDFdQp2Z2ZUH3pX9U2ihyUY0nvLv7J6TrWowklRGPYbB/IuIMfYgxaCPg5Bpg==, - } - engines: { node: ">= 14.6" } + resolution: {integrity: sha512-AvbaCLOO2Otw/lW5bmh9d/WEdcDFdQp2Z2ZUH3pX9U2ihyUY0nvLv7J6TrWowklRGPYbB/IuIMfYgxaCPg5Bpg==} + engines: {node: '>= 14.6'} hasBin: true yargs-parser@18.1.3: - resolution: - { - integrity: sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==, - } - engines: { node: ">=6" } + resolution: {integrity: sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==} + engines: {node: '>=6'} yargs-parser@21.1.1: - resolution: - { - integrity: sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==, - } - engines: { node: ">=12" } + resolution: {integrity: sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==} + engines: {node: '>=12'} yargs@15.4.1: - resolution: - { - integrity: sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==, - } - engines: { node: ">=8" } + resolution: {integrity: sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==} + engines: {node: '>=8'} yargs@17.7.2: - resolution: - { - integrity: sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==, - } - engines: { node: ">=12" } + resolution: {integrity: sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==} + engines: {node: '>=12'} yocto-queue@0.1.0: - resolution: - { - integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==, - } - engines: { node: ">=10" } + resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} + engines: {node: '>=10'} zod@3.25.76: - resolution: - { - integrity: sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==, - } + resolution: {integrity: sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==} zod@4.3.6: - resolution: - { - integrity: sha512-rftlrkhHZOcjDwkGlnUtZZkvaPHCsDATp4pGpuOOMDaTdDDXF91wuVDJoWoPsKX/3YPQ5fHuF3STjcYyKr+Qhg==, - } + resolution: {integrity: sha512-rftlrkhHZOcjDwkGlnUtZZkvaPHCsDATp4pGpuOOMDaTdDDXF91wuVDJoWoPsKX/3YPQ5fHuF3STjcYyKr+Qhg==} snapshots: - "@actions/core@1.11.1": - dependencies: - "@actions/exec": 1.1.1 - "@actions/http-client": 2.2.3 - "@actions/exec@1.1.1": + '@actions/core@1.11.1': dependencies: - "@actions/io": 1.1.3 + '@actions/exec': 1.1.1 + '@actions/http-client': 2.2.3 - "@actions/github@6.0.1": + '@actions/exec@1.1.1': dependencies: - "@actions/http-client": 2.2.3 - "@octokit/core": 5.2.2 - "@octokit/plugin-paginate-rest": 9.2.2(@octokit/core@5.2.2) - "@octokit/plugin-rest-endpoint-methods": 10.4.1(@octokit/core@5.2.2) - "@octokit/request": 8.4.1 - "@octokit/request-error": 5.1.1 + '@actions/io': 1.1.3 + + '@actions/github@6.0.1': + dependencies: + '@actions/http-client': 2.2.3 + '@octokit/core': 5.2.2 + '@octokit/plugin-paginate-rest': 9.2.2(@octokit/core@5.2.2) + '@octokit/plugin-rest-endpoint-methods': 10.4.1(@octokit/core@5.2.2) + '@octokit/request': 8.4.1 + '@octokit/request-error': 5.1.1 undici: 5.29.0 - "@actions/http-client@2.2.3": + '@actions/http-client@2.2.3': dependencies: tunnel: 0.0.6 undici: 5.29.0 - "@actions/io@1.1.3": {} + '@actions/io@1.1.3': {} - "@adobe/css-tools@4.4.4": {} + '@adobe/css-tools@4.4.4': {} - "@asamuzakjp/css-color@3.2.0": + '@asamuzakjp/css-color@3.2.0': dependencies: - "@csstools/css-calc": 2.1.4(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4) - "@csstools/css-color-parser": 3.1.0(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4) - "@csstools/css-parser-algorithms": 3.0.5(@csstools/css-tokenizer@3.0.4) - "@csstools/css-tokenizer": 3.0.4 + '@csstools/css-calc': 2.1.4(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4) + '@csstools/css-color-parser': 3.1.0(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4) + '@csstools/css-parser-algorithms': 3.0.5(@csstools/css-tokenizer@3.0.4) + '@csstools/css-tokenizer': 3.0.4 lru-cache: 10.4.3 - "@babel/code-frame@7.29.0": + '@babel/code-frame@7.29.0': dependencies: - "@babel/helper-validator-identifier": 7.28.5 + '@babel/helper-validator-identifier': 7.28.5 js-tokens: 4.0.0 picocolors: 1.1.1 - "@babel/compat-data@7.29.0": {} + '@babel/compat-data@7.29.0': {} - "@babel/core@7.29.0": + '@babel/core@7.29.0': dependencies: - "@babel/code-frame": 7.29.0 - "@babel/generator": 7.29.1 - "@babel/helper-compilation-targets": 7.28.6 - "@babel/helper-module-transforms": 7.28.6(@babel/core@7.29.0) - "@babel/helpers": 7.29.2 - "@babel/parser": 7.29.2 - "@babel/template": 7.28.6 - "@babel/traverse": 7.29.0 - "@babel/types": 7.29.0 - "@jridgewell/remapping": 2.3.5 + '@babel/code-frame': 7.29.0 + '@babel/generator': 7.29.1 + '@babel/helper-compilation-targets': 7.28.6 + '@babel/helper-module-transforms': 7.28.6(@babel/core@7.29.0) + '@babel/helpers': 7.29.2 + '@babel/parser': 7.29.2 + '@babel/template': 7.28.6 + '@babel/traverse': 7.29.0 + '@babel/types': 7.29.0 + '@jridgewell/remapping': 2.3.5 convert-source-map: 2.0.0 debug: 4.4.3 gensync: 1.0.0-beta.2 @@ -10626,666 +6776,666 @@ snapshots: transitivePeerDependencies: - supports-color - "@babel/eslint-parser@7.28.6(@babel/core@7.29.0)(eslint@8.57.1)": + '@babel/eslint-parser@7.28.6(@babel/core@7.29.0)(eslint@8.57.1)': dependencies: - "@babel/core": 7.29.0 - "@nicolo-ribaudo/eslint-scope-5-internals": 5.1.1-v1 + '@babel/core': 7.29.0 + '@nicolo-ribaudo/eslint-scope-5-internals': 5.1.1-v1 eslint: 8.57.1 eslint-visitor-keys: 2.1.0 semver: 6.3.1 - "@babel/eslint-plugin@7.27.1(@babel/eslint-parser@7.28.6(@babel/core@7.29.0)(eslint@8.57.1))(eslint@8.57.1)": + '@babel/eslint-plugin@7.27.1(@babel/eslint-parser@7.28.6(@babel/core@7.29.0)(eslint@8.57.1))(eslint@8.57.1)': dependencies: - "@babel/eslint-parser": 7.28.6(@babel/core@7.29.0)(eslint@8.57.1) + '@babel/eslint-parser': 7.28.6(@babel/core@7.29.0)(eslint@8.57.1) eslint: 8.57.1 eslint-rule-composer: 0.3.0 - "@babel/generator@7.29.1": + '@babel/generator@7.29.1': dependencies: - "@babel/parser": 7.29.2 - "@babel/types": 7.29.0 - "@jridgewell/gen-mapping": 0.3.13 - "@jridgewell/trace-mapping": 0.3.31 + '@babel/parser': 7.29.2 + '@babel/types': 7.29.0 + '@jridgewell/gen-mapping': 0.3.13 + '@jridgewell/trace-mapping': 0.3.31 jsesc: 3.1.0 - "@babel/helper-annotate-as-pure@7.27.3": + '@babel/helper-annotate-as-pure@7.27.3': dependencies: - "@babel/types": 7.29.0 + '@babel/types': 7.29.0 - "@babel/helper-compilation-targets@7.28.6": + '@babel/helper-compilation-targets@7.28.6': dependencies: - "@babel/compat-data": 7.29.0 - "@babel/helper-validator-option": 7.27.1 + '@babel/compat-data': 7.29.0 + '@babel/helper-validator-option': 7.27.1 browserslist: 4.28.2 lru-cache: 5.1.1 semver: 6.3.1 - "@babel/helper-create-class-features-plugin@7.28.6(@babel/core@7.29.0)": + '@babel/helper-create-class-features-plugin@7.28.6(@babel/core@7.29.0)': dependencies: - "@babel/core": 7.29.0 - "@babel/helper-annotate-as-pure": 7.27.3 - "@babel/helper-member-expression-to-functions": 7.28.5 - "@babel/helper-optimise-call-expression": 7.27.1 - "@babel/helper-replace-supers": 7.28.6(@babel/core@7.29.0) - "@babel/helper-skip-transparent-expression-wrappers": 7.27.1 - "@babel/traverse": 7.29.0 + '@babel/core': 7.29.0 + '@babel/helper-annotate-as-pure': 7.27.3 + '@babel/helper-member-expression-to-functions': 7.28.5 + '@babel/helper-optimise-call-expression': 7.27.1 + '@babel/helper-replace-supers': 7.28.6(@babel/core@7.29.0) + '@babel/helper-skip-transparent-expression-wrappers': 7.27.1 + '@babel/traverse': 7.29.0 semver: 6.3.1 transitivePeerDependencies: - supports-color - "@babel/helper-create-regexp-features-plugin@7.28.5(@babel/core@7.29.0)": + '@babel/helper-create-regexp-features-plugin@7.28.5(@babel/core@7.29.0)': dependencies: - "@babel/core": 7.29.0 - "@babel/helper-annotate-as-pure": 7.27.3 + '@babel/core': 7.29.0 + '@babel/helper-annotate-as-pure': 7.27.3 regexpu-core: 6.4.0 semver: 6.3.1 - "@babel/helper-define-polyfill-provider@0.6.8(@babel/core@7.29.0)": + '@babel/helper-define-polyfill-provider@0.6.8(@babel/core@7.29.0)': dependencies: - "@babel/core": 7.29.0 - "@babel/helper-compilation-targets": 7.28.6 - "@babel/helper-plugin-utils": 7.28.6 + '@babel/core': 7.29.0 + '@babel/helper-compilation-targets': 7.28.6 + '@babel/helper-plugin-utils': 7.28.6 debug: 4.4.3 lodash.debounce: 4.0.8 resolve: 1.22.12 transitivePeerDependencies: - supports-color - "@babel/helper-globals@7.28.0": {} + '@babel/helper-globals@7.28.0': {} - "@babel/helper-member-expression-to-functions@7.28.5": + '@babel/helper-member-expression-to-functions@7.28.5': dependencies: - "@babel/traverse": 7.29.0 - "@babel/types": 7.29.0 + '@babel/traverse': 7.29.0 + '@babel/types': 7.29.0 transitivePeerDependencies: - supports-color - "@babel/helper-module-imports@7.28.6": + '@babel/helper-module-imports@7.28.6': dependencies: - "@babel/traverse": 7.29.0 - "@babel/types": 7.29.0 + '@babel/traverse': 7.29.0 + '@babel/types': 7.29.0 transitivePeerDependencies: - supports-color - "@babel/helper-module-transforms@7.28.6(@babel/core@7.29.0)": + '@babel/helper-module-transforms@7.28.6(@babel/core@7.29.0)': dependencies: - "@babel/core": 7.29.0 - "@babel/helper-module-imports": 7.28.6 - "@babel/helper-validator-identifier": 7.28.5 - "@babel/traverse": 7.29.0 + '@babel/core': 7.29.0 + '@babel/helper-module-imports': 7.28.6 + '@babel/helper-validator-identifier': 7.28.5 + '@babel/traverse': 7.29.0 transitivePeerDependencies: - supports-color - "@babel/helper-optimise-call-expression@7.27.1": + '@babel/helper-optimise-call-expression@7.27.1': dependencies: - "@babel/types": 7.29.0 + '@babel/types': 7.29.0 - "@babel/helper-plugin-utils@7.28.6": {} + '@babel/helper-plugin-utils@7.28.6': {} - "@babel/helper-remap-async-to-generator@7.27.1(@babel/core@7.29.0)": + '@babel/helper-remap-async-to-generator@7.27.1(@babel/core@7.29.0)': dependencies: - "@babel/core": 7.29.0 - "@babel/helper-annotate-as-pure": 7.27.3 - "@babel/helper-wrap-function": 7.28.6 - "@babel/traverse": 7.29.0 + '@babel/core': 7.29.0 + '@babel/helper-annotate-as-pure': 7.27.3 + '@babel/helper-wrap-function': 7.28.6 + '@babel/traverse': 7.29.0 transitivePeerDependencies: - supports-color - "@babel/helper-replace-supers@7.28.6(@babel/core@7.29.0)": + '@babel/helper-replace-supers@7.28.6(@babel/core@7.29.0)': dependencies: - "@babel/core": 7.29.0 - "@babel/helper-member-expression-to-functions": 7.28.5 - "@babel/helper-optimise-call-expression": 7.27.1 - "@babel/traverse": 7.29.0 + '@babel/core': 7.29.0 + '@babel/helper-member-expression-to-functions': 7.28.5 + '@babel/helper-optimise-call-expression': 7.27.1 + '@babel/traverse': 7.29.0 transitivePeerDependencies: - supports-color - "@babel/helper-skip-transparent-expression-wrappers@7.27.1": + '@babel/helper-skip-transparent-expression-wrappers@7.27.1': dependencies: - "@babel/traverse": 7.29.0 - "@babel/types": 7.29.0 + '@babel/traverse': 7.29.0 + '@babel/types': 7.29.0 transitivePeerDependencies: - supports-color - "@babel/helper-string-parser@7.27.1": {} + '@babel/helper-string-parser@7.27.1': {} - "@babel/helper-validator-identifier@7.28.5": {} + '@babel/helper-validator-identifier@7.28.5': {} - "@babel/helper-validator-option@7.27.1": {} + '@babel/helper-validator-option@7.27.1': {} - "@babel/helper-wrap-function@7.28.6": + '@babel/helper-wrap-function@7.28.6': dependencies: - "@babel/template": 7.28.6 - "@babel/traverse": 7.29.0 - "@babel/types": 7.29.0 + '@babel/template': 7.28.6 + '@babel/traverse': 7.29.0 + '@babel/types': 7.29.0 transitivePeerDependencies: - supports-color - "@babel/helpers@7.29.2": + '@babel/helpers@7.29.2': dependencies: - "@babel/template": 7.28.6 - "@babel/types": 7.29.0 + '@babel/template': 7.28.6 + '@babel/types': 7.29.0 - "@babel/parser@7.29.2": + '@babel/parser@7.29.2': dependencies: - "@babel/types": 7.29.0 + '@babel/types': 7.29.0 - "@babel/plugin-bugfix-firefox-class-in-computed-class-key@7.28.5(@babel/core@7.29.0)": + '@babel/plugin-bugfix-firefox-class-in-computed-class-key@7.28.5(@babel/core@7.29.0)': dependencies: - "@babel/core": 7.29.0 - "@babel/helper-plugin-utils": 7.28.6 - "@babel/traverse": 7.29.0 + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.28.6 + '@babel/traverse': 7.29.0 transitivePeerDependencies: - supports-color - "@babel/plugin-bugfix-safari-class-field-initializer-scope@7.27.1(@babel/core@7.29.0)": + '@babel/plugin-bugfix-safari-class-field-initializer-scope@7.27.1(@babel/core@7.29.0)': dependencies: - "@babel/core": 7.29.0 - "@babel/helper-plugin-utils": 7.28.6 + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.28.6 - "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@7.27.1(@babel/core@7.29.0)": + '@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@7.27.1(@babel/core@7.29.0)': dependencies: - "@babel/core": 7.29.0 - "@babel/helper-plugin-utils": 7.28.6 + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.28.6 - "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@7.27.1(@babel/core@7.29.0)": + '@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@7.27.1(@babel/core@7.29.0)': dependencies: - "@babel/core": 7.29.0 - "@babel/helper-plugin-utils": 7.28.6 - "@babel/helper-skip-transparent-expression-wrappers": 7.27.1 - "@babel/plugin-transform-optional-chaining": 7.28.6(@babel/core@7.29.0) + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.28.6 + '@babel/helper-skip-transparent-expression-wrappers': 7.27.1 + '@babel/plugin-transform-optional-chaining': 7.28.6(@babel/core@7.29.0) transitivePeerDependencies: - supports-color - "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly@7.28.6(@babel/core@7.29.0)": + '@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly@7.28.6(@babel/core@7.29.0)': dependencies: - "@babel/core": 7.29.0 - "@babel/helper-plugin-utils": 7.28.6 - "@babel/traverse": 7.29.0 + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.28.6 + '@babel/traverse': 7.29.0 transitivePeerDependencies: - supports-color - "@babel/plugin-proposal-private-property-in-object@7.21.0-placeholder-for-preset-env.2(@babel/core@7.29.0)": + '@babel/plugin-proposal-private-property-in-object@7.21.0-placeholder-for-preset-env.2(@babel/core@7.29.0)': dependencies: - "@babel/core": 7.29.0 + '@babel/core': 7.29.0 - "@babel/plugin-syntax-import-assertions@7.28.6(@babel/core@7.29.0)": + '@babel/plugin-syntax-import-assertions@7.28.6(@babel/core@7.29.0)': dependencies: - "@babel/core": 7.29.0 - "@babel/helper-plugin-utils": 7.28.6 + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.28.6 - "@babel/plugin-syntax-import-attributes@7.28.6(@babel/core@7.29.0)": + '@babel/plugin-syntax-import-attributes@7.28.6(@babel/core@7.29.0)': dependencies: - "@babel/core": 7.29.0 - "@babel/helper-plugin-utils": 7.28.6 + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.28.6 - "@babel/plugin-syntax-jsx@7.28.6(@babel/core@7.29.0)": + '@babel/plugin-syntax-jsx@7.28.6(@babel/core@7.29.0)': dependencies: - "@babel/core": 7.29.0 - "@babel/helper-plugin-utils": 7.28.6 + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.28.6 - "@babel/plugin-syntax-typescript@7.28.6(@babel/core@7.29.0)": + '@babel/plugin-syntax-typescript@7.28.6(@babel/core@7.29.0)': dependencies: - "@babel/core": 7.29.0 - "@babel/helper-plugin-utils": 7.28.6 + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.28.6 - "@babel/plugin-syntax-unicode-sets-regex@7.18.6(@babel/core@7.29.0)": + '@babel/plugin-syntax-unicode-sets-regex@7.18.6(@babel/core@7.29.0)': dependencies: - "@babel/core": 7.29.0 - "@babel/helper-create-regexp-features-plugin": 7.28.5(@babel/core@7.29.0) - "@babel/helper-plugin-utils": 7.28.6 + '@babel/core': 7.29.0 + '@babel/helper-create-regexp-features-plugin': 7.28.5(@babel/core@7.29.0) + '@babel/helper-plugin-utils': 7.28.6 - "@babel/plugin-transform-arrow-functions@7.27.1(@babel/core@7.29.0)": + '@babel/plugin-transform-arrow-functions@7.27.1(@babel/core@7.29.0)': dependencies: - "@babel/core": 7.29.0 - "@babel/helper-plugin-utils": 7.28.6 + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.28.6 - "@babel/plugin-transform-async-generator-functions@7.29.0(@babel/core@7.29.0)": + '@babel/plugin-transform-async-generator-functions@7.29.0(@babel/core@7.29.0)': dependencies: - "@babel/core": 7.29.0 - "@babel/helper-plugin-utils": 7.28.6 - "@babel/helper-remap-async-to-generator": 7.27.1(@babel/core@7.29.0) - "@babel/traverse": 7.29.0 + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.28.6 + '@babel/helper-remap-async-to-generator': 7.27.1(@babel/core@7.29.0) + '@babel/traverse': 7.29.0 transitivePeerDependencies: - supports-color - "@babel/plugin-transform-async-to-generator@7.28.6(@babel/core@7.29.0)": + '@babel/plugin-transform-async-to-generator@7.28.6(@babel/core@7.29.0)': dependencies: - "@babel/core": 7.29.0 - "@babel/helper-module-imports": 7.28.6 - "@babel/helper-plugin-utils": 7.28.6 - "@babel/helper-remap-async-to-generator": 7.27.1(@babel/core@7.29.0) + '@babel/core': 7.29.0 + '@babel/helper-module-imports': 7.28.6 + '@babel/helper-plugin-utils': 7.28.6 + '@babel/helper-remap-async-to-generator': 7.27.1(@babel/core@7.29.0) transitivePeerDependencies: - supports-color - "@babel/plugin-transform-block-scoped-functions@7.27.1(@babel/core@7.29.0)": + '@babel/plugin-transform-block-scoped-functions@7.27.1(@babel/core@7.29.0)': dependencies: - "@babel/core": 7.29.0 - "@babel/helper-plugin-utils": 7.28.6 + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.28.6 - "@babel/plugin-transform-block-scoping@7.28.6(@babel/core@7.29.0)": + '@babel/plugin-transform-block-scoping@7.28.6(@babel/core@7.29.0)': dependencies: - "@babel/core": 7.29.0 - "@babel/helper-plugin-utils": 7.28.6 + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.28.6 - "@babel/plugin-transform-class-properties@7.28.6(@babel/core@7.29.0)": + '@babel/plugin-transform-class-properties@7.28.6(@babel/core@7.29.0)': dependencies: - "@babel/core": 7.29.0 - "@babel/helper-create-class-features-plugin": 7.28.6(@babel/core@7.29.0) - "@babel/helper-plugin-utils": 7.28.6 + '@babel/core': 7.29.0 + '@babel/helper-create-class-features-plugin': 7.28.6(@babel/core@7.29.0) + '@babel/helper-plugin-utils': 7.28.6 transitivePeerDependencies: - supports-color - "@babel/plugin-transform-class-static-block@7.28.6(@babel/core@7.29.0)": + '@babel/plugin-transform-class-static-block@7.28.6(@babel/core@7.29.0)': dependencies: - "@babel/core": 7.29.0 - "@babel/helper-create-class-features-plugin": 7.28.6(@babel/core@7.29.0) - "@babel/helper-plugin-utils": 7.28.6 + '@babel/core': 7.29.0 + '@babel/helper-create-class-features-plugin': 7.28.6(@babel/core@7.29.0) + '@babel/helper-plugin-utils': 7.28.6 transitivePeerDependencies: - supports-color - "@babel/plugin-transform-classes@7.28.6(@babel/core@7.29.0)": + '@babel/plugin-transform-classes@7.28.6(@babel/core@7.29.0)': dependencies: - "@babel/core": 7.29.0 - "@babel/helper-annotate-as-pure": 7.27.3 - "@babel/helper-compilation-targets": 7.28.6 - "@babel/helper-globals": 7.28.0 - "@babel/helper-plugin-utils": 7.28.6 - "@babel/helper-replace-supers": 7.28.6(@babel/core@7.29.0) - "@babel/traverse": 7.29.0 + '@babel/core': 7.29.0 + '@babel/helper-annotate-as-pure': 7.27.3 + '@babel/helper-compilation-targets': 7.28.6 + '@babel/helper-globals': 7.28.0 + '@babel/helper-plugin-utils': 7.28.6 + '@babel/helper-replace-supers': 7.28.6(@babel/core@7.29.0) + '@babel/traverse': 7.29.0 transitivePeerDependencies: - supports-color - "@babel/plugin-transform-computed-properties@7.28.6(@babel/core@7.29.0)": + '@babel/plugin-transform-computed-properties@7.28.6(@babel/core@7.29.0)': dependencies: - "@babel/core": 7.29.0 - "@babel/helper-plugin-utils": 7.28.6 - "@babel/template": 7.28.6 + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.28.6 + '@babel/template': 7.28.6 - "@babel/plugin-transform-destructuring@7.28.5(@babel/core@7.29.0)": + '@babel/plugin-transform-destructuring@7.28.5(@babel/core@7.29.0)': dependencies: - "@babel/core": 7.29.0 - "@babel/helper-plugin-utils": 7.28.6 - "@babel/traverse": 7.29.0 + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.28.6 + '@babel/traverse': 7.29.0 transitivePeerDependencies: - supports-color - "@babel/plugin-transform-dotall-regex@7.28.6(@babel/core@7.29.0)": + '@babel/plugin-transform-dotall-regex@7.28.6(@babel/core@7.29.0)': dependencies: - "@babel/core": 7.29.0 - "@babel/helper-create-regexp-features-plugin": 7.28.5(@babel/core@7.29.0) - "@babel/helper-plugin-utils": 7.28.6 + '@babel/core': 7.29.0 + '@babel/helper-create-regexp-features-plugin': 7.28.5(@babel/core@7.29.0) + '@babel/helper-plugin-utils': 7.28.6 - "@babel/plugin-transform-duplicate-keys@7.27.1(@babel/core@7.29.0)": + '@babel/plugin-transform-duplicate-keys@7.27.1(@babel/core@7.29.0)': dependencies: - "@babel/core": 7.29.0 - "@babel/helper-plugin-utils": 7.28.6 + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.28.6 - "@babel/plugin-transform-duplicate-named-capturing-groups-regex@7.29.0(@babel/core@7.29.0)": + '@babel/plugin-transform-duplicate-named-capturing-groups-regex@7.29.0(@babel/core@7.29.0)': dependencies: - "@babel/core": 7.29.0 - "@babel/helper-create-regexp-features-plugin": 7.28.5(@babel/core@7.29.0) - "@babel/helper-plugin-utils": 7.28.6 + '@babel/core': 7.29.0 + '@babel/helper-create-regexp-features-plugin': 7.28.5(@babel/core@7.29.0) + '@babel/helper-plugin-utils': 7.28.6 - "@babel/plugin-transform-dynamic-import@7.27.1(@babel/core@7.29.0)": + '@babel/plugin-transform-dynamic-import@7.27.1(@babel/core@7.29.0)': dependencies: - "@babel/core": 7.29.0 - "@babel/helper-plugin-utils": 7.28.6 + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.28.6 - "@babel/plugin-transform-explicit-resource-management@7.28.6(@babel/core@7.29.0)": + '@babel/plugin-transform-explicit-resource-management@7.28.6(@babel/core@7.29.0)': dependencies: - "@babel/core": 7.29.0 - "@babel/helper-plugin-utils": 7.28.6 - "@babel/plugin-transform-destructuring": 7.28.5(@babel/core@7.29.0) + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.28.6 + '@babel/plugin-transform-destructuring': 7.28.5(@babel/core@7.29.0) transitivePeerDependencies: - supports-color - "@babel/plugin-transform-exponentiation-operator@7.28.6(@babel/core@7.29.0)": + '@babel/plugin-transform-exponentiation-operator@7.28.6(@babel/core@7.29.0)': dependencies: - "@babel/core": 7.29.0 - "@babel/helper-plugin-utils": 7.28.6 + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.28.6 - "@babel/plugin-transform-export-namespace-from@7.27.1(@babel/core@7.29.0)": + '@babel/plugin-transform-export-namespace-from@7.27.1(@babel/core@7.29.0)': dependencies: - "@babel/core": 7.29.0 - "@babel/helper-plugin-utils": 7.28.6 + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.28.6 - "@babel/plugin-transform-for-of@7.27.1(@babel/core@7.29.0)": + '@babel/plugin-transform-for-of@7.27.1(@babel/core@7.29.0)': dependencies: - "@babel/core": 7.29.0 - "@babel/helper-plugin-utils": 7.28.6 - "@babel/helper-skip-transparent-expression-wrappers": 7.27.1 + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.28.6 + '@babel/helper-skip-transparent-expression-wrappers': 7.27.1 transitivePeerDependencies: - supports-color - "@babel/plugin-transform-function-name@7.27.1(@babel/core@7.29.0)": + '@babel/plugin-transform-function-name@7.27.1(@babel/core@7.29.0)': dependencies: - "@babel/core": 7.29.0 - "@babel/helper-compilation-targets": 7.28.6 - "@babel/helper-plugin-utils": 7.28.6 - "@babel/traverse": 7.29.0 + '@babel/core': 7.29.0 + '@babel/helper-compilation-targets': 7.28.6 + '@babel/helper-plugin-utils': 7.28.6 + '@babel/traverse': 7.29.0 transitivePeerDependencies: - supports-color - "@babel/plugin-transform-json-strings@7.28.6(@babel/core@7.29.0)": + '@babel/plugin-transform-json-strings@7.28.6(@babel/core@7.29.0)': dependencies: - "@babel/core": 7.29.0 - "@babel/helper-plugin-utils": 7.28.6 + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.28.6 - "@babel/plugin-transform-literals@7.27.1(@babel/core@7.29.0)": + '@babel/plugin-transform-literals@7.27.1(@babel/core@7.29.0)': dependencies: - "@babel/core": 7.29.0 - "@babel/helper-plugin-utils": 7.28.6 + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.28.6 - "@babel/plugin-transform-logical-assignment-operators@7.28.6(@babel/core@7.29.0)": + '@babel/plugin-transform-logical-assignment-operators@7.28.6(@babel/core@7.29.0)': dependencies: - "@babel/core": 7.29.0 - "@babel/helper-plugin-utils": 7.28.6 + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.28.6 - "@babel/plugin-transform-member-expression-literals@7.27.1(@babel/core@7.29.0)": + '@babel/plugin-transform-member-expression-literals@7.27.1(@babel/core@7.29.0)': dependencies: - "@babel/core": 7.29.0 - "@babel/helper-plugin-utils": 7.28.6 + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.28.6 - "@babel/plugin-transform-modules-amd@7.27.1(@babel/core@7.29.0)": + '@babel/plugin-transform-modules-amd@7.27.1(@babel/core@7.29.0)': dependencies: - "@babel/core": 7.29.0 - "@babel/helper-module-transforms": 7.28.6(@babel/core@7.29.0) - "@babel/helper-plugin-utils": 7.28.6 + '@babel/core': 7.29.0 + '@babel/helper-module-transforms': 7.28.6(@babel/core@7.29.0) + '@babel/helper-plugin-utils': 7.28.6 transitivePeerDependencies: - supports-color - "@babel/plugin-transform-modules-commonjs@7.28.6(@babel/core@7.29.0)": + '@babel/plugin-transform-modules-commonjs@7.28.6(@babel/core@7.29.0)': dependencies: - "@babel/core": 7.29.0 - "@babel/helper-module-transforms": 7.28.6(@babel/core@7.29.0) - "@babel/helper-plugin-utils": 7.28.6 + '@babel/core': 7.29.0 + '@babel/helper-module-transforms': 7.28.6(@babel/core@7.29.0) + '@babel/helper-plugin-utils': 7.28.6 transitivePeerDependencies: - supports-color - "@babel/plugin-transform-modules-systemjs@7.29.0(@babel/core@7.29.0)": + '@babel/plugin-transform-modules-systemjs@7.29.0(@babel/core@7.29.0)': dependencies: - "@babel/core": 7.29.0 - "@babel/helper-module-transforms": 7.28.6(@babel/core@7.29.0) - "@babel/helper-plugin-utils": 7.28.6 - "@babel/helper-validator-identifier": 7.28.5 - "@babel/traverse": 7.29.0 + '@babel/core': 7.29.0 + '@babel/helper-module-transforms': 7.28.6(@babel/core@7.29.0) + '@babel/helper-plugin-utils': 7.28.6 + '@babel/helper-validator-identifier': 7.28.5 + '@babel/traverse': 7.29.0 transitivePeerDependencies: - supports-color - "@babel/plugin-transform-modules-umd@7.27.1(@babel/core@7.29.0)": + '@babel/plugin-transform-modules-umd@7.27.1(@babel/core@7.29.0)': dependencies: - "@babel/core": 7.29.0 - "@babel/helper-module-transforms": 7.28.6(@babel/core@7.29.0) - "@babel/helper-plugin-utils": 7.28.6 + '@babel/core': 7.29.0 + '@babel/helper-module-transforms': 7.28.6(@babel/core@7.29.0) + '@babel/helper-plugin-utils': 7.28.6 transitivePeerDependencies: - supports-color - "@babel/plugin-transform-named-capturing-groups-regex@7.29.0(@babel/core@7.29.0)": + '@babel/plugin-transform-named-capturing-groups-regex@7.29.0(@babel/core@7.29.0)': dependencies: - "@babel/core": 7.29.0 - "@babel/helper-create-regexp-features-plugin": 7.28.5(@babel/core@7.29.0) - "@babel/helper-plugin-utils": 7.28.6 + '@babel/core': 7.29.0 + '@babel/helper-create-regexp-features-plugin': 7.28.5(@babel/core@7.29.0) + '@babel/helper-plugin-utils': 7.28.6 - "@babel/plugin-transform-new-target@7.27.1(@babel/core@7.29.0)": + '@babel/plugin-transform-new-target@7.27.1(@babel/core@7.29.0)': dependencies: - "@babel/core": 7.29.0 - "@babel/helper-plugin-utils": 7.28.6 + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.28.6 - "@babel/plugin-transform-nullish-coalescing-operator@7.28.6(@babel/core@7.29.0)": + '@babel/plugin-transform-nullish-coalescing-operator@7.28.6(@babel/core@7.29.0)': dependencies: - "@babel/core": 7.29.0 - "@babel/helper-plugin-utils": 7.28.6 + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.28.6 - "@babel/plugin-transform-numeric-separator@7.28.6(@babel/core@7.29.0)": + '@babel/plugin-transform-numeric-separator@7.28.6(@babel/core@7.29.0)': dependencies: - "@babel/core": 7.29.0 - "@babel/helper-plugin-utils": 7.28.6 + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.28.6 - "@babel/plugin-transform-object-rest-spread@7.28.6(@babel/core@7.29.0)": + '@babel/plugin-transform-object-rest-spread@7.28.6(@babel/core@7.29.0)': dependencies: - "@babel/core": 7.29.0 - "@babel/helper-compilation-targets": 7.28.6 - "@babel/helper-plugin-utils": 7.28.6 - "@babel/plugin-transform-destructuring": 7.28.5(@babel/core@7.29.0) - "@babel/plugin-transform-parameters": 7.27.7(@babel/core@7.29.0) - "@babel/traverse": 7.29.0 + '@babel/core': 7.29.0 + '@babel/helper-compilation-targets': 7.28.6 + '@babel/helper-plugin-utils': 7.28.6 + '@babel/plugin-transform-destructuring': 7.28.5(@babel/core@7.29.0) + '@babel/plugin-transform-parameters': 7.27.7(@babel/core@7.29.0) + '@babel/traverse': 7.29.0 transitivePeerDependencies: - supports-color - "@babel/plugin-transform-object-super@7.27.1(@babel/core@7.29.0)": + '@babel/plugin-transform-object-super@7.27.1(@babel/core@7.29.0)': dependencies: - "@babel/core": 7.29.0 - "@babel/helper-plugin-utils": 7.28.6 - "@babel/helper-replace-supers": 7.28.6(@babel/core@7.29.0) + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.28.6 + '@babel/helper-replace-supers': 7.28.6(@babel/core@7.29.0) transitivePeerDependencies: - supports-color - "@babel/plugin-transform-optional-catch-binding@7.28.6(@babel/core@7.29.0)": + '@babel/plugin-transform-optional-catch-binding@7.28.6(@babel/core@7.29.0)': dependencies: - "@babel/core": 7.29.0 - "@babel/helper-plugin-utils": 7.28.6 + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.28.6 - "@babel/plugin-transform-optional-chaining@7.28.6(@babel/core@7.29.0)": + '@babel/plugin-transform-optional-chaining@7.28.6(@babel/core@7.29.0)': dependencies: - "@babel/core": 7.29.0 - "@babel/helper-plugin-utils": 7.28.6 - "@babel/helper-skip-transparent-expression-wrappers": 7.27.1 + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.28.6 + '@babel/helper-skip-transparent-expression-wrappers': 7.27.1 transitivePeerDependencies: - supports-color - "@babel/plugin-transform-parameters@7.27.7(@babel/core@7.29.0)": + '@babel/plugin-transform-parameters@7.27.7(@babel/core@7.29.0)': dependencies: - "@babel/core": 7.29.0 - "@babel/helper-plugin-utils": 7.28.6 + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.28.6 - "@babel/plugin-transform-private-methods@7.28.6(@babel/core@7.29.0)": + '@babel/plugin-transform-private-methods@7.28.6(@babel/core@7.29.0)': dependencies: - "@babel/core": 7.29.0 - "@babel/helper-create-class-features-plugin": 7.28.6(@babel/core@7.29.0) - "@babel/helper-plugin-utils": 7.28.6 + '@babel/core': 7.29.0 + '@babel/helper-create-class-features-plugin': 7.28.6(@babel/core@7.29.0) + '@babel/helper-plugin-utils': 7.28.6 transitivePeerDependencies: - supports-color - "@babel/plugin-transform-private-property-in-object@7.28.6(@babel/core@7.29.0)": + '@babel/plugin-transform-private-property-in-object@7.28.6(@babel/core@7.29.0)': dependencies: - "@babel/core": 7.29.0 - "@babel/helper-annotate-as-pure": 7.27.3 - "@babel/helper-create-class-features-plugin": 7.28.6(@babel/core@7.29.0) - "@babel/helper-plugin-utils": 7.28.6 + '@babel/core': 7.29.0 + '@babel/helper-annotate-as-pure': 7.27.3 + '@babel/helper-create-class-features-plugin': 7.28.6(@babel/core@7.29.0) + '@babel/helper-plugin-utils': 7.28.6 transitivePeerDependencies: - supports-color - "@babel/plugin-transform-property-literals@7.27.1(@babel/core@7.29.0)": + '@babel/plugin-transform-property-literals@7.27.1(@babel/core@7.29.0)': dependencies: - "@babel/core": 7.29.0 - "@babel/helper-plugin-utils": 7.28.6 + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.28.6 - "@babel/plugin-transform-react-display-name@7.28.0(@babel/core@7.29.0)": + '@babel/plugin-transform-react-display-name@7.28.0(@babel/core@7.29.0)': dependencies: - "@babel/core": 7.29.0 - "@babel/helper-plugin-utils": 7.28.6 + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.28.6 - "@babel/plugin-transform-react-jsx-development@7.27.1(@babel/core@7.29.0)": + '@babel/plugin-transform-react-jsx-development@7.27.1(@babel/core@7.29.0)': dependencies: - "@babel/core": 7.29.0 - "@babel/plugin-transform-react-jsx": 7.28.6(@babel/core@7.29.0) + '@babel/core': 7.29.0 + '@babel/plugin-transform-react-jsx': 7.28.6(@babel/core@7.29.0) transitivePeerDependencies: - supports-color - "@babel/plugin-transform-react-jsx-self@7.27.1(@babel/core@7.29.0)": + '@babel/plugin-transform-react-jsx-self@7.27.1(@babel/core@7.29.0)': dependencies: - "@babel/core": 7.29.0 - "@babel/helper-plugin-utils": 7.28.6 + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.28.6 - "@babel/plugin-transform-react-jsx-source@7.27.1(@babel/core@7.29.0)": + '@babel/plugin-transform-react-jsx-source@7.27.1(@babel/core@7.29.0)': dependencies: - "@babel/core": 7.29.0 - "@babel/helper-plugin-utils": 7.28.6 + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.28.6 - "@babel/plugin-transform-react-jsx@7.28.6(@babel/core@7.29.0)": + '@babel/plugin-transform-react-jsx@7.28.6(@babel/core@7.29.0)': dependencies: - "@babel/core": 7.29.0 - "@babel/helper-annotate-as-pure": 7.27.3 - "@babel/helper-module-imports": 7.28.6 - "@babel/helper-plugin-utils": 7.28.6 - "@babel/plugin-syntax-jsx": 7.28.6(@babel/core@7.29.0) - "@babel/types": 7.29.0 + '@babel/core': 7.29.0 + '@babel/helper-annotate-as-pure': 7.27.3 + '@babel/helper-module-imports': 7.28.6 + '@babel/helper-plugin-utils': 7.28.6 + '@babel/plugin-syntax-jsx': 7.28.6(@babel/core@7.29.0) + '@babel/types': 7.29.0 transitivePeerDependencies: - supports-color - "@babel/plugin-transform-react-pure-annotations@7.27.1(@babel/core@7.29.0)": + '@babel/plugin-transform-react-pure-annotations@7.27.1(@babel/core@7.29.0)': dependencies: - "@babel/core": 7.29.0 - "@babel/helper-annotate-as-pure": 7.27.3 - "@babel/helper-plugin-utils": 7.28.6 + '@babel/core': 7.29.0 + '@babel/helper-annotate-as-pure': 7.27.3 + '@babel/helper-plugin-utils': 7.28.6 - "@babel/plugin-transform-regenerator@7.29.0(@babel/core@7.29.0)": + '@babel/plugin-transform-regenerator@7.29.0(@babel/core@7.29.0)': dependencies: - "@babel/core": 7.29.0 - "@babel/helper-plugin-utils": 7.28.6 + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.28.6 - "@babel/plugin-transform-regexp-modifiers@7.28.6(@babel/core@7.29.0)": + '@babel/plugin-transform-regexp-modifiers@7.28.6(@babel/core@7.29.0)': dependencies: - "@babel/core": 7.29.0 - "@babel/helper-create-regexp-features-plugin": 7.28.5(@babel/core@7.29.0) - "@babel/helper-plugin-utils": 7.28.6 + '@babel/core': 7.29.0 + '@babel/helper-create-regexp-features-plugin': 7.28.5(@babel/core@7.29.0) + '@babel/helper-plugin-utils': 7.28.6 - "@babel/plugin-transform-reserved-words@7.27.1(@babel/core@7.29.0)": + '@babel/plugin-transform-reserved-words@7.27.1(@babel/core@7.29.0)': dependencies: - "@babel/core": 7.29.0 - "@babel/helper-plugin-utils": 7.28.6 + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.28.6 - "@babel/plugin-transform-shorthand-properties@7.27.1(@babel/core@7.29.0)": + '@babel/plugin-transform-shorthand-properties@7.27.1(@babel/core@7.29.0)': dependencies: - "@babel/core": 7.29.0 - "@babel/helper-plugin-utils": 7.28.6 + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.28.6 - "@babel/plugin-transform-spread@7.28.6(@babel/core@7.29.0)": + '@babel/plugin-transform-spread@7.28.6(@babel/core@7.29.0)': dependencies: - "@babel/core": 7.29.0 - "@babel/helper-plugin-utils": 7.28.6 - "@babel/helper-skip-transparent-expression-wrappers": 7.27.1 + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.28.6 + '@babel/helper-skip-transparent-expression-wrappers': 7.27.1 transitivePeerDependencies: - supports-color - "@babel/plugin-transform-sticky-regex@7.27.1(@babel/core@7.29.0)": + '@babel/plugin-transform-sticky-regex@7.27.1(@babel/core@7.29.0)': dependencies: - "@babel/core": 7.29.0 - "@babel/helper-plugin-utils": 7.28.6 + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.28.6 - "@babel/plugin-transform-template-literals@7.27.1(@babel/core@7.29.0)": + '@babel/plugin-transform-template-literals@7.27.1(@babel/core@7.29.0)': dependencies: - "@babel/core": 7.29.0 - "@babel/helper-plugin-utils": 7.28.6 + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.28.6 - "@babel/plugin-transform-typeof-symbol@7.27.1(@babel/core@7.29.0)": + '@babel/plugin-transform-typeof-symbol@7.27.1(@babel/core@7.29.0)': dependencies: - "@babel/core": 7.29.0 - "@babel/helper-plugin-utils": 7.28.6 + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.28.6 - "@babel/plugin-transform-typescript@7.28.6(@babel/core@7.29.0)": + '@babel/plugin-transform-typescript@7.28.6(@babel/core@7.29.0)': dependencies: - "@babel/core": 7.29.0 - "@babel/helper-annotate-as-pure": 7.27.3 - "@babel/helper-create-class-features-plugin": 7.28.6(@babel/core@7.29.0) - "@babel/helper-plugin-utils": 7.28.6 - "@babel/helper-skip-transparent-expression-wrappers": 7.27.1 - "@babel/plugin-syntax-typescript": 7.28.6(@babel/core@7.29.0) + '@babel/core': 7.29.0 + '@babel/helper-annotate-as-pure': 7.27.3 + '@babel/helper-create-class-features-plugin': 7.28.6(@babel/core@7.29.0) + '@babel/helper-plugin-utils': 7.28.6 + '@babel/helper-skip-transparent-expression-wrappers': 7.27.1 + '@babel/plugin-syntax-typescript': 7.28.6(@babel/core@7.29.0) transitivePeerDependencies: - supports-color - "@babel/plugin-transform-unicode-escapes@7.27.1(@babel/core@7.29.0)": + '@babel/plugin-transform-unicode-escapes@7.27.1(@babel/core@7.29.0)': dependencies: - "@babel/core": 7.29.0 - "@babel/helper-plugin-utils": 7.28.6 + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.28.6 - "@babel/plugin-transform-unicode-property-regex@7.28.6(@babel/core@7.29.0)": + '@babel/plugin-transform-unicode-property-regex@7.28.6(@babel/core@7.29.0)': dependencies: - "@babel/core": 7.29.0 - "@babel/helper-create-regexp-features-plugin": 7.28.5(@babel/core@7.29.0) - "@babel/helper-plugin-utils": 7.28.6 + '@babel/core': 7.29.0 + '@babel/helper-create-regexp-features-plugin': 7.28.5(@babel/core@7.29.0) + '@babel/helper-plugin-utils': 7.28.6 - "@babel/plugin-transform-unicode-regex@7.27.1(@babel/core@7.29.0)": + '@babel/plugin-transform-unicode-regex@7.27.1(@babel/core@7.29.0)': dependencies: - "@babel/core": 7.29.0 - "@babel/helper-create-regexp-features-plugin": 7.28.5(@babel/core@7.29.0) - "@babel/helper-plugin-utils": 7.28.6 + '@babel/core': 7.29.0 + '@babel/helper-create-regexp-features-plugin': 7.28.5(@babel/core@7.29.0) + '@babel/helper-plugin-utils': 7.28.6 - "@babel/plugin-transform-unicode-sets-regex@7.28.6(@babel/core@7.29.0)": + '@babel/plugin-transform-unicode-sets-regex@7.28.6(@babel/core@7.29.0)': dependencies: - "@babel/core": 7.29.0 - "@babel/helper-create-regexp-features-plugin": 7.28.5(@babel/core@7.29.0) - "@babel/helper-plugin-utils": 7.28.6 + '@babel/core': 7.29.0 + '@babel/helper-create-regexp-features-plugin': 7.28.5(@babel/core@7.29.0) + '@babel/helper-plugin-utils': 7.28.6 - "@babel/preset-env@7.29.2(@babel/core@7.29.0)": + '@babel/preset-env@7.29.2(@babel/core@7.29.0)': dependencies: - "@babel/compat-data": 7.29.0 - "@babel/core": 7.29.0 - "@babel/helper-compilation-targets": 7.28.6 - "@babel/helper-plugin-utils": 7.28.6 - "@babel/helper-validator-option": 7.27.1 - "@babel/plugin-bugfix-firefox-class-in-computed-class-key": 7.28.5(@babel/core@7.29.0) - "@babel/plugin-bugfix-safari-class-field-initializer-scope": 7.27.1(@babel/core@7.29.0) - "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": 7.27.1(@babel/core@7.29.0) - "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": 7.27.1(@babel/core@7.29.0) - "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": 7.28.6(@babel/core@7.29.0) - "@babel/plugin-proposal-private-property-in-object": 7.21.0-placeholder-for-preset-env.2(@babel/core@7.29.0) - "@babel/plugin-syntax-import-assertions": 7.28.6(@babel/core@7.29.0) - "@babel/plugin-syntax-import-attributes": 7.28.6(@babel/core@7.29.0) - "@babel/plugin-syntax-unicode-sets-regex": 7.18.6(@babel/core@7.29.0) - "@babel/plugin-transform-arrow-functions": 7.27.1(@babel/core@7.29.0) - "@babel/plugin-transform-async-generator-functions": 7.29.0(@babel/core@7.29.0) - "@babel/plugin-transform-async-to-generator": 7.28.6(@babel/core@7.29.0) - "@babel/plugin-transform-block-scoped-functions": 7.27.1(@babel/core@7.29.0) - "@babel/plugin-transform-block-scoping": 7.28.6(@babel/core@7.29.0) - "@babel/plugin-transform-class-properties": 7.28.6(@babel/core@7.29.0) - "@babel/plugin-transform-class-static-block": 7.28.6(@babel/core@7.29.0) - "@babel/plugin-transform-classes": 7.28.6(@babel/core@7.29.0) - "@babel/plugin-transform-computed-properties": 7.28.6(@babel/core@7.29.0) - "@babel/plugin-transform-destructuring": 7.28.5(@babel/core@7.29.0) - "@babel/plugin-transform-dotall-regex": 7.28.6(@babel/core@7.29.0) - "@babel/plugin-transform-duplicate-keys": 7.27.1(@babel/core@7.29.0) - "@babel/plugin-transform-duplicate-named-capturing-groups-regex": 7.29.0(@babel/core@7.29.0) - "@babel/plugin-transform-dynamic-import": 7.27.1(@babel/core@7.29.0) - "@babel/plugin-transform-explicit-resource-management": 7.28.6(@babel/core@7.29.0) - "@babel/plugin-transform-exponentiation-operator": 7.28.6(@babel/core@7.29.0) - "@babel/plugin-transform-export-namespace-from": 7.27.1(@babel/core@7.29.0) - "@babel/plugin-transform-for-of": 7.27.1(@babel/core@7.29.0) - "@babel/plugin-transform-function-name": 7.27.1(@babel/core@7.29.0) - "@babel/plugin-transform-json-strings": 7.28.6(@babel/core@7.29.0) - "@babel/plugin-transform-literals": 7.27.1(@babel/core@7.29.0) - "@babel/plugin-transform-logical-assignment-operators": 7.28.6(@babel/core@7.29.0) - "@babel/plugin-transform-member-expression-literals": 7.27.1(@babel/core@7.29.0) - "@babel/plugin-transform-modules-amd": 7.27.1(@babel/core@7.29.0) - "@babel/plugin-transform-modules-commonjs": 7.28.6(@babel/core@7.29.0) - "@babel/plugin-transform-modules-systemjs": 7.29.0(@babel/core@7.29.0) - "@babel/plugin-transform-modules-umd": 7.27.1(@babel/core@7.29.0) - "@babel/plugin-transform-named-capturing-groups-regex": 7.29.0(@babel/core@7.29.0) - "@babel/plugin-transform-new-target": 7.27.1(@babel/core@7.29.0) - "@babel/plugin-transform-nullish-coalescing-operator": 7.28.6(@babel/core@7.29.0) - "@babel/plugin-transform-numeric-separator": 7.28.6(@babel/core@7.29.0) - "@babel/plugin-transform-object-rest-spread": 7.28.6(@babel/core@7.29.0) - "@babel/plugin-transform-object-super": 7.27.1(@babel/core@7.29.0) - "@babel/plugin-transform-optional-catch-binding": 7.28.6(@babel/core@7.29.0) - "@babel/plugin-transform-optional-chaining": 7.28.6(@babel/core@7.29.0) - "@babel/plugin-transform-parameters": 7.27.7(@babel/core@7.29.0) - "@babel/plugin-transform-private-methods": 7.28.6(@babel/core@7.29.0) - "@babel/plugin-transform-private-property-in-object": 7.28.6(@babel/core@7.29.0) - "@babel/plugin-transform-property-literals": 7.27.1(@babel/core@7.29.0) - "@babel/plugin-transform-regenerator": 7.29.0(@babel/core@7.29.0) - "@babel/plugin-transform-regexp-modifiers": 7.28.6(@babel/core@7.29.0) - "@babel/plugin-transform-reserved-words": 7.27.1(@babel/core@7.29.0) - "@babel/plugin-transform-shorthand-properties": 7.27.1(@babel/core@7.29.0) - "@babel/plugin-transform-spread": 7.28.6(@babel/core@7.29.0) - "@babel/plugin-transform-sticky-regex": 7.27.1(@babel/core@7.29.0) - "@babel/plugin-transform-template-literals": 7.27.1(@babel/core@7.29.0) - "@babel/plugin-transform-typeof-symbol": 7.27.1(@babel/core@7.29.0) - "@babel/plugin-transform-unicode-escapes": 7.27.1(@babel/core@7.29.0) - "@babel/plugin-transform-unicode-property-regex": 7.28.6(@babel/core@7.29.0) - "@babel/plugin-transform-unicode-regex": 7.27.1(@babel/core@7.29.0) - "@babel/plugin-transform-unicode-sets-regex": 7.28.6(@babel/core@7.29.0) - "@babel/preset-modules": 0.1.6-no-external-plugins(@babel/core@7.29.0) + '@babel/compat-data': 7.29.0 + '@babel/core': 7.29.0 + '@babel/helper-compilation-targets': 7.28.6 + '@babel/helper-plugin-utils': 7.28.6 + '@babel/helper-validator-option': 7.27.1 + '@babel/plugin-bugfix-firefox-class-in-computed-class-key': 7.28.5(@babel/core@7.29.0) + '@babel/plugin-bugfix-safari-class-field-initializer-scope': 7.27.1(@babel/core@7.29.0) + '@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression': 7.27.1(@babel/core@7.29.0) + '@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining': 7.27.1(@babel/core@7.29.0) + '@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly': 7.28.6(@babel/core@7.29.0) + '@babel/plugin-proposal-private-property-in-object': 7.21.0-placeholder-for-preset-env.2(@babel/core@7.29.0) + '@babel/plugin-syntax-import-assertions': 7.28.6(@babel/core@7.29.0) + '@babel/plugin-syntax-import-attributes': 7.28.6(@babel/core@7.29.0) + '@babel/plugin-syntax-unicode-sets-regex': 7.18.6(@babel/core@7.29.0) + '@babel/plugin-transform-arrow-functions': 7.27.1(@babel/core@7.29.0) + '@babel/plugin-transform-async-generator-functions': 7.29.0(@babel/core@7.29.0) + '@babel/plugin-transform-async-to-generator': 7.28.6(@babel/core@7.29.0) + '@babel/plugin-transform-block-scoped-functions': 7.27.1(@babel/core@7.29.0) + '@babel/plugin-transform-block-scoping': 7.28.6(@babel/core@7.29.0) + '@babel/plugin-transform-class-properties': 7.28.6(@babel/core@7.29.0) + '@babel/plugin-transform-class-static-block': 7.28.6(@babel/core@7.29.0) + '@babel/plugin-transform-classes': 7.28.6(@babel/core@7.29.0) + '@babel/plugin-transform-computed-properties': 7.28.6(@babel/core@7.29.0) + '@babel/plugin-transform-destructuring': 7.28.5(@babel/core@7.29.0) + '@babel/plugin-transform-dotall-regex': 7.28.6(@babel/core@7.29.0) + '@babel/plugin-transform-duplicate-keys': 7.27.1(@babel/core@7.29.0) + '@babel/plugin-transform-duplicate-named-capturing-groups-regex': 7.29.0(@babel/core@7.29.0) + '@babel/plugin-transform-dynamic-import': 7.27.1(@babel/core@7.29.0) + '@babel/plugin-transform-explicit-resource-management': 7.28.6(@babel/core@7.29.0) + '@babel/plugin-transform-exponentiation-operator': 7.28.6(@babel/core@7.29.0) + '@babel/plugin-transform-export-namespace-from': 7.27.1(@babel/core@7.29.0) + '@babel/plugin-transform-for-of': 7.27.1(@babel/core@7.29.0) + '@babel/plugin-transform-function-name': 7.27.1(@babel/core@7.29.0) + '@babel/plugin-transform-json-strings': 7.28.6(@babel/core@7.29.0) + '@babel/plugin-transform-literals': 7.27.1(@babel/core@7.29.0) + '@babel/plugin-transform-logical-assignment-operators': 7.28.6(@babel/core@7.29.0) + '@babel/plugin-transform-member-expression-literals': 7.27.1(@babel/core@7.29.0) + '@babel/plugin-transform-modules-amd': 7.27.1(@babel/core@7.29.0) + '@babel/plugin-transform-modules-commonjs': 7.28.6(@babel/core@7.29.0) + '@babel/plugin-transform-modules-systemjs': 7.29.0(@babel/core@7.29.0) + '@babel/plugin-transform-modules-umd': 7.27.1(@babel/core@7.29.0) + '@babel/plugin-transform-named-capturing-groups-regex': 7.29.0(@babel/core@7.29.0) + '@babel/plugin-transform-new-target': 7.27.1(@babel/core@7.29.0) + '@babel/plugin-transform-nullish-coalescing-operator': 7.28.6(@babel/core@7.29.0) + '@babel/plugin-transform-numeric-separator': 7.28.6(@babel/core@7.29.0) + '@babel/plugin-transform-object-rest-spread': 7.28.6(@babel/core@7.29.0) + '@babel/plugin-transform-object-super': 7.27.1(@babel/core@7.29.0) + '@babel/plugin-transform-optional-catch-binding': 7.28.6(@babel/core@7.29.0) + '@babel/plugin-transform-optional-chaining': 7.28.6(@babel/core@7.29.0) + '@babel/plugin-transform-parameters': 7.27.7(@babel/core@7.29.0) + '@babel/plugin-transform-private-methods': 7.28.6(@babel/core@7.29.0) + '@babel/plugin-transform-private-property-in-object': 7.28.6(@babel/core@7.29.0) + '@babel/plugin-transform-property-literals': 7.27.1(@babel/core@7.29.0) + '@babel/plugin-transform-regenerator': 7.29.0(@babel/core@7.29.0) + '@babel/plugin-transform-regexp-modifiers': 7.28.6(@babel/core@7.29.0) + '@babel/plugin-transform-reserved-words': 7.27.1(@babel/core@7.29.0) + '@babel/plugin-transform-shorthand-properties': 7.27.1(@babel/core@7.29.0) + '@babel/plugin-transform-spread': 7.28.6(@babel/core@7.29.0) + '@babel/plugin-transform-sticky-regex': 7.27.1(@babel/core@7.29.0) + '@babel/plugin-transform-template-literals': 7.27.1(@babel/core@7.29.0) + '@babel/plugin-transform-typeof-symbol': 7.27.1(@babel/core@7.29.0) + '@babel/plugin-transform-unicode-escapes': 7.27.1(@babel/core@7.29.0) + '@babel/plugin-transform-unicode-property-regex': 7.28.6(@babel/core@7.29.0) + '@babel/plugin-transform-unicode-regex': 7.27.1(@babel/core@7.29.0) + '@babel/plugin-transform-unicode-sets-regex': 7.28.6(@babel/core@7.29.0) + '@babel/preset-modules': 0.1.6-no-external-plugins(@babel/core@7.29.0) babel-plugin-polyfill-corejs2: 0.4.17(@babel/core@7.29.0) babel-plugin-polyfill-corejs3: 0.14.2(@babel/core@7.29.0) babel-plugin-polyfill-regenerator: 0.6.8(@babel/core@7.29.0) @@ -11294,501 +7444,501 @@ snapshots: transitivePeerDependencies: - supports-color - "@babel/preset-modules@0.1.6-no-external-plugins(@babel/core@7.29.0)": + '@babel/preset-modules@0.1.6-no-external-plugins(@babel/core@7.29.0)': dependencies: - "@babel/core": 7.29.0 - "@babel/helper-plugin-utils": 7.28.6 - "@babel/types": 7.29.0 + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.28.6 + '@babel/types': 7.29.0 esutils: 2.0.3 - "@babel/preset-react@7.28.5(@babel/core@7.29.0)": + '@babel/preset-react@7.28.5(@babel/core@7.29.0)': dependencies: - "@babel/core": 7.29.0 - "@babel/helper-plugin-utils": 7.28.6 - "@babel/helper-validator-option": 7.27.1 - "@babel/plugin-transform-react-display-name": 7.28.0(@babel/core@7.29.0) - "@babel/plugin-transform-react-jsx": 7.28.6(@babel/core@7.29.0) - "@babel/plugin-transform-react-jsx-development": 7.27.1(@babel/core@7.29.0) - "@babel/plugin-transform-react-pure-annotations": 7.27.1(@babel/core@7.29.0) + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.28.6 + '@babel/helper-validator-option': 7.27.1 + '@babel/plugin-transform-react-display-name': 7.28.0(@babel/core@7.29.0) + '@babel/plugin-transform-react-jsx': 7.28.6(@babel/core@7.29.0) + '@babel/plugin-transform-react-jsx-development': 7.27.1(@babel/core@7.29.0) + '@babel/plugin-transform-react-pure-annotations': 7.27.1(@babel/core@7.29.0) transitivePeerDependencies: - supports-color - "@babel/preset-typescript@7.28.5(@babel/core@7.29.0)": + '@babel/preset-typescript@7.28.5(@babel/core@7.29.0)': dependencies: - "@babel/core": 7.29.0 - "@babel/helper-plugin-utils": 7.28.6 - "@babel/helper-validator-option": 7.27.1 - "@babel/plugin-syntax-jsx": 7.28.6(@babel/core@7.29.0) - "@babel/plugin-transform-modules-commonjs": 7.28.6(@babel/core@7.29.0) - "@babel/plugin-transform-typescript": 7.28.6(@babel/core@7.29.0) + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.28.6 + '@babel/helper-validator-option': 7.27.1 + '@babel/plugin-syntax-jsx': 7.28.6(@babel/core@7.29.0) + '@babel/plugin-transform-modules-commonjs': 7.28.6(@babel/core@7.29.0) + '@babel/plugin-transform-typescript': 7.28.6(@babel/core@7.29.0) transitivePeerDependencies: - supports-color - "@babel/runtime@7.29.2": {} + '@babel/runtime@7.29.2': {} - "@babel/template@7.28.6": + '@babel/template@7.28.6': dependencies: - "@babel/code-frame": 7.29.0 - "@babel/parser": 7.29.2 - "@babel/types": 7.29.0 + '@babel/code-frame': 7.29.0 + '@babel/parser': 7.29.2 + '@babel/types': 7.29.0 - "@babel/traverse@7.29.0": + '@babel/traverse@7.29.0': dependencies: - "@babel/code-frame": 7.29.0 - "@babel/generator": 7.29.1 - "@babel/helper-globals": 7.28.0 - "@babel/parser": 7.29.2 - "@babel/template": 7.28.6 - "@babel/types": 7.29.0 + '@babel/code-frame': 7.29.0 + '@babel/generator': 7.29.1 + '@babel/helper-globals': 7.28.0 + '@babel/parser': 7.29.2 + '@babel/template': 7.28.6 + '@babel/types': 7.29.0 debug: 4.4.3 transitivePeerDependencies: - supports-color - "@babel/types@7.29.0": + '@babel/types@7.29.0': dependencies: - "@babel/helper-string-parser": 7.27.1 - "@babel/helper-validator-identifier": 7.28.5 + '@babel/helper-string-parser': 7.27.1 + '@babel/helper-validator-identifier': 7.28.5 - "@bcoe/v8-coverage@1.0.2": {} + '@bcoe/v8-coverage@1.0.2': {} - "@bufbuild/protobuf@1.10.1": {} + '@bufbuild/protobuf@1.10.1': {} - "@codecov/bundler-plugin-core@1.9.1": + '@codecov/bundler-plugin-core@1.9.1': dependencies: - "@actions/core": 1.11.1 - "@actions/github": 6.0.1 + '@actions/core': 1.11.1 + '@actions/github': 6.0.1 chalk: 4.1.2 semver: 7.7.4 unplugin: 1.16.1 zod: 3.25.76 - "@codecov/vite-plugin@1.9.1(vite@8.0.8(@types/node@24.12.2)(esbuild@0.27.7)(jiti@2.6.1)(sass@1.99.0)(terser@5.46.1)(yaml@2.8.3))": + '@codecov/vite-plugin@1.9.1(vite@8.0.8(@types/node@24.12.2)(esbuild@0.27.7)(jiti@2.6.1)(sass@1.99.0)(terser@5.46.1)(yaml@2.8.3))': dependencies: - "@codecov/bundler-plugin-core": 1.9.1 + '@codecov/bundler-plugin-core': 1.9.1 unplugin: 1.16.1 vite: 8.0.8(@types/node@24.12.2)(esbuild@0.27.7)(jiti@2.6.1)(sass@1.99.0)(terser@5.46.1)(yaml@2.8.3) - "@csstools/cascade-layer-name-parser@2.0.5(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4)": + '@csstools/cascade-layer-name-parser@2.0.5(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4)': dependencies: - "@csstools/css-parser-algorithms": 3.0.5(@csstools/css-tokenizer@3.0.4) - "@csstools/css-tokenizer": 3.0.4 + '@csstools/css-parser-algorithms': 3.0.5(@csstools/css-tokenizer@3.0.4) + '@csstools/css-tokenizer': 3.0.4 - "@csstools/color-helpers@5.1.0": {} + '@csstools/color-helpers@5.1.0': {} - "@csstools/css-calc@2.1.4(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4)": + '@csstools/css-calc@2.1.4(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4)': dependencies: - "@csstools/css-parser-algorithms": 3.0.5(@csstools/css-tokenizer@3.0.4) - "@csstools/css-tokenizer": 3.0.4 + '@csstools/css-parser-algorithms': 3.0.5(@csstools/css-tokenizer@3.0.4) + '@csstools/css-tokenizer': 3.0.4 - "@csstools/css-color-parser@3.1.0(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4)": + '@csstools/css-color-parser@3.1.0(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4)': dependencies: - "@csstools/color-helpers": 5.1.0 - "@csstools/css-calc": 2.1.4(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4) - "@csstools/css-parser-algorithms": 3.0.5(@csstools/css-tokenizer@3.0.4) - "@csstools/css-tokenizer": 3.0.4 + '@csstools/color-helpers': 5.1.0 + '@csstools/css-calc': 2.1.4(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4) + '@csstools/css-parser-algorithms': 3.0.5(@csstools/css-tokenizer@3.0.4) + '@csstools/css-tokenizer': 3.0.4 - "@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4)": + '@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4)': dependencies: - "@csstools/css-tokenizer": 3.0.4 + '@csstools/css-tokenizer': 3.0.4 - "@csstools/css-tokenizer@3.0.4": {} + '@csstools/css-tokenizer@3.0.4': {} - "@csstools/media-query-list-parser@4.0.3(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4)": + '@csstools/media-query-list-parser@4.0.3(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4)': dependencies: - "@csstools/css-parser-algorithms": 3.0.5(@csstools/css-tokenizer@3.0.4) - "@csstools/css-tokenizer": 3.0.4 + '@csstools/css-parser-algorithms': 3.0.5(@csstools/css-tokenizer@3.0.4) + '@csstools/css-tokenizer': 3.0.4 - "@csstools/postcss-alpha-function@1.0.1(postcss@8.5.10)": + '@csstools/postcss-alpha-function@1.0.1(postcss@8.5.10)': dependencies: - "@csstools/css-color-parser": 3.1.0(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4) - "@csstools/css-parser-algorithms": 3.0.5(@csstools/css-tokenizer@3.0.4) - "@csstools/css-tokenizer": 3.0.4 - "@csstools/postcss-progressive-custom-properties": 4.2.1(postcss@8.5.10) - "@csstools/utilities": 2.0.0(postcss@8.5.10) + '@csstools/css-color-parser': 3.1.0(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4) + '@csstools/css-parser-algorithms': 3.0.5(@csstools/css-tokenizer@3.0.4) + '@csstools/css-tokenizer': 3.0.4 + '@csstools/postcss-progressive-custom-properties': 4.2.1(postcss@8.5.10) + '@csstools/utilities': 2.0.0(postcss@8.5.10) postcss: 8.5.10 - "@csstools/postcss-cascade-layers@5.0.2(postcss@8.5.10)": + '@csstools/postcss-cascade-layers@5.0.2(postcss@8.5.10)': dependencies: - "@csstools/selector-specificity": 5.0.0(postcss-selector-parser@7.1.1) + '@csstools/selector-specificity': 5.0.0(postcss-selector-parser@7.1.1) postcss: 8.5.10 postcss-selector-parser: 7.1.1 - "@csstools/postcss-color-function-display-p3-linear@1.0.1(postcss@8.5.10)": + '@csstools/postcss-color-function-display-p3-linear@1.0.1(postcss@8.5.10)': dependencies: - "@csstools/css-color-parser": 3.1.0(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4) - "@csstools/css-parser-algorithms": 3.0.5(@csstools/css-tokenizer@3.0.4) - "@csstools/css-tokenizer": 3.0.4 - "@csstools/postcss-progressive-custom-properties": 4.2.1(postcss@8.5.10) - "@csstools/utilities": 2.0.0(postcss@8.5.10) + '@csstools/css-color-parser': 3.1.0(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4) + '@csstools/css-parser-algorithms': 3.0.5(@csstools/css-tokenizer@3.0.4) + '@csstools/css-tokenizer': 3.0.4 + '@csstools/postcss-progressive-custom-properties': 4.2.1(postcss@8.5.10) + '@csstools/utilities': 2.0.0(postcss@8.5.10) postcss: 8.5.10 - "@csstools/postcss-color-function@4.0.12(postcss@8.5.10)": + '@csstools/postcss-color-function@4.0.12(postcss@8.5.10)': dependencies: - "@csstools/css-color-parser": 3.1.0(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4) - "@csstools/css-parser-algorithms": 3.0.5(@csstools/css-tokenizer@3.0.4) - "@csstools/css-tokenizer": 3.0.4 - "@csstools/postcss-progressive-custom-properties": 4.2.1(postcss@8.5.10) - "@csstools/utilities": 2.0.0(postcss@8.5.10) + '@csstools/css-color-parser': 3.1.0(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4) + '@csstools/css-parser-algorithms': 3.0.5(@csstools/css-tokenizer@3.0.4) + '@csstools/css-tokenizer': 3.0.4 + '@csstools/postcss-progressive-custom-properties': 4.2.1(postcss@8.5.10) + '@csstools/utilities': 2.0.0(postcss@8.5.10) postcss: 8.5.10 - "@csstools/postcss-color-mix-function@3.0.12(postcss@8.5.10)": + '@csstools/postcss-color-mix-function@3.0.12(postcss@8.5.10)': dependencies: - "@csstools/css-color-parser": 3.1.0(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4) - "@csstools/css-parser-algorithms": 3.0.5(@csstools/css-tokenizer@3.0.4) - "@csstools/css-tokenizer": 3.0.4 - "@csstools/postcss-progressive-custom-properties": 4.2.1(postcss@8.5.10) - "@csstools/utilities": 2.0.0(postcss@8.5.10) + '@csstools/css-color-parser': 3.1.0(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4) + '@csstools/css-parser-algorithms': 3.0.5(@csstools/css-tokenizer@3.0.4) + '@csstools/css-tokenizer': 3.0.4 + '@csstools/postcss-progressive-custom-properties': 4.2.1(postcss@8.5.10) + '@csstools/utilities': 2.0.0(postcss@8.5.10) postcss: 8.5.10 - "@csstools/postcss-color-mix-variadic-function-arguments@1.0.2(postcss@8.5.10)": + '@csstools/postcss-color-mix-variadic-function-arguments@1.0.2(postcss@8.5.10)': dependencies: - "@csstools/css-color-parser": 3.1.0(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4) - "@csstools/css-parser-algorithms": 3.0.5(@csstools/css-tokenizer@3.0.4) - "@csstools/css-tokenizer": 3.0.4 - "@csstools/postcss-progressive-custom-properties": 4.2.1(postcss@8.5.10) - "@csstools/utilities": 2.0.0(postcss@8.5.10) + '@csstools/css-color-parser': 3.1.0(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4) + '@csstools/css-parser-algorithms': 3.0.5(@csstools/css-tokenizer@3.0.4) + '@csstools/css-tokenizer': 3.0.4 + '@csstools/postcss-progressive-custom-properties': 4.2.1(postcss@8.5.10) + '@csstools/utilities': 2.0.0(postcss@8.5.10) postcss: 8.5.10 - "@csstools/postcss-content-alt-text@2.0.8(postcss@8.5.10)": + '@csstools/postcss-content-alt-text@2.0.8(postcss@8.5.10)': dependencies: - "@csstools/css-parser-algorithms": 3.0.5(@csstools/css-tokenizer@3.0.4) - "@csstools/css-tokenizer": 3.0.4 - "@csstools/postcss-progressive-custom-properties": 4.2.1(postcss@8.5.10) - "@csstools/utilities": 2.0.0(postcss@8.5.10) + '@csstools/css-parser-algorithms': 3.0.5(@csstools/css-tokenizer@3.0.4) + '@csstools/css-tokenizer': 3.0.4 + '@csstools/postcss-progressive-custom-properties': 4.2.1(postcss@8.5.10) + '@csstools/utilities': 2.0.0(postcss@8.5.10) postcss: 8.5.10 - "@csstools/postcss-contrast-color-function@2.0.12(postcss@8.5.10)": + '@csstools/postcss-contrast-color-function@2.0.12(postcss@8.5.10)': dependencies: - "@csstools/css-color-parser": 3.1.0(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4) - "@csstools/css-parser-algorithms": 3.0.5(@csstools/css-tokenizer@3.0.4) - "@csstools/css-tokenizer": 3.0.4 - "@csstools/postcss-progressive-custom-properties": 4.2.1(postcss@8.5.10) - "@csstools/utilities": 2.0.0(postcss@8.5.10) + '@csstools/css-color-parser': 3.1.0(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4) + '@csstools/css-parser-algorithms': 3.0.5(@csstools/css-tokenizer@3.0.4) + '@csstools/css-tokenizer': 3.0.4 + '@csstools/postcss-progressive-custom-properties': 4.2.1(postcss@8.5.10) + '@csstools/utilities': 2.0.0(postcss@8.5.10) postcss: 8.5.10 - "@csstools/postcss-exponential-functions@2.0.9(postcss@8.5.10)": + '@csstools/postcss-exponential-functions@2.0.9(postcss@8.5.10)': dependencies: - "@csstools/css-calc": 2.1.4(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4) - "@csstools/css-parser-algorithms": 3.0.5(@csstools/css-tokenizer@3.0.4) - "@csstools/css-tokenizer": 3.0.4 + '@csstools/css-calc': 2.1.4(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4) + '@csstools/css-parser-algorithms': 3.0.5(@csstools/css-tokenizer@3.0.4) + '@csstools/css-tokenizer': 3.0.4 postcss: 8.5.10 - "@csstools/postcss-font-format-keywords@4.0.0(postcss@8.5.10)": + '@csstools/postcss-font-format-keywords@4.0.0(postcss@8.5.10)': dependencies: - "@csstools/utilities": 2.0.0(postcss@8.5.10) + '@csstools/utilities': 2.0.0(postcss@8.5.10) postcss: 8.5.10 postcss-value-parser: 4.2.0 - "@csstools/postcss-gamut-mapping@2.0.11(postcss@8.5.10)": + '@csstools/postcss-gamut-mapping@2.0.11(postcss@8.5.10)': dependencies: - "@csstools/css-color-parser": 3.1.0(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4) - "@csstools/css-parser-algorithms": 3.0.5(@csstools/css-tokenizer@3.0.4) - "@csstools/css-tokenizer": 3.0.4 + '@csstools/css-color-parser': 3.1.0(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4) + '@csstools/css-parser-algorithms': 3.0.5(@csstools/css-tokenizer@3.0.4) + '@csstools/css-tokenizer': 3.0.4 postcss: 8.5.10 - "@csstools/postcss-gradients-interpolation-method@5.0.12(postcss@8.5.10)": + '@csstools/postcss-gradients-interpolation-method@5.0.12(postcss@8.5.10)': dependencies: - "@csstools/css-color-parser": 3.1.0(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4) - "@csstools/css-parser-algorithms": 3.0.5(@csstools/css-tokenizer@3.0.4) - "@csstools/css-tokenizer": 3.0.4 - "@csstools/postcss-progressive-custom-properties": 4.2.1(postcss@8.5.10) - "@csstools/utilities": 2.0.0(postcss@8.5.10) + '@csstools/css-color-parser': 3.1.0(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4) + '@csstools/css-parser-algorithms': 3.0.5(@csstools/css-tokenizer@3.0.4) + '@csstools/css-tokenizer': 3.0.4 + '@csstools/postcss-progressive-custom-properties': 4.2.1(postcss@8.5.10) + '@csstools/utilities': 2.0.0(postcss@8.5.10) postcss: 8.5.10 - "@csstools/postcss-hwb-function@4.0.12(postcss@8.5.10)": + '@csstools/postcss-hwb-function@4.0.12(postcss@8.5.10)': dependencies: - "@csstools/css-color-parser": 3.1.0(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4) - "@csstools/css-parser-algorithms": 3.0.5(@csstools/css-tokenizer@3.0.4) - "@csstools/css-tokenizer": 3.0.4 - "@csstools/postcss-progressive-custom-properties": 4.2.1(postcss@8.5.10) - "@csstools/utilities": 2.0.0(postcss@8.5.10) + '@csstools/css-color-parser': 3.1.0(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4) + '@csstools/css-parser-algorithms': 3.0.5(@csstools/css-tokenizer@3.0.4) + '@csstools/css-tokenizer': 3.0.4 + '@csstools/postcss-progressive-custom-properties': 4.2.1(postcss@8.5.10) + '@csstools/utilities': 2.0.0(postcss@8.5.10) postcss: 8.5.10 - "@csstools/postcss-ic-unit@4.0.4(postcss@8.5.10)": + '@csstools/postcss-ic-unit@4.0.4(postcss@8.5.10)': dependencies: - "@csstools/postcss-progressive-custom-properties": 4.2.1(postcss@8.5.10) - "@csstools/utilities": 2.0.0(postcss@8.5.10) + '@csstools/postcss-progressive-custom-properties': 4.2.1(postcss@8.5.10) + '@csstools/utilities': 2.0.0(postcss@8.5.10) postcss: 8.5.10 postcss-value-parser: 4.2.0 - "@csstools/postcss-initial@2.0.1(postcss@8.5.10)": + '@csstools/postcss-initial@2.0.1(postcss@8.5.10)': dependencies: postcss: 8.5.10 - "@csstools/postcss-is-pseudo-class@5.0.3(postcss@8.5.10)": + '@csstools/postcss-is-pseudo-class@5.0.3(postcss@8.5.10)': dependencies: - "@csstools/selector-specificity": 5.0.0(postcss-selector-parser@7.1.1) + '@csstools/selector-specificity': 5.0.0(postcss-selector-parser@7.1.1) postcss: 8.5.10 postcss-selector-parser: 7.1.1 - "@csstools/postcss-light-dark-function@2.0.11(postcss@8.5.10)": + '@csstools/postcss-light-dark-function@2.0.11(postcss@8.5.10)': dependencies: - "@csstools/css-parser-algorithms": 3.0.5(@csstools/css-tokenizer@3.0.4) - "@csstools/css-tokenizer": 3.0.4 - "@csstools/postcss-progressive-custom-properties": 4.2.1(postcss@8.5.10) - "@csstools/utilities": 2.0.0(postcss@8.5.10) + '@csstools/css-parser-algorithms': 3.0.5(@csstools/css-tokenizer@3.0.4) + '@csstools/css-tokenizer': 3.0.4 + '@csstools/postcss-progressive-custom-properties': 4.2.1(postcss@8.5.10) + '@csstools/utilities': 2.0.0(postcss@8.5.10) postcss: 8.5.10 - "@csstools/postcss-logical-float-and-clear@3.0.0(postcss@8.5.10)": + '@csstools/postcss-logical-float-and-clear@3.0.0(postcss@8.5.10)': dependencies: postcss: 8.5.10 - "@csstools/postcss-logical-overflow@2.0.0(postcss@8.5.10)": + '@csstools/postcss-logical-overflow@2.0.0(postcss@8.5.10)': dependencies: postcss: 8.5.10 - "@csstools/postcss-logical-overscroll-behavior@2.0.0(postcss@8.5.10)": + '@csstools/postcss-logical-overscroll-behavior@2.0.0(postcss@8.5.10)': dependencies: postcss: 8.5.10 - "@csstools/postcss-logical-resize@3.0.0(postcss@8.5.10)": + '@csstools/postcss-logical-resize@3.0.0(postcss@8.5.10)': dependencies: postcss: 8.5.10 postcss-value-parser: 4.2.0 - "@csstools/postcss-logical-viewport-units@3.0.4(postcss@8.5.10)": + '@csstools/postcss-logical-viewport-units@3.0.4(postcss@8.5.10)': dependencies: - "@csstools/css-tokenizer": 3.0.4 - "@csstools/utilities": 2.0.0(postcss@8.5.10) + '@csstools/css-tokenizer': 3.0.4 + '@csstools/utilities': 2.0.0(postcss@8.5.10) postcss: 8.5.10 - "@csstools/postcss-media-minmax@2.0.9(postcss@8.5.10)": + '@csstools/postcss-media-minmax@2.0.9(postcss@8.5.10)': dependencies: - "@csstools/css-calc": 2.1.4(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4) - "@csstools/css-parser-algorithms": 3.0.5(@csstools/css-tokenizer@3.0.4) - "@csstools/css-tokenizer": 3.0.4 - "@csstools/media-query-list-parser": 4.0.3(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4) + '@csstools/css-calc': 2.1.4(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4) + '@csstools/css-parser-algorithms': 3.0.5(@csstools/css-tokenizer@3.0.4) + '@csstools/css-tokenizer': 3.0.4 + '@csstools/media-query-list-parser': 4.0.3(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4) postcss: 8.5.10 - "@csstools/postcss-media-queries-aspect-ratio-number-values@3.0.5(postcss@8.5.10)": + '@csstools/postcss-media-queries-aspect-ratio-number-values@3.0.5(postcss@8.5.10)': dependencies: - "@csstools/css-parser-algorithms": 3.0.5(@csstools/css-tokenizer@3.0.4) - "@csstools/css-tokenizer": 3.0.4 - "@csstools/media-query-list-parser": 4.0.3(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4) + '@csstools/css-parser-algorithms': 3.0.5(@csstools/css-tokenizer@3.0.4) + '@csstools/css-tokenizer': 3.0.4 + '@csstools/media-query-list-parser': 4.0.3(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4) postcss: 8.5.10 - "@csstools/postcss-nested-calc@4.0.0(postcss@8.5.10)": + '@csstools/postcss-nested-calc@4.0.0(postcss@8.5.10)': dependencies: - "@csstools/utilities": 2.0.0(postcss@8.5.10) + '@csstools/utilities': 2.0.0(postcss@8.5.10) postcss: 8.5.10 postcss-value-parser: 4.2.0 - "@csstools/postcss-normalize-display-values@4.0.1(postcss@8.5.10)": + '@csstools/postcss-normalize-display-values@4.0.1(postcss@8.5.10)': dependencies: postcss: 8.5.10 postcss-value-parser: 4.2.0 - "@csstools/postcss-oklab-function@4.0.12(postcss@8.5.10)": + '@csstools/postcss-oklab-function@4.0.12(postcss@8.5.10)': dependencies: - "@csstools/css-color-parser": 3.1.0(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4) - "@csstools/css-parser-algorithms": 3.0.5(@csstools/css-tokenizer@3.0.4) - "@csstools/css-tokenizer": 3.0.4 - "@csstools/postcss-progressive-custom-properties": 4.2.1(postcss@8.5.10) - "@csstools/utilities": 2.0.0(postcss@8.5.10) + '@csstools/css-color-parser': 3.1.0(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4) + '@csstools/css-parser-algorithms': 3.0.5(@csstools/css-tokenizer@3.0.4) + '@csstools/css-tokenizer': 3.0.4 + '@csstools/postcss-progressive-custom-properties': 4.2.1(postcss@8.5.10) + '@csstools/utilities': 2.0.0(postcss@8.5.10) postcss: 8.5.10 - "@csstools/postcss-position-area-property@1.0.0(postcss@8.5.10)": + '@csstools/postcss-position-area-property@1.0.0(postcss@8.5.10)': dependencies: postcss: 8.5.10 - "@csstools/postcss-progressive-custom-properties@4.2.1(postcss@8.5.10)": + '@csstools/postcss-progressive-custom-properties@4.2.1(postcss@8.5.10)': dependencies: postcss: 8.5.10 postcss-value-parser: 4.2.0 - "@csstools/postcss-property-rule-prelude-list@1.0.0(postcss@8.5.10)": + '@csstools/postcss-property-rule-prelude-list@1.0.0(postcss@8.5.10)': dependencies: - "@csstools/css-parser-algorithms": 3.0.5(@csstools/css-tokenizer@3.0.4) - "@csstools/css-tokenizer": 3.0.4 + '@csstools/css-parser-algorithms': 3.0.5(@csstools/css-tokenizer@3.0.4) + '@csstools/css-tokenizer': 3.0.4 postcss: 8.5.10 - "@csstools/postcss-random-function@2.0.1(postcss@8.5.10)": + '@csstools/postcss-random-function@2.0.1(postcss@8.5.10)': dependencies: - "@csstools/css-calc": 2.1.4(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4) - "@csstools/css-parser-algorithms": 3.0.5(@csstools/css-tokenizer@3.0.4) - "@csstools/css-tokenizer": 3.0.4 + '@csstools/css-calc': 2.1.4(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4) + '@csstools/css-parser-algorithms': 3.0.5(@csstools/css-tokenizer@3.0.4) + '@csstools/css-tokenizer': 3.0.4 postcss: 8.5.10 - "@csstools/postcss-relative-color-syntax@3.0.12(postcss@8.5.10)": + '@csstools/postcss-relative-color-syntax@3.0.12(postcss@8.5.10)': dependencies: - "@csstools/css-color-parser": 3.1.0(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4) - "@csstools/css-parser-algorithms": 3.0.5(@csstools/css-tokenizer@3.0.4) - "@csstools/css-tokenizer": 3.0.4 - "@csstools/postcss-progressive-custom-properties": 4.2.1(postcss@8.5.10) - "@csstools/utilities": 2.0.0(postcss@8.5.10) + '@csstools/css-color-parser': 3.1.0(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4) + '@csstools/css-parser-algorithms': 3.0.5(@csstools/css-tokenizer@3.0.4) + '@csstools/css-tokenizer': 3.0.4 + '@csstools/postcss-progressive-custom-properties': 4.2.1(postcss@8.5.10) + '@csstools/utilities': 2.0.0(postcss@8.5.10) postcss: 8.5.10 - "@csstools/postcss-scope-pseudo-class@4.0.1(postcss@8.5.10)": + '@csstools/postcss-scope-pseudo-class@4.0.1(postcss@8.5.10)': dependencies: postcss: 8.5.10 postcss-selector-parser: 7.1.1 - "@csstools/postcss-sign-functions@1.1.4(postcss@8.5.10)": + '@csstools/postcss-sign-functions@1.1.4(postcss@8.5.10)': dependencies: - "@csstools/css-calc": 2.1.4(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4) - "@csstools/css-parser-algorithms": 3.0.5(@csstools/css-tokenizer@3.0.4) - "@csstools/css-tokenizer": 3.0.4 + '@csstools/css-calc': 2.1.4(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4) + '@csstools/css-parser-algorithms': 3.0.5(@csstools/css-tokenizer@3.0.4) + '@csstools/css-tokenizer': 3.0.4 postcss: 8.5.10 - "@csstools/postcss-stepped-value-functions@4.0.9(postcss@8.5.10)": + '@csstools/postcss-stepped-value-functions@4.0.9(postcss@8.5.10)': dependencies: - "@csstools/css-calc": 2.1.4(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4) - "@csstools/css-parser-algorithms": 3.0.5(@csstools/css-tokenizer@3.0.4) - "@csstools/css-tokenizer": 3.0.4 + '@csstools/css-calc': 2.1.4(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4) + '@csstools/css-parser-algorithms': 3.0.5(@csstools/css-tokenizer@3.0.4) + '@csstools/css-tokenizer': 3.0.4 postcss: 8.5.10 - "@csstools/postcss-syntax-descriptor-syntax-production@1.0.1(postcss@8.5.10)": + '@csstools/postcss-syntax-descriptor-syntax-production@1.0.1(postcss@8.5.10)': dependencies: - "@csstools/css-tokenizer": 3.0.4 + '@csstools/css-tokenizer': 3.0.4 postcss: 8.5.10 - "@csstools/postcss-system-ui-font-family@1.0.0(postcss@8.5.10)": + '@csstools/postcss-system-ui-font-family@1.0.0(postcss@8.5.10)': dependencies: - "@csstools/css-parser-algorithms": 3.0.5(@csstools/css-tokenizer@3.0.4) - "@csstools/css-tokenizer": 3.0.4 + '@csstools/css-parser-algorithms': 3.0.5(@csstools/css-tokenizer@3.0.4) + '@csstools/css-tokenizer': 3.0.4 postcss: 8.5.10 - "@csstools/postcss-text-decoration-shorthand@4.0.3(postcss@8.5.10)": + '@csstools/postcss-text-decoration-shorthand@4.0.3(postcss@8.5.10)': dependencies: - "@csstools/color-helpers": 5.1.0 + '@csstools/color-helpers': 5.1.0 postcss: 8.5.10 postcss-value-parser: 4.2.0 - "@csstools/postcss-trigonometric-functions@4.0.9(postcss@8.5.10)": + '@csstools/postcss-trigonometric-functions@4.0.9(postcss@8.5.10)': dependencies: - "@csstools/css-calc": 2.1.4(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4) - "@csstools/css-parser-algorithms": 3.0.5(@csstools/css-tokenizer@3.0.4) - "@csstools/css-tokenizer": 3.0.4 + '@csstools/css-calc': 2.1.4(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4) + '@csstools/css-parser-algorithms': 3.0.5(@csstools/css-tokenizer@3.0.4) + '@csstools/css-tokenizer': 3.0.4 postcss: 8.5.10 - "@csstools/postcss-unset-value@4.0.0(postcss@8.5.10)": + '@csstools/postcss-unset-value@4.0.0(postcss@8.5.10)': dependencies: postcss: 8.5.10 - "@csstools/selector-resolve-nested@3.1.0(postcss-selector-parser@7.1.1)": + '@csstools/selector-resolve-nested@3.1.0(postcss-selector-parser@7.1.1)': dependencies: postcss-selector-parser: 7.1.1 - "@csstools/selector-specificity@5.0.0(postcss-selector-parser@7.1.1)": + '@csstools/selector-specificity@5.0.0(postcss-selector-parser@7.1.1)': dependencies: postcss-selector-parser: 7.1.1 - "@csstools/utilities@2.0.0(postcss@8.5.10)": + '@csstools/utilities@2.0.0(postcss@8.5.10)': dependencies: postcss: 8.5.10 - "@emnapi/core@1.9.2": + '@emnapi/core@1.9.2': dependencies: - "@emnapi/wasi-threads": 1.2.1 + '@emnapi/wasi-threads': 1.2.1 tslib: 2.8.1 optional: true - "@emnapi/runtime@1.9.2": + '@emnapi/runtime@1.9.2': dependencies: tslib: 2.8.1 optional: true - "@emnapi/wasi-threads@1.2.1": + '@emnapi/wasi-threads@1.2.1': dependencies: tslib: 2.8.1 optional: true - "@es-joy/jsdoccomment@0.78.0": + '@es-joy/jsdoccomment@0.78.0': dependencies: - "@types/estree": 1.0.8 - "@typescript-eslint/types": 8.58.2 + '@types/estree': 1.0.8 + '@typescript-eslint/types': 8.58.2 comment-parser: 1.4.1 esquery: 1.7.0 jsdoc-type-pratt-parser: 7.0.0 - "@es-joy/resolve.exports@1.2.0": {} + '@es-joy/resolve.exports@1.2.0': {} - "@esbuild/aix-ppc64@0.27.7": + '@esbuild/aix-ppc64@0.27.7': optional: true - "@esbuild/android-arm64@0.27.7": + '@esbuild/android-arm64@0.27.7': optional: true - "@esbuild/android-arm@0.27.7": + '@esbuild/android-arm@0.27.7': optional: true - "@esbuild/android-x64@0.27.7": + '@esbuild/android-x64@0.27.7': optional: true - "@esbuild/darwin-arm64@0.27.7": + '@esbuild/darwin-arm64@0.27.7': optional: true - "@esbuild/darwin-x64@0.27.7": + '@esbuild/darwin-x64@0.27.7': optional: true - "@esbuild/freebsd-arm64@0.27.7": + '@esbuild/freebsd-arm64@0.27.7': optional: true - "@esbuild/freebsd-x64@0.27.7": + '@esbuild/freebsd-x64@0.27.7': optional: true - "@esbuild/linux-arm64@0.27.7": + '@esbuild/linux-arm64@0.27.7': optional: true - "@esbuild/linux-arm@0.27.7": + '@esbuild/linux-arm@0.27.7': optional: true - "@esbuild/linux-ia32@0.27.7": + '@esbuild/linux-ia32@0.27.7': optional: true - "@esbuild/linux-loong64@0.27.7": + '@esbuild/linux-loong64@0.27.7': optional: true - "@esbuild/linux-mips64el@0.27.7": + '@esbuild/linux-mips64el@0.27.7': optional: true - "@esbuild/linux-ppc64@0.27.7": + '@esbuild/linux-ppc64@0.27.7': optional: true - "@esbuild/linux-riscv64@0.27.7": + '@esbuild/linux-riscv64@0.27.7': optional: true - "@esbuild/linux-s390x@0.27.7": + '@esbuild/linux-s390x@0.27.7': optional: true - "@esbuild/linux-x64@0.27.7": + '@esbuild/linux-x64@0.27.7': optional: true - "@esbuild/netbsd-arm64@0.27.7": + '@esbuild/netbsd-arm64@0.27.7': optional: true - "@esbuild/netbsd-x64@0.27.7": + '@esbuild/netbsd-x64@0.27.7': optional: true - "@esbuild/openbsd-arm64@0.27.7": + '@esbuild/openbsd-arm64@0.27.7': optional: true - "@esbuild/openbsd-x64@0.27.7": + '@esbuild/openbsd-x64@0.27.7': optional: true - "@esbuild/openharmony-arm64@0.27.7": + '@esbuild/openharmony-arm64@0.27.7': optional: true - "@esbuild/sunos-x64@0.27.7": + '@esbuild/sunos-x64@0.27.7': optional: true - "@esbuild/win32-arm64@0.27.7": + '@esbuild/win32-arm64@0.27.7': optional: true - "@esbuild/win32-ia32@0.27.7": + '@esbuild/win32-ia32@0.27.7': optional: true - "@esbuild/win32-x64@0.27.7": + '@esbuild/win32-x64@0.27.7': optional: true - "@eslint-community/eslint-utils@4.9.1(eslint@8.57.1)": + '@eslint-community/eslint-utils@4.9.1(eslint@8.57.1)': dependencies: eslint: 8.57.1 eslint-visitor-keys: 3.4.3 - "@eslint-community/regexpp@4.12.2": {} + '@eslint-community/regexpp@4.12.2': {} - "@eslint/eslintrc@2.1.4": + '@eslint/eslintrc@2.1.4': dependencies: ajv: 6.14.0 debug: 4.4.3 @@ -11802,92 +7952,92 @@ snapshots: transitivePeerDependencies: - supports-color - "@eslint/js@8.57.1": {} + '@eslint/js@8.57.1': {} - "@fastify/busboy@2.1.1": {} + '@fastify/busboy@2.1.1': {} - "@floating-ui/core@1.7.5": + '@floating-ui/core@1.7.5': dependencies: - "@floating-ui/utils": 0.2.11 + '@floating-ui/utils': 0.2.11 - "@floating-ui/dom@1.7.4": + '@floating-ui/dom@1.7.4': dependencies: - "@floating-ui/core": 1.7.5 - "@floating-ui/utils": 0.2.11 + '@floating-ui/core': 1.7.5 + '@floating-ui/utils': 0.2.11 - "@floating-ui/dom@1.7.6": + '@floating-ui/dom@1.7.6': dependencies: - "@floating-ui/core": 1.7.5 - "@floating-ui/utils": 0.2.11 + '@floating-ui/core': 1.7.5 + '@floating-ui/utils': 0.2.11 - "@floating-ui/react-dom@2.1.8(react-dom@19.2.5(react@19.2.5))(react@19.2.5)": + '@floating-ui/react-dom@2.1.8(react-dom@19.2.5(react@19.2.5))(react@19.2.5)': dependencies: - "@floating-ui/dom": 1.7.6 + '@floating-ui/dom': 1.7.6 react: 19.2.5 react-dom: 19.2.5(react@19.2.5) - "@floating-ui/react@0.27.19(react-dom@19.2.5(react@19.2.5))(react@19.2.5)": + '@floating-ui/react@0.27.19(react-dom@19.2.5(react@19.2.5))(react@19.2.5)': dependencies: - "@floating-ui/react-dom": 2.1.8(react-dom@19.2.5(react@19.2.5))(react@19.2.5) - "@floating-ui/utils": 0.2.11 + '@floating-ui/react-dom': 2.1.8(react-dom@19.2.5(react@19.2.5))(react@19.2.5) + '@floating-ui/utils': 0.2.11 react: 19.2.5 react-dom: 19.2.5(react@19.2.5) tabbable: 6.4.0 - "@floating-ui/utils@0.2.11": {} + '@floating-ui/utils@0.2.11': {} - "@fontsource/inconsolata@5.2.8": {} + '@fontsource/inconsolata@5.2.8': {} - "@fontsource/inter@5.2.8": {} + '@fontsource/inter@5.2.8': {} - "@formatjs/ecma402-abstract@2.3.6": + '@formatjs/ecma402-abstract@2.3.6': dependencies: - "@formatjs/fast-memoize": 2.2.7 - "@formatjs/intl-localematcher": 0.6.2 + '@formatjs/fast-memoize': 2.2.7 + '@formatjs/intl-localematcher': 0.6.2 decimal.js: 10.6.0 tslib: 2.8.1 - "@formatjs/fast-memoize@2.2.7": + '@formatjs/fast-memoize@2.2.7': dependencies: tslib: 2.8.1 - "@formatjs/fast-memoize@3.1.2": {} + '@formatjs/fast-memoize@3.1.2': {} - "@formatjs/intl-durationformat@0.10.4": + '@formatjs/intl-durationformat@0.10.4': dependencies: - "@formatjs/intl-localematcher": 0.8.3 + '@formatjs/intl-localematcher': 0.8.3 - "@formatjs/intl-localematcher@0.6.2": + '@formatjs/intl-localematcher@0.6.2': dependencies: tslib: 2.8.1 - "@formatjs/intl-localematcher@0.8.3": + '@formatjs/intl-localematcher@0.8.3': dependencies: - "@formatjs/fast-memoize": 3.1.2 + '@formatjs/fast-memoize': 3.1.2 - "@formatjs/intl-segmenter@11.7.12": + '@formatjs/intl-segmenter@11.7.12': dependencies: - "@formatjs/ecma402-abstract": 2.3.6 - "@formatjs/intl-localematcher": 0.6.2 + '@formatjs/ecma402-abstract': 2.3.6 + '@formatjs/intl-localematcher': 0.6.2 tslib: 2.8.1 - "@gulpjs/to-absolute-glob@4.0.0": + '@gulpjs/to-absolute-glob@4.0.0': dependencies: is-negated-glob: 1.0.0 - "@humanwhocodes/config-array@0.13.0": + '@humanwhocodes/config-array@0.13.0': dependencies: - "@humanwhocodes/object-schema": 2.0.3 + '@humanwhocodes/object-schema': 2.0.3 debug: 4.4.3 minimatch: 10.2.5 transitivePeerDependencies: - supports-color - "@humanwhocodes/module-importer@1.0.1": {} + '@humanwhocodes/module-importer@1.0.1': {} - "@humanwhocodes/object-schema@2.0.3": {} + '@humanwhocodes/object-schema@2.0.3': {} - "@isaacs/cliui@8.0.2": + '@isaacs/cliui@8.0.2': dependencies: string-width: 5.1.2 string-width-cjs: string-width@4.2.3 @@ -11896,7 +8046,7 @@ snapshots: wrap-ansi: 8.1.0 wrap-ansi-cjs: wrap-ansi@7.0.0 - "@joshwooding/vite-plugin-react-docgen-typescript@0.7.0(typescript@5.9.3)(vite@8.0.8(@types/node@24.12.2)(esbuild@0.27.7)(jiti@2.6.1)(sass@1.99.0)(terser@5.46.1)(yaml@2.8.3))": + '@joshwooding/vite-plugin-react-docgen-typescript@0.7.0(typescript@5.9.3)(vite@8.0.8(@types/node@24.12.2)(esbuild@0.27.7)(jiti@2.6.1)(sass@1.99.0)(terser@5.46.1)(yaml@2.8.3))': dependencies: glob: 10.5.0 react-docgen-typescript: 2.4.0(typescript@5.9.3) @@ -11904,41 +8054,41 @@ snapshots: optionalDependencies: typescript: 5.9.3 - "@jridgewell/gen-mapping@0.3.13": + '@jridgewell/gen-mapping@0.3.13': dependencies: - "@jridgewell/sourcemap-codec": 1.5.5 - "@jridgewell/trace-mapping": 0.3.31 + '@jridgewell/sourcemap-codec': 1.5.5 + '@jridgewell/trace-mapping': 0.3.31 - "@jridgewell/remapping@2.3.5": + '@jridgewell/remapping@2.3.5': dependencies: - "@jridgewell/gen-mapping": 0.3.13 - "@jridgewell/trace-mapping": 0.3.31 + '@jridgewell/gen-mapping': 0.3.13 + '@jridgewell/trace-mapping': 0.3.31 - "@jridgewell/resolve-uri@3.1.2": {} + '@jridgewell/resolve-uri@3.1.2': {} - "@jridgewell/source-map@0.3.11": + '@jridgewell/source-map@0.3.11': dependencies: - "@jridgewell/gen-mapping": 0.3.13 - "@jridgewell/trace-mapping": 0.3.31 + '@jridgewell/gen-mapping': 0.3.13 + '@jridgewell/trace-mapping': 0.3.31 - "@jridgewell/sourcemap-codec@1.5.5": {} + '@jridgewell/sourcemap-codec@1.5.5': {} - "@jridgewell/trace-mapping@0.3.31": + '@jridgewell/trace-mapping@0.3.31': dependencies: - "@jridgewell/resolve-uri": 3.1.2 - "@jridgewell/sourcemap-codec": 1.5.5 + '@jridgewell/resolve-uri': 3.1.2 + '@jridgewell/sourcemap-codec': 1.5.5 - "@livekit/components-core@0.12.13(livekit-client@2.18.3(@types/dom-mediacapture-record@1.0.22))(tslib@2.8.1)": + '@livekit/components-core@0.12.13(livekit-client@2.18.3(@types/dom-mediacapture-record@1.0.22))(tslib@2.8.1)': dependencies: - "@floating-ui/dom": 1.7.4 + '@floating-ui/dom': 1.7.4 livekit-client: 2.18.3(@types/dom-mediacapture-record@1.0.22) loglevel: 1.9.1 rxjs: 7.8.2 tslib: 2.8.1 - "@livekit/components-react@2.9.20(livekit-client@2.18.3(@types/dom-mediacapture-record@1.0.22))(react-dom@19.2.5(react@19.2.5))(react@19.2.5)(tslib@2.8.1)": + '@livekit/components-react@2.9.20(livekit-client@2.18.3(@types/dom-mediacapture-record@1.0.22))(react-dom@19.2.5(react@19.2.5))(react@19.2.5)(tslib@2.8.1)': dependencies: - "@livekit/components-core": 0.12.13(livekit-client@2.18.3(@types/dom-mediacapture-record@1.0.22))(tslib@2.8.1) + '@livekit/components-core': 0.12.13(livekit-client@2.18.3(@types/dom-mediacapture-record@1.0.22))(tslib@2.8.1) clsx: 2.1.1 events: 3.3.0 jose: 6.2.2 @@ -11948,757 +8098,836 @@ snapshots: tslib: 2.8.1 usehooks-ts: 3.1.1(react@19.2.5) - "@livekit/mutex@1.1.1": {} + '@livekit/mutex@1.1.1': {} - "@livekit/protocol@1.45.3": + '@livekit/protocol@1.45.3': dependencies: - "@bufbuild/protobuf": 1.10.1 + '@bufbuild/protobuf': 1.10.1 - "@livekit/track-processors@0.7.2(@types/dom-mediacapture-transform@0.1.11)(livekit-client@2.18.3(@types/dom-mediacapture-record@1.0.22))": + '@livekit/track-processors@0.7.2(@types/dom-mediacapture-transform@0.1.11)(livekit-client@2.18.3(@types/dom-mediacapture-record@1.0.22))': dependencies: - "@mediapipe/tasks-vision": 0.10.34 - "@types/dom-mediacapture-transform": 0.1.11 + '@mediapipe/tasks-vision': 0.10.34 + '@types/dom-mediacapture-transform': 0.1.11 livekit-client: 2.18.3(@types/dom-mediacapture-record@1.0.22) - "@matrix-org/matrix-sdk-crypto-wasm@18.0.0": {} + '@matrix-org/matrix-sdk-crypto-wasm@18.0.0': {} - "@mdx-js/react@3.1.1(@types/react@19.2.14)(react@19.2.5)": + '@mdx-js/react@3.1.1(@types/react@19.2.14)(react@19.2.5)': dependencies: - "@types/mdx": 2.0.13 - "@types/react": 19.2.14 + '@types/mdx': 2.0.13 + '@types/react': 19.2.14 react: 19.2.5 - "@mediapipe/tasks-vision@0.10.34": {} + '@mediapipe/tasks-vision@0.10.34': {} - "@napi-rs/wasm-runtime@1.1.4(@emnapi/core@1.9.2)(@emnapi/runtime@1.9.2)": + '@napi-rs/wasm-runtime@1.1.4(@emnapi/core@1.9.2)(@emnapi/runtime@1.9.2)': dependencies: - "@emnapi/core": 1.9.2 - "@emnapi/runtime": 1.9.2 - "@tybys/wasm-util": 0.10.1 + '@emnapi/core': 1.9.2 + '@emnapi/runtime': 1.9.2 + '@tybys/wasm-util': 0.10.1 optional: true - "@nicolo-ribaudo/eslint-scope-5-internals@5.1.1-v1": + '@nicolo-ribaudo/eslint-scope-5-internals@5.1.1-v1': dependencies: eslint-scope: 5.1.1 - "@nodelib/fs.scandir@2.1.5": + '@nodelib/fs.scandir@2.1.5': dependencies: - "@nodelib/fs.stat": 2.0.5 + '@nodelib/fs.stat': 2.0.5 run-parallel: 1.2.0 - "@nodelib/fs.stat@2.0.5": {} + '@nodelib/fs.stat@2.0.5': {} - "@nodelib/fs.walk@1.2.8": + '@nodelib/fs.walk@1.2.8': dependencies: - "@nodelib/fs.scandir": 2.1.5 + '@nodelib/fs.scandir': 2.1.5 fastq: 1.20.1 - "@octokit/auth-token@4.0.0": {} + '@octokit/auth-token@4.0.0': {} - "@octokit/core@5.2.2": + '@octokit/core@5.2.2': dependencies: - "@octokit/auth-token": 4.0.0 - "@octokit/graphql": 7.1.1 - "@octokit/request": 8.4.1 - "@octokit/request-error": 5.1.1 - "@octokit/types": 13.10.0 + '@octokit/auth-token': 4.0.0 + '@octokit/graphql': 7.1.1 + '@octokit/request': 8.4.1 + '@octokit/request-error': 5.1.1 + '@octokit/types': 13.10.0 before-after-hook: 2.2.3 universal-user-agent: 6.0.1 - "@octokit/endpoint@9.0.6": + '@octokit/endpoint@9.0.6': dependencies: - "@octokit/types": 13.10.0 + '@octokit/types': 13.10.0 universal-user-agent: 6.0.1 - "@octokit/graphql@7.1.1": + '@octokit/graphql@7.1.1': dependencies: - "@octokit/request": 8.4.1 - "@octokit/types": 13.10.0 + '@octokit/request': 8.4.1 + '@octokit/types': 13.10.0 universal-user-agent: 6.0.1 - "@octokit/openapi-types@20.0.0": {} + '@octokit/openapi-types@20.0.0': {} - "@octokit/openapi-types@24.2.0": {} + '@octokit/openapi-types@24.2.0': {} - "@octokit/plugin-paginate-rest@9.2.2(@octokit/core@5.2.2)": + '@octokit/plugin-paginate-rest@9.2.2(@octokit/core@5.2.2)': dependencies: - "@octokit/core": 5.2.2 - "@octokit/types": 12.6.0 + '@octokit/core': 5.2.2 + '@octokit/types': 12.6.0 - "@octokit/plugin-rest-endpoint-methods@10.4.1(@octokit/core@5.2.2)": + '@octokit/plugin-rest-endpoint-methods@10.4.1(@octokit/core@5.2.2)': dependencies: - "@octokit/core": 5.2.2 - "@octokit/types": 12.6.0 + '@octokit/core': 5.2.2 + '@octokit/types': 12.6.0 - "@octokit/request-error@5.1.1": + '@octokit/request-error@5.1.1': dependencies: - "@octokit/types": 13.10.0 + '@octokit/types': 13.10.0 deprecation: 2.3.1 once: 1.4.0 - "@octokit/request@8.4.1": + '@octokit/request@8.4.1': dependencies: - "@octokit/endpoint": 9.0.6 - "@octokit/request-error": 5.1.1 - "@octokit/types": 13.10.0 + '@octokit/endpoint': 9.0.6 + '@octokit/request-error': 5.1.1 + '@octokit/types': 13.10.0 universal-user-agent: 6.0.1 - "@octokit/types@12.6.0": + '@octokit/types@12.6.0': dependencies: - "@octokit/openapi-types": 20.0.0 + '@octokit/openapi-types': 20.0.0 - "@octokit/types@13.10.0": + '@octokit/types@13.10.0': dependencies: - "@octokit/openapi-types": 24.2.0 + '@octokit/openapi-types': 24.2.0 - "@oxc-project/types@0.124.0": {} + '@oxc-project/types@0.124.0': {} - "@oxc-resolver/binding-android-arm-eabi@11.19.1": + '@oxc-resolver/binding-android-arm-eabi@11.19.1': optional: true - "@oxc-resolver/binding-android-arm64@11.19.1": + '@oxc-resolver/binding-android-arm64@11.19.1': optional: true - "@oxc-resolver/binding-darwin-arm64@11.19.1": + '@oxc-resolver/binding-darwin-arm64@11.19.1': optional: true - "@oxc-resolver/binding-darwin-x64@11.19.1": + '@oxc-resolver/binding-darwin-x64@11.19.1': optional: true - "@oxc-resolver/binding-freebsd-x64@11.19.1": + '@oxc-resolver/binding-freebsd-x64@11.19.1': optional: true - "@oxc-resolver/binding-linux-arm-gnueabihf@11.19.1": + '@oxc-resolver/binding-linux-arm-gnueabihf@11.19.1': optional: true - "@oxc-resolver/binding-linux-arm-musleabihf@11.19.1": + '@oxc-resolver/binding-linux-arm-musleabihf@11.19.1': optional: true - "@oxc-resolver/binding-linux-arm64-gnu@11.19.1": + '@oxc-resolver/binding-linux-arm64-gnu@11.19.1': optional: true - "@oxc-resolver/binding-linux-arm64-musl@11.19.1": + '@oxc-resolver/binding-linux-arm64-musl@11.19.1': optional: true - "@oxc-resolver/binding-linux-ppc64-gnu@11.19.1": + '@oxc-resolver/binding-linux-ppc64-gnu@11.19.1': optional: true - "@oxc-resolver/binding-linux-riscv64-gnu@11.19.1": + '@oxc-resolver/binding-linux-riscv64-gnu@11.19.1': optional: true - "@oxc-resolver/binding-linux-riscv64-musl@11.19.1": + '@oxc-resolver/binding-linux-riscv64-musl@11.19.1': optional: true - "@oxc-resolver/binding-linux-s390x-gnu@11.19.1": + '@oxc-resolver/binding-linux-s390x-gnu@11.19.1': optional: true - "@oxc-resolver/binding-linux-x64-gnu@11.19.1": + '@oxc-resolver/binding-linux-x64-gnu@11.19.1': optional: true - "@oxc-resolver/binding-linux-x64-musl@11.19.1": + '@oxc-resolver/binding-linux-x64-musl@11.19.1': optional: true - "@oxc-resolver/binding-openharmony-arm64@11.19.1": + '@oxc-resolver/binding-openharmony-arm64@11.19.1': optional: true - "@oxc-resolver/binding-wasm32-wasi@11.19.1(@emnapi/core@1.9.2)(@emnapi/runtime@1.9.2)": + '@oxc-resolver/binding-wasm32-wasi@11.19.1(@emnapi/core@1.9.2)(@emnapi/runtime@1.9.2)': dependencies: - "@napi-rs/wasm-runtime": 1.1.4(@emnapi/core@1.9.2)(@emnapi/runtime@1.9.2) + '@napi-rs/wasm-runtime': 1.1.4(@emnapi/core@1.9.2)(@emnapi/runtime@1.9.2) transitivePeerDependencies: - - "@emnapi/core" - - "@emnapi/runtime" + - '@emnapi/core' + - '@emnapi/runtime' optional: true - "@oxc-resolver/binding-win32-arm64-msvc@11.19.1": + '@oxc-resolver/binding-win32-arm64-msvc@11.19.1': optional: true - "@oxc-resolver/binding-win32-ia32-msvc@11.19.1": + '@oxc-resolver/binding-win32-ia32-msvc@11.19.1': optional: true - "@oxc-resolver/binding-win32-x64-msvc@11.19.1": + '@oxc-resolver/binding-win32-x64-msvc@11.19.1': optional: true - "@parcel/watcher-android-arm64@2.5.6": + '@parcel/watcher-android-arm64@2.5.6': optional: true - "@parcel/watcher-darwin-arm64@2.5.6": + '@parcel/watcher-darwin-arm64@2.5.6': optional: true - "@parcel/watcher-darwin-x64@2.5.6": + '@parcel/watcher-darwin-x64@2.5.6': optional: true - "@parcel/watcher-freebsd-x64@2.5.6": + '@parcel/watcher-freebsd-x64@2.5.6': optional: true - "@parcel/watcher-linux-arm-glibc@2.5.6": + '@parcel/watcher-linux-arm-glibc@2.5.6': optional: true - "@parcel/watcher-linux-arm-musl@2.5.6": + '@parcel/watcher-linux-arm-musl@2.5.6': optional: true - "@parcel/watcher-linux-arm64-glibc@2.5.6": + '@parcel/watcher-linux-arm64-glibc@2.5.6': optional: true - "@parcel/watcher-linux-arm64-musl@2.5.6": + '@parcel/watcher-linux-arm64-musl@2.5.6': optional: true - "@parcel/watcher-linux-x64-glibc@2.5.6": + '@parcel/watcher-linux-x64-glibc@2.5.6': optional: true - "@parcel/watcher-linux-x64-musl@2.5.6": + '@parcel/watcher-linux-x64-musl@2.5.6': optional: true - "@parcel/watcher-win32-arm64@2.5.6": + '@parcel/watcher-win32-arm64@2.5.6': optional: true - "@parcel/watcher-win32-ia32@2.5.6": + '@parcel/watcher-win32-ia32@2.5.6': optional: true - "@parcel/watcher-win32-x64@2.5.6": + '@parcel/watcher-win32-x64@2.5.6': optional: true - "@parcel/watcher@2.5.6": + '@parcel/watcher@2.5.6': dependencies: detect-libc: 2.1.2 is-glob: 4.0.3 node-addon-api: 7.1.1 picomatch: 4.0.4 optionalDependencies: - "@parcel/watcher-android-arm64": 2.5.6 - "@parcel/watcher-darwin-arm64": 2.5.6 - "@parcel/watcher-darwin-x64": 2.5.6 - "@parcel/watcher-freebsd-x64": 2.5.6 - "@parcel/watcher-linux-arm-glibc": 2.5.6 - "@parcel/watcher-linux-arm-musl": 2.5.6 - "@parcel/watcher-linux-arm64-glibc": 2.5.6 - "@parcel/watcher-linux-arm64-musl": 2.5.6 - "@parcel/watcher-linux-x64-glibc": 2.5.6 - "@parcel/watcher-linux-x64-musl": 2.5.6 - "@parcel/watcher-win32-arm64": 2.5.6 - "@parcel/watcher-win32-ia32": 2.5.6 - "@parcel/watcher-win32-x64": 2.5.6 + '@parcel/watcher-android-arm64': 2.5.6 + '@parcel/watcher-darwin-arm64': 2.5.6 + '@parcel/watcher-darwin-x64': 2.5.6 + '@parcel/watcher-freebsd-x64': 2.5.6 + '@parcel/watcher-linux-arm-glibc': 2.5.6 + '@parcel/watcher-linux-arm-musl': 2.5.6 + '@parcel/watcher-linux-arm64-glibc': 2.5.6 + '@parcel/watcher-linux-arm64-musl': 2.5.6 + '@parcel/watcher-linux-x64-glibc': 2.5.6 + '@parcel/watcher-linux-x64-musl': 2.5.6 + '@parcel/watcher-win32-arm64': 2.5.6 + '@parcel/watcher-win32-ia32': 2.5.6 + '@parcel/watcher-win32-x64': 2.5.6 optional: true - "@pkgjs/parseargs@0.11.0": + '@pkgjs/parseargs@0.11.0': optional: true - "@playwright/test@1.59.1": + '@playwright/test@1.59.1': dependencies: playwright: 1.59.1 - "@radix-ui/number@1.1.1": {} + '@radix-ui/number@1.1.1': {} - "@radix-ui/primitive@1.1.3": {} + '@radix-ui/primitive@1.1.3': {} - "@radix-ui/react-arrow@1.1.7(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5)": + '@radix-ui/react-arrow@1.1.7(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5)': dependencies: - "@radix-ui/react-primitive": 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5) + '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5) react: 19.2.5 react-dom: 19.2.5(react@19.2.5) optionalDependencies: - "@types/react": 19.2.14 - "@types/react-dom": 19.2.3(@types/react@19.2.14) + '@types/react': 19.2.14 + '@types/react-dom': 19.2.3(@types/react@19.2.14) - "@radix-ui/react-collection@1.1.7(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5)": + '@radix-ui/react-collection@1.1.7(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5)': dependencies: - "@radix-ui/react-compose-refs": 1.1.2(@types/react@19.2.14)(react@19.2.5) - "@radix-ui/react-context": 1.1.2(@types/react@19.2.14)(react@19.2.5) - "@radix-ui/react-primitive": 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5) - "@radix-ui/react-slot": 1.2.3(@types/react@19.2.14)(react@19.2.5) + '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.14)(react@19.2.5) + '@radix-ui/react-context': 1.1.2(@types/react@19.2.14)(react@19.2.5) + '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5) + '@radix-ui/react-slot': 1.2.3(@types/react@19.2.14)(react@19.2.5) react: 19.2.5 react-dom: 19.2.5(react@19.2.5) optionalDependencies: - "@types/react": 19.2.14 - "@types/react-dom": 19.2.3(@types/react@19.2.14) + '@types/react': 19.2.14 + '@types/react-dom': 19.2.3(@types/react@19.2.14) - "@radix-ui/react-compose-refs@1.1.2(@types/react@19.2.14)(react@19.2.5)": + '@radix-ui/react-compose-refs@1.1.2(@types/react@19.2.14)(react@19.2.5)': dependencies: react: 19.2.5 optionalDependencies: - "@types/react": 19.2.14 + '@types/react': 19.2.14 - "@radix-ui/react-context-menu@2.2.16(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5)": + '@radix-ui/react-context-menu@2.2.16(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5)': dependencies: - "@radix-ui/primitive": 1.1.3 - "@radix-ui/react-context": 1.1.2(@types/react@19.2.14)(react@19.2.5) - "@radix-ui/react-menu": 2.1.16(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5) - "@radix-ui/react-primitive": 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5) - "@radix-ui/react-use-callback-ref": 1.1.1(@types/react@19.2.14)(react@19.2.5) - "@radix-ui/react-use-controllable-state": 1.2.2(@types/react@19.2.14)(react@19.2.5) + '@radix-ui/primitive': 1.1.3 + '@radix-ui/react-context': 1.1.2(@types/react@19.2.14)(react@19.2.5) + '@radix-ui/react-menu': 2.1.16(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5) + '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5) + '@radix-ui/react-use-callback-ref': 1.1.1(@types/react@19.2.14)(react@19.2.5) + '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@19.2.14)(react@19.2.5) react: 19.2.5 react-dom: 19.2.5(react@19.2.5) optionalDependencies: - "@types/react": 19.2.14 - "@types/react-dom": 19.2.3(@types/react@19.2.14) + '@types/react': 19.2.14 + '@types/react-dom': 19.2.3(@types/react@19.2.14) - "@radix-ui/react-context@1.1.2(@types/react@19.2.14)(react@19.2.5)": + '@radix-ui/react-context@1.1.2(@types/react@19.2.14)(react@19.2.5)': dependencies: react: 19.2.5 optionalDependencies: - "@types/react": 19.2.14 + '@types/react': 19.2.14 - "@radix-ui/react-context@1.1.3(@types/react@19.2.14)(react@19.2.5)": + '@radix-ui/react-context@1.1.3(@types/react@19.2.14)(react@19.2.5)': dependencies: react: 19.2.5 optionalDependencies: - "@types/react": 19.2.14 + '@types/react': 19.2.14 - "@radix-ui/react-dialog@1.1.15(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5)": + '@radix-ui/react-dialog@1.1.15(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5)': dependencies: - "@radix-ui/primitive": 1.1.3 - "@radix-ui/react-compose-refs": 1.1.2(@types/react@19.2.14)(react@19.2.5) - "@radix-ui/react-context": 1.1.2(@types/react@19.2.14)(react@19.2.5) - "@radix-ui/react-dismissable-layer": 1.1.11(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5) - "@radix-ui/react-focus-guards": 1.1.3(@types/react@19.2.14)(react@19.2.5) - "@radix-ui/react-focus-scope": 1.1.7(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5) - "@radix-ui/react-id": 1.1.1(@types/react@19.2.14)(react@19.2.5) - "@radix-ui/react-portal": 1.1.9(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5) - "@radix-ui/react-presence": 1.1.5(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5) - "@radix-ui/react-primitive": 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5) - "@radix-ui/react-slot": 1.2.3(@types/react@19.2.14)(react@19.2.5) - "@radix-ui/react-use-controllable-state": 1.2.2(@types/react@19.2.14)(react@19.2.5) + '@radix-ui/primitive': 1.1.3 + '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.14)(react@19.2.5) + '@radix-ui/react-context': 1.1.2(@types/react@19.2.14)(react@19.2.5) + '@radix-ui/react-dismissable-layer': 1.1.11(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5) + '@radix-ui/react-focus-guards': 1.1.3(@types/react@19.2.14)(react@19.2.5) + '@radix-ui/react-focus-scope': 1.1.7(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5) + '@radix-ui/react-id': 1.1.1(@types/react@19.2.14)(react@19.2.5) + '@radix-ui/react-portal': 1.1.9(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5) + '@radix-ui/react-presence': 1.1.5(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5) + '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5) + '@radix-ui/react-slot': 1.2.3(@types/react@19.2.14)(react@19.2.5) + '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@19.2.14)(react@19.2.5) aria-hidden: 1.2.6 react: 19.2.5 react-dom: 19.2.5(react@19.2.5) react-remove-scroll: 2.7.2(@types/react@19.2.14)(react@19.2.5) optionalDependencies: - "@types/react": 19.2.14 - "@types/react-dom": 19.2.3(@types/react@19.2.14) + '@types/react': 19.2.14 + '@types/react-dom': 19.2.3(@types/react@19.2.14) - "@radix-ui/react-direction@1.1.1(@types/react@19.2.14)(react@19.2.5)": + '@radix-ui/react-direction@1.1.1(@types/react@19.2.14)(react@19.2.5)': dependencies: react: 19.2.5 optionalDependencies: - "@types/react": 19.2.14 + '@types/react': 19.2.14 - "@radix-ui/react-dismissable-layer@1.1.11(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5)": + '@radix-ui/react-dismissable-layer@1.1.11(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5)': dependencies: - "@radix-ui/primitive": 1.1.3 - "@radix-ui/react-compose-refs": 1.1.2(@types/react@19.2.14)(react@19.2.5) - "@radix-ui/react-primitive": 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5) - "@radix-ui/react-use-callback-ref": 1.1.1(@types/react@19.2.14)(react@19.2.5) - "@radix-ui/react-use-escape-keydown": 1.1.1(@types/react@19.2.14)(react@19.2.5) + '@radix-ui/primitive': 1.1.3 + '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.14)(react@19.2.5) + '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5) + '@radix-ui/react-use-callback-ref': 1.1.1(@types/react@19.2.14)(react@19.2.5) + '@radix-ui/react-use-escape-keydown': 1.1.1(@types/react@19.2.14)(react@19.2.5) react: 19.2.5 react-dom: 19.2.5(react@19.2.5) optionalDependencies: - "@types/react": 19.2.14 - "@types/react-dom": 19.2.3(@types/react@19.2.14) + '@types/react': 19.2.14 + '@types/react-dom': 19.2.3(@types/react@19.2.14) - "@radix-ui/react-dropdown-menu@2.1.16(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5)": + '@radix-ui/react-dropdown-menu@2.1.16(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5)': dependencies: - "@radix-ui/primitive": 1.1.3 - "@radix-ui/react-compose-refs": 1.1.2(@types/react@19.2.14)(react@19.2.5) - "@radix-ui/react-context": 1.1.2(@types/react@19.2.14)(react@19.2.5) - "@radix-ui/react-id": 1.1.1(@types/react@19.2.14)(react@19.2.5) - "@radix-ui/react-menu": 2.1.16(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5) - "@radix-ui/react-primitive": 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5) - "@radix-ui/react-use-controllable-state": 1.2.2(@types/react@19.2.14)(react@19.2.5) + '@radix-ui/primitive': 1.1.3 + '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.14)(react@19.2.5) + '@radix-ui/react-context': 1.1.2(@types/react@19.2.14)(react@19.2.5) + '@radix-ui/react-id': 1.1.1(@types/react@19.2.14)(react@19.2.5) + '@radix-ui/react-menu': 2.1.16(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5) + '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5) + '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@19.2.14)(react@19.2.5) react: 19.2.5 react-dom: 19.2.5(react@19.2.5) optionalDependencies: - "@types/react": 19.2.14 - "@types/react-dom": 19.2.3(@types/react@19.2.14) + '@types/react': 19.2.14 + '@types/react-dom': 19.2.3(@types/react@19.2.14) - "@radix-ui/react-focus-guards@1.1.3(@types/react@19.2.14)(react@19.2.5)": + '@radix-ui/react-focus-guards@1.1.3(@types/react@19.2.14)(react@19.2.5)': dependencies: react: 19.2.5 optionalDependencies: - "@types/react": 19.2.14 + '@types/react': 19.2.14 - "@radix-ui/react-focus-scope@1.1.7(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5)": + '@radix-ui/react-focus-scope@1.1.7(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5)': dependencies: - "@radix-ui/react-compose-refs": 1.1.2(@types/react@19.2.14)(react@19.2.5) - "@radix-ui/react-primitive": 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5) - "@radix-ui/react-use-callback-ref": 1.1.1(@types/react@19.2.14)(react@19.2.5) + '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.14)(react@19.2.5) + '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5) + '@radix-ui/react-use-callback-ref': 1.1.1(@types/react@19.2.14)(react@19.2.5) react: 19.2.5 react-dom: 19.2.5(react@19.2.5) optionalDependencies: - "@types/react": 19.2.14 - "@types/react-dom": 19.2.3(@types/react@19.2.14) + '@types/react': 19.2.14 + '@types/react-dom': 19.2.3(@types/react@19.2.14) - "@radix-ui/react-form@0.1.8(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5)": + '@radix-ui/react-form@0.1.8(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5)': dependencies: - "@radix-ui/primitive": 1.1.3 - "@radix-ui/react-compose-refs": 1.1.2(@types/react@19.2.14)(react@19.2.5) - "@radix-ui/react-context": 1.1.2(@types/react@19.2.14)(react@19.2.5) - "@radix-ui/react-id": 1.1.1(@types/react@19.2.14)(react@19.2.5) - "@radix-ui/react-label": 2.1.7(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5) - "@radix-ui/react-primitive": 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5) + '@radix-ui/primitive': 1.1.3 + '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.14)(react@19.2.5) + '@radix-ui/react-context': 1.1.2(@types/react@19.2.14)(react@19.2.5) + '@radix-ui/react-id': 1.1.1(@types/react@19.2.14)(react@19.2.5) + '@radix-ui/react-label': 2.1.7(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5) + '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5) react: 19.2.5 react-dom: 19.2.5(react@19.2.5) optionalDependencies: - "@types/react": 19.2.14 - "@types/react-dom": 19.2.3(@types/react@19.2.14) + '@types/react': 19.2.14 + '@types/react-dom': 19.2.3(@types/react@19.2.14) - "@radix-ui/react-id@1.1.1(@types/react@19.2.14)(react@19.2.5)": + '@radix-ui/react-id@1.1.1(@types/react@19.2.14)(react@19.2.5)': dependencies: - "@radix-ui/react-use-layout-effect": 1.1.1(@types/react@19.2.14)(react@19.2.5) + '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@19.2.14)(react@19.2.5) react: 19.2.5 optionalDependencies: - "@types/react": 19.2.14 + '@types/react': 19.2.14 - "@radix-ui/react-label@2.1.7(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5)": + '@radix-ui/react-label@2.1.7(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5)': dependencies: - "@radix-ui/react-primitive": 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5) + '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5) react: 19.2.5 react-dom: 19.2.5(react@19.2.5) optionalDependencies: - "@types/react": 19.2.14 - "@types/react-dom": 19.2.3(@types/react@19.2.14) + '@types/react': 19.2.14 + '@types/react-dom': 19.2.3(@types/react@19.2.14) - "@radix-ui/react-menu@2.1.16(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5)": + '@radix-ui/react-menu@2.1.16(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5)': dependencies: - "@radix-ui/primitive": 1.1.3 - "@radix-ui/react-collection": 1.1.7(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5) - "@radix-ui/react-compose-refs": 1.1.2(@types/react@19.2.14)(react@19.2.5) - "@radix-ui/react-context": 1.1.2(@types/react@19.2.14)(react@19.2.5) - "@radix-ui/react-direction": 1.1.1(@types/react@19.2.14)(react@19.2.5) - "@radix-ui/react-dismissable-layer": 1.1.11(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5) - "@radix-ui/react-focus-guards": 1.1.3(@types/react@19.2.14)(react@19.2.5) - "@radix-ui/react-focus-scope": 1.1.7(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5) - "@radix-ui/react-id": 1.1.1(@types/react@19.2.14)(react@19.2.5) - "@radix-ui/react-popper": 1.2.8(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5) - "@radix-ui/react-portal": 1.1.9(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5) - "@radix-ui/react-presence": 1.1.5(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5) - "@radix-ui/react-primitive": 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5) - "@radix-ui/react-roving-focus": 1.1.11(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5) - "@radix-ui/react-slot": 1.2.3(@types/react@19.2.14)(react@19.2.5) - "@radix-ui/react-use-callback-ref": 1.1.1(@types/react@19.2.14)(react@19.2.5) + '@radix-ui/primitive': 1.1.3 + '@radix-ui/react-collection': 1.1.7(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5) + '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.14)(react@19.2.5) + '@radix-ui/react-context': 1.1.2(@types/react@19.2.14)(react@19.2.5) + '@radix-ui/react-direction': 1.1.1(@types/react@19.2.14)(react@19.2.5) + '@radix-ui/react-dismissable-layer': 1.1.11(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5) + '@radix-ui/react-focus-guards': 1.1.3(@types/react@19.2.14)(react@19.2.5) + '@radix-ui/react-focus-scope': 1.1.7(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5) + '@radix-ui/react-id': 1.1.1(@types/react@19.2.14)(react@19.2.5) + '@radix-ui/react-popper': 1.2.8(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5) + '@radix-ui/react-portal': 1.1.9(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5) + '@radix-ui/react-presence': 1.1.5(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5) + '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5) + '@radix-ui/react-roving-focus': 1.1.11(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5) + '@radix-ui/react-slot': 1.2.3(@types/react@19.2.14)(react@19.2.5) + '@radix-ui/react-use-callback-ref': 1.1.1(@types/react@19.2.14)(react@19.2.5) aria-hidden: 1.2.6 react: 19.2.5 react-dom: 19.2.5(react@19.2.5) react-remove-scroll: 2.7.2(@types/react@19.2.14)(react@19.2.5) optionalDependencies: - "@types/react": 19.2.14 - "@types/react-dom": 19.2.3(@types/react@19.2.14) + '@types/react': 19.2.14 + '@types/react-dom': 19.2.3(@types/react@19.2.14) - "@radix-ui/react-popper@1.2.8(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5)": + '@radix-ui/react-popper@1.2.8(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5)': dependencies: - "@floating-ui/react-dom": 2.1.8(react-dom@19.2.5(react@19.2.5))(react@19.2.5) - "@radix-ui/react-arrow": 1.1.7(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5) - "@radix-ui/react-compose-refs": 1.1.2(@types/react@19.2.14)(react@19.2.5) - "@radix-ui/react-context": 1.1.2(@types/react@19.2.14)(react@19.2.5) - "@radix-ui/react-primitive": 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5) - "@radix-ui/react-use-callback-ref": 1.1.1(@types/react@19.2.14)(react@19.2.5) - "@radix-ui/react-use-layout-effect": 1.1.1(@types/react@19.2.14)(react@19.2.5) - "@radix-ui/react-use-rect": 1.1.1(@types/react@19.2.14)(react@19.2.5) - "@radix-ui/react-use-size": 1.1.1(@types/react@19.2.14)(react@19.2.5) - "@radix-ui/rect": 1.1.1 + '@floating-ui/react-dom': 2.1.8(react-dom@19.2.5(react@19.2.5))(react@19.2.5) + '@radix-ui/react-arrow': 1.1.7(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5) + '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.14)(react@19.2.5) + '@radix-ui/react-context': 1.1.2(@types/react@19.2.14)(react@19.2.5) + '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5) + '@radix-ui/react-use-callback-ref': 1.1.1(@types/react@19.2.14)(react@19.2.5) + '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@19.2.14)(react@19.2.5) + '@radix-ui/react-use-rect': 1.1.1(@types/react@19.2.14)(react@19.2.5) + '@radix-ui/react-use-size': 1.1.1(@types/react@19.2.14)(react@19.2.5) + '@radix-ui/rect': 1.1.1 react: 19.2.5 react-dom: 19.2.5(react@19.2.5) optionalDependencies: - "@types/react": 19.2.14 - "@types/react-dom": 19.2.3(@types/react@19.2.14) + '@types/react': 19.2.14 + '@types/react-dom': 19.2.3(@types/react@19.2.14) - "@radix-ui/react-portal@1.1.9(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5)": + '@radix-ui/react-portal@1.1.9(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5)': dependencies: - "@radix-ui/react-primitive": 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5) - "@radix-ui/react-use-layout-effect": 1.1.1(@types/react@19.2.14)(react@19.2.5) + '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5) + '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@19.2.14)(react@19.2.5) react: 19.2.5 react-dom: 19.2.5(react@19.2.5) optionalDependencies: - "@types/react": 19.2.14 - "@types/react-dom": 19.2.3(@types/react@19.2.14) + '@types/react': 19.2.14 + '@types/react-dom': 19.2.3(@types/react@19.2.14) - "@radix-ui/react-presence@1.1.5(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5)": + '@radix-ui/react-presence@1.1.5(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5)': dependencies: - "@radix-ui/react-compose-refs": 1.1.2(@types/react@19.2.14)(react@19.2.5) - "@radix-ui/react-use-layout-effect": 1.1.1(@types/react@19.2.14)(react@19.2.5) + '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.14)(react@19.2.5) + '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@19.2.14)(react@19.2.5) react: 19.2.5 react-dom: 19.2.5(react@19.2.5) optionalDependencies: - "@types/react": 19.2.14 - "@types/react-dom": 19.2.3(@types/react@19.2.14) + '@types/react': 19.2.14 + '@types/react-dom': 19.2.3(@types/react@19.2.14) - "@radix-ui/react-primitive@2.1.3(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5)": + '@radix-ui/react-primitive@2.1.3(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5)': dependencies: - "@radix-ui/react-slot": 1.2.3(@types/react@19.2.14)(react@19.2.5) + '@radix-ui/react-slot': 1.2.3(@types/react@19.2.14)(react@19.2.5) react: 19.2.5 react-dom: 19.2.5(react@19.2.5) optionalDependencies: - "@types/react": 19.2.14 - "@types/react-dom": 19.2.3(@types/react@19.2.14) + '@types/react': 19.2.14 + '@types/react-dom': 19.2.3(@types/react@19.2.14) - "@radix-ui/react-primitive@2.1.4(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5)": + '@radix-ui/react-primitive@2.1.4(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5)': dependencies: - "@radix-ui/react-slot": 1.2.4(@types/react@19.2.14)(react@19.2.5) + '@radix-ui/react-slot': 1.2.4(@types/react@19.2.14)(react@19.2.5) react: 19.2.5 react-dom: 19.2.5(react@19.2.5) optionalDependencies: - "@types/react": 19.2.14 - "@types/react-dom": 19.2.3(@types/react@19.2.14) + '@types/react': 19.2.14 + '@types/react-dom': 19.2.3(@types/react@19.2.14) - "@radix-ui/react-progress@1.1.8(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5)": + '@radix-ui/react-progress@1.1.8(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5)': dependencies: - "@radix-ui/react-context": 1.1.3(@types/react@19.2.14)(react@19.2.5) - "@radix-ui/react-primitive": 2.1.4(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5) + '@radix-ui/react-context': 1.1.3(@types/react@19.2.14)(react@19.2.5) + '@radix-ui/react-primitive': 2.1.4(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5) react: 19.2.5 react-dom: 19.2.5(react@19.2.5) optionalDependencies: - "@types/react": 19.2.14 - "@types/react-dom": 19.2.3(@types/react@19.2.14) + '@types/react': 19.2.14 + '@types/react-dom': 19.2.3(@types/react@19.2.14) - "@radix-ui/react-roving-focus@1.1.11(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5)": + '@radix-ui/react-roving-focus@1.1.11(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5)': dependencies: - "@radix-ui/primitive": 1.1.3 - "@radix-ui/react-collection": 1.1.7(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5) - "@radix-ui/react-compose-refs": 1.1.2(@types/react@19.2.14)(react@19.2.5) - "@radix-ui/react-context": 1.1.2(@types/react@19.2.14)(react@19.2.5) - "@radix-ui/react-direction": 1.1.1(@types/react@19.2.14)(react@19.2.5) - "@radix-ui/react-id": 1.1.1(@types/react@19.2.14)(react@19.2.5) - "@radix-ui/react-primitive": 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5) - "@radix-ui/react-use-callback-ref": 1.1.1(@types/react@19.2.14)(react@19.2.5) - "@radix-ui/react-use-controllable-state": 1.2.2(@types/react@19.2.14)(react@19.2.5) + '@radix-ui/primitive': 1.1.3 + '@radix-ui/react-collection': 1.1.7(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5) + '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.14)(react@19.2.5) + '@radix-ui/react-context': 1.1.2(@types/react@19.2.14)(react@19.2.5) + '@radix-ui/react-direction': 1.1.1(@types/react@19.2.14)(react@19.2.5) + '@radix-ui/react-id': 1.1.1(@types/react@19.2.14)(react@19.2.5) + '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5) + '@radix-ui/react-use-callback-ref': 1.1.1(@types/react@19.2.14)(react@19.2.5) + '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@19.2.14)(react@19.2.5) react: 19.2.5 react-dom: 19.2.5(react@19.2.5) optionalDependencies: - "@types/react": 19.2.14 - "@types/react-dom": 19.2.3(@types/react@19.2.14) + '@types/react': 19.2.14 + '@types/react-dom': 19.2.3(@types/react@19.2.14) - "@radix-ui/react-separator@1.1.8(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5)": + '@radix-ui/react-separator@1.1.8(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5)': dependencies: - "@radix-ui/react-primitive": 2.1.4(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5) + '@radix-ui/react-primitive': 2.1.4(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5) react: 19.2.5 react-dom: 19.2.5(react@19.2.5) optionalDependencies: - "@types/react": 19.2.14 - "@types/react-dom": 19.2.3(@types/react@19.2.14) + '@types/react': 19.2.14 + '@types/react-dom': 19.2.3(@types/react@19.2.14) - "@radix-ui/react-slider@1.3.6(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5)": + '@radix-ui/react-slider@1.3.6(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5)': dependencies: - "@radix-ui/number": 1.1.1 - "@radix-ui/primitive": 1.1.3 - "@radix-ui/react-collection": 1.1.7(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5) - "@radix-ui/react-compose-refs": 1.1.2(@types/react@19.2.14)(react@19.2.5) - "@radix-ui/react-context": 1.1.2(@types/react@19.2.14)(react@19.2.5) - "@radix-ui/react-direction": 1.1.1(@types/react@19.2.14)(react@19.2.5) - "@radix-ui/react-primitive": 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5) - "@radix-ui/react-use-controllable-state": 1.2.2(@types/react@19.2.14)(react@19.2.5) - "@radix-ui/react-use-layout-effect": 1.1.1(@types/react@19.2.14)(react@19.2.5) - "@radix-ui/react-use-previous": 1.1.1(@types/react@19.2.14)(react@19.2.5) - "@radix-ui/react-use-size": 1.1.1(@types/react@19.2.14)(react@19.2.5) + '@radix-ui/number': 1.1.1 + '@radix-ui/primitive': 1.1.3 + '@radix-ui/react-collection': 1.1.7(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5) + '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.14)(react@19.2.5) + '@radix-ui/react-context': 1.1.2(@types/react@19.2.14)(react@19.2.5) + '@radix-ui/react-direction': 1.1.1(@types/react@19.2.14)(react@19.2.5) + '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5) + '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@19.2.14)(react@19.2.5) + '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@19.2.14)(react@19.2.5) + '@radix-ui/react-use-previous': 1.1.1(@types/react@19.2.14)(react@19.2.5) + '@radix-ui/react-use-size': 1.1.1(@types/react@19.2.14)(react@19.2.5) react: 19.2.5 react-dom: 19.2.5(react@19.2.5) optionalDependencies: - "@types/react": 19.2.14 - "@types/react-dom": 19.2.3(@types/react@19.2.14) + '@types/react': 19.2.14 + '@types/react-dom': 19.2.3(@types/react@19.2.14) - "@radix-ui/react-slot@1.2.3(@types/react@19.2.14)(react@19.2.5)": + '@radix-ui/react-slot@1.2.3(@types/react@19.2.14)(react@19.2.5)': dependencies: - "@radix-ui/react-compose-refs": 1.1.2(@types/react@19.2.14)(react@19.2.5) + '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.14)(react@19.2.5) react: 19.2.5 optionalDependencies: - "@types/react": 19.2.14 + '@types/react': 19.2.14 - "@radix-ui/react-slot@1.2.4(@types/react@19.2.14)(react@19.2.5)": + '@radix-ui/react-slot@1.2.4(@types/react@19.2.14)(react@19.2.5)': dependencies: - "@radix-ui/react-compose-refs": 1.1.2(@types/react@19.2.14)(react@19.2.5) + '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.14)(react@19.2.5) react: 19.2.5 optionalDependencies: - "@types/react": 19.2.14 + '@types/react': 19.2.14 - "@radix-ui/react-use-callback-ref@1.1.1(@types/react@19.2.14)(react@19.2.5)": + '@radix-ui/react-use-callback-ref@1.1.1(@types/react@19.2.14)(react@19.2.5)': dependencies: react: 19.2.5 optionalDependencies: - "@types/react": 19.2.14 + '@types/react': 19.2.14 - "@radix-ui/react-use-controllable-state@1.2.2(@types/react@19.2.14)(react@19.2.5)": + '@radix-ui/react-use-controllable-state@1.2.2(@types/react@19.2.14)(react@19.2.5)': dependencies: - "@radix-ui/react-use-effect-event": 0.0.2(@types/react@19.2.14)(react@19.2.5) - "@radix-ui/react-use-layout-effect": 1.1.1(@types/react@19.2.14)(react@19.2.5) + '@radix-ui/react-use-effect-event': 0.0.2(@types/react@19.2.14)(react@19.2.5) + '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@19.2.14)(react@19.2.5) react: 19.2.5 optionalDependencies: - "@types/react": 19.2.14 + '@types/react': 19.2.14 - "@radix-ui/react-use-effect-event@0.0.2(@types/react@19.2.14)(react@19.2.5)": + '@radix-ui/react-use-effect-event@0.0.2(@types/react@19.2.14)(react@19.2.5)': dependencies: - "@radix-ui/react-use-layout-effect": 1.1.1(@types/react@19.2.14)(react@19.2.5) + '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@19.2.14)(react@19.2.5) react: 19.2.5 optionalDependencies: - "@types/react": 19.2.14 + '@types/react': 19.2.14 - "@radix-ui/react-use-escape-keydown@1.1.1(@types/react@19.2.14)(react@19.2.5)": + '@radix-ui/react-use-escape-keydown@1.1.1(@types/react@19.2.14)(react@19.2.5)': dependencies: - "@radix-ui/react-use-callback-ref": 1.1.1(@types/react@19.2.14)(react@19.2.5) + '@radix-ui/react-use-callback-ref': 1.1.1(@types/react@19.2.14)(react@19.2.5) react: 19.2.5 optionalDependencies: - "@types/react": 19.2.14 + '@types/react': 19.2.14 - "@radix-ui/react-use-layout-effect@1.1.1(@types/react@19.2.14)(react@19.2.5)": + '@radix-ui/react-use-layout-effect@1.1.1(@types/react@19.2.14)(react@19.2.5)': dependencies: react: 19.2.5 optionalDependencies: - "@types/react": 19.2.14 + '@types/react': 19.2.14 - "@radix-ui/react-use-previous@1.1.1(@types/react@19.2.14)(react@19.2.5)": + '@radix-ui/react-use-previous@1.1.1(@types/react@19.2.14)(react@19.2.5)': dependencies: react: 19.2.5 optionalDependencies: - "@types/react": 19.2.14 + '@types/react': 19.2.14 - "@radix-ui/react-use-rect@1.1.1(@types/react@19.2.14)(react@19.2.5)": + '@radix-ui/react-use-rect@1.1.1(@types/react@19.2.14)(react@19.2.5)': dependencies: - "@radix-ui/rect": 1.1.1 + '@radix-ui/rect': 1.1.1 react: 19.2.5 optionalDependencies: - "@types/react": 19.2.14 + '@types/react': 19.2.14 - "@radix-ui/react-use-size@1.1.1(@types/react@19.2.14)(react@19.2.5)": + '@radix-ui/react-use-size@1.1.1(@types/react@19.2.14)(react@19.2.5)': dependencies: - "@radix-ui/react-use-layout-effect": 1.1.1(@types/react@19.2.14)(react@19.2.5) + '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@19.2.14)(react@19.2.5) react: 19.2.5 optionalDependencies: - "@types/react": 19.2.14 + '@types/react': 19.2.14 - "@radix-ui/react-visually-hidden@1.2.4(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5)": + '@radix-ui/react-visually-hidden@1.2.4(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5)': dependencies: - "@radix-ui/react-primitive": 2.1.4(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5) + '@radix-ui/react-primitive': 2.1.4(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5) react: 19.2.5 react-dom: 19.2.5(react@19.2.5) optionalDependencies: - "@types/react": 19.2.14 - "@types/react-dom": 19.2.3(@types/react@19.2.14) + '@types/react': 19.2.14 + '@types/react-dom': 19.2.3(@types/react@19.2.14) - "@radix-ui/rect@1.1.1": {} + '@radix-ui/rect@1.1.1': {} - "@react-spring/animated@10.0.3(react@19.2.5)": + '@react-spring/animated@10.0.3(react@19.2.5)': dependencies: - "@react-spring/shared": 10.0.3(react@19.2.5) - "@react-spring/types": 10.0.3 + '@react-spring/shared': 10.0.3(react@19.2.5) + '@react-spring/types': 10.0.3 react: 19.2.5 - "@react-spring/core@10.0.3(react@19.2.5)": + '@react-spring/core@10.0.3(react@19.2.5)': dependencies: - "@react-spring/animated": 10.0.3(react@19.2.5) - "@react-spring/shared": 10.0.3(react@19.2.5) - "@react-spring/types": 10.0.3 + '@react-spring/animated': 10.0.3(react@19.2.5) + '@react-spring/shared': 10.0.3(react@19.2.5) + '@react-spring/types': 10.0.3 react: 19.2.5 - "@react-spring/rafz@10.0.3": {} + '@react-spring/rafz@10.0.3': {} - "@react-spring/shared@10.0.3(react@19.2.5)": + '@react-spring/shared@10.0.3(react@19.2.5)': dependencies: - "@react-spring/rafz": 10.0.3 - "@react-spring/types": 10.0.3 + '@react-spring/rafz': 10.0.3 + '@react-spring/types': 10.0.3 react: 19.2.5 - "@react-spring/types@10.0.3": {} + '@react-spring/types@10.0.3': {} - "@react-spring/web@10.0.3(react-dom@19.2.5(react@19.2.5))(react@19.2.5)": + '@react-spring/web@10.0.3(react-dom@19.2.5(react@19.2.5))(react@19.2.5)': dependencies: - "@react-spring/animated": 10.0.3(react@19.2.5) - "@react-spring/core": 10.0.3(react@19.2.5) - "@react-spring/shared": 10.0.3(react@19.2.5) - "@react-spring/types": 10.0.3 + '@react-spring/animated': 10.0.3(react@19.2.5) + '@react-spring/core': 10.0.3(react@19.2.5) + '@react-spring/shared': 10.0.3(react@19.2.5) + '@react-spring/types': 10.0.3 react: 19.2.5 react-dom: 19.2.5(react@19.2.5) - "@rolldown/binding-android-arm64@1.0.0-rc.15": + '@rolldown/binding-android-arm64@1.0.0-rc.15': optional: true - "@rolldown/binding-darwin-arm64@1.0.0-rc.15": + '@rolldown/binding-darwin-arm64@1.0.0-rc.15': optional: true - "@rolldown/binding-darwin-x64@1.0.0-rc.15": + '@rolldown/binding-darwin-x64@1.0.0-rc.15': optional: true - "@rolldown/binding-freebsd-x64@1.0.0-rc.15": + '@rolldown/binding-freebsd-x64@1.0.0-rc.15': optional: true - "@rolldown/binding-linux-arm-gnueabihf@1.0.0-rc.15": + '@rolldown/binding-linux-arm-gnueabihf@1.0.0-rc.15': optional: true - "@rolldown/binding-linux-arm64-gnu@1.0.0-rc.15": + '@rolldown/binding-linux-arm64-gnu@1.0.0-rc.15': optional: true - "@rolldown/binding-linux-arm64-musl@1.0.0-rc.15": + '@rolldown/binding-linux-arm64-musl@1.0.0-rc.15': optional: true - "@rolldown/binding-linux-ppc64-gnu@1.0.0-rc.15": + '@rolldown/binding-linux-ppc64-gnu@1.0.0-rc.15': optional: true - "@rolldown/binding-linux-s390x-gnu@1.0.0-rc.15": + '@rolldown/binding-linux-s390x-gnu@1.0.0-rc.15': optional: true - "@rolldown/binding-linux-x64-gnu@1.0.0-rc.15": + '@rolldown/binding-linux-x64-gnu@1.0.0-rc.15': optional: true - "@rolldown/binding-linux-x64-musl@1.0.0-rc.15": + '@rolldown/binding-linux-x64-musl@1.0.0-rc.15': optional: true - "@rolldown/binding-openharmony-arm64@1.0.0-rc.15": + '@rolldown/binding-openharmony-arm64@1.0.0-rc.15': optional: true - "@rolldown/binding-wasm32-wasi@1.0.0-rc.15": + '@rolldown/binding-wasm32-wasi@1.0.0-rc.15': dependencies: - "@emnapi/core": 1.9.2 - "@emnapi/runtime": 1.9.2 - "@napi-rs/wasm-runtime": 1.1.4(@emnapi/core@1.9.2)(@emnapi/runtime@1.9.2) + '@emnapi/core': 1.9.2 + '@emnapi/runtime': 1.9.2 + '@napi-rs/wasm-runtime': 1.1.4(@emnapi/core@1.9.2)(@emnapi/runtime@1.9.2) optional: true - "@rolldown/binding-win32-arm64-msvc@1.0.0-rc.15": + '@rolldown/binding-win32-arm64-msvc@1.0.0-rc.15': optional: true - "@rolldown/binding-win32-x64-msvc@1.0.0-rc.15": + '@rolldown/binding-win32-x64-msvc@1.0.0-rc.15': optional: true - "@rolldown/pluginutils@1.0.0-beta.27": {} + '@rolldown/pluginutils@1.0.0-beta.27': {} - "@rolldown/pluginutils@1.0.0-rc.15": {} + '@rolldown/pluginutils@1.0.0-rc.15': {} - "@rollup/plugin-inject@5.0.5": + '@rollup/plugin-inject@5.0.5(rollup@4.60.1)': dependencies: - "@rollup/pluginutils": 5.3.0 + '@rollup/pluginutils': 5.3.0(rollup@4.60.1) estree-walker: 2.0.2 magic-string: 0.30.21 + optionalDependencies: + rollup: 4.60.1 - "@rollup/pluginutils@4.2.1": + '@rollup/pluginutils@4.2.1': dependencies: estree-walker: 2.0.2 picomatch: 2.3.2 - "@rollup/pluginutils@5.3.0": + '@rollup/pluginutils@5.3.0(rollup@4.60.1)': dependencies: - "@types/estree": 1.0.8 + '@types/estree': 1.0.8 estree-walker: 2.0.2 picomatch: 4.0.4 + optionalDependencies: + rollup: 4.60.1 - "@rtsao/scc@1.1.0": {} + '@rollup/rollup-android-arm-eabi@4.60.1': + optional: true - "@sentry-internal/browser-utils@8.55.1": + '@rollup/rollup-android-arm64@4.60.1': + optional: true + + '@rollup/rollup-darwin-arm64@4.60.1': + optional: true + + '@rollup/rollup-darwin-x64@4.60.1': + optional: true + + '@rollup/rollup-freebsd-arm64@4.60.1': + optional: true + + '@rollup/rollup-freebsd-x64@4.60.1': + optional: true + + '@rollup/rollup-linux-arm-gnueabihf@4.60.1': + optional: true + + '@rollup/rollup-linux-arm-musleabihf@4.60.1': + optional: true + + '@rollup/rollup-linux-arm64-gnu@4.60.1': + optional: true + + '@rollup/rollup-linux-arm64-musl@4.60.1': + optional: true + + '@rollup/rollup-linux-loong64-gnu@4.60.1': + optional: true + + '@rollup/rollup-linux-loong64-musl@4.60.1': + optional: true + + '@rollup/rollup-linux-ppc64-gnu@4.60.1': + optional: true + + '@rollup/rollup-linux-ppc64-musl@4.60.1': + optional: true + + '@rollup/rollup-linux-riscv64-gnu@4.60.1': + optional: true + + '@rollup/rollup-linux-riscv64-musl@4.60.1': + optional: true + + '@rollup/rollup-linux-s390x-gnu@4.60.1': + optional: true + + '@rollup/rollup-linux-x64-gnu@4.60.1': + optional: true + + '@rollup/rollup-linux-x64-musl@4.60.1': + optional: true + + '@rollup/rollup-openbsd-x64@4.60.1': + optional: true + + '@rollup/rollup-openharmony-arm64@4.60.1': + optional: true + + '@rollup/rollup-win32-arm64-msvc@4.60.1': + optional: true + + '@rollup/rollup-win32-ia32-msvc@4.60.1': + optional: true + + '@rollup/rollup-win32-x64-gnu@4.60.1': + optional: true + + '@rollup/rollup-win32-x64-msvc@4.60.1': + optional: true + + '@rtsao/scc@1.1.0': {} + + '@sentry-internal/browser-utils@8.55.1': dependencies: - "@sentry/core": 8.55.1 + '@sentry/core': 8.55.1 - "@sentry-internal/feedback@8.55.1": + '@sentry-internal/feedback@8.55.1': dependencies: - "@sentry/core": 8.55.1 + '@sentry/core': 8.55.1 - "@sentry-internal/replay-canvas@8.55.1": + '@sentry-internal/replay-canvas@8.55.1': dependencies: - "@sentry-internal/replay": 8.55.1 - "@sentry/core": 8.55.1 + '@sentry-internal/replay': 8.55.1 + '@sentry/core': 8.55.1 - "@sentry-internal/replay@8.55.1": + '@sentry-internal/replay@8.55.1': dependencies: - "@sentry-internal/browser-utils": 8.55.1 - "@sentry/core": 8.55.1 + '@sentry-internal/browser-utils': 8.55.1 + '@sentry/core': 8.55.1 - "@sentry/babel-plugin-component-annotate@3.6.1": {} + '@sentry/babel-plugin-component-annotate@3.6.1': {} - "@sentry/browser@8.55.1": + '@sentry/browser@8.55.1': dependencies: - "@sentry-internal/browser-utils": 8.55.1 - "@sentry-internal/feedback": 8.55.1 - "@sentry-internal/replay": 8.55.1 - "@sentry-internal/replay-canvas": 8.55.1 - "@sentry/core": 8.55.1 + '@sentry-internal/browser-utils': 8.55.1 + '@sentry-internal/feedback': 8.55.1 + '@sentry-internal/replay': 8.55.1 + '@sentry-internal/replay-canvas': 8.55.1 + '@sentry/core': 8.55.1 - "@sentry/bundler-plugin-core@3.6.1": + '@sentry/bundler-plugin-core@3.6.1': dependencies: - "@babel/core": 7.29.0 - "@sentry/babel-plugin-component-annotate": 3.6.1 - "@sentry/cli": 2.58.5 + '@babel/core': 7.29.0 + '@sentry/babel-plugin-component-annotate': 3.6.1 + '@sentry/cli': 2.58.5 dotenv: 16.6.1 find-up: 5.0.0 glob: 10.5.0 @@ -12708,31 +8937,31 @@ snapshots: - encoding - supports-color - "@sentry/cli-darwin@2.58.5": + '@sentry/cli-darwin@2.58.5': optional: true - "@sentry/cli-linux-arm64@2.58.5": + '@sentry/cli-linux-arm64@2.58.5': optional: true - "@sentry/cli-linux-arm@2.58.5": + '@sentry/cli-linux-arm@2.58.5': optional: true - "@sentry/cli-linux-i686@2.58.5": + '@sentry/cli-linux-i686@2.58.5': optional: true - "@sentry/cli-linux-x64@2.58.5": + '@sentry/cli-linux-x64@2.58.5': optional: true - "@sentry/cli-win32-arm64@2.58.5": + '@sentry/cli-win32-arm64@2.58.5': optional: true - "@sentry/cli-win32-i686@2.58.5": + '@sentry/cli-win32-i686@2.58.5': optional: true - "@sentry/cli-win32-x64@2.58.5": + '@sentry/cli-win32-x64@2.58.5': optional: true - "@sentry/cli@2.58.5": + '@sentry/cli@2.58.5': dependencies: https-proxy-agent: 5.0.1 node-fetch: 2.7.0 @@ -12740,59 +8969,59 @@ snapshots: proxy-from-env: 1.1.0 which: 2.0.2 optionalDependencies: - "@sentry/cli-darwin": 2.58.5 - "@sentry/cli-linux-arm": 2.58.5 - "@sentry/cli-linux-arm64": 2.58.5 - "@sentry/cli-linux-i686": 2.58.5 - "@sentry/cli-linux-x64": 2.58.5 - "@sentry/cli-win32-arm64": 2.58.5 - "@sentry/cli-win32-i686": 2.58.5 - "@sentry/cli-win32-x64": 2.58.5 + '@sentry/cli-darwin': 2.58.5 + '@sentry/cli-linux-arm': 2.58.5 + '@sentry/cli-linux-arm64': 2.58.5 + '@sentry/cli-linux-i686': 2.58.5 + '@sentry/cli-linux-x64': 2.58.5 + '@sentry/cli-win32-arm64': 2.58.5 + '@sentry/cli-win32-i686': 2.58.5 + '@sentry/cli-win32-x64': 2.58.5 transitivePeerDependencies: - encoding - supports-color - "@sentry/core@8.55.1": {} + '@sentry/core@8.55.1': {} - "@sentry/react@8.55.1(react@19.2.5)": + '@sentry/react@8.55.1(react@19.2.5)': dependencies: - "@sentry/browser": 8.55.1 - "@sentry/core": 8.55.1 + '@sentry/browser': 8.55.1 + '@sentry/core': 8.55.1 hoist-non-react-statics: 3.3.2 react: 19.2.5 - "@sentry/vite-plugin@3.6.1": + '@sentry/vite-plugin@3.6.1': dependencies: - "@sentry/bundler-plugin-core": 3.6.1 + '@sentry/bundler-plugin-core': 3.6.1 unplugin: 1.0.1 transitivePeerDependencies: - encoding - supports-color - "@sindresorhus/base62@1.0.0": {} + '@sindresorhus/base62@1.0.0': {} - "@standard-schema/spec@1.1.0": {} + '@standard-schema/spec@1.1.0': {} - "@storybook/addon-docs@10.3.5(@types/react@19.2.14)(esbuild@0.27.7)(storybook@10.3.5(@testing-library/dom@10.4.1)(prettier@3.8.3)(react-dom@19.2.5(react@19.2.5))(react@19.2.5))(vite@8.0.8(@types/node@24.12.2)(esbuild@0.27.7)(jiti@2.6.1)(sass@1.99.0)(terser@5.46.1)(yaml@2.8.3))": + '@storybook/addon-docs@10.3.5(@types/react@19.2.14)(esbuild@0.27.7)(rollup@4.60.1)(storybook@10.3.5(@testing-library/dom@10.4.1)(prettier@3.8.3)(react-dom@19.2.5(react@19.2.5))(react@19.2.5))(vite@8.0.8(@types/node@24.12.2)(esbuild@0.27.7)(jiti@2.6.1)(sass@1.99.0)(terser@5.46.1)(yaml@2.8.3))': dependencies: - "@mdx-js/react": 3.1.1(@types/react@19.2.14)(react@19.2.5) - "@storybook/csf-plugin": 10.3.5(esbuild@0.27.7)(storybook@10.3.5(@testing-library/dom@10.4.1)(prettier@3.8.3)(react-dom@19.2.5(react@19.2.5))(react@19.2.5))(vite@8.0.8(@types/node@24.12.2)(esbuild@0.27.7)(jiti@2.6.1)(sass@1.99.0)(terser@5.46.1)(yaml@2.8.3)) - "@storybook/icons": 2.0.1(react-dom@19.2.5(react@19.2.5))(react@19.2.5) - "@storybook/react-dom-shim": 10.3.5(react-dom@19.2.5(react@19.2.5))(react@19.2.5)(storybook@10.3.5(@testing-library/dom@10.4.1)(prettier@3.8.3)(react-dom@19.2.5(react@19.2.5))(react@19.2.5)) + '@mdx-js/react': 3.1.1(@types/react@19.2.14)(react@19.2.5) + '@storybook/csf-plugin': 10.3.5(esbuild@0.27.7)(rollup@4.60.1)(storybook@10.3.5(@testing-library/dom@10.4.1)(prettier@3.8.3)(react-dom@19.2.5(react@19.2.5))(react@19.2.5))(vite@8.0.8(@types/node@24.12.2)(esbuild@0.27.7)(jiti@2.6.1)(sass@1.99.0)(terser@5.46.1)(yaml@2.8.3)) + '@storybook/icons': 2.0.1(react-dom@19.2.5(react@19.2.5))(react@19.2.5) + '@storybook/react-dom-shim': 10.3.5(react-dom@19.2.5(react@19.2.5))(react@19.2.5)(storybook@10.3.5(@testing-library/dom@10.4.1)(prettier@3.8.3)(react-dom@19.2.5(react@19.2.5))(react@19.2.5)) react: 19.2.5 react-dom: 19.2.5(react@19.2.5) storybook: 10.3.5(@testing-library/dom@10.4.1)(prettier@3.8.3)(react-dom@19.2.5(react@19.2.5))(react@19.2.5) ts-dedent: 2.2.0 transitivePeerDependencies: - - "@types/react" + - '@types/react' - esbuild - rollup - vite - webpack - "@storybook/builder-vite@10.3.5(esbuild@0.27.7)(storybook@10.3.5(@testing-library/dom@10.4.1)(prettier@3.8.3)(react-dom@19.2.5(react@19.2.5))(react@19.2.5))(vite@8.0.8(@types/node@24.12.2)(esbuild@0.27.7)(jiti@2.6.1)(sass@1.99.0)(terser@5.46.1)(yaml@2.8.3))": + '@storybook/builder-vite@10.3.5(esbuild@0.27.7)(rollup@4.60.1)(storybook@10.3.5(@testing-library/dom@10.4.1)(prettier@3.8.3)(react-dom@19.2.5(react@19.2.5))(react@19.2.5))(vite@8.0.8(@types/node@24.12.2)(esbuild@0.27.7)(jiti@2.6.1)(sass@1.99.0)(terser@5.46.1)(yaml@2.8.3))': dependencies: - "@storybook/csf-plugin": 10.3.5(esbuild@0.27.7)(storybook@10.3.5(@testing-library/dom@10.4.1)(prettier@3.8.3)(react-dom@19.2.5(react@19.2.5))(react@19.2.5))(vite@8.0.8(@types/node@24.12.2)(esbuild@0.27.7)(jiti@2.6.1)(sass@1.99.0)(terser@5.46.1)(yaml@2.8.3)) + '@storybook/csf-plugin': 10.3.5(esbuild@0.27.7)(rollup@4.60.1)(storybook@10.3.5(@testing-library/dom@10.4.1)(prettier@3.8.3)(react-dom@19.2.5(react@19.2.5))(react@19.2.5))(vite@8.0.8(@types/node@24.12.2)(esbuild@0.27.7)(jiti@2.6.1)(sass@1.99.0)(terser@5.46.1)(yaml@2.8.3)) storybook: 10.3.5(@testing-library/dom@10.4.1)(prettier@3.8.3)(react-dom@19.2.5(react@19.2.5))(react@19.2.5) ts-dedent: 2.2.0 vite: 8.0.8(@types/node@24.12.2)(esbuild@0.27.7)(jiti@2.6.1)(sass@1.99.0)(terser@5.46.1)(yaml@2.8.3) @@ -12801,33 +9030,34 @@ snapshots: - rollup - webpack - "@storybook/csf-plugin@10.3.5(esbuild@0.27.7)(storybook@10.3.5(@testing-library/dom@10.4.1)(prettier@3.8.3)(react-dom@19.2.5(react@19.2.5))(react@19.2.5))(vite@8.0.8(@types/node@24.12.2)(esbuild@0.27.7)(jiti@2.6.1)(sass@1.99.0)(terser@5.46.1)(yaml@2.8.3))": + '@storybook/csf-plugin@10.3.5(esbuild@0.27.7)(rollup@4.60.1)(storybook@10.3.5(@testing-library/dom@10.4.1)(prettier@3.8.3)(react-dom@19.2.5(react@19.2.5))(react@19.2.5))(vite@8.0.8(@types/node@24.12.2)(esbuild@0.27.7)(jiti@2.6.1)(sass@1.99.0)(terser@5.46.1)(yaml@2.8.3))': dependencies: storybook: 10.3.5(@testing-library/dom@10.4.1)(prettier@3.8.3)(react-dom@19.2.5(react@19.2.5))(react@19.2.5) unplugin: 2.3.11 optionalDependencies: esbuild: 0.27.7 + rollup: 4.60.1 vite: 8.0.8(@types/node@24.12.2)(esbuild@0.27.7)(jiti@2.6.1)(sass@1.99.0)(terser@5.46.1)(yaml@2.8.3) - "@storybook/global@5.0.0": {} + '@storybook/global@5.0.0': {} - "@storybook/icons@2.0.1(react-dom@19.2.5(react@19.2.5))(react@19.2.5)": + '@storybook/icons@2.0.1(react-dom@19.2.5(react@19.2.5))(react@19.2.5)': dependencies: react: 19.2.5 react-dom: 19.2.5(react@19.2.5) - "@storybook/react-dom-shim@10.3.5(react-dom@19.2.5(react@19.2.5))(react@19.2.5)(storybook@10.3.5(@testing-library/dom@10.4.1)(prettier@3.8.3)(react-dom@19.2.5(react@19.2.5))(react@19.2.5))": + '@storybook/react-dom-shim@10.3.5(react-dom@19.2.5(react@19.2.5))(react@19.2.5)(storybook@10.3.5(@testing-library/dom@10.4.1)(prettier@3.8.3)(react-dom@19.2.5(react@19.2.5))(react@19.2.5))': dependencies: react: 19.2.5 react-dom: 19.2.5(react@19.2.5) storybook: 10.3.5(@testing-library/dom@10.4.1)(prettier@3.8.3)(react-dom@19.2.5(react@19.2.5))(react@19.2.5) - "@storybook/react-vite@10.3.5(esbuild@0.27.7)(react-dom@19.2.5(react@19.2.5))(react@19.2.5)(storybook@10.3.5(@testing-library/dom@10.4.1)(prettier@3.8.3)(react-dom@19.2.5(react@19.2.5))(react@19.2.5))(typescript@5.9.3)(vite@8.0.8(@types/node@24.12.2)(esbuild@0.27.7)(jiti@2.6.1)(sass@1.99.0)(terser@5.46.1)(yaml@2.8.3))": + '@storybook/react-vite@10.3.5(esbuild@0.27.7)(react-dom@19.2.5(react@19.2.5))(react@19.2.5)(rollup@4.60.1)(storybook@10.3.5(@testing-library/dom@10.4.1)(prettier@3.8.3)(react-dom@19.2.5(react@19.2.5))(react@19.2.5))(typescript@5.9.3)(vite@8.0.8(@types/node@24.12.2)(esbuild@0.27.7)(jiti@2.6.1)(sass@1.99.0)(terser@5.46.1)(yaml@2.8.3))': dependencies: - "@joshwooding/vite-plugin-react-docgen-typescript": 0.7.0(typescript@5.9.3)(vite@8.0.8(@types/node@24.12.2)(esbuild@0.27.7)(jiti@2.6.1)(sass@1.99.0)(terser@5.46.1)(yaml@2.8.3)) - "@rollup/pluginutils": 5.3.0 - "@storybook/builder-vite": 10.3.5(esbuild@0.27.7)(storybook@10.3.5(@testing-library/dom@10.4.1)(prettier@3.8.3)(react-dom@19.2.5(react@19.2.5))(react@19.2.5))(vite@8.0.8(@types/node@24.12.2)(esbuild@0.27.7)(jiti@2.6.1)(sass@1.99.0)(terser@5.46.1)(yaml@2.8.3)) - "@storybook/react": 10.3.5(react-dom@19.2.5(react@19.2.5))(react@19.2.5)(storybook@10.3.5(@testing-library/dom@10.4.1)(prettier@3.8.3)(react-dom@19.2.5(react@19.2.5))(react@19.2.5))(typescript@5.9.3) + '@joshwooding/vite-plugin-react-docgen-typescript': 0.7.0(typescript@5.9.3)(vite@8.0.8(@types/node@24.12.2)(esbuild@0.27.7)(jiti@2.6.1)(sass@1.99.0)(terser@5.46.1)(yaml@2.8.3)) + '@rollup/pluginutils': 5.3.0(rollup@4.60.1) + '@storybook/builder-vite': 10.3.5(esbuild@0.27.7)(rollup@4.60.1)(storybook@10.3.5(@testing-library/dom@10.4.1)(prettier@3.8.3)(react-dom@19.2.5(react@19.2.5))(react@19.2.5))(vite@8.0.8(@types/node@24.12.2)(esbuild@0.27.7)(jiti@2.6.1)(sass@1.99.0)(terser@5.46.1)(yaml@2.8.3)) + '@storybook/react': 10.3.5(react-dom@19.2.5(react@19.2.5))(react@19.2.5)(storybook@10.3.5(@testing-library/dom@10.4.1)(prettier@3.8.3)(react-dom@19.2.5(react@19.2.5))(react@19.2.5))(typescript@5.9.3) empathic: 2.0.0 magic-string: 0.30.21 react: 19.2.5 @@ -12844,10 +9074,10 @@ snapshots: - typescript - webpack - "@storybook/react@10.3.5(react-dom@19.2.5(react@19.2.5))(react@19.2.5)(storybook@10.3.5(@testing-library/dom@10.4.1)(prettier@3.8.3)(react-dom@19.2.5(react@19.2.5))(react@19.2.5))(typescript@5.9.3)": + '@storybook/react@10.3.5(react-dom@19.2.5(react@19.2.5))(react@19.2.5)(storybook@10.3.5(@testing-library/dom@10.4.1)(prettier@3.8.3)(react-dom@19.2.5(react@19.2.5))(react@19.2.5))(typescript@5.9.3)': dependencies: - "@storybook/global": 5.0.0 - "@storybook/react-dom-shim": 10.3.5(react-dom@19.2.5(react@19.2.5))(react@19.2.5)(storybook@10.3.5(@testing-library/dom@10.4.1)(prettier@3.8.3)(react-dom@19.2.5(react@19.2.5))(react@19.2.5)) + '@storybook/global': 5.0.0 + '@storybook/react-dom-shim': 10.3.5(react-dom@19.2.5(react@19.2.5))(react@19.2.5)(storybook@10.3.5(@testing-library/dom@10.4.1)(prettier@3.8.3)(react-dom@19.2.5(react@19.2.5))(react@19.2.5)) react: 19.2.5 react-docgen: 8.0.3 react-docgen-typescript: 2.4.0(typescript@5.9.3) @@ -12858,9 +9088,9 @@ snapshots: transitivePeerDependencies: - supports-color - "@stylistic/eslint-plugin@3.1.0(eslint@8.57.1)(typescript@5.9.3)": + '@stylistic/eslint-plugin@3.1.0(eslint@8.57.1)(typescript@5.9.3)': dependencies: - "@typescript-eslint/utils": 8.58.2(eslint@8.57.1)(typescript@5.9.3) + '@typescript-eslint/utils': 8.58.2(eslint@8.57.1)(typescript@5.9.3) eslint: 8.57.1 eslint-visitor-keys: 4.2.1 espree: 10.4.0 @@ -12870,54 +9100,54 @@ snapshots: - supports-color - typescript - "@svgr/babel-plugin-add-jsx-attribute@8.0.0(@babel/core@7.29.0)": + '@svgr/babel-plugin-add-jsx-attribute@8.0.0(@babel/core@7.29.0)': dependencies: - "@babel/core": 7.29.0 + '@babel/core': 7.29.0 - "@svgr/babel-plugin-remove-jsx-attribute@8.0.0(@babel/core@7.29.0)": + '@svgr/babel-plugin-remove-jsx-attribute@8.0.0(@babel/core@7.29.0)': dependencies: - "@babel/core": 7.29.0 + '@babel/core': 7.29.0 - "@svgr/babel-plugin-remove-jsx-empty-expression@8.0.0(@babel/core@7.29.0)": + '@svgr/babel-plugin-remove-jsx-empty-expression@8.0.0(@babel/core@7.29.0)': dependencies: - "@babel/core": 7.29.0 + '@babel/core': 7.29.0 - "@svgr/babel-plugin-replace-jsx-attribute-value@8.0.0(@babel/core@7.29.0)": + '@svgr/babel-plugin-replace-jsx-attribute-value@8.0.0(@babel/core@7.29.0)': dependencies: - "@babel/core": 7.29.0 + '@babel/core': 7.29.0 - "@svgr/babel-plugin-svg-dynamic-title@8.0.0(@babel/core@7.29.0)": + '@svgr/babel-plugin-svg-dynamic-title@8.0.0(@babel/core@7.29.0)': dependencies: - "@babel/core": 7.29.0 + '@babel/core': 7.29.0 - "@svgr/babel-plugin-svg-em-dimensions@8.0.0(@babel/core@7.29.0)": + '@svgr/babel-plugin-svg-em-dimensions@8.0.0(@babel/core@7.29.0)': dependencies: - "@babel/core": 7.29.0 + '@babel/core': 7.29.0 - "@svgr/babel-plugin-transform-react-native-svg@8.1.0(@babel/core@7.29.0)": + '@svgr/babel-plugin-transform-react-native-svg@8.1.0(@babel/core@7.29.0)': dependencies: - "@babel/core": 7.29.0 + '@babel/core': 7.29.0 - "@svgr/babel-plugin-transform-svg-component@8.0.0(@babel/core@7.29.0)": + '@svgr/babel-plugin-transform-svg-component@8.0.0(@babel/core@7.29.0)': dependencies: - "@babel/core": 7.29.0 + '@babel/core': 7.29.0 - "@svgr/babel-preset@8.1.0(@babel/core@7.29.0)": + '@svgr/babel-preset@8.1.0(@babel/core@7.29.0)': dependencies: - "@babel/core": 7.29.0 - "@svgr/babel-plugin-add-jsx-attribute": 8.0.0(@babel/core@7.29.0) - "@svgr/babel-plugin-remove-jsx-attribute": 8.0.0(@babel/core@7.29.0) - "@svgr/babel-plugin-remove-jsx-empty-expression": 8.0.0(@babel/core@7.29.0) - "@svgr/babel-plugin-replace-jsx-attribute-value": 8.0.0(@babel/core@7.29.0) - "@svgr/babel-plugin-svg-dynamic-title": 8.0.0(@babel/core@7.29.0) - "@svgr/babel-plugin-svg-em-dimensions": 8.0.0(@babel/core@7.29.0) - "@svgr/babel-plugin-transform-react-native-svg": 8.1.0(@babel/core@7.29.0) - "@svgr/babel-plugin-transform-svg-component": 8.0.0(@babel/core@7.29.0) + '@babel/core': 7.29.0 + '@svgr/babel-plugin-add-jsx-attribute': 8.0.0(@babel/core@7.29.0) + '@svgr/babel-plugin-remove-jsx-attribute': 8.0.0(@babel/core@7.29.0) + '@svgr/babel-plugin-remove-jsx-empty-expression': 8.0.0(@babel/core@7.29.0) + '@svgr/babel-plugin-replace-jsx-attribute-value': 8.0.0(@babel/core@7.29.0) + '@svgr/babel-plugin-svg-dynamic-title': 8.0.0(@babel/core@7.29.0) + '@svgr/babel-plugin-svg-em-dimensions': 8.0.0(@babel/core@7.29.0) + '@svgr/babel-plugin-transform-react-native-svg': 8.1.0(@babel/core@7.29.0) + '@svgr/babel-plugin-transform-svg-component': 8.0.0(@babel/core@7.29.0) - "@svgr/core@8.1.0(typescript@5.9.3)": + '@svgr/core@8.1.0(typescript@5.9.3)': dependencies: - "@babel/core": 7.29.0 - "@svgr/babel-preset": 8.1.0(@babel/core@7.29.0) + '@babel/core': 7.29.0 + '@svgr/babel-preset': 8.1.0(@babel/core@7.29.0) camelcase: 6.3.0 cosmiconfig: 8.3.6(typescript@5.9.3) snake-case: 3.0.4 @@ -12925,176 +9155,176 @@ snapshots: - supports-color - typescript - "@svgr/hast-util-to-babel-ast@8.0.0": + '@svgr/hast-util-to-babel-ast@8.0.0': dependencies: - "@babel/types": 7.29.0 + '@babel/types': 7.29.0 entities: 4.5.0 - "@svgr/plugin-jsx@8.1.0(@svgr/core@8.1.0(typescript@5.9.3))": + '@svgr/plugin-jsx@8.1.0(@svgr/core@8.1.0(typescript@5.9.3))': dependencies: - "@babel/core": 7.29.0 - "@svgr/babel-preset": 8.1.0(@babel/core@7.29.0) - "@svgr/core": 8.1.0(typescript@5.9.3) - "@svgr/hast-util-to-babel-ast": 8.0.0 + '@babel/core': 7.29.0 + '@svgr/babel-preset': 8.1.0(@babel/core@7.29.0) + '@svgr/core': 8.1.0(typescript@5.9.3) + '@svgr/hast-util-to-babel-ast': 8.0.0 svg-parser: 2.0.4 transitivePeerDependencies: - supports-color - "@testing-library/dom@10.4.1": + '@testing-library/dom@10.4.1': dependencies: - "@babel/code-frame": 7.29.0 - "@babel/runtime": 7.29.2 - "@types/aria-query": 5.0.4 + '@babel/code-frame': 7.29.0 + '@babel/runtime': 7.29.2 + '@types/aria-query': 5.0.4 aria-query: 5.3.0 dom-accessibility-api: 0.5.16 lz-string: 1.5.0 picocolors: 1.1.1 pretty-format: 27.5.1 - "@testing-library/jest-dom@6.9.1": + '@testing-library/jest-dom@6.9.1': dependencies: - "@adobe/css-tools": 4.4.4 + '@adobe/css-tools': 4.4.4 aria-query: 5.3.2 css.escape: 1.5.1 dom-accessibility-api: 0.6.3 picocolors: 1.1.1 redent: 3.0.0 - "@testing-library/react@16.3.2(@testing-library/dom@10.4.1)(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5)": + '@testing-library/react@16.3.2(@testing-library/dom@10.4.1)(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5)': dependencies: - "@babel/runtime": 7.29.2 - "@testing-library/dom": 10.4.1 + '@babel/runtime': 7.29.2 + '@testing-library/dom': 10.4.1 react: 19.2.5 react-dom: 19.2.5(react@19.2.5) optionalDependencies: - "@types/react": 19.2.14 - "@types/react-dom": 19.2.3(@types/react@19.2.14) + '@types/react': 19.2.14 + '@types/react-dom': 19.2.3(@types/react@19.2.14) - "@testing-library/user-event@14.6.1(@testing-library/dom@10.4.1)": + '@testing-library/user-event@14.6.1(@testing-library/dom@10.4.1)': dependencies: - "@testing-library/dom": 10.4.1 + '@testing-library/dom': 10.4.1 - "@tybys/wasm-util@0.10.1": + '@tybys/wasm-util@0.10.1': dependencies: tslib: 2.8.1 optional: true - "@types/aria-query@5.0.4": {} + '@types/aria-query@5.0.4': {} - "@types/babel__core@7.20.5": + '@types/babel__core@7.20.5': dependencies: - "@babel/parser": 7.29.2 - "@babel/types": 7.29.0 - "@types/babel__generator": 7.27.0 - "@types/babel__template": 7.4.4 - "@types/babel__traverse": 7.28.0 + '@babel/parser': 7.29.2 + '@babel/types': 7.29.0 + '@types/babel__generator': 7.27.0 + '@types/babel__template': 7.4.4 + '@types/babel__traverse': 7.28.0 - "@types/babel__generator@7.27.0": + '@types/babel__generator@7.27.0': dependencies: - "@babel/types": 7.29.0 + '@babel/types': 7.29.0 - "@types/babel__template@7.4.4": + '@types/babel__template@7.4.4': dependencies: - "@babel/parser": 7.29.2 - "@babel/types": 7.29.0 + '@babel/parser': 7.29.2 + '@babel/types': 7.29.0 - "@types/babel__traverse@7.28.0": + '@types/babel__traverse@7.28.0': dependencies: - "@babel/types": 7.29.0 + '@babel/types': 7.29.0 - "@types/chai@5.2.3": + '@types/chai@5.2.3': dependencies: - "@types/deep-eql": 4.0.2 + '@types/deep-eql': 4.0.2 assertion-error: 2.0.1 - "@types/content-type@1.1.9": {} + '@types/content-type@1.1.9': {} - "@types/deep-eql@4.0.2": {} + '@types/deep-eql@4.0.2': {} - "@types/doctrine@0.0.9": {} + '@types/doctrine@0.0.9': {} - "@types/dom-mediacapture-record@1.0.22": {} + '@types/dom-mediacapture-record@1.0.22': {} - "@types/dom-mediacapture-transform@0.1.11": + '@types/dom-mediacapture-transform@0.1.11': dependencies: - "@types/dom-webcodecs": 0.1.18 + '@types/dom-webcodecs': 0.1.18 - "@types/dom-webcodecs@0.1.18": {} + '@types/dom-webcodecs@0.1.18': {} - "@types/estree@1.0.8": {} + '@types/estree@1.0.8': {} - "@types/events@3.0.3": {} + '@types/events@3.0.3': {} - "@types/glob-to-regexp@0.4.4": {} + '@types/glob-to-regexp@0.4.4': {} - "@types/grecaptcha@3.0.9": {} + '@types/grecaptcha@3.0.9': {} - "@types/jsdom@21.1.7": + '@types/jsdom@21.1.7': dependencies: - "@types/node": 24.12.2 - "@types/tough-cookie": 4.0.5 + '@types/node': 24.12.2 + '@types/tough-cookie': 4.0.5 parse5: 7.3.0 - "@types/json-schema@7.0.15": {} + '@types/json-schema@7.0.15': {} - "@types/json5@0.0.29": {} + '@types/json5@0.0.29': {} - "@types/lodash-es@4.17.12": + '@types/lodash-es@4.17.12': dependencies: - "@types/lodash": 4.17.24 + '@types/lodash': 4.17.24 - "@types/lodash@4.17.24": {} + '@types/lodash@4.17.24': {} - "@types/mdx@2.0.13": {} + '@types/mdx@2.0.13': {} - "@types/minimatch@3.0.5": {} + '@types/minimatch@3.0.5': {} - "@types/node@24.12.2": + '@types/node@24.12.2': dependencies: undici-types: 7.16.0 - "@types/normalize-package-data@2.4.4": {} + '@types/normalize-package-data@2.4.4': {} - "@types/pako@2.0.4": {} + '@types/pako@2.0.4': {} - "@types/qrcode@1.5.6": + '@types/qrcode@1.5.6': dependencies: - "@types/node": 24.12.2 + '@types/node': 24.12.2 - "@types/react-dom@19.2.3(@types/react@19.2.14)": + '@types/react-dom@19.2.3(@types/react@19.2.14)': dependencies: - "@types/react": 19.2.14 + '@types/react': 19.2.14 - "@types/react@19.2.14": + '@types/react@19.2.14': dependencies: csstype: 3.2.3 - "@types/resolve@1.20.6": {} + '@types/resolve@1.20.6': {} - "@types/sdp-transform@2.15.0": {} + '@types/sdp-transform@2.15.0': {} - "@types/semver@7.7.1": {} + '@types/semver@7.7.1': {} - "@types/symlink-or-copy@1.2.2": {} + '@types/symlink-or-copy@1.2.2': {} - "@types/tough-cookie@4.0.5": {} + '@types/tough-cookie@4.0.5': {} - "@types/uuid@10.0.0": {} + '@types/uuid@10.0.0': {} - "@types/yargs-parser@21.0.3": {} + '@types/yargs-parser@21.0.3': {} - "@types/yargs@17.0.35": + '@types/yargs@17.0.35': dependencies: - "@types/yargs-parser": 21.0.3 + '@types/yargs-parser': 21.0.3 - "@typescript-eslint/eslint-plugin@8.58.2(@typescript-eslint/parser@8.58.2(eslint@8.57.1)(typescript@5.9.3))(eslint@8.57.1)(typescript@5.9.3)": + '@typescript-eslint/eslint-plugin@8.58.2(@typescript-eslint/parser@8.58.2(eslint@8.57.1)(typescript@5.9.3))(eslint@8.57.1)(typescript@5.9.3)': dependencies: - "@eslint-community/regexpp": 4.12.2 - "@typescript-eslint/parser": 8.58.2(eslint@8.57.1)(typescript@5.9.3) - "@typescript-eslint/scope-manager": 8.58.2 - "@typescript-eslint/type-utils": 8.58.2(eslint@8.57.1)(typescript@5.9.3) - "@typescript-eslint/utils": 8.58.2(eslint@8.57.1)(typescript@5.9.3) - "@typescript-eslint/visitor-keys": 8.58.2 + '@eslint-community/regexpp': 4.12.2 + '@typescript-eslint/parser': 8.58.2(eslint@8.57.1)(typescript@5.9.3) + '@typescript-eslint/scope-manager': 8.58.2 + '@typescript-eslint/type-utils': 8.58.2(eslint@8.57.1)(typescript@5.9.3) + '@typescript-eslint/utils': 8.58.2(eslint@8.57.1)(typescript@5.9.3) + '@typescript-eslint/visitor-keys': 8.58.2 eslint: 8.57.1 ignore: 7.0.5 natural-compare: 1.4.0 @@ -13103,54 +9333,54 @@ snapshots: transitivePeerDependencies: - supports-color - "@typescript-eslint/experimental-utils@5.62.0(eslint@8.57.1)(typescript@5.9.3)": + '@typescript-eslint/experimental-utils@5.62.0(eslint@8.57.1)(typescript@5.9.3)': dependencies: - "@typescript-eslint/utils": 5.62.0(eslint@8.57.1)(typescript@5.9.3) + '@typescript-eslint/utils': 5.62.0(eslint@8.57.1)(typescript@5.9.3) eslint: 8.57.1 transitivePeerDependencies: - supports-color - typescript - "@typescript-eslint/parser@8.58.2(eslint@8.57.1)(typescript@5.9.3)": + '@typescript-eslint/parser@8.58.2(eslint@8.57.1)(typescript@5.9.3)': dependencies: - "@typescript-eslint/scope-manager": 8.58.2 - "@typescript-eslint/types": 8.58.2 - "@typescript-eslint/typescript-estree": 8.58.2(typescript@5.9.3) - "@typescript-eslint/visitor-keys": 8.58.2 + '@typescript-eslint/scope-manager': 8.58.2 + '@typescript-eslint/types': 8.58.2 + '@typescript-eslint/typescript-estree': 8.58.2(typescript@5.9.3) + '@typescript-eslint/visitor-keys': 8.58.2 debug: 4.4.3 eslint: 8.57.1 typescript: 5.9.3 transitivePeerDependencies: - supports-color - "@typescript-eslint/project-service@8.58.2(typescript@5.9.3)": + '@typescript-eslint/project-service@8.58.2(typescript@5.9.3)': dependencies: - "@typescript-eslint/tsconfig-utils": 8.58.2(typescript@5.9.3) - "@typescript-eslint/types": 8.58.2 + '@typescript-eslint/tsconfig-utils': 8.58.2(typescript@5.9.3) + '@typescript-eslint/types': 8.58.2 debug: 4.4.3 typescript: 5.9.3 transitivePeerDependencies: - supports-color - "@typescript-eslint/scope-manager@5.62.0": + '@typescript-eslint/scope-manager@5.62.0': dependencies: - "@typescript-eslint/types": 5.62.0 - "@typescript-eslint/visitor-keys": 5.62.0 + '@typescript-eslint/types': 5.62.0 + '@typescript-eslint/visitor-keys': 5.62.0 - "@typescript-eslint/scope-manager@8.58.2": + '@typescript-eslint/scope-manager@8.58.2': dependencies: - "@typescript-eslint/types": 8.58.2 - "@typescript-eslint/visitor-keys": 8.58.2 + '@typescript-eslint/types': 8.58.2 + '@typescript-eslint/visitor-keys': 8.58.2 - "@typescript-eslint/tsconfig-utils@8.58.2(typescript@5.9.3)": + '@typescript-eslint/tsconfig-utils@8.58.2(typescript@5.9.3)': dependencies: typescript: 5.9.3 - "@typescript-eslint/type-utils@8.58.2(eslint@8.57.1)(typescript@5.9.3)": + '@typescript-eslint/type-utils@8.58.2(eslint@8.57.1)(typescript@5.9.3)': dependencies: - "@typescript-eslint/types": 8.58.2 - "@typescript-eslint/typescript-estree": 8.58.2(typescript@5.9.3) - "@typescript-eslint/utils": 8.58.2(eslint@8.57.1)(typescript@5.9.3) + '@typescript-eslint/types': 8.58.2 + '@typescript-eslint/typescript-estree': 8.58.2(typescript@5.9.3) + '@typescript-eslint/utils': 8.58.2(eslint@8.57.1)(typescript@5.9.3) debug: 4.4.3 eslint: 8.57.1 ts-api-utils: 2.5.0(typescript@5.9.3) @@ -13158,14 +9388,14 @@ snapshots: transitivePeerDependencies: - supports-color - "@typescript-eslint/types@5.62.0": {} + '@typescript-eslint/types@5.62.0': {} - "@typescript-eslint/types@8.58.2": {} + '@typescript-eslint/types@8.58.2': {} - "@typescript-eslint/typescript-estree@5.62.0(typescript@5.9.3)": + '@typescript-eslint/typescript-estree@5.62.0(typescript@5.9.3)': dependencies: - "@typescript-eslint/types": 5.62.0 - "@typescript-eslint/visitor-keys": 5.62.0 + '@typescript-eslint/types': 5.62.0 + '@typescript-eslint/visitor-keys': 5.62.0 debug: 4.4.3 globby: 11.1.0 is-glob: 4.0.3 @@ -13176,12 +9406,12 @@ snapshots: transitivePeerDependencies: - supports-color - "@typescript-eslint/typescript-estree@8.58.2(typescript@5.9.3)": + '@typescript-eslint/typescript-estree@8.58.2(typescript@5.9.3)': dependencies: - "@typescript-eslint/project-service": 8.58.2(typescript@5.9.3) - "@typescript-eslint/tsconfig-utils": 8.58.2(typescript@5.9.3) - "@typescript-eslint/types": 8.58.2 - "@typescript-eslint/visitor-keys": 8.58.2 + '@typescript-eslint/project-service': 8.58.2(typescript@5.9.3) + '@typescript-eslint/tsconfig-utils': 8.58.2(typescript@5.9.3) + '@typescript-eslint/types': 8.58.2 + '@typescript-eslint/visitor-keys': 8.58.2 debug: 4.4.3 minimatch: 10.2.5 semver: 7.7.4 @@ -13191,14 +9421,14 @@ snapshots: transitivePeerDependencies: - supports-color - "@typescript-eslint/utils@5.62.0(eslint@8.57.1)(typescript@5.9.3)": + '@typescript-eslint/utils@5.62.0(eslint@8.57.1)(typescript@5.9.3)': dependencies: - "@eslint-community/eslint-utils": 4.9.1(eslint@8.57.1) - "@types/json-schema": 7.0.15 - "@types/semver": 7.7.1 - "@typescript-eslint/scope-manager": 5.62.0 - "@typescript-eslint/types": 5.62.0 - "@typescript-eslint/typescript-estree": 5.62.0(typescript@5.9.3) + '@eslint-community/eslint-utils': 4.9.1(eslint@8.57.1) + '@types/json-schema': 7.0.15 + '@types/semver': 7.7.1 + '@typescript-eslint/scope-manager': 5.62.0 + '@typescript-eslint/types': 5.62.0 + '@typescript-eslint/typescript-estree': 5.62.0(typescript@5.9.3) eslint: 8.57.1 eslint-scope: 5.1.1 semver: 7.7.4 @@ -13206,78 +9436,78 @@ snapshots: - supports-color - typescript - "@typescript-eslint/utils@8.58.2(eslint@8.57.1)(typescript@5.9.3)": + '@typescript-eslint/utils@8.58.2(eslint@8.57.1)(typescript@5.9.3)': dependencies: - "@eslint-community/eslint-utils": 4.9.1(eslint@8.57.1) - "@typescript-eslint/scope-manager": 8.58.2 - "@typescript-eslint/types": 8.58.2 - "@typescript-eslint/typescript-estree": 8.58.2(typescript@5.9.3) + '@eslint-community/eslint-utils': 4.9.1(eslint@8.57.1) + '@typescript-eslint/scope-manager': 8.58.2 + '@typescript-eslint/types': 8.58.2 + '@typescript-eslint/typescript-estree': 8.58.2(typescript@5.9.3) eslint: 8.57.1 typescript: 5.9.3 transitivePeerDependencies: - supports-color - "@typescript-eslint/visitor-keys@5.62.0": + '@typescript-eslint/visitor-keys@5.62.0': dependencies: - "@typescript-eslint/types": 5.62.0 + '@typescript-eslint/types': 5.62.0 eslint-visitor-keys: 3.4.3 - "@typescript-eslint/visitor-keys@8.58.2": + '@typescript-eslint/visitor-keys@8.58.2': dependencies: - "@typescript-eslint/types": 8.58.2 + '@typescript-eslint/types': 8.58.2 eslint-visitor-keys: 5.0.1 - "@ungap/structured-clone@1.3.0": {} + '@ungap/structured-clone@1.3.0': {} - "@use-gesture/core@10.3.1": {} + '@use-gesture/core@10.3.1': {} - "@use-gesture/react@10.3.1(react@19.2.5)": + '@use-gesture/react@10.3.1(react@19.2.5)': dependencies: - "@use-gesture/core": 10.3.1 + '@use-gesture/core': 10.3.1 react: 19.2.5 - "@vector-im/compound-design-tokens@10.1.0(@types/react@19.2.14)(react@19.2.5)": + '@vector-im/compound-design-tokens@10.1.0(@types/react@19.2.14)(react@19.2.5)': optionalDependencies: - "@types/react": 19.2.14 + '@types/react': 19.2.14 react: 19.2.5 - "@vector-im/compound-web@9.2.0(@fontsource/inconsolata@5.2.8)(@fontsource/inter@5.2.8)(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(@vector-im/compound-design-tokens@10.1.0(@types/react@19.2.14)(react@19.2.5))(react-dom@19.2.5(react@19.2.5))(react@19.2.5)": + '@vector-im/compound-web@9.2.0(@fontsource/inconsolata@5.2.8)(@fontsource/inter@5.2.8)(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(@vector-im/compound-design-tokens@10.1.0(@types/react@19.2.14)(react@19.2.5))(react-dom@19.2.5(react@19.2.5))(react@19.2.5)': dependencies: - "@floating-ui/react": 0.27.19(react-dom@19.2.5(react@19.2.5))(react@19.2.5) - "@fontsource/inconsolata": 5.2.8 - "@fontsource/inter": 5.2.8 - "@radix-ui/react-context-menu": 2.2.16(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5) - "@radix-ui/react-dropdown-menu": 2.1.16(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5) - "@radix-ui/react-form": 0.1.8(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5) - "@radix-ui/react-progress": 1.1.8(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5) - "@radix-ui/react-separator": 1.1.8(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5) - "@radix-ui/react-slot": 1.2.4(@types/react@19.2.14)(react@19.2.5) - "@vector-im/compound-design-tokens": 10.1.0(@types/react@19.2.14)(react@19.2.5) + '@floating-ui/react': 0.27.19(react-dom@19.2.5(react@19.2.5))(react@19.2.5) + '@fontsource/inconsolata': 5.2.8 + '@fontsource/inter': 5.2.8 + '@radix-ui/react-context-menu': 2.2.16(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5) + '@radix-ui/react-dropdown-menu': 2.1.16(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5) + '@radix-ui/react-form': 0.1.8(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5) + '@radix-ui/react-progress': 1.1.8(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5) + '@radix-ui/react-separator': 1.1.8(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5) + '@radix-ui/react-slot': 1.2.4(@types/react@19.2.14)(react@19.2.5) + '@vector-im/compound-design-tokens': 10.1.0(@types/react@19.2.14)(react@19.2.5) classnames: 2.5.1 react: 19.2.5 vaul: 1.1.2(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5) optionalDependencies: - "@types/react": 19.2.14 + '@types/react': 19.2.14 transitivePeerDependencies: - - "@types/react-dom" + - '@types/react-dom' - react-dom - "@vitejs/plugin-react@4.7.0(vite@8.0.8(@types/node@24.12.2)(esbuild@0.27.7)(jiti@2.6.1)(sass@1.99.0)(terser@5.46.1)(yaml@2.8.3))": + '@vitejs/plugin-react@4.7.0(vite@8.0.8(@types/node@24.12.2)(esbuild@0.27.7)(jiti@2.6.1)(sass@1.99.0)(terser@5.46.1)(yaml@2.8.3))': dependencies: - "@babel/core": 7.29.0 - "@babel/plugin-transform-react-jsx-self": 7.27.1(@babel/core@7.29.0) - "@babel/plugin-transform-react-jsx-source": 7.27.1(@babel/core@7.29.0) - "@rolldown/pluginutils": 1.0.0-beta.27 - "@types/babel__core": 7.20.5 + '@babel/core': 7.29.0 + '@babel/plugin-transform-react-jsx-self': 7.27.1(@babel/core@7.29.0) + '@babel/plugin-transform-react-jsx-source': 7.27.1(@babel/core@7.29.0) + '@rolldown/pluginutils': 1.0.0-beta.27 + '@types/babel__core': 7.20.5 react-refresh: 0.17.0 vite: 8.0.8(@types/node@24.12.2)(esbuild@0.27.7)(jiti@2.6.1)(sass@1.99.0)(terser@5.46.1)(yaml@2.8.3) transitivePeerDependencies: - supports-color - "@vitest/coverage-v8@4.1.4(vitest@4.1.4)": + '@vitest/coverage-v8@4.1.4(vitest@4.1.4)': dependencies: - "@bcoe/v8-coverage": 1.0.2 - "@vitest/utils": 4.1.4 + '@bcoe/v8-coverage': 1.0.2 + '@vitest/utils': 4.1.4 ast-v8-to-istanbul: 1.0.0 istanbul-lib-coverage: 3.2.2 istanbul-lib-report: 3.0.1 @@ -13288,70 +9518,70 @@ snapshots: tinyrainbow: 3.1.0 vitest: 4.1.4(@types/node@24.12.2)(@vitest/coverage-v8@4.1.4)(jsdom@26.1.0)(vite@8.0.8(@types/node@24.12.2)(esbuild@0.27.7)(jiti@2.6.1)(sass@1.99.0)(terser@5.46.1)(yaml@2.8.3)) - "@vitest/expect@3.2.4": + '@vitest/expect@3.2.4': dependencies: - "@types/chai": 5.2.3 - "@vitest/spy": 3.2.4 - "@vitest/utils": 3.2.4 + '@types/chai': 5.2.3 + '@vitest/spy': 3.2.4 + '@vitest/utils': 3.2.4 chai: 5.3.3 tinyrainbow: 2.0.0 - "@vitest/expect@4.1.4": + '@vitest/expect@4.1.4': dependencies: - "@standard-schema/spec": 1.1.0 - "@types/chai": 5.2.3 - "@vitest/spy": 4.1.4 - "@vitest/utils": 4.1.4 + '@standard-schema/spec': 1.1.0 + '@types/chai': 5.2.3 + '@vitest/spy': 4.1.4 + '@vitest/utils': 4.1.4 chai: 6.2.2 tinyrainbow: 3.1.0 - "@vitest/mocker@4.1.4(vite@8.0.8(@types/node@24.12.2)(esbuild@0.27.7)(jiti@2.6.1)(sass@1.99.0)(terser@5.46.1)(yaml@2.8.3))": + '@vitest/mocker@4.1.4(vite@8.0.8(@types/node@24.12.2)(esbuild@0.27.7)(jiti@2.6.1)(sass@1.99.0)(terser@5.46.1)(yaml@2.8.3))': dependencies: - "@vitest/spy": 4.1.4 + '@vitest/spy': 4.1.4 estree-walker: 3.0.3 magic-string: 0.30.21 optionalDependencies: vite: 8.0.8(@types/node@24.12.2)(esbuild@0.27.7)(jiti@2.6.1)(sass@1.99.0)(terser@5.46.1)(yaml@2.8.3) - "@vitest/pretty-format@3.2.4": + '@vitest/pretty-format@3.2.4': dependencies: tinyrainbow: 2.0.0 - "@vitest/pretty-format@4.1.4": + '@vitest/pretty-format@4.1.4': dependencies: tinyrainbow: 3.1.0 - "@vitest/runner@4.1.4": + '@vitest/runner@4.1.4': dependencies: - "@vitest/utils": 4.1.4 + '@vitest/utils': 4.1.4 pathe: 2.0.3 - "@vitest/snapshot@4.1.4": + '@vitest/snapshot@4.1.4': dependencies: - "@vitest/pretty-format": 4.1.4 - "@vitest/utils": 4.1.4 + '@vitest/pretty-format': 4.1.4 + '@vitest/utils': 4.1.4 magic-string: 0.30.21 pathe: 2.0.3 - "@vitest/spy@3.2.4": + '@vitest/spy@3.2.4': dependencies: tinyspy: 4.0.4 - "@vitest/spy@4.1.4": {} + '@vitest/spy@4.1.4': {} - "@vitest/utils@3.2.4": + '@vitest/utils@3.2.4': dependencies: - "@vitest/pretty-format": 3.2.4 + '@vitest/pretty-format': 3.2.4 loupe: 3.2.1 tinyrainbow: 2.0.0 - "@vitest/utils@4.1.4": + '@vitest/utils@4.1.4': dependencies: - "@vitest/pretty-format": 4.1.4 + '@vitest/pretty-format': 4.1.4 convert-source-map: 2.0.0 tinyrainbow: 3.1.0 - "@webcontainer/env@1.1.1": {} + '@webcontainer/env@1.1.1': {} acorn-jsx@5.3.2(acorn@8.16.0): dependencies: @@ -13500,7 +9730,7 @@ snapshots: ast-v8-to-istanbul@1.0.0: dependencies: - "@jridgewell/trace-mapping": 0.3.31 + '@jridgewell/trace-mapping': 0.3.31 estree-walker: 3.0.3 js-tokens: 10.0.0 @@ -13529,32 +9759,32 @@ snapshots: babel-plugin-polyfill-corejs2@0.4.17(@babel/core@7.29.0): dependencies: - "@babel/compat-data": 7.29.0 - "@babel/core": 7.29.0 - "@babel/helper-define-polyfill-provider": 0.6.8(@babel/core@7.29.0) + '@babel/compat-data': 7.29.0 + '@babel/core': 7.29.0 + '@babel/helper-define-polyfill-provider': 0.6.8(@babel/core@7.29.0) semver: 6.3.1 transitivePeerDependencies: - supports-color babel-plugin-polyfill-corejs3@0.14.2(@babel/core@7.29.0): dependencies: - "@babel/core": 7.29.0 - "@babel/helper-define-polyfill-provider": 0.6.8(@babel/core@7.29.0) + '@babel/core': 7.29.0 + '@babel/helper-define-polyfill-provider': 0.6.8(@babel/core@7.29.0) core-js-compat: 3.49.0 transitivePeerDependencies: - supports-color babel-plugin-polyfill-regenerator@0.6.8(@babel/core@7.29.0): dependencies: - "@babel/core": 7.29.0 - "@babel/helper-define-polyfill-provider": 0.6.8(@babel/core@7.29.0) + '@babel/core': 7.29.0 + '@babel/helper-define-polyfill-provider': 0.6.8(@babel/core@7.29.0) transitivePeerDependencies: - supports-color babel-plugin-transform-vite-meta-env@1.0.3: dependencies: - "@babel/runtime": 7.29.2 - "@types/babel__core": 7.20.5 + '@babel/runtime': 7.29.2 + '@types/babel__core': 7.20.5 balanced-match@4.0.4: {} @@ -13935,7 +10165,7 @@ snapshots: css-has-pseudo@7.0.3(postcss@8.5.10): dependencies: - "@csstools/selector-specificity": 5.0.0(postcss-selector-parser@7.1.1) + '@csstools/selector-specificity': 5.0.0(postcss-selector-parser@7.1.1) postcss: 8.5.10 postcss-selector-parser: 7.1.1 postcss-value-parser: 4.2.0 @@ -13970,7 +10200,7 @@ snapshots: cssstyle@4.6.0: dependencies: - "@asamuzakjp/css-color": 3.2.0 + '@asamuzakjp/css-color': 3.2.0 rrweb-cssom: 0.8.0 csstype@3.2.3: {} @@ -14281,32 +10511,32 @@ snapshots: esbuild@0.27.7: optionalDependencies: - "@esbuild/aix-ppc64": 0.27.7 - "@esbuild/android-arm": 0.27.7 - "@esbuild/android-arm64": 0.27.7 - "@esbuild/android-x64": 0.27.7 - "@esbuild/darwin-arm64": 0.27.7 - "@esbuild/darwin-x64": 0.27.7 - "@esbuild/freebsd-arm64": 0.27.7 - "@esbuild/freebsd-x64": 0.27.7 - "@esbuild/linux-arm": 0.27.7 - "@esbuild/linux-arm64": 0.27.7 - "@esbuild/linux-ia32": 0.27.7 - "@esbuild/linux-loong64": 0.27.7 - "@esbuild/linux-mips64el": 0.27.7 - "@esbuild/linux-ppc64": 0.27.7 - "@esbuild/linux-riscv64": 0.27.7 - "@esbuild/linux-s390x": 0.27.7 - "@esbuild/linux-x64": 0.27.7 - "@esbuild/netbsd-arm64": 0.27.7 - "@esbuild/netbsd-x64": 0.27.7 - "@esbuild/openbsd-arm64": 0.27.7 - "@esbuild/openbsd-x64": 0.27.7 - "@esbuild/openharmony-arm64": 0.27.7 - "@esbuild/sunos-x64": 0.27.7 - "@esbuild/win32-arm64": 0.27.7 - "@esbuild/win32-ia32": 0.27.7 - "@esbuild/win32-x64": 0.27.7 + '@esbuild/aix-ppc64': 0.27.7 + '@esbuild/android-arm': 0.27.7 + '@esbuild/android-arm64': 0.27.7 + '@esbuild/android-x64': 0.27.7 + '@esbuild/darwin-arm64': 0.27.7 + '@esbuild/darwin-x64': 0.27.7 + '@esbuild/freebsd-arm64': 0.27.7 + '@esbuild/freebsd-x64': 0.27.7 + '@esbuild/linux-arm': 0.27.7 + '@esbuild/linux-arm64': 0.27.7 + '@esbuild/linux-ia32': 0.27.7 + '@esbuild/linux-loong64': 0.27.7 + '@esbuild/linux-mips64el': 0.27.7 + '@esbuild/linux-ppc64': 0.27.7 + '@esbuild/linux-riscv64': 0.27.7 + '@esbuild/linux-s390x': 0.27.7 + '@esbuild/linux-x64': 0.27.7 + '@esbuild/netbsd-arm64': 0.27.7 + '@esbuild/netbsd-x64': 0.27.7 + '@esbuild/openbsd-arm64': 0.27.7 + '@esbuild/openbsd-x64': 0.27.7 + '@esbuild/openharmony-arm64': 0.27.7 + '@esbuild/sunos-x64': 0.27.7 + '@esbuild/win32-arm64': 0.27.7 + '@esbuild/win32-ia32': 0.27.7 + '@esbuild/win32-x64': 0.27.7 escalade@3.2.0: {} @@ -14324,7 +10554,7 @@ snapshots: eslint-etc@5.2.1(eslint@8.57.1)(typescript@5.9.3): dependencies: - "@typescript-eslint/experimental-utils": 5.62.0(eslint@8.57.1)(typescript@5.9.3) + '@typescript-eslint/experimental-utils': 5.62.0(eslint@8.57.1)(typescript@5.9.3) eslint: 8.57.1 tsutils: 3.21.0(typescript@5.9.3) tsutils-etc: 1.4.2(tsutils@3.21.0(typescript@5.9.3))(typescript@5.9.3) @@ -14344,7 +10574,7 @@ snapshots: dependencies: debug: 3.2.7 optionalDependencies: - "@typescript-eslint/parser": 8.58.2(eslint@8.57.1)(typescript@5.9.3) + '@typescript-eslint/parser': 8.58.2(eslint@8.57.1)(typescript@5.9.3) eslint: 8.57.1 eslint-import-resolver-node: 0.3.10 transitivePeerDependencies: @@ -14356,7 +10586,7 @@ snapshots: eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.58.2(eslint@8.57.1)(typescript@5.9.3))(eslint@8.57.1): dependencies: - "@rtsao/scc": 1.1.0 + '@rtsao/scc': 1.1.0 array-includes: 3.1.9 array.prototype.findlastindex: 1.2.6 array.prototype.flat: 1.3.3 @@ -14377,7 +10607,7 @@ snapshots: string.prototype.trimend: 1.0.9 tsconfig-paths: 3.15.0 optionalDependencies: - "@typescript-eslint/parser": 8.58.2(eslint@8.57.1)(typescript@5.9.3) + '@typescript-eslint/parser': 8.58.2(eslint@8.57.1)(typescript@5.9.3) transitivePeerDependencies: - eslint-import-resolver-typescript - eslint-import-resolver-webpack @@ -14385,18 +10615,18 @@ snapshots: eslint-plugin-jest@29.15.2(@typescript-eslint/eslint-plugin@8.58.2(@typescript-eslint/parser@8.58.2(eslint@8.57.1)(typescript@5.9.3))(eslint@8.57.1)(typescript@5.9.3))(eslint@8.57.1)(typescript@5.9.3): dependencies: - "@typescript-eslint/utils": 8.58.2(eslint@8.57.1)(typescript@5.9.3) + '@typescript-eslint/utils': 8.58.2(eslint@8.57.1)(typescript@5.9.3) eslint: 8.57.1 optionalDependencies: - "@typescript-eslint/eslint-plugin": 8.58.2(@typescript-eslint/parser@8.58.2(eslint@8.57.1)(typescript@5.9.3))(eslint@8.57.1)(typescript@5.9.3) + '@typescript-eslint/eslint-plugin': 8.58.2(@typescript-eslint/parser@8.58.2(eslint@8.57.1)(typescript@5.9.3))(eslint@8.57.1)(typescript@5.9.3) typescript: 5.9.3 transitivePeerDependencies: - supports-color eslint-plugin-jsdoc@61.7.1(eslint@8.57.1): dependencies: - "@es-joy/jsdoccomment": 0.78.0 - "@es-joy/resolve.exports": 1.2.0 + '@es-joy/jsdoccomment': 0.78.0 + '@es-joy/resolve.exports': 1.2.0 are-docs-informative: 0.0.2 comment-parser: 1.4.1 debug: 4.4.3 @@ -14432,14 +10662,14 @@ snapshots: safe-regex-test: 1.1.0 string.prototype.includes: 2.0.1 - eslint-plugin-matrix-org@2.1.0(@babel/core@7.29.0)(@babel/eslint-parser@7.28.6(@babel/core@7.29.0)(eslint@8.57.1))(@babel/eslint-plugin@7.27.1(@babel/eslint-parser@7.28.6(@babel/core@7.29.0)(eslint@8.57.1))(eslint@8.57.1))(@stylistic/eslint-plugin@3.1.0(eslint@8.57.1)(typescript@5.9.3))(@typescript-eslint/eslint-plugin@8.58.2(@typescript-eslint/parser@8.58.2(eslint@8.57.1)(typescript@5.9.3))(eslint@8.57.1)(typescript@5.9.3))(@typescript-eslint/parser@8.58.2(eslint@8.57.1)(typescript@5.9.3))(eslint-config-google@0.14.0(eslint@8.57.1))(eslint-config-prettier@10.1.8(eslint@8.57.1))(eslint-plugin-deprecate@0.9.0(eslint@8.57.1))(eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.58.2(eslint@8.57.1)(typescript@5.9.3))(eslint@8.57.1))(eslint-plugin-jest@29.15.2(@typescript-eslint/eslint-plugin@8.58.2(@typescript-eslint/parser@8.58.2(eslint@8.57.1)(typescript@5.9.3))(eslint@8.57.1)(typescript@5.9.3))(eslint@8.57.1)(typescript@5.9.3))(eslint-plugin-jsx-a11y@6.10.2(eslint@8.57.1))(eslint-plugin-react-hooks@5.2.0(eslint@8.57.1))(eslint-plugin-react@7.37.5(eslint@8.57.1))(eslint-plugin-unicorn@56.0.1(eslint@8.57.1))(eslint@8.57.1)(prettier@3.8.3)(typescript@5.9.3): - dependencies: - "@babel/core": 7.29.0 - "@babel/eslint-parser": 7.28.6(@babel/core@7.29.0)(eslint@8.57.1) - "@babel/eslint-plugin": 7.27.1(@babel/eslint-parser@7.28.6(@babel/core@7.29.0)(eslint@8.57.1))(eslint@8.57.1) - "@stylistic/eslint-plugin": 3.1.0(eslint@8.57.1)(typescript@5.9.3) - "@typescript-eslint/eslint-plugin": 8.58.2(@typescript-eslint/parser@8.58.2(eslint@8.57.1)(typescript@5.9.3))(eslint@8.57.1)(typescript@5.9.3) - "@typescript-eslint/parser": 8.58.2(eslint@8.57.1)(typescript@5.9.3) + ? eslint-plugin-matrix-org@2.1.0(@babel/core@7.29.0)(@babel/eslint-parser@7.28.6(@babel/core@7.29.0)(eslint@8.57.1))(@babel/eslint-plugin@7.27.1(@babel/eslint-parser@7.28.6(@babel/core@7.29.0)(eslint@8.57.1))(eslint@8.57.1))(@stylistic/eslint-plugin@3.1.0(eslint@8.57.1)(typescript@5.9.3))(@typescript-eslint/eslint-plugin@8.58.2(@typescript-eslint/parser@8.58.2(eslint@8.57.1)(typescript@5.9.3))(eslint@8.57.1)(typescript@5.9.3))(@typescript-eslint/parser@8.58.2(eslint@8.57.1)(typescript@5.9.3))(eslint-config-google@0.14.0(eslint@8.57.1))(eslint-config-prettier@10.1.8(eslint@8.57.1))(eslint-plugin-deprecate@0.9.0(eslint@8.57.1))(eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.58.2(eslint@8.57.1)(typescript@5.9.3))(eslint@8.57.1))(eslint-plugin-jest@29.15.2(@typescript-eslint/eslint-plugin@8.58.2(@typescript-eslint/parser@8.58.2(eslint@8.57.1)(typescript@5.9.3))(eslint@8.57.1)(typescript@5.9.3))(eslint@8.57.1)(typescript@5.9.3))(eslint-plugin-jsx-a11y@6.10.2(eslint@8.57.1))(eslint-plugin-react-hooks@5.2.0(eslint@8.57.1))(eslint-plugin-react@7.37.5(eslint@8.57.1))(eslint-plugin-unicorn@56.0.1(eslint@8.57.1))(eslint@8.57.1)(prettier@3.8.3)(typescript@5.9.3) + : dependencies: + '@babel/core': 7.29.0 + '@babel/eslint-parser': 7.28.6(@babel/core@7.29.0)(eslint@8.57.1) + '@babel/eslint-plugin': 7.27.1(@babel/eslint-parser@7.28.6(@babel/core@7.29.0)(eslint@8.57.1))(eslint@8.57.1) + '@stylistic/eslint-plugin': 3.1.0(eslint@8.57.1)(typescript@5.9.3) + '@typescript-eslint/eslint-plugin': 8.58.2(@typescript-eslint/parser@8.58.2(eslint@8.57.1)(typescript@5.9.3))(eslint@8.57.1)(typescript@5.9.3) + '@typescript-eslint/parser': 8.58.2(eslint@8.57.1)(typescript@5.9.3) eslint: 8.57.1 eslint-config-google: 0.14.0(eslint@8.57.1) eslint-config-prettier: 10.1.8(eslint@8.57.1) @@ -14481,7 +10711,7 @@ snapshots: eslint-plugin-rxjs@5.0.3(eslint@8.57.1)(typescript@5.9.3): dependencies: - "@typescript-eslint/experimental-utils": 5.62.0(eslint@8.57.1)(typescript@5.9.3) + '@typescript-eslint/experimental-utils': 5.62.0(eslint@8.57.1)(typescript@5.9.3) common-tags: 1.8.2 decamelize: 5.0.1 eslint: 8.57.1 @@ -14497,7 +10727,7 @@ snapshots: eslint-plugin-storybook@10.3.5(eslint@8.57.1)(storybook@10.3.5(@testing-library/dom@10.4.1)(prettier@3.8.3)(react-dom@19.2.5(react@19.2.5))(react@19.2.5))(typescript@5.9.3): dependencies: - "@typescript-eslint/utils": 8.58.2(eslint@8.57.1)(typescript@5.9.3) + '@typescript-eslint/utils': 8.58.2(eslint@8.57.1)(typescript@5.9.3) eslint: 8.57.1 storybook: 10.3.5(@testing-library/dom@10.4.1)(prettier@3.8.3)(react-dom@19.2.5(react@19.2.5))(react@19.2.5) transitivePeerDependencies: @@ -14506,8 +10736,8 @@ snapshots: eslint-plugin-unicorn@56.0.1(eslint@8.57.1): dependencies: - "@babel/helper-validator-identifier": 7.28.5 - "@eslint-community/eslint-utils": 4.9.1(eslint@8.57.1) + '@babel/helper-validator-identifier': 7.28.5 + '@eslint-community/eslint-utils': 4.9.1(eslint@8.57.1) ci-info: 4.4.0 clean-regexp: 1.0.0 core-js-compat: 3.49.0 @@ -14546,14 +10776,14 @@ snapshots: eslint@8.57.1: dependencies: - "@eslint-community/eslint-utils": 4.9.1(eslint@8.57.1) - "@eslint-community/regexpp": 4.12.2 - "@eslint/eslintrc": 2.1.4 - "@eslint/js": 8.57.1 - "@humanwhocodes/config-array": 0.13.0 - "@humanwhocodes/module-importer": 1.0.1 - "@nodelib/fs.walk": 1.2.8 - "@ungap/structured-clone": 1.3.0 + '@eslint-community/eslint-utils': 4.9.1(eslint@8.57.1) + '@eslint-community/regexpp': 4.12.2 + '@eslint/eslintrc': 2.1.4 + '@eslint/js': 8.57.1 + '@humanwhocodes/config-array': 0.13.0 + '@humanwhocodes/module-importer': 1.0.1 + '@nodelib/fs.walk': 1.2.8 + '@ungap/structured-clone': 1.3.0 ajv: 6.14.0 chalk: 4.1.2 cross-spawn: 7.0.6 @@ -14623,7 +10853,7 @@ snapshots: estree-walker@3.0.3: dependencies: - "@types/estree": 1.0.8 + '@types/estree': 1.0.8 esutils@2.0.3: {} @@ -14648,8 +10878,8 @@ snapshots: fast-glob@3.3.3: dependencies: - "@nodelib/fs.stat": 2.0.5 - "@nodelib/fs.walk": 1.2.8 + '@nodelib/fs.stat': 2.0.5 + '@nodelib/fs.walk': 1.2.8 glob-parent: 5.1.2 merge2: 1.4.1 micromatch: 4.0.8 @@ -14672,7 +10902,7 @@ snapshots: fetch-mock@11.1.5: dependencies: - "@types/glob-to-regexp": 0.4.4 + '@types/glob-to-regexp': 0.4.4 dequal: 2.0.3 glob-to-regexp: 0.4.1 is-subset: 0.1.1 @@ -14763,7 +10993,7 @@ snapshots: fs-tree-diff@2.0.1: dependencies: - "@types/symlink-or-copy": 1.2.2 + '@types/symlink-or-copy': 1.2.2 heimdalljs-logger: 0.1.10 object-assign: 4.1.1 path-posix: 1.0.0 @@ -14832,7 +11062,7 @@ snapshots: glob-stream@8.0.3: dependencies: - "@gulpjs/to-absolute-glob": 4.0.0 + '@gulpjs/to-absolute-glob': 4.0.0 anymatch: 3.1.3 fastq: 1.20.1 glob-parent: 6.0.2 @@ -15007,11 +11237,11 @@ snapshots: i18next-browser-languagedetector@8.2.1: dependencies: - "@babel/runtime": 7.29.2 + '@babel/runtime': 7.29.2 i18next-parser@9.4.0: dependencies: - "@babel/runtime": 7.29.2 + '@babel/runtime': 7.29.2 broccoli-plugin: 4.0.7 cheerio: 1.2.0 colors: 1.4.0 @@ -15035,13 +11265,13 @@ snapshots: i18next@24.2.3(typescript@5.9.3): dependencies: - "@babel/runtime": 7.29.2 + '@babel/runtime': 7.29.2 optionalDependencies: typescript: 5.9.3 i18next@25.10.10(typescript@5.9.3): dependencies: - "@babel/runtime": 7.29.2 + '@babel/runtime': 7.29.2 optionalDependencies: typescript: 5.9.3 @@ -15262,9 +11492,9 @@ snapshots: jackspeak@3.4.3: dependencies: - "@isaacs/cliui": 8.0.2 + '@isaacs/cliui': 8.0.2 optionalDependencies: - "@pkgjs/parseargs": 0.11.0 + '@pkgjs/parseargs': 0.11.0 jake@10.9.4: dependencies: @@ -15358,8 +11588,8 @@ snapshots: knip@5.88.1(@emnapi/core@1.9.2)(@emnapi/runtime@1.9.2)(@types/node@24.12.2)(typescript@5.9.3): dependencies: - "@nodelib/fs.walk": 1.2.8 - "@types/node": 24.12.2 + '@nodelib/fs.walk': 1.2.8 + '@types/node': 24.12.2 fast-glob: 3.3.3 formatly: 0.3.0 jiti: 2.6.1 @@ -15374,8 +11604,8 @@ snapshots: yaml: 2.8.3 zod: 4.3.6 transitivePeerDependencies: - - "@emnapi/core" - - "@emnapi/runtime" + - '@emnapi/core' + - '@emnapi/runtime' language-subtag-registry@0.3.23: {} @@ -15445,9 +11675,9 @@ snapshots: livekit-client@2.18.3(@types/dom-mediacapture-record@1.0.22): dependencies: - "@livekit/mutex": 1.1.1 - "@livekit/protocol": 1.45.3 - "@types/dom-mediacapture-record": 1.0.22 + '@livekit/mutex': 1.1.1 + '@livekit/protocol': 1.45.3 + '@types/dom-mediacapture-record': 1.0.22 events: 3.3.0 jose: 6.2.2 loglevel: 1.9.2 @@ -15494,16 +11724,16 @@ snapshots: magic-string@0.30.21: dependencies: - "@jridgewell/sourcemap-codec": 1.5.5 + '@jridgewell/sourcemap-codec': 1.5.5 magic-string@0.30.8: dependencies: - "@jridgewell/sourcemap-codec": 1.5.5 + '@jridgewell/sourcemap-codec': 1.5.5 magicast@0.5.2: dependencies: - "@babel/parser": 7.29.2 - "@babel/types": 7.29.0 + '@babel/parser': 7.29.2 + '@babel/types': 7.29.0 source-map-js: 1.2.1 make-dir@4.0.0: @@ -15512,17 +11742,17 @@ snapshots: matcher-collection@2.0.1: dependencies: - "@types/minimatch": 3.0.5 + '@types/minimatch': 3.0.5 minimatch: 10.2.5 math-intrinsics@1.1.0: {} matrix-events-sdk@0.0.1: {} - matrix-js-sdk@https://codeload.github.com/matrix-org/matrix-js-sdk/tar.gz/ca5655bced1cbb215ac1c18e179384a069d98b0a: + matrix-js-sdk@https://codeload.github.com/matrix-org/matrix-js-sdk/tar.gz/fd01b172368e0ac5479d4830f92ad261a7eccc6c: dependencies: - "@babel/runtime": 7.29.2 - "@matrix-org/matrix-sdk-crypto-wasm": 18.0.0 + '@babel/runtime': 7.29.2 + '@matrix-org/matrix-sdk-crypto-wasm': 18.0.0 another-json: 0.2.0 bs58: 6.0.0 content-type: 1.0.5 @@ -15538,7 +11768,7 @@ snapshots: matrix-widget-api@1.17.0: dependencies: - "@types/events": 3.0.3 + '@types/events': 3.0.3 events: 3.3.0 md5.js@1.3.5: @@ -15757,29 +11987,29 @@ snapshots: oxc-resolver@11.19.1(@emnapi/core@1.9.2)(@emnapi/runtime@1.9.2): optionalDependencies: - "@oxc-resolver/binding-android-arm-eabi": 11.19.1 - "@oxc-resolver/binding-android-arm64": 11.19.1 - "@oxc-resolver/binding-darwin-arm64": 11.19.1 - "@oxc-resolver/binding-darwin-x64": 11.19.1 - "@oxc-resolver/binding-freebsd-x64": 11.19.1 - "@oxc-resolver/binding-linux-arm-gnueabihf": 11.19.1 - "@oxc-resolver/binding-linux-arm-musleabihf": 11.19.1 - "@oxc-resolver/binding-linux-arm64-gnu": 11.19.1 - "@oxc-resolver/binding-linux-arm64-musl": 11.19.1 - "@oxc-resolver/binding-linux-ppc64-gnu": 11.19.1 - "@oxc-resolver/binding-linux-riscv64-gnu": 11.19.1 - "@oxc-resolver/binding-linux-riscv64-musl": 11.19.1 - "@oxc-resolver/binding-linux-s390x-gnu": 11.19.1 - "@oxc-resolver/binding-linux-x64-gnu": 11.19.1 - "@oxc-resolver/binding-linux-x64-musl": 11.19.1 - "@oxc-resolver/binding-openharmony-arm64": 11.19.1 - "@oxc-resolver/binding-wasm32-wasi": 11.19.1(@emnapi/core@1.9.2)(@emnapi/runtime@1.9.2) - "@oxc-resolver/binding-win32-arm64-msvc": 11.19.1 - "@oxc-resolver/binding-win32-ia32-msvc": 11.19.1 - "@oxc-resolver/binding-win32-x64-msvc": 11.19.1 + '@oxc-resolver/binding-android-arm-eabi': 11.19.1 + '@oxc-resolver/binding-android-arm64': 11.19.1 + '@oxc-resolver/binding-darwin-arm64': 11.19.1 + '@oxc-resolver/binding-darwin-x64': 11.19.1 + '@oxc-resolver/binding-freebsd-x64': 11.19.1 + '@oxc-resolver/binding-linux-arm-gnueabihf': 11.19.1 + '@oxc-resolver/binding-linux-arm-musleabihf': 11.19.1 + '@oxc-resolver/binding-linux-arm64-gnu': 11.19.1 + '@oxc-resolver/binding-linux-arm64-musl': 11.19.1 + '@oxc-resolver/binding-linux-ppc64-gnu': 11.19.1 + '@oxc-resolver/binding-linux-riscv64-gnu': 11.19.1 + '@oxc-resolver/binding-linux-riscv64-musl': 11.19.1 + '@oxc-resolver/binding-linux-s390x-gnu': 11.19.1 + '@oxc-resolver/binding-linux-x64-gnu': 11.19.1 + '@oxc-resolver/binding-linux-x64-musl': 11.19.1 + '@oxc-resolver/binding-openharmony-arm64': 11.19.1 + '@oxc-resolver/binding-wasm32-wasi': 11.19.1(@emnapi/core@1.9.2)(@emnapi/runtime@1.9.2) + '@oxc-resolver/binding-win32-arm64-msvc': 11.19.1 + '@oxc-resolver/binding-win32-ia32-msvc': 11.19.1 + '@oxc-resolver/binding-win32-x64-msvc': 11.19.1 transitivePeerDependencies: - - "@emnapi/core" - - "@emnapi/runtime" + - '@emnapi/core' + - '@emnapi/runtime' p-limit@2.3.0: dependencies: @@ -15832,7 +12062,7 @@ snapshots: parse-json@5.2.0: dependencies: - "@babel/code-frame": 7.29.0 + '@babel/code-frame': 7.29.0 error-ex: 1.3.4 json-parse-even-better-errors: 2.3.1 lines-and-columns: 1.2.4 @@ -15925,47 +12155,47 @@ snapshots: postcss-color-functional-notation@7.0.12(postcss@8.5.10): dependencies: - "@csstools/css-color-parser": 3.1.0(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4) - "@csstools/css-parser-algorithms": 3.0.5(@csstools/css-tokenizer@3.0.4) - "@csstools/css-tokenizer": 3.0.4 - "@csstools/postcss-progressive-custom-properties": 4.2.1(postcss@8.5.10) - "@csstools/utilities": 2.0.0(postcss@8.5.10) + '@csstools/css-color-parser': 3.1.0(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4) + '@csstools/css-parser-algorithms': 3.0.5(@csstools/css-tokenizer@3.0.4) + '@csstools/css-tokenizer': 3.0.4 + '@csstools/postcss-progressive-custom-properties': 4.2.1(postcss@8.5.10) + '@csstools/utilities': 2.0.0(postcss@8.5.10) postcss: 8.5.10 postcss-color-hex-alpha@10.0.0(postcss@8.5.10): dependencies: - "@csstools/utilities": 2.0.0(postcss@8.5.10) + '@csstools/utilities': 2.0.0(postcss@8.5.10) postcss: 8.5.10 postcss-value-parser: 4.2.0 postcss-color-rebeccapurple@10.0.0(postcss@8.5.10): dependencies: - "@csstools/utilities": 2.0.0(postcss@8.5.10) + '@csstools/utilities': 2.0.0(postcss@8.5.10) postcss: 8.5.10 postcss-value-parser: 4.2.0 postcss-custom-media@11.0.6(postcss@8.5.10): dependencies: - "@csstools/cascade-layer-name-parser": 2.0.5(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4) - "@csstools/css-parser-algorithms": 3.0.5(@csstools/css-tokenizer@3.0.4) - "@csstools/css-tokenizer": 3.0.4 - "@csstools/media-query-list-parser": 4.0.3(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4) + '@csstools/cascade-layer-name-parser': 2.0.5(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4) + '@csstools/css-parser-algorithms': 3.0.5(@csstools/css-tokenizer@3.0.4) + '@csstools/css-tokenizer': 3.0.4 + '@csstools/media-query-list-parser': 4.0.3(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4) postcss: 8.5.10 postcss-custom-properties@14.0.6(postcss@8.5.10): dependencies: - "@csstools/cascade-layer-name-parser": 2.0.5(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4) - "@csstools/css-parser-algorithms": 3.0.5(@csstools/css-tokenizer@3.0.4) - "@csstools/css-tokenizer": 3.0.4 - "@csstools/utilities": 2.0.0(postcss@8.5.10) + '@csstools/cascade-layer-name-parser': 2.0.5(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4) + '@csstools/css-parser-algorithms': 3.0.5(@csstools/css-tokenizer@3.0.4) + '@csstools/css-tokenizer': 3.0.4 + '@csstools/utilities': 2.0.0(postcss@8.5.10) postcss: 8.5.10 postcss-value-parser: 4.2.0 postcss-custom-selectors@8.0.5(postcss@8.5.10): dependencies: - "@csstools/cascade-layer-name-parser": 2.0.5(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4) - "@csstools/css-parser-algorithms": 3.0.5(@csstools/css-tokenizer@3.0.4) - "@csstools/css-tokenizer": 3.0.4 + '@csstools/cascade-layer-name-parser': 2.0.5(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4) + '@csstools/css-parser-algorithms': 3.0.5(@csstools/css-tokenizer@3.0.4) + '@csstools/css-tokenizer': 3.0.4 postcss: 8.5.10 postcss-selector-parser: 7.1.1 @@ -15976,8 +12206,8 @@ snapshots: postcss-double-position-gradients@6.0.4(postcss@8.5.10): dependencies: - "@csstools/postcss-progressive-custom-properties": 4.2.1(postcss@8.5.10) - "@csstools/utilities": 2.0.0(postcss@8.5.10) + '@csstools/postcss-progressive-custom-properties': 4.2.1(postcss@8.5.10) + '@csstools/utilities': 2.0.0(postcss@8.5.10) postcss: 8.5.10 postcss-value-parser: 4.2.0 @@ -16001,17 +12231,17 @@ snapshots: postcss-image-set-function@7.0.0(postcss@8.5.10): dependencies: - "@csstools/utilities": 2.0.0(postcss@8.5.10) + '@csstools/utilities': 2.0.0(postcss@8.5.10) postcss: 8.5.10 postcss-value-parser: 4.2.0 postcss-lab-function@7.0.12(postcss@8.5.10): dependencies: - "@csstools/css-color-parser": 3.1.0(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4) - "@csstools/css-parser-algorithms": 3.0.5(@csstools/css-tokenizer@3.0.4) - "@csstools/css-tokenizer": 3.0.4 - "@csstools/postcss-progressive-custom-properties": 4.2.1(postcss@8.5.10) - "@csstools/utilities": 2.0.0(postcss@8.5.10) + '@csstools/css-color-parser': 3.1.0(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4) + '@csstools/css-parser-algorithms': 3.0.5(@csstools/css-tokenizer@3.0.4) + '@csstools/css-tokenizer': 3.0.4 + '@csstools/postcss-progressive-custom-properties': 4.2.1(postcss@8.5.10) + '@csstools/utilities': 2.0.0(postcss@8.5.10) postcss: 8.5.10 postcss-logical@8.1.0(postcss@8.5.10): @@ -16021,8 +12251,8 @@ snapshots: postcss-nesting@13.0.2(postcss@8.5.10): dependencies: - "@csstools/selector-resolve-nested": 3.1.0(postcss-selector-parser@7.1.1) - "@csstools/selector-specificity": 5.0.0(postcss-selector-parser@7.1.1) + '@csstools/selector-resolve-nested': 3.1.0(postcss-selector-parser@7.1.1) + '@csstools/selector-specificity': 5.0.0(postcss-selector-parser@7.1.1) postcss: 8.5.10 postcss-selector-parser: 7.1.1 @@ -16046,46 +12276,46 @@ snapshots: postcss-preset-env@10.6.1(postcss@8.5.10): dependencies: - "@csstools/postcss-alpha-function": 1.0.1(postcss@8.5.10) - "@csstools/postcss-cascade-layers": 5.0.2(postcss@8.5.10) - "@csstools/postcss-color-function": 4.0.12(postcss@8.5.10) - "@csstools/postcss-color-function-display-p3-linear": 1.0.1(postcss@8.5.10) - "@csstools/postcss-color-mix-function": 3.0.12(postcss@8.5.10) - "@csstools/postcss-color-mix-variadic-function-arguments": 1.0.2(postcss@8.5.10) - "@csstools/postcss-content-alt-text": 2.0.8(postcss@8.5.10) - "@csstools/postcss-contrast-color-function": 2.0.12(postcss@8.5.10) - "@csstools/postcss-exponential-functions": 2.0.9(postcss@8.5.10) - "@csstools/postcss-font-format-keywords": 4.0.0(postcss@8.5.10) - "@csstools/postcss-gamut-mapping": 2.0.11(postcss@8.5.10) - "@csstools/postcss-gradients-interpolation-method": 5.0.12(postcss@8.5.10) - "@csstools/postcss-hwb-function": 4.0.12(postcss@8.5.10) - "@csstools/postcss-ic-unit": 4.0.4(postcss@8.5.10) - "@csstools/postcss-initial": 2.0.1(postcss@8.5.10) - "@csstools/postcss-is-pseudo-class": 5.0.3(postcss@8.5.10) - "@csstools/postcss-light-dark-function": 2.0.11(postcss@8.5.10) - "@csstools/postcss-logical-float-and-clear": 3.0.0(postcss@8.5.10) - "@csstools/postcss-logical-overflow": 2.0.0(postcss@8.5.10) - "@csstools/postcss-logical-overscroll-behavior": 2.0.0(postcss@8.5.10) - "@csstools/postcss-logical-resize": 3.0.0(postcss@8.5.10) - "@csstools/postcss-logical-viewport-units": 3.0.4(postcss@8.5.10) - "@csstools/postcss-media-minmax": 2.0.9(postcss@8.5.10) - "@csstools/postcss-media-queries-aspect-ratio-number-values": 3.0.5(postcss@8.5.10) - "@csstools/postcss-nested-calc": 4.0.0(postcss@8.5.10) - "@csstools/postcss-normalize-display-values": 4.0.1(postcss@8.5.10) - "@csstools/postcss-oklab-function": 4.0.12(postcss@8.5.10) - "@csstools/postcss-position-area-property": 1.0.0(postcss@8.5.10) - "@csstools/postcss-progressive-custom-properties": 4.2.1(postcss@8.5.10) - "@csstools/postcss-property-rule-prelude-list": 1.0.0(postcss@8.5.10) - "@csstools/postcss-random-function": 2.0.1(postcss@8.5.10) - "@csstools/postcss-relative-color-syntax": 3.0.12(postcss@8.5.10) - "@csstools/postcss-scope-pseudo-class": 4.0.1(postcss@8.5.10) - "@csstools/postcss-sign-functions": 1.1.4(postcss@8.5.10) - "@csstools/postcss-stepped-value-functions": 4.0.9(postcss@8.5.10) - "@csstools/postcss-syntax-descriptor-syntax-production": 1.0.1(postcss@8.5.10) - "@csstools/postcss-system-ui-font-family": 1.0.0(postcss@8.5.10) - "@csstools/postcss-text-decoration-shorthand": 4.0.3(postcss@8.5.10) - "@csstools/postcss-trigonometric-functions": 4.0.9(postcss@8.5.10) - "@csstools/postcss-unset-value": 4.0.0(postcss@8.5.10) + '@csstools/postcss-alpha-function': 1.0.1(postcss@8.5.10) + '@csstools/postcss-cascade-layers': 5.0.2(postcss@8.5.10) + '@csstools/postcss-color-function': 4.0.12(postcss@8.5.10) + '@csstools/postcss-color-function-display-p3-linear': 1.0.1(postcss@8.5.10) + '@csstools/postcss-color-mix-function': 3.0.12(postcss@8.5.10) + '@csstools/postcss-color-mix-variadic-function-arguments': 1.0.2(postcss@8.5.10) + '@csstools/postcss-content-alt-text': 2.0.8(postcss@8.5.10) + '@csstools/postcss-contrast-color-function': 2.0.12(postcss@8.5.10) + '@csstools/postcss-exponential-functions': 2.0.9(postcss@8.5.10) + '@csstools/postcss-font-format-keywords': 4.0.0(postcss@8.5.10) + '@csstools/postcss-gamut-mapping': 2.0.11(postcss@8.5.10) + '@csstools/postcss-gradients-interpolation-method': 5.0.12(postcss@8.5.10) + '@csstools/postcss-hwb-function': 4.0.12(postcss@8.5.10) + '@csstools/postcss-ic-unit': 4.0.4(postcss@8.5.10) + '@csstools/postcss-initial': 2.0.1(postcss@8.5.10) + '@csstools/postcss-is-pseudo-class': 5.0.3(postcss@8.5.10) + '@csstools/postcss-light-dark-function': 2.0.11(postcss@8.5.10) + '@csstools/postcss-logical-float-and-clear': 3.0.0(postcss@8.5.10) + '@csstools/postcss-logical-overflow': 2.0.0(postcss@8.5.10) + '@csstools/postcss-logical-overscroll-behavior': 2.0.0(postcss@8.5.10) + '@csstools/postcss-logical-resize': 3.0.0(postcss@8.5.10) + '@csstools/postcss-logical-viewport-units': 3.0.4(postcss@8.5.10) + '@csstools/postcss-media-minmax': 2.0.9(postcss@8.5.10) + '@csstools/postcss-media-queries-aspect-ratio-number-values': 3.0.5(postcss@8.5.10) + '@csstools/postcss-nested-calc': 4.0.0(postcss@8.5.10) + '@csstools/postcss-normalize-display-values': 4.0.1(postcss@8.5.10) + '@csstools/postcss-oklab-function': 4.0.12(postcss@8.5.10) + '@csstools/postcss-position-area-property': 1.0.0(postcss@8.5.10) + '@csstools/postcss-progressive-custom-properties': 4.2.1(postcss@8.5.10) + '@csstools/postcss-property-rule-prelude-list': 1.0.0(postcss@8.5.10) + '@csstools/postcss-random-function': 2.0.1(postcss@8.5.10) + '@csstools/postcss-relative-color-syntax': 3.0.12(postcss@8.5.10) + '@csstools/postcss-scope-pseudo-class': 4.0.1(postcss@8.5.10) + '@csstools/postcss-sign-functions': 1.1.4(postcss@8.5.10) + '@csstools/postcss-stepped-value-functions': 4.0.9(postcss@8.5.10) + '@csstools/postcss-syntax-descriptor-syntax-production': 1.0.1(postcss@8.5.10) + '@csstools/postcss-system-ui-font-family': 1.0.0(postcss@8.5.10) + '@csstools/postcss-text-decoration-shorthand': 4.0.3(postcss@8.5.10) + '@csstools/postcss-trigonometric-functions': 4.0.9(postcss@8.5.10) + '@csstools/postcss-unset-value': 4.0.0(postcss@8.5.10) autoprefixer: 10.5.0(postcss@8.5.10) browserslist: 4.28.2 css-blank-pseudo: 7.0.1(postcss@8.5.10) @@ -16233,13 +12463,13 @@ snapshots: react-docgen@8.0.3: dependencies: - "@babel/core": 7.29.0 - "@babel/traverse": 7.29.0 - "@babel/types": 7.29.0 - "@types/babel__core": 7.20.5 - "@types/babel__traverse": 7.28.0 - "@types/doctrine": 0.0.9 - "@types/resolve": 1.20.6 + '@babel/core': 7.29.0 + '@babel/traverse': 7.29.0 + '@babel/types': 7.29.0 + '@types/babel__core': 7.20.5 + '@types/babel__traverse': 7.28.0 + '@types/doctrine': 0.0.9 + '@types/resolve': 1.20.6 doctrine: 3.0.0 resolve: 1.22.12 strip-indent: 4.1.1 @@ -16253,7 +12483,7 @@ snapshots: react-i18next@16.6.6(i18next@25.10.10(typescript@5.9.3))(react-dom@19.2.5(react@19.2.5))(react@19.2.5)(typescript@5.9.3): dependencies: - "@babel/runtime": 7.29.2 + '@babel/runtime': 7.29.2 html-parse-stringify: 3.0.1 i18next: 25.10.10(typescript@5.9.3) react: 19.2.5 @@ -16274,7 +12504,7 @@ snapshots: react-style-singleton: 2.2.3(@types/react@19.2.14)(react@19.2.5) tslib: 2.8.1 optionalDependencies: - "@types/react": 19.2.14 + '@types/react': 19.2.14 react-remove-scroll@2.7.2(@types/react@19.2.14)(react@19.2.5): dependencies: @@ -16285,7 +12515,7 @@ snapshots: use-callback-ref: 1.3.3(@types/react@19.2.14)(react@19.2.5) use-sidecar: 1.1.3(@types/react@19.2.14)(react@19.2.5) optionalDependencies: - "@types/react": 19.2.14 + '@types/react': 19.2.14 react-router-dom@7.14.1(react-dom@19.2.5(react@19.2.5))(react@19.2.5): dependencies: @@ -16307,7 +12537,7 @@ snapshots: react: 19.2.5 tslib: 2.8.1 optionalDependencies: - "@types/react": 19.2.14 + '@types/react': 19.2.14 react-use-measure@2.1.7(react-dom@19.2.5(react@19.2.5))(react@19.2.5): dependencies: @@ -16325,7 +12555,7 @@ snapshots: read-pkg@5.2.0: dependencies: - "@types/normalize-package-data": 2.4.4 + '@types/normalize-package-data': 2.4.4 normalize-package-data: 2.5.0 parse-json: 5.2.0 type-fest: 0.6.0 @@ -16467,24 +12697,56 @@ snapshots: rolldown@1.0.0-rc.15: dependencies: - "@oxc-project/types": 0.124.0 - "@rolldown/pluginutils": 1.0.0-rc.15 + '@oxc-project/types': 0.124.0 + '@rolldown/pluginutils': 1.0.0-rc.15 optionalDependencies: - "@rolldown/binding-android-arm64": 1.0.0-rc.15 - "@rolldown/binding-darwin-arm64": 1.0.0-rc.15 - "@rolldown/binding-darwin-x64": 1.0.0-rc.15 - "@rolldown/binding-freebsd-x64": 1.0.0-rc.15 - "@rolldown/binding-linux-arm-gnueabihf": 1.0.0-rc.15 - "@rolldown/binding-linux-arm64-gnu": 1.0.0-rc.15 - "@rolldown/binding-linux-arm64-musl": 1.0.0-rc.15 - "@rolldown/binding-linux-ppc64-gnu": 1.0.0-rc.15 - "@rolldown/binding-linux-s390x-gnu": 1.0.0-rc.15 - "@rolldown/binding-linux-x64-gnu": 1.0.0-rc.15 - "@rolldown/binding-linux-x64-musl": 1.0.0-rc.15 - "@rolldown/binding-openharmony-arm64": 1.0.0-rc.15 - "@rolldown/binding-wasm32-wasi": 1.0.0-rc.15 - "@rolldown/binding-win32-arm64-msvc": 1.0.0-rc.15 - "@rolldown/binding-win32-x64-msvc": 1.0.0-rc.15 + '@rolldown/binding-android-arm64': 1.0.0-rc.15 + '@rolldown/binding-darwin-arm64': 1.0.0-rc.15 + '@rolldown/binding-darwin-x64': 1.0.0-rc.15 + '@rolldown/binding-freebsd-x64': 1.0.0-rc.15 + '@rolldown/binding-linux-arm-gnueabihf': 1.0.0-rc.15 + '@rolldown/binding-linux-arm64-gnu': 1.0.0-rc.15 + '@rolldown/binding-linux-arm64-musl': 1.0.0-rc.15 + '@rolldown/binding-linux-ppc64-gnu': 1.0.0-rc.15 + '@rolldown/binding-linux-s390x-gnu': 1.0.0-rc.15 + '@rolldown/binding-linux-x64-gnu': 1.0.0-rc.15 + '@rolldown/binding-linux-x64-musl': 1.0.0-rc.15 + '@rolldown/binding-openharmony-arm64': 1.0.0-rc.15 + '@rolldown/binding-wasm32-wasi': 1.0.0-rc.15 + '@rolldown/binding-win32-arm64-msvc': 1.0.0-rc.15 + '@rolldown/binding-win32-x64-msvc': 1.0.0-rc.15 + + rollup@4.60.1: + dependencies: + '@types/estree': 1.0.8 + optionalDependencies: + '@rollup/rollup-android-arm-eabi': 4.60.1 + '@rollup/rollup-android-arm64': 4.60.1 + '@rollup/rollup-darwin-arm64': 4.60.1 + '@rollup/rollup-darwin-x64': 4.60.1 + '@rollup/rollup-freebsd-arm64': 4.60.1 + '@rollup/rollup-freebsd-x64': 4.60.1 + '@rollup/rollup-linux-arm-gnueabihf': 4.60.1 + '@rollup/rollup-linux-arm-musleabihf': 4.60.1 + '@rollup/rollup-linux-arm64-gnu': 4.60.1 + '@rollup/rollup-linux-arm64-musl': 4.60.1 + '@rollup/rollup-linux-loong64-gnu': 4.60.1 + '@rollup/rollup-linux-loong64-musl': 4.60.1 + '@rollup/rollup-linux-ppc64-gnu': 4.60.1 + '@rollup/rollup-linux-ppc64-musl': 4.60.1 + '@rollup/rollup-linux-riscv64-gnu': 4.60.1 + '@rollup/rollup-linux-riscv64-musl': 4.60.1 + '@rollup/rollup-linux-s390x-gnu': 4.60.1 + '@rollup/rollup-linux-x64-gnu': 4.60.1 + '@rollup/rollup-linux-x64-musl': 4.60.1 + '@rollup/rollup-openbsd-x64': 4.60.1 + '@rollup/rollup-openharmony-arm64': 4.60.1 + '@rollup/rollup-win32-arm64-msvc': 4.60.1 + '@rollup/rollup-win32-ia32-msvc': 4.60.1 + '@rollup/rollup-win32-x64-gnu': 4.60.1 + '@rollup/rollup-win32-x64-msvc': 4.60.1 + fsevents: 2.3.3 + optional: true rrweb-cssom@0.8.0: {} @@ -16500,9 +12762,9 @@ snapshots: rxjs-report-usage@1.0.6: dependencies: - "@babel/parser": 7.29.2 - "@babel/traverse": 7.29.0 - "@babel/types": 7.29.0 + '@babel/parser': 7.29.2 + '@babel/traverse': 7.29.0 + '@babel/types': 7.29.0 bent: 7.3.12 chalk: 4.1.2 glob: 10.5.0 @@ -16545,7 +12807,7 @@ snapshots: immutable: 5.1.5 source-map-js: 1.2.1 optionalDependencies: - "@parcel/watcher": 2.5.6 + '@parcel/watcher': 2.5.6 saxes@6.0.0: dependencies: @@ -16693,13 +12955,13 @@ snapshots: storybook@10.3.5(@testing-library/dom@10.4.1)(prettier@3.8.3)(react-dom@19.2.5(react@19.2.5))(react@19.2.5): dependencies: - "@storybook/global": 5.0.0 - "@storybook/icons": 2.0.1(react-dom@19.2.5(react@19.2.5))(react@19.2.5) - "@testing-library/jest-dom": 6.9.1 - "@testing-library/user-event": 14.6.1(@testing-library/dom@10.4.1) - "@vitest/expect": 3.2.4 - "@vitest/spy": 3.2.4 - "@webcontainer/env": 1.1.1 + '@storybook/global': 5.0.0 + '@storybook/icons': 2.0.1(react-dom@19.2.5(react@19.2.5))(react@19.2.5) + '@testing-library/jest-dom': 6.9.1 + '@testing-library/user-event': 14.6.1(@testing-library/dom@10.4.1) + '@vitest/expect': 3.2.4 + '@vitest/spy': 3.2.4 + '@webcontainer/env': 1.1.1 esbuild: 0.27.7 open: 10.2.0 recast: 0.23.11 @@ -16709,7 +12971,7 @@ snapshots: optionalDependencies: prettier: 3.8.3 transitivePeerDependencies: - - "@testing-library/dom" + - '@testing-library/dom' - bufferutil - react - react-dom @@ -16856,7 +13118,7 @@ snapshots: terser@5.46.1: dependencies: - "@jridgewell/source-map": 0.3.11 + '@jridgewell/source-map': 0.3.11 acorn: 8.16.0 commander: 2.20.3 source-map-support: 0.5.21 @@ -16920,7 +13182,7 @@ snapshots: to-valid-identifier@1.0.0: dependencies: - "@sindresorhus/base62": 1.0.0 + '@sindresorhus/base62': 1.0.0 reserved-identifiers: 1.2.0 toggle-selection@1.0.6: {} @@ -16943,7 +13205,7 @@ snapshots: tsconfig-paths@3.15.0: dependencies: - "@types/json5": 0.0.29 + '@types/json5': 0.0.29 json5: 1.0.2 minimist: 1.2.8 strip-bom: 3.0.0 @@ -16960,7 +13222,7 @@ snapshots: tsutils-etc@1.4.2(tsutils@3.21.0(typescript@5.9.3))(typescript@5.9.3): dependencies: - "@types/yargs": 17.0.35 + '@types/yargs': 17.0.35 tsutils: 3.21.0(typescript@5.9.3) typescript: 5.9.3 yargs: 17.7.2 @@ -17023,7 +13285,7 @@ snapshots: typescript-eslint-language-service@5.0.5(@typescript-eslint/parser@8.58.2(eslint@8.57.1)(typescript@5.9.3))(eslint@8.57.1)(typescript@5.9.3): dependencies: - "@typescript-eslint/parser": 8.58.2(eslint@8.57.1)(typescript@5.9.3) + '@typescript-eslint/parser': 8.58.2(eslint@8.57.1)(typescript@5.9.3) eslint: 8.57.1 typescript: 5.9.3 @@ -17047,7 +13309,7 @@ snapshots: undici@5.29.0: dependencies: - "@fastify/busboy": 2.1.1 + '@fastify/busboy': 2.1.1 undici@7.25.0: {} @@ -17086,7 +13348,7 @@ snapshots: unplugin@2.3.11: dependencies: - "@jridgewell/remapping": 2.3.5 + '@jridgewell/remapping': 2.3.5 acorn: 8.16.0 picomatch: 4.0.4 webpack-virtual-modules: 0.6.2 @@ -17111,7 +13373,7 @@ snapshots: react: 19.2.5 tslib: 2.8.1 optionalDependencies: - "@types/react": 19.2.14 + '@types/react': 19.2.14 use-sidecar@1.1.3(@types/react@19.2.14)(react@19.2.5): dependencies: @@ -17119,7 +13381,7 @@ snapshots: react: 19.2.5 tslib: 2.8.1 optionalDependencies: - "@types/react": 19.2.14 + '@types/react': 19.2.14 use-sync-external-store@1.6.0(react@19.2.5): dependencies: @@ -17151,12 +13413,12 @@ snapshots: vaul@1.1.2(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5): dependencies: - "@radix-ui/react-dialog": 1.1.15(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5) + '@radix-ui/react-dialog': 1.1.15(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.5(react@19.2.5))(react@19.2.5) react: 19.2.5 react-dom: 19.2.5(react@19.2.5) transitivePeerDependencies: - - "@types/react" - - "@types/react-dom" + - '@types/react' + - '@types/react-dom' vinyl-contents@2.0.0: dependencies: @@ -17217,7 +13479,7 @@ snapshots: vite-plugin-html@3.2.2(vite@8.0.8(@types/node@24.12.2)(esbuild@0.27.7)(jiti@2.6.1)(sass@1.99.0)(terser@5.46.1)(yaml@2.8.3)): dependencies: - "@rollup/pluginutils": 4.2.1 + '@rollup/pluginutils': 4.2.1 colorette: 2.0.20 connect-history-api-fallback: 1.6.0 consola: 2.15.3 @@ -17231,25 +13493,37 @@ snapshots: pathe: 0.2.0 vite: 8.0.8(@types/node@24.12.2)(esbuild@0.27.7)(jiti@2.6.1)(sass@1.99.0)(terser@5.46.1)(yaml@2.8.3) - vite-plugin-node-stdlib-browser@0.2.1(node-stdlib-browser@1.3.1)(vite@8.0.8(@types/node@24.12.2)(esbuild@0.27.7)(jiti@2.6.1)(sass@1.99.0)(terser@5.46.1)(yaml@2.8.3)): + vite-plugin-node-polyfills@0.26.0(rollup@4.60.1)(vite@8.0.8(@types/node@24.12.2)(esbuild@0.27.7)(jiti@2.6.1)(sass@1.99.0)(terser@5.46.1)(yaml@2.8.3)): dependencies: - "@rollup/plugin-inject": 5.0.5 + '@rollup/plugin-inject': 5.0.5(rollup@4.60.1) node-stdlib-browser: 1.3.1 vite: 8.0.8(@types/node@24.12.2)(esbuild@0.27.7)(jiti@2.6.1)(sass@1.99.0)(terser@5.46.1)(yaml@2.8.3) transitivePeerDependencies: - rollup - vite-plugin-svgr@4.5.0(typescript@5.9.3)(vite@8.0.8(@types/node@24.12.2)(esbuild@0.27.7)(jiti@2.6.1)(sass@1.99.0)(terser@5.46.1)(yaml@2.8.3)): + vite-plugin-node-stdlib-browser@0.2.1(node-stdlib-browser@1.3.1)(rollup@4.60.1)(vite@8.0.8(@types/node@24.12.2)(esbuild@0.27.7)(jiti@2.6.1)(sass@1.99.0)(terser@5.46.1)(yaml@2.8.3)): dependencies: - "@rollup/pluginutils": 5.3.0 - "@svgr/core": 8.1.0(typescript@5.9.3) - "@svgr/plugin-jsx": 8.1.0(@svgr/core@8.1.0(typescript@5.9.3)) + '@rollup/plugin-inject': 5.0.5(rollup@4.60.1) + node-stdlib-browser: 1.3.1 + vite: 8.0.8(@types/node@24.12.2)(esbuild@0.27.7)(jiti@2.6.1)(sass@1.99.0)(terser@5.46.1)(yaml@2.8.3) + transitivePeerDependencies: + - rollup + + vite-plugin-svgr@4.5.0(rollup@4.60.1)(typescript@5.9.3)(vite@8.0.8(@types/node@24.12.2)(esbuild@0.27.7)(jiti@2.6.1)(sass@1.99.0)(terser@5.46.1)(yaml@2.8.3)): + dependencies: + '@rollup/pluginutils': 5.3.0(rollup@4.60.1) + '@svgr/core': 8.1.0(typescript@5.9.3) + '@svgr/plugin-jsx': 8.1.0(@svgr/core@8.1.0(typescript@5.9.3)) vite: 8.0.8(@types/node@24.12.2)(esbuild@0.27.7)(jiti@2.6.1)(sass@1.99.0)(terser@5.46.1)(yaml@2.8.3) transitivePeerDependencies: - rollup - supports-color - typescript + vite-plugin-wasm@3.6.0(vite@8.0.8(@types/node@24.12.2)(esbuild@0.27.7)(jiti@2.6.1)(sass@1.99.0)(terser@5.46.1)(yaml@2.8.3)): + dependencies: + vite: 8.0.8(@types/node@24.12.2)(esbuild@0.27.7)(jiti@2.6.1)(sass@1.99.0)(terser@5.46.1)(yaml@2.8.3) + vite@8.0.8(@types/node@24.12.2)(esbuild@0.27.7)(jiti@2.6.1)(sass@1.99.0)(terser@5.46.1)(yaml@2.8.3): dependencies: lightningcss: 1.32.0 @@ -17258,7 +13532,7 @@ snapshots: rolldown: 1.0.0-rc.15 tinyglobby: 0.2.16 optionalDependencies: - "@types/node": 24.12.2 + '@types/node': 24.12.2 esbuild: 0.27.7 fsevents: 2.3.3 jiti: 2.6.1 @@ -17268,7 +13542,7 @@ snapshots: vitest-axe@1.0.0-pre.5(vitest@4.1.4(@types/node@24.12.2)(@vitest/coverage-v8@4.1.4)(jsdom@26.1.0)(vite@8.0.8(@types/node@24.12.2)(esbuild@0.27.7)(jiti@2.6.1)(sass@1.99.0)(terser@5.46.1)(yaml@2.8.3))): dependencies: - "@vitest/pretty-format": 3.2.4 + '@vitest/pretty-format': 3.2.4 axe-core: 4.11.3 chalk: 5.6.2 lodash-es: 4.18.1 @@ -17276,13 +13550,13 @@ snapshots: vitest@4.1.4(@types/node@24.12.2)(@vitest/coverage-v8@4.1.4)(jsdom@26.1.0)(vite@8.0.8(@types/node@24.12.2)(esbuild@0.27.7)(jiti@2.6.1)(sass@1.99.0)(terser@5.46.1)(yaml@2.8.3)): dependencies: - "@vitest/expect": 4.1.4 - "@vitest/mocker": 4.1.4(vite@8.0.8(@types/node@24.12.2)(esbuild@0.27.7)(jiti@2.6.1)(sass@1.99.0)(terser@5.46.1)(yaml@2.8.3)) - "@vitest/pretty-format": 4.1.4 - "@vitest/runner": 4.1.4 - "@vitest/snapshot": 4.1.4 - "@vitest/spy": 4.1.4 - "@vitest/utils": 4.1.4 + '@vitest/expect': 4.1.4 + '@vitest/mocker': 4.1.4(vite@8.0.8(@types/node@24.12.2)(esbuild@0.27.7)(jiti@2.6.1)(sass@1.99.0)(terser@5.46.1)(yaml@2.8.3)) + '@vitest/pretty-format': 4.1.4 + '@vitest/runner': 4.1.4 + '@vitest/snapshot': 4.1.4 + '@vitest/spy': 4.1.4 + '@vitest/utils': 4.1.4 es-module-lexer: 2.0.0 expect-type: 1.3.0 magic-string: 0.30.21 @@ -17297,8 +13571,8 @@ snapshots: vite: 8.0.8(@types/node@24.12.2)(esbuild@0.27.7)(jiti@2.6.1)(sass@1.99.0)(terser@5.46.1)(yaml@2.8.3) why-is-node-running: 2.3.0 optionalDependencies: - "@types/node": 24.12.2 - "@vitest/coverage-v8": 4.1.4(vitest@4.1.4) + '@types/node': 24.12.2 + '@vitest/coverage-v8': 4.1.4(vitest@4.1.4) jsdom: 26.1.0 transitivePeerDependencies: - msw @@ -17313,7 +13587,7 @@ snapshots: walk-sync@2.2.0: dependencies: - "@types/minimatch": 3.0.5 + '@types/minimatch': 3.0.5 ensure-posix-path: 1.1.1 matcher-collection: 2.0.1 minimatch: 10.2.5 diff --git a/vite.config.ts b/vite.config.ts index 3374f0846..5b3ab2994 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -17,6 +17,8 @@ import { createHtmlPlugin } from "vite-plugin-html"; import { codecovVitePlugin } from "@codecov/vite-plugin"; import { sentryVitePlugin } from "@sentry/vite-plugin"; +import { nodePolyfills } from 'vite-plugin-node-polyfills' +import wasm from "vite-plugin-wasm"; import react from "@vitejs/plugin-react"; import { realpathSync } from "fs"; @@ -36,6 +38,11 @@ export default ({ process.env.VITE_PACKAGE = packageType ?? "full"; const plugins: PluginOption[] = [ react(), + wasm(), + nodePolyfills({ + // Enables the 'events' module, which is required by the matrix-js-sdk + include: ['events'], + }), svgrPlugin({ svgrOptions: { // This enables ref forwarding on SVGR components, which is needed, for @@ -43,7 +50,6 @@ export default ({ ref: true, }, }), - codecovVitePlugin({ enableBundleAnalysis: process.env.CODECOV_TOKEN !== undefined, bundleName: "element-call", @@ -150,12 +156,5 @@ export default ({ "@radix-ui/react-dismissable-layer", ], }, - // Vite is using esbuild in development mode, which doesn't work with the wasm loader - // in matrix-sdk-crypto-wasm, so we need to exclude it here. This doesn't affect the - // production build (which uses rollup) which still works as expected. - // https://vite.dev/guide/why.html#why-not-bundle-with-esbuild - optimizeDeps: { - exclude: ["@matrix-org/matrix-sdk-crypto-wasm"], - }, }; }; From 2adb498620a72c73214092995436538b0211729d Mon Sep 17 00:00:00 2001 From: fkwp Date: Fri, 17 Apr 2026 18:28:02 +0200 Subject: [PATCH 523/748] prettier --- src/vitest.setup.ts | 2 +- vite.config.ts | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/vitest.setup.ts b/src/vitest.setup.ts index ca65006e2..bd06310cb 100644 --- a/src/vitest.setup.ts +++ b/src/vitest.setup.ts @@ -100,4 +100,4 @@ if ( writable: true, configurable: true, }); -} \ No newline at end of file +} diff --git a/vite.config.ts b/vite.config.ts index 5b3ab2994..801ea79aa 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -17,7 +17,7 @@ import { createHtmlPlugin } from "vite-plugin-html"; import { codecovVitePlugin } from "@codecov/vite-plugin"; import { sentryVitePlugin } from "@sentry/vite-plugin"; -import { nodePolyfills } from 'vite-plugin-node-polyfills' +import { nodePolyfills } from "vite-plugin-node-polyfills"; import wasm from "vite-plugin-wasm"; import react from "@vitejs/plugin-react"; @@ -41,7 +41,7 @@ export default ({ wasm(), nodePolyfills({ // Enables the 'events' module, which is required by the matrix-js-sdk - include: ['events'], + include: ["events"], }), svgrPlugin({ svgrOptions: { From 4d86580542ca7ee3a9b8bcf046c6343c5d6d3196 Mon Sep 17 00:00:00 2001 From: fkwp Date: Fri, 17 Apr 2026 23:03:17 +0200 Subject: [PATCH 524/748] pin lk-jwt-service to delegation PR --- dev-backend-docker-compose.yml | 4 ++-- scripts/playwright-webserver-command.sh | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/dev-backend-docker-compose.yml b/dev-backend-docker-compose.yml index 2514d069e..c2191db7f 100644 --- a/dev-backend-docker-compose.yml +++ b/dev-backend-docker-compose.yml @@ -3,7 +3,7 @@ networks: services: auth-service: - image: ghcr.io/element-hq/lk-jwt-service:sha-f8ddd00 + image: ghcr.io/element-hq/lk-jwt-service:pr_171 pull_policy: always hostname: auth-server environment: @@ -25,7 +25,7 @@ services: - ecbackend auth-service-1: - image: ghcr.io/element-hq/lk-jwt-service:sha-f8ddd00 + image: ghcr.io/element-hq/lk-jwt-service:pr_171 pull_policy: always hostname: auth-server-1 environment: diff --git a/scripts/playwright-webserver-command.sh b/scripts/playwright-webserver-command.sh index 8cea50e34..70726f453 100755 --- a/scripts/playwright-webserver-command.sh +++ b/scripts/playwright-webserver-command.sh @@ -6,5 +6,5 @@ if [ -n "$USE_DOCKER" ]; then exec docker run --rm --name element-call-testing -p 8080:8080 -v ./config/config.devenv.json:/app/config.json:ro,Z element-call:testing else cp config/config.devenv.json public/config.json - exec pnpm dev + exec pnpm dev --host fi From 66cea929a76de7479c8f15a9b8474000717cf8ba Mon Sep 17 00:00:00 2001 From: Timo K Date: Mon, 20 Apr 2026 16:59:34 +0200 Subject: [PATCH 525/748] Add back our custom linking plugins to pnpm --- .githooks/post-commit | 9 ++++--- .githooks/pre-commit | 11 ++++---- .gitignore | 5 ++++ .pnpmfile.cjs | 58 +++++++++++++++++++++++++++++++++++++++++++ docs/linking.md | 24 ++++++++++-------- package.json | 4 +-- pnpm-lock.yaml | 18 ++++++++------ 7 files changed, 100 insertions(+), 29 deletions(-) create mode 100644 .pnpmfile.cjs diff --git a/.githooks/post-commit b/.githooks/post-commit index 467799bd8..9054c0e13 100755 --- a/.githooks/post-commit +++ b/.githooks/post-commit @@ -1,11 +1,12 @@ #!/usr/bin/sh -FILE=.links.temp-disabled.yaml -if test -f "$FILE"; then +FILE=.links.cjs +FILE_DIS=.links.temp-disabled.cjs +if test -f "$FILE_DIS"; then # Only do the post-commit hook if the file was temp-disabled by the pre-commit hook. # Otherwise linking was actively (`yarn links:disable`) disabled and this hook should noop. - mv .links.temp-disabled.yaml .links.yaml + mv $FILE_DIS $FILE yarnLog=$(yarn) - echo "[yarn-linker] The post-commit hook has re-enabled .links.yaml." + echo "[yarn-linker] The post-commit hook has re-enabled $FILE" exit 1 fi diff --git a/.githooks/pre-commit b/.githooks/pre-commit index 435d75f13..6d8d26b01 100755 --- a/.githooks/pre-commit +++ b/.githooks/pre-commit @@ -1,11 +1,12 @@ #!/usr/bin/sh -FILE=".links.yaml" +FILE=.links.cjs +FILE_DIS=.links.temp-disabled.cjs if test -f "$FILE"; then - mv .links.yaml .links.temp-disabled.yaml + mv $FILE .links.temp-disabled.cjs # echo "running yarn" - x=$(yarn) - y=$(git add yarn.lock) - echo "[yarn-linker] The pre-commit hook has disabled .links.yaml and MODIFIED the yarn.lock file. Review the staged changes (the hook added yarn.lock, was this desired?) and run \`git commit \` again if they look okay. The post-commit hook will re-enable your links." + x=$(pnpm install) + y=$(git add pnpm-lock.yaml) + echo "[yarn-linker] The pre-commit hook has disabled $FILE and MODIFIED the pnpm-lock.yaml file. Review the staged changes (the hook added pnpm-lock.yaml, was this desired?) and run \`git commit \` again if they look okay. The post-commit hook will re-enable your links." exit 1 fi diff --git a/.gitignore b/.gitignore index 2b6fab8eb..e9225072d 100644 --- a/.gitignore +++ b/.gitignore @@ -21,9 +21,14 @@ yarn-error.log !/.yarn/releases !/.yarn/sdks !/.yarn/versions +# old yarn based linking /.links.yaml /.links.disabled.yaml /.links.temp-disabled.yaml +# pnpm based linking +/.links.cjs +/.links.disabled.cjs +/.links.temp-disabled.cjs # Playwright /test-results/ diff --git a/.pnpmfile.cjs b/.pnpmfile.cjs new file mode 100644 index 000000000..f5759c260 --- /dev/null +++ b/.pnpmfile.cjs @@ -0,0 +1,58 @@ +/* +Copyright 2026 Element Creations Ltd. + +SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial +Please see LICENSE in the repository root for full details. +*/ + +// Created based on https://github.com/element-hq/element-call/blob/60fae70a60e3697eb41210ccf1e400cab37df7c8/.yarn/plugins/linker.cjs +// and the following prompt history: +// - Can you convert this yarn plugin into a pnpm plugin. +// - The goal is to not have modifications to the package.json and lock files so that we do not track links on gh. +// This seems to modify the package.json file. +// What can we do with pnpm to have the link inforamtion in a seperate file +// - why do you cache the loaded links. When does this file get executed? +// Do we need this optimization. +// How do we guarantee, that we aleays use the most recent content from the links file? +// +// Manual transition to cjs. Claude proposed manual yaml parsing. + +const fs = require("fs"); +const path = require("path"); + +function loadLinks() { + try { + return require(path.join(__dirname, ".links.cjs")); + } catch (e) { + return null; + } +} + +function readPackage(pkg, context) { + const links = loadLinks(); + if (!links) return pkg; + + const manifest = JSON.parse( + fs.readFileSync(path.join(__dirname, "package.json"), "utf8"), + ); + if (pkg.name !== manifest.name) return pkg; + + for (const [name, linkPath] of Object.entries(links)) { + const resolved = `link:${path.resolve(__dirname, linkPath)}`; + if (pkg.dependencies && pkg.dependencies[name]) { + context.log(`Linking ${name} -> ${resolved}`); + pkg.dependencies[name] = resolved; + } else if (pkg.devDependencies && pkg.devDependencies[name]) { + context.log(`Linking ${name} -> ${resolved}`); + pkg.devDependencies[name] = resolved; + } + } + + return pkg; +} + +module.exports = { + hooks: { + readPackage, + }, +}; diff --git a/docs/linking.md b/docs/linking.md index 0abbc73ec..689a6f025 100644 --- a/docs/linking.md +++ b/docs/linking.md @@ -1,30 +1,34 @@ # Developing with linked packages -If you want to make changes to a package that Element Call depends on and see those changes applied in real time, you can create a link to a local copy of the package. Yarn has a command for this (`yarn link`), but it's not recommended to use it as it ends up modifying package.json with details specific to your development environment. +If you want to make changes to a package that Element Call depends on and see those changes applied in real time, you can create a link to a local copy of the package. Pnpm has a command for this (`pnpm link`), but it's not recommended to use it as it ends up modifying package.json with details specific to your development environment. -Instead, you can use our little 'linker' plugin. Create a file named `.links.yaml` in the Element Call project directory, listing the names and paths of any dependencies you want to link. For example: +Instead, you can use our little 'linker' plugin. Create a file named `.links.cjs` in the Element Call project directory, listing the names and paths of any dependencies you want to link. For example: -```yaml -matrix-js-sdk: ../path/to/matrix-js-sdk -"@vector-im/compound-web": /home/alice/path/to/compound-web +```cjs +// Packages to link to local checkouts +module.exports = { + "matrix-js-sdk": "../your/path/matrix-js-sdk", + "matrix-widget-api": "../your/path/matrix-widget-api", +}; ``` -Then run `yarn install`. +Then run `pnpm install`. ## Hooks -Changes in `.links.yaml` will also update `yarn.lock` when `yarn` is executed. The lockfile will then contain the local +Changes in `.links.yaml` will also update `pnpm-lock.yaml` when `pnpm` is executed. The lockfile will then contain the local version of the package which would not work on others dev setups or the github CI. + One always needs to run: ```bash -mv .links.yaml .links.disabled.yaml +mv .links.cjs .links.disabled.cjs yarn ``` before committing a change. -To make it more convenient to work with this linking system we added git hooks for your conviniece. +To make it more convenient to work with this linking system we added git hooks. A `pre-commit` hook will run `mv .links.yaml .links.disabled.yaml`, `yarn` and `git add yarn.lock` if it detects a `.links.yaml` file and abort the commit. You will than need to check if the resulting changes are appropriate and commit again. @@ -35,5 +39,5 @@ before if a `.links.disabled.yaml` is present. It runs `mv .links.disabled.yaml To activate the hooks automatically configure git with ```bash -git config --local core.hooksPath .githooks/ +git config --local core.hooksPath .githooks ``` diff --git a/package.json b/package.json index 65c0f4690..c0f4d505e 100644 --- a/package.json +++ b/package.json @@ -32,8 +32,8 @@ "backend-playwright": "docker-compose -f playwright-backend-docker-compose.yml -f playwright-backend-docker-compose.override.yml up", "test:playwright": "playwright test", "test:playwright:open": "pnpm test:playwright --ui", - "links:enable": "mv .links.disabled.yaml .links.yaml & touch .links.yaml", - "links:disable": "mv .links.yaml .links.disabled.yaml", + "links:enable": "mv .links.disabled.cjs .links.cjs & touch .links.cjs", + "links:disable": "mv .links.cjs .links.disabled.cjs", "storybook": "storybook dev -p 6006", "build-storybook": "storybook build" }, diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 01c59c965..c800b0c20 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -14,6 +14,8 @@ overrides: js-yaml: ^4.1.1 esbuild: ^0.27.7 +pnpmfileChecksum: rxqlpiscahzxqq6bf4el6c6jvu + importers: .: @@ -236,7 +238,7 @@ importers: version: 1.9.2 matrix-js-sdk: specifier: matrix-org/matrix-js-sdk#develop - version: https://codeload.github.com/matrix-org/matrix-js-sdk/tar.gz/fd01b172368e0ac5479d4830f92ad261a7eccc6c + version: https://codeload.github.com/matrix-org/matrix-js-sdk/tar.gz/668183d7226ccb4819788018fb48e9a58f85a45b matrix-widget-api: specifier: ^1.16.1 version: 1.17.0 @@ -1576,8 +1578,8 @@ packages: '@types/dom-mediacapture-transform': ^0.1.9 livekit-client: ^1.12.0 || ^2.1.0 - '@matrix-org/matrix-sdk-crypto-wasm@18.0.0': - resolution: {integrity: sha512-88+n+dvxLI1cjS10UIlKXVYK7TGWbpAnnaDC9fow7ch/hCvdu3dFhJ3tS3/13N9s9+1QFXB4FFuommj+tHJPhQ==} + '@matrix-org/matrix-sdk-crypto-wasm@18.1.0': + resolution: {integrity: sha512-GxXK2U39+2qWNvR3fXJY7nxdikvpiT17RaS0/Dktk6R8FMKDk3vm79Hq65yrCWLBmT7pJZoerfILNZqhrcUHrg==} engines: {node: '>= 18'} '@mdx-js/react@3.1.1': @@ -4974,8 +4976,8 @@ packages: matrix-events-sdk@0.0.1: resolution: {integrity: sha512-1QEOsXO+bhyCroIe2/A5OwaxHvBm7EsSQ46DEDn8RBIfQwN5HWBpFvyWWR4QY0KHPPnnJdI99wgRiAl7Ad5qaA==} - matrix-js-sdk@https://codeload.github.com/matrix-org/matrix-js-sdk/tar.gz/fd01b172368e0ac5479d4830f92ad261a7eccc6c: - resolution: {tarball: https://codeload.github.com/matrix-org/matrix-js-sdk/tar.gz/fd01b172368e0ac5479d4830f92ad261a7eccc6c} + matrix-js-sdk@https://codeload.github.com/matrix-org/matrix-js-sdk/tar.gz/668183d7226ccb4819788018fb48e9a58f85a45b: + resolution: {tarball: https://codeload.github.com/matrix-org/matrix-js-sdk/tar.gz/668183d7226ccb4819788018fb48e9a58f85a45b} version: 41.3.0 engines: {node: '>=22.0.0'} @@ -8110,7 +8112,7 @@ snapshots: '@types/dom-mediacapture-transform': 0.1.11 livekit-client: 2.18.3(@types/dom-mediacapture-record@1.0.22) - '@matrix-org/matrix-sdk-crypto-wasm@18.0.0': {} + '@matrix-org/matrix-sdk-crypto-wasm@18.1.0': {} '@mdx-js/react@3.1.1(@types/react@19.2.14)(react@19.2.5)': dependencies: @@ -11749,10 +11751,10 @@ snapshots: matrix-events-sdk@0.0.1: {} - matrix-js-sdk@https://codeload.github.com/matrix-org/matrix-js-sdk/tar.gz/fd01b172368e0ac5479d4830f92ad261a7eccc6c: + matrix-js-sdk@https://codeload.github.com/matrix-org/matrix-js-sdk/tar.gz/668183d7226ccb4819788018fb48e9a58f85a45b: dependencies: '@babel/runtime': 7.29.2 - '@matrix-org/matrix-sdk-crypto-wasm': 18.0.0 + '@matrix-org/matrix-sdk-crypto-wasm': 18.1.0 another-json: 0.2.0 bs58: 6.0.0 content-type: 1.0.5 From 1f443cf739a228bbb81da8da87f7d3d22c6144db Mon Sep 17 00:00:00 2001 From: Timo K Date: Mon, 20 Apr 2026 17:12:56 +0200 Subject: [PATCH 526/748] bump jwt for dev backend back to proper release (v0.4.4) --- dev-backend-docker-compose.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dev-backend-docker-compose.yml b/dev-backend-docker-compose.yml index c2191db7f..a8619834f 100644 --- a/dev-backend-docker-compose.yml +++ b/dev-backend-docker-compose.yml @@ -25,7 +25,7 @@ services: - ecbackend auth-service-1: - image: ghcr.io/element-hq/lk-jwt-service:pr_171 + image: ghcr.io/element-hq/lk-jwt-service:0.4.4 pull_policy: always hostname: auth-server-1 environment: From ff6112826c2182f475da394045cd9f1a56001859 Mon Sep 17 00:00:00 2001 From: Timo K Date: Mon, 20 Apr 2026 18:02:53 +0200 Subject: [PATCH 527/748] missed version bump --- dev-backend-docker-compose.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dev-backend-docker-compose.yml b/dev-backend-docker-compose.yml index a8619834f..36fc7f44b 100644 --- a/dev-backend-docker-compose.yml +++ b/dev-backend-docker-compose.yml @@ -3,7 +3,7 @@ networks: services: auth-service: - image: ghcr.io/element-hq/lk-jwt-service:pr_171 + image: ghcr.io/element-hq/lk-jwt-service:0.4.4 pull_policy: always hostname: auth-server environment: From 4d09651fe1e4add2ed8516d9aba54582f289c76c Mon Sep 17 00:00:00 2001 From: Timo K Date: Tue, 21 Apr 2026 10:00:36 +0200 Subject: [PATCH 528/748] Bump pnpm to v10 --- package.json | 2 +- pnpm-lock.yaml | 20 ++++++++++---------- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/package.json b/package.json index c0f4d505e..867822c91 100644 --- a/package.json +++ b/package.json @@ -156,5 +156,5 @@ "esbuild": "^0.27.7" } }, - "packageManager": "pnpm@9.0.0" + "packageManager": "pnpm@10.0.0" } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index c800b0c20..7bbc1dcb8 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -14,7 +14,7 @@ overrides: js-yaml: ^4.1.1 esbuild: ^0.27.7 -pnpmfileChecksum: rxqlpiscahzxqq6bf4el6c6jvu +pnpmfileChecksum: sha256-toM8G/xDIU9KCsLzvrWKlNM+7K7S70ZB0m5kCeEztjs= importers: @@ -190,7 +190,7 @@ importers: version: 6.10.2(eslint@8.57.1) eslint-plugin-matrix-org: specifier: 2.1.0 - version: 2.1.0(@babel/core@7.29.0)(@babel/eslint-parser@7.28.6(@babel/core@7.29.0)(eslint@8.57.1))(@babel/eslint-plugin@7.27.1(@babel/eslint-parser@7.28.6(@babel/core@7.29.0)(eslint@8.57.1))(eslint@8.57.1))(@stylistic/eslint-plugin@3.1.0(eslint@8.57.1)(typescript@5.9.3))(@typescript-eslint/eslint-plugin@8.58.2(@typescript-eslint/parser@8.58.2(eslint@8.57.1)(typescript@5.9.3))(eslint@8.57.1)(typescript@5.9.3))(@typescript-eslint/parser@8.58.2(eslint@8.57.1)(typescript@5.9.3))(eslint-config-google@0.14.0(eslint@8.57.1))(eslint-config-prettier@10.1.8(eslint@8.57.1))(eslint-plugin-deprecate@0.9.0(eslint@8.57.1))(eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.58.2(eslint@8.57.1)(typescript@5.9.3))(eslint@8.57.1))(eslint-plugin-jest@29.15.2(@typescript-eslint/eslint-plugin@8.58.2(@typescript-eslint/parser@8.58.2(eslint@8.57.1)(typescript@5.9.3))(eslint@8.57.1)(typescript@5.9.3))(eslint@8.57.1)(typescript@5.9.3))(eslint-plugin-jsx-a11y@6.10.2(eslint@8.57.1))(eslint-plugin-react-hooks@5.2.0(eslint@8.57.1))(eslint-plugin-react@7.37.5(eslint@8.57.1))(eslint-plugin-unicorn@56.0.1(eslint@8.57.1))(eslint@8.57.1)(prettier@3.8.3)(typescript@5.9.3) + version: 2.1.0(09e41ec1b738154136ea8b36e5821317) eslint-plugin-react: specifier: ^7.29.4 version: 7.37.5(eslint@8.57.1) @@ -238,7 +238,7 @@ importers: version: 1.9.2 matrix-js-sdk: specifier: matrix-org/matrix-js-sdk#develop - version: https://codeload.github.com/matrix-org/matrix-js-sdk/tar.gz/668183d7226ccb4819788018fb48e9a58f85a45b + version: https://codeload.github.com/matrix-org/matrix-js-sdk/tar.gz/4ee3e591bf6498eecc1a92aad92b2ff3fc604fb8 matrix-widget-api: specifier: ^1.16.1 version: 1.17.0 @@ -334,7 +334,7 @@ importers: version: 4.1.4(@types/node@24.12.2)(@vitest/coverage-v8@4.1.4)(jsdom@26.1.0)(vite@8.0.8(@types/node@24.12.2)(esbuild@0.27.7)(jiti@2.6.1)(sass@1.99.0)(terser@5.46.1)(yaml@2.8.3)) vitest-axe: specifier: ^1.0.0-pre.3 - version: 1.0.0-pre.5(vitest@4.1.4(@types/node@24.12.2)(@vitest/coverage-v8@4.1.4)(jsdom@26.1.0)(vite@8.0.8(@types/node@24.12.2)(esbuild@0.27.7)(jiti@2.6.1)(sass@1.99.0)(terser@5.46.1)(yaml@2.8.3))) + version: 1.0.0-pre.5(vitest@4.1.4) packages: @@ -4976,8 +4976,8 @@ packages: matrix-events-sdk@0.0.1: resolution: {integrity: sha512-1QEOsXO+bhyCroIe2/A5OwaxHvBm7EsSQ46DEDn8RBIfQwN5HWBpFvyWWR4QY0KHPPnnJdI99wgRiAl7Ad5qaA==} - matrix-js-sdk@https://codeload.github.com/matrix-org/matrix-js-sdk/tar.gz/668183d7226ccb4819788018fb48e9a58f85a45b: - resolution: {tarball: https://codeload.github.com/matrix-org/matrix-js-sdk/tar.gz/668183d7226ccb4819788018fb48e9a58f85a45b} + matrix-js-sdk@https://codeload.github.com/matrix-org/matrix-js-sdk/tar.gz/4ee3e591bf6498eecc1a92aad92b2ff3fc604fb8: + resolution: {tarball: https://codeload.github.com/matrix-org/matrix-js-sdk/tar.gz/4ee3e591bf6498eecc1a92aad92b2ff3fc604fb8} version: 41.3.0 engines: {node: '>=22.0.0'} @@ -10664,8 +10664,8 @@ snapshots: safe-regex-test: 1.1.0 string.prototype.includes: 2.0.1 - ? eslint-plugin-matrix-org@2.1.0(@babel/core@7.29.0)(@babel/eslint-parser@7.28.6(@babel/core@7.29.0)(eslint@8.57.1))(@babel/eslint-plugin@7.27.1(@babel/eslint-parser@7.28.6(@babel/core@7.29.0)(eslint@8.57.1))(eslint@8.57.1))(@stylistic/eslint-plugin@3.1.0(eslint@8.57.1)(typescript@5.9.3))(@typescript-eslint/eslint-plugin@8.58.2(@typescript-eslint/parser@8.58.2(eslint@8.57.1)(typescript@5.9.3))(eslint@8.57.1)(typescript@5.9.3))(@typescript-eslint/parser@8.58.2(eslint@8.57.1)(typescript@5.9.3))(eslint-config-google@0.14.0(eslint@8.57.1))(eslint-config-prettier@10.1.8(eslint@8.57.1))(eslint-plugin-deprecate@0.9.0(eslint@8.57.1))(eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.58.2(eslint@8.57.1)(typescript@5.9.3))(eslint@8.57.1))(eslint-plugin-jest@29.15.2(@typescript-eslint/eslint-plugin@8.58.2(@typescript-eslint/parser@8.58.2(eslint@8.57.1)(typescript@5.9.3))(eslint@8.57.1)(typescript@5.9.3))(eslint@8.57.1)(typescript@5.9.3))(eslint-plugin-jsx-a11y@6.10.2(eslint@8.57.1))(eslint-plugin-react-hooks@5.2.0(eslint@8.57.1))(eslint-plugin-react@7.37.5(eslint@8.57.1))(eslint-plugin-unicorn@56.0.1(eslint@8.57.1))(eslint@8.57.1)(prettier@3.8.3)(typescript@5.9.3) - : dependencies: + eslint-plugin-matrix-org@2.1.0(09e41ec1b738154136ea8b36e5821317): + dependencies: '@babel/core': 7.29.0 '@babel/eslint-parser': 7.28.6(@babel/core@7.29.0)(eslint@8.57.1) '@babel/eslint-plugin': 7.27.1(@babel/eslint-parser@7.28.6(@babel/core@7.29.0)(eslint@8.57.1))(eslint@8.57.1) @@ -11751,7 +11751,7 @@ snapshots: matrix-events-sdk@0.0.1: {} - matrix-js-sdk@https://codeload.github.com/matrix-org/matrix-js-sdk/tar.gz/668183d7226ccb4819788018fb48e9a58f85a45b: + matrix-js-sdk@https://codeload.github.com/matrix-org/matrix-js-sdk/tar.gz/4ee3e591bf6498eecc1a92aad92b2ff3fc604fb8: dependencies: '@babel/runtime': 7.29.2 '@matrix-org/matrix-sdk-crypto-wasm': 18.1.0 @@ -13542,7 +13542,7 @@ snapshots: terser: 5.46.1 yaml: 2.8.3 - vitest-axe@1.0.0-pre.5(vitest@4.1.4(@types/node@24.12.2)(@vitest/coverage-v8@4.1.4)(jsdom@26.1.0)(vite@8.0.8(@types/node@24.12.2)(esbuild@0.27.7)(jiti@2.6.1)(sass@1.99.0)(terser@5.46.1)(yaml@2.8.3))): + vitest-axe@1.0.0-pre.5(vitest@4.1.4): dependencies: '@vitest/pretty-format': 3.2.4 axe-core: 4.11.3 From 00d6e034a08ca6bcb0e66c195f72498ad84b9ad9 Mon Sep 17 00:00:00 2001 From: Timo K Date: Tue, 21 Apr 2026 10:53:56 +0200 Subject: [PATCH 529/748] fixup some missing yarn -> pnpm transitions --- .githooks/post-commit | 5 ++--- .githooks/pre-commit | 3 +-- README.md | 14 +++++++------- WIDGET_TEST.md | 4 ++-- backend/dev_nginx.conf | 20 ++++++++++---------- docs/linking.md | 6 +++--- docs/self-hosting.md | 4 ++-- embedded/android/publish_android_package.sh | 8 ++++---- knip.ts | 8 +------- renovate.json | 4 ++-- sdk/README.md | 4 ++-- sdk/main.ts | 2 +- src/livekit/BlurBackgroundTransformer.ts | 2 +- 13 files changed, 38 insertions(+), 46 deletions(-) diff --git a/.githooks/post-commit b/.githooks/post-commit index 9054c0e13..243b4f511 100755 --- a/.githooks/post-commit +++ b/.githooks/post-commit @@ -4,9 +4,8 @@ FILE=.links.cjs FILE_DIS=.links.temp-disabled.cjs if test -f "$FILE_DIS"; then # Only do the post-commit hook if the file was temp-disabled by the pre-commit hook. - # Otherwise linking was actively (`yarn links:disable`) disabled and this hook should noop. + # Otherwise linking was actively (`pnpm links:disable`) disabled and this hook should noop. mv $FILE_DIS $FILE - yarnLog=$(yarn) - echo "[yarn-linker] The post-commit hook has re-enabled $FILE" + echo "[pnpm-linker] The post-commit hook has re-enabled $FILE" exit 1 fi diff --git a/.githooks/pre-commit b/.githooks/pre-commit index 6d8d26b01..f8ecfe4d6 100755 --- a/.githooks/pre-commit +++ b/.githooks/pre-commit @@ -4,9 +4,8 @@ FILE=.links.cjs FILE_DIS=.links.temp-disabled.cjs if test -f "$FILE"; then mv $FILE .links.temp-disabled.cjs - # echo "running yarn" x=$(pnpm install) y=$(git add pnpm-lock.yaml) - echo "[yarn-linker] The pre-commit hook has disabled $FILE and MODIFIED the pnpm-lock.yaml file. Review the staged changes (the hook added pnpm-lock.yaml, was this desired?) and run \`git commit \` again if they look okay. The post-commit hook will re-enable your links." + echo "[pnpm-linker] The pre-commit hook has disabled $FILE and MODIFIED the pnpm-lock.yaml file. Review the staged changes (the hook added pnpm-lock.yaml, was this desired?) and run \`git commit \` again if they look okay. The post-commit hook will re-enable your links." exit 1 fi diff --git a/README.md b/README.md index 688a7a7f8..3685e5231 100644 --- a/README.md +++ b/README.md @@ -186,7 +186,7 @@ To get started clone and set up this project: git clone https://github.com/element-hq/element-call.git cd element-call corepack enable -yarn +pnpm install ``` To use it, create a local config by, e.g., @@ -197,7 +197,7 @@ environment as outlined in the next section out of box. You're now ready to launch the development server: ```sh -yarn dev +pnpm dev ``` See also: @@ -230,7 +230,7 @@ only for local development and **_never be exposed to the public Internet._** Run backend components: ```sh -yarn backend +pnpm backend # or for podman-compose # podman-compose -f dev-backend-docker-compose.yml up ``` @@ -260,13 +260,13 @@ on https://localhost:3000 (this is configured in `playwright.config.ts`) - this is what will be tested. The local backend environment should be running for the test to work: -`yarn backend` +`pnpm backend` There are a few different ways to run the tests yourself. The simplest is to run: ```shell -yarn run test:playwright +pnpm run test:playwright ``` This will run the Playwright tests once, non-interactively. @@ -274,7 +274,7 @@ This will run the Playwright tests once, non-interactively. There is a more user-friendly way to run the tests in interactive mode: ```shell -yarn run test:playwright:open +pnpm run test:playwright:open ``` The easiest way to develop new test is to use the codegen feature of Playwright: @@ -316,7 +316,7 @@ To add a new translation key you can do these steps: 1. Add the new key entry to the code where the new key is used: `t("some_new_key")` -1. Run `yarn i18n` to extract the new key and update the translation files. This +1. Run `pnpm i18n` to extract the new key and update the translation files. This will add a skeleton entry to the `locales/en/app.json` file: ```jsonc diff --git a/WIDGET_TEST.md b/WIDGET_TEST.md index 53e26a29d..fbad026a4 100644 --- a/WIDGET_TEST.md +++ b/WIDGET_TEST.md @@ -1,6 +1,6 @@ # Testing Element-Call in widget mode -When running `yarn backend` the latest element-web develop will be deployed and served on `http://localhost:8081`. +When running `pnpm backend` the latest element-web develop will be deployed and served on `http://localhost:8081`. In a development environment, you might prefer to just use the `element-web` repo directly, but this setup is useful for CI/CD testing. ## Setup @@ -18,7 +18,7 @@ that uses It is part of the existing backend setup. To start the backend, run: ```sh -yarn backend +pnpm backend ``` Then open `http://localhost:8081` in your browser. diff --git a/backend/dev_nginx.conf b/backend/dev_nginx.conf index d3ddbc531..bfd79fa28 100644 --- a/backend/dev_nginx.conf +++ b/backend/dev_nginx.conf @@ -28,11 +28,11 @@ server { # Reason: the lk-jwt-service uses the federation API for the openid token # verification, which requires TLS location ~ ^(/_matrix|/_synapse/client) { - proxy_pass "http://homeserver:8008"; + proxy_pass "http://homeserver:8008"; proxy_http_version 1.1; proxy_set_header X-Forwarded-For $remote_addr; proxy_set_header X-Forwarded-Proto $scheme; - proxy_set_header Host $host; + proxy_set_header Host $host; } error_page 500 502 503 504 /50x.html; @@ -73,7 +73,7 @@ server { proxy_http_version 1.1; proxy_set_header X-Forwarded-For $remote_addr; proxy_set_header X-Forwarded-Proto $scheme; - proxy_set_header Host $host; + proxy_set_header Host $host; } error_page 500 502 503 504 /50x.html; @@ -108,7 +108,7 @@ server { # JWT Service running at port 6080 proxy_pass http://jwt-auth-services/; - + } location ^~ /livekit/sfu/ { @@ -128,7 +128,7 @@ server { # LiveKit SFU websocket connection running at port 7880 proxy_pass http://livekit-sfu:7880/; } - + error_page 500 502 503 504 /50x.html; } @@ -156,7 +156,7 @@ server { # JWT Service running at port 16080 proxy_pass http://auth-service-1:16080/; - + } location ^~ /livekit/sfu/ { @@ -176,14 +176,14 @@ server { # LiveKit SFU websocket connection running at port 17880 proxy_pass http://livekit-sfu-1:17880/; } - + error_page 500 502 503 504 /50x.html; } # Convenience reverse proxy for the call.m.localhost domain to element call # running on the host either via -# - yarn dev --host or +# - pnpm dev --host or # - falling back to http (the element call docker container) server { listen 80; @@ -260,7 +260,7 @@ server { proxy_ssl_verify off; } - + error_page 500 502 503 504 /50x.html; } @@ -293,7 +293,7 @@ server { proxy_ssl_verify off; } - + error_page 500 502 503 504 /50x.html; } diff --git a/docs/linking.md b/docs/linking.md index 689a6f025..4ac6abf7e 100644 --- a/docs/linking.md +++ b/docs/linking.md @@ -23,18 +23,18 @@ One always needs to run: ```bash mv .links.cjs .links.disabled.cjs -yarn +pnpm install ``` before committing a change. To make it more convenient to work with this linking system we added git hooks. -A `pre-commit` hook will run `mv .links.yaml .links.disabled.yaml`, `yarn` and `git add yarn.lock` if it detects +A `pre-commit` hook will run `mv .links.yaml .links.disabled.yaml`, `pnpm install` and `git add yarn.lock` if it detects a `.links.yaml` file and abort the commit. You will than need to check if the resulting changes are appropriate and commit again. A `post-commit` hook will setup the linking as it was -before if a `.links.disabled.yaml` is present. It runs `mv .links.disabled.yaml .links.yaml` and `yarn`. +before if a `.links.disabled.cjs` is present. It runs `mv .links.disabled.cjs .links.cjs` and `pnpm install`. To activate the hooks automatically configure git with diff --git a/docs/self-hosting.md b/docs/self-hosting.md index d6d464217..dc1dd6873 100644 --- a/docs/self-hosting.md +++ b/docs/self-hosting.md @@ -237,8 +237,8 @@ source. First, clone and install the package: git clone https://github.com/element-hq/element-call.git cd element-call corepack enable -yarn -yarn build +pnpm install +pnpm build ``` If all went well, you can now find the build output under `dist` as a series of diff --git a/embedded/android/publish_android_package.sh b/embedded/android/publish_android_package.sh index 8c310c9ba..316933179 100755 --- a/embedded/android/publish_android_package.sh +++ b/embedded/android/publish_android_package.sh @@ -11,7 +11,7 @@ pushd $CURRENT_DIR > /dev/null function build_assets() { echo "Generating Element Call assets..." pushd ../.. > /dev/null - yarn build + pnpm build popd > /dev/null } @@ -26,7 +26,7 @@ function copy_assets() { } getopts :sh opt -case $opt in +case $opt in s) SKIP=1 ;; @@ -41,7 +41,7 @@ if [ ! $SKIP ]; then echo "" if [[ $REPLY =~ ^[Yy]$ ]]; then build_assets - else + else echo "Using existing assets from ../../dist" fi copy_assets @@ -56,4 +56,4 @@ echo "Publishing the Android project" ./gradlew publishAndReleaseToMavenCentral --no-daemon -popd > /dev/null \ No newline at end of file +popd > /dev/null diff --git a/knip.ts b/knip.ts index 3be3e6539..aa6aee796 100644 --- a/knip.ts +++ b/knip.ts @@ -30,16 +30,10 @@ export default { "@types/content-type", "@types/sdp-transform", "@types/uuid", - // We obviously use this, but if the package has been linked with yarn link, + // We obviously use this, but if the package has been linked with pnpm link, // then Knip will flag it as a false positive // https://github.com/webpro-nl/knip/issues/766 "@vector-im/compound-web", - // Yarn plugins are allowed to depend on packages provided by the Yarn - // runtime. These shouldn't be listed in package.json, because plugins - // should work before Yarn even installs dependencies for the first time. - // https://yarnpkg.com/advanced/plugin-tutorial#what-does-a-plugin-look-like - "@yarnpkg/core", - "@yarnpkg/parsers", "matrix-widget-api", ], ignoreExportsUsedInFile: true, diff --git a/renovate.json b/renovate.json index 612e6674e..39fbf0c16 100644 --- a/renovate.json +++ b/renovate.json @@ -54,8 +54,8 @@ "matchFileNames": ["embedded/**/*"] }, { - "groupName": "Yarn", - "matchDepNames": ["yarn"] + "groupName": "Pnpm", + "matchDepNames": ["pnpm"] } ], "semanticCommits": "disabled", diff --git a/sdk/README.md b/sdk/README.md index ad8ff97eb..7102ba29c 100644 --- a/sdk/README.md +++ b/sdk/README.md @@ -13,8 +13,8 @@ This folder contains an example index.html file that showcases the sdk in use (h To get started run ``` -yarn -yarn build:sdk +pnpm install +pnpm build:sdk ``` in the repository root. diff --git a/sdk/main.ts b/sdk/main.ts index c65bf4a70..286c16ea2 100644 --- a/sdk/main.ts +++ b/sdk/main.ts @@ -8,7 +8,7 @@ Please see LICENSE in the repository root for full details. /** * EXPERIMENTAL * - * This file is the entrypoint for the sdk build of element call: `yarn build:sdk` + * This file is the entrypoint for the sdk build of element call: `pnpm build:sdk` * use in widgets. * It exposes the `createMatrixRTCSdk` which creates the `MatrixRTCSdk` interface (see below) that * can be used to join a rtc session and exchange realtime data. diff --git a/src/livekit/BlurBackgroundTransformer.ts b/src/livekit/BlurBackgroundTransformer.ts index c3d885bab..7bec3cc4f 100644 --- a/src/livekit/BlurBackgroundTransformer.ts +++ b/src/livekit/BlurBackgroundTransformer.ts @@ -29,7 +29,7 @@ interface WasmFileset { // MediaPipe and depend on node_modules having this specific structure. It's // easy to see this breaking if our dependencies changed and MediaPipe were // no longer hoisted, or if we switched to another dependency loader such as -// Yarn PnP. +// pnpm PnP. // https://github.com/google-ai-edge/mediapipe/issues/5961 const wasmFileset: WasmFileset = { wasmLoaderPath: new URL( From e9fd84816ee90bf2ee60a6cc8f4e561c84477f48 Mon Sep 17 00:00:00 2001 From: Robin Date: Tue, 21 Apr 2026 11:17:57 +0200 Subject: [PATCH 530/748] Invert the colors of the camera and microphone buttons again Turns out design prefers the button colors how they were prior to fa844446b6a745731ceb20178314bf8ba0b0ca41. --- src/button/Button.tsx | 4 ++-- src/room/__snapshots__/InCallView.test.tsx.snap | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/button/Button.tsx b/src/button/Button.tsx index 73938794e..8a22668e4 100644 --- a/src/button/Button.tsx +++ b/src/button/Button.tsx @@ -47,7 +47,7 @@ export const MicButton: FC = ({ enabled, ...props }) => { = ({ enabled, ...props }) => { rendering > renders 1`] = ` aria-disabled="true" aria-labelledby="_r_i_" class="_button_13vu4_8 _has-icon_13vu4_60 _icon-only_13vu4_53" - data-kind="secondary" + data-kind="primary" data-size="lg" data-testid="incall_mute" role="switch" @@ -354,7 +354,7 @@ exports[`InCallView > rendering > renders 1`] = ` aria-disabled="true" aria-labelledby="_r_n_" class="_button_13vu4_8 _has-icon_13vu4_60 _icon-only_13vu4_53" - data-kind="secondary" + data-kind="primary" data-size="lg" data-testid="incall_videomute" role="switch" From 84ed5943eab25ef6ef45448759ee23bc29556e1c Mon Sep 17 00:00:00 2001 From: Valere Date: Tue, 21 Apr 2026 11:55:03 +0200 Subject: [PATCH 531/748] fix: using vars. instead of secrets. for NETLIFY_SITE_ID --- .github/workflows/test-netlify.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test-netlify.yaml b/.github/workflows/test-netlify.yaml index 959f7af0c..bccde4450 100644 --- a/.github/workflows/test-netlify.yaml +++ b/.github/workflows/test-netlify.yaml @@ -42,7 +42,7 @@ jobs: branch: ${{ github.event.workflow_run.head_branch }} revision: ${{ github.event.workflow_run.head_sha }} token: ${{ secrets.NETLIFY_AUTH_TOKEN }} - site_id: ${{ vars.NETLIFY_SITE_ID }} + site_id: ${{ secrets.NETLIFY_SITE_ID }} desc: Playwright Report deployment_env: EndToEndTests prefix: "e2e-" From b58076f1b93bdd17ec33ac0596d11c831b832fec Mon Sep 17 00:00:00 2001 From: Timo K Date: Tue, 21 Apr 2026 15:06:06 +0200 Subject: [PATCH 532/748] remove pnpmfileChecksum and .pnpmfile.cjs --- .pnpmfile.cjs | 58 -------------------------------------------------- pnpm-lock.yaml | 2 -- 2 files changed, 60 deletions(-) delete mode 100644 .pnpmfile.cjs diff --git a/.pnpmfile.cjs b/.pnpmfile.cjs deleted file mode 100644 index f5759c260..000000000 --- a/.pnpmfile.cjs +++ /dev/null @@ -1,58 +0,0 @@ -/* -Copyright 2026 Element Creations Ltd. - -SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial -Please see LICENSE in the repository root for full details. -*/ - -// Created based on https://github.com/element-hq/element-call/blob/60fae70a60e3697eb41210ccf1e400cab37df7c8/.yarn/plugins/linker.cjs -// and the following prompt history: -// - Can you convert this yarn plugin into a pnpm plugin. -// - The goal is to not have modifications to the package.json and lock files so that we do not track links on gh. -// This seems to modify the package.json file. -// What can we do with pnpm to have the link inforamtion in a seperate file -// - why do you cache the loaded links. When does this file get executed? -// Do we need this optimization. -// How do we guarantee, that we aleays use the most recent content from the links file? -// -// Manual transition to cjs. Claude proposed manual yaml parsing. - -const fs = require("fs"); -const path = require("path"); - -function loadLinks() { - try { - return require(path.join(__dirname, ".links.cjs")); - } catch (e) { - return null; - } -} - -function readPackage(pkg, context) { - const links = loadLinks(); - if (!links) return pkg; - - const manifest = JSON.parse( - fs.readFileSync(path.join(__dirname, "package.json"), "utf8"), - ); - if (pkg.name !== manifest.name) return pkg; - - for (const [name, linkPath] of Object.entries(links)) { - const resolved = `link:${path.resolve(__dirname, linkPath)}`; - if (pkg.dependencies && pkg.dependencies[name]) { - context.log(`Linking ${name} -> ${resolved}`); - pkg.dependencies[name] = resolved; - } else if (pkg.devDependencies && pkg.devDependencies[name]) { - context.log(`Linking ${name} -> ${resolved}`); - pkg.devDependencies[name] = resolved; - } - } - - return pkg; -} - -module.exports = { - hooks: { - readPackage, - }, -}; diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 7bbc1dcb8..f75fdaa15 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -14,8 +14,6 @@ overrides: js-yaml: ^4.1.1 esbuild: ^0.27.7 -pnpmfileChecksum: sha256-toM8G/xDIU9KCsLzvrWKlNM+7K7S70ZB0m5kCeEztjs= - importers: .: From 741b82b0263ff79c98ac48a0f6ea9dbd7e8b2e95 Mon Sep 17 00:00:00 2001 From: Timo K Date: Tue, 21 Apr 2026 16:06:51 +0200 Subject: [PATCH 533/748] update linking realted logic - remove post-commit hook - remove .links.cjs enable/disable (instead just add/rm .pnpmfile.cjs) - rename pnpm links:enable -> pnpm links:on - rename pnpm links:disable -> pnpm links:off - unify doc filenames `-` -> `_` - add linking_concept_reasoning.md to provide background why the linking is how it is. --- .githooks/post-commit | 11 ---- .githooks/pre-commit | 14 ++--- README.md | 6 +- docs/README.md | 6 +- ...d-standalone.md => embedded_standalone.md} | 6 +- docs/linking.md | 45 +++++++++----- docs/linking_concept_reasoning.md | 27 ++++++++ docs/{self-hosting.md => self_hosting.md} | 0 docs/{url-params.md => url_params.md} | 14 ++--- package.json | 4 +- pnpm-lock.yaml | 8 +-- scripts/.pnpmfile.cjs | 62 +++++++++++++++++++ scripts/setup-linking.sh | 26 ++++++++ 13 files changed, 174 insertions(+), 55 deletions(-) delete mode 100755 .githooks/post-commit rename docs/{embedded-standalone.md => embedded_standalone.md} (97%) create mode 100644 docs/linking_concept_reasoning.md rename docs/{self-hosting.md => self_hosting.md} (100%) rename docs/{url-params.md => url_params.md} (97%) create mode 100644 scripts/.pnpmfile.cjs create mode 100755 scripts/setup-linking.sh diff --git a/.githooks/post-commit b/.githooks/post-commit deleted file mode 100755 index 243b4f511..000000000 --- a/.githooks/post-commit +++ /dev/null @@ -1,11 +0,0 @@ -#!/usr/bin/sh - -FILE=.links.cjs -FILE_DIS=.links.temp-disabled.cjs -if test -f "$FILE_DIS"; then - # Only do the post-commit hook if the file was temp-disabled by the pre-commit hook. - # Otherwise linking was actively (`pnpm links:disable`) disabled and this hook should noop. - mv $FILE_DIS $FILE - echo "[pnpm-linker] The post-commit hook has re-enabled $FILE" - exit 1 -fi diff --git a/.githooks/pre-commit b/.githooks/pre-commit index f8ecfe4d6..2656c9b93 100755 --- a/.githooks/pre-commit +++ b/.githooks/pre-commit @@ -1,11 +1,9 @@ -#!/usr/bin/sh +#!/usr/bin/env bash -FILE=.links.cjs -FILE_DIS=.links.temp-disabled.cjs -if test -f "$FILE"; then - mv $FILE .links.temp-disabled.cjs - x=$(pnpm install) - y=$(git add pnpm-lock.yaml) - echo "[pnpm-linker] The pre-commit hook has disabled $FILE and MODIFIED the pnpm-lock.yaml file. Review the staged changes (the hook added pnpm-lock.yaml, was this desired?) and run \`git commit \` again if they look okay. The post-commit hook will re-enable your links." +# Checks if there currently is linking configured. Informs the user to disable linking before committing. + +PNPMFILE=.pnpmfile.cjs +if test -f "$PNPMFILE"; then + echo "[pnpm-linker] The pre-commit hook detected $PNPMFILE which implies you have linked packages in your pnpm-lock.yaml. Run pnpm links:off and commit again. See also linking.md." exit 1 fi diff --git a/README.md b/README.md index 3685e5231..0c82e4b05 100644 --- a/README.md +++ b/README.md @@ -108,17 +108,17 @@ recommended method for embedding Element Call.

For more details on the packages, see the -[Embedded vs. Standalone Guide](./docs/embedded-standalone.md). +[Embedded vs. Standalone Guide](./docs/embedded_standalone.md). ## 🛠️ Self-Hosting For operating and deploying Element Call on your own server, refer to the -[**Self-Hosting Guide**](./docs/self-hosting.md). +[**Self-Hosting Guide**](./docs/self_hosting.md). ## 🧭 MatrixRTC Backend Discovery and Selection For proper Element Call operation each site deployment needs a MatrixRTC backend -setup as outlined in the [Self-Hosting](#self-hosting). A typical federated site +setup as outlined in the [Self-Hosting](#self_hosting). A typical federated site deployment for three different sites A, B and C is depicted below.

diff --git a/docs/README.md b/docs/README.md index d97e8d568..e5a5d08a3 100644 --- a/docs/README.md +++ b/docs/README.md @@ -2,8 +2,8 @@ This folder contains documentation for setup, usage, and development of Element Call. -- [Embedded vs standalone mode](./embedded-standalone.md) -- [Url format and parameters](./url-params.md) +- [Embedded vs standalone mode](./embedded_standalone.md) +- [Url format and parameters](./url_params.md) - [Global JS controls](./controls.md) -- [Self-Hosting](./self-hosting.md) +- [Self-Hosting](./self_hosting.md) - [Developing with linked packages](./linking.md) diff --git a/docs/embedded-standalone.md b/docs/embedded_standalone.md similarity index 97% rename from docs/embedded-standalone.md rename to docs/embedded_standalone.md index 440dfac0d..24ad2a7dd 100644 --- a/docs/embedded-standalone.md +++ b/docs/embedded_standalone.md @@ -14,7 +14,7 @@ The table below provides a comparison of the two packages: | **Release artifacts** | Docker Image, Tarball | Tarball, NPM for Web, Android AAR, SwiftPM for iOS | | **Recommended for** | Standalone/guest access usage | Embedding within messenger apps | | **Responsibility for regulatory compliance** | The administrator that is deploying the app is responsible for compliance with any applicable regulations (e.g. privacy) | The developer of the messenger app is responsible for compliance | -| **Analytics consent** | Element Call will show a consent UI. | Element Call will not show a consent UI. The messenger app should only provide the embedded Element Call with the [analytics URL parameters](./url-params.md#embedded-only-parameters) if consent has been granted. | +| **Analytics consent** | Element Call will show a consent UI. | Element Call will not show a consent UI. The messenger app should only provide the embedded Element Call with the [analytics URL parameters](./url_params.md#embedded-only-parameters) if consent has been granted. | | **Analytics data** | Element Call will send data to the Posthog, Sentry and Open Telemetry targets specified by the administrator in the `config.json` | Element Call will send data to the Posthog and Sentry targets specified in the URL parameters by the messenger app | ### Using the embedded package within a messenger app @@ -26,7 +26,7 @@ The basics are: 1. Add the appropriate platform dependency as given for a [release](https://github.com/element-hq/element-call/releases), or use the embedded tarball. e.g. `npm install @element-hq/element-call-embedded@0.9.0` 2. Include the assets from the platform dependency in the build process. e.g. copy the assets during a [Webpack](https://github.com/element-hq/element-web/blob/247cd8d56d832d006d7dfb919d1042529d712b59/webpack.config.js#L677-L682) build. 3. Use the `index.html` entrypointof the imported assets when you are constructing the WebView or iframe. e.g. using a [relative path in a webapp](https://github.com/element-hq/element-web/blob/247cd8d56d832d006d7dfb919d1042529d712b59/src/models/Call.ts#L680), or on the the Android [WebViewAssetLoader](https://github.com/element-hq/element-x-android/blob/fe5aab6588ecdcf9354a3bfbd9e97c1b31175a8f/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/utils/DefaultCallWidgetProvider.kt#L20) -4. Set any of the [embedded-only URL parameters](./url-params.md#embedded-only-parameters) that you need. +4. Set any of the [embedded-only URL parameters](./url_params.md#embedded-only-parameters) that you need. ## Widget vs standalone mode @@ -36,4 +36,4 @@ As a widget, the app only uses the core calling (MatrixRTC) parts. The rest (aut Element Call and the hosting client are connected via the widget API. Element Call detects that it is run as a widget if a widgetId is defined in the url parameters. If `widgetId` is present then Element Call will try to connect to the client via the widget postMessage API using the parameters provided in [Url Format and parameters -](./url-params.md). +](./url_params.md). diff --git a/docs/linking.md b/docs/linking.md index 4ac6abf7e..b9c62edf2 100644 --- a/docs/linking.md +++ b/docs/linking.md @@ -1,8 +1,25 @@ +## Quickstart guide +run +```bash +./scripts/setup-linking.sh +``` +Read the script output: +``` +Setup complete. +Update: .links.cjs to your liking +Run: 'pnpm links:on' to test your .links.cjs +Run: 'git commit' with links enabled to test the git pre-commit hook. +Run: 'pnpm links:off' to be able to commit again +Run: 'git config --local core.hooksPath ""' to allow committing with linking (not recommended) +Run: 'rm links.cjs' & 'git config --local core.hooksPath ""' to fully revert what this script did +``` + + # Developing with linked packages -If you want to make changes to a package that Element Call depends on and see those changes applied in real time, you can create a link to a local copy of the package. Pnpm has a command for this (`pnpm link`), but it's not recommended to use it as it ends up modifying package.json with details specific to your development environment. +If you want to make changes to a package that Element Call depends on and see those changes applied in real time, you can create a link to a local copy of the package. `pnpm` has a command for this (`pnpm link`), but it's not recommended to use it as it ends up modifying package.json with details specific to your development environment. -Instead, you can use our little 'linker' plugin. Create a file named `.links.cjs` in the Element Call project directory, listing the names and paths of any dependencies you want to link. For example: +Instead, create a file named `.links.cjs` in the Element Call project directory (or run `./scripts/setup-linking.sh` to create a template), listing the names and paths of any dependencies you want to link. For example: ```cjs // Packages to link to local checkouts @@ -12,32 +29,32 @@ module.exports = { }; ``` -Then run `pnpm install`. +Then run `pnpm links:on`. (this will activate the pnpm file + run `pnpm install` to setup the linking) ## Hooks -Changes in `.links.yaml` will also update `pnpm-lock.yaml` when `pnpm` is executed. The lockfile will then contain the local +Changes in `.links.cjs` will also update `pnpm-lock.yaml` when `pnpm install` is executed. The lockfile will then contain the local version of the package which would not work on others dev setups or the github CI. -One always needs to run: +One always needs to remove the pnpm `readPackage` script (the `.pnpmfile.cjs`) and run: ```bash -mv .links.cjs .links.disabled.cjs pnpm install ``` before committing a change. -To make it more convenient to work with this linking system we added git hooks. -A `pre-commit` hook will run `mv .links.yaml .links.disabled.yaml`, `pnpm install` and `git add yarn.lock` if it detects -a `.links.yaml` file and abort the commit. -You will than need to check if the resulting changes are appropriate and commit again. +To make this less of a foot gun we added a git hook. +A `pre-commit` hook will check if linking is currently used. If it detects +a `.pnpmfile.cjs` file it will abort the commit with an explanatory message. +You will than need to run `pnpm links:off` and commit again. -A `post-commit` hook will setup the linking as it was -before if a `.links.disabled.cjs` is present. It runs `mv .links.disabled.cjs .links.cjs` and `pnpm install`. - -To activate the hooks automatically configure git with +To activate the hooks configure git with (when using the setup script (`./scripts/setup-linking.sh`) this is already done): ```bash git config --local core.hooksPath .githooks ``` +This will add the hook path for this repository only to .gihooks. which is a tracked (by git) folder containing the pre-commit hook. + +## Background +Information, why this approach is used can be found in the [linking concept reasoning](./linking_concept_reasoning.md) document. diff --git a/docs/linking_concept_reasoning.md b/docs/linking_concept_reasoning.md new file mode 100644 index 000000000..37221344c --- /dev/null +++ b/docs/linking_concept_reasoning.md @@ -0,0 +1,27 @@ + +### Why do we not enable .pnpmfile.cjs by default +Background: The presence of the `.pnpmfile.cjs` adds a field to the `pnpm-lock.yaml` called: `pnpmfileChecksum`. This field is a checksum of the content of the `.pnpmfile.cjs` file. +`pnpm install --frozen-lockfile` **fails** if there is a `.pnpmfile.cjs` but no `pnpmfileChecksum` or vice versa (or on mismatch). + +_TLDR: running with `--ignore-pnpmfile` will fail if `pnpmfileChecksum` is present._ + +#### `pnpmfileChecksum` + renovate bot +When the renovate bot creates a PR it runs `pnpm install --ignore-pnpmfile`. This means that the `pnpmfileChecksum` in the lockfile will be **empty**. +This breaks builds that **don't** ignore the `.pnpmfile.cjs`-file. (CI that runs on the renovate PR) +From here we have two possible paths: + - ignore `.pnpmfile.cjs` in all CI builds CI will also fail if we accidently add it locally. + - fixup the `pnpm-lock.yaml` in the renovate PR to contain the correct `pnpmfileChecksum`. + + Ignoring in all CI builds means that CI will always fail if we enable the linking system. + This is annoying but can be worked around with the git hook we provide that at least lets us know that we are + commiting with enabled linking. + Only if we remember setting it back/disbale linking (or let ourselves remember by the git hook) the CI will work. + + #### Summary + - We will always run into conflicts with the `pnpmfileChecksum` because in renovate prs it will be empty (`--ignore-pnpmfile`) + - To keep it simple we set `--ignore-pnpmfile` in all of ours CI to see issues immediately. + - The only solution is to never have a `.pnpmfile.cjs` in the repository when pushing. + - This way there will never be a commit with `pnpmfileChecksum` in the lockfile. + - renovate (which uses `--ignore-pnpmfile` which we cannot disable) and other CI will work + - We are able to use the linking system locally if we `cp` this file from the scripts folder into `./` on demand. + - `pnpm links:on` and `pnpm links:off` + `./scripts/setup-linking.sh` will help us with this. diff --git a/docs/self-hosting.md b/docs/self_hosting.md similarity index 100% rename from docs/self-hosting.md rename to docs/self_hosting.md diff --git a/docs/url-params.md b/docs/url_params.md similarity index 97% rename from docs/url-params.md rename to docs/url_params.md index a1e4793d4..e88e7095b 100644 --- a/docs/url-params.md +++ b/docs/url_params.md @@ -4,7 +4,7 @@ There are two formats for Element Call URLs. ## Link for sharing -Requires Element Call to be deployed in [standalone](./embedded-standalone.md) mode. +Requires Element Call to be deployed in [standalone](./embedded_standalone.md) mode. ```text https://element_call.domain/room/# @@ -36,15 +36,15 @@ possible to support encryption. | Package | Deployment | URL | | ------------------------------------ | ----------------------------- | ----------------------------------------------------------------------------- | -| [Full](./embedded-standalone.md) | All | `https://element_call.domain/room` | -| [Embedded](./embedded-standalone.md) | Remote URL | `https://element_call.domain/` n.b. no `/room` part | -| [Embedded](./embedded-standalone.md) | Embedded within messenger app | Platform dependent, but you load the `index.html` file without a `/room` part | +| [Full](./embedded_standalone.md) | All | `https://element_call.domain/room` | +| [Embedded](./embedded_standalone.md) | Remote URL | `https://element_call.domain/` n.b. no `/room` part | +| [Embedded](./embedded_standalone.md) | Embedded within messenger app | Platform dependent, but you load the `index.html` file without a `/room` part | ## Parameters ### Common Parameters -These parameters are relevant to both [widget](./embedded-standalone.md) and [standalone](./embedded-standalone.md) modes: +These parameters are relevant to both [widget](./embedded_standalone.md) and [standalone](./embedded_standalone.md) modes: | Name | Values | Required for widget | Required for SPA | Description | | ---------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------- | ---------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | @@ -74,7 +74,7 @@ These parameters are relevant to both [widget](./embedded-standalone.md) and [st ### Widget-only parameters -These parameters are only supported in [widget](./embedded-standalone.md) mode. +These parameters are only supported in [widget](./embedded_standalone.md) mode. | Name | Values | Required | Description | | --------------- | ----------------------------------------------------------------------------------------- | ----------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | @@ -89,7 +89,7 @@ These parameters are only supported in [widget](./embedded-standalone.md) mode. ### Embedded-only parameters -These parameters are only supported in the [embedded](./embedded-standalone.md) package of Element Call and will be ignored in the [full](./embedded-standalone.md) package. +These parameters are only supported in the [embedded](./embedded_standalone.md) package of Element Call and will be ignored in the [full](./embedded_standalone.md) package. | Name | Values | Required | Description | | -------------------- | -------------------------------------------------------------------------- | -------- | ---------------------------------------------------------------------------------------------------------------------------------- | diff --git a/package.json b/package.json index 867822c91..da6b7a2d4 100644 --- a/package.json +++ b/package.json @@ -32,8 +32,8 @@ "backend-playwright": "docker-compose -f playwright-backend-docker-compose.yml -f playwright-backend-docker-compose.override.yml up", "test:playwright": "playwright test", "test:playwright:open": "pnpm test:playwright --ui", - "links:enable": "mv .links.disabled.cjs .links.cjs & touch .links.cjs", - "links:disable": "mv .links.cjs .links.disabled.cjs", + "links:on": "cp scripts/.pnpmfile.cjs .pnpmfile.cjs & pnpm install", + "links:off": "rm .pnpmfile.cjs & pnpm install", "storybook": "storybook dev -p 6006", "build-storybook": "storybook build" }, diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index f75fdaa15..c9d752aba 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -236,7 +236,7 @@ importers: version: 1.9.2 matrix-js-sdk: specifier: matrix-org/matrix-js-sdk#develop - version: https://codeload.github.com/matrix-org/matrix-js-sdk/tar.gz/4ee3e591bf6498eecc1a92aad92b2ff3fc604fb8 + version: https://codeload.github.com/matrix-org/matrix-js-sdk/tar.gz/d7d771fadb983bf40bed2c97aa31c398d8eec875 matrix-widget-api: specifier: ^1.16.1 version: 1.17.0 @@ -4974,8 +4974,8 @@ packages: matrix-events-sdk@0.0.1: resolution: {integrity: sha512-1QEOsXO+bhyCroIe2/A5OwaxHvBm7EsSQ46DEDn8RBIfQwN5HWBpFvyWWR4QY0KHPPnnJdI99wgRiAl7Ad5qaA==} - matrix-js-sdk@https://codeload.github.com/matrix-org/matrix-js-sdk/tar.gz/4ee3e591bf6498eecc1a92aad92b2ff3fc604fb8: - resolution: {tarball: https://codeload.github.com/matrix-org/matrix-js-sdk/tar.gz/4ee3e591bf6498eecc1a92aad92b2ff3fc604fb8} + matrix-js-sdk@https://codeload.github.com/matrix-org/matrix-js-sdk/tar.gz/d7d771fadb983bf40bed2c97aa31c398d8eec875: + resolution: {tarball: https://codeload.github.com/matrix-org/matrix-js-sdk/tar.gz/d7d771fadb983bf40bed2c97aa31c398d8eec875} version: 41.3.0 engines: {node: '>=22.0.0'} @@ -11749,7 +11749,7 @@ snapshots: matrix-events-sdk@0.0.1: {} - matrix-js-sdk@https://codeload.github.com/matrix-org/matrix-js-sdk/tar.gz/4ee3e591bf6498eecc1a92aad92b2ff3fc604fb8: + matrix-js-sdk@https://codeload.github.com/matrix-org/matrix-js-sdk/tar.gz/d7d771fadb983bf40bed2c97aa31c398d8eec875: dependencies: '@babel/runtime': 7.29.2 '@matrix-org/matrix-sdk-crypto-wasm': 18.1.0 diff --git a/scripts/.pnpmfile.cjs b/scripts/.pnpmfile.cjs new file mode 100644 index 000000000..23b0759f4 --- /dev/null +++ b/scripts/.pnpmfile.cjs @@ -0,0 +1,62 @@ +/* +Copyright 2026 Element Creations Ltd. + +SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial +Please see LICENSE in the repository root for full details. +*/ +// DONT RUN THIS FILE MANUALLY +// This file is intended to be used with `pnpm links:on` and `pnpm links:off` which will copy this file to the project root. +// See docs/linking.md for details. +// +// +// Created based on https://github.com/element-hq/element-call/blob/60fae70a60e3697eb41210ccf1e400cab37df7c8/.yarn/plugins/linker.cjs +// and the following prompt history: +// - Can you convert this yarn plugin into a pnpm plugin. +// - The goal is to not have modifications to the package.json and lock files so that we do not track links on gh. +// This seems to modify the package.json file. +// What can we do with pnpm to have the link inforamtion in a seperate file +// - why do you cache the loaded links. When does this file get executed? +// Do we need this optimization. +// How do we guarantee, that we aleays use the most recent content from the links file? +// +// Manual transition to cjs. Claude proposed manual yaml parsing. + +const fs = require("fs"); +const path = require("path"); + +function loadLinks() { + try { + return require(path.join(__dirname, ".links.cjs")); + } catch (e) { + return null; + } +} + +function readPackage(pkg, context) { + const links = loadLinks(); + if (!links) return pkg; + + const manifest = JSON.parse( + fs.readFileSync(path.join(__dirname, "package.json"), "utf8"), + ); + if (pkg.name !== manifest.name) return pkg; + + for (const [name, linkPath] of Object.entries(links)) { + const resolved = `link:${path.resolve(__dirname, linkPath)}`; + if (pkg.dependencies && pkg.dependencies[name]) { + context.log(`Linking ${name} -> ${resolved}`); + pkg.dependencies[name] = resolved; + } else if (pkg.devDependencies && pkg.devDependencies[name]) { + context.log(`Linking ${name} -> ${resolved}`); + pkg.devDependencies[name] = resolved; + } + } + + return pkg; +} + +module.exports = { + hooks: { + readPackage, + }, +}; diff --git a/scripts/setup-linking.sh b/scripts/setup-linking.sh new file mode 100755 index 000000000..b20228d6a --- /dev/null +++ b/scripts/setup-linking.sh @@ -0,0 +1,26 @@ +#!/usr/bin/env bash + +# Checks if there currently is linking configured. Informs the user to disable linking before committing. + +LINKSFILE=.links.cjs +echo "Checking for existing linking configuration in $LINKSFILE..." +if test -f "$LINKSFILE"; then +echo "Linking configuration found in $LINKSFILE." +else + echo "No $LINKSFILE -> Creating $LINKSFILE with default values. Please edit this file to point to your local checkouts of the dependencies you want to link." + echo '''// Packages to link to local checkouts +module.exports = { + "matrix-js-sdk": "../your/path/matrix-js-sdk", + "matrix-widget-api": "../your/path/matrix-widget-api", +};''' > $LINKSFILE +fi +echo "updating local git hookPath to .githooks" +git config --local core.hooksPath .githooks +echo "" +echo "Setup complete." +echo "Update: .links.cjs to your liking" +echo "Run: 'pnpm links:on' to test your .links.cjs" +echo "Run: 'git commit' with links enabled to test the git pre-commit hook." +echo "Run: 'pnpm links:off' to be able to commit again" +echo "Run: 'git config --local core.hooksPath \"\"' to allow committing with linking on (not recommended)" +echo "Run: 'rm links.cjs' & 'git config --local core.hooksPath \"\"' to fully revert what this script did" From 8728676eb6abf0eed37486f78a6bfee175c217b0 Mon Sep 17 00:00:00 2001 From: Timo K Date: Tue, 21 Apr 2026 16:10:45 +0200 Subject: [PATCH 534/748] update CI to ignore pnpmfile - This is save since we never run pnpmfiles in ci - We can still run it locally - It helps us detect if we accidently commit it anyways. --- .github/workflows/build-element-call.yaml | 3 ++- .github/workflows/lint.yaml | 3 ++- .github/workflows/test.yaml | 6 ++++-- .github/workflows/translations-download.yaml | 3 ++- 4 files changed, 10 insertions(+), 5 deletions(-) diff --git a/.github/workflows/build-element-call.yaml b/.github/workflows/build-element-call.yaml index 190cdfdb1..f4071975e 100644 --- a/.github/workflows/build-element-call.yaml +++ b/.github/workflows/build-element-call.yaml @@ -43,7 +43,8 @@ jobs: cache: "pnpm" node-version-file: ".node-version" - name: Install dependencies - run: "pnpm install --frozen-lockfile" + # ignore-pnpmfile should never be commited. Make CI crash if it happened (`pnpmfileChecksum` is present) + run: "pnpm install --frozen-lockfile --ignore-pnpmfile" - name: Build Element Call run: pnpm run build:"$PACKAGE":"$BUILD_MODE" env: diff --git a/.github/workflows/lint.yaml b/.github/workflows/lint.yaml index 60b9095eb..0638eca6d 100644 --- a/.github/workflows/lint.yaml +++ b/.github/workflows/lint.yaml @@ -18,7 +18,8 @@ jobs: cache: "pnpm" node-version-file: ".node-version" - name: Install dependencies - run: "pnpm install --frozen-lockfile" + # ignore-pnpmfile should never be commited. Make CI crash if it happened (`pnpmfileChecksum` is present) + run: "pnpm install --frozen-lockfile --ignore-pnpmfile" - name: Prettier run: "pnpm run prettier:check" - name: i18n diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml index c436c5eed..d8af6f922 100644 --- a/.github/workflows/test.yaml +++ b/.github/workflows/test.yaml @@ -20,7 +20,8 @@ jobs: cache: "pnpm" node-version-file: ".node-version" - name: Install dependencies - run: "pnpm install --frozen-lockfile" + # ignore-pnpmfile should never be commited. Make CI crash if it happened (`pnpmfileChecksum` is present) + run: "pnpm install --frozen-lockfile --ignore-pnpmfile" - name: Vitest run: "pnpm run test:coverage" - name: Upload to codecov @@ -45,7 +46,8 @@ jobs: cache: "pnpm" node-version-file: ".node-version" - name: Install dependencies - run: pnpm install --frozen-lockfile + # ignore-pnpmfile should never be commited. Make CI crash if it happened (`pnpmfileChecksum` is present) + run: pnpm install --frozen-lockfile --ignore-pnpmfile - name: Install Playwright Browsers run: pnpm exec playwright install --with-deps - name: Run backend components diff --git a/.github/workflows/translations-download.yaml b/.github/workflows/translations-download.yaml index 6339e378d..08260a5a1 100644 --- a/.github/workflows/translations-download.yaml +++ b/.github/workflows/translations-download.yaml @@ -26,7 +26,8 @@ jobs: node-version-file: ".node-version" - name: Install Deps - run: "pnpm install --frozen-lockfile" + # ignore-pnpmfile should never be commited. Make CI crash if it happened (`pnpmfileChecksum` is present) + run: "pnpm install --frozen-lockfile --ignore-pnpmfile" - name: Prune i18n run: "rm -R locales" From 6ae88531ecec1ebc4259b38fda3e7a8817d8e723 Mon Sep 17 00:00:00 2001 From: Timo K Date: Tue, 21 Apr 2026 16:10:57 +0200 Subject: [PATCH 535/748] pnpm v10.33.0 + lock file --- package.json | 2 +- pnpm-lock.yaml | 37 +++++++++++++++++++++++++++++++++++++ 2 files changed, 38 insertions(+), 1 deletion(-) diff --git a/package.json b/package.json index da6b7a2d4..87204c665 100644 --- a/package.json +++ b/package.json @@ -156,5 +156,5 @@ "esbuild": "^0.27.7" } }, - "packageManager": "pnpm@10.0.0" + "packageManager": "pnpm@10.33.0" } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index c9d752aba..b342500de 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -1700,41 +1700,49 @@ packages: resolution: {integrity: sha512-heV2+jmXyYnUrpUXSPugqWDRpnsQcDm2AX4wzTuvgdlZfoNYO0O3W2AVpJYaDn9AG4JdM6Kxom8+foE7/BcSig==} cpu: [arm64] os: [linux] + libc: [glibc] '@oxc-resolver/binding-linux-arm64-musl@11.19.1': resolution: {integrity: sha512-jvo2Pjs1c9KPxMuMPIeQsgu0mOJF9rEb3y3TdpsrqwxRM+AN6/nDDwv45n5ZrUnQMsdBy5gIabioMKnQfWo9ew==} cpu: [arm64] os: [linux] + libc: [musl] '@oxc-resolver/binding-linux-ppc64-gnu@11.19.1': resolution: {integrity: sha512-vLmdNxWCdN7Uo5suays6A/+ywBby2PWBBPXctWPg5V0+eVuzsJxgAn6MMB4mPlshskYbppjpN2Zg83ArHze9gQ==} cpu: [ppc64] os: [linux] + libc: [glibc] '@oxc-resolver/binding-linux-riscv64-gnu@11.19.1': resolution: {integrity: sha512-/b+WgR+VTSBxzgOhDO7TlMXC1ufPIMR6Vj1zN+/x+MnyXGW7prTLzU9eW85Aj7Th7CCEG9ArCbTeqxCzFWdg2w==} cpu: [riscv64] os: [linux] + libc: [glibc] '@oxc-resolver/binding-linux-riscv64-musl@11.19.1': resolution: {integrity: sha512-YlRdeWb9j42p29ROh+h4eg/OQ3dTJlpHSa+84pUM9+p6i3djtPz1q55yLJhgW9XfDch7FN1pQ/Vd6YP+xfRIuw==} cpu: [riscv64] os: [linux] + libc: [musl] '@oxc-resolver/binding-linux-s390x-gnu@11.19.1': resolution: {integrity: sha512-EDpafVOQWF8/MJynsjOGFThcqhRHy417sRyLfQmeiamJ8qVhSKAn2Dn2VVKUGCjVB9C46VGjhNo7nOPUi1x6uA==} cpu: [s390x] os: [linux] + libc: [glibc] '@oxc-resolver/binding-linux-x64-gnu@11.19.1': resolution: {integrity: sha512-NxjZe+rqWhr+RT8/Ik+5ptA3oz7tUw361Wa5RWQXKnfqwSSHdHyrw6IdcTfYuml9dM856AlKWZIUXDmA9kkiBQ==} cpu: [x64] os: [linux] + libc: [glibc] '@oxc-resolver/binding-linux-x64-musl@11.19.1': resolution: {integrity: sha512-cM/hQwsO3ReJg5kR+SpI69DMfvNCp+A/eVR4b4YClE5bVZwz8rh2Nh05InhwI5HR/9cArbEkzMjcKgTHS6UaNw==} cpu: [x64] os: [linux] + libc: [musl] '@oxc-resolver/binding-openharmony-arm64@11.19.1': resolution: {integrity: sha512-QF080IowFB0+9Rh6RcD19bdgh49BpQHUW5TajG1qvWHvmrQznTZZjYlgE2ltLXyKY+qs4F/v5xuX1XS7Is+3qA==} @@ -1790,36 +1798,42 @@ packages: engines: {node: '>= 10.0.0'} cpu: [arm] os: [linux] + libc: [glibc] '@parcel/watcher-linux-arm-musl@2.5.6': resolution: {integrity: sha512-Ve3gUCG57nuUUSyjBq/MAM0CzArtuIOxsBdQ+ftz6ho8n7s1i9E1Nmk/xmP323r2YL0SONs1EuwqBp2u1k5fxg==} engines: {node: '>= 10.0.0'} cpu: [arm] os: [linux] + libc: [musl] '@parcel/watcher-linux-arm64-glibc@2.5.6': resolution: {integrity: sha512-f2g/DT3NhGPdBmMWYoxixqYr3v/UXcmLOYy16Bx0TM20Tchduwr4EaCbmxh1321TABqPGDpS8D/ggOTaljijOA==} engines: {node: '>= 10.0.0'} cpu: [arm64] os: [linux] + libc: [glibc] '@parcel/watcher-linux-arm64-musl@2.5.6': resolution: {integrity: sha512-qb6naMDGlbCwdhLj6hgoVKJl2odL34z2sqkC7Z6kzir8b5W65WYDpLB6R06KabvZdgoHI/zxke4b3zR0wAbDTA==} engines: {node: '>= 10.0.0'} cpu: [arm64] os: [linux] + libc: [musl] '@parcel/watcher-linux-x64-glibc@2.5.6': resolution: {integrity: sha512-kbT5wvNQlx7NaGjzPFu8nVIW1rWqV780O7ZtkjuWaPUgpv2NMFpjYERVi0UYj1msZNyCzGlaCWEtzc+exjMGbQ==} engines: {node: '>= 10.0.0'} cpu: [x64] os: [linux] + libc: [glibc] '@parcel/watcher-linux-x64-musl@2.5.6': resolution: {integrity: sha512-1JRFeC+h7RdXwldHzTsmdtYR/Ku8SylLgTU/reMuqdVD7CtLwf0VR1FqeprZ0eHQkO0vqsbvFLXUmYm/uNKJBg==} engines: {node: '>= 10.0.0'} cpu: [x64] os: [linux] + libc: [musl] '@parcel/watcher-win32-arm64@2.5.6': resolution: {integrity: sha512-3ukyebjc6eGlw9yRt678DxVF7rjXatWiHvTXqphZLvo7aC5NdEgFufVwjFfY51ijYEWpXbqF5jtrK275z52D4Q==} @@ -2327,36 +2341,42 @@ packages: engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [linux] + libc: [glibc] '@rolldown/binding-linux-arm64-musl@1.0.0-rc.15': resolution: {integrity: sha512-ZvRYMGrAklV9PEkgt4LQM6MjQX2P58HPAuecwYObY2DhS2t35R0I810bKi0wmaYORt6m/2Sm+Z+nFgb0WhXNcQ==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [linux] + libc: [musl] '@rolldown/binding-linux-ppc64-gnu@1.0.0-rc.15': resolution: {integrity: sha512-VDpgGBzgfg5hLg+uBpCLoFG5kVvEyafmfxGUV0UHLcL5irxAK7PKNeC2MwClgk6ZAiNhmo9FLhRYgvMmedLtnQ==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [ppc64] os: [linux] + libc: [glibc] '@rolldown/binding-linux-s390x-gnu@1.0.0-rc.15': resolution: {integrity: sha512-y1uXY3qQWCzcPgRJATPSOUP4tCemh4uBdY7e3EZbVwCJTY3gLJWnQABgeUetvED+bt1FQ01OeZwvhLS2bpNrAQ==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [s390x] os: [linux] + libc: [glibc] '@rolldown/binding-linux-x64-gnu@1.0.0-rc.15': resolution: {integrity: sha512-023bTPBod7J3Y/4fzAN6QtpkSABR0rigtrwaP+qSEabUh5zf6ELr9Nc7GujaROuPY3uwdSIXWrvhn1KxOvurWA==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [linux] + libc: [glibc] '@rolldown/binding-linux-x64-musl@1.0.0-rc.15': resolution: {integrity: sha512-witB2O0/hU4CgfOOKUoeFgQ4GktPi1eEbAhaLAIpgD6+ZnhcPkUtPsoKKHRzmOoWPZue46IThdSgdo4XneOLYw==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [linux] + libc: [musl] '@rolldown/binding-openharmony-arm64@1.0.0-rc.15': resolution: {integrity: sha512-UCL68NJ0Ud5zRipXZE9dF5PmirzJE4E4BCIOOssEnM7wLDsxjc6Qb0sGDxTNRTP53I6MZpygyCpY8Aa8sPfKPg==} @@ -2443,66 +2463,79 @@ packages: resolution: {integrity: sha512-L+34Qqil+v5uC0zEubW7uByo78WOCIrBvci69E7sFASRl0X7b/MB6Cqd1lky/CtcSVTydWa2WZwFuWexjS5o6g==} cpu: [arm] os: [linux] + libc: [glibc] '@rollup/rollup-linux-arm-musleabihf@4.60.1': resolution: {integrity: sha512-n83O8rt4v34hgFzlkb1ycniJh7IR5RCIqt6mz1VRJD6pmhRi0CXdmfnLu9dIUS6buzh60IvACM842Ffb3xd6Gg==} cpu: [arm] os: [linux] + libc: [musl] '@rollup/rollup-linux-arm64-gnu@4.60.1': resolution: {integrity: sha512-Nql7sTeAzhTAja3QXeAI48+/+GjBJ+QmAH13snn0AJSNL50JsDqotyudHyMbO2RbJkskbMbFJfIJKWA6R1LCJQ==} cpu: [arm64] os: [linux] + libc: [glibc] '@rollup/rollup-linux-arm64-musl@4.60.1': resolution: {integrity: sha512-+pUymDhd0ys9GcKZPPWlFiZ67sTWV5UU6zOJat02M1+PiuSGDziyRuI/pPue3hoUwm2uGfxdL+trT6Z9rxnlMA==} cpu: [arm64] os: [linux] + libc: [musl] '@rollup/rollup-linux-loong64-gnu@4.60.1': resolution: {integrity: sha512-VSvgvQeIcsEvY4bKDHEDWcpW4Yw7BtlKG1GUT4FzBUlEKQK0rWHYBqQt6Fm2taXS+1bXvJT6kICu5ZwqKCnvlQ==} cpu: [loong64] os: [linux] + libc: [glibc] '@rollup/rollup-linux-loong64-musl@4.60.1': resolution: {integrity: sha512-4LqhUomJqwe641gsPp6xLfhqWMbQV04KtPp7/dIp0nzPxAkNY1AbwL5W0MQpcalLYk07vaW9Kp1PBhdpZYYcEw==} cpu: [loong64] os: [linux] + libc: [musl] '@rollup/rollup-linux-ppc64-gnu@4.60.1': resolution: {integrity: sha512-tLQQ9aPvkBxOc/EUT6j3pyeMD6Hb8QF2BTBnCQWP/uu1lhc9AIrIjKnLYMEroIz/JvtGYgI9dF3AxHZNaEH0rw==} cpu: [ppc64] os: [linux] + libc: [glibc] '@rollup/rollup-linux-ppc64-musl@4.60.1': resolution: {integrity: sha512-RMxFhJwc9fSXP6PqmAz4cbv3kAyvD1etJFjTx4ONqFP9DkTkXsAMU4v3Vyc5BgzC+anz7nS/9tp4obsKfqkDHg==} cpu: [ppc64] os: [linux] + libc: [musl] '@rollup/rollup-linux-riscv64-gnu@4.60.1': resolution: {integrity: sha512-QKgFl+Yc1eEk6MmOBfRHYF6lTxiiiV3/z/BRrbSiW2I7AFTXoBFvdMEyglohPj//2mZS4hDOqeB0H1ACh3sBbg==} cpu: [riscv64] os: [linux] + libc: [glibc] '@rollup/rollup-linux-riscv64-musl@4.60.1': resolution: {integrity: sha512-RAjXjP/8c6ZtzatZcA1RaQr6O1TRhzC+adn8YZDnChliZHviqIjmvFwHcxi4JKPSDAt6Uhf/7vqcBzQJy0PDJg==} cpu: [riscv64] os: [linux] + libc: [musl] '@rollup/rollup-linux-s390x-gnu@4.60.1': resolution: {integrity: sha512-wcuocpaOlaL1COBYiA89O6yfjlp3RwKDeTIA0hM7OpmhR1Bjo9j31G1uQVpDlTvwxGn2nQs65fBFL5UFd76FcQ==} cpu: [s390x] os: [linux] + libc: [glibc] '@rollup/rollup-linux-x64-gnu@4.60.1': resolution: {integrity: sha512-77PpsFQUCOiZR9+LQEFg9GClyfkNXj1MP6wRnzYs0EeWbPcHs02AXu4xuUbM1zhwn3wqaizle3AEYg5aeoohhg==} cpu: [x64] os: [linux] + libc: [glibc] '@rollup/rollup-linux-x64-musl@4.60.1': resolution: {integrity: sha512-5cIATbk5vynAjqqmyBjlciMJl1+R/CwX9oLk/EyiFXDWd95KpHdrOJT//rnUl4cUcskrd0jCCw3wpZnhIHdD9w==} cpu: [x64] os: [linux] + libc: [musl] '@rollup/rollup-openbsd-x64@4.60.1': resolution: {integrity: sha512-cl0w09WsCi17mcmWqqglez9Gk8isgeWvoUZ3WiJFYSR3zjBQc2J5/ihSjpl+VLjPqjQ/1hJRcqBfLjssREQILw==} @@ -4857,24 +4890,28 @@ packages: engines: {node: '>= 12.0.0'} cpu: [arm64] os: [linux] + libc: [glibc] lightningcss-linux-arm64-musl@1.32.0: resolution: {integrity: sha512-UpQkoenr4UJEzgVIYpI80lDFvRmPVg6oqboNHfoH4CQIfNA+HOrZ7Mo7KZP02dC6LjghPQJeBsvXhJod/wnIBg==} engines: {node: '>= 12.0.0'} cpu: [arm64] os: [linux] + libc: [musl] lightningcss-linux-x64-gnu@1.32.0: resolution: {integrity: sha512-V7Qr52IhZmdKPVr+Vtw8o+WLsQJYCTd8loIfpDaMRWGUZfBOYEJeyJIkqGIDMZPwPx24pUMfwSxxI8phr/MbOA==} engines: {node: '>= 12.0.0'} cpu: [x64] os: [linux] + libc: [glibc] lightningcss-linux-x64-musl@1.32.0: resolution: {integrity: sha512-bYcLp+Vb0awsiXg/80uCRezCYHNg1/l3mt0gzHnWV9XP1W5sKa5/TCdGWaR/zBM2PeF/HbsQv/j2URNOiVuxWg==} engines: {node: '>= 12.0.0'} cpu: [x64] os: [linux] + libc: [musl] lightningcss-win32-arm64-msvc@1.32.0: resolution: {integrity: sha512-8SbC8BR40pS6baCM8sbtYDSwEVQd4JlFTOlaD3gWGHfThTcABnNDBda6eTZeqbofalIJhFx0qKzgHJmcPTnGdw==} From 92338a2e7cf02910c5d24cb77d99a04c8a2aa360 Mon Sep 17 00:00:00 2001 From: Timo K Date: Tue, 21 Apr 2026 16:12:14 +0200 Subject: [PATCH 536/748] review --- src/livekit/BlurBackgroundTransformer.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/livekit/BlurBackgroundTransformer.ts b/src/livekit/BlurBackgroundTransformer.ts index 7bec3cc4f..f86120d33 100644 --- a/src/livekit/BlurBackgroundTransformer.ts +++ b/src/livekit/BlurBackgroundTransformer.ts @@ -29,7 +29,7 @@ interface WasmFileset { // MediaPipe and depend on node_modules having this specific structure. It's // easy to see this breaking if our dependencies changed and MediaPipe were // no longer hoisted, or if we switched to another dependency loader such as -// pnpm PnP. +// yarn PnP. // https://github.com/google-ai-edge/mediapipe/issues/5961 const wasmFileset: WasmFileset = { wasmLoaderPath: new URL( From d28cad3f12431111fa44e172cb6a35f6ac885278 Mon Sep 17 00:00:00 2001 From: Timo K Date: Tue, 21 Apr 2026 16:45:00 +0200 Subject: [PATCH 537/748] fix matrix-js-sdk branch reference --- pnpm-lock.yaml | 8 ++++---- pnpm-workspace.yaml | 3 +++ 2 files changed, 7 insertions(+), 4 deletions(-) create mode 100644 pnpm-workspace.yaml diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index b342500de..fa9ebebb5 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -236,7 +236,7 @@ importers: version: 1.9.2 matrix-js-sdk: specifier: matrix-org/matrix-js-sdk#develop - version: https://codeload.github.com/matrix-org/matrix-js-sdk/tar.gz/d7d771fadb983bf40bed2c97aa31c398d8eec875 + version: https://codeload.github.com/matrix-org/matrix-js-sdk/tar.gz/4b33892d48017b3733a00a48cf5d30182be4a6fb matrix-widget-api: specifier: ^1.16.1 version: 1.17.0 @@ -5011,8 +5011,8 @@ packages: matrix-events-sdk@0.0.1: resolution: {integrity: sha512-1QEOsXO+bhyCroIe2/A5OwaxHvBm7EsSQ46DEDn8RBIfQwN5HWBpFvyWWR4QY0KHPPnnJdI99wgRiAl7Ad5qaA==} - matrix-js-sdk@https://codeload.github.com/matrix-org/matrix-js-sdk/tar.gz/d7d771fadb983bf40bed2c97aa31c398d8eec875: - resolution: {tarball: https://codeload.github.com/matrix-org/matrix-js-sdk/tar.gz/d7d771fadb983bf40bed2c97aa31c398d8eec875} + matrix-js-sdk@https://codeload.github.com/matrix-org/matrix-js-sdk/tar.gz/4b33892d48017b3733a00a48cf5d30182be4a6fb: + resolution: {tarball: https://codeload.github.com/matrix-org/matrix-js-sdk/tar.gz/4b33892d48017b3733a00a48cf5d30182be4a6fb} version: 41.3.0 engines: {node: '>=22.0.0'} @@ -11786,7 +11786,7 @@ snapshots: matrix-events-sdk@0.0.1: {} - matrix-js-sdk@https://codeload.github.com/matrix-org/matrix-js-sdk/tar.gz/d7d771fadb983bf40bed2c97aa31c398d8eec875: + matrix-js-sdk@https://codeload.github.com/matrix-org/matrix-js-sdk/tar.gz/4b33892d48017b3733a00a48cf5d30182be4a6fb: dependencies: '@babel/runtime': 7.29.2 '@matrix-org/matrix-sdk-crypto-wasm': 18.1.0 diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml new file mode 100644 index 000000000..3fbe34a8a --- /dev/null +++ b/pnpm-workspace.yaml @@ -0,0 +1,3 @@ +# dependencies where we use branches and hashes in the package.json. But that also use a pre/post install script. +onlyBuiltDependencies: + - "matrix-js-sdk" From 2d16487ca1d54fe34b8a42024fd867bd876c4f77 Mon Sep 17 00:00:00 2001 From: Timo K Date: Tue, 21 Apr 2026 17:11:40 +0200 Subject: [PATCH 538/748] fix sticky send race --- playwright/spa-call-sticky.spec.ts | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/playwright/spa-call-sticky.spec.ts b/playwright/spa-call-sticky.spec.ts index 246b4a73a..33af94bff 100644 --- a/playwright/spa-call-sticky.spec.ts +++ b/playwright/spa-call-sticky.spec.ts @@ -28,7 +28,7 @@ async function setupTwoUserSpaCall( await page.goto("/"); let androlHasSentStickyEvent = false; - + const androlResolver = Promise.withResolvers(); await interceptEventSend( page, // This room is not encrypted, so the event is sent in clear @@ -36,6 +36,7 @@ async function setupTwoUserSpaCall( (req) => { androlHasSentStickyEvent = androlHasSentStickyEvent || isStickySend(req.url()); + androlResolver.resolve(); }, ); @@ -53,6 +54,7 @@ async function setupTwoUserSpaCall( let pevaraHasSentStickyEvent = false; + const paveraResolver = Promise.withResolvers(); await interceptEventSend( guestPage, // This room is not encrypted, so the event is sent in clear @@ -60,6 +62,7 @@ async function setupTwoUserSpaCall( (req) => { pevaraHasSentStickyEvent = pevaraHasSentStickyEvent || isStickySend(req.url()); + paveraResolver.resolve(); }, ); @@ -70,7 +73,9 @@ async function setupTwoUserSpaCall( "2_0", ); // Assert both sides have sent sticky membership events + await androlResolver.promise; expect(androlHasSentStickyEvent).toEqual(true); + await paveraResolver.promise; expect(pevaraHasSentStickyEvent).toEqual(true); return { guestPage }; From ecb2a6846f63e02da810b8af749bf40d2393ca81 Mon Sep 17 00:00:00 2001 From: Timo K Date: Tue, 21 Apr 2026 17:13:13 +0200 Subject: [PATCH 539/748] prettier --- docs/linking.md | 7 ++++++- docs/linking_concept_reasoning.md | 35 +++++++++++++++++-------------- 2 files changed, 25 insertions(+), 17 deletions(-) diff --git a/docs/linking.md b/docs/linking.md index b9c62edf2..1016fffbd 100644 --- a/docs/linking.md +++ b/docs/linking.md @@ -1,9 +1,13 @@ ## Quickstart guide + run + ```bash ./scripts/setup-linking.sh ``` + Read the script output: + ``` Setup complete. Update: .links.cjs to your liking @@ -14,7 +18,6 @@ Run: 'git config --local core.hooksPath ""' to allow committing with linking (no Run: 'rm links.cjs' & 'git config --local core.hooksPath ""' to fully revert what this script did ``` - # Developing with linked packages If you want to make changes to a package that Element Call depends on and see those changes applied in real time, you can create a link to a local copy of the package. `pnpm` has a command for this (`pnpm link`), but it's not recommended to use it as it ends up modifying package.json with details specific to your development environment. @@ -54,7 +57,9 @@ To activate the hooks configure git with (when using the setup script (`./script ```bash git config --local core.hooksPath .githooks ``` + This will add the hook path for this repository only to .gihooks. which is a tracked (by git) folder containing the pre-commit hook. ## Background + Information, why this approach is used can be found in the [linking concept reasoning](./linking_concept_reasoning.md) document. diff --git a/docs/linking_concept_reasoning.md b/docs/linking_concept_reasoning.md index 37221344c..7c135a964 100644 --- a/docs/linking_concept_reasoning.md +++ b/docs/linking_concept_reasoning.md @@ -1,27 +1,30 @@ - ### Why do we not enable .pnpmfile.cjs by default + Background: The presence of the `.pnpmfile.cjs` adds a field to the `pnpm-lock.yaml` called: `pnpmfileChecksum`. This field is a checksum of the content of the `.pnpmfile.cjs` file. `pnpm install --frozen-lockfile` **fails** if there is a `.pnpmfile.cjs` but no `pnpmfileChecksum` or vice versa (or on mismatch). _TLDR: running with `--ignore-pnpmfile` will fail if `pnpmfileChecksum` is present._ #### `pnpmfileChecksum` + renovate bot + When the renovate bot creates a PR it runs `pnpm install --ignore-pnpmfile`. This means that the `pnpmfileChecksum` in the lockfile will be **empty**. This breaks builds that **don't** ignore the `.pnpmfile.cjs`-file. (CI that runs on the renovate PR) From here we have two possible paths: - - ignore `.pnpmfile.cjs` in all CI builds CI will also fail if we accidently add it locally. - - fixup the `pnpm-lock.yaml` in the renovate PR to contain the correct `pnpmfileChecksum`. - - Ignoring in all CI builds means that CI will always fail if we enable the linking system. - This is annoying but can be worked around with the git hook we provide that at least lets us know that we are - commiting with enabled linking. - Only if we remember setting it back/disbale linking (or let ourselves remember by the git hook) the CI will work. - #### Summary - - We will always run into conflicts with the `pnpmfileChecksum` because in renovate prs it will be empty (`--ignore-pnpmfile`) - - To keep it simple we set `--ignore-pnpmfile` in all of ours CI to see issues immediately. - - The only solution is to never have a `.pnpmfile.cjs` in the repository when pushing. - - This way there will never be a commit with `pnpmfileChecksum` in the lockfile. - - renovate (which uses `--ignore-pnpmfile` which we cannot disable) and other CI will work - - We are able to use the linking system locally if we `cp` this file from the scripts folder into `./` on demand. - - `pnpm links:on` and `pnpm links:off` + `./scripts/setup-linking.sh` will help us with this. +- ignore `.pnpmfile.cjs` in all CI builds CI will also fail if we accidently add it locally. +- fixup the `pnpm-lock.yaml` in the renovate PR to contain the correct `pnpmfileChecksum`. + +Ignoring in all CI builds means that CI will always fail if we enable the linking system. +This is annoying but can be worked around with the git hook we provide that at least lets us know that we are +commiting with enabled linking. +Only if we remember setting it back/disbale linking (or let ourselves remember by the git hook) the CI will work. + +#### Summary + +- We will always run into conflicts with the `pnpmfileChecksum` because in renovate prs it will be empty (`--ignore-pnpmfile`) +- To keep it simple we set `--ignore-pnpmfile` in all of ours CI to see issues immediately. +- The only solution is to never have a `.pnpmfile.cjs` in the repository when pushing. + - This way there will never be a commit with `pnpmfileChecksum` in the lockfile. + - renovate (which uses `--ignore-pnpmfile` which we cannot disable) and other CI will work +- We are able to use the linking system locally if we `cp` this file from the scripts folder into `./` on demand. +- `pnpm links:on` and `pnpm links:off` + `./scripts/setup-linking.sh` will help us with this. From bbb73b27cb834171ffcfadc92014843094f4f0f0 Mon Sep 17 00:00:00 2001 From: Timo K Date: Tue, 21 Apr 2026 17:20:58 +0200 Subject: [PATCH 540/748] fix knip --- knip.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/knip.ts b/knip.ts index aa6aee796..d76289416 100644 --- a/knip.ts +++ b/knip.ts @@ -18,6 +18,7 @@ export default { // https://docs.docker.com/compose/migrate/ "docker-compose", ], + ignoreFiles: ["scripts/.pnpmfile.cjs"], ignoreDependencies: [ // Used in CSS "normalize.css", From ea73e5881ae854427dce58d94fb1a5158fa7ffe1 Mon Sep 17 00:00:00 2001 From: Timo K Date: Tue, 21 Apr 2026 17:29:15 +0200 Subject: [PATCH 541/748] pevara --- playwright/spa-call-sticky.spec.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/playwright/spa-call-sticky.spec.ts b/playwright/spa-call-sticky.spec.ts index 33af94bff..328a65da1 100644 --- a/playwright/spa-call-sticky.spec.ts +++ b/playwright/spa-call-sticky.spec.ts @@ -54,7 +54,7 @@ async function setupTwoUserSpaCall( let pevaraHasSentStickyEvent = false; - const paveraResolver = Promise.withResolvers(); + const pevaraResolver = Promise.withResolvers(); await interceptEventSend( guestPage, // This room is not encrypted, so the event is sent in clear @@ -62,7 +62,7 @@ async function setupTwoUserSpaCall( (req) => { pevaraHasSentStickyEvent = pevaraHasSentStickyEvent || isStickySend(req.url()); - paveraResolver.resolve(); + pevaraResolver.resolve(); }, ); @@ -75,7 +75,7 @@ async function setupTwoUserSpaCall( // Assert both sides have sent sticky membership events await androlResolver.promise; expect(androlHasSentStickyEvent).toEqual(true); - await paveraResolver.promise; + await pevaraResolver.promise; expect(pevaraHasSentStickyEvent).toEqual(true); return { guestPage }; From 4211405e7b419cec745076ff137244150b9b6057 Mon Sep 17 00:00:00 2001 From: Valere Date: Fri, 3 Apr 2026 16:09:30 +0200 Subject: [PATCH 542/748] Use synapse API to register instead doing via UI --- backend/dev_homeserver-othersite.yaml | 3 + backend/dev_homeserver.yaml | 3 + backend/dev_nginx.conf | 21 ++- backend/playwright_homeserver-othersite.yaml | 3 + backend/playwright_homeserver.yaml | 3 + playwright.config.ts | 11 ++ playwright/utils/synapse-admin.ts | 142 +++++++++++++++++++ playwright/widget/test-helpers.ts | 50 ++++--- 8 files changed, 213 insertions(+), 23 deletions(-) create mode 100644 playwright/utils/synapse-admin.ts diff --git a/backend/dev_homeserver-othersite.yaml b/backend/dev_homeserver-othersite.yaml index 81e775cab..7eb8f294a 100644 --- a/backend/dev_homeserver-othersite.yaml +++ b/backend/dev_homeserver-othersite.yaml @@ -50,6 +50,9 @@ max_event_delay_duration: 24h enable_registration: true enable_registration_without_verification: true +# Shared secret for admin user registration via API (for testing only!) +registration_shared_secret: "test_shared_secret_for_local_dev_only" + report_stats: false serve_server_wellknown: true diff --git a/backend/dev_homeserver.yaml b/backend/dev_homeserver.yaml index dc7b42c84..0aea2ece2 100644 --- a/backend/dev_homeserver.yaml +++ b/backend/dev_homeserver.yaml @@ -50,6 +50,9 @@ max_event_delay_duration: 24h enable_registration: true enable_registration_without_verification: true +# Shared secret for admin user registration via API (for testing only!) +registration_shared_secret: "test_shared_secret_for_local_dev_only" + report_stats: false serve_server_wellknown: true diff --git a/backend/dev_nginx.conf b/backend/dev_nginx.conf index d3ddbc531..fdefa3bd8 100644 --- a/backend/dev_nginx.conf +++ b/backend/dev_nginx.conf @@ -28,11 +28,18 @@ server { # Reason: the lk-jwt-service uses the federation API for the openid token # verification, which requires TLS location ~ ^(/_matrix|/_synapse/client) { - proxy_pass "http://homeserver:8008"; + proxy_pass "http://homeserver:8008"; proxy_http_version 1.1; proxy_set_header X-Forwarded-For $remote_addr; proxy_set_header X-Forwarded-Proto $scheme; - proxy_set_header Host $host; + proxy_set_header Host $host; + } + location ~ ^(/_matrix|/_synapse/admin) { + proxy_pass "http://homeserver:8008"; + proxy_http_version 1.1; + proxy_set_header X-Forwarded-For $remote_addr; + proxy_set_header X-Forwarded-Proto $scheme; + proxy_set_header Host $host; } error_page 500 502 503 504 /50x.html; @@ -73,7 +80,15 @@ server { proxy_http_version 1.1; proxy_set_header X-Forwarded-For $remote_addr; proxy_set_header X-Forwarded-Proto $scheme; - proxy_set_header Host $host; + proxy_set_header Host $host; + } + + location ~ ^(/_matrix|/_synapse/admin) { + proxy_pass "http://homeserver-1:18008"; + proxy_http_version 1.1; + proxy_set_header X-Forwarded-For $remote_addr; + proxy_set_header X-Forwarded-Proto $scheme; + proxy_set_header Host $host; } error_page 500 502 503 504 /50x.html; diff --git a/backend/playwright_homeserver-othersite.yaml b/backend/playwright_homeserver-othersite.yaml index 35640ae9a..86c77b35f 100644 --- a/backend/playwright_homeserver-othersite.yaml +++ b/backend/playwright_homeserver-othersite.yaml @@ -50,6 +50,9 @@ max_event_delay_duration: 24h enable_registration: true enable_registration_without_verification: true +# Shared secret for admin user registration via API (for testing only!) +registration_shared_secret: "test_shared_secret_for_local_dev_only" + report_stats: false serve_server_wellknown: true diff --git a/backend/playwright_homeserver.yaml b/backend/playwright_homeserver.yaml index a83247cd9..8f4375241 100644 --- a/backend/playwright_homeserver.yaml +++ b/backend/playwright_homeserver.yaml @@ -50,6 +50,9 @@ max_event_delay_duration: 24h enable_registration: true enable_registration_without_verification: true +# Shared secret for admin user registration via API (for testing only!) +registration_shared_secret: "test_shared_secret_for_local_dev_only" + report_stats: false serve_server_wellknown: true diff --git a/playwright.config.ts b/playwright.config.ts index 4fb86b95b..84afed643 100644 --- a/playwright.config.ts +++ b/playwright.config.ts @@ -7,11 +7,22 @@ Please see LICENSE in the repository root for full details. */ import { defineConfig, devices } from "@playwright/test"; +import { join } from "path"; +import path from "node:path"; +import { fileURLToPath } from "node:url"; const baseURL = process.env.USE_DOCKER ? "http://localhost:8080" : "https://localhost:3000"; +const __dirname = path.dirname(fileURLToPath(import.meta.url)); + +// Needed by the synapse admin API called in fixtures +process.env.NODE_EXTRA_CA_CERTS = join( + __dirname, + "backend/dev_tls_local-ca.crt", +); + /** * See https://playwright.dev/docs/test-configuration. */ diff --git a/playwright/utils/synapse-admin.ts b/playwright/utils/synapse-admin.ts new file mode 100644 index 000000000..b1d0039c6 --- /dev/null +++ b/playwright/utils/synapse-admin.ts @@ -0,0 +1,142 @@ +/* +Copyright 2026 Element Creations Ltd. + +SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial +Please see LICENSE in the repository root for full details. +*/ + +import { createHmac } from "crypto"; + +/** + * Response from Synapse registration API + */ +export interface SynapseRegistrationResponse { + access_token: string; + user_id: string; + home_server: string; + device_id: string; +} + +/** + * Utility class for interacting with Synapse Admin API + * This provides fast user registration without going through the UI + * + * @see https://matrix-org.github.io/synapse/latest/admin_api/register_api.html + */ +export class SynapseAdmin { + public constructor( + private baseUrl: string = "https://synapse.m.localhost", + private sharedSecret: string = "test_shared_secret_for_local_dev_only", + ) {} + + /** + * Register a user using the Synapse Admin API + * This is much faster than going through the UI registration flow + * + * @param username - The username (localpart) for the new user + * @param password - The password for the new user + * @param displayName - Optional display name (defaults to username) + * @param admin - Whether the user should be an admin (defaults to false) + * @returns Registration response containing access token and user ID + */ + public async registerUser( + username: string, + password: string, + displayName?: string, + admin: boolean = false, + ): Promise { + // Get a nonce first + const nonce = await this.getNonce(); + + // Generate the HMAC + const mac = this.generateMac(username, password, admin, nonce); + + // Make the registration request + const response = await fetch(`${this.baseUrl}/_synapse/admin/v1/register`, { + method: "POST", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify({ + nonce, + username, + password, + displayname: displayName || username, + admin, + mac, + }), + }); + + if (!response.ok) { + const error = await response.text(); + throw new Error( + `Failed to register user ${username}: ${response.status} ${error}`, + ); + } + + return response.json(); + } + + /** + * Get a nonce for registration + * The nonce is required for the HMAC calculation + * + * @returns A nonce string + */ + private async getNonce(): Promise { + const response = await fetch(`${this.baseUrl}/_synapse/admin/v1/register`, { + method: "GET", + }); + + if (!response.ok) { + throw new Error( + `Failed to get nonce: ${response.status} ${await response.text()}`, + ); + } + + const data = await response.json(); + return data.nonce; + } + + /** + * Generate HMAC for shared secret registration + * This is the authentication mechanism for the admin API + * + * @param username - The username + * @param password - The password + * @param admin - Whether the user is an admin + * @param nonce - The nonce from the server + * @returns The HMAC hex string + */ + private generateMac( + username: string, + password: string, + admin: boolean, + nonce: string, + ): string { + const mac = createHmac("sha1", this.sharedSecret); + mac.update(nonce); + mac.update("\x00"); + mac.update(username); + mac.update("\x00"); + mac.update(password); + mac.update("\x00"); + mac.update(admin ? "admin" : "notadmin"); + + return mac.digest("hex"); + } + + /** + * Create a new SynapseAdmin instance for a different homeserver + * + * @param baseUrl - The base URL of the homeserver + * @param sharedSecret - The shared secret (defaults to test secret) + * @returns A new SynapseAdmin instance + */ + public static forHomeserver( + baseUrl: string, + sharedSecret: string = "test_shared_secret_for_local_dev_only", + ): SynapseAdmin { + return new SynapseAdmin(baseUrl, sharedSecret); + } +} diff --git a/playwright/widget/test-helpers.ts b/playwright/widget/test-helpers.ts index ff5fa7e2a..d0674f8a8 100644 --- a/playwright/widget/test-helpers.ts +++ b/playwright/widget/test-helpers.ts @@ -13,6 +13,8 @@ import { } from "@playwright/test"; import { type MatrixClient } from "matrix-js-sdk"; +import { SynapseAdmin } from "../utils/synapse-admin.ts"; + const PASSWORD = "foobarbaz1!"; export const HOST1 = "https://app.m.localhost/#/welcome"; @@ -74,29 +76,41 @@ export class TestHelpers { clientHandle: JSHandle; mxId: string; }> { + // Determine which homeserver to use based on the host + const synapseBaseUrl = + host === HOST2 + ? "https://synapse.othersite.m.localhost" + : "https://synapse.m.localhost"; + + // Register user via Synapse Admin API to speed things up + const synapseAdmin = SynapseAdmin.forHomeserver(synapseBaseUrl); + const credentials = await synapseAdmin.registerUser( + username, + PASSWORD, + username, + ); + + // STEP 2: Open browser and login const userContext = await browser.newContext({ reducedMotion: "reduce", }); const page = await userContext.newPage(); - await page.goto(host); - await page.getByRole("link", { name: "Create Account" }).click(); + await page.goto(host + "/#/login"); + + await page.getByRole("link", { name: "Sign in" }).click(); + await page.getByRole("textbox", { name: "Username" }).fill(username); - await page.getByRole("textbox", { name: "Password", exact: true }).click(); - await page - .getByRole("textbox", { name: "Password", exact: true }) - .fill(PASSWORD); - await page.getByRole("textbox", { name: "Confirm password" }).click(); - await page - .getByRole("textbox", { name: "Confirm password" }) - .fill(PASSWORD); - await page.getByRole("button", { name: "Register" }).click(); + await page.getByRole("textbox", { name: "Password" }).fill(PASSWORD); + await page.getByRole("button", { name: "Sign in" }).click(); + + // 😤For reasons web is staying on an infinite loading page after login, so we reload the page + // Super annoying to have to wait... + await page.waitForTimeout(2000); + await page.reload(); await expect( page.getByRole("heading", { name: `Welcome ${username}` }), - ).toBeVisible({ - // Increase timeout as registration can be slow :/ - timeout: 15_000, - }); + ).toBeVisible(); await this.maybeDismissBrowserNotSupportedToast(page); await this.maybeDismissServiceWorkerWarningToast(page); @@ -106,11 +120,7 @@ export class TestHelpers { const clientHandle = await page.evaluateHandle(() => window.mxMatrixClientPeg.get(), ); - const mxId = (await clientHandle.evaluate( - (cli: MatrixClient) => cli.getUserId(), - clientHandle, - ))!; - + const mxId = credentials.user_id; return { page, clientHandle, mxId }; } From 24e721f572625ffd55da82d765194e79639918f6 Mon Sep 17 00:00:00 2001 From: Valere Date: Tue, 7 Apr 2026 13:43:19 +0200 Subject: [PATCH 543/748] fix web stuck problem! go to / and not to #/login --- playwright/widget/test-helpers.ts | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/playwright/widget/test-helpers.ts b/playwright/widget/test-helpers.ts index d0674f8a8..2279e20e8 100644 --- a/playwright/widget/test-helpers.ts +++ b/playwright/widget/test-helpers.ts @@ -95,7 +95,7 @@ export class TestHelpers { reducedMotion: "reduce", }); const page = await userContext.newPage(); - await page.goto(host + "/#/login"); + await page.goto(host); await page.getByRole("link", { name: "Sign in" }).click(); @@ -103,11 +103,6 @@ export class TestHelpers { await page.getByRole("textbox", { name: "Password" }).fill(PASSWORD); await page.getByRole("button", { name: "Sign in" }).click(); - // 😤For reasons web is staying on an infinite loading page after login, so we reload the page - // Super annoying to have to wait... - await page.waitForTimeout(2000); - await page.reload(); - await expect( page.getByRole("heading", { name: `Welcome ${username}` }), ).toBeVisible(); From 0127040a8c88f60e6ad1009804994f8fc3cb316a Mon Sep 17 00:00:00 2001 From: Valere Date: Tue, 7 Apr 2026 15:43:55 +0200 Subject: [PATCH 544/748] Remove slow? no registration anymore --- playwright/mobile/create-call-mobile.spec.ts | 1 - playwright/widget/huddle-call.test.ts | 2 -- playwright/widget/pip-call-button-interaction.test.ts | 2 -- playwright/widget/pip-call.test.ts | 2 -- playwright/widget/simple-create.spec.ts | 2 -- playwright/widget/voice-call-dm.spec.ts | 6 ------ 6 files changed, 15 deletions(-) diff --git a/playwright/mobile/create-call-mobile.spec.ts b/playwright/mobile/create-call-mobile.spec.ts index b66ad6c4f..1d9d3af0e 100644 --- a/playwright/mobile/create-call-mobile.spec.ts +++ b/playwright/mobile/create-call-mobile.spec.ts @@ -53,7 +53,6 @@ test("@mobile Start a new call then leave and show the feedback screen", async ( mobileTest( "Test earpiece overlay in controlledAudioDevices mode", async ({ asMobile, browser }) => { - test.slow(); // Triples the timeout const { creatorPage, inviteLink } = asMobile; // ======== diff --git a/playwright/widget/huddle-call.test.ts b/playwright/widget/huddle-call.test.ts index 9c7cfc807..ea5d64b69 100644 --- a/playwright/widget/huddle-call.test.ts +++ b/playwright/widget/huddle-call.test.ts @@ -16,8 +16,6 @@ widgetTest("Create and join a group call", async ({ addUser, browserName }) => { "The is test is not working on firefox CI environment. No mic/audio device inputs so cam/mic are disabled", ); - test.slow(); // We are registering multiple users here, give it more time - const valere = await addUser("Valere", HOST1); const timo = await addUser("Timo", HOST1); const robin = await addUser("Robin", HOST1); diff --git a/playwright/widget/pip-call-button-interaction.test.ts b/playwright/widget/pip-call-button-interaction.test.ts index 5e59f822b..95aa41960 100644 --- a/playwright/widget/pip-call-button-interaction.test.ts +++ b/playwright/widget/pip-call-button-interaction.test.ts @@ -16,8 +16,6 @@ widgetTest("Footer interaction in PiP", async ({ addUser, browserName }) => { "The is test is not working on firefox CI environment. No mic/audio device inputs so cam/mic are disabled", ); - test.slow(); - const valere = await addUser("Valere", HOST1); const callRoom = "CallRoom"; diff --git a/playwright/widget/pip-call.test.ts b/playwright/widget/pip-call.test.ts index 63ba2050a..ef19a36e6 100644 --- a/playwright/widget/pip-call.test.ts +++ b/playwright/widget/pip-call.test.ts @@ -16,8 +16,6 @@ widgetTest("Put call in PIP", async ({ addUser, browserName }) => { "The is test is not working on firefox CI environment. No mic/audio device inputs so cam/mic are disabled", ); - test.slow(); - const valere = await addUser("Valere", HOST1); const timo = await addUser("Timo", HOST1); diff --git a/playwright/widget/simple-create.spec.ts b/playwright/widget/simple-create.spec.ts index 4686e99dc..6b5d17bb9 100644 --- a/playwright/widget/simple-create.spec.ts +++ b/playwright/widget/simple-create.spec.ts @@ -17,8 +17,6 @@ widgetTest.skip( ); widgetTest("Start a new call as widget", async ({ asWidget, browserName }) => { - test.slow(); // Triples the timeout - const { brooks, whistler } = asWidget; await TestHelpers.startCallInCurrentRoom(brooks.page, false); diff --git a/playwright/widget/voice-call-dm.spec.ts b/playwright/widget/voice-call-dm.spec.ts index a4e6255bc..7a13c58be 100644 --- a/playwright/widget/voice-call-dm.spec.ts +++ b/playwright/widget/voice-call-dm.spec.ts @@ -20,8 +20,6 @@ widgetTest( "The is test is not working on firefox CI environment. No mic/audio device inputs so cam/mic are disabled", ); - test.slow(); // Triples the timeout - const { brooks, whistler } = asWidget; await TestHelpers.startCallInCurrentRoom(brooks.page, true); @@ -113,8 +111,6 @@ widgetTest( "The is test is not working on firefox CI environment. No mic/audio device inputs so cam/mic are disabled", ); - test.slow(); // Triples the timeout - const { brooks, whistler } = asWidget; await TestHelpers.startCallInCurrentRoom(brooks.page, false); @@ -200,8 +196,6 @@ widgetTest( "The is test is not working on firefox CI environment. No mic/audio device inputs so cam/mic are disabled", ); - test.slow(); // Triples the timeout - const { brooks, whistler } = asWidget; await TestHelpers.startCallInCurrentRoom(brooks.page, false); From 701edd952273de7ba77bd3309cdcb8227eb793f2 Mon Sep 17 00:00:00 2001 From: Valere Date: Tue, 21 Apr 2026 17:54:10 +0200 Subject: [PATCH 545/748] fixup lint --- playwright/widget/simple-create.spec.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/playwright/widget/simple-create.spec.ts b/playwright/widget/simple-create.spec.ts index 6b5d17bb9..c8fb8013e 100644 --- a/playwright/widget/simple-create.spec.ts +++ b/playwright/widget/simple-create.spec.ts @@ -5,7 +5,7 @@ SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial Please see LICENSE in the repository root for full details. */ -import { expect, test } from "@playwright/test"; +import { expect } from "@playwright/test"; import { widgetTest } from "../fixtures/widget-user.ts"; import { TestHelpers } from "./test-helpers.ts"; From 754a42ffd1ff2f9eff8f7999b07457386ba588e8 Mon Sep 17 00:00:00 2001 From: Valere Date: Tue, 21 Apr 2026 18:14:51 +0200 Subject: [PATCH 546/748] increase default timeout on huddle test --- playwright/widget/huddle-call.test.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/playwright/widget/huddle-call.test.ts b/playwright/widget/huddle-call.test.ts index ea5d64b69..7bc94f81d 100644 --- a/playwright/widget/huddle-call.test.ts +++ b/playwright/widget/huddle-call.test.ts @@ -11,6 +11,9 @@ import { widgetTest } from "../fixtures/widget-user.ts"; import { HOST1, TestHelpers } from "./test-helpers.ts"; widgetTest("Create and join a group call", async ({ addUser, browserName }) => { + // increase the timeouts, it is a long test and it is annoying to retry from the beginning for a single timeout. + test.slow(); + test.skip( browserName === "firefox", "The is test is not working on firefox CI environment. No mic/audio device inputs so cam/mic are disabled", From 0e2d2c6f72e8953a3d0be2c26093bc66e1070ad6 Mon Sep 17 00:00:00 2001 From: Valere Date: Tue, 21 Apr 2026 18:36:40 +0200 Subject: [PATCH 547/748] try paralelize registrations? --- playwright/widget/federated-call.test.ts | 6 ++++-- playwright/widget/huddle-call.test.ts | 14 ++++++++------ playwright/widget/screen-share.test.ts | 8 +++++--- 3 files changed, 17 insertions(+), 11 deletions(-) diff --git a/playwright/widget/federated-call.test.ts b/playwright/widget/federated-call.test.ts index fda582501..2b17a706e 100644 --- a/playwright/widget/federated-call.test.ts +++ b/playwright/widget/federated-call.test.ts @@ -26,8 +26,10 @@ modePairs.forEach(([rtcMode1, rtcMode2]) => { "The is test is not working on firefox CI environment. No mic/audio device inputs so cam/mic are disabled", ); - const florian = await addUser("floriant", HOST1); - const timo = await addUser("timo", HOST2); + const [florian, timo] = await Promise.all([ + addUser("florian", HOST1), + addUser("timo", HOST2), + ]); const roomName = "Call Room"; diff --git a/playwright/widget/huddle-call.test.ts b/playwright/widget/huddle-call.test.ts index 7bc94f81d..07f12d8a8 100644 --- a/playwright/widget/huddle-call.test.ts +++ b/playwright/widget/huddle-call.test.ts @@ -8,7 +8,7 @@ Please see LICENSE in the repository root for full details. import { expect, test } from "@playwright/test"; import { widgetTest } from "../fixtures/widget-user.ts"; -import { HOST1, TestHelpers } from "./test-helpers.ts"; +import { HOST1, HOST2, TestHelpers } from "./test-helpers.ts"; widgetTest("Create and join a group call", async ({ addUser, browserName }) => { // increase the timeouts, it is a long test and it is annoying to retry from the beginning for a single timeout. @@ -19,11 +19,13 @@ widgetTest("Create and join a group call", async ({ addUser, browserName }) => { "The is test is not working on firefox CI environment. No mic/audio device inputs so cam/mic are disabled", ); - const valere = await addUser("Valere", HOST1); - const timo = await addUser("Timo", HOST1); - const robin = await addUser("Robin", HOST1); - const halfshot = await addUser("Halfshot", HOST1); - const florian = await addUser("florian", HOST1); + const [valere, timo, robin, halfshot, florian] = await Promise.all([ + addUser("Valere", HOST1), + addUser("Timo", HOST1), + addUser("Robin", HOST1), + addUser("Halfshot", HOST1), + addUser("florian", HOST1), + ]); const roomName = "Group Call Room"; await TestHelpers.createRoom(roomName, valere.page, [ diff --git a/playwright/widget/screen-share.test.ts b/playwright/widget/screen-share.test.ts index c60ef6976..f8437e1f0 100644 --- a/playwright/widget/screen-share.test.ts +++ b/playwright/widget/screen-share.test.ts @@ -18,9 +18,11 @@ widgetTest("Sharing screen in group call", async ({ addUser, browserName }) => { test.slow(); // We are registering multiple users here, give it more time - const alice = await addUser("Alice", HOST1); - const bob = await addUser("Bob", HOST1); - const carol = await addUser("Carol", HOST1); + const [alice, bob, carol] = await Promise.all([ + addUser("Alice", HOST1), + addUser("Bob", HOST1), + addUser("Carol", HOST1), + ]); const roomName = "Meeting Room"; await TestHelpers.createRoom(roomName, alice.page, [bob.mxId, carol.mxId]); From d1b14d8bfb1d02b3a7fb034edd973f070a909010 Mon Sep 17 00:00:00 2001 From: manfrommedan Date: Tue, 21 Apr 2026 23:29:47 +0300 Subject: [PATCH 548/748] Add Promise.withResolvers polyfill for older WebViews (Chrome < 119) --- index.html | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/index.html b/index.html index f17c73c0b..5d66703f4 100644 --- a/index.html +++ b/index.html @@ -16,6 +16,19 @@ + + <% if (packageType === "full") { %> From 55de3fd216ef84c0501754c6f704a9f8f492063b Mon Sep 17 00:00:00 2001 From: Valere Date: Wed, 22 Apr 2026 09:03:57 +0200 Subject: [PATCH 549/748] tests optimizations --- .../widget/hotswap-legacy-compat.test.ts | 12 +-- playwright/widget/huddle-call.test.ts | 93 ++++++++++--------- playwright/widget/test-helpers.ts | 5 +- 3 files changed, 57 insertions(+), 53 deletions(-) diff --git a/playwright/widget/hotswap-legacy-compat.test.ts b/playwright/widget/hotswap-legacy-compat.test.ts index e4695624a..f58a562d9 100644 --- a/playwright/widget/hotswap-legacy-compat.test.ts +++ b/playwright/widget/hotswap-legacy-compat.test.ts @@ -65,15 +65,13 @@ widgetTest( .contentFrame(); await expect(frame.getByTestId("videoTile")).toHaveCount(2); - // There are no other options than to wait for all media to be ready? - // Or it is too flaky :/ - await user.page.waitForTimeout(3000); - // No one should be waiting for media - await expect(frame.getByText("Waiting for media...")).not.toBeVisible(); + // Wait for "Waiting for media..." to disappear (with timeout) + await expect(frame.getByText("Waiting for media...")).not.toBeVisible({ + timeout: 10000, // Maximum time to wait + }); // There should be 2 video elements, visible and autoplaying - const videoElements = await frame.locator("video").all(); - expect(videoElements.length).toBe(2); + await expect(frame.locator("video")).toHaveCount(2); const blockDisplayCount = await frame .locator("video") diff --git a/playwright/widget/huddle-call.test.ts b/playwright/widget/huddle-call.test.ts index 07f12d8a8..262b66dbb 100644 --- a/playwright/widget/huddle-call.test.ts +++ b/playwright/widget/huddle-call.test.ts @@ -8,7 +8,7 @@ Please see LICENSE in the repository root for full details. import { expect, test } from "@playwright/test"; import { widgetTest } from "../fixtures/widget-user.ts"; -import { HOST1, HOST2, TestHelpers } from "./test-helpers.ts"; +import { HOST1, TestHelpers } from "./test-helpers.ts"; widgetTest("Create and join a group call", async ({ addUser, browserName }) => { // increase the timeouts, it is a long test and it is annoying to retry from the beginning for a single timeout. @@ -50,52 +50,56 @@ widgetTest("Create and join a group call", async ({ addUser, browserName }) => { await TestHelpers.joinCallFromLobby(valere.page); - for (const user of [timo, robin, halfshot, florian]) { - await TestHelpers.joinCallInCurrentRoom(user.page); - } + await Promise.all( + [timo, robin, halfshot, florian].map(async (user) => { + await TestHelpers.joinCallInCurrentRoom(user.page); + }), + ); - for (const user of [timo, robin, halfshot, florian]) { - const frame = user.page - .locator('iframe[title="Element Call"]') - .contentFrame(); - // No lobby, should start with video on - await expect( - frame.getByRole("switch", { name: "Stop video", checked: true }), - ).toBeVisible(); - } + await Promise.all( + [timo, robin, halfshot, florian].map(async (user) => { + const frame = user.page + .locator('iframe[title="Element Call"]') + .contentFrame(); + await expect( + frame.getByRole("switch", { name: "Stop video", checked: true }), + ).toBeVisible(); + }), + ); // We should see 5 video tiles everywhere now - for (const user of [valere, timo, robin, halfshot, florian]) { - const frame = user.page - .locator('iframe[title="Element Call"]') - .contentFrame(); - await expect(frame.getByTestId("videoTile")).toHaveCount(5); - for (const participant of [valere, timo, robin, halfshot, florian]) { - // Check the names are correct - await expect(frame.getByText(participant.displayName)).toBeVisible(); - } + await Promise.all( + [valere, timo, robin, halfshot, florian].map(async (user) => { + const frame = user.page + .locator('iframe[title="Element Call"]') + .contentFrame(); + await expect(frame.getByTestId("videoTile")).toHaveCount(5); + for (const participant of [valere, timo, robin, halfshot, florian]) { + // Check the names are correct + await expect(frame.getByText(participant.displayName)).toBeVisible(); + } - // There is no other options than to wait for all media to be ready? - // Or it is too flaky :/ - await user.page.waitForTimeout(5000); - // No one should be waiting for media - await expect(frame.getByText("Waiting for media...")).not.toBeVisible(); + // No one should be waiting for media + await expect(frame.getByText("Waiting for media...")).not.toBeVisible({ + // Use a bigger timeout here + timeout: 10000, + }); - // There should be 5 video elements, visible and autoplaying - const videoElements = await frame.locator("video").all(); - expect(videoElements.length).toBe(5); - await expect(frame.locator("video[autoplay]")).toHaveCount(5); + // There should be 5 video elements, visible and autoplaying + await expect(frame.locator("video")).toHaveCount(5); + await expect(frame.locator("video[autoplay]")).toHaveCount(5); - const blockDisplayCount = await frame - .locator("video") - .evaluateAll( - (videos: Element[]) => - videos.filter( - (v: Element) => window.getComputedStyle(v).display === "block", - ).length, - ); - expect(blockDisplayCount).toBe(5); - } + const blockDisplayCount = await frame + .locator("video") + .evaluateAll( + (videos: Element[]) => + videos.filter( + (v: Element) => window.getComputedStyle(v).display === "block", + ).length, + ); + expect(blockDisplayCount).toBe(5); + }), + ); // Quickly test muting one participant to see it reflects and that our asserts works const florianFrame = florian.page @@ -111,15 +115,14 @@ widgetTest("Create and join a group call", async ({ addUser, browserName }) => { await expect(florianVideoButton).toHaveAccessibleName("Start video"); await expect(florianVideoButton).not.toBeChecked(); - // wait a bit for the state to propagate - await valere.page.waitForTimeout(3000); { const frame = valere.page .locator('iframe[title="Element Call"]') .contentFrame(); - const videoElements = await frame.locator("video").all(); - expect(videoElements.length).toBe(5); + await expect(frame.locator("video")).toHaveCount(5, { + timeout: 10000, + }); const blockDisplayCount = await frame .locator("video") diff --git a/playwright/widget/test-helpers.ts b/playwright/widget/test-helpers.ts index 2279e20e8..e37e4b5be 100644 --- a/playwright/widget/test-helpers.ts +++ b/playwright/widget/test-helpers.ts @@ -105,7 +105,10 @@ export class TestHelpers { await expect( page.getByRole("heading", { name: `Welcome ${username}` }), - ).toBeVisible(); + ).toBeVisible({ + // Increase timeout here + timeout: 10000, + }); await this.maybeDismissBrowserNotSupportedToast(page); await this.maybeDismissServiceWorkerWarningToast(page); From 33172837e7490eb53b86ce86cb740eb9672fbe64 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 22 Apr 2026 07:23:47 +0000 Subject: [PATCH 550/748] Update dependency livekit-client to v2.18.4 --- pnpm-lock.yaml | 134 ++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 111 insertions(+), 23 deletions(-) diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index fa9ebebb5..2d3e891d7 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -47,16 +47,16 @@ importers: version: 11.7.12 '@livekit/components-core': specifier: ^0.12.0 - version: 0.12.13(livekit-client@2.18.3(@types/dom-mediacapture-record@1.0.22))(tslib@2.8.1) + version: 0.12.13(livekit-client@2.18.4(@types/dom-mediacapture-record@1.0.22))(tslib@2.8.1) '@livekit/components-react': specifier: ^2.0.0 - version: 2.9.20(livekit-client@2.18.3(@types/dom-mediacapture-record@1.0.22))(react-dom@19.2.5(react@19.2.5))(react@19.2.5)(tslib@2.8.1) + version: 2.9.20(livekit-client@2.18.4(@types/dom-mediacapture-record@1.0.22))(react-dom@19.2.5(react@19.2.5))(react@19.2.5)(tslib@2.8.1) '@livekit/protocol': specifier: ^1.42.2 version: 1.45.3 '@livekit/track-processors': specifier: ^0.7.1 - version: 0.7.2(@types/dom-mediacapture-transform@0.1.11)(livekit-client@2.18.3(@types/dom-mediacapture-record@1.0.22)) + version: 0.7.2(@types/dom-mediacapture-transform@0.1.11)(livekit-client@2.18.4(@types/dom-mediacapture-record@1.0.22)) '@mediapipe/tasks-vision': specifier: ^0.10.18 version: 0.10.34 @@ -227,7 +227,7 @@ importers: version: 5.88.1(@emnapi/core@1.9.2)(@emnapi/runtime@1.9.2)(@types/node@24.12.2)(typescript@5.9.3) livekit-client: specifier: ^2.18.1 - version: 2.18.3(@types/dom-mediacapture-record@1.0.22) + version: 2.18.4(@types/dom-mediacapture-record@1.0.22) lodash-es: specifier: ^4.17.21 version: 4.18.1 @@ -236,7 +236,7 @@ importers: version: 1.9.2 matrix-js-sdk: specifier: matrix-org/matrix-js-sdk#develop - version: https://codeload.github.com/matrix-org/matrix-js-sdk/tar.gz/4b33892d48017b3733a00a48cf5d30182be4a6fb + version: https://codeload.github.com/matrix-org/matrix-js-sdk/tar.gz/fef093747e1c35a60b0fdc687a7166a7d7eb8a28 matrix-widget-api: specifier: ^1.16.1 version: 1.17.0 @@ -2981,6 +2981,12 @@ packages: peerDependencies: typescript: '>=4.8.4 <6.1.0' + '@typescript-eslint/project-service@8.59.0': + resolution: {integrity: sha512-Lw5ITrR5s5TbC19YSvlr63ZfLaJoU6vtKTHyB0GQOpX0W7d5/Ir6vUahWi/8Sps/nOukZQ0IB3SmlxZnjaKVnw==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + typescript: '>=4.8.4 <6.1.0' + '@typescript-eslint/scope-manager@5.62.0': resolution: {integrity: sha512-VXuvVvZeQCQb5Zgf4HAxc04q5j+WrNAtNh9OwCsCgpKqESMTu3tF/jhZ3xG6T4NZwWl65Bg8KuS2uEvhSfLl0w==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} @@ -2989,12 +2995,22 @@ packages: resolution: {integrity: sha512-SgmyvDPexWETQek+qzZnrG6844IaO02UVyOLhI4wpo82dpZJY9+6YZCKAMFzXb7qhx37mFK1QcPQ18tud+vo6Q==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@typescript-eslint/scope-manager@8.59.0': + resolution: {integrity: sha512-UzR16Ut8IpA3Mc4DbgAShlPPkVm8xXMWafXxB0BocaVRHs8ZGakAxGRskF7FId3sdk9lgGD73GSFaWmWFDE4dg==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@typescript-eslint/tsconfig-utils@8.58.2': resolution: {integrity: sha512-3SR+RukipDvkkKp/d0jP0dyzuls3DbGmwDpVEc5wqk5f38KFThakqAAO0XMirWAE+kT00oTauTbzMFGPoAzB0A==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: typescript: '>=4.8.4 <6.1.0' + '@typescript-eslint/tsconfig-utils@8.59.0': + resolution: {integrity: sha512-91Sbl3s4Kb3SybliIY6muFBmHVv+pYXfybC4Oolp3dvk8BvIE3wOPc+403CWIT7mJNkfQRGtdqghzs2+Z91Tqg==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + typescript: '>=4.8.4 <6.1.0' + '@typescript-eslint/type-utils@8.58.2': resolution: {integrity: sha512-Z7EloNR/B389FvabdGeTo2XMs4W9TjtPiO9DAsmT0yom0bwlPyRjkJ1uCdW1DvrrrYP50AJZ9Xc3sByZA9+dcg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} @@ -3010,6 +3026,10 @@ packages: resolution: {integrity: sha512-9TukXyATBQf/Jq9AMQXfvurk+G5R2MwfqQGDR2GzGz28HvY/lXNKGhkY+6IOubwcquikWk5cjlgPvD2uAA7htQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@typescript-eslint/types@8.59.0': + resolution: {integrity: sha512-nLzdsT1gdOgFxxxwrlNVUBzSNBEEHJ86bblmk4QAS6stfig7rcJzWKqCyxFy3YRRHXDWEkb2NralA1nOYkkm/A==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@typescript-eslint/typescript-estree@5.62.0': resolution: {integrity: sha512-CmcQ6uY7b9y694lKdRB8FEel7JbU/40iSAPomu++SjLMntB+2Leay2LO6i8VnJk58MtE9/nQSFIH6jpyRWyYzA==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} @@ -3025,6 +3045,12 @@ packages: peerDependencies: typescript: '>=4.8.4 <6.1.0' + '@typescript-eslint/typescript-estree@8.59.0': + resolution: {integrity: sha512-O9Re9P1BmBLFJyikRbQpLku/QA3/AueZNO9WePLBwQrvkixTmDe8u76B6CYUAITRl/rHawggEqUGn5QIkVRLMw==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + typescript: '>=4.8.4 <6.1.0' + '@typescript-eslint/utils@5.62.0': resolution: {integrity: sha512-n8oxjeb5aIbPFEtmQxQYOLI0i9n5ySBEY/ZEHHZqKQSFnxio1rv6dthascc9dLuwrL0RC5mPCxB7vnAVGAYWAQ==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} @@ -3038,6 +3064,13 @@ packages: eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 typescript: '>=4.8.4 <6.1.0' + '@typescript-eslint/utils@8.59.0': + resolution: {integrity: sha512-I1R/K7V07XsMJ12Oaxg/O9GfrysGTmCRhvZJBv0RE0NcULMzjqVpR5kRRQjHsz3J/bElU7HwCO7zkqL+MSUz+g==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 + typescript: '>=4.8.4 <6.1.0' + '@typescript-eslint/visitor-keys@5.62.0': resolution: {integrity: sha512-07ny+LHRzQXepkGg6w0mFY41fVUNBrL2Roj/++7V1txKugfjm/Ci/qSND03r2RhlJhJYMcTn9AhhSSqQp0Ysyw==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} @@ -3046,6 +3079,10 @@ packages: resolution: {integrity: sha512-f1WO2Lx8a9t8DARmcWAUPJbu0G20bJlj8L4z72K00TMeJAoyLr/tHhI/pzYBLrR4dXWkcxO1cWYZEOX8DKHTqA==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@typescript-eslint/visitor-keys@8.59.0': + resolution: {integrity: sha512-/uejZt4dSere1bx12WLlPfv8GktzcaDtuJ7s42/HEZ5zGj9oxRaD4bj7qwSunXkf+pbAhFt2zjpHYUiT5lHf0Q==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@ungap/structured-clone@1.3.0': resolution: {integrity: sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g==} @@ -4936,8 +4973,8 @@ packages: lines-and-columns@1.2.4: resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==} - livekit-client@2.18.3: - resolution: {integrity: sha512-A8QDaVPo+Ye35bJFyKe6PjMOtY33dmdRXGKP/3+BG48ynEES3YwFzHbsPHJiScgI4OZouNef3Ew/BPazXKwo8Q==} + livekit-client@2.18.4: + resolution: {integrity: sha512-kjbH9WdA85gZNqFiAMY9jKJ3HArk8F+AQvAvSE5N6PnY+wNCV9OYe9yeb9BVezZiD6ltGyB3CkTxGyuX6BXYAw==} peerDependencies: '@types/dom-mediacapture-record': ^1 @@ -5011,8 +5048,8 @@ packages: matrix-events-sdk@0.0.1: resolution: {integrity: sha512-1QEOsXO+bhyCroIe2/A5OwaxHvBm7EsSQ46DEDn8RBIfQwN5HWBpFvyWWR4QY0KHPPnnJdI99wgRiAl7Ad5qaA==} - matrix-js-sdk@https://codeload.github.com/matrix-org/matrix-js-sdk/tar.gz/4b33892d48017b3733a00a48cf5d30182be4a6fb: - resolution: {tarball: https://codeload.github.com/matrix-org/matrix-js-sdk/tar.gz/4b33892d48017b3733a00a48cf5d30182be4a6fb} + matrix-js-sdk@https://codeload.github.com/matrix-org/matrix-js-sdk/tar.gz/fef093747e1c35a60b0fdc687a7166a7d7eb8a28: + resolution: {tarball: https://codeload.github.com/matrix-org/matrix-js-sdk/tar.gz/fef093747e1c35a60b0fdc687a7166a7d7eb8a28} version: 41.3.0 engines: {node: '>=22.0.0'} @@ -6611,8 +6648,8 @@ packages: webpack-virtual-modules@0.6.2: resolution: {integrity: sha512-66/V2i5hQanC51vBQKPH4aI8NMAcBW59FVBs+rC7eGHupMyfn34q7rZIE+ETlJ+XTevqfUhVVBgSUNSW2flEUQ==} - webrtc-adapter@9.0.4: - resolution: {integrity: sha512-5ZZY1+lGq8LEKuDlg9M2RPJHlH3R7OVwyHqMcUsLKCgd9Wvf+QrFTCItkXXYPmrJn8H6gRLXbSgxLLdexiqHxw==} + webrtc-adapter@9.0.5: + resolution: {integrity: sha512-U9vjByy/sK2OMXu5mmfuZFKTMIUQe34c0JXRO+oDrxJTsntdYT2iIFwYMOV7HhMTuktcZLGf2W1N/OcSf9ssWg==} engines: {node: '>=6.0.0', npm: '>=3.10.0'} whatwg-encoding@3.1.1: @@ -8115,21 +8152,21 @@ snapshots: '@jridgewell/resolve-uri': 3.1.2 '@jridgewell/sourcemap-codec': 1.5.5 - '@livekit/components-core@0.12.13(livekit-client@2.18.3(@types/dom-mediacapture-record@1.0.22))(tslib@2.8.1)': + '@livekit/components-core@0.12.13(livekit-client@2.18.4(@types/dom-mediacapture-record@1.0.22))(tslib@2.8.1)': dependencies: '@floating-ui/dom': 1.7.4 - livekit-client: 2.18.3(@types/dom-mediacapture-record@1.0.22) + livekit-client: 2.18.4(@types/dom-mediacapture-record@1.0.22) loglevel: 1.9.1 rxjs: 7.8.2 tslib: 2.8.1 - '@livekit/components-react@2.9.20(livekit-client@2.18.3(@types/dom-mediacapture-record@1.0.22))(react-dom@19.2.5(react@19.2.5))(react@19.2.5)(tslib@2.8.1)': + '@livekit/components-react@2.9.20(livekit-client@2.18.4(@types/dom-mediacapture-record@1.0.22))(react-dom@19.2.5(react@19.2.5))(react@19.2.5)(tslib@2.8.1)': dependencies: - '@livekit/components-core': 0.12.13(livekit-client@2.18.3(@types/dom-mediacapture-record@1.0.22))(tslib@2.8.1) + '@livekit/components-core': 0.12.13(livekit-client@2.18.4(@types/dom-mediacapture-record@1.0.22))(tslib@2.8.1) clsx: 2.1.1 events: 3.3.0 jose: 6.2.2 - livekit-client: 2.18.3(@types/dom-mediacapture-record@1.0.22) + livekit-client: 2.18.4(@types/dom-mediacapture-record@1.0.22) react: 19.2.5 react-dom: 19.2.5(react@19.2.5) tslib: 2.8.1 @@ -8141,11 +8178,11 @@ snapshots: dependencies: '@bufbuild/protobuf': 1.10.1 - '@livekit/track-processors@0.7.2(@types/dom-mediacapture-transform@0.1.11)(livekit-client@2.18.3(@types/dom-mediacapture-record@1.0.22))': + '@livekit/track-processors@0.7.2(@types/dom-mediacapture-transform@0.1.11)(livekit-client@2.18.4(@types/dom-mediacapture-record@1.0.22))': dependencies: '@mediapipe/tasks-vision': 0.10.34 '@types/dom-mediacapture-transform': 0.1.11 - livekit-client: 2.18.3(@types/dom-mediacapture-record@1.0.22) + livekit-client: 2.18.4(@types/dom-mediacapture-record@1.0.22) '@matrix-org/matrix-sdk-crypto-wasm@18.1.0': {} @@ -9399,6 +9436,15 @@ snapshots: transitivePeerDependencies: - supports-color + '@typescript-eslint/project-service@8.59.0(typescript@5.9.3)': + dependencies: + '@typescript-eslint/tsconfig-utils': 8.59.0(typescript@5.9.3) + '@typescript-eslint/types': 8.59.0 + debug: 4.4.3 + typescript: 5.9.3 + transitivePeerDependencies: + - supports-color + '@typescript-eslint/scope-manager@5.62.0': dependencies: '@typescript-eslint/types': 5.62.0 @@ -9409,10 +9455,19 @@ snapshots: '@typescript-eslint/types': 8.58.2 '@typescript-eslint/visitor-keys': 8.58.2 + '@typescript-eslint/scope-manager@8.59.0': + dependencies: + '@typescript-eslint/types': 8.59.0 + '@typescript-eslint/visitor-keys': 8.59.0 + '@typescript-eslint/tsconfig-utils@8.58.2(typescript@5.9.3)': dependencies: typescript: 5.9.3 + '@typescript-eslint/tsconfig-utils@8.59.0(typescript@5.9.3)': + dependencies: + typescript: 5.9.3 + '@typescript-eslint/type-utils@8.58.2(eslint@8.57.1)(typescript@5.9.3)': dependencies: '@typescript-eslint/types': 8.58.2 @@ -9429,6 +9484,8 @@ snapshots: '@typescript-eslint/types@8.58.2': {} + '@typescript-eslint/types@8.59.0': {} + '@typescript-eslint/typescript-estree@5.62.0(typescript@5.9.3)': dependencies: '@typescript-eslint/types': 5.62.0 @@ -9458,6 +9515,21 @@ snapshots: transitivePeerDependencies: - supports-color + '@typescript-eslint/typescript-estree@8.59.0(typescript@5.9.3)': + dependencies: + '@typescript-eslint/project-service': 8.59.0(typescript@5.9.3) + '@typescript-eslint/tsconfig-utils': 8.59.0(typescript@5.9.3) + '@typescript-eslint/types': 8.59.0 + '@typescript-eslint/visitor-keys': 8.59.0 + debug: 4.4.3 + minimatch: 10.2.5 + semver: 7.7.4 + tinyglobby: 0.2.16 + ts-api-utils: 2.5.0(typescript@5.9.3) + typescript: 5.9.3 + transitivePeerDependencies: + - supports-color + '@typescript-eslint/utils@5.62.0(eslint@8.57.1)(typescript@5.9.3)': dependencies: '@eslint-community/eslint-utils': 4.9.1(eslint@8.57.1) @@ -9484,6 +9556,17 @@ snapshots: transitivePeerDependencies: - supports-color + '@typescript-eslint/utils@8.59.0(eslint@8.57.1)(typescript@5.9.3)': + dependencies: + '@eslint-community/eslint-utils': 4.9.1(eslint@8.57.1) + '@typescript-eslint/scope-manager': 8.59.0 + '@typescript-eslint/types': 8.59.0 + '@typescript-eslint/typescript-estree': 8.59.0(typescript@5.9.3) + eslint: 8.57.1 + typescript: 5.9.3 + transitivePeerDependencies: + - supports-color + '@typescript-eslint/visitor-keys@5.62.0': dependencies: '@typescript-eslint/types': 5.62.0 @@ -9494,6 +9577,11 @@ snapshots: '@typescript-eslint/types': 8.58.2 eslint-visitor-keys: 5.0.1 + '@typescript-eslint/visitor-keys@8.59.0': + dependencies: + '@typescript-eslint/types': 8.59.0 + eslint-visitor-keys: 5.0.1 + '@ungap/structured-clone@1.3.0': {} '@use-gesture/core@10.3.1': {} @@ -10652,7 +10740,7 @@ snapshots: eslint-plugin-jest@29.15.2(@typescript-eslint/eslint-plugin@8.58.2(@typescript-eslint/parser@8.58.2(eslint@8.57.1)(typescript@5.9.3))(eslint@8.57.1)(typescript@5.9.3))(eslint@8.57.1)(typescript@5.9.3): dependencies: - '@typescript-eslint/utils': 8.58.2(eslint@8.57.1)(typescript@5.9.3) + '@typescript-eslint/utils': 8.59.0(eslint@8.57.1)(typescript@5.9.3) eslint: 8.57.1 optionalDependencies: '@typescript-eslint/eslint-plugin': 8.58.2(@typescript-eslint/parser@8.58.2(eslint@8.57.1)(typescript@5.9.3))(eslint@8.57.1)(typescript@5.9.3) @@ -11710,7 +11798,7 @@ snapshots: lines-and-columns@1.2.4: {} - livekit-client@2.18.3(@types/dom-mediacapture-record@1.0.22): + livekit-client@2.18.4(@types/dom-mediacapture-record@1.0.22): dependencies: '@livekit/mutex': 1.1.1 '@livekit/protocol': 1.45.3 @@ -11721,7 +11809,7 @@ snapshots: sdp-transform: 2.15.0 tslib: 2.8.1 typed-emitter: 2.1.0 - webrtc-adapter: 9.0.4 + webrtc-adapter: 9.0.5 locate-path@5.0.0: dependencies: @@ -11786,7 +11874,7 @@ snapshots: matrix-events-sdk@0.0.1: {} - matrix-js-sdk@https://codeload.github.com/matrix-org/matrix-js-sdk/tar.gz/4b33892d48017b3733a00a48cf5d30182be4a6fb: + matrix-js-sdk@https://codeload.github.com/matrix-org/matrix-js-sdk/tar.gz/fef093747e1c35a60b0fdc687a7166a7d7eb8a28: dependencies: '@babel/runtime': 7.29.2 '@matrix-org/matrix-sdk-crypto-wasm': 18.1.0 @@ -13643,7 +13731,7 @@ snapshots: webpack-virtual-modules@0.6.2: {} - webrtc-adapter@9.0.4: + webrtc-adapter@9.0.5: dependencies: sdp: 3.2.2 From 2b46925e77a2b9685953d8a8e5a448e7e4ee6d5b Mon Sep 17 00:00:00 2001 From: Timo K Date: Wed, 22 Apr 2026 11:51:33 +0200 Subject: [PATCH 551/748] Call window.controls.onBackButtonPressed if esc is pressed without any focus. --- src/useCallViewKeyboardShortcuts.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/useCallViewKeyboardShortcuts.ts b/src/useCallViewKeyboardShortcuts.ts index 728a26149..3d9654be6 100644 --- a/src/useCallViewKeyboardShortcuts.ts +++ b/src/useCallViewKeyboardShortcuts.ts @@ -68,6 +68,8 @@ export function useCallViewKeyboardShortcuts( } else if (KeyToReactionMap[event.key]) { event.preventDefault(); sendReaction(KeyToReactionMap[event.key]); + } else if (event.key === "Escape") { + window.controls.onBackButtonPressed?.(); } }, [ From 56bab70534d52c368c5d2b05e2c61cc5eb34e5aa Mon Sep 17 00:00:00 2001 From: Timo K Date: Wed, 22 Apr 2026 12:26:03 +0200 Subject: [PATCH 552/748] add tests --- src/useCallViewKeyboardShortcuts.test.tsx | 72 ++++++++++++++++++++++- 1 file changed, 71 insertions(+), 1 deletion(-) diff --git a/src/useCallViewKeyboardShortcuts.test.tsx b/src/useCallViewKeyboardShortcuts.test.tsx index e22380d1f..5a327f83d 100644 --- a/src/useCallViewKeyboardShortcuts.test.tsx +++ b/src/useCallViewKeyboardShortcuts.test.tsx @@ -6,7 +6,7 @@ Please see LICENSE in the repository root for full details. */ import { render } from "@testing-library/react"; -import { type FC, useRef } from "react"; +import { type FC, useRef, useState } from "react"; import { expect, test, vi } from "vitest"; import { Button } from "@vector-im/compound-web"; import userEvent from "@testing-library/user-event"; @@ -17,6 +17,7 @@ import { ReactionSet, ReactionsRowSize, } from "./reactions"; +import { type Controls } from "./controls"; // Test Explanation: // - The main objective is to test `useCallViewKeyboardShortcuts`. @@ -27,6 +28,7 @@ interface TestComponentProps { onButtonClick?: () => void; sendReaction?: () => void; toggleHandRaised?: () => void; + initialModalOpen?: boolean; } const TestComponent: FC = ({ @@ -34,7 +36,9 @@ const TestComponent: FC = ({ onButtonClick = (): void => {}, sendReaction = (reaction: ReactionOption): void => {}, toggleHandRaised = (): void => {}, + initialModalOpen = false, }) => { + const [modalOpen, setModalOpen] = useState(initialModalOpen); const ref = useRef(null); useCallViewKeyboardShortcuts( ref, @@ -47,6 +51,19 @@ const TestComponent: FC = ({ return (

+ {modalOpen && ( + { + if (e.key === "Escape") { + e.preventDefault(); + setModalOpen(false); + } + }} + > + + + )}
); }; @@ -118,6 +135,27 @@ test("raised hand can be sent via keyboard presses", async () => { expect(toggleHandRaised).toHaveBeenCalledOnce(); }); +test("raised hand cannot be sent via keyboard presses if modal open and focussed", async () => { + const user = userEvent.setup(); + const toggleHandRaised = vi.fn(); + const { getByRole } = render( + , + ); + getByRole("button", { name: "InModalButton" }).focus(); + await user.keyboard("h"); + + expect(toggleHandRaised).not.toHaveBeenCalledOnce(); + + // once we press esc... + await user.keyboard("[Escape]"); + // we can toggle the hand raise... + await user.keyboard("h"); + expect(toggleHandRaised).toHaveBeenCalledOnce(); +}); + test("unmuting happens in place of the default action", async () => { const user = userEvent.setup(); const defaultPrevented = vi.fn(); @@ -138,3 +176,35 @@ test("unmuting happens in place of the default action", async () => { await user.keyboard("[Space]"); expect(defaultPrevented).toBeCalledWith(true); }); + +test("escape button triggers the controls back action", async () => { + const user = userEvent.setup(); + + window.controls = { onBackButtonPressed: vi.fn() } as unknown as Controls; + // In the real application, we mostly just want the spacebar shortcut to avoid + // scrolling the page. But to test that here in JSDOM, we need some kind of + // container element that can be interactive and receive focus / keydown + // events.
{!hideControls &&
{buttons}
} {setLayoutMode && layoutMode && showLayoutSwitcher && ( - )}
diff --git a/src/room/LayoutToggle.module.css b/src/room/LayoutToggle.module.css deleted file mode 100644 index d9ae58137..000000000 --- a/src/room/LayoutToggle.module.css +++ /dev/null @@ -1,79 +0,0 @@ -/* -Copyright 2023, 2024 New Vector Ltd. - -SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial -Please see LICENSE in the repository root for full details. -*/ - -.toggle { - padding: 2px; - border: 1px solid var(--cpd-color-border-interactive-secondary); - border-radius: var(--cpd-radius-pill-effect); - background: var(--cpd-color-bg-canvas-default); - display: flex; - position: relative; -} - -.toggle input { - appearance: none; - /* Safari puts a margin on these, which is not removed via appearance: none */ - margin: 0; - block-size: var(--cpd-space-11x); - inline-size: var(--cpd-space-11x); - cursor: pointer; - border-radius: var(--cpd-radius-pill-effect); - background: var(--cpd-color-bg-action-secondary-rest); - box-shadow: var(--small-drop-shadow); - transition: background-color 0.1s; -} - -.toggle svg { - display: block; - position: absolute; - padding: calc(2.5 * var(--cpd-space-1x)); - pointer-events: none; - color: var(--cpd-color-icon-primary); - transition: color 0.1s; -} - -.toggle svg:nth-child(2) { - inset-inline-start: 2px; -} - -.toggle svg:nth-child(4) { - inset-inline-end: 2px; -} - -@media (hover: hover) { - .toggle input:hover { - background: var(--cpd-color-bg-action-secondary-hovered); - box-shadow: none; - } -} - -.toggle input:active { - background: var(--cpd-color-bg-action-secondary-pressed); - box-shadow: none; -} - -.toggle input:checked { - background: var(--cpd-color-bg-action-primary-rest); -} - -.toggle input:checked + svg { - color: var(--cpd-color-icon-on-solid-primary); -} - -@media (hover: hover) { - .toggle input:checked:hover { - background: var(--cpd-color-bg-action-primary-hovered); - } -} - -.toggle input:checked:active { - background: var(--cpd-color-bg-action-primary-pressed); -} - -.toggle input:first-child { - margin-inline-end: 5px; -} diff --git a/src/room/LayoutToggle.stories.tsx b/src/room/LayoutToggle.stories.tsx deleted file mode 100644 index 72a2ffade..000000000 --- a/src/room/LayoutToggle.stories.tsx +++ /dev/null @@ -1,25 +0,0 @@ -/* -Copyright 2026 Element Creations Ltd. - -SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial -Please see LICENSE in the repository root for full details. -*/ - -import { fn } from "storybook/test"; - -import type { Meta, StoryObj } from "@storybook/react-vite"; -import { LayoutToggle } from "./LayoutToggle"; - -const meta = { - component: LayoutToggle, -} satisfies Meta; - -export default meta; -type Story = StoryObj; - -export const Default: Story = { - args: { - layout: "grid", - setLayout: fn(), - }, -}; diff --git a/src/room/LayoutToggle.tsx b/src/room/LayoutToggle.tsx deleted file mode 100644 index 98ed91d31..000000000 --- a/src/room/LayoutToggle.tsx +++ /dev/null @@ -1,59 +0,0 @@ -/* -Copyright 2023, 2024 New Vector Ltd. - -SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial -Please see LICENSE in the repository root for full details. -*/ - -import { type ChangeEvent, type FC, useCallback } from "react"; -import { useTranslation } from "react-i18next"; -import { Tooltip } from "@vector-im/compound-web"; -import { - SpotlightIcon, - GridIcon, -} from "@vector-im/compound-design-tokens/assets/web/icons"; -import classNames from "classnames"; - -import styles from "./LayoutToggle.module.css"; - -export type Layout = "spotlight" | "grid"; - -type Props = { - layout: Layout; - setLayout: (layout: Layout) => void; - className?: string; -}; - -export const LayoutToggle: FC = ({ layout, setLayout, className }) => { - const { t } = useTranslation(); - - const onChange = useCallback( - (e: ChangeEvent) => setLayout(e.target.value as Layout), - [setLayout], - ); - - return ( -
- - - - - - - - - - ); -}; From d8be06974767e36598f71003121b80b5c7673a00 Mon Sep 17 00:00:00 2001 From: Half-Shot Date: Fri, 24 Apr 2026 11:54:24 +0100 Subject: [PATCH 587/748] Fix type --- locales/en/app.json | 1 + package.json | 2 +- src/components/CallFooter.tsx | 3 ++- 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/locales/en/app.json b/locales/en/app.json index 5398930f2..2545bb4b0 100644 --- a/locales/en/app.json +++ b/locales/en/app.json @@ -143,6 +143,7 @@ "text": "This call already exists, would you like to join?", "title": "Join existing call?" }, + "layout_switch_label": "Layout", "layout_grid_label": "Grid", "layout_spotlight_label": "Spotlight", "lobby": { diff --git a/package.json b/package.json index 5fa4fed21..f27cf8f4a 100644 --- a/package.json +++ b/package.json @@ -81,7 +81,7 @@ "@typescript-eslint/parser": "^8.31.0", "@use-gesture/react": "^10.2.11", "@vector-im/compound-design-tokens": "^10.0.0", - "@vector-im/compound-web": "element-hq/compound-web#e7c91ef18e20f2fc70069696f4414018361ac512", + "@vector-im/compound-web": "element-hq/compound-web#fc2e677326aaefec61ef74fb1d9de3c01eecfa7e", "@vitejs/plugin-react": "^4.0.1", "@vitest/coverage-v8": "^4.0.18", "babel-plugin-transform-vite-meta-env": "^1.0.3", diff --git a/src/components/CallFooter.tsx b/src/components/CallFooter.tsx index 21ff52c69..d10e4ecf6 100644 --- a/src/components/CallFooter.tsx +++ b/src/components/CallFooter.tsx @@ -237,7 +237,8 @@ export const CallFooter: FC = ({
{!hideControls &&
{buttons}
} {setLayoutMode && layoutMode && showLayoutSwitcher && ( - + aria-label={t("layout_switch_label")} leftLabel={t("layout_spotlight_label")} leftValue="spotlight" leftIcon={SpotlightIcon} From 9b71070ef8e312bd17d1b0c71eda775c36cf4e30 Mon Sep 17 00:00:00 2001 From: Half-Shot Date: Fri, 24 Apr 2026 11:57:13 +0100 Subject: [PATCH 588/748] publish lock changes --- pnpm-lock.yaml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 07bc5fbce..062699634 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -150,8 +150,8 @@ importers: specifier: ^10.0.0 version: 10.1.0(@types/react@19.2.14)(react@19.2.5) '@vector-im/compound-web': - specifier: element-hq/compound-web#e7c91ef18e20f2fc70069696f4414018361ac512 - version: https://codeload.github.com/element-hq/compound-web/tar.gz/e7c91ef18e20f2fc70069696f4414018361ac512(@fontsource/inconsolata@5.2.8)(@fontsource/inter@5.2.8)(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(@vector-im/compound-design-tokens@10.1.0(@types/react@19.2.14)(react@19.2.5))(react-dom@19.2.5(react@19.2.5))(react@19.2.5) + specifier: element-hq/compound-web#fc2e677326aaefec61ef74fb1d9de3c01eecfa7e + version: https://codeload.github.com/element-hq/compound-web/tar.gz/fc2e677326aaefec61ef74fb1d9de3c01eecfa7e(@fontsource/inconsolata@5.2.8)(@fontsource/inter@5.2.8)(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(@vector-im/compound-design-tokens@10.1.0(@types/react@19.2.14)(react@19.2.5))(react-dom@19.2.5(react@19.2.5))(react@19.2.5) '@vitejs/plugin-react': specifier: ^4.0.1 version: 4.7.0(vite@8.0.8(@types/node@24.12.2)(esbuild@0.27.7)(jiti@2.6.1)(sass@1.99.0)(terser@5.46.1)(yaml@2.8.3)) @@ -3037,8 +3037,8 @@ packages: react: optional: true - '@vector-im/compound-web@https://codeload.github.com/element-hq/compound-web/tar.gz/e7c91ef18e20f2fc70069696f4414018361ac512': - resolution: {tarball: https://codeload.github.com/element-hq/compound-web/tar.gz/e7c91ef18e20f2fc70069696f4414018361ac512} + '@vector-im/compound-web@https://codeload.github.com/element-hq/compound-web/tar.gz/fc2e677326aaefec61ef74fb1d9de3c01eecfa7e': + resolution: {tarball: https://codeload.github.com/element-hq/compound-web/tar.gz/fc2e677326aaefec61ef74fb1d9de3c01eecfa7e} version: 9.2.1 peerDependencies: '@fontsource/inconsolata': ^5 @@ -9474,7 +9474,7 @@ snapshots: '@types/react': 19.2.14 react: 19.2.5 - '@vector-im/compound-web@https://codeload.github.com/element-hq/compound-web/tar.gz/e7c91ef18e20f2fc70069696f4414018361ac512(@fontsource/inconsolata@5.2.8)(@fontsource/inter@5.2.8)(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(@vector-im/compound-design-tokens@10.1.0(@types/react@19.2.14)(react@19.2.5))(react-dom@19.2.5(react@19.2.5))(react@19.2.5)': + '@vector-im/compound-web@https://codeload.github.com/element-hq/compound-web/tar.gz/fc2e677326aaefec61ef74fb1d9de3c01eecfa7e(@fontsource/inconsolata@5.2.8)(@fontsource/inter@5.2.8)(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(@vector-im/compound-design-tokens@10.1.0(@types/react@19.2.14)(react@19.2.5))(react-dom@19.2.5(react@19.2.5))(react@19.2.5)': dependencies: '@floating-ui/react': 0.27.19(react-dom@19.2.5(react@19.2.5))(react@19.2.5) '@fontsource/inconsolata': 5.2.8 From 62751787ca0c4f95572d3feadd880297d3933e5e Mon Sep 17 00:00:00 2001 From: Half-Shot Date: Fri, 24 Apr 2026 13:02:47 +0100 Subject: [PATCH 589/748] Use actual package --- package.json | 2 +- pnpm-lock.yaml | 11 +++++------ 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/package.json b/package.json index f27cf8f4a..a8dc49fa8 100644 --- a/package.json +++ b/package.json @@ -81,7 +81,7 @@ "@typescript-eslint/parser": "^8.31.0", "@use-gesture/react": "^10.2.11", "@vector-im/compound-design-tokens": "^10.0.0", - "@vector-im/compound-web": "element-hq/compound-web#fc2e677326aaefec61ef74fb1d9de3c01eecfa7e", + "@vector-im/compound-web": "^9.3.0", "@vitejs/plugin-react": "^4.0.1", "@vitest/coverage-v8": "^4.0.18", "babel-plugin-transform-vite-meta-env": "^1.0.3", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 062699634..41e3f9439 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -150,8 +150,8 @@ importers: specifier: ^10.0.0 version: 10.1.0(@types/react@19.2.14)(react@19.2.5) '@vector-im/compound-web': - specifier: element-hq/compound-web#fc2e677326aaefec61ef74fb1d9de3c01eecfa7e - version: https://codeload.github.com/element-hq/compound-web/tar.gz/fc2e677326aaefec61ef74fb1d9de3c01eecfa7e(@fontsource/inconsolata@5.2.8)(@fontsource/inter@5.2.8)(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(@vector-im/compound-design-tokens@10.1.0(@types/react@19.2.14)(react@19.2.5))(react-dom@19.2.5(react@19.2.5))(react@19.2.5) + specifier: ^9.3.0 + version: 9.3.0(@fontsource/inconsolata@5.2.8)(@fontsource/inter@5.2.8)(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(@vector-im/compound-design-tokens@10.1.0(@types/react@19.2.14)(react@19.2.5))(react-dom@19.2.5(react@19.2.5))(react@19.2.5) '@vitejs/plugin-react': specifier: ^4.0.1 version: 4.7.0(vite@8.0.8(@types/node@24.12.2)(esbuild@0.27.7)(jiti@2.6.1)(sass@1.99.0)(terser@5.46.1)(yaml@2.8.3)) @@ -3037,9 +3037,8 @@ packages: react: optional: true - '@vector-im/compound-web@https://codeload.github.com/element-hq/compound-web/tar.gz/fc2e677326aaefec61ef74fb1d9de3c01eecfa7e': - resolution: {tarball: https://codeload.github.com/element-hq/compound-web/tar.gz/fc2e677326aaefec61ef74fb1d9de3c01eecfa7e} - version: 9.2.1 + '@vector-im/compound-web@9.3.0': + resolution: {integrity: sha512-Elu4Uw8RbfP6JaudQYkVibALYT6qpwubqfKhteTxIPWBWzSYM+P5T+B1uX+ra+grNcXwXUt2xfMxpqYQsAHgYA==} peerDependencies: '@fontsource/inconsolata': ^5 '@fontsource/inter': ^5 @@ -9474,7 +9473,7 @@ snapshots: '@types/react': 19.2.14 react: 19.2.5 - '@vector-im/compound-web@https://codeload.github.com/element-hq/compound-web/tar.gz/fc2e677326aaefec61ef74fb1d9de3c01eecfa7e(@fontsource/inconsolata@5.2.8)(@fontsource/inter@5.2.8)(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(@vector-im/compound-design-tokens@10.1.0(@types/react@19.2.14)(react@19.2.5))(react-dom@19.2.5(react@19.2.5))(react@19.2.5)': + '@vector-im/compound-web@9.3.0(@fontsource/inconsolata@5.2.8)(@fontsource/inter@5.2.8)(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(@vector-im/compound-design-tokens@10.1.0(@types/react@19.2.14)(react@19.2.5))(react-dom@19.2.5(react@19.2.5))(react@19.2.5)': dependencies: '@floating-ui/react': 0.27.19(react-dom@19.2.5(react@19.2.5))(react@19.2.5) '@fontsource/inconsolata': 5.2.8 From 3bc8c0590d3d8c355cbc09f6e9727f7dc48f7861 Mon Sep 17 00:00:00 2001 From: Valere Date: Fri, 24 Apr 2026 18:27:05 +0200 Subject: [PATCH 590/748] dev-tool: Add option to enable extended livekit logs --- src/App.tsx | 2 ++ src/LivekitLogLevelSync.tsx | 22 ++++++++++++++++++++++ src/settings/DeveloperSettingsTab.tsx | 19 +++++++++++++++++++ src/settings/settings.ts | 5 +++++ 4 files changed, 48 insertions(+) create mode 100644 src/LivekitLogLevelSync.tsx diff --git a/src/App.tsx b/src/App.tsx index b87f587ca..e124b0bd8 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -32,6 +32,7 @@ import { type AppViewModel } from "./state/AppViewModel"; import { MediaDevicesContext } from "./MediaDevicesContext"; import { getUrlParams, HeaderStyle } from "./UrlParams"; import { AppBar } from "./AppBar"; +import { LivekitLogLevelSync } from "./LivekitLogLevelSync.tsx"; const SentryRoute = Sentry.withSentryReactRouterV7Routing(Route); @@ -81,6 +82,7 @@ export const App: FC = ({ vm }) => { const content = loaded ? ( + } diff --git a/src/LivekitLogLevelSync.tsx b/src/LivekitLogLevelSync.tsx new file mode 100644 index 000000000..5d3916d20 --- /dev/null +++ b/src/LivekitLogLevelSync.tsx @@ -0,0 +1,22 @@ +/* +Copyright 2026 Element Creations Ltd. + +SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial +Please see LICENSE in the repository root for full details. +*/ + +// Syncs the livekit log level with the "Enable extended Livekit logs" developer setting. +import { type FC, useEffect } from "react"; +import { setLogLevel } from "livekit-client"; + +import { useSetting, enableExtendedLivekitLogs } from "./settings/settings.ts"; + +export const LivekitLogLevelSync: FC = () => { + const [extendedLivekitLogs] = useSetting(enableExtendedLivekitLogs); + + useEffect(() => { + setLogLevel(extendedLivekitLogs ? "trace" : "info"); + }, [extendedLivekitLogs]); + + return <>; +}; diff --git a/src/settings/DeveloperSettingsTab.tsx b/src/settings/DeveloperSettingsTab.tsx index 9df6181f9..0db5e2efc 100644 --- a/src/settings/DeveloperSettingsTab.tsx +++ b/src/settings/DeveloperSettingsTab.tsx @@ -43,6 +43,7 @@ import { matrixRTCMode as matrixRTCModeSetting, customLivekitUrl as customLivekitUrlSetting, MatrixRTCMode, + enableExtendedLivekitLogs as enableExtendedLivekitLogsSetting, } from "./settings"; import styles from "./DeveloperSettingsTab.module.css"; import { useUrlParams } from "../UrlParams"; @@ -101,6 +102,10 @@ export const DeveloperSettingsTab: FC = ({ alwaysShowIphoneEarpieceSetting, ); + const [enableExtendedLivekitLogs, setEnableExtendedLivekitLogs] = useSetting( + enableExtendedLivekitLogsSetting, + ); + const [customLivekitUrlUpdateError, setCustomLivekitUrlUpdateError] = useState(null); const [customLivekitUrl, setCustomLivekitUrl] = useSetting( @@ -227,6 +232,20 @@ export const DeveloperSettingsTab: FC = ({ )} />{" "} + + ): void => { + setEnableExtendedLivekitLogs(event.target.checked); + }, + [setEnableExtendedLivekitLogs], + )} + />{" "} + e.preventDefault()} helpLabel={ diff --git a/src/settings/settings.ts b/src/settings/settings.ts index 917c79f16..cf0d9d66b 100644 --- a/src/settings/settings.ts +++ b/src/settings/settings.ts @@ -129,6 +129,11 @@ export const alwaysShowIphoneEarpiece = new Setting( false, ); +export const enableExtendedLivekitLogs = new Setting( + "extended-livekit-logs", + false, +); + export enum MatrixRTCMode { Legacy = "legacy", Compatibility = "compatibility", From 5aa45714bfa194a3224e0181a2e8970a0b693ff1 Mon Sep 17 00:00:00 2001 From: Half-Shot Date: Mon, 27 Apr 2026 09:34:46 +0100 Subject: [PATCH 591/748] Snap updates --- locales/en/app.json | 2 +- .../ReactionToggleButton.test.tsx.snap | 10 +++---- .../GroupCallErrorBoundary.test.tsx.snap | 18 ++++++------ .../__snapshots__/InCallView.test.tsx.snap | 28 +++++++++---------- 4 files changed, 29 insertions(+), 29 deletions(-) diff --git a/locales/en/app.json b/locales/en/app.json index 2545bb4b0..b51c6ed9b 100644 --- a/locales/en/app.json +++ b/locales/en/app.json @@ -143,9 +143,9 @@ "text": "This call already exists, would you like to join?", "title": "Join existing call?" }, - "layout_switch_label": "Layout", "layout_grid_label": "Grid", "layout_spotlight_label": "Spotlight", + "layout_switch_label": "Layout", "lobby": { "ask_to_join": "Request to join call", "join_as_guest": "Join as guest", diff --git a/src/button/__snapshots__/ReactionToggleButton.test.tsx.snap b/src/button/__snapshots__/ReactionToggleButton.test.tsx.snap index 608c1a0fc..a1e319d95 100644 --- a/src/button/__snapshots__/ReactionToggleButton.test.tsx.snap +++ b/src/button/__snapshots__/ReactionToggleButton.test.tsx.snap @@ -10,7 +10,7 @@ exports[`Can close reaction dialog 1`] = ` aria-expanded="true" aria-haspopup="true" aria-labelledby="_r_bb_" - class="_button_13vu4_8 _has-icon_13vu4_60 _icon-only_13vu4_53" + class="_button_1nw83_8 _has-icon_1nw83_60 _icon-only_1nw83_53" data-kind="primary" data-size="lg" role="button" @@ -44,7 +44,7 @@ exports[`Can fully expand emoji picker 1`] = ` aria-expanded="true" aria-haspopup="true" aria-labelledby="_r_7m_" - class="_button_13vu4_8 _has-icon_13vu4_60 _icon-only_13vu4_53" + class="_button_1nw83_8 _has-icon_1nw83_60 _icon-only_1nw83_53" data-kind="primary" data-size="lg" role="button" @@ -75,7 +75,7 @@ exports[`Can lower hand 1`] = ` aria-expanded="false" aria-haspopup="true" aria-labelledby="_r_36_" - class="_button_13vu4_8 _has-icon_13vu4_60 _icon-only_13vu4_53" + class="_button_1nw83_8 _has-icon_1nw83_60 _icon-only_1nw83_53" data-kind="secondary" data-size="lg" role="button" @@ -109,7 +109,7 @@ exports[`Can open menu 1`] = ` aria-expanded="true" aria-haspopup="true" aria-labelledby="_r_0_" - class="_button_13vu4_8 _has-icon_13vu4_60 _icon-only_13vu4_53" + class="_button_1nw83_8 _has-icon_1nw83_60 _icon-only_1nw83_53" data-kind="primary" data-size="lg" role="button" @@ -140,7 +140,7 @@ exports[`Can raise hand 1`] = ` aria-expanded="false" aria-haspopup="true" aria-labelledby="_r_1j_" - class="_button_13vu4_8 raisedButton _has-icon_13vu4_60 _icon-only_13vu4_53" + class="_button_1nw83_8 raisedButton _has-icon_1nw83_60 _icon-only_1nw83_53" data-kind="primary" data-size="lg" role="button" diff --git a/src/room/__snapshots__/GroupCallErrorBoundary.test.tsx.snap b/src/room/__snapshots__/GroupCallErrorBoundary.test.tsx.snap index 0d2d39bce..92a6fe54f 100644 --- a/src/room/__snapshots__/GroupCallErrorBoundary.test.tsx.snap +++ b/src/room/__snapshots__/GroupCallErrorBoundary.test.tsx.snap @@ -134,7 +134,7 @@ exports[`ConnectionLostError: Action handling should reset error state 1`] = ` You were disconnected from the call.

-
From d4a3c8bd802526c0d1dff2d1727b3b6d276f2806 Mon Sep 17 00:00:00 2001 From: Timo K Date: Mon, 27 Apr 2026 13:56:40 +0200 Subject: [PATCH 592/748] Contributing.md update. Issue First policy --- .github/PULL_REQUEST_TEMPLATE.md | 29 ++++++++------ CONTRIBUTING.md | 68 ++++++++++++++++++++++++++++++++ 2 files changed, 86 insertions(+), 11 deletions(-) diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index 787ddc730..1c1111f7b 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -1,4 +1,11 @@ - + + +> [!IMPORTANT] +> **Features and UI changes require a pre-approved issue.** +> Every PR must have a linked issue +> that a maintainer has reviewed and approved **before you started writing code**. +> PRs that don't meet this requirement will not be reviewed. +> See [CONTRIBUTING.md](https://github.com/element-hq/element-call/blob/livekit/CONTRIBUTING.md) for ElementCall decided for this approach. ## Content @@ -6,34 +13,34 @@ ## Motivation and context - + ## Screenshots / GIFs + +--> ## Tests - + - Step 1 - Step 2 - Step ... -- ## Checklist -- [ ] I have read through [CONTRIBUTING.md](https://github.com/element-hq/element-call/blob/livekit/CONTRIBUTING.md). -- [ ] Pull request includes screenshots or videos if containing UI changes -- [ ] Tests written for new code (and old code if feasible). +- [ ] A linked, pre-approved issue exists for this feature or UI change. +- [ ] I have read [CONTRIBUTING.md](https://github.com/element-hq/element-call/blob/livekit/CONTRIBUTING.md) in full. +- [ ] Pull request includes screenshots or videos for any UI changes. +- [ ] Tests written for new code (and existing touched code where feasible). - [ ] Linter and other CI checks pass. - [ ] I have licensed the changes to Element by completing the [Contributor License Agreement (CLA)](https://cla-assistant.io/element-hq/element-call) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 0a4a6ac69..05b78455a 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,3 +1,71 @@ # Contributing code to Element Element follows the same pattern as the [matrix-js-sdk](https://github.com/matrix-org/matrix-js-sdk/blob/develop/CONTRIBUTING.md). + +# Contributing to Element Call + +Element Call is a native Matrix video conferencing application built on +[MatrixRTC (MSC4143)](https://github.com/matrix-org/matrix-spec-proposals/pull/4143) +and [LiveKit](https://livekit.io/). It runs in multiple deployment contexts — as a +standalone web app and as a widget embedded in Element Web, Element X iOS, and +Element X Android. It is also the primary R&D foundation for MatrixRTC, which means +its architecture, maintainability, and flexibility are held to a high standard. + +We welcome contributions from the community. This document explains how to +contribute effectively so that both you and the maintainers get the best outcome. + +## Issue First Policy + +> [!IMPORTANT] +> Before writing a single line of code for a new feature or UI change, you **must** +> open an issue and have the approach agreed with the maintainers. +> +> **We will not review or merge feature or UI pull requests that arrive without a +> corresponding, pre-approved issue.** + +This is not gatekeeping — it's how we prevent wasted effort on both sides. Element +Call must work correctly across multiple deployment contexts and meet specific product +and design requirements. It is also a fast-moving codebase that underpins ongoing +MatrixRTC development. A PR that looks reasonable in isolation can easily conflict +with in-progress work, planned architecture changes, or design decisions that haven't +been publicly documented yet. + +The issue is where we resolve all of that **before** anyone writes code. + +**Bug fixes** are no exception — most confirmed bugs should already have an issue anyways, existing issues that are marked as bugs have an implicit maintainer approval. If the solution for the bug is controversial it is highly recommended to discuss the approach in the issue before opening a PR. + +## Contribution Workflow + +1. **Open an issue** using the [Enhancement request](https://github.com/element-hq/element-call/issues/new?template=enhancement.yml) template. +2. **Wait for feedback.** A maintainer will discuss the use case and approach with you. + This may involve questions, suggestions, or a request to adjust scope. + This also allows to bring design and product into the loop before code gets created. +3. **Get a green light.** Wait for explicit approval from a maintainer before starting + implementation. +4. **Implement.** Write the code against the agreed approach. +5. **Open a PR.** Link to the issue in your PR description and satisfy the checklist + in the PR template. + +## Code Quality + +Element Call moves fast and the codebase must stay clean and maintainable. + +- **Take responsibility for AI-generated code.** AI tools can be a useful aid, but we expect all the generated code to be understood and reasoned about by the contributor. Questions by the maintainers should be answered without just forwarding them to AI. The maintainers also have access to AI tools. If your contribution is just transporting messages between LLM <-> maintaines all our time is better used if the maintainers decide to interact with AI for this specific problem by themselves. +- **Think across deployment contexts.** Changes must work correctly in both standalone + and widget modes. Consider how your change interacts with Element Web, Element X + iOS, and Element X Android. +- **Write tests.** New functionality should be covered by tests. Where it is feasible, + existing uncovered code touched by your PR should also gain tests. + +## Contributor License Agreement + +All contributors must sign the +[Element Contributor License Agreement](https://cla-assistant.io/element-hq/element-call) +before their contribution can be merged. The CLA assistant bot will prompt you +automatically when you open a PR. + +## Getting Help + +The best place to ask questions about Element Call development is the MatrixRTC room: + +**[#matrixRtc:matrix.org](https://matrix.to/#/#matrixrtc:matrix.org)** From 89281c6d702cb17c4b89edbdb1796c71df339935 Mon Sep 17 00:00:00 2001 From: Timo K Date: Mon, 27 Apr 2026 14:20:13 +0200 Subject: [PATCH 593/748] Refactor leveraging the fact, things blocking shortcuts are using react portals. --- src/room/InCallView.tsx | 1 - src/room/LobbyView.tsx | 6 ++++ src/useCallViewKeyboardShortcuts.ts | 52 ++++++++++++++++++++--------- 3 files changed, 43 insertions(+), 16 deletions(-) diff --git a/src/room/InCallView.tsx b/src/room/InCallView.tsx index 4940f4d83..d1cfdf10d 100644 --- a/src/room/InCallView.tsx +++ b/src/room/InCallView.tsx @@ -230,7 +230,6 @@ export const InCallView: FC = ({ // This function incorrectly assumes that there is a camera and microphone, which is not always the case. // TODO: Make sure that this module is resilient when it comes to camera/microphone availability! useCallViewKeyboardShortcuts( - containerRef1, toggleAudio, toggleVideo, setAudioEnabled, diff --git a/src/room/LobbyView.tsx b/src/room/LobbyView.tsx index 367dc8df5..e2d92126c 100644 --- a/src/room/LobbyView.tsx +++ b/src/room/LobbyView.tsx @@ -47,6 +47,7 @@ import { usePageTitle } from "../usePageTitle"; import { getValue } from "../utils/observable"; import { useBehavior } from "../useBehavior"; import { CallFooter } from "../components/CallFooter"; +import { useCallViewKeyboardShortcuts } from "../useCallViewKeyboardShortcuts"; interface Props { client: MatrixClient; @@ -91,6 +92,11 @@ export const LobbyView: FC = ({ const [settingsModalOpen, setSettingsModalOpen] = useState(false); const [settingsTab, setSettingsTab] = useState(defaultSettingsTab); + // This function incorrectly assumes that there is a camera and microphone, which is not always the case. + // TODO: Make sure that this module is resilient when it comes to camera/microphone availability! + // Next to the keyboard shortcuts, this is also responsible for catching escape key presses and forwarding the to mobile -> pip. + useCallViewKeyboardShortcuts(toggleAudio, toggleVideo, null, null, null); + const openSettings = useCallback( () => setSettingsModalOpen(true), [setSettingsModalOpen], diff --git a/src/useCallViewKeyboardShortcuts.ts b/src/useCallViewKeyboardShortcuts.ts index 3d9654be6..7eb66717f 100644 --- a/src/useCallViewKeyboardShortcuts.ts +++ b/src/useCallViewKeyboardShortcuts.ts @@ -6,6 +6,7 @@ Please see LICENSE in the repository root for full details. */ import { type RefObject, useCallback, useMemo, useRef } from "react"; +import { logger } from "matrix-js-sdk/lib/logger"; import { useEventTarget } from "./useEvents"; import { @@ -18,22 +19,46 @@ import { * Determines whether focus is in the same part of the tree as the given * element (specifically, if the element or an ancestor of it is focused). */ -const mayReceiveKeyEvents = (e: HTMLElement): boolean => { - const focusedElement = document.activeElement; - return focusedElement !== null && focusedElement.contains(e); +const mayReceiveKeyEvents = (): boolean => { + const root = document.getElementById("root"); + if (root === null) { + logger.warn( + "[mayReceiveKeyEvents] Root element not found, always allow keyboard shortcuts (m,v,esc...)", + ); + return true; + } + const focusElement = document.activeElement; + const nothingInFocus = focusElement === null; + const focusOnBody = focusElement === document.body; + const noPrimaryFocus = + nothingInFocus || root.contains(focusElement) || focusOnBody; + + // Only if we do not have a primary focus we allow keyboard shortcut events. + return noPrimaryFocus; }; const KeyToReactionMap: Record = Object.fromEntries( ReactionSet.slice(0, ReactionsRowSize).map((r, i) => [(i + 1).toString(), r]), ); +/** + * This hook sets up gloabl keyboard shortcuts. It will filter for keyboard presses that should be ignored due to user + * currently focussing on a modal. + * This is achieved by using the fact, that all modal inputs are outside the #root element and use react portals to get rendered. + * The following shortcuts are auspported (optional): + * @param toggleAudio - triggered on (m) + * @param toggleVideo - triggered on (v) + * @param setAudioEnabled - push to talk behavior controlled via (space) + * @param sendReaction - triggered on (1,2,3,...) + * @param toggleHandRaised - triggered on (h) + * Additionally this method listens to the (escape) key to trigger the onBackButtonPressed callback, which is used to navigate to pip in the native app. + */ export function useCallViewKeyboardShortcuts( - focusElement: RefObject, toggleAudio: (() => void) | null, toggleVideo: (() => void) | null, setAudioEnabled: ((enabled: boolean) => void) | null, - sendReaction: (reaction: ReactionOption) => void, - toggleHandRaised: () => void, + sendReaction: ((reaction: ReactionOption) => void) | null, + toggleHandRaised: (() => void) | null, ): void { const spacebarHeld = useRef(false); @@ -45,8 +70,8 @@ export function useCallViewKeyboardShortcuts( "keydown", useCallback( (event: KeyboardEvent) => { - if (focusElement.current === null) return; - if (!mayReceiveKeyEvents(focusElement.current)) return; + logger.info("Keydown event", event); + if (!mayReceiveKeyEvents()) return; if (event.altKey || event.ctrlKey || event.metaKey || event.shiftKey) return; @@ -64,16 +89,15 @@ export function useCallViewKeyboardShortcuts( } } else if (event.key === "h") { event.preventDefault(); - toggleHandRaised(); + toggleHandRaised?.(); } else if (KeyToReactionMap[event.key]) { event.preventDefault(); - sendReaction(KeyToReactionMap[event.key]); + sendReaction?.(KeyToReactionMap[event.key]); } else if (event.key === "Escape") { window.controls.onBackButtonPressed?.(); } }, [ - focusElement, toggleVideo, toggleAudio, setAudioEnabled, @@ -92,15 +116,13 @@ export function useCallViewKeyboardShortcuts( "keyup", useCallback( (event: KeyboardEvent) => { - if (focusElement.current === null) return; - if (!mayReceiveKeyEvents(focusElement.current)) return; - + if (!mayReceiveKeyEvents()) return; if (event.key === " ") { spacebarHeld.current = false; setAudioEnabled?.(false); } }, - [focusElement, setAudioEnabled], + [setAudioEnabled], ), ); From d335a307bb63ed8032d0ffeb175a95ff957165b4 Mon Sep 17 00:00:00 2001 From: Will Hunt <2072976+Half-Shot@users.noreply.github.com> Date: Mon, 27 Apr 2026 13:54:00 +0100 Subject: [PATCH 594/748] Update compound-web to 9.3.0 and update Buttons from "sm" to "md". (#3926) * Update compound-web to 9.3.0 and update Buttons from "sm" to "md". * Clean up the liast bits * Update snaps too * fix test, need to dismiss a new dialog --------- Co-authored-by: Valere --- package.json | 2 +- playwright/widget/test-helpers.ts | 17 +++++++++++++++++ pnpm-lock.yaml | 10 +++++----- src/RTCConnectionStats.tsx | 4 ++-- src/button/Button.tsx | 12 ++++++------ src/button/InviteButton.tsx | 2 +- src/button/ReactionToggleButton.tsx | 2 +- .../ReactionToggleButton.test.tsx.snap | 10 +++++----- src/components/CallFooter.tsx | 2 +- src/input/AvatarInputField.tsx | 4 ++-- src/room/EarpieceOverlay.tsx | 2 +- src/room/LobbyView.tsx | 2 +- .../GroupCallErrorBoundary.test.tsx.snap | 18 +++++++++--------- .../__snapshots__/InCallView.test.tsx.snap | 12 ++++++------ 14 files changed, 58 insertions(+), 41 deletions(-) diff --git a/package.json b/package.json index a6601382b..f2548099a 100644 --- a/package.json +++ b/package.json @@ -81,7 +81,7 @@ "@typescript-eslint/parser": "^8.31.0", "@use-gesture/react": "^10.2.11", "@vector-im/compound-design-tokens": "^10.0.0", - "@vector-im/compound-web": "^9.0.0", + "@vector-im/compound-web": "^9.3.0", "@vitejs/plugin-react": "^4.0.1", "@vitest/coverage-v8": "^4.0.18", "babel-plugin-transform-vite-meta-env": "^1.0.3", diff --git a/playwright/widget/test-helpers.ts b/playwright/widget/test-helpers.ts index b47588ce7..9167412e0 100644 --- a/playwright/widget/test-helpers.ts +++ b/playwright/widget/test-helpers.ts @@ -122,6 +122,7 @@ export class TestHelpers { await this.maybeDismissBrowserNotSupportedToast(page); await this.maybeDismissServiceWorkerWarningToast(page); + await this.maybeDismissBackupChat(page); await TestHelpers.setDevToolElementCallDevUrl(page); @@ -170,6 +171,22 @@ export class TestHelpers { } } + private static async maybeDismissBackupChat(page: Page): Promise { + const toast = page + .locator(".mx_Toast_toast") + .getByText("Back up your chats"); + + try { + await expect(toast).toBeVisible({ timeout: 700 }); + await page + .locator(".mx_Toast_toast") + .getByRole("button", { name: "Dismiss" }) + .click(); + } catch { + // toast not visible, continue as normal + } + } + public static async maybeDismissKeyBackupToast(page: Page): Promise { const toast = page .locator(".mx_Toast_toast") diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index ce574ca34..84f0a087f 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -148,8 +148,8 @@ importers: specifier: ^10.0.0 version: 10.1.0(@types/react@19.2.14)(react@19.2.5) '@vector-im/compound-web': - specifier: ^9.0.0 - version: 9.2.0(@fontsource/inconsolata@5.2.8)(@fontsource/inter@5.2.8)(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(@vector-im/compound-design-tokens@10.1.0(@types/react@19.2.14)(react@19.2.5))(react-dom@19.2.5(react@19.2.5))(react@19.2.5) + specifier: ^9.3.0 + version: 9.3.0(@fontsource/inconsolata@5.2.8)(@fontsource/inter@5.2.8)(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(@vector-im/compound-design-tokens@10.1.0(@types/react@19.2.14)(react@19.2.5))(react-dom@19.2.5(react@19.2.5))(react@19.2.5) '@vitejs/plugin-react': specifier: ^4.0.1 version: 4.7.0(vite@8.0.8(@types/node@24.12.2)(esbuild@0.27.7)(jiti@2.6.1)(sass@1.99.0)(terser@5.46.1)(yaml@2.8.3)) @@ -3105,8 +3105,8 @@ packages: react: optional: true - '@vector-im/compound-web@9.2.0': - resolution: {integrity: sha512-jHbABGEQ2yqNtm5xRIkklQs198VEfSk9AJQolI+e4WSJ0xg8Ozyv9t9KIuKQAmjdSV9aow5G6hDE861XB6DQgw==} + '@vector-im/compound-web@9.3.0': + resolution: {integrity: sha512-Elu4Uw8RbfP6JaudQYkVibALYT6qpwubqfKhteTxIPWBWzSYM+P5T+B1uX+ra+grNcXwXUt2xfMxpqYQsAHgYA==} peerDependencies: '@fontsource/inconsolata': ^5 '@fontsource/inter': ^5 @@ -9596,7 +9596,7 @@ snapshots: '@types/react': 19.2.14 react: 19.2.5 - '@vector-im/compound-web@9.2.0(@fontsource/inconsolata@5.2.8)(@fontsource/inter@5.2.8)(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(@vector-im/compound-design-tokens@10.1.0(@types/react@19.2.14)(react@19.2.5))(react-dom@19.2.5(react@19.2.5))(react@19.2.5)': + '@vector-im/compound-web@9.3.0(@fontsource/inconsolata@5.2.8)(@fontsource/inter@5.2.8)(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(@vector-im/compound-design-tokens@10.1.0(@types/react@19.2.14)(react@19.2.5))(react-dom@19.2.5(react@19.2.5))(react@19.2.5)': dependencies: '@floating-ui/react': 0.27.19(react-dom@19.2.5(react@19.2.5))(react@19.2.5) '@fontsource/inconsolata': 5.2.8 diff --git a/src/RTCConnectionStats.tsx b/src/RTCConnectionStats.tsx index f62a1e4d1..ea9df3f5e 100644 --- a/src/RTCConnectionStats.tsx +++ b/src/RTCConnectionStats.tsx @@ -87,7 +87,7 @@ export const RTCConnectionStats: FC = ({
); diff --git a/src/button/ReactionToggleButton.tsx b/src/button/ReactionToggleButton.tsx index 39804a5f8..c71642e97 100644 --- a/src/button/ReactionToggleButton.tsx +++ b/src/button/ReactionToggleButton.tsx @@ -173,7 +173,7 @@ export interface ReactionData { interface ReactionToggleButtonProps extends ComponentPropsWithoutRef<"button"> { reactionData: ReactionData; identifier: string; - size?: "sm" | "lg"; + size?: "md" | "lg"; /** List of participants raising their hand */ } diff --git a/src/button/__snapshots__/ReactionToggleButton.test.tsx.snap b/src/button/__snapshots__/ReactionToggleButton.test.tsx.snap index 608c1a0fc..a1e319d95 100644 --- a/src/button/__snapshots__/ReactionToggleButton.test.tsx.snap +++ b/src/button/__snapshots__/ReactionToggleButton.test.tsx.snap @@ -10,7 +10,7 @@ exports[`Can close reaction dialog 1`] = ` aria-expanded="true" aria-haspopup="true" aria-labelledby="_r_bb_" - class="_button_13vu4_8 _has-icon_13vu4_60 _icon-only_13vu4_53" + class="_button_1nw83_8 _has-icon_1nw83_60 _icon-only_1nw83_53" data-kind="primary" data-size="lg" role="button" @@ -44,7 +44,7 @@ exports[`Can fully expand emoji picker 1`] = ` aria-expanded="true" aria-haspopup="true" aria-labelledby="_r_7m_" - class="_button_13vu4_8 _has-icon_13vu4_60 _icon-only_13vu4_53" + class="_button_1nw83_8 _has-icon_1nw83_60 _icon-only_1nw83_53" data-kind="primary" data-size="lg" role="button" @@ -75,7 +75,7 @@ exports[`Can lower hand 1`] = ` aria-expanded="false" aria-haspopup="true" aria-labelledby="_r_36_" - class="_button_13vu4_8 _has-icon_13vu4_60 _icon-only_13vu4_53" + class="_button_1nw83_8 _has-icon_1nw83_60 _icon-only_1nw83_53" data-kind="secondary" data-size="lg" role="button" @@ -109,7 +109,7 @@ exports[`Can open menu 1`] = ` aria-expanded="true" aria-haspopup="true" aria-labelledby="_r_0_" - class="_button_13vu4_8 _has-icon_13vu4_60 _icon-only_13vu4_53" + class="_button_1nw83_8 _has-icon_1nw83_60 _icon-only_1nw83_53" data-kind="primary" data-size="lg" role="button" @@ -140,7 +140,7 @@ exports[`Can raise hand 1`] = ` aria-expanded="false" aria-haspopup="true" aria-labelledby="_r_1j_" - class="_button_13vu4_8 raisedButton _has-icon_13vu4_60 _icon-only_13vu4_53" + class="_button_1nw83_8 raisedButton _has-icon_1nw83_60 _icon-only_1nw83_53" data-kind="primary" data-size="lg" role="button" diff --git a/src/components/CallFooter.tsx b/src/components/CallFooter.tsx index 4e728d3b7..fdedf36c6 100644 --- a/src/components/CallFooter.tsx +++ b/src/components/CallFooter.tsx @@ -101,7 +101,7 @@ export const CallFooter: FC = ({ tileStoreGeneration, }) => { const buttons: JSX.Element[] = []; - const buttonSize = asPip ? "sm" : "lg"; + const buttonSize = asPip ? "md" : "lg"; const showSettingsButton = openSettings !== undefined && !asPip && !hideControls; const showLayoutSwitcher = !asPip && !hideControls; diff --git a/src/input/AvatarInputField.tsx b/src/input/AvatarInputField.tsx index 4a3173b40..f9b147076 100644 --- a/src/input/AvatarInputField.tsx +++ b/src/input/AvatarInputField.tsx @@ -113,7 +113,7 @@ export const AvatarInputField: FC = ({ iconOnly Icon={EditIcon} kind="tertiary" - size="sm" + size="md" aria-label={t("action.edit")} /> } @@ -136,7 +136,7 @@ export const AvatarInputField: FC = ({ iconOnly Icon={EditIcon} kind="tertiary" - size="sm" + size="md" aria-label={t("action.edit")} onClick={onSelectUpload} /> diff --git a/src/room/EarpieceOverlay.tsx b/src/room/EarpieceOverlay.tsx index 6835bdd7a..574792f0a 100644 --- a/src/room/EarpieceOverlay.tsx +++ b/src/room/EarpieceOverlay.tsx @@ -30,7 +30,7 @@ export const EarpieceOverlay: FC = ({ show, onBackToVideoPressed }) => { {t("handset.overlay_description")} + <> +
+ +
+ {/*// modal lives outside of the root*/} {modalOpen && ( = ({ )} -
+ ); }; @@ -164,12 +165,13 @@ test("unmuting happens in place of the default action", async () => { // container element that can be interactive and receive focus / keydown // events.