pixelon 0.3.25 → 0.3.27

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 +2221 -348
  226. package/dist/index.js +2221 -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,1929 @@ 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 = globalThis.crypto?.randomUUID?.() ?? "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, (c) => {
3660
+ const r = Math.random() * 16 | 0;
3661
+ return (c === "x" ? r : r & 3 | 8).toString(16);
3662
+ });
3663
+ return new Promise((resolve, reject) => {
3664
+ const timeoutId = setTimeout(() => {
3665
+ unsubscribe();
3666
+ reject(new Error(`Timeout: no response for ${url} after ${FETCH_TIMEOUT_MS}ms`));
3667
+ }, FETCH_TIMEOUT_MS);
3668
+ const unsubscribe = eventBus.on(CHAT_EVENT.FETCH_RESPONSE, (response) => {
3669
+ if (response.requestId !== requestId) return;
3670
+ clearTimeout(timeoutId);
3671
+ unsubscribe();
3672
+ if (response.httpError) {
3673
+ reject(new Error(response.httpError));
3674
+ } else {
3675
+ resolve(response.data);
3676
+ }
3677
+ });
3678
+ eventBus.emit(CHAT_EVENT.FETCH_REQUEST, {
3679
+ requestId,
3680
+ service,
3681
+ url,
3682
+ method,
3683
+ ...body ? { body } : {}
3684
+ });
3685
+ });
3686
+ }
3687
+
3688
+ function formatTime$1(value, timezone) {
3689
+ try {
3690
+ const d = new Date(value);
3691
+ if (isNaN(d.getTime())) return value;
3692
+ return d.toLocaleTimeString([], {
3693
+ hour: "2-digit",
3694
+ minute: "2-digit",
3695
+ hour12: false,
3696
+ ...timezone ? { timeZone: timezone } : {}
3697
+ });
3698
+ } catch {
3699
+ return value;
3700
+ }
3701
+ }
3702
+ function formatDate$3(value, timezone) {
3703
+ try {
3704
+ const d = new Date(value);
3705
+ if (isNaN(d.getTime())) return value;
3706
+ return d.toLocaleDateString("sv-SE", {
3707
+ year: "numeric",
3708
+ month: "2-digit",
3709
+ day: "2-digit",
3710
+ ...timezone ? { timeZone: timezone } : {}
3711
+ });
3712
+ } catch {
3713
+ return value;
3714
+ }
3715
+ }
3716
+ async function mockFetch(url, params) {
3717
+ await new Promise((r) => setTimeout(r, 600 + Math.random() * 400));
3718
+ if (url.includes("companies")) {
3719
+ return [
3720
+ { id: "company-1", name: "Goluti" },
3721
+ { id: "company-2", name: "Barbeer" }
3722
+ ];
3723
+ }
3724
+ if (url.includes("locations")) {
3725
+ if (params.company_id === "company-1") {
3726
+ return [
3727
+ { id: "loc-1", name: "Sede Chico" },
3728
+ { id: "loc-2", name: "Sede Suba" }
3729
+ ];
3730
+ }
3731
+ return [{ id: "loc-3", name: "Sede Norte" }];
3732
+ }
3733
+ if (url.includes("services")) {
3734
+ return [
3735
+ { id: "svc-1", name: "Corte de cabello" },
3736
+ { id: "svc-2", name: "Manicure" },
3737
+ { id: "svc-3", name: "Tinte completo" }
3738
+ ];
3739
+ }
3740
+ if (url.includes("availability")) {
3741
+ return [
3742
+ {
3743
+ collaborator_id: "collab-1",
3744
+ user_location_rol_id: "ulr-1",
3745
+ name: "Leon",
3746
+ assignment_hours: [
3747
+ { start: "2026-03-02T14:00:00", end: "2026-03-02T14:20:00", start_time: "14:00", end_time: "14:20" },
3748
+ { start: "2026-03-02T14:30:00", end: "2026-03-02T14:50:00", start_time: "14:30", end_time: "14:50" }
3749
+ ]
3750
+ },
3751
+ {
3752
+ collaborator_id: "collab-2",
3753
+ user_location_rol_id: "ulr-2",
3754
+ name: "Carlos",
3755
+ assignment_hours: [
3756
+ { start: "2026-03-02T10:00:00", end: "2026-03-02T10:20:00", start_time: "10:00", end_time: "10:20" },
3757
+ { start: "2026-03-02T11:00:00", end: "2026-03-02T11:20:00", start_time: "11:00", end_time: "11:20" }
3758
+ ]
3759
+ }
3760
+ ];
3761
+ }
3762
+ return [];
3763
+ }
3764
+ function getDependencies(field) {
3765
+ if (!field.depends_on) return [];
3766
+ return Array.isArray(field.depends_on) ? field.depends_on : [field.depends_on];
3767
+ }
3768
+ function allDepsResolved(deps, formValues) {
3769
+ return deps.every((dep) => {
3770
+ const val = formValues[dep];
3771
+ if (Array.isArray(val)) return val.length > 0;
3772
+ return val !== "" && val !== null && val !== void 0;
3773
+ });
3774
+ }
3775
+ function useReactiveEndpoints({ fields, fieldStates, setFieldState, eventBus, timezone, formTitle }) {
3776
+ const loadingRef = useRef(/* @__PURE__ */ new Set());
3777
+ const loadEndpoint = useCallback(
3778
+ async (field, formValues) => {
3779
+ if (!field.endpoint || loadingRef.current.has(field.name)) return;
3780
+ const deps = getDependencies(field);
3781
+ if (!allDepsResolved(deps, formValues)) return;
3782
+ loadingRef.current.add(field.name);
3783
+ setFieldState(field.name, { loading: true, error: null });
3784
+ const startTime = Date.now();
3785
+ try {
3786
+ const resolvedBody = field.endpoint.body ? resolveBody(field.endpoint.body, formValues, fieldStates) : void 0;
3787
+ const params = field.endpoint.params ? resolveParams(field.endpoint.params, formValues, fieldStates) : {};
3788
+ const requestBody = resolvedBody ?? (Object.keys(params).length > 0 ? params : void 0);
3789
+ if (eventBus) {
3790
+ eventBus.emit(CHAT_EVENT.FORM_TRACE, {
3791
+ chatId: "",
3792
+ formTitle: formTitle || "",
3793
+ source: "reactive_form",
3794
+ phase: "request",
3795
+ service: field.endpoint.service,
3796
+ url: field.endpoint.url,
3797
+ method: field.endpoint.method,
3798
+ body: requestBody
3799
+ });
3800
+ }
3801
+ let rawData;
3802
+ if (eventBus) {
3803
+ rawData = await fetchViaEventBus(
3804
+ eventBus,
3805
+ field.endpoint.service,
3806
+ field.endpoint.url,
3807
+ field.endpoint.method,
3808
+ requestBody
3809
+ );
3810
+ } else {
3811
+ rawData = await mockFetch(field.endpoint.url, params);
3812
+ }
3813
+ let dataArray;
3814
+ let data = rawData;
3815
+ if (rawData && typeof rawData === "object" && "response" in rawData) {
3816
+ data = rawData.response;
3817
+ }
3818
+ if (field.endpoint.response_path && data && typeof data === "object" && !Array.isArray(data)) {
3819
+ const extracted = data[field.endpoint.response_path];
3820
+ dataArray = Array.isArray(extracted) ? extracted : [];
3821
+ } else {
3822
+ dataArray = Array.isArray(data) ? data : [];
3823
+ }
3824
+ if (eventBus && rawData && typeof rawData === "object") {
3825
+ const resp = rawData;
3826
+ if (resp.notification_type && String(resp.notification_type).toLowerCase() !== "success") {
3827
+ throw new Error(resp.message || "Error en la respuesta");
3828
+ }
3829
+ }
3830
+ const options = dataArray.map((item) => {
3831
+ const opt = {
3832
+ value: String(item[field.endpoint.value_field] || ""),
3833
+ label: String(item[field.endpoint.label_field] || "")
3834
+ };
3835
+ if (field.endpoint.extra_fields) {
3836
+ for (const ef of field.endpoint.extra_fields) {
3837
+ opt[ef] = item[ef];
3838
+ }
3839
+ }
3840
+ return opt;
3841
+ });
3842
+ setFieldState(field.name, { options, loading: false });
3843
+ if (eventBus) {
3844
+ eventBus.emit(CHAT_EVENT.FORM_TRACE, {
3845
+ chatId: "",
3846
+ formTitle: formTitle || "",
3847
+ source: "reactive_form",
3848
+ phase: "response",
3849
+ service: field.endpoint.service,
3850
+ url: field.endpoint.url,
3851
+ method: field.endpoint.method,
3852
+ status: 200,
3853
+ duration_ms: Date.now() - startTime,
3854
+ success: true,
3855
+ response: rawData
3856
+ });
3857
+ }
3858
+ } catch (err) {
3859
+ const errorMsg = err instanceof Error ? err.message : "Error al cargar opciones";
3860
+ setFieldState(field.name, { loading: false, error: errorMsg });
3861
+ if (eventBus) {
3862
+ eventBus.emit(CHAT_EVENT.FORM_TRACE, {
3863
+ chatId: "",
3864
+ formTitle: formTitle || "",
3865
+ source: "reactive_form",
3866
+ phase: "response",
3867
+ service: field.endpoint.service,
3868
+ url: field.endpoint.url,
3869
+ method: field.endpoint.method,
3870
+ status: 500,
3871
+ duration_ms: Date.now() - startTime,
3872
+ success: false,
3873
+ error: errorMsg
3874
+ });
3875
+ }
3876
+ } finally {
3877
+ loadingRef.current.delete(field.name);
3878
+ }
3879
+ },
3880
+ [fields, fieldStates, setFieldState, eventBus]
3881
+ );
3882
+ const resolveOptionsFrom = useCallback(
3883
+ (field, formValues) => {
3884
+ if (!field.options_from) return;
3885
+ const sourceState = fieldStates[field.options_from.source_field];
3886
+ const sourceValue = formValues[field.options_from.source_field];
3887
+ if (!sourceState || !sourceValue) return;
3888
+ const selectedItem = sourceState.options.find((o) => o.value === sourceValue);
3889
+ if (!selectedItem) return;
3890
+ const rawData = selectedItem[field.options_from.data_field];
3891
+ if (!Array.isArray(rawData)) return;
3892
+ const options = rawData.map((item) => {
3893
+ let val = field.options_from.value_template;
3894
+ let lbl = field.options_from.label_template;
3895
+ for (const [k, v] of Object.entries(item)) {
3896
+ const strVal = String(v);
3897
+ const timeStr = formatTime$1(strVal, timezone);
3898
+ const dateStr = formatDate$3(strVal, timezone);
3899
+ val = val.replace(`\${${k}|time}`, timeStr);
3900
+ val = val.replace(`\${${k}|date}`, dateStr);
3901
+ val = val.replace(`\${${k}_time}`, timeStr);
3902
+ val = val.replace(`\${${k}_date}`, dateStr);
3903
+ val = val.replace(`\${${k}}`, strVal);
3904
+ lbl = lbl.replace(`\${${k}|time}`, timeStr);
3905
+ lbl = lbl.replace(`\${${k}|date}`, dateStr);
3906
+ lbl = lbl.replace(`\${${k}_time}`, timeStr);
3907
+ lbl = lbl.replace(`\${${k}_date}`, dateStr);
3908
+ lbl = lbl.replace(`\${${k}}`, strVal);
3909
+ }
3910
+ return { value: val, label: lbl, ...item };
3911
+ });
3912
+ setFieldState(field.name, { options, loading: false });
3913
+ },
3914
+ [fieldStates, setFieldState]
3915
+ );
3916
+ return { loadEndpoint, resolveOptionsFrom, getDependencies, allDepsResolved, fetchViaEventBus: eventBus ? fetchViaEventBus.bind(null, eventBus) : void 0 };
3917
+ }
3918
+
3919
+ function createInitialFieldStates(fields) {
3920
+ const map = {};
3921
+ for (const f of fields) {
3922
+ map[f.name] = {
3923
+ value: f.type === "hidden" ? f.default_value ?? "" : f.type === "select_multiple" ? [] : "",
3924
+ label: "",
3925
+ options: f.options || [],
3926
+ loading: false,
3927
+ error: null
3928
+ };
3929
+ }
3930
+ return map;
3931
+ }
3932
+ function useReactiveForm(props) {
3933
+ const { fields, steps, submit, eventBus } = props;
3934
+ const { timezone } = useChatConfig();
3935
+ const [formStatus, setFormStatus] = useState("closed");
3936
+ const [currentStep, setCurrentStep] = useState(0);
3937
+ const [values, setValues] = useState(() => buildInitialValues(fields));
3938
+ const [errors, setErrors] = useState({});
3939
+ const [touched, setTouched] = useState({});
3940
+ const [fieldStates, setFieldStatesMap] = useState(
3941
+ () => createInitialFieldStates(fields)
3942
+ );
3943
+ const validationSchema = useMemo(() => buildYupSchema(fields), [fields]);
3944
+ const totalSteps = steps.length + 1;
3945
+ const setFieldState = useCallback((name, partial) => {
3946
+ setFieldStatesMap((prev) => ({
3947
+ ...prev,
3948
+ [name]: { ...prev[name], ...partial }
3949
+ }));
3950
+ }, []);
3951
+ const { loadEndpoint, resolveOptionsFrom, getDependencies, allDepsResolved } = useReactiveEndpoints({ fields, fieldStates, setFieldState, eventBus, timezone, formTitle: props.title });
3952
+ const handleTriggerClick = () => {
3953
+ if (formStatus === "completed") return;
3954
+ setFormStatus(formStatus === "open" ? "closed" : "open");
3955
+ };
3956
+ const setFieldValue = useCallback((name, value) => {
3957
+ setValues((prev) => ({ ...prev, [name]: value }));
3958
+ }, []);
3959
+ const handleFieldChange = useCallback(
3960
+ (fieldName, value, label, extraData) => {
3961
+ setFieldValue(fieldName, value);
3962
+ setFieldState(fieldName, { value, label, extraData });
3963
+ setErrors((prev) => {
3964
+ const next = { ...prev };
3965
+ delete next[fieldName];
3966
+ return next;
3967
+ });
3968
+ for (const f of fields) {
3969
+ const deps = getDependencies(f);
3970
+ if (deps.includes(fieldName)) {
3971
+ const resetVal = f.type === "select_multiple" ? [] : "";
3972
+ setFieldValue(f.name, resetVal);
3973
+ setFieldState(f.name, { value: resetVal, label: "", options: [], extraData: void 0 });
3974
+ }
3975
+ }
3976
+ setValues((currentValues) => {
3977
+ const nextValues = { ...currentValues, [fieldName]: value };
3978
+ for (const f of fields) {
3979
+ const deps = getDependencies(f);
3980
+ if (deps.includes(fieldName) && allDepsResolved(deps, nextValues)) {
3981
+ if (f.endpoint) {
3982
+ loadEndpoint(f, nextValues);
3983
+ } else if (f.options_from) {
3984
+ setTimeout(() => resolveOptionsFrom(f, nextValues), 0);
3985
+ }
3986
+ }
3987
+ }
3988
+ return nextValues;
3989
+ });
3990
+ },
3991
+ [fields, getDependencies, allDepsResolved, loadEndpoint, resolveOptionsFrom, setFieldState, setFieldValue]
3992
+ );
3993
+ useEffect(() => {
3994
+ if (formStatus !== "open") return;
3995
+ const initialValues = buildInitialValues(fields);
3996
+ for (const f of fields) {
3997
+ if (!f.endpoint || fieldStates[f.name]?.options.length > 0) continue;
3998
+ const deps = getDependencies(f);
3999
+ if (deps.length === 0 || allDepsResolved(deps, initialValues)) {
4000
+ loadEndpoint(f, initialValues);
4001
+ }
4002
+ }
4003
+ }, [formStatus]);
4004
+ useEffect(() => {
4005
+ if (formStatus !== "open" || currentStep >= steps.length) return;
4006
+ const stepFieldNames = steps[currentStep].fields;
4007
+ setValues((currentValues) => {
4008
+ for (const f of fields) {
4009
+ if (!stepFieldNames.includes(f.name)) continue;
4010
+ if (!f.endpoint && !f.options_from) continue;
4011
+ if (fieldStates[f.name]?.options.length > 0) continue;
4012
+ if (fieldStates[f.name]?.loading) continue;
4013
+ const deps = getDependencies(f);
4014
+ if (allDepsResolved(deps, currentValues)) {
4015
+ if (f.endpoint) {
4016
+ loadEndpoint(f, currentValues);
4017
+ } else if (f.options_from) {
4018
+ resolveOptionsFrom(f, currentValues);
4019
+ }
4020
+ }
4021
+ }
4022
+ return currentValues;
4023
+ });
4024
+ }, [currentStep, formStatus]);
4025
+ const validateFields = async (fieldNames) => {
4026
+ const fieldErrors = {};
4027
+ try {
4028
+ await validationSchema.validate(values, { abortEarly: false });
4029
+ } catch (err) {
4030
+ if (err && typeof err === "object" && "inner" in err) {
4031
+ const yupErr = err;
4032
+ for (const e of yupErr.inner) {
4033
+ if (e.path && fieldNames.includes(e.path)) {
4034
+ fieldErrors[e.path] = e.message;
4035
+ }
4036
+ }
4037
+ }
4038
+ }
4039
+ return fieldErrors;
4040
+ };
4041
+ const validateStep = async (stepIndex) => {
4042
+ if (stepIndex >= steps.length) return true;
4043
+ const stepFieldNames = steps[stepIndex].fields;
4044
+ const stepErrors = await validateFields(stepFieldNames);
4045
+ setErrors((prev) => ({ ...prev, ...stepErrors }));
4046
+ const touchMap = {};
4047
+ for (const name of stepFieldNames) touchMap[name] = true;
4048
+ setTouched((prev) => ({ ...prev, ...touchMap }));
4049
+ return Object.keys(stepErrors).length === 0;
4050
+ };
4051
+ const handleNext = async () => {
4052
+ const valid = await validateStep(currentStep);
4053
+ if (valid) setCurrentStep((s) => s + 1);
4054
+ };
4055
+ const handleBack = () => setCurrentStep((s) => s - 1);
4056
+ const [submitMessage, setSubmitMessage] = useState("");
4057
+ const handleSubmit = async () => {
4058
+ const resolvedPayload = resolveBody(submit.payload_map, values, fieldStates);
4059
+ if (eventBus) {
4060
+ try {
4061
+ const data = await fetchViaEventBus(
4062
+ eventBus,
4063
+ submit.service,
4064
+ submit.url,
4065
+ submit.method,
4066
+ resolvedPayload
4067
+ );
4068
+ const resp = data;
4069
+ const notificationType = String(resp?.notification_type ?? "SUCCESS").toUpperCase();
4070
+ const message = String(resp?.message ?? "");
4071
+ const formLabels = {};
4072
+ for (const [name, state] of Object.entries(fieldStates)) {
4073
+ if (state.label) formLabels[name] = state.label;
4074
+ }
4075
+ eventBus.emit(CHAT_EVENT.FORM_SUBMIT, {
4076
+ formType: "reactive_form",
4077
+ submitUrl: submit.url,
4078
+ result: data,
4079
+ formValues: values,
4080
+ formLabels
4081
+ });
4082
+ if (notificationType === "SUCCESS") {
4083
+ setSubmitMessage(message || "Completado");
4084
+ setFormStatus("completed");
4085
+ } else if (notificationType === "WARNING") {
4086
+ setSubmitMessage(message || "Advertencia");
4087
+ setFormStatus("warning");
4088
+ } else {
4089
+ setSubmitMessage(message || "Error al procesar");
4090
+ setFormStatus("error");
4091
+ }
4092
+ } catch (err) {
4093
+ const message = err instanceof Error ? err.message : "Error al enviar formulario";
4094
+ setSubmitMessage(message);
4095
+ setFormStatus("error");
4096
+ }
4097
+ } else {
4098
+ console.log("[ReactiveForm] Submit:", values);
4099
+ console.log("[ReactiveForm] Payload map:", resolvedPayload);
4100
+ setFormStatus("completed");
4101
+ }
4102
+ };
4103
+ const resolveRows = (rows) => resolveSummaryRows(rows, values, fieldStates);
4104
+ return {
4105
+ formStatus,
4106
+ setFormStatus,
4107
+ submitMessage,
4108
+ currentStep,
4109
+ setCurrentStep,
4110
+ values,
4111
+ errors,
4112
+ touched,
4113
+ fieldStates,
4114
+ validationSchema,
4115
+ totalSteps,
4116
+ handleTriggerClick,
4117
+ setFieldValue,
4118
+ handleFieldChange,
4119
+ validateFields,
4120
+ validateStep,
4121
+ handleNext,
4122
+ handleBack,
4123
+ handleSubmit,
4124
+ getDependencies,
4125
+ allDepsResolved,
4126
+ resolveSummaryRows: resolveRows
4127
+ };
4128
+ }
4129
+
4130
+ const MOBILE_BREAKPOINT = 640;
4131
+ const useIsMobile$1 = () => {
4132
+ const [isMobile, setIsMobile] = useState(
4133
+ typeof window !== "undefined" ? window.innerWidth < MOBILE_BREAKPOINT : false
4134
+ );
4135
+ useEffect(() => {
4136
+ const mq = window.matchMedia(`(max-width: ${MOBILE_BREAKPOINT - 1}px)`);
4137
+ const handler = (e) => setIsMobile(e.matches);
4138
+ mq.addEventListener("change", handler);
4139
+ return () => mq.removeEventListener("change", handler);
4140
+ }, []);
4141
+ return isMobile;
4142
+ };
4143
+ const ReactiveForm = ({ component, eventBus }) => {
4144
+ const props = component.props;
4145
+ const isMobile = useIsMobile$1();
4146
+ const form = useReactiveForm({ ...props, eventBus });
4147
+ if (component.answered && form.formStatus !== "completed" && form.formStatus !== "warning" && form.formStatus !== "error") {
4148
+ form.setFormStatus("completed");
4149
+ }
4150
+ return /* @__PURE__ */ jsx(
4151
+ ReactiveFormView,
4152
+ {
4153
+ ...props,
4154
+ form,
4155
+ drawerPlacement: isMobile ? "bottom" : "right"
4156
+ }
4157
+ );
4158
+ };
4159
+
4160
+ function useStoreState(store, key) {
4161
+ const [value, setValue] = useState(() => store.get(key));
4162
+ useEffect(() => {
4163
+ return store.subscribe(key, setValue);
4164
+ }, [store, key]);
4165
+ return value;
4166
+ }
4167
+
4168
+ function createStore(initial) {
4169
+ const state = { ...initial };
4170
+ const listeners = {};
4171
+ const notify = (key, value) => {
4172
+ const keyStr = String(key);
4173
+ listeners[keyStr]?.forEach((l) => l(value));
4174
+ };
4175
+ const subscribe = (key, listener) => {
4176
+ const keyStr = String(key);
4177
+ if (!listeners[keyStr]) listeners[keyStr] = /* @__PURE__ */ new Set();
4178
+ listeners[keyStr].add(listener);
4179
+ listener(state[key]);
4180
+ return () => {
4181
+ listeners[keyStr].delete(listener);
4182
+ };
4183
+ };
4184
+ const set = (key, value) => {
4185
+ state[key] = value;
4186
+ notify(key, value);
4187
+ };
4188
+ const get = (key) => state[key];
4189
+ return { set, get, subscribe };
4190
+ }
4191
+
4192
+ const CAROUSEL_STORE_KEYS = {
4193
+ ITEMS: "items",
4194
+ ORIGINAL_ITEMS: "originalItems",
4195
+ SEARCH_QUERY: "searchQuery",
4196
+ SEARCH_STATUS: "searchStatus",
4197
+ SELECTED_IDS: "selectedIds",
4198
+ CURRENT_PAGE: "currentPage",
4199
+ HAS_MORE: "hasMore"
4200
+ };
4201
+
4202
+ function createCarouselStore(initialItems) {
4203
+ return createStore({
4204
+ [CAROUSEL_STORE_KEYS.ITEMS]: initialItems,
4205
+ [CAROUSEL_STORE_KEYS.ORIGINAL_ITEMS]: initialItems,
4206
+ [CAROUSEL_STORE_KEYS.SEARCH_QUERY]: "",
4207
+ [CAROUSEL_STORE_KEYS.SEARCH_STATUS]: "idle",
4208
+ [CAROUSEL_STORE_KEYS.SELECTED_IDS]: [],
4209
+ [CAROUSEL_STORE_KEYS.CURRENT_PAGE]: 0,
4210
+ [CAROUSEL_STORE_KEYS.HAS_MORE]: false
4211
+ });
4212
+ }
4213
+
4214
+ function createCarouselActions(store) {
4215
+ return {
4216
+ items: {
4217
+ set: (items) => store.set(CAROUSEL_STORE_KEYS.ITEMS, items),
4218
+ remove: (id) => {
4219
+ const current = store.get(CAROUSEL_STORE_KEYS.ITEMS);
4220
+ if (current.length <= 1) return;
4221
+ store.set(CAROUSEL_STORE_KEYS.ITEMS, current.filter((i) => i.id !== id));
4222
+ },
4223
+ get: () => store.get(CAROUSEL_STORE_KEYS.ITEMS)
4224
+ },
4225
+ selection: {
4226
+ toggle: (id) => {
4227
+ const current = store.get(CAROUSEL_STORE_KEYS.SELECTED_IDS);
4228
+ const next = current.includes(id) ? current.filter((i) => i !== id) : [...current, id];
4229
+ store.set(CAROUSEL_STORE_KEYS.SELECTED_IDS, next);
4230
+ },
4231
+ clear: () => store.set(CAROUSEL_STORE_KEYS.SELECTED_IDS, []),
4232
+ get: () => store.get(CAROUSEL_STORE_KEYS.SELECTED_IDS)
4233
+ },
4234
+ search: {
4235
+ setQuery: (query) => store.set(CAROUSEL_STORE_KEYS.SEARCH_QUERY, query),
4236
+ setStatus: (status) => store.set(CAROUSEL_STORE_KEYS.SEARCH_STATUS, status),
4237
+ getQuery: () => store.get(CAROUSEL_STORE_KEYS.SEARCH_QUERY)
4238
+ },
4239
+ pagination: {
4240
+ setPage: (page) => store.set(CAROUSEL_STORE_KEYS.CURRENT_PAGE, page),
4241
+ setHasMore: (hasMore) => store.set(CAROUSEL_STORE_KEYS.HAS_MORE, hasMore),
4242
+ getPage: () => store.get(CAROUSEL_STORE_KEYS.CURRENT_PAGE)
4243
+ },
4244
+ getOriginalItems: () => store.get(CAROUSEL_STORE_KEYS.ORIGINAL_ITEMS)
4245
+ };
4246
+ }
4247
+
4248
+ const SIZE_PX = { small: 80, medium: 120, large: 180 };
4249
+ const GAP_PX = 8;
4250
+ function calcPageLimit(size, containerWidth) {
4251
+ const cardWidth = SIZE_PX[size];
4252
+ return Math.max(1, Math.floor(containerWidth / (cardWidth + GAP_PX)));
4253
+ }
4254
+ function resolveSize(size, itemCount) {
4255
+ if (size && size !== "auto") return size;
4256
+ if (itemCount <= 3) return "large";
4257
+ if (itemCount <= 6) return "medium";
4258
+ return "small";
4259
+ }
4260
+ function mapResponseToItems(data, endpoint) {
4261
+ let unwrapped = data;
4262
+ if (unwrapped && typeof unwrapped === "object" && "response" in unwrapped) {
4263
+ unwrapped = unwrapped.response;
4264
+ }
4265
+ if (endpoint.response_path && unwrapped && typeof unwrapped === "object" && !Array.isArray(unwrapped)) {
4266
+ unwrapped = unwrapped[endpoint.response_path];
4267
+ }
4268
+ const arr = Array.isArray(unwrapped) ? unwrapped : [];
4269
+ return arr.map((item) => {
4270
+ const metadata = {};
4271
+ if (endpoint.extra_fields) {
4272
+ for (const field of endpoint.extra_fields) {
4273
+ metadata[field] = item[field];
4274
+ }
4275
+ }
4276
+ return {
4277
+ id: String(item[endpoint.id_field] ?? ""),
4278
+ type: endpoint.item_type,
4279
+ title: endpoint.title_field ? String(item[endpoint.title_field] ?? "") : void 0,
4280
+ description: endpoint.description_field ? String(item[endpoint.description_field] ?? "") : void 0,
4281
+ src: endpoint.src_field ? String(item[endpoint.src_field] ?? "") : void 0,
4282
+ file_type: endpoint.file_type_field ? String(item[endpoint.file_type_field] ?? "") : void 0,
4283
+ status: "ready",
4284
+ metadata: Object.keys(metadata).length > 0 ? metadata : void 0
4285
+ };
4286
+ });
4287
+ }
4288
+
4289
+ const MOCK_NAMES = [
4290
+ "Alpha",
4291
+ "Beta",
4292
+ "Gamma",
4293
+ "Delta",
4294
+ "Epsilon",
4295
+ "Zeta",
4296
+ "Eta",
4297
+ "Theta",
4298
+ "Iota",
4299
+ "Kappa",
4300
+ "Lambda",
4301
+ "Mu",
4302
+ "Nu",
4303
+ "Xi",
4304
+ "Omicron",
4305
+ "Pi",
4306
+ "Rho",
4307
+ "Sigma",
4308
+ "Tau",
4309
+ "Upsilon",
4310
+ "Phi",
4311
+ "Chi",
4312
+ "Psi",
4313
+ "Omega",
4314
+ "Altair",
4315
+ "Vega",
4316
+ "Sirius",
4317
+ "Rigel",
4318
+ "Polaris",
4319
+ "Antares"
4320
+ ];
4321
+ const MOCK_ITEMS = MOCK_NAMES.map((name, i) => ({
4322
+ id: String(i + 1),
4323
+ name: `Empresa ${name}`,
4324
+ address: `Calle ${i + 1} #${(i + 1) * 10}-${(i + 1) * 5}`,
4325
+ logo_url: `https://picsum.photos/seed/${name.toLowerCase()}/200`
4326
+ }));
4327
+ async function mockSearchFetch(query, skip, limit) {
4328
+ await new Promise((r) => setTimeout(r, 400 + Math.random() * 300));
4329
+ let filtered = MOCK_ITEMS;
4330
+ if (query) {
4331
+ filtered = MOCK_ITEMS.filter((i) => i.name.toLowerCase().includes(query.toLowerCase()));
4332
+ }
4333
+ return filtered.slice(skip, skip + limit);
4334
+ }
4335
+ function useCarouselSearch({ actions, endpoint, eventBus, pageLimit }) {
4336
+ const loadingRef = useRef(false);
4337
+ const search = useCallback(
4338
+ async (query, page = 0) => {
4339
+ if (loadingRef.current) return;
4340
+ loadingRef.current = true;
4341
+ actions.search.setQuery(query);
4342
+ if (page === 0) {
4343
+ actions.search.setStatus("loading");
4344
+ }
4345
+ const limit = endpoint?.limit ?? pageLimit;
4346
+ const skip = page * limit;
4347
+ const startTime = Date.now();
4348
+ try {
4349
+ let rawData;
4350
+ if (eventBus && endpoint) {
4351
+ const baseBody = endpoint.body ?? {};
4352
+ const cleanBody = {};
4353
+ for (const [k, v] of Object.entries(baseBody)) {
4354
+ if (typeof v === "string" && v.includes("$query")) continue;
4355
+ cleanBody[k] = v;
4356
+ }
4357
+ const body = {
4358
+ ...cleanBody,
4359
+ skip,
4360
+ limit
4361
+ };
4362
+ if (query && endpoint.query_param) {
4363
+ body.filters = [
4364
+ ...Array.isArray(body.filters) ? body.filters : [],
4365
+ { field: endpoint.query_param, condition: "like", value: query }
4366
+ ];
4367
+ }
4368
+ eventBus.emit(CHAT_EVENT.FORM_TRACE, {
4369
+ chatId: "",
4370
+ formTitle: "carousel",
4371
+ source: "carousel",
4372
+ phase: "request",
4373
+ service: endpoint.service,
4374
+ url: endpoint.url,
4375
+ method: endpoint.method,
4376
+ body
4377
+ });
4378
+ rawData = await fetchViaEventBus(
4379
+ eventBus,
4380
+ endpoint.service,
4381
+ endpoint.url,
4382
+ endpoint.method,
4383
+ body
4384
+ );
4385
+ eventBus.emit(CHAT_EVENT.FORM_TRACE, {
4386
+ chatId: "",
4387
+ formTitle: "carousel",
4388
+ source: "carousel",
4389
+ phase: "response",
4390
+ service: endpoint.service,
4391
+ url: endpoint.url,
4392
+ method: endpoint.method,
4393
+ status: 200,
4394
+ duration_ms: Date.now() - startTime,
4395
+ success: true,
4396
+ response: rawData
4397
+ });
4398
+ } else {
4399
+ rawData = await mockSearchFetch(query, skip, limit);
4400
+ }
4401
+ let newItems;
4402
+ if (endpoint) {
4403
+ newItems = mapResponseToItems(rawData, endpoint);
4404
+ } else {
4405
+ const arr = Array.isArray(rawData) ? rawData : [];
4406
+ newItems = arr.map((item) => ({
4407
+ id: String(item.id ?? ""),
4408
+ type: "image",
4409
+ title: String(item.name ?? ""),
4410
+ description: String(item.address ?? ""),
4411
+ src: String(item.logo_url ?? ""),
4412
+ status: "ready"
4413
+ }));
4414
+ }
4415
+ actions.items.set(newItems);
4416
+ actions.pagination.setPage(page);
4417
+ actions.pagination.setHasMore(newItems.length === limit);
4418
+ actions.search.setStatus("idle");
4419
+ } catch (err) {
4420
+ actions.search.setStatus("error");
4421
+ if (eventBus && endpoint) {
4422
+ eventBus.emit(CHAT_EVENT.FORM_TRACE, {
4423
+ chatId: "",
4424
+ formTitle: "carousel",
4425
+ source: "carousel",
4426
+ phase: "response",
4427
+ service: endpoint.service,
4428
+ url: endpoint.url,
4429
+ method: endpoint.method,
4430
+ status: 500,
4431
+ duration_ms: Date.now() - startTime,
4432
+ success: false,
4433
+ error: err instanceof Error ? err.message : "Error en busqueda"
4434
+ });
4435
+ }
4436
+ } finally {
4437
+ loadingRef.current = false;
4438
+ }
4439
+ },
4440
+ [actions, endpoint, eventBus, pageLimit]
4441
+ );
4442
+ const loadNext = useCallback(() => {
4443
+ const currentPage = actions.pagination.getPage();
4444
+ const query = actions.search.getQuery();
4445
+ search(query, currentPage + 1);
4446
+ }, [actions, search]);
4447
+ const loadPrev = useCallback(() => {
4448
+ const currentPage = actions.pagination.getPage();
4449
+ if (currentPage <= 0) return;
4450
+ const query = actions.search.getQuery();
4451
+ search(query, currentPage - 1);
4452
+ }, [actions, search]);
4453
+ return { search, loadNext, loadPrev };
4454
+ }
4455
+
4456
+ const FILE_ICONS = {
4457
+ pdf: "\u{1F4C4}",
4458
+ doc: "\u{1F4DD}",
4459
+ docx: "\u{1F4DD}",
4460
+ xls: "\u{1F4CA}",
4461
+ xlsx: "\u{1F4CA}",
4462
+ ppt: "\u{1F4CE}",
4463
+ pptx: "\u{1F4CE}",
4464
+ zip: "\u{1F4E6}",
4465
+ rar: "\u{1F4E6}",
4466
+ jpg: "\u{1F5BC}\uFE0F",
4467
+ jpeg: "\u{1F5BC}\uFE0F",
4468
+ png: "\u{1F5BC}\uFE0F",
4469
+ gif: "\u{1F5BC}\uFE0F",
4470
+ webp: "\u{1F5BC}\uFE0F",
4471
+ mp4: "\u{1F3AC}",
4472
+ mov: "\u{1F3AC}",
4473
+ avi: "\u{1F3AC}",
4474
+ mp3: "\u{1F3B5}",
4475
+ wav: "\u{1F3B5}"
4476
+ };
4477
+ const CarouselCard = ({
4478
+ item,
4479
+ size,
4480
+ selectionMode,
4481
+ isSelected,
4482
+ disabled,
4483
+ onSelect,
4484
+ onRemove,
4485
+ onPreview
4486
+ }) => {
4487
+ const isSelectable = selectionMode !== "none" && !disabled;
4488
+ const hasPreview = selectionMode === "none" && !!onPreview && item.src && (item.type === "image" || item.type === "file");
4489
+ const isClickable = isSelectable || hasPreview;
4490
+ const handleClick = () => {
4491
+ if (isSelectable) {
4492
+ if (selectionMode === "removable") return;
4493
+ onSelect(item);
4494
+ return;
4495
+ }
4496
+ if (hasPreview) {
4497
+ onPreview(item);
4498
+ }
4499
+ };
4500
+ const handleRemove = (e) => {
4501
+ e.stopPropagation();
4502
+ if (disabled) return;
4503
+ onRemove(item);
4504
+ };
4505
+ if (item.status === "loading") {
4506
+ 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" }) });
4507
+ }
4508
+ return /* @__PURE__ */ jsxs(
4509
+ "div",
4510
+ {
4511
+ className: [
4512
+ "px-chat-carousel-card",
4513
+ `px-chat-carousel-card--${size}`,
4514
+ `px-chat-carousel-card--${item.type}`,
4515
+ isSelected ? "px-chat-carousel-card--selected" : "",
4516
+ isClickable ? "px-chat-carousel-card--clickable" : "",
4517
+ disabled ? "px-chat-carousel-card--disabled" : ""
4518
+ ].filter(Boolean).join(" "),
4519
+ onClick: handleClick,
4520
+ role: isClickable ? "button" : void 0,
4521
+ tabIndex: isClickable ? 0 : void 0,
4522
+ onKeyDown: isClickable ? (e) => {
4523
+ if (e.key === "Enter" || e.key === " ") handleClick();
4524
+ } : void 0,
4525
+ children: [
4526
+ selectionMode === "removable" && !disabled && /* @__PURE__ */ jsx(
4527
+ "button",
4528
+ {
4529
+ className: "px-chat-carousel-card__remove",
4530
+ onClick: handleRemove,
4531
+ "aria-label": "Eliminar",
4532
+ type: "button",
4533
+ children: "\xD7"
4534
+ }
4535
+ ),
4536
+ isSelected && selectionMode !== "removable" && /* @__PURE__ */ jsx("div", { className: "px-chat-carousel-card__check", children: "\u2713" }),
4537
+ item.type === "image" && /* @__PURE__ */ jsx(
4538
+ "img",
4539
+ {
4540
+ className: "px-chat-carousel-card__image",
4541
+ src: item.src,
4542
+ alt: item.title || "",
4543
+ loading: "lazy"
4544
+ }
4545
+ ),
4546
+ item.type === "file" && /* @__PURE__ */ jsx("div", { className: "px-chat-carousel-card__file-icon", children: FILE_ICONS[item.file_type?.toLowerCase() ?? ""] || "\u{1F4C1}" }),
4547
+ item.type === "text" && !item.title && !item.description && /* @__PURE__ */ jsx("div", { className: "px-chat-carousel-card__file-icon", children: "\u{1F4CB}" }),
4548
+ (item.title || item.description) && /* @__PURE__ */ jsxs("div", { className: "px-chat-carousel-card__info", children: [
4549
+ item.title && /* @__PURE__ */ jsx("div", { className: "px-chat-carousel-card__title", children: item.title }),
4550
+ item.description && /* @__PURE__ */ jsx("div", { className: "px-chat-carousel-card__description", children: item.description })
4551
+ ] })
4552
+ ]
4553
+ }
4554
+ );
4555
+ };
4556
+
4557
+ const CarouselTrack = ({
4558
+ currentPage,
4559
+ hasMore,
4560
+ onPrev,
4561
+ onNext,
4562
+ children
4563
+ }) => {
4564
+ const trackRef = useRef(null);
4565
+ useEffect(() => {
4566
+ if (trackRef.current) {
4567
+ trackRef.current.scrollLeft = 0;
4568
+ }
4569
+ }, [currentPage]);
4570
+ const showPrev = currentPage > 0;
4571
+ const showNext = hasMore;
4572
+ return /* @__PURE__ */ jsxs("div", { className: "px-chat-carousel-track-wrapper", children: [
4573
+ showPrev && /* @__PURE__ */ jsx(
4574
+ "button",
4575
+ {
4576
+ className: "px-chat-carousel-track__nav",
4577
+ onClick: onPrev,
4578
+ type: "button",
4579
+ "aria-label": "Anterior",
4580
+ 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" }) })
4581
+ }
4582
+ ),
4583
+ /* @__PURE__ */ jsx("div", { className: "px-chat-carousel-track", ref: trackRef, children }),
4584
+ showNext && /* @__PURE__ */ jsx(
4585
+ "button",
4586
+ {
4587
+ className: "px-chat-carousel-track__nav",
4588
+ onClick: onNext,
4589
+ type: "button",
4590
+ "aria-label": "Siguiente",
4591
+ 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" }) })
4592
+ }
4593
+ )
4594
+ ] });
4595
+ };
4596
+
4597
+ const DEBOUNCE_MS = 300;
4598
+ const CarouselSearch = ({ onSearch, loading }) => {
4599
+ const [value, setValue] = useState("");
4600
+ const timerRef = useRef(void 0);
4601
+ const onSearchRef = useRef(onSearch);
4602
+ onSearchRef.current = onSearch;
4603
+ useEffect(() => {
4604
+ clearTimeout(timerRef.current);
4605
+ timerRef.current = setTimeout(() => {
4606
+ onSearchRef.current(value);
4607
+ }, DEBOUNCE_MS);
4608
+ return () => clearTimeout(timerRef.current);
4609
+ }, [value]);
4610
+ return /* @__PURE__ */ jsxs("div", { className: "px-chat-carousel-search", children: [
4611
+ /* @__PURE__ */ jsx(
4612
+ "input",
4613
+ {
4614
+ className: "px-chat-carousel-search__input",
4615
+ type: "text",
4616
+ placeholder: "Buscar...",
4617
+ value,
4618
+ onChange: (e) => setValue(e.target.value)
4619
+ }
4620
+ ),
4621
+ loading && /* @__PURE__ */ jsx("span", { className: "px-chat-carousel-search__spinner" }),
4622
+ value && !loading && /* @__PURE__ */ jsx(
4623
+ "button",
4624
+ {
4625
+ className: "px-chat-carousel-search__clear",
4626
+ onClick: () => setValue(""),
4627
+ type: "button",
4628
+ "aria-label": "Limpiar",
4629
+ children: "\xD7"
4630
+ }
4631
+ )
4632
+ ] });
4633
+ };
4634
+
4635
+ const CarouselConfirm = ({
4636
+ label,
4637
+ count,
4638
+ disabled,
4639
+ onClick
4640
+ }) => {
4641
+ return /* @__PURE__ */ jsx("div", { className: "px-chat-carousel-confirm", children: /* @__PURE__ */ jsxs(
4642
+ "button",
4643
+ {
4644
+ className: "px-chat-carousel-confirm__button",
4645
+ disabled,
4646
+ onClick,
4647
+ type: "button",
4648
+ children: [
4649
+ label,
4650
+ " ",
4651
+ count > 0 && /* @__PURE__ */ jsxs("span", { className: "px-chat-carousel-confirm__count", children: [
4652
+ "(",
4653
+ count,
4654
+ ")"
4655
+ ] })
4656
+ ]
4657
+ }
4658
+ ) });
4659
+ };
4660
+
4661
+ const CarouselDisplay = ({
4662
+ component,
4663
+ eventBus,
4664
+ assistantMessageId = ""
4665
+ }) => {
4666
+ const props = component.props;
4667
+ const {
4668
+ items: initialItems = [],
4669
+ size: sizeProp,
4670
+ selection_mode: selectionMode = "none",
4671
+ confirm_label: confirmLabel = "Confirmar",
4672
+ searchable = false,
4673
+ search_endpoint: searchEndpoint,
4674
+ field_name: fieldName = ""
4675
+ } = props;
4676
+ const isAnswered = component.answered === true;
4677
+ const disabled = isAnswered && selectionMode !== "none";
4678
+ const { store, actions } = useMemo(() => {
4679
+ const s = createCarouselStore(initialItems);
4680
+ if (searchable && initialItems.length === 0) {
4681
+ s.set(CAROUSEL_STORE_KEYS.SEARCH_STATUS, "loading");
4682
+ }
4683
+ return { store: s, actions: createCarouselActions(s) };
4684
+ }, []);
4685
+ const items = useStoreState(store, CAROUSEL_STORE_KEYS.ITEMS);
4686
+ const selectedIds = useStoreState(store, CAROUSEL_STORE_KEYS.SELECTED_IDS);
4687
+ const searchStatus = useStoreState(store, CAROUSEL_STORE_KEYS.SEARCH_STATUS);
4688
+ const hasMore = useStoreState(store, CAROUSEL_STORE_KEYS.HAS_MORE);
4689
+ const currentPage = useStoreState(store, CAROUSEL_STORE_KEYS.CURRENT_PAGE);
4690
+ const containerRef = useRef(null);
4691
+ const resolvedSize = resolveSize(sizeProp, items.length);
4692
+ const pageLimit = useMemo(() => {
4693
+ const width = containerRef.current?.clientWidth ?? window.innerWidth;
4694
+ return calcPageLimit(resolvedSize, width);
4695
+ }, [resolvedSize]);
4696
+ const { emitInteraction, isConfirmed } = useComponentInteraction({
4697
+ eventBus,
4698
+ fieldName,
4699
+ componentType: "carousel",
4700
+ assistantMessageId
4701
+ });
4702
+ const { search, loadNext, loadPrev } = useCarouselSearch({
4703
+ actions,
4704
+ endpoint: searchEndpoint,
4705
+ eventBus,
4706
+ pageLimit
4707
+ });
4708
+ useEffect(() => {
4709
+ if (searchable && initialItems.length === 0) {
4710
+ search("", 0);
4711
+ }
4712
+ }, []);
4713
+ const handleSelect = useCallback(
4714
+ (item) => {
4715
+ if (disabled || isConfirmed) return;
4716
+ if (selectionMode === "single") {
4717
+ actions.selection.clear();
4718
+ actions.selection.toggle(item.id);
4719
+ emitInteraction(
4720
+ [{ value: item.id, label: item.title || item.id }],
4721
+ item.title || item.id
4722
+ );
4723
+ return;
4724
+ }
4725
+ if (selectionMode === "multiple") {
4726
+ actions.selection.toggle(item.id);
4727
+ }
4728
+ },
4729
+ [selectionMode, disabled, isConfirmed, actions, emitInteraction]
4730
+ );
4731
+ const handleRemove = useCallback(
4732
+ (item) => {
4733
+ if (disabled || isConfirmed) return;
4734
+ actions.items.remove(item.id);
4735
+ },
4736
+ [disabled, isConfirmed, actions]
4737
+ );
4738
+ const handleConfirm = useCallback(() => {
4739
+ if (disabled || isConfirmed) return;
4740
+ if (selectionMode === "multiple") {
4741
+ const selected = items.filter((i) => selectedIds.includes(i.id));
4742
+ const value = selected.map((i) => ({ value: i.id, label: i.title || i.id }));
4743
+ const label = selected.map((i) => i.title || i.id).join(", ");
4744
+ emitInteraction(value, label);
4745
+ }
4746
+ if (selectionMode === "removable") {
4747
+ const value = items.map((i) => ({ value: i.id, label: i.title || i.id }));
4748
+ const label = items.map((i) => i.title || i.id).join(", ");
4749
+ emitInteraction(value, label);
4750
+ }
4751
+ }, [selectionMode, disabled, isConfirmed, items, selectedIds, emitInteraction]);
4752
+ const confirmDisabled = useMemo(() => {
4753
+ if (selectionMode === "multiple") return selectedIds.length === 0;
4754
+ if (selectionMode === "removable") {
4755
+ const originalLen = actions.getOriginalItems().length;
4756
+ return items.length === originalLen;
4757
+ }
4758
+ return true;
4759
+ }, [selectionMode, selectedIds, items, actions]);
4760
+ const showConfirm = (selectionMode === "multiple" || selectionMode === "removable") && !disabled && !isConfirmed;
4761
+ if (selectionMode === "single" && (isConfirmed || isAnswered)) {
4762
+ return null;
4763
+ }
4764
+ return /* @__PURE__ */ jsxs("div", { className: "px-chat-carousel", ref: containerRef, children: [
4765
+ searchable && /* @__PURE__ */ jsx(
4766
+ CarouselSearch,
4767
+ {
4768
+ onSearch: (q) => search(q, 0),
4769
+ loading: searchStatus === "loading"
4770
+ }
4771
+ ),
4772
+ /* @__PURE__ */ jsx(
4773
+ CarouselTrack,
4774
+ {
4775
+ currentPage,
4776
+ hasMore,
4777
+ onPrev: loadPrev,
4778
+ onNext: loadNext,
4779
+ children: items.map((item) => /* @__PURE__ */ jsx(
4780
+ CarouselCard,
4781
+ {
4782
+ item,
4783
+ size: resolvedSize,
4784
+ selectionMode,
4785
+ isSelected: selectedIds.includes(item.id),
4786
+ disabled: disabled || isConfirmed,
4787
+ onSelect: handleSelect,
4788
+ onRemove: handleRemove
4789
+ },
4790
+ item.id
4791
+ ))
4792
+ }
4793
+ ),
4794
+ showConfirm && /* @__PURE__ */ jsx(
4795
+ CarouselConfirm,
4796
+ {
4797
+ label: confirmLabel,
4798
+ count: selectionMode === "multiple" ? selectedIds.length : items.length,
4799
+ disabled: confirmDisabled,
4800
+ onClick: handleConfirm
4801
+ }
4802
+ ),
4803
+ items.length === 0 && searchStatus !== "loading" && /* @__PURE__ */ jsx("div", { className: "px-chat-carousel__empty", children: "Sin resultados" })
4804
+ ] });
4805
+ };
4806
+
4807
+ const COMPONENT_MAP = {
4808
+ select: SelectWithConfirm,
4809
+ select_multiple: SelectMultipleWithConfirm,
4810
+ confirm: ConfirmButton,
4811
+ date_input: DateInputWithConfirm,
4812
+ time_input: TimeInputWithConfirm,
4813
+ input: InputWithConfirm,
4814
+ card: CardDisplay,
4815
+ badge: BadgeDisplay,
4816
+ reactive_form: ReactiveForm,
4817
+ carousel: CarouselDisplay
4818
+ };
4819
+ function renderComponent(props) {
4820
+ const { component } = props;
4821
+ if (component.answered && !DISPLAY_COMPONENTS.has(component.type)) {
4822
+ return null;
4823
+ }
4824
+ const Component = COMPONENT_MAP[component.type];
4825
+ if (!Component) return null;
4826
+ return /* @__PURE__ */ jsx(Component, { ...props });
4827
+ }
4828
+
4829
+ const StructuredContent = ({
4830
+ content,
4831
+ eventBus,
4832
+ assistantMessageId,
4833
+ className = ""
4834
+ }) => {
4835
+ const structured = parseContent(content);
4836
+ const markdownContent = structured ? structured.message : content;
4837
+ const rawComponent = structured?.component || null;
4838
+ const components = rawComponent ? Array.isArray(rawComponent) ? rawComponent : [rawComponent] : [];
4839
+ const hasVisibleComponents = components.some((comp) => !comp.answered || DISPLAY_COMPONENTS.has(comp.type));
4840
+ return /* @__PURE__ */ jsxs("div", { className: `${COMPONENT_PREFIX$1}structured-content ${className}`, children: [
4841
+ markdownContent && /* @__PURE__ */ jsx("div", { className: `${COMPONENT_PREFIX$1}assistant-message__markdown${hasVisibleComponents ? ` ${COMPONENT_PREFIX$1}assistant-message__markdown--with-component` : ``}`, children: /* @__PURE__ */ jsx(
4842
+ ReactMarkdown,
4843
+ {
4844
+ components: {
4845
+ a: ({ href, children }) => /* @__PURE__ */ jsx(
4846
+ Link,
4847
+ {
4848
+ href: href || "#",
4849
+ variant: "primary",
4850
+ size: "medium",
4851
+ weight: "bold",
4852
+ underline: false,
4853
+ children
4854
+ }
4855
+ )
4856
+ },
4857
+ children: markdownContent
4858
+ }
4859
+ ) }),
4860
+ 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}`)) })
4861
+ ] });
4862
+ };
4863
+
4864
+ const getAttachmentType = (file) => {
4865
+ const mimeType = file.type.toLowerCase();
4866
+ if (mimeType.startsWith(MIME_PREFIXES.AUDIO)) {
4867
+ return AttachmentType.AUDIO;
4868
+ }
4869
+ if (mimeType.startsWith(MIME_PREFIXES.VIDEO)) {
4870
+ return AttachmentType.VIDEO;
4871
+ }
4872
+ if (mimeType.startsWith(MIME_PREFIXES.IMAGE)) {
4873
+ return AttachmentType.IMAGE;
4874
+ }
4875
+ if (mimeType === MIME_TYPES.PDF) {
4876
+ return AttachmentType.PDF;
4877
+ }
4878
+ 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)) {
4879
+ return AttachmentType.DOCUMENT;
4880
+ }
4881
+ return AttachmentType.OTHER;
4882
+ };
4883
+ const filterFilesByType = (files, type) => {
4884
+ const types = Array.isArray(type) ? type : [type];
4885
+ return files.filter((file) => {
4886
+ const fileType = getAttachmentType(file);
4887
+ return types.includes(fileType);
4888
+ });
4889
+ };
4890
+ const getFileUrl = (file) => {
4891
+ if (file.url) {
4892
+ return file.url;
4893
+ }
4894
+ return URL.createObjectURL(file);
4895
+ };
4896
+ const getAudioFiles = (files) => {
4897
+ return filterFilesByType(files, [AttachmentType.AUDIO]);
4898
+ };
4899
+ const getNonAudioFiles = (files) => {
4900
+ return filterFilesByType(files, [
4901
+ AttachmentType.IMAGE,
4902
+ AttachmentType.PDF,
4903
+ AttachmentType.DOCUMENT,
4904
+ AttachmentType.OTHER
4905
+ ]);
4906
+ };
4907
+
4908
+ function deepMerge(target, source) {
3100
4909
  if (typeof target !== "object" || target === null) {
3101
4910
  return source;
3102
4911
  }
@@ -3197,24 +5006,248 @@ const AssistantMessage = ({
3197
5006
  className: `${COMPONENT_PREFIX$1}assistant-message__timestamp`,
3198
5007
  children: timestamp
3199
5008
  }
3200
- )
3201
- ] }) });
5009
+ )
5010
+ ] }) });
5011
+ };
5012
+
5013
+ const initialState$1 = {
5014
+ // ChatInput (molécula) - Estados del input de chat
5015
+ chatInput: {
5016
+ buttonSend: {
5017
+ disabled: true,
5018
+ // Disabled hasta que haya contenido
5019
+ visible: false
5020
+ // Inicialmente oculto
5021
+ },
5022
+ buttonMicrophone: {
5023
+ disabled: false,
5024
+ visible: true
5025
+ // Inicialmente visible (botón de audio por defecto)
5026
+ },
5027
+ buttonAttachment: {
5028
+ disabled: false
5029
+ },
5030
+ hasText: false,
5031
+ hasAttachments: false
5032
+ },
5033
+ // AssistantThinkingIndicator (molécula) - Estado del indicador
5034
+ assistantThinkingIndicator: {
5035
+ visible: false,
5036
+ agentName: void 0,
5037
+ agentLabel: void 0,
5038
+ toolName: void 0
5039
+ },
5040
+ // ScrollButton (átomo) - Estado del botón de scroll
5041
+ scrollButton: {
5042
+ visible: false
5043
+ },
5044
+ // VirtualKeyboard - Estado del teclado virtual
5045
+ virtualKeyboard: {
5046
+ isOpen: false
5047
+ },
5048
+ // Textarea - Estado del textarea del chat
5049
+ textarea: {
5050
+ isFocused: false,
5051
+ isEmpty: true,
5052
+ shouldPreventKeyboard: false,
5053
+ shouldFocus: false,
5054
+ shouldBlur: false
5055
+ },
5056
+ // Scroll to top trigger
5057
+ scrollToTop: {
5058
+ pending: false
5059
+ }
5060
+ };
5061
+ const chatStore = createStore(initialState$1);
5062
+ const setChatStore = createStoreMerger(chatStore);
5063
+ const subscribeChatProperty = createDeepPropertySubscriber(chatStore);
5064
+
5065
+ const CHAT_STORE_KEYS = {
5066
+ // ChatInput relacionado
5067
+ CHAT_INPUT: "chatInput",
5068
+ // AssistantThinkingIndicator relacionado
5069
+ ASSISTANT_THINKING_INDICATOR: "assistantThinkingIndicator",
5070
+ // ScrollButton relacionado
5071
+ SCROLL_BUTTON: "scrollButton",
5072
+ // VirtualKeyboard relacionado
5073
+ VIRTUAL_KEYBOARD: "virtualKeyboard",
5074
+ // Textarea relacionado
5075
+ TEXTAREA: "textarea",
5076
+ // Scroll to top trigger
5077
+ SCROLL_TO_TOP: "scrollToTop"
5078
+ };
5079
+
5080
+ const textareaActions = {
5081
+ focus: () => setChatStore(CHAT_STORE_KEYS.TEXTAREA, { shouldFocus: true }),
5082
+ blur: () => setChatStore(CHAT_STORE_KEYS.TEXTAREA, { shouldBlur: true }),
5083
+ setFocused: (isFocused) => setChatStore(CHAT_STORE_KEYS.TEXTAREA, { isFocused }),
5084
+ setEmpty: (isEmpty) => setChatStore(CHAT_STORE_KEYS.TEXTAREA, { isEmpty }),
5085
+ setShouldPreventKeyboard: (shouldPrevent) => setChatStore(CHAT_STORE_KEYS.TEXTAREA, { shouldPreventKeyboard: shouldPrevent }),
5086
+ resetTriggers: () => setChatStore(CHAT_STORE_KEYS.TEXTAREA, { shouldFocus: false, shouldBlur: false }),
5087
+ maintainFocusAfterSend: () => {
5088
+ setTimeout(() => {
5089
+ setChatStore(CHAT_STORE_KEYS.TEXTAREA, { shouldFocus: true });
5090
+ }, 10);
5091
+ setTimeout(() => {
5092
+ setChatStore(CHAT_STORE_KEYS.TEXTAREA, { shouldFocus: true });
5093
+ }, 50);
5094
+ },
5095
+ preserveFocusWithKeyboard: () => {
5096
+ setChatStore(CHAT_STORE_KEYS.TEXTAREA, { shouldFocus: true });
5097
+ setTimeout(() => {
5098
+ setChatStore(CHAT_STORE_KEYS.TEXTAREA, { shouldFocus: true });
5099
+ }, 10);
5100
+ setTimeout(() => {
5101
+ setChatStore(CHAT_STORE_KEYS.TEXTAREA, { shouldFocus: true });
5102
+ }, 50);
5103
+ }
5104
+ };
5105
+ const keyboardActions = {
5106
+ setOpen: (isOpen) => setChatStore(CHAT_STORE_KEYS.VIRTUAL_KEYBOARD, { isOpen }),
5107
+ open: () => setChatStore(CHAT_STORE_KEYS.VIRTUAL_KEYBOARD, { isOpen: true }),
5108
+ close: () => setChatStore(CHAT_STORE_KEYS.VIRTUAL_KEYBOARD, { isOpen: false })
5109
+ };
5110
+ const chatInputActions = {
5111
+ setSendDisabled: (disabled) => {
5112
+ const currentState = chatStore.get(CHAT_STORE_KEYS.CHAT_INPUT);
5113
+ setChatStore(CHAT_STORE_KEYS.CHAT_INPUT, {
5114
+ buttonSend: {
5115
+ disabled,
5116
+ visible: currentState.buttonSend.visible
5117
+ }
5118
+ });
5119
+ },
5120
+ setMicDisabled: (disabled) => {
5121
+ const currentState = chatStore.get(CHAT_STORE_KEYS.CHAT_INPUT);
5122
+ setChatStore(CHAT_STORE_KEYS.CHAT_INPUT, {
5123
+ buttonMicrophone: {
5124
+ disabled,
5125
+ visible: currentState.buttonMicrophone.visible
5126
+ }
5127
+ });
5128
+ },
5129
+ setAttachDisabled: (disabled) => setChatStore(CHAT_STORE_KEYS.CHAT_INPUT, { buttonAttachment: { disabled } }),
5130
+ setSendVisible: (visible) => {
5131
+ const currentState = chatStore.get(CHAT_STORE_KEYS.CHAT_INPUT);
5132
+ setChatStore(CHAT_STORE_KEYS.CHAT_INPUT, {
5133
+ buttonSend: {
5134
+ visible,
5135
+ disabled: currentState.buttonSend.disabled
5136
+ }
5137
+ });
5138
+ },
5139
+ setMicVisible: (visible) => {
5140
+ const currentState = chatStore.get(CHAT_STORE_KEYS.CHAT_INPUT);
5141
+ setChatStore(CHAT_STORE_KEYS.CHAT_INPUT, {
5142
+ buttonMicrophone: {
5143
+ visible,
5144
+ disabled: currentState.buttonMicrophone.disabled
5145
+ }
5146
+ });
5147
+ },
5148
+ setHasText: (hasText) => setChatStore(CHAT_STORE_KEYS.CHAT_INPUT, { hasText }),
5149
+ setHasAttachments: (hasAttachments) => setChatStore(CHAT_STORE_KEYS.CHAT_INPUT, { hasAttachments }),
5150
+ updateButtonVisibility: (hasText, hasAttachments) => {
5151
+ const shouldShowSend = hasText || hasAttachments;
5152
+ const shouldShowMic = !hasText && !hasAttachments;
5153
+ const isThinking = chatStore.get(CHAT_STORE_KEYS.ASSISTANT_THINKING_INDICATOR).visible;
5154
+ const hasContent = hasText || hasAttachments;
5155
+ const currentState = chatStore.get(CHAT_STORE_KEYS.CHAT_INPUT);
5156
+ setChatStore(CHAT_STORE_KEYS.CHAT_INPUT, {
5157
+ hasText,
5158
+ hasAttachments,
5159
+ buttonSend: {
5160
+ visible: shouldShowSend,
5161
+ disabled: isThinking || !hasContent
5162
+ },
5163
+ buttonMicrophone: {
5164
+ visible: shouldShowMic,
5165
+ disabled: currentState.buttonMicrophone.disabled
5166
+ }
5167
+ });
5168
+ }
5169
+ };
5170
+ const thinkingActions = {
5171
+ setVisible: (visible) => setChatStore(CHAT_STORE_KEYS.ASSISTANT_THINKING_INDICATOR, { visible }),
5172
+ show: () => setChatStore(CHAT_STORE_KEYS.ASSISTANT_THINKING_INDICATOR, { visible: true }),
5173
+ hide: () => setChatStore(CHAT_STORE_KEYS.ASSISTANT_THINKING_INDICATOR, {
5174
+ visible: false,
5175
+ agentName: void 0,
5176
+ agentLabel: void 0,
5177
+ toolName: void 0
5178
+ }),
5179
+ setThinking: (isThinking) => {
5180
+ setChatStore(CHAT_STORE_KEYS.ASSISTANT_THINKING_INDICATOR, { visible: isThinking });
5181
+ },
5182
+ setAgentName: (agentName) => setChatStore(CHAT_STORE_KEYS.ASSISTANT_THINKING_INDICATOR, { agentName }),
5183
+ setAgentLabel: (agentLabel) => setChatStore(CHAT_STORE_KEYS.ASSISTANT_THINKING_INDICATOR, { agentLabel }),
5184
+ setToolName: (toolName) => setChatStore(CHAT_STORE_KEYS.ASSISTANT_THINKING_INDICATOR, { toolName })
5185
+ };
5186
+ const scrollButtonActions = {
5187
+ setVisible: (visible) => setChatStore(CHAT_STORE_KEYS.SCROLL_BUTTON, { visible }),
5188
+ show: () => setChatStore(CHAT_STORE_KEYS.SCROLL_BUTTON, { visible: true }),
5189
+ hide: () => setChatStore(CHAT_STORE_KEYS.SCROLL_BUTTON, { visible: false })
5190
+ };
5191
+ const scrollToTopActions = {
5192
+ activate: () => setChatStore(CHAT_STORE_KEYS.SCROLL_TO_TOP, { pending: true }),
5193
+ reset: () => setChatStore(CHAT_STORE_KEYS.SCROLL_TO_TOP, { pending: false })
5194
+ };
5195
+ const combinedActions = {
5196
+ prepareFileButtonClick: (isEmpty, isKeyboardOpen) => {
5197
+ if (!isKeyboardOpen && isEmpty) {
5198
+ textareaActions.setShouldPreventKeyboard(true);
5199
+ textareaActions.blur();
5200
+ }
5201
+ },
5202
+ initializeChat: () => {
5203
+ textareaActions.setEmpty(true);
5204
+ textareaActions.setFocused(false);
5205
+ keyboardActions.close();
5206
+ thinkingActions.hide();
5207
+ scrollButtonActions.hide();
5208
+ chatInputActions.updateButtonVisibility(false, false);
5209
+ },
5210
+ handleMessageSend: () => {
5211
+ textareaActions.maintainFocusAfterSend();
5212
+ }
3202
5213
  };
3203
5214
 
3204
- const messages = {
5215
+ const fallbackMessages = {
3205
5216
  short: ["Revisando...", "Procesando...", "Analizando..."],
3206
5217
  medium: ["Analizando tu consulta...", "Estoy viendo c\xF3mo resolverlo...", "Buscando la mejor manera de ayudarte..."],
3207
5218
  long: ["Sigo con esto. Un momento m\xE1s.", "Estoy en eso, ya te respondo.", "Ya casi lo tengo."],
3208
5219
  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
5220
  };
3210
5221
  const getRandomMessage = (category) => {
3211
- const categoryMessages = messages[category];
5222
+ const categoryMessages = fallbackMessages[category];
3212
5223
  return categoryMessages[Math.floor(Math.random() * categoryMessages.length)];
3213
5224
  };
3214
5225
  const AssistantThinkingIndicator = () => {
3215
5226
  const { showRoleLabels } = useChatConfig();
3216
- const [displayedMessage, setDisplayedMessage] = useState(getRandomMessage("short"));
5227
+ const [fallbackMessage, setFallbackMessage] = useState(getRandomMessage("short"));
3217
5228
  const [elapsedSeconds, setElapsedSeconds] = useState(0);
5229
+ const [agentLabel, setAgentLabel] = useState(
5230
+ chatStore.get(CHAT_STORE_KEYS.ASSISTANT_THINKING_INDICATOR).agentLabel
5231
+ );
5232
+ const [toolName, setToolName] = useState(
5233
+ chatStore.get(CHAT_STORE_KEYS.ASSISTANT_THINKING_INDICATOR).toolName
5234
+ );
5235
+ useEffect(() => {
5236
+ const unsubLabel = subscribeChatProperty(
5237
+ CHAT_STORE_KEYS.ASSISTANT_THINKING_INDICATOR,
5238
+ "agentLabel",
5239
+ setAgentLabel
5240
+ );
5241
+ const unsubTool = subscribeChatProperty(
5242
+ CHAT_STORE_KEYS.ASSISTANT_THINKING_INDICATOR,
5243
+ "toolName",
5244
+ setToolName
5245
+ );
5246
+ return () => {
5247
+ unsubLabel();
5248
+ unsubTool();
5249
+ };
5250
+ }, []);
3218
5251
  useEffect(() => {
3219
5252
  const timer = setInterval(() => {
3220
5253
  setElapsedSeconds((prev) => prev + 1);
@@ -3223,13 +5256,14 @@ const AssistantThinkingIndicator = () => {
3223
5256
  }, []);
3224
5257
  useEffect(() => {
3225
5258
  if (elapsedSeconds === 6) {
3226
- setDisplayedMessage(getRandomMessage("medium"));
5259
+ setFallbackMessage(getRandomMessage("medium"));
3227
5260
  } else if (elapsedSeconds === 13) {
3228
- setDisplayedMessage(getRandomMessage("long"));
5261
+ setFallbackMessage(getRandomMessage("long"));
3229
5262
  } else if (elapsedSeconds === 21) {
3230
- setDisplayedMessage(getRandomMessage("veryLong"));
5263
+ setFallbackMessage(getRandomMessage("veryLong"));
3231
5264
  }
3232
5265
  }, [elapsedSeconds]);
5266
+ const displayedMessage = agentLabel ? toolName ? `${agentLabel} \u2014 ${toolName}` : `${agentLabel}...` : fallbackMessage;
3233
5267
  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
5268
  showRoleLabels && /* @__PURE__ */ jsx(Text, { variant: "caption", color: "secondary", className: `${COMPONENT_PREFIX$1}assistant-thinking-indicator__role`, children: "Assistant" }),
3235
5269
  /* @__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 +5706,6 @@ const FullscreenViewer = ({
3672
5706
  );
3673
5707
  };
3674
5708
 
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
5709
  const ChatInput = forwardRef(({
3867
5710
  value,
3868
5711
  onChange,
@@ -4787,6 +6630,15 @@ const useChatStore = () => {
4787
6630
  const [showThinking, setShowThinking] = useState(
4788
6631
  chatStore.get(CHAT_STORE_KEYS.ASSISTANT_THINKING_INDICATOR).visible
4789
6632
  );
6633
+ const [agentName, setAgentName] = useState(
6634
+ chatStore.get(CHAT_STORE_KEYS.ASSISTANT_THINKING_INDICATOR).agentName
6635
+ );
6636
+ const [agentLabel, setAgentLabel] = useState(
6637
+ chatStore.get(CHAT_STORE_KEYS.ASSISTANT_THINKING_INDICATOR).agentLabel
6638
+ );
6639
+ const [toolName, setToolName] = useState(
6640
+ chatStore.get(CHAT_STORE_KEYS.ASSISTANT_THINKING_INDICATOR).toolName
6641
+ );
4790
6642
  const [scrollButtonState, setScrollButtonState] = useState(
4791
6643
  chatStore.get(CHAT_STORE_KEYS.SCROLL_BUTTON)
4792
6644
  );
@@ -4799,6 +6651,21 @@ const useChatStore = () => {
4799
6651
  "visible",
4800
6652
  setShowThinking
4801
6653
  );
6654
+ const unsubAgentName = subscribeChatProperty(
6655
+ CHAT_STORE_KEYS.ASSISTANT_THINKING_INDICATOR,
6656
+ "agentName",
6657
+ setAgentName
6658
+ );
6659
+ const unsubAgentLabel = subscribeChatProperty(
6660
+ CHAT_STORE_KEYS.ASSISTANT_THINKING_INDICATOR,
6661
+ "agentLabel",
6662
+ setAgentLabel
6663
+ );
6664
+ const unsubToolName = subscribeChatProperty(
6665
+ CHAT_STORE_KEYS.ASSISTANT_THINKING_INDICATOR,
6666
+ "toolName",
6667
+ setToolName
6668
+ );
4802
6669
  const unsubScrollButton = subscribeChatProperty(
4803
6670
  CHAT_STORE_KEYS.SCROLL_BUTTON,
4804
6671
  "",
@@ -4811,12 +6678,18 @@ const useChatStore = () => {
4811
6678
  );
4812
6679
  return () => {
4813
6680
  unsubThinking();
6681
+ unsubAgentName();
6682
+ unsubAgentLabel();
6683
+ unsubToolName();
4814
6684
  unsubScrollButton();
4815
6685
  unsubScrollToTop();
4816
6686
  };
4817
6687
  }, []);
4818
6688
  return {
4819
6689
  showThinking,
6690
+ agentName,
6691
+ agentLabel,
6692
+ toolName,
4820
6693
  scrollButtonState,
4821
6694
  scrollToTopPending
4822
6695
  };