@flamingo-stack/openframe-frontend-core 0.0.685-snapshot.20260929164409 → 0.0.685

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 (170) hide show
  1. package/dist/{chunk-DL67S7H4.cjs → chunk-5LJZPJHX.cjs} +59 -59
  2. package/dist/{chunk-DL67S7H4.cjs.map → chunk-5LJZPJHX.cjs.map} +1 -1
  3. package/dist/{chunk-IZ3WKG62.js → chunk-65KTXRBY.js} +6 -6
  4. package/dist/{chunk-IBKMIJ7Y.js → chunk-7XF63THA.js} +6 -6
  5. package/dist/{chunk-SI77HF4U.cjs → chunk-A3CSQB4A.cjs} +805 -1247
  6. package/dist/chunk-A3CSQB4A.cjs.map +1 -0
  7. package/dist/{chunk-5MUR43QD.cjs → chunk-B25CF3PO.cjs} +30 -30
  8. package/dist/{chunk-5MUR43QD.cjs.map → chunk-B25CF3PO.cjs.map} +1 -1
  9. package/dist/{chunk-32KBPEF7.js → chunk-B32YLOYQ.js} +4 -4
  10. package/dist/{chunk-OBLED7JY.cjs → chunk-B5N3AHPG.cjs} +81 -81
  11. package/dist/{chunk-OBLED7JY.cjs.map → chunk-B5N3AHPG.cjs.map} +1 -1
  12. package/dist/{chunk-QSRUYHTW.js → chunk-BZ2XOEHW.js} +3 -3
  13. package/dist/{chunk-XATA4OVO.cjs → chunk-C3B36OYZ.cjs} +3 -3
  14. package/dist/{chunk-XATA4OVO.cjs.map → chunk-C3B36OYZ.cjs.map} +1 -1
  15. package/dist/{chunk-V26TKJ4Z.cjs → chunk-CMQXPD5C.cjs} +28 -28
  16. package/dist/{chunk-V26TKJ4Z.cjs.map → chunk-CMQXPD5C.cjs.map} +1 -1
  17. package/dist/{chunk-QNWQQ4RT.cjs → chunk-DQOQ3KTP.cjs} +73 -78
  18. package/dist/chunk-DQOQ3KTP.cjs.map +1 -0
  19. package/dist/{chunk-5HVGOIAE.cjs → chunk-DWXWEGGO.cjs} +22 -22
  20. package/dist/{chunk-5HVGOIAE.cjs.map → chunk-DWXWEGGO.cjs.map} +1 -1
  21. package/dist/{chunk-6CMH53MP.cjs → chunk-EFBMNVSH.cjs} +15 -15
  22. package/dist/{chunk-6CMH53MP.cjs.map → chunk-EFBMNVSH.cjs.map} +1 -1
  23. package/dist/{chunk-DDFYKF3B.js → chunk-GHLGXFNU.js} +3 -3
  24. package/dist/{chunk-VDV7K5TD.js → chunk-GXV6UEVY.js} +3 -3
  25. package/dist/{chunk-AEAFQTVR.cjs → chunk-HMXUOLZR.cjs} +20 -20
  26. package/dist/{chunk-AEAFQTVR.cjs.map → chunk-HMXUOLZR.cjs.map} +1 -1
  27. package/dist/{chunk-2OD2PPNO.cjs → chunk-K2HZG4RM.cjs} +32 -32
  28. package/dist/{chunk-2OD2PPNO.cjs.map → chunk-K2HZG4RM.cjs.map} +1 -1
  29. package/dist/{chunk-JNDHXL2D.cjs → chunk-M4HYIXP6.cjs} +383 -384
  30. package/dist/chunk-M4HYIXP6.cjs.map +1 -0
  31. package/dist/{chunk-KTWJKCUB.js → chunk-N4Z6X5BV.js} +5 -5
  32. package/dist/{chunk-T2RHI676.js → chunk-O7LOZW4R.js} +5 -5
  33. package/dist/{chunk-ZHYYGIAI.cjs → chunk-P2ASEPA2.cjs} +6 -6
  34. package/dist/{chunk-ZHYYGIAI.cjs.map → chunk-P2ASEPA2.cjs.map} +1 -1
  35. package/dist/{chunk-CHRDLXXX.js → chunk-PSQKD6ZN.js} +3 -3
  36. package/dist/{chunk-GSJR33UP.cjs → chunk-QHLJSB2J.cjs} +12 -12
  37. package/dist/{chunk-GSJR33UP.cjs.map → chunk-QHLJSB2J.cjs.map} +1 -1
  38. package/dist/{chunk-CFL3EW4V.cjs → chunk-T4DUTP5C.cjs} +5 -5
  39. package/dist/{chunk-CFL3EW4V.cjs.map → chunk-T4DUTP5C.cjs.map} +1 -1
  40. package/dist/{chunk-22RSJ57Z.js → chunk-T6KWNJDW.js} +465 -470
  41. package/dist/chunk-T6KWNJDW.js.map +1 -0
  42. package/dist/{chunk-2FGFB2HY.cjs → chunk-TJI5V5BR.cjs} +7 -7
  43. package/dist/{chunk-2FGFB2HY.cjs.map → chunk-TJI5V5BR.cjs.map} +1 -1
  44. package/dist/{chunk-HLEXYTOE.js → chunk-TUG7IT6H.js} +2 -2
  45. package/dist/{chunk-DWCVA6XT.cjs → chunk-U3IXG7TR.cjs} +33 -33
  46. package/dist/{chunk-DWCVA6XT.cjs.map → chunk-U3IXG7TR.cjs.map} +1 -1
  47. package/dist/{chunk-WJ5XN4AL.js → chunk-UT333EOT.js} +4 -4
  48. package/dist/{chunk-OTV4W3YD.js → chunk-VDPCK437.js} +5 -6
  49. package/dist/{chunk-OTV4W3YD.js.map → chunk-VDPCK437.js.map} +1 -1
  50. package/dist/{chunk-5GK7TU2Q.js → chunk-WJK2EETW.js} +2 -2
  51. package/dist/{chunk-YPXXXX6R.js → chunk-XGX6JSEU.js} +1644 -2086
  52. package/dist/chunk-XGX6JSEU.js.map +1 -0
  53. package/dist/{chunk-XODE4YTG.js → chunk-XW7MUIW4.js} +3 -3
  54. package/dist/{chunk-N74MQ4HQ.js → chunk-Y7ZYOQNB.js} +3 -3
  55. package/dist/{chunk-2NUB5EMG.cjs → chunk-YCTVLN47.cjs} +10 -10
  56. package/dist/{chunk-2NUB5EMG.cjs.map → chunk-YCTVLN47.cjs.map} +1 -1
  57. package/dist/{chunk-TILC52ZF.js → chunk-ZF4Z36G4.js} +7 -7
  58. package/dist/components/case-studies/index.cjs +16 -16
  59. package/dist/components/case-studies/index.js +4 -4
  60. package/dist/components/chat/ai-assistant-info.d.ts.map +1 -1
  61. package/dist/components/chat/approval-request-message.d.ts.map +1 -1
  62. package/dist/components/chat/chat-input.d.ts.map +1 -1
  63. package/dist/components/chat/chat-message-enhanced.d.ts.map +1 -1
  64. package/dist/components/chat/chat-message-list.d.ts.map +1 -1
  65. package/dist/components/chat/error-message-display.d.ts.map +1 -1
  66. package/dist/components/chat/index.cjs +3 -21
  67. package/dist/components/chat/index.cjs.map +1 -1
  68. package/dist/components/chat/index.d.ts +0 -6
  69. package/dist/components/chat/index.d.ts.map +1 -1
  70. package/dist/components/chat/index.js +2 -20
  71. package/dist/components/chat/msp-organization-card.d.ts +1 -7
  72. package/dist/components/chat/msp-organization-card.d.ts.map +1 -1
  73. package/dist/components/chat/types/chat.types.d.ts +0 -13
  74. package/dist/components/chat/types/chat.types.d.ts.map +1 -1
  75. package/dist/components/chat/types/component.types.d.ts +1 -20
  76. package/dist/components/chat/types/component.types.d.ts.map +1 -1
  77. package/dist/components/contact/index.cjs +5 -5
  78. package/dist/components/contact/index.js +4 -4
  79. package/dist/components/docs/index.cjs +8 -8
  80. package/dist/components/docs/index.js +7 -7
  81. package/dist/components/embeds/index.cjs +5 -5
  82. package/dist/components/embeds/index.js +4 -4
  83. package/dist/components/faq/index.cjs +5 -5
  84. package/dist/components/faq/index.js +4 -4
  85. package/dist/components/features/index.cjs +4 -4
  86. package/dist/components/features/index.js +3 -3
  87. package/dist/components/help-center-pages/index.cjs +91 -91
  88. package/dist/components/help-center-pages/index.js +15 -15
  89. package/dist/components/index.cjs +55 -73
  90. package/dist/components/index.cjs.map +1 -1
  91. package/dist/components/index.js +15 -33
  92. package/dist/components/index.js.map +1 -1
  93. package/dist/components/meeting-scheduler/index.cjs +41 -41
  94. package/dist/components/meeting-scheduler/index.js +3 -3
  95. package/dist/components/navigation/index.cjs +7 -7
  96. package/dist/components/navigation/index.js +6 -6
  97. package/dist/components/onboarding-guides/index.cjs +7 -7
  98. package/dist/components/onboarding-guides/index.js +6 -6
  99. package/dist/components/related-content/index.cjs +3 -3
  100. package/dist/components/related-content/index.js +2 -2
  101. package/dist/components/tickets/index.cjs +8 -8
  102. package/dist/components/tickets/index.js +7 -7
  103. package/dist/components/ui/avatar-stack.d.ts +1 -5
  104. package/dist/components/ui/avatar-stack.d.ts.map +1 -1
  105. package/dist/components/ui/index.cjs +4 -22
  106. package/dist/components/ui/index.cjs.map +1 -1
  107. package/dist/components/ui/index.js +3 -21
  108. package/dist/components/ui/reopen-ticket-request-modal.d.ts +1 -4
  109. package/dist/components/ui/reopen-ticket-request-modal.d.ts.map +1 -1
  110. package/dist/index.cjs +9 -27
  111. package/dist/index.cjs.map +1 -1
  112. package/dist/index.js +7 -25
  113. package/dist/index.js.map +1 -1
  114. package/package.json +1 -1
  115. package/src/components/chat/ai-assistant-info.tsx +1 -7
  116. package/src/components/chat/approval-request-message.tsx +1 -6
  117. package/src/components/chat/chat-input.tsx +1 -26
  118. package/src/components/chat/chat-message-enhanced.tsx +142 -180
  119. package/src/components/chat/chat-message-list.tsx +164 -169
  120. package/src/components/chat/error-message-display.tsx +3 -21
  121. package/src/components/chat/index.ts +0 -6
  122. package/src/components/chat/msp-organization-card.tsx +0 -35
  123. package/src/components/chat/types/chat.types.ts +0 -15
  124. package/src/components/chat/types/component.types.ts +0 -20
  125. package/src/components/ui/avatar-stack.tsx +5 -15
  126. package/src/components/ui/reopen-ticket-request-modal.tsx +2 -6
  127. package/src/styles/ods-colors.css +0 -10
  128. package/src/styles/ods-effects.css +0 -13
  129. package/dist/chunk-22RSJ57Z.js.map +0 -1
  130. package/dist/chunk-JNDHXL2D.cjs.map +0 -1
  131. package/dist/chunk-QNWQQ4RT.cjs.map +0 -1
  132. package/dist/chunk-SI77HF4U.cjs.map +0 -1
  133. package/dist/chunk-YPXXXX6R.js.map +0 -1
  134. package/dist/components/chat/chat-appearance-context.d.ts +0 -9
  135. package/dist/components/chat/chat-appearance-context.d.ts.map +0 -1
  136. package/dist/components/chat/chat-nav-sidebar.d.ts +0 -50
  137. package/dist/components/chat/chat-nav-sidebar.d.ts.map +0 -1
  138. package/dist/components/chat/chat-top-navigation.d.ts +0 -29
  139. package/dist/components/chat/chat-top-navigation.d.ts.map +0 -1
  140. package/dist/components/chat/onboarding-carousel.d.ts +0 -29
  141. package/dist/components/chat/onboarding-carousel.d.ts.map +0 -1
  142. package/dist/components/chat/system-event-message.d.ts +0 -14
  143. package/dist/components/chat/system-event-message.d.ts.map +0 -1
  144. package/src/components/chat/__tests__/chat-appearance.test.tsx +0 -79
  145. package/src/components/chat/__tests__/onboarding-carousel.test.tsx +0 -56
  146. package/src/components/chat/chat-appearance-context.tsx +0 -15
  147. package/src/components/chat/chat-nav-sidebar.tsx +0 -163
  148. package/src/components/chat/chat-top-navigation.tsx +0 -109
  149. package/src/components/chat/onboarding-carousel.tsx +0 -162
  150. package/src/components/chat/system-event-message.tsx +0 -54
  151. package/src/components/ui/__tests__/avatar-stack.test.tsx +0 -25
  152. package/src/stories/FaeLayoutV2.stories.tsx +0 -150
  153. package/src/stories/FaeOnboardingV2.stories.tsx +0 -68
  154. package/src/stories/FaeThreadV2.stories.tsx +0 -192
  155. package/src/stories/fae-brand-decorator.tsx +0 -28
  156. /package/dist/{chunk-IZ3WKG62.js.map → chunk-65KTXRBY.js.map} +0 -0
  157. /package/dist/{chunk-IBKMIJ7Y.js.map → chunk-7XF63THA.js.map} +0 -0
  158. /package/dist/{chunk-32KBPEF7.js.map → chunk-B32YLOYQ.js.map} +0 -0
  159. /package/dist/{chunk-QSRUYHTW.js.map → chunk-BZ2XOEHW.js.map} +0 -0
  160. /package/dist/{chunk-DDFYKF3B.js.map → chunk-GHLGXFNU.js.map} +0 -0
  161. /package/dist/{chunk-VDV7K5TD.js.map → chunk-GXV6UEVY.js.map} +0 -0
  162. /package/dist/{chunk-KTWJKCUB.js.map → chunk-N4Z6X5BV.js.map} +0 -0
  163. /package/dist/{chunk-T2RHI676.js.map → chunk-O7LOZW4R.js.map} +0 -0
  164. /package/dist/{chunk-CHRDLXXX.js.map → chunk-PSQKD6ZN.js.map} +0 -0
  165. /package/dist/{chunk-HLEXYTOE.js.map → chunk-TUG7IT6H.js.map} +0 -0
  166. /package/dist/{chunk-WJ5XN4AL.js.map → chunk-UT333EOT.js.map} +0 -0
  167. /package/dist/{chunk-5GK7TU2Q.js.map → chunk-WJK2EETW.js.map} +0 -0
  168. /package/dist/{chunk-XODE4YTG.js.map → chunk-XW7MUIW4.js.map} +0 -0
  169. /package/dist/{chunk-N74MQ4HQ.js.map → chunk-Y7ZYOQNB.js.map} +0 -0
  170. /package/dist/{chunk-TILC52ZF.js.map → chunk-ZF4Z36G4.js.map} +0 -0
@@ -1,9 +0,0 @@
1
- import { type ChatAppearance } from './types/chat.types';
2
- /**
3
- * Thread-wide `ChatAppearance`. `ChatMessageList` provides it, so the blocks a
4
- * message renders (error, lifecycle receipts) follow the thread without every
5
- * segment component growing an `appearance` prop.
6
- */
7
- export declare const ChatAppearanceContext: import("react").Context<ChatAppearance>;
8
- export declare function useChatAppearance(): ChatAppearance;
9
- //# sourceMappingURL=chat-appearance-context.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"chat-appearance-context.d.ts","sourceRoot":"","sources":["../../../src/components/chat/chat-appearance-context.tsx"],"names":[],"mappings":"AAGA,OAAO,EAAmB,KAAK,cAAc,EAAE,MAAM,oBAAoB,CAAC;AAE1E;;;;GAIG;AACH,eAAO,MAAM,qBAAqB,yCAAyD,CAAC;AAE5F,wBAAgB,iBAAiB,IAAI,cAAc,CAElD"}
@@ -1,50 +0,0 @@
1
- import { type ButtonHTMLAttributes, type HTMLAttributes, type ReactNode } from 'react';
2
- export interface ChatNavSidebarItem {
3
- id: string;
4
- label: string;
5
- /** 24px glyph before the label. */
6
- icon: ReactNode;
7
- /** The view this item opens is the one on screen. */
8
- active?: boolean;
9
- onClick?: () => void;
10
- }
11
- export interface ChatNavSidebarProps extends HTMLAttributes<HTMLElement> {
12
- /** Brand row at the top. */
13
- logo?: ReactNode;
14
- /** Primary actions under the logo (new chat, archive, help, ...). */
15
- items: ChatNavSidebarItem[];
16
- /** Caption over the list (e.g. "Your Current Chats"). */
17
- sectionLabel?: string;
18
- /** The list itself, typically `ChatListItem` rows or an empty state. Scrolls
19
- * on its own; everything above it stays put. */
20
- children?: ReactNode;
21
- /** Pinned under the list, full width, above a divider (e.g. the MSP card). */
22
- footer?: ReactNode;
23
- }
24
- /**
25
- * Left rail of the fae chat v2 layout (Figma `chat-sidebar`): brand, a stack of
26
- * navigation actions, a captioned scrolling list and a pinned footer. It only
27
- * lays things out; which rows exist, what they show and what selecting them
28
- * does belong to the host.
29
- */
30
- declare const ChatNavSidebar: import("react").ForwardRefExoticComponent<ChatNavSidebarProps & import("react").RefAttributes<HTMLElement>>;
31
- export interface ChatListItemProps extends Omit<ButtonHTMLAttributes<HTMLButtonElement>, 'title'> {
32
- title: ReactNode;
33
- /** Second line (e.g. the ticket number). */
34
- subtitle?: ReactNode;
35
- /** 16px mark before the title (e.g. a resolved check). */
36
- leading?: ReactNode;
37
- /** 24px status glyph at the row's end. */
38
- trailing?: ReactNode;
39
- /** The chat open on screen. */
40
- active?: boolean;
41
- }
42
- /**
43
- * One row of the `ChatNavSidebar` list (Figma `chat-list-item`): a one-line
44
- * title over a caption, an optional mark before the title and a status glyph
45
- * at the end. The selected row takes the accent's secondary fill, so a tenant
46
- * accent recolours it with the rest of the brand.
47
- */
48
- declare const ChatListItem: import("react").ForwardRefExoticComponent<ChatListItemProps & import("react").RefAttributes<HTMLButtonElement>>;
49
- export { ChatNavSidebar, ChatListItem };
50
- //# sourceMappingURL=chat-nav-sidebar.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"chat-nav-sidebar.d.ts","sourceRoot":"","sources":["../../../src/components/chat/chat-nav-sidebar.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAc,KAAK,oBAAoB,EAAE,KAAK,cAAc,EAAE,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAInG,MAAM,WAAW,kBAAkB;IACjC,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,mCAAmC;IACnC,IAAI,EAAE,SAAS,CAAC;IAChB,qDAAqD;IACrD,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;CACtB;AAED,MAAM,WAAW,mBAAoB,SAAQ,cAAc,CAAC,WAAW,CAAC;IACtE,4BAA4B;IAC5B,IAAI,CAAC,EAAE,SAAS,CAAC;IACjB,qEAAqE;IACrE,KAAK,EAAE,kBAAkB,EAAE,CAAC;IAC5B,yDAAyD;IACzD,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB;qDACiD;IACjD,QAAQ,CAAC,EAAE,SAAS,CAAC;IACrB,8EAA8E;IAC9E,MAAM,CAAC,EAAE,SAAS,CAAC;CACpB;AAED;;;;;GAKG;AACH,QAAA,MAAM,cAAc,6GA6CnB,CAAC;AA6BF,MAAM,WAAW,iBAAkB,SAAQ,IAAI,CAAC,oBAAoB,CAAC,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC/F,KAAK,EAAE,SAAS,CAAC;IACjB,4CAA4C;IAC5C,QAAQ,CAAC,EAAE,SAAS,CAAC;IACrB,0DAA0D;IAC1D,OAAO,CAAC,EAAE,SAAS,CAAC;IACpB,0CAA0C;IAC1C,QAAQ,CAAC,EAAE,SAAS,CAAC;IACrB,+BAA+B;IAC/B,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAED;;;;;GAKG;AACH,QAAA,MAAM,YAAY,iHA8BjB,CAAC;AAIF,OAAO,EAAE,cAAc,EAAE,YAAY,EAAE,CAAC"}
@@ -1,29 +0,0 @@
1
- import { type HTMLAttributes, type ReactNode } from 'react';
2
- export interface ChatTopNavigationProps extends HTMLAttributes<HTMLElement> {
3
- /** Who the user is talking to. */
4
- name: string;
5
- /** Line under the name (e.g. "Your AI Assistant", "IT Technician"). */
6
- subtitle?: string;
7
- avatarUrl?: string | null;
8
- /** Actions after the identity (e.g. "Request a Technician"). */
9
- actions?: ReactNode;
10
- /** Shows the sidebar toggle at the start of the bar. */
11
- onToggleSidebar?: () => void;
12
- /** Whether the sidebar is currently shown; drives the toggle's state. */
13
- sidebarOpen?: boolean;
14
- /** Shows the settings button at the end of the bar. */
15
- onOpenSettings?: () => void;
16
- /** Content above the bar, full width (e.g. a "Back to ..." strip). */
17
- before?: ReactNode;
18
- /** Identity still resolving: placeholders instead of a default name that
19
- * would flash before the tenant's branding lands. */
20
- isLoading?: boolean;
21
- }
22
- /**
23
- * Top bar of the fae chat v2 layout (Figma `chat-top-navigation`): an optional
24
- * sidebar toggle, the counterpart's avatar, name and role, the host's actions
25
- * and an optional settings button, split by vertical dividers.
26
- */
27
- declare const ChatTopNavigation: import("react").ForwardRefExoticComponent<ChatTopNavigationProps & import("react").RefAttributes<HTMLElement>>;
28
- export { ChatTopNavigation };
29
- //# sourceMappingURL=chat-top-navigation.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"chat-top-navigation.d.ts","sourceRoot":"","sources":["../../../src/components/chat/chat-top-navigation.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAc,KAAK,cAAc,EAAE,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAMxE,MAAM,WAAW,sBAAuB,SAAQ,cAAc,CAAC,WAAW,CAAC;IACzE,kCAAkC;IAClC,IAAI,EAAE,MAAM,CAAC;IACb,uEAAuE;IACvE,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,gEAAgE;IAChE,OAAO,CAAC,EAAE,SAAS,CAAC;IACpB,wDAAwD;IACxD,eAAe,CAAC,EAAE,MAAM,IAAI,CAAC;IAC7B,yEAAyE;IACzE,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,uDAAuD;IACvD,cAAc,CAAC,EAAE,MAAM,IAAI,CAAC;IAC5B,sEAAsE;IACtE,MAAM,CAAC,EAAE,SAAS,CAAC;IACnB;0DACsD;IACtD,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB;AAQD;;;;GAIG;AACH,QAAA,MAAM,iBAAiB,gHAgEtB,CAAC;AAIF,OAAO,EAAE,iBAAiB,EAAE,CAAC"}
@@ -1,29 +0,0 @@
1
- import { type ReactNode } from 'react';
2
- export interface OnboardingCarouselStep {
3
- id: string;
4
- /** Glyph in the 64px tile above the title. Pass it sized to 28px. */
5
- icon: ReactNode;
6
- title: ReactNode;
7
- description?: ReactNode;
8
- }
9
- export interface OnboardingCarouselProps {
10
- steps: OnboardingCarouselStep[];
11
- /** The last step's primary action. */
12
- onComplete: () => void;
13
- /** Label of the last step's primary action. */
14
- completeLabel?: string;
15
- previousLabel?: string;
16
- nextLabel?: string;
17
- /** Accessible name of the carousel region. */
18
- label?: string;
19
- className?: string;
20
- }
21
- /**
22
- * Step-by-step introduction: one card at a time in the middle, its neighbours
23
- * peeking in from the sides under an edge fade, dots below, Previous / Next
24
- * underneath. The last step swaps Next for `completeLabel`. There is no skip:
25
- * the design walks every step. Fills the height its parent gives it: the cards
26
- * stretch, the dots and buttons keep their size.
27
- */
28
- export declare function OnboardingCarousel({ steps, onComplete, completeLabel, previousLabel, nextLabel, label, className, }: OnboardingCarouselProps): import("react").JSX.Element;
29
- //# sourceMappingURL=onboarding-carousel.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"onboarding-carousel.d.ts","sourceRoot":"","sources":["../../../src/components/chat/onboarding-carousel.tsx"],"names":[],"mappings":"AAEA,OAAO,EAA0C,KAAK,SAAS,EAAY,MAAM,OAAO,CAAC;AAIzF,MAAM,WAAW,sBAAsB;IACrC,EAAE,EAAE,MAAM,CAAC;IACX,qEAAqE;IACrE,IAAI,EAAE,SAAS,CAAC;IAChB,KAAK,EAAE,SAAS,CAAC;IACjB,WAAW,CAAC,EAAE,SAAS,CAAC;CACzB;AAED,MAAM,WAAW,uBAAuB;IACtC,KAAK,EAAE,sBAAsB,EAAE,CAAC;IAChC,sCAAsC;IACtC,UAAU,EAAE,MAAM,IAAI,CAAC;IACvB,+CAA+C;IAC/C,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,8CAA8C;IAC9C,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED;;;;;;GAMG;AACH,wBAAgB,kBAAkB,CAAC,EACjC,KAAK,EACL,UAAU,EACV,aAA4B,EAC5B,aAA+B,EAC/B,SAAuB,EACvB,KAAsB,EACtB,SAAS,GACV,EAAE,uBAAuB,+BAuHzB"}
@@ -1,14 +0,0 @@
1
- import { type HTMLAttributes } from 'react';
2
- export interface SystemEventMessageProps extends HTMLAttributes<HTMLDivElement> {
3
- /** The system line as the backend sent it. */
4
- text: string;
5
- timestamp?: Date;
6
- }
7
- /**
8
- * A system line in the fae chat v2 thread (`ai-assistant-info`,
9
- * type=direct-chat): a technician joining becomes "Technician Joined" with
10
- * their initials; any other line keeps its own wording under an info icon.
11
- */
12
- declare const SystemEventMessage: import("react").ForwardRefExoticComponent<SystemEventMessageProps & import("react").RefAttributes<HTMLDivElement>>;
13
- export { SystemEventMessage };
14
- //# sourceMappingURL=system-event-message.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"system-event-message.d.ts","sourceRoot":"","sources":["../../../src/components/chat/system-event-message.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAc,KAAK,cAAc,EAAE,MAAM,OAAO,CAAC;AAWxD,MAAM,WAAW,uBAAwB,SAAQ,cAAc,CAAC,cAAc,CAAC;IAC7E,8CAA8C;IAC9C,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,CAAC,EAAE,IAAI,CAAC;CAClB;AAED;;;;GAIG;AACH,QAAA,MAAM,kBAAkB,oHAyBtB,CAAC;AAIH,OAAO,EAAE,kBAAkB,EAAE,CAAC"}
@@ -1,79 +0,0 @@
1
- import { render, screen } from '@testing-library/react';
2
- import { describe, expect, it } from 'vitest';
3
- import { AiAssistantInfo } from '../ai-assistant-info';
4
- import { ChatAppearanceContext } from '../chat-appearance-context';
5
- import { ChatInput } from '../chat-input';
6
- import { ChatMessageEnhanced } from '../chat-message-enhanced';
7
- import { ErrorMessageDisplay } from '../error-message-display';
8
-
9
- describe('chat appearance', () => {
10
- it('classic keeps the colon after the author name', () => {
11
- render(<ChatMessageEnhanced role="assistant" assistantType="fae" name="Fae" content="Hi" />);
12
- expect(screen.getByText('Fae:')).toBeTruthy();
13
- });
14
-
15
- it('v2 drops the colon after the author name', () => {
16
- render(<ChatMessageEnhanced role="assistant" assistantType="fae" name="Fae" content="Hi" appearance="v2" />);
17
- expect(screen.getByText('Fae')).toBeTruthy();
18
- expect(screen.queryByText('Fae:')).toBeNull();
19
- });
20
-
21
- it('a row inherits v2 from the thread context', () => {
22
- render(
23
- <ChatAppearanceContext.Provider value="v2">
24
- <ChatMessageEnhanced role="user" name="John Smith" content="Hi" />
25
- </ChatAppearanceContext.Provider>,
26
- );
27
- expect(screen.getByText('John Smith')).toBeTruthy();
28
- });
29
-
30
- it('v2 blocks sit on the page surface', () => {
31
- render(
32
- <ChatAppearanceContext.Provider value="v2">
33
- <ErrorMessageDisplay data-testid="error" title="AI response error" details="Something went wrong." />
34
- <AiAssistantInfo data-testid="info" title="Handed Off to a Technician" />
35
- </ChatAppearanceContext.Provider>,
36
- );
37
- const error = screen.getByTestId('error');
38
- const info = screen.getByTestId('info');
39
- expect(error.className).toContain('bg-ods-bg');
40
- expect(error.className).not.toContain('mb-');
41
- expect(info.className).toContain('bg-ods-bg');
42
- expect(info.className).toContain('items-center');
43
- });
44
-
45
- it('v2 turns a technician joining into a receipt card', () => {
46
- render(
47
- <ChatMessageEnhanced
48
- role="user"
49
- authorType="system"
50
- name="Roman Smith joined the chat"
51
- content=""
52
- appearance="v2"
53
- />,
54
- );
55
- expect(screen.getByText('Technician Joined')).toBeTruthy();
56
- expect(screen.getByText("You're now chatting with Roman Smith.")).toBeTruthy();
57
- });
58
-
59
- it('classic keeps the system line as an author row', () => {
60
- render(<ChatMessageEnhanced role="user" authorType="system" name="Roman Smith joined the chat" content="" />);
61
- expect(screen.getByText('Roman Smith joined the chat')).toBeTruthy();
62
- expect(screen.queryByText('Technician Joined')).toBeNull();
63
- });
64
-
65
- it('hand-off bar names the team and shows their faces', () => {
66
- render(
67
- <ChatInput
68
- awaitingResponse
69
- appearance="v2"
70
- awaitingTeam={[
71
- { key: '1', name: 'Roman Smith' },
72
- { key: '2', name: 'Ada Lin' },
73
- ]}
74
- />,
75
- );
76
- expect(screen.getByText('Handed off to your technical support team')).toBeTruthy();
77
- expect(screen.getByRole('group', { name: 'Technicians: Roman Smith, Ada Lin' })).toBeTruthy();
78
- });
79
- });
@@ -1,56 +0,0 @@
1
- import { fireEvent, render, screen } from '@testing-library/react';
2
- import { describe, expect, it, vi } from 'vitest';
3
- import { OnboardingCarousel } from '../onboarding-carousel';
4
-
5
- const STEPS = [
6
- { id: 'a', icon: null, title: 'First' },
7
- { id: 'b', icon: null, title: 'Second' },
8
- { id: 'c', icon: null, title: 'Third' },
9
- ];
10
-
11
- const currentSlide = () =>
12
- screen.getAllByRole('group', { hidden: true }).find(el => el.getAttribute('aria-hidden') === 'false');
13
-
14
- describe('OnboardingCarousel', () => {
15
- it('starts on the first step with Previous disabled', () => {
16
- render(<OnboardingCarousel steps={STEPS} onComplete={vi.fn()} />);
17
- expect(currentSlide()).toHaveTextContent('First');
18
- expect(screen.getByRole('button', { name: 'Previous Step' })).toHaveAttribute('aria-disabled', 'true');
19
- expect(screen.getByRole('button', { name: 'Next Step' })).toBeEnabled();
20
- });
21
-
22
- it('walks forward and back', () => {
23
- render(<OnboardingCarousel steps={STEPS} onComplete={vi.fn()} />);
24
- fireEvent.click(screen.getByRole('button', { name: 'Next Step' }));
25
- expect(currentSlide()).toHaveTextContent('Second');
26
- fireEvent.click(screen.getByRole('button', { name: 'Previous Step' }));
27
- expect(currentSlide()).toHaveTextContent('First');
28
- expect(screen.getByText('Step 1 of 3: First')).toHaveAttribute('aria-live', 'polite');
29
- });
30
-
31
- it('swaps Next for the complete action on the last step', () => {
32
- const onComplete = vi.fn();
33
- render(<OnboardingCarousel steps={STEPS} onComplete={onComplete} />);
34
- fireEvent.click(screen.getByRole('button', { name: 'Go to step 3' }));
35
- expect(screen.queryByRole('button', { name: 'Next Step' })).not.toBeInTheDocument();
36
- fireEvent.click(screen.getByRole('button', { name: 'Start Chat' }));
37
- expect(onComplete).toHaveBeenCalledTimes(1);
38
- });
39
-
40
- it('follows the arrow keys and stops at the ends', () => {
41
- render(<OnboardingCarousel steps={STEPS} onComplete={vi.fn()} />);
42
- const region = screen.getByRole('region', { name: 'Introduction' });
43
- fireEvent.keyDown(region, { key: 'ArrowLeft' });
44
- expect(currentSlide()).toHaveTextContent('First');
45
- fireEvent.keyDown(region, { key: 'ArrowRight' });
46
- fireEvent.keyDown(region, { key: 'ArrowRight' });
47
- fireEvent.keyDown(region, { key: 'ArrowRight' });
48
- expect(currentSlide()).toHaveTextContent('Third');
49
- });
50
-
51
- it('marks the current dot', () => {
52
- render(<OnboardingCarousel steps={STEPS} onComplete={vi.fn()} />);
53
- expect(screen.getByRole('button', { name: 'Go to step 1' })).toHaveAttribute('aria-current', 'step');
54
- expect(screen.getByRole('button', { name: 'Go to step 2' })).not.toHaveAttribute('aria-current');
55
- });
56
- });
@@ -1,15 +0,0 @@
1
- 'use client';
2
-
3
- import { createContext, useContext } from 'react';
4
- import { CHAT_APPEARANCE, type ChatAppearance } from './types/chat.types';
5
-
6
- /**
7
- * Thread-wide `ChatAppearance`. `ChatMessageList` provides it, so the blocks a
8
- * message renders (error, lifecycle receipts) follow the thread without every
9
- * segment component growing an `appearance` prop.
10
- */
11
- export const ChatAppearanceContext = createContext<ChatAppearance>(CHAT_APPEARANCE.CLASSIC);
12
-
13
- export function useChatAppearance(): ChatAppearance {
14
- return useContext(ChatAppearanceContext);
15
- }
@@ -1,163 +0,0 @@
1
- 'use client';
2
-
3
- import { forwardRef, type ButtonHTMLAttributes, type HTMLAttributes, type ReactNode } from 'react';
4
- import { cn } from '../../utils/cn';
5
- import { ScrollFadeOverlay, useScrollFade } from '../ui/scroll-fade';
6
-
7
- export interface ChatNavSidebarItem {
8
- id: string;
9
- label: string;
10
- /** 24px glyph before the label. */
11
- icon: ReactNode;
12
- /** The view this item opens is the one on screen. */
13
- active?: boolean;
14
- onClick?: () => void;
15
- }
16
-
17
- export interface ChatNavSidebarProps extends HTMLAttributes<HTMLElement> {
18
- /** Brand row at the top. */
19
- logo?: ReactNode;
20
- /** Primary actions under the logo (new chat, archive, help, ...). */
21
- items: ChatNavSidebarItem[];
22
- /** Caption over the list (e.g. "Your Current Chats"). */
23
- sectionLabel?: string;
24
- /** The list itself, typically `ChatListItem` rows or an empty state. Scrolls
25
- * on its own; everything above it stays put. */
26
- children?: ReactNode;
27
- /** Pinned under the list, full width, above a divider (e.g. the MSP card). */
28
- footer?: ReactNode;
29
- }
30
-
31
- /**
32
- * Left rail of the fae chat v2 layout (Figma `chat-sidebar`): brand, a stack of
33
- * navigation actions, a captioned scrolling list and a pinned footer. It only
34
- * lays things out; which rows exist, what they show and what selecting them
35
- * does belong to the host.
36
- */
37
- const ChatNavSidebar = forwardRef<HTMLElement, ChatNavSidebarProps>(
38
- ({ className, logo, items, sectionLabel, children, footer, ...props }, ref) => {
39
- const { scrollRef, fadeTop, fadeBottom, update: updateFade } = useScrollFade<HTMLDivElement>();
40
-
41
- return (
42
- <aside
43
- ref={ref}
44
- className={cn('flex h-full w-[296px] shrink-0 flex-col border-r border-ods-border bg-ods-bg', className)}
45
- {...props}
46
- >
47
- <div className="flex min-h-0 flex-1 flex-col gap-[var(--spacing-system-m)] px-[var(--spacing-system-xs)] pt-[var(--spacing-system-mf)]">
48
- {logo && <div className="flex shrink-0 items-center px-[var(--spacing-system-xs)]">{logo}</div>}
49
-
50
- <nav className="flex shrink-0 flex-col gap-[var(--spacing-system-xxs)]">
51
- {items.map(item => (
52
- <ChatNavSidebarButton key={item.id} icon={item.icon} active={item.active} onClick={item.onClick}>
53
- {item.label}
54
- </ChatNavSidebarButton>
55
- ))}
56
- </nav>
57
-
58
- <div className="flex min-h-0 flex-1 flex-col gap-[var(--spacing-system-xxs)]">
59
- {sectionLabel && (
60
- <p className="shrink-0 px-[var(--spacing-system-xs)] pt-[var(--spacing-system-xs)] text-ods-text-secondary text-h5">
61
- {sectionLabel}
62
- </p>
63
- )}
64
- <div className="relative flex min-h-0 flex-1 flex-col">
65
- <div
66
- ref={scrollRef}
67
- onScroll={updateFade}
68
- className="flex min-h-0 flex-1 flex-col gap-[var(--spacing-system-xxs)] overflow-y-auto overscroll-contain pb-[var(--spacing-system-mf)]"
69
- >
70
- {children}
71
- </div>
72
- <ScrollFadeOverlay edge="top" visible={fadeTop} />
73
- <ScrollFadeOverlay edge="bottom" visible={fadeBottom} />
74
- </div>
75
- </div>
76
- </div>
77
-
78
- {footer && <div className="shrink-0 border-t border-ods-border">{footer}</div>}
79
- </aside>
80
- );
81
- },
82
- );
83
-
84
- ChatNavSidebar.displayName = 'ChatNavSidebar';
85
-
86
- interface ChatNavSidebarButtonProps extends ButtonHTMLAttributes<HTMLButtonElement> {
87
- icon: ReactNode;
88
- active?: boolean;
89
- }
90
-
91
- function ChatNavSidebarButton({ icon, active, className, children, ...props }: ChatNavSidebarButtonProps) {
92
- return (
93
- <button
94
- type="button"
95
- aria-current={active ? 'page' : undefined}
96
- className={cn(
97
- 'flex w-full items-center gap-[var(--spacing-system-xs)] rounded-md p-[var(--spacing-system-xs)] text-left text-h4',
98
- 'focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ods-focus',
99
- '[&_svg]:size-6 [&_svg]:shrink-0',
100
- active ? 'text-ods-accent' : 'text-ods-text-primary [&_svg]:text-ods-text-secondary',
101
- className,
102
- )}
103
- {...props}
104
- >
105
- {icon}
106
- <span className="min-w-0 flex-1 truncate">{children}</span>
107
- </button>
108
- );
109
- }
110
-
111
- export interface ChatListItemProps extends Omit<ButtonHTMLAttributes<HTMLButtonElement>, 'title'> {
112
- title: ReactNode;
113
- /** Second line (e.g. the ticket number). */
114
- subtitle?: ReactNode;
115
- /** 16px mark before the title (e.g. a resolved check). */
116
- leading?: ReactNode;
117
- /** 24px status glyph at the row's end. */
118
- trailing?: ReactNode;
119
- /** The chat open on screen. */
120
- active?: boolean;
121
- }
122
-
123
- /**
124
- * One row of the `ChatNavSidebar` list (Figma `chat-list-item`): a one-line
125
- * title over a caption, an optional mark before the title and a status glyph
126
- * at the end. The selected row takes the accent's secondary fill, so a tenant
127
- * accent recolours it with the rest of the brand.
128
- */
129
- const ChatListItem = forwardRef<HTMLButtonElement, ChatListItemProps>(
130
- ({ className, title, subtitle, leading, trailing, active, ...props }, ref) => (
131
- <button
132
- ref={ref}
133
- type="button"
134
- aria-current={active ? 'true' : undefined}
135
- className={cn(
136
- 'flex w-full shrink-0 items-center gap-[var(--spacing-system-xs)] rounded-md p-[var(--spacing-system-xs)] text-left',
137
- 'focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-ods-focus',
138
- active && 'bg-ods-accent-secondary',
139
- className,
140
- )}
141
- {...props}
142
- >
143
- <span className="flex min-w-0 flex-1 flex-col">
144
- <span className="flex min-w-0 items-center gap-[var(--spacing-system-xxs)]">
145
- {leading && <span className="flex shrink-0 items-center [&_svg]:size-4">{leading}</span>}
146
- <span className={cn('min-w-0 flex-1 truncate text-h4', active ? 'text-ods-accent' : 'text-ods-text-primary')}>
147
- {title}
148
- </span>
149
- </span>
150
- {subtitle != null && (
151
- <span className={cn('truncate text-h6', active ? 'text-ods-text-primary' : 'text-ods-text-secondary')}>
152
- {subtitle}
153
- </span>
154
- )}
155
- </span>
156
- {trailing && <span className="flex shrink-0 items-center [&_svg]:size-6">{trailing}</span>}
157
- </button>
158
- ),
159
- );
160
-
161
- ChatListItem.displayName = 'ChatListItem';
162
-
163
- export { ChatNavSidebar, ChatListItem };
@@ -1,109 +0,0 @@
1
- 'use client';
2
-
3
- import { forwardRef, type HTMLAttributes, type ReactNode } from 'react';
4
- import { cn } from '../../utils/cn';
5
- import { Settings01Icon, SidebarIcon } from '../icons-v2-generated';
6
- import { Skeleton } from '../ui/skeleton';
7
- import { SquareAvatar } from '../ui/square-avatar';
8
-
9
- export interface ChatTopNavigationProps extends HTMLAttributes<HTMLElement> {
10
- /** Who the user is talking to. */
11
- name: string;
12
- /** Line under the name (e.g. "Your AI Assistant", "IT Technician"). */
13
- subtitle?: string;
14
- avatarUrl?: string | null;
15
- /** Actions after the identity (e.g. "Request a Technician"). */
16
- actions?: ReactNode;
17
- /** Shows the sidebar toggle at the start of the bar. */
18
- onToggleSidebar?: () => void;
19
- /** Whether the sidebar is currently shown; drives the toggle's state. */
20
- sidebarOpen?: boolean;
21
- /** Shows the settings button at the end of the bar. */
22
- onOpenSettings?: () => void;
23
- /** Content above the bar, full width (e.g. a "Back to ..." strip). */
24
- before?: ReactNode;
25
- /** Identity still resolving: placeholders instead of a default name that
26
- * would flash before the tenant's branding lands. */
27
- isLoading?: boolean;
28
- }
29
-
30
- const edgeButtonClass = cn(
31
- 'flex size-14 shrink-0 items-center justify-center border-ods-border text-ods-text-secondary',
32
- 'hover:text-ods-text-primary focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-ods-focus',
33
- '[&_svg]:size-6',
34
- );
35
-
36
- /**
37
- * Top bar of the fae chat v2 layout (Figma `chat-top-navigation`): an optional
38
- * sidebar toggle, the counterpart's avatar, name and role, the host's actions
39
- * and an optional settings button, split by vertical dividers.
40
- */
41
- const ChatTopNavigation = forwardRef<HTMLElement, ChatTopNavigationProps>(
42
- (
43
- {
44
- className,
45
- name,
46
- subtitle,
47
- avatarUrl,
48
- actions,
49
- onToggleSidebar,
50
- sidebarOpen,
51
- onOpenSettings,
52
- before,
53
- isLoading,
54
- ...props
55
- },
56
- ref,
57
- ) => (
58
- <header ref={ref} className={cn('flex shrink-0 flex-col bg-ods-bg', className)} {...props}>
59
- {before}
60
- <div className="flex h-14 items-stretch border-b border-ods-border">
61
- {onToggleSidebar && (
62
- <button
63
- type="button"
64
- onClick={onToggleSidebar}
65
- aria-label={sidebarOpen ? 'Hide sidebar' : 'Show sidebar'}
66
- aria-expanded={sidebarOpen}
67
- className={cn(edgeButtonClass, 'border-r')}
68
- >
69
- <SidebarIcon />
70
- </button>
71
- )}
72
- <div className="flex min-w-0 flex-1 items-center gap-[var(--spacing-system-m)] px-[var(--spacing-system-m)]">
73
- {isLoading ? (
74
- <>
75
- <Skeleton className="size-10 shrink-0 rounded-full" />
76
- <div className="flex min-w-0 flex-1 flex-col gap-[var(--spacing-system-xxs)]">
77
- <Skeleton className="h-5 w-24" />
78
- <Skeleton className="h-4 w-32" />
79
- </div>
80
- </>
81
- ) : (
82
- <>
83
- <SquareAvatar src={avatarUrl ?? undefined} alt={name} fallback={name} size="md" variant="round" />
84
- <div className="flex min-w-0 flex-1 flex-col">
85
- <p className="truncate text-ods-text-primary text-h3">{name}</p>
86
- {subtitle && <p className="truncate text-ods-text-secondary text-h6">{subtitle}</p>}
87
- </div>
88
- </>
89
- )}
90
- {actions && <div className="flex shrink-0 items-center gap-[var(--spacing-system-xs)]">{actions}</div>}
91
- </div>
92
- {onOpenSettings && (
93
- <button
94
- type="button"
95
- onClick={onOpenSettings}
96
- aria-label="Settings"
97
- className={cn(edgeButtonClass, 'border-l')}
98
- >
99
- <Settings01Icon />
100
- </button>
101
- )}
102
- </div>
103
- </header>
104
- ),
105
- );
106
-
107
- ChatTopNavigation.displayName = 'ChatTopNavigation';
108
-
109
- export { ChatTopNavigation };