pixelon 0.3.25 → 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 +67 -0
  223. package/dist/index(1).esm.js +19378 -0
  224. package/dist/index(1).js +19487 -0
  225. package/dist/index.esm.js +2218 -348
  226. package/dist/index.js +2218 -348
  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.esm.js CHANGED
@@ -6,9 +6,9 @@ import ReactMarkdown from 'react-markdown';
6
6
  import DatePicker, { registerLocale } from 'react-datepicker';
7
7
  import { es } from 'date-fns/locale';
8
8
  import 'react-datepicker/dist/react-datepicker.css';
9
+ import * as yup from 'yup';
9
10
  import { QRCodeCanvas, QRCodeSVG } from 'qrcode.react';
10
11
  import { Controller, useFormContext, useForm, useWatch, FormProvider } from 'react-hook-form';
11
- import * as yup from 'yup';
12
12
  import { Link as Link$1 } from 'react-router-dom';
13
13
  import { yupResolver } from '@hookform/resolvers/yup';
14
14
 
@@ -1618,7 +1618,7 @@ function parseContent(content) {
1618
1618
  return null;
1619
1619
  }
1620
1620
 
1621
- const DISPLAY_COMPONENTS = /* @__PURE__ */ new Set(["card", "badge"]);
1621
+ const DISPLAY_COMPONENTS = /* @__PURE__ */ new Set(["card", "badge", "reactive_form", "carousel"]);
1622
1622
 
1623
1623
  const useAppHeight$5 = () => {
1624
1624
  useEffect(() => {
@@ -1658,6 +1658,7 @@ const Drawer$1 = ({
1658
1658
  title,
1659
1659
  headerExtra,
1660
1660
  footer,
1661
+ placement = "bottom",
1661
1662
  showCloseButton = true,
1662
1663
  closeOnOverlayClick = true,
1663
1664
  closeOnEscape = true,
@@ -1709,6 +1710,7 @@ const Drawer$1 = ({
1709
1710
  const drawerClasses = [
1710
1711
  `${prefix}drawer`,
1711
1712
  animating && `${prefix}drawer--open`,
1713
+ `${prefix}drawer--${placement}`,
1712
1714
  className
1713
1715
  ].filter(Boolean).join(" ");
1714
1716
  return createPortal(
@@ -1775,7 +1777,14 @@ const CHAT_EVENT = {
1775
1777
  PLACEHOLDER_UPDATED: "placeholderUpdated",
1776
1778
  THINKING_UPDATED: "thinkingUpdated",
1777
1779
  INPUT_DISABLED: "inputDisabled",
1778
- CLOSE: "close"
1780
+ CLOSE: "close",
1781
+ FETCH_REQUEST: "fetchRequest",
1782
+ FETCH_RESPONSE: "fetchResponse",
1783
+ FORM_SUBMIT: "formSubmit",
1784
+ FORM_TRACE: "formTrace",
1785
+ AGENT_EVENT: "agentEvent",
1786
+ STREAM_CHUNK: "streamChunk",
1787
+ MESSAGE_SAVED: "messageSaved"
1779
1788
  };
1780
1789
  const chatEventBus = createEventBus();
1781
1790
 
@@ -1802,13 +1811,13 @@ function useComponentInteraction({
1802
1811
  return { emitInteraction, isConfirmed };
1803
1812
  }
1804
1813
 
1805
- const MOBILE_BREAKPOINT$3 = 640;
1806
- const useIsMobile$4 = () => {
1814
+ const MOBILE_BREAKPOINT$4 = 640;
1815
+ const useIsMobile$5 = () => {
1807
1816
  const [isMobile, setIsMobile] = useState(
1808
- typeof window !== "undefined" ? window.innerWidth < MOBILE_BREAKPOINT$3 : false
1817
+ typeof window !== "undefined" ? window.innerWidth < MOBILE_BREAKPOINT$4 : false
1809
1818
  );
1810
1819
  useEffect(() => {
1811
- const mq = window.matchMedia(`(max-width: ${MOBILE_BREAKPOINT$3 - 1}px)`);
1820
+ const mq = window.matchMedia(`(max-width: ${MOBILE_BREAKPOINT$4 - 1}px)`);
1812
1821
  const handler = (e) => setIsMobile(e.matches);
1813
1822
  mq.addEventListener("change", handler);
1814
1823
  return () => mq.removeEventListener("change", handler);
@@ -1824,7 +1833,7 @@ const SelectWithConfirm = ({
1824
1833
  const [isDrawerOpen, setIsDrawerOpen] = useState(false);
1825
1834
  const [searchValue, setSearchValue] = useState("");
1826
1835
  const searchInputRef = useRef(null);
1827
- const isMobile = useIsMobile$4();
1836
+ const isMobile = useIsMobile$5();
1828
1837
  const { field_name, value, ...componentProps } = component.props;
1829
1838
  const options = componentProps.options || [];
1830
1839
  const placeholder = componentProps.placeholder || "Seleccionar...";
@@ -1991,13 +2000,13 @@ const SelectWithConfirm = ({
1991
2000
  ] });
1992
2001
  };
1993
2002
 
1994
- const MOBILE_BREAKPOINT$2 = 640;
1995
- const useIsMobile$3 = () => {
2003
+ const MOBILE_BREAKPOINT$3 = 640;
2004
+ const useIsMobile$4 = () => {
1996
2005
  const [isMobile, setIsMobile] = useState(
1997
- typeof window !== "undefined" ? window.innerWidth < MOBILE_BREAKPOINT$2 : false
2006
+ typeof window !== "undefined" ? window.innerWidth < MOBILE_BREAKPOINT$3 : false
1998
2007
  );
1999
2008
  useEffect(() => {
2000
- const mq = window.matchMedia(`(max-width: ${MOBILE_BREAKPOINT$2 - 1}px)`);
2009
+ const mq = window.matchMedia(`(max-width: ${MOBILE_BREAKPOINT$3 - 1}px)`);
2001
2010
  const handler = (e) => setIsMobile(e.matches);
2002
2011
  mq.addEventListener("change", handler);
2003
2012
  return () => mq.removeEventListener("change", handler);
@@ -2013,7 +2022,7 @@ const SelectMultipleWithConfirm = ({
2013
2022
  const [isDrawerOpen, setIsDrawerOpen] = useState(false);
2014
2023
  const [searchValue, setSearchValue] = useState("");
2015
2024
  const searchInputRef = useRef(null);
2016
- const isMobile = useIsMobile$3();
2025
+ const isMobile = useIsMobile$4();
2017
2026
  const { field_name, value, ...componentProps } = component.props;
2018
2027
  const options = componentProps.options || [];
2019
2028
  const placeholder = componentProps.placeholder || "Seleccionar...";
@@ -2256,8 +2265,8 @@ const ChatConfigProvider = ({ value, children }) => /* @__PURE__ */ jsx(ChatConf
2256
2265
  const useChatConfig = () => useContext(ChatConfigContext);
2257
2266
 
2258
2267
  registerLocale("es", es);
2259
- const MOBILE_BREAKPOINT$1 = 640;
2260
- const parseDate$2 = (dateString) => {
2268
+ const MOBILE_BREAKPOINT$2 = 640;
2269
+ const parseDate$3 = (dateString) => {
2261
2270
  if (!dateString) return null;
2262
2271
  try {
2263
2272
  if (/^\d{4}-\d{2}-\d{2}$/.test(dateString)) {
@@ -2270,14 +2279,14 @@ const parseDate$2 = (dateString) => {
2270
2279
  return null;
2271
2280
  }
2272
2281
  };
2273
- const formatDateToISO = (date) => {
2282
+ const formatDateToISO$1 = (date) => {
2274
2283
  if (!date) return "";
2275
2284
  const year = date.getFullYear();
2276
2285
  const month = (date.getMonth() + 1).toString().padStart(2, "0");
2277
2286
  const day = date.getDate().toString().padStart(2, "0");
2278
2287
  return `${year}-${month}-${day}`;
2279
2288
  };
2280
- const formatDateDisplay = (date, locale, timezone) => {
2289
+ const formatDateDisplay$1 = (date, locale, timezone) => {
2281
2290
  if (!date) return "";
2282
2291
  return date.toLocaleDateString(locale, {
2283
2292
  day: "2-digit",
@@ -2326,12 +2335,12 @@ const CustomHeader$1 = ({
2326
2335
  )
2327
2336
  ] });
2328
2337
  };
2329
- const useIsMobile$2 = () => {
2338
+ const useIsMobile$3 = () => {
2330
2339
  const [isMobile, setIsMobile] = useState(
2331
- typeof window !== "undefined" ? window.innerWidth < MOBILE_BREAKPOINT$1 : false
2340
+ typeof window !== "undefined" ? window.innerWidth < MOBILE_BREAKPOINT$2 : false
2332
2341
  );
2333
2342
  useEffect(() => {
2334
- const mq = window.matchMedia(`(max-width: ${MOBILE_BREAKPOINT$1 - 1}px)`);
2343
+ const mq = window.matchMedia(`(max-width: ${MOBILE_BREAKPOINT$2 - 1}px)`);
2335
2344
  const handler = (e) => setIsMobile(e.matches);
2336
2345
  mq.addEventListener("change", handler);
2337
2346
  return () => mq.removeEventListener("change", handler);
@@ -2347,15 +2356,15 @@ const DateInputWithConfirm = ({
2347
2356
  const [selectedDate, setSelectedDate] = useState(null);
2348
2357
  const [isOpen, setIsOpen] = useState(false);
2349
2358
  const triggerRef = useRef(null);
2350
- const isMobile = useIsMobile$2();
2359
+ const isMobile = useIsMobile$3();
2351
2360
  const { emitInteraction, isConfirmed } = useComponentInteraction({
2352
2361
  eventBus,
2353
2362
  fieldName: component.props.field_name,
2354
2363
  componentType: component.type,
2355
2364
  assistantMessageId
2356
2365
  });
2357
- const minDate = component.props.min_date ? parseDate$2(component.props.min_date) : void 0;
2358
- const maxDate = component.props.max_date ? parseDate$2(component.props.max_date) : void 0;
2366
+ const minDate = component.props.min_date ? parseDate$3(component.props.min_date) : void 0;
2367
+ const maxDate = component.props.max_date ? parseDate$3(component.props.max_date) : void 0;
2359
2368
  useEffect(() => {
2360
2369
  if (!isOpen || isMobile) return;
2361
2370
  const handleKey = (e) => {
@@ -2372,12 +2381,12 @@ const DateInputWithConfirm = ({
2372
2381
  };
2373
2382
  const handleConfirm = useCallback(() => {
2374
2383
  if (!selectedDate) return;
2375
- const isoValue = formatDateToISO(selectedDate);
2376
- const displayValue2 = formatDateDisplay(selectedDate, locale, timezone);
2384
+ const isoValue = formatDateToISO$1(selectedDate);
2385
+ const displayValue2 = formatDateDisplay$1(selectedDate, locale, timezone);
2377
2386
  emitInteraction(isoValue, displayValue2);
2378
2387
  setIsOpen(false);
2379
2388
  }, [selectedDate, emitInteraction, locale, timezone]);
2380
- const displayValue = formatDateDisplay(selectedDate, locale, timezone);
2389
+ const displayValue = formatDateDisplay$1(selectedDate, locale, timezone);
2381
2390
  const placeholder = component.props.placeholder || "Selecciona una fecha";
2382
2391
  const label = component.props.label || "Selecciona una fecha";
2383
2392
  const calendarContent = /* @__PURE__ */ jsx(
@@ -2516,13 +2525,14 @@ const ConfirmButton = ({
2516
2525
  };
2517
2526
 
2518
2527
  const CardDisplay = ({ component }) => {
2519
- const { title, rows, variant = "default" } = component.props;
2528
+ const { title, rows, content, variant = "default" } = component.props;
2520
2529
  return /* @__PURE__ */ jsxs("div", { className: `px-chat-card px-chat-card--${variant}`, children: [
2521
2530
  /* @__PURE__ */ jsx("div", { className: "px-chat-card__title", children: title }),
2522
- /* @__PURE__ */ jsx("div", { className: "px-chat-card__rows", children: rows.map((row, i) => /* @__PURE__ */ jsxs("div", { className: "px-chat-card__row", children: [
2531
+ content && !rows?.length && /* @__PURE__ */ jsx("div", { className: "px-chat-card__content", children: content }),
2532
+ rows?.length ? /* @__PURE__ */ jsx("div", { className: "px-chat-card__rows", children: rows.map((row, i) => /* @__PURE__ */ jsxs("div", { className: "px-chat-card__row", children: [
2523
2533
  /* @__PURE__ */ jsx("span", { className: "px-chat-card__row-label", children: row.label }),
2524
2534
  /* @__PURE__ */ jsx("span", { className: "px-chat-card__row-value", children: row.value })
2525
- ] }, i)) })
2535
+ ] }, i)) }) : null
2526
2536
  ] });
2527
2537
  };
2528
2538
 
@@ -2673,13 +2683,13 @@ const ScrollableColumn$1 = ({
2673
2683
  ] });
2674
2684
  };
2675
2685
 
2676
- const MOBILE_BREAKPOINT = 640;
2677
- const useIsMobile$1 = () => {
2686
+ const MOBILE_BREAKPOINT$1 = 640;
2687
+ const useIsMobile$2 = () => {
2678
2688
  const [isMobile, setIsMobile] = useState(
2679
- typeof window !== "undefined" ? window.innerWidth < MOBILE_BREAKPOINT : false
2689
+ typeof window !== "undefined" ? window.innerWidth < MOBILE_BREAKPOINT$1 : false
2680
2690
  );
2681
2691
  useEffect(() => {
2682
- const mq = window.matchMedia(`(max-width: ${MOBILE_BREAKPOINT - 1}px)`);
2692
+ const mq = window.matchMedia(`(max-width: ${MOBILE_BREAKPOINT$1 - 1}px)`);
2683
2693
  const handler = (e) => setIsMobile(e.matches);
2684
2694
  mq.addEventListener("change", handler);
2685
2695
  return () => mq.removeEventListener("change", handler);
@@ -2732,7 +2742,7 @@ const TimeInputWithConfirm = ({
2732
2742
  assistantMessageId = ""
2733
2743
  }) => {
2734
2744
  const { timezone, locale } = useChatConfig();
2735
- const isMobile = useIsMobile$1();
2745
+ const isMobile = useIsMobile$2();
2736
2746
  const [isOpen, setIsOpen] = useState(false);
2737
2747
  const [confirmedTime, setConfirmedTime] = useState("");
2738
2748
  const triggerRef = useRef(null);
@@ -2973,130 +2983,1926 @@ const TimeInputWithConfirm = ({
2973
2983
  ] });
2974
2984
  };
2975
2985
 
2976
- const COMPONENT_MAP = {
2977
- select: SelectWithConfirm,
2978
- select_multiple: SelectMultipleWithConfirm,
2979
- confirm: ConfirmButton,
2980
- date_input: DateInputWithConfirm,
2981
- time_input: TimeInputWithConfirm,
2982
- input: InputWithConfirm,
2983
- card: CardDisplay,
2984
- badge: BadgeDisplay
2985
- };
2986
- function renderComponent(props) {
2987
- const { component } = props;
2988
- if (component.answered && !DISPLAY_COMPONENTS.has(component.type)) {
2986
+ registerLocale("es", es);
2987
+ const parseDate$2 = (dateString) => {
2988
+ if (!dateString) return null;
2989
+ try {
2990
+ if (/^\d{4}-\d{2}-\d{2}$/.test(dateString)) {
2991
+ const [year, month, day] = dateString.split("-").map(Number);
2992
+ return new Date(year, month - 1, day);
2993
+ }
2994
+ const parsed = new Date(dateString);
2995
+ return isNaN(parsed.getTime()) ? null : parsed;
2996
+ } catch {
2989
2997
  return null;
2990
2998
  }
2991
- const Component = COMPONENT_MAP[component.type];
2992
- if (!Component) return null;
2993
- return /* @__PURE__ */ jsx(Component, { ...props });
2994
- }
2995
-
2996
- const StructuredContent = ({
2997
- content,
2998
- eventBus,
2999
- assistantMessageId,
3000
- className = ""
2999
+ };
3000
+ const formatDateToISO = (date) => {
3001
+ if (!date) return "";
3002
+ const year = date.getFullYear();
3003
+ const month = (date.getMonth() + 1).toString().padStart(2, "0");
3004
+ const day = date.getDate().toString().padStart(2, "0");
3005
+ return `${year}-${month}-${day}`;
3006
+ };
3007
+ const formatDateDisplay = (date) => {
3008
+ if (!date) return "";
3009
+ return date.toLocaleDateString("es", { day: "2-digit", month: "long", year: "numeric" });
3010
+ };
3011
+ const DynamicField = ({
3012
+ field,
3013
+ value,
3014
+ error,
3015
+ disabled,
3016
+ fieldState,
3017
+ onChange,
3018
+ drawerPlacement = "bottom"
3001
3019
  }) => {
3002
- const structured = parseContent(content);
3003
- const markdownContent = structured ? structured.message : content;
3004
- const rawComponent = structured?.component || null;
3005
- const components = rawComponent ? Array.isArray(rawComponent) ? rawComponent : [rawComponent] : [];
3006
- const hasVisibleComponents = components.some((comp) => !comp.answered || DISPLAY_COMPONENTS.has(comp.type));
3007
- return /* @__PURE__ */ jsxs("div", { className: `${COMPONENT_PREFIX$1}structured-content ${className}`, children: [
3008
- markdownContent && /* @__PURE__ */ jsx("div", { className: `${COMPONENT_PREFIX$1}assistant-message__markdown${hasVisibleComponents ? ` ${COMPONENT_PREFIX$1}assistant-message__markdown--with-component` : ``}`, children: /* @__PURE__ */ jsx(
3009
- ReactMarkdown,
3020
+ const { loading, options } = fieldState;
3021
+ if (field.type === "hidden") return null;
3022
+ const renderField = () => {
3023
+ switch (field.type) {
3024
+ case "select":
3025
+ return /* @__PURE__ */ jsx(
3026
+ SelectField$1,
3027
+ {
3028
+ field,
3029
+ value,
3030
+ disabled,
3031
+ loading,
3032
+ options,
3033
+ onChange,
3034
+ drawerPlacement
3035
+ }
3036
+ );
3037
+ case "select_multiple":
3038
+ return /* @__PURE__ */ jsx(
3039
+ SelectMultipleField,
3040
+ {
3041
+ field,
3042
+ value,
3043
+ disabled,
3044
+ loading,
3045
+ options,
3046
+ onChange,
3047
+ drawerPlacement
3048
+ }
3049
+ );
3050
+ case "date":
3051
+ return /* @__PURE__ */ jsx(
3052
+ DateField,
3053
+ {
3054
+ field,
3055
+ value,
3056
+ disabled,
3057
+ onChange,
3058
+ drawerPlacement
3059
+ }
3060
+ );
3061
+ default:
3062
+ return /* @__PURE__ */ jsx(
3063
+ "input",
3064
+ {
3065
+ type: field.type === "email" ? "email" : field.type === "number" ? "number" : "text",
3066
+ className: "px-chat-rf__input",
3067
+ placeholder: field.placeholder,
3068
+ value: value || "",
3069
+ disabled,
3070
+ onChange: (e) => onChange(e.target.value, e.target.value)
3071
+ }
3072
+ );
3073
+ }
3074
+ };
3075
+ return /* @__PURE__ */ jsxs("div", { className: `px-chat-rf__field ${error ? "px-chat-rf__field--error" : ""} ${disabled ? "px-chat-rf__field--disabled" : ""}`, children: [
3076
+ /* @__PURE__ */ jsx("label", { className: "px-chat-rf__field-label", children: field.label }),
3077
+ renderField(),
3078
+ error && /* @__PURE__ */ jsx("span", { className: "px-chat-rf__field-error", children: error })
3079
+ ] });
3080
+ };
3081
+ const SelectField$1 = ({ field, value, disabled, loading, options, onChange, drawerPlacement }) => {
3082
+ const [isDrawerOpen, setIsDrawerOpen] = useState(false);
3083
+ const [searchValue, setSearchValue] = useState("");
3084
+ const searchInputRef = useRef(null);
3085
+ const selectedLabel = options.find((o) => o.value === value)?.label || "";
3086
+ const placeholder = loading ? "Cargando..." : field.placeholder || "Seleccionar...";
3087
+ const filteredOptions = searchValue ? options.filter((opt) => opt.label.toLowerCase().includes(searchValue.toLowerCase())) : options;
3088
+ useEffect(() => {
3089
+ if (isDrawerOpen && searchInputRef.current) {
3090
+ setTimeout(() => searchInputRef.current?.focus(), 350);
3091
+ }
3092
+ }, [isDrawerOpen]);
3093
+ const handleSelect = (opt) => {
3094
+ const { value: v, label, ...extra } = opt;
3095
+ onChange(v, label, Object.keys(extra).length > 0 ? extra : void 0);
3096
+ };
3097
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
3098
+ /* @__PURE__ */ jsxs(
3099
+ "div",
3010
3100
  {
3011
- components: {
3012
- a: ({ href, children }) => /* @__PURE__ */ jsx(
3013
- Link,
3014
- {
3015
- href: href || "#",
3016
- variant: "primary",
3017
- size: "medium",
3018
- weight: "bold",
3019
- underline: false,
3020
- children
3021
- }
3022
- )
3101
+ className: `px-chat-select-with-confirm__trigger ${isDrawerOpen ? "px-chat-select-with-confirm__trigger--open" : ""}`,
3102
+ onClick: () => !disabled && !loading && setIsDrawerOpen(true),
3103
+ role: "button",
3104
+ tabIndex: disabled ? -1 : 0,
3105
+ onKeyDown: (e) => {
3106
+ if (!disabled && (e.key === "Enter" || e.key === " ")) setIsDrawerOpen(true);
3023
3107
  },
3024
- children: markdownContent
3108
+ children: [
3109
+ /* @__PURE__ */ jsx("span", { className: `px-chat-select-with-confirm__trigger-text ${!value ? "px-chat-select-with-confirm__trigger-text--placeholder" : ""}`, children: value ? selectedLabel : placeholder }),
3110
+ /* @__PURE__ */ jsx("span", { className: "px-chat-select-with-confirm__chevron", children: loading ? /* @__PURE__ */ jsx(Loader$1, { size: "small" }) : /* @__PURE__ */ jsx(Icon$1, { type: ICON_TYPES.CHEVRON_DOWN, size: "small" }) })
3111
+ ]
3025
3112
  }
3026
- ) }),
3027
- components.length > 0 && /* @__PURE__ */ jsx("div", { className: `${COMPONENT_PREFIX$1}structured-content__component`, children: components.map((comp, index) => /* @__PURE__ */ jsx(React.Fragment, { children: renderComponent({ component: comp, eventBus, assistantMessageId }) }, `${comp.type}-${index}`)) })
3113
+ ),
3114
+ /* @__PURE__ */ jsx(
3115
+ Drawer$1,
3116
+ {
3117
+ isOpen: isDrawerOpen,
3118
+ onClose: () => {
3119
+ setIsDrawerOpen(false);
3120
+ setSearchValue("");
3121
+ },
3122
+ title: field.label,
3123
+ placement: drawerPlacement,
3124
+ children: /* @__PURE__ */ jsxs("div", { className: "px-chat-select-drawer px-chat-rf-select-drawer", children: [
3125
+ /* @__PURE__ */ jsxs("div", { className: "px-chat-select-drawer__search", children: [
3126
+ /* @__PURE__ */ jsx(Icon$1, { type: ICON_TYPES.SEARCH, size: "small" }),
3127
+ /* @__PURE__ */ jsx(
3128
+ "input",
3129
+ {
3130
+ ref: searchInputRef,
3131
+ type: "text",
3132
+ className: "px-chat-select-drawer__search-input",
3133
+ value: searchValue,
3134
+ onChange: (e) => setSearchValue(e.target.value),
3135
+ placeholder: "Buscar..."
3136
+ }
3137
+ ),
3138
+ searchValue && /* @__PURE__ */ jsx("button", { type: "button", className: "px-chat-select-drawer__search-clear", onClick: () => setSearchValue(""), children: /* @__PURE__ */ jsx(Icon$1, { type: ICON_TYPES.CLOSE, size: "small" }) })
3139
+ ] }),
3140
+ /* @__PURE__ */ jsx("ul", { className: "px-chat-select-drawer__options", role: "listbox", children: filteredOptions.length === 0 ? /* @__PURE__ */ jsx("li", { className: "px-chat-select-drawer__empty", children: "No hay opciones disponibles" }) : filteredOptions.map((opt) => {
3141
+ const isSelected = opt.value === value;
3142
+ return /* @__PURE__ */ jsxs(
3143
+ "li",
3144
+ {
3145
+ className: `px-chat-select-drawer__option ${isSelected ? "px-chat-select-drawer__option--selected" : ""}`,
3146
+ onClick: () => {
3147
+ handleSelect(opt);
3148
+ setIsDrawerOpen(false);
3149
+ setSearchValue("");
3150
+ },
3151
+ role: "option",
3152
+ "aria-selected": isSelected,
3153
+ children: [
3154
+ /* @__PURE__ */ jsx("span", { className: "px-chat-select-drawer__option-label", children: opt.label }),
3155
+ isSelected && /* @__PURE__ */ jsx("span", { className: "px-chat-select-drawer__option-check", children: /* @__PURE__ */ jsx(Icon$1, { type: ICON_TYPES.CHECK, size: "small" }) })
3156
+ ]
3157
+ },
3158
+ opt.value
3159
+ );
3160
+ }) })
3161
+ ] })
3162
+ }
3163
+ )
3028
3164
  ] });
3029
3165
  };
3030
-
3031
- const getAttachmentType = (file) => {
3032
- const mimeType = file.type.toLowerCase();
3033
- if (mimeType.startsWith(MIME_PREFIXES.AUDIO)) {
3034
- return AttachmentType.AUDIO;
3035
- }
3036
- if (mimeType.startsWith(MIME_PREFIXES.VIDEO)) {
3037
- return AttachmentType.VIDEO;
3038
- }
3039
- if (mimeType.startsWith(MIME_PREFIXES.IMAGE)) {
3040
- return AttachmentType.IMAGE;
3041
- }
3042
- if (mimeType === MIME_TYPES.PDF) {
3043
- return AttachmentType.PDF;
3044
- }
3045
- 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)) {
3046
- return AttachmentType.DOCUMENT;
3047
- }
3048
- return AttachmentType.OTHER;
3049
- };
3050
- const filterFilesByType = (files, type) => {
3051
- const types = Array.isArray(type) ? type : [type];
3052
- return files.filter((file) => {
3053
- const fileType = getAttachmentType(file);
3054
- return types.includes(fileType);
3055
- });
3056
- };
3057
- const getFileUrl = (file) => {
3058
- if (file.url) {
3059
- return file.url;
3060
- }
3061
- return URL.createObjectURL(file);
3062
- };
3063
- const getAudioFiles = (files) => {
3064
- return filterFilesByType(files, [AttachmentType.AUDIO]);
3065
- };
3066
- const getNonAudioFiles = (files) => {
3067
- return filterFilesByType(files, [
3068
- AttachmentType.IMAGE,
3069
- AttachmentType.PDF,
3070
- AttachmentType.DOCUMENT,
3071
- AttachmentType.OTHER
3072
- ]);
3073
- };
3074
-
3075
- function createStore(initial) {
3076
- const state = { ...initial };
3077
- const listeners = {};
3078
- const notify = (key, value) => {
3079
- const keyStr = String(key);
3080
- listeners[keyStr]?.forEach((l) => l(value));
3081
- };
3082
- const subscribe = (key, listener) => {
3083
- const keyStr = String(key);
3084
- if (!listeners[keyStr]) listeners[keyStr] = /* @__PURE__ */ new Set();
3085
- listeners[keyStr].add(listener);
3086
- listener(state[key]);
3087
- return () => {
3088
- listeners[keyStr].delete(listener);
3089
- };
3090
- };
3091
- const set = (key, value) => {
3092
- state[key] = value;
3093
- notify(key, value);
3166
+ const SelectMultipleField = ({ field, value, disabled, loading, options, onChange, drawerPlacement }) => {
3167
+ const [isDrawerOpen, setIsDrawerOpen] = useState(false);
3168
+ const [searchValue, setSearchValue] = useState("");
3169
+ const searchInputRef = useRef(null);
3170
+ const selected = value || [];
3171
+ const placeholder = loading ? "Cargando..." : field.placeholder || "Seleccionar...";
3172
+ const filteredOptions = searchValue ? options.filter((opt) => opt.label.toLowerCase().includes(searchValue.toLowerCase())) : options;
3173
+ useEffect(() => {
3174
+ if (isDrawerOpen && searchInputRef.current) {
3175
+ setTimeout(() => searchInputRef.current?.focus(), 350);
3176
+ }
3177
+ }, [isDrawerOpen]);
3178
+ const toggleOption = (optValue) => {
3179
+ const isChecked = selected.includes(optValue);
3180
+ const next = isChecked ? selected.filter((v) => v !== optValue) : [...selected, optValue];
3181
+ const labels = next.map((v) => options.find((o) => o.value === v)?.label || v).join(", ");
3182
+ onChange(next, labels);
3094
3183
  };
3095
- const get = (key) => state[key];
3096
- return { set, get, subscribe };
3097
- }
3098
-
3099
- function deepMerge(target, source) {
3184
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
3185
+ /* @__PURE__ */ jsxs(
3186
+ "div",
3187
+ {
3188
+ className: `px-chat-select-with-confirm__trigger ${isDrawerOpen ? "px-chat-select-with-confirm__trigger--open" : ""}`,
3189
+ onClick: () => !disabled && !loading && setIsDrawerOpen(true),
3190
+ role: "button",
3191
+ tabIndex: disabled ? -1 : 0,
3192
+ onKeyDown: (e) => {
3193
+ if (!disabled && (e.key === "Enter" || e.key === " ")) setIsDrawerOpen(true);
3194
+ },
3195
+ children: [
3196
+ selected.length === 0 ? /* @__PURE__ */ jsx("span", { className: "px-chat-select-with-confirm__trigger-text px-chat-select-with-confirm__trigger-text--placeholder", children: placeholder }) : /* @__PURE__ */ jsx("div", { className: "px-chat-select-with-confirm__trigger-tags", children: selected.map((v) => {
3197
+ const opt = options.find((o) => o.value === v);
3198
+ return /* @__PURE__ */ jsxs("span", { className: "px-chat-select-with-confirm__trigger-tag", children: [
3199
+ opt?.label || v,
3200
+ /* @__PURE__ */ jsx(
3201
+ "button",
3202
+ {
3203
+ type: "button",
3204
+ className: "px-chat-select-with-confirm__trigger-tag-remove",
3205
+ onClick: (e) => {
3206
+ e.stopPropagation();
3207
+ toggleOption(v);
3208
+ },
3209
+ "aria-label": `Quitar ${opt?.label || v}`,
3210
+ children: /* @__PURE__ */ jsx(Icon$1, { type: ICON_TYPES.CLOSE, size: "small" })
3211
+ }
3212
+ )
3213
+ ] }, v);
3214
+ }) }),
3215
+ /* @__PURE__ */ jsx("span", { className: "px-chat-select-with-confirm__chevron", children: loading ? /* @__PURE__ */ jsx(Loader$1, { size: "small" }) : /* @__PURE__ */ jsx(Icon$1, { type: ICON_TYPES.CHEVRON_DOWN, size: "small" }) })
3216
+ ]
3217
+ }
3218
+ ),
3219
+ /* @__PURE__ */ jsx(
3220
+ Drawer$1,
3221
+ {
3222
+ isOpen: isDrawerOpen,
3223
+ onClose: () => {
3224
+ setIsDrawerOpen(false);
3225
+ setSearchValue("");
3226
+ },
3227
+ title: field.label,
3228
+ placement: drawerPlacement,
3229
+ footer: /* @__PURE__ */ jsxs(
3230
+ "button",
3231
+ {
3232
+ type: "button",
3233
+ className: "px-chat-rf__btn px-chat-rf__btn--primary",
3234
+ style: { width: "100%" },
3235
+ onClick: () => {
3236
+ setIsDrawerOpen(false);
3237
+ setSearchValue("");
3238
+ },
3239
+ children: [
3240
+ "Listo",
3241
+ selected.length > 0 ? ` (${selected.length})` : ""
3242
+ ]
3243
+ }
3244
+ ),
3245
+ children: /* @__PURE__ */ jsxs("div", { className: "px-chat-select-drawer px-chat-rf-select-drawer", children: [
3246
+ /* @__PURE__ */ jsxs("div", { className: "px-chat-select-drawer__search", children: [
3247
+ /* @__PURE__ */ jsx(Icon$1, { type: ICON_TYPES.SEARCH, size: "small" }),
3248
+ /* @__PURE__ */ jsx(
3249
+ "input",
3250
+ {
3251
+ ref: searchInputRef,
3252
+ type: "text",
3253
+ className: "px-chat-select-drawer__search-input",
3254
+ value: searchValue,
3255
+ onChange: (e) => setSearchValue(e.target.value),
3256
+ placeholder: "Buscar..."
3257
+ }
3258
+ ),
3259
+ searchValue && /* @__PURE__ */ jsx("button", { type: "button", className: "px-chat-select-drawer__search-clear", onClick: () => setSearchValue(""), children: /* @__PURE__ */ jsx(Icon$1, { type: ICON_TYPES.CLOSE, size: "small" }) })
3260
+ ] }),
3261
+ /* @__PURE__ */ jsx("ul", { className: "px-chat-select-drawer__options", role: "listbox", "aria-multiselectable": "true", children: filteredOptions.length === 0 ? /* @__PURE__ */ jsx("li", { className: "px-chat-select-drawer__empty", children: "No hay opciones disponibles" }) : filteredOptions.map((opt) => {
3262
+ const isChecked = selected.includes(opt.value);
3263
+ return /* @__PURE__ */ jsxs(
3264
+ "li",
3265
+ {
3266
+ className: `px-chat-select-drawer__option ${isChecked ? "px-chat-select-drawer__option--selected" : ""}`,
3267
+ onClick: () => toggleOption(opt.value),
3268
+ role: "option",
3269
+ "aria-selected": isChecked,
3270
+ children: [
3271
+ /* @__PURE__ */ jsx("span", { className: `px-chat-select-drawer__checkbox ${isChecked ? "px-chat-select-drawer__checkbox--checked" : ""}`, children: isChecked && /* @__PURE__ */ jsx(Icon$1, { type: ICON_TYPES.CHECK, size: "small" }) }),
3272
+ /* @__PURE__ */ jsx("span", { className: "px-chat-select-drawer__option-label", children: opt.label })
3273
+ ]
3274
+ },
3275
+ opt.value
3276
+ );
3277
+ }) })
3278
+ ] })
3279
+ }
3280
+ )
3281
+ ] });
3282
+ };
3283
+ const DateField = ({ field, value, disabled, onChange, drawerPlacement }) => {
3284
+ const [isOpen, setIsOpen] = useState(false);
3285
+ const selectedDate = value ? parseDate$2(value) : null;
3286
+ const displayValue = formatDateDisplay(selectedDate);
3287
+ const placeholder = field.placeholder || "Selecciona una fecha";
3288
+ 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;
3289
+ 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;
3290
+ const minDate = minDateRaw ? parseDate$2(minDateRaw) : void 0;
3291
+ const maxDate = maxDateRaw ? parseDate$2(maxDateRaw) : void 0;
3292
+ const handleDateChange = (date) => {
3293
+ if (!date) return;
3294
+ const isoValue = formatDateToISO(date);
3295
+ const display = formatDateDisplay(date);
3296
+ onChange(isoValue, display);
3297
+ };
3298
+ const calendarContent = /* @__PURE__ */ jsx(
3299
+ DatePicker,
3300
+ {
3301
+ selected: selectedDate,
3302
+ onChange: handleDateChange,
3303
+ inline: true,
3304
+ locale: "es",
3305
+ minDate: minDate || void 0,
3306
+ maxDate: maxDate || void 0,
3307
+ renderCustomHeader: ({ date, decreaseMonth, increaseMonth, prevMonthButtonDisabled, nextMonthButtonDisabled }) => /* @__PURE__ */ jsxs("div", { className: "px-chat-datepicker__header", children: [
3308
+ /* @__PURE__ */ jsx("button", { type: "button", className: "px-chat-datepicker__nav-btn", onClick: decreaseMonth, disabled: prevMonthButtonDisabled, children: "\u2039" }),
3309
+ /* @__PURE__ */ jsx("span", { className: "px-chat-datepicker__month-year", children: date.toLocaleDateString("es", { month: "long", year: "numeric" }) }),
3310
+ /* @__PURE__ */ jsx("button", { type: "button", className: "px-chat-datepicker__nav-btn", onClick: increaseMonth, disabled: nextMonthButtonDisabled, children: "\u203A" })
3311
+ ] })
3312
+ }
3313
+ );
3314
+ const calendarIcon = /* @__PURE__ */ jsx("svg", { width: "16", height: "16", viewBox: "0 0 16 16", fill: "none", xmlns: "http://www.w3.org/2000/svg", children: /* @__PURE__ */ 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" }) });
3315
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
3316
+ /* @__PURE__ */ jsxs(
3317
+ "div",
3318
+ {
3319
+ className: `px-chat-rf__date-trigger ${isOpen ? "px-chat-rf__date-trigger--open" : ""}`,
3320
+ onClick: () => !disabled && setIsOpen(!isOpen),
3321
+ role: "button",
3322
+ tabIndex: disabled ? -1 : 0,
3323
+ onKeyDown: (e) => {
3324
+ if (!disabled && (e.key === "Enter" || e.key === " ")) setIsOpen(!isOpen);
3325
+ },
3326
+ children: [
3327
+ /* @__PURE__ */ jsx("span", { className: `px-chat-rf__date-trigger-text ${!selectedDate ? "px-chat-rf__date-trigger-text--placeholder" : ""}`, children: selectedDate ? displayValue : placeholder }),
3328
+ /* @__PURE__ */ jsx("span", { className: "px-chat-rf__date-trigger-icon", children: calendarIcon })
3329
+ ]
3330
+ }
3331
+ ),
3332
+ /* @__PURE__ */ jsxs(
3333
+ Drawer$1,
3334
+ {
3335
+ isOpen,
3336
+ onClose: () => setIsOpen(false),
3337
+ title: field.label,
3338
+ placement: drawerPlacement,
3339
+ footer: /* @__PURE__ */ jsx(
3340
+ "button",
3341
+ {
3342
+ type: "button",
3343
+ className: "px-chat-rf__btn px-chat-rf__btn--primary",
3344
+ style: { width: "100%" },
3345
+ disabled: !selectedDate,
3346
+ onClick: () => setIsOpen(false),
3347
+ children: "Confirmar"
3348
+ }
3349
+ ),
3350
+ children: [
3351
+ /* @__PURE__ */ jsx("div", { className: "px-chat-datepicker px-chat-datepicker--mobile", children: calendarContent }),
3352
+ selectedDate && /* @__PURE__ */ jsx("div", { className: "px-chat-datepicker__selected-date", children: displayValue })
3353
+ ]
3354
+ }
3355
+ )
3356
+ ] });
3357
+ };
3358
+
3359
+ const checkIcon = /* @__PURE__ */ jsx("svg", { width: "12", height: "12", viewBox: "0 0 12 12", fill: "none", xmlns: "http://www.w3.org/2000/svg", children: /* @__PURE__ */ jsx("path", { d: "M2.5 6L5 8.5L9.5 3.5", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round" }) });
3360
+ const calendarIcon = /* @__PURE__ */ jsxs("svg", { width: "16", height: "16", viewBox: "0 0 16 16", fill: "none", xmlns: "http://www.w3.org/2000/svg", children: [
3361
+ /* @__PURE__ */ jsx("rect", { x: "2", y: "3", width: "12", height: "11", rx: "1.5", stroke: "currentColor", strokeWidth: "1.2" }),
3362
+ /* @__PURE__ */ jsx("path", { d: "M2 6.5H14", stroke: "currentColor", strokeWidth: "1.2" }),
3363
+ /* @__PURE__ */ jsx("path", { d: "M5.5 1.5V4", stroke: "currentColor", strokeWidth: "1.2", strokeLinecap: "round" }),
3364
+ /* @__PURE__ */ jsx("path", { d: "M10.5 1.5V4", stroke: "currentColor", strokeWidth: "1.2", strokeLinecap: "round" })
3365
+ ] });
3366
+ const formIcon = /* @__PURE__ */ jsxs("svg", { width: "16", height: "16", viewBox: "0 0 16 16", fill: "none", xmlns: "http://www.w3.org/2000/svg", children: [
3367
+ /* @__PURE__ */ jsx("rect", { x: "2", y: "1.5", width: "12", height: "13", rx: "1.5", stroke: "currentColor", strokeWidth: "1.2" }),
3368
+ /* @__PURE__ */ jsx("path", { d: "M5 5.5H11", stroke: "currentColor", strokeWidth: "1.2", strokeLinecap: "round" }),
3369
+ /* @__PURE__ */ jsx("path", { d: "M5 8.5H11", stroke: "currentColor", strokeWidth: "1.2", strokeLinecap: "round" }),
3370
+ /* @__PURE__ */ jsx("path", { d: "M5 11.5H8.5", stroke: "currentColor", strokeWidth: "1.2", strokeLinecap: "round" })
3371
+ ] });
3372
+ const chevronDown = /* @__PURE__ */ jsx("svg", { width: "12", height: "12", viewBox: "0 0 12 12", fill: "none", xmlns: "http://www.w3.org/2000/svg", children: /* @__PURE__ */ jsx("path", { d: "M3 4.5L6 7.5L9 4.5", stroke: "currentColor", strokeWidth: "1.2", strokeLinecap: "round", strokeLinejoin: "round" }) });
3373
+ const chevronRight = /* @__PURE__ */ jsx("svg", { width: "12", height: "12", viewBox: "0 0 12 12", fill: "none", xmlns: "http://www.w3.org/2000/svg", children: /* @__PURE__ */ jsx("path", { d: "M4.5 3L7.5 6L4.5 9", stroke: "currentColor", strokeWidth: "1.2", strokeLinecap: "round", strokeLinejoin: "round" }) });
3374
+ const ReactiveFormView = ({ title, trigger, steps, fields, submit, summary, form, drawerPlacement = "bottom" }) => {
3375
+ const {
3376
+ formStatus,
3377
+ setFormStatus,
3378
+ currentStep,
3379
+ setCurrentStep,
3380
+ values,
3381
+ errors,
3382
+ touched,
3383
+ fieldStates,
3384
+ totalSteps,
3385
+ handleTriggerClick,
3386
+ handleFieldChange,
3387
+ handleNext,
3388
+ handleBack,
3389
+ handleSubmit,
3390
+ getDependencies,
3391
+ allDepsResolved,
3392
+ resolveSummaryRows
3393
+ } = form;
3394
+ const renderTrigger = () => {
3395
+ const isOpen = formStatus === "open";
3396
+ const isFinished = formStatus === "completed" || formStatus === "warning" || formStatus === "error";
3397
+ const statusClass = isFinished ? `px-chat-rf__trigger--${formStatus}` : "";
3398
+ return /* @__PURE__ */ jsxs(
3399
+ "button",
3400
+ {
3401
+ type: "button",
3402
+ className: `px-chat-rf__trigger ${isOpen ? "px-chat-rf__trigger--open" : ""} ${statusClass}`,
3403
+ onClick: handleTriggerClick,
3404
+ children: [
3405
+ /* @__PURE__ */ jsx("span", { className: "px-chat-rf__trigger-icon", children: isFinished ? checkIcon : trigger.icon === "calendar" ? calendarIcon : formIcon }),
3406
+ /* @__PURE__ */ jsx("span", { className: "px-chat-rf__trigger-label", children: isFinished ? form.submitMessage : trigger.label }),
3407
+ !isFinished && /* @__PURE__ */ jsx("span", { className: "px-chat-rf__trigger-arrow", children: isOpen ? chevronDown : chevronRight })
3408
+ ]
3409
+ }
3410
+ );
3411
+ };
3412
+ const renderStepIndicator = () => /* @__PURE__ */ jsxs("div", { className: "px-chat-rf__steps-indicator", children: [
3413
+ steps.map((step, i) => {
3414
+ const isCompleted = i < currentStep;
3415
+ const isActive = i === currentStep;
3416
+ return /* @__PURE__ */ jsxs(React.Fragment, { children: [
3417
+ i > 0 && /* @__PURE__ */ jsx("div", { className: `px-chat-rf__step-line ${isCompleted ? "px-chat-rf__step-line--done" : ""}` }),
3418
+ /* @__PURE__ */ jsx(
3419
+ "button",
3420
+ {
3421
+ type: "button",
3422
+ className: `px-chat-rf__step-dot ${isActive ? "px-chat-rf__step-dot--active" : ""} ${isCompleted ? "px-chat-rf__step-dot--done" : ""}`,
3423
+ onClick: () => isCompleted && setCurrentStep(i),
3424
+ disabled: !isCompleted && !isActive,
3425
+ title: step.title,
3426
+ children: isCompleted ? checkIcon : i + 1
3427
+ }
3428
+ )
3429
+ ] }, i);
3430
+ }),
3431
+ /* @__PURE__ */ jsx("div", { className: `px-chat-rf__step-line ${currentStep >= steps.length ? "px-chat-rf__step-line--done" : ""}` }),
3432
+ /* @__PURE__ */ jsx(
3433
+ "button",
3434
+ {
3435
+ type: "button",
3436
+ className: `px-chat-rf__step-dot ${currentStep >= steps.length ? "px-chat-rf__step-dot--active" : ""}`,
3437
+ disabled: currentStep < steps.length,
3438
+ children: currentStep >= steps.length ? checkIcon : totalSteps
3439
+ }
3440
+ )
3441
+ ] });
3442
+ const renderNavButtons = () => /* @__PURE__ */ jsxs("div", { className: "px-chat-rf__nav", children: [
3443
+ currentStep > 0 && /* @__PURE__ */ jsx("button", { type: "button", className: "px-chat-rf__btn px-chat-rf__btn--secondary", onClick: handleBack, children: "Atras" }),
3444
+ /* @__PURE__ */ jsx("button", { type: "button", className: "px-chat-rf__btn px-chat-rf__btn--primary", onClick: handleNext, children: "Siguiente" })
3445
+ ] });
3446
+ const renderSummaryActions = () => {
3447
+ const actions = summary.actions;
3448
+ if (!actions || actions.length === 0) {
3449
+ return /* @__PURE__ */ jsx("button", { type: "button", className: "px-chat-rf__btn px-chat-rf__btn--primary px-chat-rf__btn--full", onClick: handleSubmit, children: submit.label });
3450
+ }
3451
+ const actionHandlers = {
3452
+ submit: handleSubmit,
3453
+ close: () => setFormStatus("closed"),
3454
+ back: handleBack
3455
+ };
3456
+ return /* @__PURE__ */ jsx("div", { className: "px-chat-rf__nav", children: actions.map((act, i) => /* @__PURE__ */ jsx(
3457
+ "button",
3458
+ {
3459
+ type: "button",
3460
+ className: `px-chat-rf__btn px-chat-rf__btn--${act.variant || "primary"}`,
3461
+ onClick: actionHandlers[act.action] || (() => {
3462
+ }),
3463
+ children: act.label
3464
+ },
3465
+ i
3466
+ )) });
3467
+ };
3468
+ const renderStepContent = () => {
3469
+ if (currentStep >= steps.length) {
3470
+ const resolvedRows = resolveSummaryRows(summary.rows);
3471
+ return /* @__PURE__ */ jsx("div", { className: "px-chat-rf__summary", children: /* @__PURE__ */ jsxs("div", { className: "px-chat-rf__summary-card", children: [
3472
+ /* @__PURE__ */ jsx("div", { className: "px-chat-rf__summary-title", children: summary.title }),
3473
+ resolvedRows.map((row, i) => /* @__PURE__ */ jsxs("div", { className: "px-chat-rf__summary-row", children: [
3474
+ /* @__PURE__ */ jsx("span", { className: "px-chat-rf__summary-label", children: row.label }),
3475
+ /* @__PURE__ */ jsx("span", { className: "px-chat-rf__summary-value", children: row.value })
3476
+ ] }, i))
3477
+ ] }) });
3478
+ }
3479
+ const step = steps[currentStep];
3480
+ const stepFields = step.fields.map((name) => fields.find((f) => f.name === name)).filter(Boolean);
3481
+ return /* @__PURE__ */ jsxs("div", { className: "px-chat-rf__step-content", children: [
3482
+ currentStep > 0 && /* @__PURE__ */ jsx("div", { className: "px-chat-rf__completed-steps", children: steps.slice(0, currentStep).map((prevStep, si) => /* @__PURE__ */ jsxs("div", { className: "px-chat-rf__completed-step", children: [
3483
+ /* @__PURE__ */ jsxs("div", { className: "px-chat-rf__completed-step-header", children: [
3484
+ /* @__PURE__ */ jsx("span", { className: "px-chat-rf__completed-step-title", children: prevStep.title }),
3485
+ /* @__PURE__ */ jsx(
3486
+ "button",
3487
+ {
3488
+ type: "button",
3489
+ className: "px-chat-rf__edit-btn",
3490
+ onClick: () => setCurrentStep(si),
3491
+ children: "editar"
3492
+ }
3493
+ )
3494
+ ] }),
3495
+ prevStep.fields.map((fname) => {
3496
+ const fs = fieldStates[fname];
3497
+ const fld = fields.find((f) => f.name === fname);
3498
+ return /* @__PURE__ */ jsxs("div", { className: "px-chat-rf__completed-field", children: [
3499
+ /* @__PURE__ */ jsxs("span", { className: "px-chat-rf__completed-field-label", children: [
3500
+ fld?.label,
3501
+ ":"
3502
+ ] }),
3503
+ /* @__PURE__ */ jsx("span", { className: "px-chat-rf__completed-field-value", children: fs?.label || String(values[fname] || "") })
3504
+ ] }, fname);
3505
+ })
3506
+ ] }, si)) }),
3507
+ /* @__PURE__ */ jsxs("div", { className: "px-chat-rf__active-step", children: [
3508
+ /* @__PURE__ */ jsx("div", { className: "px-chat-rf__step-title", children: step.title }),
3509
+ stepFields.map((field) => {
3510
+ const deps = getDependencies(field);
3511
+ const isDisabled = !allDepsResolved(deps, values);
3512
+ return /* @__PURE__ */ jsx(
3513
+ DynamicField,
3514
+ {
3515
+ field,
3516
+ value: values[field.name],
3517
+ error: touched[field.name] ? errors[field.name] : void 0,
3518
+ disabled: isDisabled,
3519
+ fieldState: fieldStates[field.name],
3520
+ drawerPlacement,
3521
+ onChange: (val, label, extra) => handleFieldChange(field.name, val, label, extra)
3522
+ },
3523
+ field.name
3524
+ );
3525
+ })
3526
+ ] })
3527
+ ] });
3528
+ };
3529
+ const renderDrawerFooter = () => {
3530
+ if (currentStep >= steps.length) return renderSummaryActions();
3531
+ return renderNavButtons();
3532
+ };
3533
+ return /* @__PURE__ */ jsxs("div", { className: "px-chat-rf", children: [
3534
+ renderTrigger(),
3535
+ /* @__PURE__ */ jsxs(
3536
+ Drawer$1,
3537
+ {
3538
+ isOpen: formStatus === "open",
3539
+ onClose: () => setFormStatus("closed"),
3540
+ title,
3541
+ placement: drawerPlacement,
3542
+ className: "px-chat-rf-drawer--mobile",
3543
+ footer: renderDrawerFooter(),
3544
+ children: [
3545
+ renderStepIndicator(),
3546
+ renderStepContent()
3547
+ ]
3548
+ }
3549
+ )
3550
+ ] });
3551
+ };
3552
+
3553
+ function buildYupSchema(fields) {
3554
+ const shape = {};
3555
+ for (const field of fields) {
3556
+ if (field.type === "hidden") continue;
3557
+ const v = field.validation;
3558
+ if (!v) continue;
3559
+ if (field.type === "select_multiple") {
3560
+ let s = yup.array().of(yup.string());
3561
+ if (v.required) s = s.min(1, v.required);
3562
+ if (v.min) s = s.min(Number(v.min.value), v.min.message);
3563
+ if (v.max) s = s.max(Number(v.max.value), v.max.message);
3564
+ shape[field.name] = s;
3565
+ } else if (field.type === "date") {
3566
+ let s = yup.string().typeError(`${field.label || field.name}: fecha inv\xE1lida`);
3567
+ if (v.required) s = s.required(v.required);
3568
+ const minDateRule = v.min_date ?? field.min_date;
3569
+ if (minDateRule) {
3570
+ const minVal = typeof minDateRule === "object" && minDateRule !== null ? String(minDateRule.value) : String(minDateRule);
3571
+ const minMsg = typeof minDateRule === "object" && minDateRule !== null ? minDateRule.message || `La fecha debe ser ${minVal} o posterior` : `La fecha debe ser ${minVal} o posterior`;
3572
+ s = s.test("min-date", minMsg, (val) => !val || val >= minVal);
3573
+ }
3574
+ const maxDateRule = v.max_date ?? field.max_date;
3575
+ if (maxDateRule) {
3576
+ const maxVal = typeof maxDateRule === "object" && maxDateRule !== null ? String(maxDateRule.value) : String(maxDateRule);
3577
+ const maxMsg = typeof maxDateRule === "object" && maxDateRule !== null ? maxDateRule.message || `La fecha debe ser ${maxVal} o anterior` : `La fecha debe ser ${maxVal} o anterior`;
3578
+ s = s.test("max-date", maxMsg, (val) => !val || val <= maxVal);
3579
+ }
3580
+ shape[field.name] = s;
3581
+ } else {
3582
+ let s = yup.string();
3583
+ if (v.required) s = s.required(v.required);
3584
+ if (v.pattern) s = s.matches(new RegExp(v.pattern.value), v.pattern.message);
3585
+ if (v.email) s = s.email(v.email);
3586
+ if (v.min) s = s.min(Number(v.min.value), v.min.message);
3587
+ if (v.max) s = s.max(Number(v.max.value), v.max.message);
3588
+ shape[field.name] = s;
3589
+ }
3590
+ }
3591
+ return yup.object().shape(shape);
3592
+ }
3593
+ function buildInitialValues(fields) {
3594
+ const values = {};
3595
+ for (const field of fields) {
3596
+ if (field.type === "hidden") {
3597
+ values[field.name] = field.default_value ?? "";
3598
+ } else {
3599
+ values[field.name] = field.type === "select_multiple" ? [] : "";
3600
+ }
3601
+ }
3602
+ return values;
3603
+ }
3604
+
3605
+ function resolveVariable(template, formValues, fieldStates) {
3606
+ if (!template.startsWith("$")) return template;
3607
+ const withoutDollar = template.slice(1);
3608
+ const dotIndex = withoutDollar.indexOf(".");
3609
+ const fieldName = dotIndex >= 0 ? withoutDollar.slice(0, dotIndex) : withoutDollar;
3610
+ const prop = dotIndex >= 0 ? withoutDollar.slice(dotIndex + 1) : null;
3611
+ const value = formValues[fieldName];
3612
+ const state = fieldStates[fieldName];
3613
+ if (!prop) return value;
3614
+ if (prop === "label" && state) {
3615
+ return state.label || "";
3616
+ }
3617
+ if (prop === "labels" && state && Array.isArray(value)) {
3618
+ return value.map((v) => {
3619
+ const opt = state.options.find((o) => o.value === v);
3620
+ return opt?.label || v;
3621
+ }).join(", ");
3622
+ }
3623
+ if (state) {
3624
+ const selectedOpt = state.options.find((o) => o.value === value);
3625
+ if (selectedOpt && prop in selectedOpt) {
3626
+ return selectedOpt[prop];
3627
+ }
3628
+ }
3629
+ return "";
3630
+ }
3631
+ function resolveBody(obj, formValues, fieldStates) {
3632
+ if (typeof obj === "string") return resolveVariable(obj, formValues, fieldStates);
3633
+ if (Array.isArray(obj)) return obj.map((item) => resolveBody(item, formValues, fieldStates));
3634
+ if (obj !== null && typeof obj === "object") {
3635
+ const resolved = {};
3636
+ for (const [key, value] of Object.entries(obj)) {
3637
+ resolved[key] = resolveBody(value, formValues, fieldStates);
3638
+ }
3639
+ return resolved;
3640
+ }
3641
+ return obj;
3642
+ }
3643
+ function resolveParams(params, formValues, fieldStates) {
3644
+ const resolved = {};
3645
+ for (const [key, template] of Object.entries(params)) {
3646
+ resolved[key] = resolveVariable(template, formValues, fieldStates);
3647
+ }
3648
+ return resolved;
3649
+ }
3650
+ function resolveSummaryRows(rows, formValues, fieldStates) {
3651
+ return rows.map((row) => ({
3652
+ label: row.label,
3653
+ value: String(resolveVariable(row.value, formValues, fieldStates) ?? "")
3654
+ }));
3655
+ }
3656
+
3657
+ const FETCH_TIMEOUT_MS = 12e4;
3658
+ function fetchViaEventBus(eventBus, service, url, method, body) {
3659
+ const requestId = crypto.randomUUID();
3660
+ return new Promise((resolve, reject) => {
3661
+ const timeoutId = setTimeout(() => {
3662
+ unsubscribe();
3663
+ reject(new Error(`Timeout: no response for ${url} after ${FETCH_TIMEOUT_MS}ms`));
3664
+ }, FETCH_TIMEOUT_MS);
3665
+ const unsubscribe = eventBus.on(CHAT_EVENT.FETCH_RESPONSE, (response) => {
3666
+ if (response.requestId !== requestId) return;
3667
+ clearTimeout(timeoutId);
3668
+ unsubscribe();
3669
+ if (response.httpError) {
3670
+ reject(new Error(response.httpError));
3671
+ } else {
3672
+ resolve(response.data);
3673
+ }
3674
+ });
3675
+ eventBus.emit(CHAT_EVENT.FETCH_REQUEST, {
3676
+ requestId,
3677
+ service,
3678
+ url,
3679
+ method,
3680
+ ...body ? { body } : {}
3681
+ });
3682
+ });
3683
+ }
3684
+
3685
+ function formatTime$1(value, timezone) {
3686
+ try {
3687
+ const d = new Date(value);
3688
+ if (isNaN(d.getTime())) return value;
3689
+ return d.toLocaleTimeString([], {
3690
+ hour: "2-digit",
3691
+ minute: "2-digit",
3692
+ hour12: false,
3693
+ ...timezone ? { timeZone: timezone } : {}
3694
+ });
3695
+ } catch {
3696
+ return value;
3697
+ }
3698
+ }
3699
+ function formatDate$3(value, timezone) {
3700
+ try {
3701
+ const d = new Date(value);
3702
+ if (isNaN(d.getTime())) return value;
3703
+ return d.toLocaleDateString("sv-SE", {
3704
+ year: "numeric",
3705
+ month: "2-digit",
3706
+ day: "2-digit",
3707
+ ...timezone ? { timeZone: timezone } : {}
3708
+ });
3709
+ } catch {
3710
+ return value;
3711
+ }
3712
+ }
3713
+ async function mockFetch(url, params) {
3714
+ await new Promise((r) => setTimeout(r, 600 + Math.random() * 400));
3715
+ if (url.includes("companies")) {
3716
+ return [
3717
+ { id: "company-1", name: "Goluti" },
3718
+ { id: "company-2", name: "Barbeer" }
3719
+ ];
3720
+ }
3721
+ if (url.includes("locations")) {
3722
+ if (params.company_id === "company-1") {
3723
+ return [
3724
+ { id: "loc-1", name: "Sede Chico" },
3725
+ { id: "loc-2", name: "Sede Suba" }
3726
+ ];
3727
+ }
3728
+ return [{ id: "loc-3", name: "Sede Norte" }];
3729
+ }
3730
+ if (url.includes("services")) {
3731
+ return [
3732
+ { id: "svc-1", name: "Corte de cabello" },
3733
+ { id: "svc-2", name: "Manicure" },
3734
+ { id: "svc-3", name: "Tinte completo" }
3735
+ ];
3736
+ }
3737
+ if (url.includes("availability")) {
3738
+ return [
3739
+ {
3740
+ collaborator_id: "collab-1",
3741
+ user_location_rol_id: "ulr-1",
3742
+ name: "Leon",
3743
+ assignment_hours: [
3744
+ { start: "2026-03-02T14:00:00", end: "2026-03-02T14:20:00", start_time: "14:00", end_time: "14:20" },
3745
+ { start: "2026-03-02T14:30:00", end: "2026-03-02T14:50:00", start_time: "14:30", end_time: "14:50" }
3746
+ ]
3747
+ },
3748
+ {
3749
+ collaborator_id: "collab-2",
3750
+ user_location_rol_id: "ulr-2",
3751
+ name: "Carlos",
3752
+ assignment_hours: [
3753
+ { start: "2026-03-02T10:00:00", end: "2026-03-02T10:20:00", start_time: "10:00", end_time: "10:20" },
3754
+ { start: "2026-03-02T11:00:00", end: "2026-03-02T11:20:00", start_time: "11:00", end_time: "11:20" }
3755
+ ]
3756
+ }
3757
+ ];
3758
+ }
3759
+ return [];
3760
+ }
3761
+ function getDependencies(field) {
3762
+ if (!field.depends_on) return [];
3763
+ return Array.isArray(field.depends_on) ? field.depends_on : [field.depends_on];
3764
+ }
3765
+ function allDepsResolved(deps, formValues) {
3766
+ return deps.every((dep) => {
3767
+ const val = formValues[dep];
3768
+ if (Array.isArray(val)) return val.length > 0;
3769
+ return val !== "" && val !== null && val !== void 0;
3770
+ });
3771
+ }
3772
+ function useReactiveEndpoints({ fields, fieldStates, setFieldState, eventBus, timezone, formTitle }) {
3773
+ const loadingRef = useRef(/* @__PURE__ */ new Set());
3774
+ const loadEndpoint = useCallback(
3775
+ async (field, formValues) => {
3776
+ if (!field.endpoint || loadingRef.current.has(field.name)) return;
3777
+ const deps = getDependencies(field);
3778
+ if (!allDepsResolved(deps, formValues)) return;
3779
+ loadingRef.current.add(field.name);
3780
+ setFieldState(field.name, { loading: true, error: null });
3781
+ const startTime = Date.now();
3782
+ try {
3783
+ const resolvedBody = field.endpoint.body ? resolveBody(field.endpoint.body, formValues, fieldStates) : void 0;
3784
+ const params = field.endpoint.params ? resolveParams(field.endpoint.params, formValues, fieldStates) : {};
3785
+ const requestBody = resolvedBody ?? (Object.keys(params).length > 0 ? params : void 0);
3786
+ if (eventBus) {
3787
+ eventBus.emit(CHAT_EVENT.FORM_TRACE, {
3788
+ chatId: "",
3789
+ formTitle: formTitle || "",
3790
+ source: "reactive_form",
3791
+ phase: "request",
3792
+ service: field.endpoint.service,
3793
+ url: field.endpoint.url,
3794
+ method: field.endpoint.method,
3795
+ body: requestBody
3796
+ });
3797
+ }
3798
+ let rawData;
3799
+ if (eventBus) {
3800
+ rawData = await fetchViaEventBus(
3801
+ eventBus,
3802
+ field.endpoint.service,
3803
+ field.endpoint.url,
3804
+ field.endpoint.method,
3805
+ requestBody
3806
+ );
3807
+ } else {
3808
+ rawData = await mockFetch(field.endpoint.url, params);
3809
+ }
3810
+ let dataArray;
3811
+ let data = rawData;
3812
+ if (rawData && typeof rawData === "object" && "response" in rawData) {
3813
+ data = rawData.response;
3814
+ }
3815
+ if (field.endpoint.response_path && data && typeof data === "object" && !Array.isArray(data)) {
3816
+ const extracted = data[field.endpoint.response_path];
3817
+ dataArray = Array.isArray(extracted) ? extracted : [];
3818
+ } else {
3819
+ dataArray = Array.isArray(data) ? data : [];
3820
+ }
3821
+ if (eventBus && rawData && typeof rawData === "object") {
3822
+ const resp = rawData;
3823
+ if (resp.notification_type && String(resp.notification_type).toLowerCase() !== "success") {
3824
+ throw new Error(resp.message || "Error en la respuesta");
3825
+ }
3826
+ }
3827
+ const options = dataArray.map((item) => {
3828
+ const opt = {
3829
+ value: String(item[field.endpoint.value_field] || ""),
3830
+ label: String(item[field.endpoint.label_field] || "")
3831
+ };
3832
+ if (field.endpoint.extra_fields) {
3833
+ for (const ef of field.endpoint.extra_fields) {
3834
+ opt[ef] = item[ef];
3835
+ }
3836
+ }
3837
+ return opt;
3838
+ });
3839
+ setFieldState(field.name, { options, loading: false });
3840
+ if (eventBus) {
3841
+ eventBus.emit(CHAT_EVENT.FORM_TRACE, {
3842
+ chatId: "",
3843
+ formTitle: formTitle || "",
3844
+ source: "reactive_form",
3845
+ phase: "response",
3846
+ service: field.endpoint.service,
3847
+ url: field.endpoint.url,
3848
+ method: field.endpoint.method,
3849
+ status: 200,
3850
+ duration_ms: Date.now() - startTime,
3851
+ success: true,
3852
+ response: rawData
3853
+ });
3854
+ }
3855
+ } catch (err) {
3856
+ const errorMsg = err instanceof Error ? err.message : "Error al cargar opciones";
3857
+ setFieldState(field.name, { loading: false, error: errorMsg });
3858
+ if (eventBus) {
3859
+ eventBus.emit(CHAT_EVENT.FORM_TRACE, {
3860
+ chatId: "",
3861
+ formTitle: formTitle || "",
3862
+ source: "reactive_form",
3863
+ phase: "response",
3864
+ service: field.endpoint.service,
3865
+ url: field.endpoint.url,
3866
+ method: field.endpoint.method,
3867
+ status: 500,
3868
+ duration_ms: Date.now() - startTime,
3869
+ success: false,
3870
+ error: errorMsg
3871
+ });
3872
+ }
3873
+ } finally {
3874
+ loadingRef.current.delete(field.name);
3875
+ }
3876
+ },
3877
+ [fields, fieldStates, setFieldState, eventBus]
3878
+ );
3879
+ const resolveOptionsFrom = useCallback(
3880
+ (field, formValues) => {
3881
+ if (!field.options_from) return;
3882
+ const sourceState = fieldStates[field.options_from.source_field];
3883
+ const sourceValue = formValues[field.options_from.source_field];
3884
+ if (!sourceState || !sourceValue) return;
3885
+ const selectedItem = sourceState.options.find((o) => o.value === sourceValue);
3886
+ if (!selectedItem) return;
3887
+ const rawData = selectedItem[field.options_from.data_field];
3888
+ if (!Array.isArray(rawData)) return;
3889
+ const options = rawData.map((item) => {
3890
+ let val = field.options_from.value_template;
3891
+ let lbl = field.options_from.label_template;
3892
+ for (const [k, v] of Object.entries(item)) {
3893
+ const strVal = String(v);
3894
+ const timeStr = formatTime$1(strVal, timezone);
3895
+ const dateStr = formatDate$3(strVal, timezone);
3896
+ val = val.replace(`\${${k}|time}`, timeStr);
3897
+ val = val.replace(`\${${k}|date}`, dateStr);
3898
+ val = val.replace(`\${${k}_time}`, timeStr);
3899
+ val = val.replace(`\${${k}_date}`, dateStr);
3900
+ val = val.replace(`\${${k}}`, strVal);
3901
+ lbl = lbl.replace(`\${${k}|time}`, timeStr);
3902
+ lbl = lbl.replace(`\${${k}|date}`, dateStr);
3903
+ lbl = lbl.replace(`\${${k}_time}`, timeStr);
3904
+ lbl = lbl.replace(`\${${k}_date}`, dateStr);
3905
+ lbl = lbl.replace(`\${${k}}`, strVal);
3906
+ }
3907
+ return { value: val, label: lbl, ...item };
3908
+ });
3909
+ setFieldState(field.name, { options, loading: false });
3910
+ },
3911
+ [fieldStates, setFieldState]
3912
+ );
3913
+ return { loadEndpoint, resolveOptionsFrom, getDependencies, allDepsResolved, fetchViaEventBus: eventBus ? fetchViaEventBus.bind(null, eventBus) : void 0 };
3914
+ }
3915
+
3916
+ function createInitialFieldStates(fields) {
3917
+ const map = {};
3918
+ for (const f of fields) {
3919
+ map[f.name] = {
3920
+ value: f.type === "hidden" ? f.default_value ?? "" : f.type === "select_multiple" ? [] : "",
3921
+ label: "",
3922
+ options: f.options || [],
3923
+ loading: false,
3924
+ error: null
3925
+ };
3926
+ }
3927
+ return map;
3928
+ }
3929
+ function useReactiveForm(props) {
3930
+ const { fields, steps, submit, eventBus } = props;
3931
+ const { timezone } = useChatConfig();
3932
+ const [formStatus, setFormStatus] = useState("closed");
3933
+ const [currentStep, setCurrentStep] = useState(0);
3934
+ const [values, setValues] = useState(() => buildInitialValues(fields));
3935
+ const [errors, setErrors] = useState({});
3936
+ const [touched, setTouched] = useState({});
3937
+ const [fieldStates, setFieldStatesMap] = useState(
3938
+ () => createInitialFieldStates(fields)
3939
+ );
3940
+ const validationSchema = useMemo(() => buildYupSchema(fields), [fields]);
3941
+ const totalSteps = steps.length + 1;
3942
+ const setFieldState = useCallback((name, partial) => {
3943
+ setFieldStatesMap((prev) => ({
3944
+ ...prev,
3945
+ [name]: { ...prev[name], ...partial }
3946
+ }));
3947
+ }, []);
3948
+ const { loadEndpoint, resolveOptionsFrom, getDependencies, allDepsResolved } = useReactiveEndpoints({ fields, fieldStates, setFieldState, eventBus, timezone, formTitle: props.title });
3949
+ const handleTriggerClick = () => {
3950
+ if (formStatus === "completed") return;
3951
+ setFormStatus(formStatus === "open" ? "closed" : "open");
3952
+ };
3953
+ const setFieldValue = useCallback((name, value) => {
3954
+ setValues((prev) => ({ ...prev, [name]: value }));
3955
+ }, []);
3956
+ const handleFieldChange = useCallback(
3957
+ (fieldName, value, label, extraData) => {
3958
+ setFieldValue(fieldName, value);
3959
+ setFieldState(fieldName, { value, label, extraData });
3960
+ setErrors((prev) => {
3961
+ const next = { ...prev };
3962
+ delete next[fieldName];
3963
+ return next;
3964
+ });
3965
+ for (const f of fields) {
3966
+ const deps = getDependencies(f);
3967
+ if (deps.includes(fieldName)) {
3968
+ const resetVal = f.type === "select_multiple" ? [] : "";
3969
+ setFieldValue(f.name, resetVal);
3970
+ setFieldState(f.name, { value: resetVal, label: "", options: [], extraData: void 0 });
3971
+ }
3972
+ }
3973
+ setValues((currentValues) => {
3974
+ const nextValues = { ...currentValues, [fieldName]: value };
3975
+ for (const f of fields) {
3976
+ const deps = getDependencies(f);
3977
+ if (deps.includes(fieldName) && allDepsResolved(deps, nextValues)) {
3978
+ if (f.endpoint) {
3979
+ loadEndpoint(f, nextValues);
3980
+ } else if (f.options_from) {
3981
+ setTimeout(() => resolveOptionsFrom(f, nextValues), 0);
3982
+ }
3983
+ }
3984
+ }
3985
+ return nextValues;
3986
+ });
3987
+ },
3988
+ [fields, getDependencies, allDepsResolved, loadEndpoint, resolveOptionsFrom, setFieldState, setFieldValue]
3989
+ );
3990
+ useEffect(() => {
3991
+ if (formStatus !== "open") return;
3992
+ const initialValues = buildInitialValues(fields);
3993
+ for (const f of fields) {
3994
+ if (!f.endpoint || fieldStates[f.name]?.options.length > 0) continue;
3995
+ const deps = getDependencies(f);
3996
+ if (deps.length === 0 || allDepsResolved(deps, initialValues)) {
3997
+ loadEndpoint(f, initialValues);
3998
+ }
3999
+ }
4000
+ }, [formStatus]);
4001
+ useEffect(() => {
4002
+ if (formStatus !== "open" || currentStep >= steps.length) return;
4003
+ const stepFieldNames = steps[currentStep].fields;
4004
+ setValues((currentValues) => {
4005
+ for (const f of fields) {
4006
+ if (!stepFieldNames.includes(f.name)) continue;
4007
+ if (!f.endpoint && !f.options_from) continue;
4008
+ if (fieldStates[f.name]?.options.length > 0) continue;
4009
+ if (fieldStates[f.name]?.loading) continue;
4010
+ const deps = getDependencies(f);
4011
+ if (allDepsResolved(deps, currentValues)) {
4012
+ if (f.endpoint) {
4013
+ loadEndpoint(f, currentValues);
4014
+ } else if (f.options_from) {
4015
+ resolveOptionsFrom(f, currentValues);
4016
+ }
4017
+ }
4018
+ }
4019
+ return currentValues;
4020
+ });
4021
+ }, [currentStep, formStatus]);
4022
+ const validateFields = async (fieldNames) => {
4023
+ const fieldErrors = {};
4024
+ try {
4025
+ await validationSchema.validate(values, { abortEarly: false });
4026
+ } catch (err) {
4027
+ if (err && typeof err === "object" && "inner" in err) {
4028
+ const yupErr = err;
4029
+ for (const e of yupErr.inner) {
4030
+ if (e.path && fieldNames.includes(e.path)) {
4031
+ fieldErrors[e.path] = e.message;
4032
+ }
4033
+ }
4034
+ }
4035
+ }
4036
+ return fieldErrors;
4037
+ };
4038
+ const validateStep = async (stepIndex) => {
4039
+ if (stepIndex >= steps.length) return true;
4040
+ const stepFieldNames = steps[stepIndex].fields;
4041
+ const stepErrors = await validateFields(stepFieldNames);
4042
+ setErrors((prev) => ({ ...prev, ...stepErrors }));
4043
+ const touchMap = {};
4044
+ for (const name of stepFieldNames) touchMap[name] = true;
4045
+ setTouched((prev) => ({ ...prev, ...touchMap }));
4046
+ return Object.keys(stepErrors).length === 0;
4047
+ };
4048
+ const handleNext = async () => {
4049
+ const valid = await validateStep(currentStep);
4050
+ if (valid) setCurrentStep((s) => s + 1);
4051
+ };
4052
+ const handleBack = () => setCurrentStep((s) => s - 1);
4053
+ const [submitMessage, setSubmitMessage] = useState("");
4054
+ const handleSubmit = async () => {
4055
+ const resolvedPayload = resolveBody(submit.payload_map, values, fieldStates);
4056
+ if (eventBus) {
4057
+ try {
4058
+ const data = await fetchViaEventBus(
4059
+ eventBus,
4060
+ submit.service,
4061
+ submit.url,
4062
+ submit.method,
4063
+ resolvedPayload
4064
+ );
4065
+ const resp = data;
4066
+ const notificationType = String(resp?.notification_type ?? "SUCCESS").toUpperCase();
4067
+ const message = String(resp?.message ?? "");
4068
+ const formLabels = {};
4069
+ for (const [name, state] of Object.entries(fieldStates)) {
4070
+ if (state.label) formLabels[name] = state.label;
4071
+ }
4072
+ eventBus.emit(CHAT_EVENT.FORM_SUBMIT, {
4073
+ formType: "reactive_form",
4074
+ submitUrl: submit.url,
4075
+ result: data,
4076
+ formValues: values,
4077
+ formLabels
4078
+ });
4079
+ if (notificationType === "SUCCESS") {
4080
+ setSubmitMessage(message || "Completado");
4081
+ setFormStatus("completed");
4082
+ } else if (notificationType === "WARNING") {
4083
+ setSubmitMessage(message || "Advertencia");
4084
+ setFormStatus("warning");
4085
+ } else {
4086
+ setSubmitMessage(message || "Error al procesar");
4087
+ setFormStatus("error");
4088
+ }
4089
+ } catch (err) {
4090
+ const message = err instanceof Error ? err.message : "Error al enviar formulario";
4091
+ setSubmitMessage(message);
4092
+ setFormStatus("error");
4093
+ }
4094
+ } else {
4095
+ console.log("[ReactiveForm] Submit:", values);
4096
+ console.log("[ReactiveForm] Payload map:", resolvedPayload);
4097
+ setFormStatus("completed");
4098
+ }
4099
+ };
4100
+ const resolveRows = (rows) => resolveSummaryRows(rows, values, fieldStates);
4101
+ return {
4102
+ formStatus,
4103
+ setFormStatus,
4104
+ submitMessage,
4105
+ currentStep,
4106
+ setCurrentStep,
4107
+ values,
4108
+ errors,
4109
+ touched,
4110
+ fieldStates,
4111
+ validationSchema,
4112
+ totalSteps,
4113
+ handleTriggerClick,
4114
+ setFieldValue,
4115
+ handleFieldChange,
4116
+ validateFields,
4117
+ validateStep,
4118
+ handleNext,
4119
+ handleBack,
4120
+ handleSubmit,
4121
+ getDependencies,
4122
+ allDepsResolved,
4123
+ resolveSummaryRows: resolveRows
4124
+ };
4125
+ }
4126
+
4127
+ const MOBILE_BREAKPOINT = 640;
4128
+ const useIsMobile$1 = () => {
4129
+ const [isMobile, setIsMobile] = useState(
4130
+ typeof window !== "undefined" ? window.innerWidth < MOBILE_BREAKPOINT : false
4131
+ );
4132
+ useEffect(() => {
4133
+ const mq = window.matchMedia(`(max-width: ${MOBILE_BREAKPOINT - 1}px)`);
4134
+ const handler = (e) => setIsMobile(e.matches);
4135
+ mq.addEventListener("change", handler);
4136
+ return () => mq.removeEventListener("change", handler);
4137
+ }, []);
4138
+ return isMobile;
4139
+ };
4140
+ const ReactiveForm = ({ component, eventBus }) => {
4141
+ const props = component.props;
4142
+ const isMobile = useIsMobile$1();
4143
+ const form = useReactiveForm({ ...props, eventBus });
4144
+ if (component.answered && form.formStatus !== "completed" && form.formStatus !== "warning" && form.formStatus !== "error") {
4145
+ form.setFormStatus("completed");
4146
+ }
4147
+ return /* @__PURE__ */ jsx(
4148
+ ReactiveFormView,
4149
+ {
4150
+ ...props,
4151
+ form,
4152
+ drawerPlacement: isMobile ? "bottom" : "right"
4153
+ }
4154
+ );
4155
+ };
4156
+
4157
+ function useStoreState(store, key) {
4158
+ const [value, setValue] = useState(() => store.get(key));
4159
+ useEffect(() => {
4160
+ return store.subscribe(key, setValue);
4161
+ }, [store, key]);
4162
+ return value;
4163
+ }
4164
+
4165
+ function createStore(initial) {
4166
+ const state = { ...initial };
4167
+ const listeners = {};
4168
+ const notify = (key, value) => {
4169
+ const keyStr = String(key);
4170
+ listeners[keyStr]?.forEach((l) => l(value));
4171
+ };
4172
+ const subscribe = (key, listener) => {
4173
+ const keyStr = String(key);
4174
+ if (!listeners[keyStr]) listeners[keyStr] = /* @__PURE__ */ new Set();
4175
+ listeners[keyStr].add(listener);
4176
+ listener(state[key]);
4177
+ return () => {
4178
+ listeners[keyStr].delete(listener);
4179
+ };
4180
+ };
4181
+ const set = (key, value) => {
4182
+ state[key] = value;
4183
+ notify(key, value);
4184
+ };
4185
+ const get = (key) => state[key];
4186
+ return { set, get, subscribe };
4187
+ }
4188
+
4189
+ const CAROUSEL_STORE_KEYS = {
4190
+ ITEMS: "items",
4191
+ ORIGINAL_ITEMS: "originalItems",
4192
+ SEARCH_QUERY: "searchQuery",
4193
+ SEARCH_STATUS: "searchStatus",
4194
+ SELECTED_IDS: "selectedIds",
4195
+ CURRENT_PAGE: "currentPage",
4196
+ HAS_MORE: "hasMore"
4197
+ };
4198
+
4199
+ function createCarouselStore(initialItems) {
4200
+ return createStore({
4201
+ [CAROUSEL_STORE_KEYS.ITEMS]: initialItems,
4202
+ [CAROUSEL_STORE_KEYS.ORIGINAL_ITEMS]: initialItems,
4203
+ [CAROUSEL_STORE_KEYS.SEARCH_QUERY]: "",
4204
+ [CAROUSEL_STORE_KEYS.SEARCH_STATUS]: "idle",
4205
+ [CAROUSEL_STORE_KEYS.SELECTED_IDS]: [],
4206
+ [CAROUSEL_STORE_KEYS.CURRENT_PAGE]: 0,
4207
+ [CAROUSEL_STORE_KEYS.HAS_MORE]: false
4208
+ });
4209
+ }
4210
+
4211
+ function createCarouselActions(store) {
4212
+ return {
4213
+ items: {
4214
+ set: (items) => store.set(CAROUSEL_STORE_KEYS.ITEMS, items),
4215
+ remove: (id) => {
4216
+ const current = store.get(CAROUSEL_STORE_KEYS.ITEMS);
4217
+ if (current.length <= 1) return;
4218
+ store.set(CAROUSEL_STORE_KEYS.ITEMS, current.filter((i) => i.id !== id));
4219
+ },
4220
+ get: () => store.get(CAROUSEL_STORE_KEYS.ITEMS)
4221
+ },
4222
+ selection: {
4223
+ toggle: (id) => {
4224
+ const current = store.get(CAROUSEL_STORE_KEYS.SELECTED_IDS);
4225
+ const next = current.includes(id) ? current.filter((i) => i !== id) : [...current, id];
4226
+ store.set(CAROUSEL_STORE_KEYS.SELECTED_IDS, next);
4227
+ },
4228
+ clear: () => store.set(CAROUSEL_STORE_KEYS.SELECTED_IDS, []),
4229
+ get: () => store.get(CAROUSEL_STORE_KEYS.SELECTED_IDS)
4230
+ },
4231
+ search: {
4232
+ setQuery: (query) => store.set(CAROUSEL_STORE_KEYS.SEARCH_QUERY, query),
4233
+ setStatus: (status) => store.set(CAROUSEL_STORE_KEYS.SEARCH_STATUS, status),
4234
+ getQuery: () => store.get(CAROUSEL_STORE_KEYS.SEARCH_QUERY)
4235
+ },
4236
+ pagination: {
4237
+ setPage: (page) => store.set(CAROUSEL_STORE_KEYS.CURRENT_PAGE, page),
4238
+ setHasMore: (hasMore) => store.set(CAROUSEL_STORE_KEYS.HAS_MORE, hasMore),
4239
+ getPage: () => store.get(CAROUSEL_STORE_KEYS.CURRENT_PAGE)
4240
+ },
4241
+ getOriginalItems: () => store.get(CAROUSEL_STORE_KEYS.ORIGINAL_ITEMS)
4242
+ };
4243
+ }
4244
+
4245
+ const SIZE_PX = { small: 80, medium: 120, large: 180 };
4246
+ const GAP_PX = 8;
4247
+ function calcPageLimit(size, containerWidth) {
4248
+ const cardWidth = SIZE_PX[size];
4249
+ return Math.max(1, Math.floor(containerWidth / (cardWidth + GAP_PX)));
4250
+ }
4251
+ function resolveSize(size, itemCount) {
4252
+ if (size && size !== "auto") return size;
4253
+ if (itemCount <= 3) return "large";
4254
+ if (itemCount <= 6) return "medium";
4255
+ return "small";
4256
+ }
4257
+ function mapResponseToItems(data, endpoint) {
4258
+ let unwrapped = data;
4259
+ if (unwrapped && typeof unwrapped === "object" && "response" in unwrapped) {
4260
+ unwrapped = unwrapped.response;
4261
+ }
4262
+ if (endpoint.response_path && unwrapped && typeof unwrapped === "object" && !Array.isArray(unwrapped)) {
4263
+ unwrapped = unwrapped[endpoint.response_path];
4264
+ }
4265
+ const arr = Array.isArray(unwrapped) ? unwrapped : [];
4266
+ return arr.map((item) => {
4267
+ const metadata = {};
4268
+ if (endpoint.extra_fields) {
4269
+ for (const field of endpoint.extra_fields) {
4270
+ metadata[field] = item[field];
4271
+ }
4272
+ }
4273
+ return {
4274
+ id: String(item[endpoint.id_field] ?? ""),
4275
+ type: endpoint.item_type,
4276
+ title: endpoint.title_field ? String(item[endpoint.title_field] ?? "") : void 0,
4277
+ description: endpoint.description_field ? String(item[endpoint.description_field] ?? "") : void 0,
4278
+ src: endpoint.src_field ? String(item[endpoint.src_field] ?? "") : void 0,
4279
+ file_type: endpoint.file_type_field ? String(item[endpoint.file_type_field] ?? "") : void 0,
4280
+ status: "ready",
4281
+ metadata: Object.keys(metadata).length > 0 ? metadata : void 0
4282
+ };
4283
+ });
4284
+ }
4285
+
4286
+ const MOCK_NAMES = [
4287
+ "Alpha",
4288
+ "Beta",
4289
+ "Gamma",
4290
+ "Delta",
4291
+ "Epsilon",
4292
+ "Zeta",
4293
+ "Eta",
4294
+ "Theta",
4295
+ "Iota",
4296
+ "Kappa",
4297
+ "Lambda",
4298
+ "Mu",
4299
+ "Nu",
4300
+ "Xi",
4301
+ "Omicron",
4302
+ "Pi",
4303
+ "Rho",
4304
+ "Sigma",
4305
+ "Tau",
4306
+ "Upsilon",
4307
+ "Phi",
4308
+ "Chi",
4309
+ "Psi",
4310
+ "Omega",
4311
+ "Altair",
4312
+ "Vega",
4313
+ "Sirius",
4314
+ "Rigel",
4315
+ "Polaris",
4316
+ "Antares"
4317
+ ];
4318
+ const MOCK_ITEMS = MOCK_NAMES.map((name, i) => ({
4319
+ id: String(i + 1),
4320
+ name: `Empresa ${name}`,
4321
+ address: `Calle ${i + 1} #${(i + 1) * 10}-${(i + 1) * 5}`,
4322
+ logo_url: `https://picsum.photos/seed/${name.toLowerCase()}/200`
4323
+ }));
4324
+ async function mockSearchFetch(query, skip, limit) {
4325
+ await new Promise((r) => setTimeout(r, 400 + Math.random() * 300));
4326
+ let filtered = MOCK_ITEMS;
4327
+ if (query) {
4328
+ filtered = MOCK_ITEMS.filter((i) => i.name.toLowerCase().includes(query.toLowerCase()));
4329
+ }
4330
+ return filtered.slice(skip, skip + limit);
4331
+ }
4332
+ function useCarouselSearch({ actions, endpoint, eventBus, pageLimit }) {
4333
+ const loadingRef = useRef(false);
4334
+ const search = useCallback(
4335
+ async (query, page = 0) => {
4336
+ if (loadingRef.current) return;
4337
+ loadingRef.current = true;
4338
+ actions.search.setQuery(query);
4339
+ if (page === 0) {
4340
+ actions.search.setStatus("loading");
4341
+ }
4342
+ const limit = endpoint?.limit ?? pageLimit;
4343
+ const skip = page * limit;
4344
+ const startTime = Date.now();
4345
+ try {
4346
+ let rawData;
4347
+ if (eventBus && endpoint) {
4348
+ const baseBody = endpoint.body ?? {};
4349
+ const cleanBody = {};
4350
+ for (const [k, v] of Object.entries(baseBody)) {
4351
+ if (typeof v === "string" && v.includes("$query")) continue;
4352
+ cleanBody[k] = v;
4353
+ }
4354
+ const body = {
4355
+ ...cleanBody,
4356
+ skip,
4357
+ limit
4358
+ };
4359
+ if (query && endpoint.query_param) {
4360
+ body.filters = [
4361
+ ...Array.isArray(body.filters) ? body.filters : [],
4362
+ { field: endpoint.query_param, condition: "like", value: query }
4363
+ ];
4364
+ }
4365
+ eventBus.emit(CHAT_EVENT.FORM_TRACE, {
4366
+ chatId: "",
4367
+ formTitle: "carousel",
4368
+ source: "carousel",
4369
+ phase: "request",
4370
+ service: endpoint.service,
4371
+ url: endpoint.url,
4372
+ method: endpoint.method,
4373
+ body
4374
+ });
4375
+ rawData = await fetchViaEventBus(
4376
+ eventBus,
4377
+ endpoint.service,
4378
+ endpoint.url,
4379
+ endpoint.method,
4380
+ body
4381
+ );
4382
+ eventBus.emit(CHAT_EVENT.FORM_TRACE, {
4383
+ chatId: "",
4384
+ formTitle: "carousel",
4385
+ source: "carousel",
4386
+ phase: "response",
4387
+ service: endpoint.service,
4388
+ url: endpoint.url,
4389
+ method: endpoint.method,
4390
+ status: 200,
4391
+ duration_ms: Date.now() - startTime,
4392
+ success: true,
4393
+ response: rawData
4394
+ });
4395
+ } else {
4396
+ rawData = await mockSearchFetch(query, skip, limit);
4397
+ }
4398
+ let newItems;
4399
+ if (endpoint) {
4400
+ newItems = mapResponseToItems(rawData, endpoint);
4401
+ } else {
4402
+ const arr = Array.isArray(rawData) ? rawData : [];
4403
+ newItems = arr.map((item) => ({
4404
+ id: String(item.id ?? ""),
4405
+ type: "image",
4406
+ title: String(item.name ?? ""),
4407
+ description: String(item.address ?? ""),
4408
+ src: String(item.logo_url ?? ""),
4409
+ status: "ready"
4410
+ }));
4411
+ }
4412
+ actions.items.set(newItems);
4413
+ actions.pagination.setPage(page);
4414
+ actions.pagination.setHasMore(newItems.length === limit);
4415
+ actions.search.setStatus("idle");
4416
+ } catch (err) {
4417
+ actions.search.setStatus("error");
4418
+ if (eventBus && endpoint) {
4419
+ eventBus.emit(CHAT_EVENT.FORM_TRACE, {
4420
+ chatId: "",
4421
+ formTitle: "carousel",
4422
+ source: "carousel",
4423
+ phase: "response",
4424
+ service: endpoint.service,
4425
+ url: endpoint.url,
4426
+ method: endpoint.method,
4427
+ status: 500,
4428
+ duration_ms: Date.now() - startTime,
4429
+ success: false,
4430
+ error: err instanceof Error ? err.message : "Error en busqueda"
4431
+ });
4432
+ }
4433
+ } finally {
4434
+ loadingRef.current = false;
4435
+ }
4436
+ },
4437
+ [actions, endpoint, eventBus, pageLimit]
4438
+ );
4439
+ const loadNext = useCallback(() => {
4440
+ const currentPage = actions.pagination.getPage();
4441
+ const query = actions.search.getQuery();
4442
+ search(query, currentPage + 1);
4443
+ }, [actions, search]);
4444
+ const loadPrev = useCallback(() => {
4445
+ const currentPage = actions.pagination.getPage();
4446
+ if (currentPage <= 0) return;
4447
+ const query = actions.search.getQuery();
4448
+ search(query, currentPage - 1);
4449
+ }, [actions, search]);
4450
+ return { search, loadNext, loadPrev };
4451
+ }
4452
+
4453
+ const FILE_ICONS = {
4454
+ pdf: "\u{1F4C4}",
4455
+ doc: "\u{1F4DD}",
4456
+ docx: "\u{1F4DD}",
4457
+ xls: "\u{1F4CA}",
4458
+ xlsx: "\u{1F4CA}",
4459
+ ppt: "\u{1F4CE}",
4460
+ pptx: "\u{1F4CE}",
4461
+ zip: "\u{1F4E6}",
4462
+ rar: "\u{1F4E6}",
4463
+ jpg: "\u{1F5BC}\uFE0F",
4464
+ jpeg: "\u{1F5BC}\uFE0F",
4465
+ png: "\u{1F5BC}\uFE0F",
4466
+ gif: "\u{1F5BC}\uFE0F",
4467
+ webp: "\u{1F5BC}\uFE0F",
4468
+ mp4: "\u{1F3AC}",
4469
+ mov: "\u{1F3AC}",
4470
+ avi: "\u{1F3AC}",
4471
+ mp3: "\u{1F3B5}",
4472
+ wav: "\u{1F3B5}"
4473
+ };
4474
+ const CarouselCard = ({
4475
+ item,
4476
+ size,
4477
+ selectionMode,
4478
+ isSelected,
4479
+ disabled,
4480
+ onSelect,
4481
+ onRemove,
4482
+ onPreview
4483
+ }) => {
4484
+ const isSelectable = selectionMode !== "none" && !disabled;
4485
+ const hasPreview = selectionMode === "none" && !!onPreview && item.src && (item.type === "image" || item.type === "file");
4486
+ const isClickable = isSelectable || hasPreview;
4487
+ const handleClick = () => {
4488
+ if (isSelectable) {
4489
+ if (selectionMode === "removable") return;
4490
+ onSelect(item);
4491
+ return;
4492
+ }
4493
+ if (hasPreview) {
4494
+ onPreview(item);
4495
+ }
4496
+ };
4497
+ const handleRemove = (e) => {
4498
+ e.stopPropagation();
4499
+ if (disabled) return;
4500
+ onRemove(item);
4501
+ };
4502
+ if (item.status === "loading") {
4503
+ return /* @__PURE__ */ jsx("div", { className: `px-chat-carousel-card px-chat-carousel-card--${size} px-chat-carousel-card--loading`, children: /* @__PURE__ */ jsx("div", { className: "px-chat-carousel-card__skeleton" }) });
4504
+ }
4505
+ return /* @__PURE__ */ jsxs(
4506
+ "div",
4507
+ {
4508
+ className: [
4509
+ "px-chat-carousel-card",
4510
+ `px-chat-carousel-card--${size}`,
4511
+ `px-chat-carousel-card--${item.type}`,
4512
+ isSelected ? "px-chat-carousel-card--selected" : "",
4513
+ isClickable ? "px-chat-carousel-card--clickable" : "",
4514
+ disabled ? "px-chat-carousel-card--disabled" : ""
4515
+ ].filter(Boolean).join(" "),
4516
+ onClick: handleClick,
4517
+ role: isClickable ? "button" : void 0,
4518
+ tabIndex: isClickable ? 0 : void 0,
4519
+ onKeyDown: isClickable ? (e) => {
4520
+ if (e.key === "Enter" || e.key === " ") handleClick();
4521
+ } : void 0,
4522
+ children: [
4523
+ selectionMode === "removable" && !disabled && /* @__PURE__ */ jsx(
4524
+ "button",
4525
+ {
4526
+ className: "px-chat-carousel-card__remove",
4527
+ onClick: handleRemove,
4528
+ "aria-label": "Eliminar",
4529
+ type: "button",
4530
+ children: "\xD7"
4531
+ }
4532
+ ),
4533
+ isSelected && selectionMode !== "removable" && /* @__PURE__ */ jsx("div", { className: "px-chat-carousel-card__check", children: "\u2713" }),
4534
+ item.type === "image" && /* @__PURE__ */ jsx(
4535
+ "img",
4536
+ {
4537
+ className: "px-chat-carousel-card__image",
4538
+ src: item.src,
4539
+ alt: item.title || "",
4540
+ loading: "lazy"
4541
+ }
4542
+ ),
4543
+ item.type === "file" && /* @__PURE__ */ jsx("div", { className: "px-chat-carousel-card__file-icon", children: FILE_ICONS[item.file_type?.toLowerCase() ?? ""] || "\u{1F4C1}" }),
4544
+ item.type === "text" && !item.title && !item.description && /* @__PURE__ */ jsx("div", { className: "px-chat-carousel-card__file-icon", children: "\u{1F4CB}" }),
4545
+ (item.title || item.description) && /* @__PURE__ */ jsxs("div", { className: "px-chat-carousel-card__info", children: [
4546
+ item.title && /* @__PURE__ */ jsx("div", { className: "px-chat-carousel-card__title", children: item.title }),
4547
+ item.description && /* @__PURE__ */ jsx("div", { className: "px-chat-carousel-card__description", children: item.description })
4548
+ ] })
4549
+ ]
4550
+ }
4551
+ );
4552
+ };
4553
+
4554
+ const CarouselTrack = ({
4555
+ currentPage,
4556
+ hasMore,
4557
+ onPrev,
4558
+ onNext,
4559
+ children
4560
+ }) => {
4561
+ const trackRef = useRef(null);
4562
+ useEffect(() => {
4563
+ if (trackRef.current) {
4564
+ trackRef.current.scrollLeft = 0;
4565
+ }
4566
+ }, [currentPage]);
4567
+ const showPrev = currentPage > 0;
4568
+ const showNext = hasMore;
4569
+ return /* @__PURE__ */ jsxs("div", { className: "px-chat-carousel-track-wrapper", children: [
4570
+ showPrev && /* @__PURE__ */ jsx(
4571
+ "button",
4572
+ {
4573
+ className: "px-chat-carousel-track__nav",
4574
+ onClick: onPrev,
4575
+ type: "button",
4576
+ "aria-label": "Anterior",
4577
+ children: /* @__PURE__ */ jsx("svg", { width: "20", height: "20", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsx("polyline", { points: "15 18 9 12 15 6" }) })
4578
+ }
4579
+ ),
4580
+ /* @__PURE__ */ jsx("div", { className: "px-chat-carousel-track", ref: trackRef, children }),
4581
+ showNext && /* @__PURE__ */ jsx(
4582
+ "button",
4583
+ {
4584
+ className: "px-chat-carousel-track__nav",
4585
+ onClick: onNext,
4586
+ type: "button",
4587
+ "aria-label": "Siguiente",
4588
+ children: /* @__PURE__ */ jsx("svg", { width: "20", height: "20", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsx("polyline", { points: "9 18 15 12 9 6" }) })
4589
+ }
4590
+ )
4591
+ ] });
4592
+ };
4593
+
4594
+ const DEBOUNCE_MS = 300;
4595
+ const CarouselSearch = ({ onSearch, loading }) => {
4596
+ const [value, setValue] = useState("");
4597
+ const timerRef = useRef(void 0);
4598
+ const onSearchRef = useRef(onSearch);
4599
+ onSearchRef.current = onSearch;
4600
+ useEffect(() => {
4601
+ clearTimeout(timerRef.current);
4602
+ timerRef.current = setTimeout(() => {
4603
+ onSearchRef.current(value);
4604
+ }, DEBOUNCE_MS);
4605
+ return () => clearTimeout(timerRef.current);
4606
+ }, [value]);
4607
+ return /* @__PURE__ */ jsxs("div", { className: "px-chat-carousel-search", children: [
4608
+ /* @__PURE__ */ jsx(
4609
+ "input",
4610
+ {
4611
+ className: "px-chat-carousel-search__input",
4612
+ type: "text",
4613
+ placeholder: "Buscar...",
4614
+ value,
4615
+ onChange: (e) => setValue(e.target.value)
4616
+ }
4617
+ ),
4618
+ loading && /* @__PURE__ */ jsx("span", { className: "px-chat-carousel-search__spinner" }),
4619
+ value && !loading && /* @__PURE__ */ jsx(
4620
+ "button",
4621
+ {
4622
+ className: "px-chat-carousel-search__clear",
4623
+ onClick: () => setValue(""),
4624
+ type: "button",
4625
+ "aria-label": "Limpiar",
4626
+ children: "\xD7"
4627
+ }
4628
+ )
4629
+ ] });
4630
+ };
4631
+
4632
+ const CarouselConfirm = ({
4633
+ label,
4634
+ count,
4635
+ disabled,
4636
+ onClick
4637
+ }) => {
4638
+ return /* @__PURE__ */ jsx("div", { className: "px-chat-carousel-confirm", children: /* @__PURE__ */ jsxs(
4639
+ "button",
4640
+ {
4641
+ className: "px-chat-carousel-confirm__button",
4642
+ disabled,
4643
+ onClick,
4644
+ type: "button",
4645
+ children: [
4646
+ label,
4647
+ " ",
4648
+ count > 0 && /* @__PURE__ */ jsxs("span", { className: "px-chat-carousel-confirm__count", children: [
4649
+ "(",
4650
+ count,
4651
+ ")"
4652
+ ] })
4653
+ ]
4654
+ }
4655
+ ) });
4656
+ };
4657
+
4658
+ const CarouselDisplay = ({
4659
+ component,
4660
+ eventBus,
4661
+ assistantMessageId = ""
4662
+ }) => {
4663
+ const props = component.props;
4664
+ const {
4665
+ items: initialItems = [],
4666
+ size: sizeProp,
4667
+ selection_mode: selectionMode = "none",
4668
+ confirm_label: confirmLabel = "Confirmar",
4669
+ searchable = false,
4670
+ search_endpoint: searchEndpoint,
4671
+ field_name: fieldName = ""
4672
+ } = props;
4673
+ const isAnswered = component.answered === true;
4674
+ const disabled = isAnswered && selectionMode !== "none";
4675
+ const { store, actions } = useMemo(() => {
4676
+ const s = createCarouselStore(initialItems);
4677
+ if (searchable && initialItems.length === 0) {
4678
+ s.set(CAROUSEL_STORE_KEYS.SEARCH_STATUS, "loading");
4679
+ }
4680
+ return { store: s, actions: createCarouselActions(s) };
4681
+ }, []);
4682
+ const items = useStoreState(store, CAROUSEL_STORE_KEYS.ITEMS);
4683
+ const selectedIds = useStoreState(store, CAROUSEL_STORE_KEYS.SELECTED_IDS);
4684
+ const searchStatus = useStoreState(store, CAROUSEL_STORE_KEYS.SEARCH_STATUS);
4685
+ const hasMore = useStoreState(store, CAROUSEL_STORE_KEYS.HAS_MORE);
4686
+ const currentPage = useStoreState(store, CAROUSEL_STORE_KEYS.CURRENT_PAGE);
4687
+ const containerRef = useRef(null);
4688
+ const resolvedSize = resolveSize(sizeProp, items.length);
4689
+ const pageLimit = useMemo(() => {
4690
+ const width = containerRef.current?.clientWidth ?? window.innerWidth;
4691
+ return calcPageLimit(resolvedSize, width);
4692
+ }, [resolvedSize]);
4693
+ const { emitInteraction, isConfirmed } = useComponentInteraction({
4694
+ eventBus,
4695
+ fieldName,
4696
+ componentType: "carousel",
4697
+ assistantMessageId
4698
+ });
4699
+ const { search, loadNext, loadPrev } = useCarouselSearch({
4700
+ actions,
4701
+ endpoint: searchEndpoint,
4702
+ eventBus,
4703
+ pageLimit
4704
+ });
4705
+ useEffect(() => {
4706
+ if (searchable && initialItems.length === 0) {
4707
+ search("", 0);
4708
+ }
4709
+ }, []);
4710
+ const handleSelect = useCallback(
4711
+ (item) => {
4712
+ if (disabled || isConfirmed) return;
4713
+ if (selectionMode === "single") {
4714
+ actions.selection.clear();
4715
+ actions.selection.toggle(item.id);
4716
+ emitInteraction(
4717
+ [{ value: item.id, label: item.title || item.id }],
4718
+ item.title || item.id
4719
+ );
4720
+ return;
4721
+ }
4722
+ if (selectionMode === "multiple") {
4723
+ actions.selection.toggle(item.id);
4724
+ }
4725
+ },
4726
+ [selectionMode, disabled, isConfirmed, actions, emitInteraction]
4727
+ );
4728
+ const handleRemove = useCallback(
4729
+ (item) => {
4730
+ if (disabled || isConfirmed) return;
4731
+ actions.items.remove(item.id);
4732
+ },
4733
+ [disabled, isConfirmed, actions]
4734
+ );
4735
+ const handleConfirm = useCallback(() => {
4736
+ if (disabled || isConfirmed) return;
4737
+ if (selectionMode === "multiple") {
4738
+ const selected = items.filter((i) => selectedIds.includes(i.id));
4739
+ const value = selected.map((i) => ({ value: i.id, label: i.title || i.id }));
4740
+ const label = selected.map((i) => i.title || i.id).join(", ");
4741
+ emitInteraction(value, label);
4742
+ }
4743
+ if (selectionMode === "removable") {
4744
+ const value = items.map((i) => ({ value: i.id, label: i.title || i.id }));
4745
+ const label = items.map((i) => i.title || i.id).join(", ");
4746
+ emitInteraction(value, label);
4747
+ }
4748
+ }, [selectionMode, disabled, isConfirmed, items, selectedIds, emitInteraction]);
4749
+ const confirmDisabled = useMemo(() => {
4750
+ if (selectionMode === "multiple") return selectedIds.length === 0;
4751
+ if (selectionMode === "removable") {
4752
+ const originalLen = actions.getOriginalItems().length;
4753
+ return items.length === originalLen;
4754
+ }
4755
+ return true;
4756
+ }, [selectionMode, selectedIds, items, actions]);
4757
+ const showConfirm = (selectionMode === "multiple" || selectionMode === "removable") && !disabled && !isConfirmed;
4758
+ if (selectionMode === "single" && (isConfirmed || isAnswered)) {
4759
+ return null;
4760
+ }
4761
+ return /* @__PURE__ */ jsxs("div", { className: "px-chat-carousel", ref: containerRef, children: [
4762
+ searchable && /* @__PURE__ */ jsx(
4763
+ CarouselSearch,
4764
+ {
4765
+ onSearch: (q) => search(q, 0),
4766
+ loading: searchStatus === "loading"
4767
+ }
4768
+ ),
4769
+ /* @__PURE__ */ jsx(
4770
+ CarouselTrack,
4771
+ {
4772
+ currentPage,
4773
+ hasMore,
4774
+ onPrev: loadPrev,
4775
+ onNext: loadNext,
4776
+ children: items.map((item) => /* @__PURE__ */ jsx(
4777
+ CarouselCard,
4778
+ {
4779
+ item,
4780
+ size: resolvedSize,
4781
+ selectionMode,
4782
+ isSelected: selectedIds.includes(item.id),
4783
+ disabled: disabled || isConfirmed,
4784
+ onSelect: handleSelect,
4785
+ onRemove: handleRemove
4786
+ },
4787
+ item.id
4788
+ ))
4789
+ }
4790
+ ),
4791
+ showConfirm && /* @__PURE__ */ jsx(
4792
+ CarouselConfirm,
4793
+ {
4794
+ label: confirmLabel,
4795
+ count: selectionMode === "multiple" ? selectedIds.length : items.length,
4796
+ disabled: confirmDisabled,
4797
+ onClick: handleConfirm
4798
+ }
4799
+ ),
4800
+ items.length === 0 && searchStatus !== "loading" && /* @__PURE__ */ jsx("div", { className: "px-chat-carousel__empty", children: "Sin resultados" })
4801
+ ] });
4802
+ };
4803
+
4804
+ const COMPONENT_MAP = {
4805
+ select: SelectWithConfirm,
4806
+ select_multiple: SelectMultipleWithConfirm,
4807
+ confirm: ConfirmButton,
4808
+ date_input: DateInputWithConfirm,
4809
+ time_input: TimeInputWithConfirm,
4810
+ input: InputWithConfirm,
4811
+ card: CardDisplay,
4812
+ badge: BadgeDisplay,
4813
+ reactive_form: ReactiveForm,
4814
+ carousel: CarouselDisplay
4815
+ };
4816
+ function renderComponent(props) {
4817
+ const { component } = props;
4818
+ if (component.answered && !DISPLAY_COMPONENTS.has(component.type)) {
4819
+ return null;
4820
+ }
4821
+ const Component = COMPONENT_MAP[component.type];
4822
+ if (!Component) return null;
4823
+ return /* @__PURE__ */ jsx(Component, { ...props });
4824
+ }
4825
+
4826
+ const StructuredContent = ({
4827
+ content,
4828
+ eventBus,
4829
+ assistantMessageId,
4830
+ className = ""
4831
+ }) => {
4832
+ const structured = parseContent(content);
4833
+ const markdownContent = structured ? structured.message : content;
4834
+ const rawComponent = structured?.component || null;
4835
+ const components = rawComponent ? Array.isArray(rawComponent) ? rawComponent : [rawComponent] : [];
4836
+ const hasVisibleComponents = components.some((comp) => !comp.answered || DISPLAY_COMPONENTS.has(comp.type));
4837
+ return /* @__PURE__ */ jsxs("div", { className: `${COMPONENT_PREFIX$1}structured-content ${className}`, children: [
4838
+ markdownContent && /* @__PURE__ */ jsx("div", { className: `${COMPONENT_PREFIX$1}assistant-message__markdown${hasVisibleComponents ? ` ${COMPONENT_PREFIX$1}assistant-message__markdown--with-component` : ``}`, children: /* @__PURE__ */ jsx(
4839
+ ReactMarkdown,
4840
+ {
4841
+ components: {
4842
+ a: ({ href, children }) => /* @__PURE__ */ jsx(
4843
+ Link,
4844
+ {
4845
+ href: href || "#",
4846
+ variant: "primary",
4847
+ size: "medium",
4848
+ weight: "bold",
4849
+ underline: false,
4850
+ children
4851
+ }
4852
+ )
4853
+ },
4854
+ children: markdownContent
4855
+ }
4856
+ ) }),
4857
+ components.length > 0 && /* @__PURE__ */ jsx("div", { className: `${COMPONENT_PREFIX$1}structured-content__component`, children: components.map((comp, index) => /* @__PURE__ */ jsx(React.Fragment, { children: renderComponent({ component: comp, eventBus, assistantMessageId }) }, `${comp.type}-${index}`)) })
4858
+ ] });
4859
+ };
4860
+
4861
+ const getAttachmentType = (file) => {
4862
+ const mimeType = file.type.toLowerCase();
4863
+ if (mimeType.startsWith(MIME_PREFIXES.AUDIO)) {
4864
+ return AttachmentType.AUDIO;
4865
+ }
4866
+ if (mimeType.startsWith(MIME_PREFIXES.VIDEO)) {
4867
+ return AttachmentType.VIDEO;
4868
+ }
4869
+ if (mimeType.startsWith(MIME_PREFIXES.IMAGE)) {
4870
+ return AttachmentType.IMAGE;
4871
+ }
4872
+ if (mimeType === MIME_TYPES.PDF) {
4873
+ return AttachmentType.PDF;
4874
+ }
4875
+ 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)) {
4876
+ return AttachmentType.DOCUMENT;
4877
+ }
4878
+ return AttachmentType.OTHER;
4879
+ };
4880
+ const filterFilesByType = (files, type) => {
4881
+ const types = Array.isArray(type) ? type : [type];
4882
+ return files.filter((file) => {
4883
+ const fileType = getAttachmentType(file);
4884
+ return types.includes(fileType);
4885
+ });
4886
+ };
4887
+ const getFileUrl = (file) => {
4888
+ if (file.url) {
4889
+ return file.url;
4890
+ }
4891
+ return URL.createObjectURL(file);
4892
+ };
4893
+ const getAudioFiles = (files) => {
4894
+ return filterFilesByType(files, [AttachmentType.AUDIO]);
4895
+ };
4896
+ const getNonAudioFiles = (files) => {
4897
+ return filterFilesByType(files, [
4898
+ AttachmentType.IMAGE,
4899
+ AttachmentType.PDF,
4900
+ AttachmentType.DOCUMENT,
4901
+ AttachmentType.OTHER
4902
+ ]);
4903
+ };
4904
+
4905
+ function deepMerge(target, source) {
3100
4906
  if (typeof target !== "object" || target === null) {
3101
4907
  return source;
3102
4908
  }
@@ -3197,24 +5003,248 @@ const AssistantMessage = ({
3197
5003
  className: `${COMPONENT_PREFIX$1}assistant-message__timestamp`,
3198
5004
  children: timestamp
3199
5005
  }
3200
- )
3201
- ] }) });
5006
+ )
5007
+ ] }) });
5008
+ };
5009
+
5010
+ const initialState$1 = {
5011
+ // ChatInput (molécula) - Estados del input de chat
5012
+ chatInput: {
5013
+ buttonSend: {
5014
+ disabled: true,
5015
+ // Disabled hasta que haya contenido
5016
+ visible: false
5017
+ // Inicialmente oculto
5018
+ },
5019
+ buttonMicrophone: {
5020
+ disabled: false,
5021
+ visible: true
5022
+ // Inicialmente visible (botón de audio por defecto)
5023
+ },
5024
+ buttonAttachment: {
5025
+ disabled: false
5026
+ },
5027
+ hasText: false,
5028
+ hasAttachments: false
5029
+ },
5030
+ // AssistantThinkingIndicator (molécula) - Estado del indicador
5031
+ assistantThinkingIndicator: {
5032
+ visible: false,
5033
+ agentName: void 0,
5034
+ agentLabel: void 0,
5035
+ toolName: void 0
5036
+ },
5037
+ // ScrollButton (átomo) - Estado del botón de scroll
5038
+ scrollButton: {
5039
+ visible: false
5040
+ },
5041
+ // VirtualKeyboard - Estado del teclado virtual
5042
+ virtualKeyboard: {
5043
+ isOpen: false
5044
+ },
5045
+ // Textarea - Estado del textarea del chat
5046
+ textarea: {
5047
+ isFocused: false,
5048
+ isEmpty: true,
5049
+ shouldPreventKeyboard: false,
5050
+ shouldFocus: false,
5051
+ shouldBlur: false
5052
+ },
5053
+ // Scroll to top trigger
5054
+ scrollToTop: {
5055
+ pending: false
5056
+ }
5057
+ };
5058
+ const chatStore = createStore(initialState$1);
5059
+ const setChatStore = createStoreMerger(chatStore);
5060
+ const subscribeChatProperty = createDeepPropertySubscriber(chatStore);
5061
+
5062
+ const CHAT_STORE_KEYS = {
5063
+ // ChatInput relacionado
5064
+ CHAT_INPUT: "chatInput",
5065
+ // AssistantThinkingIndicator relacionado
5066
+ ASSISTANT_THINKING_INDICATOR: "assistantThinkingIndicator",
5067
+ // ScrollButton relacionado
5068
+ SCROLL_BUTTON: "scrollButton",
5069
+ // VirtualKeyboard relacionado
5070
+ VIRTUAL_KEYBOARD: "virtualKeyboard",
5071
+ // Textarea relacionado
5072
+ TEXTAREA: "textarea",
5073
+ // Scroll to top trigger
5074
+ SCROLL_TO_TOP: "scrollToTop"
5075
+ };
5076
+
5077
+ const textareaActions = {
5078
+ focus: () => setChatStore(CHAT_STORE_KEYS.TEXTAREA, { shouldFocus: true }),
5079
+ blur: () => setChatStore(CHAT_STORE_KEYS.TEXTAREA, { shouldBlur: true }),
5080
+ setFocused: (isFocused) => setChatStore(CHAT_STORE_KEYS.TEXTAREA, { isFocused }),
5081
+ setEmpty: (isEmpty) => setChatStore(CHAT_STORE_KEYS.TEXTAREA, { isEmpty }),
5082
+ setShouldPreventKeyboard: (shouldPrevent) => setChatStore(CHAT_STORE_KEYS.TEXTAREA, { shouldPreventKeyboard: shouldPrevent }),
5083
+ resetTriggers: () => setChatStore(CHAT_STORE_KEYS.TEXTAREA, { shouldFocus: false, shouldBlur: false }),
5084
+ maintainFocusAfterSend: () => {
5085
+ setTimeout(() => {
5086
+ setChatStore(CHAT_STORE_KEYS.TEXTAREA, { shouldFocus: true });
5087
+ }, 10);
5088
+ setTimeout(() => {
5089
+ setChatStore(CHAT_STORE_KEYS.TEXTAREA, { shouldFocus: true });
5090
+ }, 50);
5091
+ },
5092
+ preserveFocusWithKeyboard: () => {
5093
+ setChatStore(CHAT_STORE_KEYS.TEXTAREA, { shouldFocus: true });
5094
+ setTimeout(() => {
5095
+ setChatStore(CHAT_STORE_KEYS.TEXTAREA, { shouldFocus: true });
5096
+ }, 10);
5097
+ setTimeout(() => {
5098
+ setChatStore(CHAT_STORE_KEYS.TEXTAREA, { shouldFocus: true });
5099
+ }, 50);
5100
+ }
5101
+ };
5102
+ const keyboardActions = {
5103
+ setOpen: (isOpen) => setChatStore(CHAT_STORE_KEYS.VIRTUAL_KEYBOARD, { isOpen }),
5104
+ open: () => setChatStore(CHAT_STORE_KEYS.VIRTUAL_KEYBOARD, { isOpen: true }),
5105
+ close: () => setChatStore(CHAT_STORE_KEYS.VIRTUAL_KEYBOARD, { isOpen: false })
5106
+ };
5107
+ const chatInputActions = {
5108
+ setSendDisabled: (disabled) => {
5109
+ const currentState = chatStore.get(CHAT_STORE_KEYS.CHAT_INPUT);
5110
+ setChatStore(CHAT_STORE_KEYS.CHAT_INPUT, {
5111
+ buttonSend: {
5112
+ disabled,
5113
+ visible: currentState.buttonSend.visible
5114
+ }
5115
+ });
5116
+ },
5117
+ setMicDisabled: (disabled) => {
5118
+ const currentState = chatStore.get(CHAT_STORE_KEYS.CHAT_INPUT);
5119
+ setChatStore(CHAT_STORE_KEYS.CHAT_INPUT, {
5120
+ buttonMicrophone: {
5121
+ disabled,
5122
+ visible: currentState.buttonMicrophone.visible
5123
+ }
5124
+ });
5125
+ },
5126
+ setAttachDisabled: (disabled) => setChatStore(CHAT_STORE_KEYS.CHAT_INPUT, { buttonAttachment: { disabled } }),
5127
+ setSendVisible: (visible) => {
5128
+ const currentState = chatStore.get(CHAT_STORE_KEYS.CHAT_INPUT);
5129
+ setChatStore(CHAT_STORE_KEYS.CHAT_INPUT, {
5130
+ buttonSend: {
5131
+ visible,
5132
+ disabled: currentState.buttonSend.disabled
5133
+ }
5134
+ });
5135
+ },
5136
+ setMicVisible: (visible) => {
5137
+ const currentState = chatStore.get(CHAT_STORE_KEYS.CHAT_INPUT);
5138
+ setChatStore(CHAT_STORE_KEYS.CHAT_INPUT, {
5139
+ buttonMicrophone: {
5140
+ visible,
5141
+ disabled: currentState.buttonMicrophone.disabled
5142
+ }
5143
+ });
5144
+ },
5145
+ setHasText: (hasText) => setChatStore(CHAT_STORE_KEYS.CHAT_INPUT, { hasText }),
5146
+ setHasAttachments: (hasAttachments) => setChatStore(CHAT_STORE_KEYS.CHAT_INPUT, { hasAttachments }),
5147
+ updateButtonVisibility: (hasText, hasAttachments) => {
5148
+ const shouldShowSend = hasText || hasAttachments;
5149
+ const shouldShowMic = !hasText && !hasAttachments;
5150
+ const isThinking = chatStore.get(CHAT_STORE_KEYS.ASSISTANT_THINKING_INDICATOR).visible;
5151
+ const hasContent = hasText || hasAttachments;
5152
+ const currentState = chatStore.get(CHAT_STORE_KEYS.CHAT_INPUT);
5153
+ setChatStore(CHAT_STORE_KEYS.CHAT_INPUT, {
5154
+ hasText,
5155
+ hasAttachments,
5156
+ buttonSend: {
5157
+ visible: shouldShowSend,
5158
+ disabled: isThinking || !hasContent
5159
+ },
5160
+ buttonMicrophone: {
5161
+ visible: shouldShowMic,
5162
+ disabled: currentState.buttonMicrophone.disabled
5163
+ }
5164
+ });
5165
+ }
5166
+ };
5167
+ const thinkingActions = {
5168
+ setVisible: (visible) => setChatStore(CHAT_STORE_KEYS.ASSISTANT_THINKING_INDICATOR, { visible }),
5169
+ show: () => setChatStore(CHAT_STORE_KEYS.ASSISTANT_THINKING_INDICATOR, { visible: true }),
5170
+ hide: () => setChatStore(CHAT_STORE_KEYS.ASSISTANT_THINKING_INDICATOR, {
5171
+ visible: false,
5172
+ agentName: void 0,
5173
+ agentLabel: void 0,
5174
+ toolName: void 0
5175
+ }),
5176
+ setThinking: (isThinking) => {
5177
+ setChatStore(CHAT_STORE_KEYS.ASSISTANT_THINKING_INDICATOR, { visible: isThinking });
5178
+ },
5179
+ setAgentName: (agentName) => setChatStore(CHAT_STORE_KEYS.ASSISTANT_THINKING_INDICATOR, { agentName }),
5180
+ setAgentLabel: (agentLabel) => setChatStore(CHAT_STORE_KEYS.ASSISTANT_THINKING_INDICATOR, { agentLabel }),
5181
+ setToolName: (toolName) => setChatStore(CHAT_STORE_KEYS.ASSISTANT_THINKING_INDICATOR, { toolName })
5182
+ };
5183
+ const scrollButtonActions = {
5184
+ setVisible: (visible) => setChatStore(CHAT_STORE_KEYS.SCROLL_BUTTON, { visible }),
5185
+ show: () => setChatStore(CHAT_STORE_KEYS.SCROLL_BUTTON, { visible: true }),
5186
+ hide: () => setChatStore(CHAT_STORE_KEYS.SCROLL_BUTTON, { visible: false })
5187
+ };
5188
+ const scrollToTopActions = {
5189
+ activate: () => setChatStore(CHAT_STORE_KEYS.SCROLL_TO_TOP, { pending: true }),
5190
+ reset: () => setChatStore(CHAT_STORE_KEYS.SCROLL_TO_TOP, { pending: false })
5191
+ };
5192
+ const combinedActions = {
5193
+ prepareFileButtonClick: (isEmpty, isKeyboardOpen) => {
5194
+ if (!isKeyboardOpen && isEmpty) {
5195
+ textareaActions.setShouldPreventKeyboard(true);
5196
+ textareaActions.blur();
5197
+ }
5198
+ },
5199
+ initializeChat: () => {
5200
+ textareaActions.setEmpty(true);
5201
+ textareaActions.setFocused(false);
5202
+ keyboardActions.close();
5203
+ thinkingActions.hide();
5204
+ scrollButtonActions.hide();
5205
+ chatInputActions.updateButtonVisibility(false, false);
5206
+ },
5207
+ handleMessageSend: () => {
5208
+ textareaActions.maintainFocusAfterSend();
5209
+ }
3202
5210
  };
3203
5211
 
3204
- const messages = {
5212
+ const fallbackMessages = {
3205
5213
  short: ["Revisando...", "Procesando...", "Analizando..."],
3206
5214
  medium: ["Analizando tu consulta...", "Estoy viendo c\xF3mo resolverlo...", "Buscando la mejor manera de ayudarte..."],
3207
5215
  long: ["Sigo con esto. Un momento m\xE1s.", "Estoy en eso, ya te respondo.", "Ya casi lo tengo."],
3208
5216
  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."]
3209
5217
  };
3210
5218
  const getRandomMessage = (category) => {
3211
- const categoryMessages = messages[category];
5219
+ const categoryMessages = fallbackMessages[category];
3212
5220
  return categoryMessages[Math.floor(Math.random() * categoryMessages.length)];
3213
5221
  };
3214
5222
  const AssistantThinkingIndicator = () => {
3215
5223
  const { showRoleLabels } = useChatConfig();
3216
- const [displayedMessage, setDisplayedMessage] = useState(getRandomMessage("short"));
5224
+ const [fallbackMessage, setFallbackMessage] = useState(getRandomMessage("short"));
3217
5225
  const [elapsedSeconds, setElapsedSeconds] = useState(0);
5226
+ const [agentLabel, setAgentLabel] = useState(
5227
+ chatStore.get(CHAT_STORE_KEYS.ASSISTANT_THINKING_INDICATOR).agentLabel
5228
+ );
5229
+ const [toolName, setToolName] = useState(
5230
+ chatStore.get(CHAT_STORE_KEYS.ASSISTANT_THINKING_INDICATOR).toolName
5231
+ );
5232
+ useEffect(() => {
5233
+ const unsubLabel = subscribeChatProperty(
5234
+ CHAT_STORE_KEYS.ASSISTANT_THINKING_INDICATOR,
5235
+ "agentLabel",
5236
+ setAgentLabel
5237
+ );
5238
+ const unsubTool = subscribeChatProperty(
5239
+ CHAT_STORE_KEYS.ASSISTANT_THINKING_INDICATOR,
5240
+ "toolName",
5241
+ setToolName
5242
+ );
5243
+ return () => {
5244
+ unsubLabel();
5245
+ unsubTool();
5246
+ };
5247
+ }, []);
3218
5248
  useEffect(() => {
3219
5249
  const timer = setInterval(() => {
3220
5250
  setElapsedSeconds((prev) => prev + 1);
@@ -3223,13 +5253,14 @@ const AssistantThinkingIndicator = () => {
3223
5253
  }, []);
3224
5254
  useEffect(() => {
3225
5255
  if (elapsedSeconds === 6) {
3226
- setDisplayedMessage(getRandomMessage("medium"));
5256
+ setFallbackMessage(getRandomMessage("medium"));
3227
5257
  } else if (elapsedSeconds === 13) {
3228
- setDisplayedMessage(getRandomMessage("long"));
5258
+ setFallbackMessage(getRandomMessage("long"));
3229
5259
  } else if (elapsedSeconds === 21) {
3230
- setDisplayedMessage(getRandomMessage("veryLong"));
5260
+ setFallbackMessage(getRandomMessage("veryLong"));
3231
5261
  }
3232
5262
  }, [elapsedSeconds]);
5263
+ const displayedMessage = agentLabel ? toolName ? `${agentLabel} \u2014 ${toolName}` : `${agentLabel}...` : fallbackMessage;
3233
5264
  return /* @__PURE__ */ jsx("div", { className: `${COMPONENT_PREFIX$1}assistant-thinking-indicator`, children: /* @__PURE__ */ jsx("div", { className: `${COMPONENT_PREFIX$1}assistant-thinking-indicator__content`, children: /* @__PURE__ */ jsxs("div", { className: `${COMPONENT_PREFIX$1}assistant-thinking-indicator__bubble`, children: [
3234
5265
  showRoleLabels && /* @__PURE__ */ jsx(Text, { variant: "caption", color: "secondary", className: `${COMPONENT_PREFIX$1}assistant-thinking-indicator__role`, children: "Assistant" }),
3235
5266
  /* @__PURE__ */ jsx("div", { className: `${COMPONENT_PREFIX$1}assistant-thinking-indicator__text-container`, children: /* @__PURE__ */ jsx(Text, { variant: "body", color: "primary", className: `${COMPONENT_PREFIX$1}assistant-thinking-indicator__wave-text`, children: displayedMessage.split("").map((char, index) => /* @__PURE__ */ jsx(
@@ -3672,197 +5703,6 @@ const FullscreenViewer = ({
3672
5703
  );
3673
5704
  };
3674
5705
 
3675
- const initialState$1 = {
3676
- // ChatInput (molécula) - Estados del input de chat
3677
- chatInput: {
3678
- buttonSend: {
3679
- disabled: true,
3680
- // Disabled hasta que haya contenido
3681
- visible: false
3682
- // Inicialmente oculto
3683
- },
3684
- buttonMicrophone: {
3685
- disabled: false,
3686
- visible: true
3687
- // Inicialmente visible (botón de audio por defecto)
3688
- },
3689
- buttonAttachment: {
3690
- disabled: false
3691
- },
3692
- hasText: false,
3693
- hasAttachments: false
3694
- },
3695
- // AssistantThinkingIndicator (molécula) - Estado del indicador
3696
- assistantThinkingIndicator: {
3697
- visible: false
3698
- },
3699
- // ScrollButton (átomo) - Estado del botón de scroll
3700
- scrollButton: {
3701
- visible: false
3702
- },
3703
- // VirtualKeyboard - Estado del teclado virtual
3704
- virtualKeyboard: {
3705
- isOpen: false
3706
- },
3707
- // Textarea - Estado del textarea del chat
3708
- textarea: {
3709
- isFocused: false,
3710
- isEmpty: true,
3711
- shouldPreventKeyboard: false,
3712
- shouldFocus: false,
3713
- shouldBlur: false
3714
- },
3715
- // Scroll to top trigger
3716
- scrollToTop: {
3717
- pending: false
3718
- }
3719
- };
3720
- const chatStore = createStore(initialState$1);
3721
- const setChatStore = createStoreMerger(chatStore);
3722
- const subscribeChatProperty = createDeepPropertySubscriber(chatStore);
3723
-
3724
- const CHAT_STORE_KEYS = {
3725
- // ChatInput relacionado
3726
- CHAT_INPUT: "chatInput",
3727
- // AssistantThinkingIndicator relacionado
3728
- ASSISTANT_THINKING_INDICATOR: "assistantThinkingIndicator",
3729
- // ScrollButton relacionado
3730
- SCROLL_BUTTON: "scrollButton",
3731
- // VirtualKeyboard relacionado
3732
- VIRTUAL_KEYBOARD: "virtualKeyboard",
3733
- // Textarea relacionado
3734
- TEXTAREA: "textarea",
3735
- // Scroll to top trigger
3736
- SCROLL_TO_TOP: "scrollToTop"
3737
- };
3738
-
3739
- const textareaActions = {
3740
- focus: () => setChatStore(CHAT_STORE_KEYS.TEXTAREA, { shouldFocus: true }),
3741
- blur: () => setChatStore(CHAT_STORE_KEYS.TEXTAREA, { shouldBlur: true }),
3742
- setFocused: (isFocused) => setChatStore(CHAT_STORE_KEYS.TEXTAREA, { isFocused }),
3743
- setEmpty: (isEmpty) => setChatStore(CHAT_STORE_KEYS.TEXTAREA, { isEmpty }),
3744
- setShouldPreventKeyboard: (shouldPrevent) => setChatStore(CHAT_STORE_KEYS.TEXTAREA, { shouldPreventKeyboard: shouldPrevent }),
3745
- resetTriggers: () => setChatStore(CHAT_STORE_KEYS.TEXTAREA, { shouldFocus: false, shouldBlur: false }),
3746
- maintainFocusAfterSend: () => {
3747
- setTimeout(() => {
3748
- setChatStore(CHAT_STORE_KEYS.TEXTAREA, { shouldFocus: true });
3749
- }, 10);
3750
- setTimeout(() => {
3751
- setChatStore(CHAT_STORE_KEYS.TEXTAREA, { shouldFocus: true });
3752
- }, 50);
3753
- },
3754
- preserveFocusWithKeyboard: () => {
3755
- setChatStore(CHAT_STORE_KEYS.TEXTAREA, { shouldFocus: true });
3756
- setTimeout(() => {
3757
- setChatStore(CHAT_STORE_KEYS.TEXTAREA, { shouldFocus: true });
3758
- }, 10);
3759
- setTimeout(() => {
3760
- setChatStore(CHAT_STORE_KEYS.TEXTAREA, { shouldFocus: true });
3761
- }, 50);
3762
- }
3763
- };
3764
- const keyboardActions = {
3765
- setOpen: (isOpen) => setChatStore(CHAT_STORE_KEYS.VIRTUAL_KEYBOARD, { isOpen }),
3766
- open: () => setChatStore(CHAT_STORE_KEYS.VIRTUAL_KEYBOARD, { isOpen: true }),
3767
- close: () => setChatStore(CHAT_STORE_KEYS.VIRTUAL_KEYBOARD, { isOpen: false })
3768
- };
3769
- const chatInputActions = {
3770
- setSendDisabled: (disabled) => {
3771
- const currentState = chatStore.get(CHAT_STORE_KEYS.CHAT_INPUT);
3772
- setChatStore(CHAT_STORE_KEYS.CHAT_INPUT, {
3773
- buttonSend: {
3774
- disabled,
3775
- visible: currentState.buttonSend.visible
3776
- }
3777
- });
3778
- },
3779
- setMicDisabled: (disabled) => {
3780
- const currentState = chatStore.get(CHAT_STORE_KEYS.CHAT_INPUT);
3781
- setChatStore(CHAT_STORE_KEYS.CHAT_INPUT, {
3782
- buttonMicrophone: {
3783
- disabled,
3784
- visible: currentState.buttonMicrophone.visible
3785
- }
3786
- });
3787
- },
3788
- setAttachDisabled: (disabled) => setChatStore(CHAT_STORE_KEYS.CHAT_INPUT, { buttonAttachment: { disabled } }),
3789
- setSendVisible: (visible) => {
3790
- const currentState = chatStore.get(CHAT_STORE_KEYS.CHAT_INPUT);
3791
- setChatStore(CHAT_STORE_KEYS.CHAT_INPUT, {
3792
- buttonSend: {
3793
- visible,
3794
- disabled: currentState.buttonSend.disabled
3795
- }
3796
- });
3797
- },
3798
- setMicVisible: (visible) => {
3799
- const currentState = chatStore.get(CHAT_STORE_KEYS.CHAT_INPUT);
3800
- setChatStore(CHAT_STORE_KEYS.CHAT_INPUT, {
3801
- buttonMicrophone: {
3802
- visible,
3803
- disabled: currentState.buttonMicrophone.disabled
3804
- }
3805
- });
3806
- },
3807
- setHasText: (hasText) => setChatStore(CHAT_STORE_KEYS.CHAT_INPUT, { hasText }),
3808
- setHasAttachments: (hasAttachments) => setChatStore(CHAT_STORE_KEYS.CHAT_INPUT, { hasAttachments }),
3809
- updateButtonVisibility: (hasText, hasAttachments) => {
3810
- const shouldShowSend = hasText || hasAttachments;
3811
- const shouldShowMic = !hasText && !hasAttachments;
3812
- const isThinking = chatStore.get(CHAT_STORE_KEYS.ASSISTANT_THINKING_INDICATOR).visible;
3813
- const hasContent = hasText || hasAttachments;
3814
- const currentState = chatStore.get(CHAT_STORE_KEYS.CHAT_INPUT);
3815
- setChatStore(CHAT_STORE_KEYS.CHAT_INPUT, {
3816
- hasText,
3817
- hasAttachments,
3818
- buttonSend: {
3819
- visible: shouldShowSend,
3820
- disabled: isThinking || !hasContent
3821
- },
3822
- buttonMicrophone: {
3823
- visible: shouldShowMic,
3824
- disabled: currentState.buttonMicrophone.disabled
3825
- }
3826
- });
3827
- }
3828
- };
3829
- const thinkingActions = {
3830
- setVisible: (visible) => setChatStore(CHAT_STORE_KEYS.ASSISTANT_THINKING_INDICATOR, { visible }),
3831
- show: () => setChatStore(CHAT_STORE_KEYS.ASSISTANT_THINKING_INDICATOR, { visible: true }),
3832
- hide: () => setChatStore(CHAT_STORE_KEYS.ASSISTANT_THINKING_INDICATOR, { visible: false }),
3833
- setThinking: (isThinking) => {
3834
- setChatStore(CHAT_STORE_KEYS.ASSISTANT_THINKING_INDICATOR, { visible: isThinking });
3835
- }
3836
- };
3837
- const scrollButtonActions = {
3838
- setVisible: (visible) => setChatStore(CHAT_STORE_KEYS.SCROLL_BUTTON, { visible }),
3839
- show: () => setChatStore(CHAT_STORE_KEYS.SCROLL_BUTTON, { visible: true }),
3840
- hide: () => setChatStore(CHAT_STORE_KEYS.SCROLL_BUTTON, { visible: false })
3841
- };
3842
- const scrollToTopActions = {
3843
- activate: () => setChatStore(CHAT_STORE_KEYS.SCROLL_TO_TOP, { pending: true }),
3844
- reset: () => setChatStore(CHAT_STORE_KEYS.SCROLL_TO_TOP, { pending: false })
3845
- };
3846
- const combinedActions = {
3847
- prepareFileButtonClick: (isEmpty, isKeyboardOpen) => {
3848
- if (!isKeyboardOpen && isEmpty) {
3849
- textareaActions.setShouldPreventKeyboard(true);
3850
- textareaActions.blur();
3851
- }
3852
- },
3853
- initializeChat: () => {
3854
- textareaActions.setEmpty(true);
3855
- textareaActions.setFocused(false);
3856
- keyboardActions.close();
3857
- thinkingActions.hide();
3858
- scrollButtonActions.hide();
3859
- chatInputActions.updateButtonVisibility(false, false);
3860
- },
3861
- handleMessageSend: () => {
3862
- textareaActions.maintainFocusAfterSend();
3863
- }
3864
- };
3865
-
3866
5706
  const ChatInput = forwardRef(({
3867
5707
  value,
3868
5708
  onChange,
@@ -4787,6 +6627,15 @@ const useChatStore = () => {
4787
6627
  const [showThinking, setShowThinking] = useState(
4788
6628
  chatStore.get(CHAT_STORE_KEYS.ASSISTANT_THINKING_INDICATOR).visible
4789
6629
  );
6630
+ const [agentName, setAgentName] = useState(
6631
+ chatStore.get(CHAT_STORE_KEYS.ASSISTANT_THINKING_INDICATOR).agentName
6632
+ );
6633
+ const [agentLabel, setAgentLabel] = useState(
6634
+ chatStore.get(CHAT_STORE_KEYS.ASSISTANT_THINKING_INDICATOR).agentLabel
6635
+ );
6636
+ const [toolName, setToolName] = useState(
6637
+ chatStore.get(CHAT_STORE_KEYS.ASSISTANT_THINKING_INDICATOR).toolName
6638
+ );
4790
6639
  const [scrollButtonState, setScrollButtonState] = useState(
4791
6640
  chatStore.get(CHAT_STORE_KEYS.SCROLL_BUTTON)
4792
6641
  );
@@ -4799,6 +6648,21 @@ const useChatStore = () => {
4799
6648
  "visible",
4800
6649
  setShowThinking
4801
6650
  );
6651
+ const unsubAgentName = subscribeChatProperty(
6652
+ CHAT_STORE_KEYS.ASSISTANT_THINKING_INDICATOR,
6653
+ "agentName",
6654
+ setAgentName
6655
+ );
6656
+ const unsubAgentLabel = subscribeChatProperty(
6657
+ CHAT_STORE_KEYS.ASSISTANT_THINKING_INDICATOR,
6658
+ "agentLabel",
6659
+ setAgentLabel
6660
+ );
6661
+ const unsubToolName = subscribeChatProperty(
6662
+ CHAT_STORE_KEYS.ASSISTANT_THINKING_INDICATOR,
6663
+ "toolName",
6664
+ setToolName
6665
+ );
4802
6666
  const unsubScrollButton = subscribeChatProperty(
4803
6667
  CHAT_STORE_KEYS.SCROLL_BUTTON,
4804
6668
  "",
@@ -4811,12 +6675,18 @@ const useChatStore = () => {
4811
6675
  );
4812
6676
  return () => {
4813
6677
  unsubThinking();
6678
+ unsubAgentName();
6679
+ unsubAgentLabel();
6680
+ unsubToolName();
4814
6681
  unsubScrollButton();
4815
6682
  unsubScrollToTop();
4816
6683
  };
4817
6684
  }, []);
4818
6685
  return {
4819
6686
  showThinking,
6687
+ agentName,
6688
+ agentLabel,
6689
+ toolName,
4820
6690
  scrollButtonState,
4821
6691
  scrollToTopPending
4822
6692
  };