@dktunited-techoff/techoff-suite-ui 0.9.15 → 0.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.
Files changed (47) hide show
  1. package/esm/components/Inputs/Input/Input.css +31 -4
  2. package/esm/components/Inputs/Input/Input.d.ts +1 -1
  3. package/esm/components/Inputs/Input/Input.js +11 -4
  4. package/esm/components/Inputs/Input/Input.js.map +1 -1
  5. package/esm/components/Inputs/Input/Input.tsx +40 -4
  6. package/esm/components/Inputs/Input/Input.types.d.ts +5 -1
  7. package/esm/components/Inputs/Input/Input.types.ts +5 -1
  8. package/esm/components/Inputs/Input/__stories__/Input.stories.mdx +29 -2
  9. package/esm/components/Select/__stories__/Select.stories.mdx +5 -1
  10. package/esm/layouts/Header/Header.css +60 -1
  11. package/esm/layouts/Header/Header.d.ts +1 -1
  12. package/esm/layouts/Header/Header.js +4 -3
  13. package/esm/layouts/Header/Header.js.map +1 -1
  14. package/esm/layouts/Header/Header.types.d.ts +9 -0
  15. package/esm/layouts/Header/HeaderSearch.d.ts +3 -0
  16. package/esm/layouts/Header/HeaderSearch.js +60 -0
  17. package/esm/layouts/Header/HeaderSearch.js.map +1 -0
  18. package/esm/layouts/Header/__stories__/Header.stories.mdx +25 -0
  19. package/lib/components/Inputs/Input/Input.css +31 -4
  20. package/lib/components/Inputs/Input/Input.d.ts +1 -1
  21. package/lib/components/Inputs/Input/Input.js +11 -4
  22. package/lib/components/Inputs/Input/Input.js.map +1 -1
  23. package/lib/components/Inputs/Input/Input.tsx +40 -4
  24. package/lib/components/Inputs/Input/Input.types.d.ts +5 -1
  25. package/lib/components/Inputs/Input/Input.types.ts +5 -1
  26. package/lib/components/Inputs/Input/__stories__/Input.stories.mdx +29 -2
  27. package/lib/components/Select/__stories__/Select.stories.mdx +5 -1
  28. package/lib/layouts/Header/Header.css +60 -1
  29. package/lib/layouts/Header/Header.d.ts +1 -1
  30. package/lib/layouts/Header/Header.js +4 -3
  31. package/lib/layouts/Header/Header.js.map +1 -1
  32. package/lib/layouts/Header/Header.types.d.ts +9 -0
  33. package/lib/layouts/Header/HeaderSearch.d.ts +3 -0
  34. package/lib/layouts/Header/HeaderSearch.js +64 -0
  35. package/lib/layouts/Header/HeaderSearch.js.map +1 -0
  36. package/lib/layouts/Header/__stories__/Header.stories.mdx +25 -0
  37. package/package.json +1 -1
  38. package/src/components/Inputs/Input/Input.css +31 -4
  39. package/src/components/Inputs/Input/Input.tsx +40 -4
  40. package/src/components/Inputs/Input/Input.types.ts +5 -1
  41. package/src/components/Inputs/Input/__stories__/Input.stories.mdx +29 -2
  42. package/src/components/Select/__stories__/Select.stories.mdx +5 -1
  43. package/src/layouts/Header/Header.css +60 -1
  44. package/src/layouts/Header/Header.tsx +4 -3
  45. package/src/layouts/Header/Header.types.ts +9 -0
  46. package/src/layouts/Header/HeaderSearch.tsx +97 -0
  47. package/src/layouts/Header/__stories__/Header.stories.mdx +25 -0
@@ -19,23 +19,26 @@
19
19
  }
20
20
  .input-container > input {
21
21
  width: 100%;
22
- height: 32px;
23
- padding: 0 40px 0 12px;
24
- border: 1px solid #d4d4d4;
22
+ padding: 0 16px;
25
23
  border-radius: 6px;
24
+ background: #ffffff;
26
25
  color: #007dbc;
27
26
  font-weight: 700;
28
27
  }
29
28
  .input-container > input::placeholder {
30
29
  font-weight: 400;
31
30
  }
32
- .input-container > .icon {
31
+ .input-container > .input-icon-container {
33
32
  position: absolute;
34
33
  top: 50%;
35
34
  right: 12px;
35
+ display: flex;
36
36
  color: #4e5d6b;
37
37
  transform: translateY(-50%);
38
38
  }
39
+ .input-container > .input-icon-container > * {
40
+ margin-left: 8px;
41
+ }
39
42
  .input--error {
40
43
  display: flex;
41
44
  align-items: center;
@@ -49,6 +52,30 @@
49
52
  .input-container--error > input {
50
53
  border: 2px solid #ed6a5e;
51
54
  }
55
+ /* ########## */
56
+ /* VARIANTS */
57
+ .input-primary .input-container > input {
58
+ border: 1px solid #d4d4d4;
59
+ }
60
+ .input-shadow .input-container > input {
61
+ border: 0;
62
+ box-shadow: 0px 12px 12px 0px #00537d1a;
63
+ }
64
+
65
+ /* ###### */
66
+ /* SIZE */
67
+ .input-md .input-container > input {
68
+ height: 32px;
69
+ }
70
+ .input-lg .input-container > input {
71
+ height: 40px;
72
+ }
73
+
74
+ /* ######### */
75
+ /* ROUNDED */
76
+ .input--rounded .input-container > input {
77
+ border-radius: 9999px;
78
+ }
52
79
 
53
80
  /* ######### */
54
81
  /* GLOBALS */
@@ -1,4 +1,4 @@
1
1
  import * as React from 'react';
2
2
  import { InputProps } from './Input.types';
3
3
  import './Input.css';
4
- export declare const Input: ({ errorLabel, icon, label, type, value, disabled, onChange, ...props }: InputProps) => React.JSX.Element;
4
+ export declare const Input: ({ errorLabel, icon, label, size, type, value, variant, disabled, resetable, rounded, onChange, ...props }: InputProps) => React.JSX.Element;
@@ -1,17 +1,24 @@
1
1
  import * as React from 'react';
2
2
  import { Icon } from '../../Icon/Icon';
3
3
  import './Input.css';
4
- export const Input = ({ errorLabel, icon, label, type = 'text', value, disabled, onChange, ...props }) => {
4
+ export const Input = ({ errorLabel, icon, label, size = 'md', type = 'text', value, variant = 'primary', disabled, resetable, rounded, onChange, ...props }) => {
5
5
  // ########
6
6
  // Handlers
7
7
  const handleChange = (e) => onChange(e.target.value);
8
8
  // #########
9
9
  // Rendering
10
- return (React.createElement("div", { className: `input ${disabled ? 'input--disabled' : ''}` },
10
+ return (React.createElement("div", { className: `
11
+ input input-${variant} input-${size}
12
+ ${disabled ? 'input--disabled' : ''}
13
+ ${rounded ? 'input--rounded' : ''}
14
+ ` },
11
15
  label && React.createElement("label", null, label),
12
16
  React.createElement("div", { className: `input-container ${errorLabel ? 'input-container--error' : ''}` },
13
- React.createElement("input", { type: type, value: value, disabled: disabled, onChange: handleChange, ...props }),
14
- icon && React.createElement(Icon, { name: icon, size: "16" })),
17
+ React.createElement("input", { style: { paddingRight: icon && resetable ? '58px' : icon || resetable ? '36px' : '16px' }, type: type, value: value, disabled: disabled, onChange: handleChange, ...props }),
18
+ (icon || resetable) && (React.createElement("div", { className: "input-icon-container" },
19
+ resetable && (React.createElement("div", { style: { cursor: 'pointer' }, onClick: () => onChange('') },
20
+ React.createElement(Icon, { name: "close", size: "16" }))),
21
+ icon && React.createElement(Icon, { name: icon, size: "16" })))),
15
22
  errorLabel && (React.createElement("div", { className: "input--error" },
16
23
  React.createElement(Icon, { name: "alert-circle-filled" }),
17
24
  React.createElement("div", { className: "input--error-label" }, errorLabel)))));
@@ -1 +1 @@
1
- {"version":3,"file":"Input.js","sourceRoot":"","sources":["../../../../src/components/Inputs/Input/Input.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAE/B,OAAO,EAAE,IAAI,EAAE,MAAM,iBAAiB,CAAC;AAEvC,OAAO,aAAa,CAAC;AAErB,MAAM,CAAC,MAAM,KAAK,GAAG,CAAC,EAAE,UAAU,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,GAAG,MAAM,EAAE,KAAK,EAAE,QAAQ,EAAE,QAAQ,EAAE,GAAG,KAAK,EAAc,EAAE,EAAE;IACnH,WAAW;IACX,WAAW;IACX,MAAM,YAAY,GAAG,CAAC,CAAgC,EAAE,EAAE,CAAC,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IAEpF,YAAY;IACZ,YAAY;IACZ,OAAO,CACL,6BAAK,SAAS,EAAE,SAAS,QAAQ,CAAC,CAAC,CAAC,iBAAiB,CAAC,CAAC,CAAC,EAAE,EAAE;QACzD,KAAK,IAAI,mCAAQ,KAAK,CAAS;QAEhC,6BAAK,SAAS,EAAE,mBAAmB,UAAU,CAAC,CAAC,CAAC,wBAAwB,CAAC,CAAC,CAAC,EAAE,EAAE;YAC7E,+BAAO,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,KAAK,EAAE,QAAQ,EAAE,QAAQ,EAAE,QAAQ,EAAE,YAAY,KAAM,KAAK,GAAI;YACzF,IAAI,IAAI,oBAAC,IAAI,IAAC,IAAI,EAAE,IAAI,EAAE,IAAI,EAAC,IAAI,GAAG,CACnC;QAEL,UAAU,IAAI,CACb,6BAAK,SAAS,EAAC,cAAc;YAC3B,oBAAC,IAAI,IAAC,IAAI,EAAC,qBAAqB,GAAG;YACnC,6BAAK,SAAS,EAAC,oBAAoB,IAAE,UAAU,CAAO,CAClD,CACP,CACG,CACP,CAAC;AACJ,CAAC,CAAC"}
1
+ {"version":3,"file":"Input.js","sourceRoot":"","sources":["../../../../src/components/Inputs/Input/Input.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAE/B,OAAO,EAAE,IAAI,EAAE,MAAM,iBAAiB,CAAC;AAEvC,OAAO,aAAa,CAAC;AAErB,MAAM,CAAC,MAAM,KAAK,GAAG,CAAC,EACpB,UAAU,EACV,IAAI,EACJ,KAAK,EACL,IAAI,GAAG,IAAI,EACX,IAAI,GAAG,MAAM,EACb,KAAK,EACL,OAAO,GAAG,SAAS,EACnB,QAAQ,EACR,SAAS,EACT,OAAO,EACP,QAAQ,EACR,GAAG,KAAK,EACG,EAAE,EAAE;IACf,WAAW;IACX,WAAW;IACX,MAAM,YAAY,GAAG,CAAC,CAAgC,EAAE,EAAE,CAAC,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IAEpF,YAAY;IACZ,YAAY;IACZ,OAAO,CACL,6BACE,SAAS,EAAE;sBACK,OAAO,UAAU,IAAI;UACjC,QAAQ,CAAC,CAAC,CAAC,iBAAiB,CAAC,CAAC,CAAC,EAAE;UACjC,OAAO,CAAC,CAAC,CAAC,gBAAgB,CAAC,CAAC,CAAC,EAAE;OAClC;QAEA,KAAK,IAAI,mCAAQ,KAAK,CAAS;QAEhC,6BAAK,SAAS,EAAE,mBAAmB,UAAU,CAAC,CAAC,CAAC,wBAAwB,CAAC,CAAC,CAAC,EAAE,EAAE;YAC7E,+BACE,KAAK,EAAE,EAAE,YAAY,EAAE,IAAI,IAAI,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,IAAI,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,EAAE,EACzF,IAAI,EAAE,IAAI,EACV,KAAK,EAAE,KAAK,EACZ,QAAQ,EAAE,QAAQ,EAClB,QAAQ,EAAE,YAAY,KAClB,KAAK,GACT;YAED,CAAC,IAAI,IAAI,SAAS,CAAC,IAAI,CACtB,6BAAK,SAAS,EAAC,sBAAsB;gBAClC,SAAS,IAAI,CACZ,6BAAK,KAAK,EAAE,EAAE,MAAM,EAAE,SAAS,EAAE,EAAE,OAAO,EAAE,GAAG,EAAE,CAAC,QAAQ,CAAC,EAAE,CAAC;oBAC5D,oBAAC,IAAI,IAAC,IAAI,EAAC,OAAO,EAAC,IAAI,EAAC,IAAI,GAAG,CAC3B,CACP;gBACA,IAAI,IAAI,oBAAC,IAAI,IAAC,IAAI,EAAE,IAAI,EAAE,IAAI,EAAC,IAAI,GAAG,CACnC,CACP,CACG;QAEL,UAAU,IAAI,CACb,6BAAK,SAAS,EAAC,cAAc;YAC3B,oBAAC,IAAI,IAAC,IAAI,EAAC,qBAAqB,GAAG;YACnC,6BAAK,SAAS,EAAC,oBAAoB,IAAE,UAAU,CAAO,CAClD,CACP,CACG,CACP,CAAC;AACJ,CAAC,CAAC"}
@@ -4,7 +4,20 @@ import { Icon } from '../../Icon/Icon';
4
4
  import { InputProps } from './Input.types';
5
5
  import './Input.css';
6
6
 
7
- export const Input = ({ errorLabel, icon, label, type = 'text', value, disabled, onChange, ...props }: InputProps) => {
7
+ export const Input = ({
8
+ errorLabel,
9
+ icon,
10
+ label,
11
+ size = 'md',
12
+ type = 'text',
13
+ value,
14
+ variant = 'primary',
15
+ disabled,
16
+ resetable,
17
+ rounded,
18
+ onChange,
19
+ ...props
20
+ }: InputProps) => {
8
21
  // ########
9
22
  // Handlers
10
23
  const handleChange = (e: ChangeEvent<HTMLInputElement>) => onChange(e.target.value);
@@ -12,12 +25,35 @@ export const Input = ({ errorLabel, icon, label, type = 'text', value, disabled,
12
25
  // #########
13
26
  // Rendering
14
27
  return (
15
- <div className={`input ${disabled ? 'input--disabled' : ''}`}>
28
+ <div
29
+ className={`
30
+ input input-${variant} input-${size}
31
+ ${disabled ? 'input--disabled' : ''}
32
+ ${rounded ? 'input--rounded' : ''}
33
+ `}
34
+ >
16
35
  {label && <label>{label}</label>}
17
36
 
18
37
  <div className={`input-container ${errorLabel ? 'input-container--error' : ''}`}>
19
- <input type={type} value={value} disabled={disabled} onChange={handleChange} {...props} />
20
- {icon && <Icon name={icon} size="16" />}
38
+ <input
39
+ style={{ paddingRight: icon && resetable ? '58px' : icon || resetable ? '36px' : '16px' }}
40
+ type={type}
41
+ value={value}
42
+ disabled={disabled}
43
+ onChange={handleChange}
44
+ {...props}
45
+ />
46
+
47
+ {(icon || resetable) && (
48
+ <div className="input-icon-container">
49
+ {resetable && (
50
+ <div style={{ cursor: 'pointer' }} onClick={() => onChange('')}>
51
+ <Icon name="close" size="16" />
52
+ </div>
53
+ )}
54
+ {icon && <Icon name={icon} size="16" />}
55
+ </div>
56
+ )}
21
57
  </div>
22
58
 
23
59
  {errorLabel && (
@@ -3,8 +3,12 @@ export type InputProps = {
3
3
  errorLabel?: string;
4
4
  icon?: string;
5
5
  label?: string;
6
+ size?: 'md' | 'lg';
6
7
  type?: 'text' | 'number';
7
8
  value: string;
9
+ variant?: 'primary' | 'shadow';
8
10
  disabled?: boolean;
11
+ resetable?: boolean;
12
+ rounded?: boolean;
9
13
  onChange: (value: string) => void;
10
- } & Omit<InputHTMLAttributes<HTMLInputElement>, 'onChange'>;
14
+ } & Omit<Omit<InputHTMLAttributes<HTMLInputElement>, 'onChange'>, 'size'>;
@@ -4,8 +4,12 @@ export type InputProps = {
4
4
  errorLabel?: string;
5
5
  icon?: string;
6
6
  label?: string;
7
+ size?: 'md' | 'lg';
7
8
  type?: 'text' | 'number';
8
9
  value: string;
10
+ variant?: 'primary' | 'shadow';
9
11
  disabled?: boolean;
12
+ resetable?: boolean;
13
+ rounded?: boolean;
10
14
  onChange: (value: string) => void;
11
- } & Omit<InputHTMLAttributes<HTMLInputElement>, 'onChange'>;
15
+ } & Omit<Omit<InputHTMLAttributes<HTMLInputElement>, 'onChange'>, 'size'>;
@@ -20,18 +20,41 @@ export const inputArgTypes = {
20
20
  control: 'text',
21
21
  description: 'Placeholder displayed when the input is empty.',
22
22
  },
23
+ size: {
24
+ control: 'inline-radio',
25
+ options: ['md', 'lg'],
26
+ description: 'Define the size of the input.',
27
+ table: { defaultValue: { summary: 'md' } },
28
+ },
23
29
  type: {
24
- control: 'select',
30
+ control: 'inline-radio',
25
31
  options: ['text', 'number'],
26
32
  description: 'Type of the input.',
33
+ table: { defaultValue: { summary: 'text' } },
27
34
  },
28
35
  value: {
29
36
  control: 'text',
30
37
  description: 'Value of the input.',
31
38
  },
39
+ variant: {
40
+ control: 'inline-radio',
41
+ options: ['primary', 'shadow'],
42
+ description: 'Variant of the input.',
43
+ table: { defaultValue: { summary: 'primary' } },
44
+ },
32
45
  disabled: {
33
46
  control: 'boolean',
34
- description: 'Auto focus the input once mounted',
47
+ description: 'Disabled the input',
48
+ table: { defaultValue: { summary: 'false' } },
49
+ },
50
+ resetable: {
51
+ control: 'boolean',
52
+ description: 'Reset the input value',
53
+ table: { defaultValue: { summary: 'false' } },
54
+ },
55
+ rounded: {
56
+ control: 'boolean',
57
+ description: 'Rounded the input',
35
58
  table: { defaultValue: { summary: 'false' } },
36
59
  },
37
60
  onChange: {
@@ -53,9 +76,13 @@ Text input allows the user to enter content and data when the expected user inpu
53
76
  errorLabel: '',
54
77
  label: 'Label',
55
78
  placeholder: 'This is a placeholder',
79
+ size: 'md',
56
80
  type: 'text',
57
81
  value: '',
82
+ variant: 'primary',
58
83
  disabled: false,
84
+ resetable: false,
85
+ rounded: false,
59
86
  }}
60
87
  argTypes={inputArgTypes}
61
88
  >
@@ -7,7 +7,11 @@ import { Select } from '../Select';
7
7
  export const selectArgTypes = {
8
8
  label: {
9
9
  control: 'text',
10
- description: 'Label of the input.',
10
+ description: 'Label of the select.',
11
+ },
12
+ value: {
13
+ control: 'text',
14
+ description: 'Value of the select.',
11
15
  },
12
16
  onChange: {
13
17
  control: 'function',
@@ -17,10 +17,19 @@ header {
17
17
  height: 64px;
18
18
  padding: 0 24px;
19
19
  }
20
- .header-left-side {
20
+ .header-aside {
21
21
  display: flex;
22
+ align-items: center;
22
23
  flex: 1;
24
+ height: 100%;
25
+ }
26
+ .header-right-side {
27
+ justify-content: flex-end;
28
+ }
29
+ .header-search-bar {
30
+ display: flex;
23
31
  align-items: center;
32
+ width: 400px;
24
33
  height: 100%;
25
34
  }
26
35
  .header-actions {
@@ -115,6 +124,56 @@ header {
115
124
  padding: 0 2px;
116
125
  }
117
126
 
127
+ /* ############### */
128
+ /* HEADER SEARCH */
129
+ .header-search {
130
+ position: relative;
131
+ width: 100%;
132
+ }
133
+ .header-search-items-container {
134
+ position: absolute;
135
+ top: calc(100% + 4px);
136
+ width: 100%;
137
+ max-height: 200px;
138
+ border-radius: 8px;
139
+ box-shadow: 0px 12px 12px 0px #00537d1a;
140
+ background-color: white;
141
+ overflow-y: auto;
142
+ }
143
+ .header-search-loading {
144
+ display: flex;
145
+ align-items: center;
146
+ justify-content: center;
147
+ height: 40px;
148
+ }
149
+ .header-search-no-items {
150
+ display: flex;
151
+ align-items: center;
152
+ justify-content: center;
153
+ height: 40px;
154
+ color: #8c96a2;
155
+ font-style: italic;
156
+ }
157
+ .header-search-items {
158
+ padding: 8px;
159
+ }
160
+ .header-search-item {
161
+ display: flex;
162
+ align-items: center;
163
+ height: 32px;
164
+ padding: 0 10px;
165
+ border-radius: 4px;
166
+ cursor: pointer;
167
+ }
168
+ .header-search-item:hover {
169
+ background: #e7f3f9;
170
+ }
171
+ .header-search-item--match {
172
+ background: #cce5f2;
173
+ color: #007dbc;
174
+ font-weight: 700;
175
+ }
176
+
118
177
  /* ######### */
119
178
  /* GLOBALS */
120
179
  * {
@@ -1,4 +1,4 @@
1
1
  import * as React from 'react';
2
2
  import { HeaderProps } from './Header.types';
3
3
  import './Header.css';
4
- export declare const Header: ({ actions, appName }: HeaderProps) => React.JSX.Element;
4
+ export declare const Header: ({ actions, appName, search }: HeaderProps) => React.JSX.Element;
@@ -1,13 +1,14 @@
1
1
  import * as React from 'react';
2
2
  import { icons } from '../../components/Icon/icons';
3
3
  import './Header.css';
4
- export const Header = ({ actions, appName }) => {
4
+ export const Header = ({ actions, appName, search }) => {
5
5
  // #########
6
6
  // Rendering
7
7
  return (React.createElement("header", null,
8
- React.createElement("div", { className: "header-left-side" },
8
+ React.createElement("div", { className: "header-aside" },
9
9
  React.createElement("div", { className: "header-techoff", dangerouslySetInnerHTML: { __html: icons[`header-${appName}`] } })),
10
- React.createElement("div", null,
10
+ search && React.createElement("div", { className: "header-search-bar" }, search),
11
+ React.createElement("div", { className: "header-aside header-right-side" },
11
12
  React.createElement("div", { className: "header-actions" }, actions))));
12
13
  };
13
14
  //# sourceMappingURL=Header.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"Header.js","sourceRoot":"","sources":["../../../src/layouts/Header/Header.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAC/B,OAAO,EAAE,KAAK,EAAE,MAAM,6BAA6B,CAAC;AAEpD,OAAO,cAAc,CAAC;AAEtB,MAAM,CAAC,MAAM,MAAM,GAAG,CAAC,EAAE,OAAO,EAAE,OAAO,EAAe,EAAE,EAAE;IAC1D,YAAY;IACZ,YAAY;IACZ,OAAO,CACL;QACE,6BAAK,SAAS,EAAC,kBAAkB;YAC/B,6BAAK,SAAS,EAAC,gBAAgB,EAAC,uBAAuB,EAAE,EAAE,MAAM,EAAE,KAAK,CAAC,UAAU,OAAO,EAAE,CAAC,EAAE,GAAI,CAC/F;QACN;YACE,6BAAK,SAAS,EAAC,gBAAgB,IAAE,OAAO,CAAO,CAC3C,CACC,CACV,CAAC;AACJ,CAAC,CAAC"}
1
+ {"version":3,"file":"Header.js","sourceRoot":"","sources":["../../../src/layouts/Header/Header.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAC/B,OAAO,EAAE,KAAK,EAAE,MAAM,6BAA6B,CAAC;AAEpD,OAAO,cAAc,CAAC;AAEtB,MAAM,CAAC,MAAM,MAAM,GAAG,CAAC,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,EAAe,EAAE,EAAE;IAClE,YAAY;IACZ,YAAY;IACZ,OAAO,CACL;QACE,6BAAK,SAAS,EAAC,cAAc;YAC3B,6BAAK,SAAS,EAAC,gBAAgB,EAAC,uBAAuB,EAAE,EAAE,MAAM,EAAE,KAAK,CAAC,UAAU,OAAO,EAAE,CAAC,EAAE,GAAI,CAC/F;QACL,MAAM,IAAI,6BAAK,SAAS,EAAC,mBAAmB,IAAE,MAAM,CAAO;QAC5D,6BAAK,SAAS,EAAC,gCAAgC;YAC7C,6BAAK,SAAS,EAAC,gBAAgB,IAAE,OAAO,CAAO,CAC3C,CACC,CACV,CAAC;AACJ,CAAC,CAAC"}
@@ -2,9 +2,18 @@ import { ReactElement } from 'react';
2
2
  export type HeaderProps = {
3
3
  actions: ReactElement;
4
4
  appName: 'bikestudio' | 'nsc-helmet' | 'opticost' | 'repairability';
5
+ search?: ReactElement;
5
6
  };
6
7
  export type HeaderProfileProps = {
7
8
  firstname: string;
8
9
  lastname: string;
9
10
  supportLink?: string;
10
11
  };
12
+ export type HeaderSearchProps = {
13
+ getItemLabel: (e: any) => string;
14
+ getItemValue: (e: any) => string;
15
+ loadItems: (search?: string) => Promise<any[]>;
16
+ noDataLabel?: string;
17
+ placeholder?: string;
18
+ onChange: (value: string) => void;
19
+ };
@@ -0,0 +1,3 @@
1
+ import * as React from 'react';
2
+ import { HeaderSearchProps } from './Header.types';
3
+ export declare const HeaderSearch: ({ getItemLabel, getItemValue, loadItems, noDataLabel, placeholder, onChange, }: HeaderSearchProps) => React.JSX.Element;
@@ -0,0 +1,60 @@
1
+ import * as React from 'react';
2
+ import { useEffect, useState } from 'react';
3
+ import { Input } from '../../components/Inputs/Input/Input';
4
+ import { Loader } from '../../components/Loader/Loader';
5
+ import { useClickOutside } from '../../hooks/use-click-outside';
6
+ export const HeaderSearch = ({ getItemLabel, getItemValue, loadItems, noDataLabel, placeholder, onChange, }) => {
7
+ const [searchValue, setSearchValue] = useState('');
8
+ const [items, setItems] = useState([]);
9
+ const [isLoading, setIsLoading] = useState(false);
10
+ const [showItems, setShowItems] = useState(false);
11
+ const ref = useClickOutside(() => setShowItems(false));
12
+ // #######
13
+ // Helpers
14
+ const getBeforeMatch = (item) => {
15
+ const label = getItemLabel(item);
16
+ const matchStartIndex = label.toLowerCase().indexOf(searchValue.toLowerCase());
17
+ return label.substring(0, matchStartIndex);
18
+ };
19
+ const getMatch = (item) => {
20
+ const label = getItemLabel(item);
21
+ const matchStartIndex = label.toLowerCase().indexOf(searchValue.toLowerCase());
22
+ const matchEndIndex = matchStartIndex + searchValue.length;
23
+ return label.substring(matchStartIndex, matchEndIndex);
24
+ };
25
+ const getAfterMatch = (item) => {
26
+ const label = getItemLabel(item);
27
+ const matchStartIndex = label.toLowerCase().indexOf(searchValue.toLowerCase());
28
+ const matchEndIndex = matchStartIndex + searchValue.length;
29
+ return label.substring(matchEndIndex);
30
+ };
31
+ // ########
32
+ // Watchers
33
+ useEffect(() => {
34
+ if (searchValue === '') {
35
+ setShowItems(false);
36
+ setItems([]);
37
+ setIsLoading(false);
38
+ }
39
+ else {
40
+ setShowItems(true);
41
+ setIsLoading(true);
42
+ loadItems(searchValue)
43
+ .then(setItems)
44
+ .finally(() => setIsLoading(false));
45
+ }
46
+ }, [searchValue]);
47
+ // #########
48
+ // Rendering
49
+ return (React.createElement("div", { className: "header-search", ref: ref },
50
+ React.createElement(Input, { placeholder: placeholder, icon: "search", size: "lg", value: searchValue, variant: "shadow", resetable: true, rounded: true, onChange: setSearchValue, onFocus: () => setShowItems(true) }),
51
+ showItems && searchValue !== '' && (React.createElement("div", { className: "header-search-items-container" },
52
+ isLoading && (React.createElement("div", { className: "header-search-loading" },
53
+ React.createElement(Loader, { size: "sm" }))),
54
+ !isLoading && items.length === 0 && React.createElement("div", { className: "header-search-no-items" }, noDataLabel),
55
+ !isLoading && items.length > 0 && (React.createElement("div", { className: "header-search-items" }, items.map(item => (React.createElement("div", { className: "header-search-item", onClick: () => onChange(getItemValue(item)) },
56
+ getBeforeMatch(item),
57
+ React.createElement("span", { className: "header-search-item--match" }, getMatch(item)),
58
+ getAfterMatch(item))))))))));
59
+ };
60
+ //# sourceMappingURL=HeaderSearch.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"HeaderSearch.js","sourceRoot":"","sources":["../../../src/layouts/Header/HeaderSearch.tsx"],"names":[],"mappings":"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"}
@@ -2,6 +2,7 @@ import React from 'react';
2
2
  import { ArgsTable, Canvas, Meta, Story } from '@storybook/blocks';
3
3
  import { Header } from '../Header';
4
4
  import { HeaderProfile } from '../HeaderProfile';
5
+ import { HeaderSearch } from '../HeaderSearch';
5
6
  import { Button } from '../../../components/Button/Button';
6
7
 
7
8
  <Meta title="Layouts/Header" />
@@ -14,6 +15,20 @@ export const headerArgTypes = {
14
15
  },
15
16
  };
16
17
 
18
+ export const loadItems = () => {
19
+ return Promise.resolve([
20
+ { id: 1, label: 'Item 1' },
21
+ { id: 2, label: 'Item 2' },
22
+ { id: 3, label: 'Item 3' },
23
+ { id: 4, label: 'Item 4' },
24
+ { id: 5, label: 'Item 5' },
25
+ { id: 6, label: 'Item 6' },
26
+ { id: 7, label: 'Item 7' },
27
+ { id: 8, label: 'Item 8' },
28
+ { id: 9, label: 'Item 9' },
29
+ ]);
30
+ };
31
+
17
32
  # Header
18
33
 
19
34
  The header will allow users to quickly find the information they need at a glance but also make some actions. The header is therefore central in the design of each application: it contains all the essential information, obvious shortcuts, which will help boost Deacthlon Techoff brand image.
@@ -31,6 +46,16 @@ The header will allow users to quickly find the information they need at a glanc
31
46
  </>
32
47
  ),
33
48
  appName: 'repairability',
49
+ search: (
50
+ <HeaderSearch
51
+ getItemLabel={item => item.label}
52
+ getItemValue={item => item.id}
53
+ loadItems={loadItems}
54
+ noDataLabel="No item found."
55
+ placeholder="Search something in the application"
56
+ onChange={() => {}}
57
+ />
58
+ ),
34
59
  }}
35
60
  argTypes={headerArgTypes}
36
61
  >
@@ -19,23 +19,26 @@
19
19
  }
20
20
  .input-container > input {
21
21
  width: 100%;
22
- height: 32px;
23
- padding: 0 40px 0 12px;
24
- border: 1px solid #d4d4d4;
22
+ padding: 0 16px;
25
23
  border-radius: 6px;
24
+ background: #ffffff;
26
25
  color: #007dbc;
27
26
  font-weight: 700;
28
27
  }
29
28
  .input-container > input::placeholder {
30
29
  font-weight: 400;
31
30
  }
32
- .input-container > .icon {
31
+ .input-container > .input-icon-container {
33
32
  position: absolute;
34
33
  top: 50%;
35
34
  right: 12px;
35
+ display: flex;
36
36
  color: #4e5d6b;
37
37
  transform: translateY(-50%);
38
38
  }
39
+ .input-container > .input-icon-container > * {
40
+ margin-left: 8px;
41
+ }
39
42
  .input--error {
40
43
  display: flex;
41
44
  align-items: center;
@@ -49,6 +52,30 @@
49
52
  .input-container--error > input {
50
53
  border: 2px solid #ed6a5e;
51
54
  }
55
+ /* ########## */
56
+ /* VARIANTS */
57
+ .input-primary .input-container > input {
58
+ border: 1px solid #d4d4d4;
59
+ }
60
+ .input-shadow .input-container > input {
61
+ border: 0;
62
+ box-shadow: 0px 12px 12px 0px #00537d1a;
63
+ }
64
+
65
+ /* ###### */
66
+ /* SIZE */
67
+ .input-md .input-container > input {
68
+ height: 32px;
69
+ }
70
+ .input-lg .input-container > input {
71
+ height: 40px;
72
+ }
73
+
74
+ /* ######### */
75
+ /* ROUNDED */
76
+ .input--rounded .input-container > input {
77
+ border-radius: 9999px;
78
+ }
52
79
 
53
80
  /* ######### */
54
81
  /* GLOBALS */
@@ -1,4 +1,4 @@
1
1
  import * as React from 'react';
2
2
  import { InputProps } from './Input.types';
3
3
  import './Input.css';
4
- export declare const Input: ({ errorLabel, icon, label, type, value, disabled, onChange, ...props }: InputProps) => React.JSX.Element;
4
+ export declare const Input: ({ errorLabel, icon, label, size, type, value, variant, disabled, resetable, rounded, onChange, ...props }: InputProps) => React.JSX.Element;
@@ -4,17 +4,24 @@ exports.Input = void 0;
4
4
  const React = require("react");
5
5
  const Icon_1 = require("../../Icon/Icon");
6
6
  require("./Input.css");
7
- const Input = ({ errorLabel, icon, label, type = 'text', value, disabled, onChange, ...props }) => {
7
+ const Input = ({ errorLabel, icon, label, size = 'md', type = 'text', value, variant = 'primary', disabled, resetable, rounded, onChange, ...props }) => {
8
8
  // ########
9
9
  // Handlers
10
10
  const handleChange = (e) => onChange(e.target.value);
11
11
  // #########
12
12
  // Rendering
13
- return (React.createElement("div", { className: `input ${disabled ? 'input--disabled' : ''}` },
13
+ return (React.createElement("div", { className: `
14
+ input input-${variant} input-${size}
15
+ ${disabled ? 'input--disabled' : ''}
16
+ ${rounded ? 'input--rounded' : ''}
17
+ ` },
14
18
  label && React.createElement("label", null, label),
15
19
  React.createElement("div", { className: `input-container ${errorLabel ? 'input-container--error' : ''}` },
16
- React.createElement("input", { type: type, value: value, disabled: disabled, onChange: handleChange, ...props }),
17
- icon && React.createElement(Icon_1.Icon, { name: icon, size: "16" })),
20
+ React.createElement("input", { style: { paddingRight: icon && resetable ? '58px' : icon || resetable ? '36px' : '16px' }, type: type, value: value, disabled: disabled, onChange: handleChange, ...props }),
21
+ (icon || resetable) && (React.createElement("div", { className: "input-icon-container" },
22
+ resetable && (React.createElement("div", { style: { cursor: 'pointer' }, onClick: () => onChange('') },
23
+ React.createElement(Icon_1.Icon, { name: "close", size: "16" }))),
24
+ icon && React.createElement(Icon_1.Icon, { name: icon, size: "16" })))),
18
25
  errorLabel && (React.createElement("div", { className: "input--error" },
19
26
  React.createElement(Icon_1.Icon, { name: "alert-circle-filled" }),
20
27
  React.createElement("div", { className: "input--error-label" }, errorLabel)))));
@@ -1 +1 @@
1
- {"version":3,"file":"Input.js","sourceRoot":"","sources":["../../../../src/components/Inputs/Input/Input.tsx"],"names":[],"mappings":";;;AAAA,+BAA+B;AAE/B,0CAAuC;AAEvC,uBAAqB;AAEd,MAAM,KAAK,GAAG,CAAC,EAAE,UAAU,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,GAAG,MAAM,EAAE,KAAK,EAAE,QAAQ,EAAE,QAAQ,EAAE,GAAG,KAAK,EAAc,EAAE,EAAE;IACnH,WAAW;IACX,WAAW;IACX,MAAM,YAAY,GAAG,CAAC,CAAgC,EAAE,EAAE,CAAC,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IAEpF,YAAY;IACZ,YAAY;IACZ,OAAO,CACL,6BAAK,SAAS,EAAE,SAAS,QAAQ,CAAC,CAAC,CAAC,iBAAiB,CAAC,CAAC,CAAC,EAAE,EAAE;QACzD,KAAK,IAAI,mCAAQ,KAAK,CAAS;QAEhC,6BAAK,SAAS,EAAE,mBAAmB,UAAU,CAAC,CAAC,CAAC,wBAAwB,CAAC,CAAC,CAAC,EAAE,EAAE;YAC7E,+BAAO,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,KAAK,EAAE,QAAQ,EAAE,QAAQ,EAAE,QAAQ,EAAE,YAAY,KAAM,KAAK,GAAI;YACzF,IAAI,IAAI,oBAAC,WAAI,IAAC,IAAI,EAAE,IAAI,EAAE,IAAI,EAAC,IAAI,GAAG,CACnC;QAEL,UAAU,IAAI,CACb,6BAAK,SAAS,EAAC,cAAc;YAC3B,oBAAC,WAAI,IAAC,IAAI,EAAC,qBAAqB,GAAG;YACnC,6BAAK,SAAS,EAAC,oBAAoB,IAAE,UAAU,CAAO,CAClD,CACP,CACG,CACP,CAAC;AACJ,CAAC,CAAC;AAxBW,QAAA,KAAK,SAwBhB"}
1
+ {"version":3,"file":"Input.js","sourceRoot":"","sources":["../../../../src/components/Inputs/Input/Input.tsx"],"names":[],"mappings":";;;AAAA,+BAA+B;AAE/B,0CAAuC;AAEvC,uBAAqB;AAEd,MAAM,KAAK,GAAG,CAAC,EACpB,UAAU,EACV,IAAI,EACJ,KAAK,EACL,IAAI,GAAG,IAAI,EACX,IAAI,GAAG,MAAM,EACb,KAAK,EACL,OAAO,GAAG,SAAS,EACnB,QAAQ,EACR,SAAS,EACT,OAAO,EACP,QAAQ,EACR,GAAG,KAAK,EACG,EAAE,EAAE;IACf,WAAW;IACX,WAAW;IACX,MAAM,YAAY,GAAG,CAAC,CAAgC,EAAE,EAAE,CAAC,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IAEpF,YAAY;IACZ,YAAY;IACZ,OAAO,CACL,6BACE,SAAS,EAAE;sBACK,OAAO,UAAU,IAAI;UACjC,QAAQ,CAAC,CAAC,CAAC,iBAAiB,CAAC,CAAC,CAAC,EAAE;UACjC,OAAO,CAAC,CAAC,CAAC,gBAAgB,CAAC,CAAC,CAAC,EAAE;OAClC;QAEA,KAAK,IAAI,mCAAQ,KAAK,CAAS;QAEhC,6BAAK,SAAS,EAAE,mBAAmB,UAAU,CAAC,CAAC,CAAC,wBAAwB,CAAC,CAAC,CAAC,EAAE,EAAE;YAC7E,+BACE,KAAK,EAAE,EAAE,YAAY,EAAE,IAAI,IAAI,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,IAAI,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,EAAE,EACzF,IAAI,EAAE,IAAI,EACV,KAAK,EAAE,KAAK,EACZ,QAAQ,EAAE,QAAQ,EAClB,QAAQ,EAAE,YAAY,KAClB,KAAK,GACT;YAED,CAAC,IAAI,IAAI,SAAS,CAAC,IAAI,CACtB,6BAAK,SAAS,EAAC,sBAAsB;gBAClC,SAAS,IAAI,CACZ,6BAAK,KAAK,EAAE,EAAE,MAAM,EAAE,SAAS,EAAE,EAAE,OAAO,EAAE,GAAG,EAAE,CAAC,QAAQ,CAAC,EAAE,CAAC;oBAC5D,oBAAC,WAAI,IAAC,IAAI,EAAC,OAAO,EAAC,IAAI,EAAC,IAAI,GAAG,CAC3B,CACP;gBACA,IAAI,IAAI,oBAAC,WAAI,IAAC,IAAI,EAAE,IAAI,EAAE,IAAI,EAAC,IAAI,GAAG,CACnC,CACP,CACG;QAEL,UAAU,IAAI,CACb,6BAAK,SAAS,EAAC,cAAc;YAC3B,oBAAC,WAAI,IAAC,IAAI,EAAC,qBAAqB,GAAG;YACnC,6BAAK,SAAS,EAAC,oBAAoB,IAAE,UAAU,CAAO,CAClD,CACP,CACG,CACP,CAAC;AACJ,CAAC,CAAC;AA5DW,QAAA,KAAK,SA4DhB"}