@vendure/dashboard 3.4.0-minor-202506250934 → 3.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (523) hide show
  1. package/README.md +102 -3
  2. package/dist/plugin/api/api-extensions.d.ts +1 -0
  3. package/dist/plugin/api/api-extensions.js +38 -0
  4. package/dist/plugin/api/metrics.resolver.d.ts +8 -0
  5. package/dist/plugin/api/metrics.resolver.js +40 -0
  6. package/dist/plugin/config/metrics-strategies.d.ts +39 -0
  7. package/dist/plugin/config/metrics-strategies.js +74 -0
  8. package/dist/plugin/constants.d.ts +4 -3
  9. package/dist/plugin/constants.js +10 -277
  10. package/dist/plugin/dashboard.plugin.d.ts +95 -0
  11. package/dist/plugin/dashboard.plugin.js +168 -0
  12. package/dist/plugin/index.d.ts +2 -1
  13. package/dist/plugin/index.js +18 -1
  14. package/dist/plugin/package.json +3 -0
  15. package/dist/plugin/service/metrics.service.d.ts +15 -0
  16. package/dist/plugin/service/metrics.service.js +145 -0
  17. package/dist/plugin/types.d.ts +23 -0
  18. package/dist/plugin/types.js +13 -0
  19. package/dist/vite/constants.d.ts +5 -0
  20. package/dist/vite/constants.js +277 -0
  21. package/dist/vite/index.d.ts +1 -0
  22. package/dist/vite/index.js +1 -0
  23. package/dist/vite/types.d.ts +40 -0
  24. package/dist/{plugin → vite}/utils/ast-utils.d.ts +0 -5
  25. package/dist/vite/utils/ast-utils.js +29 -0
  26. package/dist/vite/utils/ast-utils.spec.d.ts +1 -0
  27. package/dist/vite/utils/ast-utils.spec.js +45 -0
  28. package/dist/vite/utils/compiler.d.ts +22 -0
  29. package/dist/vite/utils/compiler.js +162 -0
  30. package/dist/vite/utils/config-loader.d.ts +1 -0
  31. package/dist/vite/utils/config-loader.js +1 -0
  32. package/dist/vite/utils/logger.d.ts +3 -0
  33. package/dist/vite/utils/logger.js +39 -0
  34. package/dist/vite/utils/plugin-discovery.d.ts +27 -0
  35. package/dist/vite/utils/plugin-discovery.js +387 -0
  36. package/dist/vite/utils/tsconfig-utils.d.ts +9 -0
  37. package/dist/vite/utils/tsconfig-utils.js +50 -0
  38. package/dist/vite/utils/ui-config.d.ts +3 -0
  39. package/dist/vite/utils/ui-config.js +30 -0
  40. package/dist/{plugin → vite}/vite-plugin-config-loader.d.ts +3 -3
  41. package/dist/{plugin → vite}/vite-plugin-config-loader.js +18 -13
  42. package/dist/{plugin → vite}/vite-plugin-config.js +6 -7
  43. package/dist/{plugin → vite}/vite-plugin-dashboard-metadata.d.ts +1 -3
  44. package/dist/{plugin → vite}/vite-plugin-dashboard-metadata.js +20 -10
  45. package/dist/vite/vite-plugin-tailwind-source.d.ts +7 -0
  46. package/dist/vite/vite-plugin-tailwind-source.js +61 -0
  47. package/dist/vite/vite-plugin-theme.js +130 -0
  48. package/dist/vite/vite-plugin-ui-config.d.ts +123 -0
  49. package/dist/{plugin → vite}/vite-plugin-ui-config.js +3 -11
  50. package/dist/vite/vite-plugin-vendure-dashboard.d.ts +85 -0
  51. package/dist/{plugin → vite}/vite-plugin-vendure-dashboard.js +10 -7
  52. package/index.html +1 -1
  53. package/package.json +56 -31
  54. package/src/app/app-providers.tsx +7 -7
  55. package/src/app/common/delete-bulk-action.tsx +148 -0
  56. package/src/app/common/duplicate-bulk-action.tsx +134 -0
  57. package/src/app/main.tsx +9 -9
  58. package/src/app/routes/__root.tsx +1 -2
  59. package/src/app/routes/_authenticated/_administrators/administrators.graphql.ts +10 -1
  60. package/src/app/routes/_authenticated/_administrators/administrators.tsx +15 -8
  61. package/src/app/routes/_authenticated/_administrators/administrators_.$id.tsx +16 -12
  62. package/src/app/routes/_authenticated/_administrators/components/administrator-bulk-actions.tsx +15 -0
  63. package/src/app/routes/_authenticated/_administrators/components/role-permissions-display.tsx +16 -16
  64. package/src/app/routes/_authenticated/_assets/assets.graphql.ts +13 -2
  65. package/src/app/routes/_authenticated/_assets/assets.tsx +16 -4
  66. package/src/app/routes/_authenticated/_assets/assets_.$id.tsx +52 -38
  67. package/src/app/routes/_authenticated/_assets/components/asset-bulk-actions.tsx +45 -0
  68. package/src/app/routes/_authenticated/_channels/channels.graphql.ts +10 -1
  69. package/src/app/routes/_authenticated/_channels/channels.tsx +17 -10
  70. package/src/app/routes/_authenticated/_channels/channels_.$id.tsx +21 -17
  71. package/src/app/routes/_authenticated/_channels/components/channel-bulk-actions.tsx +15 -0
  72. package/src/app/routes/_authenticated/_collections/collections.graphql.ts +60 -3
  73. package/src/app/routes/_authenticated/_collections/collections.tsx +168 -124
  74. package/src/app/routes/_authenticated/_collections/collections_.$id.tsx +21 -17
  75. package/src/app/routes/_authenticated/_collections/components/collection-bulk-actions.tsx +123 -0
  76. package/src/app/routes/_authenticated/_collections/components/collection-contents-preview-table.tsx +8 -9
  77. package/src/app/routes/_authenticated/_collections/components/collection-contents-sheet.tsx +9 -5
  78. package/src/app/routes/_authenticated/_collections/components/collection-contents-table.tsx +10 -9
  79. package/src/app/routes/_authenticated/_collections/components/collection-filters-selector.tsx +12 -79
  80. package/src/app/routes/_authenticated/_collections/components/move-collections-dialog.tsx +430 -0
  81. package/src/app/routes/_authenticated/_collections/components/move-single-collection.tsx +33 -0
  82. package/src/app/routes/_authenticated/_countries/components/country-bulk-actions.tsx +15 -0
  83. package/src/app/routes/_authenticated/_countries/countries.graphql.ts +11 -2
  84. package/src/app/routes/_authenticated/_countries/countries.tsx +13 -6
  85. package/src/app/routes/_authenticated/_countries/countries_.$id.tsx +21 -17
  86. package/src/app/routes/_authenticated/_customer-groups/components/customer-group-bulk-actions.tsx +15 -0
  87. package/src/app/routes/_authenticated/_customer-groups/components/customer-group-members-sheet.tsx +12 -5
  88. package/src/app/routes/_authenticated/_customer-groups/components/customer-group-members-table.tsx +22 -17
  89. package/src/app/routes/_authenticated/_customer-groups/customer-groups.graphql.ts +11 -2
  90. package/src/app/routes/_authenticated/_customer-groups/customer-groups.tsx +13 -6
  91. package/src/app/routes/_authenticated/_customer-groups/customer-groups_.$id.tsx +18 -15
  92. package/src/app/routes/_authenticated/_customers/components/customer-address-card.tsx +19 -19
  93. package/src/app/routes/_authenticated/_customers/components/customer-address-form.tsx +10 -10
  94. package/src/app/routes/_authenticated/_customers/components/customer-bulk-actions.tsx +15 -0
  95. package/src/app/routes/_authenticated/_customers/components/customer-history/customer-history-container.tsx +5 -5
  96. package/src/app/routes/_authenticated/_customers/components/customer-history/customer-history.tsx +11 -7
  97. package/src/app/routes/_authenticated/_customers/components/customer-history/use-customer-history.ts +4 -4
  98. package/src/app/routes/_authenticated/_customers/components/customer-order-table.tsx +75 -73
  99. package/src/app/routes/_authenticated/_customers/components/customer-status-badge.tsx +4 -4
  100. package/src/app/routes/_authenticated/_customers/customers.graphql.ts +10 -2
  101. package/src/app/routes/_authenticated/_customers/customers.tsx +13 -6
  102. package/src/app/routes/_authenticated/_customers/customers_.$id.tsx +19 -15
  103. package/src/app/routes/_authenticated/_facets/components/edit-facet-value.tsx +9 -9
  104. package/src/app/routes/_authenticated/_facets/components/facet-bulk-actions.tsx +104 -0
  105. package/src/app/routes/_authenticated/_facets/components/facet-values-sheet.tsx +4 -4
  106. package/src/app/routes/_authenticated/_facets/components/facet-values-table.tsx +76 -65
  107. package/src/app/routes/_authenticated/_facets/facets.graphql.ts +80 -1
  108. package/src/app/routes/_authenticated/_facets/facets.tsx +31 -7
  109. package/src/app/routes/_authenticated/_facets/facets_.$facetId.values_.$id.tsx +147 -0
  110. package/src/app/routes/_authenticated/_facets/facets_.$id.tsx +17 -13
  111. package/src/app/routes/_authenticated/_global-settings/global-settings.graphql.ts +1 -1
  112. package/src/app/routes/_authenticated/_global-settings/global-settings.tsx +26 -18
  113. package/src/app/routes/_authenticated/_orders/components/add-manual-payment-dialog.tsx +191 -0
  114. package/src/app/routes/_authenticated/_orders/components/customer-address-selector.tsx +11 -15
  115. package/src/app/routes/_authenticated/_orders/components/edit-order-table.tsx +111 -80
  116. package/src/app/routes/_authenticated/_orders/components/fulfill-order-dialog.tsx +320 -0
  117. package/src/app/routes/_authenticated/_orders/components/fulfillment-details.tsx +153 -0
  118. package/src/app/routes/_authenticated/_orders/components/money-gross-net.tsx +11 -9
  119. package/src/app/routes/_authenticated/_orders/components/order-address.tsx +19 -13
  120. package/src/app/routes/_authenticated/_orders/components/order-history/order-history-container.tsx +67 -62
  121. package/src/app/routes/_authenticated/_orders/components/order-history/order-history.tsx +391 -39
  122. package/src/app/routes/_authenticated/_orders/components/order-history/use-order-history.ts +9 -5
  123. package/src/app/routes/_authenticated/_orders/components/order-line-custom-fields-form.tsx +28 -13
  124. package/src/app/routes/_authenticated/_orders/components/order-modification-preview-dialog.tsx +364 -0
  125. package/src/app/routes/_authenticated/_orders/components/order-modification-summary.tsx +222 -0
  126. package/src/app/routes/_authenticated/_orders/components/order-table-totals.tsx +39 -22
  127. package/src/app/routes/_authenticated/_orders/components/order-table.tsx +148 -87
  128. package/src/app/routes/_authenticated/_orders/components/order-tax-summary.tsx +37 -36
  129. package/src/app/routes/_authenticated/_orders/components/payment-details.tsx +274 -48
  130. package/src/app/routes/_authenticated/_orders/components/settle-refund-dialog.tsx +80 -0
  131. package/src/app/routes/_authenticated/_orders/components/shipping-method-selector.tsx +43 -44
  132. package/src/app/routes/_authenticated/_orders/components/state-transition-control.tsx +102 -0
  133. package/src/app/routes/_authenticated/_orders/components/use-transition-order-to-state.tsx +144 -0
  134. package/src/app/routes/_authenticated/_orders/orders.graphql.ts +219 -5
  135. package/src/app/routes/_authenticated/_orders/orders.tsx +23 -22
  136. package/src/app/routes/_authenticated/_orders/orders_.$id.tsx +190 -42
  137. package/src/app/routes/_authenticated/_orders/orders_.$id_.modify.tsx +550 -0
  138. package/src/app/routes/_authenticated/_orders/orders_.draft.$id.tsx +187 -107
  139. package/src/app/routes/_authenticated/_orders/utils/order-types.ts +10 -0
  140. package/src/app/routes/_authenticated/_orders/utils/order-utils.ts +78 -0
  141. package/src/app/routes/_authenticated/_payment-methods/components/payment-eligibility-checker-selector.tsx +12 -79
  142. package/src/app/routes/_authenticated/_payment-methods/components/payment-handler-selector.tsx +12 -79
  143. package/src/app/routes/_authenticated/_payment-methods/components/payment-method-bulk-actions.tsx +58 -0
  144. package/src/app/routes/_authenticated/_payment-methods/payment-methods.graphql.ts +29 -2
  145. package/src/app/routes/_authenticated/_payment-methods/payment-methods.tsx +36 -14
  146. package/src/app/routes/_authenticated/_payment-methods/payment-methods_.$id.tsx +22 -15
  147. package/src/app/routes/_authenticated/_product-variants/components/product-variant-bulk-actions.tsx +110 -0
  148. package/src/app/routes/_authenticated/_product-variants/components/variant-price-detail.tsx +7 -6
  149. package/src/app/routes/_authenticated/_product-variants/product-variants.graphql.ts +64 -3
  150. package/src/app/routes/_authenticated/_product-variants/product-variants.tsx +39 -9
  151. package/src/app/routes/_authenticated/_product-variants/product-variants_.$id.tsx +33 -22
  152. package/src/app/routes/_authenticated/_products/components/add-product-variant-dialog.tsx +10 -10
  153. package/src/app/routes/_authenticated/_products/components/assign-facet-values-dialog.tsx +281 -0
  154. package/src/app/routes/_authenticated/_products/components/create-product-options-dialog.tsx +57 -41
  155. package/src/app/routes/_authenticated/_products/components/create-product-variants-dialog.tsx +11 -11
  156. package/src/app/routes/_authenticated/_products/components/create-product-variants.tsx +18 -14
  157. package/src/app/routes/_authenticated/_products/components/option-value-input.tsx +23 -17
  158. package/src/app/routes/_authenticated/_products/components/product-bulk-actions.tsx +123 -0
  159. package/src/app/routes/_authenticated/_products/components/product-option-select.tsx +28 -34
  160. package/src/app/routes/_authenticated/_products/components/product-variants-table.tsx +84 -53
  161. package/src/app/routes/_authenticated/_products/products.graphql.ts +70 -2
  162. package/src/app/routes/_authenticated/_products/products.tsx +36 -7
  163. package/src/app/routes/_authenticated/_products/products_.$id.tsx +34 -26
  164. package/src/app/routes/_authenticated/_profile/profile.graphql.ts +1 -1
  165. package/src/app/routes/_authenticated/_profile/profile.tsx +8 -8
  166. package/src/app/routes/_authenticated/_promotions/components/promotion-actions-selector.tsx +14 -86
  167. package/src/app/routes/_authenticated/_promotions/components/promotion-bulk-actions.tsx +82 -0
  168. package/src/app/routes/_authenticated/_promotions/components/promotion-conditions-selector.tsx +14 -86
  169. package/src/app/routes/_authenticated/_promotions/promotions.graphql.ts +27 -2
  170. package/src/app/routes/_authenticated/_promotions/promotions.tsx +31 -7
  171. package/src/app/routes/_authenticated/_promotions/promotions_.$id.tsx +20 -16
  172. package/src/app/routes/_authenticated/_roles/components/expandable-permissions.tsx +5 -5
  173. package/src/app/routes/_authenticated/_roles/components/permissions-grid.tsx +21 -17
  174. package/src/app/routes/_authenticated/_roles/components/role-bulk-actions.tsx +15 -0
  175. package/src/app/routes/_authenticated/_roles/roles.graphql.ts +10 -1
  176. package/src/app/routes/_authenticated/_roles/roles.tsx +17 -10
  177. package/src/app/routes/_authenticated/_roles/roles_.$id.tsx +16 -12
  178. package/src/app/routes/_authenticated/_sellers/components/seller-bulk-actions.tsx +15 -0
  179. package/src/app/routes/_authenticated/_sellers/sellers.graphql.ts +10 -1
  180. package/src/app/routes/_authenticated/_sellers/sellers.tsx +13 -6
  181. package/src/app/routes/_authenticated/_sellers/sellers_.$id.tsx +17 -13
  182. package/src/app/routes/_authenticated/_shipping-methods/components/fulfillment-handler-selector.tsx +6 -6
  183. package/src/app/routes/_authenticated/_shipping-methods/components/shipping-calculator-selector.tsx +12 -80
  184. package/src/app/routes/_authenticated/_shipping-methods/components/shipping-eligibility-checker-selector.tsx +15 -80
  185. package/src/app/routes/_authenticated/_shipping-methods/components/shipping-method-bulk-actions.tsx +61 -0
  186. package/src/app/routes/_authenticated/_shipping-methods/components/test-shipping-method-dialog.tsx +3 -3
  187. package/src/app/routes/_authenticated/_shipping-methods/shipping-methods.graphql.ts +29 -2
  188. package/src/app/routes/_authenticated/_shipping-methods/shipping-methods.tsx +25 -6
  189. package/src/app/routes/_authenticated/_shipping-methods/shipping-methods_.$id.tsx +25 -19
  190. package/src/app/routes/_authenticated/_stock-locations/components/stock-location-bulk-actions.tsx +58 -0
  191. package/src/app/routes/_authenticated/_stock-locations/stock-locations.graphql.ts +26 -1
  192. package/src/app/routes/_authenticated/_stock-locations/stock-locations.tsx +25 -6
  193. package/src/app/routes/_authenticated/_stock-locations/stock-locations_.$id.tsx +16 -12
  194. package/src/app/routes/_authenticated/_system/components/payload-dialog.tsx +5 -5
  195. package/src/app/routes/_authenticated/_system/healthchecks.tsx +5 -5
  196. package/src/app/routes/_authenticated/_system/job-queue.graphql.ts +12 -1
  197. package/src/app/routes/_authenticated/_system/job-queue.tsx +110 -11
  198. package/src/app/routes/_authenticated/_system/scheduled-tasks.tsx +34 -28
  199. package/src/app/routes/_authenticated/_tax-categories/components/tax-category-bulk-actions.tsx +15 -0
  200. package/src/app/routes/_authenticated/_tax-categories/tax-categories.graphql.ts +11 -2
  201. package/src/app/routes/_authenticated/_tax-categories/tax-categories.tsx +14 -7
  202. package/src/app/routes/_authenticated/_tax-categories/tax-categories_.$id.tsx +20 -16
  203. package/src/app/routes/_authenticated/_tax-rates/components/tax-rate-bulk-actions.tsx +15 -0
  204. package/src/app/routes/_authenticated/_tax-rates/tax-rates.graphql.ts +11 -2
  205. package/src/app/routes/_authenticated/_tax-rates/tax-rates.tsx +15 -8
  206. package/src/app/routes/_authenticated/_tax-rates/tax-rates_.$id.tsx +22 -18
  207. package/src/app/routes/_authenticated/_zones/components/zone-bulk-actions.tsx +15 -0
  208. package/src/app/routes/_authenticated/_zones/components/zone-countries-sheet.tsx +4 -4
  209. package/src/app/routes/_authenticated/_zones/components/zone-countries-table.tsx +12 -15
  210. package/src/app/routes/_authenticated/_zones/zones.graphql.ts +11 -2
  211. package/src/app/routes/_authenticated/_zones/zones.tsx +13 -6
  212. package/src/app/routes/_authenticated/_zones/zones_.$id.tsx +18 -14
  213. package/src/app/routes/_authenticated/index.tsx +6 -6
  214. package/src/app/routes/_authenticated.tsx +4 -4
  215. package/src/app/routes/login.tsx +2 -2
  216. package/src/app/styles.css +5 -2
  217. package/src/lib/components/data-display/boolean.tsx +1 -1
  218. package/src/lib/components/data-display/date-time.tsx +9 -3
  219. package/src/lib/components/data-display/json.tsx +1 -1
  220. package/src/lib/components/data-display/money.tsx +2 -3
  221. package/src/lib/components/data-input/affixed-input.tsx +3 -8
  222. package/src/lib/components/data-input/combination-mode-input.tsx +52 -0
  223. package/src/lib/components/data-input/configurable-operation-list-input.tsx +433 -0
  224. package/src/lib/components/data-input/custom-field-list-input.tsx +297 -0
  225. package/src/lib/components/data-input/customer-group-input.tsx +2 -2
  226. package/src/lib/components/data-input/datetime-input.tsx +132 -146
  227. package/src/lib/components/data-input/default-relation-input.tsx +599 -0
  228. package/src/lib/components/data-input/facet-value-input.tsx +30 -22
  229. package/src/lib/components/data-input/index.ts +17 -0
  230. package/src/lib/components/data-input/money-input.tsx +5 -12
  231. package/src/lib/components/data-input/product-multi-selector.tsx +426 -0
  232. package/src/lib/components/data-input/relation-input.tsx +164 -0
  233. package/src/lib/components/data-input/relation-selector.tsx +476 -0
  234. package/src/lib/components/data-input/{richt-text-input.tsx → rich-text-input.tsx} +15 -9
  235. package/src/lib/components/data-input/select-with-options.tsx +84 -0
  236. package/src/lib/components/data-input/struct-form-input.tsx +324 -0
  237. package/src/lib/components/data-table/add-filter-menu.tsx +9 -18
  238. package/src/lib/components/data-table/data-table-bulk-action-item.tsx +101 -0
  239. package/src/lib/components/data-table/data-table-bulk-actions.tsx +108 -0
  240. package/src/lib/components/data-table/data-table-column-header.tsx +4 -22
  241. package/src/lib/components/data-table/data-table-faceted-filter.tsx +8 -8
  242. package/src/lib/components/data-table/data-table-filter-badge.tsx +16 -8
  243. package/src/lib/components/data-table/data-table-filter-dialog.tsx +8 -8
  244. package/src/lib/components/data-table/data-table-pagination.tsx +4 -4
  245. package/src/lib/components/data-table/data-table-utils.ts +34 -0
  246. package/src/lib/components/data-table/data-table-view-options.tsx +27 -23
  247. package/src/lib/components/data-table/data-table.tsx +90 -43
  248. package/src/lib/components/data-table/filters/data-table-boolean-filter.tsx +11 -8
  249. package/src/lib/components/data-table/filters/data-table-datetime-filter.tsx +14 -23
  250. package/src/lib/components/data-table/filters/data-table-id-filter.tsx +15 -10
  251. package/src/lib/components/data-table/filters/data-table-number-filter.tsx +18 -17
  252. package/src/lib/components/data-table/filters/data-table-string-filter.tsx +29 -12
  253. package/src/lib/components/data-table/human-readable-operator.tsx +3 -3
  254. package/src/lib/components/data-table/refresh-button.tsx +30 -15
  255. package/src/lib/components/data-table/use-generated-columns.tsx +322 -0
  256. package/src/lib/components/labeled-data.tsx +21 -0
  257. package/src/lib/components/layout/app-layout.tsx +8 -13
  258. package/src/lib/components/layout/app-sidebar.tsx +5 -5
  259. package/src/lib/components/layout/channel-switcher.tsx +171 -62
  260. package/src/lib/components/layout/content-language-selector.tsx +16 -10
  261. package/src/lib/components/layout/dev-mode-indicator.tsx +18 -0
  262. package/src/lib/components/layout/generated-breadcrumbs.tsx +1 -1
  263. package/src/lib/components/layout/language-dialog.tsx +7 -12
  264. package/src/lib/components/layout/manage-languages-dialog.tsx +405 -0
  265. package/src/lib/components/layout/nav-item-wrapper.tsx +107 -0
  266. package/src/lib/components/layout/nav-main.tsx +200 -111
  267. package/src/lib/components/layout/nav-projects.tsx +2 -2
  268. package/src/lib/components/layout/nav-user.tsx +7 -7
  269. package/src/lib/components/layout/prerelease-popup.tsx +1 -1
  270. package/src/lib/components/login/login-form.tsx +85 -50
  271. package/src/lib/components/shared/alerts.tsx +3 -3
  272. package/src/lib/components/shared/animated-number.tsx +2 -2
  273. package/src/lib/components/shared/asset/asset-bulk-actions.tsx +109 -0
  274. package/src/lib/components/shared/asset/asset-focal-point-editor.tsx +29 -19
  275. package/src/lib/components/shared/asset/asset-gallery.tsx +25 -20
  276. package/src/lib/components/shared/asset/asset-picker-dialog.tsx +63 -66
  277. package/src/lib/components/shared/asset/asset-preview-dialog.tsx +3 -7
  278. package/src/lib/components/shared/asset/asset-preview-selector.tsx +4 -6
  279. package/src/lib/components/shared/asset/asset-preview.tsx +7 -21
  280. package/src/lib/components/shared/asset/asset-properties.tsx +7 -9
  281. package/src/lib/components/shared/asset/focal-point-control.tsx +5 -13
  282. package/src/lib/components/shared/assign-to-channel-bulk-action.tsx +71 -0
  283. package/src/lib/components/shared/assign-to-channel-dialog.tsx +155 -0
  284. package/src/lib/components/shared/assigned-facet-values.tsx +1 -5
  285. package/src/lib/components/shared/channel-code-label.tsx +3 -4
  286. package/src/lib/components/shared/channel-selector.tsx +6 -6
  287. package/src/lib/components/shared/configurable-operation-arg-input.tsx +367 -23
  288. package/src/lib/components/shared/configurable-operation-input.tsx +87 -48
  289. package/src/lib/components/shared/configurable-operation-multi-selector.tsx +260 -0
  290. package/src/lib/components/shared/configurable-operation-selector.tsx +156 -0
  291. package/src/lib/components/shared/confirmation-dialog.tsx +2 -2
  292. package/src/lib/components/shared/copyable-text.tsx +3 -4
  293. package/src/lib/components/shared/country-selector.tsx +21 -18
  294. package/src/lib/components/shared/currency-selector.tsx +5 -5
  295. package/src/lib/components/shared/custom-fields-form.tsx +423 -50
  296. package/src/lib/components/shared/customer-address-form.tsx +18 -13
  297. package/src/lib/components/shared/customer-group-selector.tsx +6 -6
  298. package/src/lib/components/shared/customer-selector.tsx +24 -18
  299. package/src/lib/components/shared/detail-page-button.tsx +45 -1
  300. package/src/lib/components/shared/entity-assets.tsx +33 -34
  301. package/src/lib/components/shared/error-page.tsx +6 -6
  302. package/src/lib/components/shared/facet-value-chip.tsx +12 -5
  303. package/src/lib/components/shared/facet-value-selector.tsx +64 -63
  304. package/src/lib/components/shared/form-field-wrapper.tsx +47 -24
  305. package/src/lib/components/shared/history-timeline/history-entry-date.tsx +37 -0
  306. package/src/lib/components/shared/history-timeline/history-entry.tsx +146 -70
  307. package/src/lib/components/shared/history-timeline/history-note-checkbox.tsx +3 -3
  308. package/src/lib/components/shared/history-timeline/history-note-editor.tsx +4 -4
  309. package/src/lib/components/shared/history-timeline/history-note-input.tsx +7 -7
  310. package/src/lib/components/shared/history-timeline/history-timeline.tsx +8 -48
  311. package/src/lib/components/shared/language-selector.tsx +5 -5
  312. package/src/lib/components/shared/logo-mark.tsx +2 -2
  313. package/src/lib/components/shared/multi-select.tsx +6 -6
  314. package/src/lib/components/shared/navigation-confirmation.tsx +24 -9
  315. package/src/lib/components/shared/option-value-input.tsx +18 -16
  316. package/src/lib/components/shared/paginated-list-data-table.tsx +35 -230
  317. package/src/lib/components/shared/permission-guard.tsx +4 -4
  318. package/src/lib/components/shared/product-variant-selector.tsx +59 -34
  319. package/src/lib/components/shared/remove-from-channel-bulk-action.tsx +90 -0
  320. package/src/lib/components/shared/role-code-label.tsx +10 -6
  321. package/src/lib/components/shared/role-selector.tsx +4 -4
  322. package/src/lib/components/shared/seller-selector.tsx +21 -17
  323. package/src/lib/components/shared/stock-level-label.tsx +5 -5
  324. package/src/lib/components/shared/tax-category-selector.tsx +5 -5
  325. package/src/lib/components/shared/translatable-form-field.tsx +46 -23
  326. package/src/lib/components/shared/vendure-image.tsx +31 -2
  327. package/src/lib/components/shared/zone-selector.tsx +5 -6
  328. package/src/lib/components/ui/accordion.tsx +3 -3
  329. package/src/lib/components/ui/alert-dialog.tsx +10 -10
  330. package/src/lib/components/ui/alert.tsx +3 -3
  331. package/src/lib/components/ui/aspect-ratio.tsx +9 -0
  332. package/src/lib/components/ui/badge.tsx +2 -2
  333. package/src/lib/components/ui/breadcrumb.tsx +4 -4
  334. package/src/lib/components/ui/button.tsx +10 -3
  335. package/src/lib/components/ui/calendar.tsx +392 -459
  336. package/src/lib/components/ui/card.tsx +2 -2
  337. package/src/lib/components/ui/carousel.tsx +241 -0
  338. package/src/lib/components/ui/chart.tsx +351 -0
  339. package/src/lib/components/ui/checkbox.tsx +2 -2
  340. package/src/lib/components/ui/command.tsx +12 -6
  341. package/src/lib/components/ui/context-menu.tsx +252 -0
  342. package/src/lib/components/ui/dialog.tsx +2 -2
  343. package/src/lib/components/ui/drawer.tsx +133 -0
  344. package/src/lib/components/ui/dropdown-menu.tsx +7 -7
  345. package/src/lib/components/ui/form.tsx +8 -8
  346. package/src/lib/components/ui/hover-card.tsx +3 -3
  347. package/src/lib/components/ui/input-otp.tsx +77 -0
  348. package/src/lib/components/ui/input.tsx +1 -1
  349. package/src/lib/components/ui/label.tsx +2 -2
  350. package/src/lib/components/ui/menubar.tsx +274 -0
  351. package/src/lib/components/ui/navigation-menu.tsx +168 -0
  352. package/src/lib/components/ui/pagination.tsx +87 -108
  353. package/src/lib/components/ui/popover.tsx +3 -3
  354. package/src/lib/components/ui/progress.tsx +29 -0
  355. package/src/lib/components/ui/radio-group.tsx +45 -0
  356. package/src/lib/components/ui/resizable.tsx +54 -0
  357. package/src/lib/components/ui/scroll-area.tsx +2 -2
  358. package/src/lib/components/ui/select.tsx +151 -129
  359. package/src/lib/components/ui/separator.tsx +2 -2
  360. package/src/lib/components/ui/sheet.tsx +5 -5
  361. package/src/lib/components/ui/sidebar.tsx +10 -10
  362. package/src/lib/components/ui/skeleton.tsx +1 -1
  363. package/src/lib/components/ui/slider.tsx +63 -0
  364. package/src/lib/components/ui/switch.tsx +2 -2
  365. package/src/lib/components/ui/table.tsx +2 -2
  366. package/src/lib/components/ui/tabs.tsx +3 -3
  367. package/src/lib/components/ui/textarea.tsx +1 -1
  368. package/src/lib/components/ui/toggle-group.tsx +73 -0
  369. package/src/lib/components/ui/toggle.tsx +45 -0
  370. package/src/lib/components/ui/tooltip.tsx +3 -3
  371. package/src/lib/framework/alert/alert-extensions.tsx +2 -3
  372. package/src/lib/framework/alert/alert-item.tsx +5 -3
  373. package/src/lib/framework/component-registry/component-registry.tsx +33 -47
  374. package/src/lib/framework/component-registry/dynamic-component.tsx +3 -3
  375. package/src/lib/framework/dashboard-widget/base-widget.tsx +5 -13
  376. package/src/lib/framework/dashboard-widget/latest-orders-widget/index.tsx +8 -8
  377. package/src/lib/framework/dashboard-widget/latest-orders-widget/latest-orders-widget.graphql.ts +1 -1
  378. package/src/lib/framework/dashboard-widget/metrics-widget/index.tsx +7 -8
  379. package/src/lib/framework/dashboard-widget/metrics-widget/metrics-widget.graphql.ts +1 -1
  380. package/src/lib/framework/dashboard-widget/orders-summary/index.tsx +7 -8
  381. package/src/lib/framework/dashboard-widget/orders-summary/order-summary-widget.graphql.ts +1 -1
  382. package/src/lib/framework/dashboard-widget/widget-extensions.tsx +1 -1
  383. package/src/lib/framework/data-table/data-table-extensions.ts +35 -0
  384. package/src/lib/framework/defaults.ts +5 -11
  385. package/src/lib/framework/document-extension/extend-detail-form-query.ts +50 -0
  386. package/src/lib/framework/document-extension/extend-document.spec.ts +884 -0
  387. package/src/lib/framework/document-extension/extend-document.ts +159 -0
  388. package/src/lib/framework/document-introspection/add-custom-fields.ts +50 -2
  389. package/src/lib/framework/document-introspection/get-document-structure.spec.ts +321 -2
  390. package/src/lib/framework/document-introspection/get-document-structure.ts +187 -36
  391. package/src/lib/framework/document-introspection/hooks.ts +4 -1
  392. package/src/lib/framework/extension-api/define-dashboard-extension.ts +35 -49
  393. package/src/lib/framework/extension-api/display-component-extensions.tsx +69 -0
  394. package/src/lib/framework/extension-api/extension-api-types.ts +34 -98
  395. package/src/lib/framework/extension-api/input-component-extensions.tsx +73 -0
  396. package/src/lib/framework/extension-api/logic/alerts.ts +10 -0
  397. package/src/lib/framework/extension-api/logic/data-table.ts +60 -0
  398. package/src/lib/framework/extension-api/logic/detail-forms.ts +48 -0
  399. package/src/lib/framework/extension-api/logic/form-components.ts +13 -0
  400. package/src/lib/framework/extension-api/logic/index.ts +9 -0
  401. package/src/lib/framework/extension-api/logic/layout.ts +22 -0
  402. package/src/lib/framework/extension-api/logic/login.ts +17 -0
  403. package/src/lib/framework/extension-api/logic/navigation.ts +38 -0
  404. package/src/lib/framework/extension-api/logic/widgets.ts +10 -0
  405. package/src/lib/framework/extension-api/types/alerts.ts +54 -0
  406. package/src/lib/framework/extension-api/types/data-table.ts +96 -0
  407. package/src/lib/framework/extension-api/types/detail-forms.ts +94 -0
  408. package/src/lib/framework/extension-api/types/form-components.ts +43 -0
  409. package/src/lib/framework/extension-api/types/index.ts +9 -0
  410. package/src/lib/framework/extension-api/types/layout.ts +90 -0
  411. package/src/lib/framework/extension-api/types/login.ts +96 -0
  412. package/src/lib/framework/extension-api/types/navigation.ts +76 -0
  413. package/src/lib/framework/extension-api/types/widgets.ts +93 -0
  414. package/src/lib/framework/extension-api/use-dashboard-extensions.ts +2 -1
  415. package/src/lib/framework/extension-api/use-login-extensions.ts +26 -0
  416. package/src/lib/framework/form-engine/custom-form-component-extensions.ts +38 -0
  417. package/src/lib/framework/form-engine/custom-form-component.tsx +33 -0
  418. package/src/lib/framework/form-engine/form-schema-tools.spec.ts +472 -0
  419. package/src/lib/framework/form-engine/form-schema-tools.ts +341 -6
  420. package/src/lib/framework/form-engine/overridden-form-component.tsx +51 -0
  421. package/src/lib/framework/form-engine/use-generated-form.tsx +82 -24
  422. package/src/lib/framework/form-engine/utils.spec.ts +37 -0
  423. package/src/lib/framework/form-engine/utils.ts +99 -0
  424. package/src/lib/framework/layout-engine/dev-mode-button.tsx +24 -0
  425. package/src/lib/framework/layout-engine/layout-extensions.ts +1 -4
  426. package/src/lib/framework/layout-engine/location-wrapper.tsx +98 -72
  427. package/src/lib/framework/layout-engine/page-block-provider.tsx +6 -0
  428. package/src/lib/framework/layout-engine/page-layout.tsx +135 -58
  429. package/src/lib/framework/page/detail-page-route-loader.tsx +26 -7
  430. package/src/lib/framework/page/detail-page.tsx +94 -37
  431. package/src/lib/framework/page/list-page.tsx +18 -11
  432. package/src/lib/framework/page/use-detail-page.ts +47 -13
  433. package/src/lib/framework/page/use-extended-router.tsx +4 -5
  434. package/src/lib/framework/registry/global-registry.ts +4 -0
  435. package/src/lib/framework/registry/registry-types.ts +17 -5
  436. package/src/lib/graphql/api.ts +25 -3
  437. package/src/lib/graphql/common-operations.ts +18 -0
  438. package/src/lib/graphql/{fragments.tsx → fragments.ts} +1 -2
  439. package/src/lib/graphql/graphql-env.d.ts +27 -24
  440. package/src/lib/graphql/settings-store-operations.ts +17 -0
  441. package/src/lib/hooks/use-auth.tsx +1 -1
  442. package/src/lib/hooks/use-channel.ts +1 -1
  443. package/src/lib/hooks/use-extended-detail-query.ts +37 -0
  444. package/src/lib/hooks/use-extended-list-query.ts +75 -0
  445. package/src/lib/hooks/use-floating-bulk-actions.ts +82 -0
  446. package/src/lib/hooks/use-grouped-permissions.ts +3 -2
  447. package/src/lib/hooks/use-local-format.ts +20 -5
  448. package/src/lib/hooks/use-page-block.tsx +18 -0
  449. package/src/lib/hooks/use-page.tsx +2 -2
  450. package/src/lib/hooks/use-permissions.ts +3 -2
  451. package/src/lib/hooks/use-server-config.ts +1 -1
  452. package/src/lib/hooks/use-theme.ts +1 -1
  453. package/src/lib/hooks/use-user-settings.tsx +1 -1
  454. package/src/lib/index.ts +85 -7
  455. package/src/lib/lib/trans.tsx +3 -3
  456. package/src/lib/lib/utils.ts +52 -1
  457. package/src/lib/providers/auth.tsx +37 -14
  458. package/src/lib/providers/channel-provider.tsx +17 -15
  459. package/src/lib/providers/server-config.tsx +13 -11
  460. package/src/lib/providers/theme-provider.tsx +2 -3
  461. package/src/lib/providers/user-settings.tsx +78 -3
  462. package/src/lib/virtual.d.ts +26 -2
  463. package/src/vite-env.d.ts +2 -0
  464. package/vite/tests/barrel-exports.spec.ts +30 -0
  465. package/vite/tests/fixtures-barrel-exports/my-plugin/index.ts +1 -0
  466. package/vite/tests/fixtures-barrel-exports/my-plugin/src/my.plugin.ts +8 -0
  467. package/vite/tests/fixtures-barrel-exports/package.json +6 -0
  468. package/vite/tests/fixtures-barrel-exports/vendure-config.ts +19 -0
  469. package/vite/tests/fixtures-npm-plugin/fake_node_modules/test-plugin/index.js +20 -0
  470. package/vite/tests/fixtures-npm-plugin/fake_node_modules/test-plugin/package.json +8 -0
  471. package/vite/tests/fixtures-npm-plugin/package.json +6 -0
  472. package/vite/tests/fixtures-npm-plugin/vendure-config.ts +18 -0
  473. package/vite/tests/fixtures-path-alias/js-aliased/index.ts +1 -0
  474. package/vite/tests/fixtures-path-alias/js-aliased/src/js-aliased.plugin.ts +8 -0
  475. package/vite/tests/fixtures-path-alias/package.json +6 -0
  476. package/vite/tests/fixtures-path-alias/star-aliased/index.ts +1 -0
  477. package/vite/tests/fixtures-path-alias/star-aliased/src/star-aliased.plugin.ts +8 -0
  478. package/vite/tests/fixtures-path-alias/ts-aliased/index.ts +1 -0
  479. package/vite/tests/fixtures-path-alias/ts-aliased/src/ts-aliased.plugin.ts +8 -0
  480. package/vite/tests/fixtures-path-alias/vendure-config.ts +20 -0
  481. package/vite/tests/npm-plugin.spec.ts +46 -0
  482. package/vite/tests/path-alias.spec.ts +61 -0
  483. package/vite/tests/tsconfig.json +21 -0
  484. package/vite/types.ts +44 -0
  485. package/vite/utils/ast-utils.spec.ts +1 -80
  486. package/vite/utils/ast-utils.ts +0 -86
  487. package/vite/utils/compiler.ts +244 -0
  488. package/vite/utils/config-loader.ts +0 -445
  489. package/vite/utils/logger.ts +43 -0
  490. package/vite/utils/plugin-discovery.ts +494 -0
  491. package/vite/utils/tsconfig-utils.ts +79 -0
  492. package/vite/utils/ui-config.ts +30 -42
  493. package/vite/vite-plugin-config-loader.ts +25 -17
  494. package/vite/vite-plugin-config.ts +6 -7
  495. package/vite/vite-plugin-dashboard-metadata.ts +27 -16
  496. package/vite/vite-plugin-tailwind-source.ts +81 -0
  497. package/vite/vite-plugin-theme.ts +69 -69
  498. package/vite/vite-plugin-ui-config.ts +119 -17
  499. package/vite/vite-plugin-vendure-dashboard.ts +60 -16
  500. package/dist/plugin/utils/ast-utils.js +0 -96
  501. package/dist/plugin/utils/ast-utils.spec.js +0 -120
  502. package/dist/plugin/utils/config-loader.d.ts +0 -52
  503. package/dist/plugin/utils/config-loader.js +0 -343
  504. package/dist/plugin/utils/ui-config.d.ts +0 -3
  505. package/dist/plugin/utils/ui-config.js +0 -34
  506. package/dist/plugin/vite-plugin-theme.js +0 -130
  507. package/dist/plugin/vite-plugin-ui-config.d.ts +0 -15
  508. package/dist/plugin/vite-plugin-vendure-dashboard.d.ts +0 -44
  509. package/src/lib/components/shared/rich-text-editor.tsx +0 -0
  510. package/src/lib/framework/alert/types.ts +0 -13
  511. package/src/lib/framework/dashboard-widget/types.ts +0 -22
  512. /package/dist/{plugin/utils/ast-utils.spec.d.ts → vite/types.js} +0 -0
  513. /package/dist/{plugin → vite}/utils/schema-generator.d.ts +0 -0
  514. /package/dist/{plugin → vite}/utils/schema-generator.js +0 -0
  515. /package/dist/{plugin → vite}/vite-plugin-admin-api-schema.d.ts +0 -0
  516. /package/dist/{plugin → vite}/vite-plugin-admin-api-schema.js +0 -0
  517. /package/dist/{plugin → vite}/vite-plugin-config.d.ts +0 -0
  518. /package/dist/{plugin → vite}/vite-plugin-gql-tada.d.ts +0 -0
  519. /package/dist/{plugin → vite}/vite-plugin-gql-tada.js +0 -0
  520. /package/dist/{plugin → vite}/vite-plugin-theme.d.ts +0 -0
  521. /package/dist/{plugin → vite}/vite-plugin-transform-index.d.ts +0 -0
  522. /package/dist/{plugin → vite}/vite-plugin-transform-index.js +0 -0
  523. /package/src/lib/components/data-table/{data-table-types.ts → types.ts} +0 -0
@@ -1,5 +1,5 @@
1
1
  import type { TypedDocumentNode } from '@graphql-typed-document-node/core';
2
- import { VariablesOf } from 'gql.tada';
2
+ import { ResultOf, VariablesOf } from 'gql.tada';
3
3
  import {
4
4
  DocumentNode,
5
5
  FieldNode,
@@ -32,33 +32,165 @@ export interface FieldInfo {
32
32
  */
33
33
  export function getListQueryFields(documentNode: DocumentNode): FieldInfo[] {
34
34
  const fields: FieldInfo[] = [];
35
- const fragments: Record<string, FragmentDefinitionNode> = {};
35
+ const fragments = collectFragments(documentNode);
36
+ const operationDefinition = findQueryOperation(documentNode);
37
+
38
+ for (const query of operationDefinition.selectionSet.selections) {
39
+ if (query.kind === 'Field') {
40
+ const queryField = query;
41
+ const fieldInfo = getQueryInfo(queryField.name.value);
42
+ if (fieldInfo.isPaginatedList) {
43
+ processPaginatedList(queryField, fieldInfo, fields, fragments);
44
+ } else if (queryField.selectionSet) {
45
+ // Check for nested paginated lists
46
+ findNestedPaginatedLists(queryField, fieldInfo.type, fields, fragments);
47
+ }
48
+ }
49
+ }
50
+
51
+ return fields;
52
+ }
53
+
54
+ // Utility type to get all valid paths into a type
55
+ export type PathTo<T> = T extends object
56
+ ? {
57
+ [K in keyof T & (string | number)]: [K] | [K, ...PathTo<T[K]>];
58
+ }[keyof T & (string | number)]
59
+ : [];
36
60
 
37
- // Collect all fragment definitions
61
+ /**
62
+ * @description
63
+ * This function is used to get the FieldInfo for the fields in the path of a DocumentNode.
64
+ *
65
+ * For example, in the following query:
66
+ *
67
+ * ```graphql
68
+ * query {
69
+ * product {
70
+ * id
71
+ * name
72
+ * variants {
73
+ * id
74
+ * name
75
+ * }
76
+ * }
77
+ * }
78
+ * ```
79
+ *
80
+ * The path `['product', 'variants']` will return the FieldInfo for the `variants` field,
81
+ * namely the `id` and `name` fields.
82
+ */
83
+ export function getFieldsFromDocumentNode<
84
+ T extends TypedDocumentNode<any, any>,
85
+ P extends PathTo<ResultOf<T>>,
86
+ >(documentNode: T, path: P): FieldInfo[] {
87
+ const fragments = collectFragments(documentNode);
88
+ const operationDefinition = findQueryOperation(documentNode);
89
+
90
+ // Navigate to the target path
91
+ let currentSelections = operationDefinition.selectionSet.selections;
92
+ let currentType = 'Query';
93
+
94
+ for (let i = 0; i < path.length; i++) {
95
+ const pathSegment = path[i] as string;
96
+ const { fieldNode } = findFieldInSelections(
97
+ currentSelections,
98
+ pathSegment,
99
+ fragments,
100
+ path.slice(0, i + 1),
101
+ );
102
+
103
+ const fieldInfo = getObjectFieldInfo(currentType, pathSegment);
104
+ if (!fieldInfo) {
105
+ throw new Error(`Could not determine type for field "${pathSegment}"`);
106
+ }
107
+
108
+ // If this is the last path segment, collect the fields
109
+ if (i === path.length - 1) {
110
+ return collectFieldsFromNode(fieldNode, fieldInfo.type, fragments);
111
+ }
112
+
113
+ // Continue navigating deeper
114
+ if (!fieldNode.selectionSet) {
115
+ throw new Error(`Field "${pathSegment}" has no selection set but path continues`);
116
+ }
117
+ currentSelections = fieldNode.selectionSet.selections;
118
+ currentType = fieldInfo.type;
119
+ }
120
+
121
+ return [];
122
+ }
123
+
124
+ function collectFragments(documentNode: DocumentNode): Record<string, FragmentDefinitionNode> {
125
+ const fragments: Record<string, FragmentDefinitionNode> = {};
38
126
  documentNode.definitions.forEach(def => {
39
127
  if (def.kind === 'FragmentDefinition') {
40
128
  fragments[def.name.value] = def;
41
129
  }
42
130
  });
131
+ return fragments;
132
+ }
43
133
 
134
+ function findQueryOperation(documentNode: DocumentNode): OperationDefinitionNode {
44
135
  const operationDefinition = documentNode.definitions.find(
45
136
  (def): def is OperationDefinitionNode =>
46
137
  def.kind === 'OperationDefinition' && def.operation === 'query',
47
138
  );
139
+ if (!operationDefinition) {
140
+ throw new Error('Could not find query operation definition');
141
+ }
142
+ return operationDefinition;
143
+ }
48
144
 
49
- for (const query of operationDefinition?.selectionSet.selections ?? []) {
50
- if (query.kind === 'Field') {
51
- const queryField = query;
52
- const fieldInfo = getQueryInfo(queryField.name.value);
53
- if (fieldInfo.isPaginatedList) {
54
- processPaginatedList(queryField, fieldInfo, fields, fragments);
55
- } else if (queryField.selectionSet) {
56
- // Check for nested paginated lists
57
- findNestedPaginatedLists(queryField, fieldInfo.type, fields, fragments);
145
+ function findMutationOperation(documentNode: DocumentNode): OperationDefinitionNode {
146
+ const operationDefinition = documentNode.definitions.find(
147
+ (def): def is OperationDefinitionNode =>
148
+ def.kind === 'OperationDefinition' && def.operation === 'mutation',
149
+ );
150
+ if (!operationDefinition) {
151
+ throw new Error('Could not find mutation operation definition');
152
+ }
153
+ return operationDefinition;
154
+ }
155
+
156
+ function findFieldInSelections(
157
+ selections: readonly any[],
158
+ pathSegment: string,
159
+ fragments: Record<string, FragmentDefinitionNode>,
160
+ currentPath: string[] = [],
161
+ ): { fieldNode: FieldNode; fragmentSelections: readonly any[] } {
162
+ for (const selection of selections) {
163
+ if (selection.kind === 'Field' && selection.name.value === pathSegment) {
164
+ return { fieldNode: selection, fragmentSelections: [] };
165
+ } else if (selection.kind === 'FragmentSpread') {
166
+ const fragment = fragments[selection.name.value];
167
+ if (fragment) {
168
+ const fragmentField = fragment.selectionSet.selections.find(
169
+ s => s.kind === 'Field' && s.name.value === pathSegment,
170
+ ) as FieldNode;
171
+ if (fragmentField) {
172
+ return { fieldNode: fragmentField, fragmentSelections: fragment.selectionSet.selections };
173
+ }
58
174
  }
59
175
  }
60
176
  }
177
+ const pathString = currentPath.join('.');
178
+ throw new Error(`Field "${pathSegment}" not found at path ${pathString}`);
179
+ }
61
180
 
181
+ function collectFieldsFromNode(
182
+ fieldNode: FieldNode,
183
+ typeName: string,
184
+ fragments: Record<string, FragmentDefinitionNode>,
185
+ ): FieldInfo[] {
186
+ const fields: FieldInfo[] = [];
187
+ if (fieldNode.selectionSet) {
188
+ for (const selection of fieldNode.selectionSet.selections) {
189
+ if (selection.kind === 'Field' || selection.kind === 'FragmentSpread') {
190
+ collectFields(typeName, selection, fields, fragments);
191
+ }
192
+ }
193
+ }
62
194
  return fields;
63
195
  }
64
196
 
@@ -199,6 +331,20 @@ function unwrapVariableDefinitionType(type: TypeNode): NamedTypeNode {
199
331
  return type;
200
332
  }
201
333
 
334
+ /**
335
+ * @description
336
+ * Helper function to get the first field selection from a query operation definition.
337
+ */
338
+ function getFirstQueryField(documentNode: DocumentNode): FieldNode {
339
+ const operationDefinition = findQueryOperation(documentNode);
340
+ const firstSelection = operationDefinition.selectionSet.selections[0];
341
+ if (firstSelection?.kind === 'Field') {
342
+ return firstSelection;
343
+ } else {
344
+ throw new Error('Could not determine query field');
345
+ }
346
+ }
347
+
202
348
  /**
203
349
  * @description
204
350
  * This function is used to get the name of the query from a DocumentNode.
@@ -216,16 +362,32 @@ function unwrapVariableDefinitionType(type: TypeNode): NamedTypeNode {
216
362
  * The query name is `product`.
217
363
  */
218
364
  export function getQueryName(documentNode: DocumentNode): string {
219
- const operationDefinition = documentNode.definitions.find(
220
- (def): def is OperationDefinitionNode =>
221
- def.kind === 'OperationDefinition' && def.operation === 'query',
222
- );
223
- const firstSelection = operationDefinition?.selectionSet.selections[0];
224
- if (firstSelection?.kind === 'Field') {
225
- return firstSelection.name.value;
226
- } else {
227
- throw new Error('Could not determine query name');
228
- }
365
+ const firstField = getFirstQueryField(documentNode);
366
+ return firstField.name.value;
367
+ }
368
+
369
+ /**
370
+ * @description
371
+ * This function is used to get the entity name from a DocumentNode.
372
+ *
373
+ * For example, in the following query:
374
+ *
375
+ * ```graphql
376
+ * query ProductDetail($id: ID!) {
377
+ * product(id: $id) {
378
+ * ...ProductDetail
379
+ * }
380
+ * }
381
+ * ```
382
+ *
383
+ * The entity name is `Product`.
384
+ */
385
+ export function getEntityName(documentNode: DocumentNode): string {
386
+ const firstField = getFirstQueryField(documentNode);
387
+ // Get the return type from the field definition
388
+ const fieldName = firstField.name.value;
389
+ const queryInfo = getQueryInfo(fieldName);
390
+ return queryInfo.type;
229
391
  }
230
392
 
231
393
  /**
@@ -272,15 +434,7 @@ export function getObjectPathToPaginatedList(
272
434
  documentNode: DocumentNode,
273
435
  currentPath: string[] = [],
274
436
  ): string[] {
275
- // get the query OperationDefinition
276
- const operationDefinition = documentNode.definitions.find(
277
- (def): def is OperationDefinitionNode =>
278
- def.kind === 'OperationDefinition' && def.operation === 'query',
279
- );
280
- if (!operationDefinition) {
281
- throw new Error('Could not find query operation definition');
282
- }
283
-
437
+ const operationDefinition = findQueryOperation(documentNode);
284
438
  return findPaginatedListPath(operationDefinition.selectionSet, 'Query', currentPath);
285
439
  }
286
440
 
@@ -332,11 +486,8 @@ function findPaginatedListPath(
332
486
  * The mutation name is `createProduct`.
333
487
  */
334
488
  export function getMutationName(documentNode: DocumentNode): string {
335
- const operationDefinition = documentNode.definitions.find(
336
- (def): def is OperationDefinitionNode =>
337
- def.kind === 'OperationDefinition' && def.operation === 'mutation',
338
- );
339
- const firstSelection = operationDefinition?.selectionSet.selections[0];
489
+ const operationDefinition = findMutationOperation(documentNode);
490
+ const firstSelection = operationDefinition.selectionSet.selections[0];
340
491
  if (firstSelection?.kind === 'Field') {
341
492
  return firstSelection.name.value;
342
493
  } else {
@@ -1,4 +1,7 @@
1
- import { FieldInfo, getListQueryFields } from '@/framework/document-introspection/get-document-structure.js';
1
+ import {
2
+ FieldInfo,
3
+ getListQueryFields,
4
+ } from '@/vdb/framework/document-introspection/get-document-structure.js';
2
5
  import { DocumentNode } from 'graphql';
3
6
  import { useMemo } from 'react';
4
7
 
@@ -1,13 +1,16 @@
1
- import { registerDashboardWidget } from '../dashboard-widget/widget-extensions.js';
2
- import {
3
- registerDashboardActionBarItem,
4
- registerDashboardPageBlock,
5
- } from '../layout-engine/layout-extensions.js';
6
- import { addNavMenuItem, addNavMenuSection, NavMenuItem } from '../nav-menu/nav-menu-extensions.js';
7
- import { registerRoute } from '../page/page-api.js';
8
1
  import { globalRegistry } from '../registry/global-registry.js';
9
2
 
10
3
  import { DashboardExtension } from './extension-api-types.js';
4
+ import {
5
+ registerAlertExtensions,
6
+ registerDataTableExtensions,
7
+ registerDetailFormExtensions,
8
+ registerFormComponentExtensions,
9
+ registerLayoutExtensions,
10
+ registerLoginExtensions,
11
+ registerNavigationExtensions,
12
+ registerWidgetExtensions,
13
+ } from './logic/index.js';
11
14
 
12
15
  globalRegistry.register('extensionSourceChangeCallbacks', new Set<() => void>());
13
16
  globalRegistry.register('registerDashboardExtensionCallbacks', new Set<() => void>());
@@ -34,48 +37,31 @@ export function executeDashboardExtensionCallbacks() {
34
37
  */
35
38
  export function defineDashboardExtension(extension: DashboardExtension) {
36
39
  globalRegistry.get('registerDashboardExtensionCallbacks').add(() => {
37
- if (extension.navSections) {
38
- for (const section of extension.navSections) {
39
- addNavMenuSection({
40
- ...section,
41
- placement: 'top',
42
- order: section.order ?? 999,
43
- items: [],
44
- });
45
- }
46
- }
47
- if (extension.routes) {
48
- for (const route of extension.routes) {
49
- if (route.navMenuItem) {
50
- // Add the nav menu item
51
- const item: NavMenuItem = {
52
- url: route.navMenuItem.url ?? route.path,
53
- id: route.navMenuItem.id ?? route.path,
54
- title: route.navMenuItem.title ?? route.path,
55
- };
56
- addNavMenuItem(item, route.navMenuItem.sectionId);
57
- }
58
- if (route.path) {
59
- // Configure a list page
60
- registerRoute(route);
61
- }
62
- }
63
- }
64
- if (extension.actionBarItems) {
65
- for (const item of extension.actionBarItems) {
66
- registerDashboardActionBarItem(item);
67
- }
68
- }
69
- if (extension.pageBlocks) {
70
- for (const block of extension.pageBlocks) {
71
- registerDashboardPageBlock(block);
72
- }
73
- }
74
- if (extension.widgets) {
75
- for (const widget of extension.widgets) {
76
- registerDashboardWidget(widget);
77
- }
78
- }
40
+ // Register navigation extensions (nav sections and routes)
41
+ registerNavigationExtensions(extension.navSections, extension.routes);
42
+
43
+ // Register layout extensions (action bar items and page blocks)
44
+ registerLayoutExtensions(extension.actionBarItems, extension.pageBlocks);
45
+
46
+ // Register widget extensions
47
+ registerWidgetExtensions(extension.widgets);
48
+
49
+ // Register form component extensions (custom form components, input components, and display components)
50
+ registerFormComponentExtensions(extension.customFormComponents);
51
+
52
+ // Register data table extensions
53
+ registerDataTableExtensions(extension.dataTables);
54
+
55
+ // Register detail form extensions
56
+ registerDetailFormExtensions(extension.detailForms);
57
+
58
+ // Register alert extensions
59
+ registerAlertExtensions(extension.alerts);
60
+
61
+ // Register login extensions
62
+ registerLoginExtensions(extension.login);
63
+
64
+ // Execute extension source change callbacks
79
65
  const callbacks = globalRegistry.get('extensionSourceChangeCallbacks');
80
66
  if (callbacks.size) {
81
67
  for (const callback of callbacks) {
@@ -0,0 +1,69 @@
1
+ import { BooleanDisplayBadge, BooleanDisplayCheckbox } from '@/vdb/components/data-display/boolean.js';
2
+ import { DateTime } from '@/vdb/components/data-display/date-time.js';
3
+ import { Money } from '@/vdb/components/data-display/money.js';
4
+ import { VendureImage } from '@/vdb/components/shared/vendure-image.js';
5
+ import { DataDisplayComponent } from '../component-registry/component-registry.js';
6
+ import { globalRegistry } from '../registry/global-registry.js';
7
+
8
+ globalRegistry.register('displayComponents', new Map<string, DataDisplayComponent>());
9
+
10
+ // Create component function for asset display
11
+ const AssetDisplay: DataDisplayComponent = ({ value }) => <VendureImage asset={value} preset="tiny" />;
12
+
13
+ // Register built-in display components
14
+ const displayComponents = globalRegistry.get('displayComponents');
15
+ displayComponents.set('vendure:booleanCheckbox', BooleanDisplayCheckbox);
16
+ displayComponents.set('vendure:booleanBadge', BooleanDisplayBadge);
17
+ displayComponents.set('vendure:dateTime', DateTime);
18
+ displayComponents.set('vendure:asset', AssetDisplay);
19
+ displayComponents.set('vendure:money', Money);
20
+
21
+ export function getDisplayComponent(id: string): DataDisplayComponent | undefined {
22
+ return globalRegistry.get('displayComponents').get(id);
23
+ }
24
+
25
+ /**
26
+ * @description
27
+ * Gets a display component using the targeting properties.
28
+ * Uses the same key pattern as registration: pageId_blockId_fieldName
29
+ */
30
+ export function getTargetedDisplayComponent(
31
+ pageId: string,
32
+ blockId: string,
33
+ field: string,
34
+ ): DataDisplayComponent | undefined {
35
+ const key = generateDisplayComponentKey(pageId, blockId, field);
36
+ return globalRegistry.get('displayComponents').get(key);
37
+ }
38
+
39
+ /**
40
+ * @description
41
+ * Generates a display component key based on the targeting properties.
42
+ * Follows the existing pattern: pageId_blockId_fieldName
43
+ */
44
+ export function generateDisplayComponentKey(pageId: string, blockId: string, field: string): string {
45
+ return `${pageId}_${blockId}_${field}`;
46
+ }
47
+
48
+ export function addDisplayComponent({
49
+ pageId,
50
+ blockId,
51
+ field,
52
+ component,
53
+ }: {
54
+ pageId: string;
55
+ blockId: string;
56
+ field: string;
57
+ component: React.ComponentType<{ value: any; [key: string]: any }>;
58
+ }) {
59
+ const displayComponents = globalRegistry.get('displayComponents');
60
+
61
+ // Generate the key using the helper function
62
+ const key = generateDisplayComponentKey(pageId, blockId, field);
63
+
64
+ if (displayComponents.has(key)) {
65
+ // eslint-disable-next-line no-console
66
+ console.warn(`Display component with key "${key}" is already registered and will be overwritten.`);
67
+ }
68
+ displayComponents.set(key, component);
69
+ }
@@ -1,100 +1,16 @@
1
- import { PageContextValue } from '@/framework/layout-engine/page-provider.js';
2
- import { AnyRoute, RouteOptions } from '@tanstack/react-router';
3
- import { LucideIcon } from 'lucide-react';
4
- import type React from 'react';
5
-
6
- import { DashboardAlertDefinition } from '../alert/types.js';
7
- import { DashboardWidgetDefinition } from '../dashboard-widget/types.js';
8
- import { NavMenuItem } from '../nav-menu/nav-menu-extensions.js';
9
-
10
- export interface DashboardRouteDefinition {
11
- component: (route: AnyRoute) => React.ReactNode;
12
- path: string;
13
- navMenuItem?: Partial<NavMenuItem> & { sectionId: string };
14
- loader?: RouteOptions['loader'];
15
- }
16
-
17
- export interface ActionBarButtonState {
18
- disabled: boolean;
19
- visible: boolean;
20
- }
21
-
22
- export interface DashboardNavSectionDefinition {
23
- id: string;
24
- title: string;
25
- icon?: LucideIcon;
26
- order?: number;
27
- }
28
-
29
- /**
30
- * @description
31
- * **Status: Developer Preview**
32
- *
33
- * Allows you to define custom action bar items for any page in the dashboard.
34
- *
35
- * @docsCategory extensions
36
- * @since 3.3.0
37
- */
38
- export interface DashboardActionBarItem {
39
- /**
40
- * @description
41
- * The ID of the page where the action bar item should be displayed.
42
- */
43
- pageId: string;
44
- /**
45
- * @description
46
- * A React component that will be rendered in the action bar.
47
- */
48
- component: React.FunctionComponent<{ context: PageContextValue }>;
49
- /**
50
- * @description
51
- * Any permissions that are required to display this action bar item.
52
- */
53
- requiresPermission?: string | string[];
54
- }
55
-
56
- export interface DashboardActionBarDropdownMenuItem {
57
- locationId: string;
58
- component: React.FunctionComponent<{ context: PageContextValue }>;
59
- requiresPermission?: string | string[];
60
- }
61
-
62
- export type PageBlockPosition = { blockId: string; order: 'before' | 'after' | 'replace' };
63
-
64
- /**
65
- * @description
66
- * **Status: Developer Preview**
67
- *
68
- * The location of a page block in the dashboard. The location can be found by turning on
69
- * "developer mode" in the dashboard user menu (bottom left corner) and then
70
- * clicking the `< />` icon when hovering over a page block.
71
- *
72
- * @docsCategory extensions
73
- * @since 3.3.0
74
- */
75
- export type PageBlockLocation = {
76
- pageId: string;
77
- position: PageBlockPosition;
78
- column: 'main' | 'side';
79
- };
80
-
81
- /**
82
- * @description
83
- * **Status: Developer Preview**
84
- *
85
- * This allows you to insert a custom component into a specific location
86
- * on any page in the dashboard.
87
- *
88
- * @docsCategory extensions
89
- * @since 3.3.0
90
- */
91
- export interface DashboardPageBlockDefinition {
92
- id: string;
93
- title?: React.ReactNode;
94
- location: PageBlockLocation;
95
- component: React.FunctionComponent<{ context: PageContextValue }>;
96
- requiresPermission?: string | string[];
97
- }
1
+ // Import types for the main interface
2
+ import {
3
+ DashboardActionBarItem,
4
+ DashboardAlertDefinition,
5
+ DashboardCustomFormComponents,
6
+ DashboardDataTableExtensionDefinition,
7
+ DashboardDetailFormExtensionDefinition,
8
+ DashboardLoginExtensions,
9
+ DashboardNavSectionDefinition,
10
+ DashboardPageBlockDefinition,
11
+ DashboardRouteDefinition,
12
+ DashboardWidgetDefinition,
13
+ } from './types/index.js';
98
14
 
99
15
  /**
100
16
  * @description
@@ -128,7 +44,7 @@ export interface DashboardExtension {
128
44
  actionBarItems?: DashboardActionBarItem[];
129
45
  /**
130
46
  * @description
131
- * Not yet implemented
47
+ * Allows you to define custom alerts that can be displayed in the dashboard.
132
48
  */
133
49
  alerts?: DashboardAlertDefinition[];
134
50
  /**
@@ -137,4 +53,24 @@ export interface DashboardExtension {
137
53
  * given components and optionally also add a nav menu item.
138
54
  */
139
55
  widgets?: DashboardWidgetDefinition[];
56
+ /**
57
+ * @description
58
+ * Unified registration for custom form custom field components.
59
+ */
60
+ customFormComponents?: DashboardCustomFormComponents;
61
+ /**
62
+ * @description
63
+ * Allows you to customize aspects of existing data tables in the dashboard.
64
+ */
65
+ dataTables?: DashboardDataTableExtensionDefinition[];
66
+ /**
67
+ * @description
68
+ * Allows you to customize the detail form for any page in the dashboard.
69
+ */
70
+ detailForms?: DashboardDetailFormExtensionDefinition[];
71
+ /**
72
+ * @description
73
+ * Allows you to customize the login page with custom components.
74
+ */
75
+ login?: DashboardLoginExtensions;
140
76
  }
@@ -0,0 +1,73 @@
1
+ import { CombinationModeInput } from '@/vdb/components/data-input/combination-mode-input.js';
2
+ import { DateTimeInput } from '@/vdb/components/data-input/datetime-input.js';
3
+ import { FacetValueInput } from '@/vdb/components/data-input/facet-value-input.js';
4
+ import { MoneyInput } from '@/vdb/components/data-input/money-input.js';
5
+ import { ProductMultiInput } from '@/vdb/components/data-input/product-multi-selector.js';
6
+ import { Checkbox } from '@/vdb/components/ui/checkbox.js';
7
+ import { Input } from '@/vdb/components/ui/input.js';
8
+ import { DataInputComponent } from '../component-registry/component-registry.js';
9
+ import { globalRegistry } from '../registry/global-registry.js';
10
+
11
+ globalRegistry.register('inputComponents', new Map<string, DataInputComponent>());
12
+
13
+ // Create component functions for built-in components
14
+ const TextInput: DataInputComponent = props => (
15
+ <Input {...props} onChange={e => props.onChange(e.target.value)} />
16
+ );
17
+ const NumberInput: DataInputComponent = props => (
18
+ <Input {...props} onChange={e => props.onChange(e.target.valueAsNumber)} type="number" />
19
+ );
20
+ const CheckboxInput: DataInputComponent = props => (
21
+ <Checkbox
22
+ {...props}
23
+ checked={props.value === 'true' || props.value === true}
24
+ onCheckedChange={value => props.onChange(value)}
25
+ />
26
+ );
27
+
28
+ // Register built-in input components
29
+ const inputComponents = globalRegistry.get('inputComponents');
30
+ inputComponents.set('vendure:moneyInput', MoneyInput);
31
+ inputComponents.set('vendure:textInput', TextInput);
32
+ inputComponents.set('vendure:numberInput', NumberInput);
33
+ inputComponents.set('vendure:dateTimeInput', DateTimeInput);
34
+ inputComponents.set('vendure:checkboxInput', CheckboxInput);
35
+ inputComponents.set('vendure:facetValueInput', FacetValueInput);
36
+ inputComponents.set('vendure:combinationModeInput', CombinationModeInput);
37
+ inputComponents.set('vendure:productMultiInput', ProductMultiInput);
38
+
39
+ export function getInputComponent(id: string): DataInputComponent | undefined {
40
+ return globalRegistry.get('inputComponents').get(id);
41
+ }
42
+
43
+ /**
44
+ * @description
45
+ * Generates a component key based on the targeting properties.
46
+ * Follows the existing pattern: pageId_blockId_fieldName
47
+ */
48
+ export function generateInputComponentKey(pageId: string, blockId: string, field: string): string {
49
+ return `${pageId}_${blockId}_${field}`;
50
+ }
51
+
52
+ export function addInputComponent({
53
+ pageId,
54
+ blockId,
55
+ field,
56
+ component,
57
+ }: {
58
+ pageId: string;
59
+ blockId: string;
60
+ field: string;
61
+ component: DataInputComponent;
62
+ }) {
63
+ const inputComponents = globalRegistry.get('inputComponents');
64
+
65
+ // Generate the key using the helper function
66
+ const key = generateInputComponentKey(pageId, blockId, field);
67
+
68
+ if (inputComponents.has(key)) {
69
+ // eslint-disable-next-line no-console
70
+ console.warn(`Input component with key "${key}" is already registered and will be overwritten.`);
71
+ }
72
+ inputComponents.set(key, component);
73
+ }