@unofficialbox/box-open-elements 0.5.0 → 0.7.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 (227) hide show
  1. package/README.md +27 -73
  2. package/dist/components/collections/table.d.ts +113 -3
  3. package/dist/components/collections/table.js +540 -37
  4. package/dist/components/feedback/due-badge.d.ts +38 -0
  5. package/dist/components/feedback/due-badge.js +168 -0
  6. package/dist/components/feedback/due-types.d.ts +32 -0
  7. package/dist/components/feedback/due-types.js +91 -0
  8. package/dist/components/feedback/progress-steps.d.ts +51 -5
  9. package/dist/components/feedback/progress-steps.js +200 -22
  10. package/dist/components/feedback/stage-path.d.ts +44 -0
  11. package/dist/components/feedback/stage-path.js +235 -0
  12. package/dist/components/forms/select.d.ts +21 -0
  13. package/dist/components/forms/select.js +100 -3
  14. package/dist/components/forms/text-field.d.ts +21 -0
  15. package/dist/components/forms/text-field.js +100 -1
  16. package/dist/components/layout/nav-sidebar.d.ts +14 -0
  17. package/dist/components/layout/nav-sidebar.js +49 -0
  18. package/dist/components/layout/split-view.d.ts +14 -0
  19. package/dist/components/layout/split-view.js +80 -1
  20. package/dist/components/overlays/command-palette.d.ts +62 -0
  21. package/dist/components/overlays/command-palette.js +537 -0
  22. package/dist/components/overlays/command-types.d.ts +90 -0
  23. package/dist/components/overlays/command-types.js +259 -0
  24. package/dist/components/overlays/drawer.d.ts +18 -0
  25. package/dist/components/overlays/drawer.js +135 -9
  26. package/dist/components/overlays/shortcuts-overlay.d.ts +48 -0
  27. package/dist/components/overlays/shortcuts-overlay.js +385 -0
  28. package/dist/components/overlays/tooltip.js +1 -1
  29. package/dist/core/index.d.ts +4 -0
  30. package/dist/core/index.js +2 -0
  31. package/dist/core/offset-window.d.ts +70 -0
  32. package/dist/core/offset-window.js +134 -0
  33. package/dist/core/virtualize.d.ts +71 -0
  34. package/dist/core/virtualize.js +67 -0
  35. package/dist/element-maps.d.ts +292 -0
  36. package/dist/element-maps.js +1 -0
  37. package/dist/entries/activity-density.d.ts +1 -0
  38. package/dist/entries/activity-density.js +1 -0
  39. package/dist/entries/agent-chat.d.ts +1 -0
  40. package/dist/entries/agent-chat.js +1 -0
  41. package/dist/entries/audit-log.d.ts +1 -0
  42. package/dist/entries/audit-log.js +1 -0
  43. package/dist/entries/command-palette.d.ts +1 -0
  44. package/dist/entries/command-palette.js +1 -0
  45. package/dist/entries/compare-view.d.ts +1 -0
  46. package/dist/entries/compare-view.js +1 -0
  47. package/dist/entries/diff-viewer.d.ts +1 -0
  48. package/dist/entries/diff-viewer.js +1 -0
  49. package/dist/entries/due-badge.d.ts +1 -0
  50. package/dist/entries/due-badge.js +1 -0
  51. package/dist/entries/form-wizard.d.ts +1 -0
  52. package/dist/entries/form-wizard.js +1 -0
  53. package/dist/entries/lineage-graph.d.ts +1 -0
  54. package/dist/entries/lineage-graph.js +1 -0
  55. package/dist/entries/notification-bell.d.ts +1 -0
  56. package/dist/entries/notification-bell.js +1 -0
  57. package/dist/entries/notification-inbox.d.ts +1 -0
  58. package/dist/entries/notification-inbox.js +1 -0
  59. package/dist/entries/provenance-strip.d.ts +1 -0
  60. package/dist/entries/provenance-strip.js +1 -0
  61. package/dist/entries/run-trace.d.ts +1 -0
  62. package/dist/entries/run-trace.js +1 -0
  63. package/dist/entries/shortcuts-overlay.d.ts +1 -0
  64. package/dist/entries/shortcuts-overlay.js +1 -0
  65. package/dist/entries/signature-ceremony.d.ts +1 -0
  66. package/dist/entries/signature-ceremony.js +1 -0
  67. package/dist/entries/stage-path.d.ts +1 -0
  68. package/dist/entries/stage-path.js +1 -0
  69. package/dist/entries/timeline.d.ts +1 -0
  70. package/dist/entries/timeline.js +1 -0
  71. package/dist/entries/version-graph.d.ts +1 -0
  72. package/dist/entries/version-graph.js +1 -0
  73. package/dist/entries/version-list.d.ts +1 -0
  74. package/dist/entries/version-list.js +1 -0
  75. package/dist/entries/wizard-summary.d.ts +1 -0
  76. package/dist/entries/wizard-summary.js +1 -0
  77. package/dist/entries/work-queue.d.ts +1 -0
  78. package/dist/entries/work-queue.js +1 -0
  79. package/dist/entries/workload-board.d.ts +1 -0
  80. package/dist/entries/workload-board.js +1 -0
  81. package/dist/index.d.ts +21 -0
  82. package/dist/index.js +21 -0
  83. package/dist/patterns/agent-chat/agent-chat.d.ts +75 -0
  84. package/dist/patterns/agent-chat/agent-chat.js +820 -0
  85. package/dist/patterns/agent-chat/controller.d.ts +27 -0
  86. package/dist/patterns/agent-chat/controller.js +182 -0
  87. package/dist/patterns/agent-chat/index.d.ts +3 -0
  88. package/dist/patterns/agent-chat/index.js +6 -0
  89. package/dist/patterns/agent-chat/types.d.ts +109 -0
  90. package/dist/patterns/agent-chat/types.js +1 -0
  91. package/dist/patterns/audit/activity-density.d.ts +68 -0
  92. package/dist/patterns/audit/activity-density.js +428 -0
  93. package/dist/patterns/audit/audit-log.d.ts +182 -0
  94. package/dist/patterns/audit/audit-log.js +1082 -0
  95. package/dist/patterns/audit/index.d.ts +3 -0
  96. package/dist/patterns/audit/index.js +7 -0
  97. package/dist/patterns/audit/shared.d.ts +10 -0
  98. package/dist/patterns/audit/shared.js +50 -0
  99. package/dist/patterns/audit/types.d.ts +143 -0
  100. package/dist/patterns/audit/types.js +327 -0
  101. package/dist/patterns/audit/window.d.ts +116 -0
  102. package/dist/patterns/audit/window.js +132 -0
  103. package/dist/patterns/content-explorer/actions/controller.js +12 -2
  104. package/dist/patterns/content-explorer/box-transport.js +117 -25
  105. package/dist/patterns/content-explorer/content-explorer.d.ts +13 -1
  106. package/dist/patterns/content-explorer/content-explorer.js +36 -3
  107. package/dist/patterns/content-explorer/contracts.d.ts +24 -1
  108. package/dist/patterns/content-explorer/contracts.js +68 -11
  109. package/dist/patterns/content-explorer/controller.d.ts +16 -1
  110. package/dist/patterns/content-explorer/controller.js +130 -4
  111. package/dist/patterns/content-explorer/navigation/controller.js +11 -9
  112. package/dist/patterns/content-explorer/types.d.ts +58 -1
  113. package/dist/patterns/content-picker/content-picker.d.ts +71 -0
  114. package/dist/patterns/content-picker/content-picker.js +747 -0
  115. package/dist/patterns/content-picker/controller.d.ts +38 -0
  116. package/dist/patterns/content-picker/controller.js +141 -0
  117. package/dist/patterns/content-picker/index.d.ts +3 -0
  118. package/dist/patterns/content-picker/index.js +6 -0
  119. package/dist/patterns/content-picker/types.d.ts +52 -0
  120. package/dist/patterns/content-picker/types.js +26 -0
  121. package/dist/patterns/content-sidebar/content-sidebar.d.ts +43 -0
  122. package/dist/patterns/content-sidebar/content-sidebar.js +293 -0
  123. package/dist/patterns/content-sidebar/index.d.ts +2 -0
  124. package/dist/patterns/content-sidebar/index.js +4 -0
  125. package/dist/patterns/content-sidebar/types.d.ts +18 -0
  126. package/dist/patterns/content-sidebar/types.js +20 -0
  127. package/dist/patterns/content-uploader/box-transport.d.ts +14 -0
  128. package/dist/patterns/content-uploader/box-transport.js +54 -0
  129. package/dist/patterns/content-uploader/content-uploader.d.ts +62 -0
  130. package/dist/patterns/content-uploader/content-uploader.js +559 -0
  131. package/dist/patterns/content-uploader/controller.d.ts +39 -0
  132. package/dist/patterns/content-uploader/controller.js +227 -0
  133. package/dist/patterns/content-uploader/index.d.ts +4 -0
  134. package/dist/patterns/content-uploader/index.js +8 -0
  135. package/dist/patterns/content-uploader/types.d.ts +120 -0
  136. package/dist/patterns/content-uploader/types.js +38 -0
  137. package/dist/patterns/diff/compare-view.d.ts +47 -0
  138. package/dist/patterns/diff/compare-view.js +276 -0
  139. package/dist/patterns/diff/diff-viewer.d.ts +42 -0
  140. package/dist/patterns/diff/diff-viewer.js +434 -0
  141. package/dist/patterns/diff/engine.d.ts +22 -0
  142. package/dist/patterns/diff/engine.js +276 -0
  143. package/dist/patterns/diff/index.d.ts +4 -0
  144. package/dist/patterns/diff/index.js +8 -0
  145. package/dist/patterns/diff/types.d.ts +69 -0
  146. package/dist/patterns/diff/types.js +24 -0
  147. package/dist/patterns/form-wizard/controller.d.ts +39 -0
  148. package/dist/patterns/form-wizard/controller.js +157 -0
  149. package/dist/patterns/form-wizard/form-wizard.d.ts +63 -0
  150. package/dist/patterns/form-wizard/form-wizard.js +468 -0
  151. package/dist/patterns/form-wizard/index.d.ts +4 -0
  152. package/dist/patterns/form-wizard/index.js +8 -0
  153. package/dist/patterns/form-wizard/types.d.ts +109 -0
  154. package/dist/patterns/form-wizard/types.js +83 -0
  155. package/dist/patterns/form-wizard/wizard-summary.d.ts +62 -0
  156. package/dist/patterns/form-wizard/wizard-summary.js +324 -0
  157. package/dist/patterns/internal/safe-href.d.ts +17 -0
  158. package/dist/patterns/internal/safe-href.js +17 -0
  159. package/dist/patterns/lineage/index.d.ts +3 -0
  160. package/dist/patterns/lineage/index.js +6 -0
  161. package/dist/patterns/lineage/lineage-graph.d.ts +30 -0
  162. package/dist/patterns/lineage/lineage-graph.js +434 -0
  163. package/dist/patterns/lineage/provenance-strip.d.ts +22 -0
  164. package/dist/patterns/lineage/provenance-strip.js +194 -0
  165. package/dist/patterns/lineage/types.d.ts +53 -0
  166. package/dist/patterns/lineage/types.js +49 -0
  167. package/dist/patterns/notifications/index.d.ts +3 -0
  168. package/dist/patterns/notifications/index.js +6 -0
  169. package/dist/patterns/notifications/notification-bell.d.ts +38 -0
  170. package/dist/patterns/notifications/notification-bell.js +198 -0
  171. package/dist/patterns/notifications/notification-inbox.d.ts +46 -0
  172. package/dist/patterns/notifications/notification-inbox.js +537 -0
  173. package/dist/patterns/notifications/types.d.ts +61 -0
  174. package/dist/patterns/notifications/types.js +108 -0
  175. package/dist/patterns/preview/annotation-inspector.d.ts +25 -6
  176. package/dist/patterns/preview/annotation-inspector.js +239 -94
  177. package/dist/patterns/preview/annotation-thread.d.ts +25 -5
  178. package/dist/patterns/preview/annotation-thread.js +233 -82
  179. package/dist/patterns/preview/annotation-toolbar.d.ts +20 -6
  180. package/dist/patterns/preview/annotation-toolbar.js +162 -96
  181. package/dist/patterns/preview/content-preview-adapter.d.ts +10 -1
  182. package/dist/patterns/preview/content-preview-adapter.js +26 -1
  183. package/dist/patterns/preview/preview-element.d.ts +15 -2
  184. package/dist/patterns/preview/preview-element.js +223 -52
  185. package/dist/patterns/preview/provider-adapter.d.ts +47 -0
  186. package/dist/patterns/preview/provider-adapter.js +17 -0
  187. package/dist/patterns/run/index.d.ts +2 -0
  188. package/dist/patterns/run/index.js +4 -0
  189. package/dist/patterns/run/run-trace.d.ts +40 -0
  190. package/dist/patterns/run/run-trace.js +441 -0
  191. package/dist/patterns/run/types.d.ts +66 -0
  192. package/dist/patterns/run/types.js +152 -0
  193. package/dist/patterns/signature/index.d.ts +2 -0
  194. package/dist/patterns/signature/index.js +4 -0
  195. package/dist/patterns/signature/signature-ceremony.d.ts +33 -0
  196. package/dist/patterns/signature/signature-ceremony.js +317 -0
  197. package/dist/patterns/signature/types.d.ts +68 -0
  198. package/dist/patterns/signature/types.js +89 -0
  199. package/dist/patterns/timeline/index.d.ts +2 -0
  200. package/dist/patterns/timeline/index.js +4 -0
  201. package/dist/patterns/timeline/timeline.d.ts +27 -0
  202. package/dist/patterns/timeline/timeline.js +430 -0
  203. package/dist/patterns/timeline/types.d.ts +36 -0
  204. package/dist/patterns/timeline/types.js +27 -0
  205. package/dist/patterns/versions/graph-layout.d.ts +43 -0
  206. package/dist/patterns/versions/graph-layout.js +159 -0
  207. package/dist/patterns/versions/index.d.ts +4 -0
  208. package/dist/patterns/versions/index.js +8 -0
  209. package/dist/patterns/versions/shared.d.ts +4 -0
  210. package/dist/patterns/versions/shared.js +13 -0
  211. package/dist/patterns/versions/types.d.ts +37 -0
  212. package/dist/patterns/versions/types.js +39 -0
  213. package/dist/patterns/versions/version-graph.d.ts +36 -0
  214. package/dist/patterns/versions/version-graph.js +438 -0
  215. package/dist/patterns/versions/version-list.d.ts +39 -0
  216. package/dist/patterns/versions/version-list.js +407 -0
  217. package/dist/patterns/work-queue/controller.d.ts +26 -0
  218. package/dist/patterns/work-queue/controller.js +150 -0
  219. package/dist/patterns/work-queue/index.d.ts +4 -0
  220. package/dist/patterns/work-queue/index.js +7 -0
  221. package/dist/patterns/work-queue/types.d.ts +128 -0
  222. package/dist/patterns/work-queue/types.js +45 -0
  223. package/dist/patterns/work-queue/work-queue.d.ts +48 -0
  224. package/dist/patterns/work-queue/work-queue.js +534 -0
  225. package/dist/patterns/work-queue/workload-board.d.ts +53 -0
  226. package/dist/patterns/work-queue/workload-board.js +608 -0
  227. package/package.json +89 -5
@@ -10,6 +10,12 @@ const escapeHtml = (value) => value
10
10
  .replaceAll('"', """)
11
11
  .replaceAll("'", "'");
12
12
  const elementStyles = `
13
+ /* Author display rules on parts would otherwise defeat the UA's
14
+ [hidden] rule — state toggling relies on the hidden attribute. */
15
+ [hidden] {
16
+ display: none !important;
17
+ }
18
+
13
19
  :host {
14
20
  display: block;
15
21
  color: inherit;
@@ -46,11 +52,19 @@ const elementStyles = `
46
52
  [part="entries"] {
47
53
  display: grid;
48
54
  gap: 0.6rem;
55
+ margin: 0;
56
+ padding: 0;
57
+ list-style: none;
58
+ }
59
+
60
+ [part="entry-item"] {
61
+ display: block;
49
62
  }
50
63
 
51
64
  [part="entry"] {
52
65
  appearance: none;
53
66
  display: grid;
67
+ inline-size: 100%;
54
68
  grid-template-columns: auto 1fr;
55
69
  gap: ${boePanel.gap};
56
70
  align-items: start;
@@ -144,9 +158,48 @@ const elementStyles = `
144
158
  color: var(--boe-token-text-text-secondary, #6f6f6f);
145
159
  }
146
160
 
161
+ [part="composer"] {
162
+ display: grid;
163
+ gap: 0.5rem;
164
+ }
165
+
166
+ [part="composer-label"] {
167
+ font-size: 0.74rem;
168
+ font-weight: 700;
169
+ letter-spacing: 0.08em;
170
+ text-transform: uppercase;
171
+ color: var(--boe-token-text-text-secondary, #6f6f6f);
172
+ }
173
+
174
+ [part="composer-input"] {
175
+ min-height: 4rem;
176
+ padding: 0.55rem;
177
+ border: 1px solid color-mix(in srgb, var(--boe-token-stroke-stroke, #e8e8e8) 60%, transparent);
178
+ border-radius: ${boePanel.radius};
179
+ background: var(--boe-token-surface-surface, #ffffff);
180
+ color: inherit;
181
+ font: inherit;
182
+ line-height: 1.5;
183
+ resize: vertical;
184
+ }
185
+
186
+ [part="composer-submit"] {
187
+ appearance: none;
188
+ justify-self: start;
189
+ min-height: 2rem;
190
+ padding: 0.4rem 0.7rem;
191
+ border: 1px solid transparent;
192
+ border-radius: 999px;
193
+ background: var(--boe-token-surface-surface-brand, #0061d5);
194
+ color: var(--boe-token-text-text-on-brand, #ffffff);
195
+ font: inherit;
196
+ cursor: pointer;
197
+ }
198
+
147
199
  ${boeNeutralInteractiveStyles('[part="entry"]')}
148
200
  ${boeNeutralInteractiveStyles('[part="action"]')}
149
201
  ${boeBrandInteractiveStyles('[part="action"][data-tone="primary"]')}
202
+ ${boeBrandInteractiveStyles('[part="composer-submit"]')}
150
203
 
151
204
  [part="entry"][aria-pressed="true"],
152
205
  [part="entry"][aria-pressed="true"]:hover:not(:disabled) {
@@ -163,14 +216,29 @@ const elementStyles = `
163
216
  export class AnnotationThread extends BaseElement {
164
217
  static tagName = DEFAULT_TAG_NAME;
165
218
  static get observedAttributes() {
166
- return ["actions", "entries", "message", "selected-entry-id", "heading"];
219
+ return ["actions", "composable", "entries", "message", "selected-entry-id", "heading"];
167
220
  }
221
+ titleEl;
222
+ messageEl;
223
+ entriesEl;
224
+ emptyEl;
225
+ actionsEl;
226
+ composerEl;
227
+ composerInputEl;
228
+ entriesSignature = "";
229
+ actionsSignature = "";
168
230
  get actions() {
169
231
  return this.parseJsonAttribute("actions", []);
170
232
  }
171
233
  set actions(value) {
172
234
  this.setAttribute("actions", JSON.stringify(value));
173
235
  }
236
+ get composable() {
237
+ return this.hasAttribute("composable");
238
+ }
239
+ set composable(value) {
240
+ this.toggleAttribute("composable", value);
241
+ }
174
242
  get entries() {
175
243
  return this.parseJsonAttribute("entries", []);
176
244
  }
@@ -203,12 +271,6 @@ export class AnnotationThread extends BaseElement {
203
271
  set heading(value) {
204
272
  this.setAttribute("heading", value);
205
273
  }
206
- connectedCallback() {
207
- super.connectedCallback();
208
- }
209
- attributeChangedCallback(name, oldValue, newValue) {
210
- super.attributeChangedCallback(name, oldValue, newValue);
211
- }
212
274
  parseJsonAttribute(name, fallback) {
213
275
  const raw = this.getAttribute(name);
214
276
  if (!raw) {
@@ -239,94 +301,183 @@ export class AnnotationThread extends BaseElement {
239
301
  detail: entry,
240
302
  }));
241
303
  }
242
- renderTemplate() {
243
- if (!this.shadowRoot) {
304
+ submitComposer() {
305
+ const body = this.composerInputEl.value.trim();
306
+ if (!this.composable || !body) {
244
307
  return;
245
308
  }
246
- this.shadowRoot.innerHTML = `
247
- <style>${elementStyles}</style>
248
- <div part="content-host"></div>
249
- `;
309
+ this.dispatchEvent(new CustomEvent("entry-submitted", {
310
+ bubbles: true,
311
+ composed: true,
312
+ detail: {
313
+ body,
314
+ inReplyToId: this.selectedEntryId || null,
315
+ },
316
+ }));
317
+ this.composerInputEl.value = "";
250
318
  }
251
- update() {
319
+ entriesKey() {
320
+ return this.getAttribute("entries") ?? "";
321
+ }
322
+ actionsKey() {
323
+ return JSON.stringify(this.actions.map(action => action.id));
324
+ }
325
+ rebuildEntries() {
326
+ this.entriesEl.innerHTML = this.entries
327
+ .map(entry => {
328
+ const selected = entry.id === this.selectedEntryId;
329
+ return `
330
+ <li part="entry-item" role="listitem">
331
+ <button
332
+ type="button"
333
+ part="entry"
334
+ data-entry-id="${escapeHtml(entry.id)}"
335
+ aria-pressed="${selected ? "true" : "false"}"
336
+ >
337
+ <span part="entry-avatar">${escapeHtml(entry.initials ?? entry.author.slice(0, 2).toUpperCase())}</span>
338
+ <span part="entry-copy">
339
+ <span part="entry-topline">
340
+ <span part="entry-author">${escapeHtml(entry.author)}</span>
341
+ ${entry.toolLabel ? `<span part="entry-tool">${escapeHtml(entry.toolLabel)}</span>` : ""}
342
+ ${entry.status ? `<span part="entry-status">${escapeHtml(entry.status)}</span>` : ""}
343
+ </span>
344
+ <span part="entry-body">${escapeHtml(entry.body)}</span>
345
+ ${entry.createdAt ? `<span part="entry-time">${escapeHtml(entry.createdAt)}</span>` : ""}
346
+ </span>
347
+ </button>
348
+ </li>
349
+ `;
350
+ })
351
+ .join("");
352
+ }
353
+ patchEntrySelection() {
354
+ this.entriesEl.querySelectorAll('[part="entry"]').forEach(button => {
355
+ const selected = button.getAttribute("data-entry-id") === this.selectedEntryId;
356
+ button.setAttribute("aria-pressed", selected ? "true" : "false");
357
+ });
358
+ }
359
+ rebuildActions() {
360
+ this.actionsEl.innerHTML = this.actions
361
+ .map(action => `
362
+ <button type="button" part="action" data-action-id="${escapeHtml(action.id)}" data-tone="${escapeHtml(action.tone ?? "neutral")}">
363
+ ${escapeHtml(action.label)}
364
+ </button>
365
+ `)
366
+ .join("");
367
+ }
368
+ patchActionLabels() {
369
+ // Action IDs are arbitrary strings (quotes, newlines, …) — match on the
370
+ // dataset instead of interpolating them into a CSS selector.
371
+ const buttons = Array.from(this.actionsEl.querySelectorAll('[part="action"]'));
372
+ this.actions.forEach(action => {
373
+ const button = buttons.find(candidate => candidate.dataset.actionId === action.id);
374
+ if (!button) {
375
+ return;
376
+ }
377
+ button.textContent = action.label;
378
+ button.dataset.tone = action.tone ?? "neutral";
379
+ });
380
+ }
381
+ renderTemplate() {
252
382
  if (!this.shadowRoot) {
253
383
  return;
254
384
  }
255
- const messageMarkup = this.message ? `<div part="message">${escapeHtml(this.message)}</div>` : "";
256
- const actionsMarkup = this.actions.length
257
- ? `
258
- <div part="actions">
259
- ${this.actions
260
- .map(action => `
261
- <button type="button" part="action" data-action-id="${escapeHtml(action.id)}" data-tone="${escapeHtml(action.tone ?? "neutral")}">
262
- ${escapeHtml(action.label)}
263
- </button>
264
- `)
265
- .join("")}
266
- </div>
267
- `
268
- : "";
269
- const entriesMarkup = this.entries.length
270
- ? `
271
- <div part="entries" role="list" aria-label="${escapeHtml(this.heading)} entries">
272
- ${this.entries
273
- .map(entry => {
274
- const selected = entry.id === this.selectedEntryId;
275
- return `
276
- <button
277
- type="button"
278
- part="entry"
279
- data-entry-id="${escapeHtml(entry.id)}"
280
- aria-pressed="${selected ? "true" : "false"}"
281
- >
282
- <span part="entry-avatar">${escapeHtml(entry.initials ?? entry.author.slice(0, 2).toUpperCase())}</span>
283
- <span part="entry-copy">
284
- <span part="entry-topline">
285
- <span part="entry-author">${escapeHtml(entry.author)}</span>
286
- ${entry.toolLabel ? `<span part="entry-tool">${escapeHtml(entry.toolLabel)}</span>` : ""}
287
- ${entry.status ? `<span part="entry-status">${escapeHtml(entry.status)}</span>` : ""}
288
- </span>
289
- <span part="entry-body">${escapeHtml(entry.body)}</span>
290
- ${entry.createdAt ? `<span part="entry-time">${escapeHtml(entry.createdAt)}</span>` : ""}
291
- </span>
292
- </button>
293
- `;
294
- })
295
- .join("")}
296
- </div>
297
- `
298
- : `<div part="empty">No annotation thread entries available.</div>`;
299
- const host = this.shadowRoot.querySelector('[part="content-host"]');
300
- if (!host) {
301
- return;
302
- }
303
- host.innerHTML = `
385
+ this.shadowRoot.innerHTML = `
386
+ <style>${elementStyles}</style>
304
387
  <article part="thread">
305
388
  <header part="header">
306
- <h2 part="title">${escapeHtml(this.heading)}</h2>
307
- ${messageMarkup}
389
+ <h2 part="title"></h2>
390
+ <div part="message" hidden></div>
308
391
  </header>
309
- ${entriesMarkup}
310
- ${actionsMarkup}
392
+ <ul part="entries" role="list" hidden></ul>
393
+ <div part="empty" hidden>No annotation thread entries available.</div>
394
+ <div part="actions" hidden></div>
395
+ <div part="composer" hidden>
396
+ <label part="composer-label" for="annotation-thread-composer-input">Reply</label>
397
+ <textarea
398
+ part="composer-input"
399
+ id="annotation-thread-composer-input"
400
+ placeholder="Add a reply"
401
+ ></textarea>
402
+ <button type="button" part="composer-submit">Reply</button>
403
+ </div>
311
404
  </article>
312
405
  `;
313
- this.shadowRoot.querySelectorAll('[part="entry"]').forEach(button => {
314
- button.addEventListener("click", () => {
315
- const entryId = button.getAttribute("data-entry-id");
316
- const entry = this.entries.find(item => item.id === entryId);
317
- if (entry) {
318
- this.emitEntrySelected(entry);
319
- }
320
- });
406
+ this.titleEl = this.shadowRoot.querySelector('[part="title"]');
407
+ this.messageEl = this.shadowRoot.querySelector('[part="message"]');
408
+ this.entriesEl = this.shadowRoot.querySelector('[part="entries"]');
409
+ this.emptyEl = this.shadowRoot.querySelector('[part="empty"]');
410
+ this.actionsEl = this.shadowRoot.querySelector('[part="actions"]');
411
+ this.composerEl = this.shadowRoot.querySelector('[part="composer"]');
412
+ this.composerInputEl = this.shadowRoot.querySelector('[part="composer-input"]');
413
+ }
414
+ setupListeners() {
415
+ this.entriesEl.addEventListener("click", event => {
416
+ const button = event.target.closest('[part="entry"]');
417
+ if (!button || !this.entriesEl.contains(button)) {
418
+ return;
419
+ }
420
+ const entryId = button.getAttribute("data-entry-id");
421
+ const entry = this.entries.find(item => item.id === entryId);
422
+ if (entry) {
423
+ this.emitEntrySelected(entry);
424
+ }
425
+ });
426
+ this.actionsEl.addEventListener("click", event => {
427
+ const button = event.target.closest('[part="action"]');
428
+ if (!button || !this.actionsEl.contains(button)) {
429
+ return;
430
+ }
431
+ const actionId = button.getAttribute("data-action-id");
432
+ if (actionId) {
433
+ this.emitAction(actionId);
434
+ }
321
435
  });
322
- this.shadowRoot.querySelectorAll('[part="action"]').forEach(button => {
323
- button.addEventListener("click", () => {
324
- const actionId = button.getAttribute("data-action-id");
325
- if (actionId) {
326
- this.emitAction(actionId);
327
- }
328
- });
436
+ this.composerEl.addEventListener("click", event => {
437
+ const button = event.target.closest('[part="composer-submit"]');
438
+ if (button) {
439
+ this.submitComposer();
440
+ }
329
441
  });
442
+ this.composerInputEl.addEventListener("keydown", event => {
443
+ if (event.key === "Enter" && (event.metaKey || event.ctrlKey)) {
444
+ event.preventDefault();
445
+ this.submitComposer();
446
+ }
447
+ });
448
+ }
449
+ update() {
450
+ if (!this.entriesEl) {
451
+ return;
452
+ }
453
+ this.titleEl.textContent = this.heading;
454
+ this.messageEl.hidden = !this.message;
455
+ this.messageEl.textContent = this.message;
456
+ const entries = this.entries;
457
+ this.entriesEl.hidden = entries.length === 0;
458
+ this.emptyEl.hidden = entries.length > 0;
459
+ this.entriesEl.setAttribute("aria-label", `${this.heading} entries`);
460
+ const nextEntries = this.entriesKey();
461
+ if (nextEntries !== this.entriesSignature) {
462
+ this.entriesSignature = nextEntries;
463
+ this.rebuildEntries();
464
+ }
465
+ else {
466
+ this.patchEntrySelection();
467
+ }
468
+ const actions = this.actions;
469
+ this.actionsEl.hidden = actions.length === 0;
470
+ const nextActions = this.actionsKey();
471
+ if (nextActions !== this.actionsSignature || this.actionsEl.childElementCount === 0) {
472
+ this.actionsSignature = nextActions;
473
+ this.rebuildActions();
474
+ }
475
+ else {
476
+ this.patchActionLabels();
477
+ }
478
+ const composable = this.composable;
479
+ this.composerEl.hidden = !composable;
480
+ this.composerInputEl.disabled = !composable;
330
481
  }
331
482
  }
332
483
  AnnotationThread.register();
@@ -1,16 +1,16 @@
1
1
  import { BaseElement } from "../../core/index.js";
2
- type AnnotationToolbarTool = {
2
+ export type AnnotationToolbarTool = {
3
3
  disabled?: boolean;
4
4
  icon?: string;
5
5
  id: string;
6
6
  label: string;
7
7
  };
8
- type AnnotationToolbarAction = {
8
+ export type AnnotationToolbarAction = {
9
9
  id: string;
10
10
  label: string;
11
11
  tone?: string;
12
12
  };
13
- type AnnotationToolbarColor = {
13
+ export type AnnotationToolbarColor = {
14
14
  id: string;
15
15
  label: string;
16
16
  value: string;
@@ -18,6 +18,14 @@ type AnnotationToolbarColor = {
18
18
  export declare class AnnotationToolbar extends BaseElement {
19
19
  static readonly tagName: string;
20
20
  static get observedAttributes(): string[];
21
+ private headerEl;
22
+ private toolsEl;
23
+ private colorsEl;
24
+ private actionsSectionEl;
25
+ private actionsEl;
26
+ private toolsSignature;
27
+ private colorsSignature;
28
+ private actionsSignature;
21
29
  get actions(): AnnotationToolbarAction[];
22
30
  set actions(value: AnnotationToolbarAction[]);
23
31
  get activeToolId(): string;
@@ -30,13 +38,19 @@ export declare class AnnotationToolbar extends BaseElement {
30
38
  set label(value: string);
31
39
  get tools(): AnnotationToolbarTool[];
32
40
  set tools(value: AnnotationToolbarTool[]);
33
- connectedCallback(): void;
34
- attributeChangedCallback(name: string, oldValue: string | null, newValue: string | null): void;
35
41
  private parseJsonAttribute;
36
42
  private emitAction;
37
43
  private emitToolSelected;
38
44
  private emitColorSelected;
45
+ private enabledButtons;
46
+ private rebuildTools;
47
+ private rebuildColors;
48
+ private rebuildActions;
49
+ private patchToolSelection;
50
+ private patchColorSelection;
39
51
  protected renderTemplate(): void;
52
+ protected setupListeners(): void;
40
53
  protected update(): void;
54
+ private actionsKey;
55
+ private patchActionLabels;
41
56
  }
42
- export {};