@mercurjs/vendor 2.1.2 → 2.2.0-canary.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 (230) hide show
  1. package/dist/{[id]-PDGHF5J2.js → [id]-2DQX3YWJ.js} +35 -31
  2. package/dist/{[id]-TO6KT3ZE.js → [id]-4OBGG7OH.js} +23 -21
  3. package/dist/{[id]-X4DDKOMQ.js → [id]-4PKMKNJH.js} +26 -22
  4. package/dist/[id]-4STHLE4N.js +1442 -0
  5. package/dist/{[id]-4VCL3MMM.js → [id]-5UFO4RKF.js} +26 -22
  6. package/dist/{[id]-H3C3ZSC6.js → [id]-6MXCVV5J.js} +25 -21
  7. package/dist/{[id]-6PXEWRG7.js → [id]-7BAKUHUO.js} +13 -13
  8. package/dist/{[id]-7RUAH3TI.js → [id]-K2CT7BXQ.js} +4 -4
  9. package/dist/{[id]-3G5G7ZFV.js → [id]-KJIQTFGE.js} +22 -20
  10. package/dist/{[id]-INOFZHL7.js → [id]-LTNOHLGE.js} +16 -16
  11. package/dist/{[id]-B3LHVQM5.js → [id]-PGIT5WJC.js} +25 -21
  12. package/dist/{[id]-T2ROPEGY.js → [id]-Y2ISCLUD.js} +7 -7
  13. package/dist/{[id]-Y7GAMNC5.js → [id]-ZCMSBEVM.js} +4 -4
  14. package/dist/{[id]-UTKO3VG4.js → [id]-ZWWMJAKI.js} +9 -9
  15. package/dist/{[location_id]-D55RQOXT.js → [location_id]-NUBXDDJC.js} +9 -9
  16. package/dist/{[province_id]-OFH2ZOFQ.js → [province_id]-H2QAPKVH.js} +20 -18
  17. package/dist/{add-C6OX5C54.js → add-GZJ7OMV3.js} +34 -30
  18. package/dist/add-KQAABWCR.js +392 -0
  19. package/dist/{add-customer-groups-PJRJUWS2.js → add-customer-groups-RAHCP67U.js} +16 -14
  20. package/dist/{add-products-INOLNPO6.js → add-products-TSVQHC67.js} +23 -19
  21. package/dist/{add-promotions-AHDOP52Q.js → add-promotions-CSCAJZHV.js} +7 -7
  22. package/dist/{add-to-campaign-HL6NGRR4.js → add-to-campaign-DLP7PSQB.js} +4 -4
  23. package/dist/{address-KRENKSLP.js → address-7F5SN7PV.js} +17 -15
  24. package/dist/{adjust-inventory-H4EUP7J3.js → adjust-inventory-SZF4W7LR.js} +2 -2
  25. package/dist/{allocate-items-SUCUZU4D.js → allocate-items-SDFS5GYN.js} +6 -6
  26. package/dist/{areas-UUMZDXLX.js → areas-7Y6BVS5A.js} +8 -8
  27. package/dist/{attributes-CALEHJJG.js → attributes-MBZ76HVZ.js} +3 -3
  28. package/dist/{breadcrumb-BS7Y5OKF.js → breadcrumb-65SAGUUL.js} +2 -2
  29. package/dist/{breadcrumb-6W2VP3OZ.js → breadcrumb-7PURSRTT.js} +13 -11
  30. package/dist/{breadcrumb-M5Z5WA6I.js → breadcrumb-EDPMEN2P.js} +2 -2
  31. package/dist/breadcrumb-FLDHJRVY.js +26 -0
  32. package/dist/{breadcrumb-VNNZ3TTW.js → breadcrumb-HND5FFWC.js} +2 -2
  33. package/dist/{breadcrumb-OIGGCB3L.js → breadcrumb-QV2IAX7N.js} +8 -2
  34. package/dist/{breadcrumb-KQSFIXQ4.js → breadcrumb-VWELWDB2.js} +1 -1
  35. package/dist/{breadcrumb-IG7VZGW2.js → breadcrumb-WRG4SITG.js} +13 -11
  36. package/dist/{breadcrumb-TW5JEOYS.js → breadcrumb-ZCG2RHIU.js} +12 -10
  37. package/dist/{campaigns-HS6MIO7X.js → campaigns-L6ULR6KR.js} +5 -5
  38. package/dist/{categories-PKWR3FM3.js → categories-FUZQKBXV.js} +6 -6
  39. package/dist/{chunk-PDQSPKG5.js → chunk-2DXNJURE.js} +1 -1
  40. package/dist/{chunk-ZZO3INVE.js → chunk-2MDGYHWN.js} +128 -25
  41. package/dist/{chunk-5UD4P6YL.js → chunk-2USXZSTK.js} +4 -4
  42. package/dist/{chunk-6SBMVLJ2.js → chunk-36L54SQQ.js} +1 -1
  43. package/dist/chunk-37G4Y5I7.js +101 -0
  44. package/dist/{chunk-5M3SL4UZ.js → chunk-3CVJA5UE.js} +9 -104
  45. package/dist/chunk-432S4FGR.js +0 -0
  46. package/dist/{chunk-KQGVSLUI.js → chunk-44RQ5PTN.js} +1803 -914
  47. package/dist/{chunk-Y2QI7KWS.js → chunk-4LVP635F.js} +408 -664
  48. package/dist/{chunk-UL4O5M4S.js → chunk-4S6XGIC6.js} +1 -18
  49. package/dist/chunk-5ZVWOCAC.js +426 -0
  50. package/dist/{chunk-WITQNQXN.js → chunk-6BS2AVGJ.js} +3 -3
  51. package/dist/{chunk-ZYOXKUKZ.js → chunk-7LBY5JLV.js} +1 -1
  52. package/dist/chunk-7SLWXX6L.js +811 -0
  53. package/dist/{chunk-LQYMBSRQ.js → chunk-AIZM66CG.js} +1 -1
  54. package/dist/{chunk-IZ5RG5XI.js → chunk-AJLGY3LQ.js} +1 -21
  55. package/dist/{chunk-WFE6CT6M.js → chunk-AVOIZO63.js} +21 -77
  56. package/dist/chunk-C2FG3SX2.js +68 -0
  57. package/dist/chunk-CFRWIQIZ.js +43 -0
  58. package/dist/{chunk-WNVEMFIK.js → chunk-CNMY5HVP.js} +2 -2
  59. package/dist/{chunk-BLVJAKBA.js → chunk-DDH7ULIQ.js} +1 -1
  60. package/dist/chunk-DIW4GRTI.js +503 -0
  61. package/dist/{chunk-JQP7MOFH.js → chunk-DVEKYLPV.js} +1 -1
  62. package/dist/{chunk-QX45GVAL.js → chunk-EIUYXS7E.js} +8 -8
  63. package/dist/{chunk-N7OVXN72.js → chunk-EROX26D4.js} +1 -1
  64. package/dist/{chunk-2RHAI7WK.js → chunk-EZ3JOAUS.js} +1 -1
  65. package/dist/{chunk-HFRHHT36.js → chunk-FDR22JMM.js} +63 -8
  66. package/dist/{chunk-PEKANQ3T.js → chunk-FJUUGFXL.js} +2 -2
  67. package/dist/{chunk-3CK6OINO.js → chunk-GDWBOQI5.js} +3 -5
  68. package/dist/{chunk-47SXTGLN.js → chunk-GXIAIITP.js} +63 -200
  69. package/dist/{chunk-4MFMCZEJ.js → chunk-H6LZ77GX.js} +2 -2
  70. package/dist/chunk-IWLDKGYQ.js +95 -0
  71. package/dist/chunk-K4X324QP.js +18 -0
  72. package/dist/{chunk-VQ5EKDA3.js → chunk-KD7RYE6R.js} +1 -1
  73. package/dist/chunk-LEWA4BPH.js +18 -0
  74. package/dist/{chunk-7Q5SDEK7.js → chunk-LNM2D2I4.js} +4 -4
  75. package/dist/{chunk-LPOAVK6Y.js → chunk-LQD232FW.js} +47 -12
  76. package/dist/{chunk-OXXL4WQU.js → chunk-M7KSRYRI.js} +5 -5
  77. package/dist/chunk-MBFHMJHN.js +2063 -0
  78. package/dist/{chunk-I2IKYOZX.js → chunk-N4MVIBFM.js} +19 -19
  79. package/dist/{chunk-PCMNEUMV.js → chunk-NHFEY3EI.js} +1 -1
  80. package/dist/{chunk-RTAWYMQP.js → chunk-NJMNYS7G.js} +1 -1
  81. package/dist/{chunk-HGQTL7NX.js → chunk-NSZQERLE.js} +2 -2
  82. package/dist/{chunk-RL7SFZOF.js → chunk-NXNJQZCP.js} +1 -1
  83. package/dist/{chunk-CNLP35S7.js → chunk-OD3U3TX4.js} +16 -31
  84. package/dist/{chunk-D2MA5TAP.js → chunk-PBD36EZJ.js} +2 -2
  85. package/dist/{chunk-4ZGFODSC.js → chunk-PZ44R4AS.js} +1 -1
  86. package/dist/{chunk-ZEVYT6IX.js → chunk-QNNJN4H6.js} +116 -286
  87. package/dist/{chunk-WBI7FEGI.js → chunk-QS6RWIBL.js} +1 -1
  88. package/dist/chunk-QT7YFHCA.js +198 -0
  89. package/dist/{chunk-GYV6SKY7.js → chunk-QXLRABYH.js} +4 -6
  90. package/dist/chunk-RXZFEFNV.js +73 -0
  91. package/dist/{chunk-RUE5BPC2.js → chunk-RZLN2Q6G.js} +1 -1
  92. package/dist/{chunk-NYDJTWRL.js → chunk-SGR4DMCW.js} +4 -4
  93. package/dist/chunk-T6LHVNWO.js +27 -0
  94. package/dist/{chunk-DKQ4XMSN.js → chunk-TNVYTMBL.js} +6 -6
  95. package/dist/{chunk-32RYSB2V.js → chunk-TODJFRLH.js} +2 -2
  96. package/dist/{chunk-P3ZTO6T2.js → chunk-UAF2S447.js} +1 -1
  97. package/dist/{chunk-J6BRLL3F.js → chunk-UCQKXXLD.js} +2 -2
  98. package/dist/chunk-UORPTGV2.js +114 -0
  99. package/dist/{chunk-CYTNBXWF.js → chunk-UX7J5NZG.js} +9 -9
  100. package/dist/{chunk-X4FLOQ45.js → chunk-WBHFU3MG.js} +2 -2
  101. package/dist/chunk-WLT7K7K7.js +63 -0
  102. package/dist/{chunk-4URLUCTD.js → chunk-WUPJADSO.js} +2 -2
  103. package/dist/{chunk-ITI54CII.js → chunk-X4INVIWL.js} +5 -5
  104. package/dist/{chunk-PTW7JNAP.js → chunk-XFQJU6FA.js} +4 -4
  105. package/dist/{collections-DJZI2RM2.js → collections-3OPR3DSD.js} +22 -19
  106. package/dist/{configuration-RHPIO2QT.js → configuration-C4IGBNXH.js} +1 -1
  107. package/dist/{configuration-GN3TO77H.js → configuration-UOSNP45I.js} +3 -3
  108. package/dist/{create-3EK5CNNX.js → create-2MQFQHTE.js} +33 -29
  109. package/dist/{create-YO55Z3YD.js → create-2PCLG7TV.js} +32 -38
  110. package/dist/{create-G4T2PAJH.js → create-35MYQPVM.js} +23 -21
  111. package/dist/{create-HKJVSFB7.js → create-BJ4OO6LS.js} +23 -21
  112. package/dist/create-DDPIXCXT.js +210 -0
  113. package/dist/{create-7S7CZWEN.js → create-GB3ZA4LH.js} +4 -4
  114. package/dist/create-JDGM5KXE.js +193 -0
  115. package/dist/{create-IDVCZHIX.js → create-ORXYT74H.js} +14 -12
  116. package/dist/{create-GHM7OTCR.js → create-R7K3ECN6.js} +1 -1
  117. package/dist/{create-D6EW3EWC.js → create-SFU3W3ZH.js} +1 -1
  118. package/dist/{create-3ZVXEPX5.js → create-SQ3FYMGI.js} +25 -21
  119. package/dist/{create-33TRLASX.js → create-UPYB65PD.js} +1 -1
  120. package/dist/{create-OCFPLNNY.js → create-UQNYMVBM.js} +6 -6
  121. package/dist/{create-OGLPDVOI.js → create-XAD5NMSJ.js} +37 -35
  122. package/dist/{create-KGYL7FBM.js → create-XVHOCZHJ.js} +1 -1
  123. package/dist/{create-4AE3VTWN.js → create-YBF4YGWG.js} +2 -2
  124. package/dist/{customers-6ZLE65UX.js → customers-ETXVNM3G.js} +5 -5
  125. package/dist/{edit-QBISX7D3.js → edit-2Q7TRUTL.js} +14 -12
  126. package/dist/{edit-B5B3XKDM.js → edit-522DG3BY.js} +1 -1
  127. package/dist/{edit-ATXE6CM5.js → edit-C4OCKQVU.js} +1 -1
  128. package/dist/{edit-IR6V2IDN.js → edit-FKXIQ6ZI.js} +19 -17
  129. package/dist/{edit-4HZHLYI3.js → edit-GQNIINRR.js} +1 -1
  130. package/dist/{edit-LRRJTHV2.js → edit-KAKVPHZZ.js} +1 -1
  131. package/dist/{edit-ZSOI56BQ.js → edit-L5ZZLMAY.js} +22 -22
  132. package/dist/{edit-FNDDSSMT.js → edit-NYD45J2Q.js} +37 -8
  133. package/dist/{edit-GIJXLMC3.js → edit-O4JLGKQR.js} +2 -2
  134. package/dist/{edit-5CJZRHAA.js → edit-ORXS3A2Y.js} +1 -1
  135. package/dist/{edit-FC64DWB2.js → edit-Q3UQIOLS.js} +1 -1
  136. package/dist/{edit-7HTH2UJF.js → edit-REDDBLTA.js} +3 -3
  137. package/dist/{edit-2KRJIPRK.js → edit-SGUY2CCK.js} +19 -17
  138. package/dist/{edit-B75KK5ZX.js → edit-SWRWWFW6.js} +35 -31
  139. package/dist/{edit-7GVP6SRA.js → edit-ZAHCMF5U.js} +1 -1
  140. package/dist/{edit-RNT555GP.js → edit-ZCXUG42Q.js} +13 -11
  141. package/dist/{edit-MYSWY6W4.js → edit-ZMERG3L7.js} +1 -1
  142. package/dist/{edit-budget-J27CSEZH.js → edit-budget-L3CCEWNF.js} +1 -1
  143. package/dist/{edit-inventory-item-US77M2FF.js → edit-inventory-item-6B7ITDGD.js} +2 -2
  144. package/dist/{edit-inventory-item-attributes-UGAE2NAZ.js → edit-inventory-item-attributes-Y7MQZLXI.js} +3 -3
  145. package/dist/{fulfillment-DCS67LTK.js → fulfillment-75Z4H23W.js} +16 -14
  146. package/dist/{fulfillment-providers-GM5PO6N3.js → fulfillment-providers-KCQWL62T.js} +20 -17
  147. package/dist/index.css +27 -62
  148. package/dist/index.d.ts +3 -10
  149. package/dist/index.js +522 -458
  150. package/dist/{inventory-OPZ2FSEE.js → inventory-KAUVPMPZ.js} +6 -6
  151. package/dist/{invite-764K3TJS.js → invite-6CPYVHDX.js} +24 -21
  152. package/dist/{invite-KEJLNXEZ.js → invite-CI2P4GF6.js} +15 -12
  153. package/dist/loader-FBB5OQRT.js +31 -0
  154. package/dist/{locations-ZVPTQCQY.js → locations-INS6FTMJ.js} +4 -4
  155. package/dist/{login-OUHRNNXA.js → login-KY342RMK.js} +12 -10
  156. package/dist/{manage-locations-YUKEFCBJ.js → manage-locations-WNHEBS3A.js} +2 -2
  157. package/dist/{media-4KYFHB5V.js → media-KOYAOXG6.js} +41 -9
  158. package/dist/{metadata-NYYL26MQ.js → metadata-2CMH4I6U.js} +16 -14
  159. package/dist/{metadata-AWUKZ25V.js → metadata-5BPOBBU2.js} +3 -3
  160. package/dist/{metadata-OCE6A3JE.js → metadata-GWI6R4ES.js} +15 -13
  161. package/dist/{metadata-G7KZXVNE.js → metadata-NUXUC2JA.js} +15 -13
  162. package/dist/{metadata-XP3ZYW2M.js → metadata-TLDUF5KV.js} +17 -15
  163. package/dist/{metadata-PYY4IB7K.js → metadata-WR4RFXO5.js} +16 -14
  164. package/dist/offer-create-page-YKMHHTU5.js +743 -0
  165. package/dist/offer-detail-page-6MAHNNIO.js +488 -0
  166. package/dist/offer-edit-page-DYQFU6JU.js +151 -0
  167. package/dist/offer-inventory-batch-page-WKCWNDNK.js +290 -0
  168. package/dist/offer-pricing-edit-page-4TYGGSOE.js +195 -0
  169. package/dist/offers-UGQJNGTD.js +32 -0
  170. package/dist/{onboarding-WXZHW62K.js → onboarding-43LQQQGQ.js} +22 -20
  171. package/dist/{orders-LWJ472VM.js → orders-R2LOJ6N5.js} +24 -21
  172. package/dist/organization-XGFU4YDG.js +375 -0
  173. package/dist/{organize-RFOMQCBG.js → organize-HNJUHEEG.js} +4 -4
  174. package/dist/{organize-OVKJ3HZO.js → organize-K6QMAMEN.js} +4 -4
  175. package/dist/pages/index.d.ts +415 -758
  176. package/dist/pages/index.js +81 -77
  177. package/dist/{payment-details-UVXYCTUK.js → payment-details-64US5XWD.js} +17 -15
  178. package/dist/{payouts-TR7K5I37.js → payouts-UXJDTXDL.js} +6 -6
  179. package/dist/{price-lists-S2WNELFZ.js → price-lists-KBPUVSZI.js} +8 -8
  180. package/dist/{pricing-UF27DAXA.js → pricing-DF6C5XK4.js} +35 -32
  181. package/dist/{product-tags-2CKH2M6D.js → product-tags-CL7HSEDI.js} +32 -28
  182. package/dist/{product-types-FX43JEO2.js → product-types-UUHBV4IZ.js} +5 -5
  183. package/dist/product-variant-detail-RVWEYVPC.js +220 -0
  184. package/dist/{product-variant-edit-P3DSIFE3.js → product-variant-edit-MNCS7ZYW.js} +126 -66
  185. package/dist/{products-H5EMRJYS.js → products-4KV5Y2JY.js} +23 -19
  186. package/dist/{products-2LHGS7X3.js → products-SXYTQFJ3.js} +40 -43
  187. package/dist/{professional-details-HYKTH44B.js → professional-details-5T2VS6MM.js} +16 -14
  188. package/dist/{profile-PB27WIRW.js → profile-6XGHAT7H.js} +20 -18
  189. package/dist/{promotions-5EYPGHJP.js → promotions-O7U4BTK6.js} +8 -8
  190. package/dist/{register-4O4F6YZK.js → register-GDKN3SKM.js} +16 -14
  191. package/dist/{reset-password-GTWLBOFK.js → reset-password-EICPAY2N.js} +1 -1
  192. package/dist/{return-reasons-LOKYRGMI.js → return-reasons-M6IR77XW.js} +16 -14
  193. package/dist/{sales-channels-7R2IY3KG.js → sales-channels-B6FULRWI.js} +8 -7
  194. package/dist/{sales-channels-Y4LRP7JC.js → sales-channels-JW3QUYR7.js} +8 -7
  195. package/dist/{settings-2XDLFYMS.js → settings-SAAHTUZZ.js} +39 -35
  196. package/dist/{shipment-4GW2JFWB.js → shipment-Q33QBMXX.js} +13 -11
  197. package/dist/{shipping-profile-R3NABPQF.js → shipping-profile-Y4SNEPZX.js} +2 -2
  198. package/dist/{shipping-profiles-QVKNFLCW.js → shipping-profiles-2NWKCEJK.js} +18 -16
  199. package/dist/{stock-5RXNUPUT.js → stock-7CSVEJJU.js} +19 -17
  200. package/dist/{store-DE2RGX7T.js → store-GHFWU7EV.js} +28 -25
  201. package/dist/{store-closure-DNMCHUXD.js → store-closure-P5PD2RSV.js} +16 -14
  202. package/dist/{store-select-GZEJHRZ7.js → store-select-KDT6USQA.js} +17 -15
  203. package/dist/{tax-regions-UD6P5FVC.js → tax-regions-YXZW7UVX.js} +5 -5
  204. package/dist/{team-JXKAVRPU.js → team-EDJ62747.js} +25 -23
  205. package/dist/types-CtCEtTE6.d.ts +16 -0
  206. package/package.json +3 -3
  207. package/dist/[id]-BYP37PU4.js +0 -1314
  208. package/dist/add-KRAGFFBJ.js +0 -158
  209. package/dist/bulk-edit-3SMBLIOA.js +0 -244
  210. package/dist/chunk-4KX6CBJ4.js +0 -178
  211. package/dist/chunk-DLNNTQRY.js +0 -217
  212. package/dist/chunk-FX4V5JCF.js +0 -37
  213. package/dist/chunk-GC33DBKG.js +0 -143
  214. package/dist/chunk-NK4NR6MN.js +0 -173
  215. package/dist/chunk-PFU6FSXY.js +0 -430
  216. package/dist/chunk-QJEOPT2P.js +0 -330
  217. package/dist/chunk-QSGR43JM.js +0 -30
  218. package/dist/chunk-STR3NGWE.js +0 -3736
  219. package/dist/create-3DOO3RNH.js +0 -716
  220. package/dist/create-I7HV3RM6.js +0 -150
  221. package/dist/edit-K2AD335I.js +0 -237
  222. package/dist/edit-VO5XLIEL.js +0 -362
  223. package/dist/edit-stocks-and-prices-MHHQFWFA.js +0 -408
  224. package/dist/organization-LPYQRTQC.js +0 -303
  225. package/dist/prices-3OXV5RGY.js +0 -270
  226. package/dist/product-variant-detail-WV4KXVXR.js +0 -590
  227. package/dist/stock-GPC3BCL6.js +0 -500
  228. package/dist/{chunk-SDSEW72R.js → chunk-E2HQPY32.js} +3 -3
  229. package/dist/{chunk-6WY5X4PE.js → chunk-L7QKFC5N.js} +7 -7
  230. /package/dist/{chunk-CAS74NLJ.js → chunk-YV6MK4PZ.js} +0 -0
@@ -1,3736 +0,0 @@
1
- import {
2
- HandleInput
3
- } from "./chunk-HJ56YXBU.js";
4
- import {
5
- useSalesChannelTableColumns,
6
- useSalesChannelTableEmptyState,
7
- useSalesChannelTableFilters,
8
- useSalesChannelTableQuery
9
- } from "./chunk-WFE6CT6M.js";
10
- import {
11
- CategoryCombobox
12
- } from "./chunk-PFU6FSXY.js";
13
- import {
14
- useComboboxData
15
- } from "./chunk-OVPAOBZB.js";
16
- import {
17
- UploadMediaFormItem
18
- } from "./chunk-PDQSPKG5.js";
19
- import {
20
- CountrySelect
21
- } from "./chunk-7CAFYKKA.js";
22
- import {
23
- UserCreatedOptionsList
24
- } from "./chunk-QJEOPT2P.js";
25
- import {
26
- PRODUCT_CREATE_FORM_DEFAULTS,
27
- ProductCreateSchema,
28
- decorateVariantsWithDefaultValues
29
- } from "./chunk-NK4NR6MN.js";
30
- import {
31
- NumericInput
32
- } from "./chunk-DLNNTQRY.js";
33
- import {
34
- SwitchBox
35
- } from "./chunk-YVCBMOJG.js";
36
- import {
37
- Combobox
38
- } from "./chunk-VBRTC2VU.js";
39
- import {
40
- TabbedForm,
41
- TabbedFormContext,
42
- useTabbedForm
43
- } from "./chunk-LPOAVK6Y.js";
44
- import {
45
- DataGrid,
46
- DataGridMediaCell,
47
- createDataGridHelper,
48
- createDataGridPriceColumns
49
- } from "./chunk-Y2QI7KWS.js";
50
- import {
51
- KeyboundForm
52
- } from "./chunk-U2ZFCAPX.js";
53
- import {
54
- RouteFocusModal,
55
- StackedFocusModal,
56
- useRouteModal,
57
- useStackedModal
58
- } from "./chunk-3CK6OINO.js";
59
- import {
60
- Form
61
- } from "./chunk-3QSRE5LS.js";
62
- import {
63
- DataTable
64
- } from "./chunk-PPLC4IKI.js";
65
- import {
66
- useStockLocations
67
- } from "./chunk-NBPMNUKZ.js";
68
- import {
69
- usePricePreferences,
70
- useRegions
71
- } from "./chunk-UL4O5M4S.js";
72
- import {
73
- useStore
74
- } from "./chunk-FX4V5JCF.js";
75
- import {
76
- ActionMenu
77
- } from "./chunk-BDGZ4EQO.js";
78
- import {
79
- useSalesChannels
80
- } from "./chunk-3B34B2M2.js";
81
- import {
82
- useCreateProduct
83
- } from "./chunk-ZEVYT6IX.js";
84
- import {
85
- queryKeysFactory
86
- } from "./chunk-ZA2KFUFR.js";
87
- import {
88
- fetchQuery,
89
- sdk,
90
- uploadFilesQuery
91
- } from "./chunk-RIN4CBRB.js";
92
-
93
- // src/pages/products/create/product-create-page.tsx
94
- import { Children as Children4, useCallback as useCallback5, useRef as useRef5, useState as useState10 } from "react";
95
- import { useTranslation as useTranslation16 } from "react-i18next";
96
-
97
- // src/pages/products/create/product-create-form/product-create-form.tsx
98
- import { useCallback as useCallback2, useEffect as useEffect5, useMemo as useMemo4, useRef as useRef3, useState as useState6 } from "react";
99
- import { Button as Button4, ProgressTabs, toast } from "@medusajs/ui";
100
- import { useForm, useWatch as useWatch3 } from "react-hook-form";
101
- import { useTranslation as useTranslation12 } from "react-i18next";
102
- import { z as z2 } from "zod";
103
- import { zodResolver } from "@hookform/resolvers/zod";
104
-
105
- // src/hooks/api/attributes.tsx
106
- import {
107
- useQuery
108
- } from "@tanstack/react-query";
109
- var ATTRIBUTES_QUERY_KEY = "attributes";
110
- var attributesQueryKeys = queryKeysFactory(ATTRIBUTES_QUERY_KEY);
111
- var useAttributes = (query, options) => {
112
- const { data, ...rest } = useQuery({
113
- queryFn: () => fetchQuery("/vendor/attributes", {
114
- method: "GET",
115
- query
116
- }),
117
- queryKey: attributesQueryKeys.list(query),
118
- ...options
119
- });
120
- return { ...data, ...rest };
121
- };
122
-
123
- // src/pages/products/create/product-create-attributes-form/product-create-attributes-form.tsx
124
- import { forwardRef as forwardRef2, useEffect as useEffect2, useImperativeHandle } from "react";
125
- import { CircleInfoSolid } from "@medusajs/icons";
126
- import { Button, Divider, Heading, Text as Text2, Tooltip } from "@medusajs/ui";
127
- import { useFieldArray } from "react-hook-form";
128
- import { useTranslation as useTranslation3 } from "react-i18next";
129
-
130
- // src/pages/products/create/utils/attribute-validation.ts
131
- import { z } from "zod";
132
- var createAttributeValidationRules = (attributes, t) => {
133
- const rules = {};
134
- attributes.forEach((attr) => {
135
- const fieldName = attr.handle;
136
- const isRequired = attr.is_required;
137
- if (isRequired) {
138
- switch (attr.ui_component) {
139
- case "select":
140
- case "toggle":
141
- rules[fieldName] = {
142
- required: t("products.fields.attributes.validation.requiredSelect"),
143
- validate: (value) => {
144
- if (typeof value !== "string" || !value || value === "") {
145
- return t("products.fields.attributes.validation.requiredSelect");
146
- }
147
- return true;
148
- }
149
- };
150
- break;
151
- case "text":
152
- case "text_area":
153
- case "color_picker":
154
- rules[fieldName] = {
155
- required: t("products.fields.attributes.validation.requiredEnter"),
156
- validate: (value) => {
157
- if (typeof value !== "string" || !value || value === "") {
158
- return t("products.fields.attributes.validation.requiredEnter");
159
- }
160
- return true;
161
- }
162
- };
163
- break;
164
- case "multivalue":
165
- rules[fieldName] = {
166
- required: t("products.fields.attributes.validation.requiredSelectMultiple"),
167
- validate: (value) => {
168
- if (!Array.isArray(value) || value.length === 0) {
169
- return t("products.fields.attributes.validation.requiredSelectMultiple");
170
- }
171
- return true;
172
- }
173
- };
174
- break;
175
- case "unit":
176
- rules[fieldName] = {
177
- required: t("products.fields.attributes.validation.requiredEnter"),
178
- validate: (value) => {
179
- if (value === void 0 || value === null || value === "") {
180
- return t("products.fields.attributes.validation.requiredEnter");
181
- }
182
- return true;
183
- }
184
- };
185
- break;
186
- default:
187
- rules[fieldName] = {
188
- required: t("products.fields.attributes.validation.requiredEnter"),
189
- validate: (value) => {
190
- if (typeof value !== "string" || !value || value === "") {
191
- return t("products.fields.attributes.validation.requiredEnter");
192
- }
193
- return true;
194
- }
195
- };
196
- break;
197
- }
198
- }
199
- });
200
- return rules;
201
- };
202
-
203
- // src/pages/products/create/utils/process-attributes.ts
204
- var processAttributes = (allAttributes, primaryCategoryId) => {
205
- if (!allAttributes || allAttributes.length === 0) {
206
- return {
207
- required: {
208
- categorySpecific: [],
209
- global: [],
210
- all: []
211
- }
212
- };
213
- }
214
- const globalAttributes = allAttributes.filter(
215
- (attr) => !attr.product_categories || attr.product_categories.length === 0
216
- );
217
- const categorySpecificAttributes = allAttributes.filter(
218
- (attr) => attr.product_categories && attr.product_categories.length > 0
219
- );
220
- const applicableCategoryAttributes = categorySpecificAttributes.filter(
221
- (attr) => attr.product_categories?.some(
222
- (cat) => cat.id === primaryCategoryId
223
- )
224
- );
225
- const mapToFormField = (attr) => ({
226
- key: attr.id,
227
- id: attr.id,
228
- name: attr.name,
229
- handle: attr.handle || attr.id,
230
- ui_component: attr.ui_component,
231
- is_required: attr.is_required,
232
- description: attr.description,
233
- possible_values: attr.possible_values?.map((value) => ({
234
- value: value.id,
235
- label: value.value
236
- })) || []
237
- });
238
- const requiredCategorySpecificFormFields = applicableCategoryAttributes.filter((attr) => attr.is_required).map(mapToFormField);
239
- const requiredGlobalFormFields = globalAttributes.filter((attr) => attr.is_required).map(mapToFormField);
240
- return {
241
- required: {
242
- categorySpecific: requiredCategorySpecificFormFields,
243
- global: requiredGlobalFormFields,
244
- all: [
245
- ...requiredCategorySpecificFormFields,
246
- ...requiredGlobalFormFields
247
- ]
248
- }
249
- };
250
- };
251
-
252
- // src/pages/products/create/product-create-attributes-form/required-attributes-list.tsx
253
- import { Select, Textarea } from "@medusajs/ui";
254
- import { useTranslation as useTranslation2 } from "react-i18next";
255
-
256
- // src/components/inputs/multi-select/multi-select.tsx
257
- import { forwardRef, useEffect, useMemo, useRef, useState } from "react";
258
- import { CheckMini, TrianglesMini, XMarkMini } from "@medusajs/icons";
259
- import { Badge, Input, Text } from "@medusajs/ui";
260
- import { useTranslation } from "react-i18next";
261
- import { Fragment, jsx, jsxs } from "react/jsx-runtime";
262
- var MultiSelect = forwardRef(
263
- ({
264
- options,
265
- value,
266
- onChange,
267
- onBlur,
268
- name,
269
- placeholder,
270
- "aria-invalid": ariaInvalid = false,
271
- disabled = false,
272
- className = "",
273
- showSearch = true
274
- }, ref) => {
275
- const { t } = useTranslation();
276
- const [isOpen, setIsOpen] = useState(false);
277
- const [searchValue, setSearchValue] = useState("");
278
- const dropdownRef = useRef(null);
279
- const triggerRef = useRef(null);
280
- const badgesContainerRef = useRef(null);
281
- const [visibleBadgesCount, setVisibleBadgesCount] = useState(0);
282
- useEffect(() => {
283
- const handleClickOutside = (event) => {
284
- if (dropdownRef.current && !dropdownRef.current.contains(event.target) && triggerRef.current && !triggerRef.current.contains(event.target)) {
285
- setIsOpen(false);
286
- }
287
- };
288
- document.addEventListener("mousedown", handleClickOutside);
289
- return () => {
290
- document.removeEventListener("mousedown", handleClickOutside);
291
- };
292
- }, []);
293
- const calculateVisibleBadges = () => {
294
- if (!value || value.length === 0 || !badgesContainerRef.current) {
295
- setVisibleBadgesCount(0);
296
- return;
297
- }
298
- const container = badgesContainerRef.current;
299
- const containerWidth = container.offsetWidth;
300
- const padding = 24;
301
- const gap = 8;
302
- const availableWidth = containerWidth - padding;
303
- const estimateBadgeWidth = (label) => {
304
- const baseWidth = 32;
305
- const charWidth = 8;
306
- return baseWidth + label.length * charWidth;
307
- };
308
- let totalWidth = 0;
309
- let count = 0;
310
- for (let i = 0; i < value.length; i++) {
311
- const option = options.find((opt) => opt.value === value[i]);
312
- const optionLabel = option?.label || "Unknown";
313
- const badgeWidth = estimateBadgeWidth(optionLabel) > 200 ? 235 : estimateBadgeWidth(optionLabel);
314
- if (totalWidth + badgeWidth + (count > 0 ? gap : 0) <= availableWidth) {
315
- totalWidth += badgeWidth + (count > 0 ? gap : 0);
316
- count++;
317
- } else {
318
- break;
319
- }
320
- }
321
- setVisibleBadgesCount(count);
322
- };
323
- useEffect(() => {
324
- calculateVisibleBadges();
325
- }, [value, options]);
326
- useEffect(() => {
327
- const resizeObserver = new ResizeObserver(() => {
328
- calculateVisibleBadges();
329
- });
330
- if (badgesContainerRef.current) {
331
- resizeObserver.observe(badgesContainerRef.current);
332
- }
333
- return () => {
334
- resizeObserver.disconnect();
335
- };
336
- }, [value, options]);
337
- const handleToggle = () => {
338
- if (disabled) return;
339
- setIsOpen((prev) => !prev);
340
- if (!isOpen && showSearch) {
341
- setSearchValue("");
342
- }
343
- };
344
- const handleItemClick = (optionValue) => {
345
- const currentValue = value || [];
346
- const isSelected = currentValue.includes(optionValue);
347
- if (isSelected) {
348
- onChange(currentValue.filter((val) => val !== optionValue));
349
- } else {
350
- onChange([...currentValue, optionValue]);
351
- }
352
- };
353
- const handleRemoveBadge = (optionValue, e) => {
354
- e.stopPropagation();
355
- const currentValue = value || [];
356
- onChange(currentValue.filter((val) => val !== optionValue));
357
- };
358
- const filteredOptions = useMemo(() => {
359
- if (!showSearch || !searchValue.trim()) {
360
- return options;
361
- }
362
- return options.filter(
363
- (option) => option.label.toLowerCase().includes(searchValue.toLowerCase())
364
- );
365
- }, [options, searchValue, showSearch]);
366
- const handleSearchChange = (e) => {
367
- setSearchValue(e.target.value);
368
- };
369
- const handleClearSearch = () => {
370
- setSearchValue("");
371
- };
372
- return /* @__PURE__ */ jsxs("div", { ref, className: `relative ${className}`, children: [
373
- /* @__PURE__ */ jsxs(
374
- "div",
375
- {
376
- ref: triggerRef,
377
- className: `relative flex h-8 w-full cursor-pointer items-center justify-between overflow-hidden rounded-md border bg-ui-bg-field text-ui-fg-base shadow-sm transition-colors duration-150 ease-in-out focus-within:ring-1 hover:bg-ui-bg-field-hover ${disabled ? "cursor-not-allowed bg-ui-bg-disabled opacity-50" : ariaInvalid ? "!shadow-borders-error" : "focus-within:ring-ui-ring-interactive border-ui-border-base focus-within:border-ui-border-interactive"}`,
378
- onClick: handleToggle,
379
- onBlur,
380
- tabIndex: 0,
381
- role: "combobox",
382
- "aria-controls": isOpen ? `${name}-listbox` : void 0,
383
- "aria-expanded": isOpen,
384
- "aria-haspopup": "listbox",
385
- "aria-invalid": ariaInvalid,
386
- "aria-label": name,
387
- children: [
388
- /* @__PURE__ */ jsx(
389
- "div",
390
- {
391
- ref: badgesContainerRef,
392
- className: "flex min-w-0 flex-1 items-center gap-2 px-3 py-2",
393
- children: value && value.length > 0 ? /* @__PURE__ */ jsxs(Fragment, { children: [
394
- value.slice(0, visibleBadgesCount).map((optionValue) => {
395
- const option = options.find(
396
- (opt) => opt.value === optionValue
397
- );
398
- return /* @__PURE__ */ jsx(
399
- "button",
400
- {
401
- type: "button",
402
- onClick: (e) => handleRemoveBadge(optionValue, e),
403
- className: "flex flex-shrink-0 items-center self-center",
404
- disabled,
405
- children: /* @__PURE__ */ jsxs(
406
- Badge,
407
- {
408
- size: "2xsmall",
409
- className: "w-fit bg-ui-bg-base p-0",
410
- children: [
411
- /* @__PURE__ */ jsx("span", { className: "max-w-[200px] truncate text-ellipsis border-r border-ui-border-base px-1.5", children: option?.label || "Unknown" }),
412
- /* @__PURE__ */ jsx(XMarkMini, { className: "mr-0.5 !text-ui-fg-base" })
413
- ]
414
- }
415
- )
416
- },
417
- optionValue
418
- );
419
- }),
420
- value && value.length > visibleBadgesCount && /* @__PURE__ */ jsxs(
421
- Badge,
422
- {
423
- size: "small",
424
- className: "txt-compact-small-plus w-fit flex-shrink-0 border-none bg-transparent px-0 text-ui-fg-subtle",
425
- children: [
426
- "+",
427
- value.length - visibleBadgesCount
428
- ]
429
- }
430
- )
431
- ] }) : /* @__PURE__ */ jsx(Text, { className: "text-ui-fg-subtle", children: placeholder || t("general.selectValues") })
432
- }
433
- ),
434
- /* @__PURE__ */ jsx("div", { className: "flex h-full items-center justify-center", children: /* @__PURE__ */ jsx("span", { className: "flex h-full w-8 items-center justify-center", children: /* @__PURE__ */ jsx(TrianglesMini, { className: "text-ui-fg-muted" }) }) })
435
- ]
436
- }
437
- ),
438
- isOpen && !disabled && /* @__PURE__ */ jsxs(
439
- "div",
440
- {
441
- ref: dropdownRef,
442
- className: "absolute z-10 mt-1 max-h-60 w-full overflow-hidden rounded-md border border-ui-border-base bg-ui-bg-base shadow-lg",
443
- children: [
444
- showSearch && /* @__PURE__ */ jsx("div", { className: "sticky top-0 z-10 border-b border-ui-border-base bg-ui-bg-base p-2", children: /* @__PURE__ */ jsxs("div", { className: "relative", children: [
445
- /* @__PURE__ */ jsx(
446
- Input,
447
- {
448
- value: searchValue,
449
- onChange: handleSearchChange,
450
- placeholder: t("general.searchOptions"),
451
- className: "w-full bg-transparent pr-8 shadow-none focus:!shadow-none"
452
- }
453
- ),
454
- searchValue && /* @__PURE__ */ jsx(
455
- "button",
456
- {
457
- type: "button",
458
- onClick: handleClearSearch,
459
- className: "absolute right-2 top-1/2 -translate-y-1/2 rounded-md p-1 transition-colors hover:bg-ui-bg-base-hover",
460
- "aria-label": "Clear search",
461
- children: /* @__PURE__ */ jsx(XMarkMini, { className: "h-4 w-4 text-ui-fg-muted" })
462
- }
463
- )
464
- ] }) }),
465
- /* @__PURE__ */ jsx(
466
- "div",
467
- {
468
- className: `${showSearch ? "max-h-48" : "max-h-60"} overflow-y-auto py-1`,
469
- children: filteredOptions.length === 0 ? /* @__PURE__ */ jsx("div", { className: "txt-compact-small-plus p-3 text-ui-fg-subtle", children: showSearch && searchValue.trim() ? t("general.noOptionsFound") : t("general.noOptionsAvailable") }) : filteredOptions.map((option) => {
470
- const currentValue = value || [];
471
- const isSelected = currentValue.includes(option.value);
472
- return (
473
- // oxlint-disable-next-line jsx-a11y/click-events-have-key-events, jsx-a11y/no-static-element-interactions
474
- /* @__PURE__ */ jsx(
475
- "div",
476
- {
477
- className: "flex cursor-pointer items-center px-1 py-1 hover:bg-ui-bg-base-hover",
478
- onClick: () => handleItemClick(option.value),
479
- children: /* @__PURE__ */ jsxs("div", { className: "flex flex-1 items-center gap-x-2 rounded-md px-2", children: [
480
- /* @__PURE__ */ jsx("div", { className: "flex size-5 shrink-0 items-center justify-center", children: isSelected && /* @__PURE__ */ jsx(CheckMini, {}) }),
481
- /* @__PURE__ */ jsx(Text, { className: "truncate", children: option.label })
482
- ] })
483
- },
484
- option.value
485
- )
486
- );
487
- })
488
- }
489
- )
490
- ]
491
- }
492
- )
493
- ] });
494
- }
495
- );
496
- MultiSelect.displayName = "MultiSelect";
497
- var multi_select_default = MultiSelect;
498
-
499
- // src/pages/products/create/product-create-attributes-form/required-attributes-list.tsx
500
- import { Fragment as Fragment2, jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
501
- var RequiredAttributesList = ({
502
- form,
503
- fields,
504
- validationRules
505
- }) => {
506
- const { t } = useTranslation2();
507
- return /* @__PURE__ */ jsx2(Fragment2, { children: fields.map((field) => /* @__PURE__ */ jsxs2("div", { className: "flex flex-col gap-y-4", children: [
508
- field.ui_component === "select" && /* @__PURE__ */ jsx2(
509
- Form.Field,
510
- {
511
- control: form.control,
512
- name: field.handle,
513
- rules: validationRules[field.handle] || {},
514
- render: ({ field: formField, fieldState }) => /* @__PURE__ */ jsxs2(Form.Item, { children: [
515
- /* @__PURE__ */ jsx2(Form.Label, { optional: !field.is_required, children: field.name }),
516
- field.description && /* @__PURE__ */ jsx2("p", { className: "txt-compact-small !my-1 text-ui-fg-subtle", children: field.description }),
517
- /* @__PURE__ */ jsx2(Form.Control, { children: /* @__PURE__ */ jsx2(
518
- Combobox,
519
- {
520
- ...formField,
521
- options: field.possible_values,
522
- "aria-invalid": !!fieldState.error
523
- }
524
- ) }),
525
- /* @__PURE__ */ jsx2(Form.ErrorMessage, {})
526
- ] })
527
- }
528
- ),
529
- field.ui_component === "multivalue" && /* @__PURE__ */ jsxs2("div", { className: "flex flex-col gap-y-2", children: [
530
- /* @__PURE__ */ jsx2(
531
- Form.Field,
532
- {
533
- control: form.control,
534
- name: field.handle,
535
- rules: validationRules[field.handle] || {},
536
- render: ({ field: formField, fieldState }) => /* @__PURE__ */ jsxs2(Form.Item, { children: [
537
- /* @__PURE__ */ jsx2(Form.Label, { optional: !field.is_required, children: field.name }),
538
- field.description && /* @__PURE__ */ jsx2("p", { className: "txt-compact-small mb-1 text-ui-fg-subtle", children: field.description }),
539
- /* @__PURE__ */ jsx2(Form.Control, { children: /* @__PURE__ */ jsx2(
540
- multi_select_default,
541
- {
542
- value: formField.value,
543
- onChange: formField.onChange,
544
- name: formField.name,
545
- options: field.possible_values,
546
- showSearch: true,
547
- "aria-invalid": !!fieldState.error
548
- }
549
- ) }),
550
- /* @__PURE__ */ jsx2(Form.ErrorMessage, {})
551
- ] })
552
- }
553
- ),
554
- /* @__PURE__ */ jsx2(
555
- SwitchBox,
556
- {
557
- control: form.control,
558
- name: `${field.handle}UseForVariants`,
559
- label: t(
560
- "products.fields.attributes.useForVariants.label"
561
- ),
562
- description: t(
563
- "products.fields.attributes.useForVariants.description"
564
- )
565
- }
566
- )
567
- ] }),
568
- field.ui_component === "text_area" && /* @__PURE__ */ jsx2(
569
- Form.Field,
570
- {
571
- control: form.control,
572
- name: field.handle,
573
- rules: validationRules[field.handle] || {},
574
- render: ({ field: formField, fieldState }) => /* @__PURE__ */ jsxs2(Form.Item, { children: [
575
- /* @__PURE__ */ jsx2(Form.Label, { optional: !field.is_required, children: field.name }),
576
- field.description && /* @__PURE__ */ jsx2("p", { className: "txt-compact-small !my-1 text-ui-fg-subtle", children: field.description }),
577
- /* @__PURE__ */ jsx2(Form.Control, { children: /* @__PURE__ */ jsx2(
578
- Textarea,
579
- {
580
- ...formField,
581
- placeholder: t(
582
- "products.fields.attributes.enterValuePlaceholder"
583
- ),
584
- "aria-invalid": !!fieldState.error
585
- }
586
- ) }),
587
- /* @__PURE__ */ jsx2(Form.ErrorMessage, {})
588
- ] })
589
- }
590
- ),
591
- field.ui_component === "toggle" && /* @__PURE__ */ jsx2(
592
- Form.Field,
593
- {
594
- control: form.control,
595
- name: field.handle,
596
- rules: validationRules[field.handle] || {},
597
- render: ({ field: formField, fieldState }) => /* @__PURE__ */ jsxs2(Form.Item, { children: [
598
- /* @__PURE__ */ jsx2(Form.Label, { optional: !field.is_required, children: field.name }),
599
- field.description && /* @__PURE__ */ jsx2("p", { className: "txt-compact-small !my-1 text-ui-fg-subtle", children: field.description }),
600
- /* @__PURE__ */ jsx2(Form.Control, { children: /* @__PURE__ */ jsxs2(
601
- Select,
602
- {
603
- ...formField,
604
- onValueChange: formField.onChange,
605
- value: formField.value,
606
- children: [
607
- /* @__PURE__ */ jsx2(
608
- Select.Trigger,
609
- {
610
- "aria-invalid": !!fieldState.error,
611
- children: /* @__PURE__ */ jsx2(
612
- Select.Value,
613
- {
614
- placeholder: t(
615
- "products.fields.attributes.selectValuePlaceholder"
616
- )
617
- }
618
- )
619
- }
620
- ),
621
- /* @__PURE__ */ jsxs2(Select.Content, { children: [
622
- /* @__PURE__ */ jsx2(Select.Item, { value: "true", children: t("general.true") }),
623
- /* @__PURE__ */ jsx2(Select.Item, { value: "false", children: t("general.false") })
624
- ] })
625
- ]
626
- }
627
- ) }),
628
- /* @__PURE__ */ jsx2(Form.ErrorMessage, {})
629
- ] })
630
- }
631
- ),
632
- field.ui_component === "unit" && /* @__PURE__ */ jsx2(
633
- Form.Field,
634
- {
635
- control: form.control,
636
- name: field.handle,
637
- rules: validationRules[field.handle] || {},
638
- render: ({ field: formField, fieldState }) => /* @__PURE__ */ jsxs2(Form.Item, { children: [
639
- /* @__PURE__ */ jsx2(Form.Label, { optional: !field.is_required, children: field.name }),
640
- field.description && /* @__PURE__ */ jsx2("p", { className: "txt-compact-small !my-1 text-ui-fg-subtle", children: field.description }),
641
- /* @__PURE__ */ jsx2(Form.Control, { children: /* @__PURE__ */ jsx2(
642
- NumericInput,
643
- {
644
- value: formField.value,
645
- onChange: formField.onChange,
646
- onBlur: formField.onBlur,
647
- name: formField.name,
648
- placeholder: t(
649
- "products.fields.attributes.enterValuePlaceholder"
650
- ),
651
- "aria-invalid": !!fieldState.error,
652
- hideControls: true
653
- }
654
- ) }),
655
- /* @__PURE__ */ jsx2(Form.ErrorMessage, {})
656
- ] })
657
- }
658
- )
659
- ] }, field.id)) });
660
- };
661
-
662
- // src/pages/products/create/product-create-attributes-form/product-create-attributes-form.tsx
663
- import { Fragment as Fragment3, jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
664
- var ProductCreateAttributesForm = forwardRef2(({ form }, ref) => {
665
- const { t } = useTranslation3();
666
- const primaryCategoryId = form.watch("categories")?.[0];
667
- const options = useFieldArray({
668
- control: form.control,
669
- name: "options"
670
- });
671
- const { attributes: allAttributes, isLoading: allAttributesLoading } = useAttributes({
672
- fields: "id,name,handle,description,ui_component,is_required,product_categories.*,possible_values.*"
673
- });
674
- const processedAttributes = processAttributes(
675
- allAttributes,
676
- primaryCategoryId
677
- );
678
- const requiredFormFields = processedAttributes.required.all;
679
- const validationRules = createAttributeValidationRules(
680
- requiredFormFields,
681
- t
682
- );
683
- const validateAttributes = async () => {
684
- const errors = {};
685
- requiredFormFields.forEach((field) => {
686
- if (field.is_required) {
687
- const value = form.getValues(
688
- field.handle
689
- );
690
- switch (field.ui_component) {
691
- case "select":
692
- case "toggle":
693
- if (!value || value === "") {
694
- errors[field.handle] = t(
695
- "products.fields.attributes.validation.requiredSelect"
696
- );
697
- }
698
- break;
699
- case "text":
700
- case "text_area":
701
- if (!value || value === "") {
702
- errors[field.handle] = t(
703
- "products.fields.attributes.validation.requiredEnter"
704
- );
705
- }
706
- break;
707
- case "multivalue":
708
- if (!value || !Array.isArray(value) || value.length === 0) {
709
- errors[field.handle] = t(
710
- "products.fields.attributes.validation.requiredSelectMultiple"
711
- );
712
- }
713
- break;
714
- case "unit":
715
- if (value === void 0 || value === null || value === "") {
716
- errors[field.handle] = t(
717
- "products.fields.attributes.validation.requiredEnter"
718
- );
719
- }
720
- break;
721
- }
722
- }
723
- });
724
- requiredFormFields.forEach((field) => {
725
- if (field.is_required) {
726
- form.clearErrors(
727
- field.handle
728
- );
729
- }
730
- });
731
- Object.keys(errors).forEach((fieldName) => {
732
- form.setError(fieldName, {
733
- type: "required",
734
- message: errors[fieldName]
735
- });
736
- });
737
- const currentOptions = form.getValues("options") || [];
738
- const optionsValid = currentOptions.length > 0 ? await form.trigger("options") : true;
739
- return Object.keys(errors).length === 0 && optionsValid;
740
- };
741
- useImperativeHandle(
742
- ref,
743
- () => ({
744
- validateAttributes,
745
- requiredFormFields
746
- }),
747
- /* oxlint-disable react-hooks/exhaustive-deps */
748
- [
749
- requiredFormFields,
750
- validateAttributes
751
- ]
752
- /* oxlint-enable react-hooks/exhaustive-deps */
753
- );
754
- useEffect2(() => {
755
- const subscription = form.watch((values, { name }) => {
756
- if (name && requiredFormFields.some((field) => field.handle === name)) {
757
- const field = requiredFormFields.find(
758
- (f) => f.handle === name
759
- );
760
- if (field && field.is_required) {
761
- const value = values[name];
762
- let isValid = false;
763
- switch (field.ui_component) {
764
- case "select":
765
- case "toggle":
766
- isValid = typeof value === "string" && value !== "";
767
- break;
768
- case "text":
769
- case "text_area":
770
- isValid = typeof value === "string" && value !== "";
771
- break;
772
- case "multivalue":
773
- isValid = Array.isArray(value) && value.length > 0;
774
- break;
775
- case "unit":
776
- isValid = value !== void 0 && value !== null && value !== "";
777
- break;
778
- default:
779
- isValid = false;
780
- break;
781
- }
782
- if (isValid) {
783
- form.clearErrors(
784
- name
785
- );
786
- }
787
- }
788
- }
789
- });
790
- return () => subscription.unsubscribe();
791
- }, [form, requiredFormFields]);
792
- const nonRequiredAttributes = allAttributes?.filter(
793
- (attribute) => !attribute.is_required
794
- );
795
- const availableAttributes = nonRequiredAttributes?.filter(
796
- (attribute) => !options.fields?.some(
797
- (option) => option.attributeId === attribute.id
798
- )
799
- );
800
- return /* @__PURE__ */ jsx3("div", { className: "flex flex-col items-center p-16", children: /* @__PURE__ */ jsxs3("div", { className: "flex w-full max-w-[720px] flex-col gap-y-8", children: [
801
- /* @__PURE__ */ jsx3(Header, { options }),
802
- /* @__PURE__ */ jsxs3("div", { className: "flex flex-col gap-y-8", children: [
803
- /* @__PURE__ */ jsx3(
804
- UserCreatedOptionsList,
805
- {
806
- form,
807
- options,
808
- availableAttributes,
809
- allNonRequiredAttributes: nonRequiredAttributes,
810
- allowCreate: true
811
- }
812
- ),
813
- requiredFormFields.length === 0 ? /* @__PURE__ */ jsx3("div", { className: "py-8 text-center text-gray-500", children: allAttributesLoading ? t("products.create.attributes.loading") : null }) : /* @__PURE__ */ jsxs3(Fragment3, { children: [
814
- /* @__PURE__ */ jsx3(Divider, { variant: "dashed" }),
815
- /* @__PURE__ */ jsxs3("div", { className: "flex flex-col gap-y-2", children: [
816
- /* @__PURE__ */ jsx3(Heading, { level: "h3", className: "text-ui-fg-base", children: t(
817
- "products.create.attributes.requiredHeading"
818
- ) }),
819
- /* @__PURE__ */ jsx3(
820
- Text2,
821
- {
822
- size: "small",
823
- className: "text-ui-fg-subtle",
824
- children: t(
825
- "products.create.attributes.requiredDescription"
826
- )
827
- }
828
- )
829
- ] }),
830
- /* @__PURE__ */ jsx3(
831
- RequiredAttributesList,
832
- {
833
- form,
834
- fields: requiredFormFields,
835
- validationRules
836
- }
837
- )
838
- ] })
839
- ] })
840
- ] }) });
841
- });
842
- ProductCreateAttributesForm.displayName = "ProductCreateAttributesForm";
843
- var Header = ({ options }) => {
844
- const { t } = useTranslation3();
845
- return /* @__PURE__ */ jsx3("div", { className: "flex flex-col gap-y-2", children: /* @__PURE__ */ jsxs3("div", { className: "flex items-start justify-between", children: [
846
- /* @__PURE__ */ jsxs3("div", { className: "flex flex-col gap-y-2", children: [
847
- /* @__PURE__ */ jsx3(Heading, { level: "h1", className: "text-ui-fg-base", children: t("products.create.tabs.attributes") }),
848
- /* @__PURE__ */ jsxs3("div", { className: "space-y-0.5", children: [
849
- /* @__PURE__ */ jsx3(
850
- Text2,
851
- {
852
- size: "small",
853
- className: "max-w-[440px] text-ui-fg-subtle",
854
- children: t("products.create.attributes.description")
855
- }
856
- ),
857
- /* @__PURE__ */ jsxs3(
858
- Text2,
859
- {
860
- size: "small",
861
- className: "flex items-center gap-1 text-ui-fg-subtle",
862
- children: [
863
- t(
864
- "products.create.attributes.learnMore.label"
865
- ),
866
- /* @__PURE__ */ jsx3(
867
- Tooltip,
868
- {
869
- content: t(
870
- "products.create.attributes.learnMore.content"
871
- ),
872
- children: /* @__PURE__ */ jsx3(CircleInfoSolid, {})
873
- }
874
- )
875
- ]
876
- }
877
- )
878
- ] })
879
- ] }),
880
- /* @__PURE__ */ jsxs3(
881
- Button,
882
- {
883
- size: "small",
884
- variant: "secondary",
885
- type: "button",
886
- className: "min-w-[100px]",
887
- onClick: () => {
888
- options.append(
889
- {
890
- title: "",
891
- values: [],
892
- metadata: { author: "vendor" },
893
- useForVariants: true
894
- },
895
- {
896
- shouldFocus: false
897
- }
898
- );
899
- },
900
- children: [
901
- t("actions.add"),
902
- " ",
903
- t("products.create.attributes.buttonLabel")
904
- ]
905
- }
906
- )
907
- ] }) });
908
- };
909
-
910
- // src/pages/products/create/product-create-details-form/product-create-details-form.tsx
911
- import { Heading as Heading2 } from "@medusajs/ui";
912
- import { Children } from "react";
913
- import { useTranslation as useTranslation6 } from "react-i18next";
914
-
915
- // src/pages/products/create/product-create-details-form/components/product-create-details-general-section/product-create-general-section.tsx
916
- import { Input as Input2, Textarea as Textarea2 } from "@medusajs/ui";
917
- import { useTranslation as useTranslation4 } from "react-i18next";
918
- import { jsx as jsx4, jsxs as jsxs4 } from "react/jsx-runtime";
919
- var ProductCreateGeneralSection = () => {
920
- const { t } = useTranslation4();
921
- const form = useTabbedForm();
922
- return /* @__PURE__ */ jsxs4("div", { id: "general", className: "flex flex-col gap-y-6", children: [
923
- /* @__PURE__ */ jsx4("div", { className: "flex flex-col gap-y-2", children: /* @__PURE__ */ jsxs4("div", { className: "grid grid-cols-1 gap-4 md:grid-cols-3", children: [
924
- /* @__PURE__ */ jsx4(
925
- Form.Field,
926
- {
927
- control: form.control,
928
- name: "title",
929
- render: ({ field }) => {
930
- return /* @__PURE__ */ jsxs4(Form.Item, { children: [
931
- /* @__PURE__ */ jsx4(Form.Label, { children: t("products.fields.title.label") }),
932
- /* @__PURE__ */ jsx4(Form.Control, { children: /* @__PURE__ */ jsx4(
933
- Input2,
934
- {
935
- ...field,
936
- placeholder: t("products.fields.title.placeholder")
937
- }
938
- ) }),
939
- /* @__PURE__ */ jsx4(Form.ErrorMessage, { children: form.formState.errors.title?.message })
940
- ] });
941
- }
942
- }
943
- ),
944
- /* @__PURE__ */ jsx4(
945
- Form.Field,
946
- {
947
- control: form.control,
948
- name: "subtitle",
949
- render: ({ field }) => {
950
- return /* @__PURE__ */ jsxs4(Form.Item, { children: [
951
- /* @__PURE__ */ jsx4(Form.Label, { optional: true, children: t("products.fields.subtitle.label") }),
952
- /* @__PURE__ */ jsx4(Form.Control, { children: /* @__PURE__ */ jsx4(
953
- Input2,
954
- {
955
- ...field,
956
- placeholder: t("products.fields.subtitle.placeholder")
957
- }
958
- ) })
959
- ] });
960
- }
961
- }
962
- ),
963
- /* @__PURE__ */ jsx4(
964
- Form.Field,
965
- {
966
- control: form.control,
967
- name: "handle",
968
- render: ({ field }) => {
969
- return /* @__PURE__ */ jsxs4(Form.Item, { children: [
970
- /* @__PURE__ */ jsx4(
971
- Form.Label,
972
- {
973
- tooltip: t("products.fields.handle.tooltip"),
974
- optional: true,
975
- children: t("fields.handle")
976
- }
977
- ),
978
- /* @__PURE__ */ jsx4(Form.Control, { children: /* @__PURE__ */ jsx4(
979
- HandleInput,
980
- {
981
- ...field,
982
- placeholder: t("products.fields.handle.placeholder")
983
- }
984
- ) }),
985
- /* @__PURE__ */ jsx4(Form.ErrorMessage, { children: form.formState.errors.handle?.message })
986
- ] });
987
- }
988
- }
989
- )
990
- ] }) }),
991
- /* @__PURE__ */ jsx4(
992
- Form.Field,
993
- {
994
- control: form.control,
995
- name: "description",
996
- render: ({ field }) => {
997
- return /* @__PURE__ */ jsxs4(Form.Item, { children: [
998
- /* @__PURE__ */ jsx4(Form.Label, { optional: true, children: t("products.fields.description.label") }),
999
- /* @__PURE__ */ jsx4(Form.Control, { children: /* @__PURE__ */ jsx4(
1000
- Textarea2,
1001
- {
1002
- ...field,
1003
- placeholder: t("products.fields.description.placeholder")
1004
- }
1005
- ) })
1006
- ] });
1007
- }
1008
- }
1009
- )
1010
- ] });
1011
- };
1012
-
1013
- // src/pages/products/create/product-create-details-form/components/product-create-details-media-section/product-create-details-media-section.tsx
1014
- import {
1015
- defaultDropAnimationSideEffects,
1016
- DndContext,
1017
- DragOverlay,
1018
- KeyboardSensor,
1019
- PointerSensor,
1020
- useSensor,
1021
- useSensors
1022
- } from "@dnd-kit/core";
1023
- import {
1024
- arrayMove,
1025
- SortableContext,
1026
- sortableKeyboardCoordinates,
1027
- useSortable
1028
- } from "@dnd-kit/sortable";
1029
- import { CSS } from "@dnd-kit/utilities";
1030
- import {
1031
- DotsSix,
1032
- StackPerspective,
1033
- ThumbnailBadge,
1034
- Trash,
1035
- XMark
1036
- } from "@medusajs/icons";
1037
- import { IconButton, Text as Text3 } from "@medusajs/ui";
1038
- import { useState as useState2 } from "react";
1039
- import { useFieldArray as useFieldArray2 } from "react-hook-form";
1040
- import { useTranslation as useTranslation5 } from "react-i18next";
1041
- import { jsx as jsx5, jsxs as jsxs5 } from "react/jsx-runtime";
1042
- var dropAnimationConfig = {
1043
- sideEffects: defaultDropAnimationSideEffects({
1044
- styles: {
1045
- active: {
1046
- opacity: "0.4"
1047
- }
1048
- }
1049
- })
1050
- };
1051
- var ProductCreateMediaSection = () => {
1052
- const form = useTabbedForm();
1053
- const { fields, append, remove } = useFieldArray2({
1054
- name: "media",
1055
- control: form.control,
1056
- keyName: "field_id"
1057
- });
1058
- const [activeId, setActiveId] = useState2(null);
1059
- const sensors = useSensors(
1060
- useSensor(PointerSensor),
1061
- useSensor(KeyboardSensor, {
1062
- coordinateGetter: sortableKeyboardCoordinates
1063
- })
1064
- );
1065
- const handleDragStart = (event) => {
1066
- setActiveId(event.active.id);
1067
- };
1068
- const handleDragEnd = (event) => {
1069
- setActiveId(null);
1070
- const { active, over } = event;
1071
- if (active.id !== over?.id) {
1072
- const oldIndex = fields.findIndex((item) => item.field_id === active.id);
1073
- const newIndex = fields.findIndex((item) => item.field_id === over?.id);
1074
- form.setValue("media", arrayMove(fields, oldIndex, newIndex), {
1075
- shouldDirty: true,
1076
- shouldTouch: true
1077
- });
1078
- }
1079
- };
1080
- const handleDragCancel = () => {
1081
- setActiveId(null);
1082
- };
1083
- const getOnDelete = (index) => {
1084
- return () => {
1085
- remove(index);
1086
- };
1087
- };
1088
- const getMakeThumbnail = (index) => {
1089
- return () => {
1090
- const newFields = fields.map((field, i) => {
1091
- return {
1092
- ...field,
1093
- isThumbnail: i === index
1094
- };
1095
- });
1096
- form.setValue("media", newFields, {
1097
- shouldDirty: true,
1098
- shouldTouch: true
1099
- });
1100
- };
1101
- };
1102
- const getItemHandlers = (index) => {
1103
- return {
1104
- onDelete: getOnDelete(index),
1105
- onMakeThumbnail: getMakeThumbnail(index)
1106
- };
1107
- };
1108
- return /* @__PURE__ */ jsxs5("div", { id: "media", className: "flex flex-col gap-y-2", children: [
1109
- /* @__PURE__ */ jsx5(UploadMediaFormItem, { form, append, showHint: false }),
1110
- /* @__PURE__ */ jsxs5(
1111
- DndContext,
1112
- {
1113
- sensors,
1114
- onDragEnd: handleDragEnd,
1115
- onDragStart: handleDragStart,
1116
- onDragCancel: handleDragCancel,
1117
- children: [
1118
- /* @__PURE__ */ jsx5(DragOverlay, { dropAnimation: dropAnimationConfig, children: activeId ? /* @__PURE__ */ jsx5(
1119
- MediaGridItemOverlay,
1120
- {
1121
- field: fields.find((m) => m.field_id === activeId)
1122
- }
1123
- ) : null }),
1124
- /* @__PURE__ */ jsx5("ul", { className: "flex flex-col gap-y-2", children: /* @__PURE__ */ jsx5(SortableContext, { items: fields.map((field) => field.field_id), children: fields.map((field, index) => {
1125
- const { onDelete, onMakeThumbnail } = getItemHandlers(index);
1126
- return /* @__PURE__ */ jsx5(
1127
- MediaItem,
1128
- {
1129
- field,
1130
- onDelete,
1131
- onMakeThumbnail
1132
- },
1133
- field.field_id
1134
- );
1135
- }) }) })
1136
- ]
1137
- }
1138
- )
1139
- ] });
1140
- };
1141
- var MediaItem = ({ field, onDelete, onMakeThumbnail }) => {
1142
- const { t } = useTranslation5();
1143
- const {
1144
- attributes,
1145
- listeners,
1146
- setNodeRef,
1147
- setActivatorNodeRef,
1148
- transform,
1149
- transition,
1150
- isDragging
1151
- } = useSortable({ id: field.field_id });
1152
- const style = {
1153
- opacity: isDragging ? 0.4 : void 0,
1154
- transform: CSS.Translate.toString(transform),
1155
- transition
1156
- };
1157
- if (!field.file) {
1158
- return null;
1159
- }
1160
- return /* @__PURE__ */ jsxs5(
1161
- "li",
1162
- {
1163
- className: "bg-ui-bg-component shadow-elevation-card-rest flex items-center justify-between rounded-lg px-3 py-2",
1164
- ref: setNodeRef,
1165
- style,
1166
- children: [
1167
- /* @__PURE__ */ jsxs5("div", { className: "flex items-center gap-x-2", children: [
1168
- /* @__PURE__ */ jsx5(
1169
- IconButton,
1170
- {
1171
- variant: "transparent",
1172
- type: "button",
1173
- size: "small",
1174
- ...attributes,
1175
- ...listeners,
1176
- ref: setActivatorNodeRef,
1177
- className: "cursor-grab touch-none active:cursor-grabbing",
1178
- children: /* @__PURE__ */ jsx5(DotsSix, { className: "text-ui-fg-muted" })
1179
- }
1180
- ),
1181
- /* @__PURE__ */ jsxs5("div", { className: "flex items-center gap-x-3", children: [
1182
- /* @__PURE__ */ jsx5("div", { className: "bg-ui-bg-base h-10 w-[30px] overflow-hidden rounded-md", children: /* @__PURE__ */ jsx5(ThumbnailPreview, { url: field.url }) }),
1183
- /* @__PURE__ */ jsxs5("div", { className: "flex flex-col", children: [
1184
- /* @__PURE__ */ jsx5(Text3, { size: "small", leading: "compact", children: field.file.name }),
1185
- /* @__PURE__ */ jsxs5("div", { className: "flex items-center gap-x-1", children: [
1186
- field.isThumbnail && /* @__PURE__ */ jsx5(ThumbnailBadge, {}),
1187
- /* @__PURE__ */ jsx5(
1188
- Text3,
1189
- {
1190
- size: "xsmall",
1191
- leading: "compact",
1192
- className: "text-ui-fg-subtle",
1193
- children: formatFileSize(field.file.size)
1194
- }
1195
- )
1196
- ] })
1197
- ] })
1198
- ] })
1199
- ] }),
1200
- /* @__PURE__ */ jsxs5("div", { className: "flex items-center gap-x-1", children: [
1201
- /* @__PURE__ */ jsx5(
1202
- ActionMenu,
1203
- {
1204
- groups: [
1205
- {
1206
- actions: [
1207
- {
1208
- label: t("products.media.makeThumbnail"),
1209
- icon: /* @__PURE__ */ jsx5(StackPerspective, {}),
1210
- onClick: onMakeThumbnail
1211
- }
1212
- ]
1213
- },
1214
- {
1215
- actions: [
1216
- {
1217
- icon: /* @__PURE__ */ jsx5(Trash, {}),
1218
- label: t("actions.delete"),
1219
- onClick: onDelete
1220
- }
1221
- ]
1222
- }
1223
- ]
1224
- }
1225
- ),
1226
- /* @__PURE__ */ jsx5(
1227
- IconButton,
1228
- {
1229
- type: "button",
1230
- size: "small",
1231
- variant: "transparent",
1232
- onClick: onDelete,
1233
- children: /* @__PURE__ */ jsx5(XMark, {})
1234
- }
1235
- )
1236
- ] })
1237
- ]
1238
- }
1239
- );
1240
- };
1241
- var MediaGridItemOverlay = ({ field }) => {
1242
- return /* @__PURE__ */ jsxs5("li", { className: "bg-ui-bg-component shadow-elevation-card-rest flex items-center justify-between rounded-lg px-3 py-2", children: [
1243
- /* @__PURE__ */ jsxs5("div", { className: "flex items-center gap-x-2", children: [
1244
- /* @__PURE__ */ jsx5(
1245
- IconButton,
1246
- {
1247
- variant: "transparent",
1248
- size: "small",
1249
- className: "cursor-grab touch-none active:cursor-grabbing",
1250
- children: /* @__PURE__ */ jsx5(DotsSix, { className: "text-ui-fg-muted" })
1251
- }
1252
- ),
1253
- /* @__PURE__ */ jsxs5("div", { className: "flex items-center gap-x-3", children: [
1254
- /* @__PURE__ */ jsx5("div", { className: "bg-ui-bg-base h-10 w-[30px] overflow-hidden rounded-md", children: /* @__PURE__ */ jsx5(ThumbnailPreview, { url: field.url }) }),
1255
- /* @__PURE__ */ jsxs5("div", { className: "flex flex-col", children: [
1256
- /* @__PURE__ */ jsx5(Text3, { size: "small", leading: "compact", children: field.file?.name }),
1257
- /* @__PURE__ */ jsxs5("div", { className: "flex items-center gap-x-1", children: [
1258
- field.isThumbnail && /* @__PURE__ */ jsx5(ThumbnailBadge, {}),
1259
- /* @__PURE__ */ jsx5(
1260
- Text3,
1261
- {
1262
- size: "xsmall",
1263
- leading: "compact",
1264
- className: "text-ui-fg-subtle",
1265
- children: formatFileSize(field.file?.size ?? 0)
1266
- }
1267
- )
1268
- ] })
1269
- ] })
1270
- ] })
1271
- ] }),
1272
- /* @__PURE__ */ jsxs5("div", { className: "flex items-center gap-x-1", children: [
1273
- /* @__PURE__ */ jsx5(ActionMenu, { groups: [] }),
1274
- /* @__PURE__ */ jsx5(
1275
- IconButton,
1276
- {
1277
- type: "button",
1278
- size: "small",
1279
- variant: "transparent",
1280
- onClick: () => {
1281
- },
1282
- children: /* @__PURE__ */ jsx5(XMark, {})
1283
- }
1284
- )
1285
- ] })
1286
- ] });
1287
- };
1288
- var ThumbnailPreview = ({ url }) => {
1289
- if (!url) {
1290
- return null;
1291
- }
1292
- return /* @__PURE__ */ jsx5("img", { src: url, alt: "", className: "size-full object-cover object-center" });
1293
- };
1294
- function formatFileSize(bytes, decimalPlaces = 2) {
1295
- if (bytes === 0) {
1296
- return "0 Bytes";
1297
- }
1298
- const k = 1024;
1299
- const sizes = ["Bytes", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"];
1300
- const i = Math.floor(Math.log(bytes) / Math.log(k));
1301
- return parseFloat((bytes / Math.pow(k, i)).toFixed(decimalPlaces)) + " " + sizes[i];
1302
- }
1303
-
1304
- // src/pages/products/create/product-create-details-form/product-create-details-form.tsx
1305
- import { jsx as jsx6, jsxs as jsxs6 } from "react/jsx-runtime";
1306
- var Root = ({ children }) => {
1307
- if (Children.count(children) > 0) {
1308
- return /* @__PURE__ */ jsx6("div", { className: "flex flex-col items-center p-16", children: /* @__PURE__ */ jsxs6("div", { className: "flex w-full max-w-[720px] flex-col gap-y-8", children: [
1309
- /* @__PURE__ */ jsx6(Header2, {}),
1310
- children
1311
- ] }) });
1312
- }
1313
- return /* @__PURE__ */ jsx6("div", { className: "flex flex-col items-center p-16", children: /* @__PURE__ */ jsxs6("div", { className: "flex w-full max-w-[720px] flex-col gap-y-8", children: [
1314
- /* @__PURE__ */ jsx6(Header2, {}),
1315
- /* @__PURE__ */ jsxs6("div", { className: "flex flex-col gap-y-6", children: [
1316
- /* @__PURE__ */ jsx6(ProductCreateGeneralSection, {}),
1317
- /* @__PURE__ */ jsx6(ProductCreateMediaSection, {})
1318
- ] })
1319
- ] }) });
1320
- };
1321
- Root._tabMeta = {
1322
- id: "details",
1323
- labelKey: "products.create.tabs.details",
1324
- validationFields: ["title", "media"]
1325
- };
1326
- var Header2 = () => {
1327
- const { t } = useTranslation6();
1328
- return /* @__PURE__ */ jsx6("div", { className: "flex flex-col", children: /* @__PURE__ */ jsx6(Heading2, { children: t("products.create.tabs.details") }) });
1329
- };
1330
- var ProductCreateDetailsForm = Object.assign(Root, {
1331
- _tabMeta: Root._tabMeta,
1332
- GeneralSection: ProductCreateGeneralSection,
1333
- MediaSection: ProductCreateMediaSection
1334
- });
1335
-
1336
- // src/pages/products/create/product-create-inventory-kit-form/product-create-inventory-kit-form.tsx
1337
- import { Children as Children2 } from "react";
1338
-
1339
- // src/pages/products/create/product-create-inventory-kit-form/components/product-create-inventory-kit-section/product-create-inventory-kit-section.tsx
1340
- import { Button as Button2, Heading as Heading3, IconButton as IconButton2, Input as Input3, Label } from "@medusajs/ui";
1341
- import { useFieldArray as useFieldArray3, useWatch } from "react-hook-form";
1342
- import { XMarkMini as XMarkMini2 } from "@medusajs/icons";
1343
- import { useTranslation as useTranslation7 } from "react-i18next";
1344
- import { jsx as jsx7, jsxs as jsxs7 } from "react/jsx-runtime";
1345
- function VariantSection({ variant, index }) {
1346
- const { t } = useTranslation7();
1347
- const form = useTabbedForm();
1348
- const inventory = useFieldArray3({
1349
- control: form.control,
1350
- name: `variants.${index}.inventory`
1351
- });
1352
- const inventoryFormData = useWatch({
1353
- control: form.control,
1354
- name: `variants.${index}.inventory`
1355
- });
1356
- const items = useComboboxData({
1357
- queryKey: ["inventory_items"],
1358
- queryFn: (params) => fetchQuery(`/vendor/inventory-items`, {
1359
- method: "GET",
1360
- query: params
1361
- }),
1362
- getOptions: (data) => data.inventory_items.map((item) => ({
1363
- label: item.title || item.sku || item.id,
1364
- value: item.id
1365
- }))
1366
- });
1367
- const isItemOptionDisabled = (option, inventoryIndex) => {
1368
- return inventoryFormData?.some(
1369
- (i, index2) => index2 != inventoryIndex && i.inventory_item_id === option.value
1370
- );
1371
- };
1372
- return /* @__PURE__ */ jsxs7("div", { className: "grid gap-y-4", children: [
1373
- /* @__PURE__ */ jsxs7("div", { className: "flex items-start justify-between gap-x-4", children: [
1374
- /* @__PURE__ */ jsxs7("div", { className: "flex flex-col", children: [
1375
- /* @__PURE__ */ jsx7(Form.Label, { children: variant.title }),
1376
- /* @__PURE__ */ jsx7(Form.Hint, { children: t("products.create.inventory.label") })
1377
- ] }),
1378
- /* @__PURE__ */ jsx7(
1379
- Button2,
1380
- {
1381
- size: "small",
1382
- variant: "secondary",
1383
- type: "button",
1384
- onClick: () => {
1385
- inventory.append({
1386
- inventory_item_id: "",
1387
- required_quantity: ""
1388
- });
1389
- },
1390
- children: t("actions.add")
1391
- }
1392
- )
1393
- ] }),
1394
- inventory.fields.map((inventoryItem, inventoryIndex) => /* @__PURE__ */ jsxs7(
1395
- "li",
1396
- {
1397
- className: "bg-ui-bg-component shadow-elevation-card-rest grid grid-cols-[1fr_28px] items-center gap-1.5 rounded-xl p-1.5",
1398
- children: [
1399
- /* @__PURE__ */ jsxs7("div", { className: "grid grid-cols-[min-content,1fr] items-center gap-1.5", children: [
1400
- /* @__PURE__ */ jsx7("div", { className: "flex items-center px-2 py-1.5", children: /* @__PURE__ */ jsx7(
1401
- Label,
1402
- {
1403
- size: "xsmall",
1404
- weight: "plus",
1405
- className: "text-ui-fg-subtle",
1406
- htmlFor: `variants.${index}.inventory.${inventoryIndex}.inventory_item_id`,
1407
- children: t("fields.item")
1408
- }
1409
- ) }),
1410
- /* @__PURE__ */ jsx7(
1411
- Form.Field,
1412
- {
1413
- control: form.control,
1414
- name: `variants.${index}.inventory.${inventoryIndex}.inventory_item_id`,
1415
- render: ({ field }) => {
1416
- return /* @__PURE__ */ jsx7(Form.Item, { children: /* @__PURE__ */ jsx7(Form.Control, { children: /* @__PURE__ */ jsx7(
1417
- Combobox,
1418
- {
1419
- ...field,
1420
- options: items.options.map((o) => ({
1421
- ...o,
1422
- disabled: isItemOptionDisabled(o, inventoryIndex)
1423
- })),
1424
- searchValue: items.searchValue,
1425
- onSearchValueChange: items.onSearchValueChange,
1426
- fetchNextPage: items.fetchNextPage,
1427
- className: "bg-ui-bg-field-component hover:bg-ui-bg-field-component-hover",
1428
- placeholder: t(
1429
- "products.create.inventory.itemPlaceholder"
1430
- )
1431
- }
1432
- ) }) });
1433
- }
1434
- }
1435
- ),
1436
- /* @__PURE__ */ jsx7("div", { className: "flex items-center px-2 py-1.5", children: /* @__PURE__ */ jsx7(
1437
- Label,
1438
- {
1439
- size: "xsmall",
1440
- weight: "plus",
1441
- className: "text-ui-fg-subtle",
1442
- htmlFor: `variants.${index}.inventory.${inventoryIndex}.required_quantity`,
1443
- children: t("fields.quantity")
1444
- }
1445
- ) }),
1446
- /* @__PURE__ */ jsx7(
1447
- Form.Field,
1448
- {
1449
- control: form.control,
1450
- name: `variants.${index}.inventory.${inventoryIndex}.required_quantity`,
1451
- render: ({ field: { onChange, value, ...field } }) => {
1452
- return /* @__PURE__ */ jsxs7(Form.Item, { children: [
1453
- /* @__PURE__ */ jsx7(Form.Control, { children: /* @__PURE__ */ jsx7(
1454
- Input3,
1455
- {
1456
- type: "number",
1457
- className: "bg-ui-bg-field-component",
1458
- min: 0,
1459
- value,
1460
- onChange: (e) => {
1461
- const value2 = e.target.value;
1462
- if (value2 === "") {
1463
- onChange(null);
1464
- } else {
1465
- onChange(Number(value2));
1466
- }
1467
- },
1468
- ...field,
1469
- placeholder: t(
1470
- "products.create.inventory.quantityPlaceholder"
1471
- )
1472
- }
1473
- ) }),
1474
- /* @__PURE__ */ jsx7(Form.ErrorMessage, {})
1475
- ] });
1476
- }
1477
- }
1478
- )
1479
- ] }),
1480
- /* @__PURE__ */ jsx7(
1481
- IconButton2,
1482
- {
1483
- type: "button",
1484
- size: "small",
1485
- variant: "transparent",
1486
- className: "text-ui-fg-muted",
1487
- onClick: () => inventory.remove(inventoryIndex),
1488
- children: /* @__PURE__ */ jsx7(XMarkMini2, {})
1489
- }
1490
- )
1491
- ]
1492
- },
1493
- inventoryItem.id
1494
- ))
1495
- ] });
1496
- }
1497
- var ProductCreateInventoryKitSection = () => {
1498
- const { t } = useTranslation7();
1499
- const form = useTabbedForm();
1500
- const variants = useFieldArray3({
1501
- control: form.control,
1502
- name: "variants"
1503
- });
1504
- return /* @__PURE__ */ jsxs7("div", { id: "organize", className: "flex flex-col gap-y-8", children: [
1505
- /* @__PURE__ */ jsx7(Heading3, { children: t("products.create.inventory.heading") }),
1506
- variants.fields.filter((v) => v.inventory_kit).map((variant, variantIndex) => /* @__PURE__ */ jsx7(
1507
- VariantSection,
1508
- {
1509
- variant,
1510
- index: variantIndex
1511
- },
1512
- variant.id
1513
- ))
1514
- ] });
1515
- };
1516
-
1517
- // src/pages/products/create/product-create-inventory-kit-form/product-create-inventory-kit-form.tsx
1518
- import { jsx as jsx8 } from "react/jsx-runtime";
1519
- var Root2 = ({ children }) => {
1520
- if (Children2.count(children) > 0) {
1521
- return /* @__PURE__ */ jsx8("div", { className: "flex flex-col items-center p-16", children: /* @__PURE__ */ jsx8("div", { className: "flex w-full max-w-[720px] flex-col gap-y-8", children }) });
1522
- }
1523
- return /* @__PURE__ */ jsx8("div", { className: "flex flex-col items-center p-16", children: /* @__PURE__ */ jsx8("div", { className: "flex w-full max-w-[720px] flex-col gap-y-8", children: /* @__PURE__ */ jsx8(ProductCreateInventoryKitSection, {}) }) });
1524
- };
1525
- Root2._tabMeta = {
1526
- id: "inventory",
1527
- labelKey: "products.create.tabs.inventory",
1528
- isVisible: (form) => form.getValues("variants").some((v) => v.manage_inventory && v.inventory_kit)
1529
- };
1530
- var ProductCreateInventoryKitForm = Object.assign(Root2, {
1531
- _tabMeta: Root2._tabMeta,
1532
- InventoryKitSection: ProductCreateInventoryKitSection
1533
- });
1534
-
1535
- // src/pages/products/create/product-create-organize-form/product-create-organize-form.tsx
1536
- import { Children as Children3 } from "react";
1537
-
1538
- // src/pages/products/create/product-create-organize-form/components/product-create-organize-section/product-create-details-organize-section.tsx
1539
- import { useState as useState3 } from "react";
1540
- import { Heading as Heading4 } from "@medusajs/ui";
1541
- import { useTranslation as useTranslation8 } from "react-i18next";
1542
- import { jsx as jsx9, jsxs as jsxs8 } from "react/jsx-runtime";
1543
- var ProductCreateOrganizationSection = () => {
1544
- const { t } = useTranslation8();
1545
- const form = useTabbedForm();
1546
- const collections = useComboboxData({
1547
- queryKey: ["product_collections"],
1548
- queryFn: (params) => sdk.vendor.collections.query({ offset: 0, limit: 100, ...params }),
1549
- getOptions: (data) => data.collections.map((collection) => ({
1550
- label: collection.title,
1551
- value: collection.id
1552
- }))
1553
- });
1554
- const types = useComboboxData({
1555
- queryKey: ["product_types", "creating"],
1556
- queryFn: (params) => fetchQuery("/vendor/product-types", {
1557
- method: "GET",
1558
- query: params
1559
- }),
1560
- getOptions: (data) => data.product_types.map((type) => ({
1561
- label: type.value,
1562
- value: type.id
1563
- }))
1564
- });
1565
- const tags = useComboboxData({
1566
- queryKey: ["product_tags", "creating"],
1567
- queryFn: (params) => fetchQuery("/vendor/product-tags", {
1568
- method: "GET",
1569
- query: params
1570
- }),
1571
- getOptions: (data) => data.product_tags.map((tag) => ({
1572
- label: tag.value,
1573
- value: tag.id
1574
- }))
1575
- });
1576
- return /* @__PURE__ */ jsxs8("div", { id: "organize", className: "flex flex-col gap-y-8", children: [
1577
- /* @__PURE__ */ jsx9(Heading4, { children: t("products.organization.header") }),
1578
- /* @__PURE__ */ jsx9(
1579
- SwitchBox,
1580
- {
1581
- control: form.control,
1582
- name: "discountable",
1583
- label: t("products.fields.discountable.label"),
1584
- description: t("products.fields.discountable.hint"),
1585
- optional: true
1586
- }
1587
- ),
1588
- /* @__PURE__ */ jsxs8("div", { className: "grid grid-cols-1 gap-4 md:grid-cols-2", children: [
1589
- /* @__PURE__ */ jsx9(
1590
- Form.Field,
1591
- {
1592
- control: form.control,
1593
- name: "tags",
1594
- render: ({ field }) => {
1595
- return /* @__PURE__ */ jsxs8(Form.Item, { children: [
1596
- /* @__PURE__ */ jsx9(Form.Label, { optional: true, children: t("products.fields.tags.label") }),
1597
- /* @__PURE__ */ jsx9(Form.Control, { children: /* @__PURE__ */ jsx9(
1598
- Combobox,
1599
- {
1600
- ...field,
1601
- options: tags.options,
1602
- searchValue: tags.searchValue,
1603
- onSearchValueChange: tags.onSearchValueChange,
1604
- fetchNextPage: tags.fetchNextPage
1605
- }
1606
- ) }),
1607
- /* @__PURE__ */ jsx9(Form.ErrorMessage, {})
1608
- ] });
1609
- }
1610
- }
1611
- ),
1612
- /* @__PURE__ */ jsx9(
1613
- Form.Field,
1614
- {
1615
- control: form.control,
1616
- name: "type_id",
1617
- render: ({ field }) => {
1618
- return /* @__PURE__ */ jsxs8(Form.Item, { children: [
1619
- /* @__PURE__ */ jsx9(Form.Label, { optional: true, children: t("products.fields.type.label") }),
1620
- /* @__PURE__ */ jsx9(Form.Control, { children: /* @__PURE__ */ jsx9(
1621
- Combobox,
1622
- {
1623
- ...field,
1624
- options: types.options,
1625
- searchValue: types.searchValue,
1626
- onSearchValueChange: types.onSearchValueChange,
1627
- fetchNextPage: types.fetchNextPage,
1628
- allowClear: true
1629
- }
1630
- ) }),
1631
- /* @__PURE__ */ jsx9(Form.ErrorMessage, {})
1632
- ] });
1633
- }
1634
- }
1635
- )
1636
- ] }),
1637
- /* @__PURE__ */ jsxs8("div", { className: "grid grid-cols-1 gap-4 md:grid-cols-2", children: [
1638
- /* @__PURE__ */ jsx9(
1639
- Form.Field,
1640
- {
1641
- control: form.control,
1642
- name: "categories",
1643
- render: ({ field }) => {
1644
- const [isFocused, setIsFocused] = useState3(false);
1645
- return /* @__PURE__ */ jsxs8(Form.Item, { children: [
1646
- /* @__PURE__ */ jsx9(Form.Label, { tooltip: t("products.fields.primaryCategory.tooltip"), children: t("products.fields.primaryCategory.label") }),
1647
- /* @__PURE__ */ jsx9(Form.Control, { children: /* @__PURE__ */ jsx9(
1648
- CategoryCombobox,
1649
- {
1650
- ...field,
1651
- onFocus: () => setIsFocused(true),
1652
- onBlur: () => {
1653
- setIsFocused(false);
1654
- field.onBlur();
1655
- },
1656
- isSingleSelect: true,
1657
- allowClear: false
1658
- }
1659
- ) }),
1660
- !isFocused && /* @__PURE__ */ jsx9(Form.ErrorMessage, {})
1661
- ] });
1662
- }
1663
- }
1664
- ),
1665
- /* @__PURE__ */ jsx9(
1666
- Form.Field,
1667
- {
1668
- control: form.control,
1669
- name: "secondary_categories",
1670
- render: ({ field }) => {
1671
- return /* @__PURE__ */ jsxs8(Form.Item, { children: [
1672
- /* @__PURE__ */ jsx9(Form.Label, { optional: true, children: t("products.fields.secondaryCategories.label", "Secondary Categories") }),
1673
- /* @__PURE__ */ jsx9(Form.Control, { children: /* @__PURE__ */ jsx9(
1674
- CategoryCombobox,
1675
- {
1676
- ...field,
1677
- value: field.value || []
1678
- }
1679
- ) }),
1680
- /* @__PURE__ */ jsx9(Form.ErrorMessage, {})
1681
- ] });
1682
- }
1683
- }
1684
- )
1685
- ] }),
1686
- /* @__PURE__ */ jsx9("div", { className: "grid grid-cols-1 gap-4 md:grid-cols-2", children: /* @__PURE__ */ jsx9(
1687
- Form.Field,
1688
- {
1689
- control: form.control,
1690
- name: "collection_id",
1691
- render: ({ field }) => {
1692
- return /* @__PURE__ */ jsxs8(Form.Item, { children: [
1693
- /* @__PURE__ */ jsx9(Form.Label, { optional: true, children: t("products.fields.collection.label") }),
1694
- /* @__PURE__ */ jsx9(Form.Control, { children: /* @__PURE__ */ jsx9(
1695
- Combobox,
1696
- {
1697
- ...field,
1698
- options: collections.options,
1699
- searchValue: collections.searchValue,
1700
- onSearchValueChange: collections.onSearchValueChange,
1701
- fetchNextPage: collections.fetchNextPage,
1702
- allowClear: true
1703
- }
1704
- ) }),
1705
- /* @__PURE__ */ jsx9(Form.ErrorMessage, {})
1706
- ] });
1707
- }
1708
- }
1709
- ) })
1710
- ] });
1711
- };
1712
-
1713
- // src/pages/products/create/product-create-organize-form/components/product-create-organize-attribute-section/product-create-details-attribute-section.tsx
1714
- import { Heading as Heading5, Input as Input4 } from "@medusajs/ui";
1715
- import { useTranslation as useTranslation9 } from "react-i18next";
1716
- import { jsx as jsx10, jsxs as jsxs9 } from "react/jsx-runtime";
1717
- var ProductCreateAttributeSection = () => {
1718
- const { t } = useTranslation9();
1719
- const form = useTabbedForm();
1720
- return /* @__PURE__ */ jsxs9("div", { id: "attributes", className: "flex flex-col gap-y-8", children: [
1721
- /* @__PURE__ */ jsx10(Heading5, { level: "h2", children: t("products.attributes") }),
1722
- /* @__PURE__ */ jsxs9("div", { className: "grid grid-cols-2 gap-x-4 gap-y-8", children: [
1723
- /* @__PURE__ */ jsx10(
1724
- Form.Field,
1725
- {
1726
- control: form.control,
1727
- name: "origin_country",
1728
- render: ({ field }) => {
1729
- return /* @__PURE__ */ jsxs9(Form.Item, { children: [
1730
- /* @__PURE__ */ jsx10(Form.Label, { optional: true, children: t("products.fields.countryOrigin.label") }),
1731
- /* @__PURE__ */ jsx10(Form.Control, { children: /* @__PURE__ */ jsx10(CountrySelect, { ...field }) })
1732
- ] });
1733
- }
1734
- }
1735
- ),
1736
- /* @__PURE__ */ jsx10(
1737
- Form.Field,
1738
- {
1739
- control: form.control,
1740
- name: "material",
1741
- render: ({ field }) => {
1742
- return /* @__PURE__ */ jsxs9(Form.Item, { children: [
1743
- /* @__PURE__ */ jsx10(Form.Label, { optional: true, children: t("products.fields.material.label") }),
1744
- /* @__PURE__ */ jsx10(Form.Control, { children: /* @__PURE__ */ jsx10(Input4, { ...field }) })
1745
- ] });
1746
- }
1747
- }
1748
- )
1749
- ] }),
1750
- /* @__PURE__ */ jsxs9("div", { className: "grid grid-cols-2 gap-x-4 gap-y-8", children: [
1751
- /* @__PURE__ */ jsx10(
1752
- Form.Field,
1753
- {
1754
- control: form.control,
1755
- name: "width",
1756
- render: ({ field }) => {
1757
- return /* @__PURE__ */ jsxs9(Form.Item, { children: [
1758
- /* @__PURE__ */ jsx10(Form.Label, { optional: true, children: t("products.fields.width.label") }),
1759
- /* @__PURE__ */ jsx10(Form.Control, { children: /* @__PURE__ */ jsx10(Input4, { ...field, type: "number", min: 0 }) })
1760
- ] });
1761
- }
1762
- }
1763
- ),
1764
- /* @__PURE__ */ jsx10(
1765
- Form.Field,
1766
- {
1767
- control: form.control,
1768
- name: "length",
1769
- render: ({ field }) => {
1770
- return /* @__PURE__ */ jsxs9(Form.Item, { children: [
1771
- /* @__PURE__ */ jsx10(Form.Label, { optional: true, children: t("products.fields.length.label") }),
1772
- /* @__PURE__ */ jsx10(Form.Control, { children: /* @__PURE__ */ jsx10(Input4, { ...field, type: "number", min: 0 }) })
1773
- ] });
1774
- }
1775
- }
1776
- ),
1777
- /* @__PURE__ */ jsx10(
1778
- Form.Field,
1779
- {
1780
- control: form.control,
1781
- name: "height",
1782
- render: ({ field }) => {
1783
- return /* @__PURE__ */ jsxs9(Form.Item, { children: [
1784
- /* @__PURE__ */ jsx10(Form.Label, { optional: true, children: t("products.fields.height.label") }),
1785
- /* @__PURE__ */ jsx10(Form.Control, { children: /* @__PURE__ */ jsx10(Input4, { ...field, type: "number", min: 0 }) })
1786
- ] });
1787
- }
1788
- }
1789
- ),
1790
- /* @__PURE__ */ jsx10(
1791
- Form.Field,
1792
- {
1793
- control: form.control,
1794
- name: "weight",
1795
- render: ({ field }) => {
1796
- return /* @__PURE__ */ jsxs9(Form.Item, { children: [
1797
- /* @__PURE__ */ jsx10(Form.Label, { optional: true, children: t("products.fields.weight.label") }),
1798
- /* @__PURE__ */ jsx10(Form.Control, { children: /* @__PURE__ */ jsx10(Input4, { ...field, type: "number", min: 0 }) })
1799
- ] });
1800
- }
1801
- }
1802
- ),
1803
- /* @__PURE__ */ jsx10(
1804
- Form.Field,
1805
- {
1806
- control: form.control,
1807
- name: "mid_code",
1808
- render: ({ field }) => {
1809
- return /* @__PURE__ */ jsxs9(Form.Item, { children: [
1810
- /* @__PURE__ */ jsx10(Form.Label, { optional: true, children: t("products.fields.mid_code.label") }),
1811
- /* @__PURE__ */ jsx10(Form.Control, { children: /* @__PURE__ */ jsx10(Input4, { ...field }) })
1812
- ] });
1813
- }
1814
- }
1815
- ),
1816
- /* @__PURE__ */ jsx10(
1817
- Form.Field,
1818
- {
1819
- control: form.control,
1820
- name: "hs_code",
1821
- render: ({ field }) => {
1822
- return /* @__PURE__ */ jsxs9(Form.Item, { children: [
1823
- /* @__PURE__ */ jsx10(Form.Label, { optional: true, children: t("products.fields.hs_code.label") }),
1824
- /* @__PURE__ */ jsx10(Form.Control, { children: /* @__PURE__ */ jsx10(Input4, { ...field }) })
1825
- ] });
1826
- }
1827
- }
1828
- )
1829
- ] })
1830
- ] });
1831
- };
1832
-
1833
- // src/pages/products/create/product-create-organize-form/components/product-create-sales-channel-stacked-modal/product-create-sales-channel-drawer.tsx
1834
- import {
1835
- Button as Button3,
1836
- createDataTableColumnHelper
1837
- } from "@medusajs/ui";
1838
- import { useEffect as useEffect3, useMemo as useMemo2, useState as useState4 } from "react";
1839
- import { useTranslation as useTranslation10 } from "react-i18next";
1840
- import { keepPreviousData } from "@tanstack/react-query";
1841
-
1842
- // src/pages/products/create/product-create-organize-form/constants.ts
1843
- var SC_STACKED_MODAL_ID = "sc";
1844
-
1845
- // src/pages/products/create/product-create-organize-form/components/product-create-sales-channel-stacked-modal/product-create-sales-channel-drawer.tsx
1846
- import { jsx as jsx11, jsxs as jsxs10 } from "react/jsx-runtime";
1847
- var PAGE_SIZE = 50;
1848
- var ProductCreateSalesChannelStackedModal = () => {
1849
- const { t } = useTranslation10();
1850
- const form = useTabbedForm();
1851
- const { getValues, setValue } = form;
1852
- const { setIsOpen, getIsOpen } = useStackedModal();
1853
- const [rowSelection, setRowSelection] = useState4(
1854
- {}
1855
- );
1856
- const [state, setState] = useState4([]);
1857
- const searchParams = useSalesChannelTableQuery({
1858
- pageSize: PAGE_SIZE,
1859
- prefix: SC_STACKED_MODAL_ID
1860
- });
1861
- const { sales_channels, count, isLoading, isError, error } = useSalesChannels(
1862
- searchParams,
1863
- {
1864
- placeholderData: keepPreviousData
1865
- }
1866
- );
1867
- const open = getIsOpen(SC_STACKED_MODAL_ID);
1868
- useEffect3(() => {
1869
- if (!open) {
1870
- return;
1871
- }
1872
- const salesChannels = getValues("sales_channels");
1873
- if (salesChannels) {
1874
- setState(
1875
- salesChannels.map((channel) => ({
1876
- id: channel.id,
1877
- name: channel.name
1878
- }))
1879
- );
1880
- setRowSelection(
1881
- salesChannels.reduce(
1882
- (acc, channel) => ({
1883
- ...acc,
1884
- [channel.id]: true
1885
- }),
1886
- {}
1887
- )
1888
- );
1889
- }
1890
- }, [open, getValues]);
1891
- const onRowSelectionChange = (state2) => {
1892
- const ids = Object.keys(state2);
1893
- const addedIdsSet = new Set(
1894
- ids.filter((id) => state2[id] && !rowSelection[id])
1895
- );
1896
- let addedSalesChannels = [];
1897
- if (addedIdsSet.size > 0) {
1898
- addedSalesChannels = sales_channels?.filter((channel) => addedIdsSet.has(channel.id)) ?? [];
1899
- }
1900
- setState((prev) => {
1901
- const filteredPrev = prev.filter((channel) => state2[channel.id]);
1902
- return Array.from(/* @__PURE__ */ new Set([...filteredPrev, ...addedSalesChannels]));
1903
- });
1904
- setRowSelection(state2);
1905
- };
1906
- const handleAdd = () => {
1907
- setValue("sales_channels", state, {
1908
- shouldDirty: true,
1909
- shouldTouch: true
1910
- });
1911
- setIsOpen(SC_STACKED_MODAL_ID, false);
1912
- };
1913
- const filters = useSalesChannelTableFilters();
1914
- const columns = useColumns();
1915
- const emptyState = useSalesChannelTableEmptyState();
1916
- if (isError) {
1917
- throw error;
1918
- }
1919
- return /* @__PURE__ */ jsxs10(StackedFocusModal.Content, { className: "flex flex-col overflow-hidden", children: [
1920
- /* @__PURE__ */ jsx11(StackedFocusModal.Header, {}),
1921
- /* @__PURE__ */ jsx11(StackedFocusModal.Body, { className: "flex-1 overflow-hidden", children: /* @__PURE__ */ jsx11(
1922
- DataTable,
1923
- {
1924
- data: sales_channels,
1925
- columns,
1926
- filters,
1927
- emptyState,
1928
- rowCount: count,
1929
- pageSize: PAGE_SIZE,
1930
- getRowId: (row) => row.id,
1931
- rowSelection: {
1932
- state: rowSelection,
1933
- onRowSelectionChange
1934
- },
1935
- isLoading,
1936
- layout: "fill",
1937
- prefix: SC_STACKED_MODAL_ID
1938
- }
1939
- ) }),
1940
- /* @__PURE__ */ jsx11(StackedFocusModal.Footer, { children: /* @__PURE__ */ jsxs10("div", { className: "flex items-center justify-end gap-x-2", children: [
1941
- /* @__PURE__ */ jsx11(StackedFocusModal.Close, { asChild: true, children: /* @__PURE__ */ jsx11(Button3, { size: "small", variant: "secondary", type: "button", children: t("actions.cancel") }) }),
1942
- /* @__PURE__ */ jsx11(Button3, { size: "small", onClick: handleAdd, type: "button", children: t("actions.save") })
1943
- ] }) })
1944
- ] });
1945
- };
1946
- var columnHelper = createDataTableColumnHelper();
1947
- var useColumns = () => {
1948
- const base = useSalesChannelTableColumns();
1949
- return useMemo2(() => [columnHelper.select(), ...base], [base]);
1950
- };
1951
-
1952
- // src/pages/products/create/product-create-organize-form/product-create-organize-form.tsx
1953
- import { jsx as jsx12, jsxs as jsxs11 } from "react/jsx-runtime";
1954
- var Root3 = ({ children }) => {
1955
- if (Children3.count(children) > 0) {
1956
- return /* @__PURE__ */ jsxs11(StackedFocusModal, { id: SC_STACKED_MODAL_ID, children: [
1957
- /* @__PURE__ */ jsx12("div", { className: "flex flex-col items-center p-16", children: /* @__PURE__ */ jsx12("div", { className: "flex w-full max-w-[720px] flex-col gap-y-8", children }) }),
1958
- /* @__PURE__ */ jsx12(ProductCreateSalesChannelStackedModal, {})
1959
- ] });
1960
- }
1961
- return /* @__PURE__ */ jsxs11(StackedFocusModal, { id: SC_STACKED_MODAL_ID, children: [
1962
- /* @__PURE__ */ jsx12("div", { className: "flex flex-col items-center p-16", children: /* @__PURE__ */ jsx12("div", { className: "flex w-full max-w-[720px] flex-col gap-y-8", children: /* @__PURE__ */ jsx12(ProductCreateOrganizationSection, {}) }) }),
1963
- /* @__PURE__ */ jsx12(ProductCreateSalesChannelStackedModal, {})
1964
- ] });
1965
- };
1966
- Root3._tabMeta = {
1967
- id: "organize",
1968
- labelKey: "products.create.tabs.organize",
1969
- validationFields: ["discountable", "categories", "tags", "sales_channels"]
1970
- };
1971
- var ProductCreateOrganizeForm = Object.assign(Root3, {
1972
- _tabMeta: Root3._tabMeta,
1973
- OrganizationSection: ProductCreateOrganizationSection,
1974
- AttributeSection: ProductCreateAttributeSection,
1975
- SalesChannelModal: ProductCreateSalesChannelStackedModal
1976
- });
1977
-
1978
- // src/pages/products/create/product-create-variants-form/product-create-variants-form.tsx
1979
- import { useCallback, useEffect as useEffect4, useMemo as useMemo3, useRef as useRef2, useState as useState5 } from "react";
1980
- import { Checkbox, Tooltip as Tooltip2 } from "@medusajs/ui";
1981
- import { useWatch as useWatch2 } from "react-hook-form";
1982
- import { useTranslation as useTranslation11 } from "react-i18next";
1983
- import { jsx as jsx13 } from "react/jsx-runtime";
1984
- var ProductCreateVariantsForm = ({
1985
- form,
1986
- store,
1987
- regions = [],
1988
- pricePreferences = [],
1989
- onOpenMediaModal,
1990
- productMedia = []
1991
- }) => {
1992
- const { t } = useTranslation11();
1993
- const [searchValue, setSearchValue] = useState5("");
1994
- const variants = useWatch2({
1995
- control: form.control,
1996
- name: "variants",
1997
- defaultValue: []
1998
- });
1999
- const attributesResult = useAttributes();
2000
- const allAttributes = attributesResult.attributes || [];
2001
- const { stock_locations = [] } = useStockLocations({
2002
- limit: 9999,
2003
- fields: "id,name"
2004
- });
2005
- const formValues = useWatch2({
2006
- control: form.control
2007
- });
2008
- const variantAttributes = useMemo3(() => {
2009
- const result = [];
2010
- allAttributes.forEach((attr) => {
2011
- if (attr.ui_component === "multivalue") {
2012
- const useForVariants = formValues?.[`${attr.handle}UseForVariants`];
2013
- if (useForVariants === false) return;
2014
- const selectedValueIds = formValues?.[attr.handle];
2015
- if (selectedValueIds && Array.isArray(selectedValueIds) && selectedValueIds.length > 0) {
2016
- const selectedValues = selectedValueIds.map((valueId) => {
2017
- const possibleValue = attr.possible_values?.find(
2018
- (pv) => pv.id === valueId
2019
- );
2020
- return possibleValue ? { id: valueId, value: possibleValue.value } : null;
2021
- }).filter(
2022
- (item) => item !== null
2023
- );
2024
- if (selectedValues.length > 0) {
2025
- result.push({
2026
- handle: attr.handle,
2027
- name: attr.name,
2028
- selectedValues
2029
- });
2030
- }
2031
- }
2032
- }
2033
- });
2034
- const options = formValues?.options || [];
2035
- options.forEach((option) => {
2036
- if (option?.useForVariants !== false && option?.title && option?.values && Array.isArray(option.values) && option.values.length > 0) {
2037
- result.push({
2038
- handle: `option-${option.title}`,
2039
- name: option.title,
2040
- selectedValues: option.values.map((value) => ({
2041
- id: value,
2042
- value
2043
- }))
2044
- });
2045
- }
2046
- });
2047
- return result;
2048
- }, [formValues, allAttributes]);
2049
- const hasProductMedia = productMedia.length > 0;
2050
- const columns = useColumns2({
2051
- variantAttributes,
2052
- store,
2053
- regions,
2054
- pricePreferences,
2055
- stockLocations: stock_locations,
2056
- onOpenMediaModal,
2057
- form,
2058
- productMedia,
2059
- hasProductMedia
2060
- });
2061
- const variantData = useMemo3(() => {
2062
- const ret = [];
2063
- if (variantAttributes.length > 0) {
2064
- const totalCombinations = variantAttributes.reduce(
2065
- (acc, attr) => acc * attr.selectedValues.length,
2066
- 1
2067
- );
2068
- for (let i = 0; i < totalCombinations; i++) {
2069
- const variantOptions = {};
2070
- variantAttributes.forEach((attr) => {
2071
- let valueIndex = 0;
2072
- let divisor = 1;
2073
- for (let j = variantAttributes.length - 1; j >= 0; j--) {
2074
- if (variantAttributes[j].handle === attr.handle) {
2075
- valueIndex = Math.floor(i / divisor) % attr.selectedValues.length;
2076
- break;
2077
- }
2078
- divisor *= variantAttributes[j].selectedValues.length;
2079
- }
2080
- variantOptions[attr.name] = attr.selectedValues[valueIndex]?.value || "";
2081
- });
2082
- const autoTitle = variantAttributes.map((attr) => variantOptions[attr.name]).filter(Boolean).join(" / ");
2083
- const existingVariant = variants.find((v) => {
2084
- if (!v.options) return false;
2085
- return variantAttributes.every(
2086
- (attr) => v.options[attr.name] === variantOptions[attr.name]
2087
- );
2088
- });
2089
- ret.push({
2090
- title: autoTitle,
2091
- should_create: existingVariant?.should_create ?? true,
2092
- variant_rank: i,
2093
- options: variantOptions,
2094
- sku: existingVariant?.sku || "",
2095
- prices: existingVariant?.prices || {},
2096
- is_default: i === 0,
2097
- media: existingVariant?.media || [],
2098
- originalIndex: existingVariant ? variants.indexOf(existingVariant) : i
2099
- });
2100
- }
2101
- } else {
2102
- variants.forEach((v, i) => {
2103
- if (v.should_create) {
2104
- ret.push({
2105
- ...v,
2106
- originalIndex: i
2107
- });
2108
- }
2109
- });
2110
- }
2111
- return ret;
2112
- }, [variants, variantAttributes]);
2113
- const filteredVariantData = useMemo3(() => {
2114
- if (!searchValue.trim()) return variantData;
2115
- return variantData.filter(
2116
- (variant) => variant.title.toLowerCase().includes(searchValue.toLowerCase())
2117
- );
2118
- }, [variantData, searchValue]);
2119
- const variantStructureKey = useMemo3(() => {
2120
- return variantAttributes.map(
2121
- (attr) => `${attr.handle}:${attr.selectedValues.map((v) => v.id).join(",")}`
2122
- ).join("|");
2123
- }, [variantAttributes]);
2124
- useEffect4(() => {
2125
- if (variantAttributes.length > 0) {
2126
- const totalCombinations = variantAttributes.reduce(
2127
- (acc, attr) => acc * attr.selectedValues.length,
2128
- 1
2129
- );
2130
- const currentVariants = form.getValues("variants") || [];
2131
- const newVariants = [];
2132
- for (let i = 0; i < totalCombinations; i++) {
2133
- const variantOptions = {};
2134
- variantAttributes.forEach((attr) => {
2135
- let valueIndex = 0;
2136
- let divisor = 1;
2137
- for (let j = variantAttributes.length - 1; j >= 0; j--) {
2138
- if (variantAttributes[j].handle === attr.handle) {
2139
- valueIndex = Math.floor(i / divisor) % attr.selectedValues.length;
2140
- break;
2141
- }
2142
- divisor *= variantAttributes[j].selectedValues.length;
2143
- }
2144
- variantOptions[attr.name] = attr.selectedValues[valueIndex]?.value || "";
2145
- });
2146
- const autoTitle = variantAttributes.map((attr) => variantOptions[attr.name]).filter(Boolean).join(" / ");
2147
- const existingVariant = currentVariants.find((v) => {
2148
- if (!v.options) return false;
2149
- return variantAttributes.every(
2150
- (attr) => v.options[attr.name] === variantOptions[attr.name]
2151
- );
2152
- });
2153
- newVariants.push({
2154
- title: autoTitle,
2155
- should_create: existingVariant?.should_create ?? true,
2156
- variant_rank: i,
2157
- options: variantOptions,
2158
- sku: existingVariant?.sku || "",
2159
- prices: existingVariant?.prices || {},
2160
- is_default: i === 0,
2161
- media: existingVariant?.media || []
2162
- });
2163
- }
2164
- form.setValue("variants", newVariants);
2165
- } else {
2166
- const currentVariants = form.getValues("variants") || [];
2167
- if (currentVariants.length === 0) {
2168
- const defaultVariant = decorateVariantsWithDefaultValues([
2169
- {
2170
- title: "Default variant",
2171
- should_create: true,
2172
- variant_rank: 0,
2173
- options: {},
2174
- sku: "",
2175
- prices: {},
2176
- is_default: true,
2177
- media: []
2178
- }
2179
- ]);
2180
- form.setValue("variants", defaultVariant);
2181
- } else {
2182
- const hasOnlyDefaultVariant = currentVariants.length === 1 && currentVariants[0].is_default;
2183
- if (!hasOnlyDefaultVariant) {
2184
- const defaultVariant = decorateVariantsWithDefaultValues([
2185
- {
2186
- title: "Default variant",
2187
- should_create: true,
2188
- variant_rank: 0,
2189
- options: {},
2190
- sku: "",
2191
- prices: {},
2192
- is_default: true,
2193
- media: []
2194
- }
2195
- ]);
2196
- form.setValue("variants", defaultVariant);
2197
- }
2198
- }
2199
- }
2200
- }, [
2201
- variantStructureKey,
2202
- form,
2203
- variantAttributes,
2204
- variantAttributes.length
2205
- ]);
2206
- return /* @__PURE__ */ jsx13("div", { className: "border-ui-border flex h-full flex-col justify-between divide-y", children: /* @__PURE__ */ jsx13(
2207
- DataGrid,
2208
- {
2209
- columns,
2210
- data: filteredVariantData,
2211
- state: form,
2212
- searchValue,
2213
- onSearchChange: setSearchValue,
2214
- searchPlaceholder: t(
2215
- "products.create.variants.productVariants.searchPlaceholder"
2216
- )
2217
- }
2218
- ) });
2219
- };
2220
- var columnHelper2 = createDataGridHelper();
2221
- var useColumns2 = ({
2222
- variantAttributes = [],
2223
- store,
2224
- regions: _regions = [],
2225
- pricePreferences = [],
2226
- stockLocations: _stockLocations = [],
2227
- onOpenMediaModal,
2228
- form,
2229
- productMedia = [],
2230
- hasProductMedia = false
2231
- }) => {
2232
- const { t } = useTranslation11();
2233
- const variants = useWatch2({
2234
- control: form.control,
2235
- name: "variants",
2236
- defaultValue: []
2237
- });
2238
- const variantsRef = useRef2(variants);
2239
- variantsRef.current = variants;
2240
- const allSelected = variants.length > 0 && variants.every((v) => v.should_create);
2241
- const someSelected = variants.some((v) => v.should_create) && !allSelected;
2242
- const handleSelectAll = useCallback(
2243
- (checked) => {
2244
- const currentVariants = form.getValues("variants") || [];
2245
- const updatedVariants = currentVariants.map((v) => ({
2246
- ...v,
2247
- should_create: checked
2248
- }));
2249
- form.setValue("variants", updatedVariants);
2250
- },
2251
- [form]
2252
- );
2253
- return useMemo3(
2254
- () => [
2255
- columnHelper2.column({
2256
- id: "checkbox",
2257
- header: () => /* @__PURE__ */ jsx13(
2258
- Checkbox,
2259
- {
2260
- checked: allSelected ? true : someSelected ? "indeterminate" : false,
2261
- onCheckedChange: handleSelectAll
2262
- }
2263
- ),
2264
- field: (context) => {
2265
- const rowData = context.row.original;
2266
- return `variants.${rowData.originalIndex}.should_create`;
2267
- },
2268
- type: "boolean",
2269
- cell: (context) => /* @__PURE__ */ jsx13(DataGrid.BooleanCell, { context }),
2270
- disableHiding: true,
2271
- size: 52,
2272
- pin: "left"
2273
- }),
2274
- columnHelper2.column({
2275
- id: "options_combined",
2276
- name: variantAttributes.length > 0 ? variantAttributes.map((attr) => attr.name).join(" / ") : t("products.create.variants.optionsHeader"),
2277
- header: () => {
2278
- const label = variantAttributes.length > 0 ? variantAttributes.map((attr) => attr.name).join(" / ") : t("products.create.variants.optionsHeader");
2279
- return /* @__PURE__ */ jsx13(Tooltip2, { content: label, children: /* @__PURE__ */ jsx13("span", { className: "w-full truncate", children: label }) });
2280
- },
2281
- cell: (context) => {
2282
- if (variantAttributes.length === 0) {
2283
- return /* @__PURE__ */ jsx13(DataGrid.ReadonlyCell, { context });
2284
- }
2285
- const rowData = context.row.original;
2286
- const combinedValue = variantAttributes.map(
2287
- (attr) => rowData.options?.[attr.name] || ""
2288
- ).filter(Boolean).join(" / ");
2289
- return /* @__PURE__ */ jsx13(DataGrid.ReadonlyCell, { context, children: combinedValue });
2290
- },
2291
- disableHiding: true,
2292
- pin: "left"
2293
- }),
2294
- columnHelper2.column({
2295
- id: "title",
2296
- name: t("fields.title"),
2297
- header: t("fields.title"),
2298
- field: (context) => {
2299
- const rowData = context.row.original;
2300
- return `variants.${rowData.originalIndex}.title`;
2301
- },
2302
- type: "text",
2303
- cell: (context) => /* @__PURE__ */ jsx13(DataGrid.TextCell, { context }),
2304
- disableHiding: true,
2305
- pin: "left"
2306
- }),
2307
- columnHelper2.column({
2308
- id: "media",
2309
- name: t(
2310
- "products.create.variants.productVariants.media"
2311
- ),
2312
- header: t(
2313
- "products.create.variants.productVariants.media"
2314
- ),
2315
- field: (context) => {
2316
- const rowData = context.row.original;
2317
- return `variants.${rowData.originalIndex}.media`;
2318
- },
2319
- type: "media",
2320
- cell: (context) => {
2321
- const rowData = context.row.original;
2322
- return /* @__PURE__ */ jsx13(
2323
- DataGridMediaCell,
2324
- {
2325
- context,
2326
- disabled: !hasProductMedia,
2327
- onOpenMediaModal: hasProductMedia ? () => {
2328
- const currentMedia = variantsRef.current[rowData.originalIndex]?.media;
2329
- onOpenMediaModal?.(
2330
- rowData.originalIndex,
2331
- rowData.title,
2332
- currentMedia,
2333
- productMedia
2334
- );
2335
- } : void 0
2336
- }
2337
- );
2338
- }
2339
- }),
2340
- columnHelper2.column({
2341
- id: "sku",
2342
- name: t("fields.sku"),
2343
- header: t("fields.sku"),
2344
- field: (context) => {
2345
- const rowData = context.row.original;
2346
- return `variants.${rowData.originalIndex}.sku`;
2347
- },
2348
- type: "text",
2349
- cell: (context) => /* @__PURE__ */ jsx13(DataGrid.TextCell, { context })
2350
- }),
2351
- ...createDataGridPriceColumns({
2352
- currencies: store?.supported_currencies?.map(
2353
- (c) => c.currency_code
2354
- ) || [],
2355
- pricePreferences,
2356
- getFieldName: (context, value) => {
2357
- const rowData = context.row.original;
2358
- return `variants.${rowData.originalIndex}.prices.${value}`;
2359
- },
2360
- t
2361
- })
2362
- ],
2363
- [
2364
- variantAttributes,
2365
- t,
2366
- store,
2367
- pricePreferences,
2368
- onOpenMediaModal,
2369
- allSelected,
2370
- someSelected,
2371
- handleSelectAll,
2372
- hasProductMedia,
2373
- productMedia
2374
- ]
2375
- );
2376
- };
2377
-
2378
- // src/pages/products/create/product-create-form/product-create-form.tsx
2379
- import { jsx as jsx14, jsxs as jsxs12 } from "react/jsx-runtime";
2380
- var SAVE_DRAFT_BUTTON = "save-draft-button";
2381
- var SEC_CAT_PRODUCT_KEY = "sec_cat_product_key";
2382
- var TAB_ORDER = [
2383
- "details" /* DETAILS */,
2384
- "organize" /* ORGANIZE */,
2385
- "attributes" /* ATTRIBUTES */,
2386
- "variants" /* VARIANTS */,
2387
- "inventory" /* INVENTORY */
2388
- ];
2389
- var isMovingForward = (currentTab, newTab) => {
2390
- const currentIndex = TAB_ORDER.indexOf(currentTab);
2391
- const newIndex = TAB_ORDER.indexOf(newTab);
2392
- return newIndex > currentIndex;
2393
- };
2394
- var ProductCreateForm = ({
2395
- defaultChannel,
2396
- store,
2397
- onOpenMediaModal,
2398
- onSaveVariantMediaRef
2399
- }) => {
2400
- const [tab, setTab] = useState6("details" /* DETAILS */);
2401
- const [maxReachedTab, setMaxReachedTab] = useState6("details" /* DETAILS */);
2402
- const [tabState, setTabState] = useState6({
2403
- ["details" /* DETAILS */]: "in-progress",
2404
- ["organize" /* ORGANIZE */]: "not-started",
2405
- ["attributes" /* ATTRIBUTES */]: "not-started",
2406
- ["variants" /* VARIANTS */]: "not-started",
2407
- ["inventory" /* INVENTORY */]: "not-started"
2408
- });
2409
- const { t } = useTranslation12();
2410
- const { handleSuccess } = useRouteModal();
2411
- const { regions } = useRegions({ limit: 9999 });
2412
- const { price_preferences: pricePreferences } = usePricePreferences({
2413
- limit: 9999
2414
- });
2415
- const { attributes: allAttributes } = useAttributes({
2416
- fields: "id,name,handle,description,ui_component,is_required,product_categories.*,possible_values.*"
2417
- });
2418
- const dynamicAttributeSchema = useMemo4(() => {
2419
- const attributeFields = {};
2420
- allAttributes?.forEach((attr) => {
2421
- switch (attr.ui_component) {
2422
- case "multivalue":
2423
- attributeFields[attr.handle] = z2.array(z2.string()).optional();
2424
- attributeFields[`${attr.handle}UseForVariants`] = z2.boolean().optional();
2425
- break;
2426
- case "select":
2427
- case "text":
2428
- case "text_area":
2429
- attributeFields[attr.handle] = z2.string().optional();
2430
- break;
2431
- case "unit":
2432
- attributeFields[attr.handle] = z2.union([z2.string(), z2.number()]).optional();
2433
- break;
2434
- case "toggle":
2435
- attributeFields[attr.handle] = z2.string().optional();
2436
- break;
2437
- }
2438
- });
2439
- return attributeFields;
2440
- }, [allAttributes]);
2441
- const extendedSchema = useMemo4(() => {
2442
- const baseSchema = ProductCreateSchema.innerType();
2443
- const extendedBaseSchema = baseSchema.extend({
2444
- ...dynamicAttributeSchema
2445
- });
2446
- return extendedBaseSchema.superRefine((data, ctx) => {
2447
- if (data.variants.every((v) => !v.should_create)) {
2448
- return ctx.addIssue({
2449
- code: z2.ZodIssueCode.custom,
2450
- path: ["variants"],
2451
- message: "invalid_length"
2452
- });
2453
- }
2454
- const skus = /* @__PURE__ */ new Set();
2455
- data.variants.forEach((v, index) => {
2456
- if (v.sku) {
2457
- if (skus.has(v.sku)) {
2458
- ctx.addIssue({
2459
- code: z2.ZodIssueCode.custom,
2460
- path: [`variants.${index}.sku`],
2461
- message: "SKU must be unique"
2462
- });
2463
- }
2464
- skus.add(v.sku);
2465
- }
2466
- });
2467
- });
2468
- }, [dynamicAttributeSchema]);
2469
- const dynamicDefaultValues = useMemo4(() => {
2470
- const defaults = {};
2471
- allAttributes?.forEach((attr) => {
2472
- switch (attr.ui_component) {
2473
- case "multivalue":
2474
- defaults[attr.handle] = [];
2475
- defaults[`${attr.handle}UseForVariants`] = false;
2476
- break;
2477
- case "select":
2478
- case "text":
2479
- case "unit":
2480
- case "text_area":
2481
- case "toggle":
2482
- defaults[attr.handle] = void 0;
2483
- break;
2484
- }
2485
- });
2486
- return defaults;
2487
- }, [allAttributes]);
2488
- const form = useForm({
2489
- defaultValues: {
2490
- ...PRODUCT_CREATE_FORM_DEFAULTS,
2491
- ...dynamicDefaultValues,
2492
- sales_channels: defaultChannel ? [{ id: defaultChannel.id, name: defaultChannel.name }] : []
2493
- },
2494
- resolver: zodResolver(extendedSchema),
2495
- mode: "onBlur"
2496
- });
2497
- const { mutateAsync, isPending } = useCreateProduct();
2498
- const attributesFormRef = useRef3(null);
2499
- const watchedVariants = useWatch3({
2500
- control: form.control,
2501
- name: "variants"
2502
- });
2503
- const watchedMedia = useWatch3({
2504
- control: form.control,
2505
- name: "media"
2506
- });
2507
- const showInventoryTab = useMemo4(
2508
- () => watchedVariants.some(
2509
- (v) => v.manage_inventory && v.inventory_kit
2510
- ),
2511
- [watchedVariants]
2512
- );
2513
- const handleSaveVariantMedia = useCallback2(
2514
- (variantIndex, media) => {
2515
- const currentVariants = form.getValues("variants") || [];
2516
- if (currentVariants[variantIndex]) {
2517
- const updatedVariants = [...currentVariants];
2518
- updatedVariants[variantIndex] = {
2519
- ...updatedVariants[variantIndex],
2520
- media
2521
- };
2522
- form.setValue("variants", updatedVariants, {
2523
- shouldDirty: true
2524
- });
2525
- }
2526
- },
2527
- [form]
2528
- );
2529
- useEffect5(() => {
2530
- if (tab === "variants" /* VARIANTS */) {
2531
- const currentOptions = form.getValues("options");
2532
- const currentVariants = form.getValues("variants");
2533
- if (currentOptions.length === 0 && currentVariants.length === 0) {
2534
- form.setValue(
2535
- "variants",
2536
- decorateVariantsWithDefaultValues([
2537
- {
2538
- title: "Default variant",
2539
- should_create: true,
2540
- variant_rank: 0,
2541
- options: {},
2542
- is_default: true
2543
- }
2544
- ])
2545
- );
2546
- }
2547
- }
2548
- }, [tab, form]);
2549
- useEffect5(() => {
2550
- if (onSaveVariantMediaRef) {
2551
- onSaveVariantMediaRef.current = handleSaveVariantMedia;
2552
- }
2553
- }, [handleSaveVariantMedia, onSaveVariantMediaRef]);
2554
- const handleSubmit = form.handleSubmit(async (values, e) => {
2555
- let isDraftSubmission = false;
2556
- if (e?.nativeEvent instanceof SubmitEvent) {
2557
- const submitter = e?.nativeEvent?.submitter;
2558
- isDraftSubmission = submitter.dataset.name === SAVE_DRAFT_BUTTON;
2559
- }
2560
- const media = values.media || [];
2561
- const { secondary_categories, ...rest } = values;
2562
- const secCatProductKey = Array.isArray(secondary_categories) && secondary_categories.length > 0 ? `sec-cat-${Date.now()}-${Math.random().toString(36).slice(2, 10)}` : void 0;
2563
- const adminAttributes = [];
2564
- const vendorAttributes = [];
2565
- const allFieldNames = Object.keys(values);
2566
- let dynamicAttributeFields = [];
2567
- if (allAttributes && allAttributes.length > 0) {
2568
- dynamicAttributeFields = allAttributes.map(
2569
- (attr) => attr.handle || attr.id
2570
- );
2571
- }
2572
- const vendorOptions = rest.options?.filter(
2573
- (opt) => opt.metadata?.author === "vendor" && opt.title && opt.values?.length > 0
2574
- ) || [];
2575
- const vendorOptionsForVariants = vendorOptions.filter(
2576
- (opt) => opt.useForVariants === true
2577
- );
2578
- const adminOptionsForVariants = (rest.options || []).filter(
2579
- (opt) => opt.useForVariants === true && opt.metadata?.author === "admin" && opt.attributeId && opt.title && opt.values?.length > 0
2580
- );
2581
- const requiredAttributeOptions = [];
2582
- allAttributes?.forEach((attr) => {
2583
- if (!attr.is_required) return;
2584
- const fieldHandle = attr.handle || attr.id;
2585
- const value = form.getValues(fieldHandle);
2586
- if (value === void 0 || value === null || value === "")
2587
- return;
2588
- if (attr.ui_component === "multivalue" && Array.isArray(value) && value.length > 0) {
2589
- const useForVariants = form.getValues(
2590
- `${fieldHandle}UseForVariants`
2591
- );
2592
- const selectedValues = value.map((valueId) => {
2593
- const possibleValue = attr.possible_values?.find(
2594
- (pv) => pv.id === valueId
2595
- );
2596
- return possibleValue ? possibleValue.value : null;
2597
- }).filter((item) => item !== null);
2598
- if (selectedValues.length > 0 && useForVariants === true) {
2599
- requiredAttributeOptions.push({
2600
- title: attr.name,
2601
- values: selectedValues,
2602
- metadata: { author: "admin" },
2603
- useForVariants: true
2604
- });
2605
- }
2606
- }
2607
- });
2608
- const allOptions = [
2609
- ...vendorOptionsForVariants,
2610
- ...requiredAttributeOptions,
2611
- ...adminOptionsForVariants
2612
- ];
2613
- dynamicAttributeFields.forEach((fieldName) => {
2614
- const value = form.getValues(fieldName);
2615
- if (value === void 0 || value === null || value === "")
2616
- return;
2617
- const attribute = allAttributes?.find(
2618
- (attr) => (attr.handle || attr.id) === fieldName
2619
- );
2620
- if (!attribute) return;
2621
- if (Array.isArray(value) && value.length > 0) {
2622
- const attrFieldHandle = attribute.handle || attribute.id;
2623
- const useForVariants = form.getValues(
2624
- `${attrFieldHandle}UseForVariants`
2625
- );
2626
- const vals = value.map((valueId) => {
2627
- const possibleValue = attribute.possible_values?.find(
2628
- (pv) => pv.id === valueId
2629
- );
2630
- return possibleValue ? possibleValue.value : valueId;
2631
- }).filter(
2632
- (item) => item !== null && item !== void 0
2633
- );
2634
- if (vals.length > 0) {
2635
- adminAttributes.push({
2636
- attribute_id: attribute.id,
2637
- values: vals.map((item) => String(item)),
2638
- use_for_variations: useForVariants === true
2639
- });
2640
- }
2641
- } else if (!Array.isArray(value)) {
2642
- let actualValue = value;
2643
- if (attribute.possible_values && typeof value === "string") {
2644
- const possibleValue = attribute.possible_values.find(
2645
- (pv) => pv.id === value
2646
- );
2647
- if (possibleValue) {
2648
- actualValue = possibleValue.value;
2649
- }
2650
- }
2651
- adminAttributes.push({
2652
- attribute_id: attribute.id,
2653
- values: [String(actualValue)],
2654
- use_for_variations: false
2655
- });
2656
- }
2657
- });
2658
- vendorOptions.forEach((option) => {
2659
- vendorAttributes.push({
2660
- name: option.title,
2661
- values: option.values.map((value) => String(value)),
2662
- use_for_variations: option.useForVariants === true,
2663
- ui_component: "multivalue"
2664
- });
2665
- });
2666
- const allFormOptions = rest.options || [];
2667
- allFormOptions.filter(
2668
- (opt) => opt.useForVariants === false && opt.metadata?.author === "admin" && opt.attributeId && opt.title && opt.values?.length > 0
2669
- ).forEach((option) => {
2670
- adminAttributes.push({
2671
- attribute_id: option.attributeId,
2672
- values: option.values.map(
2673
- (value) => String(value)
2674
- ),
2675
- use_for_variations: false
2676
- });
2677
- });
2678
- adminOptionsForVariants.forEach((option) => {
2679
- adminAttributes.push({
2680
- attribute_id: option.attributeId,
2681
- values: option.values.map((value) => String(value)),
2682
- use_for_variations: true
2683
- });
2684
- });
2685
- const { ...payload } = rest;
2686
- dynamicAttributeFields.forEach((fieldName) => {
2687
- delete payload[fieldName];
2688
- });
2689
- const useForVariantsFields = allFieldNames.filter(
2690
- (fieldName) => fieldName.endsWith("UseForVariants")
2691
- );
2692
- useForVariantsFields.forEach((fieldName) => {
2693
- delete payload[fieldName];
2694
- });
2695
- const finalPayload = { ...payload, media: void 0 };
2696
- let uploadedMedia = [];
2697
- try {
2698
- if (media.length) {
2699
- const thumbnailReq = media.filter(
2700
- (m) => m.isThumbnail && m.file
2701
- );
2702
- const otherMediaReq = media.filter(
2703
- (m) => !m.isThumbnail && m.file
2704
- );
2705
- const fileReqs = [];
2706
- if (thumbnailReq?.length) {
2707
- fileReqs.push(
2708
- uploadFilesQuery(thumbnailReq).then(
2709
- (r) => (Array.isArray(r?.files) ? r.files : []).map(
2710
- (f) => ({
2711
- ...f,
2712
- isThumbnail: true
2713
- })
2714
- )
2715
- )
2716
- );
2717
- }
2718
- if (otherMediaReq?.length) {
2719
- fileReqs.push(
2720
- uploadFilesQuery(otherMediaReq).then(
2721
- (r) => (Array.isArray(r?.files) ? r.files : []).map(
2722
- (f) => ({
2723
- ...f,
2724
- isThumbnail: false
2725
- })
2726
- )
2727
- )
2728
- );
2729
- }
2730
- uploadedMedia = (await Promise.all(fileReqs)).flat();
2731
- }
2732
- } catch (error) {
2733
- if (error instanceof Error) {
2734
- toast.error(error.message);
2735
- }
2736
- }
2737
- const blobToUploadedUrl = /* @__PURE__ */ new Map();
2738
- const allOriginalMedia = media;
2739
- if (uploadedMedia.length > 0) {
2740
- const thumbnailItems = allOriginalMedia.filter(
2741
- (m) => m.isThumbnail && m.file
2742
- );
2743
- const otherItems = allOriginalMedia.filter(
2744
- (m) => !m.isThumbnail && m.file
2745
- );
2746
- let thumbIdx = 0;
2747
- let otherIdx = 0;
2748
- for (const uploaded of uploadedMedia) {
2749
- if (uploaded.isThumbnail && thumbIdx < thumbnailItems.length) {
2750
- const blobUrl = thumbnailItems[thumbIdx].url;
2751
- if (blobUrl) {
2752
- blobToUploadedUrl.set(blobUrl, uploaded.url);
2753
- }
2754
- thumbIdx++;
2755
- }
2756
- if (!uploaded.isThumbnail && otherIdx < otherItems.length) {
2757
- const blobUrl = otherItems[otherIdx].url;
2758
- if (blobUrl) {
2759
- blobToUploadedUrl.set(blobUrl, uploaded.url);
2760
- }
2761
- otherIdx++;
2762
- }
2763
- }
2764
- }
2765
- const variantsToCreate = finalPayload.variants.filter(
2766
- (variant) => variant.should_create === true
2767
- );
2768
- const variantImageKeyByIndex = /* @__PURE__ */ new Map();
2769
- const variantsImages = [];
2770
- for (let i = 0; i < variantsToCreate.length; i++) {
2771
- const variant = variantsToCreate[i];
2772
- const variantMedia = variant.media || [];
2773
- if (!variantMedia.length) continue;
2774
- const resolvedUrls = variantMedia.map(
2775
- (m) => m.url ? blobToUploadedUrl.get(m.url) : void 0
2776
- ).filter((url) => !!url);
2777
- if (resolvedUrls.length === 0) continue;
2778
- const variantThumb = variantMedia.find(
2779
- (m) => m.isThumbnail
2780
- );
2781
- const resolvedThumbUrl = variantThumb?.url ? blobToUploadedUrl.get(variantThumb.url) : void 0;
2782
- const thumbnailUrl = resolvedThumbUrl || resolvedUrls[0];
2783
- const variantImageKey = `variant-${i}-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;
2784
- variantImageKeyByIndex.set(i, variantImageKey);
2785
- variantsImages.push({
2786
- variant_image_key: variantImageKey,
2787
- image_urls: resolvedUrls,
2788
- thumbnail_url: thumbnailUrl
2789
- });
2790
- }
2791
- const mappedVariants = variantsToCreate.map(
2792
- (variant, index) => {
2793
- const mappedOptions = {};
2794
- allOptions.forEach((option) => {
2795
- if (variant.options && variant.options[option.title]) {
2796
- mappedOptions[option.title] = variant.options[option.title];
2797
- } else {
2798
- const variantTitle = variant.title || "";
2799
- const optionValues = option.values || [];
2800
- const matchingValue = optionValues.find(
2801
- (value) => variantTitle.includes(value)
2802
- );
2803
- if (matchingValue) {
2804
- mappedOptions[option.title] = matchingValue;
2805
- } else if (optionValues.length > 0) {
2806
- mappedOptions[option.title] = optionValues[0];
2807
- }
2808
- }
2809
- });
2810
- const variantImageKey = variantImageKeyByIndex.get(index);
2811
- const {
2812
- media: _media,
2813
- stock_locations: _sl,
2814
- ...variantWithoutMedia
2815
- } = variant;
2816
- return {
2817
- ...variantWithoutMedia,
2818
- options: Object.keys(mappedOptions).length > 0 ? mappedOptions : {
2819
- [t("products.create.defaults.optionTitle")]: t(
2820
- "products.create.defaults.optionValue"
2821
- )
2822
- },
2823
- ...variantImageKey && {
2824
- metadata: { variant_image_key: variantImageKey }
2825
- }
2826
- };
2827
- }
2828
- );
2829
- const payloadToSend = {
2830
- ...finalPayload,
2831
- status: isDraftSubmission ? "draft" : "proposed",
2832
- images: uploadedMedia,
2833
- weight: parseInt(finalPayload.weight || "") || void 0,
2834
- length: parseInt(finalPayload.length || "") || void 0,
2835
- height: parseInt(finalPayload.height || "") || void 0,
2836
- width: parseInt(finalPayload.width || "") || void 0,
2837
- type_id: finalPayload.type_id || void 0,
2838
- tags: finalPayload.tags?.map((tag) => ({
2839
- id: tag
2840
- })) || [],
2841
- collection_id: finalPayload.collection_id || void 0,
2842
- shipping_profile_id: void 0,
2843
- enable_variants: void 0,
2844
- options: allOptions.length > 0 ? allOptions : [
2845
- {
2846
- title: t("products.create.defaults.optionTitle"),
2847
- values: [t("products.create.defaults.optionValue")]
2848
- }
2849
- ],
2850
- metadata: (() => {
2851
- const existing = finalPayload?.metadata ?? void 0;
2852
- if (!secCatProductKey) return existing;
2853
- return {
2854
- ...existing ?? {},
2855
- [SEC_CAT_PRODUCT_KEY]: secCatProductKey
2856
- };
2857
- })(),
2858
- additional_data: (() => {
2859
- const additionalData = {};
2860
- if (adminAttributes.length > 0) {
2861
- additionalData.admin_attributes = adminAttributes;
2862
- }
2863
- if (vendorAttributes.length > 0) {
2864
- additionalData.vendor_attributes = vendorAttributes;
2865
- }
2866
- if (Array.isArray(secondary_categories) && secondary_categories.length > 0 && secCatProductKey) {
2867
- additionalData.secondary_categories = [
2868
- {
2869
- sec_cat_product_key: secCatProductKey,
2870
- category_ids: secondary_categories
2871
- }
2872
- ];
2873
- }
2874
- if (variantsImages.length > 0) {
2875
- additionalData.variants_images = variantsImages;
2876
- }
2877
- return Object.keys(additionalData).length > 0 ? additionalData : void 0;
2878
- })(),
2879
- categories: finalPayload.categories.map((cat) => ({
2880
- id: cat
2881
- })),
2882
- variants: mappedVariants.map((variant) => {
2883
- const {
2884
- media: _m,
2885
- stock_locations: _sl,
2886
- ...variantWithoutMedia
2887
- } = variant;
2888
- return {
2889
- ...variantWithoutMedia,
2890
- sku: variant.sku === "" ? void 0 : variant.sku,
2891
- manage_inventory: true,
2892
- allow_backorder: false,
2893
- should_create: void 0,
2894
- is_default: void 0,
2895
- inventory_kit: void 0,
2896
- inventory: void 0,
2897
- prices: Object.keys(variant.prices || {}).map(
2898
- (key) => ({
2899
- currency_code: key,
2900
- amount: parseFloat(variant.prices?.[key])
2901
- })
2902
- )
2903
- };
2904
- })
2905
- };
2906
- const productData = await mutateAsync(payloadToSend, {
2907
- onError: (error) => {
2908
- toast.error(error.message);
2909
- }
2910
- });
2911
- toast.success(t("products.create.successToast", { title: productData.product.title }));
2912
- handleSuccess(`../${productData.product.id}`);
2913
- });
2914
- const onNext = async (currentTab) => {
2915
- let fieldsToValidate = [];
2916
- let shouldProceed = true;
2917
- switch (currentTab) {
2918
- case "details" /* DETAILS */:
2919
- fieldsToValidate = ["title", "handle"];
2920
- break;
2921
- case "organize" /* ORGANIZE */:
2922
- fieldsToValidate = ["categories"];
2923
- break;
2924
- case "attributes" /* ATTRIBUTES */:
2925
- if (attributesFormRef.current) {
2926
- shouldProceed = await attributesFormRef.current.validateAttributes();
2927
- }
2928
- break;
2929
- case "variants" /* VARIANTS */:
2930
- fieldsToValidate = ["variants", "options"];
2931
- break;
2932
- case "inventory" /* INVENTORY */:
2933
- break;
2934
- }
2935
- if (fieldsToValidate.length > 0) {
2936
- const valid = await form.trigger(fieldsToValidate);
2937
- if (!valid) return;
2938
- }
2939
- if (!shouldProceed) return;
2940
- let nextTab;
2941
- if (currentTab === "details" /* DETAILS */) {
2942
- nextTab = "organize" /* ORGANIZE */;
2943
- } else if (currentTab === "organize" /* ORGANIZE */) {
2944
- nextTab = "attributes" /* ATTRIBUTES */;
2945
- } else if (currentTab === "attributes" /* ATTRIBUTES */) {
2946
- nextTab = "variants" /* VARIANTS */;
2947
- } else if (currentTab === "variants" /* VARIANTS */) {
2948
- nextTab = "inventory" /* INVENTORY */;
2949
- } else {
2950
- return;
2951
- }
2952
- const currentTabIndex = TAB_ORDER.indexOf(currentTab);
2953
- const currentMaxIndex = TAB_ORDER.indexOf(maxReachedTab);
2954
- if (currentTabIndex >= currentMaxIndex) {
2955
- setMaxReachedTab(TAB_ORDER[currentMaxIndex + 1]);
2956
- }
2957
- setTab(nextTab);
2958
- };
2959
- useEffect5(() => {
2960
- const currentIndex = TAB_ORDER.indexOf(tab);
2961
- const maxReachedIndex = TAB_ORDER.indexOf(maxReachedTab);
2962
- const currentState = {
2963
- ["details" /* DETAILS */]: "not-started",
2964
- ["organize" /* ORGANIZE */]: "not-started",
2965
- ["attributes" /* ATTRIBUTES */]: "not-started",
2966
- ["variants" /* VARIANTS */]: "not-started",
2967
- ["inventory" /* INVENTORY */]: "not-started"
2968
- };
2969
- TAB_ORDER.forEach((tabItem, index) => {
2970
- if (index < currentIndex && index <= maxReachedIndex) {
2971
- currentState[tabItem] = "completed";
2972
- } else if (index === currentIndex) {
2973
- currentState[tabItem] = "in-progress";
2974
- } else if (index > currentIndex && index <= maxReachedIndex) {
2975
- currentState[tabItem] = "completed";
2976
- } else {
2977
- currentState[tabItem] = "not-started";
2978
- }
2979
- });
2980
- setTabState(currentState);
2981
- }, [tab, maxReachedTab]);
2982
- return /* @__PURE__ */ jsx14(TabbedFormContext.Provider, { value: form, children: /* @__PURE__ */ jsx14(RouteFocusModal.Form, { form, children: /* @__PURE__ */ jsxs12(
2983
- KeyboundForm,
2984
- {
2985
- onKeyDown: (e) => {
2986
- if (e.key === "Enter") {
2987
- if (e.target instanceof HTMLTextAreaElement && !(e.metaKey || e.ctrlKey)) {
2988
- return;
2989
- }
2990
- e.preventDefault();
2991
- if (e.metaKey || e.ctrlKey) {
2992
- if (tab !== "variants" /* VARIANTS */) {
2993
- e.stopPropagation();
2994
- onNext(tab);
2995
- return;
2996
- }
2997
- handleSubmit();
2998
- }
2999
- }
3000
- },
3001
- onSubmit: handleSubmit,
3002
- className: "flex h-full flex-col",
3003
- children: [
3004
- /* @__PURE__ */ jsxs12(
3005
- ProgressTabs,
3006
- {
3007
- value: tab,
3008
- onValueChange: async (newTab) => {
3009
- const newTabValue = newTab;
3010
- const currentIndex = TAB_ORDER.indexOf(tab);
3011
- const newIndex = TAB_ORDER.indexOf(newTabValue);
3012
- const maxReachedIndex = TAB_ORDER.indexOf(maxReachedTab);
3013
- const movingForward = isMovingForward(
3014
- tab,
3015
- newTabValue
3016
- );
3017
- if (movingForward) {
3018
- if (newIndex > maxReachedIndex + 1) return;
3019
- let fieldsToValidate = [];
3020
- switch (tab) {
3021
- case "details" /* DETAILS */:
3022
- fieldsToValidate = ["title", "handle"];
3023
- break;
3024
- case "organize" /* ORGANIZE */:
3025
- fieldsToValidate = ["categories"];
3026
- break;
3027
- case "attributes" /* ATTRIBUTES */:
3028
- fieldsToValidate = [];
3029
- break;
3030
- case "variants" /* VARIANTS */:
3031
- fieldsToValidate = ["variants", "options"];
3032
- break;
3033
- case "inventory" /* INVENTORY */:
3034
- break;
3035
- }
3036
- if (fieldsToValidate.length > 0) {
3037
- const valid = await form.trigger(fieldsToValidate);
3038
- if (!valid) return;
3039
- } else if (tab === "attributes" /* ATTRIBUTES */) {
3040
- if (attributesFormRef.current) {
3041
- const valid = await attributesFormRef.current.validateAttributes();
3042
- if (!valid) return;
3043
- }
3044
- }
3045
- if (currentIndex >= maxReachedIndex) {
3046
- setMaxReachedTab(
3047
- TAB_ORDER[currentIndex + 1]
3048
- );
3049
- }
3050
- }
3051
- setTab(newTabValue);
3052
- },
3053
- className: "flex h-full flex-col overflow-hidden",
3054
- children: [
3055
- /* @__PURE__ */ jsx14(RouteFocusModal.Header, { children: /* @__PURE__ */ jsx14("div", { className: "-my-2 w-full border-l", children: /* @__PURE__ */ jsxs12(ProgressTabs.List, { className: "justify-start-start flex w-full items-center", children: [
3056
- /* @__PURE__ */ jsx14(
3057
- ProgressTabs.Trigger,
3058
- {
3059
- status: tabState["details" /* DETAILS */],
3060
- value: "details" /* DETAILS */,
3061
- className: "max-w-[200px] truncate",
3062
- children: t("products.create.tabs.details")
3063
- }
3064
- ),
3065
- /* @__PURE__ */ jsx14(
3066
- ProgressTabs.Trigger,
3067
- {
3068
- status: tabState["organize" /* ORGANIZE */],
3069
- value: "organize" /* ORGANIZE */,
3070
- className: "max-w-[200px] truncate",
3071
- children: t("products.create.tabs.organize")
3072
- }
3073
- ),
3074
- /* @__PURE__ */ jsx14(
3075
- ProgressTabs.Trigger,
3076
- {
3077
- status: tabState["attributes" /* ATTRIBUTES */],
3078
- value: "attributes" /* ATTRIBUTES */,
3079
- className: "max-w-[200px] truncate",
3080
- children: t("products.create.tabs.attributes")
3081
- }
3082
- ),
3083
- /* @__PURE__ */ jsx14(
3084
- ProgressTabs.Trigger,
3085
- {
3086
- status: tabState["variants" /* VARIANTS */],
3087
- value: "variants" /* VARIANTS */,
3088
- className: "max-w-[200px] truncate",
3089
- children: t("products.create.tabs.variants")
3090
- }
3091
- ),
3092
- showInventoryTab && /* @__PURE__ */ jsx14(
3093
- ProgressTabs.Trigger,
3094
- {
3095
- status: tabState["inventory" /* INVENTORY */],
3096
- value: "inventory" /* INVENTORY */,
3097
- className: "max-w-[200px] truncate",
3098
- children: t("products.create.tabs.inventory")
3099
- }
3100
- )
3101
- ] }) }) }),
3102
- /* @__PURE__ */ jsxs12(RouteFocusModal.Body, { className: "size-full overflow-hidden", children: [
3103
- /* @__PURE__ */ jsx14(
3104
- ProgressTabs.Content,
3105
- {
3106
- className: "size-full overflow-y-auto",
3107
- value: "details" /* DETAILS */,
3108
- children: /* @__PURE__ */ jsx14(ProductCreateDetailsForm, { form })
3109
- }
3110
- ),
3111
- /* @__PURE__ */ jsx14(
3112
- ProgressTabs.Content,
3113
- {
3114
- className: "size-full overflow-y-auto",
3115
- value: "organize" /* ORGANIZE */,
3116
- children: /* @__PURE__ */ jsx14(
3117
- ProductCreateOrganizeForm,
3118
- {
3119
- form
3120
- }
3121
- )
3122
- }
3123
- ),
3124
- /* @__PURE__ */ jsx14(
3125
- ProgressTabs.Content,
3126
- {
3127
- className: "size-full overflow-y-auto",
3128
- value: "attributes" /* ATTRIBUTES */,
3129
- children: /* @__PURE__ */ jsx14(
3130
- ProductCreateAttributesForm,
3131
- {
3132
- form,
3133
- ref: attributesFormRef
3134
- }
3135
- )
3136
- }
3137
- ),
3138
- /* @__PURE__ */ jsx14(
3139
- ProgressTabs.Content,
3140
- {
3141
- className: "size-full overflow-y-auto",
3142
- value: "variants" /* VARIANTS */,
3143
- children: /* @__PURE__ */ jsx14(
3144
- ProductCreateVariantsForm,
3145
- {
3146
- form,
3147
- store,
3148
- regions,
3149
- pricePreferences,
3150
- onOpenMediaModal,
3151
- productMedia: watchedMedia || []
3152
- }
3153
- )
3154
- }
3155
- ),
3156
- showInventoryTab && /* @__PURE__ */ jsx14(
3157
- ProgressTabs.Content,
3158
- {
3159
- className: "size-full overflow-y-auto",
3160
- value: "inventory" /* INVENTORY */,
3161
- children: /* @__PURE__ */ jsx14(
3162
- ProductCreateInventoryKitForm,
3163
- {
3164
- form
3165
- }
3166
- )
3167
- }
3168
- )
3169
- ] })
3170
- ]
3171
- }
3172
- ),
3173
- /* @__PURE__ */ jsx14(RouteFocusModal.Footer, { children: /* @__PURE__ */ jsxs12("div", { className: "flex items-center justify-end gap-x-2", children: [
3174
- /* @__PURE__ */ jsx14(RouteFocusModal.Close, { asChild: true, children: /* @__PURE__ */ jsx14(Button4, { variant: "secondary", size: "small", children: t("actions.cancel") }) }),
3175
- /* @__PURE__ */ jsx14(
3176
- Button4,
3177
- {
3178
- "data-name": SAVE_DRAFT_BUTTON,
3179
- size: "small",
3180
- type: "submit",
3181
- onClick: () => {
3182
- if (form.getValues("categories").length === 0 && form.getValues("title")) {
3183
- onNext("details" /* DETAILS */);
3184
- return;
3185
- }
3186
- handleSubmit();
3187
- },
3188
- isLoading: isPending,
3189
- variant: "secondary",
3190
- className: "whitespace-nowrap",
3191
- children: t("actions.saveAsDraft")
3192
- }
3193
- ),
3194
- /* @__PURE__ */ jsx14(
3195
- PrimaryButton,
3196
- {
3197
- tab,
3198
- next: onNext,
3199
- isLoading: isPending,
3200
- showInventoryTab
3201
- }
3202
- )
3203
- ] }) })
3204
- ]
3205
- }
3206
- ) }) });
3207
- };
3208
- var PrimaryButton = ({
3209
- tab,
3210
- next,
3211
- isLoading,
3212
- showInventoryTab
3213
- }) => {
3214
- const { t } = useTranslation12();
3215
- if (tab === "variants" /* VARIANTS */ && !showInventoryTab || tab === "inventory" /* INVENTORY */ && showInventoryTab) {
3216
- return /* @__PURE__ */ jsx14(
3217
- Button4,
3218
- {
3219
- "data-name": "publish-button",
3220
- type: "submit",
3221
- variant: "primary",
3222
- size: "small",
3223
- isLoading,
3224
- children: t("actions.publish")
3225
- },
3226
- "submit-button"
3227
- );
3228
- }
3229
- return /* @__PURE__ */ jsx14(
3230
- Button4,
3231
- {
3232
- type: "button",
3233
- variant: "primary",
3234
- size: "small",
3235
- onClick: () => next(tab),
3236
- children: t("actions.continue")
3237
- },
3238
- "next-button"
3239
- );
3240
- };
3241
-
3242
- // src/pages/products/create/variant-media-view/variant-media-view.tsx
3243
- import { useRef as useRef4, useState as useState9 } from "react";
3244
- import { Button as Button6 } from "@medusajs/ui";
3245
- import { useTranslation as useTranslation15 } from "react-i18next";
3246
-
3247
- // src/pages/products/create/edit-variant-media-form/edit-variant-media-form.tsx
3248
- import { Fragment as Fragment4, useCallback as useCallback3, useEffect as useEffect6, useMemo as useMemo5, useState as useState7 } from "react";
3249
- import { ThumbnailBadge as ThumbnailBadge2 } from "@medusajs/icons";
3250
- import { Checkbox as Checkbox2, clx, CommandBar, Tooltip as Tooltip3 } from "@medusajs/ui";
3251
- import { useTranslation as useTranslation13 } from "react-i18next";
3252
- import { jsx as jsx15, jsxs as jsxs13 } from "react/jsx-runtime";
3253
- var EditVariantMediaForm = ({
3254
- variantIndex,
3255
- onSaveMedia,
3256
- onClose,
3257
- saveRef,
3258
- initialMedia = [],
3259
- productMedia = []
3260
- }) => {
3261
- const { t } = useTranslation13();
3262
- const [selectedUrls, setSelectedUrls] = useState7(
3263
- () => new Set(initialMedia.filter((m) => m.url).map((m) => m.url))
3264
- );
3265
- const [thumbnailUrl, setThumbnailUrl] = useState7(
3266
- () => {
3267
- const thumb = initialMedia.find((m) => m.isThumbnail);
3268
- return thumb?.url ?? null;
3269
- }
3270
- );
3271
- const [checkedUrls, setCheckedUrls] = useState7({});
3272
- const availableMedia = useMemo5(
3273
- () => productMedia.filter(
3274
- (m) => !!m.url
3275
- ),
3276
- [productMedia]
3277
- );
3278
- const selectedImages = useMemo5(
3279
- () => availableMedia.filter((m) => selectedUrls.has(m.url)),
3280
- [availableMedia, selectedUrls]
3281
- );
3282
- const unselectedImages = useMemo5(
3283
- () => availableMedia.filter((m) => !selectedUrls.has(m.url)),
3284
- [availableMedia, selectedUrls]
3285
- );
3286
- const handleSelectImage = useCallback3((url) => {
3287
- setSelectedUrls((prev) => {
3288
- const next = new Set(prev);
3289
- next.add(url);
3290
- return next;
3291
- });
3292
- }, []);
3293
- const handleDeselectImage = useCallback3(
3294
- (url) => {
3295
- setSelectedUrls((prev) => {
3296
- const next = new Set(prev);
3297
- next.delete(url);
3298
- return next;
3299
- });
3300
- if (thumbnailUrl === url) {
3301
- setThumbnailUrl(null);
3302
- }
3303
- const { [url]: _, ...restChecked } = checkedUrls;
3304
- setCheckedUrls(restChecked);
3305
- },
3306
- [thumbnailUrl, checkedUrls]
3307
- );
3308
- const handleCheckedChange = useCallback3(
3309
- (url, value) => {
3310
- if (!value) {
3311
- const { [url]: _, ...rest } = checkedUrls;
3312
- setCheckedUrls(rest);
3313
- return;
3314
- }
3315
- setCheckedUrls((prev) => ({ ...prev, [url]: true }));
3316
- },
3317
- [checkedUrls]
3318
- );
3319
- const handlePromoteToThumbnail = useCallback3(() => {
3320
- const urls = Object.keys(checkedUrls);
3321
- if (urls.length !== 1) {
3322
- return;
3323
- }
3324
- setThumbnailUrl(urls[0]);
3325
- setCheckedUrls({});
3326
- }, [checkedUrls]);
3327
- const getEffectiveThumbnailUrl = useCallback3(() => {
3328
- if (selectedUrls.size === 0) {
3329
- return null;
3330
- }
3331
- if (thumbnailUrl && selectedUrls.has(thumbnailUrl)) {
3332
- return thumbnailUrl;
3333
- }
3334
- return [...selectedUrls][0];
3335
- }, [selectedUrls, thumbnailUrl]);
3336
- const handleSave = useCallback3(() => {
3337
- const effectiveThumb = getEffectiveThumbnailUrl();
3338
- const media = [...selectedUrls].map((url) => ({
3339
- url,
3340
- isThumbnail: url === effectiveThumb
3341
- }));
3342
- onSaveMedia?.(variantIndex, media);
3343
- onClose?.();
3344
- }, [
3345
- getEffectiveThumbnailUrl,
3346
- selectedUrls,
3347
- onSaveMedia,
3348
- variantIndex,
3349
- onClose
3350
- ]);
3351
- useEffect6(() => {
3352
- saveRef.current = handleSave;
3353
- }, [handleSave, saveRef]);
3354
- const checkedCount = Object.keys(checkedUrls).length;
3355
- return /* @__PURE__ */ jsxs13("div", { className: "flex size-full flex-col overflow-hidden", children: [
3356
- /* @__PURE__ */ jsxs13("div", { className: "flex size-full", children: [
3357
- /* @__PURE__ */ jsx15("div", { className: "flex-1 overflow-auto bg-ui-bg-subtle p-6", children: /* @__PURE__ */ jsx15("div", { className: "flex flex-wrap content-start gap-6", children: selectedImages.map((img) => {
3358
- const effectiveThumb = getEffectiveThumbnailUrl();
3359
- const isThumb = img.url === effectiveThumb;
3360
- return /* @__PURE__ */ jsx15(
3361
- SelectedImageCard,
3362
- {
3363
- image: img,
3364
- isThumbnail: isThumb,
3365
- checked: !!checkedUrls[img.url],
3366
- onCheckedChange: (val) => handleCheckedChange(img.url, val)
3367
- },
3368
- img.url
3369
- );
3370
- }) }) }),
3371
- /* @__PURE__ */ jsx15("div", { className: "w-px shrink-0 bg-ui-border-base" }),
3372
- /* @__PURE__ */ jsxs13("div", { className: "flex w-[318px] shrink-0 flex-col", children: [
3373
- /* @__PURE__ */ jsxs13("div", { className: "p-4", children: [
3374
- /* @__PURE__ */ jsx15("p", { className: "txt-compact-small-plus text-ui-fg-base", children: t("products.media.selectImages") }),
3375
- /* @__PURE__ */ jsx15("p", { className: "txt-small mt-1 text-ui-fg-subtle", children: t("products.media.selectImagesHint") })
3376
- ] }),
3377
- /* @__PURE__ */ jsx15("div", { className: "h-px bg-ui-border-base" }),
3378
- /* @__PURE__ */ jsx15("div", { className: "flex-1 overflow-auto p-4", children: /* @__PURE__ */ jsx15("div", { className: "grid grid-cols-2 gap-4", children: unselectedImages.map((img) => /* @__PURE__ */ jsx15(
3379
- UnselectedImageCard,
3380
- {
3381
- image: img,
3382
- onSelect: () => handleSelectImage(img.url)
3383
- },
3384
- img.url
3385
- )) }) })
3386
- ] })
3387
- ] }),
3388
- /* @__PURE__ */ jsx15(CommandBar, { open: !!checkedCount, children: /* @__PURE__ */ jsxs13(CommandBar.Bar, { children: [
3389
- /* @__PURE__ */ jsx15(CommandBar.Value, { children: t("general.countSelected", {
3390
- count: checkedCount
3391
- }) }),
3392
- /* @__PURE__ */ jsx15(CommandBar.Seperator, {}),
3393
- checkedCount === 1 && /* @__PURE__ */ jsxs13(Fragment4, { children: [
3394
- /* @__PURE__ */ jsx15(
3395
- CommandBar.Command,
3396
- {
3397
- action: handlePromoteToThumbnail,
3398
- label: t("products.media.makeThumbnail"),
3399
- shortcut: "t"
3400
- }
3401
- ),
3402
- /* @__PURE__ */ jsx15(CommandBar.Seperator, {})
3403
- ] }),
3404
- /* @__PURE__ */ jsx15(
3405
- CommandBar.Command,
3406
- {
3407
- action: () => {
3408
- Object.keys(checkedUrls).forEach(
3409
- (url) => handleDeselectImage(url)
3410
- );
3411
- setCheckedUrls({});
3412
- },
3413
- label: t("actions.remove"),
3414
- shortcut: "r"
3415
- }
3416
- )
3417
- ] }) })
3418
- ] });
3419
- };
3420
- var SelectedImageCard = ({
3421
- image,
3422
- isThumbnail,
3423
- checked,
3424
- onCheckedChange
3425
- }) => {
3426
- const { t } = useTranslation13();
3427
- return /* @__PURE__ */ jsxs13(
3428
- "div",
3429
- {
3430
- className: clx(
3431
- "group relative size-[156px] shrink-0 overflow-hidden rounded-lg",
3432
- "shadow-elevation-card-rest"
3433
- ),
3434
- children: [
3435
- isThumbnail && /* @__PURE__ */ jsx15("div", { className: "absolute left-2 top-2 z-[1]", children: /* @__PURE__ */ jsx15(
3436
- Tooltip3,
3437
- {
3438
- content: t("products.media.thumbnailTooltip"),
3439
- children: /* @__PURE__ */ jsx15(ThumbnailBadge2, {})
3440
- }
3441
- ) }),
3442
- /* @__PURE__ */ jsx15(
3443
- "div",
3444
- {
3445
- className: clx(
3446
- "absolute right-2 top-2 z-[1] opacity-0 transition-opacity",
3447
- "group-hover:opacity-100",
3448
- { "opacity-100": checked }
3449
- ),
3450
- children: /* @__PURE__ */ jsx15(
3451
- Checkbox2,
3452
- {
3453
- checked,
3454
- onCheckedChange,
3455
- "aria-label": t("actions.select")
3456
- }
3457
- )
3458
- }
3459
- ),
3460
- /* @__PURE__ */ jsx15(
3461
- "img",
3462
- {
3463
- src: image.url,
3464
- alt: "",
3465
- className: "size-full object-cover object-center"
3466
- }
3467
- )
3468
- ]
3469
- }
3470
- );
3471
- };
3472
- var UnselectedImageCard = ({
3473
- image,
3474
- onSelect
3475
- }) => {
3476
- const { t } = useTranslation13();
3477
- return /* @__PURE__ */ jsx15(
3478
- "button",
3479
- {
3480
- type: "button",
3481
- onClick: onSelect,
3482
- className: clx(
3483
- "aspect-square w-full overflow-hidden rounded-lg",
3484
- "shadow-elevation-card-rest transition-shadow",
3485
- "hover:shadow-elevation-card-hover",
3486
- "outline-none focus-visible:shadow-borders-focus"
3487
- ),
3488
- "aria-label": t("products.media.selectImages"),
3489
- children: /* @__PURE__ */ jsx15(
3490
- "img",
3491
- {
3492
- src: image.url,
3493
- alt: "",
3494
- className: "size-full object-cover object-center"
3495
- }
3496
- )
3497
- }
3498
- );
3499
- };
3500
-
3501
- // src/pages/products/create/variant-media-view/components/variant-media-gallery/variant-media-gallery.tsx
3502
- import { useCallback as useCallback4, useEffect as useEffect7, useState as useState8 } from "react";
3503
- import {
3504
- ThumbnailBadge as ThumbnailBadge3,
3505
- TriangleLeftMini,
3506
- TriangleRightMini
3507
- } from "@medusajs/icons";
3508
- import { Button as Button5, clx as clx2, IconButton as IconButton3, Text as Text4, Tooltip as Tooltip4 } from "@medusajs/ui";
3509
- import { useTranslation as useTranslation14 } from "react-i18next";
3510
-
3511
- // src/pages/products/create/variant-media-view/variant-media-view-context.tsx
3512
- import { createContext } from "react";
3513
- var VariantMediaViewContext = createContext(null);
3514
-
3515
- // src/pages/products/create/variant-media-view/components/variant-media-gallery/variant-media-gallery.tsx
3516
- import { Fragment as Fragment5, jsx as jsx16, jsxs as jsxs14 } from "react/jsx-runtime";
3517
- var VariantMediaGallery = ({
3518
- goToEdit,
3519
- variantMedia = []
3520
- }) => {
3521
- const [curr, setCurr] = useState8(0);
3522
- const { t } = useTranslation14();
3523
- const media = (variantMedia || []).map(
3524
- (m, idx) => ({
3525
- ...m,
3526
- id: m.id || `variant-${idx}-${m.url}`
3527
- })
3528
- );
3529
- const next = useCallback4(() => {
3530
- setCurr((prev2) => (prev2 + 1) % media.length);
3531
- }, [media.length]);
3532
- const prev = useCallback4(() => {
3533
- setCurr((prev2) => (prev2 - 1 + media.length) % media.length);
3534
- }, [media.length]);
3535
- const goTo = useCallback4(
3536
- (index) => {
3537
- if (index < 0 || index >= media.length) return;
3538
- setCurr(index);
3539
- },
3540
- [media.length]
3541
- );
3542
- useEffect7(() => {
3543
- const handleKeyDown = (e) => {
3544
- if (e.key === "ArrowRight") next();
3545
- else if (e.key === "ArrowLeft") prev();
3546
- };
3547
- document.addEventListener("keydown", handleKeyDown);
3548
- return () => document.removeEventListener("keydown", handleKeyDown);
3549
- }, [next, prev]);
3550
- const noMedia = !media.length;
3551
- return /* @__PURE__ */ jsx16(VariantMediaViewContext.Consumer, { children: () => /* @__PURE__ */ jsx16("div", { className: "flex size-full flex-col bg-ui-bg-subtle", children: noMedia ? /* @__PURE__ */ jsxs14("div", { className: "flex size-full flex-col items-center justify-center gap-y-4 bg-ui-bg-subtle pb-8 pt-6", children: [
3552
- /* @__PURE__ */ jsxs14("div", { className: "flex flex-col items-center", children: [
3553
- /* @__PURE__ */ jsx16(Text4, { size: "small", leading: "compact", weight: "plus", className: "text-ui-fg-subtle", children: t("products.media.emptyState.header", "No media") }),
3554
- /* @__PURE__ */ jsx16(Text4, { size: "small", className: "text-ui-fg-muted", children: t("products.media.emptyState.description", "No images assigned to this variant.") })
3555
- ] }),
3556
- /* @__PURE__ */ jsx16(Button5, { size: "small", variant: "secondary", onClick: goToEdit, children: t("products.media.emptyState.action", "Add images") })
3557
- ] }) : /* @__PURE__ */ jsxs14(Fragment5, { children: [
3558
- /* @__PURE__ */ jsx16("div", { className: "relative size-full overflow-hidden bg-ui-bg-subtle", children: /* @__PURE__ */ jsx16("div", { className: "flex size-full items-center justify-center p-6", children: /* @__PURE__ */ jsxs14("div", { className: "relative inline-block max-h-full max-w-full", children: [
3559
- media[curr]?.isThumbnail && /* @__PURE__ */ jsx16("div", { className: "absolute left-2 top-2", children: /* @__PURE__ */ jsx16(Tooltip4, { content: t("products.media.thumbnailTooltip"), children: /* @__PURE__ */ jsx16(ThumbnailBadge3, {}) }) }),
3560
- /* @__PURE__ */ jsx16(
3561
- "img",
3562
- {
3563
- src: media[curr]?.url,
3564
- alt: "",
3565
- className: "object-fit max-h-[calc(100vh-200px)] w-auto rounded-xl object-contain shadow-elevation-card-rest"
3566
- }
3567
- )
3568
- ] }) }) }),
3569
- media.length > 1 && /* @__PURE__ */ jsxs14("div", { className: "flex shrink-0 items-center justify-center gap-x-2 border-t p-3", children: [
3570
- /* @__PURE__ */ jsx16(IconButton3, { size: "small", variant: "transparent", className: "text-ui-fg-muted", type: "button", onClick: prev, children: /* @__PURE__ */ jsx16(TriangleLeftMini, {}) }),
3571
- /* @__PURE__ */ jsx16("div", { className: "flex items-center gap-x-2", children: media.slice(0, 8).map((item, _idx) => {
3572
- const isCurrentImage = item.id === media[curr]?.id;
3573
- const originalIndex = media.findIndex((i) => i.id === item.id);
3574
- return /* @__PURE__ */ jsx16(
3575
- "button",
3576
- {
3577
- type: "button",
3578
- onClick: () => goTo(originalIndex),
3579
- className: clx2("size-7 overflow-hidden rounded-[4px] outline-none transition-fg", {
3580
- "shadow-borders-focus": isCurrentImage
3581
- }),
3582
- children: /* @__PURE__ */ jsx16("img", { src: item.url, alt: "", className: "size-full object-cover" })
3583
- },
3584
- item.id
3585
- );
3586
- }) }),
3587
- /* @__PURE__ */ jsx16(IconButton3, { size: "small", variant: "transparent", className: "text-ui-fg-muted", type: "button", onClick: next, children: /* @__PURE__ */ jsx16(TriangleRightMini, {}) })
3588
- ] })
3589
- ] }) }) });
3590
- };
3591
-
3592
- // src/pages/products/create/variant-media-view/variant-media-view.tsx
3593
- import { jsx as jsx17, jsxs as jsxs15 } from "react/jsx-runtime";
3594
- var getView = (currentView) => {
3595
- if (currentView === "edit" /* EDIT */) return "edit" /* EDIT */;
3596
- return "gallery" /* GALLERY */;
3597
- };
3598
- var VariantMediaView = ({
3599
- variantIndex,
3600
- variantTitle,
3601
- onClose,
3602
- onSaveMedia,
3603
- initialMedia,
3604
- productMedia
3605
- }) => {
3606
- const [currentView, setCurrentView] = useState9("edit" /* EDIT */);
3607
- const view = getView(currentView);
3608
- const { t } = useTranslation15();
3609
- const saveRef = useRef4(null);
3610
- const handleGoToView = (v) => () => setCurrentView(v);
3611
- const contextValue = {
3612
- goToGallery: handleGoToView("gallery" /* GALLERY */),
3613
- goToEdit: handleGoToView("edit" /* EDIT */),
3614
- onCancel: onClose,
3615
- onClose
3616
- };
3617
- const handleFooterSave = () => {
3618
- saveRef.current?.();
3619
- };
3620
- return /* @__PURE__ */ jsx17(VariantMediaViewContext.Provider, { value: contextValue, children: /* @__PURE__ */ jsxs15(StackedFocusModal.Content, { children: [
3621
- /* @__PURE__ */ jsx17(StackedFocusModal.Header, { children: view === "edit" /* EDIT */ ? /* @__PURE__ */ jsx17(Button6, { variant: "secondary", size: "small", onClick: contextValue.goToGallery, children: t("products.media.galleryLabel", "Gallery") }) : /* @__PURE__ */ jsx17(Button6, { variant: "secondary", size: "small", onClick: contextValue.goToEdit, children: t("products.media.editLabel", "Edit") }) }),
3622
- /* @__PURE__ */ jsxs15(StackedFocusModal.Body, { className: "flex flex-col overflow-hidden", children: [
3623
- view === "gallery" /* GALLERY */ && /* @__PURE__ */ jsx17(VariantMediaGallery, { goToEdit: contextValue.goToEdit, variantMedia: initialMedia }),
3624
- view === "edit" /* EDIT */ && /* @__PURE__ */ jsx17(
3625
- EditVariantMediaForm,
3626
- {
3627
- variantIndex,
3628
- variantTitle,
3629
- onSaveMedia,
3630
- onClose,
3631
- saveRef,
3632
- initialMedia,
3633
- productMedia
3634
- }
3635
- )
3636
- ] }),
3637
- view === "edit" /* EDIT */ && /* @__PURE__ */ jsx17(StackedFocusModal.Footer, { children: /* @__PURE__ */ jsxs15("div", { className: "flex justify-end gap-x-2", children: [
3638
- /* @__PURE__ */ jsx17(Button6, { variant: "secondary", size: "small", onClick: onClose, children: t("actions.cancel") }),
3639
- /* @__PURE__ */ jsx17(Button6, { size: "small", onClick: handleFooterSave, children: t("actions.save") })
3640
- ] }) })
3641
- ] }) });
3642
- };
3643
-
3644
- // src/pages/products/create/product-create-page.tsx
3645
- import { Fragment as Fragment6, jsx as jsx18, jsxs as jsxs16 } from "react/jsx-runtime";
3646
- var ProductCreateFormWithModal = ({
3647
- defaultChannel,
3648
- store
3649
- }) => {
3650
- const { setIsOpen } = useStackedModal();
3651
- const [selectedVariantIndex, setSelectedVariantIndex] = useState10(null);
3652
- const [selectedVariantTitle, setSelectedVariantTitle] = useState10(void 0);
3653
- const [selectedVariantMedia, setSelectedVariantMedia] = useState10(void 0);
3654
- const [productMedia, setProductMedia] = useState10([]);
3655
- const saveVariantMediaRef = useRef5(null);
3656
- const handleOpenMediaModal = useCallback5(
3657
- (variantIndex, variantTitle, initialMedia, currentProductMedia) => {
3658
- setSelectedVariantIndex(variantIndex);
3659
- setSelectedVariantTitle(variantTitle);
3660
- setSelectedVariantMedia(initialMedia);
3661
- setProductMedia(currentProductMedia || []);
3662
- setIsOpen("variant-media-modal", true);
3663
- },
3664
- [setIsOpen]
3665
- );
3666
- const handleCloseModal = () => {
3667
- setIsOpen("variant-media-modal", false);
3668
- setSelectedVariantIndex(null);
3669
- setSelectedVariantTitle(void 0);
3670
- setSelectedVariantMedia(void 0);
3671
- setProductMedia([]);
3672
- };
3673
- const handleSaveMedia = useCallback5((variantIndex, media) => {
3674
- if (saveVariantMediaRef.current) {
3675
- saveVariantMediaRef.current(variantIndex, media);
3676
- }
3677
- handleCloseModal();
3678
- }, []);
3679
- return /* @__PURE__ */ jsxs16(Fragment6, { children: [
3680
- /* @__PURE__ */ jsx18(
3681
- ProductCreateForm,
3682
- {
3683
- defaultChannel,
3684
- store,
3685
- onOpenMediaModal: handleOpenMediaModal,
3686
- onSaveVariantMediaRef: saveVariantMediaRef
3687
- }
3688
- ),
3689
- /* @__PURE__ */ jsx18(
3690
- StackedFocusModal,
3691
- {
3692
- id: "variant-media-modal",
3693
- onOpenChangeCallback: (open) => {
3694
- if (!open) {
3695
- handleCloseModal();
3696
- }
3697
- },
3698
- children: selectedVariantIndex !== null && /* @__PURE__ */ jsx18(
3699
- VariantMediaView,
3700
- {
3701
- variantIndex: selectedVariantIndex,
3702
- variantTitle: selectedVariantTitle,
3703
- onClose: handleCloseModal,
3704
- onSaveMedia: handleSaveMedia,
3705
- initialMedia: selectedVariantMedia,
3706
- productMedia
3707
- }
3708
- )
3709
- }
3710
- )
3711
- ] });
3712
- };
3713
- var Root4 = ({ children }) => {
3714
- const { t } = useTranslation16();
3715
- const { store, isPending: isStorePending } = useStore();
3716
- const { sales_channels, isPending: isSalesChannelPending } = useSalesChannels();
3717
- const ready = !!store && !isStorePending && !!sales_channels && !isSalesChannelPending;
3718
- const defaultChannel = sales_channels?.[0];
3719
- return /* @__PURE__ */ jsxs16(RouteFocusModal, { children: [
3720
- /* @__PURE__ */ jsx18(RouteFocusModal.Title, { asChild: true, children: /* @__PURE__ */ jsx18("span", { className: "sr-only", children: t("products.create.title") }) }),
3721
- /* @__PURE__ */ jsx18(RouteFocusModal.Description, { asChild: true, children: /* @__PURE__ */ jsx18("span", { className: "sr-only", children: t("products.create.description") }) }),
3722
- ready && (Children4.count(children) > 0 ? children : /* @__PURE__ */ jsx18(ProductCreateFormWithModal, { defaultChannel, store }))
3723
- ] });
3724
- };
3725
- var ProductCreatePage = Object.assign(Root4, {
3726
- DetailsForm: ProductCreateDetailsForm,
3727
- OrganizeForm: ProductCreateOrganizeForm,
3728
- VariantsForm: ProductCreateVariantsForm,
3729
- InventoryKitForm: ProductCreateInventoryKitForm,
3730
- Form: ProductCreateForm,
3731
- Tab: TabbedForm.Tab
3732
- });
3733
-
3734
- export {
3735
- ProductCreatePage
3736
- };