torch-glare 1.0.2
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/LICENSE +21 -0
- package/README.md +207 -0
- package/cli/bin/addComponent.js +278 -0
- package/cli/bin/addHooks.js +75 -0
- package/cli/bin/addLayout.js +71 -0
- package/cli/bin/addProvider.js +71 -0
- package/cli/bin/addUtils.js +74 -0
- package/cli/bin/cli.js +73 -0
- package/cli/bin/init/init.js +15 -0
- package/cli/bin/init/tailwindInit.js +174 -0
- package/cli/bin/update.js +147 -0
- package/lib/components/ActionButton.tsx +63 -0
- package/lib/components/ActionsGroup.tsx +34 -0
- package/lib/components/AlertDialog.tsx +211 -0
- package/lib/components/Badge.tsx +116 -0
- package/lib/components/BadgeField.tsx +192 -0
- package/lib/components/Button.tsx +277 -0
- package/lib/components/Card.tsx +63 -0
- package/lib/components/Checkbox.tsx +122 -0
- package/lib/components/CountBadge.tsx +54 -0
- package/lib/components/DatePicker.tsx +464 -0
- package/lib/components/Drawer.tsx +118 -0
- package/lib/components/DropdownMenu.tsx +399 -0
- package/lib/components/FieldHint.tsx +76 -0
- package/lib/components/ImageAttachment.tsx +180 -0
- package/lib/components/InnerLabelField.tsx +155 -0
- package/lib/components/Input.tsx +179 -0
- package/lib/components/InputField.tsx +147 -0
- package/lib/components/Label.tsx +107 -0
- package/lib/components/LabelField.tsx +75 -0
- package/lib/components/LabeledCheckBox.tsx +65 -0
- package/lib/components/LabeledRadio.tsx +45 -0
- package/lib/components/LinkButton.tsx +94 -0
- package/lib/components/LoginButton.tsx +56 -0
- package/lib/components/PasswordLevel.tsx +58 -0
- package/lib/components/Popover.tsx +274 -0
- package/lib/components/ProfileMenu.tsx +90 -0
- package/lib/components/Radio.tsx +77 -0
- package/lib/components/RadioCard.tsx +72 -0
- package/lib/components/RingLoading.tsx +190 -0
- package/lib/components/SearchField.tsx +49 -0
- package/lib/components/Select.tsx +417 -0
- package/lib/components/SlideDatePicker.tsx +120 -0
- package/lib/components/SpinLoading.tsx +190 -0
- package/lib/components/Switcher.tsx +56 -0
- package/lib/components/TabFormItem.tsx +158 -0
- package/lib/components/Table.tsx +395 -0
- package/lib/components/Textarea.tsx +108 -0
- package/lib/components/Tooltip.tsx +111 -0
- package/lib/components/TransparentLabel.tsx +72 -0
- package/lib/components/TreeDropDown.tsx +69 -0
- package/lib/hooks/MobileSlidePicker/components/Picker.tsx +218 -0
- package/lib/hooks/MobileSlidePicker/components/PickerColumn.tsx +238 -0
- package/lib/hooks/MobileSlidePicker/components/PickerItem.tsx +64 -0
- package/lib/hooks/MobileSlidePicker/index.ts +10 -0
- package/lib/hooks/useActiveTreeItem.tsx +61 -0
- package/lib/hooks/useClickOutside.tsx +20 -0
- package/lib/hooks/useResize.tsx +78 -0
- package/lib/layouts/CLayout.tsx +326 -0
- package/lib/layouts/FieldSection.tsx +64 -0
- package/lib/layouts/TreeSubLayout.tsx +187 -0
- package/lib/providers/ThemeProvider.tsx +99 -0
- package/lib/utils/cn.ts +6 -0
- package/lib/utils/convertImageFileToDataUrl.ts +17 -0
- package/lib/utils/resize.ts +35 -0
- package/lib/utils/types.ts +12 -0
- package/package.json +28 -0
- package/torch-glare.js +24 -0
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import { forwardRef, InputHTMLAttributes, ReactNode, useState } from "react";
|
|
4
|
+
import { InputField } from "./InputField";
|
|
5
|
+
import { ToolTipSide } from "./Tooltip";
|
|
6
|
+
import { cn } from "../utils/cn";
|
|
7
|
+
import { Themes } from "../utils/types";
|
|
8
|
+
|
|
9
|
+
interface Props
|
|
10
|
+
extends Omit<InputHTMLAttributes<HTMLInputElement>, "size" | "variant"> {
|
|
11
|
+
size?: "S" | "M"; // this is used to change the size style of the component
|
|
12
|
+
variant?: "SystemStyle" | "PresentationStyle";
|
|
13
|
+
icon?: ReactNode; // to add left side icon if you pass it
|
|
14
|
+
childrenSide?: ReactNode; // to add action button to the end of the input
|
|
15
|
+
popoverChildren?: ReactNode; // to add drop down list if you pass it
|
|
16
|
+
errorMessage?: string; // to show tooltip component when error_message not null
|
|
17
|
+
onTable?: boolean; // to change the border style of the component when it is on table
|
|
18
|
+
label?: string; // to show label
|
|
19
|
+
required?: boolean; // to show required icon
|
|
20
|
+
toolTipSide?: ToolTipSide;
|
|
21
|
+
theme?: Themes
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export const InnerLabelField = forwardRef<HTMLInputElement, Props>(
|
|
25
|
+
(
|
|
26
|
+
{
|
|
27
|
+
size = "S",
|
|
28
|
+
icon,
|
|
29
|
+
childrenSide,
|
|
30
|
+
popoverChildren,
|
|
31
|
+
errorMessage,
|
|
32
|
+
onTable,
|
|
33
|
+
variant,
|
|
34
|
+
className,
|
|
35
|
+
label,
|
|
36
|
+
theme,
|
|
37
|
+
required,
|
|
38
|
+
toolTipSide,
|
|
39
|
+
...props
|
|
40
|
+
},
|
|
41
|
+
ref
|
|
42
|
+
) => {
|
|
43
|
+
const [focus, setFocus] = useState(false);
|
|
44
|
+
const [isEmpty, setIsEmpty] = useState(!props.value);
|
|
45
|
+
|
|
46
|
+
return (
|
|
47
|
+
<InputField
|
|
48
|
+
{...props}
|
|
49
|
+
theme={theme}
|
|
50
|
+
onFocus={(e) => {
|
|
51
|
+
setFocus(true);
|
|
52
|
+
props.onFocus?.(e);
|
|
53
|
+
}}
|
|
54
|
+
onBlur={(e) => {
|
|
55
|
+
setFocus(false);
|
|
56
|
+
props.onBlur?.(e);
|
|
57
|
+
}}
|
|
58
|
+
onChange={(e) => {
|
|
59
|
+
setIsEmpty(!e.target.value);
|
|
60
|
+
props.onChange?.(e);
|
|
61
|
+
}}
|
|
62
|
+
className={cn(className, "group")}
|
|
63
|
+
ref={ref}
|
|
64
|
+
toolTipSide={toolTipSide}
|
|
65
|
+
size={size}
|
|
66
|
+
variant={variant}
|
|
67
|
+
childrenSide={childrenSide}
|
|
68
|
+
popoverChildren={popoverChildren}
|
|
69
|
+
errorMessage={errorMessage}
|
|
70
|
+
onTable={onTable}
|
|
71
|
+
icon={
|
|
72
|
+
<Label
|
|
73
|
+
focus={focus}
|
|
74
|
+
isEmpty={isEmpty}
|
|
75
|
+
label={label}
|
|
76
|
+
required={required}
|
|
77
|
+
disabled={props.disabled}
|
|
78
|
+
error={!errorMessage}
|
|
79
|
+
/>
|
|
80
|
+
}
|
|
81
|
+
/>
|
|
82
|
+
);
|
|
83
|
+
}
|
|
84
|
+
);
|
|
85
|
+
|
|
86
|
+
InnerLabelField.displayName = "LabelLessInput"
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
// TODO: Active label when input is empty
|
|
90
|
+
// TODO: Active on Hover
|
|
91
|
+
// TODO: Active on Focus when input is empty
|
|
92
|
+
// TODO: Active on Disabled when input is empty
|
|
93
|
+
// TODO: Active on Error when input is empty
|
|
94
|
+
|
|
95
|
+
const Label = ({
|
|
96
|
+
|
|
97
|
+
focus,
|
|
98
|
+
isEmpty,
|
|
99
|
+
label,
|
|
100
|
+
required,
|
|
101
|
+
disabled,
|
|
102
|
+
error,
|
|
103
|
+
}: {
|
|
104
|
+
focus: boolean;
|
|
105
|
+
isEmpty: boolean;
|
|
106
|
+
label?: string;
|
|
107
|
+
required?: boolean;
|
|
108
|
+
disabled?: boolean;
|
|
109
|
+
error?: boolean;
|
|
110
|
+
}) => {
|
|
111
|
+
return (
|
|
112
|
+
<section className="flex items-center">
|
|
113
|
+
<section
|
|
114
|
+
className={cn([
|
|
115
|
+
"px-[3px]",
|
|
116
|
+
"typography-labels-small-regular",
|
|
117
|
+
"text-content-presentation-global-secondary",
|
|
118
|
+
"flex",
|
|
119
|
+
"items-center",
|
|
120
|
+
])}
|
|
121
|
+
>
|
|
122
|
+
<p
|
|
123
|
+
className={cn(
|
|
124
|
+
"transition-all",
|
|
125
|
+
"duration-300",
|
|
126
|
+
"ease-in-out",
|
|
127
|
+
"group-hover:text-content-presentation-global-primary group-hover:typography-body-small-regular",
|
|
128
|
+
{ "text-content-presentation-global-primary typography-body-small-regular": isEmpty },
|
|
129
|
+
{ "text-content-presentation-global-primary typography-body-small-regular": focus && isEmpty },
|
|
130
|
+
{ "text-content-presentation-global-primary typography-body-small-regular": error && isEmpty },
|
|
131
|
+
{ "text-content-presentation-global-primary typography-body-small-regular": disabled && isEmpty },
|
|
132
|
+
)}
|
|
133
|
+
>
|
|
134
|
+
{label}
|
|
135
|
+
</p>
|
|
136
|
+
{required && (
|
|
137
|
+
<p className="text-content-presentation-state-negative">*</p>
|
|
138
|
+
)}
|
|
139
|
+
</section>
|
|
140
|
+
<span
|
|
141
|
+
className={cn(
|
|
142
|
+
"w-[1px]",
|
|
143
|
+
"h-[12px]",
|
|
144
|
+
"bg-border-presentation-action-primary ",
|
|
145
|
+
"transition-all",
|
|
146
|
+
"duration-300",
|
|
147
|
+
"ease-in-out",
|
|
148
|
+
"rounded-full",
|
|
149
|
+
"group-hover:bg-border-presentation-action-hover",
|
|
150
|
+
"group-hover:h-[22px]",
|
|
151
|
+
)}
|
|
152
|
+
/>
|
|
153
|
+
</section>
|
|
154
|
+
);
|
|
155
|
+
};
|
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
import React, { forwardRef, HTMLAttributes, InputHTMLAttributes } from 'react'
|
|
2
|
+
import { cn } from '../utils/cn'
|
|
3
|
+
import { cva } from 'class-variance-authority';
|
|
4
|
+
|
|
5
|
+
export const GroupStyles = cva(
|
|
6
|
+
[
|
|
7
|
+
"flex w-full min-w-0 px-1 justify-center items-center",
|
|
8
|
+
"typography-body-small-regular",
|
|
9
|
+
"border",
|
|
10
|
+
"transition-all duration-200 ease-in-out",
|
|
11
|
+
"hover:shadow-[0px_1px_6px_0px_rgba(0,0,0,0.30)]",
|
|
12
|
+
"[&_i]:leading-[0px] leading-[0px]",
|
|
13
|
+
'[&:has(input[disabled="true"])]:!border-border-presentation-action-disabled',
|
|
14
|
+
'[&:has(input[disabled="true"])]:!bg-background-presentation-action-disabled',
|
|
15
|
+
'[&:has(input[disabled="true"])]:hover:border-border-presentation-action-disabled',
|
|
16
|
+
'[&:has(input[disabled="true"])]:hover:bg-background-presentation-action-disabled',
|
|
17
|
+
],
|
|
18
|
+
{
|
|
19
|
+
variants: {
|
|
20
|
+
variant: {
|
|
21
|
+
PresentationStyle: [
|
|
22
|
+
"bg-background-presentation-form-field-primary",
|
|
23
|
+
"border-border-presentation-action-primary",
|
|
24
|
+
"hover:bg-background-presentation-form-field-hover",
|
|
25
|
+
"hover:border-border-presentation-action-hover",
|
|
26
|
+
"hover:text-content-presentation-action-light-primary",
|
|
27
|
+
'focus-within:border-border-presentation-state-focus',
|
|
28
|
+
'focus-within:bg-background-presentation-form-field-primary',
|
|
29
|
+
'focus-within:shadow-[0px_1px_6px_0px_rgba(0,0,0,0.30)]',
|
|
30
|
+
'focus-within:hover:border-border-presentation-state-focus',
|
|
31
|
+
'focus-within:caret-border-presentation-state-focus',
|
|
32
|
+
'focus-within:hover:caret-border-presentation-state-focus',
|
|
33
|
+
],
|
|
34
|
+
SystemStyle: [
|
|
35
|
+
"bg-black-alpha-20",
|
|
36
|
+
"text-white",
|
|
37
|
+
"border-[#2C2D2E]",
|
|
38
|
+
"hover:border-[#9748FF]",
|
|
39
|
+
"hover:bg-purple-alpha-10",
|
|
40
|
+
'focus-within:border-border-presentation-state-focus',
|
|
41
|
+
'focus-within:shadow-[0px_1px_6px_0px_rgba(0,0,0,0.30)]',
|
|
42
|
+
'focus-within:hover:border-border-presentation-state-focus',
|
|
43
|
+
'focus-within:caret-border-presentation-state-focus',
|
|
44
|
+
'focus-within:hover:caret-border-presentation-state-focus',
|
|
45
|
+
'focus-within:hover:bg-black-alpha-20',
|
|
46
|
+
"[&_div[data-role='icon']]:focus-within:text-white",
|
|
47
|
+
"[&_input]:placeholder:text-[#A0A0A0]",
|
|
48
|
+
"[&_input]:hover:placeholder:text-[#A0A0A0]",
|
|
49
|
+
"[&_input]:text-white"
|
|
50
|
+
],
|
|
51
|
+
},
|
|
52
|
+
size: {
|
|
53
|
+
S: ["h-[30px]", "rounded-[6px] [&_input]:h-[30px] [&_div[data-role='icon']]:text-[16px]"],
|
|
54
|
+
M: ["h-[40px]", "rounded-[8px] [&_input]:h-[40px] [&_div[data-role='icon']]:text-[18px] [&_div[data-role='icon']]:px-[2px]"],
|
|
55
|
+
},
|
|
56
|
+
error: {
|
|
57
|
+
true: [
|
|
58
|
+
"border-border-presentation-state-negative",
|
|
59
|
+
"caret-border-presentation-state-negative",
|
|
60
|
+
"hover:border-border-presentation-state-negative",
|
|
61
|
+
"hover:caret-border-presentation-state-negative",
|
|
62
|
+
],
|
|
63
|
+
},
|
|
64
|
+
onTable: {
|
|
65
|
+
true: [
|
|
66
|
+
'border-transparent',
|
|
67
|
+
'bg-transparent',
|
|
68
|
+
'h-[26px]',
|
|
69
|
+
],
|
|
70
|
+
},
|
|
71
|
+
},
|
|
72
|
+
|
|
73
|
+
}
|
|
74
|
+
);
|
|
75
|
+
|
|
76
|
+
interface InputGroupProps extends Omit<HTMLAttributes<HTMLDivElement>, "size"> {
|
|
77
|
+
size?: 'S' | 'M';
|
|
78
|
+
variant?: 'PresentationStyle' | 'SystemStyle';
|
|
79
|
+
error?: boolean;
|
|
80
|
+
onTable?: boolean;
|
|
81
|
+
ref?: any
|
|
82
|
+
className?: string;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
export const Group = ({ size = 'M', variant = "PresentationStyle", error = false, onTable = false, ref, className, ...props }: InputGroupProps) => {
|
|
86
|
+
return (
|
|
87
|
+
<div
|
|
88
|
+
className={cn(GroupStyles({ size, variant, error, onTable }), className)}
|
|
89
|
+
ref={ref}
|
|
90
|
+
{...props}>
|
|
91
|
+
</div>
|
|
92
|
+
)
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
interface IconProps {
|
|
98
|
+
children: React.ReactNode;
|
|
99
|
+
className?: string;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
export const Icon = ({ children, className }: IconProps) => {
|
|
103
|
+
return (
|
|
104
|
+
<div
|
|
105
|
+
className={cn(
|
|
106
|
+
"flex items-center justify-center",
|
|
107
|
+
"transition-all duration-200 ease-in-out",
|
|
108
|
+
"leading-0 text-content-presentation-action-light-secondary",
|
|
109
|
+
className
|
|
110
|
+
)} data-role="icon">
|
|
111
|
+
{children}
|
|
112
|
+
</div>
|
|
113
|
+
);
|
|
114
|
+
};
|
|
115
|
+
|
|
116
|
+
|
|
117
|
+
interface TrillingProps {
|
|
118
|
+
children: React.ReactNode;
|
|
119
|
+
className?: string;
|
|
120
|
+
}
|
|
121
|
+
export const Trilling = ({ children, className }: TrillingProps) => {
|
|
122
|
+
return (
|
|
123
|
+
<div
|
|
124
|
+
className={cn(
|
|
125
|
+
"flex items-center justify-center h-full gap-1 py-1",
|
|
126
|
+
className
|
|
127
|
+
)}
|
|
128
|
+
>
|
|
129
|
+
{children}
|
|
130
|
+
</div>
|
|
131
|
+
)
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
|
|
135
|
+
|
|
136
|
+
|
|
137
|
+
interface InputProps extends Omit<InputHTMLAttributes<HTMLInputElement>, "size"> {
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
export const Input = forwardRef<HTMLInputElement, InputProps>(
|
|
141
|
+
({ className, ...props }, ref) => {
|
|
142
|
+
return (
|
|
143
|
+
<input
|
|
144
|
+
{...props}
|
|
145
|
+
autoComplete="off"
|
|
146
|
+
className={cn(
|
|
147
|
+
// Base styles
|
|
148
|
+
"typography-body-small-regular",
|
|
149
|
+
"text-content-presentation-action-light-primary",
|
|
150
|
+
"bg-transparent",
|
|
151
|
+
"h-full",
|
|
152
|
+
"px-[4px]",
|
|
153
|
+
"flex-[1_1_0%]",
|
|
154
|
+
"min-w-[30px]",
|
|
155
|
+
"outline-none",
|
|
156
|
+
"transition-all duration-200 ease-in-out",
|
|
157
|
+
"[mask-image:linear-gradient(to_right,black_0%,black_0%,black_85%,transparent_100%)]",
|
|
158
|
+
"rtl:[mask-image:linear-gradient(to_left,black_0%,black_0%,black_85%,transparent_100%)]",
|
|
159
|
+
"hover:placeholder:text-content-presentation-action-light-primary",
|
|
160
|
+
className
|
|
161
|
+
)}
|
|
162
|
+
ref={ref}
|
|
163
|
+
/>
|
|
164
|
+
);
|
|
165
|
+
}
|
|
166
|
+
);
|
|
167
|
+
|
|
168
|
+
Input.displayName = "Input";
|
|
169
|
+
|
|
170
|
+
|
|
171
|
+
/* // solution to fix autofill issue
|
|
172
|
+
input:-webkit-autofill,
|
|
173
|
+
input:-webkit-autofill:hover,
|
|
174
|
+
input:-webkit-autofill:focus,
|
|
175
|
+
input:-webkit-autofill:active {
|
|
176
|
+
-webkit-transition: "color 1000s ease-out, background-color 1000s ease-out";
|
|
177
|
+
-webkit-transition-delay: 1000s;
|
|
178
|
+
}
|
|
179
|
+
*/
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import {
|
|
3
|
+
forwardRef,
|
|
4
|
+
InputHTMLAttributes,
|
|
5
|
+
ReactNode,
|
|
6
|
+
useEffect,
|
|
7
|
+
useRef,
|
|
8
|
+
useState,
|
|
9
|
+
} from "react";
|
|
10
|
+
import { cn } from "../utils/cn";
|
|
11
|
+
import { Tooltip, ToolTipSide } from "./Tooltip";
|
|
12
|
+
import { Popover, PopoverContent, PopoverTrigger } from "./Popover";
|
|
13
|
+
import { ActionButton } from "./ActionButton";
|
|
14
|
+
import { Themes } from "../utils/types";
|
|
15
|
+
import { Icon, Input, Group, Trilling } from "./Input";
|
|
16
|
+
|
|
17
|
+
export interface Props
|
|
18
|
+
extends Omit<InputHTMLAttributes<HTMLInputElement>, "size" | "variant"> {
|
|
19
|
+
size?: "S" | "M"; // this is used to change the size style of the component
|
|
20
|
+
variant?: "SystemStyle" | "PresentationStyle";
|
|
21
|
+
icon?: ReactNode; // to add left side icon if you pass it
|
|
22
|
+
childrenSide?: ReactNode; // to add action button to the end of the input
|
|
23
|
+
popoverChildren?: ReactNode; // to add drop down list if you pass it
|
|
24
|
+
errorMessage?: string; // to show tooltip component when error_message not null
|
|
25
|
+
onTable?: boolean; // to change the border style of the component when it is on table
|
|
26
|
+
toolTipSide?: ToolTipSide;
|
|
27
|
+
theme?: Themes
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
export const InputField = forwardRef<HTMLInputElement, Props>(
|
|
32
|
+
(
|
|
33
|
+
{
|
|
34
|
+
size = "M",
|
|
35
|
+
icon,
|
|
36
|
+
childrenSide,
|
|
37
|
+
popoverChildren,
|
|
38
|
+
errorMessage,
|
|
39
|
+
onTable,
|
|
40
|
+
variant = "PresentationStyle",
|
|
41
|
+
toolTipSide,
|
|
42
|
+
theme,
|
|
43
|
+
className,
|
|
44
|
+
...props
|
|
45
|
+
},
|
|
46
|
+
forwardedRef
|
|
47
|
+
) => {
|
|
48
|
+
const [isPopoverOpen, setIsPopoverOpen] = useState(false);
|
|
49
|
+
const [PopoverWidth, setPopoverWidth] = useState(0);
|
|
50
|
+
const inputRef = useRef<HTMLInputElement>(null);
|
|
51
|
+
|
|
52
|
+
useEffect(() => {
|
|
53
|
+
if (!forwardedRef) return;
|
|
54
|
+
if (typeof forwardedRef === "function") forwardedRef(inputRef.current);
|
|
55
|
+
else forwardedRef.current = inputRef.current;
|
|
56
|
+
}, [forwardedRef]);
|
|
57
|
+
// TODO: make the user input visible when input is focused
|
|
58
|
+
return (
|
|
59
|
+
<Popover open={isPopoverOpen}>
|
|
60
|
+
<Tooltip
|
|
61
|
+
theme={theme}
|
|
62
|
+
toolTipSide={toolTipSide}
|
|
63
|
+
open={errorMessage !== undefined}
|
|
64
|
+
text={errorMessage}
|
|
65
|
+
>
|
|
66
|
+
<PopoverTrigger asChild>
|
|
67
|
+
<div>
|
|
68
|
+
<Group
|
|
69
|
+
error={errorMessage !== undefined}
|
|
70
|
+
onTable={onTable}
|
|
71
|
+
size={size}
|
|
72
|
+
variant={variant}
|
|
73
|
+
data-theme={theme}
|
|
74
|
+
onFocus={(e) => {
|
|
75
|
+
setPopoverWidth(e.currentTarget.offsetWidth);
|
|
76
|
+
setIsPopoverOpen(!isPopoverOpen);
|
|
77
|
+
inputRef.current?.focus();
|
|
78
|
+
}}
|
|
79
|
+
className={className}
|
|
80
|
+
>
|
|
81
|
+
{icon && (
|
|
82
|
+
<Icon>
|
|
83
|
+
{icon}
|
|
84
|
+
</Icon>
|
|
85
|
+
)}
|
|
86
|
+
<Input
|
|
87
|
+
{...props}
|
|
88
|
+
onFocus={(e) => {
|
|
89
|
+
setIsPopoverOpen(true)
|
|
90
|
+
props.onFocus?.(e)
|
|
91
|
+
}}
|
|
92
|
+
onBlur={(e) => {
|
|
93
|
+
setIsPopoverOpen(false)
|
|
94
|
+
props.onBlur?.(e)
|
|
95
|
+
}}
|
|
96
|
+
ref={inputRef}
|
|
97
|
+
/>
|
|
98
|
+
|
|
99
|
+
<Trilling >
|
|
100
|
+
{childrenSide}
|
|
101
|
+
{popoverChildren && (
|
|
102
|
+
<PopoverActionButton size={size} variant={variant} isPopoverOpen={isPopoverOpen} />
|
|
103
|
+
)}
|
|
104
|
+
</Trilling>
|
|
105
|
+
</Group>
|
|
106
|
+
</div>
|
|
107
|
+
</PopoverTrigger>
|
|
108
|
+
</Tooltip>
|
|
109
|
+
|
|
110
|
+
|
|
111
|
+
{
|
|
112
|
+
popoverChildren && (
|
|
113
|
+
<PopoverContent
|
|
114
|
+
theme={theme}
|
|
115
|
+
variant={variant}
|
|
116
|
+
onOpenAutoFocus={(e: any) => e.preventDefault()}
|
|
117
|
+
style={{ width: PopoverWidth }}
|
|
118
|
+
>
|
|
119
|
+
{popoverChildren}
|
|
120
|
+
</PopoverContent>
|
|
121
|
+
)
|
|
122
|
+
}
|
|
123
|
+
</Popover >
|
|
124
|
+
);
|
|
125
|
+
}
|
|
126
|
+
);
|
|
127
|
+
|
|
128
|
+
InputField.displayName = "InputField";
|
|
129
|
+
|
|
130
|
+
const PopoverActionButton = ({ size, variant, isPopoverOpen }: { size: "S" | "M", variant: "SystemStyle" | "PresentationStyle", isPopoverOpen: boolean }) => {
|
|
131
|
+
return (
|
|
132
|
+
<ActionButton size={size}>
|
|
133
|
+
<i
|
|
134
|
+
className={cn(
|
|
135
|
+
"ri-arrow-down-s-line",
|
|
136
|
+
"transition-[transform,rotate]",
|
|
137
|
+
"duration-200",
|
|
138
|
+
"ease-in-out",
|
|
139
|
+
{ "rotate-180": isPopoverOpen },
|
|
140
|
+
{ "!text-[16px]": size === "S" },
|
|
141
|
+
{ "!text-[26px]": size === "M" },
|
|
142
|
+
{ "text-white": variant === "SystemStyle" }
|
|
143
|
+
)}
|
|
144
|
+
/>
|
|
145
|
+
</ActionButton>
|
|
146
|
+
);
|
|
147
|
+
};
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
import { LabelHTMLAttributes, ReactNode } from "react";
|
|
2
|
+
import React from "react";
|
|
3
|
+
import { cn } from "../utils/cn";
|
|
4
|
+
import { cva, type VariantProps } from "class-variance-authority";
|
|
5
|
+
import { Themes } from "../utils/types";
|
|
6
|
+
|
|
7
|
+
const labelComponentVariants = cva("flex", {
|
|
8
|
+
variants: {
|
|
9
|
+
directions: {
|
|
10
|
+
vertical: "flex-col justify-start items-start",
|
|
11
|
+
horizontal: "flex-row justify-start items-center gap-1",
|
|
12
|
+
},
|
|
13
|
+
},
|
|
14
|
+
defaultVariants: {
|
|
15
|
+
directions: "horizontal",
|
|
16
|
+
},
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
interface Props
|
|
20
|
+
extends LabelHTMLAttributes<HTMLDivElement>,
|
|
21
|
+
VariantProps<typeof labelComponentVariants> {
|
|
22
|
+
label?: ReactNode; // main label
|
|
23
|
+
requiredLabel?: ReactNode; // normal text with required style
|
|
24
|
+
secondaryLabel?: ReactNode; // normal text with secondary style
|
|
25
|
+
as?: React.ElementType;
|
|
26
|
+
asChild?: boolean;
|
|
27
|
+
size?: "S" | "M" | "L";
|
|
28
|
+
variant?: "SystemStyle" | "PresentationStyle";
|
|
29
|
+
theme?: Themes
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export const Label = React.forwardRef<HTMLDivElement, Props>(
|
|
33
|
+
(
|
|
34
|
+
{
|
|
35
|
+
children,
|
|
36
|
+
label,
|
|
37
|
+
secondaryLabel,
|
|
38
|
+
requiredLabel,
|
|
39
|
+
size = "M",
|
|
40
|
+
directions,
|
|
41
|
+
className,
|
|
42
|
+
variant = "PresentationStyle",
|
|
43
|
+
theme,
|
|
44
|
+
...props
|
|
45
|
+
},
|
|
46
|
+
forwardedRef
|
|
47
|
+
) => {
|
|
48
|
+
return (
|
|
49
|
+
<div
|
|
50
|
+
data-theme={theme}
|
|
51
|
+
className={cn(labelComponentVariants({ directions }), className)} // Merge generated and custom classNames
|
|
52
|
+
ref={forwardedRef}
|
|
53
|
+
{...props}
|
|
54
|
+
>
|
|
55
|
+
{label && (
|
|
56
|
+
<p
|
|
57
|
+
className={cn(
|
|
58
|
+
"text-start",
|
|
59
|
+
{
|
|
60
|
+
"typography-body-small-regular": size === "S",
|
|
61
|
+
"typography-body-medium-regular": size === "M",
|
|
62
|
+
"typography-body-large-regular": size === "L",
|
|
63
|
+
},
|
|
64
|
+
{
|
|
65
|
+
"text-content-presentation-global-primary":
|
|
66
|
+
variant === "PresentationStyle",
|
|
67
|
+
"text-[#E5E5E5]": variant === "SystemStyle",
|
|
68
|
+
}
|
|
69
|
+
)}
|
|
70
|
+
>
|
|
71
|
+
{label}
|
|
72
|
+
</p>
|
|
73
|
+
)}
|
|
74
|
+
{secondaryLabel && (
|
|
75
|
+
<p
|
|
76
|
+
className={cn(
|
|
77
|
+
"text-content-presentation-global-secondary text-start",
|
|
78
|
+
{
|
|
79
|
+
"typography-labels-small-regular": size === "S",
|
|
80
|
+
"typography-labels-medium-regular": size === "M",
|
|
81
|
+
"typography-body-small-regular": size === "L",
|
|
82
|
+
}
|
|
83
|
+
)}
|
|
84
|
+
>
|
|
85
|
+
{secondaryLabel}
|
|
86
|
+
</p>
|
|
87
|
+
)}
|
|
88
|
+
{requiredLabel && (
|
|
89
|
+
<p
|
|
90
|
+
className={cn(
|
|
91
|
+
"text-content-presentation-state-negative text-start",
|
|
92
|
+
{
|
|
93
|
+
"typography-labels-small-medium": size === "S",
|
|
94
|
+
"typography-labels-medium-medium": size === "M",
|
|
95
|
+
"typography-body-small-medium": size === "L",
|
|
96
|
+
}
|
|
97
|
+
)}
|
|
98
|
+
>
|
|
99
|
+
{requiredLabel}
|
|
100
|
+
</p>
|
|
101
|
+
)}
|
|
102
|
+
{children}
|
|
103
|
+
</div>
|
|
104
|
+
);
|
|
105
|
+
}
|
|
106
|
+
);
|
|
107
|
+
Label.displayName = "Label";
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import { InputHTMLAttributes, ReactNode, forwardRef } from "react";
|
|
2
|
+
import { InputField } from "./InputField";
|
|
3
|
+
import { cn } from "../utils/cn";
|
|
4
|
+
import { Label } from "./Label";
|
|
5
|
+
import { ToolTipSide } from "./Tooltip";
|
|
6
|
+
import { Themes } from "../utils/types";
|
|
7
|
+
|
|
8
|
+
export interface Props
|
|
9
|
+
extends Omit<InputHTMLAttributes<HTMLInputElement>, "size" | "variant"> {
|
|
10
|
+
size?: "S" | "M"; // this is used to change the size style of the component
|
|
11
|
+
variant?: "SystemStyle" | "PresentationStyle";
|
|
12
|
+
icon?: ReactNode; // to add left side icon if you pass it
|
|
13
|
+
childrenSide?: ReactNode; // to add action button to the end of the input
|
|
14
|
+
popoverChildren?: ReactNode; // to add drop down list if you pass it
|
|
15
|
+
errorMessage?: string; // to show tooltip component when error_message not null
|
|
16
|
+
onTable?: boolean; // to change the border style of the component when it is on table
|
|
17
|
+
label?: ReactNode; // main label
|
|
18
|
+
requiredLabel?: ReactNode; // normal text with required style
|
|
19
|
+
secondaryLabel?: ReactNode; // normal text with secondary style
|
|
20
|
+
labelDirections?: "vertical" | "horizontal"; // to change the direction of the label
|
|
21
|
+
toolTipSide?: ToolTipSide;
|
|
22
|
+
theme?: Themes
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export const LabelField = forwardRef<HTMLInputElement, Props>(
|
|
26
|
+
(
|
|
27
|
+
{
|
|
28
|
+
label,
|
|
29
|
+
requiredLabel,
|
|
30
|
+
secondaryLabel,
|
|
31
|
+
size,
|
|
32
|
+
variant,
|
|
33
|
+
theme,
|
|
34
|
+
icon,
|
|
35
|
+
childrenSide,
|
|
36
|
+
popoverChildren,
|
|
37
|
+
errorMessage,
|
|
38
|
+
onTable,
|
|
39
|
+
className,
|
|
40
|
+
labelDirections,
|
|
41
|
+
toolTipSide,
|
|
42
|
+
|
|
43
|
+
...props
|
|
44
|
+
},
|
|
45
|
+
ref
|
|
46
|
+
) => {
|
|
47
|
+
return (
|
|
48
|
+
<section data-theme={theme} className={cn("flex flex-col gap-1 flex-1 w-full", className)}>
|
|
49
|
+
<Label
|
|
50
|
+
label={label}
|
|
51
|
+
requiredLabel={requiredLabel}
|
|
52
|
+
secondaryLabel={secondaryLabel}
|
|
53
|
+
directions={labelDirections}
|
|
54
|
+
variant={variant}
|
|
55
|
+
/>
|
|
56
|
+
<InputField
|
|
57
|
+
{...props}
|
|
58
|
+
theme={theme}
|
|
59
|
+
className={className}
|
|
60
|
+
ref={ref}
|
|
61
|
+
size={size}
|
|
62
|
+
icon={icon}
|
|
63
|
+
toolTipSide={toolTipSide}
|
|
64
|
+
variant={variant}
|
|
65
|
+
childrenSide={childrenSide}
|
|
66
|
+
popoverChildren={popoverChildren}
|
|
67
|
+
errorMessage={errorMessage}
|
|
68
|
+
onTable={onTable}
|
|
69
|
+
/>
|
|
70
|
+
</section>
|
|
71
|
+
);
|
|
72
|
+
}
|
|
73
|
+
);
|
|
74
|
+
|
|
75
|
+
LabelField.displayName = "LabelField";
|