unspaghettit 0.2.0 → 0.3.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/build/client/_app/immutable/assets/0.DSctqr5I.css +1 -0
- package/build/client/_app/immutable/assets/0.DSctqr5I.css.br +0 -0
- package/build/client/_app/immutable/assets/0.DSctqr5I.css.gz +0 -0
- package/build/client/_app/immutable/assets/BehaviorGraph.Bk0xQRZk.css +1 -0
- package/build/client/_app/immutable/assets/BehaviorGraph.Bk0xQRZk.css.br +0 -0
- package/build/client/_app/immutable/assets/BehaviorGraph.Bk0xQRZk.css.gz +0 -0
- package/build/client/_app/immutable/chunks/9nXQ5qrY2.js +1 -0
- package/build/client/_app/immutable/chunks/9nXQ5qrY2.js.br +0 -0
- package/build/client/_app/immutable/chunks/9nXQ5qrY2.js.gz +0 -0
- package/build/client/_app/immutable/chunks/B439_FLv.js +1 -0
- package/build/client/_app/immutable/chunks/B439_FLv.js.br +0 -0
- package/build/client/_app/immutable/chunks/B439_FLv.js.gz +0 -0
- package/build/client/_app/immutable/chunks/BCEY79Dw.js +1 -0
- package/build/client/_app/immutable/chunks/BCEY79Dw.js.br +2 -0
- package/build/client/_app/immutable/chunks/BCEY79Dw.js.gz +0 -0
- package/build/client/_app/immutable/chunks/{DBJWcC6Y.js → BYIrIC5L.js} +1 -1
- package/build/client/_app/immutable/chunks/BYIrIC5L.js.br +0 -0
- package/build/client/_app/immutable/chunks/BYIrIC5L.js.gz +0 -0
- package/build/client/_app/immutable/chunks/B_9TWPrx2.js +1 -0
- package/build/client/_app/immutable/chunks/B_9TWPrx2.js.br +0 -0
- package/build/client/_app/immutable/chunks/B_9TWPrx2.js.gz +0 -0
- package/build/client/_app/immutable/chunks/BvOhVtZg.js +1 -0
- package/build/client/_app/immutable/chunks/BvOhVtZg.js.br +1 -0
- package/build/client/_app/immutable/chunks/BvOhVtZg.js.gz +0 -0
- package/build/client/_app/immutable/chunks/CY3em1ma2.js +1 -0
- package/build/client/_app/immutable/chunks/CY3em1ma2.js.br +0 -0
- package/build/client/_app/immutable/chunks/CY3em1ma2.js.gz +0 -0
- package/build/client/_app/immutable/chunks/CgdRZPgI.js +1 -0
- package/build/client/_app/immutable/chunks/CgdRZPgI.js.br +0 -0
- package/build/client/_app/immutable/chunks/CgdRZPgI.js.gz +0 -0
- package/build/client/_app/immutable/chunks/D5speDV82.js +908 -0
- package/build/client/_app/immutable/chunks/D5speDV82.js.br +0 -0
- package/build/client/_app/immutable/chunks/D5speDV82.js.gz +0 -0
- package/build/client/_app/immutable/chunks/DkxwAIfJ2.js +1 -0
- package/build/client/_app/immutable/chunks/DkxwAIfJ2.js.br +0 -0
- package/build/client/_app/immutable/chunks/DkxwAIfJ2.js.gz +0 -0
- package/build/client/_app/immutable/chunks/{DatGSObE.js → OJscNS3T.js} +1 -1
- package/build/client/_app/immutable/chunks/OJscNS3T.js.br +0 -0
- package/build/client/_app/immutable/chunks/OJscNS3T.js.gz +0 -0
- package/build/client/_app/immutable/chunks/U9p9CtKG2.js +2 -0
- package/build/client/_app/immutable/chunks/U9p9CtKG2.js.br +0 -0
- package/build/client/_app/immutable/chunks/U9p9CtKG2.js.gz +0 -0
- package/build/client/_app/immutable/entry/app.Cd4S3giu.js +2 -0
- package/build/client/_app/immutable/entry/app.Cd4S3giu.js.br +0 -0
- package/build/client/_app/immutable/entry/app.Cd4S3giu.js.gz +0 -0
- package/build/client/_app/immutable/entry/start.C3xXQVkq.js +1 -0
- package/build/client/_app/immutable/entry/start.C3xXQVkq.js.br +0 -0
- package/build/client/_app/immutable/entry/start.C3xXQVkq.js.gz +0 -0
- package/build/client/_app/immutable/nodes/0.dIOlQ-0y.js +4 -0
- package/build/client/_app/immutable/nodes/0.dIOlQ-0y.js.br +0 -0
- package/build/client/_app/immutable/nodes/0.dIOlQ-0y.js.gz +0 -0
- package/build/client/_app/immutable/nodes/{1.KYdA6ppX.js → 1.Dyte3Ggf.js} +1 -1
- package/build/client/_app/immutable/nodes/1.Dyte3Ggf.js.br +2 -0
- package/build/client/_app/immutable/nodes/1.Dyte3Ggf.js.gz +0 -0
- package/build/client/_app/immutable/nodes/10.ivxAosDg.js +2 -0
- package/build/client/_app/immutable/nodes/10.ivxAosDg.js.br +0 -0
- package/build/client/_app/immutable/nodes/10.ivxAosDg.js.gz +0 -0
- package/build/client/_app/immutable/nodes/{9.CMW6a2Lg.js → 11.wvMfJKC2.js} +1 -1
- package/build/client/_app/immutable/nodes/11.wvMfJKC2.js.br +0 -0
- package/build/client/_app/immutable/nodes/11.wvMfJKC2.js.gz +0 -0
- package/build/client/_app/immutable/nodes/{2.DBz20KgG.js → 2.CmPPom9Z.js} +1 -1
- package/build/client/_app/immutable/nodes/2.CmPPom9Z.js.br +0 -0
- package/build/client/_app/immutable/nodes/2.CmPPom9Z.js.gz +0 -0
- package/build/client/_app/immutable/nodes/3.D-iCGCEx.js +1 -0
- package/build/client/_app/immutable/nodes/3.D-iCGCEx.js.br +0 -0
- package/build/client/_app/immutable/nodes/3.D-iCGCEx.js.gz +0 -0
- package/build/client/_app/immutable/nodes/{4.BvMzqBJj.js → 4.DbfAvO8Z.js} +1 -1
- package/build/client/_app/immutable/nodes/4.DbfAvO8Z.js.br +0 -0
- package/build/client/_app/immutable/nodes/4.DbfAvO8Z.js.gz +0 -0
- package/build/client/_app/immutable/nodes/5.CC5Q7lVw.js +42 -0
- package/build/client/_app/immutable/nodes/5.CC5Q7lVw.js.br +0 -0
- package/build/client/_app/immutable/nodes/5.CC5Q7lVw.js.gz +0 -0
- package/build/client/_app/immutable/nodes/6.CHIjlzpO.js +1 -0
- package/build/client/_app/immutable/nodes/6.CHIjlzpO.js.br +0 -0
- package/build/client/_app/immutable/nodes/6.CHIjlzpO.js.gz +0 -0
- package/build/client/_app/immutable/nodes/{6.BOHISqs-.js → 7.Ejs18ZUc.js} +1 -1
- package/build/client/_app/immutable/nodes/7.Ejs18ZUc.js.br +0 -0
- package/build/client/_app/immutable/nodes/7.Ejs18ZUc.js.gz +0 -0
- package/build/client/_app/immutable/nodes/{7.CemgNJfw.js → 8.B-HweAc8.js} +1 -1
- package/build/client/_app/immutable/nodes/8.B-HweAc8.js.br +0 -0
- package/build/client/_app/immutable/nodes/8.B-HweAc8.js.gz +0 -0
- package/build/client/_app/immutable/nodes/9.CKPeM6tx.js +5 -0
- package/build/client/_app/immutable/nodes/9.CKPeM6tx.js.br +0 -0
- package/build/client/_app/immutable/nodes/9.CKPeM6tx.js.gz +0 -0
- package/build/client/_app/version.json +1 -1
- package/build/client/_app/version.json.br +0 -0
- package/build/client/_app/version.json.gz +0 -0
- package/build/client/lyriks_logo.svg +148 -0
- package/build/client/lyriks_logo.svg.br +0 -0
- package/build/client/lyriks_logo.svg.gz +0 -0
- package/build/server/chunks/{0-C_o0oz-N.js → 0-Co8kcANG.js} +4 -4
- package/build/server/chunks/{0-C_o0oz-N.js.map → 0-Co8kcANG.js.map} +1 -1
- package/build/server/chunks/1-BSUItTig.js +9 -0
- package/build/server/chunks/{1-DPpKAKXV.js.map → 1-BSUItTig.js.map} +1 -1
- package/build/server/chunks/10-BygvxrZp.js +9 -0
- package/build/server/chunks/10-BygvxrZp.js.map +1 -0
- package/build/server/chunks/11-DRx0tRx2.js +9 -0
- package/build/server/chunks/11-DRx0tRx2.js.map +1 -0
- package/build/server/chunks/{2-AlfFqtL1.js → 2-BQT3m1vc.js} +3 -3
- package/build/server/chunks/{2-AlfFqtL1.js.map → 2-BQT3m1vc.js.map} +1 -1
- package/build/server/chunks/{3-vbjUt_51.js → 3-DPZ9BquJ.js} +3 -3
- package/build/server/chunks/{3-vbjUt_51.js.map → 3-DPZ9BquJ.js.map} +1 -1
- package/build/server/chunks/{4-BNow4x6D.js → 4-DHo47YX6.js} +3 -3
- package/build/server/chunks/{4-BNow4x6D.js.map → 4-DHo47YX6.js.map} +1 -1
- package/build/server/chunks/5-Cp9evBAG.js +9 -0
- package/build/server/chunks/5-Cp9evBAG.js.map +1 -0
- package/build/server/chunks/6-DiBq3bOV.js +9 -0
- package/build/server/chunks/6-DiBq3bOV.js.map +1 -0
- package/build/server/chunks/{6-QQ7r8Rd5.js → 7-C4hmS0dG.js} +3 -3
- package/build/server/chunks/{6-QQ7r8Rd5.js.map → 7-C4hmS0dG.js.map} +1 -1
- package/build/server/chunks/{7-CbPLGaIG.js → 8-CFFuDzBC.js} +4 -4
- package/build/server/chunks/{7-CbPLGaIG.js.map → 8-CFFuDzBC.js.map} +1 -1
- package/build/server/chunks/9-nhhKZJrs.js +9 -0
- package/build/server/chunks/9-nhhKZJrs.js.map +1 -0
- package/build/server/chunks/BehaviorGraph-m5kYj5HH.js +757 -0
- package/build/server/chunks/BehaviorGraph-m5kYj5HH.js.map +1 -0
- package/build/server/chunks/{FeatureCard-BQOY6gJQ.js → FeatureCard-CfbXNYe8.js} +2 -2
- package/build/server/chunks/{FeatureCard-BQOY6gJQ.js.map → FeatureCard-CfbXNYe8.js.map} +1 -1
- package/build/server/chunks/{ProgressBar-CfhccQ83.js → ProgressBar-DDoQJ_C9.js} +2 -2
- package/build/server/chunks/ProgressBar-DDoQJ_C9.js.map +1 -0
- package/build/server/chunks/{ProjectsIndex-CoDrvRya.js → ProjectsIndex-DUVJ3hyL.js} +2 -2
- package/build/server/chunks/{ProjectsIndex-CoDrvRya.js.map → ProjectsIndex-DUVJ3hyL.js.map} +1 -1
- package/build/server/chunks/TransitionCatalog-B8zHs-2E.js +271 -0
- package/build/server/chunks/TransitionCatalog-B8zHs-2E.js.map +1 -0
- package/build/server/chunks/{_layout.svelte-BREws55o.js → _layout.svelte-CLTmk0xU.js} +66 -15
- package/build/server/chunks/_layout.svelte-CLTmk0xU.js.map +1 -0
- package/build/server/chunks/{_page.svelte-De508ek8.js → _page.svelte-B1nG3PKn.js} +4 -4
- package/build/server/chunks/{_page.svelte-De508ek8.js.map → _page.svelte-B1nG3PKn.js.map} +1 -1
- package/build/server/chunks/{_page.svelte-Zf9H4KOP.js → _page.svelte-BW_nbAAH.js} +11 -315
- package/build/server/chunks/_page.svelte-BW_nbAAH.js.map +1 -0
- package/build/server/chunks/{_page.svelte-BqSC-1vK.js → _page.svelte-Caq7J0jU.js} +91 -47
- package/build/server/chunks/_page.svelte-Caq7J0jU.js.map +1 -0
- package/build/server/chunks/{_page.svelte-B7hT3P8E.js → _page.svelte-Cham-dsM.js} +4 -4
- package/build/server/chunks/{_page.svelte-B7hT3P8E.js.map → _page.svelte-Cham-dsM.js.map} +1 -1
- package/build/server/chunks/_page.svelte-Dhwjwph_.js +41 -0
- package/build/server/chunks/_page.svelte-Dhwjwph_.js.map +1 -0
- package/build/server/chunks/{_page.svelte-BKKCa9H5.js → _page.svelte-DlFVT40-.js} +3 -3
- package/build/server/chunks/{_page.svelte-BKKCa9H5.js.map → _page.svelte-DlFVT40-.js.map} +1 -1
- package/build/server/chunks/{_page.svelte-BtI2zZ_Z.js → _page.svelte-NVT2dzpG.js} +176 -327
- package/build/server/chunks/_page.svelte-NVT2dzpG.js.map +1 -0
- package/build/server/chunks/{_page.svelte-BKTveFAj.js → _page.svelte-Oj-W7G5s.js} +5 -5
- package/build/server/chunks/{_page.svelte-BKTveFAj.js.map → _page.svelte-Oj-W7G5s.js.map} +1 -1
- package/build/server/chunks/_page.svelte-Z_kK2lHY.js +68 -0
- package/build/server/chunks/_page.svelte-Z_kK2lHY.js.map +1 -0
- package/build/server/chunks/{builderModeStore.svelte-ihupr-3p.js → builderModeStore.svelte-BpRIU_zP.js} +217 -6
- package/build/server/chunks/builderModeStore.svelte-BpRIU_zP.js.map +1 -0
- package/build/server/chunks/client-DeX3TC3s.js +51 -0
- package/build/server/chunks/{client-DfpLcAZ9.js.map → client-DeX3TC3s.js.map} +1 -1
- package/build/server/chunks/{error.svelte-C35KOpru.js → error.svelte-Cdjeq3L2.js} +4 -4
- package/build/server/chunks/{error.svelte-C35KOpru.js.map → error.svelte-Cdjeq3L2.js.map} +1 -1
- package/build/server/chunks/featureStore.svelte-DIYgPBVm.js +161 -0
- package/build/server/chunks/featureStore.svelte-DIYgPBVm.js.map +1 -0
- package/build/server/chunks/{hooks.server-Rv301GTB.js → hooks.server-y3jdg_sB.js} +6 -2
- package/build/server/chunks/hooks.server-y3jdg_sB.js.map +1 -0
- package/build/server/chunks/{internal-BPKrFkK1.js → internal-KYK0WpL7.js} +4 -4
- package/build/server/chunks/{internal-BPKrFkK1.js.map → internal-KYK0WpL7.js.map} +1 -1
- package/build/server/chunks/projectFeaturesStore.svelte-2o-72_vr.js +313 -0
- package/build/server/chunks/projectFeaturesStore.svelte-2o-72_vr.js.map +1 -0
- package/build/server/chunks/{reconcile-Dv7jS3C8.js → reconcile-B5xqb6-s.js} +3 -272
- package/build/server/chunks/reconcile-B5xqb6-s.js.map +1 -0
- package/build/server/chunks/registry-DqAn_hVE.js +21 -0
- package/build/server/chunks/registry-DqAn_hVE.js.map +1 -0
- package/build/server/chunks/{state-CpLVNZq7.js → state-DBjl9lhV.js} +2 -2
- package/build/server/chunks/{state-CpLVNZq7.js.map → state-DBjl9lhV.js.map} +1 -1
- package/build/server/index.js +1 -1
- package/build/server/index.js.map +1 -1
- package/build/server/manifest.js +33 -17
- package/build/server/manifest.js.map +1 -1
- package/cli/commands/dashboard.ts +14 -0
- package/cli/commands/init.ts +26 -0
- package/cli/commands/theme.ts +62 -0
- package/cli/unspa.ts +38 -2
- package/cli/util/context-files.ts +5 -0
- package/cli/util/theme.ts +34 -0
- package/mcp-server/sync-notifier.ts +88 -35
- package/package.json +2 -1
- package/src/app.css +187 -0
- package/src/app.html +15 -1
- package/src/features/behavior-model/domain/services/BehaviorGraphModel.ts +531 -0
- package/src/features/behavior-model/presentation/adapters/VisBehaviorGraphRenderer.ts +492 -0
- package/src/features/behavior-model/presentation/components/BehaviorGraph.svelte +370 -0
- package/src/features/behavior-model/presentation/components/FeatureHeader.svelte +13 -5
- package/src/features/behavior-model/presentation/view-models/BehaviorGraphTheme.ts +43 -0
- package/src/features/builder-mode/domain/BuilderModeDashboard.ts +7 -1
- package/src/features/builder-mode/presentation/components/BuilderModeDashboard.svelte +78 -16
- package/src/features/builder-mode/presentation/components/BuilderTagChips.svelte +25 -0
- package/src/features/builder-mode/presentation/stores/builderModeStore.svelte.ts +247 -3
- package/src/features/projects/presentation/components/ProjectEditor.svelte +7 -0
- package/src/features/simulator/application/use-cases/RunScenarios.ts +15 -1
- package/src/hooks.server.ts +11 -1
- package/src/lib/theme/registry.ts +77 -0
- package/src/lib/theme/themeStore.svelte.ts +64 -0
- package/src/routes/+layout.svelte +184 -30
- package/src/routes/features/[id]/graph/+page.svelte +34 -0
- package/src/routes/projects/[id]/graph/+page.svelte +79 -0
- package/src/shared/presentation/components/ProgressBar.svelte +1 -1
- package/src/shared/presentation/toast/SyncToast.svelte +14 -3
- package/src/shared/presentation/toast/viewLinkResolver.ts +32 -0
- package/static/lyriks_logo.svg +148 -0
- package/build/client/_app/immutable/assets/0.DFMDYAU9.css +0 -1
- package/build/client/_app/immutable/assets/0.DFMDYAU9.css.br +0 -0
- package/build/client/_app/immutable/assets/0.DFMDYAU9.css.gz +0 -0
- package/build/client/_app/immutable/chunks/BO66rBOa2.js +0 -1
- package/build/client/_app/immutable/chunks/BO66rBOa2.js.br +0 -0
- package/build/client/_app/immutable/chunks/BO66rBOa2.js.gz +0 -0
- package/build/client/_app/immutable/chunks/DBJWcC6Y.js.br +0 -0
- package/build/client/_app/immutable/chunks/DBJWcC6Y.js.gz +0 -0
- package/build/client/_app/immutable/chunks/DHoA038D.js +0 -1
- package/build/client/_app/immutable/chunks/DHoA038D.js.br +0 -2
- package/build/client/_app/immutable/chunks/DHoA038D.js.gz +0 -0
- package/build/client/_app/immutable/chunks/DatGSObE.js.br +0 -0
- package/build/client/_app/immutable/chunks/DatGSObE.js.gz +0 -0
- package/build/client/_app/immutable/chunks/DjWKKtqp.js +0 -1
- package/build/client/_app/immutable/chunks/DjWKKtqp.js.br +0 -1
- package/build/client/_app/immutable/chunks/DjWKKtqp.js.gz +0 -0
- package/build/client/_app/immutable/chunks/Dq0DUAz1.js +0 -1
- package/build/client/_app/immutable/chunks/Dq0DUAz1.js.br +0 -0
- package/build/client/_app/immutable/chunks/Dq0DUAz1.js.gz +0 -0
- package/build/client/_app/immutable/chunks/iQu0D9Ux.js +0 -1
- package/build/client/_app/immutable/chunks/iQu0D9Ux.js.br +0 -0
- package/build/client/_app/immutable/chunks/iQu0D9Ux.js.gz +0 -0
- package/build/client/_app/immutable/entry/app.CLgh6Mx_.js +0 -2
- package/build/client/_app/immutable/entry/app.CLgh6Mx_.js.br +0 -0
- package/build/client/_app/immutable/entry/app.CLgh6Mx_.js.gz +0 -0
- package/build/client/_app/immutable/entry/start.D5GPCQZD.js +0 -1
- package/build/client/_app/immutable/entry/start.D5GPCQZD.js.br +0 -0
- package/build/client/_app/immutable/entry/start.D5GPCQZD.js.gz +0 -0
- package/build/client/_app/immutable/nodes/0.BOoI-hsu.js +0 -4
- package/build/client/_app/immutable/nodes/0.BOoI-hsu.js.br +0 -0
- package/build/client/_app/immutable/nodes/0.BOoI-hsu.js.gz +0 -0
- package/build/client/_app/immutable/nodes/1.KYdA6ppX.js.br +0 -2
- package/build/client/_app/immutable/nodes/1.KYdA6ppX.js.gz +0 -0
- package/build/client/_app/immutable/nodes/2.DBz20KgG.js.br +0 -0
- package/build/client/_app/immutable/nodes/2.DBz20KgG.js.gz +0 -0
- package/build/client/_app/immutable/nodes/3.19DIoFtw.js +0 -1
- package/build/client/_app/immutable/nodes/3.19DIoFtw.js.br +0 -0
- package/build/client/_app/immutable/nodes/3.19DIoFtw.js.gz +0 -0
- package/build/client/_app/immutable/nodes/4.BvMzqBJj.js.br +0 -0
- package/build/client/_app/immutable/nodes/4.BvMzqBJj.js.gz +0 -0
- package/build/client/_app/immutable/nodes/5.Dq6obSGG.js +0 -42
- package/build/client/_app/immutable/nodes/5.Dq6obSGG.js.br +0 -0
- package/build/client/_app/immutable/nodes/5.Dq6obSGG.js.gz +0 -0
- package/build/client/_app/immutable/nodes/6.BOHISqs-.js.br +0 -0
- package/build/client/_app/immutable/nodes/6.BOHISqs-.js.gz +0 -0
- package/build/client/_app/immutable/nodes/7.CemgNJfw.js.br +0 -0
- package/build/client/_app/immutable/nodes/7.CemgNJfw.js.gz +0 -0
- package/build/client/_app/immutable/nodes/8.DejSfIYh.js +0 -5
- package/build/client/_app/immutable/nodes/8.DejSfIYh.js.br +0 -0
- package/build/client/_app/immutable/nodes/8.DejSfIYh.js.gz +0 -0
- package/build/client/_app/immutable/nodes/9.CMW6a2Lg.js.br +0 -0
- package/build/client/_app/immutable/nodes/9.CMW6a2Lg.js.gz +0 -0
- package/build/server/chunks/1-DPpKAKXV.js +0 -9
- package/build/server/chunks/5-D7OCJpxD.js +0 -9
- package/build/server/chunks/5-D7OCJpxD.js.map +0 -1
- package/build/server/chunks/8-CVO-E-sf.js +0 -9
- package/build/server/chunks/8-CVO-E-sf.js.map +0 -1
- package/build/server/chunks/9-DxT1baO5.js +0 -9
- package/build/server/chunks/9-DxT1baO5.js.map +0 -1
- package/build/server/chunks/ProgressBar-CfhccQ83.js.map +0 -1
- package/build/server/chunks/_layout.svelte-BREws55o.js.map +0 -1
- package/build/server/chunks/_page.svelte-BqSC-1vK.js.map +0 -1
- package/build/server/chunks/_page.svelte-BtI2zZ_Z.js.map +0 -1
- package/build/server/chunks/_page.svelte-Zf9H4KOP.js.map +0 -1
- package/build/server/chunks/builderModeStore.svelte-ihupr-3p.js.map +0 -1
- package/build/server/chunks/client-DfpLcAZ9.js +0 -24
- package/build/server/chunks/hooks.server-Rv301GTB.js.map +0 -1
- package/build/server/chunks/reconcile-Dv7jS3C8.js.map +0 -1
- /package/build/client/_app/immutable/assets/{9.nv0I59TU.css → 11.nv0I59TU.css} +0 -0
- /package/build/client/_app/immutable/assets/{9.nv0I59TU.css.br → 11.nv0I59TU.css.br} +0 -0
- /package/build/client/_app/immutable/assets/{9.nv0I59TU.css.gz → 11.nv0I59TU.css.gz} +0 -0
|
@@ -10,6 +10,8 @@
|
|
|
10
10
|
import { projectsStore } from "$features/projects/presentation/stores/projectsStore.svelte";
|
|
11
11
|
import { builderModeStore } from "$features/builder-mode/presentation/stores/builderModeStore.svelte";
|
|
12
12
|
import { enabledViews, isEnabled } from "$lib/views/enabled";
|
|
13
|
+
import { themeStore } from "$lib/theme/themeStore.svelte";
|
|
14
|
+
import { ALL_THEMES } from "$lib/theme/registry";
|
|
13
15
|
import { identityStore } from "$shared/identity/identityStore.svelte";
|
|
14
16
|
import { authStore } from "$shared/security/authStore.svelte";
|
|
15
17
|
import {
|
|
@@ -23,6 +25,10 @@
|
|
|
23
25
|
// tries to read identityStore.author (notably the YDocClient
|
|
24
26
|
// building its WebSocket URL). Idempotent on re-mount.
|
|
25
27
|
identityStore.init();
|
|
28
|
+
// Mirror the active colour theme from the <html data-theme> attribute
|
|
29
|
+
// (server default + the inline head script's localStorage override) into
|
|
30
|
+
// reactive state so the header switcher and chrome track it live.
|
|
31
|
+
themeStore.init();
|
|
26
32
|
// Hydrate the optional dashboard auth token the same way. When
|
|
27
33
|
// unset, every API/SSE/WS request goes out unauthenticated; the
|
|
28
34
|
// first 401 from the server triggers `apiFetch`'s prompt-and-retry
|
|
@@ -73,6 +79,8 @@
|
|
|
73
79
|
let identityMenuRef = $state<HTMLDivElement | null>(null);
|
|
74
80
|
let settingsMenuOpen = $state(false);
|
|
75
81
|
let settingsMenuRef = $state<HTMLDivElement | null>(null);
|
|
82
|
+
let themeMenuOpen = $state(false);
|
|
83
|
+
let themeMenuRef = $state<HTMLDivElement | null>(null);
|
|
76
84
|
|
|
77
85
|
function handleGlobalMouseDown(event: MouseEvent) {
|
|
78
86
|
const target = event.target as Node;
|
|
@@ -90,6 +98,9 @@
|
|
|
90
98
|
) {
|
|
91
99
|
settingsMenuOpen = false;
|
|
92
100
|
}
|
|
101
|
+
if (themeMenuOpen && themeMenuRef && !themeMenuRef.contains(target)) {
|
|
102
|
+
themeMenuOpen = false;
|
|
103
|
+
}
|
|
93
104
|
}
|
|
94
105
|
|
|
95
106
|
async function pickRename() {
|
|
@@ -143,13 +154,25 @@
|
|
|
143
154
|
// only when more than one view is active — a toggle between one thing is
|
|
144
155
|
// meaningless. Builder is only "active" when it's both enabled and routed to.
|
|
145
156
|
const views = $derived(enabledViews());
|
|
146
|
-
|
|
157
|
+
// The Lyriks community edition presents a single, unswitched view, so hide
|
|
158
|
+
// the Expert/Builder switcher while that theme is active.
|
|
159
|
+
const showViewSwitcher = $derived(views.length > 1 && !themeStore.isLyriks);
|
|
147
160
|
const builderActive = $derived(
|
|
148
161
|
isEnabled("builder") && page.url.pathname.startsWith("/builder-mode"),
|
|
149
162
|
);
|
|
150
163
|
const mcpActive = $derived(page.url.pathname.startsWith("/mcp"));
|
|
151
|
-
//
|
|
152
|
-
|
|
164
|
+
// The feature editor + graph use a wider 1600px content column than the rest
|
|
165
|
+
// of the app (max-w-7xl). Match the header container to whichever the current
|
|
166
|
+
// route uses, so the header always spans the same width as the content below.
|
|
167
|
+
const wideContent = $derived(page.url.pathname.startsWith("/features/"));
|
|
168
|
+
// The Lyriks theme paints the header with a saturated violet→fuchsia
|
|
169
|
+
// gradient (see below) and the shell with a cool canvas. Cosmetic only.
|
|
170
|
+
const lyriks = $derived(themeStore.isLyriks);
|
|
171
|
+
const themes = ALL_THEMES;
|
|
172
|
+
// Dark chrome while in Builder OR under the Lyriks gradient header, so the
|
|
173
|
+
// header's foreground (logo, icons, switcher) stays legible on a dark/vivid
|
|
174
|
+
// background. The dropdown panels keep their own white surface regardless.
|
|
175
|
+
const dark = $derived(builderActive || lyriks);
|
|
153
176
|
const builderProject = $derived(
|
|
154
177
|
builderActive ? builderModeStore.selectedProject : null,
|
|
155
178
|
);
|
|
@@ -167,39 +190,65 @@
|
|
|
167
190
|
if (e.key === "Escape") {
|
|
168
191
|
identityMenuOpen = false;
|
|
169
192
|
settingsMenuOpen = false;
|
|
193
|
+
themeMenuOpen = false;
|
|
170
194
|
}
|
|
171
195
|
}}
|
|
172
196
|
/>
|
|
173
197
|
|
|
174
198
|
<div
|
|
175
|
-
class="flex min-h-full flex-col
|
|
199
|
+
class="flex min-h-full flex-col text-ink {lyriks
|
|
200
|
+
? 'bg-[linear-gradient(180deg,#e6ddfa_0%,#eeeafb_220px,#eeeafb_100%)]'
|
|
201
|
+
: 'bg-[linear-gradient(180deg,#f0fdfa_0%,#f8fafc_220px,#f8fafc_100%)]'}"
|
|
176
202
|
>
|
|
177
203
|
<header
|
|
178
|
-
class="sticky top-0 z-30 border-b backdrop-blur transition-colors {
|
|
179
|
-
? 'border-
|
|
180
|
-
:
|
|
204
|
+
class="sticky top-0 z-30 border-b backdrop-blur transition-colors {lyriks
|
|
205
|
+
? 'border-transparent bg-[linear-gradient(90deg,#6d28d9_0%,#a21caf_55%,#db2777_100%)]'
|
|
206
|
+
: dark
|
|
207
|
+
? 'border-slate-800 bg-slate-950/90'
|
|
208
|
+
: 'border-slate-200 bg-white/95'}"
|
|
181
209
|
>
|
|
182
210
|
<div
|
|
183
|
-
class="mx-auto flex h-16
|
|
211
|
+
class="mx-auto flex h-16 items-center justify-between px-4 sm:px-6 {wideContent
|
|
212
|
+
? 'max-w-400'
|
|
213
|
+
: 'max-w-7xl'}"
|
|
184
214
|
>
|
|
185
215
|
<div class="flex min-w-0 items-center gap-3">
|
|
186
|
-
<a href="/" class="flex shrink-0 items-center gap-2">
|
|
216
|
+
<a href="/" class="flex shrink-0 items-center gap-2.5">
|
|
187
217
|
<img
|
|
188
|
-
src="/unspaghettit_logo.png"
|
|
189
|
-
alt="Unspaghettit"
|
|
190
|
-
class="h-12 w-auto"
|
|
218
|
+
src={lyriks ? "/lyriks_logo.svg" : "/unspaghettit_logo.png"}
|
|
219
|
+
alt={lyriks ? "Lyriks" : "Unspaghettit"}
|
|
220
|
+
class={lyriks ? "h-9 w-9 shrink-0" : "h-12 w-auto"}
|
|
191
221
|
/>
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
222
|
+
{#if lyriks}
|
|
223
|
+
<!-- Clean stacked lockup: wordmark with an aligned uppercase
|
|
224
|
+
edition label below (the old absolute subtitle overflowed
|
|
225
|
+
because "community edition" is wider than "Lyriks"). -->
|
|
226
|
+
<span class="hidden flex-col items-start leading-none sm:flex">
|
|
227
|
+
<span
|
|
228
|
+
class="font-brand text-2xl font-bold tracking-tight {dark
|
|
229
|
+
? 'text-white'
|
|
230
|
+
: 'text-slate-950'}">Lyriks.io</span
|
|
231
|
+
>
|
|
232
|
+
<span
|
|
233
|
+
class="mt-1 pl-px text-[9px] font-semibold uppercase tracking-[0.18em] {dark
|
|
234
|
+
? 'text-white/75'
|
|
235
|
+
: 'text-slate-500'}">Community Edition</span
|
|
236
|
+
>
|
|
237
|
+
</span>
|
|
238
|
+
{:else}
|
|
198
239
|
<span
|
|
199
|
-
class="
|
|
200
|
-
|
|
240
|
+
class="relative hidden font-brand text-3xl font-semibold leading-none sm:inline-block {dark
|
|
241
|
+
? 'text-white'
|
|
242
|
+
: 'text-slate-950'}"
|
|
201
243
|
>
|
|
202
|
-
|
|
244
|
+
Unspaghettit
|
|
245
|
+
<span
|
|
246
|
+
class="font-grotesk absolute right-0 -bottom-2 text-[10px] font-medium tracking-wide {dark
|
|
247
|
+
? 'text-white/70'
|
|
248
|
+
: 'text-slate-500'}">by Lyriks.io</span
|
|
249
|
+
>
|
|
250
|
+
</span>
|
|
251
|
+
{/if}
|
|
203
252
|
</a>
|
|
204
253
|
{#if showViewSwitcher}
|
|
205
254
|
<div
|
|
@@ -287,6 +336,105 @@
|
|
|
287
336
|
</div>
|
|
288
337
|
{/if}
|
|
289
338
|
<div class="flex shrink-0 items-center gap-1.5">
|
|
339
|
+
<div bind:this={themeMenuRef} class="relative">
|
|
340
|
+
<button
|
|
341
|
+
type="button"
|
|
342
|
+
onclick={() => {
|
|
343
|
+
themeMenuOpen = !themeMenuOpen;
|
|
344
|
+
settingsMenuOpen = false;
|
|
345
|
+
identityMenuOpen = false;
|
|
346
|
+
}}
|
|
347
|
+
aria-haspopup="menu"
|
|
348
|
+
aria-expanded={themeMenuOpen}
|
|
349
|
+
aria-label="Switch dashboard theme"
|
|
350
|
+
title="Switch theme"
|
|
351
|
+
class="grid h-9 w-9 place-items-center rounded-md transition {themeMenuOpen
|
|
352
|
+
? lyriks
|
|
353
|
+
? 'bg-white/30 text-white'
|
|
354
|
+
: dark
|
|
355
|
+
? 'bg-slate-800 text-white'
|
|
356
|
+
: 'bg-slate-900 text-white'
|
|
357
|
+
: lyriks
|
|
358
|
+
? 'bg-white/15 text-white hover:bg-white/25'
|
|
359
|
+
: dark
|
|
360
|
+
? 'text-slate-300 hover:bg-white/10 hover:text-white'
|
|
361
|
+
: 'text-slate-600 hover:bg-slate-100 hover:text-slate-950'}"
|
|
362
|
+
>
|
|
363
|
+
<!-- Swatch / palette glyph: overlapping colour discs. -->
|
|
364
|
+
<svg
|
|
365
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
366
|
+
viewBox="0 0 24 24"
|
|
367
|
+
fill="none"
|
|
368
|
+
stroke="currentColor"
|
|
369
|
+
stroke-width="1.6"
|
|
370
|
+
stroke-linecap="round"
|
|
371
|
+
stroke-linejoin="round"
|
|
372
|
+
class="h-5 w-5"
|
|
373
|
+
aria-hidden="true"
|
|
374
|
+
>
|
|
375
|
+
<circle cx="13.5" cy="6.5" r="2.5" />
|
|
376
|
+
<circle cx="17.5" cy="10.5" r="2.5" />
|
|
377
|
+
<circle cx="8.5" cy="7.5" r="2.5" />
|
|
378
|
+
<path
|
|
379
|
+
d="M12 21a9 9 0 1 1 0-18c4.97 0 9 3.58 9 8 0 2.5-2 3.5-3.5 3.5H15a2 2 0 0 0-1.4 3.42A1.5 1.5 0 0 1 12 21z"
|
|
380
|
+
/>
|
|
381
|
+
</svg>
|
|
382
|
+
</button>
|
|
383
|
+
{#if themeMenuOpen}
|
|
384
|
+
<div
|
|
385
|
+
role="menu"
|
|
386
|
+
class="absolute right-0 top-12 z-40 w-64 overflow-hidden rounded-lg border border-slate-200 bg-white p-1 shadow-lg shadow-slate-950/10"
|
|
387
|
+
>
|
|
388
|
+
<p
|
|
389
|
+
class="px-3 pt-2 pb-1 text-[10px] font-semibold uppercase tracking-wide text-slate-400"
|
|
390
|
+
>
|
|
391
|
+
Theme
|
|
392
|
+
</p>
|
|
393
|
+
{#each themes as theme (theme.id)}
|
|
394
|
+
{@const active = themeStore.current === theme.id}
|
|
395
|
+
<button
|
|
396
|
+
type="button"
|
|
397
|
+
role="menuitemradio"
|
|
398
|
+
aria-checked={active}
|
|
399
|
+
onclick={() => {
|
|
400
|
+
themeStore.setTheme(theme.id);
|
|
401
|
+
themeMenuOpen = false;
|
|
402
|
+
}}
|
|
403
|
+
class="flex w-full items-center gap-3 rounded-md px-3 py-2 text-left text-sm {active
|
|
404
|
+
? 'bg-slate-100 text-slate-950'
|
|
405
|
+
: 'text-slate-700 hover:bg-slate-50'}"
|
|
406
|
+
>
|
|
407
|
+
<span
|
|
408
|
+
class="h-5 w-5 shrink-0 rounded-full ring-1 ring-slate-950/10"
|
|
409
|
+
style="background: {theme.swatch}"
|
|
410
|
+
aria-hidden="true"
|
|
411
|
+
></span>
|
|
412
|
+
<span class="min-w-0 flex-1">
|
|
413
|
+
<span class="block font-medium">{theme.label}</span>
|
|
414
|
+
<span class="block text-[11px] text-slate-500"
|
|
415
|
+
>{theme.description}</span
|
|
416
|
+
>
|
|
417
|
+
</span>
|
|
418
|
+
{#if active}
|
|
419
|
+
<svg
|
|
420
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
421
|
+
viewBox="0 0 24 24"
|
|
422
|
+
fill="none"
|
|
423
|
+
stroke="currentColor"
|
|
424
|
+
stroke-width="2"
|
|
425
|
+
stroke-linecap="round"
|
|
426
|
+
stroke-linejoin="round"
|
|
427
|
+
class="h-4 w-4 shrink-0 text-brand-600"
|
|
428
|
+
aria-hidden="true"
|
|
429
|
+
>
|
|
430
|
+
<path d="M20 6 9 17l-5-5" />
|
|
431
|
+
</svg>
|
|
432
|
+
{/if}
|
|
433
|
+
</button>
|
|
434
|
+
{/each}
|
|
435
|
+
</div>
|
|
436
|
+
{/if}
|
|
437
|
+
</div>
|
|
290
438
|
<div bind:this={settingsMenuRef} class="relative">
|
|
291
439
|
<button
|
|
292
440
|
type="button"
|
|
@@ -300,12 +448,16 @@
|
|
|
300
448
|
title="App menu"
|
|
301
449
|
class="grid h-9 w-9 place-items-center rounded-md transition {settingsMenuOpen ||
|
|
302
450
|
mcpActive
|
|
303
|
-
?
|
|
304
|
-
? 'bg-
|
|
305
|
-
:
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
451
|
+
? lyriks
|
|
452
|
+
? 'bg-white/30 text-white'
|
|
453
|
+
: dark
|
|
454
|
+
? 'bg-slate-800 text-white'
|
|
455
|
+
: 'bg-slate-900 text-white'
|
|
456
|
+
: lyriks
|
|
457
|
+
? 'bg-white/15 text-white hover:bg-white/25'
|
|
458
|
+
: dark
|
|
459
|
+
? 'text-slate-400 hover:bg-slate-800 hover:text-white'
|
|
460
|
+
: 'text-slate-600 hover:bg-slate-100 hover:text-slate-950'}"
|
|
309
461
|
>
|
|
310
462
|
<svg
|
|
311
463
|
xmlns="http://www.w3.org/2000/svg"
|
|
@@ -399,9 +551,11 @@
|
|
|
399
551
|
href="/tutorial"
|
|
400
552
|
aria-label="Help & tutorial"
|
|
401
553
|
title="Help & tutorial"
|
|
402
|
-
class="grid h-9 w-9 place-items-center rounded-md transition {
|
|
403
|
-
? 'text-
|
|
404
|
-
:
|
|
554
|
+
class="grid h-9 w-9 place-items-center rounded-md transition {lyriks
|
|
555
|
+
? 'bg-white/15 text-white hover:bg-white/25'
|
|
556
|
+
: dark
|
|
557
|
+
? 'text-slate-400 hover:bg-slate-800 hover:text-white'
|
|
558
|
+
: 'text-slate-600 hover:bg-slate-100 hover:text-slate-950'}"
|
|
405
559
|
>
|
|
406
560
|
<svg
|
|
407
561
|
xmlns="http://www.w3.org/2000/svg"
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { onMount } from 'svelte';
|
|
3
|
+
import { page } from '$app/stores';
|
|
4
|
+
import { asFeatureId } from '$features/behavior-model/domain/value-objects/ids';
|
|
5
|
+
import { featureStore } from '$features/behavior-model/presentation/stores/featureStore.svelte';
|
|
6
|
+
import { implementationStatusStore } from '$features/implementation-status/presentation/stores/implementationStatusStore.svelte';
|
|
7
|
+
import { projectContextStore } from '$features/projects/presentation/stores/projectContextStore.svelte';
|
|
8
|
+
import BehaviorGraph from '$features/behavior-model/presentation/components/BehaviorGraph.svelte';
|
|
9
|
+
|
|
10
|
+
onMount(() => {
|
|
11
|
+
const id = asFeatureId($page.params.id ?? '');
|
|
12
|
+
featureStore.load(id);
|
|
13
|
+
projectContextStore.load(id);
|
|
14
|
+
return () => {
|
|
15
|
+
featureStore.reset();
|
|
16
|
+
implementationStatusStore.reset();
|
|
17
|
+
projectContextStore.reset();
|
|
18
|
+
};
|
|
19
|
+
});
|
|
20
|
+
</script>
|
|
21
|
+
|
|
22
|
+
{#if featureStore.loading}
|
|
23
|
+
<div class="mx-auto max-w-7xl px-4 py-10 text-sm text-neutral-500">Loading...</div>
|
|
24
|
+
{:else if featureStore.error}
|
|
25
|
+
<div class="mx-auto max-w-7xl px-4 py-10 text-sm text-red-600">{featureStore.error}</div>
|
|
26
|
+
{:else if !featureStore.feature}
|
|
27
|
+
<div class="mx-auto max-w-7xl px-4 py-10 text-sm text-neutral-500">
|
|
28
|
+
Feature not found. <a href="/features" class="text-brand-700 underline">Back to list</a>.
|
|
29
|
+
</div>
|
|
30
|
+
{:else}
|
|
31
|
+
<main class="mx-auto max-w-[1600px] px-4 py-6">
|
|
32
|
+
<BehaviorGraph feature={featureStore.feature} />
|
|
33
|
+
</main>
|
|
34
|
+
{/if}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { onDestroy, onMount } from 'svelte';
|
|
3
|
+
import { page } from '$app/stores';
|
|
4
|
+
import { asFeatureId } from '$features/behavior-model/domain/value-objects/ids';
|
|
5
|
+
import BehaviorGraph from '$features/behavior-model/presentation/components/BehaviorGraph.svelte';
|
|
6
|
+
import { asProjectId } from '$features/projects/domain/value-objects/ids';
|
|
7
|
+
import { projectFeaturesStore } from '$features/projects/presentation/stores/projectFeaturesStore.svelte';
|
|
8
|
+
import { projectStore } from '$features/projects/presentation/stores/projectStore.svelte';
|
|
9
|
+
import { subscribeSyncEvents } from '$lib/client/sync/syncEvents';
|
|
10
|
+
|
|
11
|
+
let unsubscribeSync: (() => void) | null = null;
|
|
12
|
+
let graphDataReady = $state(false);
|
|
13
|
+
|
|
14
|
+
onMount(async () => {
|
|
15
|
+
const raw = $page.params.id;
|
|
16
|
+
if (!raw) return;
|
|
17
|
+
graphDataReady = false;
|
|
18
|
+
const id = asProjectId(raw);
|
|
19
|
+
await projectStore.load(id);
|
|
20
|
+
await projectFeaturesStore.loadAllSummaries();
|
|
21
|
+
if (projectStore.project) {
|
|
22
|
+
await projectFeaturesStore.load(projectStore.project.featureIds);
|
|
23
|
+
}
|
|
24
|
+
graphDataReady = true;
|
|
25
|
+
unsubscribeSync = subscribeSyncEvents(async (evt) => {
|
|
26
|
+
if (!projectStore.project) return;
|
|
27
|
+
if (evt.kind === 'project' && evt.id === String(id)) {
|
|
28
|
+
graphDataReady = false;
|
|
29
|
+
await projectFeaturesStore.syncWith(projectStore.project.featureIds);
|
|
30
|
+
graphDataReady = true;
|
|
31
|
+
} else if (evt.kind === 'feature') {
|
|
32
|
+
const ours = projectStore.project.featureIds.some((fid) => String(fid) === evt.id);
|
|
33
|
+
if (ours) {
|
|
34
|
+
await projectFeaturesStore.refetchOne(asFeatureId(evt.id));
|
|
35
|
+
} else {
|
|
36
|
+
await projectFeaturesStore.loadAllSummaries();
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
});
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
onDestroy(() => {
|
|
43
|
+
unsubscribeSync?.();
|
|
44
|
+
unsubscribeSync = null;
|
|
45
|
+
graphDataReady = false;
|
|
46
|
+
projectStore.reset();
|
|
47
|
+
projectFeaturesStore.reset();
|
|
48
|
+
});
|
|
49
|
+
</script>
|
|
50
|
+
|
|
51
|
+
<svelte:head>
|
|
52
|
+
<title>Project Graph / Unspaghettit</title>
|
|
53
|
+
</svelte:head>
|
|
54
|
+
|
|
55
|
+
{#if projectStore.loading}
|
|
56
|
+
<p class="mx-auto max-w-7xl px-4 py-10 text-sm text-neutral-500">Loading project...</p>
|
|
57
|
+
{:else if projectStore.error}
|
|
58
|
+
<p class="mx-auto max-w-7xl px-4 py-10 text-sm text-red-600">{projectStore.error}</p>
|
|
59
|
+
{:else if !projectStore.project}
|
|
60
|
+
<p class="mx-auto max-w-7xl px-4 py-10 text-sm text-neutral-500">
|
|
61
|
+
Project not found. <a href="/projects" class="text-brand-700 hover:underline">Back to projects</a>
|
|
62
|
+
</p>
|
|
63
|
+
{:else if projectFeaturesStore.loading || !graphDataReady}
|
|
64
|
+
<p class="mx-auto max-w-7xl px-4 py-10 text-sm text-neutral-500">Loading project features...</p>
|
|
65
|
+
{:else if projectFeaturesStore.error}
|
|
66
|
+
<p class="mx-auto max-w-7xl px-4 py-10 text-sm text-red-600">{projectFeaturesStore.error}</p>
|
|
67
|
+
{:else if projectStore.project.featureIds.length > 0 && projectFeaturesStore.features.length === 0}
|
|
68
|
+
<div class="mx-auto max-w-7xl px-4 py-10">
|
|
69
|
+
<p class="text-sm font-medium text-slate-900">No feature snapshots loaded for this project.</p>
|
|
70
|
+
<p class="mt-2 text-sm text-slate-600">
|
|
71
|
+
The project lists {projectStore.project.featureIds.length} feature{projectStore.project.featureIds.length === 1 ? '' : 's'},
|
|
72
|
+
but the graph could not load their behavior models from the shared hub.
|
|
73
|
+
</p>
|
|
74
|
+
</div>
|
|
75
|
+
{:else}
|
|
76
|
+
<main class="mx-auto max-w-[1800px] px-4 py-6">
|
|
77
|
+
<BehaviorGraph project={projectStore.project} features={projectFeaturesStore.features} />
|
|
78
|
+
</main>
|
|
79
|
+
{/if}
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
* Designed to replace the "single flat colored fill" pattern that was
|
|
6
6
|
* scattered across FeatureCard / MaturityPanel / FeatureHealthStrip.
|
|
7
7
|
* Adds:
|
|
8
|
-
* - tier-based color (red < 50%, amber < 80%, emerald
|
|
8
|
+
* - tier-based color (red < 50%, amber < 80%, emerald >= 80%) when no
|
|
9
9
|
* explicit `color` is passed. The tier breakpoints match the
|
|
10
10
|
* existing scorer thresholds so the visual identity stays in step
|
|
11
11
|
* with the textual "critical / recommended" semantics.
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
import { fly, fade } from 'svelte/transition';
|
|
4
4
|
import { cubicOut } from 'svelte/easing';
|
|
5
5
|
import { syncToastStore, type SyncToast } from './syncToastStore.svelte';
|
|
6
|
+
import { resolveViewLink } from './viewLinkResolver';
|
|
6
7
|
|
|
7
8
|
onMount(() => {
|
|
8
9
|
// Idempotent — starts the SSE subscription on first mount, no-ops on
|
|
@@ -89,6 +90,15 @@
|
|
|
89
90
|
if (cleaned.length === 0) cleaned.push(toast.entityId);
|
|
90
91
|
return cleaned;
|
|
91
92
|
}
|
|
93
|
+
|
|
94
|
+
// The "View" target. Prefer the active view's own deep-link (e.g. the
|
|
95
|
+
// Builder, while it's open) so the user stays where they are; fall back to
|
|
96
|
+
// the default Expert route the toast was created with. Deletes carry no
|
|
97
|
+
// viewable target (the entity is gone).
|
|
98
|
+
function viewHref(toast: SyncToast): string | undefined {
|
|
99
|
+
if (toast.op === 'delete') return undefined;
|
|
100
|
+
return resolveViewLink(toast.kind, toast.entityId) ?? toast.href;
|
|
101
|
+
}
|
|
92
102
|
</script>
|
|
93
103
|
|
|
94
104
|
{#if syncToastStore.toasts.length > 0}
|
|
@@ -99,6 +109,7 @@
|
|
|
99
109
|
>
|
|
100
110
|
{#each syncToastStore.toasts as toast (toast.id)}
|
|
101
111
|
{@const crumbs = breadcrumb(toast)}
|
|
112
|
+
{@const target = viewHref(toast)}
|
|
102
113
|
<div
|
|
103
114
|
class="pointer-events-auto flex items-start gap-3 rounded-lg border px-3 py-2 shadow-md shadow-slate-950/10 {kindAccent(toast.kind)}"
|
|
104
115
|
in:fly={{ x: 24, duration: 180, easing: cubicOut }}
|
|
@@ -137,9 +148,9 @@
|
|
|
137
148
|
{/if}
|
|
138
149
|
</div>
|
|
139
150
|
<div class="flex shrink-0 items-center gap-1">
|
|
140
|
-
{#if
|
|
151
|
+
{#if target}
|
|
141
152
|
<a
|
|
142
|
-
href={
|
|
153
|
+
href={target}
|
|
143
154
|
class="rounded-md bg-white/70 px-2 py-1 text-xs font-medium text-slate-700 hover:bg-white hover:text-brand-800"
|
|
144
155
|
onclick={() => syncToastStore.dismiss(toast.id)}
|
|
145
156
|
>
|
|
@@ -152,7 +163,7 @@
|
|
|
152
163
|
onclick={() => syncToastStore.dismiss(toast.id)}
|
|
153
164
|
aria-label="Dismiss"
|
|
154
165
|
>
|
|
155
|
-
|
|
166
|
+
×
|
|
156
167
|
</button>
|
|
157
168
|
</div>
|
|
158
169
|
</div>
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import type { SyncEvent } from '$lib/client/sync/syncEvents';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Lets the active view teach the activity-toast where its "View" button should
|
|
5
|
+
* point WITHOUT the shared toast layer importing any feature. A view (today the
|
|
6
|
+
* Builder) registers a resolver while it is mounted; the toast asks it for an
|
|
7
|
+
* in-view link to the changed entity first, and falls back to the default
|
|
8
|
+
* (Expert) route when the resolver returns null (entity not shown in that view)
|
|
9
|
+
* or no view is registered.
|
|
10
|
+
*
|
|
11
|
+
* Dependency inversion: the shared toast depends on this abstraction; the
|
|
12
|
+
* feature supplies the implementation — the same shape as the BuilderHost ports.
|
|
13
|
+
*/
|
|
14
|
+
export type ViewLinkResolver = (kind: SyncEvent['kind'], id: string) => string | null;
|
|
15
|
+
|
|
16
|
+
let resolver: ViewLinkResolver | null = null;
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Register the active view's resolver. Returns an unregister fn; calling it
|
|
20
|
+
* only clears the slot when it still holds THIS resolver, so a remount that
|
|
21
|
+
* registers a new one before the old view's cleanup runs isn't torn down.
|
|
22
|
+
*/
|
|
23
|
+
export const registerViewLinkResolver = (next: ViewLinkResolver): (() => void) => {
|
|
24
|
+
resolver = next;
|
|
25
|
+
return () => {
|
|
26
|
+
if (resolver === next) resolver = null;
|
|
27
|
+
};
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
/** In-view link for the changed entity, or null to use the default route. */
|
|
31
|
+
export const resolveViewLink = (kind: SyncEvent['kind'], id: string): string | null =>
|
|
32
|
+
resolver ? resolver(kind, id) : null;
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
|
2
|
+
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
|
3
|
+
|
|
4
|
+
<svg
|
|
5
|
+
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
|
6
|
+
xmlns:cc="http://creativecommons.org/ns#"
|
|
7
|
+
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
|
8
|
+
xmlns:svg="http://www.w3.org/2000/svg"
|
|
9
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
10
|
+
xmlns:xlink="http://www.w3.org/1999/xlink"
|
|
11
|
+
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
|
12
|
+
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
|
13
|
+
width="48"
|
|
14
|
+
height="48"
|
|
15
|
+
viewBox="0 0 12.7 12.7"
|
|
16
|
+
version="1.1"
|
|
17
|
+
id="svg8"
|
|
18
|
+
inkscape:version="0.92.3 (2405546, 2018-03-11)"
|
|
19
|
+
sodipodi:docname="lyriks-1.svg">
|
|
20
|
+
<defs
|
|
21
|
+
id="defs2">
|
|
22
|
+
<linearGradient
|
|
23
|
+
inkscape:collect="always"
|
|
24
|
+
id="linearGradient4618">
|
|
25
|
+
<stop
|
|
26
|
+
style="stop-color:#ffa101;stop-opacity:1;"
|
|
27
|
+
offset="0"
|
|
28
|
+
id="stop4614" />
|
|
29
|
+
<stop
|
|
30
|
+
style="stop-color:#ffa101;stop-opacity:0;"
|
|
31
|
+
offset="1"
|
|
32
|
+
id="stop4616" />
|
|
33
|
+
</linearGradient>
|
|
34
|
+
<linearGradient
|
|
35
|
+
inkscape:collect="always"
|
|
36
|
+
id="linearGradient4610">
|
|
37
|
+
<stop
|
|
38
|
+
style="stop-color:#bb46f5;stop-opacity:1;"
|
|
39
|
+
offset="0"
|
|
40
|
+
id="stop4606" />
|
|
41
|
+
<stop
|
|
42
|
+
style="stop-color:#bb46f5;stop-opacity:0;"
|
|
43
|
+
offset="1"
|
|
44
|
+
id="stop4608" />
|
|
45
|
+
</linearGradient>
|
|
46
|
+
<linearGradient
|
|
47
|
+
inkscape:collect="always"
|
|
48
|
+
id="linearGradient4602">
|
|
49
|
+
<stop
|
|
50
|
+
style="stop-color:#0066ff;stop-opacity:1;"
|
|
51
|
+
offset="0"
|
|
52
|
+
id="stop4598" />
|
|
53
|
+
<stop
|
|
54
|
+
style="stop-color:#0066ff;stop-opacity:0;"
|
|
55
|
+
offset="1"
|
|
56
|
+
id="stop4600" />
|
|
57
|
+
</linearGradient>
|
|
58
|
+
<linearGradient
|
|
59
|
+
inkscape:collect="always"
|
|
60
|
+
xlink:href="#linearGradient4602"
|
|
61
|
+
id="linearGradient4604"
|
|
62
|
+
x1="433.33047"
|
|
63
|
+
y1="223.41049"
|
|
64
|
+
x2="432.65369"
|
|
65
|
+
y2="484.82812"
|
|
66
|
+
gradientUnits="userSpaceOnUse"
|
|
67
|
+
gradientTransform="matrix(0.26458333,0,0,0.26458333,-82.110177,-99.957753)" />
|
|
68
|
+
<linearGradient
|
|
69
|
+
inkscape:collect="always"
|
|
70
|
+
xlink:href="#linearGradient4610"
|
|
71
|
+
id="linearGradient4612"
|
|
72
|
+
x1="432.83047"
|
|
73
|
+
y1="323.48856"
|
|
74
|
+
x2="433.53754"
|
|
75
|
+
y2="146.35829"
|
|
76
|
+
gradientUnits="userSpaceOnUse"
|
|
77
|
+
gradientTransform="matrix(0.26458333,0,0,0.26458333,-82.110177,-99.957753)" />
|
|
78
|
+
<linearGradient
|
|
79
|
+
inkscape:collect="always"
|
|
80
|
+
xlink:href="#linearGradient4618"
|
|
81
|
+
id="linearGradient4620"
|
|
82
|
+
x1="22.477682"
|
|
83
|
+
y1="34.598564"
|
|
84
|
+
x2="21.553013"
|
|
85
|
+
y2="86.671013"
|
|
86
|
+
gradientUnits="userSpaceOnUse"
|
|
87
|
+
gradientTransform="translate(12.832291,-41.407291)" />
|
|
88
|
+
</defs>
|
|
89
|
+
<sodipodi:namedview
|
|
90
|
+
id="base"
|
|
91
|
+
pagecolor="#ffffff"
|
|
92
|
+
bordercolor="#666666"
|
|
93
|
+
borderopacity="1.0"
|
|
94
|
+
inkscape:pageopacity="0.0"
|
|
95
|
+
inkscape:pageshadow="2"
|
|
96
|
+
inkscape:zoom="11.313708"
|
|
97
|
+
inkscape:cx="31.592839"
|
|
98
|
+
inkscape:cy="4.7086138"
|
|
99
|
+
inkscape:document-units="mm"
|
|
100
|
+
inkscape:current-layer="layer1"
|
|
101
|
+
showgrid="false"
|
|
102
|
+
inkscape:window-width="2560"
|
|
103
|
+
inkscape:window-height="1369"
|
|
104
|
+
inkscape:window-x="-8"
|
|
105
|
+
inkscape:window-y="-8"
|
|
106
|
+
inkscape:window-maximized="1"
|
|
107
|
+
inkscape:pagecheckerboard="false"
|
|
108
|
+
units="px" />
|
|
109
|
+
<metadata
|
|
110
|
+
id="metadata5">
|
|
111
|
+
<rdf:RDF>
|
|
112
|
+
<cc:Work
|
|
113
|
+
rdf:about="">
|
|
114
|
+
<dc:format>image/svg+xml</dc:format>
|
|
115
|
+
<dc:type
|
|
116
|
+
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
|
117
|
+
<dc:title></dc:title>
|
|
118
|
+
</cc:Work>
|
|
119
|
+
</rdf:RDF>
|
|
120
|
+
</metadata>
|
|
121
|
+
<g
|
|
122
|
+
inkscape:label="Calque 1"
|
|
123
|
+
inkscape:groupmode="layer"
|
|
124
|
+
id="layer1"
|
|
125
|
+
transform="translate(0,-284.3)">
|
|
126
|
+
<g
|
|
127
|
+
transform="matrix(0.43489873,0,0,0.40888801,-9.9205419,298.38648)"
|
|
128
|
+
id="g3740">
|
|
129
|
+
<rect
|
|
130
|
+
id="rect3742-2-8"
|
|
131
|
+
width="29.185829"
|
|
132
|
+
height="7.0625973"
|
|
133
|
+
x="22.823183"
|
|
134
|
+
y="-10.439077"
|
|
135
|
+
style="fill:url(#linearGradient4620);fill-opacity:1;stroke-width:0.29681981" />
|
|
136
|
+
<path
|
|
137
|
+
style="fill:url(#linearGradient4604);fill-opacity:1;stroke-width:0.09354433"
|
|
138
|
+
d="m 22.821255,-30.364151 v -4.069178 h 9.494747 9.494751 v 4.069178 4.069178 h -9.494751 -9.494747 z"
|
|
139
|
+
id="path3785"
|
|
140
|
+
inkscape:connector-curvature="0" />
|
|
141
|
+
<path
|
|
142
|
+
style="fill:url(#linearGradient4612);fill-opacity:1;stroke-width:0.09354433"
|
|
143
|
+
d="m 22.821255,-18.343704 v -4.022408 h 9.494747 9.494751 v 4.022408 4.022404 h -9.494751 -9.494747 z"
|
|
144
|
+
id="path3787"
|
|
145
|
+
inkscape:connector-curvature="0" />
|
|
146
|
+
</g>
|
|
147
|
+
</g>
|
|
148
|
+
</svg>
|