@myparcel-dev/pdk-admin 1.14.1 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (499) hide show
  1. package/CHANGELOG.md +19 -0
  2. package/package.json +5 -5
  3. package/src/__tests__/__snapshots__/exports.spec.ts.snap +8 -1
  4. package/src/__tests__/doComponentTestTeardown.ts +2 -0
  5. package/src/__tests__/mocks/index.ts +1 -1
  6. package/src/__tests__/mocks/mockDefaultAccount.ts +1 -0
  7. package/src/__tests__/mocks/mockDefaultGlobalContext.ts +2 -2
  8. package/src/__tests__/mocks/{mockDefaultPlatform.ts → mockDefaultProposition.ts} +1 -3
  9. package/src/__tests__/mocks/mockDefaultShop.ts +1 -0
  10. package/src/__tests__/utils/getActionIds.ts +12 -0
  11. package/src/__tests__/utils/mockOrderData.ts +20 -0
  12. package/src/actions/composables/mutations/orders/useExportOrdersMutation.ts +1 -1
  13. package/src/actions/composables/queries/account/useOrderCapabilitiesQuery.ts +67 -0
  14. package/src/actions/composables/queries/account/useShipmentCapabilitiesQuery.ts +96 -0
  15. package/src/actions/definitions/orders.ts +6 -8
  16. package/src/actions/index.ts +1 -0
  17. package/src/actions/orderModeActions.spec.ts +150 -0
  18. package/src/actions/orderModeActions.ts +90 -0
  19. package/src/components/OrderBox/ShipmentOptionsBox.spec.ts +109 -0
  20. package/src/components/OrderBox/ShipmentOptionsBox.vue +9 -25
  21. package/src/components/OrderListItem/OrderModeOrderListItem.spec.ts +125 -0
  22. package/src/components/OrderListItem/OrderModeOrderListItem.vue +10 -6
  23. package/src/components/PluginSettings/PluginSettingsForms.vue +7 -4
  24. package/src/components/common/DeliveryOptionsExcerptCarrierName.vue +3 -3
  25. package/src/components/modals/ShipmentOptionsModal.spec.ts +79 -0
  26. package/src/components/modals/ShipmentOptionsModal.vue +4 -21
  27. package/src/composables/components/useToggleInputContext.ts +2 -2
  28. package/src/composables/components/useTriStateInputContext.ts +2 -2
  29. package/src/composables/context/index.ts +1 -0
  30. package/src/composables/context/useOrderMode.spec.ts +75 -0
  31. package/src/composables/context/useOrderMode.ts +26 -0
  32. package/src/composables/language/useLanguage.spec.ts +2 -2
  33. package/src/composables/shipments/useShipmentData.ts +2 -2
  34. package/src/data/index.ts +1 -0
  35. package/src/data/orderMode.spec.ts +22 -0
  36. package/src/data/orderMode.ts +50 -0
  37. package/src/forms/form-builder/builders/buildAfterUpdate.spec.ts +5 -8
  38. package/src/forms/form-builder/operations/executeOperations.spec.ts +4 -7
  39. package/src/forms/form-builder/operations/executeSetPropOperation.spec.ts +4 -7
  40. package/src/forms/form-builder/operations/executeSetValueOperation.spec.ts +3 -2
  41. package/src/forms/form-builder/utils/createValueSetter.ts +21 -8
  42. package/src/forms/helpers/addCapabilitiesClearNotification.ts +39 -0
  43. package/src/forms/helpers/getDeliveryTypes.ts +5 -10
  44. package/src/forms/helpers/getFieldLabel.ts +7 -2
  45. package/src/forms/helpers/getPackageTypes.ts +7 -12
  46. package/src/forms/helpers/index.ts +3 -10
  47. package/src/forms/helpers/useFormCapabilities.spec.ts +227 -0
  48. package/src/forms/helpers/useFormCapabilities.ts +176 -0
  49. package/src/forms/pluginSettings/createPluginSettingsForm.ts +2 -2
  50. package/src/forms/pluginSettings/filterPluginSettingsView.spec.ts +158 -0
  51. package/src/forms/pluginSettings/filterPluginSettingsView.ts +96 -0
  52. package/src/forms/pluginSettings/index.ts +1 -0
  53. package/src/forms/pluginSettings/resolveSettingsValues.spec.ts +62 -0
  54. package/src/forms/pluginSettings/resolveSettingsValues.ts +16 -0
  55. package/src/forms/shipmentOptions/createShipmentOptionsForm.spec.ts +108 -0
  56. package/src/forms/shipmentOptions/createShipmentOptionsForm.ts +114 -52
  57. package/src/forms/shipmentOptions/field.ts +6 -66
  58. package/src/forms/shipmentOptions/fieldFactoryRegistry.ts +26 -0
  59. package/src/forms/shipmentOptions/fields/createCarrierField.ts +119 -30
  60. package/src/forms/shipmentOptions/fields/createDigitalStampRangeField.ts +3 -3
  61. package/src/forms/shipmentOptions/fields/createInsuranceField.ts +43 -22
  62. package/src/forms/shipmentOptions/fields/createPackageTypeField.ts +1 -2
  63. package/src/forms/shipmentOptions/fields/createShipmentOptionField.spec.ts +177 -0
  64. package/src/forms/shipmentOptions/fields/createShipmentOptionField.ts +90 -8
  65. package/src/forms/shipmentOptions/fields/index.ts +0 -9
  66. package/src/forms/shipmentOptions/useCapabilitiesAutoClear.spec.ts +347 -0
  67. package/src/forms/shipmentOptions/useCapabilitiesAutoClear.ts +452 -0
  68. package/src/forms/shipmentOptions/useCapabilitiesWatcher.spec.ts +14 -0
  69. package/src/forms/shipmentOptions/useCapabilitiesWatcher.ts +29 -0
  70. package/src/forms/shipmentOptions/wireProxyCapabilities.spec.ts +160 -0
  71. package/src/forms/shipmentOptions/wireProxyCapabilities.ts +102 -0
  72. package/src/index.ts +2 -0
  73. package/src/pdk/instance/plugins/createRegisterComponentsPlugin.ts +2 -0
  74. package/src/sdk/composables/api/useFetchCarrier.ts +39 -4
  75. package/src/sdk/composables/usePdkAdminApi.ts +8 -3
  76. package/src/stores/useActionStore.spec.ts +101 -0
  77. package/src/stores/useActionStore.ts +4 -28
  78. package/src/stores/useQueryStore.ts +15 -0
  79. package/src/types/actions/endpoints.types.ts +2 -1
  80. package/src/types/sdk.types.ts +54 -1
  81. package/src/utils/forms/formToBody.ts +2 -1
  82. package/src/utils/forms/getEnabledValues.spec.ts +66 -0
  83. package/src/utils/forms/getEnabledValues.ts +25 -0
  84. package/src/utils/forms/index.ts +1 -0
  85. package/src/utils/translations/getDynamicTranslation.ts +1 -1
  86. package/src/views/OrderBox.vue +11 -5
  87. package/src/views/OrderListItem.spec.ts +71 -0
  88. package/src/views/OrderListItem.vue +6 -7
  89. package/dist/__tests__/doComponentTestSetup.d.ts +0 -2
  90. package/dist/__tests__/doComponentTestTeardown.d.ts +0 -1
  91. package/dist/__tests__/index.d.ts +0 -3
  92. package/dist/__tests__/mocks/index.d.ts +0 -14
  93. package/dist/__tests__/mocks/mockDefaultAccount.d.ts +0 -2
  94. package/dist/__tests__/mocks/mockDefaultAppConfig.d.ts +0 -2
  95. package/dist/__tests__/mocks/mockDefaultAppInfo.d.ts +0 -2
  96. package/dist/__tests__/mocks/mockDefaultCarriers.d.ts +0 -2
  97. package/dist/__tests__/mocks/mockDefaultConfig.d.ts +0 -2
  98. package/dist/__tests__/mocks/mockDefaultDynamicContext.d.ts +0 -2
  99. package/dist/__tests__/mocks/mockDefaultEndpoints.d.ts +0 -2
  100. package/dist/__tests__/mocks/mockDefaultGlobalContext.d.ts +0 -2
  101. package/dist/__tests__/mocks/mockDefaultLogger.d.ts +0 -1
  102. package/dist/__tests__/mocks/mockDefaultPlatform.d.ts +0 -2
  103. package/dist/__tests__/mocks/mockDefaultPluginSettings.d.ts +0 -2
  104. package/dist/__tests__/mocks/mockDefaultPrintOptionsView.d.ts +0 -2
  105. package/dist/__tests__/mocks/mockDefaultShop.d.ts +0 -2
  106. package/dist/__tests__/mocks/mockDefaultTranslations.d.ts +0 -2
  107. package/dist/actions/composables/index.d.ts +0 -2
  108. package/dist/actions/composables/mutations/account/index.d.ts +0 -2
  109. package/dist/actions/composables/mutations/account/useDeleteAccountMutation.d.ts +0 -3
  110. package/dist/actions/composables/mutations/account/useUpdateAccountMutation.d.ts +0 -3
  111. package/dist/actions/composables/mutations/debug/index.d.ts +0 -3
  112. package/dist/actions/composables/mutations/debug/useDownloadLogsMutation.d.ts +0 -3
  113. package/dist/actions/composables/mutations/debug/useSwitchToAcceptanceApiMutation.d.ts +0 -3
  114. package/dist/actions/composables/mutations/debug/useSwitchToProductionApiMutation.d.ts +0 -3
  115. package/dist/actions/composables/mutations/index.d.ts +0 -7
  116. package/dist/actions/composables/mutations/orders/index.d.ts +0 -3
  117. package/dist/actions/composables/mutations/orders/useExportOrdersMutation.d.ts +0 -5
  118. package/dist/actions/composables/mutations/orders/usePrintOrdersMutation.d.ts +0 -4
  119. package/dist/actions/composables/mutations/orders/useUpdateOrdersMutation.d.ts +0 -4
  120. package/dist/actions/composables/mutations/settings/index.d.ts +0 -2
  121. package/dist/actions/composables/mutations/settings/useUpdatePluginSettingsMutation.d.ts +0 -3
  122. package/dist/actions/composables/mutations/settings/useUpdateProductSettingsMutation.d.ts +0 -3
  123. package/dist/actions/composables/mutations/shipments/index.d.ts +0 -4
  124. package/dist/actions/composables/mutations/shipments/useDeleteShipmentsMutation.d.ts +0 -4
  125. package/dist/actions/composables/mutations/shipments/useExportReturnMutation.d.ts +0 -4
  126. package/dist/actions/composables/mutations/shipments/usePrintShipmentsMutation.d.ts +0 -4
  127. package/dist/actions/composables/mutations/shipments/useUpdateShipmentsMutation.d.ts +0 -4
  128. package/dist/actions/composables/mutations/usePdkMutation.d.ts +0 -15
  129. package/dist/actions/composables/mutations/webhooks/index.d.ts +0 -2
  130. package/dist/actions/composables/mutations/webhooks/useCreateWebhooksMutation.d.ts +0 -1
  131. package/dist/actions/composables/mutations/webhooks/useDeleteWebhooksMutation.d.ts +0 -3
  132. package/dist/actions/composables/queries/account/index.d.ts +0 -1
  133. package/dist/actions/composables/queries/account/useFetchContextQuery.d.ts +0 -3
  134. package/dist/actions/composables/queries/index.d.ts +0 -6
  135. package/dist/actions/composables/queries/orders/index.d.ts +0 -1
  136. package/dist/actions/composables/queries/orders/useFetchOrdersQuery.d.ts +0 -3
  137. package/dist/actions/composables/queries/products/index.d.ts +0 -1
  138. package/dist/actions/composables/queries/products/useFetchProductsQuery.d.ts +0 -3
  139. package/dist/actions/composables/queries/queryKeys.d.ts +0 -2
  140. package/dist/actions/composables/queries/shipments/index.d.ts +0 -1
  141. package/dist/actions/composables/queries/shipments/useFetchShipmentsQuery.d.ts +0 -4
  142. package/dist/actions/composables/queries/webhooks/index.d.ts +0 -1
  143. package/dist/actions/composables/queries/webhooks/useFetchWebhooksQuery.d.ts +0 -3
  144. package/dist/actions/defineAction.d.ts +0 -8
  145. package/dist/actions/definitions/account.d.ts +0 -13
  146. package/dist/actions/definitions/context.d.ts +0 -6
  147. package/dist/actions/definitions/debug.d.ts +0 -13
  148. package/dist/actions/definitions/index.d.ts +0 -8
  149. package/dist/actions/definitions/modal.d.ts +0 -17
  150. package/dist/actions/definitions/orders.d.ts +0 -38
  151. package/dist/actions/definitions/settings.d.ts +0 -2
  152. package/dist/actions/definitions/shipments.d.ts +0 -15
  153. package/dist/actions/definitions/webhooks.d.ts +0 -4
  154. package/dist/actions/executors/createHandlerWithParameters.d.ts +0 -5
  155. package/dist/actions/executors/createMutationHandler.d.ts +0 -3
  156. package/dist/actions/executors/createOrdersMutationHandler.d.ts +0 -2
  157. package/dist/actions/executors/createQueryHandler.d.ts +0 -3
  158. package/dist/actions/executors/createShipmentsMutationHandler.d.ts +0 -2
  159. package/dist/actions/executors/doMutate.d.ts +0 -4
  160. package/dist/actions/executors/executeAction.d.ts +0 -6
  161. package/dist/actions/executors/executeAfterHandle.d.ts +0 -3
  162. package/dist/actions/executors/executeBeforeHandle.d.ts +0 -4
  163. package/dist/actions/executors/executeHandler.d.ts +0 -3
  164. package/dist/actions/executors/executeNextAction.d.ts +0 -6
  165. package/dist/actions/executors/index.d.ts +0 -14
  166. package/dist/actions/executors/resolveOrderParameters.d.ts +0 -3
  167. package/dist/actions/executors/resolveQuerySuffix.d.ts +0 -3
  168. package/dist/actions/executors/types.d.ts +0 -19
  169. package/dist/actions/index.d.ts +0 -6
  170. package/dist/actions/print/index.d.ts +0 -3
  171. package/dist/actions/print/openOrPrintPdf.d.ts +0 -3
  172. package/dist/actions/print/resolvePrintParameters.d.ts +0 -3
  173. package/dist/actions/print/waitForLabelPrompt.d.ts +0 -3
  174. package/dist/actions/stopActionHandler.d.ts +0 -2
  175. package/dist/components/OrderBox/OrderShipmentsTable.vue.d.ts +0 -6
  176. package/dist/components/OrderBox/OrderShipmentsTableRow.vue.d.ts +0 -21
  177. package/dist/components/OrderBox/ShipmentOptionsBox.vue.d.ts +0 -2
  178. package/dist/components/OrderBox/ShipmentTableBox.vue.d.ts +0 -2
  179. package/dist/components/OrderListItem/OrderModeOrderListItem.vue.d.ts +0 -2
  180. package/dist/components/OrderListItem/ShipmentLabel.vue.d.ts +0 -15
  181. package/dist/components/OrderListItem/ShipmentModeOrderListItem.vue.d.ts +0 -2
  182. package/dist/components/PluginSettings/AccountSettings.vue.d.ts +0 -2
  183. package/dist/components/PluginSettings/DebugOptions.vue.d.ts +0 -2
  184. package/dist/components/PluginSettings/EditApiKeyForm.vue.d.ts +0 -7
  185. package/dist/components/PluginSettings/PluginSettingsForms.vue.d.ts +0 -2
  186. package/dist/components/PluginSettings/WebhooksStatus.vue.d.ts +0 -2
  187. package/dist/components/PluginSettings/createUpdateAccountSettingsValidator.d.ts +0 -4
  188. package/dist/components/common/ActionButton.vue.d.ts +0 -52
  189. package/dist/components/common/BulkSelectCheckbox.vue.d.ts +0 -22
  190. package/dist/components/common/CarrierLogo.vue.d.ts +0 -16
  191. package/dist/components/common/DateRelative.vue.d.ts +0 -16
  192. package/dist/components/common/DeliveryOptionsDeliveryType.vue.d.ts +0 -16
  193. package/dist/components/common/DeliveryOptionsExcerpt.vue.d.ts +0 -2
  194. package/dist/components/common/DeliveryOptionsExcerptCarrierName.vue.d.ts +0 -16
  195. package/dist/components/common/DeliveryOptionsPackageType.vue.d.ts +0 -16
  196. package/dist/components/common/DigitalStampWeightRange.vue.d.ts +0 -15
  197. package/dist/components/common/NotificationContainer.vue.d.ts +0 -19
  198. package/dist/components/common/PackageType.vue.d.ts +0 -16
  199. package/dist/components/common/PlainElement.d.ts +0 -2
  200. package/dist/components/common/ResetButton.vue.d.ts +0 -15
  201. package/dist/components/common/ReturnsForm.vue.d.ts +0 -14
  202. package/dist/components/common/ShipmentBarcode.vue.d.ts +0 -15
  203. package/dist/components/common/ShipmentOptionsForm.vue.d.ts +0 -16
  204. package/dist/components/common/ShipmentStatus.vue.d.ts +0 -15
  205. package/dist/components/common/StatusIndicator.vue.d.ts +0 -23
  206. package/dist/components/common/SubmitButton.vue.d.ts +0 -15
  207. package/dist/components/common/TabNavigation.vue.d.ts +0 -66
  208. package/dist/components/common/index.d.ts +0 -20
  209. package/dist/components/index.d.ts +0 -1
  210. package/dist/components/modals/PrintOptionsModal.vue.d.ts +0 -2
  211. package/dist/components/modals/PrintOptionsModalForm.vue.d.ts +0 -2
  212. package/dist/components/modals/ShipmentOptionsModal.vue.d.ts +0 -2
  213. package/dist/components/modals/ShipmentOptionsModalForm.vue.d.ts +0 -16
  214. package/dist/composables/components/index.d.ts +0 -15
  215. package/dist/composables/components/useBulkSelectCheckbox.d.ts +0 -9
  216. package/dist/composables/components/useCheckboxGroupContext.d.ts +0 -4
  217. package/dist/composables/components/useDropOffInputContext.d.ts +0 -13
  218. package/dist/composables/components/useDropdownButtonContext.d.ts +0 -15
  219. package/dist/composables/components/useElementContext.d.ts +0 -7
  220. package/dist/composables/components/useElementOptions.d.ts +0 -6
  221. package/dist/composables/components/useInputWithOptionsContext.d.ts +0 -10
  222. package/dist/composables/components/useModalElementContext.d.ts +0 -11
  223. package/dist/composables/components/useMultiSelectInputContext.d.ts +0 -4
  224. package/dist/composables/components/useRadioGroupContext.d.ts +0 -10
  225. package/dist/composables/components/useSelectInputContext.d.ts +0 -4
  226. package/dist/composables/components/useShippingMethodsInputContext.d.ts +0 -13
  227. package/dist/composables/components/useTableContext.d.ts +0 -7
  228. package/dist/composables/components/useToggleInputContext.d.ts +0 -11
  229. package/dist/composables/components/useTriStateInputContext.d.ts +0 -17
  230. package/dist/composables/context/index.d.ts +0 -7
  231. package/dist/composables/context/useAppInfo.d.ts +0 -2
  232. package/dist/composables/context/useContext.d.ts +0 -3
  233. package/dist/composables/context/useGlobalContext.d.ts +0 -2
  234. package/dist/composables/context/useInstanceContext.d.ts +0 -8
  235. package/dist/composables/context/useModalContext.d.ts +0 -11
  236. package/dist/composables/context/useModalOrder.d.ts +0 -1
  237. package/dist/composables/context/usePluginSettings.d.ts +0 -2
  238. package/dist/composables/formatter/default/createCurrencyFormat.d.ts +0 -1
  239. package/dist/composables/formatter/default/createLongDateFormat.d.ts +0 -1
  240. package/dist/composables/formatter/default/createRelativeTimeFormat.d.ts +0 -1
  241. package/dist/composables/formatter/default/defaultCurrencyFormatters.d.ts +0 -2
  242. package/dist/composables/formatter/default/defaultDateFormatters.d.ts +0 -4
  243. package/dist/composables/formatter/default/index.d.ts +0 -6
  244. package/dist/composables/formatter/default/parseDate.d.ts +0 -1
  245. package/dist/composables/formatter/formatter.types.d.ts +0 -23
  246. package/dist/composables/formatter/index.d.ts +0 -4
  247. package/dist/composables/formatter/useFormatter.d.ts +0 -2
  248. package/dist/composables/formatter/useLocalizedFormatter.d.ts +0 -2
  249. package/dist/composables/index.d.ts +0 -17
  250. package/dist/composables/language/index.d.ts +0 -4
  251. package/dist/composables/language/resolveTranslatedString.d.ts +0 -3
  252. package/dist/composables/language/resolveTranslationKey.d.ts +0 -2
  253. package/dist/composables/language/types.d.ts +0 -1
  254. package/dist/composables/language/useLanguage.d.ts +0 -23
  255. package/dist/composables/orders/index.d.ts +0 -3
  256. package/dist/composables/orders/useOrder.d.ts +0 -3
  257. package/dist/composables/orders/useOrderData.d.ts +0 -9
  258. package/dist/composables/orders/useOrdersData.d.ts +0 -3
  259. package/dist/composables/products/index.d.ts +0 -1
  260. package/dist/composables/products/useProductData.d.ts +0 -8
  261. package/dist/composables/shipments/index.d.ts +0 -3
  262. package/dist/composables/shipments/useShipment.d.ts +0 -3
  263. package/dist/composables/shipments/useShipmentData.d.ts +0 -12
  264. package/dist/composables/shipments/useShipmentsData.d.ts +0 -2
  265. package/dist/composables/useAdminConfig.d.ts +0 -2
  266. package/dist/composables/useAdminInstance.d.ts +0 -2
  267. package/dist/composables/useDigitalStampRanges.d.ts +0 -12
  268. package/dist/composables/useGlobalPdkAdmin.d.ts +0 -2
  269. package/dist/composables/useLoadMore.d.ts +0 -14
  270. package/dist/composables/useLoading.d.ts +0 -10
  271. package/dist/composables/useLogger.d.ts +0 -2
  272. package/dist/composables/useStoreContextQuery.d.ts +0 -3
  273. package/dist/composables/useStoreQuery.d.ts +0 -4
  274. package/dist/composables/useWeekdays.d.ts +0 -9
  275. package/dist/data/components.d.ts +0 -195
  276. package/dist/data/constants.d.ts +0 -63
  277. package/dist/data/endpoints.d.ts +0 -5
  278. package/dist/data/index.d.ts +0 -4
  279. package/dist/data/view.d.ts +0 -9
  280. package/dist/deprecated.d.ts +0 -6
  281. package/dist/forms/createReturnsForm.d.ts +0 -1
  282. package/dist/forms/form-builder/builders/buildAfterUpdate.d.ts +0 -3
  283. package/dist/forms/form-builder/builders/buildFormStateWatcher.d.ts +0 -3
  284. package/dist/forms/form-builder/builders/index.d.ts +0 -2
  285. package/dist/forms/form-builder/conditions/index.d.ts +0 -3
  286. package/dist/forms/form-builder/conditions/validateIfCondition.d.ts +0 -2
  287. package/dist/forms/form-builder/conditions/validateIfConditions.d.ts +0 -2
  288. package/dist/forms/form-builder/conditions/validateIsTruthy.d.ts +0 -2
  289. package/dist/forms/form-builder/index.d.ts +0 -5
  290. package/dist/forms/form-builder/operations/executeCustomOperationHandlers.d.ts +0 -2
  291. package/dist/forms/form-builder/operations/executeOperation.d.ts +0 -2
  292. package/dist/forms/form-builder/operations/executeOperations.d.ts +0 -2
  293. package/dist/forms/form-builder/operations/executeSetPropOperation.d.ts +0 -2
  294. package/dist/forms/form-builder/operations/executeSetValueOperation.d.ts +0 -2
  295. package/dist/forms/form-builder/operations/index.d.ts +0 -5
  296. package/dist/forms/form-builder/operations/parseBuilders.d.ts +0 -3
  297. package/dist/forms/form-builder/types/FormCondition.types.d.ts +0 -36
  298. package/dist/forms/form-builder/types/FormOperations.types.d.ts +0 -16
  299. package/dist/forms/form-builder/types/SubOperationBuilder.types.d.ts +0 -13
  300. package/dist/forms/form-builder/types/common.types.d.ts +0 -21
  301. package/dist/forms/form-builder/types/index.d.ts +0 -4
  302. package/dist/forms/form-builder/utils/createPropSetter.d.ts +0 -4
  303. package/dist/forms/form-builder/utils/createValueGetter.d.ts +0 -4
  304. package/dist/forms/form-builder/utils/createValueSetter.d.ts +0 -4
  305. package/dist/forms/form-builder/utils/index.d.ts +0 -4
  306. package/dist/forms/formKeys.d.ts +0 -10
  307. package/dist/forms/helpers/addBulkEditNotification.d.ts +0 -1
  308. package/dist/forms/helpers/createDefaultOption.d.ts +0 -3
  309. package/dist/forms/helpers/createHasShipmentOptionWatcher.d.ts +0 -3
  310. package/dist/forms/helpers/createLabel.d.ts +0 -1
  311. package/dist/forms/helpers/defineFormField.d.ts +0 -2
  312. package/dist/forms/helpers/getCarrier.d.ts +0 -3
  313. package/dist/forms/helpers/getDeliveryTypes.d.ts +0 -3
  314. package/dist/forms/helpers/getFieldLabel.d.ts +0 -2
  315. package/dist/forms/helpers/getFormCarrierName.d.ts +0 -2
  316. package/dist/forms/helpers/getInsuranceOptions.d.ts +0 -3
  317. package/dist/forms/helpers/getPackageTypes.d.ts +0 -3
  318. package/dist/forms/helpers/hasPostNlAgeCheck.d.ts +0 -2
  319. package/dist/forms/helpers/hasShipmentOption.d.ts +0 -3
  320. package/dist/forms/helpers/index.d.ts +0 -21
  321. package/dist/forms/helpers/isPackageTypeMailbox.d.ts +0 -2
  322. package/dist/forms/helpers/isPackageTypePackage.d.ts +0 -2
  323. package/dist/forms/helpers/isPackageTypePackageOrSmall.d.ts +0 -2
  324. package/dist/forms/helpers/isPackageTypeSmallPackage.d.ts +0 -2
  325. package/dist/forms/helpers/resolveFormComponent.d.ts +0 -3
  326. package/dist/forms/helpers/setFieldProp.d.ts +0 -8
  327. package/dist/forms/helpers/setPostNlAgeCheckSubtext.d.ts +0 -2
  328. package/dist/forms/helpers/triStateFieldIsEnabled.d.ts +0 -2
  329. package/dist/forms/helpers/updateFieldsDefaults.d.ts +0 -6
  330. package/dist/forms/index.d.ts +0 -6
  331. package/dist/forms/pluginSettings/createFormTab.d.ts +0 -3
  332. package/dist/forms/pluginSettings/createPluginSettingsForm.d.ts +0 -4
  333. package/dist/forms/pluginSettings/createPluginSettingsTabs.d.ts +0 -4
  334. package/dist/forms/pluginSettings/createPluginSettingsTabsComponent.d.ts +0 -4
  335. package/dist/forms/pluginSettings/generateFormFields.d.ts +0 -8
  336. package/dist/forms/pluginSettings/index.d.ts +0 -6
  337. package/dist/forms/pluginSettings/types.d.ts +0 -13
  338. package/dist/forms/shipmentOptions/createShipmentOptionsForm.d.ts +0 -4
  339. package/dist/forms/shipmentOptions/field.d.ts +0 -36
  340. package/dist/forms/shipmentOptions/fields/createAgeCheckField.d.ts +0 -3
  341. package/dist/forms/shipmentOptions/fields/createCarrierField.d.ts +0 -4
  342. package/dist/forms/shipmentOptions/fields/createDeliveryTypeField.d.ts +0 -3
  343. package/dist/forms/shipmentOptions/fields/createDigitalStampRangeField.d.ts +0 -4
  344. package/dist/forms/shipmentOptions/fields/createDirectReturnField.d.ts +0 -3
  345. package/dist/forms/shipmentOptions/fields/createHideSenderField.d.ts +0 -3
  346. package/dist/forms/shipmentOptions/fields/createInsuranceField.d.ts +0 -3
  347. package/dist/forms/shipmentOptions/fields/createLabelAmountField.d.ts +0 -3
  348. package/dist/forms/shipmentOptions/fields/createLargeFormatField.d.ts +0 -3
  349. package/dist/forms/shipmentOptions/fields/createOnlyRecipientField.d.ts +0 -3
  350. package/dist/forms/shipmentOptions/fields/createPackageTypeField.d.ts +0 -3
  351. package/dist/forms/shipmentOptions/fields/createPriorityDeliveryField.d.ts +0 -3
  352. package/dist/forms/shipmentOptions/fields/createReceiptCodeField.d.ts +0 -3
  353. package/dist/forms/shipmentOptions/fields/createRef.d.ts +0 -3
  354. package/dist/forms/shipmentOptions/fields/createSameDayDeliveryField.d.ts +0 -3
  355. package/dist/forms/shipmentOptions/fields/createShipmentOptionField.d.ts +0 -4
  356. package/dist/forms/shipmentOptions/fields/createSignatureField.d.ts +0 -3
  357. package/dist/forms/shipmentOptions/fields/index.d.ts +0 -15
  358. package/dist/forms/shipmentOptions/index.d.ts +0 -4
  359. package/dist/forms/shipmentOptions/types.d.ts +0 -2
  360. package/dist/index.d.ts +0 -19
  361. package/dist/pdk/PdkAdmin.d.ts +0 -18
  362. package/dist/pdk/boot.d.ts +0 -3
  363. package/dist/pdk/createAdminConfig.d.ts +0 -2
  364. package/dist/pdk/createPdkAdmin.d.ts +0 -8
  365. package/dist/pdk/createPdkAdminPlugin.d.ts +0 -3
  366. package/dist/pdk/fillShipmentsQueryData.d.ts +0 -4
  367. package/dist/pdk/index.d.ts +0 -11
  368. package/dist/pdk/instance/createInstanceContext.d.ts +0 -5
  369. package/dist/pdk/instance/createQueryClient.d.ts +0 -2
  370. package/dist/pdk/instance/index.d.ts +0 -3
  371. package/dist/pdk/instance/plugins/createContextPlugin.d.ts +0 -2
  372. package/dist/pdk/instance/plugins/createLoggerPlugin.d.ts +0 -2
  373. package/dist/pdk/instance/plugins/createRegisterComponentsPlugin.d.ts +0 -5
  374. package/dist/pdk/instance/plugins/createStorePlugin.d.ts +0 -2
  375. package/dist/pdk/instance/plugins/createVueQueryPlugin.d.ts +0 -5
  376. package/dist/pdk/instance/plugins/index.d.ts +0 -6
  377. package/dist/pdk/instance/plugins/plugins.types.d.ts +0 -3
  378. package/dist/pdk/renderMap.d.ts +0 -3
  379. package/dist/pdk/sendBootEvent.d.ts +0 -3
  380. package/dist/pdk/setupAdminApp.d.ts +0 -3
  381. package/dist/pdk/testIdDirective.d.ts +0 -5
  382. package/dist/sdk/PdkFetchClient.d.ts +0 -11
  383. package/dist/sdk/composables/api/index.d.ts +0 -1
  384. package/dist/sdk/composables/api/useFetchCarrier.d.ts +0 -2
  385. package/dist/sdk/composables/index.d.ts +0 -3
  386. package/dist/sdk/composables/useMyParcelApi.d.ts +0 -5
  387. package/dist/sdk/composables/usePdkAdminApi.d.ts +0 -6
  388. package/dist/sdk/endpoints/abstractPdkEndpoint.d.ts +0 -7
  389. package/dist/sdk/endpoints/index.d.ts +0 -1
  390. package/dist/sdk/index.d.ts +0 -3
  391. package/dist/services/actions/createAction.d.ts +0 -4
  392. package/dist/services/actions/createActionContext.d.ts +0 -3
  393. package/dist/services/actions/downloadFile.d.ts +0 -4
  394. package/dist/services/actions/getActionIdentifier.d.ts +0 -2
  395. package/dist/services/actions/index.d.ts +0 -4
  396. package/dist/services/addErrorToNotifications.d.ts +0 -2
  397. package/dist/services/context/getElementContext.d.ts +0 -2
  398. package/dist/services/context/index.d.ts +0 -1
  399. package/dist/services/createNotification.d.ts +0 -5
  400. package/dist/services/index.d.ts +0 -9
  401. package/dist/services/instantiateAction.d.ts +0 -2
  402. package/dist/services/instantiateActions.d.ts +0 -8
  403. package/dist/services/logger.d.ts +0 -19
  404. package/dist/services/mutations/getCallbackForMutationMode.d.ts +0 -4
  405. package/dist/services/mutations/getModalMutationOptions.d.ts +0 -2
  406. package/dist/services/mutations/index.d.ts +0 -3
  407. package/dist/services/mutations/mutationMode.d.ts +0 -4
  408. package/dist/services/print/index.d.ts +0 -1
  409. package/dist/services/print/openPdfInNewWindow.d.ts +0 -4
  410. package/dist/stores/createQueryCacheKey.d.ts +0 -3
  411. package/dist/stores/index.d.ts +0 -6
  412. package/dist/stores/types.d.ts +0 -13
  413. package/dist/stores/useActionStore.d.ts +0 -25
  414. package/dist/stores/useModalStore.d.ts +0 -16
  415. package/dist/stores/useNotificationStore.d.ts +0 -60
  416. package/dist/stores/useQueryStore.d.ts +0 -77
  417. package/dist/symbols.d.ts +0 -5
  418. package/dist/testing.d.ts +0 -1
  419. package/dist/types/actions/actions.types.d.ts +0 -31
  420. package/dist/types/actions/endpoints.types.d.ts +0 -9
  421. package/dist/types/actions/index.d.ts +0 -4
  422. package/dist/types/actions/parameters.types.d.ts +0 -55
  423. package/dist/types/actions/response.types.d.ts +0 -7
  424. package/dist/types/actions.types.d.ts +0 -45
  425. package/dist/types/admin.types.d.ts +0 -26
  426. package/dist/types/common.types.d.ts +0 -53
  427. package/dist/types/components-form.types.d.ts +0 -107
  428. package/dist/types/components.types.d.ts +0 -273
  429. package/dist/types/configuration.types.d.ts +0 -95
  430. package/dist/types/context.types.d.ts +0 -20
  431. package/dist/types/endpoints.types.d.ts +0 -7
  432. package/dist/types/form.types.d.ts +0 -39
  433. package/dist/types/index.d.ts +0 -12
  434. package/dist/types/language.types.d.ts +0 -9
  435. package/dist/types/sdk.types.d.ts +0 -155
  436. package/dist/utils/booleanToTriState.d.ts +0 -2
  437. package/dist/utils/convertDotNotationToObject.d.ts +0 -1
  438. package/dist/utils/createAssetUrl.d.ts +0 -1
  439. package/dist/utils/createClasses.d.ts +0 -8
  440. package/dist/utils/createObjectWithKeys.d.ts +0 -3
  441. package/dist/utils/decodeHtmlEntities.d.ts +0 -7
  442. package/dist/utils/downloadBlob.d.ts +0 -1
  443. package/dist/utils/downloadFileFromUrl.d.ts +0 -1
  444. package/dist/utils/encodeArrayParameter.d.ts +0 -2
  445. package/dist/utils/extendAdminInstance.d.ts +0 -2
  446. package/dist/utils/fakeLinkClick.d.ts +0 -4
  447. package/dist/utils/forms/createFormElement.d.ts +0 -3
  448. package/dist/utils/forms/createShipmentFormName.d.ts +0 -1
  449. package/dist/utils/forms/formToBody.d.ts +0 -2
  450. package/dist/utils/forms/generateFieldId.d.ts +0 -3
  451. package/dist/utils/forms/index.d.ts +0 -4
  452. package/dist/utils/generateLabelFilename.d.ts +0 -3
  453. package/dist/utils/getOrderId.d.ts +0 -3
  454. package/dist/utils/getOrderShipmentIds.d.ts +0 -2
  455. package/dist/utils/index.d.ts +0 -22
  456. package/dist/utils/openUrlInNewTab.d.ts +0 -1
  457. package/dist/utils/prefixComponent.d.ts +0 -3
  458. package/dist/utils/query/index.d.ts +0 -3
  459. package/dist/utils/query/setQueryData.d.ts +0 -2
  460. package/dist/utils/query/setQueryOrder.d.ts +0 -10
  461. package/dist/utils/query/setQueryShipment.d.ts +0 -3
  462. package/dist/utils/resolveCarrier.d.ts +0 -1
  463. package/dist/utils/translations/getDeliveryTypeTranslation.d.ts +0 -2
  464. package/dist/utils/translations/getDynamicTranslation.d.ts +0 -1
  465. package/dist/utils/translations/getPackageTypeTranslation.d.ts +0 -2
  466. package/dist/utils/translations/index.d.ts +0 -4
  467. package/dist/utils/translations/translateSelectOption.d.ts +0 -3
  468. package/dist/utils/triStateToBoolean.d.ts +0 -2
  469. package/dist/utils/unprefixComponent.d.ts +0 -3
  470. package/dist/utils/validateId.d.ts +0 -2
  471. package/dist/views/ChildProductSettings.vue.d.ts +0 -2
  472. package/dist/views/Modals.vue.d.ts +0 -2
  473. package/dist/views/Notifications.vue.d.ts +0 -2
  474. package/dist/views/OrderBox.vue.d.ts +0 -2
  475. package/dist/views/OrderListItem.vue.d.ts +0 -2
  476. package/dist/views/PluginSettings.vue.d.ts +0 -2
  477. package/dist/views/ProductSettings.vue.d.ts +0 -35
  478. package/dist/views/integrated/OrderBoxView.vue.d.ts +0 -12
  479. package/dist/views/integrated/OrderListItemView.vue.d.ts +0 -12
  480. package/dist/views/integrated/index.d.ts +0 -7
  481. package/src/forms/helpers/createHasShipmentOptionWatcher.ts +0 -12
  482. package/src/forms/helpers/getCarrier.ts +0 -11
  483. package/src/forms/helpers/getInsuranceOptions.ts +0 -23
  484. package/src/forms/helpers/hasPostNlAgeCheck.ts +0 -11
  485. package/src/forms/helpers/hasShipmentOption.ts +0 -8
  486. package/src/forms/helpers/isPackageTypeMailbox.ts +0 -7
  487. package/src/forms/helpers/isPackageTypePackage.ts +0 -7
  488. package/src/forms/helpers/isPackageTypePackageOrSmall.ts +0 -7
  489. package/src/forms/helpers/isPackageTypeSmallPackage.ts +0 -7
  490. package/src/forms/helpers/setPostNlAgeCheckSubtext.ts +0 -17
  491. package/src/forms/shipmentOptions/fields/createAgeCheckField.ts +0 -33
  492. package/src/forms/shipmentOptions/fields/createDirectReturnField.ts +0 -8
  493. package/src/forms/shipmentOptions/fields/createHideSenderField.ts +0 -8
  494. package/src/forms/shipmentOptions/fields/createLargeFormatField.ts +0 -8
  495. package/src/forms/shipmentOptions/fields/createOnlyRecipientField.ts +0 -21
  496. package/src/forms/shipmentOptions/fields/createPriorityDeliveryField.ts +0 -12
  497. package/src/forms/shipmentOptions/fields/createReceiptCodeField.ts +0 -21
  498. package/src/forms/shipmentOptions/fields/createSameDayDeliveryField.ts +0 -8
  499. package/src/forms/shipmentOptions/fields/createSignatureField.ts +0 -11
@@ -0,0 +1,452 @@
1
+ import {toValue, watch, type Ref} from 'vue';
2
+ import {snakeCase} from 'lodash-unified';
3
+ import {type FormInstance, type InteractiveElementInstance} from '@myparcel-dev/vue-form-builder';
4
+ import {BackendEndpoint, type CarrierModel, type Plugin, TriState} from '@myparcel-dev/pdk-common';
5
+ import {
6
+ addCapabilitiesClearNotification,
7
+ CAPABILITIES_CLEARED_NOTIFICATION_ID,
8
+ useFormCapabilities,
9
+ } from '../helpers';
10
+ import {setFieldRef} from '../form-builder/utils/createValueSetter';
11
+ import {useLanguage} from '../../composables';
12
+ import {useNotificationStore, useQueryStore} from '../../stores';
13
+ import {type CapabilitiesSelection} from './wireProxyCapabilities';
14
+ import {
15
+ FIELD_CARRIER,
16
+ FIELD_DELIVERY_TYPE,
17
+ FIELD_PACKAGE_TYPE,
18
+ FIELD_SHIPMENT_OPTIONS_PREFIX,
19
+ SHIPMENT_OPTIONS,
20
+ } from './field';
21
+
22
+ type InheritedDeliveryOptions = Plugin.ModelContextOrderDataContext['inheritedDeliveryOptions'];
23
+
24
+ type AxisField = typeof FIELD_CARRIER | typeof FIELD_PACKAGE_TYPE | typeof FIELD_DELIVERY_TYPE;
25
+
26
+ /**
27
+ * Translation key per axis. Carrier uses the form-builder's bare `'carrier'` key (matching
28
+ * `createCarrierField`); packageType / deliveryType use the existing field labels.
29
+ */
30
+ const FIELD_TO_LABEL_KEY: Record<AxisField, string> = {
31
+ [FIELD_CARRIER]: 'carrier',
32
+ [FIELD_PACKAGE_TYPE]: snakeCase(`${SHIPMENT_OPTIONS}_package_type`),
33
+ [FIELD_DELIVERY_TYPE]: snakeCase(`${SHIPMENT_OPTIONS}_delivery_type`),
34
+ };
35
+
36
+ const optionFieldName = (key: string): string => `${FIELD_SHIPMENT_OPTIONS_PREFIX}.${key}`;
37
+
38
+ /**
39
+ * Translation key for an option's field label (matches `getFieldLabel(name)` from the
40
+ * shipment-option factories).
41
+ */
42
+ const optionLabelKey = (key: string): string => snakeCase(`${SHIPMENT_OPTIONS}_${key}`);
43
+
44
+ /**
45
+ * Set a form field's value safely. `vue-form-builder` swaps `field.ref` from a Vue Ref to a
46
+ * primitive after the first render cycle, so `form.setValue(name, value)` (which does
47
+ * `field.ref.value = value`) throws once that swap has happened. `setFieldRef` checks
48
+ * `isRef(field.ref)` and falls back to `field.ref = value` for the post-render shape.
49
+ */
50
+ const setFieldValue = (form: FormInstance, fieldName: string, value: string | number | boolean | undefined): void => {
51
+ const field = form.getField(fieldName) as InteractiveElementInstance | undefined;
52
+
53
+ if (!field) return;
54
+
55
+ setFieldRef(field, value as Parameters<typeof setFieldRef>[1]);
56
+ };
57
+
58
+ type ShipmentResponseSnapshot =
59
+ | {state: 'pending'}
60
+ | {state: 'invalid_combo'}
61
+ | {state: 'matched'; carrier: CarrierModel};
62
+
63
+ /**
64
+ * Read the shipment query's state directly so the auto-clear can distinguish three cases the
65
+ * helper-level `getCarrierCapabilitiesForShipment` collapses for its consumers:
66
+ *
67
+ * - **`pending`**: query not registered, loading, errored, or has no data yet. No clear should
68
+ * fire — transient state. Errored requests are logged via `globalLogger.error` inside the
69
+ * query composable; the form keeps its current selection rather than blocking the merchant
70
+ * on an intermittent failure.
71
+ * - **`invalid_combo`**: query is `success` but `results` is empty or doesn't contain the
72
+ * chosen carrier. The server has confirmed this combination isn't valid; trigger an
73
+ * axis-rollback.
74
+ * - **`matched`**: query is `success` and the carrier was found. Use the response's narrow
75
+ * `options` to decide which active option fields are now orphaned.
76
+ */
77
+ const readShipmentSnapshot = (
78
+ selection: Readonly<Ref<CapabilitiesSelection>>,
79
+ queryStore: ReturnType<typeof useQueryStore>,
80
+ orderId: string,
81
+ ): ShipmentResponseSnapshot => {
82
+ const modifier = `${orderId}.shipment`;
83
+
84
+ if (!queryStore.has(BackendEndpoint.ProxyCapabilities, modifier)) return {state: 'pending'};
85
+
86
+ const query = queryStore.get(BackendEndpoint.ProxyCapabilities, modifier);
87
+
88
+ if (toValue(query.status) !== 'success') return {state: 'pending'};
89
+
90
+ const carriers = (toValue(query.data) ?? []) as CarrierModel[];
91
+ // Compare against the carrier from the *debounced* selection — the same selection the
92
+ // shipment query was last fetched for. Reading directly from `form.getValue(carrier)` here
93
+ // would race: when the user just changed an axis, the form value updates immediately while
94
+ // the debounced selection (and thus the query's data) lags by `DEBOUNCE_MS`. During that
95
+ // window we'd compare the new form carrier against the previous-fetch's response, see no
96
+ // match, and falsely declare invalid_combo.
97
+ const queryCarrier = selection.value.carrier;
98
+ const matched = carriers.find((carrier) => carrier.carrier === queryCarrier);
99
+
100
+ return matched ? {state: 'matched', carrier: matched} : {state: 'invalid_combo'};
101
+ };
102
+
103
+ /**
104
+ * Watch the form's selection refs and the capability queries, and roll back any field that
105
+ * has become invalid because of another axis changing. Each clear is announced through a
106
+ * single rolling form-level notification (see {@link addCapabilitiesClearNotification}).
107
+ *
108
+ * The core rule (per design): when a user action invalidates the form, the field the user
109
+ * just touched is cleared — they're already at that field in the UI, so they immediately
110
+ * see the rollback and can pick again. We never silently mutate fields the user previously
111
+ * set without notifying them.
112
+ *
113
+ * Three independent invalidation sources are handled, each in its own watcher:
114
+ *
115
+ * 1. **Cross-axis (synchronous) — order data**: when the chosen carrier's `packageTypes` /
116
+ * `deliveryTypes` (from the order query) no longer contain the form's current value,
117
+ * we clear that field. Carrier-change is special-cased through the same silent +
118
+ * inherited-defaults flow as the shipment-query path; without that, the order watcher
119
+ * (which fires synchronously) would emit a noisy notification before the debounced
120
+ * shipment watcher gets a chance to apply the silent reset.
121
+ * 2. **Shipment-empty — server invalidation**: when the shipment query returns no entry for
122
+ * the chosen carrier (empty `results` or carrier not present), the server has confirmed
123
+ * the combination isn't valid. Clears the just-touched axis (or deliveryType by default).
124
+ * 3. **Option key dropped — cross-axis effect on options**: when the shipment query has the
125
+ * chosen carrier but its `options` no longer carries an option key the form has active,
126
+ * that option is cleared (`TriState.Inherit`). Axis intent wins over an active option.
127
+ *
128
+ * Form values are read via `form.getValue(name)` rather than `form.values[name]` so reactive
129
+ * dep tracking inside `computed` / `watch` callbacks fires correctly (the PDK's existing
130
+ * `createValueGetter` follows the same pattern).
131
+ */
132
+ export const useCapabilitiesAutoClear = (
133
+ form: FormInstance,
134
+ allOptionKeys: string[],
135
+ orderId: string,
136
+ inheritedDeliveryOptions: InheritedDeliveryOptions,
137
+ selection: Readonly<Ref<CapabilitiesSelection>>,
138
+ ): void => {
139
+ // Capture Pinia stores + translator at setup time so watcher callbacks don't call
140
+ // `useQueryStore()` / `useNotificationStore()` / `useLanguage()` in non-setup contexts (which
141
+ // fires Vue's "inject() can only be used inside setup()" warning AND can yield a disconnected
142
+ // store instance, breaking reactive dep tracking on `queries.value[key]`).
143
+ const queryStore = useQueryStore();
144
+ const notificationStore = useNotificationStore();
145
+ const {translate} = useLanguage();
146
+ const {getCarrierCapabilitiesForOrder} = useFormCapabilities();
147
+
148
+ let lastModifiedAxis: AxisField | undefined;
149
+ /**
150
+ * The value the most-recently-modified axis held BEFORE the user's just-rejected change.
151
+ * Used to revert (rather than clear) on invalid-combo, so the user's previous valid choice
152
+ * is restored rather than the field being emptied.
153
+ */
154
+ let lastModifiedPreviousValue: unknown;
155
+ let suppressTracking = false;
156
+
157
+ /**
158
+ * Set a field value while suppressing the `lastModifiedAxis` tracker for the duration of
159
+ * the write. Without this guard the next reactive watcher tick would attribute the clear
160
+ * to the user (turning every auto-clear into a self-perpetuating "user just touched X"
161
+ * signal). Pairs with the `suppressTracking` flag the axis-tracking watcher reads.
162
+ */
163
+ const setSilently = (fieldName: string, value: string | number | boolean | undefined): boolean => {
164
+ if (form.getValue(fieldName) === value) return false;
165
+
166
+ suppressTracking = true;
167
+ try {
168
+ setFieldValue(form, fieldName, value);
169
+ } finally {
170
+ suppressTracking = false;
171
+ }
172
+
173
+ return true;
174
+ };
175
+
176
+ const previousAxisValues: Record<AxisField, unknown> = {
177
+ [FIELD_CARRIER]: form.getValue(FIELD_CARRIER),
178
+ [FIELD_PACKAGE_TYPE]: form.getValue(FIELD_PACKAGE_TYPE),
179
+ [FIELD_DELIVERY_TYPE]: form.getValue(FIELD_DELIVERY_TYPE),
180
+ };
181
+
182
+ // Drop the rolling "capabilities cleared" notification on any form change. The order- and
183
+ // shipment-watchers later in the same tick will re-add it via `notifyClears` if the new
184
+ // selection is still invalid; otherwise the notification stays cleared, so a successful
185
+ // re-pick doesn't leave a stale toast on screen. `flush: 'sync'` so the remove fires before
186
+ // any pre-flush watcher's add path on the same tick — the add then wins and the user sees
187
+ // the up-to-date message instead of the previous attempt's.
188
+ watch(
189
+ [
190
+ () => form.getValue(FIELD_CARRIER),
191
+ () => form.getValue(FIELD_PACKAGE_TYPE),
192
+ () => form.getValue(FIELD_DELIVERY_TYPE),
193
+ ...allOptionKeys.map((key) => () => form.getValue(optionFieldName(key))),
194
+ ],
195
+ () => {
196
+ notificationStore.remove(CAPABILITIES_CLEARED_NOTIFICATION_ID);
197
+ },
198
+ {flush: 'sync'},
199
+ );
200
+
201
+ watch(
202
+ [
203
+ () => form.getValue(FIELD_CARRIER),
204
+ () => form.getValue(FIELD_PACKAGE_TYPE),
205
+ () => form.getValue(FIELD_DELIVERY_TYPE),
206
+ ],
207
+ ([carrierValue, packageTypeValue, deliveryTypeValue]) => {
208
+ // Capture lastModified attribution ONLY for genuine user changes — silent writes from
209
+ // the auto-clear itself shouldn't masquerade as user intent.
210
+ if (!suppressTracking) {
211
+ if (carrierValue !== previousAxisValues[FIELD_CARRIER]) {
212
+ lastModifiedAxis = FIELD_CARRIER;
213
+ lastModifiedPreviousValue = previousAxisValues[FIELD_CARRIER];
214
+ } else if (packageTypeValue !== previousAxisValues[FIELD_PACKAGE_TYPE]) {
215
+ lastModifiedAxis = FIELD_PACKAGE_TYPE;
216
+ lastModifiedPreviousValue = previousAxisValues[FIELD_PACKAGE_TYPE];
217
+ } else if (deliveryTypeValue !== previousAxisValues[FIELD_DELIVERY_TYPE]) {
218
+ lastModifiedAxis = FIELD_DELIVERY_TYPE;
219
+ lastModifiedPreviousValue = previousAxisValues[FIELD_DELIVERY_TYPE];
220
+ }
221
+ }
222
+
223
+ // Always mirror current values into the snapshot — under suppressTracking the prior
224
+ // snapshot becomes stale (the auto-clear just rewrote a field), and a future genuine
225
+ // user change would otherwise capture the pre-clear value as `lastModifiedPreviousValue`
226
+ // and revert to a value already known to be invalid.
227
+ previousAxisValues[FIELD_CARRIER] = carrierValue;
228
+ previousAxisValues[FIELD_PACKAGE_TYPE] = packageTypeValue;
229
+ previousAxisValues[FIELD_DELIVERY_TYPE] = deliveryTypeValue;
230
+ },
231
+ // `sync` flush is essential here: `suppressTracking` is set inside `setSilently`'s
232
+ // `try`/`finally`, which is synchronous. With Vue's default (`pre`) flush, the watcher
233
+ // callback runs LATER — by which time `suppressTracking` has been reset to `false`, and
234
+ // the silent write gets attributed to the user. That makes `lastModifiedPreviousValue`
235
+ // capture the value the auto-clear just overwrote, and the next `revertAxis` reverts to
236
+ // it — producing a flip-flop cycle visible to the merchant. Sync flush fires the callback
237
+ // inside the ref setter so it observes `suppressTracking === true`.
238
+ {flush: 'sync'},
239
+ );
240
+
241
+ /**
242
+ * Roll back the just-touched axis. If we have a previous valid value to revert to (the user
243
+ * picked something invalid AFTER having a valid choice), restore that — preserves the
244
+ * previous selection so the form doesn't surprise the user with an emptied field. If there's
245
+ * no revert target (axis was never set, or this is the first-ever change on a freshly-opened
246
+ * modal), clear the field. Returns whether a previous value was actually restored so the
247
+ * caller can pick the right notification line.
248
+ */
249
+ const revertAxis = (axis: AxisField): {restored: boolean; changed: boolean} => {
250
+ const target = lastModifiedAxis === axis ? lastModifiedPreviousValue : undefined;
251
+ const changed = setSilently(axis, target as string | number | boolean | undefined);
252
+
253
+ return {restored: target !== undefined, changed};
254
+ };
255
+
256
+ /**
257
+ * Pick a sensible default for `packageType` / `deliveryType` given a carrier, sourced from
258
+ * `inheritedDeliveryOptions[carrier]`. Returns `undefined` when no useful default exists
259
+ * (caller falls back to clearing the field).
260
+ */
261
+ const inheritedDefault = (carrierName: string, axis: typeof FIELD_PACKAGE_TYPE | typeof FIELD_DELIVERY_TYPE) => {
262
+ const defaults = inheritedDeliveryOptions[carrierName];
263
+
264
+ if (!defaults) return undefined;
265
+
266
+ return axis === FIELD_PACKAGE_TYPE ? defaults.packageType : defaults.deliveryType;
267
+ };
268
+
269
+ /**
270
+ * Carrier-switch reset: keep the new carrier (switching is "fresh start" intent), apply the
271
+ * inherited defaults for `packageType` / `deliveryType`, and emit no notification (the UI
272
+ * already shifts significantly on carrier change). Called from BOTH the order watcher and
273
+ * the shipment watcher's invalid-combo branch — both paths converge on the same reset.
274
+ */
275
+ const applyCarrierDefaults = (): void => {
276
+ const carrierName = form.getValue<string | undefined>(FIELD_CARRIER);
277
+ const pkgDefault = carrierName ? inheritedDefault(carrierName, FIELD_PACKAGE_TYPE) : undefined;
278
+ const dtDefault = carrierName ? inheritedDefault(carrierName, FIELD_DELIVERY_TYPE) : undefined;
279
+
280
+ // Only write fields when an inherited default exists. Writing `undefined` triggers
281
+ // form-builder's RadioGroup `defaultValue` fallback, which then re-emits the default
282
+ // value as if the user had clicked it — looks like a user change to the axis-tracker
283
+ // and re-attributes `lastModifiedAxis` away from CARRIER, which spirals into a cycle
284
+ // where each auto-clear write produces another "user-like" change that triggers the
285
+ // shipment query again with the same invalid combo.
286
+ if (pkgDefault !== undefined) {
287
+ setSilently(FIELD_PACKAGE_TYPE, pkgDefault as string | number | boolean | undefined);
288
+ }
289
+ if (dtDefault !== undefined) {
290
+ setSilently(FIELD_DELIVERY_TYPE, dtDefault as string | number | boolean | undefined);
291
+ }
292
+ };
293
+
294
+ /**
295
+ * Build the user-visible notification line for an axis revert/clear. `restored: true` means
296
+ * the prior valid value was put back; `false` means the field was nulled because there was
297
+ * no prior valid value to fall back to.
298
+ */
299
+ const lineForAxisClear = (axis: AxisField, restored: boolean): string => {
300
+ const fieldLabel = translate(FIELD_TO_LABEL_KEY[axis]);
301
+
302
+ return restored
303
+ ? translate({key: 'capabilities_cleared_field_reverted', args: {field: fieldLabel}})
304
+ : translate({key: 'capabilities_cleared_field_cleared', args: {field: fieldLabel}});
305
+ };
306
+
307
+ const lineForOptionClear = (optionKey: string): string => {
308
+ const fieldLabel = translate(optionLabelKey(optionKey));
309
+
310
+ return translate({key: 'capabilities_cleared_option_cleared', args: {field: fieldLabel}});
311
+ };
312
+
313
+ const notifyClears = (lines: string[]): void => {
314
+ if (lines.length === 0) return;
315
+
316
+ addCapabilitiesClearNotification(notificationStore, translate('capabilities_cleared'), lines);
317
+ };
318
+
319
+ /**
320
+ * Decide how to react when the shipment query confirms the current selection is an invalid
321
+ * combo.
322
+ *
323
+ * - Carrier change: silent reset via `applyCarrierDefaults` (no notification).
324
+ * - PackageType / deliveryType change: revert THAT axis to its prior valid value (or clear
325
+ * if there's no revert target), with a notification explaining which path was taken.
326
+ * - No recent user action (modal pre-fill, weight slider): default-clear deliveryType with
327
+ * a notification.
328
+ *
329
+ * Returns the lines for the rolling notification. An empty array means "carrier change —
330
+ * silent."
331
+ */
332
+ const resolveInvalidCombo = (): string[] => {
333
+ if (lastModifiedAxis === FIELD_CARRIER) {
334
+ applyCarrierDefaults();
335
+
336
+ return [];
337
+ }
338
+
339
+ if (lastModifiedAxis === FIELD_PACKAGE_TYPE || lastModifiedAxis === FIELD_DELIVERY_TYPE) {
340
+ const {restored, changed} = revertAxis(lastModifiedAxis);
341
+
342
+ return changed ? [lineForAxisClear(lastModifiedAxis, restored)] : [];
343
+ }
344
+
345
+ const wrote = setSilently(FIELD_DELIVERY_TYPE, undefined);
346
+
347
+ return wrote ? [lineForAxisClear(FIELD_DELIVERY_TYPE, false)] : [];
348
+ };
349
+
350
+ /**
351
+ * Synchronous cross-axis validation against the order query — runs whenever the carrier
352
+ * dropdown or its underlying data changes. Catches "current packageType isn't even in the
353
+ * carrier's order-level union" without waiting for the shipment query round trip.
354
+ */
355
+ watch(
356
+ () => {
357
+ const carrier = getCarrierCapabilitiesForOrder(form);
358
+ const packageType = form.getValue<string | undefined>(FIELD_PACKAGE_TYPE);
359
+ const deliveryType = form.getValue<string | undefined>(FIELD_DELIVERY_TYPE);
360
+
361
+ return {
362
+ carrierName: carrier?.carrier,
363
+ packageTypesInCarrier: carrier?.packageTypes ?? [],
364
+ deliveryTypesInCarrier: carrier?.deliveryTypes ?? [],
365
+ packageType,
366
+ deliveryType,
367
+ };
368
+ },
369
+ ({carrierName, packageTypesInCarrier, deliveryTypesInCarrier, packageType, deliveryType}) => {
370
+ if (!carrierName) return;
371
+
372
+ const packageTypeInvalid = Boolean(packageType) && !packageTypesInCarrier.includes(packageType as string);
373
+ const deliveryTypeInvalid = Boolean(deliveryType) && !deliveryTypesInCarrier.includes(deliveryType as string);
374
+
375
+ if (!packageTypeInvalid && !deliveryTypeInvalid) return;
376
+
377
+ // Carrier-change special case: silent reset via inherited defaults. Without this branch
378
+ // the order watcher would clear/notify before the (debounced) shipment watcher gets a
379
+ // chance to apply the same silent reset, contradicting the silent-on-carrier rule.
380
+ if (lastModifiedAxis === FIELD_CARRIER) {
381
+ applyCarrierDefaults();
382
+
383
+ return;
384
+ }
385
+
386
+ const lines: string[] = [];
387
+
388
+ // Clear / revert the axis that's actually invalid for the current carrier — not
389
+ // `lastModifiedAxis`. The order-data watcher fires on weight / cc changes too, where
390
+ // `lastModifiedAxis` may not point at the field that's now out-of-list. Targeting the
391
+ // invalid axis directly avoids clearing deliveryType in response to an invalid
392
+ // packageType, and vice versa.
393
+ if (packageTypeInvalid) {
394
+ const {restored, changed} = revertAxis(FIELD_PACKAGE_TYPE);
395
+
396
+ if (changed) lines.push(lineForAxisClear(FIELD_PACKAGE_TYPE, restored));
397
+ }
398
+
399
+ if (deliveryTypeInvalid) {
400
+ const {restored, changed} = revertAxis(FIELD_DELIVERY_TYPE);
401
+
402
+ if (changed) lines.push(lineForAxisClear(FIELD_DELIVERY_TYPE, restored));
403
+ }
404
+
405
+ notifyClears(lines);
406
+ },
407
+ {deep: true},
408
+ );
409
+
410
+ /**
411
+ * Shipment-query watcher — handles both invalid-combo and option-availability cases via the
412
+ * snapshot helper above. Reads the query state directly so we can distinguish "still
413
+ * loading" (do nothing) from "loaded but combo invalid" (axis rollback) and "loaded and
414
+ * matched" (option-availability scan).
415
+ */
416
+ watch(
417
+ () => readShipmentSnapshot(selection, queryStore, orderId),
418
+ (snapshot) => {
419
+ if (snapshot.state === 'pending') return;
420
+
421
+ if (snapshot.state === 'invalid_combo') {
422
+ notifyClears(resolveInvalidCombo());
423
+
424
+ return;
425
+ }
426
+
427
+ const availableOptionKeys = Object.keys(snapshot.carrier.options);
428
+ const lines: string[] = [];
429
+ // Carrier switches reshape the form heavily already (different option set, different
430
+ // packageType/deliveryType lists). Notifying on top of that adds noise — silently turn
431
+ // off any orphaned options. Notify only when the change came from a non-carrier axis.
432
+ const silent = lastModifiedAxis === FIELD_CARRIER;
433
+
434
+ for (const optionKey of allOptionKeys) {
435
+ const fieldName = optionFieldName(optionKey);
436
+ const value = form.getValue(fieldName);
437
+ const isActive = value !== undefined && value !== TriState.Inherit && Boolean(value);
438
+
439
+ if (!isActive) continue;
440
+ if (availableOptionKeys.includes(optionKey)) continue;
441
+
442
+ setSilently(fieldName, TriState.Inherit);
443
+
444
+ if (!silent) {
445
+ lines.push(lineForOptionClear(optionKey));
446
+ }
447
+ }
448
+
449
+ notifyClears(lines);
450
+ },
451
+ );
452
+ };
@@ -0,0 +1,14 @@
1
+ import {describe, expect, it} from 'vitest';
2
+ import {ref} from 'vue';
3
+ import {useCapabilitiesWatcher, type FormInput, type OrderInput} from './useCapabilitiesWatcher';
4
+
5
+ describe('useCapabilitiesWatcher', () => {
6
+ it('merges order and form refs into the initial selection', () => {
7
+ const orderRef = ref<OrderInput>({cc: 'NL', weight: 2000});
8
+ const formRef = ref<FormInput>({carrier: 'POSTNL', packageType: 'PACKAGE'});
9
+
10
+ const selection = useCapabilitiesWatcher(orderRef, formRef);
11
+
12
+ expect(selection.value).toMatchObject({cc: 'NL', weight: 2000, carrier: 'POSTNL', packageType: 'PACKAGE'});
13
+ });
14
+ });
@@ -0,0 +1,29 @@
1
+ import {computed, toValue, type MaybeRefOrGetter, type Ref} from 'vue';
2
+ import {refDebounced} from '@vueuse/core';
3
+ import {type CapabilitiesSelection} from '../../actions/composables/queries/account/useShipmentCapabilitiesQuery';
4
+
5
+ const DEBOUNCE_MS = 100;
6
+
7
+ export type OrderInput = {cc?: string; weight?: number};
8
+ export type FormInput = {carrier?: string; packageType?: string; deliveryType?: string};
9
+
10
+ /**
11
+ * Merge an order source and a shipment-options form source into a single debounced selection
12
+ * ref suitable for the order and shipment capabilities queries. Rapid form-state changes
13
+ * (clicking through carriers, toggling options) collapse into one query refetch after the
14
+ * user pauses.
15
+ *
16
+ * Inputs accept any of `Ref<T>`, `ComputedRef<T>`, or `() => T` so callers can pass whatever
17
+ * shape they already have.
18
+ */
19
+ export const useCapabilitiesWatcher = (
20
+ order: MaybeRefOrGetter<OrderInput>,
21
+ form: MaybeRefOrGetter<FormInput>,
22
+ ): Readonly<Ref<CapabilitiesSelection>> => {
23
+ const merged = computed<CapabilitiesSelection>(() => ({
24
+ ...toValue(order),
25
+ ...toValue(form),
26
+ }));
27
+
28
+ return refDebounced(merged, DEBOUNCE_MS);
29
+ };
@@ -0,0 +1,160 @@
1
+ import {describe, expect, it, vi, beforeEach} from 'vitest';
2
+ import {effectScope, nextTick, ref} from 'vue';
3
+ import {BackendEndpoint, TriState} from '@myparcel-dev/pdk-common';
4
+ import {FIELD_CARRIER, FIELD_DELIVERY_TYPE, FIELD_MANUAL_WEIGHT, FIELD_PACKAGE_TYPE} from './field';
5
+
6
+ const queryStoreMock = {
7
+ register: vi.fn(),
8
+ unregister: vi.fn(),
9
+ };
10
+
11
+ vi.mock('../../stores', () => ({
12
+ useQueryStore: () => queryStoreMock,
13
+ }));
14
+
15
+ vi.mock('../../services', () => ({
16
+ globalLogger: {debug: vi.fn(), error: vi.fn(), warn: vi.fn(), info: vi.fn()},
17
+ }));
18
+
19
+ const useOrderCapabilitiesQueryMock = vi.fn(() => ({status: ref('loading'), data: ref(undefined)}));
20
+ const useShipmentCapabilitiesQueryMock = vi.fn(() => ({status: ref('loading'), data: ref(undefined)}));
21
+
22
+ vi.mock('../../actions/composables/queries/account/useOrderCapabilitiesQuery', () => ({
23
+ useOrderCapabilitiesQuery: useOrderCapabilitiesQueryMock,
24
+ }));
25
+
26
+ vi.mock('../../actions/composables/queries/account/useShipmentCapabilitiesQuery', () => ({
27
+ useShipmentCapabilitiesQuery: useShipmentCapabilitiesQueryMock,
28
+ }));
29
+
30
+ const buildForm = (initial: Record<string, unknown>) => {
31
+ const fields = new Map<string, {ref: ReturnType<typeof ref>}>();
32
+
33
+ Object.keys(initial).forEach((name) => {
34
+ fields.set(name, {ref: ref(initial[name])});
35
+ });
36
+
37
+ return {
38
+ getValue: <T,>(name: string): T => fields.get(name)?.ref.value as T,
39
+ setExternally: (name: string, value: unknown) => {
40
+ const field = fields.get(name);
41
+
42
+ if (field) {
43
+ (field.ref as ReturnType<typeof ref>).value = value;
44
+ } else {
45
+ fields.set(name, {ref: ref(value)});
46
+ }
47
+ },
48
+ };
49
+ };
50
+
51
+ beforeEach(() => {
52
+ queryStoreMock.register.mockClear();
53
+ queryStoreMock.unregister.mockClear();
54
+ useOrderCapabilitiesQueryMock.mockClear();
55
+ useShipmentCapabilitiesQueryMock.mockClear();
56
+ });
57
+
58
+ const orderShape = (cc = 'NL', initialWeight = 1500) =>
59
+ ({
60
+ externalIdentifier: 'order-1',
61
+ shippingAddress: {cc},
62
+ physicalProperties: {initialWeight},
63
+ }) as never;
64
+
65
+ describe('wireProxyCapabilities', () => {
66
+ it('treats TriState.Inherit (-1) as "no manual override" and falls back to initialWeight', async () => {
67
+ const form = buildForm({
68
+ [FIELD_CARRIER]: 'POSTNL',
69
+ [FIELD_PACKAGE_TYPE]: 'PACKAGE',
70
+ [FIELD_DELIVERY_TYPE]: 'STANDARD',
71
+ [FIELD_MANUAL_WEIGHT]: TriState.Inherit,
72
+ });
73
+
74
+ const scope = effectScope();
75
+ const {wireProxyCapabilities} = await import('./wireProxyCapabilities');
76
+
77
+ scope.run(() => {
78
+ wireProxyCapabilities(form as never, orderShape('NL', 2500));
79
+ });
80
+
81
+ // The order query is wired with a `computed` over the captured input — read its argument
82
+ // ref's value to verify the manual-weight guard.
83
+ const orderInputRef = useOrderCapabilitiesQueryMock.mock.calls[0][0] as {value: {weight?: number}};
84
+
85
+ expect(orderInputRef.value.weight).toBe(2500);
86
+
87
+ scope.stop();
88
+ });
89
+
90
+ it('uses positive manual weight when set', async () => {
91
+ const form = buildForm({
92
+ [FIELD_CARRIER]: 'POSTNL',
93
+ [FIELD_PACKAGE_TYPE]: 'PACKAGE',
94
+ [FIELD_DELIVERY_TYPE]: 'STANDARD',
95
+ [FIELD_MANUAL_WEIGHT]: 4200,
96
+ });
97
+
98
+ const scope = effectScope();
99
+ const {wireProxyCapabilities} = await import('./wireProxyCapabilities');
100
+
101
+ scope.run(() => {
102
+ wireProxyCapabilities(form as never, orderShape('NL', 2500));
103
+ });
104
+
105
+ const orderInputRef = useOrderCapabilitiesQueryMock.mock.calls[0][0] as {value: {weight?: number}};
106
+
107
+ // Wait for the debounce (refDebounced default 100ms in this codebase).
108
+ await new Promise((resolve) => setTimeout(resolve, 150));
109
+ await nextTick();
110
+
111
+ expect(orderInputRef.value.weight).toBe(4200);
112
+
113
+ scope.stop();
114
+ });
115
+
116
+ it('skips wiring and returns undefined when the order has no externalIdentifier (bulk path)', async () => {
117
+ const form = buildForm({});
118
+
119
+ const scope = effectScope();
120
+ const {wireProxyCapabilities} = await import('./wireProxyCapabilities');
121
+ let result: unknown;
122
+
123
+ scope.run(() => {
124
+ result = wireProxyCapabilities(form as never, {} as never);
125
+ });
126
+
127
+ expect(result).toBeUndefined();
128
+ expect(queryStoreMock.register).not.toHaveBeenCalled();
129
+ expect(useOrderCapabilitiesQueryMock).not.toHaveBeenCalled();
130
+ expect(useShipmentCapabilitiesQueryMock).not.toHaveBeenCalled();
131
+
132
+ scope.stop();
133
+ });
134
+
135
+ it('unregisters BOTH query modifiers when the form scope disposes', async () => {
136
+ const form = buildForm({
137
+ [FIELD_CARRIER]: 'POSTNL',
138
+ [FIELD_PACKAGE_TYPE]: 'PACKAGE',
139
+ [FIELD_DELIVERY_TYPE]: 'STANDARD',
140
+ [FIELD_MANUAL_WEIGHT]: TriState.Inherit,
141
+ });
142
+
143
+ const scope = effectScope();
144
+ const {wireProxyCapabilities} = await import('./wireProxyCapabilities');
145
+
146
+ scope.run(() => {
147
+ wireProxyCapabilities(form as never, orderShape());
148
+ });
149
+
150
+ // Before dispose: both modifiers registered, neither unregistered.
151
+ expect(queryStoreMock.register).toHaveBeenCalledTimes(2);
152
+ expect(queryStoreMock.unregister).not.toHaveBeenCalled();
153
+
154
+ scope.stop();
155
+
156
+ expect(queryStoreMock.unregister).toHaveBeenCalledTimes(2);
157
+ expect(queryStoreMock.unregister).toHaveBeenCalledWith(BackendEndpoint.ProxyCapabilities, 'order-1.order');
158
+ expect(queryStoreMock.unregister).toHaveBeenCalledWith(BackendEndpoint.ProxyCapabilities, 'order-1.shipment');
159
+ });
160
+ });