@wallarm-org/claude-design 0.0.0-stage → 4.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (963) hide show
  1. package/README.md +114 -2
  2. package/bin/claude-design.js +347 -0
  3. package/dist/SETUP.md +130 -0
  4. package/dist/UPDATE.md +84 -0
  5. package/dist/assets/Icons/activity.svg +1 -0
  6. package/dist/assets/Icons/alt.svg +1 -0
  7. package/dist/assets/Icons/android-neutral.svg +1 -0
  8. package/dist/assets/Icons/android.svg +1 -0
  9. package/dist/assets/Icons/api.svg +1 -0
  10. package/dist/assets/Icons/apple-music-neutral.svg +1 -0
  11. package/dist/assets/Icons/apple-music.svg +1 -0
  12. package/dist/assets/Icons/apple-neutral.svg +1 -0
  13. package/dist/assets/Icons/apple-podcasts-neutral.svg +1 -0
  14. package/dist/assets/Icons/apple-podcasts.svg +1 -0
  15. package/dist/assets/Icons/apple.svg +1 -0
  16. package/dist/assets/Icons/archive.svg +1 -0
  17. package/dist/assets/Icons/arrow-big-up-dash.svg +1 -0
  18. package/dist/assets/Icons/arrow-big-up.svg +1 -0
  19. package/dist/assets/Icons/arrow-down-left.svg +1 -0
  20. package/dist/assets/Icons/arrow-down-right.svg +1 -0
  21. package/dist/assets/Icons/arrow-down.svg +1 -0
  22. package/dist/assets/Icons/arrow-left.svg +1 -0
  23. package/dist/assets/Icons/arrow-right-alt.svg +1 -0
  24. package/dist/assets/Icons/arrow-right.svg +1 -0
  25. package/dist/assets/Icons/arrow-up-down.svg +1 -0
  26. package/dist/assets/Icons/arrow-up-left.svg +1 -0
  27. package/dist/assets/Icons/arrow-up-right.svg +1 -0
  28. package/dist/assets/Icons/arrow-up.svg +1 -0
  29. package/dist/assets/Icons/artstation-neutral.svg +1 -0
  30. package/dist/assets/Icons/artstation.svg +1 -0
  31. package/dist/assets/Icons/asterisk.svg +1 -0
  32. package/dist/assets/Icons/audio-waveform.svg +1 -0
  33. package/dist/assets/Icons/aws-neutral.svg +1 -0
  34. package/dist/assets/Icons/aws.svg +1 -0
  35. package/dist/assets/Icons/badge-check.svg +1 -0
  36. package/dist/assets/Icons/baidu-neutral.svg +1 -0
  37. package/dist/assets/Icons/baidu.svg +1 -0
  38. package/dist/assets/Icons/bandage.svg +1 -0
  39. package/dist/assets/Icons/behance-neutral.svg +1 -0
  40. package/dist/assets/Icons/behance.svg +1 -0
  41. package/dist/assets/Icons/bell-cog.svg +1 -0
  42. package/dist/assets/Icons/bell.svg +1 -0
  43. package/dist/assets/Icons/binary.svg +1 -0
  44. package/dist/assets/Icons/book-open.svg +1 -0
  45. package/dist/assets/Icons/book.svg +1 -0
  46. package/dist/assets/Icons/boosty-neutral.svg +1 -0
  47. package/dist/assets/Icons/boosty.svg +1 -0
  48. package/dist/assets/Icons/bot.svg +1 -0
  49. package/dist/assets/Icons/brain.svg +1 -0
  50. package/dist/assets/Icons/braze-neutral.svg +1 -0
  51. package/dist/assets/Icons/braze.svg +1 -0
  52. package/dist/assets/Icons/brevo-neutral.svg +1 -0
  53. package/dist/assets/Icons/brevo.svg +1 -0
  54. package/dist/assets/Icons/bug-off.svg +1 -0
  55. package/dist/assets/Icons/bug-play.svg +1 -0
  56. package/dist/assets/Icons/bug.svg +1 -0
  57. package/dist/assets/Icons/building.svg +1 -0
  58. package/dist/assets/Icons/building2.svg +1 -0
  59. package/dist/assets/Icons/calendar-check.svg +1 -0
  60. package/dist/assets/Icons/calendar-check2.svg +1 -0
  61. package/dist/assets/Icons/calendar-clock.svg +1 -0
  62. package/dist/assets/Icons/calendar-cog.svg +1 -0
  63. package/dist/assets/Icons/calendar-days.svg +1 -0
  64. package/dist/assets/Icons/calendar-fold.svg +1 -0
  65. package/dist/assets/Icons/calendar-heart.svg +1 -0
  66. package/dist/assets/Icons/calendar-minus.svg +1 -0
  67. package/dist/assets/Icons/calendar-minus2.svg +1 -0
  68. package/dist/assets/Icons/calendar-off.svg +1 -0
  69. package/dist/assets/Icons/calendar-plus.svg +1 -0
  70. package/dist/assets/Icons/calendar-plus2.svg +1 -0
  71. package/dist/assets/Icons/calendar-range.svg +1 -0
  72. package/dist/assets/Icons/calendar-search.svg +1 -0
  73. package/dist/assets/Icons/calendar-x.svg +1 -0
  74. package/dist/assets/Icons/calendar-x2.svg +1 -0
  75. package/dist/assets/Icons/calendar.svg +1 -0
  76. package/dist/assets/Icons/chart-area.svg +1 -0
  77. package/dist/assets/Icons/chart-bar.svg +1 -0
  78. package/dist/assets/Icons/chart-column.svg +1 -0
  79. package/dist/assets/Icons/chart-no-axes-column.svg +1 -0
  80. package/dist/assets/Icons/check-check.svg +1 -0
  81. package/dist/assets/Icons/check.svg +1 -0
  82. package/dist/assets/Icons/checkbox-indeterminate.svg +1 -0
  83. package/dist/assets/Icons/chevron-down.svg +1 -0
  84. package/dist/assets/Icons/chevron-first.svg +1 -0
  85. package/dist/assets/Icons/chevron-last.svg +1 -0
  86. package/dist/assets/Icons/chevron-left.svg +1 -0
  87. package/dist/assets/Icons/chevron-right.svg +1 -0
  88. package/dist/assets/Icons/chevron-up-down.svg +1 -0
  89. package/dist/assets/Icons/chevron-up.svg +1 -0
  90. package/dist/assets/Icons/chevrons-down-up.svg +1 -0
  91. package/dist/assets/Icons/chevrons-down.svg +1 -0
  92. package/dist/assets/Icons/chevrons-left-right.svg +1 -0
  93. package/dist/assets/Icons/chevrons-left.svg +1 -0
  94. package/dist/assets/Icons/chevrons-right-left.svg +1 -0
  95. package/dist/assets/Icons/chevrons-right.svg +1 -0
  96. package/dist/assets/Icons/chevrons-up-down.svg +1 -0
  97. package/dist/assets/Icons/chevrons-up.svg +1 -0
  98. package/dist/assets/Icons/circle-arrow-down.svg +1 -0
  99. package/dist/assets/Icons/circle-arrow-left.svg +1 -0
  100. package/dist/assets/Icons/circle-arrow-out-down-left.svg +1 -0
  101. package/dist/assets/Icons/circle-arrow-out-down-right.svg +1 -0
  102. package/dist/assets/Icons/circle-arrow-out-up-left.svg +1 -0
  103. package/dist/assets/Icons/circle-arrow-out-up-right.svg +1 -0
  104. package/dist/assets/Icons/circle-arrow-right.svg +1 -0
  105. package/dist/assets/Icons/circle-arrow-up.svg +1 -0
  106. package/dist/assets/Icons/circle-check-big.svg +1 -0
  107. package/dist/assets/Icons/circle-check.svg +1 -0
  108. package/dist/assets/Icons/circle-chevron-down.svg +1 -0
  109. package/dist/assets/Icons/circle-chevron-left.svg +1 -0
  110. package/dist/assets/Icons/circle-chevron-right.svg +1 -0
  111. package/dist/assets/Icons/circle-chevron-up.svg +1 -0
  112. package/dist/assets/Icons/circle-dashed.svg +1 -0
  113. package/dist/assets/Icons/circle-dot-dashed.svg +1 -0
  114. package/dist/assets/Icons/circle-ellipsis.svg +1 -0
  115. package/dist/assets/Icons/circle-gauge.svg +1 -0
  116. package/dist/assets/Icons/circle-help.svg +1 -0
  117. package/dist/assets/Icons/circle-minus.svg +1 -0
  118. package/dist/assets/Icons/circle-plus.svg +1 -0
  119. package/dist/assets/Icons/circle-slash.svg +1 -0
  120. package/dist/assets/Icons/circle-slash2.svg +1 -0
  121. package/dist/assets/Icons/circle-stop.svg +1 -0
  122. package/dist/assets/Icons/circle.svg +1 -0
  123. package/dist/assets/Icons/clipboard-check.svg +1 -0
  124. package/dist/assets/Icons/clipboard-x.svg +1 -0
  125. package/dist/assets/Icons/clipboard.svg +1 -0
  126. package/dist/assets/Icons/clock-fading.svg +1 -0
  127. package/dist/assets/Icons/clock.svg +1 -0
  128. package/dist/assets/Icons/cloud-off.svg +1 -0
  129. package/dist/assets/Icons/cloud-sync.svg +1 -0
  130. package/dist/assets/Icons/cloud.svg +1 -0
  131. package/dist/assets/Icons/code.svg +1 -0
  132. package/dist/assets/Icons/collapse.svg +1 -0
  133. package/dist/assets/Icons/columns3-cog.svg +1 -0
  134. package/dist/assets/Icons/command.svg +1 -0
  135. package/dist/assets/Icons/compass.svg +1 -0
  136. package/dist/assets/Icons/copy-slash.svg +1 -0
  137. package/dist/assets/Icons/copy.svg +1 -0
  138. package/dist/assets/Icons/corner-down-left.svg +1 -0
  139. package/dist/assets/Icons/corner-down-right.svg +1 -0
  140. package/dist/assets/Icons/corner-left-down.svg +1 -0
  141. package/dist/assets/Icons/corner-left-up.svg +1 -0
  142. package/dist/assets/Icons/corner-right-down.svg +1 -0
  143. package/dist/assets/Icons/corner-right-up.svg +1 -0
  144. package/dist/assets/Icons/corner-up-left.svg +1 -0
  145. package/dist/assets/Icons/corner-up-right.svg +1 -0
  146. package/dist/assets/Icons/cpu.svg +1 -0
  147. package/dist/assets/Icons/credit-card.svg +1 -0
  148. package/dist/assets/Icons/crosshair.svg +1 -0
  149. package/dist/assets/Icons/ctrl.svg +1 -0
  150. package/dist/assets/Icons/database.svg +1 -0
  151. package/dist/assets/Icons/devianart-neutral.svg +1 -0
  152. package/dist/assets/Icons/devianart.svg +1 -0
  153. package/dist/assets/Icons/discord-neutral.svg +1 -0
  154. package/dist/assets/Icons/discord.svg +1 -0
  155. package/dist/assets/Icons/dollar-sign.svg +1 -0
  156. package/dist/assets/Icons/dot.svg +1 -0
  157. package/dist/assets/Icons/download.svg +1 -0
  158. package/dist/assets/Icons/dprofile-neutral.svg +1 -0
  159. package/dist/assets/Icons/dprofile.svg +1 -0
  160. package/dist/assets/Icons/dribbble-neutral.svg +1 -0
  161. package/dist/assets/Icons/dribbble.svg +1 -0
  162. package/dist/assets/Icons/droplet.svg +1 -0
  163. package/dist/assets/Icons/duplicate.svg +1 -0
  164. package/dist/assets/Icons/dzen-neutral.svg +1 -0
  165. package/dist/assets/Icons/dzen.svg +1 -0
  166. package/dist/assets/Icons/earth-lock.svg +1 -0
  167. package/dist/assets/Icons/earth.svg +1 -0
  168. package/dist/assets/Icons/ellipsis.svg +1 -0
  169. package/dist/assets/Icons/expand.svg +1 -0
  170. package/dist/assets/Icons/external-link.svg +1 -0
  171. package/dist/assets/Icons/eye-off.svg +1 -0
  172. package/dist/assets/Icons/eye.svg +1 -0
  173. package/dist/assets/Icons/facebook-neutral.svg +1 -0
  174. package/dist/assets/Icons/facebook.svg +1 -0
  175. package/dist/assets/Icons/fast-forward.svg +1 -0
  176. package/dist/assets/Icons/figma-neutral.svg +1 -0
  177. package/dist/assets/Icons/figma.svg +1 -0
  178. package/dist/assets/Icons/file-down.svg +1 -0
  179. package/dist/assets/Icons/file-plus.svg +1 -0
  180. package/dist/assets/Icons/file-text.svg +1 -0
  181. package/dist/assets/Icons/file.svg +1 -0
  182. package/dist/assets/Icons/film.svg +1 -0
  183. package/dist/assets/Icons/filter-x.svg +1 -0
  184. package/dist/assets/Icons/filter.svg +1 -0
  185. package/dist/assets/Icons/fingerprint-pattern.svg +1 -0
  186. package/dist/assets/Icons/flag.svg +1 -0
  187. package/dist/assets/Icons/flask-conical.svg +1 -0
  188. package/dist/assets/Icons/folder.svg +1 -0
  189. package/dist/assets/Icons/funnel-plus.svg +1 -0
  190. package/dist/assets/Icons/ghost.svg +1 -0
  191. package/dist/assets/Icons/git-branch.svg +1 -0
  192. package/dist/assets/Icons/git-commit-horizontal.svg +1 -0
  193. package/dist/assets/Icons/git-commit-vertical.svg +1 -0
  194. package/dist/assets/Icons/git-compare-arrows-alt.svg +1 -0
  195. package/dist/assets/Icons/git-compare-arrows.svg +1 -0
  196. package/dist/assets/Icons/git-compare.svg +1 -0
  197. package/dist/assets/Icons/git-fork.svg +1 -0
  198. package/dist/assets/Icons/git-graph.svg +1 -0
  199. package/dist/assets/Icons/git-merge.svg +1 -0
  200. package/dist/assets/Icons/git-pull-request-arrow.svg +1 -0
  201. package/dist/assets/Icons/git-pull-request-closed.svg +1 -0
  202. package/dist/assets/Icons/git-pull-request-create-arrow.svg +1 -0
  203. package/dist/assets/Icons/git-pull-request-create.svg +1 -0
  204. package/dist/assets/Icons/git-pull-request-draft.svg +1 -0
  205. package/dist/assets/Icons/git-pull-request.svg +1 -0
  206. package/dist/assets/Icons/github-neutral.svg +1 -0
  207. package/dist/assets/Icons/github.svg +1 -0
  208. package/dist/assets/Icons/globe-lock.svg +1 -0
  209. package/dist/assets/Icons/globe.svg +1 -0
  210. package/dist/assets/Icons/gmail-neutral.svg +1 -0
  211. package/dist/assets/Icons/gmail.svg +1 -0
  212. package/dist/assets/Icons/google-meet-neutral.svg +1 -0
  213. package/dist/assets/Icons/google-meet.svg +1 -0
  214. package/dist/assets/Icons/google-neutral.svg +1 -0
  215. package/dist/assets/Icons/google-play-neutral.svg +1 -0
  216. package/dist/assets/Icons/google-play.svg +1 -0
  217. package/dist/assets/Icons/google-podcast-neutral.svg +1 -0
  218. package/dist/assets/Icons/google-podcast.svg +1 -0
  219. package/dist/assets/Icons/google.svg +1 -0
  220. package/dist/assets/Icons/grip-horizontal.svg +1 -0
  221. package/dist/assets/Icons/grip-vertical.svg +1 -0
  222. package/dist/assets/Icons/hammer.svg +1 -0
  223. package/dist/assets/Icons/heart-pulse.svg +1 -0
  224. package/dist/assets/Icons/history.svg +1 -0
  225. package/dist/assets/Icons/home.svg +1 -0
  226. package/dist/assets/Icons/imo-neutral.svg +1 -0
  227. package/dist/assets/Icons/imo.svg +1 -0
  228. package/dist/assets/Icons/infinity.svg +1 -0
  229. package/dist/assets/Icons/info.svg +1 -0
  230. package/dist/assets/Icons/infobip-neutral.svg +1 -0
  231. package/dist/assets/Icons/infobip.svg +1 -0
  232. package/dist/assets/Icons/instagram-neutral.svg +1 -0
  233. package/dist/assets/Icons/instagram.svg +1 -0
  234. package/dist/assets/Icons/key-round.svg +1 -0
  235. package/dist/assets/Icons/key-square.svg +1 -0
  236. package/dist/assets/Icons/keyboard.svg +1 -0
  237. package/dist/assets/Icons/kickstarter-neutral.svg +1 -0
  238. package/dist/assets/Icons/kickstarter.svg +1 -0
  239. package/dist/assets/Icons/laptop.svg +1 -0
  240. package/dist/assets/Icons/layers.svg +1 -0
  241. package/dist/assets/Icons/layers2.svg +1 -0
  242. package/dist/assets/Icons/layers3.svg +1 -0
  243. package/dist/assets/Icons/layout-dashboard.svg +1 -0
  244. package/dist/assets/Icons/layout-grid.svg +1 -0
  245. package/dist/assets/Icons/layout-list.svg +1 -0
  246. package/dist/assets/Icons/layout-panel-left.svg +1 -0
  247. package/dist/assets/Icons/layout-panel-top.svg +1 -0
  248. package/dist/assets/Icons/layout-template.svg +1 -0
  249. package/dist/assets/Icons/library-big.svg +1 -0
  250. package/dist/assets/Icons/life-buoy.svg +1 -0
  251. package/dist/assets/Icons/lightbulb-off.svg +1 -0
  252. package/dist/assets/Icons/lightbulb.svg +1 -0
  253. package/dist/assets/Icons/line-neutral.svg +1 -0
  254. package/dist/assets/Icons/line.svg +1 -0
  255. package/dist/assets/Icons/link.svg +1 -0
  256. package/dist/assets/Icons/link2-off.svg +1 -0
  257. package/dist/assets/Icons/link2.svg +1 -0
  258. package/dist/assets/Icons/linkedin-neutral.svg +1 -0
  259. package/dist/assets/Icons/linkedin.svg +1 -0
  260. package/dist/assets/Icons/list-checks.svg +1 -0
  261. package/dist/assets/Icons/list-collapse.svg +1 -0
  262. package/dist/assets/Icons/list-filter.svg +1 -0
  263. package/dist/assets/Icons/list-minus.svg +1 -0
  264. package/dist/assets/Icons/list-ordered.svg +1 -0
  265. package/dist/assets/Icons/list-plus.svg +1 -0
  266. package/dist/assets/Icons/list-restart.svg +1 -0
  267. package/dist/assets/Icons/list-start.svg +1 -0
  268. package/dist/assets/Icons/list-todo.svg +1 -0
  269. package/dist/assets/Icons/list-tree.svg +1 -0
  270. package/dist/assets/Icons/list-video.svg +1 -0
  271. package/dist/assets/Icons/list-x.svg +1 -0
  272. package/dist/assets/Icons/list.svg +1 -0
  273. package/dist/assets/Icons/loader-circle.svg +1 -0
  274. package/dist/assets/Icons/loader.svg +1 -0
  275. package/dist/assets/Icons/lock-open.svg +1 -0
  276. package/dist/assets/Icons/lock.svg +1 -0
  277. package/dist/assets/Icons/log-in.svg +1 -0
  278. package/dist/assets/Icons/log-out.svg +1 -0
  279. package/dist/assets/Icons/mail-check.svg +1 -0
  280. package/dist/assets/Icons/mail-minus.svg +1 -0
  281. package/dist/assets/Icons/mail-open.svg +1 -0
  282. package/dist/assets/Icons/mail-plus.svg +1 -0
  283. package/dist/assets/Icons/mail-question.svg +1 -0
  284. package/dist/assets/Icons/mail-search.svg +1 -0
  285. package/dist/assets/Icons/mail-warning.svg +1 -0
  286. package/dist/assets/Icons/mail-x.svg +1 -0
  287. package/dist/assets/Icons/mail.svg +1 -0
  288. package/dist/assets/Icons/mailbox.svg +1 -0
  289. package/dist/assets/Icons/mailersend-neutral.svg +1 -0
  290. package/dist/assets/Icons/mailersend.svg +1 -0
  291. package/dist/assets/Icons/mailgun-neutral.svg +1 -0
  292. package/dist/assets/Icons/mailgun.svg +1 -0
  293. package/dist/assets/Icons/mailjet-neutral.svg +1 -0
  294. package/dist/assets/Icons/mailjet.svg +1 -0
  295. package/dist/assets/Icons/mails.svg +1 -0
  296. package/dist/assets/Icons/mailtrap-neutral.svg +1 -0
  297. package/dist/assets/Icons/mailtrap.svg +1 -0
  298. package/dist/assets/Icons/mandrill-neutral.svg +1 -0
  299. package/dist/assets/Icons/mandrill.svg +1 -0
  300. package/dist/assets/Icons/map-pin.svg +1 -0
  301. package/dist/assets/Icons/maqsam-neutral.svg +1 -0
  302. package/dist/assets/Icons/maqsam.svg +1 -0
  303. package/dist/assets/Icons/mattermost-neutral.svg +1 -0
  304. package/dist/assets/Icons/mattermost.svg +1 -0
  305. package/dist/assets/Icons/maximize.svg +1 -0
  306. package/dist/assets/Icons/maximize2.svg +1 -0
  307. package/dist/assets/Icons/medium-neutral.svg +1 -0
  308. package/dist/assets/Icons/medium.svg +1 -0
  309. package/dist/assets/Icons/megaphone-off.svg +1 -0
  310. package/dist/assets/Icons/megaphone.svg +1 -0
  311. package/dist/assets/Icons/menu.svg +1 -0
  312. package/dist/assets/Icons/merge.svg +1 -0
  313. package/dist/assets/Icons/message-square-code.svg +1 -0
  314. package/dist/assets/Icons/message-square-dashed.svg +1 -0
  315. package/dist/assets/Icons/message-square-diff.svg +1 -0
  316. package/dist/assets/Icons/message-square-dot.svg +1 -0
  317. package/dist/assets/Icons/message-square-heart.svg +1 -0
  318. package/dist/assets/Icons/message-square-off.svg +1 -0
  319. package/dist/assets/Icons/message-square-plus.svg +1 -0
  320. package/dist/assets/Icons/message-square-quote.svg +1 -0
  321. package/dist/assets/Icons/message-square-reply.svg +1 -0
  322. package/dist/assets/Icons/message-square-share.svg +1 -0
  323. package/dist/assets/Icons/message-square-text.svg +1 -0
  324. package/dist/assets/Icons/message-square-warning.svg +1 -0
  325. package/dist/assets/Icons/message-square-x.svg +1 -0
  326. package/dist/assets/Icons/message-square.svg +1 -0
  327. package/dist/assets/Icons/messages-square.svg +1 -0
  328. package/dist/assets/Icons/messenger-neutral.svg +1 -0
  329. package/dist/assets/Icons/messenger.svg +1 -0
  330. package/dist/assets/Icons/microsoft-neutral.svg +1 -0
  331. package/dist/assets/Icons/microsoft-teams-neutral.svg +1 -0
  332. package/dist/assets/Icons/microsoft-teams.svg +1 -0
  333. package/dist/assets/Icons/microsoft.svg +1 -0
  334. package/dist/assets/Icons/minimize.svg +1 -0
  335. package/dist/assets/Icons/minimize2.svg +1 -0
  336. package/dist/assets/Icons/minus.svg +1 -0
  337. package/dist/assets/Icons/moon.svg +1 -0
  338. package/dist/assets/Icons/mouse-pointer-ban.svg +1 -0
  339. package/dist/assets/Icons/mouse-pointer-click.svg +1 -0
  340. package/dist/assets/Icons/mouse-pointer.svg +1 -0
  341. package/dist/assets/Icons/mouse-pointer2.svg +1 -0
  342. package/dist/assets/Icons/mouse.svg +1 -0
  343. package/dist/assets/Icons/move-diagonal.svg +1 -0
  344. package/dist/assets/Icons/move-diagonal2.svg +1 -0
  345. package/dist/assets/Icons/move-down-left.svg +1 -0
  346. package/dist/assets/Icons/move-down-right.svg +1 -0
  347. package/dist/assets/Icons/move-down.svg +1 -0
  348. package/dist/assets/Icons/move-horizontal.svg +1 -0
  349. package/dist/assets/Icons/move-left.svg +1 -0
  350. package/dist/assets/Icons/move-right.svg +1 -0
  351. package/dist/assets/Icons/move-up-left.svg +1 -0
  352. package/dist/assets/Icons/move-up-right.svg +1 -0
  353. package/dist/assets/Icons/move-up.svg +1 -0
  354. package/dist/assets/Icons/move-vertical.svg +1 -0
  355. package/dist/assets/Icons/move3-d.svg +1 -0
  356. package/dist/assets/Icons/netcore-neutral.svg +1 -0
  357. package/dist/assets/Icons/netcore.svg +1 -0
  358. package/dist/assets/Icons/notebook-pen.svg +1 -0
  359. package/dist/assets/Icons/notebook-tabs.svg +1 -0
  360. package/dist/assets/Icons/notebook-text.svg +1 -0
  361. package/dist/assets/Icons/notebook.svg +1 -0
  362. package/dist/assets/Icons/notepad-text-dashed.svg +1 -0
  363. package/dist/assets/Icons/notepad-text.svg +1 -0
  364. package/dist/assets/Icons/notion-neutral.svg +1 -0
  365. package/dist/assets/Icons/notion.svg +1 -0
  366. package/dist/assets/Icons/octagon-alert.svg +1 -0
  367. package/dist/assets/Icons/octagon-pause.svg +1 -0
  368. package/dist/assets/Icons/octagon-x.svg +1 -0
  369. package/dist/assets/Icons/octagon.svg +1 -0
  370. package/dist/assets/Icons/ok-neutral.svg +1 -0
  371. package/dist/assets/Icons/ok-only-sign-neutral.svg +1 -0
  372. package/dist/assets/Icons/ok-only-sign.svg +1 -0
  373. package/dist/assets/Icons/ok.svg +1 -0
  374. package/dist/assets/Icons/onlyfans-neutral.svg +1 -0
  375. package/dist/assets/Icons/onlyfans.svg +1 -0
  376. package/dist/assets/Icons/option.svg +1 -0
  377. package/dist/assets/Icons/outlook365-neutral.svg +1 -0
  378. package/dist/assets/Icons/outlook365.svg +1 -0
  379. package/dist/assets/Icons/paintbrush.svg +1 -0
  380. package/dist/assets/Icons/panel-bottom-open.svg +1 -0
  381. package/dist/assets/Icons/panel-bottom.svg +1 -0
  382. package/dist/assets/Icons/panel-left-close.svg +1 -0
  383. package/dist/assets/Icons/panel-left-dashed.svg +1 -0
  384. package/dist/assets/Icons/panel-left-open.svg +1 -0
  385. package/dist/assets/Icons/panel-left.svg +1 -0
  386. package/dist/assets/Icons/panel-right-animated.svg +1 -0
  387. package/dist/assets/Icons/panel-right-close.svg +1 -0
  388. package/dist/assets/Icons/panel-right-dashed.svg +1 -0
  389. package/dist/assets/Icons/panel-right-open.svg +1 -0
  390. package/dist/assets/Icons/panel-right.svg +1 -0
  391. package/dist/assets/Icons/panel-top-bottom-dashed.svg +1 -0
  392. package/dist/assets/Icons/panel-top-close.svg +1 -0
  393. package/dist/assets/Icons/panel-top-open.svg +1 -0
  394. package/dist/assets/Icons/panel-top.svg +1 -0
  395. package/dist/assets/Icons/panels-left-bottom.svg +1 -0
  396. package/dist/assets/Icons/panels-right-bottom.svg +1 -0
  397. package/dist/assets/Icons/panels-top-left.svg +1 -0
  398. package/dist/assets/Icons/paperclip.svg +1 -0
  399. package/dist/assets/Icons/patreon-neutral.svg +1 -0
  400. package/dist/assets/Icons/patreon.svg +1 -0
  401. package/dist/assets/Icons/paypal-neutral.svg +1 -0
  402. package/dist/assets/Icons/paypal.svg +1 -0
  403. package/dist/assets/Icons/pen-line.svg +1 -0
  404. package/dist/assets/Icons/pen-off.svg +1 -0
  405. package/dist/assets/Icons/pen-tool.svg +1 -0
  406. package/dist/assets/Icons/pen.svg +1 -0
  407. package/dist/assets/Icons/pencil-line.svg +1 -0
  408. package/dist/assets/Icons/pencil-off.svg +1 -0
  409. package/dist/assets/Icons/pencil-ruler.svg +1 -0
  410. package/dist/assets/Icons/pencil.svg +1 -0
  411. package/dist/assets/Icons/pentagon.svg +1 -0
  412. package/dist/assets/Icons/percentage.svg +1 -0
  413. package/dist/assets/Icons/phone.svg +1 -0
  414. package/dist/assets/Icons/pin-off.svg +1 -0
  415. package/dist/assets/Icons/pin.svg +1 -0
  416. package/dist/assets/Icons/pinterest-neutral.svg +1 -0
  417. package/dist/assets/Icons/pinterest.svg +1 -0
  418. package/dist/assets/Icons/play.svg +1 -0
  419. package/dist/assets/Icons/plug.svg +1 -0
  420. package/dist/assets/Icons/plunk-neutral.svg +1 -0
  421. package/dist/assets/Icons/plunk.svg +1 -0
  422. package/dist/assets/Icons/plus.svg +1 -0
  423. package/dist/assets/Icons/postmark-neutral.svg +1 -0
  424. package/dist/assets/Icons/postmark.svg +1 -0
  425. package/dist/assets/Icons/product-hunt-neutral.svg +1 -0
  426. package/dist/assets/Icons/product-hunt.svg +1 -0
  427. package/dist/assets/Icons/quora-neutral.svg +1 -0
  428. package/dist/assets/Icons/quora.svg +1 -0
  429. package/dist/assets/Icons/quote.svg +1 -0
  430. package/dist/assets/Icons/radar.svg +1 -0
  431. package/dist/assets/Icons/reddit-neutral.svg +1 -0
  432. package/dist/assets/Icons/reddit.svg +1 -0
  433. package/dist/assets/Icons/redo-dot.svg +1 -0
  434. package/dist/assets/Icons/redo.svg +1 -0
  435. package/dist/assets/Icons/redo2.svg +1 -0
  436. package/dist/assets/Icons/refresh-ccw.svg +1 -0
  437. package/dist/assets/Icons/refresh-cw-off.svg +1 -0
  438. package/dist/assets/Icons/resend-neutral.svg +1 -0
  439. package/dist/assets/Icons/resend.svg +1 -0
  440. package/dist/assets/Icons/rss.svg +1 -0
  441. package/dist/assets/Icons/rules.svg +1 -0
  442. package/dist/assets/Icons/scan-line.svg +1 -0
  443. package/dist/assets/Icons/scroll-text.svg +1 -0
  444. package/dist/assets/Icons/search-hint.svg +1 -0
  445. package/dist/assets/Icons/search-x.svg +1 -0
  446. package/dist/assets/Icons/search.svg +1 -0
  447. package/dist/assets/Icons/sendgrid-neutral.svg +1 -0
  448. package/dist/assets/Icons/sendgrid.svg +1 -0
  449. package/dist/assets/Icons/server.svg +1 -0
  450. package/dist/assets/Icons/ses-neutral.svg +1 -0
  451. package/dist/assets/Icons/ses.svg +1 -0
  452. package/dist/assets/Icons/settings.svg +1 -0
  453. package/dist/assets/Icons/settings2.svg +1 -0
  454. package/dist/assets/Icons/shapes.svg +1 -0
  455. package/dist/assets/Icons/share.svg +1 -0
  456. package/dist/assets/Icons/sheet.svg +1 -0
  457. package/dist/assets/Icons/shield-alert.svg +1 -0
  458. package/dist/assets/Icons/shield-ban.svg +1 -0
  459. package/dist/assets/Icons/shield-check.svg +1 -0
  460. package/dist/assets/Icons/shield-ellipsis.svg +1 -0
  461. package/dist/assets/Icons/shield-half.svg +1 -0
  462. package/dist/assets/Icons/shield-minus.svg +1 -0
  463. package/dist/assets/Icons/shield-off.svg +1 -0
  464. package/dist/assets/Icons/shield-plus.svg +1 -0
  465. package/dist/assets/Icons/shield-question.svg +1 -0
  466. package/dist/assets/Icons/shield-user.svg +1 -0
  467. package/dist/assets/Icons/shield-x.svg +1 -0
  468. package/dist/assets/Icons/shield.svg +1 -0
  469. package/dist/assets/Icons/shift.svg +1 -0
  470. package/dist/assets/Icons/signal-neutral.svg +1 -0
  471. package/dist/assets/Icons/signal.svg +1 -0
  472. package/dist/assets/Icons/signpost.svg +1 -0
  473. package/dist/assets/Icons/sina-weibo-neutral.svg +1 -0
  474. package/dist/assets/Icons/sina-weibo.svg +1 -0
  475. package/dist/assets/Icons/skull.svg +1 -0
  476. package/dist/assets/Icons/skype-neutral.svg +1 -0
  477. package/dist/assets/Icons/skype.svg +1 -0
  478. package/dist/assets/Icons/slack-neutral.svg +1 -0
  479. package/dist/assets/Icons/slack.svg +1 -0
  480. package/dist/assets/Icons/sliders-horizontal.svg +1 -0
  481. package/dist/assets/Icons/sliders-vertical.svg +1 -0
  482. package/dist/assets/Icons/smtp-neutral.svg +1 -0
  483. package/dist/assets/Icons/smtp.svg +1 -0
  484. package/dist/assets/Icons/snapchat-neutral.svg +1 -0
  485. package/dist/assets/Icons/snapchat.svg +1 -0
  486. package/dist/assets/Icons/soundcloud-neutral.svg +1 -0
  487. package/dist/assets/Icons/soundcloud.svg +1 -0
  488. package/dist/assets/Icons/space.svg +1 -0
  489. package/dist/assets/Icons/sparkpost-neutral.svg +1 -0
  490. package/dist/assets/Icons/sparkpost.svg +1 -0
  491. package/dist/assets/Icons/speed.svg +1 -0
  492. package/dist/assets/Icons/split.svg +1 -0
  493. package/dist/assets/Icons/spotify-neutral.svg +1 -0
  494. package/dist/assets/Icons/spotify.svg +1 -0
  495. package/dist/assets/Icons/square-arrow-out-up-right.svg +1 -0
  496. package/dist/assets/Icons/square-minus.svg +1 -0
  497. package/dist/assets/Icons/square-pen.svg +1 -0
  498. package/dist/assets/Icons/square-plus.svg +1 -0
  499. package/dist/assets/Icons/square-user-round.svg +1 -0
  500. package/dist/assets/Icons/stack-overflow-neutral.svg +1 -0
  501. package/dist/assets/Icons/stack-overflow.svg +1 -0
  502. package/dist/assets/Icons/star.svg +1 -0
  503. package/dist/assets/Icons/sun.svg +1 -0
  504. package/dist/assets/Icons/syringe.svg +1 -0
  505. package/dist/assets/Icons/tag.svg +1 -0
  506. package/dist/assets/Icons/target.svg +1 -0
  507. package/dist/assets/Icons/teams-neutral.svg +1 -0
  508. package/dist/assets/Icons/teams.svg +1 -0
  509. package/dist/assets/Icons/telegram-neutral.svg +1 -0
  510. package/dist/assets/Icons/telegram-only-sign-neutral.svg +1 -0
  511. package/dist/assets/Icons/telegram-only-sign.svg +1 -0
  512. package/dist/assets/Icons/telegram.svg +1 -0
  513. package/dist/assets/Icons/terminal.svg +1 -0
  514. package/dist/assets/Icons/test-policies.svg +1 -0
  515. package/dist/assets/Icons/threads-neutral.svg +1 -0
  516. package/dist/assets/Icons/threads.svg +1 -0
  517. package/dist/assets/Icons/thumbs-down.svg +1 -0
  518. package/dist/assets/Icons/thumbs-up.svg +1 -0
  519. package/dist/assets/Icons/tiktok-neutral.svg +1 -0
  520. package/dist/assets/Icons/tiktok.svg +1 -0
  521. package/dist/assets/Icons/tinder-neutral.svg +1 -0
  522. package/dist/assets/Icons/tinder.svg +1 -0
  523. package/dist/assets/Icons/trash.svg +1 -0
  524. package/dist/assets/Icons/trash2.svg +1 -0
  525. package/dist/assets/Icons/triangle-alert.svg +1 -0
  526. package/dist/assets/Icons/tumblr-neutral.svg +1 -0
  527. package/dist/assets/Icons/tumblr.svg +1 -0
  528. package/dist/assets/Icons/twitch-neutral.svg +1 -0
  529. package/dist/assets/Icons/twitch.svg +1 -0
  530. package/dist/assets/Icons/undo-dot.svg +1 -0
  531. package/dist/assets/Icons/undo.svg +1 -0
  532. package/dist/assets/Icons/undo2.svg +1 -0
  533. package/dist/assets/Icons/unplug.svg +1 -0
  534. package/dist/assets/Icons/user-check.svg +1 -0
  535. package/dist/assets/Icons/user-minus.svg +1 -0
  536. package/dist/assets/Icons/user-plus.svg +1 -0
  537. package/dist/assets/Icons/user-round-x.svg +1 -0
  538. package/dist/assets/Icons/user-round.svg +1 -0
  539. package/dist/assets/Icons/user.svg +1 -0
  540. package/dist/assets/Icons/username.svg +1 -0
  541. package/dist/assets/Icons/users-round.svg +1 -0
  542. package/dist/assets/Icons/users.svg +1 -0
  543. package/dist/assets/Icons/viber-neutral.svg +1 -0
  544. package/dist/assets/Icons/viber.svg +1 -0
  545. package/dist/assets/Icons/video.svg +1 -0
  546. package/dist/assets/Icons/vimeo-neutral.svg +1 -0
  547. package/dist/assets/Icons/vimeo.svg +1 -0
  548. package/dist/assets/Icons/vk-music-neutral.svg +1 -0
  549. package/dist/assets/Icons/vk-music.svg +1 -0
  550. package/dist/assets/Icons/vk-neutral.svg +1 -0
  551. package/dist/assets/Icons/vk-only-sign-neutral.svg +1 -0
  552. package/dist/assets/Icons/vk-only-sign.svg +1 -0
  553. package/dist/assets/Icons/vk.svg +1 -0
  554. package/dist/assets/Icons/webhook-neutral.svg +1 -0
  555. package/dist/assets/Icons/webhook.svg +1 -0
  556. package/dist/assets/Icons/wechat-neutral.svg +1 -0
  557. package/dist/assets/Icons/wechat.svg +1 -0
  558. package/dist/assets/Icons/whatsapp-badge-neutral.svg +1 -0
  559. package/dist/assets/Icons/whatsapp-badge.svg +1 -0
  560. package/dist/assets/Icons/whatsapp-neutral.svg +1 -0
  561. package/dist/assets/Icons/whatsapp.svg +1 -0
  562. package/dist/assets/Icons/workflow.svg +1 -0
  563. package/dist/assets/Icons/wrap-text.svg +1 -0
  564. package/dist/assets/Icons/wrench.svg +1 -0
  565. package/dist/assets/Icons/x-ex-twitter-neutral.svg +1 -0
  566. package/dist/assets/Icons/x-ex-twitter.svg +1 -0
  567. package/dist/assets/Icons/x.svg +1 -0
  568. package/dist/assets/Icons/xing-neutral.svg +1 -0
  569. package/dist/assets/Icons/xing.svg +1 -0
  570. package/dist/assets/Icons/yandex-music-neutral.svg +1 -0
  571. package/dist/assets/Icons/yandex-music.svg +1 -0
  572. package/dist/assets/Icons/yelp-neutral.svg +1 -0
  573. package/dist/assets/Icons/yelp.svg +1 -0
  574. package/dist/assets/Icons/youtube-music-neutral.svg +1 -0
  575. package/dist/assets/Icons/youtube-music.svg +1 -0
  576. package/dist/assets/Icons/youtube-neutral.svg +1 -0
  577. package/dist/assets/Icons/youtube-shorts-neutral.svg +1 -0
  578. package/dist/assets/Icons/youtube-shorts.svg +1 -0
  579. package/dist/assets/Icons/youtube.svg +1 -0
  580. package/dist/assets/Icons/zap.svg +1 -0
  581. package/dist/assets/Icons/zoom-in.svg +1 -0
  582. package/dist/assets/Icons/zoom-neutral.svg +1 -0
  583. package/dist/assets/Icons/zoom-out.svg +1 -0
  584. package/dist/assets/Icons/zoom.svg +1 -0
  585. package/dist/assets/Icons/zulip-neutral.svg +1 -0
  586. package/dist/assets/Icons/zulip.svg +1 -0
  587. package/dist/assets/Logos/wallarm.svg +1 -0
  588. package/dist/assets.json +4666 -0
  589. package/dist/project/README.md +265 -0
  590. package/dist/project/components/Accordion/README.md +354 -0
  591. package/dist/project/components/Accordion/preview.html +2 -0
  592. package/dist/project/components/Accordion/stories.js +12 -0
  593. package/dist/project/components/AgentAvatar/README.md +127 -0
  594. package/dist/project/components/AgentAvatar/preview.html +2 -0
  595. package/dist/project/components/AgentAvatar/stories.js +12 -0
  596. package/dist/project/components/AgentAvatar/stories.md +1805 -0
  597. package/dist/project/components/AgentGlyph/README.md +1182 -0
  598. package/dist/project/components/AgentGlyph/preview.html +2 -0
  599. package/dist/project/components/AgentGlyph/stories.js +12 -0
  600. package/dist/project/components/AgentLookBuilder/README.md +269 -0
  601. package/dist/project/components/AgentLookBuilder/preview.html +2 -0
  602. package/dist/project/components/AgentLookBuilder/stories.js +12 -0
  603. package/dist/project/components/Alert/README.md +492 -0
  604. package/dist/project/components/Alert/preview.html +2 -0
  605. package/dist/project/components/Alert/stories.js +12 -0
  606. package/dist/project/components/AnimatedBackground/README.md +124 -0
  607. package/dist/project/components/AnimatedBackground/preview.html +2 -0
  608. package/dist/project/components/AnimatedBackground/stories.js +12 -0
  609. package/dist/project/components/AppShell/README.md +75 -0
  610. package/dist/project/components/AppShell/preview.html +2 -0
  611. package/dist/project/components/AppShell/stories.js +28 -0
  612. package/dist/project/components/AppShell/stories.md +2878 -0
  613. package/dist/project/components/ApprovalCard/README.md +353 -0
  614. package/dist/project/components/ApprovalCard/preview.html +2 -0
  615. package/dist/project/components/ApprovalCard/stories.js +12 -0
  616. package/dist/project/components/AreaChart/README.md +673 -0
  617. package/dist/project/components/AreaChart/preview.html +2 -0
  618. package/dist/project/components/AreaChart/stories.js +12 -0
  619. package/dist/project/components/AssistantMessage/README.md +724 -0
  620. package/dist/project/components/AssistantMessage/preview.html +2 -0
  621. package/dist/project/components/AssistantMessage/stories.js +55 -0
  622. package/dist/project/components/Attribute/README.md +1174 -0
  623. package/dist/project/components/Attribute/preview.html +2 -0
  624. package/dist/project/components/Attribute/stories.js +12 -0
  625. package/dist/project/components/Avatar/README.md +416 -0
  626. package/dist/project/components/Avatar/preview.html +2 -0
  627. package/dist/project/components/Avatar/stories.js +12 -0
  628. package/dist/project/components/Badge/README.md +853 -0
  629. package/dist/project/components/Badge/preview.html +2 -0
  630. package/dist/project/components/Badge/stories.js +12 -0
  631. package/dist/project/components/Banner/README.md +341 -0
  632. package/dist/project/components/Banner/preview.html +2 -0
  633. package/dist/project/components/Banner/stories.js +12 -0
  634. package/dist/project/components/BarList/README.md +757 -0
  635. package/dist/project/components/BarList/preview.html +2 -0
  636. package/dist/project/components/BarList/stories.js +12 -0
  637. package/dist/project/components/Breadcrumbs/README.md +274 -0
  638. package/dist/project/components/Breadcrumbs/preview.html +2 -0
  639. package/dist/project/components/Breadcrumbs/stories.js +12 -0
  640. package/dist/project/components/BulkBar/README.md +19 -0
  641. package/dist/project/components/Button/README.md +467 -0
  642. package/dist/project/components/Button/preview.html +2 -0
  643. package/dist/project/components/Button/stories.js +12 -0
  644. package/dist/project/components/Calendar/README.md +654 -0
  645. package/dist/project/components/Calendar/preview.html +2 -0
  646. package/dist/project/components/Calendar/stories.js +12 -0
  647. package/dist/project/components/Card/README.md +367 -0
  648. package/dist/project/components/Card/preview.html +2 -0
  649. package/dist/project/components/Card/stories.js +12 -0
  650. package/dist/project/components/ChainOfThought/README.md +412 -0
  651. package/dist/project/components/ChainOfThought/preview.html +2 -0
  652. package/dist/project/components/ChainOfThought/stories.js +12 -0
  653. package/dist/project/components/Chart/README.md +224 -0
  654. package/dist/project/components/Chart/preview.html +2 -0
  655. package/dist/project/components/Chart/stories.js +12 -0
  656. package/dist/project/components/Chat/README.md +1244 -0
  657. package/dist/project/components/Chat/preview.html +2 -0
  658. package/dist/project/components/Chat/stories.js +12 -0
  659. package/dist/project/components/ChatInput/README.md +378 -0
  660. package/dist/project/components/ChatInput/preview.html +2 -0
  661. package/dist/project/components/ChatInput/stories.js +12 -0
  662. package/dist/project/components/ChatPermissions/README.md +218 -0
  663. package/dist/project/components/ChatPermissions/preview.html +2 -0
  664. package/dist/project/components/ChatPermissions/stories.js +12 -0
  665. package/dist/project/components/Checkbox/README.md +367 -0
  666. package/dist/project/components/Checkbox/preview.html +2 -0
  667. package/dist/project/components/Checkbox/stories.js +12 -0
  668. package/dist/project/components/Code/README.md +243 -0
  669. package/dist/project/components/Code/preview.html +2 -0
  670. package/dist/project/components/Code/stories.js +12 -0
  671. package/dist/project/components/CodeEditor/README.md +280 -0
  672. package/dist/project/components/CodeEditor/preview.html +2 -0
  673. package/dist/project/components/CodeEditor/stories.js +162 -0
  674. package/dist/project/components/CodeEditor/stories.md +1533 -0
  675. package/dist/project/components/CodeSnippet/README.md +1352 -0
  676. package/dist/project/components/CodeSnippet/preview.html +2 -0
  677. package/dist/project/components/CodeSnippet/stories.js +156 -0
  678. package/dist/project/components/ColumnChart/README.md +521 -0
  679. package/dist/project/components/ColumnChart/preview.html +2 -0
  680. package/dist/project/components/ColumnChart/stories.js +12 -0
  681. package/dist/project/components/Conversation/README.md +314 -0
  682. package/dist/project/components/Conversation/preview.html +2 -0
  683. package/dist/project/components/Conversation/stories.js +12 -0
  684. package/dist/project/components/Copyable/README.md +406 -0
  685. package/dist/project/components/Copyable/preview.html +2 -0
  686. package/dist/project/components/Copyable/stories.js +12 -0
  687. package/dist/project/components/Country/README.md +226 -0
  688. package/dist/project/components/Country/preview.html +2 -0
  689. package/dist/project/components/Country/stories.js +12 -0
  690. package/dist/project/components/Cover/preview.html +43 -0
  691. package/dist/project/components/DateInput/README.md +458 -0
  692. package/dist/project/components/DateInput/preview.html +2 -0
  693. package/dist/project/components/DateInput/stories.js +12 -0
  694. package/dist/project/components/DateRangeInput/README.md +412 -0
  695. package/dist/project/components/DateRangeInput/preview.html +2 -0
  696. package/dist/project/components/DateRangeInput/stories.js +12 -0
  697. package/dist/project/components/Dialog/README.md +1140 -0
  698. package/dist/project/components/Dialog/preview.html +2 -0
  699. package/dist/project/components/Dialog/stories.js +12 -0
  700. package/dist/project/components/Drawer/README.md +1163 -0
  701. package/dist/project/components/Drawer/preview.html +2 -0
  702. package/dist/project/components/Drawer/stories.js +12 -0
  703. package/dist/project/components/DropdownMenu/README.md +678 -0
  704. package/dist/project/components/DropdownMenu/preview.html +2 -0
  705. package/dist/project/components/DropdownMenu/stories.js +12 -0
  706. package/dist/project/components/EmptyState/README.md +276 -0
  707. package/dist/project/components/EmptyState/preview.html +2 -0
  708. package/dist/project/components/EmptyState/stories.js +12 -0
  709. package/dist/project/components/FeedbackPulse/README.md +125 -0
  710. package/dist/project/components/FeedbackPulse/preview.html +2 -0
  711. package/dist/project/components/FeedbackPulse/stories.js +12 -0
  712. package/dist/project/components/Field/README.md +676 -0
  713. package/dist/project/components/Field/preview.html +2 -0
  714. package/dist/project/components/Field/stories.js +12 -0
  715. package/dist/project/components/FileUpload/README.md +544 -0
  716. package/dist/project/components/FileUpload/preview.html +2 -0
  717. package/dist/project/components/FileUpload/stories.js +12 -0
  718. package/dist/project/components/FilterCascade/README.md +348 -0
  719. package/dist/project/components/FilterCascade/preview.html +2 -0
  720. package/dist/project/components/FilterCascade/stories.js +12 -0
  721. package/dist/project/components/FilterDropdown/README.md +542 -0
  722. package/dist/project/components/FilterDropdown/preview.html +2 -0
  723. package/dist/project/components/FilterDropdown/stories.js +12 -0
  724. package/dist/project/components/FilterInput/README.md +416 -0
  725. package/dist/project/components/FilterInput/preview.html +2 -0
  726. package/dist/project/components/FilterInput/stories.js +12 -0
  727. package/dist/project/components/FilterInput/stories.md +6682 -0
  728. package/dist/project/components/Flex/README.md +225 -0
  729. package/dist/project/components/Flex/preview.html +2 -0
  730. package/dist/project/components/Flex/stories.js +12 -0
  731. package/dist/project/components/FormatDateTime/README.md +315 -0
  732. package/dist/project/components/FormatDateTime/preview.html +2 -0
  733. package/dist/project/components/FormatDateTime/stories.js +12 -0
  734. package/dist/project/components/FormatNumber/README.md +317 -0
  735. package/dist/project/components/FormatNumber/preview.html +2 -0
  736. package/dist/project/components/FormatNumber/stories.js +12 -0
  737. package/dist/project/components/Heading/README.md +240 -0
  738. package/dist/project/components/Heading/preview.html +2 -0
  739. package/dist/project/components/Heading/stories.js +12 -0
  740. package/dist/project/components/HorizontalBarStack/README.md +281 -0
  741. package/dist/project/components/HorizontalBarStack/preview.html +2 -0
  742. package/dist/project/components/HorizontalBarStack/stories.js +12 -0
  743. package/dist/project/components/HttpMethod/README.md +137 -0
  744. package/dist/project/components/HttpMethod/preview.html +2 -0
  745. package/dist/project/components/HttpMethod/stories.js +12 -0
  746. package/dist/project/components/ImageCropper/README.md +332 -0
  747. package/dist/project/components/ImageCropper/preview.html +2 -0
  748. package/dist/project/components/ImageCropper/stories.js +33 -0
  749. package/dist/project/components/Indicator/README.md +110 -0
  750. package/dist/project/components/Indicator/preview.html +2 -0
  751. package/dist/project/components/Indicator/stories.js +12 -0
  752. package/dist/project/components/InlineEdit/README.md +977 -0
  753. package/dist/project/components/InlineEdit/preview.html +2 -0
  754. package/dist/project/components/InlineEdit/stories.js +12 -0
  755. package/dist/project/components/Input/README.md +187 -0
  756. package/dist/project/components/Input/preview.html +2 -0
  757. package/dist/project/components/Input/stories.js +12 -0
  758. package/dist/project/components/InputGroup/README.md +423 -0
  759. package/dist/project/components/InputGroup/preview.html +2 -0
  760. package/dist/project/components/InputGroup/stories.js +12 -0
  761. package/dist/project/components/InputOTP/README.md +201 -0
  762. package/dist/project/components/InputOTP/preview.html +2 -0
  763. package/dist/project/components/InputOTP/stories.js +12 -0
  764. package/dist/project/components/Ip/README.md +226 -0
  765. package/dist/project/components/Ip/preview.html +2 -0
  766. package/dist/project/components/Ip/stories.js +12 -0
  767. package/dist/project/components/Kbd/README.md +126 -0
  768. package/dist/project/components/Kbd/preview.html +2 -0
  769. package/dist/project/components/Kbd/stories.js +12 -0
  770. package/dist/project/components/LineChart/README.md +1479 -0
  771. package/dist/project/components/LineChart/preview.html +2 -0
  772. package/dist/project/components/LineChart/stories.js +12 -0
  773. package/dist/project/components/Link/README.md +160 -0
  774. package/dist/project/components/Link/preview.html +2 -0
  775. package/dist/project/components/Link/stories.js +12 -0
  776. package/dist/project/components/List/README.md +181 -0
  777. package/dist/project/components/List/preview.html +2 -0
  778. package/dist/project/components/List/stories.js +12 -0
  779. package/dist/project/components/Loader/README.md +145 -0
  780. package/dist/project/components/Loader/preview.html +2 -0
  781. package/dist/project/components/Loader/stories.js +12 -0
  782. package/dist/project/components/Logo/README.md +183 -0
  783. package/dist/project/components/Logo/preview.html +2 -0
  784. package/dist/project/components/Logo/stories.js +12 -0
  785. package/dist/project/components/MessageActions/README.md +255 -0
  786. package/dist/project/components/MessageActions/preview.html +2 -0
  787. package/dist/project/components/MessageActions/stories.js +12 -0
  788. package/dist/project/components/Metric/README.md +324 -0
  789. package/dist/project/components/Metric/preview.html +2 -0
  790. package/dist/project/components/Metric/stories.js +12 -0
  791. package/dist/project/components/NavRail/README.md +25 -0
  792. package/dist/project/components/NotificationCenter/README.md +91 -0
  793. package/dist/project/components/NotificationCenter/preview.html +2 -0
  794. package/dist/project/components/NotificationCenter/stories.js +12 -0
  795. package/dist/project/components/NotificationCenter/stories.md +2170 -0
  796. package/dist/project/components/NumberInput/README.md +177 -0
  797. package/dist/project/components/NumberInput/preview.html +2 -0
  798. package/dist/project/components/NumberInput/stories.js +12 -0
  799. package/dist/project/components/NumericBadge/README.md +252 -0
  800. package/dist/project/components/NumericBadge/preview.html +2 -0
  801. package/dist/project/components/NumericBadge/stories.js +12 -0
  802. package/dist/project/components/OverflowList/README.md +324 -0
  803. package/dist/project/components/OverflowList/preview.html +2 -0
  804. package/dist/project/components/OverflowList/stories.js +12 -0
  805. package/dist/project/components/OverflowTooltip/README.md +421 -0
  806. package/dist/project/components/OverflowTooltip/preview.html +2 -0
  807. package/dist/project/components/OverflowTooltip/stories.js +12 -0
  808. package/dist/project/components/Overlay/README.md +95 -0
  809. package/dist/project/components/Overlay/preview.html +2 -0
  810. package/dist/project/components/Overlay/stories.js +12 -0
  811. package/dist/project/components/Overview/README.md +445 -0
  812. package/dist/project/components/Overview/preview.html +2 -0
  813. package/dist/project/components/Overview/stories.js +12 -0
  814. package/dist/project/components/Page/README.md +215 -0
  815. package/dist/project/components/Page/preview.html +2 -0
  816. package/dist/project/components/Page/stories.js +12 -0
  817. package/dist/project/components/Pagination/README.md +302 -0
  818. package/dist/project/components/Pagination/preview.html +2 -0
  819. package/dist/project/components/Pagination/stories.js +12 -0
  820. package/dist/project/components/ParameterPath/README.md +284 -0
  821. package/dist/project/components/ParameterPath/preview.html +2 -0
  822. package/dist/project/components/ParameterPath/stories.js +12 -0
  823. package/dist/project/components/PasswordComplexity/README.md +171 -0
  824. package/dist/project/components/PasswordComplexity/preview.html +2 -0
  825. package/dist/project/components/PasswordComplexity/stories.js +12 -0
  826. package/dist/project/components/PasswordInput/README.md +254 -0
  827. package/dist/project/components/PasswordInput/preview.html +2 -0
  828. package/dist/project/components/PasswordInput/stories.js +12 -0
  829. package/dist/project/components/PieChart/README.md +895 -0
  830. package/dist/project/components/PieChart/preview.html +2 -0
  831. package/dist/project/components/PieChart/stories.js +12 -0
  832. package/dist/project/components/Popover/README.md +282 -0
  833. package/dist/project/components/Popover/preview.html +2 -0
  834. package/dist/project/components/Popover/stories.js +12 -0
  835. package/dist/project/components/Progress/README.md +174 -0
  836. package/dist/project/components/Progress/preview.html +2 -0
  837. package/dist/project/components/Progress/stories.js +12 -0
  838. package/dist/project/components/Radio/README.md +264 -0
  839. package/dist/project/components/Radio/preview.html +2 -0
  840. package/dist/project/components/Radio/stories.js +12 -0
  841. package/dist/project/components/RemoteShell/README.md +1758 -0
  842. package/dist/project/components/RemoteShell/preview.html +2 -0
  843. package/dist/project/components/RemoteShell/stories.js +28 -0
  844. package/dist/project/components/Resizable/README.md +290 -0
  845. package/dist/project/components/Resizable/preview.html +2 -0
  846. package/dist/project/components/Resizable/stories.js +12 -0
  847. package/dist/project/components/ResponseCode/README.md +205 -0
  848. package/dist/project/components/ResponseCode/preview.html +2 -0
  849. package/dist/project/components/ResponseCode/stories.js +12 -0
  850. package/dist/project/components/ScrollArea/README.md +234 -0
  851. package/dist/project/components/ScrollArea/preview.html +2 -0
  852. package/dist/project/components/ScrollArea/stories.js +12 -0
  853. package/dist/project/components/SearchInput/README.md +158 -0
  854. package/dist/project/components/SearchInput/preview.html +2 -0
  855. package/dist/project/components/SearchInput/stories.js +12 -0
  856. package/dist/project/components/SearchModal/README.md +836 -0
  857. package/dist/project/components/SearchModal/preview.html +2 -0
  858. package/dist/project/components/SearchModal/stories.js +12 -0
  859. package/dist/project/components/SegmentedControl/README.md +382 -0
  860. package/dist/project/components/SegmentedControl/preview.html +2 -0
  861. package/dist/project/components/SegmentedControl/stories.js +12 -0
  862. package/dist/project/components/SegmentedTabs/README.md +390 -0
  863. package/dist/project/components/SegmentedTabs/preview.html +2 -0
  864. package/dist/project/components/SegmentedTabs/stories.js +12 -0
  865. package/dist/project/components/Select/README.md +1311 -0
  866. package/dist/project/components/Select/preview.html +2 -0
  867. package/dist/project/components/Select/stories.js +12 -0
  868. package/dist/project/components/Selection/README.md +648 -0
  869. package/dist/project/components/Selection/preview.html +2 -0
  870. package/dist/project/components/Selection/stories.js +12 -0
  871. package/dist/project/components/Separator/README.md +77 -0
  872. package/dist/project/components/Separator/preview.html +2 -0
  873. package/dist/project/components/Separator/stories.js +12 -0
  874. package/dist/project/components/Skeleton/README.md +358 -0
  875. package/dist/project/components/Skeleton/preview.html +2 -0
  876. package/dist/project/components/Skeleton/stories.js +12 -0
  877. package/dist/project/components/Slider/README.md +433 -0
  878. package/dist/project/components/Slider/preview.html +2 -0
  879. package/dist/project/components/Slider/stories.js +12 -0
  880. package/dist/project/components/SplashScreen/README.md +192 -0
  881. package/dist/project/components/SplashScreen/preview.html +2 -0
  882. package/dist/project/components/SplashScreen/stories.js +12 -0
  883. package/dist/project/components/SplitButton/README.md +402 -0
  884. package/dist/project/components/SplitButton/preview.html +2 -0
  885. package/dist/project/components/SplitButton/stories.js +12 -0
  886. package/dist/project/components/Stack/README.md +269 -0
  887. package/dist/project/components/Stack/preview.html +2 -0
  888. package/dist/project/components/Stack/stories.js +12 -0
  889. package/dist/project/components/Stepper/README.md +682 -0
  890. package/dist/project/components/Stepper/preview.html +2 -0
  891. package/dist/project/components/Stepper/stories.js +12 -0
  892. package/dist/project/components/Switch/README.md +236 -0
  893. package/dist/project/components/Switch/preview.html +2 -0
  894. package/dist/project/components/Switch/stories.js +12 -0
  895. package/dist/project/components/Table/README.md +471 -0
  896. package/dist/project/components/Table/preview.html +2 -0
  897. package/dist/project/components/Table/stories.js +12 -0
  898. package/dist/project/components/Table/stories.md +3697 -0
  899. package/dist/project/components/Tabs/README.md +443 -0
  900. package/dist/project/components/Tabs/preview.html +2 -0
  901. package/dist/project/components/Tabs/stories.js +12 -0
  902. package/dist/project/components/Tag/README.md +324 -0
  903. package/dist/project/components/Tag/preview.html +2 -0
  904. package/dist/project/components/Tag/stories.js +12 -0
  905. package/dist/project/components/Text/README.md +200 -0
  906. package/dist/project/components/Text/preview.html +2 -0
  907. package/dist/project/components/Text/stories.js +12 -0
  908. package/dist/project/components/Textarea/README.md +273 -0
  909. package/dist/project/components/Textarea/preview.html +2 -0
  910. package/dist/project/components/Textarea/stories.js +12 -0
  911. package/dist/project/components/TimeInput/README.md +359 -0
  912. package/dist/project/components/TimeInput/preview.html +2 -0
  913. package/dist/project/components/TimeInput/stories.js +12 -0
  914. package/dist/project/components/Timeline/README.md +204 -0
  915. package/dist/project/components/Timeline/preview.html +2 -0
  916. package/dist/project/components/Timeline/stories.js +12 -0
  917. package/dist/project/components/Toast/README.md +718 -0
  918. package/dist/project/components/Toast/preview.html +2 -0
  919. package/dist/project/components/Toast/stories.js +12 -0
  920. package/dist/project/components/ToggleButton/README.md +292 -0
  921. package/dist/project/components/ToggleButton/preview.html +2 -0
  922. package/dist/project/components/ToggleButton/stories.js +12 -0
  923. package/dist/project/components/Tooltip/README.md +199 -0
  924. package/dist/project/components/Tooltip/preview.html +2 -0
  925. package/dist/project/components/Tooltip/stories.js +12 -0
  926. package/dist/project/components/TopHeader/README.md +21 -0
  927. package/dist/project/components/Tour/README.md +532 -0
  928. package/dist/project/components/Tour/preview.html +2 -0
  929. package/dist/project/components/Tour/stories.js +12 -0
  930. package/dist/project/components/Tree/README.md +450 -0
  931. package/dist/project/components/Tree/preview.html +2 -0
  932. package/dist/project/components/Tree/stories.js +12 -0
  933. package/dist/project/components/TreeView/README.md +531 -0
  934. package/dist/project/components/TreeView/preview.html +2 -0
  935. package/dist/project/components/TreeView/stories.js +12 -0
  936. package/dist/project/components/UTILITIES.md +647 -0
  937. package/dist/project/components/UserMessage/README.md +166 -0
  938. package/dist/project/components/UserMessage/preview.html +2 -0
  939. package/dist/project/components/UserMessage/stories.js +12 -0
  940. package/dist/project/components/UtilityPage/README.md +147 -0
  941. package/dist/project/components/UtilityPage/preview.html +2 -0
  942. package/dist/project/components/UtilityPage/stories.js +12 -0
  943. package/dist/project/components/WallyAssistant/README.md +1380 -0
  944. package/dist/project/components/WallyAssistant/preview.html +2 -0
  945. package/dist/project/components/WallyAssistant/stories.js +12 -0
  946. package/dist/project/components/WallyIcon/README.md +130 -0
  947. package/dist/project/components/WallyIcon/preview.html +2 -0
  948. package/dist/project/components/WallyIcon/stories.js +12 -0
  949. package/dist/project/components/WallySkeleton/README.md +96 -0
  950. package/dist/project/components/WallySkeleton/preview.html +2 -0
  951. package/dist/project/components/WallySkeleton/stories.js +12 -0
  952. package/dist/project/components/bundle.css +18734 -0
  953. package/dist/project/components/bundle.js +167 -0
  954. package/dist/project/components/index.d.ts +27226 -0
  955. package/dist/project/design-system.json +35 -0
  956. package/dist/project/fonts/Geist-Variable.woff2 +0 -0
  957. package/dist/project/fonts/GeistMono-Variable.woff2 +0 -0
  958. package/dist/project/fonts/GeistPixel-Square.woff2 +0 -0
  959. package/dist/project/sampler.dc.html +238 -0
  960. package/dist/project/tokens.css +1395 -0
  961. package/dist/project/tokens.json +5235 -0
  962. package/dist/wallarm-sampler.dc.html +239 -0
  963. package/package.json +67 -3
@@ -0,0 +1,1758 @@
1
+ The frame of one product inside `AppShell` — its navigation panel, breadcrumbs and content area, all driven by a single `NavConfig`. The panel is configured only through `config`: `link`, `group`, `section-header` and `drill` nodes, with `dividerAfter` for a line. Its parts are internal; never compose the panel by hand. The URL is the state: the active item, the drill level and the breadcrumbs are matched from the pathname. When a router owns the URL, hand the shell the router’s pathname through `pathname` and take its navigations back through `onNavigate` — then links in the page, the host rail or `router.navigate` keep the menu in sync. Without `pathname` the shell reads `window.location` and only notices `popstate` and its own navigations.
2
+
3
+ ## Props as canvas attributes
4
+
5
+ Use kebab-case attribute names. Pass non-string values through renderVals holes, including booleans. The full emitted API is in `components/index.d.ts`.
6
+
7
+ | Attribute | Type | Required | Default | Description |
8
+ | --- | --- | --- | --- | --- |
9
+ | `config` | `NavConfig` | yes | — | Navigation config used to build nav state for sub-components. |
10
+ | `base-path` | `string \| undefined` | no | — | URL prefix stripped before matching and prepended when navigating (e.g. `"/edge"`). |
11
+ | `pathname` | `string \| undefined` | no | — | Current pathname. When set, it is the single source of truth for the active nav item, drill level and breadcrumbs, and `window.location` is ignored. Pass it — **together with `onNavigate`** — whenever a router owns the URL: router navigations (links in page content, `router.navigate`, memory history, the host's rail) do not fire `popstate`, so without it the shell can go stale. Without `onNavigate` the shell's own navigations would only reach `window.history`, which a controlled shell ignores (a dev warning flags this). Either form is accepted: with the `basePath` prefix (what `onNavigate` receives) or without it — the prefix is stripped only when the pathname starts with a whole `basePath` segment. With TanStack Router, `useRouterState({ select: s => s.location.pathname })` is router-relative: it excludes the router's own `basepath`. So when the router has `basepath`: - omit `basePath` here — `pathname` and `onNavigate` are then both router-relative and `onNavigate={to => navigate({ to })}` is correct; or - keep `basePath` and strip it in `onNavigate` (`to => navigate({ to: to.slice(basePath.length) \|\| '/' })`), otherwise the router prefixes it a second time. Omit it to read `window.location.pathname` (updated on `popstate` and on the shell's own navigations). |
12
+ | `on-navigate` | `((pathname: string) => void) \| undefined` | no | — | Navigation handler for router integration (TanStack Router, React Router, Next.js, …). Receives the target pathname, prefixed with `basePath` when one is set. Without it the shell pushes to `window.history` itself. |
13
+ | `default-checked` | `boolean \| undefined` | no | — | |
14
+ | `default-value` | `string \| number \| readonly string[] \| undefined` | no | — | |
15
+ | `auto-focus` | `boolean \| undefined` | no | — | |
16
+ | `id` | `string \| undefined` | no | — | |
17
+ | `tab-index` | `number \| undefined` | no | — | |
18
+ | `title` | `string \| undefined` | no | — | |
19
+ | `rel` | `string \| undefined` | no | — | |
20
+ | `on-change` | `ChangeEventHandler<T, Element> \| undefined` | no | — | |
21
+ | `data-testid` | `string \| undefined` | no | — | |
22
+
23
+ ## Sub-components
24
+
25
+ - `WallarmDS.RemoteShellBreadcrumb` — `RemoteShellBreadcrumbProps` in the declaration bundle.
26
+ - `WallarmDS.RemoteShellContent` — `RemoteShellContentProps` in the declaration bundle.
27
+ - `WallarmDS.RemoteShellPanel` — `RemoteShellPanelProps` in the declaration bundle.
28
+
29
+ ## Stories
30
+
31
+ ### Basic
32
+
33
+ A standalone product on TanStack Router — the recommended integration. `pathname` is
34
+ the router’s `location.pathname` and `onNavigate` calls `navigate`, so the menu, drill
35
+ level and breadcrumbs follow every navigation: the panel, the breadcrumbs and the
36
+ router links in the page. This router has no `basepath` (its routes include `/edge`),
37
+ so both sides use the full pathname. If your router sets `basepath`, its
38
+ `location.pathname` is router-relative: omit `basePath` on `RemoteShell` (or keep it
39
+ and strip it in `onNavigate`), otherwise `navigate` prefixes it twice.
40
+
41
+ Source: RemoteShell/RemoteShell.stories.tsx#Basic
42
+
43
+ ## Story sources
44
+
45
+ ### RemoteShell/RemoteShell.stories.tsx
46
+
47
+ ```tsx
48
+ import type { FC } from 'react';
49
+ import { Link as RouterLink, useNavigate, useRouterState } from '@tanstack/react-router';
50
+ import type { Meta, StoryFn } from 'storybook-react-rsbuild';
51
+ import { edgeNavConfig, StoryRouter } from '../AppShell/story-content';
52
+ import { Link } from '../Link';
53
+ import { Page, PageContent, PageHeader, PageTitle } from '../Page';
54
+ import { Text } from '../Text';
55
+ import { useRemoteShellContext } from './model';
56
+ import { RemoteShell, type RemoteShellProps } from './RemoteShell';
57
+ import { RemoteShellBreadcrumb } from './RemoteShellBreadcrumb';
58
+ import { RemoteShellContent } from './RemoteShellContent';
59
+ import { RemoteShellPanel } from './RemoteShellPanel';
60
+
61
+ const DESCRIPTION = [
62
+ 'The frame of one product inside `AppShell` — its navigation panel, breadcrumbs and content area, all driven by a single `NavConfig`.',
63
+ 'The panel is configured only through `config`: `link`, `group`, `section-header` and `drill` nodes, with `dividerAfter` for a line. Its parts are internal; never compose the panel by hand.',
64
+ 'The URL is the state: the active item, the drill level and the breadcrumbs are matched from the pathname. When a router owns the URL, hand the shell the router’s pathname through `pathname` and take its navigations back through `onNavigate` — then links in the page, the host rail or `router.navigate` keep the menu in sync. Without `pathname` the shell reads `window.location` and only notices `popstate` and its own navigations.',
65
+ ].join(' ');
66
+
67
+ const meta = {
68
+ title: 'Navigation/RemoteShell',
69
+ component: RemoteShell,
70
+ subcomponents: {
71
+ RemoteShellPanel,
72
+ RemoteShellBreadcrumb,
73
+ RemoteShellContent,
74
+ },
75
+ // Each story render gets its own TanStack Router on a memory history (story-only
76
+ // harness); the story body below is the integration a product writes itself.
77
+ decorators: [
78
+ Story => (
79
+ <StoryRouter initialPath='/edge/overview'>
80
+ <Story />
81
+ </StoryRouter>
82
+ ),
83
+ ],
84
+ parameters: {
85
+ layout: 'fullscreen',
86
+ docs: {
87
+ description: {
88
+ component: DESCRIPTION,
89
+ },
90
+ },
91
+ },
92
+ argTypes: {
93
+ children: { control: false },
94
+ ref: { control: false },
95
+ config: { control: false },
96
+ basePath: { control: false },
97
+ pathname: { control: false },
98
+ onNavigate: { control: false },
99
+ },
100
+ } satisfies Meta<typeof RemoteShell>;
101
+
102
+ export default meta;
103
+
104
+ const EDGE_LINKS = [
105
+ { to: '/edge/overview', label: 'Edge overview' },
106
+ { to: '/edge/data-planes/production/services', label: 'Production → Services' },
107
+ { to: '/edge/data-planes/staging/overview', label: 'Staging → Overview' },
108
+ { to: '/edge/data-planes/production/nodes/node-2/metrics', label: 'Node 2 → Metrics' },
109
+ ];
110
+
111
+ const EdgePage: FC = () => {
112
+ const { breadcrumbSegments } = useRemoteShellContext();
113
+ const pathname = useRouterState({ select: state => state.location.pathname });
114
+ const title = breadcrumbSegments[breadcrumbSegments.length - 1]?.label ?? '';
115
+
116
+ return (
117
+ <Page title={title} fixedHeight>
118
+ <PageHeader>
119
+ <PageTitle>{title}</PageTitle>
120
+ </PageHeader>
121
+ <PageContent>
122
+ <div className='flex flex-col gap-12'>
123
+ <Text size='sm' color='secondary'>
124
+ Router pathname: <code>{pathname}</code>
125
+ </Text>
126
+ <Text size='sm' color='secondary'>
127
+ These are router links in the page, not shell navigation — the panel and the breadcrumbs
128
+ follow them.
129
+ </Text>
130
+ <ul className='flex flex-col gap-4'>
131
+ {EDGE_LINKS.map(link => (
132
+ <li key={link.to}>
133
+ <Link asChild>
134
+ <RouterLink to={link.to}>{link.label}</RouterLink>
135
+ </Link>
136
+ </li>
137
+ ))}
138
+ </ul>
139
+ </div>
140
+ </PageContent>
141
+ </Page>
142
+ );
143
+ };
144
+
145
+ /**
146
+ * A standalone product on TanStack Router — the recommended integration. `pathname` is
147
+ * the router’s `location.pathname` and `onNavigate` calls `navigate`, so the menu, drill
148
+ * level and breadcrumbs follow every navigation: the panel, the breadcrumbs and the
149
+ * router links in the page. This router has no `basepath` (its routes include `/edge`),
150
+ * so both sides use the full pathname. If your router sets `basepath`, its
151
+ * `location.pathname` is router-relative: omit `basePath` on `RemoteShell` (or keep it
152
+ * and strip it in `onNavigate`), otherwise `navigate` prefixes it twice.
153
+ */
154
+ export const Basic: StoryFn<RemoteShellProps> = () => {
155
+ const navigate = useNavigate();
156
+ const pathname = useRouterState({ select: state => state.location.pathname });
157
+
158
+ return (
159
+ <div className='h-screen bg-bg-page-bg'>
160
+ <RemoteShell
161
+ config={edgeNavConfig}
162
+ basePath='/edge'
163
+ pathname={pathname}
164
+ onNavigate={to => navigate({ to })}
165
+ >
166
+ <RemoteShellPanel resizable />
167
+ <RemoteShellBreadcrumb />
168
+ <RemoteShellContent>
169
+ <EdgePage />
170
+ </RemoteShellContent>
171
+ </RemoteShell>
172
+ </div>
173
+ );
174
+ };
175
+ ```
176
+
177
+ ### AppShell/story-content/index.ts
178
+
179
+ ```tsx
180
+ export { AccountDropdown, railModeFor, type SidebarMode } from './_storyAccountDropdown';
181
+ export { ConfigRemote, type ConfigRemoteProps, RemoteForProduct } from './_storyConfigRenderer';
182
+ export { HeaderActions } from './_storyHeaderActions';
183
+ export { HomeContent } from './_storyHomeContent';
184
+ export { deriveProduct, PRODUCT_CONFIGS, type Product, productLandingPath } from './_storyLib';
185
+ export {
186
+ aiHypervisorNavConfig,
187
+ edgeNavConfig,
188
+ infraDiscoveryNavConfig,
189
+ securityTestingNavConfig,
190
+ settingsNavConfig,
191
+ } from './_storyNavConfigs';
192
+ export { NavRailFooterContent } from './_storyNavRailFooter';
193
+ export { NotificationsInbox } from './_storyNotificationsInbox';
194
+ export { ProductNavItems } from './_storyProductNavItems';
195
+ export { QuickHelpDropdown } from './_storyQuickHelpDropdown';
196
+ export { RecentDropdown } from './_storyRecentDropdown';
197
+ export { StoryRouter, useStoryPathname, useStoryProductNavigation } from './_storyRouter';
198
+ export { WallarmLogo } from './_storyWallarmLogo';
199
+ ```
200
+
201
+ ### AppShell/story-content/_storyAccountDropdown.tsx
202
+
203
+ ```tsx
204
+ import { Fragment } from 'react';
205
+ import { LogOut, PanelLeftDashed, PencilRuler, Settings, UserRound } from '../../../icons';
206
+ import { cn } from '../../../utils/cn';
207
+ import {
208
+ Avatar,
209
+ AvatarContent,
210
+ AvatarDescription,
211
+ AvatarFallback,
212
+ AvatarImage,
213
+ AvatarName,
214
+ } from '../../Avatar';
215
+ import {
216
+ DropdownMenu,
217
+ DropdownMenuContent,
218
+ DropdownMenuItem,
219
+ DropdownMenuItemContent,
220
+ DropdownMenuItemIcon,
221
+ DropdownMenuItemText,
222
+ DropdownMenuRadioGroup,
223
+ DropdownMenuRadioItem,
224
+ DropdownMenuSeparator,
225
+ DropdownMenuTrigger,
226
+ DropdownMenuTriggerItem,
227
+ } from '../../DropdownMenu';
228
+ import { NavRailItem, type NavRailMode } from '../../NavRail';
229
+ import { Text } from '../../Text';
230
+ import { type FrameStyle, type Theme, useTheme } from '../../ThemeProvider';
231
+
232
+ export type SidebarMode = 'adaptive' | 'expanded' | 'collapsed' | 'compact';
233
+
234
+ /** Adaptive collapses the rail inside a product and expands it on Home; the other modes pin it. */
235
+ export const railModeFor = (mode: SidebarMode, onHome: boolean): NavRailMode => {
236
+ if (mode === 'adaptive') return onHome ? 'expanded' : 'collapsed';
237
+ return mode;
238
+ };
239
+
240
+ const USER_NAME = 'Meow Meow';
241
+ const USER_EMAIL = 'meow@meow.com';
242
+
243
+ const THEMES: Theme[] = ['light', 'dark'];
244
+ // Adaptive on its own, then the two pinned widths, then compact.
245
+ const SIDEBAR_MODE_GROUPS: SidebarMode[][] = [['adaptive'], ['expanded', 'collapsed'], ['compact']];
246
+ const SIDEBAR_MODES = SIDEBAR_MODE_GROUPS.flat();
247
+
248
+ const THEME_LABELS: Record<Theme, string> = {
249
+ light: 'Light',
250
+ dark: 'Dark',
251
+ };
252
+
253
+ const FRAME_STYLES: FrameStyle[] = ['neutral', 'branded'];
254
+
255
+ const FRAME_STYLE_LABELS: Record<FrameStyle, string> = {
256
+ neutral: 'Neutral',
257
+ branded: 'Branded',
258
+ };
259
+
260
+ // The swatch in front of each Frame style option, as in Figma.
261
+ const FRAME_STYLE_SWATCH: Record<FrameStyle, string> = {
262
+ neutral: 'bg-icon-secondary',
263
+ branded: 'bg-icon-brand',
264
+ };
265
+
266
+ const SIDEBAR_MODE_LABELS: Record<SidebarMode, string> = {
267
+ adaptive: 'Adaptive',
268
+ expanded: 'Always expanded',
269
+ collapsed: 'Always collapsed',
270
+ compact: 'Compact',
271
+ };
272
+
273
+ export const AccountDropdown = ({
274
+ sidebarMode,
275
+ onSidebarModeChange,
276
+ theme,
277
+ onThemeChange,
278
+ }: {
279
+ sidebarMode: SidebarMode;
280
+ onSidebarModeChange: (mode: SidebarMode) => void;
281
+ theme: Theme;
282
+ onThemeChange: (theme: Theme) => void;
283
+ }) => {
284
+ const { frameStyle, setFrameStyle } = useTheme();
285
+
286
+ return (
287
+ <DropdownMenu positioning={{ placement: 'right-end', gutter: 6, offset: { crossAxis: 12 } }}>
288
+ <DropdownMenuTrigger>
289
+ <NavRailItem icon={UserRound} label={USER_NAME} avatar />
290
+ </DropdownMenuTrigger>
291
+ <DropdownMenuContent className='w-256'>
292
+ <div className='rounded-6 border border-border-primary-light bg-states-primary-hover px-8 py-8 mb-4'>
293
+ <Avatar size='md'>
294
+ <AvatarImage />
295
+ <AvatarFallback name={USER_NAME} />
296
+ <AvatarContent>
297
+ <AvatarName>{USER_NAME}</AvatarName>
298
+ <AvatarDescription>{USER_EMAIL}</AvatarDescription>
299
+ </AvatarContent>
300
+ </Avatar>
301
+ </div>
302
+ <DropdownMenuItem>
303
+ <DropdownMenuItemIcon>
304
+ <Settings />
305
+ </DropdownMenuItemIcon>
306
+ <DropdownMenuItemText>Profile settings</DropdownMenuItemText>
307
+ </DropdownMenuItem>
308
+ <DropdownMenu>
309
+ <DropdownMenuTriggerItem>
310
+ <DropdownMenuItemIcon>
311
+ <PencilRuler />
312
+ </DropdownMenuItemIcon>
313
+ <DropdownMenuItemContent>
314
+ <DropdownMenuItemText>Appearance</DropdownMenuItemText>
315
+ <Text size='xs' color='secondary'>
316
+ {THEME_LABELS[theme]} and {FRAME_STYLE_LABELS[frameStyle].toLowerCase()}
317
+ </Text>
318
+ </DropdownMenuItemContent>
319
+ </DropdownMenuTriggerItem>
320
+ <DropdownMenuContent className='w-132'>
321
+ <DropdownMenuRadioGroup
322
+ value={theme}
323
+ onValueChange={({ value }) => {
324
+ const next = THEMES.find(t => t === value);
325
+ if (next) onThemeChange(next);
326
+ }}
327
+ >
328
+ {THEMES.map(t => (
329
+ <DropdownMenuRadioItem key={t} value={t}>
330
+ <DropdownMenuItemText>{THEME_LABELS[t]}</DropdownMenuItemText>
331
+ </DropdownMenuRadioItem>
332
+ ))}
333
+ </DropdownMenuRadioGroup>
334
+ <DropdownMenuSeparator />
335
+ <DropdownMenuRadioGroup
336
+ value={frameStyle}
337
+ onValueChange={({ value }) => {
338
+ const next = FRAME_STYLES.find(s => s === value);
339
+ if (next) setFrameStyle(next);
340
+ }}
341
+ >
342
+ {FRAME_STYLES.map(s => (
343
+ <DropdownMenuRadioItem key={s} value={s}>
344
+ <DropdownMenuItemIcon>
345
+ <span className='flex size-16 items-center justify-center'>
346
+ <span className={cn('size-8 rounded-full', FRAME_STYLE_SWATCH[s])} />
347
+ </span>
348
+ </DropdownMenuItemIcon>
349
+ <DropdownMenuItemText>{FRAME_STYLE_LABELS[s]}</DropdownMenuItemText>
350
+ </DropdownMenuRadioItem>
351
+ ))}
352
+ </DropdownMenuRadioGroup>
353
+ </DropdownMenuContent>
354
+ </DropdownMenu>
355
+ <DropdownMenu>
356
+ <DropdownMenuTriggerItem>
357
+ <DropdownMenuItemIcon>
358
+ <PanelLeftDashed />
359
+ </DropdownMenuItemIcon>
360
+ <DropdownMenuItemContent>
361
+ <DropdownMenuItemText>Sidebar mode</DropdownMenuItemText>
362
+ <Text size='xs' color='secondary'>
363
+ {SIDEBAR_MODE_LABELS[sidebarMode]}
364
+ </Text>
365
+ </DropdownMenuItemContent>
366
+ </DropdownMenuTriggerItem>
367
+ <DropdownMenuContent className='w-200'>
368
+ <DropdownMenuRadioGroup
369
+ value={sidebarMode}
370
+ onValueChange={({ value }) => {
371
+ const next = SIDEBAR_MODES.find(m => m === value);
372
+ if (next) onSidebarModeChange(next);
373
+ }}
374
+ >
375
+ {SIDEBAR_MODE_GROUPS.map((group, index) => (
376
+ <Fragment key={group.join('-')}>
377
+ {index > 0 && <DropdownMenuSeparator />}
378
+ {group.map(m => (
379
+ <DropdownMenuRadioItem key={m} value={m}>
380
+ <DropdownMenuItemText>{SIDEBAR_MODE_LABELS[m]}</DropdownMenuItemText>
381
+ </DropdownMenuRadioItem>
382
+ ))}
383
+ </Fragment>
384
+ ))}
385
+ </DropdownMenuRadioGroup>
386
+ </DropdownMenuContent>
387
+ </DropdownMenu>
388
+ <DropdownMenuSeparator />
389
+ <DropdownMenuItem>
390
+ <DropdownMenuItemIcon>
391
+ <LogOut />
392
+ </DropdownMenuItemIcon>
393
+ <DropdownMenuItemText>Sign out</DropdownMenuItemText>
394
+ </DropdownMenuItem>
395
+ </DropdownMenuContent>
396
+ </DropdownMenu>
397
+ );
398
+ };
399
+ ```
400
+
401
+ ### AppShell/story-content/_storyConfigRenderer.tsx
402
+
403
+ ```tsx
404
+ import { type FC, type ReactNode, useEffect, useState } from 'react';
405
+ import { useNavigate } from '@tanstack/react-router';
406
+ import { Page, PageContent, PageHeader, PageTitle } from '../../Page';
407
+ import {
408
+ type NavConfig,
409
+ RemoteShell,
410
+ RemoteShellBreadcrumb,
411
+ RemoteShellContent,
412
+ RemoteShellPanel,
413
+ useRemoteShellContext,
414
+ } from '../../RemoteShell';
415
+ import { HomeContent } from './_storyHomeContent';
416
+ import { PRODUCT_CONFIGS, type Product } from './_storyLib';
417
+ import { useStoryPathname } from './_storyRouter';
418
+
419
+ export interface ConfigRemoteProps {
420
+ config: NavConfig;
421
+ basePath?: string;
422
+ /** Fake a 2s load when the product opens, to show the panel and content skeletons. */
423
+ simulateLoading?: boolean;
424
+ /** Page content; defaults to a placeholder page titled after the breadcrumbs. */
425
+ children?: ReactNode;
426
+ }
427
+
428
+ const RemotePageContent: FC = () => {
429
+ const { breadcrumbSegments } = useRemoteShellContext();
430
+
431
+ const lastSegment = breadcrumbSegments[breadcrumbSegments.length - 1];
432
+ const pageTitle = lastSegment?.label ?? '';
433
+ const fullPath = breadcrumbSegments.map(s => s.label).join(' / ');
434
+
435
+ return (
436
+ <Page title={pageTitle} fixedHeight>
437
+ <PageHeader>
438
+ <PageTitle>{pageTitle}</PageTitle>
439
+ </PageHeader>
440
+ <PageContent>
441
+ <p className='text-sm text-text-secondary'>Placeholder page for {fullPath}.</p>
442
+ </PageContent>
443
+ </Page>
444
+ );
445
+ };
446
+
447
+ /**
448
+ * A product remote wired to TanStack Router the recommended way: the router owns the
449
+ * URL, `RemoteShell` gets the router's pathname (`pathname`) and hands navigations
450
+ * back to it (`onNavigate`). Must render inside a router (`StoryRouter`).
451
+ */
452
+ export const ConfigRemote: FC<ConfigRemoteProps> = ({
453
+ config,
454
+ basePath,
455
+ simulateLoading = true,
456
+ children,
457
+ }) => {
458
+ const navigate = useNavigate();
459
+ const pathname = useStoryPathname();
460
+ const [loading, setLoading] = useState(simulateLoading);
461
+
462
+ // Remounted per product (see `RemoteForProduct`), so this runs once per product.
463
+ useEffect(() => {
464
+ if (!simulateLoading) return;
465
+ const timer = setTimeout(() => setLoading(false), 2000);
466
+ return () => clearTimeout(timer);
467
+ }, [simulateLoading]);
468
+
469
+ return (
470
+ <RemoteShell
471
+ config={config}
472
+ basePath={basePath}
473
+ pathname={pathname}
474
+ onNavigate={to => navigate({ to })}
475
+ >
476
+ {loading ? (
477
+ <>
478
+ <RemoteShellPanel isLoading />
479
+ <RemoteShellContent isLoading />
480
+ </>
481
+ ) : (
482
+ <>
483
+ <RemoteShellPanel resizable />
484
+ <RemoteShellBreadcrumb />
485
+ <RemoteShellContent>{children ?? <RemotePageContent />}</RemoteShellContent>
486
+ </>
487
+ )}
488
+ </RemoteShell>
489
+ );
490
+ };
491
+
492
+ export const RemoteForProduct = ({
493
+ product,
494
+ simulateLoading = true,
495
+ }: {
496
+ product: Product;
497
+ simulateLoading?: boolean;
498
+ }) => {
499
+ if (product === 'home') return <HomeContent />;
500
+ const { config } = PRODUCT_CONFIGS[product];
501
+ // Keyed by product: each product is its own remote, so its drill-transition and
502
+ // loading state never carry over to the next one.
503
+ return (
504
+ <ConfigRemote
505
+ key={product}
506
+ config={config}
507
+ basePath={`/${product}`}
508
+ simulateLoading={simulateLoading}
509
+ />
510
+ );
511
+ };
512
+ ```
513
+
514
+ ### AppShell/story-content/_storyHeaderActions.tsx
515
+
516
+ ```tsx
517
+ import type { ReactNode } from 'react';
518
+ import { ChevronUpDown } from '../../../icons';
519
+ import { Button } from '../../Button';
520
+ import { Code } from '../../Code';
521
+ import { Text } from '../../Text';
522
+ import { TopHeaderSeparator } from '../../TopHeader';
523
+ import { NotificationsInbox } from './_storyNotificationsInbox';
524
+ import { QuickHelpDropdown } from './_storyQuickHelpDropdown';
525
+ import { StorySearchModal } from './_storySearchModal';
526
+
527
+ interface HeaderActionsProps {
528
+ /** Rendered before the notifications bell — where the host puts its AI Assistant toggle. */
529
+ assistantToggle?: ReactNode;
530
+ }
531
+
532
+ export const HeaderActions = ({ assistantToggle }: HeaderActionsProps) => (
533
+ <>
534
+ <StorySearchModal />
535
+
536
+ <TopHeaderSeparator />
537
+
538
+ <Button variant='ghost' size='small' color='neutral' className='py-4 rounded-6'>
539
+ <Text size='xs' weight='medium'>
540
+ Tenant Name
541
+ </Text>
542
+ <span className='text-text-tertiary mx-[-2px]'>•</span>
543
+ <Code size='s' color='secondary'>
544
+ 12345
545
+ </Code>
546
+ <ChevronUpDown className='!icon-sm' />
547
+ </Button>
548
+
549
+ {assistantToggle}
550
+
551
+ <NotificationsInbox />
552
+
553
+ <QuickHelpDropdown />
554
+ </>
555
+ );
556
+ ```
557
+
558
+ ### AppShell/story-content/_storyHomeContent.tsx
559
+
560
+ ```tsx
561
+ import type { FC } from 'react';
562
+
563
+ export const HomeContent: FC = () => (
564
+ <div className='p-24'>
565
+ <h1 className='text-xl font-semibold text-text-primary'>Home</h1>
566
+ <p className='mt-4 text-sm text-text-secondary'>
567
+ Cross-product summary. Click any product in the rail to drill into it.
568
+ </p>
569
+ </div>
570
+ );
571
+ ```
572
+
573
+ ### AppShell/story-content/_storyLib.ts
574
+
575
+ ```tsx
576
+ import { findFirstLinkPath } from '../../RemoteShell';
577
+ import {
578
+ aiHypervisorNavConfig,
579
+ edgeNavConfig,
580
+ infraDiscoveryNavConfig,
581
+ securityTestingNavConfig,
582
+ settingsNavConfig,
583
+ } from './_storyNavConfigs';
584
+
585
+ const KNOWN_PRODUCTS = [
586
+ 'home',
587
+ 'edge',
588
+ 'ai-hypervisor',
589
+ 'infra-discovery',
590
+ 'security-testing',
591
+ 'settings',
592
+ ] as const;
593
+
594
+ export type Product = (typeof KNOWN_PRODUCTS)[number];
595
+
596
+ export const PRODUCT_CONFIGS: Record<Exclude<Product, 'home'>, { config: typeof edgeNavConfig }> = {
597
+ edge: { config: edgeNavConfig },
598
+ 'ai-hypervisor': { config: aiHypervisorNavConfig },
599
+ 'infra-discovery': { config: infraDiscoveryNavConfig },
600
+ 'security-testing': { config: securityTestingNavConfig },
601
+ settings: { config: settingsNavConfig },
602
+ };
603
+
604
+ export function deriveProduct(pathname: string): Product {
605
+ const segment = pathname.split('/').filter(Boolean)[0];
606
+ if (segment && (KNOWN_PRODUCTS as readonly string[]).includes(segment)) {
607
+ return segment as Product;
608
+ }
609
+ return 'home';
610
+ }
611
+
612
+ /** Landing URL of a product: its first link, or `/home`. */
613
+ export function productLandingPath(product: Product): string {
614
+ if (product === 'home') return '/home';
615
+ const { config } = PRODUCT_CONFIGS[product];
616
+ const firstPath = findFirstLinkPath(config.items) ?? '';
617
+ return `/${product}/${firstPath}`;
618
+ }
619
+ ```
620
+
621
+ ### AppShell/story-content/_storyNavConfigs.ts
622
+
623
+ ```tsx
624
+ import { CircleDashed, Filter, Plus } from '../../../icons';
625
+ import type { NavConfig } from '../../RemoteShell';
626
+
627
+ export const edgeNavConfig: NavConfig = {
628
+ productLabel: 'Edge',
629
+ productPath: '/edge',
630
+ headerActions: [
631
+ { icon: Filter, label: 'Filter', onClick: () => alert('Filter clicked') },
632
+ { icon: Plus, label: 'Add', onClick: () => alert('Add clicked') },
633
+ ],
634
+ items: [
635
+ { type: 'link', id: 'overview', label: 'Overview', path: 'overview', icon: CircleDashed },
636
+ {
637
+ type: 'drill',
638
+ id: 'data-planes',
639
+ label: 'Data planes',
640
+ path: 'data-planes',
641
+ icon: CircleDashed,
642
+ param: 'dataPlaneId',
643
+ entities: [
644
+ { id: 'production', label: 'Production', description: 'Main production environment' },
645
+ { id: 'staging', label: 'Staging', description: 'Pre-production testing' },
646
+ { id: 'edge-eu', label: 'Edge EU', description: 'European edge nodes' },
647
+ { id: 'edge-us', label: 'Edge US', description: 'US edge nodes' },
648
+ ],
649
+ children: [
650
+ {
651
+ type: 'link',
652
+ id: 'dp-overview',
653
+ label: 'Overview',
654
+ path: 'overview',
655
+ icon: CircleDashed,
656
+ },
657
+ {
658
+ type: 'drill',
659
+ id: 'dp-nodes',
660
+ label: 'Nodes',
661
+ path: 'nodes',
662
+ icon: CircleDashed,
663
+ param: 'nodeId',
664
+ entities: [
665
+ { id: 'node-1', label: 'Node 1', description: 'Primary node' },
666
+ { id: 'node-2', label: 'Node 2', description: 'Secondary node' },
667
+ { id: 'node-3', label: 'Node 3', description: 'Tertiary node' },
668
+ ],
669
+ children: [
670
+ {
671
+ type: 'link',
672
+ id: 'node-overview',
673
+ label: 'Overview',
674
+ path: 'overview',
675
+ icon: CircleDashed,
676
+ },
677
+ {
678
+ type: 'link',
679
+ id: 'node-metrics',
680
+ label: 'Metrics',
681
+ path: 'metrics',
682
+ icon: CircleDashed,
683
+ },
684
+ { type: 'link', id: 'node-logs', label: 'Logs', path: 'logs', icon: CircleDashed },
685
+ {
686
+ type: 'link',
687
+ id: 'node-config',
688
+ label: 'Configuration',
689
+ path: 'config',
690
+ icon: CircleDashed,
691
+ },
692
+ ],
693
+ },
694
+ {
695
+ type: 'link',
696
+ id: 'dp-services',
697
+ label: 'Services',
698
+ path: 'services',
699
+ icon: CircleDashed,
700
+ dividerAfter: true,
701
+ },
702
+ { type: 'link', id: 'dp-govern', label: 'Govern', path: 'govern', icon: CircleDashed },
703
+ {
704
+ type: 'group',
705
+ id: 'dp-operations',
706
+ label: 'Operations',
707
+ icon: CircleDashed,
708
+ children: [
709
+ {
710
+ type: 'link',
711
+ id: 'dp-routing-rules',
712
+ label: 'Routing rules',
713
+ path: 'routing-rules',
714
+ },
715
+ { type: 'link', id: 'dp-settings', label: 'Settings', path: 'settings' },
716
+ ],
717
+ },
718
+ ],
719
+ },
720
+ {
721
+ type: 'link',
722
+ id: 'dashboards',
723
+ label: 'Dashboards',
724
+ path: 'dashboards',
725
+ icon: CircleDashed,
726
+ dividerAfter: true,
727
+ },
728
+ { type: 'section-header', id: 'section-detect', label: 'Detect & Respond' },
729
+ {
730
+ type: 'group',
731
+ id: 'events',
732
+ label: 'Events',
733
+ icon: CircleDashed,
734
+ defaultExpanded: true,
735
+ children: [
736
+ { type: 'link', id: 'attacks', label: 'Attacks', path: 'attacks' },
737
+ { type: 'link', id: 'incidents', label: 'Incidents', path: 'incidents' },
738
+ { type: 'link', id: 'security-issues', label: 'Security Issues', path: 'security-issues' },
739
+ { type: 'link', id: 'api-sessions', label: 'API Sessions', path: 'api-sessions' },
740
+ ],
741
+ },
742
+ {
743
+ type: 'group',
744
+ id: 'api-security',
745
+ label: 'API Security',
746
+ icon: CircleDashed,
747
+ children: [
748
+ {
749
+ type: 'link',
750
+ id: 'api-attack-surface',
751
+ label: 'API Attack Surface',
752
+ path: 'api-attack-surface',
753
+ },
754
+ { type: 'link', id: 'api-discovery', label: 'API Discovery', path: 'api-discovery' },
755
+ {
756
+ type: 'link',
757
+ id: 'api-abuse-prevention',
758
+ label: 'API Abuse Prevention',
759
+ path: 'api-abuse-prevention',
760
+ },
761
+ {
762
+ type: 'link',
763
+ id: 'api-specifications',
764
+ label: 'API Specifications',
765
+ path: 'api-specifications',
766
+ },
767
+ ],
768
+ },
769
+ {
770
+ type: 'group',
771
+ id: 'security-controls',
772
+ label: 'Security controls',
773
+ icon: CircleDashed,
774
+ children: [
775
+ {
776
+ type: 'link',
777
+ id: 'ip-session-lists',
778
+ label: 'IP & Session Lists',
779
+ path: 'ip-session-lists',
780
+ },
781
+ { type: 'link', id: 'triggers', label: 'Triggers', path: 'triggers' },
782
+ { type: 'link', id: 'rules', label: 'Rules', path: 'rules' },
783
+ {
784
+ type: 'link',
785
+ id: 'mitigation-controls',
786
+ label: 'Mitigation Controls',
787
+ path: 'mitigation-controls',
788
+ },
789
+ {
790
+ type: 'link',
791
+ id: 'credential-stuffing',
792
+ label: 'Credential Stuffing',
793
+ path: 'credential-stuffing',
794
+ },
795
+ ],
796
+ },
797
+ { type: 'section-header', id: 'section-protect', label: 'Protect' },
798
+ {
799
+ type: 'group',
800
+ id: 'security-testing',
801
+ label: 'Security Testing',
802
+ icon: CircleDashed,
803
+ children: [
804
+ { type: 'link', id: 'threat-replay', label: 'Threat Replay', path: 'threat-replay' },
805
+ { type: 'link', id: 'schema-based', label: 'Schema-Based', path: 'schema-based' },
806
+ ],
807
+ },
808
+ {
809
+ type: 'group',
810
+ id: 'configuration',
811
+ label: 'Configuration',
812
+ icon: CircleDashed,
813
+ children: [
814
+ {
815
+ type: 'group',
816
+ id: 'nodes',
817
+ label: 'Nodes',
818
+ children: [
819
+ {
820
+ type: 'link',
821
+ id: 'nodes-overview',
822
+ label: 'Overview',
823
+ path: 'nodes-overview',
824
+ },
825
+ { type: 'link', id: 'nodes-pools', label: 'Pools', path: 'nodes-pools' },
826
+ {
827
+ type: 'link',
828
+ id: 'nodes-health-checks',
829
+ label: 'Health checks',
830
+ path: 'nodes-health-checks',
831
+ },
832
+ ],
833
+ },
834
+ { type: 'link', id: 'security-edge', label: 'Security Edge', path: 'security-edge' },
835
+ { type: 'link', id: 'integrations', label: 'Integrations', path: 'integrations' },
836
+ ],
837
+ },
838
+ ],
839
+ };
840
+
841
+ export const aiHypervisorNavConfig: NavConfig = {
842
+ productLabel: 'AI Hypervisor',
843
+ productPath: '/ai-hypervisor',
844
+ items: [
845
+ { type: 'link', id: 'heatmap', label: 'Heatmap', path: 'heatmap', icon: CircleDashed },
846
+ { type: 'link', id: 'registry', label: 'Registry', path: 'registry', icon: CircleDashed },
847
+ {
848
+ type: 'group',
849
+ id: 'topology',
850
+ label: 'Topology',
851
+ icon: CircleDashed,
852
+ defaultExpanded: true,
853
+ children: [
854
+ {
855
+ type: 'link',
856
+ id: 'topology-overview',
857
+ label: 'Overview',
858
+ path: 'topology-overview',
859
+ },
860
+ {
861
+ type: 'link',
862
+ id: 'topology-services',
863
+ label: 'Services',
864
+ path: 'topology-services',
865
+ },
866
+ {
867
+ type: 'group',
868
+ id: 'graphs',
869
+ label: 'Graphs',
870
+ children: [
871
+ { type: 'link', id: 'flow-graph', label: 'Flow graph', path: 'flow-graph' },
872
+ {
873
+ type: 'link',
874
+ id: 'dependency-graph',
875
+ label: 'Dependency graph',
876
+ path: 'dependency-graph',
877
+ },
878
+ {
879
+ type: 'link',
880
+ id: 'traffic-graph',
881
+ label: 'Traffic graph',
882
+ path: 'traffic-graph',
883
+ },
884
+ ],
885
+ },
886
+ ],
887
+ },
888
+ {
889
+ type: 'link',
890
+ id: 'data-tracks',
891
+ label: 'Data Tracks',
892
+ path: 'data-tracks',
893
+ icon: CircleDashed,
894
+ },
895
+ {
896
+ type: 'link',
897
+ id: 'user-tracks',
898
+ label: 'User Tracks',
899
+ path: 'user-tracks',
900
+ icon: CircleDashed,
901
+ },
902
+ {
903
+ type: 'link',
904
+ id: 'supply-chain',
905
+ label: 'Supply Chain',
906
+ path: 'supply-chain',
907
+ icon: CircleDashed,
908
+ },
909
+ {
910
+ type: 'link',
911
+ id: 'enforcement',
912
+ label: 'Enforcement',
913
+ path: 'enforcement',
914
+ icon: CircleDashed,
915
+ },
916
+ {
917
+ type: 'link',
918
+ id: 'ai-integrations',
919
+ label: 'Integrations',
920
+ path: 'ai-integrations',
921
+ icon: CircleDashed,
922
+ },
923
+ { type: 'link', id: 'red-team', label: 'Red Team', path: 'red-team', icon: CircleDashed },
924
+ { type: 'link', id: 'debugger', label: 'Debugger', path: 'debugger', icon: CircleDashed },
925
+ ],
926
+ };
927
+
928
+ export const infraDiscoveryNavConfig: NavConfig = {
929
+ productLabel: 'Infra Discovery',
930
+ productPath: '/infra-discovery',
931
+ headerActions: [{ icon: Filter, label: 'Filter', onClick: () => alert('Filter clicked') }],
932
+ items: [
933
+ { type: 'link', id: 'overview', label: 'Overview', path: 'overview', icon: CircleDashed },
934
+ {
935
+ type: 'group',
936
+ id: 'inventory',
937
+ label: 'Inventory',
938
+ icon: CircleDashed,
939
+ defaultExpanded: true,
940
+ children: [
941
+ { type: 'link', id: 'all-assets', label: 'All assets', path: 'all-assets' },
942
+ { type: 'link', id: 'untagged', label: 'Untagged', path: 'untagged' },
943
+ {
944
+ type: 'group',
945
+ id: 'by-source',
946
+ label: 'By source',
947
+ children: [
948
+ {
949
+ type: 'link',
950
+ id: 'cloud-accounts',
951
+ label: 'Cloud accounts',
952
+ path: 'cloud-accounts',
953
+ },
954
+ { type: 'link', id: 'kubernetes', label: 'Kubernetes', path: 'kubernetes' },
955
+ {
956
+ type: 'link',
957
+ id: 'source-control',
958
+ label: 'Source control',
959
+ path: 'source-control',
960
+ },
961
+ ],
962
+ },
963
+ ],
964
+ },
965
+ { type: 'link', id: 'topology', label: 'Topology', path: 'topology', icon: CircleDashed },
966
+ { type: 'link', id: 'findings', label: 'Findings', path: 'findings', icon: CircleDashed },
967
+ { type: 'link', id: 'risks', label: 'Risks', path: 'risks', icon: CircleDashed },
968
+ {
969
+ type: 'link',
970
+ id: 'infra-integrations',
971
+ label: 'Integrations',
972
+ path: 'infra-integrations',
973
+ icon: CircleDashed,
974
+ },
975
+ {
976
+ type: 'link',
977
+ id: 'infra-settings',
978
+ label: 'Settings',
979
+ path: 'infra-settings',
980
+ icon: CircleDashed,
981
+ },
982
+ ],
983
+ };
984
+
985
+ export const securityTestingNavConfig: NavConfig = {
986
+ productLabel: 'Security Testing',
987
+ productPath: '/security-testing',
988
+ items: [
989
+ { type: 'link', id: 'overview', label: 'Overview', path: 'overview', icon: CircleDashed },
990
+ {
991
+ type: 'link',
992
+ id: 'test-suites',
993
+ label: 'Test Suites',
994
+ path: 'test-suites',
995
+ icon: CircleDashed,
996
+ },
997
+ {
998
+ type: 'group',
999
+ id: 'templates',
1000
+ label: 'Templates',
1001
+ icon: CircleDashed,
1002
+ children: [
1003
+ { type: 'link', id: 'owasp', label: 'OWASP', path: 'owasp' },
1004
+ { type: 'link', id: 'pci-dss', label: 'PCI DSS', path: 'pci-dss' },
1005
+ { type: 'link', id: 'internal', label: 'Internal', path: 'internal' },
1006
+ ],
1007
+ },
1008
+ { type: 'link', id: 'schedules', label: 'Schedules', path: 'schedules', icon: CircleDashed },
1009
+ { type: 'link', id: 'results', label: 'Results', path: 'results', icon: CircleDashed },
1010
+ { type: 'link', id: 'coverage', label: 'Coverage', path: 'coverage', icon: CircleDashed },
1011
+ {
1012
+ type: 'link',
1013
+ id: 'testing-settings',
1014
+ label: 'Settings',
1015
+ path: 'testing-settings',
1016
+ icon: CircleDashed,
1017
+ },
1018
+ ],
1019
+ };
1020
+
1021
+ export const settingsNavConfig: NavConfig = {
1022
+ productLabel: 'Settings',
1023
+ productPath: '/settings',
1024
+ items: [
1025
+ { type: 'link', id: 'profile', label: 'Profile', path: 'profile', icon: CircleDashed },
1026
+ { type: 'link', id: 'general', label: 'General', path: 'general', icon: CircleDashed },
1027
+ {
1028
+ type: 'link',
1029
+ id: 'subscriptions',
1030
+ label: 'Subscriptions',
1031
+ path: 'subscriptions',
1032
+ icon: CircleDashed,
1033
+ },
1034
+ {
1035
+ type: 'link',
1036
+ id: 'applications',
1037
+ label: 'Applications',
1038
+ path: 'applications',
1039
+ icon: CircleDashed,
1040
+ },
1041
+ {
1042
+ type: 'group',
1043
+ id: 'users',
1044
+ label: 'Users',
1045
+ icon: CircleDashed,
1046
+ defaultExpanded: true,
1047
+ children: [
1048
+ { type: 'link', id: 'users-all', label: 'All users', path: 'users-all' },
1049
+ {
1050
+ type: 'link',
1051
+ id: 'users-invites',
1052
+ label: 'Pending invites',
1053
+ path: 'users-invites',
1054
+ },
1055
+ { type: 'link', id: 'users-roles', label: 'Roles', path: 'users-roles' },
1056
+ ],
1057
+ },
1058
+ { type: 'section-header', id: 'section-access', label: 'Access Management' },
1059
+ { type: 'link', id: 'groups', label: 'Groups', path: 'groups', icon: CircleDashed },
1060
+ { type: 'link', id: 'api-tokens', label: 'API Tokens', path: 'api-tokens', icon: CircleDashed },
1061
+ {
1062
+ type: 'link',
1063
+ id: 'activity-log',
1064
+ label: 'Activity Log',
1065
+ path: 'activity-log',
1066
+ icon: CircleDashed,
1067
+ dividerAfter: true,
1068
+ },
1069
+ {
1070
+ type: 'group',
1071
+ id: 'admin-zone',
1072
+ label: 'Admin Zone',
1073
+ icon: CircleDashed,
1074
+ defaultExpanded: true,
1075
+ children: [
1076
+ {
1077
+ type: 'link',
1078
+ id: 'customer-settings',
1079
+ label: 'Customer Settings',
1080
+ path: 'customer-settings',
1081
+ },
1082
+ {
1083
+ type: 'group',
1084
+ id: 'system-configuration',
1085
+ label: 'System Configuration',
1086
+ children: [
1087
+ { type: 'link', id: 'sys-general', label: 'General', path: 'sys-general' },
1088
+ { type: 'link', id: 'sys-storage', label: 'Storage', path: 'sys-storage' },
1089
+ {
1090
+ type: 'link',
1091
+ id: 'sys-networking',
1092
+ label: 'Networking',
1093
+ path: 'sys-networking',
1094
+ },
1095
+ ],
1096
+ },
1097
+ {
1098
+ type: 'link',
1099
+ id: 'bola-triggers',
1100
+ label: 'BOLA Triggers',
1101
+ path: 'bola-triggers',
1102
+ },
1103
+ { type: 'link', id: 'experiments', label: 'Experiments', path: 'experiments' },
1104
+ ],
1105
+ },
1106
+ ],
1107
+ };
1108
+ ```
1109
+
1110
+ ### AppShell/story-content/_storyNavRailFooter.tsx
1111
+
1112
+ ```tsx
1113
+ import type { FC } from 'react';
1114
+ import { Settings } from '../../../icons';
1115
+ import { NavRailFooter, NavRailItem } from '../../NavRail';
1116
+ import type { Theme } from '../../ThemeProvider';
1117
+ import { AccountDropdown, type SidebarMode } from './_storyAccountDropdown';
1118
+ import type { Product } from './_storyLib';
1119
+
1120
+ interface NavRailFooterContentProps {
1121
+ activeProduct: Product;
1122
+ onSelectProduct: (product: Product) => void;
1123
+ sidebarMode: SidebarMode;
1124
+ onSidebarModeChange: (mode: SidebarMode) => void;
1125
+ theme: Theme;
1126
+ onThemeChange: (theme: Theme) => void;
1127
+ }
1128
+
1129
+ export const NavRailFooterContent: FC<NavRailFooterContentProps> = ({
1130
+ activeProduct,
1131
+ onSelectProduct,
1132
+ sidebarMode,
1133
+ onSidebarModeChange,
1134
+ theme,
1135
+ onThemeChange,
1136
+ }) => (
1137
+ <NavRailFooter>
1138
+ <NavRailItem
1139
+ icon={Settings}
1140
+ label='Settings'
1141
+ shortcut={['G', 'S']}
1142
+ active={activeProduct === 'settings'}
1143
+ onClick={() => onSelectProduct('settings')}
1144
+ />
1145
+ <AccountDropdown
1146
+ sidebarMode={sidebarMode}
1147
+ onSidebarModeChange={onSidebarModeChange}
1148
+ theme={theme}
1149
+ onThemeChange={onThemeChange}
1150
+ />
1151
+ </NavRailFooter>
1152
+ );
1153
+ ```
1154
+
1155
+ ### AppShell/story-content/_storyNotificationsInbox.tsx
1156
+
1157
+ ```tsx
1158
+ import { Settings } from '../../../icons';
1159
+ import {
1160
+ NotificationCenter,
1161
+ NotificationCenterBody,
1162
+ NotificationCenterContent,
1163
+ NotificationCenterHeader,
1164
+ NotificationCenterHeaderAction,
1165
+ NotificationCenterHeaderActions,
1166
+ NotificationCenterItem,
1167
+ NotificationCenterItemDescription,
1168
+ NotificationCenterItemTime,
1169
+ NotificationCenterItemTitle,
1170
+ NotificationCenterList,
1171
+ NotificationCenterSkeleton,
1172
+ NotificationCenterTabs,
1173
+ NotificationCenterTabsList,
1174
+ NotificationCenterTitle,
1175
+ NotificationCenterTrigger,
1176
+ } from '../../NotificationCenter';
1177
+ import { NumericBadge } from '../../NumericBadge';
1178
+ import { TabsContent, TabsTrigger } from '../../Tabs';
1179
+
1180
+ const MINUTE = 60_000;
1181
+ const minutesAgo = (minutes: number) => new Date(Date.now() - minutes * MINUTE);
1182
+
1183
+ const NEW = [
1184
+ {
1185
+ id: 'attack',
1186
+ title: 'New attack detected on api.example.com',
1187
+ description: '214 SQL injection attempts from 12 IPs in the last 10 minutes.',
1188
+ createdAt: minutesAgo(3),
1189
+ },
1190
+ {
1191
+ id: 'node',
1192
+ title: 'Node wallarm-node-3 is offline',
1193
+ description: 'No heartbeat for 15 minutes. Traffic fails over to wallarm-node-1.',
1194
+ createdAt: minutesAgo(22),
1195
+ },
1196
+ ];
1197
+
1198
+ const READ = [
1199
+ {
1200
+ id: 'report',
1201
+ title: 'Weekly API discovery report is ready',
1202
+ description: '38 new endpoints this week, 5 of them handling sensitive data.',
1203
+ createdAt: minutesAgo(60 * 24 * 7),
1204
+ },
1205
+ ];
1206
+
1207
+ /** The host's inbox, as core-frontend's NotificationsInbox: bell with the unread count, New/Read tabs. */
1208
+ export const NotificationsInbox = ({ loading = false }: { loading?: boolean }) => (
1209
+ <NotificationCenter data-testid='notifications'>
1210
+ <NotificationCenterTrigger count={loading ? 0 : NEW.length} />
1211
+ <NotificationCenterContent>
1212
+ <NotificationCenterHeader>
1213
+ <NotificationCenterTitle />
1214
+ <NotificationCenterHeaderActions>
1215
+ <NotificationCenterHeaderAction disabled={loading}>
1216
+ Mark all as read
1217
+ </NotificationCenterHeaderAction>
1218
+ <NotificationCenterHeaderAction asChild aria-label='Notification settings'>
1219
+ <a href='#notification-settings'>
1220
+ <Settings />
1221
+ </a>
1222
+ </NotificationCenterHeaderAction>
1223
+ </NotificationCenterHeaderActions>
1224
+ </NotificationCenterHeader>
1225
+ {loading ? (
1226
+ <NotificationCenterBody>
1227
+ <NotificationCenterSkeleton />
1228
+ </NotificationCenterBody>
1229
+ ) : (
1230
+ <NotificationCenterTabs defaultValue='new'>
1231
+ <NotificationCenterTabsList>
1232
+ <TabsTrigger value='new'>
1233
+ New <NumericBadge size='small'>{NEW.length}</NumericBadge>
1234
+ </TabsTrigger>
1235
+ <TabsTrigger value='read'>Read</TabsTrigger>
1236
+ </NotificationCenterTabsList>
1237
+ {[
1238
+ { value: 'new', items: NEW },
1239
+ { value: 'read', items: READ },
1240
+ ].map(tab => (
1241
+ <TabsContent key={tab.value} value={tab.value}>
1242
+ <NotificationCenterBody>
1243
+ <NotificationCenterList>
1244
+ {tab.items.map(item => (
1245
+ <NotificationCenterItem key={item.id} unread={tab.value === 'new'}>
1246
+ <NotificationCenterItemTitle>{item.title}</NotificationCenterItemTitle>
1247
+ <NotificationCenterItemTime value={item.createdAt} />
1248
+ <NotificationCenterItemDescription>
1249
+ {item.description}
1250
+ </NotificationCenterItemDescription>
1251
+ </NotificationCenterItem>
1252
+ ))}
1253
+ </NotificationCenterList>
1254
+ </NotificationCenterBody>
1255
+ </TabsContent>
1256
+ ))}
1257
+ </NotificationCenterTabs>
1258
+ )}
1259
+ </NotificationCenterContent>
1260
+ </NotificationCenter>
1261
+ );
1262
+ ```
1263
+
1264
+ ### AppShell/story-content/_storyProductNavItems.tsx
1265
+
1266
+ ```tsx
1267
+ import type { FC } from 'react';
1268
+ import { CircleDashed } from '../../../icons';
1269
+ import { NavRailItem } from '../../NavRail';
1270
+ import type { Product } from './_storyLib';
1271
+
1272
+ interface ProductNavItemsProps {
1273
+ activeProduct: Product;
1274
+ onSelectProduct: (product: Product) => void;
1275
+ }
1276
+
1277
+ export const ProductNavItems: FC<ProductNavItemsProps> = ({ activeProduct, onSelectProduct }) => (
1278
+ <>
1279
+ <NavRailItem
1280
+ icon={CircleDashed}
1281
+ label='Edge'
1282
+ shortcut={['G', 'E']}
1283
+ active={activeProduct === 'edge'}
1284
+ onClick={() => onSelectProduct('edge')}
1285
+ />
1286
+ <NavRailItem
1287
+ icon={CircleDashed}
1288
+ label='AI Hypervisor'
1289
+ shortcut={['G', 'A']}
1290
+ active={activeProduct === 'ai-hypervisor'}
1291
+ onClick={() => onSelectProduct('ai-hypervisor')}
1292
+ />
1293
+ <NavRailItem
1294
+ icon={CircleDashed}
1295
+ label='Infra Discovery'
1296
+ shortcut={['G', 'I']}
1297
+ active={activeProduct === 'infra-discovery'}
1298
+ onClick={() => onSelectProduct('infra-discovery')}
1299
+ />
1300
+ <NavRailItem
1301
+ icon={CircleDashed}
1302
+ label='Security Testing'
1303
+ shortcut={['G', 'T']}
1304
+ active={activeProduct === 'security-testing'}
1305
+ onClick={() => onSelectProduct('security-testing')}
1306
+ />
1307
+ </>
1308
+ );
1309
+ ```
1310
+
1311
+ ### AppShell/story-content/_storyQuickHelpDropdown.tsx
1312
+
1313
+ ```tsx
1314
+ import {
1315
+ Activity,
1316
+ Book,
1317
+ CircleHelp,
1318
+ LifeBuoy,
1319
+ NotebookText,
1320
+ SquareArrowOutUpRight,
1321
+ } from '../../../icons';
1322
+ import { Button } from '../../Button';
1323
+ import {
1324
+ DropdownMenu,
1325
+ DropdownMenuContent,
1326
+ DropdownMenuItem,
1327
+ DropdownMenuItemContent,
1328
+ DropdownMenuItemIcon,
1329
+ DropdownMenuItemText,
1330
+ DropdownMenuSeparator,
1331
+ DropdownMenuTrigger,
1332
+ } from '../../DropdownMenu';
1333
+ import { Text } from '../../Text';
1334
+ import { Tooltip, TooltipContent, TooltipTrigger } from '../../Tooltip';
1335
+
1336
+ export const QuickHelpDropdown = () => (
1337
+ <DropdownMenu positioning={{ placement: 'bottom-end', gutter: 4 }}>
1338
+ <Tooltip>
1339
+ <TooltipTrigger asChild>
1340
+ <span className='inline-flex'>
1341
+ <DropdownMenuTrigger asChild>
1342
+ <Button variant='ghost' size='small' color='neutral' aria-label='Quick Help'>
1343
+ <CircleHelp />
1344
+ </Button>
1345
+ </DropdownMenuTrigger>
1346
+ </span>
1347
+ </TooltipTrigger>
1348
+ <TooltipContent>Quick help</TooltipContent>
1349
+ </Tooltip>
1350
+
1351
+ <DropdownMenuContent className='w-320'>
1352
+ <DropdownMenuItem onSelect={() => window.open('https://docs.wallarm.com/', '_blank')}>
1353
+ <DropdownMenuItemIcon>
1354
+ <Book />
1355
+ </DropdownMenuItemIcon>
1356
+
1357
+ <DropdownMenuItemContent>
1358
+ <DropdownMenuItemText>Documentation</DropdownMenuItemText>
1359
+ <Text size='xs' color='secondary'>
1360
+ Setup, deployment, and how-tos
1361
+ </Text>
1362
+ </DropdownMenuItemContent>
1363
+ </DropdownMenuItem>
1364
+
1365
+ <DropdownMenuItem onSelect={() => window.open('https://status.wallarm.com/', '_blank')}>
1366
+ <DropdownMenuItemIcon>
1367
+ <Activity />
1368
+ </DropdownMenuItemIcon>
1369
+
1370
+ <DropdownMenuItemContent>
1371
+ <DropdownMenuItemText>Service status</DropdownMenuItemText>
1372
+ <Text size='xs' color='secondary'>
1373
+ Live uptime and alerts
1374
+ </Text>
1375
+ </DropdownMenuItemContent>
1376
+ </DropdownMenuItem>
1377
+
1378
+ <DropdownMenuItem onSelect={() => window.open('mailto:support@wallarm.com')}>
1379
+ <DropdownMenuItemIcon>
1380
+ <LifeBuoy />
1381
+ </DropdownMenuItemIcon>
1382
+
1383
+ <DropdownMenuItemContent>
1384
+ <DropdownMenuItemText>Support</DropdownMenuItemText>
1385
+ <Text size='xs' color='secondary'>
1386
+ Talk to our team
1387
+ </Text>
1388
+ </DropdownMenuItemContent>
1389
+ </DropdownMenuItem>
1390
+
1391
+ <DropdownMenuItem onSelect={() => window.open('https://lab.wallarm.com', '_blank')}>
1392
+ <DropdownMenuItemIcon>
1393
+ <NotebookText />
1394
+ </DropdownMenuItemIcon>
1395
+
1396
+ <DropdownMenuItemContent>
1397
+ <DropdownMenuItemText>Blog</DropdownMenuItemText>
1398
+ <Text size='xs' color='secondary'>
1399
+ Security news and updates
1400
+ </Text>
1401
+ </DropdownMenuItemContent>
1402
+ </DropdownMenuItem>
1403
+
1404
+ <DropdownMenuSeparator />
1405
+
1406
+ <DropdownMenuItem onSelect={() => window.open('https://playground.wallarm.com', '_blank')}>
1407
+ <DropdownMenuItemIcon>
1408
+ <SquareArrowOutUpRight />
1409
+ </DropdownMenuItemIcon>
1410
+
1411
+ <DropdownMenuItemContent>
1412
+ <DropdownMenuItemText>Wallarm Playground</DropdownMenuItemText>
1413
+ <Text size='xs' color='secondary'>
1414
+ Try the platform without any setup
1415
+ </Text>
1416
+ </DropdownMenuItemContent>
1417
+ </DropdownMenuItem>
1418
+ </DropdownMenuContent>
1419
+ </DropdownMenu>
1420
+ );
1421
+ ```
1422
+
1423
+ ### AppShell/story-content/_storyRecentDropdown.tsx
1424
+
1425
+ ```tsx
1426
+ import { History } from '../../../icons';
1427
+ import {
1428
+ DropdownMenu,
1429
+ DropdownMenuContent,
1430
+ DropdownMenuItem,
1431
+ DropdownMenuItemContent,
1432
+ DropdownMenuItemText,
1433
+ DropdownMenuLabel,
1434
+ DropdownMenuTrigger,
1435
+ } from '../../DropdownMenu';
1436
+ import { NavRailItem } from '../../NavRail';
1437
+ import { Text } from '../../Text';
1438
+
1439
+ const RECENT_ITEMS = [
1440
+ { pageName: 'WAF Rules', productName: 'Edge' },
1441
+ { pageName: 'API Sessions', dataPlane: 'US Cloud', productName: 'Edge' },
1442
+ { pageName: 'Prompt Inspector', productName: 'AI Hypervisor' },
1443
+ { pageName: 'Scanner Results', dataPlane: 'EU Cloud', productName: 'Security Testing' },
1444
+ { pageName: 'Asset Inventory', productName: 'Infra Discovery' },
1445
+ { pageName: 'Pupu', productName: 'Edge' },
1446
+ { pageName: 'Pupupu', dataPlane: 'US Cloud', productName: 'Edge' },
1447
+ { pageName: 'PuPuPuuu', productName: 'AI Hypervisor' },
1448
+ { pageName: 'MeowMeow', dataPlane: 'EU Cloud', productName: 'Security Testing' },
1449
+ { pageName: '...', productName: '....' },
1450
+ ];
1451
+
1452
+ export const RecentDropdown = () => (
1453
+ <DropdownMenu positioning={{ placement: 'right-start', gutter: 8 }}>
1454
+ <DropdownMenuTrigger>
1455
+ <NavRailItem icon={History} label='Recent' />
1456
+ </DropdownMenuTrigger>
1457
+
1458
+ <DropdownMenuContent className='w-304 h-290 overscroll-none'>
1459
+ <DropdownMenuLabel className='sticky top-0 z-10 bg-bg-surface-2'>Recent</DropdownMenuLabel>
1460
+
1461
+ {RECENT_ITEMS.map(item => (
1462
+ <DropdownMenuItem key={`${item.pageName}-${item.productName}`}>
1463
+ <DropdownMenuItemContent>
1464
+ <DropdownMenuItemText>{item.pageName}</DropdownMenuItemText>
1465
+ <Text size='xs' color='secondary'>
1466
+ {item.dataPlane ? `${item.dataPlane} \u00b7 ${item.productName}` : item.productName}
1467
+ </Text>
1468
+ </DropdownMenuItemContent>
1469
+ </DropdownMenuItem>
1470
+ ))}
1471
+ </DropdownMenuContent>
1472
+ </DropdownMenu>
1473
+ );
1474
+ ```
1475
+
1476
+ ### AppShell/story-content/_storyRouter.tsx
1477
+
1478
+ ```tsx
1479
+ import { createContext, type FC, type ReactNode, useCallback, useContext, useState } from 'react';
1480
+ import {
1481
+ createMemoryHistory,
1482
+ createRootRoute,
1483
+ createRoute,
1484
+ createRouter,
1485
+ RouterProvider,
1486
+ useNavigate,
1487
+ useRouterState,
1488
+ } from '@tanstack/react-router';
1489
+ import { deriveProduct, type Product, productLandingPath } from './_storyLib';
1490
+
1491
+ // Story-only harness: every story gets its own TanStack Router on a memory history,
1492
+ // so navigation never touches Storybook's iframe URL and stories don't share history.
1493
+ // `story-content/**` is excluded from the published build (see rslib.config.ts).
1494
+
1495
+ const StoryContentContext = createContext<ReactNode>(null);
1496
+
1497
+ const StoryContent: FC = () => <>{useContext(StoryContentContext)}</>;
1498
+
1499
+ const createStoryRouter = (initialPath: string) => {
1500
+ const rootRoute = createRootRoute({ component: StoryContent });
1501
+ // Catch-all so every product URL matches; the shell reads the pathname itself.
1502
+ const splatRoute = createRoute({ getParentRoute: () => rootRoute, path: '$' });
1503
+
1504
+ return createRouter({
1505
+ routeTree: rootRoute.addChildren([splatRoute]),
1506
+ history: createMemoryHistory({ initialEntries: [initialPath] }),
1507
+ });
1508
+ };
1509
+
1510
+ interface StoryRouterProps {
1511
+ /** Starting URL of the memory history. */
1512
+ initialPath?: string;
1513
+ children: ReactNode;
1514
+ }
1515
+
1516
+ /** Renders `children` inside a per-render TanStack Router with memory history. */
1517
+ export const StoryRouter: FC<StoryRouterProps> = ({ initialPath = '/home', children }) => {
1518
+ const [router] = useState(() => createStoryRouter(initialPath));
1519
+
1520
+ return (
1521
+ <StoryContentContext.Provider value={children}>
1522
+ <RouterProvider router={router} />
1523
+ </StoryContentContext.Provider>
1524
+ );
1525
+ };
1526
+
1527
+ StoryRouter.displayName = 'StoryRouter';
1528
+
1529
+ /** Current router pathname — what a host passes to `RemoteShell`'s `pathname` prop. */
1530
+ export const useStoryPathname = (): string =>
1531
+ useRouterState({ select: state => state.location.pathname });
1532
+
1533
+ /** Router-driven product navigation for the rail. */
1534
+ export const useStoryProductNavigation = () => {
1535
+ const navigate = useNavigate();
1536
+ const pathname = useStoryPathname();
1537
+
1538
+ const goToProduct = useCallback(
1539
+ (product: Product) => {
1540
+ navigate({ to: productLandingPath(product) });
1541
+ },
1542
+ [navigate],
1543
+ );
1544
+
1545
+ return { pathname, activeProduct: deriveProduct(pathname), goToProduct };
1546
+ };
1547
+ ```
1548
+
1549
+ ### AppShell/story-content/_storyWallarmLogo.tsx
1550
+
1551
+ ```tsx
1552
+ export const WallarmLogo = () => (
1553
+ <svg width='89' height='16' viewBox='0 0 89 16' fill='none' xmlns='http://www.w3.org/2000/svg'>
1554
+ <path
1555
+ fillRule='evenodd'
1556
+ clipRule='evenodd'
1557
+ d='M33.9026 4.87835H35.5876L37.698 11.2096L39.383 4.87835H41.4934L38.5405 14.1625H36.8555L34.7451 7.83127L32.6346 14.1625H30.9496L27.9884 4.87835H30.0988L31.7838 11.2096L33.8942 4.87835H33.9026ZM44.9886 12.7862C46.3733 12.7862 47.4076 12.0104 47.4076 10.8676V10.292C46.8738 10.0835 46.1314 9.92502 45.3139 9.92502C44.0042 9.92502 43.2201 10.4589 43.2201 11.3931V11.4265C43.2201 12.294 43.9959 12.7778 44.9802 12.7778L44.9886 12.7862ZM42.7613 5.35382C43.5371 5.07855 44.388 4.90337 45.5057 4.90337C48.2001 4.90337 49.518 6.24637 49.518 8.68212V14.1709H47.4076V13.0531C46.782 13.7955 45.8728 14.3627 44.4881 14.3627C42.7614 14.3627 41.2432 13.3784 41.2432 11.5433V11.5099C41.2432 9.5413 42.8197 8.57368 44.9385 8.57368C46.0479 8.57368 46.6986 8.73217 47.4076 8.95739V8.73217C47.4076 7.47258 46.6652 6.78023 45.2138 6.78023C44.2712 6.78023 43.5204 6.98043 42.7613 7.28073V5.3705V5.35382ZM50.786 14.1625V1.5H52.8964V14.1625H50.786ZM54.1643 14.1625V1.5H56.2747L56.3164 14.1625H54.1643ZM61.0378 12.7862C62.4225 12.7862 63.4569 12.0104 63.4569 10.8676V10.292C62.923 10.0835 62.1806 9.92502 61.3631 9.92502C60.0535 9.92502 59.2694 10.4589 59.2694 11.3931V11.4265C59.2694 12.294 60.0451 12.7778 61.0295 12.7778L61.0378 12.7862ZM58.8106 5.35382C59.578 5.07855 60.4372 4.90337 61.555 4.90337C64.2493 4.90337 65.5589 6.24637 65.5589 8.68212V14.1709H63.4485V13.0531C62.8229 13.7955 61.9137 14.3627 60.529 14.3627C58.8022 14.3627 57.2841 13.3784 57.2841 11.5433V11.5099C57.2841 9.5413 58.8606 8.57368 60.9794 8.57368C62.0888 8.57368 62.7395 8.73217 63.4485 8.95739V8.73217C63.4485 7.47258 62.7061 6.78023 61.2547 6.78023C60.3121 6.78023 59.5613 6.98043 58.8022 7.28073V5.3705L58.8106 5.35382ZM66.8269 14.1625V4.87835H68.9373V6.93872C69.5045 5.5707 70.5389 4.63644 72.1405 4.71152V6.92204H72.0237C70.1885 6.92204 68.9373 8.11489 68.9373 10.534V14.1709H66.8269V14.1625ZM87.0969 8.18162V14.1709H84.9865V8.94071C84.9865 7.48927 84.3359 6.58838 83.1597 6.58838C81.9835 6.58838 81.1911 7.47258 81.1911 8.94071V14.1709H79.0807V8.80724C79.0807 7.38917 78.43 6.58838 77.2705 6.58838C76.1111 6.58838 75.2769 7.52263 75.2769 8.94071V14.1709H73.1665V4.87835H75.2769V6.26305C75.8692 5.45392 76.695 4.68649 78.0964 4.68649C79.406 4.68649 80.3236 5.32879 80.8074 6.29642C81.5498 5.32879 82.5174 4.68649 83.9021 4.68649C85.8874 4.68649 87.0969 5.94607 87.0969 8.18162Z'
1558
+ fill='currentColor'
1559
+ />
1560
+ <path
1561
+ d='M0.849998 6.83954L9.8954 3V8.4134L16.4618 5.62599V9.59236L21.2757 7.54864V10.4542L16.4618 12.498V10.754L9.8954 13.5414V11.1662L0.849998 15V6.83954Z'
1562
+ fill='#FF441C'
1563
+ />
1564
+ </svg>
1565
+ );
1566
+ ```
1567
+
1568
+ ### ../utils/cn.ts
1569
+
1570
+ ```tsx
1571
+ import { type ClassArray, clsx } from 'clsx';
1572
+ import { twMerge } from 'tailwind-merge';
1573
+
1574
+ export const cn = (...inputs: ClassArray): string => {
1575
+ return twMerge(clsx(inputs));
1576
+ };
1577
+ ```
1578
+
1579
+ ### AppShell/story-content/_storySearchModal.tsx
1580
+
1581
+ ```tsx
1582
+ import { useState } from 'react';
1583
+ import { Building, CircleDashed, Plus } from '../../../icons';
1584
+ import { Button } from '../../Button';
1585
+ import { Code } from '../../Code';
1586
+ import { EmptyState, EmptyStateDescription, EmptyStateMessage } from '../../EmptyState';
1587
+ import { Kbd } from '../../Kbd';
1588
+ import {
1589
+ SearchModal,
1590
+ SearchModalBody,
1591
+ SearchModalContent,
1592
+ SearchModalEmpty,
1593
+ SearchModalFooter,
1594
+ SearchModalGroup,
1595
+ SearchModalGroupLabel,
1596
+ SearchModalInput,
1597
+ SearchModalItem,
1598
+ SearchModalTrigger,
1599
+ } from '../../SearchModal';
1600
+ import { Text } from '../../Text';
1601
+ import { WallyIcon } from '../../WallyIcon';
1602
+
1603
+ const recentItems = [
1604
+ { page: 'Attacks', product: 'Cloud WAF', date: '2 hours ago', href: '/attacks' },
1605
+ { page: 'Rules', product: 'Cloud WAF', date: '5 hours ago', href: '/rules' },
1606
+ {
1607
+ page: 'Endpoints',
1608
+ product: 'US East',
1609
+ dataPlane: true,
1610
+ productExtra: 'API Discovery',
1611
+ date: 'Yesterday',
1612
+ href: '/endpoints',
1613
+ },
1614
+ { page: 'Dashboards', product: 'Cloud WAF', date: '2 days ago', href: '/dashboards' },
1615
+ { page: 'Triggers', product: 'Cloud WAF', date: '3 days ago', href: '/triggers' },
1616
+ ];
1617
+
1618
+ const jumpToItems = [
1619
+ { name: 'Cloud WAF', href: '/cloud-waf' },
1620
+ { name: 'API Discovery', href: '/api-discovery' },
1621
+ ];
1622
+
1623
+ const filterRecent = (query: string) => {
1624
+ if (!query) return recentItems;
1625
+ return recentItems.filter(item => {
1626
+ const text = `${item.page} ${item.product} ${item.productExtra ?? ''}`.toLowerCase();
1627
+ return text.includes(query);
1628
+ });
1629
+ };
1630
+
1631
+ const filterJumpTo = (query: string) => {
1632
+ if (!query) return jumpToItems;
1633
+ return jumpToItems.filter(item => item.name.toLowerCase().includes(query));
1634
+ };
1635
+
1636
+ export const StorySearchModal = () => {
1637
+ const [open, setOpen] = useState(false);
1638
+ const [query, setQuery] = useState('');
1639
+ const lowerQuery = query.toLowerCase();
1640
+
1641
+ const filteredRecent = filterRecent(lowerQuery);
1642
+ const filteredJumpTo = filterJumpTo(lowerQuery);
1643
+ const hasResults = filteredRecent.length > 0 || filteredJumpTo.length > 0 || !lowerQuery;
1644
+
1645
+ const handleOpenChange = (nextOpen: boolean) => {
1646
+ setOpen(nextOpen);
1647
+ if (!nextOpen) {
1648
+ setQuery('');
1649
+ }
1650
+ };
1651
+
1652
+ return (
1653
+ <SearchModal open={open} onOpenChange={handleOpenChange} onQueryChange={setQuery}>
1654
+ <SearchModalTrigger asChild>
1655
+ <Button
1656
+ variant='ghost'
1657
+ size='small'
1658
+ color='neutral'
1659
+ className='p-4 gap-6 rounded-6'
1660
+ data-slot='top-header-search'
1661
+ >
1662
+ <Code size='s' color='secondary'>
1663
+ Search Wallarm
1664
+ </Code>
1665
+ <Kbd size='xsmall'>⌘ K</Kbd>
1666
+ </Button>
1667
+ </SearchModalTrigger>
1668
+
1669
+ <SearchModalContent>
1670
+ <SearchModalInput placeholder='Search products, features, and more...' />
1671
+
1672
+ {lowerQuery && !hasResults && (
1673
+ <SearchModalEmpty>
1674
+ <EmptyState type='no-results' className='pb-8'>
1675
+ <EmptyStateMessage>
1676
+ <EmptyStateDescription>No results</EmptyStateDescription>
1677
+ </EmptyStateMessage>
1678
+ </EmptyState>
1679
+ </SearchModalEmpty>
1680
+ )}
1681
+
1682
+ <SearchModalBody>
1683
+ <SearchModalGroup>
1684
+ <SearchModalGroupLabel>
1685
+ <Text size='xs' color='secondary' weight='medium'>
1686
+ Quick actions
1687
+ </Text>
1688
+ </SearchModalGroupLabel>
1689
+ <SearchModalItem onSelect={() => {}}>
1690
+ <WallyIcon variant='circle' size='sm' />
1691
+ <Text size='sm'>Ask Wally</Text>
1692
+ </SearchModalItem>
1693
+
1694
+ {!lowerQuery && (
1695
+ <>
1696
+ <SearchModalItem onSelect={() => {}}>
1697
+ <Building className='text-text-secondary !icon-md' />
1698
+ <Text size='sm'>Switch tenant</Text>
1699
+ </SearchModalItem>
1700
+
1701
+ <SearchModalItem onSelect={() => {}}>
1702
+ <Plus className='text-text-secondary !icon-md' />
1703
+ <Text size='sm'>Create...</Text>
1704
+ </SearchModalItem>
1705
+ </>
1706
+ )}
1707
+ </SearchModalGroup>
1708
+
1709
+ {filteredRecent.length > 0 && (
1710
+ <SearchModalGroup>
1711
+ <SearchModalGroupLabel>
1712
+ <Text size='xs' color='secondary' weight='medium'>
1713
+ Recent
1714
+ </Text>
1715
+ </SearchModalGroupLabel>
1716
+ {filteredRecent.map(item => (
1717
+ <SearchModalItem key={`${item.page}-${item.product}`} onSelect={() => {}}>
1718
+ <CircleDashed className='text-text-primary shrink-0 !icon-md' />
1719
+ <Text size='sm' grow truncate>
1720
+ {item.page}
1721
+ <Text size='sm' color='secondary' inline>
1722
+ {' '}
1723
+ — {item.dataPlane ? `${item.productExtra} · ${item.product}` : item.product}
1724
+ </Text>
1725
+ </Text>
1726
+ <span className='shrink-0'>
1727
+ <Text size='xs' color='secondary'>
1728
+ {item.date}
1729
+ </Text>
1730
+ </span>
1731
+ </SearchModalItem>
1732
+ ))}
1733
+ </SearchModalGroup>
1734
+ )}
1735
+
1736
+ {filteredJumpTo.length > 0 && (
1737
+ <SearchModalGroup>
1738
+ <SearchModalGroupLabel>
1739
+ <Text size='xs' color='secondary' weight='medium'>
1740
+ Jump to
1741
+ </Text>
1742
+ </SearchModalGroupLabel>
1743
+ {filteredJumpTo.map(item => (
1744
+ <SearchModalItem key={item.href} onSelect={() => {}}>
1745
+ <CircleDashed className='text-text-primary shrink-0 !icon-md' />
1746
+ <Text size='sm'>{item.name}</Text>
1747
+ </SearchModalItem>
1748
+ ))}
1749
+ </SearchModalGroup>
1750
+ )}
1751
+ </SearchModalBody>
1752
+
1753
+ <SearchModalFooter />
1754
+ </SearchModalContent>
1755
+ </SearchModal>
1756
+ );
1757
+ };
1758
+ ```