@libreapps/commerce 7.5.1

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 (327) hide show
  1. package/.turbo/turbo-build.log +4 -0
  2. package/CHANGELOG.md +13 -0
  3. package/LICENSE.md +21 -0
  4. package/components/Icons.tsx +35 -0
  5. package/components/add-to-cart-widget.tsx +183 -0
  6. package/components/buy/buy-card.tsx +259 -0
  7. package/components/buy/carousel-buy-card.tsx +242 -0
  8. package/components/buy/multi-family/all-variants-carousel.tsx +261 -0
  9. package/components/buy/multi-family/family-carousel/index.tsx +77 -0
  10. package/components/buy/multi-family/family-carousel/slide.tsx +83 -0
  11. package/components/buy/multi-family/family-carousel/state.ts +87 -0
  12. package/components/buy/multi-family/index.ts +2 -0
  13. package/components/buy/single-family-selector.tsx +90 -0
  14. package/components/buy/title-and-byline.tsx +25 -0
  15. package/components/cart/cart-panel/cart-line-item.tsx +76 -0
  16. package/components/cart/cart-panel/index.tsx +154 -0
  17. package/components/cart/cart-panel/promo-code.tsx +109 -0
  18. package/components/cart/cart-panel/total-area.tsx +60 -0
  19. package/components/checkout/payment-step-form/card-icon-row.tsx +26 -0
  20. package/components/checkout/payment-step-form/card-icons/amex.tsx +32 -0
  21. package/components/checkout/payment-step-form/card-icons/diners-club.tsx +13 -0
  22. package/components/checkout/payment-step-form/card-icons/discover.tsx +25 -0
  23. package/components/checkout/payment-step-form/card-icons/jcb.tsx +26 -0
  24. package/components/checkout/payment-step-form/card-icons/mastercard.tsx +27 -0
  25. package/components/checkout/payment-step-form/card-icons/visa.tsx +25 -0
  26. package/components/checkout/payment-step-form/cc-button.tsx +17 -0
  27. package/components/checkout/payment-step-form/contact-form.tsx +50 -0
  28. package/components/checkout/payment-step-form/crypto-icons/btc.tsx +11 -0
  29. package/components/checkout/payment-step-form/crypto-icons/eth.tsx +20 -0
  30. package/components/checkout/payment-step-form/crypto-icons/usdt.tsx +13 -0
  31. package/components/checkout/payment-step-form/index.tsx +122 -0
  32. package/components/checkout/payment-step-form/methods/bank-transfer.tsx +79 -0
  33. package/components/checkout/payment-step-form/methods/card.tsx +232 -0
  34. package/components/checkout/payment-step-form/methods/crypto.tsx +227 -0
  35. package/components/checkout/payment-step-form/methods/index.ts +23 -0
  36. package/components/checkout/shipping-step-form.tsx +175 -0
  37. package/components/index.ts +11 -0
  38. package/components/item/product-card.tsx +48 -0
  39. package/components/item-selector/button.tsx +188 -0
  40. package/components/item-selector/carousel/index.tsx +197 -0
  41. package/components/item-selector/carousel/slider.tsx +40 -0
  42. package/components/item-selector/index.ts +5 -0
  43. package/components/item-selector/quantity-indicator.tsx +48 -0
  44. package/components/node-tabs/index.tsx +91 -0
  45. package/components/node-tabs/node-image.tsx +31 -0
  46. package/dist/components/Icons.d.ts +18 -0
  47. package/dist/components/Icons.js +19 -0
  48. package/dist/components/Icons.js.map +1 -0
  49. package/dist/components/add-to-cart-widget.d.ts +11 -0
  50. package/dist/components/add-to-cart-widget.js +85 -0
  51. package/dist/components/add-to-cart-widget.js.map +1 -0
  52. package/dist/components/buy/buy-card.d.ts +30 -0
  53. package/dist/components/buy/buy-card.js +109 -0
  54. package/dist/components/buy/buy-card.js.map +1 -0
  55. package/dist/components/buy/carousel-buy-card.d.ts +12 -0
  56. package/dist/components/buy/carousel-buy-card.js +94 -0
  57. package/dist/components/buy/carousel-buy-card.js.map +1 -0
  58. package/dist/components/buy/multi-family/all-variants-carousel.d.ts +4 -0
  59. package/dist/components/buy/multi-family/all-variants-carousel.js +115 -0
  60. package/dist/components/buy/multi-family/all-variants-carousel.js.map +1 -0
  61. package/dist/components/buy/multi-family/family-carousel/index.d.ts +4 -0
  62. package/dist/components/buy/multi-family/family-carousel/index.js +27 -0
  63. package/dist/components/buy/multi-family/family-carousel/index.js.map +1 -0
  64. package/dist/components/buy/multi-family/family-carousel/slide.d.ts +11 -0
  65. package/dist/components/buy/multi-family/family-carousel/slide.js +35 -0
  66. package/dist/components/buy/multi-family/family-carousel/slide.js.map +1 -0
  67. package/dist/components/buy/multi-family/family-carousel/state.d.ts +20 -0
  68. package/dist/components/buy/multi-family/family-carousel/state.js +59 -0
  69. package/dist/components/buy/multi-family/family-carousel/state.js.map +1 -0
  70. package/dist/components/buy/multi-family/index.d.ts +2 -0
  71. package/dist/components/buy/multi-family/index.js +3 -0
  72. package/dist/components/buy/multi-family/index.js.map +1 -0
  73. package/dist/components/buy/single-family-selector.d.ts +15 -0
  74. package/dist/components/buy/single-family-selector.js +28 -0
  75. package/dist/components/buy/single-family-selector.js.map +1 -0
  76. package/dist/components/buy/title-and-byline.d.ts +8 -0
  77. package/dist/components/buy/title-and-byline.js +7 -0
  78. package/dist/components/buy/title-and-byline.js.map +1 -0
  79. package/dist/components/cart/cart-panel/cart-line-item.d.ts +11 -0
  80. package/dist/components/cart/cart-panel/cart-line-item.js +25 -0
  81. package/dist/components/cart/cart-panel/cart-line-item.js.map +1 -0
  82. package/dist/components/cart/cart-panel/index.d.ts +19 -0
  83. package/dist/components/cart/cart-panel/index.js +65 -0
  84. package/dist/components/cart/cart-panel/index.js.map +1 -0
  85. package/dist/components/cart/cart-panel/promo-code.d.ts +4 -0
  86. package/dist/components/cart/cart-panel/promo-code.js +62 -0
  87. package/dist/components/cart/cart-panel/promo-code.js.map +1 -0
  88. package/dist/components/cart/cart-panel/total-area.d.ts +7 -0
  89. package/dist/components/cart/cart-panel/total-area.js +14 -0
  90. package/dist/components/cart/cart-panel/total-area.js.map +1 -0
  91. package/dist/components/checkout/payment-step-form/card-icon-row.d.ts +2 -0
  92. package/dist/components/checkout/payment-step-form/card-icon-row.js +14 -0
  93. package/dist/components/checkout/payment-step-form/card-icon-row.js.map +1 -0
  94. package/dist/components/checkout/payment-step-form/card-icons/amex.d.ts +4 -0
  95. package/dist/components/checkout/payment-step-form/card-icons/amex.js +6 -0
  96. package/dist/components/checkout/payment-step-form/card-icons/amex.js.map +1 -0
  97. package/dist/components/checkout/payment-step-form/card-icons/diners-club.d.ts +4 -0
  98. package/dist/components/checkout/payment-step-form/card-icons/diners-club.js +6 -0
  99. package/dist/components/checkout/payment-step-form/card-icons/diners-club.js.map +1 -0
  100. package/dist/components/checkout/payment-step-form/card-icons/discover.d.ts +4 -0
  101. package/dist/components/checkout/payment-step-form/card-icons/discover.js +6 -0
  102. package/dist/components/checkout/payment-step-form/card-icons/discover.js.map +1 -0
  103. package/dist/components/checkout/payment-step-form/card-icons/jcb.d.ts +4 -0
  104. package/dist/components/checkout/payment-step-form/card-icons/jcb.js +6 -0
  105. package/dist/components/checkout/payment-step-form/card-icons/jcb.js.map +1 -0
  106. package/dist/components/checkout/payment-step-form/card-icons/mastercard.d.ts +4 -0
  107. package/dist/components/checkout/payment-step-form/card-icons/mastercard.js +6 -0
  108. package/dist/components/checkout/payment-step-form/card-icons/mastercard.js.map +1 -0
  109. package/dist/components/checkout/payment-step-form/card-icons/visa.d.ts +4 -0
  110. package/dist/components/checkout/payment-step-form/card-icons/visa.js +6 -0
  111. package/dist/components/checkout/payment-step-form/card-icons/visa.js.map +1 -0
  112. package/dist/components/checkout/payment-step-form/cc-button.d.ts +3 -0
  113. package/dist/components/checkout/payment-step-form/cc-button.js +6 -0
  114. package/dist/components/checkout/payment-step-form/cc-button.js.map +1 -0
  115. package/dist/components/checkout/payment-step-form/contact-form.d.ts +5 -0
  116. package/dist/components/checkout/payment-step-form/contact-form.js +6 -0
  117. package/dist/components/checkout/payment-step-form/contact-form.js.map +1 -0
  118. package/dist/components/checkout/payment-step-form/crypto-icons/btc.d.ts +4 -0
  119. package/dist/components/checkout/payment-step-form/crypto-icons/btc.js +6 -0
  120. package/dist/components/checkout/payment-step-form/crypto-icons/btc.js.map +1 -0
  121. package/dist/components/checkout/payment-step-form/crypto-icons/eth.d.ts +4 -0
  122. package/dist/components/checkout/payment-step-form/crypto-icons/eth.js +6 -0
  123. package/dist/components/checkout/payment-step-form/crypto-icons/eth.js.map +1 -0
  124. package/dist/components/checkout/payment-step-form/crypto-icons/usdt.d.ts +4 -0
  125. package/dist/components/checkout/payment-step-form/crypto-icons/usdt.js +6 -0
  126. package/dist/components/checkout/payment-step-form/crypto-icons/usdt.js.map +1 -0
  127. package/dist/components/checkout/payment-step-form/index.d.ts +4 -0
  128. package/dist/components/checkout/payment-step-form/index.js +77 -0
  129. package/dist/components/checkout/payment-step-form/index.js.map +1 -0
  130. package/dist/components/checkout/payment-step-form/methods/bank-transfer.d.ts +4 -0
  131. package/dist/components/checkout/payment-step-form/methods/bank-transfer.js +24 -0
  132. package/dist/components/checkout/payment-step-form/methods/bank-transfer.js.map +1 -0
  133. package/dist/components/checkout/payment-step-form/methods/card.d.ts +4 -0
  134. package/dist/components/checkout/payment-step-form/methods/card.js +160 -0
  135. package/dist/components/checkout/payment-step-form/methods/card.js.map +1 -0
  136. package/dist/components/checkout/payment-step-form/methods/crypto.d.ts +9 -0
  137. package/dist/components/checkout/payment-step-form/methods/crypto.js +137 -0
  138. package/dist/components/checkout/payment-step-form/methods/crypto.js.map +1 -0
  139. package/dist/components/checkout/payment-step-form/methods/index.d.ts +6 -0
  140. package/dist/components/checkout/payment-step-form/methods/index.js +21 -0
  141. package/dist/components/checkout/payment-step-form/methods/index.js.map +1 -0
  142. package/dist/components/checkout/shipping-step-form.d.ts +3 -0
  143. package/dist/components/checkout/shipping-step-form.js +53 -0
  144. package/dist/components/checkout/shipping-step-form.js.map +1 -0
  145. package/dist/components/index.d.ts +8 -0
  146. package/dist/components/index.js +9 -0
  147. package/dist/components/index.js.map +1 -0
  148. package/dist/components/item/product-card.d.ts +7 -0
  149. package/dist/components/item/product-card.js +9 -0
  150. package/dist/components/item/product-card.js.map +1 -0
  151. package/dist/components/item-selector/button.d.ts +4 -0
  152. package/dist/components/item-selector/button.js +47 -0
  153. package/dist/components/item-selector/button.js.map +1 -0
  154. package/dist/components/item-selector/carousel/index.d.ts +12 -0
  155. package/dist/components/item-selector/carousel/index.js +74 -0
  156. package/dist/components/item-selector/carousel/index.js.map +1 -0
  157. package/dist/components/item-selector/carousel/slider.d.ts +8 -0
  158. package/dist/components/item-selector/carousel/slider.js +12 -0
  159. package/dist/components/item-selector/carousel/slider.js.map +1 -0
  160. package/dist/components/item-selector/index.d.ts +2 -0
  161. package/dist/components/item-selector/index.js +3 -0
  162. package/dist/components/item-selector/index.js.map +1 -0
  163. package/dist/components/item-selector/quantity-indicator.d.ts +9 -0
  164. package/dist/components/item-selector/quantity-indicator.js +16 -0
  165. package/dist/components/item-selector/quantity-indicator.js.map +1 -0
  166. package/dist/components/node-tabs/index.d.ts +14 -0
  167. package/dist/components/node-tabs/index.js +42 -0
  168. package/dist/components/node-tabs/index.js.map +1 -0
  169. package/dist/components/node-tabs/node-image.d.ts +6 -0
  170. package/dist/components/node-tabs/node-image.js +13 -0
  171. package/dist/components/node-tabs/node-image.js.map +1 -0
  172. package/dist/index.d.ts +5 -0
  173. package/dist/index.js +5 -0
  174. package/dist/index.js.map +1 -0
  175. package/dist/service/context.d.ts +8 -0
  176. package/dist/service/context.js +19 -0
  177. package/dist/service/context.js.map +1 -0
  178. package/dist/service/debug.d.ts +10 -0
  179. package/dist/service/debug.js +30 -0
  180. package/dist/service/debug.js.map +1 -0
  181. package/dist/service/impls/standalone/actual-line-item.d.ts +40 -0
  182. package/dist/service/impls/standalone/actual-line-item.js +84 -0
  183. package/dist/service/impls/standalone/actual-line-item.js.map +1 -0
  184. package/dist/service/impls/standalone/get-instance.d.ts +2 -0
  185. package/dist/service/impls/standalone/get-instance.js +39 -0
  186. package/dist/service/impls/standalone/get-instance.js.map +1 -0
  187. package/dist/service/impls/standalone/index.d.ts +67 -0
  188. package/dist/service/impls/standalone/index.js +416 -0
  189. package/dist/service/impls/standalone/index.js.map +1 -0
  190. package/dist/service/impls/standalone/order/firebase.d.ts +2 -0
  191. package/dist/service/impls/standalone/order/firebase.js +13 -0
  192. package/dist/service/impls/standalone/order/firebase.js.map +1 -0
  193. package/dist/service/impls/standalone/order/index.d.ts +24 -0
  194. package/dist/service/impls/standalone/order/index.js +61 -0
  195. package/dist/service/impls/standalone/order/index.js.map +1 -0
  196. package/dist/service/impls/standalone/persistence.d.ts +4 -0
  197. package/dist/service/impls/standalone/persistence.js +22 -0
  198. package/dist/service/impls/standalone/persistence.js.map +1 -0
  199. package/dist/service/path-utils.d.ts +7 -0
  200. package/dist/service/path-utils.js +16 -0
  201. package/dist/service/path-utils.js.map +1 -0
  202. package/dist/service/sep.d.ts +6 -0
  203. package/dist/service/sep.js +6 -0
  204. package/dist/service/sep.js.map +1 -0
  205. package/dist/types/category-node.d.ts +36 -0
  206. package/dist/types/category-node.js +2 -0
  207. package/dist/types/category-node.js.map +1 -0
  208. package/dist/types/checkout.d.ts +33 -0
  209. package/dist/types/checkout.js +2 -0
  210. package/dist/types/checkout.js.map +1 -0
  211. package/dist/types/commerce-config.d.ts +11 -0
  212. package/dist/types/commerce-config.js +2 -0
  213. package/dist/types/commerce-config.js.map +1 -0
  214. package/dist/types/commerce-service.d.ts +109 -0
  215. package/dist/types/commerce-service.js +2 -0
  216. package/dist/types/commerce-service.js.map +1 -0
  217. package/dist/types/family.d.ts +16 -0
  218. package/dist/types/family.js +2 -0
  219. package/dist/types/family.js.map +1 -0
  220. package/dist/types/index.d.ts +13 -0
  221. package/dist/types/index.js +8 -0
  222. package/dist/types/index.js.map +1 -0
  223. package/dist/types/item-selector.d.ts +72 -0
  224. package/dist/types/item-selector.js +2 -0
  225. package/dist/types/item-selector.js.map +1 -0
  226. package/dist/types/line-item.d.ts +14 -0
  227. package/dist/types/line-item.js +2 -0
  228. package/dist/types/line-item.js.map +1 -0
  229. package/dist/types/multi-family-selector-props.d.ts +16 -0
  230. package/dist/types/multi-family-selector-props.js +2 -0
  231. package/dist/types/multi-family-selector-props.js.map +1 -0
  232. package/dist/types/product.d.ts +15 -0
  233. package/dist/types/product.js +2 -0
  234. package/dist/types/product.js.map +1 -0
  235. package/dist/types/promo.d.ts +7 -0
  236. package/dist/types/promo.js +2 -0
  237. package/dist/types/promo.js.map +1 -0
  238. package/dist/types/selection-ui-specifier.d.ts +40 -0
  239. package/dist/types/selection-ui-specifier.js +2 -0
  240. package/dist/types/selection-ui-specifier.js.map +1 -0
  241. package/dist/types/string-mutator.d.ts +9 -0
  242. package/dist/types/string-mutator.js +2 -0
  243. package/dist/types/string-mutator.js.map +1 -0
  244. package/dist/types/token-separators.d.ts +6 -0
  245. package/dist/types/token-separators.js +2 -0
  246. package/dist/types/token-separators.js.map +1 -0
  247. package/dist/util/analytics.d.ts +9 -0
  248. package/dist/util/analytics.js +10 -0
  249. package/dist/util/analytics.js.map +1 -0
  250. package/dist/util/countries.d.ts +7 -0
  251. package/dist/util/countries.js +197 -0
  252. package/dist/util/countries.js.map +1 -0
  253. package/dist/util/error.d.ts +1 -0
  254. package/dist/util/error.js +22 -0
  255. package/dist/util/error.js.map +1 -0
  256. package/dist/util/index.d.ts +15 -0
  257. package/dist/util/index.js +54 -0
  258. package/dist/util/index.js.map +1 -0
  259. package/dist/util/item-selector-options-accessor.d.ts +3 -0
  260. package/dist/util/item-selector-options-accessor.js +27 -0
  261. package/dist/util/item-selector-options-accessor.js.map +1 -0
  262. package/dist/util/line-item-ref.d.ts +8 -0
  263. package/dist/util/line-item-ref.js +15 -0
  264. package/dist/util/line-item-ref.js.map +1 -0
  265. package/dist/util/multi-family-selector-options-accessor.d.ts +3 -0
  266. package/dist/util/multi-family-selector-options-accessor.js +11 -0
  267. package/dist/util/multi-family-selector-options-accessor.js.map +1 -0
  268. package/dist/util/obs-string-mutator.d.ts +8 -0
  269. package/dist/util/obs-string-mutator.js +15 -0
  270. package/dist/util/obs-string-mutator.js.map +1 -0
  271. package/dist/util/product-media-accessor.d.ts +29 -0
  272. package/dist/util/product-media-accessor.js +22 -0
  273. package/dist/util/product-media-accessor.js.map +1 -0
  274. package/dist/util/promo-codes.d.ts +3 -0
  275. package/dist/util/promo-codes.js +100 -0
  276. package/dist/util/promo-codes.js.map +1 -0
  277. package/dist/util/selection-ui-specifiers.d.ts +3 -0
  278. package/dist/util/selection-ui-specifiers.js +24 -0
  279. package/dist/util/selection-ui-specifiers.js.map +1 -0
  280. package/dist/util/square-payment.d.ts +7 -0
  281. package/dist/util/square-payment.js +37 -0
  282. package/dist/util/square-payment.js.map +1 -0
  283. package/dist/util/use-sync-sku-param-w-current-item.d.ts +2 -0
  284. package/dist/util/use-sync-sku-param-w-current-item.js +61 -0
  285. package/dist/util/use-sync-sku-param-w-current-item.js.map +1 -0
  286. package/index.ts +13 -0
  287. package/libreapps-ui.d.ts +108 -0
  288. package/package.json +67 -0
  289. package/service/context.tsx +45 -0
  290. package/service/debug.ts +41 -0
  291. package/service/impls/standalone/actual-line-item.ts +136 -0
  292. package/service/impls/standalone/get-instance.ts +64 -0
  293. package/service/impls/standalone/index.ts +579 -0
  294. package/service/impls/standalone/order/firebase.ts +14 -0
  295. package/service/impls/standalone/order/index.ts +129 -0
  296. package/service/impls/standalone/persistence.ts +33 -0
  297. package/service/path-utils.ts +26 -0
  298. package/service/sep.ts +7 -0
  299. package/tsconfig.json +17 -0
  300. package/types/README.md +2 -0
  301. package/types/category-node.ts +50 -0
  302. package/types/checkout.ts +47 -0
  303. package/types/commerce-config.ts +13 -0
  304. package/types/commerce-service.ts +128 -0
  305. package/types/family.ts +26 -0
  306. package/types/index.ts +15 -0
  307. package/types/item-selector.ts +97 -0
  308. package/types/line-item.ts +29 -0
  309. package/types/multi-family-selector-props.ts +20 -0
  310. package/types/product.ts +21 -0
  311. package/types/promo.ts +10 -0
  312. package/types/selection-ui-specifier.ts +52 -0
  313. package/types/string-mutator.ts +14 -0
  314. package/types/token-separators.ts +7 -0
  315. package/util/analytics.ts +21 -0
  316. package/util/countries.ts +196 -0
  317. package/util/error.ts +34 -0
  318. package/util/index.ts +71 -0
  319. package/util/item-selector-options-accessor.ts +35 -0
  320. package/util/line-item-ref.ts +23 -0
  321. package/util/multi-family-selector-options-accessor.ts +15 -0
  322. package/util/obs-string-mutator.ts +22 -0
  323. package/util/product-media-accessor.ts +58 -0
  324. package/util/promo-codes.ts +106 -0
  325. package/util/selection-ui-specifiers.ts +30 -0
  326. package/util/square-payment.ts +50 -0
  327. package/util/use-sync-sku-param-w-current-item.ts +88 -0
@@ -0,0 +1,87 @@
1
+ import type { Family, LineItem, ObsLineItemRef, Product } from '../../../../types'
2
+ import { observable, action, computed, makeObservable } from 'mobx'
3
+
4
+ class SlideState implements ObsLineItemRef {
5
+
6
+ _fam: Family
7
+ _item: Product
8
+ _syncSku: (sku: string) => void
9
+ _selected: boolean
10
+
11
+ constructor(fam: Family, initiallySelected: boolean, sync: (sku: string) => void) {
12
+ this._fam = fam
13
+ this._item = fam.products[0]
14
+ this._selected = initiallySelected
15
+ this._syncSku = sync
16
+
17
+ makeObservable(this, {
18
+ _item: observable,
19
+ item: computed,
20
+ selectSku: action
21
+ })
22
+ }
23
+
24
+ selectSku = (sku: string) => {
25
+ if (this._item.sku === sku) return;
26
+ const found = this._fam.products.find((i) => (i.sku === sku))
27
+ if (found) {
28
+ this._item = found
29
+ if (this._selected) {
30
+ this._syncSku(sku)
31
+ }
32
+ }
33
+ else {
34
+ throw new Error('SlideState.selectSku(): no item found!')
35
+ }
36
+ }
37
+
38
+ setSelected = (b: boolean) => {this._selected = b}
39
+
40
+ get id(): string {return (this._fam.id)}
41
+
42
+ get item(): LineItem | undefined {
43
+ return this._item as LineItem
44
+ }
45
+ }
46
+
47
+ class FamilyCarouselState {
48
+
49
+ _map = new Map<string, SlideState>()
50
+ _syncSku: (sku: string) => void
51
+
52
+ constructor(
53
+ fams: Family[],
54
+ // initialFamilyId: string,
55
+ syncSkuToCurrentSlide: (sku: string) => void
56
+ ) {
57
+
58
+ fams.forEach((f, index) => {this._map.set(f.id, new SlideState(
59
+ f,
60
+ (index === 0),
61
+ syncSkuToCurrentSlide
62
+ ))})
63
+ this._syncSku = syncSkuToCurrentSlide
64
+ }
65
+
66
+ setCurrentFamily = (id: string) => {
67
+
68
+ this._map.forEach((s) => {
69
+ s.setSelected(s.id === id)
70
+ })
71
+
72
+ const slideState = this._map.get(id)
73
+ if (slideState) {
74
+ this._syncSku(slideState.item!.sku)
75
+ }
76
+ else {
77
+ throw new Error(`FamilyCarouselState.setCurrentFamily: no state object for id '${id}'!`)
78
+ }
79
+ }
80
+
81
+ getSlideState = (familyId: string): SlideState | undefined => (this._map.get(familyId))
82
+ }
83
+
84
+ export {
85
+ SlideState,
86
+ FamilyCarouselState
87
+ }
@@ -0,0 +1,2 @@
1
+ export { default as FamilyCarousel } from './family-carousel'
2
+ export { default as AllVariantsCarousel } from './all-variants-carousel'
@@ -0,0 +1,90 @@
1
+ import React from 'react'
2
+ import { observer } from 'mobx-react-lite'
3
+
4
+ import { MediaStack, Skeleton } from '@libreapps/ui/primitives'
5
+ import type { Dimensions } from '@libreapps/ui/types'
6
+
7
+ import { useCommerce } from '../..'
8
+
9
+ import type { ItemSelectorOptions, ItemSelectorProps, LineItem } from '../../types'
10
+ import TitleAndByline from './title-and-byline'
11
+ import { accessItemOptions } from '../../util'
12
+ import { cn } from '@libreapps/ui/util'
13
+
14
+
15
+ const DEF_MEDIA_CONSTRAINT = {w: 200, h: 200}
16
+
17
+ const SingleFamilySelector: React.FC<{
18
+ items: LineItem[] // these may be sorted, so are we can't just use currentFamily.products
19
+ Selector: React.ComponentType<ItemSelectorProps>
20
+ selOptions: ItemSelectorOptions | undefined
21
+ scrollable?: boolean
22
+ showItemMedia?: boolean
23
+ mediaConstraint?: Dimensions
24
+ mobile?: boolean
25
+ clx?: string
26
+ titleAreaClx?: string
27
+ }> = ({
28
+ items,
29
+ Selector,
30
+ selOptions,
31
+ scrollable=false,
32
+ showItemMedia=true,
33
+ mediaConstraint=DEF_MEDIA_CONSTRAINT,
34
+ mobile=false,
35
+ clx='',
36
+ titleAreaClx=''
37
+ }) => {
38
+
39
+ const cmmc = useCommerce()
40
+
41
+
42
+ const MyTitleAndByline: React.FC<{clx?: string}> = observer(({
43
+ clx=''
44
+ }) => {
45
+ const { familyTitle, showFamilyByline } = accessItemOptions(selOptions)
46
+ const title = (familyTitle === 'none' ?
47
+ undefined
48
+ :
49
+ (familyTitle === 'long' ?
50
+ cmmc.currentFamily?.title
51
+ :
52
+ (cmmc.currentFamily?.titleShort ?? cmmc.currentFamily?.title)
53
+ )
54
+ )
55
+ const byline = (familyTitle !== 'none') && showFamilyByline ? cmmc.currentFamily?.byline : undefined
56
+ return ( <TitleAndByline clx={clx} title={title} byline={byline}/> )
57
+ })
58
+
59
+ const ItemMedia: React.FC = observer(() => (
60
+ cmmc.currentItem ? (
61
+ <MediaStack
62
+ media={cmmc.currentItem!}
63
+ constrainTo={mediaConstraint}
64
+ clx={'mb-2 ' + (scrollable ? 'shrink-0' : '')}
65
+ />
66
+ ) : (
67
+ <Skeleton className={'w-[200px] h-[200px] my-2 ' + (scrollable ? 'shrink-0' : '')}/>
68
+ )
69
+ ))
70
+
71
+ return (
72
+ <div className={cn(clx, 'flex flex-col items-center', (scrollable ? 'shrink' : ''))}>
73
+ <MyTitleAndByline clx={cn(titleAreaClx, (scrollable ? 'shrink-0' : ''))} />
74
+ {showItemMedia && (<ItemMedia />)}
75
+ {items && (
76
+ <Selector
77
+ items={items}
78
+ selectedItemRef={cmmc}
79
+ selectSku={cmmc.setCurrentItem.bind(cmmc)}
80
+ scrollable={scrollable}
81
+ mobile={mobile}
82
+ options={selOptions}
83
+ clx={(scrollable ? 'shrink' : '')}
84
+ />
85
+ )}
86
+ </div>
87
+ )
88
+ }
89
+
90
+ export default SingleFamilySelector
@@ -0,0 +1,25 @@
1
+ import React from 'react'
2
+
3
+ import { ApplyTypography } from '@libreapps/ui/primitives'
4
+ import { cn } from '@libreapps/ui/util'
5
+
6
+ const TitleAndByline: React.FC<{
7
+ title: string | undefined
8
+ byline?: string | undefined
9
+ clx?: string
10
+ bylineClx?: string
11
+ }> = ({
12
+ title,
13
+ byline,
14
+ clx='',
15
+ bylineClx=''
16
+ }) => ( (title || byline) ? (
17
+ <ApplyTypography className={cn('flex flex-col items-center !gap-0 [&>*]:!m-0 ', clx)} >
18
+ <h4>{title}</h4>
19
+ {byline && (<h6 className={bylineClx}>{byline}</h6>)}
20
+ </ApplyTypography>
21
+ ) : (null)
22
+ )
23
+
24
+ export default TitleAndByline
25
+
@@ -0,0 +1,76 @@
1
+ 'use client'
2
+
3
+ import React from 'react'
4
+ import { observer } from 'mobx-react-lite'
5
+
6
+ import { cn } from '@libreapps/ui/util'
7
+ import { Image } from '@libreapps/ui/primitives'
8
+
9
+ import type { LineItem } from '../../../types'
10
+ import { formatCurrencyValue } from '../../../util'
11
+ import AddToCartWidget from '../../add-to-cart-widget'
12
+ import { useCommerce } from '../../../service/context'
13
+
14
+ const DEF_IMG_SIZE=40
15
+
16
+ const renderTitle = (t: string): React.ReactNode => {
17
+ const toks = t.split(', ')
18
+ if (toks.length === 2) {
19
+ return <><p>{toks[0]},</p><p className=''>{toks[1]}</p></>
20
+ }
21
+ return <p>{t}</p>
22
+ }
23
+
24
+ const CartLineItem: React.FC<{
25
+ item: LineItem
26
+ className?: string
27
+ imgSizePx?: number
28
+ showPromoCode?: boolean
29
+ itemClicked?: (item: LineItem) => void
30
+ selected?: boolean
31
+ }> = observer(({
32
+ item,
33
+ className='',
34
+ imgSizePx=DEF_IMG_SIZE,
35
+ showPromoCode=false,
36
+ itemClicked,
37
+ selected=false
38
+ }) => {
39
+
40
+ const cmmc = useCommerce()
41
+ const promoPrice = showPromoCode ? cmmc.itemPromoPrice(item) : undefined
42
+
43
+ return (
44
+ <div
45
+ className={cn(
46
+ 'flex flex-col justify-start items-start text-sm font-sans',
47
+ 'border border-background rounded-sm p-1',
48
+ selected ? 'border-foreground' : '',
49
+ (itemClicked && !selected ? 'cursor-pointer hover:!border-muted-4' : 'cursor-default '),
50
+ className
51
+ )}
52
+ onClick={() => {itemClicked && itemClicked(item)}}
53
+ >
54
+ <div className='flex flex-row justify-between items-center gap-1' >
55
+ {item.img ? (
56
+ <Image def={item.img} constrainTo={{w: imgSizePx, h: imgSizePx}} />
57
+ ) : ( // placeholder so things align
58
+ <div style={{height: imgSizePx, width: imgSizePx}} className='bg-level-3'/>
59
+ )}
60
+ <div className='grow leading-tight ml-1'>{renderTitle(item.title)}</div>
61
+ </div>
62
+ <div className='flex flex-row items-center justify-between w-full'>
63
+ <div className='flex flex-row items-center'>
64
+ <AddToCartWidget variant='minimal' item={item} />
65
+ {item.quantity > 1 && (<span className='pl-2.5'>{'@' + formatCurrencyValue(item.price)}</span>)}
66
+ </div>
67
+ <div className='flex flex-row gap-1 items-center justify-end'>
68
+ <span className={promoPrice ? 'line-through text-muted-2' : ''}>{formatCurrencyValue(item.price * item.quantity)}</span>
69
+ {promoPrice && <span>{formatCurrencyValue(promoPrice * item.quantity)}</span>}
70
+ </div>
71
+ </div>
72
+ </div>
73
+ )
74
+ })
75
+
76
+ export default CartLineItem
@@ -0,0 +1,154 @@
1
+ 'use client'
2
+ import React, { useLayoutEffect, type PropsWithChildren } from 'react'
3
+ import { reaction } from 'mobx'
4
+ import { observer } from 'mobx-react-lite'
5
+
6
+ import { Button, ScrollArea } from '@libreapps/ui/primitives'
7
+ import { cn } from '@libreapps/ui/util'
8
+
9
+ import type { LineItem } from '../../../types'
10
+ import { useCommerce } from '../../../service/context'
11
+ import { sendFBEvent, sendGAEvent } from '../../../util/analytics'
12
+
13
+ import CartLineItem from './cart-line-item'
14
+ import TotalArea from './total-area'
15
+
16
+ const CartPanel: React.FC<PropsWithChildren & {
17
+ /** fix size and scroll after 'scrollAfter items in teh cart. */
18
+ scrollAfter?: number
19
+ scrollHeightClx?: string
20
+ imgSizePx?: number
21
+ className?: string
22
+ itemClx?: string
23
+ listClx?: string
24
+ noItemsClx?: string
25
+ totalClx?: string
26
+ buttonClx?: string
27
+ showPromoCode?: boolean
28
+ showShipping?: boolean
29
+ selectItems?: boolean
30
+ /** if not provided, 'checkout' button will be rendered */
31
+ handleCheckout?: () => void
32
+ }> = observer(({
33
+ /** If provided, 'children' is rendered above the items. eg, a heading. */
34
+ children,
35
+ scrollAfter=5,
36
+ scrollHeightClx='h-[70vh]',
37
+ imgSizePx=40,
38
+ className='',
39
+ itemClx='',
40
+ listClx='',
41
+ noItemsClx='',
42
+ totalClx='',
43
+ buttonClx='',
44
+ showPromoCode=false,
45
+ showShipping=false,
46
+ selectItems=false,
47
+ handleCheckout,
48
+ }) => {
49
+
50
+ const cmmc = useCommerce()
51
+
52
+ useLayoutEffect(() => {
53
+ if (!cmmc) {
54
+ return
55
+ }
56
+ if (!cmmc.cartEmpty && !cmmc.currentItem) {
57
+ cmmc.setCurrentItem(cmmc.cartItems[0].sku)
58
+ }
59
+ // return mobx disposer
60
+ return reaction(() => (
61
+ cmmc.cartItems.length
62
+ ),
63
+ (itemCount) => {
64
+ if (itemCount > 0) {
65
+ cmmc.setCurrentItem(cmmc.cartItems[0].sku)
66
+ }
67
+ })
68
+ }, [])
69
+
70
+ if (!cmmc) {
71
+ return <div />
72
+ }
73
+
74
+ const _handleCheckout = () => {
75
+ sendGAEvent('begin_checkout', {
76
+ currency: 'USD',
77
+ value: cmmc.cartTotal,
78
+ items: cmmc.cartItems.map((item) => ({
79
+ item_id: item.sku,
80
+ item_name: item.title,
81
+ item_category: item.familyId,
82
+ price: item.price,
83
+ quantity: item.quantity
84
+ })),
85
+ })
86
+ sendFBEvent('InitiateCheckout', {
87
+ content_ids: cmmc.cartItems.map((item) => item.sku),
88
+ contents: cmmc.cartItems.map(item => ({
89
+ id: item.sku,
90
+ quantity: item.quantity
91
+ })),
92
+ num_items: cmmc.cartItems.length,
93
+ value: cmmc.cartTotal,
94
+ currency: 'USD',
95
+ })
96
+ handleCheckout && handleCheckout()
97
+ }
98
+
99
+ const itemClicked = (item: LineItem) => {
100
+ cmmc.setCurrentItem(item.sku)
101
+ }
102
+
103
+ const MainStuff: React.FC = observer(() => (<>
104
+ {cmmc.cartEmpty ? (
105
+ <p className={cn('text-center my-3', noItemsClx)}>No items</p>
106
+ ) : (<>
107
+ {cmmc.cartItems.map((item) => (
108
+ <CartLineItem
109
+ key={`mobile-${item.sku}`}
110
+ imgSizePx={imgSizePx}
111
+ item={item}
112
+ className={cn('mb-2', itemClx)}
113
+ showPromoCode={showPromoCode}
114
+ itemClicked={selectItems ? itemClicked : undefined}
115
+ selected={selectItems ? cmmc.currentItem?.sku === item.sku : false}
116
+ />
117
+ ))}
118
+ </>)}
119
+ <TotalArea clx={totalClx} showPromoCode={showPromoCode} showShipping={showShipping}/>
120
+ </>))
121
+
122
+ const scrolling = (cmmc.cartItems.length > scrollAfter)
123
+
124
+ return (
125
+ <div className={cn(
126
+ 'border p-4 rounded-lg flex flex-col',
127
+ className,
128
+ scrolling ? scrollHeightClx : 'h-auto'
129
+ )}>
130
+ {children}
131
+ {scrolling ? (
132
+ <ScrollArea className={cn('mt-2 w-full shrink py-0', listClx)}>
133
+ <MainStuff />
134
+ </ScrollArea>
135
+ ) : (
136
+ <div className={cn('mt-2 w-full', listClx)}>
137
+ <MainStuff />
138
+ </div>
139
+ )}
140
+ {handleCheckout && !cmmc.cartEmpty && (
141
+ <Button
142
+ onClick={_handleCheckout}
143
+ variant='primary'
144
+ rounded='lg'
145
+ className={cn('mt-12 mx-auto w-full sm:max-w-[220px]', buttonClx)}
146
+ >
147
+ Checkout
148
+ </Button>
149
+ )}
150
+ </div>
151
+ )
152
+ })
153
+
154
+ export default CartPanel
@@ -0,0 +1,109 @@
1
+ 'use client'
2
+
3
+ import { useEffect, useState } from 'react'
4
+ import { useSearchParams } from 'next/navigation'
5
+ import { observer } from 'mobx-react-lite'
6
+
7
+ import { useForm } from 'react-hook-form'
8
+ import * as z from 'zod'
9
+ import { zodResolver } from '@hookform/resolvers/zod'
10
+ import { Check } from 'lucide-react'
11
+
12
+ import {
13
+ Button,
14
+ Input
15
+ } from '@libreapps/ui/primitives'
16
+
17
+ import {
18
+ Form,
19
+ FormControl,
20
+ FormField,
21
+ FormItem,
22
+ } from '@libreapps/ui/form'
23
+
24
+ import { useCommerce } from '../../../service/context'
25
+ import type { Promo } from '../../../types'
26
+ import getPromoFromApi from '../../../util/promo-codes'
27
+
28
+ const formSchema = z.object({
29
+ code: z.string().min(1, 'Invalid code'),
30
+ })
31
+
32
+ const PromoCode = observer(() => {
33
+ const cmmc = useCommerce()
34
+ const searchParams = useSearchParams()
35
+
36
+ const [codeAccepted, setCodeAccepted] = useState<boolean>(false)
37
+
38
+ useEffect(() => {
39
+ const code = searchParams.get('code')
40
+ if (code) {
41
+ getPromoFromApi(code).then((promo?: Promo) => {
42
+ if (promo) {
43
+ form.setValue('code', code)
44
+ setCodeAccepted(true)
45
+ cmmc.setAppliedPromo(promo)
46
+ }
47
+ })
48
+ }
49
+ }, [searchParams])
50
+
51
+ useEffect(() => {
52
+ if (cmmc.appliedPromo) {
53
+ form.setValue('code', cmmc.appliedPromo.code)
54
+ setCodeAccepted(true)
55
+ }
56
+ }, [cmmc.appliedPromo])
57
+
58
+ const form = useForm<z.infer<typeof formSchema>>({
59
+ resolver: zodResolver(formSchema),
60
+ defaultValues: {
61
+ code: '',
62
+ },
63
+ })
64
+
65
+ const applyPromoCode = async (values: z.infer<typeof formSchema>) => {
66
+ const { code } = values
67
+ const promo = await getPromoFromApi(code)
68
+ if (!promo) {
69
+ form.setError('code', { message: 'Invalid code' })
70
+ return
71
+ }
72
+ setCodeAccepted(true)
73
+ cmmc.setAppliedPromo(promo)
74
+ }
75
+
76
+ const removePromoCode = () => {
77
+ cmmc.setAppliedPromo(null)
78
+ setCodeAccepted(false)
79
+ }
80
+
81
+ return (
82
+ <div className='flex flex-col gap-2 border-t py-1'>
83
+ <Form {...form}>
84
+ <form onSubmit={form.handleSubmit(applyPromoCode)}>
85
+ <div className='flex gap-2 items-center'>
86
+ <FormField
87
+ control={form.control}
88
+ name='code'
89
+ render={({ field }) => (
90
+ <FormItem className='w-full'>
91
+ <FormControl>
92
+ <Input {...field} className='h-9' placeholder='Discount or invite code' onInput={removePromoCode}/>
93
+ </FormControl>
94
+ </FormItem>
95
+ )}
96
+ />
97
+ {codeAccepted ? (
98
+ <Check/>
99
+ ) : (
100
+ <Button variant='outline' className='!w-fit !min-w-0 font-inter text-muted text-sm'>Apply</Button>
101
+ )}
102
+ </div>
103
+ </form>
104
+ </Form>
105
+ </div>
106
+ )
107
+ })
108
+
109
+ export default PromoCode
@@ -0,0 +1,60 @@
1
+ 'use client'
2
+ import React, { Suspense } from 'react'
3
+ import { observer } from 'mobx-react-lite'
4
+
5
+ import { cn } from '@libreapps/ui/util'
6
+
7
+ import { formatCurrencyValue } from '../../../util'
8
+ import PromoCode from './promo-code'
9
+ import { useCommerce } from '../../../service/context'
10
+
11
+ const TotalArea: React.FC<{
12
+ showPromoCode?: boolean
13
+ showShipping?: boolean
14
+ clx?: string
15
+ }> = observer(({
16
+ showPromoCode=false,
17
+ showShipping=false,
18
+ clx
19
+ }) => {
20
+
21
+ const cmmc = useCommerce()
22
+
23
+ return (
24
+ <div className={clx}>
25
+ {showPromoCode && (
26
+ <Suspense>
27
+ <PromoCode/>
28
+ </Suspense>
29
+ )}
30
+ {(showShipping || showPromoCode) && (
31
+ <div className={'flex flex-col gap-0.5 pb-1.5 text-sm ' + (!showPromoCode ? 'border-t pt-1.5' : '')} >
32
+ <p className='flex justify-between'>
33
+ <span className='text-muted-1'>Subtotal</span>
34
+ <span className='font-semibold'>{cmmc.cartTotal === 0 ? '0' : formatCurrencyValue(cmmc.cartTotal)}</span>
35
+ </p>
36
+ {cmmc.promoAppliedCartTotal !== cmmc.cartTotal && (
37
+ <p className='flex justify-between'>
38
+ <span className='text-muted-1'>Promo Discount</span>
39
+ <span className='font-semibold'>-{formatCurrencyValue(cmmc.cartTotal - cmmc.promoAppliedCartTotal)}</span>
40
+ </p>
41
+ )}
42
+ {showShipping && (
43
+ <p className='flex justify-between'>
44
+ <span className='text-muted-1'>Shipping</span>
45
+ <span className='font-semibold'>Free Global Shipping</span>
46
+ </p>
47
+ )}
48
+ </div>
49
+ )}
50
+ <p className={cn('border-t py-2 flex justify-between')}>
51
+ TOTAL
52
+ <span className='font-semibold'>
53
+ {formatCurrencyValue(showPromoCode ? cmmc.promoAppliedCartTotal : cmmc.cartTotal)}
54
+ </span>
55
+ </p>
56
+ </div>
57
+ )
58
+ })
59
+
60
+ export default TotalArea
@@ -0,0 +1,26 @@
1
+ import { LockKeyhole } from 'lucide-react'
2
+ import Amex from './card-icons/amex'
3
+ import Discover from './card-icons/discover'
4
+ import Mastercard from './card-icons/mastercard'
5
+ import Visa from './card-icons/visa'
6
+ import DinersClub from './card-icons/diners-club'
7
+ import Jcb from './card-icons/jcb'
8
+
9
+ // <span className='hidden sm:flex text-sm'>Secure payments with</span>
10
+
11
+ const PaymentMethods: React.FC = () => {
12
+ return (
13
+ <div className='flex gap-1 items-center text-muted-1 pb-3'>
14
+ <LockKeyhole className='w-4 h-4'/>
15
+ <span className='hidden sm:flex text-sm'>Secure payments with</span>
16
+ <Amex className='w-9 h-5'/>
17
+ <Discover className='w-9 h-5'/>
18
+ <Mastercard className='w-9 h-5'/>
19
+ <Visa className='w-9 h-5'/>
20
+ <DinersClub className='w-9 h-5'/>
21
+ <Jcb className='w-9 h-5'/>
22
+ </div>
23
+ )
24
+ }
25
+
26
+ export default PaymentMethods
@@ -0,0 +1,32 @@
1
+ import React from 'react'
2
+ import { type LucideProps } from 'lucide-react'
3
+
4
+ const Amex: React.FC<LucideProps> = (props: LucideProps) => (
5
+ <svg
6
+ xmlns="http://www.w3.org/2000/svg"
7
+ role="img"
8
+ viewBox="0 0 38 24"
9
+ aria-labelledby="pi-american_express"
10
+ {...props}
11
+ >
12
+ <title id="pi-american_express">American Express</title>
13
+ <g fill="none">
14
+ <path
15
+ fill="#000"
16
+ d="M35,0 L3,0 C1.3,0 0,1.3 0,3 L0,21 C0,22.7 1.4,24 3,24 L35,24 C36.7,24 38,22.7 38,21 L38,3 C38,1.3 36.6,0 35,0 Z"
17
+ opacity=".07"
18
+ />
19
+ <path
20
+ fill="#006FCF"
21
+ d="M35,1 C36.1,1 37,1.9 37,3 L37,21 C37,22.1 36.1,23 35,23 L3,23 C1.9,23 1,22.1 1,21 L1,3 C1,1.9 1.9,1 3,1 L35,1"
22
+ />
23
+ <path
24
+ fill="#FFF"
25
+ d="M8.971,10.268 L9.745,12.144 L8.203,12.144 L8.971,10.268 Z M25.046,10.346 L22.069,10.346 L22.069,11.173 L24.998,11.173 L24.998,12.412 L22.075,12.412 L22.075,13.334 L25.052,13.334 L25.052,14.073 L27.129,11.828 L25.052,9.488 L25.046,10.346 L25.046,10.346 Z M10.983,8.006 L14.978,8.006 L15.865,9.941 L16.687,8 L27.057,8 L28.135,9.19 L29.25,8 L34.013,8 L30.494,11.852 L33.977,15.68 L29.143,15.68 L28.065,14.49 L26.94,15.68 L10.03,15.68 L9.536,14.49 L8.406,14.49 L7.911,15.68 L4,15.68 L7.286,8 L10.716,8 L10.983,8.006 Z M19.646,9.084 L17.407,9.084 L15.907,12.62 L14.282,9.084 L12.06,9.084 L12.06,13.894 L10,9.084 L8.007,9.084 L5.625,14.596 L7.18,14.596 L7.674,13.406 L10.27,13.406 L10.764,14.596 L13.484,14.596 L13.484,10.661 L15.235,14.602 L16.425,14.602 L18.165,10.673 L18.165,14.603 L19.623,14.603 L19.647,9.083 L19.646,9.084 Z M28.986,11.852 L31.517,9.084 L29.695,9.084 L28.094,10.81 L26.546,9.084 L20.652,9.084 L20.652,14.602 L26.462,14.602 L28.076,12.864 L29.624,14.602 L31.499,14.602 L28.987,11.852 L28.986,11.852 Z"
26
+ />
27
+ </g>
28
+ </svg>
29
+
30
+ )
31
+
32
+ export default Amex
@@ -0,0 +1,13 @@
1
+ import React from 'react'
2
+ import { type LucideProps } from 'lucide-react'
3
+
4
+ const DinersClub: React.FC<LucideProps> = (props: LucideProps) => (
5
+ <svg enableBackground="new 0 0 780 500" viewBox="0 0 780 500" xmlns="http://www.w3.org/2000/svg" {...props}>
6
+ <path d="m40 0h700c22.092 0 40 17.909 40 40v420c0 22.092-17.908 40-40 40h-700c-22.091 0-40-17.908-40-40v-420c0-22.091 17.909-40 40-40z" fill="#0079be"/>
7
+ <path d="m599.93 251.45c0-99.415-82.98-168.13-173.9-168.1h-78.242c-92.003-.033-167.73 68.705-167.73 168.1 0 90.93 75.727 165.64 167.73 165.2h78.242c90.914.436 173.9-74.294 173.9-165.2z" fill="#fff"/>
8
+ <path d="m348.28 97.43c-84.07.027-152.19 68.308-152.21 152.58.02 84.258 68.144 152.53 152.21 152.56 84.09-.027 152.23-68.303 152.24-152.56-.011-84.272-68.149-152.55-152.24-152.58z" fill="#0079be"/>
9
+ <path d="m252.07 249.6c.08-41.181 25.746-76.297 61.94-90.25v180.48c-36.194-13.948-61.861-49.045-61.94-90.23zm131 90.274v-180.53c36.207 13.92 61.914 49.057 61.979 90.257-.065 41.212-25.772 76.322-61.979 90.269z" fill="#fff"/>
10
+ </svg>
11
+ )
12
+
13
+ export default DinersClub