@hotmeshio/long-tail 0.20.0 → 0.21.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +4 -4
- package/build/api/escalations/accumulate.d.ts +96 -0
- package/build/api/escalations/accumulate.js +516 -0
- package/build/api/escalations/index.d.ts +1 -0
- package/build/api/escalations/index.js +10 -1
- package/build/api/roles.d.ts +4 -5
- package/build/api/roles.js +53 -4
- package/build/api/scan-codes/execute.js +2 -0
- package/build/api/scan-codes/verbs.d.ts +15 -0
- package/build/api/scan-codes/verbs.js +65 -0
- package/build/index.js +60 -0
- package/build/lib/db/schemas/036_role_portals.sql +12 -0
- package/build/routes/escalations/accumulate.d.ts +7 -0
- package/build/routes/escalations/accumulate.js +150 -0
- package/build/routes/escalations/index.js +5 -0
- package/build/sdk/index.d.ts +25 -0
- package/build/sdk/index.js +8 -0
- package/build/services/escalation/accumulate.d.ts +81 -0
- package/build/services/escalation/accumulate.js +154 -0
- package/build/services/escalation/index.d.ts +1 -0
- package/build/services/escalation/index.js +1 -0
- package/build/services/mcp/playwright-server/schemas.d.ts +2 -2
- package/build/services/orchestrator/condition.d.ts +40 -3
- package/build/services/orchestrator/condition.js +42 -2
- package/build/services/role/index.js +1 -0
- package/build/services/role/seed.js +6 -1
- package/build/services/role/sql.d.ts +6 -3
- package/build/services/role/sql.js +7 -2
- package/build/services/role/types.d.ts +38 -10
- package/build/services/role/types.js +10 -1
- package/build/services/scan-code/validate.js +16 -0
- package/build/shared/form-validation/display-only-widgets.d.ts +16 -0
- package/build/shared/form-validation/display-only-widgets.js +25 -0
- package/build/shared/form-validation/index.d.ts +2 -0
- package/build/shared/form-validation/index.js +2 -0
- package/build/shared/form-validation/x-lt-bind.d.ts +2 -14
- package/build/shared/form-validation/x-lt-bind.js +12 -8
- package/build/shared/form-validation/x-lt-invoke.d.ts +38 -0
- package/build/shared/form-validation/x-lt-invoke.js +103 -0
- package/build/system/mcp-servers/admin/escalations.js +39 -0
- package/build/system/mcp-servers/admin/schemas.d.ts +192 -13
- package/build/system/mcp-servers/admin/schemas.js +39 -3
- package/build/system/mcp-servers/admin/users.js +1 -0
- package/build/system/mcp-servers/docs.js +4 -0
- package/build/system/mcp-servers/human-queue-schemas.d.ts +85 -0
- package/build/system/mcp-servers/human-queue-schemas.js +19 -1
- package/build/system/mcp-servers/human-queue.d.ts +2 -0
- package/build/system/mcp-servers/human-queue.js +77 -0
- package/build/system/seed/tool-manifests-admin.d.ts +922 -103
- package/build/system/seed/tool-manifests-admin.js +4 -1
- package/build/system/seed/tool-manifests-escalation.d.ts +174 -0
- package/build/system/seed/tool-manifests-escalation.js +56 -0
- package/build/tsconfig.tsbuildinfo +1 -1
- package/build/types/escalation.d.ts +52 -0
- package/build/types/escalation.js +29 -1
- package/build/types/index.d.ts +2 -2
- package/build/types/index.js +3 -1
- package/build/types/scan-code.d.ts +24 -0
- package/build/types/scan-code.js +9 -0
- package/build/types/startup.d.ts +20 -0
- package/dashboard/dist/assets/{AdminDashboard-DplvDBti.js → AdminDashboard-uarpHB88.js} +2 -2
- package/dashboard/dist/assets/{AdminDashboard-DplvDBti.js.map → AdminDashboard-uarpHB88.js.map} +1 -1
- package/dashboard/dist/assets/{AgentConfigPage-D8Bf6YxO.js → AgentConfigPage-BcUaDD5E.js} +6 -6
- package/dashboard/dist/assets/{AgentConfigPage-D8Bf6YxO.js.map → AgentConfigPage-BcUaDD5E.js.map} +1 -1
- package/dashboard/dist/assets/{AgentDetailPage-BN8g0Y2G.js → AgentDetailPage-BaZBhK6i.js} +3 -3
- package/dashboard/dist/assets/{AgentDetailPage-BN8g0Y2G.js.map → AgentDetailPage-BaZBhK6i.js.map} +1 -1
- package/dashboard/dist/assets/AgentsPage-CuVFSDc4.js +2 -0
- package/dashboard/dist/assets/{AgentsPage-7JJBHku8.js.map → AgentsPage-CuVFSDc4.js.map} +1 -1
- package/dashboard/dist/assets/AvailableEscalationsPage-iO5NyyIK.js +2 -0
- package/dashboard/dist/assets/AvailableEscalationsPage-iO5NyyIK.js.map +1 -0
- package/dashboard/dist/assets/{BotPicker-CGCnIz8I.js → BotPicker-CClMby6B.js} +2 -2
- package/dashboard/dist/assets/{BotPicker-CGCnIz8I.js.map → BotPicker-CClMby6B.js.map} +1 -1
- package/dashboard/dist/assets/BulkAssignModal-BL8FRgkN.js +2 -0
- package/dashboard/dist/assets/{BulkAssignModal-NJBcoj-f.js.map → BulkAssignModal-BL8FRgkN.js.map} +1 -1
- package/dashboard/dist/assets/CapabilitiesPage-D53ogPor.js +2 -0
- package/dashboard/dist/assets/{CapabilitiesPage-F8dpNn9B.js.map → CapabilitiesPage-D53ogPor.js.map} +1 -1
- package/dashboard/dist/assets/{CollapsibleSection-BZW6VpCU.js → CollapsibleSection-ow8jpbtD.js} +2 -2
- package/dashboard/dist/assets/{CollapsibleSection-BZW6VpCU.js.map → CollapsibleSection-ow8jpbtD.js.map} +1 -1
- package/dashboard/dist/assets/{ConfirmDeleteModal-64adXLdq.js → ConfirmDeleteModal-CeEDt9iJ.js} +2 -2
- package/dashboard/dist/assets/{ConfirmDeleteModal-64adXLdq.js.map → ConfirmDeleteModal-CeEDt9iJ.js.map} +1 -1
- package/dashboard/dist/assets/{CountdownTimer-BxDub9d2.js → CountdownTimer-CSqyZMCG.js} +2 -2
- package/dashboard/dist/assets/{CountdownTimer-BxDub9d2.js.map → CountdownTimer-CSqyZMCG.js.map} +1 -1
- package/dashboard/dist/assets/{CredentialsPage-CnLzopLL.js → CredentialsPage-Dx7SxA23.js} +2 -2
- package/dashboard/dist/assets/{CredentialsPage-CnLzopLL.js.map → CredentialsPage-Dx7SxA23.js.map} +1 -1
- package/dashboard/dist/assets/{CronLabel-CAD5UYDT.js → CronLabel-LYPxpvNN.js} +2 -2
- package/dashboard/dist/assets/{CronLabel-CAD5UYDT.js.map → CronLabel-LYPxpvNN.js.map} +1 -1
- package/dashboard/dist/assets/DataTable-spX1dFyb.js +2 -0
- package/dashboard/dist/assets/DataTable-spX1dFyb.js.map +1 -0
- package/dashboard/dist/assets/{DropZone-XlcY8hEH.js → DropZone-f1o-GLM8.js} +2 -2
- package/dashboard/dist/assets/{DropZone-XlcY8hEH.js.map → DropZone-f1o-GLM8.js.map} +1 -1
- package/dashboard/dist/assets/{ElapsedCell-CwO4ufd0.js → ElapsedCell-BZJTSm9N.js} +2 -2
- package/dashboard/dist/assets/{ElapsedCell-CwO4ufd0.js.map → ElapsedCell-BZJTSm9N.js.map} +1 -1
- package/dashboard/dist/assets/EntityTimelinePanel-0wIIW2en.js +2 -0
- package/dashboard/dist/assets/{EntityTimelinePanel-CkF-oW-m.js.map → EntityTimelinePanel-0wIIW2en.js.map} +1 -1
- package/dashboard/dist/assets/{EscalationListSchemaPage-h9JO_q5f.js → EscalationListSchemaPage-CoYvtMzj.js} +3 -3
- package/dashboard/dist/assets/{EscalationListSchemaPage-h9JO_q5f.js.map → EscalationListSchemaPage-CoYvtMzj.js.map} +1 -1
- package/dashboard/dist/assets/EscalationListView-DWFHPufv.js +2 -0
- package/dashboard/dist/assets/EscalationListView-DWFHPufv.js.map +1 -0
- package/dashboard/dist/assets/{EscalationSchemaPage-mJFL5_Se.js → EscalationSchemaPage-C9Xu_A25.js} +3 -3
- package/dashboard/dist/assets/{EscalationSchemaPage-mJFL5_Se.js.map → EscalationSchemaPage-C9Xu_A25.js.map} +1 -1
- package/dashboard/dist/assets/EscalationTimeline-D8W2LNNk.js +2 -0
- package/dashboard/dist/assets/EscalationTimeline-D8W2LNNk.js.map +1 -0
- package/dashboard/dist/assets/EscalationTitleSelect-DLK8NWMp.js +2 -0
- package/dashboard/dist/assets/EscalationTitleSelect-DLK8NWMp.js.map +1 -0
- package/dashboard/dist/assets/{EscalationsOverview-DlXUFqWJ.js → EscalationsOverview-CW57FaP9.js} +2 -2
- package/dashboard/dist/assets/{EscalationsOverview-DlXUFqWJ.js.map → EscalationsOverview-CW57FaP9.js.map} +1 -1
- package/dashboard/dist/assets/{EventTable-Ike2xchn.js → EventTable-D1ctWhKf.js} +2 -2
- package/dashboard/dist/assets/{EventTable-Ike2xchn.js.map → EventTable-D1ctWhKf.js.map} +1 -1
- package/dashboard/dist/assets/{FilterBar-DMOR-O1c.js → FilterBar-C-iur-Nj.js} +2 -2
- package/dashboard/dist/assets/{FilterBar-DMOR-O1c.js.map → FilterBar-C-iur-Nj.js.map} +1 -1
- package/dashboard/dist/assets/GraphInvokePage-CcA_44M4.js +2 -0
- package/dashboard/dist/assets/{GraphInvokePage-CKtvWowP.js.map → GraphInvokePage-CcA_44M4.js.map} +1 -1
- package/dashboard/dist/assets/HomePage-Dc085ghJ.js +2 -0
- package/dashboard/dist/assets/{HomePage-BQ3Q791Q.js.map → HomePage-Dc085ghJ.js.map} +1 -1
- package/dashboard/dist/assets/ListToolbar-h_ziBt4O.js +2 -0
- package/dashboard/dist/assets/{ListToolbar-DdJzj472.js.map → ListToolbar-h_ziBt4O.js.map} +1 -1
- package/dashboard/dist/assets/{McpOverview-BbtrduWn.js → McpOverview-qXXhbNWV.js} +2 -2
- package/dashboard/dist/assets/{McpOverview-BbtrduWn.js.map → McpOverview-qXXhbNWV.js.map} +1 -1
- package/dashboard/dist/assets/{McpQueryDetailPage-C1L4T-Wt.js → McpQueryDetailPage-SEzSbZrd.js} +2 -2
- package/dashboard/dist/assets/{McpQueryDetailPage-C1L4T-Wt.js.map → McpQueryDetailPage-SEzSbZrd.js.map} +1 -1
- package/dashboard/dist/assets/McpQueryPage-Cy0V0kv9.js +2 -0
- package/dashboard/dist/assets/{McpQueryPage-CfJy7HZ7.js.map → McpQueryPage-Cy0V0kv9.js.map} +1 -1
- package/dashboard/dist/assets/{McpRunDetailPage-CA9yv7he.js → McpRunDetailPage-DjJO5vSb.js} +2 -2
- package/dashboard/dist/assets/{McpRunDetailPage-CA9yv7he.js.map → McpRunDetailPage-DjJO5vSb.js.map} +1 -1
- package/dashboard/dist/assets/McpRunsPage-BfjiJ8mM.js +2 -0
- package/dashboard/dist/assets/{McpRunsPage-D7QXjW9z.js.map → McpRunsPage-BfjiJ8mM.js.map} +1 -1
- package/dashboard/dist/assets/{NamespacePill-Bb3revqD.js → NamespacePill-DADRJOUl.js} +2 -2
- package/dashboard/dist/assets/{NamespacePill-Bb3revqD.js.map → NamespacePill-DADRJOUl.js.map} +1 -1
- package/dashboard/dist/assets/OperationsPage-dJcER0T_.js +3 -0
- package/dashboard/dist/assets/OperationsPage-dJcER0T_.js.map +1 -0
- package/dashboard/dist/assets/OperatorDashboard-zCkW4eqk.js +2 -0
- package/dashboard/dist/assets/{OperatorDashboard-sXNDh1Ph.js.map → OperatorDashboard-zCkW4eqk.js.map} +1 -1
- package/dashboard/dist/assets/{PageHeader-Di5Sz3an.js → PageHeader-Csq434-v.js} +2 -2
- package/dashboard/dist/assets/{PageHeader-Di5Sz3an.js.map → PageHeader-Csq434-v.js.map} +1 -1
- package/dashboard/dist/assets/{PageHeaderWithStats-DutKJ-h2.js → PageHeaderWithStats-CSnk1p5A.js} +2 -2
- package/dashboard/dist/assets/{PageHeaderWithStats-DutKJ-h2.js.map → PageHeaderWithStats-CSnk1p5A.js.map} +1 -1
- package/dashboard/dist/assets/{PersonaDetailPage-NeHD-Gra.js → PersonaDetailPage-Cx6L3Jvu.js} +2 -2
- package/dashboard/dist/assets/{PersonaDetailPage-NeHD-Gra.js.map → PersonaDetailPage-Cx6L3Jvu.js.map} +1 -1
- package/dashboard/dist/assets/{PersonasPage-DavKXRWX.js → PersonasPage-DOgGUlJl.js} +2 -2
- package/dashboard/dist/assets/{PersonasPage-DavKXRWX.js.map → PersonasPage-DOgGUlJl.js.map} +1 -1
- package/dashboard/dist/assets/PortalPage-BKuL1BeJ.js +2 -0
- package/dashboard/dist/assets/PortalPage-BKuL1BeJ.js.map +1 -0
- package/dashboard/dist/assets/{ProcessDetailPage-DkdKJGe6.js → ProcessDetailPage-BFcFSDUv.js} +2 -2
- package/dashboard/dist/assets/{ProcessDetailPage-DkdKJGe6.js.map → ProcessDetailPage-BFcFSDUv.js.map} +1 -1
- package/dashboard/dist/assets/ProcessesListPage-BaHV2cXp.js +2 -0
- package/dashboard/dist/assets/{ProcessesListPage-CjwVKe32.js.map → ProcessesListPage-BaHV2cXp.js.map} +1 -1
- package/dashboard/dist/assets/ResolverForm-Bgc0Zrya.js +7 -0
- package/dashboard/dist/assets/ResolverForm-Bgc0Zrya.js.map +1 -0
- package/dashboard/dist/assets/RoleDetailPage-BPY6i3CU.js +8 -0
- package/dashboard/dist/assets/RoleDetailPage-BPY6i3CU.js.map +1 -0
- package/dashboard/dist/assets/{RolePill-DhnVPK4q.js → RolePill-BafrASDX.js} +2 -2
- package/dashboard/dist/assets/{RolePill-DhnVPK4q.js.map → RolePill-BafrASDX.js.map} +1 -1
- package/dashboard/dist/assets/{RolesPage-OM9KM8Pg.js → RolesPage-DSqqKPbv.js} +2 -2
- package/dashboard/dist/assets/{RolesPage-OM9KM8Pg.js.map → RolesPage-DSqqKPbv.js.map} +1 -1
- package/dashboard/dist/assets/RunAsSelector-B29iWwel.js +2 -0
- package/dashboard/dist/assets/{RunAsSelector-fFMt1bGe.js.map → RunAsSelector-B29iWwel.js.map} +1 -1
- package/dashboard/dist/assets/{ScanCodesPage-AujH-pPQ.js → ScanCodesPage-S8aAJfnC.js} +2 -2
- package/dashboard/dist/assets/{ScanCodesPage-AujH-pPQ.js.map → ScanCodesPage-S8aAJfnC.js.map} +1 -1
- package/dashboard/dist/assets/{ScanSchemeDetailPage-eKQpmsC_.js → ScanSchemeDetailPage-CUBRAtmJ.js} +2 -2
- package/dashboard/dist/assets/{ScanSchemeDetailPage-eKQpmsC_.js.map → ScanSchemeDetailPage-CUBRAtmJ.js.map} +1 -1
- package/dashboard/dist/assets/ScanStationPage-R9t1-CeQ.js +2 -0
- package/dashboard/dist/assets/{ScanStationPage-C1_ppDoZ.js.map → ScanStationPage-R9t1-CeQ.js.map} +1 -1
- package/dashboard/dist/assets/{ScopeBadge-CXUg0FHo.js → ScopeBadge-b6MIBiYD.js} +2 -2
- package/dashboard/dist/assets/{ScopeBadge-CXUg0FHo.js.map → ScopeBadge-b6MIBiYD.js.map} +1 -1
- package/dashboard/dist/assets/{StickyPagination-B91Pk9xh.js → StickyPagination-CkW_A507.js} +2 -2
- package/dashboard/dist/assets/{StickyPagination-B91Pk9xh.js.map → StickyPagination-CkW_A507.js.map} +1 -1
- package/dashboard/dist/assets/{StreamMessageDetail-C7SPqaJt.js → StreamMessageDetail-yzWX0wac.js} +2 -2
- package/dashboard/dist/assets/{StreamMessageDetail-C7SPqaJt.js.map → StreamMessageDetail-yzWX0wac.js.map} +1 -1
- package/dashboard/dist/assets/{SwimlaneTimeline-BcHR8ylf.js → SwimlaneTimeline-Cf4DXFxj.js} +2 -2
- package/dashboard/dist/assets/{SwimlaneTimeline-BcHR8ylf.js.map → SwimlaneTimeline-Cf4DXFxj.js.map} +1 -1
- package/dashboard/dist/assets/{TagInput-BZ8vb2oW.js → TagInput-ZrIIrEUP.js} +2 -2
- package/dashboard/dist/assets/{TagInput-BZ8vb2oW.js.map → TagInput-ZrIIrEUP.js.map} +1 -1
- package/dashboard/dist/assets/{TaskDetailPage-Bqj0I_I0.js → TaskDetailPage-DCDcEps9.js} +2 -2
- package/dashboard/dist/assets/{TaskDetailPage-Bqj0I_I0.js.map → TaskDetailPage-DCDcEps9.js.map} +1 -1
- package/dashboard/dist/assets/{TaskQueuePill-Bxir8WRl.js → TaskQueuePill-DkQ1uc6y.js} +2 -2
- package/dashboard/dist/assets/{TaskQueuePill-Bxir8WRl.js.map → TaskQueuePill-DkQ1uc6y.js.map} +1 -1
- package/dashboard/dist/assets/TasksListPage-BBATgpf7.js +2 -0
- package/dashboard/dist/assets/{TasksListPage-BB1f79lL.js.map → TasksListPage-BBATgpf7.js.map} +1 -1
- package/dashboard/dist/assets/{TimeAgo-BFnODmNe.js → TimeAgo-CSNVEjch.js} +2 -2
- package/dashboard/dist/assets/{TimeAgo-BFnODmNe.js.map → TimeAgo-CSNVEjch.js.map} +1 -1
- package/dashboard/dist/assets/{TimestampCell-BXgLOBsr.js → TimestampCell-Du1nBrPn.js} +2 -2
- package/dashboard/dist/assets/{TimestampCell-BXgLOBsr.js.map → TimestampCell-Du1nBrPn.js.map} +1 -1
- package/dashboard/dist/assets/{ToolPill-FkgTXIhq.js → ToolPill-Baxm02L6.js} +2 -2
- package/dashboard/dist/assets/{ToolPill-FkgTXIhq.js.map → ToolPill-Baxm02L6.js.map} +1 -1
- package/dashboard/dist/assets/ToolTestPanel-CF-h_5Rg.js +2 -0
- package/dashboard/dist/assets/{ToolTestPanel-Bwe3J5lj.js.map → ToolTestPanel-CF-h_5Rg.js.map} +1 -1
- package/dashboard/dist/assets/{TopicDetailPage-DAF07vZ9.js → TopicDetailPage-Dr1UmWcp.js} +3 -3
- package/dashboard/dist/assets/{TopicDetailPage-DAF07vZ9.js.map → TopicDetailPage-Dr1UmWcp.js.map} +1 -1
- package/dashboard/dist/assets/TopicsPage-CUUo-Ylf.js +2 -0
- package/dashboard/dist/assets/{TopicsPage-C1gxBUap.js.map → TopicsPage-CUUo-Ylf.js.map} +1 -1
- package/dashboard/dist/assets/{UserName-BzXJUE6q.js → UserName-kBh1dc39.js} +2 -2
- package/dashboard/dist/assets/{UserName-BzXJUE6q.js.map → UserName-kBh1dc39.js.map} +1 -1
- package/dashboard/dist/assets/{WorkflowExecutionPage-SkRU5cRX.js → WorkflowExecutionPage-CCRSbnDx.js} +2 -2
- package/dashboard/dist/assets/{WorkflowExecutionPage-SkRU5cRX.js.map → WorkflowExecutionPage-CCRSbnDx.js.map} +1 -1
- package/dashboard/dist/assets/{WorkflowPill--AYMW7u_.js → WorkflowPill-ZepbO_ny.js} +2 -2
- package/dashboard/dist/assets/{WorkflowPill--AYMW7u_.js.map → WorkflowPill-ZepbO_ny.js.map} +1 -1
- package/dashboard/dist/assets/WorkflowsDashboard-BNQVvyek.js +2 -0
- package/dashboard/dist/assets/{WorkflowsDashboard-CZAqRk1N.js.map → WorkflowsDashboard-BNQVvyek.js.map} +1 -1
- package/dashboard/dist/assets/{WorkflowsOverview-BoN44VTE.js → WorkflowsOverview-DswubNJN.js} +2 -2
- package/dashboard/dist/assets/{WorkflowsOverview-BoN44VTE.js.map → WorkflowsOverview-DswubNJN.js.map} +1 -1
- package/dashboard/dist/assets/{YamlWorkflowDetailPage-CqjhtdJf.js → YamlWorkflowDetailPage-Cw9Dlmup.js} +11 -11
- package/dashboard/dist/assets/{YamlWorkflowDetailPage-CqjhtdJf.js.map → YamlWorkflowDetailPage-Cw9Dlmup.js.map} +1 -1
- package/dashboard/dist/assets/{YamlWorkflowsPage-CwnJkzyb.js → YamlWorkflowsPage-DB8xnIXy.js} +2 -2
- package/dashboard/dist/assets/{YamlWorkflowsPage-CwnJkzyb.js.map → YamlWorkflowsPage-DB8xnIXy.js.map} +1 -1
- package/dashboard/dist/assets/{agents-gV0Ys-sY.js → agents-BwEnf6N9.js} +2 -2
- package/dashboard/dist/assets/{agents-gV0Ys-sY.js.map → agents-BwEnf6N9.js.map} +1 -1
- package/dashboard/dist/assets/{bots-B97itB3I.js → bots-CCmJTT2u.js} +2 -2
- package/dashboard/dist/assets/{bots-B97itB3I.js.map → bots-CCmJTT2u.js.map} +1 -1
- package/dashboard/dist/assets/{capabilities-CR9xZgGd.js → capabilities-BZHgp_nh.js} +2 -2
- package/dashboard/dist/assets/{capabilities-CR9xZgGd.js.map → capabilities-BZHgp_nh.js.map} +1 -1
- package/dashboard/dist/assets/{constants-BHkpVaqx.js → constants-CeBBTzf5.js} +2 -2
- package/dashboard/dist/assets/{constants-BHkpVaqx.js.map → constants-CeBBTzf5.js.map} +1 -1
- package/dashboard/dist/assets/{controlplane-YxvP1KCa.js → controlplane-CyfwUlFA.js} +2 -2
- package/dashboard/dist/assets/{controlplane-YxvP1KCa.js.map → controlplane-CyfwUlFA.js.map} +1 -1
- package/dashboard/dist/assets/escalation-columns-BJPTNmLW.js +2 -0
- package/dashboard/dist/assets/escalation-columns-BJPTNmLW.js.map +1 -0
- package/dashboard/dist/assets/index-3gbd5neL.js +67 -0
- package/dashboard/dist/assets/index-3gbd5neL.js.map +1 -0
- package/dashboard/dist/assets/index-BAAVTyZ-.js +2 -0
- package/dashboard/dist/assets/{index-BQpV-DTG.js.map → index-BAAVTyZ-.js.map} +1 -1
- package/dashboard/dist/assets/{index-B9BBCqLI.js → index-BC6Jenlo.js} +2 -2
- package/dashboard/dist/assets/{index-B9BBCqLI.js.map → index-BC6Jenlo.js.map} +1 -1
- package/dashboard/dist/assets/index-C7KHqOTQ.js +2 -0
- package/dashboard/dist/assets/{index-Bp9KBLT5.js.map → index-C7KHqOTQ.js.map} +1 -1
- package/dashboard/dist/assets/index-CDrqqbSR.js +3 -0
- package/dashboard/dist/assets/index-CDrqqbSR.js.map +1 -0
- package/dashboard/dist/assets/index-CVwzCZ43.js +2 -0
- package/dashboard/dist/assets/{index-CFbo9FU9.js.map → index-CVwzCZ43.js.map} +1 -1
- package/dashboard/dist/assets/index-CaGF6TCC.js +2 -0
- package/dashboard/dist/assets/index-CaGF6TCC.js.map +1 -0
- package/dashboard/dist/assets/index-ClVbfe4z.js +13 -0
- package/dashboard/dist/assets/{index-Cfvkl2J0.js.map → index-ClVbfe4z.js.map} +1 -1
- package/dashboard/dist/assets/{index-DMeaiKgf.js → index-CuVkSmj5.js} +2 -2
- package/dashboard/dist/assets/{index-DMeaiKgf.js.map → index-CuVkSmj5.js.map} +1 -1
- package/dashboard/dist/assets/{index-ipqwPavs.js → index-DAuX_PlL.js} +2 -2
- package/dashboard/dist/assets/{index-ipqwPavs.js.map → index-DAuX_PlL.js.map} +1 -1
- package/dashboard/dist/assets/{index-CIpHj4di.js → index-DBWS5QL8.js} +2 -2
- package/dashboard/dist/assets/{index-CIpHj4di.js.map → index-DBWS5QL8.js.map} +1 -1
- package/dashboard/dist/assets/index-DIWCI6HC.js +2 -0
- package/dashboard/dist/assets/{index-CUZ6LYye.js.map → index-DIWCI6HC.js.map} +1 -1
- package/dashboard/dist/assets/{index-DwOnWeu8.js → index-DZ8X_Gp4.js} +2 -2
- package/dashboard/dist/assets/{index-DwOnWeu8.js.map → index-DZ8X_Gp4.js.map} +1 -1
- package/dashboard/dist/assets/index-Dh8MJl3L.css +1 -0
- package/dashboard/dist/assets/{knowledge-XX6cW4Ob.js → knowledge-CqyLhUMg.js} +2 -2
- package/dashboard/dist/assets/{knowledge-XX6cW4Ob.js.map → knowledge-CqyLhUMg.js.map} +1 -1
- package/dashboard/dist/assets/{mcp-CH13hNH2.js → mcp-Cvu6bFYH.js} +2 -2
- package/dashboard/dist/assets/{mcp-CH13hNH2.js.map → mcp-Cvu6bFYH.js.map} +1 -1
- package/dashboard/dist/assets/{mcp-query-Duydd3JA.js → mcp-query-qC6A3e9l.js} +2 -2
- package/dashboard/dist/assets/{mcp-query-Duydd3JA.js.map → mcp-query-qC6A3e9l.js.map} +1 -1
- package/dashboard/dist/assets/metadata-display-COo3mMCr.js +2 -0
- package/dashboard/dist/assets/metadata-display-COo3mMCr.js.map +1 -0
- package/dashboard/dist/assets/{personas-mDk4lLQS.js → personas-BKN_lJuV.js} +2 -2
- package/dashboard/dist/assets/{personas-mDk4lLQS.js.map → personas-BKN_lJuV.js.map} +1 -1
- package/dashboard/dist/assets/{pipelines-B5GcgCeF.js → pipelines-BldIfv85.js} +2 -2
- package/dashboard/dist/assets/{pipelines-B5GcgCeF.js.map → pipelines-BldIfv85.js.map} +1 -1
- package/dashboard/dist/assets/{tasks-CItmNsRp.js → tasks-B-Uay8uL.js} +2 -2
- package/dashboard/dist/assets/{tasks-CItmNsRp.js.map → tasks-B-Uay8uL.js.map} +1 -1
- package/dashboard/dist/assets/{topics-CJYG7BX5.js → topics-438EQogt.js} +2 -2
- package/dashboard/dist/assets/{topics-CJYG7BX5.js.map → topics-438EQogt.js.map} +1 -1
- package/dashboard/dist/assets/useContainerWidth-DSLp1gEm.js +2 -0
- package/dashboard/dist/assets/useContainerWidth-DSLp1gEm.js.map +1 -0
- package/dashboard/dist/assets/{useDebouncedValue-BrwgXcp8.js → useDebouncedValue-Cw8hYZ8y.js} +2 -2
- package/dashboard/dist/assets/{useDebouncedValue-BrwgXcp8.js.map → useDebouncedValue-Cw8hYZ8y.js.map} +1 -1
- package/dashboard/dist/assets/{useNamespace-CHty0HAS.js → useNamespace-D1218GQ8.js} +2 -2
- package/dashboard/dist/assets/{useNamespace-CHty0HAS.js.map → useNamespace-D1218GQ8.js.map} +1 -1
- package/dashboard/dist/assets/{useYamlActivityEvents-CoTsia7t.js → useYamlActivityEvents-BAQf_y_U.js} +2 -2
- package/dashboard/dist/assets/{useYamlActivityEvents-CoTsia7t.js.map → useYamlActivityEvents-BAQf_y_U.js.map} +1 -1
- package/dashboard/dist/assets/{vendor-icons-DeBdvyKJ.js → vendor-icons-B7OcUM6b.js} +2 -2
- package/dashboard/dist/assets/{vendor-icons-DeBdvyKJ.js.map → vendor-icons-B7OcUM6b.js.map} +1 -1
- package/dashboard/dist/assets/{yaml-workflows-CiWwx5rM.js → yaml-workflows-CN01gEB0.js} +2 -2
- package/dashboard/dist/assets/{yaml-workflows-CiWwx5rM.js.map → yaml-workflows-CN01gEB0.js.map} +1 -1
- package/dashboard/dist/index.html +3 -3
- package/docs/accumulator.md +113 -0
- package/docs/api/http/escalations.md +89 -0
- package/docs/api/http/roles.md +1 -0
- package/docs/api/sdk/escalations.md +91 -0
- package/docs/api/sdk/roles.md +2 -0
- package/docs/architecture.md +1 -1
- package/docs/code-owned-configuration.md +2 -1
- package/docs/dashboard.md +10 -4
- package/docs/hitl/design.md +1 -1
- package/docs/hitl/escalation.md +37 -1
- package/docs/hitl/invoke-form.md +4 -0
- package/docs/hitl/pinned-views.md +4 -0
- package/docs/hitl/portal.md +97 -0
- package/docs/hitl/resolution.md +41 -0
- package/docs/hitl/x-lt-embed.md +1 -1
- package/docs/hitl/x-lt-invoke.md +95 -0
- package/docs/hitl/x-lt-list-schema.md +3 -1
- package/docs/hitl/x-lt-widget.md +1 -0
- package/docs/hitl-guide.md +8 -1
- package/docs/scan-codes.md +15 -2
- package/docs/sdk.md +1 -1
- package/docs/workflows.md +2 -2
- package/package.json +4 -2
- package/dashboard/dist/assets/AgentsPage-7JJBHku8.js +0 -2
- package/dashboard/dist/assets/AvailableEscalationsPage-lz5qwSjg.js +0 -2
- package/dashboard/dist/assets/AvailableEscalationsPage-lz5qwSjg.js.map +0 -1
- package/dashboard/dist/assets/BulkAssignModal-NJBcoj-f.js +0 -2
- package/dashboard/dist/assets/CapabilitiesPage-F8dpNn9B.js +0 -2
- package/dashboard/dist/assets/DataTable-7C7riavf.js +0 -2
- package/dashboard/dist/assets/DataTable-7C7riavf.js.map +0 -1
- package/dashboard/dist/assets/EntityTimelinePanel-CkF-oW-m.js +0 -2
- package/dashboard/dist/assets/EscalationListView-AHW2xtlr.js +0 -2
- package/dashboard/dist/assets/EscalationListView-AHW2xtlr.js.map +0 -1
- package/dashboard/dist/assets/GraphInvokePage-CKtvWowP.js +0 -2
- package/dashboard/dist/assets/HomePage-BQ3Q791Q.js +0 -2
- package/dashboard/dist/assets/ListToolbar-DdJzj472.js +0 -2
- package/dashboard/dist/assets/McpQueryPage-CfJy7HZ7.js +0 -2
- package/dashboard/dist/assets/McpRunsPage-D7QXjW9z.js +0 -2
- package/dashboard/dist/assets/OperationsPage-aLHHAP2X.js +0 -3
- package/dashboard/dist/assets/OperationsPage-aLHHAP2X.js.map +0 -1
- package/dashboard/dist/assets/OperatorDashboard-sXNDh1Ph.js +0 -2
- package/dashboard/dist/assets/ProcessesListPage-CjwVKe32.js +0 -2
- package/dashboard/dist/assets/ResolverForm-Bk-wDkN-.js +0 -3
- package/dashboard/dist/assets/ResolverForm-Bk-wDkN-.js.map +0 -1
- package/dashboard/dist/assets/RoleDetailPage-WQt0y5l7.js +0 -8
- package/dashboard/dist/assets/RoleDetailPage-WQt0y5l7.js.map +0 -1
- package/dashboard/dist/assets/RunAsSelector-fFMt1bGe.js +0 -2
- package/dashboard/dist/assets/ScanStationPage-C1_ppDoZ.js +0 -2
- package/dashboard/dist/assets/TasksListPage-BB1f79lL.js +0 -2
- package/dashboard/dist/assets/ToolTestPanel-Bwe3J5lj.js +0 -2
- package/dashboard/dist/assets/TopicsPage-C1gxBUap.js +0 -2
- package/dashboard/dist/assets/WorkflowsDashboard-CZAqRk1N.js +0 -2
- package/dashboard/dist/assets/escalation-columns-uq-IV2aj.js +0 -2
- package/dashboard/dist/assets/escalation-columns-uq-IV2aj.js.map +0 -1
- package/dashboard/dist/assets/index-3ezfWLkE.js +0 -6
- package/dashboard/dist/assets/index-3ezfWLkE.js.map +0 -1
- package/dashboard/dist/assets/index-BQpV-DTG.js +0 -2
- package/dashboard/dist/assets/index-Bp9KBLT5.js +0 -2
- package/dashboard/dist/assets/index-Bpvfr4OW.css +0 -1
- package/dashboard/dist/assets/index-CFbo9FU9.js +0 -2
- package/dashboard/dist/assets/index-CIwlVfvV.js +0 -67
- package/dashboard/dist/assets/index-CIwlVfvV.js.map +0 -1
- package/dashboard/dist/assets/index-CUZ6LYye.js +0 -2
- package/dashboard/dist/assets/index-Cfvkl2J0.js +0 -13
- package/dashboard/dist/assets/index-SGyrXGp8.js +0 -3
- package/dashboard/dist/assets/index-SGyrXGp8.js.map +0 -1
- package/dashboard/dist/assets/invoke-context-DrVyUEfs.js +0 -2
- package/dashboard/dist/assets/invoke-context-DrVyUEfs.js.map +0 -1
- package/dashboard/dist/assets/metadata-display--TzK0REC.js +0 -2
- package/dashboard/dist/assets/metadata-display--TzK0REC.js.map +0 -1
- package/dashboard/dist/assets/resolver-payload-m9AGKZ3a.js +0 -2
- package/dashboard/dist/assets/resolver-payload-m9AGKZ3a.js.map +0 -1
- package/docs/compilation.md +0 -152
- package/docs/compiler.md +0 -311
- package/docs/contributing.md +0 -56
- package/docs/design-principles.md +0 -245
- package/docs/schema-exchange.md +0 -173
- package/docs/self-test.md +0 -106
- package/docs/story.md +0 -184
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"ResolverForm-Bk-wDkN-.js","sources":["../../src/lib/seed-form-json.ts","../../../shared/form-validation/derive-field-label.ts","../../../shared/form-validation/ctx-path.ts","../../../shared/form-validation/x-lt-options.ts","../../../shared/form-validation/field-validator.ts","../../../shared/form-validation/x-lt-show-if.ts","../../src/components/escalation/resolver-form/LockedFormFrame.tsx","../../src/components/escalation/resolver-form/FieldChrome.tsx","../../src/components/escalation/widgets/FileUploadWidget.tsx","../../src/components/escalation/widgets/CodeEditorWidget.tsx","../../src/components/escalation/widgets/SignatureWidget.tsx","../../src/components/escalation/widgets/RichTextWidget.tsx","../../src/components/escalation/widgets/MarkdownWidget.tsx","../../src/components/escalation/widgets/ChecklistWidget.tsx","../../src/components/escalation/widgets/AttachmentWidget.tsx","../../src/components/escalation/widgets/LinkWidget.tsx","../../src/components/escalation/widgets/OpenDetailButton.tsx","../../src/components/escalation/widgets/EscalationWidget.tsx","../../../shared/form-validation/x-lt-query.ts","../../src/components/escalation/widgets/EscalationListWidget.tsx","../../src/components/escalation/widgets/index.ts","../../src/components/escalation/resolver-form/form-cells.ts","../../src/components/escalation/resolver-form/SelectField.tsx","../../src/components/escalation/resolver-form/MultiSelectField.tsx","../../src/components/escalation/resolver-form/JsonField.tsx","../../src/components/escalation/resolver-form/FieldRow.tsx","../../src/components/escalation/resolver-form/DictionaryList.tsx","../../src/components/escalation/resolver-form/SectionGroup.tsx","../../src/components/escalation/resolver-form/ResolverForm.tsx"],"sourcesContent":["import { mapPayloadToForm } from './x-lt-bind';\n\n/**\n * The initial JSON an x-lt-* form edits: the schema rides along as the\n * `_form_schema` sidecar and every property starts at its prefill, its\n * declared default, or the zero value for its type. Object fields start as\n * {} so a checklist round-trips as an object from the first interaction.\n */\nexport function seedFormJson(\n formSchema: Record<string, any>,\n prefillPayload: Record<string, unknown> = {},\n): string {\n const prefill = mapPayloadToForm(prefillPayload, formSchema);\n const initial: Record<string, unknown> = { _form_schema: formSchema };\n for (const [key, def] of Object.entries((formSchema.properties ?? {}) as Record<string, Record<string, any>>)) {\n const zero = def.type === 'object' ? {} : '';\n initial[key] = prefill[key] ?? def.default ?? zero;\n }\n return JSON.stringify(initial, null, 2);\n}\n","/**\n * Human-readable label for a schema field.\n *\n * Resolution order:\n * 1. The JSON Schema `title` keyword — the author's explicit label, always wins.\n * 2. Snake/kebab keys become Title Case: `left_quantity` → `Left Quantity`.\n * 3. Single-token keys pass through unchanged: `PO`, `SKU`, `LEFTQUANTITY` —\n * a run of capitals carries no word boundaries to recover, and lowercasing\n * would mangle acronyms. Authors who want prose labels declare `title`.\n *\n * Used everywhere a field name faces a human: form labels, dictionary lists,\n * the errors panel, and metadata displays.\n */\nexport function deriveFieldLabel(\n key: string,\n fieldSchema?: Record<string, unknown> | null,\n): string {\n const title = fieldSchema?.title;\n if (typeof title === 'string' && title.trim().length > 0) return title.trim();\n\n const words = key.split(/[_-]+/).filter(Boolean);\n if (words.length <= 1) return key;\n\n return words\n .map((w) => (isCapsToken(w) ? w : w.charAt(0).toUpperCase() + w.slice(1)))\n .join(' ');\n}\n\n/** All-caps tokens (PO, SKU, ID) keep their casing inside multi-word keys. */\nfunction isCapsToken(word: string): boolean {\n return word.length > 1 && word === word.toUpperCase() && /[A-Z]/.test(word);\n}\n","/**\n * Context-path resolution shared by every token that names a `\"domain.path\"`.\n *\n * A path may embed `{{domain.path}}` interpolation segments — the same\n * grammar as x-lt-help tokens — resolved against the live context before the\n * walk. This is what makes cascading selects work: a field can declare\n *\n * x-lt-options: \"lookup.geo.regions.{{resolver.country}}\"\n *\n * and its option list follows the submitter's country answer, re-resolved\n * locally on every edit. An unresolved segment means \"no concrete path yet\",\n * never a literal placeholder.\n */\nimport { getDeep } from './x-lt-bind';\n\nexport const INTERPOLATION_PATTERN = /\\{\\{\\s*([^{}]+?)\\s*\\}\\}/g;\n\n/** Whether a token embeds `{{domain.path}}` interpolation segments. */\nexport function hasInterpolation(token: unknown): token is string {\n return typeof token === 'string' && /\\{\\{[^{}]+\\}\\}/.test(token);\n}\n\n/** Resolve a concrete `\"domain.path\"` (x-lt-bind syntax, `a.b[0].c`) against the context. */\nexport function resolveCtxPath(\n path: string,\n ctx: Record<string, unknown> | undefined,\n): unknown {\n if (!ctx) return undefined;\n const dot = path.indexOf('.');\n const root = ctx[dot === -1 ? path : path.slice(0, dot)];\n if (dot === -1) return root;\n if (root === null || typeof root !== 'object') return undefined;\n return getDeep(root, path.slice(dot + 1));\n}\n\n/**\n * Interpolate every `{{domain.path}}` segment against the context. Returns\n * the concrete path, or null when any segment resolves to nothing (missing,\n * null, empty string) or to a non-scalar — an unanswered cascade parent\n * yields no path, so the dependent field offers nothing.\n */\nexport function interpolatePath(\n template: string,\n ctx: Record<string, unknown> | undefined,\n): string | null {\n let unresolved = false;\n const concrete = template.replace(INTERPOLATION_PATTERN, (_match, rawPath: string) => {\n const value = resolveCtxPath(rawPath, ctx);\n if (typeof value === 'string' && value.trim().length > 0) return value;\n if (typeof value === 'number' && Number.isFinite(value)) return String(value);\n unresolved = true;\n return '';\n });\n return unresolved ? null : concrete;\n}\n","/**\n * x-lt-options — a select's option list resolved from the escalation context.\n * The field-level token names a `\"domain.path\"`; the value at that path is an\n * array whose entries are scalars (strings or numbers) or `{ value, label }`\n * objects (`{ id, label }` accepted as an alias), so one static role form can\n * offer a different legal set per escalation (e.g. `[1..N]` where N rides the\n * envelope, or a versioned knowledge lookup under the `lookup` domain).\n *\n * x-lt-options \"domain.path\", an ORDERED array of paths, or an inline\n * literal list (an array with no string entries: `{ value,\n * label }` objects, numbers, or booleans) — e.g.\n * \"envelope.left_quantity_options\" or\n * [\"lookup.reasons.items\", \"envelope.reject_reason_items\"].\n * With an array, the first entry that resolves to options\n * wins, so lookup-backed and envelope-embedded rows render\n * the same shared schema interchangeably (a parked row\n * falls through to the envelope it already carries).\n * Paths may embed {{domain.path}} interpolation segments —\n * e.g. \"lookup.geo.regions.{{resolver.country}}\" — making\n * the option list follow another answer (cascading selects);\n * an entry whose interpolation cannot resolve falls through\n * to the next entry.\n *\n * Object entries separate what the submitter SEES from what the payload\n * STORES: the select renders the label and emits the value (a DB-backed pick\n * list showing text while storing its foreign key). A scalar entry is both.\n *\n * A static `enum` takes precedence when both are present — the same\n * static-over-dynamic rule as x-lt-minimum/x-lt-maximum. Resolution is a\n * tri-state:\n *\n * undefined — no dynamic contract: a plain path that resolves to nothing\n * (the field renders as its plain input; membership unenforced)\n * [] — a dynamic (interpolated) contract offering nothing YET: the\n * select renders disabled and a present value fails membership\n * options — the option list\n *\n * Malformed entries in a resolved array are dropped.\n */\nimport { hasInterpolation, interpolatePath, resolveCtxPath } from './ctx-path';\n\nexport const X_LT_OPTIONS = 'x-lt-options';\n\nexport type OptionValue = string | number | boolean;\n\n/** One resolved option: the payload value and the rendered label. */\nexport interface ResolvedOption {\n value: OptionValue;\n label: string;\n}\n\nfunction isScalar(v: unknown): v is OptionValue {\n return typeof v === 'string' || typeof v === 'boolean' || (typeof v === 'number' && Number.isFinite(v));\n}\n\n/**\n * An array token with no string entries is the option list itself, written\n * inline. A bare string is always a context path, so a literal string value\n * is written as `{ value, label }`.\n */\nfunction isLiteralList(token: unknown): token is unknown[] {\n return Array.isArray(token) && token.length > 0 && !token.some((e) => typeof e === 'string');\n}\n\n/** Normalize one array entry, mixed arrays resolving each entry independently. */\nfunction toOption(entry: unknown): ResolvedOption | null {\n if (isScalar(entry)) return { value: entry, label: String(entry) };\n if (entry && typeof entry === 'object' && !Array.isArray(entry)) {\n const o = entry as Record<string, unknown>;\n const value = o.value !== undefined ? o.value : o.id;\n if (isScalar(value) && typeof o.label === 'string' && o.label.length > 0) {\n return { value, label: o.label };\n }\n }\n return null;\n}\n\n/**\n * The field's effective option list: the static `enum` when present, else an\n * inline literal list, else the entries at the token's `\"domain.path\"`.\n */\nexport function resolveFieldOptions(\n fieldSchema: Record<string, unknown> | null | undefined,\n ctx: Record<string, unknown> | undefined,\n): ResolvedOption[] | undefined {\n if (!fieldSchema) return undefined;\n\n // Enum entries pass through verbatim as values (whatever their type), each\n // labeled by its string form.\n const staticEnum = fieldSchema.enum;\n if (Array.isArray(staticEnum) && staticEnum.length > 0) {\n return staticEnum.map((v) => ({ value: v as OptionValue, label: String(v) }));\n }\n\n const token = fieldSchema[X_LT_OPTIONS];\n if (isLiteralList(token)) {\n const options = token.map(toOption).filter((o): o is ResolvedOption => o !== null);\n return options.length > 0 ? options : undefined;\n }\n const paths = (typeof token === 'string' ? [token] : Array.isArray(token) ? token : [])\n .filter((p): p is string => typeof p === 'string' && p.length > 0);\n if (paths.length === 0) return undefined;\n\n // Interpolated entries are a standing contract: when nothing resolves, the\n // field stays a (disabled) select and fails closed — a cascade child never\n // becomes free text. All-plain-path tokens keep the legacy undefined-on-miss\n // reading (the field falls back to its typed plain input).\n const miss = paths.some(hasInterpolation) ? ([] as ResolvedOption[]) : undefined;\n\n for (const sourcePath of paths) {\n let concrete = sourcePath;\n if (hasInterpolation(sourcePath)) {\n const resolved = interpolatePath(sourcePath, ctx);\n if (resolved === null) continue;\n concrete = resolved;\n }\n const cur = resolveCtxPath(concrete, ctx);\n if (!Array.isArray(cur)) continue;\n const options = cur.map(toOption).filter((o): o is ResolvedOption => o !== null);\n if (options.length > 0) return options;\n }\n return miss;\n}\n","import { resolveFieldOptions, X_LT_OPTIONS } from './x-lt-options';\nimport { hasInterpolation, interpolatePath, resolveCtxPath } from './ctx-path';\n\nexport interface FieldError { field: string; message: string }\n\ninterface ChecklistItem { id: string; label: string; required?: boolean }\n\n/**\n * Resolve a checklist widget's item definitions from its `x-lt-source` —\n * a \"domain.path\" or an ORDERED array of paths — against the escalation\n * context. With an array, the first entry that resolves to a non-empty item\n * list wins, so lookup-backed and envelope-embedded rows render the same\n * shared schema interchangeably. Paths may embed `{{domain.path}}`\n * interpolation segments (cascading sources); an entry that cannot resolve\n * falls through to the next. Nothing resolvable yields an empty list.\n */\nexport function resolveChecklistItems(\n source: unknown,\n ctx: Record<string, unknown> | undefined,\n): ChecklistItem[] {\n const paths = (typeof source === 'string' ? [source] : Array.isArray(source) ? source : [])\n .filter((p): p is string => typeof p === 'string' && p.length > 0);\n if (paths.length === 0 || !ctx) return [];\n for (const sourcePath of paths) {\n let concrete = sourcePath;\n if (hasInterpolation(sourcePath)) {\n const resolved = interpolatePath(sourcePath, ctx);\n if (resolved === null) continue;\n concrete = resolved;\n }\n const cur = resolveCtxPath(concrete, ctx);\n if (Array.isArray(cur) && cur.length > 0) return cur as ChecklistItem[];\n }\n return [];\n}\n\nexport const X_LT_DEFAULT_CHECKED = 'x-lt-default-checked';\n\n/**\n * The checklist's first-load default (`x-lt-default-checked`): every resolved\n * item starts checked, for affirm-then-exception flows where the submitter\n * unchecks what failed. Returns the all-checked answer map ONLY when the\n * field carries no answer yet — a saved or drafted map (any key, even\n * all-false) is never clobbered — and null otherwise: absent flag, existing\n * answer, or a source that resolves to no items. Declared on the widget\n * because the item set is runtime-sourced (envelope or lookup): a pure\n * escalation-minting step cannot enumerate the ids to seed formDefaults.\n */\nexport function resolveChecklistDefault(\n fieldSchema: Record<string, unknown> | null | undefined,\n currentValue: unknown,\n ctx?: Record<string, unknown>,\n): Record<string, boolean> | null {\n if (fieldSchema?.['x-lt-widget'] !== 'checklist') return null;\n if (fieldSchema[X_LT_DEFAULT_CHECKED] !== true) return null;\n if (\n currentValue && typeof currentValue === 'object' && !Array.isArray(currentValue)\n && Object.keys(currentValue).length > 0\n ) {\n return null;\n }\n const items = resolveChecklistItems(fieldSchema['x-lt-source'], ctx);\n if (items.length === 0) return null;\n return Object.fromEntries(items.map((i) => [i.id, true]));\n}\n\n/**\n * The checklist completion guard (`x-lt-require-all`): every rendered item must\n * be checked, except items whose definition carries `required: false` (the\n * explicit opt-out). Vacuous when the source resolves to no items — never\n * blocks on zero. Returns the panel message, or undefined when satisfied.\n * Stricter than (and composes with) the field-level required-array entry,\n * which remains the at-least-one check.\n */\nexport function validateRequireAll(\n value: unknown,\n fieldSchema: Record<string, unknown> | undefined,\n ctx?: Record<string, unknown>,\n): string | undefined {\n if (fieldSchema?.['x-lt-widget'] !== 'checklist') return undefined;\n if (fieldSchema['x-lt-require-all'] !== true) return undefined;\n\n const items = resolveChecklistItems(fieldSchema['x-lt-source'], ctx);\n const mandatory = items.filter((i) => i.required !== false);\n if (mandatory.length === 0) return undefined;\n\n const state = (typeof value === 'object' && value !== null && !Array.isArray(value))\n ? (value as Record<string, unknown>)\n : {};\n const incomplete = mandatory.filter((i) => !state[i.id]).length;\n if (incomplete === 0) return undefined;\n return `${incomplete} of ${mandatory.length} checks incomplete`;\n}\n\nexport const INVALID_JSON = 'Invalid JSON';\n\n/** The json editor holds unparseable text as a string at the field's key. */\nfunction isJsonWidget(fieldSchema: Record<string, unknown> | undefined): boolean {\n return fieldSchema?.['x-lt-widget'] === 'json';\n}\n\n/** A list is edited through the json editor or a multi-select; any other list value is display only. */\nfunction isEditableList(fieldSchema: Record<string, unknown> | undefined): boolean {\n return isJsonWidget(fieldSchema) || fieldSchema?.[X_LT_OPTIONS] !== undefined;\n}\n\nfunction plural(n: number, noun: string): string {\n return `${n} ${noun}${n === 1 ? '' : 's'}`;\n}\n\n/**\n * Runtime type check against the field's declared JSON Schema `type`. Guards\n * the payload contract for API-first callers (a form widget already produces\n * the right primitive; a script or agent submitting `\"1\"` for a number field\n * does not). Absent/empty values pass — presence is the required check's job.\n */\nexport function validateFieldType(\n value: unknown,\n fieldSchema: Record<string, unknown> | undefined,\n): string | undefined {\n const declared = fieldSchema?.type;\n if (typeof declared !== 'string') return undefined;\n if (value === undefined || value === null || value === '') return undefined;\n switch (declared) {\n case 'string':\n return typeof value === 'string' ? undefined : 'Expected text';\n case 'number':\n return typeof value === 'number' && Number.isFinite(value) ? undefined : 'Expected a number';\n case 'integer':\n return typeof value === 'number' && Number.isInteger(value) ? undefined : 'Expected a whole number';\n case 'boolean':\n return typeof value === 'boolean' ? undefined : 'Expected true or false';\n case 'array':\n if (Array.isArray(value)) return undefined;\n return isJsonWidget(fieldSchema) && typeof value === 'string' ? INVALID_JSON : 'Expected a list';\n case 'object':\n if (typeof value === 'object' && !Array.isArray(value)) return undefined;\n return isJsonWidget(fieldSchema) && typeof value === 'string' ? INVALID_JSON : 'Expected an object';\n default:\n return undefined;\n }\n}\n\n/**\n * Per-field JSON Schema validation — subset used by the resolver form.\n *\n * Returns a human-readable error string when the value fails a constraint,\n * or undefined when the value is valid. Callers are responsible for the\n * required check (empty-when-required) before calling this for constraint checks.\n *\n * `ctx` is optional context (ShowIfContext-shaped) used to resolve dynamic\n * constraint paths like `x-lt-minimum: \"envelope.min_score\"`.\n */\nexport function validateFieldConstraints(\n value: unknown,\n fieldSchema: Record<string, unknown> | undefined,\n ctx?: Record<string, unknown>,\n): string | undefined {\n if (!fieldSchema) return undefined;\n\n // Option membership — the form's select widget constrains choices; API-first\n // callers are unconstrained, so the effective option list is the contract:\n // the static enum, or the x-lt-options list resolved from context. The\n // submitted answer is the option VALUE (labels are presentation). An\n // interpolated list that currently offers nothing fails closed — a stale\n // cascade child value never submits.\n const allowed = resolveFieldOptions(fieldSchema, ctx);\n if (allowed !== undefined && value !== undefined && value !== null && value !== '' && !Array.isArray(value)) {\n if (allowed.length === 0) {\n return 'No valid options for this selection';\n }\n if (!allowed.some((o) => o.value === value)) {\n return `Must be one of: ${allowed.map((o) => String(o.value)).join(', ')}`;\n }\n }\n\n if (Array.isArray(value)) {\n return isEditableList(fieldSchema) ? validateListConstraints(value, fieldSchema, allowed, ctx) : undefined;\n }\n\n if (value !== null && typeof value === 'object') {\n return validateMapConstraints(value as Record<string, unknown>, fieldSchema, ctx);\n }\n\n if (typeof value === 'string') {\n const s = value.trim();\n if (s === '') return undefined; // empty string: required check is the caller's job\n\n const minLength = resolveNumericConstraint(fieldSchema.minLength, fieldSchema['x-lt-min-length'], ctx);\n if (minLength !== undefined && s.length < minLength) {\n return `Minimum ${minLength} character${minLength === 1 ? '' : 's'}`;\n }\n\n const maxLength = resolveNumericConstraint(fieldSchema.maxLength, fieldSchema['x-lt-max-length'], ctx);\n if (maxLength !== undefined && s.length > maxLength) {\n return `Maximum ${maxLength} characters (${s.length} entered)`;\n }\n\n const pattern = fieldSchema.pattern as string | undefined;\n if (pattern) {\n try {\n if (!new RegExp(pattern).test(s)) {\n const patternError = fieldSchema['x-lt-pattern-error'] as string | undefined;\n return patternError ?? 'Invalid format';\n }\n } catch {\n // Malformed pattern in schema — silently skip\n }\n }\n\n const fmt = fieldSchema.format as string | undefined;\n if (fmt === 'email' && !/^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/.test(s)) {\n return 'Enter a valid email address';\n }\n if (fmt === 'uri' && !/^https?:\\/\\/.+/.test(s)) {\n return 'Enter a valid URL';\n }\n }\n\n if (typeof value === 'number') {\n const minimum = resolveNumericConstraint(fieldSchema.minimum, fieldSchema['x-lt-minimum'], ctx);\n const exclusiveMinimum = resolveNumericConstraint(fieldSchema.exclusiveMinimum, undefined, ctx);\n const maximum = resolveNumericConstraint(fieldSchema.maximum, fieldSchema['x-lt-maximum'], ctx);\n const exclusiveMaximum = resolveNumericConstraint(fieldSchema.exclusiveMaximum, undefined, ctx);\n\n if (minimum !== undefined && value < minimum) {\n return `Minimum value is ${minimum}`;\n }\n if (exclusiveMinimum !== undefined && value <= exclusiveMinimum) {\n return `Must be greater than ${exclusiveMinimum}`;\n }\n if (maximum !== undefined && value > maximum) {\n return `Maximum value is ${maximum}`;\n }\n if (exclusiveMaximum !== undefined && value >= exclusiveMaximum) {\n return `Must be less than ${exclusiveMaximum}`;\n }\n }\n\n return undefined;\n}\n\n/**\n * An edited list: every item must belong to the field's `x-lt-options` when\n * declared, the length must sit within `minItems`/`maxItems`, and each item\n * must satisfy `items`. An empty list passes; presence is the required\n * check's job.\n */\nfunction validateListConstraints(\n value: unknown[],\n fieldSchema: Record<string, unknown>,\n allowed: ReturnType<typeof resolveFieldOptions>,\n ctx: Record<string, unknown> | undefined,\n): string | undefined {\n if (value.length === 0) return undefined;\n if (allowed !== undefined) {\n if (allowed.length === 0) return 'No valid options for this selection';\n if (value.some((v) => !allowed.some((o) => o.value === v))) {\n return `Must be one of: ${allowed.map((o) => String(o.value)).join(', ')}`;\n }\n }\n const minItems = resolveNumericConstraint(fieldSchema.minItems, undefined, ctx);\n if (minItems !== undefined && value.length < minItems) return `At least ${plural(minItems, 'item')}`;\n const maxItems = resolveNumericConstraint(fieldSchema.maxItems, undefined, ctx);\n if (maxItems !== undefined && value.length > maxItems) return `At most ${plural(maxItems, 'item')}`;\n const items = fieldSchema.items;\n if (items && typeof items === 'object' && !Array.isArray(items)) {\n const itemSchema = items as Record<string, unknown>;\n for (let i = 0; i < value.length; i++) {\n const err = validateFieldType(value[i], itemSchema) ?? validateFieldConstraints(value[i], itemSchema, ctx);\n if (err) return `Item ${i + 1}: ${err}`;\n }\n }\n return undefined;\n}\n\n/**\n * A map value: keys must belong to `propertyNames.enum` when declared, and\n * every value must satisfy an object-shaped `additionalProperties`.\n */\nfunction validateMapConstraints(\n value: Record<string, unknown>,\n fieldSchema: Record<string, unknown>,\n ctx: Record<string, unknown> | undefined,\n): string | undefined {\n const entries = Object.entries(value);\n if (entries.length === 0) return undefined;\n const propertyNames = fieldSchema.propertyNames as Record<string, unknown> | undefined;\n const allowedKeys = Array.isArray(propertyNames?.enum) ? propertyNames.enum.map(String) : undefined;\n if (allowedKeys) {\n const unknown = entries.find(([k]) => !allowedKeys.includes(k));\n if (unknown) return `Unknown key \"${unknown[0]}\". Allowed: ${allowedKeys.join(', ')}`;\n }\n const ap = fieldSchema.additionalProperties;\n if (ap && typeof ap === 'object' && !Array.isArray(ap)) {\n const valueSchema = ap as Record<string, unknown>;\n for (const [k, v] of entries) {\n const err = validateFieldType(v, valueSchema) ?? validateFieldConstraints(v, valueSchema, ctx);\n if (err) return `\"${k}\": ${err}`;\n }\n }\n return undefined;\n}\n\nfunction resolveNumericConstraint(\n staticVal: unknown,\n dynamicPath: unknown,\n ctx: Record<string, unknown> | undefined,\n): number | undefined {\n if (typeof staticVal === 'number') return staticVal;\n if (typeof dynamicPath === 'string' && ctx) {\n const dot = dynamicPath.indexOf('.');\n if (dot !== -1) {\n const domain = dynamicPath.slice(0, dot);\n const path = dynamicPath.slice(dot + 1);\n const domainObj = ctx[domain];\n if (domainObj && typeof domainObj === 'object') {\n const parts = path.split('.');\n let cur: unknown = domainObj;\n for (const p of parts) {\n cur = (cur as Record<string, unknown>)[p];\n if (cur === undefined) break;\n }\n if (typeof cur === 'number') return cur;\n if (typeof cur === 'string') {\n const n = Number(cur);\n if (!Number.isNaN(n)) return n;\n }\n }\n }\n }\n return undefined;\n}\n\n/** Full field error including required check then constraints. */\nexport function validateField(\n value: unknown,\n fieldSchema: Record<string, unknown> | undefined,\n isRequired: boolean,\n isTouched: boolean,\n ctx?: Record<string, unknown>,\n): string | undefined {\n if (!isTouched) return undefined;\n\n if (isRequired) {\n if (value === undefined || value === null) return 'Required';\n // A checkbox must be checked; a boolean with an option list is answered by either value.\n if (typeof value === 'boolean' && !value && resolveFieldOptions(fieldSchema, ctx) === undefined) return 'Required';\n if (typeof value === 'string' && value.trim() === '') return 'Required';\n // A picked or edited list needs one item; a plain list value is not checked.\n if (Array.isArray(value) && value.length === 0 && isEditableList(fieldSchema)) return 'Required';\n if (typeof value === 'object' && !Array.isArray(value) && value !== null) {\n const vals = Object.values(value as Record<string, unknown>);\n if (vals.length === 0) return 'Required';\n // A json map is answered by any key; every other object needs one truthy value.\n if (!isJsonWidget(fieldSchema) && vals.every((v) => !v)) return 'Required';\n }\n }\n\n // Declared-type check runs before constraints: a mis-typed value would make\n // the numeric/string constraint branches silently inapplicable.\n const typeError = validateFieldType(value, fieldSchema);\n if (typeError) return typeError;\n\n // Checklist completion — the stricter guard runs regardless of the\n // required-array entry (which stays at-least-one when present).\n const requireAll = validateRequireAll(value, fieldSchema, ctx);\n if (requireAll) return requireAll;\n\n return validateFieldConstraints(value, fieldSchema, ctx);\n}\n","/**\n * x-lt-showIf — conditional field visibility. A form_schema property may\n * declare `x-lt-showIf: \"domain.path\"` to show the field only when the value\n * at that path is present and truthy. Prefix `!` to invert: show when absent\n * or falsy.\n *\n * Equality forms compare the resolved value's string form:\n * \"domain.path=VALUE\" — show when String(value) equals VALUE\n * \"domain.path!=VALUE\" — show when it does not\n * An absent value compares as the empty string, so `=X` is false and `!=X` is\n * true when the path is missing. VALUE is the raw remainder after the operator\n * (trimmed; no quoting). The truthy/! forms are unchanged.\n *\n * Domains follow the same `domain.path` convention as x-lt-help tokens:\n * metadata — the escalation row's metadata dict\n * payload — the escalation context payload (escalation_payload)\n * envelope — the workflow-sent input envelope\n * escalation — top-level escalation row fields\n * resolver — the submitted resolver payload\n *\n * A missing or non-string condition always shows the field (opt-in, safe default).\n */\nimport { getDeep } from './x-lt-bind';\nimport { HELP_DOMAINS, type HelpTokenContext } from './x-lt-help';\n\nexport type ShowIfContext = HelpTokenContext;\n\nfunction isTruthy(value: unknown): boolean {\n return value !== null && value !== undefined && value !== '' && value !== false && value !== 0;\n}\n\n/** The value's comparable string form; absent compares as the empty string. */\nfunction asComparable(value: unknown): string {\n if (value === null || value === undefined) return '';\n if (typeof value === 'object') return JSON.stringify(value);\n return String(value);\n}\n\nfunction resolvePath(expr: string, ctx: ShowIfContext): { known: boolean; value: unknown } {\n const dot = expr.indexOf('.');\n const domain = (dot === -1 ? expr : expr.slice(0, dot)) as (typeof HELP_DOMAINS)[number];\n if (!(HELP_DOMAINS as readonly string[]).includes(domain)) return { known: false, value: undefined };\n const root = ctx[domain];\n if (dot === -1) return { known: true, value: root };\n try {\n return { known: true, value: getDeep(root, expr.slice(dot + 1)) };\n } catch {\n return { known: true, value: undefined };\n }\n}\n\n/**\n * Evaluates an x-lt-showIf condition. Returns true when the field should be\n * shown. Returns true when condition is absent, non-string, or context is null.\n * An array of conditions shows the field only when every one holds.\n */\nexport function evaluateShowIf(condition: unknown, ctx: ShowIfContext | null | undefined): boolean {\n if (Array.isArray(condition)) return condition.every((c) => evaluateShowIf(c, ctx));\n if (typeof condition !== 'string' || condition.length === 0) return true;\n if (!ctx) return true;\n const negate = condition.startsWith('!');\n const expr = negate ? condition.slice(1) : condition;\n\n // Equality forms — `!=` first so it never parses as `=` with a `!` in the path.\n const neqAt = expr.indexOf('!=');\n const eqAt = expr.indexOf('=');\n if (neqAt !== -1 || (eqAt !== -1 && eqAt !== neqAt + 1)) {\n const isNeq = neqAt !== -1 && (eqAt === -1 || neqAt < eqAt);\n const opAt = isNeq ? neqAt : eqAt;\n const path = expr.slice(0, opAt).trim();\n const expected = expr.slice(opAt + (isNeq ? 2 : 1)).trim();\n const { known, value } = resolvePath(path, ctx);\n if (!known) return true; // unknown domain — safe default, same as truthy form\n const matches = asComparable(value) === expected;\n const result = isNeq ? !matches : matches;\n return negate ? !result : result;\n }\n\n const { known, value } = resolvePath(expr, ctx);\n if (!known) return true;\n return negate ? !isTruthy(value) : isTruthy(value);\n}\n\n/**\n * `x-lt-hide-if-empty`: the field is suppressed while its value is empty\n * (null, undefined, '', false, or 0). Render and validation share this test.\n */\nexport function isHiddenIfEmpty(fieldSchema: Record<string, unknown> | undefined, value: unknown): boolean {\n if (fieldSchema?.['x-lt-hide-if-empty'] !== true) return false;\n return value === null || value === undefined || value === '' || value === false || value === 0;\n}\n","import { useEffect, useState, type ReactNode } from 'react';\nimport { Lock } from 'lucide-react';\n\n/** Animation length; a fallback timer clears state where animationend never fires. */\nconst HINT_MS = 2600;\n\n/**\n * The locked form's interaction frame. A click reports the gesture (the page\n * nudges Claim) and answers right at the click point: a small toast pops in\n * above the cursor naming the state — \"Claim this escalation to edit the\n * form\", \"Claimed by …\", \"resolved\" — holds a beat, and drifts out. Children\n * arrive as a prop, so hint state re-renders only this frame, never the form\n * beneath it.\n */\nexport function LockedFormFrame({\n hint,\n onLockedClick,\n children,\n}: {\n hint?: ReactNode;\n onLockedClick?: () => void;\n children: ReactNode;\n}) {\n const [hintAt, setHintAt] = useState<{ x: number; y: number; n: number } | null>(null);\n\n useEffect(() => {\n if (!hintAt) return;\n const timer = setTimeout(() => setHintAt(null), HINT_MS);\n return () => clearTimeout(timer);\n }, [hintAt]);\n\n const handleClick = (e: React.MouseEvent) => {\n onLockedClick?.();\n if (hint) {\n // Keep the bubble on screen when the click hugs a viewport edge.\n const x = Math.min(Math.max(e.clientX, 96), window.innerWidth - 96);\n setHintAt((prev) => ({ x, y: e.clientY, n: (prev?.n ?? 0) + 1 }));\n }\n };\n\n return (\n <div className=\"pb-8 max-w-form\" onClick={handleClick} data-testid=\"locked-form-frame\">\n {children}\n {hint && hintAt && (\n <div\n // Keyed per click so a repeat click replays the pop at the new spot.\n key={hintAt.n}\n role=\"status\"\n className=\"fixed z-[60] pointer-events-none flex items-center gap-2 px-3 py-1.5 rounded-md bg-surface-raised border border-surface-border shadow-lg text-xs font-medium text-text-primary whitespace-nowrap animate-[click-hint_2.6s_ease-in-out_both]\"\n style={{ left: hintAt.x, top: hintAt.y - 12 }}\n onAnimationEnd={() => setHintAt(null)}\n data-testid=\"locked-form-hint\"\n >\n <Lock className=\"w-3.5 h-3.5 text-accent shrink-0\" strokeWidth={1.5} />\n {hint}\n </div>\n )}\n </div>\n );\n}\n","/**\n * Shared field chrome for the resolver form: label, helper, error, and the\n * input class recipes. One place styles every generated field.\n */\n\nexport function FieldLabel({ children, isRequired, htmlFor }: {\n children: React.ReactNode;\n isRequired?: boolean;\n htmlFor?: string;\n}) {\n // `block` is load-bearing: a <label> is inline by default, and the\n // label→instruction→control anatomy would then hold only by accident —\n // a full-width control wraps below, but a narrow control (number,\n // max-w-48) with no instruction line sits flush BESIDE the label. The\n // anatomy is a column; the label declares it.\n return (\n <label htmlFor={htmlFor} className=\"block text-2xs font-semibold uppercase tracking-wider text-text-secondary\">\n {children}\n {isRequired && <span className=\"text-status-error ml-0.5\">*</span>}\n </label>\n );\n}\n\nexport function FieldHelper({ id, children }: { id?: string; children: React.ReactNode }) {\n return (\n <p id={id} className=\"text-2xs text-text-tertiary mt-0.5 leading-snug\">\n {children}\n </p>\n );\n}\n\nexport function FieldError({ error, id }: { error?: string; id?: string }) {\n if (!error) return null;\n return (\n <p id={id} role=\"alert\" className=\"text-2xs text-status-error mt-1 animate-[field-error-in_0.3s_ease-out]\">\n {error}\n </p>\n );\n}\n\nexport function inputClass(hasError?: boolean): string {\n return hasError\n ? 'input text-sm w-full mt-1 border-status-error/50 focus:border-status-error animate-[field-shake_0.4s_ease-in-out]'\n : 'input text-sm w-full mt-1';\n}\n\n// Select shares the field recipe but adds the unified chevron (via .select).\n// Width follows the content, floored for presence and capped by the cell —\n// a one-word choice never stretches across the measure. The floor is\n// min(16rem, 100%): CSS lets min-width beat max-width, so a bare min-w-64\n// would overflow a cell narrower than 16rem — the cell always wins.\nexport function selectClass(hasError?: boolean): string {\n return hasError\n ? 'select text-sm mt-1 min-w-[min(16rem,100%)] max-w-full border-status-error/50 focus:border-status-error animate-[field-shake_0.4s_ease-in-out]'\n : 'select text-sm mt-1 min-w-[min(16rem,100%)] max-w-full';\n}\n","import { useCallback, useRef } from 'react';\nimport { deriveFieldLabel } from '../../../lib/derive-field-label';\nimport { FieldLabel } from '../resolver-form/FieldChrome';\n\ninterface FileUploadWidgetProps {\n fieldKey: string;\n value: string;\n onChange: (v: string) => void;\n schema?: Record<string, unknown>;\n isRequired?: boolean;\n}\n\n/**\n * File upload widget that reads a file via FileReader and stores\n * its base64 data URL in the form value.\n */\nexport function FileUploadWidget({ fieldKey, value, onChange, schema, isRequired }: FileUploadWidgetProps) {\n const inputRef = useRef<HTMLInputElement>(null);\n const accept = (schema?.accept as string) ?? undefined;\n const label = deriveFieldLabel(fieldKey, schema);\n const helperText = schema?.description as string | undefined;\n\n const handleFile = useCallback((e: React.ChangeEvent<HTMLInputElement>) => {\n const file = e.target.files?.[0];\n if (!file) return;\n const reader = new FileReader();\n reader.onload = () => {\n if (typeof reader.result === 'string') {\n onChange(reader.result);\n }\n };\n reader.readAsDataURL(file);\n }, [onChange]);\n\n const hasFile = value.startsWith('data:');\n\n return (\n <div>\n <FieldLabel isRequired={isRequired}>\n {label}\n </FieldLabel>\n {helperText && <p className=\"text-2xs text-text-tertiary mt-0.5\">{helperText}</p>}\n <div className=\"mt-1\">\n <input\n ref={inputRef}\n type=\"file\"\n accept={accept}\n onChange={handleFile}\n className=\"hidden\"\n />\n <button\n type=\"button\"\n onClick={() => inputRef.current?.click()}\n className=\"btn-secondary text-xs px-3 py-1.5\"\n >\n {hasFile ? 'Replace file' : 'Choose file'}\n </button>\n {hasFile && (\n <span className=\"ml-2 text-xs text-status-success\">File attached</span>\n )}\n </div>\n </div>\n );\n}\n","import { useCallback } from 'react';\nimport { deriveFieldLabel } from '../../../lib/derive-field-label';\nimport { FieldLabel } from '../resolver-form/FieldChrome';\n\ninterface CodeEditorWidgetProps {\n fieldKey: string;\n value: string;\n onChange: (v: string) => void;\n schema?: Record<string, unknown>;\n isRequired?: boolean;\n}\n\n/**\n * Monospace textarea with tab-key support for code input.\n */\nexport function CodeEditorWidget({ fieldKey, value, onChange, schema, isRequired }: CodeEditorWidgetProps) {\n const label = deriveFieldLabel(fieldKey, schema);\n const helperText = schema?.description as string | undefined;\n const language = (schema?.['x-lt-language'] as string) ?? '';\n\n const handleKeyDown = useCallback((e: React.KeyboardEvent<HTMLTextAreaElement>) => {\n if (e.key === 'Tab') {\n e.preventDefault();\n const target = e.currentTarget;\n const start = target.selectionStart;\n const end = target.selectionEnd;\n const updated = value.substring(0, start) + ' ' + value.substring(end);\n onChange(updated);\n requestAnimationFrame(() => {\n target.selectionStart = target.selectionEnd = start + 2;\n });\n }\n }, [value, onChange]);\n\n return (\n <div>\n <FieldLabel isRequired={isRequired}>\n {label}\n {language && (\n <span className=\"ml-2 text-text-tertiary/60 normal-case font-normal\">{language}</span>\n )}\n </FieldLabel>\n {helperText && <p className=\"text-2xs text-text-tertiary mt-0.5\">{helperText}</p>}\n <textarea\n value={value}\n onChange={(e) => onChange(e.target.value)}\n onKeyDown={handleKeyDown}\n className=\"input w-full mt-1 font-mono text-xs leading-relaxed\"\n rows={10}\n spellCheck={false}\n />\n </div>\n );\n}\n","import { useCallback, useEffect, useRef, useState } from 'react';\nimport { deriveFieldLabel } from '../../../lib/derive-field-label';\nimport { FieldLabel } from '../resolver-form/FieldChrome';\n\ninterface SignatureWidgetProps {\n fieldKey: string;\n value: string;\n onChange: (v: string) => void;\n schema?: Record<string, unknown>;\n isRequired?: boolean;\n}\n\n/**\n * HTML5 Canvas signature pad. Outputs a PNG data URL.\n */\nexport function SignatureWidget({ fieldKey, value, onChange, schema, isRequired }: SignatureWidgetProps) {\n const canvasRef = useRef<HTMLCanvasElement>(null);\n const [isDrawing, setIsDrawing] = useState(false);\n const label = deriveFieldLabel(fieldKey, schema);\n const helperText = schema?.description as string | undefined;\n\n useEffect(() => {\n const canvas = canvasRef.current;\n if (!canvas) return;\n const ctx = canvas.getContext('2d');\n if (!ctx) return;\n ctx.lineWidth = 2;\n ctx.lineCap = 'round';\n // Deliberately unthemed: the signature is a captured document artifact —\n // the exported PNG must read like ink on paper regardless of theme.\n ctx.strokeStyle = '#1E1535';\n\n if (value && value.startsWith('data:')) {\n const img = new Image();\n img.onload = () => ctx.drawImage(img, 0, 0);\n img.src = value;\n }\n }, []); // eslint-disable-line react-hooks/exhaustive-deps\n\n const getPos = useCallback((e: React.MouseEvent<HTMLCanvasElement> | React.TouchEvent<HTMLCanvasElement>) => {\n const canvas = canvasRef.current!;\n const rect = canvas.getBoundingClientRect();\n // The backing store is a fixed 400×150 document; the element may display\n // at any width. Scale pointer coordinates into store space so the ink\n // lands under the cursor at every display size.\n const scaleX = rect.width > 0 ? canvas.width / rect.width : 1;\n const scaleY = rect.height > 0 ? canvas.height / rect.height : 1;\n if ('touches' in e) {\n return {\n x: (e.touches[0].clientX - rect.left) * scaleX,\n y: (e.touches[0].clientY - rect.top) * scaleY,\n };\n }\n return { x: (e.clientX - rect.left) * scaleX, y: (e.clientY - rect.top) * scaleY };\n }, []);\n\n const startDraw = useCallback((e: React.MouseEvent<HTMLCanvasElement> | React.TouchEvent<HTMLCanvasElement>) => {\n setIsDrawing(true);\n const ctx = canvasRef.current?.getContext('2d');\n if (!ctx) return;\n const pos = getPos(e);\n ctx.beginPath();\n ctx.moveTo(pos.x, pos.y);\n }, [getPos]);\n\n const draw = useCallback((e: React.MouseEvent<HTMLCanvasElement> | React.TouchEvent<HTMLCanvasElement>) => {\n if (!isDrawing) return;\n const ctx = canvasRef.current?.getContext('2d');\n if (!ctx) return;\n const pos = getPos(e);\n ctx.lineTo(pos.x, pos.y);\n ctx.stroke();\n }, [isDrawing, getPos]);\n\n const endDraw = useCallback(() => {\n setIsDrawing(false);\n const canvas = canvasRef.current;\n if (canvas) {\n onChange(canvas.toDataURL('image/png'));\n }\n }, [onChange]);\n\n const clear = useCallback(() => {\n const canvas = canvasRef.current;\n if (!canvas) return;\n const ctx = canvas.getContext('2d');\n if (!ctx) return;\n ctx.clearRect(0, 0, canvas.width, canvas.height);\n onChange('');\n }, [onChange]);\n\n return (\n <div>\n <FieldLabel isRequired={isRequired}>\n {label}\n </FieldLabel>\n {helperText && <p className=\"text-2xs text-text-tertiary mt-0.5\">{helperText}</p>}\n {/* The pad holds its natural document proportion (25rem = the 400px\n backing store), never stretched to the measure — the exported PNG\n is the artifact. Narrower cells shrink it; the scaling in getPos\n keeps the ink under the cursor either way. */}\n <div className=\"mt-1 max-w-[25rem] border border-surface-border rounded-md overflow-hidden bg-white\">\n <canvas\n ref={canvasRef}\n width={400}\n height={150}\n className=\"w-full cursor-crosshair touch-none\"\n onMouseDown={startDraw}\n onMouseMove={draw}\n onMouseUp={endDraw}\n onMouseLeave={endDraw}\n onTouchStart={startDraw}\n onTouchMove={draw}\n onTouchEnd={endDraw}\n />\n </div>\n <button\n type=\"button\"\n onClick={clear}\n className=\"mt-1 text-2xs text-text-tertiary hover:text-accent transition-colors\"\n >\n Clear\n </button>\n </div>\n );\n}\n","import { deriveFieldLabel } from '../../../lib/derive-field-label';\nimport { FieldLabel } from '../resolver-form/FieldChrome';\n\ninterface RichTextWidgetProps {\n fieldKey: string;\n value: string;\n onChange: (v: string) => void;\n schema?: Record<string, unknown>;\n isRequired?: boolean;\n}\n\n/**\n * Rich text input — a tall textarea with formatting hints.\n * A full WYSIWYG editor can replace this in a future iteration.\n */\nexport function RichTextWidget({ fieldKey, value, onChange, schema, isRequired }: RichTextWidgetProps) {\n const label = deriveFieldLabel(fieldKey, schema);\n const helperText = schema?.description as string | undefined;\n\n return (\n <div>\n <FieldLabel isRequired={isRequired}>\n {label}\n </FieldLabel>\n {helperText && <p className=\"text-2xs text-text-tertiary mt-0.5\">{helperText}</p>}\n <textarea\n value={value}\n onChange={(e) => onChange(e.target.value)}\n className=\"input w-full mt-1 text-sm leading-relaxed\"\n rows={8}\n placeholder=\"Supports plain text. Markdown formatting is preserved.\"\n />\n </div>\n );\n}\n","import { useState } from 'react';\nimport { deriveFieldLabel } from '../../../lib/derive-field-label';\nimport { FieldLabel } from '../resolver-form/FieldChrome';\nimport { MarkdownRenderer } from '../../common/display/MarkdownRenderer';\n\ninterface MarkdownWidgetProps {\n fieldKey: string;\n value: string;\n onChange: (v: string) => void;\n schema?: Record<string, unknown>;\n isRequired?: boolean;\n}\n\n/**\n * Markdown field — the same renderer the docs drawer uses, so a versioned\n * form schema can carry page source. Two shapes:\n *\n * - `readOnly: true` → a content block. The field's markdown (typically the\n * schema `default`) renders as HTML with no input chrome — instructions,\n * SOPs, and context live in the form as authored, versioned pages.\n * - editable → a Write/Preview source editor. The submitted value is the\n * markdown source.\n */\nexport function MarkdownWidget({ fieldKey, value, onChange, schema, isRequired }: MarkdownWidgetProps) {\n const [tab, setTab] = useState<'write' | 'preview'>('write');\n const label = deriveFieldLabel(fieldKey, schema);\n const helperText = schema?.description as string | undefined;\n const isReadOnly = schema?.readOnly === true;\n\n if (isReadOnly) {\n // Pure content block — the markdown carries its own headings and structure.\n return <MarkdownRenderer content={value} className=\"my-1\" />;\n }\n\n return (\n <div>\n <div className=\"flex items-center justify-between\">\n <FieldLabel isRequired={isRequired}>\n {label}\n </FieldLabel>\n <div className=\"flex items-center gap-0.5\">\n {(['write', 'preview'] as const).map((t) => (\n <button\n key={t}\n type=\"button\"\n onClick={() => setTab(t)}\n className={`px-2 py-0.5 text-2xs rounded transition-colors ${\n tab === t\n ? 'bg-accent/10 text-accent font-semibold'\n : 'text-text-quaternary hover:text-text-secondary'\n }`}\n >\n {t === 'write' ? 'Write' : 'Preview'}\n </button>\n ))}\n </div>\n </div>\n {helperText && <p className=\"text-2xs text-text-tertiary mt-0.5\">{helperText}</p>}\n {tab === 'write' ? (\n <textarea\n value={value}\n onChange={(e) => onChange(e.target.value)}\n className=\"input w-full mt-1 text-sm font-mono leading-relaxed\"\n rows={10}\n placeholder=\"Write markdown — headings, lists, tables, code blocks, and links all render.\"\n />\n ) : (\n <div className=\"mt-1 px-3 py-2 border border-surface-border rounded min-h-[120px]\">\n {value.trim() ? (\n <MarkdownRenderer content={value} />\n ) : (\n <p className=\"text-xs text-text-quaternary italic\">Nothing to preview.</p>\n )}\n </div>\n )}\n </div>\n );\n}\n","import { useEffect } from 'react';\nimport { Check } from 'lucide-react';\n\nimport { deriveFieldLabel } from '../../../lib/derive-field-label';\nimport { resolveChecklistItems, resolveChecklistDefault } from '../../../lib/field-validator';\nimport type { ShowIfContext } from '../../../lib/x-lt-show-if';\nimport { FieldLabel, FieldHelper } from '../resolver-form/FieldChrome';\nimport type { WidgetProps } from './index';\n\ninterface ChecklistItem { id: string; label: string; required?: boolean }\n\n/** Labels at or under this length read as tags; longer ones read as sentences. */\nconst CHIP_LABEL_MAX = 28;\n\n/**\n * Checklist widget — a dynamic list of labeled checkboxes driven by runtime\n * data in the escalation context.\n *\n * Schema usage:\n * \"x-lt-widget\": \"checklist\"\n * \"x-lt-source\": \"envelope.checklist_items\" (any domain.path, or an\n * ordered array of paths — first source that resolves wins)\n * \"x-lt-variant\": \"chips\" | \"rows\" (optional; see geometry below)\n *\n * Item definitions: Array<{ id: string; label: string; required?: boolean }>\n *\n * GEOMETRY — item length and selection mode decide it:\n * - rows — one item per line. The shape for rituals: sentence-length\n * confirmations read top-down and are ticked deliberately.\n * `x-lt-require-all` always renders rows.\n * - chips — a wrapping cloud of selectable pills. The shape for tags:\n * short pick-any items (reject reasons, categories) flow horizontally,\n * thumb-sized, selection visible at a glance.\n * Explicit `x-lt-variant` wins; otherwise require-all → rows, else chips\n * when every label is ≤28 characters.\n *\n * \"x-lt-require-all\": true — completion guard: every item must be checked\n * before submission, except items whose definition carries required: false.\n *\n * \"x-lt-default-checked\": true — first-load default: an unanswered field\n * initializes to every item checked (affirm-then-exception: the submitter\n * unchecks what failed). A saved answer map is never clobbered.\n *\n * Value stored: Record<string, boolean> keyed by item id.\n */\nexport function ChecklistWidget({\n fieldKey,\n value,\n onChange,\n schema,\n escalationContext,\n isRequired,\n submitAttempted,\n error,\n}: WidgetProps & { escalationContext?: ShowIfContext }) {\n const requireAll = schema?.['x-lt-require-all'] === true;\n // The shared resolver serves render and enforcement alike — including\n // {{domain.path}} interpolation in the source path.\n const items: ChecklistItem[] = resolveChecklistItems(\n schema?.['x-lt-source'],\n escalationContext as Record<string, unknown> | undefined,\n );\n\n let state: Record<string, boolean> = {};\n try { if (value) state = JSON.parse(value) as Record<string, boolean>; } catch { /* start empty */ }\n\n // First-load default (x-lt-default-checked): the moment the source resolves\n // (a lookup arrives async), an unanswered field initializes to every item\n // checked. Keyed on the serialized default so it fires once per material\n // change and never against a saved answer map.\n const defaultJson = (() => {\n const d = resolveChecklistDefault(schema, state, escalationContext as Record<string, unknown> | undefined);\n return d ? JSON.stringify(d) : null;\n })();\n useEffect(() => {\n if (defaultJson) onChange(defaultJson);\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [defaultJson]);\n\n const toggle = (id: string) => onChange(JSON.stringify({ ...state, [id]: !state[id] }));\n\n const title = deriveFieldLabel(fieldKey, schema);\n const helperText = schema?.description as string | undefined;\n\n if (items.length === 0) {\n return (\n <>\n <p className=\"text-xs text-text-tertiary italic mt-1\">\n No checklist items. None of the field's x-lt-source paths resolved on this escalation.\n </p>\n {error && (\n <p className=\"text-2xs text-status-error mt-1 animate-[field-error-in_0.3s_ease-out]\">\n {error}\n </p>\n )}\n </>\n );\n }\n\n const explicitVariant = schema?.['x-lt-variant'] as string | undefined;\n const variant = explicitVariant === 'chips' || explicitVariant === 'rows'\n ? explicitVariant\n : requireAll || items.some((i) => i.label.length > CHIP_LABEL_MAX)\n ? 'rows'\n : 'chips';\n\n const checkedCount = items.filter((item) => state[item.id]).length;\n // The click-to-focus anchor: the first unchecked mandatory item, so the\n // error panel lands the user on the next box to tick (first item when done).\n const focusId = (items.find((i) => !state[i.id] && i.required !== false) ?? items[0]).id;\n\n return (\n <div role=\"group\" aria-label={title} aria-required={isRequired || undefined} aria-invalid={error ? true : undefined}>\n <FieldLabel isRequired={isRequired}>{title}</FieldLabel>\n {helperText && <FieldHelper>{helperText}</FieldHelper>}\n {variant === 'chips' ? (\n <div className=\"flex flex-wrap gap-2 mt-2\">\n {items.map((item) => {\n const checked = state[item.id] ?? false;\n const showItemError = !checked && !!submitAttempted && checkedCount === 0 && (item.required || isRequired);\n return (\n // The pill IS the checkbox: the real input stays in the label\n // (sr-only) so native semantics and the focus anchor survive.\n // Selection is an act — it earns the solid accent.\n <label\n key={item.id}\n className={`inline-flex items-center gap-1.5 cursor-pointer select-none px-3.5 py-2 text-sm border transition-colors rounded-[var(--lt-radius-field)] ${\n checked\n ? 'bg-accent border-accent text-text-inverse'\n : showItemError\n ? 'bg-surface-field border-status-error/60 text-status-error'\n : 'bg-surface-field border-surface-field-border text-text-secondary hover:border-accent hover:text-text-primary'\n }`}\n >\n <input\n type=\"checkbox\"\n checked={checked}\n onChange={() => toggle(item.id)}\n className=\"sr-only\"\n data-testid={`checklist-item-${item.id}`}\n {...(item.id === focusId ? { 'data-field-key': fieldKey } : {})}\n />\n {checked && <Check className=\"w-3.5 h-3.5 shrink-0\" strokeWidth={2.5} />}\n {item.label}\n </label>\n );\n })}\n </div>\n ) : (\n <div className=\"space-y-2.5 mt-2\">\n {items.map((item) => {\n const checked = state[item.id] ?? false;\n // require-all: every unchecked mandatory item (required !== false) is an\n // error after a submit attempt, clearing live as each is checked.\n // At-least-one mode: highlight only while ZERO are checked — once any\n // item is confirmed the group requirement is met and highlights clear.\n const showItemError = !checked && !!submitAttempted && (\n requireAll\n ? item.required !== false\n : checkedCount === 0 && (item.required || isRequired)\n );\n return (\n <label\n key={item.id}\n className={`flex items-start gap-3 cursor-pointer group select-none rounded px-2 py-1 -mx-2 transition-colors ${\n showItemError ? 'bg-status-error/5' : 'hover:bg-surface-hover'\n }`}\n >\n <input\n type=\"checkbox\"\n checked={checked}\n onChange={() => toggle(item.id)}\n className={`mt-0.5 w-3.5 h-3.5 shrink-0 rounded ${showItemError ? 'accent-status-error' : 'accent-accent'}`}\n data-testid={`checklist-item-${item.id}`}\n {...(item.id === focusId ? { 'data-field-key': fieldKey } : {})}\n />\n <span className={`text-sm leading-snug transition-colors ${\n showItemError\n ? 'text-status-error'\n : 'text-text-secondary group-hover:text-text-primary'\n }`}>\n {item.label}\n {item.required && (\n <span className={`ml-0.5 text-2xs ${showItemError ? 'text-status-error' : 'text-text-quaternary'}`}>*</span>\n )}\n </span>\n </label>\n );\n })}\n </div>\n )}\n <p className=\"text-2xs text-text-quaternary mt-3 tabular-nums\">\n {variant === 'chips' ? (\n <>\n {checkedCount} selected\n {isRequired && checkedCount === 0 && !!submitAttempted && (\n <span className=\"ml-1 text-text-quaternary/60\">(check at least one)</span>\n )}\n </>\n ) : (\n <>\n {checkedCount} / {items.length} confirmed\n {requireAll ? (\n <span className=\"ml-1 text-text-quaternary/60\">\n (all required{items.some((i) => i.required === false) ? ' except optional' : ''})\n </span>\n ) : isRequired && checkedCount === 0 && !!submitAttempted && (\n <span className=\"ml-1 text-text-quaternary/60\">(at least one required)</span>\n )}\n </>\n )}\n </p>\n {error && (\n <p role=\"alert\" className=\"text-2xs text-status-error mt-1 animate-[field-error-in_0.3s_ease-out]\">\n {error}\n </p>\n )}\n </div>\n );\n}\n","import { useState } from 'react';\nimport { Paperclip, Download, ExternalLink } from 'lucide-react';\nimport type { WidgetProps } from './index';\n\n/**\n * Attachment widget — readOnly display of a binary value captured earlier\n * (typically by the file-upload widget): a data URL or a fetchable URL.\n * Declared as `x-lt-widget: \"attachment\"` (`\"image\"` is an accepted alias).\n *\n * Type dispatch keeps rendering safe:\n * image/* — inline constrained preview, click for full size (the <img>\n * context is script-inert, so data URLs are safe here)\n * everything else — a labeled open/download affordance, NEVER embedded as a\n * document (inlining arbitrary data: content is an XSS vector)\n */\n\ntype Kind =\n | { kind: 'none' }\n | { kind: 'image'; src: string }\n | { kind: 'file'; href: string; label: string; isData: boolean };\n\nconst IMAGE_EXT = /\\.(png|jpe?g|gif|webp|avif|bmp|svg)(\\?.*)?$/i;\n\nfunction classify(value: string): Kind {\n const v = value.trim();\n if (!v) return { kind: 'none' };\n\n const dataMime = /^data:([^;,]+)[;,]/.exec(v)?.[1]?.toLowerCase();\n if (dataMime) {\n if (dataMime.startsWith('image/')) return { kind: 'image', src: v };\n const label = dataMime === 'application/pdf' ? 'PDF' : dataMime;\n return { kind: 'file', href: v, label, isData: true };\n }\n\n if (/^https?:\\/\\//i.test(v)) {\n if (IMAGE_EXT.test(v)) return { kind: 'image', src: v };\n const ext = /\\.([a-z0-9]{2,5})(\\?.*)?$/i.exec(v)?.[1]?.toUpperCase();\n return { kind: 'file', href: v, label: ext ?? 'attachment', isData: false };\n }\n\n return { kind: 'none' };\n}\n\nexport function AttachmentWidget({ fieldKey, value, schema }: WidgetProps) {\n const [expanded, setExpanded] = useState(false);\n const att = classify(value ?? '');\n const label = fieldKey.replace(/[_-]/g, ' ');\n const helperText = schema?.description as string | undefined;\n\n const head = (\n <>\n <label className=\"text-2xs font-semibold uppercase tracking-widest text-text-tertiary\">\n {label}\n </label>\n {helperText && <p className=\"text-2xs text-text-tertiary mt-0.5\">{helperText}</p>}\n </>\n );\n\n if (att.kind === 'none') {\n return (\n <div>\n {head}\n <p className=\"text-xs text-text-quaternary italic mt-1\">No attachment</p>\n </div>\n );\n }\n\n if (att.kind === 'image') {\n return (\n <div>\n {head}\n <div className=\"mt-1\">\n <button\n type=\"button\"\n onClick={() => setExpanded(true)}\n className=\"block rounded-[0.125em] border border-surface-border overflow-hidden hover:border-accent transition-colors\"\n title=\"View full size\"\n >\n <img\n src={att.src}\n alt={fieldKey.replace(/[_-]/g, ' ')}\n className=\"max-h-48 max-w-full object-contain\"\n data-testid={`attachment-image-${fieldKey}`}\n />\n </button>\n {expanded && (\n <div\n className=\"fixed inset-0 z-[100] bg-text-primary/60 backdrop-blur-sm flex items-center justify-center p-8 cursor-zoom-out\"\n onClick={() => setExpanded(false)}\n role=\"dialog\"\n aria-modal=\"true\"\n aria-label={`${label} — full size`}\n >\n <img src={att.src} alt={label} className=\"max-h-[90vh] max-w-[90vw] object-contain\" />\n </div>\n )}\n </div>\n </div>\n );\n }\n\n // Non-image: safe open/download only — the content is never embedded.\n return (\n <div>\n {head}\n <div className=\"mt-1\">\n <a\n href={att.href}\n {...(att.isData\n ? { download: `${fieldKey}.${att.label === 'PDF' ? 'pdf' : 'bin'}` }\n : { target: '_blank', rel: 'noopener noreferrer' })}\n className=\"inline-flex items-center gap-1.5 text-xs text-accent hover:text-accent-hover transition-colors\"\n data-testid={`attachment-link-${fieldKey}`}\n >\n <Paperclip className=\"w-3.5 h-3.5\" strokeWidth={1.5} />\n {att.isData ? `Download ${att.label}` : `Open ${att.label}`}\n {att.isData\n ? <Download className=\"w-3 h-3\" strokeWidth={1.5} />\n : <ExternalLink className=\"w-3 h-3\" strokeWidth={1.5} />}\n </a>\n </div>\n </div>\n );\n}\n","import { Link } from 'react-router-dom';\nimport { ExternalLink } from 'lucide-react';\nimport { interpolateHelp } from '../../../lib/x-lt-help';\nimport { FieldLabel, FieldHelper } from '../resolver-form/FieldChrome';\nimport type { WidgetProps } from './index';\n\n/**\n * Link widget — a named navigation link whose URL is a `{{domain.path}}`\n * template resolved at render time from the escalation context.\n *\n * Schema usage:\n * \"x-lt-widget\": \"link\"\n * \"x-lt-href\": \"/escalations/available?role=foo&facets={\\\"orderId\\\":\\\"{{metadata.orderId}}\\\"}\"\n * \"title\": \"Human-readable label\"\n * \"description\": \"One-line instruction text\"\n *\n * URL behaviour:\n * Paths starting with \"/\" navigate inside the dashboard (React Router <Link>).\n * Anything else opens in a new tab with rel=\"noreferrer\".\n *\n * This widget is display-only — it produces no resolver payload value and must\n * never appear in the schema's `required` array.\n */\nexport function LinkWidget({ fieldKey, schema, escalationContext }: WidgetProps) {\n const hrefTemplate = (schema?.['x-lt-href'] as string | undefined) ?? '';\n const href = hrefTemplate && escalationContext\n ? interpolateHelp(hrefTemplate, escalationContext)\n : hrefTemplate;\n\n const label = (schema?.title as string | undefined) ?? (schema?.description as string | undefined) ?? 'Open';\n const helperText = schema?.description as string | undefined;\n const isInternal = href.startsWith('/');\n const isEmpty = !href.trim();\n\n return (\n <div data-field-key={fieldKey}>\n <FieldLabel>{label}</FieldLabel>\n {helperText && <FieldHelper>{helperText}</FieldHelper>}\n <div className=\"mt-1\">\n {isEmpty ? (\n <span className=\"text-xs text-text-quaternary italic\">No link configured</span>\n ) : isInternal ? (\n <Link\n to={href}\n className=\"inline-flex items-center gap-1 text-xs text-accent hover:text-accent-hover transition-colors\"\n data-testid={`link-widget-${fieldKey}`}\n >\n {label}\n <ExternalLink className=\"w-3 h-3 shrink-0\" strokeWidth={1.5} />\n </Link>\n ) : (\n <a\n href={href}\n target=\"_blank\"\n rel=\"noreferrer\"\n className=\"inline-flex items-center gap-1 text-xs text-accent hover:text-accent-hover transition-colors\"\n data-testid={`link-widget-${fieldKey}`}\n >\n {label}\n <ExternalLink className=\"w-3 h-3 shrink-0\" strokeWidth={1.5} />\n </a>\n )}\n </div>\n </div>\n );\n}\n","import { Link } from 'react-router-dom';\nimport { ArrowUpRight } from 'lucide-react';\n\n/**\n * The one affordance for opening an embedded row's detail page — a clear\n * icon-in-a-button, not a bare glyph, so the gesture reads as \"open this\". The\n * tooltip stays generic (\"View details\") rather than naming the record kind, so\n * the same control fits any embed. Non-focusable: the row/card click and the\n * canned actions carry the keyboard path; this is a pointer shortcut.\n */\nexport function OpenDetailButton({ to, className = '' }: { to: string; className?: string }) {\n return (\n <Link\n to={to}\n title=\"View details\"\n tabIndex={-1}\n className={`inline-flex items-center justify-center w-6 h-6 shrink-0 rounded border border-surface-border text-accent/70 hover:text-accent hover:border-accent/60 hover:bg-accent/5 transition-colors ${className}`}\n >\n <ArrowUpRight className=\"w-3.5 h-3.5\" strokeWidth={2} />\n <span className=\"sr-only\">View details</span>\n </Link>\n );\n}\n","import { OpenDetailButton } from './OpenDetailButton';\n\nimport { interpolateHelp } from '../../../lib/x-lt-help';\nimport { getDeep } from '../../../lib/x-lt-bind';\nimport { formatAgoCompact } from '../../../lib/format';\nimport { useEscalation } from '../../../api/escalations';\nimport { rowContext } from '../EscalationListView';\nimport { FieldLabel, FieldHelper } from '../resolver-form/FieldChrome';\nimport { StatusBadge } from '../../common/display/StatusBadge';\nimport type { WidgetProps } from './index';\nimport type { ShowIfContext } from '../../../lib/x-lt-show-if';\n\ninterface FieldDef { label: string; value: string; format?: string }\n\nconst EM_DASH = '—';\n\nfunction resolveSourceId(\n sourcePath: string | undefined,\n escalationContext: ShowIfContext | undefined,\n): string {\n if (!sourcePath || !escalationContext) return '';\n const dot = sourcePath.indexOf('.');\n if (dot === -1) return '';\n const domain = sourcePath.slice(0, dot) as keyof ShowIfContext;\n const path = sourcePath.slice(dot + 1);\n try {\n const v = getDeep(escalationContext[domain] as unknown, path);\n return typeof v === 'string' ? v : '';\n } catch {\n return '';\n }\n}\n\nfunction renderFieldValue(raw: string, format?: string): string {\n if (!raw || raw === EM_DASH) return EM_DASH;\n if (format === 'age') {\n const d = new Date(raw);\n return Number.isNaN(d.getTime()) ? raw : formatAgoCompact(raw);\n }\n return raw;\n}\n\n/**\n * Escalation widget — embeds a single escalation record inline in the form as\n * a compact card. The escalation ID is resolved from a `domain.path` declared\n * in `x-lt-source`; the card's detail rows are configured via `x-lt-fields`.\n *\n * Schema usage:\n * \"x-lt-widget\": \"escalation\"\n * \"x-lt-source\": \"metadata.parent_escalation_id\" (any domain.path → ID)\n * \"x-lt-fields\": [ (optional, any of escalation's data)\n * { \"label\": \"Order\", \"value\": \"{{metadata.orderId}}\" },\n * { \"label\": \"Decision\", \"value\": \"{{resolver.decision}}\" },\n * { \"label\": \"Age\", \"value\": \"{{escalation.created_at}}\", \"format\": \"age\" }\n * ]\n * \"title\": \"Card heading label\"\n * \"description\": \"One-line instruction text\"\n *\n * `x-lt-fields` token values resolve against the *embedded* escalation's own\n * context (its escalation row, metadata, envelope, payload, resolver) — not the\n * parent form's context. Same domain/path convention as x-lt-active.fields.\n *\n * Display-only — produces no resolver payload and must not appear in `required`.\n */\nexport function EscalationWidget({ fieldKey, schema, escalationContext }: WidgetProps) {\n const sourcePath = schema?.['x-lt-source'] as string | undefined;\n const fields = (schema?.['x-lt-fields'] as FieldDef[] | undefined) ?? [];\n const label = (schema?.title as string | undefined) ?? 'Linked escalation';\n const helperText = schema?.description as string | undefined;\n\n const id = resolveSourceId(sourcePath, escalationContext);\n const { data: esc, isLoading, isError } = useEscalation(id);\n\n return (\n <div data-field-key={fieldKey}>\n <FieldLabel>{label}</FieldLabel>\n {helperText && <FieldHelper>{helperText}</FieldHelper>}\n <div className=\"mt-1\">\n {!id || isError ? (\n <p className=\"text-xs text-text-quaternary italic\" data-testid={`escalation-widget-empty-${fieldKey}`}>\n No linked record\n </p>\n ) : isLoading ? (\n <EscalationCardSkeleton />\n ) : esc ? (\n <EscalationCard esc={esc} fields={fields} fieldKey={fieldKey} />\n ) : (\n <p className=\"text-xs text-text-quaternary italic\">No linked record</p>\n )}\n </div>\n </div>\n );\n}\n\nfunction EscalationCard({\n esc,\n fields,\n fieldKey,\n}: {\n esc: ReturnType<typeof useEscalation>['data'];\n fields: FieldDef[];\n fieldKey: string;\n}) {\n if (!esc) return null;\n const ctx = rowContext(esc);\n\n return (\n <div\n className=\"border-l-2 border-accent-faint pl-3 py-2 space-y-2\"\n data-testid={`escalation-widget-card-${fieldKey}`}\n >\n {/* Header: type + status */}\n <div className=\"flex items-center gap-2 flex-wrap\">\n <span className=\"text-2xs font-semibold uppercase tracking-wider text-text-secondary\">\n {esc.type}{esc.subtype && esc.subtype !== esc.type ? ` · ${esc.subtype}` : ''}\n </span>\n <StatusBadge status={esc.status} />\n </div>\n\n {/* Description */}\n {esc.description && (\n <p className=\"text-xs text-text-primary leading-snug\">{esc.description}</p>\n )}\n\n {/* x-lt-fields facts — same dictionary visual as DictionaryList */}\n {fields.length > 0 && (\n <dl className=\"grid grid-cols-[auto_1fr] gap-x-4 gap-y-0.5\">\n {fields.map((f) => {\n const raw = interpolateHelp(f.value, ctx);\n const display = renderFieldValue(raw, f.format);\n return (\n <div key={f.label} className=\"contents\">\n <dt className=\"text-2xs text-text-tertiary whitespace-nowrap\">{f.label}</dt>\n <dd className=\"text-2xs text-text-primary\">{display}</dd>\n </div>\n );\n })}\n </dl>\n )}\n\n {/* Footer: role, age, detail link */}\n <div className=\"flex items-center justify-between gap-2\">\n <span className=\"text-2xs text-text-quaternary\">\n {esc.role} · {formatAgoCompact(esc.created_at)}\n </span>\n <OpenDetailButton to={`/escalations/detail/${esc.id}`} />\n </div>\n </div>\n );\n}\n\nfunction EscalationCardSkeleton() {\n return (\n <div className=\"border-l-2 border-accent-faint pl-3 py-2 space-y-2 animate-pulse\">\n <div className=\"h-3 w-32 bg-surface-sunken rounded\" />\n <div className=\"h-3 w-48 bg-surface-sunken rounded\" />\n <div className=\"h-3 w-24 bg-surface-sunken rounded\" />\n </div>\n );\n}\n","import { interpolateHelp } from './x-lt-help';\nimport type { ShowIfContext } from './x-lt-show-if';\n\n/**\n * The embedded escalation query shape shared by `x-lt-query` (escalation-list\n * widget) and `x-lt-submit-guard.query` (form-level submit gate). String\n * values inside `facets` support `{{domain.path}}` token interpolation against\n * the host escalation's context. Isomorphic: the dashboard renders embeds from\n * it, and the API layer enforces the submit gate from the identical mapping.\n *\n * `assigned` is the ownership scope. Ownership is not a separate list — it is\n * one more dimension of the same faceted query language the escalation API\n * composes server-side (\"claimed\" is the implied status: pending, held, claim\n * window live):\n * - `\"me\"` — rows claimed by the viewing user (the walk case: I walk what I own)\n * - `\"any\"` — all matching rows regardless of claim state\n * - omitted — available rows only (unclaimed, or claim window lapsed)\n */\nexport interface EmbedQuery {\n role?: string;\n status?: string;\n facets?: Record<string, string>;\n limit?: number;\n assigned?: 'me' | 'any';\n /** Superseded by `assigned`; honored only when `assigned` is omitted. */\n available?: boolean;\n}\n\n/** Interpolate `{{domain.path}}` tokens in every string value of the facets map. */\nexport function resolveQueryFacets(\n facets: Record<string, string> | undefined,\n ctx: ShowIfContext,\n): Record<string, unknown> {\n if (!facets) return {};\n const resolved: Record<string, unknown> = {};\n for (const [k, v] of Object.entries(facets)) {\n resolved[k] = typeof v === 'string' ? interpolateHelp(v, ctx) : v;\n }\n return resolved;\n}\n\n/** The escalation-query params an EmbedQuery resolves to — the exact input\n * shape of `useEscalations`, so every embed surface queries identically. */\nexport interface ScopedQueryParams {\n role?: string;\n status: string;\n facets: Record<string, unknown>;\n assigned_to?: string;\n available?: boolean;\n limit?: number;\n enabled: boolean;\n}\n\n/**\n * Resolve an EmbedQuery into concrete escalation-query params — the ONE\n * mapping every embed surface (escalation-list, x-lt-actions, x-lt-submit-guard)\n * consumes, so the visible rows and any count derived from the same query can\n * never disagree.\n *\n * Ownership scope translates into the faceted query language:\n * - `assigned: \"me\"` → `assigned_to = viewer AND available = false` — the\n * implied \"claimed\" status (pending + live claim window held by the viewer)\n * - `assigned: \"any\"` → no ownership constraint\n * - omitted → `available = true` (the unclaimed pool; a declared\n * legacy `available` value is honored)\n *\n * When `assigned: \"me\"` and no viewer id is supplied (a surface with no\n * resolving user, e.g. an MCP resolve), the scope cannot be evaluated —\n * `enabled` is false rather than silently widening to another scope.\n */\nexport function resolveScopedQuery(\n query: EmbedQuery,\n ctx: ShowIfContext,\n viewerId: string | undefined,\n): ScopedQueryParams {\n const facets = resolveQueryFacets(query.facets, ctx);\n const base: ScopedQueryParams = {\n role: query.role,\n status: query.status ?? 'pending',\n facets,\n limit: query.limit,\n enabled: !!(query.role || Object.keys(facets).length),\n };\n if (query.assigned === 'me') {\n return { ...base, assigned_to: viewerId, available: false, enabled: base.enabled && !!viewerId };\n }\n if (query.assigned === 'any') {\n return base;\n }\n return { ...base, available: query.available ?? true };\n}\n","import { useState } from 'react';\nimport { OpenDetailButton } from './OpenDetailButton';\nimport { interpolateHelp } from '../../../lib/x-lt-help';\nimport { formatAgoCompact } from '../../../lib/format';\nimport { rowContext } from '../EscalationListView';\nimport { useEscalations, useResolveEscalation } from '../../../api/escalations';\nimport { useAuth } from '../../../hooks/useAuth';\nimport { FieldLabel, FieldHelper } from '../resolver-form/FieldChrome';\nimport { resolveScopedQuery, type EmbedQuery } from '../../../lib/x-lt-query';\nimport { schemaNeedsEnvelope } from '../../../lib/schema-needs-envelope';\nimport type { WidgetProps } from './index';\nimport type { ShowIfContext } from '../../../lib/x-lt-show-if';\nimport type { LTEscalationRecord } from '../../../api/types';\n\ninterface ColumnDef { label: string; value: string; format?: string }\n\n/**\n * An inline row action: fires a canned resolve against the row through the\n * standard resolve endpoint — RBAC and enforce_schema validation apply\n * server-side exactly as a full-form resolve. String leaves inside\n * `resolverPayload` (and `confirm`) interpolate `{{domain.path}}` tokens\n * against the row's own context; booleans and numbers pass through typed.\n */\ninterface ActionDef {\n label: string;\n resolverPayload: Record<string, unknown>;\n /** Optional confirm prompt shown before firing; tokens interpolate per row. */\n confirm?: string;\n}\n\nconst DEFAULT_COLUMNS: ColumnDef[] = [\n { label: 'Description', value: '{{escalation.description}}' },\n { label: 'Role', value: '{{escalation.role}}' },\n { label: 'Age', value: '{{escalation.created_at}}', format: 'age' },\n];\n\nconst EM_DASH = '—';\n\nfunction renderValue(raw: string, format?: string): string {\n if (!raw || raw === EM_DASH) return EM_DASH;\n if (format === 'age') {\n const d = new Date(raw);\n return Number.isNaN(d.getTime()) ? raw : formatAgoCompact(raw);\n }\n return raw;\n}\n\n/** Deep-walk a payload template: string leaves interpolate `{{domain.path}}`\n * tokens against the row context; every other type passes through typed. */\nfunction interpolatePayload(value: unknown, ctx: ShowIfContext): unknown {\n if (typeof value === 'string') return interpolateHelp(value, ctx);\n if (Array.isArray(value)) return value.map((v) => interpolatePayload(v, ctx));\n if (value && typeof value === 'object') {\n return Object.fromEntries(\n Object.entries(value).map(([k, v]) => [k, interpolatePayload(v, ctx)]),\n );\n }\n return value;\n}\n\n/**\n * Escalation list widget — embeds a compact list of escalations inline in the\n * form, driven by a facet query declared in `x-lt-query`. String values inside\n * `x-lt-query.facets` support `{{domain.path}}` token interpolation.\n *\n * Schema usage:\n * \"x-lt-widget\": \"escalation-list\"\n * \"x-lt-query\": {\n * \"role\": \"rel-originator\",\n * \"facets\": { \"customerId\": \"{{metadata.customerId}}\" },\n * \"status\": \"pending\",\n * \"limit\": 5\n * }\n * \"x-lt-columns\": [ (optional)\n * { \"label\": \"Order\", \"value\": \"{{metadata.orderId}}\" },\n * { \"label\": \"Age\", \"value\": \"{{escalation.created_at}}\", \"format\": \"age\" }\n * ]\n * \"title\": \"List heading\"\n * \"description\": \"One-line instruction text\"\n * \"x-lt-actions\": [ (optional)\n * { \"label\": \"Bagged ✓\",\n * \"resolverPayload\": { \"approved\": true, \"checks\": { \"bagged\": true } },\n * \"confirm\": \"Bag {{metadata.orderId}}?\" }\n * ]\n *\n * Column `value` strings use the same `{{domain.path}}` token convention as\n * `x-lt-active.fields` and `x-lt-columns` in list schemas — tokens resolve\n * against each displayed escalation's own row context.\n *\n * When `x-lt-columns` is absent, falls back to three default columns:\n * description, role, age.\n *\n * Produces no resolver payload for the PARENT form and must not appear in\n * `required`. `x-lt-actions` buttons resolve the ROW through the standard\n * resolve endpoint — server-side RBAC and enforce_schema apply; a rejected\n * canned resolve surfaces its message inline and the row's detail link\n * remains the full-form path.\n */\nexport function EscalationListWidget({ fieldKey, schema, escalationContext }: WidgetProps) {\n const rawQuery = (schema?.['x-lt-query'] as EmbedQuery | undefined) ?? {};\n const columns = (schema?.['x-lt-columns'] as ColumnDef[] | undefined) ?? DEFAULT_COLUMNS;\n const actions = (schema?.['x-lt-actions'] as ActionDef[] | undefined) ?? [];\n const label = (schema?.title as string | undefined) ?? 'Related items';\n const helperText = schema?.description as string | undefined;\n\n const ctx = escalationContext ?? {};\n const { user } = useAuth();\n\n // ONE shared mapping (resolveScopedQuery) turns x-lt-query into concrete\n // escalation params — the same call x-lt-submit-guard makes, so the visible\n // rows and the guard's count evaluate the identical scope.\n const scoped = resolveScopedQuery(rawQuery, ctx, user?.userId);\n\n const { data, isLoading } = useEscalations({\n role: scoped.role,\n status: scoped.status,\n facets: scoped.facets,\n assigned_to: scoped.assigned_to,\n available: scoped.available,\n limit: scoped.limit ?? 5,\n enabled: scoped.enabled,\n include: schemaNeedsEnvelope({ columns, actions }) ? 'envelope' : undefined,\n });\n\n const escalations = data?.escalations ?? [];\n\n const resolve = useResolveEscalation();\n const [rowErrors, setRowErrors] = useState<Record<string, string>>({});\n const [pendingRow, setPendingRow] = useState<string | null>(null);\n\n const fireAction = async (esc: LTEscalationRecord, action: ActionDef) => {\n const rowCtx = rowContext(esc);\n if (action.confirm && !window.confirm(interpolateHelp(action.confirm, rowCtx))) return;\n setPendingRow(esc.id);\n setRowErrors((prev) => ({ ...prev, [esc.id]: '' }));\n try {\n await resolve.mutateAsync({\n id: esc.id,\n resolverPayload: interpolatePayload(action.resolverPayload, rowCtx) as Record<string, unknown>,\n });\n } catch (err) {\n setRowErrors((prev) => ({ ...prev, [esc.id]: (err as Error).message }));\n } finally {\n setPendingRow(null);\n }\n };\n\n return (\n <div data-field-key={fieldKey}>\n <FieldLabel>{label}</FieldLabel>\n {helperText && <FieldHelper>{helperText}</FieldHelper>}\n <div className=\"mt-1\" data-testid={`escalation-list-widget-${fieldKey}`}>\n {isLoading ? (\n <ListSkeleton columns={columns.length} />\n ) : (\n <EmbedTable\n escalations={escalations}\n columns={columns}\n fieldKey={fieldKey}\n actions={actions}\n onAction={fireAction}\n pendingRow={pendingRow}\n rowErrors={rowErrors}\n />\n )}\n </div>\n </div>\n );\n}\n\nfunction EmbedTable({\n escalations,\n columns,\n fieldKey,\n actions,\n onAction,\n pendingRow,\n rowErrors,\n}: {\n escalations: LTEscalationRecord[];\n columns: ColumnDef[];\n fieldKey: string;\n actions: ActionDef[];\n onAction: (esc: LTEscalationRecord, action: ActionDef) => void;\n pendingRow: string | null;\n rowErrors: Record<string, string>;\n}) {\n if (escalations.length === 0) {\n return (\n <p className=\"text-xs text-text-quaternary italic py-1\" data-testid={`escalation-list-empty-${fieldKey}`}>\n No items found\n </p>\n );\n }\n\n return (\n <table className=\"w-full text-xs border-collapse\" data-testid={`escalation-list-table-${fieldKey}`}>\n <thead>\n <tr className=\"border-b border-surface-border\">\n {columns.map((col) => (\n <th\n key={col.label}\n className=\"text-left text-2xs font-semibold uppercase tracking-wider text-text-tertiary pb-1 pr-3 last:pr-0\"\n >\n {col.label}\n </th>\n ))}\n {actions.length > 0 && <th className=\"w-px\" />}\n <th className=\"w-8\" />\n </tr>\n </thead>\n <tbody>\n {escalations.map((esc) => {\n const ctx = rowContext(esc);\n const error = rowErrors[esc.id];\n return (\n <tr\n key={esc.id}\n className=\"border-b border-surface-border/50 last:border-0 hover:bg-surface-sunken/50 transition-colors\"\n >\n {columns.map((col) => {\n const raw = interpolateHelp(col.value, ctx);\n const display = renderValue(raw, col.format);\n return (\n <td key={col.label} className=\"py-1 pr-3 last:pr-0 text-text-primary align-top\">\n {display}\n </td>\n );\n })}\n {actions.length > 0 && (\n <td className=\"py-1 pr-2 align-top whitespace-nowrap\">\n {actions.map((action) => (\n <button\n key={action.label}\n type=\"button\"\n onClick={() => onAction(esc, action)}\n disabled={pendingRow === esc.id}\n className=\"px-2 py-0.5 text-2xs font-medium text-accent border border-accent/40 rounded hover:bg-accent/10 disabled:opacity-40 disabled:cursor-default transition-colors ml-1 first:ml-0\"\n data-testid={`escalation-list-action-${esc.id}`}\n >\n {action.label}\n </button>\n ))}\n {error && (\n <p className=\"text-2xs text-status-error mt-0.5 whitespace-normal max-w-[16rem]\" data-testid={`escalation-list-action-error-${esc.id}`}>\n {error}\n </p>\n )}\n </td>\n )}\n <td className=\"py-1 pl-2 align-top\">\n <OpenDetailButton to={`/escalations/detail/${esc.id}`} />\n </td>\n </tr>\n );\n })}\n </tbody>\n </table>\n );\n}\n\nfunction ListSkeleton({ columns }: { columns: number }) {\n return (\n <div className=\"space-y-1.5 animate-pulse\">\n {[0, 1, 2].map((i) => (\n <div key={i} className=\"flex gap-4\">\n {Array.from({ length: columns }, (_, j) => (\n <div key={j} className=\"h-3 bg-surface-sunken rounded flex-1\" />\n ))}\n </div>\n ))}\n </div>\n );\n}\n","import type { ComponentType } from 'react';\nimport { FileUploadWidget } from './FileUploadWidget';\nimport { CodeEditorWidget } from './CodeEditorWidget';\nimport { SignatureWidget } from './SignatureWidget';\nimport { RichTextWidget } from './RichTextWidget';\nimport { MarkdownWidget } from './MarkdownWidget';\nimport { ChecklistWidget } from './ChecklistWidget';\nimport { AttachmentWidget } from './AttachmentWidget';\nimport { LinkWidget } from './LinkWidget';\nimport { EscalationWidget } from './EscalationWidget';\nimport { EscalationListWidget } from './EscalationListWidget';\nimport type { ShowIfContext } from '../../../lib/x-lt-show-if';\n\nexport interface WidgetProps {\n fieldKey: string;\n value: string;\n onChange: (v: string) => void;\n schema?: Record<string, unknown>;\n /** Escalation context — used by widgets that read from envelope/metadata/payload at render time. */\n escalationContext?: ShowIfContext;\n /** Whether this field is listed in the schema's required array. */\n isRequired?: boolean;\n /** Whether the user has attempted to submit — triggers required/validation display in widgets. */\n submitAttempted?: boolean;\n /** Validation error to display inside the widget. */\n error?: string;\n}\n\n/**\n * Registry of custom widgets referenced via `x-lt-widget` in JSON Schema.\n * String-typed fields receive value directly; object-typed fields are\n * JSON-serialized into the widget and parsed back on change (see FieldRow).\n */\nexport const WIDGET_MAP: Record<string, ComponentType<WidgetProps>> = {\n 'file-upload': FileUploadWidget,\n 'code-editor': CodeEditorWidget,\n 'signature': SignatureWidget,\n 'rich-text': RichTextWidget,\n 'markdown': MarkdownWidget,\n 'checklist': ChecklistWidget,\n // Attachment renders a captured binary (data URL / fetchable URL): images\n // inline, everything else as a safe open/download link. \"image\" is an alias\n // so schemas can name the constrained intent.\n 'attachment': AttachmentWidget,\n 'image': AttachmentWidget,\n // Embed and navigation — display-only; produce no resolver payload.\n 'link': LinkWidget,\n 'escalation': EscalationWidget,\n 'escalation-list': EscalationListWidget,\n};\n","/**\n * Layout cell partitioning for the schema-driven resolver form.\n *\n * A section's fields render as a sequence of cells:\n * - `dictionary` — consecutive read-only facts merged into one dense\n * definition list (`x-lt-display: \"dictionary\"` at field, section, or\n * schema level)\n * - `column-group` — consecutive fields sharing an `x-lt-column-group` name,\n * rendered as an inner two-column grid inside one cell of a two-column\n * layout (the 2×2 nesting level)\n * - `field` — everything else, one input per cell\n */\n\nexport type JsonValue =\n | string\n | number\n | boolean\n | null\n | JsonValue[]\n | { [key: string]: JsonValue };\n\nexport type FormEntry = [string, JsonValue];\n\nexport type FieldKind = 'string' | 'number' | 'integer' | 'boolean' | 'array' | 'object' | 'null';\nconst FIELD_KINDS = new Set<FieldKind>(['string', 'number', 'integer', 'boolean', 'array', 'object']);\n\n/** The control follows the declared `type`; the runtime value decides only when the schema declares none. */\nexport function declaredKind(fieldSchema: Record<string, unknown> | undefined, value: unknown): FieldKind {\n const declared = fieldSchema?.type;\n if (typeof declared === 'string' && FIELD_KINDS.has(declared as FieldKind)) return declared as FieldKind;\n if (value === null || value === undefined) return 'null';\n if (Array.isArray(value)) return 'array';\n const t = typeof value;\n if (t === 'number' || t === 'boolean' || t === 'string') return t;\n return 'object';\n}\n\nexport interface SectionOptions {\n display?: string;\n columns?: number;\n}\n\nexport type FormCell =\n | { kind: 'field'; entry: FormEntry }\n | { kind: 'dictionary'; entries: FormEntry[] }\n | { kind: 'column-group'; name: string; entries: FormEntry[] };\n\nconst DICTIONARY = 'dictionary';\n\n/** Widgets that render content blocks even when readOnly — never dictionary rows. */\nconst CONTENT_WIDGETS = new Set(['markdown', 'attachment', 'image']);\n\nexport function sectionOptionsFor(\n formSchema: Record<string, any> | null | undefined,\n sectionName: string | null,\n): SectionOptions | undefined {\n if (!sectionName) return undefined;\n const all = formSchema?.['x-lt-section-options'] as Record<string, SectionOptions> | undefined;\n const opts = all?.[sectionName];\n return opts && typeof opts === 'object' ? opts : undefined;\n}\n\n/**\n * A field renders as a dictionary row when it is read-only, is not a content\n * widget, and dictionary display is requested at the nearest level:\n * field `x-lt-display` > section options > schema-root `x-lt-display`.\n */\nexport function isDictionaryField(\n formSchema: Record<string, any> | null | undefined,\n sectionName: string | null,\n key: string,\n): boolean {\n const fieldSchema = formSchema?.properties?.[key] as Record<string, unknown> | undefined;\n if (fieldSchema?.readOnly !== true) return false;\n const widget = fieldSchema?.['x-lt-widget'];\n if (typeof widget === 'string' && CONTENT_WIDGETS.has(widget)) return false;\n\n const fieldDisplay = fieldSchema?.['x-lt-display'];\n if (typeof fieldDisplay === 'string') return fieldDisplay === DICTIONARY;\n const sectionDisplay = sectionOptionsFor(formSchema, sectionName)?.display;\n if (typeof sectionDisplay === 'string') return sectionDisplay === DICTIONARY;\n return formSchema?.['x-lt-display'] === DICTIONARY;\n}\n\nexport function partitionCells(\n entries: FormEntry[],\n formSchema: Record<string, any> | null | undefined,\n sectionName: string | null,\n layout: string | undefined,\n): FormCell[] {\n const cells: FormCell[] = [];\n for (const entry of entries) {\n const [key] = entry;\n const last = cells[cells.length - 1];\n\n if (isDictionaryField(formSchema, sectionName, key)) {\n if (last?.kind === 'dictionary') {\n last.entries.push(entry);\n } else {\n cells.push({ kind: 'dictionary', entries: [entry] });\n }\n continue;\n }\n\n const fieldSchema = formSchema?.properties?.[key] as Record<string, unknown> | undefined;\n const groupName = fieldSchema?.['x-lt-column-group'];\n if (layout === 'two-column' && typeof groupName === 'string' && groupName.trim()) {\n if (last?.kind === 'column-group' && last.name === groupName) {\n last.entries.push(entry);\n } else {\n cells.push({ kind: 'column-group', name: groupName, entries: [entry] });\n }\n continue;\n }\n\n cells.push({ kind: 'field', entry });\n }\n return cells;\n}\n","import type { ResolvedOption } from '../../../lib/x-lt-options';\nimport { FieldLabel, FieldHelper, FieldError, selectClass } from './FieldChrome';\nimport type { FieldControlProps } from './field-control-props';\nimport type { JsonValue } from './form-cells';\n\n/**\n * One choice from an option list. The submitted answer is the option VALUE\n * with its own type (a numeric or boolean option stays so). A value outside\n * the list shows the disabled Choose placeholder, and once a value is picked\n * there is no way back. With `x-lt-nullable` the placeholder stays enabled\n * and picking it submits null. An empty list (a cascade child whose parent\n * is unanswered) renders disabled until options arrive.\n */\nexport function SelectField({ value, options, nullable, fieldKey, label, helperText, isRequired, error, onBlur, ids, ariaProps, onChange }: FieldControlProps & {\n value: JsonValue;\n options: ResolvedOption[];\n nullable?: boolean;\n}) {\n const current = value === null || value === undefined || value === '' ? '' : String(value);\n const hasCurrent = options.some((opt) => String(opt.value) === current);\n return (\n <div>\n <FieldLabel isRequired={isRequired} htmlFor={ids.field}>{label}</FieldLabel>\n {helperText && <FieldHelper id={ids.help}>{helperText}</FieldHelper>}\n <select\n value={hasCurrent ? current : ''}\n disabled={options.length === 0}\n onChange={(e) => {\n const picked = options.find((opt) => String(opt.value) === e.target.value);\n onChange(picked ? picked.value : null);\n onBlur?.();\n }}\n onBlur={onBlur}\n data-field-key={fieldKey}\n className={selectClass(!!error)}\n {...ariaProps}\n >\n {(!hasCurrent || nullable) && <option value=\"\" disabled={!nullable}>Choose…</option>}\n {options.map((opt) => (\n <option key={String(opt.value)} value={String(opt.value)}>{opt.label}</option>\n ))}\n </select>\n <FieldError error={error} id={ids.error} />\n </div>\n );\n}\n","import { Check } from 'lucide-react';\nimport type { OptionValue, ResolvedOption } from '../../../lib/x-lt-options';\nimport { FieldLabel, FieldHelper, FieldError } from './FieldChrome';\nimport type { FieldControlProps } from './field-control-props';\nimport type { JsonValue } from './form-cells';\n\n/**\n * Pick any from an option list: chips, each a real checkbox. The submitted\n * value is the picked option values in list order. An empty list renders\n * disabled until options arrive.\n */\nexport function MultiSelectField({ value, options, fieldKey, label, helperText, isRequired, error, onBlur, ids, ariaProps, onChange }: FieldControlProps & {\n value: JsonValue;\n options: ResolvedOption[];\n}) {\n const picked = new Set<OptionValue>(Array.isArray(value) ? (value as OptionValue[]) : []);\n const toggle = (v: OptionValue) => {\n const next = new Set(picked);\n if (next.has(v)) next.delete(v); else next.add(v);\n onChange(options.filter((o) => next.has(o.value)).map((o) => o.value) as JsonValue);\n onBlur?.();\n };\n return (\n <div role=\"group\" aria-label={label} aria-required={isRequired || undefined} aria-invalid={error ? true : undefined} aria-describedby={ariaProps['aria-describedby']}>\n <FieldLabel isRequired={isRequired}>{label}</FieldLabel>\n {helperText && <FieldHelper id={ids.help}>{helperText}</FieldHelper>}\n {options.length === 0 ? (\n <p className=\"text-xs text-text-tertiary italic mt-1\">No options yet</p>\n ) : (\n <div className=\"flex flex-wrap gap-2 mt-2\">\n {options.map((opt, i) => {\n const checked = picked.has(opt.value);\n return (\n <label\n key={String(opt.value)}\n className={`inline-flex items-center gap-1.5 cursor-pointer select-none px-3.5 py-2 text-sm border transition-colors rounded-[var(--lt-radius-field)] ${\n checked\n ? 'bg-accent border-accent text-text-inverse'\n : error\n ? 'bg-surface-field border-status-error/60 text-status-error'\n : 'bg-surface-field border-surface-field-border text-text-secondary hover:border-accent hover:text-text-primary'\n }`}\n >\n <input\n type=\"checkbox\"\n checked={checked}\n onChange={() => toggle(opt.value)}\n className=\"sr-only\"\n data-testid={`multi-select-${fieldKey}-${String(opt.value)}`}\n {...(i === 0 ? { 'data-field-key': fieldKey, id: ids.field } : {})}\n />\n {checked && <Check className=\"w-3.5 h-3.5 shrink-0\" strokeWidth={2.5} />}\n {opt.label}\n </label>\n );\n })}\n </div>\n )}\n <FieldError error={error} id={ids.error} />\n </div>\n );\n}\n","import { useEffect, useState } from 'react';\nimport { FieldLabel, FieldHelper, FieldError, inputClass } from './FieldChrome';\nimport type { FieldControlProps } from './field-control-props';\nimport type { JsonValue } from './form-cells';\n\nfunction pretty(value: JsonValue): string {\n if (typeof value === 'string') return value;\n if (value === null || value === undefined) return '';\n return JSON.stringify(value, null, 2);\n}\n\nfunction parse(text: string): { ok: true; value: JsonValue } | { ok: false } {\n try {\n return { ok: true, value: JSON.parse(text) as JsonValue };\n } catch {\n return { ok: false };\n }\n}\n\n/**\n * Raw JSON for a list or map field. The text lives here while it is edited;\n * a valid parse emits the parsed value, empty text emits null, and text that\n * does not parse is emitted as-is so the shared pass reports Invalid JSON.\n * Typing never reformats; an outside change to the value resyncs the text.\n */\nexport function JsonField({ value, fieldKey, label, helperText, isRequired, error, onBlur, ids, ariaProps, onChange }: FieldControlProps & {\n value: JsonValue;\n}) {\n const [text, setText] = useState(() => pretty(value));\n\n useEffect(() => {\n if (typeof value === 'string') {\n if (value !== text) setText(value);\n return;\n }\n const parsed = parse(text);\n const same = parsed.ok && JSON.stringify(parsed.value) === JSON.stringify(value ?? null);\n if (!same && !(text.trim() === '' && value === null)) setText(pretty(value));\n // Resync only follows the value; the text is the source while typing.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [value]);\n\n const lines = text.split('\\n').length;\n return (\n <div>\n <FieldLabel isRequired={isRequired} htmlFor={ids.field}>{label}</FieldLabel>\n {helperText && <FieldHelper id={ids.help}>{helperText}</FieldHelper>}\n <textarea\n value={text}\n onChange={(e) => {\n const next = e.target.value;\n setText(next);\n if (next.trim() === '') { onChange(null); return; }\n const parsed = parse(next);\n onChange(parsed.ok ? parsed.value : next);\n }}\n onBlur={onBlur}\n spellCheck={false}\n data-field-key={fieldKey}\n rows={Math.min(14, Math.max(4, lines))}\n className={`${inputClass(!!error)} font-mono text-xs leading-relaxed`}\n {...ariaProps}\n />\n <FieldError error={error} id={ids.error} />\n </div>\n );\n}\n","import { WIDGET_MAP } from '../widgets';\nimport { type ShowIfContext } from '../../../lib/x-lt-show-if';\nimport { resolveFieldOptions } from '../../../lib/x-lt-options';\nimport { resolveCtxPath } from '../../../lib/ctx-path';\nimport { deriveFieldLabel } from '../../../lib/derive-field-label';\nimport { FieldLabel, FieldHelper, FieldError, inputClass } from './FieldChrome';\nimport { declaredKind, type JsonValue } from './form-cells';\nimport type { FieldControlProps } from './field-control-props';\nimport { SelectField } from './SelectField';\nimport { MultiSelectField } from './MultiSelectField';\nimport { JsonField } from './JsonField';\n\nconst FORMAT_INPUT_TYPES: Record<string, string> = {\n date: 'date',\n 'date-time': 'datetime-local',\n email: 'email',\n uri: 'url',\n};\nconst FORMAT_WIDTH: Record<string, string> = {\n date: 'max-w-48',\n 'date-time': 'max-w-64',\n};\n\n/**\n * Field row: the control follows the field's declared `type` and its tokens;\n * the stored value only fills it. The `data-field-key` attribute and\n * `lt-field-*` ids are load-bearing: the errors panel scroll-and-focus and\n * the test suite target them.\n */\nexport function FieldRow({ fieldKey, value, onChange, onBlur, schema, isRequired, isReadOnly, error, escalationContext, submitAttempted }: {\n fieldKey: string;\n value: JsonValue;\n onChange: (v: JsonValue) => void;\n onBlur?: () => void;\n schema?: Record<string, any> | null;\n isRequired?: boolean;\n isReadOnly?: boolean;\n error?: string;\n escalationContext?: ShowIfContext;\n submitAttempted?: boolean;\n}) {\n const fieldSchema = schema?.properties?.[fieldKey] as Record<string, any> | undefined;\n const label = deriveFieldLabel(fieldKey, fieldSchema);\n const widgetName = fieldSchema?.['x-lt-widget'] as string | undefined;\n const kind = declaredKind(fieldSchema, value);\n\n const fieldId = `lt-field-${fieldKey}`;\n const ids = { field: fieldId, help: `${fieldId}-help`, error: `${fieldId}-error` };\n const helperText = typeof fieldSchema?.description === 'string' && fieldSchema.description.length > 0\n ? fieldSchema.description\n : undefined;\n const ariaProps = {\n id: fieldId,\n 'aria-required': isRequired || undefined,\n 'aria-invalid': error ? true : undefined,\n 'aria-describedby': error ? ids.error : helperText ? ids.help : undefined,\n } as const;\n const control: FieldControlProps = { fieldKey, label, helperText, isRequired, error, onBlur, ids, ariaProps, onChange };\n\n // Content and embed widgets render even when readOnly; everything else reads as static text.\n const isMarkdown = widgetName === 'markdown' && typeof value === 'string';\n const isAttachment = (widgetName === 'attachment' || widgetName === 'image') && typeof value === 'string';\n const hasRegisteredWidget = !!(widgetName && widgetName in WIDGET_MAP);\n\n if (isReadOnly && !isMarkdown && !isAttachment && !hasRegisteredWidget) {\n const displayValue = value === null ? 'null'\n : typeof value === 'object' ? JSON.stringify(value, null, 2)\n : String(value);\n return (\n <div>\n <FieldLabel isRequired={isRequired}>{label}</FieldLabel>\n <p className=\"text-sm text-text-secondary mt-0.5 whitespace-pre-wrap\">{displayValue}</p>\n </div>\n );\n }\n\n if (widgetName === 'json' && (kind === 'array' || kind === 'object')) {\n return <JsonField {...control} value={value} />;\n }\n\n // The widget interface deals in strings; FieldRow owns the object/string\n // boundary by DECLARED type, so a stray string value heals on the next edit.\n if (widgetName && widgetName in WIDGET_MAP) {\n const Widget = WIDGET_MAP[widgetName];\n const widgetRequired = isRequired || fieldSchema?.['x-lt-require-all'] === true;\n const widgetProps = { fieldKey, schema: fieldSchema, escalationContext, isRequired: widgetRequired, submitAttempted, error };\n if (fieldSchema?.type === 'object') {\n const raw = typeof value === 'string'\n ? value\n : typeof value === 'object' && value !== null && !Array.isArray(value)\n ? JSON.stringify(value)\n : '';\n return (\n <Widget\n {...widgetProps}\n value={raw}\n onChange={(next) => { try { onChange(JSON.parse(next) as JsonValue); } catch { onChange(next); } }}\n />\n );\n }\n if (typeof value === 'string') {\n return <Widget {...widgetProps} value={value} onChange={(v) => onChange(v)} />;\n }\n if (typeof value === 'object' && value !== null && !Array.isArray(value)) {\n return (\n <Widget\n {...widgetProps}\n value={JSON.stringify(value)}\n onChange={(raw) => { try { onChange(JSON.parse(raw) as JsonValue); } catch { onChange(raw); } }}\n />\n );\n }\n }\n\n // Option lists: the static enum, an inline literal list, or a context path.\n // A list field becomes a multi-select only through its own x-lt-options. An\n // interpolated list that resolves to nothing yet renders disabled and\n // populates when the parent answer lands.\n const options = resolveFieldOptions(fieldSchema, escalationContext as Record<string, unknown> | undefined);\n if (kind === 'array') {\n if (options !== undefined && fieldSchema?.['x-lt-options'] !== undefined) {\n return <MultiSelectField {...control} value={value} options={options} />;\n }\n } else if (options !== undefined && kind !== 'object') {\n return <SelectField {...control} value={value} options={options} nullable={fieldSchema?.['x-lt-nullable'] === true} />;\n }\n\n switch (kind) {\n case 'boolean':\n return (\n <div>\n <label className=\"flex items-center gap-2 cursor-pointer\">\n <input\n type=\"checkbox\"\n checked={value === true}\n onChange={(e) => { onChange(e.target.checked); onBlur?.(); }}\n className=\"w-3.5 h-3.5 rounded accent-accent\"\n data-field-key={fieldKey}\n {...ariaProps}\n />\n <span className=\"text-2xs font-semibold uppercase tracking-wider text-text-secondary\">\n {label}\n {isRequired && <span className=\"text-status-error ml-0.5\">*</span>}\n </span>\n </label>\n {helperText && <FieldHelper id={ids.help}>{helperText}</FieldHelper>}\n <FieldError error={error} id={ids.error} />\n </div>\n );\n\n case 'number':\n case 'integer':\n // Numbers are short; the input holds a hand-sized width.\n return (\n <div>\n <FieldLabel isRequired={isRequired} htmlFor={fieldId}>{label}</FieldLabel>\n {helperText && <FieldHelper id={ids.help}>{helperText}</FieldHelper>}\n <input\n type=\"number\"\n value={typeof value === 'number' || typeof value === 'string' ? value : ''}\n onChange={(e) => onChange(parseFloat(e.target.value) || 0)}\n onBlur={onBlur}\n step=\"any\"\n data-field-key={fieldKey}\n className={`${inputClass(!!error)} max-w-48`}\n {...ariaProps}\n />\n <FieldError error={error} id={ids.error} />\n </div>\n );\n\n case 'string':\n return renderText(typeof value === 'string' ? value : value === null || value === undefined ? '' : String(value));\n\n case 'array':\n // Without an option list or the json widget a list is display only.\n if (!Array.isArray(value)) return renderText(value === null || value === undefined ? '' : String(value));\n return (\n <div>\n <FieldLabel isRequired={isRequired}>{label}</FieldLabel>\n <div className=\"flex flex-wrap gap-1.5 mt-1\">\n {value.map((item, i) => (\n <span key={i} className=\"px-2 py-0.5 text-2xs font-mono bg-surface-sunken rounded text-text-secondary\">\n {String(item)}\n </span>\n ))}\n </div>\n </div>\n );\n\n case 'object': {\n if (typeof value !== 'object' || value === null || Array.isArray(value)) {\n return renderText(value === null || value === undefined ? '' : String(value));\n }\n const entries = Object.entries(value);\n return (\n <div>\n <FieldLabel isRequired={isRequired}>{label}</FieldLabel>\n <div className=\"ml-4 mt-2 pl-4 border-l border-accent-faint space-y-3\">\n {entries.map(([k, v]) => (\n <FieldRow\n key={k}\n fieldKey={k}\n value={v}\n onChange={(updated) => onChange({ ...value, [k]: updated })}\n />\n ))}\n </div>\n </div>\n );\n }\n\n default:\n return (\n <div>\n <FieldLabel isRequired={isRequired}>{label}</FieldLabel>\n <p className=\"text-xs text-text-tertiary italic mt-1\">null</p>\n </div>\n );\n }\n\n function renderText(text: string) {\n const format = fieldSchema?.format as string | undefined;\n\n if (format === 'password') {\n return (\n <div>\n <FieldLabel isRequired={isRequired} htmlFor={fieldId}>{label}</FieldLabel>\n {helperText && <FieldHelper id={ids.help}>{helperText}</FieldHelper>}\n <input\n type=\"password\"\n value={text}\n onChange={(e) => onChange(e.target.value)}\n onBlur={onBlur}\n data-field-key={fieldKey}\n className={inputClass(!!error)}\n autoComplete=\"off\"\n {...ariaProps}\n />\n <FieldError error={error} id={ids.error} />\n </div>\n );\n }\n\n // Emails and urls fill the cell; dates hold a hand-sized width, like numbers.\n if (format && format in FORMAT_INPUT_TYPES) {\n return (\n <div>\n <FieldLabel isRequired={isRequired} htmlFor={fieldId}>{label}</FieldLabel>\n {helperText && <FieldHelper id={ids.help}>{helperText}</FieldHelper>}\n <input\n type={FORMAT_INPUT_TYPES[format]}\n value={text}\n onChange={(e) => onChange(e.target.value)}\n onBlur={onBlur}\n data-field-key={fieldKey}\n className={`${inputClass(!!error)} ${FORMAT_WIDTH[format] ?? ''}`}\n {...ariaProps}\n />\n <FieldError error={error} id={ids.error} />\n </div>\n );\n }\n\n // Explicit textarea format or long content.\n if (format === 'textarea' || text.length > 80) {\n const staticMax = fieldSchema?.maxLength as number | undefined;\n const dynamicMax = fieldSchema?.['x-lt-max-length'] as string | undefined;\n const dynamicValue = dynamicMax ? Number(resolveCtxPath(dynamicMax, escalationContext as Record<string, unknown> | undefined)) : NaN;\n const resolvedMax = staticMax ?? (Number.isFinite(dynamicValue) ? dynamicValue : undefined);\n const isOverMax = resolvedMax !== undefined && text.length > resolvedMax;\n return (\n <div>\n <FieldLabel isRequired={isRequired} htmlFor={fieldId}>{label}</FieldLabel>\n {helperText && <FieldHelper id={ids.help}>{helperText}</FieldHelper>}\n <textarea\n value={text}\n onChange={(e) => { onChange(e.target.value); onBlur?.(); }}\n onBlur={onBlur}\n data-field-key={fieldKey}\n className={`${inputClass(!!error)} leading-relaxed`}\n rows={Math.min(6, Math.max(3, Math.ceil(text.length / 60)))}\n {...ariaProps}\n />\n {resolvedMax !== undefined && (\n <p className={`text-2xs mt-0.5 text-right tabular-nums ${isOverMax ? 'text-status-error font-medium' : 'text-text-quaternary'}`}>\n {text.length} / {resolvedMax}\n </p>\n )}\n <FieldError error={error} id={ids.error} />\n </div>\n );\n }\n\n return (\n <div>\n <FieldLabel isRequired={isRequired} htmlFor={fieldId}>{label}</FieldLabel>\n {helperText && <FieldHelper id={ids.help}>{helperText}</FieldHelper>}\n <input\n type=\"text\"\n value={text}\n onChange={(e) => onChange(e.target.value)}\n onBlur={onBlur}\n data-field-key={fieldKey}\n className={inputClass(!!error)}\n {...ariaProps}\n />\n <FieldError error={error} id={ids.error} />\n </div>\n );\n }\n}\n","import { Fragment } from 'react';\nimport { type JsonValue } from './form-cells';\n\nexport interface DictionaryItem {\n key: string;\n label: string;\n value: JsonValue;\n}\n\n/**\n * Dense definition-list display for read-only label/value facts — the compact\n * alternative to full-height field rows. Labels sit beside values in a\n * max-content column so a run of short facts reads like a spec sheet, not a\n * form.\n *\n * The poster child of the responsive doctrine: geometry follows the\n * CONTAINER. The same pairs render as two pairs per row (≥ @dict-pairs),\n * one label|value pair per row (≥ @dict-inline), or label stacked over\n * value below that — however narrow a side panel squeezes the form.\n * Two-column mode fills ROW BY ROW, so the author's ordering controls\n * pairing (Left Qty beside Right Qty, Left first) in every geometry.\n */\nexport function DictionaryList({ items, columns = 1 }: {\n items: DictionaryItem[];\n columns?: number;\n}) {\n if (items.length === 0) return null;\n\n const gridCols = columns >= 2 && items.length > 1\n ? 'grid-cols-1 @dict-inline:grid-cols-[max-content_1fr] @dict-pairs:grid-cols-[max-content_1fr_max-content_1fr]'\n : 'grid-cols-1 @dict-inline:grid-cols-[max-content_1fr]';\n\n return (\n <div className=\"@container\">\n <dl className={`grid ${gridCols} items-baseline gap-x-6 @dict-pairs:gap-x-8 gap-y-1.5`}>\n {items.map(({ key, label, value }) => (\n <Fragment key={key}>\n {/* Stacked geometry clusters each label with its value. */}\n <dt className=\"text-2xs font-semibold uppercase tracking-wide text-text-secondary mt-2 first:mt-0 @dict-inline:mt-0\">\n {label}\n </dt>\n <dd className=\"text-sm text-text-primary break-words min-w-0\" data-field-key={key}>\n {formatDictionaryValue(value)}\n </dd>\n </Fragment>\n ))}\n </dl>\n </div>\n );\n}\n\nfunction formatDictionaryValue(value: JsonValue): string {\n if (value === null || value === undefined || value === '') return '—';\n if (typeof value === 'boolean') return value ? 'Yes' : 'No';\n if (typeof value === 'object') return JSON.stringify(value);\n return String(value);\n}\n","import { type ReactNode } from 'react';\nimport { deriveFieldLabel } from '../../../lib/derive-field-label';\nimport { DictionaryList } from './DictionaryList';\nimport {\n partitionCells,\n sectionOptionsFor,\n type FormEntry,\n type JsonValue,\n} from './form-cells';\n\n/**\n * One visual section of the resolver form: optional named chrome (accent rule,\n * sunken band, section header), then the section's fields laid out as cells —\n * dictionary runs, 2×2 column groups, and single fields.\n */\nexport function SectionGroup({ name, entries, formSchema, layout, renderField }: {\n name: string | null;\n entries: FormEntry[];\n formSchema: Record<string, any> | null;\n layout: string | undefined;\n renderField: (entry: FormEntry) => ReactNode;\n}) {\n const cells = partitionCells(entries, formSchema, name, layout);\n const options = sectionOptionsFor(formSchema, name);\n const dictionaryColumns = options?.columns ?? (layout === 'two-column' ? 2 : 1);\n\n const dictionaryItems = (dictEntries: FormEntry[]) =>\n dictEntries.map(([key, value]: [string, JsonValue]) => ({\n key,\n label: deriveFieldLabel(key, formSchema?.properties?.[key] as Record<string, unknown> | undefined),\n value,\n }));\n\n const renderCells = () =>\n cells.map((cell, i) => {\n if (cell.kind === 'dictionary') {\n return (\n <div key={`dict-${i}`} className={layout === 'two-column' ? 'col-span-full' : ''}>\n <DictionaryList items={dictionaryItems(cell.entries)} columns={dictionaryColumns} />\n </div>\n );\n }\n if (cell.kind === 'column-group') {\n // One cell of the outer two-column grid holding its own two columns —\n // the single extra nesting level (2×2). The cell is its own container:\n // it measures the half-width it actually gets, not the section.\n return (\n <div key={`group-${cell.name}-${i}`} className=\"@container\">\n <div className=\"grid grid-cols-1 @grp-cols:grid-cols-2 gap-x-4 gap-y-5\">\n {cell.entries.map((entry) => renderField(entry))}\n </div>\n </div>\n );\n }\n return renderField(cell.entry);\n });\n\n return (\n <div\n className={name\n // Sections are distinct surfaces on the page wash — white paper in\n // light themes, the deeper well at night — with field wells stepping\n // away from them. Theme-driven, never a hardcoded hex.\n ? 'border border-surface-border bg-surface-sunken rounded-[var(--lt-radius-section)] p-4 animate-[section-enter_0.25s_ease-out]'\n : ''}\n >\n {name && (\n <p className=\"mb-4 text-[1.40625rem] font-semibold tracking-wider text-heading [font-variant-caps:small-caps]\">\n {name}\n </p>\n )}\n {layout === 'two-column' ? (\n // Geometry follows the container: the grid splits when the SECTION\n // is wide enough, whatever the viewport says.\n <div className=\"@container\">\n <div className=\"grid grid-cols-1 @form-cols:grid-cols-2 gap-x-col-gap gap-y-5\">\n {renderCells()}\n </div>\n </div>\n ) : (\n <div className=\"space-y-5\">\n {renderCells()}\n </div>\n )}\n </div>\n );\n}\n","import { useState, useEffect, useCallback, type ReactNode } from 'react';\nimport { LockedFormFrame } from './LockedFormFrame';\nimport { HelpCircle } from 'lucide-react';\nimport { evaluateShowIf, isHiddenIfEmpty, type ShowIfContext } from '../../../lib/x-lt-show-if';\nimport { validateField } from '../../../lib/field-validator';\nimport { FieldRow } from './FieldRow';\nimport { SectionGroup } from './SectionGroup';\nimport { type FormEntry, type JsonValue } from './form-cells';\n\n/**\n * Renders a JSON object as an editable form with typed inputs.\n *\n * - Strings → text input (textarea if > 80 chars)\n * - Booleans → toggle switch\n * - Numbers → number input\n * - Null → disabled placeholder\n * - Objects → nested section\n * - Arrays of strings → tag display\n * - Keys starting with `_` → hidden (preserved in output)\n *\n * Calls `onChange` with the full JSON string on every edit.\n */\nexport function ResolverForm({ value, onChange, disabled, submitAttempted, escalationContext, onOpenHelp, onDisabledClick, disabledHint }: {\n value: string;\n onChange: (json: string) => void;\n disabled?: boolean;\n submitAttempted?: boolean;\n escalationContext?: ShowIfContext;\n /** Opens the Instructions panel view; renders a help icon when the schema carries authored help. */\n onOpenHelp?: () => void;\n /** Fires when the user clicks the locked form — the page points them at Claim. */\n onDisabledClick?: () => void;\n /** Cursor-following hint over the locked form naming the state or gesture. */\n disabledHint?: ReactNode;\n}) {\n const [data, setData] = useState<Record<string, JsonValue>>({});\n const [hidden, setHidden] = useState<Record<string, JsonValue>>({});\n const [formSchema, setFormSchema] = useState<Record<string, any> | null>(null);\n const [parseError, setParseError] = useState(false);\n const [touched, setTouched] = useState<Set<string>>(new Set());\n\n // Parse incoming JSON\n useEffect(() => {\n try {\n const parsed = JSON.parse(value);\n if (typeof parsed === 'object' && parsed !== null && !Array.isArray(parsed)) {\n const visible: Record<string, JsonValue> = {};\n const internal: Record<string, JsonValue> = {};\n for (const [k, v] of Object.entries(parsed)) {\n if (k.startsWith('_')) {\n internal[k] = v as JsonValue;\n } else {\n visible[k] = v as JsonValue;\n }\n }\n setData(visible);\n setHidden(internal);\n setFormSchema(\n internal._form_schema && typeof internal._form_schema === 'object'\n ? internal._form_schema as Record<string, any>\n : null,\n );\n setParseError(false);\n }\n } catch {\n setParseError(true);\n }\n }, [value]);\n\n const emitChange = useCallback((updated: Record<string, JsonValue>) => {\n setData(updated);\n onChange(JSON.stringify({ ...updated, ...hidden }, null, 2));\n }, [hidden, onChange]);\n\n const updateField = useCallback((key: string, val: JsonValue) => {\n emitChange({ ...data, [key]: val });\n }, [data, emitChange]);\n\n const markTouched = useCallback((key: string) => {\n setTouched((prev) => {\n if (prev.has(key)) return prev;\n const next = new Set(prev);\n next.add(key);\n return next;\n });\n }, []);\n\n if (parseError) {\n return (\n <p className=\"text-xs text-status-error\">\n Unable to parse resolver data as form. Use the JSON editor below.\n </p>\n );\n }\n\n const allEntries = Object.entries(data);\n if (allEntries.length === 0) {\n return (\n <p className=\"text-xs text-text-tertiary italic\">\n No resolver fields defined.\n </p>\n );\n }\n\n // Field ordering via x-lt-order\n const fieldOrder = formSchema?.['x-lt-order'] as string[] | undefined;\n const ordered = fieldOrder\n ? [...allEntries].sort((a, b) => {\n const ai = fieldOrder.indexOf(a[0]);\n const bi = fieldOrder.indexOf(b[0]);\n return (ai === -1 ? Infinity : ai) - (bi === -1 ? Infinity : bi);\n })\n : allEntries;\n\n // Merge current form data into the resolver domain so x-lt-showIf: 'resolver.field'\n // reacts to live edits — the parent context only carries the saved row state.\n const liveCtx: ShowIfContext = { ...(escalationContext ?? {}), resolver: data as Record<string, unknown>, input: data as Record<string, unknown> };\n\n // Conditional visibility via x-lt-showIf and x-lt-hide-if-empty\n const entries = ordered.filter(([key, val]) => {\n const fieldSchema = formSchema?.properties?.[key] as Record<string, unknown> | undefined;\n if (!evaluateShowIf(fieldSchema?.['x-lt-showIf'], liveCtx)) return false;\n return !isHiddenIfEmpty(fieldSchema, val);\n });\n\n const requiredFields = new Set(formSchema?.required as string[] ?? []);\n const layout = formSchema?.['x-lt-layout'] as string | undefined;\n const schemaTitle = formSchema?.title as string | undefined;\n const schemaDescription = formSchema?.description as string | undefined;\n const hasAuthoredHelp =\n typeof formSchema?.['x-lt-help'] === 'string' || typeof formSchema?.['x-lt-context'] === 'string';\n\n // Group entries by x-lt-section for labeled visual grouping.\n // Fields without x-lt-section or with an empty value form an unnamed group.\n type Section = { name: string | null; entries: FormEntry[] };\n const sectionGroups: Section[] = [];\n for (const entry of entries) {\n const [key] = entry;\n const fieldSchema = formSchema?.properties?.[key] as Record<string, unknown> | undefined;\n const sectionName = (fieldSchema?.['x-lt-section'] as string | undefined)?.trim() || null;\n const last = sectionGroups[sectionGroups.length - 1];\n if (!last || last.name !== sectionName) {\n sectionGroups.push({ name: sectionName, entries: [entry] });\n } else {\n last.entries.push(entry);\n }\n }\n\n const renderField = ([key, val]: FormEntry) => {\n const fieldSchema = formSchema?.properties?.[key] as Record<string, unknown> | undefined;\n const isReadOnly = fieldSchema?.readOnly === true;\n const span = (fieldSchema?.['x-lt-span'] as number) ?? 1;\n const isReq = requiredFields.has(key);\n const isTouched = touched.has(key) || !!submitAttempted;\n\n const error = validateField(val, fieldSchema, isReq, isTouched, liveCtx as Record<string, unknown>);\n\n return (\n <div\n key={key}\n className={`animate-[field-enter_0.2s_ease-out] ${layout === 'two-column' && span >= 2 ? 'col-span-full' : ''}`}\n >\n <FieldRow\n fieldKey={key}\n value={val}\n onChange={(v) => updateField(key, v)}\n onBlur={() => markTouched(key)}\n schema={formSchema}\n isRequired={isReq}\n isReadOnly={isReadOnly}\n error={error}\n escalationContext={liveCtx}\n submitAttempted={!!submitAttempted}\n />\n </div>\n );\n };\n\n // A locked form stays fully readable — no fade. `inert` (not just\n // pointer-events) locks the body for keyboard and assistive-tech users —\n // fields leave the tab order entirely — and makes it transparent to hit\n // testing, so a click anywhere on the locked form lands on the frame,\n // which reports the interaction and carries the cursor hint.\n // max-w-form: the form holds a readable measure on any monitor.\n const body = (\n <div\n className={disabled ? 'pointer-events-none' : undefined}\n inert={disabled || undefined}\n aria-disabled={disabled || undefined}\n >\n {schemaTitle && (\n <div className=\"mb-1 flex items-center gap-1.5\">\n <h3 className=\"heading-3\">{schemaTitle}</h3>\n {hasAuthoredHelp && onOpenHelp && (\n <button\n type=\"button\"\n onClick={onOpenHelp}\n title=\"Open instructions\"\n aria-label=\"Open instructions\"\n className=\"p-1 rounded-md text-text-tertiary hover:text-accent hover:bg-surface-hover transition-colors\"\n >\n <HelpCircle className=\"w-4 h-4\" strokeWidth={1.5} />\n </button>\n )}\n </div>\n )}\n {schemaDescription && (\n <p className=\"text-sm text-text-secondary leading-relaxed mb-6\">{schemaDescription}</p>\n )}\n\n <div className=\"space-y-8\">\n {sectionGroups.map((group, i) => (\n <SectionGroup\n key={group.name ?? `__s${i}`}\n name={group.name}\n entries={group.entries}\n formSchema={formSchema}\n layout={layout}\n renderField={renderField}\n />\n ))}\n </div>\n </div>\n );\n\n if (disabled) {\n return (\n <LockedFormFrame hint={disabledHint} onLockedClick={onDisabledClick}>\n {body}\n </LockedFormFrame>\n );\n }\n return <div className=\"pb-8 max-w-form\">{body}</div>;\n}\n"],"names":["seedFormJson","formSchema","prefillPayload","prefill","mapPayloadToForm","initial","key","def","zero","deriveFieldLabel","fieldSchema","title","words","w","isCapsToken","word","INTERPOLATION_PATTERN","hasInterpolation","token","resolveCtxPath","path","ctx","dot","root","getDeep","interpolatePath","template","unresolved","concrete","_match","rawPath","value","X_LT_OPTIONS","isScalar","v","isLiteralList","toOption","entry","o","resolveFieldOptions","staticEnum","options","paths","p","miss","sourcePath","resolved","cur","resolveChecklistItems","source","X_LT_DEFAULT_CHECKED","resolveChecklistDefault","currentValue","items","validateRequireAll","mandatory","i","state","incomplete","INVALID_JSON","isJsonWidget","isEditableList","plural","n","noun","validateFieldType","declared","validateFieldConstraints","allowed","validateListConstraints","validateMapConstraints","s","minLength","resolveNumericConstraint","maxLength","pattern","fmt","minimum","exclusiveMinimum","maximum","exclusiveMaximum","minItems","maxItems","itemSchema","err","entries","propertyNames","allowedKeys","unknown","k","ap","valueSchema","staticVal","dynamicPath","domain","domainObj","parts","validateField","isRequired","isTouched","vals","typeError","requireAll","isTruthy","asComparable","resolvePath","expr","HELP_DOMAINS","evaluateShowIf","condition","c","negate","neqAt","eqAt","isNeq","opAt","expected","known","matches","result","isHiddenIfEmpty","HINT_MS","LockedFormFrame","hint","onLockedClick","children","hintAt","setHintAt","useState","useEffect","timer","handleClick","e","x","prev","jsxs","jsx","Lock","FieldLabel","htmlFor","FieldHelper","id","FieldError","error","inputClass","hasError","selectClass","FileUploadWidget","fieldKey","onChange","schema","inputRef","useRef","accept","label","helperText","handleFile","useCallback","file","_a","reader","hasFile","CodeEditorWidget","language","handleKeyDown","target","start","end","updated","SignatureWidget","canvasRef","isDrawing","setIsDrawing","canvas","img","getPos","rect","scaleX","scaleY","startDraw","pos","draw","endDraw","clear","RichTextWidget","MarkdownWidget","tab","setTab","MarkdownRenderer","t","CHIP_LABEL_MAX","ChecklistWidget","escalationContext","submitAttempted","defaultJson","d","toggle","Fragment","explicitVariant","variant","checkedCount","item","focusId","checked","showItemError","Check","IMAGE_EXT","classify","dataMime","_b","ext","_d","_c","AttachmentWidget","expanded","setExpanded","att","head","Paperclip","Download","ExternalLink","LinkWidget","hrefTemplate","href","interpolateHelp","isInternal","isEmpty","Link","OpenDetailButton","to","className","ArrowUpRight","EM_DASH","resolveSourceId","renderFieldValue","raw","format","formatAgoCompact","EscalationWidget","fields","esc","isLoading","isError","useEscalation","EscalationCardSkeleton","EscalationCard","rowContext","StatusBadge","f","display","resolveQueryFacets","facets","resolveScopedQuery","query","viewerId","base","DEFAULT_COLUMNS","renderValue","interpolatePayload","EscalationListWidget","rawQuery","columns","actions","user","useAuth","scoped","data","useEscalations","schemaNeedsEnvelope","escalations","resolve","useResolveEscalation","rowErrors","setRowErrors","pendingRow","setPendingRow","fireAction","action","rowCtx","ListSkeleton","EmbedTable","onAction","col","_","j","WIDGET_MAP","FIELD_KINDS","declaredKind","DICTIONARY","CONTENT_WIDGETS","sectionOptionsFor","sectionName","all","opts","isDictionaryField","widget","fieldDisplay","sectionDisplay","partitionCells","layout","cells","last","groupName","SelectField","nullable","onBlur","ids","ariaProps","current","hasCurrent","opt","picked","MultiSelectField","next","pretty","parse","text","JsonField","setText","parsed","lines","FORMAT_INPUT_TYPES","FORMAT_WIDTH","FieldRow","isReadOnly","widgetName","kind","fieldId","control","isMarkdown","isAttachment","hasRegisteredWidget","displayValue","Widget","widgetRequired","widgetProps","renderText","staticMax","dynamicMax","dynamicValue","resolvedMax","isOverMax","DictionaryList","gridCols","formatDictionaryValue","SectionGroup","name","renderField","dictionaryColumns","dictionaryItems","dictEntries","renderCells","cell","ResolverForm","disabled","onOpenHelp","onDisabledClick","disabledHint","setData","hidden","setHidden","setFormSchema","parseError","setParseError","touched","setTouched","visible","internal","emitChange","updateField","val","markTouched","allEntries","fieldOrder","ordered","a","b","ai","bi","liveCtx","requiredFields","schemaTitle","schemaDescription","hasAuthoredHelp","sectionGroups","span","isReq","body","HelpCircle","group"],"mappings":"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"}
|
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
import{j as e,a as u}from"./vendor-query-DvWWuNIB.js";import{ap as X,aR as ee,aS as A,J as te,aT as se,w as ae,x as ne,_ as re}from"./index-CIwlVfvV.js";import{A as ie}from"./AutoGrowTextarea-7X3T9La8.js";import{C as le}from"./ConfirmDeleteModal-64adXLdq.js";import{aP as J,y as oe,bB as V,G as I,bC as ce,$ as K,aD as de,n as q,an as xe,P as W,I as T,w as me,o as G,aa as he,bD as ue}from"./vendor-icons-DeBdvyKJ.js";import{u as pe,L as U,e as fe,f as be}from"./vendor-react-_9U4mKFr.js";function je({role:t}){const{data:a}=X({role:t,limit:100}),s=(a==null?void 0:a.users)??[];return s.length===0?e.jsx("p",{className:"text-2xs text-text-tertiary",children:"Assign users to this role to staff its queue. Members see and resolve escalations here according to their read/write scope; admins manage the role itself."}):e.jsx("div",{className:"divide-y divide-surface-border/40",children:s.map(r=>{const c=r.roles.find(i=>i.role===t);return c?e.jsxs("div",{className:"flex items-center justify-between py-1.5 gap-2",children:[e.jsx("span",{className:"text-xs text-text-secondary truncate",children:r.display_name||r.external_id}),e.jsx("span",{className:"text-2xs text-text-quaternary font-mono shrink-0",children:ve(c)})]},r.id):null})})}function ve(t){return t.type==="superadmin"||t.type==="admin"?t.type:`member · read ${t.read_scope} · write ${t.write_scope}`}function M(t){return t==null?"":JSON.stringify(t,null,2)}function S(t){const a=t.trim();if(!a)return{ok:!0,value:void 0};try{const s=JSON.parse(a);return typeof s!="object"||Array.isArray(s)||s===null?{ok:!1}:{ok:!0,value:s}}catch{return{ok:!1}}}const O=/^[a-zA-Z0-9_]+$/;function ge(t){var s;const a=S(t);return a.ok&&((s=a.value)==null?void 0:s.kiosk)===!0}function ye(t){const a=S(t);if(!a.ok)return null;const s={...a.value??{}};return s.kiosk===!0?delete s.kiosk:s.kiosk=!0,JSON.stringify(s,null,2)}const _e={title:"",description:"",ops_visible:!1,ops_home_default:!1,enforce_schema:!1,parent_role:"",metadata_schema:"",properties:"{}",sla_minutes:"",target_per_hour:"",worker_count:"",priority_threshold_minutes:"",priority_facet:"",entity_facet:"",entity_state_source:"role"};function Ne(t){return{title:t.title??"",description:t.description??"",ops_visible:t.ops_visible,ops_home_default:t.ops_home_default,enforce_schema:t.enforce_schema,parent_role:t.parent_role??"",metadata_schema:M(t.metadata_schema),properties:M(t.properties)||"{}",sla_minutes:t.sla_minutes!=null?String(t.sla_minutes):"",target_per_hour:t.target_per_hour!=null?String(t.target_per_hour):"",worker_count:t.worker_count!=null?String(t.worker_count):"",priority_threshold_minutes:t.priority_threshold_minutes!=null?String(t.priority_threshold_minutes):"",priority_facet:t.priority_facet??"",entity_facet:t.entity_facet??"",entity_state_source:t.entity_state_source??"role"}}function j({icon:t,label:a,annotation:s,aside:r,accent:c=!1,children:i}){const l=c?"text-accent":"text-text-tertiary";return e.jsxs("div",{children:[e.jsxs("div",{className:"flex items-center justify-between mb-5",children:[e.jsxs("div",{className:"flex items-center gap-1.5 min-w-0",children:[e.jsx(t,{className:`w-3 h-3 ${l} shrink-0`,strokeWidth:1.5}),e.jsx("span",{className:`text-2xs font-semibold uppercase tracking-widest ${l}`,children:a}),s&&e.jsxs("span",{className:"text-2xs text-text-quaternary truncate",children:["— ",s]})]}),r]}),e.jsx("div",{className:`border-l-2 pl-5 ${c?"border-accent/15":"border-surface-border/60"}`,children:i})]})}function E(){return e.jsxs("div",{className:"flex items-center gap-1",children:[e.jsx("span",{className:"w-2.5 h-2.5 rounded-full dot-ring bg-status-success"}),e.jsx("span",{className:"text-2xs font-semibold uppercase tracking-widest text-status-success",children:"Live"})]})}function $({checked:t,onChange:a,title:s}){return e.jsx("button",{onClick:a,title:s,className:`w-9 h-5 rounded-full transition-colors relative shrink-0 ${t?"bg-accent":"bg-surface-border"}`,children:e.jsx("span",{className:`absolute top-[3px] left-0 w-3.5 h-3.5 rounded-full bg-text-inverse transition-transform shadow ${t?"translate-x-[18px]":"translate-x-[3px]"}`})})}function ke({items:t,empty:a,onRemove:s}){return t.length===0?e.jsx("p",{className:"text-2xs text-text-tertiary leading-relaxed",children:a}):e.jsx("div",{className:"flex flex-wrap gap-1.5",children:t.map(r=>e.jsxs("span",{className:"inline-flex items-center gap-1 px-2 py-0.5 text-2xs bg-accent/10 rounded-sm font-mono text-accent",children:[r,e.jsx("button",{onClick:()=>s(r),className:"text-accent/50 hover:text-status-error transition-colors leading-none ml-0.5",children:"×"})]},r))})}function we({role:t,draft:a,update:s}){const r=pe(),c=ee(),[i,l]=u.useState(!1),m=t.user_count>0||t.chain_count>0||t.workflow_count>0;return e.jsxs("div",{className:"space-y-14",children:[e.jsx(j,{icon:J,label:"Identity",annotation:"name and description",accent:!0,children:e.jsxs("div",{className:"space-y-8",children:[e.jsxs("div",{children:[e.jsx("label",{className:"block text-2xs font-semibold uppercase tracking-widest text-text-tertiary mb-1.5",children:"Display Name"}),e.jsx("input",{type:"text",value:a.title,onChange:o=>s({title:o.target.value}),placeholder:`e.g., ${t.role.charAt(0).toUpperCase()+t.role.slice(1)}`,className:"input text-sm w-full"})]}),e.jsxs("div",{children:[e.jsx("label",{className:"block text-2xs font-semibold uppercase tracking-widest text-text-tertiary mb-1.5",children:"Description"}),e.jsx(ie,{value:a.description,onChange:o=>s({description:o}),placeholder:"A short description shown on role cards and in the operations view.",rows:2})]})]})}),e.jsx("div",{className:"border-t border-surface-border/40 pt-6",children:m?e.jsxs("p",{className:"text-2xs text-text-quaternary leading-relaxed",children:["This role is referenced by"," ",[t.user_count>0?`${t.user_count} member${t.user_count===1?"":"s"}`:null,t.workflow_count>0?`${t.workflow_count} workflow${t.workflow_count===1?"":"s"}`:null,t.chain_count>0?"routing config":null].filter(Boolean).join(", ")," ","and cannot be deleted."]}):e.jsxs("button",{onClick:()=>l(!0),className:"px-3 py-1.5 text-xs rounded-md text-status-error/60 hover:text-status-error hover:bg-status-error/10 transition-colors flex items-center gap-1",children:[e.jsx(oe,{className:"w-3 h-3"})," Delete this role"]})}),e.jsx(le,{open:i,onClose:()=>l(!1),onConfirm:()=>c.mutate(t.role,{onSuccess:()=>r("/admin/roles")}),title:"Delete Role",description:e.jsxs(e.Fragment,{children:["Delete role ",e.jsx("span",{className:"font-medium font-mono text-text-primary",children:t.role}),"? This cannot be undone."]}),isPending:c.isPending,error:c.error})]})}function Se({role:t,allRoles:a,draft:s,update:r,errors:c}){const i=parseFloat(s.sla_minutes),l=parseFloat(s.target_per_hour),m=parseFloat(s.worker_count),o=!isNaN(i)&&i>0,f=!isNaN(l)&&l>0,b=!isNaN(m)&&m>0,v=o&&b&&!f?`→ target ≈ ${(m/(i/60)).toFixed(1)}/h`:o&&f&&!b?`→ workers ≈ ${(l*(i/60)).toFixed(1)}`:f&&b&&!o?`→ SLA ≈ ${(m/l*60).toFixed(0)}m`:null,d=u.useMemo(()=>a.filter(n=>{if(n.role===t.role)return!1;let h=n;const p=new Set;for(;h!=null&&h.parent_role;){if(h.parent_role===t.role)return!1;if(p.has(h.parent_role))break;p.add(h.parent_role),h=a.find(y=>y.role===h.parent_role)}return!0}),[a,t]);return e.jsxs("div",{className:"space-y-14",children:[e.jsx(j,{icon:V,label:"Pace Board",annotation:"this role on the Pace Board",accent:!0,children:e.jsxs("div",{className:"flex items-center justify-between gap-4",children:[e.jsxs("div",{children:[e.jsx("p",{className:"text-xs text-text-secondary",children:"Show this role on the Pace Board"}),e.jsx("p",{className:"text-2xs text-text-tertiary leading-relaxed mt-1",children:"Roles appear on the Operations chart and table with live counts, pace, and the time-in-state mix."})]}),e.jsx($,{checked:s.ops_visible,onChange:()=>r({ops_visible:!s.ops_visible}),title:"Show this role on the Pace Board"})]})}),e.jsx(j,{icon:I,label:"Capacity",annotation:"throughput = workers / (sla / 60)",children:e.jsxs("div",{className:"flex items-end gap-6",children:[[{key:"sla_minutes",label:"SLA",unit:"min",placeholder:"30"},{key:"target_per_hour",label:"Target",unit:"/h",placeholder:"20"},{key:"worker_count",label:"Workers",unit:"",placeholder:"4"}].map(({key:n,label:h,unit:p,placeholder:y})=>e.jsxs("div",{children:[e.jsxs("label",{className:"block text-2xs font-semibold uppercase tracking-widest text-text-quaternary mb-1",children:[h,p&&e.jsx("span",{className:"normal-case font-normal ml-1",children:p})]}),e.jsx("input",{type:"number",min:"0",step:"any",value:s[n],onChange:L=>r({[n]:L.target.value}),placeholder:y,className:"input text-xs w-20 font-mono"})]},n)),v&&e.jsx("span",{className:"text-2xs text-accent font-mono whitespace-nowrap pb-2",children:v})]})}),e.jsxs(j,{icon:I,label:"Priority",annotation:"when a pending item counts as overdue",children:[e.jsxs("div",{className:"flex items-end gap-6",children:[e.jsxs("div",{children:[e.jsxs("label",{className:"block text-2xs font-semibold uppercase tracking-widest text-text-quaternary mb-1",children:["Threshold",e.jsx("span",{className:"normal-case font-normal ml-1",children:"min"})]}),e.jsx("input",{type:"number",min:"0",step:"any",value:s.priority_threshold_minutes,onChange:n=>r({priority_threshold_minutes:n.target.value}),placeholder:s.sla_minutes||"60",className:"input text-xs w-20 font-mono"})]}),e.jsxs("div",{children:[e.jsx("label",{className:"block text-2xs font-semibold uppercase tracking-widest text-text-quaternary mb-1",children:"Age Facet"}),e.jsx("input",{type:"text",value:s.priority_facet,onChange:n=>r({priority_facet:n.target.value}),placeholder:"created_at",className:"input text-xs w-36 font-mono"}),c.priority_facet&&e.jsx("p",{className:"text-2xs text-status-error mt-0.5",children:c.priority_facet})]})]}),e.jsxs("p",{className:"text-2xs text-text-tertiary leading-relaxed mt-3",children:["Pending unclaimed items older than the threshold count as priority. Age is measured from the metadata facet (an ISO 8601 UTC timestamp, e.g. ",e.jsx("code",{className:"font-mono",children:"authorized_at"}),") or from"," ",e.jsx("code",{className:"font-mono",children:"created_at"})," when blank; the threshold falls back to SLA when blank."]})]}),e.jsxs(j,{icon:ce,label:"Entity",annotation:"what moves through this role",accent:!0,children:[e.jsx("input",{type:"text",value:s.entity_facet,onChange:n=>r({entity_facet:n.target.value}),placeholder:"serialNumber",className:"input text-xs w-44 font-mono"}),c.entity_facet&&e.jsx("p",{className:"text-2xs text-status-error mt-0.5",children:c.entity_facet}),e.jsxs("p",{className:"text-2xs text-text-tertiary leading-relaxed mt-3",children:["The metadata key naming the entity that moves through this role —"," ",e.jsx("code",{className:"font-mono",children:"serialNumber"}),","," ",e.jsx("code",{className:"font-mono",children:"orderId"}),". Roles sharing a key form that entity's system: its state mix, per-entity dwell, and timelines all derive from it. Blank = the role has no entity notion."]}),s.entity_facet.trim()!==""&&e.jsxs("div",{className:"mt-5",children:[e.jsx("label",{className:"block text-2xs font-semibold uppercase tracking-widest text-text-quaternary mb-1.5",children:"States from"}),e.jsx("div",{className:"flex items-center gap-1",children:[{value:"role",label:"Role"},{value:"subtype",label:"Subtypes"}].map(({value:n,label:h})=>e.jsx("button",{onClick:()=>r({entity_state_source:n}),className:`px-2.5 py-1 text-2xs rounded transition-colors ${s.entity_state_source===n?"bg-accent/10 text-accent font-semibold":"icon-link"}`,children:h},n))}),e.jsxs("p",{className:"text-2xs text-text-tertiary leading-relaxed mt-1.5",children:["How this role names the entity's state. ",e.jsx("strong",{children:"Role"}),": being here is one state (a servicing or harvesting queue)."," ",e.jsx("strong",{children:"Subtypes"}),": this one role holds several states, named by each escalation's subtype (a fleet role parking"," ",e.jsx("code",{className:"font-mono",children:"ready"})," /"," ",e.jsx("code",{className:"font-mono",children:"printing"}),")."]})]})]}),e.jsx("div",{className:`overflow-hidden transition-all duration-300 ease-out ${s.ops_visible?"opacity-100 max-h-[900px]":"opacity-0 max-h-0 pointer-events-none"}`,"aria-hidden":!s.ops_visible,children:e.jsx(j,{icon:K,label:"Sequence",annotation:"where this role sits in its segment",children:e.jsxs("div",{className:"space-y-8",children:[e.jsxs("div",{children:[e.jsx("label",{className:"block text-2xs font-semibold uppercase tracking-widest text-text-tertiary mb-1.5",children:"Prior Step"}),e.jsxs("select",{value:s.parent_role,onChange:n=>r({parent_role:n.target.value}),className:"select text-sm w-full font-mono",children:[e.jsx("option",{value:"",children:"None — root process"}),d.map(n=>e.jsx("option",{value:n.role,children:n.title?`${n.role} — ${n.title}`:n.role},n.role))]}),e.jsx("p",{className:"text-2xs text-text-tertiary leading-relaxed mt-1.5",children:"Places this role in one Pace Board sequence. A role with no prior step starts its own sequence."})]}),e.jsxs("div",{children:[e.jsxs("div",{className:"flex items-center justify-between mb-1.5",children:[e.jsx("label",{className:"block text-2xs font-semibold uppercase tracking-widest text-text-tertiary",children:"Upstream Inputs"}),e.jsx(E,{})]}),e.jsx(Ce,{role:t,allRoles:a})]}),e.jsxs("div",{children:[e.jsxs("div",{className:"flex items-center justify-between gap-4",children:[e.jsx("label",{className:"block text-2xs font-semibold uppercase tracking-widest text-text-tertiary",children:"Home Segment"}),e.jsx($,{checked:s.ops_home_default,onChange:()=>r({ops_home_default:!s.ops_home_default}),title:"Lead the home Pace Board with this role's sequence"})]}),e.jsx("p",{className:"text-2xs text-text-tertiary leading-relaxed mt-1.5",children:"Lead the home page's Pace Board with this role's sequence. One role holds this — saving it here releases the previous holder. Unset everywhere, the board opens on its first sequence."})]})]})})})]})}function Ce({role:t,allRoles:a}){const s=A(),[r,c]=u.useState(""),i=t.upstream_roles??[],l=u.useMemo(()=>a.map(o=>o.role).filter(o=>o!==t.role&&o!=="superadmin"&&!i.includes(o)),[a,t.role,i]),m=o=>s.mutate({role:t.role,upstream_roles:o},{onSuccess:()=>c("")});return e.jsxs("div",{className:"space-y-2",children:[l.length>0&&e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsxs("select",{value:r,onChange:o=>c(o.target.value),className:"select text-xs font-mono flex-1",children:[e.jsx("option",{value:"",children:"Add upstream input…"}),l.map(o=>e.jsx("option",{value:o,children:o},o))]}),e.jsx("button",{onClick:()=>{r&&m([...i,r])},disabled:!r||s.isPending,className:"px-2.5 py-1 text-xs rounded bg-accent text-text-inverse hover:bg-accent-hover transition-colors disabled:opacity-40 disabled:cursor-not-allowed shrink-0",children:s.isPending?"…":"Add"})]}),e.jsx(ke,{items:i,empty:"Roles from other sequences this role draws input from. Add one above and it lands here.",onRemove:o=>m(i.filter(f=>f!==o))}),s.error&&e.jsx("p",{className:"text-2xs text-status-error",children:s.error.message})]})}function Pe({role:t,draft:a,update:s,errors:r,editingJson:c,startEditingJson:i,setMetadataSchemaError:l}){return e.jsxs("div",{className:"space-y-14",children:[e.jsx(j,{icon:de,label:"Enforcement",annotation:"server-side resolver validation",accent:!0,children:e.jsxs("div",{className:"flex items-center justify-between gap-4",children:[e.jsxs("div",{children:[e.jsx("p",{className:"text-xs text-text-secondary",children:"Enforce the escalation form schema"}),e.jsx("p",{className:"text-2xs text-text-tertiary leading-relaxed mt-1",children:"Every resolve surface — API, MCP, CLI — validates submitted payloads against this role's form schema and rejects violations with field-level errors before any state changes."})]}),e.jsx($,{checked:a.enforce_schema,onChange:()=>s({enforce_schema:!a.enforce_schema}),title:"Validate every resolve payload against this role's form schema"})]})}),e.jsxs(j,{icon:q,label:"Escalation Schema",annotation:"the resolve form",accent:!0,aside:t.current_schema_version!=null?e.jsxs("span",{className:"text-2xs font-mono text-text-quaternary",children:["v",t.current_schema_version," in use"]}):void 0,children:[e.jsxs("p",{className:"text-2xs text-text-tertiary mb-3 leading-relaxed",children:["The form a person completes to resolve this role's escalations. Versioned — each save adds one; workflows pin any version via"," ",e.jsx("code",{className:"font-mono",children:"schemaVersion"}),"."]}),e.jsx(U,{to:`/admin/roles/${encodeURIComponent(t.role)}/schema`,className:"text-xs text-accent hover:underline",children:t.form_schema?`Open schema editor — v${t.current_schema_version??1} in use →`:"Define the escalation form →"})]}),e.jsxs(j,{icon:xe,label:"Escalations List Schema",annotation:"rich list view",aside:t.current_list_schema_version!=null?e.jsxs("span",{className:"text-2xs font-mono text-text-quaternary",children:["v",t.current_list_schema_version," in use"]}):void 0,children:[e.jsx("p",{className:"text-2xs text-text-tertiary mb-3 leading-relaxed",children:"Richly formats the escalation list when it's scoped to just this role. Versioned on its own timeline — separate from the resolve form."}),e.jsx(U,{to:`/admin/roles/${encodeURIComponent(t.role)}/list-schema`,className:"text-xs text-accent hover:underline",children:t.list_schema?`Open list schema editor — v${t.current_list_schema_version??1} in use →`:"Define the list view →"})]}),e.jsxs(j,{icon:q,label:"Metadata Schema",annotation:"validates metadata at creation",aside:!c.has("metadata_schema")&&t.metadata_schema?e.jsx("button",{onClick:()=>i("metadata_schema"),className:"text-2xs text-accent hover:underline",children:"Edit"}):void 0,children:[e.jsxs("p",{className:"text-2xs text-text-tertiary mb-3 leading-relaxed",children:["Validates ",e.jsx("code",{className:"font-mono",children:"metadata"})," at creation time. Keys appear in faceted search autocomplete."]}),!c.has("metadata_schema")&&t.metadata_schema?e.jsx(te,{data:t.metadata_schema}):e.jsxs(e.Fragment,{children:[e.jsx("textarea",{value:a.metadata_schema,onChange:m=>{const o=m.target.value;s({metadata_schema:o}),l(S(o).ok?void 0:"Invalid JSON")},rows:10,spellCheck:!1,className:"input text-xs font-mono w-full resize-y",placeholder:`{
|
|
2
|
-
"type": "object",
|
|
3
|
-
"properties": {
|
|
4
|
-
"order_id": { "type": "string" }
|
|
5
|
-
},
|
|
6
|
-
"required": ["order_id"]
|
|
7
|
-
}`}),r.metadata_schema&&e.jsx("p",{className:"text-2xs text-status-error mt-1",children:r.metadata_schema})]})]})]})}function qe({role:t}){return e.jsxs(e.Fragment,{children:[e.jsx(j,{icon:q,label:"Link Variables",annotation:"facet names members bind per device — pins reference them as {lt:name}",aside:e.jsx(E,{}),children:e.jsx(Ae,{role:t})}),e.jsx(j,{icon:W,label:"Default Pins",annotation:"pinned views every member starts with",aside:e.jsx(E,{}),accent:!0,children:e.jsx(Le,{role:t})})]})}function $e(t){var s;const a=(s=t.properties)==null?void 0:s.link_variables;return Array.isArray(a)?a.filter(r=>typeof(r==null?void 0:r.name)=="string"):[]}function Ae({role:t}){const a=A(),[s,r]=u.useState(""),[c,i]=u.useState(""),[l,m]=u.useState(""),o=$e(t),f=d=>a.mutate({role:t.role,properties:{...t.properties??{},link_variables:d.length?d:void 0}},{onSuccess:()=>{r(""),i(""),m("")}}),b=s.trim(),v=O.test(b)&&!o.some(d=>d.name===b);return e.jsxs("div",{className:"space-y-2",children:[e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx("input",{type:"text",value:s,onChange:d=>r(d.target.value),placeholder:"facet name — e.g. region",className:"input text-xs font-mono w-40 shrink-0"}),e.jsx("input",{type:"text",value:c,onChange:d=>i(d.target.value),placeholder:"label (optional)",className:"input text-xs flex-1"}),e.jsx("input",{type:"text",value:l,onChange:d=>m(d.target.value),placeholder:"default (optional)",className:"input text-xs font-mono w-36 shrink-0"}),e.jsx("button",{onClick:()=>{v&&f([...o,{name:b,...c.trim()?{label:c.trim()}:{},...l.trim()?{default:l.trim()}:{}}])},disabled:!v||a.isPending,className:"px-2.5 py-1 text-xs rounded bg-accent text-text-inverse hover:bg-accent-hover transition-colors disabled:opacity-40 disabled:cursor-not-allowed shrink-0",children:a.isPending?"…":"Add"})]}),o.length===0?e.jsxs("p",{className:"text-2xs text-text-tertiary leading-relaxed",children:["Facet names members bind per device. A pin below can then carry",e.jsxs("span",{className:"font-mono",children:[' facets={"region":"',"{lt:region}",'"} ']}),"and each device opens it scoped to its own value."]}):e.jsx("div",{className:"space-y-1",children:o.map(d=>e.jsxs("div",{className:"flex items-baseline gap-2 text-2xs","data-testid":"link-var-decl",children:[e.jsx("span",{className:"font-mono font-medium text-text-secondary shrink-0",children:d.name}),d.label&&e.jsx("span",{className:"text-text-quaternary truncate",children:d.label}),e.jsx("span",{className:"font-mono text-text-quaternary truncate flex-1",children:d.default?`default: ${d.default}`:"no default — unset drops the facet"}),e.jsx("span",{className:"font-mono text-text-quaternary shrink-0",title:"Reference in a pin URL",children:se(d.name)}),e.jsx("button",{onClick:()=>f(o.filter(n=>n.name!==d.name)),className:"text-text-quaternary hover:text-status-error transition-colors leading-none shrink-0","aria-label":`Remove variable ${d.name}`,children:"×"})]},d.name))}),a.error&&e.jsx("p",{className:"text-2xs text-status-error",children:a.error.message})]})}function Le({role:t}){const a=A(),[s,r]=u.useState(""),[c,i]=u.useState(""),[l,m]=u.useState(!0),{values:o,defaults:f}=ae(),b=t.default_pins??[],v=n=>a.mutate({role:t.role,default_pins:n.length?n:null},{onSuccess:()=>{r(""),i(""),m(!0)}}),d=s.trim()!==""&&c.trim().startsWith("/");return e.jsxs("div",{className:"space-y-2",children:[e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx("input",{type:"text",value:s,onChange:n=>r(n.target.value),placeholder:"Label — e.g. Needs harvesting",className:"input text-xs w-40 shrink-0"}),e.jsx("input",{type:"text",value:c,onChange:n=>i(n.target.value),placeholder:'/escalations/available?role=… or …facets={"region":"{lt:region}"}',className:"input text-xs font-mono flex-1"}),e.jsxs("label",{className:"flex items-center gap-1 text-2xs text-text-tertiary shrink-0",title:"Show a live count beside the label",children:[e.jsx("input",{type:"checkbox",checked:l,onChange:n=>m(n.target.checked),className:"w-3 h-3 accent-accent"}),"count"]}),e.jsx("button",{onClick:()=>{d&&v([...b,{label:s.trim(),url:c.trim(),badge:l}])},disabled:!d||a.isPending,className:"px-2.5 py-1 text-xs rounded bg-accent text-text-inverse hover:bg-accent-hover transition-colors disabled:opacity-40 disabled:cursor-not-allowed shrink-0",children:a.isPending?"…":"Add"})]}),b.length===0?e.jsx("p",{className:"text-2xs text-text-tertiary leading-relaxed",children:"Pinned views every member starts with — the persona's exact queries. Add one above and it lands here."}):e.jsx("div",{className:"space-y-1",children:b.map(n=>{const h=ne(n.url);return e.jsxs("div",{children:[e.jsxs("div",{className:"flex items-baseline gap-2 text-2xs",children:[e.jsx("span",{className:"font-medium text-text-secondary shrink-0",children:n.label}),n.badge&&e.jsx("span",{className:"text-2xs text-accent shrink-0",title:"Shows a live count",children:"count"}),e.jsx("span",{className:"font-mono text-text-quaternary truncate flex-1",title:n.url,children:n.url}),e.jsx("button",{onClick:()=>v(b.filter(p=>p.label!==n.label)),className:"text-text-quaternary hover:text-status-error transition-colors leading-none shrink-0","aria-label":`Remove pin ${n.label}`,children:"×"})]}),h.length>0&&e.jsxs("p",{className:"pl-2 font-mono text-2xs text-text-quaternary","data-testid":"pin-binding-caption",children:[h.map(p=>{const y=o[p]??f[p];return`${p} = ${y?`'${y}'`:"<empty>"}`}).join(", "),e.jsx("span",{className:"font-sans",children:" on this device"})]})]},n.label)})}),a.error&&e.jsx("p",{className:"text-2xs text-status-error",children:a.error.message})]})}const z=[{key:"identity",label:"Identity",icon:J},{key:"pace-board",label:"Pace Board",icon:V},{key:"schemas",label:"Schemas",icon:q},{key:"members",label:"Members",icon:G},{key:"pins",label:"Pins",icon:W}],Re=t=>z.some(a=>a.key===t);function Te(){const{role:t}=fe(),{data:a,isLoading:s}=re(),r=A(),c=(a==null?void 0:a.roles)??[],i=c.find(x=>x.role===t),[l,m]=u.useState(_e),[o,f]=u.useState(!1),[b,v]=u.useState(!1),[d,n]=u.useState({}),[h,p]=u.useState(new Set),y=x=>p(g=>new Set([...g,x])),[L,F]=be(),B=L.get("section"),N=Re(B)?B:"identity",H=u.useCallback(x=>{F(g=>{const _=new URLSearchParams(g);return _.set("section",x),_},{replace:!0})},[F]);u.useEffect(()=>{i&&(m(Ne(i)),f(!1),v(!1),n({}),p(new Set))},[t,i==null?void 0:i.role]);const C=x=>{m(g=>({...g,...x})),f(!0),v(!1)},Y=()=>{if(!i)return;const x=S(l.metadata_schema),g=S(l.properties),_=l.priority_facet.trim(),R=l.entity_facet.trim(),k={};if(x.ok||(k.metadata_schema="Invalid JSON"),g.ok||(k.properties="Invalid JSON"),_&&!O.test(_)&&(k.priority_facet="Letters, numbers, underscores only"),R&&!O.test(R)&&(k.entity_facet="Letters, numbers, underscores only"),n(k),Object.keys(k).length)return;const P=D=>{const w=parseFloat(D);return isNaN(w)?null:w},Q=D=>{const w=P(D);return w==null?null:Math.round(w)};r.mutate({role:i.role,title:l.title.trim()||null,description:l.description.trim()||null,ops_visible:l.ops_visible,ops_home_default:l.ops_home_default,enforce_schema:l.enforce_schema,parent_role:l.parent_role||null,metadata_schema:x.value??null,properties:g.value??{},sla_minutes:P(l.sla_minutes),target_per_hour:P(l.target_per_hour),worker_count:Q(l.worker_count),priority_threshold_minutes:P(l.priority_threshold_minutes),priority_facet:_||null,entity_facet:R||null,entity_state_source:l.entity_state_source},{onSuccess:()=>{f(!1),v(!0),p(new Set),window.setTimeout(()=>v(!1),2500)}})};if(s)return e.jsxs("div",{className:"animate-pulse space-y-4",children:[e.jsx("div",{className:"h-8 bg-surface-sunken rounded w-48"}),e.jsx("div",{className:"h-4 bg-surface-sunken rounded w-64"}),e.jsx("div",{className:"h-64 bg-surface-sunken rounded"})]});if(!i)return e.jsxs("div",{className:"flex flex-col items-center justify-center py-20 text-center",children:[e.jsx(T,{className:"w-12 h-12 text-text-quaternary mb-4",strokeWidth:1}),e.jsx("h2",{className:"heading-3 mb-2",children:"Role not found"})]});const Z=o&&!Object.values(d).some(Boolean);return e.jsxs("div",{children:[e.jsxs("div",{className:"mb-10 min-w-0",children:[e.jsxs("div",{className:"flex items-center gap-3 mb-1",children:[e.jsx(T,{className:"w-5 h-5 text-accent",strokeWidth:1.5}),e.jsx("h1",{className:"text-lg font-mono font-medium text-text-primary",children:i.role}),e.jsx("button",{onClick:()=>{window.location.hash="#docs:dashboard.md:role-detail"},className:"text-text-quaternary hover:text-accent transition-colors",title:"Open docs for this page",children:e.jsx(me,{className:"w-4 h-4",strokeWidth:1.5})}),i.parent_role&&e.jsxs("span",{className:"flex items-center gap-1 text-2xs text-text-quaternary font-mono",children:[e.jsx(K,{className:"w-3 h-3"})," ",i.parent_role]})]}),i.title&&e.jsx("p",{className:"text-sm text-text-secondary pl-8",children:i.title})]}),e.jsxs("div",{className:"flex gap-10",children:[e.jsxs("nav",{className:"w-44 shrink-0 sticky top-0 self-start pt-2",children:[e.jsx("div",{className:"space-y-0.5",children:z.map(x=>{const g=x.icon,_=N===x.key;return e.jsxs("button",{onClick:()=>H(x.key),className:`w-full flex items-center gap-2.5 px-3 py-2 rounded-md text-left transition-colors ${_?"bg-accent/10 text-accent":"text-text-tertiary hover:text-text-primary hover:bg-surface-hover"}`,children:[e.jsx(g,{className:"w-3.5 h-3.5 shrink-0",strokeWidth:1.5}),e.jsx("span",{className:"text-xs font-medium",children:x.label})]},x.key)})}),e.jsxs("div",{className:"mt-8 pt-4 border-t border-surface-border space-y-2",children:[e.jsx("button",{onClick:Y,disabled:!Z||r.isPending,className:"w-full px-3 py-1.5 text-xs rounded-md bg-accent text-text-inverse hover:bg-accent-hover transition-colors disabled:opacity-40 disabled:cursor-not-allowed",children:r.isPending?"Saving…":o?"Save changes":"Save"}),b&&e.jsxs("span",{className:"flex items-center justify-center gap-1 text-xs text-status-success animate-page-enter",children:[e.jsx(he,{className:"w-3 h-3"})," Saved"]}),r.error&&e.jsx("p",{className:"text-2xs text-status-error leading-relaxed",children:r.error.message}),Object.values(d).some(Boolean)&&e.jsx("p",{className:"text-2xs text-status-error leading-relaxed",children:"Fix the highlighted fields before saving."})]})]}),e.jsxs("div",{className:"flex-1 min-w-0 pt-2 max-w-3xl",children:[N==="identity"&&e.jsx(we,{role:i,draft:l,update:C,errors:d}),N==="pace-board"&&e.jsx(Se,{role:i,allRoles:c,draft:l,update:C,errors:d}),N==="schemas"&&e.jsx(Pe,{role:i,draft:l,update:C,errors:d,editingJson:h,startEditingJson:y,setMetadataSchemaError:x=>n(g=>({...g,metadata_schema:x}))}),N==="members"&&e.jsxs("div",{className:"space-y-14",children:[e.jsx(j,{icon:G,label:"Members",annotation:"read = what appears · write = what they can act on",accent:!0,children:e.jsx(je,{role:i.role})}),e.jsx(j,{icon:ue,label:"Kiosk",annotation:"the locked viewport for single-role logins",children:e.jsxs("div",{className:"flex items-center justify-between gap-4",children:[e.jsxs("div",{children:[e.jsx("p",{className:"text-xs text-text-secondary",children:"Lock single-role members to this queue"}),e.jsx("p",{className:"text-2xs text-text-tertiary leading-relaxed mt-1",children:"A member who holds only this role signs in to a locked viewport: no side navigation, this queue as home, held to the list, the item detail, and the scan screens. Members with other roles keep the full dashboard."})]}),e.jsx($,{checked:ge(l.properties),onChange:()=>{const x=ye(l.properties);x!==null&&C({properties:x})},title:"Kiosk viewport"})]})})]}),N==="pins"&&e.jsx(qe,{role:i})]})]})]})}export{Te as RoleDetailPage};
|
|
8
|
-
//# sourceMappingURL=RoleDetailPage-WQt0y5l7.js.map
|