wini-web-components 2.8.2 → 2.8.4

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 (65) hide show
  1. package/package.json +6 -2
  2. package/src/component/button/button.module.css +210 -0
  3. package/src/component/button/button.tsx +57 -0
  4. package/src/component/calendar/calendar.module.css +153 -0
  5. package/src/component/calendar/calendar.tsx +389 -0
  6. package/src/component/carousel/carousel.css +622 -0
  7. package/src/component/carousel/carousel.tsx +91 -0
  8. package/src/component/checkbox/checkbox.module.css +48 -0
  9. package/src/component/checkbox/checkbox.tsx +80 -0
  10. package/src/component/ck-editor/ck-editor.css +206 -0
  11. package/src/component/ck-editor/ckeditor.tsx +522 -0
  12. package/src/component/component-status.tsx +53 -0
  13. package/src/component/date-time-picker/date-time-picker.module.css +94 -0
  14. package/src/component/date-time-picker/date-time-picker.tsx +663 -0
  15. package/src/component/dialog/dialog.module.css +111 -0
  16. package/src/component/dialog/dialog.tsx +109 -0
  17. package/src/component/import-file/import-file.module.css +83 -0
  18. package/src/component/import-file/import-file.tsx +174 -0
  19. package/src/component/infinite-scroll/infinite-scroll.module.css +34 -0
  20. package/src/component/infinite-scroll/infinite-scroll.tsx +35 -0
  21. package/src/component/input-multi-select/input-multi-select.module.css +121 -0
  22. package/src/component/input-multi-select/input-multi-select.tsx +263 -0
  23. package/src/component/input-otp/input-otp.module.css +41 -0
  24. package/src/component/input-otp/input-otp.tsx +110 -0
  25. package/src/component/number-picker/number-picker.module.css +137 -0
  26. package/src/component/number-picker/number-picker.tsx +107 -0
  27. package/src/component/pagination/pagination.module.css +48 -0
  28. package/src/component/pagination/pagination.tsx +88 -0
  29. package/src/component/popup/popup.css +136 -0
  30. package/src/component/popup/popup.tsx +125 -0
  31. package/src/component/progress-bar/progress-bar.module.css +42 -0
  32. package/src/component/progress-bar/progress-bar.tsx +33 -0
  33. package/src/component/progress-circle/progress-circle.css +0 -0
  34. package/src/component/progress-circle/progress-circle.tsx +25 -0
  35. package/src/component/radio-button/radio-button.module.css +51 -0
  36. package/src/component/radio-button/radio-button.tsx +60 -0
  37. package/src/component/rating/rating.module.css +11 -0
  38. package/src/component/rating/rating.tsx +65 -0
  39. package/src/component/select1/select1.module.css +108 -0
  40. package/src/component/select1/select1.tsx +271 -0
  41. package/src/component/switch/switch.module.css +53 -0
  42. package/src/component/switch/switch.tsx +68 -0
  43. package/src/component/table/table.css +74 -0
  44. package/src/component/table/table.tsx +108 -0
  45. package/src/component/tag/tag.module.css +108 -0
  46. package/src/component/tag/tag.tsx +31 -0
  47. package/src/component/text/text.css +27 -0
  48. package/src/component/text/text.tsx +24 -0
  49. package/src/component/text-area/text-area.module.css +57 -0
  50. package/src/component/text-area/text-area.tsx +65 -0
  51. package/src/component/text-field/text-field.module.css +71 -0
  52. package/src/component/text-field/text-field.tsx +102 -0
  53. package/src/component/toast-noti/toast-noti.css +866 -0
  54. package/src/component/toast-noti/toast-noti.tsx +22 -0
  55. package/src/component/wini-icon/winicon.module.css +110 -0
  56. package/src/component/wini-icon/winicon.tsx +9424 -0
  57. package/src/form/login/view.module.css +80 -0
  58. package/src/form/login/view.tsx +138 -0
  59. package/src/global.d.ts +5 -0
  60. package/src/index.tsx +66 -0
  61. package/src/language/i18n.tsx +143 -0
  62. package/src/skin/layout.css +649 -0
  63. package/src/skin/root.css +294 -0
  64. package/src/skin/typography.css +314 -0
  65. package/src/vite-env.d.ts +1 -0
@@ -0,0 +1,65 @@
1
+ import React, { CSSProperties } from "react"
2
+ import styles from './rating.module.css'
3
+
4
+ interface RatingProps {
5
+ id?: string,
6
+ /**
7
+ value: 0-5
8
+ */
9
+ value?: number,
10
+ size?: number | string,
11
+ onChange?: (e: number) => void
12
+ className?: string,
13
+ style?: CSSProperties,
14
+ strokeColor?: string,
15
+ fillColor?: string,
16
+ }
17
+
18
+ interface RatingState {
19
+ value: number,
20
+ }
21
+
22
+ const autoKeyId = () => window.crypto.randomUUID().replace(/-/g, '')
23
+
24
+ export class Rating extends React.Component<RatingProps, RatingState> {
25
+ state: Readonly<RatingState> = {
26
+ value: this.props.value ?? 0
27
+ }
28
+
29
+ componentDidUpdate(prevProps: Readonly<RatingProps>): void {
30
+ if (prevProps.value !== this.props.value) {
31
+ this.setState({ value: this.props.value ?? 0 })
32
+ }
33
+ }
34
+ render(): React.ReactNode {
35
+ return <div id={this.props.id} className={`row ${styles['rating-container']} ${this.props.className ?? ''}`} style={this.props.style}>
36
+ {Array.from({ length: 5 }).map((_, i) => {
37
+ let uniqueId = 'rating-star-grad-0'
38
+ let stopValue = 0
39
+ if (this.state.value >= 5) {
40
+ uniqueId = 'rating-star-grad-5'
41
+ stopValue = 100
42
+ } else if (this.state.value >= i) {
43
+ uniqueId = autoKeyId()
44
+ stopValue = (this.state.value - i) * 100
45
+ }
46
+ return <svg onClick={() => {
47
+ if (this.props.onChange) {
48
+ this.setState({ value: i + 1 })
49
+ this.props.onChange(i + 1)
50
+ }
51
+ }} key={'rate-' + i} width={"100%"} height={"100%"} style={{ width: this.props.size ?? '2rem', height: this.props.size ?? '2rem' }} viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
52
+ <defs>
53
+ <linearGradient id={uniqueId} x1="0%" x2="100%" y1="0%" y2="0%">
54
+ <stop offset="0%" style={{ stopColor: this.props.fillColor ?? 'var(--secondary3-main-color,#FAAD1E)' }} />
55
+ <stop offset={`${stopValue}%`} style={{ stopColor: this.props.fillColor ?? 'var(--secondary3-main-color,#FAAD1E)' }} />
56
+ <stop offset={`${stopValue}%`} style={{ stopColor: '#00000000' }} />
57
+ </linearGradient>
58
+ </defs>
59
+ <path fillRule="evenodd" clipRule="evenodd" d="M10 1.66667C10.2884 1.66667 10.5518 1.82993 10.6794 2.0878L12.844 6.46194L17.6847 7.16325C17.97 7.20459 18.2071 7.4039 18.2962 7.67736C18.3853 7.95082 18.311 8.25101 18.1045 8.45172L14.6018 11.8563L15.4285 16.6636C15.4772 16.947 15.3604 17.2334 15.127 17.4024C14.8937 17.5714 14.5844 17.5937 14.3292 17.4599L10 15.1897L5.67081 17.4599C5.41557 17.5937 5.10627 17.5714 4.87295 17.4024C4.63964 17.2334 4.52278 16.947 4.57151 16.6636L5.39815 11.8563L1.89545 8.45172C1.68896 8.25101 1.61465 7.95082 1.70377 7.67736C1.79288 7.4039 2.02996 7.20459 2.31533 7.16325L7.15599 6.46194L9.32063 2.0878C9.44825 1.82993 9.71162 1.66667 10 1.66667ZM10 4.12915L8.33846 7.48665C8.22811 7.70963 8.01479 7.86418 7.76802 7.89993L4.05223 8.43827L6.74094 11.0517C6.91947 11.2252 7.00094 11.4752 6.95881 11.7203L6.3243 15.4102L9.64738 13.6676C9.86813 13.5519 10.1319 13.5519 10.3526 13.6676L13.6757 15.4102L13.0412 11.7203C12.9991 11.4752 13.0805 11.2252 13.2591 11.0517L15.9478 8.43827L12.232 7.89993C11.9852 7.86418 11.7719 7.70963 11.6615 7.48665L10 4.12915Z" style={{ fill: this.props.strokeColor ?? 'var(--neutral-text-placeholder-color,#878792)' }} />
60
+ <path d="M17.738 7.18949L12.8212 6.47499L10.6249 2.02268C10.5611 1.91426 10.47 1.82438 10.3608 1.76194C10.2515 1.6995 10.1279 1.66666 10.0021 1.66666C9.87623 1.66666 9.75259 1.6995 9.64335 1.76194C9.53411 1.82438 9.44306 1.91426 9.37921 2.02268L7.17875 6.47499L2.26191 7.18949C2.13368 7.208 2.0132 7.26201 1.91406 7.34542C1.81493 7.42882 1.74111 7.5383 1.70095 7.66147C1.66078 7.78463 1.65588 7.91658 1.68678 8.04239C1.71769 8.1682 1.78317 8.28286 1.87583 8.3734L5.43449 11.8411L4.59499 16.7385C4.57311 16.8662 4.58739 16.9975 4.63622 17.1175C4.68505 17.2375 4.76648 17.3414 4.8713 17.4175C4.97612 17.4937 5.10016 17.539 5.22938 17.5483C5.3586 17.5577 5.48785 17.5306 5.60252 17.4704L9.99998 15.1588L14.3974 17.4704C14.5121 17.5306 14.6414 17.5577 14.7706 17.5483C14.8998 17.539 15.0238 17.4937 15.1286 17.4175C15.2335 17.3414 15.3149 17.2375 15.3637 17.1175C15.4126 16.9975 15.4268 16.8662 15.405 16.7385L14.5655 11.8411L18.1241 8.3734C18.2168 8.28295 18.2823 8.16841 18.3132 8.0427C18.3442 7.91699 18.3394 7.78512 18.2994 7.66199C18.2594 7.53886 18.1858 7.42937 18.0868 7.34587C17.9879 7.26238 17.8675 7.20822 17.7394 7.18949H17.738Z" fill={`url(#${uniqueId})`} />
61
+ </svg>
62
+ })}
63
+ </div>
64
+ }
65
+ }
@@ -0,0 +1,108 @@
1
+ .select1-container {
2
+ border-radius: 0.8rem;
3
+ width: 100%;
4
+ box-sizing: border-box;
5
+ padding: 0.8rem 1.6rem;
6
+ border: var(--neutral-bolder-border);
7
+ border-radius: 0.8rem;
8
+ gap: 0.8rem;
9
+ position: relative;
10
+ cursor: context-menu;
11
+ }
12
+
13
+ .select1-container:focus-within {
14
+ border-color: var(--primary-main-color);
15
+ }
16
+
17
+ .select1-container.disabled {
18
+ background-color: var(--neutral-disable-background-color) !important;
19
+ pointer-events: none !important;
20
+ }
21
+
22
+ .select1-container.helper-text {
23
+ overflow: visible !important;
24
+ border-color: var(--helper-text-color) !important;
25
+ }
26
+
27
+ .select1-container.helper-text::after {
28
+ content: attr(helper-text);
29
+ color: var(--helper-text-color);
30
+ position: absolute;
31
+ left: 0;
32
+ bottom: -0.4rem;
33
+ width: max-content;
34
+ font-size: 1.2rem;
35
+ line-height: 1.6rem;
36
+ font-family: inherit;
37
+ transform: translateY(100%);
38
+ }
39
+
40
+ .select1-container>input {
41
+ flex: 1;
42
+ width: 100%;
43
+ border: none;
44
+ outline: none;
45
+ padding: 0;
46
+ background-color: transparent !important;
47
+ font: inherit;
48
+ color: inherit;
49
+ font-size: inherit;
50
+ font-family: inherit;
51
+ font-weight: inherit;
52
+ line-height: inherit;
53
+ text-align: inherit;
54
+ text-overflow: inherit;
55
+ }
56
+
57
+ .select1-container input:read-only {
58
+ cursor: context-menu;
59
+ }
60
+
61
+ .select1-popup {
62
+ position: absolute;
63
+ z-index: 10;
64
+ background-color: var(--neutral-absolute-background-color);
65
+ border-radius: 0.8rem;
66
+ border: var(--neutral-main-border);
67
+ height: fit-content;
68
+ box-shadow: 0 0 12px 0 #00204d1f;
69
+ align-items: center;
70
+ }
71
+
72
+ .select1-popup>.select-body {
73
+ max-height: 100%;
74
+ flex: 1;
75
+ align-items: start;
76
+ max-height: 28rem;
77
+ min-height: 8rem;
78
+ width: 100%;
79
+ padding: 0.4rem 0;
80
+ overflow: hidden auto;
81
+ }
82
+
83
+ .select1-popup>.select-body .select-tile {
84
+ justify-content: start;
85
+ align-items: center;
86
+ padding: 0.8rem 1.6rem;
87
+ gap: 0.8rem;
88
+ width: 100%;
89
+ cursor: context-menu;
90
+ }
91
+
92
+ .select1-popup>.select-body .select-tile:hover {
93
+ background-color: var(--neutral-hover-background-color);
94
+ }
95
+
96
+ .select1-popup>.select-body .select-tile.disabled {
97
+ background-color: var(--neutral-disable-background-color) !important;
98
+ }
99
+
100
+ .select1-popup>.select-body .select-tile.disabled * {
101
+ color: var(--neutral-text-disabled-color) !important;
102
+ }
103
+
104
+ .no-results-found {
105
+ padding: 0.8rem;
106
+ font: 400 1.4rem/2rem "Inter";
107
+ color: var(--neutral-text-title-reverse-color);
108
+ }
@@ -0,0 +1,271 @@
1
+ import styles from './select1.module.css'
2
+ import React, { createRef, CSSProperties, ReactNode, useState } from 'react'
3
+ import { Winicon } from '../wini-icon/winicon'
4
+ import { Text } from '../text/text'
5
+ import { WithTranslation, withTranslation } from 'react-i18next';
6
+ import { PopupOverlay } from '../popup/popup'
7
+
8
+ export interface OptionsItem {
9
+ id: string | number,
10
+ parentId?: string,
11
+ name: string | ReactNode,
12
+ title?: string | ((onSelect: (e: OptionsItem) => void) => ReactNode),
13
+ disabled?: boolean
14
+ }
15
+
16
+ interface Select1Props extends WithTranslation {
17
+ id?: string,
18
+ value?: string | number,
19
+ options: Required<Array<OptionsItem>>,
20
+ onChange?: (v?: OptionsItem) => void,
21
+ placeholder?: string,
22
+ disabled?: boolean,
23
+ className?: string,
24
+ helperText?: string,
25
+ helperTextColor?: string,
26
+ style?: CSSProperties,
27
+ handleSearch?: (e: string) => Promise<Array<OptionsItem>>,
28
+ handleLoadmore?: (onLoadMore: boolean, ev: React.UIEvent<HTMLDivElement, UIEvent>) => void,
29
+ handleLoadChildren?: () => {}
30
+ readOnly?: boolean,
31
+ popupClassName?: string,
32
+ prefix?: ReactNode,
33
+ suffix?: ReactNode,
34
+ onOpenOptions?: (popupRef: HTMLDivElement) => void
35
+ }
36
+
37
+ interface Select1State {
38
+ value?: string | number,
39
+ options: Required<Array<OptionsItem>>,
40
+ offset: DOMRect,
41
+ isOpen: boolean,
42
+ onSelect: any,
43
+ selected?: string | number,
44
+ search?: Array<OptionsItem>,
45
+ style?: Object
46
+ };
47
+
48
+ class TSelect1 extends React.Component<Select1Props, Select1State> {
49
+ private containerRef = createRef<HTMLDivElement>()
50
+ private inputRef = createRef<HTMLInputElement>()
51
+ constructor(props: Select1Props) {
52
+ super(props)
53
+ this.state = {
54
+ value: props.value,
55
+ options: props.options,
56
+ offset: {
57
+ x: 0,
58
+ y: 0,
59
+ height: 0,
60
+ width: 0,
61
+ bottom: 0,
62
+ left: 0,
63
+ right: 0,
64
+ top: 0,
65
+ toJSON: function () {
66
+ throw new Error('Function not implemented.')
67
+ }
68
+ },
69
+ isOpen: false,
70
+ onSelect: null,
71
+ }
72
+ this.search = this.search.bind(this)
73
+ this.onSelect = this.onSelect.bind(this)
74
+ this.onKeyDown = this.onKeyDown.bind(this)
75
+ if (this.inputRef.current) this.inputRef.current.value = `${this.state.options.find(e => e.id === this.state.value)?.name ?? ""}`
76
+ }
77
+
78
+ private async search(ev: React.ChangeEvent<HTMLInputElement>) {
79
+ if (ev.target.value.trim().length) {
80
+ if (this.props?.handleSearch) {
81
+ const res = await this.props.handleSearch(ev.target.value.trim())
82
+ this.setState({ ...this.state, search: res })
83
+ } else {
84
+ this.setState({
85
+ ...this.state,
86
+ search: this.props.options.filter(e => typeof e.name === "string" && e.name.toLowerCase().includes(ev.target.value.trim().toLowerCase()))
87
+ })
88
+ }
89
+ } else {
90
+ this.setState({ ...this.state, search: undefined })
91
+ }
92
+ }
93
+
94
+ private onSelect(item: OptionsItem) {
95
+ if (item.disabled) {
96
+ this.setState({ ...this.state, isOpen: false, onSelect: undefined, selected: undefined })
97
+ this.inputRef.current?.blur()
98
+ } else {
99
+ let newState = { ...this.state, isOpen: false, value: item.id, onSelect: undefined, selected: undefined }
100
+ if (!newState.options.some(e => e.id === item.id)) newState.options.push(item)
101
+ this.setState(newState)
102
+ this.inputRef.current?.blur()
103
+ }
104
+ if (this.props.onChange) this.props.onChange(item)
105
+ }
106
+
107
+ private onKeyDown = (ev: React.KeyboardEvent<HTMLInputElement>) => {
108
+ if ((this.state.options?.length || this.state.search?.length) && this.state.isOpen) {
109
+ switch (ev.key.toLowerCase()) {
110
+ case "enter":
111
+ ev.preventDefault()
112
+ const _selectItem = (this.state.search ?? this.state.options).find(e => e.id === this.state.selected)
113
+ if (_selectItem) this.onSelect(_selectItem)
114
+ break;
115
+ case "arrowup":
116
+ ev.preventDefault()
117
+ if (this.state.selected) {
118
+ let _index = (this.state.search ?? this.state.options).findIndex((e) => e.id === this.state.selected)
119
+ _index = ((_index === 0) ? this.props.options.length : _index) - 1
120
+ this.setState({ ...this.state, selected: this.props.options[_index]?.id })
121
+ }
122
+ break;
123
+ case "arrowdown":
124
+ ev.preventDefault()
125
+ if (this.state.selected) {
126
+ let _index = (this.state.search ?? this.state.options).findIndex((e) => e.id === this.state.selected)
127
+ _index = ((_index + 1 === this.props.options.length) ? -1 : _index) + 1
128
+ this.setState({ ...this.state, selected: this.props.options[_index]?.id })
129
+ }
130
+ break;
131
+ default:
132
+ break;
133
+ }
134
+ }
135
+ }
136
+
137
+ componentDidUpdate(prevProps: Select1Props, prevState: Select1State) {
138
+ if (prevProps.options !== this.props.options) {
139
+ this.setState({ ...this.state, options: this.props.options })
140
+ if (this.inputRef.current) this.inputRef.current.value = `${this.props.options.find(e => e.id === this.state.value)?.name ?? ""}`
141
+ }
142
+ if (prevProps.value !== this.props.value) this.setState({ ...this.state, value: this.props.value })
143
+ if (prevState.value !== this.state.value && this.inputRef.current) this.inputRef.current.value = `${this.state.options.find(e => e.id === this.state.value)?.name ?? ""}`
144
+ //
145
+ if (this.state.isOpen && prevState.isOpen !== this.state.isOpen) {
146
+ const thisPopupRect = this.containerRef.current!.querySelector(`.select1-popup`)?.getBoundingClientRect()
147
+ if (thisPopupRect) {
148
+ let style: { top?: string, left?: string, right?: string, bottom?: string, width?: string, height?: string } | undefined;
149
+ if (thisPopupRect.right > document.body.offsetWidth) {
150
+ style = {
151
+ top: this.state.offset.y + this.state.offset.height + 2 + 'px',
152
+ right: document.body.offsetWidth - this.state.offset.right + 'px'
153
+ }
154
+ }
155
+ let _bottom = thisPopupRect.bottom - 8
156
+ const thisContainerRect = this.containerRef.current?.getBoundingClientRect()
157
+ if (thisContainerRect) {
158
+ if (_bottom > document.body.offsetHeight) {
159
+ style = { ...(style ?? {}), top: `${thisContainerRect.y - 2 - thisPopupRect.height}px` }
160
+ }
161
+ }
162
+ if (style) {
163
+ style.left ??= (style.right ? undefined : `${this.state.offset.x}px`)
164
+ style.width ??= `${this.state.offset.width}px`
165
+ this.setState({ ...this.state, style: style })
166
+ }
167
+ }
168
+ }
169
+ }
170
+
171
+ componentDidMount(): void {
172
+ if (this.inputRef.current) this.inputRef.current.value = `${this.state.options.find(e => e.id === this.state.value)?.name ?? ""}`
173
+ }
174
+
175
+ render() {
176
+ const { t } = this.props;
177
+ const _value = this.state.options.find(e => e.id === this.state.value)
178
+ return <div
179
+ id={this.props.id}
180
+ ref={this.containerRef}
181
+ className={`${styles['select1-container']} row ${this.props.disabled ? styles['disabled'] : ''} ${this.props.helperText?.length && styles['helper-text']} ${this.props.className ?? 'body-3'}`}
182
+ helper-text={this.props.helperText}
183
+ 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)}
184
+ onClick={() => {
185
+ if (!this.state.isOpen) {
186
+ this.setState({
187
+ ...this.state,
188
+ isOpen: true,
189
+ style: undefined,
190
+ offset: this.containerRef?.current?.getBoundingClientRect() as any,
191
+ })
192
+ this.inputRef.current?.focus()
193
+ }
194
+ }}
195
+ >
196
+ {this.props.prefix}
197
+ {(!_value || typeof _value.name === "string" || typeof _value.name === "number") ? <input ref={this.inputRef} readOnly={this.props.readOnly} onChange={this.search} placeholder={this.props.placeholder}
198
+ onBlur={ev => {
199
+ if (this.state.onSelect && !this.props.readOnly) ev.target.focus()
200
+ }}
201
+ /> : _value.name}
202
+ {this.props.suffix ?? <div ref={iconRef => {
203
+ if (iconRef?.parentElement && iconRef.parentElement.getBoundingClientRect().width < 88) iconRef.style.display = "none"
204
+ }} className='row' >
205
+ <Winicon src={this.state.isOpen ? "fill/arrows/up-arrow" : "fill/arrows/down-arrow"} size={"1.2rem"} />
206
+ </div>}
207
+ {this.state.isOpen && <PopupOverlay
208
+ onOpen={this.props.onOpenOptions}
209
+ className={`hidden-overlay`}
210
+ onClose={(ev) => {
211
+ if (ev.target !== this.inputRef.current) this.setState({ ...this.state, isOpen: false })
212
+ }}
213
+ >
214
+ <div className={`${styles['select1-popup']} select1-popup col ${this.props.popupClassName ?? ""}`} style={this.state.style ?? {
215
+ top: this.state.offset.y + this.state.offset.height + 2 + 'px',
216
+ left: this.state.offset.x + 'px',
217
+ width: this.state.offset.width,
218
+ }}>
219
+ <div className={`col ${styles['select-body']}`} onScroll={this.props.handleLoadmore ? (ev) => {
220
+ if (this.props.handleLoadmore) {
221
+ let scrollElement = ev.target as HTMLDivElement
222
+ this.props.handleLoadmore(Math.round(scrollElement.offsetHeight + scrollElement.scrollTop) >= (scrollElement.scrollHeight - 1), ev)
223
+ }
224
+ } : undefined}>
225
+ {(this.state.search ?? this.state.options).filter(e => !e.parentId).map(item => {
226
+ return <OptionsItemTile
227
+ key={item.id}
228
+ item={item}
229
+ children={(this.state.search ?? this.state.options).filter(e => e.parentId === item.id)}
230
+ selected={this.state.selected === item.id}
231
+ onClick={this.onSelect}
232
+ treeData={(this.state.search ?? this.state.options).some(e => e.parentId)}
233
+ />
234
+ })}
235
+ {(!this.state.search?.length && !this.props.options?.length) && (
236
+ <div className={styles['no-results-found']}>{t("noResultFound")}</div>
237
+ )}
238
+ </div>
239
+ </div>
240
+ </PopupOverlay>}
241
+ </div>
242
+ }
243
+ }
244
+
245
+ interface OptionTileProps {
246
+ item: OptionsItem,
247
+ children?: Array<OptionsItem>,
248
+ selected?: boolean,
249
+ onClick: (e: OptionsItem) => void,
250
+ treeData?: boolean
251
+ }
252
+
253
+ function OptionsItemTile({ item, children, selected, onClick, treeData }: OptionTileProps) {
254
+ const [isOpen, setIsOpen] = useState<boolean>(false)
255
+
256
+ return item.title && typeof item.title !== "string" ? <>{item.title(onClick)}</> : <div className='col' style={{ width: '100%' }}>
257
+ <div className={`${styles['select-tile']} row ${item.disabled ? styles["disabled"] : ""}`} style={{ paddingLeft: item.parentId ? '4.4rem' : undefined, backgroundColor: selected ? "var(--neutral-selected-background-color)" : undefined }} onClick={() => {
258
+ if (children?.length) {
259
+ setIsOpen(!isOpen)
260
+ } else onClick(item)
261
+ }}>
262
+ {treeData ? <div className='row' style={{ width: '1.4rem', height: '1.4rem' }}>
263
+ {children?.length ? <Winicon src={isOpen ? "fill/arrows/triangle-down" : "fill/arrows/triangle-right"} size={"1.2rem"} /> : null}
264
+ </div> : undefined}
265
+ {((item.title && typeof item.title === "string") || typeof item.name === "string") ? <Text className='body-3'>{item.title && typeof item.title === "string" ? item.title : item.name}</Text> : item.name}
266
+ </div>
267
+ {children?.length ? <div className='col' style={{ display: isOpen ? "flex" : "none", width: '100%' }}>{children.map(e => <OptionsItemTile key={e.id} item={e} onClick={onClick} />)}</div> : undefined}
268
+ </div>
269
+ }
270
+
271
+ export const Select1 = withTranslation()(TSelect1)
@@ -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: var(--neutral-bolder-border);
43
+ background-color: var(--neutral-disable-background-color) !important;
44
+ }
45
+
46
+ .switch-container:has(> input:disabled:not(*:checked)) .slider {
47
+ background-color: var(--neutral-text-disabled-color) !important;
48
+ }
49
+
50
+ .switch-container:has(> input:disabled:checked) {
51
+ pointer-events: none;
52
+ background-color: var(--primary-lighter-color) !important;
53
+ }
@@ -0,0 +1,68 @@
1
+ import React, { CSSProperties } from 'react';
2
+ import styles from './switch.module.css';
3
+
4
+ interface SwitchProps {
5
+ id?: string,
6
+ onChange?: (value: boolean) => void,
7
+ value?: boolean,
8
+ disabled?: boolean,
9
+ className?: string,
10
+ style?: CSSProperties,
11
+ size?: number | string,
12
+ dotColor?: string,
13
+ onBackground?: string,
14
+ offBackground?: string,
15
+ name?: string,
16
+ }
17
+
18
+ interface SwitchState {
19
+ value?: boolean,
20
+ }
21
+
22
+ export class Switch extends React.Component<SwitchProps, SwitchState> {
23
+ state: Readonly<SwitchState> = {
24
+ value: this.props.value ?? false
25
+ }
26
+
27
+ componentDidUpdate(prevProps: Readonly<SwitchProps>): void {
28
+ if (prevProps.value !== this.props.value) {
29
+ this.setState({ value: this.props.value })
30
+ }
31
+ }
32
+
33
+ render() {
34
+ const propStyle = {
35
+ '--off-bg': this.props.offBackground ?? 'var(--neutral-main-background-color)',
36
+ '--on-bg': this.props.onBackground ?? 'var(--primary-main-color)',
37
+ '--dot-color': this.props.dotColor ?? '#ffffff',
38
+ '--size': this.props.size ? (typeof this.props.size === 'number') ? `${this.props.size}px` : this.props.size : '2rem'
39
+ }
40
+ let convertStyle: CSSProperties = {
41
+ height: this.props.size ?? '2rem',
42
+ width: `calc(${this.props.size ? (typeof this.props.size === 'number') ? `${this.props.size}px` : this.props.size : '2rem'} * 9 / 5)`,
43
+ ...propStyle
44
+ }
45
+ if (this.props.style) {
46
+ delete this.props.style.width
47
+ delete this.props.style.minWidth
48
+ delete this.props.style.maxWidth
49
+ delete this.props.style.height
50
+ delete this.props.style.minHeight
51
+ delete this.props.style.maxHeight
52
+ convertStyle = {
53
+ ...this.props.style,
54
+ ...convertStyle,
55
+ }
56
+ }
57
+ return <label id={this.props.id} className={`${styles['switch-container']} row ${this.props.className ?? ''}`} style={convertStyle} >
58
+ <input type="checkbox" checked={this.state.value} name={this.props.name} disabled={this.props.disabled}
59
+ onChange={() => {
60
+ const newValue = !this.state.value
61
+ this.setState({ value: newValue })
62
+ if (this.props.onChange) this.props.onChange(newValue)
63
+ }}
64
+ />
65
+ <span className={styles['slider']}></span>
66
+ </label>
67
+ }
68
+ }
@@ -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(--neutral-bolder-border);
16
+ border-bottom: var(--neutral-bolder-border);
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 tr>td {
29
+ background-color: #ffffff;
30
+ overflow: hidden;
31
+ text-overflow: ellipsis;
32
+ max-width: 52rem;
33
+ }
34
+
35
+ .custom-table>.tb-header>tr>td {
36
+ font: 600 1.2rem/2rem 'Inter';
37
+ white-space: nowrap;
38
+ color: #00204D99;
39
+ background-color: #f9fafb;
40
+ }
41
+
42
+ .custom-table tr.selected {
43
+ background-color: #f5f7fa;
44
+ }
45
+
46
+ .custom-table tr.selected>td {
47
+ background-color: #f5f7fa;
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: #f9fafb;
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
+ }