@medusajs/dashboard 3.0.0-snapshot-20251216145629 → 3.0.0-snapshot-20260102134455

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 (290) hide show
  1. package/dist/add-locales-2OZXZCT5.mjs +81 -0
  2. package/dist/{adjust-inventory-26YXAXQL.mjs → adjust-inventory-47KGDWME.mjs} +2 -2
  3. package/dist/{api-key-management-create-EMP32G2D.mjs → api-key-management-create-EFPPZPZ7.mjs} +4 -4
  4. package/dist/{api-key-management-detail-6RCDH73M.mjs → api-key-management-detail-4IFED7SF.mjs} +15 -15
  5. package/dist/{api-key-management-edit-IBM3ZXHK.mjs → api-key-management-edit-QGVBNLUL.mjs} +4 -4
  6. package/dist/{api-key-management-list-KC5GOWAU.mjs → api-key-management-list-ROIJIIPQ.mjs} +4 -4
  7. package/dist/{api-key-management-sales-channels-LUB5G6RC.mjs → api-key-management-sales-channels-7P5L45AT.mjs} +6 -6
  8. package/dist/app.css +33 -3
  9. package/dist/app.js +18467 -16698
  10. package/dist/app.mjs +13 -13
  11. package/dist/{campaign-create-FJOECKGT.mjs → campaign-create-EZGZ4SBQ.mjs} +3 -3
  12. package/dist/{campaign-detail-5Q4BYCPX.mjs → campaign-detail-NFKLFPY4.mjs} +12 -12
  13. package/dist/{categories-metadata-J7M3XWI7.mjs → categories-metadata-G7BACZ26.mjs} +12 -12
  14. package/dist/{category-create-KHJZSC7G.mjs → category-create-7MV25HYX.mjs} +6 -6
  15. package/dist/{category-detail-S5IPXMHX.mjs → category-detail-XJQQ7UU4.mjs} +14 -14
  16. package/dist/{category-edit-CTA2EPDG.mjs → category-edit-LV7EARAB.mjs} +3 -3
  17. package/dist/{category-list-QBYJ4T3R.mjs → category-list-NIVLV5S3.mjs} +6 -6
  18. package/dist/{category-organize-SXP33XET.mjs → category-organize-SCRGWKDG.mjs} +3 -3
  19. package/dist/{category-products-KPW6BA5J.mjs → category-products-FXFSMCR6.mjs} +13 -13
  20. package/dist/{chunk-OXPE5TAY.mjs → chunk-24C2YVFU.mjs} +1 -1
  21. package/dist/{chunk-4JQR6QNW.mjs → chunk-333HK6Y6.mjs} +2 -2
  22. package/dist/{chunk-DODQ3KJT.mjs → chunk-3RRA56WC.mjs} +8 -3
  23. package/dist/{chunk-5LGRZSEH.mjs → chunk-3YPZ3R4U.mjs} +1 -1
  24. package/dist/chunk-5BUFAGKR.mjs +13 -0
  25. package/dist/{chunk-2DULKOPN.mjs → chunk-5ISRTMYH.mjs} +1 -1
  26. package/dist/{chunk-PHLCT2HA.mjs → chunk-5ZPKY5XP.mjs} +1 -1
  27. package/dist/{chunk-U6G4M5LP.mjs → chunk-6EXKKRZY.mjs} +1 -1
  28. package/dist/{chunk-GRZSG4EP.mjs → chunk-74WPAWMW.mjs} +127 -226
  29. package/dist/{chunk-UULAOAFM.mjs → chunk-772OR7OQ.mjs} +358 -242
  30. package/dist/chunk-7AXHHXCX.mjs +4 -0
  31. package/dist/{chunk-BMS2QLJY.mjs → chunk-BMJ5RYIO.mjs} +1 -1
  32. package/dist/{chunk-Y2YVTIJI.mjs → chunk-CW5PQUJ6.mjs} +1 -1
  33. package/dist/{chunk-IAV7IKJ6.mjs → chunk-DN5BRKVN.mjs} +1 -1
  34. package/dist/{chunk-RS7DWLEP.mjs → chunk-DQUXK4WW.mjs} +1 -1
  35. package/dist/{chunk-2XTBDCGE.mjs → chunk-DWH2OQFK.mjs} +1 -1
  36. package/dist/{chunk-CCQD65EY.mjs → chunk-FKNW5MLZ.mjs} +360 -288
  37. package/dist/{chunk-HTCYX4VD.mjs → chunk-G35UUG2P.mjs} +1 -1
  38. package/dist/{chunk-QKALAT7P.mjs → chunk-GGONMC2N.mjs} +1 -1
  39. package/dist/{chunk-FYWHE3W5.mjs → chunk-GJN5SXGZ.mjs} +1 -1
  40. package/dist/{chunk-CVHJAKLQ.mjs → chunk-HDO2UCKF.mjs} +1 -1
  41. package/dist/{chunk-3C6WQ7NH.mjs → chunk-IWNNQ6HA.mjs} +37 -3
  42. package/dist/{chunk-OL24RDYM.mjs → chunk-KHJL6MUQ.mjs} +8 -8
  43. package/dist/{chunk-6P4Q4AAP.mjs → chunk-KPI4WFJU.mjs} +3 -3
  44. package/dist/{chunk-AHZLMCZF.mjs → chunk-KSDXSKJ7.mjs} +1 -1
  45. package/dist/{chunk-BZKI5J2M.mjs → chunk-L7A2JIQY.mjs} +3 -3
  46. package/dist/{chunk-XY7A7GZJ.mjs → chunk-LEAMWI5H.mjs} +1 -1
  47. package/dist/{chunk-A4XYK3MY.mjs → chunk-LG5B2BVB.mjs} +2 -2
  48. package/dist/{chunk-23GTCEOV.mjs → chunk-ML7BA2NY.mjs} +1 -1
  49. package/dist/{chunk-OFN7DIZA.mjs → chunk-OYHFHBNL.mjs} +94 -7
  50. package/dist/{chunk-OSHH5GAS.mjs → chunk-Q34TRFIW.mjs} +1 -13
  51. package/dist/{chunk-UJ2TMPV4.mjs → chunk-QBIQEVTU.mjs} +0 -12
  52. package/dist/{chunk-YYOPBKME.mjs → chunk-QHRAWZGA.mjs} +3 -3
  53. package/dist/{chunk-A2WBKOXJ.mjs → chunk-SO2DE6MM.mjs} +2 -2
  54. package/dist/{chunk-EHU67PIM.mjs → chunk-TOCMU7UV.mjs} +7 -3
  55. package/dist/{chunk-YIOBBZUB.mjs → chunk-U7KANQ5A.mjs} +2 -2
  56. package/dist/{chunk-Z6BFNHEO.mjs → chunk-UCYUWNJL.mjs} +109 -62
  57. package/dist/{chunk-WYATCUOM.mjs → chunk-V2RGYIAG.mjs} +10 -10
  58. package/dist/{chunk-UWY5ZV66.mjs → chunk-VQ73B7ZZ.mjs} +1 -13
  59. package/dist/chunk-XD72PXRS.mjs +329 -0
  60. package/dist/{store-add-locales-VJ4RJ7UI.mjs → chunk-YFXI6CWD.mjs} +2 -67
  61. package/dist/{chunk-AWRCV3ME.mjs → chunk-YM4XGCHB.mjs} +1 -1
  62. package/dist/{chunk-ZMG5B4FG.mjs → chunk-ZGV5NOTE.mjs} +1 -1
  63. package/dist/{collection-add-products-FU2BS3D3.mjs → collection-add-products-YDMBU2JY.mjs} +13 -13
  64. package/dist/{collection-create-GWKWVT7B.mjs → collection-create-RXHEXU6T.mjs} +3 -3
  65. package/dist/{collection-detail-VJE7XHLV.mjs → collection-detail-75XPGVOX.mjs} +13 -13
  66. package/dist/{collection-edit-EZIO2BR5.mjs → collection-edit-CGF47VIN.mjs} +3 -3
  67. package/dist/{collection-list-IGA6SCNF.mjs → collection-list-75N5NYXQ.mjs} +18 -17
  68. package/dist/{collection-metadata-QK7MI3D2.mjs → collection-metadata-TGGC6HM2.mjs} +12 -12
  69. package/dist/{customer-detail-MOV2T3LF.mjs → customer-detail-KDLZ23B3.mjs} +17 -16
  70. package/dist/{customer-group-detail-6T7OXGQD.mjs → customer-group-detail-ZIAVMOYS.mjs} +12 -12
  71. package/dist/{customer-group-list-AJEAF5D2.mjs → customer-group-list-BDDC5VVZ.mjs} +15 -15
  72. package/dist/{customers-add-customer-group-QVTVSQYM.mjs → customers-add-customer-group-B3ASQGP6.mjs} +12 -12
  73. package/dist/{edit-inventory-item-H7DAZWIT.mjs → edit-inventory-item-OKAXQRJ5.mjs} +2 -2
  74. package/dist/{edit-inventory-item-attributes-7HTXXPGZ.mjs → edit-inventory-item-attributes-FVWDV6O5.mjs} +2 -2
  75. package/dist/{edit-reservation-OVTRZHJR.mjs → edit-reservation-3PU6YSNJ.mjs} +3 -3
  76. package/dist/{edit-rules-SMVRTCUP.mjs → edit-rules-LOJ3P4YB.mjs} +14 -14
  77. package/dist/en.json +73 -5
  78. package/dist/{inventory-create-ANYUM4P5.mjs → inventory-create-C2WWS7QR.mjs} +13 -13
  79. package/dist/{inventory-detail-ZPSEMYI2.mjs → inventory-detail-AKOZ4T3Z.mjs} +12 -12
  80. package/dist/{inventory-list-RXJPSVZE.mjs → inventory-list-DRFJIU2O.mjs} +2 -2
  81. package/dist/{inventory-metadata-FNEJ3RAT.mjs → inventory-metadata-N6CJZEWD.mjs} +12 -12
  82. package/dist/{inventory-stock-FD4ZM4BB.mjs → inventory-stock-IJ2N7LKC.mjs} +14 -14
  83. package/dist/{location-detail-N3GUZSY7.mjs → location-detail-PL4Y43RS.mjs} +16 -16
  84. package/dist/{location-fulfillment-providers-7ZUJAGNY.mjs → location-fulfillment-providers-2PLOVSXC.mjs} +17 -16
  85. package/dist/{location-sales-channels-P3QJTFDT.mjs → location-sales-channels-SZARSLWT.mjs} +5 -5
  86. package/dist/{location-service-zone-shipping-option-create-ZJ4GIBTJ.mjs → location-service-zone-shipping-option-create-CUNSAP24.mjs} +15 -15
  87. package/dist/{location-service-zone-shipping-option-edit-4CGPQ3VT.mjs → location-service-zone-shipping-option-edit-OJ462SVM.mjs} +1 -1
  88. package/dist/{location-service-zone-shipping-option-pricing-CR4BVYG3.mjs → location-service-zone-shipping-option-pricing-5HN2Z5RB.mjs} +2 -2
  89. package/dist/login-VBUNWZHI.mjs +301 -0
  90. package/dist/{manage-locations-7HH6R4UP.mjs → manage-locations-JPCSBA5D.mjs} +2 -2
  91. package/dist/{order-allocate-items-HZGGYJ42.mjs → order-allocate-items-6QHQASQJ.mjs} +4 -4
  92. package/dist/{order-create-claim-SCDJGM46.mjs → order-create-claim-ECVSH5GC.mjs} +22 -22
  93. package/dist/{order-create-edit-JIE3HDHP.mjs → order-create-edit-EVIOJIXE.mjs} +14 -13
  94. package/dist/{order-create-exchange-LQU4YN7F.mjs → order-create-exchange-ZVYYOGI3.mjs} +22 -22
  95. package/dist/{order-create-fulfillment-OWUVTZXW.mjs → order-create-fulfillment-FDIFEV6X.mjs} +16 -16
  96. package/dist/{order-create-refund-Q6HQY42R.mjs → order-create-refund-TNPGKR5P.mjs} +17 -17
  97. package/dist/{order-create-return-52GHGW5Z.mjs → order-create-return-NR6XQLDD.mjs} +9 -9
  98. package/dist/{order-create-shipment-WAGGEPRW.mjs → order-create-shipment-UP3WGRWB.mjs} +12 -12
  99. package/dist/{order-detail-PVPGEWGY.mjs → order-detail-F6D5DV74.mjs} +28 -28
  100. package/dist/{order-edit-billing-address-UM76J4KX.mjs → order-edit-billing-address-D4AJ6Z5Q.mjs} +44 -12
  101. package/dist/{order-edit-email-CL3KNOCM.mjs → order-edit-email-MXYA5BII.mjs} +12 -12
  102. package/dist/{order-edit-shipping-address-PIESTGVL.mjs → order-edit-shipping-address-GKW2ZPGR.mjs} +42 -12
  103. package/dist/{order-export-LE363ZLB.mjs → order-export-KQUI2TK7.mjs} +14 -14
  104. package/dist/{order-list-GRLQWN4L.mjs → order-list-7A5UKGXR.mjs} +11 -11
  105. package/dist/{order-metadata-FHBB7MTG.mjs → order-metadata-2IXELA7C.mjs} +12 -12
  106. package/dist/{order-receive-return-PRVKP6J2.mjs → order-receive-return-XXHOXGDC.mjs} +13 -13
  107. package/dist/{order-request-transfer-XSAGRUMT.mjs → order-request-transfer-2ENR64VR.mjs} +13 -13
  108. package/dist/{price-list-configuration-6S3MLNXQ.mjs → price-list-configuration-BZ3ZH5FY.mjs} +3 -3
  109. package/dist/{price-list-create-MFRUQADC.mjs → price-list-create-GFGNP6OS.mjs} +16 -16
  110. package/dist/{price-list-detail-Q5VG5VGW.mjs → price-list-detail-SNNOR5N7.mjs} +17 -17
  111. package/dist/{price-list-edit-53UW35L3.mjs → price-list-edit-YW5BXBF2.mjs} +3 -3
  112. package/dist/{price-list-list-DG5YEZ44.mjs → price-list-list-OF562HME.mjs} +4 -4
  113. package/dist/{price-list-prices-add-SDU5YZAT.mjs → price-list-prices-add-F7A2EV7L.mjs} +15 -15
  114. package/dist/{price-list-prices-edit-5USQR4D4.mjs → price-list-prices-edit-PQ26MOJE.mjs} +5 -5
  115. package/dist/{product-attributes-K4FGFORS.mjs → product-attributes-HO2B4OHP.mjs} +13 -13
  116. package/dist/{product-create-7YTRHZQQ.mjs → product-create-UEVW5JO4.mjs} +485 -561
  117. package/dist/{product-create-variant-ERKHTEJZ.mjs → product-create-variant-PLZ5Q2R6.mjs} +14 -14
  118. package/dist/{product-detail-32ZXNWOP.mjs → product-detail-Z7K5TGZY.mjs} +45 -66
  119. package/dist/{product-edit-FBAKONMR.mjs → product-edit-6I6JG4GP.mjs} +13 -13
  120. package/dist/{product-export-5AD7NELI.mjs → product-export-UMMROQ7T.mjs} +18 -17
  121. package/dist/{product-image-variants-edit-M6QF2RLE.mjs → product-image-variants-edit-VRG3AJID.mjs} +12 -12
  122. package/dist/{product-import-V3KQN4TV.mjs → product-import-EPS4KDID.mjs} +12 -12
  123. package/dist/{product-list-EUWZIFTM.mjs → product-list-37O7VB2L.mjs} +20 -20
  124. package/dist/{product-media-3VJ7KENL.mjs → product-media-IV5NUSLW.mjs} +3 -3
  125. package/dist/{product-metadata-GL2MVPDI.mjs → product-metadata-KTVRI7B3.mjs} +12 -12
  126. package/dist/product-option-create-C5BPN6P6.mjs +268 -0
  127. package/dist/product-option-detail-VVK3YBCE.mjs +331 -0
  128. package/dist/product-option-edit-7FQSKI2R.mjs +325 -0
  129. package/dist/product-option-list-YHGRI7OJ.mjs +268 -0
  130. package/dist/product-option-metadata-P2DHDGYR.mjs +73 -0
  131. package/dist/product-options-manage-B4N54NCR.mjs +358 -0
  132. package/dist/{product-organization-IUSVX22S.mjs → product-organization-L23V4JA7.mjs} +15 -15
  133. package/dist/{product-prices-4C36AG4R.mjs → product-prices-GUO3KM2U.mjs} +3 -3
  134. package/dist/{product-sales-channels-PPXUG4KT.mjs → product-sales-channels-BOZD3AC3.mjs} +5 -5
  135. package/dist/{product-shipping-profile-ETQFZ7DC.mjs → product-shipping-profile-FNFRDY47.mjs} +3 -3
  136. package/dist/{product-stock-VEGE6SUZ.mjs → product-stock-2DNYG73L.mjs} +14 -14
  137. package/dist/{product-tag-create-PQMDDKWH.mjs → product-tag-create-CW7GUCZW.mjs} +12 -12
  138. package/dist/{product-tag-detail-I3MBZX7U.mjs → product-tag-detail-IB5VIZ3K.mjs} +26 -25
  139. package/dist/{product-tag-edit-K3BBQLJR.mjs → product-tag-edit-ZSXD3DOC.mjs} +12 -12
  140. package/dist/{product-tag-list-JUWSOMB7.mjs → product-tag-list-MJO5PURP.mjs} +24 -23
  141. package/dist/{product-tag-metadata-MJH5LH7E.mjs → product-tag-metadata-DAKCXWZF.mjs} +12 -12
  142. package/dist/{product-type-create-DRFXTL5O.mjs → product-type-create-NRLNMABQ.mjs} +2 -2
  143. package/dist/{product-type-detail-RKHT5NBL.mjs → product-type-detail-J2IMAZW6.mjs} +14 -14
  144. package/dist/{product-type-edit-SRHCZDK7.mjs → product-type-edit-BHTPMMVI.mjs} +2 -2
  145. package/dist/{product-type-list-QQKAHBJ3.mjs → product-type-list-MQ2PW2IE.mjs} +3 -3
  146. package/dist/{product-type-metadata-CDJDFFGQ.mjs → product-type-metadata-BCZMUG3K.mjs} +12 -12
  147. package/dist/{product-variant-detail-XAYG5CKE.mjs → product-variant-detail-4L6DHT3K.mjs} +12 -12
  148. package/dist/{product-variant-edit-DEZEY2H2.mjs → product-variant-edit-PZU4P65H.mjs} +13 -13
  149. package/dist/{product-variant-manage-inventory-items-Y2VEOHP7.mjs → product-variant-manage-inventory-items-E3GPBPEZ.mjs} +3 -3
  150. package/dist/{product-variant-media-2WLVNGI4.mjs → product-variant-media-BSNCO642.mjs} +2 -2
  151. package/dist/{product-variant-metadata-VTZDNWUT.mjs → product-variant-metadata-FHGGZGPV.mjs} +12 -12
  152. package/dist/{promotion-add-campaign-DO67QK6M.mjs → promotion-add-campaign-NQSIFI33.mjs} +3 -3
  153. package/dist/{promotion-create-HWFNUQXG.mjs → promotion-create-GBZWJVAI.mjs} +24 -21
  154. package/dist/{promotion-detail-QC36KXB3.mjs → promotion-detail-W2OGUESO.mjs} +12 -12
  155. package/dist/{refund-reason-create-YHCDEHGQ.mjs → refund-reason-create-DLVRT5OU.mjs} +12 -12
  156. package/dist/{refund-reason-edit-CZ5QZ2SZ.mjs → refund-reason-edit-XCSU7RMH.mjs} +12 -12
  157. package/dist/{refund-reason-list-OJYYEYJE.mjs → refund-reason-list-G6UNVGPG.mjs} +18 -18
  158. package/dist/{region-create-NA7Y2LN4.mjs → region-create-2CRTF7HJ.mjs} +1 -1
  159. package/dist/{region-edit-WAU347DP.mjs → region-edit-IB3PJE7V.mjs} +1 -1
  160. package/dist/{region-metadata-H6XXUQ4S.mjs → region-metadata-WBEUKOI6.mjs} +12 -12
  161. package/dist/{reservation-create-ZCIYM6JI.mjs → reservation-create-ERFJUBME.mjs} +4 -4
  162. package/dist/{reservation-detail-LZAQL4XA.mjs → reservation-detail-Y6UZRZXY.mjs} +12 -12
  163. package/dist/{reservation-list-B47DXTA7.mjs → reservation-list-LEDZB7KL.mjs} +3 -3
  164. package/dist/{reservation-metadata-5HZSDDOK.mjs → reservation-metadata-7KH4EXMN.mjs} +12 -12
  165. package/dist/{return-reason-list-SCBGTOEI.mjs → return-reason-list-UUQAL464.mjs} +6 -6
  166. package/dist/{sales-channel-add-products-F7YV4MO5.mjs → sales-channel-add-products-GSPG7OTK.mjs} +14 -14
  167. package/dist/{sales-channel-create-MI7HHZYE.mjs → sales-channel-create-MM237EBQ.mjs} +3 -3
  168. package/dist/{sales-channel-detail-MXIPZCGA.mjs → sales-channel-detail-65ZFV2OI.mjs} +14 -14
  169. package/dist/{sales-channel-edit-VSHOIR37.mjs → sales-channel-edit-AC2J4N3M.mjs} +3 -3
  170. package/dist/{sales-channel-list-RLGL7FM3.mjs → sales-channel-list-LXLW7X3U.mjs} +14 -14
  171. package/dist/{sales-channel-metadata-M364R4RJ.mjs → sales-channel-metadata-QUAL2RH6.mjs} +13 -13
  172. package/dist/{shipping-option-type-create-C5WUWON7.mjs → shipping-option-type-create-EU75JC2Q.mjs} +12 -12
  173. package/dist/{shipping-option-type-detail-PENS2K73.mjs → shipping-option-type-detail-5GYEWATD.mjs} +13 -13
  174. package/dist/{shipping-option-type-edit-CIU5EHRP.mjs → shipping-option-type-edit-YR4JXT5M.mjs} +12 -12
  175. package/dist/{shipping-option-type-list-DIOX7VG7.mjs → shipping-option-type-list-BLC4Z5QW.mjs} +13 -13
  176. package/dist/{shipping-profile-metadata-75G2NNMA.mjs → shipping-profile-metadata-64YRWPDA.mjs} +12 -12
  177. package/dist/store-add-locales-TSMLNFZP.mjs +81 -0
  178. package/dist/{store-detail-JSNPOB2F.mjs → store-detail-3SS53LZR.mjs} +13 -13
  179. package/dist/{store-edit-5ZS562ZO.mjs → store-edit-SMEWFETF.mjs} +1 -1
  180. package/dist/{store-metadata-CYXTVJUE.mjs → store-metadata-IJGVDDA6.mjs} +12 -12
  181. package/dist/{tax-region-create-DWGL4EUT.mjs → tax-region-create-XLYIS5XX.mjs} +13 -13
  182. package/dist/{tax-region-detail-2AE2EFI3.mjs → tax-region-detail-66FKEGFB.mjs} +29 -28
  183. package/dist/{tax-region-edit-EEVEEU2Q.mjs → tax-region-edit-GBR4EDW7.mjs} +13 -13
  184. package/dist/{tax-region-province-detail-4ERSEQFF.mjs → tax-region-province-detail-OBA7Q7MQ.mjs} +29 -28
  185. package/dist/{tax-region-tax-override-create-PHCGEF7V.mjs → tax-region-tax-override-create-34WYD2QZ.mjs} +28 -27
  186. package/dist/{tax-region-tax-override-edit-SMRPSILC.mjs → tax-region-tax-override-edit-6WJVOGWA.mjs} +27 -26
  187. package/dist/translation-list-J65VNNAX.mjs +527 -0
  188. package/dist/{translations-edit-KECSHYZY.mjs → translations-edit-6P3KC4MO.mjs} +280 -304
  189. package/dist/{user-detail-BJUXLZZQ.mjs → user-detail-VMOJFHIJ.mjs} +2 -2
  190. package/dist/{user-metadata-2WPJOEJA.mjs → user-metadata-UOPVFX2L.mjs} +12 -12
  191. package/dist/{workflow-execution-detail-H2AKEZJX.mjs → workflow-execution-detail-WAQ7IG4T.mjs} +12 -12
  192. package/package.json +9 -9
  193. package/src/components/data-grid/components/data-grid-cell-container.tsx +7 -10
  194. package/src/components/data-grid/components/data-grid-multiline-cell.tsx +103 -0
  195. package/src/components/data-grid/components/data-grid-readonly-cell.tsx +1 -4
  196. package/src/components/data-grid/components/data-grid-root.tsx +68 -51
  197. package/src/components/data-grid/components/data-grid-text-cell.tsx +6 -76
  198. package/src/components/data-grid/components/index.ts +1 -0
  199. package/src/components/data-grid/data-grid.tsx +2 -0
  200. package/src/components/data-grid/hooks/use-data-grid-cell.tsx +12 -0
  201. package/src/components/data-grid/hooks/use-data-grid-form-handlers.tsx +1 -0
  202. package/src/components/data-grid/hooks/use-data-grid-keydown-event.tsx +65 -7
  203. package/src/components/data-grid/types.ts +1 -0
  204. package/src/components/inputs/combobox/combobox.tsx +185 -95
  205. package/src/components/layout/main-layout/main-layout.tsx +7 -4
  206. package/src/components/table/table-cells/order/country-cell/country-cell.tsx +5 -1
  207. package/src/dashboard-app/routes/get-route.map.tsx +68 -12
  208. package/src/hooks/api/cloud.tsx +41 -0
  209. package/src/hooks/api/index.ts +3 -1
  210. package/src/hooks/api/product-options.tsx +151 -0
  211. package/src/hooks/api/products.tsx +26 -66
  212. package/src/hooks/api/translations.tsx +103 -191
  213. package/src/hooks/table/columns/use-order-table-columns.tsx +5 -3
  214. package/src/hooks/table/columns/use-product-option-table-columns.tsx +44 -0
  215. package/src/hooks/table/filters/index.ts +1 -0
  216. package/src/hooks/table/filters/use-product-option-table-filters.tsx +33 -0
  217. package/src/hooks/table/query/use-product-option-table-query.tsx +34 -0
  218. package/src/i18n/translations/$schema.json +290 -32
  219. package/src/i18n/translations/en.json +73 -5
  220. package/src/i18n/translations/es.json +9 -1
  221. package/src/routes/customers/customer-detail/components/customer-order-section/customer-order-section.tsx +1 -1
  222. package/src/routes/login/components/cloud-auth-login.tsx +114 -0
  223. package/src/routes/login/login.tsx +9 -1
  224. package/src/routes/orders/order-create-edit/components/order-edit-create-form/order-edit-item.tsx +1 -0
  225. package/src/routes/orders/order-edit-billing-address/components/edit-order-billing-address-form/edit-order-billing-address-form.tsx +34 -0
  226. package/src/routes/orders/order-edit-shipping-address/components/edit-order-shipping-address-form/edit-order-shipping-address-form.tsx +32 -0
  227. package/src/routes/product-options/common/hooks/use-delete-product-option-action.tsx +41 -0
  228. package/src/routes/product-options/product-option-create/components/create-product-option-form/create-product-option-details.tsx +71 -0
  229. package/src/routes/product-options/product-option-create/components/create-product-option-form/create-product-option-form.tsx +97 -0
  230. package/src/routes/product-options/product-option-create/components/create-product-option-form/create-product-option-organize.tsx +92 -0
  231. package/src/routes/product-options/product-option-create/components/create-product-option-form/index.ts +1 -0
  232. package/src/routes/product-options/product-option-create/components/create-product-option-form/schema.ts +15 -0
  233. package/src/routes/product-options/product-option-create/index.ts +1 -0
  234. package/src/routes/product-options/product-option-create/product-option-create.tsx +10 -0
  235. package/src/routes/product-options/product-option-detail/breadcrumb.tsx +14 -0
  236. package/src/routes/product-options/product-option-detail/components/product-option-general-section/index.ts +1 -0
  237. package/src/routes/product-options/product-option-detail/components/product-option-general-section/product-option-general-section.tsx +84 -0
  238. package/src/routes/product-options/product-option-detail/components/product-option-product-section/index.ts +1 -0
  239. package/src/routes/product-options/product-option-detail/components/product-option-product-section/product-option-product-section.tsx +82 -0
  240. package/src/routes/product-options/product-option-detail/index.ts +3 -0
  241. package/src/routes/product-options/product-option-detail/loader.ts +18 -0
  242. package/src/routes/product-options/product-option-detail/product-option-detail.tsx +50 -0
  243. package/src/routes/product-options/product-option-edit/components/edit-product-option-form/edit-product-option-details.tsx +94 -0
  244. package/src/routes/product-options/product-option-edit/components/edit-product-option-form/edit-product-option-form.tsx +116 -0
  245. package/src/routes/product-options/product-option-edit/components/edit-product-option-form/edit-product-option-organize.tsx +77 -0
  246. package/src/routes/product-options/product-option-edit/components/edit-product-option-form/index.ts +1 -0
  247. package/src/routes/product-options/product-option-edit/components/edit-product-option-form/schema.ts +13 -0
  248. package/src/routes/product-options/product-option-edit/index.ts +1 -0
  249. package/src/routes/product-options/product-option-edit/product-option-edit.tsx +34 -0
  250. package/src/routes/product-options/product-option-list/components/product-option-list-table/index.ts +1 -0
  251. package/src/routes/product-options/product-option-list/components/product-option-list-table/product-option-list-table.tsx +140 -0
  252. package/src/routes/product-options/product-option-list/index.ts +1 -0
  253. package/src/routes/product-options/product-option-list/product-option-list.tsx +19 -0
  254. package/src/routes/product-options/product-option-metadata/index.ts +1 -0
  255. package/src/routes/product-options/product-option-metadata/product-option-metadata.tsx +27 -0
  256. package/src/routes/products/product-create/components/product-create-details-form/components/product-create-details-general-section/product-create-general-section.tsx +16 -4
  257. package/src/routes/products/product-create/components/product-create-details-form/components/product-create-details-variant-section/product-create-details-variant-section.tsx +327 -194
  258. package/src/routes/products/product-create/components/product-create-form/product-create-form.tsx +4 -7
  259. package/src/routes/products/product-create/constants.ts +2 -0
  260. package/src/routes/products/product-create/utils.ts +6 -1
  261. package/src/routes/products/product-detail/components/product-option-section/product-option-section.tsx +33 -51
  262. package/src/routes/products/product-options-manage/components/product-options-manage-form/index.ts +1 -0
  263. package/src/routes/products/product-options-manage/components/product-options-manage-form/product-options-manage-form.tsx +328 -0
  264. package/src/routes/products/product-options-manage/index.ts +1 -0
  265. package/src/routes/products/product-options-manage/product-options-manage.tsx +35 -0
  266. package/src/routes/promotions/promotion-create/components/create-promotion-form/create-promotion-form.tsx +6 -0
  267. package/src/routes/translations/add-locales/add-locales.tsx +29 -0
  268. package/src/routes/translations/add-locales/index.tsx +1 -0
  269. package/src/routes/translations/translation-list/components/active-locales-section/active-locales-section.tsx +42 -17
  270. package/src/routes/translations/translation-list/components/translation-list-section/translation-list-section.tsx +5 -1
  271. package/src/routes/translations/translation-list/components/translations-completion-section/translations-completion-section.tsx +182 -121
  272. package/src/routes/translations/translations-edit/components/translations-edit-form/translations-edit-form.tsx +330 -361
  273. package/src/routes/translations/translations-edit/translations-edit.tsx +8 -13
  274. package/dist/chunk-HGRIOEAR.mjs +0 -32
  275. package/dist/chunk-XDJ7OMBR.mjs +0 -160
  276. package/dist/login-VNOLI5YG.mjs +0 -201
  277. package/dist/product-create-option-7AOXAA4S.mjs +0 -151
  278. package/dist/product-edit-option-LWJT3CYJ.mjs +0 -156
  279. package/dist/translation-list-UF7FLXOW.mjs +0 -441
  280. package/src/routes/products/product-create-option/components/create-product-option-form/create-product-option-form.tsx +0 -122
  281. package/src/routes/products/product-create-option/components/create-product-option-form/index.ts +0 -1
  282. package/src/routes/products/product-create-option/index.ts +0 -1
  283. package/src/routes/products/product-create-option/product-create-option.tsx +0 -30
  284. package/src/routes/products/product-edit-option/components/edit-product-option-form/edit-product-option-form.tsx +0 -123
  285. package/src/routes/products/product-edit-option/components/edit-product-option-form/index.ts +0 -1
  286. package/src/routes/products/product-edit-option/index.ts +0 -1
  287. package/src/routes/products/product-edit-option/product-edit-option.tsx +0 -35
  288. package/dist/{chunk-FBYTX6K7.mjs → chunk-ORWRXJJT.mjs} +4 -4
  289. package/dist/{location-list-KVBA6J47.mjs → location-list-3WP65J3E.mjs} +1 -1
  290. package/dist/{user-list-YTZQNYSO.mjs → user-list-3EAKK4XC.mjs} +3 -3
@@ -1,37 +1,43 @@
1
- import { XMarkMini } from "@medusajs/icons"
2
1
  import {
3
2
  Alert,
4
- Button,
5
3
  Checkbox,
6
4
  clx,
7
5
  Heading,
8
6
  Hint,
9
- IconButton,
10
7
  InlineTip,
11
- Input,
12
8
  Label,
13
9
  Text,
14
10
  } from "@medusajs/ui"
15
11
  import {
16
- Controller,
17
12
  FieldArrayWithId,
18
13
  useFieldArray,
19
14
  UseFormReturn,
20
15
  useWatch,
21
16
  } from "react-hook-form"
22
17
  import { useTranslation } from "react-i18next"
18
+ import { useMemo } from "react"
23
19
 
24
20
  import { Form } from "../../../../../../../components/common/form"
25
21
  import { SortableList } from "../../../../../../../components/common/sortable-list"
26
22
  import { SwitchBox } from "../../../../../../../components/common/switch-box"
27
23
  import { ChipInput } from "../../../../../../../components/inputs/chip-input"
24
+ import { Combobox } from "../../../../../../../components/inputs/combobox"
28
25
  import { ProductCreateSchemaType } from "../../../../types"
29
26
  import { decorateVariantsWithDefaultValues } from "../../../../utils"
27
+ import { useProductOptions } from "../../../../../../../hooks/api"
28
+ import { AdminProductOption } from "@medusajs/types"
30
29
 
31
30
  type ProductCreateVariantsSectionProps = {
32
31
  form: UseFormReturn<ProductCreateSchemaType>
33
32
  }
34
33
 
34
+ type ProductOptionFormValue = {
35
+ title: string
36
+ values: string[]
37
+ id?: string
38
+ value_ids?: string[]
39
+ }
40
+
35
41
  const getPermutations = (
36
42
  data: { title: string; values: string[] }[]
37
43
  ): { [key: string]: string }[] => {
@@ -65,11 +71,6 @@ export const ProductCreateVariantsSection = ({
65
71
  }: ProductCreateVariantsSectionProps) => {
66
72
  const { t } = useTranslation()
67
73
 
68
- const options = useFieldArray({
69
- control: form.control,
70
- name: "options",
71
- })
72
-
73
74
  const variants = useFieldArray({
74
75
  control: form.control,
75
76
  name: "variants",
@@ -97,92 +98,194 @@ export const ProductCreateVariantsSection = ({
97
98
  const showInvalidVariantsMessage =
98
99
  form.formState.errors.variants?.root?.message === "invalid_length"
99
100
 
100
- const handleOptionValueUpdate = (index: number, value: string[]) => {
101
- const { isTouched: hasUserSelectedVariants } =
102
- form.getFieldState("variants")
103
-
104
- const newOptions = [...watchedOptions]
105
- newOptions[index].values = value
101
+ const { product_options = [], isLoading } = useProductOptions({
102
+ is_exclusive: false,
103
+ })
106
104
 
107
- const permutations = getPermutations(
108
- newOptions.filter(({ values }) => values.length)
105
+ const productOptionChoices = useMemo(() => {
106
+ const existingChoices = product_options.map((option) => ({
107
+ value: option.id,
108
+ label: option.title,
109
+ }))
110
+
111
+ const newChoices = watchedOptions
112
+ .filter((opt) => !opt.id && opt.title)
113
+ .map((opt) => ({
114
+ value: opt.title,
115
+ label: opt.title,
116
+ }))
117
+
118
+ return [...existingChoices, ...newChoices]
119
+ }, [product_options, watchedOptions])
120
+
121
+ const selectedOptionValues = useMemo(() => {
122
+ return watchedOptions.map((opt) => opt.id || opt.title)
123
+ }, [watchedOptions])
124
+
125
+ const handleProductOptionSelect = (optionValues: string[]) => {
126
+ const existingOptionIds = optionValues.filter((val) =>
127
+ product_options.some((opt) => opt.id === val)
128
+ )
129
+ const newOptionTitles = optionValues.filter(
130
+ (val) => !product_options.some((opt) => opt.id === val)
109
131
  )
110
- const oldVariants = [...watchedVariants]
111
-
112
- const findMatchingPermutation = (options: Record<string, string>) => {
113
- return permutations.find((permutation) =>
114
- Object.keys(options).every((key) => options[key] === permutation[key])
115
- )
116
- }
117
132
 
118
- const newVariants = oldVariants.reduce((variants, variant) => {
119
- const match = findMatchingPermutation(variant.options)
133
+ const allSelectedOptions: Array<
134
+ AdminProductOption | { title: string; values: string[] }
135
+ > = []
120
136
 
121
- if (match) {
122
- variants.push({
123
- ...variant,
124
- title: getVariantName(match),
125
- options: match,
137
+ const selectedProductOptions = product_options.filter((option) =>
138
+ existingOptionIds.includes(option.id)
139
+ )
140
+ allSelectedOptions.push(...selectedProductOptions)
141
+
142
+ const watchedOptions = form.getValues("options")
143
+ watchedOptions.forEach((opt) => {
144
+ if (!opt.id && opt.title && newOptionTitles.includes(opt.title)) {
145
+ allSelectedOptions.push({
146
+ title: opt.title,
147
+ values: opt.values || [],
126
148
  })
127
149
  }
150
+ })
128
151
 
129
- return variants
130
- }, [] as typeof oldVariants)
152
+ const newSelectedValues: Record<string, string[]> = {}
131
153
 
132
- const usedPermutations = new Set(
133
- newVariants.map((variant) => variant.options)
134
- )
135
- const unusedPermutations = permutations.filter(
136
- (permutation) => !usedPermutations.has(permutation)
154
+ allSelectedOptions.forEach((option) => {
155
+ if ("id" in option && option.id) {
156
+ const currentOption = watchedOptions.find((opt) => opt.id === option.id)
157
+ if (currentOption?.value_ids) {
158
+ newSelectedValues[option.id] = currentOption.value_ids
159
+ } else {
160
+ newSelectedValues[option.id] = option.values?.map((v) => v.id) || []
161
+ }
162
+ }
163
+ })
164
+
165
+ updateFormWithSelectedValues(allSelectedOptions, newSelectedValues)
166
+ }
167
+
168
+ const generateAndSetVariants = (options: ProductOptionFormValue[]) => {
169
+ const permutations = getPermutations(
170
+ options.filter(({ values }) => values && values.length > 0)
137
171
  )
138
172
 
139
- unusedPermutations.forEach((permutation) => {
140
- newVariants.push({
141
- title: getVariantName(permutation),
142
- options: permutation,
143
- should_create: hasUserSelectedVariants ? false : true,
144
- variant_rank: newVariants.length,
145
- // NOTE - prepare inventory array here for now so we prevent rendering issue if we append the items later
146
- inventory: [{ inventory_item_id: "", required_quantity: "" }],
147
- })
148
- })
173
+ const newVariants = permutations.map((permutation, index) => ({
174
+ title: getVariantName(permutation),
175
+ options: permutation,
176
+ should_create: true,
177
+ variant_rank: index,
178
+ inventory: [{ inventory_item_id: "", required_quantity: "" }],
179
+ }))
149
180
 
150
181
  form.setValue("variants", newVariants)
151
182
  }
152
183
 
153
- const handleRemoveOption = (index: number) => {
154
- if (index === 0) {
184
+ const handleValueChange = (optionId: string, valueIds: string[]) => {
185
+ if (valueIds.length === 0) {
155
186
  return
156
187
  }
157
188
 
158
- options.remove(index)
189
+ const currentOption = watchedOptions.find((opt) => opt.id === optionId)
190
+ if (!currentOption) {
191
+ return
192
+ }
159
193
 
160
- const newOptions = [...watchedOptions]
161
- newOptions.splice(index, 1)
162
- const validOptionTitles = new Set(newOptions.map((option) => option.title))
194
+ const productOption = product_options.find((opt) => opt.id === optionId)
195
+ const existingValueIds = new Set(
196
+ productOption?.values?.map((v) => v.id) || []
197
+ )
163
198
 
164
- const permutations = getPermutations(newOptions)
165
- const oldVariants = [...watchedVariants]
199
+ const validValueIds: string[] = []
200
+ const newValueNames: string[] = []
166
201
 
167
- const newVariants = permutations.reduce((variants, permutation) => {
168
- const variant = oldVariants.find(({ options }) =>
169
- Object.keys(options)
170
- .filter((option) => validOptionTitles.has(option))
171
- .every((key) => options[key] === permutation[key])
172
- )
202
+ valueIds.forEach((id) => {
203
+ if (existingValueIds.has(id)) {
204
+ validValueIds.push(id)
205
+ } else {
206
+ newValueNames.push(id)
207
+ }
208
+ })
173
209
 
174
- if (variant) {
175
- variants.push({
176
- ...variant,
177
- title: variant.title,
178
- options: permutation,
179
- })
210
+ const updatedOptions = watchedOptions.map((opt) => {
211
+ if (opt.id === optionId) {
212
+ const selectedExistingValues =
213
+ productOption?.values
214
+ ?.filter((v) => validValueIds.includes(v.id))
215
+ .map((v) => v.value) || []
216
+
217
+ return {
218
+ ...opt,
219
+ value_ids: valueIds,
220
+ values: [...selectedExistingValues, ...newValueNames],
221
+ }
180
222
  }
223
+ return opt
224
+ })
181
225
 
182
- return variants
183
- }, [] as typeof oldVariants)
226
+ form.setValue("options", updatedOptions)
227
+ generateAndSetVariants(updatedOptions)
228
+ }
184
229
 
185
- form.setValue("variants", newVariants)
230
+ const handleNewOptionValueChange = (
231
+ optionTitle: string,
232
+ valueNames: string[]
233
+ ) => {
234
+ const updatedOptions = watchedOptions.map((opt) => {
235
+ if (!opt.id && opt.title === optionTitle) {
236
+ return {
237
+ ...opt,
238
+ values: valueNames,
239
+ }
240
+ }
241
+ return opt
242
+ })
243
+
244
+ form.setValue("options", updatedOptions)
245
+ generateAndSetVariants(updatedOptions)
246
+ }
247
+
248
+ const updateFormWithSelectedValues = (
249
+ selectedProductOptions: Array<
250
+ AdminProductOption | { title: string; values: string[] }
251
+ >,
252
+ valueSelections: Record<string, string[]>
253
+ ) => {
254
+ const newOptions: ProductOptionFormValue[] = selectedProductOptions.map(
255
+ (option) => {
256
+ if ("id" in option && option.id !== undefined) {
257
+ const existingOption = option as AdminProductOption
258
+ const selectedValueIds = valueSelections[existingOption.id] || []
259
+ const allValues = option.values || []
260
+
261
+ const selectedValues = allValues
262
+ .filter((v) => selectedValueIds.includes(v.id))
263
+ .sort((a, b) => {
264
+ const rankA = a.rank ?? Number.MAX_VALUE
265
+ const rankB = b.rank ?? Number.MAX_VALUE
266
+ return rankA - rankB
267
+ })
268
+ .map((v) => v.value)
269
+
270
+ return {
271
+ id: existingOption.id,
272
+ title: existingOption.title,
273
+ values: selectedValues,
274
+ value_ids:
275
+ selectedValueIds.length > 0 ? selectedValueIds : undefined,
276
+ }
277
+ } else {
278
+ const newOption = option as { title: string; values: string[] }
279
+ return {
280
+ title: newOption.title,
281
+ values: newOption.values,
282
+ }
283
+ }
284
+ }
285
+ )
286
+
287
+ form.setValue("options", newOptions)
288
+ generateAndSetVariants(newOptions)
186
289
  }
187
290
 
188
291
  const handleRankChange = (
@@ -295,132 +398,162 @@ export const ProductCreateVariantsSection = ({
295
398
  {watchedAreVariantsEnabled && (
296
399
  <>
297
400
  <div className="flex flex-col gap-y-6">
298
- <Form.Field
299
- control={form.control}
300
- name="options"
301
- render={() => {
302
- return (
303
- <Form.Item>
304
- <div className="flex flex-col gap-y-6">
305
- <div className="flex items-start justify-between gap-x-4">
306
- <div className="flex flex-col">
307
- <Form.Label>
308
- {t("products.create.variants.productOptions.label")}
309
- </Form.Label>
310
- <Form.Hint>
311
- {t("products.create.variants.productOptions.hint")}
312
- </Form.Hint>
313
- </div>
314
- <Button
315
- size="small"
316
- variant="secondary"
317
- type="button"
318
- onClick={() => {
319
- options.append({
320
- title: "",
321
- values: [],
322
- })
323
- }}
324
- >
325
- {t("actions.add")}
326
- </Button>
327
- </div>
328
- {showInvalidOptionsMessage && (
329
- <Alert dismissible variant="error">
330
- {t("products.create.errors.options")}
331
- </Alert>
332
- )}
333
- <ul className="flex flex-col gap-y-4">
334
- {options.fields.map((option, index) => {
335
- const hasError =
336
- !!form.formState.errors.options?.[index]
337
- return (
338
- <li
339
- key={option.id}
340
- className={clx(
341
- "bg-ui-bg-component shadow-elevation-card-rest grid grid-cols-[1fr_28px] items-center gap-1.5 rounded-xl p-1.5",
342
- {
343
- "border-ui-border-error shadow-borders-error":
344
- hasError,
345
- }
346
- )}
347
- >
348
- <div className="grid grid-cols-[min-content,1fr] items-center gap-1.5">
349
- <div className="flex items-center px-2 py-1.5">
350
- <Label
351
- size="xsmall"
352
- weight="plus"
353
- className="text-ui-fg-subtle"
354
- htmlFor={`options.${index}.title`}
355
- >
356
- {t("fields.title")}
357
- </Label>
358
- </div>
359
- <Input
360
- className="bg-ui-bg-field-component hover:bg-ui-bg-field-component-hover"
361
- {...form.register(
362
- `options.${index}.title` as const
363
- )}
364
- placeholder={t(
365
- "products.fields.options.optionTitlePlaceholder"
366
- )}
367
- />
368
- <div className="flex items-center px-2 py-1.5">
369
- <Label
370
- size="xsmall"
371
- weight="plus"
372
- className="text-ui-fg-subtle"
373
- htmlFor={`options.${index}.values`}
374
- >
375
- {t("fields.values")}
376
- </Label>
377
- </div>
378
- <Controller
379
- control={form.control}
380
- name={`options.${index}.values` as const}
381
- render={({
382
- field: { onChange, ...field },
383
- }) => {
384
- const handleValueChange = (
385
- value: string[]
386
- ) => {
387
- handleOptionValueUpdate(index, value)
388
- onChange(value)
389
- }
390
-
391
- return (
392
- <ChipInput
393
- {...field}
394
- variant="contrast"
395
- onChange={handleValueChange}
396
- placeholder={t(
397
- "products.fields.options.variantionsPlaceholder"
398
- )}
399
- />
400
- )
401
- }}
402
- />
403
- </div>
404
- <IconButton
405
- type="button"
406
- size="small"
407
- variant="transparent"
408
- className="text-ui-fg-muted"
409
- disabled={index === 0}
410
- onClick={() => handleRemoveOption(index)}
411
- >
412
- <XMarkMini />
413
- </IconButton>
414
- </li>
415
- )
416
- })}
417
- </ul>
418
- </div>
419
- </Form.Item>
401
+ <div className="flex flex-col">
402
+ <Label weight="plus">
403
+ {t("products.create.variants.productOptions.label")}
404
+ </Label>
405
+ <Hint>{t("products.create.variants.productOptions.hint")}</Hint>
406
+ </div>
407
+ {showInvalidOptionsMessage && (
408
+ <Alert dismissible variant="error">
409
+ {t("products.create.errors.options")}
410
+ </Alert>
411
+ )}
412
+ <Combobox
413
+ value={selectedOptionValues}
414
+ onChange={(value) => handleProductOptionSelect(value as string[])}
415
+ options={productOptionChoices}
416
+ onCreateOption={async (options) => {
417
+ const optionTitle = options[options.length - 1]?.trim()
418
+
419
+ if (!optionTitle) {
420
+ return
421
+ }
422
+
423
+ const allSelectedOptions: Array<
424
+ AdminProductOption | { title: string; values: string[] }
425
+ > = []
426
+
427
+ const valueSelections: Record<string, string[]> = {}
428
+
429
+ watchedOptions.forEach((opt) => {
430
+ if (opt.id) {
431
+ const productOption = product_options.find(
432
+ (p) => p.id === opt.id
433
+ )
434
+ if (productOption) {
435
+ allSelectedOptions.push(productOption)
436
+ if (opt.value_ids) {
437
+ valueSelections[opt.id] = opt.value_ids
438
+ }
439
+ }
440
+ } else {
441
+ allSelectedOptions.push({
442
+ title: opt.title,
443
+ values: opt.values || [],
444
+ })
445
+ }
446
+ })
447
+
448
+ const newOption = {
449
+ title: optionTitle,
450
+ is_exclusive: true,
451
+ values: [],
452
+ }
453
+
454
+ allSelectedOptions.push(newOption)
455
+
456
+ updateFormWithSelectedValues(
457
+ allSelectedOptions,
458
+ valueSelections
420
459
  )
421
460
  }}
461
+ placeholder={t("products.fields.options.optionTitlePlaceholder")}
462
+ disabled={isLoading}
463
+ displayMode="chips"
422
464
  />
423
465
  </div>
466
+ {watchedOptions.length > 0 && (
467
+ <div className="flex flex-col gap-y-4">
468
+ <div className="flex flex-col">
469
+ <Label weight="plus">{t("fields.values")}</Label>
470
+ <Hint>{t("products.create.variants.selectValuesHint")}</Hint>
471
+ </div>
472
+ <div className="flex flex-col gap-y-3">
473
+ {watchedOptions.map((opt, index) => {
474
+ if (opt.id) {
475
+ const productOption = product_options.find(
476
+ (p) => p.id === opt.id
477
+ )
478
+
479
+ const existingValues = productOption?.values || []
480
+ const customValueNames =
481
+ opt.values?.filter(
482
+ (v) => !existingValues.some((ev) => ev.value === v)
483
+ ) || []
484
+
485
+ const existingValueOptions = existingValues
486
+ .sort((a, b) => {
487
+ const rankA = a.rank ?? Number.MAX_VALUE
488
+ const rankB = b.rank ?? Number.MAX_VALUE
489
+ return rankA - rankB
490
+ })
491
+ .map((v) => ({
492
+ value: v.id,
493
+ label: v.value,
494
+ }))
495
+
496
+ const customValueOptions = customValueNames.map((v) => ({
497
+ value: v,
498
+ label: v,
499
+ }))
500
+
501
+ const valueOptions = [
502
+ ...existingValueOptions,
503
+ ...customValueOptions,
504
+ ]
505
+
506
+ return (
507
+ <div key={opt.id} className="flex flex-col gap-y-2">
508
+ <Label size="small" weight="plus">
509
+ {opt.title}
510
+ </Label>
511
+ <Combobox
512
+ value={opt.value_ids ?? []}
513
+ onChange={(value) =>
514
+ handleValueChange(opt.id!, value as string[])
515
+ }
516
+ onCreateOption={async (values) => {
517
+ const newValueName =
518
+ values[values.length - 1]?.trim()
519
+ if (newValueName && opt.id) {
520
+ const currentValueIds = opt.value_ids || []
521
+ handleValueChange(opt.id, [
522
+ ...currentValueIds,
523
+ newValueName,
524
+ ])
525
+ }
526
+ }}
527
+ options={valueOptions}
528
+ placeholder={t(
529
+ "products.fields.options.variantionsPlaceholder"
530
+ )}
531
+ displayMode="chips"
532
+ />
533
+ </div>
534
+ )
535
+ } else {
536
+ return (
537
+ <div key={index} className="flex flex-col gap-y-2">
538
+ <Label size="small" weight="plus">
539
+ {opt.title}
540
+ </Label>
541
+ <ChipInput
542
+ value={opt.values ?? []}
543
+ onChange={(value) =>
544
+ handleNewOptionValueChange(opt.title, value)
545
+ }
546
+ placeholder={t(
547
+ "products.fields.options.variantionsPlaceholder"
548
+ )}
549
+ />
550
+ </div>
551
+ )
552
+ }
553
+ })}
554
+ </div>
555
+ </div>
556
+ )}
424
557
  <div className="grid grid-cols-1 gap-x-4 gap-y-8">
425
558
  <div className="flex flex-col gap-y-6">
426
559
  <div className="flex flex-col">
@@ -78,13 +78,10 @@ export const ProductCreateForm = ({
78
78
  return {}
79
79
  }
80
80
 
81
- return regions.reduce(
82
- (acc, reg) => {
83
- acc[reg.id] = reg.currency_code
84
- return acc
85
- },
86
- {} as Record<string, string>
87
- )
81
+ return regions.reduce((acc, reg) => {
82
+ acc[reg.id] = reg.currency_code
83
+ return acc
84
+ }, {} as Record<string, string>)
88
85
  }, [regions])
89
86
 
90
87
  /**
@@ -47,8 +47,10 @@ export type ProductCreateVariantSchema = z.infer<
47
47
  >
48
48
 
49
49
  const ProductCreateOptionSchema = z.object({
50
+ id: z.string().optional(),
50
51
  title: z.string(),
51
52
  values: z.array(z.string()).min(1),
53
+ value_ids: z.array(z.string()).optional(),
52
54
  })
53
55
 
54
56
  export type ProductCreateOptionSchema = z.infer<
@@ -13,6 +13,8 @@ export const normalizeProductFormValues = (
13
13
  ?.filter((media) => !media.isThumbnail)
14
14
  .map((media) => ({ url: media.url }))
15
15
 
16
+ const options = values.options.filter((o) => o.title) // clean temp. values
17
+
16
18
  return {
17
19
  status: values.status,
18
20
  is_giftcard: false,
@@ -41,7 +43,10 @@ export const normalizeProductFormValues = (
41
43
  length: values.length ? parseFloat(values.length) : undefined,
42
44
  height: values.height ? parseFloat(values.height) : undefined,
43
45
  weight: values.weight ? parseFloat(values.weight) : undefined,
44
- options: values.options.filter((o) => o.title), // clean temp. values
46
+ options: options.map((option) => {
47
+ const { id, value_ids, ...rest } = option
48
+ return id ? { id, value_ids } : { ...rest, is_exclusive: true }
49
+ }),
45
50
  variants: normalizeVariants(
46
51
  values.variants.filter((variant) => variant.should_create),
47
52
  values.regionsCurrencyMap