@lostgradient/cinder 0.8.0 → 0.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (271) hide show
  1. package/CHANGELOG.md +9 -0
  2. package/README.md +2 -2
  3. package/components.json +59 -15
  4. package/dist/components/_internal/command-list-context.d.ts +3 -3
  5. package/dist/components/_internal/create-command-list-state.svelte.d.ts +11 -11
  6. package/dist/components/access-gate/index.js +201 -126
  7. package/dist/components/approval-card/approval-card-actions.svelte.d.ts +16 -0
  8. package/dist/components/approval-card/approval-card-state.d.ts +65 -0
  9. package/dist/components/approval-card/approval-card.css +269 -92
  10. package/dist/components/approval-card/approval-card.schema.js +10 -31
  11. package/dist/components/approval-card/approval-card.svelte.d.ts +3 -3
  12. package/dist/components/approval-card/approval-card.types.d.ts +14 -28
  13. package/dist/components/approval-card/index.d.ts +1 -1
  14. package/dist/components/approval-card/index.js +4268 -2884
  15. package/dist/components/card/card.css +5 -0
  16. package/dist/components/card/card.schema.js +2 -2
  17. package/dist/components/card/card.types.d.ts +2 -2
  18. package/dist/components/card/index.js +2 -1
  19. package/dist/components/chat/chat.schema.js +44 -2
  20. package/dist/components/chat/chat.svelte.d.ts +4 -2
  21. package/dist/components/chat/chat.types.d.ts +34 -3
  22. package/dist/components/chat/container/chat.svelte.d.ts +4 -2
  23. package/dist/components/chat/index.d.ts +3 -3
  24. package/dist/components/chat/index.js +2485 -6279
  25. package/dist/components/chat/input/chat-attachment-serialization.d.ts +9 -0
  26. package/dist/components/chat/input/chat-input.svelte.d.ts +22 -1
  27. package/dist/components/chat/input/index.d.ts +1 -0
  28. package/dist/components/chat-composer-popover/chat-composer-popover-filter.d.ts +11 -0
  29. package/dist/components/chat-composer-popover/chat-composer-popover.css +7 -0
  30. package/dist/components/chat-composer-popover/chat-composer-popover.css.d.ts +1 -0
  31. package/dist/components/chat-composer-popover/chat-composer-popover.schema.d.ts +3 -0
  32. package/dist/components/chat-composer-popover/chat-composer-popover.schema.js +150 -0
  33. package/dist/components/chat-composer-popover/chat-composer-popover.svelte.d.ts +46 -0
  34. package/dist/components/chat-composer-popover/chat-composer-popover.types.d.ts +77 -0
  35. package/dist/components/chat-composer-popover/chat-composer-popover.variables.d.ts +2 -0
  36. package/dist/components/chat-composer-popover/chat-composer-popover.variables.js +61 -0
  37. package/dist/components/chat-composer-popover/index.d.ts +6 -0
  38. package/dist/components/chat-composer-popover/index.js +3285 -0
  39. package/dist/components/chat-conversation-header/index.js +1627 -5600
  40. package/dist/components/chat-conversation-list/index.js +15 -3988
  41. package/dist/components/code-block/code-block.schema.js +5 -1
  42. package/dist/components/code-block/code-block.types.d.ts +6 -0
  43. package/dist/components/code-block/index.js +4 -4
  44. package/dist/components/command-item/index.js +7 -6
  45. package/dist/components/command-menu/command-menu.schema.js +5 -1
  46. package/dist/components/command-menu/command-menu.types.d.ts +2 -0
  47. package/dist/components/command-menu/index.js +48 -19
  48. package/dist/components/command-palette/index.js +40 -14
  49. package/dist/components/event-stream-viewer/index.js +44 -44
  50. package/dist/components/experimental/json-viewer/index.js +44 -44
  51. package/dist/components/json-schema-editor/index.js +5 -2
  52. package/dist/components/json-viewer/index.js +44 -44
  53. package/dist/components/json-viewer/json-viewer.css +10 -6
  54. package/dist/components/payload-inspector/index.d.ts +1 -1
  55. package/dist/components/payload-inspector/index.js +306 -1422
  56. package/dist/components/payload-inspector/payload-inspector.css +15 -75
  57. package/dist/components/payload-inspector/payload-inspector.schema.js +5 -41
  58. package/dist/components/payload-inspector/payload-inspector.svelte.d.ts +5 -5
  59. package/dist/components/payload-inspector/payload-inspector.types.d.ts +10 -56
  60. package/dist/components/tab/index.js +5 -2
  61. package/dist/components/tab/tab.schema.js +7 -3
  62. package/dist/components/tab/tab.svelte.d.ts +2 -1
  63. package/dist/components/tab/tab.types.d.ts +8 -2
  64. package/dist/components/tabs/index.js +5 -2
  65. package/dist/components/team-section/index.js +2 -1
  66. package/dist/components/testimonial-section/index.js +2 -1
  67. package/dist/index.d.ts +4 -2
  68. package/dist/index.js +23711 -27432
  69. package/dist/server/components/access-gate/index.js +2 -1
  70. package/dist/server/components/accordion/index.js +2 -2
  71. package/dist/server/components/alert-dialog/index.js +2 -2
  72. package/dist/server/components/approval-card/index.js +15 -19
  73. package/dist/server/components/autocomplete/index.js +7 -7
  74. package/dist/server/components/avatar-group/index.js +5 -5
  75. package/dist/server/components/button-group/index.js +3 -5
  76. package/dist/server/components/card/index.js +2 -2
  77. package/dist/server/components/chat/index.js +14 -11
  78. package/dist/server/components/chat-composer-popover/index.js +26 -0
  79. package/dist/server/components/chat-conversation-header/index.js +9 -10
  80. package/dist/server/components/chat-conversation-list/index.js +4 -5
  81. package/dist/server/components/checkbox/index.js +3 -3
  82. package/dist/server/components/choice-grid/index.js +2 -2
  83. package/dist/server/components/code-block/index.js +2 -2
  84. package/dist/server/components/color-field/index.js +3 -3
  85. package/dist/server/components/combobox/index.js +6 -6
  86. package/dist/server/components/command-item/index.js +5 -3
  87. package/dist/server/components/command-menu/index.js +6 -4
  88. package/dist/server/components/command-palette/index.js +2 -2
  89. package/dist/server/components/confirm-dialog/index.js +2 -2
  90. package/dist/server/components/context-menu/index.js +5 -5
  91. package/dist/server/components/data-table/index.js +5 -5
  92. package/dist/server/components/date-picker/index.js +6 -6
  93. package/dist/server/components/date-range-field/index.js +7 -7
  94. package/dist/server/components/description-list/index.js +3 -5
  95. package/dist/server/components/diff-viewer/index.js +7 -7
  96. package/dist/server/components/drawer/index.js +3 -3
  97. package/dist/server/components/dropdown/index.js +4 -4
  98. package/dist/server/components/event-stream-viewer/index.js +2 -2
  99. package/dist/server/components/experimental/json-viewer/index.js +2 -2
  100. package/dist/server/components/faceted-filter-bar/index.js +1 -1
  101. package/dist/server/components/hover-card/index.js +1 -1
  102. package/dist/server/components/input/index.js +3 -3
  103. package/dist/server/components/json-schema-editor/index.js +22 -22
  104. package/dist/server/components/json-viewer/index.js +2 -2
  105. package/dist/server/components/markdown-editor/index.js +13 -13
  106. package/dist/server/components/modal/index.js +1 -1
  107. package/dist/server/components/multi-select/index.js +1 -1
  108. package/dist/server/components/newsletter-section/index.js +3 -3
  109. package/dist/server/components/payload-inspector/index.js +4 -16
  110. package/dist/server/components/popover/index.js +5 -5
  111. package/dist/server/components/review-editor/index.js +25 -25
  112. package/dist/server/components/run-step-timeline/index.js +2 -2
  113. package/dist/server/components/schema-form/index.js +4 -4
  114. package/dist/server/components/secret-value-field/index.js +3 -5
  115. package/dist/server/components/segment/index.js +3 -3
  116. package/dist/server/components/segmented-control/index.js +4 -4
  117. package/dist/server/components/selection-popover/index.js +4 -4
  118. package/dist/server/components/sheet/index.js +2 -2
  119. package/dist/server/components/sidebar/index.js +3 -3
  120. package/dist/server/components/tab/index.js +2 -2
  121. package/dist/server/components/table/index.js +3 -3
  122. package/dist/server/components/tabs/index.js +4 -4
  123. package/dist/server/components/tag-input/index.js +3 -3
  124. package/dist/server/components/team-section/index.js +8 -8
  125. package/dist/server/components/testimonial-section/index.js +2 -2
  126. package/dist/server/components/toggle/index.js +2 -2
  127. package/dist/server/components/tooltip/index.js +1 -1
  128. package/dist/server/index.js +159 -148
  129. package/dist/server/{index.server-cbtg8rq5.js → index.server-0atyznp7.js} +5 -5
  130. package/dist/server/{index.server-20y4mdhm.js → index.server-0chhpkg7.js} +40 -14
  131. package/dist/server/{index.server-ecm1vs3g.js → index.server-1nq7z1qw.js} +1 -1
  132. package/dist/server/{index.server-jync915v.js → index.server-2dga5yzr.js} +25 -25
  133. package/dist/server/index.server-2hqrv7ca.js +9 -0
  134. package/dist/server/{index.server-69epaape.js → index.server-2qj6s2mh.js} +1 -1
  135. package/dist/server/{index.server-pt8b65mt.js → index.server-38aywdk1.js} +1 -1
  136. package/dist/server/{index.server-rermas0k.js → index.server-47v2fhp4.js} +4 -4
  137. package/dist/server/{index.server-9j5sym59.js → index.server-4x91gzy1.js} +2 -2
  138. package/dist/server/{index.server-q48q15g7.js → index.server-4y2jtvv1.js} +4 -2
  139. package/dist/server/index.server-67qgdypc.js +9 -0
  140. package/dist/server/{index.server-9jete4xx.js → index.server-6sh11ap6.js} +4 -4
  141. package/dist/server/{index.server-4ztq565m.js → index.server-85p4ydph.js} +1 -1
  142. package/dist/server/{index.server-4nk7gy0q.js → index.server-894t97kv.js} +1 -1
  143. package/dist/server/{index.server-1vscnped.js → index.server-8dt36sdm.js} +2 -1
  144. package/dist/server/{index.server-bfsbp9dz.js → index.server-8xvc73zh.js} +4 -4
  145. package/dist/server/{index.server-cvnw3hw9.js → index.server-9kz37z89.js} +1 -1
  146. package/dist/server/{index.server-kc1k02tk.js → index.server-9ykk1kbg.js} +1 -1
  147. package/dist/server/{index.server-g789yep6.js → index.server-aqethy0w.js} +2 -2
  148. package/dist/server/{index.server-wc9aggfz.js → index.server-bmxbsk4y.js} +7 -7
  149. package/dist/server/{index.server-j3ddzcaa.js → index.server-c6pe4kaf.js} +6 -6
  150. package/dist/server/{index.server-q89dz8h1.js → index.server-d3pqthtp.js} +4 -3
  151. package/dist/server/{index.server-qfa2rxzx.js → index.server-dg83ke3k.js} +3 -5
  152. package/dist/server/{index.server-jk4rx4aa.js → index.server-dmmvwy6p.js} +1 -1
  153. package/dist/server/{index.server-hcfnae5y.js → index.server-dwwqssey.js} +4 -4
  154. package/dist/server/{index.server-e8x1hgw6.js → index.server-dz1r9xw5.js} +4 -4
  155. package/dist/server/{index.server-wm7mk5kw.js → index.server-ez5hp0ya.js} +1 -1
  156. package/dist/server/{index.server-ejyf7e48.js → index.server-fy068yne.js} +1 -1
  157. package/dist/server/{index.server-wc8dbm5e.js → index.server-g95bk8rc.js} +4 -2
  158. package/dist/server/index.server-gkazv439.js +576 -0
  159. package/dist/server/{index.server-dp9j2kkr.js → index.server-h0cvwvhy.js} +1 -1
  160. package/dist/server/{index.server-pacrqvyz.js → index.server-h90pjrez.js} +1 -1
  161. package/dist/server/{index.server-p8d04em5.js → index.server-hcsd5gdb.js} +6 -2
  162. package/dist/server/{index.server-n39drzes.js → index.server-hpeavvnq.js} +1 -1
  163. package/dist/server/{index.server-1p3patnj.js → index.server-hx91ng7z.js} +1 -1
  164. package/dist/server/{index.server-jtj3r53y.js → index.server-jgb8yh5k.js} +1 -1
  165. package/dist/server/{index.server-w1g5q9j9.js → index.server-jtgw9d23.js} +4 -2
  166. package/dist/server/{index.server-mehav5vs.js → index.server-jxg42jpz.js} +4 -4
  167. package/dist/server/{index.server-hd8gpehd.js → index.server-jxseyx33.js} +1 -1
  168. package/dist/server/{index.server-kg2sepsr.js → index.server-krqvnt6p.js} +14 -15
  169. package/dist/server/{index.server-0e1m3agz.js → index.server-ks49bprh.js} +1 -1
  170. package/dist/server/{index.server-f0hma3jp.js → index.server-kt0ncrqs.js} +1 -1
  171. package/dist/server/index.server-m0ezemav.js +170 -0
  172. package/dist/server/index.server-m191rm44.js +79 -0
  173. package/dist/server/{index.server-f23vtaw4.js → index.server-marjz8ps.js} +6 -6
  174. package/dist/server/index.server-mqt1ngqw.js +250 -0
  175. package/dist/server/{index.server-s9khh4ry.js → index.server-mzzb7dnm.js} +3 -5
  176. package/dist/server/{index.server-z721a5gp.js → index.server-n82rcv0m.js} +4 -4
  177. package/dist/server/{index.server-rhhmdxtz.js → index.server-np3c7kx0.js} +4 -4
  178. package/dist/server/{index.server-hpcs7tmh.js → index.server-p56xxef1.js} +1 -1
  179. package/dist/server/{index.server-w83kmcrx.js → index.server-pag862vz.js} +10 -10
  180. package/dist/server/{index.server-gxf0d1p5.js → index.server-q7w4jw89.js} +2 -2
  181. package/dist/server/{index.server-v4zabrsx.js → index.server-qh9qzd5t.js} +163 -25
  182. package/dist/server/{index.server-pxg74pyp.js → index.server-qk1h0n02.js} +4 -4
  183. package/dist/server/{index.server-sh2rxejg.js → index.server-qke3ekjt.js} +1 -1
  184. package/dist/server/{index.server-73x2d3j3.js → index.server-rbpvcrr3.js} +1 -1
  185. package/dist/server/{index.server-8cxs4kya.js → index.server-rga8sc7j.js} +41 -44
  186. package/dist/server/{index.server-e3fnv1g6.js → index.server-sedjxt36.js} +5 -5
  187. package/dist/server/{index.server-pen9pxt6.js → index.server-sf3nk3j2.js} +2 -2
  188. package/dist/server/{index.server-7fp0epev.js → index.server-veastatv.js} +4 -4
  189. package/dist/server/{index.server-jeqg2d22.js → index.server-xeqtpv61.js} +1 -1
  190. package/dist/server/{index.server-9s4na701.js → index.server-xjnge1yw.js} +4 -4
  191. package/dist/server/index.server-xtjjmsyq.js +315 -0
  192. package/dist/server/{index.server-hhxjaeen.js → index.server-xz99aed4.js} +4 -4
  193. package/dist/server/{index.server-vne4rzfa.js → index.server-y4n8vc08.js} +1 -1
  194. package/dist/server/{index.server-5d01cn4f.js → index.server-y83kqayt.js} +4 -4
  195. package/dist/server/{index.server-1nh09ck7.js → index.server-yhzydqxe.js} +5 -5
  196. package/dist/server/{index.server-atjc1qcq.js → index.server-yz4k36cw.js} +1 -1
  197. package/dist/server/{index.server-w6k62afr.js → index.server-ze1ymmbw.js} +2 -2
  198. package/dist/server/{index.server-914v805w.js → index.server-zgd1g8mk.js} +1 -1
  199. package/dist/server/{index.server-aeexcxdp.js → index.server-zh3r8vfd.js} +1 -1
  200. package/dist/server/{index.server-10jb2jzm.js → index.server-zsjf8enc.js} +4 -4
  201. package/package.json +40 -6
  202. package/src/components/_internal/command-list-context.ts +3 -3
  203. package/src/components/_internal/create-command-list-state.svelte.ts +39 -13
  204. package/src/components/approval-card/approval-card-actions.svelte +168 -0
  205. package/src/components/approval-card/approval-card-state.ts +152 -1
  206. package/src/components/approval-card/approval-card.css +269 -92
  207. package/src/components/approval-card/approval-card.examples.json +3 -3
  208. package/src/components/approval-card/approval-card.schema.json +9 -30
  209. package/src/components/approval-card/approval-card.schema.ts +13 -31
  210. package/src/components/approval-card/approval-card.svelte +176 -470
  211. package/src/components/approval-card/approval-card.types.ts +15 -28
  212. package/src/components/approval-card/index.ts +1 -0
  213. package/src/components/card/card.css +5 -0
  214. package/src/components/card/card.schema.json +1 -1
  215. package/src/components/card/card.schema.ts +1 -1
  216. package/src/components/card/card.svelte +1 -0
  217. package/src/components/card/card.types.ts +2 -2
  218. package/src/components/chat/chat.schema.json +36 -1
  219. package/src/components/chat/chat.schema.ts +44 -1
  220. package/src/components/chat/chat.svelte +12 -0
  221. package/src/components/chat/chat.types.ts +35 -3
  222. package/src/components/chat/container/chat.svelte +73 -3
  223. package/src/components/chat/index.ts +15 -3
  224. package/src/components/chat/input/chat-attachment-serialization.ts +63 -0
  225. package/src/components/chat/input/chat-input.svelte +22 -5
  226. package/src/components/chat/input/index.ts +5 -0
  227. package/src/components/chat-composer-popover/chat-composer-popover-filter.ts +68 -0
  228. package/src/components/chat-composer-popover/chat-composer-popover.css +7 -0
  229. package/src/components/chat-composer-popover/chat-composer-popover.examples.json +13 -0
  230. package/src/components/chat-composer-popover/chat-composer-popover.schema.json +90 -0
  231. package/src/components/chat-composer-popover/chat-composer-popover.schema.ts +95 -0
  232. package/src/components/chat-composer-popover/chat-composer-popover.svelte +234 -0
  233. package/src/components/chat-composer-popover/chat-composer-popover.types.ts +88 -0
  234. package/src/components/chat-composer-popover/chat-composer-popover.variables.json +1 -0
  235. package/src/components/chat-composer-popover/chat-composer-popover.variables.ts +3 -0
  236. package/src/components/chat-composer-popover/index.ts +19 -0
  237. package/src/components/code-block/code-block.schema.json +4 -0
  238. package/src/components/code-block/code-block.schema.ts +5 -0
  239. package/src/components/code-block/code-block.svelte +3 -3
  240. package/src/components/code-block/code-block.types.ts +6 -0
  241. package/src/components/command-item/command-item.svelte +7 -6
  242. package/src/components/command-menu/command-menu.schema.json +4 -0
  243. package/src/components/command-menu/command-menu.schema.ts +4 -0
  244. package/src/components/command-menu/command-menu.svelte +16 -5
  245. package/src/components/command-menu/command-menu.types.ts +2 -0
  246. package/src/components/json-viewer/_json-viewer-node.svelte +15 -1
  247. package/src/components/json-viewer/json-viewer.css +10 -6
  248. package/src/components/payload-inspector/index.ts +0 -2
  249. package/src/components/payload-inspector/payload-inspector.css +15 -75
  250. package/src/components/payload-inspector/payload-inspector.examples.json +5 -5
  251. package/src/components/payload-inspector/payload-inspector.schema.json +3 -31
  252. package/src/components/payload-inspector/payload-inspector.schema.ts +3 -36
  253. package/src/components/payload-inspector/payload-inspector.svelte +46 -239
  254. package/src/components/payload-inspector/payload-inspector.types.ts +10 -58
  255. package/src/components/tab/tab.schema.json +6 -2
  256. package/src/components/tab/tab.schema.ts +8 -2
  257. package/src/components/tab/tab.svelte +9 -5
  258. package/src/components/tab/tab.types.ts +8 -2
  259. package/src/index.ts +18 -5
  260. package/src/styles/components.css +1 -0
  261. package/dist/server/index-49we2xfs.js +0 -344
  262. package/dist/server/index-8fhvxk30.js +0 -265
  263. package/dist/server/index-x2ysg8ds.js +0 -388
  264. package/dist/server/index.server-20j0jh30.js +0 -9
  265. package/dist/server/index.server-dc35kh7d.js +0 -1835
  266. package/dist/server/index.server-kd4b0342.js +0 -607
  267. package/dist/server/index.server-n5cdmsz4.js +0 -30
  268. package/dist/server/index.server-rjap4k7y.js +0 -1389
  269. package/dist/server/index.server-vt6sn9y4.js +0 -447
  270. package/dist/server/index.server-w63n618v.js +0 -9
  271. package/dist/server/index.server-y2pa1k46.js +0 -9
@@ -1,6 +1,7 @@
1
1
  import { inDocumentOrder } from '../../utilities/document-order.ts';
2
2
  export class CommandListState {
3
- listboxId;
3
+ #getListboxId;
4
+ #registeredListboxId = $state('');
4
5
  registrations = $state([]);
5
6
  registrationsReady = $state(false);
6
7
  #itemCounter = 0;
@@ -15,7 +16,24 @@ export class CommandListState {
15
16
  ? this.#intendedActiveId
16
17
  : (this.enabledIds[0] ?? null));
17
18
  constructor(listboxId) {
18
- this.listboxId = listboxId;
19
+ this.#getListboxId = typeof listboxId === 'function' ? listboxId : () => listboxId;
20
+ this.#registeredListboxId = this.#getListboxId();
21
+ }
22
+ get listboxId() {
23
+ return this.#registeredListboxId;
24
+ }
25
+ syncListboxId(nextListboxId = this.#getListboxId()) {
26
+ const listboxId = nextListboxId;
27
+ if (this.#registeredListboxId === listboxId)
28
+ return;
29
+ this.#registeredListboxId = listboxId;
30
+ this.#intendedActiveId = null;
31
+ this.registrations = this.registrations.map((registration, index) => ({
32
+ ...registration,
33
+ id: updateRegistrationHandleId(registration, `${listboxId}-item-${index + 1}`),
34
+ }));
35
+ this.#itemCounter = this.registrations.length;
36
+ this.refreshRegistrationsReady();
19
37
  }
20
38
  resetActiveItem() {
21
39
  this.#intendedActiveId = null;
@@ -38,22 +56,26 @@ export class CommandListState {
38
56
  this.#intendedActiveId = id;
39
57
  }
40
58
  register(input, node) {
59
+ this.syncListboxId();
41
60
  const id = `${this.listboxId}-item-${++this.#itemCounter}`;
42
- this.registrations.push({
43
- id,
44
- node,
45
- getValue: input.getValue,
46
- getOnselect: input.getOnselect,
47
- getDisabled: input.getDisabled,
48
- });
49
- return {
61
+ const handle = $state({
50
62
  id,
51
63
  unregister: () => {
52
- const index = this.registrations.findIndex((registration) => registration.id === id);
64
+ const index = this.registrations.findIndex((registeredItem) => registeredItem.node === node);
53
65
  if (index !== -1)
54
66
  this.registrations.splice(index, 1);
55
67
  },
68
+ });
69
+ const registration = {
70
+ id,
71
+ node,
72
+ handle,
73
+ getValue: input.getValue,
74
+ getOnselect: input.getOnselect,
75
+ getDisabled: input.getDisabled,
56
76
  };
77
+ this.registrations.push(registration);
78
+ return handle;
57
79
  }
58
80
  activateItemById(id) {
59
81
  const record = this.registrations.find((registration) => registration.id === id);
@@ -122,13 +144,13 @@ export class CommandListState {
122
144
  return false;
123
145
  }
124
146
  createContext(activateItemById = (id) => void this.activateItemById(id)) {
125
- const listboxId = this.listboxId;
147
+ const getListboxId = () => this.listboxId;
126
148
  const getActiveItemId = () => this.activeItemId;
127
149
  const register = (input, node) => this.register(input, node);
128
150
  const setActiveById = (id) => this.setActiveById(id);
129
151
  return {
130
152
  get listboxId() {
131
- return listboxId;
153
+ return getListboxId();
132
154
  },
133
155
  get activeItemId() {
134
156
  return getActiveItemId();
@@ -142,3 +164,7 @@ export class CommandListState {
142
164
  export function createCommandListState(listboxId) {
143
165
  return new CommandListState(listboxId);
144
166
  }
167
+ function updateRegistrationHandleId(registration, id) {
168
+ registration.handle.id = id;
169
+ return id;
170
+ }
@@ -0,0 +1,168 @@
1
+ <script lang="ts">
2
+ import Button from '../button/button.svelte';
3
+ import { formatEditableArguments, parseJsonText } from './approval-card-state.ts';
4
+ let { idBase, requestKey, canEditArguments, argumentsValue, resolve } = $props();
5
+ const reasonId = $derived(`${idBase}-resolution-reason`);
6
+ const editorId = $derived(`${idBase}-edited-arguments`);
7
+ const editRegionId = $derived(`${idBase}-edit-region`);
8
+ const editDescriptionId = $derived(`${idBase}-edit-description`);
9
+ const editErrorId = $derived(`${idBase}-edit-error`);
10
+ let resolutionReason = $state('');
11
+ let rememberResolution = $state(false);
12
+ let editingArguments = $state(false);
13
+ let editedArgumentsText = $state('');
14
+ // A writable `$derived` that reads `requestKey` looked like the simpler
15
+ // reset mechanism, but a $derived re-runs whenever ANY parent prop update
16
+ // touches its host — not only when the tracked value actually changes —
17
+ // so it silently wiped in-progress reason text / edits on every unrelated
18
+ // host re-render. `{#key requestKey}` has the same intent but was
19
+ // unreliable in practice here (a fresh DOM node with a stale value).
20
+ // Comparing the previous value explicitly, inside the effect, is the
21
+ // one thing that's actually gated on requestKey CHANGING, not merely
22
+ // being re-touched.
23
+ let previousRequestKey = requestKey;
24
+ $effect(() => {
25
+ if (requestKey === previousRequestKey)
26
+ return;
27
+ previousRequestKey = requestKey;
28
+ resolutionReason = '';
29
+ rememberResolution = false;
30
+ // A new request must never leave a stale editor open, even if its
31
+ // arguments happen to serialize identically to the previous request's
32
+ // (the separate snapshot effect below wouldn't see a change in that
33
+ // case) — an edit must never be confirmed against the wrong request.
34
+ editingArguments = false;
35
+ editedArgumentsText = '';
36
+ });
37
+ // Separate from the identity reset above: a host can revise
38
+ // `operation.argsPreview` for the SAME request (e.g. a live update) while
39
+ // the edit panel is open. Comparing the formatted snapshot — not object
40
+ // identity, which changes on unrelated re-renders too — closes a stale
41
+ // editor whenever the underlying arguments actually change, so a confirmed
42
+ // edit can never be based on arguments older than what PayloadInspector is
43
+ // currently showing. Re-opening reseeds from the current value.
44
+ let previousArgumentsSnapshot = formatEditableArguments(argumentsValue);
45
+ $effect(() => {
46
+ const snapshot = formatEditableArguments(argumentsValue);
47
+ if (snapshot === previousArgumentsSnapshot)
48
+ return;
49
+ previousArgumentsSnapshot = snapshot;
50
+ editingArguments = false;
51
+ editedArgumentsText = '';
52
+ });
53
+ const editParseResult = $derived(parseJsonText(editedArgumentsText));
54
+ function emitResolution(decision, editedArgs) {
55
+ const trimmedReason = resolutionReason.trim();
56
+ const resolution = {
57
+ decision,
58
+ remember: rememberResolution,
59
+ };
60
+ if (decision === 'approve_with_edits') {
61
+ resolution.editedArgs = editedArgs;
62
+ }
63
+ if (trimmedReason) {
64
+ resolution.reason = trimmedReason;
65
+ }
66
+ resolve(resolution);
67
+ }
68
+ function toggleEditingArguments() {
69
+ if (!canEditArguments)
70
+ return;
71
+ if (!editingArguments) {
72
+ editedArgumentsText = formatEditableArguments(argumentsValue);
73
+ }
74
+ editingArguments = !editingArguments;
75
+ }
76
+ function handleConfirmEditedApproval() {
77
+ if (!canEditArguments || !editParseResult.ok)
78
+ return;
79
+ emitResolution('approve_with_edits', editParseResult.value);
80
+ }
81
+ </script>
82
+
83
+ <div class="cinder-approval-card__actions">
84
+ <div class="cinder-approval-card__resolution-controls">
85
+ <label class="cinder-approval-card__control-label" for={reasonId}>Reason</label>
86
+ <textarea
87
+ id={reasonId}
88
+ class="cinder-approval-card__textarea cinder-approval-card__textarea--reason"
89
+ bind:value={resolutionReason}
90
+ rows="2"
91
+ ></textarea>
92
+ </div>
93
+
94
+ <div class="cinder-approval-card__action-row" role="group" aria-label="Approval actions">
95
+ <label class="cinder-approval-card__remember-control">
96
+ <input type="checkbox" bind:checked={rememberResolution} />
97
+ <span>Don't ask again for operations like this</span>
98
+ </label>
99
+
100
+ <div class="cinder-approval-card__action-buttons">
101
+ <Button
102
+ type="button"
103
+ variant="ghost"
104
+ class="cinder-approval-card__dismiss"
105
+ onclick={() => emitResolution('cancel')}
106
+ >
107
+ Dismiss
108
+ </Button>
109
+ <Button type="button" variant="soft-danger" onclick={() => emitResolution('deny')}>
110
+ Deny
111
+ </Button>
112
+ {#if canEditArguments}
113
+ <Button
114
+ type="button"
115
+ variant="secondary"
116
+ onclick={toggleEditingArguments}
117
+ aria-expanded={editingArguments}
118
+ aria-controls={editingArguments ? editRegionId : undefined}
119
+ >
120
+ Approve with edits
121
+ </Button>
122
+ {/if}
123
+ <Button type="button" variant="primary" onclick={() => emitResolution('approve')}>
124
+ Approve
125
+ </Button>
126
+ </div>
127
+ </div>
128
+
129
+ {#if editingArguments && canEditArguments}
130
+ <div id={editRegionId} class="cinder-approval-card__editor">
131
+ <label class="cinder-approval-card__control-label" for={editorId}>
132
+ Edited arguments JSON
133
+ </label>
134
+ <p id={editDescriptionId} class="cinder-approval-card__muted">
135
+ Approving sends the parsed JSON below instead of the original arguments.
136
+ </p>
137
+ <textarea
138
+ id={editorId}
139
+ class="cinder-approval-card__textarea"
140
+ bind:value={editedArgumentsText}
141
+ rows="8"
142
+ spellcheck="false"
143
+ aria-describedby={editParseResult.ok
144
+ ? editDescriptionId
145
+ : `${editDescriptionId} ${editErrorId}`}
146
+ aria-invalid={editParseResult.ok ? undefined : 'true'}
147
+ {@attach (element) => {
148
+ element.focus();
149
+ }}
150
+ ></textarea>
151
+ {#if !editParseResult.ok}
152
+ <p id={editErrorId} class="cinder-approval-card__error" role="alert">
153
+ {editParseResult.message}
154
+ </p>
155
+ {/if}
156
+ <div class="cinder-approval-card__editor-actions">
157
+ <Button
158
+ type="button"
159
+ variant="primary"
160
+ onclick={handleConfirmEditedApproval}
161
+ disabled={!editParseResult.ok}
162
+ >
163
+ Confirm edited approval
164
+ </Button>
165
+ </div>
166
+ </div>
167
+ {/if}
168
+ </div>
@@ -1,5 +1,40 @@
1
- import type { ApprovalState } from './approval-card.types.ts';
1
+ import type { StatusDotStatus } from '../status-dot/status-dot.types.ts';
2
+ import type { ApprovalState, ApprovalToolRisk } from './approval-card.types.ts';
2
3
 
4
+ /** Character budget for the serialized arguments preview before truncation. */
5
+ export const ARGUMENTS_PREVIEW_MAX_CHARACTERS = 4_096;
6
+
7
+ /** Visible label for each risk level. */
8
+ export const RISK_LABELS = {
9
+ low: 'Low risk',
10
+ medium: 'Medium risk',
11
+ high: 'High risk',
12
+ } as const satisfies Record<ApprovalToolRisk, string>;
13
+
14
+ /** Visible label for each approval state. */
15
+ export const STATE_LABELS = {
16
+ pending: 'Pending',
17
+ approved: 'Approved',
18
+ approved_with_edits: 'Approved with edits',
19
+ denied: 'Denied',
20
+ expired: 'Expired',
21
+ cancelled: 'Cancelled',
22
+ } as const satisfies Record<ApprovalState, string>;
23
+
24
+ /** StatusDot status for each approval state. */
25
+ export const STATE_DOT_STATUS = {
26
+ pending: 'pending',
27
+ approved: 'success',
28
+ approved_with_edits: 'success',
29
+ denied: 'danger',
30
+ expired: 'neutral',
31
+ cancelled: 'offline',
32
+ } as const satisfies Record<ApprovalState, StatusDotStatus>;
33
+
34
+ /**
35
+ * Resolves the state shown to the approver: a pending approval whose
36
+ * expiration timestamp has passed presents as expired.
37
+ */
3
38
  export function resolveEffectiveApprovalState(
4
39
  approvalState: ApprovalState,
5
40
  expirationTimestamp: number | undefined,
@@ -9,6 +44,7 @@ export function resolveEffectiveApprovalState(
9
44
  return resolveComparisonTime(currentTime) >= expirationTimestamp ? 'expired' : approvalState;
10
45
  }
11
46
 
47
+ /** Whether approval actions may still be taken on the request. */
12
48
  export function isApprovalActionable(
13
49
  approvalState: ApprovalState,
14
50
  expirationTimestamp: number | undefined,
@@ -22,3 +58,118 @@ export function isApprovalActionable(
22
58
  function resolveComparisonTime(currentTime: number | undefined): number {
23
59
  return currentTime ?? Date.now();
24
60
  }
61
+
62
+ /** Parses an ISO expiration timestamp, returning undefined for invalid input. */
63
+ export function parseExpirationTimestamp(value: string | undefined): number | undefined {
64
+ if (!value) return undefined;
65
+ const timestamp = Date.parse(value);
66
+ return Number.isFinite(timestamp) ? timestamp : undefined;
67
+ }
68
+
69
+ /** Formats a millisecond duration as a compact countdown such as `2h 5m` or `45s`. */
70
+ export function formatRemainingTime(milliseconds: number): string {
71
+ const totalSeconds = Math.max(0, Math.ceil(milliseconds / 1_000));
72
+ const hours = Math.floor(totalSeconds / 3_600);
73
+ const minutes = Math.floor((totalSeconds % 3_600) / 60);
74
+ const seconds = totalSeconds % 60;
75
+
76
+ if (hours > 0) return `${hours}h ${minutes}m`;
77
+ if (minutes > 0) return `${minutes}m ${seconds}s`;
78
+ return `${seconds}s`;
79
+ }
80
+
81
+ /**
82
+ * Accepts serialized JSON strings as argument previews by parsing them into
83
+ * their structured form; any other value passes through unchanged.
84
+ */
85
+ export function normalizeArgumentsPreviewValue(value: unknown): unknown {
86
+ if (typeof value !== 'string') return value;
87
+
88
+ try {
89
+ return JSON.parse(value);
90
+ } catch {
91
+ return value;
92
+ }
93
+ }
94
+
95
+ /**
96
+ * Bounds the arguments preview: values whose serialized form exceeds the
97
+ * character budget are replaced with a truncation notice and an excerpt.
98
+ */
99
+ export function prepareArgumentsPreview(value: unknown): { value: unknown; truncated: boolean } {
100
+ try {
101
+ const serialized = JSON.stringify(value);
102
+ if (typeof serialized !== 'string' || serialized.length <= ARGUMENTS_PREVIEW_MAX_CHARACTERS) {
103
+ // Pass the original value through unchanged — including strings.
104
+ // PayloadInspector does its own parsing/display/copy handling for
105
+ // strings; re-serializing here would hand it an already-quoted JSON
106
+ // string, which displays unquoted but copies quoted (a mismatch).
107
+ return { value, truncated: false };
108
+ }
109
+ return {
110
+ value: {
111
+ notice: 'Arguments preview truncated',
112
+ originalCharacters: serialized.length,
113
+ displayedCharacters: ARGUMENTS_PREVIEW_MAX_CHARACTERS,
114
+ excerpt: serialized.slice(0, ARGUMENTS_PREVIEW_MAX_CHARACTERS),
115
+ },
116
+ truncated: true,
117
+ };
118
+ } catch {
119
+ return { value, truncated: false };
120
+ }
121
+ }
122
+
123
+ /** Serializes the arguments preview as the editable JSON seed text. */
124
+ export function formatEditableArguments(value: unknown): string {
125
+ try {
126
+ const serialized = JSON.stringify(value, null, 2);
127
+ return serialized ?? 'null';
128
+ } catch {
129
+ return '{}';
130
+ }
131
+ }
132
+
133
+ /** Parses editor text as JSON, returning a friendly error for invalid input. */
134
+ export function parseJsonText(
135
+ text: string,
136
+ ): { ok: true; value: unknown } | { ok: false; message: string } {
137
+ try {
138
+ return { ok: true, value: JSON.parse(text) };
139
+ } catch {
140
+ return { ok: false, message: 'Edited arguments must be valid JSON.' };
141
+ }
142
+ }
143
+
144
+ /**
145
+ * Reduces environment entries to unique variable names. Values accidentally
146
+ * supplied as `NAME=value` are stripped so no secret material is rendered.
147
+ */
148
+ export function sanitizeEnvironmentNames(names: string[]): string[] {
149
+ const seen = new Set<string>();
150
+ const sanitizedNames: string[] = [];
151
+
152
+ for (const name of names) {
153
+ const [firstPart] = name.split('=');
154
+ const sanitizedName = firstPart?.trim() ?? '';
155
+ if (!sanitizedName || seen.has(sanitizedName)) continue;
156
+ seen.add(sanitizedName);
157
+ sanitizedNames.push(sanitizedName);
158
+ }
159
+
160
+ return sanitizedNames;
161
+ }
162
+
163
+ /** Collapses duplicate file paths while preserving first-seen order. */
164
+ export function dedupeFilePaths(paths: string[]): string[] {
165
+ const seen = new Set<string>();
166
+ const uniquePaths: string[] = [];
167
+
168
+ for (const path of paths) {
169
+ if (seen.has(path)) continue;
170
+ seen.add(path);
171
+ uniquePaths.push(path);
172
+ }
173
+
174
+ return uniquePaths;
175
+ }