@open-mercato/core 0.6.7-develop.6863.1.61001cf9a8 → 0.6.7-develop.6869.1.d1ce9999ea

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 (110) hide show
  1. package/.turbo/turbo-build.log +1 -1
  2. package/dist/modules/attachments/backend/config/attachments/page.js +1 -1
  3. package/dist/modules/attachments/backend/config/attachments/page.js.map +2 -2
  4. package/dist/modules/audit_logs/components/AuditLogsActions.js +1 -1
  5. package/dist/modules/audit_logs/components/AuditLogsActions.js.map +2 -2
  6. package/dist/modules/auth/frontend/login.js +2 -2
  7. package/dist/modules/auth/frontend/login.js.map +2 -2
  8. package/dist/modules/catalog/widgets/injection/product-bulk-delete/widget.js +10 -5
  9. package/dist/modules/catalog/widgets/injection/product-bulk-delete/widget.js.map +2 -2
  10. package/dist/modules/communication_channels/backend/profile/communication-channels/page.js +4 -4
  11. package/dist/modules/communication_channels/backend/profile/communication-channels/page.js.map +2 -2
  12. package/dist/modules/customer_accounts/backend/customer_accounts/settings/domain/components/Diagnostics.js +2 -2
  13. package/dist/modules/customer_accounts/backend/customer_accounts/settings/domain/components/Diagnostics.js.map +2 -2
  14. package/dist/modules/customers/api/utils.js +9 -6
  15. package/dist/modules/customers/api/utils.js.map +2 -2
  16. package/dist/modules/customers/backend/customers/deals/pipeline/page.js +1 -1
  17. package/dist/modules/customers/backend/customers/deals/pipeline/page.js.map +2 -2
  18. package/dist/modules/customers/components/calendar/CalendarEventEditor.js +1 -1
  19. package/dist/modules/customers/components/calendar/CalendarEventEditor.js.map +2 -2
  20. package/dist/modules/customers/components/detail/ConfirmDealLostDialog.js +1 -1
  21. package/dist/modules/customers/components/detail/ConfirmDealLostDialog.js.map +2 -2
  22. package/dist/modules/customers/components/detail/MiniWeekCalendar.js +7 -52
  23. package/dist/modules/customers/components/detail/MiniWeekCalendar.js.map +2 -2
  24. package/dist/modules/customers/components/detail/ScheduleActivityDialog.js +1 -1
  25. package/dist/modules/customers/components/detail/ScheduleActivityDialog.js.map +2 -2
  26. package/dist/modules/customers/components/detail/legacyActivities.js +69 -0
  27. package/dist/modules/customers/components/detail/legacyActivities.js.map +7 -0
  28. package/dist/modules/customers/utils/phoneDuplicates.js +1 -2
  29. package/dist/modules/customers/utils/phoneDuplicates.js.map +2 -2
  30. package/dist/modules/data_sync/backend/data-sync/page.js +3 -3
  31. package/dist/modules/data_sync/backend/data-sync/page.js.map +2 -2
  32. package/dist/modules/data_sync/components/IntegrationScheduleTab.js +5 -5
  33. package/dist/modules/data_sync/components/IntegrationScheduleTab.js.map +2 -2
  34. package/dist/modules/entities/api/records.js +8 -4
  35. package/dist/modules/entities/api/records.js.map +2 -2
  36. package/dist/modules/entities/backend/entities/user/[entityId]/page.js +1 -1
  37. package/dist/modules/entities/backend/entities/user/[entityId]/page.js.map +2 -2
  38. package/dist/modules/feature_toggles/components/FeatureToggleOverrideCard.js +1 -1
  39. package/dist/modules/feature_toggles/components/FeatureToggleOverrideCard.js.map +2 -2
  40. package/dist/modules/portal/frontend/[orgSlug]/portal/invite/page.js +1 -1
  41. package/dist/modules/portal/frontend/[orgSlug]/portal/invite/page.js.map +2 -2
  42. package/dist/modules/portal/frontend/[orgSlug]/portal/login/page.js +1 -1
  43. package/dist/modules/portal/frontend/[orgSlug]/portal/login/page.js.map +2 -2
  44. package/dist/modules/portal/frontend/[orgSlug]/portal/reset-password/page.js +1 -1
  45. package/dist/modules/portal/frontend/[orgSlug]/portal/reset-password/page.js.map +2 -2
  46. package/dist/modules/portal/frontend/[orgSlug]/portal/signup/page.js +1 -1
  47. package/dist/modules/portal/frontend/[orgSlug]/portal/signup/page.js.map +2 -2
  48. package/dist/modules/portal/frontend/[orgSlug]/portal/verify/page.js +1 -1
  49. package/dist/modules/portal/frontend/[orgSlug]/portal/verify/page.js.map +2 -2
  50. package/dist/modules/sales/components/documents/ItemsSection.js +11 -1
  51. package/dist/modules/sales/components/documents/ItemsSection.js.map +2 -2
  52. package/dist/modules/sync_excel/widgets/injection/upload-config/widget.client.js +1 -1
  53. package/dist/modules/sync_excel/widgets/injection/upload-config/widget.client.js.map +2 -2
  54. package/dist/modules/workflows/backend/definitions/[id]/page.js +2 -2
  55. package/dist/modules/workflows/backend/definitions/[id]/page.js.map +2 -2
  56. package/dist/modules/workflows/backend/definitions/create/page.js +1 -1
  57. package/dist/modules/workflows/backend/definitions/create/page.js.map +2 -2
  58. package/dist/modules/workflows/backend/definitions/visual-editor/page.js +3 -3
  59. package/dist/modules/workflows/backend/definitions/visual-editor/page.js.map +2 -2
  60. package/dist/modules/workflows/components/DefinitionTriggersEditor.js +1 -1
  61. package/dist/modules/workflows/components/DefinitionTriggersEditor.js.map +2 -2
  62. package/dist/modules/workflows/components/NodeEditDialog.js +3 -3
  63. package/dist/modules/workflows/components/NodeEditDialog.js.map +2 -2
  64. package/dist/modules/workflows/components/NodeEditDialogCrudForm.js +3 -3
  65. package/dist/modules/workflows/components/NodeEditDialogCrudForm.js.map +2 -2
  66. package/dist/modules/workflows/components/WorkflowGraphImpl.js +1 -1
  67. package/dist/modules/workflows/components/WorkflowGraphImpl.js.map +2 -2
  68. package/dist/modules/workflows/components/fields/FormFieldArrayEditor.js +1 -1
  69. package/dist/modules/workflows/components/fields/FormFieldArrayEditor.js.map +2 -2
  70. package/package.json +7 -7
  71. package/src/modules/attachments/backend/config/attachments/page.tsx +1 -1
  72. package/src/modules/audit_logs/components/AuditLogsActions.tsx +1 -1
  73. package/src/modules/auth/frontend/login.tsx +2 -2
  74. package/src/modules/catalog/widgets/injection/product-bulk-delete/widget.ts +15 -5
  75. package/src/modules/communication_channels/backend/profile/communication-channels/page.tsx +4 -4
  76. package/src/modules/communication_channels/i18n/de.json +2 -2
  77. package/src/modules/communication_channels/i18n/en.json +2 -2
  78. package/src/modules/communication_channels/i18n/es.json +2 -2
  79. package/src/modules/communication_channels/i18n/ko.json +2 -2
  80. package/src/modules/communication_channels/i18n/pl.json +2 -2
  81. package/src/modules/customer_accounts/backend/customer_accounts/settings/domain/components/Diagnostics.tsx +2 -2
  82. package/src/modules/customers/api/utils.ts +13 -6
  83. package/src/modules/customers/backend/customers/deals/pipeline/page.tsx +1 -1
  84. package/src/modules/customers/components/calendar/CalendarEventEditor.tsx +1 -1
  85. package/src/modules/customers/components/detail/ConfirmDealLostDialog.tsx +1 -1
  86. package/src/modules/customers/components/detail/MiniWeekCalendar.tsx +8 -57
  87. package/src/modules/customers/components/detail/ScheduleActivityDialog.tsx +1 -1
  88. package/src/modules/customers/components/detail/legacyActivities.ts +79 -0
  89. package/src/modules/customers/utils/phoneDuplicates.ts +6 -3
  90. package/src/modules/data_sync/backend/data-sync/page.tsx +3 -3
  91. package/src/modules/data_sync/components/IntegrationScheduleTab.tsx +5 -5
  92. package/src/modules/entities/api/records.ts +12 -4
  93. package/src/modules/entities/backend/entities/user/[entityId]/page.tsx +1 -1
  94. package/src/modules/feature_toggles/components/FeatureToggleOverrideCard.tsx +1 -1
  95. package/src/modules/portal/frontend/[orgSlug]/portal/invite/page.tsx +1 -1
  96. package/src/modules/portal/frontend/[orgSlug]/portal/login/page.tsx +1 -1
  97. package/src/modules/portal/frontend/[orgSlug]/portal/reset-password/page.tsx +1 -1
  98. package/src/modules/portal/frontend/[orgSlug]/portal/signup/page.tsx +1 -1
  99. package/src/modules/portal/frontend/[orgSlug]/portal/verify/page.tsx +1 -1
  100. package/src/modules/sales/components/documents/ItemsSection.tsx +13 -0
  101. package/src/modules/sales/components/documents/lineItemTypes.ts +1 -0
  102. package/src/modules/sync_excel/widgets/injection/upload-config/widget.client.tsx +1 -1
  103. package/src/modules/workflows/backend/definitions/[id]/page.tsx +2 -2
  104. package/src/modules/workflows/backend/definitions/create/page.tsx +1 -1
  105. package/src/modules/workflows/backend/definitions/visual-editor/page.tsx +3 -3
  106. package/src/modules/workflows/components/DefinitionTriggersEditor.tsx +1 -1
  107. package/src/modules/workflows/components/NodeEditDialog.tsx +3 -3
  108. package/src/modules/workflows/components/NodeEditDialogCrudForm.tsx +3 -3
  109. package/src/modules/workflows/components/WorkflowGraphImpl.tsx +1 -1
  110. package/src/modules/workflows/components/fields/FormFieldArrayEditor.tsx +1 -1
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../src/modules/workflows/components/NodeEditDialogCrudForm.tsx"],
4
- "sourcesContent": ["'use client'\n\nimport type { Node } from '@xyflow/react'\nimport { useState, useEffect, useCallback, useMemo } from 'react'\nimport { Dialog, DialogContent, DialogHeader, DialogTitle, DialogDescription } from '@open-mercato/ui/primitives/dialog'\nimport { Badge } from '@open-mercato/ui/primitives/badge'\nimport { Alert, AlertDescription } from '@open-mercato/ui/primitives/alert'\nimport { Button } from '@open-mercato/ui/primitives/button'\nimport { Trash2 } from 'lucide-react'\nimport { CrudForm, type CrudFormGroup, type CrudField, type CrudCustomFieldRenderProps } from '@open-mercato/ui/backend/CrudForm'\nimport { JsonBuilder } from '@open-mercato/ui/backend/JsonBuilder'\nimport { FormFieldArrayEditor } from './fields/FormFieldArrayEditor'\nimport { ActivityArrayEditor } from './fields/ActivityArrayEditor'\nimport { MappingArrayEditor } from './fields/MappingArrayEditor'\nimport { WorkflowSelectorField } from './fields/WorkflowSelectorField'\nimport { StartPreConditionsEditor } from './fields/StartPreConditionsEditor'\nimport { nodeToFormValues, formValuesToNodeUpdates, isJsonSchemaFormat, type NodeFormValues } from '../lib/nodeFormTransforms'\nimport { sanitizeId } from '../lib/graph-utils'\n\n/**\n * JsonConfigEditor - Custom field wrapper for JsonBuilder\n */\nfunction JsonConfigEditor({ value, setValue, disabled }: CrudCustomFieldRenderProps) {\n return (\n <JsonBuilder\n value={value || {}}\n onChange={setValue}\n disabled={disabled}\n />\n )\n}\n\nexport interface NodeEditDialogCrudFormProps {\n node: Node | null\n isOpen: boolean\n onClose: () => void\n onSave: (nodeId: string, updates: Partial<Node['data']>) => void\n onDelete?: (nodeId: string) => void\n}\n\n/**\n * NodeEditDialogCrudForm - CrudForm-based modal dialog for editing step properties\n *\n * Migrated from NodeEditDialog to use CrudForm for:\n * - UI coherence with other admin forms\n * - Custom fields support (future enhancement)\n * - Standardized validation and error handling\n * - Consistent keyboard shortcuts\n *\n * Handles 7 node types with dynamic groups:\n * - start: Non-editable (alert only)\n * - end: Non-editable (alert only)\n * - userTask: Assignment fields + form builder\n * - automated: Activity type + activities array\n * - subWorkflow: Workflow selector + input/output mappings\n * - waitForSignal: Signal name + timeout\n * - decision: Basic fields only\n */\nexport function NodeEditDialogCrudForm({ node, isOpen, onClose, onSave, onDelete }: NodeEditDialogCrudFormProps) {\n const [initialValues, setInitialValues] = useState<Partial<NodeFormValues>>({})\n const [showJsonSchemaWarning, setShowJsonSchemaWarning] = useState(false)\n\n // Load node data when dialog opens\n useEffect(() => {\n if (node && isOpen) {\n const values = nodeToFormValues(node)\n setInitialValues(values)\n setShowJsonSchemaWarning(isJsonSchemaFormat(node))\n }\n }, [node, isOpen])\n\n const handleSubmit = useCallback(async (values: Record<string, unknown>) => {\n if (!node) return\n\n // Validate and sanitize step ID\n const sanitizedId = sanitizeId(node.id)\n if (sanitizedId !== node.id) {\n if (typeof window !== 'undefined') {\n window.alert(\n `\u26A0\uFE0F Step ID was sanitized from \"${node.id}\" to \"${sanitizedId}\" to match schema requirements (lowercase letters, numbers, hyphens, and underscores only).`\n )\n }\n }\n\n try {\n const updates = formValuesToNodeUpdates(values as unknown as NodeFormValues, node)\n onSave(node.id, updates)\n onClose()\n } catch (error) {\n // Error will be displayed in form (e.g., invalid JSON)\n throw error\n }\n }, [node, onSave, onClose])\n\n const handleDelete = useCallback(() => {\n if (!node || !onDelete) return\n onDelete(node.id)\n }, [node, onDelete])\n\n const handleKeyDown = useCallback((e: React.KeyboardEvent) => {\n if (e.key === 'Escape') {\n onClose()\n }\n }, [onClose])\n\n // Dynamic groups based on node type\n const groups: CrudFormGroup[] = useMemo(() => {\n if (!node) return []\n\n // End nodes are non-editable\n if (node.type === 'end') {\n return [\n {\n id: 'info',\n column: 1,\n bare: true,\n component: () => (\n <Alert variant=\"info\">\n <AlertDescription>\n End nodes cannot be edited. They mark the completion of the workflow.\n </AlertDescription>\n </Alert>\n ),\n },\n ]\n }\n\n // Start nodes: allow editing pre-conditions\n if (node.type === 'start') {\n return [\n {\n id: 'info',\n column: 1,\n bare: true,\n component: () => (\n <Alert variant=\"info\" className=\"mb-4\">\n <AlertDescription>\n Start nodes mark the beginning of the workflow. You can define pre-conditions that must pass before the workflow can be started.\n </AlertDescription>\n </Alert>\n ),\n },\n {\n id: 'preConditions',\n title: 'Pre-Conditions',\n column: 1,\n description: 'Business rules that must pass before the workflow can start',\n fields: ['preConditions'],\n },\n ]\n }\n\n const baseGroups: CrudFormGroup[] = [\n {\n id: 'basic',\n title: 'Basic Information',\n column: 1,\n fields: ['stepName', 'description', 'timeout'],\n },\n ]\n\n // UserTask specific groups\n if (node.type === 'userTask') {\n return [\n ...baseGroups,\n {\n id: 'userTask',\n title: 'User Task Configuration',\n column: 1,\n fields: ['assignedTo', 'assignedToRoles', 'formKey'],\n },\n {\n id: 'formFields',\n title: 'Form Fields',\n column: 1,\n description: 'Define the form structure for this user task',\n fields: ['formFields'],\n },\n {\n id: 'advanced',\n title: 'Advanced Configuration',\n column: 1,\n description: 'Additional JSON configuration (userTaskConfig, retryPolicy, etc.)',\n fields: ['advancedConfig'],\n },\n ]\n }\n\n // Automated specific groups\n if (node.type === 'automated') {\n return [\n ...baseGroups,\n {\n id: 'automated',\n title: 'Automated Task Configuration',\n column: 1,\n fields: ['activityType', 'activityId'],\n },\n {\n id: 'stepActivities',\n title: 'Step Activities',\n column: 1,\n description: 'Activities executed as part of this automated step',\n fields: ['stepActivities'],\n },\n {\n id: 'advanced',\n title: 'Advanced Configuration',\n column: 1,\n description: 'Additional JSON configuration (retryPolicy, etc.)',\n fields: ['advancedConfig'],\n },\n ]\n }\n\n // SubWorkflow specific groups\n if (node.type === 'subWorkflow') {\n return [\n ...baseGroups,\n {\n id: 'subWorkflow',\n title: 'Sub-Workflow Configuration',\n column: 1,\n fields: ['subWorkflowId', 'subWorkflowVersion'],\n },\n {\n id: 'mappings',\n title: 'Data Mappings',\n column: 1,\n description: 'Map data between parent and sub-workflow',\n fields: ['inputMappings', 'outputMappings'],\n },\n {\n id: 'advanced',\n title: 'Advanced Configuration',\n column: 1,\n description: 'Additional JSON configuration',\n fields: ['advancedConfig'],\n },\n ]\n }\n\n // WaitForSignal specific groups\n if (node.type === 'waitForSignal') {\n return [\n ...baseGroups,\n {\n id: 'signal',\n title: 'Signal Configuration',\n column: 1,\n fields: ['signalName', 'signalTimeout'],\n },\n {\n id: 'advanced',\n title: 'Advanced Configuration',\n column: 1,\n description: 'Additional JSON configuration',\n fields: ['advancedConfig'],\n },\n ]\n }\n\n // Decision and other types: just basic fields + advanced\n return [\n ...baseGroups,\n {\n id: 'advanced',\n title: 'Advanced Configuration',\n column: 1,\n description: 'Additional JSON configuration',\n fields: ['advancedConfig'],\n },\n ]\n }, [node])\n\n // Define all possible form fields (only relevant ones are used based on groups)\n const fields: CrudField[] = useMemo(() => [\n // Basic fields\n {\n id: 'stepName',\n label: 'Step Name',\n type: 'text',\n placeholder: 'Enter step name',\n required: true,\n description: 'Display name for this step',\n },\n {\n id: 'description',\n label: 'Description',\n type: 'textarea',\n placeholder: 'Enter step description',\n description: 'Optional description of what this step does',\n },\n {\n id: 'timeout',\n label: 'Timeout',\n type: 'text',\n placeholder: 'PT30S or 30000',\n description: 'ISO 8601 duration (e.g., PT30S) or milliseconds',\n },\n\n // UserTask fields\n {\n id: 'assignedTo',\n label: 'Assigned To',\n type: 'text',\n placeholder: 'user@example.com or userId',\n description: 'User email or ID to assign this task to',\n },\n {\n id: 'assignedToRoles',\n label: 'Assigned To Roles',\n type: 'text',\n placeholder: 'admin, manager',\n description: 'Comma-separated list of roles that can claim this task',\n },\n {\n id: 'formKey',\n label: 'Form Key',\n type: 'text',\n placeholder: 'approval_form',\n description: 'Optional form key for external form rendering',\n },\n {\n id: 'formFields',\n label: 'Form Fields',\n type: 'custom',\n component: (props) => (\n <FormFieldArrayEditor\n {...props}\n value={props.value as any}\n isJsonSchemaFormat={showJsonSchemaWarning}\n />\n ),\n },\n\n // Automated fields\n {\n id: 'activityType',\n label: 'Activity Type',\n type: 'select',\n options: [\n { value: 'SEND_EMAIL', label: 'Send Email' },\n { value: 'CALL_API', label: 'Call API' },\n { value: 'UPDATE_ENTITY', label: 'Update Entity' },\n { value: 'EMIT_EVENT', label: 'Emit Event' },\n { value: 'CALL_WEBHOOK', label: 'Call Webhook' },\n { value: 'EXECUTE_FUNCTION', label: 'Execute Function' },\n { value: 'WAIT', label: 'Wait' },\n ],\n description: 'Type of activity to execute',\n },\n {\n id: 'activityId',\n label: 'Activity ID',\n type: 'text',\n placeholder: 'send_welcome_email',\n description: 'Unique identifier for this activity',\n },\n {\n id: 'stepActivities',\n label: 'Step Activities',\n type: 'custom',\n component: (props) => <ActivityArrayEditor {...props} value={props.value as any} />,\n },\n\n // SubWorkflow fields\n {\n id: 'subWorkflowId',\n label: 'Sub-Workflow',\n type: 'custom',\n component: (props) => <WorkflowSelectorField {...props} value={props.value as any} />,\n },\n {\n id: 'subWorkflowVersion',\n label: 'Version',\n type: 'number',\n placeholder: '1',\n description: 'Specific version of the sub-workflow to invoke',\n },\n {\n id: 'inputMappings',\n label: 'Input Mappings',\n type: 'custom',\n component: (props) => (\n <MappingArrayEditor\n {...props}\n value={props.value as any}\n label=\"Input Mappings\"\n description=\"Map parent workflow data to sub-workflow input\"\n />\n ),\n },\n {\n id: 'outputMappings',\n label: 'Output Mappings',\n type: 'custom',\n component: (props) => (\n <MappingArrayEditor\n {...props}\n value={props.value as any}\n label=\"Output Mappings\"\n description=\"Map sub-workflow output back to parent workflow\"\n />\n ),\n },\n\n // WaitForSignal fields\n {\n id: 'signalName',\n label: 'Signal Name',\n type: 'text',\n placeholder: 'approval_received',\n description: 'Name of the signal to wait for',\n },\n {\n id: 'signalTimeout',\n label: 'Signal Timeout',\n type: 'text',\n placeholder: 'PT5M',\n description: 'How long to wait for the signal (ISO 8601 duration)',\n },\n\n // Advanced configuration\n {\n id: 'advancedConfig',\n label: 'Advanced Configuration (JSON)',\n type: 'custom',\n description: 'Additional JSON configuration merged with the step data',\n component: (props) => <JsonConfigEditor {...props} />,\n },\n\n // Start node pre-conditions\n {\n id: 'preConditions',\n label: 'Pre-Conditions',\n type: 'custom',\n description: 'Business rules that must pass before the workflow can start',\n component: (props) => <StartPreConditionsEditor {...props} value={props.value as any} />,\n },\n ], [showJsonSchemaWarning])\n\n if (!isOpen || !node) return null\n\n const nodeType = node.type || 'unknown'\n const nodeTypeLabel = nodeType.charAt(0).toUpperCase() + nodeType.slice(1).replace(/([A-Z])/g, ' $1')\n\n const canDelete = !!onDelete\n\n return (\n <Dialog open={isOpen} onOpenChange={onClose}>\n <DialogContent\n className=\"sm:max-w-7xl max-h-[90vh] overflow-hidden flex flex-col !p-0 [&_.grid]:!grid-cols-1\"\n onKeyDown={handleKeyDown}\n >\n <DialogHeader className=\"flex-shrink-0 p-6 pb-4 border-b border-border/70\">\n <div className=\"flex items-center gap-2 mb-2\">\n <DialogTitle>Edit Step</DialogTitle>\n <Badge variant=\"secondary\" className=\"text-xs\">\n {nodeTypeLabel}\n </Badge>\n </div>\n <div className=\"space-y-1\">\n <DialogDescription>\n Configure step properties and behavior\n </DialogDescription>\n <div className=\"flex items-center gap-2 text-xs text-muted-foreground\">\n <span className=\"font-medium\">ID:</span>\n <code className=\"px-1.5 py-0.5 rounded bg-muted font-mono\">{node.id}</code>\n </div>\n </div>\n </DialogHeader>\n\n <div className=\"flex-1 overflow-y-auto min-h-0 px-6\">\n {/* JSON Schema Conversion Warning */}\n {showJsonSchemaWarning && (\n <Alert variant=\"info\" className=\"mb-4\">\n <AlertDescription className=\"text-xs\">\n This form uses JSON Schema format. Fields have been converted for visual editing.\n When you save, it will be converted to the simplified format. To preserve the original JSON Schema,\n edit it in the &#34;Advanced Configuration (JSON)&#34; section.\n </AlertDescription>\n </Alert>\n )}\n\n <CrudForm\n fields={fields}\n groups={groups}\n initialValues={initialValues}\n onSubmit={handleSubmit}\n embedded={true}\n submitLabel=\"Save Step\"\n extraActions={\n canDelete ? (\n <Button\n type=\"button\"\n variant=\"destructive\"\n onClick={handleDelete}\n >\n <Trash2 className=\"size-4 mr-2\" />\n Delete Step\n </Button>\n ) : undefined\n }\n />\n </div>\n </DialogContent>\n </Dialog>\n )\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["'use client'\n\nimport type { Node } from '@xyflow/react'\nimport { useState, useEffect, useCallback, useMemo } from 'react'\nimport { Dialog, DialogContent, DialogHeader, DialogTitle, DialogDescription } from '@open-mercato/ui/primitives/dialog'\nimport { Badge } from '@open-mercato/ui/primitives/badge'\nimport { Alert, AlertDescription } from '@open-mercato/ui/primitives/alert'\nimport { Button } from '@open-mercato/ui/primitives/button'\nimport { Trash2 } from 'lucide-react'\nimport { CrudForm, type CrudFormGroup, type CrudField, type CrudCustomFieldRenderProps } from '@open-mercato/ui/backend/CrudForm'\nimport { JsonBuilder } from '@open-mercato/ui/backend/JsonBuilder'\nimport { FormFieldArrayEditor } from './fields/FormFieldArrayEditor'\nimport { ActivityArrayEditor } from './fields/ActivityArrayEditor'\nimport { MappingArrayEditor } from './fields/MappingArrayEditor'\nimport { WorkflowSelectorField } from './fields/WorkflowSelectorField'\nimport { StartPreConditionsEditor } from './fields/StartPreConditionsEditor'\nimport { nodeToFormValues, formValuesToNodeUpdates, isJsonSchemaFormat, type NodeFormValues } from '../lib/nodeFormTransforms'\nimport { sanitizeId } from '../lib/graph-utils'\n\n/**\n * JsonConfigEditor - Custom field wrapper for JsonBuilder\n */\nfunction JsonConfigEditor({ value, setValue, disabled }: CrudCustomFieldRenderProps) {\n return (\n <JsonBuilder\n value={value || {}}\n onChange={setValue}\n disabled={disabled}\n />\n )\n}\n\nexport interface NodeEditDialogCrudFormProps {\n node: Node | null\n isOpen: boolean\n onClose: () => void\n onSave: (nodeId: string, updates: Partial<Node['data']>) => void\n onDelete?: (nodeId: string) => void\n}\n\n/**\n * NodeEditDialogCrudForm - CrudForm-based modal dialog for editing step properties\n *\n * Migrated from NodeEditDialog to use CrudForm for:\n * - UI coherence with other admin forms\n * - Custom fields support (future enhancement)\n * - Standardized validation and error handling\n * - Consistent keyboard shortcuts\n *\n * Handles 7 node types with dynamic groups:\n * - start: Non-editable (alert only)\n * - end: Non-editable (alert only)\n * - userTask: Assignment fields + form builder\n * - automated: Activity type + activities array\n * - subWorkflow: Workflow selector + input/output mappings\n * - waitForSignal: Signal name + timeout\n * - decision: Basic fields only\n */\nexport function NodeEditDialogCrudForm({ node, isOpen, onClose, onSave, onDelete }: NodeEditDialogCrudFormProps) {\n const [initialValues, setInitialValues] = useState<Partial<NodeFormValues>>({})\n const [showJsonSchemaWarning, setShowJsonSchemaWarning] = useState(false)\n\n // Load node data when dialog opens\n useEffect(() => {\n if (node && isOpen) {\n const values = nodeToFormValues(node)\n setInitialValues(values)\n setShowJsonSchemaWarning(isJsonSchemaFormat(node))\n }\n }, [node, isOpen])\n\n const handleSubmit = useCallback(async (values: Record<string, unknown>) => {\n if (!node) return\n\n // Validate and sanitize step ID\n const sanitizedId = sanitizeId(node.id)\n if (sanitizedId !== node.id) {\n if (typeof window !== 'undefined') {\n window.alert(\n `\u26A0\uFE0F Step ID was sanitized from \"${node.id}\" to \"${sanitizedId}\" to match schema requirements (lowercase letters, numbers, hyphens, and underscores only).`\n )\n }\n }\n\n try {\n const updates = formValuesToNodeUpdates(values as unknown as NodeFormValues, node)\n onSave(node.id, updates)\n onClose()\n } catch (error) {\n // Error will be displayed in form (e.g., invalid JSON)\n throw error\n }\n }, [node, onSave, onClose])\n\n const handleDelete = useCallback(() => {\n if (!node || !onDelete) return\n onDelete(node.id)\n }, [node, onDelete])\n\n const handleKeyDown = useCallback((e: React.KeyboardEvent) => {\n if (e.key === 'Escape') {\n onClose()\n }\n }, [onClose])\n\n // Dynamic groups based on node type\n const groups: CrudFormGroup[] = useMemo(() => {\n if (!node) return []\n\n // End nodes are non-editable\n if (node.type === 'end') {\n return [\n {\n id: 'info',\n column: 1,\n bare: true,\n component: () => (\n <Alert status=\"information\">\n <AlertDescription>\n End nodes cannot be edited. They mark the completion of the workflow.\n </AlertDescription>\n </Alert>\n ),\n },\n ]\n }\n\n // Start nodes: allow editing pre-conditions\n if (node.type === 'start') {\n return [\n {\n id: 'info',\n column: 1,\n bare: true,\n component: () => (\n <Alert status=\"information\" className=\"mb-4\">\n <AlertDescription>\n Start nodes mark the beginning of the workflow. You can define pre-conditions that must pass before the workflow can be started.\n </AlertDescription>\n </Alert>\n ),\n },\n {\n id: 'preConditions',\n title: 'Pre-Conditions',\n column: 1,\n description: 'Business rules that must pass before the workflow can start',\n fields: ['preConditions'],\n },\n ]\n }\n\n const baseGroups: CrudFormGroup[] = [\n {\n id: 'basic',\n title: 'Basic Information',\n column: 1,\n fields: ['stepName', 'description', 'timeout'],\n },\n ]\n\n // UserTask specific groups\n if (node.type === 'userTask') {\n return [\n ...baseGroups,\n {\n id: 'userTask',\n title: 'User Task Configuration',\n column: 1,\n fields: ['assignedTo', 'assignedToRoles', 'formKey'],\n },\n {\n id: 'formFields',\n title: 'Form Fields',\n column: 1,\n description: 'Define the form structure for this user task',\n fields: ['formFields'],\n },\n {\n id: 'advanced',\n title: 'Advanced Configuration',\n column: 1,\n description: 'Additional JSON configuration (userTaskConfig, retryPolicy, etc.)',\n fields: ['advancedConfig'],\n },\n ]\n }\n\n // Automated specific groups\n if (node.type === 'automated') {\n return [\n ...baseGroups,\n {\n id: 'automated',\n title: 'Automated Task Configuration',\n column: 1,\n fields: ['activityType', 'activityId'],\n },\n {\n id: 'stepActivities',\n title: 'Step Activities',\n column: 1,\n description: 'Activities executed as part of this automated step',\n fields: ['stepActivities'],\n },\n {\n id: 'advanced',\n title: 'Advanced Configuration',\n column: 1,\n description: 'Additional JSON configuration (retryPolicy, etc.)',\n fields: ['advancedConfig'],\n },\n ]\n }\n\n // SubWorkflow specific groups\n if (node.type === 'subWorkflow') {\n return [\n ...baseGroups,\n {\n id: 'subWorkflow',\n title: 'Sub-Workflow Configuration',\n column: 1,\n fields: ['subWorkflowId', 'subWorkflowVersion'],\n },\n {\n id: 'mappings',\n title: 'Data Mappings',\n column: 1,\n description: 'Map data between parent and sub-workflow',\n fields: ['inputMappings', 'outputMappings'],\n },\n {\n id: 'advanced',\n title: 'Advanced Configuration',\n column: 1,\n description: 'Additional JSON configuration',\n fields: ['advancedConfig'],\n },\n ]\n }\n\n // WaitForSignal specific groups\n if (node.type === 'waitForSignal') {\n return [\n ...baseGroups,\n {\n id: 'signal',\n title: 'Signal Configuration',\n column: 1,\n fields: ['signalName', 'signalTimeout'],\n },\n {\n id: 'advanced',\n title: 'Advanced Configuration',\n column: 1,\n description: 'Additional JSON configuration',\n fields: ['advancedConfig'],\n },\n ]\n }\n\n // Decision and other types: just basic fields + advanced\n return [\n ...baseGroups,\n {\n id: 'advanced',\n title: 'Advanced Configuration',\n column: 1,\n description: 'Additional JSON configuration',\n fields: ['advancedConfig'],\n },\n ]\n }, [node])\n\n // Define all possible form fields (only relevant ones are used based on groups)\n const fields: CrudField[] = useMemo(() => [\n // Basic fields\n {\n id: 'stepName',\n label: 'Step Name',\n type: 'text',\n placeholder: 'Enter step name',\n required: true,\n description: 'Display name for this step',\n },\n {\n id: 'description',\n label: 'Description',\n type: 'textarea',\n placeholder: 'Enter step description',\n description: 'Optional description of what this step does',\n },\n {\n id: 'timeout',\n label: 'Timeout',\n type: 'text',\n placeholder: 'PT30S or 30000',\n description: 'ISO 8601 duration (e.g., PT30S) or milliseconds',\n },\n\n // UserTask fields\n {\n id: 'assignedTo',\n label: 'Assigned To',\n type: 'text',\n placeholder: 'user@example.com or userId',\n description: 'User email or ID to assign this task to',\n },\n {\n id: 'assignedToRoles',\n label: 'Assigned To Roles',\n type: 'text',\n placeholder: 'admin, manager',\n description: 'Comma-separated list of roles that can claim this task',\n },\n {\n id: 'formKey',\n label: 'Form Key',\n type: 'text',\n placeholder: 'approval_form',\n description: 'Optional form key for external form rendering',\n },\n {\n id: 'formFields',\n label: 'Form Fields',\n type: 'custom',\n component: (props) => (\n <FormFieldArrayEditor\n {...props}\n value={props.value as any}\n isJsonSchemaFormat={showJsonSchemaWarning}\n />\n ),\n },\n\n // Automated fields\n {\n id: 'activityType',\n label: 'Activity Type',\n type: 'select',\n options: [\n { value: 'SEND_EMAIL', label: 'Send Email' },\n { value: 'CALL_API', label: 'Call API' },\n { value: 'UPDATE_ENTITY', label: 'Update Entity' },\n { value: 'EMIT_EVENT', label: 'Emit Event' },\n { value: 'CALL_WEBHOOK', label: 'Call Webhook' },\n { value: 'EXECUTE_FUNCTION', label: 'Execute Function' },\n { value: 'WAIT', label: 'Wait' },\n ],\n description: 'Type of activity to execute',\n },\n {\n id: 'activityId',\n label: 'Activity ID',\n type: 'text',\n placeholder: 'send_welcome_email',\n description: 'Unique identifier for this activity',\n },\n {\n id: 'stepActivities',\n label: 'Step Activities',\n type: 'custom',\n component: (props) => <ActivityArrayEditor {...props} value={props.value as any} />,\n },\n\n // SubWorkflow fields\n {\n id: 'subWorkflowId',\n label: 'Sub-Workflow',\n type: 'custom',\n component: (props) => <WorkflowSelectorField {...props} value={props.value as any} />,\n },\n {\n id: 'subWorkflowVersion',\n label: 'Version',\n type: 'number',\n placeholder: '1',\n description: 'Specific version of the sub-workflow to invoke',\n },\n {\n id: 'inputMappings',\n label: 'Input Mappings',\n type: 'custom',\n component: (props) => (\n <MappingArrayEditor\n {...props}\n value={props.value as any}\n label=\"Input Mappings\"\n description=\"Map parent workflow data to sub-workflow input\"\n />\n ),\n },\n {\n id: 'outputMappings',\n label: 'Output Mappings',\n type: 'custom',\n component: (props) => (\n <MappingArrayEditor\n {...props}\n value={props.value as any}\n label=\"Output Mappings\"\n description=\"Map sub-workflow output back to parent workflow\"\n />\n ),\n },\n\n // WaitForSignal fields\n {\n id: 'signalName',\n label: 'Signal Name',\n type: 'text',\n placeholder: 'approval_received',\n description: 'Name of the signal to wait for',\n },\n {\n id: 'signalTimeout',\n label: 'Signal Timeout',\n type: 'text',\n placeholder: 'PT5M',\n description: 'How long to wait for the signal (ISO 8601 duration)',\n },\n\n // Advanced configuration\n {\n id: 'advancedConfig',\n label: 'Advanced Configuration (JSON)',\n type: 'custom',\n description: 'Additional JSON configuration merged with the step data',\n component: (props) => <JsonConfigEditor {...props} />,\n },\n\n // Start node pre-conditions\n {\n id: 'preConditions',\n label: 'Pre-Conditions',\n type: 'custom',\n description: 'Business rules that must pass before the workflow can start',\n component: (props) => <StartPreConditionsEditor {...props} value={props.value as any} />,\n },\n ], [showJsonSchemaWarning])\n\n if (!isOpen || !node) return null\n\n const nodeType = node.type || 'unknown'\n const nodeTypeLabel = nodeType.charAt(0).toUpperCase() + nodeType.slice(1).replace(/([A-Z])/g, ' $1')\n\n const canDelete = !!onDelete\n\n return (\n <Dialog open={isOpen} onOpenChange={onClose}>\n <DialogContent\n className=\"sm:max-w-7xl max-h-[90vh] overflow-hidden flex flex-col !p-0 [&_.grid]:!grid-cols-1\"\n onKeyDown={handleKeyDown}\n >\n <DialogHeader className=\"flex-shrink-0 p-6 pb-4 border-b border-border/70\">\n <div className=\"flex items-center gap-2 mb-2\">\n <DialogTitle>Edit Step</DialogTitle>\n <Badge variant=\"secondary\" className=\"text-xs\">\n {nodeTypeLabel}\n </Badge>\n </div>\n <div className=\"space-y-1\">\n <DialogDescription>\n Configure step properties and behavior\n </DialogDescription>\n <div className=\"flex items-center gap-2 text-xs text-muted-foreground\">\n <span className=\"font-medium\">ID:</span>\n <code className=\"px-1.5 py-0.5 rounded bg-muted font-mono\">{node.id}</code>\n </div>\n </div>\n </DialogHeader>\n\n <div className=\"flex-1 overflow-y-auto min-h-0 px-6\">\n {/* JSON Schema Conversion Warning */}\n {showJsonSchemaWarning && (\n <Alert status=\"information\" className=\"mb-4\">\n <AlertDescription className=\"text-xs\">\n This form uses JSON Schema format. Fields have been converted for visual editing.\n When you save, it will be converted to the simplified format. To preserve the original JSON Schema,\n edit it in the &#34;Advanced Configuration (JSON)&#34; section.\n </AlertDescription>\n </Alert>\n )}\n\n <CrudForm\n fields={fields}\n groups={groups}\n initialValues={initialValues}\n onSubmit={handleSubmit}\n embedded={true}\n submitLabel=\"Save Step\"\n extraActions={\n canDelete ? (\n <Button\n type=\"button\"\n variant=\"destructive\"\n onClick={handleDelete}\n >\n <Trash2 className=\"size-4 mr-2\" />\n Delete Step\n </Button>\n ) : undefined\n }\n />\n </div>\n </DialogContent>\n </Dialog>\n )\n}\n"],
5
+ "mappings": ";AAwBI,cAgbM,YAhbN;AArBJ,SAAS,UAAU,WAAW,aAAa,eAAe;AAC1D,SAAS,QAAQ,eAAe,cAAc,aAAa,yBAAyB;AACpF,SAAS,aAAa;AACtB,SAAS,OAAO,wBAAwB;AACxC,SAAS,cAAc;AACvB,SAAS,cAAc;AACvB,SAAS,gBAAqF;AAC9F,SAAS,mBAAmB;AAC5B,SAAS,4BAA4B;AACrC,SAAS,2BAA2B;AACpC,SAAS,0BAA0B;AACnC,SAAS,6BAA6B;AACtC,SAAS,gCAAgC;AACzC,SAAS,kBAAkB,yBAAyB,0BAA+C;AACnG,SAAS,kBAAkB;AAK3B,SAAS,iBAAiB,EAAE,OAAO,UAAU,SAAS,GAA+B;AACnF,SACE;AAAA,IAAC;AAAA;AAAA,MACC,OAAO,SAAS,CAAC;AAAA,MACjB,UAAU;AAAA,MACV;AAAA;AAAA,EACF;AAEJ;AA4BO,SAAS,uBAAuB,EAAE,MAAM,QAAQ,SAAS,QAAQ,SAAS,GAAgC;AAC/G,QAAM,CAAC,eAAe,gBAAgB,IAAI,SAAkC,CAAC,CAAC;AAC9E,QAAM,CAAC,uBAAuB,wBAAwB,IAAI,SAAS,KAAK;AAGxE,YAAU,MAAM;AACd,QAAI,QAAQ,QAAQ;AAClB,YAAM,SAAS,iBAAiB,IAAI;AACpC,uBAAiB,MAAM;AACvB,+BAAyB,mBAAmB,IAAI,CAAC;AAAA,IACnD;AAAA,EACF,GAAG,CAAC,MAAM,MAAM,CAAC;AAEjB,QAAM,eAAe,YAAY,OAAO,WAAoC;AAC1E,QAAI,CAAC,KAAM;AAGX,UAAM,cAAc,WAAW,KAAK,EAAE;AACtC,QAAI,gBAAgB,KAAK,IAAI;AAC3B,UAAI,OAAO,WAAW,aAAa;AACjC,eAAO;AAAA,UACL,4CAAkC,KAAK,EAAE,SAAS,WAAW;AAAA,QAC/D;AAAA,MACF;AAAA,IACF;AAEA,QAAI;AACF,YAAM,UAAU,wBAAwB,QAAqC,IAAI;AACjF,aAAO,KAAK,IAAI,OAAO;AACvB,cAAQ;AAAA,IACV,SAAS,OAAO;AAEd,YAAM;AAAA,IACR;AAAA,EACF,GAAG,CAAC,MAAM,QAAQ,OAAO,CAAC;AAE1B,QAAM,eAAe,YAAY,MAAM;AACrC,QAAI,CAAC,QAAQ,CAAC,SAAU;AACxB,aAAS,KAAK,EAAE;AAAA,EAClB,GAAG,CAAC,MAAM,QAAQ,CAAC;AAEnB,QAAM,gBAAgB,YAAY,CAAC,MAA2B;AAC5D,QAAI,EAAE,QAAQ,UAAU;AACtB,cAAQ;AAAA,IACV;AAAA,EACF,GAAG,CAAC,OAAO,CAAC;AAGZ,QAAM,SAA0B,QAAQ,MAAM;AAC5C,QAAI,CAAC,KAAM,QAAO,CAAC;AAGnB,QAAI,KAAK,SAAS,OAAO;AACvB,aAAO;AAAA,QACL;AAAA,UACE,IAAI;AAAA,UACJ,QAAQ;AAAA,UACR,MAAM;AAAA,UACN,WAAW,MACT,oBAAC,SAAM,QAAO,eACZ,8BAAC,oBAAiB,mFAElB,GACF;AAAA,QAEJ;AAAA,MACF;AAAA,IACF;AAGA,QAAI,KAAK,SAAS,SAAS;AACzB,aAAO;AAAA,QACL;AAAA,UACE,IAAI;AAAA,UACJ,QAAQ;AAAA,UACR,MAAM;AAAA,UACN,WAAW,MACT,oBAAC,SAAM,QAAO,eAAc,WAAU,QACpC,8BAAC,oBAAiB,8IAElB,GACF;AAAA,QAEJ;AAAA,QACA;AAAA,UACE,IAAI;AAAA,UACJ,OAAO;AAAA,UACP,QAAQ;AAAA,UACR,aAAa;AAAA,UACb,QAAQ,CAAC,eAAe;AAAA,QAC1B;AAAA,MACF;AAAA,IACF;AAEA,UAAM,aAA8B;AAAA,MAClC;AAAA,QACE,IAAI;AAAA,QACJ,OAAO;AAAA,QACP,QAAQ;AAAA,QACR,QAAQ,CAAC,YAAY,eAAe,SAAS;AAAA,MAC/C;AAAA,IACF;AAGA,QAAI,KAAK,SAAS,YAAY;AAC5B,aAAO;AAAA,QACL,GAAG;AAAA,QACH;AAAA,UACE,IAAI;AAAA,UACJ,OAAO;AAAA,UACP,QAAQ;AAAA,UACR,QAAQ,CAAC,cAAc,mBAAmB,SAAS;AAAA,QACrD;AAAA,QACA;AAAA,UACE,IAAI;AAAA,UACJ,OAAO;AAAA,UACP,QAAQ;AAAA,UACR,aAAa;AAAA,UACb,QAAQ,CAAC,YAAY;AAAA,QACvB;AAAA,QACA;AAAA,UACE,IAAI;AAAA,UACJ,OAAO;AAAA,UACP,QAAQ;AAAA,UACR,aAAa;AAAA,UACb,QAAQ,CAAC,gBAAgB;AAAA,QAC3B;AAAA,MACF;AAAA,IACF;AAGA,QAAI,KAAK,SAAS,aAAa;AAC7B,aAAO;AAAA,QACL,GAAG;AAAA,QACH;AAAA,UACE,IAAI;AAAA,UACJ,OAAO;AAAA,UACP,QAAQ;AAAA,UACR,QAAQ,CAAC,gBAAgB,YAAY;AAAA,QACvC;AAAA,QACA;AAAA,UACE,IAAI;AAAA,UACJ,OAAO;AAAA,UACP,QAAQ;AAAA,UACR,aAAa;AAAA,UACb,QAAQ,CAAC,gBAAgB;AAAA,QAC3B;AAAA,QACA;AAAA,UACE,IAAI;AAAA,UACJ,OAAO;AAAA,UACP,QAAQ;AAAA,UACR,aAAa;AAAA,UACb,QAAQ,CAAC,gBAAgB;AAAA,QAC3B;AAAA,MACF;AAAA,IACF;AAGA,QAAI,KAAK,SAAS,eAAe;AAC/B,aAAO;AAAA,QACL,GAAG;AAAA,QACH;AAAA,UACE,IAAI;AAAA,UACJ,OAAO;AAAA,UACP,QAAQ;AAAA,UACR,QAAQ,CAAC,iBAAiB,oBAAoB;AAAA,QAChD;AAAA,QACA;AAAA,UACE,IAAI;AAAA,UACJ,OAAO;AAAA,UACP,QAAQ;AAAA,UACR,aAAa;AAAA,UACb,QAAQ,CAAC,iBAAiB,gBAAgB;AAAA,QAC5C;AAAA,QACA;AAAA,UACE,IAAI;AAAA,UACJ,OAAO;AAAA,UACP,QAAQ;AAAA,UACR,aAAa;AAAA,UACb,QAAQ,CAAC,gBAAgB;AAAA,QAC3B;AAAA,MACF;AAAA,IACF;AAGA,QAAI,KAAK,SAAS,iBAAiB;AACjC,aAAO;AAAA,QACL,GAAG;AAAA,QACH;AAAA,UACE,IAAI;AAAA,UACJ,OAAO;AAAA,UACP,QAAQ;AAAA,UACR,QAAQ,CAAC,cAAc,eAAe;AAAA,QACxC;AAAA,QACA;AAAA,UACE,IAAI;AAAA,UACJ,OAAO;AAAA,UACP,QAAQ;AAAA,UACR,aAAa;AAAA,UACb,QAAQ,CAAC,gBAAgB;AAAA,QAC3B;AAAA,MACF;AAAA,IACF;AAGA,WAAO;AAAA,MACL,GAAG;AAAA,MACH;AAAA,QACE,IAAI;AAAA,QACJ,OAAO;AAAA,QACP,QAAQ;AAAA,QACR,aAAa;AAAA,QACb,QAAQ,CAAC,gBAAgB;AAAA,MAC3B;AAAA,IACF;AAAA,EACF,GAAG,CAAC,IAAI,CAAC;AAGT,QAAM,SAAsB,QAAQ,MAAM;AAAA;AAAA,IAExC;AAAA,MACE,IAAI;AAAA,MACJ,OAAO;AAAA,MACP,MAAM;AAAA,MACN,aAAa;AAAA,MACb,UAAU;AAAA,MACV,aAAa;AAAA,IACf;AAAA,IACA;AAAA,MACE,IAAI;AAAA,MACJ,OAAO;AAAA,MACP,MAAM;AAAA,MACN,aAAa;AAAA,MACb,aAAa;AAAA,IACf;AAAA,IACA;AAAA,MACE,IAAI;AAAA,MACJ,OAAO;AAAA,MACP,MAAM;AAAA,MACN,aAAa;AAAA,MACb,aAAa;AAAA,IACf;AAAA;AAAA,IAGA;AAAA,MACE,IAAI;AAAA,MACJ,OAAO;AAAA,MACP,MAAM;AAAA,MACN,aAAa;AAAA,MACb,aAAa;AAAA,IACf;AAAA,IACA;AAAA,MACE,IAAI;AAAA,MACJ,OAAO;AAAA,MACP,MAAM;AAAA,MACN,aAAa;AAAA,MACb,aAAa;AAAA,IACf;AAAA,IACA;AAAA,MACE,IAAI;AAAA,MACJ,OAAO;AAAA,MACP,MAAM;AAAA,MACN,aAAa;AAAA,MACb,aAAa;AAAA,IACf;AAAA,IACA;AAAA,MACE,IAAI;AAAA,MACJ,OAAO;AAAA,MACP,MAAM;AAAA,MACN,WAAW,CAAC,UACV;AAAA,QAAC;AAAA;AAAA,UACE,GAAG;AAAA,UACJ,OAAO,MAAM;AAAA,UACb,oBAAoB;AAAA;AAAA,MACtB;AAAA,IAEJ;AAAA;AAAA,IAGA;AAAA,MACE,IAAI;AAAA,MACJ,OAAO;AAAA,MACP,MAAM;AAAA,MACN,SAAS;AAAA,QACP,EAAE,OAAO,cAAc,OAAO,aAAa;AAAA,QAC3C,EAAE,OAAO,YAAY,OAAO,WAAW;AAAA,QACvC,EAAE,OAAO,iBAAiB,OAAO,gBAAgB;AAAA,QACjD,EAAE,OAAO,cAAc,OAAO,aAAa;AAAA,QAC3C,EAAE,OAAO,gBAAgB,OAAO,eAAe;AAAA,QAC/C,EAAE,OAAO,oBAAoB,OAAO,mBAAmB;AAAA,QACvD,EAAE,OAAO,QAAQ,OAAO,OAAO;AAAA,MACjC;AAAA,MACA,aAAa;AAAA,IACf;AAAA,IACA;AAAA,MACE,IAAI;AAAA,MACJ,OAAO;AAAA,MACP,MAAM;AAAA,MACN,aAAa;AAAA,MACb,aAAa;AAAA,IACf;AAAA,IACA;AAAA,MACE,IAAI;AAAA,MACJ,OAAO;AAAA,MACP,MAAM;AAAA,MACN,WAAW,CAAC,UAAU,oBAAC,uBAAqB,GAAG,OAAO,OAAO,MAAM,OAAc;AAAA,IACnF;AAAA;AAAA,IAGA;AAAA,MACE,IAAI;AAAA,MACJ,OAAO;AAAA,MACP,MAAM;AAAA,MACN,WAAW,CAAC,UAAU,oBAAC,yBAAuB,GAAG,OAAO,OAAO,MAAM,OAAc;AAAA,IACrF;AAAA,IACA;AAAA,MACE,IAAI;AAAA,MACJ,OAAO;AAAA,MACP,MAAM;AAAA,MACN,aAAa;AAAA,MACb,aAAa;AAAA,IACf;AAAA,IACA;AAAA,MACE,IAAI;AAAA,MACJ,OAAO;AAAA,MACP,MAAM;AAAA,MACN,WAAW,CAAC,UACV;AAAA,QAAC;AAAA;AAAA,UACE,GAAG;AAAA,UACJ,OAAO,MAAM;AAAA,UACb,OAAM;AAAA,UACN,aAAY;AAAA;AAAA,MACd;AAAA,IAEJ;AAAA,IACA;AAAA,MACE,IAAI;AAAA,MACJ,OAAO;AAAA,MACP,MAAM;AAAA,MACN,WAAW,CAAC,UACV;AAAA,QAAC;AAAA;AAAA,UACE,GAAG;AAAA,UACJ,OAAO,MAAM;AAAA,UACb,OAAM;AAAA,UACN,aAAY;AAAA;AAAA,MACd;AAAA,IAEJ;AAAA;AAAA,IAGA;AAAA,MACE,IAAI;AAAA,MACJ,OAAO;AAAA,MACP,MAAM;AAAA,MACN,aAAa;AAAA,MACb,aAAa;AAAA,IACf;AAAA,IACA;AAAA,MACE,IAAI;AAAA,MACJ,OAAO;AAAA,MACP,MAAM;AAAA,MACN,aAAa;AAAA,MACb,aAAa;AAAA,IACf;AAAA;AAAA,IAGA;AAAA,MACE,IAAI;AAAA,MACJ,OAAO;AAAA,MACP,MAAM;AAAA,MACN,aAAa;AAAA,MACb,WAAW,CAAC,UAAU,oBAAC,oBAAkB,GAAG,OAAO;AAAA,IACrD;AAAA;AAAA,IAGA;AAAA,MACE,IAAI;AAAA,MACJ,OAAO;AAAA,MACP,MAAM;AAAA,MACN,aAAa;AAAA,MACb,WAAW,CAAC,UAAU,oBAAC,4BAA0B,GAAG,OAAO,OAAO,MAAM,OAAc;AAAA,IACxF;AAAA,EACF,GAAG,CAAC,qBAAqB,CAAC;AAE1B,MAAI,CAAC,UAAU,CAAC,KAAM,QAAO;AAE7B,QAAM,WAAW,KAAK,QAAQ;AAC9B,QAAM,gBAAgB,SAAS,OAAO,CAAC,EAAE,YAAY,IAAI,SAAS,MAAM,CAAC,EAAE,QAAQ,YAAY,KAAK;AAEpG,QAAM,YAAY,CAAC,CAAC;AAEpB,SACE,oBAAC,UAAO,MAAM,QAAQ,cAAc,SAClC;AAAA,IAAC;AAAA;AAAA,MACC,WAAU;AAAA,MACV,WAAW;AAAA,MAEX;AAAA,6BAAC,gBAAa,WAAU,oDACtB;AAAA,+BAAC,SAAI,WAAU,gCACb;AAAA,gCAAC,eAAY,uBAAS;AAAA,YACtB,oBAAC,SAAM,SAAQ,aAAY,WAAU,WAClC,yBACH;AAAA,aACF;AAAA,UACA,qBAAC,SAAI,WAAU,aACb;AAAA,gCAAC,qBAAkB,oDAEnB;AAAA,YACA,qBAAC,SAAI,WAAU,yDACb;AAAA,kCAAC,UAAK,WAAU,eAAc,iBAAG;AAAA,cACjC,oBAAC,UAAK,WAAU,4CAA4C,eAAK,IAAG;AAAA,eACtE;AAAA,aACF;AAAA,WACF;AAAA,QAEA,qBAAC,SAAI,WAAU,uCAEZ;AAAA,mCACC,oBAAC,SAAM,QAAO,eAAc,WAAU,QACpC,8BAAC,oBAAiB,WAAU,WAAU,2PAItC,GACF;AAAA,UAGF;AAAA,YAAC;AAAA;AAAA,cACC;AAAA,cACA;AAAA,cACA;AAAA,cACA,UAAU;AAAA,cACV,UAAU;AAAA,cACV,aAAY;AAAA,cACZ,cACE,YACE;AAAA,gBAAC;AAAA;AAAA,kBACC,MAAK;AAAA,kBACL,SAAQ;AAAA,kBACR,SAAS;AAAA,kBAET;AAAA,wCAAC,UAAO,WAAU,eAAc;AAAA,oBAAE;AAAA;AAAA;AAAA,cAEpC,IACE;AAAA;AAAA,UAER;AAAA,WACF;AAAA;AAAA;AAAA,EACF,GACF;AAEJ;",
6
6
  "names": []
7
7
  }
@@ -192,7 +192,7 @@ function WorkflowGraphImpl({
192
192
  }
193
193
  ),
194
194
  !editable && !isCompactViewport && /* @__PURE__ */ jsx(Panel, { position: "top-left", style: { margin: 10 }, children: /* @__PURE__ */ jsx("div", { className: "bg-card rounded-lg shadow-sm border border-border px-4 py-2", children: /* @__PURE__ */ jsx("p", { className: "text-sm text-muted-foreground font-medium", children: t("workflows.graph.visualization") }) }) }),
195
- editable && !isCompactViewport && /* @__PURE__ */ jsx(Panel, { position: "top-left", style: { margin: 10 }, children: /* @__PURE__ */ jsx(Alert, { variant: "info", icon: /* @__PURE__ */ jsx(Edit3, { "aria-hidden": "true" }), className: "max-w-sm", children: /* @__PURE__ */ jsx(AlertDescription, { className: "font-medium", children: t("workflows.graph.editModeInfo") }) }) })
195
+ editable && !isCompactViewport && /* @__PURE__ */ jsx(Panel, { position: "top-left", style: { margin: 10 }, children: /* @__PURE__ */ jsx(Alert, { status: "information", icon: /* @__PURE__ */ jsx(Edit3, { "aria-hidden": "true" }), className: "max-w-sm", children: /* @__PURE__ */ jsx(AlertDescription, { className: "font-medium", children: t("workflows.graph.editModeInfo") }) }) })
196
196
  ]
197
197
  }
198
198
  ) });
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../src/modules/workflows/components/WorkflowGraphImpl.tsx"],
4
- "sourcesContent": ["'use client'\n\nimport '@xyflow/react/dist/style.css'\n\nimport { useCallback, useMemo, useEffect, useRef, useState } from 'react'\nimport {\n ReactFlow,\n Node,\n Edge,\n Controls,\n Background,\n BackgroundVariant,\n MiniMap,\n Panel,\n useNodesState,\n useEdgesState,\n addEdge,\n applyNodeChanges,\n applyEdgeChanges,\n Connection,\n NodeChange,\n EdgeChange,\n ConnectionMode,\n MarkerType,\n} from '@xyflow/react'\nimport {StartNode, EndNode, UserTaskNode, AutomatedNode, SubWorkflowNode, WaitForSignalNode, WaitForTimerNode, ParallelForkNode, ParallelJoinNode} from './nodes'\nimport { WorkflowTransitionEdge } from './WorkflowTransitionEdge'\nimport { STATUS_COLORS } from '../lib/status-colors'\nimport { Alert, AlertDescription } from '@open-mercato/ui/primitives/alert'\nimport { Edit3 } from 'lucide-react'\nimport { useTheme } from '@open-mercato/ui/theme'\nimport { useT } from '@open-mercato/shared/lib/i18n/context'\n\nexport interface WorkflowGraphImplProps {\n initialNodes?: Node[]\n initialEdges?: Edge[]\n onNodesChange?: (nodes: Node[]) => void\n onEdgesChange?: (edges: Edge[]) => void\n onNodeClick?: (event: React.MouseEvent, node: Node) => void\n onEdgeClick?: (event: React.MouseEvent, edge: Edge) => void\n onConnect?: (connection: Connection) => void\n editable?: boolean\n className?: string\n height?: string\n}\n\nexport default function WorkflowGraphImpl({\n initialNodes = [],\n initialEdges = [],\n onNodesChange: onNodesChangeProp,\n onEdgesChange: onEdgesChangeProp,\n onNodeClick: onNodeClickProp,\n onEdgeClick: onEdgeClickProp,\n onConnect: onConnectProp,\n editable = false,\n className = '',\n height = '600px',\n}: WorkflowGraphImplProps) {\n const t = useT()\n const [nodes, setNodes] = useNodesState(initialNodes)\n const [edges, setEdges] = useEdgesState(initialEdges)\n\n // Track the latest committed graph so the change reducers can run inside the\n // lazy boundary (#3169) and forward the already-applied arrays to the parent,\n // keeping React Flow's runtime out of the editor page chunk.\n const latestNodesRef = useRef(nodes)\n latestNodesRef.current = nodes\n const latestEdgesRef = useRef(edges)\n latestEdgesRef.current = edges\n\n const { resolvedTheme } = useTheme()\n const isDark = resolvedTheme === 'dark'\n const backgroundDotColor = isDark ? '#374151' : '#e5e7eb'\n const [isCompactViewport, setIsCompactViewport] = useState(false)\n\n useEffect(() => {\n if (typeof window === 'undefined') return\n const mediaQuery = window.matchMedia('(max-width: 1279px)')\n const updateViewportMode = () => setIsCompactViewport(mediaQuery.matches)\n\n updateViewportMode()\n mediaQuery.addEventListener('change', updateViewportMode)\n\n return () => {\n mediaQuery.removeEventListener('change', updateViewportMode)\n }\n }, [])\n\n useEffect(() => {\n setNodes(initialNodes)\n }, [initialNodes, setNodes])\n\n useEffect(() => {\n setEdges(initialEdges)\n }, [initialEdges, setEdges])\n\n const onConnect = useCallback(\n (connection: Connection) => {\n if (onConnectProp) {\n onConnectProp(connection)\n } else {\n const newEdge = {\n ...connection,\n type: 'workflowTransition',\n animated: false,\n markerEnd: {\n type: MarkerType.ArrowClosed,\n width: 16,\n height: 16,\n color: '#9ca3af',\n },\n }\n setEdges((eds) => addEdge(newEdge, eds))\n }\n },\n [setEdges, onConnectProp]\n )\n\n const handleNodesChange = useCallback(\n (changes: NodeChange[]) => {\n const nextNodes = applyNodeChanges(changes, latestNodesRef.current)\n setNodes(nextNodes)\n if (onNodesChangeProp) {\n onNodesChangeProp(nextNodes)\n }\n },\n [setNodes, onNodesChangeProp]\n )\n\n const handleEdgesChange = useCallback(\n (changes: EdgeChange[]) => {\n const nextEdges = applyEdgeChanges(changes, latestEdgesRef.current)\n setEdges(nextEdges)\n if (onEdgesChangeProp) {\n onEdgesChangeProp(nextEdges)\n }\n },\n [setEdges, onEdgesChangeProp]\n )\n\n const nodeTypes = useMemo(\n () => ({\n start: StartNode,\n end: EndNode,\n userTask: UserTaskNode,\n automated: AutomatedNode,\n subWorkflow: SubWorkflowNode,\n waitForSignal: WaitForSignalNode,\n waitForTimer: WaitForTimerNode,\n parallelFork: ParallelForkNode,\n parallelJoin: ParallelJoinNode,\n }),\n []\n )\n\n const edgeTypes = useMemo(\n () => ({\n workflowTransition: WorkflowTransitionEdge,\n }),\n []\n )\n\n return (\n <div className={`workflow-graph-container ${className}`} style={{ height }}>\n <ReactFlow\n nodes={nodes}\n edges={edges}\n nodeTypes={nodeTypes}\n edgeTypes={edgeTypes}\n onNodesChange={handleNodesChange}\n onEdgesChange={handleEdgesChange}\n onConnect={editable ? onConnect : undefined}\n onNodeClick={onNodeClickProp}\n onEdgeClick={onEdgeClickProp}\n connectionMode={ConnectionMode.Loose}\n fitView\n fitViewOptions={{\n padding: 0.2,\n maxZoom: isCompactViewport ? 0.9 : 1,\n }}\n minZoom={0.1}\n maxZoom={2}\n defaultEdgeOptions={{\n type: 'workflowTransition',\n animated: false,\n markerEnd: {\n type: MarkerType.ArrowClosed,\n width: 16,\n height: 16,\n color: '#9ca3af',\n },\n }}\n nodesDraggable={editable}\n nodesConnectable={editable}\n elementsSelectable={editable}\n proOptions={{ hideAttribution: true }}\n >\n <Background\n variant={BackgroundVariant.Dots}\n gap={16}\n size={1}\n color={backgroundDotColor}\n />\n\n <Controls\n showZoom={true}\n showFitView={true}\n showInteractive={false}\n position={isCompactViewport ? 'bottom-right' : 'top-right'}\n className={`!bg-card !border-border !shadow-md [&>button]:!bg-card [&>button]:!border-border [&>button]:!fill-foreground [&>button:hover]:!bg-muted ${isCompactViewport ? 'scale-90 origin-bottom-right' : ''}`}\n />\n\n {!isCompactViewport && (\n <MiniMap\n nodeStrokeWidth={3}\n nodeColor={(node) => {\n const status = (node.data?.status || 'not_started') as keyof typeof STATUS_COLORS\n return STATUS_COLORS[status]?.hex || STATUS_COLORS.not_started.hex\n }}\n maskColor=\"rgba(0, 0, 0, 0.1)\"\n position=\"bottom-left\"\n className=\"!bg-card !border !border-border !rounded-lg\"\n />\n )}\n\n {!editable && !isCompactViewport && (\n <Panel position=\"top-left\" style={{ margin: 10 }}>\n <div className=\"bg-card rounded-lg shadow-sm border border-border px-4 py-2\">\n <p className=\"text-sm text-muted-foreground font-medium\">\n {t('workflows.graph.visualization')}\n </p>\n </div>\n </Panel>\n )}\n\n {editable && !isCompactViewport && (\n <Panel position=\"top-left\" style={{ margin: 10 }}>\n <Alert variant=\"info\" icon={<Edit3 aria-hidden=\"true\" />} className=\"max-w-sm\">\n <AlertDescription className=\"font-medium\">\n {t('workflows.graph.editModeInfo')}\n </AlertDescription>\n </Alert>\n </Panel>\n )}\n </ReactFlow>\n </div>\n )\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["'use client'\n\nimport '@xyflow/react/dist/style.css'\n\nimport { useCallback, useMemo, useEffect, useRef, useState } from 'react'\nimport {\n ReactFlow,\n Node,\n Edge,\n Controls,\n Background,\n BackgroundVariant,\n MiniMap,\n Panel,\n useNodesState,\n useEdgesState,\n addEdge,\n applyNodeChanges,\n applyEdgeChanges,\n Connection,\n NodeChange,\n EdgeChange,\n ConnectionMode,\n MarkerType,\n} from '@xyflow/react'\nimport {StartNode, EndNode, UserTaskNode, AutomatedNode, SubWorkflowNode, WaitForSignalNode, WaitForTimerNode, ParallelForkNode, ParallelJoinNode} from './nodes'\nimport { WorkflowTransitionEdge } from './WorkflowTransitionEdge'\nimport { STATUS_COLORS } from '../lib/status-colors'\nimport { Alert, AlertDescription } from '@open-mercato/ui/primitives/alert'\nimport { Edit3 } from 'lucide-react'\nimport { useTheme } from '@open-mercato/ui/theme'\nimport { useT } from '@open-mercato/shared/lib/i18n/context'\n\nexport interface WorkflowGraphImplProps {\n initialNodes?: Node[]\n initialEdges?: Edge[]\n onNodesChange?: (nodes: Node[]) => void\n onEdgesChange?: (edges: Edge[]) => void\n onNodeClick?: (event: React.MouseEvent, node: Node) => void\n onEdgeClick?: (event: React.MouseEvent, edge: Edge) => void\n onConnect?: (connection: Connection) => void\n editable?: boolean\n className?: string\n height?: string\n}\n\nexport default function WorkflowGraphImpl({\n initialNodes = [],\n initialEdges = [],\n onNodesChange: onNodesChangeProp,\n onEdgesChange: onEdgesChangeProp,\n onNodeClick: onNodeClickProp,\n onEdgeClick: onEdgeClickProp,\n onConnect: onConnectProp,\n editable = false,\n className = '',\n height = '600px',\n}: WorkflowGraphImplProps) {\n const t = useT()\n const [nodes, setNodes] = useNodesState(initialNodes)\n const [edges, setEdges] = useEdgesState(initialEdges)\n\n // Track the latest committed graph so the change reducers can run inside the\n // lazy boundary (#3169) and forward the already-applied arrays to the parent,\n // keeping React Flow's runtime out of the editor page chunk.\n const latestNodesRef = useRef(nodes)\n latestNodesRef.current = nodes\n const latestEdgesRef = useRef(edges)\n latestEdgesRef.current = edges\n\n const { resolvedTheme } = useTheme()\n const isDark = resolvedTheme === 'dark'\n const backgroundDotColor = isDark ? '#374151' : '#e5e7eb'\n const [isCompactViewport, setIsCompactViewport] = useState(false)\n\n useEffect(() => {\n if (typeof window === 'undefined') return\n const mediaQuery = window.matchMedia('(max-width: 1279px)')\n const updateViewportMode = () => setIsCompactViewport(mediaQuery.matches)\n\n updateViewportMode()\n mediaQuery.addEventListener('change', updateViewportMode)\n\n return () => {\n mediaQuery.removeEventListener('change', updateViewportMode)\n }\n }, [])\n\n useEffect(() => {\n setNodes(initialNodes)\n }, [initialNodes, setNodes])\n\n useEffect(() => {\n setEdges(initialEdges)\n }, [initialEdges, setEdges])\n\n const onConnect = useCallback(\n (connection: Connection) => {\n if (onConnectProp) {\n onConnectProp(connection)\n } else {\n const newEdge = {\n ...connection,\n type: 'workflowTransition',\n animated: false,\n markerEnd: {\n type: MarkerType.ArrowClosed,\n width: 16,\n height: 16,\n color: '#9ca3af',\n },\n }\n setEdges((eds) => addEdge(newEdge, eds))\n }\n },\n [setEdges, onConnectProp]\n )\n\n const handleNodesChange = useCallback(\n (changes: NodeChange[]) => {\n const nextNodes = applyNodeChanges(changes, latestNodesRef.current)\n setNodes(nextNodes)\n if (onNodesChangeProp) {\n onNodesChangeProp(nextNodes)\n }\n },\n [setNodes, onNodesChangeProp]\n )\n\n const handleEdgesChange = useCallback(\n (changes: EdgeChange[]) => {\n const nextEdges = applyEdgeChanges(changes, latestEdgesRef.current)\n setEdges(nextEdges)\n if (onEdgesChangeProp) {\n onEdgesChangeProp(nextEdges)\n }\n },\n [setEdges, onEdgesChangeProp]\n )\n\n const nodeTypes = useMemo(\n () => ({\n start: StartNode,\n end: EndNode,\n userTask: UserTaskNode,\n automated: AutomatedNode,\n subWorkflow: SubWorkflowNode,\n waitForSignal: WaitForSignalNode,\n waitForTimer: WaitForTimerNode,\n parallelFork: ParallelForkNode,\n parallelJoin: ParallelJoinNode,\n }),\n []\n )\n\n const edgeTypes = useMemo(\n () => ({\n workflowTransition: WorkflowTransitionEdge,\n }),\n []\n )\n\n return (\n <div className={`workflow-graph-container ${className}`} style={{ height }}>\n <ReactFlow\n nodes={nodes}\n edges={edges}\n nodeTypes={nodeTypes}\n edgeTypes={edgeTypes}\n onNodesChange={handleNodesChange}\n onEdgesChange={handleEdgesChange}\n onConnect={editable ? onConnect : undefined}\n onNodeClick={onNodeClickProp}\n onEdgeClick={onEdgeClickProp}\n connectionMode={ConnectionMode.Loose}\n fitView\n fitViewOptions={{\n padding: 0.2,\n maxZoom: isCompactViewport ? 0.9 : 1,\n }}\n minZoom={0.1}\n maxZoom={2}\n defaultEdgeOptions={{\n type: 'workflowTransition',\n animated: false,\n markerEnd: {\n type: MarkerType.ArrowClosed,\n width: 16,\n height: 16,\n color: '#9ca3af',\n },\n }}\n nodesDraggable={editable}\n nodesConnectable={editable}\n elementsSelectable={editable}\n proOptions={{ hideAttribution: true }}\n >\n <Background\n variant={BackgroundVariant.Dots}\n gap={16}\n size={1}\n color={backgroundDotColor}\n />\n\n <Controls\n showZoom={true}\n showFitView={true}\n showInteractive={false}\n position={isCompactViewport ? 'bottom-right' : 'top-right'}\n className={`!bg-card !border-border !shadow-md [&>button]:!bg-card [&>button]:!border-border [&>button]:!fill-foreground [&>button:hover]:!bg-muted ${isCompactViewport ? 'scale-90 origin-bottom-right' : ''}`}\n />\n\n {!isCompactViewport && (\n <MiniMap\n nodeStrokeWidth={3}\n nodeColor={(node) => {\n const status = (node.data?.status || 'not_started') as keyof typeof STATUS_COLORS\n return STATUS_COLORS[status]?.hex || STATUS_COLORS.not_started.hex\n }}\n maskColor=\"rgba(0, 0, 0, 0.1)\"\n position=\"bottom-left\"\n className=\"!bg-card !border !border-border !rounded-lg\"\n />\n )}\n\n {!editable && !isCompactViewport && (\n <Panel position=\"top-left\" style={{ margin: 10 }}>\n <div className=\"bg-card rounded-lg shadow-sm border border-border px-4 py-2\">\n <p className=\"text-sm text-muted-foreground font-medium\">\n {t('workflows.graph.visualization')}\n </p>\n </div>\n </Panel>\n )}\n\n {editable && !isCompactViewport && (\n <Panel position=\"top-left\" style={{ margin: 10 }}>\n <Alert status=\"information\" icon={<Edit3 aria-hidden=\"true\" />} className=\"max-w-sm\">\n <AlertDescription className=\"font-medium\">\n {t('workflows.graph.editModeInfo')}\n </AlertDescription>\n </Alert>\n </Panel>\n )}\n </ReactFlow>\n </div>\n )\n}\n"],
5
+ "mappings": ";AAoKM,SAiCE,KAjCF;AAlKN,OAAO;AAEP,SAAS,aAAa,SAAS,WAAW,QAAQ,gBAAgB;AAClE;AAAA,EACE;AAAA,EAGA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EAIA;AAAA,EACA;AAAA,OACK;AACP,SAAQ,WAAW,SAAS,cAAc,eAAe,iBAAiB,mBAAmB,kBAAkB,kBAAkB,wBAAuB;AACxJ,SAAS,8BAA8B;AACvC,SAAS,qBAAqB;AAC9B,SAAS,OAAO,wBAAwB;AACxC,SAAS,aAAa;AACtB,SAAS,gBAAgB;AACzB,SAAS,YAAY;AAeN,SAAR,kBAAmC;AAAA,EACxC,eAAe,CAAC;AAAA,EAChB,eAAe,CAAC;AAAA,EAChB,eAAe;AAAA,EACf,eAAe;AAAA,EACf,aAAa;AAAA,EACb,aAAa;AAAA,EACb,WAAW;AAAA,EACX,WAAW;AAAA,EACX,YAAY;AAAA,EACZ,SAAS;AACX,GAA2B;AACzB,QAAM,IAAI,KAAK;AACf,QAAM,CAAC,OAAO,QAAQ,IAAI,cAAc,YAAY;AACpD,QAAM,CAAC,OAAO,QAAQ,IAAI,cAAc,YAAY;AAKpD,QAAM,iBAAiB,OAAO,KAAK;AACnC,iBAAe,UAAU;AACzB,QAAM,iBAAiB,OAAO,KAAK;AACnC,iBAAe,UAAU;AAEzB,QAAM,EAAE,cAAc,IAAI,SAAS;AACnC,QAAM,SAAS,kBAAkB;AACjC,QAAM,qBAAqB,SAAS,YAAY;AAChD,QAAM,CAAC,mBAAmB,oBAAoB,IAAI,SAAS,KAAK;AAEhE,YAAU,MAAM;AACd,QAAI,OAAO,WAAW,YAAa;AACnC,UAAM,aAAa,OAAO,WAAW,qBAAqB;AAC1D,UAAM,qBAAqB,MAAM,qBAAqB,WAAW,OAAO;AAExE,uBAAmB;AACnB,eAAW,iBAAiB,UAAU,kBAAkB;AAExD,WAAO,MAAM;AACX,iBAAW,oBAAoB,UAAU,kBAAkB;AAAA,IAC7D;AAAA,EACF,GAAG,CAAC,CAAC;AAEL,YAAU,MAAM;AACd,aAAS,YAAY;AAAA,EACvB,GAAG,CAAC,cAAc,QAAQ,CAAC;AAE3B,YAAU,MAAM;AACd,aAAS,YAAY;AAAA,EACvB,GAAG,CAAC,cAAc,QAAQ,CAAC;AAE3B,QAAM,YAAY;AAAA,IAChB,CAAC,eAA2B;AAC1B,UAAI,eAAe;AACjB,sBAAc,UAAU;AAAA,MAC1B,OAAO;AACL,cAAM,UAAU;AAAA,UACd,GAAG;AAAA,UACH,MAAM;AAAA,UACN,UAAU;AAAA,UACV,WAAW;AAAA,YACT,MAAM,WAAW;AAAA,YACjB,OAAO;AAAA,YACP,QAAQ;AAAA,YACR,OAAO;AAAA,UACT;AAAA,QACF;AACA,iBAAS,CAAC,QAAQ,QAAQ,SAAS,GAAG,CAAC;AAAA,MACzC;AAAA,IACF;AAAA,IACA,CAAC,UAAU,aAAa;AAAA,EAC1B;AAEA,QAAM,oBAAoB;AAAA,IACxB,CAAC,YAA0B;AACzB,YAAM,YAAY,iBAAiB,SAAS,eAAe,OAAO;AAClE,eAAS,SAAS;AAClB,UAAI,mBAAmB;AACrB,0BAAkB,SAAS;AAAA,MAC7B;AAAA,IACF;AAAA,IACA,CAAC,UAAU,iBAAiB;AAAA,EAC9B;AAEA,QAAM,oBAAoB;AAAA,IACxB,CAAC,YAA0B;AACzB,YAAM,YAAY,iBAAiB,SAAS,eAAe,OAAO;AAClE,eAAS,SAAS;AAClB,UAAI,mBAAmB;AACrB,0BAAkB,SAAS;AAAA,MAC7B;AAAA,IACF;AAAA,IACA,CAAC,UAAU,iBAAiB;AAAA,EAC9B;AAEA,QAAM,YAAY;AAAA,IAChB,OAAO;AAAA,MACL,OAAO;AAAA,MACP,KAAK;AAAA,MACL,UAAU;AAAA,MACV,WAAW;AAAA,MACX,aAAa;AAAA,MACb,eAAe;AAAA,MACf,cAAc;AAAA,MACd,cAAc;AAAA,MACd,cAAc;AAAA,IAChB;AAAA,IACA,CAAC;AAAA,EACH;AAEA,QAAM,YAAY;AAAA,IAChB,OAAO;AAAA,MACL,oBAAoB;AAAA,IACtB;AAAA,IACA,CAAC;AAAA,EACH;AAEA,SACE,oBAAC,SAAI,WAAW,4BAA4B,SAAS,IAAI,OAAO,EAAE,OAAO,GACvE;AAAA,IAAC;AAAA;AAAA,MACC;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA,eAAe;AAAA,MACf,eAAe;AAAA,MACf,WAAW,WAAW,YAAY;AAAA,MAClC,aAAa;AAAA,MACb,aAAa;AAAA,MACb,gBAAgB,eAAe;AAAA,MAC/B,SAAO;AAAA,MACP,gBAAgB;AAAA,QACd,SAAS;AAAA,QACT,SAAS,oBAAoB,MAAM;AAAA,MACrC;AAAA,MACA,SAAS;AAAA,MACT,SAAS;AAAA,MACT,oBAAoB;AAAA,QAClB,MAAM;AAAA,QACN,UAAU;AAAA,QACV,WAAW;AAAA,UACT,MAAM,WAAW;AAAA,UACjB,OAAO;AAAA,UACP,QAAQ;AAAA,UACR,OAAO;AAAA,QACT;AAAA,MACF;AAAA,MACA,gBAAgB;AAAA,MAChB,kBAAkB;AAAA,MAClB,oBAAoB;AAAA,MACpB,YAAY,EAAE,iBAAiB,KAAK;AAAA,MAEpC;AAAA;AAAA,UAAC;AAAA;AAAA,YACC,SAAS,kBAAkB;AAAA,YAC3B,KAAK;AAAA,YACL,MAAM;AAAA,YACN,OAAO;AAAA;AAAA,QACT;AAAA,QAEA;AAAA,UAAC;AAAA;AAAA,YACC,UAAU;AAAA,YACV,aAAa;AAAA,YACb,iBAAiB;AAAA,YACjB,UAAU,oBAAoB,iBAAiB;AAAA,YAC/C,WAAW,2IAA2I,oBAAoB,iCAAiC,EAAE;AAAA;AAAA,QAC/M;AAAA,QAEC,CAAC,qBACA;AAAA,UAAC;AAAA;AAAA,YACC,iBAAiB;AAAA,YACjB,WAAW,CAAC,SAAS;AACnB,oBAAM,SAAU,KAAK,MAAM,UAAU;AACrC,qBAAO,cAAc,MAAM,GAAG,OAAO,cAAc,YAAY;AAAA,YACjE;AAAA,YACA,WAAU;AAAA,YACV,UAAS;AAAA,YACT,WAAU;AAAA;AAAA,QACZ;AAAA,QAGD,CAAC,YAAY,CAAC,qBACb,oBAAC,SAAM,UAAS,YAAW,OAAO,EAAE,QAAQ,GAAG,GAC7C,8BAAC,SAAI,WAAU,+DACb,8BAAC,OAAE,WAAU,6CACV,YAAE,+BAA+B,GACpC,GACF,GACF;AAAA,QAGD,YAAY,CAAC,qBACZ,oBAAC,SAAM,UAAS,YAAW,OAAO,EAAE,QAAQ,GAAG,GAC7C,8BAAC,SAAM,QAAO,eAAc,MAAM,oBAAC,SAAM,eAAY,QAAO,GAAI,WAAU,YACxE,8BAAC,oBAAiB,WAAU,eACzB,YAAE,8BAA8B,GACnC,GACF,GACF;AAAA;AAAA;AAAA,EAEJ,GACF;AAEJ;",
6
6
  "names": []
7
7
  }
@@ -96,7 +96,7 @@ function FormFieldArrayEditor({
96
96
  }
97
97
  )
98
98
  ] }),
99
- isJsonSchemaFormat && /* @__PURE__ */ jsx(Alert, { variant: "info", children: /* @__PURE__ */ jsx(AlertDescription, { className: "text-xs", children: t("workflows.fieldEditors.formFields.jsonSchemaNotice") }) }),
99
+ isJsonSchemaFormat && /* @__PURE__ */ jsx(Alert, { status: "information", children: /* @__PURE__ */ jsx(AlertDescription, { className: "text-xs", children: t("workflows.fieldEditors.formFields.jsonSchemaNotice") }) }),
100
100
  formFields.length === 0 ? /* @__PURE__ */ jsx("div", { className: "p-4 text-center text-sm text-muted-foreground bg-muted rounded-lg border", children: t("workflows.fieldEditors.formFields.emptyState") }) : /* @__PURE__ */ jsx("div", { className: "space-y-2", children: formFields.map((field, index) => {
101
101
  const isExpanded = expandedIndices.has(index);
102
102
  return /* @__PURE__ */ jsxs("div", { className: "border border-gray-200 rounded-lg bg-gray-50", children: [
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../../src/modules/workflows/components/fields/FormFieldArrayEditor.tsx"],
4
- "sourcesContent": ["'use client'\n\nimport { useState } 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 { Input } from '@open-mercato/ui/primitives/input'\nimport { Label } from '@open-mercato/ui/primitives/label'\nimport {\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n} from '@open-mercato/ui/primitives/select'\nimport { Alert, AlertDescription } from '@open-mercato/ui/primitives/alert'\nimport { ChevronDown, Plus, Trash2 } from 'lucide-react'\nimport type { CrudCustomFieldRenderProps } from '@open-mercato/ui/backend/CrudForm'\n\n/**\n * Form field definition structure\n */\nexport interface FormField {\n name: string\n type: string\n label: string\n required: boolean\n placeholder?: string\n options?: string[]\n defaultValue?: string\n}\n\ninterface FormFieldArrayEditorProps extends CrudCustomFieldRenderProps {\n value: FormField[]\n isJsonSchemaFormat?: boolean\n}\n\n/**\n * FormFieldArrayEditor - Custom field component for managing UserTask form fields\n *\n * Provides an interface to add, edit, and remove form field definitions for user tasks.\n * Supports 12 field types with conditional options for select/radio types.\n *\n * Displays a warning banner if the form was converted from JSON Schema format.\n *\n * Used by NodeEditDialog (UserTask type only)\n */\nexport function FormFieldArrayEditor({\n id,\n value = [],\n error,\n setValue,\n disabled,\n isJsonSchemaFormat = false,\n}: FormFieldArrayEditorProps) {\n const t = useT()\n const { confirm, ConfirmDialogElement } = useConfirmDialog()\n const [expandedIndices, setExpandedIndices] = useState<Set<number>>(new Set())\n\n const formFields = Array.isArray(value) ? value : []\n\n const toggleExpanded = (index: number) => {\n const newExpanded = new Set(expandedIndices)\n if (newExpanded.has(index)) {\n newExpanded.delete(index)\n } else {\n newExpanded.add(index)\n }\n setExpandedIndices(newExpanded)\n }\n\n const addFormField = () => {\n const newField: FormField = {\n name: `field_${Date.now()}`,\n type: 'text',\n label: t('workflows.form.newField'),\n required: false,\n placeholder: '',\n }\n const newFields = [...formFields, newField]\n setValue(newFields)\n\n // Auto-expand the newly added field\n const newExpanded = new Set(expandedIndices)\n newExpanded.add(formFields.length)\n setExpandedIndices(newExpanded)\n }\n\n const removeFormField = async (index: number) => {\n const confirmed = await confirm({\n title: t('workflows.fieldEditors.formFields.removeField'),\n text: t('workflows.fieldEditors.formFields.confirmRemove'),\n variant: 'destructive',\n })\n if (!confirmed) return\n\n const newFields = formFields.filter((_, i) => i !== index)\n setValue(newFields)\n\n // Remove from expanded set\n const newExpanded = new Set(expandedIndices)\n newExpanded.delete(index)\n setExpandedIndices(newExpanded)\n }\n\n const updateFormField = (index: number, fieldKey: keyof FormField, fieldValue: any) => {\n const updated = [...formFields]\n updated[index] = { ...updated[index], [fieldKey]: fieldValue }\n setValue(updated)\n }\n\n return (\n <div className=\"space-y-3\">\n <div className=\"flex flex-col gap-3 sm:flex-row sm:items-center sm:justify-between\">\n <div>\n <Label className=\"text-sm font-semibold\">{t('workflows.fieldEditors.formFields.title')} ({formFields.length})</Label>\n <p className=\"text-xs text-muted-foreground mt-0.5\">\n {t('workflows.fieldEditors.formFields.description')}\n </p>\n {error && <p className=\"text-xs text-status-error-text mt-1\">{error}</p>}\n </div>\n <Button\n type=\"button\"\n size=\"sm\"\n onClick={addFormField}\n disabled={disabled}\n className=\"w-full sm:w-auto\"\n >\n <Plus className=\"size-3 mr-1\" />\n {t('workflows.fieldEditors.formFields.addField')}\n </Button>\n </div>\n\n {/* JSON Schema Format Notice */}\n {isJsonSchemaFormat && (\n <Alert variant=\"info\">\n <AlertDescription className=\"text-xs\">\n {t('workflows.fieldEditors.formFields.jsonSchemaNotice')}\n </AlertDescription>\n </Alert>\n )}\n\n {formFields.length === 0 ? (\n <div className=\"p-4 text-center text-sm text-muted-foreground bg-muted rounded-lg border\">\n {t('workflows.fieldEditors.formFields.emptyState')}\n </div>\n ) : (\n <div className=\"space-y-2\">\n {formFields.map((field, index) => {\n const isExpanded = expandedIndices.has(index)\n return (\n <div key={index} className=\"border border-gray-200 rounded-lg bg-gray-50\">\n {/* Collapsed Header */}\n <button\n type=\"button\"\n onClick={() => toggleExpanded(index)}\n disabled={disabled}\n className=\"w-full px-4 py-3 text-left flex items-center justify-between hover:bg-gray-100 transition-colors rounded-t-lg disabled:opacity-50\"\n >\n <div className=\"flex-1\">\n <div className=\"flex flex-wrap items-center gap-2\">\n <span className=\"text-sm font-semibold text-gray-900\">\n {field.label || field.name}\n </span>\n <Badge variant=\"secondary\" className=\"text-xs\">\n {field.type}\n </Badge>\n {field.required && (\n <Badge variant=\"destructive\" className=\"text-xs text-white\">\n {t('workflows.form.required')}\n </Badge>\n )}\n </div>\n <p className=\"text-xs text-gray-600 mt-1\">\n Field name: <code className=\"bg-white px-1 rounded\">{field.name}</code>\n </p>\n </div>\n <ChevronDown\n className={`w-5 h-5 text-gray-400 transition-transform ${isExpanded ? 'rotate-180' : ''}`}\n />\n </button>\n\n {/* Expanded Content */}\n {isExpanded && (\n <div className=\"px-4 pb-4 space-y-3 border-t border-gray-200 bg-white\">\n {/* Field Name */}\n <div className=\"pt-3\">\n <Label htmlFor={`${id}-${index}-name`} className=\"text-xs font-medium mb-1\">\n {t('workflows.fieldEditors.formFields.fieldName')} *\n </Label>\n <Input\n id={`${id}-${index}-name`}\n type=\"text\"\n value={field.name}\n onChange={(e) => updateFormField(index, 'name', e.target.value)}\n placeholder={t('workflows.fieldEditors.formFields.fieldNamePlaceholder')}\n className=\"text-xs\"\n disabled={disabled}\n />\n <p className=\"text-xs text-muted-foreground mt-0.5\">{t('workflows.fieldEditors.formFields.fieldNameHint')}</p>\n </div>\n\n {/* Field Label */}\n <div>\n <Label htmlFor={`${id}-${index}-label`} className=\"text-xs font-medium mb-1\">\n {t('workflows.fieldEditors.formFields.fieldLabel')} *\n </Label>\n <Input\n id={`${id}-${index}-label`}\n type=\"text\"\n value={field.label}\n onChange={(e) => updateFormField(index, 'label', e.target.value)}\n placeholder={t('workflows.fieldEditors.formFields.fieldLabelPlaceholder')}\n className=\"text-xs\"\n disabled={disabled}\n />\n <p className=\"text-xs text-muted-foreground mt-0.5\">{t('workflows.fieldEditors.formFields.fieldLabelHint')}</p>\n </div>\n\n {/* Field Type */}\n <div>\n <Label htmlFor={`${id}-${index}-type`} className=\"text-xs font-medium mb-1\">\n {t('workflows.fieldEditors.formFields.fieldType')} *\n </Label>\n <Select\n value={field.type}\n onValueChange={(value) => updateFormField(index, 'type', value)}\n disabled={disabled}\n >\n <SelectTrigger id={`${id}-${index}-type`}>\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n <SelectItem value=\"text\">{t('workflows.form.fieldTypes.text')}</SelectItem>\n <SelectItem value=\"number\">{t('workflows.form.fieldTypes.number')}</SelectItem>\n <SelectItem value=\"email\">{t('workflows.form.fieldTypes.email')}</SelectItem>\n <SelectItem value=\"tel\">{t('workflows.form.fieldTypes.tel')}</SelectItem>\n <SelectItem value=\"url\">{t('workflows.form.fieldTypes.url')}</SelectItem>\n <SelectItem value=\"textarea\">{t('workflows.form.fieldTypes.textarea')}</SelectItem>\n <SelectItem value=\"select\">{t('workflows.form.fieldTypes.select')}</SelectItem>\n <SelectItem value=\"radio\">{t('workflows.form.fieldTypes.radio')}</SelectItem>\n <SelectItem value=\"checkbox\">{t('workflows.form.fieldTypes.checkbox')}</SelectItem>\n <SelectItem value=\"date\">{t('workflows.form.fieldTypes.date')}</SelectItem>\n <SelectItem value=\"time\">{t('workflows.form.fieldTypes.time')}</SelectItem>\n <SelectItem value=\"datetime-local\">{t('workflows.form.fieldTypes.datetime-local')}</SelectItem>\n </SelectContent>\n </Select>\n </div>\n\n {/* Placeholder */}\n <div>\n <Label htmlFor={`${id}-${index}-placeholder`} className=\"text-xs font-medium mb-1\">\n {t('workflows.fieldEditors.formFields.placeholder')}\n </Label>\n <Input\n id={`${id}-${index}-placeholder`}\n type=\"text\"\n value={field.placeholder || ''}\n onChange={(e) => updateFormField(index, 'placeholder', e.target.value)}\n placeholder={t('workflows.fieldEditors.formFields.placeholderPlaceholder')}\n className=\"text-xs\"\n disabled={disabled}\n />\n </div>\n\n {/* Default Value */}\n <div>\n <Label htmlFor={`${id}-${index}-defaultValue`} className=\"text-xs font-medium mb-1\">\n {t('workflows.fieldEditors.formFields.defaultValue')}\n </Label>\n <Input\n id={`${id}-${index}-defaultValue`}\n type=\"text\"\n value={field.defaultValue || ''}\n onChange={(e) => updateFormField(index, 'defaultValue', e.target.value)}\n placeholder={t('workflows.fieldEditors.formFields.defaultValuePlaceholder')}\n className=\"text-xs\"\n disabled={disabled}\n />\n </div>\n\n {/* Options (for select/radio) */}\n {(field.type === 'select' || field.type === 'radio') && (\n <div>\n <Label htmlFor={`${id}-${index}-options`} className=\"text-xs font-medium mb-1\">\n {t('workflows.fieldEditors.formFields.options')}\n </Label>\n <Input\n id={`${id}-${index}-options`}\n type=\"text\"\n value={field.options?.join(', ') || ''}\n onChange={(e) =>\n updateFormField(\n index,\n 'options',\n e.target.value\n .split(',')\n .map((o) => o.trim())\n .filter(Boolean)\n )\n }\n placeholder={t('workflows.fieldEditors.formFields.optionsPlaceholder')}\n className=\"text-xs\"\n disabled={disabled}\n />\n <p className=\"text-xs text-muted-foreground mt-0.5\">{t('workflows.fieldEditors.formFields.optionsHint')}</p>\n </div>\n )}\n\n {/* Required Checkbox */}\n <div>\n <div className=\"flex items-center gap-2\">\n <input\n type=\"checkbox\"\n id={`${id}-${index}-required`}\n checked={field.required}\n onChange={(e) => updateFormField(index, 'required', e.target.checked)}\n className=\"h-4 w-4 rounded border-gray-300 text-blue-600 focus-visible:ring-ring\"\n disabled={disabled}\n />\n <Label htmlFor={`${id}-${index}-required`} className=\"text-xs font-medium cursor-pointer\">\n {t('workflows.fieldEditors.formFields.requiredField')}\n </Label>\n </div>\n </div>\n\n {/* Delete Button */}\n <div className=\"border-t border-gray-200 pt-3\">\n <Button\n type=\"button\"\n variant=\"destructive\"\n size=\"sm\"\n onClick={() => removeFormField(index)}\n disabled={disabled}\n >\n <Trash2 className=\"size-4 mr-1\" />\n {t('workflows.fieldEditors.formFields.removeField')}\n </Button>\n </div>\n </div>\n )}\n </div>\n )\n })}\n </div>\n )}\n {ConfirmDialogElement}\n </div>\n )\n}\n"],
5
- "mappings": ";AAoHU,SACA,KADA;AAlHV,SAAS,gBAAgB;AACzB,SAAS,YAAY;AACrB,SAAS,wBAAwB;AACjC,SAAS,cAAc;AACvB,SAAS,aAAa;AACtB,SAAS,aAAa;AACtB,SAAS,aAAa;AACtB;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AACP,SAAS,OAAO,wBAAwB;AACxC,SAAS,aAAa,MAAM,cAAc;AA+BnC,SAAS,qBAAqB;AAAA,EACnC;AAAA,EACA,QAAQ,CAAC;AAAA,EACT;AAAA,EACA;AAAA,EACA;AAAA,EACA,qBAAqB;AACvB,GAA8B;AAC5B,QAAM,IAAI,KAAK;AACf,QAAM,EAAE,SAAS,qBAAqB,IAAI,iBAAiB;AAC3D,QAAM,CAAC,iBAAiB,kBAAkB,IAAI,SAAsB,oBAAI,IAAI,CAAC;AAE7E,QAAM,aAAa,MAAM,QAAQ,KAAK,IAAI,QAAQ,CAAC;AAEnD,QAAM,iBAAiB,CAAC,UAAkB;AACxC,UAAM,cAAc,IAAI,IAAI,eAAe;AAC3C,QAAI,YAAY,IAAI,KAAK,GAAG;AAC1B,kBAAY,OAAO,KAAK;AAAA,IAC1B,OAAO;AACL,kBAAY,IAAI,KAAK;AAAA,IACvB;AACA,uBAAmB,WAAW;AAAA,EAChC;AAEA,QAAM,eAAe,MAAM;AACzB,UAAM,WAAsB;AAAA,MAC1B,MAAM,SAAS,KAAK,IAAI,CAAC;AAAA,MACzB,MAAM;AAAA,MACN,OAAO,EAAE,yBAAyB;AAAA,MAClC,UAAU;AAAA,MACV,aAAa;AAAA,IACf;AACA,UAAM,YAAY,CAAC,GAAG,YAAY,QAAQ;AAC1C,aAAS,SAAS;AAGlB,UAAM,cAAc,IAAI,IAAI,eAAe;AAC3C,gBAAY,IAAI,WAAW,MAAM;AACjC,uBAAmB,WAAW;AAAA,EAChC;AAEA,QAAM,kBAAkB,OAAO,UAAkB;AAC/C,UAAM,YAAY,MAAM,QAAQ;AAAA,MAC9B,OAAO,EAAE,+CAA+C;AAAA,MACxD,MAAM,EAAE,iDAAiD;AAAA,MACzD,SAAS;AAAA,IACX,CAAC;AACD,QAAI,CAAC,UAAW;AAEhB,UAAM,YAAY,WAAW,OAAO,CAAC,GAAG,MAAM,MAAM,KAAK;AACzD,aAAS,SAAS;AAGlB,UAAM,cAAc,IAAI,IAAI,eAAe;AAC3C,gBAAY,OAAO,KAAK;AACxB,uBAAmB,WAAW;AAAA,EAChC;AAEA,QAAM,kBAAkB,CAAC,OAAe,UAA2B,eAAoB;AACrF,UAAM,UAAU,CAAC,GAAG,UAAU;AAC9B,YAAQ,KAAK,IAAI,EAAE,GAAG,QAAQ,KAAK,GAAG,CAAC,QAAQ,GAAG,WAAW;AAC7D,aAAS,OAAO;AAAA,EAClB;AAEA,SACE,qBAAC,SAAI,WAAU,aACb;AAAA,yBAAC,SAAI,WAAU,sEACb;AAAA,2BAAC,SACC;AAAA,6BAAC,SAAM,WAAU,yBAAyB;AAAA,YAAE,yCAAyC;AAAA,UAAE;AAAA,UAAG,WAAW;AAAA,UAAO;AAAA,WAAC;AAAA,QAC7G,oBAAC,OAAE,WAAU,wCACV,YAAE,+CAA+C,GACpD;AAAA,QACC,SAAS,oBAAC,OAAE,WAAU,uCAAuC,iBAAM;AAAA,SACtE;AAAA,MACA;AAAA,QAAC;AAAA;AAAA,UACC,MAAK;AAAA,UACL,MAAK;AAAA,UACL,SAAS;AAAA,UACT;AAAA,UACA,WAAU;AAAA,UAEV;AAAA,gCAAC,QAAK,WAAU,eAAc;AAAA,YAC7B,EAAE,4CAA4C;AAAA;AAAA;AAAA,MACjD;AAAA,OACF;AAAA,IAGC,sBACC,oBAAC,SAAM,SAAQ,QACb,8BAAC,oBAAiB,WAAU,WACzB,YAAE,oDAAoD,GACzD,GACF;AAAA,IAGD,WAAW,WAAW,IACrB,oBAAC,SAAI,WAAU,4EACZ,YAAE,8CAA8C,GACnD,IAEA,oBAAC,SAAI,WAAU,aACZ,qBAAW,IAAI,CAAC,OAAO,UAAU;AAChC,YAAM,aAAa,gBAAgB,IAAI,KAAK;AAC5C,aACE,qBAAC,SAAgB,WAAU,gDAEzB;AAAA;AAAA,UAAC;AAAA;AAAA,YACC,MAAK;AAAA,YACL,SAAS,MAAM,eAAe,KAAK;AAAA,YACnC;AAAA,YACA,WAAU;AAAA,YAEV;AAAA,mCAAC,SAAI,WAAU,UACb;AAAA,qCAAC,SAAI,WAAU,qCACb;AAAA,sCAAC,UAAK,WAAU,uCACb,gBAAM,SAAS,MAAM,MACxB;AAAA,kBACA,oBAAC,SAAM,SAAQ,aAAY,WAAU,WAClC,gBAAM,MACT;AAAA,kBACC,MAAM,YACL,oBAAC,SAAM,SAAQ,eAAc,WAAU,sBACpC,YAAE,yBAAyB,GAC9B;AAAA,mBAEJ;AAAA,gBACA,qBAAC,OAAE,WAAU,8BAA6B;AAAA;AAAA,kBAC5B,oBAAC,UAAK,WAAU,yBAAyB,gBAAM,MAAK;AAAA,mBAClE;AAAA,iBACF;AAAA,cACA;AAAA,gBAAC;AAAA;AAAA,kBACC,WAAW,8CAA8C,aAAa,eAAe,EAAE;AAAA;AAAA,cACzF;AAAA;AAAA;AAAA,QACF;AAAA,QAGC,cACC,qBAAC,SAAI,WAAU,yDAEb;AAAA,+BAAC,SAAI,WAAU,QACb;AAAA,iCAAC,SAAM,SAAS,GAAG,EAAE,IAAI,KAAK,SAAS,WAAU,4BAC9C;AAAA,gBAAE,6CAA6C;AAAA,cAAE;AAAA,eACpD;AAAA,YACA;AAAA,cAAC;AAAA;AAAA,gBACC,IAAI,GAAG,EAAE,IAAI,KAAK;AAAA,gBAClB,MAAK;AAAA,gBACL,OAAO,MAAM;AAAA,gBACb,UAAU,CAAC,MAAM,gBAAgB,OAAO,QAAQ,EAAE,OAAO,KAAK;AAAA,gBAC9D,aAAa,EAAE,wDAAwD;AAAA,gBACvE,WAAU;AAAA,gBACV;AAAA;AAAA,YACF;AAAA,YACA,oBAAC,OAAE,WAAU,wCAAwC,YAAE,iDAAiD,GAAE;AAAA,aAC5G;AAAA,UAGA,qBAAC,SACC;AAAA,iCAAC,SAAM,SAAS,GAAG,EAAE,IAAI,KAAK,UAAU,WAAU,4BAC/C;AAAA,gBAAE,8CAA8C;AAAA,cAAE;AAAA,eACrD;AAAA,YACA;AAAA,cAAC;AAAA;AAAA,gBACC,IAAI,GAAG,EAAE,IAAI,KAAK;AAAA,gBAClB,MAAK;AAAA,gBACL,OAAO,MAAM;AAAA,gBACb,UAAU,CAAC,MAAM,gBAAgB,OAAO,SAAS,EAAE,OAAO,KAAK;AAAA,gBAC/D,aAAa,EAAE,yDAAyD;AAAA,gBACxE,WAAU;AAAA,gBACV;AAAA;AAAA,YACF;AAAA,YACA,oBAAC,OAAE,WAAU,wCAAwC,YAAE,kDAAkD,GAAE;AAAA,aAC7G;AAAA,UAGA,qBAAC,SACC;AAAA,iCAAC,SAAM,SAAS,GAAG,EAAE,IAAI,KAAK,SAAS,WAAU,4BAC9C;AAAA,gBAAE,6CAA6C;AAAA,cAAE;AAAA,eACpD;AAAA,YACA;AAAA,cAAC;AAAA;AAAA,gBACC,OAAO,MAAM;AAAA,gBACb,eAAe,CAACA,WAAU,gBAAgB,OAAO,QAAQA,MAAK;AAAA,gBAC9D;AAAA,gBAEA;AAAA,sCAAC,iBAAc,IAAI,GAAG,EAAE,IAAI,KAAK,SAC/B,8BAAC,eAAY,GACf;AAAA,kBACA,qBAAC,iBACC;AAAA,wCAAC,cAAW,OAAM,QAAQ,YAAE,gCAAgC,GAAE;AAAA,oBAC9D,oBAAC,cAAW,OAAM,UAAU,YAAE,kCAAkC,GAAE;AAAA,oBAClE,oBAAC,cAAW,OAAM,SAAS,YAAE,iCAAiC,GAAE;AAAA,oBAChE,oBAAC,cAAW,OAAM,OAAO,YAAE,+BAA+B,GAAE;AAAA,oBAC5D,oBAAC,cAAW,OAAM,OAAO,YAAE,+BAA+B,GAAE;AAAA,oBAC5D,oBAAC,cAAW,OAAM,YAAY,YAAE,oCAAoC,GAAE;AAAA,oBACtE,oBAAC,cAAW,OAAM,UAAU,YAAE,kCAAkC,GAAE;AAAA,oBAClE,oBAAC,cAAW,OAAM,SAAS,YAAE,iCAAiC,GAAE;AAAA,oBAChE,oBAAC,cAAW,OAAM,YAAY,YAAE,oCAAoC,GAAE;AAAA,oBACtE,oBAAC,cAAW,OAAM,QAAQ,YAAE,gCAAgC,GAAE;AAAA,oBAC9D,oBAAC,cAAW,OAAM,QAAQ,YAAE,gCAAgC,GAAE;AAAA,oBAC9D,oBAAC,cAAW,OAAM,kBAAkB,YAAE,0CAA0C,GAAE;AAAA,qBACpF;AAAA;AAAA;AAAA,YACF;AAAA,aACF;AAAA,UAGA,qBAAC,SACC;AAAA,gCAAC,SAAM,SAAS,GAAG,EAAE,IAAI,KAAK,gBAAgB,WAAU,4BACrD,YAAE,+CAA+C,GACpD;AAAA,YACA;AAAA,cAAC;AAAA;AAAA,gBACC,IAAI,GAAG,EAAE,IAAI,KAAK;AAAA,gBAClB,MAAK;AAAA,gBACL,OAAO,MAAM,eAAe;AAAA,gBAC5B,UAAU,CAAC,MAAM,gBAAgB,OAAO,eAAe,EAAE,OAAO,KAAK;AAAA,gBACrE,aAAa,EAAE,0DAA0D;AAAA,gBACzE,WAAU;AAAA,gBACV;AAAA;AAAA,YACF;AAAA,aACF;AAAA,UAGA,qBAAC,SACC;AAAA,gCAAC,SAAM,SAAS,GAAG,EAAE,IAAI,KAAK,iBAAiB,WAAU,4BACtD,YAAE,gDAAgD,GACrD;AAAA,YACA;AAAA,cAAC;AAAA;AAAA,gBACC,IAAI,GAAG,EAAE,IAAI,KAAK;AAAA,gBAClB,MAAK;AAAA,gBACL,OAAO,MAAM,gBAAgB;AAAA,gBAC7B,UAAU,CAAC,MAAM,gBAAgB,OAAO,gBAAgB,EAAE,OAAO,KAAK;AAAA,gBACtE,aAAa,EAAE,2DAA2D;AAAA,gBAC1E,WAAU;AAAA,gBACV;AAAA;AAAA,YACF;AAAA,aACF;AAAA,WAGE,MAAM,SAAS,YAAY,MAAM,SAAS,YAC1C,qBAAC,SACC;AAAA,gCAAC,SAAM,SAAS,GAAG,EAAE,IAAI,KAAK,YAAY,WAAU,4BACjD,YAAE,2CAA2C,GAChD;AAAA,YACA;AAAA,cAAC;AAAA;AAAA,gBACC,IAAI,GAAG,EAAE,IAAI,KAAK;AAAA,gBAClB,MAAK;AAAA,gBACL,OAAO,MAAM,SAAS,KAAK,IAAI,KAAK;AAAA,gBACpC,UAAU,CAAC,MACT;AAAA,kBACE;AAAA,kBACA;AAAA,kBACA,EAAE,OAAO,MACN,MAAM,GAAG,EACT,IAAI,CAAC,MAAM,EAAE,KAAK,CAAC,EACnB,OAAO,OAAO;AAAA,gBACnB;AAAA,gBAEF,aAAa,EAAE,sDAAsD;AAAA,gBACrE,WAAU;AAAA,gBACV;AAAA;AAAA,YACF;AAAA,YACA,oBAAC,OAAE,WAAU,wCAAwC,YAAE,+CAA+C,GAAE;AAAA,aAC1G;AAAA,UAIF,oBAAC,SACC,+BAAC,SAAI,WAAU,2BACb;AAAA;AAAA,cAAC;AAAA;AAAA,gBACC,MAAK;AAAA,gBACL,IAAI,GAAG,EAAE,IAAI,KAAK;AAAA,gBAClB,SAAS,MAAM;AAAA,gBACf,UAAU,CAAC,MAAM,gBAAgB,OAAO,YAAY,EAAE,OAAO,OAAO;AAAA,gBACpE,WAAU;AAAA,gBACV;AAAA;AAAA,YACF;AAAA,YACA,oBAAC,SAAM,SAAS,GAAG,EAAE,IAAI,KAAK,aAAa,WAAU,sCAClD,YAAE,iDAAiD,GACtD;AAAA,aACF,GACF;AAAA,UAGA,oBAAC,SAAI,WAAU,iCACb;AAAA,YAAC;AAAA;AAAA,cACC,MAAK;AAAA,cACL,SAAQ;AAAA,cACR,MAAK;AAAA,cACL,SAAS,MAAM,gBAAgB,KAAK;AAAA,cACpC;AAAA,cAEA;AAAA,oCAAC,UAAO,WAAU,eAAc;AAAA,gBAC/B,EAAE,+CAA+C;AAAA;AAAA;AAAA,UACpD,GACF;AAAA,WACF;AAAA,WA5LM,KA8LV;AAAA,IAEJ,CAAC,GACH;AAAA,IAED;AAAA,KACH;AAEJ;",
4
+ "sourcesContent": ["'use client'\n\nimport { useState } 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 { Input } from '@open-mercato/ui/primitives/input'\nimport { Label } from '@open-mercato/ui/primitives/label'\nimport {\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n} from '@open-mercato/ui/primitives/select'\nimport { Alert, AlertDescription } from '@open-mercato/ui/primitives/alert'\nimport { ChevronDown, Plus, Trash2 } from 'lucide-react'\nimport type { CrudCustomFieldRenderProps } from '@open-mercato/ui/backend/CrudForm'\n\n/**\n * Form field definition structure\n */\nexport interface FormField {\n name: string\n type: string\n label: string\n required: boolean\n placeholder?: string\n options?: string[]\n defaultValue?: string\n}\n\ninterface FormFieldArrayEditorProps extends CrudCustomFieldRenderProps {\n value: FormField[]\n isJsonSchemaFormat?: boolean\n}\n\n/**\n * FormFieldArrayEditor - Custom field component for managing UserTask form fields\n *\n * Provides an interface to add, edit, and remove form field definitions for user tasks.\n * Supports 12 field types with conditional options for select/radio types.\n *\n * Displays a warning banner if the form was converted from JSON Schema format.\n *\n * Used by NodeEditDialog (UserTask type only)\n */\nexport function FormFieldArrayEditor({\n id,\n value = [],\n error,\n setValue,\n disabled,\n isJsonSchemaFormat = false,\n}: FormFieldArrayEditorProps) {\n const t = useT()\n const { confirm, ConfirmDialogElement } = useConfirmDialog()\n const [expandedIndices, setExpandedIndices] = useState<Set<number>>(new Set())\n\n const formFields = Array.isArray(value) ? value : []\n\n const toggleExpanded = (index: number) => {\n const newExpanded = new Set(expandedIndices)\n if (newExpanded.has(index)) {\n newExpanded.delete(index)\n } else {\n newExpanded.add(index)\n }\n setExpandedIndices(newExpanded)\n }\n\n const addFormField = () => {\n const newField: FormField = {\n name: `field_${Date.now()}`,\n type: 'text',\n label: t('workflows.form.newField'),\n required: false,\n placeholder: '',\n }\n const newFields = [...formFields, newField]\n setValue(newFields)\n\n // Auto-expand the newly added field\n const newExpanded = new Set(expandedIndices)\n newExpanded.add(formFields.length)\n setExpandedIndices(newExpanded)\n }\n\n const removeFormField = async (index: number) => {\n const confirmed = await confirm({\n title: t('workflows.fieldEditors.formFields.removeField'),\n text: t('workflows.fieldEditors.formFields.confirmRemove'),\n variant: 'destructive',\n })\n if (!confirmed) return\n\n const newFields = formFields.filter((_, i) => i !== index)\n setValue(newFields)\n\n // Remove from expanded set\n const newExpanded = new Set(expandedIndices)\n newExpanded.delete(index)\n setExpandedIndices(newExpanded)\n }\n\n const updateFormField = (index: number, fieldKey: keyof FormField, fieldValue: any) => {\n const updated = [...formFields]\n updated[index] = { ...updated[index], [fieldKey]: fieldValue }\n setValue(updated)\n }\n\n return (\n <div className=\"space-y-3\">\n <div className=\"flex flex-col gap-3 sm:flex-row sm:items-center sm:justify-between\">\n <div>\n <Label className=\"text-sm font-semibold\">{t('workflows.fieldEditors.formFields.title')} ({formFields.length})</Label>\n <p className=\"text-xs text-muted-foreground mt-0.5\">\n {t('workflows.fieldEditors.formFields.description')}\n </p>\n {error && <p className=\"text-xs text-status-error-text mt-1\">{error}</p>}\n </div>\n <Button\n type=\"button\"\n size=\"sm\"\n onClick={addFormField}\n disabled={disabled}\n className=\"w-full sm:w-auto\"\n >\n <Plus className=\"size-3 mr-1\" />\n {t('workflows.fieldEditors.formFields.addField')}\n </Button>\n </div>\n\n {/* JSON Schema Format Notice */}\n {isJsonSchemaFormat && (\n <Alert status=\"information\">\n <AlertDescription className=\"text-xs\">\n {t('workflows.fieldEditors.formFields.jsonSchemaNotice')}\n </AlertDescription>\n </Alert>\n )}\n\n {formFields.length === 0 ? (\n <div className=\"p-4 text-center text-sm text-muted-foreground bg-muted rounded-lg border\">\n {t('workflows.fieldEditors.formFields.emptyState')}\n </div>\n ) : (\n <div className=\"space-y-2\">\n {formFields.map((field, index) => {\n const isExpanded = expandedIndices.has(index)\n return (\n <div key={index} className=\"border border-gray-200 rounded-lg bg-gray-50\">\n {/* Collapsed Header */}\n <button\n type=\"button\"\n onClick={() => toggleExpanded(index)}\n disabled={disabled}\n className=\"w-full px-4 py-3 text-left flex items-center justify-between hover:bg-gray-100 transition-colors rounded-t-lg disabled:opacity-50\"\n >\n <div className=\"flex-1\">\n <div className=\"flex flex-wrap items-center gap-2\">\n <span className=\"text-sm font-semibold text-gray-900\">\n {field.label || field.name}\n </span>\n <Badge variant=\"secondary\" className=\"text-xs\">\n {field.type}\n </Badge>\n {field.required && (\n <Badge variant=\"destructive\" className=\"text-xs text-white\">\n {t('workflows.form.required')}\n </Badge>\n )}\n </div>\n <p className=\"text-xs text-gray-600 mt-1\">\n Field name: <code className=\"bg-white px-1 rounded\">{field.name}</code>\n </p>\n </div>\n <ChevronDown\n className={`w-5 h-5 text-gray-400 transition-transform ${isExpanded ? 'rotate-180' : ''}`}\n />\n </button>\n\n {/* Expanded Content */}\n {isExpanded && (\n <div className=\"px-4 pb-4 space-y-3 border-t border-gray-200 bg-white\">\n {/* Field Name */}\n <div className=\"pt-3\">\n <Label htmlFor={`${id}-${index}-name`} className=\"text-xs font-medium mb-1\">\n {t('workflows.fieldEditors.formFields.fieldName')} *\n </Label>\n <Input\n id={`${id}-${index}-name`}\n type=\"text\"\n value={field.name}\n onChange={(e) => updateFormField(index, 'name', e.target.value)}\n placeholder={t('workflows.fieldEditors.formFields.fieldNamePlaceholder')}\n className=\"text-xs\"\n disabled={disabled}\n />\n <p className=\"text-xs text-muted-foreground mt-0.5\">{t('workflows.fieldEditors.formFields.fieldNameHint')}</p>\n </div>\n\n {/* Field Label */}\n <div>\n <Label htmlFor={`${id}-${index}-label`} className=\"text-xs font-medium mb-1\">\n {t('workflows.fieldEditors.formFields.fieldLabel')} *\n </Label>\n <Input\n id={`${id}-${index}-label`}\n type=\"text\"\n value={field.label}\n onChange={(e) => updateFormField(index, 'label', e.target.value)}\n placeholder={t('workflows.fieldEditors.formFields.fieldLabelPlaceholder')}\n className=\"text-xs\"\n disabled={disabled}\n />\n <p className=\"text-xs text-muted-foreground mt-0.5\">{t('workflows.fieldEditors.formFields.fieldLabelHint')}</p>\n </div>\n\n {/* Field Type */}\n <div>\n <Label htmlFor={`${id}-${index}-type`} className=\"text-xs font-medium mb-1\">\n {t('workflows.fieldEditors.formFields.fieldType')} *\n </Label>\n <Select\n value={field.type}\n onValueChange={(value) => updateFormField(index, 'type', value)}\n disabled={disabled}\n >\n <SelectTrigger id={`${id}-${index}-type`}>\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n <SelectItem value=\"text\">{t('workflows.form.fieldTypes.text')}</SelectItem>\n <SelectItem value=\"number\">{t('workflows.form.fieldTypes.number')}</SelectItem>\n <SelectItem value=\"email\">{t('workflows.form.fieldTypes.email')}</SelectItem>\n <SelectItem value=\"tel\">{t('workflows.form.fieldTypes.tel')}</SelectItem>\n <SelectItem value=\"url\">{t('workflows.form.fieldTypes.url')}</SelectItem>\n <SelectItem value=\"textarea\">{t('workflows.form.fieldTypes.textarea')}</SelectItem>\n <SelectItem value=\"select\">{t('workflows.form.fieldTypes.select')}</SelectItem>\n <SelectItem value=\"radio\">{t('workflows.form.fieldTypes.radio')}</SelectItem>\n <SelectItem value=\"checkbox\">{t('workflows.form.fieldTypes.checkbox')}</SelectItem>\n <SelectItem value=\"date\">{t('workflows.form.fieldTypes.date')}</SelectItem>\n <SelectItem value=\"time\">{t('workflows.form.fieldTypes.time')}</SelectItem>\n <SelectItem value=\"datetime-local\">{t('workflows.form.fieldTypes.datetime-local')}</SelectItem>\n </SelectContent>\n </Select>\n </div>\n\n {/* Placeholder */}\n <div>\n <Label htmlFor={`${id}-${index}-placeholder`} className=\"text-xs font-medium mb-1\">\n {t('workflows.fieldEditors.formFields.placeholder')}\n </Label>\n <Input\n id={`${id}-${index}-placeholder`}\n type=\"text\"\n value={field.placeholder || ''}\n onChange={(e) => updateFormField(index, 'placeholder', e.target.value)}\n placeholder={t('workflows.fieldEditors.formFields.placeholderPlaceholder')}\n className=\"text-xs\"\n disabled={disabled}\n />\n </div>\n\n {/* Default Value */}\n <div>\n <Label htmlFor={`${id}-${index}-defaultValue`} className=\"text-xs font-medium mb-1\">\n {t('workflows.fieldEditors.formFields.defaultValue')}\n </Label>\n <Input\n id={`${id}-${index}-defaultValue`}\n type=\"text\"\n value={field.defaultValue || ''}\n onChange={(e) => updateFormField(index, 'defaultValue', e.target.value)}\n placeholder={t('workflows.fieldEditors.formFields.defaultValuePlaceholder')}\n className=\"text-xs\"\n disabled={disabled}\n />\n </div>\n\n {/* Options (for select/radio) */}\n {(field.type === 'select' || field.type === 'radio') && (\n <div>\n <Label htmlFor={`${id}-${index}-options`} className=\"text-xs font-medium mb-1\">\n {t('workflows.fieldEditors.formFields.options')}\n </Label>\n <Input\n id={`${id}-${index}-options`}\n type=\"text\"\n value={field.options?.join(', ') || ''}\n onChange={(e) =>\n updateFormField(\n index,\n 'options',\n e.target.value\n .split(',')\n .map((o) => o.trim())\n .filter(Boolean)\n )\n }\n placeholder={t('workflows.fieldEditors.formFields.optionsPlaceholder')}\n className=\"text-xs\"\n disabled={disabled}\n />\n <p className=\"text-xs text-muted-foreground mt-0.5\">{t('workflows.fieldEditors.formFields.optionsHint')}</p>\n </div>\n )}\n\n {/* Required Checkbox */}\n <div>\n <div className=\"flex items-center gap-2\">\n <input\n type=\"checkbox\"\n id={`${id}-${index}-required`}\n checked={field.required}\n onChange={(e) => updateFormField(index, 'required', e.target.checked)}\n className=\"h-4 w-4 rounded border-gray-300 text-blue-600 focus-visible:ring-ring\"\n disabled={disabled}\n />\n <Label htmlFor={`${id}-${index}-required`} className=\"text-xs font-medium cursor-pointer\">\n {t('workflows.fieldEditors.formFields.requiredField')}\n </Label>\n </div>\n </div>\n\n {/* Delete Button */}\n <div className=\"border-t border-gray-200 pt-3\">\n <Button\n type=\"button\"\n variant=\"destructive\"\n size=\"sm\"\n onClick={() => removeFormField(index)}\n disabled={disabled}\n >\n <Trash2 className=\"size-4 mr-1\" />\n {t('workflows.fieldEditors.formFields.removeField')}\n </Button>\n </div>\n </div>\n )}\n </div>\n )\n })}\n </div>\n )}\n {ConfirmDialogElement}\n </div>\n )\n}\n"],
5
+ "mappings": "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",
6
6
  "names": ["value"]
7
7
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@open-mercato/core",
3
- "version": "0.6.7-develop.6863.1.61001cf9a8",
3
+ "version": "0.6.7-develop.6869.1.d1ce9999ea",
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.6863.1.61001cf9a8",
258
- "@open-mercato/shared": "0.6.7-develop.6863.1.61001cf9a8",
259
- "@open-mercato/ui": "0.6.7-develop.6863.1.61001cf9a8",
257
+ "@open-mercato/ai-assistant": "0.6.7-develop.6869.1.d1ce9999ea",
258
+ "@open-mercato/shared": "0.6.7-develop.6869.1.d1ce9999ea",
259
+ "@open-mercato/ui": "0.6.7-develop.6869.1.d1ce9999ea",
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.6863.1.61001cf9a8",
265
- "@open-mercato/shared": "0.6.7-develop.6863.1.61001cf9a8",
266
- "@open-mercato/ui": "0.6.7-develop.6863.1.61001cf9a8",
264
+ "@open-mercato/ai-assistant": "0.6.7-develop.6869.1.d1ce9999ea",
265
+ "@open-mercato/shared": "0.6.7-develop.6869.1.d1ce9999ea",
266
+ "@open-mercato/ui": "0.6.7-develop.6869.1.d1ce9999ea",
267
267
  "@testing-library/dom": "^10.4.1",
268
268
  "@testing-library/jest-dom": "^7.0.0",
269
269
  "@testing-library/react": "^16.3.1",
@@ -23,7 +23,7 @@ export default async function AttachmentsConfigurationPage() {
23
23
  <Page>
24
24
  <PageBody className="space-y-6">
25
25
  {partitionsLocked ? (
26
- <Alert variant="warning">
26
+ <Alert status="warning">
27
27
  <AlertTitle>{lockedTitle}</AlertTitle>
28
28
  <AlertDescription>
29
29
  {lockedDescription}{' '}
@@ -235,7 +235,7 @@ export function AuditLogsActions({
235
235
  return (
236
236
  <>
237
237
  {showSelfOnlyHint ? (
238
- <Alert variant="info" className="mb-4">
238
+ <Alert status="information" className="mb-4">
239
239
  <AlertDescription>
240
240
  {t('audit_logs.hint.view_self_only', 'Showing only your own changes. Contact an administrator for broader access.')}
241
241
  </AlertDescription>
@@ -360,7 +360,7 @@ export default function LoginPage() {
360
360
  <input type="hidden" name="tenantId" value={tenantId} />
361
361
  ) : null}
362
362
  {!!translatedRoles.length && (
363
- <Alert variant="info" className="text-center">
363
+ <Alert status="information" className="text-center">
364
364
  <AlertDescription>
365
365
  {translate(
366
366
  translatedRoles.length > 1 ? 'auth.login.requireRolesMessage' : 'auth.login.requireRoleMessage',
@@ -373,7 +373,7 @@ export default function LoginPage() {
373
373
  </Alert>
374
374
  )}
375
375
  {!!translatedFeatures.length && (
376
- <Alert variant="info" className="text-center">
376
+ <Alert status="information" className="text-center">
377
377
  <AlertDescription>
378
378
  {translate('auth.login.featureDenied', "You don't have access to this feature ({feature}). Please contact your administrator.", {
379
379
  feature: translatedFeatures.join(', '),
@@ -8,6 +8,9 @@ type ProductRow = {
8
8
  id: string
9
9
  }
10
10
 
11
+ const FILTERED_IDS_PAGE_SIZE = 100
12
+ const FILTERED_IDS_MAX_PAGES = 1000
13
+
11
14
  type BulkActionContext = {
12
15
  confirm?: (options?: {
13
16
  title?: string
@@ -32,7 +35,7 @@ function readRowId(row: unknown): string | null {
32
35
  }
33
36
 
34
37
  function buildListParams(context: BulkActionContext): Record<string, string> {
35
- const params: Record<string, string> = { pageSize: '100' }
38
+ const params: Record<string, string> = { pageSize: String(FILTERED_IDS_PAGE_SIZE) }
36
39
  const injectionContext = context.injectionContext
37
40
  const search = typeof injectionContext?.search === 'string' ? injectionContext.search.trim() : ''
38
41
  if (search) params.search = search
@@ -106,19 +109,26 @@ async function fetchFilteredProductIds(context: BulkActionContext): Promise<stri
106
109
  const baseParams = buildListParams(context)
107
110
  const productIds = new Set<string>()
108
111
  let page = 1
109
- let totalPages = 1
110
112
 
111
- while (page <= totalPages) {
113
+ // Short-page termination: server-reported `totalPages` is a display value, not a loop
114
+ // bound — it can under-report (capped counts) or drift mid-enumeration. Fail closed at
115
+ // the page ceiling: a partial id set would turn "delete all filtered" into "delete the
116
+ // first N" with no signal to the user.
117
+ for (;;) {
112
118
  const payload = await fetchCrudList<ProductRow>('catalog/products', {
113
119
  ...baseParams,
114
120
  page,
115
121
  })
116
- for (const item of payload.items) {
122
+ const items = Array.isArray(payload.items) ? payload.items : []
123
+ for (const item of items) {
117
124
  if (typeof item?.id === 'string' && item.id.length > 0) {
118
125
  productIds.add(item.id)
119
126
  }
120
127
  }
121
- totalPages = typeof payload.totalPages === 'number' && payload.totalPages > 0 ? payload.totalPages : 1
128
+ if (items.length < FILTERED_IDS_PAGE_SIZE) break
129
+ if (page >= FILTERED_IDS_MAX_PAGES) {
130
+ throw new Error(`[internal] filtered product enumeration exceeded ${FILTERED_IDS_MAX_PAGES} pages; refusing to bulk-delete a partial set`)
131
+ }
122
132
  page += 1
123
133
  }
124
134
 
@@ -463,7 +463,7 @@ export default function ProfileCommunicationChannelsPage() {
463
463
  <p className="text-sm text-muted-foreground">
464
464
  {t(
465
465
  'communication_channels.profile.subtitle',
466
- 'Connect your personal mailbox so outbound messages come from your address and inbound emails land in your unified inbox.',
466
+ 'Connect your communication channels so outbound messages come from your own account and inbound messages land in your unified inbox.',
467
467
  )}
468
468
  </p>
469
469
  </div>
@@ -477,7 +477,7 @@ export default function ProfileCommunicationChannelsPage() {
477
477
  </header>
478
478
 
479
479
  {reauthRows.length > 0 ? (
480
- <Alert variant="warning" className="mb-4">
480
+ <Alert status="warning" className="mb-4">
481
481
  <AlertDescription>
482
482
  {t(
483
483
  'communication_channels.profile.alerts.requiresReauth',
@@ -497,7 +497,7 @@ export default function ProfileCommunicationChannelsPage() {
497
497
  error={errorMessage}
498
498
  emptyState={t(
499
499
  'communication_channels.profile.empty',
500
- 'You have no connected channels yet. Use the "Connect channel" entry above to add Gmail or IMAP.',
500
+ 'You have no connected channels yet. Use one of the Connect buttons above to add a channel.',
501
501
  )}
502
502
  />
503
503
  <ImportHistoryDialog
@@ -736,7 +736,7 @@ function ImportHistoryDialog({ channel, onClose, onQueued }: ImportHistoryDialog
736
736
  </div>
737
737
 
738
738
  {fieldErrors.channelId ? (
739
- <Alert variant="warning">
739
+ <Alert status="warning">
740
740
  <AlertDescription>{fieldErrors.channelId}</AlertDescription>
741
741
  </Alert>
742
742
  ) : null}
@@ -96,7 +96,7 @@
96
96
  "communication_channels.profile.disconnect.description": "Dies entfernt die Verbindung und stoppt die Synchronisierung. Bereits importierte E-Mails bleiben in Ihren Timelines. Sie können den Kanal jederzeit erneut verbinden.",
97
97
  "communication_channels.profile.disconnect.submitting": "Wird getrennt…",
98
98
  "communication_channels.profile.disconnect.title": "Kanal trennen",
99
- "communication_channels.profile.empty": "Sie haben noch keine verbundenen Kanäle. Verwenden Sie oben den Eintrag \"Kanal verbinden\", um Gmail oder IMAP hinzuzufügen.",
99
+ "communication_channels.profile.empty": "Sie haben noch keine verbundenen Kanäle. Verwenden Sie oben eine der Schaltflächen zum Verbinden, um einen Kanal hinzuzufügen.",
100
100
  "communication_channels.profile.flash.connected": "Kanal verbunden.",
101
101
  "communication_channels.profile.flash.connectedWithProvider": "Kanal verbunden ({provider}).",
102
102
  "communication_channels.profile.flash.error": "Kanal konnte nicht verbunden werden.",
@@ -118,7 +118,7 @@
118
118
  "communication_channels.profile.importHistory.submitting": "Wird eingereiht…",
119
119
  "communication_channels.profile.importHistory.title": "Kanalverlauf importieren",
120
120
  "communication_channels.profile.primary": "Primär",
121
- "communication_channels.profile.subtitle": "Verbinden Sie Ihr persönliches Postfach, damit ausgehende Nachrichten von Ihrer Adresse stammen und eingehende E-Mails in Ihrem einheitlichen Posteingang landen.",
121
+ "communication_channels.profile.subtitle": "Verbinden Sie Ihre Kommunikationskanäle, damit ausgehende Nachrichten von Ihrem eigenen Konto stammen und eingehende Nachrichten in Ihrem einheitlichen Posteingang landen.",
122
122
  "communication_channels.profile.tableTitle": "Ihre Kanäle",
123
123
  "communication_channels.profile.title": "Meine Kommunikationskanäle",
124
124
  "communication_channels.push.button.reregister": "Push neu registrieren",
@@ -96,7 +96,7 @@
96
96
  "communication_channels.profile.disconnect.description": "This removes the connection and stops syncing. Emails already imported stay on your timelines. You can reconnect anytime.",
97
97
  "communication_channels.profile.disconnect.submitting": "Disconnecting…",
98
98
  "communication_channels.profile.disconnect.title": "Disconnect channel",
99
- "communication_channels.profile.empty": "You have no connected channels yet. Use the \"Connect channel\" entry above to add Gmail or IMAP.",
99
+ "communication_channels.profile.empty": "You have no connected channels yet. Use one of the Connect buttons above to add a channel.",
100
100
  "communication_channels.profile.flash.connected": "Channel connected.",
101
101
  "communication_channels.profile.flash.connectedWithProvider": "Channel connected ({provider}).",
102
102
  "communication_channels.profile.flash.error": "Failed to connect channel.",
@@ -118,7 +118,7 @@
118
118
  "communication_channels.profile.importHistory.submitting": "Queueing…",
119
119
  "communication_channels.profile.importHistory.title": "Import channel history",
120
120
  "communication_channels.profile.primary": "Primary",
121
- "communication_channels.profile.subtitle": "Connect your personal mailbox so outbound messages come from your address and inbound emails land in your unified inbox.",
121
+ "communication_channels.profile.subtitle": "Connect your communication channels so outbound messages come from your own account and inbound messages land in your unified inbox.",
122
122
  "communication_channels.profile.tableTitle": "Your channels",
123
123
  "communication_channels.profile.title": "My communication channels",
124
124
  "communication_channels.push.button.reregister": "Re-register push",
@@ -96,7 +96,7 @@
96
96
  "communication_channels.profile.disconnect.description": "Esto elimina la conexión y detiene la sincronización. Los correos ya importados permanecen en tus cronologías. Puedes volver a conectarlo cuando quieras.",
97
97
  "communication_channels.profile.disconnect.submitting": "Desconectando…",
98
98
  "communication_channels.profile.disconnect.title": "Desconectar canal",
99
- "communication_channels.profile.empty": "Aún no tienes canales conectados. Usa la opción \"Conectar canal\" de arriba para añadir Gmail o IMAP.",
99
+ "communication_channels.profile.empty": "Aún no tienes canales conectados. Usa uno de los botones de conexión de arriba para añadir un canal.",
100
100
  "communication_channels.profile.flash.connected": "Canal conectado.",
101
101
  "communication_channels.profile.flash.connectedWithProvider": "Canal conectado ({provider}).",
102
102
  "communication_channels.profile.flash.error": "No se pudo conectar el canal.",
@@ -118,7 +118,7 @@
118
118
  "communication_channels.profile.importHistory.submitting": "Encolando…",
119
119
  "communication_channels.profile.importHistory.title": "Importar historial del canal",
120
120
  "communication_channels.profile.primary": "Principal",
121
- "communication_channels.profile.subtitle": "Conecta tu buzón personal para que los mensajes salientes provengan de tu dirección y los correos entrantes lleguen a tu bandeja de entrada unificada.",
121
+ "communication_channels.profile.subtitle": "Conecta tus canales de comunicación para que los mensajes salientes provengan de tu propia cuenta y los mensajes entrantes lleguen a tu bandeja de entrada unificada.",
122
122
  "communication_channels.profile.tableTitle": "Tus canales",
123
123
  "communication_channels.profile.title": "Mis canales de comunicación",
124
124
  "communication_channels.push.button.reregister": "Re-registrar push",
@@ -96,7 +96,7 @@
96
96
  "communication_channels.profile.disconnect.description": "연결을 제거하고 동기화를 중지합니다. 이미 가져온 이메일은 타임라인에 그대로 유지됩니다. 언제든지 다시 연결할 수 있습니다.",
97
97
  "communication_channels.profile.disconnect.submitting": "연결 해제 중…",
98
98
  "communication_channels.profile.disconnect.title": "채널 연결 해제",
99
- "communication_channels.profile.empty": "아직 연결된 채널이 없습니다. 위의 \"채널 연결\" 항목을 사용하여 Gmail이나 IMAP을 추가하세요.",
99
+ "communication_channels.profile.empty": "아직 연결된 채널이 없습니다. 위의 연결 버튼 중 하나를 사용하여 채널을 추가하세요.",
100
100
  "communication_channels.profile.flash.connected": "채널이 연결되었습니다.",
101
101
  "communication_channels.profile.flash.connectedWithProvider": "채널이 연결되었습니다 ({provider}).",
102
102
  "communication_channels.profile.flash.error": "채널 연결에 실패했습니다.",
@@ -118,7 +118,7 @@
118
118
  "communication_channels.profile.importHistory.submitting": "대기열에 추가하는 중…",
119
119
  "communication_channels.profile.importHistory.title": "채널 기록 가져오기",
120
120
  "communication_channels.profile.primary": "기본",
121
- "communication_channels.profile.subtitle": "개인 메일함을 연결하면 발신 메시지가 회원님의 주소에서 전송되고 수신 이메일이 통합 받은편지함에 도착합니다.",
121
+ "communication_channels.profile.subtitle": "커뮤니케이션 채널을 연결하면 발신 메시지가 회원님의 계정에서 전송되고 수신 메시지가 통합 받은편지함에 도착합니다.",
122
122
  "communication_channels.profile.tableTitle": "내 채널",
123
123
  "communication_channels.profile.title": "내 통신 채널",
124
124
  "communication_channels.push.button.reregister": "푸시 다시 등록",
@@ -96,7 +96,7 @@
96
96
  "communication_channels.profile.disconnect.description": "Spowoduje to usunięcie połączenia i zatrzymanie synchronizacji. Już zaimportowane wiadomości pozostaną na osiach czasu. Możesz połączyć ponownie w dowolnej chwili.",
97
97
  "communication_channels.profile.disconnect.submitting": "Rozłączanie…",
98
98
  "communication_channels.profile.disconnect.title": "Rozłącz kanał",
99
- "communication_channels.profile.empty": "Nie masz jeszcze połączonych kanałów. Użyj opcji \"Połącz kanał\" powyżej, aby dodać Gmail lub IMAP.",
99
+ "communication_channels.profile.empty": "Nie masz jeszcze połączonych kanałów. Użyj jednego z przycisków połączenia powyżej, aby dodać kanał.",
100
100
  "communication_channels.profile.flash.connected": "Kanał połączony.",
101
101
  "communication_channels.profile.flash.connectedWithProvider": "Kanał połączony ({provider}).",
102
102
  "communication_channels.profile.flash.error": "Nie udało się połączyć kanału.",
@@ -118,7 +118,7 @@
118
118
  "communication_channels.profile.importHistory.submitting": "Kolejkowanie…",
119
119
  "communication_channels.profile.importHistory.title": "Importuj historię kanału",
120
120
  "communication_channels.profile.primary": "Główny",
121
- "communication_channels.profile.subtitle": "Połącz swoją osobistą skrzynkę pocztową, aby wysyłane wiadomości pochodziły z Twojego adresu, a przychodzące trafiały do Twojej skrzynki odbiorczej.",
121
+ "communication_channels.profile.subtitle": "Połącz swoje kanały komunikacji, aby wysyłane wiadomości pochodziły z Twojego konta, a przychodzące trafiały do Twojej wspólnej skrzynki odbiorczej.",
122
122
  "communication_channels.profile.tableTitle": "Twoje kanały",
123
123
  "communication_channels.profile.title": "Moje kanały komunikacji",
124
124
  "communication_channels.push.button.reregister": "Zarejestruj push ponownie",