@linagora/twake-mui 7.1.0 → 9.0.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.
Files changed (82) hide show
  1. package/CHANGELOG.md +58 -0
  2. package/dist/components/Apptitle/index.js +9 -5
  3. package/dist/components/Avatar/Avatar.stories.js +58 -37
  4. package/dist/components/Avatar/helpers.d.ts +0 -28
  5. package/dist/components/Avatar/helpers.js +0 -28
  6. package/dist/components/Avatar/index.d.ts +4 -6
  7. package/dist/components/Avatar/index.js +24 -31
  8. package/dist/components/Button/index.d.ts +12 -0
  9. package/dist/components/Button/index.js +8 -0
  10. package/dist/{stories → components/Dialog}/Dialog.stories.d.ts +2 -2
  11. package/dist/components/Dialog/Dialog.stories.js +81 -0
  12. package/dist/components/Dialog/index.d.ts +9 -0
  13. package/dist/components/Dialog/index.js +9 -0
  14. package/dist/components/Nav/index.d.ts +8 -0
  15. package/dist/components/Nav/index.js +14 -0
  16. package/dist/components/NavDesktopDropdown/index.d.ts +8 -0
  17. package/dist/components/NavDesktopDropdown/index.js +24 -0
  18. package/dist/components/NavDesktopLimiter/index.d.ts +6 -0
  19. package/dist/components/NavDesktopLimiter/index.js +31 -0
  20. package/dist/components/NavDesktopLimiter/locales/en.json +6 -0
  21. package/dist/components/NavDesktopLimiter/locales/fr.json +6 -0
  22. package/dist/components/NavDesktopLimiter/locales/ru.json +6 -0
  23. package/dist/components/NavDesktopLimiter/locales/vi.json +6 -0
  24. package/dist/components/NavIcon/index.d.ts +7 -0
  25. package/dist/components/NavIcon/index.js +17 -0
  26. package/dist/components/NavItem/index.d.ts +8 -0
  27. package/dist/components/NavItem/index.js +29 -0
  28. package/dist/components/NavLink/index.d.ts +3 -0
  29. package/dist/components/NavLink/index.js +36 -0
  30. package/dist/components/NavText/index.d.ts +7 -0
  31. package/dist/components/NavText/index.js +14 -0
  32. package/dist/components/Sidebar/Sidebar.stories.d.ts +7 -0
  33. package/dist/components/Sidebar/Sidebar.stories.js +57 -0
  34. package/dist/components/Sidebar/index.d.ts +7 -0
  35. package/dist/components/Sidebar/index.js +21 -0
  36. package/dist/components/Switch/Switch.stories.d.ts +7 -0
  37. package/dist/components/Switch/Switch.stories.js +58 -0
  38. package/dist/components/Switch/index.d.ts +9 -0
  39. package/dist/components/Switch/index.js +8 -0
  40. package/dist/components/Tabs/Tabs.stories.d.ts +7 -0
  41. package/dist/components/Tabs/Tabs.stories.js +52 -0
  42. package/dist/components/Tabs/index.d.ts +10 -0
  43. package/dist/components/Tabs/index.js +5 -0
  44. package/dist/components/ThemeProvider/index.js +9 -10
  45. package/dist/components/ThemeProvider/types.d.ts +6 -0
  46. package/dist/index.d.ts +26 -1
  47. package/dist/index.js +13 -1
  48. package/dist/lib/makePalette.d.ts +1 -1
  49. package/dist/lib/makePalette.js +3 -1
  50. package/dist/lib/makeShadows.d.ts +1 -1
  51. package/dist/lib/makeShadows.js +2 -2
  52. package/dist/lib/makeTheme.d.ts +3 -2
  53. package/dist/lib/makeTheme.js +15 -16
  54. package/dist/lib/overrides.d.ts +2 -0
  55. package/dist/lib/overrides.js +1027 -0
  56. package/dist/lib/types.d.ts +14 -0
  57. package/dist/stories/Alert.stories.js +57 -53
  58. package/dist/stories/Badge.stories.d.ts +7 -0
  59. package/dist/stories/Badge.stories.js +84 -0
  60. package/dist/stories/Button.stories.d.ts +3 -3
  61. package/dist/stories/Button.stories.js +67 -58
  62. package/dist/stories/{Selection.stories.d.ts → Checkbox.stories.d.ts} +1 -1
  63. package/dist/stories/Checkbox.stories.js +59 -0
  64. package/dist/stories/Divider.stories.d.ts +7 -0
  65. package/dist/stories/Divider.stories.js +56 -0
  66. package/dist/stories/Radio.stories.d.ts +7 -0
  67. package/dist/stories/Radio.stories.js +60 -0
  68. package/dist/stories/Snackbar.stories.d.ts +7 -0
  69. package/dist/stories/Snackbar.stories.js +60 -0
  70. package/dist/stories/{Input.stories.d.ts → TextField.stories.d.ts} +1 -1
  71. package/dist/stories/TextField.stories.js +86 -0
  72. package/dist/stories/ThemePlayground.stories.js +20 -113
  73. package/dist/stories/Typography.stories.d.ts +1 -1
  74. package/dist/stories/Typography.stories.js +48 -34
  75. package/package.json +5 -2
  76. package/dist/lib/darkOverrides.d.ts +0 -2
  77. package/dist/lib/darkOverrides.js +0 -3
  78. package/dist/lib/lightOverrides.d.ts +0 -2
  79. package/dist/lib/lightOverrides.js +0 -551
  80. package/dist/stories/Dialog.stories.js +0 -40
  81. package/dist/stories/Input.stories.js +0 -41
  82. package/dist/stories/Selection.stories.js +0 -37
@@ -0,0 +1,7 @@
1
+ import { IconProps } from '@linagora/twake-icons';
2
+ import { ListItemIconProps } from '@mui/material';
3
+ import React from 'react';
4
+ export interface NavIconProps extends ListItemIconProps {
5
+ icon: IconProps['icon'];
6
+ }
7
+ export declare const NavIcon: ({ icon, ...props }: NavIconProps) => React.ReactElement;
@@ -0,0 +1,17 @@
1
+ import { Icon } from '@linagora/twake-icons';
2
+ import { ListItemIcon } from '@mui/material';
3
+ import { styled } from '@mui/material/styles';
4
+ import React from 'react';
5
+ const NavIconRoot = styled(ListItemIcon)(({ theme }) => ({
6
+ minWidth: 0,
7
+ marginRight: 12,
8
+ color: theme.vars.palette.text.primary,
9
+ [theme.breakpoints.down('lg')]: {
10
+ display: 'block',
11
+ marginRight: 0,
12
+ color: theme.vars.palette.text.secondary,
13
+ '& svg': { margin: '4px auto 5px', width: 16, height: 16 }
14
+ }
15
+ }));
16
+ export const NavIcon = ({ icon, ...props }) => (React.createElement(NavIconRoot, { ...props },
17
+ React.createElement(Icon, { icon: icon, "aria-hidden": "true", focusable: "false" })));
@@ -0,0 +1,8 @@
1
+ import { Theme } from '@mui/material/styles';
2
+ import React from 'react';
3
+ export declare const NavItem: import("@emotion/styled").StyledComponent<import("@mui/material").ListItemOwnProps & import("@mui/material/OverridableComponent").CommonProps & Omit<Omit<React.DetailedHTMLProps<React.LiHTMLAttributes<HTMLLIElement>, HTMLLIElement>, "ref"> & {
4
+ ref?: ((instance: HTMLLIElement | null) => void) | React.RefObject<HTMLLIElement> | null | undefined;
5
+ }, "style" | "className" | "children" | "classes" | "sx" | "alignItems" | "dense" | "divider" | "slotProps" | "slots" | "disableGutters" | "disablePadding" | "secondaryAction"> & import("@mui/system").MUIStyledCommonProps<Theme> & {
6
+ secondary?: boolean;
7
+ }, {}, {}>;
8
+ export type NavItemProps = React.ComponentProps<typeof NavItem>;
@@ -0,0 +1,29 @@
1
+ import { ListItem, listItemButtonClasses } from '@mui/material';
2
+ import { styled } from '@mui/material/styles';
3
+ export const NavItem = styled(ListItem, {
4
+ shouldForwardProp: prop => prop !== 'secondary'
5
+ })(({ theme, secondary }) => ({
6
+ padding: 0,
7
+ height: 36,
8
+ [theme.breakpoints.down('lg')]: {
9
+ display: 'block',
10
+ height: 'auto',
11
+ margin: '0 12px',
12
+ flex: '0 0 40px'
13
+ },
14
+ ...(secondary && {
15
+ height: 'auto',
16
+ margin: '3px 0',
17
+ [theme.breakpoints.down('lg')]: { display: 'none' },
18
+ [`& .${listItemButtonClasses.root}`]: {
19
+ margin: '0 16px 0 2.8rem',
20
+ padding: '8px 16px',
21
+ height: 'auto',
22
+ fontSize: theme.typography.pxToRem(14),
23
+ [`&.${listItemButtonClasses.selected}, &.active`]: {
24
+ color: theme.vars.palette.secondary.contrastText,
25
+ backgroundColor: theme.vars.palette.secondary.main
26
+ }
27
+ }
28
+ })
29
+ }));
@@ -0,0 +1,3 @@
1
+ import { ListItemButton, ListItemButtonProps } from '@mui/material';
2
+ export type NavLinkProps = ListItemButtonProps;
3
+ export declare const NavLink: typeof ListItemButton;
@@ -0,0 +1,36 @@
1
+ import { ListItemButton, listItemButtonClasses, listItemIconClasses } from '@mui/material';
2
+ import { styled } from '@mui/material/styles';
3
+ // Cast keeps ListItemButton's `component` generic (react-router NavLink etc.)
4
+ export const NavLink = styled(ListItemButton)(({ theme }) => ({
5
+ margin: '0 16px',
6
+ padding: '0 8px',
7
+ height: '100%',
8
+ borderRadius: 8,
9
+ lineHeight: 1.375,
10
+ color: theme.vars.palette.text.primary,
11
+ [`&.${listItemButtonClasses.selected}, &.active`]: {
12
+ color: theme.vars.palette.primary.main,
13
+ backgroundColor: theme.vars.palette.action.selected,
14
+ '&:hover': { backgroundColor: theme.vars.palette.action.selected },
15
+ [`& .${listItemIconClasses.root}`]: {
16
+ color: theme.vars.palette.primary.main
17
+ }
18
+ },
19
+ [theme.breakpoints.down('lg')]: {
20
+ display: 'block',
21
+ height: 'auto',
22
+ margin: 0,
23
+ padding: 0,
24
+ textAlign: 'center',
25
+ fontSize: theme.typography.pxToRem(11),
26
+ lineHeight: '12px',
27
+ color: theme.vars.palette.text.secondary,
28
+ [`&.${listItemButtonClasses.selected}, &.active`]: {
29
+ color: theme.vars.palette.text.primary,
30
+ backgroundColor: 'transparent',
31
+ [`& .${listItemIconClasses.root}`]: {
32
+ color: theme.vars.palette.text.primary
33
+ }
34
+ }
35
+ }
36
+ }));
@@ -0,0 +1,7 @@
1
+ import { SxProps } from '@mui/material';
2
+ import { Theme } from '@mui/material/styles';
3
+ import React from 'react';
4
+ export interface NavTextProps extends React.ComponentPropsWithoutRef<'span'> {
5
+ sx?: SxProps<Theme>;
6
+ }
7
+ export declare const NavText: React.FC<NavTextProps>;
@@ -0,0 +1,14 @@
1
+ import { styled } from '@mui/material/styles';
2
+ // Explicit annotation: declaration emit for styled('span') otherwise
3
+ // widens the element props to the whole JSX.IntrinsicElements map.
4
+ export const NavText = styled('span')(({ theme }) => ({
5
+ fontSize: theme.typography.pxToRem(14),
6
+ fontWeight: 500,
7
+ letterSpacing: '.15px',
8
+ [theme.breakpoints.down('lg')]: {
9
+ display: 'block',
10
+ textAlign: 'center',
11
+ whiteSpace: 'nowrap',
12
+ fontSize: theme.typography.pxToRem(12)
13
+ }
14
+ }));
@@ -0,0 +1,7 @@
1
+ import type { Meta, StoryObj } from '@storybook/react-vite';
2
+ import { Sidebar } from './index';
3
+ declare const meta: Meta<typeof Sidebar>;
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,57 @@
1
+ import { Check, Download, Warn } from '@linagora/twake-icons';
2
+ import { Box, Typography } from '@mui/material';
3
+ import React, { useState } from 'react';
4
+ import { Nav } from '../Nav';
5
+ import { NavDesktopDropdown } from '../NavDesktopDropdown';
6
+ import { NavDesktopLimiter } from '../NavDesktopLimiter';
7
+ import { NavIcon } from '../NavIcon';
8
+ import { NavItem } from '../NavItem';
9
+ import { NavLink } from '../NavLink';
10
+ import { NavText } from '../NavText';
11
+ import { Sidebar } from './index';
12
+ const SidebarDemo = (props) => {
13
+ const [active, setActive] = useState(['Section 1', 'Subsection 1']);
14
+ const makeProps = (route) => ({
15
+ selected: active.slice(0, route.length).join('/') === route.join('/'),
16
+ onClick: () => setActive(route)
17
+ });
18
+ return (React.createElement(Box, { sx: { display: 'flex' } },
19
+ React.createElement(Sidebar, { ...props },
20
+ React.createElement(Nav, null,
21
+ React.createElement(NavItem, null,
22
+ React.createElement(NavLink, { ...makeProps(['Section 1']) },
23
+ React.createElement(NavIcon, { icon: Warn }),
24
+ React.createElement(NavText, null, "Section 1"))),
25
+ React.createElement(NavDesktopLimiter, null, Array.from(Array(10).keys()).map(i => (React.createElement(NavItem, { secondary: true, key: i },
26
+ React.createElement(NavLink, { ...makeProps(['Section 1', `Subsection ${i}`]) },
27
+ React.createElement(NavText, null,
28
+ "Subsection ",
29
+ i)))))),
30
+ React.createElement(NavItem, null,
31
+ React.createElement(NavLink, { ...makeProps(['Section 2']) },
32
+ React.createElement(NavIcon, { icon: Check }),
33
+ React.createElement(NavText, null, "Section 2"))),
34
+ React.createElement(NavItem, null,
35
+ React.createElement(NavLink, { ...makeProps(['Section 3']) },
36
+ React.createElement(NavIcon, { icon: Download }),
37
+ React.createElement(NavText, null, "Section 3"))),
38
+ React.createElement(NavDesktopDropdown, { label: "Section 4" }, Array.from(Array(6).keys()).map(i => (React.createElement(NavItem, { secondary: true, key: i },
39
+ React.createElement(NavLink, { ...makeProps(['Section 4', `Subsection ${i}`]) },
40
+ React.createElement(NavText, null,
41
+ "Subsection ",
42
+ i)))))))),
43
+ React.createElement(Box, { sx: { flex: 1, p: 2 } },
44
+ React.createElement(Typography, { variant: "h5" }, active.join(' / ')))));
45
+ };
46
+ const meta = {
47
+ title: 'Sidebar',
48
+ component: Sidebar,
49
+ tags: ['autodocs'],
50
+ render: args => React.createElement(SidebarDemo, { ...args })
51
+ };
52
+ export default meta;
53
+ export const Default = {};
54
+ // Visual Regression - Combined view for Argos testing
55
+ export const Screenshot = {
56
+ tags: ['argos']
57
+ };
@@ -0,0 +1,7 @@
1
+ import { SxProps } from '@mui/material';
2
+ import { Theme } from '@mui/material/styles';
3
+ import React from 'react';
4
+ export interface SidebarProps extends React.ComponentPropsWithoutRef<'aside'> {
5
+ sx?: SxProps<Theme>;
6
+ }
7
+ export declare const Sidebar: React.FC<SidebarProps>;
@@ -0,0 +1,21 @@
1
+ import { styled } from '@mui/material/styles';
2
+ export const Sidebar = styled('aside')(({ theme }) => ({
3
+ width: 236,
4
+ flex: '0 0 auto',
5
+ display: 'flex',
6
+ flexDirection: 'column',
7
+ overflowX: 'hidden',
8
+ overflowY: 'auto',
9
+ backgroundColor: theme.vars.palette.background.default,
10
+ [theme.breakpoints.down('lg')]: {
11
+ position: 'fixed',
12
+ bottom: 0,
13
+ left: 0,
14
+ width: '100%',
15
+ height: 52,
16
+ boxSizing: 'content-box',
17
+ display: 'block',
18
+ borderTop: `1px solid ${theme.vars.palette.divider}`,
19
+ zIndex: theme.zIndex.appBar
20
+ }
21
+ }));
@@ -0,0 +1,7 @@
1
+ import type { Meta, StoryObj } from '@storybook/react-vite';
2
+ import { Switch } from './index';
3
+ declare const meta: Meta<typeof Switch>;
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,58 @@
1
+ import { Check } from '@linagora/twake-icons';
2
+ import { Divider, FormControlLabel, FormGroup, Stack, Typography } from '@mui/material';
3
+ import React from 'react';
4
+ import { Switch } from './index';
5
+ const colors = ['primary', 'secondary', 'success', 'default'];
6
+ const meta = {
7
+ title: 'Switch',
8
+ component: Switch,
9
+ parameters: { layout: 'centered' },
10
+ tags: ['autodocs'],
11
+ argTypes: {
12
+ color: { control: 'select', options: colors },
13
+ checked: { control: 'boolean' },
14
+ disabled: { control: 'boolean' },
15
+ icon: { control: 'boolean', mapping: { true: Check, false: undefined } }
16
+ }
17
+ };
18
+ export default meta;
19
+ const StateSwitch = ({ defaultChecked, ...props }) => {
20
+ const [checked, setChecked] = React.useState(!!defaultChecked);
21
+ return (React.createElement(Switch, { checked: checked, onChange: event => setChecked(event.target.checked), ...props }));
22
+ };
23
+ export const Default = {
24
+ args: { color: 'primary' },
25
+ render: args => React.createElement(StateSwitch, { defaultChecked: true, ...args })
26
+ };
27
+ const Labelled = ({ labelPlacement }) => (React.createElement(Stack, { spacing: 1 },
28
+ React.createElement(Typography, { variant: "h4" }, "With labels"),
29
+ React.createElement(FormGroup, { row: true },
30
+ React.createElement(FormControlLabel, { control: React.createElement(Switch, { color: "primary" }), label: "With label", labelPlacement: labelPlacement }),
31
+ React.createElement(FormControlLabel, { control: React.createElement(Switch, { color: "primary", checked: true }), label: "With label - checked", labelPlacement: labelPlacement })),
32
+ React.createElement(Typography, { variant: "h5" }, "With disable"),
33
+ colors.map(color => (React.createElement(FormGroup, { key: color, row: true },
34
+ React.createElement(FormControlLabel, { control: React.createElement(Switch, { color: color, disabled: true }), label: color, labelPlacement: labelPlacement }),
35
+ React.createElement(FormControlLabel, { control: React.createElement(Switch, { color: color, checked: true, disabled: true }), label: `${color} - checked`, labelPlacement: labelPlacement })))),
36
+ React.createElement(FormGroup, { row: true },
37
+ React.createElement(FormControlLabel, { control: React.createElement(Switch, { color: "primary", icon: Check, disabled: true }), label: "primary with icon", labelPlacement: labelPlacement }),
38
+ React.createElement(FormControlLabel, { control: React.createElement(Switch, { color: "primary", icon: Check, checked: true, disabled: true }), label: "primary with icon - checked", labelPlacement: labelPlacement }))));
39
+ // Visual Regression - Every example of the cozy-ui Switch doc
40
+ export const Screenshot = {
41
+ tags: ['argos'],
42
+ render: () => (React.createElement(Stack, { spacing: 2 },
43
+ React.createElement("section", null,
44
+ React.createElement("h3", { style: { marginBottom: '12px' } }, "Colors, with icon"),
45
+ colors.map(color => (React.createElement(Stack, { key: color, direction: "row", sx: { alignItems: 'center' } },
46
+ React.createElement(Typography, { sx: { width: 96 } },
47
+ color,
48
+ ":"),
49
+ React.createElement(Switch, { color: color, icon: Check }),
50
+ React.createElement(Switch, { color: color, icon: Check, checked: true }))))),
51
+ React.createElement(Divider, null),
52
+ React.createElement("section", null,
53
+ React.createElement(Labelled, null)),
54
+ React.createElement(Divider, null),
55
+ React.createElement("section", null,
56
+ React.createElement("h3", { style: { marginBottom: '12px' } }, "Label before"),
57
+ React.createElement(Labelled, { labelPlacement: "start" }))))
58
+ };
@@ -0,0 +1,9 @@
1
+ import { IconProps } from '@linagora/twake-icons';
2
+ import { SwitchProps as MuiSwitchProps } from '@mui/material';
3
+ import React from 'react';
4
+ export interface SwitchProps extends Omit<MuiSwitchProps, 'icon' | 'checkedIcon'> {
5
+ /** A twake icon drawn inside the thumb */
6
+ icon?: IconProps['icon'];
7
+ }
8
+ export declare const Switch: React.FC<SwitchProps>;
9
+ export default Switch;
@@ -0,0 +1,8 @@
1
+ import { Icon } from '@linagora/twake-icons';
2
+ import { Switch as MuiSwitch } from '@mui/material';
3
+ import React from 'react';
4
+ export const Switch = ({ icon, ...props }) => {
5
+ const thumb = (React.createElement("span", { className: "switchThumb" }, !!icon && React.createElement(Icon, { icon: icon, size: 14 })));
6
+ return React.createElement(MuiSwitch, { icon: thumb, checkedIcon: thumb, ...props });
7
+ };
8
+ export default Switch;
@@ -0,0 +1,7 @@
1
+ import type { Meta, StoryObj } from '@storybook/react-vite';
2
+ import { Tabs } from './index';
3
+ declare const meta: Meta<typeof Tabs>;
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,52 @@
1
+ import { Stack, Tab } from '@mui/material';
2
+ import React from 'react';
3
+ import { Tabs } from './index';
4
+ const variants = ['standard', 'fullWidth', 'scrollable'];
5
+ const meta = {
6
+ title: 'Tabs',
7
+ component: Tabs,
8
+ parameters: { layout: 'centered' },
9
+ tags: ['autodocs'],
10
+ argTypes: {
11
+ variant: { control: 'select', options: variants },
12
+ narrowed: { control: 'boolean' },
13
+ segmented: { control: 'boolean' },
14
+ centered: { control: 'boolean' }
15
+ }
16
+ };
17
+ export default meta;
18
+ const Example = props => {
19
+ const [value, setValue] = React.useState(0);
20
+ const scrollable = props.variant === 'scrollable';
21
+ return (React.createElement(Tabs, { value: value, "aria-label": "simple tabs example", onChange: (_event, newValue) => setValue(newValue), ...props },
22
+ React.createElement(Tab, { label: "Item One", id: "simple-tab-0", "aria-controls": "simple-tabpanel-0" }),
23
+ React.createElement(Tab, { label: "Item Two", id: "simple-tab-1", "aria-controls": "simple-tabpanel-1" }),
24
+ React.createElement(Tab, { label: "Item Disabled", id: "simple-tab-3", "aria-controls": "simple-tabpanel-3", disabled: true }),
25
+ React.createElement(Tab, { label: "Item Three", id: "simple-tab-2", "aria-controls": "simple-tabpanel-2" }),
26
+ scrollable && React.createElement(Tab, { label: "Item Four", id: "simple-tab-4" }),
27
+ scrollable && React.createElement(Tab, { label: "Item Five", id: "simple-tab-5" }),
28
+ scrollable && React.createElement(Tab, { label: "Item Six", id: "simple-tab-6" })));
29
+ };
30
+ export const Default = {
31
+ args: { variant: 'standard' },
32
+ render: args => React.createElement(Example, { ...args })
33
+ };
34
+ // Visual Regression - Every example of the cozy-ui Tabs doc
35
+ export const Screenshot = {
36
+ tags: ['argos'],
37
+ render: () => (React.createElement(Stack, { spacing: 4, sx: { width: 800 } },
38
+ React.createElement("section", null,
39
+ React.createElement("h3", { style: { marginBottom: '12px' } }, "Default"),
40
+ React.createElement(Example, null)),
41
+ React.createElement("section", null,
42
+ React.createElement("h3", { style: { marginBottom: '12px' } }, "Narrowed"),
43
+ React.createElement(Example, { narrowed: true })),
44
+ React.createElement("section", null,
45
+ React.createElement("h3", { style: { marginBottom: '12px' } }, "Segmented"),
46
+ React.createElement(Example, { segmented: true })),
47
+ variants.map(variant => (React.createElement("section", { key: variant },
48
+ React.createElement("h3", { style: { marginBottom: '12px' } }, variant),
49
+ React.createElement(Stack, { spacing: 4 },
50
+ React.createElement(Example, { variant: variant }),
51
+ React.createElement(Example, { variant: variant, segmented: true })))))))
52
+ };
@@ -0,0 +1,10 @@
1
+ import { TabsProps as MuiTabsProps } from '@mui/material';
2
+ import React from 'react';
3
+ export interface TabsProps extends MuiTabsProps {
4
+ /** Drops the minimum tab width */
5
+ narrowed?: boolean;
6
+ /** Pill container with the selected tab raised on a white pill */
7
+ segmented?: boolean;
8
+ }
9
+ export declare const Tabs: React.FC<TabsProps>;
10
+ export default Tabs;
@@ -0,0 +1,5 @@
1
+ import { Tabs as MuiTabs } from '@mui/material';
2
+ import cx from 'classnames';
3
+ import React from 'react';
4
+ export const Tabs = ({ className, narrowed, segmented, ...props }) => React.createElement(MuiTabs, { className: cx(className, { narrowed, segmented }), ...props });
5
+ export default Tabs;
@@ -1,16 +1,15 @@
1
1
  import { CssBaseline } from '@mui/material';
2
- import { ThemeProvider as MuiThemeProvider, createTheme } from '@mui/material/styles';
2
+ import { ThemeProvider as MuiThemeProvider } from '@mui/material/styles';
3
3
  import React, { useMemo } from 'react';
4
4
  import { makeTheme } from '../../lib/makeTheme';
5
- export const TwakeMuiThemeProvider = ({ children, mode = 'light', themeOptions }) => {
6
- const theme = useMemo(() => {
7
- const baseTheme = makeTheme(mode);
8
- if (!themeOptions) {
9
- return baseTheme;
10
- }
11
- return createTheme(baseTheme, themeOptions);
12
- }, [mode, themeOptions]);
13
- return (React.createElement(MuiThemeProvider, { theme: theme },
5
+ export const TwakeMuiThemeProvider = ({ children, mode = 'light', palette, themeOptions }) => {
6
+ // The palette holds plain JSON, so comparing it by content lets consumers
7
+ // pass it inline without rebuilding the whole theme on every render.
8
+ const paletteKey = JSON.stringify(palette);
9
+ const theme = useMemo(() => makeTheme(mode, palette, themeOptions),
10
+ // eslint-disable-next-line react-hooks/exhaustive-deps
11
+ [mode, paletteKey, themeOptions]);
12
+ return (React.createElement(MuiThemeProvider, { theme: theme, defaultMode: mode },
14
13
  React.createElement(CssBaseline, null),
15
14
  children));
16
15
  };
@@ -1,7 +1,13 @@
1
1
  import { ThemeOptions } from '@mui/material/styles';
2
2
  import { ReactNode } from 'react';
3
+ import { PaletteJson } from '../../lib/types';
3
4
  export interface ThemeProviderProps {
4
5
  children: ReactNode;
6
+ /**
7
+ * @deprecated Only sets `defaultColorScheme` now (both schemes are always
8
+ * present) - switch theme at runtime with MUI's `useColorScheme()` instead.
9
+ */
5
10
  mode?: 'light' | 'dark';
11
+ palette?: Partial<PaletteJson>;
6
12
  themeOptions?: Partial<ThemeOptions>;
7
13
  }
package/dist/index.d.ts CHANGED
@@ -1,17 +1,42 @@
1
1
  export * from '@mui/material';
2
2
  export * from '@mui/lab';
3
- export { createTheme, ThemeProvider, styled, alpha, darken, lighten, useTheme } from '@mui/material/styles';
3
+ export { createTheme, ThemeProvider, styled, alpha, darken, lighten, useTheme, useColorScheme } from '@mui/material/styles';
4
4
  export { default as Autocomplete } from '@mui/material/Autocomplete';
5
5
  export { makePalette } from './lib/makePalette';
6
6
  export { theme } from './lib/theme';
7
7
  export { radius } from './lib/radius';
8
8
  export { TwakeMuiThemeProvider } from './components/ThemeProvider';
9
9
  export { Avatar, default as AvatarDefault } from './components/Avatar';
10
+ export { Button, default as ButtonDefault } from './components/Button';
10
11
  export { default as Chip } from './components/Chip';
12
+ export { Dialog, default as DialogDefault } from './components/Dialog';
13
+ export { Tabs, default as TabsDefault } from './components/Tabs';
14
+ export { Switch, default as SwitchDefault } from './components/Switch';
15
+ export { Sidebar } from './components/Sidebar';
16
+ export { Nav } from './components/Nav';
17
+ export { NavItem } from './components/NavItem';
18
+ export { NavLink } from './components/NavLink';
19
+ export { NavIcon } from './components/NavIcon';
20
+ export { NavText } from './components/NavText';
21
+ export { NavDesktopLimiter } from './components/NavDesktopLimiter';
22
+ export { NavDesktopDropdown } from './components/NavDesktopDropdown';
11
23
  export { nameToColor, supportedColors } from './components/Avatar/helpers';
12
24
  export { default as AccordionExpandIcon } from './components/AccordionExpandIcon';
13
25
  export { useBreakpoints } from './hooks/useBreakpoints';
14
26
  export type { TwakeTheme } from './lib/theme';
27
+ export type { PaletteJson } from './lib/types';
15
28
  export type { AvatarProps } from './components/Avatar';
29
+ export type { ButtonProps } from './components/Button';
16
30
  export type { ChipProps } from './components/Chip';
31
+ export type { DialogProps, DialogSize } from './components/Dialog';
32
+ export type { TabsProps } from './components/Tabs';
33
+ export type { SwitchProps } from './components/Switch';
34
+ export type { SidebarProps } from './components/Sidebar';
35
+ export type { NavProps } from './components/Nav';
36
+ export type { NavItemProps } from './components/NavItem';
37
+ export type { NavLinkProps } from './components/NavLink';
38
+ export type { NavIconProps } from './components/NavIcon';
39
+ export type { NavTextProps } from './components/NavText';
40
+ export type { NavDesktopLimiterProps } from './components/NavDesktopLimiter';
41
+ export type { NavDesktopDropdownProps } from './components/NavDesktopDropdown';
17
42
  export type { Breakpoints } from './hooks/useBreakpoints';
package/dist/index.js CHANGED
@@ -1,7 +1,7 @@
1
1
  // MUI
2
2
  export * from '@mui/material';
3
3
  export * from '@mui/lab';
4
- export { createTheme, ThemeProvider, styled, alpha, darken, lighten, useTheme } from '@mui/material/styles';
4
+ export { createTheme, ThemeProvider, styled, alpha, darken, lighten, useTheme, useColorScheme } from '@mui/material/styles';
5
5
  export { default as Autocomplete } from '@mui/material/Autocomplete';
6
6
  // LIB
7
7
  export { makePalette } from './lib/makePalette';
@@ -10,7 +10,19 @@ export { radius } from './lib/radius';
10
10
  // COMPONENTS & HELPERS
11
11
  export { TwakeMuiThemeProvider } from './components/ThemeProvider';
12
12
  export { Avatar, default as AvatarDefault } from './components/Avatar';
13
+ export { Button, default as ButtonDefault } from './components/Button';
13
14
  export { default as Chip } from './components/Chip';
15
+ export { Dialog, default as DialogDefault } from './components/Dialog';
16
+ export { Tabs, default as TabsDefault } from './components/Tabs';
17
+ export { Switch, default as SwitchDefault } from './components/Switch';
18
+ export { Sidebar } from './components/Sidebar';
19
+ export { Nav } from './components/Nav';
20
+ export { NavItem } from './components/NavItem';
21
+ export { NavLink } from './components/NavLink';
22
+ export { NavIcon } from './components/NavIcon';
23
+ export { NavText } from './components/NavText';
24
+ export { NavDesktopLimiter } from './components/NavDesktopLimiter';
25
+ export { NavDesktopDropdown } from './components/NavDesktopDropdown';
14
26
  export { nameToColor, supportedColors } from './components/Avatar/helpers';
15
27
  export { default as AccordionExpandIcon } from './components/AccordionExpandIcon';
16
28
  export { useBreakpoints } from './hooks/useBreakpoints';
@@ -1,6 +1,6 @@
1
1
  import { PaletteOptions } from '@mui/material/styles';
2
2
  import { PaletteJson, BackgroundPalette, GreyPalette, BorderPalette } from './types';
3
- export declare const makePalette: (mode?: "light" | "dark", palette?: PaletteJson) => PaletteOptions & {
3
+ export declare const makePalette: (mode?: "light" | "dark", overrides?: Partial<PaletteJson>) => PaletteOptions & {
4
4
  background: BackgroundPalette;
5
5
  grey: GreyPalette;
6
6
  border: BorderPalette;
@@ -1,7 +1,9 @@
1
1
  import { alpha } from '@mui/material/styles';
2
+ import { deepmerge } from '@mui/utils';
2
3
  import paletteJson from './palette.json';
3
4
  const paletteData = paletteJson;
4
- export const makePalette = (mode = 'light', palette = paletteData) => {
5
+ export const makePalette = (mode = 'light', overrides = {}) => {
6
+ const palette = deepmerge(paletteData, overrides);
5
7
  if (mode === 'dark') {
6
8
  return {
7
9
  mode,
@@ -1,3 +1,3 @@
1
1
  import { Shadows } from '@mui/material/styles';
2
2
  import { PaletteJson } from './types';
3
- export declare const makeShadows: (mode?: "light" | "dark", palette?: PaletteJson) => Shadows;
3
+ export declare const makeShadows: (palette?: PaletteJson) => Shadows;
@@ -39,8 +39,8 @@ const OUTLINE_OPACITY = 0.12;
39
39
  * through the type. Kept to stay iso with cozy-ui.
40
40
  */
41
41
  const EXTRA_ELEVATION_OPACITY = 0.04;
42
- export const makeShadows = (mode = 'light', palette = paletteData) => {
43
- const shadowColor = mode === 'dark' ? palette.Common.black : palette.Grey[900];
42
+ export const makeShadows = (palette = paletteData) => {
43
+ const shadowColor = palette.Common.black;
44
44
  const outline = `0px 0px 0px 0.5px ${alpha(shadowColor, OUTLINE_OPACITY)}`;
45
45
  const shadows = elevations.map(([y1, blur1, spread1, o1, y2, blur2, spread2, o2]) => [
46
46
  `0px ${y1}px ${blur1}px ${spread1}px ${alpha(shadowColor, o1)}`,
@@ -1,2 +1,3 @@
1
- import { createTheme } from '@mui/material/styles';
2
- export declare const makeTheme: (mode?: "light" | "dark") => ReturnType<typeof createTheme>;
1
+ import { createTheme, ThemeOptions } from '@mui/material/styles';
2
+ import { PaletteJson } from './types';
3
+ export declare const makeTheme: (mode?: "light" | "dark", paletteOverrides?: Partial<PaletteJson>, themeOptions?: ThemeOptions) => ReturnType<typeof createTheme>;
@@ -1,9 +1,9 @@
1
1
  import { createTheme } from '@mui/material/styles';
2
- import { darkOverrides } from './darkOverrides';
3
- import { lightOverrides } from './lightOverrides';
2
+ import { deepmerge } from '@mui/utils';
4
3
  import { makePalette } from './makePalette';
5
4
  import { makeShadows } from './makeShadows';
6
5
  import { makeTypography } from './makeTypography';
6
+ import { overrides } from './overrides';
7
7
  // DatePicker styles are applied through component overrides
8
8
  const themesCommonConfig = {
9
9
  shape: {
@@ -22,19 +22,18 @@ const themesCommonConfig = {
22
22
  modal: 1300
23
23
  }
24
24
  };
25
- export const makeTheme = (mode = 'light') => {
26
- const palette = makePalette(mode);
27
- const typography = makeTypography();
28
- const theme = createTheme({
25
+ export const makeTheme = (mode = 'light', paletteOverrides, themeOptions) => {
26
+ const baseOptions = {
29
27
  ...themesCommonConfig,
30
- palette,
31
- typography,
32
- shadows: makeShadows(mode)
33
- });
34
- const components = mode === 'dark' ? darkOverrides : lightOverrides;
35
- // Create the final theme with components
36
- return createTheme({
37
- ...theme,
38
- components
39
- });
28
+ cssVariables: { colorSchemeSelector: 'data-theme' },
29
+ defaultColorScheme: mode,
30
+ colorSchemes: {
31
+ light: { palette: makePalette('light', paletteOverrides) },
32
+ dark: { palette: makePalette('dark', paletteOverrides) }
33
+ },
34
+ typography: makeTypography(),
35
+ shadows: makeShadows(),
36
+ components: overrides
37
+ };
38
+ return createTheme(deepmerge(baseOptions, themeOptions ?? {}));
40
39
  };
@@ -0,0 +1,2 @@
1
+ import { ThemeOptions } from '@mui/material/styles';
2
+ export declare const overrides: NonNullable<ThemeOptions['components']>;