@sbb-esta/lyne-elements 5.1.0 → 5.3.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 (91) hide show
  1. package/_index.scss +1 -0
  2. package/action-group.pure.js +1 -1
  3. package/alert.pure.js +14 -14
  4. package/breadcrumb.pure.js +3 -3
  5. package/calendar.pure.js +68 -68
  6. package/carousel/_carousel.global.scss +6 -0
  7. package/carousel.pure.js +1 -1
  8. package/chip.pure.js +1 -1
  9. package/clock.pure.js +1 -1
  10. package/core/styles/_theme.scss +6 -0
  11. package/core.js +17 -17
  12. package/custom-elements.json +1626 -221
  13. package/date-input.pure.js +1 -1
  14. package/development/action-group.pure.js +1 -1
  15. package/development/alert.pure.js +14 -14
  16. package/development/breadcrumb.pure.js +3 -3
  17. package/development/calendar.pure.js +67 -67
  18. package/development/carousel.pure.js +1 -1
  19. package/development/chip/chip-group/chip-group.component.d.ts +2 -1
  20. package/development/chip.pure.js +3 -0
  21. package/development/clock.pure.js +15 -17
  22. package/development/core/i18n/i18n.d.ts +2 -0
  23. package/development/core.js +15 -3
  24. package/development/date-input.pure.js +15 -7
  25. package/development/download/download/download.component.d.ts +51 -0
  26. package/development/download/download-info/download-info.component.d.ts +59 -0
  27. package/development/download.d.ts +1 -0
  28. package/development/download.js +10 -0
  29. package/development/download.pure.d.ts +3 -0
  30. package/development/download.pure.js +436 -0
  31. package/development/expansion-panel.pure.js +6 -6
  32. package/development/file-selector.pure.js +7 -3
  33. package/development/flip-card.pure.js +5 -4
  34. package/development/image.pure.js +8 -8
  35. package/development/map-container.pure.js +8 -8
  36. package/development/mini-calendar.pure.js +1 -1
  37. package/development/notification.pure.js +12 -9
  38. package/development/option.pure.js +11 -11
  39. package/development/overlay.pure.js +1 -1
  40. package/development/paginator.pure.js +18 -18
  41. package/development/popover.pure.js +1 -1
  42. package/development/signet.pure.js +17 -17
  43. package/development/stepper/step/step.component.d.ts +0 -2
  44. package/development/stepper/stepper/stepper.component.d.ts +2 -2
  45. package/development/stepper.pure.js +24 -17
  46. package/development/tabs.pure.js +4 -4
  47. package/development/teaser.pure.js +1 -1
  48. package/development/time-input.pure.js +10 -6
  49. package/development/timetable-form.pure.js +3 -3
  50. package/development/timetable-occupancy.pure.js +22 -22
  51. package/development/toast.pure.js +6 -6
  52. package/development/tooltip.pure.js +4 -2
  53. package/development/train.pure.js +29 -29
  54. package/development/visual-checkbox.pure.js +13 -13
  55. package/download/_download.global.scss +12 -0
  56. package/download.js +1 -0
  57. package/download.pure.js +21 -0
  58. package/expansion-panel.pure.js +6 -6
  59. package/file-selector.pure.js +2 -2
  60. package/flip-card.pure.js +1 -1
  61. package/image.pure.js +8 -8
  62. package/index.d.ts +3 -0
  63. package/index.js +3 -0
  64. package/lean-off-brand-theme.css +45 -5
  65. package/lean-safety-theme.css +45 -5
  66. package/lean-theme.css +45 -5
  67. package/map-container.pure.js +8 -8
  68. package/mini-calendar.pure.js +1 -1
  69. package/notification.pure.js +12 -9
  70. package/off-brand-theme.css +45 -5
  71. package/option.pure.js +11 -11
  72. package/overlay/_overlay.global.scss +0 -4
  73. package/overlay.pure.js +1 -1
  74. package/package.json +11 -1
  75. package/paginator.pure.js +18 -18
  76. package/popover.pure.js +2 -2
  77. package/safety-theme.css +45 -5
  78. package/signet.pure.js +17 -17
  79. package/standard-theme.css +45 -5
  80. package/stepper.pure.js +3 -3
  81. package/table/_table.global.scss +46 -1
  82. package/tabs.pure.js +4 -4
  83. package/teaser/_teaser.global.scss +4 -0
  84. package/teaser.pure.js +1 -1
  85. package/time-input.pure.js +1 -1
  86. package/timetable-form.pure.js +3 -3
  87. package/timetable-occupancy.pure.js +22 -22
  88. package/toast.pure.js +6 -6
  89. package/tooltip.pure.js +3 -3
  90. package/train.pure.js +29 -29
  91. package/visual-checkbox.pure.js +13 -13
@@ -0,0 +1,436 @@
1
+ import { __esDecorate, __runInitializers } from "tslib";
2
+ import { html, nothing, unsafeCSS } from "lit";
3
+ import { property } from "lit/decorators.js";
4
+ import { SbbSecondaryButtonStaticElement } from "./button.pure.js";
5
+ import { SbbElement, SbbLanguageController, SbbLinkBaseElement, SbbPropertyWatcherController, defaultDateAdapter, forceType, i18nDownload, i18nNonAccessible, omitEmptyConverter, readConfig, screenReaderOnlyStyles } from "./core.js";
6
+ import { SbbIconNameMixin } from "./icon.pure.js";
7
+
8
+ //#region src/elements/download/download/download.scss?inline
9
+ var download_default = ":host {\n --sbb-card-background-color: var(--sbb-background-color-1);\n --sbb-card-border-color: transparent;\n --sbb-card-border-radius: var(--sbb-border-radius-4x);\n --sbb-card-animation-easing: var(--sbb-animation-easing);\n --sbb-card-border-style: solid;\n --sbb-card-padding-inline-default: var(--sbb-spacing-responsive-s);\n --sbb-card-padding-block-default: var(--sbb-spacing-responsive-xxxs);\n --sbb-card-with-badge-padding-block-default: var(--sbb-spacing-fixed-6x) var(--sbb-spacing-responsive-xxxs);\n --sbb-card-padding-block: var(--sbb-card-padding-block-default);\n --sbb-card-with-badge-padding-block: var(--sbb-card-with-badge-padding-block-default);\n --sbb-card-padding-inline: var(--sbb-card-padding-inline-default);\n display: block;\n}\n\n:host(:where([color=white])) {\n --sbb-card-background-color: var(--sbb-background-color-1);\n --sbb-card-border-color: transparent;\n}\n\n:host(:where([color=milk])) {\n --sbb-card-background-color: var(--sbb-background-color-3);\n --sbb-card-border-color: transparent;\n}\n\n.sbb-download {\n --sbb-focus-outline-color: var(--sbb-focus-outline-color-default);\n --sbb-focus-outline-color: light-dark(\n var(--sbb-focus-outline-color-default),\n var(--sbb-focus-outline-color-dark)\n );\n --sbb-card-animation-duration: var(\n --sbb-disable-animation-duration,\n var(--sbb-animation-duration-1x)\n );\n display: block;\n position: relative;\n padding-inline: var(--sbb-card-padding-inline);\n padding-block: var(--sbb-card-padding-block);\n border-radius: var(--sbb-card-border-radius);\n background-color: var(--sbb-card-background-color);\n box-shadow: none;\n transition: box-shadow var(--sbb-card-animation-duration) var(--sbb-card-animation-easing);\n color: var(--sbb-card-color);\n}\n.sbb-download::after {\n content: \"\";\n position: absolute;\n inset: 0;\n background-color: transparent;\n border: var(--sbb-card-border-width) var(--sbb-card-border-style) var(--sbb-card-border-color);\n border-radius: var(--sbb-card-border-radius);\n pointer-events: none;\n}\n@media (forced-colors: active) {\n .sbb-download {\n --sbb-title-color: var(--sbb-card-color);\n }\n}\n.sbb-download {\n display: flex;\n align-items: center;\n gap: var(--sbb-download-gap);\n text-decoration: none;\n translate: 0 var(--sbb-card-hover-shift, 0);\n transition: box-shadow var(--sbb-card-animation-duration) var(--sbb-card-animation-easing), translate var(--sbb-card-animation-duration) var(--sbb-card-animation-easing);\n}\n\n.sbb-download:focus-visible {\n outline-offset: var(--sbb-focus-outline-offset);\n outline: var(--sbb-focus-outline-color) var(--sbb-focus-outline-style, solid) var(--sbb-focus-outline-width);\n}\n\n@media (any-hover: hover) {\n :host(:hover) .sbb-download {\n --sbb-card-hover-shift: -0.125rem;\n box-shadow: var(--sbb-box-shadow-level-9-hard);\n }\n}\n@media (any-hover: hover) and (forced-colors: active) {\n :host(:hover) .sbb-download {\n --sbb-card-border-color: Highlight;\n }\n}\n\n.sbb-download__icon {\n flex: 0 0 auto;\n}\n\n.sbb-download__content {\n display: flex;\n flex-direction: column;\n flex: 1 1 auto;\n min-width: 0;\n}\n\n.sbb-download__label {\n overflow-wrap: break-word;\n font-weight: bold;\n color: var(--sbb-download-label-color);\n}\n\n.sbb-download__custom-content,\n.sbb-download__info {\n line-height: var(--sbb-typo-line-height-text);\n letter-spacing: var(--sbb-typo-letter-spacing-text);\n font-size: var(--sbb-text-font-size-xxs);\n color: var(--sbb-download-info-color);\n}\n\n.sbb-download__button {\n flex: 0 0 auto;\n margin-inline-start: auto;\n}\n";
10
+
11
+ //#endregion
12
+ //#region src/elements/download/download/download.component.ts
13
+ const fileExtensionIcons = /* @__PURE__ */ new Map([
14
+ ["pdf", "document-pdf-small"],
15
+ ["xls", "document-xls-small"],
16
+ ["xlsx", "document-xls-small"],
17
+ ["ppt", "document-ppt-small"],
18
+ ["pptx", "document-ppt-small"],
19
+ ["doc", "document-doc-small"],
20
+ ["docx", "document-doc-small"],
21
+ ["zip", "document-zip-small"],
22
+ ["jpg", "document-image-small"],
23
+ ["jpeg", "document-image-small"],
24
+ ["png", "document-image-small"],
25
+ ["gif", "document-image-small"],
26
+ ["svg", "document-image-small"],
27
+ ["webp", "document-image-small"]
28
+ ]);
29
+ /**
30
+ * It displays a downloadable document, styled as a card.
31
+ *
32
+ * Inherits link properties from `SbbLinkBaseElement`: `href`, `target`, `rel`
33
+ * and `accessibilityLabel`. The download behavior is always enabled.
34
+ *
35
+ * @slot - Use the unnamed slot to add custom content. Optional.
36
+ * @slot info - Slot used to render a `sbb-download-info`. A `sbb-download-info`
37
+ * placed in the unnamed slot is automatically moved to this slot. Optional.
38
+ * @slot icon - Use this slot to display a custom icon, by providing a
39
+ * `sbb-icon` component. Optional.
40
+ */
41
+ let SbbDownloadElement = (() => {
42
+ let _classSuper = SbbIconNameMixin(SbbLinkBaseElement);
43
+ let _instanceExtraInitializers = [];
44
+ let _color_decorators;
45
+ let _color_initializers = [];
46
+ let _color_extraInitializers = [];
47
+ let _label_decorators;
48
+ let _label_initializers = [];
49
+ let _label_extraInitializers = [];
50
+ let _set_download_decorators;
51
+ return class SbbDownloadElement extends _classSuper {
52
+ constructor() {
53
+ super(...arguments);
54
+ this.#color_accessor_storage = (__runInitializers(this, _instanceExtraInitializers), __runInitializers(this, _color_initializers, "white"));
55
+ this.#label_accessor_storage = (__runInitializers(this, _color_extraInitializers), __runInitializers(this, _label_initializers, ""));
56
+ this._languageController = (__runInitializers(this, _label_extraInitializers), new SbbLanguageController(this));
57
+ }
58
+ static {
59
+ const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(_classSuper[Symbol.metadata] ?? null) : void 0;
60
+ _color_decorators = [property({ reflect: true })];
61
+ _label_decorators = [forceType(), property({ converter: omitEmptyConverter })];
62
+ _set_download_decorators = [property({
63
+ type: Boolean,
64
+ reflect: false
65
+ })];
66
+ __esDecorate(this, null, _color_decorators, {
67
+ kind: "accessor",
68
+ name: "color",
69
+ static: false,
70
+ private: false,
71
+ access: {
72
+ has: (obj) => "color" in obj,
73
+ get: (obj) => obj.color,
74
+ set: (obj, value) => {
75
+ obj.color = value;
76
+ }
77
+ },
78
+ metadata: _metadata
79
+ }, _color_initializers, _color_extraInitializers);
80
+ __esDecorate(this, null, _label_decorators, {
81
+ kind: "accessor",
82
+ name: "label",
83
+ static: false,
84
+ private: false,
85
+ access: {
86
+ has: (obj) => "label" in obj,
87
+ get: (obj) => obj.label,
88
+ set: (obj, value) => {
89
+ obj.label = value;
90
+ }
91
+ },
92
+ metadata: _metadata
93
+ }, _label_initializers, _label_extraInitializers);
94
+ __esDecorate(this, null, _set_download_decorators, {
95
+ kind: "setter",
96
+ name: "download",
97
+ static: false,
98
+ private: false,
99
+ access: {
100
+ has: (obj) => "download" in obj,
101
+ set: (obj, value) => {
102
+ obj.download = value;
103
+ }
104
+ },
105
+ metadata: _metadata
106
+ }, null, _instanceExtraInitializers);
107
+ if (_metadata) Object.defineProperty(this, Symbol.metadata, {
108
+ enumerable: true,
109
+ configurable: true,
110
+ writable: true,
111
+ value: _metadata
112
+ });
113
+ }
114
+ static {
115
+ this.elementName = "sbb-download";
116
+ }
117
+ static {
118
+ this.elementDependencies = [SbbSecondaryButtonStaticElement];
119
+ }
120
+ static {
121
+ this.styles = [screenReaderOnlyStyles, unsafeCSS(download_default)];
122
+ }
123
+ #color_accessor_storage;
124
+ /** Option to set the component's background color. */
125
+ get color() {
126
+ return this.#color_accessor_storage;
127
+ }
128
+ set color(value) {
129
+ this.#color_accessor_storage = value;
130
+ }
131
+ #label_accessor_storage;
132
+ /** The label of the download. Defaults to the file name of the `href`. */
133
+ get label() {
134
+ return this.#label_accessor_storage;
135
+ }
136
+ set label(value) {
137
+ this.#label_accessor_storage = value;
138
+ }
139
+ /**
140
+ * The download behavior is always enabled and handled internally, therefore
141
+ * this property cannot be disabled and is not reflected to the host element.
142
+ * @default true
143
+ */
144
+ set download(_value) {}
145
+ get download() {
146
+ return true;
147
+ }
148
+ /** The file name extracted from the `href` (e.g. `report.pdf`). */
149
+ get fileName() {
150
+ return this.href.split(/[?#]/)[0].split("/").filter(Boolean).at(-1) ?? "";
151
+ }
152
+ /** The lower-cased file extension extracted from the `href` (e.g. `pdf`), if any. */
153
+ get fileExtension() {
154
+ const fileName = this.fileName;
155
+ return fileName.includes(".") ? fileName.split(".").at(-1)?.toLowerCase() ?? "" : "";
156
+ }
157
+ /**
158
+ * Provides a default icon based on the `href` extension, if no icon name is
159
+ * set.
160
+ */
161
+ renderIconName() {
162
+ if (this.iconName) return this.iconName;
163
+ else if (!this.href) return "";
164
+ const extension = this.fileExtension;
165
+ return extension && fileExtensionIcons.get(extension) || "document-standard-small";
166
+ }
167
+ firstUpdated(_changedProperties) {
168
+ super.firstUpdated(_changedProperties);
169
+ this._updateDescribedByElements();
170
+ }
171
+ _updateDescribedByElements() {
172
+ const link = this.shadowRoot?.querySelector?.("a");
173
+ if (link) {
174
+ const customContentElement = this.shadowRoot?.querySelector?.(".sbb-download__custom-content");
175
+ link.ariaDescribedByElements = [...customContentElement ? [customContentElement] : [], ...this._downloadInfoElements()];
176
+ }
177
+ }
178
+ _downloadInfoElements() {
179
+ return this.querySelectorAll?.("sbb-download-info") ?? [];
180
+ }
181
+ renderTemplate() {
182
+ return html`
183
+ ${this.renderIconSlot("sbb-download__icon")}
184
+ <span class="sbb-download__content">
185
+ <span class="sbb-download__label">${this.label || this.fileName}</span>
186
+ <span class="sbb-screen-reader-only">
187
+ ${!this._downloadInfoElements().length ? html`&nbsp;${this.fileExtension}` : nothing}&nbsp;${i18nDownload[this._languageController.current]}
188
+ </span>
189
+ <span class="sbb-download__custom-content" aria-hidden="true">
190
+ <slot></slot>
191
+ </span>
192
+ <span class="sbb-download__info">
193
+ <slot name="info" @slotchange="${() => this._updateDescribedByElements()}"></slot>
194
+ </span>
195
+ </span>
196
+ <sbb-secondary-button-static
197
+ class="sbb-download__button"
198
+ icon-name="download-small"
199
+ ></sbb-secondary-button-static>
200
+ `;
201
+ }
202
+ };
203
+ })();
204
+
205
+ //#endregion
206
+ //#region src/elements/download/download-info/download-info.scss?inline
207
+ var download_info_default = ":host {\n display: block;\n}\n";
208
+
209
+ //#endregion
210
+ //#region src/elements/download/download-info/download-info.component.ts
211
+ const fileSizeSuffixes = [
212
+ "B",
213
+ "KB",
214
+ "MB",
215
+ "GB",
216
+ "TB"
217
+ ];
218
+ /**
219
+ * It displays metadata of a document; used within a `sbb-download`.
220
+ */
221
+ let SbbDownloadInfoElement = (() => {
222
+ let _classSuper = SbbElement;
223
+ let _type_decorators;
224
+ let _type_initializers = [];
225
+ let _type_extraInitializers = [];
226
+ let _size_decorators;
227
+ let _size_initializers = [];
228
+ let _size_extraInitializers = [];
229
+ let _changed_decorators;
230
+ let _changed_initializers = [];
231
+ let _changed_extraInitializers = [];
232
+ let _nonAccessible_decorators;
233
+ let _nonAccessible_initializers = [];
234
+ let _nonAccessible_extraInitializers = [];
235
+ return class SbbDownloadInfoElement extends _classSuper {
236
+ static {
237
+ const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(_classSuper[Symbol.metadata] ?? null) : void 0;
238
+ _type_decorators = [forceType(), property({ converter: omitEmptyConverter })];
239
+ _size_decorators = [forceType(), property({ converter: omitEmptyConverter })];
240
+ _changed_decorators = [forceType(), property({ converter: omitEmptyConverter })];
241
+ _nonAccessible_decorators = [forceType(), property({
242
+ attribute: "non-accessible",
243
+ type: Boolean
244
+ })];
245
+ __esDecorate(this, null, _type_decorators, {
246
+ kind: "accessor",
247
+ name: "type",
248
+ static: false,
249
+ private: false,
250
+ access: {
251
+ has: (obj) => "type" in obj,
252
+ get: (obj) => obj.type,
253
+ set: (obj, value) => {
254
+ obj.type = value;
255
+ }
256
+ },
257
+ metadata: _metadata
258
+ }, _type_initializers, _type_extraInitializers);
259
+ __esDecorate(this, null, _size_decorators, {
260
+ kind: "accessor",
261
+ name: "size",
262
+ static: false,
263
+ private: false,
264
+ access: {
265
+ has: (obj) => "size" in obj,
266
+ get: (obj) => obj.size,
267
+ set: (obj, value) => {
268
+ obj.size = value;
269
+ }
270
+ },
271
+ metadata: _metadata
272
+ }, _size_initializers, _size_extraInitializers);
273
+ __esDecorate(this, null, _changed_decorators, {
274
+ kind: "accessor",
275
+ name: "changed",
276
+ static: false,
277
+ private: false,
278
+ access: {
279
+ has: (obj) => "changed" in obj,
280
+ get: (obj) => obj.changed,
281
+ set: (obj, value) => {
282
+ obj.changed = value;
283
+ }
284
+ },
285
+ metadata: _metadata
286
+ }, _changed_initializers, _changed_extraInitializers);
287
+ __esDecorate(this, null, _nonAccessible_decorators, {
288
+ kind: "accessor",
289
+ name: "nonAccessible",
290
+ static: false,
291
+ private: false,
292
+ access: {
293
+ has: (obj) => "nonAccessible" in obj,
294
+ get: (obj) => obj.nonAccessible,
295
+ set: (obj, value) => {
296
+ obj.nonAccessible = value;
297
+ }
298
+ },
299
+ metadata: _metadata
300
+ }, _nonAccessible_initializers, _nonAccessible_extraInitializers);
301
+ if (_metadata) Object.defineProperty(this, Symbol.metadata, {
302
+ enumerable: true,
303
+ configurable: true,
304
+ writable: true,
305
+ value: _metadata
306
+ });
307
+ }
308
+ static {
309
+ this.elementName = "sbb-download-info";
310
+ }
311
+ static {
312
+ this.styles = [unsafeCSS(download_info_default)];
313
+ }
314
+ #type_accessor_storage;
315
+ /**
316
+ * The type of the document (e.g. `PDF`). Falls back to the extension of the
317
+ * parent `sbb-download`.
318
+ */
319
+ get type() {
320
+ return this.#type_accessor_storage;
321
+ }
322
+ set type(value) {
323
+ this.#type_accessor_storage = value;
324
+ }
325
+ #size_accessor_storage;
326
+ /**
327
+ * The size of the document. If the value contains non-numeric characters it
328
+ * is rendered as is, otherwise it is interpreted as a number of bytes and
329
+ * shortened to the closest unit.
330
+ */
331
+ get size() {
332
+ return this.#size_accessor_storage;
333
+ }
334
+ set size(value) {
335
+ this.#size_accessor_storage = value;
336
+ }
337
+ #changed_accessor_storage;
338
+ /** The date of the latest change of the document, as an ISO 8601 string. */
339
+ get changed() {
340
+ return this.#changed_accessor_storage;
341
+ }
342
+ set changed(value) {
343
+ this.#changed_accessor_storage = value;
344
+ }
345
+ #nonAccessible_accessor_storage;
346
+ /** Whether the document is not accessible. */
347
+ get nonAccessible() {
348
+ return this.#nonAccessible_accessor_storage;
349
+ }
350
+ set nonAccessible(value) {
351
+ this.#nonAccessible_accessor_storage = value;
352
+ }
353
+ constructor() {
354
+ super();
355
+ this.#type_accessor_storage = __runInitializers(this, _type_initializers, "");
356
+ this.#size_accessor_storage = (__runInitializers(this, _type_extraInitializers), __runInitializers(this, _size_initializers, ""));
357
+ this.#changed_accessor_storage = (__runInitializers(this, _size_extraInitializers), __runInitializers(this, _changed_initializers, ""));
358
+ this.#nonAccessible_accessor_storage = (__runInitializers(this, _changed_extraInitializers), __runInitializers(this, _nonAccessible_initializers, false));
359
+ this._language = (__runInitializers(this, _nonAccessible_extraInitializers), new SbbLanguageController(this));
360
+ this._dateAdapter = readConfig().datetime?.dateAdapter ?? defaultDateAdapter;
361
+ this._resolvedType = "";
362
+ this._typeRedundant = false;
363
+ this._resolvedSize = "";
364
+ this._resolvedChanged = "";
365
+ /** @internal **/
366
+ this.internals.ariaHidden = "true";
367
+ this.addController(new SbbPropertyWatcherController(this, () => this.closest("sbb-download"), {
368
+ href: () => this.requestUpdate(),
369
+ label: () => this.requestUpdate()
370
+ }));
371
+ }
372
+ connectedCallback() {
373
+ super.connectedCallback();
374
+ this.slot ||= "info";
375
+ this.requestUpdate();
376
+ }
377
+ willUpdate(changedProperties) {
378
+ super.willUpdate(changedProperties);
379
+ this._resolvedType = this._resolveType();
380
+ this._typeRedundant = this._isTypeRedundant();
381
+ if (changedProperties.has("size")) this._resolvedSize = this._resolveSize();
382
+ if (changedProperties.has("changed")) this._resolvedChanged = this._resolveChanged();
383
+ }
384
+ /** Resolves the type, falling back to the extension of the parent download's
385
+ * href.
386
+ */
387
+ _resolveType() {
388
+ return this.type || (this.closest?.("sbb-download")?.fileExtension.toUpperCase() ?? "");
389
+ }
390
+ /**
391
+ * Whether the type is already conveyed by the parent download's label.
392
+ * When the parent download has no explicit `label`, it falls back to the file
393
+ * name (e.g. `some-file.pdf`), which already includes the extension. In that
394
+ * case the type is redundant for assistive technology.
395
+ */
396
+ _isTypeRedundant() {
397
+ const parent = this.closest?.("sbb-download");
398
+ return !!parent && !parent.label && !!parent.fileExtension;
399
+ }
400
+ /**
401
+ * Formats the size, shortening a pure number of bytes to the closest unit.
402
+ */
403
+ _resolveSize() {
404
+ const size = this.size.trim();
405
+ if (!size || !/^\d+$/.test(size)) return size;
406
+ const bytes = Number(size);
407
+ if (bytes <= 0) return `0 ${fileSizeSuffixes[0]}`;
408
+ const i = Math.min(Math.floor(Math.log(bytes) / Math.log(1024)), fileSizeSuffixes.length - 1);
409
+ return `${(bytes / 1024 ** i).toFixed(0)} ${fileSizeSuffixes[i]}`;
410
+ }
411
+ /**
412
+ * Formats the ISO 8601 change date using the configured date adapter, or
413
+ * renders it as is if invalid.
414
+ */
415
+ _resolveChanged() {
416
+ if (!this.changed) return "";
417
+ const date = this._dateAdapter.deserialize(this.changed);
418
+ if (!this._dateAdapter.isValid(date)) return this.changed;
419
+ return this._dateAdapter.format(date, { weekdayStyle: "none" });
420
+ }
421
+ render() {
422
+ const separator = ", ";
423
+ const items = [
424
+ this._resolvedType,
425
+ this._resolvedSize,
426
+ this.nonAccessible ? i18nNonAccessible[this._language.current] : "",
427
+ this._resolvedChanged
428
+ ].filter(Boolean);
429
+ this.internals.ariaLabel = items.slice(this._typeRedundant && this._resolvedType ? 1 : 0).join(separator);
430
+ return html`${items.join(separator)}`;
431
+ }
432
+ };
433
+ })();
434
+
435
+ //#endregion
436
+ export { SbbDownloadElement, SbbDownloadInfoElement };
@@ -111,12 +111,12 @@ var SbbExpansionPanelHeaderElement = class extends SbbDisabledTabIndexActionMixi
111
111
  <slot></slot>
112
112
  </span>
113
113
  ${!this.disabled ? html`<span class="sbb-expansion-panel-header__toggle">
114
- <sbb-icon
115
- name="chevron-small-down-medium"
116
- class="sbb-expansion-panel-header__toggle-icon"
117
- >
118
- </sbb-icon>
119
- </span>` : nothing}
114
+ <sbb-icon
115
+ name="chevron-small-down-medium"
116
+ class="sbb-expansion-panel-header__toggle-icon"
117
+ >
118
+ </sbb-icon>
119
+ </span>` : nothing}
120
120
  `;
121
121
  }
122
122
  };
@@ -279,13 +279,14 @@ const SbbFileSelectorCommonElementMixin = (superclass) => {
279
279
  if (fileInput.files) this.createFileList(fileInput.files);
280
280
  forwardEvent(event, this);
281
281
  }
282
- createFileList(files) {
282
+ createFileList(files, emitNativeEvents = false) {
283
283
  const fileArray = Array.from(files);
284
284
  if (!this.multiple && files.length > 1 || this.accept && fileArray.some((file) => !this.accept.split(",").some((a) => file.name.endsWith(a.trim())))) return;
285
285
  if (!this.multiple || this.multipleMode !== "persistent" || this.files.length === 0) this.files = fileArray;
286
286
  else this.files = fileArray.filter((newFile) => this.files.findIndex((oldFile) => this._checkFileEquality(newFile, oldFile)) === -1).concat(this.files);
287
287
  this._updateA11yLiveRegion();
288
288
  this._dispatchFileChangedEvent();
289
+ if (emitNativeEvents) this._dispatchNativeEvents();
289
290
  }
290
291
  getButtonLabel() {
291
292
  return this.multiple ? i18nFileSelectorButtonLabelMultiple[this.language.current] : i18nFileSelectorButtonLabel[this.language.current];
@@ -293,6 +294,10 @@ const SbbFileSelectorCommonElementMixin = (superclass) => {
293
294
  _removeFile(file) {
294
295
  this.files = this.files.filter((f) => !this._checkFileEquality(file, f));
295
296
  this._updateA11yLiveRegion();
297
+ this._dispatchNativeEvents();
298
+ this._dispatchFileChangedEvent();
299
+ }
300
+ _dispatchNativeEvents() {
296
301
  /** The input event fires when the value has been changed as a direct result of a user action. */
297
302
  this.dispatchEvent(new InputEvent("input", {
298
303
  bubbles: true,
@@ -304,7 +309,6 @@ const SbbFileSelectorCommonElementMixin = (superclass) => {
304
309
  * for each alteration to an element's value.
305
310
  */
306
311
  this.dispatchEvent(new Event("change", { bubbles: true }));
307
- this._dispatchFileChangedEvent();
308
312
  }
309
313
  _dispatchFileChangedEvent() {
310
314
  const filechanged = this.files;
@@ -367,7 +371,7 @@ const SbbFileSelectorCommonElementMixin = (superclass) => {
367
371
  if (!this.disabled && !this.formDisabled) {
368
372
  this._setDragState();
369
373
  this._blockEvent(event);
370
- this.createFileList(event.dataTransfer.files);
374
+ this.createFileList(event.dataTransfer.files, true);
371
375
  }
372
376
  }
373
377
  _blockEvent(event) {
@@ -232,7 +232,7 @@ let SbbFlipCardElement = (() => {
232
232
  }
233
233
  /** Returns the card details content element wrapper. */
234
234
  get _detailsContentElement() {
235
- return this.details.shadowRoot.firstElementChild;
235
+ return this.details?.shadowRoot?.querySelector(".sbb-flip-card-details") ?? null;
236
236
  }
237
237
  /** Whether the flip card is flipped. */
238
238
  get isFlipped() {
@@ -268,10 +268,11 @@ let SbbFlipCardElement = (() => {
268
268
  /** Toggles the state of the sbb-flip-card. */
269
269
  toggle() {
270
270
  this._flipped = !this._flipped;
271
- if (this._flipped) {
271
+ const detailsContentElement = this._detailsContentElement;
272
+ if (this._flipped && detailsContentElement) {
272
273
  this._setCardDetailsHeight();
273
- this._cardDetailsResizeObserver.observe(this._detailsContentElement);
274
- } else this._cardDetailsResizeObserver.unobserve(this._detailsContentElement);
274
+ this._cardDetailsResizeObserver.observe(detailsContentElement);
275
+ } else if (detailsContentElement) this._cardDetailsResizeObserver.unobserve(detailsContentElement);
275
276
  this.toggleState("flipped", this._flipped);
276
277
  ɵstateController(this.details)?.toggle("flipped", this._flipped);
277
278
  this.summary.inert = this._flipped;
@@ -715,14 +715,14 @@ let SbbImageElement = (() => {
715
715
  return html`
716
716
  <div class="sbb-image__wrapper">
717
717
  ${!this.skipLqip ? html`<img
718
- alt=""
719
- class="sbb-image__blurred"
720
- src=${imageUrlLQIP}
721
- width="1000"
722
- height="562"
723
- loading=${this.loading ?? nothing}
724
- decoding=${this.decoding ?? nothing}
725
- />` : nothing}
718
+ alt=""
719
+ class="sbb-image__blurred"
720
+ src=${imageUrlLQIP}
721
+ width="1000"
722
+ height="562"
723
+ loading=${this.loading ?? nothing}
724
+ decoding=${this.decoding ?? nothing}
725
+ />` : nothing}
726
726
 
727
727
  <picture>
728
728
  <!-- render picture element sources -->
@@ -159,14 +159,14 @@ let SbbMapContainerElement = (() => {
159
159
  <slot></slot>
160
160
 
161
161
  ${!this.hideScrollUpButton ? html`<sbb-accent-button
162
- class="sbb-map-container__sidebar-button"
163
- size="l"
164
- icon-name="location-pin-map-small"
165
- @click=${() => this._onScrollButtonClick()}
166
- ?inert=${!this._scrollUpButtonVisible}
167
- >
168
- ${i18nMapContainerButtonLabel[this._language.current]}
169
- </sbb-accent-button>` : nothing}
162
+ class="sbb-map-container__sidebar-button"
163
+ size="l"
164
+ icon-name="location-pin-map-small"
165
+ @click=${() => this._onScrollButtonClick()}
166
+ ?inert=${!this._scrollUpButtonVisible}
167
+ >
168
+ ${i18nMapContainerButtonLabel[this._language.current]}
169
+ </sbb-accent-button>` : nothing}
170
170
  </div>
171
171
  `;
172
172
  }
@@ -5,7 +5,7 @@ import { SbbButtonBaseElement, SbbElement, SbbPropertyWatcherController, default
5
5
  import { MutationController } from "@lit-labs/observers/mutation-controller.js";
6
6
 
7
7
  //#region src/elements/mini-calendar/mini-calendar-day/mini-calendar-day.scss?inline
8
- var mini_calendar_day_default = ":host {\n --sbb-mini-calendar-day-animation-duration: var(\n --sbb-disable-animation-duration,\n var(--sbb-animation-duration-2x)\n );\n display: block;\n height: var(--sbb-mini-calendar-day-dimensions);\n width: var(--sbb-mini-calendar-day-dimensions);\n margin: 0.0625rem;\n border-radius: var(--sbb-border-radius-infinity);\n color: var(--sbb-color-storm);\n color: light-dark(var(--sbb-color-storm), var(--sbb-color-smoke));\n background-color: currentcolor;\n}\n\n@media (any-hover: hover) {\n :host(:hover) {\n scale: var(--sbb-mini-calendar-day-scale);\n transition: scale var(--sbb-mini-calendar-day-animation-easing) var(--sbb-mini-calendar-day-animation-duration);\n }\n}\n\n:host(:focus-visible) {\n outline-offset: var(--sbb-focus-outline-offset);\n outline: var(--sbb-focus-outline-color) var(--sbb-focus-outline-style, solid) var(--sbb-focus-outline-width);\n outline-offset: 0.125rem;\n}\n\n:host([color=charcoal]) {\n color: var(--sbb-background-color-2-inverted);\n}\n\n:host([color=cloud]) {\n color: var(--sbb-background-color-4-inverted);\n}\n\n:host([color=orange]) {\n color: var(--sbb-color-orange-light);\n}\n\n:host([color=red]) {\n color: var(--sbb-color-error);\n}\n\n:host([color=sky]) {\n color: var(--sbb-color-sky-light);\n}\n\n:host([marker=circle]) {\n background-color: var(--sbb-color-1-inverted);\n border: 0.0625rem solid currentcolor;\n}\n\n:host([marker=target]) {\n background: radial-gradient(circle, currentcolor 0%, currentcolor 25%, var(--sbb-color-1-inverted) 25%, var(--sbb-color-1-inverted) 50%, currentcolor 50%, currentcolor 100%);\n}\n\n:host([marker=slash]) {\n position: relative;\n}\n:host([marker=slash])::before {\n content: \"\";\n position: absolute;\n inset: 0;\n background-image: linear-gradient(-45deg, transparent 45%, var(--sbb-color-1-inverted) 45%, var(--sbb-color-1-inverted) 55%, transparent 55%);\n}\n\n:host([marker=cross]) {\n position: relative;\n}\n:host([marker=cross])::before {\n content: \"\";\n position: absolute;\n inset: 0;\n background-image: linear-gradient(-45deg, transparent 45%, var(--sbb-color-1-inverted) 45%, var(--sbb-color-1-inverted) 55%, transparent 55%), linear-gradient(45deg, transparent 45%, var(--sbb-color-1-inverted) 45%, var(--sbb-color-1-inverted) 55%, transparent 55%);\n}\n";
8
+ var mini_calendar_day_default = ":host {\n --sbb-mini-calendar-day-animation-duration: var(\n --sbb-disable-animation-duration,\n var(--sbb-animation-duration-2x)\n );\n display: block;\n height: var(--sbb-mini-calendar-day-dimensions);\n width: var(--sbb-mini-calendar-day-dimensions);\n margin: 0.0625rem;\n border-radius: var(--sbb-border-radius-infinity);\n color: var(--sbb-color-storm);\n color: light-dark(var(--sbb-color-storm), var(--sbb-color-smoke));\n background-color: currentcolor;\n}\n\n@media (any-hover: hover) {\n :host(:hover) {\n scale: var(--sbb-mini-calendar-day-scale);\n transition: scale var(--sbb-mini-calendar-day-animation-easing) var(--sbb-mini-calendar-day-animation-duration);\n }\n}\n\n:host(:focus-visible) {\n outline-offset: var(--sbb-focus-outline-offset);\n outline: var(--sbb-focus-outline-color) var(--sbb-focus-outline-style, solid) var(--sbb-focus-outline-width);\n outline-offset: 0.125rem;\n}\n\n:host([color=charcoal]) {\n color: var(--sbb-background-color-2-inverted);\n}\n\n:host([color=cloud]) {\n color: var(--sbb-background-color-4);\n}\n\n:host([color=orange]) {\n color: var(--sbb-color-orange-light);\n}\n\n:host([color=red]) {\n color: var(--sbb-color-error);\n}\n\n:host([color=sky]) {\n color: var(--sbb-color-sky-light);\n}\n\n:host([marker=circle]) {\n background-color: var(--sbb-color-1-inverted);\n border: 0.0625rem solid currentcolor;\n}\n\n:host([marker=target]) {\n background: radial-gradient(circle, currentcolor 0%, currentcolor 25%, var(--sbb-color-1-inverted) 25%, var(--sbb-color-1-inverted) 50%, currentcolor 50%, currentcolor 100%);\n}\n\n:host([marker=slash]) {\n position: relative;\n}\n:host([marker=slash])::before {\n content: \"\";\n position: absolute;\n inset: 0;\n background-image: linear-gradient(-45deg, transparent 45%, var(--sbb-color-1-inverted) 45%, var(--sbb-color-1-inverted) 55%, transparent 55%);\n}\n\n:host([marker=cross]) {\n position: relative;\n}\n:host([marker=cross])::before {\n content: \"\";\n position: absolute;\n inset: 0;\n background-image: linear-gradient(-45deg, transparent 45%, var(--sbb-color-1-inverted) 45%, var(--sbb-color-1-inverted) 55%, transparent 55%), linear-gradient(45deg, transparent 45%, var(--sbb-color-1-inverted) 45%, var(--sbb-color-1-inverted) 55%, transparent 55%);\n}\n";
9
9
 
10
10
  //#endregion
11
11
  //#region src/elements/mini-calendar/mini-calendar-day/mini-calendar-day.component.ts
@@ -240,15 +240,18 @@ let SbbNotificationElement = (() => {
240
240
  </span>
241
241
 
242
242
  ${!this.readOnly ? html`
243
- <sbb-divider class="sbb-notification__divider" orientation="vertical"></sbb-divider>
244
- <sbb-secondary-button
245
- size=${this.size || nothing}
246
- icon-name="cross-small"
247
- @click=${() => this.close()}
248
- aria-label=${i18nCloseNotification[this._language.current]}
249
- class="sbb-notification__close"
250
- ></sbb-secondary-button>
251
- ` : nothing}
243
+ <sbb-divider
244
+ class="sbb-notification__divider"
245
+ orientation="vertical"
246
+ ></sbb-divider>
247
+ <sbb-secondary-button
248
+ size=${this.size || nothing}
249
+ icon-name="cross-small"
250
+ @click=${() => this.close()}
251
+ aria-label=${i18nCloseNotification[this._language.current]}
252
+ class="sbb-notification__close"
253
+ ></sbb-secondary-button>
254
+ ` : nothing}
252
255
  </div>
253
256
  </div>
254
257
  `;
@@ -129,11 +129,11 @@ let SbbOptgroupBaseElement = (() => {
129
129
  render() {
130
130
  return html`
131
131
  ${this.label ? html`
132
- <div class="sbb-optgroup__label" aria-hidden="true">
133
- <div class="sbb-optgroup__icon-space"></div>
134
- <span>${this.label}</span>
135
- </div>
136
- ` : nothing}
132
+ <div class="sbb-optgroup__label" aria-hidden="true">
133
+ <div class="sbb-optgroup__icon-space"></div>
134
+ <span>${this.label}</span>
135
+ </div>
136
+ ` : nothing}
137
137
  <slot @slotchange=${this._handleSlotchange}></slot>
138
138
  `;
139
139
  }
@@ -698,12 +698,12 @@ var SbbOptionElement = class extends SbbOptionBaseElement {
698
698
 
699
699
  <!-- Checkbox -->
700
700
  ${this._isMultiple() ? html`
701
- <sbb-visual-checkbox
702
- ?checked=${this.selected}
703
- ?disabled=${this.disabled || this.disabledFromGroup}
704
- ?negative=${this.matches?.(":is(:state(negative),[state--negative])")}
705
- ></sbb-visual-checkbox>
706
- ` : nothing}
701
+ <sbb-visual-checkbox
702
+ ?checked=${this.selected}
703
+ ?disabled=${this.disabled || this.disabledFromGroup}
704
+ ?negative=${this.matches?.(":is(:state(negative),[state--negative])")}
705
+ ></sbb-visual-checkbox>
706
+ ` : nothing}
707
707
  `;
708
708
  }
709
709
  renderLabel() {