@heyramzi/ui 3.4.0 → 3.6.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 (305) hide show
  1. package/COMPONENTS.md +2 -0
  2. package/dist/ai/chat-window/icons.js +43 -0
  3. package/dist/ai/chat-window/index.js +5 -0
  4. package/dist/ai/chat-window/labels.js +16 -0
  5. package/dist/ai/chat-window/reveal.svelte.js +106 -0
  6. package/dist/ai/chat-window/types.js +4 -0
  7. package/dist/components/copy/clipboard.js +3 -3
  8. package/dist/components/flag/codes.js +13 -0
  9. package/dist/components/flag/index.js +2 -0
  10. package/dist/slides/export/pdf.js +7 -0
  11. package/dist/vite/flags.js +46 -0
  12. package/package.json +7 -2
  13. package/src/ai/chat-window/ChatGlyph.svelte +38 -0
  14. package/src/ai/chat-window/ChatGlyph.svelte.d.ts +9 -0
  15. package/src/ai/chat-window/ChatGptWindow.svelte +636 -0
  16. package/src/ai/chat-window/ChatGptWindow.svelte.d.ts +25 -0
  17. package/src/ai/chat-window/ClaudeWindow.svelte +668 -0
  18. package/src/ai/chat-window/ClaudeWindow.svelte.d.ts +25 -0
  19. package/src/ai/chat-window/chat-window.test.ts +80 -0
  20. package/src/ai/chat-window/icons/LICENSE +24 -0
  21. package/src/ai/chat-window/icons/chatgpt-chevron.svg +2 -0
  22. package/src/ai/chat-window/icons/chatgpt-copy.svg +2 -0
  23. package/src/ai/chat-window/icons/chatgpt-mic.svg +2 -0
  24. package/src/ai/chat-window/icons/chatgpt-more.svg +2 -0
  25. package/src/ai/chat-window/icons/chatgpt-plus.svg +2 -0
  26. package/src/ai/chat-window/icons/chatgpt-regenerate.svg +2 -0
  27. package/src/ai/chat-window/icons/chatgpt-share.svg +2 -0
  28. package/src/ai/chat-window/icons/chatgpt-sidebar.svg +1 -0
  29. package/src/ai/chat-window/icons/chatgpt-thumb.svg +2 -0
  30. package/src/ai/chat-window/icons/chatgpt-voice.svg +2 -0
  31. package/src/ai/chat-window/icons/claude-chevron.svg +1 -0
  32. package/src/ai/chat-window/icons/claude-copy.svg +1 -0
  33. package/src/ai/chat-window/icons/claude-plus.svg +1 -0
  34. package/src/ai/chat-window/icons/claude-retry.svg +1 -0
  35. package/src/ai/chat-window/icons/claude-send.svg +1 -0
  36. package/src/ai/chat-window/icons/claude-sidebar.svg +1 -0
  37. package/src/ai/chat-window/icons/claude-sliders.svg +1 -0
  38. package/src/ai/chat-window/icons/claude-spark.svg +1 -0
  39. package/src/ai/chat-window/icons/claude-thumb.svg +1 -0
  40. package/src/ai/chat-window/icons.ts +46 -0
  41. package/src/ai/chat-window/index.ts +26 -0
  42. package/src/ai/chat-window/labels.ts +39 -0
  43. package/src/ai/chat-window/reveal.svelte.ts +106 -0
  44. package/src/ai/chat-window/types.ts +42 -0
  45. package/src/components/copy/clipboard.test.ts +17 -1
  46. package/src/components/copy/clipboard.ts +3 -3
  47. package/src/components/flag/codes.test.ts +30 -0
  48. package/src/components/flag/codes.ts +25 -0
  49. package/src/components/flag/flag.svelte +51 -0
  50. package/src/components/flag/flag.svelte.d.ts +12 -0
  51. package/src/components/flag/flags/AD.svg +1 -0
  52. package/src/components/flag/flags/AE.svg +1 -0
  53. package/src/components/flag/flags/AF.svg +1 -0
  54. package/src/components/flag/flags/AG.svg +1 -0
  55. package/src/components/flag/flags/AI.svg +1 -0
  56. package/src/components/flag/flags/AL.svg +1 -0
  57. package/src/components/flag/flags/AM.svg +1 -0
  58. package/src/components/flag/flags/AO.svg +1 -0
  59. package/src/components/flag/flags/AQ.svg +1 -0
  60. package/src/components/flag/flags/AR.svg +1 -0
  61. package/src/components/flag/flags/AS.svg +1 -0
  62. package/src/components/flag/flags/AT.svg +1 -0
  63. package/src/components/flag/flags/AU.svg +1 -0
  64. package/src/components/flag/flags/AW.svg +1 -0
  65. package/src/components/flag/flags/AX.svg +1 -0
  66. package/src/components/flag/flags/AZ.svg +1 -0
  67. package/src/components/flag/flags/BA.svg +1 -0
  68. package/src/components/flag/flags/BB.svg +1 -0
  69. package/src/components/flag/flags/BD.svg +1 -0
  70. package/src/components/flag/flags/BE.svg +1 -0
  71. package/src/components/flag/flags/BF.svg +1 -0
  72. package/src/components/flag/flags/BG.svg +1 -0
  73. package/src/components/flag/flags/BH.svg +1 -0
  74. package/src/components/flag/flags/BI.svg +1 -0
  75. package/src/components/flag/flags/BJ.svg +1 -0
  76. package/src/components/flag/flags/BL.svg +1 -0
  77. package/src/components/flag/flags/BM.svg +1 -0
  78. package/src/components/flag/flags/BN.svg +1 -0
  79. package/src/components/flag/flags/BO.svg +1 -0
  80. package/src/components/flag/flags/BQ.svg +1 -0
  81. package/src/components/flag/flags/BR.svg +1 -0
  82. package/src/components/flag/flags/BS.svg +1 -0
  83. package/src/components/flag/flags/BT.svg +1 -0
  84. package/src/components/flag/flags/BV.svg +1 -0
  85. package/src/components/flag/flags/BW.svg +1 -0
  86. package/src/components/flag/flags/BY.svg +1 -0
  87. package/src/components/flag/flags/BZ.svg +1 -0
  88. package/src/components/flag/flags/CA.svg +1 -0
  89. package/src/components/flag/flags/CC.svg +1 -0
  90. package/src/components/flag/flags/CD.svg +1 -0
  91. package/src/components/flag/flags/CF.svg +1 -0
  92. package/src/components/flag/flags/CG.svg +1 -0
  93. package/src/components/flag/flags/CH.svg +1 -0
  94. package/src/components/flag/flags/CI.svg +1 -0
  95. package/src/components/flag/flags/CK.svg +1 -0
  96. package/src/components/flag/flags/CL.svg +1 -0
  97. package/src/components/flag/flags/CM.svg +1 -0
  98. package/src/components/flag/flags/CN.svg +1 -0
  99. package/src/components/flag/flags/CO.svg +1 -0
  100. package/src/components/flag/flags/CR.svg +1 -0
  101. package/src/components/flag/flags/CU.svg +1 -0
  102. package/src/components/flag/flags/CV.svg +1 -0
  103. package/src/components/flag/flags/CW.svg +1 -0
  104. package/src/components/flag/flags/CX.svg +1 -0
  105. package/src/components/flag/flags/CY.svg +1 -0
  106. package/src/components/flag/flags/CZ.svg +1 -0
  107. package/src/components/flag/flags/DE.svg +1 -0
  108. package/src/components/flag/flags/DJ.svg +1 -0
  109. package/src/components/flag/flags/DK.svg +1 -0
  110. package/src/components/flag/flags/DM.svg +1 -0
  111. package/src/components/flag/flags/DO.svg +1 -0
  112. package/src/components/flag/flags/DZ.svg +1 -0
  113. package/src/components/flag/flags/EC.svg +1 -0
  114. package/src/components/flag/flags/EE.svg +1 -0
  115. package/src/components/flag/flags/EG.svg +1 -0
  116. package/src/components/flag/flags/EH.svg +1 -0
  117. package/src/components/flag/flags/ER.svg +1 -0
  118. package/src/components/flag/flags/ES.svg +1 -0
  119. package/src/components/flag/flags/ET.svg +1 -0
  120. package/src/components/flag/flags/FI.svg +1 -0
  121. package/src/components/flag/flags/FJ.svg +1 -0
  122. package/src/components/flag/flags/FK.svg +1 -0
  123. package/src/components/flag/flags/FM.svg +1 -0
  124. package/src/components/flag/flags/FO.svg +1 -0
  125. package/src/components/flag/flags/FR.svg +1 -0
  126. package/src/components/flag/flags/GA.svg +1 -0
  127. package/src/components/flag/flags/GB.svg +1 -0
  128. package/src/components/flag/flags/GD.svg +1 -0
  129. package/src/components/flag/flags/GE.svg +1 -0
  130. package/src/components/flag/flags/GF.svg +1 -0
  131. package/src/components/flag/flags/GG.svg +1 -0
  132. package/src/components/flag/flags/GH.svg +1 -0
  133. package/src/components/flag/flags/GI.svg +1 -0
  134. package/src/components/flag/flags/GL.svg +1 -0
  135. package/src/components/flag/flags/GM.svg +1 -0
  136. package/src/components/flag/flags/GN.svg +1 -0
  137. package/src/components/flag/flags/GP.svg +1 -0
  138. package/src/components/flag/flags/GQ.svg +1 -0
  139. package/src/components/flag/flags/GR.svg +1 -0
  140. package/src/components/flag/flags/GS.svg +1 -0
  141. package/src/components/flag/flags/GT.svg +1 -0
  142. package/src/components/flag/flags/GU.svg +1 -0
  143. package/src/components/flag/flags/GW.svg +1 -0
  144. package/src/components/flag/flags/GY.svg +1 -0
  145. package/src/components/flag/flags/HK.svg +1 -0
  146. package/src/components/flag/flags/HM.svg +1 -0
  147. package/src/components/flag/flags/HN.svg +1 -0
  148. package/src/components/flag/flags/HR.svg +1 -0
  149. package/src/components/flag/flags/HT.svg +1 -0
  150. package/src/components/flag/flags/HU.svg +1 -0
  151. package/src/components/flag/flags/ID.svg +1 -0
  152. package/src/components/flag/flags/IE.svg +1 -0
  153. package/src/components/flag/flags/IL.svg +1 -0
  154. package/src/components/flag/flags/IM.svg +1 -0
  155. package/src/components/flag/flags/IN.svg +1 -0
  156. package/src/components/flag/flags/IO.svg +1 -0
  157. package/src/components/flag/flags/IQ.svg +1 -0
  158. package/src/components/flag/flags/IR.svg +1 -0
  159. package/src/components/flag/flags/IS.svg +1 -0
  160. package/src/components/flag/flags/IT.svg +1 -0
  161. package/src/components/flag/flags/JE.svg +1 -0
  162. package/src/components/flag/flags/JM.svg +1 -0
  163. package/src/components/flag/flags/JO.svg +1 -0
  164. package/src/components/flag/flags/JP.svg +1 -0
  165. package/src/components/flag/flags/KE.svg +1 -0
  166. package/src/components/flag/flags/KG.svg +1 -0
  167. package/src/components/flag/flags/KH.svg +1 -0
  168. package/src/components/flag/flags/KI.svg +1 -0
  169. package/src/components/flag/flags/KM.svg +1 -0
  170. package/src/components/flag/flags/KN.svg +1 -0
  171. package/src/components/flag/flags/KP.svg +1 -0
  172. package/src/components/flag/flags/KR.svg +1 -0
  173. package/src/components/flag/flags/KW.svg +1 -0
  174. package/src/components/flag/flags/KY.svg +1 -0
  175. package/src/components/flag/flags/KZ.svg +1 -0
  176. package/src/components/flag/flags/LA.svg +1 -0
  177. package/src/components/flag/flags/LB.svg +1 -0
  178. package/src/components/flag/flags/LC.svg +1 -0
  179. package/src/components/flag/flags/LI.svg +1 -0
  180. package/src/components/flag/flags/LICENSE +22 -0
  181. package/src/components/flag/flags/LK.svg +1 -0
  182. package/src/components/flag/flags/LR.svg +1 -0
  183. package/src/components/flag/flags/LS.svg +1 -0
  184. package/src/components/flag/flags/LT.svg +1 -0
  185. package/src/components/flag/flags/LU.svg +1 -0
  186. package/src/components/flag/flags/LV.svg +1 -0
  187. package/src/components/flag/flags/LY.svg +1 -0
  188. package/src/components/flag/flags/MA.svg +1 -0
  189. package/src/components/flag/flags/MC.svg +1 -0
  190. package/src/components/flag/flags/MD.svg +1 -0
  191. package/src/components/flag/flags/ME.svg +1 -0
  192. package/src/components/flag/flags/MF.svg +1 -0
  193. package/src/components/flag/flags/MG.svg +1 -0
  194. package/src/components/flag/flags/MH.svg +1 -0
  195. package/src/components/flag/flags/MK.svg +1 -0
  196. package/src/components/flag/flags/ML.svg +1 -0
  197. package/src/components/flag/flags/MM.svg +1 -0
  198. package/src/components/flag/flags/MN.svg +1 -0
  199. package/src/components/flag/flags/MO.svg +1 -0
  200. package/src/components/flag/flags/MP.svg +1 -0
  201. package/src/components/flag/flags/MQ.svg +1 -0
  202. package/src/components/flag/flags/MR.svg +1 -0
  203. package/src/components/flag/flags/MS.svg +1 -0
  204. package/src/components/flag/flags/MT.svg +1 -0
  205. package/src/components/flag/flags/MU.svg +1 -0
  206. package/src/components/flag/flags/MV.svg +1 -0
  207. package/src/components/flag/flags/MW.svg +1 -0
  208. package/src/components/flag/flags/MX.svg +1 -0
  209. package/src/components/flag/flags/MY.svg +1 -0
  210. package/src/components/flag/flags/MZ.svg +1 -0
  211. package/src/components/flag/flags/NA.svg +1 -0
  212. package/src/components/flag/flags/NC.svg +1 -0
  213. package/src/components/flag/flags/NE.svg +1 -0
  214. package/src/components/flag/flags/NF.svg +1 -0
  215. package/src/components/flag/flags/NG.svg +1 -0
  216. package/src/components/flag/flags/NI.svg +1 -0
  217. package/src/components/flag/flags/NL.svg +1 -0
  218. package/src/components/flag/flags/NO.svg +1 -0
  219. package/src/components/flag/flags/NP.svg +1 -0
  220. package/src/components/flag/flags/NR.svg +1 -0
  221. package/src/components/flag/flags/NU.svg +1 -0
  222. package/src/components/flag/flags/NZ.svg +1 -0
  223. package/src/components/flag/flags/OM.svg +1 -0
  224. package/src/components/flag/flags/PA.svg +1 -0
  225. package/src/components/flag/flags/PE.svg +1 -0
  226. package/src/components/flag/flags/PF.svg +1 -0
  227. package/src/components/flag/flags/PG.svg +1 -0
  228. package/src/components/flag/flags/PH.svg +1 -0
  229. package/src/components/flag/flags/PK.svg +1 -0
  230. package/src/components/flag/flags/PL.svg +1 -0
  231. package/src/components/flag/flags/PM.svg +1 -0
  232. package/src/components/flag/flags/PN.svg +1 -0
  233. package/src/components/flag/flags/PR.svg +1 -0
  234. package/src/components/flag/flags/PS.svg +1 -0
  235. package/src/components/flag/flags/PT.svg +1 -0
  236. package/src/components/flag/flags/PW.svg +1 -0
  237. package/src/components/flag/flags/PY.svg +1 -0
  238. package/src/components/flag/flags/QA.svg +1 -0
  239. package/src/components/flag/flags/RE.svg +1 -0
  240. package/src/components/flag/flags/RO.svg +1 -0
  241. package/src/components/flag/flags/RS.svg +1 -0
  242. package/src/components/flag/flags/RU.svg +1 -0
  243. package/src/components/flag/flags/RW.svg +1 -0
  244. package/src/components/flag/flags/SA.svg +1 -0
  245. package/src/components/flag/flags/SB.svg +1 -0
  246. package/src/components/flag/flags/SC.svg +1 -0
  247. package/src/components/flag/flags/SD.svg +1 -0
  248. package/src/components/flag/flags/SE.svg +1 -0
  249. package/src/components/flag/flags/SG.svg +1 -0
  250. package/src/components/flag/flags/SH.svg +1 -0
  251. package/src/components/flag/flags/SI.svg +1 -0
  252. package/src/components/flag/flags/SJ.svg +1 -0
  253. package/src/components/flag/flags/SK.svg +1 -0
  254. package/src/components/flag/flags/SL.svg +1 -0
  255. package/src/components/flag/flags/SM.svg +1 -0
  256. package/src/components/flag/flags/SN.svg +1 -0
  257. package/src/components/flag/flags/SO.svg +1 -0
  258. package/src/components/flag/flags/SR.svg +1 -0
  259. package/src/components/flag/flags/SS.svg +1 -0
  260. package/src/components/flag/flags/ST.svg +1 -0
  261. package/src/components/flag/flags/SV.svg +1 -0
  262. package/src/components/flag/flags/SX.svg +1 -0
  263. package/src/components/flag/flags/SY.svg +1 -0
  264. package/src/components/flag/flags/SZ.svg +1 -0
  265. package/src/components/flag/flags/TC.svg +1 -0
  266. package/src/components/flag/flags/TD.svg +1 -0
  267. package/src/components/flag/flags/TF.svg +1 -0
  268. package/src/components/flag/flags/TG.svg +1 -0
  269. package/src/components/flag/flags/TH.svg +1 -0
  270. package/src/components/flag/flags/TJ.svg +1 -0
  271. package/src/components/flag/flags/TK.svg +1 -0
  272. package/src/components/flag/flags/TL.svg +1 -0
  273. package/src/components/flag/flags/TM.svg +1 -0
  274. package/src/components/flag/flags/TN.svg +1 -0
  275. package/src/components/flag/flags/TO.svg +1 -0
  276. package/src/components/flag/flags/TR.svg +1 -0
  277. package/src/components/flag/flags/TT.svg +1 -0
  278. package/src/components/flag/flags/TV.svg +1 -0
  279. package/src/components/flag/flags/TW.svg +1 -0
  280. package/src/components/flag/flags/TZ.svg +1 -0
  281. package/src/components/flag/flags/UA.svg +1 -0
  282. package/src/components/flag/flags/UG.svg +1 -0
  283. package/src/components/flag/flags/UM.svg +1 -0
  284. package/src/components/flag/flags/US.svg +1 -0
  285. package/src/components/flag/flags/UY.svg +1 -0
  286. package/src/components/flag/flags/UZ.svg +1 -0
  287. package/src/components/flag/flags/VA.svg +1 -0
  288. package/src/components/flag/flags/VC.svg +1 -0
  289. package/src/components/flag/flags/VE.svg +1 -0
  290. package/src/components/flag/flags/VG.svg +1 -0
  291. package/src/components/flag/flags/VI.svg +1 -0
  292. package/src/components/flag/flags/VN.svg +1 -0
  293. package/src/components/flag/flags/VU.svg +1 -0
  294. package/src/components/flag/flags/WF.svg +1 -0
  295. package/src/components/flag/flags/WS.svg +1 -0
  296. package/src/components/flag/flags/XK.svg +1 -0
  297. package/src/components/flag/flags/YE.svg +1 -0
  298. package/src/components/flag/flags/YT.svg +1 -0
  299. package/src/components/flag/flags/ZA.svg +1 -0
  300. package/src/components/flag/flags/ZM.svg +1 -0
  301. package/src/components/flag/flags/ZW.svg +1 -0
  302. package/src/components/flag/index.ts +2 -0
  303. package/src/slides/export/pdf.ts +11 -0
  304. package/src/vite/flags.test.ts +38 -0
  305. package/src/vite/flags.ts +63 -0
package/COMPONENTS.md CHANGED
@@ -63,6 +63,7 @@ Generic pieces built on the primitives, imported from `@heyramzi/ui/components/<
63
63
 
64
64
  - `copy` — CopyButton, copyText, copyRichText, htmlToPlainText, Copied
65
65
  - `data-table` — SortableHead, Pagination, InfiniteScroll, RowContextMenu, TableSkeleton, and the sort, page and filter helpers
66
+ - `flag` — Flag, FLAG_CODES, flagCode: a country flag from an ISO 3166-1 alpha-2 code (plus XK for Kosovo), 1em tall at 3:2, one lazy `<img>` of `/flags/<CODE>.svg` each. Add `flagAssets()` from `@heyramzi/ui/vite` to the app's Vite plugins to serve the 250 SVGs (country-flag-icons, MIT, licence beside them). Decorative unless `label` is set. An unknown code renders nothing; to keep a row's layout, wrap it in `<span class="inline-block aspect-[3/2] h-[1em]">`
66
67
  - `hold-to-confirm` — HoldToConfirm, press and hold to confirm
67
68
  - `language-flag` — LanguageFlag, LANGUAGE_FLAGS (code to `/flags/*.svg`, also a SegmentedFilter option's `image`)
68
69
  - `list-page` — ListPageShell, MasterDetail, GroupedList, RailRow and the rest of the master-detail page kit, DetailPanel, ToolbarSearch, toolbarTriggerClass, NoticeBar, EmptyState, FilterPopover, setSectionHost
@@ -124,6 +125,7 @@ Named exports from `@heyramzi/ui/effects/<name>`, e.g.
124
125
  Imported from `@heyramzi/ui/ai/<name>`, e.g. `import { AiButton } from "@heyramzi/ui/ai/ai-button"`.
125
126
 
126
127
  - `ai-button` — AiButton
128
+ - `chat-window` — ChatGptWindow, ClaudeWindow: still or playing pictures of a ChatGPT or Claude conversation for a marketing page, with a connector call row. `messages` takes user text, assistant text or a snippet, and tool steps; every printed string is a prop
127
129
  - `confirmation` — Confirmation, ConfirmationTitle, ConfirmationState (`when` names the kind it shows), ConfirmationActions, ConfirmationAction, type ConfirmationKind
128
130
  - `generation-progress` — GenerationProgress
129
131
  - `loading-state` — PixelLoader
@@ -0,0 +1,43 @@
1
+ // Each glyph is a file a CSS mask paints in the current colour. Sources and licences: icons/LICENSE.
2
+ import gptChevron from "../../../src/ai/chat-window/icons/chatgpt-chevron.svg";
3
+ import gptCopy from "../../../src/ai/chat-window/icons/chatgpt-copy.svg";
4
+ import gptMic from "../../../src/ai/chat-window/icons/chatgpt-mic.svg";
5
+ import gptMore from "../../../src/ai/chat-window/icons/chatgpt-more.svg";
6
+ import gptPlus from "../../../src/ai/chat-window/icons/chatgpt-plus.svg";
7
+ import gptRegenerate from "../../../src/ai/chat-window/icons/chatgpt-regenerate.svg";
8
+ import gptShare from "../../../src/ai/chat-window/icons/chatgpt-share.svg";
9
+ import gptSidebar from "../../../src/ai/chat-window/icons/chatgpt-sidebar.svg";
10
+ import gptThumb from "../../../src/ai/chat-window/icons/chatgpt-thumb.svg";
11
+ import gptVoice from "../../../src/ai/chat-window/icons/chatgpt-voice.svg";
12
+ import claudeChevron from "../../../src/ai/chat-window/icons/claude-chevron.svg";
13
+ import claudeCopy from "../../../src/ai/chat-window/icons/claude-copy.svg";
14
+ import claudePlus from "../../../src/ai/chat-window/icons/claude-plus.svg";
15
+ import claudeRetry from "../../../src/ai/chat-window/icons/claude-retry.svg";
16
+ import claudeSend from "../../../src/ai/chat-window/icons/claude-send.svg";
17
+ import claudeSidebar from "../../../src/ai/chat-window/icons/claude-sidebar.svg";
18
+ import claudeSliders from "../../../src/ai/chat-window/icons/claude-sliders.svg";
19
+ import claudeSpark from "../../../src/ai/chat-window/icons/claude-spark.svg";
20
+ import claudeThumb from "../../../src/ai/chat-window/icons/claude-thumb.svg";
21
+ export const CHATGPT_ICONS = {
22
+ chevron: gptChevron,
23
+ copy: gptCopy,
24
+ mic: gptMic,
25
+ more: gptMore,
26
+ plus: gptPlus,
27
+ regenerate: gptRegenerate,
28
+ share: gptShare,
29
+ sidebar: gptSidebar,
30
+ thumb: gptThumb,
31
+ voice: gptVoice
32
+ };
33
+ export const CLAUDE_ICONS = {
34
+ chevron: claudeChevron,
35
+ copy: claudeCopy,
36
+ plus: claudePlus,
37
+ retry: claudeRetry,
38
+ send: claudeSend,
39
+ sidebar: claudeSidebar,
40
+ sliders: claudeSliders,
41
+ spark: claudeSpark,
42
+ thumb: claudeThumb
43
+ };
@@ -0,0 +1,5 @@
1
+ import ChatGptWindow from "../../../src/ai/chat-window/ChatGptWindow.svelte";
2
+ import ClaudeWindow from "../../../src/ai/chat-window/ClaudeWindow.svelte";
3
+ export { CHATGPT_LABELS, CLAUDE_LABELS } from "./labels.js";
4
+ export { REVEAL_BEATS, revealSchedule } from "./reveal.svelte.js";
5
+ export { ChatGptWindow, ClaudeWindow };
@@ -0,0 +1,16 @@
1
+ export const CHATGPT_LABELS = {
2
+ running: "Calling {name}",
3
+ done: "Used {name}",
4
+ share: "Share",
5
+ disclaimer: "ChatGPT can make mistakes. Check important info.",
6
+ userSaid: "You said:",
7
+ assistantSaid: "ChatGPT said:"
8
+ };
9
+ export const CLAUDE_LABELS = {
10
+ running: "Using {name}",
11
+ done: "Used {name}",
12
+ share: "Share",
13
+ disclaimer: "Claude can make mistakes. Please double-check responses.",
14
+ userSaid: "You said:",
15
+ assistantSaid: "Claude said:"
16
+ };
@@ -0,0 +1,106 @@
1
+ import { untrack } from "svelte";
2
+ /** Milliseconds each beat holds, read as one conversation's pacing, not a transition. */
3
+ export const REVEAL_BEATS = {
4
+ lead: 400,
5
+ user: 900,
6
+ thinking: 900,
7
+ stream: 1500,
8
+ running: 1300,
9
+ after: 350
10
+ };
11
+ /** The timeline for a conversation: when each message enters and settles, and when it ends. */
12
+ export function revealSchedule(roles, beats = REVEAL_BEATS) {
13
+ const out = [];
14
+ let t = beats.lead;
15
+ roles.forEach((role, index) => {
16
+ if (role === "user") {
17
+ out.push({
18
+ at: t,
19
+ index,
20
+ phase: "done"
21
+ });
22
+ t += beats.user;
23
+ } else if (role === "assistant") {
24
+ out.push({
25
+ at: t,
26
+ index,
27
+ phase: "thinking"
28
+ });
29
+ t += beats.thinking;
30
+ out.push({
31
+ at: t,
32
+ index,
33
+ phase: "streaming"
34
+ });
35
+ t += beats.stream;
36
+ out.push({
37
+ at: t,
38
+ index,
39
+ phase: "done"
40
+ });
41
+ t += beats.after;
42
+ } else {
43
+ out.push({
44
+ at: t,
45
+ index,
46
+ phase: "running"
47
+ });
48
+ t += beats.running;
49
+ out.push({
50
+ at: t,
51
+ index,
52
+ phase: "done"
53
+ });
54
+ t += beats.after;
55
+ }
56
+ });
57
+ return {
58
+ beats: out,
59
+ end: t
60
+ };
61
+ }
62
+ /**
63
+ * Plays a conversation once the window is on screen and `active`, again each time `active` turns on.
64
+ * Renders finished for SSR, no JavaScript and reduced motion.
65
+ */
66
+ export function createReveal(options) {
67
+ let phases = $state([]);
68
+ let node = $state(null);
69
+ let seen = $state(false);
70
+ $effect(() => {
71
+ const { enabled } = options();
72
+ if (!node || !enabled || seen) return;
73
+ const io = new IntersectionObserver((entries) => {
74
+ if (entries.some((e) => e.isIntersecting)) {
75
+ seen = true;
76
+ io.disconnect();
77
+ }
78
+ }, { threshold: .35 });
79
+ io.observe(node);
80
+ return () => io.disconnect();
81
+ });
82
+ $effect(() => {
83
+ const { enabled, active } = options();
84
+ if (!enabled || !active || !seen) return;
85
+ if (window.matchMedia("(prefers-reduced-motion: reduce)").matches) return;
86
+ const { roles, hold, ondone } = untrack(options);
87
+ const { beats, end } = revealSchedule(roles);
88
+ phases = roles.map(() => "hidden");
89
+ const timers = beats.map((b) => setTimeout(() => phases[b.index] = b.phase, b.at));
90
+ timers.push(setTimeout(() => ondone?.(), end + hold));
91
+ return () => {
92
+ timers.forEach(clearTimeout);
93
+ phases = [];
94
+ };
95
+ });
96
+ return {
97
+ /** A message's phase; `done` when nothing is playing. */
98
+ phase: (index) => phases[index] ?? "done",
99
+ /** Attach to the window's root, so the reveal waits until it scrolls into view. */
100
+ attach: (el) => {
101
+ node = el;
102
+ return () => node = null;
103
+ },
104
+ streamMs: REVEAL_BEATS.stream
105
+ };
106
+ }
@@ -0,0 +1,4 @@
1
+ /** Fills `{name}` in a label such as "Used {name}". */
2
+ export function fillName(template, name) {
3
+ return template.replaceAll("{name}", name);
4
+ }
@@ -32,7 +32,7 @@ export function htmlToPlainText(html) {
32
32
  if (typeof document === "undefined") {
33
33
  return html.replace(/<br\s*\/?>/gi, "\n").replace(/<\/p>/gi, "\n\n").replace(/<\/li>/gi, "\n").replace(/<li>/gi, "• ").replace(/<[^>]+>/g, "").replace(/&nbsp;/g, " ").replace(/&amp;/g, "&").replace(/&lt;/g, "<").replace(/&gt;/g, ">").trim();
34
34
  }
35
- const div = document.createElement("div");
36
- div.innerHTML = html;
37
- return div.textContent || div.innerText || "";
35
+ // A DOMParser document has no browsing context, so nothing in the markup loads or runs.
36
+ // An element from document.createElement belongs to the live page: an <img onerror> fires.
37
+ return new DOMParser().parseFromString(html, "text/html").body.textContent ?? "";
38
38
  }
@@ -0,0 +1,13 @@
1
+ /** Where the host serves the flag files. `flagAssets()` from `@heyramzi/ui/vite` serves them there. */
2
+ export const FLAG_BASE = "/flags";
3
+ /**
4
+ * The 249 ISO 3166-1 alpha-2 codes plus XK (Kosovo, user-assigned but in common use), each with
5
+ * a file in `./flags`, from country-flag-icons 1.6.20 (MIT).
6
+ */
7
+ export const FLAG_CODES = ("AD AE AF AG AI AL AM AO AQ AR AS AT AU AW AX AZ BA BB BD BE BF BG BH BI BJ BL BM BN BO BQ BR " + "BS BT BV BW BY BZ CA CC CD CF CG CH CI CK CL CM CN CO CR CU CV CW CX CY CZ DE DJ DK DM DO DZ " + "EC EE EG EH ER ES ET FI FJ FK FM FO FR GA GB GD GE GF GG GH GI GL GM GN GP GQ GR GS GT GU GW " + "GY HK HM HN HR HT HU ID IE IL IM IN IO IQ IR IS IT JE JM JO JP KE KG KH KI KM KN KP KR KW KY " + "KZ LA LB LC LI LK LR LS LT LU LV LY MA MC MD ME MF MG MH MK ML MM MN MO MP MQ MR MS MT MU MV " + "MW MX MY MZ NA NC NE NF NG NI NL NO NP NR NU NZ OM PA PE PF PG PH PK PL PM PN PR PS PT PW PY " + "QA RE RO RS RU RW SA SB SC SD SE SG SH SI SJ SK SL SM SN SO SR SS ST SV SX SY SZ TC TD TF TG " + "TH TJ TK TL TM TN TO TR TT TV TW TZ UA UG UM US UY UZ VA VC VE VG VI VN VU WF WS XK YE YT ZA ZM ZW").split(" ");
8
+ const KNOWN = new Set(FLAG_CODES);
9
+ /** The code in capitals when a flag exists for it, else null. */
10
+ export function flagCode(code) {
11
+ const upper = code?.trim().toUpperCase() ?? "";
12
+ return KNOWN.has(upper) ? upper : null;
13
+ }
@@ -0,0 +1,2 @@
1
+ export { default as Flag } from "../../../src/components/flag/flag.svelte";
2
+ export { FLAG_BASE, FLAG_CODES, flagCode } from "./codes.js";
@@ -38,6 +38,13 @@ export async function printPage(page, options = {}) {
38
38
  }
39
39
  await page.evaluate(() => document.fonts.ready.then(() => undefined));
40
40
  if (options.settle) await page.waitForTimeout(options.settle);
41
+ // WHY: a lazy or still-loading image read as broken while the PDF printed it (testimonial photos, 11 Nov 2026).
42
+ await page.evaluate(() => Promise.all([...document.images].map((img) => {
43
+ img.loading = "eager";
44
+ if (img.complete) return undefined;
45
+ const loaded = img.decode().catch(() => undefined);
46
+ return Promise.race([loaded, new Promise((resolve) => setTimeout(resolve, 15e3))]);
47
+ })).then(() => undefined));
41
48
  const brokenImages = await page.evaluate(() => [...document.images].filter((img) => !img.complete || img.naturalWidth === 0).map((img) => img.src));
42
49
  const { size } = options;
43
50
  const pdf = await page.pdf({
@@ -0,0 +1,46 @@
1
+ import { existsSync, readdirSync, readFileSync } from "node:fs";
2
+ import { dirname, join } from "node:path";
3
+ import { fileURLToPath } from "node:url";
4
+ // From src/vite in the repo, or dist/vite in the published package.
5
+ const here = dirname(fileURLToPath(import.meta.url));
6
+ const FLAGS_DIR = [join(here, "../components/flag/flags"), join(here, "../../src/components/flag/flags")].find((dir) => existsSync(dir));
7
+ /**
8
+ * Serves the `Flag` SVGs at `/flags/<CODE>.svg`: from the package in dev and preview, and as
9
+ * one static file each in the client build. Add it to `plugins` in `vite.config.ts`.
10
+ */
11
+ export function flagAssets(options = {}) {
12
+ const base = (options.base ?? "/flags").replace(/\/$/, "");
13
+ if (!FLAGS_DIR) throw new Error("@heyramzi/ui: the flag SVGs are missing from the package");
14
+ const dir = FLAGS_DIR;
15
+ const files = readdirSync(dir).filter((name) => /^[A-Z]{2}\.svg$/.test(name));
16
+ const known = new Set(files);
17
+ let ssrBuild = false;
18
+ // Returns nothing: Vite calls a function returned from configureServer as a post hook.
19
+ const serve = (server) => {
20
+ server.middlewares.use((req, res, next) => {
21
+ const path = req.url?.split("?")[0] ?? "";
22
+ const name = path.startsWith(`${base}/`) ? path.slice(base.length + 1) : "";
23
+ if (!known.has(name)) return next();
24
+ res.setHeader("Content-Type", "image/svg+xml");
25
+ res.setHeader("Cache-Control", "public, max-age=86400");
26
+ res.end(readFileSync(join(dir, name)));
27
+ });
28
+ };
29
+ return {
30
+ name: "heyramzi-ui:flags",
31
+ configResolved(config) {
32
+ ssrBuild = Boolean(config.build.ssr);
33
+ },
34
+ configureServer: serve,
35
+ configurePreviewServer: serve,
36
+ generateBundle() {
37
+ const consumer = this.environment?.config?.consumer;
38
+ if (consumer ? consumer !== "client" : ssrBuild) return;
39
+ for (const name of files) this.emitFile({
40
+ type: "asset",
41
+ fileName: `${base.replace(/^\//, "")}/${name}`,
42
+ source: readFileSync(join(dir, name))
43
+ });
44
+ }
45
+ };
46
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@heyramzi/ui",
3
- "version": "3.4.0",
3
+ "version": "3.6.0",
4
4
  "description": "Svelte 5 UI for apps: primitives, effects and animations, plus work (tasks and docs), charts, slides, an editor, onboarding and a canvas as subpaths.",
5
5
  "homepage": "https://ui.heyramzi.com",
6
6
  "license": "MIT",
@@ -115,6 +115,11 @@
115
115
  "node": "./dist/effects/magnetic/magnetic.js",
116
116
  "default": "./src/effects/magnetic/magnetic.ts"
117
117
  },
118
+ "./vite": {
119
+ "types": "./src/vite/flags.ts",
120
+ "node": "./dist/vite/flags.js",
121
+ "default": "./src/vite/flags.ts"
122
+ },
118
123
  "./icons/sf-symbols": {
119
124
  "svelte": "./src/icons/sf-symbols.ts",
120
125
  "types": "./src/icons/sf-symbols.ts",
@@ -389,6 +394,6 @@
389
394
  "sync": "pnpm sync:transitions && pnpm sync:shadcn",
390
395
  "sync:check": "node scripts/sync-transitions.mjs --check && node scripts/sync-shadcn.mjs --check",
391
396
  "check": "svelte-check --tsconfig ./tsconfig.json",
392
- "build": "node ../../../vibe-kit/scripts/build-dist.mjs"
397
+ "build": "node ../../../upsys/kit/scripts/build-dist.mjs"
393
398
  }
394
399
  }
@@ -0,0 +1,38 @@
1
+ <script lang="ts">
2
+ // =========================
3
+ // PROPS
4
+ // =========================
5
+ interface Props {
6
+ /** The SVG file's URL, painted through a mask in the current colour. */
7
+ src: string;
8
+ size?: number;
9
+ class?: string;
10
+ }
11
+
12
+ let { src, size = 20, class: className = "" }: Props = $props();
13
+ </script>
14
+
15
+ <!-- =========================== -->
16
+ <!-- MARKUP -->
17
+ <!-- =========================== -->
18
+ <span
19
+ class="chat-glyph {className}"
20
+ style:--glyph={`url("${src}")`}
21
+ style:--size="{size}px"
22
+ aria-hidden="true"
23
+ ></span>
24
+
25
+ <style>
26
+ @layer theme, base, components, utilities;
27
+
28
+ @layer components {
29
+ .chat-glyph {
30
+ display: block;
31
+ flex: none;
32
+ width: var(--size);
33
+ height: var(--size);
34
+ background: currentColor;
35
+ mask: var(--glyph) center / contain no-repeat;
36
+ }
37
+ }
38
+ </style>
@@ -0,0 +1,9 @@
1
+ interface Props {
2
+ /** The SVG file's URL, painted through a mask in the current colour. */
3
+ src: string;
4
+ size?: number;
5
+ class?: string;
6
+ }
7
+ declare const $$Component: import("svelte").Component<Props, {}, "">;
8
+ type $$Component = ReturnType<typeof $$Component>;
9
+ export default $$Component;