@inorain_development/hotel-smarters-chat-ui 1.0.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 (241) hide show
  1. package/README.md +110 -0
  2. package/lib/commonjs/features/chat/components/common/cart-icon.native.js +36 -0
  3. package/lib/commonjs/features/chat/components/common/cart-icon.native.js.map +1 -0
  4. package/lib/commonjs/features/chat/components/common/collapsible.js +20 -0
  5. package/lib/commonjs/features/chat/components/common/collapsible.js.map +1 -0
  6. package/lib/commonjs/features/chat/components/common/collapsible.native.js +38 -0
  7. package/lib/commonjs/features/chat/components/common/collapsible.native.js.map +1 -0
  8. package/lib/commonjs/features/chat/components/product/index.js +13 -0
  9. package/lib/commonjs/features/chat/components/product/index.js.map +1 -0
  10. package/lib/commonjs/features/chat/components/product/product.js +83 -0
  11. package/lib/commonjs/features/chat/components/product/product.js.map +1 -0
  12. package/lib/commonjs/features/chat/components/product/product.model.js +6 -0
  13. package/lib/commonjs/features/chat/components/product/product.model.js.map +1 -0
  14. package/lib/commonjs/features/chat/components/product/product.native.js +125 -0
  15. package/lib/commonjs/features/chat/components/product/product.native.js.map +1 -0
  16. package/lib/commonjs/features/chat/components/service/index.js +13 -0
  17. package/lib/commonjs/features/chat/components/service/index.js.map +1 -0
  18. package/lib/commonjs/features/chat/components/service/service.js +83 -0
  19. package/lib/commonjs/features/chat/components/service/service.js.map +1 -0
  20. package/lib/commonjs/features/chat/components/service/service.model.js +6 -0
  21. package/lib/commonjs/features/chat/components/service/service.model.js.map +1 -0
  22. package/lib/commonjs/features/chat/components/service/service.native.js +106 -0
  23. package/lib/commonjs/features/chat/components/service/service.native.js.map +1 -0
  24. package/lib/commonjs/features/chat/index.d.js +6 -0
  25. package/lib/commonjs/features/chat/index.d.js.map +1 -0
  26. package/lib/commonjs/features/chat/index.d.ts.map +1 -0
  27. package/lib/commonjs/features/chat/index.js +46 -0
  28. package/lib/commonjs/features/chat/index.js.map +1 -0
  29. package/lib/commonjs/features/chat/model/chat.model.js +23 -0
  30. package/lib/commonjs/features/chat/model/chat.model.js.map +1 -0
  31. package/lib/commonjs/features/chat/renderer/index.js +13 -0
  32. package/lib/commonjs/features/chat/renderer/index.js.map +1 -0
  33. package/lib/commonjs/features/chat/renderer/renderer.js +32 -0
  34. package/lib/commonjs/features/chat/renderer/renderer.js.map +1 -0
  35. package/lib/commonjs/features/chat/renderer/renderer.native.js +32 -0
  36. package/lib/commonjs/features/chat/renderer/renderer.native.js.map +1 -0
  37. package/lib/commonjs/index.d.js +17 -0
  38. package/lib/commonjs/index.d.js.map +1 -0
  39. package/lib/commonjs/index.d.ts.map +1 -0
  40. package/lib/commonjs/index.js +17 -0
  41. package/lib/commonjs/index.js.map +1 -0
  42. package/lib/commonjs/native.d.js +6 -0
  43. package/lib/commonjs/native.d.js.map +1 -0
  44. package/lib/commonjs/native.d.ts.map +1 -0
  45. package/lib/commonjs/native.js +46 -0
  46. package/lib/commonjs/native.js.map +1 -0
  47. package/lib/commonjs/package.json +1 -0
  48. package/lib/commonjs/styles/global.css +3 -0
  49. package/lib/commonjs/utils/i18n.utils.js +12 -0
  50. package/lib/commonjs/utils/i18n.utils.js.map +1 -0
  51. package/lib/commonjs/utils/theme.utils.js +37 -0
  52. package/lib/commonjs/utils/theme.utils.js.map +1 -0
  53. package/lib/commonjs/utils/use-expandable-list.js +23 -0
  54. package/lib/commonjs/utils/use-expandable-list.js.map +1 -0
  55. package/lib/commonjs/web.d.js +6 -0
  56. package/lib/commonjs/web.d.js.map +1 -0
  57. package/lib/commonjs/web.d.ts.map +1 -0
  58. package/lib/commonjs/web.js +46 -0
  59. package/lib/commonjs/web.js.map +1 -0
  60. package/lib/module/features/chat/components/common/cart-icon.native.js +32 -0
  61. package/lib/module/features/chat/components/common/cart-icon.native.js.map +1 -0
  62. package/lib/module/features/chat/components/common/collapsible.js +16 -0
  63. package/lib/module/features/chat/components/common/collapsible.js.map +1 -0
  64. package/lib/module/features/chat/components/common/collapsible.native.js +34 -0
  65. package/lib/module/features/chat/components/common/collapsible.native.js.map +1 -0
  66. package/lib/module/features/chat/components/product/index.js +4 -0
  67. package/lib/module/features/chat/components/product/index.js.map +1 -0
  68. package/lib/module/features/chat/components/product/product.js +79 -0
  69. package/lib/module/features/chat/components/product/product.js.map +1 -0
  70. package/lib/module/features/chat/components/product/product.model.js +4 -0
  71. package/lib/module/features/chat/components/product/product.model.js.map +1 -0
  72. package/lib/module/features/chat/components/product/product.native.js +121 -0
  73. package/lib/module/features/chat/components/product/product.native.js.map +1 -0
  74. package/lib/module/features/chat/components/service/index.js +4 -0
  75. package/lib/module/features/chat/components/service/index.js.map +1 -0
  76. package/lib/module/features/chat/components/service/service.js +79 -0
  77. package/lib/module/features/chat/components/service/service.js.map +1 -0
  78. package/lib/module/features/chat/components/service/service.model.js +4 -0
  79. package/lib/module/features/chat/components/service/service.model.js.map +1 -0
  80. package/lib/module/features/chat/components/service/service.native.js +102 -0
  81. package/lib/module/features/chat/components/service/service.native.js.map +1 -0
  82. package/lib/module/features/chat/index.d.js +10 -0
  83. package/lib/module/features/chat/index.d.js.map +1 -0
  84. package/lib/module/features/chat/index.d.ts.map +1 -0
  85. package/lib/module/features/chat/index.js +7 -0
  86. package/lib/module/features/chat/index.js.map +1 -0
  87. package/lib/module/features/chat/model/chat.model.js +19 -0
  88. package/lib/module/features/chat/model/chat.model.js.map +1 -0
  89. package/lib/module/features/chat/renderer/index.js +4 -0
  90. package/lib/module/features/chat/renderer/index.js.map +1 -0
  91. package/lib/module/features/chat/renderer/renderer.js +28 -0
  92. package/lib/module/features/chat/renderer/renderer.js.map +1 -0
  93. package/lib/module/features/chat/renderer/renderer.native.js +28 -0
  94. package/lib/module/features/chat/renderer/renderer.native.js.map +1 -0
  95. package/lib/module/index.d.js +13 -0
  96. package/lib/module/index.d.js.map +1 -0
  97. package/lib/module/index.d.ts.map +1 -0
  98. package/lib/module/index.js +13 -0
  99. package/lib/module/index.js.map +1 -0
  100. package/lib/module/native.d.js +11 -0
  101. package/lib/module/native.d.js.map +1 -0
  102. package/lib/module/native.d.ts.map +1 -0
  103. package/lib/module/native.js +7 -0
  104. package/lib/module/native.js.map +1 -0
  105. package/lib/module/package.json +1 -0
  106. package/lib/module/styles/global.css +3 -0
  107. package/lib/module/utils/i18n.utils.js +8 -0
  108. package/lib/module/utils/i18n.utils.js.map +1 -0
  109. package/lib/module/utils/theme.utils.js +33 -0
  110. package/lib/module/utils/theme.utils.js.map +1 -0
  111. package/lib/module/utils/use-expandable-list.js +19 -0
  112. package/lib/module/utils/use-expandable-list.js.map +1 -0
  113. package/lib/module/web.d.js +10 -0
  114. package/lib/module/web.d.js.map +1 -0
  115. package/lib/module/web.d.ts.map +1 -0
  116. package/lib/module/web.js +7 -0
  117. package/lib/module/web.js.map +1 -0
  118. package/lib/typescript/commonjs/features/chat/components/common/cart-icon.native.d.ts +6 -0
  119. package/lib/typescript/commonjs/features/chat/components/common/cart-icon.native.d.ts.map +1 -0
  120. package/lib/typescript/commonjs/features/chat/components/common/collapsible.d.ts +6 -0
  121. package/lib/typescript/commonjs/features/chat/components/common/collapsible.d.ts.map +1 -0
  122. package/lib/typescript/commonjs/features/chat/components/common/collapsible.native.d.ts +6 -0
  123. package/lib/typescript/commonjs/features/chat/components/common/collapsible.native.d.ts.map +1 -0
  124. package/lib/typescript/commonjs/features/chat/components/product/index.d.ts +3 -0
  125. package/lib/typescript/commonjs/features/chat/components/product/index.d.ts.map +1 -0
  126. package/lib/typescript/commonjs/features/chat/components/product/product.d.ts +4 -0
  127. package/lib/typescript/commonjs/features/chat/components/product/product.d.ts.map +1 -0
  128. package/lib/typescript/commonjs/features/chat/components/product/product.model.d.ts +10 -0
  129. package/lib/typescript/commonjs/features/chat/components/product/product.model.d.ts.map +1 -0
  130. package/lib/typescript/commonjs/features/chat/components/product/product.native.d.ts +4 -0
  131. package/lib/typescript/commonjs/features/chat/components/product/product.native.d.ts.map +1 -0
  132. package/lib/typescript/commonjs/features/chat/components/service/index.d.ts +3 -0
  133. package/lib/typescript/commonjs/features/chat/components/service/index.d.ts.map +1 -0
  134. package/lib/typescript/commonjs/features/chat/components/service/service.d.ts +4 -0
  135. package/lib/typescript/commonjs/features/chat/components/service/service.d.ts.map +1 -0
  136. package/lib/typescript/commonjs/features/chat/components/service/service.model.d.ts +10 -0
  137. package/lib/typescript/commonjs/features/chat/components/service/service.model.d.ts.map +1 -0
  138. package/lib/typescript/commonjs/features/chat/components/service/service.native.d.ts +4 -0
  139. package/lib/typescript/commonjs/features/chat/components/service/service.native.d.ts.map +1 -0
  140. package/lib/typescript/commonjs/features/chat/index.d.ts +8 -0
  141. package/lib/typescript/commonjs/features/chat/index.d.ts.map +1 -0
  142. package/lib/typescript/commonjs/features/chat/model/chat.model.d.ts +31 -0
  143. package/lib/typescript/commonjs/features/chat/model/chat.model.d.ts.map +1 -0
  144. package/lib/typescript/commonjs/features/chat/renderer/index.d.ts +2 -0
  145. package/lib/typescript/commonjs/features/chat/renderer/index.d.ts.map +1 -0
  146. package/lib/typescript/commonjs/features/chat/renderer/renderer.d.ts +5 -0
  147. package/lib/typescript/commonjs/features/chat/renderer/renderer.d.ts.map +1 -0
  148. package/lib/typescript/commonjs/features/chat/renderer/renderer.native.d.ts +5 -0
  149. package/lib/typescript/commonjs/features/chat/renderer/renderer.native.d.ts.map +1 -0
  150. package/lib/typescript/commonjs/index.d.ts +11 -0
  151. package/lib/typescript/commonjs/index.d.ts.map +1 -0
  152. package/lib/typescript/commonjs/native.d.ts +8 -0
  153. package/lib/typescript/commonjs/native.d.ts.map +1 -0
  154. package/lib/typescript/commonjs/package.json +1 -0
  155. package/lib/typescript/commonjs/utils/i18n.utils.d.ts +3 -0
  156. package/lib/typescript/commonjs/utils/i18n.utils.d.ts.map +1 -0
  157. package/lib/typescript/commonjs/utils/theme.utils.d.ts +16 -0
  158. package/lib/typescript/commonjs/utils/theme.utils.d.ts.map +1 -0
  159. package/lib/typescript/commonjs/utils/use-expandable-list.d.ts +8 -0
  160. package/lib/typescript/commonjs/utils/use-expandable-list.d.ts.map +1 -0
  161. package/lib/typescript/commonjs/web.d.ts +8 -0
  162. package/lib/typescript/commonjs/web.d.ts.map +1 -0
  163. package/lib/typescript/module/features/chat/components/common/cart-icon.native.d.ts +6 -0
  164. package/lib/typescript/module/features/chat/components/common/cart-icon.native.d.ts.map +1 -0
  165. package/lib/typescript/module/features/chat/components/common/collapsible.d.ts +6 -0
  166. package/lib/typescript/module/features/chat/components/common/collapsible.d.ts.map +1 -0
  167. package/lib/typescript/module/features/chat/components/common/collapsible.native.d.ts +6 -0
  168. package/lib/typescript/module/features/chat/components/common/collapsible.native.d.ts.map +1 -0
  169. package/lib/typescript/module/features/chat/components/product/index.d.ts +3 -0
  170. package/lib/typescript/module/features/chat/components/product/index.d.ts.map +1 -0
  171. package/lib/typescript/module/features/chat/components/product/product.d.ts +4 -0
  172. package/lib/typescript/module/features/chat/components/product/product.d.ts.map +1 -0
  173. package/lib/typescript/module/features/chat/components/product/product.model.d.ts +10 -0
  174. package/lib/typescript/module/features/chat/components/product/product.model.d.ts.map +1 -0
  175. package/lib/typescript/module/features/chat/components/product/product.native.d.ts +4 -0
  176. package/lib/typescript/module/features/chat/components/product/product.native.d.ts.map +1 -0
  177. package/lib/typescript/module/features/chat/components/service/index.d.ts +3 -0
  178. package/lib/typescript/module/features/chat/components/service/index.d.ts.map +1 -0
  179. package/lib/typescript/module/features/chat/components/service/service.d.ts +4 -0
  180. package/lib/typescript/module/features/chat/components/service/service.d.ts.map +1 -0
  181. package/lib/typescript/module/features/chat/components/service/service.model.d.ts +10 -0
  182. package/lib/typescript/module/features/chat/components/service/service.model.d.ts.map +1 -0
  183. package/lib/typescript/module/features/chat/components/service/service.native.d.ts +4 -0
  184. package/lib/typescript/module/features/chat/components/service/service.native.d.ts.map +1 -0
  185. package/lib/typescript/module/features/chat/index.d.ts +8 -0
  186. package/lib/typescript/module/features/chat/index.d.ts.map +1 -0
  187. package/lib/typescript/module/features/chat/model/chat.model.d.ts +31 -0
  188. package/lib/typescript/module/features/chat/model/chat.model.d.ts.map +1 -0
  189. package/lib/typescript/module/features/chat/renderer/index.d.ts +2 -0
  190. package/lib/typescript/module/features/chat/renderer/index.d.ts.map +1 -0
  191. package/lib/typescript/module/features/chat/renderer/renderer.d.ts +5 -0
  192. package/lib/typescript/module/features/chat/renderer/renderer.d.ts.map +1 -0
  193. package/lib/typescript/module/features/chat/renderer/renderer.native.d.ts +5 -0
  194. package/lib/typescript/module/features/chat/renderer/renderer.native.d.ts.map +1 -0
  195. package/lib/typescript/module/index.d.ts +11 -0
  196. package/lib/typescript/module/index.d.ts.map +1 -0
  197. package/lib/typescript/module/native.d.ts +8 -0
  198. package/lib/typescript/module/native.d.ts.map +1 -0
  199. package/lib/typescript/module/package.json +1 -0
  200. package/lib/typescript/module/utils/i18n.utils.d.ts +3 -0
  201. package/lib/typescript/module/utils/i18n.utils.d.ts.map +1 -0
  202. package/lib/typescript/module/utils/theme.utils.d.ts +16 -0
  203. package/lib/typescript/module/utils/theme.utils.d.ts.map +1 -0
  204. package/lib/typescript/module/utils/use-expandable-list.d.ts +8 -0
  205. package/lib/typescript/module/utils/use-expandable-list.d.ts.map +1 -0
  206. package/lib/typescript/module/web.d.ts +8 -0
  207. package/lib/typescript/module/web.d.ts.map +1 -0
  208. package/nativewind-env.d.ts +1 -0
  209. package/package.json +142 -0
  210. package/src/features/chat/components/common/cart-icon.native.tsx +20 -0
  211. package/src/features/chat/components/common/collapsible.native.tsx +28 -0
  212. package/src/features/chat/components/common/collapsible.tsx +13 -0
  213. package/src/features/chat/components/product/index.ts +2 -0
  214. package/src/features/chat/components/product/product.model.ts +10 -0
  215. package/src/features/chat/components/product/product.native.tsx +117 -0
  216. package/src/features/chat/components/product/product.tsx +80 -0
  217. package/src/features/chat/components/service/index.ts +2 -0
  218. package/src/features/chat/components/service/service.model.ts +10 -0
  219. package/src/features/chat/components/service/service.native.tsx +96 -0
  220. package/src/features/chat/components/service/service.tsx +80 -0
  221. package/src/features/chat/index.d.ts +8 -0
  222. package/src/features/chat/index.d.ts.map +1 -0
  223. package/src/features/chat/index.ts +13 -0
  224. package/src/features/chat/model/chat.model.ts +36 -0
  225. package/src/features/chat/renderer/index.ts +1 -0
  226. package/src/features/chat/renderer/renderer.native.tsx +22 -0
  227. package/src/features/chat/renderer/renderer.tsx +22 -0
  228. package/src/index.d.ts +11 -0
  229. package/src/index.d.ts.map +1 -0
  230. package/src/index.ts +10 -0
  231. package/src/native.d.ts +9 -0
  232. package/src/native.d.ts.map +1 -0
  233. package/src/native.ts +13 -0
  234. package/src/styles/global.css +3 -0
  235. package/src/utils/i18n.utils.ts +7 -0
  236. package/src/utils/theme.utils.ts +47 -0
  237. package/src/utils/use-expandable-list.ts +12 -0
  238. package/src/web.d.ts +8 -0
  239. package/src/web.d.ts.map +1 -0
  240. package/src/web.ts +13 -0
  241. package/tailwind.config.js +43 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"service.d.ts","sourceRoot":"","sources":["../../../../../../../src/features/chat/components/service/service.tsx"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,2BAAwB,CAAC;AACjE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,oBAAiB,CAAC;AAEnD,wBAAgB,OAAO,CAAC,EACtB,IAAI,EACJ,KAAkB,EAClB,QAAQ,EACR,QAAQ,GACT,EAAE,kBAAkB,CAAC,WAAW,CAAC,+BAiEjC"}
@@ -0,0 +1,10 @@
1
+ import type { LocalizedText } from '../../model/chat.model.js';
2
+ export interface ServiceItem {
3
+ id: number;
4
+ image: string;
5
+ name: LocalizedText;
6
+ description: LocalizedText;
7
+ price: string;
8
+ departmentUnitId: number;
9
+ }
10
+ //# sourceMappingURL=service.model.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"service.model.d.ts","sourceRoot":"","sources":["../../../../../../../src/features/chat/components/service/service.model.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,2BAAwB,CAAC;AAE5D,MAAM,WAAW,WAAW;IAC1B,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,aAAa,CAAC;IACpB,WAAW,EAAE,aAAa,CAAC;IAC3B,KAAK,EAAE,MAAM,CAAC;IACd,gBAAgB,EAAE,MAAM,CAAC;CAC1B"}
@@ -0,0 +1,4 @@
1
+ import type { ChatComponentProps } from '../../model/chat.model.js';
2
+ import type { ServiceItem } from './service.model.js';
3
+ export declare function Service({ data, theme, language, actionLabel, onAction, onSelect, }: ChatComponentProps<ServiceItem>): import("react").JSX.Element;
4
+ //# sourceMappingURL=service.native.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"service.native.d.ts","sourceRoot":"","sources":["../../../../../../../src/features/chat/components/service/service.native.tsx"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,2BAAwB,CAAC;AACjE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,oBAAiB,CAAC;AAEnD,wBAAgB,OAAO,CAAC,EACtB,IAAI,EACJ,KAAkB,EAClB,QAAQ,EACR,WAAuB,EACvB,QAAQ,EACR,QAAQ,GACT,EAAE,kBAAkB,CAAC,WAAW,CAAC,+BA8EjC"}
@@ -0,0 +1,8 @@
1
+ export { Product } from './components/product/index.js';
2
+ export { Service } from './components/service/index.js';
3
+ export { ChatComponentRenderer } from './renderer/index.js';
4
+ export { ComponentType, ItemAction, Theme } from './model/chat.model.js';
5
+ export type { ProductItem } from './components/product/product.model.js';
6
+ export type { ServiceItem } from './components/service/service.model.js';
7
+ export type { ActionHandler, ChatComponentProps, ItemCount, Language, LocalizedText, } from './model/chat.model.js';
8
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/features/chat/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,+BAAsB,CAAC;AAC/C,OAAO,EAAE,OAAO,EAAE,MAAM,+BAAsB,CAAC;AAC/C,OAAO,EAAE,qBAAqB,EAAE,MAAM,qBAAY,CAAC;AACnD,OAAO,EAAE,aAAa,EAAE,UAAU,EAAE,KAAK,EAAE,MAAM,uBAAoB,CAAC;AACtE,YAAY,EAAE,WAAW,EAAE,MAAM,uCAAoC,CAAC;AACtE,YAAY,EAAE,WAAW,EAAE,MAAM,uCAAoC,CAAC;AACtE,YAAY,EACV,aAAa,EACb,kBAAkB,EAClB,SAAS,EACT,QAAQ,EACR,aAAa,GACd,MAAM,uBAAoB,CAAC"}
@@ -0,0 +1,31 @@
1
+ export declare enum Theme {
2
+ Dark = "dark",
3
+ Light = "light"
4
+ }
5
+ export type Language = string;
6
+ export type LocalizedText = Record<string, string>;
7
+ export declare enum ComponentType {
8
+ Product = "product",
9
+ ProductList = "productList",
10
+ Service = "service",
11
+ ServiceList = "serviceList"
12
+ }
13
+ export declare enum ItemAction {
14
+ Add = "add"
15
+ }
16
+ export type ActionHandler<TItem = unknown> = (item: TItem, action?: ItemAction) => void;
17
+ export interface ItemCount {
18
+ id: number;
19
+ count: number;
20
+ }
21
+ export interface ChatComponentProps<TItem = unknown> {
22
+ type: ComponentType;
23
+ data: TItem | TItem[];
24
+ language?: Language;
25
+ onAction?: ActionHandler<TItem>;
26
+ onSelect?: ActionHandler<TItem>;
27
+ actionLabel?: string;
28
+ counts?: ItemCount[];
29
+ theme?: Theme;
30
+ }
31
+ //# sourceMappingURL=chat.model.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"chat.model.d.ts","sourceRoot":"","sources":["../../../../../../src/features/chat/model/chat.model.ts"],"names":[],"mappings":"AAAA,oBAAY,KAAK;IACf,IAAI,SAAS;IACb,KAAK,UAAU;CAChB;AAED,MAAM,MAAM,QAAQ,GAAG,MAAM,CAAC;AAC9B,MAAM,MAAM,aAAa,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;AAEnD,oBAAY,aAAa;IACvB,OAAO,YAAY;IACnB,WAAW,gBAAgB;IAC3B,OAAO,YAAY;IACnB,WAAW,gBAAgB;CAC5B;AAED,oBAAY,UAAU;IACpB,GAAG,QAAQ;CACZ;AAED,MAAM,MAAM,aAAa,CAAC,KAAK,GAAG,OAAO,IAAI,CAAC,IAAI,EAAE,KAAK,EAAE,MAAM,CAAC,EAAE,UAAU,KAAK,IAAI,CAAC;AAExF,MAAM,WAAW,SAAS;IACxB,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,kBAAkB,CAAC,KAAK,GAAG,OAAO;IACjD,IAAI,EAAE,aAAa,CAAC;IACpB,IAAI,EAAE,KAAK,GAAG,KAAK,EAAE,CAAC;IACtB,QAAQ,CAAC,EAAE,QAAQ,CAAC;IACpB,QAAQ,CAAC,EAAE,aAAa,CAAC,KAAK,CAAC,CAAC;IAChC,QAAQ,CAAC,EAAE,aAAa,CAAC,KAAK,CAAC,CAAC;IAChC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,MAAM,CAAC,EAAE,SAAS,EAAE,CAAC;IACrB,KAAK,CAAC,EAAE,KAAK,CAAC;CACf"}
@@ -0,0 +1,2 @@
1
+ export { ChatComponentRenderer } from './renderer';
2
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../../src/features/chat/renderer/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,qBAAqB,EAAE,MAAM,YAAY,CAAC"}
@@ -0,0 +1,5 @@
1
+ import type { ProductItem } from '../components/product/product.model.js';
2
+ import type { ServiceItem } from '../components/service/service.model.js';
3
+ import type { ChatComponentProps } from '../model/chat.model.js';
4
+ export declare function ChatComponentRenderer({ type, ...rest }: ChatComponentProps<ProductItem | ServiceItem>): import("react").JSX.Element | null;
5
+ //# sourceMappingURL=renderer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"renderer.d.ts","sourceRoot":"","sources":["../../../../../../src/features/chat/renderer/renderer.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,wCAAqC,CAAC;AACvE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,wCAAqC,CAAC;AAEvE,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,wBAAqB,CAAC;AAE9D,wBAAgB,qBAAqB,CAAC,EACpC,IAAI,EACJ,GAAG,IAAI,EACR,EAAE,kBAAkB,CAAC,WAAW,GAAG,WAAW,CAAC,sCAW/C"}
@@ -0,0 +1,5 @@
1
+ import type { ProductItem } from '../components/product/product.model.js';
2
+ import type { ServiceItem } from '../components/service/service.model.js';
3
+ import type { ChatComponentProps } from '../model/chat.model.js';
4
+ export declare function ChatComponentRenderer({ type, ...rest }: ChatComponentProps<ProductItem | ServiceItem>): import("react").JSX.Element | null;
5
+ //# sourceMappingURL=renderer.native.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"renderer.native.d.ts","sourceRoot":"","sources":["../../../../../../src/features/chat/renderer/renderer.native.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,wCAAqC,CAAC;AACvE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,wCAAqC,CAAC;AAEvE,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,wBAAqB,CAAC;AAE9D,wBAAgB,qBAAqB,CAAC,EACpC,IAAI,EACJ,GAAG,IAAI,EACR,EAAE,kBAAkB,CAAC,WAAW,GAAG,WAAW,CAAC,sCAW/C"}
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Root entry (aggregator). Defaults to the web/DOM build.
3
+ *
4
+ * Prefer importing the explicit platform entry in apps:
5
+ * - `@inorain_development/hotel-smarters-chat-ui/native` -> React Native (mobile + web client via react-native-web)
6
+ * - `@inorain_development/hotel-smarters-chat-ui/web` -> React DOM (admin)
7
+ *
8
+ * Public exports are added here once domain components exist.
9
+ */
10
+ export * from './web.js';
11
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,cAAc,UAAO,CAAC"}
@@ -0,0 +1,8 @@
1
+ export { Product } from './features/chat/components/product/product.native.js';
2
+ export { Service } from './features/chat/components/service/service.native.js';
3
+ export { ChatComponentRenderer } from './features/chat/renderer/renderer.native.js';
4
+ export { ComponentType, ItemAction, Theme } from './features/chat/model/chat.model.js';
5
+ export type { ProductItem } from './features/chat/components/product/product.model.js';
6
+ export type { ServiceItem } from './features/chat/components/service/service.model.js';
7
+ export type { ActionHandler, ChatComponentProps, ItemCount, Language, LocalizedText, } from './features/chat/model/chat.model.js';
8
+ //# sourceMappingURL=native.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"native.d.ts","sourceRoot":"","sources":["../../../src/native.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,sDAAmD,CAAC;AAC5E,OAAO,EAAE,OAAO,EAAE,MAAM,sDAAmD,CAAC;AAC5E,OAAO,EAAE,qBAAqB,EAAE,MAAM,6CAA0C,CAAC;AACjF,OAAO,EAAE,aAAa,EAAE,UAAU,EAAE,KAAK,EAAE,MAAM,qCAAkC,CAAC;AACpF,YAAY,EAAE,WAAW,EAAE,MAAM,qDAAkD,CAAC;AACpF,YAAY,EAAE,WAAW,EAAE,MAAM,qDAAkD,CAAC;AACpF,YAAY,EACV,aAAa,EACb,kBAAkB,EAClB,SAAS,EACT,QAAQ,EACR,aAAa,GACd,MAAM,qCAAkC,CAAC"}
@@ -0,0 +1 @@
1
+ {"type":"module"}
@@ -0,0 +1,3 @@
1
+ import type { Language, LocalizedText } from '../features/chat/model/chat.model.js';
2
+ export declare function resolveText(text: LocalizedText, language?: Language): string;
3
+ //# sourceMappingURL=i18n.utils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"i18n.utils.d.ts","sourceRoot":"","sources":["../../../../src/utils/i18n.utils.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,aAAa,EAAE,MAAM,sCAAmC,CAAC;AAEjF,wBAAgB,WAAW,CAAC,IAAI,EAAE,aAAa,EAAE,QAAQ,CAAC,EAAE,QAAQ,GAAG,MAAM,CAI5E"}
@@ -0,0 +1,16 @@
1
+ import { Theme } from '../features/chat/model/chat.model.js';
2
+ export interface ThemeClasses {
3
+ surface: string;
4
+ border: string;
5
+ title: string;
6
+ subtitle: string;
7
+ price: string;
8
+ actionBorder: string;
9
+ actionText: string;
10
+ divider: string;
11
+ iconBg: string;
12
+ iconText: string;
13
+ iconColor: string;
14
+ }
15
+ export declare function getThemeClasses(theme?: Theme): ThemeClasses;
16
+ //# sourceMappingURL=theme.utils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"theme.utils.d.ts","sourceRoot":"","sources":["../../../../src/utils/theme.utils.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,sCAAmC,CAAC;AAE1D,MAAM,WAAW,YAAY;IAC3B,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;CACnB;AA8BD,wBAAgB,eAAe,CAAC,KAAK,GAAE,KAAkB,GAAG,YAAY,CAEvE"}
@@ -0,0 +1,8 @@
1
+ export declare function useExpandableList<T>(items: T[], limit?: number): {
2
+ head: T[];
3
+ rest: T[];
4
+ expanded: boolean;
5
+ hasMore: boolean;
6
+ toggle: () => void;
7
+ };
8
+ //# sourceMappingURL=use-expandable-list.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"use-expandable-list.d.ts","sourceRoot":"","sources":["../../../../src/utils/use-expandable-list.ts"],"names":[],"mappings":"AAIA,wBAAgB,iBAAiB,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,EAAE,KAAK,SAAkB;;;;;;EAOvE"}
@@ -0,0 +1,8 @@
1
+ export { Product } from './features/chat/components/product/product';
2
+ export { Service } from './features/chat/components/service/service';
3
+ export { ChatComponentRenderer } from './features/chat/renderer/renderer';
4
+ export { ComponentType, ItemAction, Theme } from './features/chat/model/chat.model.js';
5
+ export type { ProductItem } from './features/chat/components/product/product.model.js';
6
+ export type { ServiceItem } from './features/chat/components/service/service.model.js';
7
+ export type { ActionHandler, ChatComponentProps, ItemCount, Language, LocalizedText, } from './features/chat/model/chat.model.js';
8
+ //# sourceMappingURL=web.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"web.d.ts","sourceRoot":"","sources":["../../../src/web.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,4CAA4C,CAAC;AACrE,OAAO,EAAE,OAAO,EAAE,MAAM,4CAA4C,CAAC;AACrE,OAAO,EAAE,qBAAqB,EAAE,MAAM,mCAAmC,CAAC;AAC1E,OAAO,EAAE,aAAa,EAAE,UAAU,EAAE,KAAK,EAAE,MAAM,qCAAkC,CAAC;AACpF,YAAY,EAAE,WAAW,EAAE,MAAM,qDAAkD,CAAC;AACpF,YAAY,EAAE,WAAW,EAAE,MAAM,qDAAkD,CAAC;AACpF,YAAY,EACV,aAAa,EACb,kBAAkB,EAClB,SAAS,EACT,QAAQ,EACR,aAAa,GACd,MAAM,qCAAkC,CAAC"}
@@ -0,0 +1 @@
1
+ /// <reference types="nativewind/types" />
package/package.json ADDED
@@ -0,0 +1,142 @@
1
+ {
2
+ "name": "@inorain_development/hotel-smarters-chat-ui",
3
+ "version": "1.0.0",
4
+ "description": "Cross-platform (React DOM + React Native) chat UI components that render dynamically from an AI-provided { type, data } payload.",
5
+ "private": false,
6
+ "license": "UNLICENSED",
7
+ "source": "./src/index.ts",
8
+ "main": "./lib/commonjs/index.js",
9
+ "module": "./lib/module/index.js",
10
+ "types": "./lib/typescript/commonjs/index.d.ts",
11
+ "exports": {
12
+ ".": {
13
+ "import": {
14
+ "types": "./lib/typescript/module/index.d.ts",
15
+ "default": "./lib/module/index.js"
16
+ },
17
+ "require": {
18
+ "types": "./lib/typescript/commonjs/index.d.ts",
19
+ "default": "./lib/commonjs/index.js"
20
+ }
21
+ },
22
+ "./native": {
23
+ "source": "./src/native.ts",
24
+ "react-native": "./src/native.ts",
25
+ "import": {
26
+ "types": "./lib/typescript/module/native.d.ts",
27
+ "default": "./lib/module/native.js"
28
+ },
29
+ "require": {
30
+ "types": "./lib/typescript/commonjs/native.d.ts",
31
+ "default": "./lib/commonjs/native.js"
32
+ }
33
+ },
34
+ "./web": {
35
+ "import": {
36
+ "types": "./lib/typescript/module/web.d.ts",
37
+ "default": "./lib/module/web.js"
38
+ },
39
+ "require": {
40
+ "types": "./lib/typescript/commonjs/web.d.ts",
41
+ "default": "./lib/commonjs/web.js"
42
+ }
43
+ },
44
+ "./styles/global.css": "./src/styles/global.css",
45
+ "./package.json": "./package.json"
46
+ },
47
+ "files": [
48
+ "src",
49
+ "lib",
50
+ "tailwind.config.js",
51
+ "nativewind-env.d.ts",
52
+ "README.md"
53
+ ],
54
+ "publishConfig": {
55
+ "access": "public"
56
+ },
57
+ "sideEffects": [
58
+ "*.css"
59
+ ],
60
+ "engines": {
61
+ "node": "^20.19.0 || ^22.12.0 || >=23.4.0"
62
+ },
63
+ "scripts": {
64
+ "dev": "vite --config playground/vite.config.ts",
65
+ "playground:build": "vite build --config playground/vite.config.ts",
66
+ "playground:preview": "vite preview --config playground/vite.config.ts",
67
+ "build": "bob build",
68
+ "clean": "rimraf lib",
69
+ "typecheck": "tsc --noEmit",
70
+ "prepare": "bob build",
71
+ "prepack": "bob build"
72
+ },
73
+ "keywords": [
74
+ "react",
75
+ "react-native",
76
+ "chat",
77
+ "ui",
78
+ "components",
79
+ "tailwind",
80
+ "nativewind",
81
+ "cross-platform"
82
+ ],
83
+ "peerDependencies": {
84
+ "nativewind": ">=4.0.0",
85
+ "react": "*",
86
+ "react-dom": "*",
87
+ "react-native": "*"
88
+ },
89
+ "peerDependenciesMeta": {
90
+ "react-dom": {
91
+ "optional": true
92
+ },
93
+ "react-native": {
94
+ "optional": true
95
+ },
96
+ "nativewind": {
97
+ "optional": true
98
+ }
99
+ },
100
+ "devDependencies": {
101
+ "@react-native/babel-preset": "^0.86.0",
102
+ "@types/react": "^19.2.17",
103
+ "@types/react-dom": "^19.2.3",
104
+ "@vitejs/plugin-react": "^6.0.3",
105
+ "autoprefixer": "^10.5.2",
106
+ "nativewind": "^4.2.6",
107
+ "postcss": "^8.5.15",
108
+ "react": "^19.2.7",
109
+ "react-dom": "^19.2.7",
110
+ "react-native": "^0.86.0",
111
+ "react-native-builder-bob": "^0.43.0",
112
+ "react-native-web": "^0.21.2",
113
+ "rimraf": "^6.1.3",
114
+ "tailwindcss": "^3.4.19",
115
+ "typescript": "^6.0.3",
116
+ "vite": "^8.1.0"
117
+ },
118
+ "react-native-builder-bob": {
119
+ "source": "src",
120
+ "output": "lib",
121
+ "targets": [
122
+ [
123
+ "commonjs",
124
+ {
125
+ "esm": true
126
+ }
127
+ ],
128
+ [
129
+ "module",
130
+ {
131
+ "esm": true
132
+ }
133
+ ],
134
+ [
135
+ "typescript",
136
+ {
137
+ "project": "tsconfig.build.json"
138
+ }
139
+ ]
140
+ ]
141
+ }
142
+ }
@@ -0,0 +1,20 @@
1
+ export interface CartIconProps {
2
+ size?: number;
3
+ color?: string;
4
+ }
5
+
6
+ export function CartIcon({ size = 16, color = 'currentColor' }: CartIconProps) {
7
+ return (
8
+ <svg width={size} height={size} viewBox="0 0 24 24" fill="none">
9
+ <path
10
+ d="M3 4h2l2.4 11.2a1.5 1.5 0 0 0 1.47 1.18h7.86a1.5 1.5 0 0 0 1.47-1.18L21 8H6"
11
+ stroke={color}
12
+ strokeWidth={1.8}
13
+ strokeLinecap="round"
14
+ strokeLinejoin="round"
15
+ />
16
+ <circle cx="9.5" cy="20" r="1.4" fill={color} />
17
+ <circle cx="17" cy="20" r="1.4" fill={color} />
18
+ </svg>
19
+ );
20
+ }
@@ -0,0 +1,28 @@
1
+ import { useEffect, useRef, useState } from 'react';
2
+ import type { ReactNode } from 'react';
3
+ import { Animated, View } from 'react-native';
4
+ import type { LayoutChangeEvent } from 'react-native';
5
+
6
+ export function Collapsible({ expanded, children }: { expanded: boolean; children: ReactNode }) {
7
+ const [height, setHeight] = useState(0);
8
+ const anim = useRef(new Animated.Value(0)).current;
9
+
10
+ useEffect(() => {
11
+ Animated.timing(anim, {
12
+ toValue: expanded ? height : 0,
13
+ duration: 250,
14
+ useNativeDriver: false,
15
+ }).start();
16
+ }, [expanded, height, anim]);
17
+
18
+ const onLayout = (e: LayoutChangeEvent) => {
19
+ const next = e.nativeEvent.layout.height;
20
+ if (next > 0 && next !== height) setHeight(next);
21
+ };
22
+
23
+ return (
24
+ <Animated.View style={{ height: anim, overflow: 'hidden' }}>
25
+ <View onLayout={onLayout}>{children}</View>
26
+ </Animated.View>
27
+ );
28
+ }
@@ -0,0 +1,13 @@
1
+ import type { ReactNode } from 'react';
2
+
3
+ export function Collapsible({ expanded, children }: { expanded: boolean; children: ReactNode }) {
4
+ return (
5
+ <div
6
+ className={`grid transition-[grid-template-rows] duration-300 ease-in-out ${
7
+ expanded ? 'grid-rows-[1fr]' : 'grid-rows-[0fr]'
8
+ }`}
9
+ >
10
+ <div className="min-h-0 overflow-hidden">{children}</div>
11
+ </div>
12
+ );
13
+ }
@@ -0,0 +1,2 @@
1
+ export { Product } from './product';
2
+ export type { ProductItem } from './product.model';
@@ -0,0 +1,10 @@
1
+ import type { LocalizedText } from '../../model/chat.model';
2
+
3
+ export interface ProductItem {
4
+ id: number;
5
+ image: string;
6
+ name: LocalizedText;
7
+ description: LocalizedText;
8
+ price: string;
9
+ categoryId: number;
10
+ }
@@ -0,0 +1,117 @@
1
+ import { Fragment, useMemo } from 'react';
2
+ import { Image, Pressable, Text, View } from 'react-native';
3
+ import { getThemeClasses } from '../../../../utils/theme.utils';
4
+ import { resolveText } from '../../../../utils/i18n.utils';
5
+ import { useExpandableList } from '../../../../utils/use-expandable-list';
6
+ import { Collapsible } from '../common/collapsible.native';
7
+ import { CartIcon } from '../common/cart-icon.native';
8
+ import { ItemAction, Theme } from '../../model/chat.model';
9
+ import type { ChatComponentProps } from '../../model/chat.model';
10
+ import type { ProductItem } from './product.model';
11
+
12
+ export function Product({
13
+ data,
14
+ theme = Theme.Dark,
15
+ language,
16
+ actionLabel = 'Add to cart',
17
+ counts,
18
+ onAction,
19
+ onSelect,
20
+ }: ChatComponentProps<ProductItem>) {
21
+ const c = getThemeClasses(theme);
22
+ const items = Array.isArray(data) ? data : [data];
23
+ const { head, rest, expanded, hasMore, toggle } = useExpandableList(items);
24
+
25
+ // Build an id -> count lookup once so each row stays O(1).
26
+ const countById = useMemo(() => {
27
+ const map = new Map<number, number>();
28
+ for (const entry of counts ?? []) map.set(entry.id, entry.count);
29
+ return map;
30
+ }, [counts]);
31
+
32
+ const renderRow = (item: ProductItem) => {
33
+ const name = resolveText(item.name, language);
34
+ const description = resolveText(item.description, language);
35
+ const count = countById.get(item.id) ?? 0;
36
+
37
+ return (
38
+ <Pressable
39
+ className="flex-row items-center gap-3"
40
+ onPress={() => onSelect?.(item)}
41
+ >
42
+ <Image
43
+ accessibilityLabel={name}
44
+ source={{ uri: item.image }}
45
+ className={`h-14 w-14 rounded-lg down-sm:h-12 down-sm:w-12 ${c.iconBg}`}
46
+ />
47
+
48
+ <View className="flex-1 gap-1">
49
+ <View className="flex-row items-center justify-between gap-2">
50
+ <Text className={`flex-1 text-base font-bold down-sm:text-sm ${c.title}`} numberOfLines={1}>
51
+ {name}
52
+ </Text>
53
+
54
+ {count > 0 ? (
55
+ <View className={`flex-row items-center gap-1 rounded-full px-2 py-0.5 ${c.iconBg}`}>
56
+ <CartIcon size={14} color={c.iconColor} />
57
+ <Text className={`text-xs font-semibold ${c.iconText}`}>{count}</Text>
58
+ </View>
59
+ ) : null}
60
+
61
+ <Text className={`text-base font-bold down-sm:text-sm ${c.price}`}>{item.price}</Text>
62
+ </View>
63
+
64
+ <View className="flex-row items-center justify-between gap-2">
65
+ <Text className={`flex-1 text-sm down-sm:text-xs ${c.subtitle}`} numberOfLines={2}>
66
+ {description}
67
+ </Text>
68
+ <Pressable
69
+ accessibilityRole="button"
70
+ onPress={() => onAction?.(item, ItemAction.Add)}
71
+ className={`rounded-xl border px-3 py-1.5 ${c.actionBorder}`}
72
+ >
73
+ <Text className={`text-sm font-medium ${c.actionText}`}>{actionLabel}</Text>
74
+ </Pressable>
75
+ </View>
76
+ </View>
77
+ </Pressable>
78
+ );
79
+ };
80
+
81
+ return (
82
+ <View className="gap-2">
83
+ <View className={`rounded-2xl border px-3 py-2 ${c.surface} ${c.border}`}>
84
+ {head.map((item, index) => (
85
+ <Fragment key={item.id}>
86
+ {index > 0 ? <View className={`my-2.5 h-px ${c.divider}`} /> : null}
87
+ {renderRow(item)}
88
+ </Fragment>
89
+ ))}
90
+
91
+ {hasMore ? (
92
+ <>
93
+ <Collapsible expanded={expanded}>
94
+ {rest.map((item) => (
95
+ <Fragment key={item.id}>
96
+ <View className={`my-2.5 h-px ${c.divider}`} />
97
+ {renderRow(item)}
98
+ </Fragment>
99
+ ))}
100
+ </Collapsible>
101
+
102
+ <View className="mt-2 items-center">
103
+ <Pressable
104
+ onPress={toggle}
105
+ className={`rounded-xl border px-4 py-1.5 ${c.actionBorder}`}
106
+ >
107
+ <Text className={`text-sm font-medium ${c.actionText}`}>
108
+ {expanded ? 'Show less' : 'Show more'}
109
+ </Text>
110
+ </Pressable>
111
+ </View>
112
+ </>
113
+ ) : null}
114
+ </View>
115
+ </View>
116
+ );
117
+ }
@@ -0,0 +1,80 @@
1
+ import { Fragment } from 'react';
2
+ import { getThemeClasses } from '../../../../utils/theme.utils';
3
+ import { resolveText } from '../../../../utils/i18n.utils';
4
+ import { useExpandableList } from '../../../../utils/use-expandable-list';
5
+ import { Collapsible } from '../common/collapsible';
6
+ import { Theme } from '../../model/chat.model';
7
+ import type { ChatComponentProps } from '../../model/chat.model';
8
+ import type { ProductItem } from './product.model';
9
+
10
+ export function Product({
11
+ data,
12
+ theme = Theme.Dark,
13
+ language,
14
+ onSelect,
15
+ }: ChatComponentProps<ProductItem>) {
16
+ const c = getThemeClasses(theme);
17
+ const items = Array.isArray(data) ? data : [data];
18
+ const { head, rest, expanded, hasMore, toggle } = useExpandableList(items);
19
+
20
+ const renderRow = (item: ProductItem) => {
21
+ const name = resolveText(item.name, language);
22
+ const description = resolveText(item.description, language);
23
+
24
+ return (
25
+ <div
26
+ className="flex cursor-pointer items-center gap-3"
27
+ onClick={() => onSelect?.(item)}
28
+ >
29
+ <img
30
+ src={item.image}
31
+ alt={name}
32
+ className={`h-14 w-14 rounded-lg object-cover down-sm:h-12 down-sm:w-12 ${c.iconBg}`}
33
+ />
34
+
35
+ <div className="flex min-w-0 flex-1 flex-col gap-1">
36
+ <div className="flex items-center justify-between gap-2">
37
+ <span className={`flex-1 truncate text-base font-bold down-sm:text-sm ${c.title}`}>{name}</span>
38
+ <span className={`shrink-0 text-base font-bold down-sm:text-sm ${c.price}`}>{item.price}</span>
39
+ </div>
40
+
41
+ <span className={`line-clamp-2 text-sm down-sm:text-xs ${c.subtitle}`}>{description}</span>
42
+ </div>
43
+ </div>
44
+ );
45
+ };
46
+
47
+ return (
48
+ <div className={`rounded-2xl border px-3 py-2 ${c.surface} ${c.border}`}>
49
+ {head.map((item, index) => (
50
+ <Fragment key={item.id}>
51
+ {index > 0 ? <div className={`my-2.5 h-px ${c.divider}`} /> : null}
52
+ {renderRow(item)}
53
+ </Fragment>
54
+ ))}
55
+
56
+ {hasMore ? (
57
+ <>
58
+ <Collapsible expanded={expanded}>
59
+ {rest.map((item) => (
60
+ <Fragment key={item.id}>
61
+ <div className={`my-2.5 h-px ${c.divider}`} />
62
+ {renderRow(item)}
63
+ </Fragment>
64
+ ))}
65
+ </Collapsible>
66
+
67
+ <div className="mt-2 flex justify-center">
68
+ <button
69
+ type="button"
70
+ onClick={toggle}
71
+ className={`rounded-xl border px-4 py-1.5 text-sm font-medium ${c.actionBorder} ${c.actionText}`}
72
+ >
73
+ {expanded ? 'Show less' : 'Show more'}
74
+ </button>
75
+ </div>
76
+ </>
77
+ ) : null}
78
+ </div>
79
+ );
80
+ }
@@ -0,0 +1,2 @@
1
+ export { Service } from './service';
2
+ export type { ServiceItem } from './service.model';
@@ -0,0 +1,10 @@
1
+ import type { LocalizedText } from '../../model/chat.model';
2
+
3
+ export interface ServiceItem {
4
+ id: number;
5
+ image: string;
6
+ name: LocalizedText;
7
+ description: LocalizedText;
8
+ price: string;
9
+ departmentUnitId: number;
10
+ }