From a2ab0293d9379e6552022c56519bff7cdf6243bb Mon Sep 17 00:00:00 2001 From: Claas Date: Thu, 27 Jun 2024 18:18:32 +0200 Subject: [PATCH] Rename files to have new old one as current one --- src/routes/journey.tsx | 745 +++++++++++++++++++++------------------- src/routes/journey2.tsx | 745 +++++++++++++++++++--------------------- 2 files changed, 745 insertions(+), 745 deletions(-) diff --git a/src/routes/journey.tsx b/src/routes/journey.tsx index 94a0ae5..288dcc3 100644 --- a/src/routes/journey.tsx +++ b/src/routes/journey.tsx @@ -1,118 +1,44 @@ -import { - Accessor, - For, - Match, - Setter, - Show, - Switch, - VoidProps, - createEffect, - createSignal, - type JSX, -} from "solid-js"; -import { - Changes, - Connection, - Transport, - Walk, - connections, - getTime, -} from "~/data"; -import { - CONNECTIONS_FROM_HAUPTBAHNHOF, - CONNECTIONS_TO_HAUPTBAHNHOF, -} from "~/data2"; +import { For, Match, Show, Switch, createSignal, type JSX } from "solid-js"; -function TransportConnectionInterim({ connection }: { connection: Transport }) { - return ( - <> -
- -
-
-
-
- -
-
-
-

- to {connection.headsign} -

- -
-
-
-
-
- - - - - - - - - - - - - - - {connection.line.type} {connection.line.number} - -
-
- - ); -} function TransportConnection({ connection, }: { - connection: Transport & Changes; + connection: Transport; }): JSX.Element { return ( <> +

+ {/* Setting w-[3rem] and pl-8 to align with grid. TODO find better solution */} + + + + + {connection.start} + + + + Pl. {connection.platform} + +

@@ -141,10 +67,10 @@ function TransportConnection({

to {connection.headsign}

@@ -195,34 +121,6 @@ function TransportConnection({
- {/*

- - - - - {connection.start} - - - - Pl. {connection.platform} - -

*/} - {/* Hide destination if it is the last connection because destination will already be shown at the top */} - -

- {connection.destination} -

-
); } @@ -233,7 +131,7 @@ function WalkConnection({ connection }: { connection: Walk }): JSX.Element {

{/* Setting pl-20 to align with grid. TODO find better solution */} - {connection.destination} + {connection.start}

{/* TODO make this aligned through grid to area below */} @@ -279,7 +177,6 @@ function Connection3(connection: Connection): JSX.Element { - {/* TODO remove grid-flow-col */}
{/* flex-none: diasable elements shrinking to fit the flex container */}
- {/* TODO find better solution than pl-[5rem] to align with grid */} -

- Beuel Konrad-Adenauer-Platz, Bonn -

{/* overscroll-x-contain: we need to be able to scroll on the y-axis */} - {/* TODO remove grid-flow-col */}
- {Connection3} + {Connection3}
@@ -414,235 +303,367 @@ function Connection2(properties: Connection2Properties): JSX.Element { ); } -function useObserver(callback: IntersectionObserverCallback) { - let observer: IntersectionObserver | undefined; - - function setScroller(element: Element) { - observer = new IntersectionObserver(callback, { - root: element, - // This ensures that the element is only triggered once it is past the snap point - threshold: 0.5, - }); - } - - function observe(element: Element) { - observer?.observe(element); - } - - //TODO on cleanup - - return { - setScroller, - observe, - }; -} - -// Temporary to give rows a different color -let debugOnlyRowIndex = 0; - -type RowProperties = { - scrollLeft?: Accessor; - setScrollLeft?: Setter; -}; - -function Row({ scrollLeft, setScrollLeft }: VoidProps) { - const debugIndex = debugOnlyRowIndex; - debugOnlyRowIndex++; - const { setScroller, observe } = useObserver(() => { - throw new Error("todo"); - }); - - const [row, setRow] = createSignal(); - - // Set scroller to row when row is set - createEffect(() => { - //TODO cleanup - const value = row(); - if (value === undefined) return; - setScroller(value); - }); - - if (scrollLeft !== undefined) { - // Update row scrollLeft when scrollLeft changes - createEffect(() => { - const value = scrollLeft(); - const scroller = row(); - if (value === undefined || scroller === undefined) return; - - console.debug("Before", scroller.scrollLeft, value); - scroller.scrollLeft = value; - }); - } - - function handleScroll(event: Event) { - if (!(event.target instanceof HTMLDivElement)) - throw new Error("Expected div"); - - if (setScrollLeft === undefined) return; - - // console.debug("Scroll", event.target.scrollLeft); - setScrollLeft(event.target.scrollLeft); - } - +export default function Journeys() { return ( -
- - {(_, index) => ( -
- Connection {index()} -
- )} -
-
+ <> + + ); } -export default function Journeys() { - const [isWalkSnapped, setIsWalkSnapped] = createSignal(false); - - // To not trigger animation on initial render - let dirtyFlag = false; - const wasWalkSnapped = () => { - if (dirtyFlag) { - dirtyFlag = false; - return true; - } - - return false; +type Line2 = { + type: "STR" | "Bus" | "RE" | "RB"; + color: string; + number: string; +}; +type Changes = { + /** Optional because this could be the last connection and destination is set. */ + changes?: Connection2[]; +}; +type Transport = { + type: "transport"; + /** Start and at the same time destination of the parent connection before this if this is not the first connection */ + start: string; + line: Line2; + headsign: string; + /** Only set if this is the last connection/leaf in the connection tree. If this is the last connection, then changes should not exist */ + destination?: string; + time: { + /** Time to change from the connection before this (parent connection). Optional because this could be the first connection */ + change?: string; + arrive: string; + depart: string; + duration: string; + delay?: { + arrive: string; + depart: string; + }; }; - createEffect(() => { - if (isWalkSnapped()) { - dirtyFlag = true; - } - }); - - function observeCallback([first]: IntersectionObserverEntry[]) { - //TODO avoid initial call with all elements - const target = first.target; + platform?: string; +}; - const isWalkFocused = - target instanceof HTMLElement && - first.isIntersecting && - target.dataset.type === "walk"; +type Walk = { + type: "walk"; + timeAvailable: string; + distance: string; + time: string; + start: string; - console.debug("Intersection", isWalkFocused); - setIsWalkSnapped(isWalkFocused); - } - const { setScroller, observe } = useObserver(observeCallback); + /** Optional because this could be the last connection and destination is set. */ + changes?: Connection2[]; +}; +type Connection2 = (Transport | Walk) & Changes; + +const WALK_BONN_HBF: Walk = { + type: "walk", + timeAvailable: "8min", + distance: "84m", + time: "6min", + start: "Hauptbahnhof, Bonn", +}; - const [row1, setRow1] = createSignal(); +const WALK_BARBAROSSAPLATZ: Walk = { + type: "walk", + timeAvailable: "9min", + distance: "334m", + time: "8min", + start: "Hauptbahnhof, Bonn", +}; - const [isScrolling, setIsScrolling] = createSignal(false); - function handleScroll({ target }: { target: Element }) { - // This should not trigger an update even if we set it to true rapidly again and again - setIsScrolling(true); +const RE_WESEL_1628: Connection2 = { + type: "transport", + start: "Bonn Hbf", + line: { + type: "RE", + color: "bg-[#7C818B]", + number: "5 (28524)", + }, + headsign: "Wesel", + time: { + arrive: "16:21", + depart: "16:04", + duration: "17min", + delay: { + arrive: "16:45", + depart: "16:28", + }, + }, + platform: "1", + changes: [ + { + ...WALK_BARBAROSSAPLATZ, + timeAvailable: "9min", + changes: [ + { + type: "transport", + start: "Barbarossaplatz, Köln", + line: { + type: "STR", + color: "bg-[#9f3d53]", + number: "18", + }, + headsign: "Riehl Slabystr., Köln", + destination: "Neumarkt, Köln", + time: { + arrive: "16:57", + depart: "16:54", + duration: "3min", + delay: { + arrive: "16:57", + depart: "16:54", + }, + }, + }, + ], + }, + ], +}; - const otherRow = row1(); - if (otherRow === undefined) return; +const STR_NIEHL_1622: Connection2 = { + type: "transport", + start: "Hauptbahnhof, Bonn", + // line: "STR 16", + line: { + type: "STR", + color: "bg-[#9f3d53]", + number: "16", + }, + headsign: "Niehl Sebastianstr., Köln", + destination: "Neumarkt, Köln", + time: { + arrive: "17:15", + depart: "16:22", + duration: "53min", + delay: { + arrive: "16:22", + depart: "17:15", + }, + }, +}; - otherRow.scrollLeft = target.scrollLeft; - } +const RB_MESSE_1633: Connection2 = { + type: "transport", + start: "Bonn Hbf", + line: { + type: "RB", + color: "bg-[#7C818B]", + number: "26 (25430)", + }, + headsign: "Köln Messe/Deutz", + destination: "Köln Süd", + time: { + arrive: "16:53", + depart: "16:33", + duration: "20min", + delay: { + arrive: "16:54", + depart: "16:34", + }, + }, + changes: [ + { + ...WALK_BARBAROSSAPLATZ, + timeAvailable: "8min", + changes: [ + { + type: "transport", + start: "Barbarossaplatz, Köln", + line: { + type: "STR", + color: "bg-[#9f3d53]", + number: "16", + }, + headsign: "Niehl Sebastianstr., Köln", + destination: "Neumarkt, Köln", + time: { + arrive: "17:05", + depart: "17:02", + duration: "3min", + delay: { + arrive: "17:05", + depart: "17:02", + }, + }, + }, + ], + }, + ], +}; - return ( -
-

- Beuel Konrad-Adenauer-Platz, Bonn -

-
setIsScrolling(false)} - > - {/* - {(_, index) => ( -
- Content {index()} -
- )} -
*/} - - {(connection) => ( -
- - - - - - - - -
- )} -
-
-

- Hauptbahnhof, Bonn -

- {/* Can't detect intersection/snap with CSS. Therefore we need to use JS */} -
{ - setRow1(element); - setScroller(element); - }} - class="grid snap-mandatory grid-flow-col content-end gap-4 overflow-y-scroll" - classList={{ - "snap-x": !isScrolling(), - "animate-grow-walk": !isWalkSnapped() && wasWalkSnapped(), - "h-24 animate-shrink-walk": isWalkSnapped(), - }} - > - {/* - {(_, index) => ( -
- Content {index()} -
- )} -
*/} - - {(connection) => ( -
- - - - - - - - -
- )} -
-
-
- ); +function withChange( + connection: Transport, + change: string | undefined, +): Connection2 { + return { + ...connection, + time: { + ...connection.time, + change, + }, + }; } + +const connections2: Connection2[] = [ + { + type: "transport", + start: "Beuel Konrad-Adenauer-Platz, Bonn", + // line: "STR 62", + line: { + type: "STR", + color: "bg-[#9f3d53]", + number: "62", + }, + headsign: "Dottendorf Quirinusplatz, Bonn", + time: { + arrive: "16:07", + depart: "15:58", + duration: "9min", + }, + changes: [ + { + type: "transport", + start: "Hauptbahnhof, Bonn", + // line: "STR 16", + line: { + type: "STR", + color: "bg-[#9f3d53]", + number: "16", + }, + headsign: "Niehl Sebastianstr., Köln", + destination: "Neumarkt, Köln", + time: { + change: "5min", + arrive: "17:05", + depart: "16:12", + duration: "53min", + delay: { + arrive: "16:12", + depart: "17:05", + }, + }, + }, + withChange(STR_NIEHL_1622, "15min"), + { + ...WALK_BONN_HBF, + timeAvailable: "21min", + changes: [withChange(RE_WESEL_1628, undefined)], + }, + ], + }, + { + type: "transport", + start: "Beuel Konrad-Adenauer-Platz, Bonn", + // line: "STR 62", + line: { + type: "STR", + color: "bg-[#9f3d53]", + number: "62", + }, + headsign: "Dottendorf Quirinusplatz, Bonn", + time: { + arrive: "16:17", + depart: "16:08", + duration: "9min", + delay: { + arrive: "16:08", + depart: "16:17", + }, + }, + changes: [ + withChange(STR_NIEHL_1622, "5min"), + withChange(RE_WESEL_1628, "9min"), + ], + }, + { + type: "transport", + start: "Beuel Konrad-Adenauer-Platz, Bonn", + line: { + type: "Bus", + color: "bg-[#76408C]", + number: "117", + }, + headsign: "Hauptbahnhof, Bonn", + time: { + arrive: "16:15", + depart: "16:05", + duration: "10min", + }, + changes: [ + withChange(STR_NIEHL_1622, "4min"), + withChange(RE_WESEL_1628, "13min"), + ], + }, + + // Bus -> Walk -> RE + { + type: "transport", + start: "Beuel Konrad-Adenauer-Platz, Bonn", + line: { + type: "Bus", + color: "bg-[#76408C]", + number: "603", + }, + headsign: "Hauptbahnhof, Bonn", + time: { + arrive: "16:20", + depart: "16:09", + duration: "10min", + }, + changes: [ + { + ...WALK_BONN_HBF, + timeAvailable: "8min", + changes: [RE_WESEL_1628], + }, + ], + }, + { + type: "transport", + start: "Beuel Konrad-Adenauer-Platz, Bonn", + line: { + type: "STR", + color: "bg-[#9f3d53]", + number: "62", + }, + headsign: "Dottendorf Quirinusplatz, Bonn", + time: { + arrive: "16:27", + depart: "16:18", + duration: "9min", + }, + changes: [ + { + ...WALK_BONN_HBF, + timeAvailable: "7min", + changes: [RB_MESSE_1633], + }, + ], + }, + // 640 -> RB 26 + { + type: "transport", + start: "Beuel Konrad-Adenauer-Platz, Bonn", + line: { + type: "Bus", + color: "bg-[#76408C]", + number: "640", + }, + headsign: "Hauptbahnhof, Bonn", + time: { + arrive: "16:23", + depart: "16:13", + duration: "10min", + delay: { + arrive: "16:28", + depart: "16:18", + }, + }, + changes: [ + { + ...WALK_BONN_HBF, + timeAvailable: "6min", + changes: [RB_MESSE_1633], + }, + ], + }, +]; diff --git a/src/routes/journey2.tsx b/src/routes/journey2.tsx index 288dcc3..94a0ae5 100644 --- a/src/routes/journey2.tsx +++ b/src/routes/journey2.tsx @@ -1,44 +1,118 @@ -import { For, Match, Show, Switch, createSignal, type JSX } from "solid-js"; +import { + Accessor, + For, + Match, + Setter, + Show, + Switch, + VoidProps, + createEffect, + createSignal, + type JSX, +} from "solid-js"; +import { + Changes, + Connection, + Transport, + Walk, + connections, + getTime, +} from "~/data"; +import { + CONNECTIONS_FROM_HAUPTBAHNHOF, + CONNECTIONS_TO_HAUPTBAHNHOF, +} from "~/data2"; +function TransportConnectionInterim({ connection }: { connection: Transport }) { + return ( + <> +
+ +
+
+
+
+ +
+
+
+

+ to {connection.headsign} +

+ +
+
+
+
+
+ + + + + + + + + + + + + + + {connection.line.type} {connection.line.number} + +
+
+ + ); +} function TransportConnection({ connection, }: { - connection: Transport; + connection: Transport & Changes; }): JSX.Element { return ( <> -

- {/* Setting w-[3rem] and pl-8 to align with grid. TODO find better solution */} - - - - - {connection.start} - - - - Pl. {connection.platform} - -

@@ -67,10 +141,10 @@ function TransportConnection({

to {connection.headsign}

@@ -121,6 +195,34 @@ function TransportConnection({
+ {/*

+ + + + + {connection.start} + + + + Pl. {connection.platform} + +

*/} + {/* Hide destination if it is the last connection because destination will already be shown at the top */} + +

+ {connection.destination} +

+
); } @@ -131,7 +233,7 @@ function WalkConnection({ connection }: { connection: Walk }): JSX.Element {

{/* Setting pl-20 to align with grid. TODO find better solution */} - {connection.start} + {connection.destination}

{/* TODO make this aligned through grid to area below */} @@ -177,6 +279,7 @@ function Connection3(connection: Connection2): JSX.Element { + {/* TODO remove grid-flow-col */}
{/* flex-none: diasable elements shrinking to fit the flex container */}
+ {/* TODO find better solution than pl-[5rem] to align with grid */} +

+ Beuel Konrad-Adenauer-Platz, Bonn +

{/* overscroll-x-contain: we need to be able to scroll on the y-axis */} + {/* TODO remove grid-flow-col */}
- {Connection3} + {Connection3}
@@ -303,367 +414,235 @@ function Connection2(properties: Connection2Properties): JSX.Element { ); } -export default function Journeys() { +function useObserver(callback: IntersectionObserverCallback) { + let observer: IntersectionObserver | undefined; + + function setScroller(element: Element) { + observer = new IntersectionObserver(callback, { + root: element, + // This ensures that the element is only triggered once it is past the snap point + threshold: 0.5, + }); + } + + function observe(element: Element) { + observer?.observe(element); + } + + //TODO on cleanup + + return { + setScroller, + observe, + }; +} + +// Temporary to give rows a different color +let debugOnlyRowIndex = 0; + +type RowProperties = { + scrollLeft?: Accessor; + setScrollLeft?: Setter; +}; + +function Row({ scrollLeft, setScrollLeft }: VoidProps) { + const debugIndex = debugOnlyRowIndex; + debugOnlyRowIndex++; + const { setScroller, observe } = useObserver(() => { + throw new Error("todo"); + }); + + const [row, setRow] = createSignal(); + + // Set scroller to row when row is set + createEffect(() => { + //TODO cleanup + const value = row(); + if (value === undefined) return; + setScroller(value); + }); + + if (scrollLeft !== undefined) { + // Update row scrollLeft when scrollLeft changes + createEffect(() => { + const value = scrollLeft(); + const scroller = row(); + if (value === undefined || scroller === undefined) return; + + console.debug("Before", scroller.scrollLeft, value); + scroller.scrollLeft = value; + }); + } + + function handleScroll(event: Event) { + if (!(event.target instanceof HTMLDivElement)) + throw new Error("Expected div"); + + if (setScrollLeft === undefined) return; + + // console.debug("Scroll", event.target.scrollLeft); + setScrollLeft(event.target.scrollLeft); + } + return ( - <> - - +
+ + {(_, index) => ( +
+ Connection {index()} +
+ )} +
+
); } -type Line2 = { - type: "STR" | "Bus" | "RE" | "RB"; - color: string; - number: string; -}; -type Changes = { - /** Optional because this could be the last connection and destination is set. */ - changes?: Connection2[]; -}; -type Transport = { - type: "transport"; - /** Start and at the same time destination of the parent connection before this if this is not the first connection */ - start: string; - line: Line2; - headsign: string; - /** Only set if this is the last connection/leaf in the connection tree. If this is the last connection, then changes should not exist */ - destination?: string; - time: { - /** Time to change from the connection before this (parent connection). Optional because this could be the first connection */ - change?: string; - arrive: string; - depart: string; - duration: string; - delay?: { - arrive: string; - depart: string; - }; +export default function Journeys() { + const [isWalkSnapped, setIsWalkSnapped] = createSignal(false); + + // To not trigger animation on initial render + let dirtyFlag = false; + const wasWalkSnapped = () => { + if (dirtyFlag) { + dirtyFlag = false; + return true; + } + + return false; }; - platform?: string; -}; + createEffect(() => { + if (isWalkSnapped()) { + dirtyFlag = true; + } + }); -type Walk = { - type: "walk"; - timeAvailable: string; - distance: string; - time: string; - start: string; + function observeCallback([first]: IntersectionObserverEntry[]) { + //TODO avoid initial call with all elements + const target = first.target; - /** Optional because this could be the last connection and destination is set. */ - changes?: Connection2[]; -}; -type Connection2 = (Transport | Walk) & Changes; - -const WALK_BONN_HBF: Walk = { - type: "walk", - timeAvailable: "8min", - distance: "84m", - time: "6min", - start: "Hauptbahnhof, Bonn", -}; + const isWalkFocused = + target instanceof HTMLElement && + first.isIntersecting && + target.dataset.type === "walk"; -const WALK_BARBAROSSAPLATZ: Walk = { - type: "walk", - timeAvailable: "9min", - distance: "334m", - time: "8min", - start: "Hauptbahnhof, Bonn", -}; + console.debug("Intersection", isWalkFocused); + setIsWalkSnapped(isWalkFocused); + } + const { setScroller, observe } = useObserver(observeCallback); -const RE_WESEL_1628: Connection2 = { - type: "transport", - start: "Bonn Hbf", - line: { - type: "RE", - color: "bg-[#7C818B]", - number: "5 (28524)", - }, - headsign: "Wesel", - time: { - arrive: "16:21", - depart: "16:04", - duration: "17min", - delay: { - arrive: "16:45", - depart: "16:28", - }, - }, - platform: "1", - changes: [ - { - ...WALK_BARBAROSSAPLATZ, - timeAvailable: "9min", - changes: [ - { - type: "transport", - start: "Barbarossaplatz, Köln", - line: { - type: "STR", - color: "bg-[#9f3d53]", - number: "18", - }, - headsign: "Riehl Slabystr., Köln", - destination: "Neumarkt, Köln", - time: { - arrive: "16:57", - depart: "16:54", - duration: "3min", - delay: { - arrive: "16:57", - depart: "16:54", - }, - }, - }, - ], - }, - ], -}; + const [row1, setRow1] = createSignal(); -const STR_NIEHL_1622: Connection2 = { - type: "transport", - start: "Hauptbahnhof, Bonn", - // line: "STR 16", - line: { - type: "STR", - color: "bg-[#9f3d53]", - number: "16", - }, - headsign: "Niehl Sebastianstr., Köln", - destination: "Neumarkt, Köln", - time: { - arrive: "17:15", - depart: "16:22", - duration: "53min", - delay: { - arrive: "16:22", - depart: "17:15", - }, - }, -}; + const [isScrolling, setIsScrolling] = createSignal(false); + function handleScroll({ target }: { target: Element }) { + // This should not trigger an update even if we set it to true rapidly again and again + setIsScrolling(true); -const RB_MESSE_1633: Connection2 = { - type: "transport", - start: "Bonn Hbf", - line: { - type: "RB", - color: "bg-[#7C818B]", - number: "26 (25430)", - }, - headsign: "Köln Messe/Deutz", - destination: "Köln Süd", - time: { - arrive: "16:53", - depart: "16:33", - duration: "20min", - delay: { - arrive: "16:54", - depart: "16:34", - }, - }, - changes: [ - { - ...WALK_BARBAROSSAPLATZ, - timeAvailable: "8min", - changes: [ - { - type: "transport", - start: "Barbarossaplatz, Köln", - line: { - type: "STR", - color: "bg-[#9f3d53]", - number: "16", - }, - headsign: "Niehl Sebastianstr., Köln", - destination: "Neumarkt, Köln", - time: { - arrive: "17:05", - depart: "17:02", - duration: "3min", - delay: { - arrive: "17:05", - depart: "17:02", - }, - }, - }, - ], - }, - ], -}; + const otherRow = row1(); + if (otherRow === undefined) return; -function withChange( - connection: Transport, - change: string | undefined, -): Connection2 { - return { - ...connection, - time: { - ...connection.time, - change, - }, - }; -} + otherRow.scrollLeft = target.scrollLeft; + } -const connections2: Connection2[] = [ - { - type: "transport", - start: "Beuel Konrad-Adenauer-Platz, Bonn", - // line: "STR 62", - line: { - type: "STR", - color: "bg-[#9f3d53]", - number: "62", - }, - headsign: "Dottendorf Quirinusplatz, Bonn", - time: { - arrive: "16:07", - depart: "15:58", - duration: "9min", - }, - changes: [ - { - type: "transport", - start: "Hauptbahnhof, Bonn", - // line: "STR 16", - line: { - type: "STR", - color: "bg-[#9f3d53]", - number: "16", - }, - headsign: "Niehl Sebastianstr., Köln", - destination: "Neumarkt, Köln", - time: { - change: "5min", - arrive: "17:05", - depart: "16:12", - duration: "53min", - delay: { - arrive: "16:12", - depart: "17:05", - }, - }, - }, - withChange(STR_NIEHL_1622, "15min"), - { - ...WALK_BONN_HBF, - timeAvailable: "21min", - changes: [withChange(RE_WESEL_1628, undefined)], - }, - ], - }, - { - type: "transport", - start: "Beuel Konrad-Adenauer-Platz, Bonn", - // line: "STR 62", - line: { - type: "STR", - color: "bg-[#9f3d53]", - number: "62", - }, - headsign: "Dottendorf Quirinusplatz, Bonn", - time: { - arrive: "16:17", - depart: "16:08", - duration: "9min", - delay: { - arrive: "16:08", - depart: "16:17", - }, - }, - changes: [ - withChange(STR_NIEHL_1622, "5min"), - withChange(RE_WESEL_1628, "9min"), - ], - }, - { - type: "transport", - start: "Beuel Konrad-Adenauer-Platz, Bonn", - line: { - type: "Bus", - color: "bg-[#76408C]", - number: "117", - }, - headsign: "Hauptbahnhof, Bonn", - time: { - arrive: "16:15", - depart: "16:05", - duration: "10min", - }, - changes: [ - withChange(STR_NIEHL_1622, "4min"), - withChange(RE_WESEL_1628, "13min"), - ], - }, - - // Bus -> Walk -> RE - { - type: "transport", - start: "Beuel Konrad-Adenauer-Platz, Bonn", - line: { - type: "Bus", - color: "bg-[#76408C]", - number: "603", - }, - headsign: "Hauptbahnhof, Bonn", - time: { - arrive: "16:20", - depart: "16:09", - duration: "10min", - }, - changes: [ - { - ...WALK_BONN_HBF, - timeAvailable: "8min", - changes: [RE_WESEL_1628], - }, - ], - }, - { - type: "transport", - start: "Beuel Konrad-Adenauer-Platz, Bonn", - line: { - type: "STR", - color: "bg-[#9f3d53]", - number: "62", - }, - headsign: "Dottendorf Quirinusplatz, Bonn", - time: { - arrive: "16:27", - depart: "16:18", - duration: "9min", - }, - changes: [ - { - ...WALK_BONN_HBF, - timeAvailable: "7min", - changes: [RB_MESSE_1633], - }, - ], - }, - // 640 -> RB 26 - { - type: "transport", - start: "Beuel Konrad-Adenauer-Platz, Bonn", - line: { - type: "Bus", - color: "bg-[#76408C]", - number: "640", - }, - headsign: "Hauptbahnhof, Bonn", - time: { - arrive: "16:23", - depart: "16:13", - duration: "10min", - delay: { - arrive: "16:28", - depart: "16:18", - }, - }, - changes: [ - { - ...WALK_BONN_HBF, - timeAvailable: "6min", - changes: [RB_MESSE_1633], - }, - ], - }, -]; + return ( +
+

+ Beuel Konrad-Adenauer-Platz, Bonn +

+
setIsScrolling(false)} + > + {/* + {(_, index) => ( +
+ Content {index()} +
+ )} +
*/} + + {(connection) => ( +
+ + + + + + + + +
+ )} +
+
+

+ Hauptbahnhof, Bonn +

+ {/* Can't detect intersection/snap with CSS. Therefore we need to use JS */} +
{ + setRow1(element); + setScroller(element); + }} + class="grid snap-mandatory grid-flow-col content-end gap-4 overflow-y-scroll" + classList={{ + "snap-x": !isScrolling(), + "animate-grow-walk": !isWalkSnapped() && wasWalkSnapped(), + "h-24 animate-shrink-walk": isWalkSnapped(), + }} + > + {/* + {(_, index) => ( +
+ Content {index()} +
+ )} +
*/} + + {(connection) => ( +
+ + + + + + + + +
+ )} +
+
+
+ ); +} -- knotmirror 0.0.1