@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
@@ -4,16 +4,13 @@ import {
4
4
  html,
5
5
  customElement,
6
6
  type TemplateResult,
7
- cssManager,
8
7
  css,
9
- unsafeCSS,
10
8
  state,
11
9
  } from '@design.estate/dees-element';
12
10
 
13
- // Import design tokens
14
- import { bdTheme } from './00colors.js';
15
- import { spacing, radius, shadows } from './00tokens.js';
16
- import { fontFamilies } from './00fonts.js';
11
+ import { sioElementStyles } from './tokens.js';
12
+ import './sio-icon.js';
13
+ import './sio-button.js';
17
14
 
18
15
  declare global {
19
16
  interface HTMLElementTagNameMap {
@@ -65,15 +62,15 @@ export class SioPdfViewer extends DeesElement {
65
62
  private resizeObserver: ResizeObserver | null = null;
66
63
 
67
64
  public static styles = [
68
- cssManager.defaultStyles,
65
+ ...sioElementStyles,
69
66
  css`
70
67
  :host {
71
68
  display: block;
72
69
  width: 100%;
73
70
  height: 100%;
74
71
  position: relative;
75
- background: ${bdTheme('background')};
76
- font-family: ${unsafeCSS(fontFamilies.sans)};
72
+ background: var(--sio-surface);
73
+ font-family: var(--sio-font-sf);
77
74
  }
78
75
 
79
76
  .container {
@@ -91,46 +88,46 @@ export class SioPdfViewer extends DeesElement {
91
88
  display: flex;
92
89
  flex-direction: column;
93
90
  align-items: center;
94
- background: ${bdTheme('muted')};
91
+ background: var(--sio-bg);
95
92
  }
96
-
93
+
97
94
  .pdf-canvas-wrapper {
98
95
  position: relative;
99
- margin: ${unsafeCSS(spacing["4"])} auto;
100
- box-shadow: ${unsafeCSS(shadows.lg)};
101
- background: white;
96
+ margin: 16px auto;
97
+ box-shadow: 0 8px 24px -4px rgba(0, 0, 0, 0.1), 0 2px 8px -2px rgba(0, 0, 0, 0.04);
98
+ background: var(--sio-surface);
102
99
  }
103
-
100
+
104
101
  canvas {
105
102
  display: block;
106
103
  max-width: 100%;
107
104
  height: auto;
108
105
  }
109
-
106
+
110
107
  .pdf-controls {
111
108
  position: sticky;
112
109
  top: 0;
113
110
  z-index: 10;
114
111
  width: 100%;
115
- padding: ${unsafeCSS(spacing["3"])};
116
- background: ${bdTheme('background')};
117
- border-bottom: 1px solid ${bdTheme('border')};
112
+ padding: 12px;
113
+ background: var(--sio-surface);
114
+ border-bottom: var(--sio-hairline) solid var(--sio-separator);
118
115
  display: flex;
119
116
  align-items: center;
120
117
  justify-content: center;
121
- gap: ${unsafeCSS(spacing["3"])};
122
- box-shadow: ${unsafeCSS(shadows.sm)};
118
+ gap: 12px;
123
119
  }
124
-
120
+
125
121
  .pdf-controls-group {
126
122
  display: flex;
127
123
  align-items: center;
128
- gap: ${unsafeCSS(spacing["2"])};
124
+ gap: 8px;
129
125
  }
130
-
126
+
131
127
  .page-info {
132
- font-size: 0.875rem;
133
- color: ${bdTheme('mutedForeground')};
128
+ font-size: 13px;
129
+ color: var(--sio-label-3);
130
+ font-variant-numeric: tabular-nums;
134
131
  min-width: 100px;
135
132
  text-align: center;
136
133
  }
@@ -141,12 +138,12 @@ export class SioPdfViewer extends DeesElement {
141
138
  left: 50%;
142
139
  transform: translate(-50%, -50%);
143
140
  text-align: center;
144
- color: ${bdTheme('mutedForeground')};
141
+ color: var(--sio-label-3);
145
142
  }
146
143
 
147
144
  .spinner {
148
145
  animation: spin 1s linear infinite;
149
- margin-bottom: ${unsafeCSS(spacing["2"])};
146
+ margin-bottom: 8px;
150
147
  }
151
148
 
152
149
  @keyframes spin {
@@ -164,35 +161,36 @@ export class SioPdfViewer extends DeesElement {
164
161
  left: 50%;
165
162
  transform: translate(-50%, -50%);
166
163
  text-align: center;
167
- padding: ${unsafeCSS(spacing["6"])};
168
- background: ${bdTheme('card')};
169
- border: 1px solid ${bdTheme('border')};
170
- border-radius: ${unsafeCSS(radius.lg)};
171
- box-shadow: ${unsafeCSS(shadows.md)};
164
+ padding: 24px;
165
+ background: var(--sio-surface);
166
+ border: var(--sio-hairline) solid var(--sio-separator);
167
+ border-radius: var(--sio-radius-lg);
168
+ box-shadow: 0 4px 12px -4px rgba(0, 0, 0, 0.1), 0 2px 4px -2px rgba(0, 0, 0, 0.04);
172
169
  max-width: 400px;
173
170
  }
174
171
 
175
172
  .error-icon {
176
- color: ${bdTheme('destructive')};
177
- margin-bottom: ${unsafeCSS(spacing["3"])};
173
+ color: var(--sio-red);
174
+ margin-bottom: 12px;
178
175
  }
179
176
 
180
177
  .error-title {
181
- font-size: 1.125rem;
178
+ font-size: 17px;
182
179
  font-weight: 600;
183
- color: ${bdTheme('foreground')};
184
- margin-bottom: ${unsafeCSS(spacing["2"])};
180
+ letter-spacing: -0.43px;
181
+ color: var(--sio-label);
182
+ margin-bottom: 8px;
185
183
  }
186
184
 
187
185
  .error-message {
188
- color: ${bdTheme('mutedForeground')};
189
- margin-bottom: ${unsafeCSS(spacing["4"])};
190
- font-size: 0.875rem;
186
+ color: var(--sio-label-3);
187
+ margin-bottom: 16px;
188
+ font-size: 13px;
191
189
  }
192
190
 
193
191
  .error-actions {
194
192
  display: flex;
195
- gap: ${unsafeCSS(spacing["2"])};
193
+ gap: 8px;
196
194
  justify-content: center;
197
195
  }
198
196
 
@@ -201,24 +199,24 @@ export class SioPdfViewer extends DeesElement {
201
199
  height: 100%;
202
200
  display: flex;
203
201
  flex-direction: column;
204
- background: ${bdTheme('background')};
202
+ background: var(--sio-surface);
205
203
  }
206
204
 
207
205
  .fallback-header {
208
- padding: ${unsafeCSS(spacing["4"])};
209
- border-bottom: 1px solid ${bdTheme('border')};
206
+ padding: 16px;
207
+ border-bottom: var(--sio-hairline) solid var(--sio-separator);
210
208
  display: flex;
211
209
  align-items: center;
212
210
  justify-content: space-between;
213
- background: ${bdTheme('card')};
211
+ background: var(--sio-surface);
214
212
  }
215
213
 
216
214
  .fallback-title {
217
215
  font-weight: 500;
218
- color: ${bdTheme('foreground')};
216
+ color: var(--sio-label);
219
217
  display: flex;
220
218
  align-items: center;
221
- gap: ${unsafeCSS(spacing["2"])};
219
+ gap: 8px;
222
220
  }
223
221
 
224
222
  .fallback-content {
@@ -226,24 +224,24 @@ export class SioPdfViewer extends DeesElement {
226
224
  display: flex;
227
225
  align-items: center;
228
226
  justify-content: center;
229
- padding: ${unsafeCSS(spacing["8"])};
227
+ padding: 32px;
230
228
  }
231
229
 
232
230
  .fallback-message {
233
231
  text-align: center;
234
- color: ${bdTheme('mutedForeground')};
232
+ color: var(--sio-label-3);
235
233
  }
236
234
 
237
235
  .fallback-icon {
238
236
  font-size: 48px;
239
- margin-bottom: ${unsafeCSS(spacing["4"])};
237
+ margin-bottom: 16px;
240
238
  opacity: 0.5;
241
239
  }
242
240
 
243
241
  .fallback-text {
244
- margin-bottom: ${unsafeCSS(spacing["4"])};
242
+ margin-bottom: 16px;
245
243
  }
246
-
244
+
247
245
  /* Scrollbar styling */
248
246
  .pdf-container::-webkit-scrollbar {
249
247
  width: 8px;
@@ -251,25 +249,25 @@ export class SioPdfViewer extends DeesElement {
251
249
  }
252
250
 
253
251
  .pdf-container::-webkit-scrollbar-track {
254
- background: ${bdTheme('muted')};
252
+ background: var(--sio-bg);
255
253
  }
256
254
 
257
255
  .pdf-container::-webkit-scrollbar-thumb {
258
- background: ${bdTheme('border')};
256
+ background: var(--sio-separator-opaque);
259
257
  border-radius: 4px;
260
258
  }
261
259
 
262
260
  .pdf-container::-webkit-scrollbar-thumb:hover {
263
- background: ${bdTheme('mutedForeground')};
261
+ background: var(--sio-label-4);
264
262
  }
265
-
263
+
266
264
  /* Responsive */
267
265
  @media (max-width: 600px) {
268
266
  .pdf-controls {
269
267
  flex-wrap: wrap;
270
- gap: ${unsafeCSS(spacing["2"])};
268
+ gap: 8px;
271
269
  }
272
-
270
+
273
271
  .pdf-controls-group {
274
272
  flex-wrap: nowrap;
275
273
  }
@@ -523,7 +521,7 @@ export class SioPdfViewer extends DeesElement {
523
521
  this.renderTask = page.render(renderContext);
524
522
  await this.renderTask.promise;
525
523
  } catch (error) {
526
- if (error.name !== 'RenderingCancelledException') {
524
+ if ((error as any).name !== 'RenderingCancelledException') {
527
525
  console.error('Error rendering page:', error);
528
526
  }
529
527
  }
@@ -0,0 +1,183 @@
1
+ import {
2
+ DeesElement,
3
+ html,
4
+ property,
5
+ customElement,
6
+ css,
7
+ cssManager,
8
+ type TemplateResult,
9
+ } from '@design.estate/dees-element';
10
+ import { sioElementStyles } from './tokens.js';
11
+
12
+ declare global {
13
+ interface HTMLElementTagNameMap {
14
+ 'sio-segmented': SioSegmented;
15
+ }
16
+ }
17
+
18
+ export interface ISioSegment {
19
+ id: string;
20
+ label: string;
21
+ count?: number;
22
+ }
23
+
24
+ export interface ISioSegmentChangeDetail {
25
+ id: string;
26
+ segment: ISioSegment;
27
+ }
28
+
29
+ /**
30
+ * sio-segmented — iOS-style segmented control (v7 prototype:
31
+ * SocialIOUnified.jsx mode switch — Priority / Timeline / By person).
32
+ *
33
+ * Recessed systemGray track (2px inner padding, radius 9), the selected
34
+ * segment floats on a white / systemGray knob with the layered iOS shadow
35
+ * and steps up to weight 600. Selecting a segment dispatches
36
+ * `segment-change` with `{ id, segment }` (bubbles, composed).
37
+ */
38
+ @customElement('sio-segmented')
39
+ export class SioSegmented extends DeesElement {
40
+ public static demo = () => html`
41
+ <div
42
+ style="display: flex; flex-direction: column; gap: 20px; max-width: 360px; padding: 20px; border-radius: 14px; background: var(--sio-bg); font-family: var(--sio-font-sf);"
43
+ >
44
+ <sio-segmented
45
+ .segments=${[
46
+ { id: 'priority', label: 'Priority' },
47
+ { id: 'time', label: 'Timeline' },
48
+ { id: 'person', label: 'By person' },
49
+ ]}
50
+ selected="priority"
51
+ ></sio-segmented>
52
+
53
+ <sio-segmented
54
+ .segments=${[
55
+ { id: 'feed', label: 'Feed', count: 12 },
56
+ { id: 'paper', label: 'Paper', count: 4 },
57
+ { id: 'people', label: 'People', count: 3 },
58
+ ]}
59
+ selected="people"
60
+ ></sio-segmented>
61
+
62
+ <sio-segmented
63
+ .segments=${[
64
+ { id: 'all', label: 'All' },
65
+ { id: 'unread', label: 'Unread', count: 7 },
66
+ ]}
67
+ selected="all"
68
+ ></sio-segmented>
69
+ </div>
70
+ `;
71
+
72
+ @property({ type: Array })
73
+ public accessor segments: ISioSegment[] = [];
74
+
75
+ @property({ type: String })
76
+ public accessor selected = '';
77
+
78
+ public static styles = [
79
+ ...sioElementStyles,
80
+ css`
81
+ :host {
82
+ display: block;
83
+
84
+ /* iOS UISegmentedControl selected fill — white in light, systemGray
85
+ #636366 in dark. Not modeled in tokens.ts (it is knob-specific,
86
+ not a surface), so it branches here via the same theme mechanism
87
+ tokens.ts uses — no string concatenation. */
88
+ --sio-segmented-knob: ${cssManager.bdTheme('#FFFFFF', '#636366')};
89
+ }
90
+
91
+ .track {
92
+ display: flex;
93
+ padding: 2px;
94
+ border-radius: 9px;
95
+ background: var(--sio-surface-2);
96
+ }
97
+
98
+ .segment {
99
+ appearance: none;
100
+ border: none;
101
+ margin: 0;
102
+ flex: 1;
103
+ min-width: 0;
104
+ display: inline-flex;
105
+ align-items: center;
106
+ justify-content: center;
107
+ gap: 5px;
108
+ padding: 5px 0;
109
+ border-radius: 7px;
110
+ background: transparent;
111
+ font-family: var(--sio-font-sf);
112
+ font-size: 13px;
113
+ font-weight: 500;
114
+ letter-spacing: -0.1px;
115
+ line-height: 1.25;
116
+ color: var(--sio-label-3);
117
+ white-space: nowrap;
118
+ cursor: pointer;
119
+ -webkit-tap-highlight-color: transparent;
120
+ transition: color 120ms ease, background 120ms ease, box-shadow 120ms ease;
121
+ }
122
+
123
+ .segment:focus-visible {
124
+ outline: 2px solid color-mix(in oklab, var(--sio-tint) 40%, transparent);
125
+ outline-offset: 1px;
126
+ }
127
+
128
+ .segment.selected {
129
+ background: var(--sio-segmented-knob);
130
+ color: var(--sio-label);
131
+ font-weight: 600;
132
+ box-shadow:
133
+ 0 1px 4px rgba(0, 0, 0, 0.12),
134
+ 0 0 0 0.5px rgba(0, 0, 0, 0.04);
135
+ }
136
+
137
+ .count {
138
+ font-variant-numeric: tabular-nums;
139
+ font-size: 12px;
140
+ font-weight: 500;
141
+ opacity: 0.55;
142
+ }
143
+ `,
144
+ ];
145
+
146
+ public render(): TemplateResult {
147
+ const selectedId = this.selected || this.segments[0]?.id;
148
+ return html`
149
+ <div class="track" role="tablist">
150
+ ${this.segments.map(
151
+ (segment) => html`
152
+ <button
153
+ type="button"
154
+ role="tab"
155
+ class="segment ${segment.id === selectedId ? 'selected' : ''}"
156
+ aria-selected=${segment.id === selectedId ? 'true' : 'false'}
157
+ @click=${() => this.handleSelect(segment)}
158
+ >
159
+ ${segment.label}
160
+ ${segment.count !== undefined
161
+ ? html`<span class="count">${segment.count}</span>`
162
+ : html``}
163
+ </button>
164
+ `,
165
+ )}
166
+ </div>
167
+ `;
168
+ }
169
+
170
+ private handleSelect(segment: ISioSegment): void {
171
+ if (segment.id === this.selected) {
172
+ return;
173
+ }
174
+ this.selected = segment.id;
175
+ this.dispatchEvent(
176
+ new CustomEvent<ISioSegmentChangeDetail>('segment-change', {
177
+ detail: { id: segment.id, segment },
178
+ bubbles: true,
179
+ composed: true,
180
+ }),
181
+ );
182
+ }
183
+ }
@@ -0,0 +1,179 @@
1
+ import {
2
+ DeesElement,
3
+ html,
4
+ property,
5
+ customElement,
6
+ css,
7
+ type TemplateResult,
8
+ } from '@design.estate/dees-element';
9
+ import { sioElementStyles } from './tokens.js';
10
+
11
+ export interface ISioStepTimelineStep {
12
+ when: string;
13
+ label: string;
14
+ done: boolean;
15
+ }
16
+
17
+ declare global {
18
+ interface HTMLElementTagNameMap {
19
+ 'sio-step-timeline': SioStepTimeline;
20
+ }
21
+ }
22
+
23
+ /**
24
+ * sio-step-timeline — v7 vertical tracking timeline (outbound letters,
25
+ * delivery receipts, meeting prep …).
26
+ *
27
+ * 14px dots take the accent color once a step is done; the 2px connecting
28
+ * line only colors between two completed steps. Labels sit at 14.5px with
29
+ * muted 12px timestamps underneath — exactly the SIOLetterTracking recipe.
30
+ */
31
+ @customElement('sio-step-timeline')
32
+ export class SioStepTimeline extends DeesElement {
33
+ public static demo = () => html`
34
+ <div
35
+ style="display: flex; flex-wrap: wrap; gap: 20px; padding: 20px; background: var(--sio-bg); border-radius: 18px; font-family: var(--sio-font-sf);"
36
+ >
37
+ <div
38
+ style="flex: 1; min-width: 260px; background: var(--sio-surface); border: 0.5px solid var(--sio-separator); border-radius: 16px; padding: 14px 16px;"
39
+ >
40
+ <div
41
+ style="font-size: 11px; font-weight: 700; color: var(--sio-label-3); letter-spacing: 0.06em; text-transform: uppercase; margin-bottom: 12px;"
42
+ >
43
+ Tracking
44
+ </div>
45
+ <sio-step-timeline
46
+ .steps=${[
47
+ { when: 'Today 08:10', label: 'Printed at Berlin-Mitte print hub', done: true },
48
+ { when: 'Today 09:42', label: 'Handed to Deutsche Post', done: true },
49
+ { when: 'Tomorrow', label: 'In transit', done: false },
50
+ { when: 'Thu', label: 'Delivered', done: false },
51
+ ]}
52
+ ></sio-step-timeline>
53
+ </div>
54
+ <div
55
+ style="flex: 1; min-width: 260px; background: var(--sio-surface); border: 0.5px solid var(--sio-separator); border-radius: 16px; padding: 14px 16px;"
56
+ >
57
+ <div
58
+ style="font-size: 11px; font-weight: 700; color: var(--sio-label-3); letter-spacing: 0.06em; text-transform: uppercase; margin-bottom: 12px;"
59
+ >
60
+ Delivery
61
+ </div>
62
+ <sio-step-timeline
63
+ color="var(--sio-bucket-done)"
64
+ .steps=${[
65
+ { when: 'Mon 14:48', label: 'Printed at Berlin-Mitte print hub', done: true },
66
+ { when: 'Mon 16:02', label: 'Handed to Deutsche Post', done: true },
67
+ { when: 'Tue', label: 'In transit', done: true },
68
+ { when: 'Wed 11:15', label: 'Delivered', done: true },
69
+ ]}
70
+ ></sio-step-timeline>
71
+ </div>
72
+ </div>
73
+ `;
74
+
75
+ /** Ordered steps, first to last. */
76
+ @property({ type: Array })
77
+ public accessor steps: ISioStepTimelineStep[] = [];
78
+
79
+ /** Accent for completed dots + connecting lines. Defaults to the letters channel. */
80
+ @property({ type: String })
81
+ public accessor color: string = 'var(--sio-ch-letters)';
82
+
83
+ public static styles = [
84
+ ...sioElementStyles,
85
+ css`
86
+ :host {
87
+ display: block;
88
+ color: var(--sio-label);
89
+ }
90
+
91
+ .step {
92
+ position: relative;
93
+ display: flex;
94
+ gap: 12px;
95
+ margin-bottom: 14px;
96
+ }
97
+ .step:last-child {
98
+ margin-bottom: 0;
99
+ }
100
+
101
+ .dot {
102
+ box-sizing: border-box;
103
+ width: 14px;
104
+ height: 14px;
105
+ border-radius: 7px;
106
+ margin-top: 3px;
107
+ flex-shrink: 0;
108
+ background: transparent;
109
+ border: 2px solid var(--sio-label-3);
110
+ position: relative;
111
+ z-index: 2;
112
+ }
113
+ .step.done .dot {
114
+ background: var(--step-color);
115
+ border-color: var(--step-color);
116
+ }
117
+
118
+ .line {
119
+ position: absolute;
120
+ left: 6px;
121
+ top: 17px;
122
+ bottom: -14px;
123
+ width: 2px;
124
+ background: var(--sio-separator);
125
+ }
126
+ .line.done {
127
+ background: var(--step-color);
128
+ }
129
+
130
+ .body {
131
+ flex: 1;
132
+ min-width: 0;
133
+ padding-bottom: 2px;
134
+ }
135
+
136
+ .label {
137
+ font-size: 14.5px;
138
+ line-height: 1.35;
139
+ font-weight: 400;
140
+ color: var(--sio-label);
141
+ }
142
+ .step.done .label {
143
+ font-weight: 500;
144
+ }
145
+
146
+ .when {
147
+ font-size: 12px;
148
+ color: var(--sio-label-3);
149
+ margin-top: 1px;
150
+ font-variant-numeric: tabular-nums;
151
+ }
152
+ `,
153
+ ];
154
+
155
+ public render(): TemplateResult {
156
+ return html`
157
+ <div style="--step-color: ${this.color};">
158
+ ${this.steps.map(
159
+ (step, index) => html`
160
+ <div class="step ${step.done ? 'done' : ''}">
161
+ <div class="dot"></div>
162
+ ${index < this.steps.length - 1
163
+ ? html`
164
+ <div
165
+ class="line ${step.done && this.steps[index + 1].done ? 'done' : ''}"
166
+ ></div>
167
+ `
168
+ : html``}
169
+ <div class="body">
170
+ <div class="label">${step.label}</div>
171
+ <div class="when">${step.when}</div>
172
+ </div>
173
+ </div>
174
+ `,
175
+ )}
176
+ </div>
177
+ `;
178
+ }
179
+ }