4 Commits

Author SHA1 Message Date
e98b24303c 🎨 Cleanup code formatting 2024-02-02 23:02:39 +01:00
f6bd241db3 Merge branch 'readme' into develop 2024-01-08 23:05:38 +01:00
3ff9a91bd0 Merge branch 'readme' into develop 2024-01-07 11:44:23 +01:00
3873fdb719 Merge branch 'readme' into develop 2024-01-07 11:30:03 +01:00
26 changed files with 1943 additions and 2010 deletions

View File

@@ -32,6 +32,7 @@
"matrix-widget-api": "^1.1.1",
"ol": "^7.3.0",
"solid-js": "^1.6.6",
"solid-transition-group": "^0.0.10"
"solid-transition-group": "^0.0.10",
"solidjs-lazily": "^0.1.2"
}
}

View File

@@ -1,15 +1,12 @@
import { Component, createSignal } from 'solid-js';
import { IVisibilityActionRequest, MatrixCapabilities, WidgetApi, WidgetApiToWidgetAction } from 'matrix-widget-api';
import { HopeProvider } from "@hope-ui/solid";
import { Component, createSignal, onCleanup, onMount } from 'solid-js';
// import { IVisibilityActionRequest, MatrixCapabilities, WidgetApi, WidgetApiToWidgetAction } from 'matrix-widget-api';
import { BusinessDataProvider } from './businessData';
import { AppContextProvider } from './appContext';
import { PassagesDisplay } from './passagesDisplay';
import { StopsSearchMenu } from './stopsSearchMenu/stopsSearchMenu';
import "./App.scss";
import { onCleanup, onMount } from 'solid-js';
function parseFragment() {
@@ -28,21 +25,21 @@ const App: Component = () => {
console.log("App: widgetId:" + widgetId);
console.log("App: userId:" + userId);
const api = new WidgetApi(widgetId != null ? widgetId : undefined);
api.requestCapability(MatrixCapabilities.AlwaysOnScreen);
api.start();
api.on("ready", function() {
console.log("App: widget API is READY !!!!");
});
// const api = new WidgetApi(widgetId != null ? widgetId : undefined);
// api.requestCapability(MatrixCapabilities.AlwaysOnScreen);
// api.start();
// api.on("ready", function() {
// console.log("App: widget API is READY !!!!");
// });
// Seems to don´t be used...
api.on(`action:${WidgetApiToWidgetAction.UpdateVisibility}`, (ev: CustomEvent<IVisibilityActionRequest>) => {
console.log("App: Visibility change");
ev.preventDefault(); // we're handling it, so stop the widget API from doing something.
console.log("App: ", ev.detail); // custom handling here
/* api.transport.reply(ev.detail, <IWidgetApiRequestEmptyData>{}); */
api.transport.reply(ev.detail, {});
});
// api.on(`action:${WidgetApiToWidgetAction.UpdateVisibility}`, (ev: CustomEvent<IVisibilityActionRequest>) => {
// console.log("App: Visibility change");
// ev.preventDefault(); // we're handling it, so stop the widget API from doing something.
// console.log("App: ", ev.detail); // custom handling here
// /* api.transport.reply(ev.detail, <IWidgetApiRequestEmptyData>{}); */
// api.transport.reply(ev.detail, {});
// });
createSignal({
height: window.innerHeight,
@@ -71,10 +68,8 @@ const App: Component = () => {
window.removeEventListener('resize', onResize);
})
return (
<BusinessDataProvider>
return <BusinessDataProvider>
<AppContextProvider>
<HopeProvider>
<div class="App">
<div class="panel">
<StopsSearchMenu />
@@ -83,10 +78,8 @@ const App: Component = () => {
<PassagesDisplay />
</div>
</div>
</HopeProvider>
</AppContextProvider>
</BusinessDataProvider>
);
</BusinessDataProvider>;
};
export default App;

View File

@@ -6,7 +6,7 @@ import { Stop } from './types';
export interface AppContextStore {
getDisplayedStops: () => Stop[];
setDisplayedStops: (stops: Stop[]) => void;
};
}
export const AppContextContext = createContext<AppContextStore>();
@@ -26,10 +26,7 @@ export function AppContextProvider(props: { children: JSX.Element }) {
const setDisplayedStops = (stops: Stop[]): void => {
console.log("setDisplayedStops=", stops);
// setStore((s: Store) => {
setStore('displayedStops', stops);
// return s;
// });
}
return (
@@ -39,5 +36,4 @@ export function AppContextProvider(props: { children: JSX.Element }) {
{props.children}
</AppContextContext.Provider>
);
};
}

View File

@@ -6,6 +6,7 @@ import { Line, Lines, Passage, Passages, Stop, StopShape, StopShapes, Stops } fr
export type StopDestinations = Record<string, string[]>;
export interface BusinessDataStore {
getLine: (lineId: string) => Promise<Line>;
getLinePassages: (lineId: string) => Record<string, Passage[]>;
@@ -23,7 +24,7 @@ export interface BusinessDataStore {
getStopDestinations: (stopId: number) => Promise<StopDestinations | undefined>;
getStopShape: (stopId: number) => Promise<StopShape | undefined>;
};
}
export const BusinessDataContext = createContext<BusinessDataStore>();
@@ -120,7 +121,7 @@ export function BusinessDataProvider(props: { children: JSX.Element }) {
for (const lineId of Object.keys(passages)) {
const newLinePassages = passages[lineId];
const linePassages = storePassages[lineId];
if (linePassages === undefined) {
if (linePassages === undefined || Object.keys(linePassages).length == 0) {
setStore('passages', lineId, newLinePassages);
}
else {
@@ -159,7 +160,7 @@ ${linePassagesDestination.length} here... refresh all them.`);
const clearPassages = (): void => {
setStore((s: Store): Store => {
for (const lineId of Object.keys(s.passages)) {
setStore('passages', lineId, undefined);
setStore('passages', lineId, {});
}
return s;
});
@@ -231,21 +232,9 @@ ${linePassagesDestination.length} here... refresh all them.`);
getLine, getLinePassages, getLineDestinations, getDestinationPassages, passages, getPassagesLineIds,
refreshPassages, addPassages, clearPassages,
getStop, getStopDestinations, getStopShape, searchStopByName
}}>
{props.children}
</BusinessDataContext.Provider>
);
}
export interface BusinessDataStore {
getLine: (lineId: string) => Promise<Line>;
getLinePassages: (lineId: string) => Record<string, Passage[]>;
passages: () => Passages;
refreshPassages: (stopId: number) => Promise<void>;
addPassages: (passages: Passages) => void;
clearPassages: () => void;
getStop: (stopId: number) => Stop | undefined;
searchStopByName: (name: string) => Promise<Stops>;
};

View File

@@ -4,10 +4,11 @@ import { VoidComponent } from "solid-js";
export const IconHamburgerMenu: VoidComponent<{}> = () => {
return (
<svg class="iconHamburgerMenu" viewBox="0 0 15 15">
<path d="M1.5 3C1.22386 3 1 3.22386 1 3.5C1 3.77614 1.22386 4 1.5 4H13.5C13.7761 4 14 3.77614 14 3.5C14 3.22386
13.7761 3 13.5 3H1.5ZM1 7.5C1 7.22386 1.22386 7 1.5 7H13.5C13.7761 7 14 7.22386 14 7.5C14 7.77614 13.7761 8 13.5
8H1.5C1.22386 8 1 7.77614 1 7.5ZM1 11.5C1 11.2239 1.22386 11 1.5 11H13.5C13.7761 11 14 11.2239 14 11.5C14 11.7761
13.7761 12 13.5 12H1.5C1.22386 12 1 11.7761 1 11.5Z"
<path
d="M1.5 3C1.22386 3 1 3.22386 1 3.5C1 3.77614 1.22386 4 1.5 4H13.5C13.7761 4 14 3.77614 14 3.5C14 3.22386
13.7761 3 13.5 3H1.5ZM1 7.5C1 7.22386 1.22386 7 1.5 7H13.5C13.7761 7 14 7.22386 14 7.5C14 7.77614 13.7761 8 13.5
8H1.5C1.22386 8 1 7.77614 1 7.5ZM1 11.5C1 11.2239 1.22386 11 1.5 11H13.5C13.7761 11 14 11.2239 14 11.5C14 11.7761
13.7761 12 13.5 12H1.5C1.22386 12 1 11.7761 1 11.5Z"
fill="currentColor"
fill-rule="evenodd"
clip-rule="evenodd"

View File

@@ -14,6 +14,7 @@
}
html, body {
height: 100vh;
aspect-ratio: 16/9;
margin: 0;

View File

@@ -1,7 +1,6 @@
import { createContext, createEffect, createResource, createSignal, For, JSX, ParentComponent, Show, useContext, VoidComponent } from "solid-js";
import { createStore } from "solid-js/store";
import { createDateNow } from "@solid-primitives/date";
import { IconButton, Menu, MenuTrigger, MenuContent, MenuItem } from "@hope-ui/solid";
import { format } from "date-fns";
import { BusinessDataContext, BusinessDataStore } from "./businessData";
@@ -9,7 +8,6 @@ import { AppContextContext, AppContextStore } from "./appContext";
import { getTransportModeSrc, PositionedPanel } from "./utils";
import { PassagesPanel } from "./passagesPanel";
import { IconHamburgerMenu } from './extra/iconHamburgerMenu';
import "./passagesDisplay.scss";
@@ -25,7 +23,7 @@ interface PassagesDisplayStore {
getDisplayedPanelId: () => number;
setDisplayedPanelId: (panelId: number) => void;
};
}
const PassagesDisplayContext = createContext<PassagesDisplayStore>();
@@ -91,7 +89,6 @@ const Header: VoidComponent<{ title: string }> = (props) => {
return <div />;
const { getLine, passages } = businessDataStore;
const { isPassagesRefreshEnabled, togglePassagesRefresh } = passagesDisplayStore;
const [dateNow] = createDateNow(1000);
@@ -113,16 +110,14 @@ const Header: VoidComponent<{ title: string }> = (props) => {
setLinesIds(Object.keys(passages()));
});
return (
<div class="header">
return <div class="header">
<Show when={transportModeUrls() !== undefined} >
<For each={transportModeUrls()}>
{(url) =>
<div class="transportMode">
<img src={url} />
</div>
}
</For>
}</For>
</Show>
<div class="title">
<svg viewBox="0 0 1260 50">
@@ -132,15 +127,6 @@ const Header: VoidComponent<{ title: string }> = (props) => {
</svg>
</div>
<div class="menu">
<Menu>
<MenuTrigger
as={IconButton}
icon=<IconHamburgerMenu />
/>
<MenuContent>
<MenuItem onSelect={() => togglePassagesRefresh()}>{isPassagesRefreshEnabled() ? "Disable" : "Enable"}</MenuItem>
</MenuContent>
</Menu>
</div>
<div class="clock">
<svg viewBox="0 0 115 43">
@@ -149,8 +135,7 @@ const Header: VoidComponent<{ title: string }> = (props) => {
</text>
</svg>
</div>
</div >
);
</div>;
};
const Footer: VoidComponent<{}> = () => {
@@ -176,8 +161,7 @@ const Footer: VoidComponent<{}> = () => {
</svg>
</div>
);
}}
</For>
}}</For>
</div>
);
}
@@ -286,13 +270,11 @@ export const PassagesDisplay: ParentComponent = () => {
const syncPeriodMsec = 20 * 1000;
const panelSwitchPeriodMsec = 4 * 1000;
return (
<div class="passagesDisplay">
return <div class="passagesDisplay">
<PassagesDisplayProvider>
<Header title="Prochains passages" />
<Body maxPassagesPerPanel={MAX_PASSAGES_PER_PANEL} syncPeriodMsec={syncPeriodMsec} panelSwitchPeriodMsec={panelSwitchPeriodMsec} />
<Footer />
</PassagesDisplayProvider>
</div>
);
</div>;
};

View File

@@ -14,15 +14,13 @@ import "./passagesPanel.scss";
const UnavailablePassage: VoidComponent<{ style: string }> = (props) => {
const textStyle = { fill: "#000000" };
return (
<div class={props.style}>
return <div class={props.style}>
<svg viewBox="0 0 230 110">
<text x="100%" y="26" font-size="25" text-anchor="end" style={textStyle}>Information</text>
<text x="100%" y="63" font-size="25" text-anchor="end" style={textStyle}>non</text>
<text x="100%" y="100" font-size="25" text-anchor="end" style={textStyle}>disponible</text>
</svg>
</div>
);
</div>;
}
const Platform: VoidComponent<{ name: string }> = (props) => {
@@ -43,14 +41,12 @@ const Platform: VoidComponent<{ name: string }> = (props) => {
}
});
return (
<svg class="platform" viewBox={`0 0 ${viewBoxWidthPx} 40`}>
return <svg class="platform" viewBox={`0 0 ${viewBoxWidthPx} 40`}>
<rect ref={rectRef} x="0" y="0" height="100%" rx="9" ry="9" />
<text ref={textRef} x="100%" y="55%" dominant-baseline="middle" text-anchor="end" font-size="25" style={{ fill: "#ffffff" }}>
QUAI {props.name}
</text>
</svg>
);
</svg>;
}
const TtwPassage: VoidComponent<{
@@ -88,8 +84,7 @@ const TtwPassage: VoidComponent<{
</Motion.text>
</svg>;
return (
<Show when={passage !== undefined} fallback=<UnavailablePassage style={props.fallbackStyle} />>
return <Show when={passage !== undefined} fallback={<UnavailablePassage style={props.fallbackStyle} />}>
<Show
when={passage.arrivalPlatformName !== null}
fallback={
@@ -100,9 +95,8 @@ const TtwPassage: VoidComponent<{
{text}
<Platform name={passage.arrivalPlatformName} />
</div>
</Show >
</Show >
);
</Show>
</Show>;
});
}
@@ -122,8 +116,7 @@ const DestinationPassages: VoidComponent<{ line: Line, destination: string }> =
// const trafficStatusStyle = { fill: trafficStatusColor.get(props.line.trafficStatus) };
const trafficStatusStyle = { fill: trafficStatusColor.get(TrafficStatus.UNKNOWN) };
return (
<div class="line">
return <div class="line">
<div class="transportMode">
{renderLineTransportMode(props.line)}
</div>
@@ -142,8 +135,7 @@ const DestinationPassages: VoidComponent<{ line: Line, destination: string }> =
<TtwPassage line={props.line} destination={props.destination} index={1}
style="secondPassage" withPlatformStyle="withPlatformSecondPassage"
fontSize={45} fallbackStyle="unavailableSecondPassage" />
</div >
);
</div>;
}
export type PassagesPanelComponentProps = ParentProps & { stopId: number, lineIds: string[], show: boolean };
@@ -162,19 +154,16 @@ export const PassagesPanel: PassagesPanelComponent = (props) => {
}
const [lines] = createResource<Line[], string[]>(props.lineIds, getLines);
return (
<div classList={{ ["passagesContainer"]: true, ["displayed"]: props.show }} >
return <div classList={{ "passagesContainer": true, "displayed": props.show }} >
<Show when={lines() !== undefined} >
<For each={lines()}>
{(line) =>
<Show when={getLineDestinations(line.id) !== undefined}>
<For each={getLineDestinations(line.id)}>
{(destination) => <DestinationPassages line={line} destination={destination} />}
</For>
<For each={getLineDestinations(line.id)}>{
(destination) => <DestinationPassages line={line} destination={destination} />
}</For>
</Show>
}
</For>
}</For>
</Show>
</div >
);
</div>;
}

View File

@@ -1,8 +1,8 @@
import { batch, createContext, JSX } from 'solid-js';
import { createContext, JSX } from 'solid-js';
import { createStore } from 'solid-js/store';
import { Marker as LeafletMarker } from 'leaflet';
import { Stop, Stops } from './types';
import { Stop } from './types';
export type ByStopIdMarkers = Record<number, LeafletMarker[] | undefined>;
@@ -52,9 +52,7 @@ export function SearchProvider(props: { children: JSX.Element }) {
setStore('markers', stopId, markers);
}
return (
<SearchContext.Provider value={{ getFoundStops, setFoundStops, getDisplayedStops, setDisplayedStops, addMarkers }}>
return <SearchContext.Provider value={{ getFoundStops, setFoundStops, getDisplayedStops, setDisplayedStops, addMarkers }}>
{props.children}
</SearchContext.Provider>
);
</SearchContext.Provider>;
}

View File

@@ -41,7 +41,7 @@ export const Map: ParentComponent<{}> = () => {
// TODO: Set padding according to the marker design.
const fitPointsPadding = [50, 50, 50, 50];
let mapDiv: HTMLDivElement | undefined = undefined;
let mapDiv: HTMLDivElement | undefined;
let popup: StopPopup | undefined = undefined;
const stopVectorSource = new OlVectorSource({ features: [] });
@@ -76,6 +76,7 @@ export const Map: ParentComponent<{}> = () => {
],
overlays: [overlay],
});
console.log("map=", map);
map.on('singleclick', onClickedMap);
}
@@ -108,7 +109,10 @@ export const Map: ParentComponent<{}> = () => {
}
}
onMount(() => buildMap(mapDiv));
onMount(() => {
buildMap(mapDiv);
})
;
// Filling the map with stops shape
createEffect(() => {
@@ -207,8 +211,8 @@ export const Map: ParentComponent<{}> = () => {
}
return <>
<div ref={mapDiv} class="map">
<StopPopup ref={popup} stop={selectedMapStop()} show={isPopupDisplayed()} />
<div ref={mapDiv!} class="map">
<StopPopup ref={popup!} stop={selectedMapStop()} show={isPopupDisplayed()} />
</div>
<For each={getFoundStops()}>{(stop) => <MapStop stop={stop} selected={selectedMapStop()} />}</For>
</>;

View File

@@ -149,8 +149,7 @@ export function SearchProvider(props: { children: JSX.Element }) {
setStore('mapFeatures', stopId, feature);
};
return (
<SearchContext.Provider value={{
return <SearchContext.Provider value={{
getSearchText, setSearchText,
getFoundStops, setFoundStops,
getDisplayedPanelId, setDisplayedPanelId,
@@ -160,6 +159,5 @@ export function SearchProvider(props: { children: JSX.Element }) {
getMapFeature, getAllMapFeatures, setMapFeature,
}}>
{props.children}
</SearchContext.Provider>
);
</SearchContext.Provider>;
}

View File

@@ -33,8 +33,7 @@ const StopRepr: VoidComponent<{ stop: Stop }> = (props) => {
const [lineReprs] = createResource<JSX.Element[], string[]>(props.stop.lines, fetchLinesRepr);
return (
<div class="stop">
return <div class="stop">
<svg class="name" viewBox={`0 0 215 ${fontSize}`}>
<text
x="100%" y="55%"
@@ -44,8 +43,7 @@ const StopRepr: VoidComponent<{ stop: Stop }> = (props) => {
</text>
</svg>
<For each={lineReprs()}>{(line: JSX.Element) => line}</For>
</div>
);
</div>;
}
@@ -83,7 +81,7 @@ const StopAreaRepr: VoidComponent<{ stop: Stop }> = (props) => {
if (line !== undefined) {
if (!(line.transportMode in byModeReprs)) {
byModeReprs[line.transportMode] = {
mode: <div class="transportMode">{renderLineTransportMode(line)}</div>,
mode: <div class="transportMode"> {renderLineTransportMode(line)}</div>,
lines: {}
};
}
@@ -91,12 +89,11 @@ const StopAreaRepr: VoidComponent<{ stop: Stop }> = (props) => {
}
}
const sortedTransportModes = Object.keys(byModeReprs).sort((x, y) => TransportModeWeights[x] <
TransportModeWeights[y] ? 1 : -1);
const sortedTransportModes = Object.keys(byModeReprs).sort((x, y) => TransportModeWeights[x] < TransportModeWeights[y] ? 1 : -1);
return (
<div class="lineRepr">
<For each={sortedTransportModes}>{(transportMode) => {
return <div class="lineRepr">
<For each={sortedTransportModes}>
{(transportMode) => {
const reprs = byModeReprs[transportMode];
const lineNames = Object.keys(reprs.lines).sort((x, y) => x.localeCompare(y));
return <>
@@ -104,40 +101,34 @@ const StopAreaRepr: VoidComponent<{ stop: Stop }> = (props) => {
<div class="linesRepresentationMatrix">
<For each={lineNames}>{(lineName) => reprs.lines[lineName]}</For>
</div>
</>
}}
</For>
</div >
);
</>;
}}</For>
</div>;
}
const [lineReprs] = createResource(props.stop, fetchLinesRepr);
return (
<div
return <div
class="stop"
onClick={() => setDisplayedStops([props.stop])}
onMouseEnter={() => setHighlightedStop(props.stop)}
onMouseLeave={resetHighlightedStop}
>
<div class="name" >
<div class="name">
<ScrollingText height={fontSize} width={100} content={props.stop.name} />
</div>
{lineReprs()}
</div>
);
</div>;
}
export const StopsPanel: ParentComponent<{ stops: Stop[], show: boolean }> = (props) => {
return (
<div classList={{ "stopPanel": true, "displayed": props.show }}>
return <div classList={{ "stopPanel": true, "displayed": props.show }}>
<For each={props.stops.sort((x, y) => x.name.localeCompare(y.name))}>
{(stop) => {
return <Show when={stop.stops !== undefined} fallback={<StopRepr stop={stop} />}>
<StopAreaRepr stop={stop} />
</Show>;
}}
</For>
</div>
);
}}</For>
</div>;
}

View File

@@ -29,21 +29,19 @@ export const StopPopup: ParentComponent<{ stop: Stop, show: boolean }> = (props)
}
const [destinations] = createResource(() => props.stop, getDestinations);
return (
<div ref={popupDiv} classList={{ "popup": true, "displayed": props.show }}>
return <div ref={popupDiv} classList={{ "popup": true, "displayed": props.show }}>
<div class="header">{props.stop?.name}</div>
<div class="body">
<div class="body" >
<For each={destinations()}>
{(dst) => {
return <div class='line'>
return <div class='line' >
{dst.lineId}
<div class="name">
< div class="name" >
<ScrollingText height={10} width={130} content={dst.destinations.join('/')} />
</div>
</div>;
}}
</For>
}}</For>
</div>
</div >
);
</div>;
}

View File

@@ -33,6 +33,7 @@
background-color: transparent;
.leftAddon {
width: 17%;

View File

@@ -1,4 +1,4 @@
import { createEffect, For, JSX, lazy, ParentComponent, useContext, Show, VoidComponent } from 'solid-js';
import { createEffect, For, JSX, ParentComponent, useContext, Show, VoidComponent } from 'solid-js';
import { lazily } from 'solidjs-lazily';
import { createScrollPosition } from "@solid-primitives/scroll";
@@ -16,11 +16,10 @@ import "./stopsSearchMenu.scss";
const StopNameInput: VoidComponent<{ onInput: JSX.EventHandler<HTMLInputElement, InputEvent>, leftAddon: string, placeholder: string }> = (props) => {
return (
<div class="stopNameInput">
return <div class="stopNameInput">
<div class="leftAddon">{props.leftAddon}</div>
<input type="text" oninput={props.onInput} placeholder={props.placeholder} />
</div>);
</div>;
};
@@ -40,8 +39,7 @@ const Header: VoidComponent<{ title: string, minCharsNb: number }> = (props) =>
}
}
return (
<div class="header">
return <div class="header">
<div class="title">
<svg viewBox="0 0 1260 50">
<text x="0" y="50%" dominant-baseline="middle" font-size="50" style="fill: #ffffff">
@@ -50,8 +48,7 @@ const Header: VoidComponent<{ title: string, minCharsNb: number }> = (props) =>
</svg>
</div>
<StopNameInput onInput={onStopNameInput} leftAddon="🚉 🚏" placeholder="Stop name..." />
</div >
);
</div>;
};
@@ -71,13 +68,15 @@ const StopsPanels: ParentComponent<{ maxStopsPerPanel: number }> = (props) => {
yStopsPanelsScroll();
for (const panel of getPanels()) {
const panelDiv = panel.panel();
const panelDiv = panel.panel;
if (panelDiv != null) {
const panelDivClientRect = panelDiv.getBoundingClientRect();
if (panelDivClientRect.y > 0) {
setDisplayedPanelId(panel.position);
break;
}
}
}
});
return (
@@ -133,7 +132,8 @@ const MapPlaceholder: VoidComponent<{}> = () => {
}
return <div
class="mapPlaceholder" ondblclick={() => onDoubleClick()}>
class="mapPlaceholder"
ondblclick={() => onDoubleClick()}>
Double-clic pour activer la carte
</div>;
};
@@ -166,35 +166,31 @@ const Footer: VoidComponent<{}> = () => {
const { getDisplayedPanelId, getPanels } = searchStore;
return (
<div class="footer">
return <div class="footer">
<For each={getPanels()}>
{(panel) => {
const position = panel.position;
return (
<div>
<svg viewBox="0 0 29 29">
<circle cx="50%" cy="50%" r="13" stroke="#ffffff" stroke-width="3"
<circle
cx="50%" cy="50%" r="13" stroke="#ffffff" stroke-width="3"
style={{ fill: `var(--idfm-${position == getDisplayedPanelId() ? "white" : "black"})` }}
/>
</svg>
</div>
);
}}
</For>
</div>
);
}}</For>
</div>;
};
export const StopsSearchMenu: VoidComponent = () => {
return (
<div class="stopSearchMenu">
return <div class="stopSearchMenu">
<SearchProvider>
<Header title="Recherche de l'arrêt..." minCharsNb={4} />
<Body />
<Footer />
</SearchProvider>
</div>
);
</div>;
};

View File

@@ -34,7 +34,7 @@ export class Passage {
this.arrivalStatus = arrivalStatus;
this.departStatus = departStatus;
}
};
}
export type Passages = Record<string, Record<string, Passage[]>>;
@@ -59,7 +59,7 @@ export class Stop {
this.lines.push(...stop.lines);
}
}
};
}
export type Stops = Record<number, Stop>;
@@ -77,7 +77,7 @@ export class StopShape {
this.epsg3857_bbox = epsg3857_bbox;
this.epsg3857_points = epsg3857_points;
}
};
}
export type StopShapes = Record<number, StopShape>;
@@ -111,6 +111,6 @@ export class Line {
this.audibleSignsAvailable = audibleSignsAvailable;
this.stopIds = stopIds;
}
};
}
export type Lines = Record<string, Line>;

View File

@@ -36,11 +36,11 @@ export function renderLineTransportMode(line: Line): JSX.Element {
}
function renderBusLinePicto(line: Line): JSX.Element {
return (
<div class="busLinePicto">
return <div class="busLinePicto">
<svg viewBox="0 0 31.5 14">
<rect x="0" y="0" width="31.5" height="14" rx="1.5" ry="1.5" style={{ fill: `#${line.backColorHexa}` }} />
<text x="50%"
<text
x="50%"
y="55%"
dominant-baseline="middle"
text-anchor="middle"
@@ -49,18 +49,17 @@ function renderBusLinePicto(line: Line): JSX.Element {
{line.shortName}
</text>
</svg>
</div>
);
</div>;
}
function renderTramLinePicto(line: Line): JSX.Element {
const lineStyle = { fill: `#${line.backColorHexa}` };
return (
<div class="tramLinePicto">
return <div class="tramLinePicto">
<svg viewBox="0 0 20 20">
<rect x="0" y="0" width="20" height="3" rx="1" ry="1" style={lineStyle} />
<rect x="0" y="17" width="20" height="3" rx="1" ry="1" style={lineStyle} />
<text x="50%"
<text
x="50%"
y="55%"
dominant-baseline="middle"
text-anchor="middle"
@@ -69,16 +68,15 @@ function renderTramLinePicto(line: Line): JSX.Element {
{line.shortName}
</text>
</svg>
</div>
);
</div>;
}
function renderMetroLinePicto(line: Line): JSX.Element {
return (
<div class="metroLinePicto">
return <div class="metroLinePicto">
<svg viewBox="0 0 20 20">
<circle cx="10" cy="10" r="10" style={{ fill: `#${line.backColorHexa}` }} />
<text x="50%"
<text
x="50%"
y="55%"
dominant-baseline="middle"
text-anchor="middle"
@@ -86,16 +84,15 @@ function renderMetroLinePicto(line: Line): JSX.Element {
{line.shortName}
</text>
</svg>
</div>
);
</div>;
}
function renderTrainLinePicto(line: Line): JSX.Element {
return (
<div class="trainLinePicto">
return <div class="trainLinePicto">
<svg viewBox="0 0 20 20">
<rect x="0" y="0" width="20" height="20" rx="4.5" ry="4.5" style={{ fill: `#${line.backColorHexa}` }} />
<text x="50%"
<text
x="50%"
y="55%"
dominant-baseline="middle"
text-anchor="middle"
@@ -104,8 +101,7 @@ function renderTrainLinePicto(line: Line): JSX.Element {
{line.shortName}
</text>
</svg>
</div>
);
</div>;
}
export function renderLinePicto(line: Line): JSX.Element {
@@ -152,8 +148,7 @@ export const ScrollingText: VoidComponent<{ height: number, width: number, conte
}
});
return (
<svg ref={viewBoxRef} viewBox={`0 0 ${props.width} ${props.height}`}>
return <svg ref={viewBoxRef} viewBox={`0 0 ${props.width} ${props.height}`}>
<text
ref={textRef}
x="0%" y="55%"
@@ -161,6 +156,5 @@ export const ScrollingText: VoidComponent<{ height: number, width: number, conte
font-size={`${props.height}px`}>
{props.content}
</text>
</svg >
);
</svg>;
}

View File

@@ -4,6 +4,7 @@
"jsxImportSource": "solid-js",
"noImplicitAny": true,
"target": "ES6",
"module": "esnext",
"moduleResolution": "node",
"allowJs": true,
"outDir": "build",