pixelon 0.3.25 → 0.3.27

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