@swr-data-lab/components 2.26.1 → 2.29.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 (33) hide show
  1. package/dist/Breakout/Breakout.svelte +93 -0
  2. package/dist/Breakout/Breakout.svelte.d.ts +8 -0
  3. package/dist/Breakout/index.d.ts +2 -0
  4. package/dist/Breakout/index.js +2 -0
  5. package/dist/ChartList/ChartList.svelte +7 -9
  6. package/dist/Copy/Copy.svelte +4 -6
  7. package/dist/Copy/Copy.svelte.d.ts +1 -0
  8. package/dist/DesignTokens/DesignTokens.svelte +2 -0
  9. package/dist/DesignTokens/Tokens.js +6 -2
  10. package/dist/DevContainer/DevContainer.svelte +423 -0
  11. package/dist/DevContainer/DevContainer.svelte.d.ts +18 -0
  12. package/dist/DevContainer/GridInspector.svelte +43 -0
  13. package/dist/DevContainer/GridInspector.svelte.d.ts +6 -0
  14. package/dist/DevContainer/SwrLogo.svg.svelte +8 -0
  15. package/dist/DevContainer/SwrLogo.svg.svelte.d.ts +26 -0
  16. package/dist/DevContainer/index.d.ts +2 -0
  17. package/dist/DevContainer/index.js +2 -0
  18. package/dist/Headline/Headline.svelte +1 -3
  19. package/dist/ScrollerSection/ScrollerSection.svelte +36 -0
  20. package/dist/ScrollerSection/ScrollerSection.svelte.d.ts +8 -0
  21. package/dist/ScrollerSection/index.d.ts +2 -0
  22. package/dist/ScrollerSection/index.js +2 -0
  23. package/dist/index.d.ts +5 -2
  24. package/dist/index.js +8 -3
  25. package/dist/maplibre/MapStyle/SWRDataLabDark.d.ts +1 -1
  26. package/dist/maplibre/MapStyle/SWRDataLabDark.js +4 -5
  27. package/dist/maplibre/MapStyle/SWRDataLabLight.d.ts +1 -1
  28. package/dist/maplibre/MapStyle/SWRDataLabLight.js +4 -2
  29. package/dist/maplibre/MapStyle/defaultOptions.d.ts +3 -0
  30. package/dist/maplibre/MapStyle/defaultOptions.js +10 -0
  31. package/dist/maplibre/MapStyle/types.d.ts +3 -0
  32. package/dist/maplibre/Tooltip/Tooltip.svelte +5 -1
  33. package/package.json +3 -3
@@ -0,0 +1,93 @@
1
+ <script lang="ts">let { layout = 'medium', children } = $props();
2
+ export {};
3
+ </script>
4
+
5
+ <div class={`container ${layout}`}>
6
+ {@render children?.()}
7
+ </div>
8
+
9
+ <style>.container {
10
+ --margin: 16px;
11
+ --column-gap: 16px;
12
+ --column-width: calc((var(--grid-width) - var(--column-gap) * 11) / 12);
13
+ --grid-width: calc(100vw - var(--margin) * 2);
14
+ }
15
+ @media (min-width: 640px) {
16
+ .container {
17
+ --margin: 40px;
18
+ }
19
+ }
20
+ @media (min-width: 768px) {
21
+ .container {
22
+ --margin: 40px;
23
+ }
24
+ }
25
+ @media (min-width: 1024px) {
26
+ .container {
27
+ --margin: 48px;
28
+ --column-gap: 32px;
29
+ }
30
+ }
31
+ @media (min-width: 1440px) {
32
+ .container {
33
+ --grid-width: calc(Min(1312px, 100vw));
34
+ --margin: calc((100vw - var(--grid-width)) * 0.5);
35
+ }
36
+ }
37
+
38
+ @media (min-width: 1024px) {
39
+ .medium {
40
+ width: calc(var(--column-width) * 10 + var(--column-gap) * 9);
41
+ margin-left: calc(var(--column-width) * -1 + (var(--column-gap)) * -1);
42
+ }
43
+ }
44
+ @media (min-width: 1440px) {
45
+ .medium {
46
+ width: calc(var(--column-width) * 8 + var(--column-gap) * 7);
47
+ margin-left: calc(var(--column-width) * -1 + (var(--column-gap)) * -1);
48
+ }
49
+ }
50
+
51
+ @media (min-width: 640px) {
52
+ .large {
53
+ width: calc(var(--column-width) * 12 + var(--column-gap) * 11);
54
+ margin-left: calc(var(--column-width) * -1 + var(--column-gap) * -1);
55
+ }
56
+ }
57
+ @media (min-width: 1024px) {
58
+ .large {
59
+ width: calc(var(--column-width) * 12 + var(--column-gap) * 11);
60
+ margin-left: calc(var(--column-width) * -2 + var(--column-gap) * -2);
61
+ }
62
+ }
63
+ @media (min-width: 1440px) {
64
+ .large {
65
+ width: calc(var(--column-width) * 10 + var(--column-gap) * 11);
66
+ margin-left: calc(var(--column-width) * -2 + var(--column-gap) * -3);
67
+ }
68
+ }
69
+
70
+ .bleed {
71
+ width: 100vw;
72
+ margin-left: calc(var(--margin) * -1);
73
+ }
74
+ @media (min-width: 640px) {
75
+ .bleed {
76
+ margin-left: calc(var(--column-width) * -1 + (var(--column-gap)) * -1 - var(--margin) * 1);
77
+ }
78
+ }
79
+ @media (min-width: 768px) {
80
+ .bleed {
81
+ margin-left: calc(var(--column-width) * -1 + (var(--column-gap)) * -1 - var(--margin) * 1);
82
+ }
83
+ }
84
+ @media (min-width: 1024px) {
85
+ .bleed {
86
+ margin-left: calc(var(--column-width) * -2 + (var(--column-gap)) * -2 - var(--margin) * 1);
87
+ }
88
+ }
89
+ @media (min-width: 1440px) {
90
+ .bleed {
91
+ margin-left: calc(var(--column-width) * -3 + (var(--column-gap)) * -3 - var(--margin) * 1);
92
+ }
93
+ }</style>
@@ -0,0 +1,8 @@
1
+ import type { Snippet } from 'svelte';
2
+ interface BreakoutProps {
3
+ layout: 'medium' | 'large' | 'bleed';
4
+ children?: Snippet;
5
+ }
6
+ declare const Breakout: import("svelte").Component<BreakoutProps, {}, "">;
7
+ type Breakout = ReturnType<typeof Breakout>;
8
+ export default Breakout;
@@ -0,0 +1,2 @@
1
+ import Breakout from './Breakout.svelte';
2
+ export default Breakout;
@@ -0,0 +1,2 @@
1
+ import Breakout from './Breakout.svelte';
2
+ export default Breakout;
@@ -30,8 +30,8 @@ let { project, charts, baseUrl } = $props();
30
30
  </tbody>
31
31
  </table>
32
32
  {/if}
33
+ <p class="notes">Nutze die "Embed URL" um Grafiken in Sophora einzubinden.</p>
33
34
  </div>
34
- <p class="notes">Nutze die "Embed URL" um Grafiken in Sophora einzubinden.</p>
35
35
  </main>
36
36
 
37
37
  <style>main {
@@ -41,8 +41,8 @@ let { project, charts, baseUrl } = $props();
41
41
  flex-flow: column;
42
42
  font-family: var(--swr-sans);
43
43
  font-size: var(--fs-small-1);
44
+ background: var(--color-pageFill);
44
45
  color: var(--color-textPrimary);
45
- max-width: 40rem;
46
46
  margin: 0 auto;
47
47
  height: 90vh;
48
48
  }
@@ -52,16 +52,14 @@ main * {
52
52
  }
53
53
 
54
54
  .inner {
55
+ margin: 0 auto;
55
56
  width: 100%;
56
- background: var(--color-surfaceFill);
57
- border: 1px solid var(--color-surfaceBorder);
57
+ max-width: 40rem;
58
58
  }
59
59
 
60
60
  h1 {
61
61
  font-size: var(--fs-base);
62
- border-bottom: 1px solid var(--color-textSecondary);
63
- padding-bottom: 0.2em;
64
- background-color: rgba(0, 0, 0, 0.2);
62
+ margin-bottom: 0.2em;
65
63
  }
66
64
  h1 em {
67
65
  background: rgba(134, 139, 84, 0.4);
@@ -74,6 +72,7 @@ table {
74
72
  border-collapse: collapse;
75
73
  border-spacing: 0;
76
74
  width: 100%;
75
+ border: 1px solid var(--color-surfaceBorder);
77
76
  }
78
77
 
79
78
  a {
@@ -83,8 +82,7 @@ a {
83
82
  }
84
83
 
85
84
  th,
86
- td,
87
- h1 {
85
+ td {
88
86
  padding: 0.2em 0.4em;
89
87
  text-align: left;
90
88
  }
@@ -1,12 +1,10 @@
1
- <script lang="ts">let { weight = 'regular', children } = $props();
1
+ <script lang="ts">let { as = 'div', weight = 'regular', children } = $props();
2
2
  export {};
3
3
  </script>
4
4
 
5
- <div class={['container', weight]}>
6
- {#if children}
7
- {@render children()}
8
- {/if}
9
- </div>
5
+ <svelte:element this={as} class={['container', weight]}>
6
+ {@render children?.()}
7
+ </svelte:element>
10
8
 
11
9
  <style>.container {
12
10
  font-family: var(--swr-sans);
@@ -1,6 +1,7 @@
1
1
  import type { Snippet } from 'svelte';
2
2
  interface CopyProps {
3
3
  weight?: 'regular' | 'bold';
4
+ as?: string;
4
5
  children?: Snippet;
5
6
  }
6
7
  declare const Copy: import("svelte").Component<CopyProps, {}, "">;
@@ -47,6 +47,7 @@ const rules = [
47
47
  --color-pageFill: var(--pageFill-light);
48
48
  --color-surfaceFill: var(--surfaceFill-light);
49
49
  --color-surfaceBorder: var(--surfaceBorder-light);
50
+ --color-dropShadow: var(--dropShadow-light);
50
51
  }
51
52
  .container[data-theme=dark] {
52
53
  --color-logoFill: var(--logoFill-dark);
@@ -56,6 +57,7 @@ const rules = [
56
57
  --color-textPrimary: var(--textPrimary-dark);
57
58
  --color-textSecondary: var(--textSecondary-dark);
58
59
  --color-textSecondaryHover: var(--textSecondaryHover-dark);
60
+ --color-dropShadow: var(--dropShadow-dark);
59
61
  }
60
62
  .container {
61
63
  --swr-text: "SWR-VAR-Text", sans-serif;
@@ -169,12 +169,16 @@ const semantics = {
169
169
  light: '#ffffff'
170
170
  },
171
171
  surfaceBorder: {
172
- dark: 'hsl(0, 0%, 35%)',
173
- light: shades.gray.base
172
+ dark: 'rgba(255,255,255,.15)',
173
+ light: shades.gray.light3
174
174
  },
175
175
  pageFill: {
176
176
  dark: '#0C0C0C',
177
177
  light: '#fff'
178
+ },
179
+ dropShadow: {
180
+ dark: 'rgba(0,0,0, 0.25)',
181
+ light: 'rgba(0,0,0, 0.0375)'
178
182
  }
179
183
  };
180
184
  const scales = {
@@ -0,0 +1,423 @@
1
+ <script lang="ts">import SwrLogo from './SwrLogo.svg.svelte';
2
+ import GridInspector from './GridInspector.svelte';
3
+ import Copy from '../Copy/Copy.svelte';
4
+ import DesignTokens from '../DesignTokens/DesignTokens.svelte';
5
+ let { showHeader = true, showNav = true, showArticleHeader = true, showPlayer = true, eyebrow = 'Wärmewende in Ihrer Gemeinde', title = 'Baden-Württemberg heizt noch größtenteils fossil', intro = 'Fast drei Viertel der privaten Heizungen in Baden-Württemberg liefen 2022 noch mit Öl und Gas. In Neubauten werden inzwischen überwiegend Wärmepumpen eingebaut, doch es gibt regionale Unterschiede.', showBreadcrumbs = true, showGrid = false, paragraphsAbove = 0, paragraphsBelow = 0, children } = $props();
6
+ const date = new Date();
7
+ let articleEl = $state();
8
+ </script>
9
+
10
+ <DesignTokens>
11
+ <div class="container">
12
+ {#if showHeader}
13
+ <header>
14
+ <div class="header-inner">
15
+ <i class="logo">
16
+ <SwrLogo />
17
+ </i>
18
+ </div>
19
+ </header>
20
+ {/if}
21
+ {#if showNav}
22
+ <div class="nav">
23
+ <div class="nav-inner grid">
24
+ <i class="circle"></i>
25
+ <ul>
26
+ <li>Nachrichten Übersicht</li>
27
+ <li>Baden-Württemberg</li>
28
+ <li>Rheinland-Pfalz</li>
29
+ </ul>
30
+ </div>
31
+ </div>
32
+ {/if}
33
+ {#if showBreadcrumbs}
34
+ <div class="breadcrumbs"></div>
35
+ {/if}
36
+
37
+ {#if showPlayer}
38
+ <div class="player">
39
+ <i class="circle"></i>
40
+ <div class="player-buttons">
41
+ <i class="button"></i>
42
+ <i class="button"></i>
43
+ </div>
44
+ </div>
45
+ {/if}
46
+ <article bind:this={articleEl} class="grid article">
47
+ {#if showGrid}
48
+ <GridInspector target={articleEl}></GridInspector>
49
+ {/if}
50
+ {#if showArticleHeader}
51
+ <div class="article-header">
52
+ <span class="article-eyebrow">{eyebrow}</span>
53
+ <h1 class="article-title">{title}</h1>
54
+ <p class="article-intro">{intro}</p>
55
+ <div class="article-meta">
56
+ <p class="article-date">
57
+ <span>Stand </span>
58
+ {date.toLocaleDateString('de-DE')}
59
+ </p>
60
+ <div class="article-byline">
61
+ <div class="byline-images">
62
+ <i class="byline-image"></i>
63
+ <i class="byline-image"></i>
64
+ <i class="byline-image"></i>
65
+ </div>
66
+ </div>
67
+ </div>
68
+ <div class="article-actions">
69
+ <i class="action-button"></i>
70
+ <i class="action-button"></i>
71
+ </div>
72
+ </div>
73
+ {/if}
74
+ <div class="article-body">
75
+ {#if paragraphsAbove > 0}
76
+ {#each { length: paragraphsAbove }}
77
+ <Copy as="p">
78
+ Das SWR Data Lab hat Kaufpreise, Fahrzeugdaten und Betriebskosten von über 5.500
79
+ Neuwagenmodellen von 2024 bis April 2025 aus dem ADAC-Autokatalog untersucht. Die
80
+ Analyse zeigt, wie teuer ein Elektroauto, Diesel oder Benziner der unteren
81
+ Mittelklasse beim Kauf und Betrieb über viele Jahre im Mittel ist.
82
+ </Copy>
83
+ {/each}
84
+ {/if}
85
+ <div class="embed">
86
+ {@render children?.()}
87
+ </div>
88
+ {#if paragraphsBelow > 0}
89
+ {#each { length: paragraphsBelow }}
90
+ <Copy as="p">
91
+ Das SWR Data Lab hat Kaufpreise, Fahrzeugdaten und Betriebskosten von über 5.500
92
+ Neuwagenmodellen von 2024 bis April 2025 aus dem ADAC-Autokatalog untersucht. Die
93
+ Analyse zeigt, wie teuer ein Elektroauto, Diesel oder Benziner der unteren
94
+ Mittelklasse beim Kauf und Betrieb über viele Jahre im Mittel ist.
95
+ </Copy>
96
+ {/each}
97
+ {/if}
98
+ </div>
99
+ </article>
100
+ </div>
101
+ </DesignTokens>
102
+
103
+ <style>* {
104
+ box-sizing: border-box;
105
+ }
106
+
107
+ :global(svg) {
108
+ display: block;
109
+ }
110
+
111
+ .container {
112
+ --blue: hsl(221, 75%, 46%);
113
+ --blue-light: hsl(221, 100%, 95%);
114
+ color: var(--blue);
115
+ font-family: "SWR-VAR-Sans", sans-serif;
116
+ }
117
+
118
+ header {
119
+ display: flex;
120
+ align-items: center;
121
+ background: var(--blue-light);
122
+ border-bottom: 1px solid var(--blue);
123
+ height: 48px;
124
+ padding: 0 16px;
125
+ }
126
+ @media (min-width: 640px) {
127
+ header {
128
+ padding: 0 40px;
129
+ height: 64px;
130
+ }
131
+ }
132
+
133
+ .header-inner {
134
+ width: 100%;
135
+ max-width: 1312px;
136
+ margin: 0 auto;
137
+ }
138
+
139
+ .logo {
140
+ display: block;
141
+ height: 24px;
142
+ }
143
+ @media (min-width: 1440px) {
144
+ .logo {
145
+ height: 28px;
146
+ }
147
+ }
148
+ .logo :global(svg) {
149
+ height: 100%;
150
+ }
151
+
152
+ .nav {
153
+ border-bottom: 1px solid var(--blue);
154
+ }
155
+ .nav .nav-inner {
156
+ width: 100%;
157
+ }
158
+ .nav ul {
159
+ display: flex;
160
+ align-items: center;
161
+ grid-column: 2/-1;
162
+ list-style: none;
163
+ gap: 2.1em;
164
+ white-space: nowrap;
165
+ overflow: hidden;
166
+ }
167
+ @media (min-width: 1440px) {
168
+ .nav ul {
169
+ margin-left: -32px;
170
+ }
171
+ }
172
+
173
+ .nav,
174
+ .breadcrumbs {
175
+ height: 48px;
176
+ display: flex;
177
+ align-items: center;
178
+ padding: 0 16px;
179
+ }
180
+ @media (min-width: 640px) {
181
+ .nav,
182
+ .breadcrumbs {
183
+ padding: 0 40px;
184
+ }
185
+ }
186
+
187
+ .circle {
188
+ display: block;
189
+ border-radius: 1000px;
190
+ width: 32px;
191
+ height: 32px;
192
+ border: 1px solid var(--blue);
193
+ }
194
+
195
+ .button {
196
+ display: block;
197
+ border: 1px solid var(--blue);
198
+ border-radius: 4px;
199
+ width: 40px;
200
+ height: 40px;
201
+ }
202
+
203
+ .player {
204
+ width: 638px;
205
+ height: 58px;
206
+ bottom: 16px;
207
+ left: 50%;
208
+ border-radius: 4px;
209
+ padding: 8px;
210
+ display: flex;
211
+ align-items: center;
212
+ justify-content: space-between;
213
+ transform: translateX(-50%);
214
+ background: var(--blue-light);
215
+ border: 1px solid var(--blue);
216
+ z-index: 100;
217
+ position: fixed;
218
+ }
219
+
220
+ .player-buttons {
221
+ column-gap: 8px;
222
+ display: flex;
223
+ }
224
+
225
+ .grid {
226
+ display: grid;
227
+ grid-template-columns: repeat(12, 1fr);
228
+ column-gap: 16px;
229
+ max-width: 1312px;
230
+ width: auto;
231
+ position: relative;
232
+ }
233
+ @media (min-width: 1440px) {
234
+ .grid {
235
+ column-gap: 32px;
236
+ margin: 0 auto;
237
+ }
238
+ }
239
+
240
+ .article {
241
+ margin: 0 16px;
242
+ }
243
+ @media (min-width: 640px) {
244
+ .article {
245
+ margin: 0 40px;
246
+ }
247
+ }
248
+ @media (min-width: 1024px) {
249
+ .article {
250
+ margin: 0 48px;
251
+ }
252
+ }
253
+ @media (min-width: 1440px) {
254
+ .article {
255
+ margin: 0 auto;
256
+ }
257
+ }
258
+
259
+ .article-body {
260
+ display: contents;
261
+ }
262
+ .article-body :global(p) {
263
+ margin-bottom: 1.5em;
264
+ grid-column: 1/13;
265
+ }
266
+ @media (min-width: 640px) {
267
+ .article-body :global(p) {
268
+ grid-column: 2/12;
269
+ }
270
+ }
271
+ @media (min-width: 1024px) {
272
+ .article-body :global(p) {
273
+ grid-column: 3/11;
274
+ }
275
+ }
276
+ @media (min-width: 1440px) {
277
+ .article-body :global(p) {
278
+ grid-column: 4/10;
279
+ }
280
+ }
281
+
282
+ .article-header {
283
+ margin-bottom: 24px;
284
+ grid-column: 1/13;
285
+ }
286
+ @media (min-width: 640px) {
287
+ .article-header {
288
+ grid-column: 2/12;
289
+ }
290
+ }
291
+ @media (min-width: 1024px) {
292
+ .article-header {
293
+ grid-column: 3/11;
294
+ }
295
+ }
296
+ @media (min-width: 1440px) {
297
+ .article-header {
298
+ grid-column: 4/10;
299
+ }
300
+ }
301
+
302
+ .article-eyebrow {
303
+ font-size: 0.875rem;
304
+ font-weight: 500;
305
+ }
306
+ @media (min-width: 1024px) {
307
+ .article-eyebrow {
308
+ font-size: 1.25rem;
309
+ }
310
+ }
311
+
312
+ .article-title {
313
+ font-size: 2rem;
314
+ line-height: 1.3;
315
+ }
316
+ @media (min-width: 1024px) {
317
+ .article-title {
318
+ line-height: 1.25;
319
+ font-size: 3rem;
320
+ }
321
+ }
322
+
323
+ .article-intro {
324
+ margin-top: 0.5em;
325
+ hyphens: auto;
326
+ font-size: 1.25rem;
327
+ line-height: 1.25;
328
+ }
329
+ @media (min-width: 1024px) {
330
+ .article-intro {
331
+ font-size: 1.5rem;
332
+ }
333
+ }
334
+
335
+ .article-meta {
336
+ display: flex;
337
+ font-size: 0.875rem;
338
+ border-bottom: 1px solid var(--blue);
339
+ flex-flow: column;
340
+ gap: 8px;
341
+ margin-top: 1rem;
342
+ padding-bottom: 1rem;
343
+ }
344
+ @media (min-width: 768px) {
345
+ .article-meta {
346
+ gap: 0;
347
+ height: 72px;
348
+ margin-top: 0;
349
+ padding-bottom: 0;
350
+ align-items: center;
351
+ flex-flow: row;
352
+ }
353
+ }
354
+
355
+ .article-date {
356
+ flex-basis: 35%;
357
+ display: flex;
358
+ flex-flow: column;
359
+ justify-content: center;
360
+ }
361
+ .article-date span {
362
+ display: block;
363
+ }
364
+
365
+ .article-byline {
366
+ display: flex;
367
+ align-items: center;
368
+ gap: 10px;
369
+ }
370
+
371
+ .byline-images {
372
+ display: flex;
373
+ flex-flow: row-reverse;
374
+ }
375
+
376
+ .byline-image {
377
+ display: block;
378
+ border: 1px solid var(--blue);
379
+ border-radius: 100px;
380
+ width: 47px;
381
+ background: white;
382
+ height: 47px;
383
+ margin-right: -10px;
384
+ }
385
+ .byline-image:first-child {
386
+ margin-right: 0;
387
+ }
388
+
389
+ .article-actions {
390
+ border-bottom: 1px solid var(--blue);
391
+ height: 64px;
392
+ display: flex;
393
+ align-items: center;
394
+ gap: 8px;
395
+ }
396
+
397
+ .action-button {
398
+ display: block;
399
+ border: 1px solid var(--blue);
400
+ border-radius: 4px;
401
+ width: 60px;
402
+ height: 32px;
403
+ }
404
+
405
+ .embed {
406
+ width: 100%;
407
+ grid-column: 1/13;
408
+ }
409
+ @media (min-width: 640px) {
410
+ .embed {
411
+ grid-column: 2/12;
412
+ }
413
+ }
414
+ @media (min-width: 1024px) {
415
+ .embed {
416
+ grid-column: 3/11;
417
+ }
418
+ }
419
+ @media (min-width: 1440px) {
420
+ .embed {
421
+ grid-column: 4/10;
422
+ }
423
+ }</style>
@@ -0,0 +1,18 @@
1
+ import type { Snippet } from 'svelte';
2
+ interface DevContainerProps {
3
+ showHeader?: boolean;
4
+ showNav?: boolean;
5
+ showPlayer?: boolean;
6
+ showGrid?: boolean;
7
+ showArticleHeader?: boolean;
8
+ showBreadcrumbs?: boolean;
9
+ paragraphsAbove?: number;
10
+ paragraphsBelow?: number;
11
+ title?: string;
12
+ eyebrow?: string;
13
+ intro?: string;
14
+ children?: Snippet;
15
+ }
16
+ declare const DevContainer: import("svelte").Component<DevContainerProps, {}, "">;
17
+ type DevContainer = ReturnType<typeof DevContainer>;
18
+ export default DevContainer;
@@ -0,0 +1,43 @@
1
+ <script lang="ts">"use strict";
2
+ const { target } = $props();
3
+ let w = $state(0);
4
+ let cols = $derived.by(() => {
5
+ w;
6
+ if (!target)
7
+ return [];
8
+ return window.getComputedStyle(target).gridTemplateColumns.split(' ');
9
+ });
10
+ </script>
11
+
12
+ <div class="container">
13
+ {#each cols as c}
14
+ <i class="col" style:width={c}></i>
15
+ {/each}
16
+ </div>
17
+
18
+ <svelte:window bind:innerWidth={w} />
19
+
20
+ <style>
21
+ .container {
22
+ display: flex;
23
+ justify-content: space-between;
24
+ position: absolute;
25
+ top: 0;
26
+ left: 0;
27
+ bottom: 0;
28
+ right: 0;
29
+ opacity: 0.1;
30
+ pointer-events: none;
31
+ z-index: 0;
32
+ }
33
+ .col {
34
+ background: rgb(104, 120, 179);
35
+ flex-grow: 0;
36
+ &:first-child {
37
+ border-left: 0;
38
+ }
39
+ &:last-child {
40
+ border-right: 0;
41
+ }
42
+ }
43
+ </style>
@@ -0,0 +1,6 @@
1
+ interface GridInspectorProps {
2
+ target: HTMLElement | undefined;
3
+ }
4
+ declare const GridInspector: import("svelte").Component<GridInspectorProps, {}, "">;
5
+ type GridInspector = ReturnType<typeof GridInspector>;
6
+ export default GridInspector;
@@ -0,0 +1,8 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 480.8 141.7">
2
+ <path
3
+ fill="currentColor"
4
+ d="M347.5 0v46.1l24.7 24.7-24.7 24.8v46.1l70.2-70.9L347.5 0zm-61.1 46.4c0-10-5.9-16-19.7-16-3 0-6.5.2-8.2.4v32.6c1.5.2 4.6.4 7.4.4 12.5 0 20.5-6.6 20.5-17.4zm39.4 88.1H290l-30.4-49.8h-1.1v49.8H229V7.1c10.8-.8 24.6-.9 39.9-.9C299 6.2 316.6 17 316.6 44c0 17.2-10.6 31.1-27.6 35.3 3.4 4.9 6.6 9.6 9.8 14.3l27 40.9zm-295.6 2c-8.9 0-18.1-.9-26.3-2.8l1.3-27.9c7.2 2.6 18 5.4 27.2 5.4 10.8 0 18.6-4.5 18.6-13.6C51 75.9.9 86.6 0 44.3c-.5-24 18.9-39.8 50.9-39.8 6.8 0 15.3.8 23.2 2.3l-.1 26c-7.2-2.1-16.7-4-24.3-4-12.3 0-18.2 5.3-18.2 12.5 0 19.8 51 12.3 51 52.1.1 24.7-19.8 43.1-52.3 43.1zM192.1 7.1 179.3 86 166.4 7.1h-29.7L123.9 86 111 7.1H81.3l22.6 127.5h33.2l14.5-81.8 14.4 81.8h33.3L221.8 7.1h-29.7z"
5
+ ></path>
6
+ <path fill="currentColor" d="M347.5 0v46.1l24.7 24.7-24.7 24.8v46.1l70.2-70.9L347.5 0z"></path>
7
+ <path fill="currentColor" d="M410.6 0v46.1l24.7 24.7-24.7 24.8v46.1l70.2-70.9L410.6 0z"></path>
8
+ </svg>
@@ -0,0 +1,26 @@
1
+ export default SwrLogo;
2
+ type SwrLogo = SvelteComponent<{
3
+ [x: string]: never;
4
+ }, {
5
+ [evt: string]: CustomEvent<any>;
6
+ }, {}> & {
7
+ $$bindings?: string | undefined;
8
+ };
9
+ declare const SwrLogo: $$__sveltets_2_IsomorphicComponent<{
10
+ [x: string]: never;
11
+ }, {
12
+ [evt: string]: CustomEvent<any>;
13
+ }, {}, {}, string>;
14
+ interface $$__sveltets_2_IsomorphicComponent<Props extends Record<string, any> = any, Events extends Record<string, any> = any, Slots extends Record<string, any> = any, Exports = {}, Bindings = string> {
15
+ new (options: import("svelte").ComponentConstructorOptions<Props>): import("svelte").SvelteComponent<Props, Events, Slots> & {
16
+ $$bindings?: Bindings;
17
+ } & Exports;
18
+ (internal: unknown, props: {
19
+ $$events?: Events;
20
+ $$slots?: Slots;
21
+ }): Exports & {
22
+ $set?: any;
23
+ $on?: any;
24
+ };
25
+ z_$$bindings?: Bindings;
26
+ }
@@ -0,0 +1,2 @@
1
+ import DevContainer from './DevContainer.svelte';
2
+ export default DevContainer;
@@ -0,0 +1,2 @@
1
+ import DevContainer from './DevContainer.svelte';
2
+ export default DevContainer;
@@ -3,9 +3,7 @@ export {};
3
3
  </script>
4
4
 
5
5
  <h2 class="container">
6
- {#if children}
7
- {@render children()}
8
- {/if}
6
+ {@render children?.()}
9
7
  </h2>
10
8
 
11
9
  <style>
@@ -0,0 +1,36 @@
1
+ <script lang="ts">import {} from 'svelte';
2
+ let { height = '100vh', children } = $props();
3
+ </script>
4
+
5
+ <section class="container" style:height>
6
+ <div class="inner">
7
+ {@render children?.()}
8
+ </div>
9
+ </section>
10
+
11
+ <style>.container {
12
+ display: flex;
13
+ align-items: center;
14
+ }
15
+
16
+ .inner {
17
+ margin: 0 auto;
18
+ padding: 1em 1.5em;
19
+ color: var(--color-textPrimary);
20
+ max-width: 40em;
21
+ font-family: var(--swr-sans);
22
+ font-weight: 400;
23
+ line-height: 1.5;
24
+ letter-spacing: 0.01em;
25
+ font-size: var(--fs-small-1);
26
+ border-radius: 8px;
27
+ background: var(--color-surfaceFill);
28
+ box-shadow: 0 0 8px 1px var(--color-dropShadow);
29
+ border: 1px solid var(--color-surfaceBorder);
30
+ }
31
+ @media (min-width: 500px) {
32
+ .inner {
33
+ padding: 1.25em;
34
+ margin: 1em auto;
35
+ }
36
+ }</style>
@@ -0,0 +1,8 @@
1
+ import { type Snippet } from 'svelte';
2
+ interface SlideContentProps {
3
+ height?: string;
4
+ children: Snippet;
5
+ }
6
+ declare const ScrollerSection: import("svelte").Component<SlideContentProps, {}, "">;
7
+ type ScrollerSection = ReturnType<typeof ScrollerSection>;
8
+ export default ScrollerSection;
@@ -0,0 +1,2 @@
1
+ import ScrollerSection from './ScrollerSection.svelte';
2
+ export default ScrollerSection;
@@ -0,0 +1,2 @@
1
+ import ScrollerSection from './ScrollerSection.svelte';
2
+ export default ScrollerSection;
package/dist/index.d.ts CHANGED
@@ -1,13 +1,14 @@
1
1
  export { default as DesignTokens } from "./DesignTokens/DesignTokens.svelte";
2
2
  export { tokens } from "./DesignTokens/index.js";
3
- export { default as isDarkMode } from "./isDarkMode/isDarkMode.svelte";
4
3
  export { default as Headline } from "./Headline/Headline.svelte";
5
4
  export { default as Copy } from "./Copy/Copy.svelte";
6
5
  export { default as Caption } from "./Caption/Caption.svelte";
7
6
  export { default as Note } from "./Note/Note.svelte";
8
- export { default as Card } from "./Card/Card.svelte";
7
+ export { default as ScrollerSection } from "./ScrollerSection/ScrollerSection.svelte";
9
8
  export { default as Scroller } from "./Scroller/Scroller.svelte";
10
9
  export { default as SwrHeader } from "./SwrHeader/SwrHeader.svelte";
10
+ export { default as Breakout } from "./Breakout/Breakout.svelte";
11
+ export { default as Card } from "./Card/Card.svelte";
11
12
  export { default as ChartHeader } from "./ChartHeader/ChartHeader.svelte";
12
13
  export { default as ChartFooter } from "./ChartFooter/ChartFooter.svelte";
13
14
  export { default as Logotype } from "./Logotype/Logotype.svelte";
@@ -32,4 +33,6 @@ export { default as Button } from "./Button/Button.svelte";
32
33
  export { default as Select } from "./Select/Select.svelte";
33
34
  export { default as Autocomplete } from "./Autocomplete/Autocomplete.svelte";
34
35
  export { default as ChartList } from "./ChartList/ChartList.svelte";
36
+ export { default as DevContainer } from "./DevContainer/DevContainer.svelte";
37
+ export { default as isDarkMode } from "./isDarkMode/isDarkMode.svelte";
35
38
  export { SWRDataLabLight, SWRDataLabDark } from "./maplibre/MapStyle";
package/dist/index.js CHANGED
@@ -1,7 +1,6 @@
1
1
  // Design Tokens
2
2
  export { default as DesignTokens } from './DesignTokens/DesignTokens.svelte';
3
3
  export { tokens as tokens } from './DesignTokens/index.js';
4
- export { default as isDarkMode } from './isDarkMode/isDarkMode.svelte';
5
4
 
6
5
  // Typography
7
6
  export { default as Headline } from './Headline/Headline.svelte';
@@ -9,10 +8,14 @@ export { default as Copy } from './Copy/Copy.svelte';
9
8
  export { default as Caption } from './Caption/Caption.svelte';
10
9
  export { default as Note } from './Note/Note.svelte';
11
10
 
12
- // Display
13
- export { default as Card } from './Card/Card.svelte';
11
+ // Layout
12
+ export { default as ScrollerSection } from './ScrollerSection/ScrollerSection.svelte';
14
13
  export { default as Scroller } from './Scroller/Scroller.svelte';
15
14
  export { default as SwrHeader } from './SwrHeader/SwrHeader.svelte';
15
+ export { default as Breakout } from './Breakout/Breakout.svelte';
16
+
17
+ // Display
18
+ export { default as Card } from './Card/Card.svelte';
16
19
 
17
20
  // Chart
18
21
  export { default as ChartHeader } from './ChartHeader/ChartHeader.svelte';
@@ -48,3 +51,5 @@ export { default as Autocomplete } from './Autocomplete/Autocomplete.svelte';
48
51
 
49
52
  // Meta
50
53
  export { default as ChartList } from './ChartList/ChartList.svelte';
54
+ export { default as DevContainer } from './DevContainer/DevContainer.svelte';
55
+ export { default as isDarkMode } from './isDarkMode/isDarkMode.svelte';
@@ -1,5 +1,5 @@
1
- import type { StyleSpecification } from 'maplibre-gl';
2
1
  import type { StyleOptions } from './types';
2
+ import type { StyleSpecification } from 'maplibre-gl';
3
3
  interface styleFunction {
4
4
  (options?: StyleOptions): StyleSpecification;
5
5
  }
@@ -1,3 +1,4 @@
1
+ import defaultOptions from './defaultOptions';
1
2
  import makeAdmin from './components/Admin';
2
3
  import makeBuildings from './components/Buildings';
3
4
  import makeLanduse from './components/Landuse';
@@ -46,10 +47,7 @@ const { roadLabels, roadBridges, roadSurface, roadTunnels } = makeRoads(tokens);
46
47
  const { buildingFootprints, buildingExtrusions, structureExtrusions } = makeBuildings(tokens);
47
48
  const style = (opts) => {
48
49
  const options = {
49
- enableBuildingExtrusions: false,
50
- roads: {
51
- showLabels: true
52
- },
50
+ ...defaultOptions,
53
51
  ...opts
54
52
  };
55
53
  return {
@@ -113,7 +111,8 @@ const style = (opts) => {
113
111
  // 8. Building extrusions
114
112
  ...(options.enableBuildingExtrusions ? [buildingExtrusions] : []),
115
113
  // 8. Point labels
116
- ...placeLabels,
114
+ ...(options.places?.showLabels ? placeLabels : []),
115
+ // 9. Admin boundary labels
117
116
  ...boundaryLabels
118
117
  ]
119
118
  };
@@ -1,5 +1,5 @@
1
- import type { StyleSpecification } from 'maplibre-gl';
2
1
  import type { StyleOptions } from './types';
2
+ import type { StyleSpecification } from 'maplibre-gl';
3
3
  interface styleFunction {
4
4
  (options?: StyleOptions): StyleSpecification;
5
5
  }
@@ -5,6 +5,7 @@ import makeTransit from './components/Transit';
5
5
  import makePlaceLabels from './components/PlaceLabels';
6
6
  import makeWalking from './components/Walking';
7
7
  import makeRoads from './components/Roads';
8
+ import defaultOptions from './defaultOptions';
8
9
  const tokens = {
9
10
  sans_regular: ['SWR Sans Regular'],
10
11
  sans_medium: ['SWR Sans Medium'],
@@ -46,7 +47,7 @@ const { roadLabels, roadBridges, roadSurface, roadTunnels } = makeRoads(tokens);
46
47
  const { buildingFootprints, buildingExtrusions, structureExtrusions } = makeBuildings(tokens);
47
48
  const style = (opts) => {
48
49
  const options = {
49
- enableBuildingExtrusions: false,
50
+ ...defaultOptions,
50
51
  ...opts
51
52
  };
52
53
  return {
@@ -110,7 +111,8 @@ const style = (opts) => {
110
111
  // 8. Building extrusions
111
112
  ...(options.enableBuildingExtrusions ? [buildingExtrusions] : []),
112
113
  // 8. Point labels
113
- ...placeLabels,
114
+ ...(options.places?.showLabels ? placeLabels : []),
115
+ // 9. Admin boundary labels
114
116
  ...boundaryLabels
115
117
  ]
116
118
  };
@@ -0,0 +1,3 @@
1
+ import type { StyleOptions } from './types';
2
+ declare const opts: StyleOptions;
3
+ export default opts;
@@ -0,0 +1,10 @@
1
+ const opts = {
2
+ enableBuildingExtrusions: false,
3
+ places: {
4
+ showLabels: true
5
+ },
6
+ roads: {
7
+ showLabels: true
8
+ }
9
+ };
10
+ export default opts;
@@ -1,5 +1,8 @@
1
1
  interface StyleOptions {
2
2
  enableBuildingExtrusions?: boolean;
3
+ places?: {
4
+ showLabels?: boolean;
5
+ };
3
6
  roads?: {
4
7
  showLabels?: boolean;
5
8
  };
@@ -1,4 +1,4 @@
1
- <script lang="ts">import { onDestroy } from 'svelte';
1
+ <script lang="ts">import { onDestroy, tick } from 'svelte';
2
2
  import maplibre, {} from 'maplibre-gl';
3
3
  import { getMapContext } from '../context.svelte.js';
4
4
  import { resetPopupEventListener } from '../utils';
@@ -14,6 +14,10 @@ let el = $state();
14
14
  $effect(() => {
15
15
  if (position && el && map) {
16
16
  tooltip.setLngLat(position).setDOMContent(el).addTo(map);
17
+ // Ensure tooltip doesn't extend beyond the map canvas, see #223
18
+ tick().then(() => {
19
+ tooltip._update();
20
+ });
17
21
  }
18
22
  else {
19
23
  tooltip.remove();
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@swr-data-lab/components",
3
3
  "description": "SWR Data Lab component library",
4
- "version": "2.26.1",
4
+ "version": "2.29.0",
5
5
  "author": "SWR Data Lab",
6
6
  "license": "UNLICENSED",
7
7
  "type": "module",
@@ -59,7 +59,7 @@
59
59
  "concurrently": "^9.2.1",
60
60
  "http-server": "^14.1.1",
61
61
  "mdx-mermaid": "^2.0.3",
62
- "playwright": "^1.55.0",
62
+ "playwright": "^1.55.1",
63
63
  "publint": "^0.3.12",
64
64
  "sass": "^1.91.0",
65
65
  "sass-embedded": "^1.93.2",
@@ -69,7 +69,7 @@
69
69
  "svelte-check": "^4.3.2",
70
70
  "svelte-preprocess": "^6.0.3",
71
71
  "typescript": "^5.9.2",
72
- "vite": "^7.1.7",
72
+ "vite": "^7.1.11",
73
73
  "vitest": "^3.1.1",
74
74
  "wait-on": "^8.0.1"
75
75
  },