@vendure/dashboard 3.3.6-master-202507050232 → 3.4.0-minor-202506250934

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 (391) hide show
  1. package/README.md +4 -41
  2. package/dist/plugin/utils/config-loader.d.ts +1 -70
  3. package/dist/plugin/utils/config-loader.js +9 -33
  4. package/dist/plugin/vite-plugin-config-loader.js +1 -6
  5. package/dist/plugin/vite-plugin-config.js +7 -6
  6. package/dist/plugin/vite-plugin-dashboard-metadata.d.ts +3 -1
  7. package/dist/plugin/vite-plugin-dashboard-metadata.js +8 -1
  8. package/dist/plugin/vite-plugin-vendure-dashboard.d.ts +0 -41
  9. package/dist/plugin/vite-plugin-vendure-dashboard.js +2 -5
  10. package/package.json +131 -131
  11. package/src/app/app-providers.tsx +6 -6
  12. package/src/app/main.tsx +9 -9
  13. package/src/app/routes/__root.tsx +2 -1
  14. package/src/app/routes/_authenticated/_administrators/administrators.graphql.ts +1 -10
  15. package/src/app/routes/_authenticated/_administrators/administrators.tsx +8 -15
  16. package/src/app/routes/_authenticated/_administrators/administrators_.$id.tsx +12 -16
  17. package/src/app/routes/_authenticated/_administrators/components/role-permissions-display.tsx +16 -16
  18. package/src/app/routes/_authenticated/_assets/assets.graphql.ts +2 -13
  19. package/src/app/routes/_authenticated/_assets/assets.tsx +4 -16
  20. package/src/app/routes/_authenticated/_assets/assets_.$id.tsx +38 -52
  21. package/src/app/routes/_authenticated/_channels/channels.graphql.ts +1 -10
  22. package/src/app/routes/_authenticated/_channels/channels.tsx +10 -17
  23. package/src/app/routes/_authenticated/_channels/channels_.$id.tsx +17 -21
  24. package/src/app/routes/_authenticated/_collections/collections.graphql.ts +3 -60
  25. package/src/app/routes/_authenticated/_collections/collections.tsx +124 -168
  26. package/src/app/routes/_authenticated/_collections/collections_.$id.tsx +16 -20
  27. package/src/app/routes/_authenticated/_collections/components/collection-contents-preview-table.tsx +8 -7
  28. package/src/app/routes/_authenticated/_collections/components/collection-contents-sheet.tsx +5 -9
  29. package/src/app/routes/_authenticated/_collections/components/collection-contents-table.tsx +9 -10
  30. package/src/app/routes/_authenticated/_collections/components/collection-filters-selector.tsx +7 -7
  31. package/src/app/routes/_authenticated/_countries/countries.graphql.ts +2 -11
  32. package/src/app/routes/_authenticated/_countries/countries.tsx +6 -13
  33. package/src/app/routes/_authenticated/_countries/countries_.$id.tsx +17 -21
  34. package/src/app/routes/_authenticated/_customer-groups/components/customer-group-members-sheet.tsx +5 -12
  35. package/src/app/routes/_authenticated/_customer-groups/components/customer-group-members-table.tsx +17 -22
  36. package/src/app/routes/_authenticated/_customer-groups/customer-groups.graphql.ts +2 -11
  37. package/src/app/routes/_authenticated/_customer-groups/customer-groups.tsx +6 -13
  38. package/src/app/routes/_authenticated/_customer-groups/customer-groups_.$id.tsx +15 -18
  39. package/src/app/routes/_authenticated/_customers/components/customer-address-card.tsx +19 -19
  40. package/src/app/routes/_authenticated/_customers/components/customer-address-form.tsx +10 -10
  41. package/src/app/routes/_authenticated/_customers/components/customer-history/customer-history-container.tsx +5 -5
  42. package/src/app/routes/_authenticated/_customers/components/customer-history/customer-history.tsx +7 -11
  43. package/src/app/routes/_authenticated/_customers/components/customer-history/use-customer-history.ts +4 -4
  44. package/src/app/routes/_authenticated/_customers/components/customer-order-table.tsx +73 -75
  45. package/src/app/routes/_authenticated/_customers/components/customer-status-badge.tsx +4 -4
  46. package/src/app/routes/_authenticated/_customers/customers.graphql.ts +2 -10
  47. package/src/app/routes/_authenticated/_customers/customers.tsx +6 -13
  48. package/src/app/routes/_authenticated/_customers/customers_.$id.tsx +15 -19
  49. package/src/app/routes/_authenticated/_facets/components/edit-facet-value.tsx +9 -9
  50. package/src/app/routes/_authenticated/_facets/components/facet-values-sheet.tsx +4 -4
  51. package/src/app/routes/_authenticated/_facets/components/facet-values-table.tsx +11 -15
  52. package/src/app/routes/_authenticated/_facets/facets.graphql.ts +1 -31
  53. package/src/app/routes/_authenticated/_facets/facets.tsx +7 -31
  54. package/src/app/routes/_authenticated/_facets/facets_.$id.tsx +13 -17
  55. package/src/app/routes/_authenticated/_global-settings/global-settings.graphql.ts +1 -1
  56. package/src/app/routes/_authenticated/_global-settings/global-settings.tsx +13 -13
  57. package/src/app/routes/_authenticated/_orders/components/customer-address-selector.tsx +14 -11
  58. package/src/app/routes/_authenticated/_orders/components/edit-order-table.tsx +55 -93
  59. package/src/app/routes/_authenticated/_orders/components/money-gross-net.tsx +9 -11
  60. package/src/app/routes/_authenticated/_orders/components/order-address.tsx +6 -5
  61. package/src/app/routes/_authenticated/_orders/components/order-history/order-history-container.tsx +62 -67
  62. package/src/app/routes/_authenticated/_orders/components/order-history/order-history.tsx +6 -11
  63. package/src/app/routes/_authenticated/_orders/components/order-history/use-order-history.ts +5 -9
  64. package/src/app/routes/_authenticated/_orders/components/order-line-custom-fields-form.tsx +7 -11
  65. package/src/app/routes/_authenticated/_orders/components/order-table-totals.tsx +22 -39
  66. package/src/app/routes/_authenticated/_orders/components/order-table.tsx +4 -4
  67. package/src/app/routes/_authenticated/_orders/components/order-tax-summary.tsx +36 -37
  68. package/src/app/routes/_authenticated/_orders/components/payment-details.tsx +33 -18
  69. package/src/app/routes/_authenticated/_orders/components/shipping-method-selector.tsx +44 -43
  70. package/src/app/routes/_authenticated/_orders/orders.graphql.ts +3 -101
  71. package/src/app/routes/_authenticated/_orders/orders.tsx +20 -21
  72. package/src/app/routes/_authenticated/_orders/orders_.$id.tsx +16 -72
  73. package/src/app/routes/_authenticated/_orders/orders_.draft.$id.tsx +90 -188
  74. package/src/app/routes/_authenticated/_payment-methods/components/payment-eligibility-checker-selector.tsx +7 -10
  75. package/src/app/routes/_authenticated/_payment-methods/components/payment-handler-selector.tsx +11 -11
  76. package/src/app/routes/_authenticated/_payment-methods/payment-methods.graphql.ts +2 -29
  77. package/src/app/routes/_authenticated/_payment-methods/payment-methods.tsx +14 -36
  78. package/src/app/routes/_authenticated/_payment-methods/payment-methods_.$id.tsx +15 -22
  79. package/src/app/routes/_authenticated/_product-variants/components/variant-price-detail.tsx +6 -7
  80. package/src/app/routes/_authenticated/_product-variants/product-variants.graphql.ts +3 -64
  81. package/src/app/routes/_authenticated/_product-variants/product-variants.tsx +9 -39
  82. package/src/app/routes/_authenticated/_product-variants/product-variants_.$id.tsx +22 -33
  83. package/src/app/routes/_authenticated/_products/components/add-product-variant-dialog.tsx +10 -10
  84. package/src/app/routes/_authenticated/_products/components/create-product-options-dialog.tsx +41 -57
  85. package/src/app/routes/_authenticated/_products/components/create-product-variants-dialog.tsx +11 -11
  86. package/src/app/routes/_authenticated/_products/components/create-product-variants.tsx +14 -18
  87. package/src/app/routes/_authenticated/_products/components/option-value-input.tsx +15 -21
  88. package/src/app/routes/_authenticated/_products/components/product-option-select.tsx +34 -28
  89. package/src/app/routes/_authenticated/_products/components/product-variants-table.tsx +53 -84
  90. package/src/app/routes/_authenticated/_products/products.graphql.ts +2 -70
  91. package/src/app/routes/_authenticated/_products/products.tsx +7 -36
  92. package/src/app/routes/_authenticated/_products/products_.$id.tsx +24 -33
  93. package/src/app/routes/_authenticated/_profile/profile.graphql.ts +1 -1
  94. package/src/app/routes/_authenticated/_profile/profile.tsx +8 -8
  95. package/src/app/routes/_authenticated/_promotions/components/promotion-actions-selector.tsx +11 -14
  96. package/src/app/routes/_authenticated/_promotions/components/promotion-conditions-selector.tsx +11 -14
  97. package/src/app/routes/_authenticated/_promotions/promotions.graphql.ts +2 -27
  98. package/src/app/routes/_authenticated/_promotions/promotions.tsx +7 -31
  99. package/src/app/routes/_authenticated/_promotions/promotions_.$id.tsx +16 -20
  100. package/src/app/routes/_authenticated/_roles/components/expandable-permissions.tsx +5 -5
  101. package/src/app/routes/_authenticated/_roles/components/permissions-grid.tsx +17 -21
  102. package/src/app/routes/_authenticated/_roles/roles.graphql.ts +1 -10
  103. package/src/app/routes/_authenticated/_roles/roles.tsx +10 -17
  104. package/src/app/routes/_authenticated/_roles/roles_.$id.tsx +12 -16
  105. package/src/app/routes/_authenticated/_sellers/sellers.graphql.ts +1 -10
  106. package/src/app/routes/_authenticated/_sellers/sellers.tsx +6 -13
  107. package/src/app/routes/_authenticated/_sellers/sellers_.$id.tsx +13 -17
  108. package/src/app/routes/_authenticated/_shipping-methods/components/fulfillment-handler-selector.tsx +6 -6
  109. package/src/app/routes/_authenticated/_shipping-methods/components/shipping-calculator-selector.tsx +21 -23
  110. package/src/app/routes/_authenticated/_shipping-methods/components/shipping-eligibility-checker-selector.tsx +21 -25
  111. package/src/app/routes/_authenticated/_shipping-methods/components/test-shipping-method-dialog.tsx +3 -3
  112. package/src/app/routes/_authenticated/_shipping-methods/shipping-methods.graphql.ts +2 -29
  113. package/src/app/routes/_authenticated/_shipping-methods/shipping-methods.tsx +6 -25
  114. package/src/app/routes/_authenticated/_shipping-methods/shipping-methods_.$id.tsx +13 -17
  115. package/src/app/routes/_authenticated/_stock-locations/stock-locations.graphql.ts +1 -26
  116. package/src/app/routes/_authenticated/_stock-locations/stock-locations.tsx +6 -25
  117. package/src/app/routes/_authenticated/_stock-locations/stock-locations_.$id.tsx +12 -16
  118. package/src/app/routes/_authenticated/_system/components/payload-dialog.tsx +4 -4
  119. package/src/app/routes/_authenticated/_system/healthchecks.tsx +4 -4
  120. package/src/app/routes/_authenticated/_system/job-queue.graphql.ts +1 -1
  121. package/src/app/routes/_authenticated/_system/job-queue.tsx +6 -10
  122. package/src/app/routes/_authenticated/_system/scheduled-tasks.tsx +28 -34
  123. package/src/app/routes/_authenticated/_tax-categories/tax-categories.graphql.ts +2 -11
  124. package/src/app/routes/_authenticated/_tax-categories/tax-categories.tsx +7 -14
  125. package/src/app/routes/_authenticated/_tax-categories/tax-categories_.$id.tsx +16 -20
  126. package/src/app/routes/_authenticated/_tax-rates/tax-rates.graphql.ts +2 -11
  127. package/src/app/routes/_authenticated/_tax-rates/tax-rates.tsx +8 -15
  128. package/src/app/routes/_authenticated/_tax-rates/tax-rates_.$id.tsx +18 -22
  129. package/src/app/routes/_authenticated/_zones/components/zone-countries-sheet.tsx +4 -4
  130. package/src/app/routes/_authenticated/_zones/components/zone-countries-table.tsx +8 -12
  131. package/src/app/routes/_authenticated/_zones/zones.graphql.ts +2 -11
  132. package/src/app/routes/_authenticated/_zones/zones.tsx +6 -13
  133. package/src/app/routes/_authenticated/_zones/zones_.$id.tsx +14 -18
  134. package/src/app/routes/_authenticated/index.tsx +4 -4
  135. package/src/app/routes/_authenticated.tsx +3 -3
  136. package/src/app/routes/login.tsx +2 -2
  137. package/src/app/styles.css +1 -4
  138. package/src/lib/components/data-display/boolean.tsx +1 -1
  139. package/src/lib/components/data-display/date-time.tsx +2 -2
  140. package/src/lib/components/data-display/json.tsx +1 -1
  141. package/src/lib/components/data-display/money.tsx +3 -2
  142. package/src/lib/components/data-input/affixed-input.tsx +8 -3
  143. package/src/lib/components/data-input/customer-group-input.tsx +2 -2
  144. package/src/lib/components/data-input/datetime-input.tsx +146 -129
  145. package/src/lib/components/data-input/facet-value-input.tsx +22 -30
  146. package/src/lib/components/data-input/money-input.tsx +12 -5
  147. package/src/lib/components/data-input/{rich-text-input.tsx → richt-text-input.tsx} +1 -1
  148. package/src/lib/components/data-table/add-filter-menu.tsx +18 -9
  149. package/src/lib/components/data-table/data-table-column-header.tsx +22 -4
  150. package/src/lib/components/data-table/data-table-faceted-filter.tsx +8 -8
  151. package/src/lib/components/data-table/data-table-filter-badge.tsx +8 -16
  152. package/src/lib/components/data-table/data-table-filter-dialog.tsx +8 -8
  153. package/src/lib/components/data-table/data-table-pagination.tsx +4 -4
  154. package/src/lib/components/data-table/data-table-view-options.tsx +21 -25
  155. package/src/lib/components/data-table/data-table.tsx +41 -85
  156. package/src/lib/components/data-table/filters/data-table-boolean-filter.tsx +8 -11
  157. package/src/lib/components/data-table/filters/data-table-datetime-filter.tsx +23 -14
  158. package/src/lib/components/data-table/filters/data-table-id-filter.tsx +10 -15
  159. package/src/lib/components/data-table/filters/data-table-number-filter.tsx +17 -18
  160. package/src/lib/components/data-table/filters/data-table-string-filter.tsx +12 -29
  161. package/src/lib/components/data-table/human-readable-operator.tsx +3 -3
  162. package/src/lib/components/data-table/refresh-button.tsx +15 -30
  163. package/src/lib/components/layout/app-layout.tsx +8 -8
  164. package/src/lib/components/layout/app-sidebar.tsx +5 -5
  165. package/src/lib/components/layout/channel-switcher.tsx +8 -8
  166. package/src/lib/components/layout/content-language-selector.tsx +10 -16
  167. package/src/lib/components/layout/generated-breadcrumbs.tsx +1 -1
  168. package/src/lib/components/layout/language-dialog.tsx +11 -5
  169. package/src/lib/components/layout/nav-main.tsx +4 -4
  170. package/src/lib/components/layout/nav-projects.tsx +2 -2
  171. package/src/lib/components/layout/nav-user.tsx +7 -7
  172. package/src/lib/components/layout/prerelease-popup.tsx +1 -1
  173. package/src/lib/components/login/login-form.tsx +5 -5
  174. package/src/lib/components/shared/alerts.tsx +3 -3
  175. package/src/lib/components/shared/animated-number.tsx +2 -2
  176. package/src/lib/components/shared/asset/asset-focal-point-editor.tsx +19 -29
  177. package/src/lib/components/shared/asset/asset-gallery.tsx +18 -23
  178. package/src/lib/components/shared/asset/asset-picker-dialog.tsx +66 -63
  179. package/src/lib/components/shared/asset/asset-preview-dialog.tsx +7 -3
  180. package/src/lib/components/shared/asset/asset-preview-selector.tsx +6 -4
  181. package/src/lib/components/shared/asset/asset-preview.tsx +15 -7
  182. package/src/lib/components/shared/asset/asset-properties.tsx +9 -7
  183. package/src/lib/components/shared/asset/focal-point-control.tsx +13 -5
  184. package/src/lib/components/shared/assigned-facet-values.tsx +5 -1
  185. package/src/lib/components/shared/channel-code-label.tsx +4 -3
  186. package/src/lib/components/shared/channel-selector.tsx +6 -6
  187. package/src/lib/components/shared/configurable-operation-arg-input.tsx +2 -2
  188. package/src/lib/components/shared/configurable-operation-input.tsx +16 -15
  189. package/src/lib/components/shared/confirmation-dialog.tsx +2 -2
  190. package/src/lib/components/shared/copyable-text.tsx +4 -3
  191. package/src/lib/components/shared/country-selector.tsx +18 -21
  192. package/src/lib/components/shared/currency-selector.tsx +5 -5
  193. package/src/lib/components/shared/custom-fields-form.tsx +51 -253
  194. package/src/lib/components/shared/customer-address-form.tsx +13 -18
  195. package/src/lib/components/shared/customer-group-selector.tsx +6 -6
  196. package/src/lib/components/shared/customer-selector.tsx +18 -24
  197. package/src/lib/components/shared/detail-page-button.tsx +1 -3
  198. package/src/lib/components/shared/entity-assets.tsx +34 -33
  199. package/src/lib/components/shared/error-page.tsx +6 -6
  200. package/src/lib/components/shared/facet-value-chip.tsx +5 -12
  201. package/src/lib/components/shared/facet-value-selector.tsx +63 -64
  202. package/src/lib/components/shared/form-field-wrapper.tsx +24 -47
  203. package/src/lib/components/shared/history-timeline/history-entry.tsx +6 -12
  204. package/src/lib/components/shared/history-timeline/history-note-checkbox.tsx +3 -3
  205. package/src/lib/components/shared/history-timeline/history-note-editor.tsx +4 -4
  206. package/src/lib/components/shared/history-timeline/history-note-input.tsx +3 -3
  207. package/src/lib/components/shared/history-timeline/history-timeline.tsx +8 -15
  208. package/src/lib/components/shared/language-selector.tsx +5 -5
  209. package/src/lib/components/shared/logo-mark.tsx +2 -2
  210. package/src/lib/components/shared/multi-select.tsx +5 -5
  211. package/src/lib/components/shared/navigation-confirmation.tsx +9 -24
  212. package/src/lib/components/shared/option-value-input.tsx +15 -17
  213. package/src/lib/components/shared/paginated-list-data-table.tsx +24 -100
  214. package/src/lib/components/shared/permission-guard.tsx +4 -4
  215. package/src/lib/components/shared/product-variant-selector.tsx +31 -32
  216. package/src/lib/components/shared/role-code-label.tsx +6 -10
  217. package/src/lib/components/shared/role-selector.tsx +4 -4
  218. package/src/lib/components/shared/seller-selector.tsx +17 -21
  219. package/src/lib/components/shared/stock-level-label.tsx +5 -5
  220. package/src/lib/components/shared/tax-category-selector.tsx +5 -5
  221. package/src/lib/components/shared/translatable-form-field.tsx +21 -30
  222. package/src/lib/components/shared/vendure-image.tsx +2 -31
  223. package/src/lib/components/shared/zone-selector.tsx +6 -5
  224. package/src/lib/components/ui/accordion.tsx +3 -3
  225. package/src/lib/components/ui/alert-dialog.tsx +10 -10
  226. package/src/lib/components/ui/alert.tsx +3 -3
  227. package/src/lib/components/ui/badge.tsx +2 -2
  228. package/src/lib/components/ui/breadcrumb.tsx +4 -4
  229. package/src/lib/components/ui/button.tsx +3 -10
  230. package/src/lib/components/ui/calendar.tsx +459 -392
  231. package/src/lib/components/ui/card.tsx +2 -2
  232. package/src/lib/components/ui/checkbox.tsx +2 -2
  233. package/src/lib/components/ui/command.tsx +6 -12
  234. package/src/lib/components/ui/dialog.tsx +2 -2
  235. package/src/lib/components/ui/dropdown-menu.tsx +7 -7
  236. package/src/lib/components/ui/form.tsx +4 -4
  237. package/src/lib/components/ui/hover-card.tsx +3 -3
  238. package/src/lib/components/ui/input.tsx +1 -1
  239. package/src/lib/components/ui/label.tsx +2 -2
  240. package/src/lib/components/ui/pagination.tsx +108 -87
  241. package/src/lib/components/ui/popover.tsx +3 -3
  242. package/src/lib/components/ui/scroll-area.tsx +2 -2
  243. package/src/lib/components/ui/select.tsx +129 -151
  244. package/src/lib/components/ui/separator.tsx +2 -2
  245. package/src/lib/components/ui/sheet.tsx +5 -5
  246. package/src/lib/components/ui/sidebar.tsx +10 -10
  247. package/src/lib/components/ui/skeleton.tsx +1 -1
  248. package/src/lib/components/ui/switch.tsx +2 -2
  249. package/src/lib/components/ui/table.tsx +2 -2
  250. package/src/lib/components/ui/tabs.tsx +3 -3
  251. package/src/lib/components/ui/textarea.tsx +1 -1
  252. package/src/lib/components/ui/tooltip.tsx +3 -3
  253. package/src/lib/framework/alert/alert-extensions.tsx +3 -2
  254. package/src/lib/framework/alert/alert-item.tsx +3 -5
  255. package/src/lib/framework/alert/types.ts +13 -0
  256. package/src/lib/framework/component-registry/component-registry.tsx +47 -33
  257. package/src/lib/framework/dashboard-widget/base-widget.tsx +13 -5
  258. package/src/lib/framework/dashboard-widget/latest-orders-widget/index.tsx +8 -8
  259. package/src/lib/framework/dashboard-widget/latest-orders-widget/latest-orders-widget.graphql.ts +1 -1
  260. package/src/lib/framework/dashboard-widget/metrics-widget/index.tsx +7 -6
  261. package/src/lib/framework/dashboard-widget/metrics-widget/metrics-widget.graphql.ts +1 -1
  262. package/src/lib/framework/dashboard-widget/orders-summary/index.tsx +6 -7
  263. package/src/lib/framework/dashboard-widget/orders-summary/order-summary-widget.graphql.ts +1 -1
  264. package/src/lib/framework/dashboard-widget/types.ts +22 -0
  265. package/src/lib/framework/dashboard-widget/widget-extensions.tsx +1 -1
  266. package/src/lib/framework/defaults.ts +1 -1
  267. package/src/lib/framework/document-introspection/add-custom-fields.ts +2 -50
  268. package/src/lib/framework/document-introspection/get-document-structure.ts +10 -43
  269. package/src/lib/framework/document-introspection/hooks.ts +1 -4
  270. package/src/lib/framework/extension-api/define-dashboard-extension.ts +49 -31
  271. package/src/lib/framework/extension-api/extension-api-types.ts +98 -25
  272. package/src/lib/framework/extension-api/use-dashboard-extensions.ts +1 -2
  273. package/src/lib/framework/form-engine/form-schema-tools.ts +1 -1
  274. package/src/lib/framework/form-engine/use-generated-form.tsx +18 -57
  275. package/src/lib/framework/layout-engine/location-wrapper.tsx +72 -105
  276. package/src/lib/framework/layout-engine/page-layout.tsx +52 -70
  277. package/src/lib/framework/page/detail-page-route-loader.tsx +7 -26
  278. package/src/lib/framework/page/detail-page.tsx +37 -94
  279. package/src/lib/framework/page/list-page.tsx +11 -9
  280. package/src/lib/framework/page/use-detail-page.ts +7 -38
  281. package/src/lib/framework/page/use-extended-router.tsx +5 -4
  282. package/src/lib/framework/registry/registry-types.ts +5 -15
  283. package/src/lib/graphql/{fragments.ts → fragments.tsx} +2 -1
  284. package/src/lib/graphql/graphql-env.d.ts +13 -16
  285. package/src/lib/hooks/use-auth.tsx +1 -1
  286. package/src/lib/hooks/use-channel.ts +1 -1
  287. package/src/lib/hooks/use-grouped-permissions.ts +2 -3
  288. package/src/lib/hooks/use-page.tsx +2 -2
  289. package/src/lib/hooks/use-permissions.ts +2 -3
  290. package/src/lib/hooks/use-server-config.ts +1 -1
  291. package/src/lib/hooks/use-theme.ts +1 -1
  292. package/src/lib/hooks/use-user-settings.tsx +1 -1
  293. package/src/lib/index.ts +6 -65
  294. package/src/lib/lib/trans.tsx +3 -3
  295. package/src/lib/lib/utils.ts +0 -49
  296. package/src/lib/providers/auth.tsx +14 -37
  297. package/src/lib/providers/channel-provider.tsx +4 -4
  298. package/src/lib/providers/server-config.tsx +11 -13
  299. package/src/lib/providers/theme-provider.tsx +3 -2
  300. package/vite/utils/config-loader.ts +10 -120
  301. package/vite/vite-plugin-config-loader.ts +1 -6
  302. package/vite/vite-plugin-config.ts +7 -6
  303. package/vite/vite-plugin-dashboard-metadata.ts +9 -1
  304. package/vite/vite-plugin-vendure-dashboard.ts +4 -48
  305. package/dist/plugin/tests/barrel-exports/my-plugin/index.d.ts +0 -1
  306. package/dist/plugin/tests/barrel-exports/my-plugin/index.js +0 -17
  307. package/dist/plugin/tests/barrel-exports/my-plugin/src/my.plugin.d.ts +0 -2
  308. package/dist/plugin/tests/barrel-exports/my-plugin/src/my.plugin.js +0 -20
  309. package/dist/plugin/tests/barrel-exports/vendure-config.d.ts +0 -2
  310. package/dist/plugin/tests/barrel-exports/vendure-config.js +0 -19
  311. package/dist/plugin/tests/barrel-exports.spec.d.ts +0 -1
  312. package/dist/plugin/tests/barrel-exports.spec.js +0 -14
  313. package/dist/plugin/vite-plugin-tailwind-source.d.ts +0 -7
  314. package/dist/plugin/vite-plugin-tailwind-source.js +0 -49
  315. package/src/app/common/delete-bulk-action.tsx +0 -148
  316. package/src/app/common/duplicate-bulk-action.tsx +0 -134
  317. package/src/app/routes/_authenticated/_administrators/components/administrator-bulk-actions.tsx +0 -15
  318. package/src/app/routes/_authenticated/_assets/components/asset-bulk-actions.tsx +0 -45
  319. package/src/app/routes/_authenticated/_channels/components/channel-bulk-actions.tsx +0 -15
  320. package/src/app/routes/_authenticated/_collections/components/collection-bulk-actions.tsx +0 -123
  321. package/src/app/routes/_authenticated/_collections/components/move-collections-dialog.tsx +0 -430
  322. package/src/app/routes/_authenticated/_collections/components/move-single-collection.tsx +0 -33
  323. package/src/app/routes/_authenticated/_countries/components/country-bulk-actions.tsx +0 -15
  324. package/src/app/routes/_authenticated/_customer-groups/components/customer-group-bulk-actions.tsx +0 -15
  325. package/src/app/routes/_authenticated/_customers/components/customer-bulk-actions.tsx +0 -15
  326. package/src/app/routes/_authenticated/_facets/components/facet-bulk-actions.tsx +0 -104
  327. package/src/app/routes/_authenticated/_orders/components/add-manual-payment-dialog.tsx +0 -191
  328. package/src/app/routes/_authenticated/_orders/components/fulfill-order-dialog.tsx +0 -320
  329. package/src/app/routes/_authenticated/_orders/components/fulfillment-details.tsx +0 -173
  330. package/src/app/routes/_authenticated/_orders/utils/order-types.ts +0 -7
  331. package/src/app/routes/_authenticated/_orders/utils/order-utils.ts +0 -77
  332. package/src/app/routes/_authenticated/_payment-methods/components/payment-method-bulk-actions.tsx +0 -58
  333. package/src/app/routes/_authenticated/_product-variants/components/product-variant-bulk-actions.tsx +0 -110
  334. package/src/app/routes/_authenticated/_products/components/assign-facet-values-dialog.tsx +0 -281
  335. package/src/app/routes/_authenticated/_products/components/product-bulk-actions.tsx +0 -123
  336. package/src/app/routes/_authenticated/_promotions/components/promotion-bulk-actions.tsx +0 -82
  337. package/src/app/routes/_authenticated/_roles/components/role-bulk-actions.tsx +0 -15
  338. package/src/app/routes/_authenticated/_sellers/components/seller-bulk-actions.tsx +0 -15
  339. package/src/app/routes/_authenticated/_shipping-methods/components/shipping-method-bulk-actions.tsx +0 -61
  340. package/src/app/routes/_authenticated/_stock-locations/components/stock-location-bulk-actions.tsx +0 -58
  341. package/src/app/routes/_authenticated/_tax-categories/components/tax-category-bulk-actions.tsx +0 -15
  342. package/src/app/routes/_authenticated/_tax-rates/components/tax-rate-bulk-actions.tsx +0 -15
  343. package/src/app/routes/_authenticated/_zones/components/zone-bulk-actions.tsx +0 -15
  344. package/src/lib/components/data-input/index.ts +0 -11
  345. package/src/lib/components/data-input/relation-input.tsx +0 -153
  346. package/src/lib/components/data-input/relation-selector.tsx +0 -468
  347. package/src/lib/components/data-table/data-table-bulk-action-item.tsx +0 -101
  348. package/src/lib/components/data-table/data-table-bulk-actions.tsx +0 -95
  349. package/src/lib/components/labeled-data.tsx +0 -21
  350. package/src/lib/components/shared/asset/asset-bulk-actions.tsx +0 -94
  351. package/src/lib/components/shared/assign-to-channel-bulk-action.tsx +0 -71
  352. package/src/lib/components/shared/assign-to-channel-dialog.tsx +0 -155
  353. package/src/lib/components/shared/remove-from-channel-bulk-action.tsx +0 -90
  354. package/src/lib/framework/data-table/data-table-extensions.ts +0 -35
  355. package/src/lib/framework/document-extension/extend-detail-form-query.ts +0 -50
  356. package/src/lib/framework/document-extension/extend-document.spec.ts +0 -884
  357. package/src/lib/framework/document-extension/extend-document.ts +0 -159
  358. package/src/lib/framework/extension-api/display-component-extensions.tsx +0 -69
  359. package/src/lib/framework/extension-api/input-component-extensions.tsx +0 -69
  360. package/src/lib/framework/extension-api/logic/alerts.ts +0 -10
  361. package/src/lib/framework/extension-api/logic/data-table.ts +0 -60
  362. package/src/lib/framework/extension-api/logic/detail-forms.ts +0 -48
  363. package/src/lib/framework/extension-api/logic/form-components.ts +0 -13
  364. package/src/lib/framework/extension-api/logic/index.ts +0 -8
  365. package/src/lib/framework/extension-api/logic/layout.ts +0 -22
  366. package/src/lib/framework/extension-api/logic/navigation.ts +0 -37
  367. package/src/lib/framework/extension-api/logic/widgets.ts +0 -10
  368. package/src/lib/framework/extension-api/types/alerts.ts +0 -54
  369. package/src/lib/framework/extension-api/types/data-table.ts +0 -87
  370. package/src/lib/framework/extension-api/types/detail-forms.ts +0 -81
  371. package/src/lib/framework/extension-api/types/form-components.ts +0 -32
  372. package/src/lib/framework/extension-api/types/index.ts +0 -8
  373. package/src/lib/framework/extension-api/types/layout.ts +0 -78
  374. package/src/lib/framework/extension-api/types/navigation.ts +0 -19
  375. package/src/lib/framework/extension-api/types/widgets.ts +0 -97
  376. package/src/lib/framework/form-engine/custom-form-component-extensions.ts +0 -38
  377. package/src/lib/framework/form-engine/custom-form-component.tsx +0 -33
  378. package/src/lib/framework/form-engine/overridden-form-component.tsx +0 -51
  379. package/src/lib/framework/form-engine/utils.ts +0 -58
  380. package/src/lib/framework/layout-engine/page-block-provider.tsx +0 -6
  381. package/src/lib/graphql/common-operations.ts +0 -18
  382. package/src/lib/hooks/use-extended-detail-query.ts +0 -37
  383. package/src/lib/hooks/use-extended-list-query.ts +0 -73
  384. package/src/lib/hooks/use-page-block.tsx +0 -18
  385. package/vite/tests/barrel-exports/my-plugin/index.ts +0 -1
  386. package/vite/tests/barrel-exports/my-plugin/src/my.plugin.ts +0 -8
  387. package/vite/tests/barrel-exports/package.json +0 -6
  388. package/vite/tests/barrel-exports/vendure-config.ts +0 -19
  389. package/vite/tests/barrel-exports.spec.ts +0 -21
  390. package/vite/vite-plugin-tailwind-source.ts +0 -65
  391. /package/src/lib/components/data-table/{types.ts → data-table-types.ts} +0 -0
@@ -1,468 +0,0 @@
1
- import { Button } from '@/vdb/components/ui/button.js';
2
- import { Checkbox } from '@/vdb/components/ui/checkbox.js';
3
- import {
4
- Command,
5
- CommandEmpty,
6
- CommandInput,
7
- CommandItem,
8
- CommandList,
9
- } from '@/vdb/components/ui/command.js';
10
- import { Popover, PopoverContent, PopoverTrigger } from '@/vdb/components/ui/popover.js';
11
- import { getQueryName } from '@/vdb/framework/document-introspection/get-document-structure.js';
12
- import { api } from '@/vdb/graphql/api.js';
13
- import { Trans } from '@/vdb/lib/trans.js';
14
- import { useInfiniteQuery } from '@tanstack/react-query';
15
- import { useDebounce } from '@uidotdev/usehooks';
16
- import type { DocumentNode } from 'graphql';
17
- import { CheckIcon, Loader2, Plus, X } from 'lucide-react';
18
- import React, { useState } from 'react';
19
-
20
- export interface RelationSelectorConfig<T = any> {
21
- /** The GraphQL query document for fetching items */
22
- listQuery: DocumentNode;
23
- /** The property key for the entity ID */
24
- idKey: keyof T;
25
- /** The property key for the display label */
26
- labelKey: keyof T;
27
- /** Number of items to load per page */
28
- pageSize?: number;
29
- /** Placeholder text for the search input */
30
- placeholder?: string;
31
- /** Whether to enable multi-select mode */
32
- multiple?: boolean;
33
- /** Custom filter function for search */
34
- buildSearchFilter?: (searchTerm: string) => any;
35
- /** Custom filter function for fetching by IDs */
36
- buildIdsFilter?: (ids: string[]) => any;
37
- /** Custom label renderer function for rich display */
38
- label?: (item: T) => React.ReactNode;
39
- }
40
-
41
- export interface RelationSelectorProps<T = any> {
42
- config: RelationSelectorConfig<T>;
43
- value?: string | string[];
44
- onChange: (value: string | string[]) => void;
45
- disabled?: boolean;
46
- className?: string;
47
- }
48
-
49
- export interface RelationSelectorItemProps<T = any> {
50
- item: T;
51
- config: RelationSelectorConfig<T>;
52
- isSelected: boolean;
53
- onSelect: () => void;
54
- showCheckbox?: boolean;
55
- }
56
-
57
- /**
58
- * Abstract relation selector item component
59
- */
60
- export function RelationSelectorItem<T>({
61
- item,
62
- config,
63
- isSelected,
64
- onSelect,
65
- showCheckbox = false,
66
- }: Readonly<RelationSelectorItemProps<T>>) {
67
- const id = String(item[config.idKey]);
68
- const label = config.label ? config.label(item) : String(item[config.labelKey]);
69
-
70
- return (
71
- <CommandItem key={id} value={id} onSelect={onSelect} className="flex items-center gap-2">
72
- {showCheckbox && (
73
- <Checkbox
74
- checked={isSelected}
75
- onChange={onSelect}
76
- onClick={(e: React.MouseEvent) => e.stopPropagation()}
77
- />
78
- )}
79
- {isSelected && !showCheckbox && <CheckIcon className="h-4 w-4" />}
80
- <span className="flex-1">{label}</span>
81
- </CommandItem>
82
- );
83
- }
84
-
85
- /**
86
- * Hook for managing relation selector state and queries
87
- */
88
- export function useRelationSelector<T>(config: RelationSelectorConfig<T>) {
89
- const [searchTerm, setSearchTerm] = useState('');
90
- const debouncedSearch = useDebounce(searchTerm, 300);
91
-
92
- const pageSize = config.pageSize ?? 25;
93
-
94
- // Build the default search filter if none provided
95
- const buildFilter =
96
- config.buildSearchFilter ??
97
- ((term: string) => ({
98
- [config.labelKey]: { contains: term },
99
- }));
100
-
101
- // Build the default IDs filter if none provided
102
- const buildIdsFilter = React.useCallback(
103
- (ids: string[]) => {
104
- if (config.buildIdsFilter) {
105
- return config.buildIdsFilter(ids);
106
- }
107
- return {
108
- [config.idKey]: { in: ids },
109
- };
110
- },
111
- [config.idKey, config.buildIdsFilter],
112
- );
113
-
114
- const { data, isLoading, fetchNextPage, hasNextPage, isFetchingNextPage, error } = useInfiniteQuery({
115
- queryKey: ['relationSelector', getQueryName(config.listQuery), debouncedSearch],
116
- queryFn: async ({ pageParam = 0 }) => {
117
- const variables: any = {
118
- options: {
119
- skip: pageParam * pageSize,
120
- take: pageSize,
121
- sort: { [config.labelKey]: 'ASC' },
122
- },
123
- };
124
-
125
- // Add search filter if there's a search term
126
- if (debouncedSearch.trim().length > 0) {
127
- variables.options.filter = buildFilter(debouncedSearch.trim());
128
- }
129
-
130
- const response = (await api.query(config.listQuery, variables)) as any;
131
- return response[getQueryName(config.listQuery)];
132
- },
133
- getNextPageParam: (lastPage, allPages) => {
134
- if (!lastPage) return undefined;
135
- const totalFetched = allPages.length * pageSize;
136
- return totalFetched < lastPage.totalItems ? allPages.length : undefined;
137
- },
138
- initialPageParam: 0,
139
- });
140
-
141
- const items = data?.pages.flatMap(page => page?.items ?? []) ?? [];
142
-
143
- // Function to fetch items by IDs
144
- const fetchItemsByIds = React.useCallback(
145
- async (ids: string[]): Promise<T[]> => {
146
- if (ids.length === 0) return [];
147
-
148
- const variables: any = {
149
- options: {
150
- take: ids.length,
151
- filter: buildIdsFilter(ids),
152
- },
153
- };
154
-
155
- try {
156
- const response = (await api.query(config.listQuery, variables)) as any;
157
- const result = response[getQueryName(config.listQuery)];
158
- return result?.items ?? [];
159
- } catch (error) {
160
- console.error('Error fetching items by IDs:', error);
161
- return [];
162
- }
163
- },
164
- [buildIdsFilter, config.listQuery],
165
- );
166
-
167
- return {
168
- items,
169
- isLoading,
170
- fetchNextPage,
171
- hasNextPage,
172
- isFetchingNextPage,
173
- error,
174
- searchTerm,
175
- setSearchTerm,
176
- fetchItemsByIds,
177
- };
178
- }
179
-
180
- /**
181
- * Abstract relation selector component
182
- */
183
- export function RelationSelector<T>({
184
- config,
185
- value,
186
- onChange,
187
- disabled,
188
- className,
189
- }: Readonly<RelationSelectorProps<T>>) {
190
- const [open, setOpen] = useState(false);
191
- const [selectedItemsCache, setSelectedItemsCache] = useState<T[]>([]);
192
- const fetchedIdsRef = React.useRef<Set<string>>(new Set());
193
- const fetchingIdsRef = React.useRef<Set<string>>(new Set());
194
- const isMultiple = config.multiple ?? false;
195
-
196
- const {
197
- items,
198
- isLoading,
199
- fetchNextPage,
200
- hasNextPage,
201
- isFetchingNextPage,
202
- searchTerm,
203
- setSearchTerm,
204
- fetchItemsByIds,
205
- } = useRelationSelector(config);
206
-
207
- // Store a stable reference to fetchItemsByIds
208
- const fetchItemsByIdsRef = React.useRef(fetchItemsByIds);
209
- fetchItemsByIdsRef.current = fetchItemsByIds;
210
-
211
- // Normalize value to always be an array for easier handling
212
- const selectedIds = React.useMemo(() => {
213
- if (isMultiple) {
214
- return Array.isArray(value) ? value : value ? [value] : [];
215
- }
216
- // For single select, ensure we only have at most one ID
217
- const singleValue = Array.isArray(value) ? value[0] : value;
218
- return singleValue ? [String(singleValue)] : [];
219
- }, [value, isMultiple]);
220
-
221
- // Fetch selected items by IDs on mount and when selectedIds change
222
- React.useEffect(() => {
223
- const fetchSelectedItems = async () => {
224
- if (selectedIds.length === 0) {
225
- setSelectedItemsCache([]);
226
- fetchedIdsRef.current.clear();
227
- fetchingIdsRef.current.clear();
228
- return;
229
- }
230
-
231
- // Find which selected IDs we haven't fetched yet and aren't currently fetching
232
- const missingIds = selectedIds.filter(
233
- id => !fetchedIdsRef.current.has(id) && !fetchingIdsRef.current.has(id),
234
- );
235
-
236
- if (missingIds.length > 0) {
237
- // Mark these IDs as being fetched
238
- missingIds.forEach(id => fetchingIdsRef.current.add(id));
239
-
240
- try {
241
- const fetchedItems = await fetchItemsByIdsRef.current(missingIds);
242
-
243
- // Mark these IDs as fetched and remove from fetching
244
- missingIds.forEach(id => {
245
- fetchedIdsRef.current.add(id);
246
- fetchingIdsRef.current.delete(id);
247
- });
248
-
249
- setSelectedItemsCache(prev => {
250
- if (!isMultiple) {
251
- // For single select, replace the entire cache
252
- return fetchedItems;
253
- }
254
- // For multi-select, filter and append
255
- const stillSelected = prev.filter(item =>
256
- selectedIds.includes(String(item[config.idKey])),
257
- );
258
- return [...stillSelected, ...fetchedItems];
259
- });
260
- } catch (error) {
261
- // Remove from fetching set on error
262
- missingIds.forEach(id => fetchingIdsRef.current.delete(id));
263
- console.error('Error fetching items by IDs:', error);
264
- }
265
- } else {
266
- // Just filter out items that are no longer selected
267
- setSelectedItemsCache(prev => {
268
- if (!isMultiple) {
269
- // For single select, if no items need fetching but we have a selection,
270
- // keep only items that are in the current selection
271
- return prev.filter(item => selectedIds.includes(String(item[config.idKey])));
272
- }
273
- // For multi-select, normal filtering
274
- return prev.filter(item => selectedIds.includes(String(item[config.idKey])));
275
- });
276
- }
277
-
278
- // Clean up fetched IDs that are no longer selected
279
- const selectedIdsSet = new Set(selectedIds);
280
- for (const fetchedId of fetchedIdsRef.current) {
281
- if (!selectedIdsSet.has(fetchedId)) {
282
- fetchedIdsRef.current.delete(fetchedId);
283
- }
284
- }
285
- };
286
-
287
- fetchSelectedItems();
288
- }, [selectedIds, config.idKey, isMultiple]);
289
-
290
- const handleSelect = (item: T) => {
291
- const itemId = String(item[config.idKey]);
292
-
293
- if (isMultiple) {
294
- const isCurrentlySelected = selectedIds.includes(itemId);
295
- const newSelectedIds = isCurrentlySelected
296
- ? selectedIds.filter(id => id !== itemId)
297
- : [...selectedIds, itemId];
298
-
299
- // Update cache: add item if selecting, remove if deselecting
300
- setSelectedItemsCache(prev => {
301
- if (isCurrentlySelected) {
302
- return prev.filter(prevItem => String(prevItem[config.idKey]) !== itemId);
303
- } else {
304
- // Only add if not already in cache
305
- const alreadyInCache = prev.some(prevItem => String(prevItem[config.idKey]) === itemId);
306
- return alreadyInCache ? prev : [...prev, item];
307
- }
308
- });
309
-
310
- // Mark the item as fetched to prevent duplicate fetching
311
- if (!isCurrentlySelected) {
312
- fetchedIdsRef.current.add(itemId);
313
- } else {
314
- fetchedIdsRef.current.delete(itemId);
315
- }
316
-
317
- onChange(newSelectedIds);
318
- } else {
319
- // For single select, update cache with the new item
320
- setSelectedItemsCache([item]);
321
- // Mark as fetched for single select too
322
- fetchedIdsRef.current.clear();
323
- fetchedIdsRef.current.add(itemId);
324
- onChange(itemId);
325
- setOpen(false);
326
- setSearchTerm('');
327
- }
328
- };
329
-
330
- const handleRemove = (itemId: string) => {
331
- if (isMultiple) {
332
- const newSelectedIds = selectedIds.filter(id => id !== itemId);
333
- // Remove from cache as well
334
- setSelectedItemsCache(prev => prev.filter(prevItem => String(prevItem[config.idKey]) !== itemId));
335
- onChange(newSelectedIds);
336
- } else {
337
- // Clear cache for single select
338
- setSelectedItemsCache([]);
339
- onChange('');
340
- }
341
- };
342
-
343
- const handleScroll = (e: React.UIEvent<HTMLDivElement>) => {
344
- const target = e.currentTarget;
345
- const scrolledToBottom = Math.abs(target.scrollHeight - target.clientHeight - target.scrollTop) < 1;
346
-
347
- if (scrolledToBottom && hasNextPage && !isFetchingNextPage) {
348
- fetchNextPage();
349
- }
350
- };
351
-
352
- // Get selected items for display from cache, filtered by current selection
353
- const selectedItems = React.useMemo(() => {
354
- const filteredItems = selectedItemsCache.filter(item =>
355
- selectedIds.includes(String(item[config.idKey])),
356
- );
357
- // For single select, ensure we only display one item
358
- return isMultiple ? filteredItems : filteredItems.slice(0, 1);
359
- }, [selectedItemsCache, selectedIds, config.idKey, isMultiple]);
360
-
361
- return (
362
- <div className={className}>
363
- {/* Display selected items */}
364
- {selectedItems.length > 0 && (
365
- <div className="flex flex-wrap gap-2 mb-2">
366
- {selectedItems.map(item => {
367
- const itemId = String(item[config.idKey]);
368
- const label = config.label ? config.label(item) : String(item[config.labelKey]);
369
- return (
370
- <div
371
- key={itemId}
372
- className="inline-flex items-center gap-1 bg-secondary text-secondary-foreground px-2 py-1 rounded-md text-sm"
373
- >
374
- <span>{label}</span>
375
- {!disabled && (
376
- <button
377
- type="button"
378
- onClick={() => handleRemove(itemId)}
379
- className="text-secondary-foreground/70 hover:text-secondary-foreground"
380
- >
381
- <X className="h-3 w-3" />
382
- </button>
383
- )}
384
- </div>
385
- );
386
- })}
387
- </div>
388
- )}
389
-
390
- {/* Selector trigger */}
391
- <Popover open={open} onOpenChange={setOpen}>
392
- <PopoverTrigger asChild>
393
- <Button variant="outline" size="sm" type="button" disabled={disabled} className="gap-2">
394
- <Plus className="h-4 w-4" />
395
- <Trans>
396
- {isMultiple
397
- ? selectedItems.length > 0
398
- ? `Add more (${selectedItems.length} selected)`
399
- : 'Select items'
400
- : selectedItems.length > 0
401
- ? 'Change selection'
402
- : 'Select item'}
403
- </Trans>
404
- </Button>
405
- </PopoverTrigger>
406
- <PopoverContent className="p-0 w-[400px]" align="start">
407
- <Command shouldFilter={false}>
408
- <CommandInput
409
- placeholder={config.placeholder ?? 'Search...'}
410
- value={searchTerm}
411
- onValueChange={setSearchTerm}
412
- disabled={disabled}
413
- />
414
- <CommandList className="h-[300px] overflow-y-auto" onScroll={handleScroll}>
415
- <CommandEmpty>
416
- {isLoading ? (
417
- <div className="flex items-center justify-center py-6">
418
- <Loader2 className="h-4 w-4 animate-spin mr-2" />
419
- <Trans>Loading...</Trans>
420
- </div>
421
- ) : (
422
- <Trans>No results found</Trans>
423
- )}
424
- </CommandEmpty>
425
-
426
- {items.map(item => {
427
- const itemId = String(item[config.idKey]);
428
- const isSelected = selectedIds.includes(itemId);
429
-
430
- return (
431
- <RelationSelectorItem
432
- key={itemId}
433
- item={item}
434
- config={config}
435
- isSelected={isSelected}
436
- onSelect={() => handleSelect(item)}
437
- showCheckbox={isMultiple}
438
- />
439
- );
440
- })}
441
-
442
- {(isFetchingNextPage || isLoading) && (
443
- <div className="flex items-center justify-center py-2">
444
- <Loader2 className="h-4 w-4 animate-spin" />
445
- </div>
446
- )}
447
-
448
- {!hasNextPage && items.length > 0 && (
449
- <div className="text-center py-2 text-sm text-muted-foreground">
450
- <Trans>No more items</Trans>
451
- </div>
452
- )}
453
- </CommandList>
454
- </Command>
455
- </PopoverContent>
456
- </Popover>
457
- </div>
458
- );
459
- }
460
-
461
- /**
462
- * Utility function to create a relation selector configuration
463
- */
464
- export function createRelationSelectorConfig<T>(
465
- config: Readonly<RelationSelectorConfig<T>>,
466
- ): RelationSelectorConfig<T> {
467
- return config;
468
- }
@@ -1,101 +0,0 @@
1
- import { usePermissions } from '@/vdb/hooks/use-permissions.js';
2
- import { Trans } from '@/vdb/lib/trans.js';
3
- import { cn } from '@/vdb/lib/utils.js';
4
- import { LucideIcon } from 'lucide-react';
5
- import { useState } from 'react';
6
- import {
7
- AlertDialog,
8
- AlertDialogAction,
9
- AlertDialogCancel,
10
- AlertDialogContent,
11
- AlertDialogDescription,
12
- AlertDialogFooter,
13
- AlertDialogHeader,
14
- AlertDialogTitle,
15
- AlertDialogTrigger,
16
- } from '../ui/alert-dialog.js';
17
- import { DropdownMenuItem } from '../ui/dropdown-menu.js';
18
-
19
- export interface DataTableBulkActionItemProps {
20
- label: React.ReactNode;
21
- icon?: LucideIcon;
22
- confirmationText?: React.ReactNode;
23
- onClick: () => void;
24
- className?: string;
25
- requiresPermission?: string[];
26
- }
27
-
28
- export function DataTableBulkActionItem({
29
- label,
30
- icon: Icon,
31
- confirmationText,
32
- className,
33
- onClick,
34
- requiresPermission,
35
- }: DataTableBulkActionItemProps) {
36
- const [isOpen, setIsOpen] = useState(false);
37
- const { hasPermissions } = usePermissions();
38
- const userHasPermission = hasPermissions(requiresPermission ?? []);
39
-
40
- const handleClick = (e: React.MouseEvent<HTMLDivElement>) => {
41
- e.preventDefault();
42
- e.stopPropagation();
43
- if (!userHasPermission) {
44
- return;
45
- }
46
- if (confirmationText) {
47
- setIsOpen(true);
48
- } else {
49
- onClick?.();
50
- }
51
- };
52
-
53
- const handleConfirm = () => {
54
- setIsOpen(false);
55
- onClick?.();
56
- };
57
-
58
- const handleCancel = () => {
59
- setIsOpen(false);
60
- };
61
-
62
- if (confirmationText) {
63
- return (
64
- <AlertDialog open={isOpen} onOpenChange={setIsOpen}>
65
- <AlertDialogTrigger asChild>
66
- <DropdownMenuItem onClick={handleClick} disabled={!userHasPermission}>
67
- {Icon && <Icon className={cn('mr-1 h-4 w-4', className)} />}
68
- <span className={cn('text-sm', className)}>
69
- <Trans>{label}</Trans>
70
- </span>
71
- </DropdownMenuItem>
72
- </AlertDialogTrigger>
73
- <AlertDialogContent>
74
- <AlertDialogHeader>
75
- <AlertDialogTitle>
76
- <Trans>Confirm Action</Trans>
77
- </AlertDialogTitle>
78
- <AlertDialogDescription>{confirmationText}</AlertDialogDescription>
79
- </AlertDialogHeader>
80
- <AlertDialogFooter>
81
- <AlertDialogCancel onClick={handleCancel}>
82
- <Trans>Cancel</Trans>
83
- </AlertDialogCancel>
84
- <AlertDialogAction onClick={handleConfirm}>
85
- <Trans>Continue</Trans>
86
- </AlertDialogAction>
87
- </AlertDialogFooter>
88
- </AlertDialogContent>
89
- </AlertDialog>
90
- );
91
- }
92
-
93
- return (
94
- <DropdownMenuItem onClick={handleClick}>
95
- {Icon && <Icon className={cn('mr-1 h-4 w-4', className)} />}
96
- <span className={cn('text-sm', className)}>
97
- <Trans>{label}</Trans>
98
- </span>
99
- </DropdownMenuItem>
100
- );
101
- }
@@ -1,95 +0,0 @@
1
- 'use client';
2
-
3
- import { Button } from '@/vdb/components/ui/button.js';
4
- import {
5
- DropdownMenu,
6
- DropdownMenuContent,
7
- DropdownMenuItem,
8
- DropdownMenuTrigger,
9
- } from '@/vdb/components/ui/dropdown-menu.js';
10
- import { getBulkActions } from '@/vdb/framework/data-table/data-table-extensions.js';
11
- import { BulkAction } from '@/vdb/framework/extension-api/types/index.js';
12
- import { usePageBlock } from '@/vdb/hooks/use-page-block.js';
13
- import { usePage } from '@/vdb/hooks/use-page.js';
14
- import { Trans } from '@/vdb/lib/trans.js';
15
- import { Table } from '@tanstack/react-table';
16
- import { ChevronDown } from 'lucide-react';
17
- import { useRef } from 'react';
18
-
19
- interface DataTableBulkActionsProps<TData> {
20
- table: Table<TData>;
21
- bulkActions: BulkAction[];
22
- }
23
-
24
- export function DataTableBulkActions<TData>({
25
- table,
26
- bulkActions,
27
- }: Readonly<DataTableBulkActionsProps<TData>>) {
28
- const { pageId } = usePage();
29
- const { blockId } = usePageBlock();
30
-
31
- // Cache to store selected items across page changes
32
- const selectedItemsCache = useRef<Map<string, TData>>(new Map());
33
- const selectedRowIds = Object.keys(table.getState().rowSelection);
34
-
35
- // Get selection from cache instead of trying to get from table
36
- const selection = selectedRowIds
37
- .map(key => {
38
- try {
39
- const row = table.getRow(key);
40
- if (row) {
41
- selectedItemsCache.current.set(key, row.original);
42
- return row.original;
43
- }
44
- } catch (error) {
45
- // ignore the error, it just means the row is not on the
46
- // current page.
47
- }
48
- if (selectedItemsCache.current.has(key)) {
49
- return selectedItemsCache.current.get(key);
50
- }
51
- return undefined;
52
- })
53
- .filter((item): item is TData => item !== undefined);
54
-
55
- if (selection.length === 0) {
56
- return null;
57
- }
58
- const extendedBulkActions = pageId ? getBulkActions(pageId, blockId) : [];
59
- const allBulkActions = [...extendedBulkActions, ...(bulkActions ?? [])];
60
- allBulkActions.sort((a, b) => (a.order ?? 10_000) - (b.order ?? 10_000));
61
-
62
- return (
63
- <div
64
- className="flex items-center gap-4 px-8 py-2 animate-in fade-in duration-200 absolute bottom-10 left-1/2 transform -translate-x-1/2 bg-white shadow-2xl rounded-md border"
65
- style={{ height: 'auto', maxHeight: '60px' }}
66
- >
67
- <span className="text-sm text-muted-foreground">
68
- <Trans>{selection.length} selected</Trans>
69
- </span>
70
- <DropdownMenu>
71
- <DropdownMenuTrigger asChild>
72
- <Button variant="outline" size="sm" className="h-8 shadow-none">
73
- <Trans>With selected...</Trans>
74
- <ChevronDown className="ml-2 h-4 w-4" />
75
- </Button>
76
- </DropdownMenuTrigger>
77
- <DropdownMenuContent align="start">
78
- {allBulkActions.length > 0 ? (
79
- allBulkActions.map((action, index) => (
80
- <action.component
81
- key={`bulk-action-${index}`}
82
- selection={selection}
83
- table={table}
84
- />
85
- ))
86
- ) : (
87
- <DropdownMenuItem className="text-muted-foreground" disabled>
88
- <Trans>No actions available</Trans>
89
- </DropdownMenuItem>
90
- )}
91
- </DropdownMenuContent>
92
- </DropdownMenu>
93
- </div>
94
- );
95
- }
@@ -1,21 +0,0 @@
1
- type LabeledDataProps = {
2
- label: string | React.ReactNode;
3
- value: React.ReactNode;
4
- className?: string;
5
- };
6
-
7
- /**
8
- * @description
9
- * Used to display a value with a label, like
10
- *
11
- * Order Code
12
- * QWERTY
13
- */
14
- export function LabeledData({ label, value, className }: Readonly<LabeledDataProps>) {
15
- return (
16
- <div className="">
17
- <span className="font-medium text-muted-foreground text-xs">{label}</span>
18
- <div className={`col-span-2 text-sm ${className}`}>{value}</div>
19
- </div>
20
- );
21
- }