@taskforcehq/taskforce 0.3.168
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 +241 -0
- package/dist/Taskforce.d.ts +3 -0
- package/dist/Taskforce.js +3 -0
- package/dist/Taskforce.module.css +7587 -0
- package/dist/TaskforceCore.CategoryFallback.test.d.ts +1 -0
- package/dist/TaskforceCore.CategoryFallback.test.js +98 -0
- package/dist/TaskforceCore.d.ts +12 -0
- package/dist/TaskforceCore.js +729 -0
- package/dist/TaskforceCore.test.d.ts +1 -0
- package/dist/TaskforceCore.test.js +2132 -0
- package/dist/TaskforceScreenshot.d.ts +11 -0
- package/dist/TaskforceScreenshot.js +113 -0
- package/dist/TaskforceWidget.d.ts +6 -0
- package/dist/TaskforceWidget.js +101 -0
- package/dist/TaskforceWidget.test.d.ts +1 -0
- package/dist/TaskforceWidget.test.js +92 -0
- package/dist/UnsavedChangesRelaxed.test.d.ts +1 -0
- package/dist/UnsavedChangesRelaxed.test.js +16 -0
- package/dist/__tests__/localizationCatalogs.test.d.ts +1 -0
- package/dist/__tests__/localizationCatalogs.test.js +37 -0
- package/dist/__tests__/planParser.test.d.ts +1 -0
- package/dist/__tests__/planParser.test.js +183 -0
- package/dist/__tests__/releaseVersion.test.d.ts +1 -0
- package/dist/__tests__/releaseVersion.test.js +32 -0
- package/dist/__tests__/structuredCommentValidation.test.d.ts +1 -0
- package/dist/__tests__/structuredCommentValidation.test.js +31 -0
- package/dist/__tests__/structuredDocValidation.test.d.ts +1 -0
- package/dist/__tests__/structuredDocValidation.test.js +30 -0
- package/dist/__tests__/templateEngine.test.d.ts +1 -0
- package/dist/__tests__/templateEngine.test.js +150 -0
- package/dist/__tests__/templates.test.d.ts +1 -0
- package/dist/__tests__/templates.test.js +45 -0
- package/dist/__tests__/workflowDocumentFixtures.test.d.ts +1 -0
- package/dist/__tests__/workflowDocumentFixtures.test.js +78 -0
- package/dist/__tests__/workflowExportMatrix.test.d.ts +1 -0
- package/dist/__tests__/workflowExportMatrix.test.js +113 -0
- package/dist/__tests__/workflowExportSnapshots.test.d.ts +1 -0
- package/dist/__tests__/workflowExportSnapshots.test.js +28 -0
- package/dist/__tests__/workflowGeneration.test.d.ts +1 -0
- package/dist/__tests__/workflowGeneration.test.js +12 -0
- package/dist/__tests__/workflowSimulation.test.d.ts +1 -0
- package/dist/__tests__/workflowSimulation.test.js +113 -0
- package/dist/__tests__/workflowV2Policy.test.d.ts +1 -0
- package/dist/__tests__/workflowV2Policy.test.js +80 -0
- package/dist/api.d.ts +30 -0
- package/dist/api.js +85 -0
- package/dist/cli.d.ts +2 -0
- package/dist/cli.js +217 -0
- package/dist/compat/priorityCompat.d.ts +2 -0
- package/dist/compat/priorityCompat.js +24 -0
- package/dist/components/features/DocumentGenerateModal.d.ts +9 -0
- package/dist/components/features/DocumentGenerateModal.js +114 -0
- package/dist/components/features/DocumentIndex.d.ts +19 -0
- package/dist/components/features/DocumentIndex.js +51 -0
- package/dist/components/features/DocumentViewer.d.ts +9 -0
- package/dist/components/features/DocumentViewer.js +253 -0
- package/dist/components/features/DocumentWorkspace.d.ts +21 -0
- package/dist/components/features/DocumentWorkspace.js +88 -0
- package/dist/components/features/TaskSettings.d.ts +209 -0
- package/dist/components/features/TaskSettings.js +500 -0
- package/dist/components/features/TaskSettings.test.d.ts +1 -0
- package/dist/components/features/TaskSettings.test.js +308 -0
- package/dist/components/features/settings/CategoryManager.d.ts +19 -0
- package/dist/components/features/settings/CategoryManager.js +113 -0
- package/dist/components/features/settings/TaxonomyEditor.d.ts +8 -0
- package/dist/components/features/settings/TaxonomyEditor.js +98 -0
- package/dist/components/features/settings/TaxonomyManager 2.d.ts +52 -0
- package/dist/components/features/settings/TaxonomyManager 2.js +75 -0
- package/dist/components/features/settings/TaxonomyManager.d.ts +54 -0
- package/dist/components/features/settings/TaxonomyManager.js +77 -0
- package/dist/components/features/settings/TypeManager.d.ts +10 -0
- package/dist/components/features/settings/TypeManager.js +50 -0
- package/dist/components/features/settings/WorkflowEditorPrototype.d.ts +15 -0
- package/dist/components/features/settings/WorkflowEditorPrototype.js +245 -0
- package/dist/components/task/TaskActionHeader.d.ts +20 -0
- package/dist/components/task/TaskActionHeader.js +13 -0
- package/dist/components/task/TaskCard.d.ts +47 -0
- package/dist/components/task/TaskCard.js +326 -0
- package/dist/components/task/TaskCard.test.d.ts +1 -0
- package/dist/components/task/TaskCard.test.js +95 -0
- package/dist/components/task/TaskContextUpload.d.ts +12 -0
- package/dist/components/task/TaskContextUpload.js +393 -0
- package/dist/components/task/TaskContextUpload.test.d.ts +1 -0
- package/dist/components/task/TaskContextUpload.test.js +189 -0
- package/dist/components/task/TaskForm.d.ts +105 -0
- package/dist/components/task/TaskForm.js +241 -0
- package/dist/components/task/TaskForm.test.d.ts +1 -0
- package/dist/components/task/TaskForm.test.js +288 -0
- package/dist/components/task/TaskKanban 2.d.ts +76 -0
- package/dist/components/task/TaskKanban 2.js +1004 -0
- package/dist/components/task/TaskKanban.d.ts +76 -0
- package/dist/components/task/TaskKanban.empty-column-drop.test.d.ts +1 -0
- package/dist/components/task/TaskKanban.empty-column-drop.test.js +66 -0
- package/dist/components/task/TaskKanban.js +1026 -0
- package/dist/components/task/TaskKanban.test.d.ts +1 -0
- package/dist/components/task/TaskKanban.test.js +46 -0
- package/dist/components/task/TaskList.d.ts +74 -0
- package/dist/components/task/TaskList.js +38 -0
- package/dist/components/task/TaskList.test.d.ts +1 -0
- package/dist/components/task/TaskList.test.js +270 -0
- package/dist/components/task/TaskScreenshotSection.d.ts +15 -0
- package/dist/components/task/TaskScreenshotSection.js +22 -0
- package/dist/components/ui/LevelSelector.d.ts +13 -0
- package/dist/components/ui/LevelSelector.js +25 -0
- package/dist/components/ui/LevelSelector.test.d.ts +1 -0
- package/dist/components/ui/LevelSelector.test.js +55 -0
- package/dist/components/ui/Markdown.d.ts +6 -0
- package/dist/components/ui/Markdown.js +94 -0
- package/dist/components/ui/Markdown.test.d.ts +1 -0
- package/dist/components/ui/Markdown.test.js +38 -0
- package/dist/components/ui/Modal.d.ts +16 -0
- package/dist/components/ui/Modal.js +49 -0
- package/dist/components/ui/MultiSelectFilter.d.ts +10 -0
- package/dist/components/ui/MultiSelectFilter.js +71 -0
- package/dist/components/ui/MultiSelectFilter.test.d.ts +1 -0
- package/dist/components/ui/MultiSelectFilter.test.js +74 -0
- package/dist/components/ui/TaxonomyDropdown.d.ts +17 -0
- package/dist/components/ui/TaxonomyDropdown.js +145 -0
- package/dist/components/ui/TaxonomyDropdown.test.d.ts +1 -0
- package/dist/components/ui/TaxonomyDropdown.test.js +130 -0
- package/dist/components/views/StandaloneLayout 2.d.ts +8 -0
- package/dist/components/views/StandaloneLayout 2.js +1660 -0
- package/dist/components/views/StandaloneLayout.d.ts +8 -0
- package/dist/components/views/StandaloneLayout.js +2117 -0
- package/dist/components/views/WidgetView.d.ts +8 -0
- package/dist/components/views/WidgetView.js +221 -0
- package/dist/config/envSchema.d.ts +28 -0
- package/dist/config/envSchema.js +374 -0
- package/dist/config/envSchema.test.d.ts +1 -0
- package/dist/config/envSchema.test.js +97 -0
- package/dist/config/surfaceBase.d.ts +2 -0
- package/dist/config/surfaceBase.js +8 -0
- package/dist/core/BulkUpdateFieldsPreview.test.d.ts +1 -0
- package/dist/core/BulkUpdateFieldsPreview.test.js +62 -0
- package/dist/core/CompletedAt.test.d.ts +1 -0
- package/dist/core/CompletedAt.test.js +44 -0
- package/dist/core/CreatedBy.test.d.ts +1 -0
- package/dist/core/CreatedBy.test.js +60 -0
- package/dist/core/EntitlementsPolicy.test.d.ts +1 -0
- package/dist/core/EntitlementsPolicy.test.js +145 -0
- package/dist/core/InitiativeTemplates.test.d.ts +1 -0
- package/dist/core/InitiativeTemplates.test.js +50 -0
- package/dist/core/ParentLifecycle.test.d.ts +1 -0
- package/dist/core/ParentLifecycle.test.js +98 -0
- package/dist/core/ScheduleFields.test.d.ts +1 -0
- package/dist/core/ScheduleFields.test.js +197 -0
- package/dist/core/SetupState.test.d.ts +1 -0
- package/dist/core/SetupState.test.js +113 -0
- package/dist/core/SystemAdmin.test.d.ts +1 -0
- package/dist/core/SystemAdmin.test.js +295 -0
- package/dist/core/TaskTaxonomyValidation.test.d.ts +1 -0
- package/dist/core/TaskTaxonomyValidation.test.js +64 -0
- package/dist/core/Taskforce.d.ts +1063 -0
- package/dist/core/Taskforce.ids.test.d.ts +1 -0
- package/dist/core/Taskforce.ids.test.js +168 -0
- package/dist/core/Taskforce.js +5981 -0
- package/dist/core/Taskforce.realtimeMutation.test.d.ts +1 -0
- package/dist/core/Taskforce.realtimeMutation.test.js +76 -0
- package/dist/core/WorkspaceDelete.test.d.ts +1 -0
- package/dist/core/WorkspaceDelete.test.js +140 -0
- package/dist/core/WorkspacePermissions.test.d.ts +1 -0
- package/dist/core/WorkspacePermissions.test.js +151 -0
- package/dist/core/WorkspacePlanMode.test.d.ts +1 -0
- package/dist/core/WorkspacePlanMode.test.js +104 -0
- package/dist/hooks/authGuardPolicy.d.ts +26 -0
- package/dist/hooks/authGuardPolicy.js +32 -0
- package/dist/hooks/authGuardPolicy.test.d.ts +1 -0
- package/dist/hooks/authGuardPolicy.test.js +76 -0
- package/dist/hooks/useDraggable.d.ts +12 -0
- package/dist/hooks/useDraggable.js +65 -0
- package/dist/hooks/useRealtimeSync.d.ts +24 -0
- package/dist/hooks/useRealtimeSync.js +275 -0
- package/dist/hooks/useRealtimeSync.test.d.ts +1 -0
- package/dist/hooks/useRealtimeSync.test.js +284 -0
- package/dist/hooks/useSyncOrchestrator.d.ts +164 -0
- package/dist/hooks/useSyncOrchestrator.js +1427 -0
- package/dist/hooks/useSyncOrchestrator.retry-closure.test.d.ts +1 -0
- package/dist/hooks/useSyncOrchestrator.retry-closure.test.js +367 -0
- package/dist/hooks/useTaskforce.d.ts +727 -0
- package/dist/hooks/useTaskforce.js +4396 -0
- package/dist/hooks/useTaskforce.priority-filters.test.d.ts +1 -0
- package/dist/hooks/useTaskforce.priority-filters.test.js +33 -0
- package/dist/hooks/useWorkspaceSyncController.d.ts +80 -0
- package/dist/hooks/useWorkspaceSyncController.js +598 -0
- package/dist/hooks/useWorkspaceSyncController.test.d.ts +1 -0
- package/dist/hooks/useWorkspaceSyncController.test.js +236 -0
- package/dist/index.d.ts +12 -0
- package/dist/index.js +11 -0
- package/dist/localization/index.d.ts +8 -0
- package/dist/localization/index.js +81 -0
- package/dist/localization/locales/en-US.d.ts +151 -0
- package/dist/localization/locales/en-US.js +150 -0
- package/dist/localization/locales/es-419.d.ts +2 -0
- package/dist/localization/locales/es-419.js +150 -0
- package/dist/localization/locales/pt-BR.d.ts +2 -0
- package/dist/localization/locales/pt-BR.js +150 -0
- package/dist/main.d.ts +1 -0
- package/dist/main.js +33 -0
- package/dist/mcp/optionResolution.d.ts +14 -0
- package/dist/mcp/optionResolution.js +126 -0
- package/dist/mcp/optionResolution.test.d.ts +1 -0
- package/dist/mcp/optionResolution.test.js +39 -0
- package/dist/mcp/server.d.ts +1 -0
- package/dist/mcp/server.js +1793 -0
- package/dist/mcp/structuredCommentValidation.d.ts +6 -0
- package/dist/mcp/structuredCommentValidation.js +56 -0
- package/dist/mcp/structuredDocValidation.d.ts +6 -0
- package/dist/mcp/structuredDocValidation.js +75 -0
- package/dist/migrations/billingSchemaParity.test.d.ts +1 -0
- package/dist/migrations/billingSchemaParity.test.js +46 -0
- package/dist/migrations/clientMigrations.d.ts +9 -0
- package/dist/migrations/clientMigrations.js +74 -0
- package/dist/migrations/flags.d.ts +6 -0
- package/dist/migrations/flags.js +8 -0
- package/dist/migrations/taskMigrations.d.ts +71 -0
- package/dist/migrations/taskMigrations.js +236 -0
- package/dist/migrations/taskMigrations.test.d.ts +1 -0
- package/dist/migrations/taskMigrations.test.js +34 -0
- package/dist/migrations/taskSchemaMigrations.d.ts +11 -0
- package/dist/migrations/taskSchemaMigrations.js +453 -0
- package/dist/plugins/index.d.ts +10 -0
- package/dist/plugins/index.js +10 -0
- package/dist/plugins/vite.d.ts +19 -0
- package/dist/plugins/vite.js +271 -0
- package/dist/public/android-chrome-192x192.png +0 -0
- package/dist/public/android-chrome-512x512.png +0 -0
- package/dist/public/apple-touch-icon.png +0 -0
- package/dist/public/favicon-16x16.png +0 -0
- package/dist/public/favicon-32x32.png +0 -0
- package/dist/public/favicon.ico +0 -0
- package/dist/public/favicon.png +0 -0
- package/dist/public/site.webmanifest +1 -0
- package/dist/public/taskforce.png +0 -0
- package/dist/resources/templates/WORKFLOW_V2_POLICY.md +55 -0
- package/dist/resources/templates/environments/aider.yaml +14 -0
- package/dist/resources/templates/environments/antigravity.yaml +10 -0
- package/dist/resources/templates/environments/claude.yaml +10 -0
- package/dist/resources/templates/environments/cline.yaml +10 -0
- package/dist/resources/templates/environments/codex.yaml +13 -0
- package/dist/resources/templates/environments/copilot.yaml +10 -0
- package/dist/resources/templates/environments/cursor.yaml +9 -0
- package/dist/resources/templates/environments/gemini.yaml +9 -0
- package/dist/resources/templates/environments/windsurf.yaml +10 -0
- package/dist/resources/templates/workflow-sources/README.md +9 -0
- package/dist/resources/templates/workflow-sources/workflowDocs.mjs +520 -0
- package/dist/resources/templates/workflow-sources/workflowEditorOverrides.json +1 -0
- package/dist/resources/templates/workflows/collaborate.yaml +104 -0
- package/dist/resources/templates/workflows/do.yaml +82 -0
- package/dist/resources/templates/workflows/evaluate.yaml +111 -0
- package/dist/resources/templates/workflows/execute.yaml +142 -0
- package/dist/resources/templates/workflows/plan.yaml +112 -0
- package/dist/resources/templates/workflows/review.yaml +109 -0
- package/dist/runtime/capabilities.d.ts +8 -0
- package/dist/runtime/capabilities.js +16 -0
- package/dist/security/virusScan.d.ts +16 -0
- package/dist/security/virusScan.js +83 -0
- package/dist/server/auth.d.ts +51 -0
- package/dist/server/auth.js +266 -0
- package/dist/server/auth.test.d.ts +1 -0
- package/dist/server/auth.test.js +111 -0
- package/dist/server/buildInfo.d.ts +7 -0
- package/dist/server/buildInfo.js +100 -0
- package/dist/server/buildInfo.test.d.ts +1 -0
- package/dist/server/buildInfo.test.js +29 -0
- package/dist/server/cors.d.ts +7 -0
- package/dist/server/cors.js +76 -0
- package/dist/server/cors.test.d.ts +1 -0
- package/dist/server/cors.test.js +71 -0
- package/dist/server/email.d.ts +28 -0
- package/dist/server/email.js +138 -0
- package/dist/server/email.test.d.ts +1 -0
- package/dist/server/email.test.js +113 -0
- package/dist/server/index.cookieProxy.test.d.ts +1 -0
- package/dist/server/index.cookieProxy.test.js +19 -0
- package/dist/server/index.d.ts +17 -0
- package/dist/server/index.js +757 -0
- package/dist/server/index.rateLimit.test.d.ts +1 -0
- package/dist/server/index.rateLimit.test.js +13 -0
- package/dist/server/index.test.d.ts +1 -0
- package/dist/server/index.test.js +19 -0
- package/dist/server/rateLimit.d.ts +29 -0
- package/dist/server/rateLimit.js +99 -0
- package/dist/server/rateLimit.test.d.ts +1 -0
- package/dist/server/rateLimit.test.js +107 -0
- package/dist/server/realtimeSync.auth.test.d.ts +1 -0
- package/dist/server/realtimeSync.auth.test.js +62 -0
- package/dist/server/realtimeSync.replay.test.d.ts +1 -0
- package/dist/server/realtimeSync.replay.test.js +192 -0
- package/dist/server/realtimeSync.workspaceIsolation.test.d.ts +1 -0
- package/dist/server/realtimeSync.workspaceIsolation.test.js +101 -0
- package/dist/server/realtimeSyncWs.d.ts +30 -0
- package/dist/server/realtimeSyncWs.js +257 -0
- package/dist/server/routes.billing.d.ts +15 -0
- package/dist/server/routes.billing.js +991 -0
- package/dist/server/routes.billing.test.d.ts +1 -0
- package/dist/server/routes.billing.test.js +387 -0
- package/dist/server/routes.d.ts +72 -0
- package/dist/server/routes.js +4820 -0
- package/dist/server/routes.sync.d.ts +17 -0
- package/dist/server/routes.sync.integration.test.d.ts +1 -0
- package/dist/server/routes.sync.integration.test.js +470 -0
- package/dist/server/routes.sync.js +1141 -0
- package/dist/server/routes.test.d.ts +1 -0
- package/dist/server/routes.test.js +4945 -0
- package/dist/server/runtimeMode.d.ts +4 -0
- package/dist/server/runtimeMode.js +25 -0
- package/dist/server/runtimeMode.test.d.ts +1 -0
- package/dist/server/runtimeMode.test.js +26 -0
- package/dist/server/securityHeaders.d.ts +3 -0
- package/dist/server/securityHeaders.js +25 -0
- package/dist/server/securityHeaders.test.d.ts +1 -0
- package/dist/server/securityHeaders.test.js +32 -0
- package/dist/server/smtpTransport.d.ts +21 -0
- package/dist/server/smtpTransport.js +11 -0
- package/dist/server/start.d.ts +1 -0
- package/dist/server/start.js +17 -0
- package/dist/services/formatTransformers.d.ts +29 -0
- package/dist/services/formatTransformers.js +56 -0
- package/dist/services/templateEngine.d.ts +46 -0
- package/dist/services/templateEngine.js +148 -0
- package/dist/shared/runtimeContract.d.ts +12 -0
- package/dist/shared/runtimeContract.js +23 -0
- package/dist/shared/runtimeContract.test.d.ts +1 -0
- package/dist/shared/runtimeContract.test.js +23 -0
- package/dist/soak/preflight.cli.d.ts +1 -0
- package/dist/soak/preflight.cli.js +28 -0
- package/dist/soak/preflight.d.ts +26 -0
- package/dist/soak/preflight.js +113 -0
- package/dist/soak/preflight.test.d.ts +1 -0
- package/dist/soak/preflight.test.js +39 -0
- package/dist/soak/syncSoakHarness.d.ts +6 -0
- package/dist/soak/syncSoakHarness.js +10 -0
- package/dist/storage/createDatabaseAdapter.d.ts +2 -0
- package/dist/storage/createDatabaseAdapter.js +9 -0
- package/dist/storage/databaseAdapter.d.ts +22 -0
- package/dist/storage/databaseAdapter.js +1 -0
- package/dist/storage/documentIntegrity.d.ts +28 -0
- package/dist/storage/documentIntegrity.js +103 -0
- package/dist/storage/documentPurge.d.ts +14 -0
- package/dist/storage/documentPurge.js +46 -0
- package/dist/storage/documentRegistry.d.ts +39 -0
- package/dist/storage/documentRegistry.js +115 -0
- package/dist/storage/integritySchedule.d.ts +17 -0
- package/dist/storage/integritySchedule.js +62 -0
- package/dist/storage/objectStorage.d.ts +20 -0
- package/dist/storage/objectStorage.js +15 -0
- package/dist/storage/objectStorageClient.d.ts +18 -0
- package/dist/storage/objectStorageClient.js +301 -0
- package/dist/storage/objectStorageConfig.d.ts +2 -0
- package/dist/storage/objectStorageConfig.js +45 -0
- package/dist/storage/postgresAdapter.d.ts +20 -0
- package/dist/storage/postgresAdapter.js +204 -0
- package/dist/storage/postgresWorker.d.ts +1 -0
- package/dist/storage/postgresWorker.js +110 -0
- package/dist/storage/providerConfig.d.ts +6 -0
- package/dist/storage/providerConfig.js +11 -0
- package/dist/storage/sqliteAdapter.d.ts +14 -0
- package/dist/storage/sqliteAdapter.js +28 -0
- package/dist/storage/taskAssetStore.d.ts +56 -0
- package/dist/storage/taskAssetStore.js +297 -0
- package/dist/sync/cloudSyncApi.d.ts +47 -0
- package/dist/sync/cloudSyncApi.js +138 -0
- package/dist/sync/cloudSyncApi.test.d.ts +1 -0
- package/dist/sync/cloudSyncApi.test.js +54 -0
- package/dist/sync/encryptionService.d.ts +11 -0
- package/dist/sync/encryptionService.js +61 -0
- package/dist/sync/encryptionService.test.d.ts +1 -0
- package/dist/sync/encryptionService.test.js +52 -0
- package/dist/sync/realtimeFeature.d.ts +6 -0
- package/dist/sync/realtimeFeature.js +20 -0
- package/dist/sync/realtimeFeature.test.d.ts +1 -0
- package/dist/sync/realtimeFeature.test.js +30 -0
- package/dist/sync/realtimeReconcile.d.ts +30 -0
- package/dist/sync/realtimeReconcile.js +90 -0
- package/dist/sync/realtimeReconcile.test.d.ts +1 -0
- package/dist/sync/realtimeReconcile.test.js +43 -0
- package/dist/sync/syncService.d.ts +96 -0
- package/dist/sync/syncService.js +423 -0
- package/dist/sync/syncService.test.d.ts +1 -0
- package/dist/sync/syncService.test.js +484 -0
- package/dist/sync/workspaceSyncModel.d.ts +61 -0
- package/dist/sync/workspaceSyncModel.js +136 -0
- package/dist/sync/workspaceSyncModel.test.d.ts +1 -0
- package/dist/sync/workspaceSyncModel.test.js +73 -0
- package/dist/test/setup.d.ts +1 -0
- package/dist/test/setup.js +15 -0
- package/dist/types.d.ts +157 -0
- package/dist/types.js +41 -0
- package/dist/ui/assets/RussoOne-Regular-C3BxZIj7.ttf +0 -0
- package/dist/ui/assets/index-0W5vyCpn.css +1 -0
- package/dist/ui/assets/index-MCZuNNfn.js +23 -0
- package/dist/ui/assets/logo_white_01-0Vx-iIIv.png +0 -0
- package/dist/ui/assets/taskforce-BxLPokNB.png +0 -0
- package/dist/ui/assets/vendor-dnd-BI1K77C1.js +5 -0
- package/dist/ui/assets/vendor-icons-ZFG3SGwo.js +1 -0
- package/dist/ui/assets/vendor-markdown-CKYkQHfj.js +29 -0
- package/dist/ui/assets/vendor-react-DdIDsh7f.js +9 -0
- package/dist/ui/assets/vendor-router-BtiNU7Dl.js +3 -0
- package/dist/ui/branding/logos/logo_black_01.png +0 -0
- package/dist/ui/branding/logos/logo_black_02.png +0 -0
- package/dist/ui/branding/logos/logo_white_01.png +0 -0
- package/dist/ui/branding/logos/logo_white_02.png +0 -0
- package/dist/ui/favicon/android-chrome-192x192.png +0 -0
- package/dist/ui/favicon/android-chrome-512x512.png +0 -0
- package/dist/ui/favicon/apple-touch-icon.png +0 -0
- package/dist/ui/favicon/favicon-16x16.png +0 -0
- package/dist/ui/favicon/favicon-32x32.png +0 -0
- package/dist/ui/favicon/favicon.ico +0 -0
- package/dist/ui/favicon/favicon.png +0 -0
- package/dist/ui/favicon/site.webmanifest +1 -0
- package/dist/ui/fonts/RussoOne-Regular.ttf +0 -0
- package/dist/ui/images/taskforce.png +0 -0
- package/dist/ui/index.html +19 -0
- package/dist/utils/checklistMarkdown.d.ts +9 -0
- package/dist/utils/checklistMarkdown.js +46 -0
- package/dist/utils/constants.d.ts +21 -0
- package/dist/utils/constants.icons.test.d.ts +1 -0
- package/dist/utils/constants.icons.test.js +40 -0
- package/dist/utils/constants.js +100 -0
- package/dist/utils/contextFiles.d.ts +8 -0
- package/dist/utils/contextFiles.js +54 -0
- package/dist/utils/formatting.d.ts +5 -0
- package/dist/utils/formatting.js +30 -0
- package/dist/utils/planParser.d.ts +22 -0
- package/dist/utils/planParser.js +151 -0
- package/dist/utils/taskDragZones.d.ts +8 -0
- package/dist/utils/taskDragZones.js +14 -0
- package/dist/utils/taskDragZones.test.d.ts +1 -0
- package/dist/utils/taskDragZones.test.js +14 -0
- package/dist/utils/taskHierarchy.d.ts +4 -0
- package/dist/utils/taskHierarchy.js +69 -0
- package/dist/utils/taskHierarchy.test.d.ts +1 -0
- package/dist/utils/taskHierarchy.test.js +38 -0
- package/dist/utils/taskParenting.d.ts +3 -0
- package/dist/utils/taskParenting.js +24 -0
- package/dist/utils/taskParenting.test.d.ts +1 -0
- package/dist/utils/taskParenting.test.js +21 -0
- package/dist/utils/taskRelations.d.ts +6 -0
- package/dist/utils/taskRelations.js +24 -0
- package/dist/utils/taskRelations.test.d.ts +1 -0
- package/dist/utils/taskRelations.test.js +34 -0
- package/dist/utils/taskUtils.d.ts +2 -0
- package/dist/utils/taskUtils.js +20 -0
- package/dist/utils/taskforceApiClient.d.ts +7 -0
- package/dist/utils/taskforceApiClient.js +42 -0
- package/dist/utils/workspaceIdentity.d.ts +8 -0
- package/dist/utils/workspaceIdentity.js +47 -0
- package/dist/utils/workspaceIdentity.test.d.ts +1 -0
- package/dist/utils/workspaceIdentity.test.js +32 -0
- package/dist/utils/workspaceLifecycle.d.ts +26 -0
- package/dist/utils/workspaceLifecycle.js +69 -0
- package/dist/utils/workspaceLifecycle.test.d.ts +1 -0
- package/dist/utils/workspaceLifecycle.test.js +64 -0
- package/package.json +133 -0
- package/scripts/check-compat-boundaries.js +48 -0
- package/scripts/check-env.ts +24 -0
- package/scripts/check-localization-strings.mjs +49 -0
- package/scripts/check-runtime-boundaries.mjs +44 -0
- package/scripts/debug-global.mjs +34 -0
- package/scripts/debug-server.mjs +36 -0
- package/scripts/export-sqlite-to-postgres.mjs +125 -0
- package/scripts/generate-env-example.ts +8 -0
- package/scripts/generate-workflow-templates.mjs +134 -0
- package/scripts/mcp-stdio-adapter.mjs +160 -0
- package/scripts/postinstall.js +60 -0
- package/scripts/release-version-lib.mjs +88 -0
- package/scripts/release-version.mjs +72 -0
- package/scripts/run-dev-proxy.sh +49 -0
- package/scripts/run-e2e-realtime.sh +16 -0
- package/scripts/run-smoke.sh +23 -0
- package/scripts/run-soak.sh +29 -0
- package/scripts/test-global.js +143 -0
- package/scripts/update-homebrew-formula.sh +38 -0
- package/src/resources/templates/WORKFLOW_V2_POLICY.md +55 -0
- package/src/resources/templates/environments/aider.yaml +14 -0
- package/src/resources/templates/environments/antigravity.yaml +10 -0
- package/src/resources/templates/environments/claude.yaml +10 -0
- package/src/resources/templates/environments/cline.yaml +10 -0
- package/src/resources/templates/environments/codex.yaml +13 -0
- package/src/resources/templates/environments/copilot.yaml +10 -0
- package/src/resources/templates/environments/cursor.yaml +9 -0
- package/src/resources/templates/environments/gemini.yaml +9 -0
- package/src/resources/templates/environments/windsurf.yaml +10 -0
- package/src/resources/templates/workflow-sources/README.md +9 -0
- package/src/resources/templates/workflow-sources/workflowDocs.mjs +520 -0
- package/src/resources/templates/workflow-sources/workflowEditorOverrides.json +1 -0
- package/src/resources/templates/workflows/collaborate.yaml +104 -0
- package/src/resources/templates/workflows/do.yaml +82 -0
- package/src/resources/templates/workflows/evaluate.yaml +111 -0
- package/src/resources/templates/workflows/execute.yaml +142 -0
- package/src/resources/templates/workflows/plan.yaml +112 -0
- package/src/resources/templates/workflows/review.yaml +109 -0
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import{r as i}from"./vendor-react-DdIDsh7f.js";var re="popstate";function ke(e={}){let{initialEntries:t=["/"],initialIndex:n,v5Compat:o=!1}=e,r;r=t.map((h,v)=>d(h,typeof h=="string"?null:h.state,v===0?"default":void 0));let a=s(n??r.length-1),l="POP",u=null;function s(h){return Math.min(Math.max(h,0),r.length-1)}function c(){return r[a]}function d(h,v=null,p){let m=z(r?c().pathname:"/",h,v,p);return S(m.pathname.charAt(0)==="/",`relative pathnames are not supported in memory history: ${JSON.stringify(h)}`),m}function f(h){return typeof h=="string"?h:M(h)}return{get index(){return a},get action(){return l},get location(){return c()},createHref:f,createURL(h){return new URL(f(h),"http://localhost")},encodeLocation(h){let v=typeof h=="string"?N(h):h;return{pathname:v.pathname||"",search:v.search||"",hash:v.hash||""}},push(h,v){l="PUSH";let p=d(h,v);a+=1,r.splice(a,r.length,p),o&&u&&u({action:l,location:p,delta:1})},replace(h,v){l="REPLACE";let p=d(h,v);r[a]=p,o&&u&&u({action:l,location:p,delta:0})},go(h){l="POP";let v=s(a+h),p=r[v];a=v,u&&u({action:l,location:p,delta:h})},listen(h){return u=h,()=>{u=null}}}}function Te(e={}){function t(o,r){let{pathname:a,search:l,hash:u}=o.location;return z("",{pathname:a,search:l,hash:u},r.state&&r.state.usr||null,r.state&&r.state.key||"default")}function n(o,r){return typeof r=="string"?r:M(r)}return Oe(t,n,null,e)}function E(e,t){if(e===!1||e===null||typeof e>"u")throw new Error(t)}function S(e,t){if(!e){typeof console<"u"&&console.warn(t);try{throw new Error(t)}catch{}}}function Ie(){return Math.random().toString(36).substring(2,10)}function ae(e,t){return{usr:e.state,key:e.key,idx:t}}function z(e,t,n=null,o){return{pathname:typeof e=="string"?e:e.pathname,search:"",hash:"",...typeof t=="string"?N(t):t,state:n,key:t&&t.key||o||Ie()}}function M({pathname:e="/",search:t="",hash:n=""}){return t&&t!=="?"&&(e+=t.charAt(0)==="?"?t:"?"+t),n&&n!=="#"&&(e+=n.charAt(0)==="#"?n:"#"+n),e}function N(e){let t={};if(e){let n=e.indexOf("#");n>=0&&(t.hash=e.substring(n),e=e.substring(0,n));let o=e.indexOf("?");o>=0&&(t.search=e.substring(o),e=e.substring(0,o)),e&&(t.pathname=e)}return t}function Oe(e,t,n,o={}){let{window:r=document.defaultView,v5Compat:a=!1}=o,l=r.history,u="POP",s=null,c=d();c==null&&(c=0,l.replaceState({...l.state,idx:c},""));function d(){return(l.state||{idx:null}).idx}function f(){u="POP";let m=d(),w=m==null?null:m-c;c=m,s&&s({action:u,location:p.location,delta:w})}function y(m,w){u="PUSH";let g=z(p.location,m,w);c=d()+1;let R=ae(g,c),C=p.createHref(g);try{l.pushState(R,"",C)}catch(x){if(x instanceof DOMException&&x.name==="DataCloneError")throw x;r.location.assign(C)}a&&s&&s({action:u,location:p.location,delta:1})}function h(m,w){u="REPLACE";let g=z(p.location,m,w);c=d();let R=ae(g,c),C=p.createHref(g);l.replaceState(R,"",C),a&&s&&s({action:u,location:p.location,delta:0})}function v(m){return De(m)}let p={get action(){return u},get location(){return e(r,l)},listen(m){if(s)throw new Error("A history only accepts one active listener");return r.addEventListener(re,f),s=m,()=>{r.removeEventListener(re,f),s=null}},createHref(m){return t(r,m)},createURL:v,encodeLocation(m){let w=v(m);return{pathname:w.pathname,search:w.search,hash:w.hash}},push:y,replace:h,go(m){return l.go(m)}};return p}function De(e,t=!1){let n="http://localhost";typeof window<"u"&&(n=window.location.origin!=="null"?window.location.origin:window.location.href),E(n,"No window.location.(origin|href) available to create URL");let o=typeof e=="string"?e:M(e);return o=o.replace(/ $/,"%20"),!t&&o.startsWith("//")&&(o=n+o),new URL(o,n)}function se(e,t,n="/"){return Me(e,t,n,!1)}function Me(e,t,n,o){let r=typeof t=="string"?N(t):t,a=P(r.pathname||"/",n);if(a==null)return null;let l=ce(e);Ne(l);let u=null;for(let s=0;u==null&&s<l.length;++s){let c=Je(a);u=ze(l[s],c,o)}return u}function ce(e,t=[],n=[],o="",r=!1){let a=(l,u,s=r,c)=>{let d={relativePath:c===void 0?l.path||"":c,caseSensitive:l.caseSensitive===!0,childrenIndex:u,route:l};if(d.relativePath.startsWith("/")){if(!d.relativePath.startsWith(o)&&s)return;E(d.relativePath.startsWith(o),`Absolute route path "${d.relativePath}" nested under path "${o}" is not valid. An absolute child route path must start with the combined path of all its parent routes.`),d.relativePath=d.relativePath.slice(o.length)}let f=L([o,d.relativePath]),y=n.concat(d);l.children&&l.children.length>0&&(E(l.index!==!0,`Index routes must not have child routes. Please remove all child routes from route path "${f}".`),ce(l.children,t,y,f,s)),!(l.path==null&&!l.index)&&t.push({path:f,score:He(f,l.index),routesMeta:y})};return e.forEach((l,u)=>{if(l.path===""||!l.path?.includes("?"))a(l,u);else for(let s of fe(l.path))a(l,u,!0,s)}),t}function fe(e){let t=e.split("/");if(t.length===0)return[];let[n,...o]=t,r=n.endsWith("?"),a=n.replace(/\?$/,"");if(o.length===0)return r?[a,""]:[a];let l=fe(o.join("/")),u=[];return u.push(...l.map(s=>s===""?a:[a,s].join("/"))),r&&u.push(...l),u.map(s=>e.startsWith("/")&&s===""?"/":s)}function Ne(e){e.sort((t,n)=>t.score!==n.score?n.score-t.score:je(t.routesMeta.map(o=>o.childrenIndex),n.routesMeta.map(o=>o.childrenIndex)))}var Fe=/^:[\w-]+$/,Ue=3,Ae=2,Be=1,_e=10,We=-2,oe=e=>e==="*";function He(e,t){let n=e.split("/"),o=n.length;return n.some(oe)&&(o+=We),t&&(o+=Ae),n.filter(r=>!oe(r)).reduce((r,a)=>r+(Fe.test(a)?Ue:a===""?Be:_e),o)}function je(e,t){return e.length===t.length&&e.slice(0,-1).every((o,r)=>o===t[r])?e[e.length-1]-t[t.length-1]:0}function ze(e,t,n=!1){let{routesMeta:o}=e,r={},a="/",l=[];for(let u=0;u<o.length;++u){let s=o[u],c=u===o.length-1,d=a==="/"?t:t.slice(a.length)||"/",f=V({path:s.relativePath,caseSensitive:s.caseSensitive,end:c},d),y=s.route;if(!f&&c&&n&&!o[o.length-1].route.index&&(f=V({path:s.relativePath,caseSensitive:s.caseSensitive,end:!1},d)),!f)return null;Object.assign(r,f.params),l.push({params:r,pathname:L([a,f.pathname]),pathnameBase:qe(L([a,f.pathnameBase])),route:y}),f.pathnameBase!=="/"&&(a=L([a,f.pathnameBase]))}return l}function V(e,t){typeof e=="string"&&(e={path:e,caseSensitive:!1,end:!0});let[n,o]=Ve(e.path,e.caseSensitive,e.end),r=t.match(n);if(!r)return null;let a=r[0],l=a.replace(/(.)\/+$/,"$1"),u=r.slice(1);return{params:o.reduce((c,{paramName:d,isOptional:f},y)=>{if(d==="*"){let v=u[y]||"";l=a.slice(0,a.length-v.length).replace(/(.)\/+$/,"$1")}const h=u[y];return f&&!h?c[d]=void 0:c[d]=(h||"").replace(/%2F/g,"/"),c},{}),pathname:a,pathnameBase:l,pattern:e}}function Ve(e,t=!1,n=!0){S(e==="*"||!e.endsWith("*")||e.endsWith("/*"),`Route path "${e}" will be treated as if it were "${e.replace(/\*$/,"/*")}" because the \`*\` character must always follow a \`/\` in the pattern. To get rid of this warning, please change the route path to "${e.replace(/\*$/,"/*")}".`);let o=[],r="^"+e.replace(/\/*\*?$/,"").replace(/^\/*/,"/").replace(/[\\.*+^${}|()[\]]/g,"\\$&").replace(/\/:([\w-]+)(\?)?/g,(l,u,s)=>(o.push({paramName:u,isOptional:s!=null}),s?"/?([^\\/]+)?":"/([^\\/]+)")).replace(/\/([\w-]+)\?(\/|$)/g,"(/$1)?$2");return e.endsWith("*")?(o.push({paramName:"*"}),r+=e==="*"||e==="/*"?"(.*)$":"(?:\\/(.+)|\\/*)$"):n?r+="\\/*$":e!==""&&e!=="/"&&(r+="(?:(?=\\/|$))"),[new RegExp(r,t?void 0:"i"),o]}function Je(e){try{return e.split("/").map(t=>decodeURIComponent(t).replace(/\//g,"%2F")).join("/")}catch(t){return S(!1,`The URL path "${e}" could not be decoded because it is a malformed URL segment. This is probably due to a bad percent encoding (${t}).`),e}}function P(e,t){if(t==="/")return e;if(!e.toLowerCase().startsWith(t.toLowerCase()))return null;let n=t.endsWith("/")?t.length-1:t.length,o=e.charAt(n);return o&&o!=="/"?null:e.slice(n)||"/"}var Ke=/^(?:[a-z][a-z0-9+.-]*:|\/\/)/i;function Ye(e,t="/"){let{pathname:n,search:o="",hash:r=""}=typeof e=="string"?N(e):e,a;return n?(n=n.replace(/\/\/+/g,"/"),n.startsWith("/")?a=le(n.substring(1),"/"):a=le(n,t)):a=t,{pathname:a,search:Xe(o),hash:Qe(r)}}function le(e,t){let n=t.replace(/\/+$/,"").split("/");return e.split("/").forEach(r=>{r===".."?n.length>1&&n.pop():r!=="."&&n.push(r)}),n.length>1?n.join("/"):"/"}function G(e,t,n,o){return`Cannot include a '${e}' character in a manually specified \`to.${t}\` field [${JSON.stringify(o)}]. Please separate it out to the \`to.${n}\` field. Alternatively you may provide the full path as a string in <Link to="..."> and the router will parse it for you.`}function Ge(e){return e.filter((t,n)=>n===0||t.route.path&&t.route.path.length>0)}function de(e){let t=Ge(e);return t.map((n,o)=>o===t.length-1?n.pathname:n.pathnameBase)}function he(e,t,n,o=!1){let r;typeof e=="string"?r=N(e):(r={...e},E(!r.pathname||!r.pathname.includes("?"),G("?","pathname","search",r)),E(!r.pathname||!r.pathname.includes("#"),G("#","pathname","hash",r)),E(!r.search||!r.search.includes("#"),G("#","search","hash",r)));let a=e===""||r.pathname==="",l=a?"/":r.pathname,u;if(l==null)u=n;else{let f=t.length-1;if(!o&&l.startsWith("..")){let y=l.split("/");for(;y[0]==="..";)y.shift(),f-=1;r.pathname=y.join("/")}u=f>=0?t[f]:"/"}let s=Ye(r,u),c=l&&l!=="/"&&l.endsWith("/"),d=(a||l===".")&&n.endsWith("/");return!s.pathname.endsWith("/")&&(c||d)&&(s.pathname+="/"),s}var L=e=>e.join("/").replace(/\/\/+/g,"/"),qe=e=>e.replace(/\/+$/,"").replace(/^\/*/,"/"),Xe=e=>!e||e==="?"?"":e.startsWith("?")?e:"?"+e,Qe=e=>!e||e==="#"?"":e.startsWith("#")?e:"#"+e,Ze=class{constructor(e,t,n,o=!1){this.status=e,this.statusText=t||"",this.internal=o,n instanceof Error?(this.data=n.toString(),this.error=n):this.data=n}};function et(e){return e!=null&&typeof e.status=="number"&&typeof e.statusText=="string"&&typeof e.internal=="boolean"&&"data"in e}function tt(e){return e.map(t=>t.route.path).filter(Boolean).join("/").replace(/\/\/*/g,"/")||"/"}var me=typeof window<"u"&&typeof window.document<"u"&&typeof window.document.createElement<"u";function pe(e,t){let n=e;if(typeof n!="string"||!Ke.test(n))return{absoluteURL:void 0,isExternal:!1,to:n};let o=n,r=!1;if(me)try{let a=new URL(window.location.href),l=n.startsWith("//")?new URL(a.protocol+n):new URL(n),u=P(l.pathname,t);l.origin===a.origin&&u!=null?n=u+l.search+l.hash:r=!0}catch{S(!1,`<Link to="${n}"> contains an invalid URL which will probably break when clicked - please update to a valid URL path.`)}return{absoluteURL:o,isExternal:r,to:n}}Object.getOwnPropertyNames(Object.prototype).sort().join("\0");var ge=["POST","PUT","PATCH","DELETE"];new Set(ge);var nt=["GET",...ge];new Set(nt);var F=i.createContext(null);F.displayName="DataRouter";var J=i.createContext(null);J.displayName="DataRouterState";var rt=i.createContext(!1),ye=i.createContext({isTransitioning:!1});ye.displayName="ViewTransition";var at=i.createContext(new Map);at.displayName="Fetchers";var ot=i.createContext(null);ot.displayName="Await";var b=i.createContext(null);b.displayName="Navigation";var K=i.createContext(null);K.displayName="Location";var $=i.createContext({outlet:null,matches:[],isDataRoute:!1});$.displayName="Route";var Q=i.createContext(null);Q.displayName="RouteError";var ve="REACT_ROUTER_ERROR",lt="REDIRECT",it="ROUTE_ERROR_RESPONSE";function ut(e){if(e.startsWith(`${ve}:${lt}:{`))try{let t=JSON.parse(e.slice(28));if(typeof t=="object"&&t&&typeof t.status=="number"&&typeof t.statusText=="string"&&typeof t.location=="string"&&typeof t.reloadDocument=="boolean"&&typeof t.replace=="boolean")return t}catch{}}function st(e){if(e.startsWith(`${ve}:${it}:{`))try{let t=JSON.parse(e.slice(40));if(typeof t=="object"&&t&&typeof t.status=="number"&&typeof t.statusText=="string")return new Ze(t.status,t.statusText,t.data)}catch{}}function ct(e,{relative:t}={}){E(B(),"useHref() may be used only in the context of a <Router> component.");let{basename:n,navigator:o}=i.useContext(b),{hash:r,pathname:a,search:l}=_(e,{relative:t}),u=a;return n!=="/"&&(u=a==="/"?n:L([n,a])),o.createHref({pathname:u,search:l,hash:r})}function B(){return i.useContext(K)!=null}function I(){return E(B(),"useLocation() may be used only in the context of a <Router> component."),i.useContext(K).location}var we="You should call navigate() in a React.useEffect(), not when your component is first rendered.";function Re(e){i.useContext(b).static||i.useLayoutEffect(e)}function ft(){let{isDataRoute:e}=i.useContext($);return e?bt():dt()}function dt(){E(B(),"useNavigate() may be used only in the context of a <Router> component.");let e=i.useContext(F),{basename:t,navigator:n}=i.useContext(b),{matches:o}=i.useContext($),{pathname:r}=I(),a=JSON.stringify(de(o)),l=i.useRef(!1);return Re(()=>{l.current=!0}),i.useCallback((s,c={})=>{if(S(l.current,we),!l.current)return;if(typeof s=="number"){n.go(s);return}let d=he(s,JSON.parse(a),r,c.relative==="path");e==null&&t!=="/"&&(d.pathname=d.pathname==="/"?t:L([t,d.pathname])),(c.replace?n.replace:n.push)(d,c.state,c)},[t,n,a,r,e])}i.createContext(null);function _(e,{relative:t}={}){let{matches:n}=i.useContext($),{pathname:o}=I(),r=JSON.stringify(de(n));return i.useMemo(()=>he(e,JSON.parse(r),o,t==="path"),[e,r,o,t])}function ht(e,t,n,o,r){E(B(),"useRoutes() may be used only in the context of a <Router> component.");let{navigator:a}=i.useContext(b),{matches:l}=i.useContext($),u=l[l.length-1],s=u?u.params:{},c=u?u.pathname:"/",d=u?u.pathnameBase:"/",f=u&&u.route;{let g=f&&f.path||"";xe(c,!f||g.endsWith("*")||g.endsWith("*?"),`You rendered descendant <Routes> (or called \`useRoutes()\`) at "${c}" (under <Route path="${g}">) but the parent route path has no trailing "*". This means if you navigate deeper, the parent won't match anymore and therefore the child routes will never render.
|
|
2
|
+
|
|
3
|
+
Please change the parent <Route path="${g}"> to <Route path="${g==="/"?"*":`${g}/*`}">.`)}let y=I(),h;h=y;let v=h.pathname||"/",p=v;if(d!=="/"){let g=d.replace(/^\//,"").split("/");p="/"+v.replace(/^\//,"").split("/").slice(g.length).join("/")}let m=se(e,{pathname:p});return S(f||m!=null,`No routes matched location "${h.pathname}${h.search}${h.hash}" `),S(m==null||m[m.length-1].route.element!==void 0||m[m.length-1].route.Component!==void 0||m[m.length-1].route.lazy!==void 0,`Matched leaf route at location "${h.pathname}${h.search}${h.hash}" does not have an element or Component. This means it will render an <Outlet /> with a null value by default resulting in an "empty" page.`),vt(m&&m.map(g=>Object.assign({},g,{params:Object.assign({},s,g.params),pathname:L([d,a.encodeLocation?a.encodeLocation(g.pathname.replace(/\?/g,"%3F").replace(/#/g,"%23")).pathname:g.pathname]),pathnameBase:g.pathnameBase==="/"?d:L([d,a.encodeLocation?a.encodeLocation(g.pathnameBase.replace(/\?/g,"%3F").replace(/#/g,"%23")).pathname:g.pathnameBase])})),l,n,o,r)}function mt(){let e=Ct(),t=et(e)?`${e.status} ${e.statusText}`:e instanceof Error?e.message:JSON.stringify(e),n=e instanceof Error?e.stack:null,o="rgba(200,200,200, 0.5)",r={padding:"0.5rem",backgroundColor:o},a={padding:"2px 4px",backgroundColor:o},l=null;return console.error("Error handled by React Router default ErrorBoundary:",e),l=i.createElement(i.Fragment,null,i.createElement("p",null,"💿 Hey developer 👋"),i.createElement("p",null,"You can provide a way better UX than this when your app throws errors by providing your own ",i.createElement("code",{style:a},"ErrorBoundary")," or"," ",i.createElement("code",{style:a},"errorElement")," prop on your route.")),i.createElement(i.Fragment,null,i.createElement("h2",null,"Unexpected Application Error!"),i.createElement("h3",{style:{fontStyle:"italic"}},t),n?i.createElement("pre",{style:r},n):null,l)}var pt=i.createElement(mt,null),Ee=class extends i.Component{constructor(e){super(e),this.state={location:e.location,revalidation:e.revalidation,error:e.error}}static getDerivedStateFromError(e){return{error:e}}static getDerivedStateFromProps(e,t){return t.location!==e.location||t.revalidation!=="idle"&&e.revalidation==="idle"?{error:e.error,location:e.location,revalidation:e.revalidation}:{error:e.error!==void 0?e.error:t.error,location:t.location,revalidation:e.revalidation||t.revalidation}}componentDidCatch(e,t){this.props.onError?this.props.onError(e,t):console.error("React Router caught the following error during render",e)}render(){let e=this.state.error;if(this.context&&typeof e=="object"&&e&&"digest"in e&&typeof e.digest=="string"){const n=st(e.digest);n&&(e=n)}let t=e!==void 0?i.createElement($.Provider,{value:this.props.routeContext},i.createElement(Q.Provider,{value:e,children:this.props.component})):this.props.children;return this.context?i.createElement(gt,{error:e},t):t}};Ee.contextType=rt;var q=new WeakMap;function gt({children:e,error:t}){let{basename:n}=i.useContext(b);if(typeof t=="object"&&t&&"digest"in t&&typeof t.digest=="string"){let o=ut(t.digest);if(o){let r=q.get(t);if(r)throw r;let a=pe(o.location,n);if(me&&!q.get(t))if(a.isExternal||o.reloadDocument)window.location.href=a.absoluteURL||a.to;else{const l=Promise.resolve().then(()=>window.__reactRouterDataRouter.navigate(a.to,{replace:o.replace}));throw q.set(t,l),l}return i.createElement("meta",{httpEquiv:"refresh",content:`0;url=${a.absoluteURL||a.to}`})}}return e}function yt({routeContext:e,match:t,children:n}){let o=i.useContext(F);return o&&o.static&&o.staticContext&&(t.route.errorElement||t.route.ErrorBoundary)&&(o.staticContext._deepestRenderedBoundaryId=t.route.id),i.createElement($.Provider,{value:e},n)}function vt(e,t=[],n=null,o=null,r=null){if(e==null){if(!n)return null;if(n.errors)e=n.matches;else if(t.length===0&&!n.initialized&&n.matches.length>0)e=n.matches;else return null}let a=e,l=n?.errors;if(l!=null){let d=a.findIndex(f=>f.route.id&&l?.[f.route.id]!==void 0);E(d>=0,`Could not find a matching route for errors on route IDs: ${Object.keys(l).join(",")}`),a=a.slice(0,Math.min(a.length,d+1))}let u=!1,s=-1;if(n)for(let d=0;d<a.length;d++){let f=a[d];if((f.route.HydrateFallback||f.route.hydrateFallbackElement)&&(s=d),f.route.id){let{loaderData:y,errors:h}=n,v=f.route.loader&&!y.hasOwnProperty(f.route.id)&&(!h||h[f.route.id]===void 0);if(f.route.lazy||v){u=!0,s>=0?a=a.slice(0,s+1):a=[a[0]];break}}}let c=n&&o?(d,f)=>{o(d,{location:n.location,params:n.matches?.[0]?.params??{},unstable_pattern:tt(n.matches),errorInfo:f})}:void 0;return a.reduceRight((d,f,y)=>{let h,v=!1,p=null,m=null;n&&(h=l&&f.route.id?l[f.route.id]:void 0,p=f.route.errorElement||pt,u&&(s<0&&y===0?(xe("route-fallback",!1,"No `HydrateFallback` element provided to render during initial hydration"),v=!0,m=null):s===y&&(v=!0,m=f.route.hydrateFallbackElement||null)));let w=t.concat(a.slice(0,y+1)),g=()=>{let R;return h?R=p:v?R=m:f.route.Component?R=i.createElement(f.route.Component,null):f.route.element?R=f.route.element:R=d,i.createElement(yt,{match:f,routeContext:{outlet:d,matches:w,isDataRoute:n!=null},children:R})};return n&&(f.route.ErrorBoundary||f.route.errorElement||y===0)?i.createElement(Ee,{location:n.location,revalidation:n.revalidation,component:p,error:h,children:g(),routeContext:{outlet:null,matches:w,isDataRoute:!0},onError:c}):g()},null)}function Z(e){return`${e} must be used within a data router. See https://reactrouter.com/en/main/routers/picking-a-router.`}function wt(e){let t=i.useContext(F);return E(t,Z(e)),t}function Rt(e){let t=i.useContext(J);return E(t,Z(e)),t}function Et(e){let t=i.useContext($);return E(t,Z(e)),t}function ee(e){let t=Et(e),n=t.matches[t.matches.length-1];return E(n.route.id,`${e} can only be used on routes that contain a unique "id"`),n.route.id}function xt(){return ee("useRouteId")}function Ct(){let e=i.useContext(Q),t=Rt("useRouteError"),n=ee("useRouteError");return e!==void 0?e:t.errors?.[n]}function bt(){let{router:e}=wt("useNavigate"),t=ee("useNavigate"),n=i.useRef(!1);return Re(()=>{n.current=!0}),i.useCallback(async(r,a={})=>{S(n.current,we),n.current&&(typeof r=="number"?await e.navigate(r):await e.navigate(r,{fromRouteId:t,...a}))},[e,t])}var ie={};function xe(e,t,n){!t&&!ie[e]&&(ie[e]=!0,S(!1,n))}i.memo(St);function St({routes:e,future:t,state:n,onError:o}){return ht(e,void 0,n,o,t)}function on({basename:e,children:t,initialEntries:n,initialIndex:o,unstable_useTransitions:r}){let a=i.useRef();a.current==null&&(a.current=ke({initialEntries:n,initialIndex:o,v5Compat:!0}));let l=a.current,[u,s]=i.useState({action:l.action,location:l.location}),c=i.useCallback(d=>{r===!1?s(d):i.startTransition(()=>s(d))},[r]);return i.useLayoutEffect(()=>l.listen(c),[l,c]),i.createElement(Ce,{basename:e,children:t,location:u.location,navigationType:u.action,navigator:l,unstable_useTransitions:r})}function Ce({basename:e="/",children:t=null,location:n,navigationType:o="POP",navigator:r,static:a=!1,unstable_useTransitions:l}){E(!B(),"You cannot render a <Router> inside another <Router>. You should never have more than one in your app.");let u=e.replace(/^\/*/,"/"),s=i.useMemo(()=>({basename:u,navigator:r,static:a,unstable_useTransitions:l,future:{}}),[u,r,a,l]);typeof n=="string"&&(n=N(n));let{pathname:c="/",search:d="",hash:f="",state:y=null,key:h="default"}=n,v=i.useMemo(()=>{let p=P(c,u);return p==null?null:{location:{pathname:p,search:d,hash:f,state:y,key:h},navigationType:o}},[u,c,d,f,y,h,o]);return S(v!=null,`<Router basename="${u}"> is not able to match the URL "${c}${d}${f}" because it does not start with the basename, so the <Router> won't render anything.`),v==null?null:i.createElement(b.Provider,{value:s},i.createElement(K.Provider,{children:t,value:v}))}var H="get",j="application/x-www-form-urlencoded";function Y(e){return typeof HTMLElement<"u"&&e instanceof HTMLElement}function Lt(e){return Y(e)&&e.tagName.toLowerCase()==="button"}function Pt(e){return Y(e)&&e.tagName.toLowerCase()==="form"}function $t(e){return Y(e)&&e.tagName.toLowerCase()==="input"}function kt(e){return!!(e.metaKey||e.altKey||e.ctrlKey||e.shiftKey)}function Tt(e,t){return e.button===0&&(!t||t==="_self")&&!kt(e)}var W=null;function It(){if(W===null)try{new FormData(document.createElement("form"),0),W=!1}catch{W=!0}return W}var Ot=new Set(["application/x-www-form-urlencoded","multipart/form-data","text/plain"]);function X(e){return e!=null&&!Ot.has(e)?(S(!1,`"${e}" is not a valid \`encType\` for \`<Form>\`/\`<fetcher.Form>\` and will default to "${j}"`),null):e}function Dt(e,t){let n,o,r,a,l;if(Pt(e)){let u=e.getAttribute("action");o=u?P(u,t):null,n=e.getAttribute("method")||H,r=X(e.getAttribute("enctype"))||j,a=new FormData(e)}else if(Lt(e)||$t(e)&&(e.type==="submit"||e.type==="image")){let u=e.form;if(u==null)throw new Error('Cannot submit a <button> or <input type="submit"> without a <form>');let s=e.getAttribute("formaction")||u.getAttribute("action");if(o=s?P(s,t):null,n=e.getAttribute("formmethod")||u.getAttribute("method")||H,r=X(e.getAttribute("formenctype"))||X(u.getAttribute("enctype"))||j,a=new FormData(u,e),!It()){let{name:c,type:d,value:f}=e;if(d==="image"){let y=c?`${c}.`:"";a.append(`${y}x`,"0"),a.append(`${y}y`,"0")}else c&&a.append(c,f)}}else{if(Y(e))throw new Error('Cannot submit element that is not <form>, <button>, or <input type="submit|image">');n=H,o=null,r=j,l=e}return a&&r==="text/plain"&&(l=a,a=void 0),{action:o,method:n.toLowerCase(),encType:r,formData:a,body:l}}Object.getOwnPropertyNames(Object.prototype).sort().join("\0");function te(e,t){if(e===!1||e===null||typeof e>"u")throw new Error(t)}function Mt(e,t,n,o){let r=typeof e=="string"?new URL(e,typeof window>"u"?"server://singlefetch/":window.location.origin):e;return n?r.pathname.endsWith("/")?r.pathname=`${r.pathname}_.${o}`:r.pathname=`${r.pathname}.${o}`:r.pathname==="/"?r.pathname=`_root.${o}`:t&&P(r.pathname,t)==="/"?r.pathname=`${t.replace(/\/$/,"")}/_root.${o}`:r.pathname=`${r.pathname.replace(/\/$/,"")}.${o}`,r}async function Nt(e,t){if(e.id in t)return t[e.id];try{let n=await import(e.module);return t[e.id]=n,n}catch(n){return console.error(`Error loading route module \`${e.module}\`, reloading page...`),console.error(n),window.__reactRouterContext&&window.__reactRouterContext.isSpaMode,window.location.reload(),new Promise(()=>{})}}function Ft(e){return e==null?!1:e.href==null?e.rel==="preload"&&typeof e.imageSrcSet=="string"&&typeof e.imageSizes=="string":typeof e.rel=="string"&&typeof e.href=="string"}async function Ut(e,t,n){let o=await Promise.all(e.map(async r=>{let a=t.routes[r.route.id];if(a){let l=await Nt(a,n);return l.links?l.links():[]}return[]}));return Wt(o.flat(1).filter(Ft).filter(r=>r.rel==="stylesheet"||r.rel==="preload").map(r=>r.rel==="stylesheet"?{...r,rel:"prefetch",as:"style"}:{...r,rel:"prefetch"}))}function ue(e,t,n,o,r,a){let l=(s,c)=>n[c]?s.route.id!==n[c].route.id:!0,u=(s,c)=>n[c].pathname!==s.pathname||n[c].route.path?.endsWith("*")&&n[c].params["*"]!==s.params["*"];return a==="assets"?t.filter((s,c)=>l(s,c)||u(s,c)):a==="data"?t.filter((s,c)=>{let d=o.routes[s.route.id];if(!d||!d.hasLoader)return!1;if(l(s,c)||u(s,c))return!0;if(s.route.shouldRevalidate){let f=s.route.shouldRevalidate({currentUrl:new URL(r.pathname+r.search+r.hash,window.origin),currentParams:n[0]?.params||{},nextUrl:new URL(e,window.origin),nextParams:s.params,defaultShouldRevalidate:!0});if(typeof f=="boolean")return f}return!0}):[]}function At(e,t,{includeHydrateFallback:n}={}){return Bt(e.map(o=>{let r=t.routes[o.route.id];if(!r)return[];let a=[r.module];return r.clientActionModule&&(a=a.concat(r.clientActionModule)),r.clientLoaderModule&&(a=a.concat(r.clientLoaderModule)),n&&r.hydrateFallbackModule&&(a=a.concat(r.hydrateFallbackModule)),r.imports&&(a=a.concat(r.imports)),a}).flat(1))}function Bt(e){return[...new Set(e)]}function _t(e){let t={},n=Object.keys(e).sort();for(let o of n)t[o]=e[o];return t}function Wt(e,t){let n=new Set;return new Set(t),e.reduce((o,r)=>{let a=JSON.stringify(_t(r));return n.has(a)||(n.add(a),o.push({key:a,link:r})),o},[])}function be(){let e=i.useContext(F);return te(e,"You must render this element inside a <DataRouterContext.Provider> element"),e}function Ht(){let e=i.useContext(J);return te(e,"You must render this element inside a <DataRouterStateContext.Provider> element"),e}var ne=i.createContext(void 0);ne.displayName="FrameworkContext";function Se(){let e=i.useContext(ne);return te(e,"You must render this element inside a <HydratedRouter> element"),e}function jt(e,t){let n=i.useContext(ne),[o,r]=i.useState(!1),[a,l]=i.useState(!1),{onFocus:u,onBlur:s,onMouseEnter:c,onMouseLeave:d,onTouchStart:f}=t,y=i.useRef(null);i.useEffect(()=>{if(e==="render"&&l(!0),e==="viewport"){let p=w=>{w.forEach(g=>{l(g.isIntersecting)})},m=new IntersectionObserver(p,{threshold:.5});return y.current&&m.observe(y.current),()=>{m.disconnect()}}},[e]),i.useEffect(()=>{if(o){let p=setTimeout(()=>{l(!0)},100);return()=>{clearTimeout(p)}}},[o]);let h=()=>{r(!0)},v=()=>{r(!1),l(!1)};return n?e!=="intent"?[a,y,{}]:[a,y,{onFocus:A(u,h),onBlur:A(s,v),onMouseEnter:A(c,h),onMouseLeave:A(d,v),onTouchStart:A(f,h)}]:[!1,y,{}]}function A(e,t){return n=>{e&&e(n),n.defaultPrevented||t(n)}}function zt({page:e,...t}){let{router:n}=be(),o=i.useMemo(()=>se(n.routes,e,n.basename),[n.routes,e,n.basename]);return o?i.createElement(Jt,{page:e,matches:o,...t}):null}function Vt(e){let{manifest:t,routeModules:n}=Se(),[o,r]=i.useState([]);return i.useEffect(()=>{let a=!1;return Ut(e,t,n).then(l=>{a||r(l)}),()=>{a=!0}},[e,t,n]),o}function Jt({page:e,matches:t,...n}){let o=I(),{future:r,manifest:a,routeModules:l}=Se(),{basename:u}=be(),{loaderData:s,matches:c}=Ht(),d=i.useMemo(()=>ue(e,t,c,a,o,"data"),[e,t,c,a,o]),f=i.useMemo(()=>ue(e,t,c,a,o,"assets"),[e,t,c,a,o]),y=i.useMemo(()=>{if(e===o.pathname+o.search+o.hash)return[];let p=new Set,m=!1;if(t.forEach(g=>{let R=a.routes[g.route.id];!R||!R.hasLoader||(!d.some(C=>C.route.id===g.route.id)&&g.route.id in s&&l[g.route.id]?.shouldRevalidate||R.hasClientLoader?m=!0:p.add(g.route.id))}),p.size===0)return[];let w=Mt(e,u,r.unstable_trailingSlashAwareDataRequests,"data");return m&&p.size>0&&w.searchParams.set("_routes",t.filter(g=>p.has(g.route.id)).map(g=>g.route.id).join(",")),[w.pathname+w.search]},[u,r.unstable_trailingSlashAwareDataRequests,s,o,a,d,t,e,l]),h=i.useMemo(()=>At(f,a),[f,a]),v=Vt(f);return i.createElement(i.Fragment,null,y.map(p=>i.createElement("link",{key:p,rel:"prefetch",as:"fetch",href:p,...n})),h.map(p=>i.createElement("link",{key:p,rel:"modulepreload",href:p,...n})),v.map(({key:p,link:m})=>i.createElement("link",{key:p,nonce:n.nonce,...m,crossOrigin:m.crossOrigin??n.crossOrigin})))}function Kt(...e){return t=>{e.forEach(n=>{typeof n=="function"?n(t):n!=null&&(n.current=t)})}}var Yt=typeof window<"u"&&typeof window.document<"u"&&typeof window.document.createElement<"u";try{Yt&&(window.__reactRouterVersion="7.13.0")}catch{}function ln({basename:e,children:t,unstable_useTransitions:n,window:o}){let r=i.useRef();r.current==null&&(r.current=Te({window:o,v5Compat:!0}));let a=r.current,[l,u]=i.useState({action:a.action,location:a.location}),s=i.useCallback(c=>{n===!1?u(c):i.startTransition(()=>u(c))},[n]);return i.useLayoutEffect(()=>a.listen(s),[a,s]),i.createElement(Ce,{basename:e,children:t,location:l.location,navigationType:l.action,navigator:a,unstable_useTransitions:n})}var Le=/^(?:[a-z][a-z0-9+.-]*:|\/\/)/i,Pe=i.forwardRef(function({onClick:t,discover:n="render",prefetch:o="none",relative:r,reloadDocument:a,replace:l,state:u,target:s,to:c,preventScrollReset:d,viewTransition:f,unstable_defaultShouldRevalidate:y,...h},v){let{basename:p,unstable_useTransitions:m}=i.useContext(b),w=typeof c=="string"&&Le.test(c),g=pe(c,p);c=g.to;let R=ct(c,{relative:r}),[C,x,k]=jt(o,h),T=Qt(c,{replace:l,state:u,target:s,preventScrollReset:d,relative:r,viewTransition:f,unstable_defaultShouldRevalidate:y,unstable_useTransitions:m});function O(U){t&&t(U),U.defaultPrevented||T(U)}let D=i.createElement("a",{...h,...k,href:g.absoluteURL||R,onClick:g.isExternal||a?t:O,ref:Kt(v,x),target:s,"data-discover":!w&&n==="render"?"true":void 0});return C&&!w?i.createElement(i.Fragment,null,D,i.createElement(zt,{page:R})):D});Pe.displayName="Link";var Gt=i.forwardRef(function({"aria-current":t="page",caseSensitive:n=!1,className:o="",end:r=!1,style:a,to:l,viewTransition:u,children:s,...c},d){let f=_(l,{relative:c.relative}),y=I(),h=i.useContext(J),{navigator:v,basename:p}=i.useContext(b),m=h!=null&&rn(f)&&u===!0,w=v.encodeLocation?v.encodeLocation(f).pathname:f.pathname,g=y.pathname,R=h&&h.navigation&&h.navigation.location?h.navigation.location.pathname:null;n||(g=g.toLowerCase(),R=R?R.toLowerCase():null,w=w.toLowerCase()),R&&p&&(R=P(R,p)||R);const C=w!=="/"&&w.endsWith("/")?w.length-1:w.length;let x=g===w||!r&&g.startsWith(w)&&g.charAt(C)==="/",k=R!=null&&(R===w||!r&&R.startsWith(w)&&R.charAt(w.length)==="/"),T={isActive:x,isPending:k,isTransitioning:m},O=x?t:void 0,D;typeof o=="function"?D=o(T):D=[o,x?"active":null,k?"pending":null,m?"transitioning":null].filter(Boolean).join(" ");let U=typeof a=="function"?a(T):a;return i.createElement(Pe,{...c,"aria-current":O,className:D,ref:d,style:U,to:l,viewTransition:u},typeof s=="function"?s(T):s)});Gt.displayName="NavLink";var qt=i.forwardRef(({discover:e="render",fetcherKey:t,navigate:n,reloadDocument:o,replace:r,state:a,method:l=H,action:u,onSubmit:s,relative:c,preventScrollReset:d,viewTransition:f,unstable_defaultShouldRevalidate:y,...h},v)=>{let{unstable_useTransitions:p}=i.useContext(b),m=tn(),w=nn(u,{relative:c}),g=l.toLowerCase()==="get"?"get":"post",R=typeof u=="string"&&Le.test(u),C=x=>{if(s&&s(x),x.defaultPrevented)return;x.preventDefault();let k=x.nativeEvent.submitter,T=k?.getAttribute("formmethod")||l,O=()=>m(k||x.currentTarget,{fetcherKey:t,method:T,navigate:n,replace:r,state:a,relative:c,preventScrollReset:d,viewTransition:f,unstable_defaultShouldRevalidate:y});p&&n!==!1?i.startTransition(()=>O()):O()};return i.createElement("form",{ref:v,method:g,action:w,onSubmit:o?s:C,...h,"data-discover":!R&&e==="render"?"true":void 0})});qt.displayName="Form";function Xt(e){return`${e} must be used within a data router. See https://reactrouter.com/en/main/routers/picking-a-router.`}function $e(e){let t=i.useContext(F);return E(t,Xt(e)),t}function Qt(e,{target:t,replace:n,state:o,preventScrollReset:r,relative:a,viewTransition:l,unstable_defaultShouldRevalidate:u,unstable_useTransitions:s}={}){let c=ft(),d=I(),f=_(e,{relative:a});return i.useCallback(y=>{if(Tt(y,t)){y.preventDefault();let h=n!==void 0?n:M(d)===M(f),v=()=>c(e,{replace:h,state:o,preventScrollReset:r,relative:a,viewTransition:l,unstable_defaultShouldRevalidate:u});s?i.startTransition(()=>v()):v()}},[d,c,f,n,o,t,e,r,a,l,u,s])}var Zt=0,en=()=>`__${String(++Zt)}__`;function tn(){let{router:e}=$e("useSubmit"),{basename:t}=i.useContext(b),n=xt(),o=e.fetch,r=e.navigate;return i.useCallback(async(a,l={})=>{let{action:u,method:s,encType:c,formData:d,body:f}=Dt(a,t);if(l.navigate===!1){let y=l.fetcherKey||en();await o(y,n,l.action||u,{unstable_defaultShouldRevalidate:l.unstable_defaultShouldRevalidate,preventScrollReset:l.preventScrollReset,formData:d,body:f,formMethod:l.method||s,formEncType:l.encType||c,flushSync:l.flushSync})}else await r(l.action||u,{unstable_defaultShouldRevalidate:l.unstable_defaultShouldRevalidate,preventScrollReset:l.preventScrollReset,formData:d,body:f,formMethod:l.method||s,formEncType:l.encType||c,replace:l.replace,state:l.state,fromRouteId:n,flushSync:l.flushSync,viewTransition:l.viewTransition})},[o,r,t,n])}function nn(e,{relative:t}={}){let{basename:n}=i.useContext(b),o=i.useContext($);E(o,"useFormAction must be used inside a RouteContext");let[r]=o.matches.slice(-1),a={..._(e||".",{relative:t})},l=I();if(e==null){a.search=l.search;let u=new URLSearchParams(a.search),s=u.getAll("index");if(s.some(d=>d==="")){u.delete("index"),s.filter(f=>f).forEach(f=>u.append("index",f));let d=u.toString();a.search=d?`?${d}`:""}}return(!e||e===".")&&r.route.index&&(a.search=a.search?a.search.replace(/^\?/,"?index&"):"?index"),n!=="/"&&(a.pathname=a.pathname==="/"?n:L([n,a.pathname])),M(a)}function rn(e,{relative:t}={}){let n=i.useContext(ye);E(n!=null,"`useViewTransitionState` must be used within `react-router-dom`'s `RouterProvider`. Did you accidentally import `RouterProvider` from `react-router`?");let{basename:o}=$e("useViewTransitionState"),r=_(e,{relative:t});if(!n.isTransitioning)return!1;let a=P(n.currentLocation.pathname,o)||n.currentLocation.pathname,l=P(n.nextLocation.pathname,o)||n.nextLocation.pathname;return V(r.pathname,l)!=null||V(r.pathname,a)!=null}export{ln as B,on as M,I as a,B as b,ft as u};
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"name":"","short_name":"","icons":[{"src":"/android-chrome-192x192.png","sizes":"192x192","type":"image/png"},{"src":"/android-chrome-512x512.png","sizes":"512x512","type":"image/png"}],"theme_color":"#ffffff","background_color":"#ffffff","display":"standalone"}
|
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="UTF-8" />
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
6
|
+
<link rel="icon" type="image/x-icon" href="/taskforce/favicon/favicon.ico" />
|
|
7
|
+
<title>Taskforce Dashboard</title>
|
|
8
|
+
<script type="module" crossorigin src="/taskforce/assets/index-MCZuNNfn.js"></script>
|
|
9
|
+
<link rel="modulepreload" crossorigin href="/taskforce/assets/vendor-react-DdIDsh7f.js">
|
|
10
|
+
<link rel="modulepreload" crossorigin href="/taskforce/assets/vendor-icons-ZFG3SGwo.js">
|
|
11
|
+
<link rel="modulepreload" crossorigin href="/taskforce/assets/vendor-markdown-CKYkQHfj.js">
|
|
12
|
+
<link rel="modulepreload" crossorigin href="/taskforce/assets/vendor-dnd-BI1K77C1.js">
|
|
13
|
+
<link rel="modulepreload" crossorigin href="/taskforce/assets/vendor-router-BtiNU7Dl.js">
|
|
14
|
+
<link rel="stylesheet" crossorigin href="/taskforce/assets/index-0W5vyCpn.css">
|
|
15
|
+
</head>
|
|
16
|
+
<body>
|
|
17
|
+
<div id="root"></div>
|
|
18
|
+
</body>
|
|
19
|
+
</html>
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export interface ParsedChecklistLine {
|
|
2
|
+
lineIndex: number;
|
|
3
|
+
text: string;
|
|
4
|
+
completed: boolean;
|
|
5
|
+
}
|
|
6
|
+
export declare function parseChecklistLines(description: string): ParsedChecklistLine[];
|
|
7
|
+
export declare function appendChecklistLine(description: string, text: string): string;
|
|
8
|
+
export declare function removeChecklistLine(description: string, lineIndex: number): string;
|
|
9
|
+
export declare function setChecklistLineCompleted(description: string, lineIndex: number, completed: boolean): string;
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
const CHECKLIST_PATTERN = /^(\s*[-*]\s+\[)( |x|X)(\]\s+)(.*)$/;
|
|
2
|
+
export function parseChecklistLines(description) {
|
|
3
|
+
if (!description)
|
|
4
|
+
return [];
|
|
5
|
+
const lines = description.split(/\r?\n/);
|
|
6
|
+
const items = [];
|
|
7
|
+
lines.forEach((line, index) => {
|
|
8
|
+
const match = line.match(CHECKLIST_PATTERN);
|
|
9
|
+
if (!match)
|
|
10
|
+
return;
|
|
11
|
+
const text = String(match[4] || '').trim();
|
|
12
|
+
if (!text)
|
|
13
|
+
return;
|
|
14
|
+
items.push({
|
|
15
|
+
lineIndex: index,
|
|
16
|
+
text,
|
|
17
|
+
completed: String(match[2]).toLowerCase() === 'x'
|
|
18
|
+
});
|
|
19
|
+
});
|
|
20
|
+
return items;
|
|
21
|
+
}
|
|
22
|
+
export function appendChecklistLine(description, text) {
|
|
23
|
+
const normalizedText = text.trim();
|
|
24
|
+
if (!normalizedText)
|
|
25
|
+
return description || '';
|
|
26
|
+
const base = description ? description.replace(/\s+$/, '') : '';
|
|
27
|
+
return base ? `${base}\n- [ ] ${normalizedText}` : `- [ ] ${normalizedText}`;
|
|
28
|
+
}
|
|
29
|
+
export function removeChecklistLine(description, lineIndex) {
|
|
30
|
+
const lines = (description || '').split(/\r?\n/);
|
|
31
|
+
if (lineIndex < 0 || lineIndex >= lines.length)
|
|
32
|
+
return description || '';
|
|
33
|
+
lines.splice(lineIndex, 1);
|
|
34
|
+
return lines.join('\n').replace(/\s+$/, '');
|
|
35
|
+
}
|
|
36
|
+
export function setChecklistLineCompleted(description, lineIndex, completed) {
|
|
37
|
+
const lines = (description || '').split(/\r?\n/);
|
|
38
|
+
if (lineIndex < 0 || lineIndex >= lines.length)
|
|
39
|
+
return description || '';
|
|
40
|
+
const line = lines[lineIndex];
|
|
41
|
+
const match = line.match(CHECKLIST_PATTERN);
|
|
42
|
+
if (!match)
|
|
43
|
+
return description || '';
|
|
44
|
+
lines[lineIndex] = `${match[1]}${completed ? 'x' : ' '}${match[3]}${match[4]}`;
|
|
45
|
+
return lines.join('\n');
|
|
46
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
export declare const STORAGE_KEY = "taskforce-settings";
|
|
2
|
+
export declare const STATUS_OPTIONS: {
|
|
3
|
+
value: string;
|
|
4
|
+
label: string;
|
|
5
|
+
}[];
|
|
6
|
+
declare const curatedIcons: readonly ["Folder", "Code", "FileText", "Terminal", "Database", "Cpu", "Globe", "Layout", "Server", "Search", "Settings", "Zap", "Shield", "Star", "Layers", "Bug", "Box", "Book", "MessageSquare", "Image", "Music", "Video", "Map", "Mail", "Camera", "Heart", "Anchor", "Rocket", "Target", "Flag", "Bookmark", "Briefcase", "Puzzle", "SquareUserRound", "Users", "User", "Unplug", "Clock", "Lock", "Pencil", "TrafficCone", "CircleDollarSign", "Activity", "Wrench", "Microscope", "Palette", "Webhook", "FlaskConical", "Bot", "Cloud", "Kanban", "Infinity", "Monitor", "Smartphone", "History", "Brain", "Calendar", "Play", "Pause", "Sparkles", "Check", "Ban", "Circle", "CheckCircle", "Wind", "Github", "Inbox", "HelpCircle", "Gauge", "FileCode", "ArrowDown", "Minus", "ArrowUp", "AlertTriangle", "CircleQuestionMark", "TriangleAlert"];
|
|
7
|
+
export type IconName = typeof curatedIcons[number];
|
|
8
|
+
export declare const IconMap: Record<string, any>;
|
|
9
|
+
export declare const AVAILABLE_ICONS: readonly ["Folder", "Code", "FileText", "Terminal", "Database", "Cpu", "Globe", "Layout", "Server", "Search", "Settings", "Zap", "Shield", "Star", "Layers", "Bug", "Box", "Book", "MessageSquare", "Image", "Music", "Video", "Map", "Mail", "Camera", "Heart", "Anchor", "Rocket", "Target", "Flag", "Bookmark", "Briefcase", "Puzzle", "SquareUserRound", "Users", "User", "Unplug", "Clock", "Lock", "Pencil", "TrafficCone", "CircleDollarSign", "Activity", "Wrench", "Microscope", "Palette", "Webhook", "FlaskConical", "Bot", "Cloud", "Kanban", "Infinity", "Monitor", "Smartphone", "History", "Brain", "Calendar", "Play", "Pause", "Sparkles", "Check", "Ban", "Circle", "CheckCircle", "Wind", "Github", "Inbox", "HelpCircle", "Gauge", "FileCode", "ArrowDown", "Minus", "ArrowUp", "AlertTriangle", "CircleQuestionMark", "TriangleAlert"];
|
|
10
|
+
export declare const TypeMeta: Record<string, {
|
|
11
|
+
icon: string;
|
|
12
|
+
color: string;
|
|
13
|
+
}>;
|
|
14
|
+
export declare const COLOR_PALETTE: Record<string, string>;
|
|
15
|
+
export declare const PALETTE_ORDER: string[];
|
|
16
|
+
/**
|
|
17
|
+
* Resolves a color value to a valid CSS hex string.
|
|
18
|
+
* Supports token IDs (e.g. 'red-500') and raw hex codes.
|
|
19
|
+
*/
|
|
20
|
+
export declare function resolveColor(colorValue?: string): string | undefined;
|
|
21
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { describe, it, expect } from 'vitest';
|
|
2
|
+
import { AVAILABLE_ICONS, IconMap, TypeMeta } from './constants';
|
|
3
|
+
import { DEFAULT_CONFIG } from '../types';
|
|
4
|
+
function collectIcons(items) {
|
|
5
|
+
return items
|
|
6
|
+
.map((item) => item.icon)
|
|
7
|
+
.filter((icon) => typeof icon === 'string' && icon.length > 0);
|
|
8
|
+
}
|
|
9
|
+
describe('icon registry coverage', () => {
|
|
10
|
+
it('resolves all system/default icon names through IconMap', () => {
|
|
11
|
+
const systemIconNames = new Set([
|
|
12
|
+
...AVAILABLE_ICONS,
|
|
13
|
+
...Object.values(TypeMeta).map((meta) => meta.icon),
|
|
14
|
+
...collectIcons(DEFAULT_CONFIG.categories),
|
|
15
|
+
...collectIcons(DEFAULT_CONFIG.priorities),
|
|
16
|
+
...collectIcons(DEFAULT_CONFIG.approaches),
|
|
17
|
+
// Schedule/hierarchy/assignee columns and form defaults used in the app.
|
|
18
|
+
'Calendar',
|
|
19
|
+
'Gauge',
|
|
20
|
+
'Bot',
|
|
21
|
+
'User',
|
|
22
|
+
'Circle',
|
|
23
|
+
'Inbox',
|
|
24
|
+
'Layers',
|
|
25
|
+
'Palette',
|
|
26
|
+
'Server',
|
|
27
|
+
'HelpCircle',
|
|
28
|
+
'Folder',
|
|
29
|
+
// Environment templates
|
|
30
|
+
'Wind',
|
|
31
|
+
'Github',
|
|
32
|
+
// Requested additions
|
|
33
|
+
'CircleQuestionMark',
|
|
34
|
+
'TriangleAlert'
|
|
35
|
+
]);
|
|
36
|
+
for (const iconName of systemIconNames) {
|
|
37
|
+
expect(IconMap[iconName], `Missing IconMap entry for "${iconName}"`).toBeTruthy();
|
|
38
|
+
}
|
|
39
|
+
});
|
|
40
|
+
});
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import * as Icons from 'lucide-react';
|
|
2
|
+
export const STORAGE_KEY = 'taskforce-settings';
|
|
3
|
+
export const STATUS_OPTIONS = [
|
|
4
|
+
{ value: 'task', label: 'To Do' },
|
|
5
|
+
{ value: 'on-hold', label: 'Blocked' },
|
|
6
|
+
{ value: 'in-progress', label: 'In Progress' },
|
|
7
|
+
{ value: 'review', label: 'Ready for Review' },
|
|
8
|
+
{ value: 'done', label: 'Completed' },
|
|
9
|
+
{ value: 'cancelled', label: 'Cancelled' }
|
|
10
|
+
];
|
|
11
|
+
// Curated list of icons for categories.
|
|
12
|
+
// Adding a name here automatically imports it and adds it to the list of choices in settings.
|
|
13
|
+
const curatedIcons = [
|
|
14
|
+
'Folder', 'Code', 'FileText', 'Terminal', 'Database', 'Cpu', 'Globe', 'Layout', 'Server', 'Search', 'Settings',
|
|
15
|
+
'Zap', 'Shield', 'Star', 'Layers', 'Bug', 'Box', 'Book', 'MessageSquare', 'Image', 'Music', 'Video', 'Map',
|
|
16
|
+
'Mail', 'Camera', 'Heart', 'Anchor', 'Rocket', 'Target', 'Flag', 'Bookmark', 'Briefcase',
|
|
17
|
+
'Puzzle', 'SquareUserRound', 'Users', 'User', 'Unplug', 'Clock', 'Lock', 'Pencil', 'TrafficCone', 'CircleDollarSign',
|
|
18
|
+
'Activity', 'Wrench', 'Microscope', 'Palette', 'Webhook', 'FlaskConical',
|
|
19
|
+
'Bot', 'Cloud', 'Kanban', 'Infinity', 'Monitor', 'Smartphone', 'History', 'Brain', 'Calendar',
|
|
20
|
+
'Play', 'Pause', 'Sparkles', 'Check', 'Ban', 'Circle', 'CheckCircle', 'Wind', 'Github',
|
|
21
|
+
// Used by built-in columns/taxonomies/defaults.
|
|
22
|
+
'Inbox', 'HelpCircle', 'Gauge', 'FileCode',
|
|
23
|
+
'ArrowDown', 'Minus', 'ArrowUp', 'AlertTriangle',
|
|
24
|
+
// Explicitly requested aliases/new options.
|
|
25
|
+
'CircleQuestionMark', 'TriangleAlert'
|
|
26
|
+
];
|
|
27
|
+
// Dynamically build the IconMap by looking up the components in the Lucide bundle
|
|
28
|
+
export const IconMap = curatedIcons.reduce((acc, name) => {
|
|
29
|
+
acc[name] = Icons[name] || Icons.HelpCircle;
|
|
30
|
+
return acc;
|
|
31
|
+
}, {});
|
|
32
|
+
export const AVAILABLE_ICONS = curatedIcons;
|
|
33
|
+
export const TypeMeta = {
|
|
34
|
+
bug: { icon: 'Bug', color: 'red-500' },
|
|
35
|
+
feature: { icon: 'Star', color: 'teal-500' },
|
|
36
|
+
chore: { icon: 'Zap', color: 'amber-500' },
|
|
37
|
+
refactor: { icon: 'Code', color: 'blue-500' },
|
|
38
|
+
documentation: { icon: 'Book', color: 'sky-500' }
|
|
39
|
+
};
|
|
40
|
+
// ------------------------------------------------------------------
|
|
41
|
+
// Color Palette System (Token-based)
|
|
42
|
+
// ------------------------------------------------------------------
|
|
43
|
+
export const COLOR_PALETTE = {
|
|
44
|
+
// Light Row (normalized curve)
|
|
45
|
+
'red-200': '#eb7a7a',
|
|
46
|
+
'orange-200': '#eba87a',
|
|
47
|
+
'amber-200': '#ebc17a',
|
|
48
|
+
'yellow-200': '#ebd07a',
|
|
49
|
+
'green-200': '#7aeba4',
|
|
50
|
+
'teal-200': '#7aebdf',
|
|
51
|
+
'sky-200': '#7ac8eb',
|
|
52
|
+
'blue-200': '#7aa5eb',
|
|
53
|
+
'indigo-200': '#7a7ceb',
|
|
54
|
+
'violet-200': '#9c7aeb',
|
|
55
|
+
// Medium Row (normalized curve)
|
|
56
|
+
'red-500': '#e42525',
|
|
57
|
+
'orange-500': '#e47325',
|
|
58
|
+
'amber-500': '#e49d25',
|
|
59
|
+
'yellow-500': '#e4b625',
|
|
60
|
+
'green-500': '#25e46b',
|
|
61
|
+
'teal-500': '#25e4cf',
|
|
62
|
+
'sky-500': '#25a9e4',
|
|
63
|
+
'blue-500': '#256ee4',
|
|
64
|
+
'indigo-500': '#2529e4',
|
|
65
|
+
'violet-500': '#5f25e4',
|
|
66
|
+
// Dark Row (normalized curve)
|
|
67
|
+
'red-700': '#951818',
|
|
68
|
+
'orange-700': '#954b18',
|
|
69
|
+
'amber-700': '#956718',
|
|
70
|
+
'yellow-700': '#957718',
|
|
71
|
+
'green-700': '#189546',
|
|
72
|
+
'teal-700': '#189587',
|
|
73
|
+
'sky-700': '#186e95',
|
|
74
|
+
'blue-700': '#184895',
|
|
75
|
+
'indigo-700': '#181b95',
|
|
76
|
+
'violet-700': '#3e1895',
|
|
77
|
+
};
|
|
78
|
+
// Ordered list of IDs for the color picker grid (Row by Row)
|
|
79
|
+
export const PALETTE_ORDER = [
|
|
80
|
+
// Light
|
|
81
|
+
'red-200', 'orange-200', 'amber-200', 'yellow-200', 'green-200', 'teal-200', 'sky-200', 'blue-200', 'indigo-200', 'violet-200',
|
|
82
|
+
// Medium
|
|
83
|
+
'red-500', 'orange-500', 'amber-500', 'yellow-500', 'green-500', 'teal-500', 'sky-500', 'blue-500', 'indigo-500', 'violet-500',
|
|
84
|
+
// Dark
|
|
85
|
+
'red-700', 'orange-700', 'amber-700', 'yellow-700', 'green-700', 'teal-700', 'sky-700', 'blue-700', 'indigo-700', 'violet-700',
|
|
86
|
+
];
|
|
87
|
+
/**
|
|
88
|
+
* Resolves a color value to a valid CSS hex string.
|
|
89
|
+
* Supports token IDs (e.g. 'red-500') and raw hex codes.
|
|
90
|
+
*/
|
|
91
|
+
export function resolveColor(colorValue) {
|
|
92
|
+
if (!colorValue)
|
|
93
|
+
return undefined;
|
|
94
|
+
// Check if it's a token
|
|
95
|
+
if (COLOR_PALETTE[colorValue]) {
|
|
96
|
+
return COLOR_PALETTE[colorValue];
|
|
97
|
+
}
|
|
98
|
+
// Return as-is (legacy hex or other format)
|
|
99
|
+
return colorValue;
|
|
100
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export interface OpenMarkdownEditorDetail {
|
|
2
|
+
path: string;
|
|
3
|
+
fsPath: string;
|
|
4
|
+
}
|
|
5
|
+
export declare function extractContextLinkedPath(sourcePath: string): string | null;
|
|
6
|
+
export declare function resolveContextFsPath(sourcePath: string, fsPath?: string): string | null;
|
|
7
|
+
export declare function isMarkdownContextFile(sourcePath: string, fsPath?: string): boolean;
|
|
8
|
+
export declare function dispatchOpenMarkdownDocument(sourcePath: string, fsPath?: string): boolean;
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
function normalizeCandidate(value) {
|
|
2
|
+
return value.trim().replace(/\\/g, '/');
|
|
3
|
+
}
|
|
4
|
+
function stripQueryAndHash(value) {
|
|
5
|
+
return value.split('?')[0].split('#')[0];
|
|
6
|
+
}
|
|
7
|
+
export function extractContextLinkedPath(sourcePath) {
|
|
8
|
+
if (!sourcePath.includes('/api/taskforce/context-link?path='))
|
|
9
|
+
return null;
|
|
10
|
+
try {
|
|
11
|
+
const parsed = new URL(sourcePath, window.location.origin);
|
|
12
|
+
const linkedPath = parsed.searchParams.get('path');
|
|
13
|
+
return linkedPath ? normalizeCandidate(linkedPath) : null;
|
|
14
|
+
}
|
|
15
|
+
catch {
|
|
16
|
+
return null;
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
export function resolveContextFsPath(sourcePath, fsPath) {
|
|
20
|
+
const normalizedFsPath = (fsPath || '').trim();
|
|
21
|
+
if (normalizedFsPath)
|
|
22
|
+
return normalizeCandidate(normalizedFsPath);
|
|
23
|
+
const linkedPath = extractContextLinkedPath(sourcePath);
|
|
24
|
+
return linkedPath ? normalizeCandidate(linkedPath) : null;
|
|
25
|
+
}
|
|
26
|
+
export function isMarkdownContextFile(sourcePath, fsPath) {
|
|
27
|
+
const candidates = [
|
|
28
|
+
(fsPath || '').trim(),
|
|
29
|
+
extractContextLinkedPath(sourcePath) || '',
|
|
30
|
+
sourcePath
|
|
31
|
+
];
|
|
32
|
+
return candidates.some((candidate) => {
|
|
33
|
+
if (!candidate)
|
|
34
|
+
return false;
|
|
35
|
+
const normalized = stripQueryAndHash(normalizeCandidate(candidate)).toLowerCase();
|
|
36
|
+
return normalized.endsWith('.md') || normalized.endsWith('.markdown');
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
export function dispatchOpenMarkdownDocument(sourcePath, fsPath) {
|
|
40
|
+
const resolvedFsPath = resolveContextFsPath(sourcePath, fsPath);
|
|
41
|
+
if (!resolvedFsPath)
|
|
42
|
+
return false;
|
|
43
|
+
if (!isMarkdownContextFile(sourcePath, resolvedFsPath))
|
|
44
|
+
return false;
|
|
45
|
+
const event = new CustomEvent('taskforce:open-markdown-document', {
|
|
46
|
+
detail: {
|
|
47
|
+
path: sourcePath,
|
|
48
|
+
fsPath: resolvedFsPath
|
|
49
|
+
},
|
|
50
|
+
cancelable: true
|
|
51
|
+
});
|
|
52
|
+
// dispatchEvent returns false when a listener calls preventDefault().
|
|
53
|
+
return !window.dispatchEvent(event);
|
|
54
|
+
}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
type DateInput = Date | string | number;
|
|
2
|
+
export declare function formatDate(value: DateInput, options: Intl.DateTimeFormatOptions, locale?: string): string;
|
|
3
|
+
export declare function formatNumber(value: number, options?: Intl.NumberFormatOptions, locale?: string): string;
|
|
4
|
+
export declare function formatCurrency(value: number, currency: string, locale?: string): string;
|
|
5
|
+
export {};
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { getLocale } from '../localization';
|
|
2
|
+
const formatterCache = new Map();
|
|
3
|
+
function toDate(value) {
|
|
4
|
+
const next = value instanceof Date ? value : new Date(value);
|
|
5
|
+
return Number.isNaN(next.getTime()) ? null : next;
|
|
6
|
+
}
|
|
7
|
+
function formatterKey(locale, options) {
|
|
8
|
+
const sortedOptions = Object.entries(options).sort(([a], [b]) => a.localeCompare(b));
|
|
9
|
+
return JSON.stringify([locale, sortedOptions]);
|
|
10
|
+
}
|
|
11
|
+
export function formatDate(value, options, locale) {
|
|
12
|
+
const date = toDate(value);
|
|
13
|
+
if (!date)
|
|
14
|
+
return '';
|
|
15
|
+
const resolvedLocale = locale ?? getLocale();
|
|
16
|
+
const key = formatterKey(resolvedLocale, options);
|
|
17
|
+
let formatter = formatterCache.get(key);
|
|
18
|
+
if (!formatter) {
|
|
19
|
+
formatter = new Intl.DateTimeFormat(resolvedLocale, options);
|
|
20
|
+
formatterCache.set(key, formatter);
|
|
21
|
+
}
|
|
22
|
+
return formatter.format(date);
|
|
23
|
+
}
|
|
24
|
+
export function formatNumber(value, options, locale) {
|
|
25
|
+
const resolvedLocale = locale ?? getLocale();
|
|
26
|
+
return new Intl.NumberFormat(resolvedLocale, options).format(value);
|
|
27
|
+
}
|
|
28
|
+
export function formatCurrency(value, currency, locale) {
|
|
29
|
+
return formatNumber(value, { style: 'currency', currency }, locale);
|
|
30
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* planParser.ts
|
|
3
|
+
* Parses a markdown implementation plan into a structured task tree.
|
|
4
|
+
* Pure function — no I/O, no side effects.
|
|
5
|
+
*/
|
|
6
|
+
export type ParsedTaskType = 'feature' | 'bug' | 'chore' | 'refactor' | 'documentation';
|
|
7
|
+
export type ParsedTaskPriority = 1 | 2 | 3 | 4;
|
|
8
|
+
export interface ParsedTask {
|
|
9
|
+
/** Stable key for idempotent generation — derived from title + depth */
|
|
10
|
+
idempotencyKey: string;
|
|
11
|
+
title: string;
|
|
12
|
+
description: string;
|
|
13
|
+
type: ParsedTaskType;
|
|
14
|
+
priority: ParsedTaskPriority;
|
|
15
|
+
/** Nesting depth: 0 = top-level phase, 1 = task under phase, 2 = subtask */
|
|
16
|
+
depth: number;
|
|
17
|
+
children: ParsedTask[];
|
|
18
|
+
/** Whether this node is selected for generation (default true) */
|
|
19
|
+
selected: boolean;
|
|
20
|
+
}
|
|
21
|
+
export declare function parsePlan(markdown: string): ParsedTask[];
|
|
22
|
+
export declare function flattenSelected(tasks: ParsedTask[]): ParsedTask[];
|