@superdispatch/ui-lab 0.50.4 → 0.50.5

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 (124) hide show
  1. package/.babelrc.js +5 -0
  2. package/package.json +38 -13
  3. package/pkg/README.md +10 -0
  4. package/{dist-node → pkg/dist-node}/index.js +41 -21
  5. package/pkg/dist-node/index.js.map +1 -0
  6. package/{dist-src → pkg/dist-src}/email-autocomplate/EmailAutocomplete.js +3 -3
  7. package/{dist-src → pkg/dist-src}/file-drop-zone/FileDropZone.js +2 -2
  8. package/{dist-src → pkg/dist-src}/index.js +1 -0
  9. package/{dist-src → pkg/dist-src}/navbar/Navbar.js +13 -4
  10. package/{dist-src → pkg/dist-src}/navbar/NavbarAccordion.js +18 -9
  11. package/{dist-src → pkg/dist-src}/navbar/NavbarList.js +1 -1
  12. package/{dist-src → pkg/dist-src}/sidebar/SidebarBackButton.js +1 -1
  13. package/{dist-src → pkg/dist-src}/sidebar/SidebarMenuItem.js +1 -1
  14. package/{dist-src → pkg/dist-src}/sidebar/SidebarMenuItemAvatar.js +1 -1
  15. package/{dist-types → pkg/dist-types}/index.d.ts +8 -2
  16. package/{dist-web → pkg/dist-web}/index.js +41 -23
  17. package/pkg/dist-web/index.js.map +1 -0
  18. package/pkg/package.json +41 -0
  19. package/playroom.ts +24 -0
  20. package/src/alert/Alert.stories.tsx +162 -0
  21. package/src/alert/Alert.tsx +135 -0
  22. package/src/banner/Banner.stories.tsx +64 -0
  23. package/src/banner/Banner.tsx +120 -0
  24. package/src/box/Box.stories.tsx +20 -0
  25. package/src/box/Box.tsx +257 -0
  26. package/src/button/Button.stories.tsx +739 -0
  27. package/src/button/Button.tsx +498 -0
  28. package/src/button-area/ButtonArea.stories.tsx +65 -0
  29. package/src/button-area/ButtonArea.tsx +90 -0
  30. package/src/chat/Chat.stories.tsx +130 -0
  31. package/src/chat/Chat.tsx +57 -0
  32. package/src/chat/ChatMessage.tsx +45 -0
  33. package/src/chat/README.MD +7 -0
  34. package/src/chat/__tests__/Chat.spec.tsx +29 -0
  35. package/src/chat/__tests__/ChatMessage.spec.tsx +39 -0
  36. package/src/container/Container.tsx +48 -0
  37. package/src/description-item/DescriptionItem.stories.tsx +163 -0
  38. package/src/description-item/DescriptionItem.tsx +104 -0
  39. package/src/description-line-item/DescriptionLineItem.stories.tsx +23 -0
  40. package/src/description-line-item/DescriptionLineItem.tsx +29 -0
  41. package/src/email-autocomplate/CloseIcon.tsx +20 -0
  42. package/src/email-autocomplate/EmailAutocomplete.stories.tsx +47 -0
  43. package/src/email-autocomplate/EmailAutocomplete.tsx +138 -0
  44. package/src/file-drop-zone/FileDropZone.stories.tsx +44 -0
  45. package/src/file-drop-zone/FileDropZone.tsx +170 -0
  46. package/src/file-list-item/FileListItem.stories.tsx +37 -0
  47. package/src/file-list-item/FileListItem.tsx +148 -0
  48. package/src/file-list-item/__tests__/FileListItem.spec.tsx +339 -0
  49. package/src/flag-list/FlagList.stories.tsx +72 -0
  50. package/src/flag-list/FlagList.tsx +54 -0
  51. package/src/flag-list/FlagListItem.tsx +126 -0
  52. package/src/index.spec.ts +53 -0
  53. package/src/index.ts +36 -0
  54. package/src/linked-text/LinkeText.stories.tsx +42 -0
  55. package/src/linked-text/LinkedText.tsx +47 -0
  56. package/src/multiline-text/MultilineText.stories.tsx +30 -0
  57. package/src/multiline-text/MultilineText.ts +16 -0
  58. package/src/navbar/Navbar.stories.tsx +137 -0
  59. package/src/navbar/Navbar.tsx +132 -0
  60. package/src/navbar/NavbarAccordion.tsx +195 -0
  61. package/src/navbar/NavbarAvatar.tsx +51 -0
  62. package/src/navbar/NavbarBottomBar.tsx +135 -0
  63. package/src/navbar/NavbarContext.tsx +22 -0
  64. package/src/navbar/NavbarItem.tsx +125 -0
  65. package/src/navbar/NavbarList.tsx +247 -0
  66. package/src/navbar/NavbarMenu.tsx +102 -0
  67. package/src/passwordStepper/PasswordStrength.stories.tsx +95 -0
  68. package/src/passwordStepper/PasswordStrength.tsx +107 -0
  69. package/src/passwordStepper/PasswordUtils.tsx +42 -0
  70. package/src/passwordStepper/PasswordValidationComponents.tsx +95 -0
  71. package/src/sidebar/Sidebar.stories.tsx +376 -0
  72. package/src/sidebar/Sidebar.tsx +75 -0
  73. package/src/sidebar/SidebarBackButton.tsx +33 -0
  74. package/src/sidebar/SidebarContainer.tsx +114 -0
  75. package/src/sidebar/SidebarContent.tsx +119 -0
  76. package/src/sidebar/SidebarDivider.tsx +15 -0
  77. package/src/sidebar/SidebarMenuItem.tsx +196 -0
  78. package/src/sidebar/SidebarMenuItemAction.tsx +27 -0
  79. package/src/sidebar/SidebarMenuItemAvatar.tsx +59 -0
  80. package/src/sidebar/SidebarMenuItemContext.tsx +33 -0
  81. package/src/sidebar/SidebarSubheader.tsx +38 -0
  82. package/src/styled.d.ts +12 -0
  83. package/src/text-box/TextBox.stories.tsx +114 -0
  84. package/src/text-box/TextBox.tsx +238 -0
  85. package/src/utils/RuleNormalizer.ts +24 -0
  86. package/src/utils/mergeStyles.ts +28 -0
  87. package/tsconfig.json +19 -0
  88. package/LICENSE +0 -21
  89. package/dist-node/index.js.map +0 -1
  90. package/dist-web/index.js.map +0 -1
  91. /package/{dist-src → pkg/dist-src}/alert/Alert.js +0 -0
  92. /package/{dist-src → pkg/dist-src}/banner/Banner.js +0 -0
  93. /package/{dist-src → pkg/dist-src}/box/Box.js +0 -0
  94. /package/{dist-src → pkg/dist-src}/button/Button.js +0 -0
  95. /package/{dist-src → pkg/dist-src}/button-area/ButtonArea.js +0 -0
  96. /package/{dist-src → pkg/dist-src}/chat/Chat.js +0 -0
  97. /package/{dist-src → pkg/dist-src}/chat/ChatMessage.js +0 -0
  98. /package/{dist-src → pkg/dist-src}/container/Container.js +0 -0
  99. /package/{dist-src → pkg/dist-src}/description-item/DescriptionItem.js +0 -0
  100. /package/{dist-src → pkg/dist-src}/description-line-item/DescriptionLineItem.js +0 -0
  101. /package/{dist-src → pkg/dist-src}/email-autocomplate/CloseIcon.js +0 -0
  102. /package/{dist-src → pkg/dist-src}/file-list-item/FileListItem.js +0 -0
  103. /package/{dist-src → pkg/dist-src}/flag-list/FlagList.js +0 -0
  104. /package/{dist-src → pkg/dist-src}/flag-list/FlagListItem.js +0 -0
  105. /package/{dist-src → pkg/dist-src}/linked-text/LinkedText.js +0 -0
  106. /package/{dist-src → pkg/dist-src}/multiline-text/MultilineText.js +0 -0
  107. /package/{dist-src → pkg/dist-src}/navbar/NavbarAvatar.js +0 -0
  108. /package/{dist-src → pkg/dist-src}/navbar/NavbarBottomBar.js +0 -0
  109. /package/{dist-src → pkg/dist-src}/navbar/NavbarContext.js +0 -0
  110. /package/{dist-src → pkg/dist-src}/navbar/NavbarItem.js +0 -0
  111. /package/{dist-src → pkg/dist-src}/navbar/NavbarMenu.js +0 -0
  112. /package/{dist-src → pkg/dist-src}/passwordStepper/PasswordStrength.js +0 -0
  113. /package/{dist-src → pkg/dist-src}/passwordStepper/PasswordUtils.js +0 -0
  114. /package/{dist-src → pkg/dist-src}/passwordStepper/PasswordValidationComponents.js +0 -0
  115. /package/{dist-src → pkg/dist-src}/sidebar/Sidebar.js +0 -0
  116. /package/{dist-src → pkg/dist-src}/sidebar/SidebarContainer.js +0 -0
  117. /package/{dist-src → pkg/dist-src}/sidebar/SidebarContent.js +0 -0
  118. /package/{dist-src → pkg/dist-src}/sidebar/SidebarDivider.js +0 -0
  119. /package/{dist-src → pkg/dist-src}/sidebar/SidebarMenuItemAction.js +0 -0
  120. /package/{dist-src → pkg/dist-src}/sidebar/SidebarMenuItemContext.js +0 -0
  121. /package/{dist-src → pkg/dist-src}/sidebar/SidebarSubheader.js +0 -0
  122. /package/{dist-src → pkg/dist-src}/text-box/TextBox.js +0 -0
  123. /package/{dist-src → pkg/dist-src}/utils/RuleNormalizer.js +0 -0
  124. /package/{dist-src → pkg/dist-src}/utils/mergeStyles.js +0 -0
@@ -0,0 +1,95 @@
1
+ import { TextField } from '@material-ui/core';
2
+ import { Meta } from '@storybook/react';
3
+ import { Stack } from '@superdispatch/ui';
4
+ import { UseState } from '@superdispatch/ui-docs';
5
+ import { Box } from '../box/Box';
6
+ import { PasswordStrength } from './PasswordStrength';
7
+
8
+ export default {
9
+ title: 'Lab/PasswordStrength',
10
+ component: PasswordStrength,
11
+ decorators: [
12
+ (Story) => (
13
+ <Box maxWidth="400px">
14
+ <Story />
15
+ </Box>
16
+ ),
17
+ ],
18
+ } as Meta;
19
+
20
+ export const basic = () => (
21
+ <Box>
22
+ <PasswordStrength value="" />
23
+ </Box>
24
+ );
25
+
26
+ export const weakPassword = () => (
27
+ <Box>
28
+ <PasswordStrength value="abc" />
29
+ </Box>
30
+ );
31
+
32
+ export const averagePassword = () => (
33
+ <Box>
34
+ <PasswordStrength value="password123" />
35
+ </Box>
36
+ );
37
+
38
+ export const goodPassword = () => (
39
+ <Box>
40
+ <PasswordStrength value="Password123" />
41
+ </Box>
42
+ );
43
+
44
+ export const strongPassword = () => (
45
+ <Box>
46
+ <PasswordStrength value="Password123!!" />
47
+ </Box>
48
+ );
49
+
50
+ export const Interactive = () => (
51
+ <UseState initialState="">
52
+ {(password, setPassword) => (
53
+ <Box>
54
+ <Stack space="medium">
55
+ <TextField
56
+ label="Password"
57
+ type="password"
58
+ value={password}
59
+ onChange={(e) => {
60
+ setPassword(e.target.value);
61
+ }}
62
+ placeholder="Type a password to see strength validation"
63
+ fullWidth={true}
64
+ />
65
+ <PasswordStrength value={password} />
66
+ </Stack>
67
+ </Box>
68
+ )}
69
+ </UseState>
70
+ );
71
+
72
+ export const ProgressiveExample = () => {
73
+ const examples = [
74
+ { label: 'Empty', value: '' },
75
+ { label: 'Too short', value: 'abc' },
76
+ { label: 'Weak (only lowercase)', value: 'password' },
77
+ { label: 'Average (lowercase + number)', value: 'password123' },
78
+ { label: 'Strong (all requirements)', value: 'Password123!!' },
79
+ ];
80
+
81
+ return (
82
+ <Box>
83
+ <Stack space="large">
84
+ {examples.map((example) => (
85
+ <div key={example.label}>
86
+ <h4>
87
+ {example.label}: &quot;{example.value}&quot;
88
+ </h4>
89
+ <PasswordStrength value={example.value} />
90
+ </div>
91
+ ))}
92
+ </Stack>
93
+ </Box>
94
+ );
95
+ };
@@ -0,0 +1,107 @@
1
+ import { Typography } from '@material-ui/core';
2
+ import { Color, ColorDynamic, Stack } from '@superdispatch/ui';
3
+ import { useMemo } from 'react';
4
+ import styled from 'styled-components';
5
+ import { Box } from '../box/Box';
6
+ import {
7
+ getPasswordStrength,
8
+ hasEnoughCharacters,
9
+ hasLowerCaseAndUpperCase,
10
+ hasNumber,
11
+ hasSpecialCharacter,
12
+ PasswordStrength as PasswordStrengthType,
13
+ } from './PasswordUtils';
14
+ import {
15
+ CheckPasswordItem,
16
+ Stepper,
17
+ StepperItem,
18
+ } from './PasswordValidationComponents';
19
+
20
+ const passwordStepperTitle = {
21
+ weak: { textColor: ColorDynamic.Red500, text: 'Weak Password' },
22
+ average: { textColor: ColorDynamic.Yellow500, text: 'Average Password' },
23
+ good: { textColor: ColorDynamic.Green500, text: 'Good Password' },
24
+ strong: { textColor: ColorDynamic.Green500, text: 'Strong Password' },
25
+ };
26
+
27
+ const passwordStrengthToActiveStepsCount = {
28
+ weak: 1,
29
+ average: 2,
30
+ good: 3,
31
+ strong: 4,
32
+ };
33
+
34
+ function steps(passwordStrength: string): boolean[] {
35
+ return [
36
+ passwordStrengthToActiveStepsCount[
37
+ passwordStrength as PasswordStrengthType
38
+ ] >= 1,
39
+ passwordStrengthToActiveStepsCount[
40
+ passwordStrength as PasswordStrengthType
41
+ ] >= 2,
42
+ passwordStrengthToActiveStepsCount[
43
+ passwordStrength as PasswordStrengthType
44
+ ] >= 3,
45
+ passwordStrengthToActiveStepsCount[
46
+ passwordStrength as PasswordStrengthType
47
+ ] >= 4,
48
+ ];
49
+ }
50
+
51
+ const PasswordText = styled(Typography)<{ colorProp?: string }>`
52
+ color: ${({ colorProp }) => colorProp ?? Color.Dark100};
53
+ `;
54
+
55
+ interface PasswordStrengthProps {
56
+ value: string;
57
+ }
58
+
59
+ export function PasswordStrength({
60
+ value,
61
+ }: PasswordStrengthProps): JSX.Element {
62
+ const passwordStrength = useMemo(() => getPasswordStrength(value), [value]);
63
+
64
+ return (
65
+ <Box>
66
+ <Box>
67
+ <PasswordText
68
+ variant="body2"
69
+ colorProp={
70
+ passwordStrength && passwordStepperTitle[passwordStrength].textColor
71
+ }
72
+ >
73
+ {passwordStrength
74
+ ? passwordStepperTitle[passwordStrength].text
75
+ : 'Password Strength'}
76
+ </PasswordText>
77
+ <Stepper>
78
+ {steps(passwordStrength ?? '').map((isStepActive, index) => (
79
+ <StepperItem
80
+ key={index}
81
+ isActive={isStepActive}
82
+ passwordStrength={passwordStrength}
83
+ />
84
+ ))}
85
+ </Stepper>
86
+ </Box>
87
+ <Box>
88
+ <Typography variant="body2">It must have:</Typography>
89
+ <Stack space="xxsmall">
90
+ <CheckPasswordItem
91
+ isDone={hasEnoughCharacters(value)}
92
+ text="At least 8 characters"
93
+ />
94
+ <CheckPasswordItem
95
+ isDone={hasLowerCaseAndUpperCase(value)}
96
+ text="Upper & lowercase letters"
97
+ />
98
+ <CheckPasswordItem isDone={hasNumber(value)} text="A number" />
99
+ <CheckPasswordItem
100
+ isDone={hasSpecialCharacter(value)}
101
+ text="A special character (%, $, #, etc.)"
102
+ />
103
+ </Stack>
104
+ </Box>
105
+ </Box>
106
+ );
107
+ }
@@ -0,0 +1,42 @@
1
+ export function getPasswordStrength(
2
+ value: string,
3
+ ): PasswordStrength | undefined {
4
+ const count = [
5
+ hasEnoughCharacters,
6
+ hasNumber,
7
+ hasLowerCaseAndUpperCase,
8
+ hasSpecialCharacter,
9
+ hasSeveralSpecialCharacters,
10
+ ].reduce<number>((acc, check) => (check(value) ? (acc += 1) : acc), 0);
11
+
12
+ if (count === 1 || count === 2) return 'weak';
13
+ if (count === 3) return 'average';
14
+ if (count >= 4) {
15
+ return value.length > 11 ? 'strong' : 'good';
16
+ }
17
+ return undefined;
18
+ }
19
+
20
+ export function hasEnoughCharacters(text: string): boolean {
21
+ return text.trim().length > 7;
22
+ }
23
+
24
+ export function hasNumber(text: string): boolean {
25
+ return /(?=.*[0-9])/.test(text);
26
+ }
27
+
28
+ export function hasLowerCaseAndUpperCase(text: string): boolean {
29
+ return /^(?=.*[a-z])(?=.*[A-Z]).+$/.test(text);
30
+ }
31
+
32
+ export function hasSpecialCharacter(text: string): boolean {
33
+ return /[!@#$%^&*()_+\-={[}\]|\\;:'"<>?,.]/.test(text);
34
+ }
35
+
36
+ export function hasSeveralSpecialCharacters(text: string): boolean {
37
+ const regex = /[!@#$%^&*()_+\-={[}\]|\\;:'"<>?,.]/g;
38
+ const charactersList = text.match(regex);
39
+ return !!charactersList && charactersList.length > 1;
40
+ }
41
+
42
+ export type PasswordStrength = 'weak' | 'average' | 'good' | 'strong';
@@ -0,0 +1,95 @@
1
+ import { Check } from '@material-ui/icons';
2
+ import { Color, ColorDynamic, Inline } from '@superdispatch/ui';
3
+ import styled from 'styled-components';
4
+ import { Box } from '../box/Box';
5
+ import { PasswordStrength } from './PasswordUtils';
6
+
7
+ const ListItem = styled.div`
8
+ display: flex;
9
+ align-items: center;
10
+ `;
11
+
12
+ const Dot = styled.div`
13
+ height: 4px;
14
+ width: 4px;
15
+ background-color: ${Color.Blue300};
16
+ border-radius: 100px;
17
+ `;
18
+
19
+ const TickBox = styled(Box)`
20
+ width: 13.33px;
21
+ height: 13.33px;
22
+ border-radius: 15px;
23
+ background-color: ${ColorDynamic.Blue50};
24
+ display: flex;
25
+ align-items: center;
26
+ justify-content: center;
27
+ `;
28
+
29
+ export function CheckPasswordItem({
30
+ isDone,
31
+ text,
32
+ }: {
33
+ isDone: boolean;
34
+ text: string;
35
+ }): JSX.Element {
36
+ return (
37
+ <ListItem>
38
+ <Box minWidth="16px">
39
+ <Inline verticalAlign="center" horizontalAlign="center">
40
+ {isDone ? (
41
+ <TickBox>
42
+ <Check style={{ fontSize: '10px', color: Color.Green500 }} />
43
+ </TickBox>
44
+ ) : (
45
+ <Dot />
46
+ )}
47
+ </Inline>
48
+ </Box>
49
+ {text}
50
+ </ListItem>
51
+ );
52
+ }
53
+
54
+ export const Stepper = styled.div`
55
+ height: 5px;
56
+ display: flex;
57
+ width: 100%;
58
+ margin-bottom: 8px;
59
+ margin-top: 4px;
60
+ `;
61
+
62
+ export const StepperItem = styled.div<{
63
+ isActive: boolean;
64
+ passwordStrength?: PasswordStrength;
65
+ }>`
66
+ height: 2px;
67
+ background-color: ${({ isActive, passwordStrength }) =>
68
+ getStepperItemColor(isActive, passwordStrength)};
69
+ flex: 1;
70
+ border-radius: 100px;
71
+ &:not(:last-child) {
72
+ margin-right: 10px;
73
+ flex: 1;
74
+ }
75
+ `;
76
+
77
+ function getStepperItemColor(
78
+ isActive: boolean,
79
+ passwordStrength?: PasswordStrength,
80
+ ): string {
81
+ if (!isActive || !passwordStrength) return ColorDynamic.Silver400;
82
+
83
+ switch (isActive) {
84
+ case passwordStrength === 'strong':
85
+ return ColorDynamic.Green500;
86
+ case passwordStrength === 'weak':
87
+ return ColorDynamic.Red500;
88
+ case passwordStrength === 'average':
89
+ return ColorDynamic.Yellow500;
90
+ case passwordStrength === 'good':
91
+ return ColorDynamic.Green500;
92
+ default:
93
+ return ColorDynamic.Silver400;
94
+ }
95
+ }