@social.io/catalog 1.3.0 → 2.0.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 (124) hide show
  1. package/.smartconfig.json +51 -0
  2. package/dist_bundle/bundle.js +5450 -3267
  3. package/dist_ts_web/00_commitinfo_data.js +3 -3
  4. package/dist_ts_web/elements/index.d.ts +20 -3
  5. package/dist_ts_web/elements/index.js +27 -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 +37 -0
  15. package/dist_ts_web/elements/sio-channel-rail.js +275 -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-message-input.d.ts +25 -4
  45. package/dist_ts_web/elements/sio-message-input.js +231 -226
  46. package/dist_ts_web/elements/sio-paper-thumb.d.ts +24 -0
  47. package/dist_ts_web/elements/sio-paper-thumb.js +293 -0
  48. package/dist_ts_web/elements/sio-pdf-viewer.d.ts +2 -0
  49. package/dist_ts_web/elements/sio-pdf-viewer.js +344 -244
  50. package/dist_ts_web/elements/sio-segmented.d.ts +32 -0
  51. package/dist_ts_web/elements/sio-segmented.js +217 -0
  52. package/dist_ts_web/elements/sio-step-timeline.d.ts +28 -0
  53. package/dist_ts_web/elements/sio-step-timeline.js +222 -0
  54. package/dist_ts_web/elements/sio-tab-bar.d.ts +36 -0
  55. package/dist_ts_web/elements/sio-tab-bar.js +232 -0
  56. package/dist_ts_web/elements/sio-unread-badge.d.ts +25 -0
  57. package/dist_ts_web/elements/sio-unread-badge.js +203 -0
  58. package/dist_ts_web/elements/sio-waveform.d.ts +34 -0
  59. package/dist_ts_web/elements/sio-waveform.js +304 -0
  60. package/dist_ts_web/elements/tokens.d.ts +70 -0
  61. package/dist_ts_web/elements/tokens.js +277 -0
  62. package/dist_ts_web/pages/firstpage.d.ts +5 -0
  63. package/dist_ts_web/pages/firstpage.js +21 -2
  64. package/dist_ts_web/pages/mainpage.d.ts +6 -0
  65. package/dist_ts_web/pages/mainpage.js +111 -39
  66. package/{license → license.md} +3 -1
  67. package/package.json +23 -29
  68. package/readme.hints.md +81 -0
  69. package/readme.md +85 -151
  70. package/ts_web/00_commitinfo_data.ts +2 -2
  71. package/ts_web/elements/index.ts +30 -7
  72. package/ts_web/elements/sio-ai-card.ts +175 -0
  73. package/ts_web/elements/sio-avatar.ts +295 -0
  74. package/ts_web/elements/sio-bucket-header.ts +157 -0
  75. package/ts_web/elements/sio-button.ts +149 -127
  76. package/ts_web/elements/sio-channel-rail.ts +243 -0
  77. package/ts_web/elements/sio-chip.ts +134 -0
  78. package/ts_web/elements/sio-cmdk.ts +461 -0
  79. package/ts_web/elements/sio-combox.ts +327 -204
  80. package/ts_web/elements/sio-composer.ts +306 -0
  81. package/ts_web/elements/sio-conversation-selector.ts +350 -228
  82. package/ts_web/elements/sio-conversation-view.ts +573 -457
  83. package/ts_web/elements/sio-dropdown-menu.ts +112 -130
  84. package/ts_web/elements/sio-fab.ts +192 -227
  85. package/ts_web/elements/sio-glass-toolbar.ts +140 -0
  86. package/ts_web/elements/sio-icon.ts +147 -25
  87. package/ts_web/elements/sio-image-lightbox.ts +62 -64
  88. package/ts_web/elements/sio-inset-list.ts +140 -0
  89. package/ts_web/elements/sio-kbd.ts +80 -0
  90. package/ts_web/elements/sio-list-row.ts +393 -0
  91. package/ts_web/elements/sio-message-input.ts +142 -221
  92. package/ts_web/elements/sio-paper-thumb.ts +244 -0
  93. package/ts_web/elements/sio-pdf-viewer.ts +58 -60
  94. package/ts_web/elements/sio-segmented.ts +183 -0
  95. package/ts_web/elements/sio-step-timeline.ts +179 -0
  96. package/ts_web/elements/sio-tab-bar.ts +195 -0
  97. package/ts_web/elements/sio-unread-badge.ts +147 -0
  98. package/ts_web/elements/sio-waveform.ts +239 -0
  99. package/ts_web/elements/tokens.ts +297 -0
  100. package/ts_web/pages/firstpage.ts +20 -1
  101. package/ts_web/pages/mainpage.ts +111 -39
  102. package/dist_bundle/bundle.js.map +0 -7
  103. package/dist_ts_web/elements/00colors.d.ts +0 -108
  104. package/dist_ts_web/elements/00colors.js +0 -137
  105. package/dist_ts_web/elements/00fonts.d.ts +0 -60
  106. package/dist_ts_web/elements/00fonts.js +0 -129
  107. package/dist_ts_web/elements/00tokens.d.ts +0 -123
  108. package/dist_ts_web/elements/00tokens.js +0 -176
  109. package/dist_ts_web/elements/sio-conversation-list.d.ts +0 -20
  110. package/dist_ts_web/elements/sio-conversation-list.js +0 -495
  111. package/dist_ts_web/elements/sio-recorder.d.ts +0 -60
  112. package/dist_ts_web/elements/sio-recorder.js +0 -173
  113. package/dist_ts_web/elements/sio-subwidget-conversations.d.ts +0 -16
  114. package/dist_ts_web/elements/sio-subwidget-conversations.js +0 -350
  115. package/dist_ts_web/elements/sio-subwidget-onboardme.d.ts +0 -7
  116. package/dist_ts_web/elements/sio-subwidget-onboardme.js +0 -243
  117. package/dist_watch/bundle.js +0 -81694
  118. package/dist_watch/bundle.js.map +0 -7
  119. package/dist_watch/index.html +0 -25
  120. package/npmextra.json +0 -19
  121. package/ts_web/elements/00colors.ts +0 -164
  122. package/ts_web/elements/00fonts.ts +0 -145
  123. package/ts_web/elements/00tokens.ts +0 -197
  124. 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
+ }