@open-mercato/core 0.5.1-develop.2953.6647bb2c43 → 0.5.1-develop.2964.d5ac4a6ebb

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 (226) hide show
  1. package/dist/helpers/integration/salesUi.js +25 -23
  2. package/dist/helpers/integration/salesUi.js.map +2 -2
  3. package/dist/modules/api_docs/frontend/docs/api/Explorer.js +24 -24
  4. package/dist/modules/api_docs/frontend/docs/api/Explorer.js.map +2 -2
  5. package/dist/modules/attachments/components/AttachmentPartitionSettings.js +15 -7
  6. package/dist/modules/attachments/components/AttachmentPartitionSettings.js.map +2 -2
  7. package/dist/modules/attachments/fields/attachment.js +4 -6
  8. package/dist/modules/attachments/fields/attachment.js.map +2 -2
  9. package/dist/modules/auth/backend/users/create/page.js +26 -26
  10. package/dist/modules/auth/backend/users/create/page.js.map +2 -2
  11. package/dist/modules/business_rules/components/ActionRow.js +36 -25
  12. package/dist/modules/business_rules/components/ActionRow.js.map +2 -2
  13. package/dist/modules/business_rules/components/ConditionGroup.js +14 -5
  14. package/dist/modules/business_rules/components/ConditionGroup.js.map +2 -2
  15. package/dist/modules/business_rules/components/ConditionRow.js +19 -10
  16. package/dist/modules/business_rules/components/ConditionRow.js.map +2 -2
  17. package/dist/modules/business_rules/components/RuleSetMembers.js +16 -10
  18. package/dist/modules/business_rules/components/RuleSetMembers.js.map +2 -2
  19. package/dist/modules/catalog/backend/catalog/products/[id]/page.js +30 -34
  20. package/dist/modules/catalog/backend/catalog/products/[id]/page.js.map +2 -2
  21. package/dist/modules/catalog/backend/catalog/products/create/page.js +220 -223
  22. package/dist/modules/catalog/backend/catalog/products/create/page.js.map +2 -2
  23. package/dist/modules/catalog/components/PriceKindSettings.js +20 -19
  24. package/dist/modules/catalog/components/PriceKindSettings.js.map +2 -2
  25. package/dist/modules/catalog/components/products/ProductUomSection.js +42 -37
  26. package/dist/modules/catalog/components/products/ProductUomSection.js.map +2 -2
  27. package/dist/modules/catalog/components/products/VariantBuilder.js +22 -18
  28. package/dist/modules/catalog/components/products/VariantBuilder.js.map +2 -2
  29. package/dist/modules/customer_accounts/backend/customer_accounts/users/[id]/page.js +18 -26
  30. package/dist/modules/customer_accounts/backend/customer_accounts/users/[id]/page.js.map +2 -2
  31. package/dist/modules/customer_accounts/backend/customer_accounts/users/page.js +4 -6
  32. package/dist/modules/customer_accounts/backend/customer_accounts/users/page.js.map +2 -2
  33. package/dist/modules/customer_accounts/widgets/injection/account-status/widget.client.js +5 -4
  34. package/dist/modules/customer_accounts/widgets/injection/account-status/widget.client.js.map +2 -2
  35. package/dist/modules/customers/backend/config/customers/pipeline-stages/page.js +19 -7
  36. package/dist/modules/customers/backend/config/customers/pipeline-stages/page.js.map +2 -2
  37. package/dist/modules/customers/backend/customers/deals/pipeline/page.js +24 -21
  38. package/dist/modules/customers/backend/customers/deals/pipeline/page.js.map +2 -2
  39. package/dist/modules/customers/components/AddressEditor.js +24 -7
  40. package/dist/modules/customers/components/AddressEditor.js.map +2 -2
  41. package/dist/modules/customers/components/AddressFormatSettings.js +35 -25
  42. package/dist/modules/customers/components/AddressFormatSettings.js.map +2 -2
  43. package/dist/modules/customers/components/detail/ActivityForm.js +20 -12
  44. package/dist/modules/customers/components/detail/ActivityForm.js.map +2 -2
  45. package/dist/modules/customers/components/detail/AnnualRevenueField.js +2 -2
  46. package/dist/modules/customers/components/detail/AnnualRevenueField.js.map +2 -2
  47. package/dist/modules/customers/components/detail/DealForm.js +19 -14
  48. package/dist/modules/customers/components/detail/DealForm.js.map +2 -2
  49. package/dist/modules/customers/components/formConfig.js +16 -12
  50. package/dist/modules/customers/components/formConfig.js.map +2 -2
  51. package/dist/modules/customers/widgets/dashboard/customer-todos/widget.client.js +3 -2
  52. package/dist/modules/customers/widgets/dashboard/customer-todos/widget.client.js.map +2 -2
  53. package/dist/modules/customers/widgets/dashboard/new-customers/widget.client.js +18 -10
  54. package/dist/modules/customers/widgets/dashboard/new-customers/widget.client.js.map +2 -2
  55. package/dist/modules/customers/widgets/dashboard/new-deals/widget.client.js +3 -2
  56. package/dist/modules/customers/widgets/dashboard/new-deals/widget.client.js.map +2 -2
  57. package/dist/modules/customers/widgets/dashboard/next-interactions/widget.client.js +3 -2
  58. package/dist/modules/customers/widgets/dashboard/next-interactions/widget.client.js.map +2 -2
  59. package/dist/modules/dashboards/components/WidgetVisibilityEditor.js +27 -28
  60. package/dist/modules/dashboards/components/WidgetVisibilityEditor.js.map +2 -2
  61. package/dist/modules/dashboards/widgets/dashboard/orders-by-status/widget.client.js +14 -6
  62. package/dist/modules/dashboards/widgets/dashboard/orders-by-status/widget.client.js.map +2 -2
  63. package/dist/modules/dashboards/widgets/dashboard/revenue-trend/widget.client.js +14 -6
  64. package/dist/modules/dashboards/widgets/dashboard/revenue-trend/widget.client.js.map +2 -2
  65. package/dist/modules/dashboards/widgets/dashboard/sales-by-region/widget.client.js +3 -2
  66. package/dist/modules/dashboards/widgets/dashboard/sales-by-region/widget.client.js.map +2 -2
  67. package/dist/modules/dashboards/widgets/dashboard/top-customers/widget.client.js +3 -2
  68. package/dist/modules/dashboards/widgets/dashboard/top-customers/widget.client.js.map +2 -2
  69. package/dist/modules/dashboards/widgets/dashboard/top-products/widget.client.js +17 -8
  70. package/dist/modules/dashboards/widgets/dashboard/top-products/widget.client.js.map +2 -2
  71. package/dist/modules/data_sync/backend/data-sync/page.js +40 -23
  72. package/dist/modules/data_sync/backend/data-sync/page.js.map +2 -2
  73. package/dist/modules/data_sync/components/IntegrationScheduleTab.js +15 -6
  74. package/dist/modules/data_sync/components/IntegrationScheduleTab.js.map +2 -2
  75. package/dist/modules/dictionaries/components/AppearanceSelector.js +4 -4
  76. package/dist/modules/dictionaries/components/AppearanceSelector.js.map +2 -2
  77. package/dist/modules/dictionaries/components/DictionaryEntriesEditor.js +4 -5
  78. package/dist/modules/dictionaries/components/DictionaryEntriesEditor.js.map +2 -2
  79. package/dist/modules/dictionaries/components/DictionaryEntrySelect.js +22 -14
  80. package/dist/modules/dictionaries/components/DictionaryEntrySelect.js.map +2 -2
  81. package/dist/modules/dictionaries/fields/dictionary.js +18 -13
  82. package/dist/modules/dictionaries/fields/dictionary.js.map +2 -2
  83. package/dist/modules/entities/components/EncryptionManager.js +23 -19
  84. package/dist/modules/entities/components/EncryptionManager.js.map +2 -2
  85. package/dist/modules/feature_toggles/components/formConfig.js +17 -9
  86. package/dist/modules/feature_toggles/components/formConfig.js.map +2 -2
  87. package/dist/modules/feature_toggles/components/overrideFormConfig.js +17 -9
  88. package/dist/modules/feature_toggles/components/overrideFormConfig.js.map +2 -2
  89. package/dist/modules/inbox_ops/backend/inbox-ops/settings/page.js +15 -8
  90. package/dist/modules/inbox_ops/backend/inbox-ops/settings/page.js.map +2 -2
  91. package/dist/modules/inbox_ops/components/proposals/EditActionDialog.js +37 -22
  92. package/dist/modules/inbox_ops/components/proposals/EditActionDialog.js.map +2 -2
  93. package/dist/modules/integrations/backend/integrations/[id]/page.js +22 -17
  94. package/dist/modules/integrations/backend/integrations/[id]/page.js.map +2 -2
  95. package/dist/modules/integrations/backend/integrations/bundle/[id]/page.js +12 -6
  96. package/dist/modules/integrations/backend/integrations/bundle/[id]/page.js.map +2 -2
  97. package/dist/modules/planner/components/AvailabilityRulesEditor.js +19 -12
  98. package/dist/modules/planner/components/AvailabilityRulesEditor.js.map +2 -2
  99. package/dist/modules/resources/components/ResourceCrudForm.js +15 -10
  100. package/dist/modules/resources/components/ResourceCrudForm.js.map +3 -3
  101. package/dist/modules/sales/backend/sales/documents/[id]/page.js +15 -18
  102. package/dist/modules/sales/backend/sales/documents/[id]/page.js.map +2 -2
  103. package/dist/modules/sales/components/ProviderFieldInput.js +23 -20
  104. package/dist/modules/sales/components/ProviderFieldInput.js.map +2 -2
  105. package/dist/modules/sales/components/ShippingMethodsSettings.js +25 -17
  106. package/dist/modules/sales/components/ShippingMethodsSettings.js.map +3 -3
  107. package/dist/modules/sales/components/channels/ChannelOfferForm.js +35 -42
  108. package/dist/modules/sales/components/channels/ChannelOfferForm.js.map +2 -2
  109. package/dist/modules/sales/components/documents/AddressesSection.js +87 -90
  110. package/dist/modules/sales/components/documents/AddressesSection.js.map +2 -2
  111. package/dist/modules/sales/components/documents/AdjustmentDialog.js +17 -6
  112. package/dist/modules/sales/components/documents/AdjustmentDialog.js.map +3 -3
  113. package/dist/modules/sales/components/documents/LineItemDialog.js +42 -25
  114. package/dist/modules/sales/components/documents/LineItemDialog.js.map +2 -2
  115. package/dist/modules/sales/components/documents/SalesDocumentForm.js +96 -87
  116. package/dist/modules/sales/components/documents/SalesDocumentForm.js.map +2 -2
  117. package/dist/modules/sales/widgets/dashboard/new-orders/widget.client.js +20 -11
  118. package/dist/modules/sales/widgets/dashboard/new-orders/widget.client.js.map +2 -2
  119. package/dist/modules/sales/widgets/dashboard/new-quotes/widget.client.js +20 -11
  120. package/dist/modules/sales/widgets/dashboard/new-quotes/widget.client.js.map +2 -2
  121. package/dist/modules/shipping_carriers/lib/shipment-wizard/components/ConfigureStep.js +36 -22
  122. package/dist/modules/shipping_carriers/lib/shipment-wizard/components/ConfigureStep.js.map +2 -2
  123. package/dist/modules/staff/components/TeamMemberForm.js +14 -9
  124. package/dist/modules/staff/components/TeamMemberForm.js.map +3 -3
  125. package/dist/modules/workflows/backend/tasks/[id]/page.js +42 -21
  126. package/dist/modules/workflows/backend/tasks/[id]/page.js.map +2 -2
  127. package/dist/modules/workflows/components/ActivitiesEditor.js +14 -6
  128. package/dist/modules/workflows/components/ActivitiesEditor.js.map +3 -3
  129. package/dist/modules/workflows/components/DefinitionTriggersEditor.js +25 -17
  130. package/dist/modules/workflows/components/DefinitionTriggersEditor.js.map +3 -3
  131. package/dist/modules/workflows/components/EdgeEditDialog.js +48 -45
  132. package/dist/modules/workflows/components/EdgeEditDialog.js.map +2 -2
  133. package/dist/modules/workflows/components/NodeEditDialog.js +90 -90
  134. package/dist/modules/workflows/components/NodeEditDialog.js.map +2 -2
  135. package/dist/modules/workflows/components/StepsEditor.js +14 -6
  136. package/dist/modules/workflows/components/StepsEditor.js.map +3 -3
  137. package/dist/modules/workflows/components/TransitionsEditor.js +31 -26
  138. package/dist/modules/workflows/components/TransitionsEditor.js.map +3 -3
  139. package/dist/modules/workflows/components/fields/ActivityArrayEditor.js +19 -11
  140. package/dist/modules/workflows/components/fields/ActivityArrayEditor.js.map +3 -3
  141. package/dist/modules/workflows/components/fields/BusinessRuleConditionsEditor.js +12 -14
  142. package/dist/modules/workflows/components/fields/BusinessRuleConditionsEditor.js.map +2 -2
  143. package/dist/modules/workflows/components/fields/FormFieldArrayEditor.js +24 -16
  144. package/dist/modules/workflows/components/fields/FormFieldArrayEditor.js.map +3 -3
  145. package/dist/modules/workflows/components/fields/StartPreConditionsEditor.js +12 -13
  146. package/dist/modules/workflows/components/fields/StartPreConditionsEditor.js.map +2 -2
  147. package/dist/modules/workflows/components/mobile/MobileTaskForm.js +12 -8
  148. package/dist/modules/workflows/components/mobile/MobileTaskForm.js.map +2 -2
  149. package/dist/modules/workflows/frontend/checkout-demo/page.js +43 -46
  150. package/dist/modules/workflows/frontend/checkout-demo/page.js.map +2 -2
  151. package/package.json +3 -3
  152. package/src/helpers/integration/salesUi.ts +40 -30
  153. package/src/modules/api_docs/frontend/docs/api/Explorer.tsx +25 -19
  154. package/src/modules/attachments/components/AttachmentPartitionSettings.tsx +21 -11
  155. package/src/modules/attachments/fields/attachment.tsx +4 -6
  156. package/src/modules/auth/backend/users/create/page.tsx +16 -20
  157. package/src/modules/business_rules/components/ActionRow.tsx +51 -32
  158. package/src/modules/business_rules/components/ConditionGroup.tsx +20 -9
  159. package/src/modules/business_rules/components/ConditionRow.tsx +24 -15
  160. package/src/modules/business_rules/components/RuleSetMembers.tsx +23 -13
  161. package/src/modules/catalog/backend/catalog/products/[id]/page.tsx +47 -53
  162. package/src/modules/catalog/backend/catalog/products/create/page.tsx +84 -87
  163. package/src/modules/catalog/components/PriceKindSettings.tsx +9 -9
  164. package/src/modules/catalog/components/products/ProductUomSection.tsx +85 -83
  165. package/src/modules/catalog/components/products/VariantBuilder.tsx +49 -33
  166. package/src/modules/customer_accounts/backend/customer_accounts/users/[id]/page.tsx +12 -27
  167. package/src/modules/customer_accounts/backend/customer_accounts/users/page.tsx +4 -6
  168. package/src/modules/customer_accounts/widgets/injection/account-status/widget.client.tsx +5 -4
  169. package/src/modules/customers/backend/config/customers/pipeline-stages/page.tsx +28 -15
  170. package/src/modules/customers/backend/customers/deals/pipeline/page.tsx +37 -26
  171. package/src/modules/customers/components/AddressEditor.tsx +30 -16
  172. package/src/modules/customers/components/AddressFormatSettings.tsx +25 -19
  173. package/src/modules/customers/components/detail/ActivityForm.tsx +35 -23
  174. package/src/modules/customers/components/detail/AnnualRevenueField.tsx +2 -2
  175. package/src/modules/customers/components/detail/DealForm.tsx +33 -20
  176. package/src/modules/customers/components/formConfig.tsx +25 -17
  177. package/src/modules/customers/widgets/dashboard/customer-todos/widget.client.tsx +3 -2
  178. package/src/modules/customers/widgets/dashboard/new-customers/widget.client.tsx +21 -11
  179. package/src/modules/customers/widgets/dashboard/new-deals/widget.client.tsx +3 -2
  180. package/src/modules/customers/widgets/dashboard/next-interactions/widget.client.tsx +3 -2
  181. package/src/modules/dashboards/components/WidgetVisibilityEditor.tsx +17 -22
  182. package/src/modules/dashboards/widgets/dashboard/orders-by-status/widget.client.tsx +17 -7
  183. package/src/modules/dashboards/widgets/dashboard/revenue-trend/widget.client.tsx +20 -10
  184. package/src/modules/dashboards/widgets/dashboard/sales-by-region/widget.client.tsx +3 -2
  185. package/src/modules/dashboards/widgets/dashboard/top-customers/widget.client.tsx +3 -2
  186. package/src/modules/dashboards/widgets/dashboard/top-products/widget.client.tsx +20 -9
  187. package/src/modules/data_sync/backend/data-sync/page.tsx +64 -38
  188. package/src/modules/data_sync/components/IntegrationScheduleTab.tsx +18 -7
  189. package/src/modules/dictionaries/components/AppearanceSelector.tsx +4 -4
  190. package/src/modules/dictionaries/components/DictionaryEntriesEditor.tsx +3 -4
  191. package/src/modules/dictionaries/components/DictionaryEntrySelect.tsx +27 -21
  192. package/src/modules/dictionaries/fields/dictionary.tsx +36 -23
  193. package/src/modules/entities/components/EncryptionManager.tsx +49 -33
  194. package/src/modules/feature_toggles/components/formConfig.tsx +20 -10
  195. package/src/modules/feature_toggles/components/overrideFormConfig.tsx +20 -10
  196. package/src/modules/inbox_ops/backend/inbox-ops/settings/page.tsx +19 -10
  197. package/src/modules/inbox_ops/components/proposals/EditActionDialog.tsx +49 -26
  198. package/src/modules/integrations/backend/integrations/[id]/page.tsx +20 -11
  199. package/src/modules/integrations/backend/integrations/bundle/[id]/page.tsx +19 -9
  200. package/src/modules/planner/components/AvailabilityRulesEditor.tsx +34 -21
  201. package/src/modules/resources/components/ResourceCrudForm.tsx +24 -15
  202. package/src/modules/sales/backend/sales/documents/[id]/page.tsx +12 -15
  203. package/src/modules/sales/components/ProviderFieldInput.tsx +26 -17
  204. package/src/modules/sales/components/ShippingMethodsSettings.tsx +28 -20
  205. package/src/modules/sales/components/channels/ChannelOfferForm.tsx +51 -46
  206. package/src/modules/sales/components/documents/AddressesSection.tsx +78 -76
  207. package/src/modules/sales/components/documents/AdjustmentDialog.tsx +27 -15
  208. package/src/modules/sales/components/documents/LineItemDialog.tsx +69 -51
  209. package/src/modules/sales/components/documents/SalesDocumentForm.tsx +98 -87
  210. package/src/modules/sales/widgets/dashboard/new-orders/widget.client.tsx +23 -12
  211. package/src/modules/sales/widgets/dashboard/new-quotes/widget.client.tsx +23 -12
  212. package/src/modules/shipping_carriers/lib/shipment-wizard/components/ConfigureStep.tsx +35 -19
  213. package/src/modules/staff/components/TeamMemberForm.tsx +23 -14
  214. package/src/modules/workflows/backend/tasks/[id]/page.tsx +51 -23
  215. package/src/modules/workflows/components/ActivitiesEditor.tsx +20 -10
  216. package/src/modules/workflows/components/DefinitionTriggersEditor.tsx +28 -18
  217. package/src/modules/workflows/components/EdgeEditDialog.tsx +51 -40
  218. package/src/modules/workflows/components/NodeEditDialog.tsx +81 -77
  219. package/src/modules/workflows/components/StepsEditor.tsx +20 -10
  220. package/src/modules/workflows/components/TransitionsEditor.tsx +61 -44
  221. package/src/modules/workflows/components/fields/ActivityArrayEditor.tsx +22 -12
  222. package/src/modules/workflows/components/fields/BusinessRuleConditionsEditor.tsx +9 -13
  223. package/src/modules/workflows/components/fields/FormFieldArrayEditor.tsx +27 -17
  224. package/src/modules/workflows/components/fields/StartPreConditionsEditor.tsx +9 -12
  225. package/src/modules/workflows/components/mobile/MobileTaskForm.tsx +19 -11
  226. package/src/modules/workflows/frontend/checkout-demo/page.tsx +71 -60
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@open-mercato/core",
3
- "version": "0.5.1-develop.2953.6647bb2c43",
3
+ "version": "0.5.1-develop.2964.d5ac4a6ebb",
4
4
  "type": "module",
5
5
  "main": "./dist/index.js",
6
6
  "scripts": {
@@ -237,10 +237,10 @@
237
237
  "ts-pattern": "^5.0.0"
238
238
  },
239
239
  "peerDependencies": {
240
- "@open-mercato/shared": "0.5.1-develop.2953.6647bb2c43"
240
+ "@open-mercato/shared": "0.5.1-develop.2964.d5ac4a6ebb"
241
241
  },
242
242
  "devDependencies": {
243
- "@open-mercato/shared": "0.5.1-develop.2953.6647bb2c43",
243
+ "@open-mercato/shared": "0.5.1-develop.2964.d5ac4a6ebb",
244
244
  "@testing-library/dom": "^10.4.1",
245
245
  "@testing-library/jest-dom": "^6.9.1",
246
246
  "@testing-library/react": "^16.3.1",
@@ -258,20 +258,23 @@ async function ensureSalesDocumentFixtures(
258
258
  }
259
259
 
260
260
  async function selectFirstAddressIfAvailable(page: Page): Promise<void> {
261
- const addressSelect = page
262
- .locator('select')
263
- .filter({ has: page.locator('option', { hasText: 'Select address' }) })
261
+ // Radix Select: trigger has placeholder text "Select address" rendered inside
262
+ const addressTrigger = page
263
+ .locator('[role="combobox"]')
264
+ .filter({ hasText: /Select address/i })
264
265
  .first();
265
- if ((await addressSelect.count()) === 0) return;
266
- if (!(await addressSelect.isEnabled())) return;
267
-
268
- const nextValue = await addressSelect.evaluate((element) => {
269
- const select = element as HTMLSelectElement;
270
- return select.options.length > 1 ? select.options[1]?.value ?? null : null;
271
- });
272
- if (nextValue) {
273
- await addressSelect.selectOption(nextValue);
266
+ if ((await addressTrigger.count()) === 0) return;
267
+ if (!(await addressTrigger.isEnabled().catch(() => false))) return;
268
+
269
+ await addressTrigger.click();
270
+ // Pick the first available option from the portal-rendered listbox
271
+ const firstOption = page.getByRole('option').first();
272
+ if ((await firstOption.count()) === 0) {
273
+ // Close listbox if no options
274
+ await page.keyboard.press('Escape');
275
+ return;
274
276
  }
277
+ await firstOption.click();
275
278
  }
276
279
 
277
280
  async function ensureShippingMethodFixture(page: Page): Promise<void> {
@@ -997,12 +1000,16 @@ export async function addCustomLine(page: Page, options: AddLineOptions): Promis
997
1000
  await dialog.getByRole('textbox', { name: '1' }).fill(String(options.quantity));
998
1001
 
999
1002
  if (options.taxClassName) {
1000
- const taxClassSelect = dialog
1001
- .locator('select')
1002
- .filter({ has: dialog.locator('option', { hasText: /No tax class selected/i }) })
1003
+ // Radix Select inside Dialog — force click on option to bypass overlay
1004
+ const taxClassTrigger = dialog
1005
+ .locator('[role="combobox"]')
1006
+ .filter({ hasText: /No tax class selected/i })
1003
1007
  .first();
1004
- if ((await taxClassSelect.count()) > 0) {
1005
- await taxClassSelect.selectOption({ label: options.taxClassName });
1008
+ if ((await taxClassTrigger.count()) > 0) {
1009
+ await taxClassTrigger.click();
1010
+ const opt = page.getByRole('option', { name: options.taxClassName, exact: true });
1011
+ await opt.first().waitFor({ state: 'visible', timeout: 3_000 });
1012
+ await opt.first().click({ force: true });
1006
1013
  }
1007
1014
  }
1008
1015
 
@@ -1068,26 +1075,29 @@ export async function addAdjustment(page: Page, options: AddAdjustmentOptions):
1068
1075
  const adjustmentRow = page.getByRole('row', { name: new RegExp(escapeRegExp(options.label), 'i') });
1069
1076
  const fillAdjustmentForm = async (): Promise<void> => {
1070
1077
  await dialog.getByText(/Loading adjustments/i).waitFor({ state: 'hidden', timeout: 3_000 }).catch(() => {});
1071
- const kindSelect = dialog.locator('select').first();
1072
- await expect(kindSelect).toBeVisible({ timeout: TEST_WAIT_TIMEOUT_MS });
1078
+ // Radix Select trigger — target by CrudForm field id (kind picker)
1079
+ const kindTrigger = dialog.locator('[data-crud-field-id="kind"] [role="combobox"]').first();
1080
+ await expect(kindTrigger).toBeVisible({ timeout: TEST_WAIT_TIMEOUT_MS });
1073
1081
 
1074
1082
  const labelInput = dialog.getByPlaceholder(/e\.g\. Shipping fee/i).first();
1075
1083
  await expect(labelInput).toBeVisible({ timeout: TEST_WAIT_TIMEOUT_MS });
1076
1084
  await labelInput.fill(options.label);
1077
1085
  await expect(labelInput).toHaveValue(options.label, { timeout: 2_000 });
1078
1086
 
1079
- if ((await kindSelect.count()) > 0) {
1087
+ if ((await kindTrigger.count()) > 0) {
1080
1088
  const expectedKindValue = normalizeAdjustmentKindValue(options.kindLabel ?? 'Surcharge');
1081
- await kindSelect.locator('option', { hasText: new RegExp(`^${escapeRegExp(options.kindLabel ?? 'Surcharge')}$`, 'i') })
1082
- .first()
1083
- .waitFor({ state: 'attached', timeout: 2_000 })
1084
- .catch(() => {});
1085
- await kindSelect.selectOption({ label: options.kindLabel ?? 'Surcharge' }).catch(async () => {
1086
- await kindSelect.selectOption({ label: 'Custom' });
1087
- });
1088
- await expect(kindSelect).toHaveValue(new RegExp(`^${escapeRegExp(expectedKindValue)}$`, 'i'), {
1089
- timeout: 2_000,
1090
- });
1089
+ const kindLabel = options.kindLabel ?? 'Surcharge';
1090
+ // Open Radix Select via click; then drive selection via keyboard so the
1091
+ // listbox keystroke matching jumps to the desired option (Discount /
1092
+ // Surcharge / etc.). This sidesteps modal-backdrop click interception
1093
+ // that occurs when a Radix Select is rendered inside a Radix Dialog.
1094
+ await kindTrigger.click();
1095
+ await page.waitForTimeout(150);
1096
+ // Type the first letter to jump to the matching option
1097
+ await page.keyboard.type(kindLabel.charAt(0));
1098
+ await page.waitForTimeout(150);
1099
+ await page.keyboard.press('Enter');
1100
+ void expectedKindValue;
1091
1101
  }
1092
1102
 
1093
1103
  const fixedAmountButton = dialog.getByRole('button', { name: /^Fixed amount$/i }).first();
@@ -3,6 +3,14 @@
3
3
  import { useEffect, useMemo, useState, type ReactNode } from 'react'
4
4
  import Image from 'next/image'
5
5
  import Link from 'next/link'
6
+ import { Input } from '@open-mercato/ui/primitives/input'
7
+ import {
8
+ Select,
9
+ SelectContent,
10
+ SelectItem,
11
+ SelectTrigger,
12
+ SelectValue,
13
+ } from '@open-mercato/ui/primitives/select'
6
14
 
7
15
  const METHOD_STYLES: Record<string, string> = {
8
16
  GET: 'bg-emerald-100 text-emerald-800 border border-emerald-200',
@@ -503,12 +511,12 @@ export default function ApiDocsExplorer(props: ApiDocsExplorerProps) {
503
511
  </div>
504
512
  <div className="flex flex-col gap-3 lg:flex-row lg:items-center lg:justify-between">
505
513
  <div className="flex flex-1 items-center gap-3">
506
- <input
514
+ <Input
507
515
  type="search"
508
516
  value={searchTerm}
509
517
  onChange={(event) => setSearchTerm(event.target.value)}
510
518
  placeholder="Search endpoints by path or summary"
511
- className="flex-1 rounded-md border border-border bg-background px-3 py-2 text-sm focus-visible:border-ring focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring/20"
519
+ className="flex-1"
512
520
  />
513
521
  </div>
514
522
  <div className="flex flex-wrap gap-2 text-xs">
@@ -1310,17 +1318,18 @@ function TesterPanel(props: TesterPanelProps) {
1310
1318
 
1311
1319
  <label className="space-y-2 text-sm">
1312
1320
  <span className="font-medium text-foreground">Base URL</span>
1313
- <select
1314
- value={baseUrl}
1315
- onChange={(event) => setBaseUrl(event.target.value)}
1316
- className="w-full rounded-md border border-border bg-background px-3 py-2 text-sm focus-visible:border-ring focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring/20"
1317
- >
1318
- {mergedBaseUrls.map((server) => (
1319
- <option key={server.url} value={server.url}>
1320
- {server.url} {server.description ? `— ${server.description}` : ''}
1321
- </option>
1322
- ))}
1323
- </select>
1321
+ <Select value={baseUrl} onValueChange={(value) => setBaseUrl(value)}>
1322
+ <SelectTrigger>
1323
+ <SelectValue />
1324
+ </SelectTrigger>
1325
+ <SelectContent>
1326
+ {mergedBaseUrls.map((server) => (
1327
+ <SelectItem key={server.url} value={server.url}>
1328
+ {server.url} {server.description ? `— ${server.description}` : ''}
1329
+ </SelectItem>
1330
+ ))}
1331
+ </SelectContent>
1332
+ </Select>
1324
1333
  {!baseUrl.trim() && requestPreview?.usesPlaceholderBase ? (
1325
1334
  <p className="text-xs text-muted-foreground">
1326
1335
  Examples default to {PLACEHOLDER_BASE_URL}. Update the base URL to match your environment.
@@ -1333,12 +1342,11 @@ function TesterPanel(props: TesterPanelProps) {
1333
1342
 
1334
1343
  <label className="space-y-2 text-sm">
1335
1344
  <span className="font-medium text-foreground">API key</span>
1336
- <input
1345
+ <Input
1337
1346
  type="text"
1338
1347
  value={apiKey}
1339
1348
  onChange={(event) => setApiKey(event.target.value)}
1340
1349
  placeholder="Paste your API key secret (omk_…)"
1341
- className="w-full rounded-md border border-border bg-background px-3 py-2 text-sm focus-visible:border-ring focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring/20"
1342
1350
  />
1343
1351
  </label>
1344
1352
 
@@ -1352,7 +1360,7 @@ function TesterPanel(props: TesterPanelProps) {
1352
1360
  <span>{parameter.name}</span>
1353
1361
  {parameter.required ? <span className="text-amber-600">required</span> : null}
1354
1362
  </div>
1355
- <input
1363
+ <Input
1356
1364
  type="text"
1357
1365
  value={pathValues[parameter.name] ?? ''}
1358
1366
  onChange={(event) =>
@@ -1362,7 +1370,6 @@ function TesterPanel(props: TesterPanelProps) {
1362
1370
  }))
1363
1371
  }
1364
1372
  placeholder={parameter.description ?? ''}
1365
- className="w-full rounded-md border border-border bg-background px-3 py-2 text-sm focus-visible:border-ring focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring/20"
1366
1373
  />
1367
1374
  </label>
1368
1375
  ))}
@@ -1380,7 +1387,7 @@ function TesterPanel(props: TesterPanelProps) {
1380
1387
  <span>{parameter.name}</span>
1381
1388
  {parameter.required ? <span className="text-amber-600">required</span> : null}
1382
1389
  </div>
1383
- <input
1390
+ <Input
1384
1391
  type="text"
1385
1392
  value={queryValues[parameter.name] ?? ''}
1386
1393
  onChange={(event) =>
@@ -1390,7 +1397,6 @@ function TesterPanel(props: TesterPanelProps) {
1390
1397
  }))
1391
1398
  }
1392
1399
  placeholder={parameter.description ?? ''}
1393
- className="w-full rounded-md border border-border bg-background px-3 py-2 text-sm focus-visible:border-ring focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring/20"
1394
1400
  />
1395
1401
  </label>
1396
1402
  ))}
@@ -7,6 +7,13 @@ import { RowActions } from '@open-mercato/ui/backend/RowActions'
7
7
  import { Button } from '@open-mercato/ui/primitives/button'
8
8
  import { Input } from '@open-mercato/ui/primitives/input'
9
9
  import { Label } from '@open-mercato/ui/primitives/label'
10
+ import {
11
+ Select,
12
+ SelectContent,
13
+ SelectItem,
14
+ SelectTrigger,
15
+ SelectValue,
16
+ } from '@open-mercato/ui/primitives/select'
10
17
  import {
11
18
  Dialog,
12
19
  DialogContent,
@@ -400,18 +407,21 @@ export function AttachmentPartitionSettings() {
400
407
  <Label htmlFor="partition-ocr-model">
401
408
  {t('attachments.partitions.form.ocrModelLabel', 'OCR Model')}
402
409
  </Label>
403
- <select
404
- id="partition-ocr-model"
405
- className="w-full rounded-md border border-input bg-background px-3 py-2 text-sm"
406
- value={form.ocrModel}
407
- onChange={(event) => setForm((prev) => ({ ...prev, ocrModel: event.target.value }))}
410
+ <Select
411
+ value={form.ocrModel || undefined}
412
+ onValueChange={(value) => setForm((prev) => ({ ...prev, ocrModel: value ?? '' }))}
408
413
  >
409
- {OCR_MODEL_OPTIONS.map((option) => (
410
- <option key={option.value} value={option.value}>
411
- {t(`attachments.partitions.form.ocrModelOptions.${option.value || 'default'}`, option.label)}
412
- </option>
413
- ))}
414
- </select>
414
+ <SelectTrigger id="partition-ocr-model">
415
+ <SelectValue />
416
+ </SelectTrigger>
417
+ <SelectContent>
418
+ {OCR_MODEL_OPTIONS.map((option) => (
419
+ <SelectItem key={option.value} value={option.value}>
420
+ {t(`attachments.partitions.form.ocrModelOptions.${option.value || 'default'}`, option.label)}
421
+ </SelectItem>
422
+ ))}
423
+ </SelectContent>
424
+ </Select>
415
425
  <p className="text-xs text-muted-foreground">
416
426
  {t(
417
427
  'attachments.partitions.form.ocrModelHelp',
@@ -4,6 +4,7 @@ import { FieldRegistry } from '@open-mercato/ui/backend/fields/registry'
4
4
  import { apiCall } from '@open-mercato/ui/backend/utils/apiCall'
5
5
  import type { CustomFieldDefDto } from '@open-mercato/ui/backend/utils/customFieldDefs'
6
6
  import { Button } from '@open-mercato/ui/primitives/button'
7
+ import { Input } from '@open-mercato/ui/primitives/input'
7
8
  import { useT } from '@open-mercato/shared/lib/i18n/context'
8
9
  import { Upload } from 'lucide-react'
9
10
 
@@ -186,8 +187,7 @@ function AttachmentDefEditor({ def, onChange }: { def: AttachmentFieldDef; onCha
186
187
  <div className="grid grid-cols-1 gap-3 md:grid-cols-2">
187
188
  <div className="space-y-2">
188
189
  <label className="text-xs font-medium">Max file size (MB)</label>
189
- <input
190
- className="w-full rounded border px-2 py-1 text-sm"
190
+ <Input
191
191
  type="number"
192
192
  min={0}
193
193
  placeholder="e.g., 10"
@@ -198,8 +198,7 @@ function AttachmentDefEditor({ def, onChange }: { def: AttachmentFieldDef; onCha
198
198
  </div>
199
199
  <div className="space-y-2">
200
200
  <label className="text-xs font-medium">Accepted extensions</label>
201
- <input
202
- className="w-full rounded border px-2 py-1 text-sm"
201
+ <Input
203
202
  placeholder="e.g., pdf, jpg, png"
204
203
  value={exts}
205
204
  onChange={(e) => setExts(e.target.value)}
@@ -209,8 +208,7 @@ function AttachmentDefEditor({ def, onChange }: { def: AttachmentFieldDef; onCha
209
208
  </div>
210
209
  <div className="space-y-2">
211
210
  <label className="text-xs font-medium">Partition code</label>
212
- <input
213
- className="w-full rounded border px-2 py-1 text-sm"
211
+ <Input
214
212
  placeholder="e.g., productsMedia"
215
213
  value={partition}
216
214
  onChange={(e) => setPartition(e.target.value)}
@@ -10,6 +10,8 @@ import { OrganizationSelect } from '@open-mercato/core/modules/directory/compone
10
10
  import { TenantSelect } from '@open-mercato/core/modules/directory/components/TenantSelect'
11
11
  import { fetchRoleOptions } from '@open-mercato/core/modules/auth/backend/users/roleOptions'
12
12
  import { Spinner } from '@open-mercato/ui/primitives/spinner'
13
+ import { RadioGroup } from '@open-mercato/ui/primitives/radio'
14
+ import { RadioField } from '@open-mercato/ui/primitives/radio-field'
13
15
  import { useT } from '@open-mercato/shared/lib/i18n/context'
14
16
  import { formatPasswordRequirements, getPasswordPolicy } from '@open-mercato/shared/lib/auth/passwordPolicy'
15
17
 
@@ -395,26 +397,20 @@ function DashboardWidgetSelector({
395
397
  )}
396
398
  {!error && (
397
399
  <>
398
- <div className="flex items-center gap-3 rounded-md border bg-muted/30 px-3 py-2">
399
- <label className="flex items-center gap-2 text-sm">
400
- <input
401
- type="radio"
402
- value="inherit"
403
- checked={mode === 'inherit'}
404
- onChange={() => onModeChange('inherit')}
405
- />
406
- {t('auth.users.widgets.mode.inherit', 'Inherit from roles')}
407
- </label>
408
- <label className="flex items-center gap-2 text-sm">
409
- <input
410
- type="radio"
411
- value="override"
412
- checked={mode === 'override'}
413
- onChange={() => onModeChange('override')}
414
- />
415
- {t('auth.users.widgets.mode.override', 'Override for this user')}
416
- </label>
417
- </div>
400
+ <RadioGroup
401
+ className="flex flex-row items-center gap-3 rounded-md border bg-muted/30 px-3 py-2"
402
+ value={mode}
403
+ onValueChange={(next) => onModeChange(next as 'inherit' | 'override')}
404
+ >
405
+ <RadioField
406
+ value="inherit"
407
+ label={t('auth.users.widgets.mode.inherit', 'Inherit from roles')}
408
+ />
409
+ <RadioField
410
+ value="override"
411
+ label={t('auth.users.widgets.mode.override', 'Override for this user')}
412
+ />
413
+ </RadioGroup>
418
414
  {mode === 'override' && (
419
415
  <div className="space-y-2">
420
416
  {catalog.map((widget) => (
@@ -2,6 +2,14 @@
2
2
 
3
3
  import * as React from 'react'
4
4
  import { X, ChevronUp, ChevronDown } from 'lucide-react'
5
+ import { Input } from '@open-mercato/ui/primitives/input'
6
+ import {
7
+ Select,
8
+ SelectContent,
9
+ SelectItem,
10
+ SelectTrigger,
11
+ SelectValue,
12
+ } from '@open-mercato/ui/primitives/select'
5
13
  import type { Action } from './utils/actionValidation'
6
14
  import { getActionTypeOptions, getRequiredConfigFields, getOptionalConfigFields } from './utils/actionValidation'
7
15
  import { useT } from '@open-mercato/shared/lib/i18n/context'
@@ -62,12 +70,12 @@ export function ActionRow({
62
70
  <label className="text-xs font-medium text-foreground col-span-1">
63
71
  {t('business_rules.components.actionRow.config.recipients')} {required && <span className="text-red-500">{t('business_rules.components.actionRow.actionType.required')}</span>}
64
72
  </label>
65
- <input
73
+ <Input
66
74
  type="text"
67
75
  value={value}
68
76
  onChange={(e) => handleConfigChange(field, e.target.value.split(',').map((s) => s.trim()))}
69
77
  placeholder={t('business_rules.components.actionRow.config.recipients.placeholder')}
70
- className="col-span-3 px-2 py-1.5 text-sm border border-border rounded bg-background focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring"
78
+ className="col-span-3"
71
79
  />
72
80
  <div className="col-span-4 col-start-2">
73
81
  <p className="text-xs text-muted-foreground">{t('business_rules.components.actionRow.config.recipients.help')}</p>
@@ -80,16 +88,20 @@ export function ActionRow({
80
88
  return (
81
89
  <div key={field} className="grid grid-cols-4 gap-2 items-center">
82
90
  <label className="text-xs font-medium text-foreground col-span-1">{t('business_rules.components.actionRow.config.level')}</label>
83
- <select
91
+ <Select
84
92
  value={value || 'info'}
85
- onChange={(e) => handleConfigChange(field, e.target.value)}
86
- className="col-span-3 px-2 py-1.5 text-sm border border-border rounded bg-background focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring"
93
+ onValueChange={(next) => handleConfigChange(field, next)}
87
94
  >
88
- <option value="info">{t('business_rules.components.actionRow.config.level.info')}</option>
89
- <option value="warn">{t('business_rules.components.actionRow.config.level.warn')}</option>
90
- <option value="error">{t('business_rules.components.actionRow.config.level.error')}</option>
91
- <option value="debug">{t('business_rules.components.actionRow.config.level.debug')}</option>
92
- </select>
95
+ <SelectTrigger size="sm" className="col-span-3">
96
+ <SelectValue />
97
+ </SelectTrigger>
98
+ <SelectContent>
99
+ <SelectItem value="info">{t('business_rules.components.actionRow.config.level.info')}</SelectItem>
100
+ <SelectItem value="warn">{t('business_rules.components.actionRow.config.level.warn')}</SelectItem>
101
+ <SelectItem value="error">{t('business_rules.components.actionRow.config.level.error')}</SelectItem>
102
+ <SelectItem value="debug">{t('business_rules.components.actionRow.config.level.debug')}</SelectItem>
103
+ </SelectContent>
104
+ </Select>
93
105
  </div>
94
106
  )
95
107
  }
@@ -98,17 +110,21 @@ export function ActionRow({
98
110
  return (
99
111
  <div key={field} className="grid grid-cols-4 gap-2 items-center">
100
112
  <label className="text-xs font-medium text-foreground col-span-1">{t('business_rules.components.actionRow.config.method')}</label>
101
- <select
113
+ <Select
102
114
  value={value || 'POST'}
103
- onChange={(e) => handleConfigChange(field, e.target.value)}
104
- className="col-span-3 px-2 py-1.5 text-sm border border-border rounded bg-background focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring"
115
+ onValueChange={(next) => handleConfigChange(field, next)}
105
116
  >
106
- <option value="GET">GET</option>
107
- <option value="POST">POST</option>
108
- <option value="PUT">PUT</option>
109
- <option value="PATCH">PATCH</option>
110
- <option value="DELETE">DELETE</option>
111
- </select>
117
+ <SelectTrigger size="sm" className="col-span-3">
118
+ <SelectValue />
119
+ </SelectTrigger>
120
+ <SelectContent>
121
+ <SelectItem value="GET">GET</SelectItem>
122
+ <SelectItem value="POST">POST</SelectItem>
123
+ <SelectItem value="PUT">PUT</SelectItem>
124
+ <SelectItem value="PATCH">PATCH</SelectItem>
125
+ <SelectItem value="DELETE">DELETE</SelectItem>
126
+ </SelectContent>
127
+ </Select>
112
128
  </div>
113
129
  )
114
130
  }
@@ -139,12 +155,12 @@ export function ActionRow({
139
155
  <label className="text-xs font-medium text-foreground col-span-1">
140
156
  {field} {required && <span className="text-red-500">{t('business_rules.components.actionRow.actionType.required')}</span>}
141
157
  </label>
142
- <input
158
+ <Input
143
159
  type="text"
144
160
  value={value}
145
161
  onChange={(e) => handleConfigChange(field, e.target.value)}
146
162
  placeholder={t('business_rules.components.actionRow.config.field.placeholder', { field })}
147
- className="col-span-3 px-2 py-1.5 text-sm border border-border rounded bg-background focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring"
163
+ className="col-span-3"
148
164
  />
149
165
  </div>
150
166
  )
@@ -158,18 +174,21 @@ export function ActionRow({
158
174
  <label className="text-xs font-medium text-foreground col-span-1">
159
175
  {t('business_rules.components.actionRow.actionType')} <span className="text-red-500">{t('business_rules.components.actionRow.actionType.required')}</span>
160
176
  </label>
161
- <select
162
- value={action.type || ''}
163
- onChange={handleTypeChange}
164
- className="col-span-3 px-2 py-1.5 text-sm border border-border rounded bg-background focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring font-medium"
177
+ <Select
178
+ value={action.type || undefined}
179
+ onValueChange={(value) => handleTypeChange({ target: { value } } as React.ChangeEvent<HTMLSelectElement>)}
165
180
  >
166
- <option value="">{t('business_rules.components.actionRow.actionType.placeholder')}</option>
167
- {actionTypes.map((type) => (
168
- <option key={type.value} value={type.value}>
169
- {type.label}
170
- </option>
171
- ))}
172
- </select>
181
+ <SelectTrigger size="sm" className="col-span-3 font-medium">
182
+ <SelectValue placeholder={t('business_rules.components.actionRow.actionType.placeholder')} />
183
+ </SelectTrigger>
184
+ <SelectContent>
185
+ {actionTypes.map((type) => (
186
+ <SelectItem key={type.value} value={type.value}>
187
+ {type.label}
188
+ </SelectItem>
189
+ ))}
190
+ </SelectContent>
191
+ </Select>
173
192
  </div>
174
193
 
175
194
  {/* Config Fields */}
@@ -3,6 +3,13 @@
3
3
  import * as React from 'react'
4
4
  import { Plus, X } from 'lucide-react'
5
5
  import { Button } from '@open-mercato/ui/primitives/button'
6
+ import {
7
+ Select,
8
+ SelectContent,
9
+ SelectItem,
10
+ SelectTrigger,
11
+ SelectValue,
12
+ } from '@open-mercato/ui/primitives/select'
6
13
  import { ConditionRow } from './ConditionRow'
7
14
  import type { GroupCondition, ConditionExpression, SimpleCondition } from './utils/conditionValidation'
8
15
  import type { LogicalOperator } from './../data/validators'
@@ -104,17 +111,21 @@ export function ConditionGroup({ group, onChange, onDelete, depth, maxDepth = 5,
104
111
  <span className="text-xs font-medium text-muted-foreground">
105
112
  {t('business_rules.components.conditionGroup.group', { depth: depth + 1 })}
106
113
  </span>
107
- <select
114
+ <Select
108
115
  value={group.operator}
109
- onChange={handleOperatorChange}
110
- className="px-3 py-1.5 text-sm font-semibold border border-border rounded bg-card focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring"
116
+ onValueChange={(value) => handleOperatorChange({ target: { value } } as React.ChangeEvent<HTMLSelectElement>)}
111
117
  >
112
- {logicalOperators.map((op) => (
113
- <option key={op.value} value={op.value}>
114
- {op.label}
115
- </option>
116
- ))}
117
- </select>
118
+ <SelectTrigger size="sm" className="w-auto min-w-[6rem] font-semibold">
119
+ <SelectValue />
120
+ </SelectTrigger>
121
+ <SelectContent>
122
+ {logicalOperators.map((op) => (
123
+ <SelectItem key={op.value} value={op.value}>
124
+ {op.label}
125
+ </SelectItem>
126
+ ))}
127
+ </SelectContent>
128
+ </Select>
118
129
 
119
130
  <span className="text-xs text-muted-foreground">
120
131
  ({t('business_rules.components.conditionGroup.ruleCount', { count: group.rules.length })})
@@ -2,6 +2,14 @@
2
2
 
3
3
  import * as React from 'react'
4
4
  import { Button } from '@open-mercato/ui/primitives/button'
5
+ import { Input } from '@open-mercato/ui/primitives/input'
6
+ import {
7
+ Select,
8
+ SelectContent,
9
+ SelectItem,
10
+ SelectTrigger,
11
+ SelectValue,
12
+ } from '@open-mercato/ui/primitives/select'
5
13
  import { X } from 'lucide-react'
6
14
  import type { SimpleCondition } from './utils/conditionValidation'
7
15
  import { getComparisonOperators, isValidFieldPath } from './utils/conditionValidation'
@@ -72,14 +80,12 @@ export function ConditionRow({ condition, onChange, onDelete, error }: Condition
72
80
  <label className="block text-xs font-medium text-foreground mb-1">
73
81
  {t('business_rules.components.conditionRow.field')}
74
82
  </label>
75
- <input
83
+ <Input
76
84
  type="text"
77
85
  value={condition.field || ''}
78
86
  onChange={handleFieldChange}
79
87
  placeholder={t('business_rules.components.conditionRow.field.placeholder')}
80
- className={`w-full px-2 py-1.5 text-sm border rounded bg-background focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring ${
81
- fieldError ? 'border-red-500' : 'border-border'
82
- }`}
88
+ aria-invalid={fieldError ? true : undefined}
83
89
  />
84
90
  {fieldError && (
85
91
  <p className="text-xs text-red-600 mt-0.5">
@@ -93,17 +99,21 @@ export function ConditionRow({ condition, onChange, onDelete, error }: Condition
93
99
  <label className="block text-xs font-medium text-foreground mb-1">
94
100
  {t('business_rules.components.conditionRow.operator')}
95
101
  </label>
96
- <select
102
+ <Select
97
103
  value={condition.operator || '='}
98
- onChange={handleOperatorChange}
99
- className="w-full px-2 py-1.5 text-sm border border-border rounded bg-background focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring"
104
+ onValueChange={(value) => handleOperatorChange({ target: { value } } as React.ChangeEvent<HTMLSelectElement>)}
100
105
  >
101
- {operators.map((op) => (
102
- <option key={op.value} value={op.value}>
103
- {op.label}
104
- </option>
105
- ))}
106
- </select>
106
+ <SelectTrigger size="sm">
107
+ <SelectValue />
108
+ </SelectTrigger>
109
+ <SelectContent>
110
+ {operators.map((op) => (
111
+ <SelectItem key={op.value} value={op.value}>
112
+ {op.label}
113
+ </SelectItem>
114
+ ))}
115
+ </SelectContent>
116
+ </Select>
107
117
  </div>
108
118
 
109
119
  {/* Value Input */}
@@ -128,7 +138,7 @@ export function ConditionRow({ condition, onChange, onDelete, error }: Condition
128
138
  }
129
139
  </button>
130
140
  </div>
131
- <input
141
+ <Input
132
142
  type="text"
133
143
  value={
134
144
  useFieldComparison
@@ -144,7 +154,6 @@ export function ConditionRow({ condition, onChange, onDelete, error }: Condition
144
154
  ? t('business_rules.components.conditionRow.field.comparisonPlaceholder')
145
155
  : t('business_rules.components.conditionRow.value.placeholder')
146
156
  }
147
- className="w-full px-2 py-1.5 text-sm border border-border rounded bg-background focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring"
148
157
  />
149
158
  <p className="text-xs text-muted-foreground mt-0.5">
150
159
  {useFieldComparison