unspaghettit 0.1.7 → 0.2.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.
Files changed (466) hide show
  1. package/README.md +30 -10
  2. package/build/client/_app/immutable/assets/0.DFMDYAU9.css +1 -0
  3. package/build/client/_app/immutable/assets/0.DFMDYAU9.css.br +0 -0
  4. package/build/client/_app/immutable/assets/0.DFMDYAU9.css.gz +0 -0
  5. package/build/client/_app/immutable/assets/3.B3akUL9A.css +1 -0
  6. package/build/client/_app/immutable/assets/3.B3akUL9A.css.br +0 -0
  7. package/build/client/_app/immutable/assets/3.B3akUL9A.css.gz +0 -0
  8. package/build/client/_app/immutable/chunks/{Buny4Lxq.js → BO66rBOa2.js} +1 -1
  9. package/build/client/_app/immutable/chunks/BO66rBOa2.js.br +0 -0
  10. package/build/client/_app/immutable/chunks/BO66rBOa2.js.gz +0 -0
  11. package/build/client/_app/immutable/chunks/{BTLTzKaZ.js → BOrLmFwJ.js} +1 -1
  12. package/build/client/_app/immutable/chunks/BOrLmFwJ.js.br +0 -0
  13. package/build/client/_app/immutable/chunks/BOrLmFwJ.js.gz +0 -0
  14. package/build/client/_app/immutable/chunks/BPl9BITm.js +3 -0
  15. package/build/client/_app/immutable/chunks/BPl9BITm.js.br +0 -0
  16. package/build/client/_app/immutable/chunks/BPl9BITm.js.gz +0 -0
  17. package/build/client/_app/immutable/chunks/BfMYiIUi.js +1 -0
  18. package/build/client/_app/immutable/chunks/BfMYiIUi.js.br +0 -0
  19. package/build/client/_app/immutable/chunks/BfMYiIUi.js.gz +0 -0
  20. package/build/client/_app/immutable/chunks/Bp2_Vghh.js +1 -0
  21. package/build/client/_app/immutable/chunks/Bp2_Vghh.js.br +0 -0
  22. package/build/client/_app/immutable/chunks/Bp2_Vghh.js.gz +0 -0
  23. package/build/client/_app/immutable/chunks/{-s9hRK72.js → Bp8HpEPe2.js} +1 -1
  24. package/build/client/_app/immutable/chunks/Bp8HpEPe2.js.br +0 -0
  25. package/build/client/_app/immutable/chunks/Bp8HpEPe2.js.gz +0 -0
  26. package/build/client/_app/immutable/chunks/C8rRKIXT.js +1 -0
  27. package/build/client/_app/immutable/chunks/C8rRKIXT.js.br +0 -0
  28. package/build/client/_app/immutable/chunks/C8rRKIXT.js.gz +0 -0
  29. package/build/client/_app/immutable/chunks/{CDgx1pP22.js → CJjJLwzv2.js} +1 -1
  30. package/build/client/_app/immutable/chunks/CJjJLwzv2.js.br +0 -0
  31. package/build/client/_app/immutable/chunks/CJjJLwzv2.js.gz +0 -0
  32. package/build/client/_app/immutable/chunks/Cl7Z3e6-.js +1 -0
  33. package/build/client/_app/immutable/chunks/Cl7Z3e6-.js.br +0 -0
  34. package/build/client/_app/immutable/chunks/Cl7Z3e6-.js.gz +0 -0
  35. package/build/client/_app/immutable/chunks/CxyLMlpt2.js +2 -0
  36. package/build/client/_app/immutable/chunks/CxyLMlpt2.js.br +0 -0
  37. package/build/client/_app/immutable/chunks/CxyLMlpt2.js.gz +0 -0
  38. package/build/client/_app/immutable/chunks/D6jhrpTg.js +1 -0
  39. package/build/client/_app/immutable/chunks/D6jhrpTg.js.br +0 -0
  40. package/build/client/_app/immutable/chunks/D6jhrpTg.js.gz +0 -0
  41. package/build/client/_app/immutable/chunks/D8YEa1po.js +1 -0
  42. package/build/client/_app/immutable/chunks/D8YEa1po.js.br +0 -0
  43. package/build/client/_app/immutable/chunks/D8YEa1po.js.gz +0 -0
  44. package/build/client/_app/immutable/chunks/D9dKmajw.js +1 -0
  45. package/build/client/_app/immutable/chunks/D9dKmajw.js.br +0 -0
  46. package/build/client/_app/immutable/chunks/D9dKmajw.js.gz +0 -0
  47. package/build/client/_app/immutable/chunks/DBJWcC6Y.js +1 -0
  48. package/build/client/_app/immutable/chunks/DBJWcC6Y.js.br +0 -0
  49. package/build/client/_app/immutable/chunks/DBJWcC6Y.js.gz +0 -0
  50. package/build/client/_app/immutable/chunks/DHoA038D.js +1 -0
  51. package/build/client/_app/immutable/chunks/DHoA038D.js.br +2 -0
  52. package/build/client/_app/immutable/chunks/DHoA038D.js.gz +0 -0
  53. package/build/client/_app/immutable/chunks/DKgYpi6_.js +1 -0
  54. package/build/client/_app/immutable/chunks/DKgYpi6_.js.br +0 -0
  55. package/build/client/_app/immutable/chunks/DKgYpi6_.js.gz +0 -0
  56. package/build/client/_app/immutable/chunks/DatGSObE.js +1 -0
  57. package/build/client/_app/immutable/chunks/DatGSObE.js.br +0 -0
  58. package/build/client/_app/immutable/chunks/DatGSObE.js.gz +0 -0
  59. package/build/client/_app/immutable/chunks/Dg0acPpT.js +1 -0
  60. package/build/client/_app/immutable/chunks/Dg0acPpT.js.br +0 -0
  61. package/build/client/_app/immutable/chunks/Dg0acPpT.js.gz +0 -0
  62. package/build/client/_app/immutable/chunks/DjWKKtqp.js +1 -0
  63. package/build/client/_app/immutable/chunks/DjWKKtqp.js.br +1 -0
  64. package/build/client/_app/immutable/chunks/DjWKKtqp.js.gz +0 -0
  65. package/build/client/_app/immutable/chunks/Dq0DUAz1.js +1 -0
  66. package/build/client/_app/immutable/chunks/Dq0DUAz1.js.br +0 -0
  67. package/build/client/_app/immutable/chunks/Dq0DUAz1.js.gz +0 -0
  68. package/build/client/_app/immutable/chunks/{Q8pmKDJe.js → HKLi1Yz3.js} +1 -1
  69. package/build/client/_app/immutable/chunks/HKLi1Yz3.js.br +0 -0
  70. package/build/client/_app/immutable/chunks/HKLi1Yz3.js.gz +0 -0
  71. package/build/client/_app/immutable/chunks/N7PXjlRH.js +1 -0
  72. package/build/client/_app/immutable/chunks/N7PXjlRH.js.br +0 -0
  73. package/build/client/_app/immutable/chunks/N7PXjlRH.js.gz +0 -0
  74. package/build/client/_app/immutable/chunks/aNMRV4sP2.js +5 -0
  75. package/build/client/_app/immutable/chunks/aNMRV4sP2.js.br +0 -0
  76. package/build/client/_app/immutable/chunks/aNMRV4sP2.js.gz +0 -0
  77. package/build/client/_app/immutable/chunks/cMamJTsF.js +1 -0
  78. package/build/client/_app/immutable/chunks/cMamJTsF.js.br +0 -0
  79. package/build/client/_app/immutable/chunks/cMamJTsF.js.gz +0 -0
  80. package/build/client/_app/immutable/chunks/hpWJNn0t2.js +2 -0
  81. package/build/client/_app/immutable/chunks/hpWJNn0t2.js.br +0 -0
  82. package/build/client/_app/immutable/chunks/hpWJNn0t2.js.gz +0 -0
  83. package/build/client/_app/immutable/chunks/iQu0D9Ux.js +1 -0
  84. package/build/client/_app/immutable/chunks/iQu0D9Ux.js.br +0 -0
  85. package/build/client/_app/immutable/chunks/iQu0D9Ux.js.gz +0 -0
  86. package/build/client/_app/immutable/chunks/ib21i2T_.js +6 -0
  87. package/build/client/_app/immutable/chunks/ib21i2T_.js.br +0 -0
  88. package/build/client/_app/immutable/chunks/ib21i2T_.js.gz +0 -0
  89. package/build/client/_app/immutable/chunks/suTxxv1t.js +1 -0
  90. package/build/client/_app/immutable/chunks/suTxxv1t.js.br +1 -0
  91. package/build/client/_app/immutable/chunks/suTxxv1t.js.gz +0 -0
  92. package/build/client/_app/immutable/entry/app.CLgh6Mx_.js +2 -0
  93. package/build/client/_app/immutable/entry/app.CLgh6Mx_.js.br +0 -0
  94. package/build/client/_app/immutable/entry/app.CLgh6Mx_.js.gz +0 -0
  95. package/build/client/_app/immutable/entry/start.D5GPCQZD.js +1 -0
  96. package/build/client/_app/immutable/entry/start.D5GPCQZD.js.br +0 -0
  97. package/build/client/_app/immutable/entry/start.D5GPCQZD.js.gz +0 -0
  98. package/build/client/_app/immutable/nodes/0.BOoI-hsu.js +4 -0
  99. package/build/client/_app/immutable/nodes/0.BOoI-hsu.js.br +0 -0
  100. package/build/client/_app/immutable/nodes/0.BOoI-hsu.js.gz +0 -0
  101. package/build/client/_app/immutable/nodes/1.KYdA6ppX.js +1 -0
  102. package/build/client/_app/immutable/nodes/1.KYdA6ppX.js.br +2 -0
  103. package/build/client/_app/immutable/nodes/1.KYdA6ppX.js.gz +0 -0
  104. package/build/client/_app/immutable/nodes/2.DBz20KgG.js +1 -0
  105. package/build/client/_app/immutable/nodes/2.DBz20KgG.js.br +0 -0
  106. package/build/client/_app/immutable/nodes/2.DBz20KgG.js.gz +0 -0
  107. package/build/client/_app/immutable/nodes/3.19DIoFtw.js +1 -0
  108. package/build/client/_app/immutable/nodes/3.19DIoFtw.js.br +0 -0
  109. package/build/client/_app/immutable/nodes/3.19DIoFtw.js.gz +0 -0
  110. package/build/client/_app/immutable/nodes/4.BvMzqBJj.js +3 -0
  111. package/build/client/_app/immutable/nodes/4.BvMzqBJj.js.br +0 -0
  112. package/build/client/_app/immutable/nodes/4.BvMzqBJj.js.gz +0 -0
  113. package/build/client/_app/immutable/nodes/5.Dq6obSGG.js +42 -0
  114. package/build/client/_app/immutable/nodes/5.Dq6obSGG.js.br +0 -0
  115. package/build/client/_app/immutable/nodes/5.Dq6obSGG.js.gz +0 -0
  116. package/build/client/_app/immutable/nodes/6.BOHISqs-.js +5 -0
  117. package/build/client/_app/immutable/nodes/6.BOHISqs-.js.br +0 -0
  118. package/build/client/_app/immutable/nodes/6.BOHISqs-.js.gz +0 -0
  119. package/build/client/_app/immutable/nodes/7.CemgNJfw.js +1 -0
  120. package/build/client/_app/immutable/nodes/7.CemgNJfw.js.br +0 -0
  121. package/build/client/_app/immutable/nodes/7.CemgNJfw.js.gz +0 -0
  122. package/build/client/_app/immutable/nodes/8.DejSfIYh.js +5 -0
  123. package/build/client/_app/immutable/nodes/8.DejSfIYh.js.br +0 -0
  124. package/build/client/_app/immutable/nodes/8.DejSfIYh.js.gz +0 -0
  125. package/build/client/_app/immutable/nodes/{8.aFYV9MSb.js → 9.CMW6a2Lg.js} +51 -48
  126. package/build/client/_app/immutable/nodes/9.CMW6a2Lg.js.br +0 -0
  127. package/build/client/_app/immutable/nodes/9.CMW6a2Lg.js.gz +0 -0
  128. package/build/client/_app/version.json +1 -1
  129. package/build/client/_app/version.json.br +0 -0
  130. package/build/client/_app/version.json.gz +0 -0
  131. package/build/server/chunks/0-C_o0oz-N.js +15 -0
  132. package/build/server/chunks/0-C_o0oz-N.js.map +1 -0
  133. package/build/server/chunks/1-DPpKAKXV.js +9 -0
  134. package/build/server/chunks/{1-BM_rl7Bx.js.map → 1-DPpKAKXV.js.map} +1 -1
  135. package/build/server/chunks/2-AlfFqtL1.js +9 -0
  136. package/build/server/chunks/2-AlfFqtL1.js.map +1 -0
  137. package/build/server/chunks/3-vbjUt_51.js +16 -0
  138. package/build/server/chunks/3-vbjUt_51.js.map +1 -0
  139. package/build/server/chunks/4-BNow4x6D.js +16 -0
  140. package/build/server/chunks/4-BNow4x6D.js.map +1 -0
  141. package/build/server/chunks/5-D7OCJpxD.js +9 -0
  142. package/build/server/chunks/5-D7OCJpxD.js.map +1 -0
  143. package/build/server/chunks/6-QQ7r8Rd5.js +9 -0
  144. package/build/server/chunks/6-QQ7r8Rd5.js.map +1 -0
  145. package/build/server/chunks/7-CbPLGaIG.js +9 -0
  146. package/build/server/chunks/7-CbPLGaIG.js.map +1 -0
  147. package/build/server/chunks/8-CVO-E-sf.js +9 -0
  148. package/build/server/chunks/8-CVO-E-sf.js.map +1 -0
  149. package/build/server/chunks/9-DxT1baO5.js +9 -0
  150. package/build/server/chunks/9-DxT1baO5.js.map +1 -0
  151. package/build/server/chunks/{FeatureCard-gVIYCpot.js → FeatureCard-BQOY6gJQ.js} +2 -2
  152. package/build/server/chunks/{FeatureCard-gVIYCpot.js.map → FeatureCard-BQOY6gJQ.js.map} +1 -1
  153. package/build/server/chunks/{FeatureJson-BKCG8vk2.js → FeatureJson-Bv-qiOSf.js} +2 -2
  154. package/build/server/chunks/{FeatureJson-BKCG8vk2.js.map → FeatureJson-Bv-qiOSf.js.map} +1 -1
  155. package/build/server/chunks/FeatureTransforms-UWDHmWEg.js +311 -0
  156. package/build/server/chunks/FeatureTransforms-UWDHmWEg.js.map +1 -0
  157. package/build/server/chunks/FeatureValidator-B8qEjAUW.js +546 -0
  158. package/build/server/chunks/FeatureValidator-B8qEjAUW.js.map +1 -0
  159. package/build/server/chunks/{ManageTagsDialog-DO6XplIb.js → ManageTagsDialog-DBxA3tM2.js} +4 -3
  160. package/build/server/chunks/ManageTagsDialog-DBxA3tM2.js.map +1 -0
  161. package/build/server/chunks/{ProjectsIndex-Boeoj8Zh.js → ProjectsIndex-CoDrvRya.js} +8 -8
  162. package/build/server/chunks/ProjectsIndex-CoDrvRya.js.map +1 -0
  163. package/build/server/chunks/{RenameTag-nSZ6Leh-.js → RenameTag-BuWLMl1m.js} +2 -2
  164. package/build/server/chunks/{RenameTag-nSZ6Leh-.js.map → RenameTag-BuWLMl1m.js.map} +1 -1
  165. package/build/server/chunks/TagDotStrip-B1XQ0m0Y.js +88 -0
  166. package/build/server/chunks/TagDotStrip-B1XQ0m0Y.js.map +1 -0
  167. package/build/server/chunks/{TagFilterSelect-5EaFX5CY.js → TagFilterSelect-DbO0Qduh.js} +4 -3
  168. package/build/server/chunks/TagFilterSelect-DbO0Qduh.js.map +1 -0
  169. package/build/server/chunks/{TagPalette-CvQJ40bt.js → TagPalette-CtMNYCmu.js} +6 -2
  170. package/build/server/chunks/TagPalette-CtMNYCmu.js.map +1 -0
  171. package/build/server/chunks/{_layout.svelte-BV7JjoXo.js → _layout.svelte-BREws55o.js} +99 -37
  172. package/build/server/chunks/_layout.svelte-BREws55o.js.map +1 -0
  173. package/build/server/chunks/{_page.svelte-PO6PTc2Z.js → _page.svelte-B1s7jxaQ.js} +9 -8
  174. package/build/server/chunks/{_page.svelte-PO6PTc2Z.js.map → _page.svelte-B1s7jxaQ.js.map} +1 -1
  175. package/build/server/chunks/_page.svelte-B7hT3P8E.js +29 -0
  176. package/build/server/chunks/{_page.svelte-D-CofieG.js.map → _page.svelte-B7hT3P8E.js.map} +1 -1
  177. package/build/server/chunks/{_page.svelte-B0w194rX.js → _page.svelte-BKKCa9H5.js} +11 -8
  178. package/build/server/chunks/{_page.svelte-B0w194rX.js.map → _page.svelte-BKKCa9H5.js.map} +1 -1
  179. package/build/server/chunks/{_page.svelte-DDOUOH7d.js → _page.svelte-BKTveFAj.js} +16 -14
  180. package/build/server/chunks/_page.svelte-BKTveFAj.js.map +1 -0
  181. package/build/server/chunks/_page.svelte-BqSC-1vK.js +404 -0
  182. package/build/server/chunks/_page.svelte-BqSC-1vK.js.map +1 -0
  183. package/build/server/chunks/{_page.svelte-AXKie8xV.js → _page.svelte-BtI2zZ_Z.js} +38 -282
  184. package/build/server/chunks/_page.svelte-BtI2zZ_Z.js.map +1 -0
  185. package/build/server/chunks/_page.svelte-De508ek8.js +29 -0
  186. package/build/server/chunks/{_page.svelte-D4bCUYdF.js.map → _page.svelte-De508ek8.js.map} +1 -1
  187. package/build/server/chunks/{_page.svelte-BSo9Np-N.js → _page.svelte-Zf9H4KOP.js} +16 -14
  188. package/build/server/chunks/_page.svelte-Zf9H4KOP.js.map +1 -0
  189. package/build/server/chunks/{_server.ts-B3vd_taO.js → _server.ts-0uNTZKwF.js} +7 -6
  190. package/build/server/chunks/{_server.ts-B3vd_taO.js.map → _server.ts-0uNTZKwF.js.map} +1 -1
  191. package/build/server/chunks/{_server.ts-CzrUSRs3.js → _server.ts-BIBWjQI-.js} +5 -4
  192. package/build/server/chunks/{_server.ts-CzrUSRs3.js.map → _server.ts-BIBWjQI-.js.map} +1 -1
  193. package/build/server/chunks/{_server.ts-DHMUKVg3.js → _server.ts-BihpbxOW.js} +5 -4
  194. package/build/server/chunks/{_server.ts-DHMUKVg3.js.map → _server.ts-BihpbxOW.js.map} +1 -1
  195. package/build/server/chunks/{_server.ts-das509Hg.js → _server.ts-BuoQ02BW.js} +5 -4
  196. package/build/server/chunks/{_server.ts-das509Hg.js.map → _server.ts-BuoQ02BW.js.map} +1 -1
  197. package/build/server/chunks/{_server.ts-C7c3v6sB.js → _server.ts-CWvU15tL.js} +5 -4
  198. package/build/server/chunks/{_server.ts-C7c3v6sB.js.map → _server.ts-CWvU15tL.js.map} +1 -1
  199. package/build/server/chunks/{_server.ts-DG5OCqvO.js → _server.ts-D4EO0VHu.js} +6 -5
  200. package/build/server/chunks/{_server.ts-DG5OCqvO.js.map → _server.ts-D4EO0VHu.js.map} +1 -1
  201. package/build/server/chunks/{_server.ts-DYI7zGy6.js → _server.ts-DDa0Nk_S.js} +5 -4
  202. package/build/server/chunks/{_server.ts-DYI7zGy6.js.map → _server.ts-DDa0Nk_S.js.map} +1 -1
  203. package/build/server/chunks/{_server.ts-C_4ug89F.js → _server.ts-DcZPhyhK.js} +7 -6
  204. package/build/server/chunks/{_server.ts-C_4ug89F.js.map → _server.ts-DcZPhyhK.js.map} +1 -1
  205. package/build/server/chunks/{_server.ts-96Zq9H2j.js → _server.ts-DsbbVoOn.js} +5 -4
  206. package/build/server/chunks/{_server.ts-96Zq9H2j.js.map → _server.ts-DsbbVoOn.js.map} +1 -1
  207. package/build/server/chunks/{_server.ts-D0xxTo-S.js → _server.ts-Dy5zQHe2.js} +8 -7
  208. package/build/server/chunks/{_server.ts-D0xxTo-S.js.map → _server.ts-Dy5zQHe2.js.map} +1 -1
  209. package/build/server/chunks/{_server.ts-Dz_KfmPw.js → _server.ts-YnfXkeMJ.js} +8 -7
  210. package/build/server/chunks/_server.ts-YnfXkeMJ.js.map +1 -0
  211. package/build/server/chunks/{_server.ts-BRlHKXzL.js → _server.ts-vcaqdwxS.js} +5 -4
  212. package/build/server/chunks/_server.ts-vcaqdwxS.js.map +1 -0
  213. package/build/server/chunks/{browserContainer-Cx0w0pZx.js → browserContainer-CNX7ANld.js} +123 -37
  214. package/build/server/chunks/browserContainer-CNX7ANld.js.map +1 -0
  215. package/build/server/chunks/builderModeStore.svelte-ihupr-3p.js +681 -0
  216. package/build/server/chunks/builderModeStore.svelte-ihupr-3p.js.map +1 -0
  217. package/build/server/chunks/{client-f1rhU0pP.js → client-DfpLcAZ9.js} +2 -2
  218. package/build/server/chunks/{client-f1rhU0pP.js.map → client-DfpLcAZ9.js.map} +1 -1
  219. package/build/server/chunks/{error.svelte-Sw2nazu6.js → error.svelte-C35KOpru.js} +4 -4
  220. package/build/server/chunks/{error.svelte-Sw2nazu6.js.map → error.svelte-C35KOpru.js.map} +1 -1
  221. package/build/server/chunks/eventBus-B9k-Vzso.js +19 -0
  222. package/build/server/chunks/eventBus-B9k-Vzso.js.map +1 -0
  223. package/build/server/chunks/{featuresStore.svelte-B-f41QwP.js → featuresStore.svelte-DR1gYZyu.js} +6 -5
  224. package/build/server/chunks/featuresStore.svelte-DR1gYZyu.js.map +1 -0
  225. package/build/server/chunks/{internal-cdqLNkR1.js → internal-BPKrFkK1.js} +2 -2
  226. package/build/server/chunks/{internal-cdqLNkR1.js.map → internal-BPKrFkK1.js.map} +1 -1
  227. package/build/server/chunks/{projectsStore.svelte-C2Swf2Gc.js → projectsStore.svelte-QDz5PchX.js} +3 -2
  228. package/build/server/chunks/projectsStore.svelte-QDz5PchX.js.map +1 -0
  229. package/build/server/chunks/{reconcile-BIZjLR73.js → reconcile-Dv7jS3C8.js} +3 -3
  230. package/build/server/chunks/{reconcile-BIZjLR73.js.map → reconcile-Dv7jS3C8.js.map} +1 -1
  231. package/build/server/chunks/shared-server-CCs2CV3b.js +14 -0
  232. package/build/server/chunks/shared-server-CCs2CV3b.js.map +1 -0
  233. package/build/server/chunks/{snapshotRepository-DoWj6ZGG.js → snapshotRepository-BPXCjX92.js} +43 -11
  234. package/build/server/chunks/snapshotRepository-BPXCjX92.js.map +1 -0
  235. package/build/server/chunks/{state-CxL934Yr.js → state-CpLVNZq7.js} +2 -2
  236. package/build/server/chunks/{state-CxL934Yr.js.map → state-CpLVNZq7.js.map} +1 -1
  237. package/build/server/chunks/{sync-1tNFVUfQ.js → sync-DZ3dn761.js} +2 -2
  238. package/build/server/chunks/{sync-1tNFVUfQ.js.map → sync-DZ3dn761.js.map} +1 -1
  239. package/build/server/chunks/{syncBridge-BQDytwK1.js → syncBridge-BwXzPdjJ.js} +2 -2
  240. package/build/server/chunks/{syncBridge-BQDytwK1.js.map → syncBridge-BwXzPdjJ.js.map} +1 -1
  241. package/build/server/chunks/{TagDotStrip-BR9Owgav.js → tagPaletteStore.svelte-DfZOBvgY.js} +5 -87
  242. package/build/server/chunks/tagPaletteStore.svelte-DfZOBvgY.js.map +1 -0
  243. package/build/server/chunks/{tourStore.svelte-ExebiCB4.js → tourStore.svelte-CYs4oLjF.js} +2 -2
  244. package/build/server/chunks/tourStore.svelte-CYs4oLjF.js.map +1 -0
  245. package/build/server/index.js +2 -12
  246. package/build/server/index.js.map +1 -1
  247. package/build/server/manifest.js +36 -28
  248. package/build/server/manifest.js.map +1 -1
  249. package/cli/README.md +46 -20
  250. package/cli/clients/claude-code.ts +5 -4
  251. package/cli/clients/claude-desktop.ts +5 -4
  252. package/cli/commands/dashboard.ts +38 -4
  253. package/cli/commands/init.ts +147 -84
  254. package/cli/commands/view.ts +77 -0
  255. package/cli/skills/unspa-audit/SKILL.md +9 -0
  256. package/cli/skills/unspa-edit/SKILL.md +91 -0
  257. package/cli/skills/unspa-implement/SKILL.md +46 -1
  258. package/cli/unspa.ts +57 -13
  259. package/cli/util/context-files.ts +5 -3
  260. package/cli/util/views.ts +38 -0
  261. package/mcp-server/resources/guide.ts +6 -4
  262. package/mcp-server/resources/operations.ts +11 -4
  263. package/mcp-server/server.ts +5 -1
  264. package/mcp-server/tools/_entity_builders.ts +44 -2
  265. package/mcp-server/tools/_evolution.ts +53 -0
  266. package/mcp-server/tools/action.ts +64 -6
  267. package/mcp-server/tools/batch.ts +1276 -1217
  268. package/mcp-server/tools/behavioralIndex.ts +193 -193
  269. package/mcp-server/tools/feature.ts +17 -9
  270. package/mcp-server/tools/parameter.ts +179 -172
  271. package/mcp-server/tools/queue.ts +101 -9
  272. package/mcp-server/tools/scenario.ts +19 -4
  273. package/mcp-server/tools/specGaps.ts +14 -1
  274. package/mcp-server/tools/state.ts +165 -156
  275. package/mcp-server/tools/valueSet.ts +95 -0
  276. package/package.json +3 -1
  277. package/src/features/behavior-model/application/use-cases/MutateFeature.ts +20 -31
  278. package/src/features/behavior-model/application/use-cases/SaveFeature.ts +13 -9
  279. package/src/features/behavior-model/domain/entities/Action.ts +167 -95
  280. package/src/features/behavior-model/domain/entities/Feature.ts +60 -51
  281. package/src/features/behavior-model/domain/entities/Parameter.ts +40 -34
  282. package/src/features/behavior-model/domain/entities/Scenario.ts +109 -67
  283. package/src/features/behavior-model/domain/entities/StateDefinition.ts +8 -1
  284. package/src/features/behavior-model/domain/entities/ValueSet.ts +16 -0
  285. package/src/features/behavior-model/domain/services/EnumValues.ts +27 -0
  286. package/src/features/behavior-model/domain/services/FeatureTransforms.ts +1052 -984
  287. package/src/features/behavior-model/domain/services/FeatureValidator.ts +968 -815
  288. package/src/features/behavior-model/domain/services/ParameterValidator.ts +12 -8
  289. package/src/features/behavior-model/domain/value-objects/ids.ts +35 -33
  290. package/src/features/behavior-model/infrastructure/persistence/InMemoryFeatureRepository.ts +37 -37
  291. package/src/features/behavior-model/infrastructure/persistence/JsonFolderFeatureRepository.ts +1 -1
  292. package/src/features/behavior-model/infrastructure/persistence/snapshot-discovery.ts +28 -3
  293. package/src/features/behavior-model/presentation/components/ActionEditor.svelte +55 -7
  294. package/src/features/builder-mode/application/use-cases/GetBuilderModeDashboard.ts +41 -0
  295. package/src/features/builder-mode/application/use-cases/GetBuilderModeProject.ts +42 -0
  296. package/src/features/builder-mode/domain/BuilderModeDashboard.ts +172 -0
  297. package/src/features/builder-mode/infrastructure/adapters/defaultBuilderHost.ts +27 -0
  298. package/src/features/builder-mode/presentation/components/BuilderModeDashboard.svelte +1335 -0
  299. package/src/features/builder-mode/presentation/components/BuilderTagChips.svelte +289 -0
  300. package/src/features/builder-mode/presentation/components/ClampedDescription.svelte +174 -0
  301. package/src/features/builder-mode/presentation/components/GameScore.svelte +194 -0
  302. package/src/features/builder-mode/presentation/ports/BuilderHostPorts.ts +39 -0
  303. package/src/features/builder-mode/presentation/stores/builderModeStore.svelte.ts +679 -0
  304. package/src/features/domains/infrastructure/persistence/InMemoryDomainRepository.ts +1 -1
  305. package/src/features/domains/infrastructure/persistence/JsonFolderDomainRepository.ts +1 -1
  306. package/src/features/implementation-queue/application/use-cases/EnqueueQueueItem.ts +16 -5
  307. package/src/features/implementation-queue/application/use-cases/SetQueueItemTarget.ts +38 -0
  308. package/src/features/implementation-queue/domain/entities/QueueItem.ts +43 -0
  309. package/src/features/implementation-queue/domain/services/QueueOperations.ts +26 -1
  310. package/src/features/maturity/domain/MaturityScorer.ts +13 -4
  311. package/src/features/mcp-tools/application/tools/generateTypes.ts +254 -250
  312. package/src/features/mcp-tools/application/tools/listActions.ts +9 -1
  313. package/src/features/projects/infrastructure/io/ProjectJson.ts +25 -4
  314. package/src/features/projects/infrastructure/persistence/InMemoryProjectRepository.ts +33 -33
  315. package/src/features/projects/infrastructure/persistence/JsonFolderProjectRepository.ts +1 -1
  316. package/src/features/simulator/application/use-cases/RunScenarios.ts +449 -310
  317. package/src/features/simulator/domain/SimulatorEngine.ts +324 -320
  318. package/src/lib/views/enabled.ts +19 -0
  319. package/src/lib/views/registry.ts +72 -0
  320. package/src/routes/+layout.svelte +583 -348
  321. package/src/routes/builder-mode/+page.svelte +9 -0
  322. package/src/routes/builder-mode/+page.ts +12 -0
  323. package/src/routes/tutorial/+page.svelte +8 -0
  324. package/src/shared/infrastructure/container.ts +208 -199
  325. package/build/client/_app/immutable/assets/0.BgNAkMzG.css +0 -1
  326. package/build/client/_app/immutable/assets/0.BgNAkMzG.css.br +0 -0
  327. package/build/client/_app/immutable/assets/0.BgNAkMzG.css.gz +0 -0
  328. package/build/client/_app/immutable/chunks/-s9hRK72.js.br +0 -0
  329. package/build/client/_app/immutable/chunks/-s9hRK72.js.gz +0 -0
  330. package/build/client/_app/immutable/chunks/1_r1S7Ly.js +0 -1
  331. package/build/client/_app/immutable/chunks/1_r1S7Ly.js.br +0 -0
  332. package/build/client/_app/immutable/chunks/1_r1S7Ly.js.gz +0 -0
  333. package/build/client/_app/immutable/chunks/B-lvxr_Y.js +0 -1
  334. package/build/client/_app/immutable/chunks/B-lvxr_Y.js.br +0 -0
  335. package/build/client/_app/immutable/chunks/B-lvxr_Y.js.gz +0 -0
  336. package/build/client/_app/immutable/chunks/B4Mul34I.js +0 -1
  337. package/build/client/_app/immutable/chunks/B4Mul34I.js.br +0 -2
  338. package/build/client/_app/immutable/chunks/B4Mul34I.js.gz +0 -0
  339. package/build/client/_app/immutable/chunks/BQQLoxQo.js +0 -5
  340. package/build/client/_app/immutable/chunks/BQQLoxQo.js.br +0 -0
  341. package/build/client/_app/immutable/chunks/BQQLoxQo.js.gz +0 -0
  342. package/build/client/_app/immutable/chunks/BTLTzKaZ.js.br +0 -1
  343. package/build/client/_app/immutable/chunks/BTLTzKaZ.js.gz +0 -0
  344. package/build/client/_app/immutable/chunks/BY81EmU42.js +0 -2
  345. package/build/client/_app/immutable/chunks/BY81EmU42.js.br +0 -0
  346. package/build/client/_app/immutable/chunks/BY81EmU42.js.gz +0 -0
  347. package/build/client/_app/immutable/chunks/BiHfqo9Y.js +0 -2
  348. package/build/client/_app/immutable/chunks/BiHfqo9Y.js.br +0 -0
  349. package/build/client/_app/immutable/chunks/BiHfqo9Y.js.gz +0 -0
  350. package/build/client/_app/immutable/chunks/Buny4Lxq.js.br +0 -0
  351. package/build/client/_app/immutable/chunks/Buny4Lxq.js.gz +0 -0
  352. package/build/client/_app/immutable/chunks/CDgx1pP22.js.br +0 -0
  353. package/build/client/_app/immutable/chunks/CDgx1pP22.js.gz +0 -0
  354. package/build/client/_app/immutable/chunks/CKUA0lwj.js +0 -1
  355. package/build/client/_app/immutable/chunks/CKUA0lwj.js.br +0 -0
  356. package/build/client/_app/immutable/chunks/CKUA0lwj.js.gz +0 -0
  357. package/build/client/_app/immutable/chunks/CM5qK71w.js +0 -6
  358. package/build/client/_app/immutable/chunks/CM5qK71w.js.br +0 -0
  359. package/build/client/_app/immutable/chunks/CM5qK71w.js.gz +0 -0
  360. package/build/client/_app/immutable/chunks/CvxLPre7.js +0 -1
  361. package/build/client/_app/immutable/chunks/CvxLPre7.js.br +0 -0
  362. package/build/client/_app/immutable/chunks/CvxLPre7.js.gz +0 -0
  363. package/build/client/_app/immutable/chunks/D9BWIMZD.js +0 -1
  364. package/build/client/_app/immutable/chunks/D9BWIMZD.js.br +0 -0
  365. package/build/client/_app/immutable/chunks/D9BWIMZD.js.gz +0 -0
  366. package/build/client/_app/immutable/chunks/DC_h2his.js +0 -1
  367. package/build/client/_app/immutable/chunks/DC_h2his.js.br +0 -0
  368. package/build/client/_app/immutable/chunks/DC_h2his.js.gz +0 -0
  369. package/build/client/_app/immutable/chunks/DF6QYH3p.js +0 -3
  370. package/build/client/_app/immutable/chunks/DF6QYH3p.js.br +0 -0
  371. package/build/client/_app/immutable/chunks/DF6QYH3p.js.gz +0 -0
  372. package/build/client/_app/immutable/chunks/DHnrY7Sb.js +0 -1
  373. package/build/client/_app/immutable/chunks/DHnrY7Sb.js.br +0 -0
  374. package/build/client/_app/immutable/chunks/DHnrY7Sb.js.gz +0 -0
  375. package/build/client/_app/immutable/chunks/Dv09pO87.js +0 -1
  376. package/build/client/_app/immutable/chunks/Dv09pO87.js.br +0 -0
  377. package/build/client/_app/immutable/chunks/Dv09pO87.js.gz +0 -0
  378. package/build/client/_app/immutable/chunks/Dvd8XBNO.js +0 -1
  379. package/build/client/_app/immutable/chunks/Dvd8XBNO.js.br +0 -1
  380. package/build/client/_app/immutable/chunks/Dvd8XBNO.js.gz +0 -0
  381. package/build/client/_app/immutable/chunks/K3JxBPSQ.js +0 -1
  382. package/build/client/_app/immutable/chunks/K3JxBPSQ.js.br +0 -0
  383. package/build/client/_app/immutable/chunks/K3JxBPSQ.js.gz +0 -0
  384. package/build/client/_app/immutable/chunks/Q8pmKDJe.js.br +0 -0
  385. package/build/client/_app/immutable/chunks/Q8pmKDJe.js.gz +0 -0
  386. package/build/client/_app/immutable/chunks/gQ3oD_Dm.js +0 -1
  387. package/build/client/_app/immutable/chunks/gQ3oD_Dm.js.br +0 -0
  388. package/build/client/_app/immutable/chunks/gQ3oD_Dm.js.gz +0 -0
  389. package/build/client/_app/immutable/chunks/lHLL3RmT.js +0 -1
  390. package/build/client/_app/immutable/chunks/lHLL3RmT.js.br +0 -0
  391. package/build/client/_app/immutable/chunks/lHLL3RmT.js.gz +0 -0
  392. package/build/client/_app/immutable/entry/app.DdaNJvmo.js +0 -2
  393. package/build/client/_app/immutable/entry/app.DdaNJvmo.js.br +0 -0
  394. package/build/client/_app/immutable/entry/app.DdaNJvmo.js.gz +0 -0
  395. package/build/client/_app/immutable/entry/start.Cu21IWs-.js +0 -1
  396. package/build/client/_app/immutable/entry/start.Cu21IWs-.js.br +0 -0
  397. package/build/client/_app/immutable/entry/start.Cu21IWs-.js.gz +0 -0
  398. package/build/client/_app/immutable/nodes/0.C1BTEwKm.js +0 -3
  399. package/build/client/_app/immutable/nodes/0.C1BTEwKm.js.br +0 -0
  400. package/build/client/_app/immutable/nodes/0.C1BTEwKm.js.gz +0 -0
  401. package/build/client/_app/immutable/nodes/1.C3Ve_ouq.js +0 -1
  402. package/build/client/_app/immutable/nodes/1.C3Ve_ouq.js.br +0 -0
  403. package/build/client/_app/immutable/nodes/1.C3Ve_ouq.js.gz +0 -0
  404. package/build/client/_app/immutable/nodes/2.CRcsCTzc.js +0 -1
  405. package/build/client/_app/immutable/nodes/2.CRcsCTzc.js.br +0 -0
  406. package/build/client/_app/immutable/nodes/2.CRcsCTzc.js.gz +0 -0
  407. package/build/client/_app/immutable/nodes/3.rv7UrHHg.js +0 -3
  408. package/build/client/_app/immutable/nodes/3.rv7UrHHg.js.br +0 -0
  409. package/build/client/_app/immutable/nodes/3.rv7UrHHg.js.gz +0 -0
  410. package/build/client/_app/immutable/nodes/4.Cev4WT4u.js +0 -42
  411. package/build/client/_app/immutable/nodes/4.Cev4WT4u.js.br +0 -0
  412. package/build/client/_app/immutable/nodes/4.Cev4WT4u.js.gz +0 -0
  413. package/build/client/_app/immutable/nodes/5.0DKVfFv2.js +0 -5
  414. package/build/client/_app/immutable/nodes/5.0DKVfFv2.js.br +0 -0
  415. package/build/client/_app/immutable/nodes/5.0DKVfFv2.js.gz +0 -0
  416. package/build/client/_app/immutable/nodes/6.DCJwg-TV.js +0 -1
  417. package/build/client/_app/immutable/nodes/6.DCJwg-TV.js.br +0 -0
  418. package/build/client/_app/immutable/nodes/6.DCJwg-TV.js.gz +0 -0
  419. package/build/client/_app/immutable/nodes/7.BFdt4Nqg.js +0 -5
  420. package/build/client/_app/immutable/nodes/7.BFdt4Nqg.js.br +0 -0
  421. package/build/client/_app/immutable/nodes/7.BFdt4Nqg.js.gz +0 -0
  422. package/build/client/_app/immutable/nodes/8.aFYV9MSb.js.br +0 -0
  423. package/build/client/_app/immutable/nodes/8.aFYV9MSb.js.gz +0 -0
  424. package/build/server/chunks/0-XDHB9lbZ.js +0 -15
  425. package/build/server/chunks/0-XDHB9lbZ.js.map +0 -1
  426. package/build/server/chunks/1-BM_rl7Bx.js +0 -9
  427. package/build/server/chunks/2-DmFhuHKK.js +0 -9
  428. package/build/server/chunks/2-DmFhuHKK.js.map +0 -1
  429. package/build/server/chunks/3-B3Ro5GyH.js +0 -16
  430. package/build/server/chunks/3-B3Ro5GyH.js.map +0 -1
  431. package/build/server/chunks/4-cj58VJgj.js +0 -9
  432. package/build/server/chunks/4-cj58VJgj.js.map +0 -1
  433. package/build/server/chunks/5-BW_j9O5v.js +0 -9
  434. package/build/server/chunks/5-BW_j9O5v.js.map +0 -1
  435. package/build/server/chunks/6-Bj0uWvDK.js +0 -9
  436. package/build/server/chunks/6-Bj0uWvDK.js.map +0 -1
  437. package/build/server/chunks/7-DiKTsjh1.js +0 -9
  438. package/build/server/chunks/7-DiKTsjh1.js.map +0 -1
  439. package/build/server/chunks/8-CZiwFSj3.js +0 -9
  440. package/build/server/chunks/8-CZiwFSj3.js.map +0 -1
  441. package/build/server/chunks/FeatureValidator-BcY63x9D.js +0 -262
  442. package/build/server/chunks/FeatureValidator-BcY63x9D.js.map +0 -1
  443. package/build/server/chunks/ManageTagsDialog-DO6XplIb.js.map +0 -1
  444. package/build/server/chunks/ProjectsIndex-Boeoj8Zh.js.map +0 -1
  445. package/build/server/chunks/TagDotStrip-BR9Owgav.js.map +0 -1
  446. package/build/server/chunks/TagFilterSelect-5EaFX5CY.js.map +0 -1
  447. package/build/server/chunks/TagPalette-CvQJ40bt.js.map +0 -1
  448. package/build/server/chunks/_layout.svelte-BV7JjoXo.js.map +0 -1
  449. package/build/server/chunks/_page.svelte-AXKie8xV.js.map +0 -1
  450. package/build/server/chunks/_page.svelte-BSo9Np-N.js.map +0 -1
  451. package/build/server/chunks/_page.svelte-D-CofieG.js +0 -27
  452. package/build/server/chunks/_page.svelte-D4bCUYdF.js +0 -27
  453. package/build/server/chunks/_page.svelte-DDOUOH7d.js.map +0 -1
  454. package/build/server/chunks/_server.ts-BRlHKXzL.js.map +0 -1
  455. package/build/server/chunks/_server.ts-Dz_KfmPw.js.map +0 -1
  456. package/build/server/chunks/browserContainer-Cx0w0pZx.js.map +0 -1
  457. package/build/server/chunks/featuresStore.svelte-B-f41QwP.js.map +0 -1
  458. package/build/server/chunks/projectsStore.svelte-C2Swf2Gc.js.map +0 -1
  459. package/build/server/chunks/snapshotRepository-DoWj6ZGG.js.map +0 -1
  460. package/build/server/chunks/tourStore.svelte-ExebiCB4.js.map +0 -1
  461. /package/build/client/_app/immutable/assets/{8.nv0I59TU.css → 9.nv0I59TU.css} +0 -0
  462. /package/build/client/_app/immutable/assets/{8.nv0I59TU.css.br → 9.nv0I59TU.css.br} +0 -0
  463. /package/build/client/_app/immutable/assets/{8.nv0I59TU.css.gz → 9.nv0I59TU.css.gz} +0 -0
  464. /package/build/client/_app/immutable/chunks/{BQ9GodWX.js → BQ9GodWX2.js} +0 -0
  465. /package/build/client/_app/immutable/chunks/{BQ9GodWX.js.br → BQ9GodWX2.js.br} +0 -0
  466. /package/build/client/_app/immutable/chunks/{BQ9GodWX.js.gz → BQ9GodWX2.js.gz} +0 -0
@@ -0,0 +1,289 @@
1
+ <script lang="ts" module>
2
+ let nextDatalistSerial = 0;
3
+ </script>
4
+
5
+ <script lang="ts">
6
+ import { tick } from 'svelte';
7
+ import { humanizeTagText, tagKey, tagLabel, type Tag } from '$shared/domain/Tags';
8
+ import { builderModeStore } from '$features/builder-mode/presentation/stores/builderModeStore.svelte';
9
+ import type { TagColor } from '$shared/domain/TagPalette';
10
+ import type { Action } from 'svelte/action';
11
+
12
+ /**
13
+ * Smoothly tween the wrapper's height to its content height whenever that
14
+ * content changes — the add `+` appearing on hover, or chips wrapping to a
15
+ * new line. Without this the card would jump in height.
16
+ *
17
+ * While a form is open (`editing`) the wrapper goes `overflow: visible` /
18
+ * `height: auto`: a clipped, fixed-height box throws off the native datalist
19
+ * dropdown's anchor (it renders far from the input) and would clip the form.
20
+ * Honors prefers-reduced-motion.
21
+ */
22
+ const animateHeight: Action<HTMLElement, boolean> = (node, editing = false) => {
23
+ const inner = node.firstElementChild as HTMLElement | null;
24
+ if (!inner) return;
25
+ const reduce =
26
+ typeof matchMedia === 'function' && matchMedia('(prefers-reduced-motion: reduce)').matches;
27
+ const hasObserver = typeof ResizeObserver !== 'undefined';
28
+ let last = inner.offsetHeight;
29
+
30
+ const toOpen = () => {
31
+ // Unclip so inputs and the native type dropdown lay out / anchor correctly.
32
+ node.style.transition = '';
33
+ node.style.overflow = 'visible';
34
+ node.style.height = 'auto';
35
+ };
36
+ const toClipped = () => {
37
+ node.style.overflow = 'hidden';
38
+ if (!hasObserver) {
39
+ node.style.height = 'auto';
40
+ return;
41
+ }
42
+ const start = node.offsetHeight;
43
+ last = inner.offsetHeight;
44
+ if (reduce) {
45
+ node.style.height = `${last}px`;
46
+ return;
47
+ }
48
+ node.style.transition = 'height 240ms cubic-bezier(0.22, 1, 0.36, 1)';
49
+ node.style.height = `${start}px`;
50
+ void node.offsetHeight; // commit the start height before transitioning
51
+ node.style.height = `${last}px`;
52
+ };
53
+
54
+ let isEditing = editing;
55
+ if (isEditing) toOpen();
56
+ else {
57
+ node.style.overflow = 'hidden';
58
+ node.style.height = `${last}px`;
59
+ if (!reduce) node.style.transition = 'height 240ms cubic-bezier(0.22, 1, 0.36, 1)';
60
+ }
61
+
62
+ let observer: ResizeObserver | null = null;
63
+ if (hasObserver) {
64
+ observer = new ResizeObserver(() => {
65
+ if (isEditing) return; // height:auto handles growth while a form is open
66
+ const next = inner.offsetHeight;
67
+ if (next === last) return;
68
+ if (reduce) {
69
+ node.style.height = `${next}px`;
70
+ last = next;
71
+ return;
72
+ }
73
+ node.style.height = `${last}px`;
74
+ void node.offsetHeight;
75
+ node.style.height = `${next}px`;
76
+ last = next;
77
+ });
78
+ observer.observe(inner);
79
+ } else if (!isEditing) {
80
+ node.style.height = 'auto';
81
+ }
82
+
83
+ return {
84
+ update(next: boolean) {
85
+ if (next === isEditing) return;
86
+ isEditing = next;
87
+ if (isEditing) toOpen();
88
+ else toClipped();
89
+ },
90
+ destroy: () => observer?.disconnect()
91
+ };
92
+ };
93
+
94
+ let {
95
+ tags,
96
+ onToggle,
97
+ isActive,
98
+ onAdd,
99
+ onRemove,
100
+ onRename,
101
+ typeOptions = [],
102
+ class: className = ''
103
+ }: {
104
+ readonly tags: readonly Tag[];
105
+ readonly onToggle?: (tag: Tag) => void;
106
+ readonly isActive?: (tag: Tag) => boolean;
107
+ readonly onAdd?: (type: string, value: string) => void | Promise<void>;
108
+ readonly onRemove?: (tag: Tag) => void | Promise<void>;
109
+ readonly onRename?: (from: Tag, to: Tag) => void | Promise<void>;
110
+ readonly typeOptions?: readonly string[];
111
+ readonly class?: string;
112
+ } = $props();
113
+
114
+ const datalistId = `buildertags-types-${++nextDatalistSerial}`;
115
+
116
+ // Mix the palette color toward a deep slate for the dark builder plate (the
117
+ // shared light-theme styles mix toward white). `active` brightens the chip.
118
+ const SLATE = '#64748b';
119
+ const chipStyle = (color: TagColor | null, active: boolean): string => {
120
+ const base = color ?? SLATE;
121
+ const fill = active ? 42 : 20;
122
+ const ring = active ? 72 : 42;
123
+ return [
124
+ `background-color: color-mix(in srgb, ${base} ${fill}%, #0b1220)`,
125
+ `color: color-mix(in srgb, ${base} 72%, white)`,
126
+ `box-shadow: inset 0 0 0 1px color-mix(in srgb, ${base} ${ring}%, transparent)`
127
+ ].join('; ');
128
+ };
129
+
130
+ // ── add ──
131
+ let adding = $state(false);
132
+ let addType = $state('');
133
+ let addValue = $state('');
134
+ let addInput = $state<HTMLInputElement | null>(null);
135
+
136
+ async function startAdd() {
137
+ adding = true;
138
+ await tick();
139
+ addInput?.focus();
140
+ }
141
+ function cancelAdd() {
142
+ adding = false;
143
+ addType = '';
144
+ addValue = '';
145
+ }
146
+ async function submitAdd(event: SubmitEvent) {
147
+ event.preventDefault();
148
+ const value = addValue.trim();
149
+ if (!value) return;
150
+ const type = addType.trim() || 'tag';
151
+ cancelAdd(); // close the form immediately; the chip appears once persisted
152
+ await onAdd?.(type, value);
153
+ }
154
+
155
+ // ── rename (propagates everywhere the tag is used) ──
156
+ let editingKey = $state<string | null>(null);
157
+ let editType = $state('');
158
+ let editValue = $state('');
159
+ let editInput = $state<HTMLInputElement | null>(null);
160
+
161
+ async function startEdit(tag: Tag) {
162
+ editingKey = tagKey(tag);
163
+ editType = humanizeTagText(tag.type);
164
+ editValue = humanizeTagText(tag.value);
165
+ await tick();
166
+ editInput?.select();
167
+ }
168
+ function cancelEdit() {
169
+ editingKey = null;
170
+ }
171
+ async function submitEdit(event: SubmitEvent, from: Tag) {
172
+ event.preventDefault();
173
+ const value = editValue.trim();
174
+ const type = editType.trim();
175
+ if (!value || !type) return;
176
+ cancelEdit();
177
+ await onRename?.(from, { type, value });
178
+ }
179
+
180
+ function onFormKey(event: KeyboardEvent, cancel: () => void) {
181
+ if (event.key === 'Escape') cancel();
182
+ }
183
+ </script>
184
+
185
+ {#if tags.length > 0 || onAdd}
186
+ <div class={className} use:animateHeight={adding || editingKey !== null}>
187
+ <div class="flex flex-wrap items-center gap-1.5">
188
+ {#each tags as tag (tagKey(tag))}
189
+ {#if editingKey === tagKey(tag)}
190
+ <form class="inline-flex items-center gap-1" onsubmit={(e) => submitEdit(e, tag)}>
191
+ <input
192
+ bind:this={editInput}
193
+ bind:value={editType}
194
+ list={typeOptions.length > 0 ? datalistId : undefined}
195
+ placeholder="Type"
196
+ onkeydown={(e) => onFormKey(e, cancelEdit)}
197
+ class="h-6 w-16 rounded border border-slate-700 bg-slate-900/70 px-1.5 text-[11px] text-slate-200 outline-none focus:border-brand-500"
198
+ />
199
+ <input
200
+ bind:value={editValue}
201
+ placeholder="Value"
202
+ onkeydown={(e) => onFormKey(e, cancelEdit)}
203
+ class="h-6 w-20 rounded border border-slate-700 bg-slate-900/70 px-1.5 text-[11px] text-slate-200 outline-none focus:border-brand-500"
204
+ />
205
+ <button type="submit" class="text-[11px] font-semibold text-brand-300 hover:text-brand-200" title="Rename everywhere">✓</button>
206
+ <button type="button" class="text-[11px] text-slate-500 hover:text-slate-300" onclick={cancelEdit} title="Cancel">✕</button>
207
+ </form>
208
+ {:else}
209
+ {@const color = builderModeStore.colorForTag(tag)}
210
+ {@const active = isActive?.(tag) ?? false}
211
+ <span
212
+ class="group/chip inline-flex max-w-full items-center gap-1 rounded-full py-0.5 pl-2 pr-1.5 text-[10px] font-medium transition"
213
+ style={chipStyle(color, active)}
214
+ >
215
+ <span class="size-1.5 shrink-0 rounded-full" style="background-color: {color ?? SLATE}"></span>
216
+ {#if onToggle}
217
+ <button
218
+ type="button"
219
+ class="truncate"
220
+ onclick={() => onToggle(tag)}
221
+ aria-pressed={active}
222
+ title={`${tagLabel(tag)} — click to filter`}
223
+ >{humanizeTagText(tag.value)}</button>
224
+ {:else}
225
+ <span class="truncate" title={tagLabel(tag)}>{humanizeTagText(tag.value)}</span>
226
+ {/if}
227
+ {#if onRename}
228
+ <button
229
+ type="button"
230
+ class="shrink-0 opacity-0 transition group-hover/chip:opacity-70 hover:opacity-100!"
231
+ onclick={() => startEdit(tag)}
232
+ aria-label={`Rename ${tagLabel(tag)}`}
233
+ title="Rename (applies everywhere)"
234
+ >✎</button>
235
+ {/if}
236
+ {#if onRemove}
237
+ <button
238
+ type="button"
239
+ class="shrink-0 opacity-0 transition group-hover/chip:opacity-70 hover:opacity-100!"
240
+ onclick={() => onRemove(tag)}
241
+ aria-label={`Remove ${tagLabel(tag)}`}
242
+ title="Remove from this item"
243
+ >✕</button>
244
+ {/if}
245
+ </span>
246
+ {/if}
247
+ {/each}
248
+
249
+ {#if onAdd}
250
+ {#if adding}
251
+ <form class="inline-flex items-center gap-1" onsubmit={submitAdd}>
252
+ <input
253
+ bind:this={addInput}
254
+ bind:value={addType}
255
+ list={typeOptions.length > 0 ? datalistId : undefined}
256
+ placeholder="Type"
257
+ onkeydown={(e) => onFormKey(e, cancelAdd)}
258
+ class="h-6 w-16 rounded border border-slate-700 bg-slate-900/70 px-1.5 text-[11px] text-slate-200 outline-none focus:border-brand-500"
259
+ />
260
+ <input
261
+ bind:value={addValue}
262
+ placeholder="Value"
263
+ onkeydown={(e) => onFormKey(e, cancelAdd)}
264
+ class="h-6 w-20 rounded border border-slate-700 bg-slate-900/70 px-1.5 text-[11px] text-slate-200 outline-none focus:border-brand-500"
265
+ />
266
+ <button type="submit" class="text-[11px] font-semibold text-brand-300 hover:text-brand-200" title="Add tag">✓</button>
267
+ <button type="button" class="text-[11px] text-slate-500 hover:text-slate-300" onclick={cancelAdd} title="Cancel">✕</button>
268
+ </form>
269
+ {:else}
270
+ <button
271
+ type="button"
272
+ class="size-5 items-center justify-center rounded-full border border-dashed border-slate-600 text-[11px] leading-none text-slate-400 transition hover:border-brand-500 hover:text-brand-300 hidden group-hover:inline-flex group-focus-within:inline-flex"
273
+ onclick={startAdd}
274
+ aria-label="Add tag"
275
+ title="Add tag"
276
+ >+</button>
277
+ {/if}
278
+ {/if}
279
+
280
+ {#if typeOptions.length > 0}
281
+ <datalist id={datalistId}>
282
+ {#each typeOptions as option (option)}
283
+ <option value={option}></option>
284
+ {/each}
285
+ </datalist>
286
+ {/if}
287
+ </div>
288
+ </div>
289
+ {/if}
@@ -0,0 +1,174 @@
1
+ <script lang="ts">
2
+ let {
3
+ text,
4
+ class: className = ''
5
+ }: {
6
+ readonly text: string;
7
+ readonly class?: string;
8
+ } = $props();
9
+
10
+ let expanded = $state(false);
11
+ let overflowing = $state(false);
12
+ let animating = $state(false);
13
+ let el = $state<HTMLParagraphElement | null>(null);
14
+
15
+ // Open feels expansive (easeOutExpo — fast then a long, soft settle); close
16
+ // is a touch quicker and symmetric (easeInOutCubic). The values are tuned to
17
+ // read as one physical motion rather than a linear height tween.
18
+ const OPEN = '560ms cubic-bezier(0.16, 1, 0.3, 1)';
19
+ const CLOSE = '440ms cubic-bezier(0.65, 0, 0.35, 1)';
20
+ const SOFT_EDGE = 'linear-gradient(to bottom, #000 calc(100% - 1.3em), transparent)';
21
+
22
+ const prefersReducedMotion = (): boolean =>
23
+ typeof matchMedia === 'function' && matchMedia('(prefers-reduced-motion: reduce)').matches;
24
+
25
+ const clampedHeight = (node: HTMLElement): number => {
26
+ const lineHeight = parseFloat(getComputedStyle(node).lineHeight) || 20;
27
+ return lineHeight * 2;
28
+ };
29
+
30
+ // Cancels the in-flight animation's transitionend listener so a mid-flight
31
+ // re-toggle doesn't get its cleanup stomped by the previous run.
32
+ let cancelPending: (() => void) | null = null;
33
+
34
+ // Reveal only carries a toggle when the clamped text actually overflows.
35
+ // While clamped, scrollHeight (full content) exceeds clientHeight (2 lines).
36
+ // Re-measured on text changes and width changes (the columns resize).
37
+ $effect(() => {
38
+ const node = el;
39
+ if (!node) return;
40
+ void text;
41
+ const measure = () => {
42
+ if (expanded || animating) return; // clientHeight === scrollHeight once open
43
+ overflowing = node.scrollHeight > node.clientHeight + 1;
44
+ };
45
+ measure();
46
+ if (typeof ResizeObserver === 'undefined') return;
47
+ const observer = new ResizeObserver(measure);
48
+ observer.observe(node);
49
+ return () => observer.disconnect();
50
+ });
51
+
52
+ function toggle(): void {
53
+ const node = el;
54
+ if (!node) return;
55
+ if (expanded) collapse(node);
56
+ else expand(node);
57
+ }
58
+
59
+ /**
60
+ * Run `max-height` from `startPx` to `endPx` with `timing`. The caller must
61
+ * already have the clamp in the right state; we pin the start height (no
62
+ * transition), commit it, then transition to the end. Starting from a caller-
63
+ * supplied height — captured BEFORE any clamp change — is what makes both
64
+ * directions animate, and makes mid-flight re-toggles reverse seamlessly.
65
+ */
66
+ function animateHeight(
67
+ node: HTMLElement,
68
+ startPx: number,
69
+ endPx: number,
70
+ timing: string,
71
+ onDone: () => void
72
+ ): void {
73
+ cancelPending?.();
74
+ animating = true;
75
+ node.style.overflow = 'hidden';
76
+ node.style.webkitMaskImage = SOFT_EDGE;
77
+ node.style.maskImage = SOFT_EDGE;
78
+ node.style.transition = 'none';
79
+ node.style.maxHeight = `${startPx}px`;
80
+ void node.offsetHeight; // commit the start frame before transitioning
81
+ node.style.transition = `max-height ${timing}`;
82
+ node.style.maxHeight = `${endPx}px`;
83
+
84
+ const done = (event: TransitionEvent) => {
85
+ if (event.propertyName !== 'max-height') return;
86
+ node.removeEventListener('transitionend', done);
87
+ cancelPending = null;
88
+ animating = false;
89
+ onDone();
90
+ };
91
+ node.addEventListener('transitionend', done);
92
+ cancelPending = () => node.removeEventListener('transitionend', done);
93
+ }
94
+
95
+ function expand(node: HTMLElement): void {
96
+ // Capture the clamped (2-line) height BEFORE unclamping — otherwise the
97
+ // element is already at full height and start === end (the instant-open bug).
98
+ const startPx = node.clientHeight;
99
+ expanded = true;
100
+ // Drop the line-clamp so content can exceed two lines; the pinned start
101
+ // height keeps it visually at two lines until the transition takes over.
102
+ node.classList.remove('clamp-2');
103
+ if (prefersReducedMotion()) return;
104
+ void node.offsetHeight; // let scrollHeight reflect the now-unclamped content
105
+ animateHeight(node, startPx, node.scrollHeight, OPEN, () => {
106
+ // Fully open: release every constraint so later reflow can't clip it.
107
+ node.style.transition = '';
108
+ node.style.maxHeight = 'none';
109
+ node.style.overflow = '';
110
+ node.style.webkitMaskImage = '';
111
+ node.style.maskImage = '';
112
+ });
113
+ }
114
+
115
+ function collapse(node: HTMLElement): void {
116
+ const startPx = node.clientHeight; // current (expanded / mid-animation) height
117
+ expanded = false;
118
+ if (prefersReducedMotion()) {
119
+ node.classList.add('clamp-2');
120
+ node.style.maxHeight = '';
121
+ return;
122
+ }
123
+ animateHeight(node, startPx, clampedHeight(node), CLOSE, () => {
124
+ // Restore the resting clamp (with its ellipsis) and drop inline overrides.
125
+ node.classList.add('clamp-2');
126
+ node.style.transition = '';
127
+ node.style.maxHeight = '';
128
+ node.style.overflow = '';
129
+ node.style.webkitMaskImage = '';
130
+ node.style.maskImage = '';
131
+ });
132
+ }
133
+ </script>
134
+
135
+ <div class={className}>
136
+ <p bind:this={el} class="clamp-2 text-sm leading-5 text-slate-400">{text}</p>
137
+ {#if overflowing || expanded || animating}
138
+ <button
139
+ type="button"
140
+ class="relative z-20 mt-1 inline-flex items-center gap-1 text-xs font-semibold text-brand-400 transition hover:text-brand-300"
141
+ onclick={toggle}
142
+ aria-expanded={expanded}
143
+ >
144
+ <span>{expanded ? 'View less' : 'View more'}</span>
145
+ <svg
146
+ viewBox="0 0 16 16"
147
+ class="h-3 w-3 transition-transform duration-500 ease-out {expanded ? 'rotate-180' : ''}"
148
+ fill="none"
149
+ stroke="currentColor"
150
+ stroke-width="2"
151
+ aria-hidden="true"
152
+ >
153
+ <path d="M4 6l4 4 4-4" stroke-linecap="round" stroke-linejoin="round" />
154
+ </svg>
155
+ </button>
156
+ {/if}
157
+ </div>
158
+
159
+ <style>
160
+ /*
161
+ * Resting two-line clamp with ellipsis. Toggled imperatively (not via a
162
+ * reactive class) because the open/close animation needs the clamp gone for
163
+ * the exact frame it swaps to a max-height transition — line-clamp itself
164
+ * can't be animated, and a deferred reactive update would race the freeze
165
+ * frame. Kept in the markup's initial class so the scoped rule isn't pruned.
166
+ */
167
+ .clamp-2 {
168
+ display: -webkit-box;
169
+ -webkit-box-orient: vertical;
170
+ -webkit-line-clamp: 2;
171
+ line-clamp: 2;
172
+ overflow: hidden;
173
+ }
174
+ </style>
@@ -0,0 +1,194 @@
1
+ <script lang="ts">
2
+ let {
3
+ label,
4
+ value
5
+ }: {
6
+ readonly label: string;
7
+ readonly value: number | null;
8
+ } = $props();
9
+
10
+ const normalized = $derived(value === null ? 0 : Math.max(0, Math.min(100, value)));
11
+ const displayValue = $derived(`${normalized}%`);
12
+ const dash = $derived(normalized * 0.87965);
13
+ const toneClass = $derived(
14
+ normalized >= 80
15
+ ? 'is-high'
16
+ : normalized >= 45
17
+ ? 'is-mid'
18
+ : 'is-low'
19
+ );
20
+ </script>
21
+
22
+ <div class="score-meter {toneClass}">
23
+ <div class="score-meter__dial">
24
+ <svg viewBox="0 0 36 36" class="score-meter__svg" aria-hidden="true">
25
+ <circle cx="18" cy="18" r="16" fill="none" class="score-meter__outer" stroke-width="1.2" />
26
+ <circle cx="18" cy="18" r="14" fill="none" class="score-meter__track" stroke-width="2.4" />
27
+ <circle
28
+ cx="18"
29
+ cy="18"
30
+ r="14"
31
+ fill="none"
32
+ class="score-meter__arc-glow"
33
+ stroke-width="8"
34
+ stroke-linecap={normalized > 0 ? 'round' : 'butt'}
35
+ stroke-dasharray={`${dash} 87.965`}
36
+ />
37
+ <circle
38
+ cx="18"
39
+ cy="18"
40
+ r="14"
41
+ fill="none"
42
+ class="score-meter__arc"
43
+ stroke-width="2.4"
44
+ stroke-linecap={normalized > 0 ? 'round' : 'butt'}
45
+ stroke-dasharray={`${dash} 87.965`}
46
+ />
47
+ </svg>
48
+ <span class="score-meter__readout">
49
+ {displayValue}
50
+ </span>
51
+ </div>
52
+ <span class="score-meter__label">{label}</span>
53
+ </div>
54
+
55
+ <style>
56
+ .score-meter {
57
+ --accent: #94a3b8;
58
+ --accent-soft: rgba(148, 163, 184, 0.24);
59
+ display: flex;
60
+ min-width: 76px;
61
+ flex-direction: column;
62
+ align-items: center;
63
+ gap: 8px;
64
+ }
65
+
66
+ .score-meter.is-high {
67
+ --accent: #34d399;
68
+ --accent-soft: rgba(52, 211, 153, 0.34);
69
+ }
70
+
71
+ .score-meter.is-mid {
72
+ --accent: #fb923c;
73
+ --accent-soft: rgba(251, 146, 60, 0.28);
74
+ }
75
+
76
+ .score-meter.is-low {
77
+ --accent: #f43f5e;
78
+ --accent-soft: rgba(244, 63, 94, 0.24);
79
+ }
80
+
81
+ .score-meter.is-empty {
82
+ --accent: #94a3b8;
83
+ --accent-soft: rgba(148, 163, 184, 0.2);
84
+ }
85
+
86
+ .score-meter__dial {
87
+ position: relative;
88
+ width: 68px;
89
+ height: 68px;
90
+ border: 1px solid rgba(15, 23, 42, 0.92);
91
+ border-radius: 999px;
92
+ background:
93
+ radial-gradient(circle at 34% 26%, rgba(255, 255, 255, 0.18), transparent 22%),
94
+ radial-gradient(circle at 50% 66%, rgba(255, 255, 255, 0.08), transparent 43%),
95
+ linear-gradient(180deg, rgba(71, 85, 105, 0.96), rgba(15, 23, 42, 0.98));
96
+ box-shadow:
97
+ 0 14px 22px rgba(0, 0, 0, 0.34),
98
+ 0 1px 0 rgba(255, 255, 255, 0.18) inset,
99
+ 0 -3px 0 rgba(2, 6, 23, 0.9) inset,
100
+ 0 0 0 6px rgba(15, 23, 42, 0.66) inset;
101
+ }
102
+
103
+ .score-meter__dial::before {
104
+ content: "";
105
+ position: absolute;
106
+ inset: 5px;
107
+ border-radius: inherit;
108
+ background:
109
+ linear-gradient(180deg, rgba(255, 255, 255, 0.12), transparent 42%),
110
+ linear-gradient(180deg, rgba(2, 6, 23, 0.2), rgba(2, 6, 23, 0.72));
111
+ box-shadow:
112
+ 0 1px 1px rgba(255, 255, 255, 0.08) inset,
113
+ 0 10px 18px rgba(0, 0, 0, 0.4) inset;
114
+ }
115
+
116
+ .score-meter__dial::after {
117
+ content: "";
118
+ position: absolute;
119
+ inset: 6px;
120
+ border-radius: inherit;
121
+ background: radial-gradient(circle, var(--accent-soft), transparent 58%);
122
+ opacity: 0.28;
123
+ filter: blur(7px);
124
+ }
125
+
126
+ .score-meter__svg {
127
+ position: absolute;
128
+ inset: 6px;
129
+ z-index: 1;
130
+ overflow: visible;
131
+ /* The lit well sits high (top-left light + thick bottom rim), so geometric-center
132
+ content reads as low — lift the arc + readout ~1px into the optical center. */
133
+ transform: translateY(-1px) rotate(-90deg);
134
+ }
135
+
136
+ .score-meter__outer {
137
+ stroke: rgba(226, 232, 240, 0.16);
138
+ }
139
+
140
+ .score-meter__track {
141
+ stroke: rgba(30, 41, 59, 0.72);
142
+ filter:
143
+ drop-shadow(0 1px 0 rgba(255, 255, 255, 0.08))
144
+ drop-shadow(0 -1px 0 rgba(0, 0, 0, 0.28))
145
+ drop-shadow(0 0 5px rgba(148, 163, 184, 0.12));
146
+ }
147
+
148
+ .score-meter.is-empty .score-meter__track {
149
+ stroke: rgba(71, 85, 105, 0.72);
150
+ filter:
151
+ drop-shadow(0 1px 0 rgba(255, 255, 255, 0.08))
152
+ drop-shadow(0 -1px 0 rgba(0, 0, 0, 0.2))
153
+ drop-shadow(0 0 7px rgba(148, 163, 184, 0.16));
154
+ }
155
+
156
+ .score-meter__arc-glow {
157
+ stroke: var(--accent);
158
+ opacity: 0.16;
159
+ filter: blur(2.8px);
160
+ }
161
+
162
+ .score-meter__arc {
163
+ stroke: var(--accent);
164
+ opacity: 0.68;
165
+ filter:
166
+ drop-shadow(0 1px 0 rgba(255, 255, 255, 0.07))
167
+ drop-shadow(0 0 7px var(--accent-soft));
168
+ }
169
+
170
+ .score-meter__readout {
171
+ position: absolute;
172
+ inset: 0;
173
+ z-index: 2;
174
+ display: grid;
175
+ place-items: center;
176
+ /* match the arc's optical lift and kill inherited line-height drift */
177
+ transform: translateY(-1px);
178
+ line-height: 1;
179
+ color: white;
180
+ font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", monospace;
181
+ font-size: 13px;
182
+ font-weight: 800;
183
+ font-variant-numeric: tabular-nums;
184
+ text-shadow: 0 1px 2px rgba(0, 0, 0, 0.75);
185
+ }
186
+
187
+ .score-meter__label {
188
+ color: rgb(148, 163, 184);
189
+ font-size: 11px;
190
+ font-weight: 800;
191
+ letter-spacing: 0;
192
+ text-transform: uppercase;
193
+ }
194
+ </style>
@@ -0,0 +1,39 @@
1
+ import type { Container } from '$shared/infrastructure/container';
2
+ import type { SyncEvent } from '$lib/client/sync/syncEvents';
3
+ import type { Tag } from '$shared/domain/Tags';
4
+ import type { TagColor } from '$shared/domain/TagPalette';
5
+
6
+ /**
7
+ * Driven ports for the builder view (hexagonal architecture). Each interface is
8
+ * one responsibility the view needs from its host; `BuilderHost` composes them.
9
+ *
10
+ * These are pure abstractions — type-only imports, no concrete singletons — so
11
+ * the view's store depends on *these*, never on the app's infrastructure
12
+ * directly (dependency inversion). Concrete implementations ("adapters") live
13
+ * under `infrastructure/adapters`, and the composition root wires them in.
14
+ */
15
+
16
+ /** Hands the view the resolved DI container (repositories + use-cases). */
17
+ export interface BuilderDataGateway {
18
+ getContainer(): Promise<Container>;
19
+ }
20
+
21
+ /** Tag colors and cross-entity tag rename. */
22
+ export interface TagPaletteGateway {
23
+ refresh(): Promise<void>;
24
+ registerTypes(types: readonly string[]): void;
25
+ colorForTag(tag: Tag): TagColor | null;
26
+ renameTag(from: Tag, to: Tag): Promise<void>;
27
+ }
28
+
29
+ /** Live "projects/features changed" notifications. */
30
+ export interface SyncGateway {
31
+ subscribe(handler: (event: SyncEvent) => void): () => void;
32
+ }
33
+
34
+ /** The composed set of host services the builder view depends on. */
35
+ export interface BuilderHost {
36
+ readonly data: BuilderDataGateway;
37
+ readonly tags: TagPaletteGateway;
38
+ readonly sync: SyncGateway;
39
+ }