@q9labsai/chalk-react 4.1.12 → 4.1.13

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.
@@ -8582,6 +8582,9 @@ import { useCallback as useCallback19, useEffect as useEffect55, useMemo as useM
8582
8582
  // src/internal/useWhiteboardSceneSubscription.ts
8583
8583
  import { useEffect as useEffect31, useState as useState37 } from "react";
8584
8584
  var errorMessage = (cause) => cause instanceof Error ? cause : new Error("Whiteboard could not connect.");
8585
+ var summaryError = (summary) => summary.error ? new Error(summary.error.message) : errorMessage(void 0);
8586
+ var MAX_RECOVERY_ATTEMPTS = 3;
8587
+ var recoveryDelayMs = (attempt) => 250 * 2 ** attempt;
8585
8588
  function useWhiteboardSceneSubscription(transport, active) {
8586
8589
  const [subscription, setSubscription] = useState37({ status: "closed" });
8587
8590
  useEffect31(() => {
@@ -8590,17 +8593,84 @@ function useWhiteboardSceneSubscription(transport, active) {
8590
8593
  return;
8591
8594
  }
8592
8595
  let disposed = false;
8593
- setSubscription({ status: "loading" });
8594
- void Promise.resolve().then(() => transport.startSceneSubscription()).then(
8595
- () => {
8596
- if (!disposed) setSubscription({ status: "ready", transport });
8597
- },
8598
- (cause) => {
8599
- if (!disposed) setSubscription({ status: "failed", error: errorMessage(cause) });
8596
+ let starting = false;
8597
+ let startupSettled = false;
8598
+ let recoveryAttempts = 0;
8599
+ let recoveryTimer;
8600
+ let latestSummary;
8601
+ const observesSummary = transport.subscribeSummary !== void 0;
8602
+ const clearRecoveryTimer = () => {
8603
+ if (recoveryTimer === void 0) return;
8604
+ globalThis.clearTimeout(recoveryTimer);
8605
+ recoveryTimer = void 0;
8606
+ };
8607
+ const recover = (cause) => {
8608
+ if (disposed || recoveryTimer !== void 0 || starting) return;
8609
+ if (recoveryAttempts >= MAX_RECOVERY_ATTEMPTS) {
8610
+ setSubscription({ status: "failed", error: errorMessage(cause) });
8611
+ return;
8600
8612
  }
8601
- );
8613
+ const attempt = recoveryAttempts++;
8614
+ setSubscription({ status: "loading" });
8615
+ recoveryTimer = globalThis.setTimeout(() => {
8616
+ recoveryTimer = void 0;
8617
+ start();
8618
+ }, recoveryDelayMs(attempt));
8619
+ };
8620
+ const handleSummary = (summary) => {
8621
+ latestSummary = summary;
8622
+ if (disposed) return;
8623
+ if (summary.status === "unsubscribed") {
8624
+ setSubscription({ status: "loading" });
8625
+ return;
8626
+ }
8627
+ if (summary.status === "ready") {
8628
+ if (!starting || startupSettled) {
8629
+ recoveryAttempts = 0;
8630
+ setSubscription({ status: "ready", transport });
8631
+ }
8632
+ return;
8633
+ }
8634
+ if (summary.status === "loading" || summary.status === "recovering") {
8635
+ setSubscription({ status: "loading" });
8636
+ return;
8637
+ }
8638
+ if (summary.status === "failed") {
8639
+ starting = false;
8640
+ setSubscription({ status: "loading" });
8641
+ recover(summaryError(summary));
8642
+ }
8643
+ };
8644
+ const start = () => {
8645
+ if (disposed || starting) return;
8646
+ clearRecoveryTimer();
8647
+ starting = true;
8648
+ startupSettled = false;
8649
+ setSubscription({ status: "loading" });
8650
+ void Promise.resolve().then(() => transport.startSceneSubscription()).then(
8651
+ () => {
8652
+ starting = false;
8653
+ startupSettled = true;
8654
+ if (disposed) return;
8655
+ if (!latestSummary || latestSummary.status === "ready") {
8656
+ recoveryAttempts = 0;
8657
+ setSubscription({ status: "ready", transport });
8658
+ }
8659
+ },
8660
+ (cause) => {
8661
+ starting = false;
8662
+ if (!disposed && observesSummary) recover(cause);
8663
+ else if (!disposed) setSubscription({ status: "failed", error: errorMessage(cause) });
8664
+ }
8665
+ );
8666
+ };
8667
+ setSubscription({ status: "loading" });
8668
+ const unsubscribeSummary = transport.subscribeSummary?.(handleSummary);
8669
+ start();
8602
8670
  return () => {
8603
8671
  disposed = true;
8672
+ clearRecoveryTimer();
8673
+ unsubscribeSummary?.();
8604
8674
  void Promise.resolve(transport.stopSceneSubscription());
8605
8675
  };
8606
8676
  }, [active, transport]);
@@ -36,7 +36,7 @@ import {
36
36
  SettingsPanel,
37
37
  Stage,
38
38
  buildStageItems
39
- } from "../chunk-5PRGSL4M.js";
39
+ } from "../chunk-4X3NFZGL.js";
40
40
  import "../chunk-A3L7BOCE.js";
41
41
  export {
42
42
  AdmissionPanel,
package/dist/index.js CHANGED
@@ -36,7 +36,7 @@ import {
36
36
  useSelf,
37
37
  useSpaceClient,
38
38
  useWhiteboard
39
- } from "./chunk-5PRGSL4M.js";
39
+ } from "./chunk-4X3NFZGL.js";
40
40
  import "./chunk-A3L7BOCE.js";
41
41
  export {
42
42
  COSMIC_CHALK_THEME,
@@ -1 +1 @@
1
- {"version":3,"file":"useWhiteboardSceneSubscription.d.ts","sourceRoot":"","sources":["../../src/internal/useWhiteboardSceneSubscription.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,wBAAwB,CAAC;AAGzE,KAAK,2BAA2B,GAAG;IAAE,QAAQ,CAAC,MAAM,EAAE,QAAQ,GAAG,SAAS,CAAA;CAAE,GAAG;IAAE,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC;IAAC,QAAQ,CAAC,SAAS,EAAE,0BAA0B,CAAA;CAAE,GAAG;IAAE,QAAQ,CAAC,MAAM,EAAE,QAAQ,CAAC;IAAC,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAA;CAAE,CAAC;AAInN,wBAAgB,8BAA8B,CAAC,SAAS,EAAE,0BAA0B,GAAG,IAAI,EAAE,MAAM,EAAE,OAAO,GAAG,2BAA2B,CA6BzI"}
1
+ {"version":3,"file":"useWhiteboardSceneSubscription.d.ts","sourceRoot":"","sources":["../../src/internal/useWhiteboardSceneSubscription.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAA0B,0BAA0B,EAAE,MAAM,wBAAwB,CAAC;AAGjG,KAAK,2BAA2B,GAAG;IAAE,QAAQ,CAAC,MAAM,EAAE,QAAQ,GAAG,SAAS,CAAA;CAAE,GAAG;IAAE,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC;IAAC,QAAQ,CAAC,SAAS,EAAE,0BAA0B,CAAA;CAAE,GAAG;IAAE,QAAQ,CAAC,MAAM,EAAE,QAAQ,CAAC;IAAC,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAA;CAAE,CAAC;AAOnN,wBAAgB,8BAA8B,CAAC,SAAS,EAAE,0BAA0B,GAAG,IAAI,EAAE,MAAM,EAAE,OAAO,GAAG,2BAA2B,CAqGzI"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@q9labsai/chalk-react",
3
- "version": "4.1.12",
3
+ "version": "4.1.13",
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.12",
65
- "@q9labsai/chalk-ui": "^4.1.12",
66
- "@q9labsai/chalk-whiteboard": "^4.1.12",
67
- "@q9labsai/facehash": "^4.1.12",
64
+ "@q9labsai/chalk-client": "^4.1.13",
65
+ "@q9labsai/chalk-ui": "^4.1.13",
66
+ "@q9labsai/chalk-whiteboard": "^4.1.13",
67
+ "@q9labsai/facehash": "^4.1.13",
68
68
  "class-variance-authority": "^0.7.1",
69
69
  "clsx": "^2.1.1",
70
70
  "qrcode.react": "^4.2.0",
@@ -72,22 +72,12 @@
72
72
  "tailwind-merge": "^3.6.0"
73
73
  },
74
74
  "devDependencies": {
75
- "@testing-library/dom": "^10.4.1",
76
- "@testing-library/jest-dom": "^7.0.1",
77
- "@testing-library/react": "^16.3.2",
78
- "@testing-library/user-event": "^14.6.4",
79
75
  "@types/node": "^26.2.0",
80
76
  "@types/react": "^19.2.18",
81
77
  "@types/react-dom": "^19.2.4",
82
- "@vitest/browser-playwright": "^4.1.10",
83
- "@vitest/coverage-v8": "^4.1.10",
84
- "happy-dom": "^20.11.2",
85
- "jsdom": "^30.0.1",
86
- "playwright": "^1.62.1",
87
78
  "react": "19.2.7",
88
79
  "react-dom": "19.2.7",
89
- "typescript": "^7.0.2",
90
- "vitest": "^4.1.10"
80
+ "typescript": "^7.0.2"
91
81
  },
92
82
  "peerDependencies": {
93
83
  "react": "^18.0.0 || ^19.0.0",
@@ -100,7 +90,6 @@
100
90
  "build:fix-use-client": "node -e \"const fs=require('fs');const files=['./dist/index.js','./dist/components/index.js','./dist/components/ui/index.js','./dist/utils/index.js'];for(const f of files){if(!fs.existsSync(f))continue;let c=fs.readFileSync(f,'utf8');c=c.replace(/['\\\"]use client['\\\"];?\\n?/g,'');c='\\\"use client\\\";\\n'+c;fs.writeFileSync(f,c);}\"",
101
91
  "build:types": "rm -f tsconfig.tsbuildinfo && tsc --build tsconfig.json",
102
92
  "dev": "tsup ./src/index.ts ./src/components/index.ts ./src/components/ui/index.ts ./src/utils/index.ts --format esm --out-dir ./dist --platform browser --external react --external react-dom --external @base-ui/react --external @hugeicons/core-free-icons --external @hugeicons/react --external @q9labsai/chalk-client --external @q9labsai/chalk-ui --external @q9labsai/chalk-ui/reactions --external @q9labsai/chalk-ui/assets --external @q9labsai/chalk-whiteboard --external @q9labsai/facehash --external @q9labsai/facehash/react --external class-variance-authority --external clsx --external sonner --external tailwind-merge --watch",
103
- "test": "pnpm exec vitest run --config ./vitest.config.ts",
104
93
  "check-types": "tsc --project tsconfig.check-types.json --noEmit",
105
94
  "lint": "pnpm run check:tokens && pnpm exec oxfmt --check . && tsc --project tsconfig.check-types.json --noEmit",
106
95
  "check:tokens": "node ./scripts/check-token-reach.mjs",
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=setup.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"setup.d.ts","sourceRoot":"","sources":["../../src/__tests__/setup.ts"],"names":[],"mappings":""}
@@ -1,33 +0,0 @@
1
- /** Minimal MediaStreamTrack stand-in for DOM tests: real event dispatch, no media. */
2
- declare class FakeMediaStreamTrack extends EventTarget implements MediaStreamTrack {
3
- contentHint: string;
4
- enabled: boolean;
5
- readonly id: string;
6
- readonly kind: string;
7
- readonly label = "fake";
8
- muted: boolean;
9
- onended: ((this: MediaStreamTrack, ev: Event) => unknown) | null;
10
- onmute: ((this: MediaStreamTrack, ev: Event) => unknown) | null;
11
- onunmute: ((this: MediaStreamTrack, ev: Event) => unknown) | null;
12
- readyState: MediaStreamTrackState;
13
- constructor(kind: "video" | "audio", id: string, muted: boolean, readyState: MediaStreamTrackState);
14
- applyConstraints(): Promise<void>;
15
- clone(): MediaStreamTrack;
16
- getCapabilities(): MediaTrackCapabilities;
17
- getConstraints(): MediaTrackConstraints;
18
- getSettings(): MediaTrackSettings;
19
- stop(): void;
20
- /** Simulates the browser signalling that frames stopped or resumed. */
21
- setMuted(muted: boolean): void;
22
- /** Simulates the source ending. */
23
- end(): void;
24
- }
25
- export interface FakeMediaStreamTrackOptions {
26
- readonly kind?: "video" | "audio";
27
- readonly id?: string;
28
- readonly muted?: boolean;
29
- readonly readyState?: MediaStreamTrackState;
30
- }
31
- export declare function createFakeMediaStreamTrack({ kind, id, muted, readyState }?: FakeMediaStreamTrackOptions): FakeMediaStreamTrack;
32
- export type { FakeMediaStreamTrack };
33
- //# sourceMappingURL=fake-media-track.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"fake-media-track.d.ts","sourceRoot":"","sources":["../../src/test-support/fake-media-track.ts"],"names":[],"mappings":"AAAA,sFAAsF;AACtF,cAAM,oBAAqB,SAAQ,WAAY,YAAW,gBAAgB;IACxE,WAAW,SAAM;IACjB,OAAO,UAAQ;IACf,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,KAAK,UAAU;IACxB,KAAK,EAAE,OAAO,CAAC;IACf,OAAO,EAAE,CAAC,CAAC,IAAI,EAAE,gBAAgB,EAAE,EAAE,EAAE,KAAK,KAAK,OAAO,CAAC,GAAG,IAAI,CAAQ;IACxE,MAAM,EAAE,CAAC,CAAC,IAAI,EAAE,gBAAgB,EAAE,EAAE,EAAE,KAAK,KAAK,OAAO,CAAC,GAAG,IAAI,CAAQ;IACvE,QAAQ,EAAE,CAAC,CAAC,IAAI,EAAE,gBAAgB,EAAE,EAAE,EAAE,KAAK,KAAK,OAAO,CAAC,GAAG,IAAI,CAAQ;IACzE,UAAU,EAAE,qBAAqB,CAAC;IAElC,YAAY,IAAI,EAAE,OAAO,GAAG,OAAO,EAAE,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,UAAU,EAAE,qBAAqB,EAMjG;IAED,gBAAgB,IAAI,OAAO,CAAC,IAAI,CAAC,CAEhC;IACD,KAAK,IAAI,gBAAgB,CAExB;IACD,eAAe,IAAI,sBAAsB,CAExC;IACD,cAAc,IAAI,qBAAqB,CAEtC;IACD,WAAW,IAAI,kBAAkB,CAEhC;IACD,IAAI,IAAI,IAAI,CAEX;IACD,uEAAuE;IACvE,QAAQ,CAAC,KAAK,EAAE,OAAO,GAAG,IAAI,CAG7B;IACD,mCAAmC;IACnC,GAAG,IAAI,IAAI,CAGV;CACF;AAED,MAAM,WAAW,2BAA2B;IAC1C,QAAQ,CAAC,IAAI,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC;IAClC,QAAQ,CAAC,EAAE,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,KAAK,CAAC,EAAE,OAAO,CAAC;IACzB,QAAQ,CAAC,UAAU,CAAC,EAAE,qBAAqB,CAAC;CAC7C;AAED,wBAAgB,0BAA0B,CAAC,EAAE,IAAc,EAAE,EAAoB,EAAE,KAAa,EAAE,UAAmB,EAAE,GAAE,2BAAgC,GAAG,oBAAoB,CAE/K;AAED,YAAY,EAAE,oBAAoB,EAAE,CAAC"}
@@ -1,8 +0,0 @@
1
- import type { SpaceClient, SpaceSnapshot } from "@q9labsai/chalk-client";
2
- import { createSnapshot } from "./preview-client";
3
- export { createSnapshot };
4
- export type TestClient = SpaceClient & {
5
- readonly setSnapshot: (snapshot: SpaceSnapshot) => void;
6
- };
7
- export declare function createTestClient(initialSnapshot?: SpaceSnapshot): TestClient;
8
- //# sourceMappingURL=test-client.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"test-client.d.ts","sourceRoot":"","sources":["../../src/test-support/test-client.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AAGzE,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAElD,OAAO,EAAE,cAAc,EAAE,CAAC;AAE1B,MAAM,MAAM,UAAU,GAAG,WAAW,GAAG;IAAE,QAAQ,CAAC,WAAW,EAAE,CAAC,QAAQ,EAAE,aAAa,KAAK,IAAI,CAAA;CAAE,CAAC;AAEnG,wBAAgB,gBAAgB,CAAC,eAAe,gBAAmB,GAAG,UAAU,CAyC/E"}