@rytass/bpm-core-react 0.17.6 → 0.17.7

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 (98) hide show
  1. package/CHANGELOG.md +33 -0
  2. package/dist/chunks/{FormBuilderView-aBcA-_tt.cjs → FormBuilderView-CUOyS07f.cjs} +2 -2
  3. package/dist/chunks/{FormBuilderView-aBcA-_tt.cjs.map → FormBuilderView-CUOyS07f.cjs.map} +1 -1
  4. package/dist/chunks/{FormBuilderView-BYL42M0d.js → FormBuilderView-ClLnQ1e_.js} +2 -2
  5. package/dist/chunks/{FormBuilderView-BYL42M0d.js.map → FormBuilderView-ClLnQ1e_.js.map} +1 -1
  6. package/dist/chunks/{FormRendererView-cZGOOjU5.js → FormRendererView-BsTwZkqU.js} +207 -198
  7. package/dist/chunks/FormRendererView-BsTwZkqU.js.map +1 -0
  8. package/dist/chunks/FormRendererView-GpsE03np.cjs +4 -0
  9. package/dist/chunks/FormRendererView-GpsE03np.cjs.map +1 -0
  10. package/dist/chunks/approver-filled-form-D1DmqDVP.cjs +2 -0
  11. package/dist/chunks/approver-filled-form-D1DmqDVP.cjs.map +1 -0
  12. package/dist/chunks/approver-filled-form-DuQGPtNB.js +95 -0
  13. package/dist/chunks/approver-filled-form-DuQGPtNB.js.map +1 -0
  14. package/dist/chunks/{compose-DOEaPfEC.cjs → compose-DjEJi5Dv.cjs} +2 -2
  15. package/dist/chunks/{compose-DOEaPfEC.cjs.map → compose-DjEJi5Dv.cjs.map} +1 -1
  16. package/dist/chunks/{compose-v1Vcw9hE.js → compose-WekGZj74.js} +4 -4
  17. package/dist/chunks/{compose-v1Vcw9hE.js.map → compose-WekGZj74.js.map} +1 -1
  18. package/dist/chunks/{designer-DBBrktom.js → designer-D87ILhjz.js} +1664 -1182
  19. package/dist/chunks/designer-D87ILhjz.js.map +1 -0
  20. package/dist/chunks/designer-DESS0CMl.cjs +65 -0
  21. package/dist/chunks/designer-DESS0CMl.cjs.map +1 -0
  22. package/dist/chunks/detail-D49NuNCn.cjs +2 -0
  23. package/dist/chunks/detail-D49NuNCn.cjs.map +1 -0
  24. package/dist/chunks/{detail-B_bSg31B.js → detail-URwxkcro.js} +1036 -847
  25. package/dist/chunks/detail-URwxkcro.js.map +1 -0
  26. package/dist/chunks/{providers-H_vPRsSN.js → providers-B_d5tbCL.js} +178 -167
  27. package/dist/chunks/providers-B_d5tbCL.js.map +1 -0
  28. package/dist/chunks/providers-chuJvMgv.cjs +2 -0
  29. package/dist/chunks/providers-chuJvMgv.cjs.map +1 -0
  30. package/dist/index.cjs +1 -1
  31. package/dist/index.js +1 -1
  32. package/dist/next/index.cjs +1 -1
  33. package/dist/next/index.js +1 -1
  34. package/dist/next/workflow-chat-route.cjs +1 -0
  35. package/dist/next/workflow-chat-route.cjs.map +1 -1
  36. package/dist/next/workflow-chat-route.d.cts +1 -1
  37. package/dist/next/workflow-chat-route.d.ts +1 -1
  38. package/dist/next/workflow-chat-route.js +1 -1
  39. package/dist/next/workflow-chat-route.js.map +1 -1
  40. package/dist/pages/instances/detail/index.cjs +1 -1
  41. package/dist/pages/instances/detail/index.js +1 -1
  42. package/dist/pages/templates/compose/index.cjs +1 -1
  43. package/dist/pages/templates/compose/index.js +1 -1
  44. package/dist/pages/templates/designer/index.cjs +1 -1
  45. package/dist/pages/templates/designer/index.js +1 -1
  46. package/dist/views/forms/builder/index.cjs +1 -1
  47. package/dist/views/forms/builder/index.js +1 -1
  48. package/dist/views/forms/renderer/FormRendererView.d.cts +16 -1
  49. package/dist/views/forms/renderer/FormRendererView.d.ts +16 -1
  50. package/dist/views/forms/renderer/index.cjs +1 -1
  51. package/dist/views/forms/renderer/index.js +1 -1
  52. package/dist/views/inbox/index.cjs +1 -1
  53. package/dist/views/inbox/index.cjs.map +1 -1
  54. package/dist/views/inbox/index.js +109 -99
  55. package/dist/views/inbox/index.js.map +1 -1
  56. package/dist/views/instances/approver-filled-form.d.cts +76 -0
  57. package/dist/views/instances/approver-filled-form.d.ts +76 -0
  58. package/dist/views/instances/detail/index.cjs +1 -1
  59. package/dist/views/instances/detail/index.js +1 -1
  60. package/dist/views/instances/detail/sections/InstanceFormSection.d.cts +30 -2
  61. package/dist/views/instances/detail/sections/InstanceFormSection.d.ts +30 -2
  62. package/dist/views/instances/detail/sections/InstanceHistorySection.d.cts +4 -1
  63. package/dist/views/instances/detail/sections/InstanceHistorySection.d.ts +4 -1
  64. package/dist/views/instances/detail/sections/InstanceTasksSection.d.cts +21 -0
  65. package/dist/views/instances/detail/sections/InstanceTasksSection.d.ts +21 -0
  66. package/dist/views/instances/detail/sections/container-helpers.d.cts +1 -1
  67. package/dist/views/instances/detail/sections/container-helpers.d.ts +1 -1
  68. package/dist/views/instances/detail/sections/shared.d.cts +11 -2
  69. package/dist/views/instances/detail/sections/shared.d.ts +11 -2
  70. package/dist/views/instances/new/index.cjs +1 -1
  71. package/dist/views/instances/new/index.cjs.map +1 -1
  72. package/dist/views/instances/new/index.js +88 -87
  73. package/dist/views/instances/new/index.js.map +1 -1
  74. package/dist/views/instances/viewer-field-access.d.cts +22 -0
  75. package/dist/views/instances/viewer-field-access.d.ts +22 -0
  76. package/dist/views/templates/compose/index.cjs +1 -1
  77. package/dist/views/templates/compose/index.js +1 -1
  78. package/dist/views/templates/designer/field-access-matrix/FieldAccessMatrixDrawer.d.cts +33 -0
  79. package/dist/views/templates/designer/field-access-matrix/FieldAccessMatrixDrawer.d.ts +33 -0
  80. package/dist/views/templates/designer/field-access-matrix/FieldAccessNodeSection.d.cts +20 -0
  81. package/dist/views/templates/designer/field-access-matrix/FieldAccessNodeSection.d.ts +20 -0
  82. package/dist/views/templates/designer/field-access-matrix/field-access-copy.d.cts +22 -0
  83. package/dist/views/templates/designer/field-access-matrix/field-access-copy.d.ts +22 -0
  84. package/dist/views/templates/designer/index.cjs +1 -1
  85. package/dist/views/templates/designer/index.js +1 -1
  86. package/package.json +3 -3
  87. package/dist/chunks/FormRendererView-DRFi_IH7.cjs +0 -4
  88. package/dist/chunks/FormRendererView-DRFi_IH7.cjs.map +0 -1
  89. package/dist/chunks/FormRendererView-cZGOOjU5.js.map +0 -1
  90. package/dist/chunks/designer-CTXMqCD2.cjs +0 -65
  91. package/dist/chunks/designer-CTXMqCD2.cjs.map +0 -1
  92. package/dist/chunks/designer-DBBrktom.js.map +0 -1
  93. package/dist/chunks/detail-BQSVgVlO.cjs +0 -2
  94. package/dist/chunks/detail-BQSVgVlO.cjs.map +0 -1
  95. package/dist/chunks/detail-B_bSg31B.js.map +0 -1
  96. package/dist/chunks/providers-DP7b0TMN.cjs +0 -2
  97. package/dist/chunks/providers-DP7b0TMN.cjs.map +0 -1
  98. package/dist/chunks/providers-H_vPRsSN.js.map +0 -1
@@ -1 +0,0 @@
1
- {"version":3,"file":"detail-B_bSg31B.js","names":["styles","readNodeKindLabel","_readDelegationChain","SECTION_BODY_STYLE","_Fragment","SECTION_BODY_STYLE","_Fragment","SECTION_BODY_STYLE","SECTION_BODY_STYLE","_Fragment","SECTION_BODY_STYLE","_Fragment","useAuth","BPMFormField","isBPMAdminMember","formatMemberLabel","readTaskNodeText","FormRenderer","Fragment$1","ContentHeader","dagre","pdf_preview_module_default","DEFAULT_VIEWPORT_WIDTH","MAX_PAGE_WIDTH","MIN_PAGE_WIDTH","PAGE_HORIZONTAL_PADDING","MIN_SCALE","MAX_SCALE","SCALE_STEP","PDFPreview","viewportRef","useRef","numPages","setNumPages","useState","pageNumber","setPageNumber","scale","setScale","viewportWidth","setViewportWidth","useEffect","viewport","observer","nextWidth","entries","fileUrl","pageWidth","useMemo","availableWidth","loadDocument","useCallback","document","hasPreviousPage","hasNextPage","canZoomOut","canZoomIn","pageLabel","zoomLabel","filename","Button","ChevronLeftIcon","currentPageNumber","Typography","ChevronRightIcon","ZoomOutIcon","currentScale","ZoomInIcon","onDownload","DownloadIcon","Document","PDFPreviewState","Page","message","readDistinctSubmitterMemberId","submittedByMemberId","initiatorMemberId","readSubmittedOnBehalfLabel","submitterMemberId","fields","readName","memberProfilesById","memberId","readDelegationChainStep","from","readStringField","item","to","reason","readDelegationChain","parsed","value","isRecord","record","key","readStringArrayField","readNumberField","isPresentText","isPendingTask","task","readErrorMessage","readFormDataSourceErrorMessage","error","formatFileSize","sizeBytes","readShortHash","hash","readInstanceStateLabel","state","readTaskStatusLabel","status","readTaskDecisionActionLabel","action","readNodeKindLabel$1","type","readNodeDisplayLabel","workflow","node","nodeId","readMemberDisplayText","profile","readTaskAssigneeLabel","delegationChain","assigneeLabel","originalAssigneeLabel","canMemberActOnTask","readReturnTargetOptions","candidate","targetNodeId","edge","targetNode","readMemberOption","readAdhocTargetDraft","useWebhookTarget","trimmedWebhookUrl","webhookUrl","memberIds","isPresentMemberOption","option","readMemberOptionFromValue","email","id","name","readUniqueMemberOption","normalizedSearchText","searchText","matches","options","readTextDescriptionPart","text","readCommentDescriptionPart","readMemberDescriptionPart","fallbackLabel","isActivityDescriptionPart","part","readCurrentActivityStep","firstPendingStepIndex","activitySteps","activityStep","isUserMeaningfulActivity","activityLog","isSequentialTaskCreation","isNotifyWebhookActivity","readActivityPayload","readSequentialActivityPayloadMemberIds","payload","NOTIFY_WEBHOOK_EVENT_TYPES","eventType","readNotifyWebhookEndpointLabel","readTaskDecisionEventLabel","readActivityEventLabel","endpointLabel","isActivityError","formatActivityDateTime","formatDateTime","readActivityDetail","candidateMemberId","previousMemberId","candidateLabel","sequentialMemberIds","assigneeMemberId","originalAssigneeMemberId","candidateMemberIds","comment","decisionLabel","transferToMemberId","arrivedCount","requiredCount","fromNodeId","toNodeId","readActivityDetailParts","taskDecision","taskDecisionsByTaskId","signatureId","signature","signaturesById","signatureVerification","isFutureTimelineNode","representedNodeIds","instanceState","readNodeRuntimeState","tasks","tokens","readFutureTimelineNodes","futureNodes","reachableDistances","readReachableFutureNodeDistances","originalNodeIndexes","index","leftDistance","left","rightDistance","right","futureNodeIds","outgoingNodeIds","nextTargets","groups","readFutureTimelineFrontierNodeIds","mergeFutureNodeDistances","distances","readFutureNodeDistancesFrom","tokenNodeIds","token","pendingTaskNodeIds","representedFrontierNodeIds","activeFrontierNodeIds","startNodeIds","walkFutureNodeDistances","startNodeId","current","restQueue","queue","visitedNodeIds","nextVisitedNodeIds","nextDistances","distance","mergedDistances","currentDistances","readFutureNodeStepTitle","readActivityStepRecords","historySteps","activityLogs","nodeLabel","pendingTaskSteps","futureNodeSteps","END_EVENT_STATUS","nodeTasks","pendingTask","cancelledTask","completedTask","nodeTokens","activeToken","waitingToken","endEventStatus","readMemberProfilesForTimeline","instance","step","adhocDirectives","directive","readAdhocDirectiveTargetMemberIds","resolveMemberProfiles","targetValueJson","readTaskDecisionsForTasks","listTaskDecisions","readLatestTaskDecisionsByTaskId","taskDecisions","currentDecision","decisionsByTaskId","decision","nextDecision","SECTION_BODY_STYLE$5","BUTTON_ROW_STYLE","InstanceFormSection","loading","canResubmitInstance","resubmitFormErrors","values","onUploadAttachment","resubmitFormData","deciding","RefreshCcwIcon","onResubmitInstance","SECTION_BODY_STYLE$4","InstanceAttachmentsSection","attachmentRows","attachments","attachment","attachmentColumns","attachmentActions","FileSearchIcon","onPreview","Table","REJECT_REASON_FORM_STYLE","REJECT_REASON_TEXTAREA_STYLE","MODAL_FORM_STYLE","SECTION_TABLE_STYLE","SECTION_SUBHEADING_STYLE","applyFullWidthTextareaHost","element","ADHOC_MODE_LABELS","ADHOC_MODE_SUPPORTING_TEXT","ADHOC_ON_REJECT_OPTIONS","ADHOC_NOTIFY_TARGET_OPTIONS","InstanceTasksSection","forwardRef","setDeciding","setError","approveComment","setApproveComment","approveModalOpen","setApproveModalOpen","rejectReason","setRejectReason","rejectReasonError","setRejectReasonError","rejectReasonModalOpen","setRejectReasonModalOpen","returnComment","setReturnComment","returnModalOpen","setReturnModalOpen","returnTargetNodeId","setReturnTargetNodeId","transferComment","setTransferComment","transferMember","setTransferMember","transferMemberLoading","setTransferMemberLoading","transferMemberOptions","setTransferMemberOptions","transferModalOpen","setTransferModalOpen","adhocComment","setAdhocComment","adhocMembers","setAdhocMembers","adhocMemberLoading","setAdhocMemberLoading","adhocMemberOptions","setAdhocMemberOptions","adhocModalOpen","setAdhocModalOpen","adhocMode","setAdhocMode","adhocOnReject","setAdhocOnReject","adhocSubmitting","setAdhocSubmitting","adhocTargetKind","setAdhocTargetKind","adhocWebhookUrl","setAdhocWebhookUrl","trimmedRejectReason","trimmedReturnComment","trimmedTransferComment","currentTask","currentMemberId","currentTaskNode","returnTargetOptions","canReturnCurrentTask","canRejectCurrentTask","canTransferCurrentTask","returnCommentRequired","canAddSignerCurrentTask","pendingAdhocDirectives","selectedReturnTargetOption","taskRows","taskColumns","adhocDirectiveRows","readAdhocDirectiveTargetLabel","adhocDirectiveColumns","handleCancelAdhocDirective","handleDecision","decideTask","requestError","onChanged","openApproveModal","closeApproveModal","handleApproveConfirm","openRejectReasonModal","closeRejectReasonModal","openReturnModal","closeReturnModal","openTransferModal","handleSearchTransferMembers","closeTransferModal","searchMembers","searchedMember","handleRejectConfirm","handleTransferConfirm","handleReturnConfirm","resetAdhocModalState","openAdhocModal","mode","handleSearchAdhocMembers","closeAdhocModal","handleAdhocConfirm","targetDraft","member","trimmedAdhocComment","requestAdhocCountersign","requestAdhocPreApproval","configureAdhocStageNotification","configureAdhocCompletionNotification","cancelAdhocDirective","directiveId","ref","isAdhocNotifyMode","adhocConfirmDisabled","selectedAdhocOnRejectOption","selectedAdhocNotifyTargetOption","Modal","Textarea","event","AutoComplete","open","Select","Input","SECTION_BODY_STYLE$3","InstanceSignaturesSection","signatureRows","signatures","signatureColumns","SECTION_BODY_STYLE$2","HISTORY_MEMBER_NAME_STYLE","HISTORY_COMMENT_STYLE","HISTORY_COMMENT_LABEL_STYLE","HISTORY_COMMENT_DANGER_STYLE","joinClassNames","classNames","className","ActivityHistoryStep","rest","displayStatus","forcePending","inlineDescriptionParts","descriptionParts","commentDescriptionParts","stepClasses","orientation","title","Fragment","partIndex","renderActivityDescriptionPart","Tooltip","tooltipProps","InstanceHistorySection","workflowTokens","workflowSnapshot","currentActivityStep","filteredDescriptionParts","Stepper","SECTION_BODY_STYLE$1","CELL_STACK_STYLE","ERROR_DETAIL_STYLE","InstanceWebhookDeliveriesSection","confirming","setConfirming","retrying","setRetrying","rows","deliveries","delivery","columns","readNodeLabel","WebhookDeliveryStatusBadge","readDeliveryTimeLabel","actions","ResetIcon","handleConfirmRetry","onRetry","retryError","Badge","WEBHOOK_DELIVERY_POLL_INTERVAL_MS","WEBHOOK_DELIVERY_POLL_LIMIT","FLOW_NODE_LAYOUT_WIDTH","FLOW_NODE_LAYOUT_HEIGHT","FLOW_MODAL_BODY_STYLE","FLOW_CANVAS_STYLE","NODE_STYLE","NODE_STATUS_STYLE","NODE_SECONDARY_STYLE","NODE_HANDLE_STYLE","EDGE_SUMMARY_STYLE","EDGE_SUMMARY_ITEM_STYLE","SECTION_BODY_STYLE","READONLY_FLOW_NODE_TYPES","WorkflowRuntimeNodeCard","InstanceDetailView","canViewWebhookDeliveries","showWebhookDeliveries","setActivityLogs","setInstance","setTaskDecisions","setAttachments","setSignatures","webhookDeliveries","setWebhookDeliveries","setSignatureVerification","setTasks","setWorkflowTokens","memberProfiles","setMemberProfiles","setLoading","workflowModalOpen","setWorkflowModalOpen","cancelComment","setCancelComment","cancelModalOpen","setCancelModalOpen","setResubmitFormErrors","setResubmitFormData","resubmitDataSourceStates","setResubmitDataSourceStates","previewAttachment","setPreviewAttachment","previewUrl","setPreviewUrl","setAdhocDirectives","trimmedCancelComment","tasksSectionRef","webhookDeliveryPollCountRef","hasInFlightWebhookDelivery","instanceId","timer","pollWebhookDeliveries","handleResubmitDataSourceStateChange","currentState","currentStates","fieldKey","canCancelInstance","layoutedWorkflowSnapshot","layoutRuntimeWorkflowDefinition","flowNodes","readRuntimeFlowNodes","flowEdges","readRuntimeFlowEdges","edgeSummaries","readEdgeSummaries","refreshInstance","nextRecord","readApprovalInstance","nextAdhocDirectives","listAdhocDirectives","nextTaskDecisions","nextMemberProfiles","nextAttachments","nextSignatures","nextWebhookDeliveries","listAttachments","readInstanceSignatures","readWebhookDeliveries","listWorkflowWebhookDeliveries","targetInstanceId","handleRetryWebhookDelivery","retryWorkflowWebhookDelivery","next","handleUploadAttachment","uploadAttachment","field","handleDownloadAttachment","url","readAttachmentDownloadUrl","handlePreviewAttachment","readAttachmentPreviewUrl","handleCancelInstance","cancelApprovalInstance","handleResubmitInstance","dataSourceBlockMessage","readFormDataSourceSubmissionBlockMessage","resubmittedValues","buildFormRendererValues","validation","validateFormRendererValues","focusFormRendererField","resubmitApprovalInstance","taskSectionDeciding","combinedDeciding","PageHeader","ShareIcon","DangerousOutlineIcon","PlusIcon","NotificationUnreadIcon","UserIcon","CheckedIcon","SectionGroup","showForm","Section","showAttachments","showTasks","showSignatures","showHistory","ReactFlow","Background","Controls","summary","readEdgeLabel","label","readNodeKindLabel","Position","graph","positionedNode","readNodeStyle","tone","readNodeStatusStyle","baseStyle","data","Handle"],"sources":["../../src/components/pdf-preview.module.scss","../../src/components/pdf-preview.tsx","../../src/views/instances/detail/submitted-by.ts","../../src/views/instances/detail/sections/shared.ts","../../src/views/instances/detail/sections/container-helpers.ts","../../src/views/instances/detail/sections/InstanceFormSection.tsx","../../src/views/instances/detail/sections/InstanceAttachmentsSection.tsx","../../src/views/instances/detail/sections/InstanceTasksSection.tsx","../../src/views/instances/detail/sections/InstanceSignaturesSection.tsx","../../src/views/instances/detail/sections/InstanceHistorySection.tsx","../../src/views/instances/detail/sections/InstanceWebhookDeliveriesSection.tsx","../../src/views/instances/detail/InstanceDetailView.tsx"],"sourcesContent":[".root {\n display: grid;\n gap: 12px;\n width: min(86vw, 1080px);\n}\n\n.toolbar {\n align-items: center;\n display: flex;\n flex-wrap: wrap;\n gap: 8px;\n justify-content: space-between;\n}\n\n.pageControls,\n.zoomControls {\n align-items: center;\n display: flex;\n gap: 8px;\n}\n\n.counter {\n min-width: 92px;\n text-align: center;\n white-space: nowrap;\n}\n\n.viewport {\n align-items: flex-start;\n background: #f8fafc;\n border: 1px solid #e2e8f0;\n border-radius: 8px;\n display: flex;\n height: min(72vh, 760px);\n justify-content: center;\n min-height: 420px;\n overflow: auto;\n padding: 16px;\n}\n\n.page {\n background: #ffffff;\n box-shadow: 0 12px 32px rgb(15 23 42 / 14%);\n color: #111827;\n}\n\n.state {\n align-items: center;\n display: flex;\n justify-content: center;\n min-height: 320px;\n width: 100%;\n}\n\n@media (max-width: 720px) {\n .root {\n width: 92vw;\n }\n\n .toolbar {\n align-items: stretch;\n display: grid;\n }\n\n .pageControls,\n .zoomControls {\n justify-content: space-between;\n }\n\n .counter {\n min-width: 84px;\n }\n\n .viewport {\n height: 68vh;\n min-height: 360px;\n padding: 12px;\n }\n}\n","'use client';\n\nimport {\n ReactElement,\n useCallback,\n useEffect,\n useMemo,\n useRef,\n useState,\n} from 'react';\nimport { Button, Typography } from '@mezzanine-ui/react';\nimport {\n ChevronLeftIcon,\n ChevronRightIcon,\n DownloadIcon,\n ZoomInIcon,\n ZoomOutIcon,\n} from '@mezzanine-ui/icons';\nimport { Document, Page, pdfjs } from 'react-pdf';\nimport type { PDFDocumentProxy } from 'pdfjs-dist';\nimport styles from './pdf-preview.module.scss';\n\n// pdfjs ships its worker as a separate chunk. Consumers should call\n// `configurePdfWorker(url)` (or set `pdfjs.GlobalWorkerOptions.workerSrc`\n// directly) before the first `<PDFPreview>` mounts. The library does not\n// hard-bundle a worker path because consumer bundlers may need to resolve\n// it through CDN, public/ asset pipeline, or pinned version.\nexport function configurePdfWorker(workerSrc: string): void {\n pdfjs.GlobalWorkerOptions.workerSrc = workerSrc;\n}\n\nconst DEFAULT_VIEWPORT_WIDTH = 760;\nconst MAX_PAGE_WIDTH = 920;\nconst MIN_PAGE_WIDTH = 320;\nconst PAGE_HORIZONTAL_PADDING = 32;\nconst MIN_SCALE = 0.75;\nconst MAX_SCALE = 1.75;\nconst SCALE_STEP = 0.25;\n\nexport interface PDFPreviewProps {\n readonly filename: string;\n readonly fileUrl: string;\n readonly onDownload?: () => void;\n}\n\n/**\n * Mezzanine-styled PDF preview powered by `react-pdf`. Used by the instance\n * detail view to preview PDF attachments inline.\n */\nexport function PDFPreview({\n filename,\n fileUrl,\n onDownload,\n}: PDFPreviewProps): ReactElement {\n const viewportRef = useRef<HTMLDivElement | null>(null);\n const [numPages, setNumPages] = useState<number | null>(null);\n const [pageNumber, setPageNumber] = useState(1);\n const [scale, setScale] = useState(1);\n const [viewportWidth, setViewportWidth] = useState(DEFAULT_VIEWPORT_WIDTH);\n\n useEffect((): (() => void) | undefined => {\n const viewport = viewportRef.current;\n\n if (!viewport || typeof ResizeObserver === 'undefined') {\n return undefined;\n }\n\n const observer = new ResizeObserver((entries): void => {\n const nextWidth = entries[0]?.contentRect.width;\n\n if (nextWidth) {\n setViewportWidth(nextWidth);\n }\n });\n\n observer.observe(viewport);\n\n return (): void => observer.disconnect();\n }, []);\n\n useEffect((): void => {\n setNumPages(null);\n setPageNumber(1);\n setScale(1);\n }, [fileUrl]);\n\n const pageWidth = useMemo((): number => {\n const availableWidth = Math.max(\n MIN_PAGE_WIDTH,\n viewportWidth - PAGE_HORIZONTAL_PADDING,\n );\n const baseWidth = Math.min(MAX_PAGE_WIDTH, availableWidth);\n\n return Math.round(baseWidth * scale);\n }, [scale, viewportWidth]);\n\n const loadDocument = useCallback((document: PDFDocumentProxy): void => {\n setNumPages(document.numPages);\n setPageNumber(1);\n }, []);\n\n const hasPreviousPage = pageNumber > 1;\n const hasNextPage = numPages !== null && pageNumber < numPages;\n const canZoomOut = scale > MIN_SCALE;\n const canZoomIn = scale < MAX_SCALE;\n const pageLabel =\n numPages === null\n ? `第 ${pageNumber} 頁`\n : `第 ${pageNumber} / ${numPages} 頁`;\n const zoomLabel = `${Math.round(scale * 100)}%`;\n\n return (\n <section aria-label={`${filename} PDF 預覽`} className={styles.root}>\n <div className={styles.toolbar}>\n <div className={styles.pageControls} aria-label=\"頁面切換\">\n <Button\n aria-label=\"上一頁\"\n disabled={!hasPreviousPage}\n icon={ChevronLeftIcon}\n onClick={(): void => {\n setPageNumber((currentPageNumber) =>\n Math.max(1, currentPageNumber - 1),\n );\n }}\n size=\"minor\"\n variant=\"base-secondary\"\n />\n <Typography\n className={styles.counter}\n component=\"span\"\n variant=\"body\"\n >\n {pageLabel}\n </Typography>\n <Button\n aria-label=\"下一頁\"\n disabled={!hasNextPage}\n icon={ChevronRightIcon}\n onClick={(): void => {\n setPageNumber((currentPageNumber) =>\n numPages === null\n ? currentPageNumber\n : Math.min(numPages, currentPageNumber + 1),\n );\n }}\n size=\"minor\"\n variant=\"base-secondary\"\n />\n </div>\n <div className={styles.zoomControls} aria-label=\"縮放\">\n <Button\n aria-label=\"縮小\"\n disabled={!canZoomOut}\n icon={ZoomOutIcon}\n onClick={(): void => {\n setScale((currentScale) =>\n Math.max(MIN_SCALE, currentScale - SCALE_STEP),\n );\n }}\n size=\"minor\"\n variant=\"base-secondary\"\n />\n <Typography\n className={styles.counter}\n component=\"span\"\n variant=\"body\"\n >\n {zoomLabel}\n </Typography>\n <Button\n aria-label=\"放大\"\n disabled={!canZoomIn}\n icon={ZoomInIcon}\n onClick={(): void => {\n setScale((currentScale) =>\n Math.min(MAX_SCALE, currentScale + SCALE_STEP),\n );\n }}\n size=\"minor\"\n variant=\"base-secondary\"\n />\n </div>\n {onDownload ? (\n <Button\n icon={DownloadIcon}\n iconType=\"leading\"\n onClick={onDownload}\n size=\"minor\"\n variant=\"base-primary\"\n >\n 下載\n </Button>\n ) : null}\n </div>\n <div className={styles.viewport} ref={viewportRef}>\n <Document\n error={<PDFPreviewState message=\"PDF 無法載入。\" />}\n file={fileUrl}\n loading={<PDFPreviewState message=\"正在載入 PDF...\" />}\n noData={<PDFPreviewState message=\"沒有可預覽的 PDF。\" />}\n onLoadSuccess={loadDocument}\n // react-pdf 11 suspends by default and hands load errors to the\n // nearest Error Boundary; keep the inline loading / error states.\n suspense={false}\n >\n <Page\n className={styles.page}\n loading={<PDFPreviewState message=\"正在載入頁面...\" />}\n pageNumber={pageNumber}\n renderAnnotationLayer\n renderTextLayer\n width={pageWidth}\n />\n </Document>\n </div>\n </section>\n );\n}\n\nfunction PDFPreviewState({\n message,\n}: {\n readonly message: string;\n}): ReactElement {\n return (\n <div className={styles.state}>\n <Typography color=\"text-neutral\" variant=\"body\">\n {message}\n </Typography>\n </div>\n );\n}\n","/**\n * Who filed an approval instance on someone's behalf.\n *\n * `submittedByMemberId` is `null` on rows written before the column existed\n * and equals `initiatorMemberId` when the applicant submitted it themselves;\n * only a different, non-empty value means somebody else filed it. This is the\n * one place the detail page reads that rule.\n */\n\ninterface SubmittedByFields {\n readonly initiatorMemberId: string | null | undefined;\n readonly submittedByMemberId?: string | null;\n}\n\ninterface NamedMember {\n readonly name: string;\n}\n\nexport function readDistinctSubmitterMemberId({\n initiatorMemberId,\n submittedByMemberId,\n}: SubmittedByFields): string | null {\n return submittedByMemberId && submittedByMemberId !== initiatorMemberId\n ? submittedByMemberId\n : null;\n}\n\n/**\n * 「由 {submitter} 代 {initiator} 送出」, or `null` when the applicant\n * submitted it themselves. A member whose profile did not load shows by id,\n * like every other member on the page.\n */\nexport function readSubmittedOnBehalfLabel(\n fields: SubmittedByFields,\n memberProfilesById: ReadonlyMap<string, NamedMember>,\n): string | null {\n const submitterMemberId = readDistinctSubmitterMemberId(fields);\n\n if (!submitterMemberId || !fields.initiatorMemberId) {\n return null;\n }\n\n const readName = (memberId: string): string =>\n memberProfilesById.get(memberId)?.name ?? memberId;\n\n return `由 ${readName(submitterMemberId)} 代 ${readName(\n fields.initiatorMemberId,\n )} 送出`;\n}\n","/**\n * Shared types, helpers, and label functions used across\n * InstanceDetailView section components.\n */\n\nimport {\n ActivityLogRecord,\n ApprovalInstanceRecord,\n AttachmentRecord,\n MemberProfileRecord,\n SignatureRecord,\n SignatureVerificationRecord,\n TaskDecisionRecord,\n TaskRecord,\n WorkflowTokenRecord,\n} from '@rytass/bpm-core-client/workflow';\nimport { readFormDataSourceErrorMessage } from '@rytass/bpm-core-client/form';\nimport { WorkflowDefinition, WorkflowNode } from '@rytass/bpm-core-shared/workflow';\nimport { formatDateTime } from '../../../../lib/format-date-time';\nimport { formatMemberLabel } from '../../../../lib/format-member-label';\nimport { readSubmittedOnBehalfLabel } from '../submitted-by';\n\n// ---------------------------------------------------------------------------\n// Row types\n// ---------------------------------------------------------------------------\n\nexport type TaskRow = Readonly<\n Record<string, unknown> &\n TaskRecord & {\n assigneeLabel: string;\n key: string;\n nodeLabel: string;\n statusLabel: string;\n }\n>;\n\nexport type AttachmentRow = Readonly<\n Record<string, unknown> & {\n attachment: AttachmentRecord;\n createdAt: string;\n filename: string;\n id: string;\n key: string;\n mimeType: string;\n sizeLabel: string;\n }\n>;\n\nexport type SignatureRow = Readonly<\n Record<string, unknown> & {\n algorithm: string;\n hashLabel: string;\n key: string;\n keyVersion: number;\n signedAtLabel: string;\n signerMemberId: string;\n }\n>;\n\nexport type MemberOption = Readonly<{\n email: string | null;\n id: string;\n name: string;\n}>;\n\n// ---------------------------------------------------------------------------\n// Activity step types (used by InstanceHistorySection)\n// ---------------------------------------------------------------------------\n\nexport type ActivityStepDescriptionPart =\n | Readonly<{ text: string; type: 'text' }>\n | Readonly<{\n email: string | null;\n label: string;\n memberId: string | null;\n prefix: string;\n type: 'member';\n }>\n /**\n * What an approver actually wrote. Kept apart from the `text` parts so the\n * timeline can give it its own line instead of burying it mid-sentence\n * between the node, the actor, the timestamp and the signature hash.\n */\n | Readonly<{\n label: string;\n text: string;\n tone: 'danger' | 'neutral';\n type: 'comment';\n }>;\n\nexport interface ActivityStepRecord {\n readonly descriptionParts: readonly ActivityStepDescriptionPart[];\n readonly error: boolean;\n readonly forcePending?: boolean;\n readonly id: string;\n readonly title: string;\n}\n\n// ---------------------------------------------------------------------------\n// Delegation chain\n// ---------------------------------------------------------------------------\n\ninterface DelegationChainStep {\n readonly from: string;\n readonly reason: string;\n readonly ruleId: string | null;\n readonly to: string;\n}\n\nfunction readDelegationChainStep(\n item: Readonly<Record<string, unknown>>,\n): DelegationChainStep | null {\n const from = readStringField(item, 'from');\n const to = readStringField(item, 'to');\n const reason = readStringField(item, 'reason');\n\n if (!from || !to || !reason) {\n return null;\n }\n\n return {\n from,\n reason,\n ruleId: readStringField(item, 'ruleId'),\n to,\n };\n}\n\nexport function readDelegationChain(value: string): readonly DelegationChainStep[] {\n try {\n const parsed = JSON.parse(value) as unknown;\n\n return Array.isArray(parsed)\n ? parsed\n .map((item): DelegationChainStep | null =>\n isRecord(item) ? readDelegationChainStep(item) : null,\n )\n .filter((item): item is DelegationChainStep => item !== null)\n : [];\n } catch {\n return [];\n }\n}\n\n// ---------------------------------------------------------------------------\n// Generic field readers\n// ---------------------------------------------------------------------------\n\nexport function readStringField(\n record: Readonly<Record<string, unknown>>,\n key: string,\n): string | null {\n const value = record[key];\n\n return typeof value === 'string' ? value : null;\n}\n\nexport function readStringArrayField(\n record: Readonly<Record<string, unknown>>,\n key: string,\n): readonly string[] {\n const value = record[key];\n\n return Array.isArray(value)\n ? value.filter((item): item is string => typeof item === 'string')\n : [];\n}\n\nexport function readNumberField(\n record: Readonly<Record<string, unknown>>,\n key: string,\n): number | null {\n const value = record[key];\n\n return typeof value === 'number' ? value : null;\n}\n\n// ---------------------------------------------------------------------------\n// Type guards / predicates\n// ---------------------------------------------------------------------------\n\nexport function isPresentText(value: string | null): value is string {\n return typeof value === 'string' && value.trim().length > 0;\n}\n\nexport function isRecord(value: unknown): value is Readonly<Record<string, unknown>> {\n return typeof value === 'object' && value !== null;\n}\n\nexport function isPendingTask(task: TaskRecord): boolean {\n return task.status === 'PENDING' || task.status === 'IN_PROGRESS';\n}\n\n// ---------------------------------------------------------------------------\n// Label helpers\n// ---------------------------------------------------------------------------\n\nexport function readErrorMessage(error: unknown): string {\n // DataSource failures arrive as stable codes so the backend never leaks\n // upstream transport detail; translate them instead of showing the raw code.\n const dataSourceMessage = readFormDataSourceErrorMessage(error);\n\n if (dataSourceMessage) {\n return dataSourceMessage;\n }\n\n return error instanceof Error ? error.message : '發生未知錯誤';\n}\n\nexport function formatFileSize(sizeBytes: number): string {\n if (!Number.isFinite(sizeBytes) || sizeBytes <= 0) {\n return '-';\n }\n\n if (sizeBytes < 1024) {\n return `${sizeBytes} B`;\n }\n\n if (sizeBytes < 1024 * 1024) {\n return `${(sizeBytes / 1024).toFixed(1)} KB`;\n }\n\n return `${(sizeBytes / 1024 / 1024).toFixed(1)} MB`;\n}\n\nexport function readShortHash(hash: string): string {\n return hash.length > 16 ? `${hash.slice(0, 12)}...` : hash;\n}\n\nexport function readInstanceStateLabel(state: string): string {\n if (state === 'APPROVED') return '已同意';\n if (state === 'CANCELLED') return '已取消';\n if (state === 'DRAFT') return '草稿';\n if (state === 'EXPIRED') return '已逾期';\n if (state === 'REJECTED') return '已拒絕';\n if (state === 'RETURNED') return '已退回';\n if (state === 'RUNNING') return '進行中';\n\n return state;\n}\n\nexport function readTaskStatusLabel(status: TaskRecord['status']): string {\n if (status === 'PENDING') return '待處理';\n if (status === 'IN_PROGRESS') return '處理中';\n if (status === 'COMPLETED') return '已完成';\n if (status === 'CANCELLED') return '已取消';\n if (status === 'TRANSFERRED') return '已轉派';\n\n return status;\n}\n\nexport function readTaskDecisionActionLabel(action: string): string {\n if (action === 'APPROVED') return '同意';\n if (action === 'REJECTED') return '拒絕';\n if (action === 'RETURNED') return '退回';\n if (action === 'TRANSFERRED') return '轉派';\n\n return action;\n}\n\nexport function readNodeKindLabel(type: WorkflowNode['type']): string {\n if (type === 'startEvent') return '開始';\n if (type === 'endEvent') return '完成';\n if (type === 'userTask') return '簽核節點';\n if (type === 'serviceTask') return '知會節點';\n if (type === 'exclusiveGateway') return '條件分流';\n\n return '平行處理';\n}\n\nexport function readNodeDisplayLabel(\n nodeId: string,\n workflow: WorkflowDefinition | null,\n): string {\n return (\n workflow?.nodes.find((node) => node.id === nodeId)?.data.label ?? nodeId\n );\n}\n\nexport function readMemberDisplayText(\n memberId: string | null,\n memberProfilesById: ReadonlyMap<string, MemberProfileRecord>,\n): string {\n if (!memberId) {\n return '-';\n }\n\n const profile = memberProfilesById.get(memberId);\n\n return profile\n ? formatMemberLabel(profile.name, profile.email, 'fullwidth')\n : memberId;\n}\n\nexport function readTaskAssigneeLabel(\n task: TaskRecord,\n memberProfilesById: ReadonlyMap<string, MemberProfileRecord> = new Map(),\n): string {\n const delegationChain = readDelegationChain(task.delegationChainJson);\n\n if (!task.assigneeMemberId) {\n return task.candidateMemberIds.length\n ? `候選 ${task.candidateMemberIds\n .map((memberId) => readMemberDisplayText(memberId, memberProfilesById))\n .join('、')}`\n : '未指定';\n }\n\n const assigneeLabel = readMemberDisplayText(\n task.assigneeMemberId,\n memberProfilesById,\n );\n const originalAssigneeLabel = readMemberDisplayText(\n task.originalAssigneeMemberId,\n memberProfilesById,\n );\n\n if (\n delegationChain.length === 0 ||\n task.originalAssigneeMemberId === task.assigneeMemberId\n ) {\n return assigneeLabel;\n }\n\n return `${assigneeLabel}(原:${originalAssigneeLabel})`;\n}\n\nexport function canMemberActOnTask(\n task: TaskRecord,\n memberId: string | null,\n): boolean {\n if (!memberId) {\n return false;\n }\n\n // `candidateMemberIds` lists everyone on the task, including SEQUENTIAL\n // candidates whose turn has not come; `openCandidateMemberIds` is who may act\n // now. The fallback only covers hosts that run their own task queries without\n // the field; the bundled client always selects it, so client and server must\n // be upgraded together (same release).\n return (\n task.assigneeMemberId === memberId ||\n (task.openCandidateMemberIds ?? task.candidateMemberIds).includes(memberId)\n );\n}\n\nexport function readReturnTargetOptions(\n workflow: WorkflowDefinition,\n node: WorkflowNode,\n): readonly { readonly id: string; readonly name: string }[] {\n if (node.type !== 'userTask' || !node.data.returnBehavior.allowReturn) {\n return [];\n }\n\n if (node.data.returnBehavior.allowedTargets === 'ANY') {\n return workflow.nodes\n .filter((candidate) => candidate.id !== node.id)\n .map((candidate) => ({\n id: candidate.id,\n name: `${candidate.data.label}(${readNodeKindLabel(candidate.type)})`,\n }));\n }\n\n const targetNodeId =\n node.data.returnBehavior.allowedTargets === 'INITIATOR'\n ? workflow.nodes.find((candidate) => candidate.type === 'startEvent')?.id\n : workflow.edges.find((edge) => edge.target === node.id)?.source;\n const targetNode = workflow.nodes.find(\n (candidate) => candidate.id === targetNodeId,\n );\n\n return targetNode\n ? [\n {\n id: targetNode.id,\n name: `${targetNode.data.label}(${readNodeKindLabel(targetNode.type)})`,\n },\n ]\n : [];\n}\n\nexport function readMemberOption(profile: MemberProfileRecord): MemberOption {\n return {\n email: profile.email,\n id: profile.memberId,\n name: formatMemberLabel(profile.name, profile.email, 'dot'),\n };\n}\n\n/**\n * The target an ad-hoc directive is sent to, or the reason it cannot be built\n * yet. Kept out of the component so the \"which shape do we send\" decision is\n * testable on its own — it is the part that changed when the member picker\n * went from one selection to many.\n */\nexport type AdhocTargetDraft =\n | Readonly<{\n target:\n | Readonly<{ kind: 'MEMBER'; memberIds: readonly string[] }>\n | Readonly<{ kind: 'WEBHOOK'; webhookUrl: string }>;\n valid: true;\n }>\n | Readonly<{ error: string; valid: false }>;\n\nexport function readAdhocTargetDraft({\n memberIds,\n useWebhookTarget,\n webhookUrl,\n}: {\n readonly memberIds: readonly string[];\n readonly useWebhookTarget: boolean;\n readonly webhookUrl: string;\n}): AdhocTargetDraft {\n if (useWebhookTarget) {\n const trimmedWebhookUrl = webhookUrl.trim();\n\n return trimmedWebhookUrl\n ? {\n target: { kind: 'WEBHOOK', webhookUrl: trimmedWebhookUrl },\n valid: true,\n }\n : { error: '請輸入 Webhook URL', valid: false };\n }\n\n return memberIds.length > 0\n ? { target: { kind: 'MEMBER', memberIds }, valid: true }\n : { error: '請選擇對象成員', valid: false };\n}\n\nexport function isPresentMemberOption(\n option: MemberOption | null,\n): option is MemberOption {\n return Boolean(option);\n}\n\nexport function readMemberOptionFromValue(value: unknown): MemberOption | null {\n if (!isRecord(value)) {\n return null;\n }\n\n const email = value.email;\n const id = value.id;\n const name = value.name;\n\n return typeof id === 'string' && typeof name === 'string'\n ? { email: typeof email === 'string' ? email : null, id, name }\n : null;\n}\n\nexport function readUniqueMemberOption(\n searchText: string,\n options: readonly MemberOption[],\n): MemberOption | null {\n const normalizedSearchText = searchText.trim().toLocaleLowerCase();\n\n if (!normalizedSearchText) {\n return null;\n }\n\n const matches = options.filter((option) =>\n [option.id, option.name, option.email ?? ''].some((value) =>\n value.toLocaleLowerCase().includes(normalizedSearchText),\n ),\n );\n\n return matches.length === 1 ? (matches[0] ?? null) : null;\n}\n\n// ---------------------------------------------------------------------------\n// Activity step helpers\n// ---------------------------------------------------------------------------\n\nexport function readTextDescriptionPart(\n text: string | null,\n): ActivityStepDescriptionPart | null {\n return isPresentText(text) ? { text, type: 'text' } : null;\n}\n\nexport function readCommentDescriptionPart(\n label: string,\n text: string | null,\n tone: 'danger' | 'neutral' = 'neutral',\n): ActivityStepDescriptionPart | null {\n return isPresentText(text) ? { label, text, tone, type: 'comment' } : null;\n}\n\nexport function readMemberDescriptionPart(\n prefix: string,\n memberId: string | null,\n memberProfilesById: ReadonlyMap<string, MemberProfileRecord>,\n fallbackLabel: string,\n): ActivityStepDescriptionPart {\n const profile = memberId ? memberProfilesById.get(memberId) : null;\n\n return {\n email: profile?.email ?? null,\n label: profile?.name ?? fallbackLabel,\n memberId,\n prefix,\n type: 'member',\n };\n}\n\nexport function isActivityDescriptionPart(\n part: ActivityStepDescriptionPart | null,\n): part is ActivityStepDescriptionPart {\n return Boolean(part);\n}\n\nexport function readCurrentActivityStep(\n activitySteps: readonly ActivityStepRecord[],\n): number {\n const firstPendingStepIndex = activitySteps.findIndex(\n (activityStep) =>\n activityStep.id.startsWith('pending-task-') ||\n activityStep.id.startsWith('future-node-'),\n );\n\n return firstPendingStepIndex === -1\n ? activitySteps.length\n : firstPendingStepIndex;\n}\n\nexport function isUserMeaningfulActivity(activityLog: ActivityLogRecord): boolean {\n return (\n activityLog.eventType === 'INSTANCE_STARTED' ||\n activityLog.eventType === 'INSTANCE_CANCELLED' ||\n activityLog.eventType === 'INSTANCE_EXPIRED' ||\n activityLog.eventType === 'TASK_DECIDED' ||\n activityLog.eventType === 'SLA_TRIGGERED' ||\n activityLog.eventType === 'TASK_CANDIDATE_ACTIVATED' ||\n activityLog.eventType === 'TASK_REASSIGNED' ||\n isSequentialTaskCreation(activityLog) ||\n isNotifyWebhookActivity(\n activityLog.eventType,\n readActivityPayload(activityLog),\n )\n );\n}\n\n/**\n * Only a SEQUENTIAL task's creation is worth a timeline entry (it carries the\n * signing order); every other TASK_CREATED row stays hidden as before.\n */\nfunction isSequentialTaskCreation(activityLog: ActivityLogRecord): boolean {\n return (\n activityLog.eventType === 'TASK_CREATED' &&\n readStringArrayField(\n readActivityPayload(activityLog),\n 'sequentialCandidateMemberIds',\n ).length > 0\n );\n}\n\n/**\n * Member ids that only appear inside the payload of the sequential-signing\n * events, so the timeline can load their profiles and show names, not ids.\n */\nexport function readSequentialActivityPayloadMemberIds(\n activityLog: ActivityLogRecord,\n): readonly string[] {\n if (\n activityLog.eventType !== 'TASK_CANDIDATE_ACTIVATED' &&\n activityLog.eventType !== 'TASK_CREATED'\n ) {\n return [];\n }\n\n const payload = readActivityPayload(activityLog);\n\n return [\n ...readStringArrayField(payload, 'sequentialCandidateMemberIds'),\n readStringField(payload, 'candidateMemberId'),\n readStringField(payload, 'previousMemberId'),\n ].filter(isPresentText);\n}\n\nconst NOTIFY_WEBHOOK_EVENT_TYPES: ReadonlySet<string> = new Set([\n 'SERVICE_TASK_EXECUTED',\n 'SERVICE_TASK_FAILED',\n 'WEBHOOK_DELIVERY_RETRIED',\n]);\n\n/**\n * A notify node's webhook outcome, or an administrator re-sending one (ADR 18\n * §3.10). Only the final word about a delivery is logged, so each is worth a\n * timeline entry; other service-task logs stay off it as before.\n */\nfunction isNotifyWebhookActivity(\n eventType: string,\n payload: Readonly<Record<string, unknown>>,\n): boolean {\n return (\n NOTIFY_WEBHOOK_EVENT_TYPES.has(eventType) &&\n readStringField(payload, 'action') === 'NOTIFY_WEBHOOK'\n );\n}\n\n/** Logs written before the label was recorded only carry the endpoint key. */\nfunction readNotifyWebhookEndpointLabel(\n payload: Readonly<Record<string, unknown>>,\n): string {\n return (\n readStringField(payload, 'endpointLabel') ??\n readStringField(payload, 'endpointKey') ??\n '外部系統'\n );\n}\n\nfunction readTaskDecisionEventLabel(action: string | null): string {\n if (action === 'APPROVED') return '已同意';\n if (action === 'REJECTED') return '已拒絕';\n if (action === 'RETURNED') return '已退回';\n if (action === 'TRANSFERRED') return '已轉派';\n\n return '簽核已決議';\n}\n\nexport function readActivityEventLabel(\n eventType: string,\n payload: Readonly<Record<string, unknown>>,\n): string {\n if (eventType === 'INSTANCE_STARTED') return '案件已發起';\n if (eventType === 'INSTANCE_CANCELLED') return '案件已取消';\n if (eventType === 'INSTANCE_EXPIRED') return '案件逾期,已由系統終止';\n if (eventType === 'TOKEN_CREATED') return '流程路徑已建立';\n if (eventType === 'ENGINE_PROCESS_REQUESTED') return '流程引擎已處理';\n if (eventType === 'TOKEN_ADVANCED') return '流程已前進';\n if (eventType === 'TASK_CREATED') return '待簽任務已建立';\n if (eventType === 'TASK_CANDIDATE_ACTIVATED') return '輪到下一位簽核';\n if (eventType === 'TASK_DECIDED') {\n return readTaskDecisionEventLabel(readStringField(payload, 'action'));\n }\n if (eventType === 'SLA_TRIGGERED') return '時限提醒已觸發';\n if (eventType === 'TASK_REASSIGNED') return '管理者改派待辦';\n if (isNotifyWebhookActivity(eventType, payload)) {\n const endpointLabel = readNotifyWebhookEndpointLabel(payload);\n\n if (eventType === 'SERVICE_TASK_EXECUTED') {\n return `已通知外部系統:${endpointLabel}`;\n }\n\n return eventType === 'SERVICE_TASK_FAILED'\n ? `通知外部系統失敗:${endpointLabel}`\n : `管理者重新傳送外部系統通知:${endpointLabel}`;\n }\n\n return eventType;\n}\n\nexport function readActivityPayload(\n activityLog: ActivityLogRecord,\n): Readonly<Record<string, unknown>> {\n try {\n const payload = JSON.parse(activityLog.payloadJson) as unknown;\n\n return isRecord(payload) ? payload : {};\n } catch {\n return {};\n }\n}\n\nexport function isActivityError(\n activityLog: ActivityLogRecord,\n payload: Readonly<Record<string, unknown>>,\n): boolean {\n return (\n activityLog.eventType === 'SLA_TRIGGERED' ||\n activityLog.eventType === 'INSTANCE_EXPIRED' ||\n (activityLog.eventType === 'SERVICE_TASK_FAILED' &&\n isNotifyWebhookActivity(activityLog.eventType, payload)) ||\n readStringField(payload, 'action') === 'REJECTED' ||\n readStringField(payload, 'instanceState') === 'REJECTED'\n );\n}\n\nexport function formatActivityDateTime(value: string): string {\n return formatDateTime(value);\n}\n\nfunction readActivityDetail(\n activityLog: ActivityLogRecord,\n payload: Readonly<Record<string, unknown>>,\n workflow: WorkflowDefinition | null,\n memberProfilesById: ReadonlyMap<string, MemberProfileRecord>,\n): string | null {\n if (activityLog.eventType === 'INSTANCE_STARTED') {\n // The actor of this event is the applicant; the payload says who pressed\n // submit. Nothing is shown when they are the same person.\n return readSubmittedOnBehalfLabel(\n {\n initiatorMemberId: activityLog.actorMemberId,\n submittedByMemberId: readStringField(payload, 'submittedByMemberId'),\n },\n memberProfilesById,\n );\n }\n\n if (activityLog.eventType === 'TASK_CANDIDATE_ACTIVATED') {\n const candidateMemberId = readStringField(payload, 'candidateMemberId');\n const previousMemberId = readStringField(payload, 'previousMemberId');\n\n if (!candidateMemberId) {\n return null;\n }\n\n const candidateLabel = readMemberDisplayText(\n candidateMemberId,\n memberProfilesById,\n );\n\n return previousMemberId\n ? `輪到:${candidateLabel}(前一位:${readMemberDisplayText(\n previousMemberId,\n memberProfilesById,\n )})`\n : `輪到:${candidateLabel}`;\n }\n\n if (activityLog.eventType === 'TASK_CREATED') {\n // A SEQUENTIAL task opens one candidate at a time; show the whole order\n // rather than only the person who is up first.\n const sequentialMemberIds = readStringArrayField(\n payload,\n 'sequentialCandidateMemberIds',\n );\n\n if (sequentialMemberIds.length) {\n return `簽核順序:${sequentialMemberIds\n .map((memberId) => readMemberDisplayText(memberId, memberProfilesById))\n .join(' → ')}`;\n }\n\n const assigneeMemberId = readStringField(payload, 'assigneeMemberId');\n const originalAssigneeMemberId = readStringField(\n payload,\n 'originalAssigneeMemberId',\n );\n\n if (!assigneeMemberId) {\n const candidateMemberIds = readStringArrayField(\n payload,\n 'candidateMemberIds',\n );\n\n return candidateMemberIds.length\n ? `候選簽核人:${candidateMemberIds\n .map((memberId) =>\n readMemberDisplayText(memberId, memberProfilesById),\n )\n .join('、')}`\n : null;\n }\n\n const assigneeLabel = readMemberDisplayText(\n assigneeMemberId,\n memberProfilesById,\n );\n const originalAssigneeLabel = readMemberDisplayText(\n originalAssigneeMemberId,\n memberProfilesById,\n );\n\n return originalAssigneeMemberId &&\n originalAssigneeMemberId !== assigneeMemberId\n ? `待簽人:${assigneeLabel}(原簽核人:${originalAssigneeLabel})`\n : `待簽人:${assigneeLabel}`;\n }\n\n if (activityLog.eventType === 'TASK_DECIDED') {\n const action = readStringField(payload, 'action');\n const comment = readStringField(payload, 'comment');\n const decisionLabel = action\n ? `決議:${readTaskDecisionActionLabel(action)}`\n : null;\n\n const transferToMemberId = readStringField(payload, 'transferToMemberId');\n\n return action === 'REJECTED' && comment\n ? [decisionLabel, `拒絕原因:${comment}`]\n .filter(isPresentText)\n .join(' · ')\n : action === 'APPROVED' && comment\n ? [decisionLabel, `同意說明:${comment}`]\n .filter(isPresentText)\n .join(' · ')\n : action === 'TRANSFERRED'\n ? [\n decisionLabel,\n `轉派給:${readMemberDisplayText(\n transferToMemberId,\n memberProfilesById,\n )}`,\n ]\n .filter(isPresentText)\n .join(' · ')\n : decisionLabel;\n }\n\n if (activityLog.eventType === 'TOKEN_ADVANCED') {\n const action = readStringField(payload, 'action');\n\n if (action) {\n return `流程結果:${readTaskDecisionActionLabel(action)}`;\n }\n\n const arrivedCount = readNumberField(payload, 'arrivedCount');\n const requiredCount = readNumberField(payload, 'requiredCount');\n\n if (arrivedCount !== null && requiredCount !== null) {\n return `等待匯合:${arrivedCount}/${requiredCount}`;\n }\n\n const fromNodeId = readStringField(payload, 'fromNodeId');\n const toNodeId = readStringField(payload, 'toNodeId');\n\n if (fromNodeId && toNodeId) {\n return `由 ${readNodeDisplayLabel(fromNodeId, workflow)} 前進至 ${readNodeDisplayLabel(toNodeId, workflow)}`;\n }\n }\n\n if (activityLog.eventType === 'ENGINE_PROCESS_REQUESTED') {\n const state = readStringField(payload, 'state');\n\n return state ? `案件狀態:${readInstanceStateLabel(state)}` : null;\n }\n\n return null;\n}\n\nexport function readActivityDetailParts(\n activityLog: ActivityLogRecord,\n payload: Readonly<Record<string, unknown>>,\n workflow: WorkflowDefinition | null,\n taskDecisionsByTaskId: ReadonlyMap<string, TaskDecisionRecord>,\n signaturesById: ReadonlyMap<string, SignatureRecord>,\n signatureVerification: SignatureVerificationRecord | null,\n memberProfilesById: ReadonlyMap<string, MemberProfileRecord>,\n): readonly ActivityStepDescriptionPart[] {\n if (activityLog.eventType !== 'TASK_DECIDED') {\n return [\n readTextDescriptionPart(\n readActivityDetail(\n activityLog,\n payload,\n workflow,\n memberProfilesById,\n ),\n ),\n ].filter(isActivityDescriptionPart);\n }\n\n const taskDecision = activityLog.taskId\n ? taskDecisionsByTaskId.get(activityLog.taskId)\n : null;\n const action =\n readStringField(payload, 'action') ?? taskDecision?.action ?? null;\n const comment =\n readStringField(payload, 'comment') ?? taskDecision?.comment ?? null;\n const transferToMemberId =\n readStringField(payload, 'transferToMemberId') ??\n taskDecision?.transferToMemberId ??\n null;\n const signatureId =\n readStringField(payload, 'signatureId') ??\n taskDecision?.signatureId ??\n null;\n const signature = signatureId ? signaturesById.get(signatureId) : null;\n const decisionLabel = action\n ? `決議:${readTaskDecisionActionLabel(action)}`\n : null;\n\n return [\n readTextDescriptionPart(decisionLabel),\n action === 'REJECTED'\n ? readCommentDescriptionPart('拒絕原因', comment ?? '-', 'danger')\n : null,\n action === 'APPROVED'\n ? readCommentDescriptionPart('同意說明', comment)\n : null,\n action === 'RETURNED'\n ? readCommentDescriptionPart('退回說明', comment ?? '-')\n : null,\n action === 'TRANSFERRED'\n ? readTextDescriptionPart(\n `轉派給:${readMemberDisplayText(\n transferToMemberId,\n memberProfilesById,\n )}`,\n )\n : null,\n action === 'TRANSFERRED'\n ? readCommentDescriptionPart('轉派說明', comment ?? '-')\n : null,\n signature\n ? readTextDescriptionPart(\n signatureVerification?.valid\n ? `簽章:已驗證(${readShortHash(signature.signedPayloadHash)})`\n : `簽章:待檢查(${readShortHash(signature.signedPayloadHash)})`,\n )\n : null,\n ].filter(isActivityDescriptionPart);\n}\n\nexport function isFutureTimelineNode(\n node: WorkflowNode,\n tasks: readonly TaskRecord[],\n tokens: readonly WorkflowTokenRecord[],\n instanceState: ApprovalInstanceRecord['state'],\n representedNodeIds: ReadonlySet<string>,\n): boolean {\n if (node.type === 'startEvent' || representedNodeIds.has(node.id)) {\n return false;\n }\n\n if (instanceState === 'REJECTED') {\n return true;\n }\n\n const state = readNodeRuntimeState(node, tasks, tokens, instanceState);\n\n return state.tone === 'neutral' || state.tone === 'waiting';\n}\n\nexport function readFutureTimelineNodes(\n workflow: WorkflowDefinition,\n tasks: readonly TaskRecord[],\n tokens: readonly WorkflowTokenRecord[],\n instanceState: ApprovalInstanceRecord['state'],\n representedNodeIds: ReadonlySet<string>,\n): readonly WorkflowNode[] {\n if (instanceState !== 'RUNNING' && instanceState !== 'REJECTED') {\n return [];\n }\n\n const futureNodes = workflow.nodes.filter((node) =>\n isFutureTimelineNode(\n node,\n tasks,\n tokens,\n instanceState,\n representedNodeIds,\n ),\n );\n const reachableDistances = readReachableFutureNodeDistances(\n workflow,\n futureNodes,\n tasks,\n tokens,\n representedNodeIds,\n );\n const originalNodeIndexes = new Map(\n workflow.nodes.map((node, index) => [node.id, index]),\n );\n\n return futureNodes\n .filter((node) => reachableDistances.has(node.id))\n .sort((left, right) => {\n const leftDistance = reachableDistances.get(left.id) ?? 0;\n const rightDistance = reachableDistances.get(right.id) ?? 0;\n\n if (leftDistance !== rightDistance) {\n return leftDistance - rightDistance;\n }\n\n if (left.position.x !== right.position.x) {\n return left.position.x - right.position.x;\n }\n\n if (left.position.y !== right.position.y) {\n return left.position.y - right.position.y;\n }\n\n return (\n (originalNodeIndexes.get(left.id) ?? 0) -\n (originalNodeIndexes.get(right.id) ?? 0)\n );\n });\n}\n\nfunction readReachableFutureNodeDistances(\n workflow: WorkflowDefinition,\n futureNodes: readonly WorkflowNode[],\n tasks: readonly TaskRecord[],\n tokens: readonly WorkflowTokenRecord[],\n representedNodeIds: ReadonlySet<string>,\n): ReadonlyMap<string, number> {\n const futureNodeIds = new Set(futureNodes.map((node) => node.id));\n const outgoingNodeIds = workflow.edges.reduce<\n ReadonlyMap<string, readonly string[]>\n >((groups, edge) => {\n const nextTargets = [...(groups.get(edge.source) ?? []), edge.target];\n\n return new Map(groups).set(edge.source, nextTargets);\n }, new Map());\n const frontierNodeIds = readFutureTimelineFrontierNodeIds(\n workflow,\n tasks,\n tokens,\n representedNodeIds,\n );\n\n return frontierNodeIds.reduce<ReadonlyMap<string, number>>(\n (distances, nodeId) =>\n mergeFutureNodeDistances(\n distances,\n readFutureNodeDistancesFrom(nodeId, outgoingNodeIds, futureNodeIds),\n ),\n new Map(),\n );\n}\n\nfunction readFutureTimelineFrontierNodeIds(\n workflow: WorkflowDefinition,\n tasks: readonly TaskRecord[],\n tokens: readonly WorkflowTokenRecord[],\n representedNodeIds: ReadonlySet<string>,\n): readonly string[] {\n const tokenNodeIds = tokens\n .filter((token) => token.status === 'ACTIVE' || token.status === 'WAITING')\n .map((token) => token.currentNodeId);\n const pendingTaskNodeIds = tasks\n .filter(isPendingTask)\n .map((task) => task.nodeId);\n const representedFrontierNodeIds = workflow.nodes\n .filter((node) => representedNodeIds.has(node.id))\n .map((node) => node.id);\n const activeFrontierNodeIds = [\n ...new Set([\n ...tokenNodeIds,\n ...pendingTaskNodeIds,\n ...representedFrontierNodeIds,\n ]),\n ];\n const startNodeIds = workflow.nodes\n .filter((node) => node.type === 'startEvent')\n .map((node) => node.id);\n\n return activeFrontierNodeIds.length > 0\n ? activeFrontierNodeIds\n : startNodeIds;\n}\n\nfunction readFutureNodeDistancesFrom(\n startNodeId: string,\n outgoingNodeIds: ReadonlyMap<string, readonly string[]>,\n futureNodeIds: ReadonlySet<string>,\n): ReadonlyMap<string, number> {\n const initialQueue: readonly {\n readonly distance: number;\n readonly nodeId: string;\n }[] = [{ distance: 0, nodeId: startNodeId }];\n\n return walkFutureNodeDistances(initialQueue, outgoingNodeIds, futureNodeIds);\n}\n\nfunction walkFutureNodeDistances(\n queue: readonly { readonly distance: number; readonly nodeId: string }[],\n outgoingNodeIds: ReadonlyMap<string, readonly string[]>,\n futureNodeIds: ReadonlySet<string>,\n visitedNodeIds: ReadonlySet<string> = new Set(),\n distances: ReadonlyMap<string, number> = new Map(),\n): ReadonlyMap<string, number> {\n const [current, ...restQueue] = queue;\n\n if (!current) {\n return distances;\n }\n\n if (visitedNodeIds.has(current.nodeId)) {\n return walkFutureNodeDistances(\n restQueue,\n outgoingNodeIds,\n futureNodeIds,\n visitedNodeIds,\n distances,\n );\n }\n\n const nextVisitedNodeIds = new Set(visitedNodeIds).add(current.nodeId);\n const nextDistances = futureNodeIds.has(current.nodeId)\n ? new Map(distances).set(\n current.nodeId,\n Math.min(\n distances.get(current.nodeId) ?? current.distance,\n current.distance,\n ),\n )\n : distances;\n const nextQueue = [\n ...restQueue,\n ...(outgoingNodeIds.get(current.nodeId) ?? []).map((nodeId) => ({\n distance: current.distance + 1,\n nodeId,\n })),\n ];\n\n return walkFutureNodeDistances(\n nextQueue,\n outgoingNodeIds,\n futureNodeIds,\n nextVisitedNodeIds,\n nextDistances,\n );\n}\n\nfunction mergeFutureNodeDistances(\n currentDistances: ReadonlyMap<string, number>,\n nextDistances: ReadonlyMap<string, number>,\n): ReadonlyMap<string, number> {\n return [...nextDistances.entries()].reduce<ReadonlyMap<string, number>>(\n (mergedDistances, [nodeId, distance]) =>\n new Map(mergedDistances).set(\n nodeId,\n Math.min(mergedDistances.get(nodeId) ?? distance, distance),\n ),\n currentDistances,\n );\n}\n\nexport function readFutureNodeStepTitle(node: WorkflowNode): string {\n if (node.type === 'userTask') return `未來簽核:${node.data.label}`;\n if (node.type === 'serviceTask') return `未來知會:${node.data.label}`;\n if (node.type === 'exclusiveGateway') return `未來分流:${node.data.label}`;\n if (node.type === 'parallelGateway') return `未來匯合:${node.data.label}`;\n if (node.type === 'endEvent') return `流程完成:${node.data.label}`;\n\n return `未來節點:${node.data.label}`;\n}\n\nexport function readActivityStepRecords(\n activityLogs: readonly ActivityLogRecord[],\n tasks: readonly TaskRecord[],\n tokens: readonly WorkflowTokenRecord[],\n workflow: WorkflowDefinition | null,\n instanceState: ApprovalInstanceRecord['state'],\n memberProfilesById: ReadonlyMap<string, MemberProfileRecord>,\n taskDecisionsByTaskId: ReadonlyMap<string, TaskDecisionRecord>,\n signaturesById: ReadonlyMap<string, SignatureRecord>,\n signatureVerification: SignatureVerificationRecord | null,\n): ActivityStepRecord[] {\n const historySteps = activityLogs\n .filter(isUserMeaningfulActivity)\n .map((activityLog): ActivityStepRecord => {\n const payload = readActivityPayload(activityLog);\n const nodeLabel = activityLog.nodeId\n ? readNodeDisplayLabel(activityLog.nodeId, workflow)\n : null;\n const descriptionParts = [\n readTextDescriptionPart(\n nodeLabel ? `節點:${nodeLabel}` : '節點:全流程',\n ),\n readMemberDescriptionPart(\n '操作者',\n activityLog.actorMemberId,\n memberProfilesById,\n '系統',\n ),\n readTextDescriptionPart(\n `時間:${formatActivityDateTime(activityLog.createdAt)}`,\n ),\n ...readActivityDetailParts(\n activityLog,\n payload,\n workflow,\n taskDecisionsByTaskId,\n signaturesById,\n signatureVerification,\n memberProfilesById,\n ),\n ].filter(isActivityDescriptionPart);\n\n return {\n descriptionParts,\n error: isActivityError(activityLog, payload),\n id: activityLog.id,\n title: readActivityEventLabel(activityLog.eventType, payload),\n };\n });\n const pendingTaskSteps = tasks.filter(isPendingTask).map(\n (task): ActivityStepRecord => ({\n descriptionParts: [\n readTextDescriptionPart(\n `節點:${readNodeDisplayLabel(task.nodeId, workflow)}`,\n ),\n readMemberDescriptionPart(\n '處理者',\n task.assigneeMemberId,\n memberProfilesById,\n '未指定',\n ),\n readTextDescriptionPart(\n `建立時間:${formatActivityDateTime(task.createdAt)}`,\n ),\n ].filter(isActivityDescriptionPart),\n error: false,\n id: `pending-task-${task.id}`,\n title: task.status === 'IN_PROGRESS' ? '簽核處理中' : '等待簽核處理',\n }),\n );\n const representedNodeIds = new Set(\n [\n ...activityLogs\n .filter(isUserMeaningfulActivity)\n .map((activityLog) => activityLog.nodeId),\n ...tasks.map((task) => task.nodeId),\n ].filter(isPresentText),\n );\n const futureNodeSteps = workflow\n ? readFutureTimelineNodes(\n workflow,\n tasks,\n tokens,\n instanceState,\n representedNodeIds,\n ).map(\n (node): ActivityStepRecord => ({\n descriptionParts: [\n readTextDescriptionPart(\n `${readNodeKindLabel(node.type)} · 尚未抵達`,\n ),\n ].filter(isActivityDescriptionPart),\n error: false,\n forcePending: true,\n id: `future-node-${node.id}`,\n title: readFutureNodeStepTitle(node),\n }),\n )\n : [];\n\n return [...historySteps, ...pendingTaskSteps, ...futureNodeSteps];\n}\n\n// ---------------------------------------------------------------------------\n// Node runtime state (used by flow canvas AND history)\n// ---------------------------------------------------------------------------\n\ntype RuntimeTone = 'cancelled' | 'completed' | 'current' | 'neutral' | 'waiting';\n\nconst END_EVENT_STATUS: Readonly<\n Record<string, Readonly<{ statusLabel: string; tone: RuntimeTone }>>\n> = {\n APPROVED: { statusLabel: '已完成', tone: 'completed' },\n CANCELLED: { statusLabel: '已取消', tone: 'cancelled' },\n EXPIRED: { statusLabel: '已逾期終止', tone: 'cancelled' },\n REJECTED: { statusLabel: '已拒絕', tone: 'cancelled' },\n};\n\nexport function readNodeRuntimeState(\n node: WorkflowNode,\n tasks: readonly TaskRecord[],\n tokens: readonly WorkflowTokenRecord[],\n instanceState: string,\n): Readonly<{\n secondaryLabel: string;\n statusLabel: string;\n tone: RuntimeTone;\n}> {\n const nodeTasks = tasks.filter((task) => task.nodeId === node.id);\n const pendingTask = nodeTasks.find(\n (task) => task.status === 'PENDING' || task.status === 'IN_PROGRESS',\n );\n const cancelledTask = nodeTasks.find((task) => task.status === 'CANCELLED');\n const completedTask = nodeTasks.find((task) => task.status === 'COMPLETED');\n const nodeTokens = tokens.filter((token) => token.currentNodeId === node.id);\n const activeToken = nodeTokens.find((token) => token.status === 'ACTIVE');\n const waitingToken = nodeTokens.find((token) => token.status === 'WAITING');\n\n if (pendingTask) {\n return {\n secondaryLabel: `處理者 ${readTaskAssigneeLabel(pendingTask)}`,\n statusLabel: '待處理',\n tone: 'current',\n };\n }\n\n if (cancelledTask) {\n return {\n secondaryLabel: `已取消 ${readTaskAssigneeLabel(cancelledTask)}`,\n statusLabel: '已取消',\n tone: 'cancelled',\n };\n }\n\n if (completedTask) {\n return {\n secondaryLabel: `已完成 ${readTaskAssigneeLabel(completedTask)}`,\n statusLabel: '已完成',\n tone: 'completed',\n };\n }\n\n if (activeToken) {\n return {\n secondaryLabel: `token ${activeToken.id}`,\n statusLabel: '執行中',\n tone: 'current',\n };\n }\n\n if (waitingToken) {\n return {\n secondaryLabel: `token ${waitingToken.id}`,\n statusLabel: '等待前置',\n tone: 'waiting',\n };\n }\n\n if (node.type === 'startEvent') {\n return {\n secondaryLabel: '流程已發起',\n statusLabel: '已發起',\n tone: 'completed',\n };\n }\n\n const endEventStatus =\n node.type === 'endEvent' ? END_EVENT_STATUS[instanceState] : undefined;\n\n // Only a closed instance has an outcome to show on its end node. Every\n // non-running state used to read 已完成 here — a cancelled, expired or\n // returned case included.\n if (endEventStatus) {\n return { ...endEventStatus, secondaryLabel: instanceState };\n }\n\n return {\n secondaryLabel: readNodeKindLabel(node.type),\n statusLabel: '未抵達',\n tone: 'neutral',\n };\n}\n","/**\n * Helper functions used by InstanceDetailView (the container) that do not\n * belong in any individual section component.\n */\n\nimport {\n ActivityLogRecord,\n AdhocDirectiveRecord,\n ApprovalInstanceRecord,\n MemberProfileRecord,\n TaskDecisionRecord,\n TaskRecord,\n listTaskDecisions,\n resolveMemberProfiles,\n} from '@rytass/bpm-core-client/workflow';\nimport {\n isPresentText,\n readDelegationChain as _readDelegationChain,\n readSequentialActivityPayloadMemberIds,\n} from './shared';\n\n// Re-export shared helpers needed by the container\nexport {\n canMemberActOnTask,\n readErrorMessage,\n readInstanceStateLabel,\n readNodeRuntimeState,\n} from './shared';\n\nexport async function readMemberProfilesForTimeline({\n activityLogs,\n adhocDirectives = [],\n instance,\n tasks,\n}: {\n readonly activityLogs: readonly ActivityLogRecord[];\n readonly adhocDirectives?: readonly AdhocDirectiveRecord[];\n readonly instance?: Pick<\n ApprovalInstanceRecord,\n 'initiatorMemberId' | 'submittedByMemberId'\n >;\n readonly tasks: readonly TaskRecord[];\n}): Promise<readonly MemberProfileRecord[]> {\n const memberIds = [\n ...new Set(\n [\n // The applicant and whoever filed on their behalf are named in the\n // page header even when the timeline does not mention them.\n instance?.initiatorMemberId ?? null,\n instance?.submittedByMemberId ?? null,\n ...activityLogs.map((activityLog) => activityLog.actorMemberId),\n ...activityLogs.flatMap(readSequentialActivityPayloadMemberIds),\n ...tasks.map((task) => task.assigneeMemberId),\n ...tasks.map((task) => task.originalAssigneeMemberId),\n ...tasks.flatMap((task) => task.candidateMemberIds),\n ...tasks.flatMap((task) =>\n _readDelegationChain(task.delegationChainJson).flatMap((step) => [\n step.from,\n step.to,\n ]),\n ),\n ...adhocDirectives.flatMap((directive) => [\n directive.createdByMemberId,\n ...readAdhocDirectiveTargetMemberIds(directive.targetValueJson),\n ]),\n ].filter(isPresentText),\n ),\n ];\n\n try {\n return await resolveMemberProfiles(memberIds);\n } catch {\n return [];\n }\n}\n\nfunction readAdhocDirectiveTargetMemberIds(\n targetValueJson: string,\n): readonly string[] {\n try {\n const value = JSON.parse(targetValueJson) as {\n readonly memberIds?: readonly unknown[];\n };\n\n return (value.memberIds ?? []).filter(\n (memberId): memberId is string => typeof memberId === 'string',\n );\n } catch {\n return [];\n }\n}\n\nexport async function readTaskDecisionsForTasks(\n tasks: readonly TaskRecord[],\n): Promise<readonly TaskDecisionRecord[]> {\n const decisionLists = await Promise.all(\n tasks.map((task) => listTaskDecisions(task.id)),\n );\n\n return decisionLists.flat();\n}\n\nexport function readLatestTaskDecisionsByTaskId(\n taskDecisions: readonly TaskDecisionRecord[],\n): ReadonlyMap<string, TaskDecisionRecord> {\n return taskDecisions.reduce<ReadonlyMap<string, TaskDecisionRecord>>(\n (decisionsByTaskId, decision) => {\n const currentDecision = decisionsByTaskId.get(decision.taskId);\n const nextDecision =\n !currentDecision ||\n new Date(decision.decidedAt).getTime() >\n new Date(currentDecision.decidedAt).getTime()\n ? decision\n : currentDecision;\n\n return new Map(decisionsByTaskId).set(decision.taskId, nextDecision);\n },\n new Map(),\n );\n}\n","'use client';\n\nimport { CSSProperties, ReactElement } from 'react';\nimport { Button, Typography } from '@mezzanine-ui/react';\nimport { RefreshCcwIcon } from '@mezzanine-ui/icons';\nimport { FormFieldDefinition } from '@rytass/bpm-core-shared/form';\nimport { ApprovalInstanceRecord, WorkflowFormData } from '@rytass/bpm-core-client/workflow';\nimport { FormRenderer } from '../../../forms/renderer/FormRendererView';\nimport type { FormDataSourceFieldState } from '../../../forms/renderer/form-data-source-field';\n\nconst SECTION_BODY_STYLE: CSSProperties = {\n display: 'grid',\n gap: 16,\n};\n\nconst BUTTON_ROW_STYLE: CSSProperties = {\n display: 'flex',\n flexWrap: 'wrap',\n gap: 8,\n};\n\nexport interface InstanceFormSectionProps {\n /** The loaded approval instance, or null while loading. */\n readonly instance: ApprovalInstanceRecord | null;\n /** Whether the instance is in a loading state. */\n readonly loading: boolean;\n /** Error message to display, if any. */\n readonly error: string | null;\n /** Whether the current user can resubmit (edit + resubmit the returned form). */\n readonly canResubmitInstance: boolean;\n /** Current form data for the resubmit flow. */\n readonly resubmitFormData: WorkflowFormData;\n /** Validation error map for the resubmit form. */\n readonly resubmitFormErrors: Readonly<Record<string, string>>;\n /** Whether a decision/submit action is in progress. */\n readonly deciding: boolean;\n /** Called when the form data changes in the resubmit flow. */\n readonly onResubmitFormChange: (values: WorkflowFormData) => void;\n /** Called when a dynamic option field changes validation state. */\n readonly onDataSourceStateChange: (\n fieldKey: string,\n state: Pick<\n FormDataSourceFieldState,\n 'hasValue' | 'invalidValues' | 'status'\n >,\n ) => void;\n /** Called when the user clicks \"重新送出\". */\n readonly onResubmitInstance: () => void;\n /** Called when an attachment upload is requested via the form field. */\n readonly onUploadAttachment: (\n field: FormFieldDefinition,\n file: File,\n ) => Promise<{ readonly id: string }>;\n}\n\n/**\n * Renders the form snapshot section of the approval instance detail page.\n * Displays the form in read-only mode normally, or editable mode when the\n * instance has been returned and the current member can resubmit it.\n */\nexport function InstanceFormSection({\n canResubmitInstance,\n deciding,\n error,\n instance,\n loading,\n onDataSourceStateChange,\n onResubmitFormChange,\n onResubmitInstance,\n onUploadAttachment,\n resubmitFormData,\n resubmitFormErrors,\n}: InstanceFormSectionProps): ReactElement {\n return (\n <div style={SECTION_BODY_STYLE}>\n {error ? (\n <Typography color=\"text-error\" variant=\"body\">\n {error}\n </Typography>\n ) : null}\n {loading ? (\n <Typography color=\"text-neutral\" variant=\"body\">\n 載入中...\n </Typography>\n ) : null}\n {instance?.formDefinitionSnapshot.schema &&\n instance.formDefinitionSnapshot.uiSchema ? (\n <>\n <FormRenderer\n dataSourceContext={\n canResubmitInstance\n ? {\n // Instance-scoped only: the runtime query rejects a context\n // that names both, and a returned instance must resolve its\n // options against its own form definition snapshot rather\n // than whatever version the template publishes today.\n instanceId: instance.id,\n kind: 'runtime',\n }\n : undefined\n }\n dataSourceInitialValues={instance.formData}\n errors={resubmitFormErrors}\n onChange={(values): void => {\n onResubmitFormChange(values);\n }}\n onDataSourceStateChange={onDataSourceStateChange}\n onUploadAttachment={\n canResubmitInstance ? onUploadAttachment : undefined\n }\n optionSnapshots={instance.formDataOptionSnapshot}\n readonly={!canResubmitInstance}\n schema={instance.formDefinitionSnapshot.schema}\n uiSchema={instance.formDefinitionSnapshot.uiSchema}\n value={\n canResubmitInstance ? resubmitFormData : instance.formData\n }\n />\n {canResubmitInstance ? (\n <div style={BUTTON_ROW_STYLE}>\n <Button\n disabled={deciding}\n icon={RefreshCcwIcon}\n iconType=\"leading\"\n onClick={onResubmitInstance}\n variant=\"base-primary\"\n >\n 重新送出\n </Button>\n </div>\n ) : null}\n </>\n ) : (\n <Typography color=\"text-neutral\" variant=\"body\">\n 此案件沒有可顯示的表單快照。\n </Typography>\n )}\n </div>\n );\n}\n","'use client';\n\nimport { CSSProperties, ReactElement, useMemo } from 'react';\nimport { Table, Typography } from '@mezzanine-ui/react';\nimport { DownloadIcon, FileSearchIcon } from '@mezzanine-ui/icons';\nimport type { TableActions, TableColumn } from '@mezzanine-ui/core/table';\nimport { AttachmentRecord } from '@rytass/bpm-core-client/workflow';\nimport { formatDateTime } from '../../../../lib/format-date-time';\nimport { AttachmentRow, formatFileSize } from './shared';\n\nconst SECTION_BODY_STYLE: CSSProperties = {\n display: 'grid',\n gap: 16,\n};\n\nexport interface InstanceAttachmentsSectionProps {\n /** The list of attachments for this instance. */\n readonly attachments: readonly AttachmentRecord[];\n /** Called when the user clicks the download action for an attachment. */\n readonly onDownload: (attachment: AttachmentRecord) => void;\n /** Called when the user clicks the preview action for a PDF attachment. */\n readonly onPreview: (attachment: AttachmentRecord) => void;\n}\n\n/**\n * Renders the attachments section of the approval instance detail page.\n * Shows a table of attachments with download and (for PDFs) preview actions.\n */\nexport function InstanceAttachmentsSection({\n attachments,\n onDownload,\n onPreview,\n}: InstanceAttachmentsSectionProps): ReactElement {\n const attachmentRows = useMemo(\n (): AttachmentRow[] =>\n attachments.map((attachment) => ({\n attachment,\n createdAt: attachment.createdAt,\n filename: attachment.filename,\n id: attachment.id,\n key: attachment.id,\n mimeType: attachment.mimeType,\n sizeLabel: formatFileSize(Number(attachment.sizeBytes)),\n })),\n [attachments],\n );\n\n const attachmentColumns = useMemo(\n (): TableColumn<AttachmentRow>[] => [\n { dataIndex: 'filename', key: 'filename', title: '檔名', width: 260 },\n { dataIndex: 'mimeType', key: 'mimeType', title: '類型', width: 180 },\n { dataIndex: 'sizeLabel', key: 'sizeLabel', title: '大小', width: 120 },\n {\n key: 'createdAt',\n render: (record: AttachmentRow): ReactElement => (\n <Typography component=\"span\" variant=\"body\">\n {formatDateTime(record.createdAt)}\n </Typography>\n ),\n title: '上傳時間',\n width: 220,\n },\n ],\n [],\n );\n\n const attachmentActions = useMemo(\n (): TableActions<AttachmentRow> => ({\n render: (record): ReturnType<TableActions<AttachmentRow>['render']> => [\n ...(record.mimeType === 'application/pdf'\n ? [\n {\n icon: FileSearchIcon,\n iconType: 'leading' as const,\n name: '預覽',\n onClick: (): void => {\n onPreview(record.attachment);\n },\n },\n ]\n : []),\n {\n icon: DownloadIcon,\n iconType: 'leading',\n name: '下載',\n onClick: (): void => {\n onDownload(record.attachment);\n },\n },\n ],\n variant: 'base-secondary',\n width: 160,\n }),\n [onDownload, onPreview],\n );\n\n return (\n <div style={SECTION_BODY_STYLE}>\n <Typography component=\"h2\" variant=\"h3\">\n 附件\n </Typography>\n {attachmentRows.length > 0 ? (\n <Table\n actions={attachmentActions}\n columns={attachmentColumns}\n dataSource={attachmentRows}\n fullWidth\n />\n ) : (\n <Typography color=\"text-neutral\" variant=\"body\">\n 此案件沒有附件。\n </Typography>\n )}\n </div>\n );\n}\n","'use client';\n\nimport {\n ChangeEvent,\n CSSProperties,\n forwardRef,\n ReactElement,\n useImperativeHandle,\n useMemo,\n useState,\n} from 'react';\nimport {\n AutoComplete,\n Button,\n Input,\n Modal,\n Select,\n Table,\n Textarea,\n Typography,\n} from '@mezzanine-ui/react';\nimport type { TableColumn } from '@mezzanine-ui/core/table';\nimport {\n AdhocDirectiveRecord,\n AdhocPreApprovalRejectBehavior,\n ApprovalInstanceRecord,\n MemberProfileRecord,\n TaskRecord,\n cancelAdhocDirective,\n configureAdhocCompletionNotification,\n configureAdhocStageNotification,\n decideTask,\n requestAdhocCountersign,\n requestAdhocPreApproval,\n searchMembers,\n} from '@rytass/bpm-core-client/workflow';\nimport { formatDateTime } from '../../../../lib/format-date-time';\nimport { readTaskNodeText } from '../../../../lib/task-node-label';\nimport { BPMFormField } from '../../../../components/bpm-form-field';\nimport {\n MemberOption,\n TaskRow,\n canMemberActOnTask,\n readErrorMessage,\n readMemberDisplayText,\n readMemberOption,\n isPresentMemberOption,\n readAdhocTargetDraft,\n readMemberOptionFromValue,\n readNodeDisplayLabel,\n readReturnTargetOptions,\n readTaskAssigneeLabel,\n readTaskStatusLabel,\n readUniqueMemberOption,\n} from './shared';\n\nconst REJECT_REASON_FORM_STYLE: CSSProperties = {\n display: 'grid',\n gap: 12,\n width: '100%',\n};\n\nconst REJECT_REASON_TEXTAREA_STYLE: CSSProperties = {\n minWidth: '100%',\n width: '100%',\n};\n\nconst MODAL_FORM_STYLE: CSSProperties = {\n display: 'grid',\n gap: 12,\n width: '100%',\n};\n\nconst SECTION_TABLE_STYLE: CSSProperties = {\n marginTop: 12,\n};\n\nconst SECTION_SUBHEADING_STYLE: CSSProperties = {\n marginTop: 24,\n};\n\nfunction applyFullWidthTextareaHost(element: HTMLDivElement | null): void {\n if (!element) {\n return;\n }\n\n element.style.width = '100%';\n}\n\n/**\n * Imperative handle exposed by InstanceTasksSection via ref.\n * The container uses these to wire PageHeader action buttons to the\n * section's internal modal state without lifting state up.\n */\nexport type AdhocActionMode =\n | 'COMPLETION_NOTIFY'\n | 'COUNTERSIGN'\n | 'PRE_APPROVAL'\n | 'STAGE_NOTIFY';\n\nexport interface InstanceTasksSectionHandle {\n /** Whether a task action (decision) is currently in flight. */\n readonly deciding: boolean;\n /** Whether the current user has an actionable pending task. */\n readonly hasCurrentTask: boolean;\n /** Whether the current task's node allows a return action. */\n readonly canReturnCurrentTask: boolean;\n /** Whether the current task's node allows a reject action. */\n readonly canRejectCurrentTask: boolean;\n /** Whether the current task's node allows a transfer action. */\n readonly canTransferCurrentTask: boolean;\n /** Whether the current task's node allows ad-hoc countersign/pre-approval. */\n readonly canAddSignerCurrentTask: boolean;\n /** Opens the reject-reason modal. */\n openRejectModal(): void;\n /** Opens the return modal. */\n openReturnModal(): void;\n /** Opens the transfer modal. */\n openTransferModal(): void;\n /** Opens the ad-hoc action modal in the given mode. */\n openAdhocModal(mode: AdhocActionMode): void;\n /** Opens the approve-comment modal. */\n handleApprove(): void;\n}\n\nexport interface InstanceTasksSectionProps {\n /** All tasks for this instance. */\n readonly tasks: readonly TaskRecord[];\n /** Ad-hoc directives recorded on this instance. */\n readonly adhocDirectives: readonly AdhocDirectiveRecord[];\n /** The loaded approval instance (used to read workflowSnapshot node labels). */\n readonly instance: ApprovalInstanceRecord | null;\n /** Member profiles indexed by memberId, for displaying assignee labels. */\n readonly memberProfilesById: ReadonlyMap<string, MemberProfileRecord>;\n /** The currently authenticated member's id. */\n readonly currentMemberId: string | null;\n /**\n * Called after any task decision action (approve / reject / return /\n * transfer) completes successfully. The container should refresh data.\n */\n readonly onChanged: () => void | Promise<void>;\n}\n\nconst ADHOC_MODE_LABELS: Readonly<Record<AdhocActionMode, string>> = {\n COMPLETION_NOTIFY: '結案通知',\n COUNTERSIGN: '臨時會簽',\n PRE_APPROVAL: '臨時加簽',\n STAGE_NOTIFY: '階段完成通知',\n};\n\nconst ADHOC_MODE_SUPPORTING_TEXT: Readonly<Record<AdhocActionMode, string>> = {\n COMPLETION_NOTIFY: '本張單到達結案狀態(核准 / 拒絕 / 取消)後,通知指定對象。',\n COUNTERSIGN: '指定對象會併入下一層簽核,下一層需所有人都完成才會繼續。',\n PRE_APPROVAL: '指定對象需先完成加簽,本階段才會往下一層繼續。',\n STAGE_NOTIFY: '本階段完成後(不論通過與否)通知指定對象。',\n};\n\nconst ADHOC_ON_REJECT_OPTIONS: readonly {\n readonly id: AdhocPreApprovalRejectBehavior;\n readonly name: string;\n}[] = [\n { id: 'REJECT_INSTANCE', name: '加簽拒絕時整單駁回' },\n { id: 'RETURN_TO_ORIGIN', name: '加簽拒絕時退回給我重新處理' },\n];\n\nconst ADHOC_NOTIFY_TARGET_OPTIONS: readonly {\n readonly id: 'MEMBER' | 'WEBHOOK';\n readonly name: string;\n}[] = [\n { id: 'MEMBER', name: '指定成員' },\n { id: 'WEBHOOK', name: 'Webhook' },\n];\n\ntype AdhocDirectiveRow = Readonly<\n Record<string, unknown> &\n AdhocDirectiveRecord & {\n createdByLabel: string;\n key: string;\n targetLabel: string;\n typeLabel: string;\n }\n>;\n\n/**\n * Renders the tasks section of the approval instance detail page.\n * Contains the task table plus all decision action modals\n * (reject, return, transfer). Approve is also handled here via the\n * imperative handle exposed through the forwarded ref.\n */\nexport const InstanceTasksSection = forwardRef<\n InstanceTasksSectionHandle,\n InstanceTasksSectionProps\n>(function InstanceTasksSection(\n {\n adhocDirectives,\n currentMemberId,\n instance,\n memberProfilesById,\n onChanged,\n tasks,\n }: InstanceTasksSectionProps,\n ref,\n): ReactElement {\n const [deciding, setDeciding] = useState(false);\n const [error, setError] = useState<string | null>(null);\n\n // Approve modal — the comment is optional here, unlike the reject reason.\n // Approving used to submit straight from the header button, so the decision\n // comment could never be filled in even though the API has always taken one.\n const [approveComment, setApproveComment] = useState('');\n const [approveModalOpen, setApproveModalOpen] = useState(false);\n\n // Reject modal\n const [rejectReason, setRejectReason] = useState('');\n const [rejectReasonError, setRejectReasonError] = useState<string | null>(null);\n const [rejectReasonModalOpen, setRejectReasonModalOpen] = useState(false);\n\n // Return modal\n const [returnComment, setReturnComment] = useState('');\n const [returnModalOpen, setReturnModalOpen] = useState(false);\n const [returnTargetNodeId, setReturnTargetNodeId] = useState<string | null>(null);\n\n // Transfer modal\n const [transferComment, setTransferComment] = useState('');\n const [transferMember, setTransferMember] = useState<MemberOption | null>(null);\n const [transferMemberLoading, setTransferMemberLoading] = useState(false);\n const [transferMemberOptions, setTransferMemberOptions] = useState<\n readonly MemberOption[]\n >([]);\n const [transferModalOpen, setTransferModalOpen] = useState(false);\n\n // Ad-hoc modal (countersign / pre-approval / stage & completion notify)\n const [adhocComment, setAdhocComment] = useState('');\n const [adhocMembers, setAdhocMembers] = useState<readonly MemberOption[]>(\n [],\n );\n const [adhocMemberLoading, setAdhocMemberLoading] = useState(false);\n const [adhocMemberOptions, setAdhocMemberOptions] = useState<\n readonly MemberOption[]\n >([]);\n const [adhocModalOpen, setAdhocModalOpen] = useState(false);\n const [adhocMode, setAdhocMode] = useState<AdhocActionMode>('COUNTERSIGN');\n const [adhocOnReject, setAdhocOnReject] =\n useState<AdhocPreApprovalRejectBehavior>('REJECT_INSTANCE');\n const [adhocSubmitting, setAdhocSubmitting] = useState(false);\n const [adhocTargetKind, setAdhocTargetKind] = useState<'MEMBER' | 'WEBHOOK'>(\n 'MEMBER',\n );\n const [adhocWebhookUrl, setAdhocWebhookUrl] = useState('');\n\n const trimmedRejectReason = rejectReason.trim();\n const trimmedReturnComment = returnComment.trim();\n const trimmedTransferComment = transferComment.trim();\n\n const currentTask = useMemo(\n (): TaskRecord | null =>\n tasks.find(\n (task) =>\n canMemberActOnTask(task, currentMemberId) &&\n (task.status === 'PENDING' || task.status === 'IN_PROGRESS'),\n ) ?? null,\n [currentMemberId, tasks],\n );\n\n const currentTaskNode = useMemo(\n () =>\n currentTask && instance\n ? (instance.workflowSnapshot.nodes.find(\n (node) => node.id === currentTask.nodeId,\n ) ?? null)\n : null,\n [currentTask, instance],\n );\n\n const returnTargetOptions = useMemo(\n (): readonly { readonly id: string; readonly name: string }[] =>\n currentTaskNode && instance\n ? readReturnTargetOptions(instance.workflowSnapshot, currentTaskNode)\n : [],\n [currentTaskNode, instance],\n );\n\n const canReturnCurrentTask =\n currentTaskNode?.type === 'userTask' &&\n currentTaskNode.data.returnBehavior.allowReturn;\n\n // Older workflow snapshots may not carry these fields. Preserve their\n // historical behaviour and only disable an action when it is explicitly\n // set to false.\n const canRejectCurrentTask =\n currentTaskNode?.type === 'userTask' &&\n currentTaskNode.data.allowReject !== false;\n const canTransferCurrentTask =\n currentTaskNode?.type === 'userTask' &&\n currentTaskNode.data.allowTransfer !== false;\n\n // Mirrors the engine rule so the approver is stopped in the modal instead of\n // by a server error after submitting.\n const returnCommentRequired =\n currentTaskNode?.type === 'userTask' &&\n currentTaskNode.data.returnBehavior.requireComment === true;\n\n const canAddSignerCurrentTask =\n currentTaskNode?.type === 'userTask' &&\n currentTaskNode.data.allowAddSigner;\n\n const pendingAdhocDirectives = useMemo(\n (): readonly AdhocDirectiveRecord[] =>\n adhocDirectives.filter((directive) => directive.status === 'PENDING'),\n [adhocDirectives],\n );\n\n const selectedReturnTargetOption =\n returnTargetOptions.find((option) => option.id === returnTargetNodeId) ??\n returnTargetOptions[0] ??\n null;\n\n const taskRows = useMemo(\n (): TaskRow[] =>\n tasks.map((task) => ({\n ...task,\n assigneeLabel: readTaskAssigneeLabel(task, memberProfilesById),\n key: task.id,\n // This view holds the snapshot, so it resolves the name itself rather\n // than trusting the server-sent `task.nodeLabel`.\n nodeLabel: readTaskNodeText({\n ...task,\n nodeLabel: readNodeDisplayLabel(\n task.nodeId,\n instance?.workflowSnapshot ?? null,\n ),\n }),\n statusLabel: readTaskStatusLabel(task.status),\n })),\n [instance, memberProfilesById, tasks],\n );\n\n const taskColumns = useMemo(\n (): TableColumn<TaskRow>[] => [\n { dataIndex: 'nodeLabel', key: 'nodeLabel', title: '節點', width: 180 },\n {\n key: 'assigneeMemberId',\n title: '處理者',\n render: (record: TaskRow): ReactElement => (\n <Typography component=\"span\" variant=\"body\">\n {record.assigneeLabel}\n </Typography>\n ),\n width: 180,\n },\n {\n dataIndex: 'statusLabel',\n key: 'statusLabel',\n title: '狀態',\n width: 120,\n },\n {\n key: 'createdAt',\n render: (record: TaskRow): ReactElement => (\n <Typography component=\"span\" variant=\"body\">\n {formatDateTime(record.createdAt)}\n </Typography>\n ),\n title: '建立時間',\n width: 220,\n },\n ],\n [],\n );\n\n const adhocDirectiveRows = useMemo(\n (): AdhocDirectiveRow[] =>\n pendingAdhocDirectives.map((directive) => ({\n ...directive,\n createdByLabel: readMemberDisplayText(\n directive.createdByMemberId,\n memberProfilesById,\n ),\n key: directive.id,\n targetLabel: readAdhocDirectiveTargetLabel(\n directive,\n memberProfilesById,\n ),\n typeLabel: ADHOC_MODE_LABELS[directive.type],\n })),\n [memberProfilesById, pendingAdhocDirectives],\n );\n\n const adhocDirectiveColumns = useMemo(\n (): TableColumn<AdhocDirectiveRow>[] => [\n {\n dataIndex: 'typeLabel',\n key: 'typeLabel',\n title: '類型',\n width: 180,\n },\n {\n key: 'targetLabel',\n render: (record: AdhocDirectiveRow): ReactElement => (\n <Typography component=\"span\" variant=\"body\">\n {record.targetLabel}\n </Typography>\n ),\n title: '對象',\n width: 220,\n },\n {\n key: 'createdByLabel',\n render: (record: AdhocDirectiveRow): ReactElement => (\n <Typography component=\"span\" variant=\"body\">\n {record.createdByLabel}\n </Typography>\n ),\n title: '設定者',\n width: 180,\n },\n {\n key: 'createdAt',\n render: (record: AdhocDirectiveRow): ReactElement => (\n <Typography component=\"span\" variant=\"body\">\n {formatDateTime(record.createdAt)}\n </Typography>\n ),\n title: '建立時間',\n width: 220,\n },\n {\n key: 'actions',\n render: (record: AdhocDirectiveRow): ReactElement =>\n record.createdByMemberId === currentMemberId ? (\n <Button\n disabled={adhocSubmitting}\n onClick={(): void =>\n void handleCancelAdhocDirective(record.id)\n }\n size=\"minor\"\n variant=\"destructive-secondary\"\n >\n 撤回\n </Button>\n ) : (\n <></>\n ),\n title: '操作',\n width: 100,\n },\n ],\n [adhocSubmitting, currentMemberId],\n );\n\n async function handleDecision({\n action,\n comment,\n returnToNodeId = null,\n transferToMemberId = null,\n }: Readonly<{\n action: 'APPROVED' | 'REJECTED' | 'RETURNED' | 'TRANSFERRED';\n comment: string | null;\n returnToNodeId?: string | null;\n transferToMemberId?: string | null;\n }>): Promise<boolean> {\n if (!currentMemberId || !currentTask) {\n return false;\n }\n\n if (action === 'REJECTED' && !canRejectCurrentTask) {\n return false;\n }\n\n if (action === 'TRANSFERRED' && !canTransferCurrentTask) {\n return false;\n }\n\n setDeciding(true);\n setError(null);\n\n try {\n await decideTask({\n action,\n comment,\n decidedByMemberId: currentMemberId,\n returnToNodeId,\n taskId: currentTask.id,\n transferToMemberId,\n });\n setRejectReasonModalOpen(false);\n setReturnModalOpen(false);\n setTransferModalOpen(false);\n setRejectReason('');\n setReturnComment('');\n setTransferComment('');\n setTransferMember(null);\n setReturnTargetNodeId(null);\n setRejectReasonError(null);\n } catch (requestError: unknown) {\n setError(readErrorMessage(requestError));\n setDeciding(false);\n\n return false;\n }\n\n try {\n await onChanged();\n } catch (requestError: unknown) {\n setError(readErrorMessage(requestError));\n } finally {\n setDeciding(false);\n }\n\n return true;\n }\n\n function openApproveModal(): void {\n if (!currentMemberId || !currentTask) {\n return;\n }\n\n setError(null);\n setApproveComment('');\n setApproveModalOpen(true);\n }\n\n function closeApproveModal(): void {\n if (deciding) {\n return;\n }\n\n setApproveModalOpen(false);\n setApproveComment('');\n }\n\n async function handleApproveConfirm(): Promise<void> {\n if (deciding) {\n return;\n }\n\n const succeeded = await handleDecision({\n action: 'APPROVED',\n comment: approveComment.trim() || null,\n });\n\n if (!succeeded) {\n return;\n }\n\n setApproveModalOpen(false);\n setApproveComment('');\n }\n\n function openRejectReasonModal(): void {\n if (!canRejectCurrentTask) {\n return;\n }\n\n setRejectReason('');\n setRejectReasonError(null);\n setRejectReasonModalOpen(true);\n }\n\n function closeRejectReasonModal(): void {\n if (deciding) {\n return;\n }\n\n setRejectReasonModalOpen(false);\n setRejectReason('');\n setRejectReasonError(null);\n }\n\n function openReturnModal(): void {\n setReturnComment('');\n setReturnTargetNodeId(returnTargetOptions[0]?.id ?? null);\n setReturnModalOpen(true);\n }\n\n function closeReturnModal(): void {\n if (deciding) {\n return;\n }\n\n setReturnModalOpen(false);\n setReturnComment('');\n setReturnTargetNodeId(null);\n }\n\n function openTransferModal(): void {\n if (!canTransferCurrentTask) {\n return;\n }\n\n setTransferComment('');\n setTransferMember(null);\n setTransferModalOpen(true);\n void handleSearchTransferMembers('');\n }\n\n function closeTransferModal(): void {\n if (deciding) {\n return;\n }\n\n setTransferModalOpen(false);\n setTransferComment('');\n setTransferMember(null);\n }\n\n async function handleSearchTransferMembers(\n searchText: string,\n ): Promise<void> {\n setTransferMemberLoading(true);\n\n try {\n setTransferMemberOptions(\n (await searchMembers(searchText))\n .filter(\n (searchedMember) => searchedMember.memberId !== currentMemberId,\n )\n .map(readMemberOption),\n );\n } catch (requestError: unknown) {\n setError(readErrorMessage(requestError));\n } finally {\n setTransferMemberLoading(false);\n }\n }\n\n async function handleRejectConfirm(): Promise<void> {\n if (!canRejectCurrentTask) {\n return;\n }\n\n if (!trimmedRejectReason) {\n setRejectReasonError('請輸入拒絕原因');\n\n return;\n }\n\n await handleDecision({\n action: 'REJECTED',\n comment: trimmedRejectReason,\n });\n }\n\n async function handleTransferConfirm(): Promise<void> {\n if (!canTransferCurrentTask) {\n return;\n }\n\n if (!transferMember) {\n setError('請選擇轉派對象');\n\n return;\n }\n\n await handleDecision({\n action: 'TRANSFERRED',\n comment: trimmedTransferComment || null,\n transferToMemberId: transferMember.id,\n });\n }\n\n async function handleReturnConfirm(): Promise<void> {\n await handleDecision({\n action: 'RETURNED',\n comment: trimmedReturnComment || null,\n returnToNodeId: selectedReturnTargetOption?.id ?? null,\n });\n }\n\n function resetAdhocModalState(): void {\n setAdhocComment('');\n setAdhocMembers([]);\n setAdhocOnReject('REJECT_INSTANCE');\n setAdhocTargetKind('MEMBER');\n setAdhocWebhookUrl('');\n }\n\n function openAdhocModal(mode: AdhocActionMode): void {\n setAdhocMode(mode);\n resetAdhocModalState();\n setAdhocModalOpen(true);\n void handleSearchAdhocMembers('');\n }\n\n function closeAdhocModal(): void {\n if (adhocSubmitting) {\n return;\n }\n\n setAdhocModalOpen(false);\n resetAdhocModalState();\n }\n\n async function handleSearchAdhocMembers(searchText: string): Promise<void> {\n setAdhocMemberLoading(true);\n\n try {\n setAdhocMemberOptions(\n (await searchMembers(searchText)).map(readMemberOption),\n );\n } catch (requestError: unknown) {\n setError(readErrorMessage(requestError));\n } finally {\n setAdhocMemberLoading(false);\n }\n }\n\n async function handleAdhocConfirm(): Promise<void> {\n if (!currentTask) {\n return;\n }\n\n const isNotifyMode =\n adhocMode === 'STAGE_NOTIFY' || adhocMode === 'COMPLETION_NOTIFY';\n const useWebhookTarget = isNotifyMode && adhocTargetKind === 'WEBHOOK';\n const targetDraft = readAdhocTargetDraft({\n memberIds: adhocMembers.map((member) => member.id),\n useWebhookTarget,\n webhookUrl: adhocWebhookUrl,\n });\n\n if (!targetDraft.valid) {\n setError(targetDraft.error);\n\n return;\n }\n\n const { target } = targetDraft;\n const trimmedAdhocComment = adhocComment.trim() || null;\n\n setAdhocSubmitting(true);\n setError(null);\n\n try {\n if (adhocMode === 'COUNTERSIGN') {\n await requestAdhocCountersign({\n comment: trimmedAdhocComment,\n target,\n taskId: currentTask.id,\n });\n } else if (adhocMode === 'PRE_APPROVAL') {\n await requestAdhocPreApproval({\n comment: trimmedAdhocComment,\n onReject: adhocOnReject,\n target,\n taskId: currentTask.id,\n });\n } else if (adhocMode === 'STAGE_NOTIFY') {\n await configureAdhocStageNotification({\n target,\n taskId: currentTask.id,\n });\n } else {\n await configureAdhocCompletionNotification({\n target,\n taskId: currentTask.id,\n });\n }\n\n setAdhocModalOpen(false);\n resetAdhocModalState();\n await onChanged();\n } catch (requestError: unknown) {\n setError(readErrorMessage(requestError));\n } finally {\n setAdhocSubmitting(false);\n }\n }\n\n async function handleCancelAdhocDirective(directiveId: string): Promise<void> {\n setAdhocSubmitting(true);\n setError(null);\n\n try {\n await cancelAdhocDirective(directiveId);\n await onChanged();\n } catch (requestError: unknown) {\n setError(readErrorMessage(requestError));\n } finally {\n setAdhocSubmitting(false);\n }\n }\n\n // Expose imperative handle so the container's PageHeader buttons can\n // trigger actions without lifting all modal state up.\n useImperativeHandle(\n ref,\n (): InstanceTasksSectionHandle => ({\n canAddSignerCurrentTask,\n canRejectCurrentTask,\n canReturnCurrentTask,\n canTransferCurrentTask,\n deciding,\n handleApprove: openApproveModal,\n hasCurrentTask: currentTask !== null,\n openAdhocModal,\n openRejectModal: openRejectReasonModal,\n openReturnModal,\n openTransferModal,\n }),\n [\n canAddSignerCurrentTask,\n canRejectCurrentTask,\n canReturnCurrentTask,\n canTransferCurrentTask,\n currentMemberId,\n currentTask,\n deciding,\n ],\n );\n\n const isAdhocNotifyMode =\n adhocMode === 'STAGE_NOTIFY' || adhocMode === 'COMPLETION_NOTIFY';\n const adhocConfirmDisabled =\n isAdhocNotifyMode && adhocTargetKind === 'WEBHOOK'\n ? !adhocWebhookUrl.trim()\n : adhocMembers.length === 0;\n const selectedAdhocOnRejectOption =\n ADHOC_ON_REJECT_OPTIONS.find((option) => option.id === adhocOnReject) ??\n ADHOC_ON_REJECT_OPTIONS[0];\n const selectedAdhocNotifyTargetOption =\n ADHOC_NOTIFY_TARGET_OPTIONS.find(\n (option) => option.id === adhocTargetKind,\n ) ?? ADHOC_NOTIFY_TARGET_OPTIONS[0];\n\n return (\n <>\n <Typography component=\"h2\" variant=\"h3\">\n 任務\n </Typography>\n {error ? (\n <Typography color=\"text-error\" variant=\"body\">\n {error}\n </Typography>\n ) : null}\n <div style={SECTION_TABLE_STYLE}>\n <Table columns={taskColumns} dataSource={taskRows} fullWidth />\n </div>\n\n {pendingAdhocDirectives.length > 0 ? (\n <>\n <Typography component=\"h3\" style={SECTION_SUBHEADING_STYLE} variant=\"h3\">\n 待生效的臨時設定\n </Typography>\n <div style={SECTION_TABLE_STYLE}>\n <Table\n columns={adhocDirectiveColumns}\n dataSource={adhocDirectiveRows}\n fullWidth\n />\n </div>\n </>\n ) : null}\n\n {/* Approve modal — comment is optional, so the confirm button stays enabled */}\n <Modal\n cancelText=\"取消\"\n confirmText=\"送出同意\"\n loading={deciding}\n modalType=\"standard\"\n onCancel={closeApproveModal}\n onClose={closeApproveModal}\n onConfirm={(): void => void handleApproveConfirm()}\n open={approveModalOpen}\n showModalFooter\n showModalHeader\n size=\"regular\"\n supportingText=\"可以留下同意的說明,內容會記錄在簽核歷程;不填也可以直接送出。\"\n title=\"簽核意見\"\n >\n {error ? (\n <Typography color=\"text-error\" role=\"alert\" variant=\"body\">\n {error}\n </Typography>\n ) : null}\n <div style={REJECT_REASON_FORM_STYLE}>\n <BPMFormField label=\"簽核意見\" name=\"approveComment\">\n <Textarea\n autoFocus\n onChange={(event: ChangeEvent<HTMLTextAreaElement>): void =>\n setApproveComment(event.target.value)\n }\n placeholder=\"選填,例如補充核准的條件或提醒事項\"\n ref={applyFullWidthTextareaHost}\n resize=\"vertical\"\n rows={4}\n style={REJECT_REASON_TEXTAREA_STYLE}\n value={approveComment}\n />\n </BPMFormField>\n </div>\n </Modal>\n\n {/* Reject modal */}\n <Modal\n cancelText=\"取消\"\n confirmButtonProps={{\n disabled: !trimmedRejectReason,\n variant: 'destructive-primary',\n }}\n confirmText=\"送出拒絕\"\n loading={deciding}\n modalStatusType=\"error\"\n modalType=\"standard\"\n onCancel={closeRejectReasonModal}\n onClose={closeRejectReasonModal}\n onConfirm={(): void => void handleRejectConfirm()}\n open={rejectReasonModalOpen}\n showModalFooter\n showModalHeader\n size=\"regular\"\n supportingText=\"拒絕案件時必須留下原因,供發起人與後續追蹤查看。\"\n title=\"拒絕原因\"\n >\n <div style={REJECT_REASON_FORM_STYLE}>\n <BPMFormField label=\"拒絕原因\" name=\"rejectReason\" required>\n <Textarea\n autoFocus\n onChange={(event: ChangeEvent<HTMLTextAreaElement>): void => {\n setRejectReason(event.target.value);\n setRejectReasonError(null);\n }}\n placeholder=\"請說明拒絕原因\"\n ref={applyFullWidthTextareaHost}\n resize=\"vertical\"\n rows={4}\n style={REJECT_REASON_TEXTAREA_STYLE}\n type={rejectReasonError ? 'error' : 'default'}\n value={rejectReason}\n />\n </BPMFormField>\n {rejectReasonError ? (\n <Typography color=\"text-error\" variant=\"body\">\n {rejectReasonError}\n </Typography>\n ) : null}\n </div>\n </Modal>\n\n {/* Transfer modal */}\n <Modal\n cancelText=\"取消\"\n confirmButtonProps={{\n disabled: !transferMember,\n }}\n confirmText=\"送出轉派\"\n loading={deciding}\n modalType=\"standard\"\n onCancel={closeTransferModal}\n onClose={closeTransferModal}\n onConfirm={(): void => void handleTransferConfirm()}\n open={transferModalOpen}\n showModalFooter\n showModalHeader\n size=\"regular\"\n supportingText=\"轉派後,原任務會保留轉派紀錄,新的待簽任務會指派給指定成員。\"\n title=\"轉派簽核\"\n >\n <div style={MODAL_FORM_STYLE}>\n <BPMFormField label=\"轉派對象\" name=\"transferToMemberId\" required>\n <AutoComplete\n asyncData\n disabledOptionsFilter\n emptyText=\"沒有符合的成員\"\n inputProps={{\n autoCapitalize: 'none',\n autoCorrect: 'off',\n name: 'transfer-member-search',\n spellCheck: false,\n }}\n loading={transferMemberLoading}\n loadingText=\"搜尋成員中...\"\n mode=\"single\"\n onChange={(option): void =>\n setTransferMember(readMemberOptionFromValue(option))\n }\n onSearch={handleSearchTransferMembers}\n onSearchTextChange={(searchText): void =>\n setTransferMember(\n readUniqueMemberOption(searchText, transferMemberOptions),\n )\n }\n onVisibilityChange={(open): void => {\n if (open) {\n void handleSearchTransferMembers('');\n }\n }}\n options={[...transferMemberOptions]}\n placeholder=\"搜尋姓名或信箱\"\n searchDebounceTime={300}\n value={transferMember}\n />\n </BPMFormField>\n <BPMFormField label=\"轉派說明\" name=\"transferComment\">\n <Textarea\n onChange={(event: ChangeEvent<HTMLTextAreaElement>): void =>\n setTransferComment(event.target.value)\n }\n placeholder=\"可補充轉派原因\"\n ref={applyFullWidthTextareaHost}\n resize=\"vertical\"\n rows={4}\n style={REJECT_REASON_TEXTAREA_STYLE}\n value={transferComment}\n />\n </BPMFormField>\n </div>\n </Modal>\n\n {/* Return modal */}\n <Modal\n cancelText=\"取消\"\n confirmButtonProps={{\n disabled:\n !selectedReturnTargetOption ||\n (returnCommentRequired && !trimmedReturnComment),\n }}\n confirmText=\"送出退回\"\n loading={deciding}\n modalType=\"standard\"\n onCancel={closeReturnModal}\n onClose={closeReturnModal}\n onConfirm={(): void => void handleReturnConfirm()}\n open={returnModalOpen}\n showModalFooter\n showModalHeader\n size=\"regular\"\n supportingText=\"退回後,流程會回到指定節點並等待重新處理。\"\n title=\"退回簽核\"\n >\n <div style={MODAL_FORM_STYLE}>\n <BPMFormField label=\"退回節點\" name=\"returnTargetNodeId\" required>\n <Select\n clearable={false}\n fullWidth\n onChange={(option): void =>\n setReturnTargetNodeId(option?.id ?? null)\n }\n options={[...returnTargetOptions]}\n placeholder=\"選擇退回節點\"\n value={selectedReturnTargetOption}\n />\n </BPMFormField>\n <BPMFormField\n hintText={\n returnCommentRequired ? '此關卡設定退回時必須填寫意見。' : undefined\n }\n label=\"退回說明\"\n name=\"returnComment\"\n required={returnCommentRequired}\n >\n <Textarea\n onChange={(event: ChangeEvent<HTMLTextAreaElement>): void =>\n setReturnComment(event.target.value)\n }\n placeholder={\n returnCommentRequired\n ? '請說明退回原因'\n : '可補充需要修改的內容'\n }\n ref={applyFullWidthTextareaHost}\n resize=\"vertical\"\n rows={4}\n style={REJECT_REASON_TEXTAREA_STYLE}\n value={returnComment}\n />\n </BPMFormField>\n </div>\n </Modal>\n\n {/* Ad-hoc countersign / pre-approval / notify modal */}\n <Modal\n cancelText=\"取消\"\n confirmButtonProps={{\n disabled: adhocConfirmDisabled,\n }}\n confirmText=\"送出\"\n loading={adhocSubmitting}\n modalType=\"standard\"\n onCancel={closeAdhocModal}\n onClose={closeAdhocModal}\n onConfirm={(): void => void handleAdhocConfirm()}\n open={adhocModalOpen}\n showModalFooter\n showModalHeader\n size=\"regular\"\n supportingText={ADHOC_MODE_SUPPORTING_TEXT[adhocMode]}\n title={ADHOC_MODE_LABELS[adhocMode]}\n >\n <div style={MODAL_FORM_STYLE}>\n {isAdhocNotifyMode ? (\n <BPMFormField label=\"通知時機\" name=\"adhocNotifyMode\" required>\n <Select\n clearable={false}\n fullWidth\n onChange={(option): void =>\n setAdhocMode(\n option?.id === 'COMPLETION_NOTIFY'\n ? 'COMPLETION_NOTIFY'\n : 'STAGE_NOTIFY',\n )\n }\n options={[\n { id: 'STAGE_NOTIFY', name: ADHOC_MODE_LABELS.STAGE_NOTIFY },\n {\n id: 'COMPLETION_NOTIFY',\n name: ADHOC_MODE_LABELS.COMPLETION_NOTIFY,\n },\n ]}\n value={{\n id: adhocMode,\n name: ADHOC_MODE_LABELS[adhocMode],\n }}\n />\n </BPMFormField>\n ) : null}\n {isAdhocNotifyMode ? (\n <BPMFormField label=\"通知對象類型\" name=\"adhocTargetKind\" required>\n <Select\n clearable={false}\n fullWidth\n onChange={(option): void =>\n setAdhocTargetKind(\n option?.id === 'WEBHOOK' ? 'WEBHOOK' : 'MEMBER',\n )\n }\n options={[...ADHOC_NOTIFY_TARGET_OPTIONS]}\n value={selectedAdhocNotifyTargetOption}\n />\n </BPMFormField>\n ) : null}\n {isAdhocNotifyMode && adhocTargetKind === 'WEBHOOK' ? (\n <BPMFormField label=\"Webhook URL\" name=\"adhocWebhookUrl\" required>\n <Input\n fullWidth\n onChange={(event: ChangeEvent<HTMLInputElement>): void =>\n setAdhocWebhookUrl(event.target.value)\n }\n placeholder=\"https://example.com/webhook\"\n value={adhocWebhookUrl}\n />\n </BPMFormField>\n ) : (\n <BPMFormField\n label={isAdhocNotifyMode ? '通知對象' : '簽核對象'}\n name=\"adhocMemberId\"\n required\n >\n <AutoComplete\n asyncData\n disabledOptionsFilter\n emptyText=\"沒有符合的成員\"\n inputProps={{\n autoCapitalize: 'none',\n autoCorrect: 'off',\n name: 'adhoc-member-search',\n spellCheck: false,\n }}\n loading={adhocMemberLoading}\n loadingText=\"搜尋成員中...\"\n menuMaxHeight={320}\n mode=\"multiple\"\n onChange={(options): void =>\n setAdhocMembers(\n options\n .map(readMemberOptionFromValue)\n .filter(isPresentMemberOption),\n )\n }\n onSearch={handleSearchAdhocMembers}\n onVisibilityChange={(open): void => {\n if (open) {\n void handleSearchAdhocMembers('');\n }\n }}\n options={[...adhocMemberOptions]}\n overflowStrategy=\"wrap\"\n placeholder=\"搜尋姓名或信箱,可加入多位\"\n searchDebounceTime={300}\n value={[...adhocMembers]}\n />\n </BPMFormField>\n )}\n {adhocMode === 'PRE_APPROVAL' ? (\n <BPMFormField label=\"拒簽處理方式\" name=\"adhocOnReject\" required>\n <Select\n clearable={false}\n fullWidth\n onChange={(option): void =>\n setAdhocOnReject(\n option?.id === 'RETURN_TO_ORIGIN'\n ? 'RETURN_TO_ORIGIN'\n : 'REJECT_INSTANCE',\n )\n }\n options={[...ADHOC_ON_REJECT_OPTIONS]}\n value={selectedAdhocOnRejectOption}\n />\n </BPMFormField>\n ) : null}\n {!isAdhocNotifyMode ? (\n <BPMFormField label=\"說明\" name=\"adhocComment\">\n <Textarea\n onChange={(event: ChangeEvent<HTMLTextAreaElement>): void =>\n setAdhocComment(event.target.value)\n }\n placeholder=\"可補充原因\"\n ref={applyFullWidthTextareaHost}\n resize=\"vertical\"\n rows={3}\n style={REJECT_REASON_TEXTAREA_STYLE}\n value={adhocComment}\n />\n </BPMFormField>\n ) : null}\n </div>\n </Modal>\n </>\n );\n});\n\nfunction readAdhocDirectiveTargetLabel(\n directive: AdhocDirectiveRecord,\n memberProfilesById: ReadonlyMap<string, MemberProfileRecord>,\n): string {\n try {\n const value = JSON.parse(directive.targetValueJson) as {\n readonly memberIds?: readonly string[];\n readonly orgUnitId?: string;\n readonly positionId?: string;\n readonly webhookUrl?: string;\n };\n\n if (value.memberIds?.length) {\n return value.memberIds\n .map(\n (memberId) => readMemberDisplayText(memberId, memberProfilesById),\n )\n .join('、');\n }\n\n if (value.webhookUrl) {\n return value.webhookUrl;\n }\n\n if (value.positionId) {\n return `職位 ${value.positionId}`;\n }\n\n if (value.orgUnitId) {\n return `部門 ${value.orgUnitId}`;\n }\n } catch {\n // Fall through to the kind label below.\n }\n\n return directive.targetKind;\n}\n","'use client';\n\nimport { CSSProperties, ReactElement, useMemo } from 'react';\nimport { Table, Typography } from '@mezzanine-ui/react';\nimport type { TableColumn } from '@mezzanine-ui/core/table';\nimport {\n SignatureRecord,\n SignatureVerificationRecord,\n} from '@rytass/bpm-core-client/workflow';\nimport { formatDateTime } from '../../../../lib/format-date-time';\nimport { SignatureRow, readShortHash } from './shared';\n\nconst SECTION_BODY_STYLE: CSSProperties = {\n display: 'grid',\n gap: 16,\n};\n\nexport interface InstanceSignaturesSectionProps {\n /** The list of signatures for this instance. */\n readonly signatures: readonly SignatureRecord[];\n /** The signature chain verification result, or null if not yet loaded. */\n readonly signatureVerification: SignatureVerificationRecord | null;\n}\n\n/**\n * Renders the signatures section of the approval instance detail page.\n * Shows the signature chain verification status and a table of individual\n * signature records.\n */\nexport function InstanceSignaturesSection({\n signatureVerification,\n signatures,\n}: InstanceSignaturesSectionProps): ReactElement {\n const signatureRows = useMemo(\n (): SignatureRow[] =>\n signatures.map((signature) => ({\n algorithm: signature.algorithm,\n hashLabel: readShortHash(signature.signedPayloadHash),\n key: signature.id,\n keyVersion: signature.keyVersion,\n signedAtLabel: formatDateTime(signature.signedAt),\n signerMemberId: signature.signerMemberId,\n })),\n [signatures],\n );\n\n const signatureColumns = useMemo(\n (): TableColumn<SignatureRow>[] => [\n {\n dataIndex: 'signerMemberId',\n key: 'signerMemberId',\n title: '簽章者',\n width: 160,\n },\n { dataIndex: 'algorithm', key: 'algorithm', title: '演算法', width: 150 },\n {\n dataIndex: 'keyVersion',\n key: 'keyVersion',\n title: 'Key 版本',\n width: 100,\n },\n {\n dataIndex: 'hashLabel',\n key: 'hashLabel',\n title: 'Payload Hash',\n width: 180,\n },\n {\n dataIndex: 'signedAtLabel',\n key: 'signedAtLabel',\n title: '簽章時間',\n width: 220,\n },\n ],\n [],\n );\n\n return (\n <div style={SECTION_BODY_STYLE}>\n <Typography component=\"h2\" variant=\"h3\">\n 簽章\n </Typography>\n <Typography\n color={\n signatureVerification?.valid ? 'text-success' : 'text-error'\n }\n variant=\"body\"\n >\n {signatureVerification\n ? signatureVerification.valid\n ? `簽章鏈已驗證,共 ${signatureVerification.checkedCount} 筆。`\n : `簽章鏈驗證失敗:${signatureVerification.errors.join('、')}`\n : '尚無簽章紀錄。'}\n </Typography>\n {signatureRows.length > 0 ? (\n <Table\n columns={signatureColumns}\n dataSource={signatureRows}\n fullWidth\n />\n ) : null}\n </div>\n );\n}\n","'use client';\n\nimport {\n CSSProperties,\n Fragment,\n ReactElement,\n RefCallback,\n forwardRef,\n} from 'react';\nimport {\n Stepper,\n Tooltip,\n Typography,\n type StepProps,\n} from '@mezzanine-ui/react';\nimport { stepClasses } from '@mezzanine-ui/core/stepper';\nimport {\n ActivityLogRecord,\n ApprovalInstanceRecord,\n MemberProfileRecord,\n SignatureRecord,\n SignatureVerificationRecord,\n TaskDecisionRecord,\n TaskRecord,\n WorkflowTokenRecord,\n} from '@rytass/bpm-core-client/workflow';\nimport { WorkflowDefinition } from '@rytass/bpm-core-shared/workflow';\nimport {\n ActivityStepDescriptionPart,\n ActivityStepRecord,\n isActivityDescriptionPart,\n isPresentText,\n readActivityStepRecords,\n readCurrentActivityStep,\n} from './shared';\n\nconst SECTION_BODY_STYLE: CSSProperties = {\n display: 'grid',\n gap: 16,\n};\n\nconst HISTORY_MEMBER_NAME_STYLE: CSSProperties = {\n cursor: 'help',\n textDecoration: 'underline dotted',\n textUnderlineOffset: 3,\n};\n\n// An approval comment is the one part of a timeline entry a person wrote, so\n// it gets its own line and a readable size instead of being appended to the\n// metadata run.\n// It is set one step above body text — the h3 size and line height, at body\n// weight — so it reads as the content of the entry rather than as more\n// metadata, without competing with the section heading, which is h3 itself.\n// The border is written as longhands so the danger tone can override only its\n// colour; mixing `borderLeft` with a `borderLeftColor` override in one style\n// object makes the result depend on key order and warns in React dev mode.\nconst HISTORY_COMMENT_STYLE: CSSProperties = {\n borderLeftColor: 'var(--mzn-color-border)',\n borderLeftStyle: 'solid',\n borderLeftWidth: 2,\n fontSize: 'var(--mzn-typography-h3-font-size)',\n lineHeight: 'var(--mzn-typography-h3-line-height)',\n marginTop: 4,\n paddingLeft: 8,\n whiteSpace: 'pre-wrap',\n};\n\nconst HISTORY_COMMENT_LABEL_STYLE: CSSProperties = {\n color: 'var(--mzn-color-text-secondary)',\n};\n\n// A rejection reason has to read as a rejection, so it carries the error colour\n// itself — label included, which is why the label drops its own colour in this\n// tone.\nconst HISTORY_COMMENT_DANGER_STYLE: CSSProperties = {\n ...HISTORY_COMMENT_STYLE,\n borderLeftColor: 'var(--mzn-color-text-error)',\n color: 'var(--mzn-color-text-error)',\n};\n\nfunction joinClassNames(\n ...classNames: readonly (string | null | undefined)[]\n): string {\n return classNames\n .filter((className): className is string =>\n isPresentText(className ?? null),\n )\n .join(' ');\n}\n\ninterface ActivityHistoryStepProps extends StepProps {\n readonly descriptionParts: readonly ActivityStepDescriptionPart[];\n readonly forcePending?: boolean;\n}\n\nconst ActivityHistoryStep = forwardRef<\n HTMLDivElement,\n ActivityHistoryStepProps\n>(function ActivityHistoryStep(\n {\n className,\n descriptionParts,\n error,\n forcePending = false,\n index = 0,\n orientation,\n status = 'pending',\n title,\n type = 'number',\n ...rest\n },\n ref,\n): ReactElement {\n const displayStatus = forcePending ? 'pending' : status;\n const inlineDescriptionParts = descriptionParts.filter(\n (part): part is Exclude<ActivityStepDescriptionPart, { type: 'comment' }> =>\n part.type !== 'comment',\n );\n const commentDescriptionParts = descriptionParts.filter(\n (part): part is Extract<ActivityStepDescriptionPart, { type: 'comment' }> =>\n part.type === 'comment',\n );\n\n return (\n <div\n {...rest}\n className={joinClassNames(\n stepClasses.host,\n type === 'dot' ? stepClasses.dot : null,\n error && displayStatus !== 'processing' ? stepClasses.error : null,\n orientation === 'horizontal' ? stepClasses.horizontal : null,\n type === 'number' ? stepClasses.number : null,\n displayStatus === 'pending' ? stepClasses.pending : null,\n displayStatus === 'processing' ? stepClasses.processing : null,\n error && displayStatus === 'processing'\n ? stepClasses.processingError\n : null,\n !error && displayStatus === 'succeeded' ? stepClasses.succeeded : null,\n orientation === 'vertical' ? stepClasses.vertical : null,\n className,\n )}\n ref={ref}\n >\n {type === 'dot' ? (\n <span\n className={joinClassNames(\n stepClasses.statusIndicator,\n stepClasses.statusIndicatorDot,\n )}\n />\n ) : (\n <span className={stepClasses.statusIndicator}>{index + 1}</span>\n )}\n <div className={stepClasses.textContainer}>\n <Typography\n className={stepClasses.title}\n variant=\"label-primary-highlight\"\n >\n {title}\n <span className={stepClasses.titleConnectLine} />\n </Typography>\n {inlineDescriptionParts.length > 0 ? (\n <Typography className={stepClasses.description} variant=\"caption\">\n {inlineDescriptionParts.map((part, partIndex) => (\n <Fragment key={`${part.type}-${partIndex}`}>\n {partIndex > 0 ? ' · ' : null}\n {renderActivityDescriptionPart(part)}\n </Fragment>\n ))}\n </Typography>\n ) : null}\n {commentDescriptionParts.map((part, partIndex) => (\n <Typography\n key={`comment-${partIndex}`}\n style={\n part.tone === 'danger'\n ? HISTORY_COMMENT_DANGER_STYLE\n : HISTORY_COMMENT_STYLE\n }\n variant=\"body\"\n >\n <span\n style={\n part.tone === 'danger' ? undefined : HISTORY_COMMENT_LABEL_STYLE\n }\n >\n {part.label}:\n </span>\n {part.text}\n </Typography>\n ))}\n </div>\n </div>\n );\n});\n\n// Comment parts are rendered on their own line by the caller, so they never\n// reach this inline renderer.\nfunction renderActivityDescriptionPart(\n part: Exclude<ActivityStepDescriptionPart, { type: 'comment' }>,\n): ReactElement | string {\n if (part.type === 'text') {\n return part.text;\n }\n\n if (!part.email?.trim()) {\n return `${part.prefix}:${part.label}`;\n }\n\n return (\n <>\n {part.prefix}:\n <Tooltip title={part.email}>\n {({ ref, ...tooltipProps }): ReactElement => (\n // Spread the whole payload, as `TooltipProps` asks: picking only the\n // mouse handlers drops `aria-describedby`, so assistive tech never\n // learns the open tooltip describes this name.\n <span\n {...tooltipProps}\n data-testid={\n part.memberId ? `member-tooltip-${part.memberId}` : undefined\n }\n ref={ref as RefCallback<HTMLSpanElement>}\n style={HISTORY_MEMBER_NAME_STYLE}\n >\n {part.label}\n </span>\n )}\n </Tooltip>\n </>\n );\n}\n\nexport interface InstanceHistorySectionProps {\n /** Activity log records for this instance. */\n readonly activityLogs: readonly ActivityLogRecord[];\n /** All tasks for this instance (used to compute pending/future steps). */\n readonly tasks: readonly TaskRecord[];\n /** All workflow tokens for this instance. */\n readonly workflowTokens: readonly WorkflowTokenRecord[];\n /** The workflow definition snapshot, or null if not yet loaded. */\n readonly workflowSnapshot: WorkflowDefinition | null;\n /** The current state of the instance. */\n readonly instanceState: ApprovalInstanceRecord['state'];\n /** Member profiles indexed by memberId. */\n readonly memberProfilesById: ReadonlyMap<string, MemberProfileRecord>;\n /** Task decisions indexed by taskId (latest per task). */\n readonly taskDecisionsByTaskId: ReadonlyMap<string, TaskDecisionRecord>;\n /** Signatures indexed by id. */\n readonly signaturesById: ReadonlyMap<string, SignatureRecord>;\n /** Signature chain verification result, or null. */\n readonly signatureVerification: SignatureVerificationRecord | null;\n}\n\n/**\n * Renders the activity history section of the approval instance detail page.\n * Computes the step records from the provided data and renders them as a\n * vertical dot stepper.\n */\nexport function InstanceHistorySection({\n activityLogs,\n instanceState,\n memberProfilesById,\n signatureVerification,\n signaturesById,\n taskDecisionsByTaskId,\n tasks,\n workflowSnapshot,\n workflowTokens,\n}: InstanceHistorySectionProps): ReactElement {\n const activitySteps: readonly ActivityStepRecord[] = readActivityStepRecords(\n activityLogs,\n tasks,\n workflowTokens,\n workflowSnapshot,\n instanceState,\n memberProfilesById,\n taskDecisionsByTaskId,\n signaturesById,\n signatureVerification,\n );\n\n const currentActivityStep = readCurrentActivityStep(activitySteps);\n\n const filteredDescriptionParts = activitySteps.map((step) => ({\n ...step,\n descriptionParts: step.descriptionParts.filter(isActivityDescriptionPart),\n }));\n\n return (\n <div style={SECTION_BODY_STYLE}>\n <Typography component=\"h2\" variant=\"h3\">\n 歷程\n </Typography>\n {filteredDescriptionParts.length > 0 ? (\n <Stepper\n currentStep={currentActivityStep}\n orientation=\"vertical\"\n type=\"dot\"\n >\n {filteredDescriptionParts.map((activityStep) => (\n <ActivityHistoryStep\n descriptionParts={activityStep.descriptionParts}\n error={activityStep.error}\n forcePending={activityStep.forcePending}\n key={activityStep.id}\n title={activityStep.title}\n />\n ))}\n </Stepper>\n ) : (\n <Typography color=\"text-neutral\" variant=\"body\">\n 尚無歷程紀錄。\n </Typography>\n )}\n </div>\n );\n}\n","'use client';\n\nimport { CSSProperties, ReactElement, useMemo, useState } from 'react';\nimport { Badge, Modal, Table, Typography } from '@mezzanine-ui/react';\nimport { ResetIcon } from '@mezzanine-ui/icons';\nimport type { TableActions, TableColumn } from '@mezzanine-ui/core/table';\nimport {\n WorkflowWebhookDeliveryRecord,\n WorkflowWebhookDeliveryStatus,\n} from '@rytass/bpm-core-client/workflow';\nimport { formatDateTime } from '../../../../lib/format-date-time';\n\nconst SECTION_BODY_STYLE: CSSProperties = {\n display: 'grid',\n gap: 16,\n};\n\nconst CELL_STACK_STYLE: CSSProperties = {\n display: 'grid',\n gap: 2,\n};\n\nconst ERROR_DETAIL_STYLE: CSSProperties = {\n overflowWrap: 'anywhere',\n whiteSpace: 'pre-wrap',\n};\n\ntype WebhookDeliveryRow = Readonly<\n Record<string, unknown> & {\n delivery: WorkflowWebhookDeliveryRecord;\n key: string;\n }\n>;\n\nexport interface InstanceWebhookDeliveriesSectionProps {\n /** The instance's notify-node webhook deliveries, oldest first. */\n readonly deliveries: readonly WorkflowWebhookDeliveryRecord[];\n /** Resolves a node id to the label shown to the reader. */\n readonly readNodeLabel: (nodeId: string) => string;\n /**\n * Re-queues a `FAILED` delivery. A rejection is shown in the section, so\n * the caller only needs to refresh what it displays on success.\n */\n readonly onRetry: (delivery: WorkflowWebhookDeliveryRecord) => Promise<void>;\n}\n\n/**\n * Administrator-only view of the webhooks this instance's notify nodes sent\n * (ADR 18 §3.10): where each delivery stands, how many attempts it took, the\n * last error, and a retry for the ones that gave up. Carries no URL or\n * payload — the server never sends them to the browser.\n */\nexport function InstanceWebhookDeliveriesSection({\n deliveries,\n onRetry,\n readNodeLabel,\n}: InstanceWebhookDeliveriesSectionProps): ReactElement {\n const [confirming, setConfirming] =\n useState<WorkflowWebhookDeliveryRecord | null>(null);\n const [retrying, setRetrying] = useState(false);\n const [error, setError] = useState<string | null>(null);\n\n const rows = useMemo(\n (): WebhookDeliveryRow[] =>\n deliveries.map((delivery) => ({ delivery, key: delivery.id })),\n [deliveries],\n );\n\n const columns = useMemo(\n (): TableColumn<WebhookDeliveryRow>[] => [\n {\n key: 'endpoint',\n render: ({ delivery }: WebhookDeliveryRow): ReactElement => (\n <div style={CELL_STACK_STYLE}>\n <Typography component=\"span\" variant=\"body\">\n {delivery.endpointLabel ?? delivery.endpointKey}\n </Typography>\n <Typography color=\"text-neutral\" component=\"span\" variant=\"caption\">\n {delivery.endpointKey}@{delivery.endpointVersion} ·{' '}\n {readNodeLabel(delivery.nodeId)}\n </Typography>\n </div>\n ),\n title: '外部系統',\n width: 240,\n },\n {\n key: 'status',\n render: ({ delivery }: WebhookDeliveryRow): ReactElement => (\n <WebhookDeliveryStatusBadge status={delivery.status} />\n ),\n title: '狀態',\n width: 120,\n },\n {\n key: 'attemptCount',\n render: ({ delivery }: WebhookDeliveryRow): ReactElement => (\n <Typography component=\"span\" variant=\"body\">\n {delivery.attemptCount}\n </Typography>\n ),\n title: '嘗試次數',\n width: 100,\n },\n {\n key: 'lastError',\n render: ({ delivery }: WebhookDeliveryRow): ReactElement =>\n delivery.lastErrorCode && delivery.status !== 'SENT' ? (\n <div style={CELL_STACK_STYLE}>\n <Typography color=\"text-error\" component=\"span\" variant=\"body\">\n {delivery.lastErrorCode}\n </Typography>\n {delivery.lastErrorDetail ? (\n <Typography\n color=\"text-neutral\"\n component=\"span\"\n style={ERROR_DETAIL_STYLE}\n variant=\"caption\"\n >\n {delivery.lastErrorDetail}\n </Typography>\n ) : null}\n </div>\n ) : (\n <Typography color=\"text-neutral\" component=\"span\" variant=\"body\">\n —\n </Typography>\n ),\n title: '最後錯誤',\n width: 280,\n },\n {\n key: 'time',\n render: ({ delivery }: WebhookDeliveryRow): ReactElement => (\n <Typography component=\"span\" variant=\"body\">\n {readDeliveryTimeLabel(delivery)}\n </Typography>\n ),\n title: '時間',\n width: 220,\n },\n ],\n [readNodeLabel],\n );\n\n const actions = useMemo(\n (): TableActions<WebhookDeliveryRow> => ({\n render: ({\n delivery,\n }): ReturnType<TableActions<WebhookDeliveryRow>['render']> =>\n // A row that failed while being queued was never sent and its frozen\n // event never passed the parameter checks; the server refuses it too.\n delivery.status === 'FAILED' && delivery.attemptCount > 0\n ? [\n {\n disabled: (): boolean => retrying,\n icon: ResetIcon,\n iconType: 'leading',\n name: '重新傳送',\n onClick: (): void => {\n setError(null);\n setConfirming(delivery);\n },\n },\n ]\n : [],\n variant: 'base-secondary',\n width: 140,\n }),\n [retrying],\n );\n\n async function handleConfirmRetry(): Promise<void> {\n if (!confirming) {\n return;\n }\n\n setRetrying(true);\n setError(null);\n\n try {\n await onRetry(confirming);\n setConfirming(null);\n } catch (retryError: unknown) {\n setConfirming(null);\n setError(\n retryError instanceof Error && retryError.message\n ? retryError.message\n : '重新傳送失敗,請稍後再試。',\n );\n } finally {\n setRetrying(false);\n }\n }\n\n return (\n <div style={SECTION_BODY_STYLE}>\n <Typography component=\"h2\" variant=\"h3\">\n 外部系統通知\n </Typography>\n {error ? (\n <Typography color=\"text-error\" variant=\"body\">\n {error}\n </Typography>\n ) : null}\n {rows.length > 0 ? (\n <Table\n actions={actions}\n columns={columns}\n dataSource={rows}\n fullWidth\n />\n ) : (\n <Typography color=\"text-neutral\" variant=\"body\">\n 此案件沒有外部系統通知。\n </Typography>\n )}\n <Modal\n cancelText=\"取消\"\n confirmText=\"重新傳送\"\n loading={retrying}\n modalStatusType=\"info\"\n modalType=\"standard\"\n onCancel={(): void => setConfirming(null)}\n onClose={(): void => setConfirming(null)}\n onConfirm={(): void => void handleConfirmRetry()}\n open={Boolean(confirming)}\n showModalFooter\n showModalHeader\n supportingText=\"會以相同的投遞編號重新送出,接收端可據此避免重複處理。\"\n title=\"重新傳送通知\"\n >\n <Typography variant=\"body\">\n 確定要重新通知「\n {confirming?.endpointLabel ?? confirming?.endpointKey ?? ''}」嗎?\n </Typography>\n </Modal>\n </div>\n );\n}\n\nfunction WebhookDeliveryStatusBadge({\n status,\n}: {\n readonly status: WorkflowWebhookDeliveryStatus;\n}): ReactElement {\n if (status === 'SENT') {\n return <Badge size=\"sub\" text=\"已送達\" variant=\"dot-success\" />;\n }\n\n if (status === 'FAILED') {\n return <Badge size=\"sub\" text=\"失敗\" variant=\"dot-error\" />;\n }\n\n return (\n <Badge\n size=\"sub\"\n text={status === 'PENDING' ? '等待傳送' : '傳送中'}\n variant=\"dot-info\"\n />\n );\n}\n\nfunction readDeliveryTimeLabel(\n delivery: WorkflowWebhookDeliveryRecord,\n): string {\n if (delivery.sentAt) {\n return `送達:${formatDateTime(delivery.sentAt)}`;\n }\n\n if (delivery.status === 'PENDING' && delivery.nextRetryAt) {\n return `下次重試:${formatDateTime(delivery.nextRetryAt)}`;\n }\n\n return delivery.lastAttemptAt\n ? `最後嘗試:${formatDateTime(delivery.lastAttemptAt)}`\n : `建立:${formatDateTime(delivery.createdAt)}`;\n}\n","'use client';\n\nimport {\n CSSProperties,\n ReactElement,\n useCallback,\n useEffect,\n useMemo,\n useRef,\n useState,\n} from 'react';\nimport {\n Background,\n Controls,\n Handle,\n Position,\n ReactFlow,\n type Edge as FlowEdge,\n type Node as FlowNode,\n type NodeProps,\n} from '@xyflow/react';\n// xyflow v12 ships no runtime style injection — the stylesheet must be bundled\n// or every ReactFlow surface renders unpositioned. See org-unit-tree-draft-editor.\nimport '@xyflow/react/dist/style.css';\nimport * as dagre from 'dagre';\nimport {\n Button,\n Modal,\n PageHeader,\n Section,\n SectionGroup,\n Textarea,\n Typography,\n} from '@mezzanine-ui/react';\nimport ContentHeader from '@mezzanine-ui/react/ContentHeader';\nimport {\n CheckedIcon,\n DangerousOutlineIcon,\n NotificationUnreadIcon,\n PlusIcon,\n RefreshCcwIcon,\n ShareIcon,\n UserIcon,\n} from '@mezzanine-ui/icons';\nimport { FormFieldDefinition } from '@rytass/bpm-core-shared/form';\nimport {\n WorkflowDefinition,\n WorkflowNode,\n} from '@rytass/bpm-core-shared/workflow';\nimport {\n buildFormRendererValues,\n focusFormRendererField,\n validateFormRendererValues,\n} from '@rytass/bpm-core-client/form';\nimport {\n ActivityLogRecord,\n AdhocDirectiveRecord,\n AttachmentRecord,\n ApprovalInstanceRecord,\n MemberProfileRecord,\n SignatureRecord,\n SignatureVerificationRecord,\n cancelApprovalInstance,\n listAdhocDirectives,\n listAttachments,\n readApprovalInstance,\n readAttachmentDownloadUrl,\n readAttachmentPreviewUrl,\n readInstanceSignatures,\n listWorkflowWebhookDeliveries,\n resubmitApprovalInstance,\n retryWorkflowWebhookDelivery,\n TaskDecisionRecord,\n TaskRecord,\n WorkflowFormData,\n WorkflowTokenRecord,\n WorkflowWebhookDeliveryRecord,\n uploadAttachment,\n} from '@rytass/bpm-core-client/workflow';\nimport { BPMFormField } from '../../../components/bpm-form-field';\nimport { formatDateTime } from '../../../lib/format-date-time';\nimport { useAuth } from '../../../lib/auth-provider';\nimport { isBPMAdminMember } from '../../../lib/use-bpm-member';\nimport { PDFPreview } from '../../../components/pdf-preview';\nimport {\n canMemberActOnTask,\n readErrorMessage,\n readInstanceStateLabel,\n readLatestTaskDecisionsByTaskId,\n readMemberProfilesForTimeline,\n readNodeRuntimeState,\n readTaskDecisionsForTasks,\n} from './sections/container-helpers';\nimport { InstanceFormSection } from './sections/InstanceFormSection';\nimport { InstanceAttachmentsSection } from './sections/InstanceAttachmentsSection';\nimport {\n InstanceTasksSection,\n type InstanceTasksSectionHandle,\n} from './sections/InstanceTasksSection';\nimport { InstanceSignaturesSection } from './sections/InstanceSignaturesSection';\nimport { InstanceHistorySection } from './sections/InstanceHistorySection';\nimport { InstanceWebhookDeliveriesSection } from './sections/InstanceWebhookDeliveriesSection';\nimport { isPresentText, readNodeDisplayLabel } from './sections/shared';\nimport { readSubmittedOnBehalfLabel } from './submitted-by';\nimport {\n readFormDataSourceSubmissionBlockMessage,\n type FormDataSourceFieldState,\n} from '../../forms/renderer/form-data-source-field';\n\n// While a webhook delivery is queued or in flight the section re-reads the\n// list, so a retry is seen landing without a manual reload. Bounded: backoff\n// can push the next attempt far beyond what anyone watches the page for.\nconst WEBHOOK_DELIVERY_POLL_INTERVAL_MS = 3000;\nconst WEBHOOK_DELIVERY_POLL_LIMIT = 40;\n\nconst FLOW_NODE_LAYOUT_WIDTH = 184;\nconst FLOW_NODE_LAYOUT_HEIGHT = 96;\n\nconst FLOW_MODAL_BODY_STYLE: CSSProperties = {\n display: 'grid',\n gap: 16,\n};\n\nconst FLOW_CANVAS_STYLE: CSSProperties = {\n background: '#f8fafc',\n border: '1px solid #e2e8f0',\n borderRadius: 8,\n height: 'min(64vh, 620px)',\n minHeight: 440,\n overflow: 'hidden',\n width: 'min(80vw, 1040px)',\n};\n\nconst NODE_STYLE: CSSProperties = {\n background: '#ffffff',\n border: '1px solid #cbd5e1',\n borderRadius: 8,\n boxShadow: '0 8px 18px rgba(15, 23, 42, 0.08)',\n display: 'grid',\n gap: 6,\n minHeight: 82,\n padding: 12,\n width: 184,\n};\n\nconst NODE_STATUS_STYLE: CSSProperties = {\n borderRadius: 999,\n fontSize: 12,\n fontWeight: 600,\n justifySelf: 'start',\n lineHeight: '18px',\n padding: '0 8px',\n};\n\nconst NODE_SECONDARY_STYLE: CSSProperties = {\n color: '#64748b',\n fontSize: 12,\n overflow: 'hidden',\n textOverflow: 'ellipsis',\n whiteSpace: 'nowrap',\n};\n\nconst NODE_HANDLE_STYLE: CSSProperties = {\n opacity: 0,\n};\n\nconst EDGE_SUMMARY_STYLE: CSSProperties = {\n display: 'flex',\n flexWrap: 'wrap',\n gap: 8,\n};\n\nconst EDGE_SUMMARY_ITEM_STYLE: CSSProperties = {\n alignItems: 'center',\n background: '#ffffff',\n border: '1px solid #cbd5e1',\n borderRadius: 8,\n color: '#334155',\n display: 'inline-flex',\n fontSize: 12,\n fontWeight: 600,\n gap: 6,\n lineHeight: '20px',\n padding: '4px 8px',\n};\n\nconst SECTION_BODY_STYLE: CSSProperties = {\n display: 'grid',\n gap: 16,\n};\n\nconst READONLY_FLOW_NODE_TYPES = {\n workflowRuntime: WorkflowRuntimeNodeCard,\n};\n\ntype RuntimeTone =\n | 'cancelled'\n | 'completed'\n | 'current'\n | 'neutral'\n | 'waiting';\n\ninterface RuntimeNodeData extends Record<string, unknown> {\n readonly kindLabel: string;\n readonly label: string;\n readonly secondaryLabel: string;\n readonly statusLabel: string;\n readonly tone: RuntimeTone;\n}\n\ntype RuntimeFlowNode = FlowNode<RuntimeNodeData, 'workflowRuntime'>;\ntype RuntimeFlowEdge = FlowEdge<\n Readonly<Record<string, unknown>>,\n 'smoothstep'\n>;\n\nexport interface InstanceDetailViewProps {\n /** Approval instance id (Next.js `params.id` resolved by the page shim). */\n readonly instanceId: string;\n /** Show the form snapshot section (default: true). */\n readonly showForm?: boolean;\n /** Show the attachments section (default: true). */\n readonly showAttachments?: boolean;\n /** Show the tasks section (default: true). */\n readonly showTasks?: boolean;\n /** Show the signatures section (default: true). */\n readonly showSignatures?: boolean;\n /** Show the history section (default: true). */\n readonly showHistory?: boolean;\n /**\n * Show the notify-node webhook deliveries section (default: true). Only\n * administrators ever see it, and only when the instance queued any.\n */\n readonly showWebhookDeliveries?: boolean;\n}\n\n/**\n * Framework-agnostic view for the BPM approval instance detail page.\n * Mechanical port of `apps/client/src/app/instances/[id]/page.tsx`. The\n * `instanceId` is provided by the host page wrapper (typically resolved\n * from `params.id` in the Next.js Server Component shim).\n */\nexport function InstanceDetailView({\n instanceId,\n showAttachments = true,\n showForm = true,\n showHistory = true,\n showSignatures = true,\n showTasks = true,\n showWebhookDeliveries = true,\n}: InstanceDetailViewProps): ReactElement {\n const { member } = useAuth();\n const currentMemberId = member?.memberId ?? null;\n const canViewWebhookDeliveries =\n showWebhookDeliveries && isBPMAdminMember(member);\n const [activityLogs, setActivityLogs] = useState<\n readonly ActivityLogRecord[]\n >([]);\n const [instance, setInstance] = useState<ApprovalInstanceRecord | null>(null);\n const [taskDecisions, setTaskDecisions] = useState<\n readonly TaskDecisionRecord[]\n >([]);\n const [attachments, setAttachments] = useState<readonly AttachmentRecord[]>(\n [],\n );\n const [signatures, setSignatures] = useState<readonly SignatureRecord[]>([]);\n const [webhookDeliveries, setWebhookDeliveries] = useState<\n readonly WorkflowWebhookDeliveryRecord[]\n >([]);\n const [signatureVerification, setSignatureVerification] =\n useState<SignatureVerificationRecord | null>(null);\n const [tasks, setTasks] = useState<readonly TaskRecord[]>([]);\n const [workflowTokens, setWorkflowTokens] = useState<\n readonly WorkflowTokenRecord[]\n >([]);\n const [memberProfiles, setMemberProfiles] = useState<\n readonly MemberProfileRecord[]\n >([]);\n const [error, setError] = useState<string | null>(null);\n const [loading, setLoading] = useState(true);\n const [deciding, setDeciding] = useState(false);\n const [workflowModalOpen, setWorkflowModalOpen] = useState(false);\n const [cancelComment, setCancelComment] = useState('');\n const [cancelModalOpen, setCancelModalOpen] = useState(false);\n const [resubmitFormErrors, setResubmitFormErrors] = useState<\n Readonly<Record<string, string>>\n >({});\n const [resubmitFormData, setResubmitFormData] = useState<WorkflowFormData>(\n {},\n );\n const [resubmitDataSourceStates, setResubmitDataSourceStates] = useState<\n Readonly<\n Record<string, Pick<FormDataSourceFieldState, 'hasValue' | 'status'>>\n >\n >({});\n const [previewAttachment, setPreviewAttachment] =\n useState<AttachmentRecord | null>(null);\n const [previewUrl, setPreviewUrl] = useState<string | null>(null);\n const [adhocDirectives, setAdhocDirectives] = useState<\n readonly AdhocDirectiveRecord[]\n >([]);\n\n const trimmedCancelComment = cancelComment.trim();\n\n // Ref to the TasksSection imperative handle, used by PageHeader buttons.\n const tasksSectionRef = useRef<InstanceTasksSectionHandle>(null);\n const webhookDeliveryPollCountRef = useRef(0);\n const hasInFlightWebhookDelivery = webhookDeliveries.some(\n (delivery) =>\n delivery.status === 'PENDING' ||\n delivery.status === 'DELIVERY_IN_PROGRESS',\n );\n\n useEffect((): void => {\n void refreshInstance();\n }, [currentMemberId, instanceId]);\n\n useEffect((): (() => void) | undefined => {\n if (\n !canViewWebhookDeliveries ||\n !hasInFlightWebhookDelivery ||\n webhookDeliveryPollCountRef.current >= WEBHOOK_DELIVERY_POLL_LIMIT\n ) {\n return undefined;\n }\n\n const timer = setTimeout((): void => {\n webhookDeliveryPollCountRef.current += 1;\n void pollWebhookDeliveries();\n }, WEBHOOK_DELIVERY_POLL_INTERVAL_MS);\n\n return (): void => clearTimeout(timer);\n }, [canViewWebhookDeliveries, hasInFlightWebhookDelivery, webhookDeliveries]);\n\n useEffect((): void => {\n setResubmitFormData(instance?.formData ?? {});\n setResubmitDataSourceStates({});\n }, [instance]);\n\n const handleResubmitDataSourceStateChange = useCallback(\n (\n fieldKey: string,\n state: Pick<\n FormDataSourceFieldState,\n 'hasValue' | 'invalidValues' | 'status'\n >,\n ): void => {\n setResubmitDataSourceStates((currentStates) => {\n const currentState = currentStates[fieldKey];\n\n if (\n currentState?.hasValue === state.hasValue &&\n currentState.status === state.status\n ) {\n return currentStates;\n }\n\n return {\n ...currentStates,\n [fieldKey]: {\n hasValue: state.hasValue,\n status: state.status,\n },\n };\n });\n },\n [],\n );\n\n // Derived from tasks (needed for PageHeader actions — read from ref for\n // deciding/hasCurrentTask, but we need these synchronously for rendering).\n const currentTask = useMemo(\n (): TaskRecord | null =>\n tasks.find(\n (task) =>\n canMemberActOnTask(task, currentMemberId) &&\n (task.status === 'PENDING' || task.status === 'IN_PROGRESS'),\n ) ?? null,\n [currentMemberId, tasks],\n );\n const currentTaskNode = useMemo(\n (): WorkflowNode | null =>\n currentTask && instance\n ? (instance.workflowSnapshot.nodes.find(\n (node) => node.id === currentTask.nodeId,\n ) ?? null)\n : null,\n [currentTask, instance],\n );\n const canReturnCurrentTask =\n currentTaskNode?.type === 'userTask' &&\n currentTaskNode.data.returnBehavior.allowReturn;\n const canRejectCurrentTask =\n currentTaskNode?.type === 'userTask' &&\n currentTaskNode.data.allowReject !== false;\n const canTransferCurrentTask =\n currentTaskNode?.type === 'userTask' &&\n currentTaskNode.data.allowTransfer !== false;\n const canAddSignerCurrentTask =\n currentTaskNode?.type === 'userTask' &&\n currentTaskNode.data.allowAddSigner;\n const canCancelInstance = Boolean(\n instance &&\n instance.initiatorMemberId === currentMemberId &&\n (instance.state === 'RUNNING' || instance.state === 'RETURNED'),\n );\n const canResubmitInstance = Boolean(\n instance &&\n instance.initiatorMemberId === currentMemberId &&\n instance.state === 'RETURNED',\n );\n const memberProfilesById = useMemo(\n (): ReadonlyMap<string, MemberProfileRecord> =>\n new Map(memberProfiles.map((profile) => [profile.memberId, profile])),\n [memberProfiles],\n );\n const taskDecisionsByTaskId = useMemo(\n (): ReadonlyMap<string, TaskDecisionRecord> =>\n readLatestTaskDecisionsByTaskId(taskDecisions),\n [taskDecisions],\n );\n const signaturesById = useMemo(\n (): ReadonlyMap<string, SignatureRecord> =>\n new Map(signatures.map((signature) => [signature.id, signature])),\n [signatures],\n );\n const layoutedWorkflowSnapshot = useMemo(\n (): WorkflowDefinition | null =>\n instance\n ? layoutRuntimeWorkflowDefinition(instance.workflowSnapshot)\n : null,\n [instance],\n );\n const flowNodes = useMemo(\n (): RuntimeFlowNode[] =>\n instance && layoutedWorkflowSnapshot\n ? readRuntimeFlowNodes(\n layoutedWorkflowSnapshot,\n tasks,\n workflowTokens,\n instance.state,\n )\n : [],\n [instance, layoutedWorkflowSnapshot, tasks, workflowTokens],\n );\n const flowEdges = useMemo(\n (): RuntimeFlowEdge[] =>\n layoutedWorkflowSnapshot\n ? readRuntimeFlowEdges(layoutedWorkflowSnapshot)\n : [],\n [layoutedWorkflowSnapshot],\n );\n const edgeSummaries = useMemo(\n (): readonly string[] =>\n instance ? readEdgeSummaries(instance.workflowSnapshot) : [],\n [instance],\n );\n\n async function refreshInstance(): Promise<void> {\n setLoading(true);\n setError(null);\n\n try {\n const nextRecord = await readApprovalInstance(instanceId);\n setActivityLogs(nextRecord.activityLogs);\n setInstance(nextRecord.instance);\n setTasks(nextRecord.tasks);\n setWorkflowTokens(nextRecord.workflowTokens);\n const nextAdhocDirectives = await listAdhocDirectives(\n nextRecord.instance.id,\n );\n const [\n nextTaskDecisions,\n nextMemberProfiles,\n nextAttachments,\n nextSignatures,\n nextWebhookDeliveries,\n ] = await Promise.all([\n readTaskDecisionsForTasks(nextRecord.tasks),\n readMemberProfilesForTimeline({\n ...nextRecord,\n adhocDirectives: nextAdhocDirectives,\n }),\n listAttachments(nextRecord.instance.id),\n readInstanceSignatures(nextRecord.instance.id),\n readWebhookDeliveries(nextRecord.instance.id),\n ]);\n setTaskDecisions(nextTaskDecisions);\n setMemberProfiles(nextMemberProfiles);\n setAttachments(nextAttachments);\n setSignatures(nextSignatures.signatures);\n setSignatureVerification(nextSignatures.verification);\n setAdhocDirectives(nextAdhocDirectives);\n setWebhookDeliveries(nextWebhookDeliveries);\n } catch (requestError: unknown) {\n setError(readErrorMessage(requestError));\n } finally {\n setLoading(false);\n }\n }\n\n async function readWebhookDeliveries(\n targetInstanceId: string,\n ): Promise<readonly WorkflowWebhookDeliveryRecord[]> {\n if (!canViewWebhookDeliveries) {\n return [];\n }\n\n // An administrator-only extra: a host without the webhook module, or a\n // role the server judges differently, must not take the page down.\n return listWorkflowWebhookDeliveries(targetInstanceId).catch(\n (): readonly WorkflowWebhookDeliveryRecord[] => [],\n );\n }\n\n async function handleRetryWebhookDelivery(\n delivery: WorkflowWebhookDeliveryRecord,\n ): Promise<void> {\n await retryWorkflowWebhookDelivery(delivery.id);\n webhookDeliveryPollCountRef.current = 0;\n await refreshInstance();\n }\n\n /**\n * Re-reads only the deliveries while any is in flight; once none is, the\n * whole instance is refreshed so the timeline picks up the outcome.\n */\n async function pollWebhookDeliveries(): Promise<void> {\n const next = await readWebhookDeliveries(instanceId);\n const settled = !next.some(\n (delivery) =>\n delivery.status === 'PENDING' ||\n delivery.status === 'DELIVERY_IN_PROGRESS',\n );\n\n if (settled) {\n await refreshInstance();\n return;\n }\n\n setWebhookDeliveries(next);\n }\n\n async function handleUploadAttachment(\n field: FormFieldDefinition,\n file: File,\n ): Promise<{ readonly id: string }> {\n if (!currentMemberId) {\n throw new Error('尚未登入,無法上傳附件');\n }\n\n const attachment = await uploadAttachment({\n file,\n formFieldPath: `form.${field.fieldKey}`,\n });\n\n return { id: attachment.id };\n }\n\n async function handleDownloadAttachment(\n attachment: AttachmentRecord,\n ): Promise<void> {\n if (!currentMemberId) {\n return;\n }\n\n const url = await readAttachmentDownloadUrl({\n id: attachment.id,\n });\n\n window.open(url, '_blank', 'noopener,noreferrer');\n }\n\n async function handlePreviewAttachment(\n attachment: AttachmentRecord,\n ): Promise<void> {\n if (!currentMemberId) {\n return;\n }\n\n const url = await readAttachmentPreviewUrl({\n id: attachment.id,\n });\n\n setPreviewAttachment(attachment);\n setPreviewUrl(url);\n }\n\n async function handleCancelInstance(): Promise<void> {\n if (!currentMemberId || !instance || !canCancelInstance) {\n return;\n }\n\n setDeciding(true);\n setError(null);\n setResubmitFormErrors({});\n\n // Cancelling throws the case away, so an incomplete resubmit form is not a\n // reason to refuse it. The required-field check belongs to resubmit only.\n\n try {\n await cancelApprovalInstance({\n cancelledByMemberId: currentMemberId,\n comment: trimmedCancelComment || null,\n instanceId: instance.id,\n });\n setCancelComment('');\n setCancelModalOpen(false);\n await refreshInstance();\n } catch (requestError: unknown) {\n setError(readErrorMessage(requestError));\n } finally {\n setDeciding(false);\n }\n }\n\n async function handleResubmitInstance(): Promise<void> {\n if (!currentMemberId || !instance || !canResubmitInstance) {\n return;\n }\n\n setDeciding(true);\n setError(null);\n setResubmitFormErrors({});\n\n const dataSourceBlockMessage = readFormDataSourceSubmissionBlockMessage(\n Object.values(resubmitDataSourceStates),\n );\n\n if (dataSourceBlockMessage) {\n setError(dataSourceBlockMessage);\n setDeciding(false);\n\n return;\n }\n\n // What the renderer shows, not just what has been touched: a table seeds\n // its `minRows` rows and a field can carry a `defaultValue`, and neither is\n // in this state until the filler edits something.\n const resubmittedValues = instance.formDefinitionSnapshot.schema\n ? buildFormRendererValues(\n instance.formDefinitionSnapshot.schema.fields,\n resubmitFormData,\n )\n : resubmitFormData;\n\n // The DataSource gate only speaks for fields that still hold a value, so a\n // cleared required field has to be caught here rather than by the backend.\n if (\n instance.formDefinitionSnapshot.schema &&\n instance.formDefinitionSnapshot.uiSchema\n ) {\n const validation = validateFormRendererValues({\n schema: instance.formDefinitionSnapshot.schema,\n uiSchema: instance.formDefinitionSnapshot.uiSchema,\n values: resubmittedValues,\n });\n\n if (!validation.valid) {\n setResubmitFormErrors(validation.errors);\n setError('請先補齊必填欄位。');\n\n if (validation.firstInvalidFieldKey) {\n focusFormRendererField(validation.firstInvalidFieldKey);\n }\n\n setDeciding(false);\n\n return;\n }\n }\n\n try {\n await resubmitApprovalInstance({\n formData: resubmittedValues,\n initiatorMemberId: currentMemberId,\n instanceId: instance.id,\n title: instance.title,\n });\n await refreshInstance();\n } catch (requestError: unknown) {\n setError(readErrorMessage(requestError));\n } finally {\n setDeciding(false);\n }\n }\n\n // Derive deciding/canReturn for the PageHeader from the ref handle\n // (falls back to local state for cancel/other actions).\n const taskSectionDeciding = tasksSectionRef.current?.deciding ?? false;\n const combinedDeciding = deciding || taskSectionDeciding;\n\n return (\n <>\n <PageHeader>\n <ContentHeader\n description={\n instance\n ? [\n readInstanceStateLabel(instance.state),\n formatDateTime(instance.startedAt),\n readSubmittedOnBehalfLabel(instance, memberProfilesById),\n ]\n .filter(isPresentText)\n .join(' · ')\n : '載入案件內容。'\n }\n title={instance?.title ?? '簽核案件'}\n >\n {instance ? (\n <Button\n aria-label=\"查看流程圖\"\n icon={ShareIcon}\n iconType=\"icon-only\"\n onClick={(): void => setWorkflowModalOpen(true)}\n title=\"查看流程圖\"\n variant=\"base-secondary\"\n >\n 流程圖\n </Button>\n ) : null}\n {canCancelInstance ? (\n <Button\n disabled={combinedDeciding}\n icon={DangerousOutlineIcon}\n iconType=\"leading\"\n onClick={(): void => setCancelModalOpen(true)}\n variant=\"destructive-secondary\"\n >\n 取消案件\n </Button>\n ) : null}\n {currentTask ? (\n <>\n {/* Stable keys keep these action buttons mounted while the\n conditional ad-hoc buttons appear, so in-flight clicks are\n not lost to re-created DOM nodes. */}\n {canAddSignerCurrentTask ? (\n <>\n <Button\n disabled={combinedDeciding}\n icon={PlusIcon}\n iconType=\"leading\"\n key=\"adhoc-countersign\"\n onClick={(): void =>\n tasksSectionRef.current?.openAdhocModal('COUNTERSIGN')\n }\n variant=\"base-secondary\"\n >\n 會簽\n </Button>\n <Button\n disabled={combinedDeciding}\n icon={PlusIcon}\n iconType=\"leading\"\n key=\"adhoc-pre-approval\"\n onClick={(): void =>\n tasksSectionRef.current?.openAdhocModal('PRE_APPROVAL')\n }\n variant=\"base-secondary\"\n >\n 加簽\n </Button>\n </>\n ) : null}\n <Button\n disabled={combinedDeciding}\n icon={NotificationUnreadIcon}\n iconType=\"leading\"\n key=\"adhoc-notify\"\n onClick={(): void =>\n tasksSectionRef.current?.openAdhocModal('STAGE_NOTIFY')\n }\n variant=\"base-secondary\"\n >\n 通知設定\n </Button>\n {canReturnCurrentTask ? (\n <Button\n disabled={combinedDeciding}\n icon={RefreshCcwIcon}\n iconType=\"leading\"\n key=\"task-return\"\n onClick={(): void => tasksSectionRef.current?.openReturnModal()}\n variant=\"base-secondary\"\n >\n 退回\n </Button>\n ) : null}\n {canTransferCurrentTask ? (\n <Button\n disabled={combinedDeciding}\n icon={UserIcon}\n iconType=\"leading\"\n key=\"task-transfer\"\n onClick={(): void =>\n tasksSectionRef.current?.openTransferModal()\n }\n variant=\"base-secondary\"\n >\n 轉派\n </Button>\n ) : null}\n {canRejectCurrentTask ? (\n <Button\n disabled={combinedDeciding}\n icon={DangerousOutlineIcon}\n iconType=\"leading\"\n key=\"task-reject\"\n onClick={(): void => tasksSectionRef.current?.openRejectModal()}\n variant=\"destructive-secondary\"\n >\n 拒絕\n </Button>\n ) : null}\n <Button\n disabled={combinedDeciding}\n icon={CheckedIcon}\n iconType=\"leading\"\n key=\"task-approve\"\n onClick={(): void => tasksSectionRef.current?.handleApprove()}\n variant=\"base-primary\"\n >\n 同意\n </Button>\n </>\n ) : null}\n </ContentHeader>\n </PageHeader>\n\n <SectionGroup>\n {showForm ? (\n <Section>\n <InstanceFormSection\n canResubmitInstance={canResubmitInstance}\n deciding={deciding}\n error={error}\n instance={instance}\n loading={loading}\n onDataSourceStateChange={handleResubmitDataSourceStateChange}\n onResubmitFormChange={(values): void => {\n setResubmitFormData(values);\n setResubmitFormErrors({});\n }}\n onResubmitInstance={(): void => void handleResubmitInstance()}\n onUploadAttachment={handleUploadAttachment}\n resubmitFormData={resubmitFormData}\n resubmitFormErrors={resubmitFormErrors}\n />\n </Section>\n ) : null}\n\n {showAttachments ? (\n <Section>\n <InstanceAttachmentsSection\n attachments={attachments}\n onDownload={(attachment): void => {\n void handleDownloadAttachment(attachment);\n }}\n onPreview={(attachment): void => {\n void handlePreviewAttachment(attachment);\n }}\n />\n </Section>\n ) : null}\n\n {showTasks ? (\n <Section>\n <InstanceTasksSection\n adhocDirectives={adhocDirectives}\n currentMemberId={currentMemberId}\n instance={instance}\n memberProfilesById={memberProfilesById}\n onChanged={refreshInstance}\n ref={tasksSectionRef}\n tasks={tasks}\n />\n </Section>\n ) : null}\n\n {showSignatures ? (\n <Section>\n <InstanceSignaturesSection\n signatureVerification={signatureVerification}\n signatures={signatures}\n />\n </Section>\n ) : null}\n\n {canViewWebhookDeliveries && webhookDeliveries.length > 0 ? (\n <Section>\n <InstanceWebhookDeliveriesSection\n deliveries={webhookDeliveries}\n onRetry={handleRetryWebhookDelivery}\n readNodeLabel={(nodeId): string =>\n readNodeDisplayLabel(nodeId, instance?.workflowSnapshot ?? null)\n }\n />\n </Section>\n ) : null}\n\n {showHistory ? (\n <Section>\n <InstanceHistorySection\n activityLogs={activityLogs}\n instanceState={instance?.state ?? 'RUNNING'}\n memberProfilesById={memberProfilesById}\n signatureVerification={signatureVerification}\n signaturesById={signaturesById}\n taskDecisionsByTaskId={taskDecisionsByTaskId}\n tasks={tasks}\n workflowSnapshot={instance?.workflowSnapshot ?? null}\n workflowTokens={workflowTokens}\n />\n </Section>\n ) : null}\n </SectionGroup>\n\n {/* Workflow flow modal */}\n {instance ? (\n <Modal\n modalType=\"standard\"\n onClose={(): void => setWorkflowModalOpen(false)}\n open={workflowModalOpen}\n showModalHeader\n size=\"wide\"\n supportingText={`${readInstanceStateLabel(\n instance.state,\n )} · ${formatDateTime(instance.startedAt)}`}\n title=\"流程圖\"\n >\n <div style={FLOW_MODAL_BODY_STYLE}>\n <div style={FLOW_CANVAS_STYLE}>\n <ReactFlow\n edges={flowEdges}\n fitView\n fitViewOptions={{ padding: 0.18 }}\n maxZoom={1.2}\n minZoom={0.2}\n nodes={flowNodes}\n nodesDraggable={false}\n nodesFocusable={false}\n nodeTypes={READONLY_FLOW_NODE_TYPES}\n panOnDrag\n proOptions={{ hideAttribution: true }}\n >\n <Background />\n <Controls showInteractive={false} />\n </ReactFlow>\n </div>\n {edgeSummaries.length > 0 ? (\n <div style={EDGE_SUMMARY_STYLE}>\n {edgeSummaries.map((summary) => (\n <span key={summary} style={EDGE_SUMMARY_ITEM_STYLE}>\n {summary}\n </span>\n ))}\n </div>\n ) : null}\n </div>\n </Modal>\n ) : null}\n\n {/* PDF preview modal */}\n <Modal\n modalType=\"standard\"\n onClose={(): void => {\n setPreviewAttachment(null);\n setPreviewUrl(null);\n }}\n open={Boolean(previewAttachment && previewUrl)}\n showModalHeader\n size=\"wide\"\n supportingText={previewAttachment?.filename ?? undefined}\n title=\"PDF 預覽\"\n >\n {previewUrl ? (\n <PDFPreview\n filename={previewAttachment?.filename ?? 'PDF 預覽'}\n fileUrl={previewUrl}\n onDownload={\n previewAttachment\n ? (): void => void handleDownloadAttachment(previewAttachment)\n : undefined\n }\n />\n ) : null}\n </Modal>\n\n {/* Cancel instance modal */}\n <Modal\n cancelText=\"保留案件\"\n confirmButtonProps={{ variant: 'destructive-primary' }}\n confirmText=\"確認取消\"\n loading={deciding}\n modalStatusType=\"error\"\n modalType=\"standard\"\n onCancel={(): void => setCancelModalOpen(false)}\n onClose={(): void => setCancelModalOpen(false)}\n onConfirm={(): void => void handleCancelInstance()}\n open={cancelModalOpen}\n showModalFooter\n showModalHeader\n supportingText=\"取消後會關閉目前待簽任務與候選簽核人。\"\n title=\"取消案件\"\n >\n <div style={SECTION_BODY_STYLE}>\n <Typography variant=\"body\">\n 確定要取消「{instance?.title ?? ''}」嗎?\n </Typography>\n <BPMFormField label=\"取消原因\" name=\"cancelComment\">\n <Textarea\n onChange={(event): void =>\n setCancelComment(event.target.value)\n }\n placeholder=\"可填寫取消原因\"\n resize=\"vertical\"\n rows={3}\n value={cancelComment}\n />\n </BPMFormField>\n </div>\n </Modal>\n </>\n );\n}\n\n// ---------------------------------------------------------------------------\n// Container-local helper functions (flow canvas, labels)\n// ---------------------------------------------------------------------------\n\nfunction readEdgeLabel(edge: WorkflowDefinition['edges'][number]): string {\n if (edge.data.label) {\n return edge.data.label;\n }\n\n if (edge.data.isDefault) {\n return '其他情況';\n }\n\n return edge.data.condition ?? '';\n}\n\nfunction readEdgeSummaries(workflow: WorkflowDefinition): readonly string[] {\n return workflow.edges\n .map(readEdgeLabel)\n .filter((label) => label.trim().length > 0);\n}\n\nfunction readNodeKindLabel(type: WorkflowNode['type']): string {\n if (type === 'startEvent') return '開始';\n if (type === 'endEvent') return '完成';\n if (type === 'userTask') return '簽核節點';\n if (type === 'serviceTask') return '知會節點';\n if (type === 'exclusiveGateway') return '條件分流';\n\n return '平行處理';\n}\n\nfunction readRuntimeFlowNodes(\n workflow: WorkflowDefinition,\n tasks: readonly TaskRecord[],\n tokens: readonly WorkflowTokenRecord[],\n instanceState: string,\n): RuntimeFlowNode[] {\n return workflow.nodes.map((node): RuntimeFlowNode => {\n const state = readNodeRuntimeState(node, tasks, tokens, instanceState);\n\n return {\n data: {\n kindLabel: readNodeKindLabel(node.type),\n label: node.data.label,\n secondaryLabel: state.secondaryLabel,\n statusLabel: state.statusLabel,\n tone: state.tone,\n },\n id: node.id,\n position: node.position,\n sourcePosition: Position.Right,\n targetPosition: Position.Left,\n type: 'workflowRuntime',\n };\n });\n}\n\nfunction layoutRuntimeWorkflowDefinition(\n workflow: WorkflowDefinition,\n): WorkflowDefinition {\n const graph = new dagre.graphlib.Graph();\n graph.setDefaultEdgeLabel(() => ({}));\n graph.setGraph({\n nodesep: 56,\n rankdir: 'LR',\n ranksep: 120,\n });\n workflow.nodes.forEach((node): void => {\n graph.setNode(node.id, {\n height: FLOW_NODE_LAYOUT_HEIGHT,\n width: FLOW_NODE_LAYOUT_WIDTH,\n });\n });\n workflow.edges.forEach((edge): void => {\n graph.setEdge(edge.source, edge.target);\n });\n dagre.layout(graph);\n\n return {\n ...workflow,\n nodes: workflow.nodes.map((node): WorkflowNode => {\n const positionedNode = graph.node(node.id) as\n | { readonly x: number; readonly y: number }\n | undefined;\n\n return positionedNode\n ? {\n ...node,\n position: {\n x: positionedNode.x - FLOW_NODE_LAYOUT_WIDTH / 2,\n y: positionedNode.y - FLOW_NODE_LAYOUT_HEIGHT / 2,\n },\n }\n : node;\n }),\n };\n}\n\nfunction readRuntimeFlowEdges(workflow: WorkflowDefinition): RuntimeFlowEdge[] {\n return workflow.edges.map((edge): RuntimeFlowEdge => {\n const label = readEdgeLabel(edge);\n\n return {\n animated: false,\n id: edge.id,\n label,\n labelBgBorderRadius: 6,\n labelBgPadding: [8, 4],\n labelBgStyle: {\n fill: edge.data.isDefault ? '#f8fafc' : '#eff6ff',\n stroke: edge.data.isDefault ? '#64748b' : '#2563eb',\n strokeWidth: 1,\n },\n labelShowBg: Boolean(label),\n labelStyle: {\n fill: edge.data.isDefault ? '#475569' : '#2563eb',\n fontSize: 12,\n fontWeight: 600,\n },\n source: edge.source,\n style: {\n stroke: '#475569',\n strokeWidth: 1.5,\n },\n target: edge.target,\n type: edge.type ?? 'smoothstep',\n };\n });\n}\n\nfunction readNodeStyle(tone: RuntimeTone): CSSProperties {\n if (tone === 'current') {\n return {\n ...NODE_STYLE,\n border: '1px solid var(--mzn-color-primary, #0057ff)',\n boxShadow: '0 0 0 3px rgba(0, 87, 255, 0.14)',\n };\n }\n\n if (tone === 'completed') {\n return {\n ...NODE_STYLE,\n border: '1px solid #16a34a',\n };\n }\n\n if (tone === 'cancelled') {\n return {\n ...NODE_STYLE,\n border: '1px solid #dc2626',\n opacity: 0.72,\n };\n }\n\n if (tone === 'waiting') {\n return {\n ...NODE_STYLE,\n border: '1px dashed #64748b',\n };\n }\n\n return NODE_STYLE;\n}\n\nfunction readNodeStatusStyle(tone: RuntimeTone): CSSProperties {\n const baseStyle = NODE_STATUS_STYLE;\n\n if (tone === 'current') {\n return { ...baseStyle, background: '#eff6ff', color: '#2563eb' };\n }\n\n if (tone === 'completed') {\n return { ...baseStyle, background: '#f0fdf4', color: '#15803d' };\n }\n\n if (tone === 'cancelled') {\n return { ...baseStyle, background: '#fef2f2', color: '#dc2626' };\n }\n\n if (tone === 'waiting') {\n return { ...baseStyle, background: '#f8fafc', color: '#475569' };\n }\n\n return { ...baseStyle, background: '#f1f5f9', color: '#64748b' };\n}\n\nfunction WorkflowRuntimeNodeCard({\n data,\n}: NodeProps<RuntimeFlowNode>): ReactElement {\n return (\n <div style={readNodeStyle(data.tone)}>\n <Handle\n isConnectable={false}\n position={Position.Left}\n style={NODE_HANDLE_STYLE}\n type=\"target\"\n />\n <Typography\n component=\"span\"\n ellipsis\n title={data.label}\n variant=\"label-primary\"\n >\n {data.label}\n </Typography>\n <span style={readNodeStatusStyle(data.tone)}>{data.statusLabel}</span>\n <span title={data.secondaryLabel} style={NODE_SECONDARY_STYLE}>\n {data.secondaryLabel || data.kindLabel}\n </span>\n <Handle\n isConnectable={false}\n position={Position.Right}\n style={NODE_HANDLE_STYLE}\n type=\"source\"\n />\n </div>\n );\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;GC+BMsB,KAAyB,KACzBC,KAAiB,KACjBC,IAAiB,KACjBC,IAA0B,IAC1BC,IAAY,KACZC,KAAY,MACZC,IAAa;AAYnB,SAAgBC,GAAW,EACzB,aACA,YACA,iBACgC;CAChC,IAAMC,IAAcC,EAA8B,IAAI,GAChD,CAACC,GAAUC,KAAeC,EAAwB,IAAI,GACtD,CAACC,GAAYC,KAAiBF,EAAS,CAAC,GACxC,CAACG,GAAOC,KAAYJ,EAAS,CAAC,GAC9B,CAACK,GAAeC,MAAoBN,EAASZ,EAAsB;CAsBzE,AApBAmB,QAA0C;EACxC,IAAMC,IAAWZ,EAAY;EAE7B,IAAI,CAACY,KAAY,OAAO,iBAAmB,KACzC;EAGF,IAAMC,IAAW,IAAI,gBAAgB,MAAkB;GACrD,IAAMC,IAAYC,EAAQ,EAAE,EAAE,YAAY;GAE1C,AAAID,KACFJ,GAAiBI,CAAS;EAE9B,CAAC;EAID,OAFAD,EAAS,QAAQD,CAAQ,SAENC,EAAS,WAAW;CACzC,GAAG,CAAC,CAAC,GAELF,QAAsB;EAGpB,AAFAR,EAAY,IAAI,GAChBG,EAAc,CAAC,GACfE,EAAS,CAAC;CACZ,GAAG,CAACQ,CAAO,CAAC;CAEZ,IAAMC,IAAYC,QAAsB;EACtC,IAAMC,IAAiB,KAAK,IAC1BzB,GACAe,IAAgBd,CAClB;EAGA,OAAO,KAAK,MAFM,KAAK,IAAIF,IAAgB0B,CAEzB,IAAYZ,CAAK;CACrC,GAAG,CAACA,GAAOE,CAAa,CAAC,GAEnBW,IAAeC,GAAa,MAAqC;EAErE,AADAlB,EAAYmB,EAAS,QAAQ,GAC7BhB,EAAc,CAAC;CACjB,GAAG,CAAC,CAAC,GAECiB,IAAkBlB,IAAa,GAC/BmB,KAActB,MAAa,QAAQG,IAAaH,GAChDuB,IAAalB,IAAQX,GACrB8B,KAAYnB,IAAQV,IACpB8B,IACJzB,MAAa,OACT,KAAKG,EAAW,MAChB,KAAKA,EAAW,KAAKH,EAAS,KAC9B0B,KAAY,GAAG,KAAK,MAAMrB,IAAQ,GAAG,EAAE;CAE7C,OACE,kBAAC,WAAD;EAAS,cAAY,GAAGsB,EAAS;EAAU,WAAW3D,EAAO;EAA7D,UAAA,CACE,kBAAC,OAAD;GAAK,WAAWA,EAAO;GAAvB,UAAA;IACE,kBAAC,OAAD;KAAK,WAAWA,EAAO;KAAc,cAAW;KAAhD,UAAA;MACE,kBAAC4D,GAAD;OACE,cAAW;OACX,UAAU,CAACP;OACX,MAAMQ;OACN,eAAqB;QACnB,GAAe,MACb,KAAK,IAAI,GAAGC,IAAoB,CAAC,CACnC;OACF;OACA,MAAK;OACL,SAAQ;MACT,CAAA;MACD,kBAACC,GAAD;OACE,WAAW/D,EAAO;OAClB,WAAU;OACV,SAAQ;OAEP,UAAAyD;MACS,CAAA;MACZ,kBAACG,GAAD;OACE,cAAW;OACX,UAAU,CAACN;OACX,MAAMU;OACN,eAAqB;QACnB,GAAe,MACbhC,MAAa,OACT8B,IACA,KAAK,IAAI9B,GAAU8B,IAAoB,CAAC,CAC9C;OACF;OACA,MAAK;OACL,SAAQ;MACT,CAAA;KACE;;IACL,kBAAC,OAAD;KAAK,WAAW9D,EAAO;KAAc,cAAW;KAAhD,UAAA;MACE,kBAAC4D,GAAD;OACE,cAAW;OACX,UAAU,CAACL;OACX,MAAMU;OACN,eAAqB;QACnB,GAAU,MACR,KAAK,IAAIvC,GAAWwC,IAAetC,CAAU,CAC/C;OACF;OACA,MAAK;OACL,SAAQ;MACT,CAAA;MACD,kBAACmC,GAAD;OACE,WAAW/D,EAAO;OAClB,WAAU;OACV,SAAQ;OAEP,UAAA0D;MACS,CAAA;MACZ,kBAACE,GAAD;OACE,cAAW;OACX,UAAU,CAACJ;OACX,MAAMW;OACN,eAAqB;QACnB,GAAU,MACR,KAAK,IAAIxC,IAAWuC,IAAetC,CAAU,CAC/C;OACF;OACA,MAAK;OACL,SAAQ;MACT,CAAA;KACE;;IACJwC,IACC,kBAACR,GAAD;KACE,MAAMS;KACN,UAAS;KACT,SAASD;KACT,MAAK;KACL,SAAQ;KACT,UAAA;IAEO,CAAA,IACN;GACD;EACL,CAAA,GAAA,kBAAC,OAAD;GAAK,WAAWpE,EAAO;GAAU,KAAK8B;GACpC,UAAA,kBAACwC,IAAD;IACE,OAAO,kBAACC,GAAD,EAAiB,SAAQ,YAAa,CAAA;IAC7C,MAAMzB;IACN,SAAS,kBAACyB,GAAD,EAAiB,SAAQ,cAAe,CAAA;IACjD,QAAQ,kBAACA,GAAD,EAAiB,SAAQ,cAAe,CAAA;IAChD,eAAerB;IAGf,UAAU;IAEV,UAAA,kBAACsB,IAAD;KACE,WAAWxE,EAAO;KAClB,SAAS,kBAACuE,GAAD,EAAiB,SAAQ,YAAa,CAAA;KACnC;KACZ,uBAAA;KACA,iBAAA;KACA,OAAOxB;IACR,CAAA;GACO,CAAA;EACP,CAAA,CACE;;AAEb;AAEA,SAASwB,EAAgB,EACvB,cAGe;CACf,OACE,kBAAC,OAAD;EAAK,WAAWvE,EAAO;EACrB,UAAA,kBAAC+D,GAAD;GAAY,OAAM;GAAe,SAAQ;GACtC,UAAAU;EACS,CAAA;CACT,CAAA;AAET;;;ACrNA,SAAgBC,GAA8B,EAC5C,sBACA,0BACmC;CACnC,OAAOC,KAAuBA,MAAwBC,IAClDD,IACA;AACN;AAOA,SAAgBE,GACd,GACA,GACe;CACf,IAAMC,IAAoBJ,GAA8BK,CAAM;CAE9D,IAAI,CAACD,KAAqB,CAACC,EAAO,mBAChC,OAAO;CAGT,IAAMC,KAAY,MAChBC,EAAmB,IAAIC,CAAQ,CAAC,EAAE,QAAQA;CAE5C,OAAO,KAAKF,EAASF,CAAiB,EAAE,KAAKE,EAC3CD,EAAO,iBACT,EAAE;AACJ;;;AC6DA,SAASI,GACP,GAC4B;CAC5B,IAAMC,IAAOC,EAAgBC,GAAM,MAAM,GACnCC,IAAKF,EAAgBC,GAAM,IAAI,GAC/BE,IAASH,EAAgBC,GAAM,QAAQ;CAM7C,OAJI,CAACF,KAAQ,CAACG,KAAM,CAACC,IACZ,OAGF;EACL;EACA;EACA,QAAQH,EAAgBC,GAAM,QAAQ;EACtC;CACF;AACF;AAEA,SAAgBG,GAAoB,GAA+C;CACjF,IAAI;EACF,IAAMC,IAAS,KAAK,MAAMC,CAAK;EAE/B,OAAO,MAAM,QAAQD,CAAM,IACvBA,EACG,KAAK,MACJE,GAASN,CAAI,IAAIH,GAAwBG,CAAI,IAAI,IACnD,CAAC,CACA,QAAQ,MAAsCA,MAAS,IAAI,IAC9D,CAAC;CACP,QAAQ;EACN,OAAO,CAAC;CACV;AACF;AAMA,SAAgBD,EACd,GACA,GACe;CACf,IAAMM,IAAQE,EAAOC;CAErB,OAAO,OAAOH,KAAU,WAAWA,IAAQ;AAC7C;AAEA,SAAgBI,GACd,GACA,GACmB;CACnB,IAAMJ,IAAQE,EAAOC;CAErB,OAAO,MAAM,QAAQH,CAAK,IACtBA,EAAM,QAAQ,MAAyB,OAAOL,KAAS,QAAQ,IAC/D,CAAC;AACP;AAEA,SAAgBU,GACd,GACA,GACe;CACf,IAAML,IAAQE,EAAOC;CAErB,OAAO,OAAOH,KAAU,WAAWA,IAAQ;AAC7C;AAMA,SAAgBM,EAAc,GAAuC;CACnE,OAAO,OAAON,KAAU,YAAYA,EAAM,KAAK,CAAC,CAAC,SAAS;AAC5D;AAEA,SAAgBC,GAAS,GAA4D;CACnF,OAAO,OAAOD,KAAU,cAAYA;AACtC;AAEA,SAAgBO,GAAc,GAA2B;CACvD,OAAOC,EAAK,WAAW,aAAaA,EAAK,WAAW;AACtD;AAMA,SAAgBC,EAAiB,GAAwB;CASvD,OAN0BC,GAA+BC,CAErD,MAIGA,aAAiB,QAAQA,EAAM,UAAU;AAClD;AAEA,SAAgBC,GAAe,GAA2B;CAaxD,OAZI,CAAC,OAAO,SAASC,CAAS,KAAKA,KAAa,IACvC,MAGLA,IAAY,OACP,GAAGA,EAAU,MAGlBA,IAAY,UACP,IAAIA,IAAY,KAAA,CAAM,QAAQ,CAAC,EAAE,OAGnC,IAAIA,IAAY,OAAO,KAAA,CAAM,QAAQ,CAAC,EAAE;AACjD;AAEA,SAAgBC,GAAc,GAAsB;CAClD,OAAOC,EAAK,SAAS,KAAK,GAAGA,EAAK,MAAM,GAAG,EAAE,EAAE,OAAOA;AACxD;AAEA,SAAgBC,GAAuB,GAAuB;CAS5D,OARIC,MAAU,aAAmB,QAC7BA,MAAU,cAAoB,QAC9BA,MAAU,UAAgB,OAC1BA,MAAU,YAAkB,QAC5BA,MAAU,aAAmB,QAC7BA,MAAU,aAAmB,QAC7BA,MAAU,YAAkB,QAEzBA;AACT;AAEA,SAAgBC,EAAoB,GAAsC;CAOxE,OANIC,MAAW,YAAkB,QAC7BA,MAAW,gBAAsB,QACjCA,MAAW,cAAoB,QAC/BA,MAAW,cAAoB,QAC/BA,MAAW,gBAAsB,QAE9BA;AACT;AAEA,SAAgBC,GAA4B,GAAwB;CAMlE,OALIC,MAAW,aAAmB,OAC9BA,MAAW,aAAmB,OAC9BA,MAAW,aAAmB,OAC9BA,MAAW,gBAAsB,OAE9BA;AACT;AAEA,SAAgB/G,EAAkB,GAAoC;CAOpE,OANIiH,MAAS,eAAqB,OAC9BA,MAAS,aAAmB,OAC5BA,MAAS,aAAmB,SAC5BA,MAAS,gBAAsB,SAC/BA,MAAS,qBAA2B,SAEjC;AACT;AAEA,SAAgBC,GACd,GACA,GACQ;CACR,OACEC,GAAU,MAAM,MAAM,MAASC,EAAK,OAAOC,CAAM,CAAC,EAAE,KAAK,SAASA;AAEtE;AAEA,SAAgBC,EACd,GACA,GACQ;CACR,IAAI,CAACrC,GACH,OAAO;CAGT,IAAMsC,IAAUvC,EAAmB,IAAIC,CAAQ;CAE/C,OAAOsC,IACHzG,EAAkByG,EAAQ,MAAMA,EAAQ,OAAO,WAAW,IAC1DtC;AACN;AAEA,SAAgBuC,EACd,GACA,oBAA+D,IAAI,IAAI,GAC/D;CACR,IAAMC,IAAkBjC,GAAoBU,EAAK,mBAAmB;CAEpE,IAAI,CAACA,EAAK,kBACR,OAAOA,EAAK,mBAAmB,SAC3B,MAAMA,EAAK,mBACR,KAAK,MAAaoB,EAAsBrC,GAAUD,CAAkB,CAAC,CAAC,CACtE,KAAK,GAAG,MACX;CAGN,IAAM0C,IAAgBJ,EACpBpB,EAAK,kBACLlB,CACF,GACM2C,IAAwBL,EAC5BpB,EAAK,0BACLlB,CACF;CASA,OANEyC,EAAgB,WAAW,KAC3BvB,EAAK,6BAA6BA,EAAK,mBAEhCwB,IAGF,GAAGA,EAAc,KAAKC,EAAsB;AACrD;AAEA,SAAgBC,GACd,GACA,GACS;CAUT,OATK3C,IAUHiB,EAAK,qBAAqBjB,MACzBiB,EAAK,0BAA0BA,EAAK,mBAAA,CAAoB,SAASjB,CAAQ,IAVnE;AAYX;AAEA,SAAgB4C,EACd,GACA,GAC2D;CAC3D,IAAIT,EAAK,SAAS,cAAc,CAACA,EAAK,KAAK,eAAe,aACxD,OAAO,CAAC;CAGV,IAAIA,EAAK,KAAK,eAAe,mBAAmB,OAC9C,OAAOD,EAAS,MACb,QAAQ,MAAcW,EAAU,OAAOV,EAAK,EAAE,CAAC,CAC/C,KAAK,OAAe;EACnB,IAAIU,EAAU;EACd,MAAM,GAAGA,EAAU,KAAK,MAAM,GAAG9H,EAAkB8H,EAAU,IAAI,EAAE;CACrE,EAAE;CAGN,IAAMC,IACJX,EAAK,KAAK,eAAe,mBAAmB,cACxCD,EAAS,MAAM,MAAM,MAAcW,EAAU,SAAS,YAAY,CAAC,EAAE,KACrEX,EAAS,MAAM,MAAM,MAASa,EAAK,WAAWZ,EAAK,EAAE,CAAC,EAAE,QACxDa,IAAad,EAAS,MAAM,MAC/B,MAAcW,EAAU,OAAOC,CAClC;CAEA,OAAOE,IACH,CACE;EACE,IAAIA,EAAW;EACf,MAAM,GAAGA,EAAW,KAAK,MAAM,GAAGjI,EAAkBiI,EAAW,IAAI,EAAE;CACvE,CACF,IACA,CAAC;AACP;AAEA,SAAgBC,GAAiB,GAA4C;CAC3E,OAAO;EACL,OAAOX,EAAQ;EACf,IAAIA,EAAQ;EACZ,MAAMzG,EAAkByG,EAAQ,MAAMA,EAAQ,OAAO,KAAK;CAC5D;AACF;AAiBA,SAAgBY,GAAqB,EACnC,cACA,qBACA,iBAKmB;CACnB,IAAIC,GAAkB;EACpB,IAAMC,IAAoBC,EAAW,KAAK;EAE1C,OAAOD,IACH;GACE,QAAQ;IAAE,MAAM;IAAW,YAAYA;GAAkB;GACzD,OAAO;EACT,IACA;GAAE,OAAO;GAAmB,OAAO;EAAM;CAC/C;CAEA,OAAOE,EAAU,SAAS,IACtB;EAAE,QAAQ;GAAE,MAAM;GAAU;EAAU;EAAG,OAAO;CAAK,IACrD;EAAE,OAAO;EAAW,OAAO;CAAM;AACvC;AAEA,SAAgBC,GACd,GACwB;CACxB,OAAO,EAAQC;AACjB;AAEA,SAAgBC,GAA0B,GAAqC;CAC7E,IAAI,CAAC/C,GAASD,CAAK,GACjB,OAAO;CAGT,IAAMiD,IAAQjD,EAAM,OACdkD,IAAKlD,EAAM,IACXmD,IAAOnD,EAAM;CAEnB,OAAO,OAAOkD,KAAO,YAAY,OAAOC,KAAS,WAC7C;EAAE,OAAO,OAAOF,KAAU,WAAWA,IAAQ;EAAM;EAAI;CAAK,IAC5D;AACN;AAEA,SAAgBG,GACd,GACA,GACqB;CACrB,IAAMC,IAAuBC,EAAW,KAAK,CAAC,CAAC,kBAAkB;CAEjE,IAAI,CAACD,GACH,OAAO;CAGT,IAAME,IAAUC,EAAQ,QAAQ,MAC9B;EAACT,EAAO;EAAIA,EAAO;EAAMA,EAAO,SAAS;CAAE,CAAC,CAAC,MAAM,MACjD/C,EAAM,kBAAkB,CAAC,CAAC,SAASqD,CAAoB,CACzD,CACF;CAEA,OAAOE,EAAQ,WAAW,IAAKA,EAAQ,MAAM,OAAQ;AACvD;AAMA,SAAgBE,EACd,GACoC;CACpC,OAAOnD,EAAcoD,CAAI,IAAI;EAAE;EAAM,MAAM;CAAO,IAAI;AACxD;AAEA,SAAgBC,EACd,GACA,GACA,IAA6B,WACO;CACpC,OAAOrD,EAAcoD,CAAI,IAAI;EAAE;EAAO;EAAM;EAAM,MAAM;CAAU,IAAI;AACxE;AAEA,SAAgBE,GACd,GACA,GACA,GACA,GAC6B;CAC7B,IAAM/B,IAAUtC,IAAWD,EAAmB,IAAIC,CAAQ,IAAI;CAE9D,OAAO;EACL,OAAOsC,GAAS,SAAS;EACzB,OAAOA,GAAS,QAAQgC;EACxB;EACA;EACA,MAAM;CACR;AACF;AAEA,SAAgBC,EACd,GACqC;CACrC,OAAO,EAAQC;AACjB;AAEA,SAAgBC,EACd,GACQ;CACR,IAAMC,IAAwBC,EAAc,WACzC,MACCC,EAAa,GAAG,WAAW,eAAe,KAC1CA,EAAa,GAAG,WAAW,cAAc,CAC7C;CAEA,OAAOF,MAA0B,KAC7BC,EAAc,SACdD;AACN;AAEA,SAAgBG,GAAyB,GAAyC;CAChF,OACEC,EAAY,cAAc,sBAC1BA,EAAY,cAAc,wBAC1BA,EAAY,cAAc,sBAC1BA,EAAY,cAAc,kBAC1BA,EAAY,cAAc,mBAC1BA,EAAY,cAAc,8BAC1BA,EAAY,cAAc,qBAC1BC,GAAyBD,CAAW,KACpCE,EACEF,EAAY,WACZG,GAAoBH,CAAW,CACjC;AAEJ;AAMA,SAASC,GAAyB,GAAyC;CACzE,OACED,EAAY,cAAc,kBAC1BjE,GACEoE,GAAoBH,CAAW,GAC/B,8BACF,CAAC,CAAC,SAAS;AAEf;AAMA,SAAgBI,GACd,GACmB;CACnB,IACEJ,EAAY,cAAc,8BAC1BA,EAAY,cAAc,gBAE1B,OAAO,CAAC;CAGV,IAAMK,IAAUF,GAAoBH,CAAW;CAE/C,OAAO;EACL,GAAGjE,GAAqBsE,GAAS,8BAA8B;EAC/DhF,EAAgBgF,GAAS,mBAAmB;EAC5ChF,EAAgBgF,GAAS,kBAAkB;CAC7C,CAAC,CAAC,OAAOpE,CAAa;AACxB;AAEA,IAAMqE,oBAAkD,IAAI,IAAI;CAC9D;CACA;CACA;AACF,CAAC;AAOD,SAASJ,EACP,GACA,GACS;CACT,OACEI,EAA2B,IAAIC,CAAS,KACxClF,EAAgBgF,GAAS,QAAQ,MAAM;AAE3C;AAGA,SAASG,GACP,GACQ;CACR,OACEnF,EAAgBgF,GAAS,eAAe,KACxChF,EAAgBgF,GAAS,aAAa,KACtC;AAEJ;AAEA,SAASI,GAA2B,GAA+B;CAMjE,OALIzD,MAAW,aAAmB,QAC9BA,MAAW,aAAmB,QAC9BA,MAAW,aAAmB,QAC9BA,MAAW,gBAAsB,QAE9B;AACT;AAEA,SAAgB0D,EACd,GACA,GACQ;CACR,IAAIH,MAAc,oBAAoB,OAAO;CAC7C,IAAIA,MAAc,sBAAsB,OAAO;CAC/C,IAAIA,MAAc,oBAAoB,OAAO;CAC7C,IAAIA,MAAc,iBAAiB,OAAO;CAC1C,IAAIA,MAAc,4BAA4B,OAAO;CACrD,IAAIA,MAAc,kBAAkB,OAAO;CAC3C,IAAIA,MAAc,gBAAgB,OAAO;CACzC,IAAIA,MAAc,4BAA4B,OAAO;CACrD,IAAIA,MAAc,gBAChB,OAAOE,GAA2BpF,EAAgBgF,GAAS,QAAQ,CAAC;CAEtE,IAAIE,MAAc,iBAAiB,OAAO;CAC1C,IAAIA,MAAc,mBAAmB,OAAO;CAC5C,IAAIL,EAAwBK,GAAWF,CAAO,GAAG;EAC/C,IAAMM,IAAgBH,GAA+BH,CAAO;EAM5D,OAJIE,MAAc,0BACT,WAAWI,MAGbJ,MAAc,wBACjB,YAAYI,MACZ,iBAAiBA;CACvB;CAEA,OAAOJ;AACT;AAEA,SAAgBJ,GACd,GACmC;CACnC,IAAI;EACF,IAAME,IAAU,KAAK,MAAML,EAAY,WAAW;EAElD,OAAOpE,GAASyE,CAAO,IAAIA,IAAU,CAAC;CACxC,QAAQ;EACN,OAAO,CAAC;CACV;AACF;AAEA,SAAgBO,GACd,GACA,GACS;CACT,OACEZ,EAAY,cAAc,mBAC1BA,EAAY,cAAc,sBACzBA,EAAY,cAAc,yBACzBE,EAAwBF,EAAY,WAAWK,CAAO,KACxDhF,EAAgBgF,GAAS,QAAQ,MAAM,cACvChF,EAAgBgF,GAAS,eAAe,MAAM;AAElD;AAEA,SAAgBQ,GAAuB,GAAuB;CAC5D,OAAOC,EAAenF,CAAK;AAC7B;AAEA,SAASoF,GACP,GACA,GACA,GACA,GACe;CACf,IAAIf,EAAY,cAAc,oBAG5B,OAAOnF,GACL;EACE,mBAAmBmF,EAAY;EAC/B,qBAAqB3E,EAAgBgF,GAAS,qBAAqB;CACrE,GACApF,CACF;CAGF,IAAI+E,EAAY,cAAc,4BAA4B;EACxD,IAAMgB,IAAoB3F,EAAgBgF,GAAS,mBAAmB,GAChEY,IAAmB5F,EAAgBgF,GAAS,kBAAkB;EAEpE,IAAI,CAACW,GACH,OAAO;EAGT,IAAME,IAAiB3D,EACrByD,GACA/F,CACF;EAEA,OAAOgG,IACH,MAAMC,EAAe,OAAO3D,EAC1B0D,GACAhG,CACF,EAAE,KACF,MAAMiG;CACZ;CAEA,IAAIlB,EAAY,cAAc,gBAAgB;EAG5C,IAAMmB,IAAsBpF,GAC1BsE,GACA,8BACF;EAEA,IAAIc,EAAoB,QACtB,OAAO,QAAQA,EACZ,KAAK,MAAa5D,EAAsBrC,GAAUD,CAAkB,CAAC,CAAC,CACtE,KAAK,KAAK;EAGf,IAAMmG,IAAmB/F,EAAgBgF,GAAS,kBAAkB,GAC9DgB,IAA2BhG,EAC/BgF,GACA,0BACF;EAEA,IAAI,CAACe,GAAkB;GACrB,IAAME,IAAqBvF,GACzBsE,GACA,oBACF;GAEA,OAAOiB,EAAmB,SACtB,SAASA,EACN,KAAK,MACJ/D,EAAsBrC,GAAUD,CAAkB,CACpD,CAAC,CACA,KAAK,GAAG,MACX;EACN;EAEA,IAAM0C,IAAgBJ,EACpB6D,GACAnG,CACF,GACM2C,IAAwBL,EAC5B8D,GACApG,CACF;EAEA,OAAOoG,KACLA,MAA6BD,IAC3B,OAAOzD,EAAc,QAAQC,EAAsB,KACnD,OAAOD;CACb;CAEA,IAAIqC,EAAY,cAAc,gBAAgB;EAC5C,IAAMhD,IAAS3B,EAAgBgF,GAAS,QAAQ,GAC1CkB,IAAUlG,EAAgBgF,GAAS,SAAS,GAC5CmB,IAAgBxE,IAClB,MAAMD,GAA4BC,CAAM,MACxC,MAEEyE,IAAqBpG,EAAgBgF,GAAS,oBAAoB;EAExE,OAAOrD,MAAW,cAAcuE,IAC5B,CAACC,GAAe,QAAQD,GAAS,CAAC,CAC/B,OAAOtF,CAAa,CAAC,CACrB,KAAK,KAAK,IACbe,MAAW,cAAcuE,IACvB,CAACC,GAAe,QAAQD,GAAS,CAAC,CAC/B,OAAOtF,CAAa,CAAC,CACrB,KAAK,KAAK,IACbe,MAAW,gBACT,CACEwE,GACA,OAAOjE,EACLkE,GACAxG,CACF,GACF,CAAC,CACE,OAAOgB,CAAa,CAAC,CACrB,KAAK,KAAK,IACbuF;CACV;CAEA,IAAIxB,EAAY,cAAc,kBAAkB;EAC9C,IAAMhD,IAAS3B,EAAgBgF,GAAS,QAAQ;EAEhD,IAAIrD,GACF,OAAO,QAAQD,GAA4BC,CAAM;EAGnD,IAAM0E,IAAe1F,GAAgBqE,GAAS,cAAc,GACtDsB,IAAgB3F,GAAgBqE,GAAS,eAAe;EAE9D,IAAIqB,MAAiB,QAAQC,MAAkB,MAC7C,OAAO,QAAQD,EAAa,GAAGC;EAGjC,IAAMC,IAAavG,EAAgBgF,GAAS,YAAY,GAClDwB,IAAWxG,EAAgBgF,GAAS,UAAU;EAEpD,IAAIuB,KAAcC,GAChB,OAAO,KAAK1E,GAAqByE,GAAYxE,CAAQ,EAAE,OAAOD,GAAqB0E,GAAUzE,CAAQ;CAEzG;CAEA,IAAI4C,EAAY,cAAc,4BAA4B;EACxD,IAAMpD,IAAQvB,EAAgBgF,GAAS,OAAO;EAE9C,OAAOzD,IAAQ,QAAQD,GAAuBC,CAAK,MAAM;CAC3D;CAEA,OAAO;AACT;AAEA,SAAgBkF,GACd,GACA,GACA,GACA,GACA,GACA,GACA,GACwC;CACxC,IAAI9B,EAAY,cAAc,gBAC5B,OAAO,CACLZ,EACE2B,GACEf,GACAK,GACAjD,GACAnC,CACF,CACF,CACF,CAAC,CAAC,OAAOwE,CAAyB;CAGpC,IAAMsC,IAAe/B,EAAY,SAC7BgC,EAAsB,IAAIhC,EAAY,MAAM,IAC5C,MACEhD,IACJ3B,EAAgBgF,GAAS,QAAQ,KAAK0B,GAAc,UAAU,MAC1DR,IACJlG,EAAgBgF,GAAS,SAAS,KAAK0B,GAAc,WAAW,MAC5DN,IACJpG,EAAgBgF,GAAS,oBAAoB,KAC7C0B,GAAc,sBACd,MACIE,IACJ5G,EAAgBgF,GAAS,aAAa,KACtC0B,GAAc,eACd,MACIG,IAAYD,IAAcE,EAAe,IAAIF,CAAW,IAAI;CAKlE,OAAO;EACL7C,EALoBpC,IAClB,MAAMD,GAA4BC,CAAM,MACxC,IAGmC;EACrCA,MAAW,aACPsC,EAA2B,QAAQiC,KAAW,KAAK,QAAQ,IAC3D;EACJvE,MAAW,aACPsC,EAA2B,QAAQiC,CAAO,IAC1C;EACJvE,MAAW,aACPsC,EAA2B,QAAQiC,KAAW,GAAG,IACjD;EACJvE,MAAW,gBACPoC,EACE,OAAO7B,EACLkE,GACAxG,CACF,GACF,IACA;EACJ+B,MAAW,gBACPsC,EAA2B,QAAQiC,KAAW,GAAG,IACjD;EACJW,IACI9C,EACEgD,GAAuB,QACnB,UAAU3F,GAAcyF,EAAU,iBAAiB,EAAE,KACrD,UAAUzF,GAAcyF,EAAU,iBAAiB,EAAE,EAC3D,IACA;CACN,CAAC,CAAC,OAAOzC,CAAyB;AACpC;AAEA,SAAgB4C,EACd,GACA,GACA,GACA,GACA,GACS;CACT,IAAIhF,EAAK,SAAS,gBAAgBiF,EAAmB,IAAIjF,EAAK,EAAE,GAC9D,OAAO;CAGT,IAAIkF,MAAkB,YACpB,OAAO;CAGT,IAAM3F,IAAQ4F,GAAqBnF,GAAMoF,GAAOC,GAAQH,CAAa;CAErE,OAAO3F,EAAM,SAAS,aAAaA,EAAM,SAAS;AACpD;AAEA,SAAgB+F,GACd,GACA,GACA,GACA,GACA,GACyB;CACzB,IAAIJ,MAAkB,aAAaA,MAAkB,YACnD,OAAO,CAAC;CAGV,IAAMK,IAAcxF,EAAS,MAAM,QAAQ,MACzCiF,EACEhF,GACAoF,GACAC,GACAH,GACAD,CACF,CACF,GACMO,IAAqBC,GACzB1F,GACAwF,GACAH,GACAC,GACAJ,CACF,GACMS,IAAsB,IAAI,IAC9B3F,EAAS,MAAM,KAAK,GAAM,MAAU,CAACC,EAAK,IAAI2F,CAAK,CAAC,CACtD;CAEA,OAAOJ,EACJ,QAAQ,MAASC,EAAmB,IAAIxF,EAAK,EAAE,CAAC,CAAC,CACjD,MAAM,GAAM,MAAU;EACrB,IAAM4F,IAAeJ,EAAmB,IAAIK,EAAK,EAAE,KAAK,GAClDC,IAAgBN,EAAmB,IAAIO,EAAM,EAAE,KAAK;EAc1D,OAZIH,MAAiBE,IAIjBD,EAAK,SAAS,MAAME,EAAM,SAAS,IAInCF,EAAK,SAAS,MAAME,EAAM,SAAS,KAKpCL,EAAoB,IAAIG,EAAK,EAAE,KAAK,MACpCH,EAAoB,IAAIK,EAAM,EAAE,KAAK,KAL/BF,EAAK,SAAS,IAAIE,EAAM,SAAS,IAJjCF,EAAK,SAAS,IAAIE,EAAM,SAAS,IAJjCH,IAAeE;CAe1B,CAAC;AACL;AAEA,SAASL,GACP,GACA,GACA,GACA,GACA,GAC6B;CAC7B,IAAMO,IAAgB,IAAI,IAAIT,EAAY,KAAK,MAASvF,EAAK,EAAE,CAAC,GAC1DiG,IAAkBlG,EAAS,MAAM,QAEpC,GAAQ,MAAS;EAClB,IAAMmG,IAAc,CAAC,GAAIC,EAAO,IAAIvF,EAAK,MAAM,KAAK,CAAC,GAAIA,EAAK,MAAM;EAEpE,OAAO,IAAI,IAAIuF,CAAM,CAAC,CAAC,IAAIvF,EAAK,QAAQsF,CAAW;CACrD,mBAAG,IAAI,IAAI,CAAC;CAQZ,OAPwBE,GACtBrG,GACAqF,GACAC,GACAJ,CAGK,CAAA,CAAgB,QACpB,GAAW,MACVoB,GACEC,GACAC,GAA4BtG,GAAQgG,GAAiBD,CAAa,CACpE,mBACF,IAAI,IAAI,CACV;AACF;AAEA,SAASI,GACP,GACA,GACA,GACA,GACmB;CACnB,IAAMI,IAAenB,EAClB,QAAQ,MAAUoB,EAAM,WAAW,YAAYA,EAAM,WAAW,SAAS,CAAC,CAC1E,KAAK,MAAUA,EAAM,aAAa,GAC/BC,IAAqBtB,EACxB,OAAOvG,EAAa,CAAC,CACrB,KAAK,MAASC,EAAK,MAAM,GACtB6H,IAA6B5G,EAAS,MACzC,QAAQ,MAASkF,EAAmB,IAAIjF,EAAK,EAAE,CAAC,CAAC,CACjD,KAAK,MAASA,EAAK,EAAE,GAClB4G,IAAwB,CAC5B,mBAAG,IAAI,IAAI;EACT,GAAGJ;EACH,GAAGE;EACH,GAAGC;CACL,CAAC,CACH,GACME,IAAe9G,EAAS,MAC3B,QAAQ,MAASC,EAAK,SAAS,YAAY,CAAC,CAC5C,KAAK,MAASA,EAAK,EAAE;CAExB,OAAO4G,EAAsB,SAAS,IAClCA,IACAC;AACN;AAEA,SAASN,GACP,GACA,GACA,GAC6B;CAM7B,OAAOO,GAAwB,CAFxB;EAAE,UAAU;EAAG,QAAQC;CAAY,CAEX,GAAcd,GAAiBD,CAAa;AAC7E;AAEA,SAASc,GACP,GACA,GACA,GACA,oBAAsC,IAAI,IAAI,GAC9C,oBAAyC,IAAI,IAAI,GACpB;CAC7B,IAAM,CAACE,GAAS,GAAGC,KAAaC;CAEhC,IAAI,CAACF,GACH,OAAOV;CAGT,IAAIa,EAAe,IAAIH,EAAQ,MAAM,GACnC,OAAOF,GACLG,GACAhB,GACAD,GACAmB,GACAb,CACF;CAGF,IAAMc,IAAqB,IAAI,IAAID,CAAc,CAAC,CAAC,IAAIH,EAAQ,MAAM,GAC/DK,IAAgBrB,EAAc,IAAIgB,EAAQ,MAAM,IAClD,IAAI,IAAIV,CAAS,CAAC,CAAC,IACjBU,EAAQ,QACR,KAAK,IACHV,EAAU,IAAIU,EAAQ,MAAM,KAAKA,EAAQ,UACzCA,EAAQ,QACV,CACF,IACAV;CASJ,OAAOQ,GACL,CARA,GAAGG,GACH,IAAIhB,EAAgB,IAAIe,EAAQ,MAAM,KAAK,CAAC,EAAA,CAAG,KAAK,OAAY;EAC9D,UAAUA,EAAQ,WAAW;EAC7B;CACF,EAAE,CAIF,GACAf,GACAD,GACAoB,GACAC,CACF;AACF;AAEA,SAAShB,GACP,GACA,GAC6B;CAC7B,OAAO,CAAC,GAAGgB,EAAc,QAAQ,CAAC,CAAC,CAAC,QACjC,GAAiB,CAACpH,GAAQqH,OACzB,IAAI,IAAIC,CAAe,CAAC,CAAC,IACvBtH,GACA,KAAK,IAAIsH,EAAgB,IAAItH,CAAM,KAAKqH,GAAUA,CAAQ,CAC5D,GACFE,CACF;AACF;AAEA,SAAgBC,GAAwB,GAA4B;CAOlE,OANIzH,EAAK,SAAS,aAAmB,QAAQA,EAAK,KAAK,UACnDA,EAAK,SAAS,gBAAsB,QAAQA,EAAK,KAAK,UACtDA,EAAK,SAAS,qBAA2B,QAAQA,EAAK,KAAK,UAC3DA,EAAK,SAAS,oBAA0B,QAAQA,EAAK,KAAK,UAC1DA,EAAK,SAAS,aAAmB,QAAQA,EAAK,KAAK,UAEhD,QAAQA,EAAK,KAAK;AAC3B;AAEA,SAAgB0H,GACd,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACsB;CACtB,IAAMC,IAAeC,EAClB,OAAOlF,EAAwB,CAAC,CAChC,KAAK,MAAoC;EACxC,IAAMM,IAAUF,GAAoBH,CAAW,GACzCkF,IAAYlF,EAAY,SAC1B7C,GAAqB6C,EAAY,QAAQ5C,CAAQ,IACjD;EAyBJ,OAAO;GACL,kBAzBuB;IACvBgC,EACE8F,IAAY,MAAMA,MAAc,QAClC;IACA3F,GACE,OACAS,EAAY,eACZ/E,GACA,IACF;IACAmE,EACE,MAAMyB,GAAuBb,EAAY,SAAS,GACpD;IACA,GAAG8B,GACD9B,GACAK,GACAjD,GACA4E,GACAG,GACAC,GACAnH,CACF;GACF,CAAC,CAAC,OAAOwE,CAGP;GACA,OAAOmB,GAAgBZ,GAAaK,CAAO;GAC3C,IAAIL,EAAY;GAChB,OAAOU,EAAuBV,EAAY,WAAWK,CAAO;EAC9D;CACF,CAAC,GACG8E,IAAmB1C,EAAM,OAAOvG,EAAa,CAAC,CAAC,KAClD,OAA8B;EAC7B,kBAAkB;GAChBkD,EACE,MAAMjC,GAAqBhB,EAAK,QAAQiB,CAAQ,GAClD;GACAmC,GACE,OACApD,EAAK,kBACLlB,GACA,KACF;GACAmE,EACE,QAAQyB,GAAuB1E,EAAK,SAAS,GAC/C;EACF,CAAC,CAAC,OAAOsD,CAAyB;EAClC,OAAO;EACP,IAAI,gBAAgBtD,EAAK;EACzB,OAAOA,EAAK,WAAW,gBAAgB,UAAU;CACnD,EACF,GACMmG,IAAqB,IAAI,IAC7B,CACE,GAAG2C,EACA,OAAOlF,EAAwB,CAAC,CAChC,KAAK,MAAgBC,EAAY,MAAM,GAC1C,GAAGyC,EAAM,KAAK,MAAStG,EAAK,MAAM,CACpC,CAAC,CAAC,OAAOF,CAAa,CACxB,GACMmJ,IAAkBhI,IACpBuF,GACEvF,GACAqF,GACAC,GACAH,GACAD,CACF,CAAC,CAAC,KACC,OAA8B;EAC7B,kBAAkB,CAChBlD,EACE,GAAGnJ,EAAkBoH,EAAK,IAAI,EAAE,QAClC,CACF,CAAC,CAAC,OAAOoC,CAAyB;EAClC,OAAO;EACP,cAAc;EACd,IAAI,eAAepC,EAAK;EACxB,OAAOyH,GAAwBzH,CAAI;CACrC,EACF,IACA,CAAC;CAEL,OAAO;EAAC,GAAG2H;EAAc,GAAGG;EAAkB,GAAGC;CAAe;AAClE;AAQA,IAAMC,KAEF;CACF,UAAU;EAAE,aAAa;EAAO,MAAM;CAAY;CAClD,WAAW;EAAE,aAAa;EAAO,MAAM;CAAY;CACnD,SAAS;EAAE,aAAa;EAAS,MAAM;CAAY;CACnD,UAAU;EAAE,aAAa;EAAO,MAAM;CAAY;AACpD;AAEA,SAAgB7C,GACd,GACA,GACA,GACA,GAKC;CACD,IAAM8C,IAAY7C,EAAM,QAAQ,MAAStG,EAAK,WAAWkB,EAAK,EAAE,GAC1DkI,IAAcD,EAAU,MAC3B,MAASnJ,EAAK,WAAW,aAAaA,EAAK,WAAW,aACzD,GACMqJ,IAAgBF,EAAU,MAAM,MAASnJ,EAAK,WAAW,WAAW,GACpEsJ,IAAgBH,EAAU,MAAM,MAASnJ,EAAK,WAAW,WAAW,GACpEuJ,IAAahD,EAAO,QAAQ,MAAUoB,EAAM,kBAAkBzG,EAAK,EAAE,GACrEsI,IAAcD,EAAW,MAAM,MAAU5B,EAAM,WAAW,QAAQ,GAClE8B,IAAeF,EAAW,MAAM,MAAU5B,EAAM,WAAW,SAAS;CAE1E,IAAIyB,GACF,OAAO;EACL,gBAAgB,OAAO9H,EAAsB8H,CAAW;EACxD,aAAa;EACb,MAAM;CACR;CAGF,IAAIC,GACF,OAAO;EACL,gBAAgB,OAAO/H,EAAsB+H,CAAa;EAC1D,aAAa;EACb,MAAM;CACR;CAGF,IAAIC,GACF,OAAO;EACL,gBAAgB,OAAOhI,EAAsBgI,CAAa;EAC1D,aAAa;EACb,MAAM;CACR;CAGF,IAAIE,GACF,OAAO;EACL,gBAAgB,SAASA,EAAY;EACrC,aAAa;EACb,MAAM;CACR;CAGF,IAAIC,GACF,OAAO;EACL,gBAAgB,SAASA,EAAa;EACtC,aAAa;EACb,MAAM;CACR;CAGF,IAAIvI,EAAK,SAAS,cAChB,OAAO;EACL,gBAAgB;EAChB,aAAa;EACb,MAAM;CACR;CAGF,IAAMwI,IACJxI,EAAK,SAAS,aAAagI,GAAiB9C,KAAiB,KAAA;CAS/D,OAJIsD,IACK;EAAE,GAAGA;EAAgB,gBAAgBtD;CAAc,IAGrD;EACL,gBAAgBtM,EAAkBoH,EAAK,IAAI;EAC3C,aAAa;EACb,MAAM;CACR;AACF;;;ACtxCA,eAAsByI,GAA8B,EAClD,iBACA,qBAAkB,CAAC,GACnB,aACA,YAS0C;CAC1C,IAAMtH,IAAY,CAChB,GAAG,IAAI,IACL;EAGEuH,GAAU,qBAAqB;EAC/BA,GAAU,uBAAuB;EACjC,GAAGd,EAAa,KAAK,MAAgBjF,EAAY,aAAa;EAC9D,GAAGiF,EAAa,QAAQ7E,EAAsC;EAC9D,GAAGqC,EAAM,KAAK,MAAStG,EAAK,gBAAgB;EAC5C,GAAGsG,EAAM,KAAK,MAAStG,EAAK,wBAAwB;EACpD,GAAGsG,EAAM,SAAS,MAAStG,EAAK,kBAAkB;EAClD,GAAGsG,EAAM,SAAS,MAChBvM,GAAqBiG,EAAK,mBAAmB,CAAC,CAAC,SAAS,MAAS,CAC/D6J,EAAK,MACLA,EAAK,EACP,CAAC,CACH;EACA,GAAGC,EAAgB,SAAS,MAAc,CACxCC,EAAU,mBACV,GAAGC,GAAkCD,EAAU,eAAe,CAChE,CAAC;CACH,CAAC,CAAC,OAAOjK,CAAa,CACxB,CACF;CAEA,IAAI;EACF,OAAO,MAAMmK,GAAsB5H,CAAS;CAC9C,QAAQ;EACN,OAAO,CAAC;CACV;AACF;AAEA,SAAS2H,GACP,GACmB;CACnB,IAAI;EAKF,QAJc,KAAK,MAAME,CAIjB,CAAA,CAAM,aAAa,CAAC,EAAA,CAAG,QAC5B,MAAiC,OAAOnL,KAAa,QACxD;CACF,QAAQ;EACN,OAAO,CAAC;CACV;AACF;AAEA,eAAsBoL,GACpB,GACwC;CAKxC,QAAO,MAJqB,QAAQ,IAClC7D,EAAM,KAAK,MAAS8D,GAAkBpK,EAAK,EAAE,CAAC,CAChD,EAAA,CAEqB,KAAK;AAC5B;AAEA,SAAgBqK,GACd,GACyC;CACzC,OAAOC,EAAc,QAClB,GAAmB,MAAa;EAC/B,IAAMC,IAAkBC,EAAkB,IAAIC,EAAS,MAAM,GACvDC,IACJ,CAACH,KACD,IAAI,KAAKE,EAAS,SAAS,CAAC,CAAC,QAAQ,IACnC,IAAI,KAAKF,EAAgB,SAAS,CAAC,CAAC,QAAQ,IAC1CE,IACAF;EAEN,OAAO,IAAI,IAAIC,CAAiB,CAAC,CAAC,IAAIC,EAAS,QAAQC,CAAY;CACrE,mBACA,IAAI,IAAI,CACV;AACF;;;AC7GA,IAAM1Q,KAAoC;CACxC,SAAS;CACT,KAAK;AACP,GAEM4Q,KAAkC;CACtC,SAAS;CACT,UAAU;CACV,KAAK;AACP;AAyCA,SAAgBC,GAAoB,EAClC,wBACA,aACA,UACA,aACA,YACA,4BACA,yBACA,uBACA,uBACA,qBACA,yBACyC;CACzC,OACE,kBAAC,OAAD;EAAK,OAAO7Q;EAAZ,UAAA;GACGmG,IACC,kBAACvC,GAAD;IAAY,OAAM;IAAa,SAAQ;IACpC,UAAAuC;GACS,CAAA,IACV;GACH2K,IACC,kBAAClN,GAAD;IAAY,OAAM;IAAe,SAAQ;IAAO,UAAA;GAEpC,CAAA,IACV;GACHgM,GAAU,uBAAuB,UAClCA,EAAS,uBAAuB,WAC9B,kBAAA3P,GAAA,EAAA,UAAA,CACE,kBAACa,GAAD;IACE,mBACEiQ,IACI;KAKE,YAAYnB,EAAS;KACrB,MAAM;IACR,IACA,KAAA;IAEN,yBAAyBA,EAAS;IAClC,QAAQoB;IACR,WAAW,MAAiB;KAC1B,EAAqBC,CAAM;IAC7B;IACyB;IACzB,oBACEF,IAAsBG,IAAqB,KAAA;IAE7C,iBAAiBtB,EAAS;IAC1B,UAAU,CAACmB;IACX,QAAQnB,EAAS,uBAAuB;IACxC,UAAUA,EAAS,uBAAuB;IAC1C,OACEmB,IAAsBI,IAAmBvB,EAAS;GAErD,CAAA,GACAmB,IACC,kBAAC,OAAD;IAAK,OAAOH;IACV,UAAA,kBAACnN,GAAD;KACE,UAAU2N;KACV,MAAMC;KACN,UAAS;KACT,SAASC;KACT,SAAQ;KACT,UAAA;IAEO,CAAA;GACL,CAAA,IACH,IACJ,EAAA,CAAA,IAEF,kBAAC1N,GAAD;IAAY,OAAM;IAAe,SAAQ;IAAO,UAAA;GAEpC,CAAA;EAEX;;AAET;;;ACjIA,IAAM1D,KAAoC;CACxC,SAAS;CACT,KAAK;AACP;AAeA,SAAgBsR,GAA2B,EACzC,gBACA,eACA,gBACgD;CAChD,IAAMC,IAAiB5O,QAEnB6O,EAAY,KAAK,OAAgB;EAC/B;EACA,WAAWC,EAAW;EACtB,UAAUA,EAAW;EACrB,IAAIA,EAAW;EACf,KAAKA,EAAW;EAChB,UAAUA,EAAW;EACrB,WAAWvL,GAAe,OAAOuL,EAAW,SAAS,CAAC;CACxD,EAAE,GACJ,CAACD,CAAW,CACd,GAEME,IAAoB/O,QACY;EAClC;GAAE,WAAW;GAAY,KAAK;GAAY,OAAO;GAAM,OAAO;EAAI;EAClE;GAAE,WAAW;GAAY,KAAK;GAAY,OAAO;GAAM,OAAO;EAAI;EAClE;GAAE,WAAW;GAAa,KAAK;GAAa,OAAO;GAAM,OAAO;EAAI;EACpE;GACE,KAAK;GACL,SAAS,MACP,kBAACe,GAAD;IAAY,WAAU;IAAO,SAAQ;IAClC,UAAA+G,EAAejF,EAAO,SAAS;GACtB,CAAA;GAEd,OAAO;GACP,OAAO;EACT;CACF,GACA,CAAC,CACH,GAEMmM,IAAoBhP,SACY;EAClC,SAAS,MAA8D,CACrE,GAAI6C,EAAO,aAAa,oBACpB,CACE;GACE,MAAMoM;GACN,UAAU;GACV,MAAM;GACN,eAAqB;IACnB,EAAUpM,EAAO,UAAU;GAC7B;EACF,CACF,IACA,CAAC,GACL;GACE,MAAMxB;GACN,UAAU;GACV,MAAM;GACN,eAAqB;IACnB,EAAWwB,EAAO,UAAU;GAC9B;EACF,CACF;EACA,SAAS;EACT,OAAO;CACT,IACA,CAACzB,GAAY8N,CAAS,CACxB;CAEA,OACE,kBAAC,OAAD;EAAK,OAAO7R;EAAZ,UAAA,CACE,kBAAC0D,GAAD;GAAY,WAAU;GAAK,SAAQ;GAAK,UAAA;EAE5B,CAAA,GACX6N,EAAe,SAAS,IACvB,kBAACO,IAAD;GACE,SAASH;GACT,SAASD;GACT,YAAYH;GACZ,WAAA;EACD,CAAA,IAED,kBAAC7N,GAAD;GAAY,OAAM;GAAe,SAAQ;GAAO,UAAA;EAEpC,CAAA,CAEX;;AAET;;;AC3DA,IAAMqO,KAA0C;CAC9C,SAAS;CACT,KAAK;CACL,OAAO;AACT,GAEMC,KAA8C;CAClD,UAAU;CACV,OAAO;AACT,GAEMC,KAAkC;CACtC,SAAS;CACT,KAAK;CACL,OAAO;AACT,GAEMC,KAAqC,EACzC,WAAW,GACb,GAEMC,KAA0C,EAC9C,WAAW,GACb;AAEA,SAASC,GAA2B,GAAsC;CACxE,AAAKC,MAIL,EAAQ,MAAM,QAAQ;AACxB;AAwDA,IAAMC,KAA+D;CACnE,mBAAmB;CACnB,aAAa;CACb,cAAc;CACd,cAAc;AAChB,GAEMC,KAAwE;CAC5E,mBAAmB;CACnB,aAAa;CACb,cAAc;CACd,cAAc;AAChB,GAEMC,KAGA,CACJ;CAAE,IAAI;CAAmB,MAAM;AAAY,GAC3C;CAAE,IAAI;CAAoB,MAAM;AAAgB,CAClD,GAEMC,KAGA,CACJ;CAAE,IAAI;CAAU,MAAM;AAAO,GAC7B;CAAE,IAAI;CAAW,MAAM;AAAU,CACnC,GAkBaC,KAAuBC,EAGlC,SACA,EACE,oBACA,oBACA,aACA,uBACA,cACA,YAEF,GACc;CACd,IAAM,CAACzB,GAAU0B,KAAe/Q,EAAS,EAAK,GACxC,CAACoE,GAAO4M,KAAYhR,EAAwB,IAAI,GAKhD,CAACiR,IAAgBC,KAAqBlR,EAAS,EAAE,GACjD,CAACmR,IAAkBC,MAAuBpR,EAAS,EAAK,GAGxD,CAACqR,GAAcC,MAAmBtR,EAAS,EAAE,GAC7C,CAACuR,IAAmBC,MAAwBxR,EAAwB,IAAI,GACxE,CAACyR,IAAuBC,MAA4B1R,EAAS,EAAK,GAGlE,CAAC2R,IAAeC,MAAoB5R,EAAS,EAAE,GAC/C,CAAC6R,IAAiBC,MAAsB9R,EAAS,EAAK,GACtD,CAAC+R,IAAoBC,MAAyBhS,EAAwB,IAAI,GAG1E,CAACiS,IAAiBC,MAAsBlS,EAAS,EAAE,GACnD,CAACmS,IAAgBC,MAAqBpS,EAA8B,IAAI,GACxE,CAACqS,IAAuBC,MAA4BtS,EAAS,EAAK,GAClE,CAACuS,IAAuBC,KAA4BxS,EAExD,CAAC,CAAC,GACE,CAACyS,IAAmBC,MAAwB1S,EAAS,EAAK,GAG1D,CAAC2S,IAAcC,MAAmB5S,EAAS,EAAE,GAC7C,CAAC6S,GAAcC,MAAmB9S,EACtC,CAAC,CACH,GACM,CAAC+S,IAAoBC,MAAyBhT,EAAS,EAAK,GAC5D,CAACiT,IAAoBC,MAAyBlT,EAElD,CAAC,CAAC,GACE,CAACmT,IAAgBC,MAAqBpT,EAAS,EAAK,GACpD,CAACqT,GAAWC,MAAgBtT,EAA0B,aAAa,GACnE,CAACuT,IAAeC,MACpBxT,EAAyC,iBAAiB,GACtD,CAACyT,GAAiBC,MAAsB1T,EAAS,EAAK,GACtD,CAAC2T,IAAiBC,MAAsB5T,EAC5C,QACF,GACM,CAAC6T,IAAiBC,KAAsB9T,EAAS,EAAE,GAEnD+T,IAAsB1C,EAAa,KAAK,GACxC2C,KAAuBrC,GAAc,KAAK,GAC1CsC,KAAyBhC,GAAgB,KAAK,GAE9CiC,IAAcpT,QAEhByJ,EAAM,MACH,MACC5E,GAAmB1B,GAAMkQ,CAAe,MACvClQ,EAAK,WAAW,aAAaA,EAAK,WAAW,cAClD,KAAK,MACP,CAACkQ,GAAiB5J,CAAK,CACzB,GAEM6J,IAAkBtT,QAEpBoT,KAAerG,IACVA,EAAS,iBAAiB,MAAM,MAC9B,MAAS1I,EAAK,OAAO+O,EAAY,MACpC,KAAK,OACL,MACN,CAACA,GAAarG,CAAQ,CACxB,GAEMwG,IAAsBvT,QAExBsT,KAAmBvG,IACfjI,EAAwBiI,EAAS,kBAAkBuG,CAAe,IAClE,CAAC,GACP,CAACA,GAAiBvG,CAAQ,CAC5B,GAEMyG,KACJF,GAAiB,SAAS,cAC1BA,EAAgB,KAAK,eAAe,aAKhCG,IACJH,GAAiB,SAAS,cAC1BA,EAAgB,KAAK,gBAAgB,IACjCI,KACJJ,GAAiB,SAAS,cAC1BA,EAAgB,KAAK,kBAAkB,IAInCK,IACJL,GAAiB,SAAS,cAC1BA,EAAgB,KAAK,eAAe,mBAAmB,IAEnDM,KACJN,GAAiB,SAAS,cAC1BA,EAAgB,KAAK,gBAEjBO,KAAyB7T,QAE3BiN,EAAgB,QAAQ,MAAcC,EAAU,WAAW,SAAS,GACtE,CAACD,CAAe,CAClB,GAEM6G,KACJP,EAAoB,MAAM,MAAW7N,EAAO,OAAOuL,EAAkB,KACrEsC,EAAoB,MACpB,MAEIQ,KAAW/T,QAEbyJ,EAAM,KAAK,OAAU;EACnB,GAAGtG;EACH,eAAesB,EAAsBtB,GAAMlB,CAAkB;EAC7D,KAAKkB,EAAK;EAGV,WAAWnF,EAAiB;GAC1B,GAAGmF;GACH,WAAWgB,GACThB,EAAK,QACL4J,GAAU,oBAAoB,IAChC;EACF,CAAC;EACD,aAAalJ,EAAoBV,EAAK,MAAM;CAC9C,EAAE,GACJ;EAAC4J;EAAU9K;EAAoBwH;CAAK,CACtC,GAEMuK,IAAchU,QACY;EAC5B;GAAE,WAAW;GAAa,KAAK;GAAa,OAAO;GAAM,OAAO;EAAI;EACpE;GACE,KAAK;GACL,OAAO;GACP,SAAS,MACP,kBAACe,GAAD;IAAY,WAAU;IAAO,SAAQ;IAClC,UAAA8B,EAAO;GACE,CAAA;GAEd,OAAO;EACT;EACA;GACE,WAAW;GACX,KAAK;GACL,OAAO;GACP,OAAO;EACT;EACA;GACE,KAAK;GACL,SAAS,MACP,kBAAC9B,GAAD;IAAY,WAAU;IAAO,SAAQ;IAClC,UAAA+G,EAAejF,EAAO,SAAS;GACtB,CAAA;GAEd,OAAO;GACP,OAAO;EACT;CACF,GACA,CAAC,CACH,GAEMoR,KAAqBjU,QAEvB6T,GAAuB,KAAK,OAAe;EACzC,GAAG3G;EACH,gBAAgB3I,EACd2I,EAAU,mBACVjL,CACF;EACA,KAAKiL,EAAU;EACf,aAAagH,GACXhH,GACAjL,CACF;EACA,WAAW0N,GAAkBzC,EAAU;CACzC,EAAE,GACJ,CAACjL,GAAoB4R,EAAsB,CAC7C,GAEMM,KAAwBnU,QACY;EACtC;GACE,WAAW;GACX,KAAK;GACL,OAAO;GACP,OAAO;EACT;EACA;GACE,KAAK;GACL,SAAS,MACP,kBAACe,GAAD;IAAY,WAAU;IAAO,SAAQ;IAClC,UAAA8B,EAAO;GACE,CAAA;GAEd,OAAO;GACP,OAAO;EACT;EACA;GACE,KAAK;GACL,SAAS,MACP,kBAAC9B,GAAD;IAAY,WAAU;IAAO,SAAQ;IAClC,UAAA8B,EAAO;GACE,CAAA;GAEd,OAAO;GACP,OAAO;EACT;EACA;GACE,KAAK;GACL,SAAS,MACP,kBAAC9B,GAAD;IAAY,WAAU;IAAO,SAAQ;IAClC,UAAA+G,EAAejF,EAAO,SAAS;GACtB,CAAA;GAEd,OAAO;GACP,OAAO;EACT;EACA;GACE,KAAK;GACL,SAAS,MACPA,EAAO,sBAAsBwQ,IAC3B,kBAACzS,GAAD;IACE,UAAU+R;IACV,eACE,KAAKyB,GAA2BvR,EAAO,EAAE;IAE3C,MAAK;IACL,SAAQ;IACT,UAAA;GAEO,CAAA,IAER,kBAAAvF,GAAA,CAAI,CAAA;GAER,OAAO;GACP,OAAO;EACT;CACF,GACA,CAACqV,GAAiBU,CAAe,CACnC;CAEA,eAAegB,EAAe,EAC5B,WACA,YACA,oBAAiB,MACjB,wBAAqB,QAMD;EASpB,IARI,CAAChB,KAAmB,CAACD,KAIrBpP,MAAW,cAAc,CAACyP,KAI1BzP,MAAW,iBAAiB,CAAC0P,IAC/B,OAAO;EAIT,AADAzD,EAAY,EAAI,GAChBC,EAAS,IAAI;EAEb,IAAI;GAiBF,AAhBA,MAAMoE,GAAW;IACf;IACA;IACA,mBAAmBjB;IACnB;IACA,QAAQD,EAAY;IACpB;GACF,CAAC,GACDxC,GAAyB,EAAK,GAC9BI,GAAmB,EAAK,GACxBY,GAAqB,EAAK,GAC1BpB,GAAgB,EAAE,GAClBM,GAAiB,EAAE,GACnBM,GAAmB,EAAE,GACrBE,GAAkB,IAAI,GACtBJ,GAAsB,IAAI,GAC1BR,GAAqB,IAAI;EAC3B,SAAS6D,GAAuB;GAI9B,OAHArE,EAAS9M,EAAiBmR,CAAY,CAAC,GACvCtE,EAAY,EAAK,GAEV;EACT;EAEA,IAAI;GACF,MAAMuE,EAAU;EAClB,SAASD,GAAuB;GAC9B,EAASnR,EAAiBmR,CAAY,CAAC;EACzC,UAAU;GACR,EAAY,EAAK;EACnB;EAEA,OAAO;CACT;CAEA,SAASE,KAAyB;EAChC,AAAKpB,KAAoBD,MAIzBlD,EAAS,IAAI,GACbE,EAAkB,EAAE,GACpBE,GAAoB,EAAI;CAC1B;CAEA,SAASoE,KAA0B;EACjC,AAAInG,MAIJ+B,GAAoB,EAAK,GACzBF,EAAkB,EAAE;CACtB;CAEA,eAAeuE,KAAsC;EACnD,AAAIpG,KASC,MALmB8F,EAAe;GACrC,QAAQ;GACR,SAASlE,GAAe,KAAK,KAAK;EACpC,CAAC,MAMDG,GAAoB,EAAK,GACzBF,EAAkB,EAAE;CACtB;CAEA,SAASwE,KAA8B;EACrC,AAAKnB,MAILjD,GAAgB,EAAE,GAClBE,GAAqB,IAAI,GACzBE,GAAyB,EAAI;CAC/B;CAEA,SAASiE,KAA+B;EACtC,AAAItG,MAIJqC,GAAyB,EAAK,GAC9BJ,GAAgB,EAAE,GAClBE,GAAqB,IAAI;CAC3B;CAEA,SAASoE,KAAwB;EAG/B,AAFAhE,GAAiB,EAAE,GACnBI,GAAsBqC,EAAoB,EAAE,EAAE,MAAM,IAAI,GACxDvC,GAAmB,EAAI;CACzB;CAEA,SAAS+D,IAAyB;EAChC,AAAIxG,MAIJyC,GAAmB,EAAK,GACxBF,GAAiB,EAAE,GACnBI,GAAsB,IAAI;CAC5B;CAEA,SAAS8D,IAA0B;EACjC,AAAKtB,OAILtC,GAAmB,EAAE,GACrBE,GAAkB,IAAI,GACtBM,GAAqB,EAAI,GACzBqD,GAAiC,EAAE;CACrC;CAEA,SAASC,IAA2B;EAClC,AAAI3G,MAIJqD,GAAqB,EAAK,GAC1BR,GAAmB,EAAE,GACrBE,GAAkB,IAAI;CACxB;CAEA,eAAe2D,GACb,GACe;EACf,GAAyB,EAAI;EAE7B,IAAI;GACF,GACG,MAAME,GAAclP,CAAU,EAAA,CAC5B,QACE,MAAmBmP,EAAe,aAAa/B,CAClD,CAAC,CACA,IAAIlO,EAAgB,CACzB;EACF,SAASoP,GAAuB;GAC9B,EAASnR,EAAiBmR,CAAY,CAAC;EACzC,UAAU;GACR,GAAyB,EAAK;EAChC;CACF;CAEA,eAAec,IAAqC;EAClD,AAAK5B,MAIAR,IAML,MAAMoB,EAAe;GACnB,QAAQ;GACR,SAASpB;EACX,CAAC,IARCvC,GAAqB,SAAS;CASlC;CAEA,eAAe4E,IAAuC;EACpD,AAAK5B,OAIArC,KAML,MAAMgD,EAAe;GACnB,QAAQ;GACR,SAASlB,MAA0B;GACnC,oBAAoB9B,GAAe;EACrC,CAAC,IATCnB,EAAS,SAAS;CAUtB;CAEA,eAAeqF,KAAqC;EAClD,MAAMlB,EAAe;GACnB,QAAQ;GACR,SAASnB,MAAwB;GACjC,gBAAgBY,IAA4B,MAAM;EACpD,CAAC;CACH;CAEA,SAAS0B,KAA6B;EAKpC,AAJA1D,GAAgB,EAAE,GAClBE,GAAgB,CAAC,CAAC,GAClBU,GAAiB,iBAAiB,GAClCI,GAAmB,QAAQ,GAC3BE,EAAmB,EAAE;CACvB;CAEA,SAASyC,GAAe,GAA6B;EAInD,AAHAjD,GAAakD,CAAI,GACjBF,GAAqB,GACrBlD,GAAkB,EAAI,GACtBqD,EAA8B,EAAE;CAClC;CAEA,SAASC,IAAwB;EAC/B,AAAIjD,MAIJL,GAAkB,EAAK,GACvBkD,GAAqB;CACvB;CAEA,eAAeG,EAAyB,GAAmC;EACzE,GAAsB,EAAI;EAE1B,IAAI;GACF,IACG,MAAMR,GAAclP,CAAU,EAAA,CAAG,IAAId,EAAgB,CACxD;EACF,SAASoP,GAAuB;GAC9B,EAASnR,EAAiBmR,CAAY,CAAC;EACzC,UAAU;GACR,GAAsB,EAAK;EAC7B;CACF;CAEA,eAAesB,KAAoC;EACjD,IAAI,CAACzC,GACH;EAKF,IAAM/N,KADJkN,MAAc,kBAAkBA,MAAc,wBACPM,OAAoB,WACvDiD,IAAc1Q,GAAqB;GACvC,WAAW2M,EAAa,KAAK,MAAWgE,EAAO,EAAE;GACjD;GACA,YAAYhD;EACd,CAAC;EAED,IAAI,CAAC+C,EAAY,OAAO;GACtB,EAASA,EAAY,KAAK;GAE1B;EACF;EAEA,IAAM,EAAE,cAAWA,GACbE,IAAsBnE,GAAa,KAAK,KAAK;EAGnD,AADAe,GAAmB,EAAI,GACvB1C,EAAS,IAAI;EAEb,IAAI;GA4BF,AA3BIqC,MAAc,gBAChB,MAAM0D,GAAwB;IAC5B,SAASD;IACT;IACA,QAAQ5C,EAAY;GACtB,CAAC,IACQb,MAAc,iBACvB,MAAM2D,GAAwB;IAC5B,SAASF;IACT,UAAUvD;IACV;IACA,QAAQW,EAAY;GACtB,CAAC,IACQb,MAAc,iBACvB,MAAM4D,GAAgC;IACpC;IACA,QAAQ/C,EAAY;GACtB,CAAC,IAED,MAAMgD,GAAqC;IACzC;IACA,QAAQhD,EAAY;GACtB,CAAC,GAGHd,GAAkB,EAAK,GACvBkD,GAAqB,GACrB,MAAMhB,EAAU;EAClB,SAASD,GAAuB;GAC9B,EAASnR,EAAiBmR,CAAY,CAAC;EACzC,UAAU;GACR,GAAmB,EAAK;EAC1B;CACF;CAEA,eAAeH,GAA2B,GAAoC;EAE5E,AADAxB,GAAmB,EAAI,GACvB1C,EAAS,IAAI;EAEb,IAAI;GAEF,AADA,MAAMmG,GAAqBC,CAAW,GACtC,MAAM9B,EAAU;EAClB,SAASD,GAAuB;GAC9B,EAASnR,EAAiBmR,CAAY,CAAC;EACzC,UAAU;GACR,GAAmB,EAAK;EAC1B;CACF;CAIA,EACEgC,UACmC;EACjC;EACA;EACA;EACA;EACA;EACA,eAAe9B;EACf,gBAAgBrB,MAAgB;EAChC;EACA,iBAAiBwB;EACjB;EACA;CACF,IACA;EACEhB;EACAH;EACAD;EACAE;EACAL;EACAD;EACA7E;CACF,CACF;CAEA,IAAMiI,IACJjE,MAAc,kBAAkBA,MAAc,qBAC1CkE,KACJD,KAAqB3D,OAAoB,YACrC,CAACE,GAAgB,KAAK,IACtBhB,EAAa,WAAW,GACxB2E,KACJ7G,GAAwB,MAAM,MAAWnK,EAAO,OAAO+M,EAAa,KACpE5C,GAAwB,IACpB8G,KACJ7G,GAA4B,MACzB,MAAWpK,EAAO,OAAOmN,EAC5B,KAAK/C,GAA4B;CAEnC,OACE,kBAAAxS,GAAA,EAAA,UAAA;EACE,kBAACyD,GAAD;GAAY,WAAU;GAAK,SAAQ;GAAK,UAAA;EAE5B,CAAA;EACXuC,IACC,kBAACvC,GAAD;GAAY,OAAM;GAAa,SAAQ;GACpC,UAAAuC;EACS,CAAA,IACV;EACJ,kBAAC,OAAD;GAAK,OAAOiM;GACV,UAAA,kBAACJ,IAAD;IAAO,SAAS6E;IAAa,YAAYD;IAAU,WAAA;GAAW,CAAA;EAC3D,CAAA;EAEJF,GAAuB,SAAS,IAC/B,kBAAAvW,GAAA,EAAA,UAAA,CACE,kBAACyD,GAAD;GAAY,WAAU;GAAK,OAAOyO;GAA0B,SAAQ;GAAK,UAAA;EAE7D,CAAA,GACZ,kBAAC,OAAD;GAAK,OAAOD;GACV,UAAA,kBAACJ,IAAD;IACE,SAASgF;IACT,YAAYF;IACZ,WAAA;GACD,CAAA;EACE,CAAA,CACL,EAAA,CAAA,IACA;EAGJ,kBAAC2C,GAAD;GACE,YAAW;GACX,aAAY;GACZ,SAASrI;GACT,WAAU;GACV,UAAUmG;GACV,SAASA;GACT,iBAAuB,KAAKC,GAAqB;GACjD,MAAMtE;GACN,iBAAA;GACA,iBAAA;GACA,MAAK;GACL,gBAAe;GACf,OAAM;GAbR,UAAA,CAeG/M,IACC,kBAACvC,GAAD;IAAY,OAAM;IAAa,MAAK;IAAQ,SAAQ;IACjD,UAAAuC;GACS,CAAA,IACV,MACJ,kBAAC,OAAD;IAAK,OAAO8L;IACV,UAAA,kBAACvR,GAAD;KAAc,OAAM;KAAO,MAAK;KAC9B,UAAA,kBAACgZ,IAAD;MACE,WAAA;MACA,WAAW,MACTzG,EAAkB0G,EAAM,OAAO,KAAK;MAEtC,aAAY;MACZ,KAAKrH;MACL,QAAO;MACP,MAAM;MACN,OAAOJ;MACP,OAAOc;KACR,CAAA;IACW,CAAA;GACX,CAAA,CACA;;EAGP,kBAACyG,GAAD;GACE,YAAW;GACX,oBAAoB;IAClB,UAAU,CAAC3D;IACX,SAAS;GACX;GACA,aAAY;GACZ,SAAS1E;GACT,iBAAgB;GAChB,WAAU;GACV,UAAUsG;GACV,SAASA;GACT,iBAAuB,KAAKQ,EAAoB;GAChD,MAAM1E;GACN,iBAAA;GACA,iBAAA;GACA,MAAK;GACL,gBAAe;GACf,OAAM;GAEN,UAAA,kBAAC,OAAD;IAAK,OAAOvB;IAAZ,UAAA,CACE,kBAACvR,GAAD;KAAc,OAAM;KAAO,MAAK;KAAe,UAAA;KAC7C,UAAA,kBAACgZ,IAAD;MACE,WAAA;MACA,WAAW,MAAkD;OAE3D,AADArG,GAAgBsG,EAAM,OAAO,KAAK,GAClCpG,GAAqB,IAAI;MAC3B;MACA,aAAY;MACZ,KAAKjB;MACL,QAAO;MACP,MAAM;MACN,OAAOJ;MACP,MAAMoB,KAAoB,UAAU;MACpC,OAAOF;KACR,CAAA;IACW,CAAA,GACbE,KACC,kBAAC1P,GAAD;KAAY,OAAM;KAAa,SAAQ;KACpC,UAAA0P;IACS,CAAA,IACV,IACD;;EACA,CAAA;EAGP,kBAACmG,GAAD;GACE,YAAW;GACX,oBAAoB,EAClB,UAAU,CAACvF,GACb;GACA,aAAY;GACZ,SAAS9C;GACT,WAAU;GACV,UAAU2G;GACV,SAASA;GACT,iBAAuB,KAAKI,EAAsB;GAClD,MAAM3D;GACN,iBAAA;GACA,iBAAA;GACA,MAAK;GACL,gBAAe;GACf,OAAM;GAEN,UAAA,kBAAC,OAAD;IAAK,OAAOrC;IAAZ,UAAA,CACE,kBAACzR,GAAD;KAAc,OAAM;KAAO,MAAK;KAAqB,UAAA;KACnD,UAAA,kBAACkZ,IAAD;MACE,WAAA;MACA,uBAAA;MACA,WAAU;MACV,YAAY;OACV,gBAAgB;OAChB,aAAa;OACb,MAAM;OACN,YAAY;MACd;MACA,SAASxF;MACT,aAAY;MACZ,MAAK;MACL,WAAW,MACTD,GAAkB3L,GAA0BD,CAAM,CAAC;MAErD,UAAUuP;MACV,qBAAqB,MACnB3D,GACEvL,GAAuBE,GAAYwL,EAAqB,CAC1D;MAEF,qBAAqB,MAAe;OAClC,AAAIuF,KACF/B,GAAiC,EAAE;MAEvC;MACA,SAAS,CAAC,GAAGxD,EAAqB;MAClC,aAAY;MACZ,oBAAoB;MACpB,OAAOJ;KACR,CAAA;IACW,CAAA,GACd,kBAACxT,GAAD;KAAc,OAAM;KAAO,MAAK;KAC9B,UAAA,kBAACgZ,IAAD;MACE,WAAW,MACTzF,GAAmB0F,EAAM,OAAO,KAAK;MAEvC,aAAY;MACZ,KAAKrH;MACL,QAAO;MACP,MAAM;MACN,OAAOJ;MACP,OAAO8B;KACR,CAAA;IACW,CAAA,CACX;;EACA,CAAA;EAGP,kBAACyF,GAAD;GACE,YAAW;GACX,oBAAoB,EAClB,UACE,CAAC9C,MACAH,KAAyB,CAACT,GAC/B;GACA,aAAY;GACZ,SAAS3E;GACT,WAAU;GACV,UAAUwG;GACV,SAASA;GACT,iBAAuB,KAAKQ,GAAoB;GAChD,MAAMxE;GACN,iBAAA;GACA,iBAAA;GACA,MAAK;GACL,gBAAe;GACf,OAAM;GAEN,UAAA,kBAAC,OAAD;IAAK,OAAOzB;IAAZ,UAAA,CACE,kBAACzR,GAAD;KAAc,OAAM;KAAO,MAAK;KAAqB,UAAA;KACnD,UAAA,kBAACoZ,GAAD;MACE,WAAW;MACX,WAAA;MACA,WAAW,MACT/F,GAAsBxL,GAAQ,MAAM,IAAI;MAE1C,SAAS,CAAC,GAAG6N,CAAmB;MAChC,aAAY;MACZ,OAAOO;KACR,CAAA;IACW,CAAA,GACd,kBAACjW,GAAD;KACE,UACE8V,IAAwB,oBAAoB,KAAA;KAE9C,OAAM;KACN,MAAK;KACL,UAAUA;KAEV,UAAA,kBAACkD,IAAD;MACE,WAAW,MACT/F,GAAiBgG,EAAM,OAAO,KAAK;MAErC,aACEnD,IACI,YACA;MAEN,KAAKlE;MACL,QAAO;MACP,MAAM;MACN,OAAOJ;MACP,OAAOwB;KACR,CAAA;IACW,CAAA,CACX;;EACA,CAAA;EAGP,kBAAC+F,GAAD;GACE,YAAW;GACX,oBAAoB,EAClB,UAAUH,GACZ;GACA,aAAY;GACZ,SAAS9D;GACT,WAAU;GACV,UAAUiD;GACV,SAASA;GACT,iBAAuB,KAAKC,GAAmB;GAC/C,MAAMxD;GACN,iBAAA;GACA,iBAAA;GACA,MAAK;GACL,gBAAgBzC,GAA2B2C;GAC3C,OAAO5C,GAAkB4C;GAEzB,UAAA,kBAAC,OAAD;IAAK,OAAOjD;IAAZ,UAAA;KACGkH,IACC,kBAAC3Y,GAAD;MAAc,OAAM;MAAO,MAAK;MAAkB,UAAA;MAChD,UAAA,kBAACoZ,GAAD;OACE,WAAW;OACX,WAAA;OACA,WAAW,MACTzE,GACE9M,GAAQ,OAAO,sBACX,sBACA,cACN;OAEF,SAAS,CACP;QAAE,IAAI;QAAgB,MAAMiK,GAAkB;OAAa,GAC3D;QACE,IAAI;QACJ,MAAMA,GAAkB;OAC1B,CACF;OACA,OAAO;QACL,IAAI4C;QACJ,MAAM5C,GAAkB4C;OAC1B;MACD,CAAA;KACW,CAAA,IACZ;KACHiE,IACC,kBAAC3Y,GAAD;MAAc,OAAM;MAAS,MAAK;MAAkB,UAAA;MAClD,UAAA,kBAACoZ,GAAD;OACE,WAAW;OACX,WAAA;OACA,WAAW,MACTnE,GACEpN,GAAQ,OAAO,YAAY,YAAY,QACzC;OAEF,SAAS,CAAC,GAAGoK,EAA2B;OACxC,OAAO6G;MACR,CAAA;KACW,CAAA,IACZ;KACHH,KAAqB3D,OAAoB,YACxC,kBAAChV,GAAD;MAAc,OAAM;MAAc,MAAK;MAAkB,UAAA;MACvD,UAAA,kBAACqZ,GAAD;OACE,WAAA;OACA,WAAW,MACTlE,EAAmB8D,EAAM,OAAO,KAAK;OAEvC,aAAY;OACZ,OAAO/D;MACR,CAAA;KACW,CAAA,IAEd,kBAAClV,GAAD;MACE,OAAO2Y,IAAoB,SAAS;MACpC,MAAK;MACL,UAAA;MAEA,UAAA,kBAACO,IAAD;OACE,WAAA;OACA,uBAAA;OACA,WAAU;OACV,YAAY;QACV,gBAAgB;QAChB,aAAa;QACb,MAAM;QACN,YAAY;OACd;OACA,SAAS9E;OACT,aAAY;OACZ,eAAe;OACf,MAAK;OACL,WAAW,MACTD,GACE7L,EACG,IAAIR,EAAyB,CAAC,CAC9B,OAAOF,EAAqB,CACjC;OAEF,UAAUkQ;OACV,qBAAqB,MAAe;QAClC,AAAIqB,KACFrB,EAA8B,EAAE;OAEpC;OACA,SAAS,CAAC,GAAGxD,EAAkB;OAC/B,kBAAiB;OACjB,aAAY;OACZ,oBAAoB;OACpB,OAAO,CAAC,GAAGJ,CAAY;MACxB,CAAA;KACW,CAAA;KAEfQ,MAAc,iBACb,kBAAC1U,GAAD;MAAc,OAAM;MAAS,MAAK;MAAgB,UAAA;MAChD,UAAA,kBAACoZ,GAAD;OACE,WAAW;OACX,WAAA;OACA,WAAW,MACTvE,GACEhN,GAAQ,OAAO,qBACX,qBACA,iBACN;OAEF,SAAS,CAAC,GAAGmK,EAAuB;OACpC,OAAO6G;MACR,CAAA;KACW,CAAA,IACZ;KACFF,IAcE,OAbF,kBAAC3Y,GAAD;MAAc,OAAM;MAAK,MAAK;MAC5B,UAAA,kBAACgZ,IAAD;OACE,WAAW,MACT/E,GAAgBgF,EAAM,OAAO,KAAK;OAEpC,aAAY;OACZ,KAAKrH;OACL,QAAO;OACP,MAAM;OACN,OAAOJ;OACP,OAAOwC;MACR,CAAA;KACW,CAAA;IAEb;;EACA,CAAA;CACP,EAAA,CAAA;AAEN,CAAC;AAED,SAASqC,GACP,GACA,GACQ;CACR,IAAI;EACF,IAAMvR,IAAQ,KAAK,MAAMuK,EAAU,eAAe;EAOlD,IAAIvK,EAAM,WAAW,QACnB,OAAOA,EAAM,UACV,KACE,MAAa4B,EAAsBrC,GAAUD,CAAkB,CAClE,CAAC,CACA,KAAK,GAAG;EAGb,IAAIU,EAAM,YACR,OAAOA,EAAM;EAGf,IAAIA,EAAM,YACR,OAAO,MAAMA,EAAM;EAGrB,IAAIA,EAAM,WACR,OAAO,MAAMA,EAAM;CAEvB,QAAQ,CAER;CAEA,OAAOuK,EAAU;AACnB;;;AC7tCA,IAAM3P,KAAoC;CACxC,SAAS;CACT,KAAK;AACP;AAcA,SAAgB6Z,GAA0B,EACxC,0BACA,iBAC+C;CAC/C,IAAMC,IAAgBrX,QAElBsX,EAAW,KAAK,OAAe;EAC7B,WAAWpO,EAAU;EACrB,WAAWzF,GAAcyF,EAAU,iBAAiB;EACpD,KAAKA,EAAU;EACf,YAAYA,EAAU;EACtB,eAAepB,EAAeoB,EAAU,QAAQ;EAChD,gBAAgBA,EAAU;CAC5B,EAAE,GACJ,CAACoO,CAAU,CACb,GAEMC,IAAmBvX,QACY;EACjC;GACE,WAAW;GACX,KAAK;GACL,OAAO;GACP,OAAO;EACT;EACA;GAAE,WAAW;GAAa,KAAK;GAAa,OAAO;GAAO,OAAO;EAAI;EACrE;GACE,WAAW;GACX,KAAK;GACL,OAAO;GACP,OAAO;EACT;EACA;GACE,WAAW;GACX,KAAK;GACL,OAAO;GACP,OAAO;EACT;EACA;GACE,WAAW;GACX,KAAK;GACL,OAAO;GACP,OAAO;EACT;CACF,GACA,CAAC,CACH;CAEA,OACE,kBAAC,OAAD;EAAK,OAAOzC;EAAZ,UAAA;GACE,kBAACwD,GAAD;IAAY,WAAU;IAAK,SAAQ;IAAK,UAAA;GAE5B,CAAA;GACZ,kBAACA,GAAD;IACE,OACEqI,GAAuB,QAAQ,iBAAiB;IAElD,SAAQ;IAEP,UAAAA,IACGA,EAAsB,QACpB,YAAYA,EAAsB,aAAa,OAC/C,WAAWA,EAAsB,OAAO,KAAK,GAAG,MAClD;GACM,CAAA;GACXiO,EAAc,SAAS,IACtB,kBAAClI,IAAD;IACE,SAASoI;IACT,YAAYF;IACZ,WAAA;GACD,CAAA,IACC;EACD;;AAET;;;ACnEA,IAAM7Z,KAAoC;CACxC,SAAS;CACT,KAAK;AACP,GAEMia,KAA2C;CAC/C,QAAQ;CACR,gBAAgB;CAChB,qBAAqB;AACvB,GAWMC,KAAuC;CAC3C,iBAAiB;CACjB,iBAAiB;CACjB,iBAAiB;CACjB,UAAU;CACV,YAAY;CACZ,WAAW;CACX,aAAa;CACb,YAAY;AACd,GAEMC,KAA6C,EACjD,OAAO,kCACT,GAKMC,KAA8C;CAClD,GAAGF;CACH,iBAAiB;CACjB,OAAO;AACT;AAEA,SAASG,GACP,GAAGC,GACK;CACR,OAAOA,EACJ,QAAQ,MACP7U,EAAc8U,KAAa,IAAI,CACjC,CAAC,CACA,KAAK,GAAG;AACb;AAOA,IAAMC,KAAsBhI,EAG1B,SACA,EACE,cACA,qBACA,UACA,kBAAe,IACf,WAAQ,GACR,gBACA,YAAS,WACT,UACA,UAAO,UACP,GAAGiI,KAEL,GACc;CACd,IAAMC,IAAgBC,IAAe,YAAYrU,GAC3CsU,IAAyBC,EAAiB,QAC7C,MACC3R,EAAK,SAAS,SAClB,GACM4R,IAA0BD,EAAiB,QAC9C,MACC3R,EAAK,SAAS,SAClB;CAEA,OACE,kBAAC,OAAD;EACE,GAAIuR;EACJ,WAAWJ,GACTU,EAAY,MACZrU,MAAS,QAAQqU,EAAY,MAAM,MACnCjV,KAAS4U,MAAkB,eAAeK,EAAY,QAAQ,MAC9DC,MAAgB,eAAeD,EAAY,aAAa,MACxDrU,MAAS,WAAWqU,EAAY,SAAS,MACzCL,MAAkB,YAAYK,EAAY,UAAU,MACpDL,MAAkB,eAAeK,EAAY,aAAa,MAC1DjV,KAAS4U,MAAkB,eACvBK,EAAY,kBACZ,MACJ,CAACjV,KAAS4U,MAAkB,cAAcK,EAAY,YAAY,MAClEC,MAAgB,aAAaD,EAAY,WAAW,MACpDR,CACF;EACK;EAjBP,UAAA,CAmBG7T,MAAS,QACR,kBAAC,QAAD,EACE,WAAW2T,GACTU,EAAY,iBACZA,EAAY,kBACd,EACD,CAAA,IAED,kBAAC,QAAD;GAAM,WAAWA,EAAY;GAAkB,UAAAvO,IAAQ;EAAQ,CAAA,GAEjE,kBAAC,OAAD;GAAK,WAAWuO,EAAY;GAA5B,UAAA;IACE,kBAACxX,GAAD;KACE,WAAWwX,EAAY;KACvB,SAAQ;KAFV,UAAA,CAIGE,GACD,kBAAC,QAAD,EAAM,WAAWF,EAAY,iBAAmB,CAAA,CACtC;;IACXH,EAAuB,SAAS,IAC/B,kBAACrX,GAAD;KAAY,WAAWwX,EAAY;KAAa,SAAQ;KACrD,UAAAH,EAAuB,KAAK,GAAM,MACjC,kBAACM,GAAD,EAAA,UAAA,CACGC,IAAY,IAAI,QAAQ,MACxBC,GAA8BlS,CAAI,CAC3B,EAAA,GAHK,GAAGA,EAAK,KAAK,GAAGiS,GAGrB,CACX;IACS,CAAA,IACV;IACHL,EAAwB,KAAK,GAAM,MAClC,kBAACvX,GAAD;KAEE,OACE2F,EAAK,SAAS,WACVkR,KACAF;KAEN,SAAQ;KAPV,UAAA,CASE,kBAAC,QAAD;MACE,OACEhR,EAAK,SAAS,WAAW,KAAA,IAAYiR;MAFzC,UAAA,CAKGjR,EAAK,OAAM,GACR;KACL,CAAA,GAAAA,EAAK,IACI;IAhBL,GAAA,WAAWiS,GAgBN,CACb;GACE;EACF,CAAA,CAAA;;AAET,CAAC;AAID,SAASC,GACP,GACuB;CASvB,OARIlS,EAAK,SAAS,SACTA,EAAK,OAGTA,EAAK,OAAO,KAAK,IAKpB,kBAAAjJ,GAAA,EAAA,UAAA;EACGiJ,EAAK;EAAO;EACb,kBAACmS,GAAD;GAAS,OAAOnS,EAAK;GACjB,WAAA,EAAE,QAAK,GAAGoS,QAIV,kBAAC,QAAD;IACE,GAAIA;IACJ,eACEpS,EAAK,WAAW,kBAAkBA,EAAK,aAAa,KAAA;IAEjD;IACL,OAAO+Q;IAEN,UAAA/Q,EAAK;GACF,CAAA;EAED,CAAA;CACT,EAAA,CAAA,IAvBK,GAAGA,EAAK,OAAO,GAAGA,EAAK;AAyBlC;AA4BA,SAAgBqS,GAAuB,EACrC,iBACA,kBACA,uBACA,0BACA,mBACA,0BACA,UACA,qBACA,qBAC4C;CAC5C,IAAMlS,IAA+CkF,GACnDE,GACAxC,GACAuP,GACAC,GACA1P,GACAtH,GACA+G,GACAG,GACAC,CACF,GAEM8P,IAAsBvS,EAAwBE,CAAa,GAE3DsS,IAA2BtS,EAAc,KAAK,OAAU;EAC5D,GAAGmG;EACH,kBAAkBA,EAAK,iBAAiB,OAAOvG,CAAyB;CAC1E,EAAE;CAEF,OACE,kBAAC,OAAD;EAAK,OAAOjJ;EAAZ,UAAA,CACE,kBAACuD,GAAD;GAAY,WAAU;GAAK,SAAQ;GAAK,UAAA;EAE5B,CAAA,GACXoY,EAAyB,SAAS,IACjC,kBAACC,IAAD;GACE,aAAaF;GACb,aAAY;GACZ,MAAK;GAEJ,UAAAC,EAAyB,KAAK,MAC7B,kBAACnB,IAAD;IACE,kBAAkBlR,EAAa;IAC/B,OAAOA,EAAa;IACpB,cAAcA,EAAa;IAE3B,OAAOA,EAAa;GACrB,GAFMA,EAAa,EAEnB,CACF;EACM,CAAA,IAET,kBAAC/F,GAAD;GAAY,OAAM;GAAe,SAAQ;GAAO,UAAA;EAEpC,CAAA,CAEX;;AAET;;;ACjTA,IAAMrD,KAAoC;CACxC,SAAS;CACT,KAAK;AACP,GAEM4b,KAAkC;CACtC,SAAS;CACT,KAAK;AACP,GAEMC,KAAoC;CACxC,cAAc;CACd,YAAY;AACd;AA2BA,SAAgBC,GAAiC,EAC/C,eACA,YACA,oBACsD;CACtD,IAAM,CAACC,GAAYC,KACjBxa,EAA+C,IAAI,GAC/C,CAACya,GAAUC,KAAe1a,EAAS,EAAK,GACxC,CAACoE,GAAO4M,KAAYhR,EAAwB,IAAI,GAEhD2a,IAAO7Z,QAET8Z,EAAW,KAAK,OAAc;EAAE;EAAU,KAAKC,EAAS;CAAG,EAAE,GAC/D,CAACD,CAAU,CACb,GAEME,IAAUha,QAC2B;EACvC;GACE,KAAK;GACL,SAAS,EAAE,kBACT,kBAAC,OAAD;IAAK,OAAOsZ;IAAZ,UAAA,CACE,kBAACvY,GAAD;KAAY,WAAU;KAAO,SAAQ;KAClC,UAAAgZ,EAAS,iBAAiBA,EAAS;IAC1B,CAAA,GACZ,kBAAChZ,GAAD;KAAY,OAAM;KAAe,WAAU;KAAO,SAAQ;KAA1D,UAAA;MACGgZ,EAAS;MAAY;MAAEA,EAAS;MAAgB;MAAG;MACnDE,EAAcF,EAAS,MAAM;KACpB;IACT,CAAA,CAAA;;GAEP,OAAO;GACP,OAAO;EACT;EACA;GACE,KAAK;GACL,SAAS,EAAE,kBACT,kBAACG,IAAD,EAA4B,QAAQH,EAAS,OAAS,CAAA;GAExD,OAAO;GACP,OAAO;EACT;EACA;GACE,KAAK;GACL,SAAS,EAAE,kBACT,kBAAChZ,GAAD;IAAY,WAAU;IAAO,SAAQ;IAClC,UAAAgZ,EAAS;GACA,CAAA;GAEd,OAAO;GACP,OAAO;EACT;EACA;GACE,KAAK;GACL,SAAS,EAAE,kBACTA,EAAS,iBAAiBA,EAAS,WAAW,SAC5C,kBAAC,OAAD;IAAK,OAAOT;IAAZ,UAAA,CACE,kBAACvY,GAAD;KAAY,OAAM;KAAa,WAAU;KAAO,SAAQ;KACrD,UAAAgZ,EAAS;IACA,CAAA,GACXA,EAAS,kBACR,kBAAChZ,GAAD;KACE,OAAM;KACN,WAAU;KACV,OAAOwY;KACP,SAAQ;KAEP,UAAAQ,EAAS;IACA,CAAA,IACV,IACD;GAEL,CAAA,IAAA,kBAAChZ,GAAD;IAAY,OAAM;IAAe,WAAU;IAAO,SAAQ;IAAO,UAAA;GAErD,CAAA;GAEhB,OAAO;GACP,OAAO;EACT;EACA;GACE,KAAK;GACL,SAAS,EAAE,kBACT,kBAACA,GAAD;IAAY,WAAU;IAAO,SAAQ;IAClC,UAAAoZ,GAAsBJ,CAAQ;GACrB,CAAA;GAEd,OAAO;GACP,OAAO;EACT;CACF,GACA,CAACE,CAAa,CAChB,GAEMG,IAAUpa,SAC2B;EACvC,SAAS,EACP,kBAIA+Z,EAAS,WAAW,YAAYA,EAAS,eAAe,IACpD,CACE;GACE,gBAAyBJ;GACzB,MAAMU;GACN,UAAU;GACV,MAAM;GACN,eAAqB;IAEnB,AADAnK,EAAS,IAAI,GACbwJ,EAAcK,CAAQ;GACxB;EACF,CACF,IACA,CAAC;EACP,SAAS;EACT,OAAO;CACT,IACA,CAACJ,CAAQ,CACX;CAEA,eAAeW,IAAoC;EACjD,IAAKb,GAIL;GACA,AADAG,EAAY,EAAI,GAChB1J,EAAS,IAAI;GAEb,IAAI;IAEF,AADA,MAAMqK,EAAQd,CAAU,GACxBC,EAAc,IAAI;GACpB,SAASc,GAAqB;IAE5B,AADAd,EAAc,IAAI,GAClBxJ,EACEsK,aAAsB,SAASA,EAAW,UACtCA,EAAW,UACX,eACN;GACF,UAAU;IACR,EAAY,EAAK;GACnB;EAfgB;CAgBlB;CAEA,OACE,kBAAC,OAAD;EAAK,OAAO9c;EAAZ,UAAA;GACE,kBAACqD,GAAD;IAAY,WAAU;IAAK,SAAQ;IAAK,UAAA;GAE5B,CAAA;GACXuC,IACC,kBAACvC,GAAD;IAAY,OAAM;IAAa,SAAQ;IACpC,UAAAuC;GACS,CAAA,IACV;GACHuW,EAAK,SAAS,IACb,kBAAC1K,IAAD;IACW;IACA;IACT,YAAY0K;IACZ,WAAA;GACD,CAAA,IAED,kBAAC9Y,GAAD;IAAY,OAAM;IAAe,SAAQ;IAAO,UAAA;GAEpC,CAAA;GAEd,kBAAC6V,GAAD;IACE,YAAW;IACX,aAAY;IACZ,SAAS+C;IACT,iBAAgB;IAChB,WAAU;IACV,gBAAsBD,EAAc,IAAI;IACxC,eAAqBA,EAAc,IAAI;IACvC,iBAAuB,KAAKY,EAAmB;IAC/C,MAAM,EAAQb;IACd,iBAAA;IACA,iBAAA;IACA,gBAAe;IACf,OAAM;IAEN,UAAA,kBAAC1Y,GAAD;KAAY,SAAQ;KAApB,UAAA;MAA2B;MAExB0Y,GAAY,iBAAiBA,GAAY,eAAe;MAAG;KAClD;;GACP,CAAA;EACJ;;AAET;AAEA,SAASS,GAA2B,EAClC,aAGe;CASf,OARIpW,MAAW,SACN,kBAAC2W,GAAD;EAAO,MAAK;EAAM,MAAK;EAAM,SAAQ;CAAe,CAAA,IAGzD3W,MAAW,WACN,kBAAC2W,GAAD;EAAO,MAAK;EAAM,MAAK;EAAK,SAAQ;CAAa,CAAA,IAIxD,kBAACA,GAAD;EACE,MAAK;EACL,MAAM3W,MAAW,YAAY,SAAS;EACtC,SAAQ;CACT,CAAA;AAEL;AAEA,SAASqW,GACP,GACQ;CASR,OARIJ,EAAS,SACJ,MAAMjS,EAAeiS,EAAS,MAAM,MAGzCA,EAAS,WAAW,aAAaA,EAAS,cACrC,QAAQjS,EAAeiS,EAAS,WAAW,MAG7CA,EAAS,gBACZ,QAAQjS,EAAeiS,EAAS,aAAa,MAC7C,MAAMjS,EAAeiS,EAAS,SAAS;AAC7C;;;ACrKA,IAAMW,KAAoC,KACpCC,KAA8B,IAE9BC,KAAyB,KACzBC,KAA0B,IAE1BC,KAAuC;CAC3C,SAAS;CACT,KAAK;AACP,GAEMC,KAAmC;CACvC,YAAY;CACZ,QAAQ;CACR,cAAc;CACd,QAAQ;CACR,WAAW;CACX,UAAU;CACV,OAAO;AACT,GAEMC,KAA4B;CAChC,YAAY;CACZ,QAAQ;CACR,cAAc;CACd,WAAW;CACX,SAAS;CACT,KAAK;CACL,WAAW;CACX,SAAS;CACT,OAAO;AACT,GAEMC,KAAmC;CACvC,cAAc;CACd,UAAU;CACV,YAAY;CACZ,aAAa;CACb,YAAY;CACZ,SAAS;AACX,GAEMC,KAAsC;CAC1C,OAAO;CACP,UAAU;CACV,UAAU;CACV,cAAc;CACd,YAAY;AACd,GAEMC,KAAmC,EACvC,SAAS,EACX,GAEMC,KAAoC;CACxC,SAAS;CACT,UAAU;CACV,KAAK;AACP,GAEMC,KAAyC;CAC7C,YAAY;CACZ,YAAY;CACZ,QAAQ;CACR,cAAc;CACd,OAAO;CACP,SAAS;CACT,UAAU;CACV,YAAY;CACZ,KAAK;CACL,YAAY;CACZ,SAAS;AACX,GAEMC,KAAoC;CACxC,SAAS;CACT,KAAK;AACP,GAEMC,KAA2B,EAC/B,iBAAiBC,GACnB;AAiDA,SAAgBC,GAAmB,EACjC,eACA,qBAAkB,IAClB,cAAW,IACX,iBAAc,IACd,oBAAiB,IACjB,eAAY,IACZ,4BAAwB,MACgB;CACxC,IAAM,EAAE,cAAW7d,EAAQ,GACrByV,IAAkB0C,GAAQ,YAAY,MACtC2F,IACJC,MAAyB7d,EAAiBiY,CAAM,GAC5C,CAAC9J,IAAc2P,MAAmB1c,EAEtC,CAAC,CAAC,GACE,CAAC6N,GAAU8O,MAAe3c,EAAwC,IAAI,GACtE,CAACuO,IAAeqO,MAAoB5c,EAExC,CAAC,CAAC,GACE,CAAC2P,IAAakN,MAAkB7c,EACpC,CAAC,CACH,GACM,CAACoY,IAAY0E,MAAiB9c,EAAqC,CAAC,CAAC,GACrE,CAAC+c,IAAmBC,MAAwBhd,EAEhD,CAAC,CAAC,GACE,CAACkK,IAAuB+S,MAC5Bjd,EAA6C,IAAI,GAC7C,CAACuK,GAAO2S,MAAYld,EAAgC,CAAC,CAAC,GACtD,CAAC8Z,GAAgBqD,MAAqBnd,EAE1C,CAAC,CAAC,GACE,CAACod,IAAgBC,MAAqBrd,EAE1C,CAAC,CAAC,GACE,CAACoE,IAAO4M,KAAYhR,EAAwB,IAAI,GAChD,CAAC+O,IAASuO,MAActd,EAAS,EAAI,GACrC,CAACqP,IAAU0B,KAAe/Q,EAAS,EAAK,GACxC,CAACud,GAAmBC,MAAwBxd,EAAS,EAAK,GAC1D,CAACyd,IAAeC,KAAoB1d,EAAS,EAAE,GAC/C,CAAC2d,GAAiBC,KAAsB5d,EAAS,EAAK,GACtD,CAACiP,IAAoB4O,KAAyB7d,EAElD,CAAC,CAAC,GACE,CAACoP,GAAkB0O,MAAuB9d,EAC9C,CAAC,CACH,GACM,CAAC+d,IAA0BC,MAA+Bhe,EAI9D,CAAC,CAAC,GACE,CAACie,GAAmBC,MACxBle,EAAkC,IAAI,GAClC,CAACme,IAAYC,MAAiBpe,EAAwB,IAAI,GAC1D,CAAC+N,IAAiBsQ,MAAsBre,EAE5C,CAAC,CAAC,GAEEse,KAAuBb,GAAc,KAAK,GAG1Cc,IAAkB1e,EAAmC,IAAI,GACzD2e,KAA8B3e,EAAO,CAAC,GACtC4e,IAA6B1B,GAAkB,MAClD,MACClC,EAAS,WAAW,aACpBA,EAAS,WAAW,sBACxB;CAuBA,AArBAta,QAAsB;EACpB,EAAqB;CACvB,GAAG,CAAC4T,GAAiBuK,CAAU,CAAC,GAEhCne,QAA0C;EACxC,IACE,CAACic,KACD,CAACiC,KACDD,GAA4B,WAAW/C,IAEvC;EAGF,IAAMkD,IAAQ,iBAAuB;GAEnC,AADA,GAA4B,WAAW,GACvCC,GAA2B;EAC7B,GAAGpD,EAAiC;EAEpC,aAAmB,aAAamD,CAAK;CACvC,GAAG;EAACnC;EAA0BiC;EAA4B1B;CAAiB,CAAC,GAE5Exc,QAAsB;EAEpB,AADAud,GAAoBjQ,GAAU,YAAY,CAAC,CAAC,GAC5CmQ,GAA4B,CAAC,CAAC;CAChC,GAAG,CAACnQ,CAAQ,CAAC;CAEb,IAAMgR,IAAsC5d,GAExC,GACA,MAIS;EACT,IAA6B,MAAkB;GAC7C,IAAM6d,IAAeC,EAAcC;GASnC,OANEF,GAAc,aAAapa,EAAM,YACjCoa,EAAa,WAAWpa,EAAM,SAEvBqa,IAGF;IACL,GAAGA;KACFC,IAAW;KACV,UAAUta,EAAM;KAChB,QAAQA,EAAM;IAChB;GACF;EACF,CAAC;CACH,GACA,CAAC,CACH,GAIMwP,IAAcpT,QAEhByJ,EAAM,MACH,MACC5E,GAAmB1B,GAAMkQ,CAAe,MACvClQ,EAAK,WAAW,aAAaA,EAAK,WAAW,cAClD,KAAK,MACP,CAACkQ,GAAiB5J,CAAK,CACzB,GACM6J,IAAkBtT,QAEpBoT,KAAerG,IACVA,EAAS,iBAAiB,MAAM,MAC9B,MAAS1I,EAAK,OAAO+O,EAAY,MACpC,KAAK,OACL,MACN,CAACA,GAAarG,CAAQ,CACxB,GACMyG,KACJF,GAAiB,SAAS,cAC1BA,EAAgB,KAAK,eAAe,aAChCG,KACJH,GAAiB,SAAS,cAC1BA,EAAgB,KAAK,gBAAgB,IACjCI,KACJJ,GAAiB,SAAS,cAC1BA,EAAgB,KAAK,kBAAkB,IACnCM,KACJN,GAAiB,SAAS,cAC1BA,EAAgB,KAAK,gBACjB6K,KAAoB,EACxB,MACEpR,EAAS,sBAAsBsG,KAC9BtG,EAAS,UAAU,aAAaA,EAAS,UAAU,aAElDmB,IAAsB,GAC1BnB,KACEA,EAAS,sBAAsBsG,KAC/BtG,EAAS,UAAU,aAEjB9K,IAAqBjC,QAEvB,IAAI,IAAIsc,GAAe,KAAK,MAAY,CAAC9X,EAAQ,UAAUA,CAAO,CAAC,CAAC,GACtE,CAAC8X,EAAc,CACjB,GACMtT,KAAwBhJ,QAE1BwN,GAAgCC,EAAa,GAC/C,CAACA,EAAa,CAChB,GACMtE,IAAiBnJ,QAEnB,IAAI,IAAIsX,GAAW,KAAK,MAAc,CAACpO,EAAU,IAAIA,CAAS,CAAC,CAAC,GAClE,CAACoO,EAAU,CACb,GACM8G,IAA2Bpe,QAE7B+M,IACIsR,GAAgCtR,EAAS,gBAAgB,IACzD,MACN,CAACA,CAAQ,CACX,GACMuR,KAAYte,QAEd+M,KAAYqR,IACRG,GACEH,GACA3U,GACAuP,GACAjM,EAAS,KACX,IACA,CAAC,GACP;EAACA;EAAUqR;EAA0B3U;EAAOuP;CAAc,CAC5D,GACMwF,KAAYxe,QAEdoe,IACIK,GAAqBL,CAAwB,IAC7C,CAAC,GACP,CAACA,CAAwB,CAC3B,GACMM,KAAgB1e,QAElB+M,IAAW4R,GAAkB5R,EAAS,gBAAgB,IAAI,CAAC,GAC7D,CAACA,CAAQ,CACX;CAEA,eAAe6R,IAAiC;EAE9C,AADApC,GAAW,EAAI,GACftM,EAAS,IAAI;EAEb,IAAI;GACF,IAAM2O,IAAa,MAAMC,GAAqBlB,CAAU;GAIxD,AAHAhC,GAAgBiD,EAAW,YAAY,GACvChD,GAAYgD,EAAW,QAAQ,GAC/BzC,GAASyC,EAAW,KAAK,GACzBxC,GAAkBwC,EAAW,cAAc;GAC3C,IAAME,IAAsB,MAAMC,GAChCH,EAAW,SAAS,EACtB,GACM,CACJI,GACAC,GACAC,GACAC,GACAC,KACE,MAAM,QAAQ,IAAI;IACpB/R,GAA0BuR,EAAW,KAAK;IAC1C/R,GAA8B;KAC5B,GAAG+R;KACH,iBAAiBE;IACnB,CAAC;IACDO,GAAgBT,EAAW,SAAS,EAAE;IACtCU,GAAuBV,EAAW,SAAS,EAAE;IAC7CW,EAAsBX,EAAW,SAAS,EAAE;GAC9C,CAAC;GAOD,AANA/C,GAAiBmD,CAAiB,GAClC1C,GAAkB2C,CAAkB,GACpCnD,GAAeoD,CAAe,GAC9BnD,GAAcoD,EAAe,UAAU,GACvCjD,GAAyBiD,EAAe,YAAY,GACpD7B,GAAmBwB,CAAmB,GACtC7C,GAAqBmD,CAAqB;EAC5C,SAAS9K,GAAuB;GAC9B,EAASnR,EAAiBmR,CAAY,CAAC;EACzC,UAAU;GACR,GAAW,EAAK;EAClB;CACF;CAEA,eAAeiL,EACb,GACmD;EAOnD,OANK9D,IAME+D,GAA8BC,CAAgB,CAAC,CAAC,YACL,CAAC,CACnD,IAPS,CAAC;CAQZ;CAEA,eAAeC,GACb,GACe;EAGf,AAFA,MAAMC,GAA6B7F,EAAS,EAAE,GAC9C,GAA4B,UAAU,GACtC,MAAM6E,EAAgB;CACxB;CAMA,eAAed,KAAuC;EACpD,IAAM+B,IAAO,MAAML,EAAsB5B,CAAU;EAOnD,AANiBiC,EAAK,MACnB,MACC9F,EAAS,WAAW,aACpBA,EAAS,WAAW,sBACxB,IAOAmC,GAAqB2D,CAAI,IAJvB,MAAMjB,EAAgB;CAK1B;CAEA,eAAekB,EACb,GACA,GACkC;EAClC,IAAI,CAACzM,GACH,MAAU,MAAM,aAAa;EAQ/B,OAAO,EAAE,KAAI,MALY0M,GAAiB;GACxC;GACA,eAAe,QAAQC,EAAM;EAC/B,CAAC,EAAA,CAEuB,GAAG;CAC7B;CAEA,eAAeC,GACb,GACe;EACf,IAAI,CAAC5M,GACH;EAGF,IAAM6M,IAAM,MAAMC,GAA0B,EAC1C,IAAIrR,EAAW,GACjB,CAAC;EAED,OAAO,KAAKoR,GAAK,UAAU,qBAAqB;CAClD;CAEA,eAAeE,GACb,GACe;EACf,IAAI,CAAC/M,GACH;EAGF,IAAM6M,IAAM,MAAMG,GAAyB,EACzC,IAAIvR,EAAW,GACjB,CAAC;EAGD,AADAsO,GAAqBtO,CAAU,GAC/BwO,GAAc4C,CAAG;CACnB;CAEA,eAAeI,KAAsC;EACnD,IAAKjN,KAAoBtG,KAAaoR,IAItC;GAEA,AAFAlO,EAAY,EAAI,GAChBC,EAAS,IAAI,GACb6M,EAAsB,CAAC,CAAC;GAKxB,IAAI;IAQF,AAPA,MAAMwD,GAAuB;KAC3B,qBAAqBlN;KACrB,SAASmK,MAAwB;KACjC,YAAYzQ,EAAS;IACvB,CAAC,GACD6P,EAAiB,EAAE,GACnBE,EAAmB,EAAK,GACxB,MAAM8B,EAAgB;GACxB,SAASrK,GAAuB;IAC9B,EAASnR,EAAiBmR,CAAY,CAAC;GACzC,UAAU;IACR,EAAY,EAAK;GACnB;EApBgB;CAqBlB;CAEA,eAAeiM,KAAwC;EACrD,IAAI,CAACnN,KAAmB,CAACtG,KAAY,CAACmB,GACpC;EAKF,AAFA+B,EAAY,EAAI,GAChBC,EAAS,IAAI,GACb6M,EAAsB,CAAC,CAAC;EAExB,IAAM0D,IAAyBC,EAC7B,OAAO,OAAOzD,EAAwB,CACxC;EAEA,IAAIwD,GAAwB;GAE1B,AADAvQ,EAASuQ,CAAsB,GAC/BxQ,EAAY,EAAK;GAEjB;EACF;EAKA,IAAM0Q,IAAoB5T,EAAS,uBAAuB,SACtD6T,GACE7T,EAAS,uBAAuB,OAAO,QACvCuB,CACF,IACAA;EAIJ,IACEvB,EAAS,uBAAuB,UAChCA,EAAS,uBAAuB,UAChC;GACA,IAAM8T,IAAaC,EAA2B;IAC5C,QAAQ/T,EAAS,uBAAuB;IACxC,UAAUA,EAAS,uBAAuB;IAC1C,QAAQ4T;GACV,CAAC;GAED,IAAI,CAACE,EAAW,OAAO;IAQrB,AAPA9D,EAAsB8D,EAAW,MAAM,GACvC3Q,EAAS,WAAW,GAEhB2Q,EAAW,wBACbE,GAAuBF,EAAW,oBAAoB,GAGxD5Q,EAAY,EAAK;IAEjB;GACF;EACF;EAEA,IAAI;GAOF,AANA,MAAM+Q,GAAyB;IAC7B,UAAUL;IACV,mBAAmBtN;IACnB,YAAYtG,EAAS;IACrB,OAAOA,EAAS;GAClB,CAAC,GACD,MAAM6R,EAAgB;EACxB,SAASrK,GAAuB;GAC9B,EAASnR,EAAiBmR,CAAY,CAAC;EACzC,UAAU;GACR,EAAY,EAAK;EACnB;CACF;CAIA,IAAM0M,KAAsBxD,EAAgB,SAAS,YAAY,IAC3DyD,IAAmB3S,MAAY0S;CAErC,OACE,kBAAAtjB,GAAA,EAAA,UAAA;EACE,kBAACwjB,IAAD,EAAA,UACE,kBAAChjB,IAAD;GACE,aACE4O,IACI;IACEpJ,GAAuBoJ,EAAS,KAAK;IACrCjF,EAAeiF,EAAS,SAAS;IACjClL,GAA2BkL,GAAU9K,CAAkB;GACzD,CAAC,CACE,OAAOgB,CAAa,CAAC,CACrB,KAAK,KAAK,IACb;GAEN,OAAO8J,GAAU,SAAS;GAZ5B,UAAA;IAcGA,IACC,kBAACnM,GAAD;KACE,cAAW;KACX,MAAMwgB;KACN,UAAS;KACT,eAAqB1E,GAAqB,EAAI;KAC9C,OAAM;KACN,SAAQ;KACT,UAAA;IAEO,CAAA,IACN;IACHyB,KACC,kBAACvd,GAAD;KACE,UAAUsgB;KACV,MAAMG;KACN,UAAS;KACT,eAAqBvE,EAAmB,EAAI;KAC5C,SAAQ;KACT,UAAA;IAEO,CAAA,IACN;IACH1J,IACC,kBAAAzV,GAAA,EAAA,UAAA;KAIGiW,KACC,kBAAAjW,GAAA,EAAA,UAAA,CACE,kBAACiD,GAAD;MACE,UAAUsgB;MACV,MAAMI;MACN,UAAS;MAET,eACE7D,EAAgB,SAAS,eAAe,aAAa;MAEvD,SAAQ;MACT,UAAA;KAEO,GAPF,mBAOE,GACR,kBAAC7c,GAAD;MACE,UAAUsgB;MACV,MAAMI;MACN,UAAS;MAET,eACE7D,EAAgB,SAAS,eAAe,cAAc;MAExD,SAAQ;MACT,UAAA;KAEO,GAPF,oBAOE,CACR,EAAA,CAAA,IACA;KACJ,kBAAC7c,GAAD;MACE,UAAUsgB;MACV,MAAMK;MACN,UAAS;MAET,eACE9D,EAAgB,SAAS,eAAe,cAAc;MAExD,SAAQ;MACT,UAAA;KAEO,GAPF,cAOE;KACPjK,KACC,kBAAC5S,GAAD;MACE,UAAUsgB;MACV,MAAM1S;MACN,UAAS;MAET,eAAqBiP,EAAgB,SAAS,gBAAgB;MAC9D,SAAQ;MACT,UAAA;KAEO,GALF,aAKE,IACN;KACH/J,KACC,kBAAC9S,GAAD;MACE,UAAUsgB;MACV,MAAMM;MACN,UAAS;MAET,eACE/D,EAAgB,SAAS,kBAAkB;MAE7C,SAAQ;MACT,UAAA;KAEO,GAPF,eAOE,IACN;KACHhK,KACC,kBAAC7S,GAAD;MACE,UAAUsgB;MACV,MAAMG;MACN,UAAS;MAET,eAAqB5D,EAAgB,SAAS,gBAAgB;MAC9D,SAAQ;MACT,UAAA;KAEO,GALF,aAKE,IACN;KACJ,kBAAC7c,GAAD;MACE,UAAUsgB;MACV,MAAMO;MACN,UAAS;MAET,eAAqBhE,EAAgB,SAAS,cAAc;MAC5D,SAAQ;MACT,UAAA;KAEO,GALF,cAKE;IACR,EAAA,CAAA,IACA;GACS;EACL,CAAA,EAAA,CAAA;EAEZ,kBAACiE,IAAD,EAAA,UAAA;GACGC,IACC,kBAACC,GAAD,EAAA,UACE,kBAAC5T,IAAD;IACuB;IACX;IACH;IACG;IACD;IACT,yBAAyB+P;IACzB,uBAAuB,MAAiB;KAEtC,AADAf,GAAoB5O,CAAM,GAC1B2O,EAAsB,CAAC,CAAC;IAC1B;IACA,0BAAgC,KAAKyD,GAAuB;IAC5D,oBAAoBV;IACF;IACE;GACrB,CAAA,EACM,CAAA,IACP;GAEH+B,IACC,kBAACD,GAAD,EAAA,UACE,kBAACjT,IAAD;IACe;IACb,aAAa,MAAqB;KAChC,GAA8BG,CAAU;IAC1C;IACA,YAAY,MAAqB;KAC/B,GAA6BA,CAAU;IACzC;GACD,CAAA,EACM,CAAA,IACP;GAEHgT,IACC,kBAACF,GAAD,EAAA,UACE,kBAAC7R,IAAD;IACmB;IACA;IACP;IACU;IACpB,WAAW6O;IACX,KAAKnB;IACE;GACR,CAAA,EACM,CAAA,IACP;GAEHsE,IACC,kBAACH,GAAD,EAAA,UACE,kBAACxK,IAAD;IACyB;IACX;GACb,CAAA,EACM,CAAA,IACP;GAEHsE,KAA4BO,GAAkB,SAAS,IACtD,kBAAC2F,GAAD,EAAA,UACE,kBAACpI,IAAD;IACE,YAAYyC;IACZ,SAAS0D;IACT,gBAAgB,MACdxb,GAAqBG,GAAQyI,GAAU,oBAAoB,IAAI;GAElE,CAAA,EACM,CAAA,IACP;GAEHiV,IACC,kBAACJ,GAAD,EAAA,UACE,kBAAC7I,IAAD;IACgB;IACd,eAAehM,GAAU,SAAS;IACd;IACG;IACP;IACO;IAChB;IACP,kBAAkBA,GAAU,oBAAoB;IAChC;GACjB,CAAA,EACM,CAAA,IACP;EACQ,EAAA,CAAA;EAGbA,IACC,kBAAC6J,GAAD;GACE,WAAU;GACV,eAAqB8F,GAAqB,EAAK;GAC/C,MAAMD;GACN,iBAAA;GACA,MAAK;GACL,gBAAgB,GAAG9Y,GACjBoJ,EAAS,KACX,EAAE,KAAKjF,EAAeiF,EAAS,SAAS;GACxC,OAAM;GAEN,UAAA,kBAAC,OAAD;IAAK,OAAO+N;IAAZ,UAAA,CACE,kBAAC,OAAD;KAAK,OAAOC;KACV,UAAA,kBAACkH,IAAD;MACE,OAAOzD;MACP,SAAA;MACA,gBAAgB,EAAE,SAAS,IAAK;MAChC,SAAS;MACT,SAAS;MACT,OAAOF;MACP,gBAAgB;MAChB,gBAAgB;MAChB,WAAW/C;MACX,WAAA;MACA,YAAY,EAAE,iBAAiB,GAAK;MAXtC,UAAA,CAaE,kBAAC2G,IAAD,CAAa,CAAA,GACb,kBAACC,IAAD,EAAU,iBAAiB,GAAQ,CAAA,CAC1B;;IACR,CAAA,GACJzD,GAAc,SAAS,IACtB,kBAAC,OAAD;KAAK,OAAOtD;KACT,UAAAsD,GAAc,KAAK,MAClB,kBAAC,QAAD;MAAoB,OAAOrD;MACxB,UAAA+G;KACG,GAFKA,CAEL,CACP;IACE,CAAA,IACH,IACD;;EACA,CAAA,IACL;EAGJ,kBAACxL,GAAD;GACE,WAAU;GACV,eAAqB;IAEnB,AADAwG,GAAqB,IAAI,GACzBE,GAAc,IAAI;GACpB;GACA,MAAM,GAAQH,KAAqBE;GACnC,iBAAA;GACA,MAAK;GACL,gBAAgBF,GAAmB,YAAY,KAAA;GAC/C,OAAM;GAEL,UAAAE,KACC,kBAACxe,IAAD;IACE,UAAUse,GAAmB,YAAY;IACzC,SAASE;IACT,YACEF,UACgB,KAAK8C,GAAyB9C,CAAiB,IAC3D,KAAA;GAEP,CAAA,IACC;EACC,CAAA;EAGP,kBAACvG,GAAD;GACE,YAAW;GACX,oBAAoB,EAAE,SAAS,sBAAsB;GACrD,aAAY;GACZ,SAASrI;GACT,iBAAgB;GAChB,WAAU;GACV,gBAAsBuO,EAAmB,EAAK;GAC9C,eAAqBA,EAAmB,EAAK;GAC7C,iBAAuB,KAAKwD,GAAqB;GACjD,MAAMzD;GACN,iBAAA;GACA,iBAAA;GACA,gBAAe;GACf,OAAM;GAEN,UAAA,kBAAC,OAAD;IAAK,OAAOvB;IAAZ,UAAA,CACE,kBAACva,GAAD;KAAY,SAAQ;KAApB,UAAA;MAA2B;MAClBgM,GAAU,SAAS;MAAG;KACnB;IACZ,CAAA,GAAA,kBAAClP,GAAD;KAAc,OAAM;KAAO,MAAK;KAC9B,UAAA,kBAACgZ,IAAD;MACE,WAAW,MACT+F,EAAiB9F,EAAM,OAAO,KAAK;MAErC,aAAY;MACZ,QAAO;MACP,MAAM;MACN,OAAO6F;KACR,CAAA;IACW,CAAA,CACX;;EACA,CAAA;CACP,EAAA,CAAA;AAEN;AAMA,SAAS0F,GAAc,GAAmD;CASxE,OARIpd,EAAK,KAAK,QACLA,EAAK,KAAK,QAGfA,EAAK,KAAK,YACL,SAGFA,EAAK,KAAK,aAAa;AAChC;AAEA,SAAS0Z,GAAkB,GAAiD;CAC1E,OAAOva,EAAS,MACb,IAAIie,EAAa,CAAC,CAClB,QAAQ,MAAUC,EAAM,KAAK,CAAC,CAAC,SAAS,CAAC;AAC9C;AAEA,SAASC,GAAkB,GAAoC;CAO7D,OANIre,MAAS,eAAqB,OAC9BA,MAAS,aAAmB,OAC5BA,MAAS,aAAmB,SAC5BA,MAAS,gBAAsB,SAC/BA,MAAS,qBAA2B,SAEjC;AACT;AAEA,SAASqa,GACP,GACA,GACA,GACA,GACmB;CACnB,OAAOna,EAAS,MAAM,KAAK,MAA0B;EACnD,IAAMR,IAAQ4F,GAAqBnF,GAAMoF,GAAOC,GAAQH,CAAa;EAErE,OAAO;GACL,MAAM;IACJ,WAAWgZ,GAAkBle,EAAK,IAAI;IACtC,OAAOA,EAAK,KAAK;IACjB,gBAAgBT,EAAM;IACtB,aAAaA,EAAM;IACnB,MAAMA,EAAM;GACd;GACA,IAAIS,EAAK;GACT,UAAUA,EAAK;GACf,gBAAgBme,EAAS;GACzB,gBAAgBA,EAAS;GACzB,MAAM;EACR;CACF,CAAC;AACH;AAEA,SAASnE,GACP,GACoB;CACpB,IAAMoE,IAAQ,IAAIrkB,GAAM,SAAS,MAAM;CAkBvC,OAjBAqkB,EAAM,2BAA2B,CAAC,EAAE,GACpCA,EAAM,SAAS;EACb,SAAS;EACT,SAAS;EACT,SAAS;CACX,CAAC,GACDre,EAAS,MAAM,SAAS,MAAe;EACrC,EAAM,QAAQC,EAAK,IAAI;GACrB,QAAQwW;GACR,OAAOD;EACT,CAAC;CACH,CAAC,GACDxW,EAAS,MAAM,SAAS,MAAe;EACrC,EAAM,QAAQa,EAAK,QAAQA,EAAK,MAAM;CACxC,CAAC,GACD7G,GAAM,OAAOqkB,CAAK,GAEX;EACL,GAAGre;EACH,OAAOA,EAAS,MAAM,KAAK,MAAuB;GAChD,IAAMse,IAAiBD,EAAM,KAAKpe,EAAK,EAAE;GAIzC,OAAOqe,IACH;IACE,GAAGre;IACH,UAAU;KACR,GAAGqe,EAAe,IAAI9H,KAAyB;KAC/C,GAAG8H,EAAe,IAAI7H,KAA0B;IAClD;GACF,IACAxW;EACN,CAAC;CACH;AACF;AAEA,SAASoa,GAAqB,GAAiD;CAC7E,OAAOra,EAAS,MAAM,KAAK,MAA0B;EACnD,IAAMke,IAAQD,GAAcpd,CAAI;EAEhC,OAAO;GACL,UAAU;GACV,IAAIA,EAAK;GACT;GACA,qBAAqB;GACrB,gBAAgB,CAAC,GAAG,CAAC;GACrB,cAAc;IACZ,MAAMA,EAAK,KAAK,YAAY,YAAY;IACxC,QAAQA,EAAK,KAAK,YAAY,YAAY;IAC1C,aAAa;GACf;GACA,aAAa,EAAQqd;GACrB,YAAY;IACV,MAAMrd,EAAK,KAAK,YAAY,YAAY;IACxC,UAAU;IACV,YAAY;GACd;GACA,QAAQA,EAAK;GACb,OAAO;IACL,QAAQ;IACR,aAAa;GACf;GACA,QAAQA,EAAK;GACb,MAAMA,EAAK,QAAQ;EACrB;CACF,CAAC;AACH;AAEA,SAAS0d,GAAc,GAAkC;CA+BvD,OA9BIC,MAAS,YACJ;EACL,GAAG5H;EACH,QAAQ;EACR,WAAW;CACb,IAGE4H,MAAS,cACJ;EACL,GAAG5H;EACH,QAAQ;CACV,IAGE4H,MAAS,cACJ;EACL,GAAG5H;EACH,QAAQ;EACR,SAAS;CACX,IAGE4H,MAAS,YACJ;EACL,GAAG5H;EACH,QAAQ;CACV,IAGKA;AACT;AAEA,SAAS6H,GAAoB,GAAkC;CAC7D,IAAMC,IAAY7H;CAkBlB,OAhBI2H,MAAS,YACJ;EAAE,GAAGE;EAAW,YAAY;EAAW,OAAO;CAAU,IAG7DF,MAAS,cACJ;EAAE,GAAGE;EAAW,YAAY;EAAW,OAAO;CAAU,IAG7DF,MAAS,cACJ;EAAE,GAAGE;EAAW,YAAY;EAAW,OAAO;CAAU,IAG7DF,MAAS,YACJ;EAAE,GAAGE;EAAW,YAAY;EAAW,OAAO;CAAU,IAG1D;EAAE,GAAGA;EAAW,YAAY;EAAW,OAAO;CAAU;AACjE;AAEA,SAAStH,GAAwB,EAC/B,WAC2C;CAC3C,OACE,kBAAC,OAAD;EAAK,OAAOmH,GAAcI,EAAK,IAAI;EAAnC,UAAA;GACE,kBAACC,IAAD;IACE,eAAe;IACf,UAAUR,EAAS;IACnB,OAAOrH;IACP,MAAK;GACN,CAAA;GACD,kBAACpa,GAAD;IACE,WAAU;IACV,UAAA;IACA,OAAOgiB,EAAK;IACZ,SAAQ;IAEP,UAAAA,EAAK;GACI,CAAA;GACZ,kBAAC,QAAD;IAAM,OAAOF,GAAoBE,EAAK,IAAI;IAAI,UAAAA,EAAK;GAAkB,CAAA;GACrE,kBAAC,QAAD;IAAM,OAAOA,EAAK;IAAgB,OAAO7H;IACtC,UAAA6H,EAAK,kBAAkBA,EAAK;GACzB,CAAA;GACN,kBAACC,IAAD;IACE,eAAe;IACf,UAAUR,EAAS;IACnB,OAAOrH;IACP,MAAK;GACN,CAAA;EACE;;AAET"}