@social.io/catalog 1.3.0 → 2.1.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 (130) hide show
  1. package/.smartconfig.json +51 -0
  2. package/dist_bundle/bundle.js +5455 -3248
  3. package/dist_ts_web/00_commitinfo_data.js +3 -3
  4. package/dist_ts_web/elements/index.d.ts +21 -3
  5. package/dist_ts_web/elements/index.js +28 -7
  6. package/dist_ts_web/elements/sio-ai-card.d.ts +39 -0
  7. package/dist_ts_web/elements/sio-ai-card.js +229 -0
  8. package/dist_ts_web/elements/sio-avatar.d.ts +46 -0
  9. package/dist_ts_web/elements/sio-avatar.js +379 -0
  10. package/dist_ts_web/elements/sio-bucket-header.d.ts +36 -0
  11. package/dist_ts_web/elements/sio-bucket-header.js +197 -0
  12. package/dist_ts_web/elements/sio-button.d.ts +7 -3
  13. package/dist_ts_web/elements/sio-button.js +253 -152
  14. package/dist_ts_web/elements/sio-channel-rail.d.ts +38 -0
  15. package/dist_ts_web/elements/sio-channel-rail.js +288 -0
  16. package/dist_ts_web/elements/sio-chip.d.ts +25 -0
  17. package/dist_ts_web/elements/sio-chip.js +188 -0
  18. package/dist_ts_web/elements/sio-cmdk.d.ts +59 -0
  19. package/dist_ts_web/elements/sio-cmdk.js +471 -0
  20. package/dist_ts_web/elements/sio-combox.d.ts +55 -1
  21. package/dist_ts_web/elements/sio-combox.js +458 -261
  22. package/dist_ts_web/elements/sio-composer.d.ts +48 -0
  23. package/dist_ts_web/elements/sio-composer.js +357 -0
  24. package/dist_ts_web/elements/sio-conversation-selector.d.ts +41 -1
  25. package/dist_ts_web/elements/sio-conversation-selector.js +426 -238
  26. package/dist_ts_web/elements/sio-conversation-view.d.ts +34 -6
  27. package/dist_ts_web/elements/sio-conversation-view.js +738 -564
  28. package/dist_ts_web/elements/sio-dropdown-menu.d.ts +6 -6
  29. package/dist_ts_web/elements/sio-dropdown-menu.js +223 -169
  30. package/dist_ts_web/elements/sio-fab.d.ts +23 -5
  31. package/dist_ts_web/elements/sio-fab.js +259 -235
  32. package/dist_ts_web/elements/sio-glass-toolbar.d.ts +22 -0
  33. package/dist_ts_web/elements/sio-glass-toolbar.js +178 -0
  34. package/dist_ts_web/elements/sio-icon.d.ts +1 -0
  35. package/dist_ts_web/elements/sio-icon.js +254 -94
  36. package/dist_ts_web/elements/sio-image-lightbox.d.ts +3 -4
  37. package/dist_ts_web/elements/sio-image-lightbox.js +282 -191
  38. package/dist_ts_web/elements/sio-inset-list.d.ts +28 -0
  39. package/dist_ts_web/elements/sio-inset-list.js +191 -0
  40. package/dist_ts_web/elements/sio-kbd.d.ts +16 -0
  41. package/dist_ts_web/elements/sio-kbd.js +117 -0
  42. package/dist_ts_web/elements/sio-list-row.d.ts +55 -0
  43. package/dist_ts_web/elements/sio-list-row.js +462 -0
  44. package/dist_ts_web/elements/sio-logo-render.d.ts +42 -0
  45. package/dist_ts_web/elements/sio-logo-render.js +306 -0
  46. package/dist_ts_web/elements/sio-logo.d.ts +64 -0
  47. package/dist_ts_web/elements/sio-logo.js +393 -0
  48. package/dist_ts_web/elements/sio-message-input.d.ts +25 -4
  49. package/dist_ts_web/elements/sio-message-input.js +231 -226
  50. package/dist_ts_web/elements/sio-paper-thumb.d.ts +24 -0
  51. package/dist_ts_web/elements/sio-paper-thumb.js +293 -0
  52. package/dist_ts_web/elements/sio-pdf-viewer.d.ts +2 -0
  53. package/dist_ts_web/elements/sio-pdf-viewer.js +344 -244
  54. package/dist_ts_web/elements/sio-segmented.d.ts +32 -0
  55. package/dist_ts_web/elements/sio-segmented.js +217 -0
  56. package/dist_ts_web/elements/sio-step-timeline.d.ts +28 -0
  57. package/dist_ts_web/elements/sio-step-timeline.js +222 -0
  58. package/dist_ts_web/elements/sio-tab-bar.d.ts +36 -0
  59. package/dist_ts_web/elements/sio-tab-bar.js +232 -0
  60. package/dist_ts_web/elements/sio-unread-badge.d.ts +25 -0
  61. package/dist_ts_web/elements/sio-unread-badge.js +203 -0
  62. package/dist_ts_web/elements/sio-waveform.d.ts +34 -0
  63. package/dist_ts_web/elements/sio-waveform.js +304 -0
  64. package/dist_ts_web/elements/tokens.d.ts +70 -0
  65. package/dist_ts_web/elements/tokens.js +277 -0
  66. package/dist_ts_web/pages/firstpage.d.ts +5 -0
  67. package/dist_ts_web/pages/firstpage.js +21 -2
  68. package/dist_ts_web/pages/mainpage.d.ts +6 -0
  69. package/dist_ts_web/pages/mainpage.js +111 -39
  70. package/{license → license.md} +3 -1
  71. package/package.json +23 -29
  72. package/readme.hints.md +82 -0
  73. package/readme.md +113 -146
  74. package/ts_web/00_commitinfo_data.ts +2 -2
  75. package/ts_web/elements/index.ts +31 -7
  76. package/ts_web/elements/sio-ai-card.ts +175 -0
  77. package/ts_web/elements/sio-avatar.ts +295 -0
  78. package/ts_web/elements/sio-bucket-header.ts +157 -0
  79. package/ts_web/elements/sio-button.ts +149 -127
  80. package/ts_web/elements/sio-channel-rail.ts +256 -0
  81. package/ts_web/elements/sio-chip.ts +134 -0
  82. package/ts_web/elements/sio-cmdk.ts +461 -0
  83. package/ts_web/elements/sio-combox.ts +327 -204
  84. package/ts_web/elements/sio-composer.ts +306 -0
  85. package/ts_web/elements/sio-conversation-selector.ts +350 -228
  86. package/ts_web/elements/sio-conversation-view.ts +573 -457
  87. package/ts_web/elements/sio-dropdown-menu.ts +112 -130
  88. package/ts_web/elements/sio-fab.ts +192 -227
  89. package/ts_web/elements/sio-glass-toolbar.ts +140 -0
  90. package/ts_web/elements/sio-icon.ts +147 -25
  91. package/ts_web/elements/sio-image-lightbox.ts +62 -64
  92. package/ts_web/elements/sio-inset-list.ts +140 -0
  93. package/ts_web/elements/sio-kbd.ts +80 -0
  94. package/ts_web/elements/sio-list-row.ts +393 -0
  95. package/ts_web/elements/sio-logo-render.ts +367 -0
  96. package/ts_web/elements/sio-logo.ts +311 -0
  97. package/ts_web/elements/sio-message-input.ts +142 -221
  98. package/ts_web/elements/sio-paper-thumb.ts +244 -0
  99. package/ts_web/elements/sio-pdf-viewer.ts +58 -60
  100. package/ts_web/elements/sio-segmented.ts +183 -0
  101. package/ts_web/elements/sio-step-timeline.ts +179 -0
  102. package/ts_web/elements/sio-tab-bar.ts +195 -0
  103. package/ts_web/elements/sio-unread-badge.ts +147 -0
  104. package/ts_web/elements/sio-waveform.ts +239 -0
  105. package/ts_web/elements/tokens.ts +297 -0
  106. package/ts_web/pages/firstpage.ts +20 -1
  107. package/ts_web/pages/mainpage.ts +111 -39
  108. package/dist_bundle/bundle.js.map +0 -7
  109. package/dist_ts_web/elements/00colors.d.ts +0 -108
  110. package/dist_ts_web/elements/00colors.js +0 -137
  111. package/dist_ts_web/elements/00fonts.d.ts +0 -60
  112. package/dist_ts_web/elements/00fonts.js +0 -129
  113. package/dist_ts_web/elements/00tokens.d.ts +0 -123
  114. package/dist_ts_web/elements/00tokens.js +0 -176
  115. package/dist_ts_web/elements/sio-conversation-list.d.ts +0 -20
  116. package/dist_ts_web/elements/sio-conversation-list.js +0 -495
  117. package/dist_ts_web/elements/sio-recorder.d.ts +0 -60
  118. package/dist_ts_web/elements/sio-recorder.js +0 -173
  119. package/dist_ts_web/elements/sio-subwidget-conversations.d.ts +0 -16
  120. package/dist_ts_web/elements/sio-subwidget-conversations.js +0 -350
  121. package/dist_ts_web/elements/sio-subwidget-onboardme.d.ts +0 -7
  122. package/dist_ts_web/elements/sio-subwidget-onboardme.js +0 -243
  123. package/dist_watch/bundle.js +0 -81694
  124. package/dist_watch/bundle.js.map +0 -7
  125. package/dist_watch/index.html +0 -25
  126. package/npmextra.json +0 -19
  127. package/ts_web/elements/00colors.ts +0 -164
  128. package/ts_web/elements/00fonts.ts +0 -145
  129. package/ts_web/elements/00tokens.ts +0 -197
  130. package/ts_web/elements/sio-recorder.ts +0 -213
@@ -0,0 +1,80 @@
1
+ import {
2
+ DeesElement,
3
+ html,
4
+ customElement,
5
+ css,
6
+ type TemplateResult,
7
+ } from '@design.estate/dees-element';
8
+
9
+ import { sioElementStyles } from './tokens.js';
10
+
11
+ declare global {
12
+ interface HTMLElementTagNameMap {
13
+ 'sio-kbd': SioKbd;
14
+ }
15
+ }
16
+
17
+ /**
18
+ * sio-kbd — keyboard hint chip (v7 `.sio-kbd`): mono 11px on surface-2
19
+ * with a 0.5px hairline border and 4px radius. Shown in toolbars and the
20
+ * command palette, e.g. ⌘R (reply), E (archive), ⌘K (commands).
21
+ */
22
+ @customElement('sio-kbd')
23
+ export class SioKbd extends DeesElement {
24
+ public static demo = () => html`
25
+ <div style="display: flex; flex-direction: column; gap: 14px;">
26
+ <div style="display: flex; gap: 6px; align-items: center;">
27
+ <sio-kbd>⌘K</sio-kbd>
28
+ <sio-kbd>⌘R</sio-kbd>
29
+ <sio-kbd>⇧⌘A</sio-kbd>
30
+ <sio-kbd>E</sio-kbd>
31
+ <sio-kbd>⌫</sio-kbd>
32
+ <sio-kbd>esc</sio-kbd>
33
+ </div>
34
+ <div style="display: flex; gap: 14px; align-items: center; font-size: 12px;">
35
+ <span style="display: inline-flex; gap: 5px; align-items: center;">
36
+ Reply <sio-kbd>⌘R</sio-kbd>
37
+ </span>
38
+ <span style="display: inline-flex; gap: 5px; align-items: center;">
39
+ Archive <sio-kbd>E</sio-kbd>
40
+ </span>
41
+ <span style="display: inline-flex; gap: 5px; align-items: center;">
42
+ Snooze <sio-kbd>H</sio-kbd>
43
+ </span>
44
+ <span style="display: inline-flex; gap: 5px; align-items: center;">
45
+ Commands <sio-kbd>⌘K</sio-kbd>
46
+ </span>
47
+ </div>
48
+ </div>
49
+ `;
50
+
51
+ public static styles = [
52
+ ...sioElementStyles,
53
+ css`
54
+ :host {
55
+ display: inline-flex;
56
+ flex-shrink: 0;
57
+ }
58
+
59
+ /* v7 .sio-kbd */
60
+ .kbd {
61
+ display: inline-flex;
62
+ align-items: center;
63
+ gap: 2px;
64
+ padding: 1px 5px;
65
+ border-radius: var(--sio-radius-xs);
66
+ background: var(--sio-surface-2);
67
+ color: var(--sio-label-2);
68
+ font-family: var(--sio-font-mono);
69
+ font-size: 11px;
70
+ border: var(--sio-hairline) solid var(--sio-separator);
71
+ white-space: nowrap;
72
+ user-select: none;
73
+ }
74
+ `,
75
+ ];
76
+
77
+ public render(): TemplateResult {
78
+ return html`<span class="kbd"><slot></slot></span>`;
79
+ }
80
+ }
@@ -0,0 +1,393 @@
1
+ import {
2
+ DeesElement,
3
+ html,
4
+ property,
5
+ state,
6
+ customElement,
7
+ css,
8
+ type TemplateResult,
9
+ } from '@design.estate/dees-element';
10
+ import { sioElementStyles, sioTabularNums } from './tokens.js';
11
+ import './sio-icon.js';
12
+
13
+ /**
14
+ * Row density per the v7 spec — comfortable 78px / cozy 62px / compact 48px
15
+ * (`--sio-row-*` tokens) with 14 / 11 / 8px vertical padding.
16
+ */
17
+ export type TSioListRowDensity = 'comfortable' | 'cozy' | 'compact';
18
+
19
+ declare global {
20
+ interface HTMLElementTagNameMap {
21
+ 'sio-list-row': SioListRow;
22
+ }
23
+ }
24
+
25
+ /**
26
+ * sio-list-row — the universal list row of social.io v7
27
+ * (thread lists, unified feed, search results, person history).
28
+ *
29
+ * Anatomy (design source: SIODesktopRow / SIOUniRow / SIORowMobile):
30
+ * [8px unread-dot gutter] [avatar slot] [line1: title + trailing + time]
31
+ * [line2: subject]
32
+ * [preview — clamped 2/1/0 lines]
33
+ * [meta slot — chips]
34
+ * plus a hover-revealed trailing `actions` slot (triage: done/snooze/draft)
35
+ * and a 0.5px inset hairline between rows (hidden on the last row).
36
+ *
37
+ * Slots:
38
+ * avatar — leading avatar (any element; 30px at cozy/comfortable, 24px compact)
39
+ * line1-trailing — small trailing adornments on line 1 (count, star, paperclip)
40
+ * meta — chip row (lane/channel chips, AI summary chip); hidden at compact
41
+ * actions — desktop triage actions, revealed on hover (opacity 0 -> 1, .12s)
42
+ *
43
+ * Events:
44
+ * row-select — bubbles/composed; fired on click or Enter/Space
45
+ * (not fired for clicks inside the `actions` slot).
46
+ */
47
+ @customElement('sio-list-row')
48
+ export class SioListRow extends DeesElement {
49
+ public static demo = () => html`
50
+ <div style="max-width: 420px; font-family: var(--sio-font-sf); display: flex; flex-direction: column; gap: 18px;">
51
+ <div style="background: var(--sio-surface); border-radius: 12px; overflow: hidden; box-shadow: 0 0 0 var(--sio-hairline) var(--sio-separator);">
52
+ <sio-list-row
53
+ unread
54
+ title="Maya Lindqvist"
55
+ time="09:41"
56
+ subject="Q3 numbers ahead of the board call"
57
+ preview="Attached the deck — the growth slide still needs your revenue split before Thursday. Can you take a pass today?"
58
+ density="comfortable"
59
+ >
60
+ <span
61
+ slot="avatar"
62
+ style="width: 30px; height: 30px; border-radius: 50%; background: var(--sio-ch-mail); color: #fff; display: inline-flex; align-items: center; justify-content: center; font-size: 12px; font-weight: 600; letter-spacing: -0.2px;"
63
+ >ML</span>
64
+ <sio-icon slot="line1-trailing" icon="star" size="11" style="color: var(--sio-yellow);"></sio-icon>
65
+ <span
66
+ slot="meta"
67
+ style="display: inline-flex; align-items: center; gap: 4px; padding: 2px 7px; border-radius: 4px; background: color-mix(in oklab, var(--sio-ch-mail) 14%, transparent); color: var(--sio-ch-mail); font-size: 10.5px; font-weight: 700; letter-spacing: 0.04em; text-transform: uppercase;"
68
+ >Mail</span>
69
+ <span slot="meta" style="font-size: 11px; color: var(--sio-label-3);">3 attachments</span>
70
+ <span slot="actions" title="Done" style="width: 24px; height: 24px; border-radius: 6px; color: var(--sio-green); display: inline-flex; align-items: center; justify-content: center;"><sio-icon icon="check" size="13"></sio-icon></span>
71
+ <span slot="actions" title="Snooze" style="width: 24px; height: 24px; border-radius: 6px; color: var(--sio-orange); display: inline-flex; align-items: center; justify-content: center;"><sio-icon icon="clock" size="13"></sio-icon></span>
72
+ <span slot="actions" title="AI draft" style="width: 24px; height: 24px; border-radius: 6px; color: var(--sio-tint); display: inline-flex; align-items: center; justify-content: center;"><sio-icon icon="sparkles" size="13"></sio-icon></span>
73
+ </sio-list-row>
74
+ <sio-list-row
75
+ selected
76
+ title="Jonas Weber"
77
+ time="08:12"
78
+ subject="Launch copy — final review"
79
+ preview="I folded your edits in. One open question on the pricing line."
80
+ density="cozy"
81
+ >
82
+ <span
83
+ slot="avatar"
84
+ style="width: 30px; height: 30px; border-radius: 50%; background: var(--sio-ch-chats); color: #fff; display: inline-flex; align-items: center; justify-content: center; font-size: 12px; font-weight: 600; letter-spacing: -0.2px;"
85
+ >JW</span>
86
+ </sio-list-row>
87
+ <sio-list-row
88
+ unread
89
+ title="Deutsche Post"
90
+ time="Yesterday"
91
+ subject="Letter scanned: Finanzamt München"
92
+ preview="2 pages · OCR ready · deadline detected: Jul 24"
93
+ density="cozy"
94
+ >
95
+ <span
96
+ slot="avatar"
97
+ style="width: 30px; height: 30px; border-radius: 50%; background: var(--sio-ch-letters); color: #fff; display: inline-flex; align-items: center; justify-content: center; font-size: 12px; font-weight: 600; letter-spacing: -0.2px;"
98
+ >DP</span>
99
+ <span slot="line1-trailing" style="font-size: 11px; color: var(--sio-label-3); font-variant-numeric: tabular-nums;">2</span>
100
+ </sio-list-row>
101
+ <sio-list-row
102
+ title="Ana Ferreira"
103
+ time="Tue"
104
+ subject="Missed call · voicemail (0:42)"
105
+ density="compact"
106
+ >
107
+ <span
108
+ slot="avatar"
109
+ style="width: 24px; height: 24px; border-radius: 50%; background: var(--sio-ch-calls); color: #fff; display: inline-flex; align-items: center; justify-content: center; font-size: 10px; font-weight: 600; letter-spacing: -0.2px;"
110
+ >AF</span>
111
+ </sio-list-row>
112
+ </div>
113
+ </div>
114
+ `;
115
+
116
+ @property({ type: String })
117
+ public accessor title = '';
118
+
119
+ /** Trailing timestamp on line 1 — rendered with tabular-nums. */
120
+ @property({ type: String })
121
+ public accessor time = '';
122
+
123
+ /** Line 2 — subject / one-line summary. Tinted when the row is selected. */
124
+ @property({ type: String })
125
+ public accessor subject = '';
126
+
127
+ /** Optional preview text — clamped to 2 lines (comfortable) / 1 line (cozy), hidden at compact. */
128
+ @property({ type: String })
129
+ public accessor preview = '';
130
+
131
+ @property({ type: String, reflect: true })
132
+ public accessor density: TSioListRowDensity = 'cozy';
133
+
134
+ /** Shows the 8px tint dot in the leading gutter. */
135
+ @property({ type: Boolean, reflect: true })
136
+ public accessor unread = false;
137
+
138
+ /** Selected state — tint-soft background, tinted subject line. */
139
+ @property({ type: Boolean, reflect: true })
140
+ public accessor selected = false;
141
+
142
+ @state()
143
+ private accessor hasMeta = false;
144
+
145
+ public static styles = [
146
+ ...sioElementStyles,
147
+ css`
148
+ :host {
149
+ display: block;
150
+ position: relative;
151
+ cursor: default;
152
+ background: transparent;
153
+ transition: background 0.08s ease;
154
+ font-family: var(--sio-font-sf);
155
+ /* inset for the inter-row hairline: 14 pad + 8 gutter + 10 gap + 30 avatar + 10 gap */
156
+ --sio-row-hairline-inset: 72px;
157
+ }
158
+ :host(:hover) {
159
+ background: var(--sio-surface-2);
160
+ }
161
+ :host([selected]) {
162
+ background: var(--sio-tint-soft);
163
+ }
164
+ :host([selected]) .subject {
165
+ color: var(--sio-tint);
166
+ }
167
+ :host([density='compact']) {
168
+ --sio-row-hairline-inset: 66px;
169
+ }
170
+
171
+ .row {
172
+ position: relative;
173
+ display: flex;
174
+ gap: 10px;
175
+ padding: 11px 14px;
176
+ min-height: var(--sio-row-cozy);
177
+ box-sizing: border-box;
178
+ align-items: flex-start;
179
+ outline: none;
180
+ }
181
+ :host([density='comfortable']) .row {
182
+ padding: 14px;
183
+ min-height: var(--sio-row-comfortable);
184
+ }
185
+ :host([density='compact']) .row {
186
+ padding: 8px 14px;
187
+ min-height: var(--sio-row-compact);
188
+ }
189
+ .row:focus-visible {
190
+ box-shadow: inset 0 0 0 2px color-mix(in oklab, var(--sio-tint) 40%, transparent);
191
+ }
192
+
193
+ /* 8px unread-dot gutter */
194
+ .gutter {
195
+ width: 8px;
196
+ flex-shrink: 0;
197
+ padding-top: 8px;
198
+ display: flex;
199
+ justify-content: center;
200
+ }
201
+ .unread-dot {
202
+ width: 8px;
203
+ height: 8px;
204
+ border-radius: 50%;
205
+ background: var(--sio-tint);
206
+ flex-shrink: 0;
207
+ }
208
+
209
+ .avatar {
210
+ flex-shrink: 0;
211
+ display: flex;
212
+ align-items: flex-start;
213
+ }
214
+
215
+ .main {
216
+ flex: 1;
217
+ min-width: 0;
218
+ }
219
+
220
+ .line1 {
221
+ display: flex;
222
+ align-items: baseline;
223
+ gap: 6px;
224
+ }
225
+ .title {
226
+ flex: 1;
227
+ font-size: 13px;
228
+ font-weight: 500;
229
+ color: var(--sio-label);
230
+ letter-spacing: -0.1px;
231
+ overflow: hidden;
232
+ text-overflow: ellipsis;
233
+ white-space: nowrap;
234
+ }
235
+ :host([unread]) .title {
236
+ font-weight: 600;
237
+ }
238
+ .time {
239
+ font-size: 11px;
240
+ color: var(--sio-label-3);
241
+ ${sioTabularNums}
242
+ }
243
+ slot[name='line1-trailing'] {
244
+ display: contents;
245
+ }
246
+
247
+ .subject {
248
+ font-size: 13px;
249
+ font-weight: 400;
250
+ color: var(--sio-label-3);
251
+ overflow: hidden;
252
+ text-overflow: ellipsis;
253
+ white-space: nowrap;
254
+ margin-top: 1px;
255
+ }
256
+ :host([unread]) .subject {
257
+ font-weight: 500;
258
+ color: var(--sio-label);
259
+ }
260
+
261
+ .preview {
262
+ font-size: 12px;
263
+ color: var(--sio-label-3);
264
+ margin-top: 2px;
265
+ line-height: 1.4;
266
+ overflow: hidden;
267
+ display: -webkit-box;
268
+ -webkit-box-orient: vertical;
269
+ -webkit-line-clamp: 1;
270
+ }
271
+ :host([density='comfortable']) .preview {
272
+ -webkit-line-clamp: 2;
273
+ }
274
+ :host([density='compact']) .preview {
275
+ display: none;
276
+ }
277
+
278
+ .meta {
279
+ display: none;
280
+ gap: 6px;
281
+ align-items: center;
282
+ margin-top: 5px;
283
+ }
284
+ .meta.has-content {
285
+ display: flex;
286
+ }
287
+ :host([density='compact']) .meta {
288
+ display: none;
289
+ }
290
+
291
+ /* hover-revealed triage actions — desktop */
292
+ .actions {
293
+ position: absolute;
294
+ right: 10px;
295
+ top: 7px;
296
+ z-index: 5;
297
+ display: flex;
298
+ gap: 2px;
299
+ padding: 3px;
300
+ border-radius: 9px;
301
+ background: var(--sio-glass-bg);
302
+ backdrop-filter: blur(28px) saturate(180%);
303
+ -webkit-backdrop-filter: blur(28px) saturate(180%);
304
+ border: var(--sio-hairline) solid var(--sio-glass-border);
305
+ box-shadow: 0 4px 14px rgba(0, 0, 0, 0.14);
306
+ opacity: 0;
307
+ pointer-events: none;
308
+ transition: opacity 0.12s ease;
309
+ }
310
+ :host(:hover) .actions {
311
+ opacity: 1;
312
+ pointer-events: auto;
313
+ }
314
+
315
+ /* 0.5px inset hairline between rows */
316
+ .hairline {
317
+ position: absolute;
318
+ bottom: 0;
319
+ left: var(--sio-row-hairline-inset);
320
+ right: 0;
321
+ height: var(--sio-hairline);
322
+ background: var(--sio-separator);
323
+ pointer-events: none;
324
+ }
325
+ :host(:last-child) .hairline {
326
+ display: none;
327
+ }
328
+ `,
329
+ ];
330
+
331
+ public render(): TemplateResult {
332
+ return html`
333
+ <div
334
+ class="row"
335
+ role="option"
336
+ tabindex="0"
337
+ aria-selected=${this.selected ? 'true' : 'false'}
338
+ @click=${this.handleSelect}
339
+ @keydown=${this.handleKeydown}
340
+ >
341
+ <div class="gutter">
342
+ ${this.unread ? html`<div class="unread-dot"></div>` : html``}
343
+ </div>
344
+ <div class="avatar">
345
+ <slot name="avatar"></slot>
346
+ </div>
347
+ <div class="main">
348
+ <div class="line1">
349
+ <span class="title">${this.title}</span>
350
+ <slot name="line1-trailing"></slot>
351
+ ${this.time ? html`<span class="time">${this.time}</span>` : html``}
352
+ </div>
353
+ ${this.subject ? html`<div class="subject">${this.subject}</div>` : html``}
354
+ ${this.preview ? html`<div class="preview">${this.preview}</div>` : html``}
355
+ <div class="meta ${this.hasMeta ? 'has-content' : ''}">
356
+ <slot name="meta" @slotchange=${this.handleMetaSlotChange}></slot>
357
+ </div>
358
+ </div>
359
+ <div class="actions">
360
+ <slot name="actions"></slot>
361
+ </div>
362
+ <div class="hairline"></div>
363
+ </div>
364
+ `;
365
+ }
366
+
367
+ private handleMetaSlotChange(eventArg: Event): void {
368
+ const slotElement = eventArg.target as HTMLSlotElement;
369
+ this.hasMeta = slotElement.assignedElements().length > 0;
370
+ }
371
+
372
+ private handleSelect(eventArg: Event): void {
373
+ // clicks inside the triage actions belong to the consumer's own handlers
374
+ const actionsContainer = this.shadowRoot?.querySelector('.actions');
375
+ if (actionsContainer && eventArg.composedPath().includes(actionsContainer)) {
376
+ return;
377
+ }
378
+ this.dispatchEvent(
379
+ new CustomEvent('row-select', {
380
+ detail: { selected: this.selected },
381
+ bubbles: true,
382
+ composed: true,
383
+ }),
384
+ );
385
+ }
386
+
387
+ private handleKeydown(eventArg: KeyboardEvent): void {
388
+ if (eventArg.key === 'Enter' || eventArg.key === ' ') {
389
+ eventArg.preventDefault();
390
+ this.handleSelect(eventArg);
391
+ }
392
+ }
393
+ }