@mieweb/ui 0.10.0-dev.2 → 0.10.0-dev.4

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/index.d.cts CHANGED
@@ -1478,6 +1478,10 @@ interface UseDiarizationOptions {
1478
1478
  /** Load the ~50 MB speaker runtime + warm Whisper. Set false to keep it dormant until it's needed
1479
1479
  * (e.g. a host feature that's off). Default true. */
1480
1480
  enabled?: boolean;
1481
+ /** Anchor clusters against THIS namespace's enrolled voices — pass the same value used at enrollment
1482
+ * (`useVoiceSetup` / `VoiceManager`), or scoped users get "Speaker N" (or another user's labels)
1483
+ * from the legacy shared store. Omit for the original unscoped store. */
1484
+ voiceprintNamespace?: string;
1481
1485
  }
1482
1486
  interface UseDiarizationResult {
1483
1487
  /** TitaNet runtime is loaded (diarization can run). */
@@ -1494,6 +1498,11 @@ declare function useDiarization(options?: UseDiarizationOptions): UseDiarization
1494
1498
 
1495
1499
  type HeyOzwellPhase = 'listening' | 'dictating' | 'transcribing';
1496
1500
  interface UseHeyOzwellOptions {
1501
+ /** Isolates persisted enrollment (WHO + WHAT prints) from other users of the same browser profile —
1502
+ * e.g. pass the signed-in user's id. A scoped store starts empty (it does NOT inherit legacy
1503
+ * unscoped records); omit to keep the original shared store. Pass the SAME value to every voice
1504
+ * surface (`VoiceSetup` / `VoiceManager`), or verification and enrollment read different stores. */
1505
+ voiceprintNamespace?: string;
1497
1506
  /** ON: "hey ozwell" opens the chat AND starts dictating. OFF: it just opens the chat and waits. */
1498
1507
  autoDictateOnWake?: boolean;
1499
1508
  /** Close the chat popup after "ozwell I'm done" transcribes + sends. */
@@ -1532,8 +1541,9 @@ interface UseHeyOzwellOptions {
1532
1541
  * mishearing, then press send) instead of sending it automatically. An accuracy safety net for clinical
1533
1542
  * use — off by default so the hands-free flow stays hands-free. */
1534
1543
  reviewBeforeSend?: boolean;
1535
- /** Diarization tuning for conversation mode (threshold, maxSpeakers, minSegmentSeconds, inferRoles). */
1536
- diarizationOptions?: Omit<UseDiarizationOptions, 'enabled'>;
1544
+ /** Diarization tuning for conversation mode (threshold, maxSpeakers, minSegmentSeconds, inferRoles).
1545
+ * `enabled` and `voiceprintNamespace` are owned by the hook (conversationMode / the shared prop). */
1546
+ diarizationOptions?: Omit<UseDiarizationOptions, 'enabled' | 'voiceprintNamespace'>;
1537
1547
  }
1538
1548
  /** Props to spread onto <HeyOzwellToggle>. */
1539
1549
  interface HeyOzwellToggleBindings {
@@ -1704,6 +1714,12 @@ interface ModelInfoListProps {
1704
1714
  declare function ModelInfoList({ status }: ModelInfoListProps): react_jsx_runtime.JSX.Element;
1705
1715
 
1706
1716
  interface HandsFreeChatProps {
1717
+ /** Isolates persisted enrollment (WHO + WHAT prints) from other users of the same browser profile —
1718
+ * e.g. pass the signed-in user's id (`voiceprintNamespace={user.id}`). Scopes both the wake
1719
+ * verifier and the embedded VoiceManager; a scoped store starts empty (it does NOT inherit legacy
1720
+ * unscoped records). Omit to keep the original shared store. Any standalone `VoiceSetup` /
1721
+ * `VoiceManager` the host renders must receive the SAME value. */
1722
+ voiceprintNamespace?: string;
1707
1723
  /** Chat header title. */
1708
1724
  title?: string;
1709
1725
  /** Suggested-action chips for the empty state. */
@@ -1729,9 +1745,15 @@ interface HandsFreeChatProps {
1729
1745
  autoDictateOnWake?: boolean;
1730
1746
  }
1731
1747
  /** Say "hey ozwell" to dictate, "ozwell I'm done" to send — wake + speaker-verify + dictation + AIChat. */
1732
- declare function HandsFreeChat({ title, suggestions, userName, logoSrc, transcription, requireDoctor, liveTranscript, conversationMode, reviewBeforeSend, autoDictateOnWake, }: HandsFreeChatProps): react_jsx_runtime.JSX.Element;
1748
+ declare function HandsFreeChat({ voiceprintNamespace, title, suggestions, userName, logoSrc, transcription, requireDoctor, liveTranscript, conversationMode, reviewBeforeSend, autoDictateOnWake, }: HandsFreeChatProps): react_jsx_runtime.JSX.Element;
1733
1749
 
1734
1750
  interface VoiceSetupProps {
1751
+ /** Isolates persisted enrollment (WHO + WHAT prints) from other users of the same browser profile —
1752
+ * e.g. pass the signed-in user's id. Enroll with the SAME value the verifying surface
1753
+ * (`useHeyOzwell` / `HandsFreeChat`) and `VoiceManager` use, or they can't see this enrollment.
1754
+ * A scoped store starts empty — no legacy unscoped records are inherited. Omit for the original
1755
+ * shared store. */
1756
+ voiceprintNamespace?: string;
1735
1757
  /**
1736
1758
  * 'enroll' (default) = fresh first-time setup. 'add' = jump straight into appending a new voice/condition
1737
1759
  * to the existing voiceprints — what the settings menu's "Add a voice" uses, so the user doesn't have to
@@ -1750,17 +1772,28 @@ interface VoiceSetupProps {
1750
1772
  onCancel?: () => void;
1751
1773
  }
1752
1774
  /** On-device voice enrollment — tap the octopus, it pulses as you talk. Brand-aligned. */
1753
- declare function VoiceSetup({ mode, voiceId, label, logoSrc, onDone, onCancel, }: VoiceSetupProps): react_jsx_runtime.JSX.Element;
1775
+ declare function VoiceSetup({ voiceprintNamespace, mode, voiceId, label, logoSrc, onDone, onCancel, }: VoiceSetupProps): react_jsx_runtime.JSX.Element;
1754
1776
 
1755
1777
  interface VoiceManagerProps {
1778
+ /** Isolates persisted enrollment (WHO + WHAT prints) from other users of the same browser profile —
1779
+ * e.g. pass the signed-in user's id. Must be the SAME value the verifying surface (`useHeyOzwell` /
1780
+ * `HandsFreeChat`) uses, or this page manages a different store than the one gating wakes (it would
1781
+ * look empty and enroll into the wrong store). A scoped store starts empty — no legacy unscoped
1782
+ * records are inherited. Omit to manage the original shared store. */
1783
+ voiceprintNamespace?: string;
1756
1784
  /** Octopus logo source, forwarded to the enrollment screen. */
1757
1785
  logoSrc?: string;
1758
1786
  }
1759
1787
  /** The central voice-enrollment management page. */
1760
- declare function VoiceManager({ logoSrc }: VoiceManagerProps): react_jsx_runtime.JSX.Element;
1788
+ declare function VoiceManager({ logoSrc, voiceprintNamespace, }: VoiceManagerProps): react_jsx_runtime.JSX.Element;
1761
1789
 
1762
1790
  type VoiceSetupPhase = 'intro' | 'getready' | 'speak' | 'gotit' | 'deny' | 'done';
1763
1791
  interface UseVoiceSetupOptions {
1792
+ /** Isolates persisted enrollment (WHO + WHAT prints) from other users of the same browser profile —
1793
+ * e.g. pass the signed-in user's id. A scoped store starts empty (it does NOT inherit legacy
1794
+ * unscoped records); omit to keep the original shared store. Enroll with the SAME value the
1795
+ * verifying surface (`useHeyOzwell` / `HandsFreeChat`) uses, or it can't see this enrollment. */
1796
+ voiceprintNamespace?: string;
1764
1797
  /** Start directly in "add a voice" (append) mode instead of a fresh enroll — for the settings menu's
1765
1798
  * "Add a voice", which appends another authorized voice / condition to the existing voiceprints. */
1766
1799
  startAdding?: boolean;
@@ -1924,6 +1957,12 @@ interface UseSpeakerVerifyOpts {
1924
1957
  /** Set false to skip loading the ~50 MB sherpa/TitaNet runtime (e.g. when the doctor-only gate is off).
1925
1958
  * Defaults to true so existing callers are unchanged. */
1926
1959
  enabled?: boolean;
1960
+ /** Isolates persisted enrollment from other users of the same browser profile — e.g. pass the
1961
+ * signed-in user's id. Every returned method (enroll / verify / identify / listVoices / clear…)
1962
+ * operates on that scoped store, which starts empty: scoped records do NOT inherit the legacy
1963
+ * unscoped key. Use the SAME value across enrollment, verification, and management (`useVoiceSetup`,
1964
+ * `useHeyOzwell`, `VoiceManager`), or they read different stores. Omit for the original shared one. */
1965
+ voiceprintNamespace?: string;
1927
1966
  }
1928
1967
  declare function useSpeakerVerify(opts?: UseSpeakerVerifyOpts): SpeakerVerifyHandle;
1929
1968
 
@@ -2089,18 +2128,6 @@ declare function askOzwell(messages: OzwellMessage[] | string, opts?: AskOpts):
2089
2128
  */
2090
2129
  declare function askOzwellStream(messages: OzwellMessage[] | string, onToken: (delta: string, full: string) => void, opts?: AskOpts): Promise<string>;
2091
2130
 
2092
- /**
2093
- * IndexedDB store for on-device voiceprints (enrollment vectors), replacing localStorage for this data.
2094
- *
2095
- * Why IndexedDB and not localStorage: it's asynchronous (off the main thread), stores `Float32Array`
2096
- * natively via structured clone (no JSON-stringifying embeddings into bloated number arrays), and isn't
2097
- * capped at ~5 MB. Why not OPFS: these are small *structured records* keyed by id, not large files —
2098
- * IndexedDB is the right tool; OPFS is for the big model files.
2099
- *
2100
- * One object store, keyed by a string id; values are any structured-cloneable object, so `Float32Array`s
2101
- * survive the round-trip intact. On first read of a key it migrates a legacy localStorage value (if a
2102
- * parser is supplied) and then clears it.
2103
- */
2104
2131
  /**
2105
2132
  * Read a voiceprint record. If IndexedDB has nothing for `key` but localStorage does, migrate it via
2106
2133
  * `migrateLegacy` (parse the old JSON string → the new shape), persist it to IndexedDB, and clear the
@@ -2111,9 +2138,9 @@ declare function getVoiceprints<T>(key: string, migrateLegacy?: (raw: string) =>
2111
2138
  declare function setVoiceprints(key: string, value: unknown): Promise<void>;
2112
2139
  /** Remove a voiceprint record (and any stale localStorage copy). */
2113
2140
  declare function clearVoiceprints(key: string): Promise<void>;
2114
- declare function loadWhatPrints(): Promise<Record<string, Float32Array[]>>;
2115
- declare function saveWhatPrints(map: Record<string, Float32Array[]>): Promise<void>;
2116
- declare function clearWhatPrints(): Promise<void>;
2141
+ declare function loadWhatPrints(namespace?: string): Promise<Record<string, Float32Array[]>>;
2142
+ declare function saveWhatPrints(map: Record<string, Float32Array[]>, namespace?: string): Promise<void>;
2143
+ declare function clearWhatPrints(namespace?: string): Promise<void>;
2117
2144
 
2118
2145
  /**
2119
2146
  * Shared on-device audio helpers for Hey Ozwell — previously copy-pasted across the enrollment,
@@ -10167,8 +10194,27 @@ interface SidebarNavGroupProps {
10167
10194
  groupId?: string;
10168
10195
  /** Additional CSS classes */
10169
10196
  className?: string;
10197
+ /**
10198
+ * Keep items mounted when the group is collapsed, hidden via `hidden`.
10199
+ *
10200
+ * For groups whose children own DOM state that a remount would destroy —
10201
+ * uncontrolled inputs, media playback position, an editor instance. State
10202
+ * survives the group's own collapse *and* the desktop rail collapsing.
10203
+ *
10204
+ * Does **not** make collapsed items findable by in-page search: `hidden` is
10205
+ * `display: none`, and browsers do not match text inside it. `hidden="until-found"`
10206
+ * would deliver that, but it is not portable enough to build the API on yet.
10207
+ *
10208
+ * Mirrors `CollapsibleContent`'s prop of the same name, and carries the same
10209
+ * caveat: this path does **not** animate. `hidden` is `display: none`, which
10210
+ * an animated height cannot run through, and dropping it for the duration
10211
+ * would let keyboard users tab into content that is visually collapsed. Not
10212
+ * animating is the safe answer until `hidden` can be sequenced around the
10213
+ * animation.
10214
+ */
10215
+ forceMount?: boolean;
10170
10216
  }
10171
- declare function SidebarNavGroup({ label, icon, children, defaultExpanded, groupId, className, }: SidebarNavGroupProps): React__default.JSX.Element;
10217
+ declare function SidebarNavGroup({ label, icon, children, defaultExpanded, groupId, className, forceMount, }: SidebarNavGroupProps): React__default.JSX.Element;
10172
10218
  interface SidebarNavItemProps {
10173
10219
  /** Item label */
10174
10220
  label: string;
package/dist/index.d.ts CHANGED
@@ -1478,6 +1478,10 @@ interface UseDiarizationOptions {
1478
1478
  /** Load the ~50 MB speaker runtime + warm Whisper. Set false to keep it dormant until it's needed
1479
1479
  * (e.g. a host feature that's off). Default true. */
1480
1480
  enabled?: boolean;
1481
+ /** Anchor clusters against THIS namespace's enrolled voices — pass the same value used at enrollment
1482
+ * (`useVoiceSetup` / `VoiceManager`), or scoped users get "Speaker N" (or another user's labels)
1483
+ * from the legacy shared store. Omit for the original unscoped store. */
1484
+ voiceprintNamespace?: string;
1481
1485
  }
1482
1486
  interface UseDiarizationResult {
1483
1487
  /** TitaNet runtime is loaded (diarization can run). */
@@ -1494,6 +1498,11 @@ declare function useDiarization(options?: UseDiarizationOptions): UseDiarization
1494
1498
 
1495
1499
  type HeyOzwellPhase = 'listening' | 'dictating' | 'transcribing';
1496
1500
  interface UseHeyOzwellOptions {
1501
+ /** Isolates persisted enrollment (WHO + WHAT prints) from other users of the same browser profile —
1502
+ * e.g. pass the signed-in user's id. A scoped store starts empty (it does NOT inherit legacy
1503
+ * unscoped records); omit to keep the original shared store. Pass the SAME value to every voice
1504
+ * surface (`VoiceSetup` / `VoiceManager`), or verification and enrollment read different stores. */
1505
+ voiceprintNamespace?: string;
1497
1506
  /** ON: "hey ozwell" opens the chat AND starts dictating. OFF: it just opens the chat and waits. */
1498
1507
  autoDictateOnWake?: boolean;
1499
1508
  /** Close the chat popup after "ozwell I'm done" transcribes + sends. */
@@ -1532,8 +1541,9 @@ interface UseHeyOzwellOptions {
1532
1541
  * mishearing, then press send) instead of sending it automatically. An accuracy safety net for clinical
1533
1542
  * use — off by default so the hands-free flow stays hands-free. */
1534
1543
  reviewBeforeSend?: boolean;
1535
- /** Diarization tuning for conversation mode (threshold, maxSpeakers, minSegmentSeconds, inferRoles). */
1536
- diarizationOptions?: Omit<UseDiarizationOptions, 'enabled'>;
1544
+ /** Diarization tuning for conversation mode (threshold, maxSpeakers, minSegmentSeconds, inferRoles).
1545
+ * `enabled` and `voiceprintNamespace` are owned by the hook (conversationMode / the shared prop). */
1546
+ diarizationOptions?: Omit<UseDiarizationOptions, 'enabled' | 'voiceprintNamespace'>;
1537
1547
  }
1538
1548
  /** Props to spread onto <HeyOzwellToggle>. */
1539
1549
  interface HeyOzwellToggleBindings {
@@ -1704,6 +1714,12 @@ interface ModelInfoListProps {
1704
1714
  declare function ModelInfoList({ status }: ModelInfoListProps): react_jsx_runtime.JSX.Element;
1705
1715
 
1706
1716
  interface HandsFreeChatProps {
1717
+ /** Isolates persisted enrollment (WHO + WHAT prints) from other users of the same browser profile —
1718
+ * e.g. pass the signed-in user's id (`voiceprintNamespace={user.id}`). Scopes both the wake
1719
+ * verifier and the embedded VoiceManager; a scoped store starts empty (it does NOT inherit legacy
1720
+ * unscoped records). Omit to keep the original shared store. Any standalone `VoiceSetup` /
1721
+ * `VoiceManager` the host renders must receive the SAME value. */
1722
+ voiceprintNamespace?: string;
1707
1723
  /** Chat header title. */
1708
1724
  title?: string;
1709
1725
  /** Suggested-action chips for the empty state. */
@@ -1729,9 +1745,15 @@ interface HandsFreeChatProps {
1729
1745
  autoDictateOnWake?: boolean;
1730
1746
  }
1731
1747
  /** Say "hey ozwell" to dictate, "ozwell I'm done" to send — wake + speaker-verify + dictation + AIChat. */
1732
- declare function HandsFreeChat({ title, suggestions, userName, logoSrc, transcription, requireDoctor, liveTranscript, conversationMode, reviewBeforeSend, autoDictateOnWake, }: HandsFreeChatProps): react_jsx_runtime.JSX.Element;
1748
+ declare function HandsFreeChat({ voiceprintNamespace, title, suggestions, userName, logoSrc, transcription, requireDoctor, liveTranscript, conversationMode, reviewBeforeSend, autoDictateOnWake, }: HandsFreeChatProps): react_jsx_runtime.JSX.Element;
1733
1749
 
1734
1750
  interface VoiceSetupProps {
1751
+ /** Isolates persisted enrollment (WHO + WHAT prints) from other users of the same browser profile —
1752
+ * e.g. pass the signed-in user's id. Enroll with the SAME value the verifying surface
1753
+ * (`useHeyOzwell` / `HandsFreeChat`) and `VoiceManager` use, or they can't see this enrollment.
1754
+ * A scoped store starts empty — no legacy unscoped records are inherited. Omit for the original
1755
+ * shared store. */
1756
+ voiceprintNamespace?: string;
1735
1757
  /**
1736
1758
  * 'enroll' (default) = fresh first-time setup. 'add' = jump straight into appending a new voice/condition
1737
1759
  * to the existing voiceprints — what the settings menu's "Add a voice" uses, so the user doesn't have to
@@ -1750,17 +1772,28 @@ interface VoiceSetupProps {
1750
1772
  onCancel?: () => void;
1751
1773
  }
1752
1774
  /** On-device voice enrollment — tap the octopus, it pulses as you talk. Brand-aligned. */
1753
- declare function VoiceSetup({ mode, voiceId, label, logoSrc, onDone, onCancel, }: VoiceSetupProps): react_jsx_runtime.JSX.Element;
1775
+ declare function VoiceSetup({ voiceprintNamespace, mode, voiceId, label, logoSrc, onDone, onCancel, }: VoiceSetupProps): react_jsx_runtime.JSX.Element;
1754
1776
 
1755
1777
  interface VoiceManagerProps {
1778
+ /** Isolates persisted enrollment (WHO + WHAT prints) from other users of the same browser profile —
1779
+ * e.g. pass the signed-in user's id. Must be the SAME value the verifying surface (`useHeyOzwell` /
1780
+ * `HandsFreeChat`) uses, or this page manages a different store than the one gating wakes (it would
1781
+ * look empty and enroll into the wrong store). A scoped store starts empty — no legacy unscoped
1782
+ * records are inherited. Omit to manage the original shared store. */
1783
+ voiceprintNamespace?: string;
1756
1784
  /** Octopus logo source, forwarded to the enrollment screen. */
1757
1785
  logoSrc?: string;
1758
1786
  }
1759
1787
  /** The central voice-enrollment management page. */
1760
- declare function VoiceManager({ logoSrc }: VoiceManagerProps): react_jsx_runtime.JSX.Element;
1788
+ declare function VoiceManager({ logoSrc, voiceprintNamespace, }: VoiceManagerProps): react_jsx_runtime.JSX.Element;
1761
1789
 
1762
1790
  type VoiceSetupPhase = 'intro' | 'getready' | 'speak' | 'gotit' | 'deny' | 'done';
1763
1791
  interface UseVoiceSetupOptions {
1792
+ /** Isolates persisted enrollment (WHO + WHAT prints) from other users of the same browser profile —
1793
+ * e.g. pass the signed-in user's id. A scoped store starts empty (it does NOT inherit legacy
1794
+ * unscoped records); omit to keep the original shared store. Enroll with the SAME value the
1795
+ * verifying surface (`useHeyOzwell` / `HandsFreeChat`) uses, or it can't see this enrollment. */
1796
+ voiceprintNamespace?: string;
1764
1797
  /** Start directly in "add a voice" (append) mode instead of a fresh enroll — for the settings menu's
1765
1798
  * "Add a voice", which appends another authorized voice / condition to the existing voiceprints. */
1766
1799
  startAdding?: boolean;
@@ -1924,6 +1957,12 @@ interface UseSpeakerVerifyOpts {
1924
1957
  /** Set false to skip loading the ~50 MB sherpa/TitaNet runtime (e.g. when the doctor-only gate is off).
1925
1958
  * Defaults to true so existing callers are unchanged. */
1926
1959
  enabled?: boolean;
1960
+ /** Isolates persisted enrollment from other users of the same browser profile — e.g. pass the
1961
+ * signed-in user's id. Every returned method (enroll / verify / identify / listVoices / clear…)
1962
+ * operates on that scoped store, which starts empty: scoped records do NOT inherit the legacy
1963
+ * unscoped key. Use the SAME value across enrollment, verification, and management (`useVoiceSetup`,
1964
+ * `useHeyOzwell`, `VoiceManager`), or they read different stores. Omit for the original shared one. */
1965
+ voiceprintNamespace?: string;
1927
1966
  }
1928
1967
  declare function useSpeakerVerify(opts?: UseSpeakerVerifyOpts): SpeakerVerifyHandle;
1929
1968
 
@@ -2089,18 +2128,6 @@ declare function askOzwell(messages: OzwellMessage[] | string, opts?: AskOpts):
2089
2128
  */
2090
2129
  declare function askOzwellStream(messages: OzwellMessage[] | string, onToken: (delta: string, full: string) => void, opts?: AskOpts): Promise<string>;
2091
2130
 
2092
- /**
2093
- * IndexedDB store for on-device voiceprints (enrollment vectors), replacing localStorage for this data.
2094
- *
2095
- * Why IndexedDB and not localStorage: it's asynchronous (off the main thread), stores `Float32Array`
2096
- * natively via structured clone (no JSON-stringifying embeddings into bloated number arrays), and isn't
2097
- * capped at ~5 MB. Why not OPFS: these are small *structured records* keyed by id, not large files —
2098
- * IndexedDB is the right tool; OPFS is for the big model files.
2099
- *
2100
- * One object store, keyed by a string id; values are any structured-cloneable object, so `Float32Array`s
2101
- * survive the round-trip intact. On first read of a key it migrates a legacy localStorage value (if a
2102
- * parser is supplied) and then clears it.
2103
- */
2104
2131
  /**
2105
2132
  * Read a voiceprint record. If IndexedDB has nothing for `key` but localStorage does, migrate it via
2106
2133
  * `migrateLegacy` (parse the old JSON string → the new shape), persist it to IndexedDB, and clear the
@@ -2111,9 +2138,9 @@ declare function getVoiceprints<T>(key: string, migrateLegacy?: (raw: string) =>
2111
2138
  declare function setVoiceprints(key: string, value: unknown): Promise<void>;
2112
2139
  /** Remove a voiceprint record (and any stale localStorage copy). */
2113
2140
  declare function clearVoiceprints(key: string): Promise<void>;
2114
- declare function loadWhatPrints(): Promise<Record<string, Float32Array[]>>;
2115
- declare function saveWhatPrints(map: Record<string, Float32Array[]>): Promise<void>;
2116
- declare function clearWhatPrints(): Promise<void>;
2141
+ declare function loadWhatPrints(namespace?: string): Promise<Record<string, Float32Array[]>>;
2142
+ declare function saveWhatPrints(map: Record<string, Float32Array[]>, namespace?: string): Promise<void>;
2143
+ declare function clearWhatPrints(namespace?: string): Promise<void>;
2117
2144
 
2118
2145
  /**
2119
2146
  * Shared on-device audio helpers for Hey Ozwell — previously copy-pasted across the enrollment,
@@ -10167,8 +10194,27 @@ interface SidebarNavGroupProps {
10167
10194
  groupId?: string;
10168
10195
  /** Additional CSS classes */
10169
10196
  className?: string;
10197
+ /**
10198
+ * Keep items mounted when the group is collapsed, hidden via `hidden`.
10199
+ *
10200
+ * For groups whose children own DOM state that a remount would destroy —
10201
+ * uncontrolled inputs, media playback position, an editor instance. State
10202
+ * survives the group's own collapse *and* the desktop rail collapsing.
10203
+ *
10204
+ * Does **not** make collapsed items findable by in-page search: `hidden` is
10205
+ * `display: none`, and browsers do not match text inside it. `hidden="until-found"`
10206
+ * would deliver that, but it is not portable enough to build the API on yet.
10207
+ *
10208
+ * Mirrors `CollapsibleContent`'s prop of the same name, and carries the same
10209
+ * caveat: this path does **not** animate. `hidden` is `display: none`, which
10210
+ * an animated height cannot run through, and dropping it for the duration
10211
+ * would let keyboard users tab into content that is visually collapsed. Not
10212
+ * animating is the safe answer until `hidden` can be sequenced around the
10213
+ * animation.
10214
+ */
10215
+ forceMount?: boolean;
10170
10216
  }
10171
- declare function SidebarNavGroup({ label, icon, children, defaultExpanded, groupId, className, }: SidebarNavGroupProps): React__default.JSX.Element;
10217
+ declare function SidebarNavGroup({ label, icon, children, defaultExpanded, groupId, className, forceMount, }: SidebarNavGroupProps): React__default.JSX.Element;
10172
10218
  interface SidebarNavItemProps {
10173
10219
  /** Item label */
10174
10220
  label: string;