@autobusal/common 1.8.3 → 1.10.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/Avatar.tsx +3 -2
- package/Button/Button.tsx +9 -1
- package/CHANGELOG.md +14 -0
- package/CompanyItem/styles.ts +3 -2
- package/RouteItem/styles.ts +7 -1
- package/Viewer/Actions.tsx +18 -1
- package/Viewer/Viewer.tsx +19 -3
- package/Viewer/types.ts +2 -0
- package/package.json +1 -1
- package/styles.ts +51 -0
package/Avatar.tsx
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import styled from 'styled-components';
|
|
2
2
|
import { OperatorData } from '@autobusal/providers/types/operators';
|
|
3
3
|
import { AgentData } from '@autobusal/providers/types/agents';
|
|
4
|
+
import { logoBox } from './styles';
|
|
4
5
|
|
|
5
6
|
interface Props {
|
|
6
7
|
display?: OperatorData | AgentData
|
|
@@ -19,8 +20,8 @@ const Container = styled.div`
|
|
|
19
20
|
gap: 10px;
|
|
20
21
|
|
|
21
22
|
& > img {
|
|
22
|
-
|
|
23
|
-
|
|
23
|
+
${ logoBox('80px', '48px') }
|
|
24
|
+
|
|
24
25
|
border-radius: ${ props => props.theme.borderRadius };
|
|
25
26
|
}
|
|
26
27
|
`;
|
package/Button/Button.tsx
CHANGED
|
@@ -11,9 +11,15 @@ interface Props {
|
|
|
11
11
|
noMargin?: boolean
|
|
12
12
|
maxWidth?: number
|
|
13
13
|
onClick?: any
|
|
14
|
+
// Edited: Ferjolt Ozuni - Date: 2026-07-31
|
|
15
|
+
// A native <button name value> pair - lets a form with more than one
|
|
16
|
+
// submit-type action (e.g. Viewer's 'save' vs 'test') tell them apart via
|
|
17
|
+
// the submit event's `submitter`, without any extra state.
|
|
18
|
+
name?: string
|
|
19
|
+
value?: string
|
|
14
20
|
}
|
|
15
21
|
|
|
16
|
-
const Button = ({ type, size, loading, active, subtype, text, noMargin, maxWidth, onClick }: Props) => (
|
|
22
|
+
const Button = ({ type, size, loading, active, subtype, text, noMargin, maxWidth, onClick, name, value }: Props) => (
|
|
17
23
|
<ButtonStyled
|
|
18
24
|
$size={ size }
|
|
19
25
|
type={ loading ? 'button' : type }
|
|
@@ -22,6 +28,8 @@ const Button = ({ type, size, loading, active, subtype, text, noMargin, maxWidth
|
|
|
22
28
|
$margin={ noMargin ? false : true }
|
|
23
29
|
$maxWidth={ maxWidth }
|
|
24
30
|
onClick={ onClick }
|
|
31
|
+
name={ name }
|
|
32
|
+
value={ value }
|
|
25
33
|
>
|
|
26
34
|
{ loading ? <RiLoader2Fill /> : text }
|
|
27
35
|
</ButtonStyled>
|
package/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,20 @@
|
|
|
3
3
|
All notable changes to `@autobusal/common` are documented here. This project follows
|
|
4
4
|
[Keep a Changelog](https://keepachangelog.com/) and [Semantic Versioning](https://semver.org/).
|
|
5
5
|
|
|
6
|
+
## [1.9.0] - 2026-07-31
|
|
7
|
+
|
|
8
|
+
### Added
|
|
9
|
+
|
|
10
|
+
- **`Viewer`/`Actions`/`Button` support a second submit-type action** via an
|
|
11
|
+
optional `onTest` prop on `Viewer` and a new `'test'` entry in its
|
|
12
|
+
`actions` array. A form with two submit buttons can't otherwise tell
|
|
13
|
+
which one triggered submission - `Button` now forwards a native
|
|
14
|
+
`name`/`value` pair, and `Viewer`'s `onSubmit` reads the submit event's
|
|
15
|
+
`submitter` to route to `onTest` instead of `onSave` when the 'test'
|
|
16
|
+
button was clicked, while keeping the exact same current form values.
|
|
17
|
+
First consumer: `@autobusal/admin-label` 1.10.0's "Test" button on the
|
|
18
|
+
SMTP settings tab.
|
|
19
|
+
|
|
6
20
|
## [1.8.3] - 2026-07-31
|
|
7
21
|
|
|
8
22
|
### Fixed
|
package/CompanyItem/styles.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import styled, { css } from 'styled-components';
|
|
2
2
|
import { Link } from 'react-router-dom';
|
|
3
|
+
import { logoBox } from '../styles';
|
|
3
4
|
|
|
4
5
|
export const Item = styled.div<{
|
|
5
6
|
$column: boolean
|
|
@@ -41,8 +42,8 @@ const LogoCss = css`
|
|
|
41
42
|
justify-content: center;
|
|
42
43
|
|
|
43
44
|
& > img {
|
|
44
|
-
|
|
45
|
-
|
|
45
|
+
${ logoBox('120px', '72px') }
|
|
46
|
+
|
|
46
47
|
border-radius: ${ props => props.theme.borderRadius };
|
|
47
48
|
}
|
|
48
49
|
`;
|
package/RouteItem/styles.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import styled, { css } from 'styled-components';
|
|
2
2
|
import { Link } from 'react-router-dom';
|
|
3
|
+
import { logoFit } from '../styles';
|
|
3
4
|
|
|
4
5
|
export const Container = styled.div`
|
|
5
6
|
padding: 10px;
|
|
@@ -29,8 +30,13 @@ export const Logo = styled(Link)`
|
|
|
29
30
|
border-radius: ${ props => props.theme.borderRadius };
|
|
30
31
|
|
|
31
32
|
& > img {
|
|
32
|
-
|
|
33
|
+
${ logoFit }
|
|
34
|
+
|
|
35
|
+
/* the container carries aspect-ratio: 1.35 - filling it completely is
|
|
36
|
+
what lets object-fit letterbox inside that shape, instead of the
|
|
37
|
+
image dictating its own height and spilling out of it */
|
|
33
38
|
width: 100%;
|
|
39
|
+
height: 100%;
|
|
34
40
|
}
|
|
35
41
|
`;
|
|
36
42
|
|
package/Viewer/Actions.tsx
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { TFunction } from 'i18next';
|
|
2
2
|
import { BiEditAlt, BiTrash, BiSend } from 'react-icons/bi';
|
|
3
|
-
import { RiSave2Line, RiCheckFill, RiSearchLine } from 'react-icons/ri';
|
|
3
|
+
import { RiSave2Line, RiCheckFill, RiSearchLine, RiMailSendLine } from 'react-icons/ri';
|
|
4
4
|
import { BsPlusCircleFill } from 'react-icons/bs';
|
|
5
5
|
import Button from '../Button/Button';
|
|
6
6
|
import { ContainerActions } from './styles';
|
|
@@ -41,6 +41,21 @@ const Actions = ({ id, available, pending, t, onDelete }: Props): JSX.Element =>
|
|
|
41
41
|
});
|
|
42
42
|
}
|
|
43
43
|
|
|
44
|
+
// Edited: Ferjolt Ozuni - Date: 2026-07-31
|
|
45
|
+
// A second submit-type action alongside 'save' (e.g. "Test SMTP") - the
|
|
46
|
+
// name/value pair lets Viewer's onSubmit tell which button was actually
|
|
47
|
+
// clicked via the submit event's `submitter`, since a form with two
|
|
48
|
+
// submit buttons can't otherwise distinguish them.
|
|
49
|
+
if (available.includes('test')) {
|
|
50
|
+
options.push({
|
|
51
|
+
label: t('table.actions.test', { ns: 'common' }),
|
|
52
|
+
icon: <RiMailSendLine />,
|
|
53
|
+
type: 'submit',
|
|
54
|
+
name: 'intent',
|
|
55
|
+
value: 'test'
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
|
|
44
59
|
if (available.includes('send')) {
|
|
45
60
|
options.push({
|
|
46
61
|
label: t('table.actions.send', { ns: 'common' }),
|
|
@@ -93,6 +108,8 @@ const Actions = ({ id, available, pending, t, onDelete }: Props): JSX.Element =>
|
|
|
93
108
|
loading={ pending }
|
|
94
109
|
noMargin
|
|
95
110
|
onClick={ item.handler }
|
|
111
|
+
name={ item.name }
|
|
112
|
+
value={ item.value }
|
|
96
113
|
/>
|
|
97
114
|
));
|
|
98
115
|
|
package/Viewer/Viewer.tsx
CHANGED
|
@@ -16,11 +16,16 @@ interface Props {
|
|
|
16
16
|
t: TFunction<'common'>
|
|
17
17
|
onSave?: (data: any) => void
|
|
18
18
|
onDelete?: (data?: any) => void
|
|
19
|
+
// Edited: Ferjolt Ozuni - Date: 2026-07-31
|
|
20
|
+
// Optional second submit-type action (actions={['save', 'test']}) - e.g.
|
|
21
|
+
// the SMTP tab's "Test" button, which needs the same current form values
|
|
22
|
+
// as save but must call a different handler instead of persisting.
|
|
23
|
+
onTest?: (data: any) => void
|
|
19
24
|
}
|
|
20
25
|
|
|
21
|
-
const Viewer = ({ id, type, data, fetching, pending, actions, t, onSave, onDelete }: Props): JSX.Element => {
|
|
26
|
+
const Viewer = ({ id, type, data, fetching, pending, actions, t, onSave, onDelete, onTest }: Props): JSX.Element => {
|
|
22
27
|
const { register, handleSubmit, formState: { errors }, setValue } = useForm<any>();
|
|
23
|
-
|
|
28
|
+
|
|
24
29
|
if (fetching) {
|
|
25
30
|
return <Loading t={ t } />;
|
|
26
31
|
}
|
|
@@ -37,7 +42,18 @@ const Viewer = ({ id, type, data, fetching, pending, actions, t, onSave, onDelet
|
|
|
37
42
|
/>
|
|
38
43
|
));
|
|
39
44
|
|
|
40
|
-
const onSubmit = (data: any): void => {
|
|
45
|
+
const onSubmit = (data: any, event?: React.BaseSyntheticEvent): void => {
|
|
46
|
+
// A form with two submit buttons can't tell which one triggered
|
|
47
|
+
// submission except via the native SubmitEvent's `submitter` - the
|
|
48
|
+
// 'test' button is the only one with a name/value pair (see Actions.tsx).
|
|
49
|
+
const submitter = (event?.nativeEvent as SubmitEvent | undefined)?.submitter as (HTMLButtonElement | undefined);
|
|
50
|
+
|
|
51
|
+
if (submitter?.value === 'test' && onTest !== undefined) {
|
|
52
|
+
onTest(data);
|
|
53
|
+
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
56
|
+
|
|
41
57
|
if (onSave !== undefined) {
|
|
42
58
|
onSave(data);
|
|
43
59
|
}
|
package/Viewer/types.ts
CHANGED
package/package.json
CHANGED
package/styles.ts
ADDED
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { css } from 'styled-components';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* How an operator/agent logo is displayed, everywhere.
|
|
5
|
+
*
|
|
6
|
+
* Edited: Ferjolt Ozuni - Date: 2026-07-31
|
|
7
|
+
*
|
|
8
|
+
* Logos are uploaded by operators at whatever size and shape they happen to
|
|
9
|
+
* have - tall badges, wide wordmarks, squares. Every place that rendered
|
|
10
|
+
* one set a width (or `width: 100%`) and no height and no `object-fit`, so
|
|
11
|
+
* the image was left to take whatever height its own ratio implied: inside
|
|
12
|
+
* a fixed or aspect-ratio'd box that meant it overflowed and was visibly
|
|
13
|
+
* cropped, and in a flex row it stretched its neighbours around.
|
|
14
|
+
*
|
|
15
|
+
* `object-fit: contain` is the whole fix. It scales the image down until it
|
|
16
|
+
* fits INSIDE the box in its own aspect ratio, never cropping and never
|
|
17
|
+
* distorting. Whatever room is left over stays empty - deliberately
|
|
18
|
+
* transparent rather than a colour, so the logo sits on whatever the
|
|
19
|
+
* surrounding card already uses and dark and light themes both work without
|
|
20
|
+
* a second rule.
|
|
21
|
+
*
|
|
22
|
+
* The box needs BOTH dimensions for this to mean anything: with only a
|
|
23
|
+
* width there is no leftover space for `contain` to preserve, and the
|
|
24
|
+
* behaviour collapses back to the original bug. Callers pass the size.
|
|
25
|
+
*
|
|
26
|
+
* `object-position: center` is explicit rather than relied upon - it is the
|
|
27
|
+
* default, but the whole point here is that nothing about the framing is
|
|
28
|
+
* left to chance.
|
|
29
|
+
*/
|
|
30
|
+
export const logoFit = css`
|
|
31
|
+
display: block;
|
|
32
|
+
object-fit: contain;
|
|
33
|
+
object-position: center;
|
|
34
|
+
|
|
35
|
+
/* no fill, so the logo adopts whatever surface it is placed on */
|
|
36
|
+
background: transparent;
|
|
37
|
+
`;
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* A complete logo box: fits the image inside the given dimensions without
|
|
41
|
+
* cropping or stretching it.
|
|
42
|
+
*
|
|
43
|
+
* Pass the size the layout wants; the image keeps its own proportions
|
|
44
|
+
* within it.
|
|
45
|
+
*/
|
|
46
|
+
export const logoBox = (width: string, height: string) => css`
|
|
47
|
+
${ logoFit }
|
|
48
|
+
|
|
49
|
+
width: ${ width };
|
|
50
|
+
height: ${ height };
|
|
51
|
+
`;
|