@psnext/design-system 2.4.0 → 2.5.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 (479) hide show
  1. package/DESIGN.md +27 -4
  2. package/SKILL.md +1 -1
  3. package/dist/Header.cjs +1 -1
  4. package/dist/Header.cjs.map +1 -1
  5. package/dist/Header.js +1 -1
  6. package/dist/Header.js.map +1 -1
  7. package/dist/Mosaic.cjs +472 -0
  8. package/dist/Mosaic.cjs.map +1 -0
  9. package/dist/Mosaic.js +459 -0
  10. package/dist/Mosaic.js.map +1 -0
  11. package/dist/index.cjs +13 -2
  12. package/dist/index.d.cts +5 -5
  13. package/dist/index.d.cts.map +1 -1
  14. package/dist/index.d.ts +5 -5
  15. package/dist/index.js +7 -3
  16. package/dist/index10.d.cts +6 -6
  17. package/dist/index10.d.cts.map +1 -1
  18. package/dist/index10.d.ts +6 -6
  19. package/dist/index11.d.cts +3 -3
  20. package/dist/index11.d.ts +3 -3
  21. package/dist/index12.d.cts +12 -12
  22. package/dist/index12.d.cts.map +1 -1
  23. package/dist/index12.d.ts +12 -12
  24. package/dist/index13.d.cts +6 -6
  25. package/dist/index13.d.cts.map +1 -1
  26. package/dist/index13.d.ts +6 -6
  27. package/dist/index14.d.cts +5 -5
  28. package/dist/index14.d.ts +5 -5
  29. package/dist/index15.d.cts +58 -23
  30. package/dist/index15.d.cts.map +1 -1
  31. package/dist/index15.d.ts +58 -23
  32. package/dist/index15.d.ts.map +1 -1
  33. package/dist/index16.d.cts +23 -32
  34. package/dist/index16.d.cts.map +1 -1
  35. package/dist/index16.d.ts +23 -32
  36. package/dist/index16.d.ts.map +1 -1
  37. package/dist/index17.d.cts +34 -15
  38. package/dist/index17.d.cts.map +1 -1
  39. package/dist/index17.d.ts +34 -15
  40. package/dist/index17.d.ts.map +1 -1
  41. package/dist/index18.d.cts +13 -67
  42. package/dist/index18.d.cts.map +1 -1
  43. package/dist/index18.d.ts +13 -67
  44. package/dist/index18.d.ts.map +1 -1
  45. package/dist/index19.d.cts +55 -48
  46. package/dist/index19.d.cts.map +1 -1
  47. package/dist/index19.d.ts +55 -48
  48. package/dist/index19.d.ts.map +1 -1
  49. package/dist/index2.d.cts +8 -8
  50. package/dist/index2.d.cts.map +1 -1
  51. package/dist/index2.d.ts +8 -8
  52. package/dist/index2.d.ts.map +1 -1
  53. package/dist/index20.d.cts +45 -75
  54. package/dist/index20.d.cts.map +1 -1
  55. package/dist/index20.d.ts +45 -75
  56. package/dist/index20.d.ts.map +1 -1
  57. package/dist/index21.d.cts +90 -28
  58. package/dist/index21.d.cts.map +1 -1
  59. package/dist/index21.d.ts +90 -28
  60. package/dist/index21.d.ts.map +1 -1
  61. package/dist/index22.d.cts +28 -56
  62. package/dist/index22.d.cts.map +1 -1
  63. package/dist/index22.d.ts +28 -56
  64. package/dist/index22.d.ts.map +1 -1
  65. package/dist/index23.d.cts +53 -78
  66. package/dist/index23.d.cts.map +1 -1
  67. package/dist/index23.d.ts +53 -78
  68. package/dist/index23.d.ts.map +1 -1
  69. package/dist/index24.d.cts +83 -33
  70. package/dist/index24.d.cts.map +1 -1
  71. package/dist/index24.d.ts +83 -33
  72. package/dist/index24.d.ts.map +1 -1
  73. package/dist/index25.d.cts +43 -11
  74. package/dist/index25.d.cts.map +1 -1
  75. package/dist/index25.d.ts +43 -11
  76. package/dist/index25.d.ts.map +1 -1
  77. package/dist/index26.d.cts +11 -74
  78. package/dist/index26.d.cts.map +1 -1
  79. package/dist/index26.d.ts +11 -74
  80. package/dist/index26.d.ts.map +1 -1
  81. package/dist/index27.d.cts +68 -59
  82. package/dist/index27.d.cts.map +1 -1
  83. package/dist/index27.d.ts +68 -59
  84. package/dist/index27.d.ts.map +1 -1
  85. package/dist/index28.d.cts +47 -30
  86. package/dist/index28.d.cts.map +1 -1
  87. package/dist/index28.d.ts +47 -30
  88. package/dist/index28.d.ts.map +1 -1
  89. package/dist/index29.d.cts +63 -17
  90. package/dist/index29.d.cts.map +1 -1
  91. package/dist/index29.d.ts +63 -17
  92. package/dist/index29.d.ts.map +1 -1
  93. package/dist/index3.d.cts +13 -13
  94. package/dist/index3.d.cts.map +1 -1
  95. package/dist/index3.d.ts +13 -13
  96. package/dist/index30.d.cts +29 -80
  97. package/dist/index30.d.cts.map +1 -1
  98. package/dist/index30.d.ts +29 -80
  99. package/dist/index30.d.ts.map +1 -1
  100. package/dist/index31.d.cts +19 -34
  101. package/dist/index31.d.cts.map +1 -1
  102. package/dist/index31.d.ts +19 -34
  103. package/dist/index31.d.ts.map +1 -1
  104. package/dist/index32.d.cts +80 -18
  105. package/dist/index32.d.cts.map +1 -1
  106. package/dist/index32.d.ts +79 -17
  107. package/dist/index32.d.ts.map +1 -1
  108. package/dist/index33.d.cts +32 -51
  109. package/dist/index33.d.cts.map +1 -1
  110. package/dist/index33.d.ts +32 -51
  111. package/dist/index33.d.ts.map +1 -1
  112. package/dist/index34.d.cts +19 -36
  113. package/dist/index34.d.cts.map +1 -1
  114. package/dist/index34.d.ts +19 -36
  115. package/dist/index34.d.ts.map +1 -1
  116. package/dist/index35.d.cts +43 -61
  117. package/dist/index35.d.cts.map +1 -1
  118. package/dist/index35.d.ts +43 -61
  119. package/dist/index35.d.ts.map +1 -1
  120. package/dist/index36.d.cts +35 -11
  121. package/dist/index36.d.cts.map +1 -1
  122. package/dist/index36.d.ts +35 -11
  123. package/dist/index36.d.ts.map +1 -1
  124. package/dist/index37.d.cts +68 -20
  125. package/dist/index37.d.cts.map +1 -1
  126. package/dist/index37.d.ts +68 -20
  127. package/dist/index37.d.ts.map +1 -1
  128. package/dist/index38.d.cts +14 -15
  129. package/dist/index38.d.cts.map +1 -1
  130. package/dist/index38.d.ts +14 -15
  131. package/dist/index38.d.ts.map +1 -1
  132. package/dist/index39.d.cts +22 -98
  133. package/dist/index39.d.cts.map +1 -1
  134. package/dist/index39.d.ts +22 -98
  135. package/dist/index39.d.ts.map +1 -1
  136. package/dist/index4.d.cts +2 -2
  137. package/dist/index4.d.cts.map +1 -1
  138. package/dist/index4.d.ts +2 -2
  139. package/dist/index4.d.ts.map +1 -1
  140. package/dist/index40.d.cts +15 -17
  141. package/dist/index40.d.cts.map +1 -1
  142. package/dist/index40.d.ts +15 -17
  143. package/dist/index40.d.ts.map +1 -1
  144. package/dist/index41.d.cts +84 -35
  145. package/dist/index41.d.cts.map +1 -1
  146. package/dist/index41.d.ts +84 -35
  147. package/dist/index41.d.ts.map +1 -1
  148. package/dist/index42.d.cts +118 -38
  149. package/dist/index42.d.cts.map +1 -1
  150. package/dist/index42.d.ts +118 -38
  151. package/dist/index42.d.ts.map +1 -1
  152. package/dist/index43.d.cts +15 -89
  153. package/dist/index43.d.cts.map +1 -1
  154. package/dist/index43.d.ts +15 -89
  155. package/dist/index43.d.ts.map +1 -1
  156. package/dist/index44.d.cts +56 -1
  157. package/dist/index44.d.cts.map +1 -0
  158. package/dist/index44.d.ts +56 -1
  159. package/dist/index44.d.ts.map +1 -0
  160. package/dist/index45.d.cts +31 -34
  161. package/dist/index45.d.cts.map +1 -1
  162. package/dist/index45.d.ts +31 -34
  163. package/dist/index45.d.ts.map +1 -1
  164. package/dist/index46.d.cts +89 -21
  165. package/dist/index46.d.cts.map +1 -1
  166. package/dist/index46.d.ts +89 -21
  167. package/dist/index46.d.ts.map +1 -1
  168. package/dist/index47.d.cts +1 -41
  169. package/dist/index47.d.ts +1 -41
  170. package/dist/index48.d.cts +122 -20
  171. package/dist/index48.d.cts.map +1 -1
  172. package/dist/index48.d.ts +122 -20
  173. package/dist/index48.d.ts.map +1 -1
  174. package/dist/index49.d.cts +40 -13
  175. package/dist/index49.d.cts.map +1 -1
  176. package/dist/index49.d.ts +40 -13
  177. package/dist/index49.d.ts.map +1 -1
  178. package/dist/index5.d.cts +7 -7
  179. package/dist/index5.d.cts.map +1 -1
  180. package/dist/index5.d.ts +7 -7
  181. package/dist/index50.d.cts +22 -63
  182. package/dist/index50.d.cts.map +1 -1
  183. package/dist/index50.d.ts +22 -63
  184. package/dist/index50.d.ts.map +1 -1
  185. package/dist/index51.d.cts +33 -55
  186. package/dist/index51.d.cts.map +1 -1
  187. package/dist/index51.d.ts +33 -55
  188. package/dist/index51.d.ts.map +1 -1
  189. package/dist/index52.d.cts +18 -24
  190. package/dist/index52.d.cts.map +1 -1
  191. package/dist/index52.d.ts +18 -24
  192. package/dist/index52.d.ts.map +1 -1
  193. package/dist/index53.d.cts +12 -200
  194. package/dist/index53.d.cts.map +1 -1
  195. package/dist/index53.d.ts +12 -200
  196. package/dist/index53.d.ts.map +1 -1
  197. package/dist/index54.d.cts +58 -15
  198. package/dist/index54.d.cts.map +1 -1
  199. package/dist/index54.d.ts +58 -15
  200. package/dist/index54.d.ts.map +1 -1
  201. package/dist/index55.d.cts +93 -23
  202. package/dist/index55.d.cts.map +1 -1
  203. package/dist/index55.d.ts +93 -23
  204. package/dist/index55.d.ts.map +1 -1
  205. package/dist/index56.d.cts +27 -21
  206. package/dist/index56.d.cts.map +1 -1
  207. package/dist/index56.d.ts +27 -21
  208. package/dist/index56.d.ts.map +1 -1
  209. package/dist/index57.d.cts +203 -6
  210. package/dist/index57.d.cts.map +1 -1
  211. package/dist/index57.d.ts +203 -6
  212. package/dist/index57.d.ts.map +1 -1
  213. package/dist/index58.d.cts +17 -41
  214. package/dist/index58.d.cts.map +1 -1
  215. package/dist/index58.d.ts +17 -41
  216. package/dist/index58.d.ts.map +1 -1
  217. package/dist/index59.d.cts +24 -47
  218. package/dist/index59.d.cts.map +1 -1
  219. package/dist/index59.d.ts +24 -47
  220. package/dist/index59.d.ts.map +1 -1
  221. package/dist/index6.d.cts +5 -5
  222. package/dist/index6.d.cts.map +1 -1
  223. package/dist/index6.d.ts +5 -5
  224. package/dist/index60.d.cts +19 -57
  225. package/dist/index60.d.cts.map +1 -1
  226. package/dist/index60.d.ts +19 -57
  227. package/dist/index60.d.ts.map +1 -1
  228. package/dist/index61.d.cts +6 -39
  229. package/dist/index61.d.cts.map +1 -1
  230. package/dist/index61.d.ts +6 -39
  231. package/dist/index61.d.ts.map +1 -1
  232. package/dist/index62.d.cts +44 -18
  233. package/dist/index62.d.cts.map +1 -1
  234. package/dist/index62.d.ts +44 -18
  235. package/dist/index62.d.ts.map +1 -1
  236. package/dist/index63.d.cts +47 -41
  237. package/dist/index63.d.cts.map +1 -1
  238. package/dist/index63.d.ts +47 -41
  239. package/dist/index63.d.ts.map +1 -1
  240. package/dist/index64.d.cts +55 -15
  241. package/dist/index64.d.cts.map +1 -1
  242. package/dist/index64.d.ts +55 -15
  243. package/dist/index64.d.ts.map +1 -1
  244. package/dist/index65.d.cts +36 -39
  245. package/dist/index65.d.cts.map +1 -1
  246. package/dist/index65.d.ts +36 -39
  247. package/dist/index65.d.ts.map +1 -1
  248. package/dist/index66.d.cts +16 -17
  249. package/dist/index66.d.cts.map +1 -1
  250. package/dist/index66.d.ts +16 -17
  251. package/dist/index66.d.ts.map +1 -1
  252. package/dist/index67.d.cts +38 -84
  253. package/dist/index67.d.cts.map +1 -1
  254. package/dist/index67.d.ts +38 -84
  255. package/dist/index67.d.ts.map +1 -1
  256. package/dist/index68.d.cts +17 -13
  257. package/dist/index68.d.cts.map +1 -1
  258. package/dist/index68.d.ts +17 -13
  259. package/dist/index68.d.ts.map +1 -1
  260. package/dist/index69.d.cts +41 -30
  261. package/dist/index69.d.cts.map +1 -1
  262. package/dist/index69.d.ts +41 -30
  263. package/dist/index69.d.ts.map +1 -1
  264. package/dist/index7.d.cts +8 -8
  265. package/dist/index7.d.ts +8 -8
  266. package/dist/index7.d.ts.map +1 -1
  267. package/dist/index70.d.cts +17 -28
  268. package/dist/index70.d.cts.map +1 -1
  269. package/dist/index70.d.ts +17 -28
  270. package/dist/index70.d.ts.map +1 -1
  271. package/dist/index71.d.cts +88 -79
  272. package/dist/index71.d.cts.map +1 -1
  273. package/dist/index71.d.ts +88 -79
  274. package/dist/index71.d.ts.map +1 -1
  275. package/dist/index72.d.cts +13 -272
  276. package/dist/index72.d.cts.map +1 -1
  277. package/dist/index72.d.ts +13 -272
  278. package/dist/index72.d.ts.map +1 -1
  279. package/dist/index73.d.cts +37 -0
  280. package/dist/index73.d.cts.map +1 -0
  281. package/dist/index73.d.ts +37 -0
  282. package/dist/index73.d.ts.map +1 -0
  283. package/dist/index74.d.cts +36 -0
  284. package/dist/index74.d.cts.map +1 -0
  285. package/dist/index74.d.ts +36 -0
  286. package/dist/index74.d.ts.map +1 -0
  287. package/dist/index75.d.cts +86 -0
  288. package/dist/index75.d.cts.map +1 -0
  289. package/dist/index75.d.ts +86 -0
  290. package/dist/index75.d.ts.map +1 -0
  291. package/dist/index76.d.cts +278 -0
  292. package/dist/index76.d.cts.map +1 -0
  293. package/dist/index76.d.ts +278 -0
  294. package/dist/index76.d.ts.map +1 -0
  295. package/dist/index8.d.cts +4 -4
  296. package/dist/index8.d.cts.map +1 -1
  297. package/dist/index8.d.ts +4 -4
  298. package/dist/index9.d.cts +2 -2
  299. package/dist/index9.d.cts.map +1 -1
  300. package/dist/index9.d.ts +2 -2
  301. package/dist/layouts/Container/index.d.cts +1 -1
  302. package/dist/layouts/Container/index.d.ts +1 -1
  303. package/dist/layouts/MultiColumn/index.d.cts +1 -1
  304. package/dist/layouts/MultiColumn/index.d.ts +1 -1
  305. package/dist/layouts/PageBackground/index.d.cts +1 -1
  306. package/dist/layouts/PageBackground/index.d.ts +1 -1
  307. package/dist/layouts/Stack/index.d.cts +1 -1
  308. package/dist/layouts/Stack/index.d.ts +1 -1
  309. package/dist/layouts/TwoColumn/index.d.cts +1 -1
  310. package/dist/layouts/TwoColumn/index.d.ts +1 -1
  311. package/dist/layouts/index.d.cts +5 -5
  312. package/dist/layouts/index.d.ts +5 -5
  313. package/dist/patterns/DataTable/index.d.cts +3 -3
  314. package/dist/patterns/DataTable/index.d.cts.map +1 -1
  315. package/dist/patterns/DataTable/index.d.ts +3 -3
  316. package/dist/patterns/Footer/index.d.cts +7 -7
  317. package/dist/patterns/Footer/index.d.ts +7 -7
  318. package/dist/patterns/Header/index.d.cts +1 -1
  319. package/dist/patterns/Header/index.d.ts +1 -1
  320. package/dist/patterns/MediaObject/index.d.cts +14 -14
  321. package/dist/patterns/MediaObject/index.d.cts.map +1 -1
  322. package/dist/patterns/MediaObject/index.d.ts +13 -13
  323. package/dist/patterns/NavRail/index.d.cts +1 -1
  324. package/dist/patterns/NavRail/index.d.ts +1 -1
  325. package/dist/patterns/SectionCard/index.d.cts +2 -2
  326. package/dist/patterns/SectionCard/index.d.cts.map +1 -1
  327. package/dist/patterns/SectionCard/index.d.ts +2 -2
  328. package/dist/patterns/SectionCard/index.d.ts.map +1 -1
  329. package/dist/patterns/SectionHeading/index.d.cts +3 -3
  330. package/dist/patterns/SectionHeading/index.d.cts.map +1 -1
  331. package/dist/patterns/SectionHeading/index.d.ts +3 -3
  332. package/dist/patterns/SectionHeading/index.d.ts.map +1 -1
  333. package/dist/patterns/index.d.cts +2 -2
  334. package/dist/patterns/index.d.ts +2 -2
  335. package/dist/primitives/Checkbox/index.cjs +1 -1
  336. package/dist/primitives/Checkbox/index.cjs.map +1 -1
  337. package/dist/primitives/Checkbox/index.d.cts +1 -1
  338. package/dist/primitives/Checkbox/index.d.ts +1 -1
  339. package/dist/primitives/Checkbox/index.js +1 -1
  340. package/dist/primitives/Checkbox/index.js.map +1 -1
  341. package/dist/primitives/CheckboxTree/index.d.cts +1 -1
  342. package/dist/primitives/CheckboxTree/index.d.ts +1 -1
  343. package/dist/primitives/CircularProgress/index.cjs +106 -0
  344. package/dist/primitives/CircularProgress/index.cjs.map +1 -0
  345. package/dist/primitives/CircularProgress/index.d.cts +2 -0
  346. package/dist/primitives/CircularProgress/index.d.ts +2 -0
  347. package/dist/primitives/CircularProgress/index.js +105 -0
  348. package/dist/primitives/CircularProgress/index.js.map +1 -0
  349. package/dist/primitives/Collapsible/index.d.cts +1 -1
  350. package/dist/primitives/Collapsible/index.d.ts +1 -1
  351. package/dist/primitives/Command/index.d.cts +1 -1
  352. package/dist/primitives/Command/index.d.ts +1 -1
  353. package/dist/primitives/ContextMenu/index.d.cts +1 -1
  354. package/dist/primitives/ContextMenu/index.d.ts +1 -1
  355. package/dist/primitives/Credits/index.d.cts +1 -1
  356. package/dist/primitives/Credits/index.d.ts +1 -1
  357. package/dist/primitives/Dialog/index.d.cts +1 -1
  358. package/dist/primitives/Dialog/index.d.ts +1 -1
  359. package/dist/primitives/Drawer/index.cjs +34 -2
  360. package/dist/primitives/Drawer/index.cjs.map +1 -1
  361. package/dist/primitives/Drawer/index.d.cts +1 -1
  362. package/dist/primitives/Drawer/index.d.ts +1 -1
  363. package/dist/primitives/Drawer/index.js +34 -2
  364. package/dist/primitives/Drawer/index.js.map +1 -1
  365. package/dist/primitives/DropdownMenu/index.d.cts +1 -1
  366. package/dist/primitives/DropdownMenu/index.d.ts +1 -1
  367. package/dist/primitives/Empty/index.d.cts +1 -1
  368. package/dist/primitives/Empty/index.d.ts +1 -1
  369. package/dist/primitives/Field/index.d.cts +1 -1
  370. package/dist/primitives/Field/index.d.ts +1 -1
  371. package/dist/primitives/FileUpload/index.cjs +354 -0
  372. package/dist/primitives/FileUpload/index.cjs.map +1 -0
  373. package/dist/primitives/FileUpload/index.d.cts +2 -0
  374. package/dist/primitives/FileUpload/index.d.ts +2 -0
  375. package/dist/primitives/FileUpload/index.js +351 -0
  376. package/dist/primitives/FileUpload/index.js.map +1 -0
  377. package/dist/primitives/Form/index.d.cts +1 -1
  378. package/dist/primitives/Form/index.d.ts +1 -1
  379. package/dist/primitives/Heading/index.d.cts +1 -1
  380. package/dist/primitives/Heading/index.d.ts +1 -1
  381. package/dist/primitives/HoverCard/index.d.cts +1 -1
  382. package/dist/primitives/HoverCard/index.d.ts +1 -1
  383. package/dist/primitives/Icon/index.d.cts +1 -1
  384. package/dist/primitives/Icon/index.d.ts +1 -1
  385. package/dist/primitives/InfoBanner/index.d.cts +1 -1
  386. package/dist/primitives/InfoBanner/index.d.ts +1 -1
  387. package/dist/primitives/Input/index.d.cts +1 -1
  388. package/dist/primitives/Input/index.d.ts +1 -1
  389. package/dist/primitives/InputGroup/index.d.cts +1 -1
  390. package/dist/primitives/InputGroup/index.d.ts +1 -1
  391. package/dist/primitives/InputOtp/index.d.cts +1 -1
  392. package/dist/primitives/InputOtp/index.d.ts +1 -1
  393. package/dist/primitives/Item/index.d.cts +1 -1
  394. package/dist/primitives/Item/index.d.ts +1 -1
  395. package/dist/primitives/Kbd/index.d.cts +1 -1
  396. package/dist/primitives/Kbd/index.d.ts +1 -1
  397. package/dist/primitives/Label/index.d.cts +1 -1
  398. package/dist/primitives/Label/index.d.ts +1 -1
  399. package/dist/primitives/Link/index.d.cts +1 -1
  400. package/dist/primitives/Link/index.d.ts +1 -1
  401. package/dist/primitives/Logo/index.d.cts +1 -1
  402. package/dist/primitives/Logo/index.d.ts +1 -1
  403. package/dist/primitives/Menubar/index.d.cts +1 -1
  404. package/dist/primitives/Menubar/index.d.ts +1 -1
  405. package/dist/primitives/Mosaic/index.cjs +4 -0
  406. package/dist/primitives/Mosaic/index.d.cts +2 -0
  407. package/dist/primitives/Mosaic/index.d.ts +2 -0
  408. package/dist/primitives/Mosaic/index.js +2 -0
  409. package/dist/primitives/NativeSelect/index.d.cts +1 -1
  410. package/dist/primitives/NativeSelect/index.d.ts +1 -1
  411. package/dist/primitives/NavRail/index.d.cts +2 -2
  412. package/dist/primitives/NavRail/index.d.ts +2 -2
  413. package/dist/primitives/NavigationMenu/index.d.cts +1 -1
  414. package/dist/primitives/NavigationMenu/index.d.ts +1 -1
  415. package/dist/primitives/NotchedCard/index.cjs +390 -0
  416. package/dist/primitives/NotchedCard/index.cjs.map +1 -0
  417. package/dist/primitives/NotchedCard/index.d.cts +2 -0
  418. package/dist/primitives/NotchedCard/index.d.ts +2 -0
  419. package/dist/primitives/NotchedCard/index.js +385 -0
  420. package/dist/primitives/NotchedCard/index.js.map +1 -0
  421. package/dist/primitives/Pagination/index.d.cts +1 -1
  422. package/dist/primitives/Pagination/index.d.ts +1 -1
  423. package/dist/primitives/Popover/index.d.cts +1 -1
  424. package/dist/primitives/Popover/index.d.ts +1 -1
  425. package/dist/primitives/Progress/index.d.cts +1 -1
  426. package/dist/primitives/Progress/index.d.ts +1 -1
  427. package/dist/primitives/RadioGroup/index.cjs +1 -1
  428. package/dist/primitives/RadioGroup/index.cjs.map +1 -1
  429. package/dist/primitives/RadioGroup/index.d.cts +1 -1
  430. package/dist/primitives/RadioGroup/index.d.ts +1 -1
  431. package/dist/primitives/RadioGroup/index.js +1 -1
  432. package/dist/primitives/RadioGroup/index.js.map +1 -1
  433. package/dist/primitives/Resizable/index.d.cts +1 -1
  434. package/dist/primitives/Resizable/index.d.ts +1 -1
  435. package/dist/primitives/ScrollArea/index.d.cts +1 -1
  436. package/dist/primitives/ScrollArea/index.d.ts +1 -1
  437. package/dist/primitives/Select/index.d.cts +1 -1
  438. package/dist/primitives/Select/index.d.ts +1 -1
  439. package/dist/primitives/Sheet/index.cjs +34 -2
  440. package/dist/primitives/Sheet/index.cjs.map +1 -1
  441. package/dist/primitives/Sheet/index.d.cts +1 -1
  442. package/dist/primitives/Sheet/index.d.ts +1 -1
  443. package/dist/primitives/Sheet/index.js +34 -2
  444. package/dist/primitives/Sheet/index.js.map +1 -1
  445. package/dist/primitives/Sidebar/index.d.cts +1 -1
  446. package/dist/primitives/Sidebar/index.d.ts +1 -1
  447. package/dist/primitives/Skeleton/index.d.cts +1 -1
  448. package/dist/primitives/Skeleton/index.d.ts +1 -1
  449. package/dist/primitives/Slider/index.d.cts +1 -1
  450. package/dist/primitives/Slider/index.d.ts +1 -1
  451. package/dist/primitives/Sonner/index.d.cts +1 -1
  452. package/dist/primitives/Sonner/index.d.ts +1 -1
  453. package/dist/primitives/Spinner/index.d.cts +1 -1
  454. package/dist/primitives/Spinner/index.d.ts +1 -1
  455. package/dist/primitives/Switch/index.d.cts +1 -1
  456. package/dist/primitives/Switch/index.d.ts +1 -1
  457. package/dist/primitives/Table/index.d.cts +1 -1
  458. package/dist/primitives/Table/index.d.ts +1 -1
  459. package/dist/primitives/Tabs/index.d.cts +1 -1
  460. package/dist/primitives/Tabs/index.d.ts +1 -1
  461. package/dist/primitives/Text/index.d.cts +1 -1
  462. package/dist/primitives/Text/index.d.ts +1 -1
  463. package/dist/primitives/Textarea/index.d.cts +1 -1
  464. package/dist/primitives/Textarea/index.d.ts +1 -1
  465. package/dist/primitives/ThemeProvider/index.d.cts +1 -1
  466. package/dist/primitives/ThemeProvider/index.d.ts +1 -1
  467. package/dist/primitives/Toggle/index.d.cts +1 -1
  468. package/dist/primitives/Toggle/index.d.ts +1 -1
  469. package/dist/primitives/ToggleGroup/index.d.cts +1 -1
  470. package/dist/primitives/ToggleGroup/index.d.ts +1 -1
  471. package/dist/primitives/Tooltip/index.d.cts +1 -1
  472. package/dist/primitives/Tooltip/index.d.ts +1 -1
  473. package/dist/primitives/index.cjs +13 -2
  474. package/dist/primitives/index.d.cts +55 -51
  475. package/dist/primitives/index.d.ts +55 -51
  476. package/dist/primitives/index.js +7 -3
  477. package/package.json +1 -1
  478. package/dist/index47.d.cts.map +0 -1
  479. package/dist/index47.d.ts.map +0 -1
package/DESIGN.md CHANGED
@@ -360,6 +360,12 @@ translucent+blurred with no border, and needs a textured layer behind it
360
360
  - **Custom props**: `nodes` (hierarchical `{id, label, children}` data); `value` (controlled selected ids, required); `onValueChange`; `defaultExpandedIds`.
361
361
  - **Notes**: Controlled only; tri-state propagation across subtrees; `role="tree"`. This is the DS answer to hierarchical multi-select.
362
362
 
363
+ ### CircularProgress
364
+ - **Exports**: CircularProgress, CircularProgressProps (type), CircularProgressVariant (type)
365
+ - **Variants**: `variant: default* | brand | success | warning | info | destructive | analyzing | ingesting` (indicator stroke); `trackVariant` — same scale for the track (defaults to `variant`, rendered at /20 opacity)
366
+ - **Custom props**: `value` (omit → indeterminate spinning arc), `min`/`max` (aria/value normalization, default 0/100), `size` (diameter px, default `48`), `strokeWidth` (px, default `4`), `progressColor`/`trackColor` (explicit CSS colours, override the variant classes), `label` (centered node), `showValueLabel` (centered `%` text when determinate, default `false`), `indeterminateLabel` (a11y text for loading state, default `Loading`).
367
+ - **Notes**: `role="progressbar"` with normalized aria values and a polite live region. Determinate animates stroke-dashoffset (500ms, motion-reduce respected); indeterminate spins a 35% arc (`motion-safe`). Circular counterpart to the linear `Progress` bar.
368
+
363
369
  ### Collapsible
364
370
  - **Exports**: Collapsible, CollapsibleTrigger, CollapsibleContent
365
371
  - **Notes**: Radix Collapsible passthrough (controlled/uncontrolled via `open`/`defaultOpen`); no styling applied.
@@ -403,7 +409,8 @@ variant with paint classes (SKILL.md → "Never re-skin a variant").
403
409
 
404
410
  ### Drawer
405
411
  - **Exports**: Drawer, DrawerPortal, DrawerOverlay, DrawerTrigger, DrawerClose, DrawerContent, DrawerHeader, DrawerFooter, DrawerTitle, DrawerDescription
406
- - **Notes**: Built on `vaul`; slide `direction` (top/bottom/left/right) set on the `Drawer` root. `DrawerContent` self-portals + renders overlay; bottom drawer shows a drag handle.
412
+ - **Variants**: DrawerContent `size: small | default* | medium | large | extraLarge`
413
+ - **Notes**: Built on `vaul`; slide `direction` (top/bottom/left/right) set on the `Drawer` root. `DrawerContent` self-portals + renders overlay; bottom drawer shows a drag handle. `size` scales the panel per direction — left/right width caps: `small` xs (20rem) · `default` sm (24rem) · `medium` md (28rem) · `large` lg (32rem) · `extraLarge` 2xl (42rem); top/bottom max-heights: 60 / 80 / 85 / 90 / 95vh. Prefer `size` over a width/height `className` override.
407
414
 
408
415
  ### DropdownMenu
409
416
  - **Exports**: DropdownMenu, DropdownMenuPortal, DropdownMenuTrigger, DropdownMenuContent, DropdownMenuGroup, DropdownMenuLabel, DropdownMenuItem, DropdownMenuCheckboxItem, DropdownMenuRadioGroup, DropdownMenuRadioItem, DropdownMenuSeparator, DropdownMenuShortcut, DropdownMenuSub, DropdownMenuSubTrigger, DropdownMenuSubContent
@@ -422,6 +429,11 @@ variant with paint classes (SKILL.md → "Never re-skin a variant").
422
429
  - **Custom props**: FieldError accepts `errors` array (deduped, listed when >1) or `children`; FieldSeparator optional centered label.
423
430
  - **Notes**: Layout primitives for forms (non-react-hook-form); `FieldError` is `role="alert"` and renders nothing when empty.
424
431
 
432
+ ### FileUpload
433
+ - **Exports**: FileUpload, FileUploadHandler (type), FileUploadItem (type), FileUploadProps (type), FileUploadStatus (type)
434
+ - **Custom props**: `multiple` (default `false`); `accept` — native accept filter (e.g. `"image/*,.pdf"`); `maxFiles` (default unlimited when `multiple`, `1` otherwise); `maxFileSize` — bytes, oversized files rejected with a message; `validateFile` — custom validator, return a message to reject or `null` to accept; `onUpload` — async handler per accepted file, receives `{ file, signal, reportProgress }`; `onItemsChange` — fires whenever file entries change (added/progress/completed/removed); `dropzoneAriaLabel` (default `"File upload drop zone"`); `disabled`.
435
+ - **Notes**: Click-to-browse + drag-and-drop dropzone with per-file states (`idle | uploading | success | error`), progress bars, and remove/cancel controls. Wire real uploads via `onUpload` — call `reportProgress(0–100)` as bytes stream and throw to mark the file failed; the `signal` aborts when the user cancels/removes. Validation errors (accept/size/custom/maxFiles) render in an `aria-live` list under the dropzone.
436
+
425
437
  ### Form
426
438
  - **Exports**: useFormField, Form, FormItem, FormLabel, FormControl, FormDescription, FormMessage, FormField
427
439
  - **Notes**: react-hook-form binding layer over the Field primitives; `Form` = RHF `FormProvider`, `FormField` wraps `Controller`. `FormControl` wires id/aria-describedby/aria-invalid via Slot; must be used within `FormField`/`FormItem`.
@@ -571,6 +583,11 @@ variant with paint classes (SKILL.md → "Never re-skin a variant").
571
583
  - **Custom props**: Item/Label/SubTrigger `inset` (default `false`)
572
584
  - **Notes**: Radix Menubar; content self-portals; auto-indents plain items when checkbox/radio items present.
573
585
 
586
+ ### Mosaic
587
+ - **Exports**: Mosaic, MosaicWindow, MosaicProps (type), MosaicWindowProps (type), and tree types re-exported from Mosaic.utils: MosaicNode, MosaicParent, MosaicKey, MosaicDirection, MosaicPath, DropZone
588
+ - **Custom props**: `value` / `defaultValue` — the pane tree, controlled or uncontrolled (`MosaicNode<T>` = leaf id `T` or `{ direction: "row" | "column", first, second, splitPercentage? }`); `onChange` — fires with the updated tree after resize/split/remove/drag (no strict veto); `renderTile` — renders a leaf's content (required); `renderTitle` — pane toolbar title (default `String(id)`); `renderControls` — extra toolbar actions after split/remove; `createNode` — id factory for toolbar splits (required); `dragToRearrange` (default `true`); `dropZoneFraction` — edge-zone fraction 0–1 (default `0.25`); `minPaneSizePercentage` (default `10`); `emptyPlaceholder` — rendered when every pane is removed; `renamable` (default `false`) — pencil button + double-click title to rename a pane in place; `paneNames` / `defaultPaneNames` / `onPaneNamesChange` — custom pane names keyed by leaf id, controlled or uncontrolled.
589
+ - **Notes**: Recursive tiling layout (react-mosaic-style) built on the DS Resizable panels: panes split into rows/columns, resize via draggable dividers, and rearrange by dragging a pane's title bar onto another pane's edge (splits there) or center (swaps). Every drag outcome is also reachable via each pane's keyboard-operable toolbar split/remove buttons. `useMosaic` is intentionally not exported — `MosaicWindow` is the supported extension point.
590
+
574
591
  ### NativeSelect
575
592
  - **Exports**: NativeSelect, nativeSelectVariants
576
593
  - **Variants**: `size: xs | sm | default* | lg`
@@ -589,6 +606,12 @@ variant with paint classes (SKILL.md → "Never re-skin a variant").
589
606
  - **Custom props**: NavigationMenu `viewport` (default `true` — shared animated viewport; `false` renders content inline)
590
607
  - **Notes**: Radix NavigationMenu; `NavigationMenuLink` takes `active` to mark the current page.
591
608
 
609
+ ### NotchedCard
610
+ - **Exports**: NotchedCard, buildNotchedCardPath, notchedCardVariants, NotchedCardProps (type), NotchedCardVariant (type)
611
+ - **Variants**: `variant: default* | muted | glass | brand | inverted` (surface fill + inherited text colour)
612
+ - **Custom props**: `topLeftComponent` / `topRightComponent` / `bottomLeftComponent` / `bottomRightComponent` (corner slots — each occupied corner notches the background around its content), `backgroundImage` (cover image inside the clipped surface), `backgroundImageOpacity` (default `0.8`), `radius` (px, default `16`), `notchRadius` (concave fillet px, default `12`), `notchGap` (gutter px between corner content and background edge, default `12`), `padding` (px, default `24`), `avoidNotches` (default `true` — float spacers with `shape-outside` keep flowing content wrapped around the cutouts; set `false` when `contentClassName` makes the wrapper flex/grid, floats have no effect there), `bordered` (default on for `default`/`muted`, off otherwise), `backgroundClassName` (classes for the clipped background layer — put custom `bg-*`/gradient fills here, NOT in `className`; the layer sits behind the content so hover fills need `group-hover:bg-*`, keyed off the root's `group` marker), `contentClassName`
613
+ - **Notes**: With no corner content it renders a plain rounded rectangle (no clipping/measuring). Corner sizes are tracked with ResizeObserver, so slots can be any content — text, icons, buttons, clusters. `className` styles the root (size/placement); the surface fill lives on an inner clipped layer, hence `backgroundClassName`. Outline is an SVG stroke following the notches (`primary-border`); surface shadow is a drop-shadow filter (box-shadow would be clipped away).
614
+
592
615
  ### Pagination
593
616
  - **Exports**: Pagination, PaginationContent, PaginationLink, PaginationItem, PaginationPrevious, PaginationNext, PaginationEllipsis
594
617
  - **Custom props**: PaginationLink `isActive` (aria-current; default `false`), `size` (default `icon`)
@@ -603,7 +626,7 @@ variant with paint classes (SKILL.md → "Never re-skin a variant").
603
626
  - **Exports**: Progress
604
627
  - **Variants**: `variant: default* | brand | success | warning | info | destructive | analyzing | ingesting`
605
628
  - **Custom props**: `value` (omit/null → indeterminate sliding segment)
606
- - **Notes**: Radix Progress; variant sets both track and indicator colors.
629
+ - **Notes**: Radix Progress; variant sets both track and indicator colors. Radial counterpart: `CircularProgress`.
607
630
 
608
631
  ### RadioGroup
609
632
  - **Exports**: RadioGroup, RadioGroupItem, RichRadioItem
@@ -634,9 +657,9 @@ variant with paint classes (SKILL.md → "Never re-skin a variant").
634
657
 
635
658
  ### Sheet
636
659
  - **Exports**: Sheet, SheetTrigger, SheetClose, SheetContent, SheetHeader, SheetFooter, SheetTitle, SheetDescription
637
- - **Variants**: SheetContent `side: top | right* | bottom | left`, `overlay: default* | dark | glass | none`
660
+ - **Variants**: SheetContent `side: top | right* | bottom | left`, `overlay: default* | dark | glass | none`, `size: small | default* | medium | large | extraLarge`
638
661
  - **Custom props**: SheetContent `showCloseButton` (default `true`)
639
- - **Notes**: Radix Dialog under the hood; content self-portals with overlay; radius on the inward edge only.
662
+ - **Notes**: Radix Dialog under the hood; content self-portals with overlay; radius on the inward edge only. `size` scales the panel per side — left/right width caps: `small` xs (20rem) · `default` sm (24rem) · `medium` md (28rem) · `large` lg (32rem) · `extraLarge` 2xl (42rem); top/bottom heights: 40vh / auto (content) / 60vh / 80vh / 95vh. Prefer `size` over a width/height `className` override.
640
663
 
641
664
  ### Sidebar
642
665
  - **Exports**: Sidebar, SidebarProvider, SidebarTrigger, SidebarRail, SidebarInset, SidebarInput, SidebarHeader, SidebarFooter, SidebarContent, SidebarGroup, SidebarGroupLabel, SidebarGroupAction, SidebarGroupContent, SidebarMenu, SidebarMenuItem, SidebarMenuButton, SidebarMenuAction, SidebarMenuBadge, SidebarMenuSkeleton, SidebarMenuSub, SidebarMenuSubItem, SidebarMenuSubButton, SidebarSeparator, useSidebar
package/SKILL.md CHANGED
@@ -18,7 +18,7 @@ demonstrably can't produce the design:
18
18
  1. **Pattern first**: does a pattern (`patterns/Header`, `DataTable`, `Footer`,
19
19
  `SectionCard`, `SectionHeading`, `MediaObject`) or layout (`Container`, `Stack`,
20
20
  `TwoColumn`, `MultiColumn`, `PageBackground`) already solve it? Use it.
21
- 2. **Primitive second**: compose from `primitives/*` (64 of them — check the catalog
21
+ 2. **Primitive second**: compose from `primitives/*` (67 of them — check the catalog
22
22
  in DESIGN.md §6 before writing anything custom).
23
23
  3. **Stock rendering**: render the chosen component with its variants/props as
24
24
  designed. Pick the variant from its "Choosing a variant" table in DESIGN.md
package/dist/Header.cjs CHANGED
@@ -213,7 +213,7 @@ const PROJECTS_MAX_PAGES = 40;
213
213
  const PATHS = {
214
214
  token: "/api/v1/studio-auth/sessions/token",
215
215
  logout: "/api/v1/studio-auth/sessions/logout",
216
- projects: (clientId) => `/api/v1/client-projects/getAllProjects?limit=50&page=1&sort=name&sortOrder=ASC&clientId=${encodeURIComponent(clientId)}&metaData=true`,
216
+ projects: (clientId) => `/save/api/v1/client-projects/getAllProjects?limit=50&page=1&sort=name&sortOrder=ASC&clientId=${encodeURIComponent(clientId)}&metaData=true`,
217
217
  credits: "/save/api/v1/users"
218
218
  };
219
219
  /** Join a base URL and path without doubling slashes. */
@@ -1 +1 @@
1
- {"version":3,"file":"Header.cjs","names":["PILL","React","cn","Skeleton","Icon","ChevronDown","Popover","PopoverTrigger","PopoverContent","Search","Input","ChevronRight","Check","React","React","cn","Logo","Skeleton","useTheme","Button","Moon","Sun","DropdownMenu","DropdownMenuTrigger","Avatar","AvatarFallback","DropdownMenuContent","DropdownMenuLabel","DropdownMenuSeparator","DropdownMenuItem","LogOut","QueryClient","QueryClientProvider","MessageSquareShare","Credits"],"sources":["../src/patterns/Header/project-tree.ts","../src/patterns/Header/ProjectPicker.tsx","../src/patterns/Header/labels.ts","../src/patterns/Header/api.ts","../src/patterns/Header/storage.ts","../src/patterns/Header/header-store.ts","../src/patterns/Header/session.ts","../src/patterns/Header/use-global-header.ts","../src/patterns/Header/Header.tsx"],"sourcesContent":["import type { ProjectNode } from \"./types\";\n\n/** True when a node with the given id exists anywhere in the tree. */\nexport function nodeExistsInTree(tree: ProjectNode[], id: string): boolean {\n return tree.some((node) => node.id === id || nodeExistsInTree(node.children, id));\n}\n\n/** Name of the node with the given id, or undefined. */\nexport function findProjectName(tree: ProjectNode[], id: string): string | undefined {\n for (const node of tree) {\n if (node.id === id) return node.name;\n const found = findProjectName(node.children, id);\n if (found) return found;\n }\n return undefined;\n}\n\n/** First selectable node in the tree (depth-first, skipping context-only ancestors). */\nexport function firstSelectableProject(tree: ProjectNode[]): ProjectNode | undefined {\n for (const node of tree) {\n if (!node.isContextOnly) return node;\n const found = firstSelectableProject(node.children);\n if (found) return found;\n }\n return undefined;\n}\n\n/** Filter the tree to nodes matching `term`, preserving ancestors of matches. */\nexport function filterTree(nodes: ProjectNode[], term: string): ProjectNode[] {\n if (!term) return nodes;\n const lower = term.toLowerCase();\n return nodes.flatMap((node) => {\n if (node.name.toLowerCase().includes(lower)) return [node];\n const children = filterTree(node.children, term);\n return children.length > 0 ? [{ ...node, children }] : [];\n });\n}\n","\"use client\";\n\nimport { Icon } from \"@/primitives/Icon\";\nimport { Check, ChevronDown, ChevronRight, Search } from \"lucide-react\";\nimport * as React from \"react\";\n\nimport { Input } from \"@/primitives/Input\";\nimport { Popover, PopoverContent, PopoverTrigger } from \"@/primitives/Popover\";\nimport { Skeleton } from \"@/primitives/Skeleton\";\nimport { cn } from \"@/utils\";\nimport { filterTree, findProjectName } from \"./project-tree\";\nimport type { ProjectNode } from \"./types\";\n\ninterface ProjectPickerProps {\n projectsTree: ProjectNode[];\n selectedProjectId: string;\n selectedProjectName?: string;\n onSelect: (id: string) => void;\n projectLabel: string;\n projectPlaceholder: string;\n searchPlaceholder: string;\n emptyStateText: string;\n isLoading?: boolean;\n}\n\n// Pill shared by the trigger and the org pill — keeps the header lockup consistent.\nconst PILL =\n \"flex min-h-8 items-center gap-1 rounded-12 border border-primary-border bg-input-bg px-3 py-1 text-xs leading-4\";\n\nexport function ProjectPicker({\n projectsTree,\n selectedProjectId,\n selectedProjectName,\n onSelect,\n projectLabel,\n projectPlaceholder,\n searchPlaceholder,\n emptyStateText,\n isLoading = false,\n}: Readonly<ProjectPickerProps>) {\n const [open, setOpen] = React.useState(false);\n const [searchTerm, setSearchTerm] = React.useState(\"\");\n const [collapsedIds, setCollapsedIds] = React.useState<Set<string>>(new Set());\n\n const toggleCollapse = (id: string) =>\n setCollapsedIds((prev) => {\n const next = new Set(prev);\n if (next.has(id)) next.delete(id);\n else next.add(id);\n return next;\n });\n\n const handleSelect = (id: string) => {\n onSelect(id);\n setOpen(false);\n };\n\n const selectedName = selectedProjectId\n ? (findProjectName(projectsTree, selectedProjectId) ?? selectedProjectName)\n : undefined;\n\n const filteredTree = filterTree(projectsTree, searchTerm);\n\n if (isLoading) {\n return (\n <div data-slot=\"header-project-picker\" className={cn(PILL, \"min-w-44\")}>\n <span className=\"shrink-0 text-muted-txt\">{projectLabel}:</span>\n <Skeleton className=\"h-3 flex-1\" />\n <Icon as={ChevronDown} className=\"size-4 shrink-0 text-muted-txt opacity-40\" />\n </div>\n );\n }\n\n return (\n <Popover\n open={open}\n onOpenChange={(next) => {\n setOpen(next);\n if (!next) setSearchTerm(\"\");\n }}\n >\n <PopoverTrigger\n data-slot=\"header-project-picker\"\n className={cn(PILL, \"text-left transition-colors hover:border-focus/60\")}\n >\n <span className=\"shrink-0 text-muted-txt\">{projectLabel}:</span>\n <span className={cn(\"max-w-36 truncate\", selectedName ? \"font-medium\" : \"text-muted-txt\")}>\n {selectedName ?? projectPlaceholder}\n </span>\n <Icon as={ChevronDown} className=\"ml-1 size-4 shrink-0 text-muted-txt\" />\n </PopoverTrigger>\n <PopoverContent align=\"start\" className=\"w-64 p-0\" role=\"tree\" aria-label={projectLabel}>\n <div className=\"border-b p-2\">\n <div className=\"relative\">\n <Icon\n as={Search}\n className=\"absolute top-1/2 left-2.5 size-3.5 -translate-y-1/2 text-muted-txt\"\n />\n <Input\n size=\"sm\"\n className=\"pl-8\"\n placeholder={searchPlaceholder}\n value={searchTerm}\n onChange={(e) => setSearchTerm(e.target.value)}\n />\n </div>\n </div>\n <div className=\"max-h-64 overflow-y-auto py-1\">\n {filteredTree.length === 0 ? (\n <p className=\"px-1 py-0.5 text-sm text-muted-txt\">{emptyStateText}</p>\n ) : (\n filteredTree.map((node) => (\n <TreeNode\n key={node.id}\n node={node}\n depth={0}\n selectedId={selectedProjectId}\n onSelect={handleSelect}\n collapsedIds={collapsedIds}\n onToggleCollapse={toggleCollapse}\n />\n ))\n )}\n </div>\n </PopoverContent>\n </Popover>\n );\n}\n\ninterface TreeNodeProps {\n node: ProjectNode;\n depth: number;\n selectedId: string;\n onSelect: (id: string) => void;\n collapsedIds: Set<string>;\n onToggleCollapse: (id: string) => void;\n}\n\nfunction TreeNode({\n node,\n depth,\n selectedId,\n onSelect,\n collapsedIds,\n onToggleCollapse,\n}: Readonly<TreeNodeProps>) {\n const isSelected = !node.isContextOnly && selectedId === node.id;\n const isCollapsed = collapsedIds.has(node.id);\n const hasChildren = node.children.length > 0;\n\n return (\n <div\n role=\"treeitem\"\n aria-selected={node.isContextOnly ? undefined : isSelected}\n aria-expanded={hasChildren ? !isCollapsed : undefined}\n >\n <div\n style={{ paddingLeft: `${0.75 + depth}rem` }}\n className={cn(\n \"flex items-center gap-1 py-2 pr-3 text-sm transition-colors\",\n node.isContextOnly\n ? \"cursor-default text-muted-txt\"\n : \"cursor-pointer hover:bg-ghost-hover-bg\",\n isSelected && \"bg-secondary-bg font-medium\",\n )}\n >\n {hasChildren ? (\n <button\n type=\"button\"\n aria-label={isCollapsed ? `Expand ${node.name}` : `Collapse ${node.name}`}\n onClick={() => onToggleCollapse(node.id)}\n className=\"shrink-0 text-muted-txt hover:text-primary-txt\"\n >\n {isCollapsed ? (\n <Icon as={ChevronRight} className=\"size-3.5\" />\n ) : (\n <Icon as={ChevronDown} className=\"size-3.5\" />\n )}\n </button>\n ) : (\n <span className=\"inline-block w-3.5 shrink-0\" />\n )}\n\n {node.isContextOnly ? (\n <span className=\"flex-1 text-left\">{node.name}</span>\n ) : (\n <button type=\"button\" onClick={() => onSelect(node.id)} className=\"flex-1 text-left\">\n {node.name}\n </button>\n )}\n\n {isSelected && <Icon as={Check} className=\"ml-auto size-3.5 shrink-0 text-primary\" />}\n </div>\n {!isCollapsed && hasChildren && (\n <div role=\"group\">\n {node.children.map((child) => (\n <TreeNode\n key={child.id}\n node={child}\n depth={depth + 1}\n selectedId={selectedId}\n onSelect={onSelect}\n collapsedIds={collapsedIds}\n onToggleCollapse={onToggleCollapse}\n />\n ))}\n </div>\n )}\n </div>\n );\n}\n","/** Default UI strings. Spread-override via the Header `labels` prop if needed. */\nexport const DEFAULT_LABELS = {\n orgLabel: \"Org\",\n projectLabel: \"Project\",\n projectPlaceholder: \"Select project...\",\n searchPlaceholder: \"Search project\",\n emptyStateText: \"No projects found\",\n profileMenuLabel: \"Profile menu\",\n logoutLabel: \"Logout\",\n} as const;\n\nexport type Labels = typeof DEFAULT_LABELS;\n","import type { Fetcher, HeaderEndpoints, HeaderProps, ProjectNode } from \"./types\";\n\n// Studio-auth API. Endpoints are built from the host-provided `apiBaseUrl` (full\n// domain) so the same header works across environments/subdomains. All requests\n// send cookies (`credentials: 'include'`); the parent-domain session cookie is\n// readable cross-subdomain.\n\n/** Page size for the paginated projects endpoint. */\nexport const PROJECTS_PAGE_LIMIT = 50;\n/** Hard cap on project pages fetched — guards against a runaway loop. */\nconst PROJECTS_MAX_PAGES = 40;\n\nconst PATHS = {\n token: \"/api/v1/studio-auth/sessions/token\",\n logout: \"/api/v1/studio-auth/sessions/logout\",\n projects: (clientId: string) =>\n `/api/v1/client-projects/getAllProjects?limit=${PROJECTS_PAGE_LIMIT}&page=1&sort=name&sortOrder=ASC&clientId=${encodeURIComponent(clientId)}&metaData=true`,\n credits: \"/save/api/v1/users\",\n};\n\n/** Join a base URL and path without doubling slashes. */\nfunction join(baseUrl: string, path: string): string {\n return `${baseUrl.replace(/\\/$/, \"\")}${path}`;\n}\n\nexport function buildEndpoints(\n apiBaseUrl: string,\n overrides?: HeaderProps[\"endpoints\"],\n): HeaderEndpoints {\n return {\n token: overrides?.token ?? join(apiBaseUrl, PATHS.token),\n logout: overrides?.logout ?? join(apiBaseUrl, PATHS.logout),\n projects:\n overrides?.projects ?? ((clientId: string) => join(apiBaseUrl, PATHS.projects(clientId))),\n credits: overrides?.credits ?? join(apiBaseUrl, PATHS.credits),\n };\n}\n\ntype ApiEnvelope<T> = { response?: { data?: T } };\n\nexport async function fetchToken(endpoints: HeaderEndpoints, fetcher: Fetcher): Promise<string> {\n const res = await fetcher(endpoints.token, { credentials: \"include\" });\n if (!res.ok) throw new Error(`token request failed: ${res.status}`);\n const { accessToken } = (await res.json()) as { accessToken: string };\n return accessToken;\n}\n\ntype ProjectsPayload = {\n projectsTree?: ProjectNode[];\n organization?: { name?: string };\n};\n\n/**\n * Return `url` with the `page` query param set to the given page (and `limit`\n * backfilled when absent). Pagination stays owned by the header: host-provided\n * endpoint URLs don't need — and can't break — the paging params. Handles\n * absolute and relative URLs.\n */\nexport function withPageParam(url: string, page: number): string {\n const isAbsolute = /^[a-z][a-z0-9+.-]*:\\/\\//i.test(url);\n try {\n const u = new URL(url, isAbsolute ? undefined : \"http://relative.invalid\");\n u.searchParams.set(\"page\", String(page));\n if (!u.searchParams.has(\"limit\")) u.searchParams.set(\"limit\", String(PROJECTS_PAGE_LIMIT));\n return isAbsolute ? u.toString() : `${u.pathname}${u.search}${u.hash}`;\n } catch {\n return url;\n }\n}\n\n/** The `limit` query param already on a URL, else the default page size. */\nfunction readLimitParam(url: string): number {\n try {\n const limit = Number(new URL(url, \"http://relative.invalid\").searchParams.get(\"limit\"));\n return Number.isInteger(limit) && limit > 0 ? limit : PROJECTS_PAGE_LIMIT;\n } catch {\n return PROJECTS_PAGE_LIMIT;\n }\n}\n\n/** Total node count in a tree page (roots + descendants). */\nfunction countNodes(tree: ProjectNode[]): number {\n return tree.reduce((sum, node) => sum + 1 + countNodes(node.children ?? []), 0);\n}\n\n/**\n * Merge a page's tree into the accumulated tree. Nodes repeated across pages\n * (e.g. a context-only ancestor whose children span a page boundary) are\n * merged by id instead of duplicated.\n */\nfunction mergeTrees(into: ProjectNode[], page: ProjectNode[]): void {\n for (const node of page) {\n const existing = into.find((n) => n.id === node.id);\n if (existing) mergeTrees(existing.children, node.children ?? []);\n else into.push({ ...node, children: [...(node.children ?? [])] });\n }\n}\n\n/**\n * Fetch ALL pages of the paginated projects endpoint and merge them into a\n * single tree, so users with more projects than one page still see everything.\n * The response carries no pagination metadata, so the first page that comes\n * back with fewer than `limit` nodes is treated as the last one.\n */\nexport async function fetchProjects(\n endpoints: HeaderEndpoints,\n clientId: string,\n accessToken: string,\n fetcher: Fetcher,\n): Promise<{ projectsTree: ProjectNode[]; organizationName: string | undefined }> {\n const projectsTree: ProjectNode[] = [];\n let organizationName: string | undefined;\n const baseUrl = endpoints.projects(clientId);\n const pageLimit = readLimitParam(baseUrl);\n\n for (let page = 1; page <= PROJECTS_MAX_PAGES; page++) {\n const res = await fetcher(withPageParam(baseUrl, page), {\n credentials: \"include\",\n headers: { Authorization: `Bearer ${accessToken}` },\n });\n if (!res.ok) throw new Error(`projects request failed: ${res.status}`);\n const body = (await res.json()) as ApiEnvelope<ProjectsPayload>;\n const pageTree = body.response?.data?.projectsTree ?? [];\n mergeTrees(projectsTree, pageTree);\n organizationName ??= body.response?.data?.organization?.name;\n\n // A short page means there is nothing left.\n if (countNodes(pageTree) < pageLimit) break;\n }\n\n return { projectsTree, organizationName };\n}\n\nexport async function fetchCredits(\n endpoints: HeaderEndpoints,\n accessToken: string,\n fetcher: Fetcher,\n): Promise<number | undefined> {\n const res = await fetcher(endpoints.credits, {\n credentials: \"include\",\n headers: { Authorization: `Bearer ${accessToken}` },\n });\n if (!res.ok) throw new Error(`credits request failed: ${res.status}`);\n const data = (await res.json()) as { remainingCredits?: number };\n return data.remainingCredits;\n}\n\nexport async function callLogout(endpoints: HeaderEndpoints, fetcher: Fetcher): Promise<void> {\n try {\n await fetcher(endpoints.logout, { method: \"POST\", credentials: \"include\" });\n } finally {\n if (typeof window !== \"undefined\") window.location.href = \"/\";\n }\n}\n","// Persists the user's project selection across reloads (sessionStorage), tagged\n// with the client it belongs to so a stale selection from a different org is\n// discarded on re-login. Explicit selections are additionally remembered in\n// localStorage (`lastSelectedProject`) so new tabs default to the project the\n// user picked last — while each tab keeps its own per-tab selection.\n// The full (all pages, merged) projects result is also cached in sessionStorage\n// so the paginated projects API is hit once per tab session, not on every mount\n// or reload.\n\nimport type { ProjectNode } from \"./types\";\n\nconst PROJECT_KEY = \"ds-header-project\";\nconst LAST_PROJECT_KEY = \"lastSelectedProject\";\nconst PROJECTS_CACHE_KEY = \"ds-header-projects-cache\";\n\nexport interface StoredProject {\n id: string;\n name: string;\n clientId?: string;\n}\n\nexport function getStoredProject(): StoredProject | null {\n try {\n const raw = sessionStorage.getItem(PROJECT_KEY);\n return raw ? (JSON.parse(raw) as StoredProject) : null;\n } catch {\n return null;\n }\n}\n\nexport function setStoredProject(project: StoredProject): void {\n try {\n sessionStorage.setItem(PROJECT_KEY, JSON.stringify(project));\n } catch {\n // sessionStorage unavailable — degrade silently\n }\n}\n\nexport function clearStoredProject(): void {\n try {\n sessionStorage.removeItem(PROJECT_KEY);\n } catch {\n // noop\n }\n}\n\n/** The project the user last explicitly selected, in any tab (localStorage). */\nexport function getLastSelectedProject(): StoredProject | null {\n try {\n const raw = localStorage.getItem(LAST_PROJECT_KEY);\n return raw ? (JSON.parse(raw) as StoredProject) : null;\n } catch {\n return null;\n }\n}\n\nexport function setLastSelectedProject(project: StoredProject): void {\n try {\n localStorage.setItem(LAST_PROJECT_KEY, JSON.stringify(project));\n } catch {\n // localStorage unavailable — degrade silently\n }\n}\n\nexport interface CachedProjects {\n projectsTree: ProjectNode[];\n organizationName: string | undefined;\n}\n\n// Keyed by client id + user id (both from the session JWT) so switching user\n// or organisation misses the cache and refetches instead of serving another\n// identity's projects.\nfunction projectsCacheKey(clientId: string, userId: string): string {\n return `${PROJECTS_CACHE_KEY}:${clientId}:${userId}`;\n}\n\n/** The session-cached projects result for this client + user, or null on miss. */\nexport function getCachedProjects(clientId: string, userId: string): CachedProjects | null {\n try {\n const raw = sessionStorage.getItem(projectsCacheKey(clientId, userId));\n if (!raw) return null;\n const cached = JSON.parse(raw) as Partial<CachedProjects>;\n if (!Array.isArray(cached.projectsTree)) return null;\n return { projectsTree: cached.projectsTree, organizationName: cached.organizationName };\n } catch {\n return null;\n }\n}\n\nexport function setCachedProjects(clientId: string, userId: string, data: CachedProjects): void {\n try {\n sessionStorage.setItem(projectsCacheKey(clientId, userId), JSON.stringify(data));\n } catch {\n // sessionStorage unavailable/full — degrade silently\n }\n}\n\n/** Drop every cached projects entry (all clients/users) — used on logout. */\nexport function clearCachedProjects(): void {\n try {\n for (let i = sessionStorage.length - 1; i >= 0; i--) {\n const key = sessionStorage.key(i);\n if (key?.startsWith(PROJECTS_CACHE_KEY)) sessionStorage.removeItem(key);\n }\n } catch {\n // noop\n }\n}\n","\"use client\";\n\nimport * as React from \"react\";\n\nimport {\n clearStoredProject,\n getStoredProject,\n setLastSelectedProject,\n setStoredProject,\n} from \"./storage\";\n\n// Module-level store for the current project/org selection. Module scope (not\n// React context) so a host app can read and change the selection from anywhere —\n// including components rendered outside the <Header> subtree. The Header is one\n// writer/reader; `useHeaderProject()` gives apps the same access.\n\nexport interface HeaderSelection {\n selectedProjectId: string;\n selectedProjectName: string;\n organizationName: string | undefined;\n /** Remaining credits for the logged-in user (read-only here; set by the Header). */\n credits: number | undefined;\n /** Client/org the current selection + org belong to (for cross-org invalidation). */\n clientId: string | undefined;\n}\n\nfunction initialState(): HeaderSelection {\n const stored = typeof window !== \"undefined\" ? getStoredProject() : null;\n return {\n selectedProjectId: stored?.id ?? \"\",\n selectedProjectName: stored?.name ?? \"\",\n organizationName: undefined,\n credits: undefined,\n clientId: stored?.clientId,\n };\n}\n\nlet state: HeaderSelection = initialState();\n// Stable reference for SSR / first server render.\nconst SERVER_SNAPSHOT: HeaderSelection = Object.freeze({\n selectedProjectId: \"\",\n selectedProjectName: \"\",\n organizationName: undefined,\n credits: undefined,\n clientId: undefined,\n});\n\nconst listeners = new Set<() => void>();\nfunction emit() {\n for (const listener of listeners) listener();\n}\n\nexport const headerStore = {\n subscribe(listener: () => void) {\n listeners.add(listener);\n return () => listeners.delete(listener);\n },\n getSnapshot(): HeaderSelection {\n return state;\n },\n getServerSnapshot(): HeaderSelection {\n return SERVER_SNAPSHOT;\n },\n\n /**\n * Set the selected project. `name` is best-effort; the Header backfills it from\n * the tree. Explicit selections are also remembered in localStorage as the\n * cross-tab default; pass `remember: false` for internal backfill/auto-select\n * writes so they don't overwrite the user's last explicit choice.\n */\n setProject(id: string, name = \"\", clientId?: string, { remember = true } = {}) {\n if (id) {\n const project = { id, name, clientId: clientId ?? state.clientId };\n setStoredProject(project);\n if (remember) setLastSelectedProject(project);\n } else clearStoredProject();\n state = {\n ...state,\n selectedProjectId: id,\n selectedProjectName: name,\n clientId: clientId ?? state.clientId,\n };\n emit();\n },\n\n clearProject() {\n clearStoredProject();\n state = { ...state, selectedProjectId: \"\", selectedProjectName: \"\" };\n emit();\n },\n\n setOrganization(name: string | undefined, clientId?: string) {\n state = { ...state, organizationName: name, clientId: clientId ?? state.clientId };\n emit();\n },\n\n setCredits(credits: number | undefined) {\n if (state.credits === credits) return;\n state = { ...state, credits };\n emit();\n },\n\n /** When the active client changes, drop a selection/org from the previous one. */\n reconcileClient(clientId: string) {\n if (state.clientId === clientId) return;\n if (state.clientId && state.clientId !== clientId) {\n clearStoredProject();\n state = {\n selectedProjectId: \"\",\n selectedProjectName: \"\",\n organizationName: undefined,\n credits: state.credits, // user-level — survives org switches\n clientId,\n };\n } else {\n state = { ...state, clientId };\n }\n emit();\n },\n};\n\n/** Internal: subscribe a component to the selection store. */\nexport function useHeaderStore(): HeaderSelection {\n return React.useSyncExternalStore(\n headerStore.subscribe,\n headerStore.getSnapshot,\n headerStore.getServerSnapshot,\n );\n}\n\nexport interface UseHeaderProjectResult {\n selectedProjectId: string;\n selectedProjectName: string | undefined;\n organizationName: string | undefined;\n /** Set the active project from outside the Header (by id). */\n setProject: (id: string) => void;\n /** Clear this tab's active project (the header re-defaults on next projects load). */\n clearProject: () => void;\n}\n\n/**\n * Read the current project/org and change the project from anywhere in the app —\n * no need to be inside the <Header>. Reflects user selections made in the header\n * and updates the header when changed here.\n */\nexport function useHeaderProject(): UseHeaderProjectResult {\n const snapshot = useHeaderStore();\n return {\n selectedProjectId: snapshot.selectedProjectId,\n selectedProjectName: snapshot.selectedProjectName || undefined,\n organizationName: snapshot.organizationName,\n setProject: React.useCallback((id: string) => headerStore.setProject(id), []),\n clearProject: React.useCallback(() => headerStore.clearProject(), []),\n };\n}\n\n/** Read the logged-in user's remaining credits (read-only; the Header owns it). */\nexport function useHeaderCredits(): number | undefined {\n return useHeaderStore().credits;\n}\n","// Client-side session detection. The auth system writes a JS-readable cookie\n// `{environmentId}-sessionId` (a JWT) on the shared parent domain. We decode it\n// and check its expiry to know whether the user is logged in — no network call.\n\ninterface JwtPayload {\n exp?: number;\n [key: string]: unknown;\n}\n\n/** Read the raw session JWT from the `{environmentId}-sessionId` cookie. */\nexport function getSessionToken(environmentId: string): string | null {\n if (typeof document === \"undefined\") return null;\n const name = `${environmentId}-sessionId`;\n for (const part of document.cookie.split(\";\")) {\n const [key, ...rest] = part.trim().split(\"=\");\n if (key === name) return decodeURIComponent(rest.join(\"=\"));\n }\n return null;\n}\n\n/** Decode a JWT payload without verifying the signature (display/expiry only). */\nexport function decodeJwt(token: string): JwtPayload | null {\n try {\n const payload = token.split(\".\")[1];\n if (!payload) return null;\n const base64 = payload.replace(/-/g, \"+\").replace(/_/g, \"/\");\n const json = atob(base64);\n return JSON.parse(json) as JwtPayload;\n } catch {\n return null;\n }\n}\n\n/** User/session claims carried in the session JWT (the subset the header uses). */\nexport interface SessionClaims {\n email?: string;\n name?: string;\n userId?: string;\n /** Active organisation id (`client_id` claim). */\n clientId?: string;\n exp?: number;\n}\n\n/**\n * Decode the user claims from the session cookie's JWT — no network call.\n * Returns null when the cookie is absent or undecodable.\n */\nexport function getSessionClaims(environmentId: string): SessionClaims | null {\n const token = getSessionToken(environmentId);\n if (!token) return null;\n const payload = decodeJwt(token);\n if (!payload) return null;\n const str = (v: unknown) => (typeof v === \"string\" ? v : undefined);\n return {\n email: str(payload.email),\n name: str(payload.name),\n userId: str(payload.user_id),\n clientId: str(payload.client_id),\n exp: typeof payload.exp === \"number\" ? payload.exp : undefined,\n };\n}\n\n/** True when a valid, unexpired session cookie exists for the environment. */\nexport function isSessionValid(environmentId: string): boolean {\n const token = getSessionToken(environmentId);\n if (!token) return false;\n const payload = decodeJwt(token);\n if (!payload) return false;\n // No exp claim → treat as a non-expiring session.\n if (typeof payload.exp !== \"number\") return true;\n return payload.exp * 1000 > Date.now();\n}\n","\"use client\";\n\nimport { useQuery } from \"@tanstack/react-query\";\nimport * as React from \"react\";\n\nimport { buildEndpoints, callLogout, fetchCredits, fetchProjects, fetchToken } from \"./api\";\nimport { headerStore, useHeaderStore } from \"./header-store\";\nimport { findProjectName, firstSelectableProject, nodeExistsInTree } from \"./project-tree\";\nimport { getSessionClaims, isSessionValid } from \"./session\";\nimport {\n clearCachedProjects,\n getCachedProjects,\n getLastSelectedProject,\n setCachedProjects,\n} from \"./storage\";\nimport type { HeaderProps, ProjectNode } from \"./types\";\n\n/** Window event other modules can dispatch to show/hide the project dropdown. */\nexport const TOGGLE_PROJECT_DROPDOWN_EVENT = \"toggle-project-dropdown\";\nexport interface ToggleProjectDropdownDetail {\n show: boolean;\n}\n\nconst DEFAULT_STALE_TIME = 5 * 60_000;\nconst DEFAULT_GC_TIME = 10 * 60_000;\n\nexport interface GlobalHeaderState {\n /** Whether a valid session cookie exists — when false, hide all user content. */\n isAuthenticated: boolean;\n userEmail: string | undefined;\n organizationName: string | undefined;\n projectsTree: ProjectNode[];\n selectedProjectId: string;\n selectedProjectName: string | undefined;\n isProjectsLoading: boolean;\n isOrgLoading: boolean;\n /** Remaining credits for the user (undefined until loaded / when disabled). */\n credits: number | undefined;\n /** Where the credits pill links to (studio-auth `/user/activity`). */\n creditsHref: string;\n projectDropdownVisible: boolean;\n selectProject: (id: string) => void;\n logout: () => void;\n}\n\ntype UseGlobalHeaderArgs = Pick<\n HeaderProps,\n | \"apiBaseUrl\"\n | \"environmentId\"\n | \"clientId\"\n | \"defaultProjectId\"\n | \"_dangerouslyInjectAccessToken\"\n | \"showProjectDropdown\"\n | \"showProfile\"\n | \"showOrg\"\n | \"showCredits\"\n | \"endpoints\"\n | \"fetcher\"\n | \"staleTime\"\n | \"gcTime\"\n | \"onProjectChange\"\n>;\n\nexport function useGlobalHeader({\n apiBaseUrl,\n environmentId,\n clientId,\n defaultProjectId,\n _dangerouslyInjectAccessToken: injectedToken,\n showProjectDropdown = false,\n showProfile = false,\n showOrg = false,\n showCredits = false,\n endpoints: endpointOverrides,\n fetcher: fetcherProp,\n staleTime = DEFAULT_STALE_TIME,\n gcTime = DEFAULT_GC_TIME,\n onProjectChange,\n}: UseGlobalHeaderArgs): GlobalHeaderState {\n const fetcher = React.useMemo(\n () => fetcherProp ?? ((input: RequestInfo | URL, init?: RequestInit) => fetch(input, init)),\n [fetcherProp],\n );\n const endpoints = React.useMemo(\n () => buildEndpoints(apiBaseUrl, endpointOverrides),\n [apiBaseUrl, endpointOverrides],\n );\n\n // Read the session cookie each render (cheap); gates every network call.\n // User identity (email, client id) comes from the JWT claims — no /me call.\n const isAuthenticated = isSessionValid(environmentId);\n const claims = getSessionClaims(environmentId);\n\n // token → projects, enabled only when the previous resolved.\n const tokenQuery = useQuery({\n queryKey: [\"ds-header\", \"token\", endpoints.token],\n queryFn: () => fetchToken(endpoints, fetcher),\n enabled: isAuthenticated && !injectedToken,\n staleTime,\n gcTime,\n });\n const token = injectedToken ?? tokenQuery.data;\n\n const effectiveClientId = clientId ?? claims?.clientId;\n const wantsProjects = showProjectDropdown || showOrg;\n // All pages of the projects API, merged. Served from the sessionStorage\n // cache when present so the API is hit once per tab session — not on every\n // mount, reload, or react-query refetch. The cache is keyed by client id +\n // user id (from the JWT), so a different user or org refetches.\n const userId = claims?.userId ?? \"\";\n const projectsQuery = useQuery({\n queryKey: [\"ds-header\", \"projects\", effectiveClientId, userId, token],\n queryFn: async () => {\n const id = effectiveClientId as string;\n const cached = getCachedProjects(id, userId);\n if (cached) return cached;\n const fresh = await fetchProjects(endpoints, id, token as string, fetcher);\n setCachedProjects(id, userId, fresh);\n return fresh;\n },\n enabled: isAuthenticated && !!token && !!effectiveClientId && wantsProjects,\n staleTime,\n gcTime,\n });\n\n // Credits — only needs the token. Always refetched on mount (staleTime 0) so a\n // page refresh shows the current balance.\n const creditsQuery = useQuery({\n queryKey: [\"ds-header\", \"credits\", endpoints.credits, token],\n queryFn: () => fetchCredits(endpoints, token as string, fetcher),\n enabled: isAuthenticated && !!token && showCredits,\n staleTime: 0,\n gcTime,\n });\n\n const projectsTree = projectsQuery.data?.projectsTree ?? [];\n const userEmail = showProfile ? claims?.email : undefined;\n const creditsHref = React.useMemo(() => {\n try {\n return new URL(\"/user/activity\", apiBaseUrl).toString();\n } catch {\n return \"/user/activity\";\n }\n }, [apiBaseUrl]);\n\n // Selection + org live in a module store so host apps can read/change them\n // from outside the header (see useHeaderProject).\n const selection = useHeaderStore();\n\n // Ref so the auto-select effect sees the latest callback without re-running.\n const onProjectChangeRef = React.useRef(onProjectChange);\n React.useEffect(() => {\n onProjectChangeRef.current = onProjectChange;\n });\n\n // Once the client id resolves, drop a selection/org from a different client.\n React.useEffect(() => {\n if (effectiveClientId) headerStore.reconcileClient(effectiveClientId);\n }, [effectiveClientId]);\n\n // Once projects load: publish the org name and validate/backfill the selection.\n // A tab with no valid selection defaults to the user's last explicitly selected\n // project (localStorage `lastSelectedProject`) when it still exists in the\n // tree, else the host's `defaultProjectId`, else the first selectable\n // project — no selection prompt.\n React.useEffect(() => {\n if (!projectsQuery.data) return;\n const tree = projectsQuery.data.projectsTree;\n const id = headerStore.getSnapshot().selectedProjectId;\n if (id && nodeExistsInTree(tree, id)) {\n const name = findProjectName(tree, id);\n if (name && name !== headerStore.getSnapshot().selectedProjectName) {\n headerStore.setProject(id, name, effectiveClientId, { remember: false });\n }\n } else {\n const last = getLastSelectedProject();\n const fallback =\n last && nodeExistsInTree(tree, last.id)\n ? { id: last.id, name: findProjectName(tree, last.id) ?? last.name }\n : defaultProjectId && nodeExistsInTree(tree, defaultProjectId)\n ? { id: defaultProjectId, name: findProjectName(tree, defaultProjectId) ?? \"\" }\n : firstSelectableProject(tree);\n if (fallback) {\n headerStore.setProject(fallback.id, fallback.name, effectiveClientId, {\n remember: false,\n });\n onProjectChangeRef.current?.(fallback.id);\n } else if (id) {\n headerStore.clearProject();\n }\n }\n headerStore.setOrganization(projectsQuery.data.organizationName, effectiveClientId);\n }, [projectsQuery.data, effectiveClientId, defaultProjectId]);\n\n // Publish credits to the store so host apps can read them via useHeaderCredits.\n React.useEffect(() => {\n if (creditsQuery.data !== undefined) headerStore.setCredits(creditsQuery.data);\n }, [creditsQuery.data]);\n\n const selectProject = (id: string) => {\n const name = findProjectName(projectsTree, id) ?? \"\";\n headerStore.setProject(id, name, effectiveClientId);\n onProjectChange?.(id);\n };\n\n const logout = () => {\n headerStore.clearProject();\n clearCachedProjects();\n void callLogout(endpoints, fetcher);\n };\n\n // Visibility: declarative from the prop, overridable at runtime via the event.\n const [projectDropdownVisible, setProjectDropdownVisible] = React.useState(showProjectDropdown);\n React.useEffect(() => setProjectDropdownVisible(showProjectDropdown), [showProjectDropdown]);\n React.useEffect(() => {\n const handler = (e: Event) => {\n setProjectDropdownVisible((e as CustomEvent<ToggleProjectDropdownDetail>).detail.show);\n };\n window.addEventListener(TOGGLE_PROJECT_DROPDOWN_EVENT, handler);\n return () => window.removeEventListener(TOGGLE_PROJECT_DROPDOWN_EVENT, handler);\n }, []);\n\n const isProjectsLoading = projectsQuery.isFetching && !projectsQuery.data;\n\n return {\n isAuthenticated,\n userEmail,\n organizationName: selection.organizationName,\n projectsTree,\n selectedProjectId: selection.selectedProjectId,\n selectedProjectName: selection.selectedProjectName || undefined,\n isProjectsLoading,\n isOrgLoading: showOrg && isProjectsLoading,\n credits: selection.credits,\n creditsHref,\n projectDropdownVisible,\n selectProject,\n logout,\n };\n}\n","\"use client\";\n\nimport { QueryClient, QueryClientProvider } from \"@tanstack/react-query\";\nimport { LogOut, MessageSquareShare, Moon, Sun } from \"lucide-react\";\nimport type * as React from \"react\";\n\nimport { Avatar, AvatarFallback } from \"@/primitives/Avatar\";\nimport { Button } from \"@/primitives/Button\";\nimport { Credits } from \"@/primitives/Credits\";\nimport {\n DropdownMenu,\n DropdownMenuContent,\n DropdownMenuItem,\n DropdownMenuLabel,\n DropdownMenuSeparator,\n DropdownMenuTrigger,\n} from \"@/primitives/DropdownMenu\";\nimport { Logo } from \"@/primitives/Logo\";\nimport { Skeleton } from \"@/primitives/Skeleton\";\nimport { type ThemeProduct, useTheme } from \"@/primitives/ThemeProvider\";\nimport { cn } from \"@/utils\";\nimport { ProjectPicker } from \"./ProjectPicker\";\nimport { DEFAULT_LABELS } from \"./labels\";\nimport type { HeaderProps } from \"./types\";\nimport { useGlobalHeader } from \"./use-global-header\";\n\n// Fallback logo destinations when the host doesn't pass `logoHref`.\nconst LOGO_HREF: Record<ThemeProduct, string> = {\n psai: \"https://sapientaiproducts.com/\",\n slingshot: \"https://sapientaiproducts.com/slingshot\",\n sustain: \"https://www.publicissapient.com/\",\n bodhi: \"https://sapientaiproducts.com/bodhi\",\n};\n\nconst PILL =\n \"flex min-h-8 items-center gap-1 rounded-12 border border-primary-border bg-input-bg px-3 py-1 text-xs leading-4\";\n\n// ── Presentational parts (props-driven; Storybook/VR-able) ──────────────────\n\n/** The header bar shell — a sticky glass strip. */\nfunction HeaderBar({ className, ...props }: React.ComponentProps<\"header\">) {\n return (\n <header\n data-slot=\"header\"\n className={cn(\n \"sticky top-1 z-10 mt-1 flex h-15 items-center gap-5 rounded-16 px-3 py-2\",\n \"bg-glass-60-bg backdrop-blur-glass\",\n className,\n )}\n {...props}\n />\n );\n}\n\n/** Product logo linking to its home, with a Suspense-safe fallback. */\nfunction HeaderLogo({ brand, href }: { brand: ThemeProduct; href?: string }) {\n return (\n <a href={href ?? LOGO_HREF[brand]} aria-label=\"Go to product home\" data-slot=\"header-logo\">\n <Logo brand={brand} className=\"h-8 w-auto\" />\n </a>\n );\n}\n\n/** Read-only organisation pill. */\nfunction OrgPill({ name, loading }: { name?: string; loading?: boolean }) {\n if (loading && !name) {\n return (\n <div className={cn(PILL, \"ml-3\")} data-slot=\"header-org\">\n <span className=\"shrink-0 text-muted-txt\">{DEFAULT_LABELS.orgLabel}:</span>\n <Skeleton className=\"h-4 w-24\" />\n </div>\n );\n }\n if (!name) return null;\n return (\n <div className={cn(PILL, \"ml-3 select-none\")} title={name} data-slot=\"header-org\">\n <span className=\"shrink-0 text-muted-txt\">{DEFAULT_LABELS.orgLabel}:</span>\n <span className=\"max-w-36 truncate text-primary-txt\">{name}</span>\n </div>\n );\n}\n\n/** Light/dark toggle — defers to ThemeProvider. */\nfunction ThemeToggle() {\n const { theme, toggleTheme } = useTheme();\n return (\n <Button variant=\"ghost\" size=\"icon\" onClick={toggleTheme} aria-label=\"Toggle theme\">\n {theme === \"light\" ? <Moon className=\"size-4\" /> : <Sun className=\"size-4\" />}\n </Button>\n );\n}\n\n/** Profile menu — avatar trigger with email + logout. */\nfunction ProfileMenu({ email, onLogout }: { email?: string; onLogout: () => void }) {\n const initial = email?.trim().charAt(0).toUpperCase() || \"?\";\n return (\n <DropdownMenu>\n <DropdownMenuTrigger asChild>\n <Button variant=\"ghost\" size=\"icon\" aria-label={DEFAULT_LABELS.profileMenuLabel}>\n <Avatar className=\"size-7\">\n <AvatarFallback>{initial}</AvatarFallback>\n </Avatar>\n </Button>\n </DropdownMenuTrigger>\n <DropdownMenuContent align=\"end\" sideOffset={8} className=\"min-w-44\">\n {email && (\n <>\n <DropdownMenuLabel className=\"truncate font-normal text-muted-txt\">\n {email}\n </DropdownMenuLabel>\n <DropdownMenuSeparator />\n </>\n )}\n <DropdownMenuItem onSelect={onLogout} variant=\"destructive\">\n <LogOut />\n {DEFAULT_LABELS.logoutLabel}\n </DropdownMenuItem>\n </DropdownMenuContent>\n </DropdownMenu>\n );\n}\n\nexport { HeaderBar, HeaderLogo, OrgPill, ThemeToggle, ProfileMenu };\n\n// ── Wired Header ─────────────────────────────────────────────────────────────\n\n// Internal singleton client so the header is drop-in (no app setup) while still\n// sharing its cache across mounts/navigation.\nlet sharedClient: QueryClient | undefined;\nfunction getQueryClient(): QueryClient {\n sharedClient ??= new QueryClient({\n defaultOptions: { queries: { retry: 1, refetchOnWindowFocus: false } },\n });\n return sharedClient;\n}\n\n/** Drop-in global header. Must be rendered inside a <ThemeProvider>. */\nexport function Header(props: HeaderProps) {\n return (\n <QueryClientProvider client={getQueryClient()}>\n <HeaderInner {...props} />\n </QueryClientProvider>\n );\n}\n\nfunction HeaderInner({\n logoType,\n logoHref,\n showOrg = false,\n showProjectDropdown = false,\n showProfile = false,\n showThemeSwitcher = false,\n showCredits = false,\n pageTitle,\n feedbackUrl,\n logoAddon,\n actionsStart,\n actionsEnd,\n className,\n ...rest\n}: HeaderProps) {\n const { product } = useTheme();\n const brand = logoType ?? product;\n const state = useGlobalHeader({\n showOrg,\n showProjectDropdown,\n showProfile,\n showCredits,\n ...rest,\n });\n\n // Logged-out users see no user content (project/org/profile/credits).\n const showProjectUi = showProjectDropdown && state.isAuthenticated;\n const showOrgUi = showOrg && state.isAuthenticated;\n const showProfileUi = showProfile && state.isAuthenticated;\n const showCreditsUi = showCredits && state.isAuthenticated && state.credits !== undefined;\n const showActions =\n showThemeSwitcher ||\n showProfileUi ||\n showCreditsUi ||\n !!feedbackUrl ||\n !!actionsStart ||\n !!actionsEnd;\n\n return (\n <HeaderBar className={className}>\n <HeaderLogo brand={brand} href={logoHref} />\n {/* Page title — 20px (gap-5) from the logo. */}\n {pageTitle && (\n <span data-slot=\"header-title\" className=\"ml-5 font-semibold text-primary-txt text-sm\">\n {pageTitle}\n </span>\n )}\n {logoAddon}\n\n {showOrgUi && <OrgPill name={state.organizationName} loading={state.isOrgLoading} />}\n\n {showProjectUi && state.projectDropdownVisible && (\n <div className=\"ml-2\">\n <ProjectPicker\n projectsTree={state.projectsTree}\n selectedProjectId={state.selectedProjectId}\n selectedProjectName={state.selectedProjectName}\n onSelect={state.selectProject}\n projectLabel={DEFAULT_LABELS.projectLabel}\n projectPlaceholder={DEFAULT_LABELS.projectPlaceholder}\n searchPlaceholder={DEFAULT_LABELS.searchPlaceholder}\n emptyStateText={DEFAULT_LABELS.emptyStateText}\n isLoading={state.isProjectsLoading}\n />\n </div>\n )}\n\n {showActions && (\n <div className=\"ml-auto flex items-center gap-2\">\n {actionsStart}\n {feedbackUrl && (\n <Button variant=\"ghost\" size=\"icon\" asChild>\n <a\n href={feedbackUrl}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n aria-label=\"Share feedback\"\n >\n <MessageSquareShare className=\"size-4\" />\n </a>\n </Button>\n )}\n {showThemeSwitcher && <ThemeToggle />}\n {showCreditsUi && state.credits !== undefined && (\n <a\n href={state.creditsHref}\n aria-label=\"View credit activity\"\n className=\"rounded-full outline-none focus-visible:ring-3 focus-visible:ring-focus\"\n >\n <Credits value={state.credits} />\n </a>\n )}\n {showProfileUi && <ProfileMenu email={state.userEmail} onLogout={state.logout} />}\n {actionsEnd}\n </div>\n )}\n </HeaderBar>\n );\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"Header.cjs","names":["PILL","React","cn","Skeleton","Icon","ChevronDown","Popover","PopoverTrigger","PopoverContent","Search","Input","ChevronRight","Check","React","React","cn","Logo","Skeleton","useTheme","Button","Moon","Sun","DropdownMenu","DropdownMenuTrigger","Avatar","AvatarFallback","DropdownMenuContent","DropdownMenuLabel","DropdownMenuSeparator","DropdownMenuItem","LogOut","QueryClient","QueryClientProvider","MessageSquareShare","Credits"],"sources":["../src/patterns/Header/project-tree.ts","../src/patterns/Header/ProjectPicker.tsx","../src/patterns/Header/labels.ts","../src/patterns/Header/api.ts","../src/patterns/Header/storage.ts","../src/patterns/Header/header-store.ts","../src/patterns/Header/session.ts","../src/patterns/Header/use-global-header.ts","../src/patterns/Header/Header.tsx"],"sourcesContent":["import type { ProjectNode } from \"./types\";\n\n/** True when a node with the given id exists anywhere in the tree. */\nexport function nodeExistsInTree(tree: ProjectNode[], id: string): boolean {\n return tree.some((node) => node.id === id || nodeExistsInTree(node.children, id));\n}\n\n/** Name of the node with the given id, or undefined. */\nexport function findProjectName(tree: ProjectNode[], id: string): string | undefined {\n for (const node of tree) {\n if (node.id === id) return node.name;\n const found = findProjectName(node.children, id);\n if (found) return found;\n }\n return undefined;\n}\n\n/** First selectable node in the tree (depth-first, skipping context-only ancestors). */\nexport function firstSelectableProject(tree: ProjectNode[]): ProjectNode | undefined {\n for (const node of tree) {\n if (!node.isContextOnly) return node;\n const found = firstSelectableProject(node.children);\n if (found) return found;\n }\n return undefined;\n}\n\n/** Filter the tree to nodes matching `term`, preserving ancestors of matches. */\nexport function filterTree(nodes: ProjectNode[], term: string): ProjectNode[] {\n if (!term) return nodes;\n const lower = term.toLowerCase();\n return nodes.flatMap((node) => {\n if (node.name.toLowerCase().includes(lower)) return [node];\n const children = filterTree(node.children, term);\n return children.length > 0 ? [{ ...node, children }] : [];\n });\n}\n","\"use client\";\n\nimport { Icon } from \"@/primitives/Icon\";\nimport { Check, ChevronDown, ChevronRight, Search } from \"lucide-react\";\nimport * as React from \"react\";\n\nimport { Input } from \"@/primitives/Input\";\nimport { Popover, PopoverContent, PopoverTrigger } from \"@/primitives/Popover\";\nimport { Skeleton } from \"@/primitives/Skeleton\";\nimport { cn } from \"@/utils\";\nimport { filterTree, findProjectName } from \"./project-tree\";\nimport type { ProjectNode } from \"./types\";\n\ninterface ProjectPickerProps {\n projectsTree: ProjectNode[];\n selectedProjectId: string;\n selectedProjectName?: string;\n onSelect: (id: string) => void;\n projectLabel: string;\n projectPlaceholder: string;\n searchPlaceholder: string;\n emptyStateText: string;\n isLoading?: boolean;\n}\n\n// Pill shared by the trigger and the org pill — keeps the header lockup consistent.\nconst PILL =\n \"flex min-h-8 items-center gap-1 rounded-12 border border-primary-border bg-input-bg px-3 py-1 text-xs leading-4\";\n\nexport function ProjectPicker({\n projectsTree,\n selectedProjectId,\n selectedProjectName,\n onSelect,\n projectLabel,\n projectPlaceholder,\n searchPlaceholder,\n emptyStateText,\n isLoading = false,\n}: Readonly<ProjectPickerProps>) {\n const [open, setOpen] = React.useState(false);\n const [searchTerm, setSearchTerm] = React.useState(\"\");\n const [collapsedIds, setCollapsedIds] = React.useState<Set<string>>(new Set());\n\n const toggleCollapse = (id: string) =>\n setCollapsedIds((prev) => {\n const next = new Set(prev);\n if (next.has(id)) next.delete(id);\n else next.add(id);\n return next;\n });\n\n const handleSelect = (id: string) => {\n onSelect(id);\n setOpen(false);\n };\n\n const selectedName = selectedProjectId\n ? (findProjectName(projectsTree, selectedProjectId) ?? selectedProjectName)\n : undefined;\n\n const filteredTree = filterTree(projectsTree, searchTerm);\n\n if (isLoading) {\n return (\n <div data-slot=\"header-project-picker\" className={cn(PILL, \"min-w-44\")}>\n <span className=\"shrink-0 text-muted-txt\">{projectLabel}:</span>\n <Skeleton className=\"h-3 flex-1\" />\n <Icon as={ChevronDown} className=\"size-4 shrink-0 text-muted-txt opacity-40\" />\n </div>\n );\n }\n\n return (\n <Popover\n open={open}\n onOpenChange={(next) => {\n setOpen(next);\n if (!next) setSearchTerm(\"\");\n }}\n >\n <PopoverTrigger\n data-slot=\"header-project-picker\"\n className={cn(PILL, \"text-left transition-colors hover:border-focus/60\")}\n >\n <span className=\"shrink-0 text-muted-txt\">{projectLabel}:</span>\n <span className={cn(\"max-w-36 truncate\", selectedName ? \"font-medium\" : \"text-muted-txt\")}>\n {selectedName ?? projectPlaceholder}\n </span>\n <Icon as={ChevronDown} className=\"ml-1 size-4 shrink-0 text-muted-txt\" />\n </PopoverTrigger>\n <PopoverContent align=\"start\" className=\"w-64 p-0\" role=\"tree\" aria-label={projectLabel}>\n <div className=\"border-b p-2\">\n <div className=\"relative\">\n <Icon\n as={Search}\n className=\"absolute top-1/2 left-2.5 size-3.5 -translate-y-1/2 text-muted-txt\"\n />\n <Input\n size=\"sm\"\n className=\"pl-8\"\n placeholder={searchPlaceholder}\n value={searchTerm}\n onChange={(e) => setSearchTerm(e.target.value)}\n />\n </div>\n </div>\n <div className=\"max-h-64 overflow-y-auto py-1\">\n {filteredTree.length === 0 ? (\n <p className=\"px-1 py-0.5 text-sm text-muted-txt\">{emptyStateText}</p>\n ) : (\n filteredTree.map((node) => (\n <TreeNode\n key={node.id}\n node={node}\n depth={0}\n selectedId={selectedProjectId}\n onSelect={handleSelect}\n collapsedIds={collapsedIds}\n onToggleCollapse={toggleCollapse}\n />\n ))\n )}\n </div>\n </PopoverContent>\n </Popover>\n );\n}\n\ninterface TreeNodeProps {\n node: ProjectNode;\n depth: number;\n selectedId: string;\n onSelect: (id: string) => void;\n collapsedIds: Set<string>;\n onToggleCollapse: (id: string) => void;\n}\n\nfunction TreeNode({\n node,\n depth,\n selectedId,\n onSelect,\n collapsedIds,\n onToggleCollapse,\n}: Readonly<TreeNodeProps>) {\n const isSelected = !node.isContextOnly && selectedId === node.id;\n const isCollapsed = collapsedIds.has(node.id);\n const hasChildren = node.children.length > 0;\n\n return (\n <div\n role=\"treeitem\"\n aria-selected={node.isContextOnly ? undefined : isSelected}\n aria-expanded={hasChildren ? !isCollapsed : undefined}\n >\n <div\n style={{ paddingLeft: `${0.75 + depth}rem` }}\n className={cn(\n \"flex items-center gap-1 py-2 pr-3 text-sm transition-colors\",\n node.isContextOnly\n ? \"cursor-default text-muted-txt\"\n : \"cursor-pointer hover:bg-ghost-hover-bg\",\n isSelected && \"bg-secondary-bg font-medium\",\n )}\n >\n {hasChildren ? (\n <button\n type=\"button\"\n aria-label={isCollapsed ? `Expand ${node.name}` : `Collapse ${node.name}`}\n onClick={() => onToggleCollapse(node.id)}\n className=\"shrink-0 text-muted-txt hover:text-primary-txt\"\n >\n {isCollapsed ? (\n <Icon as={ChevronRight} className=\"size-3.5\" />\n ) : (\n <Icon as={ChevronDown} className=\"size-3.5\" />\n )}\n </button>\n ) : (\n <span className=\"inline-block w-3.5 shrink-0\" />\n )}\n\n {node.isContextOnly ? (\n <span className=\"flex-1 text-left\">{node.name}</span>\n ) : (\n <button type=\"button\" onClick={() => onSelect(node.id)} className=\"flex-1 text-left\">\n {node.name}\n </button>\n )}\n\n {isSelected && <Icon as={Check} className=\"ml-auto size-3.5 shrink-0 text-primary\" />}\n </div>\n {!isCollapsed && hasChildren && (\n <div role=\"group\">\n {node.children.map((child) => (\n <TreeNode\n key={child.id}\n node={child}\n depth={depth + 1}\n selectedId={selectedId}\n onSelect={onSelect}\n collapsedIds={collapsedIds}\n onToggleCollapse={onToggleCollapse}\n />\n ))}\n </div>\n )}\n </div>\n );\n}\n","/** Default UI strings. Spread-override via the Header `labels` prop if needed. */\nexport const DEFAULT_LABELS = {\n orgLabel: \"Org\",\n projectLabel: \"Project\",\n projectPlaceholder: \"Select project...\",\n searchPlaceholder: \"Search project\",\n emptyStateText: \"No projects found\",\n profileMenuLabel: \"Profile menu\",\n logoutLabel: \"Logout\",\n} as const;\n\nexport type Labels = typeof DEFAULT_LABELS;\n","import type { Fetcher, HeaderEndpoints, HeaderProps, ProjectNode } from \"./types\";\n\n// Studio-auth API. Endpoints are built from the host-provided `apiBaseUrl` (full\n// domain) so the same header works across environments/subdomains. All requests\n// send cookies (`credentials: 'include'`); the parent-domain session cookie is\n// readable cross-subdomain.\n\n/** Page size for the paginated projects endpoint. */\nexport const PROJECTS_PAGE_LIMIT = 50;\n/** Hard cap on project pages fetched — guards against a runaway loop. */\nconst PROJECTS_MAX_PAGES = 40;\n\nconst PATHS = {\n token: \"/api/v1/studio-auth/sessions/token\",\n logout: \"/api/v1/studio-auth/sessions/logout\",\n projects: (clientId: string) =>\n `/save/api/v1/client-projects/getAllProjects?limit=${PROJECTS_PAGE_LIMIT}&page=1&sort=name&sortOrder=ASC&clientId=${encodeURIComponent(clientId)}&metaData=true`,\n credits: \"/save/api/v1/users\",\n};\n\n/** Join a base URL and path without doubling slashes. */\nfunction join(baseUrl: string, path: string): string {\n return `${baseUrl.replace(/\\/$/, \"\")}${path}`;\n}\n\nexport function buildEndpoints(\n apiBaseUrl: string,\n overrides?: HeaderProps[\"endpoints\"],\n): HeaderEndpoints {\n return {\n token: overrides?.token ?? join(apiBaseUrl, PATHS.token),\n logout: overrides?.logout ?? join(apiBaseUrl, PATHS.logout),\n projects:\n overrides?.projects ?? ((clientId: string) => join(apiBaseUrl, PATHS.projects(clientId))),\n credits: overrides?.credits ?? join(apiBaseUrl, PATHS.credits),\n };\n}\n\ntype ApiEnvelope<T> = { response?: { data?: T } };\n\nexport async function fetchToken(endpoints: HeaderEndpoints, fetcher: Fetcher): Promise<string> {\n const res = await fetcher(endpoints.token, { credentials: \"include\" });\n if (!res.ok) throw new Error(`token request failed: ${res.status}`);\n const { accessToken } = (await res.json()) as { accessToken: string };\n return accessToken;\n}\n\ntype ProjectsPayload = {\n projectsTree?: ProjectNode[];\n organization?: { name?: string };\n};\n\n/**\n * Return `url` with the `page` query param set to the given page (and `limit`\n * backfilled when absent). Pagination stays owned by the header: host-provided\n * endpoint URLs don't need — and can't break — the paging params. Handles\n * absolute and relative URLs.\n */\nexport function withPageParam(url: string, page: number): string {\n const isAbsolute = /^[a-z][a-z0-9+.-]*:\\/\\//i.test(url);\n try {\n const u = new URL(url, isAbsolute ? undefined : \"http://relative.invalid\");\n u.searchParams.set(\"page\", String(page));\n if (!u.searchParams.has(\"limit\")) u.searchParams.set(\"limit\", String(PROJECTS_PAGE_LIMIT));\n return isAbsolute ? u.toString() : `${u.pathname}${u.search}${u.hash}`;\n } catch {\n return url;\n }\n}\n\n/** The `limit` query param already on a URL, else the default page size. */\nfunction readLimitParam(url: string): number {\n try {\n const limit = Number(new URL(url, \"http://relative.invalid\").searchParams.get(\"limit\"));\n return Number.isInteger(limit) && limit > 0 ? limit : PROJECTS_PAGE_LIMIT;\n } catch {\n return PROJECTS_PAGE_LIMIT;\n }\n}\n\n/** Total node count in a tree page (roots + descendants). */\nfunction countNodes(tree: ProjectNode[]): number {\n return tree.reduce((sum, node) => sum + 1 + countNodes(node.children ?? []), 0);\n}\n\n/**\n * Merge a page's tree into the accumulated tree. Nodes repeated across pages\n * (e.g. a context-only ancestor whose children span a page boundary) are\n * merged by id instead of duplicated.\n */\nfunction mergeTrees(into: ProjectNode[], page: ProjectNode[]): void {\n for (const node of page) {\n const existing = into.find((n) => n.id === node.id);\n if (existing) mergeTrees(existing.children, node.children ?? []);\n else into.push({ ...node, children: [...(node.children ?? [])] });\n }\n}\n\n/**\n * Fetch ALL pages of the paginated projects endpoint and merge them into a\n * single tree, so users with more projects than one page still see everything.\n * The response carries no pagination metadata, so the first page that comes\n * back with fewer than `limit` nodes is treated as the last one.\n */\nexport async function fetchProjects(\n endpoints: HeaderEndpoints,\n clientId: string,\n accessToken: string,\n fetcher: Fetcher,\n): Promise<{ projectsTree: ProjectNode[]; organizationName: string | undefined }> {\n const projectsTree: ProjectNode[] = [];\n let organizationName: string | undefined;\n const baseUrl = endpoints.projects(clientId);\n const pageLimit = readLimitParam(baseUrl);\n\n for (let page = 1; page <= PROJECTS_MAX_PAGES; page++) {\n const res = await fetcher(withPageParam(baseUrl, page), {\n credentials: \"include\",\n headers: { Authorization: `Bearer ${accessToken}` },\n });\n if (!res.ok) throw new Error(`projects request failed: ${res.status}`);\n const body = (await res.json()) as ApiEnvelope<ProjectsPayload>;\n const pageTree = body.response?.data?.projectsTree ?? [];\n mergeTrees(projectsTree, pageTree);\n organizationName ??= body.response?.data?.organization?.name;\n\n // A short page means there is nothing left.\n if (countNodes(pageTree) < pageLimit) break;\n }\n\n return { projectsTree, organizationName };\n}\n\nexport async function fetchCredits(\n endpoints: HeaderEndpoints,\n accessToken: string,\n fetcher: Fetcher,\n): Promise<number | undefined> {\n const res = await fetcher(endpoints.credits, {\n credentials: \"include\",\n headers: { Authorization: `Bearer ${accessToken}` },\n });\n if (!res.ok) throw new Error(`credits request failed: ${res.status}`);\n const data = (await res.json()) as { remainingCredits?: number };\n return data.remainingCredits;\n}\n\nexport async function callLogout(endpoints: HeaderEndpoints, fetcher: Fetcher): Promise<void> {\n try {\n await fetcher(endpoints.logout, { method: \"POST\", credentials: \"include\" });\n } finally {\n if (typeof window !== \"undefined\") window.location.href = \"/\";\n }\n}\n","// Persists the user's project selection across reloads (sessionStorage), tagged\n// with the client it belongs to so a stale selection from a different org is\n// discarded on re-login. Explicit selections are additionally remembered in\n// localStorage (`lastSelectedProject`) so new tabs default to the project the\n// user picked last — while each tab keeps its own per-tab selection.\n// The full (all pages, merged) projects result is also cached in sessionStorage\n// so the paginated projects API is hit once per tab session, not on every mount\n// or reload.\n\nimport type { ProjectNode } from \"./types\";\n\nconst PROJECT_KEY = \"ds-header-project\";\nconst LAST_PROJECT_KEY = \"lastSelectedProject\";\nconst PROJECTS_CACHE_KEY = \"ds-header-projects-cache\";\n\nexport interface StoredProject {\n id: string;\n name: string;\n clientId?: string;\n}\n\nexport function getStoredProject(): StoredProject | null {\n try {\n const raw = sessionStorage.getItem(PROJECT_KEY);\n return raw ? (JSON.parse(raw) as StoredProject) : null;\n } catch {\n return null;\n }\n}\n\nexport function setStoredProject(project: StoredProject): void {\n try {\n sessionStorage.setItem(PROJECT_KEY, JSON.stringify(project));\n } catch {\n // sessionStorage unavailable — degrade silently\n }\n}\n\nexport function clearStoredProject(): void {\n try {\n sessionStorage.removeItem(PROJECT_KEY);\n } catch {\n // noop\n }\n}\n\n/** The project the user last explicitly selected, in any tab (localStorage). */\nexport function getLastSelectedProject(): StoredProject | null {\n try {\n const raw = localStorage.getItem(LAST_PROJECT_KEY);\n return raw ? (JSON.parse(raw) as StoredProject) : null;\n } catch {\n return null;\n }\n}\n\nexport function setLastSelectedProject(project: StoredProject): void {\n try {\n localStorage.setItem(LAST_PROJECT_KEY, JSON.stringify(project));\n } catch {\n // localStorage unavailable — degrade silently\n }\n}\n\nexport interface CachedProjects {\n projectsTree: ProjectNode[];\n organizationName: string | undefined;\n}\n\n// Keyed by client id + user id (both from the session JWT) so switching user\n// or organisation misses the cache and refetches instead of serving another\n// identity's projects.\nfunction projectsCacheKey(clientId: string, userId: string): string {\n return `${PROJECTS_CACHE_KEY}:${clientId}:${userId}`;\n}\n\n/** The session-cached projects result for this client + user, or null on miss. */\nexport function getCachedProjects(clientId: string, userId: string): CachedProjects | null {\n try {\n const raw = sessionStorage.getItem(projectsCacheKey(clientId, userId));\n if (!raw) return null;\n const cached = JSON.parse(raw) as Partial<CachedProjects>;\n if (!Array.isArray(cached.projectsTree)) return null;\n return { projectsTree: cached.projectsTree, organizationName: cached.organizationName };\n } catch {\n return null;\n }\n}\n\nexport function setCachedProjects(clientId: string, userId: string, data: CachedProjects): void {\n try {\n sessionStorage.setItem(projectsCacheKey(clientId, userId), JSON.stringify(data));\n } catch {\n // sessionStorage unavailable/full — degrade silently\n }\n}\n\n/** Drop every cached projects entry (all clients/users) — used on logout. */\nexport function clearCachedProjects(): void {\n try {\n for (let i = sessionStorage.length - 1; i >= 0; i--) {\n const key = sessionStorage.key(i);\n if (key?.startsWith(PROJECTS_CACHE_KEY)) sessionStorage.removeItem(key);\n }\n } catch {\n // noop\n }\n}\n","\"use client\";\n\nimport * as React from \"react\";\n\nimport {\n clearStoredProject,\n getStoredProject,\n setLastSelectedProject,\n setStoredProject,\n} from \"./storage\";\n\n// Module-level store for the current project/org selection. Module scope (not\n// React context) so a host app can read and change the selection from anywhere —\n// including components rendered outside the <Header> subtree. The Header is one\n// writer/reader; `useHeaderProject()` gives apps the same access.\n\nexport interface HeaderSelection {\n selectedProjectId: string;\n selectedProjectName: string;\n organizationName: string | undefined;\n /** Remaining credits for the logged-in user (read-only here; set by the Header). */\n credits: number | undefined;\n /** Client/org the current selection + org belong to (for cross-org invalidation). */\n clientId: string | undefined;\n}\n\nfunction initialState(): HeaderSelection {\n const stored = typeof window !== \"undefined\" ? getStoredProject() : null;\n return {\n selectedProjectId: stored?.id ?? \"\",\n selectedProjectName: stored?.name ?? \"\",\n organizationName: undefined,\n credits: undefined,\n clientId: stored?.clientId,\n };\n}\n\nlet state: HeaderSelection = initialState();\n// Stable reference for SSR / first server render.\nconst SERVER_SNAPSHOT: HeaderSelection = Object.freeze({\n selectedProjectId: \"\",\n selectedProjectName: \"\",\n organizationName: undefined,\n credits: undefined,\n clientId: undefined,\n});\n\nconst listeners = new Set<() => void>();\nfunction emit() {\n for (const listener of listeners) listener();\n}\n\nexport const headerStore = {\n subscribe(listener: () => void) {\n listeners.add(listener);\n return () => listeners.delete(listener);\n },\n getSnapshot(): HeaderSelection {\n return state;\n },\n getServerSnapshot(): HeaderSelection {\n return SERVER_SNAPSHOT;\n },\n\n /**\n * Set the selected project. `name` is best-effort; the Header backfills it from\n * the tree. Explicit selections are also remembered in localStorage as the\n * cross-tab default; pass `remember: false` for internal backfill/auto-select\n * writes so they don't overwrite the user's last explicit choice.\n */\n setProject(id: string, name = \"\", clientId?: string, { remember = true } = {}) {\n if (id) {\n const project = { id, name, clientId: clientId ?? state.clientId };\n setStoredProject(project);\n if (remember) setLastSelectedProject(project);\n } else clearStoredProject();\n state = {\n ...state,\n selectedProjectId: id,\n selectedProjectName: name,\n clientId: clientId ?? state.clientId,\n };\n emit();\n },\n\n clearProject() {\n clearStoredProject();\n state = { ...state, selectedProjectId: \"\", selectedProjectName: \"\" };\n emit();\n },\n\n setOrganization(name: string | undefined, clientId?: string) {\n state = { ...state, organizationName: name, clientId: clientId ?? state.clientId };\n emit();\n },\n\n setCredits(credits: number | undefined) {\n if (state.credits === credits) return;\n state = { ...state, credits };\n emit();\n },\n\n /** When the active client changes, drop a selection/org from the previous one. */\n reconcileClient(clientId: string) {\n if (state.clientId === clientId) return;\n if (state.clientId && state.clientId !== clientId) {\n clearStoredProject();\n state = {\n selectedProjectId: \"\",\n selectedProjectName: \"\",\n organizationName: undefined,\n credits: state.credits, // user-level — survives org switches\n clientId,\n };\n } else {\n state = { ...state, clientId };\n }\n emit();\n },\n};\n\n/** Internal: subscribe a component to the selection store. */\nexport function useHeaderStore(): HeaderSelection {\n return React.useSyncExternalStore(\n headerStore.subscribe,\n headerStore.getSnapshot,\n headerStore.getServerSnapshot,\n );\n}\n\nexport interface UseHeaderProjectResult {\n selectedProjectId: string;\n selectedProjectName: string | undefined;\n organizationName: string | undefined;\n /** Set the active project from outside the Header (by id). */\n setProject: (id: string) => void;\n /** Clear this tab's active project (the header re-defaults on next projects load). */\n clearProject: () => void;\n}\n\n/**\n * Read the current project/org and change the project from anywhere in the app —\n * no need to be inside the <Header>. Reflects user selections made in the header\n * and updates the header when changed here.\n */\nexport function useHeaderProject(): UseHeaderProjectResult {\n const snapshot = useHeaderStore();\n return {\n selectedProjectId: snapshot.selectedProjectId,\n selectedProjectName: snapshot.selectedProjectName || undefined,\n organizationName: snapshot.organizationName,\n setProject: React.useCallback((id: string) => headerStore.setProject(id), []),\n clearProject: React.useCallback(() => headerStore.clearProject(), []),\n };\n}\n\n/** Read the logged-in user's remaining credits (read-only; the Header owns it). */\nexport function useHeaderCredits(): number | undefined {\n return useHeaderStore().credits;\n}\n","// Client-side session detection. The auth system writes a JS-readable cookie\n// `{environmentId}-sessionId` (a JWT) on the shared parent domain. We decode it\n// and check its expiry to know whether the user is logged in — no network call.\n\ninterface JwtPayload {\n exp?: number;\n [key: string]: unknown;\n}\n\n/** Read the raw session JWT from the `{environmentId}-sessionId` cookie. */\nexport function getSessionToken(environmentId: string): string | null {\n if (typeof document === \"undefined\") return null;\n const name = `${environmentId}-sessionId`;\n for (const part of document.cookie.split(\";\")) {\n const [key, ...rest] = part.trim().split(\"=\");\n if (key === name) return decodeURIComponent(rest.join(\"=\"));\n }\n return null;\n}\n\n/** Decode a JWT payload without verifying the signature (display/expiry only). */\nexport function decodeJwt(token: string): JwtPayload | null {\n try {\n const payload = token.split(\".\")[1];\n if (!payload) return null;\n const base64 = payload.replace(/-/g, \"+\").replace(/_/g, \"/\");\n const json = atob(base64);\n return JSON.parse(json) as JwtPayload;\n } catch {\n return null;\n }\n}\n\n/** User/session claims carried in the session JWT (the subset the header uses). */\nexport interface SessionClaims {\n email?: string;\n name?: string;\n userId?: string;\n /** Active organisation id (`client_id` claim). */\n clientId?: string;\n exp?: number;\n}\n\n/**\n * Decode the user claims from the session cookie's JWT — no network call.\n * Returns null when the cookie is absent or undecodable.\n */\nexport function getSessionClaims(environmentId: string): SessionClaims | null {\n const token = getSessionToken(environmentId);\n if (!token) return null;\n const payload = decodeJwt(token);\n if (!payload) return null;\n const str = (v: unknown) => (typeof v === \"string\" ? v : undefined);\n return {\n email: str(payload.email),\n name: str(payload.name),\n userId: str(payload.user_id),\n clientId: str(payload.client_id),\n exp: typeof payload.exp === \"number\" ? payload.exp : undefined,\n };\n}\n\n/** True when a valid, unexpired session cookie exists for the environment. */\nexport function isSessionValid(environmentId: string): boolean {\n const token = getSessionToken(environmentId);\n if (!token) return false;\n const payload = decodeJwt(token);\n if (!payload) return false;\n // No exp claim → treat as a non-expiring session.\n if (typeof payload.exp !== \"number\") return true;\n return payload.exp * 1000 > Date.now();\n}\n","\"use client\";\n\nimport { useQuery } from \"@tanstack/react-query\";\nimport * as React from \"react\";\n\nimport { buildEndpoints, callLogout, fetchCredits, fetchProjects, fetchToken } from \"./api\";\nimport { headerStore, useHeaderStore } from \"./header-store\";\nimport { findProjectName, firstSelectableProject, nodeExistsInTree } from \"./project-tree\";\nimport { getSessionClaims, isSessionValid } from \"./session\";\nimport {\n clearCachedProjects,\n getCachedProjects,\n getLastSelectedProject,\n setCachedProjects,\n} from \"./storage\";\nimport type { HeaderProps, ProjectNode } from \"./types\";\n\n/** Window event other modules can dispatch to show/hide the project dropdown. */\nexport const TOGGLE_PROJECT_DROPDOWN_EVENT = \"toggle-project-dropdown\";\nexport interface ToggleProjectDropdownDetail {\n show: boolean;\n}\n\nconst DEFAULT_STALE_TIME = 5 * 60_000;\nconst DEFAULT_GC_TIME = 10 * 60_000;\n\nexport interface GlobalHeaderState {\n /** Whether a valid session cookie exists — when false, hide all user content. */\n isAuthenticated: boolean;\n userEmail: string | undefined;\n organizationName: string | undefined;\n projectsTree: ProjectNode[];\n selectedProjectId: string;\n selectedProjectName: string | undefined;\n isProjectsLoading: boolean;\n isOrgLoading: boolean;\n /** Remaining credits for the user (undefined until loaded / when disabled). */\n credits: number | undefined;\n /** Where the credits pill links to (studio-auth `/user/activity`). */\n creditsHref: string;\n projectDropdownVisible: boolean;\n selectProject: (id: string) => void;\n logout: () => void;\n}\n\ntype UseGlobalHeaderArgs = Pick<\n HeaderProps,\n | \"apiBaseUrl\"\n | \"environmentId\"\n | \"clientId\"\n | \"defaultProjectId\"\n | \"_dangerouslyInjectAccessToken\"\n | \"showProjectDropdown\"\n | \"showProfile\"\n | \"showOrg\"\n | \"showCredits\"\n | \"endpoints\"\n | \"fetcher\"\n | \"staleTime\"\n | \"gcTime\"\n | \"onProjectChange\"\n>;\n\nexport function useGlobalHeader({\n apiBaseUrl,\n environmentId,\n clientId,\n defaultProjectId,\n _dangerouslyInjectAccessToken: injectedToken,\n showProjectDropdown = false,\n showProfile = false,\n showOrg = false,\n showCredits = false,\n endpoints: endpointOverrides,\n fetcher: fetcherProp,\n staleTime = DEFAULT_STALE_TIME,\n gcTime = DEFAULT_GC_TIME,\n onProjectChange,\n}: UseGlobalHeaderArgs): GlobalHeaderState {\n const fetcher = React.useMemo(\n () => fetcherProp ?? ((input: RequestInfo | URL, init?: RequestInit) => fetch(input, init)),\n [fetcherProp],\n );\n const endpoints = React.useMemo(\n () => buildEndpoints(apiBaseUrl, endpointOverrides),\n [apiBaseUrl, endpointOverrides],\n );\n\n // Read the session cookie each render (cheap); gates every network call.\n // User identity (email, client id) comes from the JWT claims — no /me call.\n const isAuthenticated = isSessionValid(environmentId);\n const claims = getSessionClaims(environmentId);\n\n // token → projects, enabled only when the previous resolved.\n const tokenQuery = useQuery({\n queryKey: [\"ds-header\", \"token\", endpoints.token],\n queryFn: () => fetchToken(endpoints, fetcher),\n enabled: isAuthenticated && !injectedToken,\n staleTime,\n gcTime,\n });\n const token = injectedToken ?? tokenQuery.data;\n\n const effectiveClientId = clientId ?? claims?.clientId;\n const wantsProjects = showProjectDropdown || showOrg;\n // All pages of the projects API, merged. Served from the sessionStorage\n // cache when present so the API is hit once per tab session — not on every\n // mount, reload, or react-query refetch. The cache is keyed by client id +\n // user id (from the JWT), so a different user or org refetches.\n const userId = claims?.userId ?? \"\";\n const projectsQuery = useQuery({\n queryKey: [\"ds-header\", \"projects\", effectiveClientId, userId, token],\n queryFn: async () => {\n const id = effectiveClientId as string;\n const cached = getCachedProjects(id, userId);\n if (cached) return cached;\n const fresh = await fetchProjects(endpoints, id, token as string, fetcher);\n setCachedProjects(id, userId, fresh);\n return fresh;\n },\n enabled: isAuthenticated && !!token && !!effectiveClientId && wantsProjects,\n staleTime,\n gcTime,\n });\n\n // Credits — only needs the token. Always refetched on mount (staleTime 0) so a\n // page refresh shows the current balance.\n const creditsQuery = useQuery({\n queryKey: [\"ds-header\", \"credits\", endpoints.credits, token],\n queryFn: () => fetchCredits(endpoints, token as string, fetcher),\n enabled: isAuthenticated && !!token && showCredits,\n staleTime: 0,\n gcTime,\n });\n\n const projectsTree = projectsQuery.data?.projectsTree ?? [];\n const userEmail = showProfile ? claims?.email : undefined;\n const creditsHref = React.useMemo(() => {\n try {\n return new URL(\"/user/activity\", apiBaseUrl).toString();\n } catch {\n return \"/user/activity\";\n }\n }, [apiBaseUrl]);\n\n // Selection + org live in a module store so host apps can read/change them\n // from outside the header (see useHeaderProject).\n const selection = useHeaderStore();\n\n // Ref so the auto-select effect sees the latest callback without re-running.\n const onProjectChangeRef = React.useRef(onProjectChange);\n React.useEffect(() => {\n onProjectChangeRef.current = onProjectChange;\n });\n\n // Once the client id resolves, drop a selection/org from a different client.\n React.useEffect(() => {\n if (effectiveClientId) headerStore.reconcileClient(effectiveClientId);\n }, [effectiveClientId]);\n\n // Once projects load: publish the org name and validate/backfill the selection.\n // A tab with no valid selection defaults to the user's last explicitly selected\n // project (localStorage `lastSelectedProject`) when it still exists in the\n // tree, else the host's `defaultProjectId`, else the first selectable\n // project — no selection prompt.\n React.useEffect(() => {\n if (!projectsQuery.data) return;\n const tree = projectsQuery.data.projectsTree;\n const id = headerStore.getSnapshot().selectedProjectId;\n if (id && nodeExistsInTree(tree, id)) {\n const name = findProjectName(tree, id);\n if (name && name !== headerStore.getSnapshot().selectedProjectName) {\n headerStore.setProject(id, name, effectiveClientId, { remember: false });\n }\n } else {\n const last = getLastSelectedProject();\n const fallback =\n last && nodeExistsInTree(tree, last.id)\n ? { id: last.id, name: findProjectName(tree, last.id) ?? last.name }\n : defaultProjectId && nodeExistsInTree(tree, defaultProjectId)\n ? { id: defaultProjectId, name: findProjectName(tree, defaultProjectId) ?? \"\" }\n : firstSelectableProject(tree);\n if (fallback) {\n headerStore.setProject(fallback.id, fallback.name, effectiveClientId, {\n remember: false,\n });\n onProjectChangeRef.current?.(fallback.id);\n } else if (id) {\n headerStore.clearProject();\n }\n }\n headerStore.setOrganization(projectsQuery.data.organizationName, effectiveClientId);\n }, [projectsQuery.data, effectiveClientId, defaultProjectId]);\n\n // Publish credits to the store so host apps can read them via useHeaderCredits.\n React.useEffect(() => {\n if (creditsQuery.data !== undefined) headerStore.setCredits(creditsQuery.data);\n }, [creditsQuery.data]);\n\n const selectProject = (id: string) => {\n const name = findProjectName(projectsTree, id) ?? \"\";\n headerStore.setProject(id, name, effectiveClientId);\n onProjectChange?.(id);\n };\n\n const logout = () => {\n headerStore.clearProject();\n clearCachedProjects();\n void callLogout(endpoints, fetcher);\n };\n\n // Visibility: declarative from the prop, overridable at runtime via the event.\n const [projectDropdownVisible, setProjectDropdownVisible] = React.useState(showProjectDropdown);\n React.useEffect(() => setProjectDropdownVisible(showProjectDropdown), [showProjectDropdown]);\n React.useEffect(() => {\n const handler = (e: Event) => {\n setProjectDropdownVisible((e as CustomEvent<ToggleProjectDropdownDetail>).detail.show);\n };\n window.addEventListener(TOGGLE_PROJECT_DROPDOWN_EVENT, handler);\n return () => window.removeEventListener(TOGGLE_PROJECT_DROPDOWN_EVENT, handler);\n }, []);\n\n const isProjectsLoading = projectsQuery.isFetching && !projectsQuery.data;\n\n return {\n isAuthenticated,\n userEmail,\n organizationName: selection.organizationName,\n projectsTree,\n selectedProjectId: selection.selectedProjectId,\n selectedProjectName: selection.selectedProjectName || undefined,\n isProjectsLoading,\n isOrgLoading: showOrg && isProjectsLoading,\n credits: selection.credits,\n creditsHref,\n projectDropdownVisible,\n selectProject,\n logout,\n };\n}\n","\"use client\";\n\nimport { QueryClient, QueryClientProvider } from \"@tanstack/react-query\";\nimport { LogOut, MessageSquareShare, Moon, Sun } from \"lucide-react\";\nimport type * as React from \"react\";\n\nimport { Avatar, AvatarFallback } from \"@/primitives/Avatar\";\nimport { Button } from \"@/primitives/Button\";\nimport { Credits } from \"@/primitives/Credits\";\nimport {\n DropdownMenu,\n DropdownMenuContent,\n DropdownMenuItem,\n DropdownMenuLabel,\n DropdownMenuSeparator,\n DropdownMenuTrigger,\n} from \"@/primitives/DropdownMenu\";\nimport { Logo } from \"@/primitives/Logo\";\nimport { Skeleton } from \"@/primitives/Skeleton\";\nimport { type ThemeProduct, useTheme } from \"@/primitives/ThemeProvider\";\nimport { cn } from \"@/utils\";\nimport { ProjectPicker } from \"./ProjectPicker\";\nimport { DEFAULT_LABELS } from \"./labels\";\nimport type { HeaderProps } from \"./types\";\nimport { useGlobalHeader } from \"./use-global-header\";\n\n// Fallback logo destinations when the host doesn't pass `logoHref`.\nconst LOGO_HREF: Record<ThemeProduct, string> = {\n psai: \"https://sapientaiproducts.com/\",\n slingshot: \"https://sapientaiproducts.com/slingshot\",\n sustain: \"https://www.publicissapient.com/\",\n bodhi: \"https://sapientaiproducts.com/bodhi\",\n};\n\nconst PILL =\n \"flex min-h-8 items-center gap-1 rounded-12 border border-primary-border bg-input-bg px-3 py-1 text-xs leading-4\";\n\n// ── Presentational parts (props-driven; Storybook/VR-able) ──────────────────\n\n/** The header bar shell — a sticky glass strip. */\nfunction HeaderBar({ className, ...props }: React.ComponentProps<\"header\">) {\n return (\n <header\n data-slot=\"header\"\n className={cn(\n \"sticky top-1 z-10 mt-1 flex h-15 items-center gap-5 rounded-16 px-3 py-2\",\n \"bg-glass-60-bg backdrop-blur-glass\",\n className,\n )}\n {...props}\n />\n );\n}\n\n/** Product logo linking to its home, with a Suspense-safe fallback. */\nfunction HeaderLogo({ brand, href }: { brand: ThemeProduct; href?: string }) {\n return (\n <a href={href ?? LOGO_HREF[brand]} aria-label=\"Go to product home\" data-slot=\"header-logo\">\n <Logo brand={brand} className=\"h-8 w-auto\" />\n </a>\n );\n}\n\n/** Read-only organisation pill. */\nfunction OrgPill({ name, loading }: { name?: string; loading?: boolean }) {\n if (loading && !name) {\n return (\n <div className={cn(PILL, \"ml-3\")} data-slot=\"header-org\">\n <span className=\"shrink-0 text-muted-txt\">{DEFAULT_LABELS.orgLabel}:</span>\n <Skeleton className=\"h-4 w-24\" />\n </div>\n );\n }\n if (!name) return null;\n return (\n <div className={cn(PILL, \"ml-3 select-none\")} title={name} data-slot=\"header-org\">\n <span className=\"shrink-0 text-muted-txt\">{DEFAULT_LABELS.orgLabel}:</span>\n <span className=\"max-w-36 truncate text-primary-txt\">{name}</span>\n </div>\n );\n}\n\n/** Light/dark toggle — defers to ThemeProvider. */\nfunction ThemeToggle() {\n const { theme, toggleTheme } = useTheme();\n return (\n <Button variant=\"ghost\" size=\"icon\" onClick={toggleTheme} aria-label=\"Toggle theme\">\n {theme === \"light\" ? <Moon className=\"size-4\" /> : <Sun className=\"size-4\" />}\n </Button>\n );\n}\n\n/** Profile menu — avatar trigger with email + logout. */\nfunction ProfileMenu({ email, onLogout }: { email?: string; onLogout: () => void }) {\n const initial = email?.trim().charAt(0).toUpperCase() || \"?\";\n return (\n <DropdownMenu>\n <DropdownMenuTrigger asChild>\n <Button variant=\"ghost\" size=\"icon\" aria-label={DEFAULT_LABELS.profileMenuLabel}>\n <Avatar className=\"size-7\">\n <AvatarFallback>{initial}</AvatarFallback>\n </Avatar>\n </Button>\n </DropdownMenuTrigger>\n <DropdownMenuContent align=\"end\" sideOffset={8} className=\"min-w-44\">\n {email && (\n <>\n <DropdownMenuLabel className=\"truncate font-normal text-muted-txt\">\n {email}\n </DropdownMenuLabel>\n <DropdownMenuSeparator />\n </>\n )}\n <DropdownMenuItem onSelect={onLogout} variant=\"destructive\">\n <LogOut />\n {DEFAULT_LABELS.logoutLabel}\n </DropdownMenuItem>\n </DropdownMenuContent>\n </DropdownMenu>\n );\n}\n\nexport { HeaderBar, HeaderLogo, OrgPill, ThemeToggle, ProfileMenu };\n\n// ── Wired Header ─────────────────────────────────────────────────────────────\n\n// Internal singleton client so the header is drop-in (no app setup) while still\n// sharing its cache across mounts/navigation.\nlet sharedClient: QueryClient | undefined;\nfunction getQueryClient(): QueryClient {\n sharedClient ??= new QueryClient({\n defaultOptions: { queries: { retry: 1, refetchOnWindowFocus: false } },\n });\n return sharedClient;\n}\n\n/** Drop-in global header. Must be rendered inside a <ThemeProvider>. */\nexport function Header(props: HeaderProps) {\n return (\n <QueryClientProvider client={getQueryClient()}>\n <HeaderInner {...props} />\n </QueryClientProvider>\n );\n}\n\nfunction HeaderInner({\n logoType,\n logoHref,\n showOrg = false,\n showProjectDropdown = false,\n showProfile = false,\n showThemeSwitcher = false,\n showCredits = false,\n pageTitle,\n feedbackUrl,\n logoAddon,\n actionsStart,\n actionsEnd,\n className,\n ...rest\n}: HeaderProps) {\n const { product } = useTheme();\n const brand = logoType ?? product;\n const state = useGlobalHeader({\n showOrg,\n showProjectDropdown,\n showProfile,\n showCredits,\n ...rest,\n });\n\n // Logged-out users see no user content (project/org/profile/credits).\n const showProjectUi = showProjectDropdown && state.isAuthenticated;\n const showOrgUi = showOrg && state.isAuthenticated;\n const showProfileUi = showProfile && state.isAuthenticated;\n const showCreditsUi = showCredits && state.isAuthenticated && state.credits !== undefined;\n const showActions =\n showThemeSwitcher ||\n showProfileUi ||\n showCreditsUi ||\n !!feedbackUrl ||\n !!actionsStart ||\n !!actionsEnd;\n\n return (\n <HeaderBar className={className}>\n <HeaderLogo brand={brand} href={logoHref} />\n {/* Page title — 20px (gap-5) from the logo. */}\n {pageTitle && (\n <span data-slot=\"header-title\" className=\"ml-5 font-semibold text-primary-txt text-sm\">\n {pageTitle}\n </span>\n )}\n {logoAddon}\n\n {showOrgUi && <OrgPill name={state.organizationName} loading={state.isOrgLoading} />}\n\n {showProjectUi && state.projectDropdownVisible && (\n <div className=\"ml-2\">\n <ProjectPicker\n projectsTree={state.projectsTree}\n selectedProjectId={state.selectedProjectId}\n selectedProjectName={state.selectedProjectName}\n onSelect={state.selectProject}\n projectLabel={DEFAULT_LABELS.projectLabel}\n projectPlaceholder={DEFAULT_LABELS.projectPlaceholder}\n searchPlaceholder={DEFAULT_LABELS.searchPlaceholder}\n emptyStateText={DEFAULT_LABELS.emptyStateText}\n isLoading={state.isProjectsLoading}\n />\n </div>\n )}\n\n {showActions && (\n <div className=\"ml-auto flex items-center gap-2\">\n {actionsStart}\n {feedbackUrl && (\n <Button variant=\"ghost\" size=\"icon\" asChild>\n <a\n href={feedbackUrl}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n aria-label=\"Share feedback\"\n >\n <MessageSquareShare className=\"size-4\" />\n </a>\n </Button>\n )}\n {showThemeSwitcher && <ThemeToggle />}\n {showCreditsUi && state.credits !== undefined && (\n <a\n href={state.creditsHref}\n aria-label=\"View credit activity\"\n className=\"rounded-full outline-none focus-visible:ring-3 focus-visible:ring-focus\"\n >\n <Credits value={state.credits} />\n </a>\n )}\n {showProfileUi && <ProfileMenu email={state.userEmail} onLogout={state.logout} />}\n {actionsEnd}\n </div>\n )}\n </HeaderBar>\n );\n}\n"],"mappings":"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"}
package/dist/Header.js CHANGED
@@ -210,7 +210,7 @@ const PROJECTS_MAX_PAGES = 40;
210
210
  const PATHS = {
211
211
  token: "/api/v1/studio-auth/sessions/token",
212
212
  logout: "/api/v1/studio-auth/sessions/logout",
213
- projects: (clientId) => `/api/v1/client-projects/getAllProjects?limit=50&page=1&sort=name&sortOrder=ASC&clientId=${encodeURIComponent(clientId)}&metaData=true`,
213
+ projects: (clientId) => `/save/api/v1/client-projects/getAllProjects?limit=50&page=1&sort=name&sortOrder=ASC&clientId=${encodeURIComponent(clientId)}&metaData=true`,
214
214
  credits: "/save/api/v1/users"
215
215
  };
216
216
  /** Join a base URL and path without doubling slashes. */