@powerhousedao/contributor-billing 0.1.40 → 0.1.42

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 (307) hide show
  1. package/dist/document-models/document-models.d.ts.map +1 -1
  2. package/dist/document-models/document-models.js +2 -0
  3. package/dist/document-models/index.d.ts +1 -0
  4. package/dist/document-models/index.d.ts.map +1 -1
  5. package/dist/document-models/index.js +1 -0
  6. package/dist/document-models/resource-template/actions.d.ts +32 -0
  7. package/dist/document-models/resource-template/actions.d.ts.map +1 -0
  8. package/dist/document-models/resource-template/actions.js +12 -0
  9. package/dist/document-models/resource-template/gen/actions.d.ts +14 -0
  10. package/dist/document-models/resource-template/gen/actions.d.ts.map +1 -0
  11. package/dist/document-models/resource-template/gen/actions.js +6 -0
  12. package/dist/document-models/resource-template/gen/audience-management/actions.d.ts +12 -0
  13. package/dist/document-models/resource-template/gen/audience-management/actions.d.ts.map +1 -0
  14. package/dist/document-models/resource-template/gen/audience-management/actions.js +1 -0
  15. package/dist/document-models/resource-template/gen/audience-management/creators.d.ts +5 -0
  16. package/dist/document-models/resource-template/gen/audience-management/creators.d.ts.map +1 -0
  17. package/dist/document-models/resource-template/gen/audience-management/creators.js +4 -0
  18. package/dist/document-models/resource-template/gen/audience-management/error.d.ts +21 -0
  19. package/dist/document-models/resource-template/gen/audience-management/error.d.ts.map +1 -0
  20. package/dist/document-models/resource-template/gen/audience-management/error.js +20 -0
  21. package/dist/document-models/resource-template/gen/audience-management/operations.d.ts +8 -0
  22. package/dist/document-models/resource-template/gen/audience-management/operations.d.ts.map +1 -0
  23. package/dist/document-models/resource-template/gen/audience-management/operations.js +3 -0
  24. package/dist/document-models/resource-template/gen/creators.d.ts +13 -0
  25. package/dist/document-models/resource-template/gen/creators.d.ts.map +1 -0
  26. package/dist/document-models/resource-template/gen/creators.js +12 -0
  27. package/dist/document-models/resource-template/gen/document-model.d.ts +3 -0
  28. package/dist/document-models/resource-template/gen/document-model.d.ts.map +1 -0
  29. package/dist/document-models/resource-template/gen/document-model.js +410 -0
  30. package/dist/document-models/resource-template/gen/document-schema.d.ts +408 -0
  31. package/dist/document-models/resource-template/gen/document-schema.d.ts.map +1 -0
  32. package/dist/document-models/resource-template/gen/document-schema.js +33 -0
  33. package/dist/document-models/resource-template/gen/document-type.d.ts +2 -0
  34. package/dist/document-models/resource-template/gen/document-type.d.ts.map +1 -0
  35. package/dist/document-models/resource-template/gen/document-type.js +1 -0
  36. package/dist/document-models/resource-template/gen/facet-targeting/actions.d.ts +20 -0
  37. package/dist/document-models/resource-template/gen/facet-targeting/actions.d.ts.map +1 -0
  38. package/dist/document-models/resource-template/gen/facet-targeting/actions.js +1 -0
  39. package/dist/document-models/resource-template/gen/facet-targeting/creators.d.ts +7 -0
  40. package/dist/document-models/resource-template/gen/facet-targeting/creators.d.ts.map +1 -0
  41. package/dist/document-models/resource-template/gen/facet-targeting/creators.js +6 -0
  42. package/dist/document-models/resource-template/gen/facet-targeting/error.d.ts +28 -0
  43. package/dist/document-models/resource-template/gen/facet-targeting/error.d.ts.map +1 -0
  44. package/dist/document-models/resource-template/gen/facet-targeting/error.js +29 -0
  45. package/dist/document-models/resource-template/gen/facet-targeting/operations.d.ts +10 -0
  46. package/dist/document-models/resource-template/gen/facet-targeting/operations.d.ts.map +1 -0
  47. package/dist/document-models/resource-template/gen/facet-targeting/operations.js +3 -0
  48. package/dist/document-models/resource-template/gen/index.d.ts +17 -0
  49. package/dist/document-models/resource-template/gen/index.d.ts.map +1 -0
  50. package/dist/document-models/resource-template/gen/index.js +16 -0
  51. package/dist/document-models/resource-template/gen/option-group-management/actions.d.ts +16 -0
  52. package/dist/document-models/resource-template/gen/option-group-management/actions.d.ts.map +1 -0
  53. package/dist/document-models/resource-template/gen/option-group-management/actions.js +1 -0
  54. package/dist/document-models/resource-template/gen/option-group-management/creators.d.ts +6 -0
  55. package/dist/document-models/resource-template/gen/option-group-management/creators.d.ts.map +1 -0
  56. package/dist/document-models/resource-template/gen/option-group-management/creators.js +5 -0
  57. package/dist/document-models/resource-template/gen/option-group-management/error.d.ts +28 -0
  58. package/dist/document-models/resource-template/gen/option-group-management/error.d.ts.map +1 -0
  59. package/dist/document-models/resource-template/gen/option-group-management/error.js +29 -0
  60. package/dist/document-models/resource-template/gen/option-group-management/operations.d.ts +9 -0
  61. package/dist/document-models/resource-template/gen/option-group-management/operations.d.ts.map +1 -0
  62. package/dist/document-models/resource-template/gen/option-group-management/operations.js +3 -0
  63. package/dist/document-models/resource-template/gen/ph-factories.d.ts +23 -0
  64. package/dist/document-models/resource-template/gen/ph-factories.d.ts.map +1 -0
  65. package/dist/document-models/resource-template/gen/ph-factories.js +61 -0
  66. package/dist/document-models/resource-template/gen/reducer.d.ts +3 -0
  67. package/dist/document-models/resource-template/gen/reducer.d.ts.map +1 -0
  68. package/dist/document-models/resource-template/gen/reducer.js +98 -0
  69. package/dist/document-models/resource-template/gen/schema/index.d.ts +3 -0
  70. package/dist/document-models/resource-template/gen/schema/index.d.ts.map +1 -0
  71. package/dist/document-models/resource-template/gen/schema/index.js +2 -0
  72. package/dist/document-models/resource-template/gen/schema/types.d.ts +305 -0
  73. package/dist/document-models/resource-template/gen/schema/types.d.ts.map +1 -0
  74. package/dist/document-models/resource-template/gen/schema/types.js +1 -0
  75. package/dist/document-models/resource-template/gen/schema/zod.d.ts +37 -0
  76. package/dist/document-models/resource-template/gen/schema/zod.d.ts.map +1 -0
  77. package/dist/document-models/resource-template/gen/schema/zod.js +236 -0
  78. package/dist/document-models/resource-template/gen/service-category-management/actions.d.ts +12 -0
  79. package/dist/document-models/resource-template/gen/service-category-management/actions.d.ts.map +1 -0
  80. package/dist/document-models/resource-template/gen/service-category-management/actions.js +1 -0
  81. package/dist/document-models/resource-template/gen/service-category-management/creators.d.ts +5 -0
  82. package/dist/document-models/resource-template/gen/service-category-management/creators.d.ts.map +1 -0
  83. package/dist/document-models/resource-template/gen/service-category-management/creators.js +4 -0
  84. package/dist/document-models/resource-template/gen/service-category-management/error.d.ts +2 -0
  85. package/dist/document-models/resource-template/gen/service-category-management/error.d.ts.map +1 -0
  86. package/dist/document-models/resource-template/gen/service-category-management/error.js +1 -0
  87. package/dist/document-models/resource-template/gen/service-category-management/operations.d.ts +8 -0
  88. package/dist/document-models/resource-template/gen/service-category-management/operations.d.ts.map +1 -0
  89. package/dist/document-models/resource-template/gen/service-category-management/operations.js +3 -0
  90. package/dist/document-models/resource-template/gen/service-management/actions.d.ts +24 -0
  91. package/dist/document-models/resource-template/gen/service-management/actions.d.ts.map +1 -0
  92. package/dist/document-models/resource-template/gen/service-management/actions.js +1 -0
  93. package/dist/document-models/resource-template/gen/service-management/creators.d.ts +8 -0
  94. package/dist/document-models/resource-template/gen/service-management/creators.d.ts.map +1 -0
  95. package/dist/document-models/resource-template/gen/service-management/creators.js +7 -0
  96. package/dist/document-models/resource-template/gen/service-management/error.d.ts +52 -0
  97. package/dist/document-models/resource-template/gen/service-management/error.d.ts.map +1 -0
  98. package/dist/document-models/resource-template/gen/service-management/error.js +61 -0
  99. package/dist/document-models/resource-template/gen/service-management/operations.d.ts +11 -0
  100. package/dist/document-models/resource-template/gen/service-management/operations.d.ts.map +1 -0
  101. package/dist/document-models/resource-template/gen/service-management/operations.js +3 -0
  102. package/dist/document-models/resource-template/gen/template-management/actions.d.ts +20 -0
  103. package/dist/document-models/resource-template/gen/template-management/actions.d.ts.map +1 -0
  104. package/dist/document-models/resource-template/gen/template-management/actions.js +1 -0
  105. package/dist/document-models/resource-template/gen/template-management/creators.d.ts +7 -0
  106. package/dist/document-models/resource-template/gen/template-management/creators.d.ts.map +1 -0
  107. package/dist/document-models/resource-template/gen/template-management/creators.js +6 -0
  108. package/dist/document-models/resource-template/gen/template-management/error.d.ts +2 -0
  109. package/dist/document-models/resource-template/gen/template-management/error.d.ts.map +1 -0
  110. package/dist/document-models/resource-template/gen/template-management/error.js +1 -0
  111. package/dist/document-models/resource-template/gen/template-management/operations.d.ts +10 -0
  112. package/dist/document-models/resource-template/gen/template-management/operations.d.ts.map +1 -0
  113. package/dist/document-models/resource-template/gen/template-management/operations.js +3 -0
  114. package/dist/document-models/resource-template/gen/types.d.ts +12 -0
  115. package/dist/document-models/resource-template/gen/types.d.ts.map +1 -0
  116. package/dist/document-models/resource-template/gen/types.js +1 -0
  117. package/dist/document-models/resource-template/gen/utils.d.ts +15 -0
  118. package/dist/document-models/resource-template/gen/utils.d.ts.map +1 -0
  119. package/dist/document-models/resource-template/gen/utils.js +65 -0
  120. package/dist/document-models/resource-template/hooks.d.ts +11 -0
  121. package/dist/document-models/resource-template/hooks.d.ts.map +1 -0
  122. package/dist/document-models/resource-template/hooks.js +26 -0
  123. package/dist/document-models/resource-template/index.d.ts +10 -0
  124. package/dist/document-models/resource-template/index.d.ts.map +1 -0
  125. package/dist/document-models/resource-template/index.js +9 -0
  126. package/dist/document-models/resource-template/module.d.ts +5 -0
  127. package/dist/document-models/resource-template/module.d.ts.map +1 -0
  128. package/dist/document-models/resource-template/module.js +10 -0
  129. package/dist/document-models/resource-template/reducers/audience-management.d.ts +3 -0
  130. package/dist/document-models/resource-template/reducers/audience-management.d.ts.map +1 -0
  131. package/dist/document-models/resource-template/reducers/audience-management.js +17 -0
  132. package/dist/document-models/resource-template/reducers/facet-preset-management.d.ts +59 -0
  133. package/dist/document-models/resource-template/reducers/facet-preset-management.d.ts.map +1 -0
  134. package/dist/document-models/resource-template/reducers/facet-preset-management.js +52 -0
  135. package/dist/document-models/resource-template/reducers/facet-targeting.d.ts +3 -0
  136. package/dist/document-models/resource-template/reducers/facet-targeting.d.ts.map +1 -0
  137. package/dist/document-models/resource-template/reducers/facet-targeting.js +47 -0
  138. package/dist/document-models/resource-template/reducers/option-group-management.d.ts +3 -0
  139. package/dist/document-models/resource-template/reducers/option-group-management.d.ts.map +1 -0
  140. package/dist/document-models/resource-template/reducers/option-group-management.js +44 -0
  141. package/dist/document-models/resource-template/reducers/service-category-management.d.ts +3 -0
  142. package/dist/document-models/resource-template/reducers/service-category-management.d.ts.map +1 -0
  143. package/dist/document-models/resource-template/reducers/service-category-management.js +10 -0
  144. package/dist/document-models/resource-template/reducers/service-management.d.ts +3 -0
  145. package/dist/document-models/resource-template/reducers/service-management.d.ts.map +1 -0
  146. package/dist/document-models/resource-template/reducers/service-management.js +71 -0
  147. package/dist/document-models/resource-template/reducers/template-management.d.ts +3 -0
  148. package/dist/document-models/resource-template/reducers/template-management.d.ts.map +1 -0
  149. package/dist/document-models/resource-template/reducers/template-management.js +32 -0
  150. package/dist/document-models/resource-template/src/index.d.ts +2 -0
  151. package/dist/document-models/resource-template/src/index.d.ts.map +1 -0
  152. package/dist/document-models/resource-template/src/index.js +1 -0
  153. package/dist/document-models/resource-template/src/reducers/audience-management.d.ts +3 -0
  154. package/dist/document-models/resource-template/src/reducers/audience-management.d.ts.map +1 -0
  155. package/dist/document-models/resource-template/src/reducers/audience-management.js +17 -0
  156. package/dist/document-models/resource-template/src/reducers/facet-targeting.d.ts +3 -0
  157. package/dist/document-models/resource-template/src/reducers/facet-targeting.d.ts.map +1 -0
  158. package/dist/document-models/resource-template/src/reducers/facet-targeting.js +46 -0
  159. package/dist/document-models/resource-template/src/reducers/option-group-management.d.ts +3 -0
  160. package/dist/document-models/resource-template/src/reducers/option-group-management.d.ts.map +1 -0
  161. package/dist/document-models/resource-template/src/reducers/option-group-management.js +42 -0
  162. package/dist/document-models/resource-template/src/reducers/service-category-management.d.ts +3 -0
  163. package/dist/document-models/resource-template/src/reducers/service-category-management.d.ts.map +1 -0
  164. package/dist/document-models/resource-template/src/reducers/service-category-management.js +10 -0
  165. package/dist/document-models/resource-template/src/reducers/service-management.d.ts +3 -0
  166. package/dist/document-models/resource-template/src/reducers/service-management.d.ts.map +1 -0
  167. package/dist/document-models/resource-template/src/reducers/service-management.js +68 -0
  168. package/dist/document-models/resource-template/src/reducers/template-management.d.ts +3 -0
  169. package/dist/document-models/resource-template/src/reducers/template-management.d.ts.map +1 -0
  170. package/dist/document-models/resource-template/src/reducers/template-management.js +32 -0
  171. package/dist/document-models/resource-template/src/tests/audience-management.test.d.ts +6 -0
  172. package/dist/document-models/resource-template/src/tests/audience-management.test.d.ts.map +1 -0
  173. package/dist/document-models/resource-template/src/tests/audience-management.test.js +29 -0
  174. package/dist/document-models/resource-template/src/tests/document-model.test.d.ts +10 -0
  175. package/dist/document-models/resource-template/src/tests/document-model.test.d.ts.map +1 -0
  176. package/dist/document-models/resource-template/src/tests/document-model.test.js +104 -0
  177. package/dist/document-models/resource-template/src/tests/facet-targeting.test.d.ts +6 -0
  178. package/dist/document-models/resource-template/src/tests/facet-targeting.test.d.ts.map +1 -0
  179. package/dist/document-models/resource-template/src/tests/facet-targeting.test.js +49 -0
  180. package/dist/document-models/resource-template/src/tests/option-group-management.test.d.ts +6 -0
  181. package/dist/document-models/resource-template/src/tests/option-group-management.test.d.ts.map +1 -0
  182. package/dist/document-models/resource-template/src/tests/option-group-management.test.js +39 -0
  183. package/dist/document-models/resource-template/src/tests/service-category-management.test.d.ts +6 -0
  184. package/dist/document-models/resource-template/src/tests/service-category-management.test.d.ts.map +1 -0
  185. package/dist/document-models/resource-template/src/tests/service-category-management.test.js +29 -0
  186. package/dist/document-models/resource-template/src/tests/service-management.test.d.ts +6 -0
  187. package/dist/document-models/resource-template/src/tests/service-management.test.d.ts.map +1 -0
  188. package/dist/document-models/resource-template/src/tests/service-management.test.js +59 -0
  189. package/dist/document-models/resource-template/src/tests/template-management.test.d.ts +6 -0
  190. package/dist/document-models/resource-template/src/tests/template-management.test.d.ts.map +1 -0
  191. package/dist/document-models/resource-template/src/tests/template-management.test.js +49 -0
  192. package/dist/document-models/resource-template/src/utils.d.ts +2 -0
  193. package/dist/document-models/resource-template/src/utils.d.ts.map +1 -0
  194. package/dist/document-models/resource-template/src/utils.js +1 -0
  195. package/dist/document-models/resource-template/utils.d.ts +14 -0
  196. package/dist/document-models/resource-template/utils.d.ts.map +1 -0
  197. package/dist/document-models/resource-template/utils.js +7 -0
  198. package/dist/document-models/service-offering/actions.d.ts +2 -0
  199. package/dist/document-models/service-offering/actions.d.ts.map +1 -1
  200. package/dist/document-models/service-offering/gen/document-model.d.ts.map +1 -1
  201. package/dist/document-models/service-offering/gen/document-model.js +51 -6
  202. package/dist/document-models/service-offering/gen/document-schema.d.ts +35 -16
  203. package/dist/document-models/service-offering/gen/document-schema.d.ts.map +1 -1
  204. package/dist/document-models/service-offering/gen/offering-management/actions.d.ts +10 -2
  205. package/dist/document-models/service-offering/gen/offering-management/actions.d.ts.map +1 -1
  206. package/dist/document-models/service-offering/gen/offering-management/creators.d.ts +4 -2
  207. package/dist/document-models/service-offering/gen/offering-management/creators.d.ts.map +1 -1
  208. package/dist/document-models/service-offering/gen/offering-management/creators.js +3 -1
  209. package/dist/document-models/service-offering/gen/offering-management/error.d.ts +20 -1
  210. package/dist/document-models/service-offering/gen/offering-management/error.d.ts.map +1 -1
  211. package/dist/document-models/service-offering/gen/offering-management/error.js +25 -0
  212. package/dist/document-models/service-offering/gen/offering-management/operations.d.ts +3 -1
  213. package/dist/document-models/service-offering/gen/offering-management/operations.d.ts.map +1 -1
  214. package/dist/document-models/service-offering/gen/ph-factories.d.ts.map +1 -1
  215. package/dist/document-models/service-offering/gen/ph-factories.js +1 -0
  216. package/dist/document-models/service-offering/gen/reducer.d.ts.map +1 -1
  217. package/dist/document-models/service-offering/gen/reducer.js +9 -1
  218. package/dist/document-models/service-offering/gen/schema/types.d.ts +24 -11
  219. package/dist/document-models/service-offering/gen/schema/types.d.ts.map +1 -1
  220. package/dist/document-models/service-offering/gen/schema/zod.d.ts +3 -1
  221. package/dist/document-models/service-offering/gen/schema/zod.d.ts.map +1 -1
  222. package/dist/document-models/service-offering/gen/schema/zod.js +17 -0
  223. package/dist/document-models/service-offering/gen/utils.d.ts.map +1 -1
  224. package/dist/document-models/service-offering/gen/utils.js +1 -0
  225. package/dist/document-models/service-offering/src/reducers/offering-management.d.ts.map +1 -1
  226. package/dist/document-models/service-offering/src/reducers/offering-management.js +22 -4
  227. package/dist/document-models/service-offering/src/reducers/service-management.d.ts.map +1 -1
  228. package/dist/document-models/service-offering/src/reducers/service-management.js +5 -0
  229. package/dist/document-models/service-offering/src/tests/offering-management.test.js +1 -81
  230. package/dist/document-models/service-offering/src/tests/tier-management.test.d.ts +4 -0
  231. package/dist/document-models/service-offering/src/tests/tier-management.test.d.ts.map +1 -1
  232. package/dist/document-models/service-offering/src/tests/tier-management.test.js +109 -1
  233. package/dist/editors/builder-team-admin/components/DriveExplorer.d.ts.map +1 -1
  234. package/dist/editors/builder-team-admin/components/DriveExplorer.js +4 -0
  235. package/dist/editors/builder-team-admin/components/FolderTree.d.ts +1 -1
  236. package/dist/editors/builder-team-admin/components/FolderTree.d.ts.map +1 -1
  237. package/dist/editors/builder-team-admin/components/FolderTree.js +134 -9
  238. package/dist/editors/builder-team-admin/components/ResourcesServices.d.ts +8 -0
  239. package/dist/editors/builder-team-admin/components/ResourcesServices.d.ts.map +1 -0
  240. package/dist/editors/builder-team-admin/components/ResourcesServices.js +76 -0
  241. package/dist/editors/builder-team-admin/hooks/useResourcesServicesAutoPlacement.d.ts +27 -0
  242. package/dist/editors/builder-team-admin/hooks/useResourcesServicesAutoPlacement.d.ts.map +1 -0
  243. package/dist/editors/builder-team-admin/hooks/useResourcesServicesAutoPlacement.js +123 -0
  244. package/dist/editors/index.d.ts +1 -0
  245. package/dist/editors/index.d.ts.map +1 -1
  246. package/dist/editors/index.js +1 -0
  247. package/dist/editors/resource-template-editor/components/FacetTargeting.d.ts +9 -0
  248. package/dist/editors/resource-template-editor/components/FacetTargeting.d.ts.map +1 -0
  249. package/dist/editors/resource-template-editor/components/FacetTargeting.js +958 -0
  250. package/dist/editors/resource-template-editor/components/TemplateInfo.d.ts +9 -0
  251. package/dist/editors/resource-template-editor/components/TemplateInfo.d.ts.map +1 -0
  252. package/dist/editors/resource-template-editor/components/TemplateInfo.js +1288 -0
  253. package/dist/editors/resource-template-editor/editor.d.ts +2 -0
  254. package/dist/editors/resource-template-editor/editor.d.ts.map +1 -0
  255. package/dist/editors/resource-template-editor/editor.js +149 -0
  256. package/dist/editors/resource-template-editor/module.d.ts +4 -0
  257. package/dist/editors/resource-template-editor/module.d.ts.map +1 -0
  258. package/dist/editors/resource-template-editor/module.js +10 -0
  259. package/dist/editors/service-offering-editor/components/EditName.js +1 -1
  260. package/dist/editors/service-offering-editor/components/OfferingInfo.d.ts +1 -1
  261. package/dist/editors/service-offering-editor/components/OfferingInfo.d.ts.map +1 -1
  262. package/dist/editors/service-offering-editor/components/OfferingProgress.d.ts +10 -0
  263. package/dist/editors/service-offering-editor/components/OfferingProgress.d.ts.map +1 -0
  264. package/dist/editors/service-offering-editor/components/OfferingProgress.js +240 -0
  265. package/dist/editors/service-offering-editor/components/ResourceTemplateSelector.d.ts +9 -0
  266. package/dist/editors/service-offering-editor/components/ResourceTemplateSelector.d.ts.map +1 -0
  267. package/dist/editors/service-offering-editor/components/ResourceTemplateSelector.js +1157 -0
  268. package/dist/editors/service-offering-editor/components/ScopeAndFacets.d.ts +1 -1
  269. package/dist/editors/service-offering-editor/components/ScopeAndFacets.d.ts.map +1 -1
  270. package/dist/editors/service-offering-editor/components/ServiceCatalog.d.ts +1 -1
  271. package/dist/editors/service-offering-editor/components/ServiceCatalog.d.ts.map +1 -1
  272. package/dist/editors/service-offering-editor/components/ServiceCatalog.js +318 -1
  273. package/dist/editors/service-offering-editor/components/ServicesList.d.ts +1 -1
  274. package/dist/editors/service-offering-editor/components/ServicesList.d.ts.map +1 -1
  275. package/dist/editors/service-offering-editor/components/TabNavigation.d.ts.map +1 -1
  276. package/dist/editors/service-offering-editor/components/TabNavigation.js +17 -3
  277. package/dist/editors/service-offering-editor/components/TheMatrix.d.ts +1 -1
  278. package/dist/editors/service-offering-editor/components/TheMatrix.d.ts.map +1 -1
  279. package/dist/editors/service-offering-editor/components/TheMatrix.js +823 -29
  280. package/dist/editors/service-offering-editor/components/TierDefinition.d.ts +1 -1
  281. package/dist/editors/service-offering-editor/components/TierDefinition.d.ts.map +1 -1
  282. package/dist/editors/service-offering-editor/components/TierDefinition.js +406 -4
  283. package/dist/editors/service-offering-editor/components/TiersList.d.ts +1 -1
  284. package/dist/editors/service-offering-editor/components/TiersList.d.ts.map +1 -1
  285. package/dist/editors/service-offering-editor/editor.d.ts.map +1 -1
  286. package/dist/editors/service-offering-editor/editor.js +4 -4
  287. package/dist/index.d.ts +1 -1
  288. package/dist/index.d.ts.map +1 -1
  289. package/dist/powerhouse.manifest.json +18 -0
  290. package/dist/style.css +25 -0
  291. package/dist/subgraphs/index.d.ts +1 -0
  292. package/dist/subgraphs/index.d.ts.map +1 -1
  293. package/dist/subgraphs/index.js +1 -0
  294. package/dist/subgraphs/resource-template/index.d.ts +11 -0
  295. package/dist/subgraphs/resource-template/index.d.ts.map +1 -0
  296. package/dist/subgraphs/resource-template/index.js +11 -0
  297. package/dist/subgraphs/resource-template/resolvers.d.ts +3 -0
  298. package/dist/subgraphs/resource-template/resolvers.d.ts.map +1 -0
  299. package/dist/subgraphs/resource-template/resolvers.js +312 -0
  300. package/dist/subgraphs/resource-template/schema.d.ts +3 -0
  301. package/dist/subgraphs/resource-template/schema.d.ts.map +1 -0
  302. package/dist/subgraphs/resource-template/schema.js +262 -0
  303. package/dist/subgraphs/service-offering/resolvers.d.ts.map +1 -1
  304. package/dist/subgraphs/service-offering/resolvers.js +24 -0
  305. package/dist/subgraphs/service-offering/schema.d.ts.map +1 -1
  306. package/dist/subgraphs/service-offering/schema.js +21 -0
  307. package/package.json +1 -1
@@ -1,7 +1,7 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
2
  import { useState, useMemo, useEffect, useRef, useCallback } from "react";
3
3
  import { generateId } from "document-model/core";
4
- import { addServiceLevel, updateServiceLevel, addUsageLimit, updateUsageLimit, removeUsageLimit, addService, } from "../../../document-models/service-offering/gen/creators.js";
4
+ import { addServiceLevel, updateServiceLevel, addUsageLimit, updateUsageLimit, removeUsageLimit, addService, updateService, } from "../../../document-models/service-offering/gen/creators.js";
5
5
  const SERVICE_LEVELS = [
6
6
  {
7
7
  value: "INCLUDED",
@@ -437,6 +437,319 @@ const matrixStyles = `
437
437
  color: var(--so-slate-700);
438
438
  }
439
439
 
440
+ /* Premium Only Badge - Exclusivity Signal (Toggle Button) */
441
+ .matrix__premium-badge {
442
+ display: inline-flex;
443
+ align-items: center;
444
+ gap: 0.25rem;
445
+ padding: 0.125rem 0.5rem;
446
+ margin-left: 0.5rem;
447
+ font-size: 0.5625rem;
448
+ font-weight: 700;
449
+ text-transform: uppercase;
450
+ letter-spacing: 0.04em;
451
+ border-radius: 100px;
452
+ cursor: pointer;
453
+ transition: all var(--so-transition-fast);
454
+ font-family: var(--so-font-sans);
455
+ }
456
+
457
+ .matrix__premium-badge--active {
458
+ color: var(--so-amber-700);
459
+ background: linear-gradient(135deg, var(--so-amber-100) 0%, var(--so-amber-50) 100%);
460
+ border: 1px solid var(--so-amber-200);
461
+ }
462
+
463
+ .matrix__premium-badge--active:hover {
464
+ background: linear-gradient(135deg, var(--so-amber-200) 0%, var(--so-amber-100) 100%);
465
+ border-color: var(--so-amber-300);
466
+ }
467
+
468
+ .matrix__premium-badge--inactive {
469
+ color: var(--so-slate-400);
470
+ background: var(--so-slate-50);
471
+ border: 1px dashed var(--so-slate-200);
472
+ opacity: 0.6;
473
+ }
474
+
475
+ .matrix__premium-badge--inactive:hover {
476
+ opacity: 1;
477
+ color: var(--so-amber-600);
478
+ background: var(--so-amber-50);
479
+ border: 1px dashed var(--so-amber-300);
480
+ }
481
+
482
+ .matrix__premium-badge--active svg {
483
+ width: 0.625rem;
484
+ height: 0.625rem;
485
+ fill: var(--so-amber-500);
486
+ stroke: var(--so-amber-600);
487
+ }
488
+
489
+ .matrix__premium-badge--inactive svg {
490
+ width: 0.625rem;
491
+ height: 0.625rem;
492
+ fill: none;
493
+ stroke: currentColor;
494
+ }
495
+
496
+ /* Incomplete Services Warning */
497
+ .matrix__incomplete-warning {
498
+ display: flex;
499
+ align-items: flex-start;
500
+ gap: 0.875rem;
501
+ padding: 1rem 1.25rem;
502
+ margin-bottom: 1rem;
503
+ background: var(--so-amber-50);
504
+ border: 1px solid var(--so-amber-200);
505
+ border-radius: var(--so-radius-md);
506
+ animation: matrix-warning-pulse 2s ease-in-out infinite;
507
+ }
508
+
509
+ @keyframes matrix-warning-pulse {
510
+ 0%, 100% { box-shadow: 0 0 0 0 rgba(245, 158, 11, 0); }
511
+ 50% { box-shadow: 0 0 0 4px rgba(245, 158, 11, 0.1); }
512
+ }
513
+
514
+ .matrix__incomplete-icon {
515
+ flex-shrink: 0;
516
+ width: 1.5rem;
517
+ height: 1.5rem;
518
+ color: var(--so-amber-600);
519
+ }
520
+
521
+ .matrix__incomplete-icon svg {
522
+ width: 100%;
523
+ height: 100%;
524
+ }
525
+
526
+ .matrix__incomplete-content {
527
+ display: flex;
528
+ flex-direction: column;
529
+ gap: 0.25rem;
530
+ }
531
+
532
+ .matrix__incomplete-title {
533
+ font-size: 0.875rem;
534
+ font-weight: 600;
535
+ color: var(--so-amber-800);
536
+ }
537
+
538
+ .matrix__incomplete-text {
539
+ font-size: 0.8125rem;
540
+ color: var(--so-amber-700);
541
+ line-height: 1.5;
542
+ }
543
+
544
+ .matrix__incomplete-text strong {
545
+ font-weight: 600;
546
+ color: var(--so-amber-900);
547
+ }
548
+
549
+ /* Bulk Actions Toolbar */
550
+ .matrix__bulk-actions {
551
+ margin-bottom: 1rem;
552
+ }
553
+
554
+ .matrix__bulk-toggle {
555
+ display: flex;
556
+ align-items: center;
557
+ gap: 0.5rem;
558
+ padding: 0.625rem 1rem;
559
+ font-family: var(--so-font-sans);
560
+ font-size: 0.8125rem;
561
+ font-weight: 600;
562
+ color: var(--so-slate-600);
563
+ background: var(--so-slate-100);
564
+ border: 1px solid var(--so-slate-200);
565
+ border-radius: var(--so-radius-md);
566
+ cursor: pointer;
567
+ transition: all var(--so-transition-fast);
568
+ }
569
+
570
+ .matrix__bulk-toggle:hover {
571
+ background: var(--so-slate-200);
572
+ color: var(--so-slate-700);
573
+ }
574
+
575
+ .matrix__bulk-toggle svg:first-child {
576
+ width: 1rem;
577
+ height: 1rem;
578
+ }
579
+
580
+ .matrix__bulk-toggle-arrow {
581
+ width: 0.875rem;
582
+ height: 0.875rem;
583
+ margin-left: auto;
584
+ transition: transform var(--so-transition-fast);
585
+ }
586
+
587
+ .matrix__bulk-toggle-arrow--open {
588
+ transform: rotate(180deg);
589
+ }
590
+
591
+ .matrix__bulk-panel {
592
+ margin-top: 0.75rem;
593
+ padding: 1rem;
594
+ background: var(--so-slate-50);
595
+ border: 1px solid var(--so-slate-200);
596
+ border-radius: var(--so-radius-md);
597
+ display: flex;
598
+ flex-direction: column;
599
+ gap: 1rem;
600
+ animation: so-scale-in var(--so-transition-fast) ease-out;
601
+ }
602
+
603
+ .matrix__bulk-section {
604
+ display: flex;
605
+ flex-direction: column;
606
+ gap: 0.5rem;
607
+ }
608
+
609
+ .matrix__bulk-label {
610
+ font-size: 0.6875rem;
611
+ font-weight: 600;
612
+ text-transform: uppercase;
613
+ letter-spacing: 0.05em;
614
+ color: var(--so-slate-500);
615
+ }
616
+
617
+ .matrix__bulk-buttons,
618
+ .matrix__bulk-copy {
619
+ display: flex;
620
+ flex-wrap: wrap;
621
+ gap: 0.5rem;
622
+ }
623
+
624
+ .matrix__bulk-btn {
625
+ display: flex;
626
+ align-items: center;
627
+ gap: 0.375rem;
628
+ padding: 0.5rem 0.875rem;
629
+ font-family: var(--so-font-sans);
630
+ font-size: 0.75rem;
631
+ font-weight: 500;
632
+ border-radius: var(--so-radius-sm);
633
+ border: 1px solid;
634
+ cursor: pointer;
635
+ transition: all var(--so-transition-fast);
636
+ }
637
+
638
+ .matrix__bulk-btn svg {
639
+ width: 0.875rem;
640
+ height: 0.875rem;
641
+ }
642
+
643
+ .matrix__bulk-btn--include {
644
+ background: var(--so-emerald-50);
645
+ border-color: var(--so-emerald-200);
646
+ color: var(--so-emerald-700);
647
+ }
648
+
649
+ .matrix__bulk-btn--include:hover {
650
+ background: var(--so-emerald-100);
651
+ border-color: var(--so-emerald-300);
652
+ }
653
+
654
+ .matrix__bulk-btn--clear {
655
+ background: var(--so-rose-50);
656
+ border-color: var(--so-rose-200);
657
+ color: var(--so-rose-700);
658
+ }
659
+
660
+ .matrix__bulk-btn--clear:hover {
661
+ background: var(--so-rose-100);
662
+ border-color: var(--so-rose-300);
663
+ }
664
+
665
+ .matrix__bulk-btn--copy {
666
+ background: var(--so-sky-50);
667
+ border-color: var(--so-sky-200);
668
+ color: var(--so-sky-700);
669
+ }
670
+
671
+ .matrix__bulk-btn--copy:hover {
672
+ background: var(--so-sky-100);
673
+ border-color: var(--so-sky-300);
674
+ }
675
+
676
+ /* Pattern Presets Section */
677
+ .matrix__bulk-patterns {
678
+ border-top: 1px dashed var(--so-slate-200);
679
+ padding-top: 1rem;
680
+ margin-top: 0.5rem;
681
+ }
682
+
683
+ .matrix__bulk-label-icon {
684
+ width: 1rem;
685
+ height: 1rem;
686
+ vertical-align: middle;
687
+ margin-right: 0.25rem;
688
+ }
689
+
690
+ .matrix__pattern-grid {
691
+ display: grid;
692
+ grid-template-columns: repeat(auto-fill, minmax(160px, 1fr));
693
+ gap: 0.75rem;
694
+ margin-top: 0.5rem;
695
+ }
696
+
697
+ .matrix__pattern-btn {
698
+ display: flex;
699
+ flex-direction: column;
700
+ align-items: center;
701
+ gap: 0.25rem;
702
+ padding: 0.875rem 0.75rem;
703
+ background: linear-gradient(135deg, var(--so-white) 0%, var(--so-slate-50) 100%);
704
+ border: 1px solid var(--so-slate-200);
705
+ border-radius: var(--so-radius-md);
706
+ cursor: pointer;
707
+ transition: all var(--so-transition-fast);
708
+ text-align: center;
709
+ }
710
+
711
+ .matrix__pattern-btn:hover {
712
+ transform: translateY(-2px);
713
+ box-shadow: var(--so-shadow-md);
714
+ border-color: var(--so-violet-300);
715
+ background: linear-gradient(135deg, var(--so-violet-50) 0%, var(--so-white) 100%);
716
+ }
717
+
718
+ .matrix__pattern-btn:active {
719
+ transform: translateY(0);
720
+ }
721
+
722
+ .matrix__pattern-icon {
723
+ font-size: 1.5rem;
724
+ line-height: 1;
725
+ }
726
+
727
+ .matrix__pattern-name {
728
+ font-size: 0.8125rem;
729
+ font-weight: 600;
730
+ color: var(--so-slate-700);
731
+ }
732
+
733
+ .matrix__pattern-desc {
734
+ font-size: 0.6875rem;
735
+ color: var(--so-slate-500);
736
+ line-height: 1.3;
737
+ }
738
+
739
+ .matrix__pattern-btn--simple {
740
+ padding: 0.625rem 0.75rem;
741
+ flex-direction: row;
742
+ gap: 0.5rem;
743
+ }
744
+
745
+ .matrix__pattern-btn--simple .matrix__pattern-icon {
746
+ font-size: 1rem;
747
+ }
748
+
749
+ .matrix__pattern-btn--simple .matrix__pattern-name {
750
+ font-size: 0.75rem;
751
+ }
752
+
440
753
  .matrix__level-cell {
441
754
  padding: 0.625rem 1rem;
442
755
  text-align: center;
@@ -462,9 +775,50 @@ const matrixStyles = `
462
775
  font-weight: 500;
463
776
  }
464
777
 
778
+ /* Loss Aversion Styling for NOT_INCLUDED */
779
+ .matrix__level-cell--not-included {
780
+ position: relative;
781
+ background: repeating-linear-gradient(
782
+ 135deg,
783
+ transparent,
784
+ transparent 8px,
785
+ rgba(148, 163, 184, 0.08) 8px,
786
+ rgba(148, 163, 184, 0.08) 16px
787
+ );
788
+ }
789
+
790
+ .matrix__level-cell--not-included:hover .matrix__upgrade-hint {
791
+ opacity: 1;
792
+ transform: translateY(0);
793
+ }
794
+
795
+ .matrix__upgrade-hint {
796
+ position: absolute;
797
+ bottom: 2px;
798
+ left: 50%;
799
+ transform: translateX(-50%) translateY(4px);
800
+ font-size: 0.5625rem;
801
+ font-weight: 500;
802
+ color: var(--so-violet-600);
803
+ white-space: nowrap;
804
+ opacity: 0;
805
+ transition: all 0.15s ease-out;
806
+ pointer-events: none;
807
+ }
808
+
809
+ .matrix__level-value--not-included {
810
+ opacity: 0.6;
811
+ }
812
+
465
813
  /* Metric Row */
466
814
  .matrix__metric-row {
467
815
  background: inherit;
816
+ cursor: pointer;
817
+ transition: var(--so-transition-fast);
818
+ }
819
+
820
+ .matrix__metric-row:hover {
821
+ background: rgba(124, 58, 237, 0.08);
468
822
  }
469
823
 
470
824
  .matrix__metric-cell {
@@ -476,6 +830,12 @@ const matrixStyles = `
476
830
  z-index: 10;
477
831
  }
478
832
 
833
+ .matrix__metric-name-wrapper {
834
+ display: flex;
835
+ align-items: center;
836
+ gap: 0.5rem;
837
+ }
838
+
479
839
  .matrix__metric-name {
480
840
  font-family: var(--so-font-sans);
481
841
  font-size: 0.6875rem;
@@ -483,6 +843,47 @@ const matrixStyles = `
483
843
  color: var(--so-slate-500);
484
844
  }
485
845
 
846
+ .matrix__metric-actions {
847
+ display: flex;
848
+ gap: 0.25rem;
849
+ opacity: 0;
850
+ transition: var(--so-transition-fast);
851
+ }
852
+
853
+ .matrix__metric-row:hover .matrix__metric-actions {
854
+ opacity: 1;
855
+ }
856
+
857
+ .matrix__metric-btn {
858
+ padding: 0.125rem;
859
+ background: transparent;
860
+ border: none;
861
+ color: var(--so-slate-400);
862
+ cursor: pointer;
863
+ border-radius: var(--so-radius-sm);
864
+ transition: var(--so-transition-fast);
865
+ display: flex;
866
+ align-items: center;
867
+ justify-content: center;
868
+ }
869
+
870
+ .matrix__metric-btn:hover {
871
+ background: var(--so-slate-200);
872
+ }
873
+
874
+ .matrix__metric-btn--edit:hover {
875
+ color: var(--so-violet-600);
876
+ }
877
+
878
+ .matrix__metric-btn--remove:hover {
879
+ color: var(--so-rose-600);
880
+ }
881
+
882
+ .matrix__metric-btn-icon {
883
+ width: 0.75rem;
884
+ height: 0.75rem;
885
+ }
886
+
486
887
  .matrix__metric-value-cell {
487
888
  padding: 0.375rem 1rem;
488
889
  text-align: center;
@@ -494,6 +895,38 @@ const matrixStyles = `
494
895
  color: var(--so-slate-500);
495
896
  }
496
897
 
898
+ /* Add Metric Button on Service Row */
899
+ .matrix__service-cell-wrapper {
900
+ display: flex;
901
+ align-items: center;
902
+ justify-content: space-between;
903
+ gap: 0.5rem;
904
+ }
905
+
906
+ .matrix__add-metric-btn {
907
+ opacity: 0.6;
908
+ font-family: var(--so-font-sans);
909
+ font-size: 0.6875rem;
910
+ font-weight: 500;
911
+ color: var(--so-violet-600);
912
+ background: transparent;
913
+ border: none;
914
+ cursor: pointer;
915
+ padding: 0.125rem 0.375rem;
916
+ border-radius: var(--so-radius-sm);
917
+ transition: var(--so-transition-fast);
918
+ white-space: nowrap;
919
+ }
920
+
921
+ .matrix__service-row:hover .matrix__add-metric-btn {
922
+ opacity: 1;
923
+ }
924
+
925
+ .matrix__add-metric-btn:hover {
926
+ background: var(--so-violet-100);
927
+ color: var(--so-violet-700);
928
+ }
929
+
497
930
  /* Add Service Row */
498
931
  .matrix__add-service-row td {
499
932
  padding: 0.5rem 1rem;
@@ -1268,6 +1701,13 @@ export function TheMatrix({ document, dispatch, groupSetupFees = {}, }) {
1268
1701
  TEAM_STRUCTURE: "remote-team",
1269
1702
  ANONYMITY: "high-anonymity",
1270
1703
  });
1704
+ // Metric editing modal state
1705
+ const [metricModal, setMetricModal] = useState(null);
1706
+ const [metricName, setMetricName] = useState("");
1707
+ const [metricLimits, setMetricLimits] = useState({});
1708
+ const [metricEnabledTiers, setMetricEnabledTiers] = useState(new Set());
1709
+ // Bulk actions state
1710
+ const [showBulkActions, setShowBulkActions] = useState(false);
1271
1711
  const getServiceGroup = (service) => {
1272
1712
  // Services now have optionGroupId directly on them
1273
1713
  return service.optionGroupId || null;
@@ -1314,6 +1754,16 @@ export function TheMatrix({ document, dispatch, groupSetupFees = {}, }) {
1314
1754
  });
1315
1755
  return Array.from(metricsSet);
1316
1756
  };
1757
+ // Incomplete services detection - services not assigned to any tier
1758
+ const incompleteServices = useMemo(() => {
1759
+ if (tiers.length === 0)
1760
+ return [];
1761
+ return services.filter((service) => {
1762
+ // Check if service is included in at least one tier
1763
+ const isIncludedAnywhere = tiers.some((tier) => tier.serviceLevels.some((sl) => sl.serviceId === service.id && sl.level === "INCLUDED"));
1764
+ return !isIncludedAnywhere;
1765
+ });
1766
+ }, [services, tiers]);
1317
1767
  const getUsageLimitForMetric = (serviceId, metric, tier) => {
1318
1768
  return tier.usageLimits.find((ul) => ul.serviceId === serviceId && ul.metric === metric);
1319
1769
  };
@@ -1349,6 +1799,150 @@ export function TheMatrix({ document, dispatch, groupSetupFees = {}, }) {
1349
1799
  return next;
1350
1800
  });
1351
1801
  };
1802
+ // Bulk action handlers
1803
+ const handleBulkIncludeAllInTier = (tierId) => {
1804
+ const now = new Date().toISOString();
1805
+ const tier = tiers.find((t) => t.id === tierId);
1806
+ if (!tier)
1807
+ return;
1808
+ services.forEach((service) => {
1809
+ const existingLevel = tier.serviceLevels.find((sl) => sl.serviceId === service.id);
1810
+ if (!existingLevel) {
1811
+ dispatch(addServiceLevel({
1812
+ tierId,
1813
+ serviceLevelId: generateId(),
1814
+ serviceId: service.id,
1815
+ level: "INCLUDED",
1816
+ optionGroupId: service.optionGroupId || undefined,
1817
+ lastModified: now,
1818
+ }));
1819
+ }
1820
+ else if (existingLevel.level !== "INCLUDED") {
1821
+ dispatch(updateServiceLevel({
1822
+ tierId,
1823
+ serviceLevelId: existingLevel.id,
1824
+ level: "INCLUDED",
1825
+ lastModified: now,
1826
+ }));
1827
+ }
1828
+ });
1829
+ };
1830
+ const handleBulkClearTier = (tierId) => {
1831
+ const now = new Date().toISOString();
1832
+ const tier = tiers.find((t) => t.id === tierId);
1833
+ if (!tier)
1834
+ return;
1835
+ tier.serviceLevels.forEach((sl) => {
1836
+ dispatch(updateServiceLevel({
1837
+ tierId,
1838
+ serviceLevelId: sl.id,
1839
+ level: "NOT_INCLUDED",
1840
+ lastModified: now,
1841
+ }));
1842
+ });
1843
+ };
1844
+ const handleBulkCopyFromTier = (sourceTierId, targetTierId) => {
1845
+ const now = new Date().toISOString();
1846
+ const sourceTier = tiers.find((t) => t.id === sourceTierId);
1847
+ const targetTier = tiers.find((t) => t.id === targetTierId);
1848
+ if (!sourceTier || !targetTier)
1849
+ return;
1850
+ services.forEach((service) => {
1851
+ const sourceLevel = sourceTier.serviceLevels.find((sl) => sl.serviceId === service.id);
1852
+ const targetLevel = targetTier.serviceLevels.find((sl) => sl.serviceId === service.id);
1853
+ const newLevel = sourceLevel?.level || "NOT_INCLUDED";
1854
+ if (!targetLevel) {
1855
+ dispatch(addServiceLevel({
1856
+ tierId: targetTierId,
1857
+ serviceLevelId: generateId(),
1858
+ serviceId: service.id,
1859
+ level: newLevel,
1860
+ optionGroupId: service.optionGroupId || undefined,
1861
+ lastModified: now,
1862
+ }));
1863
+ }
1864
+ else if (targetLevel.level !== newLevel) {
1865
+ dispatch(updateServiceLevel({
1866
+ tierId: targetTierId,
1867
+ serviceLevelId: targetLevel.id,
1868
+ level: newLevel,
1869
+ lastModified: now,
1870
+ }));
1871
+ }
1872
+ });
1873
+ };
1874
+ // Common Pattern Presets - apply marketing psychology patterns across all tiers
1875
+ const handleApplyPattern = (patternId) => {
1876
+ const now = new Date().toISOString();
1877
+ const tierCount = tiers.length;
1878
+ if (tierCount === 0)
1879
+ return;
1880
+ // Pattern definitions
1881
+ const patterns = {
1882
+ // Good-Better-Best: Progressive inclusion (50% → 75% → 100%)
1883
+ "good-better-best": (serviceIdx, tierIdx, totalServices, totalTiers) => {
1884
+ const servicePosition = serviceIdx / totalServices;
1885
+ const tierPosition = tierIdx / (totalTiers - 1 || 1);
1886
+ // Lower tiers get fewer services
1887
+ const threshold = 0.5 + tierPosition * 0.5;
1888
+ return servicePosition < threshold ? "INCLUDED" : "NOT_INCLUDED";
1889
+ },
1890
+ // Premium Only: Top services only in top tier
1891
+ "premium-only": (serviceIdx, tierIdx, totalServices, totalTiers) => {
1892
+ const isTopTier = tierIdx === totalTiers - 1;
1893
+ const isPremiumService = serviceIdx < Math.ceil(totalServices * 0.3);
1894
+ if (isPremiumService) {
1895
+ return isTopTier ? "INCLUDED" : "NOT_INCLUDED";
1896
+ }
1897
+ return "INCLUDED";
1898
+ },
1899
+ // Core + Upgrades: Core included everywhere, extras are optional
1900
+ "core-upgrades": (serviceIdx, tierIdx, totalServices) => {
1901
+ const isCoreService = serviceIdx < Math.ceil(totalServices * 0.5);
1902
+ if (isCoreService) {
1903
+ return "INCLUDED";
1904
+ }
1905
+ return "OPTIONAL";
1906
+ },
1907
+ // Ascending: Each tier adds more services
1908
+ ascending: (serviceIdx, tierIdx, totalServices, totalTiers) => {
1909
+ const servicesPerTier = Math.ceil(totalServices / totalTiers);
1910
+ const includedUpTo = (tierIdx + 1) * servicesPerTier;
1911
+ return serviceIdx < includedUpTo ? "INCLUDED" : "NOT_INCLUDED";
1912
+ },
1913
+ // All Included: Everything included in all tiers
1914
+ "all-included": () => "INCLUDED",
1915
+ // All Optional: Everything optional in all tiers
1916
+ "all-optional": () => "OPTIONAL",
1917
+ };
1918
+ const pattern = patterns[patternId];
1919
+ if (!pattern)
1920
+ return;
1921
+ services.forEach((service, serviceIdx) => {
1922
+ tiers.forEach((tier, tierIdx) => {
1923
+ const newLevel = pattern(serviceIdx, tierIdx, services.length, tierCount);
1924
+ const existingLevel = tier.serviceLevels.find((sl) => sl.serviceId === service.id);
1925
+ if (!existingLevel) {
1926
+ dispatch(addServiceLevel({
1927
+ tierId: tier.id,
1928
+ serviceLevelId: generateId(),
1929
+ serviceId: service.id,
1930
+ level: newLevel,
1931
+ optionGroupId: service.optionGroupId || undefined,
1932
+ lastModified: now,
1933
+ }));
1934
+ }
1935
+ else if (existingLevel.level !== newLevel) {
1936
+ dispatch(updateServiceLevel({
1937
+ tierId: tier.id,
1938
+ serviceLevelId: existingLevel.id,
1939
+ level: newLevel,
1940
+ lastModified: now,
1941
+ }));
1942
+ }
1943
+ });
1944
+ });
1945
+ };
1352
1946
  const handleAddService = () => {
1353
1947
  if (!addServiceModal || !newServiceName.trim())
1354
1948
  return;
@@ -1389,6 +1983,114 @@ export function TheMatrix({ document, dispatch, groupSetupFees = {}, }) {
1389
1983
  setNewServiceDescription("");
1390
1984
  setNewServiceSelectedTiers(new Set());
1391
1985
  };
1986
+ // Metric modal handlers
1987
+ const handleAddMetric = (serviceId) => {
1988
+ setMetricModal({ serviceId, metric: null });
1989
+ setMetricName("");
1990
+ // Initialize limits for all tiers to empty string
1991
+ const initialLimits = {};
1992
+ // For new metrics, enable all tiers by default
1993
+ const allTierIds = new Set();
1994
+ tiers.forEach((tier) => {
1995
+ initialLimits[tier.id] = "";
1996
+ allTierIds.add(tier.id);
1997
+ });
1998
+ setMetricLimits(initialLimits);
1999
+ setMetricEnabledTiers(allTierIds);
2000
+ };
2001
+ const handleEditMetric = (serviceId, metric) => {
2002
+ setMetricModal({ serviceId, metric });
2003
+ setMetricName(metric);
2004
+ // Initialize limits with existing values and track which tiers have this metric
2005
+ const existingLimits = {};
2006
+ const enabledTiers = new Set();
2007
+ tiers.forEach((tier) => {
2008
+ const usageLimit = tier.usageLimits.find((ul) => ul.serviceId === serviceId && ul.metric === metric);
2009
+ // Load value from either limit (numeric) or notes (string)
2010
+ existingLimits[tier.id] =
2011
+ usageLimit?.limit?.toString() || usageLimit?.notes || "";
2012
+ if (usageLimit) {
2013
+ enabledTiers.add(tier.id);
2014
+ }
2015
+ });
2016
+ setMetricLimits(existingLimits);
2017
+ setMetricEnabledTiers(enabledTiers);
2018
+ };
2019
+ const handleRemoveMetric = (serviceId, metric) => {
2020
+ // Remove this metric from all tiers
2021
+ tiers.forEach((tier) => {
2022
+ const usageLimit = tier.usageLimits.find((ul) => ul.serviceId === serviceId && ul.metric === metric);
2023
+ if (usageLimit) {
2024
+ dispatch(removeUsageLimit({
2025
+ tierId: tier.id,
2026
+ limitId: usageLimit.id,
2027
+ lastModified: new Date().toISOString(),
2028
+ }));
2029
+ }
2030
+ });
2031
+ };
2032
+ const handleTogglePremiumExclusive = (serviceId) => {
2033
+ const service = services.find((s) => s.id === serviceId);
2034
+ if (!service)
2035
+ return;
2036
+ dispatch(updateService({
2037
+ id: serviceId,
2038
+ isPremiumExclusive: !service.isPremiumExclusive,
2039
+ lastModified: new Date().toISOString(),
2040
+ }));
2041
+ };
2042
+ const handleSaveMetric = () => {
2043
+ if (!metricModal || !metricName.trim())
2044
+ return;
2045
+ const { serviceId, metric: originalMetric } = metricModal;
2046
+ const now = new Date().toISOString();
2047
+ tiers.forEach((tier) => {
2048
+ const isEnabled = metricEnabledTiers.has(tier.id);
2049
+ const limitValue = metricLimits[tier.id];
2050
+ const existingLimit = originalMetric
2051
+ ? tier.usageLimits.find((ul) => ul.serviceId === serviceId && ul.metric === originalMetric)
2052
+ : null;
2053
+ // Check if value is numeric or string
2054
+ const parsedLimit = limitValue ? parseInt(limitValue, 10) : null;
2055
+ const isNumeric = parsedLimit !== null && !isNaN(parsedLimit);
2056
+ if (existingLimit && !isEnabled) {
2057
+ // Remove limit - tier was disabled
2058
+ dispatch(removeUsageLimit({
2059
+ tierId: tier.id,
2060
+ limitId: existingLimit.id,
2061
+ lastModified: now,
2062
+ }));
2063
+ }
2064
+ else if (existingLimit && isEnabled) {
2065
+ // Update existing limit - use limit for numeric values, notes for strings
2066
+ dispatch(updateUsageLimit({
2067
+ tierId: tier.id,
2068
+ limitId: existingLimit.id,
2069
+ metric: metricName.trim(),
2070
+ limit: isNumeric ? parsedLimit : null,
2071
+ notes: !isNumeric && limitValue ? limitValue.trim() : null,
2072
+ lastModified: now,
2073
+ }));
2074
+ }
2075
+ else if (!existingLimit && isEnabled) {
2076
+ // Add new limit - use limit for numeric values, notes for strings
2077
+ dispatch(addUsageLimit({
2078
+ tierId: tier.id,
2079
+ limitId: generateId(),
2080
+ serviceId,
2081
+ metric: metricName.trim(),
2082
+ limit: isNumeric ? parsedLimit : null,
2083
+ notes: !isNumeric && limitValue ? limitValue.trim() : null,
2084
+ resetPeriod: "MONTHLY",
2085
+ lastModified: now,
2086
+ }));
2087
+ }
2088
+ });
2089
+ setMetricModal(null);
2090
+ setMetricName("");
2091
+ setMetricLimits({});
2092
+ setMetricEnabledTiers(new Set());
2093
+ };
1392
2094
  const getLevelDisplay = (serviceLevel) => {
1393
2095
  if (!serviceLevel)
1394
2096
  return { label: "—", color: "var(--so-slate-300)" };
@@ -1420,27 +2122,33 @@ export function TheMatrix({ document, dispatch, groupSetupFees = {}, }) {
1420
2122
  : ""}`, children: option.label }, option.id))) })) : (_jsx("select", { value: selectedFacets[key] || "", onChange: (e) => setSelectedFacets((prev) => ({
1421
2123
  ...prev,
1422
2124
  [key]: e.target.value,
1423
- })), className: "matrix__facet-select", children: category.options.map((option) => (_jsx("option", { value: option.id, children: option.label }, option.id))) }))] }, key))) }), selectedFacets.ANONYMITY === "highest-anonymity" && (_jsx("div", { className: "matrix__facet-notice", children: _jsxs("p", { className: "matrix__facet-notice-text", children: [_jsx("strong", { children: "Highest Anonymity:" }), " Additional setup services may be required for enhanced privacy configurations."] }) }))] }), _jsx("div", { className: "matrix__table-wrap", children: _jsxs("table", { className: "matrix__table", children: [_jsx("thead", { children: _jsxs("tr", { children: [_jsx("th", { className: "matrix__corner-cell" }), tiers.map((tier, idx) => (_jsx("th", { onClick: () => setSelectedTierIdx(idx), className: `matrix__tier-header ${idx === selectedTierIdx
2125
+ })), className: "matrix__facet-select", children: category.options.map((option) => (_jsx("option", { value: option.id, children: option.label }, option.id))) }))] }, key))) }), selectedFacets.ANONYMITY === "highest-anonymity" && (_jsx("div", { className: "matrix__facet-notice", children: _jsxs("p", { className: "matrix__facet-notice-text", children: [_jsx("strong", { children: "Highest Anonymity:" }), " Additional setup services may be required for enhanced privacy configurations."] }) }))] }), services.length > 0 && tiers.length > 0 && (_jsxs("div", { className: "matrix__bulk-actions", children: [_jsxs("button", { type: "button", onClick: () => setShowBulkActions(!showBulkActions), className: "matrix__bulk-toggle", children: [_jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: _jsx("path", { d: "M4 6h16M4 12h16M4 18h7" }) }), "Bulk Actions", _jsx("svg", { className: `matrix__bulk-toggle-arrow ${showBulkActions ? "matrix__bulk-toggle-arrow--open" : ""}`, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: _jsx("path", { d: "M19 9l-7 7-7-7" }) })] }), showBulkActions && (_jsxs("div", { className: "matrix__bulk-panel", children: [_jsxs("div", { className: "matrix__bulk-section", children: [_jsx("span", { className: "matrix__bulk-label", children: "Include all services in:" }), _jsx("div", { className: "matrix__bulk-buttons", children: tiers.map((tier) => (_jsxs("button", { type: "button", onClick: () => handleBulkIncludeAllInTier(tier.id), className: "matrix__bulk-btn matrix__bulk-btn--include", children: [_jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: _jsx("path", { d: "M5 12l5 5L20 7" }) }), tier.name] }, tier.id))) })] }), _jsxs("div", { className: "matrix__bulk-section", children: [_jsx("span", { className: "matrix__bulk-label", children: "Clear all from:" }), _jsx("div", { className: "matrix__bulk-buttons", children: tiers.map((tier) => (_jsxs("button", { type: "button", onClick: () => handleBulkClearTier(tier.id), className: "matrix__bulk-btn matrix__bulk-btn--clear", children: [_jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: _jsx("path", { d: "M6 18L18 6M6 6l12 12" }) }), tier.name] }, tier.id))) })] }), tiers.length >= 2 && (_jsxs("div", { className: "matrix__bulk-section", children: [_jsx("span", { className: "matrix__bulk-label", children: "Copy configuration:" }), _jsx("div", { className: "matrix__bulk-copy", children: tiers.map((sourceTier, idx) => tiers
2126
+ .filter((_, i) => i !== idx)
2127
+ .map((targetTier) => (_jsxs("button", { type: "button", onClick: () => handleBulkCopyFromTier(sourceTier.id, targetTier.id), className: "matrix__bulk-btn matrix__bulk-btn--copy", children: [sourceTier.name, " \u2192 ", targetTier.name] }, `${sourceTier.id}-${targetTier.id}`)))) })] })), _jsxs("div", { className: "matrix__bulk-section matrix__bulk-patterns", children: [_jsxs("span", { className: "matrix__bulk-label", children: [_jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", className: "matrix__bulk-label-icon", children: _jsx("path", { d: "M13 10V3L4 14h7v7l9-11h-7z" }) }), "Apply Pattern Preset:"] }), _jsxs("div", { className: "matrix__pattern-grid", children: [_jsxs("button", { type: "button", onClick: () => handleApplyPattern("good-better-best"), className: "matrix__pattern-btn", title: "Progressive inclusion: Basic tier gets 50%, mid-tier 75%, top tier 100%", children: [_jsx("span", { className: "matrix__pattern-icon", children: "\uD83D\uDCC8" }), _jsx("span", { className: "matrix__pattern-name", children: "Good-Better-Best" }), _jsx("span", { className: "matrix__pattern-desc", children: "Progressive inclusion" })] }), _jsxs("button", { type: "button", onClick: () => handleApplyPattern("premium-only"), className: "matrix__pattern-btn", title: "Top 30% services exclusive to premium tier, rest included everywhere", children: [_jsx("span", { className: "matrix__pattern-icon", children: "\u2B50" }), _jsx("span", { className: "matrix__pattern-name", children: "Premium Exclusives" }), _jsx("span", { className: "matrix__pattern-desc", children: "Top services in top tier only" })] }), _jsxs("button", { type: "button", onClick: () => handleApplyPattern("core-upgrades"), className: "matrix__pattern-btn", title: "Core services included, extras as optional add-ons", children: [_jsx("span", { className: "matrix__pattern-icon", children: "\uD83C\uDFAF" }), _jsx("span", { className: "matrix__pattern-name", children: "Core + Add-ons" }), _jsx("span", { className: "matrix__pattern-desc", children: "Half included, half optional" })] }), _jsxs("button", { type: "button", onClick: () => handleApplyPattern("ascending"), className: "matrix__pattern-btn", title: "Each tier unlocks more services progressively", children: [_jsx("span", { className: "matrix__pattern-icon", children: "\uD83E\uDE9C" }), _jsx("span", { className: "matrix__pattern-name", children: "Ascending Tiers" }), _jsx("span", { className: "matrix__pattern-desc", children: "Each tier unlocks more" })] }), _jsxs("button", { type: "button", onClick: () => handleApplyPattern("all-included"), className: "matrix__pattern-btn matrix__pattern-btn--simple", title: "Everything included in all tiers", children: [_jsx("span", { className: "matrix__pattern-icon", children: "\u2713" }), _jsx("span", { className: "matrix__pattern-name", children: "All Included" })] }), _jsxs("button", { type: "button", onClick: () => handleApplyPattern("all-optional"), className: "matrix__pattern-btn matrix__pattern-btn--simple", title: "Everything optional in all tiers", children: [_jsx("span", { className: "matrix__pattern-icon", children: "\u25D0" }), _jsx("span", { className: "matrix__pattern-name", children: "All Optional" })] })] })] })] }))] })), incompleteServices.length > 0 && (_jsxs("div", { className: "matrix__incomplete-warning", children: [_jsx("div", { className: "matrix__incomplete-icon", children: _jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: _jsx("path", { d: "M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z" }) }) }), _jsxs("div", { className: "matrix__incomplete-content", children: [_jsxs("span", { className: "matrix__incomplete-title", children: [incompleteServices.length, " service", incompleteServices.length !== 1 ? "s" : "", " not configured"] }), _jsxs("span", { className: "matrix__incomplete-text", children: ["The following services are not included in any tier:", " ", _jsx("strong", { children: incompleteServices
2128
+ .slice(0, 3)
2129
+ .map((s) => s.title)
2130
+ .join(", ") }), incompleteServices.length > 3 &&
2131
+ ` and ${incompleteServices.length - 3} more`] })] })] })), _jsx("div", { className: "matrix__table-wrap", children: _jsxs("table", { className: "matrix__table", children: [_jsx("thead", { children: _jsxs("tr", { children: [_jsx("th", { className: "matrix__corner-cell" }), tiers.map((tier, idx) => (_jsx("th", { onClick: () => setSelectedTierIdx(idx), className: `matrix__tier-header ${idx === selectedTierIdx
1424
2132
  ? "matrix__tier-header--selected"
1425
2133
  : ""}`, children: _jsxs("div", { className: "matrix__tier-header-inner", children: [_jsx("div", { className: "matrix__tier-radio" }), _jsx("span", { className: "matrix__tier-name", children: tier.name }), _jsx("span", { className: "matrix__tier-price", children: tier.isCustomPricing
1426
2134
  ? "Custom"
1427
2135
  : `$${tier.pricing.amount}/mo` })] }) }, tier.id)))] }) }), _jsxs("tbody", { children: [_jsx("tr", { children: _jsx("td", { colSpan: tiers.length + 1, className: "matrix__section-header", children: "Service Catalog" }) }), (setupGroups.length > 0 ||
1428
- ungroupedSetupServices.length > 0) && (_jsx("tr", { children: _jsxs("td", { colSpan: tiers.length + 1, className: "matrix__category-header", children: [_jsx("span", { className: "matrix__category-icon", children: _jsxs("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "1.75", children: [_jsx("path", { d: "M19 21V5a2 2 0 0 0-2-2H7a2 2 0 0 0-2 2v16" }), _jsx("path", { d: "M9 21v-6h6v6" }), _jsx("path", { d: "M9 7h.01M9 11h.01M15 7h.01M15 11h.01" })] }) }), "Setup & Formation"] }) })), setupGroups.map((group) => (_jsx(ServiceGroupSection, { group: group, services: groupedServices.get(group.id) || [], tiers: tiers, isSetupFormation: true, isOptional: false, isEnabled: true, onToggle: () => { }, getServiceLevelForTier: getServiceLevelForTier, getUniqueMetricsForService: getUniqueMetricsForService, getUsageLimitForMetric: getUsageLimitForMetric, getLevelDisplay: getLevelDisplay, selectedCell: selectedCell, setSelectedCell: setSelectedCell, handleSetServiceLevel: handleSetServiceLevel, dispatch: dispatch, setupFee: groupSetupFees[group.id], onAddService: openAddServiceModal, selectedTierIdx: selectedTierIdx }, group.id))), ungroupedSetupServices.length > 0 && (_jsx(ServiceGroupSection, { group: {
2136
+ ungroupedSetupServices.length > 0) && (_jsx("tr", { children: _jsxs("td", { colSpan: tiers.length + 1, className: "matrix__category-header", children: [_jsx("span", { className: "matrix__category-icon", children: _jsxs("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "1.75", children: [_jsx("path", { d: "M19 21V5a2 2 0 0 0-2-2H7a2 2 0 0 0-2 2v16" }), _jsx("path", { d: "M9 21v-6h6v6" }), _jsx("path", { d: "M9 7h.01M9 11h.01M15 7h.01M15 11h.01" })] }) }), "Setup & Formation"] }) })), setupGroups.map((group) => (_jsx(ServiceGroupSection, { group: group, services: groupedServices.get(group.id) || [], tiers: tiers, isSetupFormation: true, isOptional: false, isEnabled: true, onToggle: () => { }, getServiceLevelForTier: getServiceLevelForTier, getUniqueMetricsForService: getUniqueMetricsForService, getUsageLimitForMetric: getUsageLimitForMetric, getLevelDisplay: getLevelDisplay, selectedCell: selectedCell, setSelectedCell: setSelectedCell, handleSetServiceLevel: handleSetServiceLevel, dispatch: dispatch, setupFee: groupSetupFees[group.id], onAddService: openAddServiceModal, selectedTierIdx: selectedTierIdx, onAddMetric: handleAddMetric, onEditMetric: handleEditMetric, onRemoveMetric: handleRemoveMetric, onTogglePremiumExclusive: handleTogglePremiumExclusive }, group.id))), ungroupedSetupServices.length > 0 && (_jsx(ServiceGroupSection, { group: {
1429
2137
  id: UNGROUPED_ID,
1430
2138
  name: "Setup & Formation",
1431
2139
  description: null,
1432
2140
  isAddOn: false,
1433
2141
  defaultSelected: true,
1434
- }, services: ungroupedSetupServices, tiers: tiers, isSetupFormation: true, isOptional: false, isEnabled: true, onToggle: () => { }, getServiceLevelForTier: getServiceLevelForTier, getUniqueMetricsForService: getUniqueMetricsForService, getUsageLimitForMetric: getUsageLimitForMetric, getLevelDisplay: getLevelDisplay, selectedCell: selectedCell, setSelectedCell: setSelectedCell, handleSetServiceLevel: handleSetServiceLevel, dispatch: dispatch, setupFee: groupSetupFees[UNGROUPED_ID], selectedTierIdx: selectedTierIdx }, "ungrouped-setup")), (regularGroups.length > 0 ||
1435
- ungroupedRegularServices.length > 0) && (_jsx("tr", { children: _jsxs("td", { colSpan: tiers.length + 1, className: "matrix__category-header", children: [_jsx("span", { className: "matrix__category-icon", children: _jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "1.75", children: _jsx("path", { d: "M12 2v4M12 18v4M4.93 4.93l2.83 2.83M16.24 16.24l2.83 2.83M2 12h4M18 12h4M4.93 19.07l2.83-2.83M16.24 7.76l2.83-2.83" }) }) }), "Recurring Services"] }) })), regularGroups.map((group) => (_jsx(ServiceGroupSection, { group: group, services: groupedServices.get(group.id) || [], tiers: tiers, isSetupFormation: false, isOptional: false, isEnabled: true, onToggle: () => { }, getServiceLevelForTier: getServiceLevelForTier, getUniqueMetricsForService: getUniqueMetricsForService, getUsageLimitForMetric: getUsageLimitForMetric, getLevelDisplay: getLevelDisplay, selectedCell: selectedCell, setSelectedCell: setSelectedCell, handleSetServiceLevel: handleSetServiceLevel, onAddService: openAddServiceModal, selectedTierIdx: selectedTierIdx, dispatch: dispatch }, group.id))), ungroupedRegularServices.length > 0 && (_jsx(ServiceGroupSection, { group: {
2142
+ }, services: ungroupedSetupServices, tiers: tiers, isSetupFormation: true, isOptional: false, isEnabled: true, onToggle: () => { }, getServiceLevelForTier: getServiceLevelForTier, getUniqueMetricsForService: getUniqueMetricsForService, getUsageLimitForMetric: getUsageLimitForMetric, getLevelDisplay: getLevelDisplay, selectedCell: selectedCell, setSelectedCell: setSelectedCell, handleSetServiceLevel: handleSetServiceLevel, dispatch: dispatch, setupFee: groupSetupFees[UNGROUPED_ID], selectedTierIdx: selectedTierIdx, onAddMetric: handleAddMetric, onEditMetric: handleEditMetric, onRemoveMetric: handleRemoveMetric, onTogglePremiumExclusive: handleTogglePremiumExclusive }, "ungrouped-setup")), (regularGroups.length > 0 ||
2143
+ ungroupedRegularServices.length > 0) && (_jsx("tr", { children: _jsxs("td", { colSpan: tiers.length + 1, className: "matrix__category-header", children: [_jsx("span", { className: "matrix__category-icon", children: _jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "1.75", children: _jsx("path", { d: "M12 2v4M12 18v4M4.93 4.93l2.83 2.83M16.24 16.24l2.83 2.83M2 12h4M18 12h4M4.93 19.07l2.83-2.83M16.24 7.76l2.83-2.83" }) }) }), "Recurring Services"] }) })), regularGroups.map((group) => (_jsx(ServiceGroupSection, { group: group, services: groupedServices.get(group.id) || [], tiers: tiers, isSetupFormation: false, isOptional: false, isEnabled: true, onToggle: () => { }, getServiceLevelForTier: getServiceLevelForTier, getUniqueMetricsForService: getUniqueMetricsForService, getUsageLimitForMetric: getUsageLimitForMetric, getLevelDisplay: getLevelDisplay, selectedCell: selectedCell, setSelectedCell: setSelectedCell, handleSetServiceLevel: handleSetServiceLevel, onAddService: openAddServiceModal, selectedTierIdx: selectedTierIdx, dispatch: dispatch, onAddMetric: handleAddMetric, onEditMetric: handleEditMetric, onRemoveMetric: handleRemoveMetric, onTogglePremiumExclusive: handleTogglePremiumExclusive }, group.id))), ungroupedRegularServices.length > 0 && (_jsx(ServiceGroupSection, { group: {
1436
2144
  id: UNGROUPED_ID,
1437
2145
  name: "Recurring Services",
1438
2146
  description: null,
1439
2147
  isAddOn: false,
1440
2148
  defaultSelected: true,
1441
- }, services: ungroupedRegularServices, tiers: tiers, isSetupFormation: false, isOptional: false, isEnabled: true, onToggle: () => { }, getServiceLevelForTier: getServiceLevelForTier, getUniqueMetricsForService: getUniqueMetricsForService, getUsageLimitForMetric: getUsageLimitForMetric, getLevelDisplay: getLevelDisplay, selectedCell: selectedCell, setSelectedCell: setSelectedCell, handleSetServiceLevel: handleSetServiceLevel, dispatch: dispatch, selectedTierIdx: selectedTierIdx }, "ungrouped-regular")), _jsxs("tr", { className: "matrix__total-row", children: [_jsx("td", { children: "SUBTOTAL" }), tiers.map((tier) => (_jsx("td", { style: { textAlign: "center" }, children: tier.isCustomPricing
2149
+ }, services: ungroupedRegularServices, tiers: tiers, isSetupFormation: false, isOptional: false, isEnabled: true, onToggle: () => { }, getServiceLevelForTier: getServiceLevelForTier, getUniqueMetricsForService: getUniqueMetricsForService, getUsageLimitForMetric: getUsageLimitForMetric, getLevelDisplay: getLevelDisplay, selectedCell: selectedCell, setSelectedCell: setSelectedCell, handleSetServiceLevel: handleSetServiceLevel, dispatch: dispatch, selectedTierIdx: selectedTierIdx, onAddMetric: handleAddMetric, onEditMetric: handleEditMetric, onRemoveMetric: handleRemoveMetric, onTogglePremiumExclusive: handleTogglePremiumExclusive }, "ungrouped-regular")), _jsxs("tr", { className: "matrix__total-row", children: [_jsx("td", { children: "SUBTOTAL" }), tiers.map((tier) => (_jsx("td", { style: { textAlign: "center" }, children: tier.isCustomPricing
1442
2150
  ? "Custom"
1443
- : `$${tier.pricing.amount}` }, tier.id)))] }), addonGroups.map((group) => (_jsx(ServiceGroupSection, { group: group, services: groupedServices.get(group.id) || [], tiers: tiers, isSetupFormation: false, isOptional: true, isEnabled: enabledOptionalGroups.has(group.id), onToggle: () => toggleOptionalGroup(group.id), getServiceLevelForTier: getServiceLevelForTier, getUniqueMetricsForService: getUniqueMetricsForService, getUsageLimitForMetric: getUsageLimitForMetric, getLevelDisplay: getLevelDisplay, selectedCell: selectedCell, setSelectedCell: setSelectedCell, handleSetServiceLevel: handleSetServiceLevel, dispatch: dispatch, onAddService: openAddServiceModal, selectedTierIdx: selectedTierIdx }, group.id))), _jsxs("tr", { className: "matrix__grand-total-row", children: [_jsx("td", { children: "Grand Total (Recurring)" }), tiers.map((tier, idx) => {
2151
+ : `$${tier.pricing.amount}` }, tier.id)))] }), addonGroups.map((group) => (_jsx(ServiceGroupSection, { group: group, services: groupedServices.get(group.id) || [], tiers: tiers, isSetupFormation: false, isOptional: true, isEnabled: enabledOptionalGroups.has(group.id), onToggle: () => toggleOptionalGroup(group.id), getServiceLevelForTier: getServiceLevelForTier, getUniqueMetricsForService: getUniqueMetricsForService, getUsageLimitForMetric: getUsageLimitForMetric, getLevelDisplay: getLevelDisplay, selectedCell: selectedCell, setSelectedCell: setSelectedCell, handleSetServiceLevel: handleSetServiceLevel, dispatch: dispatch, onAddService: openAddServiceModal, selectedTierIdx: selectedTierIdx, onAddMetric: handleAddMetric, onEditMetric: handleEditMetric, onRemoveMetric: handleRemoveMetric, onTogglePremiumExclusive: handleTogglePremiumExclusive }, group.id))), _jsxs("tr", { className: "matrix__grand-total-row", children: [_jsx("td", { children: "Grand Total (Recurring)" }), tiers.map((tier, idx) => {
1444
2152
  const tierPrice = tier.pricing.amount || 0;
1445
2153
  const grandTotal = tierPrice;
1446
2154
  return (_jsx("td", { className: idx === selectedTierIdx
@@ -1468,9 +2176,67 @@ export function TheMatrix({ document, dispatch, groupSetupFees = {}, }) {
1468
2176
  setNewServiceName("");
1469
2177
  setNewServiceDescription("");
1470
2178
  setNewServiceSelectedTiers(new Set());
1471
- }, className: "matrix__modal-btn matrix__modal-btn--cancel", children: "Cancel" }), _jsx("button", { onClick: handleAddService, disabled: !newServiceName.trim() || newServiceSelectedTiers.size === 0, className: "matrix__modal-btn matrix__modal-btn--primary", children: "Add Service" })] })] }) }))] })] }));
2179
+ }, className: "matrix__modal-btn matrix__modal-btn--cancel", children: "Cancel" }), _jsx("button", { onClick: handleAddService, disabled: !newServiceName.trim() || newServiceSelectedTiers.size === 0, className: "matrix__modal-btn matrix__modal-btn--primary", children: "Add Service" })] })] }) })), metricModal && (_jsx("div", { className: "matrix__modal-overlay", children: _jsxs("div", { className: "matrix__modal matrix__modal--wide", children: [_jsx("h3", { className: "matrix__modal-title", children: metricModal.metric ? "Edit Metric" : "Add Metric" }), _jsxs("div", { className: "matrix__modal-field", children: [_jsx("label", { className: "matrix__modal-label", children: "Metric Name" }), _jsx("input", { type: "text", value: metricName, onChange: (e) => setMetricName(e.target.value), placeholder: "e.g., API Calls, Storage, Users", className: "matrix__modal-input", autoFocus: true })] }), _jsxs("div", { className: "matrix__modal-field", children: [_jsx("label", { className: "matrix__modal-label", children: "Pricing Tiers & Values" }), _jsx("p", { className: "matrix__modal-hint", style: { marginBottom: "0.75rem" }, children: "Enable the metric for each tier and set values." }), _jsx("div", { style: {
2180
+ display: "flex",
2181
+ flexDirection: "column",
2182
+ gap: "0.5rem",
2183
+ }, children: tiers.map((tier) => {
2184
+ const isEnabled = metricEnabledTiers.has(tier.id);
2185
+ return (_jsxs("div", { style: {
2186
+ display: "flex",
2187
+ alignItems: "center",
2188
+ gap: "0.75rem",
2189
+ padding: "0.5rem",
2190
+ borderRadius: "6px",
2191
+ background: isEnabled
2192
+ ? "rgba(124, 58, 237, 0.05)"
2193
+ : "#f8fafc",
2194
+ border: isEnabled
2195
+ ? "1px solid rgba(124, 58, 237, 0.2)"
2196
+ : "1px solid #e2e8f0",
2197
+ transition: "all 0.15s ease",
2198
+ }, children: [_jsxs("label", { style: {
2199
+ display: "flex",
2200
+ alignItems: "center",
2201
+ gap: "0.5rem",
2202
+ cursor: "pointer",
2203
+ minWidth: "120px",
2204
+ }, children: [_jsx("input", { type: "checkbox", checked: isEnabled, onChange: (e) => {
2205
+ setMetricEnabledTiers((prev) => {
2206
+ const next = new Set(prev);
2207
+ if (e.target.checked) {
2208
+ next.add(tier.id);
2209
+ }
2210
+ else {
2211
+ next.delete(tier.id);
2212
+ }
2213
+ return next;
2214
+ });
2215
+ }, style: {
2216
+ width: "16px",
2217
+ height: "16px",
2218
+ accentColor: "#7c3aed",
2219
+ cursor: "pointer",
2220
+ } }), _jsx("span", { style: {
2221
+ fontWeight: 600,
2222
+ color: isEnabled ? "#334155" : "#94a3b8",
2223
+ fontSize: "0.875rem",
2224
+ }, children: tier.name })] }), _jsx("input", { type: "text", value: metricLimits[tier.id] || "", onChange: (e) => setMetricLimits((prev) => ({
2225
+ ...prev,
2226
+ [tier.id]: e.target.value,
2227
+ })), placeholder: isEnabled ? "Enter value" : "—", className: "matrix__modal-input", disabled: !isEnabled, style: {
2228
+ flex: 1,
2229
+ opacity: isEnabled ? 1 : 0.5,
2230
+ cursor: isEnabled ? "text" : "not-allowed",
2231
+ } })] }, tier.id));
2232
+ }) })] }), _jsxs("div", { className: "matrix__modal-actions", children: [_jsx("button", { onClick: () => {
2233
+ setMetricModal(null);
2234
+ setMetricName("");
2235
+ setMetricLimits({});
2236
+ setMetricEnabledTiers(new Set());
2237
+ }, className: "matrix__modal-btn matrix__modal-btn--cancel", children: "Cancel" }), _jsx("button", { onClick: handleSaveMetric, disabled: !metricName.trim() || metricEnabledTiers.size === 0, className: "matrix__modal-btn matrix__modal-btn--primary", children: metricModal.metric ? "Save Changes" : "Add Metric" })] })] }) }))] })] }));
1472
2238
  }
1473
- function ServiceGroupSection({ group, services, tiers, isSetupFormation, isOptional, isEnabled, onToggle, getServiceLevelForTier, getUniqueMetricsForService, getUsageLimitForMetric, getLevelDisplay, selectedCell, setSelectedCell, setupFee, onAddService, selectedTierIdx, }) {
2239
+ function ServiceGroupSection({ group, services, tiers, isSetupFormation, isOptional, isEnabled, onToggle, getServiceLevelForTier, getUniqueMetricsForService, getUsageLimitForMetric, getLevelDisplay, selectedCell, setSelectedCell, setupFee, onAddService, selectedTierIdx, onAddMetric, onEditMetric, onRemoveMetric, onTogglePremiumExclusive, }) {
1474
2240
  const showGroup = services.length > 0 || onAddService;
1475
2241
  if (!showGroup)
1476
2242
  return null;
@@ -1492,7 +2258,7 @@ function ServiceGroupSection({ group, services, tiers, isSetupFormation, isOptio
1492
2258
  ? "OPTIONAL"
1493
2259
  : "INCLUDED" }) })] }), services.map((service) => {
1494
2260
  const metrics = getUniqueMetricsForService(service.id);
1495
- return (_jsx(ServiceRowWithMetrics, { service: service, metrics: metrics, tiers: tiers, rowClass: rowClass, getServiceLevelForTier: getServiceLevelForTier, getUsageLimitForMetric: getUsageLimitForMetric, getLevelDisplay: getLevelDisplay, selectedCell: selectedCell, setSelectedCell: setSelectedCell, selectedTierIdx: selectedTierIdx }, service.id));
2261
+ return (_jsx(ServiceRowWithMetrics, { service: service, metrics: metrics, tiers: tiers, rowClass: rowClass, getServiceLevelForTier: getServiceLevelForTier, getUsageLimitForMetric: getUsageLimitForMetric, getLevelDisplay: getLevelDisplay, selectedCell: selectedCell, setSelectedCell: setSelectedCell, selectedTierIdx: selectedTierIdx, onAddMetric: onAddMetric, onEditMetric: onEditMetric, onRemoveMetric: onRemoveMetric, onTogglePremiumExclusive: onTogglePremiumExclusive }, service.id));
1496
2262
  }), onAddService && group.id !== "__ungrouped__" && (_jsxs("tr", { className: `matrix__add-service-row ${rowClass}`, children: [_jsx("td", { className: rowClass, children: _jsxs("button", { onClick: () => onAddService(group.id, isSetupFormation), className: "matrix__add-service-btn", children: [_jsx("svg", { className: "matrix__add-service-icon", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: _jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M12 4v16m8-8H4" }) }), "+ Add a Service"] }) }), _jsx("td", { colSpan: tiers.length, className: rowClass })] })), isSetupFormation && (_jsxs("tr", { className: "matrix__setup-total-row", children: [_jsx("td", { children: "TOTAL SETUP FEE" }), _jsx("td", { colSpan: tiers.length, style: { textAlign: "center" }, children: setupFee
1497
2263
  ? `$${setupFee} flat fee (applied to all tiers)`
1498
2264
  : "No setup fee configured" })] })), isOptional && (_jsxs("tr", { className: `matrix__total-row ${headerClass}`, children: [_jsx("td", { className: headerClass, children: "SUBTOTAL" }), tiers.map((tier, tierIdx) => {
@@ -1508,23 +2274,47 @@ function ServiceGroupSection({ group, services, tiers, isSetupFormation, isOptio
1508
2274
  }, children: isEnabled ? priceDisplay : "$0" }, tier.id));
1509
2275
  })] }))] }));
1510
2276
  }
1511
- function ServiceRowWithMetrics({ service, metrics, tiers, rowClass, getServiceLevelForTier, getUsageLimitForMetric, getLevelDisplay, selectedCell, setSelectedCell, selectedTierIdx, }) {
1512
- return (_jsxs(_Fragment, { children: [_jsxs("tr", { className: `matrix__service-row ${rowClass}`, children: [_jsx("td", { className: `matrix__service-cell ${rowClass}`, children: _jsx("span", { className: "matrix__service-title", children: service.title }) }), tiers.map((tier, tierIdx) => {
2277
+ function ServiceRowWithMetrics({ service, metrics, tiers, rowClass, getServiceLevelForTier, getUsageLimitForMetric, getLevelDisplay, selectedCell, setSelectedCell, selectedTierIdx, onAddMetric, onEditMetric, onRemoveMetric, onTogglePremiumExclusive, }) {
2278
+ // Use persisted isPremiumExclusive field from document state
2279
+ const isPremiumExclusive = service.isPremiumExclusive;
2280
+ return (_jsxs(_Fragment, { children: [_jsxs("tr", { className: `matrix__service-row ${rowClass}`, children: [_jsx("td", { className: `matrix__service-cell ${rowClass}`, children: _jsxs("div", { className: "matrix__service-cell-wrapper", children: [_jsx("span", { className: "matrix__service-title", children: service.title }), _jsxs("button", { onClick: (e) => {
2281
+ e.stopPropagation();
2282
+ onTogglePremiumExclusive(service.id);
2283
+ }, className: `matrix__premium-badge ${isPremiumExclusive ? "matrix__premium-badge--active" : "matrix__premium-badge--inactive"}`, title: isPremiumExclusive
2284
+ ? "Click to remove premium exclusive status"
2285
+ : "Click to mark as premium exclusive", children: [_jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: _jsx("path", { d: "M12 2l3.09 6.26L22 9.27l-5 4.87 1.18 6.88L12 17.77l-6.18 3.25L7 14.14 2 9.27l6.91-1.01L12 2z" }) }), "Premium"] }), _jsx("button", { onClick: (e) => {
2286
+ e.stopPropagation();
2287
+ onAddMetric(service.id);
2288
+ }, className: "matrix__add-metric-btn", title: "Add metric to this service", children: "+ Metric" })] }) }), tiers.map((tier, tierIdx) => {
1513
2289
  const serviceLevel = getServiceLevelForTier(service.id, tier);
1514
2290
  const display = getLevelDisplay(serviceLevel);
1515
2291
  const isSelected = selectedCell?.serviceId === service.id &&
1516
2292
  selectedCell?.tierId === tier.id;
1517
- return (_jsx("td", { className: `matrix__level-cell ${isSelected ? "matrix__level-cell--selected" : ""} ${tierIdx === selectedTierIdx ? "matrix__level-cell--highlight" : ""}`, onClick: () => setSelectedCell(isSelected
2293
+ const isNotIncluded = !serviceLevel || serviceLevel.level === "NOT_INCLUDED";
2294
+ // Find next tier that has this service included (for upgrade hint)
2295
+ const nextTierWithService = isNotIncluded
2296
+ ? tiers.slice(tierIdx + 1).find((t) => {
2297
+ const sl = getServiceLevelForTier(service.id, t);
2298
+ return sl && sl.level === "INCLUDED";
2299
+ })
2300
+ : null;
2301
+ return (_jsxs("td", { className: `matrix__level-cell ${isSelected ? "matrix__level-cell--selected" : ""} ${tierIdx === selectedTierIdx ? "matrix__level-cell--highlight" : ""} ${isNotIncluded ? "matrix__level-cell--not-included" : ""}`, onClick: () => setSelectedCell(isSelected
1518
2302
  ? null
1519
- : { serviceId: service.id, tierId: tier.id }), children: _jsx("span", { className: "matrix__level-value", style: { color: display.color }, children: display.label }) }, tier.id));
1520
- })] }), metrics.map((metric) => (_jsxs("tr", { className: `matrix__metric-row ${rowClass}`, children: [_jsx("td", { className: `matrix__metric-cell ${rowClass}`, children: _jsx("span", { className: "matrix__metric-name", children: metric }) }), tiers.map((tier, tierIdx) => {
2303
+ : { serviceId: service.id, tierId: tier.id }), children: [_jsx("span", { className: `matrix__level-value ${isNotIncluded ? "matrix__level-value--not-included" : ""}`, style: { color: display.color }, children: display.label }), isNotIncluded && nextTierWithService && (_jsxs("span", { className: "matrix__upgrade-hint", children: ["In ", nextTierWithService.name, " \u2192"] }))] }, tier.id));
2304
+ })] }), metrics.map((metric) => (_jsxs("tr", { className: `matrix__metric-row ${rowClass}`, onClick: () => onEditMetric(service.id, metric), children: [_jsx("td", { className: `matrix__metric-cell ${rowClass}`, children: _jsxs("div", { className: "matrix__metric-name-wrapper", children: [_jsx("span", { className: "matrix__metric-name", children: metric }), _jsxs("div", { className: "matrix__metric-actions", children: [_jsx("button", { onClick: (e) => {
2305
+ e.stopPropagation();
2306
+ onEditMetric(service.id, metric);
2307
+ }, className: "matrix__metric-btn matrix__metric-btn--edit", title: "Edit metric", children: _jsx("svg", { className: "matrix__metric-btn-icon", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: _jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M15.232 5.232l3.536 3.536m-2.036-5.036a2.5 2.5 0 113.536 3.536L6.5 21.036H3v-3.572L16.732 3.732z" }) }) }), _jsx("button", { onClick: (e) => {
2308
+ e.stopPropagation();
2309
+ onRemoveMetric(service.id, metric);
2310
+ }, className: "matrix__metric-btn matrix__metric-btn--remove", title: "Remove metric", children: _jsx("svg", { className: "matrix__metric-btn-icon", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: _jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16" }) }) })] })] }) }), tiers.map((tier, tierIdx) => {
1521
2311
  const usageLimit = getUsageLimitForMetric(service.id, metric, tier);
1522
2312
  return (_jsx("td", { className: `matrix__metric-value-cell ${tierIdx === selectedTierIdx
1523
2313
  ? "matrix__level-cell--highlight"
1524
2314
  : ""}`, children: _jsx("span", { className: "matrix__metric-value", children: usageLimit
1525
2315
  ? usageLimit.limit
1526
2316
  ? `Up to ${usageLimit.limit}`
1527
- : "Unlimited"
2317
+ : usageLimit.notes || "Unlimited"
1528
2318
  : "—" }) }, tier.id));
1529
2319
  })] }, `${service.id}-${metric}`)))] }));
1530
2320
  }
@@ -1601,12 +2391,15 @@ function ServiceLevelDetailPanel({ serviceId, tierId, services, tiers, optionGro
1601
2391
  const handleAddLimit = () => {
1602
2392
  if (!newMetric.trim())
1603
2393
  return;
2394
+ const parsedLimit = newLimit ? parseInt(newLimit, 10) : null;
2395
+ const isNumeric = parsedLimit !== null && !isNaN(parsedLimit);
1604
2396
  dispatch(addUsageLimit({
1605
2397
  tierId: tier.id,
1606
2398
  limitId: generateId(),
1607
2399
  serviceId: service.id,
1608
2400
  metric: newMetric.trim(),
1609
- limit: newLimit ? parseInt(newLimit) : undefined,
2401
+ limit: isNumeric ? parsedLimit : undefined,
2402
+ notes: !isNumeric && newLimit ? newLimit.trim() : undefined,
1610
2403
  resetPeriod: "MONTHLY",
1611
2404
  lastModified: new Date().toISOString(),
1612
2405
  }));
@@ -1652,35 +2445,36 @@ function ServiceLevelDetailPanel({ serviceId, tierId, services, tiers, optionGro
1652
2445
  }));
1653
2446
  }
1654
2447
  };
1655
- return (_jsx("div", { ref: overlayRef, className: "matrix__panel-overlay", onClick: handleOverlayClick, role: "dialog", "aria-modal": "true", "aria-labelledby": "panel-title", children: _jsxs("div", { ref: panelRef, className: "matrix__panel", children: [_jsxs("div", { className: "matrix__panel-header", children: [_jsxs("div", { className: "matrix__panel-header-top", children: [_jsxs("span", { className: "matrix__panel-tier", children: [tier.name, " Tier"] }), _jsx("button", { onClick: onClose, className: "matrix__panel-close", children: _jsx("svg", { className: "matrix__panel-close-icon", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: _jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M6 18L18 6M6 6l12 12" }) }) })] }), _jsx("h3", { id: "panel-title", className: "matrix__panel-title", children: service.title })] }), _jsxs("div", { className: "matrix__panel-body", children: [_jsxs("div", { children: [_jsx("label", { className: "matrix__panel-section-label", children: "Service Level" }), _jsx("div", { className: "matrix__panel-level-grid", children: SERVICE_LEVELS.map((option) => (_jsx("button", { onClick: () => handleSetLevel(option.value), className: `matrix__panel-level-btn ${serviceLevel?.level === option.value
1656
- ? "matrix__panel-level-btn--active"
1657
- : ""}`, children: option.label }, option.value))) })] }), serviceLevel?.level === "CUSTOM" && (_jsxs("div", { children: [_jsx("label", { className: "matrix__panel-section-label", children: "Custom Value" }), _jsx("input", { type: "text", value: customValue, onChange: (e) => setCustomValue(e.target.value), onBlur: handleUpdateCustomValue, placeholder: "e.g., Expedited, Basic, Pro", className: "matrix__panel-input" })] })), _jsxs("div", { children: [_jsxs("div", { className: "matrix__panel-limits-header", children: [_jsx("label", { className: "matrix__panel-section-label", style: { marginBottom: 0 }, children: "Usage Limits / Metrics" }), _jsx("button", { onClick: () => setIsAddingMetric(true), className: "matrix__panel-add-btn", children: "+ Add Metric" })] }), usageLimits.map((limit) => (_jsx(MetricLimitItem, { limit: limit, tierId: tier.id, dispatch: dispatch, onRemove: () => handleRemoveLimit(limit.id) }, limit.id))), usageLimits.length === 0 && !isAddingMetric && (_jsx("p", { className: "matrix__panel-empty-text", children: "No metrics added yet. Metrics will appear as nested rows under this service in the matrix." })), isAddingMetric && (_jsxs("div", { className: "matrix__panel-edit-form", children: [_jsxs("div", { children: [_jsx("label", { className: "matrix__panel-edit-label", children: "Metric Name" }), _jsx("input", { type: "text", value: newMetric, onChange: (e) => setNewMetric(e.target.value), placeholder: "e.g., API Calls, Storage, Users", className: "matrix__panel-input", autoFocus: true })] }), _jsxs("div", { children: [_jsx("label", { className: "matrix__panel-edit-label", children: "Limit Value" }), _jsx("input", { type: "text", value: newLimit, onChange: (e) => setNewLimit(e.target.value), placeholder: "e.g., 100, 5, leave empty for Unlimited", className: "matrix__panel-input" }), _jsx("p", { className: "matrix__panel-edit-hint", children: "Enter a number or leave empty for \"Unlimited\"" })] }), _jsxs("div", { className: "matrix__panel-edit-actions", children: [_jsx("button", { onClick: handleAddLimit, disabled: !newMetric.trim(), className: "matrix__panel-edit-btn matrix__panel-edit-btn--primary", children: "Add Metric" }), _jsx("button", { onClick: () => {
1658
- setNewMetric("");
1659
- setNewLimit("");
1660
- setIsAddingMetric(false);
1661
- }, className: "matrix__panel-edit-btn matrix__panel-edit-btn--secondary", children: "Cancel" })] })] }))] })] }), _jsx("div", { className: "matrix__panel-footer", children: _jsx("button", { onClick: onClose, className: "matrix__panel-done-btn", children: "Done" }) })] }) }));
2448
+ return (_jsx("div", { ref: overlayRef, className: "matrix__panel-overlay", onClick: handleOverlayClick, role: "dialog", "aria-modal": "true", "aria-labelledby": "panel-title", children: _jsxs("div", { ref: panelRef, className: "matrix__panel", children: [_jsxs("div", { className: "matrix__panel-header", children: [_jsxs("div", { className: "matrix__panel-header-top", children: [_jsxs("span", { className: "matrix__panel-tier", children: [tier.name, " Tier"] }), _jsx("button", { onClick: onClose, className: "matrix__panel-close", children: _jsx("svg", { className: "matrix__panel-close-icon", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: _jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M6 18L18 6M6 6l12 12" }) }) })] }), _jsx("h3", { id: "panel-title", className: "matrix__panel-title", children: service.title })] }), _jsx("div", { className: "matrix__panel-body", children: _jsxs("div", { children: [_jsxs("div", { className: "matrix__panel-limits-header", children: [_jsx("label", { className: "matrix__panel-section-label", style: { marginBottom: 0 }, children: "Metrics" }), _jsx("button", { onClick: () => setIsAddingMetric(true), className: "matrix__panel-add-btn", children: "+ Add Metric" })] }), usageLimits.map((limit) => (_jsx(MetricLimitItem, { limit: limit, tierId: tier.id, dispatch: dispatch, onRemove: () => handleRemoveLimit(limit.id) }, limit.id))), usageLimits.length === 0 && !isAddingMetric && (_jsx("p", { className: "matrix__panel-empty-text", children: "No metrics added yet. Metrics will appear as nested rows under this service in the matrix." })), isAddingMetric && (_jsxs("div", { className: "matrix__panel-edit-form", children: [_jsxs("div", { children: [_jsx("label", { className: "matrix__panel-edit-label", children: "Metric Name" }), _jsx("input", { type: "text", value: newMetric, onChange: (e) => setNewMetric(e.target.value), placeholder: "e.g., API Calls, Storage, Users", className: "matrix__panel-input", autoFocus: true })] }), _jsxs("div", { children: [_jsx("label", { className: "matrix__panel-edit-label", children: "Value" }), _jsx("input", { type: "text", value: newLimit, onChange: (e) => setNewLimit(e.target.value), placeholder: "e.g., 100, Unlimited, Custom", className: "matrix__panel-input" }), _jsx("p", { className: "matrix__panel-edit-hint", children: "Enter a value or leave empty" })] }), _jsxs("div", { className: "matrix__panel-edit-actions", children: [_jsx("button", { onClick: handleAddLimit, disabled: !newMetric.trim(), className: "matrix__panel-edit-btn matrix__panel-edit-btn--primary", children: "Add Metric" }), _jsx("button", { onClick: () => {
2449
+ setNewMetric("");
2450
+ setNewLimit("");
2451
+ setIsAddingMetric(false);
2452
+ }, className: "matrix__panel-edit-btn matrix__panel-edit-btn--secondary", children: "Cancel" })] })] }))] }) }), _jsx("div", { className: "matrix__panel-footer", children: _jsx("button", { onClick: onClose, className: "matrix__panel-done-btn", children: "Done" }) })] }) }));
1662
2453
  }
1663
2454
  function MetricLimitItem({ limit, tierId, dispatch, onRemove, }) {
1664
2455
  const [isEditing, setIsEditing] = useState(false);
1665
2456
  const [editMetric, setEditMetric] = useState(limit.metric);
1666
- const [editLimit, setEditLimit] = useState(limit.limit?.toString() || "");
2457
+ const [editLimit, setEditLimit] = useState(limit.limit?.toString() || limit.notes || "");
1667
2458
  const handleSave = () => {
2459
+ const parsedLimit = editLimit ? parseInt(editLimit, 10) : null;
2460
+ const isNumeric = parsedLimit !== null && !isNaN(parsedLimit);
1668
2461
  dispatch(updateUsageLimit({
1669
2462
  tierId,
1670
2463
  limitId: limit.id,
1671
2464
  metric: editMetric.trim() || limit.metric,
1672
- limit: editLimit ? parseInt(editLimit) : undefined,
2465
+ limit: isNumeric ? parsedLimit : undefined,
2466
+ notes: !isNumeric && editLimit ? editLimit.trim() : undefined,
1673
2467
  lastModified: new Date().toISOString(),
1674
2468
  }));
1675
2469
  setIsEditing(false);
1676
2470
  };
1677
2471
  const handleCancel = () => {
1678
2472
  setEditMetric(limit.metric);
1679
- setEditLimit(limit.limit?.toString() || "");
2473
+ setEditLimit(limit.limit?.toString() || limit.notes || "");
1680
2474
  setIsEditing(false);
1681
2475
  };
1682
2476
  if (isEditing) {
1683
- return (_jsxs("div", { className: "matrix__panel-edit-form", children: [_jsxs("div", { children: [_jsx("label", { className: "matrix__panel-edit-label", children: "Metric Name" }), _jsx("input", { type: "text", value: editMetric, onChange: (e) => setEditMetric(e.target.value), placeholder: "Metric name", className: "matrix__panel-input", autoFocus: true })] }), _jsxs("div", { children: [_jsx("label", { className: "matrix__panel-edit-label", children: "Limit Value" }), _jsx("input", { type: "text", value: editLimit, onChange: (e) => setEditLimit(e.target.value), placeholder: "e.g., 3, Unlimited, As needed", className: "matrix__panel-input" }), _jsx("p", { className: "matrix__panel-edit-hint", children: "Can be numeric (3) or descriptive (Unlimited, Custom)" })] }), _jsxs("div", { className: "matrix__panel-edit-actions", children: [_jsx("button", { onClick: handleSave, className: "matrix__panel-edit-btn matrix__panel-edit-btn--primary", children: "Save" }), _jsx("button", { onClick: handleCancel, className: "matrix__panel-edit-btn matrix__panel-edit-btn--secondary", children: "Cancel" })] })] }));
2477
+ return (_jsxs("div", { className: "matrix__panel-edit-form", children: [_jsxs("div", { children: [_jsx("label", { className: "matrix__panel-edit-label", children: "Metric Name" }), _jsx("input", { type: "text", value: editMetric, onChange: (e) => setEditMetric(e.target.value), placeholder: "Metric name", className: "matrix__panel-input", autoFocus: true })] }), _jsxs("div", { children: [_jsx("label", { className: "matrix__panel-edit-label", children: "Value" }), _jsx("input", { type: "text", value: editLimit, onChange: (e) => setEditLimit(e.target.value), placeholder: "e.g., 100, Unlimited, Custom", className: "matrix__panel-input" }), _jsx("p", { className: "matrix__panel-edit-hint", children: "Enter a value or leave empty" })] }), _jsxs("div", { className: "matrix__panel-edit-actions", children: [_jsx("button", { onClick: handleSave, className: "matrix__panel-edit-btn matrix__panel-edit-btn--primary", children: "Save" }), _jsx("button", { onClick: handleCancel, className: "matrix__panel-edit-btn matrix__panel-edit-btn--secondary", children: "Cancel" })] })] }));
1684
2478
  }
1685
- return (_jsxs("div", { className: "matrix__panel-limit-item", children: [_jsxs("div", { className: "matrix__panel-limit-content", onClick: () => setIsEditing(true), children: [_jsx("div", { className: "matrix__panel-limit-metric", children: limit.metric }), _jsx("div", { className: "matrix__panel-limit-value", children: limit.limit ? `Up to ${limit.limit}` : "Unlimited" })] }), _jsxs("div", { className: "matrix__panel-limit-actions", children: [_jsx("button", { onClick: () => setIsEditing(true), className: "matrix__panel-limit-btn matrix__panel-limit-btn--edit", title: "Edit metric", children: _jsx("svg", { className: "matrix__panel-limit-icon", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: _jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M15.232 5.232l3.536 3.536m-2.036-5.036a2.5 2.5 0 113.536 3.536L6.5 21.036H3v-3.572L16.732 3.732z" }) }) }), _jsx("button", { onClick: onRemove, className: "matrix__panel-limit-btn matrix__panel-limit-btn--remove", title: "Remove metric", children: _jsx("svg", { className: "matrix__panel-limit-icon", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: _jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M6 18L18 6M6 6l12 12" }) }) })] })] }));
2479
+ return (_jsxs("div", { className: "matrix__panel-limit-item", children: [_jsxs("div", { className: "matrix__panel-limit-content", onClick: () => setIsEditing(true), children: [_jsx("div", { className: "matrix__panel-limit-metric", children: limit.metric }), _jsx("div", { className: "matrix__panel-limit-value", children: limit.limit ?? limit.notes ?? "" })] }), _jsxs("div", { className: "matrix__panel-limit-actions", children: [_jsx("button", { onClick: () => setIsEditing(true), className: "matrix__panel-limit-btn matrix__panel-limit-btn--edit", title: "Edit metric", children: _jsx("svg", { className: "matrix__panel-limit-icon", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: _jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M15.232 5.232l3.536 3.536m-2.036-5.036a2.5 2.5 0 113.536 3.536L6.5 21.036H3v-3.572L16.732 3.732z" }) }) }), _jsx("button", { onClick: onRemove, className: "matrix__panel-limit-btn matrix__panel-limit-btn--remove", title: "Remove metric", children: _jsx("svg", { className: "matrix__panel-limit-icon", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: _jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M6 18L18 6M6 6l12 12" }) }) })] })] }));
1686
2480
  }