wini-web-components 0.1.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 (62) hide show
  1. package/README.md +70 -0
  2. package/package.json +62 -0
  3. package/public/favicon.ico +0 -0
  4. package/public/index.html +43 -0
  5. package/public/logo192.png +0 -0
  6. package/public/logo512.png +0 -0
  7. package/public/manifest.json +25 -0
  8. package/public/robots.txt +3 -0
  9. package/src/App.css +38 -0
  10. package/src/App.js +25 -0
  11. package/src/App.test.js +8 -0
  12. package/src/component/calendar/calendar.css +133 -0
  13. package/src/component/calendar/calendar.tsx +448 -0
  14. package/src/component/checkbox/checkbox.css +46 -0
  15. package/src/component/checkbox/checkbox.tsx +59 -0
  16. package/src/component/component-status.tsx +53 -0
  17. package/src/component/date-picker/date-picker.css +114 -0
  18. package/src/component/date-picker/date-picker.tsx +363 -0
  19. package/src/component/dialog/dialog.css +125 -0
  20. package/src/component/dialog/dialog.tsx +91 -0
  21. package/src/component/export-component.js +48 -0
  22. package/src/component/import-file/import-file.css +86 -0
  23. package/src/component/import-file/import-file.tsx +154 -0
  24. package/src/component/infinite-scroll/infinite-scroll.css +37 -0
  25. package/src/component/infinite-scroll/infinite-scroll.tsx +33 -0
  26. package/src/component/input-multi-select/input-multi-select.css +127 -0
  27. package/src/component/input-multi-select/input-multi-select.tsx +261 -0
  28. package/src/component/pagination/pagination.css +69 -0
  29. package/src/component/pagination/pagination.tsx +65 -0
  30. package/src/component/popup/popup.css +90 -0
  31. package/src/component/popup/popup.tsx +105 -0
  32. package/src/component/progress-bar/progress-bar.css +47 -0
  33. package/src/component/progress-bar/progress-bar.tsx +34 -0
  34. package/src/component/progress-circle/progress-circle.css +47 -0
  35. package/src/component/progress-circle/progress-circle.tsx +24 -0
  36. package/src/component/radio-button/radio-button.css +49 -0
  37. package/src/component/radio-button/radio-button.tsx +59 -0
  38. package/src/component/rating/rating.css +11 -0
  39. package/src/component/rating/rating.tsx +65 -0
  40. package/src/component/select1/select1.css +155 -0
  41. package/src/component/select1/select1.tsx +241 -0
  42. package/src/component/slider/slider.css +16 -0
  43. package/src/component/slider/slider.tsx +87 -0
  44. package/src/component/switch/switch.css +53 -0
  45. package/src/component/switch/switch.tsx +67 -0
  46. package/src/component/table/table.css +74 -0
  47. package/src/component/table/table.tsx +99 -0
  48. package/src/component/text/text.css +16 -0
  49. package/src/component/text/text.tsx +21 -0
  50. package/src/component/text-area/text-area.css +63 -0
  51. package/src/component/text-area/text-area.tsx +55 -0
  52. package/src/component/text-field/text-field.css +64 -0
  53. package/src/component/text-field/text-field.tsx +63 -0
  54. package/src/component/toast-noti/toast-noti.css +0 -0
  55. package/src/component/toast-noti/toast-noti.tsx +21 -0
  56. package/src/index.css +13 -0
  57. package/src/index.js +17 -0
  58. package/src/logo.svg +1 -0
  59. package/src/reportWebVitals.js +13 -0
  60. package/src/setupTests.js +5 -0
  61. package/src/skin/color.css +17 -0
  62. package/src/skin/typography.css +378 -0
@@ -0,0 +1,87 @@
1
+ import React, { CSSProperties, ReactNode } from 'react';
2
+ import AwesomeSlider from 'react-awesome-slider';
3
+ import 'react-awesome-slider/dist/styles.css';
4
+ import './slider.css';
5
+ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
6
+ import { faCircleChevronLeft, faCircleChevronRight } from '@fortawesome/free-solid-svg-icons';
7
+
8
+ interface SliderProps {
9
+ children?: Array<ReactNode>,
10
+ autoPlay?: boolean,
11
+ /** default: 2000ms */
12
+ duration?: number,
13
+ className?: string,
14
+ iconSize?: number | string,
15
+ iconColor?: string,
16
+ prevButton?: ReactNode,
17
+ nextButton?: ReactNode,
18
+ style?: CSSProperties,
19
+ buttons?: boolean,
20
+ onChage?: (i: number) => void
21
+ }
22
+
23
+ interface SliderState {
24
+ page: number
25
+ }
26
+
27
+ export class CustomSlider extends React.Component<SliderProps, SliderState> {
28
+ private intervalPlay: any
29
+ constructor(props: SliderProps) {
30
+ super(props)
31
+ props.buttons ??= true
32
+ this.state = {
33
+ page: 0
34
+ }
35
+ this.autoPlay = this.autoPlay.bind(this)
36
+ }
37
+
38
+ nextPage = () => {
39
+ let index = this.state?.page ?? 0;
40
+ if (this.props?.children && (index + 1) < this.props.children.length) {
41
+ this.setState({ page: index + 1 })
42
+ if (this.props.onChage) this.props.onChage(index + 1)
43
+ }
44
+ }
45
+
46
+ previousPage = () => {
47
+ let index = this.state?.page ?? 0;
48
+ if (this.props?.children && index > 0) {
49
+ this.setState({ page: index - 1 })
50
+ if (this.props.onChage) this.props.onChage(index - 1)
51
+ }
52
+ }
53
+
54
+
55
+ private autoPlay = () => {
56
+ let index = this.state?.page ?? 0;
57
+ if (this.props?.children && (index + 1) === this.props.children.length)
58
+ index = -1
59
+ this.setState({ page: index + 1 })
60
+ if (this.props.onChage) this.props.onChage(index + 1)
61
+ }
62
+
63
+ componentDidMount(): void {
64
+ if (this.props.autoPlay) this.intervalPlay = setInterval(this.autoPlay, this.props.duration ?? 2000)
65
+ }
66
+
67
+
68
+
69
+ componentDidUpdate(prevProps: Readonly<SliderProps>, prevState: Readonly<SliderState>): void {
70
+ if (this.props.autoPlay !== prevProps.autoPlay && !this.props.autoPlay) clearInterval(this.intervalPlay)
71
+ }
72
+
73
+ render() {
74
+ return <AwesomeSlider
75
+ style={this.props.style}
76
+ className={`custom-slider-container ${this.props.className ?? ''}`}
77
+ selected={this.state.page}
78
+ bullets={false}
79
+ buttons={this.props.buttons ? (this.props.children && this.props.children?.length > 1) : false}
80
+ organicArrows={false}
81
+ buttonContentLeft={this.props.prevButton ?? <FontAwesomeIcon icon={faCircleChevronLeft} style={{ color: this.props.iconColor ?? '#ffffff', fontSize: this.props.iconSize ?? '2.4rem' }} />}
82
+ buttonContentRight={this.props.nextButton ?? <FontAwesomeIcon icon={faCircleChevronRight} style={{ color: this.props.iconColor ?? '#ffffff', fontSize: this.props.iconSize ?? '2.4rem' }} />}
83
+ >
84
+ {this.props.children}
85
+ </AwesomeSlider>
86
+ }
87
+ }
@@ -0,0 +1,53 @@
1
+ .switch-container {
2
+ position: relative;
3
+ display: inline-block;
4
+ background-color: var(--off-bg) !important;
5
+ border-radius: 50vw !important;
6
+ border: none;
7
+ outline: none;
8
+ }
9
+
10
+ .switch-container>input {
11
+ opacity: 0;
12
+ width: 0;
13
+ height: 0;
14
+ border: none;
15
+ outline: none;
16
+ }
17
+
18
+ .switch-container>.slider {
19
+ font-size: var(--size);
20
+ position: absolute;
21
+ height: calc(100% - 0.2em);
22
+ aspect-ratio: 1 / 1;
23
+ left: 0.1em;
24
+ top: 0.1em;
25
+ background-color: var(--dot-color);
26
+ transition: 0.4s;
27
+ border-radius: 50%;
28
+ }
29
+
30
+ .switch-container>input:checked+.slider {
31
+ -webkit-transform: translateX(calc(0.8 * (100% + 0.2em)));
32
+ -ms-transform: translateX(calc(0.8 * (100% + 0.2em)));
33
+ transform: translateX(calc(0.8 * (100% + 0.2em)));
34
+ }
35
+
36
+ .switch-container:has(> input:checked) {
37
+ background-color: var(--on-bg) !important;
38
+ }
39
+
40
+ .switch-container:has(> input:disabled:not(*:checked)) {
41
+ pointer-events: none;
42
+ border: 1px inset #00358033;
43
+ background-color: var(--disabled-background) !important;
44
+ }
45
+
46
+ .switch-container:has(> input:disabled:not(*:checked)) .slider {
47
+ background-color: #00204D40;
48
+ }
49
+
50
+ .switch-container:has(> input:disabled:checked) {
51
+ pointer-events: none;
52
+ background-color: #bccdf5 !important;
53
+ }
@@ -0,0 +1,67 @@
1
+ import React, { CSSProperties } from 'react';
2
+ import './switch.css';
3
+
4
+ interface SwitchProps {
5
+ onChange?: (value: boolean) => void,
6
+ value?: boolean,
7
+ disabled: false,
8
+ style: CSSProperties,
9
+ size?: number | string,
10
+ dotColor?: string,
11
+ onBackground?: string,
12
+ offBackground?: string,
13
+ name?: string,
14
+ className?: string,
15
+ }
16
+
17
+ interface SwitchState {
18
+ value?: boolean,
19
+ }
20
+
21
+ export class Switch extends React.Component<SwitchProps, SwitchState> {
22
+ state: Readonly<SwitchState> = {
23
+ value: this.props.value ?? false
24
+ }
25
+
26
+ componentDidUpdate(prevProps: Readonly<SwitchProps>): void {
27
+ if (prevProps.value !== this.props.value) {
28
+ this.setState({ value: this.props.value })
29
+ }
30
+ }
31
+
32
+ render() {
33
+ const propStyle = {
34
+ '--off-bg': this.props.offBackground ?? 'var(--background)',
35
+ '--on-bg': this.props.onBackground ?? 'var(--infor-color)',
36
+ '--dot-color': this.props.dotColor ?? '#ffffff',
37
+ '--size': this.props.size ? (typeof this.props.size === 'number') ? `${this.props.size}px` : this.props.size : '2rem'
38
+ }
39
+ let convertStyle: CSSProperties = {
40
+ height: this.props.size ?? '2rem',
41
+ width: `calc(${this.props.size ? (typeof this.props.size === 'number') ? `${this.props.size}px` : this.props.size : '2rem'} * 9 / 5)`,
42
+ ...propStyle
43
+ }
44
+ if (this.props.style) {
45
+ delete this.props.style.width
46
+ delete this.props.style.minWidth
47
+ delete this.props.style.maxWidth
48
+ delete this.props.style.height
49
+ delete this.props.style.minHeight
50
+ delete this.props.style.maxHeight
51
+ convertStyle = {
52
+ ...this.props.style,
53
+ ...convertStyle,
54
+ }
55
+ }
56
+ return <label className={`switch-container row ${this.props.className ?? ''}`} style={convertStyle} >
57
+ <input type="checkbox" checked={this.state.value} name={this.props.name} disabled={this.props.disabled}
58
+ onChange={() => {
59
+ const newValue = !this.state.value
60
+ this.setState({ value: newValue })
61
+ if (this.props.onChange) this.props.onChange(newValue)
62
+ }}
63
+ />
64
+ <span className="slider"></span>
65
+ </label>
66
+ }
67
+ }
@@ -0,0 +1,74 @@
1
+ .custom-table {
2
+ border: none;
3
+ min-width: 100%;
4
+ border-collapse: collapse;
5
+ }
6
+
7
+ .custom-table>.tb-header {
8
+ top: -1px;
9
+ z-index: 4;
10
+ position: sticky;
11
+ background-color: #f9fafb;
12
+ }
13
+
14
+ .custom-table>.tb-header>tr {
15
+ border-top: var(--border-grey1);
16
+ border-bottom: var(--border-grey1);
17
+ }
18
+
19
+ .custom-table .tb-cell {
20
+ height: 4.4rem;
21
+ text-align: left;
22
+ padding: 0 2.4rem;
23
+ font: 400 1.4rem/2.2rem 'Inter';
24
+ color: #00204DCC;
25
+ vertical-align: middle;
26
+ }
27
+
28
+ .custom-table>.tb-header>tr>td {
29
+ font: 600 1.2rem/2rem 'Inter';
30
+ white-space: nowrap;
31
+ color: #00204D99;
32
+ background-color: #f9fafb !important;
33
+ }
34
+
35
+ .custom-table tr>td {
36
+ background-color: #ffffff !important;
37
+ overflow: hidden;
38
+ text-overflow: ellipsis;
39
+ max-width: 52rem;
40
+ }
41
+
42
+ .custom-table tr.selected {
43
+ background-color: #f5f7fa !important;
44
+ }
45
+
46
+ .custom-table tr.selected>td {
47
+ background-color: #f5f7fa !important;
48
+ }
49
+
50
+ .tb-row>.tb-cell.tb-cell-fixed {
51
+ z-index: 2;
52
+ position: sticky;
53
+ /* box-shadow: 1px 0px 6px 0px rgba(45, 50, 57, 0.06); */
54
+ background-color: #ffffff;
55
+ }
56
+
57
+ .tb-header .tb-cell.tb-cell-fixed {
58
+ z-index: 2;
59
+ position: sticky;
60
+ /* box-shadow: 1px 0px 6px 0px rgba(45, 50, 57, 0.06); */
61
+ background-color: #ffffff;
62
+ }
63
+
64
+ .tb-cell[align-cell='start'] {
65
+ text-align: start;
66
+ }
67
+
68
+ .tb-cell[align-cell='center'] {
69
+ text-align: center;
70
+ }
71
+
72
+ .tb-cell[align-cell='end'] {
73
+ text-align: end;
74
+ }
@@ -0,0 +1,99 @@
1
+ import React, { CSSProperties, MouseEventHandler, ReactNode } from 'react';
2
+ import './table.css'
3
+
4
+ export enum CellAlignItems {
5
+ start = 'start',
6
+ center = 'center',
7
+ end = 'end',
8
+ }
9
+
10
+ type TbCellProps = {
11
+ fixed?: boolean,
12
+ children?: ReactNode,
13
+ className?: string,
14
+ style?: CSSProperties,
15
+ align?: CellAlignItems | string,
16
+ }
17
+
18
+ export class TbCell extends React.Component<TbCellProps> {
19
+ render(): React.ReactNode {
20
+ return <td style={this.props.style} align-cell={this.props.align ?? CellAlignItems.start} className={`tb-cell ${this.props.className ?? ''} ${this.props.fixed ? 'tb-cell-fixed' : ''}`}>{this.props.children}</td>
21
+ }
22
+ }
23
+
24
+ interface TbRowProps {
25
+ children?: Array<TbCell>,
26
+ className?: string,
27
+ style?: CSSProperties,
28
+ onClick?: MouseEventHandler<HTMLTableRowElement>,
29
+ }
30
+
31
+
32
+ export class TbRow extends React.Component<TbRowProps> {
33
+ render(): React.ReactNode {
34
+ return <tr style={this.props.style} className={`tb-row ${this.props.className ?? ""}`} onClick={this.props.onClick}>
35
+ {(this.props.children ?? []).map((e: TbCell, i: number) => {
36
+ let ox: number | string = 0
37
+ if (this.props.children && i > 0 && i < (this.props.children.length - 1)) {
38
+ ox = `calc(${this.props.children.slice(0, i).map(tb => {
39
+ const wValue = tb.props.style?.minWidth ?? tb.props.style?.width
40
+ return wValue ? typeof wValue === 'number' ? `${wValue}px` : wValue : '60px';
41
+ }).join(" + ")})`
42
+ }
43
+ return <TbCell
44
+ key={`tb-cell-${i}`}
45
+ align={e.props.align}
46
+ children={e.props.children}
47
+ fixed={e.props.fixed}
48
+ style={e.props.fixed ? (this.props.children && i === this.props.children.length - 1) ? { right: 0, ...(e.props.style ?? {}) } : { left: ox, ...(e.props.style ?? {}) } : e.props.style}
49
+ className={e.props.className} />;
50
+ })}
51
+ </tr>
52
+ }
53
+ }
54
+
55
+ export class TbHeader extends React.Component<TbRowProps> {
56
+ render() {
57
+ return <thead style={this.props.style} className={`tb-header ${this.props.className ?? ""}`}>
58
+ <tr>
59
+ {(this.props.children ?? []).map((e: TbCell, i: number) => {
60
+ let ox: number | string = 0
61
+ if (this.props.children && i > 0 && i < (this.props.children.length - 1)) {
62
+ ox = `calc(${this.props.children.slice(0, i).map(tb => tb.props.style?.width ? typeof tb.props.style.width === 'number' ? `${tb.props.style.width}px` : tb.props.style.width : '60px').join(" + ")})`
63
+ }
64
+ return <TbCell
65
+ key={`tb-cell-${i}`}
66
+ align={e.props.align}
67
+ children={e.props.children}
68
+ fixed={e.props.fixed}
69
+ style={e.props.fixed ? (this.props.children && i === this.props.children.length - 1) ? { right: 0, ...(e.props.style ?? {}) } : { left: ox, ...(e.props.style ?? {}) } : e.props.style}
70
+ className={e.props.className} />;
71
+ })}
72
+ </tr>
73
+ </thead>
74
+ }
75
+ }
76
+
77
+ interface TbBodyProps {
78
+ children?: Array<TbRow>,
79
+ className?: string,
80
+ style?: CSSProperties,
81
+ }
82
+
83
+ export class TbBody extends React.Component<TbBodyProps> {
84
+ render(): React.ReactNode {
85
+ return <tbody>{this.props.children as ReactNode}</tbody>
86
+ }
87
+ }
88
+
89
+ interface TableProps {
90
+ children?: Array<TbBody | TbHeader>,
91
+ className?: string,
92
+ style?: CSSProperties,
93
+ }
94
+
95
+ export class Table extends React.Component<TableProps> {
96
+ render(): React.ReactNode {
97
+ return <table className={`custom-table ${this.props.className}`} style={this.props.style}>{this.props.children as ReactNode}</table>
98
+ }
99
+ }
@@ -0,0 +1,16 @@
1
+ .comp-text {
2
+ display: -webkit-box;
3
+ -webkit-box-orient: vertical;
4
+ -webkit-line-clamp: var(--max-line);
5
+ overflow: hidden;
6
+ text-overflow: ellipsis;
7
+ text-align: start;
8
+ }
9
+
10
+ .comp-text[class*="subtitle"] {
11
+ color: #00204D99;
12
+ }
13
+
14
+ .comp-text.type-button {
15
+ cursor: pointer;
16
+ }
@@ -0,0 +1,21 @@
1
+ import React, { CSSProperties, ReactNode } from 'react';
2
+ import './text.css';
3
+
4
+ interface TextProps {
5
+ children?: ReactNode,
6
+ style?: CSSProperties,
7
+ className?: string,
8
+ maxLine?: number,
9
+ onClick?: React.MouseEventHandler<HTMLDivElement>,
10
+ onHover?: React.MouseEventHandler<HTMLDivElement>,
11
+ }
12
+
13
+ export class Text extends React.Component<TextProps> {
14
+ render(): React.ReactNode {
15
+ let convertStyle: CSSProperties = this.props.style ?? {}
16
+ if (this.props.maxLine) {
17
+ convertStyle = { ...convertStyle, '--max-line': this.props.maxLine } as CSSProperties
18
+ }
19
+ return <div onMouseOver={this.props.onHover} onClick={this.props.onClick} className={`comp-text ${this.props.onClick ? 'type-button' : ''} ${this.props.className ?? ''}`} style={convertStyle}>{this.props.children}</div>
20
+ }
21
+ }
@@ -0,0 +1,63 @@
1
+ .text-area-container {
2
+ height: 4rem;
3
+ position: relative;
4
+ gap: 0.8rem;
5
+ border-radius: 0.4rem;
6
+ border: 0.5px solid #00358033;
7
+ padding: 1.6rem;
8
+ align-items: start;
9
+ }
10
+
11
+ .text-area-container:has(> textarea:disabled) {
12
+ background-color: var(--disabled-background) !important;
13
+ pointer-events: none !important;
14
+ }
15
+
16
+ .text-area-container:has(> textarea:focus) {
17
+ border-color: #366AE2;
18
+ }
19
+
20
+ .text-area-container>textarea {
21
+ flex: 1;
22
+ padding: 0;
23
+ width: 100%;
24
+ height: inherit;
25
+ max-height: 100%;
26
+ border: none;
27
+ outline: none;
28
+ background-color: transparent !important;
29
+ font: inherit;
30
+ color: inherit;
31
+ font-size: inherit;
32
+ font-family: inherit;
33
+ font-weight: inherit;
34
+ line-height: inherit;
35
+ text-align: inherit;
36
+ text-overflow: inherit;
37
+ resize: inherit;
38
+ }
39
+
40
+ .text-field-container>textarea::placeholder {
41
+ opacity: 0.4;
42
+ }
43
+
44
+ .text-area-container.helper-text {
45
+ overflow: visible !important;
46
+ border-color: var(--helper-text-color) !important;
47
+ }
48
+
49
+ .text-area-container.helper-text {
50
+ overflow: visible !important;
51
+ border-color: var(--helper-text-color) !important;
52
+ }
53
+
54
+ .text-area-container.helper-text::after {
55
+ content: attr(helper-text);
56
+ color: var(--helper-text-color);
57
+ position: absolute;
58
+ left: 0;
59
+ bottom: -0.4rem;
60
+ width: max-content;
61
+ font: 400 1.2rem/1.6rem 'Inter';
62
+ transform: translate(-7.5%, 92.5%) scale(0.85);
63
+ }
@@ -0,0 +1,55 @@
1
+ import React, { CSSProperties } from "react";
2
+ import './text-area.css'
3
+ import { UseFormRegister } from "react-hook-form";
4
+
5
+ interface TextAreaProps {
6
+ value?: string,
7
+ maxLength?: number,
8
+ defaultValue?: string,
9
+ onChange?: React.ChangeEventHandler<HTMLTextAreaElement>,
10
+ onBlur?: React.FocusEventHandler<HTMLTextAreaElement>,
11
+ onFocus?: React.FocusEventHandler<HTMLTextAreaElement>,
12
+ placeholder?: string,
13
+ disabled?: boolean,
14
+ readOnly?: boolean,
15
+ autoFocus?: boolean,
16
+ className?: string,
17
+ helperText?: string,
18
+ name?: string,
19
+ helperTextColor?: string,
20
+ style?: CSSProperties,
21
+ register?: UseFormRegister<{}>,
22
+ }
23
+
24
+ export class TextArea extends React.Component<TextAreaProps> {
25
+ render(): React.ReactNode {
26
+ return <div
27
+ className={`text-area-container row ${this.props.className ?? 'placeholder-2'} ${this.props.helperText?.length && 'helper-text'}`}
28
+ style={this.props.style ? { ...({ '--helper-text-color': this.props.helperTextColor ?? '#e14337' } as CSSProperties), ...this.props.style } : ({ '--helper-text-color': this.props.helperTextColor ?? '#e14337' } as CSSProperties)}
29
+ >
30
+ {this.props.register ?
31
+ <textarea
32
+ autoFocus={this.props.autoFocus}
33
+ {...this.props.register}
34
+ maxLength={this.props.maxLength}
35
+ name={this.props.name}
36
+ placeholder={this.props.placeholder}
37
+ readOnly={this.props.readOnly}
38
+ disabled={this.props.disabled}
39
+ onFocus={this.props.onFocus}
40
+ /> : <textarea
41
+ autoFocus={this.props.autoFocus}
42
+ maxLength={this.props.maxLength}
43
+ name={this.props.name}
44
+ defaultValue={this.props.defaultValue}
45
+ value={this.props.value}
46
+ placeholder={this.props.placeholder}
47
+ readOnly={this.props.readOnly}
48
+ disabled={this.props.disabled}
49
+ onChange={this.props.onChange}
50
+ onFocus={this.props.onFocus}
51
+ onBlur={this.props.onBlur}
52
+ />}
53
+ </div>
54
+ }
55
+ }
@@ -0,0 +1,64 @@
1
+ .text-field-container {
2
+ height: 4rem;
3
+ position: relative;
4
+ gap: 0.8rem;
5
+ border-radius: 0.8rem;
6
+ border: 0.5px solid #00358033;
7
+ padding: 1rem 1.2rem;
8
+ }
9
+
10
+ .text-field-container:has(> input:disabled) {
11
+ background-color: var(--disabled-background) !important;
12
+ pointer-events: none !important;
13
+ }
14
+
15
+ .text-field-container:has(> input:focus) {
16
+ border-color: #366AE2;
17
+ }
18
+
19
+ .text-field-container>input {
20
+ flex: 1;
21
+ width: 100%;
22
+ height: 100%;
23
+ border: none;
24
+ outline: none;
25
+ padding: 0;
26
+ background-color: transparent !important;
27
+ font: inherit;
28
+ color: inherit;
29
+ font-size: inherit;
30
+ font-family: inherit;
31
+ font-weight: inherit;
32
+ line-height: inherit;
33
+ text-align: inherit;
34
+ text-overflow: inherit;
35
+ }
36
+
37
+ .text-field-container>input::placeholder {
38
+ opacity: 0.5;
39
+ }
40
+
41
+ .text-field-container.helper-text {
42
+ overflow: visible !important;
43
+ border-color: var(--helper-text-color) !important;
44
+ }
45
+
46
+ .text-field-container.helper-text {
47
+ overflow: visible !important;
48
+ border-color: var(--helper-text-color) !important;
49
+ }
50
+
51
+ .text-field-container.helper-text::after {
52
+ content: attr(helper-text);
53
+ color: var(--helper-text-color);
54
+ position: absolute;
55
+ left: 0;
56
+ bottom: 0;
57
+ width: max-content;
58
+ font: inherit;
59
+ font-size: inherit;
60
+ font-family: inherit;
61
+ font-weight: inherit;
62
+ line-height: inherit;
63
+ transform: translate(-7.5%, 92.5%) scale(0.85);
64
+ }
@@ -0,0 +1,63 @@
1
+ import React, { CSSProperties, ReactNode } from "react";
2
+ import './text-field.css'
3
+ import { UseFormRegister } from "react-hook-form";
4
+
5
+ interface TextFieldProps {
6
+ value?: string,
7
+ maxLength?: number,
8
+ defaultValue?: string,
9
+ onChange?: React.ChangeEventHandler<HTMLInputElement>,
10
+ onBlur?: React.FocusEventHandler<HTMLInputElement>,
11
+ onFocus?: React.FocusEventHandler<HTMLInputElement>,
12
+ placeholder?: string,
13
+ disabled?: boolean,
14
+ readOnly?: boolean,
15
+ className?: string,
16
+ helperText?: string,
17
+ name?: string,
18
+ suffix?: ReactNode,
19
+ prefix?: ReactNode,
20
+ helperTextColor?: string,
21
+ style?: CSSProperties,
22
+ type?: React.HTMLInputTypeAttribute,
23
+ autoFocus?: boolean,
24
+ register?: UseFormRegister<{}>,
25
+ }
26
+
27
+ export class TextField extends React.Component<TextFieldProps> {
28
+ render(): React.ReactNode {
29
+ return <div
30
+ className={`text-field-container row ${this.props.className ?? 'placeholder-2'} ${this.props.helperText?.length && 'helper-text'}`}
31
+ helper-text={this.props.helperText}
32
+ style={this.props.style ? { ...({ '--helper-text-color': this.props.helperTextColor ?? '#e14337' } as CSSProperties), ...this.props.style } : ({ '--helper-text-color': this.props.helperTextColor ?? '#e14337' } as CSSProperties)}
33
+ >
34
+ {this.props.prefix}
35
+ {this.props.register ?
36
+ <input
37
+ {...this.props.register}
38
+ autoFocus={this.props.autoFocus}
39
+ maxLength={this.props.maxLength}
40
+ name={this.props.name}
41
+ type={this.props.type ?? 'text'}
42
+ placeholder={this.props.placeholder}
43
+ readOnly={this.props.readOnly}
44
+ disabled={this.props.disabled}
45
+ onFocus={this.props.onFocus}
46
+ /> : <input
47
+ autoFocus={this.props.autoFocus}
48
+ maxLength={this.props.maxLength}
49
+ name={this.props.name}
50
+ type={this.props.type ?? 'text'}
51
+ defaultValue={this.props.defaultValue}
52
+ value={this.props.value}
53
+ placeholder={this.props.placeholder}
54
+ readOnly={this.props.readOnly}
55
+ disabled={this.props.disabled}
56
+ onChange={this.props.onChange}
57
+ onFocus={this.props.onFocus}
58
+ onBlur={this.props.onBlur}
59
+ />}
60
+ {this.props.suffix}
61
+ </div>
62
+ }
63
+ }
File without changes
@@ -0,0 +1,21 @@
1
+ import { Slide, toast } from 'react-toastify';
2
+
3
+ export class ToastMessage {
4
+ static success(message: string) {
5
+ toast.success(message, {
6
+ hideProgressBar: true,
7
+ transition: Slide,
8
+ autoClose: 800,
9
+ theme: "colored",
10
+ });
11
+ }
12
+ static errors(message: string) {
13
+ toast.error(message, {
14
+ theme: "colored",
15
+ pauseOnHover: false,
16
+ hideProgressBar: true,
17
+ transition: Slide,
18
+ autoClose: 800,
19
+ });
20
+ }
21
+ }