@vendure/dashboard 3.3.6-master-202507020234 → 3.3.6-master-202507021511

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 (323) hide show
  1. package/dist/plugin/vite-plugin-config.js +2 -6
  2. package/package.json +4 -4
  3. package/src/app/app-providers.tsx +6 -6
  4. package/src/app/common/delete-bulk-action.tsx +4 -4
  5. package/src/app/common/duplicate-bulk-action.tsx +5 -5
  6. package/src/app/main.tsx +9 -9
  7. package/src/app/routes/__root.tsx +1 -2
  8. package/src/app/routes/_authenticated/_administrators/administrators.graphql.ts +1 -1
  9. package/src/app/routes/_authenticated/_administrators/administrators.tsx +8 -8
  10. package/src/app/routes/_authenticated/_administrators/administrators_.$id.tsx +11 -11
  11. package/src/app/routes/_authenticated/_administrators/components/administrator-bulk-actions.tsx +1 -1
  12. package/src/app/routes/_authenticated/_administrators/components/role-permissions-display.tsx +15 -15
  13. package/src/app/routes/_authenticated/_assets/assets.graphql.ts +2 -2
  14. package/src/app/routes/_authenticated/_assets/assets.tsx +12 -8
  15. package/src/app/routes/_authenticated/_assets/assets_.$id.tsx +14 -14
  16. package/src/app/routes/_authenticated/_assets/components/asset-bulk-actions.tsx +5 -5
  17. package/src/app/routes/_authenticated/_channels/channels.graphql.ts +1 -1
  18. package/src/app/routes/_authenticated/_channels/channels.tsx +10 -10
  19. package/src/app/routes/_authenticated/_channels/channels_.$id.tsx +16 -16
  20. package/src/app/routes/_authenticated/_channels/components/channel-bulk-actions.tsx +1 -1
  21. package/src/app/routes/_authenticated/_collections/collections.graphql.ts +3 -3
  22. package/src/app/routes/_authenticated/_collections/collections.tsx +7 -7
  23. package/src/app/routes/_authenticated/_collections/collections_.$id.tsx +15 -15
  24. package/src/app/routes/_authenticated/_collections/components/collection-bulk-actions.tsx +5 -5
  25. package/src/app/routes/_authenticated/_collections/components/collection-contents-preview-table.tsx +7 -8
  26. package/src/app/routes/_authenticated/_collections/components/collection-contents-sheet.tsx +9 -5
  27. package/src/app/routes/_authenticated/_collections/components/collection-contents-table.tsx +9 -8
  28. package/src/app/routes/_authenticated/_collections/components/collection-filters-selector.tsx +6 -6
  29. package/src/app/routes/_authenticated/_countries/components/country-bulk-actions.tsx +1 -1
  30. package/src/app/routes/_authenticated/_countries/countries.graphql.ts +1 -1
  31. package/src/app/routes/_authenticated/_countries/countries.tsx +6 -6
  32. package/src/app/routes/_authenticated/_countries/countries_.$id.tsx +12 -12
  33. package/src/app/routes/_authenticated/_customer-groups/components/customer-group-bulk-actions.tsx +1 -1
  34. package/src/app/routes/_authenticated/_customer-groups/components/customer-group-members-sheet.tsx +12 -5
  35. package/src/app/routes/_authenticated/_customer-groups/components/customer-group-members-table.tsx +22 -17
  36. package/src/app/routes/_authenticated/_customer-groups/customer-groups.graphql.ts +1 -1
  37. package/src/app/routes/_authenticated/_customer-groups/customer-groups.tsx +6 -6
  38. package/src/app/routes/_authenticated/_customer-groups/customer-groups_.$id.tsx +10 -10
  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 +9 -9
  41. package/src/app/routes/_authenticated/_customers/components/customer-bulk-actions.tsx +1 -1
  42. package/src/app/routes/_authenticated/_customers/components/customer-history/customer-history-container.tsx +4 -4
  43. package/src/app/routes/_authenticated/_customers/components/customer-history/customer-history.tsx +11 -7
  44. package/src/app/routes/_authenticated/_customers/components/customer-history/use-customer-history.ts +4 -4
  45. package/src/app/routes/_authenticated/_customers/components/customer-order-table.tsx +74 -72
  46. package/src/app/routes/_authenticated/_customers/components/customer-status-badge.tsx +3 -3
  47. package/src/app/routes/_authenticated/_customers/customers.graphql.ts +1 -1
  48. package/src/app/routes/_authenticated/_customers/customers.tsx +6 -6
  49. package/src/app/routes/_authenticated/_customers/customers_.$id.tsx +14 -14
  50. package/src/app/routes/_authenticated/_facets/components/edit-facet-value.tsx +8 -8
  51. package/src/app/routes/_authenticated/_facets/components/facet-bulk-actions.tsx +7 -7
  52. package/src/app/routes/_authenticated/_facets/components/facet-values-sheet.tsx +3 -3
  53. package/src/app/routes/_authenticated/_facets/components/facet-values-table.tsx +14 -10
  54. package/src/app/routes/_authenticated/_facets/facets.graphql.ts +1 -1
  55. package/src/app/routes/_authenticated/_facets/facets.tsx +7 -7
  56. package/src/app/routes/_authenticated/_facets/facets_.$id.tsx +12 -12
  57. package/src/app/routes/_authenticated/_global-settings/global-settings.graphql.ts +1 -1
  58. package/src/app/routes/_authenticated/_global-settings/global-settings.tsx +12 -12
  59. package/src/app/routes/_authenticated/_orders/components/customer-address-selector.tsx +10 -13
  60. package/src/app/routes/_authenticated/_orders/components/edit-order-table.tsx +92 -54
  61. package/src/app/routes/_authenticated/_orders/components/money-gross-net.tsx +10 -8
  62. package/src/app/routes/_authenticated/_orders/components/order-address.tsx +2 -3
  63. package/src/app/routes/_authenticated/_orders/components/order-history/order-history-container.tsx +66 -61
  64. package/src/app/routes/_authenticated/_orders/components/order-history/order-history.tsx +5 -5
  65. package/src/app/routes/_authenticated/_orders/components/order-history/use-order-history.ts +4 -4
  66. package/src/app/routes/_authenticated/_orders/components/order-line-custom-fields-form.tsx +10 -6
  67. package/src/app/routes/_authenticated/_orders/components/order-table-totals.tsx +38 -18
  68. package/src/app/routes/_authenticated/_orders/components/order-table.tsx +3 -3
  69. package/src/app/routes/_authenticated/_orders/components/order-tax-summary.tsx +37 -35
  70. package/src/app/routes/_authenticated/_orders/components/payment-details.tsx +3 -3
  71. package/src/app/routes/_authenticated/_orders/components/shipping-method-selector.tsx +42 -43
  72. package/src/app/routes/_authenticated/_orders/orders.graphql.ts +2 -2
  73. package/src/app/routes/_authenticated/_orders/orders.tsx +21 -20
  74. package/src/app/routes/_authenticated/_orders/orders_.$id.tsx +9 -9
  75. package/src/app/routes/_authenticated/_orders/orders_.draft.$id.tsx +188 -90
  76. package/src/app/routes/_authenticated/_payment-methods/components/payment-eligibility-checker-selector.tsx +10 -7
  77. package/src/app/routes/_authenticated/_payment-methods/components/payment-handler-selector.tsx +11 -11
  78. package/src/app/routes/_authenticated/_payment-methods/components/payment-method-bulk-actions.tsx +5 -5
  79. package/src/app/routes/_authenticated/_payment-methods/payment-methods.graphql.ts +2 -2
  80. package/src/app/routes/_authenticated/_payment-methods/payment-methods.tsx +7 -7
  81. package/src/app/routes/_authenticated/_payment-methods/payment-methods_.$id.tsx +13 -13
  82. package/src/app/routes/_authenticated/_product-variants/components/product-variant-bulk-actions.tsx +8 -8
  83. package/src/app/routes/_authenticated/_product-variants/components/variant-price-detail.tsx +7 -6
  84. package/src/app/routes/_authenticated/_product-variants/product-variants.graphql.ts +2 -2
  85. package/src/app/routes/_authenticated/_product-variants/product-variants.tsx +6 -6
  86. package/src/app/routes/_authenticated/_product-variants/product-variants_.$id.tsx +19 -19
  87. package/src/app/routes/_authenticated/_products/components/add-product-variant-dialog.tsx +10 -10
  88. package/src/app/routes/_authenticated/_products/components/assign-facet-values-dialog.tsx +7 -7
  89. package/src/app/routes/_authenticated/_products/components/create-product-options-dialog.tsx +57 -41
  90. package/src/app/routes/_authenticated/_products/components/create-product-variants-dialog.tsx +11 -11
  91. package/src/app/routes/_authenticated/_products/components/create-product-variants.tsx +14 -13
  92. package/src/app/routes/_authenticated/_products/components/option-value-input.tsx +16 -14
  93. package/src/app/routes/_authenticated/_products/components/product-bulk-actions.tsx +8 -8
  94. package/src/app/routes/_authenticated/_products/components/product-option-select.tsx +22 -33
  95. package/src/app/routes/_authenticated/_products/components/product-variants-table.tsx +6 -6
  96. package/src/app/routes/_authenticated/_products/products.graphql.ts +2 -2
  97. package/src/app/routes/_authenticated/_products/products.tsx +6 -6
  98. package/src/app/routes/_authenticated/_products/products_.$id.tsx +16 -16
  99. package/src/app/routes/_authenticated/_profile/profile.graphql.ts +1 -1
  100. package/src/app/routes/_authenticated/_profile/profile.tsx +8 -8
  101. package/src/app/routes/_authenticated/_promotions/components/promotion-actions-selector.tsx +13 -10
  102. package/src/app/routes/_authenticated/_promotions/components/promotion-bulk-actions.tsx +5 -5
  103. package/src/app/routes/_authenticated/_promotions/components/promotion-conditions-selector.tsx +13 -10
  104. package/src/app/routes/_authenticated/_promotions/promotions.graphql.ts +2 -2
  105. package/src/app/routes/_authenticated/_promotions/promotions.tsx +7 -7
  106. package/src/app/routes/_authenticated/_promotions/promotions_.$id.tsx +14 -14
  107. package/src/app/routes/_authenticated/_roles/components/expandable-permissions.tsx +4 -4
  108. package/src/app/routes/_authenticated/_roles/components/permissions-grid.tsx +20 -16
  109. package/src/app/routes/_authenticated/_roles/components/role-bulk-actions.tsx +1 -1
  110. package/src/app/routes/_authenticated/_roles/roles.graphql.ts +1 -1
  111. package/src/app/routes/_authenticated/_roles/roles.tsx +10 -10
  112. package/src/app/routes/_authenticated/_roles/roles_.$id.tsx +11 -11
  113. package/src/app/routes/_authenticated/_sellers/components/seller-bulk-actions.tsx +1 -1
  114. package/src/app/routes/_authenticated/_sellers/sellers.graphql.ts +1 -1
  115. package/src/app/routes/_authenticated/_sellers/sellers.tsx +7 -7
  116. package/src/app/routes/_authenticated/_sellers/sellers_.$id.tsx +10 -10
  117. package/src/app/routes/_authenticated/_shipping-methods/components/fulfillment-handler-selector.tsx +5 -5
  118. package/src/app/routes/_authenticated/_shipping-methods/components/shipping-calculator-selector.tsx +22 -20
  119. package/src/app/routes/_authenticated/_shipping-methods/components/shipping-eligibility-checker-selector.tsx +25 -21
  120. package/src/app/routes/_authenticated/_shipping-methods/components/shipping-method-bulk-actions.tsx +5 -5
  121. package/src/app/routes/_authenticated/_shipping-methods/components/test-shipping-method-dialog.tsx +3 -3
  122. package/src/app/routes/_authenticated/_shipping-methods/shipping-methods.graphql.ts +2 -2
  123. package/src/app/routes/_authenticated/_shipping-methods/shipping-methods.tsx +6 -6
  124. package/src/app/routes/_authenticated/_shipping-methods/shipping-methods_.$id.tsx +12 -12
  125. package/src/app/routes/_authenticated/_stock-locations/components/stock-location-bulk-actions.tsx +5 -5
  126. package/src/app/routes/_authenticated/_stock-locations/stock-locations.graphql.ts +1 -1
  127. package/src/app/routes/_authenticated/_stock-locations/stock-locations.tsx +6 -6
  128. package/src/app/routes/_authenticated/_stock-locations/stock-locations_.$id.tsx +11 -11
  129. package/src/app/routes/_authenticated/_system/components/payload-dialog.tsx +3 -3
  130. package/src/app/routes/_authenticated/_system/healthchecks.tsx +4 -4
  131. package/src/app/routes/_authenticated/_system/job-queue.graphql.ts +1 -1
  132. package/src/app/routes/_authenticated/_system/job-queue.tsx +10 -6
  133. package/src/app/routes/_authenticated/_system/scheduled-tasks.tsx +34 -28
  134. package/src/app/routes/_authenticated/_tax-categories/components/tax-category-bulk-actions.tsx +1 -1
  135. package/src/app/routes/_authenticated/_tax-categories/tax-categories.graphql.ts +1 -1
  136. package/src/app/routes/_authenticated/_tax-categories/tax-categories.tsx +7 -7
  137. package/src/app/routes/_authenticated/_tax-categories/tax-categories_.$id.tsx +11 -11
  138. package/src/app/routes/_authenticated/_tax-rates/components/tax-rate-bulk-actions.tsx +1 -1
  139. package/src/app/routes/_authenticated/_tax-rates/tax-rates.graphql.ts +1 -1
  140. package/src/app/routes/_authenticated/_tax-rates/tax-rates.tsx +8 -8
  141. package/src/app/routes/_authenticated/_tax-rates/tax-rates_.$id.tsx +14 -14
  142. package/src/app/routes/_authenticated/_zones/components/zone-bulk-actions.tsx +1 -1
  143. package/src/app/routes/_authenticated/_zones/components/zone-countries-sheet.tsx +3 -3
  144. package/src/app/routes/_authenticated/_zones/components/zone-countries-table.tsx +11 -7
  145. package/src/app/routes/_authenticated/_zones/zones.graphql.ts +1 -1
  146. package/src/app/routes/_authenticated/_zones/zones.tsx +6 -6
  147. package/src/app/routes/_authenticated/_zones/zones_.$id.tsx +10 -10
  148. package/src/app/routes/_authenticated/index.tsx +4 -4
  149. package/src/app/routes/_authenticated.tsx +3 -3
  150. package/src/app/routes/login.tsx +2 -2
  151. package/src/lib/components/data-display/date-time.tsx +1 -1
  152. package/src/lib/components/data-display/money.tsx +2 -3
  153. package/src/lib/components/data-input/affixed-input.tsx +2 -7
  154. package/src/lib/components/data-input/customer-group-input.tsx +2 -2
  155. package/src/lib/components/data-input/datetime-input.tsx +129 -146
  156. package/src/lib/components/data-input/facet-value-input.tsx +30 -22
  157. package/src/lib/components/data-input/money-input.tsx +3 -3
  158. package/src/lib/components/data-table/add-filter-menu.tsx +8 -17
  159. package/src/lib/components/data-table/data-table-bulk-action-item.tsx +3 -3
  160. package/src/lib/components/data-table/data-table-bulk-actions.tsx +7 -7
  161. package/src/lib/components/data-table/data-table-column-header.tsx +3 -21
  162. package/src/lib/components/data-table/data-table-faceted-filter.tsx +8 -8
  163. package/src/lib/components/data-table/data-table-filter-badge.tsx +1 -1
  164. package/src/lib/components/data-table/data-table-filter-dialog.tsx +3 -3
  165. package/src/lib/components/data-table/data-table-pagination.tsx +2 -2
  166. package/src/lib/components/data-table/data-table-view-options.tsx +25 -21
  167. package/src/lib/components/data-table/data-table.tsx +8 -8
  168. package/src/lib/components/data-table/filters/data-table-boolean-filter.tsx +7 -7
  169. package/src/lib/components/data-table/filters/data-table-datetime-filter.tsx +10 -22
  170. package/src/lib/components/data-table/filters/data-table-id-filter.tsx +14 -9
  171. package/src/lib/components/data-table/filters/data-table-number-filter.tsx +13 -16
  172. package/src/lib/components/data-table/filters/data-table-string-filter.tsx +25 -11
  173. package/src/lib/components/data-table/human-readable-operator.tsx +1 -1
  174. package/src/lib/components/data-table/refresh-button.tsx +1 -1
  175. package/src/lib/components/layout/app-layout.tsx +8 -8
  176. package/src/lib/components/layout/app-sidebar.tsx +5 -5
  177. package/src/lib/components/layout/channel-switcher.tsx +8 -8
  178. package/src/lib/components/layout/content-language-selector.tsx +16 -10
  179. package/src/lib/components/layout/generated-breadcrumbs.tsx +1 -1
  180. package/src/lib/components/layout/language-dialog.tsx +5 -11
  181. package/src/lib/components/layout/nav-main.tsx +3 -3
  182. package/src/lib/components/layout/nav-projects.tsx +2 -2
  183. package/src/lib/components/layout/nav-user.tsx +7 -7
  184. package/src/lib/components/layout/prerelease-popup.tsx +1 -1
  185. package/src/lib/components/login/login-form.tsx +5 -5
  186. package/src/lib/components/shared/alerts.tsx +3 -3
  187. package/src/lib/components/shared/animated-number.tsx +2 -2
  188. package/src/lib/components/shared/asset/asset-bulk-actions.tsx +11 -7
  189. package/src/lib/components/shared/asset/asset-focal-point-editor.tsx +29 -19
  190. package/src/lib/components/shared/asset/asset-gallery.tsx +12 -12
  191. package/src/lib/components/shared/asset/asset-picker-dialog.tsx +63 -66
  192. package/src/lib/components/shared/asset/asset-preview-dialog.tsx +3 -7
  193. package/src/lib/components/shared/asset/asset-preview-selector.tsx +3 -5
  194. package/src/lib/components/shared/asset/asset-preview.tsx +7 -15
  195. package/src/lib/components/shared/asset/asset-properties.tsx +6 -8
  196. package/src/lib/components/shared/asset/focal-point-control.tsx +5 -13
  197. package/src/lib/components/shared/assign-to-channel-bulk-action.tsx +4 -4
  198. package/src/lib/components/shared/assign-to-channel-dialog.tsx +8 -8
  199. package/src/lib/components/shared/channel-code-label.tsx +2 -3
  200. package/src/lib/components/shared/channel-selector.tsx +6 -6
  201. package/src/lib/components/shared/configurable-operation-arg-input.tsx +2 -2
  202. package/src/lib/components/shared/configurable-operation-input.tsx +15 -16
  203. package/src/lib/components/shared/confirmation-dialog.tsx +2 -2
  204. package/src/lib/components/shared/country-selector.tsx +21 -18
  205. package/src/lib/components/shared/currency-selector.tsx +5 -5
  206. package/src/lib/components/shared/custom-fields-form.tsx +8 -8
  207. package/src/lib/components/shared/customer-address-form.tsx +3 -3
  208. package/src/lib/components/shared/customer-group-selector.tsx +6 -6
  209. package/src/lib/components/shared/customer-selector.tsx +24 -18
  210. package/src/lib/components/shared/entity-assets.tsx +33 -34
  211. package/src/lib/components/shared/error-page.tsx +5 -5
  212. package/src/lib/components/shared/facet-value-chip.tsx +12 -5
  213. package/src/lib/components/shared/facet-value-selector.tsx +64 -63
  214. package/src/lib/components/shared/history-timeline/history-entry.tsx +5 -5
  215. package/src/lib/components/shared/history-timeline/history-note-checkbox.tsx +2 -2
  216. package/src/lib/components/shared/history-timeline/history-note-editor.tsx +4 -4
  217. package/src/lib/components/shared/history-timeline/history-note-input.tsx +2 -2
  218. package/src/lib/components/shared/history-timeline/history-timeline.tsx +14 -7
  219. package/src/lib/components/shared/language-selector.tsx +5 -5
  220. package/src/lib/components/shared/multi-select.tsx +5 -5
  221. package/src/lib/components/shared/navigation-confirmation.tsx +24 -9
  222. package/src/lib/components/shared/option-value-input.tsx +16 -14
  223. package/src/lib/components/shared/paginated-list-data-table.tsx +12 -12
  224. package/src/lib/components/shared/permission-guard.tsx +4 -4
  225. package/src/lib/components/shared/product-variant-selector.tsx +31 -30
  226. package/src/lib/components/shared/remove-from-channel-bulk-action.tsx +4 -4
  227. package/src/lib/components/shared/role-code-label.tsx +9 -5
  228. package/src/lib/components/shared/role-selector.tsx +4 -4
  229. package/src/lib/components/shared/seller-selector.tsx +21 -17
  230. package/src/lib/components/shared/tax-category-selector.tsx +4 -4
  231. package/src/lib/components/shared/translatable-form-field.tsx +1 -1
  232. package/src/lib/components/shared/vendure-image.tsx +1 -1
  233. package/src/lib/components/shared/zone-selector.tsx +4 -5
  234. package/src/lib/components/ui/accordion.tsx +3 -3
  235. package/src/lib/components/ui/alert-dialog.tsx +10 -10
  236. package/src/lib/components/ui/alert.tsx +3 -3
  237. package/src/lib/components/ui/badge.tsx +2 -2
  238. package/src/lib/components/ui/breadcrumb.tsx +4 -4
  239. package/src/lib/components/ui/button.tsx +10 -3
  240. package/src/lib/components/ui/calendar.tsx +392 -459
  241. package/src/lib/components/ui/card.tsx +2 -2
  242. package/src/lib/components/ui/checkbox.tsx +2 -2
  243. package/src/lib/components/ui/command.tsx +12 -6
  244. package/src/lib/components/ui/dialog.tsx +2 -2
  245. package/src/lib/components/ui/dropdown-menu.tsx +7 -7
  246. package/src/lib/components/ui/form.tsx +4 -4
  247. package/src/lib/components/ui/hover-card.tsx +3 -3
  248. package/src/lib/components/ui/input.tsx +1 -1
  249. package/src/lib/components/ui/label.tsx +2 -2
  250. package/src/lib/components/ui/pagination.tsx +87 -108
  251. package/src/lib/components/ui/popover.tsx +3 -3
  252. package/src/lib/components/ui/scroll-area.tsx +2 -2
  253. package/src/lib/components/ui/select.tsx +2 -2
  254. package/src/lib/components/ui/separator.tsx +2 -2
  255. package/src/lib/components/ui/sheet.tsx +5 -5
  256. package/src/lib/components/ui/sidebar.tsx +10 -10
  257. package/src/lib/components/ui/skeleton.tsx +1 -1
  258. package/src/lib/components/ui/switch.tsx +2 -2
  259. package/src/lib/components/ui/table.tsx +2 -2
  260. package/src/lib/components/ui/tabs.tsx +3 -3
  261. package/src/lib/components/ui/textarea.tsx +1 -1
  262. package/src/lib/components/ui/tooltip.tsx +3 -3
  263. package/src/lib/framework/alert/alert-item.tsx +3 -2
  264. package/src/lib/framework/component-registry/component-registry.tsx +31 -47
  265. package/src/lib/framework/dashboard-widget/base-widget.tsx +4 -4
  266. package/src/lib/framework/dashboard-widget/latest-orders-widget/index.tsx +7 -8
  267. package/src/lib/framework/dashboard-widget/latest-orders-widget/latest-orders-widget.graphql.ts +1 -1
  268. package/src/lib/framework/dashboard-widget/metrics-widget/index.tsx +6 -7
  269. package/src/lib/framework/dashboard-widget/metrics-widget/metrics-widget.graphql.ts +1 -1
  270. package/src/lib/framework/dashboard-widget/orders-summary/index.tsx +6 -6
  271. package/src/lib/framework/dashboard-widget/orders-summary/order-summary-widget.graphql.ts +1 -1
  272. package/src/lib/framework/data-table/data-table-extensions.ts +1 -1
  273. package/src/lib/framework/defaults.ts +1 -1
  274. package/src/lib/framework/document-extension/extend-detail-form-query.ts +2 -2
  275. package/src/lib/framework/document-extension/extend-document.spec.ts +1 -1
  276. package/src/lib/framework/document-extension/extend-document.ts +1 -1
  277. package/src/lib/framework/document-introspection/add-custom-fields.ts +2 -2
  278. package/src/lib/framework/document-introspection/hooks.ts +4 -1
  279. package/src/lib/framework/extension-api/define-dashboard-extension.ts +29 -95
  280. package/src/lib/framework/extension-api/display-component-extensions.tsx +69 -0
  281. package/src/lib/framework/extension-api/extension-api-types.ts +18 -160
  282. package/src/lib/framework/extension-api/input-component-extensions.tsx +69 -0
  283. package/src/lib/framework/extension-api/logic/alerts.ts +10 -0
  284. package/src/lib/framework/extension-api/logic/data-table.ts +60 -0
  285. package/src/lib/framework/extension-api/logic/detail-forms.ts +48 -0
  286. package/src/lib/framework/extension-api/logic/form-components.ts +13 -0
  287. package/src/lib/framework/extension-api/logic/index.ts +8 -0
  288. package/src/lib/framework/extension-api/logic/layout.ts +22 -0
  289. package/src/lib/framework/extension-api/logic/navigation.ts +37 -0
  290. package/src/lib/framework/extension-api/logic/widgets.ts +10 -0
  291. package/src/lib/framework/extension-api/types/alerts.ts +54 -0
  292. package/src/lib/framework/extension-api/types/data-table.ts +64 -0
  293. package/src/lib/framework/extension-api/types/detail-forms.ts +81 -0
  294. package/src/lib/framework/extension-api/types/form-components.ts +32 -0
  295. package/src/lib/framework/extension-api/types/index.ts +8 -0
  296. package/src/lib/framework/extension-api/types/layout.ts +78 -0
  297. package/src/lib/framework/extension-api/types/navigation.ts +19 -0
  298. package/src/lib/framework/extension-api/types/widgets.ts +94 -0
  299. package/src/lib/framework/form-engine/form-schema-tools.ts +1 -1
  300. package/src/lib/framework/layout-engine/location-wrapper.tsx +7 -7
  301. package/src/lib/framework/layout-engine/page-block-provider.tsx +1 -1
  302. package/src/lib/framework/layout-engine/page-layout.tsx +10 -10
  303. package/src/lib/framework/page/detail-page-route-loader.tsx +3 -3
  304. package/src/lib/framework/page/detail-page.tsx +57 -12
  305. package/src/lib/framework/page/list-page.tsx +10 -4
  306. package/src/lib/framework/page/use-detail-page.ts +1 -1
  307. package/src/lib/framework/registry/registry-types.ts +3 -0
  308. package/src/lib/graphql/graphql-env.d.ts +14 -31
  309. package/src/lib/hooks/use-auth.tsx +1 -1
  310. package/src/lib/hooks/use-channel.ts +1 -2
  311. package/src/lib/hooks/use-extended-detail-query.ts +2 -3
  312. package/src/lib/hooks/use-extended-list-query.ts +3 -4
  313. package/src/lib/hooks/use-grouped-permissions.ts +1 -2
  314. package/src/lib/hooks/use-page-block.tsx +1 -1
  315. package/src/lib/hooks/use-page.tsx +1 -1
  316. package/src/lib/hooks/use-server-config.ts +1 -2
  317. package/src/lib/hooks/use-theme.ts +1 -2
  318. package/src/lib/hooks/use-user-settings.tsx +1 -1
  319. package/src/lib/index.ts +28 -0
  320. package/src/lib/providers/auth.tsx +3 -3
  321. package/src/lib/providers/channel-provider.tsx +3 -3
  322. package/src/lib/providers/server-config.tsx +13 -11
  323. package/vite/vite-plugin-config.ts +3 -6
@@ -1,59 +1,53 @@
1
- "use client"
1
+ 'use client';
2
2
 
3
3
  // A custom calendar that is compatible
4
4
  // with react-day-picker v9 from https://date-picker.luca-felix.com/
5
5
 
6
- import { Button, buttonVariants } from "@/components/ui/button.js"
7
- import { cn } from "@/lib/utils.js"
8
- import { differenceInCalendarDays } from "date-fns"
9
- import { ChevronLeft, ChevronRight } from "lucide-react"
10
- import * as React from "react"
11
- import {
12
- DayPicker,
13
- labelNext,
14
- labelPrevious,
15
- useDayPicker,
16
- type DayPickerProps,
17
- } from "react-day-picker"
6
+ import { Button, buttonVariants } from '@/vdb/components/ui/button.js';
7
+ import { cn } from '@/vdb/lib/utils.js';
8
+ import { differenceInCalendarDays } from 'date-fns';
9
+ import { ChevronLeft, ChevronRight } from 'lucide-react';
10
+ import * as React from 'react';
11
+ import { DayPicker, labelNext, labelPrevious, useDayPicker, type DayPickerProps } from 'react-day-picker';
18
12
 
19
13
  export type CalendarProps = DayPickerProps & {
20
- /**
21
- * In the year view, the number of years to display at once.
22
- * @default 12
23
- */
24
- yearRange?: number
14
+ /**
15
+ * In the year view, the number of years to display at once.
16
+ * @default 12
17
+ */
18
+ yearRange?: number;
25
19
 
26
- /**
27
- * Wether to show the year switcher in the caption.
28
- * @default true
29
- */
30
- showYearSwitcher?: boolean
20
+ /**
21
+ * Wether to show the year switcher in the caption.
22
+ * @default true
23
+ */
24
+ showYearSwitcher?: boolean;
31
25
 
32
- monthsClassName?: string
33
- monthCaptionClassName?: string
34
- weekdaysClassName?: string
35
- weekdayClassName?: string
36
- monthClassName?: string
37
- captionClassName?: string
38
- captionLabelClassName?: string
39
- buttonNextClassName?: string
40
- buttonPreviousClassName?: string
41
- navClassName?: string
42
- monthGridClassName?: string
43
- weekClassName?: string
44
- dayClassName?: string
45
- dayButtonClassName?: string
46
- rangeStartClassName?: string
47
- rangeEndClassName?: string
48
- selectedClassName?: string
49
- todayClassName?: string
50
- outsideClassName?: string
51
- disabledClassName?: string
52
- rangeMiddleClassName?: string
53
- hiddenClassName?: string
54
- }
26
+ monthsClassName?: string;
27
+ monthCaptionClassName?: string;
28
+ weekdaysClassName?: string;
29
+ weekdayClassName?: string;
30
+ monthClassName?: string;
31
+ captionClassName?: string;
32
+ captionLabelClassName?: string;
33
+ buttonNextClassName?: string;
34
+ buttonPreviousClassName?: string;
35
+ navClassName?: string;
36
+ monthGridClassName?: string;
37
+ weekClassName?: string;
38
+ dayClassName?: string;
39
+ dayButtonClassName?: string;
40
+ rangeStartClassName?: string;
41
+ rangeEndClassName?: string;
42
+ selectedClassName?: string;
43
+ todayClassName?: string;
44
+ outsideClassName?: string;
45
+ disabledClassName?: string;
46
+ rangeMiddleClassName?: string;
47
+ hiddenClassName?: string;
48
+ };
55
49
 
56
- type NavView = "days" | "years"
50
+ type NavView = 'days' | 'years';
57
51
 
58
52
  /**
59
53
  * A custom calendar component built on top of react-day-picker.
@@ -62,453 +56,392 @@ type NavView = "days" | "years"
62
56
  * @returns
63
57
  */
64
58
  function Calendar({
65
- className,
66
- showOutsideDays = true,
67
- showYearSwitcher = true,
68
- yearRange = 12,
69
- numberOfMonths,
70
- ...props
59
+ className,
60
+ showOutsideDays = true,
61
+ showYearSwitcher = true,
62
+ yearRange = 12,
63
+ numberOfMonths,
64
+ ...props
71
65
  }: CalendarProps) {
72
- const [navView, setNavView] = React.useState<NavView>("days")
73
- const [displayYears, setDisplayYears] = React.useState<{
74
- from: number
75
- to: number
76
- }>(
77
- React.useMemo(() => {
78
- const currentYear = new Date().getFullYear()
79
- return {
80
- from: currentYear - Math.floor(yearRange / 2 - 1),
81
- to: currentYear + Math.ceil(yearRange / 2),
82
- }
83
- }, [yearRange])
84
- )
66
+ const [navView, setNavView] = React.useState<NavView>('days');
67
+ const [displayYears, setDisplayYears] = React.useState<{
68
+ from: number;
69
+ to: number;
70
+ }>(
71
+ React.useMemo(() => {
72
+ const currentYear = new Date().getFullYear();
73
+ return {
74
+ from: currentYear - Math.floor(yearRange / 2 - 1),
75
+ to: currentYear + Math.ceil(yearRange / 2),
76
+ };
77
+ }, [yearRange]),
78
+ );
85
79
 
86
- const { onNextClick, onPrevClick, startMonth, endMonth } = props
80
+ const { onNextClick, onPrevClick, startMonth, endMonth } = props;
87
81
 
88
- const columnsDisplayed = navView === "years" ? 1 : numberOfMonths
82
+ const columnsDisplayed = navView === 'years' ? 1 : numberOfMonths;
89
83
 
90
- const _monthsClassName = cn("relative flex", props.monthsClassName)
91
- const _monthCaptionClassName = cn(
92
- "relative mx-10 flex h-7 items-center justify-center",
93
- props.monthCaptionClassName
94
- )
95
- const _weekdaysClassName = cn("flex flex-row", props.weekdaysClassName)
96
- const _weekdayClassName = cn(
97
- "w-8 text-sm font-normal text-muted-foreground",
98
- props.weekdayClassName
99
- )
100
- const _monthClassName = cn("w-full", props.monthClassName)
101
- const _captionClassName = cn(
102
- "relative flex items-center justify-center pt-1",
103
- props.captionClassName
104
- )
105
- const _captionLabelClassName = cn(
106
- "truncate text-sm font-medium",
107
- props.captionLabelClassName
108
- )
109
- const buttonNavClassName = buttonVariants({
110
- variant: "outline",
111
- className:
112
- "absolute h-7 w-7 bg-transparent p-0 opacity-50 hover:opacity-100",
113
- })
114
- const _buttonNextClassName = cn(
115
- buttonNavClassName,
116
- "right-0",
117
- props.buttonNextClassName
118
- )
119
- const _buttonPreviousClassName = cn(
120
- buttonNavClassName,
121
- "left-0",
122
- props.buttonPreviousClassName
123
- )
124
- const _navClassName = cn("flex items-start", props.navClassName)
125
- const _monthGridClassName = cn("mx-auto mt-4", props.monthGridClassName)
126
- const _weekClassName = cn("mt-2 flex w-max items-start", props.weekClassName)
127
- const _dayClassName = cn(
128
- "flex size-8 flex-1 items-center justify-center p-0 text-sm",
129
- props.dayClassName
130
- )
131
- const _dayButtonClassName = cn(
132
- buttonVariants({ variant: "ghost" }),
133
- "size-8 rounded-md p-0 font-normal transition-none aria-selected:opacity-100",
134
- props.dayButtonClassName
135
- )
136
- const buttonRangeClassName =
137
- "bg-accent [&>button]:bg-primary [&>button]:text-primary-foreground [&>button]:hover:bg-primary [&>button]:hover:text-primary-foreground"
138
- const _rangeStartClassName = cn(
139
- buttonRangeClassName,
140
- "day-range-start rounded-s-md",
141
- props.rangeStartClassName
142
- )
143
- const _rangeEndClassName = cn(
144
- buttonRangeClassName,
145
- "day-range-end rounded-e-md",
146
- props.rangeEndClassName
147
- )
148
- const _rangeMiddleClassName = cn(
149
- "bg-accent !text-foreground [&>button]:bg-transparent [&>button]:!text-foreground [&>button]:hover:bg-transparent [&>button]:hover:!text-foreground",
150
- props.rangeMiddleClassName
151
- )
152
- const _selectedClassName = cn(
153
- "[&>button]:bg-primary [&>button]:text-primary-foreground [&>button]:hover:bg-primary [&>button]:hover:text-primary-foreground",
154
- props.selectedClassName
155
- )
156
- const _todayClassName = cn(
157
- "[&>button]:bg-accent [&>button]:text-accent-foreground",
158
- props.todayClassName
159
- )
160
- const _outsideClassName = cn(
161
- "day-outside text-muted-foreground opacity-50 aria-selected:bg-accent/50 aria-selected:text-muted-foreground aria-selected:opacity-30",
162
- props.outsideClassName
163
- )
164
- const _disabledClassName = cn(
165
- "text-muted-foreground opacity-50",
166
- props.disabledClassName
167
- )
168
- const _hiddenClassName = cn("invisible flex-1", props.hiddenClassName)
84
+ const _monthsClassName = cn('relative flex', props.monthsClassName);
85
+ const _monthCaptionClassName = cn(
86
+ 'relative mx-10 flex h-7 items-center justify-center',
87
+ props.monthCaptionClassName,
88
+ );
89
+ const _weekdaysClassName = cn('flex flex-row', props.weekdaysClassName);
90
+ const _weekdayClassName = cn('w-8 text-sm font-normal text-muted-foreground', props.weekdayClassName);
91
+ const _monthClassName = cn('w-full', props.monthClassName);
92
+ const _captionClassName = cn('relative flex items-center justify-center pt-1', props.captionClassName);
93
+ const _captionLabelClassName = cn('truncate text-sm font-medium', props.captionLabelClassName);
94
+ const buttonNavClassName = buttonVariants({
95
+ variant: 'outline',
96
+ className: 'absolute h-7 w-7 bg-transparent p-0 opacity-50 hover:opacity-100',
97
+ });
98
+ const _buttonNextClassName = cn(buttonNavClassName, 'right-0', props.buttonNextClassName);
99
+ const _buttonPreviousClassName = cn(buttonNavClassName, 'left-0', props.buttonPreviousClassName);
100
+ const _navClassName = cn('flex items-start', props.navClassName);
101
+ const _monthGridClassName = cn('mx-auto mt-4', props.monthGridClassName);
102
+ const _weekClassName = cn('mt-2 flex w-max items-start', props.weekClassName);
103
+ const _dayClassName = cn(
104
+ 'flex size-8 flex-1 items-center justify-center p-0 text-sm',
105
+ props.dayClassName,
106
+ );
107
+ const _dayButtonClassName = cn(
108
+ buttonVariants({ variant: 'ghost' }),
109
+ 'size-8 rounded-md p-0 font-normal transition-none aria-selected:opacity-100',
110
+ props.dayButtonClassName,
111
+ );
112
+ const buttonRangeClassName =
113
+ 'bg-accent [&>button]:bg-primary [&>button]:text-primary-foreground [&>button]:hover:bg-primary [&>button]:hover:text-primary-foreground';
114
+ const _rangeStartClassName = cn(
115
+ buttonRangeClassName,
116
+ 'day-range-start rounded-s-md',
117
+ props.rangeStartClassName,
118
+ );
119
+ const _rangeEndClassName = cn(
120
+ buttonRangeClassName,
121
+ 'day-range-end rounded-e-md',
122
+ props.rangeEndClassName,
123
+ );
124
+ const _rangeMiddleClassName = cn(
125
+ 'bg-accent !text-foreground [&>button]:bg-transparent [&>button]:!text-foreground [&>button]:hover:bg-transparent [&>button]:hover:!text-foreground',
126
+ props.rangeMiddleClassName,
127
+ );
128
+ const _selectedClassName = cn(
129
+ '[&>button]:bg-primary [&>button]:text-primary-foreground [&>button]:hover:bg-primary [&>button]:hover:text-primary-foreground',
130
+ props.selectedClassName,
131
+ );
132
+ const _todayClassName = cn(
133
+ '[&>button]:bg-accent [&>button]:text-accent-foreground',
134
+ props.todayClassName,
135
+ );
136
+ const _outsideClassName = cn(
137
+ 'day-outside text-muted-foreground opacity-50 aria-selected:bg-accent/50 aria-selected:text-muted-foreground aria-selected:opacity-30',
138
+ props.outsideClassName,
139
+ );
140
+ const _disabledClassName = cn('text-muted-foreground opacity-50', props.disabledClassName);
141
+ const _hiddenClassName = cn('invisible flex-1', props.hiddenClassName);
169
142
 
170
- return (
171
- <DayPicker
172
- showOutsideDays={showOutsideDays}
173
- className={cn("p-3", className)}
174
- style={{
175
- width: 248.8 * (columnsDisplayed ?? 1) + "px",
176
- }}
177
- classNames={{
178
- months: _monthsClassName,
179
- month_caption: _monthCaptionClassName,
180
- weekdays: _weekdaysClassName,
181
- weekday: _weekdayClassName,
182
- month: _monthClassName,
183
- caption: _captionClassName,
184
- caption_label: _captionLabelClassName,
185
- button_next: _buttonNextClassName,
186
- button_previous: _buttonPreviousClassName,
187
- nav: _navClassName,
188
- month_grid: _monthGridClassName,
189
- week: _weekClassName,
190
- day: _dayClassName,
191
- day_button: _dayButtonClassName,
192
- range_start: _rangeStartClassName,
193
- range_middle: _rangeMiddleClassName,
194
- range_end: _rangeEndClassName,
195
- selected: _selectedClassName,
196
- today: _todayClassName,
197
- outside: _outsideClassName,
198
- disabled: _disabledClassName,
199
- hidden: _hiddenClassName,
200
- }}
201
- components={{
202
- Chevron: ({ orientation }) => {
203
- const Icon = orientation === "left" ? ChevronLeft : ChevronRight
204
- return <Icon className="h-4 w-4" />
205
- },
206
- Nav: ({ className }) => (
207
- <Nav
208
- className={className}
209
- displayYears={displayYears}
210
- navView={navView}
211
- setDisplayYears={setDisplayYears}
212
- startMonth={startMonth}
213
- endMonth={endMonth}
214
- onPrevClick={onPrevClick}
215
- />
216
- ),
217
- CaptionLabel: (props) => (
218
- <CaptionLabel
219
- showYearSwitcher={showYearSwitcher}
220
- navView={navView}
221
- setNavView={setNavView}
222
- displayYears={displayYears}
223
- {...props}
224
- />
225
- ),
226
- MonthGrid: ({ className, children, ...props }) => (
227
- <MonthGrid
228
- children={children}
229
- className={className}
230
- displayYears={displayYears}
231
- startMonth={startMonth}
232
- endMonth={endMonth}
233
- navView={navView}
234
- setNavView={setNavView}
143
+ return (
144
+ <DayPicker
145
+ showOutsideDays={showOutsideDays}
146
+ className={cn('p-3', className)}
147
+ style={{
148
+ width: 248.8 * (columnsDisplayed ?? 1) + 'px',
149
+ }}
150
+ classNames={{
151
+ months: _monthsClassName,
152
+ month_caption: _monthCaptionClassName,
153
+ weekdays: _weekdaysClassName,
154
+ weekday: _weekdayClassName,
155
+ month: _monthClassName,
156
+ caption: _captionClassName,
157
+ caption_label: _captionLabelClassName,
158
+ button_next: _buttonNextClassName,
159
+ button_previous: _buttonPreviousClassName,
160
+ nav: _navClassName,
161
+ month_grid: _monthGridClassName,
162
+ week: _weekClassName,
163
+ day: _dayClassName,
164
+ day_button: _dayButtonClassName,
165
+ range_start: _rangeStartClassName,
166
+ range_middle: _rangeMiddleClassName,
167
+ range_end: _rangeEndClassName,
168
+ selected: _selectedClassName,
169
+ today: _todayClassName,
170
+ outside: _outsideClassName,
171
+ disabled: _disabledClassName,
172
+ hidden: _hiddenClassName,
173
+ }}
174
+ components={{
175
+ Chevron: ({ orientation }) => {
176
+ const Icon = orientation === 'left' ? ChevronLeft : ChevronRight;
177
+ return <Icon className="h-4 w-4" />;
178
+ },
179
+ Nav: ({ className }) => (
180
+ <Nav
181
+ className={className}
182
+ displayYears={displayYears}
183
+ navView={navView}
184
+ setDisplayYears={setDisplayYears}
185
+ startMonth={startMonth}
186
+ endMonth={endMonth}
187
+ onPrevClick={onPrevClick}
188
+ />
189
+ ),
190
+ CaptionLabel: props => (
191
+ <CaptionLabel
192
+ showYearSwitcher={showYearSwitcher}
193
+ navView={navView}
194
+ setNavView={setNavView}
195
+ displayYears={displayYears}
196
+ {...props}
197
+ />
198
+ ),
199
+ MonthGrid: ({ className, children, ...props }) => (
200
+ <MonthGrid
201
+ children={children}
202
+ className={className}
203
+ displayYears={displayYears}
204
+ startMonth={startMonth}
205
+ endMonth={endMonth}
206
+ navView={navView}
207
+ setNavView={setNavView}
208
+ {...props}
209
+ />
210
+ ),
211
+ }}
212
+ numberOfMonths={columnsDisplayed}
235
213
  {...props}
236
- />
237
- ),
238
- }}
239
- numberOfMonths={columnsDisplayed}
240
- {...props}
241
- />
242
- )
214
+ />
215
+ );
243
216
  }
244
- Calendar.displayName = "Calendar"
217
+
218
+ Calendar.displayName = 'Calendar';
245
219
 
246
220
  function Nav({
247
- className,
248
- navView,
249
- startMonth,
250
- endMonth,
251
- displayYears,
252
- setDisplayYears,
253
- onPrevClick,
254
- onNextClick,
221
+ className,
222
+ navView,
223
+ startMonth,
224
+ endMonth,
225
+ displayYears,
226
+ setDisplayYears,
227
+ onPrevClick,
228
+ onNextClick,
255
229
  }: {
256
- className?: string
257
- navView: NavView
258
- startMonth?: Date
259
- endMonth?: Date
260
- displayYears: { from: number; to: number }
261
- setDisplayYears: React.Dispatch<
262
- React.SetStateAction<{ from: number; to: number }>
263
- >
264
- onPrevClick?: (date: Date) => void
265
- onNextClick?: (date: Date) => void
230
+ className?: string;
231
+ navView: NavView;
232
+ startMonth?: Date;
233
+ endMonth?: Date;
234
+ displayYears: { from: number; to: number };
235
+ setDisplayYears: React.Dispatch<React.SetStateAction<{ from: number; to: number }>>;
236
+ onPrevClick?: (date: Date) => void;
237
+ onNextClick?: (date: Date) => void;
266
238
  }) {
267
- const { nextMonth, previousMonth, goToMonth } = useDayPicker()
239
+ const { nextMonth, previousMonth, goToMonth } = useDayPicker();
268
240
 
269
- const isPreviousDisabled = (() => {
270
- if (navView === "years") {
271
- return (
272
- (startMonth &&
273
- differenceInCalendarDays(
274
- new Date(displayYears.from - 1, 0, 1),
275
- startMonth
276
- ) < 0) ||
277
- (endMonth &&
278
- differenceInCalendarDays(
279
- new Date(displayYears.from - 1, 0, 1),
280
- endMonth
281
- ) > 0)
282
- )
283
- }
284
- return !previousMonth
285
- })()
286
-
287
- const isNextDisabled = (() => {
288
- if (navView === "years") {
289
- return (
290
- (startMonth &&
291
- differenceInCalendarDays(
292
- new Date(displayYears.to + 1, 0, 1),
293
- startMonth
294
- ) < 0) ||
295
- (endMonth &&
296
- differenceInCalendarDays(
297
- new Date(displayYears.to + 1, 0, 1),
298
- endMonth
299
- ) > 0)
300
- )
301
- }
302
- return !nextMonth
303
- })()
241
+ const isPreviousDisabled = (() => {
242
+ if (navView === 'years') {
243
+ return (
244
+ (startMonth &&
245
+ differenceInCalendarDays(new Date(displayYears.from - 1, 0, 1), startMonth) < 0) ||
246
+ (endMonth && differenceInCalendarDays(new Date(displayYears.from - 1, 0, 1), endMonth) > 0)
247
+ );
248
+ }
249
+ return !previousMonth;
250
+ })();
304
251
 
305
- const handlePreviousClick = React.useCallback(() => {
306
- if (!previousMonth) return
307
- if (navView === "years") {
308
- setDisplayYears((prev) => ({
309
- from: prev.from - (prev.to - prev.from + 1),
310
- to: prev.to - (prev.to - prev.from + 1),
311
- }))
312
- onPrevClick?.(
313
- new Date(
314
- displayYears.from - (displayYears.to - displayYears.from),
315
- 0,
316
- 1
317
- )
318
- )
319
- return
320
- }
321
- goToMonth(previousMonth)
322
- onPrevClick?.(previousMonth)
323
- }, [previousMonth, goToMonth])
252
+ const isNextDisabled = (() => {
253
+ if (navView === 'years') {
254
+ return (
255
+ (startMonth &&
256
+ differenceInCalendarDays(new Date(displayYears.to + 1, 0, 1), startMonth) < 0) ||
257
+ (endMonth && differenceInCalendarDays(new Date(displayYears.to + 1, 0, 1), endMonth) > 0)
258
+ );
259
+ }
260
+ return !nextMonth;
261
+ })();
324
262
 
325
- const handleNextClick = React.useCallback(() => {
326
- if (!nextMonth) return
327
- if (navView === "years") {
328
- setDisplayYears((prev) => ({
329
- from: prev.from + (prev.to - prev.from + 1),
330
- to: prev.to + (prev.to - prev.from + 1),
331
- }))
332
- onNextClick?.(
333
- new Date(
334
- displayYears.from + (displayYears.to - displayYears.from),
335
- 0,
336
- 1
337
- )
338
- )
339
- return
340
- }
341
- goToMonth(nextMonth)
342
- onNextClick?.(nextMonth)
343
- }, [goToMonth, nextMonth])
344
- return (
345
- <nav className={cn("flex items-center", className)}>
346
- <Button
347
- variant="outline"
348
- className="absolute left-0 h-7 w-7 bg-transparent p-0 opacity-80 hover:opacity-100"
349
- type="button"
350
- tabIndex={isPreviousDisabled ? undefined : -1}
351
- disabled={isPreviousDisabled}
352
- aria-label={
353
- navView === "years"
354
- ? `Go to the previous ${
355
- displayYears.to - displayYears.from + 1
356
- } years`
357
- : labelPrevious(previousMonth)
263
+ const handlePreviousClick = React.useCallback(() => {
264
+ if (!previousMonth) return;
265
+ if (navView === 'years') {
266
+ setDisplayYears(prev => ({
267
+ from: prev.from - (prev.to - prev.from + 1),
268
+ to: prev.to - (prev.to - prev.from + 1),
269
+ }));
270
+ onPrevClick?.(new Date(displayYears.from - (displayYears.to - displayYears.from), 0, 1));
271
+ return;
358
272
  }
359
- onClick={handlePreviousClick}
360
- >
361
- <ChevronLeft className="h-4 w-4" />
362
- </Button>
273
+ goToMonth(previousMonth);
274
+ onPrevClick?.(previousMonth);
275
+ }, [previousMonth, goToMonth]);
363
276
 
364
- <Button
365
- variant="outline"
366
- className="absolute right-0 h-7 w-7 bg-transparent p-0 opacity-80 hover:opacity-100"
367
- type="button"
368
- tabIndex={isNextDisabled ? undefined : -1}
369
- disabled={isNextDisabled}
370
- aria-label={
371
- navView === "years"
372
- ? `Go to the next ${displayYears.to - displayYears.from + 1} years`
373
- : labelNext(nextMonth)
277
+ const handleNextClick = React.useCallback(() => {
278
+ if (!nextMonth) return;
279
+ if (navView === 'years') {
280
+ setDisplayYears(prev => ({
281
+ from: prev.from + (prev.to - prev.from + 1),
282
+ to: prev.to + (prev.to - prev.from + 1),
283
+ }));
284
+ onNextClick?.(new Date(displayYears.from + (displayYears.to - displayYears.from), 0, 1));
285
+ return;
374
286
  }
375
- onClick={handleNextClick}
376
- >
377
- <ChevronRight className="h-4 w-4" />
378
- </Button>
379
- </nav>
380
- )
287
+ goToMonth(nextMonth);
288
+ onNextClick?.(nextMonth);
289
+ }, [goToMonth, nextMonth]);
290
+ return (
291
+ <nav className={cn('flex items-center', className)}>
292
+ <Button
293
+ variant="outline"
294
+ className="absolute left-0 h-7 w-7 bg-transparent p-0 opacity-80 hover:opacity-100"
295
+ type="button"
296
+ tabIndex={isPreviousDisabled ? undefined : -1}
297
+ disabled={isPreviousDisabled}
298
+ aria-label={
299
+ navView === 'years'
300
+ ? `Go to the previous ${displayYears.to - displayYears.from + 1} years`
301
+ : labelPrevious(previousMonth)
302
+ }
303
+ onClick={handlePreviousClick}
304
+ >
305
+ <ChevronLeft className="h-4 w-4" />
306
+ </Button>
307
+
308
+ <Button
309
+ variant="outline"
310
+ className="absolute right-0 h-7 w-7 bg-transparent p-0 opacity-80 hover:opacity-100"
311
+ type="button"
312
+ tabIndex={isNextDisabled ? undefined : -1}
313
+ disabled={isNextDisabled}
314
+ aria-label={
315
+ navView === 'years'
316
+ ? `Go to the next ${displayYears.to - displayYears.from + 1} years`
317
+ : labelNext(nextMonth)
318
+ }
319
+ onClick={handleNextClick}
320
+ >
321
+ <ChevronRight className="h-4 w-4" />
322
+ </Button>
323
+ </nav>
324
+ );
381
325
  }
382
326
 
383
327
  function CaptionLabel({
384
- children,
385
- showYearSwitcher,
386
- navView,
387
- setNavView,
388
- displayYears,
389
- ...props
328
+ children,
329
+ showYearSwitcher,
330
+ navView,
331
+ setNavView,
332
+ displayYears,
333
+ ...props
390
334
  }: {
391
- showYearSwitcher?: boolean
392
- navView: NavView
393
- setNavView: React.Dispatch<React.SetStateAction<NavView>>
394
- displayYears: { from: number; to: number }
335
+ showYearSwitcher?: boolean;
336
+ navView: NavView;
337
+ setNavView: React.Dispatch<React.SetStateAction<NavView>>;
338
+ displayYears: { from: number; to: number };
395
339
  } & React.HTMLAttributes<HTMLSpanElement>) {
396
- if (!showYearSwitcher) return <span {...props}>{children}</span>
397
- return (
398
- <Button
399
- className="h-7 w-full truncate text-sm font-medium"
400
- variant="ghost"
401
- size="sm"
402
- onClick={() => setNavView((prev) => (prev === "days" ? "years" : "days"))}
403
- >
404
- {navView === "days"
405
- ? children
406
- : displayYears.from + " - " + displayYears.to}
407
- </Button>
408
- )
340
+ if (!showYearSwitcher) return <span {...props}>{children}</span>;
341
+ return (
342
+ <Button
343
+ className="h-7 w-full truncate text-sm font-medium"
344
+ variant="ghost"
345
+ size="sm"
346
+ onClick={() => setNavView(prev => (prev === 'days' ? 'years' : 'days'))}
347
+ >
348
+ {navView === 'days' ? children : displayYears.from + ' - ' + displayYears.to}
349
+ </Button>
350
+ );
409
351
  }
410
352
 
411
353
  function MonthGrid({
412
- className,
413
- children,
414
- displayYears,
415
- startMonth,
416
- endMonth,
417
- navView,
418
- setNavView,
419
- ...props
354
+ className,
355
+ children,
356
+ displayYears,
357
+ startMonth,
358
+ endMonth,
359
+ navView,
360
+ setNavView,
361
+ ...props
420
362
  }: {
421
- className?: string
422
- children: React.ReactNode
423
- displayYears: { from: number; to: number }
424
- startMonth?: Date
425
- endMonth?: Date
426
- navView: NavView
427
- setNavView: React.Dispatch<React.SetStateAction<NavView>>
363
+ className?: string;
364
+ children: React.ReactNode;
365
+ displayYears: { from: number; to: number };
366
+ startMonth?: Date;
367
+ endMonth?: Date;
368
+ navView: NavView;
369
+ setNavView: React.Dispatch<React.SetStateAction<NavView>>;
428
370
  } & React.TableHTMLAttributes<HTMLTableElement>) {
429
- if (navView === "years") {
371
+ if (navView === 'years') {
372
+ return (
373
+ <YearGrid
374
+ displayYears={displayYears}
375
+ startMonth={startMonth}
376
+ endMonth={endMonth}
377
+ setNavView={setNavView}
378
+ navView={navView}
379
+ className={className}
380
+ {...props}
381
+ />
382
+ );
383
+ }
430
384
  return (
431
- <YearGrid
432
- displayYears={displayYears}
433
- startMonth={startMonth}
434
- endMonth={endMonth}
435
- setNavView={setNavView}
436
- navView={navView}
437
- className={className}
438
- {...props}
439
- />
440
- )
441
- }
442
- return (
443
- <table className={className} {...props}>
444
- {children}
445
- </table>
446
- )
385
+ <table className={className} {...props}>
386
+ {children}
387
+ </table>
388
+ );
447
389
  }
448
390
 
449
391
  function YearGrid({
450
- className,
451
- displayYears,
452
- startMonth,
453
- endMonth,
454
- setNavView,
455
- navView,
456
- ...props
392
+ className,
393
+ displayYears,
394
+ startMonth,
395
+ endMonth,
396
+ setNavView,
397
+ navView,
398
+ ...props
457
399
  }: {
458
- className?: string
459
- displayYears: { from: number; to: number }
460
- startMonth?: Date
461
- endMonth?: Date
462
- setNavView: React.Dispatch<React.SetStateAction<NavView>>
463
- navView: NavView
400
+ className?: string;
401
+ displayYears: { from: number; to: number };
402
+ startMonth?: Date;
403
+ endMonth?: Date;
404
+ setNavView: React.Dispatch<React.SetStateAction<NavView>>;
405
+ navView: NavView;
464
406
  } & React.HTMLAttributes<HTMLDivElement>) {
465
- const { goToMonth, selected } = useDayPicker()
407
+ const { goToMonth, selected } = useDayPicker();
466
408
 
467
- return (
468
- <div className={cn("grid grid-cols-4 gap-y-2", className)} {...props}>
469
- {Array.from(
470
- { length: displayYears.to - displayYears.from + 1 },
471
- (_, i) => {
472
- const isBefore =
473
- differenceInCalendarDays(
474
- new Date(displayYears.from + i, 11, 31),
475
- startMonth!
476
- ) < 0
409
+ return (
410
+ <div className={cn('grid grid-cols-4 gap-y-2', className)} {...props}>
411
+ {Array.from({ length: displayYears.to - displayYears.from + 1 }, (_, i) => {
412
+ const isBefore =
413
+ differenceInCalendarDays(new Date(displayYears.from + i, 11, 31), startMonth!) < 0;
477
414
 
478
- const isAfter =
479
- differenceInCalendarDays(
480
- new Date(displayYears.from + i, 0, 0),
481
- endMonth!
482
- ) > 0
415
+ const isAfter =
416
+ differenceInCalendarDays(new Date(displayYears.from + i, 0, 0), endMonth!) > 0;
483
417
 
484
- const isDisabled = isBefore || isAfter
485
- return (
486
- <Button
487
- key={i}
488
- className={cn(
489
- "h-7 w-full text-sm font-normal text-foreground",
490
- displayYears.from + i === new Date().getFullYear() &&
491
- "bg-accent font-medium text-accent-foreground"
492
- )}
493
- variant="ghost"
494
- onClick={() => {
495
- setNavView("days")
496
- goToMonth(
497
- new Date(
498
- displayYears.from + i,
499
- (selected as Date | undefined)?.getMonth() ?? 0
500
- )
501
- )
502
- }}
503
- disabled={navView === "years" ? isDisabled : undefined}
504
- >
505
- {displayYears.from + i}
506
- </Button>
507
- )
508
- }
509
- )}
510
- </div>
511
- )
418
+ const isDisabled = isBefore || isAfter;
419
+ return (
420
+ <Button
421
+ key={i}
422
+ className={cn(
423
+ 'h-7 w-full text-sm font-normal text-foreground',
424
+ displayYears.from + i === new Date().getFullYear() &&
425
+ 'bg-accent font-medium text-accent-foreground',
426
+ )}
427
+ variant="ghost"
428
+ onClick={() => {
429
+ setNavView('days');
430
+ goToMonth(
431
+ new Date(
432
+ displayYears.from + i,
433
+ (selected as Date | undefined)?.getMonth() ?? 0,
434
+ ),
435
+ );
436
+ }}
437
+ disabled={navView === 'years' ? isDisabled : undefined}
438
+ >
439
+ {displayYears.from + i}
440
+ </Button>
441
+ );
442
+ })}
443
+ </div>
444
+ );
512
445
  }
513
446
 
514
- export { Calendar }
447
+ export { Calendar };