@open-mercato/core 0.6.7-develop.6827.1.a575bebce9 → 0.6.7-develop.6834.1.e76f4b8cbc

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 (132) hide show
  1. package/.turbo/turbo-build.log +1 -1
  2. package/dist/modules/attachments/fields/attachment.js +1 -1
  3. package/dist/modules/attachments/fields/attachment.js.map +2 -2
  4. package/dist/modules/auth/components/UserConsentsPanel.js +9 -9
  5. package/dist/modules/auth/components/UserConsentsPanel.js.map +2 -2
  6. package/dist/modules/auth/frontend/reset.js +2 -2
  7. package/dist/modules/auth/frontend/reset.js.map +2 -2
  8. package/dist/modules/business_rules/components/ActionRow.js +1 -1
  9. package/dist/modules/business_rules/components/ActionRow.js.map +1 -1
  10. package/dist/modules/business_rules/components/ConditionRow.js +8 -4
  11. package/dist/modules/business_rules/components/ConditionRow.js.map +2 -2
  12. package/dist/modules/catalog/backend/catalog/products/[id]/page.js +4 -4
  13. package/dist/modules/catalog/backend/catalog/products/[id]/page.js.map +2 -2
  14. package/dist/modules/catalog/backend/catalog/products/create/page.js +5 -5
  15. package/dist/modules/catalog/backend/catalog/products/create/page.js.map +2 -2
  16. package/dist/modules/catalog/components/PriceKindSettings.js +3 -3
  17. package/dist/modules/catalog/components/PriceKindSettings.js.map +2 -2
  18. package/dist/modules/catalog/components/products/ProductCategorizeSection.js +3 -3
  19. package/dist/modules/catalog/components/products/ProductCategorizeSection.js.map +2 -2
  20. package/dist/modules/catalog/components/products/ProductMediaManager.js +1 -1
  21. package/dist/modules/catalog/components/products/ProductMediaManager.js.map +2 -2
  22. package/dist/modules/catalog/components/products/VariantBuilder.js +5 -5
  23. package/dist/modules/catalog/components/products/VariantBuilder.js.map +2 -2
  24. package/dist/modules/communication_channels/backend/profile/communication-channels/page.js +1 -1
  25. package/dist/modules/communication_channels/backend/profile/communication-channels/page.js.map +2 -2
  26. package/dist/modules/customers/components/detail/ConfirmDealLostDialog.js +1 -1
  27. package/dist/modules/customers/components/detail/ConfirmDealLostDialog.js.map +1 -1
  28. package/dist/modules/dashboards/api/widgets/data/schema.js +26 -17
  29. package/dist/modules/dashboards/api/widgets/data/schema.js.map +2 -2
  30. package/dist/modules/design_system/gallery/entries/detail.js +8 -8
  31. package/dist/modules/design_system/gallery/entries/detail.js.map +1 -1
  32. package/dist/modules/design_system/gallery/entries/overlays.js +2 -2
  33. package/dist/modules/design_system/gallery/entries/overlays.js.map +2 -2
  34. package/dist/modules/design_system/gallery/entries/scaffolding.js +8 -8
  35. package/dist/modules/design_system/gallery/entries/scaffolding.js.map +1 -1
  36. package/dist/modules/dictionaries/components/DictionaryEntrySelect.js +1 -1
  37. package/dist/modules/dictionaries/components/DictionaryEntrySelect.js.map +2 -2
  38. package/dist/modules/inbox_ops/backend/inbox-ops/log/page.js +6 -6
  39. package/dist/modules/inbox_ops/backend/inbox-ops/log/page.js.map +2 -2
  40. package/dist/modules/inbox_ops/components/proposals/EditActionDialog.js +3 -3
  41. package/dist/modules/inbox_ops/components/proposals/EditActionDialog.js.map +2 -2
  42. package/dist/modules/messages/components/message-detail/panels/dialogs.js +1 -1
  43. package/dist/modules/messages/components/message-detail/panels/dialogs.js.map +1 -1
  44. package/dist/modules/planner/components/AvailabilityRulesEditor.js +4 -4
  45. package/dist/modules/planner/components/AvailabilityRulesEditor.js.map +2 -2
  46. package/dist/modules/shipping_carriers/lib/shipment-wizard/components/PackageEditor.js +1 -1
  47. package/dist/modules/shipping_carriers/lib/shipment-wizard/components/PackageEditor.js.map +1 -1
  48. package/dist/modules/wms/components/backend/ReleaseReservationDialog.js +1 -1
  49. package/dist/modules/wms/components/backend/ReleaseReservationDialog.js.map +1 -1
  50. package/dist/modules/workflows/backend/definitions/page.js +1 -1
  51. package/dist/modules/workflows/backend/definitions/page.js.map +2 -2
  52. package/dist/modules/workflows/backend/definitions/visual-editor/page.js +1 -1
  53. package/dist/modules/workflows/backend/definitions/visual-editor/page.js.map +2 -2
  54. package/dist/modules/workflows/backend/instances/page.js +8 -8
  55. package/dist/modules/workflows/backend/instances/page.js.map +2 -2
  56. package/dist/modules/workflows/backend/tasks/page.js +6 -6
  57. package/dist/modules/workflows/backend/tasks/page.js.map +2 -2
  58. package/dist/modules/workflows/components/ActivitiesEditor.js +2 -2
  59. package/dist/modules/workflows/components/ActivitiesEditor.js.map +2 -2
  60. package/dist/modules/workflows/components/BusinessRulesSelector.js +1 -1
  61. package/dist/modules/workflows/components/BusinessRulesSelector.js.map +2 -2
  62. package/dist/modules/workflows/components/DefinitionTriggersEditor.js +2 -2
  63. package/dist/modules/workflows/components/DefinitionTriggersEditor.js.map +2 -2
  64. package/dist/modules/workflows/components/EdgeEditDialogCrudForm.js +1 -2
  65. package/dist/modules/workflows/components/EdgeEditDialogCrudForm.js.map +2 -2
  66. package/dist/modules/workflows/components/NodeEditDialogCrudForm.js +1 -2
  67. package/dist/modules/workflows/components/NodeEditDialogCrudForm.js.map +2 -2
  68. package/dist/modules/workflows/components/StepsEditor.js +2 -2
  69. package/dist/modules/workflows/components/StepsEditor.js.map +2 -2
  70. package/dist/modules/workflows/components/TransitionsEditor.js +3 -3
  71. package/dist/modules/workflows/components/TransitionsEditor.js.map +2 -2
  72. package/dist/modules/workflows/components/WorkflowLegend.js +1 -1
  73. package/dist/modules/workflows/components/WorkflowLegend.js.map +2 -2
  74. package/dist/modules/workflows/components/WorkflowSelector.js +1 -1
  75. package/dist/modules/workflows/components/WorkflowSelector.js.map +2 -2
  76. package/dist/modules/workflows/components/fields/BusinessRuleConditionsEditor.js +1 -1
  77. package/dist/modules/workflows/components/fields/BusinessRuleConditionsEditor.js.map +2 -2
  78. package/dist/modules/workflows/components/fields/FormFieldArrayEditor.js +1 -1
  79. package/dist/modules/workflows/components/fields/FormFieldArrayEditor.js.map +2 -2
  80. package/dist/modules/workflows/components/fields/MappingArrayEditor.js +1 -1
  81. package/dist/modules/workflows/components/fields/MappingArrayEditor.js.map +2 -2
  82. package/dist/modules/workflows/components/fields/StartPreConditionsEditor.js +1 -1
  83. package/dist/modules/workflows/components/fields/StartPreConditionsEditor.js.map +2 -2
  84. package/dist/modules/workflows/components/fields/WorkflowSelectorField.js +4 -4
  85. package/dist/modules/workflows/components/fields/WorkflowSelectorField.js.map +2 -2
  86. package/package.json +7 -7
  87. package/src/modules/attachments/fields/attachment.tsx +1 -1
  88. package/src/modules/auth/components/UserConsentsPanel.tsx +9 -9
  89. package/src/modules/auth/frontend/reset.tsx +2 -2
  90. package/src/modules/business_rules/components/ActionRow.tsx +1 -1
  91. package/src/modules/business_rules/components/ConditionRow.tsx +9 -6
  92. package/src/modules/catalog/backend/catalog/products/[id]/page.tsx +4 -4
  93. package/src/modules/catalog/backend/catalog/products/create/page.tsx +5 -5
  94. package/src/modules/catalog/components/PriceKindSettings.tsx +3 -3
  95. package/src/modules/catalog/components/products/ProductCategorizeSection.tsx +3 -3
  96. package/src/modules/catalog/components/products/ProductMediaManager.tsx +1 -1
  97. package/src/modules/catalog/components/products/VariantBuilder.tsx +5 -5
  98. package/src/modules/communication_channels/backend/profile/communication-channels/page.tsx +1 -1
  99. package/src/modules/customers/components/detail/ConfirmDealLostDialog.tsx +1 -1
  100. package/src/modules/dashboards/api/widgets/data/schema.ts +48 -19
  101. package/src/modules/design_system/gallery/entries/detail.tsx +8 -8
  102. package/src/modules/design_system/gallery/entries/overlays.tsx +2 -2
  103. package/src/modules/design_system/gallery/entries/scaffolding.tsx +8 -8
  104. package/src/modules/design_system/i18n/de.json +12 -0
  105. package/src/modules/design_system/i18n/en.json +12 -0
  106. package/src/modules/design_system/i18n/es.json +12 -0
  107. package/src/modules/design_system/i18n/pl.json +12 -0
  108. package/src/modules/dictionaries/components/DictionaryEntrySelect.tsx +1 -1
  109. package/src/modules/inbox_ops/backend/inbox-ops/log/page.tsx +6 -6
  110. package/src/modules/inbox_ops/components/proposals/EditActionDialog.tsx +3 -3
  111. package/src/modules/messages/components/message-detail/panels/dialogs.tsx +1 -1
  112. package/src/modules/planner/components/AvailabilityRulesEditor.tsx +4 -4
  113. package/src/modules/shipping_carriers/lib/shipment-wizard/components/PackageEditor.tsx +1 -1
  114. package/src/modules/wms/components/backend/ReleaseReservationDialog.tsx +1 -1
  115. package/src/modules/workflows/backend/definitions/page.tsx +1 -1
  116. package/src/modules/workflows/backend/definitions/visual-editor/page.tsx +1 -1
  117. package/src/modules/workflows/backend/instances/page.tsx +8 -8
  118. package/src/modules/workflows/backend/tasks/page.tsx +6 -6
  119. package/src/modules/workflows/components/ActivitiesEditor.tsx +2 -2
  120. package/src/modules/workflows/components/BusinessRulesSelector.tsx +1 -1
  121. package/src/modules/workflows/components/DefinitionTriggersEditor.tsx +2 -2
  122. package/src/modules/workflows/components/EdgeEditDialogCrudForm.tsx +1 -2
  123. package/src/modules/workflows/components/NodeEditDialogCrudForm.tsx +1 -2
  124. package/src/modules/workflows/components/StepsEditor.tsx +2 -2
  125. package/src/modules/workflows/components/TransitionsEditor.tsx +3 -3
  126. package/src/modules/workflows/components/WorkflowLegend.tsx +1 -1
  127. package/src/modules/workflows/components/WorkflowSelector.tsx +1 -1
  128. package/src/modules/workflows/components/fields/BusinessRuleConditionsEditor.tsx +1 -1
  129. package/src/modules/workflows/components/fields/FormFieldArrayEditor.tsx +1 -1
  130. package/src/modules/workflows/components/fields/MappingArrayEditor.tsx +1 -1
  131. package/src/modules/workflows/components/fields/StartPreConditionsEditor.tsx +1 -1
  132. package/src/modules/workflows/components/fields/WorkflowSelectorField.tsx +4 -4
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../../src/modules/workflows/components/fields/WorkflowSelectorField.tsx"],
4
- "sourcesContent": ["'use client'\n\nimport { useState, useEffect } from 'react'\nimport { useT } from '@open-mercato/shared/lib/i18n/context'\nimport { useConfirmDialog } from '@open-mercato/ui/backend/confirm-dialog'\nimport { Button } from '@open-mercato/ui/primitives/button'\nimport { Badge } from '@open-mercato/ui/primitives/badge'\nimport { Label } from '@open-mercato/ui/primitives/label'\nimport { Search, X, Loader2, AlertCircle, Workflow } from 'lucide-react'\nimport type { CrudCustomFieldRenderProps } from '@open-mercato/ui/backend/CrudForm'\nimport { WorkflowSelector, type WorkflowDefinition } from '../WorkflowSelector'\nimport { apiFetch } from '@open-mercato/ui/backend/utils/api'\nimport { createLogger } from '@open-mercato/shared/lib/logger'\n\nconst logger = createLogger('workflows')\n\ninterface WorkflowSelectorFieldProps extends CrudCustomFieldRenderProps {\n value: string\n label?: string\n description?: string\n}\n\ninterface WorkflowDetails {\n workflowId: string\n workflowName?: string\n version?: number\n enabled?: boolean\n description?: string | null\n loading?: boolean\n error?: boolean\n}\n\n/**\n * WorkflowSelectorField - Custom field component for selecting a sub-workflow\n *\n * Integrates with WorkflowSelector modal to pick a workflow.\n * Fetches and displays workflow details for the selected workflow ID.\n * Allows clearing the selection.\n *\n * Used by NodeEditDialog (SubWorkflow type only)\n */\nexport function WorkflowSelectorField({\n id,\n value = '',\n error,\n setValue,\n disabled,\n label: labelProp,\n description: descriptionProp,\n}: WorkflowSelectorFieldProps) {\n const t = useT()\n const { confirm, ConfirmDialogElement } = useConfirmDialog()\n const label = labelProp ?? t('workflows.fieldEditors.workflowSelector.label')\n const description = descriptionProp ?? t('workflows.fieldEditors.workflowSelector.description')\n const [isModalOpen, setIsModalOpen] = useState(false)\n const [workflowDetails, setWorkflowDetails] = useState<WorkflowDetails | null>(null)\n\n const workflowId = value || ''\n\n // Fetch workflow details when workflowId changes\n useEffect(() => {\n if (workflowId) {\n setWorkflowDetails({ workflowId, loading: true })\n fetchWorkflowDetails(workflowId)\n } else {\n setWorkflowDetails(null)\n }\n }, [workflowId])\n\n const fetchWorkflowDetails = async (wfId: string) => {\n try {\n const params = new URLSearchParams({ workflowId: wfId, limit: '1' })\n const response = await apiFetch(`/api/workflows/definitions?${params.toString()}`)\n\n if (response.ok) {\n const result = await response.json()\n const workflow = result.data?.[0] as WorkflowDefinition | undefined\n\n setWorkflowDetails({\n workflowId: wfId,\n workflowName: workflow?.workflowName,\n version: workflow?.version,\n enabled: workflow?.enabled,\n description: workflow?.description,\n loading: false,\n error: !workflow,\n })\n } else {\n setWorkflowDetails({\n workflowId: wfId,\n loading: false,\n error: true,\n })\n }\n } catch (err) {\n logger.error('Failed to fetch workflow details', { workflowId: wfId, err })\n setWorkflowDetails({\n workflowId: wfId,\n loading: false,\n error: true,\n })\n }\n }\n\n const handleSelect = (selectedWorkflowId: string, _workflow: WorkflowDefinition) => {\n setValue(selectedWorkflowId)\n setIsModalOpen(false)\n }\n\n const handleClear = async () => {\n const confirmed = await confirm({\n title: t('workflows.common.clear'),\n text: t('workflows.fieldEditors.workflowSelector.confirmClear'),\n variant: 'default',\n })\n if (!confirmed) return\n\n setValue('')\n setWorkflowDetails(null)\n }\n\n return (\n <div className=\"space-y-2\">\n <div>\n <Label htmlFor={id} className=\"text-sm font-medium\">\n {label}\n </Label>\n <p className=\"text-xs text-muted-foreground mt-0.5\">\n {description}\n </p>\n {error && <p className=\"text-xs text-red-600 mt-1\">{error}</p>}\n </div>\n\n {!workflowId ? (\n /* No Workflow Selected */\n <div className=\"border-2 border-dashed border-gray-300 rounded-lg p-6 text-center\">\n <Workflow className=\"size-8 text-muted-foreground mx-auto mb-2\" />\n <p className=\"text-sm text-muted-foreground mb-3\">{t('workflows.fieldEditors.workflowSelector.noWorkflowSelected')}</p>\n <Button\n type=\"button\"\n size=\"sm\"\n onClick={() => setIsModalOpen(true)}\n disabled={disabled}\n >\n <Search className=\"size-3 mr-1\" />\n {t('workflows.fieldEditors.workflowSelector.browseWorkflows')}\n </Button>\n </div>\n ) : (\n /* Workflow Selected */\n <div className=\"border border-gray-200 rounded-lg bg-white p-4\">\n <div className=\"flex items-start justify-between\">\n <div className=\"flex-1 min-w-0 space-y-2\">\n {workflowDetails?.loading ? (\n <div className=\"flex items-center gap-2\">\n <Loader2 className=\"size-4 animate-spin text-muted-foreground\" />\n <span className=\"text-sm text-muted-foreground\">{t('workflows.common.loadingDetails')}</span>\n </div>\n ) : workflowDetails?.error ? (\n <>\n <div className=\"flex items-center gap-2\">\n <AlertCircle className=\"size-4 text-yellow-600\" />\n <span className=\"text-sm font-semibold text-gray-900\">{workflowId}</span>\n </div>\n <p className=\"text-xs text-yellow-600\">{t('workflows.common.workflowNotFoundOrUnavailable')}</p>\n </>\n ) : (\n <>\n <div>\n <div className=\"flex items-center gap-2\">\n <span className=\"text-sm font-semibold text-gray-900\">\n {workflowDetails?.workflowName || workflowId}\n </span>\n {workflowDetails?.version !== undefined && (\n <Badge variant=\"secondary\" className=\"text-xs\">\n v{workflowDetails.version}\n </Badge>\n )}\n {workflowDetails?.enabled !== undefined && (\n workflowDetails.enabled ? (\n <Badge variant=\"default\" className=\"bg-emerald-500 text-xs\">\n {t('common.enabled')}\n </Badge>\n ) : (\n <Badge variant=\"secondary\" className=\"text-xs\">\n {t('common.disabled')}\n </Badge>\n )\n )}\n </div>\n <p className=\"text-xs text-muted-foreground font-mono mt-0.5\">{workflowId}</p>\n </div>\n {workflowDetails?.description && (\n <p className=\"text-xs text-muted-foreground\">{workflowDetails.description}</p>\n )}\n </>\n )}\n </div>\n\n {/* Actions */}\n <div className=\"flex items-center gap-2 ml-4 flex-shrink-0\">\n <Button\n type=\"button\"\n variant=\"outline\"\n size=\"sm\"\n onClick={() => setIsModalOpen(true)}\n disabled={disabled}\n >\n <Search className=\"size-3 mr-1\" />\n {t('workflows.common.change')}\n </Button>\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"sm\"\n onClick={handleClear}\n disabled={disabled}\n >\n <X className=\"size-4\" />\n </Button>\n </div>\n </div>\n </div>\n )}\n\n {/* Workflow Selector Modal */}\n <WorkflowSelector\n isOpen={isModalOpen}\n onClose={() => setIsModalOpen(false)}\n onSelect={handleSelect}\n excludeWorkflowIds={workflowId ? [workflowId] : []}\n title={t('workflows.fieldEditors.workflowSelector.selectSubWorkflow')}\n description={t('workflows.fieldEditors.workflowSelector.selectSubWorkflowDescription')}\n onlyEnabled={true}\n />\n {ConfirmDialogElement}\n </div>\n )\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["'use client'\n\nimport { useState, useEffect } from 'react'\nimport { useT } from '@open-mercato/shared/lib/i18n/context'\nimport { useConfirmDialog } from '@open-mercato/ui/backend/confirm-dialog'\nimport { Button } from '@open-mercato/ui/primitives/button'\nimport { Badge } from '@open-mercato/ui/primitives/badge'\nimport { Label } from '@open-mercato/ui/primitives/label'\nimport { Search, X, Loader2, AlertCircle, Workflow } from 'lucide-react'\nimport type { CrudCustomFieldRenderProps } from '@open-mercato/ui/backend/CrudForm'\nimport { WorkflowSelector, type WorkflowDefinition } from '../WorkflowSelector'\nimport { apiFetch } from '@open-mercato/ui/backend/utils/api'\nimport { createLogger } from '@open-mercato/shared/lib/logger'\n\nconst logger = createLogger('workflows')\n\ninterface WorkflowSelectorFieldProps extends CrudCustomFieldRenderProps {\n value: string\n label?: string\n description?: string\n}\n\ninterface WorkflowDetails {\n workflowId: string\n workflowName?: string\n version?: number\n enabled?: boolean\n description?: string | null\n loading?: boolean\n error?: boolean\n}\n\n/**\n * WorkflowSelectorField - Custom field component for selecting a sub-workflow\n *\n * Integrates with WorkflowSelector modal to pick a workflow.\n * Fetches and displays workflow details for the selected workflow ID.\n * Allows clearing the selection.\n *\n * Used by NodeEditDialog (SubWorkflow type only)\n */\nexport function WorkflowSelectorField({\n id,\n value = '',\n error,\n setValue,\n disabled,\n label: labelProp,\n description: descriptionProp,\n}: WorkflowSelectorFieldProps) {\n const t = useT()\n const { confirm, ConfirmDialogElement } = useConfirmDialog()\n const label = labelProp ?? t('workflows.fieldEditors.workflowSelector.label')\n const description = descriptionProp ?? t('workflows.fieldEditors.workflowSelector.description')\n const [isModalOpen, setIsModalOpen] = useState(false)\n const [workflowDetails, setWorkflowDetails] = useState<WorkflowDetails | null>(null)\n\n const workflowId = value || ''\n\n // Fetch workflow details when workflowId changes\n useEffect(() => {\n if (workflowId) {\n setWorkflowDetails({ workflowId, loading: true })\n fetchWorkflowDetails(workflowId)\n } else {\n setWorkflowDetails(null)\n }\n }, [workflowId])\n\n const fetchWorkflowDetails = async (wfId: string) => {\n try {\n const params = new URLSearchParams({ workflowId: wfId, limit: '1' })\n const response = await apiFetch(`/api/workflows/definitions?${params.toString()}`)\n\n if (response.ok) {\n const result = await response.json()\n const workflow = result.data?.[0] as WorkflowDefinition | undefined\n\n setWorkflowDetails({\n workflowId: wfId,\n workflowName: workflow?.workflowName,\n version: workflow?.version,\n enabled: workflow?.enabled,\n description: workflow?.description,\n loading: false,\n error: !workflow,\n })\n } else {\n setWorkflowDetails({\n workflowId: wfId,\n loading: false,\n error: true,\n })\n }\n } catch (err) {\n logger.error('Failed to fetch workflow details', { workflowId: wfId, err })\n setWorkflowDetails({\n workflowId: wfId,\n loading: false,\n error: true,\n })\n }\n }\n\n const handleSelect = (selectedWorkflowId: string, _workflow: WorkflowDefinition) => {\n setValue(selectedWorkflowId)\n setIsModalOpen(false)\n }\n\n const handleClear = async () => {\n const confirmed = await confirm({\n title: t('workflows.common.clear'),\n text: t('workflows.fieldEditors.workflowSelector.confirmClear'),\n variant: 'default',\n })\n if (!confirmed) return\n\n setValue('')\n setWorkflowDetails(null)\n }\n\n return (\n <div className=\"space-y-2\">\n <div>\n <Label htmlFor={id} className=\"text-sm font-medium\">\n {label}\n </Label>\n <p className=\"text-xs text-muted-foreground mt-0.5\">\n {description}\n </p>\n {error && <p className=\"text-xs text-status-error-text mt-1\">{error}</p>}\n </div>\n\n {!workflowId ? (\n /* No Workflow Selected */\n <div className=\"border-2 border-dashed border-gray-300 rounded-lg p-6 text-center\">\n <Workflow className=\"size-8 text-muted-foreground mx-auto mb-2\" />\n <p className=\"text-sm text-muted-foreground mb-3\">{t('workflows.fieldEditors.workflowSelector.noWorkflowSelected')}</p>\n <Button\n type=\"button\"\n size=\"sm\"\n onClick={() => setIsModalOpen(true)}\n disabled={disabled}\n >\n <Search className=\"size-3 mr-1\" />\n {t('workflows.fieldEditors.workflowSelector.browseWorkflows')}\n </Button>\n </div>\n ) : (\n /* Workflow Selected */\n <div className=\"border border-gray-200 rounded-lg bg-white p-4\">\n <div className=\"flex items-start justify-between\">\n <div className=\"flex-1 min-w-0 space-y-2\">\n {workflowDetails?.loading ? (\n <div className=\"flex items-center gap-2\">\n <Loader2 className=\"size-4 animate-spin text-muted-foreground\" />\n <span className=\"text-sm text-muted-foreground\">{t('workflows.common.loadingDetails')}</span>\n </div>\n ) : workflowDetails?.error ? (\n <>\n <div className=\"flex items-center gap-2\">\n <AlertCircle className=\"size-4 text-status-warning-text\" />\n <span className=\"text-sm font-semibold text-gray-900\">{workflowId}</span>\n </div>\n <p className=\"text-xs text-status-warning-text\">{t('workflows.common.workflowNotFoundOrUnavailable')}</p>\n </>\n ) : (\n <>\n <div>\n <div className=\"flex items-center gap-2\">\n <span className=\"text-sm font-semibold text-gray-900\">\n {workflowDetails?.workflowName || workflowId}\n </span>\n {workflowDetails?.version !== undefined && (\n <Badge variant=\"secondary\" className=\"text-xs\">\n v{workflowDetails.version}\n </Badge>\n )}\n {workflowDetails?.enabled !== undefined && (\n workflowDetails.enabled ? (\n <Badge variant=\"default\" className=\"bg-status-success-solid text-status-success-solid-foreground text-xs\">\n {t('common.enabled')}\n </Badge>\n ) : (\n <Badge variant=\"secondary\" className=\"text-xs\">\n {t('common.disabled')}\n </Badge>\n )\n )}\n </div>\n <p className=\"text-xs text-muted-foreground font-mono mt-0.5\">{workflowId}</p>\n </div>\n {workflowDetails?.description && (\n <p className=\"text-xs text-muted-foreground\">{workflowDetails.description}</p>\n )}\n </>\n )}\n </div>\n\n {/* Actions */}\n <div className=\"flex items-center gap-2 ml-4 flex-shrink-0\">\n <Button\n type=\"button\"\n variant=\"outline\"\n size=\"sm\"\n onClick={() => setIsModalOpen(true)}\n disabled={disabled}\n >\n <Search className=\"size-3 mr-1\" />\n {t('workflows.common.change')}\n </Button>\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"sm\"\n onClick={handleClear}\n disabled={disabled}\n >\n <X className=\"size-4\" />\n </Button>\n </div>\n </div>\n </div>\n )}\n\n {/* Workflow Selector Modal */}\n <WorkflowSelector\n isOpen={isModalOpen}\n onClose={() => setIsModalOpen(false)}\n onSelect={handleSelect}\n excludeWorkflowIds={workflowId ? [workflowId] : []}\n title={t('workflows.fieldEditors.workflowSelector.selectSubWorkflow')}\n description={t('workflows.fieldEditors.workflowSelector.selectSubWorkflowDescription')}\n onlyEnabled={true}\n />\n {ConfirmDialogElement}\n </div>\n )\n}\n"],
5
+ "mappings": ";AA2HM,SAoCU,UAnCR,KADF;AAzHN,SAAS,UAAU,iBAAiB;AACpC,SAAS,YAAY;AACrB,SAAS,wBAAwB;AACjC,SAAS,cAAc;AACvB,SAAS,aAAa;AACtB,SAAS,aAAa;AACtB,SAAS,QAAQ,GAAG,SAAS,aAAa,gBAAgB;AAE1D,SAAS,wBAAiD;AAC1D,SAAS,gBAAgB;AACzB,SAAS,oBAAoB;AAE7B,MAAM,SAAS,aAAa,WAAW;AA2BhC,SAAS,sBAAsB;AAAA,EACpC;AAAA,EACA,QAAQ;AAAA,EACR;AAAA,EACA;AAAA,EACA;AAAA,EACA,OAAO;AAAA,EACP,aAAa;AACf,GAA+B;AAC7B,QAAM,IAAI,KAAK;AACf,QAAM,EAAE,SAAS,qBAAqB,IAAI,iBAAiB;AAC3D,QAAM,QAAQ,aAAa,EAAE,+CAA+C;AAC5E,QAAM,cAAc,mBAAmB,EAAE,qDAAqD;AAC9F,QAAM,CAAC,aAAa,cAAc,IAAI,SAAS,KAAK;AACpD,QAAM,CAAC,iBAAiB,kBAAkB,IAAI,SAAiC,IAAI;AAEnF,QAAM,aAAa,SAAS;AAG5B,YAAU,MAAM;AACd,QAAI,YAAY;AACd,yBAAmB,EAAE,YAAY,SAAS,KAAK,CAAC;AAChD,2BAAqB,UAAU;AAAA,IACjC,OAAO;AACL,yBAAmB,IAAI;AAAA,IACzB;AAAA,EACF,GAAG,CAAC,UAAU,CAAC;AAEf,QAAM,uBAAuB,OAAO,SAAiB;AACnD,QAAI;AACF,YAAM,SAAS,IAAI,gBAAgB,EAAE,YAAY,MAAM,OAAO,IAAI,CAAC;AACnE,YAAM,WAAW,MAAM,SAAS,8BAA8B,OAAO,SAAS,CAAC,EAAE;AAEjF,UAAI,SAAS,IAAI;AACf,cAAM,SAAS,MAAM,SAAS,KAAK;AACnC,cAAM,WAAW,OAAO,OAAO,CAAC;AAEhC,2BAAmB;AAAA,UACjB,YAAY;AAAA,UACZ,cAAc,UAAU;AAAA,UACxB,SAAS,UAAU;AAAA,UACnB,SAAS,UAAU;AAAA,UACnB,aAAa,UAAU;AAAA,UACvB,SAAS;AAAA,UACT,OAAO,CAAC;AAAA,QACV,CAAC;AAAA,MACH,OAAO;AACL,2BAAmB;AAAA,UACjB,YAAY;AAAA,UACZ,SAAS;AAAA,UACT,OAAO;AAAA,QACT,CAAC;AAAA,MACH;AAAA,IACF,SAAS,KAAK;AACZ,aAAO,MAAM,oCAAoC,EAAE,YAAY,MAAM,IAAI,CAAC;AAC1E,yBAAmB;AAAA,QACjB,YAAY;AAAA,QACZ,SAAS;AAAA,QACT,OAAO;AAAA,MACT,CAAC;AAAA,IACH;AAAA,EACF;AAEA,QAAM,eAAe,CAAC,oBAA4B,cAAkC;AAClF,aAAS,kBAAkB;AAC3B,mBAAe,KAAK;AAAA,EACtB;AAEA,QAAM,cAAc,YAAY;AAC9B,UAAM,YAAY,MAAM,QAAQ;AAAA,MAC9B,OAAO,EAAE,wBAAwB;AAAA,MACjC,MAAM,EAAE,sDAAsD;AAAA,MAC9D,SAAS;AAAA,IACX,CAAC;AACD,QAAI,CAAC,UAAW;AAEhB,aAAS,EAAE;AACX,uBAAmB,IAAI;AAAA,EACzB;AAEA,SACE,qBAAC,SAAI,WAAU,aACb;AAAA,yBAAC,SACC;AAAA,0BAAC,SAAM,SAAS,IAAI,WAAU,uBAC3B,iBACH;AAAA,MACA,oBAAC,OAAE,WAAU,wCACV,uBACH;AAAA,MACC,SAAS,oBAAC,OAAE,WAAU,uCAAuC,iBAAM;AAAA,OACtE;AAAA,IAEC,CAAC;AAAA;AAAA,MAEA,qBAAC,SAAI,WAAU,qEACb;AAAA,4BAAC,YAAS,WAAU,6CAA4C;AAAA,QAChE,oBAAC,OAAE,WAAU,sCAAsC,YAAE,4DAA4D,GAAE;AAAA,QACnH;AAAA,UAAC;AAAA;AAAA,YACC,MAAK;AAAA,YACL,MAAK;AAAA,YACL,SAAS,MAAM,eAAe,IAAI;AAAA,YAClC;AAAA,YAEA;AAAA,kCAAC,UAAO,WAAU,eAAc;AAAA,cAC/B,EAAE,yDAAyD;AAAA;AAAA;AAAA,QAC9D;AAAA,SACF;AAAA;AAAA;AAAA,MAGA,oBAAC,SAAI,WAAU,kDACb,+BAAC,SAAI,WAAU,oCACb;AAAA,4BAAC,SAAI,WAAU,4BACZ,2BAAiB,UAChB,qBAAC,SAAI,WAAU,2BACb;AAAA,8BAAC,WAAQ,WAAU,6CAA4C;AAAA,UAC/D,oBAAC,UAAK,WAAU,iCAAiC,YAAE,iCAAiC,GAAE;AAAA,WACxF,IACE,iBAAiB,QACnB,iCACE;AAAA,+BAAC,SAAI,WAAU,2BACb;AAAA,gCAAC,eAAY,WAAU,mCAAkC;AAAA,YACzD,oBAAC,UAAK,WAAU,uCAAuC,sBAAW;AAAA,aACpE;AAAA,UACA,oBAAC,OAAE,WAAU,oCAAoC,YAAE,gDAAgD,GAAE;AAAA,WACvG,IAEA,iCACE;AAAA,+BAAC,SACC;AAAA,iCAAC,SAAI,WAAU,2BACb;AAAA,kCAAC,UAAK,WAAU,uCACb,2BAAiB,gBAAgB,YACpC;AAAA,cACC,iBAAiB,YAAY,UAC5B,qBAAC,SAAM,SAAQ,aAAY,WAAU,WAAU;AAAA;AAAA,gBAC3C,gBAAgB;AAAA,iBACpB;AAAA,cAED,iBAAiB,YAAY,WAC5B,gBAAgB,UACd,oBAAC,SAAM,SAAQ,WAAU,WAAU,wEAChC,YAAE,gBAAgB,GACrB,IAEA,oBAAC,SAAM,SAAQ,aAAY,WAAU,WAClC,YAAE,iBAAiB,GACtB;AAAA,eAGN;AAAA,YACA,oBAAC,OAAE,WAAU,kDAAkD,sBAAW;AAAA,aAC5E;AAAA,UACC,iBAAiB,eAChB,oBAAC,OAAE,WAAU,iCAAiC,0BAAgB,aAAY;AAAA,WAE9E,GAEJ;AAAA,QAGA,qBAAC,SAAI,WAAU,8CACb;AAAA;AAAA,YAAC;AAAA;AAAA,cACC,MAAK;AAAA,cACL,SAAQ;AAAA,cACR,MAAK;AAAA,cACL,SAAS,MAAM,eAAe,IAAI;AAAA,cAClC;AAAA,cAEA;AAAA,oCAAC,UAAO,WAAU,eAAc;AAAA,gBAC/B,EAAE,yBAAyB;AAAA;AAAA;AAAA,UAC9B;AAAA,UACA;AAAA,YAAC;AAAA;AAAA,cACC,MAAK;AAAA,cACL,SAAQ;AAAA,cACR,MAAK;AAAA,cACL,SAAS;AAAA,cACT;AAAA,cAEA,8BAAC,KAAE,WAAU,UAAS;AAAA;AAAA,UACxB;AAAA,WACF;AAAA,SACF,GACF;AAAA;AAAA,IAIF;AAAA,MAAC;AAAA;AAAA,QACC,QAAQ;AAAA,QACR,SAAS,MAAM,eAAe,KAAK;AAAA,QACnC,UAAU;AAAA,QACV,oBAAoB,aAAa,CAAC,UAAU,IAAI,CAAC;AAAA,QACjD,OAAO,EAAE,2DAA2D;AAAA,QACpE,aAAa,EAAE,sEAAsE;AAAA,QACrF,aAAa;AAAA;AAAA,IACf;AAAA,IACC;AAAA,KACH;AAEJ;",
6
6
  "names": []
7
7
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@open-mercato/core",
3
- "version": "0.6.7-develop.6827.1.a575bebce9",
3
+ "version": "0.6.7-develop.6834.1.e76f4b8cbc",
4
4
  "license": "MIT",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -254,16 +254,16 @@
254
254
  "zod": "^4.4.3"
255
255
  },
256
256
  "peerDependencies": {
257
- "@open-mercato/ai-assistant": "0.6.7-develop.6827.1.a575bebce9",
258
- "@open-mercato/shared": "0.6.7-develop.6827.1.a575bebce9",
259
- "@open-mercato/ui": "0.6.7-develop.6827.1.a575bebce9",
257
+ "@open-mercato/ai-assistant": "0.6.7-develop.6834.1.e76f4b8cbc",
258
+ "@open-mercato/shared": "0.6.7-develop.6834.1.e76f4b8cbc",
259
+ "@open-mercato/ui": "0.6.7-develop.6834.1.e76f4b8cbc",
260
260
  "react": "^19.0.0",
261
261
  "react-dom": "^19.0.0"
262
262
  },
263
263
  "devDependencies": {
264
- "@open-mercato/ai-assistant": "0.6.7-develop.6827.1.a575bebce9",
265
- "@open-mercato/shared": "0.6.7-develop.6827.1.a575bebce9",
266
- "@open-mercato/ui": "0.6.7-develop.6827.1.a575bebce9",
264
+ "@open-mercato/ai-assistant": "0.6.7-develop.6834.1.e76f4b8cbc",
265
+ "@open-mercato/shared": "0.6.7-develop.6834.1.e76f4b8cbc",
266
+ "@open-mercato/ui": "0.6.7-develop.6834.1.e76f4b8cbc",
267
267
  "@testing-library/dom": "^10.4.1",
268
268
  "@testing-library/jest-dom": "^6.9.1",
269
269
  "@testing-library/react": "^16.3.1",
@@ -162,7 +162,7 @@ export const AttachmentInput = ({
162
162
  />
163
163
  </div>
164
164
  )}
165
- {error ? <div className="text-xs text-red-600">{error}</div> : null}
165
+ {error ? <div className="text-xs text-status-error-text">{error}</div> : null}
166
166
  <div className="space-y-1">
167
167
  {loading ? <div className="text-xs text-muted-foreground">{t('attachments.library.loading', 'Loading attachments…')}</div> : null}
168
168
  {items.map(it => (
@@ -65,7 +65,7 @@ export function UserConsentsPanel({ userId }: UserConsentsPanelProps) {
65
65
  }
66
66
 
67
67
  if (error) {
68
- return <p className="text-sm text-red-600">{error}</p>
68
+ return <p className="text-sm text-status-error-text">{error}</p>
69
69
  }
70
70
 
71
71
  if (consents.length === 0) {
@@ -86,15 +86,15 @@ export function UserConsentsPanel({ userId }: UserConsentsPanelProps) {
86
86
  <span className="flex items-center gap-1.5">
87
87
  {consent.isGranted ? (
88
88
  <>
89
- <ShieldCheck className="size-4 text-emerald-600" />
90
- <span className="text-emerald-700 font-medium">
89
+ <ShieldCheck className="size-4 text-status-success-icon" />
90
+ <span className="text-status-success-text font-medium">
91
91
  {t('auth.users.consents.granted', 'Granted')}
92
92
  </span>
93
93
  </>
94
94
  ) : (
95
95
  <>
96
- <ShieldX className="size-4 text-red-500" />
97
- <span className="text-red-600 font-medium">
96
+ <ShieldX className="size-4 text-status-error-icon" />
97
+ <span className="text-status-error-text font-medium">
98
98
  {t('auth.users.consents.withdrawn', 'Withdrawn')}
99
99
  </span>
100
100
  </>
@@ -118,13 +118,13 @@ export function UserConsentsPanel({ userId }: UserConsentsPanelProps) {
118
118
  <dd className="flex items-center gap-1">
119
119
  {consent.integrityValid ? (
120
120
  <>
121
- <ShieldCheck className="size-3 text-emerald-600" />
122
- <span className="text-emerald-700">{t('auth.users.consents.integrityValid', 'Valid')}</span>
121
+ <ShieldCheck className="size-3 text-status-success-icon" />
122
+ <span className="text-status-success-text">{t('auth.users.consents.integrityValid', 'Valid')}</span>
123
123
  </>
124
124
  ) : (
125
125
  <>
126
- <ShieldAlert className="size-3 text-amber-500" />
127
- <span className="text-amber-600">{t('auth.users.consents.integrityInvalid', 'Tampered or missing')}</span>
126
+ <ShieldAlert className="size-3 text-status-warning-icon" />
127
+ <span className="text-status-warning-text">{t('auth.users.consents.integrityInvalid', 'Tampered or missing')}</span>
128
128
  </>
129
129
  )}
130
130
  </dd>
@@ -56,11 +56,11 @@ export default function ResetPage() {
56
56
  </div>
57
57
  ) : (
58
58
  <form className="grid gap-3" onSubmit={onSubmit} noValidate>
59
- {error && <div className="text-sm text-red-600">{error}</div>}
59
+ {error && <div className="text-sm text-status-error-text">{error}</div>}
60
60
  <div className="grid gap-1">
61
61
  <Label htmlFor="email">{t('auth.email')}</Label>
62
62
  <EmailInput id="email" name="email" required aria-invalid={!!fieldError} aria-describedby={fieldError ? 'email-error' : undefined} />
63
- {fieldError && <p id="email-error" className="text-sm text-red-600">{fieldError}</p>}
63
+ {fieldError && <p id="email-error" className="text-sm text-status-error-text">{fieldError}</p>}
64
64
  </div>
65
65
  <Button type="submit" className="mt-2 w-full" disabled={submitting}>
66
66
  {submitting ? '...' : t('auth.sendResetLink')}
@@ -371,7 +371,7 @@ export function ActionRow({
371
371
  onClick={() => onDelete(index)}
372
372
  variant="ghost"
373
373
  size="xs"
374
- className="hover:text-status-error-text"
374
+ className="hover:bg-destructive/10 hover:text-destructive"
375
375
  title={t('business_rules.components.actionRow.delete')}
376
376
  aria-label={t('business_rules.components.actionRow.delete')}
377
377
  >
@@ -1,7 +1,7 @@
1
1
  "use client"
2
2
 
3
3
  import * as React from 'react'
4
- import { Button } from '@open-mercato/ui/primitives/button'
4
+ import { IconButton } from '@open-mercato/ui/primitives/icon-button'
5
5
  import { Input } from '@open-mercato/ui/primitives/input'
6
6
  import {
7
7
  Select,
@@ -88,7 +88,7 @@ export function ConditionRow({ condition, onChange, onDelete, error }: Condition
88
88
  aria-invalid={fieldError ? true : undefined}
89
89
  />
90
90
  {fieldError && (
91
- <p className="text-xs text-red-600 mt-0.5">
91
+ <p className="text-xs text-status-error-text mt-0.5">
92
92
  {t('business_rules.components.conditionRow.field.invalidPath')}
93
93
  </p>
94
94
  )}
@@ -166,19 +166,22 @@ export function ConditionRow({ condition, onChange, onDelete, error }: Condition
166
166
  </div>
167
167
 
168
168
  {/* Delete Button */}
169
- <button
169
+ <IconButton
170
170
  type="button"
171
171
  onClick={onDelete}
172
- className="p-1.5 text-muted-foreground hover:text-red-600 hover:bg-red-50 dark:hover:bg-red-900/20 rounded transition-colors"
172
+ variant="ghost"
173
+ size="xs"
174
+ className="hover:bg-destructive/10 hover:text-destructive"
173
175
  title={t('business_rules.components.conditionRow.deleteCondition')}
176
+ aria-label={t('business_rules.components.conditionRow.deleteCondition')}
174
177
  >
175
178
  <X className="w-4 h-4" />
176
- </button>
179
+ </IconButton>
177
180
 
178
181
  {/* Error Display */}
179
182
  {error && (
180
183
  <div className="col-span-full mt-2">
181
- <p className="text-xs text-red-600">{error}</p>
184
+ <p className="text-xs text-status-error-text">{error}</p>
182
185
  </div>
183
186
  )}
184
187
  </div>
@@ -2608,7 +2608,7 @@ function ProductMetaSection({
2608
2608
  )}
2609
2609
  />
2610
2610
  {errors.subtitle ? (
2611
- <p className="text-xs text-red-600">{errors.subtitle}</p>
2611
+ <p className="text-xs text-status-error-text">{errors.subtitle}</p>
2612
2612
  ) : null}
2613
2613
  </div>
2614
2614
 
@@ -2641,7 +2641,7 @@ function ProductMetaSection({
2641
2641
  )}
2642
2642
  </p>
2643
2643
  {errors.handle ? (
2644
- <p className="text-xs text-red-600">{errors.handle}</p>
2644
+ <p className="text-xs text-status-error-text">{errors.handle}</p>
2645
2645
  ) : null}
2646
2646
  </div>
2647
2647
 
@@ -2663,7 +2663,7 @@ function ProductMetaSection({
2663
2663
  )}
2664
2664
  </p>
2665
2665
  {errors.sku ? (
2666
- <p className="text-xs text-red-600">{errors.sku}</p>
2666
+ <p className="text-xs text-status-error-text">{errors.sku}</p>
2667
2667
  ) : null}
2668
2668
  </div>
2669
2669
 
@@ -2700,7 +2700,7 @@ function ProductMetaSection({
2700
2700
  </SelectContent>
2701
2701
  </Select>
2702
2702
  {errors.productType ? (
2703
- <p className="text-xs text-red-600">
2703
+ <p className="text-xs text-status-error-text">
2704
2704
  {errors.productType}
2705
2705
  </p>
2706
2706
  ) : null}
@@ -1942,7 +1942,7 @@ function ProductMetaSection({
1942
1942
  )}
1943
1943
  />
1944
1944
  {errors.subtitle ? (
1945
- <p className="text-xs text-red-600">{errors.subtitle}</p>
1945
+ <p className="text-xs text-status-error-text">{errors.subtitle}</p>
1946
1946
  ) : null}
1947
1947
  </div>
1948
1948
 
@@ -1973,7 +1973,7 @@ function ProductMetaSection({
1973
1973
  )}
1974
1974
  </p>
1975
1975
  {errors.handle ? (
1976
- <p className="text-xs text-red-600">{errors.handle}</p>
1976
+ <p className="text-xs text-status-error-text">{errors.handle}</p>
1977
1977
  ) : null}
1978
1978
  </div>
1979
1979
 
@@ -1995,7 +1995,7 @@ function ProductMetaSection({
1995
1995
  )}
1996
1996
  </p>
1997
1997
  {errors.sku ? (
1998
- <p className="text-xs text-red-600">{errors.sku}</p>
1998
+ <p className="text-xs text-status-error-text">{errors.sku}</p>
1999
1999
  ) : null}
2000
2000
  </div>
2001
2001
 
@@ -2032,7 +2032,7 @@ function ProductMetaSection({
2032
2032
  </SelectContent>
2033
2033
  </Select>
2034
2034
  {errors.productType ? (
2035
- <p className="text-xs text-red-600">
2035
+ <p className="text-xs text-status-error-text">
2036
2036
  {errors.productType}
2037
2037
  </p>
2038
2038
  ) : null}
@@ -2105,7 +2105,7 @@ function ProductMetaSection({
2105
2105
  )}
2106
2106
  </p>
2107
2107
  {errors.taxRateId ? (
2108
- <p className="text-xs text-red-600">{errors.taxRateId}</p>
2108
+ <p className="text-xs text-status-error-text">{errors.taxRateId}</p>
2109
2109
  ) : null}
2110
2110
  </div>
2111
2111
  </div>
@@ -375,7 +375,7 @@ export function PriceKindSettings() {
375
375
  header: tableLabels.promotion,
376
376
  cell: ({ row }) =>
377
377
  row.original.isPromotion ? (
378
- <span className="inline-flex items-center rounded-full border border-amber-200 bg-amber-50 px-2 py-0.5 text-xs font-medium text-amber-900 dark:border-amber-500/50 dark:bg-amber-500/10 dark:text-amber-100">
378
+ <span className="inline-flex items-center rounded-full border border-status-warning-border bg-status-warning-bg px-2 py-0.5 text-xs font-medium text-status-warning-text">
379
379
  {tableLabels.promotionYes}
380
380
  </span>
381
381
  ) : (
@@ -389,7 +389,7 @@ export function PriceKindSettings() {
389
389
  header: tableLabels.active,
390
390
  cell: ({ row }) =>
391
391
  row.original.isActive ? (
392
- <span className="inline-flex items-center rounded-full border border-emerald-200 bg-emerald-50 px-2 py-0.5 text-xs font-medium text-emerald-900 dark:border-emerald-500/50 dark:bg-emerald-500/10 dark:text-emerald-100">
392
+ <span className="inline-flex items-center rounded-full border border-status-success-border bg-status-success-bg px-2 py-0.5 text-xs font-medium text-status-success-text">
393
393
  {tableLabels.activeYes}
394
394
  </span>
395
395
  ) : (
@@ -555,7 +555,7 @@ export function PriceKindSettings() {
555
555
  {t('catalog.priceKinds.form.activeLabel', 'Active')}
556
556
  </label>
557
557
  </div>
558
- {error ? <p className="text-sm text-red-600">{error}</p> : null}
558
+ {error ? <p className="text-sm text-status-error-text">{error}</p> : null}
559
559
  </form>
560
560
  <DialogFooter>
561
561
  <Button variant="ghost" onClick={closeDialog}>
@@ -220,7 +220,7 @@ export function ProductCategorizeSection({
220
220
  <p className="text-xs text-muted-foreground">
221
221
  {t('catalog.products.create.organize.categoriesHelp', 'Assign products to one or more taxonomy nodes.')}
222
222
  </p>
223
- {errors.categoryIds ? <p className="text-xs text-red-600">{errors.categoryIds}</p> : null}
223
+ {errors.categoryIds ? <p className="text-xs text-status-error-text">{errors.categoryIds}</p> : null}
224
224
  </div>
225
225
 
226
226
  <div className="space-y-2">
@@ -238,7 +238,7 @@ export function ProductCategorizeSection({
238
238
  <p className="text-xs text-muted-foreground">
239
239
  {t('catalog.products.create.organize.channelsHelp', 'Selected channels will receive default offers for this product.')}
240
240
  </p>
241
- {errors.channelIds ? <p className="text-xs text-red-600">{errors.channelIds}</p> : null}
241
+ {errors.channelIds ? <p className="text-xs text-status-error-text">{errors.channelIds}</p> : null}
242
242
  </div>
243
243
 
244
244
  <div className="space-y-2">
@@ -254,7 +254,7 @@ export function ProductCategorizeSection({
254
254
  <p className="text-xs text-muted-foreground">
255
255
  {t('catalog.products.create.organize.tagsHelp', 'Describe products with shared labels to build quick filters.')}
256
256
  </p>
257
- {errors.tags ? <p className="text-xs text-red-600">{errors.tags}</p> : null}
257
+ {errors.tags ? <p className="text-xs text-status-error-text">{errors.tags}</p> : null}
258
258
  </div>
259
259
  </div>
260
260
  )
@@ -186,7 +186,7 @@ export function ProductMediaManager({
186
186
  onChange={(event) => void acceptFiles(event.target.files)}
187
187
  />
188
188
  </div>
189
- {error ? <p className="text-xs font-medium text-red-600">{error}</p> : null}
189
+ {error ? <p className="text-xs font-medium text-status-error-text">{error}</p> : null}
190
190
  {items.length ? (
191
191
  <div className="grid grid-cols-2 gap-3 sm:grid-cols-3">
192
192
  {items.map((item) => {
@@ -98,14 +98,14 @@ export function VariantBasicsSection({ values, setValue, errors }: VariantSectio
98
98
  <div className="space-y-2">
99
99
  <Label className="flex items-center gap-1">
100
100
  {t('catalog.variants.form.nameLabel', 'Name')}
101
- <span className="text-red-600">*</span>
101
+ <span className="text-status-error-text">*</span>
102
102
  </Label>
103
103
  <Input
104
104
  value={values.name}
105
105
  onChange={(event) => setValue('name', event.target.value)}
106
106
  placeholder={t('catalog.variants.form.namePlaceholder', 'e.g., Blue / Small')}
107
107
  />
108
- {errors.name ? <p className="text-xs text-red-600">{errors.name}</p> : null}
108
+ {errors.name ? <p className="text-xs text-status-error-text">{errors.name}</p> : null}
109
109
  </div>
110
110
  <div className="grid gap-4 md:grid-cols-2">
111
111
  <div className="space-y-2">
@@ -123,7 +123,7 @@ export function VariantBasicsSection({ values, setValue, errors }: VariantSectio
123
123
  onChange={(event) => setValue('barcode', event.target.value)}
124
124
  placeholder={t('catalog.variants.form.barcodePlaceholder', 'EAN, UPC, etc.')}
125
125
  />
126
- {errors.barcode ? <p className="text-xs text-destructive">{errors.barcode}</p> : null}
126
+ {errors.barcode ? <p className="text-xs text-status-error-text">{errors.barcode}</p> : null}
127
127
  </div>
128
128
  </div>
129
129
  <div className="grid gap-4 md:grid-cols-2">
@@ -153,7 +153,7 @@ export function VariantBasicsSection({ values, setValue, errors }: VariantSectio
153
153
  'Typed barcodes are validated and kept unique per organization.',
154
154
  )}
155
155
  </p>
156
- {errors.gtinType ? <p className="text-xs text-destructive">{errors.gtinType}</p> : null}
156
+ {errors.gtinType ? <p className="text-xs text-status-error-text">{errors.gtinType}</p> : null}
157
157
  </div>
158
158
  <div className="space-y-2">
159
159
  <Label htmlFor="catalog-variant-hs-code">
@@ -164,7 +164,7 @@ export function VariantBasicsSection({ values, setValue, errors }: VariantSectio
164
164
  value={values.hsCode}
165
165
  onChange={(event) => setValue('hsCode', event.target.value)}
166
166
  />
167
- {errors.hsCode ? <p className="text-xs text-destructive">{errors.hsCode}</p> : null}
167
+ {errors.hsCode ? <p className="text-xs text-status-error-text">{errors.hsCode}</p> : null}
168
168
  </div>
169
169
  </div>
170
170
  <div className="grid gap-4 md:grid-cols-2">
@@ -871,7 +871,7 @@ function DisconnectChannelDialog({
871
871
  <Button type="button" variant="outline" onClick={onClose} disabled={submitting}>
872
872
  {t('communication_channels.profile.disconnect.cancel', 'Cancel')}
873
873
  </Button>
874
- <Button type="button" variant="destructive" onClick={() => void handleConfirm()} disabled={submitting}>
874
+ <Button type="button" variant="destructive-solid" onClick={() => void handleConfirm()} disabled={submitting}>
875
875
  {submitting
876
876
  ? t('communication_channels.profile.disconnect.submitting', 'Disconnecting…')
877
877
  : t('communication_channels.profile.disconnect.confirm', 'Disconnect')}
@@ -253,7 +253,7 @@ export function ConfirmDealLostDialog({
253
253
  </Button>
254
254
  <Button
255
255
  type="button"
256
- variant="destructive"
256
+ variant="destructive-solid"
257
257
  disabled={confirmDisabled}
258
258
  onClick={() => { void handleConfirm() }}
259
259
  >
@@ -18,17 +18,54 @@ export const dateRangePresetSchema = z.enum([
18
18
  'last_90_days',
19
19
  ])
20
20
 
21
+ const comparisonFilterOperators = ['eq', 'neq', 'gt', 'gte', 'lt', 'lte'] as const
22
+ const setFilterOperators = ['in', 'not_in'] as const
23
+ const nullFilterOperators = ['is_null', 'is_not_null'] as const
24
+ const scalarFilterOperators = [...comparisonFilterOperators, ...nullFilterOperators] as const
25
+
26
+ const scalarFilterOperatorSchema = z.enum(scalarFilterOperators)
27
+ const setFilterOperatorSchema = z.enum(setFilterOperators)
28
+
21
29
  export const filterOperatorSchema = z.enum([
22
- 'eq',
23
- 'neq',
24
- 'gt',
25
- 'gte',
26
- 'lt',
27
- 'lte',
28
- 'in',
29
- 'not_in',
30
- 'is_null',
31
- 'is_not_null',
30
+ ...comparisonFilterOperators,
31
+ ...setFilterOperators,
32
+ ...nullFilterOperators,
33
+ ])
34
+
35
+ /**
36
+ * Upper bound on how many members an `in` / `not_in` widget-data filter may carry (#4852).
37
+ *
38
+ * Every member becomes one placeholder plus one bound parameter in the aggregation's WHERE
39
+ * clause, so the cost of a set filter is proportional to its length. The bound lives here
40
+ * rather than in the SQL builder because `buildWhereClause` can only truncate the list —
41
+ * silently returning an answer to a different question than the caller asked — or throw from
42
+ * deep inside query construction; validating here yields a 400 that names the offending
43
+ * filter and is published in the route's OpenAPI schema.
44
+ *
45
+ * 200 is deliberately generous for a dashboard filter: the widest grouping a widget can render
46
+ * is capped at 100 buckets (`groupBy.limit`), and a batch carries at most 50 requests, so even
47
+ * a fully saturated batch stays an order of magnitude below PostgreSQL's per-statement limit
48
+ * of 65535 bound parameters. Raising it later is a one-line change to this constant.
49
+ */
50
+ export const MAX_SET_FILTER_VALUES = 200
51
+
52
+ // `IN` / `NOT IN` compare against literals; a null member never matches either way, which is
53
+ // what the dedicated `is_null` / `is_not_null` operators are for.
54
+ const setFilterMemberSchema = z.union([z.string(), z.number(), z.boolean()])
55
+
56
+ const setFilterValueSchema = z.array(setFilterMemberSchema).max(MAX_SET_FILTER_VALUES)
57
+
58
+ const widgetDataFilterSchema = z.discriminatedUnion('operator', [
59
+ z.object({
60
+ field: z.string().min(1),
61
+ operator: setFilterOperatorSchema,
62
+ value: setFilterValueSchema,
63
+ }),
64
+ z.object({
65
+ field: z.string().min(1),
66
+ operator: scalarFilterOperatorSchema,
67
+ value: z.unknown().optional(),
68
+ }),
32
69
  ])
33
70
 
34
71
  export const widgetDataRequestSchema = z.object({
@@ -45,15 +82,7 @@ export const widgetDataRequestSchema = z.object({
45
82
  resolveLabels: z.boolean().optional(),
46
83
  })
47
84
  .optional(),
48
- filters: z
49
- .array(
50
- z.object({
51
- field: z.string().min(1),
52
- operator: filterOperatorSchema,
53
- value: z.unknown().optional(),
54
- }),
55
- )
56
- .optional(),
85
+ filters: z.array(widgetDataFilterSchema).optional(),
57
86
  dateRange: z
58
87
  .object({
59
88
  field: z.string().min(1),
@@ -304,11 +304,11 @@ const notesAdapter: NotesDataAdapter = {
304
304
  entityId={personId}
305
305
  viewerUserId={viewer.id}
306
306
  viewerName={viewer.name}
307
- emptyLabel={t('customers.people.detail.notes.empty')}
308
- addActionLabel={t('customers.people.detail.notes.add')}
307
+ emptyLabel={t('design_system.gallery.samples.notes.empty')}
308
+ addActionLabel={t('design_system.gallery.samples.notes.add')}
309
309
  emptyState={{
310
- title: t('customers.people.detail.notes.emptyTitle'),
311
- actionLabel: t('customers.people.detail.notes.add'),
310
+ title: t('design_system.gallery.samples.notes.emptyTitle'),
311
+ actionLabel: t('design_system.gallery.samples.notes.add'),
312
312
  }}
313
313
  translator={t}
314
314
  dataAdapter={notesAdapter}
@@ -348,10 +348,10 @@ const addressesAdapter: AddressDataAdapter = {
348
348
 
349
349
  <AddressesSection
350
350
  entityId={personId}
351
- emptyLabel={t('customers.people.detail.addresses.empty')}
351
+ emptyLabel={t('design_system.gallery.samples.addresses.empty')}
352
352
  addActionLabel={t('customers.people.detail.addresses.add')}
353
353
  emptyState={{
354
- title: t('customers.people.detail.addresses.emptyTitle'),
354
+ title: t('design_system.gallery.samples.addresses.emptyTitle'),
355
355
  actionLabel: t('customers.people.detail.addresses.add'),
356
356
  }}
357
357
  translator={t}
@@ -386,8 +386,8 @@ const attachmentsSectionEntry: GalleryEntry = {
386
386
  <AttachmentsSection
387
387
  entityId="customers:person"
388
388
  recordId={person?.id ?? null}
389
- title={t('customers.people.detail.attachments.title')}
390
- description={t('customers.people.detail.attachments.description')}
389
+ title={t('design_system.gallery.samples.attachments.title')}
390
+ description={t('design_system.gallery.samples.attachments.description')}
391
391
  />`,
392
392
  },
393
393
  ],
@@ -152,7 +152,7 @@ import {
152
152
  <DialogClose asChild>
153
153
  <Button variant="outline">Cancel</Button>
154
154
  </DialogClose>
155
- <Button variant="destructive">Delete</Button>
155
+ <Button variant="destructive-solid">Delete</Button>
156
156
  </DialogFooter>
157
157
  </DialogContent>
158
158
  </Dialog>
@@ -185,7 +185,7 @@ import {
185
185
  <DialogClose asChild>
186
186
  <Button variant="outline">Cancel</Button>
187
187
  </DialogClose>
188
- <Button variant="destructive">Delete</Button>
188
+ <Button variant="destructive-solid">Delete</Button>
189
189
  </DialogFooter>
190
190
  </DialogContent>
191
191
  </Dialog>`,