@countermeasure-platform/web-components 1.2.1-dev.6.1 → 1.2.2-dev.7.1

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 (302) hide show
  1. package/dist/{arc-jVbrWVYZ.js → arc-DOJ9myHo.js} +21 -21
  2. package/dist/{arc-jVbrWVYZ.js.map → arc-DOJ9myHo.js.map} +1 -1
  3. package/dist/architecture-7EHR7CIX-RjIwnEbG.js +3 -0
  4. package/dist/{architectureDiagram-2XIMDMQ5-D5q0ma9h.js → architectureDiagram-3BPJPVTR-cYFnhp15.js} +165 -152
  5. package/dist/{architectureDiagram-2XIMDMQ5-D5q0ma9h.js.map → architectureDiagram-3BPJPVTR-cYFnhp15.js.map} +1 -1
  6. package/dist/{array-DXadUs1s.js → array-BLp0zq5K.js} +1 -1
  7. package/dist/{array-DXadUs1s.js.map → array-BLp0zq5K.js.map} +1 -1
  8. package/dist/{blockDiagram-WCTKOSBZ-BH3jwWeU.js → blockDiagram-GPEHLZMM-DNLPMFXL.js} +994 -864
  9. package/dist/blockDiagram-GPEHLZMM-DNLPMFXL.js.map +1 -0
  10. package/dist/{c4Diagram-IC4MRINW-OFLrunYI.js → c4Diagram-AAUBKEIU-G8g3OBBg.js} +232 -235
  11. package/dist/c4Diagram-AAUBKEIU-G8g3OBBg.js.map +1 -0
  12. package/dist/channel-MTYqUJFm.js +7 -0
  13. package/dist/{channel-LRbq43st.js.map → channel-MTYqUJFm.js.map} +1 -1
  14. package/dist/{chunk-KX2RTZJC-d9jFqUAY.js → chunk-2J33WTMH-BKsVIUnb.js} +4 -4
  15. package/dist/{chunk-KX2RTZJC-d9jFqUAY.js.map → chunk-2J33WTMH-BKsVIUnb.js.map} +1 -1
  16. package/dist/chunk-3OPIFGDE-CcNRL44h.js +3669 -0
  17. package/dist/chunk-3OPIFGDE-CcNRL44h.js.map +1 -0
  18. package/dist/{chunk-4BX2VUAB-BS9gpN-y.js → chunk-4BX2VUAB-BeLKo9Pn.js} +2 -2
  19. package/dist/{chunk-4BX2VUAB-BS9gpN-y.js.map → chunk-4BX2VUAB-BeLKo9Pn.js.map} +1 -1
  20. package/dist/{chunk-R5LLSJPH-c1IfaK5D.js → chunk-4EGX6M5U-Bh9as06l.js} +13 -13
  21. package/dist/chunk-4EGX6M5U-Bh9as06l.js.map +1 -0
  22. package/dist/{chunk-55IACEB6-DZ-UBhHX.js → chunk-55IACEB6-CuKbiO89.js} +3 -3
  23. package/dist/{chunk-55IACEB6-DZ-UBhHX.js.map → chunk-55IACEB6-CuKbiO89.js.map} +1 -1
  24. package/dist/chunk-5DO6E6H7-CAB8pWf5.js +25 -0
  25. package/dist/chunk-5DO6E6H7-CAB8pWf5.js.map +1 -0
  26. package/dist/{chunk-GEFDOKGD-DGJJEGSm.js → chunk-5ZQYHXKU-CjOcwRY6.js} +570 -326
  27. package/dist/chunk-5ZQYHXKU-CjOcwRY6.js.map +1 -0
  28. package/dist/{chunk-WL4C6EOR-BV-op7zg.js → chunk-727SXJPM-kowsFLrz.js} +724 -569
  29. package/dist/chunk-727SXJPM-kowsFLrz.js.map +1 -0
  30. package/dist/{chunk-NQ4KR5QH-C0nWShNk.js → chunk-AQP2D5EJ-Bc1gUIeA.js} +384 -362
  31. package/dist/chunk-AQP2D5EJ-Bc1gUIeA.js.map +1 -0
  32. package/dist/{chunk-OZEHJAEY-BsQ56PV-.js → chunk-BR22UD5L-BCFxmd5-.js} +16 -16
  33. package/dist/chunk-BR22UD5L-BCFxmd5-.js.map +1 -0
  34. package/dist/{chunk-MX3YWQON-D43mcq1f.js → chunk-BSJP7CBP-Bl94i3-1.js} +7 -5
  35. package/dist/chunk-BSJP7CBP-Bl94i3-1.js.map +1 -0
  36. package/dist/chunk-CSCIHK7Q-DyRIc27i.js +2868 -0
  37. package/dist/chunk-CSCIHK7Q-DyRIc27i.js.map +1 -0
  38. package/dist/chunk-FHYWG6QK-kLWdRarG.js +25 -0
  39. package/dist/chunk-FHYWG6QK-kLWdRarG.js.map +1 -0
  40. package/dist/{chunk-FMBD7UC4-1IxrpdPX.js → chunk-FMBD7UC4-IdpWVRCU.js} +2 -2
  41. package/dist/{chunk-FMBD7UC4-1IxrpdPX.js.map → chunk-FMBD7UC4-IdpWVRCU.js.map} +1 -1
  42. package/dist/chunk-KSCS5N6A-CVcDS9QV.js +563 -0
  43. package/dist/chunk-KSCS5N6A-CVcDS9QV.js.map +1 -0
  44. package/dist/{chunk-YBOYWFTD-DkjEOcgZ.js → chunk-L5ZTLDWV-Day0EgsR.js} +9 -9
  45. package/dist/{chunk-YBOYWFTD-DkjEOcgZ.js.map → chunk-L5ZTLDWV-Day0EgsR.js.map} +1 -1
  46. package/dist/chunk-LZXEDZCA-BO_GpQSR.js +51 -0
  47. package/dist/chunk-LZXEDZCA-BO_GpQSR.js.map +1 -0
  48. package/dist/chunk-MPE355IW-BkN6MrMO.js +25 -0
  49. package/dist/chunk-MPE355IW-BkN6MrMO.js.map +1 -0
  50. package/dist/chunk-MZUSXYTE-94iWO-dh.js +32 -0
  51. package/dist/chunk-MZUSXYTE-94iWO-dh.js.map +1 -0
  52. package/dist/chunk-N66VUXT2-QbIUkiJZ.js +56 -0
  53. package/dist/chunk-N66VUXT2-QbIUkiJZ.js.map +1 -0
  54. package/dist/{chunk-JSJVCQXG-Do17yYig.js → chunk-ND2GUHAM-Boh7GenS.js} +6 -6
  55. package/dist/{chunk-JSJVCQXG-Do17yYig.js.map → chunk-ND2GUHAM-Boh7GenS.js.map} +1 -1
  56. package/dist/chunk-NNHCCRGN-CNU0zvRn.js +20603 -0
  57. package/dist/chunk-NNHCCRGN-CNU0zvRn.js.map +1 -0
  58. package/dist/{chunk-PQ6SQG4A-Cpfc5F4u.js → chunk-NZK2D7GU-D4Ird7wv.js} +4 -4
  59. package/dist/{chunk-PQ6SQG4A-Cpfc5F4u.js.map → chunk-NZK2D7GU-D4Ird7wv.js.map} +1 -1
  60. package/dist/{chunk-PU5JKC2W-DNpn_Yik.js → chunk-O5CBEL6O-DThtyjPO.js} +85 -74
  61. package/dist/{chunk-PU5JKC2W-DNpn_Yik.js.map → chunk-O5CBEL6O-DThtyjPO.js.map} +1 -1
  62. package/dist/chunk-PUPMXCY4-DsO2K8st.js +25 -0
  63. package/dist/chunk-PUPMXCY4-DsO2K8st.js.map +1 -0
  64. package/dist/{chunk-QZHKN3VN-kDNdTVLo.js → chunk-QZHKN3VN-DC5aJQQT.js} +2 -2
  65. package/dist/{chunk-QZHKN3VN-kDNdTVLo.js.map → chunk-QZHKN3VN-DC5aJQQT.js.map} +1 -1
  66. package/dist/chunk-UIBZB4QT-Cu3IcTk1.js +25 -0
  67. package/dist/chunk-UIBZB4QT-Cu3IcTk1.js.map +1 -0
  68. package/dist/chunk-WCWK7LTN-DpMt57Ty.js +33 -0
  69. package/dist/chunk-WCWK7LTN-DpMt57Ty.js.map +1 -0
  70. package/dist/chunk-WU5MYG2G-mzocEmS2.js +12 -0
  71. package/dist/{chunk-HHEYEP7N-DJ1b-gA8.js.map → chunk-WU5MYG2G-mzocEmS2.js.map} +1 -1
  72. package/dist/{chunk-XPW4576I-BqiPnb3d.js → chunk-XPW4576I-BwxN5U1_.js} +2 -2
  73. package/dist/{chunk-XPW4576I-BqiPnb3d.js.map → chunk-XPW4576I-BwxN5U1_.js.map} +1 -1
  74. package/dist/classDiagram-4FO5ZUOK-CZv04EX-.js +31 -0
  75. package/dist/{classDiagram-VBA2DB6C-DZfC0xPM.js.map → classDiagram-4FO5ZUOK-CZv04EX-.js.map} +1 -1
  76. package/dist/classDiagram-v2-Q7XG4LA2-aOPSPoxt.js +31 -0
  77. package/dist/{classDiagram-v2-RAHNMMFH-CtWRD1ax.js.map → classDiagram-v2-Q7XG4LA2-aOPSPoxt.js.map} +1 -1
  78. package/dist/component-Dye0I6sO.js +145 -0
  79. package/dist/component-Dye0I6sO.js.map +1 -0
  80. package/dist/components/brand/index.d.ts +8 -2
  81. package/dist/components/brand/index.d.ts.map +1 -1
  82. package/dist/components/brand/index.js +58 -31
  83. package/dist/components/brand/index.js.map +1 -1
  84. package/dist/components/brand/types.d.ts +8 -0
  85. package/dist/components/brand/types.d.ts.map +1 -1
  86. package/dist/{cose-bilkent-S5V4N54A-DxM02fly.js → cose-bilkent-S5V4N54A-D_hwzCJc.js} +7 -8
  87. package/dist/{cose-bilkent-S5V4N54A-DxM02fly.js.map → cose-bilkent-S5V4N54A-D_hwzCJc.js.map} +1 -1
  88. package/dist/{cytoscape.esm-2vKMh7AJ.js → cytoscape.esm-C85eXBIz.js} +1 -1
  89. package/dist/{cytoscape.esm-2vKMh7AJ.js.map → cytoscape.esm-C85eXBIz.js.map} +1 -1
  90. package/dist/dagre-BM42HDAG-DBqY2dVf.js +299 -0
  91. package/dist/dagre-BM42HDAG-DBqY2dVf.js.map +1 -0
  92. package/dist/dagre-IxFkiJHF.js +1938 -0
  93. package/dist/dagre-IxFkiJHF.js.map +1 -0
  94. package/dist/{defaultLocale-PLHpRrsr.js → defaultLocale-DSDxELFN.js} +1 -1
  95. package/dist/{defaultLocale-PLHpRrsr.js.map → defaultLocale-DSDxELFN.js.map} +1 -1
  96. package/dist/{diagram-IFDJBPK2-D-Enf1mK.js → diagram-2AECGRRQ-BwC5Qbme.js} +39 -39
  97. package/dist/{diagram-IFDJBPK2-D-Enf1mK.js.map → diagram-2AECGRRQ-BwC5Qbme.js.map} +1 -1
  98. package/dist/diagram-5GNKFQAL-BpJ9oZ4s.js +103 -0
  99. package/dist/diagram-5GNKFQAL-BpJ9oZ4s.js.map +1 -0
  100. package/dist/diagram-KO2AKTUF-kSLn21uw.js +434 -0
  101. package/dist/diagram-KO2AKTUF-kSLn21uw.js.map +1 -0
  102. package/dist/{diagram-P4PSJMXO-O8g_RIkM.js → diagram-LMA3HP47-BRqyGMLP.js} +43 -43
  103. package/dist/{diagram-P4PSJMXO-O8g_RIkM.js.map → diagram-LMA3HP47-BRqyGMLP.js.map} +1 -1
  104. package/dist/{diagram-E7M64L7V-Co7O3gub.js → diagram-OG6HWLK6-BsskLXHm.js} +171 -174
  105. package/dist/diagram-OG6HWLK6-BsskLXHm.js.map +1 -0
  106. package/dist/{dist-BrNloUiz.js → dist-BScrlPBC.js} +32 -23
  107. package/dist/dist-BScrlPBC.js.map +1 -0
  108. package/dist/{erDiagram-INFDFZHY-C42JeR9I.js → erDiagram-TEJ5UH35-DzB7hnCi.js} +198 -164
  109. package/dist/erDiagram-TEJ5UH35-DzB7hnCi.js.map +1 -0
  110. package/dist/eventmodeling-FCH6USID-HcA67HMu.js +3 -0
  111. package/dist/{flowDiagram-PKNHOUZH-DInJjOz3.js → flowDiagram-I6XJVG4X-RYkPtPRG.js} +453 -469
  112. package/dist/flowDiagram-I6XJVG4X-RYkPtPRG.js.map +1 -0
  113. package/dist/{ganttDiagram-A5KZAMGK-Dgp-4Yss.js → ganttDiagram-6RSMTGT7-BfjlFVNd.js} +340 -333
  114. package/dist/ganttDiagram-6RSMTGT7-BfjlFVNd.js.map +1 -0
  115. package/dist/gitGraph-WXDBUCRP-D60yP8mT.js +3 -0
  116. package/dist/gitGraphDiagram-PVQCEYII-DbUp_ElG.js +731 -0
  117. package/dist/gitGraphDiagram-PVQCEYII-DbUp_ElG.js.map +1 -0
  118. package/dist/graphlib-k-wJtbbK.js +1268 -0
  119. package/dist/graphlib-k-wJtbbK.js.map +1 -0
  120. package/dist/info-J43DQDTF-DDmtkMBG.js +3 -0
  121. package/dist/{infoDiagram-LFFYTUFH-DajJJRvc.js → infoDiagram-5YYISTIA-C0TqWTrr.js} +7 -7
  122. package/dist/{infoDiagram-LFFYTUFH-DajJJRvc.js.map → infoDiagram-5YYISTIA-C0TqWTrr.js.map} +1 -1
  123. package/dist/{init-DcLTaNW1.js → init-CGzIZb6J.js} +1 -1
  124. package/dist/{init-DcLTaNW1.js.map → init-CGzIZb6J.js.map} +1 -1
  125. package/dist/{ishikawaDiagram-PHBUUO56-qHBJm2LT.js → ishikawaDiagram-YF4QCWOH-Cyk_Antz.js} +98 -97
  126. package/dist/ishikawaDiagram-YF4QCWOH-Cyk_Antz.js.map +1 -0
  127. package/dist/{journeyDiagram-4ABVD52K-PgfYdoDM.js → journeyDiagram-JHISSGLW-CTl8eDDe.js} +78 -78
  128. package/dist/journeyDiagram-JHISSGLW-CTl8eDDe.js.map +1 -0
  129. package/dist/{kanban-definition-K7BYSVSG-DFRT8j7A.js → kanban-definition-UN3LZRKU-homeDoHF.js} +46 -44
  130. package/dist/{kanban-definition-K7BYSVSG-DFRT8j7A.js.map → kanban-definition-UN3LZRKU-homeDoHF.js.map} +1 -1
  131. package/dist/{katex-BZdHnXin.js → katex-CgkxVokH.js} +1 -1
  132. package/dist/{katex-BZdHnXin.js.map → katex-CgkxVokH.js.map} +1 -1
  133. package/dist/line-k_aZSToM.js +36 -0
  134. package/dist/{line-Cq1AZT4f.js.map → line-k_aZSToM.js.map} +1 -1
  135. package/dist/{linear-BnJD01Xn.js → linear-Dpcbf4VP.js} +5 -5
  136. package/dist/{linear-BnJD01Xn.js.map → linear-Dpcbf4VP.js.map} +1 -1
  137. package/dist/{mermaid-parser.core-Dz5qv4CI.js → mermaid-parser.core-B_q76LYz.js} +32 -17
  138. package/dist/mermaid-parser.core-B_q76LYz.js.map +1 -0
  139. package/dist/mermaid.core-DAh-gNcn.js +997 -0
  140. package/dist/mermaid.core-DAh-gNcn.js.map +1 -0
  141. package/dist/{mindmap-definition-YRQLILUH-D95OPRMh.js → mindmap-definition-RKZ34NQL-Cjglmmr7.js} +153 -108
  142. package/dist/mindmap-definition-RKZ34NQL-Cjglmmr7.js.map +1 -0
  143. package/dist/{ordinal-CC9tfh_g.js → ordinal-DHGdAr1Y.js} +2 -2
  144. package/dist/{ordinal-CC9tfh_g.js.map → ordinal-DHGdAr1Y.js.map} +1 -1
  145. package/dist/packet-YPE3B663-Bo9N32Mb.js +3 -0
  146. package/dist/{path-y0uQCOMW.js → path-D-DDb3Wo.js} +1 -1
  147. package/dist/{path-y0uQCOMW.js.map → path-D-DDb3Wo.js.map} +1 -1
  148. package/dist/pie-LRSECV5Y-DndCyILX.js +3 -0
  149. package/dist/pieDiagram-4H26LBE5-Swbny_uk.js +167 -0
  150. package/dist/pieDiagram-4H26LBE5-Swbny_uk.js.map +1 -0
  151. package/dist/{quadrantDiagram-337W2JSQ-CcKc-h2o.js → quadrantDiagram-W4KKPZXB-kyt1iJkC.js} +359 -332
  152. package/dist/quadrantDiagram-W4KKPZXB-kyt1iJkC.js.map +1 -0
  153. package/dist/radar-GUYGQ44K-DpLG1fRN.js +3 -0
  154. package/dist/react/brand/index.d.ts +13 -1
  155. package/dist/react/brand/index.d.ts.map +1 -1
  156. package/dist/react/brand.js +28 -3
  157. package/dist/react/brand.js.map +1 -1
  158. package/dist/react/sidebar.d.ts +22 -1
  159. package/dist/react/sidebar.d.ts.map +1 -1
  160. package/dist/react/sidebar.js +26 -2
  161. package/dist/react/sidebar.js.map +1 -1
  162. package/dist/react/topology.js +1 -1
  163. package/dist/react.js +100 -100
  164. package/dist/{requirementDiagram-Z7DCOOCP-aPcaPduF.js → requirementDiagram-4Y6WPE33-DWRks7dz.js} +153 -133
  165. package/dist/requirementDiagram-4Y6WPE33-DWRks7dz.js.map +1 -0
  166. package/dist/{rough.esm-C9rQ9YkE.js → rough.esm-C7tiDdBn.js} +1 -1
  167. package/dist/{rough.esm-C9rQ9YkE.js.map → rough.esm-C7tiDdBn.js.map} +1 -1
  168. package/dist/{sankeyDiagram-WA2Y5GQK-CO_lUqQX.js → sankeyDiagram-5OEKKPKP-J_SVMd-0.js} +125 -76
  169. package/dist/{sankeyDiagram-WA2Y5GQK-CO_lUqQX.js.map → sankeyDiagram-5OEKKPKP-J_SVMd-0.js.map} +1 -1
  170. package/dist/sequenceDiagram-3UESZ5HK-BMhjbe8U.js +4167 -0
  171. package/dist/sequenceDiagram-3UESZ5HK-BMhjbe8U.js.map +1 -0
  172. package/dist/sidebar/component.d.ts +4 -0
  173. package/dist/sidebar/component.d.ts.map +1 -1
  174. package/dist/sidebar/index.d.ts +1 -1
  175. package/dist/sidebar/index.d.ts.map +1 -1
  176. package/dist/sidebar/index.js +1 -1
  177. package/dist/sidebar/index.js.map +1 -1
  178. package/dist/sidebar/types.d.ts +39 -0
  179. package/dist/sidebar/types.d.ts.map +1 -1
  180. package/dist/{src-D1EMXotX.js → src-CWnvxuyh.js} +603 -591
  181. package/dist/{src-D1EMXotX.js.map → src-CWnvxuyh.js.map} +1 -1
  182. package/dist/{src-BhNgmpel.js → src-DngnQkx_.js} +4 -5
  183. package/dist/{src-BhNgmpel.js.map → src-DngnQkx_.js.map} +1 -1
  184. package/dist/stateDiagram-AJRCARHV-x4JHehDk.js +220 -0
  185. package/dist/stateDiagram-AJRCARHV-x4JHehDk.js.map +1 -0
  186. package/dist/stateDiagram-v2-BHNVJYJU-CO93vpHl.js +29 -0
  187. package/dist/{stateDiagram-v2-FVOUBMTO-CAWy0Pkh.js.map → stateDiagram-v2-BHNVJYJU-CO93vpHl.js.map} +1 -1
  188. package/dist/styles/components/brand.css +30 -0
  189. package/dist/styles/sidebar.css +495 -0
  190. package/dist/{timeline-definition-YZTLITO2-CjxxCuOg.js → timeline-definition-PNZ67QCA-rsiMN1-p.js} +517 -279
  191. package/dist/timeline-definition-PNZ67QCA-rsiMN1-p.js.map +1 -0
  192. package/dist/{topology-C8cyIHlB.js → topology-B9Lv-y1-.js} +181 -182
  193. package/dist/{topology-C8cyIHlB.js.map → topology-B9Lv-y1-.js.map} +1 -1
  194. package/dist/treeView-BLDUP644-mJdM3Q6x.js +3 -0
  195. package/dist/treemap-LRROVOQU-BbNMhR6z.js +3 -0
  196. package/dist/{value-gSPnIECy.js → value-CnwEagIg.js} +2 -2
  197. package/dist/{value-gSPnIECy.js.map → value-CnwEagIg.js.map} +1 -1
  198. package/dist/{vennDiagram-LZ73GAT5-FqpGoq2s.js → vennDiagram-CIIHVFJN-JUCgWboO.js} +98 -98
  199. package/dist/{vennDiagram-LZ73GAT5-FqpGoq2s.js.map → vennDiagram-CIIHVFJN-JUCgWboO.js.map} +1 -1
  200. package/dist/visualization/mermaid-diagram/index.js +1 -1
  201. package/dist/wardley-L42UT6IY-DB53GwcN.js +3 -0
  202. package/dist/wardleyDiagram-YWT4CUSO-D9ZPcSHL.js +646 -0
  203. package/dist/wardleyDiagram-YWT4CUSO-D9ZPcSHL.js.map +1 -0
  204. package/dist/{xychartDiagram-JWTSCODW-BNEAK79X.js → xychartDiagram-2RQKCTM6-D3ufsY0S.js} +146 -143
  205. package/dist/{xychartDiagram-JWTSCODW-BNEAK79X.js.map → xychartDiagram-2RQKCTM6-D3ufsY0S.js.map} +1 -1
  206. package/package.json +1 -1
  207. package/src/components/brand/index.ts +63 -0
  208. package/src/components/brand/types.ts +9 -0
  209. package/src/react/brand/index.test.tsx +28 -0
  210. package/src/react/brand/index.tsx +38 -0
  211. package/src/react/sidebar.test.tsx +30 -0
  212. package/src/react/sidebar.tsx +52 -1
  213. package/src/sidebar/component.test.ts +109 -0
  214. package/src/sidebar/component.ts +136 -4
  215. package/src/sidebar/index.ts +1 -0
  216. package/src/sidebar/types.ts +40 -0
  217. package/src/styles/components/brand.css +30 -0
  218. package/src/styles/sidebar.css +495 -0
  219. package/dist/_basePickBy-BQMPE4-n.js +0 -168
  220. package/dist/_basePickBy-BQMPE4-n.js.map +0 -1
  221. package/dist/_baseUniq-Bdp_vFUv.js +0 -684
  222. package/dist/_baseUniq-Bdp_vFUv.js.map +0 -1
  223. package/dist/architecture-PBZL5I3N-Zk3GmKE8.js +0 -3
  224. package/dist/blockDiagram-WCTKOSBZ-BH3jwWeU.js.map +0 -1
  225. package/dist/c4Diagram-IC4MRINW-OFLrunYI.js.map +0 -1
  226. package/dist/channel-LRbq43st.js +0 -7
  227. package/dist/chunk-7E7YKBS2-BsywoVTt.js +0 -25
  228. package/dist/chunk-7E7YKBS2-BsywoVTt.js.map +0 -1
  229. package/dist/chunk-7R4GIKGN-DJmroLCH.js +0 -2054
  230. package/dist/chunk-7R4GIKGN-DJmroLCH.js.map +0 -1
  231. package/dist/chunk-C72U2L5F-BwPwVDcP.js +0 -25
  232. package/dist/chunk-C72U2L5F-BwPwVDcP.js.map +0 -1
  233. package/dist/chunk-EGIJ26TM-DKd5cEgn.js +0 -25
  234. package/dist/chunk-EGIJ26TM-DKd5cEgn.js.map +0 -1
  235. package/dist/chunk-GEFDOKGD-DGJJEGSm.js.map +0 -1
  236. package/dist/chunk-GLR3WWYH-BDwmgwCA.js +0 -43
  237. package/dist/chunk-GLR3WWYH-BDwmgwCA.js.map +0 -1
  238. package/dist/chunk-HHEYEP7N-DJ1b-gA8.js +0 -12
  239. package/dist/chunk-KYZI473N-BXYCe83A.js +0 -3437
  240. package/dist/chunk-KYZI473N-BXYCe83A.js.map +0 -1
  241. package/dist/chunk-L3YUKLVL-Y5k8UNMf.js +0 -25
  242. package/dist/chunk-L3YUKLVL-Y5k8UNMf.js.map +0 -1
  243. package/dist/chunk-MX3YWQON-D43mcq1f.js.map +0 -1
  244. package/dist/chunk-NBPlniwU.js +0 -23
  245. package/dist/chunk-NQ4KR5QH-C0nWShNk.js.map +0 -1
  246. package/dist/chunk-O4XLMI2P-DtGEm9QX.js +0 -514
  247. package/dist/chunk-O4XLMI2P-DtGEm9QX.js.map +0 -1
  248. package/dist/chunk-OZEHJAEY-BsQ56PV-.js.map +0 -1
  249. package/dist/chunk-R5LLSJPH-c1IfaK5D.js.map +0 -1
  250. package/dist/chunk-WL4C6EOR-BV-op7zg.js.map +0 -1
  251. package/dist/chunk-XIRO2GV7-Bv1hlNLi.js +0 -32
  252. package/dist/chunk-XIRO2GV7-Bv1hlNLi.js.map +0 -1
  253. package/dist/chunk-XZSTWKYB-C7maKWEr.js +0 -15799
  254. package/dist/chunk-XZSTWKYB-C7maKWEr.js.map +0 -1
  255. package/dist/classDiagram-VBA2DB6C-DZfC0xPM.js +0 -31
  256. package/dist/classDiagram-v2-RAHNMMFH-CtWRD1ax.js +0 -31
  257. package/dist/clone-CliVdNc8.js +0 -10
  258. package/dist/clone-CliVdNc8.js.map +0 -1
  259. package/dist/component-C1Jiz1Ki.js +0 -103
  260. package/dist/component-C1Jiz1Ki.js.map +0 -1
  261. package/dist/dagre-BqC9mhMk.js +0 -1485
  262. package/dist/dagre-BqC9mhMk.js.map +0 -1
  263. package/dist/dagre-KLK3FWXG-DTKcsol6.js +0 -296
  264. package/dist/dagre-KLK3FWXG-DTKcsol6.js.map +0 -1
  265. package/dist/diagram-E7M64L7V-Co7O3gub.js.map +0 -1
  266. package/dist/dist-BrNloUiz.js.map +0 -1
  267. package/dist/erDiagram-INFDFZHY-C42JeR9I.js.map +0 -1
  268. package/dist/flowDiagram-PKNHOUZH-DInJjOz3.js.map +0 -1
  269. package/dist/ganttDiagram-A5KZAMGK-Dgp-4Yss.js.map +0 -1
  270. package/dist/gitGraph-HDMCJU4V-D_QsK6Rt.js +0 -3
  271. package/dist/gitGraphDiagram-K3NZZRJ6-Dr_X0dND.js +0 -628
  272. package/dist/gitGraphDiagram-K3NZZRJ6-Dr_X0dND.js.map +0 -1
  273. package/dist/graphlib-ecencZTG.js +0 -227
  274. package/dist/graphlib-ecencZTG.js.map +0 -1
  275. package/dist/info-3K5VOQVL-BbLiZXwn.js +0 -3
  276. package/dist/isArrayLikeObject-Bjsxaqj7.js +0 -580
  277. package/dist/isArrayLikeObject-Bjsxaqj7.js.map +0 -1
  278. package/dist/isEmpty-CeZZUVts.js +0 -37
  279. package/dist/isEmpty-CeZZUVts.js.map +0 -1
  280. package/dist/ishikawaDiagram-PHBUUO56-qHBJm2LT.js.map +0 -1
  281. package/dist/journeyDiagram-4ABVD52K-PgfYdoDM.js.map +0 -1
  282. package/dist/line-Cq1AZT4f.js +0 -36
  283. package/dist/math-D4gdAuwG.js +0 -12
  284. package/dist/math-D4gdAuwG.js.map +0 -1
  285. package/dist/mermaid-parser.core-Dz5qv4CI.js.map +0 -1
  286. package/dist/mermaid.core-DTiIXVKa.js +0 -923
  287. package/dist/mermaid.core-DTiIXVKa.js.map +0 -1
  288. package/dist/mindmap-definition-YRQLILUH-D95OPRMh.js.map +0 -1
  289. package/dist/packet-RMMSAZCW-D72DRs1N.js +0 -3
  290. package/dist/pie-UPGHQEXC-C8RDLrEi.js +0 -3
  291. package/dist/pieDiagram-SKSYHLDU-BREEn_Sk.js +0 -167
  292. package/dist/pieDiagram-SKSYHLDU-BREEn_Sk.js.map +0 -1
  293. package/dist/quadrantDiagram-337W2JSQ-CcKc-h2o.js.map +0 -1
  294. package/dist/radar-KQ55EAFF-DhmvjiyN.js +0 -3
  295. package/dist/requirementDiagram-Z7DCOOCP-aPcaPduF.js.map +0 -1
  296. package/dist/sequenceDiagram-2WXFIKYE-D7Vh1Zld.js +0 -4112
  297. package/dist/sequenceDiagram-2WXFIKYE-D7Vh1Zld.js.map +0 -1
  298. package/dist/stateDiagram-RAJIS63D-DdiY5cf3.js +0 -220
  299. package/dist/stateDiagram-RAJIS63D-DdiY5cf3.js.map +0 -1
  300. package/dist/stateDiagram-v2-FVOUBMTO-CAWy0Pkh.js +0 -29
  301. package/dist/timeline-definition-YZTLITO2-CjxxCuOg.js.map +0 -1
  302. package/dist/treemap-KZPCXAKY-BvLvHb2t.js +0 -3
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@countermeasure-platform/web-components",
3
- "version": "1.2.1-dev.6.1",
3
+ "version": "1.2.2-dev.7.1",
4
4
  "description": "Shared web components for CounterMeasure applications - consolidates common frontend functionality across projects.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -4,6 +4,7 @@
4
4
  */
5
5
 
6
6
  import {
7
+ type BrandLockupConfig,
7
8
  type BrandSize,
8
9
  type ConnectorLogoConfig,
9
10
  type ConnectorLogoSize,
@@ -14,6 +15,7 @@ import { resolveContainer, uniqueId } from '../../primitives/utils'
14
15
 
15
16
  export type {
16
17
  BrandSize,
18
+ BrandLockupConfig,
17
19
  ConnectorLogoConfig,
18
20
  ConnectorLogoSize,
19
21
  DiamondConfig,
@@ -132,6 +134,23 @@ export class Wordmark {
132
134
  }
133
135
  }
134
136
 
137
+ export class BrandLockup {
138
+ public readonly el: HTMLSpanElement
139
+
140
+ constructor(config: BrandLockupConfig = {}) {
141
+ this.el = createBrandLockupElement(config)
142
+
143
+ if (config.container !== undefined) {
144
+ const parent = resolveContainer(config.container)
145
+ parent.appendChild(this.el)
146
+ }
147
+ }
148
+
149
+ destroy(): void {
150
+ this.el.remove()
151
+ }
152
+ }
153
+
135
154
  export class ConnectorLogo {
136
155
  public readonly el: HTMLSpanElement
137
156
 
@@ -230,6 +249,40 @@ export function createWordmarkSvg(config: WordmarkConfig = {}): SVGSVGElement {
230
249
  return svg
231
250
  }
232
251
 
252
+ export function createBrandLockupElement(config: BrandLockupConfig = {}): HTMLSpanElement {
253
+ const el = document.createElement('span')
254
+ el.id = uniqueId('cmm-brand-lockup')
255
+ el.className = buildBrandLockupClassName(config)
256
+
257
+ if (config.decorative === true) {
258
+ el.setAttribute('aria-hidden', 'true')
259
+ } else {
260
+ el.setAttribute('role', 'img')
261
+ el.setAttribute('aria-label', config.label ?? 'CounterMeasure')
262
+ }
263
+
264
+ el.appendChild(createDiamondSvg({ size: config.markSize ?? 22, decorative: true }))
265
+
266
+ if (config.showWordmark !== false) {
267
+ const wordmark = document.createElement('span')
268
+ wordmark.className = 'cmm-brand-lockup__wordmark'
269
+ wordmark.setAttribute('aria-hidden', 'true')
270
+
271
+ const counter = document.createElement('span')
272
+ counter.className = 'cmm-brand-lockup__counter'
273
+ counter.textContent = 'COUNTER'
274
+
275
+ const measure = document.createElement('span')
276
+ measure.className = 'cmm-brand-lockup__measure'
277
+ measure.textContent = 'MEASURE'
278
+
279
+ wordmark.append(counter, measure)
280
+ el.appendChild(wordmark)
281
+ }
282
+
283
+ return el
284
+ }
285
+
233
286
  export function getConnectorLogoColor(name: string): string {
234
287
  const paletteKey = getConnectorPaletteKey(name)
235
288
  return CONNECTOR_LOGO_PALETTE[paletteKey]
@@ -268,6 +321,16 @@ function buildWordmarkClassName(config: WordmarkConfig): string {
268
321
  return classes.join(' ')
269
322
  }
270
323
 
324
+ function buildBrandLockupClassName(config: BrandLockupConfig): string {
325
+ const classes = ['cmm-brand-lockup']
326
+
327
+ if (config.className) {
328
+ classes.push(config.className)
329
+ }
330
+
331
+ return classes.join(' ')
332
+ }
333
+
271
334
  function buildConnectorLogoClassName(config: ConnectorLogoConfig): string {
272
335
  const classes = [
273
336
  'cmm-connector-logo',
@@ -25,6 +25,15 @@ export interface WordmarkConfig {
25
25
  className?: string
26
26
  }
27
27
 
28
+ export interface BrandLockupConfig {
29
+ container?: HTMLElement | string
30
+ markSize?: BrandSize | number
31
+ label?: string
32
+ decorative?: boolean
33
+ showWordmark?: boolean
34
+ className?: string
35
+ }
36
+
28
37
  export interface ConnectorLogoConfig {
29
38
  container?: HTMLElement | string
30
39
  name: string
@@ -0,0 +1,28 @@
1
+ import { describe, expect, it } from 'vitest'
2
+ import { render } from '@testing-library/react'
3
+
4
+ import { BrandLockup, CounterMeasureBrandLockup } from './index'
5
+
6
+ describe('React brand lockup', () => {
7
+ it('renders the shared CounterMeasure lockup with split brand text', () => {
8
+ const { container } = render(<BrandLockup />)
9
+ const lockup = container.querySelector('.cmm-brand-lockup')
10
+
11
+ expect(lockup).toBeTruthy()
12
+ expect(lockup?.getAttribute('role')).toBe('img')
13
+ expect(lockup?.getAttribute('aria-label')).toBe('CounterMeasure')
14
+ expect(lockup?.querySelector('.cmm-diamond')).toBeTruthy()
15
+ expect(lockup?.textContent).toBe('COUNTERMEASURE')
16
+ expect(lockup?.querySelector('.cmm-brand-lockup__counter')?.textContent).toBe('COUNTER')
17
+ expect(lockup?.querySelector('.cmm-brand-lockup__measure')?.textContent).toBe('MEASURE')
18
+ })
19
+
20
+ it('can render mark-only for collapsed sidebars', () => {
21
+ const { container } = render(<CounterMeasureBrandLockup showWordmark={false} decorative />)
22
+ const lockup = container.querySelector('.cmm-brand-lockup')
23
+
24
+ expect(lockup?.getAttribute('aria-hidden')).toBe('true')
25
+ expect(lockup?.querySelector('.cmm-diamond')).toBeTruthy()
26
+ expect(lockup?.querySelector('.cmm-brand-lockup__wordmark')).toBeNull()
27
+ })
28
+ })
@@ -13,6 +13,7 @@ import {
13
13
  getConnectorLogoSizeClass,
14
14
  getConnectorLogoTone,
15
15
  type BrandSize,
16
+ type BrandLockupConfig,
16
17
  type ConnectorLogoSize,
17
18
  type WordmarkVariant,
18
19
  } from '../../components/brand'
@@ -159,6 +160,38 @@ export function Wordmark({
159
160
  )
160
161
  }
161
162
 
163
+ export interface BrandLockupProps extends React.HTMLAttributes<HTMLSpanElement> {
164
+ markSize?: BrandSize | number
165
+ label?: string
166
+ decorative?: boolean
167
+ showWordmark?: boolean
168
+ }
169
+
170
+ export function BrandLockup({
171
+ className,
172
+ markSize = 22,
173
+ label = 'CounterMeasure',
174
+ decorative = false,
175
+ showWordmark = true,
176
+ ...props
177
+ }: BrandLockupProps) {
178
+ const accessibilityProps = decorative
179
+ ? { 'aria-hidden': true }
180
+ : { role: 'img', 'aria-label': label }
181
+
182
+ return (
183
+ <span className={cn('cmm-brand-lockup', className)} {...accessibilityProps} {...props}>
184
+ <Diamond size={markSize} decorative />
185
+ {showWordmark ? (
186
+ <span className="cmm-brand-lockup__wordmark" aria-hidden="true">
187
+ <span className="cmm-brand-lockup__counter">COUNTER</span>
188
+ <span className="cmm-brand-lockup__measure">MEASURE</span>
189
+ </span>
190
+ ) : null}
191
+ </span>
192
+ )
193
+ }
194
+
162
195
  export interface ConnectorLogoProps extends React.HTMLAttributes<HTMLSpanElement> {
163
196
  name: string
164
197
  src?: string
@@ -211,8 +244,13 @@ export type CountermeasureLogoProps = DiamondProps
211
244
  export type CounterMeasureLogoProps = DiamondProps
212
245
  export type CountermeasureWordmarkProps = WordmarkProps
213
246
  export type CounterMeasureWordmarkProps = WordmarkProps
247
+ export type CountermeasureBrandLockupProps = BrandLockupProps
248
+ export type CounterMeasureBrandLockupProps = BrandLockupProps
249
+ export type { BrandLockupConfig }
214
250
 
215
251
  export const CountermeasureLogo = Diamond
216
252
  export const CounterMeasureLogo = Diamond
217
253
  export const CountermeasureWordmark = Wordmark
218
254
  export const CounterMeasureWordmark = Wordmark
255
+ export const CountermeasureBrandLockup = BrandLockup
256
+ export const CounterMeasureBrandLockup = BrandLockup
@@ -0,0 +1,30 @@
1
+ import { describe, expect, it } from 'vitest'
2
+ import { render } from '@testing-library/react'
3
+
4
+ import { SidebarCollapseButton } from './sidebar'
5
+
6
+ describe('SidebarCollapseButton', () => {
7
+ it('renders the shared edge-docked collapse control', () => {
8
+ const { container } = render(<SidebarCollapseButton edge />)
9
+ const button = container.querySelector('button')
10
+
11
+ expect(button).toBeTruthy()
12
+ expect(button?.getAttribute('aria-label')).toBe('Collapse sidebar')
13
+ expect(button?.getAttribute('aria-expanded')).toBe('true')
14
+ expect(button?.getAttribute('title')).toBe('Collapse sidebar')
15
+ expect(button?.classList.contains('sidebar__collapse-btn')).toBe(true)
16
+ expect(button?.classList.contains('sidebar__collapse-btn--edge')).toBe(true)
17
+ expect(button?.querySelector('path')?.getAttribute('d')).toBe('m15 18-6-6 6-6')
18
+ })
19
+
20
+ it('switches affordance metadata for collapsed sidebars', () => {
21
+ const { container } = render(<SidebarCollapseButton collapsed edge visible />)
22
+ const button = container.querySelector('button')
23
+
24
+ expect(button?.getAttribute('aria-label')).toBe('Expand sidebar')
25
+ expect(button?.getAttribute('aria-expanded')).toBe('false')
26
+ expect(button?.getAttribute('data-collapsed')).toBe('true')
27
+ expect(button?.getAttribute('data-visible')).toBe('true')
28
+ expect(button?.querySelector('path')?.getAttribute('d')).toBe('m9 18 6-6-6-6')
29
+ })
30
+ })
@@ -35,6 +35,14 @@ export interface SidebarProps extends Omit<
35
35
 
36
36
  export type { SidebarNavItem, SidebarSection, SidebarUser, SidebarFooterAction }
37
37
 
38
+ export interface SidebarCollapseButtonProps
39
+ extends React.ButtonHTMLAttributes<HTMLButtonElement> {
40
+ collapsed?: boolean
41
+ edge?: boolean
42
+ visible?: boolean
43
+ label?: string
44
+ }
45
+
38
46
  function Sidebar({ activeItemId, onNavigate, onCollapse, className, ...config }: SidebarProps) {
39
47
  const containerRef = React.useRef<HTMLDivElement>(null)
40
48
  const sidebarRef = React.useRef<SidebarComponent | null>(null)
@@ -73,4 +81,47 @@ function Sidebar({ activeItemId, onNavigate, onCollapse, className, ...config }:
73
81
 
74
82
  Sidebar.displayName = 'Sidebar'
75
83
 
76
- export { Sidebar }
84
+ function SidebarCollapseButton({
85
+ collapsed = false,
86
+ edge = false,
87
+ visible = false,
88
+ label,
89
+ className,
90
+ type = 'button',
91
+ children,
92
+ ...props
93
+ }: SidebarCollapseButtonProps) {
94
+ const resolvedLabel = label ?? (collapsed ? 'Expand sidebar' : 'Collapse sidebar')
95
+ const path = collapsed ? 'm9 18 6-6-6-6' : 'm15 18-6-6 6-6'
96
+
97
+ return (
98
+ <button
99
+ type={type}
100
+ className={cn('sidebar__collapse-btn', edge && 'sidebar__collapse-btn--edge', className)}
101
+ aria-label={resolvedLabel}
102
+ aria-expanded={!collapsed}
103
+ title={resolvedLabel}
104
+ data-collapsed={collapsed ? 'true' : 'false'}
105
+ data-visible={visible ? 'true' : undefined}
106
+ {...props}
107
+ >
108
+ {children ?? (
109
+ <svg
110
+ aria-hidden="true"
111
+ viewBox="0 0 24 24"
112
+ fill="none"
113
+ stroke="currentColor"
114
+ strokeWidth="2"
115
+ strokeLinecap="round"
116
+ strokeLinejoin="round"
117
+ >
118
+ <path d={path} />
119
+ </svg>
120
+ )}
121
+ </button>
122
+ )
123
+ }
124
+
125
+ SidebarCollapseButton.displayName = 'SidebarCollapseButton'
126
+
127
+ export { Sidebar, SidebarCollapseButton }
@@ -0,0 +1,109 @@
1
+ import { describe, expect, it, vi } from 'vitest'
2
+
3
+ import { SidebarComponent } from './component'
4
+
5
+ function createContainer(): HTMLElement {
6
+ const container = document.createElement('div')
7
+ container.style.height = '320px'
8
+ document.body.appendChild(container)
9
+ return container
10
+ }
11
+
12
+ describe('SidebarComponent', () => {
13
+ it('renders brand header, scroll body, and edge collapse control when configured', () => {
14
+ const container = createContainer()
15
+ const sidebar = new SidebarComponent({
16
+ container,
17
+ variant: 'product',
18
+ brand: { label: 'CounterMeasure' },
19
+ collapsible: true,
20
+ collapseButtonVisible: true,
21
+ sections: [
22
+ {
23
+ id: 'main',
24
+ label: 'Main',
25
+ items: [
26
+ { id: 'dashboard', label: 'Dashboard', icon: 'dashboard', badge: 3, badgeTone: 'amber' },
27
+ ],
28
+ },
29
+ ],
30
+ })
31
+
32
+ expect(container.querySelector('.sidebar')?.classList.contains('sidebar--product')).toBe(true)
33
+ expect(container.querySelector('.sidebar')?.getAttribute('data-sidebar')).toBe('product')
34
+ expect(container.querySelector('.sidebar__header .cmm-brand-lockup')).toBeTruthy()
35
+ expect(container.querySelector('.sidebar__body .sidebar__section')).toBeTruthy()
36
+ expect(container.querySelector('.sidebar__badge--amber')?.textContent).toBe('3')
37
+ expect(container.querySelector('.sidebar__item')?.getAttribute('data-badge-visible')).toBe('true')
38
+ expect(container.querySelector('.sidebar__item')?.getAttribute('data-badge-tone')).toBe('amber')
39
+
40
+ const collapseButton = container.querySelector<HTMLButtonElement>('.sidebar__collapse-btn--edge')
41
+ expect(collapseButton).toBeTruthy()
42
+ expect(collapseButton?.getAttribute('aria-label')).toBe('Collapse sidebar')
43
+ expect(collapseButton?.getAttribute('aria-expanded')).toBe('true')
44
+ expect(collapseButton?.getAttribute('data-visible')).toBe('true')
45
+
46
+ sidebar.destroy()
47
+ container.remove()
48
+ })
49
+
50
+ it('updates collapse control state and emits collapse callbacks', () => {
51
+ const container = createContainer()
52
+ const onCollapse = vi.fn()
53
+ const sidebar = new SidebarComponent({
54
+ container,
55
+ collapsible: true,
56
+ sections: [
57
+ {
58
+ id: 'main',
59
+ items: [{ id: 'dashboard', label: 'Dashboard' }],
60
+ },
61
+ ],
62
+ onCollapse,
63
+ })
64
+
65
+ const collapseButton = container.querySelector<HTMLButtonElement>('.sidebar__collapse-btn--edge')
66
+ collapseButton?.click()
67
+
68
+ expect(container.querySelector('.sidebar')?.classList.contains('sidebar--collapsed')).toBe(true)
69
+ expect(collapseButton?.getAttribute('aria-label')).toBe('Expand sidebar')
70
+ expect(collapseButton?.getAttribute('aria-expanded')).toBe('false')
71
+ expect(onCollapse).toHaveBeenCalledWith(true)
72
+
73
+ sidebar.expand()
74
+ expect(collapseButton?.getAttribute('aria-label')).toBe('Collapse sidebar')
75
+ expect(collapseButton?.getAttribute('aria-expanded')).toBe('true')
76
+ expect(onCollapse).toHaveBeenLastCalledWith(false)
77
+
78
+ sidebar.destroy()
79
+ container.remove()
80
+ })
81
+
82
+ it('updates compact badge-dot visibility state when badge counts change', () => {
83
+ const container = createContainer()
84
+ const sidebar = new SidebarComponent({
85
+ container,
86
+ sections: [
87
+ {
88
+ id: 'main',
89
+ items: [{ id: 'alerts', label: 'Alerts', badge: 5, badgeTone: 'rose' }],
90
+ },
91
+ ],
92
+ })
93
+
94
+ const item = container.querySelector<HTMLElement>('[data-item-id="alerts"]')
95
+ expect(item?.getAttribute('data-badge-visible')).toBe('true')
96
+ expect(item?.getAttribute('data-badge-tone')).toBe('rose')
97
+
98
+ sidebar.updateBadge('alerts', 0)
99
+ expect(item?.getAttribute('data-badge-visible')).toBe('false')
100
+ expect(container.querySelector('[data-badge="alerts"]')?.textContent).toBe('')
101
+
102
+ sidebar.updateBadge('alerts', 9)
103
+ expect(item?.getAttribute('data-badge-visible')).toBe('true')
104
+ expect(container.querySelector('[data-badge="alerts"]')?.textContent).toBe('9')
105
+
106
+ sidebar.destroy()
107
+ container.remove()
108
+ })
109
+ })
@@ -20,8 +20,14 @@
20
20
 
21
21
  import { getIconSvgInner, type IconSet } from '../icons/index'
22
22
  import { resolveContainer } from '../primitives/utils'
23
+ import { createBrandLockupElement } from '../components/brand'
23
24
  import { type SidebarComponentConfig } from './types'
24
25
 
26
+ function toSidebarVariantClassName(variant: string): string {
27
+ const normalized = variant.toLowerCase().replace(/[^a-z0-9]+/g, '-').replace(/^-|-$/g, '')
28
+ return `sidebar--${normalized || 'app'}`
29
+ }
30
+
25
31
  /** Create an SVG element populated with icon content from the registry. */
26
32
  function createIconSvg(iconSet: IconSet, name: string): SVGElement {
27
33
  const svgNs = 'http://www.w3.org/2000/svg'
@@ -52,6 +58,7 @@ export class SidebarComponent {
52
58
  private readonly aside: HTMLElement
53
59
  private readonly config: SidebarComponentConfig
54
60
  private readonly iconSet: IconSet
61
+ private collapseButton: HTMLButtonElement | null = null
55
62
 
56
63
  constructor(config: SidebarComponentConfig) {
57
64
  this.config = config
@@ -59,14 +66,24 @@ export class SidebarComponent {
59
66
  this.iconSet = config.iconSet ?? 'lucide'
60
67
 
61
68
  this.aside = document.createElement('aside')
62
- this.aside.classList.add('sidebar')
63
- this.aside.setAttribute('data-sidebar', config.variant ?? 'app')
69
+ const variant = config.variant ?? 'app'
70
+ this.aside.classList.add('sidebar', toSidebarVariantClassName(variant))
71
+ this.aside.setAttribute('data-sidebar', variant)
64
72
 
65
73
  this.render()
66
74
  this.container.appendChild(this.aside)
67
75
  }
68
76
 
69
77
  private render(): void {
78
+ if (this.config.collapsible === true) {
79
+ this.renderCollapseButton()
80
+ }
81
+
82
+ this.renderHeader()
83
+
84
+ const body = document.createElement('div')
85
+ body.classList.add('sidebar__body')
86
+
70
87
  for (const section of this.config.sections) {
71
88
  const sectionEl = document.createElement('div')
72
89
  sectionEl.classList.add('sidebar__section')
@@ -82,6 +99,7 @@ export class SidebarComponent {
82
99
  const link = document.createElement('a')
83
100
  link.classList.add('sidebar__item')
84
101
  link.setAttribute('data-item-id', item.id)
102
+ link.setAttribute('title', item.label)
85
103
 
86
104
  if (item.icon) {
87
105
  const icon = createIconSvg(this.iconSet, item.icon)
@@ -95,7 +113,10 @@ export class SidebarComponent {
95
113
 
96
114
  if (item.badge !== undefined && item.badge > 0) {
97
115
  const badge = document.createElement('span')
98
- badge.classList.add('sidebar__badge')
116
+ const tone = item.badgeTone ?? 'primary'
117
+ link.setAttribute('data-badge-visible', 'true')
118
+ link.setAttribute('data-badge-tone', tone)
119
+ badge.classList.add('sidebar__badge', `sidebar__badge--${tone}`)
99
120
  badge.setAttribute('data-badge', item.id)
100
121
  badge.textContent = String(item.badge)
101
122
  link.appendChild(badge)
@@ -113,12 +134,94 @@ export class SidebarComponent {
113
134
  sectionEl.appendChild(link)
114
135
  }
115
136
 
116
- this.aside.appendChild(sectionEl)
137
+ body.appendChild(sectionEl)
117
138
  }
118
139
 
140
+ this.aside.appendChild(body)
119
141
  this.renderFooter()
120
142
  }
121
143
 
144
+ private renderHeader(): void {
145
+ const brand = this.config.brand
146
+ if (brand === undefined) {
147
+ return
148
+ }
149
+
150
+ const header = document.createElement('div')
151
+ header.classList.add('sidebar__header')
152
+
153
+ const row = document.createElement('div')
154
+ row.classList.add('sidebar__header-row')
155
+
156
+ const brandEl =
157
+ brand.href !== undefined
158
+ ? document.createElement('a')
159
+ : brand.onClick !== undefined
160
+ ? document.createElement('button')
161
+ : document.createElement('span')
162
+
163
+ brandEl.classList.add('sidebar__brand')
164
+
165
+ if (brandEl instanceof HTMLAnchorElement) {
166
+ brandEl.href = brand.href ?? '#'
167
+ brandEl.setAttribute('aria-label', brand.label ?? 'CounterMeasure')
168
+ }
169
+
170
+ if (brandEl instanceof HTMLButtonElement) {
171
+ brandEl.type = 'button'
172
+ brandEl.setAttribute('aria-label', brand.label ?? 'CounterMeasure')
173
+ }
174
+
175
+ if (brand.onClick !== undefined) {
176
+ brandEl.addEventListener('click', brand.onClick)
177
+ }
178
+
179
+ brandEl.appendChild(
180
+ createBrandLockupElement({
181
+ label: brand.label ?? 'CounterMeasure',
182
+ markSize: brand.markSize ?? 22,
183
+ showWordmark: brand.showWordmark ?? true,
184
+ decorative: brand.decorative ?? false,
185
+ })
186
+ )
187
+
188
+ row.appendChild(brandEl)
189
+ header.appendChild(row)
190
+ this.aside.appendChild(header)
191
+ }
192
+
193
+ private renderCollapseButton(): void {
194
+ const button = document.createElement('button')
195
+ button.type = 'button'
196
+ button.classList.add('sidebar__collapse-btn', 'sidebar__collapse-btn--edge')
197
+ button.setAttribute('data-sidebar-toggle', '')
198
+
199
+ if (this.config.collapseButtonVisible === true) {
200
+ button.setAttribute('data-visible', 'true')
201
+ }
202
+
203
+ const svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg')
204
+ svg.setAttribute('aria-hidden', 'true')
205
+ svg.setAttribute('viewBox', '0 0 24 24')
206
+ svg.setAttribute('fill', 'none')
207
+ svg.setAttribute('stroke', 'currentColor')
208
+ svg.setAttribute('stroke-width', '2')
209
+ svg.setAttribute('stroke-linecap', 'round')
210
+ svg.setAttribute('stroke-linejoin', 'round')
211
+
212
+ const path = document.createElementNS('http://www.w3.org/2000/svg', 'path')
213
+ svg.appendChild(path)
214
+ button.appendChild(svg)
215
+
216
+ button.addEventListener('click', () => {
217
+ this.toggleCollapse()
218
+ })
219
+
220
+ this.collapseButton = button
221
+ this.updateCollapseButton()
222
+ this.aside.appendChild(button)
223
+ }
224
+
122
225
  private renderFooter(): void {
123
226
  const hasUser = this.config.user !== undefined
124
227
  const hasActions =
@@ -195,12 +298,15 @@ export class SidebarComponent {
195
298
  const badge = this.aside.querySelector<HTMLElement>(`[data-badge="${itemId}"]`)
196
299
  if (badge) {
197
300
  badge.textContent = count > 0 ? String(count) : ''
301
+ const item = badge.closest<HTMLElement>('.sidebar__item')
302
+ item?.setAttribute('data-badge-visible', String(count > 0))
198
303
  }
199
304
  }
200
305
 
201
306
  /** Toggle the sidebar between collapsed and expanded states. */
202
307
  toggleCollapse(): void {
203
308
  const isCollapsed = this.aside.classList.toggle('sidebar--collapsed')
309
+ this.updateCollapseButton()
204
310
  if (this.config.onCollapse) {
205
311
  this.config.onCollapse(isCollapsed)
206
312
  }
@@ -208,16 +314,42 @@ export class SidebarComponent {
208
314
 
209
315
  /** Collapse the sidebar. */
210
316
  collapse(): void {
317
+ const wasCollapsed = this.aside.classList.contains('sidebar--collapsed')
211
318
  this.aside.classList.add('sidebar--collapsed')
319
+ this.updateCollapseButton()
320
+ if (!wasCollapsed && this.config.onCollapse) {
321
+ this.config.onCollapse(true)
322
+ }
212
323
  }
213
324
 
214
325
  /** Expand the sidebar. */
215
326
  expand(): void {
327
+ const wasCollapsed = this.aside.classList.contains('sidebar--collapsed')
216
328
  this.aside.classList.remove('sidebar--collapsed')
329
+ this.updateCollapseButton()
330
+ if (wasCollapsed && this.config.onCollapse) {
331
+ this.config.onCollapse(false)
332
+ }
217
333
  }
218
334
 
219
335
  /** Remove the sidebar from the DOM. */
220
336
  destroy(): void {
221
337
  this.aside.remove()
222
338
  }
339
+
340
+ private updateCollapseButton(): void {
341
+ if (this.collapseButton === null) {
342
+ return
343
+ }
344
+
345
+ const isCollapsed = this.aside.classList.contains('sidebar--collapsed')
346
+ const label = isCollapsed ? 'Expand sidebar' : 'Collapse sidebar'
347
+ this.collapseButton.setAttribute('aria-label', label)
348
+ this.collapseButton.setAttribute('aria-expanded', String(!isCollapsed))
349
+ this.collapseButton.setAttribute('title', label)
350
+ this.collapseButton.setAttribute('data-collapsed', String(isCollapsed))
351
+ this.collapseButton
352
+ .querySelector('path')
353
+ ?.setAttribute('d', isCollapsed ? 'm9 18 6-6-6-6' : 'm15 18-6-6 6-6')
354
+ }
223
355
  }
@@ -15,6 +15,7 @@
15
15
  export { SidebarComponent } from './component'
16
16
  export type {
17
17
  SidebarComponentConfig,
18
+ SidebarBrandConfig,
18
19
  SidebarNavItem,
19
20
  SidebarSection,
20
21
  SidebarUser,