@q9labsai/chalk-react 4.1.2 → 4.1.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{chunk-FTWI75A2.js → chunk-4SU35WSH.js} +59 -6
- package/dist/components/index.js +1 -1
- package/dist/index.js +1 -1
- package/dist/internal/sound-cues.d.ts +5 -1
- package/dist/internal/sound-cues.d.ts.map +1 -1
- package/dist/internal/useSoundCues.d.ts +4 -2
- package/dist/internal/useSoundCues.d.ts.map +1 -1
- package/package.json +5 -5
|
@@ -9661,15 +9661,64 @@ function diffSoundCues(previous, next) {
|
|
|
9661
9661
|
}
|
|
9662
9662
|
return cues;
|
|
9663
9663
|
}
|
|
9664
|
+
var AUTOPLAY_UNLOCK_EVENTS = ["pointerdown", "touchend", "click", "keydown"];
|
|
9665
|
+
function isAutoplayBlocked(cause) {
|
|
9666
|
+
return typeof DOMException !== "undefined" && cause instanceof DOMException && cause.name === "NotAllowedError";
|
|
9667
|
+
}
|
|
9668
|
+
function supportsSinkSelection(element) {
|
|
9669
|
+
return "setSinkId" in element && typeof element.setSinkId === "function";
|
|
9670
|
+
}
|
|
9664
9671
|
function soundSourceFor(cue, canPlay) {
|
|
9665
9672
|
const asset = CHALK_SOUND_ASSETS[cue];
|
|
9666
9673
|
return canPlay(asset.opus.mimeType) ? asset.opus.url : asset.mp3.url;
|
|
9667
9674
|
}
|
|
9668
|
-
function createSoundPlayer({ volume = 0.6, onError } = {}) {
|
|
9675
|
+
function createSoundPlayer({ volume = 0.6, outputDeviceId, onError, unlockTarget = typeof window === "undefined" ? null : window } = {}) {
|
|
9669
9676
|
const elements = /* @__PURE__ */ new Map();
|
|
9670
9677
|
const lastPlayed = /* @__PURE__ */ new Map();
|
|
9678
|
+
const blocked = /* @__PURE__ */ new Set();
|
|
9679
|
+
const playbackInFlight = /* @__PURE__ */ new Set();
|
|
9671
9680
|
const probe = typeof Audio === "undefined" ? null : new Audio();
|
|
9672
9681
|
const canPlay = (mimeType) => probe !== null && probe.canPlayType(mimeType) !== "";
|
|
9682
|
+
let listeningForUnlock = false;
|
|
9683
|
+
const removeUnlockListeners = () => {
|
|
9684
|
+
if (!unlockTarget || !listeningForUnlock) return;
|
|
9685
|
+
for (const event of AUTOPLAY_UNLOCK_EVENTS) unlockTarget.removeEventListener(event, retryBlocked, true);
|
|
9686
|
+
listeningForUnlock = false;
|
|
9687
|
+
};
|
|
9688
|
+
const addUnlockListeners = () => {
|
|
9689
|
+
if (!unlockTarget || listeningForUnlock) return;
|
|
9690
|
+
for (const event of AUTOPLAY_UNLOCK_EVENTS) unlockTarget.addEventListener(event, retryBlocked, { capture: true, passive: true });
|
|
9691
|
+
listeningForUnlock = true;
|
|
9692
|
+
};
|
|
9693
|
+
const reportPlaybackFailure = (cue, cause) => {
|
|
9694
|
+
if (isAutoplayBlocked(cause)) {
|
|
9695
|
+
blocked.add(cue);
|
|
9696
|
+
addUnlockListeners();
|
|
9697
|
+
}
|
|
9698
|
+
onError?.(cue, cause);
|
|
9699
|
+
};
|
|
9700
|
+
const playElement = (cue, element) => {
|
|
9701
|
+
if (playbackInFlight.has(cue)) return;
|
|
9702
|
+
playbackInFlight.add(cue);
|
|
9703
|
+
element.currentTime = 0;
|
|
9704
|
+
element.play().then(
|
|
9705
|
+
() => {
|
|
9706
|
+
playbackInFlight.delete(cue);
|
|
9707
|
+
blocked.delete(cue);
|
|
9708
|
+
if (blocked.size === 0) removeUnlockListeners();
|
|
9709
|
+
},
|
|
9710
|
+
(cause) => {
|
|
9711
|
+
playbackInFlight.delete(cue);
|
|
9712
|
+
reportPlaybackFailure(cue, cause);
|
|
9713
|
+
}
|
|
9714
|
+
);
|
|
9715
|
+
};
|
|
9716
|
+
function retryBlocked() {
|
|
9717
|
+
for (const cue of blocked) {
|
|
9718
|
+
const element = elements.get(cue);
|
|
9719
|
+
if (element) playElement(cue, element);
|
|
9720
|
+
}
|
|
9721
|
+
}
|
|
9673
9722
|
return {
|
|
9674
9723
|
play: (cue) => {
|
|
9675
9724
|
if (probe === null) return;
|
|
@@ -9681,12 +9730,15 @@ function createSoundPlayer({ volume = 0.6, onError } = {}) {
|
|
|
9681
9730
|
element = new Audio(soundSourceFor(cue, canPlay));
|
|
9682
9731
|
element.preload = "auto";
|
|
9683
9732
|
element.volume = volume;
|
|
9733
|
+
if (outputDeviceId && supportsSinkSelection(element) && element.sinkId !== outputDeviceId) void element.setSinkId(outputDeviceId).catch(() => void 0);
|
|
9684
9734
|
elements.set(cue, element);
|
|
9685
9735
|
}
|
|
9686
|
-
element
|
|
9687
|
-
element.play().catch((cause) => onError?.(cue, cause));
|
|
9736
|
+
playElement(cue, element);
|
|
9688
9737
|
},
|
|
9689
9738
|
dispose: () => {
|
|
9739
|
+
removeUnlockListeners();
|
|
9740
|
+
blocked.clear();
|
|
9741
|
+
playbackInFlight.clear();
|
|
9690
9742
|
for (const element of elements.values()) {
|
|
9691
9743
|
element.pause();
|
|
9692
9744
|
element.removeAttribute("src");
|
|
@@ -9697,13 +9749,14 @@ function createSoundPlayer({ volume = 0.6, onError } = {}) {
|
|
|
9697
9749
|
}
|
|
9698
9750
|
|
|
9699
9751
|
// src/internal/useSoundCues.ts
|
|
9700
|
-
function useSoundCues(enabled, createPlayer =
|
|
9752
|
+
function useSoundCues(enabled, createPlayer = createSoundPlayer) {
|
|
9701
9753
|
const client = useSpaceClient();
|
|
9754
|
+
const outputDeviceId = useMedia().selection.speaker ?? void 0;
|
|
9702
9755
|
const createPlayerRef = useRef20(createPlayer);
|
|
9703
9756
|
createPlayerRef.current = createPlayer;
|
|
9704
9757
|
useEffect32(() => {
|
|
9705
9758
|
if (!enabled) return;
|
|
9706
|
-
const player = createPlayerRef.current();
|
|
9759
|
+
const player = createPlayerRef.current({ outputDeviceId });
|
|
9707
9760
|
let previous = client.getSnapshot();
|
|
9708
9761
|
const unsubscribe = client.subscribe(() => {
|
|
9709
9762
|
const next = client.getSnapshot();
|
|
@@ -9714,7 +9767,7 @@ function useSoundCues(enabled, createPlayer = () => createSoundPlayer()) {
|
|
|
9714
9767
|
unsubscribe();
|
|
9715
9768
|
player.dispose();
|
|
9716
9769
|
};
|
|
9717
|
-
}, [client, enabled]);
|
|
9770
|
+
}, [client, enabled, outputDeviceId]);
|
|
9718
9771
|
}
|
|
9719
9772
|
|
|
9720
9773
|
// src/components/composite/ReactionPicker.tsx
|
package/dist/components/index.js
CHANGED
package/dist/index.js
CHANGED
|
@@ -15,14 +15,18 @@ export interface SoundPlayer {
|
|
|
15
15
|
readonly play: (cue: SoundCue) => void;
|
|
16
16
|
readonly dispose: () => void;
|
|
17
17
|
}
|
|
18
|
+
type SoundUnlockTarget = Pick<EventTarget, "addEventListener" | "removeEventListener">;
|
|
18
19
|
/** Picks the Opus file when the browser can decode it, otherwise the MP3. */
|
|
19
20
|
export declare function soundSourceFor(cue: SoundCue, canPlay: (mimeType: string) => boolean): string;
|
|
20
21
|
/**
|
|
21
22
|
* Lazily creates one `HTMLAudioElement` per cue and replays it from the start. Playback failures
|
|
22
23
|
* (autoplay policy before the first gesture, network) are reported through `onError` and never thrown.
|
|
23
24
|
*/
|
|
24
|
-
export declare function createSoundPlayer({ volume, onError }?: {
|
|
25
|
+
export declare function createSoundPlayer({ volume, outputDeviceId, onError, unlockTarget }?: {
|
|
25
26
|
volume?: number;
|
|
27
|
+
outputDeviceId?: string;
|
|
26
28
|
onError?: (cue: SoundCue, cause: unknown) => void;
|
|
29
|
+
unlockTarget?: SoundUnlockTarget | null;
|
|
27
30
|
}): SoundPlayer;
|
|
31
|
+
export {};
|
|
28
32
|
//# sourceMappingURL=sound-cues.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sound-cues.d.ts","sourceRoot":"","sources":["../../src/internal/sound-cues.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AAC5D,OAAO,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AAE/D,MAAM,MAAM,QAAQ,GAAG,MAAM,OAAO,kBAAkB,CAAC;AAEvD,qFAAqF;AACrF,eAAO,MAAM,mBAAmB,iEAAgG,CAAC;AAEjI,8GAA8G;AAC9G,eAAO,MAAM,eAAe,MAAM,CAAC;AAMnC;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,QAAQ,EAAE,aAAa,EAAE,IAAI,EAAE,aAAa,GAAG,SAAS,QAAQ,EAAE,CA2B/F;AAED,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,IAAI,EAAE,CAAC,GAAG,EAAE,QAAQ,KAAK,IAAI,CAAC;IACvC,QAAQ,CAAC,OAAO,EAAE,MAAM,IAAI,CAAC;CAC9B;
|
|
1
|
+
{"version":3,"file":"sound-cues.d.ts","sourceRoot":"","sources":["../../src/internal/sound-cues.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AAC5D,OAAO,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AAE/D,MAAM,MAAM,QAAQ,GAAG,MAAM,OAAO,kBAAkB,CAAC;AAEvD,qFAAqF;AACrF,eAAO,MAAM,mBAAmB,iEAAgG,CAAC;AAEjI,8GAA8G;AAC9G,eAAO,MAAM,eAAe,MAAM,CAAC;AAMnC;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,QAAQ,EAAE,aAAa,EAAE,IAAI,EAAE,aAAa,GAAG,SAAS,QAAQ,EAAE,CA2B/F;AAED,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,IAAI,EAAE,CAAC,GAAG,EAAE,QAAQ,KAAK,IAAI,CAAC;IACvC,QAAQ,CAAC,OAAO,EAAE,MAAM,IAAI,CAAC;CAC9B;AASD,KAAK,iBAAiB,GAAG,IAAI,CAAC,WAAW,EAAE,kBAAkB,GAAG,qBAAqB,CAAC,CAAC;AAUvF,6EAA6E;AAC7E,wBAAgB,cAAc,CAAC,GAAG,EAAE,QAAQ,EAAE,OAAO,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,OAAO,GAAG,MAAM,CAG5F;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,EAAE,MAAY,EAAE,cAAc,EAAE,OAAO,EAAE,YAA4D,EAAE,GAAE;IAAE,MAAM,CAAC,EAAE,MAAM,CAAC;IAAC,cAAc,CAAC,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC,GAAG,EAAE,QAAQ,EAAE,KAAK,EAAE,OAAO,KAAK,IAAI,CAAC;IAAC,YAAY,CAAC,EAAE,iBAAiB,GAAG,IAAI,CAAA;CAAO,GAAG,WAAW,CAgFrS"}
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import { type SoundPlayer } from "./sound-cues";
|
|
2
2
|
/**
|
|
3
3
|
* Plays the join / leave / message / hand-raise / reaction cues for snapshot changes on the
|
|
4
|
-
* current client while `enabled`. Autoplay refusals
|
|
4
|
+
* current client while `enabled`. Autoplay refusals are retried after the next user gesture.
|
|
5
5
|
*/
|
|
6
|
-
export declare function useSoundCues(enabled: boolean, createPlayer?: (
|
|
6
|
+
export declare function useSoundCues(enabled: boolean, createPlayer?: (options: {
|
|
7
|
+
readonly outputDeviceId?: string;
|
|
8
|
+
}) => SoundPlayer): void;
|
|
7
9
|
//# sourceMappingURL=useSoundCues.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useSoundCues.d.ts","sourceRoot":"","sources":["../../src/internal/useSoundCues.ts"],"names":[],"mappings":"AAGA,OAAO,EAAoC,KAAK,WAAW,EAAE,MAAM,cAAc,CAAC;AAElF;;;GAGG;AACH,wBAAgB,YAAY,CAAC,OAAO,EAAE,OAAO,EAAE,YAAY,GAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"useSoundCues.d.ts","sourceRoot":"","sources":["../../src/internal/useSoundCues.ts"],"names":[],"mappings":"AAGA,OAAO,EAAoC,KAAK,WAAW,EAAE,MAAM,cAAc,CAAC;AAElF;;;GAGG;AACH,wBAAgB,YAAY,CAAC,OAAO,EAAE,OAAO,EAAE,YAAY,GAAE,CAAC,OAAO,EAAE;IAAE,QAAQ,CAAC,cAAc,CAAC,EAAE,MAAM,CAAA;CAAE,KAAK,WAA+B,GAAG,IAAI,CAoBrJ"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@q9labsai/chalk-react",
|
|
3
|
-
"version": "4.1.
|
|
3
|
+
"version": "4.1.3",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -61,10 +61,10 @@
|
|
|
61
61
|
"@base-ui/react": "^1.7.0",
|
|
62
62
|
"@hugeicons/core-free-icons": "^4.2.3",
|
|
63
63
|
"@hugeicons/react": "^1.1.9",
|
|
64
|
-
"@q9labsai/chalk-client": "^4.1.
|
|
65
|
-
"@q9labsai/chalk-ui": "^4.1.
|
|
66
|
-
"@q9labsai/chalk-whiteboard": "^4.1.
|
|
67
|
-
"@q9labsai/facehash": "^4.1.
|
|
64
|
+
"@q9labsai/chalk-client": "^4.1.3",
|
|
65
|
+
"@q9labsai/chalk-ui": "^4.1.3",
|
|
66
|
+
"@q9labsai/chalk-whiteboard": "^4.1.3",
|
|
67
|
+
"@q9labsai/facehash": "^4.1.3",
|
|
68
68
|
"class-variance-authority": "^0.7.1",
|
|
69
69
|
"clsx": "^2.1.1",
|
|
70
70
|
"sonner": "^2.0.8",
|