@evelan/jexity-widget 0.27.0 → 0.29.0

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 (98) hide show
  1. package/README.md +1 -0
  2. package/dist/index.mjs +3858 -3127
  3. package/dist/index.mjs.map +1 -1
  4. package/dist/loader.js +5 -5
  5. package/dist/loader.js.map +1 -1
  6. package/dist/react.mjs +4008 -3270
  7. package/dist/react.mjs.map +1 -1
  8. package/dist/types/entries/react.d.ts +2 -0
  9. package/dist/types/entries/react.d.ts.map +1 -1
  10. package/dist/types/features/chat/components/ChatScreen.d.ts +3 -1
  11. package/dist/types/features/chat/components/ChatScreen.d.ts.map +1 -1
  12. package/dist/types/features/chat/components/EscalationFormScreen.d.ts +4 -2
  13. package/dist/types/features/chat/components/EscalationFormScreen.d.ts.map +1 -1
  14. package/dist/types/features/chat/components/FormMessage.d.ts.map +1 -1
  15. package/dist/types/features/chat/components/HumanHandoffAction.d.ts +10 -0
  16. package/dist/types/features/chat/components/HumanHandoffAction.d.ts.map +1 -1
  17. package/dist/types/features/chat/components/MessageAttachments.d.ts +19 -0
  18. package/dist/types/features/chat/components/MessageAttachments.d.ts.map +1 -0
  19. package/dist/types/features/chat/components/MessageList.d.ts +4 -1
  20. package/dist/types/features/chat/components/MessageList.d.ts.map +1 -1
  21. package/dist/types/features/chat/components/magicline/TrialSessionBookingForm.d.ts.map +1 -1
  22. package/dist/types/features/chat/composer/components/ChatInput.d.ts +4 -1
  23. package/dist/types/features/chat/composer/components/ChatInput.d.ts.map +1 -1
  24. package/dist/types/features/chat/composer/components/ComposerRow.d.ts +13 -6
  25. package/dist/types/features/chat/composer/components/ComposerRow.d.ts.map +1 -1
  26. package/dist/types/features/chat/composer/components/MicButton.d.ts +13 -0
  27. package/dist/types/features/chat/composer/components/MicButton.d.ts.map +1 -0
  28. package/dist/types/features/chat/composer/components/SessionErrorNotice.d.ts +15 -1
  29. package/dist/types/features/chat/composer/components/SessionErrorNotice.d.ts.map +1 -1
  30. package/dist/types/features/chat/composer/hooks/useAttachmentUpload.d.ts +21 -0
  31. package/dist/types/features/chat/composer/hooks/useAttachmentUpload.d.ts.map +1 -0
  32. package/dist/types/features/chat/composer/hooks/useComposerInput.d.ts +4 -2
  33. package/dist/types/features/chat/composer/hooks/useComposerInput.d.ts.map +1 -1
  34. package/dist/types/features/chat/composer/hooks/useMicLevel.d.ts +10 -0
  35. package/dist/types/features/chat/composer/hooks/useMicLevel.d.ts.map +1 -0
  36. package/dist/types/features/chat/composer/hooks/useSendMessage.d.ts +5 -3
  37. package/dist/types/features/chat/composer/hooks/useSendMessage.d.ts.map +1 -1
  38. package/dist/types/features/chat/composer/hooks/useVoiceDictation.d.ts +30 -0
  39. package/dist/types/features/chat/composer/hooks/useVoiceDictation.d.ts.map +1 -0
  40. package/dist/types/features/chat/composer/lib/dictation.d.ts +75 -0
  41. package/dist/types/features/chat/composer/lib/dictation.d.ts.map +1 -0
  42. package/dist/types/features/chat/composer/state/attachments.d.ts +39 -19
  43. package/dist/types/features/chat/composer/state/attachments.d.ts.map +1 -1
  44. package/dist/types/features/chat/composer/state/index.d.ts +2 -2
  45. package/dist/types/features/chat/composer/state/index.d.ts.map +1 -1
  46. package/dist/types/features/chat/hooks/useAvailability.d.ts +1 -1
  47. package/dist/types/features/chat/hooks/useAvailability.d.ts.map +1 -1
  48. package/dist/types/features/chat/hooks/useConversation.d.ts +4 -0
  49. package/dist/types/features/chat/hooks/useConversation.d.ts.map +1 -1
  50. package/dist/types/features/chat/hooks/useConvexSession.d.ts.map +1 -1
  51. package/dist/types/features/chat/hooks/useFormClick.d.ts +14 -0
  52. package/dist/types/features/chat/hooks/useFormClick.d.ts.map +1 -0
  53. package/dist/types/features/chat/hooks/useMaintenance.d.ts +16 -0
  54. package/dist/types/features/chat/hooks/useMaintenance.d.ts.map +1 -0
  55. package/dist/types/features/chat/state/maintenance-error.d.ts +15 -0
  56. package/dist/types/features/chat/state/maintenance-error.d.ts.map +1 -0
  57. package/dist/types/features/chat/state/session-error.d.ts +4 -1
  58. package/dist/types/features/chat/state/session-error.d.ts.map +1 -1
  59. package/dist/types/i18n/config.d.ts +0 -1
  60. package/dist/types/i18n/config.d.ts.map +1 -1
  61. package/dist/types/i18n/index.d.ts +1 -1
  62. package/dist/types/i18n/index.d.ts.map +1 -1
  63. package/dist/types/i18n/locales/de.d.ts +24 -5
  64. package/dist/types/i18n/locales/de.d.ts.map +1 -1
  65. package/dist/types/i18n/locales/en.d.ts +50 -9
  66. package/dist/types/i18n/locales/en.d.ts.map +1 -1
  67. package/dist/types/i18n/resolve-widget-locale.d.ts +12 -8
  68. package/dist/types/i18n/resolve-widget-locale.d.ts.map +1 -1
  69. package/dist/types/lib/widget-config.d.ts +13 -1
  70. package/dist/types/lib/widget-config.d.ts.map +1 -1
  71. package/dist/types/lib/widgetBootstrap.d.ts +7 -0
  72. package/dist/types/lib/widgetBootstrap.d.ts.map +1 -1
  73. package/dist/types/module/screens/ScreenRouter.d.ts +3 -1
  74. package/dist/types/module/screens/ScreenRouter.d.ts.map +1 -1
  75. package/dist/types/module/shell/WidgetShell.d.ts.map +1 -1
  76. package/dist/types/module/shell/hooks/useBootstrap.d.ts +2 -1
  77. package/dist/types/module/shell/hooks/useBootstrap.d.ts.map +1 -1
  78. package/dist/types/module/shell/hooks/usePreviewBridge.d.ts +6 -3
  79. package/dist/types/module/shell/hooks/usePreviewBridge.d.ts.map +1 -1
  80. package/dist/types/module/shell/mount.d.ts.map +1 -1
  81. package/dist/types/module/shell/shell.state.d.ts +12 -0
  82. package/dist/types/module/shell/shell.state.d.ts.map +1 -1
  83. package/dist/types/module/shell/widget-instance.d.ts.map +1 -1
  84. package/dist/types/shared/ui/Footer.d.ts +1 -1
  85. package/dist/types/shared/ui/Footer.d.ts.map +1 -1
  86. package/dist/types/shared/ui/Header.d.ts +3 -1
  87. package/dist/types/shared/ui/Header.d.ts.map +1 -1
  88. package/dist/types/shared/ui/HeaderActions.d.ts +4 -2
  89. package/dist/types/shared/ui/HeaderActions.d.ts.map +1 -1
  90. package/dist/types/shared/ui/HeaderLocalePicker.d.ts +8 -0
  91. package/dist/types/shared/ui/HeaderLocalePicker.d.ts.map +1 -0
  92. package/dist/types/shared/ui/HeaderTitle.d.ts +1 -1
  93. package/dist/types/shared/ui/HeaderTitle.d.ts.map +1 -1
  94. package/dist/types/types.d.ts +9 -0
  95. package/dist/types/types.d.ts.map +1 -1
  96. package/dist/widget.js +42 -42
  97. package/dist/widget.js.map +1 -1
  98. package/package.json +2 -2
@@ -4,6 +4,8 @@ interface JexityChatContextValue {
4
4
  open: () => void;
5
5
  close: () => void;
6
6
  toggle: () => void;
7
+ /** Opens the chat and sends `text` as the visitor's message. */
8
+ ask: (text: string) => void;
7
9
  isOpen: boolean;
8
10
  }
9
11
  export interface JexityChatProviderProps extends JexityChatOptions {
@@ -1 +1 @@
1
- {"version":3,"file":"react.d.ts","sourceRoot":"","sources":["../../../src/entries/react.tsx"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAA;AACtC,OAAO,KAAK,EAAE,iBAAiB,EAAsB,MAAM,UAAU,CAAA;AAGrE,UAAU,sBAAsB;IAC9B,IAAI,EAAE,MAAM,IAAI,CAAA;IAChB,KAAK,EAAE,MAAM,IAAI,CAAA;IACjB,MAAM,EAAE,MAAM,IAAI,CAAA;IAClB,MAAM,EAAE,OAAO,CAAA;CAChB;AAID,MAAM,WAAW,uBAAwB,SAAQ,iBAAiB;IAChE,QAAQ,CAAC,EAAE,SAAS,CAAA;CACrB;AAED,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,uBAAuB,0GAsGhE;AAED,wBAAgB,aAAa,IAAI,sBAAsB,CAMtD"}
1
+ {"version":3,"file":"react.d.ts","sourceRoot":"","sources":["../../../src/entries/react.tsx"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAA;AACtC,OAAO,KAAK,EAAE,iBAAiB,EAAsB,MAAM,UAAU,CAAA;AAGrE,UAAU,sBAAsB;IAC9B,IAAI,EAAE,MAAM,IAAI,CAAA;IAChB,KAAK,EAAE,MAAM,IAAI,CAAA;IACjB,MAAM,EAAE,MAAM,IAAI,CAAA;IAClB,gEAAgE;IAChE,GAAG,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAA;IAC3B,MAAM,EAAE,OAAO,CAAA;CAChB;AAID,MAAM,WAAW,uBAAwB,SAAQ,iBAAiB;IAChE,QAAQ,CAAC,EAAE,SAAS,CAAA;CACrB;AAED,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,uBAAuB,0GA4GhE;AAED,wBAAgB,aAAa,IAAI,sBAAsB,CAMtD"}
@@ -14,6 +14,8 @@ interface ChatScreenProps {
14
14
  isOrgDeleted: boolean;
15
15
  ensureSession: () => Promise<SessionResult | null>;
16
16
  startFresh: () => Promise<SessionResult | null>;
17
+ /** True while the deployment's write-freeze is active — disables the composer. */
18
+ maintenance: boolean;
17
19
  }
18
20
  /**
19
21
  * Chat screen — renders immediately with greeting + input.
@@ -25,6 +27,6 @@ interface ChatScreenProps {
25
27
  * Note: session state is hoisted into WidgetShell so the Header can show
26
28
  * HumanHandoffAction with the same sessionId/visitorId — no duplicate subscriptions.
27
29
  */
28
- export declare function ChatScreen({ greeting, botName, starterQuestions, sessionId, visitorId, isLoading, sessionNotFound, resumeFailed, isOrgDeleted, ensureSession, startFresh }: ChatScreenProps): import("preact").JSX.Element;
30
+ export declare function ChatScreen({ greeting, botName, starterQuestions, sessionId, visitorId, isLoading, sessionNotFound, resumeFailed, isOrgDeleted, ensureSession, startFresh, maintenance }: ChatScreenProps): import("preact").JSX.Element;
29
31
  export {};
30
32
  //# sourceMappingURL=ChatScreen.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"ChatScreen.d.ts","sourceRoot":"","sources":["../../../../../src/features/chat/components/ChatScreen.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,EAAE,EAAE,MAAM,2CAA2C,CAAA;AAanE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAA;AAE9D,UAAU,eAAe;IACvB,QAAQ,EAAE,MAAM,CAAA;IAChB,qFAAqF;IACrF,OAAO,EAAE,MAAM,CAAA;IACf,wEAAwE;IACxE,gBAAgB,EAAE,MAAM,EAAE,CAAA;IAE1B,SAAS,EAAE,EAAE,CAAC,iBAAiB,CAAC,GAAG,IAAI,CAAA;IACvC,SAAS,EAAE,MAAM,GAAG,IAAI,CAAA;IACxB,SAAS,EAAE,OAAO,CAAA;IAClB,eAAe,EAAE,OAAO,CAAA;IACxB,YAAY,EAAE,OAAO,CAAA;IACrB,YAAY,EAAE,OAAO,CAAA;IACrB,aAAa,EAAE,MAAM,OAAO,CAAC,aAAa,GAAG,IAAI,CAAC,CAAA;IAClD,UAAU,EAAE,MAAM,OAAO,CAAC,aAAa,GAAG,IAAI,CAAC,CAAA;CAChD;AAED;;;;;;;;;GASG;AACH,wBAAgB,UAAU,CAAC,EAAE,QAAQ,EAAE,OAAO,EAAE,gBAAgB,EAAE,SAAS,EAAE,SAAS,EAAE,SAAS,EAAE,eAAe,EAAE,YAAY,EAAE,YAAY,EAAE,aAAa,EAAE,UAAU,EAAE,EAAE,eAAe,gCAkJ3L"}
1
+ {"version":3,"file":"ChatScreen.d.ts","sourceRoot":"","sources":["../../../../../src/features/chat/components/ChatScreen.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,EAAE,EAAE,MAAM,2CAA2C,CAAA;AAenE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAA;AAE9D,UAAU,eAAe;IACvB,QAAQ,EAAE,MAAM,CAAA;IAChB,qFAAqF;IACrF,OAAO,EAAE,MAAM,CAAA;IACf,wEAAwE;IACxE,gBAAgB,EAAE,MAAM,EAAE,CAAA;IAE1B,SAAS,EAAE,EAAE,CAAC,iBAAiB,CAAC,GAAG,IAAI,CAAA;IACvC,SAAS,EAAE,MAAM,GAAG,IAAI,CAAA;IACxB,SAAS,EAAE,OAAO,CAAA;IAClB,eAAe,EAAE,OAAO,CAAA;IACxB,YAAY,EAAE,OAAO,CAAA;IACrB,YAAY,EAAE,OAAO,CAAA;IACrB,aAAa,EAAE,MAAM,OAAO,CAAC,aAAa,GAAG,IAAI,CAAC,CAAA;IAClD,UAAU,EAAE,MAAM,OAAO,CAAC,aAAa,GAAG,IAAI,CAAC,CAAA;IAC/C,kFAAkF;IAClF,WAAW,EAAE,OAAO,CAAA;CACrB;AAED;;;;;;;;;GASG;AACH,wBAAgB,UAAU,CAAC,EAAE,QAAQ,EAAE,OAAO,EAAE,gBAAgB,EAAE,SAAS,EAAE,SAAS,EAAE,SAAS,EAAE,eAAe,EAAE,YAAY,EAAE,YAAY,EAAE,aAAa,EAAE,UAAU,EAAE,WAAW,EAAE,EAAE,eAAe,gCAuKxM"}
@@ -1,9 +1,11 @@
1
+ import type { Availability } from '../hooks/useAvailability';
1
2
  import type { Id } from '@repo/backend/convex/_generated/dataModel';
2
3
  interface EscalationFormScreenProps {
3
4
  formMessageId: Id<'conversations'>;
4
5
  sessionId: Id<'contactSessions'>;
5
6
  visitorId: string;
6
- orgSlug: string;
7
+ /** Live availability from the shell (per project when the embed names one). */
8
+ availability?: Availability;
7
9
  waitingSetAt: number;
8
10
  }
9
11
  /**
@@ -11,6 +13,6 @@ interface EscalationFormScreenProps {
11
13
  * Uses the same .jex-form-* styling as FormScreen but calls the real
12
14
  * submitEscalation mutation instead of a mock.
13
15
  */
14
- export declare function EscalationFormScreen({ formMessageId, sessionId, visitorId, orgSlug }: EscalationFormScreenProps): import("preact").JSX.Element;
16
+ export declare function EscalationFormScreen({ formMessageId, sessionId, visitorId, availability }: EscalationFormScreenProps): import("preact").JSX.Element;
15
17
  export {};
16
18
  //# sourceMappingURL=EscalationFormScreen.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"EscalationFormScreen.d.ts","sourceRoot":"","sources":["../../../../../src/features/chat/components/EscalationFormScreen.tsx"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,EAAE,EAAE,MAAM,2CAA2C,CAAA;AAEnE,UAAU,yBAAyB;IACjC,aAAa,EAAE,EAAE,CAAC,eAAe,CAAC,CAAA;IAClC,SAAS,EAAE,EAAE,CAAC,iBAAiB,CAAC,CAAA;IAChC,SAAS,EAAE,MAAM,CAAA;IACjB,OAAO,EAAE,MAAM,CAAA;IACf,YAAY,EAAE,MAAM,CAAA;CACrB;AAED;;;;GAIG;AACH,wBAAgB,oBAAoB,CAAC,EAAE,aAAa,EAAE,SAAS,EAAE,SAAS,EAAE,OAAO,EAAE,EAAE,yBAAyB,gCAsE/G"}
1
+ {"version":3,"file":"EscalationFormScreen.d.ts","sourceRoot":"","sources":["../../../../../src/features/chat/components/EscalationFormScreen.tsx"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAA;AAE5D,OAAO,KAAK,EAAE,EAAE,EAAE,MAAM,2CAA2C,CAAA;AAEnE,UAAU,yBAAyB;IACjC,aAAa,EAAE,EAAE,CAAC,eAAe,CAAC,CAAA;IAClC,SAAS,EAAE,EAAE,CAAC,iBAAiB,CAAC,CAAA;IAChC,SAAS,EAAE,MAAM,CAAA;IACjB,+EAA+E;IAC/E,YAAY,CAAC,EAAE,YAAY,CAAA;IAC3B,YAAY,EAAE,MAAM,CAAA;CACrB;AAED;;;;GAIG;AACH,wBAAgB,oBAAoB,CAAC,EAAE,aAAa,EAAE,SAAS,EAAE,SAAS,EAAE,YAAY,EAAE,EAAE,yBAAyB,gCA8EpH"}
@@ -1 +1 @@
1
- {"version":3,"file":"FormMessage.d.ts","sourceRoot":"","sources":["../../../../../src/features/chat/components/FormMessage.tsx"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,GAAG,EAAE,EAAE,EAAE,MAAM,2CAA2C,CAAA;AAExE,UAAU,gBAAgB;IACxB,OAAO,EAAE,GAAG,CAAC,eAAe,CAAC,CAAA;IAC7B,SAAS,EAAE,EAAE,CAAC,iBAAiB,CAAC,CAAA;IAChC,SAAS,EAAE,MAAM,CAAA;IACjB,YAAY,EAAE,MAAM,CAAA;CACrB;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,WAAW,CAAC,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,YAAY,EAAE,EAAE,gBAAgB,gCA6B5F"}
1
+ {"version":3,"file":"FormMessage.d.ts","sourceRoot":"","sources":["../../../../../src/features/chat/components/FormMessage.tsx"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,GAAG,EAAE,EAAE,EAAE,MAAM,2CAA2C,CAAA;AAExE,UAAU,gBAAgB;IACxB,OAAO,EAAE,GAAG,CAAC,eAAe,CAAC,CAAA;IAC7B,SAAS,EAAE,EAAE,CAAC,iBAAiB,CAAC,CAAA;IAChC,SAAS,EAAE,MAAM,CAAA;IACjB,YAAY,EAAE,MAAM,CAAA;CACrB;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,WAAW,CAAC,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,YAAY,EAAE,EAAE,gBAAgB,gCA6B5F"}
@@ -16,6 +16,16 @@ interface HumanHandoffActionProps {
16
16
  *
17
17
  * Calls createEscalationRequest. Backend decides whether the form is needed.
18
18
  * Zero LLM tokens consumed on this path.
19
+ *
20
+ * Disabled while the deployment is frozen. A handoff is a promise that a human
21
+ * will pick this up, and recording it is a write — so during maintenance the
22
+ * request cannot be stored and nobody would ever see it. Left enabled, the
23
+ * click reached `createOrResume`, was refused by the freeze, and died in the
24
+ * console: the visitor pressed a button and nothing happened at all.
25
+ *
26
+ * Gated here rather than in `ChatScreen` because the button lives in the
27
+ * Header, which `WidgetShell` renders TWICE — once embedded, once floating. A
28
+ * prop threaded from one path would have left the other still broken.
19
29
  */
20
30
  export declare function HumanHandoffAction({ sessionId, visitorId, ensureSession, availability }: HumanHandoffActionProps): import("preact").JSX.Element;
21
31
  export {};
@@ -1 +1 @@
1
- {"version":3,"file":"HumanHandoffAction.d.ts","sourceRoot":"","sources":["../../../../../src/features/chat/components/HumanHandoffAction.tsx"],"names":[],"mappings":"AACA,OAAO,EAAoB,KAAK,YAAY,EAAE,MAAM,0BAA0B,CAAA;AAE9E,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAA;AAC9D,OAAO,KAAK,EAAE,EAAE,EAAE,MAAM,2CAA2C,CAAA;AAEnE,UAAU,uBAAuB;IAC/B,SAAS,EAAE,EAAE,CAAC,iBAAiB,CAAC,GAAG,IAAI,CAAA;IACvC,SAAS,EAAE,MAAM,GAAG,IAAI,CAAA;IACxB;8EAC0E;IAC1E,aAAa,EAAE,MAAM,OAAO,CAAC,aAAa,GAAG,IAAI,CAAC,CAAA;IAClD;4EACwE;IACxE,YAAY,CAAC,EAAE,YAAY,CAAA;CAC5B;AAED;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAAC,EAAE,SAAS,EAAE,SAAS,EAAE,aAAa,EAAE,YAAY,EAAE,EAAE,uBAAuB,gCA+BhH"}
1
+ {"version":3,"file":"HumanHandoffAction.d.ts","sourceRoot":"","sources":["../../../../../src/features/chat/components/HumanHandoffAction.tsx"],"names":[],"mappings":"AACA,OAAO,EAAoB,KAAK,YAAY,EAAE,MAAM,0BAA0B,CAAA;AAG9E,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAA;AAC9D,OAAO,KAAK,EAAE,EAAE,EAAE,MAAM,2CAA2C,CAAA;AAEnE,UAAU,uBAAuB;IAC/B,SAAS,EAAE,EAAE,CAAC,iBAAiB,CAAC,GAAG,IAAI,CAAA;IACvC,SAAS,EAAE,MAAM,GAAG,IAAI,CAAA;IACxB;8EAC0E;IAC1E,aAAa,EAAE,MAAM,OAAO,CAAC,aAAa,GAAG,IAAI,CAAC,CAAA;IAClD;4EACwE;IACxE,YAAY,CAAC,EAAE,YAAY,CAAA;CAC5B;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,kBAAkB,CAAC,EAAE,SAAS,EAAE,SAAS,EAAE,aAAa,EAAE,YAAY,EAAE,EAAE,uBAAuB,gCAkChH"}
@@ -0,0 +1,19 @@
1
+ import type { FunctionReturnType } from 'convex/server';
2
+ import { api } from '@repo/backend/convex/_generated/api';
3
+ import type { Id } from '@repo/backend/convex/_generated/dataModel';
4
+ export type AttachmentRow = FunctionReturnType<typeof api.conversationAttachments.visitor.list>[number];
5
+ interface MessageAttachmentsProps {
6
+ items: readonly AttachmentRow[];
7
+ sessionId: Id<'contactSessions'>;
8
+ visitorId: string;
9
+ align: 'user' | 'bot';
10
+ }
11
+ /**
12
+ * The files of one message, under its bubble: image thumbnails and file
13
+ * cards that open in a new tab through a 15-minute signed URL, and a muted
14
+ * card for a file that is gone. When the links cannot be loaded, the files
15
+ * show as cards with a line that says so and a retry button.
16
+ */
17
+ export declare function MessageAttachments({ items, sessionId, visitorId, align }: MessageAttachmentsProps): import("preact").JSX.Element | null;
18
+ export {};
19
+ //# sourceMappingURL=MessageAttachments.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"MessageAttachments.d.ts","sourceRoot":"","sources":["../../../../../src/features/chat/components/MessageAttachments.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAA;AAEvD,OAAO,EAAE,GAAG,EAAE,MAAM,qCAAqC,CAAA;AACzD,OAAO,KAAK,EAAE,EAAE,EAAE,MAAM,2CAA2C,CAAA;AAInE,MAAM,MAAM,aAAa,GAAG,kBAAkB,CAAC,OAAO,GAAG,CAAC,uBAAuB,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,CAAA;AAYvG,UAAU,uBAAuB;IAC/B,KAAK,EAAE,SAAS,aAAa,EAAE,CAAA;IAC/B,SAAS,EAAE,EAAE,CAAC,iBAAiB,CAAC,CAAA;IAChC,SAAS,EAAE,MAAM,CAAA;IACjB,KAAK,EAAE,MAAM,GAAG,KAAK,CAAA;CACtB;AAED;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAAC,EAAE,KAAK,EAAE,SAAS,EAAE,SAAS,EAAE,KAAK,EAAE,EAAE,uBAAuB,uCA2GjG"}
@@ -1,6 +1,9 @@
1
+ import { type AttachmentRow } from './MessageAttachments';
1
2
  import type { Doc, Id } from '@repo/backend/convex/_generated/dataModel';
2
3
  interface MessageListProps {
3
4
  conversations: Doc<'conversations'>[] | undefined;
5
+ /** The session's sent files; shown under the message that carried them. */
6
+ attachments?: readonly AttachmentRow[];
4
7
  greeting: string;
5
8
  /** The widget title / bot display name (shown in each bot message header). */
6
9
  botName: string;
@@ -20,6 +23,6 @@ interface MessageListProps {
20
23
  visitorId: string | null;
21
24
  }
22
25
  /** Scrollable message area — renders messages with streaming status support. */
23
- export declare function MessageList({ conversations, greeting, botName, starterQuestions, onPickStarter, sessionNotFound, resumeFailed, onStartFresh, sessionId, visitorId }: MessageListProps): import("preact").JSX.Element;
26
+ export declare function MessageList({ conversations, attachments, greeting, botName, starterQuestions, onPickStarter, sessionNotFound, resumeFailed, onStartFresh, sessionId, visitorId }: MessageListProps): import("preact").JSX.Element;
24
27
  export {};
25
28
  //# sourceMappingURL=MessageList.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"MessageList.d.ts","sourceRoot":"","sources":["../../../../../src/features/chat/components/MessageList.tsx"],"names":[],"mappings":"AAaA,OAAO,KAAK,EAAE,GAAG,EAAE,EAAE,EAAE,MAAM,2CAA2C,CAAA;AA+ExE,UAAU,gBAAgB;IACxB,aAAa,EAAE,GAAG,CAAC,eAAe,CAAC,EAAE,GAAG,SAAS,CAAA;IACjD,QAAQ,EAAE,MAAM,CAAA;IAChB,8EAA8E;IAC9E,OAAO,EAAE,MAAM,CAAA;IACf,wEAAwE;IACxE,gBAAgB,EAAE,MAAM,EAAE,CAAA;IAC1B,kEAAkE;IAClE,aAAa,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAA;IACrC,8DAA8D;IAC9D,eAAe,CAAC,EAAE,OAAO,CAAA;IACzB,oEAAoE;IACpE,YAAY,CAAC,EAAE,OAAO,CAAA;IACtB,8DAA8D;IAC9D,YAAY,CAAC,EAAE,MAAM,IAAI,CAAA;IACzB,iDAAiD;IACjD,SAAS,EAAE,EAAE,CAAC,iBAAiB,CAAC,GAAG,IAAI,CAAA;IACvC,iDAAiD;IACjD,SAAS,EAAE,MAAM,GAAG,IAAI,CAAA;CACzB;AAED,gFAAgF;AAChF,wBAAgB,WAAW,CAAC,EAAE,aAAa,EAAE,QAAQ,EAAE,OAAO,EAAE,gBAAgB,EAAE,aAAa,EAAE,eAAe,EAAE,YAAY,EAAE,YAAY,EAAE,SAAS,EAAE,SAAS,EAAE,EAAE,gBAAgB,gCA2NrL"}
1
+ {"version":3,"file":"MessageList.d.ts","sourceRoot":"","sources":["../../../../../src/features/chat/components/MessageList.tsx"],"names":[],"mappings":"AAUA,OAAO,EAAsB,KAAK,aAAa,EAAE,MAAM,sBAAsB,CAAA;AAM7E,OAAO,KAAK,EAAE,GAAG,EAAE,EAAE,EAAE,MAAM,2CAA2C,CAAA;AA+ExE,UAAU,gBAAgB;IACxB,aAAa,EAAE,GAAG,CAAC,eAAe,CAAC,EAAE,GAAG,SAAS,CAAA;IACjD,2EAA2E;IAC3E,WAAW,CAAC,EAAE,SAAS,aAAa,EAAE,CAAA;IACtC,QAAQ,EAAE,MAAM,CAAA;IAChB,8EAA8E;IAC9E,OAAO,EAAE,MAAM,CAAA;IACf,wEAAwE;IACxE,gBAAgB,EAAE,MAAM,EAAE,CAAA;IAC1B,kEAAkE;IAClE,aAAa,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAA;IACrC,8DAA8D;IAC9D,eAAe,CAAC,EAAE,OAAO,CAAA;IACzB,oEAAoE;IACpE,YAAY,CAAC,EAAE,OAAO,CAAA;IACtB,8DAA8D;IAC9D,YAAY,CAAC,EAAE,MAAM,IAAI,CAAA;IACzB,iDAAiD;IACjD,SAAS,EAAE,EAAE,CAAC,iBAAiB,CAAC,GAAG,IAAI,CAAA;IACvC,iDAAiD;IACjD,SAAS,EAAE,MAAM,GAAG,IAAI,CAAA;CACzB;AAaD,gFAAgF;AAChF,wBAAgB,WAAW,CAAC,EAAE,aAAa,EAAE,WAAW,EAAE,QAAQ,EAAE,OAAO,EAAE,gBAAgB,EAAE,aAAa,EAAE,eAAe,EAAE,YAAY,EAAE,YAAY,EAAE,SAAS,EAAE,SAAS,EAAE,EAAE,gBAAgB,gCA2QlM"}
@@ -1 +1 @@
1
- {"version":3,"file":"TrialSessionBookingForm.d.ts","sourceRoot":"","sources":["../../../../../../src/features/chat/components/magicline/TrialSessionBookingForm.tsx"],"names":[],"mappings":"AAeA,OAAO,KAAK,EAAE,EAAE,EAAE,MAAM,2CAA2C,CAAA;AAEnE,UAAU,4BAA4B;IACpC,aAAa,EAAE,EAAE,CAAC,eAAe,CAAC,CAAA;IAClC,SAAS,EAAE,EAAE,CAAC,iBAAiB,CAAC,CAAA;IAChC,SAAS,EAAE,MAAM,CAAA;IACjB,qEAAqE;IACrE,eAAe,CAAC,EAAE,OAAO,CAAA;IACzB;;;;OAIG;IACH,YAAY,CAAC,EAAE,OAAO,CAAA;CACvB;AAKD;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,uBAAuB,CAAC,EACtC,aAAa,EACb,SAAS,EACT,SAAS,EACT,eAAuB,EACvB,YAAoB,GACrB,EAAE,4BAA4B,gCA2C9B"}
1
+ {"version":3,"file":"TrialSessionBookingForm.d.ts","sourceRoot":"","sources":["../../../../../../src/features/chat/components/magicline/TrialSessionBookingForm.tsx"],"names":[],"mappings":"AAgBA,OAAO,KAAK,EAAE,EAAE,EAAE,MAAM,2CAA2C,CAAA;AAEnE,UAAU,4BAA4B;IACpC,aAAa,EAAE,EAAE,CAAC,eAAe,CAAC,CAAA;IAClC,SAAS,EAAE,EAAE,CAAC,iBAAiB,CAAC,CAAA;IAChC,SAAS,EAAE,MAAM,CAAA;IACjB,qEAAqE;IACrE,eAAe,CAAC,EAAE,OAAO,CAAA;IACzB;;;;OAIG;IACH,YAAY,CAAC,EAAE,OAAO,CAAA;CACvB;AAKD;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,uBAAuB,CAAC,EACtC,aAAa,EACb,SAAS,EACT,SAAS,EACT,eAAuB,EACvB,YAAoB,GACrB,EAAE,4BAA4B,gCA2C9B"}
@@ -11,8 +11,11 @@ interface ChatInputProps {
11
11
  visitorId: string;
12
12
  } | null>;
13
13
  onStartFresh: () => void;
14
+ /** True while the deployment's write-freeze is active — disables the composer,
15
+ * preserving any draft text, and shows the maintenance notice. */
16
+ maintenance?: boolean;
14
17
  }
15
18
  /** Composer area: stacks inline notices above a single focus-within input row. */
16
- export declare function ChatInput({ sessionId, visitorId, isLoading, isStreaming, sessionStatus, ensureSession, onStartFresh, }: ChatInputProps): import("preact").JSX.Element;
19
+ export declare function ChatInput({ sessionId, visitorId, isLoading, isStreaming, sessionStatus, ensureSession, onStartFresh, maintenance, }: ChatInputProps): import("preact").JSX.Element;
17
20
  export {};
18
21
  //# sourceMappingURL=ChatInput.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"ChatInput.d.ts","sourceRoot":"","sources":["../../../../../../src/features/chat/composer/components/ChatInput.tsx"],"names":[],"mappings":"AAiBA,OAAO,KAAK,EAAE,EAAE,EAAE,MAAM,2CAA2C,CAAA;AACnE,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,6BAA6B,CAAA;AAEpE,UAAU,cAAc;IACtB,SAAS,EAAE,EAAE,CAAC,iBAAiB,CAAC,GAAG,IAAI,CAAA;IACvC,SAAS,EAAE,MAAM,GAAG,IAAI,CAAA;IACxB,SAAS,EAAE,OAAO,CAAA;IAClB,WAAW,EAAE,OAAO,CAAA;IAGpB,aAAa,EAAE,iBAAiB,GAAG,IAAI,CAAA;IACvC,aAAa,EAAE,MAAM,OAAO,CAAC;QAAE,SAAS,EAAE,EAAE,CAAC,iBAAiB,CAAC,CAAC;QAAC,SAAS,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC,CAAA;IAC5F,YAAY,EAAE,MAAM,IAAI,CAAA;CACzB;AAED,kFAAkF;AAClF,wBAAgB,SAAS,CAAC,EACxB,SAAS,EACT,SAAS,EACT,SAAS,EACT,WAAW,EACX,aAAa,EACb,aAAa,EACb,YAAY,GACb,EAAE,cAAc,gCA4EhB"}
1
+ {"version":3,"file":"ChatInput.d.ts","sourceRoot":"","sources":["../../../../../../src/features/chat/composer/components/ChatInput.tsx"],"names":[],"mappings":"AAyBA,OAAO,KAAK,EAAE,EAAE,EAAE,MAAM,2CAA2C,CAAA;AACnE,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,6BAA6B,CAAA;AAEpE,UAAU,cAAc;IACtB,SAAS,EAAE,EAAE,CAAC,iBAAiB,CAAC,GAAG,IAAI,CAAA;IACvC,SAAS,EAAE,MAAM,GAAG,IAAI,CAAA;IACxB,SAAS,EAAE,OAAO,CAAA;IAClB,WAAW,EAAE,OAAO,CAAA;IAGpB,aAAa,EAAE,iBAAiB,GAAG,IAAI,CAAA;IACvC,aAAa,EAAE,MAAM,OAAO,CAAC;QAAE,SAAS,EAAE,EAAE,CAAC,iBAAiB,CAAC,CAAC;QAAC,SAAS,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC,CAAA;IAC5F,YAAY,EAAE,MAAM,IAAI,CAAA;IACxB;uEACmE;IACnE,WAAW,CAAC,EAAE,OAAO,CAAA;CACtB;AAED,kFAAkF;AAClF,wBAAgB,SAAS,CAAC,EACxB,SAAS,EACT,SAAS,EACT,SAAS,EACT,WAAW,EACX,aAAa,EACb,aAAa,EACb,YAAY,EACZ,WAAmB,GACpB,EAAE,cAAc,gCAqHhB"}
@@ -4,25 +4,32 @@ interface ComposerRowProps {
4
4
  inputDisabled: boolean;
5
5
  onSend: () => void;
6
6
  onFocus?: () => void;
7
+ /** Visitor files may be sent here (widget switch on, a person joined, Media live). */
8
+ canAttach: boolean;
9
+ /** Picked files; the caller uploads them. */
10
+ onFiles: (files: File[]) => void;
7
11
  }
8
12
  /**
9
- * Composer row — autosize textarea, attach button, staged image chips,
13
+ * Composer row — autosize textarea, attach button, staged file chips,
10
14
  * and a state-driven send button rendered inside one focus-within card.
11
15
  *
12
16
  * Pure presentation. All side effects (autosize, file picker proxy,
13
17
  * focus-on-empty-click, Enter-to-send) live in `useComposerInput`.
14
18
  * The component reads two composer signals (`draftMessage`,
15
- * `attachedImages`) for render-time conditionals and writes through
16
- * the hook + `removeAttachedImage`.
19
+ * `stagedFiles`) for render-time conditionals and writes through
20
+ * the hook + `removeStaged`. Uploads run in `useAttachmentUpload`.
17
21
  *
18
22
  * Design notes:
19
23
  * - The whole card owns the border + focus-within highlight so the
20
24
  * send button can never overflow at narrow viewports.
21
- * - Send button has two visual states: "muted" (no draft / images)
22
- * and "active" (something to send). Streaming locks the textarea
25
+ * - Send button has two visual states: "muted" (no draft / ready file,
26
+ * or a file still uploading) and "active" (something to send). Streaming locks the textarea
23
27
  * via `inputDisabled` upstream; the button stays muted because
24
28
  * hasInput is false after clear-on-send.
29
+ * - Mic (voice dictation) is gated by the `voiceDictationEnabled` platform
30
+ * flag and browser support; dictation is cancelled on send and whenever
31
+ * the input locks.
25
32
  */
26
- export declare function ComposerRow({ isStreaming, disabled, inputDisabled, onSend, onFocus }: ComposerRowProps): import("preact").JSX.Element;
33
+ export declare function ComposerRow({ isStreaming, disabled, inputDisabled, onSend, onFocus, canAttach, onFiles }: ComposerRowProps): import("preact").JSX.Element;
27
34
  export {};
28
35
  //# sourceMappingURL=ComposerRow.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"ComposerRow.d.ts","sourceRoot":"","sources":["../../../../../../src/features/chat/composer/components/ComposerRow.tsx"],"names":[],"mappings":"AAKA,UAAU,gBAAgB;IACxB,WAAW,EAAE,OAAO,CAAA;IACpB,QAAQ,EAAE,OAAO,CAAA;IACjB,aAAa,EAAE,OAAO,CAAA;IACtB,MAAM,EAAE,MAAM,IAAI,CAAA;IAClB,OAAO,CAAC,EAAE,MAAM,IAAI,CAAA;CACrB;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,WAAW,CAAC,EAAE,WAAW,EAAE,QAAQ,EAAE,aAAa,EAAE,MAAM,EAAE,OAAO,EAAE,EAAE,gBAAgB,gCAiHtG"}
1
+ {"version":3,"file":"ComposerRow.d.ts","sourceRoot":"","sources":["../../../../../../src/features/chat/composer/components/ComposerRow.tsx"],"names":[],"mappings":"AAqBA,UAAU,gBAAgB;IACxB,WAAW,EAAE,OAAO,CAAA;IACpB,QAAQ,EAAE,OAAO,CAAA;IACjB,aAAa,EAAE,OAAO,CAAA;IACtB,MAAM,EAAE,MAAM,IAAI,CAAA;IAClB,OAAO,CAAC,EAAE,MAAM,IAAI,CAAA;IACpB,sFAAsF;IACtF,SAAS,EAAE,OAAO,CAAA;IAClB,6CAA6C;IAC7C,OAAO,EAAE,CAAC,KAAK,EAAE,IAAI,EAAE,KAAK,IAAI,CAAA;CACjC;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,WAAW,CAAC,EAAE,WAAW,EAAE,QAAQ,EAAE,aAAa,EAAE,MAAM,EAAE,OAAO,EAAE,SAAS,EAAE,OAAO,EAAE,EAAE,gBAAgB,gCAmM1H"}
@@ -0,0 +1,13 @@
1
+ interface MicButtonProps {
2
+ listening: boolean;
3
+ disabled: boolean;
4
+ onClick: () => void;
5
+ }
6
+ /**
7
+ * Voice-dictation toggle. The ring scales with the live mic level while
8
+ * listening; under reduced motion / on touch devices the level stays 0 and
9
+ * CSS pulses the ring instead (`.jex-mic-btn-listening .jex-mic-ring`).
10
+ */
11
+ export declare function MicButton({ listening, disabled, onClick }: MicButtonProps): import("preact").JSX.Element;
12
+ export {};
13
+ //# sourceMappingURL=MicButton.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"MicButton.d.ts","sourceRoot":"","sources":["../../../../../../src/features/chat/composer/components/MicButton.tsx"],"names":[],"mappings":"AAGA,UAAU,cAAc;IACtB,SAAS,EAAE,OAAO,CAAA;IAClB,QAAQ,EAAE,OAAO,CAAA;IACjB,OAAO,EAAE,MAAM,IAAI,CAAA;CACpB;AAED;;;;GAIG;AACH,wBAAgB,SAAS,CAAC,EAAE,SAAS,EAAE,QAAQ,EAAE,OAAO,EAAE,EAAE,cAAc,gCA0BzE"}
@@ -1,3 +1,16 @@
1
+ import { type SessionErrorReason } from '../../state';
2
+ /**
3
+ * Picks which reason to show. A live `sessionError` (from an actual failed
4
+ * send/resume attempt) always wins — it's the most current information. With
5
+ * no send attempt yet, the boot-time `maintenance` flag from the bootstrap
6
+ * response fills in so the notice shows on first render, not only after a
7
+ * failed send.
8
+ */
9
+ export declare function resolveSessionErrorReason(reason: SessionErrorReason | null, maintenance: boolean): SessionErrorReason | null;
10
+ interface SessionErrorNoticeProps {
11
+ /** True while the deployment's write-freeze is active — see resolveSessionErrorReason. */
12
+ maintenance?: boolean;
13
+ }
1
14
  /**
2
15
  * Inline banner rendered above the chat input when session creation fails.
3
16
  * Mirrors the RateLimitNotice pattern: module-scope signal, no prop drill,
@@ -7,5 +20,6 @@
7
20
  * silent catch in useConvexSession / refreshBootstrap writes a reason here
8
21
  * and this component renders it. See state/session-error.ts for the reason enum.
9
22
  */
10
- export declare function SessionErrorNotice(): import("preact").JSX.Element | null;
23
+ export declare function SessionErrorNotice({ maintenance }?: SessionErrorNoticeProps): import("preact").JSX.Element | null;
24
+ export {};
11
25
  //# sourceMappingURL=SessionErrorNotice.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"SessionErrorNotice.d.ts","sourceRoot":"","sources":["../../../../../../src/features/chat/composer/components/SessionErrorNotice.tsx"],"names":[],"mappings":"AAGA;;;;;;;;GAQG;AACH,wBAAgB,kBAAkB,wCAgBjC"}
1
+ {"version":3,"file":"SessionErrorNotice.d.ts","sourceRoot":"","sources":["../../../../../../src/features/chat/composer/components/SessionErrorNotice.tsx"],"names":[],"mappings":"AACA,OAAO,EAAgB,KAAK,kBAAkB,EAAE,MAAM,aAAa,CAAA;AAEnE;;;;;;GAMG;AACH,wBAAgB,yBAAyB,CACvC,MAAM,EAAE,kBAAkB,GAAG,IAAI,EACjC,WAAW,EAAE,OAAO,GACnB,kBAAkB,GAAG,IAAI,CAE3B;AAED,UAAU,uBAAuB;IAC/B,0FAA0F;IAC1F,WAAW,CAAC,EAAE,OAAO,CAAA;CACtB;AAED;;;;;;;;GAQG;AACH,wBAAgB,kBAAkB,CAAC,EAAE,WAAmB,EAAE,GAAE,uBAA4B,uCAiBvF"}
@@ -0,0 +1,21 @@
1
+ import type { Id } from '@repo/backend/convex/_generated/dataModel';
2
+ import type { WidgetStrings } from '../../../../i18n/locales/en';
3
+ interface UseAttachmentUploadArgs {
4
+ sessionId: Id<'contactSessions'> | null;
5
+ visitorId: string | null;
6
+ }
7
+ /**
8
+ * Visitor files: each picked file uploads at once, in the same three steps
9
+ * as the dashboard's Media upload (`apps/web/modules/saas/organization/media/hooks.ts`):
10
+ * reserve (signed PUT) → PUT straight to R2 → finalize (server checks the
11
+ * real size and file signature). The chip shows uploading / ready / failed.
12
+ * `addFiles` returns how many files were refused before upload (type, size,
13
+ * or more than 4).
14
+ */
15
+ export declare function useAttachmentUpload({ sessionId, visitorId }: UseAttachmentUploadArgs): {
16
+ addFiles: (files: File[]) => number;
17
+ };
18
+ /** One sentence for a failed chip or the live region. */
19
+ export declare function attachmentErrorText(code: string | null, s: WidgetStrings): string;
20
+ export {};
21
+ //# sourceMappingURL=useAttachmentUpload.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useAttachmentUpload.d.ts","sourceRoot":"","sources":["../../../../../../src/features/chat/composer/hooks/useAttachmentUpload.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,EAAE,EAAE,MAAM,2CAA2C,CAAA;AAEnE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,6BAA6B,CAAA;AAGhE,UAAU,uBAAuB;IAC/B,SAAS,EAAE,EAAE,CAAC,iBAAiB,CAAC,GAAG,IAAI,CAAA;IACvC,SAAS,EAAE,MAAM,GAAG,IAAI,CAAA;CACzB;AAED;;;;;;;GAOG;AACH,wBAAgB,mBAAmB,CAAC,EAAE,SAAS,EAAE,SAAS,EAAE,EAAE,uBAAuB,GAAG;IACtF,QAAQ,EAAE,CAAC,KAAK,EAAE,IAAI,EAAE,KAAK,MAAM,CAAA;CACpC,CAmDA;AAED,yDAAyD;AACzD,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,EAAE,CAAC,EAAE,aAAa,GAAG,MAAM,CAmBjF"}
@@ -2,6 +2,8 @@ import type { RefObject } from 'preact';
2
2
  interface UseComposerInputArgs {
3
3
  /** Called when the visitor presses Enter (without Shift). */
4
4
  onSend: () => void;
5
+ /** Called with the files the visitor picked (uploads start there). */
6
+ onFiles: (files: File[]) => void;
5
7
  }
6
8
  interface UseComposerInputResult {
7
9
  textareaRef: RefObject<HTMLTextAreaElement>;
@@ -10,7 +12,7 @@ interface UseComposerInputResult {
10
12
  onKeyDown: (e: KeyboardEvent) => void;
11
13
  /** Proxy click into the hidden native file input. */
12
14
  onAttachClick: () => void;
13
- /** Validate + stage selected files, then reset the input value. */
15
+ /** Hand picked files to `onFiles`, then reset the input value. */
14
16
  onFilesPicked: (e: Event) => void;
15
17
  /** Focus the textarea when the visitor clicks empty card padding. */
16
18
  onCardClick: (e: MouseEvent) => void;
@@ -30,6 +32,6 @@ interface UseComposerInputResult {
30
32
  * the autosize effect depends on the draft value, and that
31
33
  * dependency is composer-internal.
32
34
  */
33
- export declare function useComposerInput({ onSend }: UseComposerInputArgs): UseComposerInputResult;
35
+ export declare function useComposerInput({ onSend, onFiles }: UseComposerInputArgs): UseComposerInputResult;
34
36
  export {};
35
37
  //# sourceMappingURL=useComposerInput.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"useComposerInput.d.ts","sourceRoot":"","sources":["../../../../../../src/features/chat/composer/hooks/useComposerInput.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,QAAQ,CAAA;AAMvC,UAAU,oBAAoB;IAC5B,6DAA6D;IAC7D,MAAM,EAAE,MAAM,IAAI,CAAA;CACnB;AAED,UAAU,sBAAsB;IAI9B,WAAW,EAAE,SAAS,CAAC,mBAAmB,CAAC,CAAA;IAC3C,YAAY,EAAE,SAAS,CAAC,gBAAgB,CAAC,CAAA;IACzC,2CAA2C;IAC3C,SAAS,EAAE,CAAC,CAAC,EAAE,aAAa,KAAK,IAAI,CAAA;IACrC,qDAAqD;IACrD,aAAa,EAAE,MAAM,IAAI,CAAA;IACzB,mEAAmE;IACnE,aAAa,EAAE,CAAC,CAAC,EAAE,KAAK,KAAK,IAAI,CAAA;IACjC,qEAAqE;IACrE,WAAW,EAAE,CAAC,CAAC,EAAE,UAAU,KAAK,IAAI,CAAA;CACrC;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,gBAAgB,CAAC,EAAE,MAAM,EAAE,EAAE,oBAAoB,GAAG,sBAAsB,CAyEzF"}
1
+ {"version":3,"file":"useComposerInput.d.ts","sourceRoot":"","sources":["../../../../../../src/features/chat/composer/hooks/useComposerInput.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,QAAQ,CAAA;AAMvC,UAAU,oBAAoB;IAC5B,6DAA6D;IAC7D,MAAM,EAAE,MAAM,IAAI,CAAA;IAClB,sEAAsE;IACtE,OAAO,EAAE,CAAC,KAAK,EAAE,IAAI,EAAE,KAAK,IAAI,CAAA;CACjC;AAED,UAAU,sBAAsB;IAI9B,WAAW,EAAE,SAAS,CAAC,mBAAmB,CAAC,CAAA;IAC3C,YAAY,EAAE,SAAS,CAAC,gBAAgB,CAAC,CAAA;IACzC,2CAA2C;IAC3C,SAAS,EAAE,CAAC,CAAC,EAAE,aAAa,KAAK,IAAI,CAAA;IACrC,qDAAqD;IACrD,aAAa,EAAE,MAAM,IAAI,CAAA;IACzB,kEAAkE;IAClE,aAAa,EAAE,CAAC,CAAC,EAAE,KAAK,KAAK,IAAI,CAAA;IACjC,qEAAqE;IACrE,WAAW,EAAE,CAAC,CAAC,EAAE,UAAU,KAAK,IAAI,CAAA;CACrC;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,gBAAgB,CAAC,EAAE,MAAM,EAAE,OAAO,EAAE,EAAE,oBAAoB,GAAG,sBAAsB,CAwElG"}
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Live 0..1 microphone level while `active`, for the mic button's ring.
3
+ *
4
+ * Called inside MicButton so only the button re-renders per frame. Opens its
5
+ * own getUserMedia stream (SpeechRecognition does not expose its stream).
6
+ * Decorative: reduced motion, coarse pointer (single-capture mobile engines)
7
+ * or a denied stream → no stream, level stays 0, the CSS pulse takes over.
8
+ */
9
+ export declare function useMicLevel(active: boolean): number;
10
+ //# sourceMappingURL=useMicLevel.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useMicLevel.d.ts","sourceRoot":"","sources":["../../../../../../src/features/chat/composer/hooks/useMicLevel.ts"],"names":[],"mappings":"AAGA;;;;;;;GAOG;AACH,wBAAgB,WAAW,CAAC,MAAM,EAAE,OAAO,GAAG,MAAM,CAoDnD"}
@@ -16,11 +16,13 @@ interface UseSendMessageArgs {
16
16
  * - rate_limit response → write `rateLimitedUntilMs` signal
17
17
  * - success → `markActivity` so the session stays in history list
18
18
  * - network / NOT_FOUND throws → log
19
+ * - visitor files: the ready ones ride with the send and leave the
20
+ * composer only once the send succeeded (a rate-limited or failed send
21
+ * keeps them); a refused file turns its chip red with the reason
19
22
  *
20
23
  * The returned function takes only `content` because the session
21
- * deps are captured at hook-call time. Composer state mutations
22
- * (clear draft, clear staged images) remain in the calling component
23
- * so the component still owns its composer reset.
24
+ * deps are captured at hook-call time. `content` may be empty when
25
+ * files are sent.
24
26
  */
25
27
  export declare function useSendMessage({ sessionId, visitorId, ensureSession }: UseSendMessageArgs): (content: string) => Promise<void>;
26
28
  export {};
@@ -1 +1 @@
1
- {"version":3,"file":"useSendMessage.d.ts","sourceRoot":"","sources":["../../../../../../src/features/chat/composer/hooks/useSendMessage.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,EAAE,EAAE,MAAM,2CAA2C,CAAA;AAcnE,UAAU,kBAAkB;IAC1B,SAAS,EAAE,EAAE,CAAC,iBAAiB,CAAC,GAAG,IAAI,CAAA;IACvC,SAAS,EAAE,MAAM,GAAG,IAAI,CAAA;IACxB,aAAa,EAAE,MAAM,OAAO,CAAC;QAAE,SAAS,EAAE,EAAE,CAAC,iBAAiB,CAAC,CAAC;QAAC,SAAS,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC,CAAA;CAC7F;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,cAAc,CAAC,EAAE,SAAS,EAAE,SAAS,EAAE,aAAa,EAAE,EAAE,kBAAkB,aAK7C,MAAM,KAAG,OAAO,CAAC,IAAI,CAAC,CAyFlE"}
1
+ {"version":3,"file":"useSendMessage.d.ts","sourceRoot":"","sources":["../../../../../../src/features/chat/composer/hooks/useSendMessage.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,EAAE,EAAE,MAAM,2CAA2C,CAAA;AAmBnE,UAAU,kBAAkB;IAC1B,SAAS,EAAE,EAAE,CAAC,iBAAiB,CAAC,GAAG,IAAI,CAAA;IACvC,SAAS,EAAE,MAAM,GAAG,IAAI,CAAA;IACxB,aAAa,EAAE,MAAM,OAAO,CAAC;QAAE,SAAS,EAAE,EAAE,CAAC,iBAAiB,CAAC,CAAC;QAAC,SAAS,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC,CAAA;CAC7F;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,cAAc,CAAC,EAAE,SAAS,EAAE,SAAS,EAAE,aAAa,EAAE,EAAE,kBAAkB,aAK7C,MAAM,KAAG,OAAO,CAAC,IAAI,CAAC,CAyGlE"}
@@ -0,0 +1,30 @@
1
+ import { type DictationError } from '../lib/dictation';
2
+ interface UseVoiceDictationArgs {
3
+ /** Widget UI locale (`de` / `en`) → recognition language. */
4
+ locale: string;
5
+ getDraft: () => string;
6
+ setDraft: (text: string) => void;
7
+ }
8
+ export interface VoiceDictation {
9
+ /** False on Firefox / insecure contexts — the caller renders no mic. */
10
+ supported: boolean;
11
+ listening: boolean;
12
+ error: DictationError | null;
13
+ toggle: () => void;
14
+ /** Abort immediately (send, lock, unmount). Pending interim words are dropped. */
15
+ cancel: () => void;
16
+ }
17
+ /**
18
+ * Browser-native dictation into the composer draft.
19
+ *
20
+ * - One recognition instance at a time; the draft snapshot at start is the base
21
+ * the transcript is appended to.
22
+ * - A draft that changed under us (visitor typed, a send cleared it) ends
23
+ * dictation without writing — one rule for typing and every send origin.
24
+ * - Mobile (coarse pointer) runs single-utterance: continuous mode duplicates
25
+ * results on Android and the engines allow one capture at a time.
26
+ * - Never logs the transcript.
27
+ */
28
+ export declare function useVoiceDictation({ locale, getDraft, setDraft }: UseVoiceDictationArgs): VoiceDictation;
29
+ export {};
30
+ //# sourceMappingURL=useVoiceDictation.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useVoiceDictation.d.ts","sourceRoot":"","sources":["../../../../../../src/features/chat/composer/hooks/useVoiceDictation.ts"],"names":[],"mappings":"AAEA,OAAO,EAOL,KAAK,cAAc,EAGpB,MAAM,kBAAkB,CAAA;AAMzB,UAAU,qBAAqB;IAC7B,6DAA6D;IAC7D,MAAM,EAAE,MAAM,CAAA;IACd,QAAQ,EAAE,MAAM,MAAM,CAAA;IACtB,QAAQ,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAA;CACjC;AAED,MAAM,WAAW,cAAc;IAC7B,wEAAwE;IACxE,SAAS,EAAE,OAAO,CAAA;IAClB,SAAS,EAAE,OAAO,CAAA;IAClB,KAAK,EAAE,cAAc,GAAG,IAAI,CAAA;IAC5B,MAAM,EAAE,MAAM,IAAI,CAAA;IAClB,kFAAkF;IAClF,MAAM,EAAE,MAAM,IAAI,CAAA;CACnB;AAMD;;;;;;;;;;GAUG;AACH,wBAAgB,iBAAiB,CAAC,EAAE,MAAM,EAAE,QAAQ,EAAE,QAAQ,EAAE,EAAE,qBAAqB,GAAG,cAAc,CAsLvG"}
@@ -0,0 +1,75 @@
1
+ /**
2
+ * Pure helpers behind `useVoiceDictation` / `useMicLevel` (browser-native
3
+ * speech-to-text into the composer draft). No DOM access here, so every
4
+ * branch is unit-testable in node.
5
+ *
6
+ * ponytail: twin of apps/web/modules/saas/organization/project/conversations/lib/voiceDictation.ts — fix both.
7
+ */
8
+ /** User-facing error buckets. `insecure` never surfaces: no secure context = unsupported = no button. */
9
+ export type DictationError = 'permission' | 'no-mic' | 'no-speech' | 'network' | 'lang';
10
+ export interface SpeechRecognitionAlternativeLike {
11
+ readonly transcript: string;
12
+ }
13
+ export interface SpeechRecognitionResultLike {
14
+ readonly isFinal: boolean;
15
+ readonly length: number;
16
+ readonly [index: number]: SpeechRecognitionAlternativeLike;
17
+ }
18
+ export interface SpeechRecognitionResultListLike {
19
+ readonly length: number;
20
+ readonly [index: number]: SpeechRecognitionResultLike;
21
+ }
22
+ export interface SpeechRecognitionEventLike {
23
+ readonly resultIndex: number;
24
+ readonly results: SpeechRecognitionResultListLike;
25
+ }
26
+ export interface SpeechRecognitionErrorEventLike {
27
+ readonly error: string;
28
+ }
29
+ export interface SpeechRecognitionLike {
30
+ lang: string;
31
+ continuous: boolean;
32
+ interimResults: boolean;
33
+ onresult: ((e: SpeechRecognitionEventLike) => void) | null;
34
+ onerror: ((e: SpeechRecognitionErrorEventLike) => void) | null;
35
+ onend: (() => void) | null;
36
+ start(): void;
37
+ stop(): void;
38
+ abort(): void;
39
+ }
40
+ export type SpeechRecognitionCtor = new () => SpeechRecognitionLike;
41
+ export interface SpeechHost {
42
+ readonly isSecureContext?: boolean;
43
+ readonly SpeechRecognition?: SpeechRecognitionCtor;
44
+ readonly webkitSpeechRecognition?: SpeechRecognitionCtor;
45
+ }
46
+ /** Feature detect: a secure context plus the standard or webkit-prefixed constructor. */
47
+ export declare function getSpeechRecognitionCtor(host: SpeechHost | undefined): SpeechRecognitionCtor | null;
48
+ /** UI locale → `recognition.lang`. German market default. */
49
+ export declare function toRecognitionLang(locale: string): string;
50
+ /**
51
+ * Raw `SpeechRecognitionErrorEvent.error` → bucket; `aborted` is a normal stop.
52
+ *
53
+ * `network` is usually NOT our bug: Chrome streams audio to Google's speech
54
+ * service, and browsers that expose `webkitSpeechRecognition` without shipping
55
+ * that service (Brave, some Chromium forks) fail every attempt with `network`.
56
+ * Unknown raw codes also land here — `describeRecognitionError` logs the raw one.
57
+ */
58
+ export declare function mapRecognitionError(raw: string): DictationError | null;
59
+ /** Developer-facing log line: bucket, raw code, and for `network` why it is not an app bug. */
60
+ export declare function describeRecognitionError(raw: string, bucket: DictationError): string;
61
+ /**
62
+ * Full transcript of the session so far. Continuous mode keeps every result
63
+ * (final and interim) in `results`, so concatenating from 0 is always current.
64
+ */
65
+ export declare function transcriptFromEvent(e: SpeechRecognitionEventLike): string;
66
+ /** Append dictated text to the draft that existed when dictation started. */
67
+ export declare function mergeTranscript(base: string, transcript: string): string;
68
+ /**
69
+ * Time-domain samples (-1..1) → 0..1 level, quantized to 0.05 steps so the
70
+ * meter only re-renders on a visible change.
71
+ *
72
+ * ponytail: single AnalyserNode RMS, no waveform history; upgrade only if design asks.
73
+ */
74
+ export declare function rmsToLevel(samples: ArrayLike<number>): number;
75
+ //# sourceMappingURL=dictation.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dictation.d.ts","sourceRoot":"","sources":["../../../../../../src/features/chat/composer/lib/dictation.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,yGAAyG;AACzG,MAAM,MAAM,cAAc,GAAG,YAAY,GAAG,QAAQ,GAAG,WAAW,GAAG,SAAS,GAAG,MAAM,CAAA;AAIvF,MAAM,WAAW,gCAAgC;IAAG,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAA;CAAE;AACjF,MAAM,WAAW,2BAA2B;IAC1C,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAA;IACzB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;IACvB,QAAQ,EAAE,KAAK,EAAE,MAAM,GAAG,gCAAgC,CAAA;CAC3D;AACD,MAAM,WAAW,+BAA+B;IAC9C,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;IACvB,QAAQ,EAAE,KAAK,EAAE,MAAM,GAAG,2BAA2B,CAAA;CACtD;AACD,MAAM,WAAW,0BAA0B;IACzC,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAA;IAC5B,QAAQ,CAAC,OAAO,EAAE,+BAA+B,CAAA;CAClD;AACD,MAAM,WAAW,+BAA+B;IAAG,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;CAAE;AAC3E,MAAM,WAAW,qBAAqB;IACpC,IAAI,EAAE,MAAM,CAAA;IACZ,UAAU,EAAE,OAAO,CAAA;IACnB,cAAc,EAAE,OAAO,CAAA;IACvB,QAAQ,EAAE,CAAC,CAAC,CAAC,EAAE,0BAA0B,KAAK,IAAI,CAAC,GAAG,IAAI,CAAA;IAC1D,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,+BAA+B,KAAK,IAAI,CAAC,GAAG,IAAI,CAAA;IAC9D,KAAK,EAAE,CAAC,MAAM,IAAI,CAAC,GAAG,IAAI,CAAA;IAC1B,KAAK,IAAI,IAAI,CAAA;IACb,IAAI,IAAI,IAAI,CAAA;IACZ,KAAK,IAAI,IAAI,CAAA;CACd;AACD,MAAM,MAAM,qBAAqB,GAAG,UAAU,qBAAqB,CAAA;AACnE,MAAM,WAAW,UAAU;IACzB,QAAQ,CAAC,eAAe,CAAC,EAAE,OAAO,CAAA;IAClC,QAAQ,CAAC,iBAAiB,CAAC,EAAE,qBAAqB,CAAA;IAClD,QAAQ,CAAC,uBAAuB,CAAC,EAAE,qBAAqB,CAAA;CACzD;AAED,yFAAyF;AACzF,wBAAgB,wBAAwB,CAAC,IAAI,EAAE,UAAU,GAAG,SAAS,GAAG,qBAAqB,GAAG,IAAI,CAKnG;AAED,6DAA6D;AAC7D,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAExD;AAED;;;;;;;GAOG;AACH,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,MAAM,GAAG,cAAc,GAAG,IAAI,CAgBtE;AAED,+FAA+F;AAC/F,wBAAgB,wBAAwB,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,cAAc,GAAG,MAAM,CAMpF;AAED;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,CAAC,EAAE,0BAA0B,GAAG,MAAM,CAMzE;AAED,6EAA6E;AAC7E,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,MAAM,CASxE;AAKD;;;;;GAKG;AACH,wBAAgB,UAAU,CAAC,OAAO,EAAE,SAAS,CAAC,MAAM,CAAC,GAAG,MAAM,CAc7D"}
@@ -1,26 +1,46 @@
1
+ import type { Id } from '@repo/backend/convex/_generated/dataModel';
1
2
  /**
2
- * Pending image attachments staged in the composer.
3
+ * Files the visitor staged for the next message. Each one uploads at once
4
+ * (reserve → PUT → finalize, `hooks/useAttachmentUpload.ts`); only `ready`
5
+ * files with a server id are sent. A removed or never-sent file needs no
6
+ * call: its server row expires after 24h and the cleanup sweep deletes it.
3
7
  *
4
- * Frontend-only state for now. The backend `send` mutation accepts a
5
- * single `content: string` — image upload + persistence (Convex storage,
6
- * message-level attachment array, agent vision-input wiring) is a
7
- * follow-up. When that lands, replace `previewUrl` with the uploaded
8
- * `storageId` and pass the array in `send(...)`.
9
- *
10
- * `previewUrl` is an `URL.createObjectURL(file)` blob — callers MUST
11
- * revoke it via `removeAttachedImage` / `clearAttachedImages` to avoid
12
- * leaking memory.
8
+ * `previewUrl` is a blob URL for images only; `removeStaged` /
9
+ * `clearStagedFiles` revoke it.
13
10
  */
14
- export interface AttachedImage {
11
+ export type StagedStatus = 'uploading' | 'ready' | 'failed';
12
+ export interface StagedFile {
15
13
  id: string;
16
14
  file: File;
17
- previewUrl: string;
15
+ /** Images only. */
16
+ previewUrl: string | null;
17
+ status: StagedStatus;
18
+ attachmentId: Id<'conversationAttachments'> | null;
19
+ errorCode: string | null;
18
20
  }
19
- export declare const attachedImages: import("@preact/signals").Signal<AttachedImage[]>;
20
- /** Appends image files (after size + count guards) and creates blob preview URLs. */
21
- export declare function addAttachedImages(files: FileList | File[]): void;
22
- /** Removes one staged image by id and revokes its blob URL. */
23
- export declare function removeAttachedImage(id: string): void;
24
- /** Revokes every staged blob URL and resets the list. Call after send + on unmount. */
25
- export declare function clearAttachedImages(): void;
21
+ export declare const stagedFiles: import("@preact/signals").Signal<StagedFile[]>;
22
+ /**
23
+ * Splits picked files into those to upload and a rejected count: the
24
+ * extension decides the type (the server re-checks the bytes), a file must
25
+ * be 1 byte to 10 MB, and at most the room left in the message is taken.
26
+ */
27
+ export declare function acceptFiles(files: readonly File[], alreadyStaged: number): {
28
+ accepted: File[];
29
+ rejected: number;
30
+ };
31
+ /** Adds a file in `uploading` state and returns it. */
32
+ export declare function stageFile(file: File): StagedFile;
33
+ export declare function updateStaged(id: string, patch: Partial<Pick<StagedFile, 'status' | 'attachmentId' | 'errorCode'>>): void;
34
+ export declare function removeStaged(id: string): void;
35
+ export declare function clearStagedFiles(): void;
36
+ export declare function readyAttachmentIds(): Array<Id<'conversationAttachments'>>;
37
+ export declare function hasUploading(): boolean;
38
+ /** The server's error code, when the throw carries one (ConvexError data). */
39
+ export declare function errorCodeOf(err: unknown): string | null;
40
+ /**
41
+ * A send the server refused because of its files: the one file it names
42
+ * (`ATTACHMENT_NOT_FOUND` carries its id) turns failed, the others stay
43
+ * ready; a chat that no longer takes files fails every file that went out.
44
+ */
45
+ export declare function markRefusedFiles(err: unknown, sentIds: ReadonlyArray<Id<'conversationAttachments'>>): void;
26
46
  //# sourceMappingURL=attachments.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"attachments.d.ts","sourceRoot":"","sources":["../../../../../../src/features/chat/composer/state/attachments.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;;GAYG;AACH,MAAM,WAAW,aAAa;IAC5B,EAAE,EAAE,MAAM,CAAA;IACV,IAAI,EAAE,IAAI,CAAA;IACV,UAAU,EAAE,MAAM,CAAA;CACnB;AAED,eAAO,MAAM,cAAc,mDAA8B,CAAA;AAyBzD,qFAAqF;AACrF,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,QAAQ,GAAG,IAAI,EAAE,GAAG,IAAI,CAgBhE;AAED,+DAA+D;AAC/D,wBAAgB,mBAAmB,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI,CAMpD;AAED,uFAAuF;AACvF,wBAAgB,mBAAmB,IAAI,IAAI,CAK1C"}
1
+ {"version":3,"file":"attachments.d.ts","sourceRoot":"","sources":["../../../../../../src/features/chat/composer/state/attachments.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,EAAE,EAAE,MAAM,2CAA2C,CAAA;AA0BnE;;;;;;;;GAQG;AACH,MAAM,MAAM,YAAY,GAAG,WAAW,GAAG,OAAO,GAAG,QAAQ,CAAA;AAE3D,MAAM,WAAW,UAAU;IACzB,EAAE,EAAE,MAAM,CAAA;IACV,IAAI,EAAE,IAAI,CAAA;IACV,mBAAmB;IACnB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAA;IACzB,MAAM,EAAE,YAAY,CAAA;IACpB,YAAY,EAAE,EAAE,CAAC,yBAAyB,CAAC,GAAG,IAAI,CAAA;IAClD,SAAS,EAAE,MAAM,GAAG,IAAI,CAAA;CACzB;AAED,eAAO,MAAM,WAAW,gDAA2B,CAAA;AAOnD;;;;GAIG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,SAAS,IAAI,EAAE,EAAE,aAAa,EAAE,MAAM,GAAG;IAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,CAUjH;AAED,uDAAuD;AACvD,wBAAgB,SAAS,CAAC,IAAI,EAAE,IAAI,GAAG,UAAU,CAWhD;AAED,wBAAgB,YAAY,CAC1B,EAAE,EAAE,MAAM,EACV,KAAK,EAAE,OAAO,CAAC,IAAI,CAAC,UAAU,EAAE,QAAQ,GAAG,cAAc,GAAG,WAAW,CAAC,CAAC,GACxE,IAAI,CAEN;AAED,wBAAgB,YAAY,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI,CAM7C;AAED,wBAAgB,gBAAgB,IAAI,IAAI,CAOvC;AAED,wBAAgB,kBAAkB,IAAI,KAAK,CAAC,EAAE,CAAC,yBAAyB,CAAC,CAAC,CAEzE;AAED,wBAAgB,YAAY,IAAI,OAAO,CAEtC;AAED,8EAA8E;AAC9E,wBAAgB,WAAW,CAAC,GAAG,EAAE,OAAO,GAAG,MAAM,GAAG,IAAI,CAGvD;AAED;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,OAAO,EAAE,OAAO,EAAE,aAAa,CAAC,EAAE,CAAC,yBAAyB,CAAC,CAAC,GAAG,IAAI,CAY1G"}
@@ -5,7 +5,7 @@
5
5
  * - rate-limit.ts → rateLimitedUntilMs + nowMs ticker
6
6
  * - sending.ts → sendPending flag (in-flight guard, shared by all sends)
7
7
  * - privacy.ts → explicit-consent gate (shared by all send origins)
8
- * - attachments.ts → staged image attachments + blob-URL hygiene
8
+ * - attachments.ts → staged visitor files + blob-URL hygiene
9
9
  *
10
10
  * Consumers inside `composer/` should import from `../state`. The
11
11
  * outer composer barrel (`composer/index.ts`) re-exports only what is
@@ -16,5 +16,5 @@ export { draftMessage, replyingTo, setReplyTarget, composerFocusRequest, truncat
16
16
  export { rateLimitedUntilMs, nowMs } from './rate-limit';
17
17
  export { sendPending } from './sending';
18
18
  export { privacyAcknowledged, privacyGateOpen, pendingSendContent, requiresPrivacyAck, openPrivacyGate, acknowledgePrivacy, resetPrivacyGate, } from './privacy';
19
- export { attachedImages, addAttachedImages, removeAttachedImage, clearAttachedImages, type AttachedImage, } from './attachments';
19
+ export { stagedFiles, acceptFiles, stageFile, updateStaged, removeStaged, clearStagedFiles, readyAttachmentIds, hasUploading, errorCodeOf, markRefusedFiles, type StagedFile, type StagedStatus, } from './attachments';
20
20
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../../src/features/chat/composer/state/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AACH,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,cAAc,EAAE,oBAAoB,EAAE,gBAAgB,EAAE,KAAK,WAAW,EAAE,MAAM,SAAS,CAAA;AAC5H,OAAO,EAAE,kBAAkB,EAAE,KAAK,EAAE,MAAM,cAAc,CAAA;AACxD,OAAO,EAAE,WAAW,EAAE,MAAM,WAAW,CAAA;AACvC,OAAO,EACL,mBAAmB,EACnB,eAAe,EACf,kBAAkB,EAClB,kBAAkB,EAClB,eAAe,EACf,kBAAkB,EAClB,gBAAgB,GACjB,MAAM,WAAW,CAAA;AAClB,OAAO,EACL,cAAc,EACd,iBAAiB,EACjB,mBAAmB,EACnB,mBAAmB,EACnB,KAAK,aAAa,GACnB,MAAM,eAAe,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../../src/features/chat/composer/state/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AACH,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,cAAc,EAAE,oBAAoB,EAAE,gBAAgB,EAAE,KAAK,WAAW,EAAE,MAAM,SAAS,CAAA;AAC5H,OAAO,EAAE,kBAAkB,EAAE,KAAK,EAAE,MAAM,cAAc,CAAA;AACxD,OAAO,EAAE,WAAW,EAAE,MAAM,WAAW,CAAA;AACvC,OAAO,EACL,mBAAmB,EACnB,eAAe,EACf,kBAAkB,EAClB,kBAAkB,EAClB,eAAe,EACf,kBAAkB,EAClB,gBAAgB,GACjB,MAAM,WAAW,CAAA;AAClB,OAAO,EACL,WAAW,EACX,WAAW,EACX,SAAS,EACT,YAAY,EACZ,YAAY,EACZ,gBAAgB,EAChB,kBAAkB,EAClB,YAAY,EACZ,WAAW,EACX,gBAAgB,EAChB,KAAK,UAAU,EACf,KAAK,YAAY,GAClB,MAAM,eAAe,CAAA"}
@@ -2,7 +2,7 @@ export type Availability = {
2
2
  anyOnline: boolean;
3
3
  anyAway: boolean;
4
4
  };
5
- export declare function useAvailability(orgSlug: string | null): {
5
+ export declare function useAvailability(orgSlug: string | null, projSlug?: string): {
6
6
  anyOnline: boolean;
7
7
  anyAway: boolean;
8
8
  } | undefined;