@autobusal/providers 1.11.0 → 1.12.1

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.
package/CHANGELOG.md CHANGED
@@ -4,6 +4,20 @@ All notable changes to `@autobusal/providers` are documented here. This project
4
4
  adheres to [Keep a Changelog](https://keepachangelog.com/en/1.1.0/) and
5
5
  [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
6
6
 
7
+ > Note: 1.8.0 through 1.11.0 were published without changelog entries. The
8
+ > gap is left as-is rather than reconstructed after the fact.
9
+
10
+ ## [1.12.0] - 2026-08-01
11
+
12
+ ### Added
13
+
14
+ - `FoundData.stops_count` - intermediate stops between the searched from/to,
15
+ where 0 means a direct trip. Optional, because external-provider offers do
16
+ not report one: a filter must read "missing" as unknown, never as direct.
17
+ - `FoundData.priority` - the operator's subscription priority, which obtapi
18
+ was already sending but which was not typed. Used only as a tiebreak in
19
+ routes-order's "recommended" ordering.
20
+
7
21
  ## [1.7.0] - 2026-07-31
8
22
 
9
23
  ### Added
@@ -1,9 +1,10 @@
1
1
  import { useNavigate } from 'react-router-dom';
2
+ import { RiBus2Line } from 'react-icons/ri';
2
3
  import { Button, Meta } from '@autobusal/common';
3
4
  import { useSystemTheme } from '@autobusal/hooks';
4
5
  import { getLanguage } from '../Setup/languages';
5
6
  import errors from '@lang/errors';
6
- import { Background, Container, Logo, Description } from './styles';
7
+ import { Background, Road, Bus, Container, Logo, Code, Description, Detail } from './styles';
7
8
  import { useGetSettings } from '../services';
8
9
 
9
10
  interface Props {
@@ -24,9 +25,31 @@ const Message = ({ type }: Props): JSX.Element => {
24
25
  // `undefined` and crash the error page on `.not_found`/`.system`.
25
26
  const translations = errors[language as keyof typeof errors] ?? errors.en;
26
27
 
28
+ /**
29
+ * Edited: Ferjolt Ozuni - Date: 2026-08-01
30
+ *
31
+ * Each error now says what went wrong AND what to do next. One generic
32
+ * line told the reader nothing and left a Back button as their only idea;
33
+ * a missing page and a server fault are different problems and deserve
34
+ * different suggestions.
35
+ */
36
+ const notFound = type === 'not_found';
37
+
38
+ const heading = notFound ? translations.not_found : translations.system;
39
+
40
+ const detail = notFound ? translations.not_found_detail : translations.system_detail;
41
+
27
42
  return (
28
- <Meta title={ type === 'not_found' ? translations.not_found : translations.system } noIndex={ true }>
29
- <Background />
43
+ <Meta title={ heading } noIndex={ true }>
44
+ <Background>
45
+ { /* decorative: the road and the bus carry no information, so they
46
+ are hidden from assistive technology entirely */ }
47
+ <Road aria-hidden="true" />
48
+
49
+ <Bus aria-hidden="true">
50
+ <RiBus2Line />
51
+ </Bus>
52
+ </Background>
30
53
 
31
54
  <Container className="box">
32
55
  <Logo
@@ -43,9 +66,11 @@ const Message = ({ type }: Props): JSX.Element => {
43
66
  <img src={ `${ data.url }/logo-${ theme }.svg` } alt={ translations.home } />
44
67
  </Logo>
45
68
 
46
- <Description>
47
- { type === 'not_found' ? translations.not_found : translations.system }
48
- </Description>
69
+ <Code>{ notFound ? '404' : '500' }</Code>
70
+
71
+ <Description>{ heading }</Description>
72
+
73
+ <Detail>{ detail }</Detail>
49
74
 
50
75
  <Button
51
76
  type="button"
@@ -58,4 +83,4 @@ const Message = ({ type }: Props): JSX.Element => {
58
83
  );
59
84
  };
60
85
 
61
- export default Message;
86
+ export default Message;
package/Errors/styles.ts CHANGED
@@ -1,35 +1,57 @@
1
- import styled from 'styled-components';
1
+ import styled, { keyframes } from 'styled-components';
2
+
3
+ /**
4
+ * Edited: Ferjolt Ozuni - Date: 2026-08-01
5
+ *
6
+ * The error page was a line of text and a button on a blank field. It now
7
+ * borrows the road treatment from the under-construction holding page and
8
+ * sends a bus along it, with the explanation boxed in the middle - so a
9
+ * dead end still looks like part of the product rather than a crash.
10
+ */
11
+ const drift = keyframes`
12
+ from { transform: translateX(0); }
13
+ to { transform: translateX(-84px); }
14
+ `;
15
+
16
+ const travel = keyframes`
17
+ from { transform: translateX(-22vw); }
18
+ to { transform: translateX(112vw); }
19
+ `;
20
+
21
+ const rise = keyframes`
22
+ from { opacity: 0; transform: translate(-50%, calc(-50% + 10px)); }
23
+ to { opacity: 1; transform: translate(-50%, -50%); }
24
+ `;
2
25
 
3
26
  export const Background = styled.div`
4
27
  position: fixed;
5
- top: 0;
6
- left: 0;
7
- right: 0;
8
- bottom: 0;
28
+ inset: 0;
9
29
  z-index: 10000;
30
+ overflow: hidden;
10
31
  background: ${ props => props.theme.background.normal };
11
32
  `;
12
33
 
13
34
  export const Container = styled.div`
14
35
  position: fixed;
15
36
  top: 50%;
16
- right: 50%;
37
+ left: 50%;
17
38
  z-index: 10001;
18
- max-width: 400px;
39
+ width: calc(100% - 40px);
40
+ max-width: 560px;
19
41
  display: flex;
20
42
  flex-direction: column;
21
- justify-content: center;
22
43
  align-items: center;
23
- transform: translate(50%, -50%);
44
+ transform: translate(-50%, -50%);
45
+ animation: ${ rise } 0.5s ease-out both;
24
46
  `;
25
47
 
26
48
  export const Logo = styled.div`
27
- margin-bottom: 20px;
49
+ margin-bottom: 22px;
28
50
  display: inline-block;
29
51
 
30
52
  & > img {
31
53
  display: block;
32
- width: 250px;
54
+ width: 210px;
33
55
  cursor: pointer;
34
56
  }
35
57
 
@@ -39,9 +61,83 @@ export const Logo = styled.div`
39
61
  }
40
62
  `;
41
63
 
42
- export const Description = styled.div`
43
- margin-bottom: 20px;
64
+ export const Code = styled.div`
65
+ margin-bottom: 6px;
66
+ font-weight: 700;
67
+ letter-spacing: 3px;
68
+ text-transform: uppercase;
69
+ font-size: ${ props => props.theme.size.xs };
70
+ color: ${ props => props.theme.primary.normal };
71
+ `;
72
+
73
+ export const Description = styled.h1`
74
+ margin-bottom: 10px;
44
75
  font-weight: 700;
45
76
  text-align: center;
46
- font-size: ${ props => props.theme.size.xxl };
47
- `;
77
+ font-size: clamp(20px, 3vw, 28px);
78
+ `;
79
+
80
+ export const Detail = styled.p`
81
+ margin: 0 0 22px;
82
+ text-align: center;
83
+ line-height: 1.6;
84
+ color: ${ props => props.theme.font.faded };
85
+ `;
86
+
87
+ /**
88
+ * A band of road across the foot of the page. Decorative only, and hidden
89
+ * from assistive technology - it carries nothing a screen reader needs.
90
+ */
91
+ export const Road = styled.div`
92
+ position: absolute;
93
+ right: 0;
94
+ bottom: 0;
95
+ left: 0;
96
+ height: 150px;
97
+ background: linear-gradient(
98
+ to top,
99
+ ${ props => props.theme.primary.normal }22,
100
+ transparent
101
+ );
102
+
103
+ &::after {
104
+ content: '';
105
+ position: absolute;
106
+ bottom: 46px;
107
+ left: 0;
108
+ width: 200%;
109
+ height: 3px;
110
+ border-radius: 3px;
111
+ background: repeating-linear-gradient(
112
+ to right,
113
+ ${ props => props.theme.primary.normal }66 0 42px,
114
+ transparent 42px 84px
115
+ );
116
+ animation: ${ drift } 6s linear infinite;
117
+ }
118
+
119
+ /* a moving road is exactly the kind of thing that should stop for anyone
120
+ who has asked motion to stop */
121
+ @media (prefers-reduced-motion: reduce) {
122
+ &::after {
123
+ animation: none;
124
+ }
125
+ }
126
+ `;
127
+
128
+ export const Bus = styled.div`
129
+ position: absolute;
130
+ bottom: 52px;
131
+ left: 0;
132
+ display: flex;
133
+ align-items: center;
134
+ font-size: 44px;
135
+ color: ${ props => props.theme.primary.normal };
136
+ animation: ${ travel } 16s linear infinite;
137
+
138
+ /* parked, not removed - the scene should still make sense standing still */
139
+ @media (prefers-reduced-motion: reduce) {
140
+ animation: none;
141
+ transform: translateX(10vw);
142
+ }
143
+ `;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@autobusal/providers",
3
- "version": "1.11.0",
3
+ "version": "1.12.1",
4
4
  "author": "Ferjolt Ozuni",
5
5
  "type": "module",
6
6
  "main": "index.ts"
package/types/routes.ts CHANGED
@@ -91,6 +91,16 @@ export interface FoundData extends Omit<RouteData, 'locations' | 'id'> {
91
91
  // still assume a real numeric local id.
92
92
  price: Omit<PriceData, 'id'> & { id: number | string }
93
93
  duration: string
94
+ // Edited: Ferjolt Ozuni - Date: 2026-08-01
95
+ // Intermediate stops between the searched from/to - 0 is a direct trip.
96
+ // Optional because external-provider offers don't report one; a filter
97
+ // must read "missing" as unknown, never as direct.
98
+ stops_count?: number
99
+ // Edited: Ferjolt Ozuni - Date: 2026-08-01
100
+ // The operator's subscription priority, as obtapi already sends it.
101
+ // Used only as a tiebreak in the "recommended" ordering - see
102
+ // routes-order's Found/refine.ts. Absent on external-provider offers.
103
+ priority?: number
94
104
  customs: string[]
95
105
  locations: {
96
106
  from: LocationData