buildgrid-ui 1.1.0-dev.7 → 1.1.0-dev.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/buildgrid-ui.es.js +4384 -3867
- package/dist/buildgrid-ui.umd.js +72 -62
- package/dist/components/adaptive-input/index.d.ts +1 -0
- package/dist/components/alert-dialog/alert-dialog.d.ts +20 -0
- package/dist/components/alert-dialog/index.d.ts +1 -0
- package/dist/components/badge/badge.d.ts +1 -1
- package/dist/components/button/button.d.ts +1 -1
- package/dist/components/currency-input/currency-input.d.ts +10 -0
- package/dist/components/currency-input/index.d.ts +1 -0
- package/dist/components/index.d.ts +3 -1
- package/dist/lib/index.d.ts +1 -0
- package/dist/lib/utils/formatters.d.ts +8 -0
- package/package.json +2 -1
- package/src/components/{adaptative-input/adaptative-input.stories.tsx → adaptive-input/adaptive-input.stories.tsx} +1 -1
- package/src/components/{adaptative-input/adaptative-input.tsx → adaptive-input/adaptive-input.tsx} +1 -1
- package/src/components/adaptive-input/index.ts +1 -0
- package/src/components/alert-dialog/alert-dialog.stories.tsx +49 -0
- package/src/components/alert-dialog/alert-dialog.tsx +130 -0
- package/src/components/alert-dialog/index.ts +1 -0
- package/src/components/autocomplete/autocomplete.tsx +1 -1
- package/src/components/currency-input/currency-input.stories.tsx +28 -0
- package/src/components/currency-input/currency-input.tsx +93 -0
- package/src/components/currency-input/index.ts +1 -0
- package/src/components/index.ts +3 -1
- package/src/lib/index.ts +1 -0
- package/src/lib/utils/formatters.ts +55 -0
- package/dist/components/adaptative-input/index.d.ts +0 -1
- package/src/components/adaptative-input/index.ts +0 -1
- /package/dist/components/{adaptative-input/adaptative-input.d.ts → adaptive-input/adaptive-input.d.ts} +0 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './adaptive-input';
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import * as AlertDialogPrimitive from '@radix-ui/react-alert-dialog';
|
|
2
|
+
import * as React from 'react';
|
|
3
|
+
declare const AlertDialog: React.FC<AlertDialogPrimitive.AlertDialogProps>;
|
|
4
|
+
declare const AlertDialogTrigger: React.ForwardRefExoticComponent<AlertDialogPrimitive.AlertDialogTriggerProps & React.RefAttributes<HTMLButtonElement>>;
|
|
5
|
+
declare const AlertDialogPortal: React.FC<AlertDialogPrimitive.AlertDialogPortalProps>;
|
|
6
|
+
declare const AlertDialogOverlay: React.ForwardRefExoticComponent<Omit<AlertDialogPrimitive.AlertDialogOverlayProps & React.RefAttributes<HTMLDivElement>, "ref"> & React.RefAttributes<HTMLDivElement>>;
|
|
7
|
+
declare const AlertDialogContent: React.ForwardRefExoticComponent<Omit<AlertDialogPrimitive.AlertDialogContentProps & React.RefAttributes<HTMLDivElement>, "ref"> & React.RefAttributes<HTMLDivElement>>;
|
|
8
|
+
declare const AlertDialogHeader: {
|
|
9
|
+
({ className, ...props }: React.HTMLAttributes<HTMLDivElement>): import("react/jsx-runtime").JSX.Element;
|
|
10
|
+
displayName: string;
|
|
11
|
+
};
|
|
12
|
+
declare const AlertDialogFooter: {
|
|
13
|
+
({ className, ...props }: React.HTMLAttributes<HTMLDivElement>): import("react/jsx-runtime").JSX.Element;
|
|
14
|
+
displayName: string;
|
|
15
|
+
};
|
|
16
|
+
declare const AlertDialogTitle: React.ForwardRefExoticComponent<Omit<AlertDialogPrimitive.AlertDialogTitleProps & React.RefAttributes<HTMLHeadingElement>, "ref"> & React.RefAttributes<HTMLHeadingElement>>;
|
|
17
|
+
declare const AlertDialogDescription: React.ForwardRefExoticComponent<Omit<AlertDialogPrimitive.AlertDialogDescriptionProps & React.RefAttributes<HTMLParagraphElement>, "ref"> & React.RefAttributes<HTMLParagraphElement>>;
|
|
18
|
+
declare const AlertDialogAction: React.ForwardRefExoticComponent<Omit<AlertDialogPrimitive.AlertDialogActionProps & React.RefAttributes<HTMLButtonElement>, "ref"> & React.RefAttributes<HTMLButtonElement>>;
|
|
19
|
+
declare const AlertDialogCancel: React.ForwardRefExoticComponent<Omit<AlertDialogPrimitive.AlertDialogCancelProps & React.RefAttributes<HTMLButtonElement>, "ref"> & React.RefAttributes<HTMLButtonElement>>;
|
|
20
|
+
export { AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogOverlay, AlertDialogPortal, AlertDialogTitle, AlertDialogTrigger, };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './alert-dialog';
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { type VariantProps } from 'class-variance-authority';
|
|
2
2
|
import * as React from 'react';
|
|
3
3
|
declare const badgeVariants: (props?: ({
|
|
4
|
-
variant?: "default" | "
|
|
4
|
+
variant?: "default" | "destructive" | "outline" | "secondary" | null | undefined;
|
|
5
5
|
} & import("class-variance-authority/dist/types").ClassProp) | undefined) => string;
|
|
6
6
|
export interface BadgeProps extends React.HTMLAttributes<HTMLDivElement>, VariantProps<typeof badgeVariants> {
|
|
7
7
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { type VariantProps } from 'class-variance-authority';
|
|
2
2
|
import * as React from 'react';
|
|
3
3
|
declare const buttonVariants: (props?: ({
|
|
4
|
-
variant?: "default" | "link" | "
|
|
4
|
+
variant?: "default" | "link" | "destructive" | "outline" | "secondary" | "ghost" | null | undefined;
|
|
5
5
|
size?: "default" | "sm" | "lg" | "xl" | "icon" | null | undefined;
|
|
6
6
|
} & import("class-variance-authority/dist/types").ClassProp) | undefined) => string;
|
|
7
7
|
export interface ButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement>, VariantProps<typeof buttonVariants> {
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { AdaptiveInputProps } from '../adaptive-input';
|
|
3
|
+
export interface CurrencyInputProps extends AdaptiveInputProps {
|
|
4
|
+
currencySymbol?: string;
|
|
5
|
+
decimalSeparator?: string;
|
|
6
|
+
thousandSeparator?: string;
|
|
7
|
+
onValueChange: (value: number) => void;
|
|
8
|
+
}
|
|
9
|
+
declare const CurrencyInput: React.ForwardRefExoticComponent<CurrencyInputProps & React.RefAttributes<HTMLInputElement>>;
|
|
10
|
+
export { CurrencyInput };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './currency-input';
|
|
@@ -1,10 +1,12 @@
|
|
|
1
|
-
export * from './
|
|
1
|
+
export * from './adaptive-input';
|
|
2
|
+
export * from './alert-dialog';
|
|
2
3
|
export * from './autocomplete';
|
|
3
4
|
export * from './avatar';
|
|
4
5
|
export * from './badge';
|
|
5
6
|
export * from './button';
|
|
6
7
|
export * from './card';
|
|
7
8
|
export * from './checkbox';
|
|
9
|
+
export * from './currency-input';
|
|
8
10
|
export * from './dropdown-menu';
|
|
9
11
|
export * from './input';
|
|
10
12
|
export * from './password-input';
|
package/dist/lib/index.d.ts
CHANGED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export declare const formatCurrency: (number: number, language?: string, currency?: string) => string;
|
|
2
|
+
export declare const formatDateAndWeekday: (date: Date | string, language?: string) => string;
|
|
3
|
+
export declare const formatDateAndWeekdayAndYear: (date: Date | string, language?: string) => string;
|
|
4
|
+
export declare const formatDateAndMonth: (date: Date | string, language?: string) => string;
|
|
5
|
+
export declare const formatLongDate: (date: Date | string, language?: string) => string;
|
|
6
|
+
export declare const formatShortDate: (date: Date, language?: string) => string;
|
|
7
|
+
export declare const getMonthYearFromISODate: (date: string) => string;
|
|
8
|
+
export declare const formatWeekDayAndShortDate: (date: Date, language?: string) => string;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "buildgrid-ui",
|
|
3
|
-
"version": "1.1.0-dev.
|
|
3
|
+
"version": "1.1.0-dev.9",
|
|
4
4
|
"publishConfig": {
|
|
5
5
|
"access": "public"
|
|
6
6
|
},
|
|
@@ -23,6 +23,7 @@
|
|
|
23
23
|
"license": "ISC",
|
|
24
24
|
"description": "",
|
|
25
25
|
"dependencies": {
|
|
26
|
+
"@radix-ui/react-alert-dialog": "^1.1.4",
|
|
26
27
|
"@radix-ui/react-avatar": "^1.1.2",
|
|
27
28
|
"@radix-ui/react-checkbox": "^1.1.3",
|
|
28
29
|
"@radix-ui/react-dropdown-menu": "^2.1.4",
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import React from 'react'
|
|
3
3
|
import type { Meta, StoryObj } from '@storybook/react'
|
|
4
4
|
|
|
5
|
-
import { AdaptiveInput } from './
|
|
5
|
+
import { AdaptiveInput } from './adaptive-input'
|
|
6
6
|
import { HelpCircle, Phone, User } from 'lucide-react'
|
|
7
7
|
|
|
8
8
|
const meta: Meta<typeof AdaptiveInput> = {
|
package/src/components/{adaptative-input/adaptative-input.tsx → adaptive-input/adaptive-input.tsx}
RENAMED
|
@@ -39,7 +39,7 @@ const AdaptiveInput = React.forwardRef<HTMLInputElement, AdaptiveInputProps>(
|
|
|
39
39
|
}
|
|
40
40
|
|
|
41
41
|
return (
|
|
42
|
-
<div className="relative w-
|
|
42
|
+
<div className="relative w-full">
|
|
43
43
|
{leftIcon && (
|
|
44
44
|
<div className="absolute left-2 top-1/2 -translate-y-1/2 text-muted-foreground">
|
|
45
45
|
{leftIcon}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './adaptive-input'
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
// organize-imports-ignore
|
|
2
|
+
import React from 'react'
|
|
3
|
+
import type { Meta, StoryObj } from '@storybook/react'
|
|
4
|
+
import {
|
|
5
|
+
AlertDialog,
|
|
6
|
+
AlertDialogAction,
|
|
7
|
+
AlertDialogCancel,
|
|
8
|
+
AlertDialogContent,
|
|
9
|
+
AlertDialogDescription,
|
|
10
|
+
AlertDialogFooter,
|
|
11
|
+
AlertDialogHeader,
|
|
12
|
+
AlertDialogTitle,
|
|
13
|
+
AlertDialogTrigger,
|
|
14
|
+
} from './alert-dialog'
|
|
15
|
+
import { Button } from '../button'
|
|
16
|
+
|
|
17
|
+
const meta: Meta<typeof AlertDialog> = {
|
|
18
|
+
component: AlertDialog,
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export default meta
|
|
22
|
+
type Story = StoryObj<typeof AlertDialog>
|
|
23
|
+
|
|
24
|
+
const Template = () => {
|
|
25
|
+
return (
|
|
26
|
+
<AlertDialog>
|
|
27
|
+
<AlertDialogTrigger asChild>
|
|
28
|
+
<Button>Open dialog</Button>
|
|
29
|
+
</AlertDialogTrigger>
|
|
30
|
+
<AlertDialogContent>
|
|
31
|
+
<AlertDialogHeader>
|
|
32
|
+
<AlertDialogTitle>Alert title</AlertDialogTitle>
|
|
33
|
+
<AlertDialogDescription>This is the alert description</AlertDialogDescription>
|
|
34
|
+
</AlertDialogHeader>
|
|
35
|
+
<div className="bg-gray-200 p-4 h-20 text-sm">Content goes here</div>
|
|
36
|
+
|
|
37
|
+
<AlertDialogFooter>
|
|
38
|
+
<AlertDialogCancel>Cancel</AlertDialogCancel>
|
|
39
|
+
<AlertDialogAction>Submit</AlertDialogAction>
|
|
40
|
+
</AlertDialogFooter>
|
|
41
|
+
</AlertDialogContent>
|
|
42
|
+
</AlertDialog>
|
|
43
|
+
)
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export const Default: Story = {
|
|
47
|
+
render: Template.bind({}),
|
|
48
|
+
args: {},
|
|
49
|
+
}
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
import { cn } from '@/lib'
|
|
2
|
+
import * as AlertDialogPrimitive from '@radix-ui/react-alert-dialog'
|
|
3
|
+
import * as React from 'react'
|
|
4
|
+
import { buttonVariants } from '../button'
|
|
5
|
+
|
|
6
|
+
const AlertDialog = AlertDialogPrimitive.Root
|
|
7
|
+
|
|
8
|
+
const AlertDialogTrigger = AlertDialogPrimitive.Trigger
|
|
9
|
+
|
|
10
|
+
const AlertDialogPortal = AlertDialogPrimitive.Portal
|
|
11
|
+
|
|
12
|
+
const AlertDialogOverlay = React.forwardRef<
|
|
13
|
+
React.ElementRef<typeof AlertDialogPrimitive.Overlay>,
|
|
14
|
+
React.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Overlay>
|
|
15
|
+
>(({ className, ...props }, ref) => (
|
|
16
|
+
<AlertDialogPrimitive.Overlay
|
|
17
|
+
className={cn(
|
|
18
|
+
'fixed inset-0 z-50 bg-black/80 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0',
|
|
19
|
+
className,
|
|
20
|
+
)}
|
|
21
|
+
{...props}
|
|
22
|
+
ref={ref}
|
|
23
|
+
/>
|
|
24
|
+
))
|
|
25
|
+
AlertDialogOverlay.displayName = AlertDialogPrimitive.Overlay.displayName
|
|
26
|
+
|
|
27
|
+
const AlertDialogContent = React.forwardRef<
|
|
28
|
+
React.ElementRef<typeof AlertDialogPrimitive.Content>,
|
|
29
|
+
React.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Content>
|
|
30
|
+
>(({ className, ...props }, ref) => (
|
|
31
|
+
<AlertDialogPortal>
|
|
32
|
+
<AlertDialogOverlay />
|
|
33
|
+
<AlertDialogPrimitive.Content
|
|
34
|
+
ref={ref}
|
|
35
|
+
className={cn(
|
|
36
|
+
'fixed left-[50%] top-[50%] z-50 grid w-full max-w-lg translate-x-[-50%] translate-y-[-50%] gap-4 border bg-background p-6 shadow-lg duration-200 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[state=closed]:slide-out-to-left-1/2 data-[state=closed]:slide-out-to-top-[48%] data-[state=open]:slide-in-from-left-1/2 data-[state=open]:slide-in-from-top-[48%] sm:rounded-lg',
|
|
37
|
+
className,
|
|
38
|
+
)}
|
|
39
|
+
{...props}
|
|
40
|
+
/>
|
|
41
|
+
</AlertDialogPortal>
|
|
42
|
+
))
|
|
43
|
+
AlertDialogContent.displayName = AlertDialogPrimitive.Content.displayName
|
|
44
|
+
|
|
45
|
+
const AlertDialogHeader = ({
|
|
46
|
+
className,
|
|
47
|
+
...props
|
|
48
|
+
}: React.HTMLAttributes<HTMLDivElement>) => (
|
|
49
|
+
<div
|
|
50
|
+
className={cn('flex flex-col space-y-2 text-center sm:text-left', className)}
|
|
51
|
+
{...props}
|
|
52
|
+
/>
|
|
53
|
+
)
|
|
54
|
+
AlertDialogHeader.displayName = 'AlertDialogHeader'
|
|
55
|
+
|
|
56
|
+
const AlertDialogFooter = ({
|
|
57
|
+
className,
|
|
58
|
+
...props
|
|
59
|
+
}: React.HTMLAttributes<HTMLDivElement>) => (
|
|
60
|
+
<div
|
|
61
|
+
className={cn(
|
|
62
|
+
'flex flex-col-reverse sm:flex-row sm:justify-end sm:space-x-2',
|
|
63
|
+
className,
|
|
64
|
+
)}
|
|
65
|
+
{...props}
|
|
66
|
+
/>
|
|
67
|
+
)
|
|
68
|
+
AlertDialogFooter.displayName = 'AlertDialogFooter'
|
|
69
|
+
|
|
70
|
+
const AlertDialogTitle = React.forwardRef<
|
|
71
|
+
React.ElementRef<typeof AlertDialogPrimitive.Title>,
|
|
72
|
+
React.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Title>
|
|
73
|
+
>(({ className, ...props }, ref) => (
|
|
74
|
+
<AlertDialogPrimitive.Title
|
|
75
|
+
ref={ref}
|
|
76
|
+
className={cn('text-lg font-semibold', className)}
|
|
77
|
+
{...props}
|
|
78
|
+
/>
|
|
79
|
+
))
|
|
80
|
+
AlertDialogTitle.displayName = AlertDialogPrimitive.Title.displayName
|
|
81
|
+
|
|
82
|
+
const AlertDialogDescription = React.forwardRef<
|
|
83
|
+
React.ElementRef<typeof AlertDialogPrimitive.Description>,
|
|
84
|
+
React.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Description>
|
|
85
|
+
>(({ className, ...props }, ref) => (
|
|
86
|
+
<AlertDialogPrimitive.Description
|
|
87
|
+
ref={ref}
|
|
88
|
+
className={cn('text-sm text-muted-foreground', className)}
|
|
89
|
+
{...props}
|
|
90
|
+
/>
|
|
91
|
+
))
|
|
92
|
+
AlertDialogDescription.displayName = AlertDialogPrimitive.Description.displayName
|
|
93
|
+
|
|
94
|
+
const AlertDialogAction = React.forwardRef<
|
|
95
|
+
React.ElementRef<typeof AlertDialogPrimitive.Action>,
|
|
96
|
+
React.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Action>
|
|
97
|
+
>(({ className, ...props }, ref) => (
|
|
98
|
+
<AlertDialogPrimitive.Action
|
|
99
|
+
ref={ref}
|
|
100
|
+
className={cn(buttonVariants(), className)}
|
|
101
|
+
{...props}
|
|
102
|
+
/>
|
|
103
|
+
))
|
|
104
|
+
AlertDialogAction.displayName = AlertDialogPrimitive.Action.displayName
|
|
105
|
+
|
|
106
|
+
const AlertDialogCancel = React.forwardRef<
|
|
107
|
+
React.ElementRef<typeof AlertDialogPrimitive.Cancel>,
|
|
108
|
+
React.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Cancel>
|
|
109
|
+
>(({ className, ...props }, ref) => (
|
|
110
|
+
<AlertDialogPrimitive.Cancel
|
|
111
|
+
ref={ref}
|
|
112
|
+
className={cn(buttonVariants({ variant: 'outline' }), 'mt-2 sm:mt-0', className)}
|
|
113
|
+
{...props}
|
|
114
|
+
/>
|
|
115
|
+
))
|
|
116
|
+
AlertDialogCancel.displayName = AlertDialogPrimitive.Cancel.displayName
|
|
117
|
+
|
|
118
|
+
export {
|
|
119
|
+
AlertDialog,
|
|
120
|
+
AlertDialogAction,
|
|
121
|
+
AlertDialogCancel,
|
|
122
|
+
AlertDialogContent,
|
|
123
|
+
AlertDialogDescription,
|
|
124
|
+
AlertDialogFooter,
|
|
125
|
+
AlertDialogHeader,
|
|
126
|
+
AlertDialogOverlay,
|
|
127
|
+
AlertDialogPortal,
|
|
128
|
+
AlertDialogTitle,
|
|
129
|
+
AlertDialogTrigger,
|
|
130
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './alert-dialog'
|
|
@@ -2,7 +2,7 @@ import { Search } from 'lucide-react'
|
|
|
2
2
|
import { useState } from 'react'
|
|
3
3
|
|
|
4
4
|
import { cn } from '@/lib'
|
|
5
|
-
import { AdaptiveInput } from '../
|
|
5
|
+
import { AdaptiveInput } from '../adaptive-input'
|
|
6
6
|
import { Popover, PopoverContent, PopoverTrigger } from '../popover'
|
|
7
7
|
|
|
8
8
|
interface Option {
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
// organize-imports-ignore
|
|
2
|
+
import React from 'react'
|
|
3
|
+
import type { Meta, StoryObj } from '@storybook/react'
|
|
4
|
+
|
|
5
|
+
import { CurrencyInput } from './currency-input'
|
|
6
|
+
import { DollarSign } from 'lucide-react'
|
|
7
|
+
|
|
8
|
+
const meta: Meta<typeof CurrencyInput> = {
|
|
9
|
+
title: 'Components/input/currency',
|
|
10
|
+
component: CurrencyInput,
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export default meta
|
|
14
|
+
type Story = StoryObj<typeof CurrencyInput>
|
|
15
|
+
|
|
16
|
+
const Template = () => {
|
|
17
|
+
const [value, setValue] = React.useState(0)
|
|
18
|
+
return (
|
|
19
|
+
<div className="w-96">
|
|
20
|
+
<CurrencyInput value={value} onValueChange={(number) => setValue(number)} />
|
|
21
|
+
</div>
|
|
22
|
+
)
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export const Default: Story = {
|
|
26
|
+
render: Template.bind({}),
|
|
27
|
+
args: {},
|
|
28
|
+
}
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
import React, { useEffect, useImperativeHandle, useRef, useState } from 'react'
|
|
2
|
+
import { AdaptiveInput, AdaptiveInputProps } from '../adaptive-input'
|
|
3
|
+
|
|
4
|
+
export interface CurrencyInputProps extends AdaptiveInputProps {
|
|
5
|
+
currencySymbol?: string
|
|
6
|
+
decimalSeparator?: string
|
|
7
|
+
thousandSeparator?: string
|
|
8
|
+
onValueChange: (value: number) => void
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
const CurrencyInput = React.forwardRef<HTMLInputElement, CurrencyInputProps>(
|
|
12
|
+
(props, ref) => {
|
|
13
|
+
const {
|
|
14
|
+
currencySymbol = '$',
|
|
15
|
+
decimalSeparator = '.',
|
|
16
|
+
thousandSeparator = ',',
|
|
17
|
+
onValueChange,
|
|
18
|
+
className,
|
|
19
|
+
value = 0,
|
|
20
|
+
...rest
|
|
21
|
+
} = props
|
|
22
|
+
|
|
23
|
+
const inputRef = useRef<HTMLInputElement>(null)
|
|
24
|
+
|
|
25
|
+
useImperativeHandle(ref, () => inputRef.current as HTMLInputElement)
|
|
26
|
+
|
|
27
|
+
const [inputValue, setInputValue] = useState<string>('') // String to show in input
|
|
28
|
+
|
|
29
|
+
// Function to format the numeric value into a currency format
|
|
30
|
+
const formatNumber = (numericValue: number): string => {
|
|
31
|
+
const parts = numericValue.toFixed(2).split('.') // Ensure two decimal places
|
|
32
|
+
const integerPart = parts[0].replace(/\B(?=(\d{3})+(?!\d))/g, thousandSeparator) // Add thousand separators
|
|
33
|
+
return `${currencySymbol} ${integerPart}${decimalSeparator}${parts[1]}`
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
// Handle input change
|
|
37
|
+
const handleInputChange = (e: React.ChangeEvent<HTMLInputElement>) => {
|
|
38
|
+
const rawValue = e.target.value
|
|
39
|
+
const numericValue = parseFloat(rawValue.replace(/\D/g, '')) / 100
|
|
40
|
+
|
|
41
|
+
// Update the input with formatted value
|
|
42
|
+
setInputValue(formatNumber(numericValue))
|
|
43
|
+
|
|
44
|
+
// Send the numeric value (without formatting) to the parent component
|
|
45
|
+
onValueChange(numericValue)
|
|
46
|
+
|
|
47
|
+
// Move the cursor to the end of the input value
|
|
48
|
+
if (inputRef.current) {
|
|
49
|
+
window.requestAnimationFrame(() => {
|
|
50
|
+
inputRef.current?.setSelectionRange(
|
|
51
|
+
inputRef.current.value.length,
|
|
52
|
+
inputRef.current.value.length,
|
|
53
|
+
)
|
|
54
|
+
})
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
// Prevent cursor from being set elsewhere except at the end
|
|
59
|
+
const handleFocus = () => {
|
|
60
|
+
if (inputRef.current) {
|
|
61
|
+
inputRef.current.setSelectionRange(
|
|
62
|
+
inputRef.current.value.length,
|
|
63
|
+
inputRef.current.value.length,
|
|
64
|
+
)
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
// Set the initial formatted value when the component mounts or the value prop changes
|
|
69
|
+
useEffect(() => {
|
|
70
|
+
setInputValue(formatNumber(+value))
|
|
71
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
72
|
+
}, [value])
|
|
73
|
+
|
|
74
|
+
return (
|
|
75
|
+
<AdaptiveInput
|
|
76
|
+
type="text"
|
|
77
|
+
inputMode="numeric"
|
|
78
|
+
value={inputValue}
|
|
79
|
+
ref={inputRef}
|
|
80
|
+
onChange={handleInputChange}
|
|
81
|
+
onFocus={handleFocus}
|
|
82
|
+
onClick={handleFocus} // Ensures that even if the user clicks, the cursor is forced to the end
|
|
83
|
+
placeholder={`${currencySymbol} 0${decimalSeparator}00`}
|
|
84
|
+
className={className}
|
|
85
|
+
{...rest}
|
|
86
|
+
/>
|
|
87
|
+
)
|
|
88
|
+
},
|
|
89
|
+
)
|
|
90
|
+
|
|
91
|
+
CurrencyInput.displayName = 'CurrencyInput'
|
|
92
|
+
|
|
93
|
+
export { CurrencyInput }
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './currency-input'
|
package/src/components/index.ts
CHANGED
|
@@ -1,10 +1,12 @@
|
|
|
1
|
-
export * from './
|
|
1
|
+
export * from './adaptive-input'
|
|
2
|
+
export * from './alert-dialog'
|
|
2
3
|
export * from './autocomplete'
|
|
3
4
|
export * from './avatar'
|
|
4
5
|
export * from './badge'
|
|
5
6
|
export * from './button'
|
|
6
7
|
export * from './card'
|
|
7
8
|
export * from './checkbox'
|
|
9
|
+
export * from './currency-input'
|
|
8
10
|
export * from './dropdown-menu'
|
|
9
11
|
export * from './input'
|
|
10
12
|
export * from './password-input'
|
package/src/lib/index.ts
CHANGED
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
export const formatCurrency = (
|
|
2
|
+
number: number,
|
|
3
|
+
language = 'pt-BR',
|
|
4
|
+
currency = 'BRL',
|
|
5
|
+
): string => {
|
|
6
|
+
return new Intl.NumberFormat(language, {
|
|
7
|
+
style: 'currency',
|
|
8
|
+
currency,
|
|
9
|
+
minimumFractionDigits: 2,
|
|
10
|
+
}).format(number)
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export const formatDateAndWeekday = (date: Date | string, language = 'pt-BR'): string =>
|
|
14
|
+
new Intl.DateTimeFormat(language, {
|
|
15
|
+
day: '2-digit',
|
|
16
|
+
month: 'long',
|
|
17
|
+
weekday: 'long',
|
|
18
|
+
}).format(new Date(date))
|
|
19
|
+
|
|
20
|
+
export const formatDateAndWeekdayAndYear = (
|
|
21
|
+
date: Date | string,
|
|
22
|
+
language = 'pt-BR',
|
|
23
|
+
): string =>
|
|
24
|
+
new Intl.DateTimeFormat(language, {
|
|
25
|
+
day: '2-digit',
|
|
26
|
+
month: 'long',
|
|
27
|
+
weekday: 'long',
|
|
28
|
+
year: 'numeric',
|
|
29
|
+
}).format(new Date(date))
|
|
30
|
+
|
|
31
|
+
export const formatDateAndMonth = (date: Date | string, language = 'pt-BR'): string =>
|
|
32
|
+
new Intl.DateTimeFormat(language, {
|
|
33
|
+
day: '2-digit',
|
|
34
|
+
month: 'long',
|
|
35
|
+
}).format(new Date(date))
|
|
36
|
+
|
|
37
|
+
export const formatLongDate = (date: Date | string, language = 'pt-BR'): string =>
|
|
38
|
+
new Intl.DateTimeFormat(language, { dateStyle: 'long' }).format(
|
|
39
|
+
typeof date === 'string' ? new Date(date) : date,
|
|
40
|
+
)
|
|
41
|
+
|
|
42
|
+
export const formatShortDate = (date: Date, language = 'pt-BR'): string =>
|
|
43
|
+
new Intl.DateTimeFormat(language, { dateStyle: 'short' }).format(date)
|
|
44
|
+
|
|
45
|
+
export const getMonthYearFromISODate = (date: string): string => {
|
|
46
|
+
return date.slice(0, 7)
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
export const formatWeekDayAndShortDate = (date: Date, language = 'pt-BR') => {
|
|
50
|
+
return date.toLocaleDateString(language, {
|
|
51
|
+
weekday: 'short',
|
|
52
|
+
day: '2-digit',
|
|
53
|
+
month: '2-digit',
|
|
54
|
+
})
|
|
55
|
+
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export * from './adaptative-input';
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export * from './adaptative-input'
|
|
File without changes
|