pixelon 0.3.25 → 0.3.26

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