@nuraly/runtime 0.1.0

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 (970) hide show
  1. package/README.md +778 -0
  2. package/components/index.ts +13 -0
  3. package/components/ui/components/Event/EventAttribute/EventAttribute.style.ts +11 -0
  4. package/components/ui/components/Event/EventAttribute/EventAttribute.ts +28 -0
  5. package/components/ui/components/Event/EventLabel/EventLabel.ts +19 -0
  6. package/components/ui/components/Event/EventValue/EventValue.ts +79 -0
  7. package/components/ui/components/ToastContainer/ToastContainer.ts +126 -0
  8. package/components/ui/components/advanced/AIChat/AIChat.helper.ts +22 -0
  9. package/components/ui/components/advanced/AIChat/AIChat.style.ts +52 -0
  10. package/components/ui/components/advanced/AIChat/AIChat.ts +143 -0
  11. package/components/ui/components/advanced/CodeEditor/CodeEditor.ts +489 -0
  12. package/components/ui/components/advanced/Collapse/Collapse.ts +86 -0
  13. package/components/ui/components/advanced/Collections/Collections.style.ts +21 -0
  14. package/components/ui/components/advanced/Collections/Collections.ts +125 -0
  15. package/components/ui/components/advanced/MicroApp/MicroApp.ts +98 -0
  16. package/components/ui/components/advanced/RefComponent/RefComponent.ts +86 -0
  17. package/components/ui/components/advanced/RichText/RichText.ts +98 -0
  18. package/components/ui/components/advanced/RichText/RichTextEditor.ts +536 -0
  19. package/components/ui/components/base/BaseElement/base-change-detection.ts +18 -0
  20. package/components/ui/components/base/BaseElement/calculateStyles.ts +31 -0
  21. package/components/ui/components/base/BaseElement/drag-events.helpers.ts +71 -0
  22. package/components/ui/components/base/BaseElement/execute-event.helpers.ts +45 -0
  23. package/components/ui/components/base/BaseElement/handler-component-error.ts +28 -0
  24. package/components/ui/components/base/BaseElement/input-handler.helpers.ts +358 -0
  25. package/components/ui/components/base/BaseElement/interactions.helpers.ts +14 -0
  26. package/components/ui/components/base/BaseElement.ts +711 -0
  27. package/components/ui/components/display/Badge/Badge.ts +61 -0
  28. package/components/ui/components/display/BoxModel/BoxModel.ts +372 -0
  29. package/components/ui/components/display/Code/Code.ts +103 -0
  30. package/components/ui/components/display/Divider/Divider.ts +98 -0
  31. package/components/ui/components/display/Icon/Icon.ts +60 -0
  32. package/components/ui/components/display/Image/Image.ts +75 -0
  33. package/components/ui/components/display/Table/Table.style.ts +0 -0
  34. package/components/ui/components/display/Table/Table.ts +178 -0
  35. package/components/ui/components/display/Tag/Tag.ts +49 -0
  36. package/components/ui/components/display/TextLabel/TextLabel.style.ts +21 -0
  37. package/components/ui/components/display/TextLabel/TextLabel.ts +72 -0
  38. package/components/ui/components/display/Video/Video.ts +46 -0
  39. package/components/ui/components/inputs/Button/Button.style.ts +0 -0
  40. package/components/ui/components/inputs/Button/Button.ts +79 -0
  41. package/components/ui/components/inputs/Checkbox/Checkbox.ts +76 -0
  42. package/components/ui/components/inputs/ColorPicker/colorpicker.ts +65 -0
  43. package/components/ui/components/inputs/DatePicker/DatePicker.ts +60 -0
  44. package/components/ui/components/inputs/Dropdown/Dropdown.ts +128 -0
  45. package/components/ui/components/inputs/FileUpload/FileUpload.ts +43 -0
  46. package/components/ui/components/inputs/IconButton/iconbutton.ts +54 -0
  47. package/components/ui/components/inputs/IconPicker/IconPicker.style.ts +109 -0
  48. package/components/ui/components/inputs/IconPicker/IconPicker.ts +61 -0
  49. package/components/ui/components/inputs/InsertDropdown/InsertDropdown.ts +75 -0
  50. package/components/ui/components/inputs/NumberInput/NumberInput.ts +84 -0
  51. package/components/ui/components/inputs/RadioButton/Radio-button.ts +69 -0
  52. package/components/ui/components/inputs/Select/Select.ts +65 -0
  53. package/components/ui/components/inputs/Slider/Slider.ts +63 -0
  54. package/components/ui/components/inputs/TextInput/TextInput.style.ts +0 -0
  55. package/components/ui/components/inputs/TextInput/TextInput.ts +153 -0
  56. package/components/ui/components/inputs/Textarea/Textarea.ts +110 -0
  57. package/components/ui/components/inputs/UsersDropdown/UsersDropdown.ts +30 -0
  58. package/components/ui/components/layout/Card/Card.ts +46 -0
  59. package/components/ui/components/layout/Containers/Container.style.ts +34 -0
  60. package/components/ui/components/layout/Containers/Container.ts +127 -0
  61. package/components/ui/components/layout/Panel/Panel.ts +156 -0
  62. package/components/ui/components/layout/Panel/index.ts +1 -0
  63. package/components/ui/components/layout/Tabs/Tabs.style.ts +5 -0
  64. package/components/ui/components/layout/Tabs/Tabs.ts +120 -0
  65. package/components/ui/components/navigation/EmbedURL/EmbedURL.ts +108 -0
  66. package/components/ui/components/navigation/Link/Link.ts +83 -0
  67. package/components/ui/components/navigation/Menu/Menu.ts +92 -0
  68. package/components/ui/components/runtime/MicroApp/MicroApp.ts +485 -0
  69. package/components/ui/components/runtime/MicroApp/MicroAppDataLoader.ts +240 -0
  70. package/components/ui/components/utility/Border/Border.ts +643 -0
  71. package/components/ui/components/utility/BoxShadow/BoxShadow.ts +253 -0
  72. package/components/ui/components/utility/Document/Document.ts +47 -0
  73. package/components/ui/components/utility/Export-Import/Export-Import.ts +122 -0
  74. package/components/ui/components/utility/Function/InvokeFunction.ts +63 -0
  75. package/components/ui/components/utility/Handlers/Handlers.style.ts +0 -0
  76. package/components/ui/components/utility/Handlers/Handlers.ts +200 -0
  77. package/components/ui/components/wrappers/ComponentTitle/ComponentTitle.ts +95 -0
  78. package/components/ui/components/wrappers/GenerikWrapper/DragWrapper/DragWrapper.style.ts +17 -0
  79. package/components/ui/components/wrappers/GenerikWrapper/DragWrapper/DragWrapper.ts +230 -0
  80. package/components/ui/components/wrappers/GenerikWrapper/GenerikWrapper.style.ts +135 -0
  81. package/components/ui/components/wrappers/GenerikWrapper/GenerikWrapper.ts +230 -0
  82. package/components/ui/components/wrappers/GenerikWrapper/QuickActionWrapper/QuickActionWrapper.style.ts +99 -0
  83. package/components/ui/components/wrappers/GenerikWrapper/QuickActionWrapper/QuickActionWrapper.ts +94 -0
  84. package/components/ui/components/wrappers/GenerikWrapper/ResizeWrapper/ResizeWrapper.style.ts +102 -0
  85. package/components/ui/components/wrappers/GenerikWrapper/ResizeWrapper/ResizeWrapper.ts +258 -0
  86. package/components/ui/components/wrappers/PreviewWrapper.ts +28 -0
  87. package/components/ui/components/wrappers/RectangleSelection/RectangleSelection.ts +154 -0
  88. package/components/ui/nuraly-ui/.storybook/main.ts +31 -0
  89. package/components/ui/nuraly-ui/.storybook/manager.ts +17 -0
  90. package/components/ui/nuraly-ui/.storybook/preview.ts +94 -0
  91. package/components/ui/nuraly-ui/LICENSE +28 -0
  92. package/components/ui/nuraly-ui/README.md +248 -0
  93. package/components/ui/nuraly-ui/examples/README.md +413 -0
  94. package/components/ui/nuraly-ui/packages/common/README.md +137 -0
  95. package/components/ui/nuraly-ui/packages/common/dist/constants/index.js +2 -0
  96. package/components/ui/nuraly-ui/packages/common/dist/constants.js +7 -0
  97. package/components/ui/nuraly-ui/packages/common/dist/controllers/index.js +2 -0
  98. package/components/ui/nuraly-ui/packages/common/dist/controllers.js +22 -0
  99. package/components/ui/nuraly-ui/packages/common/dist/index.js +27 -0
  100. package/components/ui/nuraly-ui/packages/common/dist/mixins/index.js +3 -0
  101. package/components/ui/nuraly-ui/packages/common/dist/mixins.js +29 -0
  102. package/components/ui/nuraly-ui/packages/common/dist/shared/base-mixin.js +38 -0
  103. package/components/ui/nuraly-ui/packages/common/dist/shared/constants.js +2 -0
  104. package/components/ui/nuraly-ui/packages/common/dist/shared/controllers/dropdown.controller.js +341 -0
  105. package/components/ui/nuraly-ui/packages/common/dist/shared/controllers/dropdown.interface.js +2 -0
  106. package/components/ui/nuraly-ui/packages/common/dist/shared/controllers/index.js +4 -0
  107. package/components/ui/nuraly-ui/packages/common/dist/shared/controllers/theme.controller.js +133 -0
  108. package/components/ui/nuraly-ui/packages/common/dist/shared/dependency-mixin.js +141 -0
  109. package/components/ui/nuraly-ui/packages/common/dist/shared/event-handler-mixin.js +95 -0
  110. package/components/ui/nuraly-ui/packages/common/dist/shared/index.js +17 -0
  111. package/components/ui/nuraly-ui/packages/common/dist/shared/theme-mixin.js +194 -0
  112. package/components/ui/nuraly-ui/packages/common/dist/shared/themes.js +85 -0
  113. package/components/ui/nuraly-ui/packages/common/dist/shared/utils.js +85 -0
  114. package/components/ui/nuraly-ui/packages/common/dist/shared/validation.types.js +17 -0
  115. package/components/ui/nuraly-ui/packages/common/dist/themes/index.js +2 -0
  116. package/components/ui/nuraly-ui/packages/common/dist/themes.js +23 -0
  117. package/components/ui/nuraly-ui/packages/common/dist/utils/index.js +2 -0
  118. package/components/ui/nuraly-ui/packages/common/dist/utils.js +22 -0
  119. package/components/ui/nuraly-ui/packages/forms/README.md +84 -0
  120. package/components/ui/nuraly-ui/packages/forms/node_modules/fs-extra/LICENSE +15 -0
  121. package/components/ui/nuraly-ui/packages/forms/node_modules/fs-extra/README.md +294 -0
  122. package/components/ui/nuraly-ui/packages/forms/node_modules/fs-extra/lib/copy/copy-sync.js +171 -0
  123. package/components/ui/nuraly-ui/packages/forms/node_modules/fs-extra/lib/copy/copy.js +175 -0
  124. package/components/ui/nuraly-ui/packages/forms/node_modules/fs-extra/lib/copy/index.js +7 -0
  125. package/components/ui/nuraly-ui/packages/forms/node_modules/fs-extra/lib/empty/index.js +39 -0
  126. package/components/ui/nuraly-ui/packages/forms/node_modules/fs-extra/lib/ensure/file.js +66 -0
  127. package/components/ui/nuraly-ui/packages/forms/node_modules/fs-extra/lib/ensure/index.js +23 -0
  128. package/components/ui/nuraly-ui/packages/forms/node_modules/fs-extra/lib/ensure/link.js +64 -0
  129. package/components/ui/nuraly-ui/packages/forms/node_modules/fs-extra/lib/ensure/symlink-paths.js +101 -0
  130. package/components/ui/nuraly-ui/packages/forms/node_modules/fs-extra/lib/ensure/symlink-type.js +34 -0
  131. package/components/ui/nuraly-ui/packages/forms/node_modules/fs-extra/lib/ensure/symlink.js +67 -0
  132. package/components/ui/nuraly-ui/packages/forms/node_modules/fs-extra/lib/fs/index.js +146 -0
  133. package/components/ui/nuraly-ui/packages/forms/node_modules/fs-extra/lib/index.js +16 -0
  134. package/components/ui/nuraly-ui/packages/forms/node_modules/fs-extra/lib/json/index.js +16 -0
  135. package/components/ui/nuraly-ui/packages/forms/node_modules/fs-extra/lib/json/jsonfile.js +11 -0
  136. package/components/ui/nuraly-ui/packages/forms/node_modules/fs-extra/lib/json/output-json-sync.js +12 -0
  137. package/components/ui/nuraly-ui/packages/forms/node_modules/fs-extra/lib/json/output-json.js +12 -0
  138. package/components/ui/nuraly-ui/packages/forms/node_modules/fs-extra/lib/mkdirs/index.js +14 -0
  139. package/components/ui/nuraly-ui/packages/forms/node_modules/fs-extra/lib/mkdirs/make-dir.js +27 -0
  140. package/components/ui/nuraly-ui/packages/forms/node_modules/fs-extra/lib/mkdirs/utils.js +21 -0
  141. package/components/ui/nuraly-ui/packages/forms/node_modules/fs-extra/lib/move/index.js +7 -0
  142. package/components/ui/nuraly-ui/packages/forms/node_modules/fs-extra/lib/move/move-sync.js +55 -0
  143. package/components/ui/nuraly-ui/packages/forms/node_modules/fs-extra/lib/move/move.js +59 -0
  144. package/components/ui/nuraly-ui/packages/forms/node_modules/fs-extra/lib/output-file/index.js +31 -0
  145. package/components/ui/nuraly-ui/packages/forms/node_modules/fs-extra/lib/path-exists/index.js +12 -0
  146. package/components/ui/nuraly-ui/packages/forms/node_modules/fs-extra/lib/remove/index.js +17 -0
  147. package/components/ui/nuraly-ui/packages/forms/node_modules/fs-extra/lib/util/async.js +29 -0
  148. package/components/ui/nuraly-ui/packages/forms/node_modules/fs-extra/lib/util/stat.js +159 -0
  149. package/components/ui/nuraly-ui/packages/forms/node_modules/fs-extra/lib/util/utimes.js +36 -0
  150. package/components/ui/nuraly-ui/packages/layout/README.md +77 -0
  151. package/components/ui/nuraly-ui/packages/layout/node_modules/fs-extra/LICENSE +15 -0
  152. package/components/ui/nuraly-ui/packages/layout/node_modules/fs-extra/README.md +294 -0
  153. package/components/ui/nuraly-ui/packages/layout/node_modules/fs-extra/lib/copy/copy-sync.js +171 -0
  154. package/components/ui/nuraly-ui/packages/layout/node_modules/fs-extra/lib/copy/copy.js +175 -0
  155. package/components/ui/nuraly-ui/packages/layout/node_modules/fs-extra/lib/copy/index.js +7 -0
  156. package/components/ui/nuraly-ui/packages/layout/node_modules/fs-extra/lib/empty/index.js +39 -0
  157. package/components/ui/nuraly-ui/packages/layout/node_modules/fs-extra/lib/ensure/file.js +66 -0
  158. package/components/ui/nuraly-ui/packages/layout/node_modules/fs-extra/lib/ensure/index.js +23 -0
  159. package/components/ui/nuraly-ui/packages/layout/node_modules/fs-extra/lib/ensure/link.js +64 -0
  160. package/components/ui/nuraly-ui/packages/layout/node_modules/fs-extra/lib/ensure/symlink-paths.js +101 -0
  161. package/components/ui/nuraly-ui/packages/layout/node_modules/fs-extra/lib/ensure/symlink-type.js +34 -0
  162. package/components/ui/nuraly-ui/packages/layout/node_modules/fs-extra/lib/ensure/symlink.js +67 -0
  163. package/components/ui/nuraly-ui/packages/layout/node_modules/fs-extra/lib/fs/index.js +146 -0
  164. package/components/ui/nuraly-ui/packages/layout/node_modules/fs-extra/lib/index.js +16 -0
  165. package/components/ui/nuraly-ui/packages/layout/node_modules/fs-extra/lib/json/index.js +16 -0
  166. package/components/ui/nuraly-ui/packages/layout/node_modules/fs-extra/lib/json/jsonfile.js +11 -0
  167. package/components/ui/nuraly-ui/packages/layout/node_modules/fs-extra/lib/json/output-json-sync.js +12 -0
  168. package/components/ui/nuraly-ui/packages/layout/node_modules/fs-extra/lib/json/output-json.js +12 -0
  169. package/components/ui/nuraly-ui/packages/layout/node_modules/fs-extra/lib/mkdirs/index.js +14 -0
  170. package/components/ui/nuraly-ui/packages/layout/node_modules/fs-extra/lib/mkdirs/make-dir.js +27 -0
  171. package/components/ui/nuraly-ui/packages/layout/node_modules/fs-extra/lib/mkdirs/utils.js +21 -0
  172. package/components/ui/nuraly-ui/packages/layout/node_modules/fs-extra/lib/move/index.js +7 -0
  173. package/components/ui/nuraly-ui/packages/layout/node_modules/fs-extra/lib/move/move-sync.js +55 -0
  174. package/components/ui/nuraly-ui/packages/layout/node_modules/fs-extra/lib/move/move.js +59 -0
  175. package/components/ui/nuraly-ui/packages/layout/node_modules/fs-extra/lib/output-file/index.js +31 -0
  176. package/components/ui/nuraly-ui/packages/layout/node_modules/fs-extra/lib/path-exists/index.js +12 -0
  177. package/components/ui/nuraly-ui/packages/layout/node_modules/fs-extra/lib/remove/index.js +17 -0
  178. package/components/ui/nuraly-ui/packages/layout/node_modules/fs-extra/lib/util/async.js +29 -0
  179. package/components/ui/nuraly-ui/packages/layout/node_modules/fs-extra/lib/util/stat.js +159 -0
  180. package/components/ui/nuraly-ui/packages/layout/node_modules/fs-extra/lib/util/utimes.js +36 -0
  181. package/components/ui/nuraly-ui/packages/themes/README.md +146 -0
  182. package/components/ui/nuraly-ui/packages/themes/scripts/build.js +444 -0
  183. package/components/ui/nuraly-ui/rollup.config.js +144 -0
  184. package/components/ui/nuraly-ui/src/components/alert/README.md +236 -0
  185. package/components/ui/nuraly-ui/src/components/alert/alert.component.ts +225 -0
  186. package/components/ui/nuraly-ui/src/components/alert/alert.stories.ts +466 -0
  187. package/components/ui/nuraly-ui/src/components/alert/alert.style.ts +192 -0
  188. package/components/ui/nuraly-ui/src/components/alert/alert.types.ts +57 -0
  189. package/components/ui/nuraly-ui/src/components/alert/index.ts +8 -0
  190. package/components/ui/nuraly-ui/src/components/alert/react.ts +17 -0
  191. package/components/ui/nuraly-ui/src/components/badge/README.md +319 -0
  192. package/components/ui/nuraly-ui/src/components/badge/badge.component.ts +314 -0
  193. package/components/ui/nuraly-ui/src/components/badge/badge.stories.ts +582 -0
  194. package/components/ui/nuraly-ui/src/components/badge/badge.style.ts +250 -0
  195. package/components/ui/nuraly-ui/src/components/badge/badge.types.ts +100 -0
  196. package/components/ui/nuraly-ui/src/components/badge/index.ts +1 -0
  197. package/components/ui/nuraly-ui/src/components/badge/react.ts +9 -0
  198. package/components/ui/nuraly-ui/src/components/breadcrumb/README.md +243 -0
  199. package/components/ui/nuraly-ui/src/components/breadcrumb/breadcrumb.component.ts +280 -0
  200. package/components/ui/nuraly-ui/src/components/breadcrumb/breadcrumb.stories.ts +389 -0
  201. package/components/ui/nuraly-ui/src/components/breadcrumb/breadcrumb.style.ts +154 -0
  202. package/components/ui/nuraly-ui/src/components/breadcrumb/breadcrumb.types.ts +66 -0
  203. package/components/ui/nuraly-ui/src/components/breadcrumb/index.ts +1 -0
  204. package/components/ui/nuraly-ui/src/components/breadcrumb/react.ts +11 -0
  205. package/components/ui/nuraly-ui/src/components/button/README.md +331 -0
  206. package/components/ui/nuraly-ui/src/components/button/button.component.ts +317 -0
  207. package/components/ui/nuraly-ui/src/components/button/button.stories.ts +861 -0
  208. package/components/ui/nuraly-ui/src/components/button/button.style.ts +520 -0
  209. package/components/ui/nuraly-ui/src/components/button/button.types.ts +68 -0
  210. package/components/ui/nuraly-ui/src/components/button/controllers/base.controller.ts +99 -0
  211. package/components/ui/nuraly-ui/src/components/button/controllers/index.ts +10 -0
  212. package/components/ui/nuraly-ui/src/components/button/controllers/keyboard.controller.ts +89 -0
  213. package/components/ui/nuraly-ui/src/components/button/controllers/link.controller.ts +86 -0
  214. package/components/ui/nuraly-ui/src/components/button/controllers/ripple.controller.ts +79 -0
  215. package/components/ui/nuraly-ui/src/components/button/index.ts +1 -0
  216. package/components/ui/nuraly-ui/src/components/button/interfaces/base-controller.interface.ts +67 -0
  217. package/components/ui/nuraly-ui/src/components/button/interfaces/index.ts +1 -0
  218. package/components/ui/nuraly-ui/src/components/button/react.ts +11 -0
  219. package/components/ui/nuraly-ui/src/components/button/test/nr-button_test.ts +90 -0
  220. package/components/ui/nuraly-ui/src/components/canvas/canvas.component.ts +306 -0
  221. package/components/ui/nuraly-ui/src/components/canvas/demo/canvas-demo.ts +18 -0
  222. package/components/ui/nuraly-ui/src/components/canvas/index.ts +1 -0
  223. package/components/ui/nuraly-ui/src/components/canvas/react.ts +13 -0
  224. package/components/ui/nuraly-ui/src/components/card/card.component.ts +50 -0
  225. package/components/ui/nuraly-ui/src/components/card/card.stories.ts +360 -0
  226. package/components/ui/nuraly-ui/src/components/card/card.style.ts +62 -0
  227. package/components/ui/nuraly-ui/src/components/card/card.types.ts +17 -0
  228. package/components/ui/nuraly-ui/src/components/card/index.ts +2 -0
  229. package/components/ui/nuraly-ui/src/components/card/react.ts +12 -0
  230. package/components/ui/nuraly-ui/src/components/carousel/carousel.component.ts +116 -0
  231. package/components/ui/nuraly-ui/src/components/carousel/carousel.style.ts +69 -0
  232. package/components/ui/nuraly-ui/src/components/carousel/demo/carousel-demo.ts +59 -0
  233. package/components/ui/nuraly-ui/src/components/carousel/index.ts +1 -0
  234. package/components/ui/nuraly-ui/src/components/carousel/react.ts +12 -0
  235. package/components/ui/nuraly-ui/src/components/chatbot/README.md +527 -0
  236. package/components/ui/nuraly-ui/src/components/chatbot/chatbot.component.ts +730 -0
  237. package/components/ui/nuraly-ui/src/components/chatbot/chatbot.stories.ts +2549 -0
  238. package/components/ui/nuraly-ui/src/components/chatbot/chatbot.style.ts +1272 -0
  239. package/components/ui/nuraly-ui/src/components/chatbot/chatbot.types.ts +269 -0
  240. package/components/ui/nuraly-ui/src/components/chatbot/controllers/index.ts +9 -0
  241. package/components/ui/nuraly-ui/src/components/chatbot/controllers/scroll.controller.ts +59 -0
  242. package/components/ui/nuraly-ui/src/components/chatbot/core/README.md +550 -0
  243. package/components/ui/nuraly-ui/src/components/chatbot/core/chatbot-core.controller.ts +918 -0
  244. package/components/ui/nuraly-ui/src/components/chatbot/core/event-bus.ts +104 -0
  245. package/components/ui/nuraly-ui/src/components/chatbot/core/handlers/file-handler.ts +79 -0
  246. package/components/ui/nuraly-ui/src/components/chatbot/core/handlers/index.ts +12 -0
  247. package/components/ui/nuraly-ui/src/components/chatbot/core/handlers/message-handler.ts +117 -0
  248. package/components/ui/nuraly-ui/src/components/chatbot/core/handlers/module-handler.ts +49 -0
  249. package/components/ui/nuraly-ui/src/components/chatbot/core/handlers/state-handler.ts +152 -0
  250. package/components/ui/nuraly-ui/src/components/chatbot/core/handlers/suggestion-handler.ts +38 -0
  251. package/components/ui/nuraly-ui/src/components/chatbot/core/handlers/thread-handler.ts +153 -0
  252. package/components/ui/nuraly-ui/src/components/chatbot/core/index.ts +47 -0
  253. package/components/ui/nuraly-ui/src/components/chatbot/core/services/index.ts +11 -0
  254. package/components/ui/nuraly-ui/src/components/chatbot/core/services/localization.service.ts +20 -0
  255. package/components/ui/nuraly-ui/src/components/chatbot/core/services/plugin.service.ts +103 -0
  256. package/components/ui/nuraly-ui/src/components/chatbot/core/services/provider.service.ts +342 -0
  257. package/components/ui/nuraly-ui/src/components/chatbot/core/services/storage.service.ts +122 -0
  258. package/components/ui/nuraly-ui/src/components/chatbot/core/services/validation.service.ts +107 -0
  259. package/components/ui/nuraly-ui/src/components/chatbot/core/types.ts +456 -0
  260. package/components/ui/nuraly-ui/src/components/chatbot/file-upload-validation.stories.ts +278 -0
  261. package/components/ui/nuraly-ui/src/components/chatbot/index.ts +27 -0
  262. package/components/ui/nuraly-ui/src/components/chatbot/locales/generated/ar.ts +19 -0
  263. package/components/ui/nuraly-ui/src/components/chatbot/locales/generated/fr.ts +19 -0
  264. package/components/ui/nuraly-ui/src/components/chatbot/locales/locale-codes.ts +25 -0
  265. package/components/ui/nuraly-ui/src/components/chatbot/plugins/analytics-plugin.ts +63 -0
  266. package/components/ui/nuraly-ui/src/components/chatbot/plugins/chat-plugin.ts +76 -0
  267. package/components/ui/nuraly-ui/src/components/chatbot/plugins/flight-card-plugin.ts +636 -0
  268. package/components/ui/nuraly-ui/src/components/chatbot/plugins/flight-card.stories.ts +929 -0
  269. package/components/ui/nuraly-ui/src/components/chatbot/plugins/index.ts +14 -0
  270. package/components/ui/nuraly-ui/src/components/chatbot/plugins/markdown-plugin.stories.ts +155 -0
  271. package/components/ui/nuraly-ui/src/components/chatbot/plugins/markdown-plugin.ts +103 -0
  272. package/components/ui/nuraly-ui/src/components/chatbot/plugins/persistence-plugin.ts +97 -0
  273. package/components/ui/nuraly-ui/src/components/chatbot/plugins/print-job-card-plugin.ts +537 -0
  274. package/components/ui/nuraly-ui/src/components/chatbot/plugins/print-job-card.stories.ts +649 -0
  275. package/components/ui/nuraly-ui/src/components/chatbot/providers/custom-api-provider.ts +239 -0
  276. package/components/ui/nuraly-ui/src/components/chatbot/providers/index.ts +11 -0
  277. package/components/ui/nuraly-ui/src/components/chatbot/providers/mock-provider.ts +433 -0
  278. package/components/ui/nuraly-ui/src/components/chatbot/providers/openai-provider.ts +239 -0
  279. package/components/ui/nuraly-ui/src/components/chatbot/react.ts +57 -0
  280. package/components/ui/nuraly-ui/src/components/chatbot/storage/index.ts +8 -0
  281. package/components/ui/nuraly-ui/src/components/chatbot/storage/storage-implementations.ts +167 -0
  282. package/components/ui/nuraly-ui/src/components/chatbot/templates/chatbot-main.template.ts +157 -0
  283. package/components/ui/nuraly-ui/src/components/chatbot/templates/file-preview-modal.template.ts +90 -0
  284. package/components/ui/nuraly-ui/src/components/chatbot/templates/file-upload-area.template.ts +43 -0
  285. package/components/ui/nuraly-ui/src/components/chatbot/templates/index.ts +14 -0
  286. package/components/ui/nuraly-ui/src/components/chatbot/templates/input-box.template.ts +267 -0
  287. package/components/ui/nuraly-ui/src/components/chatbot/templates/message.template.ts +240 -0
  288. package/components/ui/nuraly-ui/src/components/chatbot/templates/suggestion.template.ts +57 -0
  289. package/components/ui/nuraly-ui/src/components/chatbot/templates/thread-sidebar.template.ts +67 -0
  290. package/components/ui/nuraly-ui/src/components/chatbot/templates/url-modal.template.ts +121 -0
  291. package/components/ui/nuraly-ui/src/components/checkbox/checkbox.component.ts +173 -0
  292. package/components/ui/nuraly-ui/src/components/checkbox/checkbox.stories.ts +521 -0
  293. package/components/ui/nuraly-ui/src/components/checkbox/checkbox.style.ts +324 -0
  294. package/components/ui/nuraly-ui/src/components/checkbox/checkbox.types.ts +5 -0
  295. package/components/ui/nuraly-ui/src/components/checkbox/index.ts +1 -0
  296. package/components/ui/nuraly-ui/src/components/checkbox/mixins/checkbox-event-mixin.ts +180 -0
  297. package/components/ui/nuraly-ui/src/components/checkbox/mixins/checkbox-focus-mixin.ts +99 -0
  298. package/components/ui/nuraly-ui/src/components/checkbox/mixins/index.ts +27 -0
  299. package/components/ui/nuraly-ui/src/components/checkbox/react.ts +12 -0
  300. package/components/ui/nuraly-ui/src/components/checkbox/test/checkbox_test.ts +97 -0
  301. package/components/ui/nuraly-ui/src/components/collapse/collapse.component.ts +315 -0
  302. package/components/ui/nuraly-ui/src/components/collapse/collapse.stories.ts +738 -0
  303. package/components/ui/nuraly-ui/src/components/collapse/collapse.style.ts +236 -0
  304. package/components/ui/nuraly-ui/src/components/collapse/collapse.type.ts +95 -0
  305. package/components/ui/nuraly-ui/src/components/collapse/controllers/accordion.controller.ts +169 -0
  306. package/components/ui/nuraly-ui/src/components/collapse/controllers/animation.controller.ts +129 -0
  307. package/components/ui/nuraly-ui/src/components/collapse/controllers/base.controller.ts +114 -0
  308. package/components/ui/nuraly-ui/src/components/collapse/controllers/index.ts +15 -0
  309. package/components/ui/nuraly-ui/src/components/collapse/controllers/keyboard.controller.ts +212 -0
  310. package/components/ui/nuraly-ui/src/components/collapse/index.ts +1 -0
  311. package/components/ui/nuraly-ui/src/components/collapse/react.ts +13 -0
  312. package/components/ui/nuraly-ui/src/components/colorpicker/color-holder.component.ts +104 -0
  313. package/components/ui/nuraly-ui/src/components/colorpicker/color-holder.style.ts +46 -0
  314. package/components/ui/nuraly-ui/src/components/colorpicker/color-picker.component.ts +398 -0
  315. package/components/ui/nuraly-ui/src/components/colorpicker/color-picker.stories.ts +888 -0
  316. package/components/ui/nuraly-ui/src/components/colorpicker/color-picker.style.ts +86 -0
  317. package/components/ui/nuraly-ui/src/components/colorpicker/color-picker.types.ts +64 -0
  318. package/components/ui/nuraly-ui/src/components/colorpicker/controllers/base.controller.ts +64 -0
  319. package/components/ui/nuraly-ui/src/components/colorpicker/controllers/dropdown.controller.ts +268 -0
  320. package/components/ui/nuraly-ui/src/components/colorpicker/controllers/event.controller.ts +147 -0
  321. package/components/ui/nuraly-ui/src/components/colorpicker/controllers/index.ts +3 -0
  322. package/components/ui/nuraly-ui/src/components/colorpicker/default-color-sets.component.ts +119 -0
  323. package/components/ui/nuraly-ui/src/components/colorpicker/default-color-sets.style.ts +35 -0
  324. package/components/ui/nuraly-ui/src/components/colorpicker/index.ts +2 -0
  325. package/components/ui/nuraly-ui/src/components/colorpicker/interfaces/index.ts +67 -0
  326. package/components/ui/nuraly-ui/src/components/colorpicker/react.ts +13 -0
  327. package/components/ui/nuraly-ui/src/components/console/react.ts +12 -0
  328. package/components/ui/nuraly-ui/src/components/datepicker/README.md +60 -0
  329. package/components/ui/nuraly-ui/src/components/datepicker/controllers/calendar.controller.ts +252 -0
  330. package/components/ui/nuraly-ui/src/components/datepicker/controllers/index.ts +11 -0
  331. package/components/ui/nuraly-ui/src/components/datepicker/controllers/keyboard.controller.ts +290 -0
  332. package/components/ui/nuraly-ui/src/components/datepicker/controllers/month-year-dropdown.controller.ts +108 -0
  333. package/components/ui/nuraly-ui/src/components/datepicker/controllers/positioning.controller.ts +278 -0
  334. package/components/ui/nuraly-ui/src/components/datepicker/controllers/selection.controller.ts +303 -0
  335. package/components/ui/nuraly-ui/src/components/datepicker/datepicker.component.ts +659 -0
  336. package/components/ui/nuraly-ui/src/components/datepicker/datepicker.constant.ts +81 -0
  337. package/components/ui/nuraly-ui/src/components/datepicker/datepicker.stories.ts +461 -0
  338. package/components/ui/nuraly-ui/src/components/datepicker/datepicker.style.ts +456 -0
  339. package/components/ui/nuraly-ui/src/components/datepicker/datepicker.style.variables.ts +119 -0
  340. package/components/ui/nuraly-ui/src/components/datepicker/datepicker.types.ts +154 -0
  341. package/components/ui/nuraly-ui/src/components/datepicker/index.ts +3 -0
  342. package/components/ui/nuraly-ui/src/components/datepicker/interfaces/base-controller.interface.ts +42 -0
  343. package/components/ui/nuraly-ui/src/components/datepicker/interfaces/datepicker-controllers.interface.ts +128 -0
  344. package/components/ui/nuraly-ui/src/components/datepicker/interfaces/index.ts +15 -0
  345. package/components/ui/nuraly-ui/src/components/datepicker/react.ts +24 -0
  346. package/components/ui/nuraly-ui/src/components/datepicker/templates/days.template.ts +57 -0
  347. package/components/ui/nuraly-ui/src/components/datepicker/templates/dropdown.template.ts +61 -0
  348. package/components/ui/nuraly-ui/src/components/datepicker/templates/headers.template.ts +7 -0
  349. package/components/ui/nuraly-ui/src/components/datepicker/templates/months.template.ts +16 -0
  350. package/components/ui/nuraly-ui/src/components/datepicker/templates/years.template.ts +18 -0
  351. package/components/ui/nuraly-ui/src/components/datepicker/test/datepicker_test.ts +124 -0
  352. package/components/ui/nuraly-ui/src/components/datepicker/utils/day.helper.ts +56 -0
  353. package/components/ui/nuraly-ui/src/components/datepicker/utils/formatter.ts +8 -0
  354. package/components/ui/nuraly-ui/src/components/datepicker/utils/index.ts +11 -0
  355. package/components/ui/nuraly-ui/src/components/datepicker/utils/locale.helper.ts +152 -0
  356. package/components/ui/nuraly-ui/src/components/datepicker/utils/month.helper.ts +26 -0
  357. package/components/ui/nuraly-ui/src/components/datepicker/utils/string.helper.ts +3 -0
  358. package/components/ui/nuraly-ui/src/components/divider/divider.component.ts +172 -0
  359. package/components/ui/nuraly-ui/src/components/divider/divider.stories.ts +271 -0
  360. package/components/ui/nuraly-ui/src/components/divider/divider.style.ts +139 -0
  361. package/components/ui/nuraly-ui/src/components/divider/divider.types.ts +59 -0
  362. package/components/ui/nuraly-ui/src/components/divider/index.ts +2 -0
  363. package/components/ui/nuraly-ui/src/components/divider/react.ts +9 -0
  364. package/components/ui/nuraly-ui/src/components/document/demo/document-demo.ts +28 -0
  365. package/components/ui/nuraly-ui/src/components/document/document.component.ts +133 -0
  366. package/components/ui/nuraly-ui/src/components/document/document.stories.ts +266 -0
  367. package/components/ui/nuraly-ui/src/components/document/document.style.ts +210 -0
  368. package/components/ui/nuraly-ui/src/components/document/document.types.ts +83 -0
  369. package/components/ui/nuraly-ui/src/components/document/index.ts +2 -0
  370. package/components/ui/nuraly-ui/src/components/document/react.ts +15 -0
  371. package/components/ui/nuraly-ui/src/components/dropdown/controllers/base.controller.ts +85 -0
  372. package/components/ui/nuraly-ui/src/components/dropdown/controllers/dropdown.controller.ts +476 -0
  373. package/components/ui/nuraly-ui/src/components/dropdown/controllers/index.ts +2 -0
  374. package/components/ui/nuraly-ui/src/components/dropdown/dropdown.component.ts +348 -0
  375. package/components/ui/nuraly-ui/src/components/dropdown/dropdown.stories.ts +1271 -0
  376. package/components/ui/nuraly-ui/src/components/dropdown/dropdown.style.ts +462 -0
  377. package/components/ui/nuraly-ui/src/components/dropdown/dropdown.types.ts +109 -0
  378. package/components/ui/nuraly-ui/src/components/dropdown/index.ts +2 -0
  379. package/components/ui/nuraly-ui/src/components/dropdown/interfaces/controller-interfaces.ts +98 -0
  380. package/components/ui/nuraly-ui/src/components/dropdown/interfaces/index.ts +1 -0
  381. package/components/ui/nuraly-ui/src/components/dropdown/react.ts +14 -0
  382. package/components/ui/nuraly-ui/src/components/dropdown/templates/nr-dropdown-item.style.ts +35 -0
  383. package/components/ui/nuraly-ui/src/components/dropdown/templates/nr-dropdown-item.ts +47 -0
  384. package/components/ui/nuraly-ui/src/components/dropdown/templates/nr-dropdown-menu.style.ts +50 -0
  385. package/components/ui/nuraly-ui/src/components/dropdown/templates/nr-dropdown-menu.ts +52 -0
  386. package/components/ui/nuraly-ui/src/components/file-upload/demo/file-upload-demo.ts +151 -0
  387. package/components/ui/nuraly-ui/src/components/file-upload/file-upload.component.ts +371 -0
  388. package/components/ui/nuraly-ui/src/components/file-upload/index.ts +1 -0
  389. package/components/ui/nuraly-ui/src/components/file-upload/react.ts +14 -0
  390. package/components/ui/nuraly-ui/src/components/file-upload/readme.md +98 -0
  391. package/components/ui/nuraly-ui/src/components/file-upload/styles.ts +284 -0
  392. package/components/ui/nuraly-ui/src/components/file-upload/types.ts +10 -0
  393. package/components/ui/nuraly-ui/src/components/file-upload/utils.ts +23 -0
  394. package/components/ui/nuraly-ui/src/components/flex/README.md +235 -0
  395. package/components/ui/nuraly-ui/src/components/flex/flex.component.ts +186 -0
  396. package/components/ui/nuraly-ui/src/components/flex/flex.stories.ts +486 -0
  397. package/components/ui/nuraly-ui/src/components/flex/flex.style.ts +101 -0
  398. package/components/ui/nuraly-ui/src/components/flex/flex.types.ts +70 -0
  399. package/components/ui/nuraly-ui/src/components/flex/index.ts +2 -0
  400. package/components/ui/nuraly-ui/src/components/flex/react.ts +9 -0
  401. package/components/ui/nuraly-ui/src/components/form/README.md +152 -0
  402. package/components/ui/nuraly-ui/src/components/form/controllers/submission.controller.ts +243 -0
  403. package/components/ui/nuraly-ui/src/components/form/controllers/validation.controller.ts +268 -0
  404. package/components/ui/nuraly-ui/src/components/form/form.component.ts +699 -0
  405. package/components/ui/nuraly-ui/src/components/form/form.stories.ts +794 -0
  406. package/components/ui/nuraly-ui/src/components/form/form.style.ts +69 -0
  407. package/components/ui/nuraly-ui/src/components/form/form.types.ts +104 -0
  408. package/components/ui/nuraly-ui/src/components/form/index.ts +15 -0
  409. package/components/ui/nuraly-ui/src/components/form/interfaces/validation.interface.ts +139 -0
  410. package/components/ui/nuraly-ui/src/components/grid/README.md +196 -0
  411. package/components/ui/nuraly-ui/src/components/grid/col.component.ts +262 -0
  412. package/components/ui/nuraly-ui/src/components/grid/col.style.ts +117 -0
  413. package/components/ui/nuraly-ui/src/components/grid/grid.stories.ts +442 -0
  414. package/components/ui/nuraly-ui/src/components/grid/grid.types.ts +89 -0
  415. package/components/ui/nuraly-ui/src/components/grid/index.ts +3 -0
  416. package/components/ui/nuraly-ui/src/components/grid/react.ts +16 -0
  417. package/components/ui/nuraly-ui/src/components/grid/row.component.ts +203 -0
  418. package/components/ui/nuraly-ui/src/components/grid/row.style.ts +68 -0
  419. package/components/ui/nuraly-ui/src/components/icon/icon.component.ts +219 -0
  420. package/components/ui/nuraly-ui/src/components/icon/icon.stories.ts +160 -0
  421. package/components/ui/nuraly-ui/src/components/icon/icon.style.ts +214 -0
  422. package/components/ui/nuraly-ui/src/components/icon/icon.types.ts +4 -0
  423. package/components/ui/nuraly-ui/src/components/icon/icon.variables.ts +132 -0
  424. package/components/ui/nuraly-ui/src/components/icon/index.ts +1 -0
  425. package/components/ui/nuraly-ui/src/components/icon/mixins/clickable-mixin.ts +154 -0
  426. package/components/ui/nuraly-ui/src/components/icon/mixins/index.ts +7 -0
  427. package/components/ui/nuraly-ui/src/components/icon/react.ts +8 -0
  428. package/components/ui/nuraly-ui/src/components/iconpicker/README.md +106 -0
  429. package/components/ui/nuraly-ui/src/components/iconpicker/controllers/event.controller.ts +94 -0
  430. package/components/ui/nuraly-ui/src/components/iconpicker/controllers/index.ts +9 -0
  431. package/components/ui/nuraly-ui/src/components/iconpicker/controllers/search.controller.ts +76 -0
  432. package/components/ui/nuraly-ui/src/components/iconpicker/controllers/selection.controller.ts +50 -0
  433. package/components/ui/nuraly-ui/src/components/iconpicker/icon-picker.component.ts +324 -0
  434. package/components/ui/nuraly-ui/src/components/iconpicker/icon-picker.constant.ts +33 -0
  435. package/components/ui/nuraly-ui/src/components/iconpicker/icon-picker.stories.ts +255 -0
  436. package/components/ui/nuraly-ui/src/components/iconpicker/icon-picker.style.ts +217 -0
  437. package/components/ui/nuraly-ui/src/components/iconpicker/icon-picker.types.ts +56 -0
  438. package/components/ui/nuraly-ui/src/components/iconpicker/index.ts +9 -0
  439. package/components/ui/nuraly-ui/src/components/iconpicker/interfaces/icon-picker.interface.ts +14 -0
  440. package/components/ui/nuraly-ui/src/components/iconpicker/interfaces/index.ts +7 -0
  441. package/components/ui/nuraly-ui/src/components/iconpicker/react.ts +22 -0
  442. package/components/ui/nuraly-ui/src/components/iconpicker/utils/icon-filter.utils.ts +119 -0
  443. package/components/ui/nuraly-ui/src/components/iconpicker/utils/icon-loader.utils.ts +129 -0
  444. package/components/ui/nuraly-ui/src/components/iconpicker/utils/index.ts +8 -0
  445. package/components/ui/nuraly-ui/src/components/iconpicker/utils/lucide-icons.ts +1624 -0
  446. package/components/ui/nuraly-ui/src/components/image/image.component.ts +136 -0
  447. package/components/ui/nuraly-ui/src/components/image/image.stories.ts +236 -0
  448. package/components/ui/nuraly-ui/src/components/image/image.style.ts +83 -0
  449. package/components/ui/nuraly-ui/src/components/image/image.types.ts +83 -0
  450. package/components/ui/nuraly-ui/src/components/image/index.ts +2 -0
  451. package/components/ui/nuraly-ui/src/components/image/react.ts +15 -0
  452. package/components/ui/nuraly-ui/src/components/input/README.md +432 -0
  453. package/components/ui/nuraly-ui/src/components/input/controllers/base.controller.ts +114 -0
  454. package/components/ui/nuraly-ui/src/components/input/controllers/event.controller.ts +421 -0
  455. package/components/ui/nuraly-ui/src/components/input/controllers/index.ts +32 -0
  456. package/components/ui/nuraly-ui/src/components/input/controllers/state.controller.ts +313 -0
  457. package/components/ui/nuraly-ui/src/components/input/controllers/validation.controller.ts +806 -0
  458. package/components/ui/nuraly-ui/src/components/input/index.ts +2 -0
  459. package/components/ui/nuraly-ui/src/components/input/input.component.ts +557 -0
  460. package/components/ui/nuraly-ui/src/components/input/input.stories.ts +1759 -0
  461. package/components/ui/nuraly-ui/src/components/input/input.style.ts +812 -0
  462. package/components/ui/nuraly-ui/src/components/input/input.types.ts +195 -0
  463. package/components/ui/nuraly-ui/src/components/input/mixins/focus-mixin.ts +112 -0
  464. package/components/ui/nuraly-ui/src/components/input/mixins/index.ts +14 -0
  465. package/components/ui/nuraly-ui/src/components/input/mixins/number-mixin.ts +167 -0
  466. package/components/ui/nuraly-ui/src/components/input/mixins/selection-mixin.ts +125 -0
  467. package/components/ui/nuraly-ui/src/components/input/react.ts +15 -0
  468. package/components/ui/nuraly-ui/src/components/input/test/nr-input_test.ts +163 -0
  469. package/components/ui/nuraly-ui/src/components/input/utils/index.ts +8 -0
  470. package/components/ui/nuraly-ui/src/components/input/utils/input-renderers.ts +217 -0
  471. package/components/ui/nuraly-ui/src/components/input/utils/input-validation.utils.ts +133 -0
  472. package/components/ui/nuraly-ui/src/components/input/validation.ts +3 -0
  473. package/components/ui/nuraly-ui/src/components/label/index.ts +1 -0
  474. package/components/ui/nuraly-ui/src/components/label/label.component.ts +52 -0
  475. package/components/ui/nuraly-ui/src/components/label/label.stories.ts +311 -0
  476. package/components/ui/nuraly-ui/src/components/label/label.style.ts +70 -0
  477. package/components/ui/nuraly-ui/src/components/label/label.style.variables.ts +35 -0
  478. package/components/ui/nuraly-ui/src/components/label/label.types.ts +48 -0
  479. package/components/ui/nuraly-ui/src/components/label/react.ts +11 -0
  480. package/components/ui/nuraly-ui/src/components/layout/README.md +200 -0
  481. package/components/ui/nuraly-ui/src/components/layout/content.component.ts +45 -0
  482. package/components/ui/nuraly-ui/src/components/layout/content.style.ts +17 -0
  483. package/components/ui/nuraly-ui/src/components/layout/footer.component.ts +54 -0
  484. package/components/ui/nuraly-ui/src/components/layout/footer.style.ts +17 -0
  485. package/components/ui/nuraly-ui/src/components/layout/header.component.ts +55 -0
  486. package/components/ui/nuraly-ui/src/components/layout/header.style.ts +19 -0
  487. package/components/ui/nuraly-ui/src/components/layout/index.ts +18 -0
  488. package/components/ui/nuraly-ui/src/components/layout/layout.component.ts +87 -0
  489. package/components/ui/nuraly-ui/src/components/layout/layout.stories.ts +616 -0
  490. package/components/ui/nuraly-ui/src/components/layout/layout.style.ts +23 -0
  491. package/components/ui/nuraly-ui/src/components/layout/layout.types.ts +90 -0
  492. package/components/ui/nuraly-ui/src/components/layout/react.ts +41 -0
  493. package/components/ui/nuraly-ui/src/components/layout/sider.component.ts +294 -0
  494. package/components/ui/nuraly-ui/src/components/layout/sider.style.ts +104 -0
  495. package/components/ui/nuraly-ui/src/components/menu/README.md +390 -0
  496. package/components/ui/nuraly-ui/src/components/menu/controllers/accessibility.controller.ts +257 -0
  497. package/components/ui/nuraly-ui/src/components/menu/controllers/base.controller.ts +123 -0
  498. package/components/ui/nuraly-ui/src/components/menu/controllers/index.ts +10 -0
  499. package/components/ui/nuraly-ui/src/components/menu/controllers/keyboard.controller.ts +360 -0
  500. package/components/ui/nuraly-ui/src/components/menu/controllers/state.controller.ts +268 -0
  501. package/components/ui/nuraly-ui/src/components/menu/index.ts +3 -0
  502. package/components/ui/nuraly-ui/src/components/menu/interfaces/controller.interface.ts +56 -0
  503. package/components/ui/nuraly-ui/src/components/menu/interfaces/index.ts +7 -0
  504. package/components/ui/nuraly-ui/src/components/menu/menu.component.ts +341 -0
  505. package/components/ui/nuraly-ui/src/components/menu/menu.constants.ts +12 -0
  506. package/components/ui/nuraly-ui/src/components/menu/menu.stories.ts +807 -0
  507. package/components/ui/nuraly-ui/src/components/menu/menu.style.ts +358 -0
  508. package/components/ui/nuraly-ui/src/components/menu/menu.types.ts +60 -0
  509. package/components/ui/nuraly-ui/src/components/menu/react.ts +11 -0
  510. package/components/ui/nuraly-ui/src/components/modal/controllers/index.ts +8 -0
  511. package/components/ui/nuraly-ui/src/components/modal/controllers/modal-drag-controller.ts +139 -0
  512. package/components/ui/nuraly-ui/src/components/modal/controllers/modal-keyboard-controller.ts +152 -0
  513. package/components/ui/nuraly-ui/src/components/modal/index.ts +10 -0
  514. package/components/ui/nuraly-ui/src/components/modal/modal-manager.ts +209 -0
  515. package/components/ui/nuraly-ui/src/components/modal/modal.component.ts +475 -0
  516. package/components/ui/nuraly-ui/src/components/modal/modal.stories.ts +823 -0
  517. package/components/ui/nuraly-ui/src/components/modal/modal.style.ts +369 -0
  518. package/components/ui/nuraly-ui/src/components/modal/modal.types.ts +148 -0
  519. package/components/ui/nuraly-ui/src/components/modal/react.ts +16 -0
  520. package/components/ui/nuraly-ui/src/components/panel/README.md +218 -0
  521. package/components/ui/nuraly-ui/src/components/panel/controllers/index.ts +8 -0
  522. package/components/ui/nuraly-ui/src/components/panel/controllers/panel-drag-controller.ts +151 -0
  523. package/components/ui/nuraly-ui/src/components/panel/controllers/panel-resize-controller.ts +153 -0
  524. package/components/ui/nuraly-ui/src/components/panel/index.ts +9 -0
  525. package/components/ui/nuraly-ui/src/components/panel/panel.component.ts +760 -0
  526. package/components/ui/nuraly-ui/src/components/panel/panel.stories.ts +978 -0
  527. package/components/ui/nuraly-ui/src/components/panel/panel.style.ts +499 -0
  528. package/components/ui/nuraly-ui/src/components/panel/panel.types.ts +89 -0
  529. package/components/ui/nuraly-ui/src/components/panel/react.ts +18 -0
  530. package/components/ui/nuraly-ui/src/components/popconfirm/README.md +403 -0
  531. package/components/ui/nuraly-ui/src/components/popconfirm/index.ts +2 -0
  532. package/components/ui/nuraly-ui/src/components/popconfirm/popconfirm.component.ts +336 -0
  533. package/components/ui/nuraly-ui/src/components/popconfirm/popconfirm.stories.ts +491 -0
  534. package/components/ui/nuraly-ui/src/components/popconfirm/popconfirm.style.ts +207 -0
  535. package/components/ui/nuraly-ui/src/components/popconfirm/popconfirm.types.ts +66 -0
  536. package/components/ui/nuraly-ui/src/components/popconfirm/react.ts +14 -0
  537. package/components/ui/nuraly-ui/src/components/radio/README.md +95 -0
  538. package/components/ui/nuraly-ui/src/components/radio/index.ts +2 -0
  539. package/components/ui/nuraly-ui/src/components/radio/radio.component.ts +186 -0
  540. package/components/ui/nuraly-ui/src/components/radio/radio.stories.ts +317 -0
  541. package/components/ui/nuraly-ui/src/components/radio/radio.style.ts +150 -0
  542. package/components/ui/nuraly-ui/src/components/radio/radio.types.ts +14 -0
  543. package/components/ui/nuraly-ui/src/components/radio/react.ts +20 -0
  544. package/components/ui/nuraly-ui/src/components/radio-group/controllers/focus.controller.ts +251 -0
  545. package/components/ui/nuraly-ui/src/components/radio-group/controllers/group.controller.ts +198 -0
  546. package/components/ui/nuraly-ui/src/components/radio-group/controllers/index.ts +11 -0
  547. package/components/ui/nuraly-ui/src/components/radio-group/controllers/keyboard.controller.ts +122 -0
  548. package/components/ui/nuraly-ui/src/components/radio-group/controllers/ripple.controller.ts +248 -0
  549. package/components/ui/nuraly-ui/src/components/radio-group/controllers/validation.controller.ts +189 -0
  550. package/components/ui/nuraly-ui/src/components/radio-group/index.ts +2 -0
  551. package/components/ui/nuraly-ui/src/components/radio-group/interfaces/base-controller.interface.ts +87 -0
  552. package/components/ui/nuraly-ui/src/components/radio-group/interfaces/focus-controller.interface.ts +45 -0
  553. package/components/ui/nuraly-ui/src/components/radio-group/interfaces/index.ts +14 -0
  554. package/components/ui/nuraly-ui/src/components/radio-group/interfaces/ripple-controller.interface.ts +35 -0
  555. package/components/ui/nuraly-ui/src/components/radio-group/interfaces/selection-controller.interface.ts +51 -0
  556. package/components/ui/nuraly-ui/src/components/radio-group/interfaces/validation-controller.interface.ts +53 -0
  557. package/components/ui/nuraly-ui/src/components/radio-group/radio-group.component.ts +426 -0
  558. package/components/ui/nuraly-ui/src/components/radio-group/radio-group.stories.ts +1334 -0
  559. package/components/ui/nuraly-ui/src/components/radio-group/radio-group.style.ts +248 -0
  560. package/components/ui/nuraly-ui/src/components/radio-group/radio-group.types.ts +43 -0
  561. package/components/ui/nuraly-ui/src/components/radio-group/radio.constant.ts +1 -0
  562. package/components/ui/nuraly-ui/src/components/radio-group/react.ts +18 -0
  563. package/components/ui/nuraly-ui/src/components/radio-group/test/radio_test.ts +87 -0
  564. package/components/ui/nuraly-ui/src/components/select/README.md +316 -0
  565. package/components/ui/nuraly-ui/src/components/select/controllers/base.controller.ts +93 -0
  566. package/components/ui/nuraly-ui/src/components/select/controllers/dropdown.controller.ts +415 -0
  567. package/components/ui/nuraly-ui/src/components/select/controllers/event.controller.ts +118 -0
  568. package/components/ui/nuraly-ui/src/components/select/controllers/focus.controller.ts +255 -0
  569. package/components/ui/nuraly-ui/src/components/select/controllers/index.ts +8 -0
  570. package/components/ui/nuraly-ui/src/components/select/controllers/keyboard.controller.ts +407 -0
  571. package/components/ui/nuraly-ui/src/components/select/controllers/search.controller.ts +187 -0
  572. package/components/ui/nuraly-ui/src/components/select/controllers/selection.controller.ts +238 -0
  573. package/components/ui/nuraly-ui/src/components/select/controllers/validation.controller.ts +236 -0
  574. package/components/ui/nuraly-ui/src/components/select/index.ts +36 -0
  575. package/components/ui/nuraly-ui/src/components/select/interfaces/base-controller.interface.ts +155 -0
  576. package/components/ui/nuraly-ui/src/components/select/interfaces/controller-interfaces.ts +105 -0
  577. package/components/ui/nuraly-ui/src/components/select/interfaces/index.ts +2 -0
  578. package/components/ui/nuraly-ui/src/components/select/react.ts +30 -0
  579. package/components/ui/nuraly-ui/src/components/select/select.component.ts +804 -0
  580. package/components/ui/nuraly-ui/src/components/select/select.constant.ts +142 -0
  581. package/components/ui/nuraly-ui/src/components/select/select.stories.ts +1653 -0
  582. package/components/ui/nuraly-ui/src/components/select/select.style.ts +593 -0
  583. package/components/ui/nuraly-ui/src/components/select/select.types.ts +120 -0
  584. package/components/ui/nuraly-ui/src/components/skeleton/README.md +373 -0
  585. package/components/ui/nuraly-ui/src/components/skeleton/index.ts +2 -0
  586. package/components/ui/nuraly-ui/src/components/skeleton/react.ts +10 -0
  587. package/components/ui/nuraly-ui/src/components/skeleton/skeleton.component.ts +385 -0
  588. package/components/ui/nuraly-ui/src/components/skeleton/skeleton.stories.ts +425 -0
  589. package/components/ui/nuraly-ui/src/components/skeleton/skeleton.style.ts +224 -0
  590. package/components/ui/nuraly-ui/src/components/skeleton/skeleton.types.ts +90 -0
  591. package/components/ui/nuraly-ui/src/components/slider-input/README.md +145 -0
  592. package/components/ui/nuraly-ui/src/components/slider-input/index.ts +2 -0
  593. package/components/ui/nuraly-ui/src/components/slider-input/react.ts +12 -0
  594. package/components/ui/nuraly-ui/src/components/slider-input/slider-input.component.ts +184 -0
  595. package/components/ui/nuraly-ui/src/components/slider-input/slider-input.stories.ts +361 -0
  596. package/components/ui/nuraly-ui/src/components/slider-input/slider-input.style.ts +171 -0
  597. package/components/ui/nuraly-ui/src/components/slider-input/slider-input.style.variables.ts +59 -0
  598. package/components/ui/nuraly-ui/src/components/slider-input/slider-input.types.ts +24 -0
  599. package/components/ui/nuraly-ui/src/components/slider-input/utils/debounce.ts +7 -0
  600. package/components/ui/nuraly-ui/src/components/slider-input/utils/index.ts +1 -0
  601. package/components/ui/nuraly-ui/src/components/table/controllers/base.controller.ts +99 -0
  602. package/components/ui/nuraly-ui/src/components/table/controllers/filter.controller.ts +163 -0
  603. package/components/ui/nuraly-ui/src/components/table/controllers/index.ts +11 -0
  604. package/components/ui/nuraly-ui/src/components/table/controllers/pagination.controller.ts +83 -0
  605. package/components/ui/nuraly-ui/src/components/table/controllers/selection.controller.ts +143 -0
  606. package/components/ui/nuraly-ui/src/components/table/controllers/sort.controller.ts +115 -0
  607. package/components/ui/nuraly-ui/src/components/table/index.ts +1 -0
  608. package/components/ui/nuraly-ui/src/components/table/interfaces/index.ts +7 -0
  609. package/components/ui/nuraly-ui/src/components/table/interfaces/table-host.interface.ts +53 -0
  610. package/components/ui/nuraly-ui/src/components/table/react.ts +14 -0
  611. package/components/ui/nuraly-ui/src/components/table/table.component.ts +344 -0
  612. package/components/ui/nuraly-ui/src/components/table/table.stories.ts +1072 -0
  613. package/components/ui/nuraly-ui/src/components/table/table.style.ts +689 -0
  614. package/components/ui/nuraly-ui/src/components/table/table.types.ts +91 -0
  615. package/components/ui/nuraly-ui/src/components/table/templates/actions.template.ts +22 -0
  616. package/components/ui/nuraly-ui/src/components/table/templates/column-filter.template.ts +88 -0
  617. package/components/ui/nuraly-ui/src/components/table/templates/content.template.ts +257 -0
  618. package/components/ui/nuraly-ui/src/components/table/templates/empty.template.ts +49 -0
  619. package/components/ui/nuraly-ui/src/components/table/templates/filter.template.ts +35 -0
  620. package/components/ui/nuraly-ui/src/components/table/templates/index.ts +7 -0
  621. package/components/ui/nuraly-ui/src/components/table/templates/loading.template.ts +56 -0
  622. package/components/ui/nuraly-ui/src/components/table/templates/pagination.template.ts +70 -0
  623. package/components/ui/nuraly-ui/src/components/tabs/controllers/base.controller.ts +136 -0
  624. package/components/ui/nuraly-ui/src/components/tabs/controllers/dragdrop.controller.ts +251 -0
  625. package/components/ui/nuraly-ui/src/components/tabs/controllers/editable.controller.ts +292 -0
  626. package/components/ui/nuraly-ui/src/components/tabs/controllers/event.controller.ts +294 -0
  627. package/components/ui/nuraly-ui/src/components/tabs/controllers/index.ts +42 -0
  628. package/components/ui/nuraly-ui/src/components/tabs/controllers/keyboard.controller.ts +276 -0
  629. package/components/ui/nuraly-ui/src/components/tabs/controllers/popout.controller.ts +516 -0
  630. package/components/ui/nuraly-ui/src/components/tabs/index.ts +11 -0
  631. package/components/ui/nuraly-ui/src/components/tabs/react.ts +52 -0
  632. package/components/ui/nuraly-ui/src/components/tabs/tabs.component.ts +499 -0
  633. package/components/ui/nuraly-ui/src/components/tabs/tabs.constant.ts +30 -0
  634. package/components/ui/nuraly-ui/src/components/tabs/tabs.stories.ts +1334 -0
  635. package/components/ui/nuraly-ui/src/components/tabs/tabs.style.ts +569 -0
  636. package/components/ui/nuraly-ui/src/components/tabs/tabs.types.ts +261 -0
  637. package/components/ui/nuraly-ui/src/components/tag/README.md +22 -0
  638. package/components/ui/nuraly-ui/src/components/tag/index.ts +1 -0
  639. package/components/ui/nuraly-ui/src/components/tag/react.ts +13 -0
  640. package/components/ui/nuraly-ui/src/components/tag/tag.component.ts +167 -0
  641. package/components/ui/nuraly-ui/src/components/tag/tag.stories.ts +50 -0
  642. package/components/ui/nuraly-ui/src/components/tag/tag.style.ts +89 -0
  643. package/components/ui/nuraly-ui/src/components/tag/tag.types.ts +30 -0
  644. package/components/ui/nuraly-ui/src/components/textarea/README.md +314 -0
  645. package/components/ui/nuraly-ui/src/components/textarea/controllers/base.controller.ts +142 -0
  646. package/components/ui/nuraly-ui/src/components/textarea/controllers/event.controller.ts +484 -0
  647. package/components/ui/nuraly-ui/src/components/textarea/controllers/index.ts +16 -0
  648. package/components/ui/nuraly-ui/src/components/textarea/controllers/validation.controller.ts +347 -0
  649. package/components/ui/nuraly-ui/src/components/textarea/index.ts +19 -0
  650. package/components/ui/nuraly-ui/src/components/textarea/react.ts +16 -0
  651. package/components/ui/nuraly-ui/src/components/textarea/textarea.component.ts +716 -0
  652. package/components/ui/nuraly-ui/src/components/textarea/textarea.stories.ts +453 -0
  653. package/components/ui/nuraly-ui/src/components/textarea/textarea.style.ts +387 -0
  654. package/components/ui/nuraly-ui/src/components/textarea/textarea.types.ts +113 -0
  655. package/components/ui/nuraly-ui/src/components/timeline/README.md +340 -0
  656. package/components/ui/nuraly-ui/src/components/timeline/index.ts +1 -0
  657. package/components/ui/nuraly-ui/src/components/timeline/react.ts +9 -0
  658. package/components/ui/nuraly-ui/src/components/timeline/timeline.component.ts +235 -0
  659. package/components/ui/nuraly-ui/src/components/timeline/timeline.stories.ts +313 -0
  660. package/components/ui/nuraly-ui/src/components/timeline/timeline.style.ts +235 -0
  661. package/components/ui/nuraly-ui/src/components/timeline/timeline.types.ts +75 -0
  662. package/components/ui/nuraly-ui/src/components/timepicker/README.md +238 -0
  663. package/components/ui/nuraly-ui/src/components/timepicker/controllers/formatting.controller.ts +230 -0
  664. package/components/ui/nuraly-ui/src/components/timepicker/controllers/index.ts +9 -0
  665. package/components/ui/nuraly-ui/src/components/timepicker/controllers/selection.controller.ts +213 -0
  666. package/components/ui/nuraly-ui/src/components/timepicker/controllers/validation.controller.ts +240 -0
  667. package/components/ui/nuraly-ui/src/components/timepicker/index.ts +12 -0
  668. package/components/ui/nuraly-ui/src/components/timepicker/interfaces/timepicker.interface.ts +122 -0
  669. package/components/ui/nuraly-ui/src/components/timepicker/test/timepicker.test.ts +249 -0
  670. package/components/ui/nuraly-ui/src/components/timepicker/timepicker.component.ts +786 -0
  671. package/components/ui/nuraly-ui/src/components/timepicker/timepicker.constants.ts +94 -0
  672. package/components/ui/nuraly-ui/src/components/timepicker/timepicker.stories.ts +643 -0
  673. package/components/ui/nuraly-ui/src/components/timepicker/timepicker.style.ts +569 -0
  674. package/components/ui/nuraly-ui/src/components/timepicker/timepicker.style.variables.ts +122 -0
  675. package/components/ui/nuraly-ui/src/components/timepicker/timepicker.types.ts +183 -0
  676. package/components/ui/nuraly-ui/src/components/timepicker/utils/time.utils.ts +288 -0
  677. package/components/ui/nuraly-ui/src/components/toast/README.md +535 -0
  678. package/components/ui/nuraly-ui/src/components/toast/controllers/base.controller.ts +105 -0
  679. package/components/ui/nuraly-ui/src/components/toast/controllers/index.ts +8 -0
  680. package/components/ui/nuraly-ui/src/components/toast/index.ts +10 -0
  681. package/components/ui/nuraly-ui/src/components/toast/react.ts +19 -0
  682. package/components/ui/nuraly-ui/src/components/toast/toast.component.ts +394 -0
  683. package/components/ui/nuraly-ui/src/components/toast/toast.stories.ts +895 -0
  684. package/components/ui/nuraly-ui/src/components/toast/toast.style.ts +339 -0
  685. package/components/ui/nuraly-ui/src/components/toast/toast.types.ts +155 -0
  686. package/components/ui/nuraly-ui/src/components/tooltips/demo/tooltips-demo.ts +128 -0
  687. package/components/ui/nuraly-ui/src/components/tooltips/index.ts +1 -0
  688. package/components/ui/nuraly-ui/src/components/tooltips/react.ts +0 -0
  689. package/components/ui/nuraly-ui/src/components/tooltips/test/tooltips_test.ts +175 -0
  690. package/components/ui/nuraly-ui/src/components/tooltips/tooltips.component.ts +282 -0
  691. package/components/ui/nuraly-ui/src/components/tooltips/tooltips.constant.ts +15 -0
  692. package/components/ui/nuraly-ui/src/components/tooltips/tooltips.style.ts +103 -0
  693. package/components/ui/nuraly-ui/src/components/tooltips/tooltips.variables.ts +14 -0
  694. package/components/ui/nuraly-ui/src/components/video/index.ts +2 -0
  695. package/components/ui/nuraly-ui/src/components/video/react.ts +17 -0
  696. package/components/ui/nuraly-ui/src/components/video/video.component.ts +179 -0
  697. package/components/ui/nuraly-ui/src/components/video/video.stories.ts +289 -0
  698. package/components/ui/nuraly-ui/src/components/video/video.style.ts +124 -0
  699. package/components/ui/nuraly-ui/src/components/video/video.types.ts +102 -0
  700. package/components/ui/nuraly-ui/src/helpers/ThemeHandler.ts +68 -0
  701. package/components/ui/nuraly-ui/src/helpers/test.ts +8 -0
  702. package/components/ui/nuraly-ui/src/introduction.stories.ts +161 -0
  703. package/components/ui/nuraly-ui/src/shared/README.md +87 -0
  704. package/components/ui/nuraly-ui/src/shared/base-mixin.ts +48 -0
  705. package/components/ui/nuraly-ui/src/shared/constants.ts +0 -0
  706. package/components/ui/nuraly-ui/src/shared/controllers/dropdown.controller.ts +393 -0
  707. package/components/ui/nuraly-ui/src/shared/controllers/dropdown.interface.ts +39 -0
  708. package/components/ui/nuraly-ui/src/shared/controllers/index.ts +3 -0
  709. package/components/ui/nuraly-ui/src/shared/controllers/theme.controller.ts +158 -0
  710. package/components/ui/nuraly-ui/src/shared/dependency-mixin.ts +174 -0
  711. package/components/ui/nuraly-ui/src/shared/event-handler-mixin.ts +190 -0
  712. package/components/ui/nuraly-ui/src/shared/index.ts +20 -0
  713. package/components/ui/nuraly-ui/src/shared/theme-mixin.ts +227 -0
  714. package/components/ui/nuraly-ui/src/shared/themes/README.md +135 -0
  715. package/components/ui/nuraly-ui/src/shared/themes/editor/README.md +202 -0
  716. package/components/ui/nuraly-ui/src/shared/themes/editor.stories.ts +366 -0
  717. package/components/ui/nuraly-ui/src/shared/themes/index.ts +132 -0
  718. package/components/ui/nuraly-ui/src/shared/utils.ts +94 -0
  719. package/components/ui/nuraly-ui/src/shared/validation.types.ts +118 -0
  720. package/components/ui/nuraly-ui/tools/bump-versions.js +83 -0
  721. package/components/ui/nuraly-ui/web-dev-server.config.js +25 -0
  722. package/components/ui/nuraly-ui/web-test-runner.config.js +124 -0
  723. package/dist/CodeEditor-Ch2tv9BE.js +106211 -0
  724. package/dist/SmartAttributeHandler-hoSLpm1Y.js +153 -0
  725. package/dist/abap-B2diVmjb.js +1314 -0
  726. package/dist/apex-3NuJ-nsI.js +315 -0
  727. package/dist/assets/editor.worker-vBWydyGC.js +11 -0
  728. package/dist/assets/html.worker-BSmGlhXp.js +458 -0
  729. package/dist/assets/json.worker-Dqnoedz4.js +42 -0
  730. package/dist/assets/ts.worker-DyHHPhrh.js +37021 -0
  731. package/dist/azcli-XGXuUsMB.js +74 -0
  732. package/dist/bat-B8Vhm634.js +95 -0
  733. package/dist/bicep-Cc8X5S_k.js +108 -0
  734. package/dist/cameligo-Bo3wBh9T.js +168 -0
  735. package/dist/clojure-CPoQlpIK.js +754 -0
  736. package/dist/coffee-BxvTGz39.js +228 -0
  737. package/dist/cpp-5RpEV7vC.js +390 -0
  738. package/dist/csharp-slXXP3fo.js +320 -0
  739. package/dist/csp-B98p6-gH.js +57 -0
  740. package/dist/css-BDsDSAin.js +186 -0
  741. package/dist/cssMode-Bt2uK8XM.js +1446 -0
  742. package/dist/cypher-Dc4IMouD.js +262 -0
  743. package/dist/dart-LhvE3yD2.js +270 -0
  744. package/dist/dockerfile-CwzplJeZ.js +132 -0
  745. package/dist/ecl-DxW3FiJi.js +454 -0
  746. package/dist/elixir-BI40g7TU.js +489 -0
  747. package/dist/flow9-tR2v0bGz.js +141 -0
  748. package/dist/freemarker2-DNc2IxPf.js +643 -0
  749. package/dist/fsharp-BLAma0OT.js +210 -0
  750. package/dist/go-nYcD3y4Z.js +208 -0
  751. package/dist/graphql-Dp1cHWmP.js +141 -0
  752. package/dist/handlebars-CIbFckEw.js +391 -0
  753. package/dist/hcl-6NT8Kbna.js +177 -0
  754. package/dist/html-nRs_fneU.js +281 -0
  755. package/dist/htmlMode-BjehA1YF.js +1456 -0
  756. package/dist/ini-BZCOLrEc.js +68 -0
  757. package/dist/java-DAMcfJbX.js +221 -0
  758. package/dist/javascript-Bn0HduZA.js +75 -0
  759. package/dist/jsonMode-CfGfcJRX.js +1866 -0
  760. package/dist/julia-CQ46G71H.js +496 -0
  761. package/dist/kotlin-CEjVo_6E.js +245 -0
  762. package/dist/less-DreV99nP.js +168 -0
  763. package/dist/lexon-DBVJhqLb.js +151 -0
  764. package/dist/liquid-m4D_LCnC.js +238 -0
  765. package/dist/lua-Dcc_j6L-.js +157 -0
  766. package/dist/m3-B9SlZL4n.js +210 -0
  767. package/dist/markdown-CuGw9_MP.js +202 -0
  768. package/dist/mdx-CakMRbCr.js +171 -0
  769. package/dist/micro-app-entry-CI1Rupdh.js +17479 -0
  770. package/dist/micro-app.bundle.js +8 -0
  771. package/dist/mips-BUWqP-OH.js +194 -0
  772. package/dist/msdax-DtkouYCg.js +377 -0
  773. package/dist/mysql-IkAsWSmF.js +876 -0
  774. package/dist/objective-c-B2-ronfg.js +188 -0
  775. package/dist/pascal-Bsnz2eJA.js +245 -0
  776. package/dist/pascaligo-D_sMUn0Q.js +158 -0
  777. package/dist/perl-BPzHt9SS.js +599 -0
  778. package/dist/pgsql-DlTJB0PD.js +847 -0
  779. package/dist/php-Dmq5OjwK.js +471 -0
  780. package/dist/pla-HJcccrBy.js +131 -0
  781. package/dist/postiats-OQn6DKv-.js +544 -0
  782. package/dist/powerquery-DKaMYC8w.js +890 -0
  783. package/dist/powershell-DWeJHik1.js +233 -0
  784. package/dist/protobuf-CBn_IseU.js +422 -0
  785. package/dist/pug-BoRpCINl.js +393 -0
  786. package/dist/python-oJwaiPUY.js +259 -0
  787. package/dist/qsharp-4rGyVZOw.js +282 -0
  788. package/dist/r-DsgLhBOb.js +245 -0
  789. package/dist/razor-u_dd4rqc.js +512 -0
  790. package/dist/redis-B2fdL4Bg.js +298 -0
  791. package/dist/redshift-DoaeyCkH.js +806 -0
  792. package/dist/restructuredtext-D-6OFBY9.js +162 -0
  793. package/dist/ruby-D1DD6baV.js +444 -0
  794. package/dist/rust-DssUV39M.js +337 -0
  795. package/dist/sb-Dmb6tAdv.js +110 -0
  796. package/dist/scala-Co3ETaym.js +353 -0
  797. package/dist/scheme-CMrqXTty.js +114 -0
  798. package/dist/scss-DkGudv8Q.js +244 -0
  799. package/dist/shell-BHN2BI4L.js +224 -0
  800. package/dist/solidity-b-R-raGB.js +1351 -0
  801. package/dist/sophia-Y4GjyxNB.js +190 -0
  802. package/dist/sparql-CDAPZb88.js +193 -0
  803. package/dist/sql-DkkpPiUq.js +818 -0
  804. package/dist/st-CSPV91Ej.js +415 -0
  805. package/dist/style.css +1 -0
  806. package/dist/swift-DdSC5O48.js +315 -0
  807. package/dist/systemverilog-CI03XpAv.js +556 -0
  808. package/dist/tcl-B8DayMSI.js +232 -0
  809. package/dist/tsMode-DlZ38d3D.js +813 -0
  810. package/dist/twig-B1AUPVB_.js +323 -0
  811. package/dist/typescript-Bjs2N5Be.js +328 -0
  812. package/dist/vb-BIC7ccdG.js +364 -0
  813. package/dist/wgsl-Bv2xeo60.js +420 -0
  814. package/dist/xml-BCveATLl.js +95 -0
  815. package/dist/yaml-BfWQPJQi.js +184 -0
  816. package/handlers/compiler.ts +362 -0
  817. package/handlers/context-setup.ts +349 -0
  818. package/handlers/handler-executor.ts +348 -0
  819. package/handlers/index.ts +184 -0
  820. package/handlers/runtime-api/applications.ts +18 -0
  821. package/handlers/runtime-api/component-properties.ts +78 -0
  822. package/handlers/runtime-api/components.ts +63 -0
  823. package/handlers/runtime-api/editor.ts +29 -0
  824. package/handlers/runtime-api/functions.ts +42 -0
  825. package/handlers/runtime-api/index.ts +221 -0
  826. package/handlers/runtime-api/navigation.ts +52 -0
  827. package/handlers/runtime-api/pages.ts +45 -0
  828. package/handlers/runtime-api/storage.ts +95 -0
  829. package/handlers/runtime-api/toast.ts +108 -0
  830. package/handlers/runtime-api/variables.ts +400 -0
  831. package/index.ts +188 -0
  832. package/micro-app/README.md +565 -0
  833. package/micro-app/index.ts +29 -0
  834. package/micro-app/messaging/MicroAppMessageBus.ts +246 -0
  835. package/micro-app/state/MicroAppPageManager.ts +275 -0
  836. package/micro-app/state/MicroAppRuntimeContext.ts +423 -0
  837. package/micro-app/state/MicroAppStoreContext.ts +441 -0
  838. package/micro-app/state/SharedVariableRegistry.ts +187 -0
  839. package/micro-app/state/VariableScopeManager.ts +310 -0
  840. package/micro-app/utils/ComponentNamespaceManager.ts +88 -0
  841. package/micro-app-entry.ts +34 -0
  842. package/package.json +119 -0
  843. package/redux/actions/aitchat.ts +17 -0
  844. package/redux/actions/application/addPageToApplicationAction.ts +14 -0
  845. package/redux/actions/application/addTempApplication.ts +8 -0
  846. package/redux/actions/application/closeShareApplicationModalAction.ts +5 -0
  847. package/redux/actions/application/index.ts +20 -0
  848. package/redux/actions/application/loadApplicationPermissionAction.ts +10 -0
  849. package/redux/actions/application/resetPermissionMessage.ts +8 -0
  850. package/redux/actions/application/setApplication.ts +5 -0
  851. package/redux/actions/application/setApplicationPermissionAction.ts +6 -0
  852. package/redux/actions/application/setDefaultApplicationPageIfNotSet.ts +12 -0
  853. package/redux/actions/application/setPermissionMessage.ts +8 -0
  854. package/redux/actions/application/showCreateApplicationModalAction.ts +5 -0
  855. package/redux/actions/application/showShareApplicationModalAction.ts +5 -0
  856. package/redux/actions/application/updateApplication.ts +16 -0
  857. package/redux/actions/component/addComponentAction.ts +90 -0
  858. package/redux/actions/component/addComponentAsChildOf.ts +29 -0
  859. package/redux/actions/component/addComponentToCurrentPageAction.ts +32 -0
  860. package/redux/actions/component/copyComponentAction.ts +12 -0
  861. package/redux/actions/component/deleteComponentAction.ts +52 -0
  862. package/redux/actions/component/index.ts +22 -0
  863. package/redux/actions/component/moveDraggedComponent.ts +130 -0
  864. package/redux/actions/component/moveDraggedComponentInside.ts +64 -0
  865. package/redux/actions/component/moveDraggedComponentIntoCurrentPageRoot.ts +50 -0
  866. package/redux/actions/component/setCurrentComponentIdAction.ts +6 -0
  867. package/redux/actions/component/setDraggingComponentInfo.ts +14 -0
  868. package/redux/actions/component/setHoveredComponentAction.ts +5 -0
  869. package/redux/actions/component/setHoveredComponentIdAction.ts +5 -0
  870. package/redux/actions/component/update-component-name.ts +63 -0
  871. package/redux/actions/component/updateComponentAttributes.ts +192 -0
  872. package/redux/actions/component.ts +25 -0
  873. package/redux/actions/debug/index.ts +1 -0
  874. package/redux/actions/debug/store.ts +72 -0
  875. package/redux/actions/editor/closeCreateApplicationModalAction.ts +5 -0
  876. package/redux/actions/editor/closeEditorTab.ts +9 -0
  877. package/redux/actions/editor/index.ts +12 -0
  878. package/redux/actions/editor/openEditorTab.ts +12 -0
  879. package/redux/actions/editor/setCurrentEditorTab.ts +8 -0
  880. package/redux/actions/editor/setEnvirementMode.ts +8 -0
  881. package/redux/actions/environment.ts +5 -0
  882. package/redux/actions/index.ts +28 -0
  883. package/redux/actions/kernel/index.ts +1 -0
  884. package/redux/actions/kernel/set-property.ts +0 -0
  885. package/redux/actions/page/addPageAction.ts +7 -0
  886. package/redux/actions/page/deletePageAction.ts +13 -0
  887. package/redux/actions/page/index.ts +12 -0
  888. package/redux/actions/page/removeComponentToCurrentPageAction.ts +32 -0
  889. package/redux/actions/page/setContextMenuEvent.ts +5 -0
  890. package/redux/actions/page/setCurrentPageAction.ts +6 -0
  891. package/redux/actions/page/setCurrentPageViewPort.ts +5 -0
  892. package/redux/actions/page/setResizing.ts +5 -0
  893. package/redux/actions/page/setShowBorder.ts +5 -0
  894. package/redux/actions/page/updatePageAction.ts +20 -0
  895. package/redux/actions/page/updatePageInfo.ts +5 -0
  896. package/redux/actions/page/updatePageStyleAttributes.ts +13 -0
  897. package/redux/actions/page/updatePageZoom.ts +5 -0
  898. package/redux/handlers/aichat/create-chat.handler.ts +22 -0
  899. package/redux/handlers/api-urls.ts +8 -0
  900. package/redux/handlers/applications/handler.ts +78 -0
  901. package/redux/handlers/applications/index.ts +1 -0
  902. package/redux/handlers/components/add-component.handler.ts +30 -0
  903. package/redux/handlers/components/delete-component.handler.ts +21 -0
  904. package/redux/handlers/components/index.ts +6 -0
  905. package/redux/handlers/components/interfaces/add-component.request.ts +4 -0
  906. package/redux/handlers/components/interfaces/index.ts +2 -0
  907. package/redux/handlers/components/interfaces/update-component.reques.ts +3 -0
  908. package/redux/handlers/components/refresh-component.ts +25 -0
  909. package/redux/handlers/components/update-component.handler.ts +32 -0
  910. package/redux/handlers/components/validation-handler.ts +45 -0
  911. package/redux/handlers/functions/build-function-handler.ts +10 -0
  912. package/redux/handlers/functions/deploy-function-handler.ts +10 -0
  913. package/redux/handlers/functions/index.ts +13 -0
  914. package/redux/handlers/functions/invoke-function-handler.ts +13 -0
  915. package/redux/handlers/functions/load-functions-handler.ts +10 -0
  916. package/redux/handlers/functions/update-function-handler.ts +13 -0
  917. package/redux/handlers/index.ts +10 -0
  918. package/redux/handlers/pages/deletePageHandler.ts +23 -0
  919. package/redux/handlers/pages/handler.ts +59 -0
  920. package/redux/handlers/pages/index.ts +4 -0
  921. package/redux/handlers/pages/page.interface.ts +14 -0
  922. package/redux/handlers/pages/refresh-pages.ts +26 -0
  923. package/redux/handlers/providers/interface.ts +7 -0
  924. package/redux/index.ts +8 -0
  925. package/redux/store/actions/component.ts +9 -0
  926. package/redux/store/apps.ts +160 -0
  927. package/redux/store/component/component.interface.ts +90 -0
  928. package/redux/store/component/helper.ts +78 -0
  929. package/redux/store/component/index.ts +51 -0
  930. package/redux/store/component/runtime-store.ts +0 -0
  931. package/redux/store/component/store.ts +306 -0
  932. package/redux/store/context.ts +138 -0
  933. package/redux/store/debug.ts +28 -0
  934. package/redux/store/environment.ts +20 -0
  935. package/redux/store/index.ts +77 -0
  936. package/redux/store/interfaces/component.interfaces.ts +4 -0
  937. package/redux/store/page.ts +105 -0
  938. package/redux/store/provider.ts +24 -0
  939. package/redux/store/ssr/server-data.ts +4 -0
  940. package/redux/store/toast.ts +26 -0
  941. package/state/editor.ts +370 -0
  942. package/state/index.ts +27 -0
  943. package/state/runtime-context.ts +784 -0
  944. package/types/IRuntimeContext.ts +203 -0
  945. package/types/core.types.ts +28 -0
  946. package/types/database.types.ts +395 -0
  947. package/types/index.ts +7 -0
  948. package/utils/RuntimeContextHelpers.ts +454 -0
  949. package/utils/api-calls-utils.ts +9 -0
  950. package/utils/change-detection.ts +58 -0
  951. package/utils/clipboard-utils.ts +113 -0
  952. package/utils/constants.ts +2 -0
  953. package/utils/envirement.ts +2 -0
  954. package/utils/handler-security-rules.ts +153 -0
  955. package/utils/handler-validator.ts +447 -0
  956. package/utils/index.ts +67 -0
  957. package/utils/local-storage.ts +26 -0
  958. package/utils/logger.ts +90 -0
  959. package/utils/memoize.ts +15 -0
  960. package/utils/naming-generator.ts +6 -0
  961. package/utils/object.utils.ts +15 -0
  962. package/utils/performance-utils.ts +589 -0
  963. package/utils/randomness.ts +3 -0
  964. package/utils/register-components.ts +49 -0
  965. package/utils/render-util.ts +173 -0
  966. package/utils/runtime-helpers.ts +57 -0
  967. package/utils/styleUtil.ts +7 -0
  968. package/utils/time.ts +7 -0
  969. package/utils/validation-error-formatter.ts +11 -0
  970. package/vite.config.ts +83 -0
@@ -0,0 +1,2549 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2023 Nuraly, Laabidi Aymen
4
+ * SPDX-License-Identifier: MIT
5
+ */
6
+
7
+ import type { Meta, StoryObj } from '@storybook/web-components';
8
+ import { html } from 'lit';
9
+ import {
10
+ ChatbotMessage,
11
+ ChatbotSuggestion,
12
+ ChatbotSender,
13
+ ChatbotSize,
14
+ ChatbotVariant,
15
+ ChatbotLoadingType,
16
+ ChatbotModule,
17
+ ChatbotThread
18
+ } from './chatbot.types.js';
19
+ import { ChatbotFileType } from './chatbot.types.js';
20
+
21
+ // Import the core controller and providers
22
+ import { ChatbotCoreController } from './core/chatbot-core.controller.js';
23
+ import { MockProvider } from './providers/mock-provider.js';
24
+
25
+ // Import storage implementations
26
+ import { MemoryStorage, LocalStorageAdapter, IndexedDBStorage } from './storage/index.js';
27
+
28
+ // Note: Theme CSS is imported globally in .storybook/preview.ts
29
+ // No need to import themes here to avoid conflicts
30
+ import '../input/input.component.js';
31
+ import '../button/button.component.js';
32
+ import '../icon/icon.component.js';
33
+ import '../dropdown/dropdown.component.js';
34
+ import '../select/select.component.js';
35
+ import '../tag/tag.component.js';
36
+ import '../modal/modal.component.js';
37
+ import '../document/document.component.js';
38
+ import './chatbot.component.js';
39
+
40
+ const meta: Meta = {
41
+ title: 'Components/Chatbot',
42
+ component: 'nr-chatbot',
43
+ parameters: {
44
+ layout: 'centered',
45
+ docs: {
46
+ description: {
47
+ component: `
48
+ # Chatbot Component with Controller Architecture
49
+
50
+ A modern, controller-based chatbot component that separates UI from business logic.
51
+
52
+ ## Architecture
53
+
54
+ - **ChatbotCoreController**: Pure business logic, framework-agnostic
55
+ - **Providers**: Pluggable AI/API backends (OpenAI, Custom, Mock)
56
+ - **UI Component**: Lit-based web component that renders the chatbot
57
+
58
+ ## Basic Usage
59
+
60
+ \`\`\`javascript
61
+ import { ChatbotCoreController, MockProvider } from '@nuraly/chatbot';
62
+
63
+ // Create controller with provider
64
+ const controller = new ChatbotCoreController({
65
+ provider: new MockProvider(),
66
+ ui: {
67
+ onStateChange: (state) => {
68
+ chatbot.messages = state.messages;
69
+ }
70
+ }
71
+ });
72
+
73
+ // Attach to component
74
+ chatbot.controller = controller;
75
+ \`\`\`
76
+ `
77
+ }
78
+ }
79
+ },
80
+ argTypes: {
81
+ size: {
82
+ control: { type: 'select' },
83
+ options: Object.values(ChatbotSize),
84
+ description: 'Chatbot size variant'
85
+ },
86
+ variant: {
87
+ control: { type: 'select' },
88
+ options: Object.values(ChatbotVariant),
89
+ description: 'Chatbot visual variant'
90
+ },
91
+ loadingIndicator: {
92
+ control: { type: 'select' },
93
+ options: Object.values(ChatbotLoadingType),
94
+ description: 'Loading indicator type'
95
+ },
96
+ isRTL: {
97
+ control: { type: 'boolean' },
98
+ description: 'Right-to-left text direction'
99
+ },
100
+ disabled: {
101
+ control: { type: 'boolean' },
102
+ description: 'Disable input and interactions'
103
+ },
104
+ showSendButton: {
105
+ control: { type: 'boolean' },
106
+ description: 'Show send button'
107
+ },
108
+ autoScroll: {
109
+ control: { type: 'boolean' },
110
+ description: 'Auto-scroll to new messages'
111
+ },
112
+ showThreads: {
113
+ control: { type: 'boolean' },
114
+ description: 'Show thread sidebar'
115
+ },
116
+ boxed: {
117
+ control: { type: 'boolean' },
118
+ description: 'Enable boxed layout for large widths (ChatGPT-style)'
119
+ },
120
+ enableModuleSelection: {
121
+ control: { type: 'boolean' },
122
+ description: 'Enable module selection dropdown'
123
+ }
124
+ }
125
+ };
126
+
127
+ export default meta;
128
+ type Story = StoryObj;
129
+
130
+ // ===== SAMPLE DATA =====
131
+
132
+ const sampleSuggestions: ChatbotSuggestion[] = [
133
+ { id: 'sugg1', text: 'What can you help me with?', enabled: true },
134
+ { id: 'sugg2', text: 'Tell me about your features', enabled: true },
135
+ { id: 'sugg3', text: 'How do I get started?', enabled: true },
136
+ { id: 'sugg4', text: 'Show me an example', enabled: true }
137
+ ];
138
+
139
+ const sampleModules: ChatbotModule[] = [
140
+ {
141
+ id: 'web-search',
142
+ name: 'Web Search',
143
+ description: 'Search the web for information',
144
+ icon: 'search',
145
+ enabled: true
146
+ },
147
+ {
148
+ id: 'file-analysis',
149
+ name: 'File Analysis',
150
+ description: 'Analyze uploaded files',
151
+ icon: 'file-text',
152
+ enabled: true
153
+ },
154
+ {
155
+ id: 'code-generation',
156
+ name: 'Code Generation',
157
+ description: 'Generate code snippets',
158
+ icon: 'code',
159
+ enabled: true
160
+ }
161
+ ];
162
+
163
+ // ===== HELPER FUNCTIONS =====
164
+
165
+ /**
166
+ * Create a controller and sync it with a chatbot element
167
+ */
168
+ function createControllerForElement(element: any, providerConfig: any = {}) {
169
+ const controller = new ChatbotCoreController({
170
+ provider: new MockProvider(providerConfig),
171
+ ui: {
172
+ onStateChange: (state) => {
173
+ element.messages = state.messages;
174
+ element.threads = state.threads;
175
+ element.isBotTyping = state.isTyping;
176
+ element.chatStarted = state.messages.length > 0;
177
+ },
178
+ onTypingStart: () => {
179
+ element.isBotTyping = true;
180
+ },
181
+ onTypingEnd: () => {
182
+ element.isBotTyping = false;
183
+ }
184
+ }
185
+ });
186
+
187
+ return controller;
188
+ }
189
+
190
+ // ===== STORIES =====
191
+
192
+ /**
193
+ * Default chatbot with mock provider - Fully interactive!
194
+ * Try asking questions and see contextual responses.
195
+ */
196
+ export const Default: Story = {
197
+ args: {
198
+ size: ChatbotSize.Medium,
199
+ variant: ChatbotVariant.Default,
200
+ isRTL: false,
201
+ disabled: false,
202
+ showSendButton: true,
203
+ autoScroll: true,
204
+ showThreads: false,
205
+ boxed: false
206
+ },
207
+ render: (args) => {
208
+ setTimeout(() => {
209
+ const chatbot = document.querySelector('nr-chatbot') as any;
210
+ if (chatbot && !chatbot.controller) {
211
+ const controller = createControllerForElement(chatbot, {
212
+ delay: 600,
213
+ streaming: true,
214
+ streamingSpeed: 4,
215
+ streamingInterval: 25,
216
+ contextualResponses: true
217
+ });
218
+ chatbot.controller = controller;
219
+ chatbot.suggestions = sampleSuggestions;
220
+ }
221
+ }, 0);
222
+
223
+ return html`
224
+ <div style="width: 500px; height: 600px;">
225
+ <nr-chatbot
226
+ .size=${args.size}
227
+ .variant=${args.variant}
228
+ .isRTL=${args.isRTL}
229
+ .disabled=${args.disabled}
230
+ .showSendButton=${args.showSendButton}
231
+ .autoScroll=${args.autoScroll}
232
+ .showThreads=${args.showThreads}
233
+ .boxed=${args.boxed}
234
+ ></nr-chatbot>
235
+ </div>
236
+ `;
237
+ }
238
+ };
239
+
240
+ /**
241
+ * Chatbot with streaming responses
242
+ */
243
+ export const WithStreaming: Story = {
244
+ args: {
245
+ ...Default.args
246
+ },
247
+ render: (args) => {
248
+ setTimeout(() => {
249
+ const chatbot = document.querySelector('#streaming-chatbot') as any;
250
+ if (chatbot && !chatbot.controller) {
251
+ const controller = createControllerForElement(chatbot, {
252
+ delay: 500,
253
+ streaming: true,
254
+ streamingSpeed: 3,
255
+ streamingInterval: 30,
256
+ contextualResponses: true
257
+ });
258
+ chatbot.controller = controller;
259
+ chatbot.suggestions = sampleSuggestions;
260
+ }
261
+ }, 0);
262
+
263
+ return html`
264
+ <div style="width: 500px; height: 600px;">
265
+ <nr-chatbot
266
+ id="streaming-chatbot"
267
+ .size=${args.size}
268
+ .variant=${args.variant}
269
+ .isRTL=${args.isRTL}
270
+ .disabled=${args.disabled}
271
+ .showSendButton=${args.showSendButton}
272
+ .autoScroll=${args.autoScroll}
273
+ .showThreads=${args.showThreads}
274
+ .boxed=${args.boxed}
275
+ ></nr-chatbot>
276
+ </div>
277
+ `;
278
+ }
279
+ };
280
+
281
+ /**
282
+ * Chatbot with thread support - Create multiple conversations!
283
+ * Try creating new threads and switching between them.
284
+ */
285
+ export const WithThreads: Story = {
286
+ args: {
287
+ ...Default.args,
288
+ showThreads: true
289
+ },
290
+ render: (args) => {
291
+ setTimeout(() => {
292
+ const chatbot = document.querySelector('#threaded-chatbot') as any;
293
+ if (chatbot && !chatbot.controller) {
294
+ // Create controller with thread support enabled
295
+ const controller = new ChatbotCoreController({
296
+ provider: new MockProvider({
297
+ delay: 500,
298
+ streaming: true,
299
+ streamingSpeed: 5,
300
+ streamingInterval: 20,
301
+ contextualResponses: true
302
+ }),
303
+ enableThreads: true,
304
+ ui: {
305
+ onStateChange: (state) => {
306
+ chatbot.messages = state.messages;
307
+ chatbot.threads = state.threads;
308
+ chatbot.isBotTyping = state.isTyping;
309
+ chatbot.chatStarted = state.messages.length > 0;
310
+ },
311
+ onTypingStart: () => {
312
+ chatbot.isBotTyping = true;
313
+ },
314
+ onTypingEnd: () => {
315
+ chatbot.isBotTyping = false;
316
+ }
317
+ }
318
+ });
319
+
320
+ chatbot.controller = controller;
321
+ chatbot.suggestions = [
322
+ { id: 'thread1', text: 'Start a conversation about AI', enabled: true },
323
+ { id: 'thread2', text: 'Ask about programming', enabled: true },
324
+ { id: 'thread3', text: 'Create a new thread', enabled: true },
325
+ { id: 'thread4', text: 'Switch between threads', enabled: true }
326
+ ];
327
+ chatbot.enableThreadCreation = true;
328
+ }
329
+ }, 0);
330
+
331
+ return html`
332
+ <div style="width: 800px; height: 600px;">
333
+ <nr-chatbot
334
+ id="threaded-chatbot"
335
+ .size=${args.size}
336
+ .variant=${args.variant}
337
+ .isRTL=${args.isRTL}
338
+ .disabled=${args.disabled}
339
+ .showSendButton=${args.showSendButton}
340
+ .autoScroll=${args.autoScroll}
341
+ .showThreads=${args.showThreads}
342
+ .boxed=${args.boxed}
343
+ ></nr-chatbot>
344
+ </div>
345
+ `;
346
+ }
347
+ };
348
+
349
+ /**
350
+ * Chatbot with module selection - Select modules and chat!
351
+ * Try selecting different modules before sending messages.
352
+ */
353
+ export const WithModules: Story = {
354
+ args: {
355
+ ...Default.args,
356
+ enableModuleSelection: true
357
+ },
358
+ render: (args) => {
359
+ setTimeout(() => {
360
+ const chatbot = document.querySelector('#module-chatbot') as any;
361
+ if (chatbot && !chatbot.controller) {
362
+ const controller = createControllerForElement(chatbot, {
363
+ delay: 500,
364
+ streaming: true,
365
+ streamingSpeed: 5,
366
+ streamingInterval: 20,
367
+ contextualResponses: true
368
+ });
369
+
370
+ chatbot.controller = controller;
371
+ chatbot.suggestions = [
372
+ { id: 'mod1', text: 'Search the web for information', enabled: true },
373
+ { id: 'mod2', text: 'Analyze this file', enabled: true },
374
+ { id: 'mod3', text: 'Generate some code', enabled: true },
375
+ { id: 'mod4', text: 'What modules are available?', enabled: true }
376
+ ];
377
+ chatbot.modules = sampleModules;
378
+ chatbot.enableModuleSelection = true;
379
+ }
380
+ }, 0);
381
+
382
+ return html`
383
+ <div style="width: 500px; height: 600px;">
384
+ <nr-chatbot
385
+ id="module-chatbot"
386
+ .size=${args.size}
387
+ .variant=${args.variant}
388
+ .isRTL=${args.isRTL}
389
+ .disabled=${args.disabled}
390
+ .showSendButton=${args.showSendButton}
391
+ .autoScroll=${args.autoScroll}
392
+ .showThreads=${args.showThreads}
393
+ .boxed=${args.boxed}
394
+ ></nr-chatbot>
395
+ </div>
396
+ `;
397
+ }
398
+ };
399
+
400
+ /**
401
+ * Boxed layout (ChatGPT-style) - Full-screen interactive experience!
402
+ * Experience a ChatGPT-like interface with centered conversation.
403
+ */
404
+ export const BoxedLayout: Story = {
405
+ args: {
406
+ ...Default.args,
407
+ boxed: true
408
+ },
409
+ parameters: {
410
+ layout: 'fullscreen'
411
+ },
412
+ render: (args) => {
413
+ setTimeout(() => {
414
+ const chatbot = document.querySelector('#boxed-chatbot') as any;
415
+ if (chatbot && !chatbot.controller) {
416
+ const controller = createControllerForElement(chatbot, {
417
+ delay: 400,
418
+ streaming: true,
419
+ streamingSpeed: 6,
420
+ streamingInterval: 15,
421
+ contextualResponses: true
422
+ });
423
+ chatbot.controller = controller;
424
+ chatbot.suggestions = sampleSuggestions;
425
+ }
426
+ }, 0);
427
+
428
+ return html`
429
+ <div style="width: 100vw; height: 100vh; background: var(--nr-color-background, #f5f5f5);">
430
+ <nr-chatbot
431
+ id="boxed-chatbot"
432
+ .size=${args.size}
433
+ .variant=${args.variant}
434
+ .isRTL=${args.isRTL}
435
+ .disabled=${args.disabled}
436
+ .showSendButton=${args.showSendButton}
437
+ .autoScroll=${args.autoScroll}
438
+ .showThreads=${args.showThreads}
439
+ .boxed=${args.boxed}
440
+ ></nr-chatbot>
441
+ </div>
442
+ `;
443
+ }
444
+ };
445
+
446
+ /**
447
+ * Interactive demo with initial messages
448
+ */
449
+ export const WithInitialMessages: Story = {
450
+ args: {
451
+ ...Default.args
452
+ },
453
+ render: (args) => {
454
+ const initialMessages: ChatbotMessage[] = [
455
+ {
456
+ id: 'welcome-1',
457
+ sender: ChatbotSender.Bot,
458
+ text: 'Hello! 👋 Welcome to the chatbot demo. I\'m powered by a mock provider that simulates realistic conversations.',
459
+ timestamp: new Date().toISOString(),
460
+ introduction: true
461
+ },
462
+ {
463
+ id: 'welcome-2',
464
+ sender: ChatbotSender.Bot,
465
+ text: 'Try asking me questions! I can respond contextually to greetings, questions about features, and more.',
466
+ timestamp: new Date().toISOString()
467
+ }
468
+ ];
469
+
470
+ setTimeout(() => {
471
+ const chatbot = document.querySelector('#initial-messages-chatbot') as any;
472
+ if (chatbot && !chatbot.controller) {
473
+ const controller = new ChatbotCoreController({
474
+ provider: new MockProvider({
475
+ delay: 600,
476
+ streaming: true,
477
+ streamingSpeed: 4,
478
+ streamingInterval: 25,
479
+ contextualResponses: true
480
+ }),
481
+ initialMessages,
482
+ ui: {
483
+ onStateChange: (state) => {
484
+ chatbot.messages = state.messages;
485
+ chatbot.isBotTyping = state.isTyping;
486
+ chatbot.chatStarted = state.messages.length > 0;
487
+ }
488
+ }
489
+ });
490
+
491
+ chatbot.controller = controller;
492
+ chatbot.suggestions = sampleSuggestions;
493
+ }
494
+ }, 0);
495
+
496
+ return html`
497
+ <div style="width: 500px; height: 600px;">
498
+ <nr-chatbot
499
+ id="initial-messages-chatbot"
500
+ .size=${args.size}
501
+ .variant=${args.variant}
502
+ .isRTL=${args.isRTL}
503
+ .disabled=${args.disabled}
504
+ .showSendButton=${args.showSendButton}
505
+ .autoScroll=${args.autoScroll}
506
+ .showThreads=${args.showThreads}
507
+ .boxed=${args.boxed}
508
+ ></nr-chatbot>
509
+ </div>
510
+ `;
511
+ }
512
+ };
513
+
514
+ /**
515
+ * RTL (Right-to-Left) layout demo - Interactive Arabic interface!
516
+ * Try the Arabic suggestions or type your own messages.
517
+ */
518
+ export const RTLLayout: Story = {
519
+ args: {
520
+ ...Default.args,
521
+ isRTL: true
522
+ },
523
+ render: (args) => {
524
+ setTimeout(() => {
525
+ const chatbot = document.querySelector('#rtl-chatbot') as any;
526
+ if (chatbot && !chatbot.controller) {
527
+ const controller = createControllerForElement(chatbot, {
528
+ delay: 500,
529
+ streaming: true,
530
+ streamingSpeed: 3,
531
+ streamingInterval: 30,
532
+ contextualResponses: true
533
+ });
534
+ chatbot.controller = controller;
535
+ chatbot.suggestions = [
536
+ { id: 'rtl1', text: 'مرحبا كيف حالك؟', enabled: true },
537
+ { id: 'rtl2', text: 'ما هي الميزات المتاحة؟', enabled: true },
538
+ { id: 'rtl3', text: 'كيف يمكنني البدء؟', enabled: true },
539
+ { id: 'rtl4', text: 'أخبرني عن نفسك', enabled: true }
540
+ ];
541
+ }
542
+ }, 0);
543
+
544
+ return html`
545
+ <div style="width: 500px; height: 600px;">
546
+ <nr-chatbot
547
+ id="rtl-chatbot"
548
+ .size=${args.size}
549
+ .variant=${args.variant}
550
+ .isRTL=${args.isRTL}
551
+ .disabled=${args.disabled}
552
+ .showSendButton=${args.showSendButton}
553
+ .autoScroll=${args.autoScroll}
554
+ .showThreads=${args.showThreads}
555
+ .boxed=${args.boxed}
556
+ ></nr-chatbot>
557
+ </div>
558
+ `;
559
+ }
560
+ };
561
+
562
+ /**
563
+ * Different size variants - All fully interactive!
564
+ */
565
+ export const SizeVariants: Story = {
566
+ render: () => {
567
+ ['small', 'medium', 'large'].forEach((size) => {
568
+ setTimeout(() => {
569
+ const chatbot = document.querySelector(`#chatbot-${size}`) as any;
570
+ if (chatbot && !chatbot.controller) {
571
+ const controller = createControllerForElement(chatbot, {
572
+ delay: 500,
573
+ streaming: true,
574
+ streamingSpeed: 4,
575
+ streamingInterval: 25,
576
+ contextualResponses: true
577
+ });
578
+ chatbot.controller = controller;
579
+ chatbot.suggestions = sampleSuggestions;
580
+ }
581
+ }, 0);
582
+ });
583
+
584
+ return html`
585
+ <div style="display: flex; gap: 20px; flex-wrap: wrap;">
586
+ <div style="flex: 1; min-width: 300px;">
587
+ <h3>Small</h3>
588
+ <div style="width: 100%; height: 400px;">
589
+ <nr-chatbot
590
+ id="chatbot-small"
591
+ .size=${ChatbotSize.Small}
592
+ ></nr-chatbot>
593
+ </div>
594
+ </div>
595
+ <div style="flex: 1; min-width: 300px;">
596
+ <h3>Medium</h3>
597
+ <div style="width: 100%; height: 500px;">
598
+ <nr-chatbot
599
+ id="chatbot-medium"
600
+ .size=${ChatbotSize.Medium}
601
+ ></nr-chatbot>
602
+ </div>
603
+ </div>
604
+ <div style="flex: 1; min-width: 300px;">
605
+ <h3>Large</h3>
606
+ <div style="width: 100%; height: 600px;">
607
+ <nr-chatbot
608
+ id="chatbot-large"
609
+ .size=${ChatbotSize.Large}
610
+ ></nr-chatbot>
611
+ </div>
612
+ </div>
613
+ </div>
614
+ `;
615
+ }
616
+ };
617
+
618
+ /**
619
+ * Custom provider configuration demo
620
+ */
621
+ export const CustomConfiguration: Story = {
622
+ args: {
623
+ ...Default.args
624
+ },
625
+ render: (args) => {
626
+ setTimeout(() => {
627
+ const chatbot = document.querySelector('#custom-config-chatbot') as any;
628
+ if (chatbot && !chatbot.controller) {
629
+ // Create controller with custom mock responses
630
+ const controller = new ChatbotCoreController({
631
+ provider: new MockProvider({
632
+ delay: 400,
633
+ streaming: true,
634
+ streamingSpeed: 6,
635
+ streamingInterval: 20,
636
+ contextualResponses: true,
637
+ customResponses: [
638
+ "That's a great question! Let me provide you with a detailed answer...",
639
+ "I understand your concern. Here's what I can tell you:",
640
+ "Based on my knowledge, I would recommend the following approach:",
641
+ "Excellent point! This is an important topic to discuss.",
642
+ "Let me break this down for you in a simple way:"
643
+ ]
644
+ }),
645
+ ui: {
646
+ onStateChange: (state) => {
647
+ chatbot.messages = state.messages;
648
+ chatbot.isBotTyping = state.isTyping;
649
+ chatbot.chatStarted = state.messages.length > 0;
650
+ },
651
+ showNotification: (message, type) => {
652
+ console.log(`[${type.toUpperCase()}]`, message);
653
+ }
654
+ }
655
+ });
656
+
657
+ chatbot.controller = controller;
658
+ chatbot.suggestions = sampleSuggestions;
659
+ }
660
+ }, 0);
661
+
662
+ return html`
663
+ <div style="width: 500px; height: 600px;">
664
+ <nr-chatbot
665
+ id="custom-config-chatbot"
666
+ .size=${args.size}
667
+ .variant=${args.variant}
668
+ .isRTL=${args.isRTL}
669
+ .disabled=${args.disabled}
670
+ .showSendButton=${args.showSendButton}
671
+ .autoScroll=${args.autoScroll}
672
+ .showThreads=${args.showThreads}
673
+ .boxed=${args.boxed}
674
+ ></nr-chatbot>
675
+ </div>
676
+ `;
677
+ }
678
+ };
679
+
680
+ /**
681
+ * Boxed layout with threads - ChatGPT-style with conversation management
682
+ * Create multiple conversations and switch between them seamlessly!
683
+ */
684
+ export const BoxedWithThreads: Story = {
685
+ args: {
686
+ ...Default.args,
687
+ boxed: true,
688
+ showThreads: true
689
+ },
690
+ parameters: {
691
+ layout: 'fullscreen'
692
+ },
693
+ render: (args) => {
694
+ setTimeout(() => {
695
+ const chatbot = document.querySelector('#boxed-threads-chatbot') as any;
696
+ if (chatbot && !chatbot.controller) {
697
+ // Create controller with thread support and file upload enabled
698
+ const controller = new ChatbotCoreController({
699
+ provider: new MockProvider({
700
+ delay: 500,
701
+ streaming: true,
702
+ streamingSpeed: 5,
703
+ streamingInterval: 20,
704
+ contextualResponses: true
705
+ }),
706
+ enableThreads: true,
707
+ enableFileUpload: true,
708
+ maxFileSize: 10 * 1024 * 1024, // 10MB
709
+ maxFiles: 5,
710
+ allowedFileTypes: ['image/*', 'application/pdf', 'text/*', 'video/*', 'audio/*'],
711
+ ui: {
712
+ onStateChange: (state) => {
713
+ chatbot.messages = state.messages;
714
+ chatbot.threads = state.threads;
715
+ chatbot.isBotTyping = state.isTyping;
716
+ chatbot.chatStarted = state.messages.length > 0;
717
+ chatbot.uploadedFiles = state.uploadedFiles;
718
+ },
719
+ onTypingStart: () => {
720
+ chatbot.isBotTyping = true;
721
+ },
722
+ onTypingEnd: () => {
723
+ chatbot.isBotTyping = false;
724
+ },
725
+ focusInput: () => {
726
+ chatbot.focusInput();
727
+ },
728
+ showNotification: (message, type) => {
729
+ console.log(`[${type.toUpperCase()}] ${message}`);
730
+ }
731
+ }
732
+ });
733
+
734
+ chatbot.controller = controller;
735
+ //chatbot.suggestions;
736
+ chatbot.enableThreadCreation = true;
737
+ chatbot.enableFileUpload = true;
738
+ chatbot.actionButtons = [
739
+ { type: 'attach', enabled: true }
740
+ ];
741
+ }
742
+ }, 0);
743
+
744
+ return html`
745
+ <div style="width: 100vw; height: 100vh; background: var(--nr-color-background, #f5f5f5);">
746
+ <nr-chatbot
747
+ id="boxed-threads-chatbot"
748
+ .size=${args.size}
749
+ .variant=${args.variant}
750
+ .isRTL=${args.isRTL}
751
+ .disabled=${args.disabled}
752
+ .showSendButton=${args.showSendButton}
753
+ .autoScroll=${args.autoScroll}
754
+ .showThreads=${args.showThreads}
755
+ .boxed=${args.boxed}
756
+ ></nr-chatbot>
757
+ </div>
758
+ `;
759
+ }
760
+ };
761
+
762
+ /**
763
+ * Message attachments: initial message shows file tags
764
+ */
765
+ export const WithInitialMessageAttachments: Story = {
766
+ args: {
767
+ ...Default.args,
768
+ boxed: false
769
+ },
770
+ render: (args) => {
771
+ setTimeout(() => {
772
+ const chatbot = document.querySelector('#attachments-initial-chatbot') as any;
773
+ if (chatbot && !chatbot.controller) {
774
+ const controller = new ChatbotCoreController({
775
+ provider: new MockProvider({
776
+ delay: 400,
777
+ streaming: true,
778
+ streamingSpeed: 4,
779
+ streamingInterval: 20,
780
+ contextualResponses: true
781
+ }),
782
+ initialMessages: [
783
+ {
784
+ id: 'intro',
785
+ sender: ChatbotSender.Bot,
786
+ text: 'Hi! I can analyze your files. Try sending a message with attachments.',
787
+ timestamp: new Date().toISOString()
788
+ },
789
+ {
790
+ id: 'with-files',
791
+ sender: ChatbotSender.User,
792
+ text: 'Please analyze the attached documents.',
793
+ timestamp: new Date().toISOString(),
794
+ files: [
795
+ { id: 'f1', name: 'report.pdf', size: 123456, type: ChatbotFileType.Document, mimeType: 'application/pdf' },
796
+ { id: 'f2', name: 'notes.txt', size: 2048, type: ChatbotFileType.Document, mimeType: 'text/plain' }
797
+ ]
798
+ }
799
+ ],
800
+ ui: {
801
+ onStateChange: (state) => {
802
+ chatbot.messages = state.messages;
803
+ chatbot.isBotTyping = state.isTyping;
804
+ chatbot.chatStarted = state.messages.length > 0;
805
+ }
806
+ }
807
+ });
808
+ chatbot.controller = controller;
809
+ }
810
+ }, 0);
811
+
812
+ return html`
813
+ <div style="width: 500px; height: 600px;">
814
+ <nr-chatbot
815
+ id="attachments-initial-chatbot"
816
+ .size=${args.size}
817
+ .variant=${args.variant}
818
+ .isRTL=${args.isRTL}
819
+ .disabled=${args.disabled}
820
+ .showSendButton=${args.showSendButton}
821
+ .autoScroll=${args.autoScroll}
822
+ .showThreads=${args.showThreads}
823
+ .boxed=${args.boxed}
824
+ ></nr-chatbot>
825
+ </div>
826
+ `;
827
+ }
828
+ };
829
+
830
+ /**
831
+ * Message attachments: attach files, then send to see tags move to the message
832
+ */
833
+ export const WithFileUploadAttachments: Story = {
834
+ args: {
835
+ ...Default.args,
836
+ boxed: false
837
+ },
838
+ render: (args) => {
839
+ setTimeout(() => {
840
+ const chatbot = document.querySelector('#attachments-upload-chatbot') as any;
841
+ const attachBtn = document.querySelector('#attach-sample-file') as HTMLButtonElement | null;
842
+ const sendBtn = document.querySelector('#send-with-files') as HTMLButtonElement | null;
843
+
844
+ if (chatbot && !chatbot.controller) {
845
+ const controller = new ChatbotCoreController({
846
+ provider: new MockProvider({
847
+ delay: 400,
848
+ streaming: true,
849
+ streamingSpeed: 4,
850
+ streamingInterval: 20,
851
+ contextualResponses: true
852
+ }),
853
+ enableFileUpload: true,
854
+ ui: {
855
+ onStateChange: (state) => {
856
+ chatbot.messages = state.messages;
857
+ chatbot.isBotTyping = state.isTyping;
858
+ chatbot.chatStarted = state.messages.length > 0;
859
+ chatbot.uploadedFiles = state.uploadedFiles;
860
+ }
861
+ }
862
+ });
863
+ chatbot.controller = controller;
864
+ chatbot.enableFileUpload = true;
865
+ }
866
+
867
+ // Wire demo buttons
868
+ if (attachBtn) {
869
+ attachBtn.onclick = async () => {
870
+ const chatbotEl = document.querySelector('#attachments-upload-chatbot') as any;
871
+ const controller = chatbotEl?.controller as ChatbotCoreController | undefined;
872
+ if (!controller) return;
873
+ // Create a sample File via Blob
874
+ const pdfBlob = new Blob([new Uint8Array([0x25,0x50,0x44,0x46])], { type: 'application/pdf' });
875
+ const txtBlob = new Blob(['Sample notes'], { type: 'text/plain' });
876
+ const pdf = new File([pdfBlob], 'sample.pdf', { type: 'application/pdf' });
877
+ const txt = new File([txtBlob], 'notes.txt', { type: 'text/plain' });
878
+ await controller.uploadFiles([pdf, txt]);
879
+ };
880
+ }
881
+
882
+ if (sendBtn) {
883
+ sendBtn.onclick = async () => {
884
+ const chatbotEl = document.querySelector('#attachments-upload-chatbot') as any;
885
+ const controller = chatbotEl?.controller as ChatbotCoreController | undefined;
886
+ if (!controller) return;
887
+ const files = controller.getUploadedFiles();
888
+ await controller.sendMessage('Analyze the attached files, please.', { files });
889
+ controller.clearFiles();
890
+ };
891
+ }
892
+ }, 0);
893
+
894
+ return html`
895
+ <div style="display: grid; gap: 12px; width: 520px;">
896
+ <div style="display:flex; gap: 8px; align-items:center;">
897
+ <button id="attach-sample-file" type="button">Attach sample files</button>
898
+ <button id="send-with-files" type="button">Send with files</button>
899
+ <span style="color:#666; font-size:12px;">Or use the Attach button inside the chatbot</span>
900
+ </div>
901
+ <div style="width: 500px; height: 600px;">
902
+ <nr-chatbot
903
+ id="attachments-upload-chatbot"
904
+ .size=${args.size}
905
+ .variant=${args.variant}
906
+ .isRTL=${args.isRTL}
907
+ .disabled=${args.disabled}
908
+ .showSendButton=${args.showSendButton}
909
+ .autoScroll=${args.autoScroll}
910
+ .showThreads=${args.showThreads}
911
+ .boxed=${args.boxed}
912
+ ></nr-chatbot>
913
+ </div>
914
+ </div>
915
+ `;
916
+ }
917
+ };
918
+
919
+ /**
920
+ * Storage - Memory Storage (Non-persistent)
921
+ * Messages are stored in memory only - lost on page refresh.
922
+ * Try sending messages and note they disappear when you refresh the page.
923
+ */
924
+ export const StorageMemory: Story = {
925
+ args: {
926
+ ...Default.args,
927
+ showThreads: true
928
+ },
929
+ render: (args) => {
930
+ setTimeout(() => {
931
+ const chatbot = document.querySelector('#storage-memory-chatbot') as any;
932
+ if (chatbot && !chatbot.controller) {
933
+ const controller = new ChatbotCoreController({
934
+ provider: new MockProvider({
935
+ delay: 500,
936
+ streaming: true,
937
+ streamingSpeed: 5,
938
+ streamingInterval: 20,
939
+ contextualResponses: true
940
+ }),
941
+ storage: new MemoryStorage(),
942
+ enableThreads: true,
943
+ autoSaveInterval: 1000, // Auto-save every 1 second
944
+ ui: {
945
+ onStateChange: (state) => {
946
+ chatbot.messages = state.messages;
947
+ chatbot.threads = state.threads;
948
+ chatbot.isBotTyping = state.isTyping;
949
+ chatbot.chatStarted = state.messages.length > 0;
950
+ },
951
+ onTypingStart: () => {
952
+ chatbot.isBotTyping = true;
953
+ },
954
+ onTypingEnd: () => {
955
+ chatbot.isBotTyping = false;
956
+ },
957
+ showNotification: (message, type) => {
958
+ console.log(`[MemoryStorage ${type.toUpperCase()}] ${message}`);
959
+ }
960
+ }
961
+ });
962
+
963
+ chatbot.controller = controller;
964
+ chatbot.suggestions = [
965
+ { id: 'mem1', text: 'Send a message', enabled: true },
966
+ { id: 'mem2', text: 'Create a thread', enabled: true },
967
+ { id: 'mem3', text: 'Messages will be lost on refresh!', enabled: true }
968
+ ];
969
+ chatbot.enableThreadCreation = true;
970
+
971
+ // Display storage info
972
+ setTimeout(() => {
973
+ console.log('[MemoryStorage] Using in-memory storage - data will be lost on page refresh');
974
+ }, 100);
975
+ }
976
+ }, 0);
977
+
978
+ return html`
979
+ <div style="display: flex; flex-direction: column; gap: 16px;">
980
+ <div style="padding: 16px; background: #fff3cd; border: 1px solid #ffc107; border-radius: 8px;">
981
+ <h3 style="margin: 0 0 8px 0; color: #856404;">🔄 Memory Storage</h3>
982
+ <p style="margin: 0; color: #856404;">
983
+ Messages are stored in memory only and <strong>will be lost on page refresh</strong>.
984
+ Perfect for temporary conversations or demos.
985
+ </p>
986
+ </div>
987
+ <div style="width: 800px; height: 600px;">
988
+ <nr-chatbot
989
+ id="storage-memory-chatbot"
990
+ .size=${args.size}
991
+ .variant=${args.variant}
992
+ .isRTL=${args.isRTL}
993
+ .disabled=${args.disabled}
994
+ .showSendButton=${args.showSendButton}
995
+ .autoScroll=${args.autoScroll}
996
+ .showThreads=${args.showThreads}
997
+ .boxed=${args.boxed}
998
+ ></nr-chatbot>
999
+ </div>
1000
+ </div>
1001
+ `;
1002
+ }
1003
+ };
1004
+
1005
+ /**
1006
+ * Storage - LocalStorage (Persistent)
1007
+ * Messages persist across page refreshes using browser's localStorage.
1008
+ * Try sending messages, refresh the page, and see them still there!
1009
+ */
1010
+ export const StorageLocalStorage: Story = {
1011
+ args: {
1012
+ ...Default.args,
1013
+ showThreads: true
1014
+ },
1015
+ render: (args) => {
1016
+ setTimeout(() => {
1017
+ const chatbot = document.querySelector('#storage-localstorage-chatbot') as any;
1018
+ if (chatbot && !chatbot.controller) {
1019
+ const controller = new ChatbotCoreController({
1020
+ provider: new MockProvider({
1021
+ delay: 500,
1022
+ streaming: true,
1023
+ streamingSpeed: 5,
1024
+ streamingInterval: 20,
1025
+ contextualResponses: true
1026
+ }),
1027
+ storage: new LocalStorageAdapter(),
1028
+ enableThreads: true,
1029
+ autoSaveInterval: 2000, // Auto-save every 2 seconds
1030
+ ui: {
1031
+ onStateChange: (state) => {
1032
+ chatbot.messages = state.messages;
1033
+ chatbot.threads = state.threads;
1034
+ chatbot.isBotTyping = state.isTyping;
1035
+ chatbot.chatStarted = state.messages.length > 0;
1036
+ },
1037
+ onTypingStart: () => {
1038
+ chatbot.isBotTyping = true;
1039
+ },
1040
+ onTypingEnd: () => {
1041
+ chatbot.isBotTyping = false;
1042
+ },
1043
+ showNotification: (message, type) => {
1044
+ console.log(`[LocalStorage ${type.toUpperCase()}] ${message}`);
1045
+ }
1046
+ }
1047
+ });
1048
+
1049
+ chatbot.controller = controller;
1050
+ chatbot.suggestions = [
1051
+ { id: 'local1', text: 'Send a message and refresh!', enabled: true },
1052
+ { id: 'local2', text: 'Create multiple threads', enabled: true },
1053
+ { id: 'local3', text: 'Messages persist across refreshes', enabled: true }
1054
+ ];
1055
+ chatbot.enableThreadCreation = true;
1056
+
1057
+ // Load persisted data
1058
+ setTimeout(async () => {
1059
+ try {
1060
+ await controller.loadFromStorage('chatbot-state');
1061
+ console.log('[LocalStorage] Successfully loaded persisted conversation history');
1062
+ } catch (error) {
1063
+ console.log('[LocalStorage] No persisted data found - starting fresh');
1064
+ }
1065
+ }, 100);
1066
+ }
1067
+ }, 0);
1068
+
1069
+ return html`
1070
+ <div style="display: flex; flex-direction: column; gap: 16px;">
1071
+ <div style="padding: 16px; background: #d1ecf1; border: 1px solid #17a2b8; border-radius: 8px;">
1072
+ <h3 style="margin: 0 0 8px 0; color: #0c5460;">💾 LocalStorage Persistence</h3>
1073
+ <p style="margin: 0 0 8px 0; color: #0c5460;">
1074
+ Messages persist across page refreshes using <strong>localStorage</strong>.
1075
+ Try sending messages, then refresh the page!
1076
+ </p>
1077
+ <button
1078
+ onclick="localStorage.clear(); location.reload();"
1079
+ style="padding: 8px 16px; background: #17a2b8; color: white; border: none; border-radius: 4px; cursor: pointer;">
1080
+ 🗑️ Clear Storage & Reload
1081
+ </button>
1082
+ </div>
1083
+ <div style="width: 800px; height: 600px;">
1084
+ <nr-chatbot
1085
+ id="storage-localstorage-chatbot"
1086
+ .size=${args.size}
1087
+ .variant=${args.variant}
1088
+ .isRTL=${args.isRTL}
1089
+ .disabled=${args.disabled}
1090
+ .showSendButton=${args.showSendButton}
1091
+ .autoScroll=${args.autoScroll}
1092
+ .showThreads=${args.showThreads}
1093
+ .boxed=${args.boxed}
1094
+ ></nr-chatbot>
1095
+ </div>
1096
+ </div>
1097
+ `;
1098
+ }
1099
+ };
1100
+
1101
+ /**
1102
+ * Storage - IndexedDB (High Performance)
1103
+ * Messages persist using IndexedDB for larger datasets and better performance.
1104
+ * Ideal for production applications with extensive conversation history.
1105
+ */
1106
+ export const StorageIndexedDB: Story = {
1107
+ args: {
1108
+ ...Default.args,
1109
+ showThreads: true
1110
+ },
1111
+ render: (args) => {
1112
+ setTimeout(() => {
1113
+ const chatbot = document.querySelector('#storage-indexeddb-chatbot') as any;
1114
+ if (chatbot && !chatbot.controller) {
1115
+ const indexedDBStorage = new IndexedDBStorage('chatbot-demo-db', 'conversations');
1116
+
1117
+ const controller = new ChatbotCoreController({
1118
+ provider: new MockProvider({
1119
+ delay: 500,
1120
+ streaming: true,
1121
+ streamingSpeed: 5,
1122
+ streamingInterval: 20,
1123
+ contextualResponses: true
1124
+ }),
1125
+ storage: indexedDBStorage,
1126
+ enableThreads: true,
1127
+ autoSaveInterval: 3000, // Auto-save every 3 seconds
1128
+ ui: {
1129
+ onStateChange: (state) => {
1130
+ chatbot.messages = state.messages;
1131
+ chatbot.threads = state.threads;
1132
+ chatbot.isBotTyping = state.isTyping;
1133
+ chatbot.chatStarted = state.messages.length > 0;
1134
+ },
1135
+ onTypingStart: () => {
1136
+ chatbot.isBotTyping = true;
1137
+ },
1138
+ onTypingEnd: () => {
1139
+ chatbot.isBotTyping = false;
1140
+ },
1141
+ showNotification: (message, type) => {
1142
+ console.log(`[IndexedDB ${type.toUpperCase()}] ${message}`);
1143
+ }
1144
+ }
1145
+ });
1146
+
1147
+ chatbot.controller = controller;
1148
+ chatbot.suggestions = [
1149
+ { id: 'idb1', text: 'High performance storage', enabled: true },
1150
+ { id: 'idb2', text: 'Handles large datasets', enabled: true },
1151
+ { id: 'idb3', text: 'Production-ready persistence', enabled: true }
1152
+ ];
1153
+ chatbot.enableThreadCreation = true;
1154
+
1155
+ // Load persisted data
1156
+ setTimeout(async () => {
1157
+ try {
1158
+ await controller.loadFromStorage('chatbot-state');
1159
+ console.log('[IndexedDB] Successfully loaded persisted conversation history');
1160
+ } catch (error) {
1161
+ console.log('[IndexedDB] No persisted data found - starting fresh');
1162
+ }
1163
+ }, 100);
1164
+ }
1165
+ }, 0);
1166
+
1167
+ return html`
1168
+ <div style="display: flex; flex-direction: column; gap: 16px;">
1169
+ <div style="padding: 16px; background: #d4edda; border: 1px solid #28a745; border-radius: 8px;">
1170
+ <h3 style="margin: 0 0 8px 0; color: #155724;">🚀 IndexedDB Storage</h3>
1171
+ <p style="margin: 0 0 8px 0; color: #155724;">
1172
+ High-performance persistent storage using <strong>IndexedDB</strong>.
1173
+ Perfect for production apps with extensive conversation history.
1174
+ </p>
1175
+ <div style="display: flex; gap: 8px;">
1176
+ <button
1177
+ onclick="
1178
+ const db = indexedDB.open('chatbot-demo-db');
1179
+ db.onsuccess = (e) => {
1180
+ const database = e.target.result;
1181
+ const transaction = database.transaction(['conversations'], 'readwrite');
1182
+ const store = transaction.objectStore('conversations');
1183
+ store.clear();
1184
+ console.log('[IndexedDB] Cleared all data');
1185
+ setTimeout(() => location.reload(), 500);
1186
+ };
1187
+ "
1188
+ style="padding: 8px 16px; background: #28a745; color: white; border: none; border-radius: 4px; cursor: pointer;">
1189
+ 🗑️ Clear IndexedDB & Reload
1190
+ </button>
1191
+ <button
1192
+ onclick="
1193
+ const db = indexedDB.open('chatbot-demo-db');
1194
+ db.onsuccess = (e) => {
1195
+ const database = e.target.result;
1196
+ const transaction = database.transaction(['conversations'], 'readonly');
1197
+ const store = transaction.objectStore('conversations');
1198
+ const request = store.get('chatbot-state');
1199
+ request.onsuccess = () => {
1200
+ console.log('[IndexedDB] Current state:', request.result);
1201
+ alert('Check console for IndexedDB data');
1202
+ };
1203
+ };
1204
+ "
1205
+ style="padding: 8px 16px; background: #17a2b8; color: white; border: none; border-radius: 4px; cursor: pointer;">
1206
+ 🔍 Inspect Data
1207
+ </button>
1208
+ </div>
1209
+ </div>
1210
+ <div style="width: 800px; height: 600px;">
1211
+ <nr-chatbot
1212
+ id="storage-indexeddb-chatbot"
1213
+ .size=${args.size}
1214
+ .variant=${args.variant}
1215
+ .isRTL=${args.isRTL}
1216
+ .disabled=${args.disabled}
1217
+ .showSendButton=${args.showSendButton}
1218
+ .autoScroll=${args.autoScroll}
1219
+ .showThreads=${args.showThreads}
1220
+ .boxed=${args.boxed}
1221
+ ></nr-chatbot>
1222
+ </div>
1223
+ </div>
1224
+ `;
1225
+ }
1226
+ };
1227
+
1228
+ /**
1229
+ * Storage Comparison - See all three storage types side by side
1230
+ * Compare Memory, LocalStorage, and IndexedDB implementations.
1231
+ */
1232
+ export const StorageComparison: Story = {
1233
+ args: {
1234
+ ...Default.args,
1235
+ showThreads: false
1236
+ },
1237
+ render: (args) => {
1238
+ ['memory', 'localstorage', 'indexeddb'].forEach((storageType) => {
1239
+ setTimeout(() => {
1240
+ const chatbot = document.querySelector(`#chatbot-${storageType}`) as any;
1241
+ if (chatbot && !chatbot.controller) {
1242
+ let storage;
1243
+ let storageLabel;
1244
+
1245
+ if (storageType === 'memory') {
1246
+ storage = new MemoryStorage();
1247
+ storageLabel = 'Memory';
1248
+ } else if (storageType === 'localstorage') {
1249
+ storage = new LocalStorageAdapter();
1250
+ storageLabel = 'LocalStorage';
1251
+ } else {
1252
+ storage = new IndexedDBStorage(`chatbot-${storageType}-db`, 'messages');
1253
+ storageLabel = 'IndexedDB';
1254
+ }
1255
+
1256
+ const controller = new ChatbotCoreController({
1257
+ provider: new MockProvider({
1258
+ delay: 300,
1259
+ streaming: true,
1260
+ streamingSpeed: 8,
1261
+ streamingInterval: 15,
1262
+ contextualResponses: true
1263
+ }),
1264
+ storage,
1265
+ enableThreads: false,
1266
+ autoSaveInterval: 2000,
1267
+ ui: {
1268
+ onStateChange: (state) => {
1269
+ chatbot.messages = state.messages;
1270
+ chatbot.isBotTyping = state.isTyping;
1271
+ chatbot.chatStarted = state.messages.length > 0;
1272
+ },
1273
+ showNotification: (message, type) => {
1274
+ console.log(`[${storageLabel} ${type.toUpperCase()}] ${message}`);
1275
+ }
1276
+ }
1277
+ });
1278
+
1279
+ chatbot.controller = controller;
1280
+ chatbot.suggestions = [
1281
+ { id: `${storageType}-1`, text: `Test ${storageLabel}`, enabled: true }
1282
+ ];
1283
+ }
1284
+ }, 0);
1285
+ });
1286
+
1287
+ return html`
1288
+ <div style="display: flex; flex-direction: column; gap: 16px;">
1289
+ <div style="padding: 16px; background: #f8f9fa; border: 1px solid #dee2e6; border-radius: 8px;">
1290
+ <h3 style="margin: 0 0 8px 0;">📊 Storage Comparison</h3>
1291
+ <p style="margin: 0;">
1292
+ Compare all three storage implementations side by side.
1293
+ Send messages to each and refresh to see persistence differences.
1294
+ </p>
1295
+ </div>
1296
+ <div style="display: flex; gap: 20px; flex-wrap: wrap;">
1297
+ <div style="flex: 1; min-width: 300px;">
1298
+ <h4 style="margin: 0 0 8px 0; padding: 8px; background: #fff3cd; border-radius: 4px;">
1299
+ 🔄 Memory Storage
1300
+ </h4>
1301
+ <div style="width: 100%; height: 450px;">
1302
+ <nr-chatbot
1303
+ id="chatbot-memory"
1304
+ .size=${ChatbotSize.Small}
1305
+ .variant=${args.variant}
1306
+ .showSendButton=${true}
1307
+ .autoScroll=${true}
1308
+ ></nr-chatbot>
1309
+ </div>
1310
+ <p style="font-size: 12px; color: #666; margin-top: 8px;">
1311
+ ⚠️ Lost on refresh
1312
+ </p>
1313
+ </div>
1314
+ <div style="flex: 1; min-width: 300px;">
1315
+ <h4 style="margin: 0 0 8px 0; padding: 8px; background: #d1ecf1; border-radius: 4px;">
1316
+ 💾 LocalStorage
1317
+ </h4>
1318
+ <div style="width: 100%; height: 450px;">
1319
+ <nr-chatbot
1320
+ id="chatbot-localstorage"
1321
+ .size=${ChatbotSize.Small}
1322
+ .variant=${args.variant}
1323
+ .showSendButton=${true}
1324
+ .autoScroll=${true}
1325
+ ></nr-chatbot>
1326
+ </div>
1327
+ <p style="font-size: 12px; color: #666; margin-top: 8px;">
1328
+ ✅ Persists across refreshes
1329
+ </p>
1330
+ </div>
1331
+ <div style="flex: 1; min-width: 300px;">
1332
+ <h4 style="margin: 0 0 8px 0; padding: 8px; background: #d4edda; border-radius: 4px;">
1333
+ 🚀 IndexedDB
1334
+ </h4>
1335
+ <div style="width: 100%; height: 450px;">
1336
+ <nr-chatbot
1337
+ id="chatbot-indexeddb"
1338
+ .size=${ChatbotSize.Small}
1339
+ .variant=${args.variant}
1340
+ .showSendButton=${true}
1341
+ .autoScroll=${true}
1342
+ ></nr-chatbot>
1343
+ </div>
1344
+ <p style="font-size: 12px; color: #666; margin-top: 8px;">
1345
+ ✅ High performance persistence
1346
+ </p>
1347
+ </div>
1348
+ </div>
1349
+ </div>
1350
+ `;
1351
+ }
1352
+ };
1353
+
1354
+ /**
1355
+ * Custom API Provider with Custom Headers - Test multipart/form-data streaming
1356
+ * Tests CustomAPIProvider with custom Content-Type headers and streaming text/plain response.
1357
+ */
1358
+ export const CustomAPIWithHeaders: Story = {
1359
+ args: {
1360
+ ...Default.args,
1361
+ boxed: true,
1362
+ showThreads: false
1363
+ },
1364
+ parameters: {
1365
+ layout: 'fullscreen'
1366
+ },
1367
+ render: (args) => {
1368
+ // Mock fetch to simulate streaming text/plain response
1369
+ const originalFetch = window.fetch;
1370
+ const mockFetch = async (url: string | URL | Request, options?: RequestInit) => {
1371
+ if (url.toString().includes('/api/v3/iassistant/text-processing')) {
1372
+ console.log('🎯 Intercepted API call to:', url);
1373
+ console.log('📦 Request options:', options);
1374
+
1375
+ // Simulate streaming text/plain response
1376
+ const responseText = 'This is a simulated streaming response from the API. It demonstrates how the chatbot handles text/plain content type with streaming. Each chunk arrives progressively to create a typewriter effect. 🎉';
1377
+
1378
+ const stream = new ReadableStream({
1379
+ start(controller) {
1380
+ let index = 0;
1381
+ const interval = setInterval(() => {
1382
+ if (index < responseText.length) {
1383
+ // Send 1-3 characters at a time to simulate realistic streaming
1384
+ const chunkSize = Math.floor(Math.random() * 3) + 1;
1385
+ const chunk = responseText.slice(index, index + chunkSize);
1386
+ controller.enqueue(new TextEncoder().encode(chunk));
1387
+ index += chunkSize;
1388
+ } else {
1389
+ clearInterval(interval);
1390
+ controller.close();
1391
+ }
1392
+ }, 50); // 50ms delay between chunks
1393
+ }
1394
+ });
1395
+
1396
+ return new Response(stream, {
1397
+ status: 200,
1398
+ headers: {
1399
+ 'Content-Type': 'text/plain',
1400
+ 'Transfer-Encoding': 'chunked'
1401
+ }
1402
+ });
1403
+ }
1404
+ return originalFetch(url, options);
1405
+ };
1406
+
1407
+ setTimeout(async () => {
1408
+ const chatbot = document.querySelector('#custom-api-headers-chatbot') as any;
1409
+ if (chatbot && !chatbot.controller) {
1410
+ // Temporarily replace fetch
1411
+ window.fetch = mockFetch as any;
1412
+
1413
+ // Import CustomAPIProvider
1414
+ const { CustomAPIProvider } = await import('./providers/custom-api-provider.js');
1415
+
1416
+ // Extend CustomAPIProvider to override buildPayload
1417
+ class ExtendedAPIProvider extends CustomAPIProvider {
1418
+ buildPayload(text: string, context: any): any {
1419
+ console.log('📤 Building payload with context:', context);
1420
+ const payload = {
1421
+ userText: text,
1422
+ variables: context.metadata || {},
1423
+ tag: context.metadata?.tag || 'default',
1424
+ stream: true
1425
+ };
1426
+ console.log('📤 Payload:', payload);
1427
+ return payload;
1428
+ }
1429
+ }
1430
+
1431
+ const provider = new ExtendedAPIProvider();
1432
+
1433
+ // Connect with custom headers
1434
+ try {
1435
+ await provider.connect({
1436
+ apiUrl: '/api/v3/iassistant/text-processing',
1437
+ headers: {
1438
+ 'accept': 'text/plain',
1439
+ 'Content-Type': 'multipart/form-data'
1440
+ }
1441
+ });
1442
+ console.log('✅ CustomAPIProvider connected with custom headers');
1443
+ console.log('📋 Headers configured for multipart/form-data with text/plain streaming');
1444
+ } catch (error) {
1445
+ console.error('❌ Failed to connect:', error);
1446
+ }
1447
+
1448
+ const controller = new ChatbotCoreController({
1449
+ provider,
1450
+ enableThreads: false,
1451
+ enableFileUpload: true,
1452
+ maxFileSize: 10 * 1024 * 1024, // 10MB
1453
+ maxFiles: 5,
1454
+ allowedFileTypes: ['image/*', 'application/pdf', 'text/*', 'video/*', 'audio/*'],
1455
+ metadata: {
1456
+ tag: 'summarize'
1457
+ },
1458
+ ui: {
1459
+ onStateChange: (state) => {
1460
+ chatbot.messages = state.messages;
1461
+ chatbot.threads = state.threads;
1462
+ chatbot.isBotTyping = state.isTyping;
1463
+ chatbot.chatStarted = state.messages.length > 0;
1464
+ chatbot.uploadedFiles = state.uploadedFiles;
1465
+ },
1466
+ onTypingStart: () => { chatbot.isBotTyping = true; },
1467
+ onTypingEnd: () => { chatbot.isBotTyping = false; },
1468
+ focusInput: () => { chatbot.focusInput(); },
1469
+ showNotification: (message, type) => {
1470
+ console.log(`[${type.toUpperCase()}] ${message}`);
1471
+ }
1472
+ }
1473
+ });
1474
+
1475
+ chatbot.controller = controller;
1476
+ chatbot.enableThreadCreation = false;
1477
+ chatbot.enableFileUpload = true;
1478
+ chatbot.actionButtons = [
1479
+ { type: 'attach', enabled: true }
1480
+ ];
1481
+
1482
+ chatbot.suggestions = [
1483
+ { id: 'test1', text: 'Test streaming response', enabled: true },
1484
+ { id: 'test2', text: 'Send with multipart/form-data', enabled: true },
1485
+ { id: 'test3', text: 'Check console for logs', enabled: true }
1486
+ ];
1487
+
1488
+ // Cleanup on unmount
1489
+ const cleanup = () => {
1490
+ window.fetch = originalFetch;
1491
+ };
1492
+
1493
+ // Store cleanup for later
1494
+ (window as any).__storyCleanup = cleanup;
1495
+ }
1496
+ }, 0);
1497
+
1498
+ return html`
1499
+ <div style="width: 100vw; height: 100vh; background: var(--nr-color-background, #f5f5f5);">
1500
+ <div style="position: absolute; top: 16px; left: 16px; right: 16px; z-index: 1000; padding: 16px; background: #fff; border: 2px solid #28a745; border-radius: 8px; box-shadow: 0 2px 8px rgba(0,0,0,0.1);">
1501
+ <h3 style="margin: 0 0 8px 0; color: #155724;">🎬 Custom API Provider - Streaming Test</h3>
1502
+ <p style="margin: 0 0 8px 0; color: #155724; font-size: 14px;">
1503
+ This story tests <strong>multipart/form-data</strong> with <strong>text/plain streaming</strong>:
1504
+ </p>
1505
+ <ul style="margin: 0; padding-left: 20px; color: #155724; font-size: 13px;">
1506
+ <li>✅ <strong>Request:</strong> multipart/form-data (FormData fields)</li>
1507
+ <li>✅ <strong>Response:</strong> text/plain with streaming</li>
1508
+ <li>✅ <strong>Metadata tag:</strong> summarize</li>
1509
+ <li>✅ <strong>Effect:</strong> Typewriter streaming animation</li>
1510
+ </ul>
1511
+ <p style="margin: 8px 0 0 0; color: #0c5460; font-size: 12px; background: #d1ecf1; padding: 8px; border-radius: 4px;">
1512
+ 💡 <strong>Try it:</strong> Send a message and watch it stream character by character!
1513
+ Open the <strong>Console</strong> to see request/response logs.
1514
+ </p>
1515
+ </div>
1516
+ <nr-chatbot
1517
+ id="custom-api-headers-chatbot"
1518
+ .size=${args.size}
1519
+ .variant=${args.variant}
1520
+ .isRTL=${args.isRTL}
1521
+ .disabled=${args.disabled}
1522
+ .showSendButton=${args.showSendButton}
1523
+ .autoScroll=${args.autoScroll}
1524
+ .showThreads=${args.showThreads}
1525
+ .boxed=${args.boxed}
1526
+ style="padding-top: 220px;"
1527
+ ></nr-chatbot>
1528
+ </div>
1529
+ `;
1530
+ }
1531
+ };
1532
+
1533
+ /**
1534
+ * Custom API Provider - Error Handling Showcase
1535
+ * Demonstrates styled error messages in the chat.
1536
+ */
1537
+ export const CustomAPIErrorHandling: Story = {
1538
+ args: {
1539
+ ...Default.args,
1540
+ boxed: false
1541
+ },
1542
+ render: (args) => {
1543
+ // Mock fetch to simulate different error scenarios
1544
+ const originalFetch = window.fetch;
1545
+ let errorScenario = 0;
1546
+
1547
+ const mockFetch = async (url: string | URL | Request, options?: RequestInit) => {
1548
+ if (url.toString().includes('/api/v3/iassistant/text-processing')) {
1549
+ console.log('🎯 Intercepted API call - Scenario:', errorScenario);
1550
+
1551
+ // Cycle through different error scenarios
1552
+ const scenarios = [
1553
+ // Scenario 0: Success
1554
+ () => {
1555
+ const stream = new ReadableStream({
1556
+ start(controller) {
1557
+ const text = '✅ Success! This is a successful streaming response.';
1558
+ let index = 0;
1559
+ const interval = setInterval(() => {
1560
+ if (index < text.length) {
1561
+ controller.enqueue(new TextEncoder().encode(text[index]));
1562
+ index++;
1563
+ } else {
1564
+ clearInterval(interval);
1565
+ controller.close();
1566
+ }
1567
+ }, 30);
1568
+ }
1569
+ });
1570
+ return new Response(stream, {
1571
+ status: 200,
1572
+ headers: { 'Content-Type': 'text/plain' }
1573
+ });
1574
+ },
1575
+ // Scenario 1: 404 Not Found
1576
+ () => new Response('The requested endpoint was not found on this server.', {
1577
+ status: 404,
1578
+ statusText: 'Not Found',
1579
+ headers: { 'Content-Type': 'text/plain' }
1580
+ }),
1581
+ // Scenario 2: 500 Internal Server Error
1582
+ () => new Response('An internal server error occurred while processing your request.', {
1583
+ status: 500,
1584
+ statusText: 'Internal Server Error',
1585
+ headers: { 'Content-Type': 'text/plain' }
1586
+ }),
1587
+ // Scenario 3: 401 Unauthorized
1588
+ () => new Response('You must be authenticated to access this resource.', {
1589
+ status: 401,
1590
+ statusText: 'Unauthorized',
1591
+ headers: { 'Content-Type': 'text/plain' }
1592
+ }),
1593
+ // Scenario 4: Network error (simulated)
1594
+ () => Promise.reject(new Error('Failed to fetch: Network connection was lost')),
1595
+ // Scenario 5: Streaming error mid-stream
1596
+ () => {
1597
+ const stream = new ReadableStream({
1598
+ start(controller) {
1599
+ const text = 'Starting to stream response... ';
1600
+ controller.enqueue(new TextEncoder().encode(text));
1601
+ setTimeout(() => {
1602
+ controller.error(new Error('Connection interrupted while streaming'));
1603
+ }, 100);
1604
+ }
1605
+ });
1606
+ return new Response(stream, {
1607
+ status: 200,
1608
+ headers: { 'Content-Type': 'text/plain' }
1609
+ });
1610
+ }
1611
+ ];
1612
+
1613
+ const scenario = scenarios[errorScenario % scenarios.length];
1614
+ errorScenario = (errorScenario + 1) % scenarios.length;
1615
+
1616
+ return scenario();
1617
+ }
1618
+ return originalFetch(url, options);
1619
+ };
1620
+
1621
+ setTimeout(async () => {
1622
+ const chatbot = document.querySelector('#error-handling-chatbot') as any;
1623
+ if (chatbot && !chatbot.controller) {
1624
+ window.fetch = mockFetch as any;
1625
+
1626
+ const { CustomAPIProvider } = await import('./providers/custom-api-provider.js');
1627
+
1628
+ class ExtendedAPIProvider extends CustomAPIProvider {
1629
+ buildPayload(text: string, context: any): any {
1630
+ return {
1631
+ userText: text,
1632
+ variables: context.metadata || {},
1633
+ tag: context.metadata?.tag || 'default',
1634
+ stream: true
1635
+ };
1636
+ }
1637
+ }
1638
+
1639
+ const provider = new ExtendedAPIProvider();
1640
+
1641
+ await provider.connect({
1642
+ apiUrl: '/api/v3/iassistant/text-processing',
1643
+ headers: {
1644
+ 'accept': 'text/plain',
1645
+ 'Content-Type': 'multipart/form-data'
1646
+ }
1647
+ });
1648
+
1649
+ const controller = new ChatbotCoreController({
1650
+ provider,
1651
+ metadata: { tag: 'test' },
1652
+ ui: {
1653
+ onStateChange: (state) => {
1654
+ chatbot.messages = state.messages;
1655
+ chatbot.isBotTyping = state.isTyping;
1656
+ chatbot.chatStarted = state.messages.length > 0;
1657
+ },
1658
+ onTypingStart: () => { chatbot.isBotTyping = true; },
1659
+ onTypingEnd: () => { chatbot.isBotTyping = false; },
1660
+ focusInput: () => { chatbot.focusInput(); }
1661
+ }
1662
+ });
1663
+
1664
+ chatbot.controller = controller;
1665
+ chatbot.suggestions = [
1666
+ { id: 'test1', text: 'Test success (1st)', enabled: true },
1667
+ { id: 'test2', text: 'Test 404 error (2nd)', enabled: true },
1668
+ { id: 'test3', text: 'Test 500 error (3rd)', enabled: true },
1669
+ { id: 'test4', text: 'Test 401 error (4th)', enabled: true },
1670
+ { id: 'test5', text: 'Test network error (5th)', enabled: true },
1671
+ { id: 'test6', text: 'Test stream error (6th)', enabled: true }
1672
+ ];
1673
+
1674
+ (window as any).__storyCleanup = () => {
1675
+ window.fetch = originalFetch;
1676
+ };
1677
+ }
1678
+ }, 0);
1679
+
1680
+ return html`
1681
+ <div style="display: flex; flex-direction: column; gap: 16px; padding: 20px; max-width: 800px;">
1682
+ <div style="padding: 16px; background: #fff; border: 2px solid #dc3545; border-radius: 8px; box-shadow: 0 2px 8px rgba(0,0,0,0.1);">
1683
+ <h3 style="margin: 0 0 8px 0; color: #721c24;">🚨 Styled Error Handling</h3>
1684
+ <p style="margin: 0 0 8px 0; color: #721c24; font-size: 14px;">
1685
+ Errors are displayed in a styled container with a title and description:
1686
+ </p>
1687
+ <ul style="margin: 0; padding-left: 20px; color: #721c24; font-size: 13px;">
1688
+ <li><strong>1st message:</strong> ✅ Success - Normal streaming response</li>
1689
+ <li><strong>2nd message:</strong> ⚠️ 404 Not Found error</li>
1690
+ <li><strong>3rd message:</strong> ⚠️ 500 Internal Server Error</li>
1691
+ <li><strong>4th message:</strong> ⚠️ 401 Unauthorized error</li>
1692
+ <li><strong>5th message:</strong> ⚠️ Network connection error</li>
1693
+ <li><strong>6th message:</strong> ⚠️ Streaming interrupted mid-stream</li>
1694
+ </ul>
1695
+ <p style="margin: 8px 0 0 0; color: #0c5460; font-size: 12px; background: #d1ecf1; padding: 8px; border-radius: 4px;">
1696
+ 💡 <strong>Try it:</strong> Send messages one by one to see each error type with styled formatting!
1697
+ </p>
1698
+ </div>
1699
+ <div style="width: 100%; height: 600px; border: 1px solid #dee2e6; border-radius: 8px; overflow: hidden;">
1700
+ <nr-chatbot
1701
+ id="error-handling-chatbot"
1702
+ .size=${args.size}
1703
+ .variant=${args.variant}
1704
+ .showSendButton=${true}
1705
+ .autoScroll=${true}
1706
+ ></nr-chatbot>
1707
+ </div>
1708
+ </div>
1709
+ `;
1710
+ }
1711
+ };
1712
+
1713
+ /**
1714
+ * Mock API with Conversation Loading
1715
+ * Tests overriding conversation loading by mocking fetch API to simulate:
1716
+ * - Loading existing conversations from API
1717
+ * - Creating new conversations
1718
+ * - Switching between conversations
1719
+ * - Deleting conversations
1720
+ */
1721
+ export const MockAPIWithConversationLoading: Story = {
1722
+ args: {
1723
+ ...Default.args,
1724
+ showThreads: true
1725
+ },
1726
+ render: (args) => {
1727
+ const originalFetch = window.fetch;
1728
+
1729
+ // Mock conversation data
1730
+ const mockConversations = [
1731
+ {
1732
+ id: 'conv_1',
1733
+ title: 'Product Recommendations',
1734
+ messages: [
1735
+ {
1736
+ id: 'msg_1',
1737
+ text: 'Can you recommend a laptop for programming?',
1738
+ sender: 'user' as ChatbotSender,
1739
+ timestamp: new Date(Date.now() - 3600000).toISOString()
1740
+ },
1741
+ {
1742
+ id: 'msg_2',
1743
+ text: 'I recommend the MacBook Pro M3 for development work. It offers excellent performance, long battery life, and a great development environment with macOS.',
1744
+ sender: 'bot' as ChatbotSender,
1745
+ timestamp: new Date(Date.now() - 3590000).toISOString()
1746
+ }
1747
+ ],
1748
+ createdAt: new Date(Date.now() - 7200000).toISOString(),
1749
+ updatedAt: new Date(Date.now() - 3590000).toISOString()
1750
+ },
1751
+ {
1752
+ id: 'conv_2',
1753
+ title: 'Web Development Tips',
1754
+ messages: [
1755
+ {
1756
+ id: 'msg_3',
1757
+ text: 'What are the best practices for React development?',
1758
+ sender: 'user' as ChatbotSender,
1759
+ timestamp: new Date(Date.now() - 86400000).toISOString()
1760
+ },
1761
+ {
1762
+ id: 'msg_4',
1763
+ text: 'Key React best practices include: 1) Use functional components with hooks, 2) Keep components small and focused, 3) Use proper state management, 4) Implement code splitting, and 5) Follow the single responsibility principle.',
1764
+ sender: 'bot' as ChatbotSender,
1765
+ timestamp: new Date(Date.now() - 86395000).toISOString()
1766
+ },
1767
+ {
1768
+ id: 'msg_5',
1769
+ text: 'How about TypeScript integration?',
1770
+ sender: 'user' as ChatbotSender,
1771
+ timestamp: new Date(Date.now() - 86300000).toISOString()
1772
+ },
1773
+ {
1774
+ id: 'msg_6',
1775
+ text: 'TypeScript with React is highly recommended! It provides type safety, better IDE support, and catches errors at compile time. Use proper typing for props, state, and events.',
1776
+ sender: 'bot' as ChatbotSender,
1777
+ timestamp: new Date(Date.now() - 86295000).toISOString()
1778
+ }
1779
+ ],
1780
+ createdAt: new Date(Date.now() - 172800000).toISOString(),
1781
+ updatedAt: new Date(Date.now() - 86295000).toISOString()
1782
+ },
1783
+ {
1784
+ id: 'conv_3',
1785
+ title: 'Database Design Question',
1786
+ messages: [
1787
+ {
1788
+ id: 'msg_7',
1789
+ text: 'What database should I use for a high-traffic app?',
1790
+ sender: 'user' as ChatbotSender,
1791
+ timestamp: new Date(Date.now() - 259200000).toISOString()
1792
+ },
1793
+ {
1794
+ id: 'msg_8',
1795
+ text: 'For high-traffic applications, consider PostgreSQL for relational data or MongoDB for document-based data. Redis is excellent for caching. The choice depends on your data structure and query patterns.',
1796
+ sender: 'bot' as ChatbotSender,
1797
+ timestamp: new Date(Date.now() - 259195000).toISOString()
1798
+ }
1799
+ ],
1800
+ createdAt: new Date(Date.now() - 259200000).toISOString(),
1801
+ updatedAt: new Date(Date.now() - 259195000).toISOString()
1802
+ }
1803
+ ];
1804
+
1805
+ let conversationStore = [...mockConversations];
1806
+
1807
+ // Mock fetch implementation
1808
+ const mockFetch = async (url: string | URL | Request, options?: RequestInit) => {
1809
+ const urlString = typeof url === 'string' ? url : url instanceof URL ? url.toString() : url.url;
1810
+
1811
+ // Mock: Load specific conversation (check this BEFORE the list endpoint)
1812
+ if (urlString.match(/\/api\/conversations\/[^/?]+$/) && (!options?.method || options?.method === 'GET')) {
1813
+ const conversationId = urlString.split('/').pop();
1814
+ const conversation = conversationStore.find(c => c.id === conversationId);
1815
+
1816
+ await new Promise(resolve => setTimeout(resolve, 300)); // Simulate network delay
1817
+
1818
+ if (conversation) {
1819
+ return new Response(JSON.stringify(conversation), {
1820
+ status: 200,
1821
+ headers: { 'Content-Type': 'application/json' }
1822
+ });
1823
+ } else {
1824
+ return new Response(JSON.stringify({ error: 'Conversation not found' }), {
1825
+ status: 404,
1826
+ headers: { 'Content-Type': 'application/json' }
1827
+ });
1828
+ }
1829
+ }
1830
+
1831
+ // Mock: Load conversations list
1832
+ if (urlString.includes('/api/conversations') && (!options?.method || options?.method === 'GET')) {
1833
+ await new Promise(resolve => setTimeout(resolve, 500)); // Simulate network delay
1834
+ return new Response(JSON.stringify({
1835
+ conversations: conversationStore.map(c => ({
1836
+ id: c.id,
1837
+ title: c.title,
1838
+ messageCount: c.messages.length,
1839
+ createdAt: c.createdAt,
1840
+ updatedAt: c.updatedAt
1841
+ }))
1842
+ }), {
1843
+ status: 200,
1844
+ headers: { 'Content-Type': 'application/json' }
1845
+ });
1846
+ }
1847
+
1848
+ // Mock: Create new conversation
1849
+ if (urlString.includes('/api/conversations') && options?.method === 'POST') {
1850
+ await new Promise(resolve => setTimeout(resolve, 400)); // Simulate network delay
1851
+
1852
+ const body = JSON.parse(options?.body as string || '{}');
1853
+ const newConversation = {
1854
+ id: `conv_${Date.now()}`,
1855
+ title: body.title || `Chat ${conversationStore.length + 1}`,
1856
+ messages: [],
1857
+ createdAt: new Date().toISOString(),
1858
+ updatedAt: new Date().toISOString()
1859
+ };
1860
+
1861
+ conversationStore = [newConversation, ...conversationStore];
1862
+
1863
+ return new Response(JSON.stringify(newConversation), {
1864
+ status: 201,
1865
+ headers: { 'Content-Type': 'application/json' }
1866
+ });
1867
+ }
1868
+
1869
+ // Mock: Delete conversation
1870
+ if (urlString.match(/\/api\/conversations\/[^/]+$/) && options?.method === 'DELETE') {
1871
+ const conversationId = urlString.split('/').pop();
1872
+ await new Promise(resolve => setTimeout(resolve, 300)); // Simulate network delay
1873
+
1874
+ conversationStore = conversationStore.filter(c => c.id !== conversationId);
1875
+
1876
+ return new Response(JSON.stringify({ success: true }), {
1877
+ status: 200,
1878
+ headers: { 'Content-Type': 'application/json' }
1879
+ });
1880
+ }
1881
+
1882
+ // Mock: Send message to conversation (streaming response)
1883
+ if (urlString.includes('/api/chat') && options?.method === 'POST') {
1884
+ await new Promise(resolve => setTimeout(resolve, 200));
1885
+
1886
+ const body = JSON.parse(options?.body as string || '{}');
1887
+ const userMessage = body.message || body.userMessage || body.text;
1888
+
1889
+ // Generate AI response based on keywords
1890
+ let aiResponse = 'I understand your question. Let me help you with that.';
1891
+
1892
+ if (userMessage.toLowerCase().includes('hello') || userMessage.toLowerCase().includes('hi')) {
1893
+ aiResponse = 'Hello! 👋 How can I assist you today?';
1894
+ } else if (userMessage.toLowerCase().includes('api')) {
1895
+ aiResponse = 'APIs are essential for modern web development. They allow different applications to communicate with each other. RESTful APIs are the most common, using HTTP methods like GET, POST, PUT, and DELETE.';
1896
+ } else if (userMessage.toLowerCase().includes('conversation') || userMessage.toLowerCase().includes('thread')) {
1897
+ aiResponse = 'This chatbot supports multiple conversations! You can create new threads, switch between them, and each conversation maintains its own history. Try creating a new conversation using the sidebar.';
1898
+ } else if (userMessage.toLowerCase().includes('help')) {
1899
+ aiResponse = 'I can help you with:\n• Web development questions\n• Programming best practices\n• Technology recommendations\n• Code architecture advice\n\nJust ask me anything!';
1900
+ }
1901
+
1902
+ // Stream the response
1903
+ const stream = new ReadableStream({
1904
+ async start(controller) {
1905
+ for (let i = 0; i < aiResponse.length; i++) {
1906
+ await new Promise(resolve => setTimeout(resolve, 20));
1907
+ controller.enqueue(new TextEncoder().encode(aiResponse[i]));
1908
+ }
1909
+ controller.close();
1910
+ }
1911
+ });
1912
+
1913
+ return new Response(stream, {
1914
+ status: 200,
1915
+ headers: { 'Content-Type': 'text/plain' }
1916
+ });
1917
+ }
1918
+
1919
+ // Fallback to original fetch for other requests
1920
+ return originalFetch(url, options);
1921
+ };
1922
+
1923
+ setTimeout(async () => {
1924
+ const chatbot = document.querySelector('#conversation-loading-chatbot') as any;
1925
+ if (chatbot && !chatbot.controller) {
1926
+ // Override fetch
1927
+ window.fetch = mockFetch as any;
1928
+
1929
+ const { CustomAPIProvider } = await import('./providers/custom-api-provider.js');
1930
+
1931
+ // Type definitions for API responses
1932
+ interface ConversationSummary {
1933
+ id: string;
1934
+ title: string;
1935
+ messageCount: number;
1936
+ createdAt: string;
1937
+ updatedAt: string;
1938
+ }
1939
+
1940
+ interface ConversationDetail extends ConversationSummary {
1941
+ messages: ChatbotMessage[];
1942
+ }
1943
+
1944
+ interface ConversationsListResponse {
1945
+ conversations: ConversationSummary[];
1946
+ }
1947
+
1948
+ // Extended provider with conversation loading support
1949
+ class ConversationAPIProvider extends CustomAPIProvider {
1950
+ async loadConversations(): Promise<ConversationSummary[]> {
1951
+ try {
1952
+ const response = await fetch('/api/conversations', { method: 'GET' });
1953
+ const data: ConversationsListResponse = await response.json();
1954
+ return data.conversations || [];
1955
+ } catch (error) {
1956
+ console.error('Failed to load conversations:', error);
1957
+ return [];
1958
+ }
1959
+ }
1960
+
1961
+ async loadConversation(conversationId: string): Promise<ConversationDetail | null> {
1962
+ try {
1963
+ const response = await fetch(`/api/conversations/${conversationId}`, { method: 'GET' });
1964
+ return await response.json() as ConversationDetail;
1965
+ } catch (error) {
1966
+ console.error(`Failed to load conversation ${conversationId}:`, error);
1967
+ return null;
1968
+ }
1969
+ }
1970
+
1971
+ async createConversation(title?: string): Promise<ConversationDetail | null> {
1972
+ try {
1973
+ const response = await fetch('/api/conversations', {
1974
+ method: 'POST',
1975
+ headers: { 'Content-Type': 'application/json' },
1976
+ body: JSON.stringify({ title })
1977
+ });
1978
+ return await response.json() as ConversationDetail;
1979
+ } catch (error) {
1980
+ console.error('Failed to create conversation:', error);
1981
+ return null;
1982
+ }
1983
+ }
1984
+
1985
+ async deleteConversation(conversationId: string): Promise<boolean> {
1986
+ try {
1987
+ const response = await fetch(`/api/conversations/${conversationId}`, { method: 'DELETE' });
1988
+ return response.ok;
1989
+ } catch (error) {
1990
+ console.error(`Failed to delete conversation ${conversationId}:`, error);
1991
+ return false;
1992
+ }
1993
+ }
1994
+
1995
+ buildPayload(text: string, context: any): any {
1996
+ return {
1997
+ message: text,
1998
+ conversationId: context.conversationId,
1999
+ metadata: context.metadata || {}
2000
+ };
2001
+ }
2002
+ }
2003
+
2004
+ const provider = new ConversationAPIProvider();
2005
+
2006
+ await provider.connect({
2007
+ apiUrl: '/api/chat',
2008
+ headers: {
2009
+ 'accept': 'text/plain',
2010
+ 'Content-Type': 'application/json'
2011
+ }
2012
+ });
2013
+
2014
+ // Create controller with threads enabled
2015
+ const controller = new ChatbotCoreController({
2016
+ provider,
2017
+ enableThreads: true,
2018
+ ui: {
2019
+ onStateChange: (state) => {
2020
+ chatbot.messages = state.messages;
2021
+ chatbot.threads = state.threads;
2022
+ chatbot.isBotTyping = state.isTyping;
2023
+ chatbot.chatStarted = state.messages.length > 0;
2024
+ },
2025
+ onTypingStart: () => { chatbot.isBotTyping = true; },
2026
+ onTypingEnd: () => { chatbot.isBotTyping = false; },
2027
+ focusInput: () => { chatbot.focusInput(); }
2028
+ }
2029
+ });
2030
+
2031
+ chatbot.controller = controller;
2032
+
2033
+ // Listen to thread events for debugging and state sync
2034
+ controller.on('thread:selected', (thread) => {
2035
+ console.log('Thread selected event:', thread);
2036
+ const state = controller.getState();
2037
+ console.log('Current state after selection:', {
2038
+ currentThreadId: state.currentThreadId,
2039
+ messagesCount: state.messages.length,
2040
+ threadsCount: state.threads.length
2041
+ });
2042
+ // Force update the UI
2043
+ chatbot.messages = state.messages;
2044
+ chatbot.threads = state.threads;
2045
+ chatbot.chatStarted = state.messages.length > 0;
2046
+ });
2047
+
2048
+ controller.on('thread:created', (thread) => {
2049
+ console.log('Thread created event:', thread);
2050
+ const state = controller.getState();
2051
+ chatbot.threads = state.threads;
2052
+ });
2053
+
2054
+ controller.on('thread:deleted', (threadId) => {
2055
+ console.log('Thread deleted event:', threadId);
2056
+ const state = controller.getState();
2057
+ chatbot.threads = state.threads;
2058
+ chatbot.messages = state.messages;
2059
+ chatbot.chatStarted = state.messages.length > 0;
2060
+ });
2061
+
2062
+ // Load existing conversations from API
2063
+ try {
2064
+ const conversations = await provider.loadConversations();
2065
+ console.log('Loaded conversations:', conversations);
2066
+
2067
+ // Convert API conversations to threads
2068
+ const loadedThreads: ChatbotThread[] = [];
2069
+ for (const conv of conversations) {
2070
+ const fullConversation = await provider.loadConversation(conv.id);
2071
+ if (fullConversation) {
2072
+ console.log('Loaded full conversation:', fullConversation);
2073
+ const thread: ChatbotThread = {
2074
+ id: fullConversation.id,
2075
+ title: fullConversation.title,
2076
+ messages: fullConversation.messages || [],
2077
+ createdAt: fullConversation.createdAt,
2078
+ updatedAt: fullConversation.updatedAt
2079
+ };
2080
+ loadedThreads.push(thread);
2081
+ }
2082
+ }
2083
+
2084
+ // Add all threads to controller state at once
2085
+ if (loadedThreads.length > 0) {
2086
+ console.log('Setting initial state with threads:', loadedThreads);
2087
+ const currentState = controller.getState();
2088
+ controller.setState({
2089
+ threads: loadedThreads,
2090
+ currentThreadId: loadedThreads[0].id,
2091
+ messages: [...loadedThreads[0].messages],
2092
+ isTyping: false
2093
+ });
2094
+
2095
+ console.log('State after initialization:', controller.getState());
2096
+
2097
+ // Force UI update
2098
+ chatbot.threads = loadedThreads;
2099
+ chatbot.messages = [...loadedThreads[0].messages];
2100
+ chatbot.chatStarted = loadedThreads[0].messages.length > 0;
2101
+
2102
+ console.log('UI updated - messages:', chatbot.messages.length, 'threads:', chatbot.threads.length);
2103
+ }
2104
+ } catch (error) {
2105
+ console.error('Failed to initialize conversations:', error);
2106
+ }
2107
+
2108
+ chatbot.suggestions = [
2109
+ { id: 'api', text: 'Tell me about APIs', enabled: true },
2110
+ { id: 'threads', text: 'How do conversations work?', enabled: true },
2111
+ { id: 'help', text: 'What can you help with?', enabled: true }
2112
+ ];
2113
+
2114
+ // Store cleanup function
2115
+ (window as any).__storyCleanup = () => {
2116
+ window.fetch = originalFetch;
2117
+ };
2118
+ }
2119
+ }, 0);
2120
+
2121
+ return html`
2122
+ <div style="display: flex; flex-direction: column; gap: 16px; padding: 20px; max-width: 1200px;">
2123
+ <div style="padding: 16px; background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); border-radius: 8px; box-shadow: 0 4px 12px rgba(0,0,0,0.15); color: white;">
2124
+ <h3 style="margin: 0 0 12px 0; font-size: 20px;">💬 Mock API with Conversation Loading</h3>
2125
+ <p style="margin: 0 0 12px 0; font-size: 14px; opacity: 0.95;">
2126
+ This story demonstrates loading existing conversations from a mocked API backend.
2127
+ </p>
2128
+ <div style="background: rgba(255,255,255,0.1); padding: 12px; border-radius: 6px; margin-bottom: 12px;">
2129
+ <p style="margin: 0 0 8px 0; font-weight: 600; font-size: 14px;">🔄 Mocked API Endpoints:</p>
2130
+ <ul style="margin: 0; padding-left: 20px; font-size: 13px; opacity: 0.9;">
2131
+ <li><code>GET /api/conversations</code> - Load all conversations</li>
2132
+ <li><code>GET /api/conversations/:id</code> - Load specific conversation</li>
2133
+ <li><code>POST /api/conversations</code> - Create new conversation</li>
2134
+ <li><code>DELETE /api/conversations/:id</code> - Delete conversation</li>
2135
+ <li><code>POST /api/chat</code> - Send message (streaming response)</li>
2136
+ </ul>
2137
+ </div>
2138
+ <div style="background: rgba(255,255,255,0.1); padding: 12px; border-radius: 6px;">
2139
+ <p style="margin: 0 0 8px 0; font-weight: 600; font-size: 14px;">✨ Features:</p>
2140
+ <ul style="margin: 0; padding-left: 20px; font-size: 13px; opacity: 0.9;">
2141
+ <li>3 pre-loaded conversations with message history</li>
2142
+ <li>Network delays simulated (300-500ms)</li>
2143
+ <li>Create new conversations via the sidebar</li>
2144
+ <li>Switch between conversations seamlessly</li>
2145
+ <li>Delete conversations (with API sync)</li>
2146
+ <li>Streaming AI responses</li>
2147
+ </ul>
2148
+ </div>
2149
+ </div>
2150
+ <div style="width: 100%; height: 700px; border: 1px solid #dee2e6; border-radius: 8px; overflow: hidden; box-shadow: 0 2px 8px rgba(0,0,0,0.1);">
2151
+ <nr-chatbot
2152
+ id="conversation-loading-chatbot"
2153
+ .size=${args.size}
2154
+ .variant=${args.variant}
2155
+ .showSendButton=${true}
2156
+ .autoScroll=${true}
2157
+ .showThreads=${true}
2158
+ .boxed=${true}
2159
+ ></nr-chatbot>
2160
+ </div>
2161
+ </div>
2162
+ `;
2163
+ }
2164
+ };
2165
+
2166
+ /**
2167
+ * Auto-Loading Conversations with Custom Provider
2168
+ * Demonstrates automatic conversation loading when extending CustomAPIProvider.
2169
+ * The controller automatically calls loadConversations() when the provider connects,
2170
+ * eliminating the need for manual initialization code.
2171
+ */
2172
+ export const AutoLoadingConversations: Story = {
2173
+ args: {
2174
+ ...Default.args,
2175
+ showThreads: true
2176
+ },
2177
+ render: (args) => {
2178
+ const originalFetch = window.fetch;
2179
+
2180
+ // Mock conversation data store
2181
+ let conversationStore = [
2182
+ {
2183
+ id: 'auto_conv_1',
2184
+ title: '✈️ Flight Booking',
2185
+ messages: [
2186
+ {
2187
+ id: 'auto_msg_1',
2188
+ text: 'I need to book a flight from New York to London',
2189
+ sender: 'user' as ChatbotSender,
2190
+ timestamp: new Date(Date.now() - 3600000).toISOString()
2191
+ },
2192
+ {
2193
+ id: 'auto_msg_2',
2194
+ text: 'I found some great flight options for you:\n\n[FLIGHT]{\n "flightNumber": "BA117",\n "airline": "British Airways",\n "origin": "JFK",\n "destination": "LHR",\n "departureTime": "6:30 PM",\n "arrivalTime": "6:45 AM",\n "departureDate": "Mar 15, 2024",\n "arrivalDate": "Mar 16, 2024",\n "duration": "7h 15min",\n "terminal": "7",\n "gate": "B32",\n "arrivalTerminal": "5",\n "arrivalGate": "A18"\n}[/FLIGHT]\n\nThis is a direct flight with excellent reviews! Would you like to see more options?',
2195
+ sender: 'bot' as ChatbotSender,
2196
+ timestamp: new Date(Date.now() - 3590000).toISOString()
2197
+ },
2198
+ {
2199
+ id: 'auto_msg_3',
2200
+ text: 'Perfect! Can you show me a business class option?',
2201
+ sender: 'user' as ChatbotSender,
2202
+ timestamp: new Date(Date.now() - 3580000).toISOString()
2203
+ },
2204
+ {
2205
+ id: 'auto_msg_4',
2206
+ text: 'Here\'s a premium business class option:\n\n[FLIGHT]{\n "flightNumber": "VS4",\n "airline": "Virgin Atlantic",\n "origin": "JFK",\n "destination": "LHR",\n "departureTime": "8:00 PM",\n "arrivalTime": "8:15 AM",\n "departureDate": "Mar 15, 2024",\n "arrivalDate": "Mar 16, 2024",\n "duration": "7h 15min",\n "terminal": "4",\n "gate": "B24",\n "arrivalTerminal": "3",\n "arrivalGate": "A10",\n "status": "On Time"\n}[/FLIGHT]\n\nThis includes lie-flat seats, premium dining, priority boarding, and access to the Clubhouse lounge!',
2207
+ sender: 'bot' as ChatbotSender,
2208
+ timestamp: new Date(Date.now() - 3570000).toISOString()
2209
+ }
2210
+ ],
2211
+ createdAt: new Date(Date.now() - 3600000).toISOString(),
2212
+ updatedAt: new Date(Date.now() - 3570000).toISOString()
2213
+ },
2214
+ {
2215
+ id: 'auto_conv_2',
2216
+ title: '🚀 Project Setup Guide',
2217
+ messages: [
2218
+ {
2219
+ id: 'auto_msg_5',
2220
+ text: 'How do I set up a new React project?',
2221
+ sender: 'user' as ChatbotSender,
2222
+ timestamp: new Date(Date.now() - 7200000).toISOString()
2223
+ },
2224
+ {
2225
+ id: 'auto_msg_6',
2226
+ text: 'Here\'s a quick guide to set up a React project:\n\n1. **Using Create React App:**\n```bash\nnpx create-react-app my-app\ncd my-app\nnpm start\n```\n\n2. **Using Vite (faster):**\n```bash\nnpm create vite@latest my-app -- --template react\ncd my-app\nnpm install\nnpm run dev\n```\n\nVite is recommended for new projects due to faster build times!',
2227
+ sender: 'bot' as ChatbotSender,
2228
+ timestamp: new Date(Date.now() - 7190000).toISOString()
2229
+ }
2230
+ ],
2231
+ createdAt: new Date(Date.now() - 7200000).toISOString(),
2232
+ updatedAt: new Date(Date.now() - 7190000).toISOString()
2233
+ },
2234
+ {
2235
+ id: 'auto_conv_3',
2236
+ title: '💡 TypeScript Best Practices',
2237
+ messages: [
2238
+ {
2239
+ id: 'auto_msg_7',
2240
+ text: 'What are some TypeScript best practices?',
2241
+ sender: 'user' as ChatbotSender,
2242
+ timestamp: new Date(Date.now() - 86400000).toISOString()
2243
+ },
2244
+ {
2245
+ id: 'auto_msg_8',
2246
+ text: 'Here are key TypeScript best practices:\n\n✅ **Enable strict mode** in tsconfig.json\n✅ **Use interfaces** for object shapes\n✅ **Avoid "any" type** - use unknown or proper types\n✅ **Leverage utility types** (Partial, Pick, Omit, etc.)\n✅ **Use type guards** for runtime type checking\n✅ **Document with JSDoc** for better IDE support\n\nThese practices will make your code more maintainable and catch bugs early!',
2247
+ sender: 'bot' as ChatbotSender,
2248
+ timestamp: new Date(Date.now() - 86390000).toISOString()
2249
+ }
2250
+ ],
2251
+ createdAt: new Date(Date.now() - 86400000).toISOString(),
2252
+ updatedAt: new Date(Date.now() - 86390000).toISOString()
2253
+ },
2254
+ {
2255
+ id: 'auto_conv_4',
2256
+ title: '🎨 CSS Architecture',
2257
+ messages: [
2258
+ {
2259
+ id: 'auto_msg_9',
2260
+ text: 'How should I organize my CSS in a large project?',
2261
+ sender: 'user' as ChatbotSender,
2262
+ timestamp: new Date(Date.now() - 172800000).toISOString()
2263
+ },
2264
+ {
2265
+ id: 'auto_msg_10',
2266
+ text: 'For large projects, consider these CSS organization strategies:\n\n**1. CSS Modules:**\n- Scoped styles per component\n- Prevents naming conflicts\n\n**2. CSS-in-JS:**\n- Styled Components\n- Emotion\n- Dynamic theming\n\n**3. Utility-First:**\n- Tailwind CSS\n- Rapid development\n\n**4. BEM Methodology:**\n- Block__Element--Modifier\n- Clear naming conventions\n\nChoose based on your team\'s preferences and project requirements!',
2267
+ sender: 'bot' as ChatbotSender,
2268
+ timestamp: new Date(Date.now() - 172790000).toISOString()
2269
+ }
2270
+ ],
2271
+ createdAt: new Date(Date.now() - 172800000).toISOString(),
2272
+ updatedAt: new Date(Date.now() - 172790000).toISOString()
2273
+ }
2274
+ ];
2275
+
2276
+ // Mock fetch to intercept API calls
2277
+ const mockFetch = async (url: string | URL | Request, options?: RequestInit) => {
2278
+ const urlString = typeof url === 'string' ? url : url instanceof URL ? url.toString() : url.url;
2279
+
2280
+ // Mock: Load specific conversation
2281
+ if (urlString.match(/\/api\/conversations\/[^/?]+$/) && (!options?.method || options?.method === 'GET')) {
2282
+ const conversationId = urlString.split('/').pop();
2283
+ const conversation = conversationStore.find(c => c.id === conversationId);
2284
+
2285
+ await new Promise(resolve => setTimeout(resolve, 200));
2286
+
2287
+ if (conversation) {
2288
+ return new Response(JSON.stringify(conversation), {
2289
+ status: 200,
2290
+ headers: { 'Content-Type': 'application/json' }
2291
+ });
2292
+ } else {
2293
+ return new Response(JSON.stringify({ error: 'Conversation not found' }), {
2294
+ status: 404,
2295
+ headers: { 'Content-Type': 'application/json' }
2296
+ });
2297
+ }
2298
+ }
2299
+
2300
+ // Mock: Load conversations list
2301
+ if (urlString.includes('/api/conversations') && (!options?.method || options?.method === 'GET')) {
2302
+ await new Promise(resolve => setTimeout(resolve, 300));
2303
+ return new Response(JSON.stringify({
2304
+ conversations: conversationStore.map(c => ({
2305
+ id: c.id,
2306
+ title: c.title,
2307
+ messageCount: c.messages.length,
2308
+ createdAt: c.createdAt,
2309
+ updatedAt: c.updatedAt
2310
+ }))
2311
+ }), {
2312
+ status: 200,
2313
+ headers: { 'Content-Type': 'application/json' }
2314
+ });
2315
+ }
2316
+
2317
+ // Mock: Create new conversation
2318
+ if (urlString.includes('/api/conversations') && options?.method === 'POST') {
2319
+ await new Promise(resolve => setTimeout(resolve, 250));
2320
+
2321
+ const body = JSON.parse(options?.body as string || '{}');
2322
+ const newConversation = {
2323
+ id: `auto_conv_${Date.now()}`,
2324
+ title: body.title || `New Chat ${conversationStore.length + 1}`,
2325
+ messages: [],
2326
+ createdAt: new Date().toISOString(),
2327
+ updatedAt: new Date().toISOString()
2328
+ };
2329
+
2330
+ conversationStore = [newConversation, ...conversationStore];
2331
+
2332
+ return new Response(JSON.stringify(newConversation), {
2333
+ status: 201,
2334
+ headers: { 'Content-Type': 'application/json' }
2335
+ });
2336
+ }
2337
+
2338
+ // Mock: Delete conversation
2339
+ if (urlString.match(/\/api\/conversations\/[^/]+$/) && options?.method === 'DELETE') {
2340
+ const conversationId = urlString.split('/').pop();
2341
+ await new Promise(resolve => setTimeout(resolve, 200));
2342
+
2343
+ conversationStore = conversationStore.filter(c => c.id !== conversationId);
2344
+
2345
+ return new Response(JSON.stringify({ success: true }), {
2346
+ status: 200,
2347
+ headers: { 'Content-Type': 'application/json' }
2348
+ });
2349
+ }
2350
+
2351
+ // Mock: Send message (streaming response)
2352
+ if (urlString.includes('/api/chat') && options?.method === 'POST') {
2353
+ await new Promise(resolve => setTimeout(resolve, 150));
2354
+
2355
+ const body = JSON.parse(options?.body as string || '{}');
2356
+ const userMessage = body.userMessage || body.message || '';
2357
+
2358
+ let aiResponse = 'Thanks for your question! ';
2359
+
2360
+ if (userMessage.toLowerCase().includes('hello') || userMessage.toLowerCase().includes('hi')) {
2361
+ aiResponse += 'Hello! How can I help you today with your development questions?';
2362
+ } else if (userMessage.toLowerCase().includes('help')) {
2363
+ aiResponse += 'I can assist you with:\n• Programming concepts\n• Framework recommendations\n• Best practices\n• Code architecture\n\nWhat would you like to know?';
2364
+ } else {
2365
+ aiResponse += 'That\'s an interesting question! Let me help you with that...';
2366
+ }
2367
+
2368
+ const stream = new ReadableStream({
2369
+ async start(controller) {
2370
+ for (let i = 0; i < aiResponse.length; i++) {
2371
+ await new Promise(resolve => setTimeout(resolve, 15));
2372
+ controller.enqueue(new TextEncoder().encode(aiResponse[i]));
2373
+ }
2374
+ controller.close();
2375
+ }
2376
+ });
2377
+
2378
+ return new Response(stream, {
2379
+ status: 200,
2380
+ headers: { 'Content-Type': 'text/plain' }
2381
+ });
2382
+ }
2383
+
2384
+ return originalFetch(url, options);
2385
+ };
2386
+
2387
+ setTimeout(async () => {
2388
+ const chatbot = document.querySelector('#auto-loading-chatbot') as any;
2389
+ if (chatbot && !chatbot.controller) {
2390
+ // Override fetch
2391
+ window.fetch = mockFetch as any;
2392
+
2393
+ const { CustomAPIProvider } = await import('./providers/custom-api-provider.js');
2394
+ const { ChatbotCoreController } = await import('./core/chatbot-core.controller.js');
2395
+ const { FlightCardPlugin } = await import('./plugins/flight-card-plugin.js');
2396
+
2397
+ // Extended provider with auto-loading support
2398
+ class AutoLoadingProvider extends CustomAPIProvider {
2399
+ async loadConversations(): Promise<Array<{id: string, title: string, createdAt: string, updatedAt: string}>> {
2400
+ console.log('[AutoLoadingProvider] loadConversations() called automatically!');
2401
+ try {
2402
+ const response = await fetch('/api/conversations', { method: 'GET' });
2403
+ const data = await response.json();
2404
+ console.log('[AutoLoadingProvider] Loaded conversation summaries:', data.conversations);
2405
+ return data.conversations || [];
2406
+ } catch (error) {
2407
+ console.error('[AutoLoadingProvider] Failed to load conversations:', error);
2408
+ return [];
2409
+ }
2410
+ }
2411
+
2412
+ async loadConversation(conversationId: string): Promise<any> {
2413
+ console.log(`[AutoLoadingProvider] loadConversation(${conversationId}) called automatically!`);
2414
+ try {
2415
+ const response = await fetch(`/api/conversations/${conversationId}`, { method: 'GET' });
2416
+ const data = await response.json();
2417
+ console.log(`[AutoLoadingProvider] Loaded full conversation ${conversationId}:`, data);
2418
+ return data;
2419
+ } catch (error) {
2420
+ console.error(`[AutoLoadingProvider] Failed to load conversation ${conversationId}:`, error);
2421
+ return null;
2422
+ }
2423
+ }
2424
+
2425
+ buildPayload(text: string, context: any): any {
2426
+ return {
2427
+ userMessage: text,
2428
+ conversationId: context.currentThread?.id,
2429
+ metadata: context.metadata || {}
2430
+ };
2431
+ }
2432
+ }
2433
+
2434
+ const provider = new AutoLoadingProvider();
2435
+
2436
+ console.log('[Story] Connecting provider...');
2437
+ await provider.connect({
2438
+ apiUrl: '/api/chat',
2439
+ headers: {
2440
+ 'accept': 'text/plain',
2441
+ 'Content-Type': 'application/json'
2442
+ }
2443
+ });
2444
+ console.log('[Story] Provider connected!');
2445
+
2446
+ // Create controller - conversations will load automatically!
2447
+ console.log('[Story] Creating ChatbotCoreController...');
2448
+ const controller = new ChatbotCoreController({
2449
+ provider,
2450
+ enableThreads: true,
2451
+ debug: true, // Enable debug logging to see auto-load process
2452
+ plugins: [new FlightCardPlugin()], // Add flight card plugin for HTML rendering
2453
+ ui: {
2454
+ onStateChange: (state) => {
2455
+ console.log('[UI] State changed:', {
2456
+ threadsCount: state.threads.length,
2457
+ messagesCount: state.messages.length,
2458
+ currentThreadId: state.currentThreadId
2459
+ });
2460
+ chatbot.messages = state.messages;
2461
+ chatbot.threads = state.threads;
2462
+ chatbot.isBotTyping = state.isTyping;
2463
+ chatbot.chatStarted = state.messages.length > 0;
2464
+ },
2465
+ onTypingStart: () => { chatbot.isBotTyping = true; },
2466
+ onTypingEnd: () => { chatbot.isBotTyping = false; },
2467
+ focusInput: () => { chatbot.focusInput(); }
2468
+ }
2469
+ });
2470
+
2471
+ chatbot.controller = controller;
2472
+
2473
+ // Note: No manual conversation loading code needed!
2474
+ // The controller automatically calls provider.loadConversations() on connect
2475
+
2476
+ chatbot.suggestions = [
2477
+ { id: 'react', text: '⚛️ React tips', enabled: true },
2478
+ { id: 'typescript', text: '📘 TypeScript help', enabled: true },
2479
+ { id: 'css', text: '🎨 CSS advice', enabled: true }
2480
+ ];
2481
+
2482
+ // Cleanup
2483
+ (window as any).__storyCleanup = () => {
2484
+ window.fetch = originalFetch;
2485
+ };
2486
+ }
2487
+ }, 0);
2488
+
2489
+ return html`
2490
+ <div style="display: flex; flex-direction: column; gap: 16px; padding: 20px; max-width: 1200px;">
2491
+ <div style="padding: 20px; background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); border-radius: 12px; box-shadow: 0 4px 20px rgba(102,126,234,0.4); color: white;">
2492
+ <h3 style="margin: 0 0 16px 0; font-size: 24px; font-weight: 600;">✨ Auto-Loading Conversations Demo</h3>
2493
+ <p style="margin: 0 0 16px 0; font-size: 15px; line-height: 1.6; opacity: 0.95;">
2494
+ This story demonstrates the <strong>automatic conversation loading</strong> feature.
2495
+ When you extend <code style="background: rgba(255,255,255,0.2); padding: 2px 6px; border-radius: 4px;">CustomAPIProvider</code>
2496
+ and implement <code style="background: rgba(255,255,255,0.2); padding: 2px 6px; border-radius: 4px;">loadConversations()</code>,
2497
+ the controller automatically loads existing conversations when the provider connects!
2498
+ </p>
2499
+
2500
+ <div style="background: rgba(255,255,255,0.15); padding: 16px; border-radius: 8px; margin-bottom: 16px;">
2501
+ <p style="margin: 0 0 12px 0; font-weight: 600; font-size: 15px;">🔄 How it works:</p>
2502
+ <ol style="margin: 0; padding-left: 24px; font-size: 14px; line-height: 1.8; opacity: 0.95;">
2503
+ <li>Provider connects via <code style="background: rgba(255,255,255,0.2); padding: 2px 6px; border-radius: 4px;">provider.connect()</code></li>
2504
+ <li>Controller detects <code style="background: rgba(255,255,255,0.2); padding: 2px 6px; border-radius: 4px;">loadConversations()</code> method</li>
2505
+ <li>Automatically calls it to fetch conversation list</li>
2506
+ <li>Loads full details for each conversation</li>
2507
+ <li><strong>Processes messages through plugins</strong> (e.g., renders flight cards)</li>
2508
+ <li>Updates UI with loaded threads - <strong>no manual code needed!</strong></li>
2509
+ </ol>
2510
+ </div>
2511
+
2512
+ <div style="background: rgba(255,255,255,0.15); padding: 16px; border-radius: 8px;">
2513
+ <p style="margin: 0 0 12px 0; font-weight: 600; font-size: 15px;">📋 Pre-loaded conversations:</p>
2514
+ <ul style="margin: 0; padding-left: 24px; font-size: 14px; line-height: 1.8; opacity: 0.95;">
2515
+ <li>✈️ <strong>Flight Booking</strong> - Demonstrates HTML rendering with flight cards</li>
2516
+ <li>🚀 Project Setup Guide</li>
2517
+ <li>💡 TypeScript Best Practices</li>
2518
+ <li>🎨 CSS Architecture</li>
2519
+ </ul>
2520
+ </div>
2521
+
2522
+ <div style="background: rgba(46,213,115,0.2); padding: 12px; border-radius: 6px; margin-top: 16px; border-left: 4px solid #2ed573;">
2523
+ <p style="margin: 0; font-size: 13px; line-height: 1.6;">
2524
+ <strong>💡 Tip:</strong> Click on the "Flight Booking" conversation to see rich HTML cards automatically rendered from loaded messages!
2525
+ </p>
2526
+ </div>
2527
+
2528
+ <div style="background: rgba(255,193,7,0.2); padding: 12px; border-radius: 6px; margin-top: 12px; border-left: 4px solid #ffc107;">
2529
+ <p style="margin: 0; font-size: 13px; line-height: 1.6;">
2530
+ <strong>🔍 Debug:</strong> Open the browser console to see the auto-loading process and plugin rendering in action!
2531
+ </p>
2532
+ </div>
2533
+ </div>
2534
+
2535
+ <div style="width: 100%; height: 700px; border: 1px solid #dee2e6; border-radius: 12px; overflow: hidden; box-shadow: 0 4px 16px rgba(0,0,0,0.1);">
2536
+ <nr-chatbot
2537
+ id="auto-loading-chatbot"
2538
+ .size=${args.size}
2539
+ .variant=${args.variant}
2540
+ .showSendButton=${true}
2541
+ .autoScroll=${true}
2542
+ .showThreads=${true}
2543
+ .boxed=${true}
2544
+ ></nr-chatbot>
2545
+ </div>
2546
+ </div>
2547
+ `;
2548
+ }
2549
+ };