@linagora/twake-mui 14.1.0 → 14.3.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 +14 -0
- package/dist/components/Filename/Filename.stories.d.ts +7 -0
- package/dist/components/Filename/Filename.stories.js +95 -0
- package/dist/components/Filename/index.d.ts +16 -0
- package/dist/components/Filename/index.js +20 -0
- package/dist/components/PasswordField/PasswordField.stories.d.ts +7 -0
- package/dist/components/PasswordField/PasswordField.stories.js +43 -0
- package/dist/components/PasswordField/index.d.ts +6 -0
- package/dist/components/PasswordField/index.js +28 -0
- package/dist/components/PasswordField/locales/de.json +6 -0
- package/dist/components/PasswordField/locales/en.json +6 -0
- package/dist/components/PasswordField/locales/es.json +6 -0
- package/dist/components/PasswordField/locales/fr.json +6 -0
- package/dist/components/PasswordField/locales/it.json +6 -0
- package/dist/components/PasswordField/locales/ru.json +6 -0
- package/dist/components/PasswordField/locales/vi.json +6 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.js +2 -0
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,17 @@
|
|
|
1
|
+
# @linagora/twake-mui [14.3.0](https://github.com/linagora/twake-ui/compare/@linagora/twake-mui@14.2.0...@linagora/twake-mui@14.3.0) (2026-10-15)
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
### Features
|
|
5
|
+
|
|
6
|
+
* **twake-mui:** Migrate PasswordField from cozy-ui ([5d39ddd](https://github.com/linagora/twake-ui/commit/5d39ddd8c7616e82c9f6c89cabe1a53b6b553864))
|
|
7
|
+
|
|
8
|
+
# @linagora/twake-mui [14.2.0](https://github.com/linagora/twake-ui/compare/@linagora/twake-mui@14.1.0...@linagora/twake-mui@14.2.0) (2026-10-15)
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
### Features
|
|
12
|
+
|
|
13
|
+
* **twake-mui:** Migrate Filename from cozy-ui ([84f4803](https://github.com/linagora/twake-ui/commit/84f4803fedbfc211dabef69717570d75500369b4))
|
|
14
|
+
|
|
1
15
|
# @linagora/twake-mui [14.1.0](https://github.com/linagora/twake-ui/compare/@linagora/twake-mui@14.0.0...@linagora/twake-mui@14.1.0) (2026-10-15)
|
|
2
16
|
|
|
3
17
|
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from '@storybook/react-vite';
|
|
2
|
+
import Filename from './index';
|
|
3
|
+
declare const meta: Meta<typeof Filename>;
|
|
4
|
+
export default meta;
|
|
5
|
+
type Story = StoryObj<typeof meta>;
|
|
6
|
+
export declare const Default: Story;
|
|
7
|
+
export declare const Screenshot: Story;
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import { File, Icon } from '@linagora/twake-icons';
|
|
2
|
+
import { Box, Stack } from '@mui/material';
|
|
3
|
+
import React from 'react';
|
|
4
|
+
import Filename from './index';
|
|
5
|
+
const longName = 'Lacinia condimentum potenti id est tortor dictumst lectus tincidunt hac ultricies, curae mattis nisi neque sodales sagittis dui nulla aliquam turpis eros, finibus ac iaculis dictum et orci elit posuere ex and this is the end';
|
|
6
|
+
const shortName = 'Lacinia condimentum this is the end';
|
|
7
|
+
const path = '/some/folder/and/subfolder';
|
|
8
|
+
const icon = React.createElement(Icon, { icon: File, size: 32 });
|
|
9
|
+
const examples = [
|
|
10
|
+
{
|
|
11
|
+
title: 'Icon, extension and path',
|
|
12
|
+
props: { icon, filename: longName, extension: '.pdf', path }
|
|
13
|
+
},
|
|
14
|
+
{
|
|
15
|
+
title: 'Middle ellipsis',
|
|
16
|
+
props: {
|
|
17
|
+
icon,
|
|
18
|
+
filename: longName,
|
|
19
|
+
extension: '.pdf',
|
|
20
|
+
path,
|
|
21
|
+
midEllipsis: true
|
|
22
|
+
}
|
|
23
|
+
},
|
|
24
|
+
{
|
|
25
|
+
title: 'Without path',
|
|
26
|
+
props: { icon, filename: longName, extension: '.pdf' }
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
title: 'Without path, middle ellipsis',
|
|
30
|
+
props: { icon, filename: longName, extension: '.pdf', midEllipsis: true }
|
|
31
|
+
},
|
|
32
|
+
{
|
|
33
|
+
title: 'Body1 variant',
|
|
34
|
+
props: {
|
|
35
|
+
icon,
|
|
36
|
+
filename: longName,
|
|
37
|
+
extension: '.pdf',
|
|
38
|
+
path,
|
|
39
|
+
variant: 'body1'
|
|
40
|
+
}
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
title: 'Without icon',
|
|
44
|
+
props: { filename: longName, extension: '.pdf', path }
|
|
45
|
+
},
|
|
46
|
+
{
|
|
47
|
+
title: 'Without extension',
|
|
48
|
+
props: { icon, filename: longName, path }
|
|
49
|
+
},
|
|
50
|
+
{
|
|
51
|
+
title: 'Short name',
|
|
52
|
+
props: { icon, filename: shortName, extension: '.pdf', path }
|
|
53
|
+
},
|
|
54
|
+
{
|
|
55
|
+
title: 'Short name without path',
|
|
56
|
+
props: { icon, filename: shortName, extension: '.pdf' }
|
|
57
|
+
}
|
|
58
|
+
];
|
|
59
|
+
const Section = ({ title, children }) => (React.createElement("section", null,
|
|
60
|
+
React.createElement("h3", null, title),
|
|
61
|
+
children));
|
|
62
|
+
const meta = {
|
|
63
|
+
title: 'Filename',
|
|
64
|
+
component: Filename,
|
|
65
|
+
tags: ['autodocs'],
|
|
66
|
+
argTypes: {
|
|
67
|
+
icon: { control: false },
|
|
68
|
+
filename: { control: 'text' },
|
|
69
|
+
extension: { control: 'text' },
|
|
70
|
+
midEllipsis: { control: 'boolean' },
|
|
71
|
+
variant: {
|
|
72
|
+
control: 'select',
|
|
73
|
+
options: ['h6', 'body1', 'body2', 'subtitle1', 'caption']
|
|
74
|
+
},
|
|
75
|
+
path: { control: 'text' }
|
|
76
|
+
}
|
|
77
|
+
};
|
|
78
|
+
export default meta;
|
|
79
|
+
export const Default = {
|
|
80
|
+
args: {
|
|
81
|
+
icon,
|
|
82
|
+
filename: longName,
|
|
83
|
+
extension: '.pdf',
|
|
84
|
+
midEllipsis: false,
|
|
85
|
+
variant: 'h6',
|
|
86
|
+
path
|
|
87
|
+
},
|
|
88
|
+
render: args => (React.createElement(Box, { sx: { maxWidth: 400 } },
|
|
89
|
+
React.createElement(Filename, { ...args })))
|
|
90
|
+
};
|
|
91
|
+
export const Screenshot = {
|
|
92
|
+
tags: ['argos'],
|
|
93
|
+
render: () => (React.createElement(Stack, { spacing: 4, sx: { maxWidth: 400 } }, examples.map(({ title, props }) => (React.createElement(Section, { key: title, title: title },
|
|
94
|
+
React.createElement(Filename, { ...props }))))))
|
|
95
|
+
};
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { TypographyProps } from '@mui/material';
|
|
2
|
+
import React from 'react';
|
|
3
|
+
export interface FilenameProps {
|
|
4
|
+
icon?: React.ReactNode;
|
|
5
|
+
/** Folder or file name */
|
|
6
|
+
filename?: string;
|
|
7
|
+
/** File extension, rendered in the secondary text color */
|
|
8
|
+
extension?: string;
|
|
9
|
+
/** Truncates the filename in its middle instead of its end */
|
|
10
|
+
midEllipsis?: boolean;
|
|
11
|
+
variant?: TypographyProps['variant'];
|
|
12
|
+
/** Shown on a second line, under the name */
|
|
13
|
+
path?: React.ReactNode;
|
|
14
|
+
}
|
|
15
|
+
declare const Filename: React.FC<FilenameProps>;
|
|
16
|
+
export default Filename;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { Box, Typography } from '@mui/material';
|
|
2
|
+
import React from 'react';
|
|
3
|
+
import MidEllipsis from '../MidEllipsis';
|
|
4
|
+
const NameAndExtension = ({ filename, extension, midEllipsis, variant }) => (React.createElement(React.Fragment, null,
|
|
5
|
+
filename && (React.createElement(Typography, { variant: variant, component: "span", noWrap: true }, midEllipsis ? React.createElement(MidEllipsis, { text: filename }) : filename)),
|
|
6
|
+
extension && (React.createElement(Typography, { variant: variant, component: "span", color: "textSecondary" }, extension))));
|
|
7
|
+
const Filename = ({ icon, filename, extension, midEllipsis = false, variant = 'h6', path }) => {
|
|
8
|
+
const nameAndExtension = (React.createElement(NameAndExtension, { filename: filename, extension: extension, midEllipsis: midEllipsis, variant: variant }));
|
|
9
|
+
const iconBox = icon && (React.createElement(Box, { className: "u-flex u-pos-relative u-mr-1", sx: path ? { float: 'left', top: 4 } : undefined }, icon));
|
|
10
|
+
if (!path) {
|
|
11
|
+
return (React.createElement("div", { className: "u-flex u-flex-items-center" },
|
|
12
|
+
iconBox,
|
|
13
|
+
nameAndExtension));
|
|
14
|
+
}
|
|
15
|
+
return (React.createElement(React.Fragment, null,
|
|
16
|
+
iconBox,
|
|
17
|
+
React.createElement("div", { className: "u-flex" }, nameAndExtension),
|
|
18
|
+
React.createElement(Typography, { variant: "body2", component: "div", noWrap: true }, path)));
|
|
19
|
+
};
|
|
20
|
+
export default Filename;
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { TextField } from '@mui/material';
|
|
2
|
+
import type { Meta, StoryObj } from '@storybook/react-vite';
|
|
3
|
+
declare const meta: Meta<typeof TextField>;
|
|
4
|
+
export default meta;
|
|
5
|
+
type Story = StoryObj<typeof meta>;
|
|
6
|
+
export declare const Default: Story;
|
|
7
|
+
export declare const Screenshot: Story;
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { Stack } from '@mui/material';
|
|
2
|
+
import React from 'react';
|
|
3
|
+
import PasswordField from './index';
|
|
4
|
+
// TextFieldProps is a union, which Storybook cannot infer args from
|
|
5
|
+
const meta = {
|
|
6
|
+
title: 'PasswordField',
|
|
7
|
+
component: PasswordField,
|
|
8
|
+
parameters: { layout: 'centered' },
|
|
9
|
+
tags: ['autodocs'],
|
|
10
|
+
argTypes: {
|
|
11
|
+
label: { control: 'text' },
|
|
12
|
+
placeholder: { control: 'text' },
|
|
13
|
+
helperText: { control: 'text' },
|
|
14
|
+
size: { control: 'select', options: ['small', 'medium'] },
|
|
15
|
+
disabled: { control: 'boolean' },
|
|
16
|
+
error: { control: 'boolean' },
|
|
17
|
+
fullWidth: { control: 'boolean' }
|
|
18
|
+
}
|
|
19
|
+
};
|
|
20
|
+
export default meta;
|
|
21
|
+
export const Default = {
|
|
22
|
+
args: {
|
|
23
|
+
defaultValue: 'Cl4ude€st1Nu@ge'
|
|
24
|
+
}
|
|
25
|
+
};
|
|
26
|
+
const Row = ({ title, children }) => (React.createElement("section", null,
|
|
27
|
+
React.createElement("h3", { style: { marginBottom: '12px' } }, title),
|
|
28
|
+
React.createElement(Stack, { direction: "row", spacing: 2, useFlexGap: true, sx: { flexWrap: 'wrap' } }, children)));
|
|
29
|
+
// Visual Regression - Combined view for Argos testing
|
|
30
|
+
export const Screenshot = {
|
|
31
|
+
tags: ['argos'],
|
|
32
|
+
render: () => (React.createElement(Stack, { spacing: 4 },
|
|
33
|
+
React.createElement(Row, { title: "Default" },
|
|
34
|
+
React.createElement(PasswordField, { defaultValue: "Cl4ude\u20ACst1Nu@ge" }),
|
|
35
|
+
React.createElement(PasswordField, { label: "Password", defaultValue: "Cl4ude\u20ACst1Nu@ge" }),
|
|
36
|
+
React.createElement(PasswordField, { label: "Password" })),
|
|
37
|
+
React.createElement(Row, { title: "Sizes" },
|
|
38
|
+
React.createElement(PasswordField, { size: "small", defaultValue: "Cl4ude\u20ACst1Nu@ge" }),
|
|
39
|
+
React.createElement(PasswordField, { size: "medium", defaultValue: "Cl4ude\u20ACst1Nu@ge" })),
|
|
40
|
+
React.createElement(Row, { title: "States" },
|
|
41
|
+
React.createElement(PasswordField, { label: "Disabled", disabled: true, defaultValue: "Cl4ude\u20ACst1Nu@ge" }),
|
|
42
|
+
React.createElement(PasswordField, { label: "Error", error: true, helperText: "Wrong password", defaultValue: "Cl4ude\u20ACst1Nu@ge" }))))
|
|
43
|
+
};
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { TextFieldProps } from '@mui/material';
|
|
2
|
+
import React from 'react';
|
|
3
|
+
export type PasswordFieldProps = TextFieldProps;
|
|
4
|
+
/** Password field with a button to show or hide its value */
|
|
5
|
+
declare const PasswordField: ({ slotProps, ...props }: PasswordFieldProps) => React.ReactElement;
|
|
6
|
+
export default PasswordField;
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { Eye, EyeClosed, Icon } from '@linagora/twake-icons';
|
|
2
|
+
import { IconButton, InputAdornment, TextField } from '@mui/material';
|
|
3
|
+
import { mergeSlotProps } from '@mui/material/utils';
|
|
4
|
+
import React, { useState } from 'react';
|
|
5
|
+
import { useExtendI18n, useI18n } from 'twake-i18n';
|
|
6
|
+
import de from './locales/de.json';
|
|
7
|
+
import en from './locales/en.json';
|
|
8
|
+
import es from './locales/es.json';
|
|
9
|
+
import fr from './locales/fr.json';
|
|
10
|
+
import it from './locales/it.json';
|
|
11
|
+
import ru from './locales/ru.json';
|
|
12
|
+
import vi from './locales/vi.json';
|
|
13
|
+
const locales = { de, en, es, fr, it, ru, vi };
|
|
14
|
+
/** Password field with a button to show or hide its value */
|
|
15
|
+
const PasswordField = ({ slotProps, ...props }) => {
|
|
16
|
+
useExtendI18n(locales);
|
|
17
|
+
const { t } = useI18n();
|
|
18
|
+
const [hidden, setHidden] = useState(true);
|
|
19
|
+
return (React.createElement(TextField, { type: hidden ? 'password' : 'text', ...props, slotProps: {
|
|
20
|
+
...slotProps,
|
|
21
|
+
input: mergeSlotProps(slotProps?.input, {
|
|
22
|
+
endAdornment: (React.createElement(InputAdornment, { position: "end" },
|
|
23
|
+
React.createElement(IconButton, { "aria-label": hidden ? t('PasswordField.show') : t('PasswordField.hide'), disabled: props.disabled, onClick: () => setHidden(current => !current), edge: "end" },
|
|
24
|
+
React.createElement(Icon, { icon: hidden ? Eye : EyeClosed }))))
|
|
25
|
+
})
|
|
26
|
+
} }));
|
|
27
|
+
};
|
|
28
|
+
export default PasswordField;
|
package/dist/index.d.ts
CHANGED
|
@@ -46,6 +46,7 @@ export { default as DropdownButton } from './components/DropdownButton';
|
|
|
46
46
|
export { default as DropdownText } from './components/DropdownText';
|
|
47
47
|
export { Empty, EmptySubTitle } from './components/Empty';
|
|
48
48
|
export { ExtendableFab } from './components/ExtendableFab';
|
|
49
|
+
export { default as Filename } from './components/Filename';
|
|
49
50
|
export { default as ListItem } from './components/ListItem';
|
|
50
51
|
export { default as ListItemButton } from './components/ListItemButton';
|
|
51
52
|
export { default as ListItemText } from './components/ListItemText';
|
|
@@ -71,6 +72,7 @@ export { NavIcon } from './components/NavIcon';
|
|
|
71
72
|
export { default as NavText } from './components/NavText';
|
|
72
73
|
export { NavDesktopLimiter } from './components/NavDesktopLimiter';
|
|
73
74
|
export { NavDesktopDropdown } from './components/NavDesktopDropdown';
|
|
75
|
+
export { default as PasswordField } from './components/PasswordField';
|
|
74
76
|
export { nameToColor, supportedColors, getInitials } from './components/Avatar/helpers';
|
|
75
77
|
export { COLORS } from './components/ColorList/helpers';
|
|
76
78
|
export { default as AccordionExpandIcon } from './components/AccordionExpandIcon';
|
|
@@ -125,6 +127,7 @@ export type { EmptyProps, EmptyIconSize, EmptyComponentsProps } from './componen
|
|
|
125
127
|
export type { DropdownButtonProps } from './components/DropdownButton';
|
|
126
128
|
export type { DropdownTextProps, DropdownTextVariant } from './components/DropdownText';
|
|
127
129
|
export type { ExtendableFabProps, ScrollOptions } from './components/ExtendableFab';
|
|
130
|
+
export type { FilenameProps } from './components/Filename';
|
|
128
131
|
export type { ListItemProps, ListItemGutters, ListItemSize } from './components/ListItem';
|
|
129
132
|
export type { ListItemButtonProps } from './components/ListItemButton';
|
|
130
133
|
export type { ListItemTextProps } from './components/ListItemText';
|
|
@@ -147,6 +150,7 @@ export type { NavDropdownProps } from './components/NavLink/NavDropdown';
|
|
|
147
150
|
export type { NavIconProps } from './components/NavIcon';
|
|
148
151
|
export type { NavTextProps } from './components/NavText';
|
|
149
152
|
export type { NavDesktopLimiterProps } from './components/NavDesktopLimiter';
|
|
153
|
+
export type { PasswordFieldProps } from './components/PasswordField';
|
|
150
154
|
export type { NavDesktopDropdownProps } from './components/NavDesktopDropdown';
|
|
151
155
|
export type { VirtualizedTableProps, VirtualizedTableColumn, VirtualizedTableRow } from './components/VirtualizedTable';
|
|
152
156
|
export type { Breakpoints } from './hooks/useBreakpoints';
|
package/dist/index.js
CHANGED
|
@@ -49,6 +49,7 @@ export { default as DropdownButton } from './components/DropdownButton';
|
|
|
49
49
|
export { default as DropdownText } from './components/DropdownText';
|
|
50
50
|
export { Empty, EmptySubTitle } from './components/Empty';
|
|
51
51
|
export { ExtendableFab } from './components/ExtendableFab';
|
|
52
|
+
export { default as Filename } from './components/Filename';
|
|
52
53
|
export { default as ListItem } from './components/ListItem';
|
|
53
54
|
export { default as ListItemButton } from './components/ListItemButton';
|
|
54
55
|
export { default as ListItemText } from './components/ListItemText';
|
|
@@ -74,6 +75,7 @@ export { NavIcon } from './components/NavIcon';
|
|
|
74
75
|
export { default as NavText } from './components/NavText';
|
|
75
76
|
export { NavDesktopLimiter } from './components/NavDesktopLimiter';
|
|
76
77
|
export { NavDesktopDropdown } from './components/NavDesktopDropdown';
|
|
78
|
+
export { default as PasswordField } from './components/PasswordField';
|
|
77
79
|
export { nameToColor, supportedColors, getInitials } from './components/Avatar/helpers';
|
|
78
80
|
export { COLORS } from './components/ColorList/helpers';
|
|
79
81
|
export { default as AccordionExpandIcon } from './components/AccordionExpandIcon';
|