pixelon 0.3.24 → 0.3.26

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 (231) hide show
  1. package/dist/components/atoms/chat/AudioWaves/AudioWaves(1).d.ts +21 -0
  2. package/dist/components/atoms/chat/AudioWaves/index(1).d.ts +2 -0
  3. package/dist/components/atoms/chat/DateDivider/DateDivider(1).d.ts +7 -0
  4. package/dist/components/atoms/chat/Loader/Loader(1).d.ts +10 -0
  5. package/dist/components/atoms/chat/Loader/index(1).d.ts +2 -0
  6. package/dist/components/atoms/chat/Select/index(1).d.ts +2 -0
  7. package/dist/components/atoms/lumi/Button/Button(1).d.ts +17 -0
  8. package/dist/components/atoms/lumi/Checkbox/Checkbox(1).d.ts +5 -0
  9. package/dist/components/atoms/lumi/Checkbox/index(1).d.ts +2 -0
  10. package/dist/components/atoms/lumi/Checkbox/index(2).d.ts +2 -0
  11. package/dist/components/atoms/lumi/Checkbox/types(1).d.ts +93 -0
  12. package/dist/components/atoms/lumi/CurrencyDisplay/index(1).d.ts +2 -0
  13. package/dist/components/atoms/lumi/DateDisplay/index(1).d.ts +2 -0
  14. package/dist/components/atoms/lumi/DateDisplay/index(2).d.ts +2 -0
  15. package/dist/components/atoms/lumi/DateInput/DateInput(1).d.ts +27 -0
  16. package/dist/components/atoms/lumi/DateInput/WebDatePicker(1).d.ts +19 -0
  17. package/dist/components/atoms/lumi/DateInput/WebDatePicker(2).d.ts +19 -0
  18. package/dist/components/atoms/lumi/Icon/Icon(1).d.ts +52 -0
  19. package/dist/components/atoms/lumi/Input/index(1).d.ts +3 -0
  20. package/dist/components/atoms/lumi/Popover/index(1).d.ts +2 -0
  21. package/dist/components/atoms/lumi/Popover/types(1).d.ts +62 -0
  22. package/dist/components/atoms/lumi/TextArea/index(1).d.ts +2 -0
  23. package/dist/components/atoms/lumi/TextArea/types(1).d.ts +35 -0
  24. package/dist/components/atoms/lumi/TimeInput/TimeInput(1).d.ts +27 -0
  25. package/dist/components/atoms/lumi/TimeInput/TimeInput(2).d.ts +27 -0
  26. package/dist/components/molecules/chat/Drawer/Drawer.d.ts +2 -0
  27. package/dist/components/molecules/chat/FullscreenViewer/hooks/useSwipeGestures(1).d.ts +12 -0
  28. package/dist/components/molecules/chat/StructuredContent/StructuredContent(1).d.ts +10 -0
  29. package/dist/components/molecules/chat/StructuredContent/components/CarouselDisplay/CarouselDisplay.d.ts +4 -0
  30. package/dist/components/molecules/chat/StructuredContent/components/CarouselDisplay/components/CarouselCard/CarouselCard.d.ts +15 -0
  31. package/dist/components/molecules/chat/StructuredContent/components/CarouselDisplay/components/CarouselConfirm/CarouselConfirm.d.ts +10 -0
  32. package/dist/components/molecules/chat/StructuredContent/components/CarouselDisplay/components/CarouselSearch/CarouselSearch.d.ts +8 -0
  33. package/dist/components/molecules/chat/StructuredContent/components/CarouselDisplay/components/CarouselTrack/CarouselTrack.d.ts +11 -0
  34. package/dist/components/molecules/chat/StructuredContent/components/CarouselDisplay/store/actions.d.ts +26 -0
  35. package/dist/components/molecules/chat/StructuredContent/components/CarouselDisplay/store/carouselStore.d.ts +8 -0
  36. package/dist/components/molecules/chat/StructuredContent/components/CarouselDisplay/store/index.d.ts +6 -0
  37. package/dist/components/molecules/chat/StructuredContent/components/CarouselDisplay/store/storeKeys.d.ts +10 -0
  38. package/dist/components/molecules/chat/StructuredContent/components/CarouselDisplay/store/types.d.ts +11 -0
  39. package/dist/components/molecules/chat/StructuredContent/components/CarouselDisplay/types.d.ts +43 -0
  40. package/dist/components/molecules/chat/StructuredContent/components/CarouselDisplay/useCarouselSearch.d.ts +15 -0
  41. package/dist/components/molecules/chat/StructuredContent/components/CarouselDisplay/useStoreState.d.ts +3 -0
  42. package/dist/components/molecules/chat/StructuredContent/components/ReactiveForm/DynamicField(1).d.ts +13 -0
  43. package/dist/components/molecules/chat/StructuredContent/components/ReactiveForm/DynamicField.d.ts +13 -0
  44. package/dist/components/molecules/chat/StructuredContent/components/ReactiveForm/ReactiveForm.d.ts +4 -0
  45. package/dist/components/molecules/chat/StructuredContent/components/ReactiveForm/ReactiveFormView.d.ts +10 -0
  46. package/dist/components/molecules/chat/StructuredContent/components/ReactiveForm/buildYupSchema(1).d.ts +4 -0
  47. package/dist/components/molecules/chat/StructuredContent/components/ReactiveForm/buildYupSchema.d.ts +4 -0
  48. package/dist/components/molecules/chat/StructuredContent/components/ReactiveForm/resolveVariables.d.ts +20 -0
  49. package/dist/components/molecules/chat/StructuredContent/components/ReactiveForm/types(1).d.ts +91 -0
  50. package/dist/components/molecules/chat/StructuredContent/components/ReactiveForm/types.d.ts +100 -0
  51. package/dist/components/molecules/chat/StructuredContent/components/ReactiveForm/useReactiveEndpoints(1).d.ts +17 -0
  52. package/dist/components/molecules/chat/StructuredContent/components/ReactiveForm/useReactiveEndpoints(2).d.ts +23 -0
  53. package/dist/components/molecules/chat/StructuredContent/components/ReactiveForm/useReactiveEndpoints.d.ts +23 -0
  54. package/dist/components/molecules/chat/StructuredContent/components/ReactiveForm/useReactiveForm(1).d.ts +38 -0
  55. package/dist/components/molecules/chat/StructuredContent/components/ReactiveForm/useReactiveForm.d.ts +38 -0
  56. package/dist/components/molecules/chat/StructuredContent/components/index.d.ts +2 -0
  57. package/dist/components/molecules/chat/StructuredContent/helpers/contentParser(1).d.ts +7 -0
  58. package/dist/components/molecules/chat/StructuredContent/helpers/fetchViaEventBus.d.ts +2 -0
  59. package/dist/components/molecules/chat/StructuredContent/index(1).d.ts +2 -0
  60. package/dist/components/molecules/lumi/Breadcrumb/Breadcrumb(1).d.ts +10 -0
  61. package/dist/components/molecules/lumi/Breadcrumb/Breadcrumb(2).d.ts +10 -0
  62. package/dist/components/molecules/lumi/Breadcrumb/types(1).d.ts +105 -0
  63. package/dist/components/molecules/lumi/Checkbox/Checkbox(1).d.ts +11 -0
  64. package/dist/components/molecules/lumi/Checkbox/index(1).d.ts +4 -0
  65. package/dist/components/molecules/lumi/Checkbox/use-cases/index(1).d.ts +1 -0
  66. package/dist/components/molecules/lumi/Checkbox/validation-helpers(1).d.ts +151 -0
  67. package/dist/components/molecules/lumi/DateInput/FormDateInput(1).d.ts +12 -0
  68. package/dist/components/molecules/lumi/DateInput/index(1).d.ts +2 -0
  69. package/dist/components/molecules/lumi/DateInput/use-cases/FormDateInputClearWithResetUseCase(1).d.ts +21 -0
  70. package/dist/components/molecules/lumi/DateInput/use-cases/FormDateInputErrorVisibilityUseCase(1).d.ts +21 -0
  71. package/dist/components/molecules/lumi/Drawer/Drawer(1).d.ts +39 -0
  72. package/dist/components/molecules/lumi/Drawer/index(1).d.ts +2 -0
  73. package/dist/components/molecules/lumi/DropdownMenu/DropdownMenu(1).d.ts +22 -0
  74. package/dist/components/molecules/lumi/DropdownMenu/index(1).d.ts +2 -0
  75. package/dist/components/molecules/lumi/DropdownMenu/types(1).d.ts +29 -0
  76. package/dist/components/molecules/lumi/Filter/FilterRow(1).d.ts +13 -0
  77. package/dist/components/molecules/lumi/Filter/helpers/conditionHelpers(1).d.ts +14 -0
  78. package/dist/components/molecules/lumi/Filter/index(1).d.ts +5 -0
  79. package/dist/components/molecules/lumi/Filter/types(1).d.ts +115 -0
  80. package/dist/components/molecules/lumi/Input/Input(1).d.ts +12 -0
  81. package/dist/components/molecules/lumi/Menu/Menu(1).d.ts +18 -0
  82. package/dist/components/molecules/lumi/Menu/MenuContext(1).d.ts +41 -0
  83. package/dist/components/molecules/lumi/Menu/MenuItem(1).d.ts +6 -0
  84. package/dist/components/molecules/lumi/Menu/MenuItem(2).d.ts +6 -0
  85. package/dist/components/molecules/lumi/Menu/MenuItemGroup(1).d.ts +6 -0
  86. package/dist/components/molecules/lumi/Menu/SubMenu(1).d.ts +6 -0
  87. package/dist/components/molecules/lumi/Menu/iconHelper(1).d.ts +15 -0
  88. package/dist/components/molecules/lumi/Menu/index(1).d.ts +8 -0
  89. package/dist/components/molecules/lumi/Menu/index(2).d.ts +8 -0
  90. package/dist/components/molecules/lumi/Menu/types(1).d.ts +119 -0
  91. package/dist/components/molecules/lumi/Pagination/Pagination(1).d.ts +4 -0
  92. package/dist/components/molecules/lumi/Pagination/index(1).d.ts +2 -0
  93. package/dist/components/molecules/lumi/Select/Select(1).d.ts +14 -0
  94. package/dist/components/molecules/lumi/Select/Select(2).d.ts +14 -0
  95. package/dist/components/molecules/lumi/Select/Select(3).d.ts +14 -0
  96. package/dist/components/molecules/lumi/Select/index(1).d.ts +2 -0
  97. package/dist/components/molecules/lumi/Select/index(2).d.ts +2 -0
  98. package/dist/components/molecules/lumi/Select/use-cases/FormSelectClearWithResetUseCase(1).d.ts +21 -0
  99. package/dist/components/molecules/lumi/Select/use-cases/FormSelectClearWithResetUseCase(2).d.ts +21 -0
  100. package/dist/components/molecules/lumi/Select/use-cases/index(1).d.ts +2 -0
  101. package/dist/components/molecules/lumi/Select/use-cases/index(2).d.ts +2 -0
  102. package/dist/components/molecules/lumi/Table/Table(1).d.ts +6 -0
  103. package/dist/components/molecules/lumi/Table/Table(2).d.ts +6 -0
  104. package/dist/components/molecules/lumi/Table/index(1).d.ts +2 -0
  105. package/dist/components/molecules/lumi/Table/types(1).d.ts +177 -0
  106. package/dist/components/molecules/lumi/Table/types(2).d.ts +177 -0
  107. package/dist/components/molecules/lumi/Tabs/Tabs(1).d.ts +4 -0
  108. package/dist/components/molecules/lumi/Tabs/Tabs(2).d.ts +4 -0
  109. package/dist/components/molecules/lumi/Tabs/index(1).d.ts +2 -0
  110. package/dist/components/molecules/lumi/Tabs/index(2).d.ts +2 -0
  111. package/dist/components/molecules/lumi/TimeInput/FormTimeInput(1).d.ts +12 -0
  112. package/dist/components/molecules/lumi/TimeInput/use-cases/FormTimeInputClearWithResetUseCase(1).d.ts +21 -0
  113. package/dist/components/molecules/lumi/TimeInput/use-cases/FormTimeInputErrorVisibilityUseCase(1).d.ts +21 -0
  114. package/dist/components/molecules/lumi/TimeInput/use-cases/index(1).d.ts +4 -0
  115. package/dist/components/organisms/chat/Chat/Chat(1).d.ts +12 -0
  116. package/dist/components/organisms/chat/Chat/hooks/useChatHandlers(1).d.ts +15 -0
  117. package/dist/components/organisms/chat/Chat/hooks/useChatStore.d.ts +3 -0
  118. package/dist/components/organisms/chat/Chat/hooks/useKeyboardLock(1).d.ts +15 -0
  119. package/dist/components/organisms/chat/Chat/index(1).d.ts +3 -0
  120. package/dist/components/organisms/chat/Chat/store/actions.d.ts +3 -0
  121. package/dist/components/organisms/chat/Chat/store/index(1).d.ts +4 -0
  122. package/dist/components/organisms/chat/Chat/store/types.d.ts +3 -0
  123. package/dist/components/organisms/chat/Chat/use-cases/GroupMessagesByDateUseCase(1).d.ts +20 -0
  124. package/dist/components/organisms/chat/index(1).d.ts +3 -0
  125. package/dist/components/organisms/chat/index(2).d.ts +3 -0
  126. package/dist/components/organisms/lumi/ActionBar/ActionBar(1).d.ts +18 -0
  127. package/dist/components/organisms/lumi/ActionBar/types(1).d.ts +57 -0
  128. package/dist/components/organisms/lumi/BaseNavbar/types(1).d.ts +34 -0
  129. package/dist/components/organisms/lumi/BaseWorkspace/BaseWorkspace(1).d.ts +28 -0
  130. package/dist/components/organisms/lumi/BaseWorkspace/index(1).d.ts +2 -0
  131. package/dist/components/organisms/lumi/Calendar/components/CalendarEvent(1).d.ts +18 -0
  132. package/dist/components/organisms/lumi/Calendar/components/CalendarEvent(2).d.ts +18 -0
  133. package/dist/components/organisms/lumi/Calendar/components/CalendarEvent(3).d.ts +18 -0
  134. package/dist/components/organisms/lumi/Calendar/components/CalendarHeader(1).d.ts +14 -0
  135. package/dist/components/organisms/lumi/Calendar/components/TimeGutter(1).d.ts +10 -0
  136. package/dist/components/organisms/lumi/Calendar/components/TimeGutter(2).d.ts +10 -0
  137. package/dist/components/organisms/lumi/Calendar/hooks/index(1).d.ts +4 -0
  138. package/dist/components/organisms/lumi/Calendar/hooks/useCalendarHeight(1).d.ts +58 -0
  139. package/dist/components/organisms/lumi/Calendar/hooks/useCalendarHeight(2).d.ts +58 -0
  140. package/dist/components/organisms/lumi/Calendar/hooks/useEventLayout(1).d.ts +21 -0
  141. package/dist/components/organisms/lumi/Calendar/hooks/useEventLayout(2).d.ts +21 -0
  142. package/dist/components/organisms/lumi/Calendar/hooks/useTimeSlots(1).d.ts +14 -0
  143. package/dist/components/organisms/lumi/Calendar/hooks/useTimeSlots(2).d.ts +14 -0
  144. package/dist/components/organisms/lumi/Calendar/hooks/useTimeSlots(3).d.ts +14 -0
  145. package/dist/components/organisms/lumi/Calendar/i18n/index(1).d.ts +1 -0
  146. package/dist/components/organisms/lumi/Calendar/i18n/index(2).d.ts +1 -0
  147. package/dist/components/organisms/lumi/Calendar/i18n/translations(1).d.ts +34 -0
  148. package/dist/components/organisms/lumi/Calendar/index(1).d.ts +2 -0
  149. package/dist/components/organisms/lumi/Calendar/utils/dateUtils(1).d.ts +140 -0
  150. package/dist/components/organisms/lumi/Calendar/utils/dateUtils(2).d.ts +140 -0
  151. package/dist/components/organisms/lumi/Calendar/utils/index(1).d.ts +2 -0
  152. package/dist/components/organisms/lumi/Calendar/utils/multiDayUtils(1).d.ts +73 -0
  153. package/dist/components/organisms/lumi/Calendar/views/DayView(1).d.ts +17 -0
  154. package/dist/components/organisms/lumi/Calendar/views/DayView(2).d.ts +17 -0
  155. package/dist/components/organisms/lumi/Calendar/views/MonthView(1).d.ts +17 -0
  156. package/dist/components/organisms/lumi/Calendar/views/MonthView(2).d.ts +17 -0
  157. package/dist/components/organisms/lumi/Calendar/views/WeekView(1).d.ts +19 -0
  158. package/dist/components/organisms/lumi/Calendar/views/WeekView(2).d.ts +19 -0
  159. package/dist/components/organisms/lumi/Calendar/views/YearView(1).d.ts +13 -0
  160. package/dist/components/organisms/lumi/Calendar/views/index(1).d.ts +4 -0
  161. package/dist/components/organisms/lumi/Calendar/views/index(2).d.ts +4 -0
  162. package/dist/components/organisms/lumi/DashboardNavbar/index(1).d.ts +7 -0
  163. package/dist/components/organisms/lumi/DashboardNavbar/types(1).d.ts +52 -0
  164. package/dist/components/organisms/lumi/DashboardWorkspace/DashboardWorkspace(1).d.ts +23 -0
  165. package/dist/components/organisms/lumi/DashboardWorkspace/DashboardWorkspace(2).d.ts +23 -0
  166. package/dist/components/organisms/lumi/DashboardWorkspace/index(1).d.ts +7 -0
  167. package/dist/components/organisms/lumi/DashboardWorkspace/index(2).d.ts +7 -0
  168. package/dist/components/organisms/lumi/DashboardWorkspace/types(1).d.ts +60 -0
  169. package/dist/components/organisms/lumi/DashboardWorkspace/types(2).d.ts +60 -0
  170. package/dist/components/organisms/lumi/DynamicForm/DynamicForm(1).d.ts +21 -0
  171. package/dist/components/organisms/lumi/DynamicForm/helpers/fieldMapper(1).d.ts +17 -0
  172. package/dist/components/organisms/lumi/DynamicForm/helpers/fieldMapper(2).d.ts +17 -0
  173. package/dist/components/organisms/lumi/DynamicForm/helpers/fieldRenderer(1).d.ts +6 -0
  174. package/dist/components/organisms/lumi/DynamicForm/helpers/fieldRenderer(2).d.ts +6 -0
  175. package/dist/components/organisms/lumi/DynamicForm/index(1).d.ts +2 -0
  176. package/dist/components/organisms/lumi/DynamicForm/index(2).d.ts +2 -0
  177. package/dist/components/organisms/lumi/DynamicForm/types(1).d.ts +96 -0
  178. package/dist/components/organisms/lumi/DynamicForm/types(2).d.ts +96 -0
  179. package/dist/components/organisms/lumi/FormDrawer/FormDrawer(1).d.ts +5 -0
  180. package/dist/components/organisms/lumi/FormDrawer/index(1).d.ts +3 -0
  181. package/dist/components/organisms/lumi/FormDrawer/types(1).d.ts +61 -0
  182. package/dist/components/organisms/lumi/FormDrawer/types(2).d.ts +61 -0
  183. package/dist/components/organisms/lumi/Stepper/StepIndicator(1).d.ts +4 -0
  184. package/dist/components/organisms/lumi/Stepper/Stepper(1).d.ts +5 -0
  185. package/dist/components/organisms/lumi/Stepper/index(1).d.ts +3 -0
  186. package/dist/components/organisms/lumi/Stepper/types(1).d.ts +96 -0
  187. package/dist/components/organisms/lumi/Stepper/types(2).d.ts +96 -0
  188. package/dist/components/organisms/lumi/index(1).d.ts +10 -0
  189. package/dist/components/organisms/lumi/index(2).d.ts +10 -0
  190. package/dist/components/templates/chat/ChatWidget/ChatWidget(1).d.ts +10 -0
  191. package/dist/components/templates/chat/ChatWidget/hooks/index(1).d.ts +1 -0
  192. package/dist/components/templates/chat/ChatWidget/index(1).d.ts +2 -0
  193. package/dist/components/templates/chat/ChatWidget/index(2).d.ts +2 -0
  194. package/dist/components/templates/chat/ChatWidget/types(1).d.ts +90 -0
  195. package/dist/components/templates/lumi/Base/hooks/index(1).d.ts +2 -0
  196. package/dist/components/templates/lumi/Base/hooks/useAppHeight(1).d.ts +21 -0
  197. package/dist/components/templates/lumi/Base/index(1).d.ts +2 -0
  198. package/dist/components/templates/lumi/Base/types(1).d.ts +54 -0
  199. package/dist/components/templates/lumi/Crud/Crud(1).d.ts +6 -0
  200. package/dist/components/templates/lumi/Crud/Crud(2).d.ts +6 -0
  201. package/dist/components/templates/lumi/Crud/helpers/fieldMapper(1).d.ts +13 -0
  202. package/dist/components/templates/lumi/Crud/hooks/useCrudActions(1).d.ts +11 -0
  203. package/dist/components/templates/lumi/Crud/index(1).d.ts +2 -0
  204. package/dist/components/templates/lumi/Crud/store/actions(1).d.ts +45 -0
  205. package/dist/components/templates/lumi/Crud/store/crudStore(1).d.ts +8 -0
  206. package/dist/components/templates/lumi/Crud/store/index(1).d.ts +5 -0
  207. package/dist/components/templates/lumi/Crud/store/types(1).d.ts +71 -0
  208. package/dist/components/templates/lumi/Dashboard/Dashboard(1).d.ts +25 -0
  209. package/dist/components/templates/lumi/Dashboard/hooks/index(1).d.ts +12 -0
  210. package/dist/components/templates/lumi/Dashboard/hooks/index(2).d.ts +12 -0
  211. package/dist/components/templates/lumi/Dashboard/hooks/useDashboardStore(1).d.ts +34 -0
  212. package/dist/components/templates/lumi/Dashboard/hooks/useScrollToTop(1).d.ts +47 -0
  213. package/dist/components/templates/lumi/Dashboard/index(1).d.ts +10 -0
  214. package/dist/components/templates/lumi/Dashboard/store/storeKeys(1).d.ts +13 -0
  215. package/dist/components/templates/lumi/Dashboard/store/types(1).d.ts +73 -0
  216. package/dist/components/templates/lumi/Dashboard/store/types(2).d.ts +73 -0
  217. package/dist/components/templates/lumi/Dashboard/types(1).d.ts +114 -0
  218. package/dist/components/templates/lumi/Dashboard/types(2).d.ts +114 -0
  219. package/dist/components/templates/lumi/index(1).d.ts +3 -0
  220. package/dist/core/chat/ChatConfigContext(1).d.ts +36 -0
  221. package/dist/core/chat/chatMessage.d.ts +1 -1
  222. package/dist/core/eventBus/chatEventBus.d.ts +72 -0
  223. package/dist/index(1).esm.js +19378 -0
  224. package/dist/index(1).js +19487 -0
  225. package/dist/index.esm.js +2260 -382
  226. package/dist/index.js +2260 -382
  227. package/dist/styles(1).css +1 -0
  228. package/dist/styles.css +1 -1
  229. package/dist/styles.css.map +1 -1
  230. package/package.json +1 -1
  231. package/src/styles/index.scss +7 -0
package/dist/index.js CHANGED
@@ -8,9 +8,9 @@ var ReactMarkdown = require('react-markdown');
8
8
  var DatePicker = require('react-datepicker');
9
9
  var locale = require('date-fns/locale');
10
10
  require('react-datepicker/dist/react-datepicker.css');
11
+ var yup = require('yup');
11
12
  var qrcode_react = require('qrcode.react');
12
13
  var reactHookForm = require('react-hook-form');
13
- var yup = require('yup');
14
14
  var reactRouterDom = require('react-router-dom');
15
15
  var yup$1 = require('@hookform/resolvers/yup');
16
16
 
@@ -1639,7 +1639,7 @@ function parseContent(content) {
1639
1639
  return null;
1640
1640
  }
1641
1641
 
1642
- const DISPLAY_COMPONENTS = /* @__PURE__ */ new Set(["card", "badge"]);
1642
+ const DISPLAY_COMPONENTS = /* @__PURE__ */ new Set(["card", "badge", "reactive_form", "carousel"]);
1643
1643
 
1644
1644
  const useAppHeight$5 = () => {
1645
1645
  React.useEffect(() => {
@@ -1679,6 +1679,7 @@ const Drawer$1 = ({
1679
1679
  title,
1680
1680
  headerExtra,
1681
1681
  footer,
1682
+ placement = "bottom",
1682
1683
  showCloseButton = true,
1683
1684
  closeOnOverlayClick = true,
1684
1685
  closeOnEscape = true,
@@ -1730,6 +1731,7 @@ const Drawer$1 = ({
1730
1731
  const drawerClasses = [
1731
1732
  `${prefix}drawer`,
1732
1733
  animating && `${prefix}drawer--open`,
1734
+ `${prefix}drawer--${placement}`,
1733
1735
  className
1734
1736
  ].filter(Boolean).join(" ");
1735
1737
  return ReactDOM.createPortal(
@@ -1795,7 +1797,15 @@ const CHAT_EVENT = {
1795
1797
  RETRY_MESSAGE: "retryMessage",
1796
1798
  PLACEHOLDER_UPDATED: "placeholderUpdated",
1797
1799
  THINKING_UPDATED: "thinkingUpdated",
1798
- CLOSE: "close"
1800
+ INPUT_DISABLED: "inputDisabled",
1801
+ CLOSE: "close",
1802
+ FETCH_REQUEST: "fetchRequest",
1803
+ FETCH_RESPONSE: "fetchResponse",
1804
+ FORM_SUBMIT: "formSubmit",
1805
+ FORM_TRACE: "formTrace",
1806
+ AGENT_EVENT: "agentEvent",
1807
+ STREAM_CHUNK: "streamChunk",
1808
+ MESSAGE_SAVED: "messageSaved"
1799
1809
  };
1800
1810
  const chatEventBus = createEventBus();
1801
1811
 
@@ -1822,13 +1832,13 @@ function useComponentInteraction({
1822
1832
  return { emitInteraction, isConfirmed };
1823
1833
  }
1824
1834
 
1825
- const MOBILE_BREAKPOINT$3 = 640;
1826
- const useIsMobile$4 = () => {
1835
+ const MOBILE_BREAKPOINT$4 = 640;
1836
+ const useIsMobile$5 = () => {
1827
1837
  const [isMobile, setIsMobile] = React.useState(
1828
- typeof window !== "undefined" ? window.innerWidth < MOBILE_BREAKPOINT$3 : false
1838
+ typeof window !== "undefined" ? window.innerWidth < MOBILE_BREAKPOINT$4 : false
1829
1839
  );
1830
1840
  React.useEffect(() => {
1831
- const mq = window.matchMedia(`(max-width: ${MOBILE_BREAKPOINT$3 - 1}px)`);
1841
+ const mq = window.matchMedia(`(max-width: ${MOBILE_BREAKPOINT$4 - 1}px)`);
1832
1842
  const handler = (e) => setIsMobile(e.matches);
1833
1843
  mq.addEventListener("change", handler);
1834
1844
  return () => mq.removeEventListener("change", handler);
@@ -1844,7 +1854,7 @@ const SelectWithConfirm = ({
1844
1854
  const [isDrawerOpen, setIsDrawerOpen] = React.useState(false);
1845
1855
  const [searchValue, setSearchValue] = React.useState("");
1846
1856
  const searchInputRef = React.useRef(null);
1847
- const isMobile = useIsMobile$4();
1857
+ const isMobile = useIsMobile$5();
1848
1858
  const { field_name, value, ...componentProps } = component.props;
1849
1859
  const options = componentProps.options || [];
1850
1860
  const placeholder = componentProps.placeholder || "Seleccionar...";
@@ -2011,13 +2021,13 @@ const SelectWithConfirm = ({
2011
2021
  ] });
2012
2022
  };
2013
2023
 
2014
- const MOBILE_BREAKPOINT$2 = 640;
2015
- const useIsMobile$3 = () => {
2024
+ const MOBILE_BREAKPOINT$3 = 640;
2025
+ const useIsMobile$4 = () => {
2016
2026
  const [isMobile, setIsMobile] = React.useState(
2017
- typeof window !== "undefined" ? window.innerWidth < MOBILE_BREAKPOINT$2 : false
2027
+ typeof window !== "undefined" ? window.innerWidth < MOBILE_BREAKPOINT$3 : false
2018
2028
  );
2019
2029
  React.useEffect(() => {
2020
- const mq = window.matchMedia(`(max-width: ${MOBILE_BREAKPOINT$2 - 1}px)`);
2030
+ const mq = window.matchMedia(`(max-width: ${MOBILE_BREAKPOINT$3 - 1}px)`);
2021
2031
  const handler = (e) => setIsMobile(e.matches);
2022
2032
  mq.addEventListener("change", handler);
2023
2033
  return () => mq.removeEventListener("change", handler);
@@ -2033,7 +2043,7 @@ const SelectMultipleWithConfirm = ({
2033
2043
  const [isDrawerOpen, setIsDrawerOpen] = React.useState(false);
2034
2044
  const [searchValue, setSearchValue] = React.useState("");
2035
2045
  const searchInputRef = React.useRef(null);
2036
- const isMobile = useIsMobile$3();
2046
+ const isMobile = useIsMobile$4();
2037
2047
  const { field_name, value, ...componentProps } = component.props;
2038
2048
  const options = componentProps.options || [];
2039
2049
  const placeholder = componentProps.placeholder || "Seleccionar...";
@@ -2276,8 +2286,8 @@ const ChatConfigProvider = ({ value, children }) => /* @__PURE__ */ jsxRuntime.j
2276
2286
  const useChatConfig = () => React.useContext(ChatConfigContext);
2277
2287
 
2278
2288
  DatePicker.registerLocale("es", locale.es);
2279
- const MOBILE_BREAKPOINT$1 = 640;
2280
- const parseDate$2 = (dateString) => {
2289
+ const MOBILE_BREAKPOINT$2 = 640;
2290
+ const parseDate$3 = (dateString) => {
2281
2291
  if (!dateString) return null;
2282
2292
  try {
2283
2293
  if (/^\d{4}-\d{2}-\d{2}$/.test(dateString)) {
@@ -2290,14 +2300,14 @@ const parseDate$2 = (dateString) => {
2290
2300
  return null;
2291
2301
  }
2292
2302
  };
2293
- const formatDateToISO = (date) => {
2303
+ const formatDateToISO$1 = (date) => {
2294
2304
  if (!date) return "";
2295
2305
  const year = date.getFullYear();
2296
2306
  const month = (date.getMonth() + 1).toString().padStart(2, "0");
2297
2307
  const day = date.getDate().toString().padStart(2, "0");
2298
2308
  return `${year}-${month}-${day}`;
2299
2309
  };
2300
- const formatDateDisplay = (date, locale, timezone) => {
2310
+ const formatDateDisplay$1 = (date, locale, timezone) => {
2301
2311
  if (!date) return "";
2302
2312
  return date.toLocaleDateString(locale, {
2303
2313
  day: "2-digit",
@@ -2346,12 +2356,12 @@ const CustomHeader$1 = ({
2346
2356
  )
2347
2357
  ] });
2348
2358
  };
2349
- const useIsMobile$2 = () => {
2359
+ const useIsMobile$3 = () => {
2350
2360
  const [isMobile, setIsMobile] = React.useState(
2351
- typeof window !== "undefined" ? window.innerWidth < MOBILE_BREAKPOINT$1 : false
2361
+ typeof window !== "undefined" ? window.innerWidth < MOBILE_BREAKPOINT$2 : false
2352
2362
  );
2353
2363
  React.useEffect(() => {
2354
- const mq = window.matchMedia(`(max-width: ${MOBILE_BREAKPOINT$1 - 1}px)`);
2364
+ const mq = window.matchMedia(`(max-width: ${MOBILE_BREAKPOINT$2 - 1}px)`);
2355
2365
  const handler = (e) => setIsMobile(e.matches);
2356
2366
  mq.addEventListener("change", handler);
2357
2367
  return () => mq.removeEventListener("change", handler);
@@ -2367,15 +2377,15 @@ const DateInputWithConfirm = ({
2367
2377
  const [selectedDate, setSelectedDate] = React.useState(null);
2368
2378
  const [isOpen, setIsOpen] = React.useState(false);
2369
2379
  const triggerRef = React.useRef(null);
2370
- const isMobile = useIsMobile$2();
2380
+ const isMobile = useIsMobile$3();
2371
2381
  const { emitInteraction, isConfirmed } = useComponentInteraction({
2372
2382
  eventBus,
2373
2383
  fieldName: component.props.field_name,
2374
2384
  componentType: component.type,
2375
2385
  assistantMessageId
2376
2386
  });
2377
- const minDate = component.props.min_date ? parseDate$2(component.props.min_date) : void 0;
2378
- const maxDate = component.props.max_date ? parseDate$2(component.props.max_date) : void 0;
2387
+ const minDate = component.props.min_date ? parseDate$3(component.props.min_date) : void 0;
2388
+ const maxDate = component.props.max_date ? parseDate$3(component.props.max_date) : void 0;
2379
2389
  React.useEffect(() => {
2380
2390
  if (!isOpen || isMobile) return;
2381
2391
  const handleKey = (e) => {
@@ -2392,12 +2402,12 @@ const DateInputWithConfirm = ({
2392
2402
  };
2393
2403
  const handleConfirm = React.useCallback(() => {
2394
2404
  if (!selectedDate) return;
2395
- const isoValue = formatDateToISO(selectedDate);
2396
- const displayValue2 = formatDateDisplay(selectedDate, locale, timezone);
2405
+ const isoValue = formatDateToISO$1(selectedDate);
2406
+ const displayValue2 = formatDateDisplay$1(selectedDate, locale, timezone);
2397
2407
  emitInteraction(isoValue, displayValue2);
2398
2408
  setIsOpen(false);
2399
2409
  }, [selectedDate, emitInteraction, locale, timezone]);
2400
- const displayValue = formatDateDisplay(selectedDate, locale, timezone);
2410
+ const displayValue = formatDateDisplay$1(selectedDate, locale, timezone);
2401
2411
  const placeholder = component.props.placeholder || "Selecciona una fecha";
2402
2412
  const label = component.props.label || "Selecciona una fecha";
2403
2413
  const calendarContent = /* @__PURE__ */ jsxRuntime.jsx(
@@ -2536,13 +2546,14 @@ const ConfirmButton = ({
2536
2546
  };
2537
2547
 
2538
2548
  const CardDisplay = ({ component }) => {
2539
- const { title, rows, variant = "default" } = component.props;
2549
+ const { title, rows, content, variant = "default" } = component.props;
2540
2550
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `px-chat-card px-chat-card--${variant}`, children: [
2541
2551
  /* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-chat-card__title", children: title }),
2542
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-chat-card__rows", children: rows.map((row, i) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "px-chat-card__row", children: [
2552
+ content && !rows?.length && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-chat-card__content", children: content }),
2553
+ rows?.length ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-chat-card__rows", children: rows.map((row, i) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "px-chat-card__row", children: [
2543
2554
  /* @__PURE__ */ jsxRuntime.jsx("span", { className: "px-chat-card__row-label", children: row.label }),
2544
2555
  /* @__PURE__ */ jsxRuntime.jsx("span", { className: "px-chat-card__row-value", children: row.value })
2545
- ] }, i)) })
2556
+ ] }, i)) }) : null
2546
2557
  ] });
2547
2558
  };
2548
2559
 
@@ -2693,13 +2704,13 @@ const ScrollableColumn$1 = ({
2693
2704
  ] });
2694
2705
  };
2695
2706
 
2696
- const MOBILE_BREAKPOINT = 640;
2697
- const useIsMobile$1 = () => {
2707
+ const MOBILE_BREAKPOINT$1 = 640;
2708
+ const useIsMobile$2 = () => {
2698
2709
  const [isMobile, setIsMobile] = React.useState(
2699
- typeof window !== "undefined" ? window.innerWidth < MOBILE_BREAKPOINT : false
2710
+ typeof window !== "undefined" ? window.innerWidth < MOBILE_BREAKPOINT$1 : false
2700
2711
  );
2701
2712
  React.useEffect(() => {
2702
- const mq = window.matchMedia(`(max-width: ${MOBILE_BREAKPOINT - 1}px)`);
2713
+ const mq = window.matchMedia(`(max-width: ${MOBILE_BREAKPOINT$1 - 1}px)`);
2703
2714
  const handler = (e) => setIsMobile(e.matches);
2704
2715
  mq.addEventListener("change", handler);
2705
2716
  return () => mq.removeEventListener("change", handler);
@@ -2752,7 +2763,7 @@ const TimeInputWithConfirm = ({
2752
2763
  assistantMessageId = ""
2753
2764
  }) => {
2754
2765
  const { timezone, locale } = useChatConfig();
2755
- const isMobile = useIsMobile$1();
2766
+ const isMobile = useIsMobile$2();
2756
2767
  const [isOpen, setIsOpen] = React.useState(false);
2757
2768
  const [confirmedTime, setConfirmedTime] = React.useState("");
2758
2769
  const triggerRef = React.useRef(null);
@@ -2993,130 +3004,1926 @@ const TimeInputWithConfirm = ({
2993
3004
  ] });
2994
3005
  };
2995
3006
 
2996
- const COMPONENT_MAP = {
2997
- select: SelectWithConfirm,
2998
- select_multiple: SelectMultipleWithConfirm,
2999
- confirm: ConfirmButton,
3000
- date_input: DateInputWithConfirm,
3001
- time_input: TimeInputWithConfirm,
3002
- input: InputWithConfirm,
3003
- card: CardDisplay,
3004
- badge: BadgeDisplay
3005
- };
3006
- function renderComponent(props) {
3007
- const { component } = props;
3008
- if (component.answered && !DISPLAY_COMPONENTS.has(component.type)) {
3007
+ DatePicker.registerLocale("es", locale.es);
3008
+ const parseDate$2 = (dateString) => {
3009
+ if (!dateString) return null;
3010
+ try {
3011
+ if (/^\d{4}-\d{2}-\d{2}$/.test(dateString)) {
3012
+ const [year, month, day] = dateString.split("-").map(Number);
3013
+ return new Date(year, month - 1, day);
3014
+ }
3015
+ const parsed = new Date(dateString);
3016
+ return isNaN(parsed.getTime()) ? null : parsed;
3017
+ } catch {
3009
3018
  return null;
3010
3019
  }
3011
- const Component = COMPONENT_MAP[component.type];
3012
- if (!Component) return null;
3013
- return /* @__PURE__ */ jsxRuntime.jsx(Component, { ...props });
3014
- }
3015
-
3016
- const StructuredContent = ({
3017
- content,
3018
- eventBus,
3019
- assistantMessageId,
3020
- className = ""
3020
+ };
3021
+ const formatDateToISO = (date) => {
3022
+ if (!date) return "";
3023
+ const year = date.getFullYear();
3024
+ const month = (date.getMonth() + 1).toString().padStart(2, "0");
3025
+ const day = date.getDate().toString().padStart(2, "0");
3026
+ return `${year}-${month}-${day}`;
3027
+ };
3028
+ const formatDateDisplay = (date) => {
3029
+ if (!date) return "";
3030
+ return date.toLocaleDateString("es", { day: "2-digit", month: "long", year: "numeric" });
3031
+ };
3032
+ const DynamicField = ({
3033
+ field,
3034
+ value,
3035
+ error,
3036
+ disabled,
3037
+ fieldState,
3038
+ onChange,
3039
+ drawerPlacement = "bottom"
3021
3040
  }) => {
3022
- const structured = parseContent(content);
3023
- const markdownContent = structured ? structured.message : content;
3024
- const rawComponent = structured?.component || null;
3025
- const components = rawComponent ? Array.isArray(rawComponent) ? rawComponent : [rawComponent] : [];
3026
- const hasVisibleComponents = components.some((comp) => !comp.answered || DISPLAY_COMPONENTS.has(comp.type));
3027
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `${COMPONENT_PREFIX$1}structured-content ${className}`, children: [
3028
- markdownContent && /* @__PURE__ */ jsxRuntime.jsx("div", { className: `${COMPONENT_PREFIX$1}assistant-message__markdown${hasVisibleComponents ? ` ${COMPONENT_PREFIX$1}assistant-message__markdown--with-component` : ``}`, children: /* @__PURE__ */ jsxRuntime.jsx(
3029
- ReactMarkdown,
3041
+ const { loading, options } = fieldState;
3042
+ if (field.type === "hidden") return null;
3043
+ const renderField = () => {
3044
+ switch (field.type) {
3045
+ case "select":
3046
+ return /* @__PURE__ */ jsxRuntime.jsx(
3047
+ SelectField$1,
3048
+ {
3049
+ field,
3050
+ value,
3051
+ disabled,
3052
+ loading,
3053
+ options,
3054
+ onChange,
3055
+ drawerPlacement
3056
+ }
3057
+ );
3058
+ case "select_multiple":
3059
+ return /* @__PURE__ */ jsxRuntime.jsx(
3060
+ SelectMultipleField,
3061
+ {
3062
+ field,
3063
+ value,
3064
+ disabled,
3065
+ loading,
3066
+ options,
3067
+ onChange,
3068
+ drawerPlacement
3069
+ }
3070
+ );
3071
+ case "date":
3072
+ return /* @__PURE__ */ jsxRuntime.jsx(
3073
+ DateField,
3074
+ {
3075
+ field,
3076
+ value,
3077
+ disabled,
3078
+ onChange,
3079
+ drawerPlacement
3080
+ }
3081
+ );
3082
+ default:
3083
+ return /* @__PURE__ */ jsxRuntime.jsx(
3084
+ "input",
3085
+ {
3086
+ type: field.type === "email" ? "email" : field.type === "number" ? "number" : "text",
3087
+ className: "px-chat-rf__input",
3088
+ placeholder: field.placeholder,
3089
+ value: value || "",
3090
+ disabled,
3091
+ onChange: (e) => onChange(e.target.value, e.target.value)
3092
+ }
3093
+ );
3094
+ }
3095
+ };
3096
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `px-chat-rf__field ${error ? "px-chat-rf__field--error" : ""} ${disabled ? "px-chat-rf__field--disabled" : ""}`, children: [
3097
+ /* @__PURE__ */ jsxRuntime.jsx("label", { className: "px-chat-rf__field-label", children: field.label }),
3098
+ renderField(),
3099
+ error && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "px-chat-rf__field-error", children: error })
3100
+ ] });
3101
+ };
3102
+ const SelectField$1 = ({ field, value, disabled, loading, options, onChange, drawerPlacement }) => {
3103
+ const [isDrawerOpen, setIsDrawerOpen] = React.useState(false);
3104
+ const [searchValue, setSearchValue] = React.useState("");
3105
+ const searchInputRef = React.useRef(null);
3106
+ const selectedLabel = options.find((o) => o.value === value)?.label || "";
3107
+ const placeholder = loading ? "Cargando..." : field.placeholder || "Seleccionar...";
3108
+ const filteredOptions = searchValue ? options.filter((opt) => opt.label.toLowerCase().includes(searchValue.toLowerCase())) : options;
3109
+ React.useEffect(() => {
3110
+ if (isDrawerOpen && searchInputRef.current) {
3111
+ setTimeout(() => searchInputRef.current?.focus(), 350);
3112
+ }
3113
+ }, [isDrawerOpen]);
3114
+ const handleSelect = (opt) => {
3115
+ const { value: v, label, ...extra } = opt;
3116
+ onChange(v, label, Object.keys(extra).length > 0 ? extra : void 0);
3117
+ };
3118
+ return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
3119
+ /* @__PURE__ */ jsxRuntime.jsxs(
3120
+ "div",
3030
3121
  {
3031
- components: {
3032
- a: ({ href, children }) => /* @__PURE__ */ jsxRuntime.jsx(
3033
- Link,
3034
- {
3035
- href: href || "#",
3036
- variant: "primary",
3037
- size: "medium",
3038
- weight: "bold",
3039
- underline: false,
3040
- children
3041
- }
3042
- )
3122
+ className: `px-chat-select-with-confirm__trigger ${isDrawerOpen ? "px-chat-select-with-confirm__trigger--open" : ""}`,
3123
+ onClick: () => !disabled && !loading && setIsDrawerOpen(true),
3124
+ role: "button",
3125
+ tabIndex: disabled ? -1 : 0,
3126
+ onKeyDown: (e) => {
3127
+ if (!disabled && (e.key === "Enter" || e.key === " ")) setIsDrawerOpen(true);
3043
3128
  },
3044
- children: markdownContent
3129
+ children: [
3130
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: `px-chat-select-with-confirm__trigger-text ${!value ? "px-chat-select-with-confirm__trigger-text--placeholder" : ""}`, children: value ? selectedLabel : placeholder }),
3131
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "px-chat-select-with-confirm__chevron", children: loading ? /* @__PURE__ */ jsxRuntime.jsx(Loader$1, { size: "small" }) : /* @__PURE__ */ jsxRuntime.jsx(Icon$1, { type: ICON_TYPES.CHEVRON_DOWN, size: "small" }) })
3132
+ ]
3045
3133
  }
3046
- ) }),
3047
- components.length > 0 && /* @__PURE__ */ jsxRuntime.jsx("div", { className: `${COMPONENT_PREFIX$1}structured-content__component`, children: components.map((comp, index) => /* @__PURE__ */ jsxRuntime.jsx(React.Fragment, { children: renderComponent({ component: comp, eventBus, assistantMessageId }) }, `${comp.type}-${index}`)) })
3134
+ ),
3135
+ /* @__PURE__ */ jsxRuntime.jsx(
3136
+ Drawer$1,
3137
+ {
3138
+ isOpen: isDrawerOpen,
3139
+ onClose: () => {
3140
+ setIsDrawerOpen(false);
3141
+ setSearchValue("");
3142
+ },
3143
+ title: field.label,
3144
+ placement: drawerPlacement,
3145
+ children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "px-chat-select-drawer px-chat-rf-select-drawer", children: [
3146
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "px-chat-select-drawer__search", children: [
3147
+ /* @__PURE__ */ jsxRuntime.jsx(Icon$1, { type: ICON_TYPES.SEARCH, size: "small" }),
3148
+ /* @__PURE__ */ jsxRuntime.jsx(
3149
+ "input",
3150
+ {
3151
+ ref: searchInputRef,
3152
+ type: "text",
3153
+ className: "px-chat-select-drawer__search-input",
3154
+ value: searchValue,
3155
+ onChange: (e) => setSearchValue(e.target.value),
3156
+ placeholder: "Buscar..."
3157
+ }
3158
+ ),
3159
+ searchValue && /* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", className: "px-chat-select-drawer__search-clear", onClick: () => setSearchValue(""), children: /* @__PURE__ */ jsxRuntime.jsx(Icon$1, { type: ICON_TYPES.CLOSE, size: "small" }) })
3160
+ ] }),
3161
+ /* @__PURE__ */ jsxRuntime.jsx("ul", { className: "px-chat-select-drawer__options", role: "listbox", children: filteredOptions.length === 0 ? /* @__PURE__ */ jsxRuntime.jsx("li", { className: "px-chat-select-drawer__empty", children: "No hay opciones disponibles" }) : filteredOptions.map((opt) => {
3162
+ const isSelected = opt.value === value;
3163
+ return /* @__PURE__ */ jsxRuntime.jsxs(
3164
+ "li",
3165
+ {
3166
+ className: `px-chat-select-drawer__option ${isSelected ? "px-chat-select-drawer__option--selected" : ""}`,
3167
+ onClick: () => {
3168
+ handleSelect(opt);
3169
+ setIsDrawerOpen(false);
3170
+ setSearchValue("");
3171
+ },
3172
+ role: "option",
3173
+ "aria-selected": isSelected,
3174
+ children: [
3175
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "px-chat-select-drawer__option-label", children: opt.label }),
3176
+ isSelected && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "px-chat-select-drawer__option-check", children: /* @__PURE__ */ jsxRuntime.jsx(Icon$1, { type: ICON_TYPES.CHECK, size: "small" }) })
3177
+ ]
3178
+ },
3179
+ opt.value
3180
+ );
3181
+ }) })
3182
+ ] })
3183
+ }
3184
+ )
3048
3185
  ] });
3049
3186
  };
3050
-
3051
- const getAttachmentType = (file) => {
3052
- const mimeType = file.type.toLowerCase();
3053
- if (mimeType.startsWith(MIME_PREFIXES.AUDIO)) {
3054
- return AttachmentType.AUDIO;
3055
- }
3056
- if (mimeType.startsWith(MIME_PREFIXES.VIDEO)) {
3057
- return AttachmentType.VIDEO;
3058
- }
3059
- if (mimeType.startsWith(MIME_PREFIXES.IMAGE)) {
3060
- return AttachmentType.IMAGE;
3061
- }
3062
- if (mimeType === MIME_TYPES.PDF) {
3063
- return AttachmentType.PDF;
3064
- }
3065
- if (mimeType.includes(MIME_KEYWORDS.DOCUMENT) || mimeType.includes(MIME_KEYWORDS.WORD) || mimeType.includes(MIME_KEYWORDS.EXCEL) || mimeType.includes(MIME_KEYWORDS.POWERPOINT) || mimeType.startsWith(MIME_PREFIXES.TEXT)) {
3066
- return AttachmentType.DOCUMENT;
3067
- }
3068
- return AttachmentType.OTHER;
3069
- };
3070
- const filterFilesByType = (files, type) => {
3071
- const types = Array.isArray(type) ? type : [type];
3072
- return files.filter((file) => {
3073
- const fileType = getAttachmentType(file);
3074
- return types.includes(fileType);
3075
- });
3076
- };
3077
- const getFileUrl = (file) => {
3078
- if (file.url) {
3079
- return file.url;
3080
- }
3081
- return URL.createObjectURL(file);
3082
- };
3083
- const getAudioFiles = (files) => {
3084
- return filterFilesByType(files, [AttachmentType.AUDIO]);
3085
- };
3086
- const getNonAudioFiles = (files) => {
3087
- return filterFilesByType(files, [
3088
- AttachmentType.IMAGE,
3089
- AttachmentType.PDF,
3090
- AttachmentType.DOCUMENT,
3091
- AttachmentType.OTHER
3092
- ]);
3093
- };
3094
-
3095
- function createStore(initial) {
3096
- const state = { ...initial };
3097
- const listeners = {};
3098
- const notify = (key, value) => {
3099
- const keyStr = String(key);
3100
- listeners[keyStr]?.forEach((l) => l(value));
3101
- };
3102
- const subscribe = (key, listener) => {
3103
- const keyStr = String(key);
3104
- if (!listeners[keyStr]) listeners[keyStr] = /* @__PURE__ */ new Set();
3105
- listeners[keyStr].add(listener);
3106
- listener(state[key]);
3107
- return () => {
3108
- listeners[keyStr].delete(listener);
3109
- };
3110
- };
3111
- const set = (key, value) => {
3112
- state[key] = value;
3113
- notify(key, value);
3187
+ const SelectMultipleField = ({ field, value, disabled, loading, options, onChange, drawerPlacement }) => {
3188
+ const [isDrawerOpen, setIsDrawerOpen] = React.useState(false);
3189
+ const [searchValue, setSearchValue] = React.useState("");
3190
+ const searchInputRef = React.useRef(null);
3191
+ const selected = value || [];
3192
+ const placeholder = loading ? "Cargando..." : field.placeholder || "Seleccionar...";
3193
+ const filteredOptions = searchValue ? options.filter((opt) => opt.label.toLowerCase().includes(searchValue.toLowerCase())) : options;
3194
+ React.useEffect(() => {
3195
+ if (isDrawerOpen && searchInputRef.current) {
3196
+ setTimeout(() => searchInputRef.current?.focus(), 350);
3197
+ }
3198
+ }, [isDrawerOpen]);
3199
+ const toggleOption = (optValue) => {
3200
+ const isChecked = selected.includes(optValue);
3201
+ const next = isChecked ? selected.filter((v) => v !== optValue) : [...selected, optValue];
3202
+ const labels = next.map((v) => options.find((o) => o.value === v)?.label || v).join(", ");
3203
+ onChange(next, labels);
3114
3204
  };
3115
- const get = (key) => state[key];
3116
- return { set, get, subscribe };
3117
- }
3118
-
3119
- function deepMerge(target, source) {
3205
+ return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
3206
+ /* @__PURE__ */ jsxRuntime.jsxs(
3207
+ "div",
3208
+ {
3209
+ className: `px-chat-select-with-confirm__trigger ${isDrawerOpen ? "px-chat-select-with-confirm__trigger--open" : ""}`,
3210
+ onClick: () => !disabled && !loading && setIsDrawerOpen(true),
3211
+ role: "button",
3212
+ tabIndex: disabled ? -1 : 0,
3213
+ onKeyDown: (e) => {
3214
+ if (!disabled && (e.key === "Enter" || e.key === " ")) setIsDrawerOpen(true);
3215
+ },
3216
+ children: [
3217
+ selected.length === 0 ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "px-chat-select-with-confirm__trigger-text px-chat-select-with-confirm__trigger-text--placeholder", children: placeholder }) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-chat-select-with-confirm__trigger-tags", children: selected.map((v) => {
3218
+ const opt = options.find((o) => o.value === v);
3219
+ return /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "px-chat-select-with-confirm__trigger-tag", children: [
3220
+ opt?.label || v,
3221
+ /* @__PURE__ */ jsxRuntime.jsx(
3222
+ "button",
3223
+ {
3224
+ type: "button",
3225
+ className: "px-chat-select-with-confirm__trigger-tag-remove",
3226
+ onClick: (e) => {
3227
+ e.stopPropagation();
3228
+ toggleOption(v);
3229
+ },
3230
+ "aria-label": `Quitar ${opt?.label || v}`,
3231
+ children: /* @__PURE__ */ jsxRuntime.jsx(Icon$1, { type: ICON_TYPES.CLOSE, size: "small" })
3232
+ }
3233
+ )
3234
+ ] }, v);
3235
+ }) }),
3236
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "px-chat-select-with-confirm__chevron", children: loading ? /* @__PURE__ */ jsxRuntime.jsx(Loader$1, { size: "small" }) : /* @__PURE__ */ jsxRuntime.jsx(Icon$1, { type: ICON_TYPES.CHEVRON_DOWN, size: "small" }) })
3237
+ ]
3238
+ }
3239
+ ),
3240
+ /* @__PURE__ */ jsxRuntime.jsx(
3241
+ Drawer$1,
3242
+ {
3243
+ isOpen: isDrawerOpen,
3244
+ onClose: () => {
3245
+ setIsDrawerOpen(false);
3246
+ setSearchValue("");
3247
+ },
3248
+ title: field.label,
3249
+ placement: drawerPlacement,
3250
+ footer: /* @__PURE__ */ jsxRuntime.jsxs(
3251
+ "button",
3252
+ {
3253
+ type: "button",
3254
+ className: "px-chat-rf__btn px-chat-rf__btn--primary",
3255
+ style: { width: "100%" },
3256
+ onClick: () => {
3257
+ setIsDrawerOpen(false);
3258
+ setSearchValue("");
3259
+ },
3260
+ children: [
3261
+ "Listo",
3262
+ selected.length > 0 ? ` (${selected.length})` : ""
3263
+ ]
3264
+ }
3265
+ ),
3266
+ children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "px-chat-select-drawer px-chat-rf-select-drawer", children: [
3267
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "px-chat-select-drawer__search", children: [
3268
+ /* @__PURE__ */ jsxRuntime.jsx(Icon$1, { type: ICON_TYPES.SEARCH, size: "small" }),
3269
+ /* @__PURE__ */ jsxRuntime.jsx(
3270
+ "input",
3271
+ {
3272
+ ref: searchInputRef,
3273
+ type: "text",
3274
+ className: "px-chat-select-drawer__search-input",
3275
+ value: searchValue,
3276
+ onChange: (e) => setSearchValue(e.target.value),
3277
+ placeholder: "Buscar..."
3278
+ }
3279
+ ),
3280
+ searchValue && /* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", className: "px-chat-select-drawer__search-clear", onClick: () => setSearchValue(""), children: /* @__PURE__ */ jsxRuntime.jsx(Icon$1, { type: ICON_TYPES.CLOSE, size: "small" }) })
3281
+ ] }),
3282
+ /* @__PURE__ */ jsxRuntime.jsx("ul", { className: "px-chat-select-drawer__options", role: "listbox", "aria-multiselectable": "true", children: filteredOptions.length === 0 ? /* @__PURE__ */ jsxRuntime.jsx("li", { className: "px-chat-select-drawer__empty", children: "No hay opciones disponibles" }) : filteredOptions.map((opt) => {
3283
+ const isChecked = selected.includes(opt.value);
3284
+ return /* @__PURE__ */ jsxRuntime.jsxs(
3285
+ "li",
3286
+ {
3287
+ className: `px-chat-select-drawer__option ${isChecked ? "px-chat-select-drawer__option--selected" : ""}`,
3288
+ onClick: () => toggleOption(opt.value),
3289
+ role: "option",
3290
+ "aria-selected": isChecked,
3291
+ children: [
3292
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: `px-chat-select-drawer__checkbox ${isChecked ? "px-chat-select-drawer__checkbox--checked" : ""}`, children: isChecked && /* @__PURE__ */ jsxRuntime.jsx(Icon$1, { type: ICON_TYPES.CHECK, size: "small" }) }),
3293
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "px-chat-select-drawer__option-label", children: opt.label })
3294
+ ]
3295
+ },
3296
+ opt.value
3297
+ );
3298
+ }) })
3299
+ ] })
3300
+ }
3301
+ )
3302
+ ] });
3303
+ };
3304
+ const DateField = ({ field, value, disabled, onChange, drawerPlacement }) => {
3305
+ const [isOpen, setIsOpen] = React.useState(false);
3306
+ const selectedDate = value ? parseDate$2(value) : null;
3307
+ const displayValue = formatDateDisplay(selectedDate);
3308
+ const placeholder = field.placeholder || "Selecciona una fecha";
3309
+ const minDateRaw = field.validation?.min_date ? String(field.validation.min_date.value ?? field.validation.min_date) : field.min_date ? String(field.min_date) : void 0;
3310
+ const maxDateRaw = field.validation?.max_date ? String(field.validation.max_date.value ?? field.validation.max_date) : field.max_date ? String(field.max_date) : void 0;
3311
+ const minDate = minDateRaw ? parseDate$2(minDateRaw) : void 0;
3312
+ const maxDate = maxDateRaw ? parseDate$2(maxDateRaw) : void 0;
3313
+ const handleDateChange = (date) => {
3314
+ if (!date) return;
3315
+ const isoValue = formatDateToISO(date);
3316
+ const display = formatDateDisplay(date);
3317
+ onChange(isoValue, display);
3318
+ };
3319
+ const calendarContent = /* @__PURE__ */ jsxRuntime.jsx(
3320
+ DatePicker,
3321
+ {
3322
+ selected: selectedDate,
3323
+ onChange: handleDateChange,
3324
+ inline: true,
3325
+ locale: "es",
3326
+ minDate: minDate || void 0,
3327
+ maxDate: maxDate || void 0,
3328
+ renderCustomHeader: ({ date, decreaseMonth, increaseMonth, prevMonthButtonDisabled, nextMonthButtonDisabled }) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "px-chat-datepicker__header", children: [
3329
+ /* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", className: "px-chat-datepicker__nav-btn", onClick: decreaseMonth, disabled: prevMonthButtonDisabled, children: "\u2039" }),
3330
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "px-chat-datepicker__month-year", children: date.toLocaleDateString("es", { month: "long", year: "numeric" }) }),
3331
+ /* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", className: "px-chat-datepicker__nav-btn", onClick: increaseMonth, disabled: nextMonthButtonDisabled, children: "\u203A" })
3332
+ ] })
3333
+ }
3334
+ );
3335
+ const calendarIcon = /* @__PURE__ */ jsxRuntime.jsx("svg", { width: "16", height: "16", viewBox: "0 0 16 16", fill: "none", xmlns: "http://www.w3.org/2000/svg", children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M5 1V3M11 1V3M1 6H15M2 2.5H14C14.5523 2.5 15 2.94772 15 3.5V14C15 14.5523 14.5523 15 14 15H2C1.44772 15 1 14.5523 1 14V3.5C1 2.94772 1.44772 2.5 2 2.5Z", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round" }) });
3336
+ return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
3337
+ /* @__PURE__ */ jsxRuntime.jsxs(
3338
+ "div",
3339
+ {
3340
+ className: `px-chat-rf__date-trigger ${isOpen ? "px-chat-rf__date-trigger--open" : ""}`,
3341
+ onClick: () => !disabled && setIsOpen(!isOpen),
3342
+ role: "button",
3343
+ tabIndex: disabled ? -1 : 0,
3344
+ onKeyDown: (e) => {
3345
+ if (!disabled && (e.key === "Enter" || e.key === " ")) setIsOpen(!isOpen);
3346
+ },
3347
+ children: [
3348
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: `px-chat-rf__date-trigger-text ${!selectedDate ? "px-chat-rf__date-trigger-text--placeholder" : ""}`, children: selectedDate ? displayValue : placeholder }),
3349
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "px-chat-rf__date-trigger-icon", children: calendarIcon })
3350
+ ]
3351
+ }
3352
+ ),
3353
+ /* @__PURE__ */ jsxRuntime.jsxs(
3354
+ Drawer$1,
3355
+ {
3356
+ isOpen,
3357
+ onClose: () => setIsOpen(false),
3358
+ title: field.label,
3359
+ placement: drawerPlacement,
3360
+ footer: /* @__PURE__ */ jsxRuntime.jsx(
3361
+ "button",
3362
+ {
3363
+ type: "button",
3364
+ className: "px-chat-rf__btn px-chat-rf__btn--primary",
3365
+ style: { width: "100%" },
3366
+ disabled: !selectedDate,
3367
+ onClick: () => setIsOpen(false),
3368
+ children: "Confirmar"
3369
+ }
3370
+ ),
3371
+ children: [
3372
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-chat-datepicker px-chat-datepicker--mobile", children: calendarContent }),
3373
+ selectedDate && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-chat-datepicker__selected-date", children: displayValue })
3374
+ ]
3375
+ }
3376
+ )
3377
+ ] });
3378
+ };
3379
+
3380
+ const checkIcon = /* @__PURE__ */ jsxRuntime.jsx("svg", { width: "12", height: "12", viewBox: "0 0 12 12", fill: "none", xmlns: "http://www.w3.org/2000/svg", children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M2.5 6L5 8.5L9.5 3.5", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round" }) });
3381
+ const calendarIcon = /* @__PURE__ */ jsxRuntime.jsxs("svg", { width: "16", height: "16", viewBox: "0 0 16 16", fill: "none", xmlns: "http://www.w3.org/2000/svg", children: [
3382
+ /* @__PURE__ */ jsxRuntime.jsx("rect", { x: "2", y: "3", width: "12", height: "11", rx: "1.5", stroke: "currentColor", strokeWidth: "1.2" }),
3383
+ /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M2 6.5H14", stroke: "currentColor", strokeWidth: "1.2" }),
3384
+ /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M5.5 1.5V4", stroke: "currentColor", strokeWidth: "1.2", strokeLinecap: "round" }),
3385
+ /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M10.5 1.5V4", stroke: "currentColor", strokeWidth: "1.2", strokeLinecap: "round" })
3386
+ ] });
3387
+ const formIcon = /* @__PURE__ */ jsxRuntime.jsxs("svg", { width: "16", height: "16", viewBox: "0 0 16 16", fill: "none", xmlns: "http://www.w3.org/2000/svg", children: [
3388
+ /* @__PURE__ */ jsxRuntime.jsx("rect", { x: "2", y: "1.5", width: "12", height: "13", rx: "1.5", stroke: "currentColor", strokeWidth: "1.2" }),
3389
+ /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M5 5.5H11", stroke: "currentColor", strokeWidth: "1.2", strokeLinecap: "round" }),
3390
+ /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M5 8.5H11", stroke: "currentColor", strokeWidth: "1.2", strokeLinecap: "round" }),
3391
+ /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M5 11.5H8.5", stroke: "currentColor", strokeWidth: "1.2", strokeLinecap: "round" })
3392
+ ] });
3393
+ const chevronDown = /* @__PURE__ */ jsxRuntime.jsx("svg", { width: "12", height: "12", viewBox: "0 0 12 12", fill: "none", xmlns: "http://www.w3.org/2000/svg", children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M3 4.5L6 7.5L9 4.5", stroke: "currentColor", strokeWidth: "1.2", strokeLinecap: "round", strokeLinejoin: "round" }) });
3394
+ const chevronRight = /* @__PURE__ */ jsxRuntime.jsx("svg", { width: "12", height: "12", viewBox: "0 0 12 12", fill: "none", xmlns: "http://www.w3.org/2000/svg", children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M4.5 3L7.5 6L4.5 9", stroke: "currentColor", strokeWidth: "1.2", strokeLinecap: "round", strokeLinejoin: "round" }) });
3395
+ const ReactiveFormView = ({ title, trigger, steps, fields, submit, summary, form, drawerPlacement = "bottom" }) => {
3396
+ const {
3397
+ formStatus,
3398
+ setFormStatus,
3399
+ currentStep,
3400
+ setCurrentStep,
3401
+ values,
3402
+ errors,
3403
+ touched,
3404
+ fieldStates,
3405
+ totalSteps,
3406
+ handleTriggerClick,
3407
+ handleFieldChange,
3408
+ handleNext,
3409
+ handleBack,
3410
+ handleSubmit,
3411
+ getDependencies,
3412
+ allDepsResolved,
3413
+ resolveSummaryRows
3414
+ } = form;
3415
+ const renderTrigger = () => {
3416
+ const isOpen = formStatus === "open";
3417
+ const isFinished = formStatus === "completed" || formStatus === "warning" || formStatus === "error";
3418
+ const statusClass = isFinished ? `px-chat-rf__trigger--${formStatus}` : "";
3419
+ return /* @__PURE__ */ jsxRuntime.jsxs(
3420
+ "button",
3421
+ {
3422
+ type: "button",
3423
+ className: `px-chat-rf__trigger ${isOpen ? "px-chat-rf__trigger--open" : ""} ${statusClass}`,
3424
+ onClick: handleTriggerClick,
3425
+ children: [
3426
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "px-chat-rf__trigger-icon", children: isFinished ? checkIcon : trigger.icon === "calendar" ? calendarIcon : formIcon }),
3427
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "px-chat-rf__trigger-label", children: isFinished ? form.submitMessage : trigger.label }),
3428
+ !isFinished && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "px-chat-rf__trigger-arrow", children: isOpen ? chevronDown : chevronRight })
3429
+ ]
3430
+ }
3431
+ );
3432
+ };
3433
+ const renderStepIndicator = () => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "px-chat-rf__steps-indicator", children: [
3434
+ steps.map((step, i) => {
3435
+ const isCompleted = i < currentStep;
3436
+ const isActive = i === currentStep;
3437
+ return /* @__PURE__ */ jsxRuntime.jsxs(React.Fragment, { children: [
3438
+ i > 0 && /* @__PURE__ */ jsxRuntime.jsx("div", { className: `px-chat-rf__step-line ${isCompleted ? "px-chat-rf__step-line--done" : ""}` }),
3439
+ /* @__PURE__ */ jsxRuntime.jsx(
3440
+ "button",
3441
+ {
3442
+ type: "button",
3443
+ className: `px-chat-rf__step-dot ${isActive ? "px-chat-rf__step-dot--active" : ""} ${isCompleted ? "px-chat-rf__step-dot--done" : ""}`,
3444
+ onClick: () => isCompleted && setCurrentStep(i),
3445
+ disabled: !isCompleted && !isActive,
3446
+ title: step.title,
3447
+ children: isCompleted ? checkIcon : i + 1
3448
+ }
3449
+ )
3450
+ ] }, i);
3451
+ }),
3452
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: `px-chat-rf__step-line ${currentStep >= steps.length ? "px-chat-rf__step-line--done" : ""}` }),
3453
+ /* @__PURE__ */ jsxRuntime.jsx(
3454
+ "button",
3455
+ {
3456
+ type: "button",
3457
+ className: `px-chat-rf__step-dot ${currentStep >= steps.length ? "px-chat-rf__step-dot--active" : ""}`,
3458
+ disabled: currentStep < steps.length,
3459
+ children: currentStep >= steps.length ? checkIcon : totalSteps
3460
+ }
3461
+ )
3462
+ ] });
3463
+ const renderNavButtons = () => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "px-chat-rf__nav", children: [
3464
+ currentStep > 0 && /* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", className: "px-chat-rf__btn px-chat-rf__btn--secondary", onClick: handleBack, children: "Atras" }),
3465
+ /* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", className: "px-chat-rf__btn px-chat-rf__btn--primary", onClick: handleNext, children: "Siguiente" })
3466
+ ] });
3467
+ const renderSummaryActions = () => {
3468
+ const actions = summary.actions;
3469
+ if (!actions || actions.length === 0) {
3470
+ return /* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", className: "px-chat-rf__btn px-chat-rf__btn--primary px-chat-rf__btn--full", onClick: handleSubmit, children: submit.label });
3471
+ }
3472
+ const actionHandlers = {
3473
+ submit: handleSubmit,
3474
+ close: () => setFormStatus("closed"),
3475
+ back: handleBack
3476
+ };
3477
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-chat-rf__nav", children: actions.map((act, i) => /* @__PURE__ */ jsxRuntime.jsx(
3478
+ "button",
3479
+ {
3480
+ type: "button",
3481
+ className: `px-chat-rf__btn px-chat-rf__btn--${act.variant || "primary"}`,
3482
+ onClick: actionHandlers[act.action] || (() => {
3483
+ }),
3484
+ children: act.label
3485
+ },
3486
+ i
3487
+ )) });
3488
+ };
3489
+ const renderStepContent = () => {
3490
+ if (currentStep >= steps.length) {
3491
+ const resolvedRows = resolveSummaryRows(summary.rows);
3492
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-chat-rf__summary", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "px-chat-rf__summary-card", children: [
3493
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-chat-rf__summary-title", children: summary.title }),
3494
+ resolvedRows.map((row, i) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "px-chat-rf__summary-row", children: [
3495
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "px-chat-rf__summary-label", children: row.label }),
3496
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "px-chat-rf__summary-value", children: row.value })
3497
+ ] }, i))
3498
+ ] }) });
3499
+ }
3500
+ const step = steps[currentStep];
3501
+ const stepFields = step.fields.map((name) => fields.find((f) => f.name === name)).filter(Boolean);
3502
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "px-chat-rf__step-content", children: [
3503
+ currentStep > 0 && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-chat-rf__completed-steps", children: steps.slice(0, currentStep).map((prevStep, si) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "px-chat-rf__completed-step", children: [
3504
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "px-chat-rf__completed-step-header", children: [
3505
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "px-chat-rf__completed-step-title", children: prevStep.title }),
3506
+ /* @__PURE__ */ jsxRuntime.jsx(
3507
+ "button",
3508
+ {
3509
+ type: "button",
3510
+ className: "px-chat-rf__edit-btn",
3511
+ onClick: () => setCurrentStep(si),
3512
+ children: "editar"
3513
+ }
3514
+ )
3515
+ ] }),
3516
+ prevStep.fields.map((fname) => {
3517
+ const fs = fieldStates[fname];
3518
+ const fld = fields.find((f) => f.name === fname);
3519
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "px-chat-rf__completed-field", children: [
3520
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "px-chat-rf__completed-field-label", children: [
3521
+ fld?.label,
3522
+ ":"
3523
+ ] }),
3524
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "px-chat-rf__completed-field-value", children: fs?.label || String(values[fname] || "") })
3525
+ ] }, fname);
3526
+ })
3527
+ ] }, si)) }),
3528
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "px-chat-rf__active-step", children: [
3529
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-chat-rf__step-title", children: step.title }),
3530
+ stepFields.map((field) => {
3531
+ const deps = getDependencies(field);
3532
+ const isDisabled = !allDepsResolved(deps, values);
3533
+ return /* @__PURE__ */ jsxRuntime.jsx(
3534
+ DynamicField,
3535
+ {
3536
+ field,
3537
+ value: values[field.name],
3538
+ error: touched[field.name] ? errors[field.name] : void 0,
3539
+ disabled: isDisabled,
3540
+ fieldState: fieldStates[field.name],
3541
+ drawerPlacement,
3542
+ onChange: (val, label, extra) => handleFieldChange(field.name, val, label, extra)
3543
+ },
3544
+ field.name
3545
+ );
3546
+ })
3547
+ ] })
3548
+ ] });
3549
+ };
3550
+ const renderDrawerFooter = () => {
3551
+ if (currentStep >= steps.length) return renderSummaryActions();
3552
+ return renderNavButtons();
3553
+ };
3554
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "px-chat-rf", children: [
3555
+ renderTrigger(),
3556
+ /* @__PURE__ */ jsxRuntime.jsxs(
3557
+ Drawer$1,
3558
+ {
3559
+ isOpen: formStatus === "open",
3560
+ onClose: () => setFormStatus("closed"),
3561
+ title,
3562
+ placement: drawerPlacement,
3563
+ className: "px-chat-rf-drawer--mobile",
3564
+ footer: renderDrawerFooter(),
3565
+ children: [
3566
+ renderStepIndicator(),
3567
+ renderStepContent()
3568
+ ]
3569
+ }
3570
+ )
3571
+ ] });
3572
+ };
3573
+
3574
+ function buildYupSchema(fields) {
3575
+ const shape = {};
3576
+ for (const field of fields) {
3577
+ if (field.type === "hidden") continue;
3578
+ const v = field.validation;
3579
+ if (!v) continue;
3580
+ if (field.type === "select_multiple") {
3581
+ let s = yup__namespace.array().of(yup__namespace.string());
3582
+ if (v.required) s = s.min(1, v.required);
3583
+ if (v.min) s = s.min(Number(v.min.value), v.min.message);
3584
+ if (v.max) s = s.max(Number(v.max.value), v.max.message);
3585
+ shape[field.name] = s;
3586
+ } else if (field.type === "date") {
3587
+ let s = yup__namespace.string().typeError(`${field.label || field.name}: fecha inv\xE1lida`);
3588
+ if (v.required) s = s.required(v.required);
3589
+ const minDateRule = v.min_date ?? field.min_date;
3590
+ if (minDateRule) {
3591
+ const minVal = typeof minDateRule === "object" && minDateRule !== null ? String(minDateRule.value) : String(minDateRule);
3592
+ const minMsg = typeof minDateRule === "object" && minDateRule !== null ? minDateRule.message || `La fecha debe ser ${minVal} o posterior` : `La fecha debe ser ${minVal} o posterior`;
3593
+ s = s.test("min-date", minMsg, (val) => !val || val >= minVal);
3594
+ }
3595
+ const maxDateRule = v.max_date ?? field.max_date;
3596
+ if (maxDateRule) {
3597
+ const maxVal = typeof maxDateRule === "object" && maxDateRule !== null ? String(maxDateRule.value) : String(maxDateRule);
3598
+ const maxMsg = typeof maxDateRule === "object" && maxDateRule !== null ? maxDateRule.message || `La fecha debe ser ${maxVal} o anterior` : `La fecha debe ser ${maxVal} o anterior`;
3599
+ s = s.test("max-date", maxMsg, (val) => !val || val <= maxVal);
3600
+ }
3601
+ shape[field.name] = s;
3602
+ } else {
3603
+ let s = yup__namespace.string();
3604
+ if (v.required) s = s.required(v.required);
3605
+ if (v.pattern) s = s.matches(new RegExp(v.pattern.value), v.pattern.message);
3606
+ if (v.email) s = s.email(v.email);
3607
+ if (v.min) s = s.min(Number(v.min.value), v.min.message);
3608
+ if (v.max) s = s.max(Number(v.max.value), v.max.message);
3609
+ shape[field.name] = s;
3610
+ }
3611
+ }
3612
+ return yup__namespace.object().shape(shape);
3613
+ }
3614
+ function buildInitialValues(fields) {
3615
+ const values = {};
3616
+ for (const field of fields) {
3617
+ if (field.type === "hidden") {
3618
+ values[field.name] = field.default_value ?? "";
3619
+ } else {
3620
+ values[field.name] = field.type === "select_multiple" ? [] : "";
3621
+ }
3622
+ }
3623
+ return values;
3624
+ }
3625
+
3626
+ function resolveVariable(template, formValues, fieldStates) {
3627
+ if (!template.startsWith("$")) return template;
3628
+ const withoutDollar = template.slice(1);
3629
+ const dotIndex = withoutDollar.indexOf(".");
3630
+ const fieldName = dotIndex >= 0 ? withoutDollar.slice(0, dotIndex) : withoutDollar;
3631
+ const prop = dotIndex >= 0 ? withoutDollar.slice(dotIndex + 1) : null;
3632
+ const value = formValues[fieldName];
3633
+ const state = fieldStates[fieldName];
3634
+ if (!prop) return value;
3635
+ if (prop === "label" && state) {
3636
+ return state.label || "";
3637
+ }
3638
+ if (prop === "labels" && state && Array.isArray(value)) {
3639
+ return value.map((v) => {
3640
+ const opt = state.options.find((o) => o.value === v);
3641
+ return opt?.label || v;
3642
+ }).join(", ");
3643
+ }
3644
+ if (state) {
3645
+ const selectedOpt = state.options.find((o) => o.value === value);
3646
+ if (selectedOpt && prop in selectedOpt) {
3647
+ return selectedOpt[prop];
3648
+ }
3649
+ }
3650
+ return "";
3651
+ }
3652
+ function resolveBody(obj, formValues, fieldStates) {
3653
+ if (typeof obj === "string") return resolveVariable(obj, formValues, fieldStates);
3654
+ if (Array.isArray(obj)) return obj.map((item) => resolveBody(item, formValues, fieldStates));
3655
+ if (obj !== null && typeof obj === "object") {
3656
+ const resolved = {};
3657
+ for (const [key, value] of Object.entries(obj)) {
3658
+ resolved[key] = resolveBody(value, formValues, fieldStates);
3659
+ }
3660
+ return resolved;
3661
+ }
3662
+ return obj;
3663
+ }
3664
+ function resolveParams(params, formValues, fieldStates) {
3665
+ const resolved = {};
3666
+ for (const [key, template] of Object.entries(params)) {
3667
+ resolved[key] = resolveVariable(template, formValues, fieldStates);
3668
+ }
3669
+ return resolved;
3670
+ }
3671
+ function resolveSummaryRows(rows, formValues, fieldStates) {
3672
+ return rows.map((row) => ({
3673
+ label: row.label,
3674
+ value: String(resolveVariable(row.value, formValues, fieldStates) ?? "")
3675
+ }));
3676
+ }
3677
+
3678
+ const FETCH_TIMEOUT_MS = 12e4;
3679
+ function fetchViaEventBus(eventBus, service, url, method, body) {
3680
+ const requestId = crypto.randomUUID();
3681
+ return new Promise((resolve, reject) => {
3682
+ const timeoutId = setTimeout(() => {
3683
+ unsubscribe();
3684
+ reject(new Error(`Timeout: no response for ${url} after ${FETCH_TIMEOUT_MS}ms`));
3685
+ }, FETCH_TIMEOUT_MS);
3686
+ const unsubscribe = eventBus.on(CHAT_EVENT.FETCH_RESPONSE, (response) => {
3687
+ if (response.requestId !== requestId) return;
3688
+ clearTimeout(timeoutId);
3689
+ unsubscribe();
3690
+ if (response.httpError) {
3691
+ reject(new Error(response.httpError));
3692
+ } else {
3693
+ resolve(response.data);
3694
+ }
3695
+ });
3696
+ eventBus.emit(CHAT_EVENT.FETCH_REQUEST, {
3697
+ requestId,
3698
+ service,
3699
+ url,
3700
+ method,
3701
+ ...body ? { body } : {}
3702
+ });
3703
+ });
3704
+ }
3705
+
3706
+ function formatTime$1(value, timezone) {
3707
+ try {
3708
+ const d = new Date(value);
3709
+ if (isNaN(d.getTime())) return value;
3710
+ return d.toLocaleTimeString([], {
3711
+ hour: "2-digit",
3712
+ minute: "2-digit",
3713
+ hour12: false,
3714
+ ...timezone ? { timeZone: timezone } : {}
3715
+ });
3716
+ } catch {
3717
+ return value;
3718
+ }
3719
+ }
3720
+ function formatDate$3(value, timezone) {
3721
+ try {
3722
+ const d = new Date(value);
3723
+ if (isNaN(d.getTime())) return value;
3724
+ return d.toLocaleDateString("sv-SE", {
3725
+ year: "numeric",
3726
+ month: "2-digit",
3727
+ day: "2-digit",
3728
+ ...timezone ? { timeZone: timezone } : {}
3729
+ });
3730
+ } catch {
3731
+ return value;
3732
+ }
3733
+ }
3734
+ async function mockFetch(url, params) {
3735
+ await new Promise((r) => setTimeout(r, 600 + Math.random() * 400));
3736
+ if (url.includes("companies")) {
3737
+ return [
3738
+ { id: "company-1", name: "Goluti" },
3739
+ { id: "company-2", name: "Barbeer" }
3740
+ ];
3741
+ }
3742
+ if (url.includes("locations")) {
3743
+ if (params.company_id === "company-1") {
3744
+ return [
3745
+ { id: "loc-1", name: "Sede Chico" },
3746
+ { id: "loc-2", name: "Sede Suba" }
3747
+ ];
3748
+ }
3749
+ return [{ id: "loc-3", name: "Sede Norte" }];
3750
+ }
3751
+ if (url.includes("services")) {
3752
+ return [
3753
+ { id: "svc-1", name: "Corte de cabello" },
3754
+ { id: "svc-2", name: "Manicure" },
3755
+ { id: "svc-3", name: "Tinte completo" }
3756
+ ];
3757
+ }
3758
+ if (url.includes("availability")) {
3759
+ return [
3760
+ {
3761
+ collaborator_id: "collab-1",
3762
+ user_location_rol_id: "ulr-1",
3763
+ name: "Leon",
3764
+ assignment_hours: [
3765
+ { start: "2026-03-02T14:00:00", end: "2026-03-02T14:20:00", start_time: "14:00", end_time: "14:20" },
3766
+ { start: "2026-03-02T14:30:00", end: "2026-03-02T14:50:00", start_time: "14:30", end_time: "14:50" }
3767
+ ]
3768
+ },
3769
+ {
3770
+ collaborator_id: "collab-2",
3771
+ user_location_rol_id: "ulr-2",
3772
+ name: "Carlos",
3773
+ assignment_hours: [
3774
+ { start: "2026-03-02T10:00:00", end: "2026-03-02T10:20:00", start_time: "10:00", end_time: "10:20" },
3775
+ { start: "2026-03-02T11:00:00", end: "2026-03-02T11:20:00", start_time: "11:00", end_time: "11:20" }
3776
+ ]
3777
+ }
3778
+ ];
3779
+ }
3780
+ return [];
3781
+ }
3782
+ function getDependencies(field) {
3783
+ if (!field.depends_on) return [];
3784
+ return Array.isArray(field.depends_on) ? field.depends_on : [field.depends_on];
3785
+ }
3786
+ function allDepsResolved(deps, formValues) {
3787
+ return deps.every((dep) => {
3788
+ const val = formValues[dep];
3789
+ if (Array.isArray(val)) return val.length > 0;
3790
+ return val !== "" && val !== null && val !== void 0;
3791
+ });
3792
+ }
3793
+ function useReactiveEndpoints({ fields, fieldStates, setFieldState, eventBus, timezone, formTitle }) {
3794
+ const loadingRef = React.useRef(/* @__PURE__ */ new Set());
3795
+ const loadEndpoint = React.useCallback(
3796
+ async (field, formValues) => {
3797
+ if (!field.endpoint || loadingRef.current.has(field.name)) return;
3798
+ const deps = getDependencies(field);
3799
+ if (!allDepsResolved(deps, formValues)) return;
3800
+ loadingRef.current.add(field.name);
3801
+ setFieldState(field.name, { loading: true, error: null });
3802
+ const startTime = Date.now();
3803
+ try {
3804
+ const resolvedBody = field.endpoint.body ? resolveBody(field.endpoint.body, formValues, fieldStates) : void 0;
3805
+ const params = field.endpoint.params ? resolveParams(field.endpoint.params, formValues, fieldStates) : {};
3806
+ const requestBody = resolvedBody ?? (Object.keys(params).length > 0 ? params : void 0);
3807
+ if (eventBus) {
3808
+ eventBus.emit(CHAT_EVENT.FORM_TRACE, {
3809
+ chatId: "",
3810
+ formTitle: formTitle || "",
3811
+ source: "reactive_form",
3812
+ phase: "request",
3813
+ service: field.endpoint.service,
3814
+ url: field.endpoint.url,
3815
+ method: field.endpoint.method,
3816
+ body: requestBody
3817
+ });
3818
+ }
3819
+ let rawData;
3820
+ if (eventBus) {
3821
+ rawData = await fetchViaEventBus(
3822
+ eventBus,
3823
+ field.endpoint.service,
3824
+ field.endpoint.url,
3825
+ field.endpoint.method,
3826
+ requestBody
3827
+ );
3828
+ } else {
3829
+ rawData = await mockFetch(field.endpoint.url, params);
3830
+ }
3831
+ let dataArray;
3832
+ let data = rawData;
3833
+ if (rawData && typeof rawData === "object" && "response" in rawData) {
3834
+ data = rawData.response;
3835
+ }
3836
+ if (field.endpoint.response_path && data && typeof data === "object" && !Array.isArray(data)) {
3837
+ const extracted = data[field.endpoint.response_path];
3838
+ dataArray = Array.isArray(extracted) ? extracted : [];
3839
+ } else {
3840
+ dataArray = Array.isArray(data) ? data : [];
3841
+ }
3842
+ if (eventBus && rawData && typeof rawData === "object") {
3843
+ const resp = rawData;
3844
+ if (resp.notification_type && String(resp.notification_type).toLowerCase() !== "success") {
3845
+ throw new Error(resp.message || "Error en la respuesta");
3846
+ }
3847
+ }
3848
+ const options = dataArray.map((item) => {
3849
+ const opt = {
3850
+ value: String(item[field.endpoint.value_field] || ""),
3851
+ label: String(item[field.endpoint.label_field] || "")
3852
+ };
3853
+ if (field.endpoint.extra_fields) {
3854
+ for (const ef of field.endpoint.extra_fields) {
3855
+ opt[ef] = item[ef];
3856
+ }
3857
+ }
3858
+ return opt;
3859
+ });
3860
+ setFieldState(field.name, { options, loading: false });
3861
+ if (eventBus) {
3862
+ eventBus.emit(CHAT_EVENT.FORM_TRACE, {
3863
+ chatId: "",
3864
+ formTitle: formTitle || "",
3865
+ source: "reactive_form",
3866
+ phase: "response",
3867
+ service: field.endpoint.service,
3868
+ url: field.endpoint.url,
3869
+ method: field.endpoint.method,
3870
+ status: 200,
3871
+ duration_ms: Date.now() - startTime,
3872
+ success: true,
3873
+ response: rawData
3874
+ });
3875
+ }
3876
+ } catch (err) {
3877
+ const errorMsg = err instanceof Error ? err.message : "Error al cargar opciones";
3878
+ setFieldState(field.name, { loading: false, error: errorMsg });
3879
+ if (eventBus) {
3880
+ eventBus.emit(CHAT_EVENT.FORM_TRACE, {
3881
+ chatId: "",
3882
+ formTitle: formTitle || "",
3883
+ source: "reactive_form",
3884
+ phase: "response",
3885
+ service: field.endpoint.service,
3886
+ url: field.endpoint.url,
3887
+ method: field.endpoint.method,
3888
+ status: 500,
3889
+ duration_ms: Date.now() - startTime,
3890
+ success: false,
3891
+ error: errorMsg
3892
+ });
3893
+ }
3894
+ } finally {
3895
+ loadingRef.current.delete(field.name);
3896
+ }
3897
+ },
3898
+ [fields, fieldStates, setFieldState, eventBus]
3899
+ );
3900
+ const resolveOptionsFrom = React.useCallback(
3901
+ (field, formValues) => {
3902
+ if (!field.options_from) return;
3903
+ const sourceState = fieldStates[field.options_from.source_field];
3904
+ const sourceValue = formValues[field.options_from.source_field];
3905
+ if (!sourceState || !sourceValue) return;
3906
+ const selectedItem = sourceState.options.find((o) => o.value === sourceValue);
3907
+ if (!selectedItem) return;
3908
+ const rawData = selectedItem[field.options_from.data_field];
3909
+ if (!Array.isArray(rawData)) return;
3910
+ const options = rawData.map((item) => {
3911
+ let val = field.options_from.value_template;
3912
+ let lbl = field.options_from.label_template;
3913
+ for (const [k, v] of Object.entries(item)) {
3914
+ const strVal = String(v);
3915
+ const timeStr = formatTime$1(strVal, timezone);
3916
+ const dateStr = formatDate$3(strVal, timezone);
3917
+ val = val.replace(`\${${k}|time}`, timeStr);
3918
+ val = val.replace(`\${${k}|date}`, dateStr);
3919
+ val = val.replace(`\${${k}_time}`, timeStr);
3920
+ val = val.replace(`\${${k}_date}`, dateStr);
3921
+ val = val.replace(`\${${k}}`, strVal);
3922
+ lbl = lbl.replace(`\${${k}|time}`, timeStr);
3923
+ lbl = lbl.replace(`\${${k}|date}`, dateStr);
3924
+ lbl = lbl.replace(`\${${k}_time}`, timeStr);
3925
+ lbl = lbl.replace(`\${${k}_date}`, dateStr);
3926
+ lbl = lbl.replace(`\${${k}}`, strVal);
3927
+ }
3928
+ return { value: val, label: lbl, ...item };
3929
+ });
3930
+ setFieldState(field.name, { options, loading: false });
3931
+ },
3932
+ [fieldStates, setFieldState]
3933
+ );
3934
+ return { loadEndpoint, resolveOptionsFrom, getDependencies, allDepsResolved, fetchViaEventBus: eventBus ? fetchViaEventBus.bind(null, eventBus) : void 0 };
3935
+ }
3936
+
3937
+ function createInitialFieldStates(fields) {
3938
+ const map = {};
3939
+ for (const f of fields) {
3940
+ map[f.name] = {
3941
+ value: f.type === "hidden" ? f.default_value ?? "" : f.type === "select_multiple" ? [] : "",
3942
+ label: "",
3943
+ options: f.options || [],
3944
+ loading: false,
3945
+ error: null
3946
+ };
3947
+ }
3948
+ return map;
3949
+ }
3950
+ function useReactiveForm(props) {
3951
+ const { fields, steps, submit, eventBus } = props;
3952
+ const { timezone } = useChatConfig();
3953
+ const [formStatus, setFormStatus] = React.useState("closed");
3954
+ const [currentStep, setCurrentStep] = React.useState(0);
3955
+ const [values, setValues] = React.useState(() => buildInitialValues(fields));
3956
+ const [errors, setErrors] = React.useState({});
3957
+ const [touched, setTouched] = React.useState({});
3958
+ const [fieldStates, setFieldStatesMap] = React.useState(
3959
+ () => createInitialFieldStates(fields)
3960
+ );
3961
+ const validationSchema = React.useMemo(() => buildYupSchema(fields), [fields]);
3962
+ const totalSteps = steps.length + 1;
3963
+ const setFieldState = React.useCallback((name, partial) => {
3964
+ setFieldStatesMap((prev) => ({
3965
+ ...prev,
3966
+ [name]: { ...prev[name], ...partial }
3967
+ }));
3968
+ }, []);
3969
+ const { loadEndpoint, resolveOptionsFrom, getDependencies, allDepsResolved } = useReactiveEndpoints({ fields, fieldStates, setFieldState, eventBus, timezone, formTitle: props.title });
3970
+ const handleTriggerClick = () => {
3971
+ if (formStatus === "completed") return;
3972
+ setFormStatus(formStatus === "open" ? "closed" : "open");
3973
+ };
3974
+ const setFieldValue = React.useCallback((name, value) => {
3975
+ setValues((prev) => ({ ...prev, [name]: value }));
3976
+ }, []);
3977
+ const handleFieldChange = React.useCallback(
3978
+ (fieldName, value, label, extraData) => {
3979
+ setFieldValue(fieldName, value);
3980
+ setFieldState(fieldName, { value, label, extraData });
3981
+ setErrors((prev) => {
3982
+ const next = { ...prev };
3983
+ delete next[fieldName];
3984
+ return next;
3985
+ });
3986
+ for (const f of fields) {
3987
+ const deps = getDependencies(f);
3988
+ if (deps.includes(fieldName)) {
3989
+ const resetVal = f.type === "select_multiple" ? [] : "";
3990
+ setFieldValue(f.name, resetVal);
3991
+ setFieldState(f.name, { value: resetVal, label: "", options: [], extraData: void 0 });
3992
+ }
3993
+ }
3994
+ setValues((currentValues) => {
3995
+ const nextValues = { ...currentValues, [fieldName]: value };
3996
+ for (const f of fields) {
3997
+ const deps = getDependencies(f);
3998
+ if (deps.includes(fieldName) && allDepsResolved(deps, nextValues)) {
3999
+ if (f.endpoint) {
4000
+ loadEndpoint(f, nextValues);
4001
+ } else if (f.options_from) {
4002
+ setTimeout(() => resolveOptionsFrom(f, nextValues), 0);
4003
+ }
4004
+ }
4005
+ }
4006
+ return nextValues;
4007
+ });
4008
+ },
4009
+ [fields, getDependencies, allDepsResolved, loadEndpoint, resolveOptionsFrom, setFieldState, setFieldValue]
4010
+ );
4011
+ React.useEffect(() => {
4012
+ if (formStatus !== "open") return;
4013
+ const initialValues = buildInitialValues(fields);
4014
+ for (const f of fields) {
4015
+ if (!f.endpoint || fieldStates[f.name]?.options.length > 0) continue;
4016
+ const deps = getDependencies(f);
4017
+ if (deps.length === 0 || allDepsResolved(deps, initialValues)) {
4018
+ loadEndpoint(f, initialValues);
4019
+ }
4020
+ }
4021
+ }, [formStatus]);
4022
+ React.useEffect(() => {
4023
+ if (formStatus !== "open" || currentStep >= steps.length) return;
4024
+ const stepFieldNames = steps[currentStep].fields;
4025
+ setValues((currentValues) => {
4026
+ for (const f of fields) {
4027
+ if (!stepFieldNames.includes(f.name)) continue;
4028
+ if (!f.endpoint && !f.options_from) continue;
4029
+ if (fieldStates[f.name]?.options.length > 0) continue;
4030
+ if (fieldStates[f.name]?.loading) continue;
4031
+ const deps = getDependencies(f);
4032
+ if (allDepsResolved(deps, currentValues)) {
4033
+ if (f.endpoint) {
4034
+ loadEndpoint(f, currentValues);
4035
+ } else if (f.options_from) {
4036
+ resolveOptionsFrom(f, currentValues);
4037
+ }
4038
+ }
4039
+ }
4040
+ return currentValues;
4041
+ });
4042
+ }, [currentStep, formStatus]);
4043
+ const validateFields = async (fieldNames) => {
4044
+ const fieldErrors = {};
4045
+ try {
4046
+ await validationSchema.validate(values, { abortEarly: false });
4047
+ } catch (err) {
4048
+ if (err && typeof err === "object" && "inner" in err) {
4049
+ const yupErr = err;
4050
+ for (const e of yupErr.inner) {
4051
+ if (e.path && fieldNames.includes(e.path)) {
4052
+ fieldErrors[e.path] = e.message;
4053
+ }
4054
+ }
4055
+ }
4056
+ }
4057
+ return fieldErrors;
4058
+ };
4059
+ const validateStep = async (stepIndex) => {
4060
+ if (stepIndex >= steps.length) return true;
4061
+ const stepFieldNames = steps[stepIndex].fields;
4062
+ const stepErrors = await validateFields(stepFieldNames);
4063
+ setErrors((prev) => ({ ...prev, ...stepErrors }));
4064
+ const touchMap = {};
4065
+ for (const name of stepFieldNames) touchMap[name] = true;
4066
+ setTouched((prev) => ({ ...prev, ...touchMap }));
4067
+ return Object.keys(stepErrors).length === 0;
4068
+ };
4069
+ const handleNext = async () => {
4070
+ const valid = await validateStep(currentStep);
4071
+ if (valid) setCurrentStep((s) => s + 1);
4072
+ };
4073
+ const handleBack = () => setCurrentStep((s) => s - 1);
4074
+ const [submitMessage, setSubmitMessage] = React.useState("");
4075
+ const handleSubmit = async () => {
4076
+ const resolvedPayload = resolveBody(submit.payload_map, values, fieldStates);
4077
+ if (eventBus) {
4078
+ try {
4079
+ const data = await fetchViaEventBus(
4080
+ eventBus,
4081
+ submit.service,
4082
+ submit.url,
4083
+ submit.method,
4084
+ resolvedPayload
4085
+ );
4086
+ const resp = data;
4087
+ const notificationType = String(resp?.notification_type ?? "SUCCESS").toUpperCase();
4088
+ const message = String(resp?.message ?? "");
4089
+ const formLabels = {};
4090
+ for (const [name, state] of Object.entries(fieldStates)) {
4091
+ if (state.label) formLabels[name] = state.label;
4092
+ }
4093
+ eventBus.emit(CHAT_EVENT.FORM_SUBMIT, {
4094
+ formType: "reactive_form",
4095
+ submitUrl: submit.url,
4096
+ result: data,
4097
+ formValues: values,
4098
+ formLabels
4099
+ });
4100
+ if (notificationType === "SUCCESS") {
4101
+ setSubmitMessage(message || "Completado");
4102
+ setFormStatus("completed");
4103
+ } else if (notificationType === "WARNING") {
4104
+ setSubmitMessage(message || "Advertencia");
4105
+ setFormStatus("warning");
4106
+ } else {
4107
+ setSubmitMessage(message || "Error al procesar");
4108
+ setFormStatus("error");
4109
+ }
4110
+ } catch (err) {
4111
+ const message = err instanceof Error ? err.message : "Error al enviar formulario";
4112
+ setSubmitMessage(message);
4113
+ setFormStatus("error");
4114
+ }
4115
+ } else {
4116
+ console.log("[ReactiveForm] Submit:", values);
4117
+ console.log("[ReactiveForm] Payload map:", resolvedPayload);
4118
+ setFormStatus("completed");
4119
+ }
4120
+ };
4121
+ const resolveRows = (rows) => resolveSummaryRows(rows, values, fieldStates);
4122
+ return {
4123
+ formStatus,
4124
+ setFormStatus,
4125
+ submitMessage,
4126
+ currentStep,
4127
+ setCurrentStep,
4128
+ values,
4129
+ errors,
4130
+ touched,
4131
+ fieldStates,
4132
+ validationSchema,
4133
+ totalSteps,
4134
+ handleTriggerClick,
4135
+ setFieldValue,
4136
+ handleFieldChange,
4137
+ validateFields,
4138
+ validateStep,
4139
+ handleNext,
4140
+ handleBack,
4141
+ handleSubmit,
4142
+ getDependencies,
4143
+ allDepsResolved,
4144
+ resolveSummaryRows: resolveRows
4145
+ };
4146
+ }
4147
+
4148
+ const MOBILE_BREAKPOINT = 640;
4149
+ const useIsMobile$1 = () => {
4150
+ const [isMobile, setIsMobile] = React.useState(
4151
+ typeof window !== "undefined" ? window.innerWidth < MOBILE_BREAKPOINT : false
4152
+ );
4153
+ React.useEffect(() => {
4154
+ const mq = window.matchMedia(`(max-width: ${MOBILE_BREAKPOINT - 1}px)`);
4155
+ const handler = (e) => setIsMobile(e.matches);
4156
+ mq.addEventListener("change", handler);
4157
+ return () => mq.removeEventListener("change", handler);
4158
+ }, []);
4159
+ return isMobile;
4160
+ };
4161
+ const ReactiveForm = ({ component, eventBus }) => {
4162
+ const props = component.props;
4163
+ const isMobile = useIsMobile$1();
4164
+ const form = useReactiveForm({ ...props, eventBus });
4165
+ if (component.answered && form.formStatus !== "completed" && form.formStatus !== "warning" && form.formStatus !== "error") {
4166
+ form.setFormStatus("completed");
4167
+ }
4168
+ return /* @__PURE__ */ jsxRuntime.jsx(
4169
+ ReactiveFormView,
4170
+ {
4171
+ ...props,
4172
+ form,
4173
+ drawerPlacement: isMobile ? "bottom" : "right"
4174
+ }
4175
+ );
4176
+ };
4177
+
4178
+ function useStoreState(store, key) {
4179
+ const [value, setValue] = React.useState(() => store.get(key));
4180
+ React.useEffect(() => {
4181
+ return store.subscribe(key, setValue);
4182
+ }, [store, key]);
4183
+ return value;
4184
+ }
4185
+
4186
+ function createStore(initial) {
4187
+ const state = { ...initial };
4188
+ const listeners = {};
4189
+ const notify = (key, value) => {
4190
+ const keyStr = String(key);
4191
+ listeners[keyStr]?.forEach((l) => l(value));
4192
+ };
4193
+ const subscribe = (key, listener) => {
4194
+ const keyStr = String(key);
4195
+ if (!listeners[keyStr]) listeners[keyStr] = /* @__PURE__ */ new Set();
4196
+ listeners[keyStr].add(listener);
4197
+ listener(state[key]);
4198
+ return () => {
4199
+ listeners[keyStr].delete(listener);
4200
+ };
4201
+ };
4202
+ const set = (key, value) => {
4203
+ state[key] = value;
4204
+ notify(key, value);
4205
+ };
4206
+ const get = (key) => state[key];
4207
+ return { set, get, subscribe };
4208
+ }
4209
+
4210
+ const CAROUSEL_STORE_KEYS = {
4211
+ ITEMS: "items",
4212
+ ORIGINAL_ITEMS: "originalItems",
4213
+ SEARCH_QUERY: "searchQuery",
4214
+ SEARCH_STATUS: "searchStatus",
4215
+ SELECTED_IDS: "selectedIds",
4216
+ CURRENT_PAGE: "currentPage",
4217
+ HAS_MORE: "hasMore"
4218
+ };
4219
+
4220
+ function createCarouselStore(initialItems) {
4221
+ return createStore({
4222
+ [CAROUSEL_STORE_KEYS.ITEMS]: initialItems,
4223
+ [CAROUSEL_STORE_KEYS.ORIGINAL_ITEMS]: initialItems,
4224
+ [CAROUSEL_STORE_KEYS.SEARCH_QUERY]: "",
4225
+ [CAROUSEL_STORE_KEYS.SEARCH_STATUS]: "idle",
4226
+ [CAROUSEL_STORE_KEYS.SELECTED_IDS]: [],
4227
+ [CAROUSEL_STORE_KEYS.CURRENT_PAGE]: 0,
4228
+ [CAROUSEL_STORE_KEYS.HAS_MORE]: false
4229
+ });
4230
+ }
4231
+
4232
+ function createCarouselActions(store) {
4233
+ return {
4234
+ items: {
4235
+ set: (items) => store.set(CAROUSEL_STORE_KEYS.ITEMS, items),
4236
+ remove: (id) => {
4237
+ const current = store.get(CAROUSEL_STORE_KEYS.ITEMS);
4238
+ if (current.length <= 1) return;
4239
+ store.set(CAROUSEL_STORE_KEYS.ITEMS, current.filter((i) => i.id !== id));
4240
+ },
4241
+ get: () => store.get(CAROUSEL_STORE_KEYS.ITEMS)
4242
+ },
4243
+ selection: {
4244
+ toggle: (id) => {
4245
+ const current = store.get(CAROUSEL_STORE_KEYS.SELECTED_IDS);
4246
+ const next = current.includes(id) ? current.filter((i) => i !== id) : [...current, id];
4247
+ store.set(CAROUSEL_STORE_KEYS.SELECTED_IDS, next);
4248
+ },
4249
+ clear: () => store.set(CAROUSEL_STORE_KEYS.SELECTED_IDS, []),
4250
+ get: () => store.get(CAROUSEL_STORE_KEYS.SELECTED_IDS)
4251
+ },
4252
+ search: {
4253
+ setQuery: (query) => store.set(CAROUSEL_STORE_KEYS.SEARCH_QUERY, query),
4254
+ setStatus: (status) => store.set(CAROUSEL_STORE_KEYS.SEARCH_STATUS, status),
4255
+ getQuery: () => store.get(CAROUSEL_STORE_KEYS.SEARCH_QUERY)
4256
+ },
4257
+ pagination: {
4258
+ setPage: (page) => store.set(CAROUSEL_STORE_KEYS.CURRENT_PAGE, page),
4259
+ setHasMore: (hasMore) => store.set(CAROUSEL_STORE_KEYS.HAS_MORE, hasMore),
4260
+ getPage: () => store.get(CAROUSEL_STORE_KEYS.CURRENT_PAGE)
4261
+ },
4262
+ getOriginalItems: () => store.get(CAROUSEL_STORE_KEYS.ORIGINAL_ITEMS)
4263
+ };
4264
+ }
4265
+
4266
+ const SIZE_PX = { small: 80, medium: 120, large: 180 };
4267
+ const GAP_PX = 8;
4268
+ function calcPageLimit(size, containerWidth) {
4269
+ const cardWidth = SIZE_PX[size];
4270
+ return Math.max(1, Math.floor(containerWidth / (cardWidth + GAP_PX)));
4271
+ }
4272
+ function resolveSize(size, itemCount) {
4273
+ if (size && size !== "auto") return size;
4274
+ if (itemCount <= 3) return "large";
4275
+ if (itemCount <= 6) return "medium";
4276
+ return "small";
4277
+ }
4278
+ function mapResponseToItems(data, endpoint) {
4279
+ let unwrapped = data;
4280
+ if (unwrapped && typeof unwrapped === "object" && "response" in unwrapped) {
4281
+ unwrapped = unwrapped.response;
4282
+ }
4283
+ if (endpoint.response_path && unwrapped && typeof unwrapped === "object" && !Array.isArray(unwrapped)) {
4284
+ unwrapped = unwrapped[endpoint.response_path];
4285
+ }
4286
+ const arr = Array.isArray(unwrapped) ? unwrapped : [];
4287
+ return arr.map((item) => {
4288
+ const metadata = {};
4289
+ if (endpoint.extra_fields) {
4290
+ for (const field of endpoint.extra_fields) {
4291
+ metadata[field] = item[field];
4292
+ }
4293
+ }
4294
+ return {
4295
+ id: String(item[endpoint.id_field] ?? ""),
4296
+ type: endpoint.item_type,
4297
+ title: endpoint.title_field ? String(item[endpoint.title_field] ?? "") : void 0,
4298
+ description: endpoint.description_field ? String(item[endpoint.description_field] ?? "") : void 0,
4299
+ src: endpoint.src_field ? String(item[endpoint.src_field] ?? "") : void 0,
4300
+ file_type: endpoint.file_type_field ? String(item[endpoint.file_type_field] ?? "") : void 0,
4301
+ status: "ready",
4302
+ metadata: Object.keys(metadata).length > 0 ? metadata : void 0
4303
+ };
4304
+ });
4305
+ }
4306
+
4307
+ const MOCK_NAMES = [
4308
+ "Alpha",
4309
+ "Beta",
4310
+ "Gamma",
4311
+ "Delta",
4312
+ "Epsilon",
4313
+ "Zeta",
4314
+ "Eta",
4315
+ "Theta",
4316
+ "Iota",
4317
+ "Kappa",
4318
+ "Lambda",
4319
+ "Mu",
4320
+ "Nu",
4321
+ "Xi",
4322
+ "Omicron",
4323
+ "Pi",
4324
+ "Rho",
4325
+ "Sigma",
4326
+ "Tau",
4327
+ "Upsilon",
4328
+ "Phi",
4329
+ "Chi",
4330
+ "Psi",
4331
+ "Omega",
4332
+ "Altair",
4333
+ "Vega",
4334
+ "Sirius",
4335
+ "Rigel",
4336
+ "Polaris",
4337
+ "Antares"
4338
+ ];
4339
+ const MOCK_ITEMS = MOCK_NAMES.map((name, i) => ({
4340
+ id: String(i + 1),
4341
+ name: `Empresa ${name}`,
4342
+ address: `Calle ${i + 1} #${(i + 1) * 10}-${(i + 1) * 5}`,
4343
+ logo_url: `https://picsum.photos/seed/${name.toLowerCase()}/200`
4344
+ }));
4345
+ async function mockSearchFetch(query, skip, limit) {
4346
+ await new Promise((r) => setTimeout(r, 400 + Math.random() * 300));
4347
+ let filtered = MOCK_ITEMS;
4348
+ if (query) {
4349
+ filtered = MOCK_ITEMS.filter((i) => i.name.toLowerCase().includes(query.toLowerCase()));
4350
+ }
4351
+ return filtered.slice(skip, skip + limit);
4352
+ }
4353
+ function useCarouselSearch({ actions, endpoint, eventBus, pageLimit }) {
4354
+ const loadingRef = React.useRef(false);
4355
+ const search = React.useCallback(
4356
+ async (query, page = 0) => {
4357
+ if (loadingRef.current) return;
4358
+ loadingRef.current = true;
4359
+ actions.search.setQuery(query);
4360
+ if (page === 0) {
4361
+ actions.search.setStatus("loading");
4362
+ }
4363
+ const limit = endpoint?.limit ?? pageLimit;
4364
+ const skip = page * limit;
4365
+ const startTime = Date.now();
4366
+ try {
4367
+ let rawData;
4368
+ if (eventBus && endpoint) {
4369
+ const baseBody = endpoint.body ?? {};
4370
+ const cleanBody = {};
4371
+ for (const [k, v] of Object.entries(baseBody)) {
4372
+ if (typeof v === "string" && v.includes("$query")) continue;
4373
+ cleanBody[k] = v;
4374
+ }
4375
+ const body = {
4376
+ ...cleanBody,
4377
+ skip,
4378
+ limit
4379
+ };
4380
+ if (query && endpoint.query_param) {
4381
+ body.filters = [
4382
+ ...Array.isArray(body.filters) ? body.filters : [],
4383
+ { field: endpoint.query_param, condition: "like", value: query }
4384
+ ];
4385
+ }
4386
+ eventBus.emit(CHAT_EVENT.FORM_TRACE, {
4387
+ chatId: "",
4388
+ formTitle: "carousel",
4389
+ source: "carousel",
4390
+ phase: "request",
4391
+ service: endpoint.service,
4392
+ url: endpoint.url,
4393
+ method: endpoint.method,
4394
+ body
4395
+ });
4396
+ rawData = await fetchViaEventBus(
4397
+ eventBus,
4398
+ endpoint.service,
4399
+ endpoint.url,
4400
+ endpoint.method,
4401
+ body
4402
+ );
4403
+ eventBus.emit(CHAT_EVENT.FORM_TRACE, {
4404
+ chatId: "",
4405
+ formTitle: "carousel",
4406
+ source: "carousel",
4407
+ phase: "response",
4408
+ service: endpoint.service,
4409
+ url: endpoint.url,
4410
+ method: endpoint.method,
4411
+ status: 200,
4412
+ duration_ms: Date.now() - startTime,
4413
+ success: true,
4414
+ response: rawData
4415
+ });
4416
+ } else {
4417
+ rawData = await mockSearchFetch(query, skip, limit);
4418
+ }
4419
+ let newItems;
4420
+ if (endpoint) {
4421
+ newItems = mapResponseToItems(rawData, endpoint);
4422
+ } else {
4423
+ const arr = Array.isArray(rawData) ? rawData : [];
4424
+ newItems = arr.map((item) => ({
4425
+ id: String(item.id ?? ""),
4426
+ type: "image",
4427
+ title: String(item.name ?? ""),
4428
+ description: String(item.address ?? ""),
4429
+ src: String(item.logo_url ?? ""),
4430
+ status: "ready"
4431
+ }));
4432
+ }
4433
+ actions.items.set(newItems);
4434
+ actions.pagination.setPage(page);
4435
+ actions.pagination.setHasMore(newItems.length === limit);
4436
+ actions.search.setStatus("idle");
4437
+ } catch (err) {
4438
+ actions.search.setStatus("error");
4439
+ if (eventBus && endpoint) {
4440
+ eventBus.emit(CHAT_EVENT.FORM_TRACE, {
4441
+ chatId: "",
4442
+ formTitle: "carousel",
4443
+ source: "carousel",
4444
+ phase: "response",
4445
+ service: endpoint.service,
4446
+ url: endpoint.url,
4447
+ method: endpoint.method,
4448
+ status: 500,
4449
+ duration_ms: Date.now() - startTime,
4450
+ success: false,
4451
+ error: err instanceof Error ? err.message : "Error en busqueda"
4452
+ });
4453
+ }
4454
+ } finally {
4455
+ loadingRef.current = false;
4456
+ }
4457
+ },
4458
+ [actions, endpoint, eventBus, pageLimit]
4459
+ );
4460
+ const loadNext = React.useCallback(() => {
4461
+ const currentPage = actions.pagination.getPage();
4462
+ const query = actions.search.getQuery();
4463
+ search(query, currentPage + 1);
4464
+ }, [actions, search]);
4465
+ const loadPrev = React.useCallback(() => {
4466
+ const currentPage = actions.pagination.getPage();
4467
+ if (currentPage <= 0) return;
4468
+ const query = actions.search.getQuery();
4469
+ search(query, currentPage - 1);
4470
+ }, [actions, search]);
4471
+ return { search, loadNext, loadPrev };
4472
+ }
4473
+
4474
+ const FILE_ICONS = {
4475
+ pdf: "\u{1F4C4}",
4476
+ doc: "\u{1F4DD}",
4477
+ docx: "\u{1F4DD}",
4478
+ xls: "\u{1F4CA}",
4479
+ xlsx: "\u{1F4CA}",
4480
+ ppt: "\u{1F4CE}",
4481
+ pptx: "\u{1F4CE}",
4482
+ zip: "\u{1F4E6}",
4483
+ rar: "\u{1F4E6}",
4484
+ jpg: "\u{1F5BC}\uFE0F",
4485
+ jpeg: "\u{1F5BC}\uFE0F",
4486
+ png: "\u{1F5BC}\uFE0F",
4487
+ gif: "\u{1F5BC}\uFE0F",
4488
+ webp: "\u{1F5BC}\uFE0F",
4489
+ mp4: "\u{1F3AC}",
4490
+ mov: "\u{1F3AC}",
4491
+ avi: "\u{1F3AC}",
4492
+ mp3: "\u{1F3B5}",
4493
+ wav: "\u{1F3B5}"
4494
+ };
4495
+ const CarouselCard = ({
4496
+ item,
4497
+ size,
4498
+ selectionMode,
4499
+ isSelected,
4500
+ disabled,
4501
+ onSelect,
4502
+ onRemove,
4503
+ onPreview
4504
+ }) => {
4505
+ const isSelectable = selectionMode !== "none" && !disabled;
4506
+ const hasPreview = selectionMode === "none" && !!onPreview && item.src && (item.type === "image" || item.type === "file");
4507
+ const isClickable = isSelectable || hasPreview;
4508
+ const handleClick = () => {
4509
+ if (isSelectable) {
4510
+ if (selectionMode === "removable") return;
4511
+ onSelect(item);
4512
+ return;
4513
+ }
4514
+ if (hasPreview) {
4515
+ onPreview(item);
4516
+ }
4517
+ };
4518
+ const handleRemove = (e) => {
4519
+ e.stopPropagation();
4520
+ if (disabled) return;
4521
+ onRemove(item);
4522
+ };
4523
+ if (item.status === "loading") {
4524
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: `px-chat-carousel-card px-chat-carousel-card--${size} px-chat-carousel-card--loading`, children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-chat-carousel-card__skeleton" }) });
4525
+ }
4526
+ return /* @__PURE__ */ jsxRuntime.jsxs(
4527
+ "div",
4528
+ {
4529
+ className: [
4530
+ "px-chat-carousel-card",
4531
+ `px-chat-carousel-card--${size}`,
4532
+ `px-chat-carousel-card--${item.type}`,
4533
+ isSelected ? "px-chat-carousel-card--selected" : "",
4534
+ isClickable ? "px-chat-carousel-card--clickable" : "",
4535
+ disabled ? "px-chat-carousel-card--disabled" : ""
4536
+ ].filter(Boolean).join(" "),
4537
+ onClick: handleClick,
4538
+ role: isClickable ? "button" : void 0,
4539
+ tabIndex: isClickable ? 0 : void 0,
4540
+ onKeyDown: isClickable ? (e) => {
4541
+ if (e.key === "Enter" || e.key === " ") handleClick();
4542
+ } : void 0,
4543
+ children: [
4544
+ selectionMode === "removable" && !disabled && /* @__PURE__ */ jsxRuntime.jsx(
4545
+ "button",
4546
+ {
4547
+ className: "px-chat-carousel-card__remove",
4548
+ onClick: handleRemove,
4549
+ "aria-label": "Eliminar",
4550
+ type: "button",
4551
+ children: "\xD7"
4552
+ }
4553
+ ),
4554
+ isSelected && selectionMode !== "removable" && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-chat-carousel-card__check", children: "\u2713" }),
4555
+ item.type === "image" && /* @__PURE__ */ jsxRuntime.jsx(
4556
+ "img",
4557
+ {
4558
+ className: "px-chat-carousel-card__image",
4559
+ src: item.src,
4560
+ alt: item.title || "",
4561
+ loading: "lazy"
4562
+ }
4563
+ ),
4564
+ item.type === "file" && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-chat-carousel-card__file-icon", children: FILE_ICONS[item.file_type?.toLowerCase() ?? ""] || "\u{1F4C1}" }),
4565
+ item.type === "text" && !item.title && !item.description && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-chat-carousel-card__file-icon", children: "\u{1F4CB}" }),
4566
+ (item.title || item.description) && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "px-chat-carousel-card__info", children: [
4567
+ item.title && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-chat-carousel-card__title", children: item.title }),
4568
+ item.description && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-chat-carousel-card__description", children: item.description })
4569
+ ] })
4570
+ ]
4571
+ }
4572
+ );
4573
+ };
4574
+
4575
+ const CarouselTrack = ({
4576
+ currentPage,
4577
+ hasMore,
4578
+ onPrev,
4579
+ onNext,
4580
+ children
4581
+ }) => {
4582
+ const trackRef = React.useRef(null);
4583
+ React.useEffect(() => {
4584
+ if (trackRef.current) {
4585
+ trackRef.current.scrollLeft = 0;
4586
+ }
4587
+ }, [currentPage]);
4588
+ const showPrev = currentPage > 0;
4589
+ const showNext = hasMore;
4590
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "px-chat-carousel-track-wrapper", children: [
4591
+ showPrev && /* @__PURE__ */ jsxRuntime.jsx(
4592
+ "button",
4593
+ {
4594
+ className: "px-chat-carousel-track__nav",
4595
+ onClick: onPrev,
4596
+ type: "button",
4597
+ "aria-label": "Anterior",
4598
+ children: /* @__PURE__ */ jsxRuntime.jsx("svg", { width: "20", height: "20", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsxRuntime.jsx("polyline", { points: "15 18 9 12 15 6" }) })
4599
+ }
4600
+ ),
4601
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-chat-carousel-track", ref: trackRef, children }),
4602
+ showNext && /* @__PURE__ */ jsxRuntime.jsx(
4603
+ "button",
4604
+ {
4605
+ className: "px-chat-carousel-track__nav",
4606
+ onClick: onNext,
4607
+ type: "button",
4608
+ "aria-label": "Siguiente",
4609
+ children: /* @__PURE__ */ jsxRuntime.jsx("svg", { width: "20", height: "20", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsxRuntime.jsx("polyline", { points: "9 18 15 12 9 6" }) })
4610
+ }
4611
+ )
4612
+ ] });
4613
+ };
4614
+
4615
+ const DEBOUNCE_MS = 300;
4616
+ const CarouselSearch = ({ onSearch, loading }) => {
4617
+ const [value, setValue] = React.useState("");
4618
+ const timerRef = React.useRef(void 0);
4619
+ const onSearchRef = React.useRef(onSearch);
4620
+ onSearchRef.current = onSearch;
4621
+ React.useEffect(() => {
4622
+ clearTimeout(timerRef.current);
4623
+ timerRef.current = setTimeout(() => {
4624
+ onSearchRef.current(value);
4625
+ }, DEBOUNCE_MS);
4626
+ return () => clearTimeout(timerRef.current);
4627
+ }, [value]);
4628
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "px-chat-carousel-search", children: [
4629
+ /* @__PURE__ */ jsxRuntime.jsx(
4630
+ "input",
4631
+ {
4632
+ className: "px-chat-carousel-search__input",
4633
+ type: "text",
4634
+ placeholder: "Buscar...",
4635
+ value,
4636
+ onChange: (e) => setValue(e.target.value)
4637
+ }
4638
+ ),
4639
+ loading && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "px-chat-carousel-search__spinner" }),
4640
+ value && !loading && /* @__PURE__ */ jsxRuntime.jsx(
4641
+ "button",
4642
+ {
4643
+ className: "px-chat-carousel-search__clear",
4644
+ onClick: () => setValue(""),
4645
+ type: "button",
4646
+ "aria-label": "Limpiar",
4647
+ children: "\xD7"
4648
+ }
4649
+ )
4650
+ ] });
4651
+ };
4652
+
4653
+ const CarouselConfirm = ({
4654
+ label,
4655
+ count,
4656
+ disabled,
4657
+ onClick
4658
+ }) => {
4659
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-chat-carousel-confirm", children: /* @__PURE__ */ jsxRuntime.jsxs(
4660
+ "button",
4661
+ {
4662
+ className: "px-chat-carousel-confirm__button",
4663
+ disabled,
4664
+ onClick,
4665
+ type: "button",
4666
+ children: [
4667
+ label,
4668
+ " ",
4669
+ count > 0 && /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "px-chat-carousel-confirm__count", children: [
4670
+ "(",
4671
+ count,
4672
+ ")"
4673
+ ] })
4674
+ ]
4675
+ }
4676
+ ) });
4677
+ };
4678
+
4679
+ const CarouselDisplay = ({
4680
+ component,
4681
+ eventBus,
4682
+ assistantMessageId = ""
4683
+ }) => {
4684
+ const props = component.props;
4685
+ const {
4686
+ items: initialItems = [],
4687
+ size: sizeProp,
4688
+ selection_mode: selectionMode = "none",
4689
+ confirm_label: confirmLabel = "Confirmar",
4690
+ searchable = false,
4691
+ search_endpoint: searchEndpoint,
4692
+ field_name: fieldName = ""
4693
+ } = props;
4694
+ const isAnswered = component.answered === true;
4695
+ const disabled = isAnswered && selectionMode !== "none";
4696
+ const { store, actions } = React.useMemo(() => {
4697
+ const s = createCarouselStore(initialItems);
4698
+ if (searchable && initialItems.length === 0) {
4699
+ s.set(CAROUSEL_STORE_KEYS.SEARCH_STATUS, "loading");
4700
+ }
4701
+ return { store: s, actions: createCarouselActions(s) };
4702
+ }, []);
4703
+ const items = useStoreState(store, CAROUSEL_STORE_KEYS.ITEMS);
4704
+ const selectedIds = useStoreState(store, CAROUSEL_STORE_KEYS.SELECTED_IDS);
4705
+ const searchStatus = useStoreState(store, CAROUSEL_STORE_KEYS.SEARCH_STATUS);
4706
+ const hasMore = useStoreState(store, CAROUSEL_STORE_KEYS.HAS_MORE);
4707
+ const currentPage = useStoreState(store, CAROUSEL_STORE_KEYS.CURRENT_PAGE);
4708
+ const containerRef = React.useRef(null);
4709
+ const resolvedSize = resolveSize(sizeProp, items.length);
4710
+ const pageLimit = React.useMemo(() => {
4711
+ const width = containerRef.current?.clientWidth ?? window.innerWidth;
4712
+ return calcPageLimit(resolvedSize, width);
4713
+ }, [resolvedSize]);
4714
+ const { emitInteraction, isConfirmed } = useComponentInteraction({
4715
+ eventBus,
4716
+ fieldName,
4717
+ componentType: "carousel",
4718
+ assistantMessageId
4719
+ });
4720
+ const { search, loadNext, loadPrev } = useCarouselSearch({
4721
+ actions,
4722
+ endpoint: searchEndpoint,
4723
+ eventBus,
4724
+ pageLimit
4725
+ });
4726
+ React.useEffect(() => {
4727
+ if (searchable && initialItems.length === 0) {
4728
+ search("", 0);
4729
+ }
4730
+ }, []);
4731
+ const handleSelect = React.useCallback(
4732
+ (item) => {
4733
+ if (disabled || isConfirmed) return;
4734
+ if (selectionMode === "single") {
4735
+ actions.selection.clear();
4736
+ actions.selection.toggle(item.id);
4737
+ emitInteraction(
4738
+ [{ value: item.id, label: item.title || item.id }],
4739
+ item.title || item.id
4740
+ );
4741
+ return;
4742
+ }
4743
+ if (selectionMode === "multiple") {
4744
+ actions.selection.toggle(item.id);
4745
+ }
4746
+ },
4747
+ [selectionMode, disabled, isConfirmed, actions, emitInteraction]
4748
+ );
4749
+ const handleRemove = React.useCallback(
4750
+ (item) => {
4751
+ if (disabled || isConfirmed) return;
4752
+ actions.items.remove(item.id);
4753
+ },
4754
+ [disabled, isConfirmed, actions]
4755
+ );
4756
+ const handleConfirm = React.useCallback(() => {
4757
+ if (disabled || isConfirmed) return;
4758
+ if (selectionMode === "multiple") {
4759
+ const selected = items.filter((i) => selectedIds.includes(i.id));
4760
+ const value = selected.map((i) => ({ value: i.id, label: i.title || i.id }));
4761
+ const label = selected.map((i) => i.title || i.id).join(", ");
4762
+ emitInteraction(value, label);
4763
+ }
4764
+ if (selectionMode === "removable") {
4765
+ const value = items.map((i) => ({ value: i.id, label: i.title || i.id }));
4766
+ const label = items.map((i) => i.title || i.id).join(", ");
4767
+ emitInteraction(value, label);
4768
+ }
4769
+ }, [selectionMode, disabled, isConfirmed, items, selectedIds, emitInteraction]);
4770
+ const confirmDisabled = React.useMemo(() => {
4771
+ if (selectionMode === "multiple") return selectedIds.length === 0;
4772
+ if (selectionMode === "removable") {
4773
+ const originalLen = actions.getOriginalItems().length;
4774
+ return items.length === originalLen;
4775
+ }
4776
+ return true;
4777
+ }, [selectionMode, selectedIds, items, actions]);
4778
+ const showConfirm = (selectionMode === "multiple" || selectionMode === "removable") && !disabled && !isConfirmed;
4779
+ if (selectionMode === "single" && (isConfirmed || isAnswered)) {
4780
+ return null;
4781
+ }
4782
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "px-chat-carousel", ref: containerRef, children: [
4783
+ searchable && /* @__PURE__ */ jsxRuntime.jsx(
4784
+ CarouselSearch,
4785
+ {
4786
+ onSearch: (q) => search(q, 0),
4787
+ loading: searchStatus === "loading"
4788
+ }
4789
+ ),
4790
+ /* @__PURE__ */ jsxRuntime.jsx(
4791
+ CarouselTrack,
4792
+ {
4793
+ currentPage,
4794
+ hasMore,
4795
+ onPrev: loadPrev,
4796
+ onNext: loadNext,
4797
+ children: items.map((item) => /* @__PURE__ */ jsxRuntime.jsx(
4798
+ CarouselCard,
4799
+ {
4800
+ item,
4801
+ size: resolvedSize,
4802
+ selectionMode,
4803
+ isSelected: selectedIds.includes(item.id),
4804
+ disabled: disabled || isConfirmed,
4805
+ onSelect: handleSelect,
4806
+ onRemove: handleRemove
4807
+ },
4808
+ item.id
4809
+ ))
4810
+ }
4811
+ ),
4812
+ showConfirm && /* @__PURE__ */ jsxRuntime.jsx(
4813
+ CarouselConfirm,
4814
+ {
4815
+ label: confirmLabel,
4816
+ count: selectionMode === "multiple" ? selectedIds.length : items.length,
4817
+ disabled: confirmDisabled,
4818
+ onClick: handleConfirm
4819
+ }
4820
+ ),
4821
+ items.length === 0 && searchStatus !== "loading" && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-chat-carousel__empty", children: "Sin resultados" })
4822
+ ] });
4823
+ };
4824
+
4825
+ const COMPONENT_MAP = {
4826
+ select: SelectWithConfirm,
4827
+ select_multiple: SelectMultipleWithConfirm,
4828
+ confirm: ConfirmButton,
4829
+ date_input: DateInputWithConfirm,
4830
+ time_input: TimeInputWithConfirm,
4831
+ input: InputWithConfirm,
4832
+ card: CardDisplay,
4833
+ badge: BadgeDisplay,
4834
+ reactive_form: ReactiveForm,
4835
+ carousel: CarouselDisplay
4836
+ };
4837
+ function renderComponent(props) {
4838
+ const { component } = props;
4839
+ if (component.answered && !DISPLAY_COMPONENTS.has(component.type)) {
4840
+ return null;
4841
+ }
4842
+ const Component = COMPONENT_MAP[component.type];
4843
+ if (!Component) return null;
4844
+ return /* @__PURE__ */ jsxRuntime.jsx(Component, { ...props });
4845
+ }
4846
+
4847
+ const StructuredContent = ({
4848
+ content,
4849
+ eventBus,
4850
+ assistantMessageId,
4851
+ className = ""
4852
+ }) => {
4853
+ const structured = parseContent(content);
4854
+ const markdownContent = structured ? structured.message : content;
4855
+ const rawComponent = structured?.component || null;
4856
+ const components = rawComponent ? Array.isArray(rawComponent) ? rawComponent : [rawComponent] : [];
4857
+ const hasVisibleComponents = components.some((comp) => !comp.answered || DISPLAY_COMPONENTS.has(comp.type));
4858
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `${COMPONENT_PREFIX$1}structured-content ${className}`, children: [
4859
+ markdownContent && /* @__PURE__ */ jsxRuntime.jsx("div", { className: `${COMPONENT_PREFIX$1}assistant-message__markdown${hasVisibleComponents ? ` ${COMPONENT_PREFIX$1}assistant-message__markdown--with-component` : ``}`, children: /* @__PURE__ */ jsxRuntime.jsx(
4860
+ ReactMarkdown,
4861
+ {
4862
+ components: {
4863
+ a: ({ href, children }) => /* @__PURE__ */ jsxRuntime.jsx(
4864
+ Link,
4865
+ {
4866
+ href: href || "#",
4867
+ variant: "primary",
4868
+ size: "medium",
4869
+ weight: "bold",
4870
+ underline: false,
4871
+ children
4872
+ }
4873
+ )
4874
+ },
4875
+ children: markdownContent
4876
+ }
4877
+ ) }),
4878
+ components.length > 0 && /* @__PURE__ */ jsxRuntime.jsx("div", { className: `${COMPONENT_PREFIX$1}structured-content__component`, children: components.map((comp, index) => /* @__PURE__ */ jsxRuntime.jsx(React.Fragment, { children: renderComponent({ component: comp, eventBus, assistantMessageId }) }, `${comp.type}-${index}`)) })
4879
+ ] });
4880
+ };
4881
+
4882
+ const getAttachmentType = (file) => {
4883
+ const mimeType = file.type.toLowerCase();
4884
+ if (mimeType.startsWith(MIME_PREFIXES.AUDIO)) {
4885
+ return AttachmentType.AUDIO;
4886
+ }
4887
+ if (mimeType.startsWith(MIME_PREFIXES.VIDEO)) {
4888
+ return AttachmentType.VIDEO;
4889
+ }
4890
+ if (mimeType.startsWith(MIME_PREFIXES.IMAGE)) {
4891
+ return AttachmentType.IMAGE;
4892
+ }
4893
+ if (mimeType === MIME_TYPES.PDF) {
4894
+ return AttachmentType.PDF;
4895
+ }
4896
+ if (mimeType.includes(MIME_KEYWORDS.DOCUMENT) || mimeType.includes(MIME_KEYWORDS.WORD) || mimeType.includes(MIME_KEYWORDS.EXCEL) || mimeType.includes(MIME_KEYWORDS.POWERPOINT) || mimeType.startsWith(MIME_PREFIXES.TEXT)) {
4897
+ return AttachmentType.DOCUMENT;
4898
+ }
4899
+ return AttachmentType.OTHER;
4900
+ };
4901
+ const filterFilesByType = (files, type) => {
4902
+ const types = Array.isArray(type) ? type : [type];
4903
+ return files.filter((file) => {
4904
+ const fileType = getAttachmentType(file);
4905
+ return types.includes(fileType);
4906
+ });
4907
+ };
4908
+ const getFileUrl = (file) => {
4909
+ if (file.url) {
4910
+ return file.url;
4911
+ }
4912
+ return URL.createObjectURL(file);
4913
+ };
4914
+ const getAudioFiles = (files) => {
4915
+ return filterFilesByType(files, [AttachmentType.AUDIO]);
4916
+ };
4917
+ const getNonAudioFiles = (files) => {
4918
+ return filterFilesByType(files, [
4919
+ AttachmentType.IMAGE,
4920
+ AttachmentType.PDF,
4921
+ AttachmentType.DOCUMENT,
4922
+ AttachmentType.OTHER
4923
+ ]);
4924
+ };
4925
+
4926
+ function deepMerge(target, source) {
3120
4927
  if (typeof target !== "object" || target === null) {
3121
4928
  return source;
3122
4929
  }
@@ -3221,20 +5028,244 @@ const AssistantMessage = ({
3221
5028
  ] }) });
3222
5029
  };
3223
5030
 
3224
- const messages = {
5031
+ const initialState$1 = {
5032
+ // ChatInput (molécula) - Estados del input de chat
5033
+ chatInput: {
5034
+ buttonSend: {
5035
+ disabled: true,
5036
+ // Disabled hasta que haya contenido
5037
+ visible: false
5038
+ // Inicialmente oculto
5039
+ },
5040
+ buttonMicrophone: {
5041
+ disabled: false,
5042
+ visible: true
5043
+ // Inicialmente visible (botón de audio por defecto)
5044
+ },
5045
+ buttonAttachment: {
5046
+ disabled: false
5047
+ },
5048
+ hasText: false,
5049
+ hasAttachments: false
5050
+ },
5051
+ // AssistantThinkingIndicator (molécula) - Estado del indicador
5052
+ assistantThinkingIndicator: {
5053
+ visible: false,
5054
+ agentName: void 0,
5055
+ agentLabel: void 0,
5056
+ toolName: void 0
5057
+ },
5058
+ // ScrollButton (átomo) - Estado del botón de scroll
5059
+ scrollButton: {
5060
+ visible: false
5061
+ },
5062
+ // VirtualKeyboard - Estado del teclado virtual
5063
+ virtualKeyboard: {
5064
+ isOpen: false
5065
+ },
5066
+ // Textarea - Estado del textarea del chat
5067
+ textarea: {
5068
+ isFocused: false,
5069
+ isEmpty: true,
5070
+ shouldPreventKeyboard: false,
5071
+ shouldFocus: false,
5072
+ shouldBlur: false
5073
+ },
5074
+ // Scroll to top trigger
5075
+ scrollToTop: {
5076
+ pending: false
5077
+ }
5078
+ };
5079
+ const chatStore = createStore(initialState$1);
5080
+ const setChatStore = createStoreMerger(chatStore);
5081
+ const subscribeChatProperty = createDeepPropertySubscriber(chatStore);
5082
+
5083
+ const CHAT_STORE_KEYS = {
5084
+ // ChatInput relacionado
5085
+ CHAT_INPUT: "chatInput",
5086
+ // AssistantThinkingIndicator relacionado
5087
+ ASSISTANT_THINKING_INDICATOR: "assistantThinkingIndicator",
5088
+ // ScrollButton relacionado
5089
+ SCROLL_BUTTON: "scrollButton",
5090
+ // VirtualKeyboard relacionado
5091
+ VIRTUAL_KEYBOARD: "virtualKeyboard",
5092
+ // Textarea relacionado
5093
+ TEXTAREA: "textarea",
5094
+ // Scroll to top trigger
5095
+ SCROLL_TO_TOP: "scrollToTop"
5096
+ };
5097
+
5098
+ const textareaActions = {
5099
+ focus: () => setChatStore(CHAT_STORE_KEYS.TEXTAREA, { shouldFocus: true }),
5100
+ blur: () => setChatStore(CHAT_STORE_KEYS.TEXTAREA, { shouldBlur: true }),
5101
+ setFocused: (isFocused) => setChatStore(CHAT_STORE_KEYS.TEXTAREA, { isFocused }),
5102
+ setEmpty: (isEmpty) => setChatStore(CHAT_STORE_KEYS.TEXTAREA, { isEmpty }),
5103
+ setShouldPreventKeyboard: (shouldPrevent) => setChatStore(CHAT_STORE_KEYS.TEXTAREA, { shouldPreventKeyboard: shouldPrevent }),
5104
+ resetTriggers: () => setChatStore(CHAT_STORE_KEYS.TEXTAREA, { shouldFocus: false, shouldBlur: false }),
5105
+ maintainFocusAfterSend: () => {
5106
+ setTimeout(() => {
5107
+ setChatStore(CHAT_STORE_KEYS.TEXTAREA, { shouldFocus: true });
5108
+ }, 10);
5109
+ setTimeout(() => {
5110
+ setChatStore(CHAT_STORE_KEYS.TEXTAREA, { shouldFocus: true });
5111
+ }, 50);
5112
+ },
5113
+ preserveFocusWithKeyboard: () => {
5114
+ setChatStore(CHAT_STORE_KEYS.TEXTAREA, { shouldFocus: true });
5115
+ setTimeout(() => {
5116
+ setChatStore(CHAT_STORE_KEYS.TEXTAREA, { shouldFocus: true });
5117
+ }, 10);
5118
+ setTimeout(() => {
5119
+ setChatStore(CHAT_STORE_KEYS.TEXTAREA, { shouldFocus: true });
5120
+ }, 50);
5121
+ }
5122
+ };
5123
+ const keyboardActions = {
5124
+ setOpen: (isOpen) => setChatStore(CHAT_STORE_KEYS.VIRTUAL_KEYBOARD, { isOpen }),
5125
+ open: () => setChatStore(CHAT_STORE_KEYS.VIRTUAL_KEYBOARD, { isOpen: true }),
5126
+ close: () => setChatStore(CHAT_STORE_KEYS.VIRTUAL_KEYBOARD, { isOpen: false })
5127
+ };
5128
+ const chatInputActions = {
5129
+ setSendDisabled: (disabled) => {
5130
+ const currentState = chatStore.get(CHAT_STORE_KEYS.CHAT_INPUT);
5131
+ setChatStore(CHAT_STORE_KEYS.CHAT_INPUT, {
5132
+ buttonSend: {
5133
+ disabled,
5134
+ visible: currentState.buttonSend.visible
5135
+ }
5136
+ });
5137
+ },
5138
+ setMicDisabled: (disabled) => {
5139
+ const currentState = chatStore.get(CHAT_STORE_KEYS.CHAT_INPUT);
5140
+ setChatStore(CHAT_STORE_KEYS.CHAT_INPUT, {
5141
+ buttonMicrophone: {
5142
+ disabled,
5143
+ visible: currentState.buttonMicrophone.visible
5144
+ }
5145
+ });
5146
+ },
5147
+ setAttachDisabled: (disabled) => setChatStore(CHAT_STORE_KEYS.CHAT_INPUT, { buttonAttachment: { disabled } }),
5148
+ setSendVisible: (visible) => {
5149
+ const currentState = chatStore.get(CHAT_STORE_KEYS.CHAT_INPUT);
5150
+ setChatStore(CHAT_STORE_KEYS.CHAT_INPUT, {
5151
+ buttonSend: {
5152
+ visible,
5153
+ disabled: currentState.buttonSend.disabled
5154
+ }
5155
+ });
5156
+ },
5157
+ setMicVisible: (visible) => {
5158
+ const currentState = chatStore.get(CHAT_STORE_KEYS.CHAT_INPUT);
5159
+ setChatStore(CHAT_STORE_KEYS.CHAT_INPUT, {
5160
+ buttonMicrophone: {
5161
+ visible,
5162
+ disabled: currentState.buttonMicrophone.disabled
5163
+ }
5164
+ });
5165
+ },
5166
+ setHasText: (hasText) => setChatStore(CHAT_STORE_KEYS.CHAT_INPUT, { hasText }),
5167
+ setHasAttachments: (hasAttachments) => setChatStore(CHAT_STORE_KEYS.CHAT_INPUT, { hasAttachments }),
5168
+ updateButtonVisibility: (hasText, hasAttachments) => {
5169
+ const shouldShowSend = hasText || hasAttachments;
5170
+ const shouldShowMic = !hasText && !hasAttachments;
5171
+ const isThinking = chatStore.get(CHAT_STORE_KEYS.ASSISTANT_THINKING_INDICATOR).visible;
5172
+ const hasContent = hasText || hasAttachments;
5173
+ const currentState = chatStore.get(CHAT_STORE_KEYS.CHAT_INPUT);
5174
+ setChatStore(CHAT_STORE_KEYS.CHAT_INPUT, {
5175
+ hasText,
5176
+ hasAttachments,
5177
+ buttonSend: {
5178
+ visible: shouldShowSend,
5179
+ disabled: isThinking || !hasContent
5180
+ },
5181
+ buttonMicrophone: {
5182
+ visible: shouldShowMic,
5183
+ disabled: currentState.buttonMicrophone.disabled
5184
+ }
5185
+ });
5186
+ }
5187
+ };
5188
+ const thinkingActions = {
5189
+ setVisible: (visible) => setChatStore(CHAT_STORE_KEYS.ASSISTANT_THINKING_INDICATOR, { visible }),
5190
+ show: () => setChatStore(CHAT_STORE_KEYS.ASSISTANT_THINKING_INDICATOR, { visible: true }),
5191
+ hide: () => setChatStore(CHAT_STORE_KEYS.ASSISTANT_THINKING_INDICATOR, {
5192
+ visible: false,
5193
+ agentName: void 0,
5194
+ agentLabel: void 0,
5195
+ toolName: void 0
5196
+ }),
5197
+ setThinking: (isThinking) => {
5198
+ setChatStore(CHAT_STORE_KEYS.ASSISTANT_THINKING_INDICATOR, { visible: isThinking });
5199
+ },
5200
+ setAgentName: (agentName) => setChatStore(CHAT_STORE_KEYS.ASSISTANT_THINKING_INDICATOR, { agentName }),
5201
+ setAgentLabel: (agentLabel) => setChatStore(CHAT_STORE_KEYS.ASSISTANT_THINKING_INDICATOR, { agentLabel }),
5202
+ setToolName: (toolName) => setChatStore(CHAT_STORE_KEYS.ASSISTANT_THINKING_INDICATOR, { toolName })
5203
+ };
5204
+ const scrollButtonActions = {
5205
+ setVisible: (visible) => setChatStore(CHAT_STORE_KEYS.SCROLL_BUTTON, { visible }),
5206
+ show: () => setChatStore(CHAT_STORE_KEYS.SCROLL_BUTTON, { visible: true }),
5207
+ hide: () => setChatStore(CHAT_STORE_KEYS.SCROLL_BUTTON, { visible: false })
5208
+ };
5209
+ const scrollToTopActions = {
5210
+ activate: () => setChatStore(CHAT_STORE_KEYS.SCROLL_TO_TOP, { pending: true }),
5211
+ reset: () => setChatStore(CHAT_STORE_KEYS.SCROLL_TO_TOP, { pending: false })
5212
+ };
5213
+ const combinedActions = {
5214
+ prepareFileButtonClick: (isEmpty, isKeyboardOpen) => {
5215
+ if (!isKeyboardOpen && isEmpty) {
5216
+ textareaActions.setShouldPreventKeyboard(true);
5217
+ textareaActions.blur();
5218
+ }
5219
+ },
5220
+ initializeChat: () => {
5221
+ textareaActions.setEmpty(true);
5222
+ textareaActions.setFocused(false);
5223
+ keyboardActions.close();
5224
+ thinkingActions.hide();
5225
+ scrollButtonActions.hide();
5226
+ chatInputActions.updateButtonVisibility(false, false);
5227
+ },
5228
+ handleMessageSend: () => {
5229
+ textareaActions.maintainFocusAfterSend();
5230
+ }
5231
+ };
5232
+
5233
+ const fallbackMessages = {
3225
5234
  short: ["Revisando...", "Procesando...", "Analizando..."],
3226
5235
  medium: ["Analizando tu consulta...", "Estoy viendo c\xF3mo resolverlo...", "Buscando la mejor manera de ayudarte..."],
3227
5236
  long: ["Sigo con esto. Un momento m\xE1s.", "Estoy en eso, ya te respondo.", "Ya casi lo tengo."],
3228
5237
  veryLong: ["Esto est\xE1 tardando mas de lo habitual.", "Esto lleva un poco m\xE1s de tiempo.", "Lleva un poco m\xE1s de lo normal."]
3229
5238
  };
3230
5239
  const getRandomMessage = (category) => {
3231
- const categoryMessages = messages[category];
5240
+ const categoryMessages = fallbackMessages[category];
3232
5241
  return categoryMessages[Math.floor(Math.random() * categoryMessages.length)];
3233
5242
  };
3234
5243
  const AssistantThinkingIndicator = () => {
3235
5244
  const { showRoleLabels } = useChatConfig();
3236
- const [displayedMessage, setDisplayedMessage] = React.useState(getRandomMessage("short"));
5245
+ const [fallbackMessage, setFallbackMessage] = React.useState(getRandomMessage("short"));
3237
5246
  const [elapsedSeconds, setElapsedSeconds] = React.useState(0);
5247
+ const [agentLabel, setAgentLabel] = React.useState(
5248
+ chatStore.get(CHAT_STORE_KEYS.ASSISTANT_THINKING_INDICATOR).agentLabel
5249
+ );
5250
+ const [toolName, setToolName] = React.useState(
5251
+ chatStore.get(CHAT_STORE_KEYS.ASSISTANT_THINKING_INDICATOR).toolName
5252
+ );
5253
+ React.useEffect(() => {
5254
+ const unsubLabel = subscribeChatProperty(
5255
+ CHAT_STORE_KEYS.ASSISTANT_THINKING_INDICATOR,
5256
+ "agentLabel",
5257
+ setAgentLabel
5258
+ );
5259
+ const unsubTool = subscribeChatProperty(
5260
+ CHAT_STORE_KEYS.ASSISTANT_THINKING_INDICATOR,
5261
+ "toolName",
5262
+ setToolName
5263
+ );
5264
+ return () => {
5265
+ unsubLabel();
5266
+ unsubTool();
5267
+ };
5268
+ }, []);
3238
5269
  React.useEffect(() => {
3239
5270
  const timer = setInterval(() => {
3240
5271
  setElapsedSeconds((prev) => prev + 1);
@@ -3243,13 +5274,14 @@ const AssistantThinkingIndicator = () => {
3243
5274
  }, []);
3244
5275
  React.useEffect(() => {
3245
5276
  if (elapsedSeconds === 6) {
3246
- setDisplayedMessage(getRandomMessage("medium"));
5277
+ setFallbackMessage(getRandomMessage("medium"));
3247
5278
  } else if (elapsedSeconds === 13) {
3248
- setDisplayedMessage(getRandomMessage("long"));
5279
+ setFallbackMessage(getRandomMessage("long"));
3249
5280
  } else if (elapsedSeconds === 21) {
3250
- setDisplayedMessage(getRandomMessage("veryLong"));
5281
+ setFallbackMessage(getRandomMessage("veryLong"));
3251
5282
  }
3252
5283
  }, [elapsedSeconds]);
5284
+ const displayedMessage = agentLabel ? toolName ? `${agentLabel} \u2014 ${toolName}` : `${agentLabel}...` : fallbackMessage;
3253
5285
  return /* @__PURE__ */ jsxRuntime.jsx("div", { className: `${COMPONENT_PREFIX$1}assistant-thinking-indicator`, children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: `${COMPONENT_PREFIX$1}assistant-thinking-indicator__content`, children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `${COMPONENT_PREFIX$1}assistant-thinking-indicator__bubble`, children: [
3254
5286
  showRoleLabels && /* @__PURE__ */ jsxRuntime.jsx(Text, { variant: "caption", color: "secondary", className: `${COMPONENT_PREFIX$1}assistant-thinking-indicator__role`, children: "Assistant" }),
3255
5287
  /* @__PURE__ */ jsxRuntime.jsx("div", { className: `${COMPONENT_PREFIX$1}assistant-thinking-indicator__text-container`, children: /* @__PURE__ */ jsxRuntime.jsx(Text, { variant: "body", color: "primary", className: `${COMPONENT_PREFIX$1}assistant-thinking-indicator__wave-text`, children: displayedMessage.split("").map((char, index) => /* @__PURE__ */ jsxRuntime.jsx(
@@ -3692,203 +5724,6 @@ const FullscreenViewer = ({
3692
5724
  );
3693
5725
  };
3694
5726
 
3695
- const initialState$1 = {
3696
- // ChatInput (molécula) - Estados del input de chat
3697
- chatInput: {
3698
- buttonSend: {
3699
- disabled: true,
3700
- // Disabled hasta que haya contenido
3701
- visible: false
3702
- // Inicialmente oculto
3703
- },
3704
- buttonMicrophone: {
3705
- disabled: false,
3706
- visible: true
3707
- // Inicialmente visible (botón de audio por defecto)
3708
- },
3709
- buttonAttachment: {
3710
- disabled: false
3711
- },
3712
- hasText: false,
3713
- hasAttachments: false
3714
- },
3715
- // AssistantThinkingIndicator (molécula) - Estado del indicador
3716
- assistantThinkingIndicator: {
3717
- visible: false
3718
- },
3719
- // ScrollButton (átomo) - Estado del botón de scroll
3720
- scrollButton: {
3721
- visible: false
3722
- },
3723
- // VirtualKeyboard - Estado del teclado virtual
3724
- virtualKeyboard: {
3725
- isOpen: false
3726
- },
3727
- // Textarea - Estado del textarea del chat
3728
- textarea: {
3729
- isFocused: false,
3730
- isEmpty: true,
3731
- shouldPreventKeyboard: false,
3732
- shouldFocus: false,
3733
- shouldBlur: false
3734
- },
3735
- // Scroll to top trigger
3736
- scrollToTop: {
3737
- pending: false
3738
- }
3739
- };
3740
- const chatStore = createStore(initialState$1);
3741
- const setChatStore = createStoreMerger(chatStore);
3742
- const subscribeChatProperty = createDeepPropertySubscriber(chatStore);
3743
-
3744
- const CHAT_STORE_KEYS = {
3745
- // ChatInput relacionado
3746
- CHAT_INPUT: "chatInput",
3747
- // AssistantThinkingIndicator relacionado
3748
- ASSISTANT_THINKING_INDICATOR: "assistantThinkingIndicator",
3749
- // ScrollButton relacionado
3750
- SCROLL_BUTTON: "scrollButton",
3751
- // VirtualKeyboard relacionado
3752
- VIRTUAL_KEYBOARD: "virtualKeyboard",
3753
- // Textarea relacionado
3754
- TEXTAREA: "textarea",
3755
- // Scroll to top trigger
3756
- SCROLL_TO_TOP: "scrollToTop"
3757
- };
3758
-
3759
- const textareaActions = {
3760
- focus: () => setChatStore(CHAT_STORE_KEYS.TEXTAREA, { shouldFocus: true }),
3761
- blur: () => setChatStore(CHAT_STORE_KEYS.TEXTAREA, { shouldBlur: true }),
3762
- setFocused: (isFocused) => setChatStore(CHAT_STORE_KEYS.TEXTAREA, { isFocused }),
3763
- setEmpty: (isEmpty) => setChatStore(CHAT_STORE_KEYS.TEXTAREA, { isEmpty }),
3764
- setShouldPreventKeyboard: (shouldPrevent) => setChatStore(CHAT_STORE_KEYS.TEXTAREA, { shouldPreventKeyboard: shouldPrevent }),
3765
- resetTriggers: () => setChatStore(CHAT_STORE_KEYS.TEXTAREA, { shouldFocus: false, shouldBlur: false }),
3766
- maintainFocusAfterSend: () => {
3767
- setTimeout(() => {
3768
- setChatStore(CHAT_STORE_KEYS.TEXTAREA, { shouldFocus: true });
3769
- }, 10);
3770
- setTimeout(() => {
3771
- setChatStore(CHAT_STORE_KEYS.TEXTAREA, { shouldFocus: true });
3772
- }, 50);
3773
- },
3774
- preserveFocusWithKeyboard: () => {
3775
- setChatStore(CHAT_STORE_KEYS.TEXTAREA, { shouldFocus: true });
3776
- setTimeout(() => {
3777
- setChatStore(CHAT_STORE_KEYS.TEXTAREA, { shouldFocus: true });
3778
- }, 10);
3779
- setTimeout(() => {
3780
- setChatStore(CHAT_STORE_KEYS.TEXTAREA, { shouldFocus: true });
3781
- }, 50);
3782
- }
3783
- };
3784
- const keyboardActions = {
3785
- setOpen: (isOpen) => setChatStore(CHAT_STORE_KEYS.VIRTUAL_KEYBOARD, { isOpen }),
3786
- open: () => setChatStore(CHAT_STORE_KEYS.VIRTUAL_KEYBOARD, { isOpen: true }),
3787
- close: () => setChatStore(CHAT_STORE_KEYS.VIRTUAL_KEYBOARD, { isOpen: false })
3788
- };
3789
- const chatInputActions = {
3790
- setSendDisabled: (disabled) => {
3791
- const currentState = chatStore.get(CHAT_STORE_KEYS.CHAT_INPUT);
3792
- setChatStore(CHAT_STORE_KEYS.CHAT_INPUT, {
3793
- buttonSend: {
3794
- disabled,
3795
- visible: currentState.buttonSend.visible
3796
- }
3797
- });
3798
- },
3799
- setMicDisabled: (disabled) => {
3800
- const currentState = chatStore.get(CHAT_STORE_KEYS.CHAT_INPUT);
3801
- setChatStore(CHAT_STORE_KEYS.CHAT_INPUT, {
3802
- buttonMicrophone: {
3803
- disabled,
3804
- visible: currentState.buttonMicrophone.visible
3805
- }
3806
- });
3807
- },
3808
- setAttachDisabled: (disabled) => setChatStore(CHAT_STORE_KEYS.CHAT_INPUT, { buttonAttachment: { disabled } }),
3809
- setSendVisible: (visible) => {
3810
- const currentState = chatStore.get(CHAT_STORE_KEYS.CHAT_INPUT);
3811
- setChatStore(CHAT_STORE_KEYS.CHAT_INPUT, {
3812
- buttonSend: {
3813
- visible,
3814
- disabled: currentState.buttonSend.disabled
3815
- }
3816
- });
3817
- },
3818
- setMicVisible: (visible) => {
3819
- const currentState = chatStore.get(CHAT_STORE_KEYS.CHAT_INPUT);
3820
- setChatStore(CHAT_STORE_KEYS.CHAT_INPUT, {
3821
- buttonMicrophone: {
3822
- visible,
3823
- disabled: currentState.buttonMicrophone.disabled
3824
- }
3825
- });
3826
- },
3827
- setHasText: (hasText) => setChatStore(CHAT_STORE_KEYS.CHAT_INPUT, { hasText }),
3828
- setHasAttachments: (hasAttachments) => setChatStore(CHAT_STORE_KEYS.CHAT_INPUT, { hasAttachments }),
3829
- updateButtonVisibility: (hasText, hasAttachments) => {
3830
- const shouldShowSend = hasText || hasAttachments;
3831
- const shouldShowMic = !hasText && !hasAttachments;
3832
- const isThinking = chatStore.get(CHAT_STORE_KEYS.ASSISTANT_THINKING_INDICATOR).visible;
3833
- const hasContent = hasText || hasAttachments;
3834
- const currentState = chatStore.get(CHAT_STORE_KEYS.CHAT_INPUT);
3835
- setChatStore(CHAT_STORE_KEYS.CHAT_INPUT, {
3836
- hasText,
3837
- hasAttachments,
3838
- buttonSend: {
3839
- visible: shouldShowSend,
3840
- disabled: isThinking || !hasContent
3841
- },
3842
- buttonMicrophone: {
3843
- visible: shouldShowMic,
3844
- disabled: currentState.buttonMicrophone.disabled
3845
- }
3846
- });
3847
- }
3848
- };
3849
- const thinkingActions = {
3850
- setVisible: (visible) => setChatStore(CHAT_STORE_KEYS.ASSISTANT_THINKING_INDICATOR, { visible }),
3851
- show: () => setChatStore(CHAT_STORE_KEYS.ASSISTANT_THINKING_INDICATOR, { visible: true }),
3852
- hide: () => setChatStore(CHAT_STORE_KEYS.ASSISTANT_THINKING_INDICATOR, { visible: false }),
3853
- setThinking: (isThinking) => {
3854
- setChatStore(CHAT_STORE_KEYS.ASSISTANT_THINKING_INDICATOR, { visible: isThinking });
3855
- if (isThinking) {
3856
- chatInputActions.setSendDisabled(true);
3857
- } else {
3858
- const currentInput = chatStore.get(CHAT_STORE_KEYS.CHAT_INPUT);
3859
- chatInputActions.updateButtonVisibility(currentInput.hasText, currentInput.hasAttachments);
3860
- }
3861
- }
3862
- };
3863
- const scrollButtonActions = {
3864
- setVisible: (visible) => setChatStore(CHAT_STORE_KEYS.SCROLL_BUTTON, { visible }),
3865
- show: () => setChatStore(CHAT_STORE_KEYS.SCROLL_BUTTON, { visible: true }),
3866
- hide: () => setChatStore(CHAT_STORE_KEYS.SCROLL_BUTTON, { visible: false })
3867
- };
3868
- const scrollToTopActions = {
3869
- activate: () => setChatStore(CHAT_STORE_KEYS.SCROLL_TO_TOP, { pending: true }),
3870
- reset: () => setChatStore(CHAT_STORE_KEYS.SCROLL_TO_TOP, { pending: false })
3871
- };
3872
- const combinedActions = {
3873
- prepareFileButtonClick: (isEmpty, isKeyboardOpen) => {
3874
- if (!isKeyboardOpen && isEmpty) {
3875
- textareaActions.setShouldPreventKeyboard(true);
3876
- textareaActions.blur();
3877
- }
3878
- },
3879
- initializeChat: () => {
3880
- textareaActions.setEmpty(true);
3881
- textareaActions.setFocused(false);
3882
- keyboardActions.close();
3883
- thinkingActions.hide();
3884
- scrollButtonActions.hide();
3885
- chatInputActions.updateButtonVisibility(false, false);
3886
- },
3887
- handleMessageSend: () => {
3888
- textareaActions.maintainFocusAfterSend();
3889
- }
3890
- };
3891
-
3892
5727
  const ChatInput = React.forwardRef(({
3893
5728
  value,
3894
5729
  onChange,
@@ -4813,6 +6648,15 @@ const useChatStore = () => {
4813
6648
  const [showThinking, setShowThinking] = React.useState(
4814
6649
  chatStore.get(CHAT_STORE_KEYS.ASSISTANT_THINKING_INDICATOR).visible
4815
6650
  );
6651
+ const [agentName, setAgentName] = React.useState(
6652
+ chatStore.get(CHAT_STORE_KEYS.ASSISTANT_THINKING_INDICATOR).agentName
6653
+ );
6654
+ const [agentLabel, setAgentLabel] = React.useState(
6655
+ chatStore.get(CHAT_STORE_KEYS.ASSISTANT_THINKING_INDICATOR).agentLabel
6656
+ );
6657
+ const [toolName, setToolName] = React.useState(
6658
+ chatStore.get(CHAT_STORE_KEYS.ASSISTANT_THINKING_INDICATOR).toolName
6659
+ );
4816
6660
  const [scrollButtonState, setScrollButtonState] = React.useState(
4817
6661
  chatStore.get(CHAT_STORE_KEYS.SCROLL_BUTTON)
4818
6662
  );
@@ -4825,6 +6669,21 @@ const useChatStore = () => {
4825
6669
  "visible",
4826
6670
  setShowThinking
4827
6671
  );
6672
+ const unsubAgentName = subscribeChatProperty(
6673
+ CHAT_STORE_KEYS.ASSISTANT_THINKING_INDICATOR,
6674
+ "agentName",
6675
+ setAgentName
6676
+ );
6677
+ const unsubAgentLabel = subscribeChatProperty(
6678
+ CHAT_STORE_KEYS.ASSISTANT_THINKING_INDICATOR,
6679
+ "agentLabel",
6680
+ setAgentLabel
6681
+ );
6682
+ const unsubToolName = subscribeChatProperty(
6683
+ CHAT_STORE_KEYS.ASSISTANT_THINKING_INDICATOR,
6684
+ "toolName",
6685
+ setToolName
6686
+ );
4828
6687
  const unsubScrollButton = subscribeChatProperty(
4829
6688
  CHAT_STORE_KEYS.SCROLL_BUTTON,
4830
6689
  "",
@@ -4837,12 +6696,18 @@ const useChatStore = () => {
4837
6696
  );
4838
6697
  return () => {
4839
6698
  unsubThinking();
6699
+ unsubAgentName();
6700
+ unsubAgentLabel();
6701
+ unsubToolName();
4840
6702
  unsubScrollButton();
4841
6703
  unsubScrollToTop();
4842
6704
  };
4843
6705
  }, []);
4844
6706
  return {
4845
6707
  showThinking,
6708
+ agentName,
6709
+ agentLabel,
6710
+ toolName,
4846
6711
  scrollButtonState,
4847
6712
  scrollToTopPending
4848
6713
  };
@@ -4870,9 +6735,9 @@ const useChatHandlers = ({
4870
6735
  clearAttachments,
4871
6736
  scrollToLastUserMessage
4872
6737
  }) => {
4873
- const isThinking = () => chatStore.get(CHAT_STORE_KEYS.ASSISTANT_THINKING_INDICATOR).visible;
6738
+ const isInputDisabled = () => chatStore.get(CHAT_STORE_KEYS.CHAT_INPUT).buttonSend.disabled;
4874
6739
  const handleSendWithFiles = (content, files) => {
4875
- if (isThinking()) return;
6740
+ if (isInputDisabled()) return;
4876
6741
  if (!content.trim() && (!files || files.length === 0)) return;
4877
6742
  combinedActions.handleMessageSend();
4878
6743
  onSend(content, files);
@@ -4883,7 +6748,7 @@ const useChatHandlers = ({
4883
6748
  const handleInputKeyDown = (e, inputValue, attachments) => {
4884
6749
  if (e.key === "Enter" && !e.shiftKey) {
4885
6750
  e.preventDefault();
4886
- if (isThinking()) return;
6751
+ if (isInputDisabled()) return;
4887
6752
  handleSendWithFiles(inputValue, attachments);
4888
6753
  }
4889
6754
  };
@@ -5220,12 +7085,21 @@ const Chat = ({
5220
7085
  const unsubComponent = eventBus.on(CHAT_EVENT.COMPONENT_INTERACTION, () => {
5221
7086
  scrollToTopActions.activate();
5222
7087
  });
7088
+ const unsubInputDisabled = eventBus.on(CHAT_EVENT.INPUT_DISABLED, ({ disabled }) => {
7089
+ if (disabled) {
7090
+ chatInputActions.setSendDisabled(true);
7091
+ } else {
7092
+ const { hasText, hasAttachments } = chatStore.get(CHAT_STORE_KEYS.CHAT_INPUT);
7093
+ chatInputActions.updateButtonVisibility(hasText, hasAttachments);
7094
+ }
7095
+ });
5223
7096
  return () => {
5224
7097
  unsubMessages();
5225
7098
  unsubHeader();
5226
7099
  unsubPlaceholder();
5227
7100
  unsubThinking();
5228
7101
  unsubComponent();
7102
+ unsubInputDisabled();
5229
7103
  };
5230
7104
  }, [eventBus]);
5231
7105
  const handleSend = (content, files) => {
@@ -5310,33 +7184,37 @@ const Chat = ({
5310
7184
  ref: messagesContainerRef,
5311
7185
  onClick: handleMainClick,
5312
7186
  children: [
5313
- messageGroups.map((group, groupIndex) => /* @__PURE__ */ jsxRuntime.jsxs(React.Fragment, { children: [
5314
- /* @__PURE__ */ jsxRuntime.jsx(DateDivider, { date: group.date }),
5315
- group.messages.map((msg, msgIndex) => {
5316
- const key = msg.id ?? `${groupIndex}-${msgIndex}`;
5317
- return msg.role === "user" ? /* @__PURE__ */ jsxRuntime.jsx(
5318
- UserMessage,
5319
- {
5320
- content: msg.content,
5321
- timestamp: msg.timestamp,
5322
- status: msg.status,
5323
- onRetry: msg.status === "failed" ? () => handleRetry(msg) : void 0,
5324
- files: msg.files
5325
- },
5326
- key
5327
- ) : /* @__PURE__ */ jsxRuntime.jsx(
5328
- AssistantMessage,
5329
- {
5330
- content: msg.content,
5331
- timestamp: msg.timestamp,
5332
- files: msg.files,
5333
- eventBus,
5334
- messageId: msg.id
5335
- },
5336
- key
5337
- );
5338
- })
5339
- ] }, `${group.date.getTime()}-${groupIndex}`)),
7187
+ messageGroups.map((group, groupIndex) => {
7188
+ const isToday = group.date.toDateString() === (/* @__PURE__ */ new Date()).toDateString();
7189
+ const showDivider = !(messageGroups.length === 1 && isToday);
7190
+ return /* @__PURE__ */ jsxRuntime.jsxs(React.Fragment, { children: [
7191
+ showDivider && /* @__PURE__ */ jsxRuntime.jsx(DateDivider, { date: group.date }),
7192
+ group.messages.map((msg, msgIndex) => {
7193
+ const key = msg.id ?? `${groupIndex}-${msgIndex}`;
7194
+ return msg.role === "user" ? /* @__PURE__ */ jsxRuntime.jsx(
7195
+ UserMessage,
7196
+ {
7197
+ content: msg.content,
7198
+ timestamp: msg.timestamp,
7199
+ status: msg.status,
7200
+ onRetry: msg.status === "failed" ? () => handleRetry(msg) : void 0,
7201
+ files: msg.files
7202
+ },
7203
+ key
7204
+ ) : /* @__PURE__ */ jsxRuntime.jsx(
7205
+ AssistantMessage,
7206
+ {
7207
+ content: msg.content,
7208
+ timestamp: msg.timestamp,
7209
+ files: msg.files,
7210
+ eventBus,
7211
+ messageId: msg.id
7212
+ },
7213
+ key
7214
+ );
7215
+ })
7216
+ ] }, `${group.date.getTime()}-${groupIndex}`);
7217
+ }),
5340
7218
  showThinking && /* @__PURE__ */ jsxRuntime.jsx(AssistantThinkingIndicator, {}),
5341
7219
  /* @__PURE__ */ jsxRuntime.jsx("div", { ref: messagesEndRef })
5342
7220
  ]