@medusajs/dashboard 3.0.0-snapshot-20251106181920 → 3.0.0-snapshot-20251114155958

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 (299) hide show
  1. package/dist/{add-campaign-promotions-ZUJD7HBF.mjs → add-campaign-promotions-I7HDYMBX.mjs} +6 -6
  2. package/dist/{adjust-inventory-MEJEPP4Y.mjs → adjust-inventory-ZB3AVET7.mjs} +3 -3
  3. package/dist/{api-key-management-create-4OZWVOSF.mjs → api-key-management-create-U6VGZK7R.mjs} +4 -4
  4. package/dist/{api-key-management-detail-K3A3T6ET.mjs → api-key-management-detail-B5XNEGKF.mjs} +36 -36
  5. package/dist/{api-key-management-edit-FYLVVQOA.mjs → api-key-management-edit-TJM737A7.mjs} +4 -4
  6. package/dist/{api-key-management-list-6YG52LWY.mjs → api-key-management-list-ZRYMMTF5.mjs} +9 -9
  7. package/dist/{api-key-management-sales-channels-S5IFH7LP.mjs → api-key-management-sales-channels-D2RAHI7W.mjs} +12 -12
  8. package/dist/app.js +4574 -1022
  9. package/dist/app.mjs +33 -33
  10. package/dist/{campaign-budget-edit-V2VMINUO.mjs → campaign-budget-edit-H2KQKD7B.mjs} +2 -2
  11. package/dist/{campaign-configuration-PP4A5ADV.mjs → campaign-configuration-A452A22M.mjs} +2 -2
  12. package/dist/{campaign-create-NEKUWDGF.mjs → campaign-create-IXOWJQ4L.mjs} +7 -7
  13. package/dist/{campaign-detail-2H2W4W5B.mjs → campaign-detail-RCA3TBE4.mjs} +33 -33
  14. package/dist/{campaign-edit-O3LKMLXK.mjs → campaign-edit-LZV56AYF.mjs} +2 -2
  15. package/dist/{campaign-list-3452F4Y6.mjs → campaign-list-OH566KWW.mjs} +8 -8
  16. package/dist/{categories-metadata-ZEYU33GV.mjs → categories-metadata-5NBC7HX4.mjs} +28 -28
  17. package/dist/{category-create-N7PP3GWU.mjs → category-create-BTMZYQ5R.mjs} +3 -3
  18. package/dist/{category-detail-DKY37LPO.mjs → category-detail-RBUJVFPN.mjs} +34 -34
  19. package/dist/{category-edit-IFDQP7EZ.mjs → category-edit-Q3KEELHO.mjs} +3 -3
  20. package/dist/{category-list-2M4BCRAL.mjs → category-list-Z6HS6N75.mjs} +8 -8
  21. package/dist/{category-organize-76I7PO24.mjs → category-organize-45NPSRNG.mjs} +3 -3
  22. package/dist/{category-products-VVRGW25X.mjs → category-products-KREOO2KQ.mjs} +33 -33
  23. package/dist/{chunk-UKX2FFFV.mjs → chunk-25UWYEJX.mjs} +1 -1
  24. package/dist/{chunk-Q33G337Z.mjs → chunk-2GWGNMAA.mjs} +1 -1
  25. package/dist/{chunk-SMDWWXCD.mjs → chunk-2QH2TBJ2.mjs} +2 -2
  26. package/dist/{chunk-NQIC7ZFS.mjs → chunk-2SSUH2HJ.mjs} +2 -2
  27. package/dist/{chunk-P5RVJWPK.mjs → chunk-2WLOIS3L.mjs} +3 -3
  28. package/dist/{chunk-2D44OO7A.mjs → chunk-2X25XWOW.mjs} +1 -1
  29. package/dist/{chunk-KX4P5L3R.mjs → chunk-3BF5SC66.mjs} +1 -1
  30. package/dist/{chunk-OI4W5AEL.mjs → chunk-3RRA56WC.mjs} +26 -12
  31. package/dist/{chunk-7DWBXEH3.mjs → chunk-42TMWI76.mjs} +4 -4
  32. package/dist/{chunk-3EGEJ6Q2.mjs → chunk-4YAPXPLM.mjs} +1 -1
  33. package/dist/{chunk-F6PXCY3N.mjs → chunk-5AFMB7XQ.mjs} +1 -1
  34. package/dist/{chunk-OFN7DIZA.mjs → chunk-5AM254NB.mjs} +83 -3
  35. package/dist/{chunk-2ZKVRTBW.mjs → chunk-5BQQRHQS.mjs} +1 -1
  36. package/dist/{chunk-Y2XQE25L.mjs → chunk-5IFK2ZTA.mjs} +2 -2
  37. package/dist/{chunk-7PWZ5GMG.mjs → chunk-5N33TBBX.mjs} +2 -2
  38. package/dist/{chunk-S22NYSST.mjs → chunk-5X6SKB2P.mjs} +1 -1
  39. package/dist/{chunk-AHQI2S2Z.mjs → chunk-67RC6SEX.mjs} +2 -2
  40. package/dist/{chunk-I6E6CALJ.mjs → chunk-6CLQKVAU.mjs} +1 -1
  41. package/dist/{chunk-A2UMBW3V.mjs → chunk-6OU4CHZI.mjs} +1 -1
  42. package/dist/{chunk-GBKLLUUX.mjs → chunk-7H6DB666.mjs} +2 -2
  43. package/dist/{chunk-R2G2B47Y.mjs → chunk-A63RZVX6.mjs} +1 -1
  44. package/dist/{chunk-YSQG2JDM.mjs → chunk-BKJMQ6RP.mjs} +2 -2
  45. package/dist/{chunk-TYTNUPXB.mjs → chunk-BYOPZAGX.mjs} +13 -4
  46. package/dist/{chunk-HGFZAXHD.mjs → chunk-BYZSMXJ7.mjs} +2 -2
  47. package/dist/{chunk-32IQRUVY.mjs → chunk-CDORR33H.mjs} +1 -1
  48. package/dist/{chunk-RLY2SL5E.mjs → chunk-CN7JXSGW.mjs} +1 -1
  49. package/dist/{chunk-2WZUO66T.mjs → chunk-CV65NY6Y.mjs} +1 -1
  50. package/dist/{chunk-227DWSFF.mjs → chunk-CWIMWR6L.mjs} +9 -9
  51. package/dist/{chunk-PIR2H25N.mjs → chunk-DYDGGABK.mjs} +1 -1
  52. package/dist/{chunk-PFKKVLZX.mjs → chunk-DZWH2RV6.mjs} +1 -1
  53. package/dist/{chunk-LYTIMAIZ.mjs → chunk-FJHAGJ5G.mjs} +2 -2
  54. package/dist/{chunk-NGR5XU3K.mjs → chunk-FNQ227BC.mjs} +2 -2
  55. package/dist/{chunk-IVZ6BMDB.mjs → chunk-GA3UMQMZ.mjs} +1 -1
  56. package/dist/{chunk-TNMXAPPT.mjs → chunk-GHBURGZC.mjs} +1 -1
  57. package/dist/{chunk-FKIOYL3D.mjs → chunk-GU5PJRPM.mjs} +1 -1
  58. package/dist/{chunk-GRT22PE5.mjs → chunk-HBXV7ENS.mjs} +2 -2
  59. package/dist/{chunk-X6DSNTTX.mjs → chunk-HI6URQ7H.mjs} +2 -2
  60. package/dist/{chunk-B4GODIOW.mjs → chunk-HKIF5HVL.mjs} +1 -1
  61. package/dist/{chunk-QZ6PT4QV.mjs → chunk-HP2JH45P.mjs} +2 -2
  62. package/dist/{chunk-KOSCMAIC.mjs → chunk-I4OBEAOJ.mjs} +1 -1
  63. package/dist/{chunk-FA5QNPXE.mjs → chunk-K75OQ7QA.mjs} +3 -3
  64. package/dist/{chunk-3G33PZVQ.mjs → chunk-KF22R23X.mjs} +1 -1
  65. package/dist/{chunk-QTCZFYFH.mjs → chunk-KI7TOXBR.mjs} +1 -1
  66. package/dist/{chunk-GI6XX5VU.mjs → chunk-KJU3T6BK.mjs} +3 -3
  67. package/dist/{chunk-C5LYZZZ5.mjs → chunk-LGNTHZ5Y.mjs} +1 -1
  68. package/dist/{chunk-RM6NY572.mjs → chunk-M32MJOJN.mjs} +1 -1
  69. package/dist/{chunk-S34JJVBQ.mjs → chunk-M4Q5Q4I3.mjs} +2 -2
  70. package/dist/{chunk-GVVAVAXG.mjs → chunk-MOGV3UZD.mjs} +2 -2
  71. package/dist/{chunk-DEQUVHHE.mjs → chunk-NFEK63OE.mjs} +4 -1
  72. package/dist/{chunk-IBSMG7AF.mjs → chunk-NFEW5CVI.mjs} +6 -6
  73. package/dist/{chunk-VAIHVNV6.mjs → chunk-NL376WAO.mjs} +1 -1
  74. package/dist/{chunk-JC75WAC7.mjs → chunk-NZNJSGGE.mjs} +4 -4
  75. package/dist/{chunk-JAXWGF4M.mjs → chunk-O5DGX2NZ.mjs} +1 -1
  76. package/dist/{chunk-MK4E5XQX.mjs → chunk-OMRGW7JS.mjs} +2 -2
  77. package/dist/{chunk-WT5BXCPV.mjs → chunk-P23S5LDK.mjs} +4 -4
  78. package/dist/{chunk-GXXQ33F7.mjs → chunk-PCV2O6DU.mjs} +1 -1
  79. package/dist/{chunk-P777A4W3.mjs → chunk-PMJJI6GO.mjs} +1 -1
  80. package/dist/{chunk-CIY65KNH.mjs → chunk-PNPT4W2F.mjs} +4 -4
  81. package/dist/{chunk-GLVCH422.mjs → chunk-PVW6M64S.mjs} +1 -1
  82. package/dist/{chunk-JDA2MYND.mjs → chunk-QPJUVTKW.mjs} +1 -1
  83. package/dist/{chunk-GVPJPLE2.mjs → chunk-QW4SQVMT.mjs} +125 -33
  84. package/dist/{chunk-W77EPLUD.mjs → chunk-RAZ6EKFT.mjs} +4 -4
  85. package/dist/{chunk-SJ3E4T6B.mjs → chunk-ROKB75YP.mjs} +1 -1
  86. package/dist/{chunk-2VTICXJR.mjs → chunk-RYJ2UVJE.mjs} +1 -1
  87. package/dist/{chunk-JDEH6Z4M.mjs → chunk-SAZHCRHS.mjs} +1 -1
  88. package/dist/{chunk-QL4XKIVL.mjs → chunk-SQDIZZDW.mjs} +1 -1
  89. package/dist/{chunk-67ORSRVT.mjs → chunk-SUYYSKCB.mjs} +23 -16
  90. package/dist/{chunk-ORMX5RJQ.mjs → chunk-T57MRRCF.mjs} +1 -1
  91. package/dist/{chunk-GRNWRTT3.mjs → chunk-TBEGSDLQ.mjs} +2 -2
  92. package/dist/{chunk-SNDSWB6B.mjs → chunk-UM4OIJZ3.mjs} +2 -2
  93. package/dist/{chunk-V2LANK5S.mjs → chunk-VCSSQVPD.mjs} +2 -2
  94. package/dist/{chunk-SBFWPL42.mjs → chunk-VW34SZWE.mjs} +3 -3
  95. package/dist/{chunk-UTVAHVAY.mjs → chunk-W4TIFG3A.mjs} +7 -7
  96. package/dist/{chunk-WEMXXZMY.mjs → chunk-W7SLPIO2.mjs} +19 -7
  97. package/dist/{chunk-ENV6YVOM.mjs → chunk-WAXMT4IY.mjs} +3 -3
  98. package/dist/{chunk-Y6ZQFV7H.mjs → chunk-Y5TTJDGO.mjs} +1 -1
  99. package/dist/{chunk-WWQZD7WM.mjs → chunk-YGEJFHC3.mjs} +2 -2
  100. package/dist/{chunk-QXXHLVRQ.mjs → chunk-YGLRZQ4C.mjs} +1 -1
  101. package/dist/{chunk-PJ5EUKOB.mjs → chunk-YTN73JYH.mjs} +1 -1
  102. package/dist/{chunk-ET6EGRW3.mjs → chunk-YVQIO3JS.mjs} +3487 -227
  103. package/dist/{chunk-3MPO56OL.mjs → chunk-ZE34KAKV.mjs} +3 -3
  104. package/dist/{chunk-WOFUOGLO.mjs → chunk-ZOJRDXH3.mjs} +34 -124
  105. package/dist/{collection-add-products-QCSFXELK.mjs → collection-add-products-KM4VO5G5.mjs} +33 -33
  106. package/dist/{collection-create-45RYGDW7.mjs → collection-create-RIGJHEX5.mjs} +3 -3
  107. package/dist/{collection-detail-OLC6DMBZ.mjs → collection-detail-MLVNULUS.mjs} +33 -33
  108. package/dist/{collection-edit-YBPBHLLZ.mjs → collection-edit-WX5G3FHR.mjs} +3 -3
  109. package/dist/{collection-list-6UJNE2QB.mjs → collection-list-KWAHQGFE.mjs} +37 -37
  110. package/dist/{collection-metadata-QG55V5ZM.mjs → collection-metadata-OMFOP3LA.mjs} +28 -28
  111. package/dist/{customer-create-WCBUYT44.mjs → customer-create-VL6SIRZ2.mjs} +2 -2
  112. package/dist/{customer-create-address-VWVIJDMK.mjs → customer-create-address-V5C6M52P.mjs} +2 -2
  113. package/dist/{customer-detail-XOCZDUJL.mjs → customer-detail-SVDGB2QD.mjs} +35 -35
  114. package/dist/{customer-edit-FMK2AWZ5.mjs → customer-edit-WTBPVWOF.mjs} +2 -2
  115. package/dist/{customer-group-add-customers-TQAH4IPM.mjs → customer-group-add-customers-2Y2GVCDV.mjs} +9 -9
  116. package/dist/{customer-group-create-Y5O2CJOI.mjs → customer-group-create-A3CB3Z4K.mjs} +2 -2
  117. package/dist/{customer-group-detail-EWSDTVTQ.mjs → customer-group-detail-OCQTI4GG.mjs} +35 -35
  118. package/dist/{customer-group-edit-SMVW7PHM.mjs → customer-group-edit-7KV2PNLE.mjs} +2 -2
  119. package/dist/{customer-group-list-NFXAELFY.mjs → customer-group-list-K5MTMFLG.mjs} +33 -33
  120. package/dist/{customer-group-metadata-XJIMV7QU.mjs → customer-group-metadata-4F2SZF4M.mjs} +2 -2
  121. package/dist/{customer-list-TXAB4URJ.mjs → customer-list-TG4D4QOT.mjs} +9 -9
  122. package/dist/{customer-metadata-E32DPXXE.mjs → customer-metadata-LZ3TAXCV.mjs} +2 -2
  123. package/dist/{customers-add-customer-group-EYZMFVBS.mjs → customers-add-customer-group-2LLBHTX3.mjs} +32 -32
  124. package/dist/{edit-inventory-item-TFJL5H5X.mjs → edit-inventory-item-O6JLGZE4.mjs} +2 -2
  125. package/dist/{edit-inventory-item-attributes-O3K7OB56.mjs → edit-inventory-item-attributes-AUVR3GYY.mjs} +2 -2
  126. package/dist/{edit-reservation-Z5TFZERY.mjs → edit-reservation-GQ6R6GVA.mjs} +4 -4
  127. package/dist/{edit-rules-IE77WUXD.mjs → edit-rules-G7YMD5RC.mjs} +30 -30
  128. package/dist/en.json +3 -3
  129. package/dist/{inventory-create-HQ5XLKOJ.mjs → inventory-create-GMFEGLE4.mjs} +29 -29
  130. package/dist/{inventory-detail-DAINM7WP.mjs → inventory-detail-3BTAVXLJ.mjs} +34 -34
  131. package/dist/{inventory-list-5ROSUTXF.mjs → inventory-list-ADJQDNX5.mjs} +7 -7
  132. package/dist/{inventory-metadata-HUL56OD2.mjs → inventory-metadata-JJBXLQJG.mjs} +28 -28
  133. package/dist/{inventory-stock-5VIUWKTQ.mjs → inventory-stock-RHLN6ARK.mjs} +30 -30
  134. package/dist/{invite-U4I4IUOM.mjs → invite-VKHAAF4Z.mjs} +3 -3
  135. package/dist/{location-create-GZCUNYDT.mjs → location-create-GDOHM4T3.mjs} +2 -2
  136. package/dist/{location-detail-QMLCFID5.mjs → location-detail-F5QYFPUH.mjs} +28 -28
  137. package/dist/{location-edit-VNEMLWGR.mjs → location-edit-4SEMGQXA.mjs} +2 -2
  138. package/dist/{location-fulfillment-providers-NAFFMP3P.mjs → location-fulfillment-providers-7JXNE6YT.mjs} +37 -37
  139. package/dist/{location-list-MVIK73QC.mjs → location-list-ZJMZZ6T3.mjs} +5 -5
  140. package/dist/{location-sales-channels-D37LXTKQ.mjs → location-sales-channels-JPH5BTUY.mjs} +12 -12
  141. package/dist/{location-service-zone-create-27MNMKPQ.mjs → location-service-zone-create-35TTX636.mjs} +9 -9
  142. package/dist/{location-service-zone-edit-LCBBZ2OA.mjs → location-service-zone-edit-RWZS2XYW.mjs} +4 -4
  143. package/dist/{location-service-zone-manage-areas-U3EPNWSI.mjs → location-service-zone-manage-areas-RGMM5Y6C.mjs} +9 -9
  144. package/dist/{location-service-zone-shipping-option-create-VM4TEJHY.mjs → location-service-zone-shipping-option-create-7VTPJAPA.mjs} +31 -31
  145. package/dist/{location-service-zone-shipping-option-edit-WN4MTZSB.mjs → location-service-zone-shipping-option-edit-OYTEZGGC.mjs} +4 -4
  146. package/dist/{location-service-zone-shipping-option-pricing-GJIO4RRM.mjs → location-service-zone-shipping-option-pricing-NQRIEGTX.mjs} +8 -8
  147. package/dist/{login-MTGOV7KC.mjs → login-BGH5LSM4.mjs} +28 -28
  148. package/dist/{manage-locations-OHDFBORX.mjs → manage-locations-ATCDVTSR.mjs} +3 -3
  149. package/dist/{order-allocate-items-NU65ZXHE.mjs → order-allocate-items-PHIW64XK.mjs} +5 -5
  150. package/dist/{order-create-claim-LTE2E75R.mjs → order-create-claim-NPQ6E5DR.mjs} +36 -36
  151. package/dist/{order-create-edit-TPU3CKUU.mjs → order-create-edit-R4ZITC5I.mjs} +33 -33
  152. package/dist/{order-create-exchange-FVSBZI7P.mjs → order-create-exchange-6XPYKVYN.mjs} +36 -36
  153. package/dist/{order-create-fulfillment-NFGPDCBV.mjs → order-create-fulfillment-7DVPBUES.mjs} +29 -29
  154. package/dist/{order-create-refund-DC7C3R4Y.mjs → order-create-refund-7KEOYZTF.mjs} +28 -28
  155. package/dist/{order-create-return-RLXYVZLO.mjs → order-create-return-J23AFCKP.mjs} +13 -13
  156. package/dist/{order-create-shipment-RDYWCG3A.mjs → order-create-shipment-KNXCANID.mjs} +28 -28
  157. package/dist/{order-detail-VVOZ6E2R.mjs → order-detail-7ATBL7GN.mjs} +49 -41
  158. package/dist/{order-edit-billing-address-LV7453CS.mjs → order-edit-billing-address-VS75YMUY.mjs} +28 -28
  159. package/dist/{order-edit-email-4U5C6UKX.mjs → order-edit-email-GEE7SF2E.mjs} +28 -28
  160. package/dist/{order-edit-shipping-address-6IQC2CVP.mjs → order-edit-shipping-address-HSRXSRLU.mjs} +28 -28
  161. package/dist/{order-list-INSYF52F.mjs → order-list-GJTJHLZF.mjs} +52 -45
  162. package/dist/{order-metadata-EEV4IWOM.mjs → order-metadata-LUBKP5Y4.mjs} +28 -28
  163. package/dist/{order-receive-return-IWHR3EBF.mjs → order-receive-return-FLI44JN2.mjs} +29 -29
  164. package/dist/{order-request-transfer-65R4A7HS.mjs → order-request-transfer-NH2XCHMV.mjs} +29 -29
  165. package/dist/{price-list-configuration-L5XYCVP2.mjs → price-list-configuration-SS2VMD4N.mjs} +9 -9
  166. package/dist/{price-list-create-5GIMBRG2.mjs → price-list-create-DZR7JCDG.mjs} +36 -36
  167. package/dist/{price-list-detail-7AL2EBRL.mjs → price-list-detail-4INABJQQ.mjs} +35 -35
  168. package/dist/{price-list-edit-DHG5STG4.mjs → price-list-edit-VRI5T4W3.mjs} +4 -4
  169. package/dist/{price-list-list-QQKZEFSU.mjs → price-list-list-S2HWTXKV.mjs} +9 -9
  170. package/dist/{price-list-prices-add-2OO4QEZB.mjs → price-list-prices-add-DO43IEAD.mjs} +35 -35
  171. package/dist/{price-list-prices-edit-2FB25KWU.mjs → price-list-prices-edit-TRCLLGU4.mjs} +9 -9
  172. package/dist/{product-attributes-CCQ6WAOD.mjs → product-attributes-D6MNCAJB.mjs} +34 -34
  173. package/dist/{product-create-AIRCVZAE.mjs → product-create-JQQTUEQL.mjs} +82 -53
  174. package/dist/{product-create-variant-7BD5KQHQ.mjs → product-create-variant-6UQRMACE.mjs} +30 -30
  175. package/dist/{product-detail-IYMXYAPH.mjs → product-detail-JMOULY3O.mjs} +50 -38
  176. package/dist/{product-edit-PDGQHCQ2.mjs → product-edit-CC4OUBEC.mjs} +34 -34
  177. package/dist/{product-export-5EINLQDF.mjs → product-export-BVREOXJT.mjs} +36 -36
  178. package/dist/{product-image-variants-edit-DDSEBG5H.mjs → product-image-variants-edit-7BBTFZO7.mjs} +32 -32
  179. package/dist/{product-import-IQJWHNYN.mjs → product-import-UEXWOHOZ.mjs} +31 -30
  180. package/dist/{product-list-PUQEGU75.mjs → product-list-RHHY3NAS.mjs} +38 -38
  181. package/dist/{product-media-Q5XFYZRS.mjs → product-media-EKXMOSO4.mjs} +4 -4
  182. package/dist/{product-metadata-WCKNOZXX.mjs → product-metadata-DU2CNDKQ.mjs} +28 -28
  183. package/dist/{product-option-create-MWFWB2SU.mjs → product-option-create-ML66ZKF3.mjs} +28 -28
  184. package/dist/{product-option-detail-UKKEZPG7.mjs → product-option-detail-DT7HJF5Q.mjs} +39 -40
  185. package/dist/{product-option-edit-NHAF7B4P.mjs → product-option-edit-GUKWRQQH.mjs} +28 -28
  186. package/dist/{product-option-list-C6ZR2WIX.mjs → product-option-list-KF3JSQ6Y.mjs} +40 -44
  187. package/dist/{product-option-metadata-OWSGHNDC.mjs → product-option-metadata-BWWRRSAW.mjs} +28 -28
  188. package/dist/product-options-manage-QYWBIHJA.mjs +304 -0
  189. package/dist/{product-organization-HHME5F2C.mjs → product-organization-HU6YVPPV.mjs} +36 -36
  190. package/dist/{product-prices-GVEPABHQ.mjs → product-prices-UMEIS5AZ.mjs} +6 -6
  191. package/dist/{product-sales-channels-ZC5ONPG7.mjs → product-sales-channels-2SALTLTF.mjs} +11 -11
  192. package/dist/{product-shipping-profile-KXSBDGRD.mjs → product-shipping-profile-T4ZKHINJ.mjs} +35 -35
  193. package/dist/{product-stock-LXRLD7FA.mjs → product-stock-CKBS4YDA.mjs} +30 -30
  194. package/dist/{product-tag-create-RAJEWM5O.mjs → product-tag-create-GFGPI7ML.mjs} +28 -28
  195. package/dist/{product-tag-detail-EOW2GMOL.mjs → product-tag-detail-TTEWVF3I.mjs} +44 -44
  196. package/dist/{product-tag-edit-ZOO56XMF.mjs → product-tag-edit-3XNTLATZ.mjs} +28 -28
  197. package/dist/{product-tag-list-B2UX2OHB.mjs → product-tag-list-24IJRVFR.mjs} +44 -44
  198. package/dist/{product-tag-metadata-OZB7SVDN.mjs → product-tag-metadata-JANWHZ3K.mjs} +28 -28
  199. package/dist/{product-type-create-AHVZETDR.mjs → product-type-create-Y752WGBV.mjs} +2 -2
  200. package/dist/{product-type-detail-4YZUC6ZS.mjs → product-type-detail-MAUHCM3C.mjs} +34 -34
  201. package/dist/{product-type-edit-2RGFBZPK.mjs → product-type-edit-SMPJ5ZEF.mjs} +2 -2
  202. package/dist/{product-type-list-J2WDYTZK.mjs → product-type-list-7WQ5D2KV.mjs} +9 -9
  203. package/dist/{product-type-metadata-6QT47ZSR.mjs → product-type-metadata-FAKUWQQF.mjs} +28 -28
  204. package/dist/{product-variant-detail-HOOYZSS2.mjs → product-variant-detail-WHPECDUY.mjs} +32 -32
  205. package/dist/{product-variant-edit-J2MTJA75.mjs → product-variant-edit-GR4RNE5G.mjs} +29 -29
  206. package/dist/{product-variant-manage-inventory-items-P4QUORRH.mjs → product-variant-manage-inventory-items-IGDCLZQE.mjs} +3 -3
  207. package/dist/{product-variant-media-U5RG7AOW.mjs → product-variant-media-EKI4BTEV.mjs} +2 -2
  208. package/dist/{product-variant-metadata-ZRSZO2D4.mjs → product-variant-metadata-DA2HKXXB.mjs} +28 -28
  209. package/dist/{profile-detail-UTJBWZSA.mjs → profile-detail-BMC7IZBY.mjs} +3 -3
  210. package/dist/{profile-edit-OOYMTKX6.mjs → profile-edit-NFVR5Y4I.mjs} +3 -3
  211. package/dist/{promotion-add-campaign-XJB2ZKZ3.mjs → promotion-add-campaign-DOALJUKJ.mjs} +7 -7
  212. package/dist/{promotion-create-2E4EF4SP.mjs → promotion-create-GGZULF2B.mjs} +33 -33
  213. package/dist/{promotion-detail-P2BHIQDG.mjs → promotion-detail-XK7U73XH.mjs} +31 -31
  214. package/dist/{promotion-edit-details-JMZ77QJ4.mjs → promotion-edit-details-AKKNOCLM.mjs} +2 -2
  215. package/dist/{promotion-list-MN6YJCYA.mjs → promotion-list-TMWKPLMJ.mjs} +6 -6
  216. package/dist/{refund-reason-create-I3BIJFJH.mjs → refund-reason-create-H7MHJ5C5.mjs} +28 -28
  217. package/dist/{refund-reason-edit-2BEZASQH.mjs → refund-reason-edit-QY36CQVS.mjs} +28 -28
  218. package/dist/{refund-reason-list-NIJHHOXJ.mjs → refund-reason-list-KSQW33QC.mjs} +38 -38
  219. package/dist/{region-add-countries-KGFPZSRE.mjs → region-add-countries-6GB2QDJK.mjs} +7 -7
  220. package/dist/{region-create-YJJRTAYO.mjs → region-create-UVJICJRX.mjs} +9 -9
  221. package/dist/{region-detail-ERE4ZF2I.mjs → region-detail-D3JBW34A.mjs} +7 -7
  222. package/dist/{region-edit-QCN7SMR5.mjs → region-edit-3NVXQECN.mjs} +5 -5
  223. package/dist/{region-list-KE5HCKOR.mjs → region-list-JAQXIBYD.mjs} +7 -7
  224. package/dist/{region-metadata-RLZSQNGW.mjs → region-metadata-4KQG6UL6.mjs} +28 -28
  225. package/dist/{reservation-create-4R2XEEZU.mjs → reservation-create-Z7TWUE2L.mjs} +5 -5
  226. package/dist/{reservation-detail-7OYGNK4L.mjs → reservation-detail-W3FULMXT.mjs} +28 -28
  227. package/dist/{reservation-list-VY44QEH6.mjs → reservation-list-MN22JYAW.mjs} +9 -9
  228. package/dist/{reservation-metadata-VJIAGIMF.mjs → reservation-metadata-AKAN5XNE.mjs} +28 -28
  229. package/dist/{reset-password-CUEG23GU.mjs → reset-password-5TAYQEUV.mjs} +2 -2
  230. package/dist/{return-reason-create-45IARQ5L.mjs → return-reason-create-PLQNC4KW.mjs} +2 -2
  231. package/dist/{return-reason-edit-5FIOEJ5Y.mjs → return-reason-edit-XJCPMZ6U.mjs} +2 -2
  232. package/dist/{return-reason-list-6UKR2BLW.mjs → return-reason-list-ATE2XU4H.mjs} +12 -12
  233. package/dist/{sales-channel-add-products-KAUMNKMD.mjs → sales-channel-add-products-POHTQHMV.mjs} +33 -33
  234. package/dist/{sales-channel-create-I6ME6QBM.mjs → sales-channel-create-UFFXX5HK.mjs} +3 -3
  235. package/dist/{sales-channel-detail-5SXDKP6P.mjs → sales-channel-detail-AACIFU2E.mjs} +33 -33
  236. package/dist/{sales-channel-edit-O7GM2B6O.mjs → sales-channel-edit-SP2HF4E3.mjs} +3 -3
  237. package/dist/{sales-channel-list-JKZ6TIY7.mjs → sales-channel-list-BY3KTVV6.mjs} +35 -35
  238. package/dist/{sales-channel-metadata-33P5SKDI.mjs → sales-channel-metadata-KGOLI4BZ.mjs} +28 -28
  239. package/dist/{shipping-option-type-create-KVYNWD2Q.mjs → shipping-option-type-create-PSQZW3RN.mjs} +28 -28
  240. package/dist/{shipping-option-type-detail-YX3HMXNI.mjs → shipping-option-type-detail-WAW6TKJU.mjs} +29 -29
  241. package/dist/{shipping-option-type-edit-ODXQMHYJ.mjs → shipping-option-type-edit-2I44YHND.mjs} +28 -28
  242. package/dist/{shipping-option-type-list-XCQNWDDA.mjs → shipping-option-type-list-F4FRLW3P.mjs} +34 -34
  243. package/dist/{shipping-profile-create-372EMPUI.mjs → shipping-profile-create-NKFUOBVZ.mjs} +2 -2
  244. package/dist/{shipping-profile-detail-MRXUOUXK.mjs → shipping-profile-detail-WTKQSOIX.mjs} +2 -2
  245. package/dist/{shipping-profile-metadata-K34DAKGY.mjs → shipping-profile-metadata-AZXPMPHG.mjs} +28 -28
  246. package/dist/{shipping-profiles-list-KYYSHLSZ.mjs → shipping-profiles-list-H3CBZKRH.mjs} +6 -6
  247. package/dist/{store-add-currencies-SNSW7A6O.mjs → store-add-currencies-QVG2SI26.mjs} +8 -8
  248. package/dist/{store-detail-3Z3BK2BH.mjs → store-detail-AKRR64I6.mjs} +32 -32
  249. package/dist/{store-edit-FNKVB3UA.mjs → store-edit-Q25HCMCQ.mjs} +4 -4
  250. package/dist/{store-metadata-FESGAO7E.mjs → store-metadata-VLEDLAIJ.mjs} +28 -28
  251. package/dist/{tax-region-create-EVFVC6HN.mjs → tax-region-create-JTM53LCS.mjs} +29 -29
  252. package/dist/{tax-region-detail-ULHK52CD.mjs → tax-region-detail-XBFYCVSH.mjs} +49 -49
  253. package/dist/{tax-region-edit-CXEPD2F2.mjs → tax-region-edit-2RRF7C7P.mjs} +29 -29
  254. package/dist/{tax-region-list-HQMSVGDD.mjs → tax-region-list-BXZBUXRJ.mjs} +5 -5
  255. package/dist/{tax-region-province-create-6GZCPPGW.mjs → tax-region-province-create-T2LKEDTK.mjs} +2 -2
  256. package/dist/{tax-region-province-detail-VUY4PDGN.mjs → tax-region-province-detail-LGCYSFKE.mjs} +47 -47
  257. package/dist/{tax-region-tax-override-create-WWZZVAG5.mjs → tax-region-tax-override-create-2W25EZNZ.mjs} +44 -44
  258. package/dist/{tax-region-tax-override-edit-HVZRD44G.mjs → tax-region-tax-override-edit-ZSYNTYUG.mjs} +45 -45
  259. package/dist/{tax-region-tax-rate-create-TJLSRCEC.mjs → tax-region-tax-rate-create-UEOU5QRU.mjs} +3 -3
  260. package/dist/{tax-region-tax-rate-edit-DEKCUURK.mjs → tax-region-tax-rate-edit-ILCDNXHV.mjs} +3 -3
  261. package/dist/{user-detail-YTVBPRH5.mjs → user-detail-K5UMPO2L.mjs} +3 -3
  262. package/dist/{user-edit-NFRTYOKO.mjs → user-edit-25HD3BYT.mjs} +2 -2
  263. package/dist/{user-invite-FQNKJKMD.mjs → user-invite-CRQTVEYA.mjs} +6 -6
  264. package/dist/{user-list-73SJSKYT.mjs → user-list-KPI3BTOA.mjs} +9 -9
  265. package/dist/{user-metadata-33W3JSHN.mjs → user-metadata-KOGHOQTW.mjs} +28 -28
  266. package/dist/{workflow-execution-detail-SHEXD5OL.mjs → workflow-execution-detail-4QAQ44YB.mjs} +28 -28
  267. package/dist/{workflow-execution-list-JOVBPL45.mjs → workflow-execution-list-IZVF2XMJ.mjs} +6 -6
  268. package/package.json +10 -11
  269. package/src/components/common/file-upload/file-upload.tsx +23 -6
  270. package/src/components/data-grid/hooks/use-data-grid-form-handlers.tsx +21 -9
  271. package/src/components/inputs/combobox/combobox.tsx +173 -92
  272. package/src/components/layout/main-layout/main-layout.tsx +1 -0
  273. package/src/components/layout/nav-item/nav-item.tsx +14 -4
  274. package/src/dashboard-app/__tests__/sort-menu-items-by-rank.spec.ts +169 -0
  275. package/src/dashboard-app/dashboard-app.tsx +10 -1
  276. package/src/dashboard-app/types.ts +2 -0
  277. package/src/dashboard-app/utils/sort-menu-items-by-rank.ts +43 -0
  278. package/src/hooks/api/products.tsx +4 -4
  279. package/src/hooks/table/columns/use-product-option-table-columns.tsx +5 -4
  280. package/src/hooks/table/filters/use-product-option-table-filters.tsx +5 -5
  281. package/src/i18n/languages.ts +23 -16
  282. package/src/i18n/translations/$schema.json +5 -5
  283. package/src/i18n/translations/en.json +3 -3
  284. package/src/i18n/translations/index.ts +4 -0
  285. package/src/i18n/translations/ptPT.json +3219 -0
  286. package/src/lib/client/client.ts +4 -1
  287. package/src/routes/orders/order-detail/components/order-activity-section/order-timeline.tsx +19 -9
  288. package/src/routes/orders/order-list/components/order-list-table/use-order-table-filters.tsx +40 -30
  289. package/src/routes/products/common/components/upload-media-form-item/upload-media-form-item.tsx +26 -8
  290. package/src/routes/products/product-create/components/product-create-details-form/components/product-create-details-general-section/product-create-general-section.tsx +16 -4
  291. package/src/routes/products/product-create/components/product-create-details-form/components/product-create-details-variant-section/product-create-details-variant-section.tsx +7 -1
  292. package/src/routes/products/product-create/constants.ts +1 -0
  293. package/src/routes/products/product-create/utils.ts +2 -2
  294. package/src/routes/products/product-detail/components/product-general-section/product-general-section.tsx +1 -0
  295. package/src/routes/products/product-detail/components/product-option-section/product-option-section.tsx +24 -11
  296. package/src/routes/products/product-import/components/upload-import.tsx +1 -0
  297. package/src/routes/products/product-options-manage/components/product-options-manage-form/product-options-manage-form.tsx +145 -8
  298. package/src/vite-env.d.ts +2 -0
  299. package/dist/product-options-manage-N73G5IXY.mjs +0 -206
@@ -15,7 +15,7 @@ import {
15
15
  TrianglesMini,
16
16
  XMarkMini,
17
17
  } from "@medusajs/icons"
18
- import { clx, Text } from "@medusajs/ui"
18
+ import { Badge, clx, Text } from "@medusajs/ui"
19
19
  import { matchSorter } from "match-sorter"
20
20
  import {
21
21
  ComponentPropsWithoutRef,
@@ -59,6 +59,7 @@ interface ComboboxProps<T extends Value = Value>
59
59
  noResultsPlaceholder?: ReactNode
60
60
  allowClear?: boolean
61
61
  forceHideInput?: boolean // always hide input -> used for singe value select that don't have query/filter
62
+ displayMode?: "count" | "chips" // how to display multiple selected values
62
63
  }
63
64
 
64
65
  const ComboboxImpl = <T extends Value = string>(
@@ -76,6 +77,7 @@ const ComboboxImpl = <T extends Value = string>(
76
77
  noResultsPlaceholder,
77
78
  allowClear,
78
79
  forceHideInput,
80
+ displayMode = "count",
79
81
  ...inputProps
80
82
  }: ComboboxProps<T>,
81
83
  ref: ForwardedRef<HTMLInputElement>
@@ -143,6 +145,15 @@ const ComboboxImpl = <T extends Value = string>(
143
145
  }
144
146
  }
145
147
 
148
+ const handleRemoveValue = (valueToRemove: string) => {
149
+ if (!isArrayValue || !Array.isArray(selectedValues)) {
150
+ return
151
+ }
152
+
153
+ const newValues = selectedValues.filter((v) => v !== valueToRemove) as T
154
+ handleValueChange(newValues)
155
+ }
156
+
146
157
  /**
147
158
  * Filter and sort the options based on the search value,
148
159
  * and whether the value is already selected.
@@ -235,109 +246,179 @@ const ComboboxImpl = <T extends Value = string>(
235
246
  startTransition(() => handleSearchChange(query))
236
247
  }}
237
248
  >
238
- <div
239
- className={clx(
240
- "relative flex cursor-pointer items-center gap-x-2 overflow-hidden",
241
- "h-8 w-full rounded-md",
242
- "bg-ui-bg-field transition-fg shadow-borders-base",
243
- "has-[input:focus]:shadow-borders-interactive-with-active",
244
- "has-[:invalid]:shadow-borders-error has-[[aria-invalid=true]]:shadow-borders-error",
245
- "has-[:disabled]:bg-ui-bg-disabled has-[:disabled]:text-ui-fg-disabled has-[:disabled]:cursor-not-allowed",
246
- className
247
- )}
248
- style={
249
- {
250
- "--tag-width": `${tagWidth}px`,
251
- } as CSSProperties
252
- }
253
- >
254
- {showTag && (
255
- <button
256
- type="button"
257
- onClick={(e) => {
258
- e.preventDefault()
259
- handleValueChange(isArrayValue ? ([] as unknown as T) : undefined)
260
- }}
261
- className="bg-ui-bg-base hover:bg-ui-bg-base-hover txt-compact-small-plus text-ui-fg-subtle focus-within:border-ui-fg-interactive transition-fg absolute start-0.5 top-0.5 z-[1] flex h-[28px] items-center rounded-[4px] border py-[3px] pe-1 ps-1.5 outline-none"
262
- >
263
- <span className="tabular-nums">{selectedValues.length}</span>
264
- <XMarkMini className="text-ui-fg-muted" />
265
- </button>
266
- )}
267
- <div className="relative flex size-full items-center">
268
- {showSelected && (
269
- <div
249
+ {displayMode === "chips" && isArrayValue ? (
250
+ <div
251
+ className={clx(
252
+ "relative flex cursor-pointer flex-wrap items-center gap-1.5",
253
+ "min-h-8 w-full rounded-md",
254
+ "bg-ui-bg-field transition-fg shadow-borders-base",
255
+ "has-[input:focus]:shadow-borders-interactive-with-active",
256
+ "has-[:invalid]:shadow-borders-error has-[[aria-invalid=true]]:shadow-borders-error",
257
+ "has-[:disabled]:bg-ui-bg-disabled has-[:disabled]:text-ui-fg-disabled has-[:disabled]:cursor-not-allowed",
258
+ "p-1",
259
+ className
260
+ )}
261
+ >
262
+ {Array.isArray(selectedValues) &&
263
+ selectedValues.map((value) => {
264
+ const option = options.find((o) => o.value === value)
265
+ if (!option) return null
266
+
267
+ return (
268
+ <Badge
269
+ key={value}
270
+ size="2xsmall"
271
+ className="gap-x-0.5 pl-1.5 pr-1 transition-fg"
272
+ >
273
+ {option.label}
274
+ <button
275
+ tabIndex={-1}
276
+ type="button"
277
+ onClick={(e) => {
278
+ e.preventDefault()
279
+ handleRemoveValue(value)
280
+ }}
281
+ className="text-ui-fg-subtle transition-fg outline-none"
282
+ >
283
+ <XMarkMini />
284
+ </button>
285
+ </Badge>
286
+ )
287
+ })}
288
+ <div className="relative flex flex-1 items-center min-w-[120px]">
289
+ <PrimitiveCombobox
290
+ autoSelect
291
+ ref={comboboxRef}
292
+ onFocus={() => setOpen(true)}
270
293
  className={clx(
271
- "pointer-events-none absolute inset-y-0 flex size-full items-center",
272
- {
273
- "start-[calc(var(--tag-width)+8px)]": showTag,
274
- "start-2": !showTag,
275
- }
294
+ "txt-compact-small text-ui-fg-base !placeholder:text-ui-fg-muted transition-fg size-full cursor-pointer bg-transparent pe-8 ps-1 outline-none focus:cursor-text"
276
295
  )}
296
+ placeholder={
297
+ Array.isArray(selectedValues) && selectedValues.length > 0
298
+ ? undefined
299
+ : placeholder
300
+ }
301
+ {...inputProps}
302
+ />
303
+ </div>
304
+ <PrimitiveComboboxDisclosure
305
+ render={(props) => {
306
+ return (
307
+ <button
308
+ {...props}
309
+ type="button"
310
+ className="text-ui-fg-muted transition-fg hover:bg-ui-bg-field-hover absolute end-0 top-0 flex h-8 w-8 items-center justify-center rounded-r outline-none"
311
+ >
312
+ <TrianglesMini />
313
+ </button>
314
+ )
315
+ }}
316
+ />
317
+ </div>
318
+ ) : (
319
+ <div
320
+ className={clx(
321
+ "relative flex cursor-pointer items-center gap-x-2 overflow-hidden",
322
+ "h-8 w-full rounded-md",
323
+ "bg-ui-bg-field transition-fg shadow-borders-base",
324
+ "has-[input:focus]:shadow-borders-interactive-with-active",
325
+ "has-[:invalid]:shadow-borders-error has-[[aria-invalid=true]]:shadow-borders-error",
326
+ "has-[:disabled]:bg-ui-bg-disabled has-[:disabled]:text-ui-fg-disabled has-[:disabled]:cursor-not-allowed",
327
+ className
328
+ )}
329
+ style={
330
+ {
331
+ "--tag-width": `${tagWidth}px`,
332
+ } as CSSProperties
333
+ }
334
+ >
335
+ {showTag && (
336
+ <button
337
+ type="button"
338
+ onClick={(e) => {
339
+ e.preventDefault()
340
+ handleValueChange(isArrayValue ? ([] as unknown as T) : undefined)
341
+ }}
342
+ className="bg-ui-bg-base hover:bg-ui-bg-base-hover txt-compact-small-plus text-ui-fg-subtle focus-within:border-ui-fg-interactive transition-fg absolute start-0.5 top-0.5 z-[1] flex h-[28px] items-center rounded-[4px] border py-[3px] pe-1 ps-1.5 outline-none"
277
343
  >
278
- <Text size="small" leading="compact">
279
- {t("general.selected")}
280
- </Text>
281
- </div>
344
+ <span className="tabular-nums">{selectedValues.length}</span>
345
+ <XMarkMini className="text-ui-fg-muted" />
346
+ </button>
282
347
  )}
283
- {hideInput && (
284
- <div
348
+ <div className="relative flex size-full items-center">
349
+ {showSelected && (
350
+ <div
351
+ className={clx(
352
+ "pointer-events-none absolute inset-y-0 flex size-full items-center",
353
+ {
354
+ "start-[calc(var(--tag-width)+8px)]": showTag,
355
+ "start-2": !showTag,
356
+ }
357
+ )}
358
+ >
359
+ <Text size="small" leading="compact">
360
+ {t("general.selected")}
361
+ </Text>
362
+ </div>
363
+ )}
364
+ {hideInput && (
365
+ <div
366
+ className={clx(
367
+ "pointer-events-none absolute inset-y-0 flex size-full items-center overflow-hidden",
368
+ {
369
+ "start-[calc(var(--tag-width)+8px)]": showTag,
370
+ "start-2": !showTag,
371
+ }
372
+ )}
373
+ >
374
+ <Text size="small" leading="compact" className="truncate">
375
+ {selectedLabel}
376
+ </Text>
377
+ </div>
378
+ )}
379
+ <PrimitiveCombobox
380
+ autoSelect
381
+ ref={comboboxRef}
382
+ onFocus={() => setOpen(true)}
285
383
  className={clx(
286
- "pointer-events-none absolute inset-y-0 flex size-full items-center overflow-hidden",
384
+ "txt-compact-small text-ui-fg-base !placeholder:text-ui-fg-muted transition-fg size-full cursor-pointer bg-transparent pe-8 ps-2 outline-none focus:cursor-text",
287
385
  {
288
- "start-[calc(var(--tag-width)+8px)]": showTag,
289
- "start-2": !showTag,
386
+ "opacity-0": hideInput,
387
+ "ps-2": !showTag,
388
+ "ps-[calc(var(--tag-width)+8px)]": showTag,
290
389
  }
291
390
  )}
391
+ placeholder={hidePlaceholder ? undefined : placeholder}
392
+ {...inputProps}
393
+ />
394
+ </div>
395
+ {allowClear && controlledValue && (
396
+ <button
397
+ type="button"
398
+ onClick={(e) => {
399
+ e.preventDefault()
400
+ handleValueChange(undefined)
401
+ }}
402
+ className="bg-ui-bg-base hover:bg-ui-bg-base-hover txt-compact-small-plus text-ui-fg-subtle focus-within:border-ui-fg-interactive transition-fg absolute end-[28px] top-0.5 z-[1] flex h-[28px] items-center rounded-[4px] border px-1.5 py-[2px] outline-none"
292
403
  >
293
- <Text size="small" leading="compact" className="truncate">
294
- {selectedLabel}
295
- </Text>
296
- </div>
404
+ <XMarkMini className="text-ui-fg-muted" />
405
+ </button>
297
406
  )}
298
- <PrimitiveCombobox
299
- autoSelect
300
- ref={comboboxRef}
301
- onFocus={() => setOpen(true)}
302
- className={clx(
303
- "txt-compact-small text-ui-fg-base !placeholder:text-ui-fg-muted transition-fg size-full cursor-pointer bg-transparent pe-8 ps-2 outline-none focus:cursor-text",
304
- "hover:bg-ui-bg-field-hover",
305
- {
306
- "opacity-0": hideInput,
307
- "ps-2": !showTag,
308
- "ps-[calc(var(--tag-width)+8px)]": showTag,
309
- }
310
- )}
311
- placeholder={hidePlaceholder ? undefined : placeholder}
312
- {...inputProps}
407
+ <PrimitiveComboboxDisclosure
408
+ render={(props) => {
409
+ return (
410
+ <button
411
+ {...props}
412
+ type="button"
413
+ className="text-ui-fg-muted transition-fg hover:bg-ui-bg-field-hover absolute end-0 flex size-8 items-center justify-center rounded-r outline-none"
414
+ >
415
+ <TrianglesMini />
416
+ </button>
417
+ )
418
+ }}
313
419
  />
314
420
  </div>
315
- {allowClear && controlledValue && (
316
- <button
317
- type="button"
318
- onClick={(e) => {
319
- e.preventDefault()
320
- handleValueChange(undefined)
321
- }}
322
- className="bg-ui-bg-base hover:bg-ui-bg-base-hover txt-compact-small-plus text-ui-fg-subtle focus-within:border-ui-fg-interactive transition-fg absolute end-[28px] top-0.5 z-[1] flex h-[28px] items-center rounded-[4px] border px-1.5 py-[2px] outline-none"
323
- >
324
- <XMarkMini className="text-ui-fg-muted" />
325
- </button>
326
- )}
327
- <PrimitiveComboboxDisclosure
328
- render={(props) => {
329
- return (
330
- <button
331
- {...props}
332
- type="button"
333
- className="text-ui-fg-muted transition-fg hover:bg-ui-bg-field-hover absolute end-0 flex size-8 items-center justify-center rounded-r outline-none"
334
- >
335
- <TrianglesMini />
336
- </button>
337
- )
338
- }}
339
- />
340
- </div>
421
+ )}
341
422
  <PrimitiveComboboxPopover
342
423
  gutter={4}
343
424
  sameWidth
@@ -351,6 +351,7 @@ const ExtensionRouteSection = () => {
351
351
  label={item.label}
352
352
  icon={item.icon ? item.icon : <SquaresPlus />}
353
353
  items={item.items}
354
+ translationNs={item.translationNs}
354
355
  type="extension"
355
356
  />
356
357
  )
@@ -17,6 +17,7 @@ type ItemType = "core" | "extension" | "setting"
17
17
  type NestedItemProps = {
18
18
  label: string
19
19
  to: string
20
+ translationNs?: string
20
21
  }
21
22
 
22
23
  export type INavItem = {
@@ -27,6 +28,7 @@ export type INavItem = {
27
28
  type?: ItemType
28
29
  from?: string
29
30
  nested?: string
31
+ translationNs?: string
30
32
  }
31
33
 
32
34
  const BASE_NAV_LINK_CLASSES =
@@ -90,10 +92,15 @@ export const NavItem = ({
90
92
  items,
91
93
  type = "core",
92
94
  from,
95
+ translationNs,
93
96
  }: INavItem) => {
97
+ const { t } = useTranslation(translationNs as any)
94
98
  const { pathname } = useLocation()
95
99
  const [open, setOpen] = useState(getIsOpen(to, items, pathname))
96
100
 
101
+ // Use translation if translationNs is provided, otherwise use label as-is
102
+ const displayLabel: string = translationNs ? t(label) : label
103
+
97
104
  useEffect(() => {
98
105
  setOpen(getIsOpen(to, items, pathname))
99
106
  }, [pathname, to, items])
@@ -150,7 +157,7 @@ export const NavItem = ({
150
157
  </div>
151
158
  )}
152
159
  <Text size="small" weight="plus" leading="compact">
153
- {label}
160
+ {displayLabel}
154
161
  </Text>
155
162
  </NavLink>
156
163
  </NavItemTooltip>
@@ -166,7 +173,7 @@ export const NavItem = ({
166
173
  <Icon icon={icon} type={type} />
167
174
  </div>
168
175
  <Text size="small" weight="plus" leading="compact">
169
- {label}
176
+ {displayLabel}
170
177
  </Text>
171
178
  </RadixCollapsible.Trigger>
172
179
  <RadixCollapsible.Content>
@@ -189,12 +196,15 @@ export const NavItem = ({
189
196
  }}
190
197
  >
191
198
  <Text size="small" weight="plus" leading="compact">
192
- {label}
199
+ {displayLabel}
193
200
  </Text>
194
201
  </NavLink>
195
202
  </NavItemTooltip>
196
203
  </li>
197
204
  {items.map((item) => {
205
+ const { t: itemT } = useTranslation(item.translationNs as any)
206
+ const itemLabel: string = item.translationNs ? itemT(item.label) : item.label
207
+
198
208
  return (
199
209
  <li key={item.to} className="flex h-7 items-center">
200
210
  <NavItemTooltip to={item.to}>
@@ -213,7 +223,7 @@ export const NavItem = ({
213
223
  }}
214
224
  >
215
225
  <Text size="small" weight="plus" leading="compact">
216
- {item.label}
226
+ {itemLabel}
217
227
  </Text>
218
228
  </NavLink>
219
229
  </NavItemTooltip>
@@ -0,0 +1,169 @@
1
+ import { describe, expect, it } from "vitest"
2
+ import { sortMenuItemsByRank } from "../utils/sort-menu-items-by-rank"
3
+ import { INavItem } from "../../components/layout/nav-item"
4
+
5
+ describe("sortMenuItemsByRank", () => {
6
+ it("should sort items by rank in ascending order", () => {
7
+ const items: INavItem[] = [
8
+ { label: "Third", to: "/third", rank: 3 },
9
+ { label: "First", to: "/first", rank: 1 },
10
+ { label: "Second", to: "/second", rank: 2 },
11
+ ]
12
+
13
+ const sorted = sortMenuItemsByRank(items)
14
+
15
+ expect(sorted[0].label).toBe("First")
16
+ expect(sorted[1].label).toBe("Second")
17
+ expect(sorted[2].label).toBe("Third")
18
+ })
19
+
20
+ it("should place items with rank before items without rank", () => {
21
+ const items: INavItem[] = [
22
+ { label: "No Rank", to: "/no-rank" },
23
+ { label: "Ranked 2", to: "/ranked-2", rank: 2 },
24
+ { label: "Ranked 1", to: "/ranked-1", rank: 1 },
25
+ { label: "Also No Rank", to: "/also-no-rank" },
26
+ ]
27
+
28
+ const sorted = sortMenuItemsByRank(items)
29
+
30
+ expect(sorted[0].label).toBe("Ranked 1")
31
+ expect(sorted[1].label).toBe("Ranked 2")
32
+ expect(sorted[2].label).toBe("No Rank")
33
+ expect(sorted[3].label).toBe("Also No Rank")
34
+ })
35
+
36
+ it("should handle items with rank 0", () => {
37
+ const items: INavItem[] = [
38
+ { label: "Rank 2", to: "/rank-2", rank: 2 },
39
+ { label: "Rank 0", to: "/rank-0", rank: 0 },
40
+ { label: "Rank 1", to: "/rank-1", rank: 1 },
41
+ ]
42
+
43
+ const sorted = sortMenuItemsByRank(items)
44
+
45
+ expect(sorted[0].label).toBe("Rank 0")
46
+ expect(sorted[1].label).toBe("Rank 1")
47
+ expect(sorted[2].label).toBe("Rank 2")
48
+ })
49
+
50
+ it("should handle negative ranks", () => {
51
+ const items: INavItem[] = [
52
+ { label: "Rank 1", to: "/rank-1", rank: 1 },
53
+ { label: "Rank -1", to: "/rank-minus-1", rank: -1 },
54
+ { label: "Rank 0", to: "/rank-0", rank: 0 },
55
+ ]
56
+
57
+ const sorted = sortMenuItemsByRank(items)
58
+
59
+ expect(sorted[0].label).toBe("Rank -1")
60
+ expect(sorted[1].label).toBe("Rank 0")
61
+ expect(sorted[2].label).toBe("Rank 1")
62
+ })
63
+
64
+ it("should sort nested items independently", () => {
65
+ const items: INavItem[] = [
66
+ {
67
+ label: "Parent 2",
68
+ to: "/parent-2",
69
+ rank: 2,
70
+ items: [
71
+ { label: "Child 2B", to: "/child-2b", rank: 2 },
72
+ { label: "Child 2A", to: "/child-2a", rank: 1 },
73
+ ],
74
+ },
75
+ {
76
+ label: "Parent 1",
77
+ to: "/parent-1",
78
+ rank: 1,
79
+ items: [
80
+ { label: "Child 1C", to: "/child-1c", rank: 3 },
81
+ { label: "Child 1A", to: "/child-1a", rank: 1 },
82
+ { label: "Child 1B", to: "/child-1b", rank: 2 },
83
+ ],
84
+ },
85
+ ]
86
+
87
+ const sorted = sortMenuItemsByRank(items)
88
+
89
+ // Parents should be sorted
90
+ expect(sorted[0].label).toBe("Parent 1")
91
+ expect(sorted[1].label).toBe("Parent 2")
92
+
93
+ // Parent 1's children should be sorted
94
+ expect(sorted[0].items![0].label).toBe("Child 1A")
95
+ expect(sorted[0].items![1].label).toBe("Child 1B")
96
+ expect(sorted[0].items![2].label).toBe("Child 1C")
97
+
98
+ // Parent 2's children should be sorted
99
+ expect(sorted[1].items![0].label).toBe("Child 2A")
100
+ expect(sorted[1].items![1].label).toBe("Child 2B")
101
+ })
102
+
103
+ it("should handle nested items with mixed ranked and unranked", () => {
104
+ const items: INavItem[] = [
105
+ {
106
+ label: "Parent",
107
+ to: "/parent",
108
+ rank: 1,
109
+ items: [
110
+ { label: "No Rank Child", to: "/no-rank" },
111
+ { label: "Rank 1 Child", to: "/rank-1", rank: 1 },
112
+ { label: "Rank 2 Child", to: "/rank-2", rank: 2 },
113
+ ],
114
+ },
115
+ ]
116
+
117
+ const sorted = sortMenuItemsByRank(items)
118
+
119
+ expect(sorted[0].items![0].label).toBe("Rank 1 Child")
120
+ expect(sorted[0].items![1].label).toBe("Rank 2 Child")
121
+ expect(sorted[0].items![2].label).toBe("No Rank Child")
122
+ })
123
+
124
+ it("should handle empty items array", () => {
125
+ const items: INavItem[] = []
126
+
127
+ const sorted = sortMenuItemsByRank(items)
128
+
129
+ expect(sorted).toEqual([])
130
+ })
131
+
132
+ it("should handle single item", () => {
133
+ const items: INavItem[] = [{ label: "Only Item", to: "/only", rank: 1 }]
134
+
135
+ const sorted = sortMenuItemsByRank(items)
136
+
137
+ expect(sorted).toHaveLength(1)
138
+ expect(sorted[0].label).toBe("Only Item")
139
+ })
140
+
141
+ it("should preserve items without nested arrays", () => {
142
+ const items: INavItem[] = [
143
+ { label: "Item 1", to: "/item-1", rank: 2 },
144
+ { label: "Item 2", to: "/item-2", rank: 1 },
145
+ ]
146
+
147
+ const sorted = sortMenuItemsByRank(items)
148
+
149
+ expect(sorted[0].items).toBeUndefined()
150
+ expect(sorted[1].items).toBeUndefined()
151
+ })
152
+
153
+ it("should handle duplicate rank values", () => {
154
+ const items: INavItem[] = [
155
+ { label: "Item C", to: "/item-c", rank: 1 },
156
+ { label: "Item A", to: "/item-a", rank: 1 },
157
+ { label: "Item B", to: "/item-b", rank: 1 },
158
+ ]
159
+
160
+ const sorted = sortMenuItemsByRank(items)
161
+
162
+ // All should have rank 1, order should be stable
163
+ expect(sorted[0].rank).toBe(1)
164
+ expect(sorted[1].rank).toBe(1)
165
+ expect(sorted[2].rank).toBe(1)
166
+ expect(sorted).toHaveLength(3)
167
+ })
168
+ })
169
+
@@ -18,6 +18,7 @@ import { Providers } from "../providers"
18
18
  import coreTranslations from "../i18n/translations"
19
19
  import { getRouteMap } from "./routes/get-route.map"
20
20
  import { createRouteMap, getRouteExtensions } from "./routes/utils"
21
+ import { sortMenuItemsByRank } from "./utils/sort-menu-items-by-rank"
21
22
  import {
22
23
  ConfigExtension,
23
24
  ConfigField,
@@ -181,12 +182,14 @@ export class DashboardApp {
181
182
  return
182
183
  }
183
184
 
184
- const navItem: INavItem = {
185
+ const navItem: INavItem & { rank?: number } = {
185
186
  label: item.label,
186
187
  to: item.path,
187
188
  icon: item.icon ? <item.icon /> : undefined,
188
189
  items: [],
189
190
  nested: item.nested,
191
+ rank: item.rank,
192
+ translationNs: item.translationNs,
190
193
  }
191
194
 
192
195
  if (parentPath !== "/" && tempRegistry[parentPath]) {
@@ -204,6 +207,12 @@ export class DashboardApp {
204
207
  tempRegistry[item.path] = navItem
205
208
  })
206
209
 
210
+ // Sort menu items by rank (ascending order, undefined ranks come last)
211
+ registry.forEach((items, key) => {
212
+ const sorted = sortMenuItemsByRank(items)
213
+ registry.set(key, sorted)
214
+ })
215
+
207
216
  return registry
208
217
  }
209
218
 
@@ -24,6 +24,8 @@ export type MenuItemExtension = {
24
24
  path: string
25
25
  icon?: ComponentType
26
26
  nested?: NestedRoutePosition
27
+ rank?: number
28
+ translationNs?: string
27
29
  }
28
30
 
29
31
  export type WidgetExtension = {
@@ -0,0 +1,43 @@
1
+ import { INavItem } from "../../components/layout/nav-item"
2
+
3
+ /**
4
+ * Sort menu items by rank in ascending order.
5
+ * Items with rank come first, sorted by rank value.
6
+ * Items without rank come last, maintaining their original order.
7
+ * Recursively sorts nested items independently.
8
+ */
9
+ export function sortMenuItemsByRank(
10
+ items: (INavItem & { rank?: number })[]
11
+ ): INavItem[] {
12
+ // Sort items by rank (ascending order)
13
+ // Items with rank come first, sorted by rank value
14
+ // Items without rank come last, maintaining their original order
15
+ const sortedItems = items.sort((a, b) => {
16
+ // If both have rank, sort by rank value
17
+ if (a.rank !== undefined && b.rank !== undefined) {
18
+ return a.rank - b.rank
19
+ }
20
+ // If only a has rank, it comes first
21
+ if (a.rank !== undefined) {
22
+ return -1
23
+ }
24
+ // If only b has rank, it comes first
25
+ if (b.rank !== undefined) {
26
+ return 1
27
+ }
28
+ // If neither has rank, maintain original order
29
+ return 0
30
+ })
31
+
32
+ // Recursively sort nested items
33
+ sortedItems.forEach((item) => {
34
+ if (item.items && item.items.length > 0) {
35
+ item.items = sortMenuItemsByRank(
36
+ item.items as (INavItem & { rank?: number })[]
37
+ )
38
+ }
39
+ })
40
+
41
+ return sortedItems
42
+ }
43
+