@loja-integrada/admin-components 0.16.2 → 0.17.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 (55) hide show
  1. package/dist/Forms/Dropdown/Dropdown.d.ts +32 -3
  2. package/dist/Forms/FloatingLabelInput/FloatingLabelInput.d.ts +10 -0
  3. package/dist/Forms/FloatingLabelInput/FloatingLabelInput.spec.d.ts +1 -0
  4. package/dist/Forms/FloatingLabelInput/FloatingLabelInput.stories.d.ts +10 -0
  5. package/dist/Forms/FloatingLabelInput/index.d.ts +1 -0
  6. package/dist/Forms/FloatingLabelInputCurrency/FloatingLabelInputCurrency.d.ts +49 -0
  7. package/dist/Forms/FloatingLabelInputCurrency/FloatingLabelInputCurrency.spec.d.ts +1 -0
  8. package/dist/Forms/FloatingLabelInputCurrency/FloatingLabelInputCurrency.stories.d.ts +10 -0
  9. package/dist/Forms/FloatingLabelInputCurrency/index.d.ts +1 -0
  10. package/dist/Forms/FloatingLabelInputMask/FloatingLabelInputMask.d.ts +18 -0
  11. package/dist/Forms/FloatingLabelInputMask/FloatingLabelInputMask.spec.d.ts +1 -0
  12. package/dist/Forms/FloatingLabelInputMask/FloatingLabelInputMask.stories.d.ts +19 -0
  13. package/dist/Forms/FloatingLabelInputMask/index.d.ts +1 -0
  14. package/dist/Forms/index.d.ts +3 -0
  15. package/dist/Icons/icons-path/Camera.d.ts +2 -0
  16. package/dist/Icons/icons-path/Lightbulb.d.ts +2 -0
  17. package/dist/Icons/icons-path/Nav.d.ts +2 -0
  18. package/dist/Icons/icons-path/ShoppingCart.d.ts +2 -0
  19. package/dist/Icons/icons-path/index.d.ts +4 -0
  20. package/dist/Indicators/InformationBox/InformationBox.d.ts +25 -0
  21. package/dist/Indicators/InformationBox/InformationBox.spec.d.ts +1 -0
  22. package/dist/Indicators/InformationBox/InformationBoxt.stories.d.ts +4 -0
  23. package/dist/Indicators/InformationBox/index.d.ts +1 -0
  24. package/dist/Indicators/index.d.ts +1 -0
  25. package/dist/admin-components.cjs.development.js +401 -15
  26. package/dist/admin-components.cjs.development.js.map +1 -1
  27. package/dist/admin-components.cjs.production.min.js +1 -1
  28. package/dist/admin-components.cjs.production.min.js.map +1 -1
  29. package/dist/admin-components.esm.js +396 -16
  30. package/dist/admin-components.esm.js.map +1 -1
  31. package/package.json +1 -1
  32. package/src/Forms/Dropdown/Dropdown.tsx +50 -15
  33. package/src/Forms/FloatingLabelInput/FloatingLabelInput.spec.tsx +25 -0
  34. package/src/Forms/FloatingLabelInput/FloatingLabelInput.stories.tsx +72 -0
  35. package/src/Forms/FloatingLabelInput/FloatingLabelInput.tsx +80 -0
  36. package/src/Forms/FloatingLabelInput/index.ts +1 -0
  37. package/src/Forms/FloatingLabelInputCurrency/FloatingLabelInputCurrency.spec.tsx +15 -0
  38. package/src/Forms/FloatingLabelInputCurrency/FloatingLabelInputCurrency.stories.tsx +72 -0
  39. package/src/Forms/FloatingLabelInputCurrency/FloatingLabelInputCurrency.tsx +251 -0
  40. package/src/Forms/FloatingLabelInputCurrency/index.ts +1 -0
  41. package/src/Forms/FloatingLabelInputMask/FloatingLabelInputMask.spec.tsx +65 -0
  42. package/src/Forms/FloatingLabelInputMask/FloatingLabelInputMask.stories.tsx +148 -0
  43. package/src/Forms/FloatingLabelInputMask/FloatingLabelInputMask.tsx +56 -0
  44. package/src/Forms/FloatingLabelInputMask/index.ts +1 -0
  45. package/src/Forms/index.ts +3 -0
  46. package/src/Icons/icons-path/Camera.tsx +9 -0
  47. package/src/Icons/icons-path/Lightbulb.tsx +9 -0
  48. package/src/Icons/icons-path/Nav.tsx +11 -0
  49. package/src/Icons/icons-path/ShoppingCart.tsx +11 -0
  50. package/src/Icons/icons-path/index.ts +8 -0
  51. package/src/Indicators/InformationBox/InformationBox.spec.tsx +27 -0
  52. package/src/Indicators/InformationBox/InformationBox.tsx +86 -0
  53. package/src/Indicators/InformationBox/InformationBoxt.stories.tsx +24 -0
  54. package/src/Indicators/InformationBox/index.tsx +1 -0
  55. package/src/Indicators/index.ts +1 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@loja-integrada/admin-components",
3
- "version": "0.16.2",
3
+ "version": "0.17.0",
4
4
  "author": "Loja Integrada Front-End Team",
5
5
  "license": "MIT",
6
6
  "main": "dist/index.js",
@@ -19,32 +19,49 @@ export const sizeClasses = {
19
19
  xlarge: 'h-24',
20
20
  }
21
21
 
22
+ export const valueFontSizesClasses = {
23
+ default: 'text-f6',
24
+ small: 'text-f7',
25
+ large: 'text-f5',
26
+ xlarge: 'text-f4',
27
+ }
28
+
22
29
  export const variantControlClasses = {
23
- default: 'border-card-stroke rounded',
30
+ default: 'border-card-stroke rounded pl-2',
24
31
  secondary:
25
- 'border-inverted-2 hover:bg-base-3 rounded-md focus:ring-2 focus:ring-focus focus:ring-offset-2 focus:bg-base-1',
32
+ 'border-inverted-2 hover:bg-base-3 rounded-md focus:ring-2 focus:ring-focus focus:ring-offset-2 focus:bg-base-1 pl-2',
33
+ simple: 'border-none',
26
34
  }
27
35
 
28
36
  export const variantValueClasses = {
29
- default: 'font-normal',
30
- secondary: 'font-semibold',
37
+ default: 'font-normal text-on-base',
38
+ secondary: 'font-semibold text-on-base',
39
+ simple: 'font-normal text-on-base',
31
40
  }
32
41
 
33
42
  export const variantSelectedClasses = {
34
43
  default: '',
35
44
  secondary: 'bg-base-1 shadow-inner',
45
+ simple: 'bg-transparent',
36
46
  }
37
47
 
38
48
  export const variantDisabledClasses = {
39
49
  default: 'cursor-not-allowed opacity-70',
40
50
  secondary: 'cursor-not-allowed opacity-90 bg-base-4 border-base-4',
51
+ simple: 'cursor-not-allowed opacity-70',
41
52
  }
42
53
 
43
54
  export const varianErrorClasses = {
44
55
  default: 'border-danger rounded',
45
56
  secondary: 'border-danger rounded-md',
57
+ simple: '',
46
58
  }
47
59
 
60
+ export const valueContainerStyles = {
61
+ default: { paddingLeft: 8 },
62
+ secondary: { paddingLeft: 8 },
63
+ simple: { paddingLeft: 0 },
64
+ }
48
65
  export interface CustomOptionProps {
49
66
  value: string | number
50
67
  label: string
@@ -57,7 +74,9 @@ export interface CustomGroupedOptionsProps {
57
74
  options: CustomOptionProps[]
58
75
  }
59
76
 
60
- export type DropdownVariant = 'default' | 'secondary'
77
+ export type DropdownVariant = 'default' | 'secondary' | 'simple'
78
+ export type DropdownSizes = keyof typeof sizeClasses
79
+ export type DropdownValueFontSizes = keyof typeof valueFontSizesClasses
61
80
 
62
81
  const {
63
82
  Option,
@@ -90,11 +109,11 @@ const CustomControl = (
90
109
  props: React.PropsWithChildren<
91
110
  ControlProps<CustomOptionProps, false, GroupTypeBase<CustomOptionProps>>
92
111
  >,
93
- size: keyof typeof sizeClasses,
112
+ size: DropdownSizes,
94
113
  variant: DropdownVariant,
95
114
  errorMessage?: string
96
115
  ) => {
97
- const controlClasses = `cursor-pointer transition-all flex itens-center border pl-2 ${
116
+ const controlClasses = `cursor-pointer transition-all flex itens-center border ${
98
117
  errorMessage ? varianErrorClasses[variant] : variantControlClasses[variant]
99
118
  } ${sizeClasses[size]} ${
100
119
  props.menuIsOpen ? variantSelectedClasses[variant] : ''
@@ -155,18 +174,23 @@ const CustomPlaceholder = (
155
174
  CustomOptionProps,
156
175
  false,
157
176
  GroupTypeBase<CustomOptionProps>
158
- >
177
+ >,
178
+ fontSize: DropdownValueFontSizes
159
179
  ) => (
160
- <Placeholder {...props} className="text-f6 tracking-4 w-full pr-2 truncate" />
180
+ <Placeholder
181
+ {...props}
182
+ className={`tracking-4 w-full pr-2 truncate ${valueFontSizesClasses[fontSize]}`}
183
+ />
161
184
  )
162
185
 
163
186
  const CustomSingleValue = (
164
187
  props: SingleValueProps<CustomOptionProps, GroupTypeBase<CustomOptionProps>>,
165
- variant: DropdownVariant
188
+ variant: DropdownVariant,
189
+ fontSize: DropdownValueFontSizes
166
190
  ) => (
167
191
  <SingleValue
168
192
  {...props}
169
- className={`text-f6 tracking-4 text-on-base text-sm truncate ${variantValueClasses[variant]}`}
193
+ className={`tracking-4 truncate ${variantValueClasses[variant]} ${valueFontSizesClasses[fontSize]}`}
170
194
  />
171
195
  )
172
196
 
@@ -197,6 +221,7 @@ const DropdownComponent = (
197
221
  menuPlacement = 'auto',
198
222
  menuWidth = '100%',
199
223
  menuHorizontalPlacement,
224
+ valueFontSize = 'default',
200
225
  }: DropdownProps,
201
226
  ref: React.ForwardedRef<any>
202
227
  ) => {
@@ -212,6 +237,7 @@ const DropdownComponent = (
212
237
  className="mb-1"
213
238
  />
214
239
  <Select
240
+ id={inputId}
215
241
  ref={ref}
216
242
  className={`w-full text-inverted-2`}
217
243
  classNamePrefix="select"
@@ -258,6 +284,9 @@ const DropdownComponent = (
258
284
  maxWidth: 'calc(100% - 6px)',
259
285
  }
260
286
  },
287
+ valueContainer: (base) => {
288
+ return { ...base, ...valueContainerStyles[variant] }
289
+ },
261
290
  input: (base) => {
262
291
  return {
263
292
  ...base,
@@ -275,8 +304,9 @@ const DropdownComponent = (
275
304
  DropdownIndicator: (props) => CustomDropdownIndicator(props),
276
305
  Control: (props) => CustomControl(props, size, variant, errorMessage),
277
306
  GroupHeading: (props) => CustomGroupHeading(props),
278
- Placeholder: (props) => CustomPlaceholder(props),
279
- SingleValue: (props) => CustomSingleValue(props, variant),
307
+ Placeholder: (props) => CustomPlaceholder(props, valueFontSize),
308
+ SingleValue: (props) =>
309
+ CustomSingleValue(props, variant, valueFontSize),
280
310
  }}
281
311
  />
282
312
  <InputHelpText
@@ -303,9 +333,14 @@ export interface DropdownProps {
303
333
  * Changes the size of dropdown
304
334
  * @default default
305
335
  * */
306
- size?: keyof typeof sizeClasses
336
+ size?: DropdownSizes
307
337
  /**
308
- * Changes the size of dropdown
338
+ * Changes the size of selected value
339
+ * @default default
340
+ * */
341
+ valueFontSize?: DropdownValueFontSizes
342
+ /**
343
+ * Changes the variant of dropdown
309
344
  * @default default
310
345
  * */
311
346
  variant?: DropdownVariant
@@ -0,0 +1,25 @@
1
+ import * as React from 'react'
2
+ import { composeStories } from '@storybook/testing-react'
3
+ import { mount } from '@cypress/react'
4
+ import * as stories from './FloatingLabelInput.stories'
5
+
6
+ const { Default, Prefix, IconPrefix, WithBoth } = composeStories(stories)
7
+
8
+ describe('Input tests', () => {
9
+ it('Default', () => {
10
+ mount(<Default />)
11
+ const val = 'Preencher campo'
12
+ cy.get('input').type(val).should('have.value', val)
13
+ })
14
+
15
+ it('Sufix and Prefix', () => {
16
+ mount(<Prefix />)
17
+ cy.get('.adornment').contains('R$')
18
+
19
+ mount(<IconPrefix />)
20
+ cy.get('svg').should('have.class', 'icon-cog').parent('label')
21
+
22
+ mount(<WithBoth />)
23
+ cy.get('.adornment').should('have.length', 2)
24
+ })
25
+ })
@@ -0,0 +1,72 @@
1
+ import React from 'react'
2
+ import { Story, Meta } from '@storybook/react'
3
+
4
+ import { Icon } from '../../Icons'
5
+ import {
6
+ FloatingLabelInput,
7
+ FloatingLabelInputProps,
8
+ } from './FloatingLabelInput'
9
+
10
+ export default {
11
+ title: 'Forms/FloatingLabelInput',
12
+ component: FloatingLabelInput,
13
+ } as Meta
14
+
15
+ const Template: Story<FloatingLabelInputProps> = (args) => (
16
+ <FloatingLabelInput {...args} />
17
+ )
18
+
19
+ export const Default = Template.bind({})
20
+ Default.args = {
21
+ label: 'Meu Campo',
22
+ name: 'nome',
23
+ id: 'campo',
24
+ }
25
+
26
+ export const Error = Template.bind({})
27
+ Error.args = {
28
+ label: 'Meu Campo',
29
+ name: 'nome',
30
+ id: 'campo',
31
+ }
32
+
33
+ export const Prefix = Template.bind({})
34
+ Prefix.args = {
35
+ label: 'Meu Campo',
36
+ prefix: 'R$',
37
+ name: 'valor',
38
+ id: 'campo',
39
+ }
40
+
41
+ export const IconPrefix = Template.bind({})
42
+ IconPrefix.args = {
43
+ label: 'Meu Campo',
44
+ prefix: <Icon icon="cog" />,
45
+ name: 'nome',
46
+ id: 'campo',
47
+ }
48
+
49
+ export const Sufix = Template.bind({})
50
+ Sufix.args = {
51
+ label: 'Meu Campo',
52
+ sufix: 'R$',
53
+ name: 'valor',
54
+ id: 'campo',
55
+ }
56
+
57
+ export const IconSufix = Template.bind({})
58
+ IconSufix.args = {
59
+ label: 'Meu Campo',
60
+ sufix: <Icon icon="cog" />,
61
+ name: 'nome',
62
+ id: 'campo',
63
+ }
64
+
65
+ export const WithBoth = Template.bind({})
66
+ WithBoth.args = {
67
+ label: 'Meu Campo',
68
+ prefix: 'R$',
69
+ sufix: <Icon icon="cog" />,
70
+ name: 'valor',
71
+ id: 'campo',
72
+ }
@@ -0,0 +1,80 @@
1
+ import React from 'react'
2
+
3
+ const FloatingLabelInputComponent = (
4
+ {
5
+ prefix,
6
+ sufix,
7
+ id,
8
+ type = 'text',
9
+ placeholder = ' ',
10
+ label,
11
+ showLabel = false,
12
+ className = '',
13
+ ...props
14
+ }: FloatingLabelInputProps,
15
+ ref: React.ForwardedRef<HTMLInputElement>
16
+ ) => {
17
+ const peerFocusLabelClasses = `peer-focus:text-f7 peer-focus:-translate-y-4 ${
18
+ prefix ? 'peer-focus:pl-0' : ''
19
+ } `
20
+ const peerPlaceholderShowLabelClasses = `${
21
+ prefix ? 'peer-placeholder-shown:pl-8' : ''
22
+ } peer-placeholder-shown:translate-y-0 peer-placeholder-shown:text-f4 `
23
+ const labelClassName = `cursor-text absolute text-f7 text-inverted-2 duration-300 transform -translate-y-4 top-5 z-10 origin-[0] ${peerFocusLabelClasses} ${peerPlaceholderShowLabelClasses}`
24
+
25
+ const inputClassName = `block text-f4 ${prefix ? 'pl-7' : ''} ${
26
+ sufix ? 'pr-6' : ''
27
+ } w-full border-none appearance-none peer focus:outline-none bg-transparent pb-2.5 pt-5 ${
28
+ className ? className : ''
29
+ }`
30
+
31
+ return (
32
+ <div className="relative">
33
+ {prefix && (
34
+ <label
35
+ htmlFor={id}
36
+ className="adornment absolute left-0 top-5 w-8 h-8 flex items-center justify-start"
37
+ >
38
+ {prefix}
39
+ </label>
40
+ )}
41
+ <input
42
+ ref={ref}
43
+ type={type}
44
+ id={id}
45
+ className={inputClassName}
46
+ placeholder={placeholder}
47
+ {...props}
48
+ />
49
+ {showLabel && (
50
+ <label htmlFor={id} className={labelClassName}>
51
+ {label}
52
+ </label>
53
+ )}
54
+ {sufix && (
55
+ <label
56
+ htmlFor={id}
57
+ className="adornment absolute right-0 top-5 w-8 h-8 flex items-center justify-end"
58
+ >
59
+ {sufix}
60
+ </label>
61
+ )}
62
+ </div>
63
+ )
64
+ }
65
+
66
+ const InputWithFowardRef = React.forwardRef(FloatingLabelInputComponent)
67
+ export const FloatingLabelInput = React.memo(InputWithFowardRef)
68
+
69
+ export interface FloatingLabelInputProps
70
+ extends Omit<
71
+ React.InputHTMLAttributes<HTMLInputElement>,
72
+ 'prefix' | 'sufix'
73
+ > {
74
+ prefix?: React.ReactNode
75
+ sufix?: React.ReactNode
76
+ label?: string
77
+ showLabel?: boolean
78
+ className?: string
79
+ textArea?: false
80
+ }
@@ -0,0 +1 @@
1
+ export * from './FloatingLabelInput'
@@ -0,0 +1,15 @@
1
+ import * as React from 'react'
2
+ import { composeStories } from '@storybook/testing-react'
3
+ import { mount } from '@cypress/react'
4
+ import * as stories from './FloatingLabelInputCurrency.stories'
5
+
6
+ const { Default } = composeStories(stories)
7
+
8
+ describe('FloatingLabelInputCurrency tests', () => {
9
+ it('Default', () => {
10
+ mount(<Default />)
11
+ const val = '456.88'
12
+ const valMasked = '456,88'
13
+ cy.get('input').type(val).should('have.value', valMasked)
14
+ })
15
+ })
@@ -0,0 +1,72 @@
1
+ import React from 'react'
2
+ import { Story, Meta } from '@storybook/react'
3
+
4
+ import { Icon } from '../../Icons'
5
+ import {
6
+ FloatingLabelInputCurrency,
7
+ FloatingLabelInputCurrencyProps,
8
+ } from './FloatingLabelInputCurrency'
9
+
10
+ export default {
11
+ title: 'Forms/FloatingLabelInputCurrency',
12
+ component: FloatingLabelInputCurrency,
13
+ } as Meta
14
+
15
+ const Template: Story<FloatingLabelInputCurrencyProps> = (args) => (
16
+ <FloatingLabelInputCurrency {...args} />
17
+ )
18
+
19
+ export const Default = Template.bind({})
20
+ Default.args = {
21
+ label: 'Meu Campo',
22
+ name: 'nome',
23
+ id: 'campo',
24
+ }
25
+
26
+ export const Error = Template.bind({})
27
+ Error.args = {
28
+ label: 'Meu Campo',
29
+ name: 'nome',
30
+ id: 'campo',
31
+ }
32
+
33
+ export const Prefix = Template.bind({})
34
+ Prefix.args = {
35
+ label: 'Meu Campo',
36
+ prefix: 'R$',
37
+ name: 'valor',
38
+ id: 'campo',
39
+ }
40
+
41
+ export const IconPrefix = Template.bind({})
42
+ IconPrefix.args = {
43
+ label: 'Meu Campo',
44
+ prefix: <Icon icon="cog" />,
45
+ name: 'nome',
46
+ id: 'campo',
47
+ }
48
+
49
+ export const Sufix = Template.bind({})
50
+ Sufix.args = {
51
+ label: 'Meu Campo',
52
+ sufix: 'R$',
53
+ name: 'valor',
54
+ id: 'campo',
55
+ }
56
+
57
+ export const IconSufix = Template.bind({})
58
+ IconSufix.args = {
59
+ label: 'Meu Campo',
60
+ sufix: <Icon icon="cog" />,
61
+ name: 'nome',
62
+ id: 'campo',
63
+ }
64
+
65
+ export const WithBoth = Template.bind({})
66
+ WithBoth.args = {
67
+ label: 'Meu Campo',
68
+ prefix: 'R$',
69
+ sufix: <Icon icon="cog" />,
70
+ name: 'valor',
71
+ id: 'campo',
72
+ }
@@ -0,0 +1,251 @@
1
+ import React, { useCallback, useEffect, useMemo, useState } from 'react'
2
+ import { composeRefs } from '../../utils'
3
+ import { FloatingLabelInput } from '../FloatingLabelInput/FloatingLabelInput'
4
+ import {
5
+ defaultIntlConfig,
6
+ defaultMaxValue,
7
+ formatCurrency,
8
+ } from '../InputCurrency/utils'
9
+
10
+ const FloatingLabelInputCurrencyComponent = (
11
+ {
12
+ value,
13
+ defaultValue,
14
+ config = defaultIntlConfig,
15
+ currency = 'BRL',
16
+ max = defaultMaxValue,
17
+ autoFocus = false,
18
+ autoSelect = false,
19
+ autoReset = false,
20
+ onChange = () => null,
21
+ onBlur = () => null,
22
+ onFocus = () => null,
23
+ onKeyPress = () => null,
24
+ prefix,
25
+ sufix,
26
+ id,
27
+ type = 'text',
28
+ placeholder = ' ',
29
+ label,
30
+ showLabel = true,
31
+ ...props
32
+ }: FloatingLabelInputCurrencyProps,
33
+ ref: React.ForwardedRef<HTMLInputElement>
34
+ ) => {
35
+ config = config[currency]
36
+
37
+ max = Number(max)
38
+
39
+ const inputRef = useCallback(
40
+ (node) => {
41
+ const isActive = node === document.activeElement
42
+ if (node && autoFocus && !isActive) {
43
+ node.focus()
44
+ }
45
+ },
46
+ [autoFocus]
47
+ )
48
+
49
+ const [maskedValue, setMaskedValue] = useState<string | number>('0')
50
+
51
+ // to prevent a malformed config object
52
+ const safeConfig = useMemo(
53
+ () => () => {
54
+ const {
55
+ format: { maximumFractionDigits },
56
+ } = config
57
+ const finalConfig = {
58
+ ...defaultIntlConfig[currency],
59
+ ...config,
60
+ }
61
+ // at the moment this prevents problems when converting numbers
62
+ // with zeroes in-between, otherwise 205 would convert to 25.
63
+ finalConfig.format.minimumFractionDigits = maximumFractionDigits
64
+ return finalConfig
65
+ },
66
+ [currency, config]
67
+ )
68
+
69
+ const clean = (number: any) => {
70
+ if (typeof number === 'number') {
71
+ return number
72
+ }
73
+
74
+ // strips everything that is not a number (positive or negative)
75
+ return Number(number.toString().replace(/[^0-9-]/g, ''))
76
+ }
77
+
78
+ const normalizeValue = (number: any) => {
79
+ const {
80
+ format: { maximumFractionDigits },
81
+ } = safeConfig()
82
+ let safeNumber = number
83
+
84
+ if (typeof number === 'string') {
85
+ safeNumber = clean(number)
86
+
87
+ if (safeNumber % 1 !== 0) {
88
+ safeNumber = safeNumber.toFixed(maximumFractionDigits)
89
+ }
90
+ } else {
91
+ // all input numbers must be a float point (for the cents portion). This is a fallback in case of integer ones.
92
+ safeNumber = Number.isInteger(number)
93
+ ? Number(number) * 10 ** maximumFractionDigits
94
+ : number.toFixed(maximumFractionDigits)
95
+ }
96
+
97
+ // divide it by 10 power the maximum fraction digits.
98
+ return clean(safeNumber) / 10 ** maximumFractionDigits
99
+ }
100
+
101
+ const calculateValues = (inputFieldValue: any) => {
102
+ const value = normalizeValue(inputFieldValue)
103
+ const maskedValue = formatCurrency(value, safeConfig())
104
+
105
+ return [value, maskedValue]
106
+ }
107
+
108
+ const updateValues = (value: any) => {
109
+ const [calculatedValue, calculatedMaskedValue] = calculateValues(value)
110
+
111
+ if ((!max && max !== 0) || calculatedValue <= max) {
112
+ setMaskedValue(calculatedMaskedValue)
113
+ return [calculatedValue, calculatedMaskedValue]
114
+ } else {
115
+ const [maxCalculatedValue, maxCalculatedMaskedValue] =
116
+ calculateValues(max)
117
+ setMaskedValue(maxCalculatedMaskedValue)
118
+ return [maxCalculatedValue, maxCalculatedMaskedValue]
119
+ }
120
+ }
121
+
122
+ const handleChange = (event: any) => {
123
+ event.preventDefault()
124
+
125
+ const [value, maskedValue] = updateValues(event.target.value)
126
+
127
+ if (maskedValue) {
128
+ onChange(event, value, maskedValue)
129
+ }
130
+ }
131
+
132
+ const handleBlur = (event: any) => {
133
+ const [value, maskedValue] = updateValues(event.target.value)
134
+ if (autoReset) {
135
+ calculateValues(0)
136
+ }
137
+ if (maskedValue) {
138
+ onBlur(event, value, maskedValue)
139
+ }
140
+ }
141
+
142
+ const handleFocus = (event: any) => {
143
+ if (autoSelect) {
144
+ event.target.select()
145
+ }
146
+ const [value, maskedValue] = updateValues(event.target.value)
147
+ if (maskedValue) {
148
+ onFocus(event, value, maskedValue)
149
+ }
150
+ }
151
+
152
+ const handleKeyUp = (event: any) =>
153
+ onKeyPress(event, event.key, event.keyCode)
154
+
155
+ useEffect(() => {
156
+ const currentValue = value || defaultValue || 0
157
+ const [, maskedValue] = calculateValues(currentValue)
158
+ setMaskedValue(maskedValue)
159
+ // eslint-disable-next-line
160
+ }, [currency, value, defaultValue, config])
161
+
162
+ return (
163
+ <FloatingLabelInput
164
+ {...props}
165
+ type={type}
166
+ id={id}
167
+ placeholder={placeholder}
168
+ onBlur={handleBlur}
169
+ onChange={handleChange}
170
+ onKeyUp={handleKeyUp}
171
+ onFocus={handleFocus}
172
+ ref={composeRefs(inputRef, ref)}
173
+ value={maskedValue}
174
+ inputMode="decimal"
175
+ label={label}
176
+ showLabel={showLabel}
177
+ prefix={prefix}
178
+ sufix={sufix}
179
+ />
180
+ )
181
+ }
182
+
183
+ const InputWithFowardRef = React.forwardRef(FloatingLabelInputCurrencyComponent)
184
+ export const FloatingLabelInputCurrency = React.memo(InputWithFowardRef)
185
+
186
+ export interface FloatingLabelInputCurrencyProps
187
+ extends Omit<
188
+ React.InputHTMLAttributes<HTMLInputElement>,
189
+ 'prefix' | 'sufix' | 'onChange' | 'onBlur' | 'onFocus' | 'onKeyPress'
190
+ > {
191
+ prefix?: React.ReactNode
192
+ sufix?: React.ReactNode
193
+ label?: string
194
+ showLabel?: boolean
195
+ /** Currency to format value to
196
+ * @default 'BRL'
197
+ * */
198
+ currency?: keyof typeof defaultIntlConfig
199
+ /** Max value allowed
200
+ * @default 1000000000000000
201
+ * */
202
+ max?: number | string
203
+ /** Custom Intl config
204
+ * @deprecated Don't use, component already has its default config
205
+ * */
206
+ config?: any
207
+ /** Should auto focus
208
+ * @default false
209
+ * */
210
+ autoFocus?: boolean
211
+ /** Should auto select
212
+ * @default false
213
+ * */
214
+ autoSelect?: boolean
215
+ /** Should auto reset
216
+ * @default false
217
+ * */
218
+ autoReset?: boolean
219
+ /**
220
+ * onChange with additional params: (event, value, maskedValue)
221
+ * */
222
+ onChange?: (
223
+ arg0: InputEvent,
224
+ arg1: string | number,
225
+ arg2: string | number
226
+ ) => void
227
+ /**
228
+ * onBlur with additional params: (event, value, maskedValue)
229
+ * */
230
+ onBlur?: (
231
+ arg0: InputEvent,
232
+ arg1: string | number,
233
+ arg2: string | number
234
+ ) => void
235
+ /**
236
+ * onFocus with additional params: (event, value, maskedValue)
237
+ * */
238
+ onFocus?: (
239
+ arg0: InputEvent,
240
+ arg1: string | number,
241
+ arg2: string | number
242
+ ) => void
243
+ /**
244
+ * onKeyPress with additional params: (event, key, keyCode)
245
+ * */
246
+ onKeyPress?: (
247
+ arg0: InputEvent,
248
+ arg1: string | number,
249
+ arg2: string | number
250
+ ) => void
251
+ }
@@ -0,0 +1 @@
1
+ export * from './FloatingLabelInputCurrency'