@arbidocs/blocks 0.4.110 → 0.4.111

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.
Files changed (94) hide show
  1. package/dist/{NativeDocxEditor-WODZAURG.cjs → NativeDocxEditor-AQKRZBIU.cjs} +7 -7
  2. package/dist/{NativeDocxEditor-WODZAURG.cjs.map → NativeDocxEditor-AQKRZBIU.cjs.map} +1 -1
  3. package/dist/{NativeDocxEditor-4PY4YZYC.js → NativeDocxEditor-IN2HEO5I.js} +3 -3
  4. package/dist/{NativeDocxEditor-4PY4YZYC.js.map → NativeDocxEditor-IN2HEO5I.js.map} +1 -1
  5. package/dist/agents/index.cjs +207 -207
  6. package/dist/agents/index.js +2 -2
  7. package/dist/calendar/EventEditor.d.ts +1 -1
  8. package/dist/calendar/draft.d.ts +7 -1
  9. package/dist/calendar/index.cjs +58 -10
  10. package/dist/calendar/index.cjs.map +1 -1
  11. package/dist/calendar/index.d.ts +1 -1
  12. package/dist/calendar/index.js +56 -11
  13. package/dist/calendar/index.js.map +1 -1
  14. package/dist/calendar/types.d.ts +20 -0
  15. package/dist/calls/CallSidePanel.d.ts +16 -1
  16. package/dist/calls/ControlBar.d.ts +25 -3
  17. package/dist/calls/PreJoin.d.ts +6 -2
  18. package/dist/calls/cards.d.ts +6 -2
  19. package/dist/calls/index.cjs +1078 -47
  20. package/dist/calls/index.cjs.map +1 -1
  21. package/dist/calls/index.d.ts +4 -3
  22. package/dist/calls/index.js +1067 -51
  23. package/dist/calls/index.js.map +1 -1
  24. package/dist/calls/panels.d.ts +11 -0
  25. package/dist/calls/webinar/ChatPermissionSetting.d.ts +18 -0
  26. package/dist/calls/webinar/OnStageCheck.d.ts +23 -0
  27. package/dist/calls/webinar/QAPanel.d.ts +56 -0
  28. package/dist/calls/webinar/RaiseHandButton.d.ts +14 -0
  29. package/dist/calls/webinar/WebinarAudiencePanel.d.ts +23 -0
  30. package/dist/calls/webinar/WebinarViewer.d.ts +39 -0
  31. package/dist/calls/webinar/WebinarWaiting.d.ts +19 -0
  32. package/dist/calls/webinar/hooks.d.ts +13 -0
  33. package/dist/calls/webinar/index.d.ts +14 -0
  34. package/dist/calls/webinar/live.d.ts +43 -0
  35. package/dist/calls/webinar/types.d.ts +49 -0
  36. package/dist/{chunk-GKDWQLVU.js → chunk-2C7TCVQZ.js} +172 -121
  37. package/dist/chunk-2C7TCVQZ.js.map +1 -0
  38. package/dist/{chunk-54WBIVHV.cjs → chunk-2WO5L7YT.cjs} +5 -5
  39. package/dist/{chunk-54WBIVHV.cjs.map → chunk-2WO5L7YT.cjs.map} +1 -1
  40. package/dist/{chunk-A35KT2II.js → chunk-6Z7DLJU2.js} +3 -3
  41. package/dist/{chunk-A35KT2II.js.map → chunk-6Z7DLJU2.js.map} +1 -1
  42. package/dist/{chunk-VZKBI2KJ.cjs → chunk-FXUQZFAN.cjs} +3 -3
  43. package/dist/{chunk-VZKBI2KJ.cjs.map → chunk-FXUQZFAN.cjs.map} +1 -1
  44. package/dist/{chunk-SQNAJPNR.js → chunk-GFYGYME3.js} +3 -3
  45. package/dist/{chunk-SQNAJPNR.js.map → chunk-GFYGYME3.js.map} +1 -1
  46. package/dist/chunk-GICUGQNN.cjs +76 -0
  47. package/dist/chunk-GICUGQNN.cjs.map +1 -0
  48. package/dist/chunk-JJLMCV3T.js +73 -0
  49. package/dist/chunk-JJLMCV3T.js.map +1 -0
  50. package/dist/{chunk-W7ZDBPJ3.cjs → chunk-OR4CO743.cjs} +3 -3
  51. package/dist/{chunk-W7ZDBPJ3.cjs.map → chunk-OR4CO743.cjs.map} +1 -1
  52. package/dist/{chunk-PEHLUB52.js → chunk-Q6B77ZWZ.js} +3 -3
  53. package/dist/{chunk-PEHLUB52.js.map → chunk-Q6B77ZWZ.js.map} +1 -1
  54. package/dist/{chunk-ELDUWTRR.cjs → chunk-TF47ATYS.cjs} +4 -4
  55. package/dist/{chunk-ELDUWTRR.cjs.map → chunk-TF47ATYS.cjs.map} +1 -1
  56. package/dist/{chunk-JB32KYAH.js → chunk-WTM65ZNG.js} +3 -3
  57. package/dist/{chunk-JB32KYAH.js.map → chunk-WTM65ZNG.js.map} +1 -1
  58. package/dist/{chunk-2NIL2ASF.cjs → chunk-XIGWUDOD.cjs} +170 -119
  59. package/dist/chunk-XIGWUDOD.cjs.map +1 -0
  60. package/dist/collaboration/index.cjs +1 -1
  61. package/dist/collaboration/index.js +1 -1
  62. package/dist/connect/docx.cjs +6 -6
  63. package/dist/connect/docx.js +4 -4
  64. package/dist/connect/index.cjs +31 -31
  65. package/dist/connect/index.js +7 -7
  66. package/dist/docx/AgentUndo.d.ts +4 -0
  67. package/dist/docx/index.cjs +46 -46
  68. package/dist/docx/index.js +3 -3
  69. package/dist/files/index.cjs +1 -1
  70. package/dist/files/index.js +1 -1
  71. package/dist/index.cjs +332 -332
  72. package/dist/index.js +6 -6
  73. package/dist/settings/index.cjs +48 -102
  74. package/dist/settings/index.cjs.map +1 -1
  75. package/dist/settings/index.js +10 -70
  76. package/dist/settings/index.js.map +1 -1
  77. package/dist/workflow-canvas/index.cjs +9 -9
  78. package/dist/workflow-canvas/index.js +2 -2
  79. package/node_modules/@arbidocs/coedit/dist/commands.cjs +179 -9
  80. package/node_modules/@arbidocs/coedit/dist/commands.cjs.map +1 -1
  81. package/node_modules/@arbidocs/coedit/dist/commands.d.cts +81 -1
  82. package/node_modules/@arbidocs/coedit/dist/commands.d.ts +81 -1
  83. package/node_modules/@arbidocs/coedit/dist/commands.js +173 -11
  84. package/node_modules/@arbidocs/coedit/dist/commands.js.map +1 -1
  85. package/node_modules/@arbidocs/coedit/dist/server.cjs +58 -2
  86. package/node_modules/@arbidocs/coedit/dist/server.cjs.map +1 -1
  87. package/node_modules/@arbidocs/coedit/dist/server.d.cts +29 -1
  88. package/node_modules/@arbidocs/coedit/dist/server.d.ts +29 -1
  89. package/node_modules/@arbidocs/coedit/dist/server.js +58 -3
  90. package/node_modules/@arbidocs/coedit/dist/server.js.map +1 -1
  91. package/node_modules/@arbidocs/coedit/package.json +1 -1
  92. package/package.json +4 -4
  93. package/dist/chunk-2NIL2ASF.cjs.map +0 -1
  94. package/dist/chunk-GKDWQLVU.js.map +0 -1
@@ -24,6 +24,17 @@ export declare function VoiceMeter({ level, muted, className, }: {
24
24
  muted?: boolean;
25
25
  className?: string;
26
26
  }): ReactElement;
27
+ /**
28
+ * A person's name as the call shows people: the app's pill (`entity`, which says "(me)" itself),
29
+ * else initials and the name, with `youLabel` after my own. Every list of people in the call
30
+ * (participants, lobby, webinar audience, Q&A askers) names them through this one piece.
31
+ */
32
+ export declare function CallPersonLabel({ name, entity, isLocal, youLabel, }: {
33
+ name: string;
34
+ entity?: ReactNode;
35
+ isLocal?: boolean;
36
+ youLabel?: string;
37
+ }): ReactElement;
27
38
  /**
28
39
  * Who is in the call, always on show under the video in the call panel: a live speaker list (the
29
40
  * app orders it, talkers first), each row with the person's pill, voice meter, mic and camera
@@ -0,0 +1,18 @@
1
+ /**
2
+ * "Who can chat: Panelists only | Everyone" — the moderators' setting, as a group of the call's
3
+ * More menu (`chatPermissionSection` for `MoreMenu`'s `groups`), so it lives with the other call
4
+ * settings rather than as a control of its own.
5
+ */
6
+ import { type ReactElement } from 'react';
7
+ import type { MoreMenuSection } from '../ControlBar';
8
+ import type { MaybePromise, WebinarChatPermission } from './types';
9
+ export interface ChatPermissionSettingProps {
10
+ value: WebinarChatPermission;
11
+ onChange(value: WebinarChatPermission): MaybePromise;
12
+ /** The app's change in flight (the menu may have closed and reopened since). */
13
+ pending?: boolean;
14
+ }
15
+ /** Menu content: a label and two radio items. Render it inside a `DropdownMenuContent`. */
16
+ export declare function ChatPermissionSetting({ value, onChange, pending, }: ChatPermissionSettingProps): ReactElement;
17
+ /** The setting as a `MoreMenu` group: `groups={[…, chatPermissionSection(props)]}`. */
18
+ export declare function chatPermissionSection(props: ChatPermissionSettingProps): MoreMenuSection;
@@ -0,0 +1,23 @@
1
+ /**
2
+ * "You're on stage": a moderator promoted me, so before my microphone and camera go out I check
3
+ * them — the call's own `PreJoin` (preview, level meter, device pickers) in a dialog (a bottom
4
+ * sheet on a phone). Only the camera video is mirrored in the self-view; no text ever is.
5
+ */
6
+ import type { ReactElement } from 'react';
7
+ import { type JoinChoices, type MediaKind } from '../join-choices';
8
+ import type { MaybePromise } from './types';
9
+ export interface OnStageCheckProps {
10
+ open: boolean;
11
+ /** Go on stage with these devices. */
12
+ onJoinStage(choices: JoinChoices): MaybePromise;
13
+ /** Decline: step back down (also on Escape / close). */
14
+ onStayInAudience(): MaybePromise;
15
+ /** Busy from outside (the app's request in flight). */
16
+ busy?: boolean;
17
+ /** A failure to show above the buttons. */
18
+ error?: string | null;
19
+ /** Mirror my camera preview (default true; only the <video> flips). */
20
+ mirror?: boolean;
21
+ describeError?(err: unknown, kind: MediaKind): string;
22
+ }
23
+ export declare function OnStageCheck({ open, onJoinStage, onStayInAudience, busy, error, mirror, describeError, }: OnStageCheckProps): ReactElement;
@@ -0,0 +1,56 @@
1
+ /**
2
+ * The webinar's Q&A, the body of a `CallSidePanel` (the attendee viewer's side, the team's Q&A tab):
3
+ * Open / Answered (and, for the team, Dismissed) questions, most upvoted first; an upvote toggle on
4
+ * each (never on my own); status chips ("Answering live", "Answered") and a text answer under the
5
+ * question. The team answers live, answers in text (an inline composer), marks answered,
6
+ * dismisses or reopens. The ask box sits at the bottom, like a chat composer.
7
+ *
8
+ * Askers are named through the app's pill (`asker`); another attendee's question is "Attendee"
9
+ * (the server hides who asked it), so attendees never learn who else attends.
10
+ */
11
+ import { type ReactElement } from 'react';
12
+ import type { MaybePromise, QuestionStatus, WebinarQuestion } from './types';
13
+ export type QAFilter = 'open' | 'answered' | 'dismissed';
14
+ export interface QAPanelProps {
15
+ questions: WebinarQuestion[];
16
+ /** A team member (host, co-host, panelist): moderates, and sees dismissed questions. */
17
+ team?: boolean;
18
+ /** The ask box's limit (default 500 characters). */
19
+ maxLength?: number;
20
+ /** Hide the ask box (e.g. before the webinar is live). */
21
+ canAsk?: boolean;
22
+ /** Resolve to clear the box; reject to keep the text (the app reports the error). */
23
+ onAsk(body: string): MaybePromise;
24
+ /** `up` = add my vote, else take it back. */
25
+ onVote(question: WebinarQuestion, up: boolean): MaybePromise;
26
+ /** Team: Answer live (`answering`), Mark answered, Dismiss, Reopen (`open`). */
27
+ onStatusChange?(question: WebinarQuestion, status: QuestionStatus): MaybePromise;
28
+ /** Team: a text answer (the server marks the question answered). */
29
+ onAnswer?(question: WebinarQuestion, answer: string): MaybePromise;
30
+ /** Delete one of my own questions while it is still open. */
31
+ onDelete?(question: WebinarQuestion): MaybePromise;
32
+ /** The filter to start on (default Open). */
33
+ defaultFilter?: QAFilter;
34
+ /** "Now" for the asked times (tests); live by default. */
35
+ now?: Date;
36
+ className?: string;
37
+ }
38
+ /** Questions of a filter, in reading order: live first, then most upvoted, then oldest. */
39
+ export declare function sortQuestions(questions: WebinarQuestion[], filter: QAFilter): WebinarQuestion[];
40
+ /**
41
+ * A text box with a counter and a send button; Enter sends, Shift+Enter breaks the line. The ask
42
+ * box and the text answer here, and the webinar's live chat in the same side panel.
43
+ */
44
+ export declare function PanelComposer({ placeholder, ariaLabel, sendLabel, maxLength, busy, onSend, onCancel, autoFocus, testId, }: {
45
+ placeholder: string;
46
+ ariaLabel: string;
47
+ sendLabel: string;
48
+ maxLength: number;
49
+ busy: boolean;
50
+ /** Resolves to whether it went (then the box clears). */
51
+ onSend(text: string): Promise<boolean>;
52
+ onCancel?(): void;
53
+ autoFocus?: boolean;
54
+ testId: string;
55
+ }): ReactElement;
56
+ export declare function QAPanel({ questions, team, maxLength, canAsk, onAsk, onVote, onStatusChange, onAnswer, onDelete, defaultFilter, now: fixedNow, className, }: QAPanelProps): ReactElement;
@@ -0,0 +1,14 @@
1
+ /** Raise / lower my hand: one control-bar button, on (solid) while the hand is up. */
2
+ import type { ReactElement } from 'react';
3
+ import type { MaybePromise } from './types';
4
+ export interface RaiseHandButtonProps {
5
+ raised: boolean;
6
+ /** Asked with the new state (`true` = raise). */
7
+ onToggle(raised: boolean): MaybePromise;
8
+ /** Busy from outside (the app's own request in flight). */
9
+ pending?: boolean;
10
+ /** Press-shortcut inside a `CallControlBar` (default H). */
11
+ shortcut?: string;
12
+ className?: string;
13
+ }
14
+ export declare function RaiseHandButton({ raised, onToggle, pending, shortcut, className, }: RaiseHandButtonProps): ReactElement;
@@ -0,0 +1,23 @@
1
+ /**
2
+ * The moderators' audience view, the body of a `CallSidePanel` (its Audience tab): the raised
3
+ * hands, oldest first, each with Promote; then everyone in the room with their stage state, Promote
4
+ * or Move to audience. Only moderators get this; an attendee's UI never lists attendees.
5
+ */
6
+ import { type ReactElement } from 'react';
7
+ import type { MaybePromise, WebinarAttendee, WebinarHand } from './types';
8
+ export interface WebinarAudiencePanelProps {
9
+ /** Raised hands (any order: shown oldest first). */
10
+ hands: WebinarHand[];
11
+ /** Everyone in the room, team included (the app's order). */
12
+ attendees: WebinarAttendee[];
13
+ /** Bring someone on stage. */
14
+ onPromote(id: string): MaybePromise;
15
+ /** Send someone on stage back to the audience (never offered for the host). */
16
+ onDemote(id: string): MaybePromise;
17
+ /** A search field appears above the attendees when there are more than this many (default 8). */
18
+ searchThreshold?: number;
19
+ /** "Now" for the raised times (tests); live by default. */
20
+ now?: Date;
21
+ className?: string;
22
+ }
23
+ export declare function WebinarAudiencePanel({ hands, attendees, onPromote, onDemote, searchThreshold, now: fixedNow, className, }: WebinarAudiencePanelProps): ReactElement;
@@ -0,0 +1,39 @@
1
+ /**
2
+ * The attendee's clean viewer: the stage (the app's `CallGrid` / `CallFocus` of the panelists),
3
+ * the live captions under it, a side slot (Q&A in a `CallSidePanel`) docked on a wide screen and
4
+ * over the stage on a narrow one, and a bottom bar with Raise hand, the side toggle and Leave.
5
+ * Audio-first, and no list of other attendees anywhere. (The team keeps the normal call UI.)
6
+ */
7
+ import type { ReactElement, ReactNode, Ref } from 'react';
8
+ import { type RaiseHandButtonProps } from './RaiseHandButton';
9
+ export interface WebinarViewerProps {
10
+ /** The header (a `CallHeader` with the title and the live chip). */
11
+ header?: ReactNode;
12
+ /** The stage: the visible panelists' tiles. */
13
+ stage: ReactNode;
14
+ stageRef?: Ref<HTMLDivElement>;
15
+ /** Floating over the stage (connection state). */
16
+ stageOverlay?: ReactNode;
17
+ /** Under the stage: a `CaptionsStrip` (or the live transcript). */
18
+ captions?: ReactNode;
19
+ /** The side (a `CallSidePanel` with the `QAPanel`); omit while closed. */
20
+ side?: ReactNode;
21
+ /** The side's toggle in the bar (Q&A); omit for none. */
22
+ sideToggle?: {
23
+ open: boolean;
24
+ onToggle(): void;
25
+ label: string;
26
+ count?: number;
27
+ };
28
+ /** My raised hand. */
29
+ hand: RaiseHandButtonProps;
30
+ onLeave(): void;
31
+ /** The bar's left end (e.g. "Enable audio"). */
32
+ left?: ReactNode;
33
+ /** More centre controls after Raise hand (e.g. a captions switch). */
34
+ controls?: ReactNode;
35
+ /** Single-key shortcuts on (the viewer is on screen). */
36
+ shortcuts?: boolean;
37
+ className?: string;
38
+ }
39
+ export declare function WebinarViewer({ header, stage, stageRef, stageOverlay, captions, side, sideToggle, hand, onLeave, left, controls, shortcuts, className, }: WebinarViewerProps): ReactElement;
@@ -0,0 +1,19 @@
1
+ /**
2
+ * The attendee's holding screen: "Starting soon" before the host goes live (the app keeps polling
3
+ * and joins on its own), and "This webinar has ended" after. A `CallStateMessage`, so it reads like
4
+ * every other state of the call stage.
5
+ */
6
+ import type { ReactElement, ReactNode } from 'react';
7
+ export interface WebinarWaitingProps {
8
+ variant: 'waiting' | 'ended';
9
+ /** The webinar's name. */
10
+ title?: string | null;
11
+ /** When it is scheduled, already formatted by the app ("Today, 15:00"). */
12
+ when?: string | null;
13
+ /** The host as the app shows people (a pill): "Hosted by …". */
14
+ host?: ReactNode;
15
+ /** A way out (back to the app); omitted, no button. */
16
+ onLeave?(): void;
17
+ leaveLabel?: string;
18
+ }
19
+ export declare function WebinarWaiting({ variant, title, when, host, onLeave, leaveLabel, }: WebinarWaitingProps): ReactElement;
@@ -0,0 +1,13 @@
1
+ /** Small hooks of the webinar blocks. */
2
+ import type { MaybePromise } from './types';
3
+ /**
4
+ * Pending state for handlers that may return a promise: `run(key, fn)` marks `key` busy until the
5
+ * promise settles and resolves to whether it succeeded (a rejection is the app's to report; the
6
+ * block only stops spinning).
7
+ */
8
+ export declare function usePending(): {
9
+ isPending(key: string): boolean;
10
+ run(key: string, fn: () => MaybePromise): Promise<boolean>;
11
+ };
12
+ /** The current time, refreshed every `ms` (relative times like "2 minutes ago"). */
13
+ export declare function useNow(ms?: number, fixed?: Date): Date;
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Webinar blocks: a webinar is an ordinary call with roles, a stage of panelists, backstage → live,
3
+ * raised hands and Q&A. Presentational like the rest of `@arbidocs/blocks/calls`; names are the
4
+ * app's person pills (`entity` / `asker` / `host`).
5
+ */
6
+ export type { MaybePromise, WebinarRole, WebinarChatPermission, QuestionStatus, WebinarHand, WebinarAttendee, WebinarQuestion, } from './types';
7
+ export { WebinarWaiting, type WebinarWaitingProps } from './WebinarWaiting';
8
+ export { BackstageBanner, WebinarLiveChip, WebinarLiveControl, WebinarEndConfirm, type WebinarLiveControlProps, } from './live';
9
+ export { RaiseHandButton, type RaiseHandButtonProps } from './RaiseHandButton';
10
+ export { WebinarAudiencePanel, type WebinarAudiencePanelProps } from './WebinarAudiencePanel';
11
+ export { QAPanel, PanelComposer, sortQuestions, type QAPanelProps, type QAFilter } from './QAPanel';
12
+ export { ChatPermissionSetting, chatPermissionSection, type ChatPermissionSettingProps, } from './ChatPermissionSetting';
13
+ export { OnStageCheck, type OnStageCheckProps } from './OnStageCheck';
14
+ export { WebinarViewer, type WebinarViewerProps } from './WebinarViewer';
@@ -0,0 +1,43 @@
1
+ /**
2
+ * Backstage → live → ended, for the team. While backstage, `BackstageBanner` (under the header)
3
+ * says so and carries Go live for the moderators; once live, the header shows `WebinarLiveChip` and
4
+ * the control bar `WebinarLiveControl` (End webinar, confirmed). Each action appears once: Go live
5
+ * only in the banner, End only in the bar.
6
+ */
7
+ import { type ReactElement } from 'react';
8
+ import type { MaybePromise } from './types';
9
+ /** "Live" in the header while the stage is open to the audience. */
10
+ export declare function WebinarLiveChip({ compact, className, }: {
11
+ compact?: boolean;
12
+ className?: string;
13
+ }): ReactElement;
14
+ export interface WebinarLiveControlProps {
15
+ /** The stage is open to the audience. */
16
+ live: boolean;
17
+ /** Moderators only: opens the stage (shown while backstage). */
18
+ onGoLive?(): MaybePromise;
19
+ /** Moderators only: ends the webinar for everyone, after a confirmation (shown while live). */
20
+ onEnd?(): MaybePromise;
21
+ /** Icon only (a narrow bar). */
22
+ compact?: boolean;
23
+ className?: string;
24
+ }
25
+ /** Go live (backstage) or End webinar (live); nothing for someone who may do neither. */
26
+ export declare function WebinarLiveControl({ live, onGoLive, onEnd, compact, className, }: WebinarLiveControlProps): ReactElement | null;
27
+ /**
28
+ * "End the webinar?" — the one confirmation before ending it for everyone, wherever End is offered
29
+ * (`WebinarLiveControl`, or the Leave button's menu in the app's call bar).
30
+ */
31
+ export declare function WebinarEndConfirm({ open, onOpenChange, onEnd, }: {
32
+ open: boolean;
33
+ onOpenChange(open: boolean): void;
34
+ onEnd(): MaybePromise;
35
+ }): ReactElement;
36
+ /**
37
+ * Under the header while backstage: the team knows the audience cannot see or hear them yet.
38
+ * Moderators get Go live here (`onGoLive`); other panelists read that the host will start it.
39
+ */
40
+ export declare function BackstageBanner({ onGoLive, className, }: {
41
+ onGoLive?(): MaybePromise;
42
+ className?: string;
43
+ }): ReactElement;
@@ -0,0 +1,49 @@
1
+ /** The shapes the webinar blocks render. The app maps its API (`/v1/calls/{call}/webinar…`) onto them. */
2
+ import type { ReactNode } from 'react';
3
+ /** A handler the block may await: while its promise is pending the control shows it is busy. */
4
+ export type MaybePromise = void | Promise<unknown>;
5
+ export type WebinarRole = 'host' | 'cohost' | 'panelist' | 'attendee';
6
+ /** Who may send chat messages: the team only, or the audience too. */
7
+ export type WebinarChatPermission = 'panelists' | 'everyone';
8
+ export type QuestionStatus = 'open' | 'answering' | 'answered' | 'dismissed';
9
+ /** A raised hand in the moderators' queue. */
10
+ export interface WebinarHand {
11
+ id: string;
12
+ name: string;
13
+ /** ISO time the hand went up. */
14
+ raisedAt: string;
15
+ /** The person as the app shows people (a pill); else initials and `name`. */
16
+ entity?: ReactNode;
17
+ }
18
+ /** Someone in the room, as the moderators see the audience. */
19
+ export interface WebinarAttendee {
20
+ id: string;
21
+ name: string;
22
+ role: WebinarRole;
23
+ /** On stage (visible, may publish). */
24
+ onStage: boolean;
25
+ handRaised: boolean;
26
+ /** The person as the app shows people (a pill); else initials and `name`. */
27
+ entity?: ReactNode;
28
+ }
29
+ /** A question of the webinar's Q&A (body and answer already decrypted by the app). */
30
+ export interface WebinarQuestion {
31
+ id: string;
32
+ body: string;
33
+ status: QuestionStatus;
34
+ /** A text answer, shown under the question. */
35
+ answer?: string | null;
36
+ /** Who wrote the text answer (the app's pill). */
37
+ answeredBy?: ReactNode;
38
+ voteCount: number;
39
+ /** I have upvoted it. */
40
+ voted: boolean;
41
+ /** I asked it (I cannot upvote it; I may delete it while it is open). */
42
+ mine: boolean;
43
+ /** ISO time it was asked. */
44
+ createdAt: string;
45
+ /** The asker's name; `null` when hidden from me (another attendee's question): "Attendee". */
46
+ askerName: string | null;
47
+ /** The asker as the app shows people (a pill; it says "(me)" on mine). */
48
+ asker?: ReactNode;
49
+ }