@autobusal/common 1.15.7 → 1.16.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.
- package/CHANGELOG.md +11 -0
- package/Calendar/Calendar.tsx +9 -1
- package/Road/Road.tsx +53 -0
- package/Road/styles.ts +87 -0
- package/UnderConstruction/UnderConstruction.tsx +8 -2
- package/UnderConstruction/styles.ts +0 -46
- package/Viewer/Data.tsx +6 -0
- package/index.ts +2 -0
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -6,6 +6,17 @@ All notable changes to `@autobusal/common` are documented here. This project fol
|
|
|
6
6
|
> Note: 1.10.0 through 1.15.1 were published without changelog entries. The
|
|
7
7
|
> gap is left as-is rather than reconstructed after the fact.
|
|
8
8
|
|
|
9
|
+
## [1.16.0] - 2026-08-01
|
|
10
|
+
|
|
11
|
+
### Added
|
|
12
|
+
|
|
13
|
+
- **The date field can tell its form when the day changes.** `ViewData.onChange`
|
|
14
|
+
was already honoured by `select` and `checkbox`, but not by `date`/`dob`/
|
|
15
|
+
`picker`, so a form whose other fields depend on the chosen day had no way
|
|
16
|
+
to observe it short of not using `Viewer` at all. `Calendar` now takes an
|
|
17
|
+
optional `onChange(DD/MM/YYYY)` and `Viewer` passes `item.onChange` through
|
|
18
|
+
to it. Purely additive - existing callers are unaffected.
|
|
19
|
+
|
|
9
20
|
## [1.15.6] - 2026-08-01
|
|
10
21
|
|
|
11
22
|
### Changed
|
package/Calendar/Calendar.tsx
CHANGED
|
@@ -22,9 +22,15 @@ interface Props {
|
|
|
22
22
|
minDate?: string
|
|
23
23
|
refs: UseFormRegister<any>
|
|
24
24
|
onUpdate: UseFormSetValue<any>
|
|
25
|
+
/**
|
|
26
|
+
* Edited: Ferjolt Ozuni - Date: 2026-08-01
|
|
27
|
+
* Notified with the newly picked DD/MM/YYYY day, for callers that need to
|
|
28
|
+
* react to it rather than only read it back at submit time.
|
|
29
|
+
*/
|
|
30
|
+
onChange?: (value: string) => void
|
|
25
31
|
}
|
|
26
32
|
|
|
27
|
-
const Calendar = ({ type, name, defaultValue, t, validation, minDate, refs, onUpdate }: Props): JSX.Element => {
|
|
33
|
+
const Calendar = ({ type, name, defaultValue, t, validation, minDate, refs, onUpdate, onChange }: Props): JSX.Element => {
|
|
28
34
|
const [ show, setShow ] = useState<boolean>(false);
|
|
29
35
|
const [ prepared, setPrepared ] = useState<string>(defaultValue ?? prepareDate(new Date()));
|
|
30
36
|
const [ selected, setSelected ] = useState<string>(prepared);
|
|
@@ -40,6 +46,8 @@ const Calendar = ({ type, name, defaultValue, t, validation, minDate, refs, onUp
|
|
|
40
46
|
setPrepared(prepared);
|
|
41
47
|
|
|
42
48
|
onUpdate(name, prepared);
|
|
49
|
+
|
|
50
|
+
onChange?.(prepared);
|
|
43
51
|
};
|
|
44
52
|
|
|
45
53
|
return (
|
package/Road/Road.tsx
ADDED
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { useState } from 'react';
|
|
2
|
+
import { RiBus2Line } from 'react-icons/ri';
|
|
3
|
+
import { Container, Bus, Vehicle, Fallback } from './styles';
|
|
4
|
+
|
|
5
|
+
interface Props {
|
|
6
|
+
/**
|
|
7
|
+
* Brand asset root (SettingsData.url). The bus is served from the label's
|
|
8
|
+
* own storage, exactly like its logo and hero artwork, so a whitelabel can
|
|
9
|
+
* ship its own vehicle without a code change.
|
|
10
|
+
*/
|
|
11
|
+
url?: string
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* A road with a bus travelling along it.
|
|
16
|
+
*
|
|
17
|
+
* Ferjolt Ozuni - Date: 2026-08-01
|
|
18
|
+
*
|
|
19
|
+
* Shared by the under-construction holding page and the error pages, which
|
|
20
|
+
* had been growing their own copies of the same CSS.
|
|
21
|
+
*
|
|
22
|
+
* The vehicle is an image from label storage rather than a bundled asset,
|
|
23
|
+
* for the same reason the logo is: every brand gets its own without a
|
|
24
|
+
* rebuild. If the brand has not supplied one the icon stands in, so a
|
|
25
|
+
* missing file degrades to what the page looked like before rather than
|
|
26
|
+
* leaving a hole where a bus should be.
|
|
27
|
+
*
|
|
28
|
+
* Entirely decorative - the caller marks it aria-hidden.
|
|
29
|
+
*/
|
|
30
|
+
const Road = ({ url }: Props): JSX.Element => {
|
|
31
|
+
const [ failed, setFailed ] = useState<boolean>(false);
|
|
32
|
+
|
|
33
|
+
return (
|
|
34
|
+
<Container>
|
|
35
|
+
<Bus>
|
|
36
|
+
{ url !== undefined && !failed
|
|
37
|
+
? (
|
|
38
|
+
/* WebP first (10KB against the PNG's 66KB), with the PNG as the
|
|
39
|
+
fallback source and the icon as the fallback for a brand that
|
|
40
|
+
has not supplied artwork at all */
|
|
41
|
+
<picture>
|
|
42
|
+
<source srcSet={ `${ url }/bus-artwork.webp` } type="image/webp" />
|
|
43
|
+
|
|
44
|
+
<Vehicle src={ `${ url }/bus-artwork.png` } alt="" onError={ () => setFailed(true) } />
|
|
45
|
+
</picture>
|
|
46
|
+
)
|
|
47
|
+
: <Fallback><RiBus2Line /></Fallback> }
|
|
48
|
+
</Bus>
|
|
49
|
+
</Container>
|
|
50
|
+
);
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
export default Road;
|
package/Road/styles.ts
ADDED
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import styled, { keyframes } from 'styled-components';
|
|
2
|
+
|
|
3
|
+
const drift = keyframes`
|
|
4
|
+
from { transform: translateX(0); }
|
|
5
|
+
to { transform: translateX(-84px); }
|
|
6
|
+
`;
|
|
7
|
+
|
|
8
|
+
const travel = keyframes`
|
|
9
|
+
from { transform: translateX(-26vw); }
|
|
10
|
+
to { transform: translateX(114vw); }
|
|
11
|
+
`;
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Ferjolt Ozuni - Date: 2026-08-01
|
|
15
|
+
*
|
|
16
|
+
* A band of road across the foot of the page. Lifted out of
|
|
17
|
+
* UnderConstruction so the error pages could use the same one instead of a
|
|
18
|
+
* second copy of the same CSS.
|
|
19
|
+
*/
|
|
20
|
+
export const Container = styled.div`
|
|
21
|
+
position: absolute;
|
|
22
|
+
right: 0;
|
|
23
|
+
bottom: 0;
|
|
24
|
+
left: 0;
|
|
25
|
+
height: 150px;
|
|
26
|
+
overflow: hidden;
|
|
27
|
+
background: linear-gradient(
|
|
28
|
+
to top,
|
|
29
|
+
${ props => props.theme.primary.normal }22,
|
|
30
|
+
transparent
|
|
31
|
+
);
|
|
32
|
+
|
|
33
|
+
&::after {
|
|
34
|
+
content: '';
|
|
35
|
+
position: absolute;
|
|
36
|
+
bottom: 46px;
|
|
37
|
+
left: 0;
|
|
38
|
+
width: 200%;
|
|
39
|
+
height: 3px;
|
|
40
|
+
border-radius: 3px;
|
|
41
|
+
background: repeating-linear-gradient(
|
|
42
|
+
to right,
|
|
43
|
+
${ props => props.theme.primary.normal }66 0 42px,
|
|
44
|
+
transparent 42px 84px
|
|
45
|
+
);
|
|
46
|
+
animation: ${ drift } 6s linear infinite;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/* a moving road is exactly the kind of thing that should stop for anyone
|
|
50
|
+
who has asked motion to stop */
|
|
51
|
+
@media (prefers-reduced-motion: reduce) {
|
|
52
|
+
&::after {
|
|
53
|
+
animation: none;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
`;
|
|
57
|
+
|
|
58
|
+
export const Bus = styled.div`
|
|
59
|
+
position: absolute;
|
|
60
|
+
bottom: 44px;
|
|
61
|
+
left: 0;
|
|
62
|
+
display: flex;
|
|
63
|
+
align-items: flex-end;
|
|
64
|
+
animation: ${ travel } 18s linear infinite;
|
|
65
|
+
|
|
66
|
+
/* parked, not removed - the scene should still make sense standing still */
|
|
67
|
+
@media (prefers-reduced-motion: reduce) {
|
|
68
|
+
animation: none;
|
|
69
|
+
transform: translateX(10vw);
|
|
70
|
+
}
|
|
71
|
+
`;
|
|
72
|
+
|
|
73
|
+
export const Vehicle = styled.img`
|
|
74
|
+
display: block;
|
|
75
|
+
width: 150px;
|
|
76
|
+
height: auto;
|
|
77
|
+
|
|
78
|
+
@media (min-width: 768px) {
|
|
79
|
+
width: 200px;
|
|
80
|
+
}
|
|
81
|
+
`;
|
|
82
|
+
|
|
83
|
+
export const Fallback = styled.span`
|
|
84
|
+
display: flex;
|
|
85
|
+
font-size: 44px;
|
|
86
|
+
color: ${ props => props.theme.primary.normal };
|
|
87
|
+
`;
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { useEffect } from 'react';
|
|
2
2
|
import { TFunction } from 'i18next';
|
|
3
|
-
import
|
|
3
|
+
import Road from '../Road/Road';
|
|
4
|
+
import { Screen, Content, Logo, Title, Message } from './styles';
|
|
4
5
|
import { useGetSettings } from '@autobusal/providers/services';
|
|
5
6
|
|
|
6
7
|
interface Props {
|
|
@@ -75,7 +76,12 @@ const UnderConstruction = ({ t }: Props): JSX.Element => {
|
|
|
75
76
|
|
|
76
77
|
</Content>
|
|
77
78
|
|
|
78
|
-
|
|
79
|
+
{ /* Edited: Ferjolt Ozuni - Date: 2026-08-01
|
|
80
|
+
Shared with the error pages now, and carrying the brand's bus
|
|
81
|
+
rather than a bare strip of road. */ }
|
|
82
|
+
<div aria-hidden="true">
|
|
83
|
+
<Road url={ settings?.url } />
|
|
84
|
+
</div>
|
|
79
85
|
</Screen>
|
|
80
86
|
);
|
|
81
87
|
};
|
|
@@ -11,11 +11,6 @@ import styled, { keyframes } from 'styled-components';
|
|
|
11
11
|
* rather than a generic maintenance page.
|
|
12
12
|
*/
|
|
13
13
|
|
|
14
|
-
const drift = keyframes`
|
|
15
|
-
from { transform: translate3d(0, 0, 0); }
|
|
16
|
-
to { transform: translate3d(-50%, 0, 0); }
|
|
17
|
-
`;
|
|
18
|
-
|
|
19
14
|
const rise = keyframes`
|
|
20
15
|
from { opacity: 0; transform: translateY(14px); }
|
|
21
16
|
to { opacity: 1; transform: translateY(0); }
|
|
@@ -72,44 +67,3 @@ export const Message = styled.p`
|
|
|
72
67
|
color: ${ props => props.theme.font.faded };
|
|
73
68
|
`;
|
|
74
69
|
|
|
75
|
-
/**
|
|
76
|
-
* A slow band of road at the foot of the page. Purely decorative, and
|
|
77
|
-
* hidden from assistive tech - it carries no information.
|
|
78
|
-
*/
|
|
79
|
-
export const Road = styled.div`
|
|
80
|
-
position: absolute;
|
|
81
|
-
right: 0;
|
|
82
|
-
bottom: 0;
|
|
83
|
-
left: 0;
|
|
84
|
-
height: 96px;
|
|
85
|
-
opacity: 0.5;
|
|
86
|
-
background: linear-gradient(
|
|
87
|
-
to top,
|
|
88
|
-
${ props => props.theme.primary.normal }22,
|
|
89
|
-
transparent
|
|
90
|
-
);
|
|
91
|
-
|
|
92
|
-
&::after {
|
|
93
|
-
content: '';
|
|
94
|
-
position: absolute;
|
|
95
|
-
bottom: 34px;
|
|
96
|
-
left: 0;
|
|
97
|
-
width: 200%;
|
|
98
|
-
height: 3px;
|
|
99
|
-
border-radius: 3px;
|
|
100
|
-
background: repeating-linear-gradient(
|
|
101
|
-
to right,
|
|
102
|
-
${ props => props.theme.primary.normal }66 0 42px,
|
|
103
|
-
transparent 42px 84px
|
|
104
|
-
);
|
|
105
|
-
animation: ${ drift } 6s linear infinite;
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
/* a moving dashed line is exactly the kind of thing that should stop for
|
|
109
|
-
anyone who has asked motion to stop */
|
|
110
|
-
@media (prefers-reduced-motion: reduce) {
|
|
111
|
-
&::after {
|
|
112
|
-
animation: none;
|
|
113
|
-
}
|
|
114
|
-
}
|
|
115
|
-
`;
|
package/Viewer/Data.tsx
CHANGED
|
@@ -83,6 +83,12 @@ const Data = ({ id, item, refs, t, onUpdate }: Props): (JSX.Element | null) => {
|
|
|
83
83
|
validation={ item.rules }
|
|
84
84
|
refs={ refs }
|
|
85
85
|
onUpdate={ onUpdate }
|
|
86
|
+
// Edited: Ferjolt Ozuni - Date: 2026-08-01
|
|
87
|
+
// `select` and `checkbox` already surfaced item.onChange; date did
|
|
88
|
+
// not, so a form whose other fields react to the chosen day (e.g.
|
|
89
|
+
// the Telegram broadcast's live recipient count) had no way to
|
|
90
|
+
// observe it short of not using Viewer at all.
|
|
91
|
+
onChange={ item.onChange }
|
|
86
92
|
/>
|
|
87
93
|
);
|
|
88
94
|
|
package/index.ts
CHANGED
|
@@ -29,6 +29,7 @@ import Policy from './Policy/Policy';
|
|
|
29
29
|
import Report from './Report/Report';
|
|
30
30
|
import RouteFeature from './RouteFeature/RouteFeature';
|
|
31
31
|
import Required from './Required/Required';
|
|
32
|
+
import Road from './Road/Road';
|
|
32
33
|
import RouteItem from './RouteItem/RouteItem';
|
|
33
34
|
import Row from './Table/Row';
|
|
34
35
|
import Table from './Table/Table';
|
|
@@ -72,6 +73,7 @@ export {
|
|
|
72
73
|
Report,
|
|
73
74
|
RouteFeature,
|
|
74
75
|
Required,
|
|
76
|
+
Road,
|
|
75
77
|
RouteItem,
|
|
76
78
|
Row,
|
|
77
79
|
Table,
|