diff --git a/src/elements-experimental/pearl-chain-legacy/pearl-chain-legacy.scss b/src/elements-experimental/pearl-chain-legacy/pearl-chain-legacy.scss
index b71aa0beb99..666e22a6c35 100644
--- a/src/elements-experimental/pearl-chain-legacy/pearl-chain-legacy.scss
+++ b/src/elements-experimental/pearl-chain-legacy/pearl-chain-legacy.scss
@@ -4,8 +4,9 @@
background-color: unset;
background-image: linear-gradient(to right, currentcolor 0%, currentcolor 50%, Canvas 50%);
background-repeat: repeat-x;
- background-size: calc(2 * var(--sbb-pearl-chain-spacing-small)) var(--sbb-pearl-chain-height);
- inset-inline-end: var(--sbb-pearl-chain-height);
+ background-size: calc(2 * var(--sbb-pearl-chain-leg-spacing-small))
+ var(--sbb-pearl-chain-leg-height);
+ inset-inline-end: var(--sbb-pearl-chain-leg-height);
@include sbb.if-forced-colors {
background: unset;
@@ -18,11 +19,11 @@
@include sbb.box-sizing;
:host {
- --sbb-pearl-chain-height: var(--sbb-border-width-2x);
- --sbb-pearl-chain-spacing-small: #{sbb.px-to-rem-build(2)};
+ --sbb-pearl-chain-leg-height: var(--sbb-border-width-2x);
+ --sbb-pearl-chain-leg-spacing-small: #{sbb.px-to-rem-build(2)};
--sbb-pearl-chain-color: var(--sbb-pearl-chain-bullet-color);
- --sbb-pearl-chain-color-disruption: var(--sbb-pearl-chain-bullet-color-disruption);
- --sbb-pearl-chain-color-past: var(--sbb-pearl-chain-bullet-color-past);
+ --sbb-pearl-chain-leg-color-disruption: var(--sbb-pearl-chain-bullet-color-disruption);
+ --sbb-pearl-chain-leg-color-past: var(--sbb-pearl-chain-bullet-color-past);
--sbb-pearl-chain-leg-width: 100%;
display: block;
@@ -38,7 +39,7 @@
color: var(--sbb-pearl-chain-color);
width: 100%;
padding-block: calc(
- (var(--sbb-pearl-chain-bullet-size-start-end) - var(--sbb-pearl-chain-height)) / 2
+ (var(--sbb-pearl-chain-bullet-size-start-end) - var(--sbb-pearl-chain-leg-height)) / 2
);
padding-inline-end: var(--sbb-pearl-chain-bullet-size-start-end);
}
@@ -69,8 +70,8 @@
flex-shrink: 0;
flex-grow: 0;
position: relative;
- height: var(--sbb-pearl-chain-height);
- border-inline-end: var(--sbb-pearl-chain-spacing-small) solid Canvas;
+ height: var(--sbb-pearl-chain-leg-height);
+ border-inline-end: var(--sbb-pearl-chain-leg-spacing-small) solid Canvas;
background-color: currentcolor;
width: var(--sbb-pearl-chain-leg-width);
display: flex;
@@ -112,7 +113,7 @@
.sbb-pearl-chain__leg--progress .sbb-pearl-chain__stop,
.sbb-pearl-chain--progress,
.sbb-pearl-chain__bullet--past {
- color: var(--sbb-pearl-chain-color-past);
+ color: var(--sbb-pearl-chain-leg-color-past);
@include sbb.pearl-chain-bullet-past;
@@ -131,7 +132,7 @@
.sbb-pearl-chain--arrival-disruption,
.sbb-pearl-chain--departure-disruption,
.sbb-pearl-chain__leg--disruption {
- color: var(--sbb-pearl-chain-color-disruption);
+ color: var(--sbb-pearl-chain-leg-color-disruption);
@include sbb.pearl-chain-bullet-disruption;
@@ -154,7 +155,7 @@
}
.sbb-pearl-chain__leg--skipped {
- color: var(--sbb-pearl-chain-color-disruption);
+ color: var(--sbb-pearl-chain-leg-color-disruption);
&::after {
@include sbb-pearl-chain-dotted;
@@ -179,7 +180,7 @@
inset-block: 0;
inset-inline-start: 0;
background-color: currentcolor;
- border-radius: var(--sbb-pearl-chain-height);
+ border-radius: var(--sbb-pearl-chain-leg-height);
z-index: 1;
@include sbb.if-forced-colors {
@@ -192,11 +193,11 @@
}
.sbb-pearl-chain__leg:last-of-type::after {
- inset-inline-end: calc(-1 * var(--sbb-pearl-chain-height));
+ inset-inline-end: calc(-1 * var(--sbb-pearl-chain-leg-height));
}
.sbb-pearl-chain__leg--progress::after {
- background-color: var(--sbb-pearl-chain-color-past);
+ background-color: var(--sbb-pearl-chain-leg-color-past);
// --sbb-pearl-chain-leg-status: defined in .ts file
width: var(--sbb-pearl-chain-leg-status);
diff --git a/src/elements/pearl-chain/pearl-chain-leg/pearl-chain-leg.scss b/src/elements/pearl-chain/pearl-chain-leg/pearl-chain-leg.scss
index 9d944f9e5d7..e86dd1b0249 100644
--- a/src/elements/pearl-chain/pearl-chain-leg/pearl-chain-leg.scss
+++ b/src/elements/pearl-chain/pearl-chain-leg/pearl-chain-leg.scss
@@ -1,11 +1,12 @@
@use '../../core/styles' as sbb;
-@mixin sbb-pearl-chain-dotted {
+@mixin sbb-pearl-chain-leg-dotted {
background-color: unset;
background-image: linear-gradient(to right, currentcolor 0%, currentcolor 50%, Canvas 50%);
background-repeat: repeat-x;
- background-size: calc(2 * var(--sbb-pearl-chain-spacing-small)) var(--sbb-pearl-chain-height);
- inset-inline-end: var(--sbb-pearl-chain-height);
+ background-size: calc(2 * var(--sbb-pearl-chain-leg-spacing-small))
+ var(--sbb-pearl-chain-leg-height);
+ inset-inline-end: var(--sbb-pearl-chain-leg-height);
@include sbb.if-forced-colors {
background: unset;
@@ -18,13 +19,11 @@
@include sbb.box-sizing;
:host {
- --sbb-pearl-chain-height: var(--sbb-border-width-2x);
- --sbb-pearl-chain-spacing-small: #{sbb.px-to-rem-build(2)};
- --sbb-pearl-chain-color: var(--sbb-pearl-chain-bullet-color);
- --sbb-pearl-chain-color-disruption: var(--sbb-pearl-chain-bullet-color-disruption);
- --sbb-pearl-chain-color-past: var(--sbb-pearl-chain-bullet-color-past);
+ --sbb-pearl-chain-leg-height: var(--sbb-border-width-2x);
+ --sbb-pearl-chain-leg-spacing-small: #{sbb.px-to-rem-build(2)};
+ --sbb-pearl-chain-leg-color-disruption: var(--sbb-pearl-chain-bullet-color-disruption);
+ --sbb-pearl-chain-leg-color-past: var(--sbb-pearl-chain-bullet-color-past);
--sbb-pearl-chain-leg-width: 100%;
- --sbb-pearl-chain-leg-animation: none;
display: contents;
@@ -34,8 +33,11 @@
.sbb-pearl-chain__leg {
flex: var(--sbb-pearl-chain-leg-weight, 1) var(--sbb-pearl-chain-leg-weight, 1);
position: relative;
- height: var(--sbb-pearl-chain-height);
- border-inline-end: var(--sbb-pearl-chain-last-leg-margin, var(--sbb-pearl-chain-spacing-small))
+ height: var(--sbb-pearl-chain-leg-height);
+ border-inline-end: var(
+ --sbb-pearl-chain-last-leg-margin,
+ var(--sbb-pearl-chain-leg-spacing-small)
+ )
solid Canvas;
background-color: currentcolor;
width: var(--sbb-pearl-chain-leg-width);
@@ -45,21 +47,17 @@
@include sbb.if-forced-colors {
background-color: CanvasText;
- :host([past='']) & {
+ :host([past]) & {
background-color: GrayText;
}
}
- :host([data-last-leg]) & {
- --sbb-pearl-chain-last-leg-margin: none;
-
- &::after {
- inset-inline-end: calc(-1 * var(--sbb-pearl-chain-height));
- }
+ &::after {
+ inset-inline-end: var(--sbb-pearl-chain-last-leg-inset-inline-end, 0);
}
:host([past]) & {
- color: var(--sbb-pearl-chain-color-past);
+ color: var(--sbb-pearl-chain-leg-color-past);
@include sbb.pearl-chain-bullet-past;
@@ -69,7 +67,7 @@
}
:host([disruption]) & {
- color: var(--sbb-pearl-chain-color-disruption);
+ color: var(--sbb-pearl-chain-leg-color-disruption);
@include sbb.pearl-chain-bullet-disruption;
@@ -79,21 +77,25 @@
}
&::after {
- @include sbb-pearl-chain-dotted;
+ @include sbb-pearl-chain-leg-dotted;
}
}
:host(:is([arrival-skipped], [departure-skipped])) & {
- color: var(--sbb-pearl-chain-color-disruption);
+ color: var(--sbb-pearl-chain-leg-color-disruption);
&::after {
- @include sbb-pearl-chain-dotted;
+ @include sbb-pearl-chain-leg-dotted;
}
}
:host([data-progress]:not([arrival-skipped], [departure-skipped], [disruption])) & {
+ --sbb-pearl-chain-status-position-normalized: calc(
+ (100% - var(--sbb-pearl-chain-bullet-size-start-end)) * var(--sbb-pearl-chain-status-position)
+ );
+
&::before {
- --sbb-pearl-chain-bullet-animation-name: var(--sbb-pearl-chain-leg-animation);
+ --sbb-pearl-chain-bullet-animation-name: var(--sbb-pearl-chain-leg-animation, none);
@include sbb.pearl-chain-bullet-position;
@@ -105,7 +107,7 @@
z-index: 4;
// --sbb-pearl-chain-status-position: defined in .ts file
- inset-inline-start: var(--sbb-pearl-chain-status-position);
+ inset-inline-start: var(--sbb-pearl-chain-status-position-normalized);
}
}
@@ -115,10 +117,10 @@
}
& {
- background-color: var(--sbb-pearl-chain-color-past);
+ background-color: var(--sbb-pearl-chain-leg-color-past);
// --sbb-pearl-chain-leg-status: defined in .ts file
- width: var(--sbb-pearl-chain-status-position);
+ width: var(--sbb-pearl-chain-status-position-normalized);
}
}
}
@@ -131,7 +133,7 @@
inset-block: 0;
inset-inline-start: 0;
background-color: currentcolor;
- border-radius: var(--sbb-pearl-chain-height);
+ border-radius: var(--sbb-pearl-chain-leg-height);
z-index: 1;
@include sbb.if-forced-colors {
@@ -144,6 +146,7 @@
}
.sbb-pearl-chain__stop {
+ display: var(--sbb-pearl-chain-leg-stop-display, unset);
position: relative;
z-index: 2;
diff --git a/src/elements/pearl-chain/pearl-chain-leg/pearl-chain-leg.ts b/src/elements/pearl-chain/pearl-chain-leg/pearl-chain-leg.ts
index f61954ce16d..b848760aba4 100644
--- a/src/elements/pearl-chain/pearl-chain-leg/pearl-chain-leg.ts
+++ b/src/elements/pearl-chain/pearl-chain-leg/pearl-chain-leg.ts
@@ -1,9 +1,8 @@
import type { CSSResultGroup, PropertyValues, TemplateResult } from 'lit';
-import { html, LitElement, nothing } from 'lit';
+import { html, LitElement } from 'lit';
import { customElement, property } from 'lit/decorators.js';
import { forceType } from '../../core/decorators.js';
-import type { SbbDateLike } from '../../core/interfaces.js';
import style from './pearl-chain-leg.scss?lit&inline';
@@ -17,23 +16,23 @@ class SbbPearlChainLegElement extends LitElement {
/** Departure time of the leg. */
@property()
- public set departure(value: SbbDateLike | null) {
+ public set departure(value: Date | null) {
this._departure = value;
}
- public get departure(): SbbDateLike | null {
+ public get departure(): Date | null {
return this._departure;
}
- private _departure: SbbDateLike | null = null;
+ private _departure: Date | null = null;
/** Arrival time of the leg. */
@property()
- public set arrival(value: SbbDateLike | null) {
+ public set arrival(value: Date | null) {
this._arrival = value;
}
- public get arrival(): SbbDateLike | null {
+ public get arrival(): Date | null {
return this._arrival;
}
- private _arrival: SbbDateLike | null = null;
+ private _arrival: Date | null = null;
/** Whether the leg is disrupted. */
@forceType()
@@ -65,26 +64,22 @@ class SbbPearlChainLegElement extends LitElement {
@property({ type: Number, attribute: 'arrival-delay' })
public accessor arrivalDelay: number = 0;
- private _displayStop(): boolean {
- return !this.hasAttribute('data-first-leg');
- }
-
- protected override willUpdate(_changedProperties: PropertyValues): void {
- super.willUpdate(_changedProperties);
+ protected override willUpdate(changedProperties: PropertyValues): void {
+ super.willUpdate(changedProperties);
- //We need to update parent pearl-chain so that following leg can be styled properly.
- if (_changedProperties.has('arrivalSkipped')) {
+ // We need to update parent pearl-chain so that following leg can be styled properly.
+ if (changedProperties.has('arrivalSkipped')) {
const parentPearlChain = this.closest?.('sbb-pearl-chain');
if (!parentPearlChain) {
return;
}
- parentPearlChain.requestUpdate();
+ parentPearlChain?.requestUpdate();
}
}
protected override render(): TemplateResult {
return html`
- ${this._displayStop() ? html` ` : nothing}
+
`;
}
}
diff --git a/src/elements/pearl-chain/pearl-chain/pearl-chain.scss b/src/elements/pearl-chain/pearl-chain/pearl-chain.scss
index 830c07aa675..be44aceeefb 100644
--- a/src/elements/pearl-chain/pearl-chain/pearl-chain.scss
+++ b/src/elements/pearl-chain/pearl-chain/pearl-chain.scss
@@ -4,11 +4,11 @@
@include sbb.box-sizing;
:host {
- --sbb-pearl-chain-height: var(--sbb-border-width-2x);
- --sbb-pearl-chain-spacing-small: #{sbb.px-to-rem-build(2)};
+ --sbb-pearl-chain-leg-height: var(--sbb-border-width-2x);
+ --sbb-pearl-chain-leg-spacing-small: #{sbb.px-to-rem-build(2)};
--sbb-pearl-chain-color: var(--sbb-pearl-chain-bullet-color);
- --sbb-pearl-chain-color-disruption: var(--sbb-pearl-chain-bullet-color-disruption);
- --sbb-pearl-chain-color-past: var(--sbb-pearl-chain-bullet-color-past);
+ --sbb-pearl-chain-leg-color-disruption: var(--sbb-pearl-chain-bullet-color-disruption);
+ --sbb-pearl-chain-leg-color-past: var(--sbb-pearl-chain-bullet-color-past);
--sbb-pearl-chain-leg-width: 100%;
display: block;
@@ -16,6 +16,19 @@
@include sbb.pearl-chain-bullet-variables;
}
+:host([marker='pulsing']) {
+ --sbb-pearl-chain-leg-animation: pearl-chain-bullet-position-pulse;
+}
+
+::slotted(sbb-pearl-chain-leg:first-of-type) {
+ --sbb-pearl-chain-leg-stop-display: none;
+}
+
+::slotted(sbb-pearl-chain-leg:last-of-type) {
+ --sbb-pearl-chain-last-leg-margin: none;
+ --sbb-pearl-chain-last-leg-inset-inline-end: calc(-1 * var(--sbb-pearl-chain-leg-height));
+}
+
.sbb-pearl-chain__wrapper {
display: flex;
justify-content: space-between;
@@ -33,12 +46,12 @@
color: var(--sbb-pearl-chain-color);
width: 100%;
padding-block: calc(
- (var(--sbb-pearl-chain-bullet-size-start-end) - var(--sbb-pearl-chain-height)) / 2
+ (var(--sbb-pearl-chain-bullet-size-start-end) - var(--sbb-pearl-chain-leg-height)) / 2
);
padding-inline-end: var(--sbb-pearl-chain-bullet-size-start-end);
}
-// first and last bullet
+// First and last bullet
.sbb-pearl-chain__bullet {
@include sbb.pearl-chain-bullet-start-end;
@include sbb.pearl-chain-bullet;
@@ -60,8 +73,8 @@
}
}
-.sbb-pearl-chain__bullet-past {
- color: var(--sbb-pearl-chain-color-past);
+.sbb-pearl-chain__bullet[data-past] {
+ color: var(--sbb-pearl-chain-leg-color-past);
@include sbb.pearl-chain-bullet-past;
@@ -70,8 +83,8 @@
}
}
-.sbb-pearl-chain__bullet-disruption {
- color: var(--sbb-pearl-chain-color-disruption);
+.sbb-pearl-chain__bullet[data-disrupted] {
+ color: var(--sbb-pearl-chain-leg-color-disruption);
@include sbb.if-forced-colors {
color: Highlight;
@@ -79,13 +92,7 @@
}
}
-.sbb-pearl-chain__bullet-skipped {
+.sbb-pearl-chain__bullet[data-skipped] {
@include sbb.pearl-chain-bullet-start-end;
@include sbb.pearl-chain-bullet-skipped;
}
-
-.sbb-pearl-chain__time {
- @include sbb.text-s--bold;
-
- color: var(--sbb-color-charcoal);
-}
diff --git a/src/elements/pearl-chain/pearl-chain/pearl-chain.stories.ts b/src/elements/pearl-chain/pearl-chain/pearl-chain.stories.ts
index 60407c2d499..c7ebbe03fbb 100644
--- a/src/elements/pearl-chain/pearl-chain/pearl-chain.stories.ts
+++ b/src/elements/pearl-chain/pearl-chain/pearl-chain.stories.ts
@@ -17,12 +17,6 @@ import {
} from './pearl-chain.sample-data.js';
import readme from './readme.md?raw';
-const disableAnimation: InputType = {
- control: {
- type: 'boolean',
- },
-};
-
const now: InputType = {
control: {
type: 'date',
@@ -44,13 +38,11 @@ const marker: InputType = {
};
const defaultArgTypes: ArgTypes = {
- 'disable-animation': disableAnimation,
marker: marker,
now,
};
const defaultArgs: Args = {
- 'disable-animation': false,
marker: marker.options![0],
now: new Date('2024-12-05T12:11:00').valueOf(),
};
@@ -157,7 +149,7 @@ export const CancelledManyStops: StoryObj = {
argTypes: defaultArgTypes,
};
-export const withPosition: StoryObj = {
+export const WithPosition: StoryObj = {
render: TemplateWithPosition,
argTypes: defaultArgTypes,
args: {
@@ -217,17 +209,6 @@ export const Mixed: StoryObj = {
},
};
-export const MixedWithTime: StoryObj = {
- render: TemplateAlteration,
- argTypes: { ...defaultArgTypes, serviceAlteration },
- args: {
- ...defaultArgs,
- serviceAlteration: serviceAlteration.options![2],
- departure: '2024-12-18T12:13:00',
- arrival: '2024-11-30T12:13:00',
- },
-};
-
const meta: Meta = {
decorators: [(story) => html`${story()}
`],
parameters: {
diff --git a/src/elements/pearl-chain/pearl-chain/pearl-chain.ts b/src/elements/pearl-chain/pearl-chain/pearl-chain.ts
index 6ac906e7996..932acf18662 100644
--- a/src/elements/pearl-chain/pearl-chain/pearl-chain.ts
+++ b/src/elements/pearl-chain/pearl-chain/pearl-chain.ts
@@ -1,21 +1,16 @@
-import { addMinutes, differenceInMinutes, format, isAfter, isBefore } from 'date-fns';
-import type { CSSResultGroup, TemplateResult } from 'lit';
-import { html, LitElement, nothing } from 'lit';
+import { addMinutes, differenceInMinutes, isAfter, isBefore } from 'date-fns';
+import type { CSSResultGroup, PropertyValues, TemplateResult } from 'lit';
+import { html, LitElement } from 'lit';
import { customElement, property } from 'lit/decorators.js';
-import { classMap } from 'lit/directives/class-map.js';
-import { SbbLanguageController } from '../../core/controllers.js';
-import { defaultDateAdapter } from '../../core/datetime.js';
-import { i18nArrival, i18nDeparture } from '../../core/i18n.js';
+import { type DateAdapter, defaultDateAdapter } from '../../core/datetime.js';
import type { SbbDateLike } from '../../core/interfaces/types.js';
-import '../../screen-reader-only.js';
import '../pearl-chain-leg.js';
import type { SbbPearlChainLegElement } from '../pearl-chain-leg.js';
import style from './pearl-chain.scss?lit&inline';
type Status = 'progress' | 'future' | 'past';
-type Marker = 'static' | 'pulsing';
/**
* It visually displays journey information.
@@ -27,103 +22,49 @@ class SbbPearlChainElement extends LitElement {
/** Whether the marker should be pulsing or static. */
@property()
- public accessor marker: Marker = 'static';
-
- /** Prop to render the departure time - will be formatted as "H:mm" */
- @property()
- public set departure(value: SbbDateLike | null) {
- this._departure = value;
- }
- public get departure(): SbbDateLike | null {
- return this._departure;
- }
- private _departure: SbbDateLike | null = null;
-
- /** Prop to render the arrival time - will be formatted as "H:mm" */
- @property()
- public set arrival(value: SbbDateLike | null) {
- this._arrival = value;
- }
- public get arrival(): SbbDateLike | null {
- return this._arrival;
- }
- private _arrival: SbbDateLike | null = null;
+ public accessor marker: 'static' | 'pulsing' = 'static';
/** A configured date which acts as the current date instead of the real current date. Recommended for testing purposes. */
@property()
- public set now(value: SbbDateLike | undefined) {
- this._now = defaultDateAdapter.getValidDateOrNull(defaultDateAdapter.deserialize(value));
+ public set now(value: Date) {
+ this._now =
+ this._dateAdapter.getValidDateOrNull(this._dateAdapter.deserialize(value)) ?? new Date();
}
- public get now(): SbbDateLike | null {
+
+ public get now(): Date {
return this._now;
}
- private _now: Date | null = null;
- private _language = new SbbLanguageController(this);
+ private _now: Date = new Date();
+
+ private _dateAdapter: DateAdapter = defaultDateAdapter;
private _legs(): SbbPearlChainLegElement[] {
return Array.from(this.querySelectorAll?.('sbb-pearl-chain-leg') ?? []);
}
- private _removeTimezone(time: SbbDateLike | null): Date | undefined {
- const parsedDate = defaultDateAdapter.deserialize(time);
-
- if (!parsedDate || !defaultDateAdapter.isValid(parsedDate)) {
- return undefined;
- }
-
- const isoTime = parsedDate!.toISOString();
-
- if (isoTime.includes('Z')) {
- return new Date(isoTime.replace('Z', ''));
- }
-
- if (isoTime.includes('T')) {
- const dateTime = isoTime.split('T');
-
- if (dateTime[1] && (dateTime[1].includes('+') || dateTime[1].includes('-'))) {
- return new Date(`${dateTime[0]}T${dateTime[1].split(/[+-]/)[0]}`);
- }
- }
- return new Date(isoTime);
- }
-
- private _getAllDuration(legs: SbbPearlChainLegElement[]): number {
+ private _totalDuration(legs: SbbPearlChainLegElement[]): number {
return legs?.reduce((sum: number, leg) => {
- const arrivalNoTz = this._removeTimezone(leg.arrival);
- const departureNoTz = this._removeTimezone(leg.departure);
+ const arrivalNoTz = this._dateAdapter.deserialize(leg.arrival);
+ const departureNoTz = this._dateAdapter.deserialize(leg.departure) as Date;
if (arrivalNoTz && departureNoTz) {
- return (
- sum +
- differenceInMinutes(
- this._removeTimezone(leg.arrival)!,
- this._removeTimezone(leg.departure)!,
- )
- );
+ return sum + differenceInMinutes(arrivalNoTz, departureNoTz);
}
return sum;
}, 0);
}
- private _isAllCancelled(legs: SbbPearlChainLegElement[]): boolean {
- return legs?.every((leg) => leg?.disruption);
- }
-
- private _getRelativeDuration(
- legs: SbbPearlChainLegElement[],
- leg: SbbPearlChainLegElement,
- ): number {
- const arrivalNoTz = this._removeTimezone(leg.arrival);
- const departureNoTz = this._removeTimezone(leg.departure);
+ private _getRelativeDuration(totalDuration: number, leg: SbbPearlChainLegElement): number {
+ const arrivalNoTz = this._dateAdapter.deserialize(leg.arrival);
+ const departureNoTz = this._dateAdapter.deserialize(leg.departure);
if (arrivalNoTz && departureNoTz) {
const duration = differenceInMinutes(arrivalNoTz, departureNoTz);
- const allDurations = this._getAllDuration(legs);
- if (allDurations === 0) {
+ if (totalDuration === 0) {
return 100;
}
- return (duration / allDurations) * 100;
+ return (duration / totalDuration) * 100;
}
return 0;
}
@@ -139,13 +80,14 @@ class SbbPearlChainElement extends LitElement {
return total && (progress / total) * 100;
}
- private _addMinutes(d: SbbDateLike, amount: number): Date {
- return addMinutes(defaultDateAdapter.deserialize(d)!, amount);
+ private _addMinutes(d: SbbDateLike | null, amount: number): Date {
+ const date: Date | null = this._dateAdapter.deserialize(d);
+ return date ? addMinutes(date, amount) : this._dateAdapter.invalid();
}
private _getLegStatus(now: Date, leg: SbbPearlChainLegElement): Status {
- const start = this._addMinutes(leg.departure!, leg.departureDelay);
- const end = this._addMinutes(leg.arrival!, leg.arrivalDelay);
+ const start = this._addMinutes(leg.departure, leg.departureDelay);
+ const end = this._addMinutes(leg.arrival, leg.arrivalDelay);
return this._getStatus(now, start, end);
}
@@ -158,120 +100,83 @@ class SbbPearlChainElement extends LitElement {
return 'future';
}
- private _renderContent(content: TemplateResult): TemplateResult {
- return html`
-
- ${this.departure && this.arrival
- ? html``
- : nothing}
- ${content}
- ${this.arrival && this.departure
- ? html``
- : nothing}
-
- `;
- }
-
private _renderPosition(now: Date, progressLeg: SbbPearlChainLegElement): void {
const currentPosition = this._getProgress(
now,
- this._addMinutes(progressLeg.departure!, progressLeg.departureDelay),
- this._addMinutes(progressLeg.arrival!, progressLeg.arrivalDelay),
+ this._addMinutes(progressLeg.departure, progressLeg.departureDelay),
+ this._addMinutes(progressLeg.arrival, progressLeg.arrivalDelay),
);
if (currentPosition < 0 && currentPosition > 100) {
return;
}
- progressLeg?.style.setProperty('--sbb-pearl-chain-status-position', `${currentPosition}%`);
- if (this.marker === 'pulsing') {
- progressLeg?.style.setProperty(
- '--sbb-pearl-chain-leg-animation',
- 'pearl-chain-bullet-position-pulse',
- );
- }
- if (currentPosition >= 50) {
- progressLeg?.style.setProperty('transform', `translateX(-100%)`);
- }
+ progressLeg?.style.setProperty('--sbb-pearl-chain-status-position', `${currentPosition / 100}`);
}
- protected override render(): TemplateResult {
- const now = (this.now as Date) ?? new Date();
+ private _getBullet(index: number): Element {
+ const a = Array.from(this.shadowRoot!.querySelectorAll('.sbb-pearl-chain__bullet'));
+ return a[index];
+ }
- const rideLegs: SbbPearlChainLegElement[] = this._legs();
+ private _getFirstBullet(): Element {
+ return this._getBullet(0);
+ }
- if (!rideLegs.length) {
- return html``;
- }
+ private _getLastBullet(): Element {
+ return this._getBullet(1);
+ }
- const statusDeparture = this._getLegStatus(now, rideLegs[0]);
+ protected override updated(changedProperties: PropertyValues): void {
+ super.updated(changedProperties);
- const statusArrival = this._getLegStatus(now, rideLegs[rideLegs.length - 1]);
+ this._setUpComponent();
+ }
+
+ private _configureBullet(bullet: Element, leg: SbbPearlChainLegElement, first: boolean): void {
+ const status = this._getLegStatus(this.now, leg);
+
+ bullet.toggleAttribute('data-disrupted', leg.disruption);
+ bullet.toggleAttribute('data-skipped', first ? leg.departureSkipped : leg.arrivalSkipped);
+ bullet.toggleAttribute('data-past', status === 'past' || (status === 'progress' && first));
+ }
+
+ private _setUpComponent(): void {
+ const legs: SbbPearlChainLegElement[] = this._legs();
- rideLegs[0]?.toggleAttribute('data-first-leg', true);
- rideLegs[rideLegs.length - 1].toggleAttribute('data-last-leg', true);
+ this._configureBullet(this._getFirstBullet(), legs[0], true);
+ this._configureBullet(this._getLastBullet(), legs[legs.length - 1], false);
- rideLegs.map((leg, index) => {
- const status = this._getLegStatus(now, leg);
+ legs.map((leg, index) => {
+ const status = this._getLegStatus(this.now, leg);
leg.style.setProperty(
'--sbb-pearl-chain-leg-weight',
- `${this._getRelativeDuration(rideLegs, leg) / 100}`,
+ `${this._getRelativeDuration(this._totalDuration(legs), leg) / 100}`,
);
leg.past = status === 'past';
leg.toggleAttribute('data-progress', status === 'progress');
if (status === 'progress') {
- this._renderPosition(now, leg);
+ this._renderPosition(this.now, leg);
}
- //If previous leg has arrival-skipped an attribute is set to style the stop
- if (index > 0 && rideLegs[index - 1]) {
- leg.toggleAttribute('data-skip-departure', !!rideLegs[index - 1].arrivalSkipped);
+ // If previous leg has arrival-skipped an attribute is set to style the stop
+ if (index > 0 && legs[index - 1]) {
+ leg.toggleAttribute('data-skip-departure', legs[index - 1].arrivalSkipped);
}
});
+ }
- if (this._isAllCancelled(rideLegs)) {
- return this._renderContent(html`
+ protected override render(): TemplateResult {
+ return html`
+
-
-
-
+
+
+
- `);
- }
-
- return this._renderContent(html`
-
-
-
-
- `);
+ `;
}
}
diff --git a/src/elements/pearl-chain/pearl-chain/pearl-chain.visual.spec.ts b/src/elements/pearl-chain/pearl-chain/pearl-chain.visual.spec.ts
index f74ffc153c7..e9c2ed0540f 100644
--- a/src/elements/pearl-chain/pearl-chain/pearl-chain.visual.spec.ts
+++ b/src/elements/pearl-chain/pearl-chain/pearl-chain.visual.spec.ts
@@ -95,8 +95,8 @@ describe(`sbb-pearl-chain`, () => {
now=${(c.now ?? new Date('2024-12-01T12:11:00').valueOf()) / 1000}
marker="static"
>
- ${c.legs.map((l) => l)}
+ ${c.legs}
+
`);
}),
);
diff --git a/src/storybook/pages/home/home-logged-in.ts b/src/storybook/pages/home/home-logged-in.ts
index 498f8b8ef2c..227e0f3dd6e 100644
--- a/src/storybook/pages/home/home-logged-in.ts
+++ b/src/storybook/pages/home/home-logged-in.ts
@@ -4,9 +4,9 @@ import { html } from 'lit';
import type { SbbDialogElement } from '../../../elements/dialog.js';
import {
- futureLeg,
- pastLeg,
-} from '../../../elements-experimental/pearl-chain-legacy/pearl-chain-legacy.sample-data.js';
+ futureLegTemplate,
+ pastLegTemplate,
+} from '../../../elements/pearl-chain/pearl-chain/pearl-chain.sample-data.js';
import {
bikeProduct,
@@ -20,7 +20,7 @@ import {
} from './home.common.js';
import '../../../elements/dialog.js';
import '../../../elements/journey-header.js';
-import '../../../elements-experimental/pearl-chain-legacy.js';
+import '../../../elements/pearl-chain.js';
import './home.scss';
export const homeLoggedInTemplate = (args: Args): TemplateResult => html`
@@ -108,10 +108,9 @@ export const homeLoggedInTemplate = (args: Args): TemplateResult => html`
2nd class, valid until 30.11.2022
-
+
+ ${pastLegTemplate} ${futureLegTemplate}
Ticket
@@ -155,10 +154,9 @@ export const homeLoggedInTemplate = (args: Args): TemplateResult => html`
Saturday, 21.02.2021, 1 h 26 min
-
+
+ ${pastLegTemplate} ${futureLegTemplate}
+
Details