pi-roundtable-web 0.29.0 → 0.29.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (219) hide show
  1. package/CHANGELOG.md +24 -0
  2. package/dist/chunk-account-66e6ezdq.js +1 -0
  3. package/dist/{chunk-action-menu-q5y7xpry.js → chunk-action-menu-ap5xn7bf.js} +1 -1
  4. package/dist/{chunk-agent-x74xezyt.js → chunk-agent-sapt5qhn.js} +1 -1
  5. package/dist/chunk-arranged-rooms-n6bk696f.js +1 -0
  6. package/dist/chunk-attachments-p5v9gqyt.js +102 -0
  7. package/dist/chunk-bulk-actions-aze4ewc4.js +1 -0
  8. package/dist/chunk-character-creator-m7tw20ef.js +225 -0
  9. package/dist/{chunk-codeeditor-239ss6a2.js → chunk-codeeditor-yy6pq8mv.js} +2 -2
  10. package/dist/chunk-confirm-0cajsfhk.js +1 -0
  11. package/dist/chunk-connectors-tw0tbm21.js +37 -0
  12. package/dist/chunk-conversations-wkm23m5r.js +1 -0
  13. package/dist/{chunk-council-sheet-a5e6tspr.js → chunk-council-sheet-mz7s23nq.js} +2 -2
  14. package/dist/chunk-council-view-zgvzxtgn.js +1 -0
  15. package/dist/{chunk-drag-7873fvzw.js → chunk-drag-d1bpy8w6.js} +1 -1
  16. package/dist/{chunk-entry-5zmjxadx.js → chunk-entry-7zr5b1fp.js} +1 -1
  17. package/dist/{chunk-folder-list-h9hmbm8e.js → chunk-folder-list-bs4eh3g9.js} +1 -1
  18. package/dist/chunk-folds-eez1q41c.js +1 -0
  19. package/dist/{chunk-gate-fa6za28z.js → chunk-gate-dt91egcd.js} +1 -1
  20. package/dist/chunk-host-icons-nfe2t8tk.js +1 -0
  21. package/dist/chunk-host-picture-4rtswxwa.js +1 -0
  22. package/dist/chunk-host-state-1vxzmmq6.js +1 -0
  23. package/dist/chunk-host-ui-x38bf0et.js +1 -0
  24. package/dist/{chunk-index-4re5prfp.js → chunk-index-0h99xcs3.js} +2 -2
  25. package/dist/{chunk-index-5ssncptg.js → chunk-index-1kb8tv4v.js} +2 -2
  26. package/dist/chunk-index-24cggw6k.js +50 -0
  27. package/dist/chunk-index-2g8xtwqg.js +2 -0
  28. package/dist/chunk-index-3n38xe7m.js +2 -0
  29. package/dist/{chunk-index-en5dm1zv.js → chunk-index-3tksdmx7.js} +2 -2
  30. package/dist/{chunk-index-rr73h4kc.js → chunk-index-4a1tdadd.js} +3 -3
  31. package/dist/{chunk-index-f4gqzfkv.js → chunk-index-53fwc7sc.js} +2 -2
  32. package/dist/chunk-index-55ps4x5n.js +2 -0
  33. package/dist/{chunk-index-4krm48hm.js → chunk-index-5j1v2q7w.js} +1 -1
  34. package/dist/chunk-index-5w6tb7p0.js +2 -0
  35. package/dist/{chunk-index-y6p8j3zv.js → chunk-index-6btdp13p.js} +1 -1
  36. package/dist/chunk-index-6m7dwsmv.js +1 -0
  37. package/dist/{chunk-index-7c9fn21n.js → chunk-index-6rdywten.js} +2 -2
  38. package/dist/{chunk-index-gj3n4dh5.js → chunk-index-6s2pqwna.js} +2 -2
  39. package/dist/{chunk-index-r0hk9kyd.js → chunk-index-7mrkq793.js} +2 -2
  40. package/dist/chunk-index-7xcbpeqz.js +2 -0
  41. package/dist/chunk-index-88wh5eyj.js +2 -0
  42. package/dist/{chunk-index-ntt3em2k.js → chunk-index-8pbwr3rs.js} +1 -1
  43. package/dist/{chunk-index-bjeg3e2j.js → chunk-index-8wpvj7k5.js} +2 -2
  44. package/dist/chunk-index-97dcp1vh.js +1 -0
  45. package/dist/chunk-index-a7e6rhxy.js +2 -0
  46. package/dist/{chunk-index-4eag6s50.js → chunk-index-bxf8eq1s.js} +2 -2
  47. package/dist/chunk-index-c8gm1crh.js +120 -0
  48. package/dist/{chunk-index-4jnn2g09.js → chunk-index-ce7hsda9.js} +2 -2
  49. package/dist/chunk-index-cfesmk1f.js +2 -0
  50. package/dist/{chunk-index-zdzzf3fp.js → chunk-index-cmzvq3nf.js} +1 -1
  51. package/dist/{chunk-index-35zqk1zr.js → chunk-index-d4mx2vvf.js} +2 -2
  52. package/dist/chunk-index-d74tpnkd.js +2 -0
  53. package/dist/chunk-index-d941ae7c.js +2 -0
  54. package/dist/{chunk-index-rtz4936v.js → chunk-index-dr0jr7d3.js} +3 -3
  55. package/dist/{chunk-index-pcbkp62w.js → chunk-index-en728705.js} +2 -2
  56. package/dist/chunk-index-fb3kzyyp.js +2 -0
  57. package/dist/{chunk-index-a8c0ap8g.js → chunk-index-ffnd0jcj.js} +2 -2
  58. package/dist/chunk-index-fn6305vn.js +3 -0
  59. package/dist/{chunk-index-evhaaqzk.js → chunk-index-gdh7wsd5.js} +11 -11
  60. package/dist/{chunk-index-3tjmyd1h.js → chunk-index-m76gdwnk.js} +1 -1
  61. package/dist/chunk-index-mr391t49.js +2 -0
  62. package/dist/chunk-index-n3khm9fq.js +2 -0
  63. package/dist/{chunk-index-93f3e06v.js → chunk-index-nn4w6a04.js} +2 -2
  64. package/dist/{chunk-index-hef4gwtb.js → chunk-index-nr275sa7.js} +2 -2
  65. package/dist/{chunk-index-cttrqfm8.js → chunk-index-prq011b6.js} +1 -1
  66. package/dist/{chunk-index-h2a42p6s.js → chunk-index-q4k9vk04.js} +17 -1
  67. package/dist/chunk-index-rgdaec7y.js +2 -0
  68. package/dist/chunk-index-rjs1can6.js +2 -0
  69. package/dist/chunk-index-s4a8e4qm.js +2 -0
  70. package/dist/{chunk-index-q33ppq0j.js → chunk-index-sz381vda.js} +3 -3
  71. package/dist/{chunk-index-1652v386.css → chunk-index-t7csmbpy.css} +1 -1
  72. package/dist/{chunk-index-amspdq2j.js → chunk-index-v9jqyr1f.js} +1 -1
  73. package/dist/{chunk-index-e46652wf.js → chunk-index-vpq2cj14.js} +1 -1
  74. package/dist/chunk-index-vsaggfns.js +2 -0
  75. package/dist/{chunk-index-7k5895sn.js → chunk-index-w17wgjby.js} +3 -3
  76. package/dist/{chunk-index-teyx2hz7.js → chunk-index-wgrx2ybn.js} +2 -2
  77. package/dist/chunk-index-wsv46y9p.js +2 -0
  78. package/dist/{chunk-index-v6h43553.js → chunk-index-xbj816p0.js} +2 -2
  79. package/dist/{chunk-index-aycxt14t.js → chunk-index-yr758n6t.js} +2 -2
  80. package/dist/{chunk-index-pfs6rm6w.js → chunk-index-ysv36nbk.js} +2 -2
  81. package/dist/{chunk-index-haac6nbt.js → chunk-index-ze9p4npm.js} +2 -2
  82. package/dist/chunk-index-zfdvyrjt.js +2 -0
  83. package/dist/chunk-lang-css-3h22se37.js +1 -0
  84. package/dist/{chunk-lang-dockerfile-2p7e3ssz.js → chunk-lang-dockerfile-y24eejnh.js} +1 -1
  85. package/dist/{chunk-lang-go-zxp9k517.js → chunk-lang-go-qzgv1161.js} +2 -2
  86. package/dist/chunk-lang-html-9rvrmmpg.js +1 -0
  87. package/dist/chunk-lang-javascript-4kv8s3tk.js +1 -0
  88. package/dist/{chunk-lang-json-zmym50rg.js → chunk-lang-json-99v80v88.js} +1 -1
  89. package/dist/{chunk-lang-markdown-ww2kcs85.js → chunk-lang-markdown-gn8he877.js} +4 -4
  90. package/dist/{chunk-lang-python-ng1zdtd4.js → chunk-lang-python-prsw4p4k.js} +2 -2
  91. package/dist/{chunk-lang-rust-6ynhxjdd.js → chunk-lang-rust-g6xqta16.js} +1 -1
  92. package/dist/{chunk-lang-shell-39t9bz2s.js → chunk-lang-shell-dmpnzc6w.js} +1 -1
  93. package/dist/{chunk-lang-sql-w875ejpg.js → chunk-lang-sql-wz7ca27b.js} +2 -2
  94. package/dist/{chunk-lang-toml-b8ckgkg5.js → chunk-lang-toml-160prtq4.js} +1 -1
  95. package/dist/chunk-lang-typescript-mp0yw903.js +1 -0
  96. package/dist/{chunk-lang-xml-bz91cjp1.js → chunk-lang-xml-9htkz2dd.js} +1 -1
  97. package/dist/{chunk-lang-yaml-g9zy0tdv.js → chunk-lang-yaml-08749wd5.js} +1 -1
  98. package/dist/chunk-layout-actions-tdx896xf.js +1 -0
  99. package/dist/chunk-menu-items-trhybv1g.js +1 -0
  100. package/dist/chunk-mode-toggle-4dtfphq4.js +1 -0
  101. package/dist/chunk-note-row-28e5x7n8.js +233 -0
  102. package/dist/chunk-notes-5nkayhw8.js +1 -0
  103. package/dist/chunk-notice-bell-xz8a04am.js +1 -0
  104. package/dist/{chunk-notices-mtn7pg1z.js → chunk-notices-d0cwvk27.js} +1 -1
  105. package/dist/{chunk-onboarding-f3hhxgg4.js → chunk-onboarding-zs4rtea9.js} +1 -1
  106. package/dist/{chunk-overview-qmepntrr.js → chunk-overview-9sb3ywa8.js} +1 -1
  107. package/dist/{chunk-palette-edkn1ypq.js → chunk-palette-5sfhrv4x.js} +1 -1
  108. package/dist/chunk-placement-items-e2neja55.js +1 -0
  109. package/dist/{chunk-profile-pwfq0wns.js → chunk-profile-jffhtpqf.js} +1 -1
  110. package/dist/{chunk-prompt-history-xp9hmeqt.js → chunk-prompt-history-1jz2gk3v.js} +1 -1
  111. package/dist/{chunk-prompts-a56qvytg.js → chunk-prompts-0t30ttd0.js} +1 -1
  112. package/dist/chunk-room-confirms-6595921h.js +1 -0
  113. package/dist/{chunk-room-menu-1m2c2ekt.js → chunk-room-menu-hwkjyxwe.js} +1 -1
  114. package/dist/chunk-rooms-menu-button-k0eq1tcr.js +1 -0
  115. package/dist/{chunk-schedules-kwnw7p8v.js → chunk-schedules-e12y8fw2.js} +1 -1
  116. package/dist/{chunk-seat-menu-m2n9nvv0.js → chunk-seat-menu-n2bcw0mf.js} +1 -1
  117. package/dist/chunk-sheet-hosts-myvm2vhd.js +29 -0
  118. package/dist/chunk-shortcut-help-434sqnxc.js +26 -0
  119. package/dist/chunk-shortcuts-mjxph0g7.js +1 -0
  120. package/dist/chunk-skill-editor-98492yrt.js +8 -0
  121. package/dist/chunk-skills-mfv8ppfh.js +1 -0
  122. package/dist/chunk-start-over-line-m526193z.js +16 -0
  123. package/dist/{chunk-switcher-list-ehsn2wsk.js → chunk-switcher-list-5ngjar24.js} +1 -1
  124. package/dist/{chunk-tab-dot-gkpe06q8.js → chunk-tab-dot-tzjkahj5.js} +1 -1
  125. package/dist/{chunk-table-av3kh3tt.js → chunk-table-xbtbex2z.js} +1 -1
  126. package/dist/{chunk-table2d-5x3jptp9.js → chunk-table2d-61bvrykm.js} +1 -1
  127. package/dist/{chunk-table3d-rsvajx7r.js → chunk-table3d-5a7vbgyj.js} +24 -24
  128. package/dist/chunk-thread-actions-bf6vf2mt.js +1 -0
  129. package/dist/{chunk-thread-cards-grzszfha.js → chunk-thread-cards-n0n603vf.js} +1 -1
  130. package/dist/chunk-thread-list-7bkdn51x.js +227 -0
  131. package/dist/{chunk-transcript-t5szb8r0.js → chunk-transcript-8ztrkt6g.js} +1 -1
  132. package/dist/chunk-waiting-chip-y83c90v3.js +32 -0
  133. package/dist/chunk-waiting-s273kcgz.js +1 -0
  134. package/dist/chunk-where-jr791gzj.js +1 -0
  135. package/dist/chunk-workspace-dw71mshw.js +586 -0
  136. package/dist/chunk-zh-tw-vm5d0w6j.js +1 -0
  137. package/dist/index.html +1 -1
  138. package/dist/sw.js +1 -1
  139. package/package.json +2 -2
  140. package/src/api-types.ts +12 -0
  141. package/src/app/app.ts +7 -0
  142. package/src/app/card-log.ts +10 -2
  143. package/src/app/protocol.ts +18 -0
  144. package/src/app/queued-delivery.ts +107 -0
  145. package/src/app/queued-frames.ts +115 -0
  146. package/src/app/room-log.ts +39 -7
  147. package/src/app/routes.ts +97 -5
  148. package/src/app/socket.ts +12 -2
  149. package/src/app/surface.ts +37 -6
  150. package/src/app/zip.ts +124 -0
  151. package/src/auth/sessions.ts +9 -1
  152. package/src/host/cards.ts +10 -3
  153. package/src/host/stored-json.ts +23 -0
  154. package/src/i18n/zh-tw.ts +14 -0
  155. package/src/notices/mount.ts +1 -0
  156. package/src/notices/store.ts +9 -1
  157. package/src/web-plugin.ts +4 -1
  158. package/dist/chunk-account-9616x405.js +0 -1
  159. package/dist/chunk-arranged-rooms-9prq46vh.js +0 -1
  160. package/dist/chunk-bulk-actions-5dc4m9ad.js +0 -1
  161. package/dist/chunk-character-creator-wf02eg0h.js +0 -1
  162. package/dist/chunk-confirm-bhrx9195.js +0 -1
  163. package/dist/chunk-connectors-k77pd9by.js +0 -37
  164. package/dist/chunk-conversations-ftcpaqw1.js +0 -1
  165. package/dist/chunk-council-view-6593rqbr.js +0 -1
  166. package/dist/chunk-folds-vxq86t1s.js +0 -1
  167. package/dist/chunk-host-icons-y6frbzqt.js +0 -1
  168. package/dist/chunk-host-picture-fqg55rbr.js +0 -1
  169. package/dist/chunk-host-state-65tdhkyq.js +0 -1
  170. package/dist/chunk-host-ui-233kz7qp.js +0 -1
  171. package/dist/chunk-index-2c00zf3z.js +0 -2
  172. package/dist/chunk-index-2dhrqvba.js +0 -2
  173. package/dist/chunk-index-2s4bkrz3.js +0 -2
  174. package/dist/chunk-index-2ypaqwjy.js +0 -2
  175. package/dist/chunk-index-39qq37j5.js +0 -2
  176. package/dist/chunk-index-57teqgct.js +0 -2
  177. package/dist/chunk-index-9m9v1p7s.js +0 -2
  178. package/dist/chunk-index-a8nqn3y0.js +0 -3
  179. package/dist/chunk-index-am7ghh75.js +0 -120
  180. package/dist/chunk-index-amxa2bn3.js +0 -2
  181. package/dist/chunk-index-dajanzxc.js +0 -1
  182. package/dist/chunk-index-e2eeckhh.js +0 -2
  183. package/dist/chunk-index-ek98d2rn.js +0 -2
  184. package/dist/chunk-index-gp4chnp3.js +0 -2
  185. package/dist/chunk-index-mg96sqpk.js +0 -2
  186. package/dist/chunk-index-nsya88fn.js +0 -1
  187. package/dist/chunk-index-smz90j6p.js +0 -2
  188. package/dist/chunk-index-vzqwn3wp.js +0 -2
  189. package/dist/chunk-index-wt2asefx.js +0 -50
  190. package/dist/chunk-index-x4tq9btg.js +0 -2
  191. package/dist/chunk-index-yvcdg5hh.js +0 -2
  192. package/dist/chunk-index-zeqfnkty.js +0 -2
  193. package/dist/chunk-index-zpwb8mkk.js +0 -2
  194. package/dist/chunk-lang-css-avzhvm72.js +0 -1
  195. package/dist/chunk-lang-html-red02gep.js +0 -1
  196. package/dist/chunk-lang-javascript-n33kmjcx.js +0 -1
  197. package/dist/chunk-lang-typescript-qf8acbb2.js +0 -1
  198. package/dist/chunk-layout-actions-fyzzzeyp.js +0 -1
  199. package/dist/chunk-menu-items-yvnk3vds.js +0 -1
  200. package/dist/chunk-mode-toggle-ccv271hm.js +0 -1
  201. package/dist/chunk-note-row-314py1pp.js +0 -204
  202. package/dist/chunk-notes-4rnrddzw.js +0 -1
  203. package/dist/chunk-notice-bell-z9wgamnz.js +0 -1
  204. package/dist/chunk-placement-items-trsa5t23.js +0 -1
  205. package/dist/chunk-room-confirms-gqpkz4h0.js +0 -1
  206. package/dist/chunk-rooms-menu-button-tcvda1gq.js +0 -1
  207. package/dist/chunk-sheet-hosts-pr8xktyq.js +0 -29
  208. package/dist/chunk-shortcut-help-sbvrds1m.js +0 -26
  209. package/dist/chunk-shortcuts-8705p7q3.js +0 -1
  210. package/dist/chunk-skill-editor-7xy09sq1.js +0 -8
  211. package/dist/chunk-skills-cnc25x7q.js +0 -1
  212. package/dist/chunk-start-over-line-97zdd9pb.js +0 -16
  213. package/dist/chunk-thread-actions-7xtkegwm.js +0 -1
  214. package/dist/chunk-thread-list-9bjjac3j.js +0 -217
  215. package/dist/chunk-waiting-chip-d8b6a0p8.js +0 -28
  216. package/dist/chunk-waiting-ts3kxjvv.js +0 -1
  217. package/dist/chunk-where-3d3ncsa5.js +0 -1
  218. package/dist/chunk-workspace-ct6hvn0z.js +0 -578
  219. package/dist/chunk-zh-tw-v9v1eerm.js +0 -1
package/CHANGELOG.md CHANGED
@@ -5,6 +5,30 @@ The format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
5
5
 
6
6
  ## [Unreleased]
7
7
 
8
+ ## [0.29.1] - 2026-10-31
9
+
10
+ ### Added
11
+
12
+ - A message's files are one attachment block: a heading "Attachments (N)" in a bordered box unlike inline code, each file a full-width chip with its icon, name and size, on phones and desktops. Agent rooms, host rooms, notes and the round table's dialogue box all show it; a host room still says how many files were removed.
13
+ - "Download all" in the heading of a message with two or more files downloads them as one zip, from `GET api/files/zip?room=<room>&message=<id>`. The route answers the room and each file as the single file route does, so someone who may not read the room gets the same refusal. It packs only the files still kept, each under its own name (a repeated name becomes `name-2`, `name-3`), in `attachments-<YYYYMMDD-HHMM>.zip` (the message's UTC time), stored without compression, and refuses past 200 MB with a message to download the files one by one. The zip is named after when the message was sent on the host's clock (`attachments-20261031-2028.zip`); `OwnerAppOptions.timeZone` and `AppApiOptions.timeZone` carry the host's zone, UTC when absent.
14
+ - A bubble with files that is taller than about one screen opens with a paperclip line "N attachments", which scrolls to the block, smoothly unless the person asked for less motion.
15
+
16
+ ### Changed
17
+
18
+ - A swipe right opens the room drawer from anywhere in the left half of the screen, the left edge included, over the header and empty space as well as over the messages. It was the messages only, and not within 32 px of either edge. The right edge stays the system's Back, and the drawer closes by a swipe left from anywhere but there.
19
+ - Host rooms have the drawer too: the swipe, and a tap on the room's picture in the header. The waiting-cards strip of a host room moved to its own file.
20
+ - A message of yours sent while a turn runs shows where it stands under it, live and after a reload: "Added to this turn" when the running turn took it, "Queued" while it waits for its own turn (the line goes when the turn starts), and "Cancelled" for one you cancelled, which stays in the room dimmed and never runs. A queued message's long-press or right-click menu offers its author Edit (a sheet with the text; the turn runs on the new text and the message shows as edited) and Cancel. Once the turn has started a notice says it is too late. `RoomMessage.delivery` carries the state (`steered` and `cancelled` are stored, in a new `delivery` column; `queued` is read from the host's queue and so does not outlive a restart); client frames `edit_queued` and `cancel_queued` (`room`, `message` id, `text`) answer with the changed message as an `edited` frame or a `refused` frame (`not_queued` when the turn has started, `forbidden` for another person's message). With a core that has no `ConversationPort.cancelQueued` and `editQueued`, both answer `not_queued`.
21
+ - Pressing ↑ in an empty message box opens Edit on your latest message in the room that still waits for its turn (not while an input method composes; Alt+↑ / Alt+↓ still switch rooms), and the `?` shortcut list names it.
22
+ - The round table's camera turns to a member by the same rule as the spotlight: only when their words show. A member who only thinks or works no longer takes it when the previous speaker's words finish; the camera stays on whoever spoke last until the next member's words start.
23
+
24
+ ### Fixed
25
+
26
+ - jsonb columns are stored as JSON values: a room message's `files`, `picture` and `intercom`, an ended card's `frame` and `answer`, a host card, a notice's `open` and a session's actor were stored as JSON strings. Migrations (`web-room-messages-json-values`, `web-room-cards-json-values`, `web-host-cards-json-values`, `web-notices-json-values`, `web-sessions-json-values`) convert the rows stored that way; reads still take either.
27
+ - Buttons with a quiet look of their own no longer turn into unreadable text on the accent fill when hovered or, on a phone, after a tap: the "N earlier tools" chip, the character creator's tiles, the files pane's folder twist and image toggle, the host room's cards toggle and seen faces, and a knight's temp knights header now say what hover does to them. A test fails for any new button that sets its own fill or text colour without a hover rule.
28
+ - The character creator's styles load with the creator instead of with the page, which leaves room in what the page loads first.
29
+ - The room drawer opens on a phone. A swipe right in a room never reached the page in Chrome: the room had the default `touch-action`, so Chrome took a sideways drag for itself a few pixels in and cancelled the touch before the swipe was 24 px long. The room, its message list, the composer and the drawer's own list now allow only up-down panning and pinch zoom, which leaves sideways drags to the page. A swipe that starts in a sideways-scrolling code block or table, a field, a card's option row, a sheet over the page, or a scene that takes every touch is still not the room's.
30
+ - Two edits of a waiting message from two sockets reach the room's log in the order the host took them, so the room shows the text the turn runs.
31
+
8
32
  ## [0.29.0] - 2026-10-31
9
33
 
10
34
  ### Added
@@ -0,0 +1 @@
1
+ import{p,T,x,e,v}from"./chunk-index-24cggw6k.js";var a={profile:x(()=>(p("jffhtpqf"),import("./chunk-profile-jffhtpqf.js")).then((o)=>({default:o.ProfilePage}))),notices:x(()=>(p("d0cwvk27"),import("./chunk-notices-d0cwvk27.js")).then((o)=>({default:o.NoticesPage}))),onboarding:x(()=>(p("zs4rtea9"),import("./chunk-onboarding-zs4rtea9.js")).then((o)=>({default:o.OnboardingPage})))};function n({pane:o}){let t=a[o];return t?e(T,{fallback:e(v,{}),children:e(t,{})}):null}export{n as default};
@@ -1 +1 @@
1
- import{o,Ne,a,r,g,e,n,s,wt,es}from"./chunk-index-wt2asefx.js";import{R}from"./chunk-index-zdzzf3fp.js";var L=()=>typeof matchMedia==="function"&&matchMedia("(max-width: 719px)").matches,k={rtMenu:!0},x=()=>Boolean(window.history.state?.rtMenu),w=8,E=(t)=>t?.isConnected?t:null;function M(t){return t.items.map((i)=>n("button",{type:"button",role:i.checked===void 0?"menuitem":"menuitemcheckbox",...i.checked===void 0?{}:{"aria-checked":i.checked},className:"menu-item menu-link","data-tone":i.tone,onClick:()=>t.onChoose(i),children:[i.icon?e("span",{className:"menu-icon","data-tone":i.tone,children:e(s,{name:i.icon,size:18})}):null,e("span",{className:"menu-text",children:e("strong",{children:i.label})}),i.checked?e(s,{name:"check",size:18,className:"menu-check"}):null]},i.id))}function H({menu:t}){let i=a(void 0);if(t)i.current=t;let l=i.current,m=a(!1),h=a(void 0),p=t?.serial;return o(()=>{if(p===void 0)return;return window.history.pushState(k,"",window.location.href),m.current=!0,()=>{if(m.current)m.current=!1,window.history.back()}},[p]),o(()=>{let f=()=>{if(!m.current||x())return;m.current=!1,wt();let y=h.current;h.current=void 0,y?.()};return window.addEventListener("popstate",f),()=>window.removeEventListener("popstate",f)},[]),e(R,{open:t!==void 0,title:l?.title??"",onClose:wt,restoreFocus:()=>E(l?.source??null),children:l?e("div",{className:"menu action-items",role:"menu","aria-label":l.title,children:e(M,{items:l.items,onChoose:(f)=>{if(!m.current){wt(),f.run();return}h.current=f.run,window.history.back()}})}):null})}function T({menu:t}){let i=a(null),[l,m]=r(t.at),{source:h}=t,p=(u)=>{E(h)?.focus(),wt(),u?.()},f=a(p);f.current=p,Ne(()=>{let u=i.current;if(!u)return;let d={left:u.style.left,top:u.style.top};u.style.left="0px",u.style.top="0px";let c={width:u.offsetWidth,height:u.offsetHeight};u.style.left=d.left,u.style.top=d.top,m({x:Math.max(w,Math.min(t.at.x,window.innerWidth-c.width-w)),y:Math.max(w,Math.min(t.at.y,window.innerHeight-c.height-w))}),u.querySelector('[role^="menuitem"]')?.focus()},[t.serial]),o(()=>{let u=(c)=>{if(c.target instanceof Node&&i.current?.contains(c.target))return;wt()},d=()=>wt();return document.addEventListener("pointerdown",u,!0),document.addEventListener("wheel",u,{capture:!0,passive:!0}),document.addEventListener("touchmove",u,{capture:!0,passive:!0}),window.addEventListener("resize",d),()=>{document.removeEventListener("pointerdown",u,!0),document.removeEventListener("wheel",u,!0),document.removeEventListener("touchmove",u,!0),window.removeEventListener("resize",d)}},[]);let y=(u)=>{let d=[...i.current?.querySelectorAll('[role^="menuitem"]')??[]],c=d.indexOf(document.activeElement),v=(b)=>{u.preventDefault(),d[(b+d.length)%d.length]?.focus()};switch(u.key){case"Escape":u.preventDefault(),u.stopPropagation(),f.current();return;case"ArrowDown":return v(c+1);case"ArrowUp":return v(c<0?-1:c-1);case"Tab":return v(u.shiftKey?c<0?-1:c-1:c+1);case"Home":return v(0);case"End":return v(-1)}};return e("div",{ref:i,className:"action-popover",role:"menu","aria-label":t.title,tabIndex:-1,style:{left:`${l.x}px`,top:`${l.y}px`},onKeyDown:y,children:e(M,{items:t.items,onChoose:(u)=>p(u.run)})})}function I(){let t=es(),i=a(void 0);if(t&&i.current?.serial!==t.serial)i.current={serial:t.serial,sheet:L()};let l=Boolean(t&&i.current?.sheet);return n(g,{children:[e(H,{menu:l?t:void 0}),t&&!l?e(T,{menu:t},t.serial):null]})}export{I as ActionMenuHost};
1
+ import{o,Te,a,r,g,e,n,s,wt,ds}from"./chunk-index-24cggw6k.js";import{R}from"./chunk-index-cmzvq3nf.js";var L=()=>typeof matchMedia==="function"&&matchMedia("(max-width: 719px)").matches,k={rtMenu:!0},x=()=>Boolean(window.history.state?.rtMenu),w=8,E=(t)=>t?.isConnected?t:null;function M(t){return t.items.map((i)=>n("button",{type:"button",role:i.checked===void 0?"menuitem":"menuitemcheckbox",...i.checked===void 0?{}:{"aria-checked":i.checked},className:"menu-item menu-link","data-tone":i.tone,onClick:()=>t.onChoose(i),children:[i.icon?e("span",{className:"menu-icon","data-tone":i.tone,children:e(s,{name:i.icon,size:18})}):null,e("span",{className:"menu-text",children:e("strong",{children:i.label})}),i.checked?e(s,{name:"check",size:18,className:"menu-check"}):null]},i.id))}function H({menu:t}){let i=a(void 0);if(t)i.current=t;let l=i.current,m=a(!1),h=a(void 0),p=t?.serial;return o(()=>{if(p===void 0)return;return window.history.pushState(k,"",window.location.href),m.current=!0,()=>{if(m.current)m.current=!1,window.history.back()}},[p]),o(()=>{let f=()=>{if(!m.current||x())return;m.current=!1,wt();let y=h.current;h.current=void 0,y?.()};return window.addEventListener("popstate",f),()=>window.removeEventListener("popstate",f)},[]),e(R,{open:t!==void 0,title:l?.title??"",onClose:wt,restoreFocus:()=>E(l?.source??null),children:l?e("div",{className:"menu action-items",role:"menu","aria-label":l.title,children:e(M,{items:l.items,onChoose:(f)=>{if(!m.current){wt(),f.run();return}h.current=f.run,window.history.back()}})}):null})}function T({menu:t}){let i=a(null),[l,m]=r(t.at),{source:h}=t,p=(u)=>{E(h)?.focus(),wt(),u?.()},f=a(p);f.current=p,Te(()=>{let u=i.current;if(!u)return;let d={left:u.style.left,top:u.style.top};u.style.left="0px",u.style.top="0px";let c={width:u.offsetWidth,height:u.offsetHeight};u.style.left=d.left,u.style.top=d.top,m({x:Math.max(w,Math.min(t.at.x,window.innerWidth-c.width-w)),y:Math.max(w,Math.min(t.at.y,window.innerHeight-c.height-w))}),u.querySelector('[role^="menuitem"]')?.focus()},[t.serial]),o(()=>{let u=(c)=>{if(c.target instanceof Node&&i.current?.contains(c.target))return;wt()},d=()=>wt();return document.addEventListener("pointerdown",u,!0),document.addEventListener("wheel",u,{capture:!0,passive:!0}),document.addEventListener("touchmove",u,{capture:!0,passive:!0}),window.addEventListener("resize",d),()=>{document.removeEventListener("pointerdown",u,!0),document.removeEventListener("wheel",u,!0),document.removeEventListener("touchmove",u,!0),window.removeEventListener("resize",d)}},[]);let y=(u)=>{let d=[...i.current?.querySelectorAll('[role^="menuitem"]')??[]],c=d.indexOf(document.activeElement),v=(b)=>{u.preventDefault(),d[(b+d.length)%d.length]?.focus()};switch(u.key){case"Escape":u.preventDefault(),u.stopPropagation(),f.current();return;case"ArrowDown":return v(c+1);case"ArrowUp":return v(c<0?-1:c-1);case"Tab":return v(u.shiftKey?c<0?-1:c-1:c+1);case"Home":return v(0);case"End":return v(-1)}};return e("div",{ref:i,className:"action-popover",role:"menu","aria-label":t.title,tabIndex:-1,style:{left:`${l.x}px`,top:`${l.y}px`},onKeyDown:y,children:e(M,{items:t.items,onChoose:(u)=>p(u.run)})})}function I(){let t=ds(),i=a(void 0);if(t&&i.current?.serial!==t.serial)i.current={serial:t.serial,sheet:L()};let l=Boolean(t&&i.current?.sheet);return n(g,{children:[e(H,{menu:l?t:void 0}),t&&!l?e(T,{menu:t},t.serial):null]})}export{I as ActionMenuHost};
@@ -1 +1 @@
1
- import{o,e,X,d,v,Ye}from"./chunk-index-wt2asefx.js";function g({name:r}){let m=d((i)=>i.listed),t=d((i)=>Object.values(i.rooms).find((n)=>n.view?.kind==="agent"&&n.view.name===r)?.view?.key,r);return o(()=>{if(t)X("room",t,{replace:!0}),Ye(r);else if(m)X("rooms",void 0,{replace:!0})},[t,m,r]),e("div",{className:"page",children:e(v,{})})}export{g as AgentPage};
1
+ import{o,e,X,d,v,Ye}from"./chunk-index-24cggw6k.js";function g({name:r}){let m=d((i)=>i.listed),t=d((i)=>Object.values(i.rooms).find((n)=>n.view?.kind==="agent"&&n.view.name===r)?.view?.key,r);return o(()=>{if(t)X("room",t,{replace:!0}),Ye(r);else if(m)X("rooms",void 0,{replace:!0})},[t,m,r]),e("div",{className:"page",children:e(v,{})})}export{g as AgentPage};
@@ -0,0 +1 @@
1
+ import{p,T,x,ee,C,a,t,g,e,n,s,Ae,d,k,_,ge,jt,xn,te,yr,Qi,Jr,Xt,Mi,eo}from"./chunk-index-24cggw6k.js";import{ze}from"./chunk-index-3n38xe7m.js";import{yi}from"./chunk-index-d74tpnkd.js";import"./chunk-index-5j1v2q7w.js";import"./chunk-index-nr275sa7.js";import{ci}from"./chunk-index-fb3kzyyp.js";import{mi,gi}from"./chunk-index-sz381vda.js";import{Zt}from"./chunk-index-bxf8eq1s.js";import"./chunk-index-5w6tb7p0.js";import"./chunk-index-yr758n6t.js";import{st}from"./chunk-index-6rdywten.js";mi();var M=x(()=>(p("bs4eh3g9"),import("./chunk-folder-list-bs4eh3g9.js")).then((o)=>({default:o.FolderList}))),O=ee(function(l){let{view:r}=l,f=Zt(()=>jt(r.key),r.home?void 0:gi(r.key));return e(Jr,{...l,press:f,item:{...r.home?{}:{"data-drop-item":"","data-key":r.key},...l.arranging?{"data-arranging":""}:{}},after:l.arranging?e("button",{type:"button",className:"icon-button row-more","aria-haspopup":"menu","aria-label":t("Room menu"),onClick:(c)=>{let u=c.currentTarget;jt(r.key).then((i)=>{if(!i)return;let y=u.getBoundingClientRect();ge({...i,at:{x:y.left,y:y.bottom},via:"key",source:u})},()=>{return})},children:e(s,{name:"more",size:18})}):null})});function L(o){let{now:l}=te(),{timeZone:r}=_(),f=Xt(o.rooms);return e("ul",{className:"room-list",children:f.map(({key:c,...u})=>{let i=o.threads[c];return e(O,{...u,active:c===o.active,now:l,timeZone:r,arranging:o.arranging,...i?{threads:e(Mi,{open:i.open,closed:i.closed,active:o.active,parent:c})}:{}},c)})})}function v(o){let r=Xt(o.rooms).length===0;if(r&&o.zone?.kind!=="pinned")return null;return n("section",{className:"stack",...r?{"data-empty":""}:{},...o.zone?{"data-drop-zone":o.zone.kind,"data-zone-id":o.zone.id}:{},children:[e("h2",{className:"section-title",children:o.title}),r?null:e(L,{rooms:o.rooms,threads:o.threads,active:o.active,arranging:o.arranging})]})}function re(o){let l=Boolean(_().kinds?.length),r=d((m)=>JSON.stringify({listed:m.listed,...st(m,(F)=>Ae(m,F))})),f=yi(),c=a(r);if(!f)c.current=r;let u=c.current,{listed:i,...y}=C(()=>JSON.parse(u),[u]),{home:w,pinned:z,folders:N,restAgents:P,restGroups:D,rest:S,threads:A,orphans:h}=y,R=yr(),K=w.length+z.length+S.length===0&&N.every((m)=>m.rooms.length===0)&&h.open.length+h.closed.length===0,b={threads:A,active:o.active,arranging:R};return n("div",{className:"page","data-column":o.active?"":void 0,"data-drop-root":"",children:[n("header",{className:"page-head",children:[e("h1",{children:t("Rooms")}),n("div",{className:"actions",children:[n("button",{type:"button",className:"header-button search-button",onClick:o.onSearch,children:[e(s,{name:"search",size:16}),e("span",{children:t("Find a room")}),e("kbd",{children:"⌘K"})]}),i?e("button",{type:"button",className:"header-button icon-button","aria-haspopup":"menu","aria-label":t("Folders and order"),onClick:(m)=>ci(m.currentTarget),children:e(s,{name:"more",size:18})}):null,e("button",{type:"button",className:"header-button icon-button","aria-label":t("Add"),"aria-haspopup":"menu",onClick:(m)=>xn(m.currentTarget),children:e(s,{name:"plus"})})]})]}),R?n("div",{className:"arrange-bar",children:[n("button",{type:"button",className:"secondary",onClick:()=>ze({kind:"new"}),children:[e(s,{name:"plus",size:16}),e("span",{children:t("Add a folder")})]}),e("button",{type:"button",onClick:()=>Qi(!1),children:t("Done")})]}):null,i&&K&&!l?e(k,{children:t("No rooms yet. Rooms appear when the team has a knight.")}):null,!i?n("div",{className:"stack","aria-busy":"true",children:[e("div",{className:"skeleton"}),e("div",{className:"skeleton"}),e("div",{className:"skeleton"})]}):null,e(v,{title:t("Home"),rooms:w,...b}),e(v,{title:t("Pinned"),rooms:z,zone:{kind:"pinned",id:"pinned"},...b}),N.length>0?e("div",{className:"stack folder-list","data-folder-list":"",children:e(T,{fallback:e("div",{className:"skeleton","aria-busy":"true"}),children:e(M,{folders:N,active:o.active,listed:i,rooms:(m)=>e(L,{rooms:m,threads:A,active:o.active,arranging:R})})})}):null,N.length>0?e(v,{title:t("Ungrouped"),rooms:S,zone:{kind:"rest",id:"rest"},...b}):n(g,{children:[e(v,{title:t("Knights"),rooms:P,zone:{kind:"rest",id:"rest-agents"},...b}),e(v,{title:t("Groups"),rooms:D,zone:{kind:"rest",id:"rest-groups"},...b})]}),h.open.length+h.closed.length>0?n("section",{className:"stack",children:[e("h2",{className:"section-title",children:t("Dispatch threads")}),e(Mi,{open:h.open,closed:h.closed,active:o.active})]}):null,e(eo,{active:o.active})]})}export{re as ArrangedRoomsPage};
@@ -0,0 +1,102 @@
1
+ import{Te,a,r,t,G,e,n,s,Se,Wt,ls,Pe,$t,Os}from"./chunk-index-24cggw6k.js";import{Y}from"./chunk-index-d941ae7c.js";var u=`
2
+ .attachments {
3
+ margin-top: var(--space-3);
4
+ padding: var(--space-2);
5
+ border: 1px solid var(--border-strong);
6
+ border-radius: var(--radius);
7
+ background: var(--bg);
8
+ color: var(--text);
9
+ min-width: 0;
10
+ scroll-margin-top: var(--space-6);
11
+ }
12
+
13
+ .bubble > .attachments:first-child {
14
+ margin-top: 0;
15
+ }
16
+
17
+ .attachments-head {
18
+ display: flex;
19
+ align-items: center;
20
+ gap: var(--space-2);
21
+ min-height: 2rem;
22
+ padding: 0 var(--space-1);
23
+ font-size: var(--text-sm);
24
+ font-weight: 600;
25
+ }
26
+
27
+ .attachments-head > span {
28
+ flex: 1;
29
+ min-width: 0;
30
+ }
31
+
32
+ .attachments .link-button {
33
+ display: inline-flex;
34
+ align-items: center;
35
+ gap: var(--space-1);
36
+ border: 1px solid transparent;
37
+ border-radius: var(--radius);
38
+ font-size: var(--text-sm);
39
+ font-weight: 500;
40
+ text-decoration: none;
41
+ white-space: nowrap;
42
+ }
43
+
44
+ .attachments .files {
45
+ flex-direction: column;
46
+ flex-wrap: nowrap;
47
+ margin-top: var(--space-1);
48
+ }
49
+
50
+ .attachments .file-chip {
51
+ display: flex;
52
+ width: 100%;
53
+ box-sizing: border-box;
54
+ min-height: 2.75rem;
55
+ border: 1px solid var(--border);
56
+ border-radius: var(--radius);
57
+ background: var(--surface);
58
+ font-family: inherit;
59
+ }
60
+
61
+ .attachments .file-chip > svg {
62
+ flex: none;
63
+ color: var(--accent);
64
+ }
65
+
66
+ .attachments .file-name {
67
+ flex: 1;
68
+ min-width: 0;
69
+ overflow: hidden;
70
+ text-overflow: ellipsis;
71
+ white-space: nowrap;
72
+ }
73
+
74
+ .attachments .file-size {
75
+ flex: none;
76
+ color: var(--muted);
77
+ font-size: var(--text-xs);
78
+ font-variant-numeric: tabular-nums;
79
+ }
80
+
81
+ .message[data-mine] .attachments .file-chip {
82
+ background: var(--surface);
83
+ color: var(--text);
84
+ }
85
+
86
+ .attachments-jump {
87
+ display: inline-flex;
88
+ align-items: center;
89
+ gap: var(--space-1);
90
+ margin: 0 0 var(--space-2);
91
+ font-size: var(--text-sm);
92
+ }
93
+
94
+ .attachments-jump[hidden] {
95
+ display: none;
96
+ }
97
+
98
+ .message[data-mine] .attachments-jump {
99
+ color: inherit;
100
+ text-decoration: underline;
101
+ }
102
+ `;function h({file:o}){let i=$t(()=>Os(o));return o.type.startsWith("image/")?e("li",{children:e("a",{...i,href:Wt(o),target:"_blank",rel:"noreferrer noopener",children:e("img",{src:Wt(o),alt:o.name,loading:"lazy",decoding:"async",className:"file-image"})})}):e("li",{children:n("a",{...i,className:"file-chip",href:Wt(o),download:o.name,title:o.name,children:[e(s,{name:"file",size:16}),e("span",{className:"file-name",children:o.name}),e("span",{className:"file-size",children:Pe(o.size)})]})})}function f(o){Y("attachments",u);let{files:i,message:m}=o;return n("section",{className:"attachments","aria-label":t("Attachments ({count})",{count:i.length}),children:[n("div",{className:"attachments-head",children:[e(s,{name:"attach",size:16}),e("span",{children:t("Attachments ({count})",{count:i.length})}),m&&i.length>=2?n("a",{className:"link-button",href:ls(m),download:!0,children:[e(s,{name:"download",size:16}),t("Download all")]}):null]}),e("ul",{className:"files",children:i.map((c)=>e(h,{file:c},c.id))})]})}var g=0.9;function A({count:o}){Y("attachments",u);let i=a(null),[m,c]=r(!1);return Te(()=>{let l=i.current?.closest(".bubble");if(!l)return;let d=()=>c(l.getBoundingClientRect().height>window.innerHeight*g);d(),window.addEventListener("resize",d);let p=typeof ResizeObserver==="function"?new ResizeObserver(d):void 0;return p?.observe(l),()=>{window.removeEventListener("resize",d),p?.disconnect()}},[]),n("button",{ref:i,type:"button",className:"link-button attachments-jump",hidden:!m,onClick:(l)=>{l.stopPropagation(),i.current?.closest(".bubble")?.querySelector(".attachments")?.scrollIntoView({behavior:Se()?"auto":"smooth",block:"start"})},children:[e(s,{name:"attach",size:14}),G(o,"{count} attachment","{count} attachments")]})}export{A as AttachmentsJump,f as default};
@@ -0,0 +1 @@
1
+ import{t,G,O,l,f}from"./chunk-index-24cggw6k.js";import{sn}from"./chunk-index-nr275sa7.js";import"./chunk-index-5j1v2q7w.js";import{Qn,so}from"./chunk-index-ysv36nbk.js";import{So}from"./chunk-index-5w6tb7p0.js";import{re}from"./chunk-index-wgrx2ybn.js";import"./chunk-index-yr758n6t.js";var s=500,c=(n)=>{let r=[];for(let e=0;e<n.length;e+=s)r.push(n.slice(e,e+s));return r},i=()=>O.dispatch({type:"changed"});async function w(n){let r=So(n),e=Object.keys(r);if(e.length===0)return;let a=[];try{for(let o of c(e))a.push(...(await Qn.readAll(o)).moved)}catch(o){f(l(o),"danger"),i();return}sn(Object.fromEntries(e.map((o)=>[o,0]))),f(G(e.length,"Marked {count} room as read","Marked {count} rooms as read"),"info",a.length?{label:t("Undo"),run:()=>void m(a,r)}:void 0)}async function m(n,r){try{for(let e of c(n)){let{restored:a}=await Qn.unreadAll(e);sn(Object.fromEntries(a.map((o)=>[o,r[o]??0])))}}catch(e){f(l(e),"danger")}i()}var P=(n)=>so(n);async function d(n){try{await Qn.restoreHelpers(n)}catch(r){f(l(r),"danger")}i()}async function R(n){let r;try{r=(await Qn.archiveFinishedHelpers(n)).archived.flatMap((a)=>a.names)}catch(e){f(l(e),"danger"),i();return}if(i(),r.length===0)return;f(G(r.length,"Archived {count} temp knight","Archived {count} temp knights"),"info",{label:t("Undo"),run:()=>void d(r)})}async function T(n,r){try{await re.archiveAgent(n)}catch(e){f(l(e),"danger"),i();return}i(),f(t("Archived {name}",{name:r}),"info",{label:t("Undo"),run:()=>void d([n])})}export{T as archiveHelper,P as clearAllFinished,R as clearFinishedHelpers,w as markAllRead,d as putBackHelpers};
@@ -0,0 +1,225 @@
1
+ import{je,Jt,W,Ri,Pn}from"./chunk-index-7mrkq793.js";import{ee,Fr,o,L,C,a,r,t,u,g,e,n,xi,fe,y,l,f,Qe,Sn,he,Je}from"./chunk-index-24cggw6k.js";import{D}from"./chunk-index-6btdp13p.js";import{R}from"./chunk-index-cmzvq3nf.js";import{Y}from"./chunk-index-d941ae7c.js";var ue={"hat.none":"No hat","hat.goggcap":"Leather cap","hat.tallcap":"Burgundian felt cap","hat.softcap":"Soft cap","hat.hardhat":"Iron skullcap","hat.fcap":"Hunter's cap","hat.winghelm":"Winged helm","hat.helm":"Helm","hat.mortar":"Biretta","hat.beret":"Chaperon","hat.goggles":"Pointed cap","hat.tricorn":"Pilgrim hat","hat.sailor":"Straw hat","hat.kettle":"Kettle hat","hat.cavalier":"Feathered hat","hat.toque":"Linen cook's cap","hair.none":"No hair","beard.none":"No beard","accessory.none":"No accessory","prop.beads":"Prayer beads","prop.marotte":"Marotte","prop.map":"Chart","prop.flask":"Alchemist's phial","prop.telescope":"Astrolabe","prop.wrench":"Dividers","outfit.surplice":"Surplice","outfit.overalls":"Work jerkin","outfit.armor":"Mail hauberk","outfit.apron":"Smith's apron","outfit.chef":"Cook's tunic","outfit.coat":"Doublet","outfit.vest":"Pourpoint","outfit.sailor":"Mariner's tunic","hair.bob":"Bob","hair.bun":"Bun","hair.ponytail":"Ponytail"},X=(i)=>i.charAt(0).toUpperCase()+i.slice(1);function x(i,c){let h=`character.${i}.${c}`,p=t(h);if(p!==h)return p;if(i==="class")return W.classes[c]?.label??X(c);return ue[`${i}.${c}`]??X(c)}function Z(i){let c=`character.jobs.${i}`,h=t(c);return h!==c?h:W.classes[i]?.jobs??""}var ae=`
2
+ .creator {
3
+ display: grid;
4
+ gap: var(--space-5);
5
+ align-items: start;
6
+ }
7
+
8
+ @media (min-width: 720px) {
9
+ .creator {
10
+ grid-template-columns: 13rem minmax(0, 1fr);
11
+ }
12
+
13
+ .creator-preview {
14
+ position: sticky;
15
+ top: var(--space-4);
16
+ }
17
+ }
18
+
19
+ .creator-preview {
20
+ display: flex;
21
+ flex-direction: column;
22
+ align-items: center;
23
+ gap: var(--space-3);
24
+ padding: var(--space-4);
25
+ border: 1px solid var(--border);
26
+ border-radius: var(--radius-lg);
27
+ background: color-mix(
28
+ in srgb,
29
+ var(--agent-accent, var(--accent)) 8%,
30
+ var(--surface)
31
+ );
32
+ }
33
+
34
+ .creator-body {
35
+ display: flex;
36
+ flex-direction: column;
37
+ gap: var(--space-4);
38
+ min-width: 0;
39
+ }
40
+
41
+ .creator-field {
42
+ display: flex;
43
+ flex-direction: column;
44
+ gap: var(--space-2);
45
+ min-width: 0;
46
+ }
47
+
48
+ .creator-field h3 {
49
+ font-size: var(--text-sm);
50
+ color: var(--muted);
51
+ font-weight: var(--weight-medium);
52
+ }
53
+
54
+ /* In the phone's sheet the sheet's own title says what the group is. */
55
+ dialog.sheet dialog.sheet .creator-field > h3 {
56
+ display: none;
57
+ }
58
+
59
+ .creator-grid {
60
+ display: grid;
61
+ grid-template-columns: repeat(auto-fill, minmax(4.5rem, 1fr));
62
+ gap: var(--space-2);
63
+ }
64
+
65
+ .creator-strip {
66
+ display: flex;
67
+ gap: var(--space-2);
68
+ /* Room for the chosen tile's ring, which the scrolling strip would otherwise clip. */
69
+ padding: 3px 3px var(--space-1);
70
+ overflow-x: auto;
71
+ scroll-snap-type: x proximity;
72
+ }
73
+
74
+ /* The row fades toward the side where more of it lies, so a cut-off tile reads as "scroll" and not as the end. */
75
+ .creator-strip[data-more="end"] {
76
+ -webkit-mask-image: linear-gradient(
77
+ to right,
78
+ #000 calc(100% - 2.5rem),
79
+ transparent
80
+ );
81
+ mask-image: linear-gradient(to right, #000 calc(100% - 2.5rem), transparent);
82
+ }
83
+ .creator-strip[data-more="start"] {
84
+ -webkit-mask-image: linear-gradient(
85
+ to left,
86
+ #000 calc(100% - 2.5rem),
87
+ transparent
88
+ );
89
+ mask-image: linear-gradient(to left, #000 calc(100% - 2.5rem), transparent);
90
+ }
91
+ .creator-strip[data-more="both"] {
92
+ -webkit-mask-image: linear-gradient(
93
+ to right,
94
+ transparent,
95
+ #000 2.5rem,
96
+ #000 calc(100% - 2.5rem),
97
+ transparent
98
+ );
99
+ mask-image: linear-gradient(
100
+ to right,
101
+ transparent,
102
+ #000 2.5rem,
103
+ #000 calc(100% - 2.5rem),
104
+ transparent
105
+ );
106
+ }
107
+
108
+ .creator-tile {
109
+ display: flex;
110
+ flex: none;
111
+ flex-direction: column;
112
+ align-items: center;
113
+ gap: 2px;
114
+ min-width: 4.25rem;
115
+ padding: var(--space-2) var(--space-1);
116
+ border: 1px solid var(--border);
117
+ border-radius: var(--radius);
118
+ background: var(--surface);
119
+ color: var(--text);
120
+ font-size: var(--text-xs);
121
+ scroll-snap-align: start;
122
+ }
123
+
124
+ .creator-grid .creator-tile {
125
+ min-width: 0;
126
+ }
127
+
128
+ .creator-tile span {
129
+ max-width: 100%;
130
+ overflow: hidden;
131
+ text-overflow: ellipsis;
132
+ white-space: nowrap;
133
+ }
134
+
135
+ .creator-tile:hover:not(:disabled) {
136
+ border-color: var(--control-border);
137
+ background: var(--surface-2);
138
+ }
139
+
140
+ .creator-tile[aria-pressed="true"],
141
+ .creator-tile[aria-pressed="true"]:hover:not(:disabled),
142
+ .creator-swatch[aria-pressed="true"],
143
+ .creator-swatch[aria-pressed="true"]:hover:not(:disabled) {
144
+ border-color: var(--agent-accent, var(--accent));
145
+ background: color-mix(
146
+ in srgb,
147
+ var(--agent-accent, var(--accent)) 14%,
148
+ var(--surface)
149
+ );
150
+ box-shadow: 0 0 0 2px var(--agent-accent, var(--accent));
151
+ }
152
+
153
+ .creator-swatches {
154
+ display: flex;
155
+ flex-wrap: wrap;
156
+ align-items: center;
157
+ gap: var(--space-2);
158
+ margin: 0;
159
+ padding: 0;
160
+ border: 0;
161
+ }
162
+
163
+ .creator-swatch {
164
+ width: 2.25rem;
165
+ height: 2.25rem;
166
+ min-height: 0;
167
+ padding: 0;
168
+ border: 2px solid var(--surface);
169
+ border-radius: var(--radius-full);
170
+ box-shadow: 0 0 0 1px var(--control-border);
171
+ }
172
+
173
+ .creator-custom {
174
+ display: flex;
175
+ flex-wrap: wrap;
176
+ gap: var(--space-4);
177
+ }
178
+
179
+ .creator-custom label {
180
+ display: flex;
181
+ flex-direction: column;
182
+ align-items: flex-start;
183
+ gap: var(--space-1);
184
+ font-size: var(--text-sm);
185
+ color: var(--muted);
186
+ }
187
+
188
+ .creator-custom input[type="color"],
189
+ .creator-swatches input[type="color"] {
190
+ width: 2.25rem;
191
+ height: 2.25rem;
192
+ padding: 0;
193
+ border: 1px solid var(--control-border);
194
+ border-radius: var(--radius-sm);
195
+ background: transparent;
196
+ }
197
+
198
+ .field-error {
199
+ margin: 0;
200
+ color: var(--danger);
201
+ font-size: var(--text-sm);
202
+ }
203
+
204
+ .creator-sections {
205
+ display: flex;
206
+ flex-direction: column;
207
+ gap: var(--space-2);
208
+ margin: 0;
209
+ padding: 0;
210
+ list-style: none;
211
+ }
212
+
213
+ .creator-section {
214
+ display: flex;
215
+ width: 100%;
216
+ align-items: center;
217
+ justify-content: space-between;
218
+ gap: var(--space-3);
219
+ text-align: left;
220
+ }
221
+
222
+ .creator-actions {
223
+ flex-wrap: wrap;
224
+ }
225
+ `;var K=[{field:"hat",title:u("Hat"),ids:W.hats},{field:"outfit",title:u("Outfit"),ids:W.outfits},{field:"prop",title:u("Prop"),ids:W.props},{field:"hair",title:u("Hair"),ids:W.hair},{field:"beard",title:u("Beard"),ids:["none",...W.beards]},{field:"accessory",title:u("Accessory"),ids:["none",...W.accessories]}],pe=new Set(["class","colors","palette","build","skin","hairColor",...K.map((i)=>i.field)]),oe=Object.keys(W.palettes),te={idle:u("Idle"),thinking:u("Thinking"),working:u("Working"),waiting:u("Waiting for you"),done:u("Done"),error:u("Error"),sleepy:u("Sleepy")},ge={slim:u("Slim"),regular:u("Regular"),stout:u("Stout")};function M(i){return{class:i.class,outfit:i.outfit,hat:i.hat,prop:i.prop,hair:i.hair,beard:i.beard,accessory:i.accessory,build:i.build,skin:i.skin,hairColor:i.hairColor,colors:{...i.colors}}}var re=(i)=>JSON.stringify(M(i)),k=(i)=>i[Math.floor(Math.random()*i.length)];function be(){return{class:k(je),outfit:k(W.outfits),hat:k(W.hats),prop:k(W.props),hair:k(W.hair),beard:k(["none",...W.beards]),accessory:k(["none",...W.accessories]),build:k(["slim","regular","stout"]),skin:k([0,1,2,3,4,5]),hairColor:k(W.hairColors),palette:k(oe)}}var ne=ee(function(c){return n("button",{type:"button",className:"creator-tile","aria-pressed":c.pressed,title:c.hint?`${c.label} — ${c.hint}`:c.label,onClick:c.onPick,...c.data,children:[e(he,{spec:c.spec,size:c.size,live:!1}),e("span",{children:c.label})]})});function ve(i,c,h){let p=JSON.stringify({...i,[c]:0});return C(()=>h.map((d)=>({...i,[c]:d})),[p,c,h])}function ye(){let i=a(null),[c,h]=r();return o(()=>{let p=i.current;if(!p)return;let d=()=>{let S=p.scrollLeft>1,P=p.scrollLeft+p.clientWidth<p.scrollWidth-1;h(S&&P?"both":P?"end":S?"start":void 0)};d(),p.addEventListener("scroll",d,{passive:!0});let b=typeof ResizeObserver>"u"?void 0:new ResizeObserver(d);return b?.observe(p),()=>{p.removeEventListener("scroll",d),b?.disconnect()}},[]),[i,c]}function ke(i){let{part:c}=i,h=ve(i.shown,c.field,c.ids),[p,d]=ye();return e("div",{className:"creator-strip",ref:p,"data-more":d,children:c.ids.map((b,S)=>e(ne,{data:{[`data-${c.field}`]:b},spec:h[S],size:44,label:x(c.field,b),pressed:i.draft[c.field]===b,onPick:()=>i.onPick(b)},b))})}function H(i){return e("button",{type:"button",className:"creator-swatch","aria-pressed":i.pressed,"aria-label":i.label,title:i.label,style:{background:i.background},onClick:i.onPick,...i.data})}function N(i){return n("div",{className:"creator-field","data-field":i.field,children:[i.title?e("h3",{children:i.title}):null,i.children,i.error?e("p",{className:"field-error",role:"alert",children:i.error}):null]})}function $e(i){Y("creator",ae);let[c,h]=r(i.character),p=Fr(c),[d,b]=r({}),[S,P]=r(!1),[I,se]=r("idle"),[_,T]=r(),[z,j]=r(),U=Qe("(max-width: 719px)"),G=a(null),F=L(),le=Je(c),ce=Sn(),A=re(c)!==re(i.character);o(()=>h(i.character),[i.character]),o(()=>{if(!A||i.onPick)return;let s=(v)=>v.preventDefault(),m=(v)=>{if(v.button!==0||v.metaKey||v.ctrlKey||v.shiftKey||v.altKey)return;let E=v.target instanceof Element?v.target.closest("a"):null;if(!E||E.target||E.hasAttribute("download"))return;if(G.current?.contains(E))return;v.preventDefault(),v.stopPropagation(),T({kind:"link",anchor:E})},B=xi((v)=>T({kind:"navigate",proceed:v}));return window.addEventListener("beforeunload",s),document.addEventListener("click",m,!0),()=>{B(),window.removeEventListener("beforeunload",s),document.removeEventListener("click",m,!0)}},[A,i.onPick]);let w=(s)=>{b({}),h((m)=>Ri(s,m))},de=async()=>{if(i.onPick){i.onPick(M(c),c);return}P(!0),b({});try{let s=await y.setCharacter(i.name,M(c));i.onSaved?.(s),f(t("Saved."))}catch(s){let m=s instanceof fe&&s.field?s.field.split(".")[0]:void 0,B=m&&pe.has(m)?m:"*";b({[B]:l(s)})}finally{P(!1)}},me=async()=>{let s=_;if(h(i.character),b({}),s?.kind==="link")setTimeout(()=>s.anchor.click(),0);else if(s?.kind==="navigate")s.proceed()},J=e(N,{field:"class",title:t("Class"),error:d.class,children:e("div",{className:"creator-grid",children:je.map((s)=>e(Ce,{id:s,base:p,pressed:c.class===s,onPick:()=>w({class:s,colors:c.colors})},s))})}),V=n(N,{field:"colors",title:t("Colors"),error:d.colors??d.palette,children:[n("fieldset",{className:"creator-swatches",children:[e("legend",{className:"visually-hidden",children:t("Palette")}),oe.map((s)=>{let m=W.palettes[s];return e(H,{data:{"data-palette":s},label:x("palette",s),pressed:c.palette===s,background:`linear-gradient(135deg, ${m.primary} 52%, ${m.trim} 52%)`,onPick:()=>w({palette:s})},s)})]}),e("div",{className:"creator-custom",children:["primary","secondary","trim"].map((s)=>n("label",{children:[e("span",{children:s==="primary"?t("Primary (the accent)"):s==="secondary"?t("Secondary"):t("Trim")}),e("input",{type:"color",value:c.colors[s],onChange:(m)=>w({colors:{[s]:m.target.value}})})]},s))})]}),q=K.map((s)=>e(N,{field:s.field,title:t(s.title),error:d[s.field],children:e(ke,{part:s,draft:c,shown:p,onPick:(m)=>w({[s.field]:m})})},s.field)),Q=n(g,{children:[e(N,{field:"build",title:t("Build"),error:d.build,children:n("fieldset",{className:"segmented",children:[e("legend",{className:"visually-hidden",children:t("Build")}),["slim","regular","stout"].map((s)=>n("label",{"data-checked":c.build===s,children:[e("input",{type:"radio",name:`${F}-build`,checked:c.build===s,onChange:()=>w({build:s})}),ie(s)]},s))]})}),e(N,{field:"skin",title:t("Skin tone"),error:d.skin,children:n("fieldset",{className:"creator-swatches",children:[e("legend",{className:"visually-hidden",children:t("Skin tone")}),(ce??W.skins).map((s,m)=>e(H,{data:{"data-skin":String(m)},label:t("Skin tone {n}",{n:m+1}),pressed:c.skin===m,background:s,onPick:()=>w({skin:m})},m))]})}),e(N,{field:"hairColor",title:t("Hair color"),error:d.hairColor,children:n("fieldset",{className:"creator-swatches",children:[e("legend",{className:"visually-hidden",children:t("Hair color")}),W.hairColors.map((s,m)=>e(H,{data:{"data-hair-color":s},label:t("Hair color {n}",{n:m+1}),pressed:c.hairColor===s,background:s,onPick:()=>w({hairColor:s})},s)),e("input",{type:"color","aria-label":t("Hair color"),value:c.hairColor,onChange:(s)=>w({hairColor:s.target.value})})]})})]}),O=[{id:"class",title:t("Class"),summary:x("class",c.class),error:d.class,node:J},{id:"colors",title:t("Colors"),summary:c.palette?x("palette",c.palette):c.colors.primary,error:d.colors??d.palette,node:V},...K.map((s,m)=>({id:s.field,title:t(s.title),summary:x(s.field,c[s.field]),error:d[s.field],node:q[m]})),{id:"body",title:t("Body"),summary:ie(c.build),error:d.build??d.skin??d.hairColor,node:Q}];return n("form",{ref:G,className:"creator",style:le,"aria-labelledby":F,onSubmit:(s)=>{if(s.preventDefault(),(A||i.onPick)&&!S)de()},children:[e("h2",{id:F,className:"visually-hidden",children:t("Character of {name}",{name:i.displayName})}),n("div",{className:"creator-preview",children:[e(he,{spec:c,name:i.name,state:I,size:176,label:t("{name}, {state}",{name:i.displayName,state:t(te[I])})}),e("button",{type:"button",className:"secondary","data-action":"cycle",onClick:()=>se((s)=>Jt[(Jt.indexOf(s)+1)%Jt.length]??"idle"),children:t("Preview states")}),e("span",{className:"meta","aria-live":"polite",children:t(te[I])})]}),n("div",{className:"creator-body",children:[d["*"]?e("p",{className:"field-error",role:"alert","data-field":"*",children:d["*"]}):null,U?e("ul",{className:"creator-sections",children:O.map((s)=>e("li",{children:n("button",{type:"button",className:"creator-section secondary",onClick:()=>j(s.id),children:[e("strong",{children:s.title}),e("span",{className:"meta",children:s.summary}),s.error?e("span",{className:"field-error",role:"alert",children:s.error}):null]})},s.id))}):n(g,{children:[J,V,q,Q]}),n("div",{className:"actions creator-actions",children:[e("button",{type:"button",className:"secondary","data-action":"suggest",onClick:()=>{b({}),h(Pn({name:i.name,displayName:i.displayName,prompt:i.prompt}))},children:t("Suggest from role")}),e("button",{type:"button",className:"secondary","data-action":"randomize",onClick:()=>w(be()),children:t("Randomize")}),e("button",{type:"button",className:"secondary","data-action":"cancel",onClick:()=>{if(i.onCancel)i.onCancel();else if(A)T({kind:"cancel"})},children:t("Cancel")}),e("button",{type:"submit","data-action":"save",disabled:!A&&!i.onPick||S,children:S?t("Saving…"):i.onPick?t("Use this look"):t("Save")})]})]}),e(R,{open:U&&z!==void 0,title:O.find((s)=>s.id===z)?.title??"",onClose:()=>j(void 0),children:e("div",{className:"stack",children:O.find((s)=>s.id===z)?.node})}),e(D,{open:_!==void 0,title:t("Discard your changes?"),confirmLabel:t("Discard"),cancelLabel:t("Keep editing"),tone:"danger",onClose:()=>T(void 0),onConfirm:me,children:e("p",{children:t("The new look for {name} has not been saved.",{name:i.displayName})})})]})}var ie=(i)=>t(ge[i]);function Ce(i){let c=i.base.colors,h=C(()=>Ri({class:i.id,colors:c}),[i.id,c]);return e(ne,{data:{"data-class":i.id},spec:h,size:56,label:x("class",i.id),hint:Z(i.id),pressed:i.pressed,onPick:i.onPick})}export{$e as CharacterCreator};