naria-ui 0.1.52 → 0.1.54

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 (51) hide show
  1. package/assets/icons/angle-down.svg +1 -0
  2. package/assets/icons/angle-left.svg +1 -0
  3. package/assets/icons/angle-right.svg +1 -0
  4. package/assets/icons/angle-up.svg +1 -0
  5. package/assets/icons/close.svg +1 -0
  6. package/assets/icons/search.svg +1 -0
  7. package/eslint.config.js +28 -0
  8. package/hooks/click-outside.ts +17 -0
  9. package/hooks/is-first-render.ts +7 -0
  10. package/hooks/use-width.ts +11 -0
  11. package/index.html +13 -0
  12. package/lib/components/Button/Button.tsx +47 -0
  13. package/lib/components/Button/button.scss +9 -0
  14. package/lib/components/Button/index.ts +1 -0
  15. package/lib/components/Input/Input.tsx +66 -0
  16. package/lib/components/Input/index.ts +1 -0
  17. package/lib/components/Select/Select.tsx +414 -0
  18. package/lib/components/Select/index.ts +1 -0
  19. package/lib/components/Select/select.scss +138 -0
  20. package/lib/components/index.ts +3 -0
  21. package/lib/index.ts +1 -0
  22. package/package.json +2 -6
  23. package/shared/loading/Loading.tsx +35 -0
  24. package/shared/loading/loading.scss +9 -0
  25. package/src/App.css +0 -0
  26. package/src/App.tsx +81 -0
  27. package/src/index.css +0 -0
  28. package/src/main.tsx +7 -0
  29. package/src/vite-env.d.ts +1 -0
  30. package/tsconfig.app.json +34 -0
  31. package/tsconfig.build.json +11 -0
  32. package/tsconfig.json +7 -0
  33. package/tsconfig.node.json +24 -0
  34. package/utils/navigator.ts +29 -0
  35. package/vite.config.ts +50 -0
  36. package/dist/lib/components/Button/Button.d.ts +0 -16
  37. package/dist/lib/components/Button/index.d.ts +0 -1
  38. package/dist/lib/components/Input/Input.d.ts +0 -18
  39. package/dist/lib/components/Input/index.d.ts +0 -1
  40. package/dist/lib/components/Select/Select.d.ts +0 -36
  41. package/dist/lib/components/Select/index.d.ts +0 -1
  42. package/dist/lib/components/index.d.ts +0 -3
  43. package/dist/lib/index.d.ts +0 -2
  44. package/dist/lib/utils/capitalize.d.ts +0 -1
  45. package/dist/lib/utils/index.d.ts +0 -1
  46. package/dist/lib/utils/navigator.d.ts +0 -3
  47. package/dist/naria-ui.cjs.js +0 -26
  48. package/dist/naria-ui.css +0 -1
  49. package/dist/naria-ui.es.js +0 -671
  50. /package/{dist → public}/light.css +0 -0
  51. /package/{dist → public}/light.scss +0 -0
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 384 512" fill="currentColor"><path fill="currentColor" d="M209.5 369c-9.4 9.4-24.6 9.4-33.9 0L15.5 209c-9.4-9.4-9.4-24.6 0-33.9s24.6-9.4 33.9 0l143 143 143-143c9.4-9.4 24.6-9.4 33.9 0s9.4 24.6 0 33.9l-160 160z"/></svg>
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 512" fill="currentColor"><path fill="currentColor" d="M15.5 239c-9.4 9.4-9.4 24.6 0 33.9l160 160c9.4 9.4 24.6 9.4 33.9 0s9.4-24.6 0-33.9l-143-143 143-143c9.4-9.4 9.4-24.6 0-33.9s-24.6-9.4-33.9 0L15.5 239z"/></svg>
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 512" fill="currentColor"><path fill="currentColor" d="M241.5 239c9.4 9.4 9.4 24.6 0 33.9L81.5 433c-9.4 9.4-24.6 9.4-33.9 0s-9.4-24.6 0-33.9l143-143-143-143c-9.4-9.4-9.4-24.6 0-33.9s24.6-9.4 33.9 0l160 160z"/></svg>
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 384 512" fill="currentColor"><path fill="currentColor" d="M175.5 143c9.4-9.4 24.6-9.4 33.9 0l160 160c9.4 9.4 9.4 24.6 0 33.9s-24.6 9.4-33.9 0l-143-143-143 143c-9.4 9.4-24.6 9.4-33.9 0s-9.4-24.6 0-33.9l160-160z"/></svg>
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 384 512" fill="currentColor"><path fill="currentColor" d="M7.5 105c-9.4-9.4-9.4-24.6 0-33.9s24.6-9.4 33.9 0l151 151 151-151c9.4-9.4 24.6-9.4 33.9 0s9.4 24.6 0 33.9l-151 151 151 151c9.4 9.4 9.4 24.6 0 33.9s-24.6 9.4-33.9 0l-151-151-151 151c-9.4 9.4-24.6 9.4-33.9 0s-9.4-24.6 0-33.9l151-151-151-151z"/></svg>
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" fill="currentColor"><path fill="currentColor" d="M368 208a160 160 0 1 0 -320 0 160 160 0 1 0 320 0zM337.1 371.1C301.7 399.2 256.8 416 208 416 93.1 416 0 322.9 0 208S93.1 0 208 0 416 93.1 416 208c0 48.8-16.8 93.7-44.9 129.1L505 471c9.4 9.4 9.4 24.6 0 33.9s-24.6 9.4-33.9 0L337.1 371.1z"/></svg>
@@ -0,0 +1,28 @@
1
+ // For more info, see https://github.com/storybookjs/eslint-plugin-storybook#configuration-flat-config-format
2
+ import storybook from "eslint-plugin-storybook";
3
+
4
+ import js from '@eslint/js'
5
+ import globals from 'globals'
6
+ import reactHooks from 'eslint-plugin-react-hooks'
7
+ import reactRefresh from 'eslint-plugin-react-refresh'
8
+ import tseslint from 'typescript-eslint'
9
+
10
+ export default tseslint.config({ ignores: ['dist'] }, {
11
+ extends: [js.configs.recommended, ...tseslint.configs.recommended],
12
+ files: ['**/*.{ts,tsx}'],
13
+ languageOptions: {
14
+ ecmaVersion: 2020,
15
+ globals: globals.browser,
16
+ },
17
+ plugins: {
18
+ 'react-hooks': reactHooks,
19
+ 'react-refresh': reactRefresh,
20
+ },
21
+ rules: {
22
+ ...reactHooks.configs.recommended.rules,
23
+ 'react-refresh/only-export-components': [
24
+ 'warn',
25
+ { allowConstantExport: true },
26
+ ],
27
+ },
28
+ }, storybook.configs["flat/recommended"]);
@@ -0,0 +1,17 @@
1
+ import { RefObject, useEffect } from 'react';
2
+
3
+ const useClickOutside = <T extends HTMLElement>(ref: RefObject<T>, buttonRef: RefObject<T>, fn: () => void) => {
4
+ useEffect(() => {
5
+ function handleClickOutside(event: Event) {
6
+ if (buttonRef.current && !buttonRef.current.contains(event.target as Node | null) && ref?.current && !ref?.current.contains(event.target as Node | null)) {
7
+ fn();
8
+ }
9
+ }
10
+ document.addEventListener('mousedown', handleClickOutside);
11
+ return () => {
12
+ document.removeEventListener('mousedown', handleClickOutside);
13
+ };
14
+ }, [ref, fn]);
15
+ };
16
+
17
+ export default useClickOutside;
@@ -0,0 +1,7 @@
1
+ import {useEffect, useState} from 'react';
2
+
3
+ export const useIsFirstRender = () => {
4
+ const [isFirst, setIsFirst] = useState(true);
5
+ useEffect(() => { setIsFirst(false) }, [])
6
+ return isFirst
7
+ }
@@ -0,0 +1,11 @@
1
+ import {useEffect, useState} from "react";
2
+
3
+ export const useWidth = () => {
4
+ const [width, setWidth] = useState(typeof window !== "undefined" ? window.innerWidth : 0);
5
+ const handleResize = () => setWidth(typeof window !== "undefined" ? window.innerWidth : 0);
6
+ useEffect(() => {
7
+ window.addEventListener('resize', handleResize);
8
+ return () => window.removeEventListener('resize', handleResize);
9
+ }, [width]);
10
+ return width;
11
+ };
package/index.html ADDED
@@ -0,0 +1,13 @@
1
+ <!doctype html>
2
+ <html lang="en" dir="ltr">
3
+ <head>
4
+ <meta charset="UTF-8" />
5
+ <link rel="icon" type="image/svg+xml" href="/vite.svg" />
6
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
7
+ <title>Vite + React + TS</title>
8
+ </head>
9
+ <body>
10
+ <div id="root"></div>
11
+ <script type="module" src="/src/main.tsx"></script>
12
+ </body>
13
+ </html>
@@ -0,0 +1,47 @@
1
+ import React, {FC, ReactNode} from "react";
2
+ import './button.scss';
3
+ import Loading from "../../../shared/loading/Loading";
4
+
5
+ export interface props extends React.DetailedHTMLProps<React.ButtonHTMLAttributes<HTMLButtonElement>, HTMLButtonElement> {
6
+ type?: "button" | "submit";
7
+ classNames?: {
8
+ button: string;
9
+ loading: {
10
+ wrapper: string;
11
+ color: string;
12
+ };
13
+ };
14
+ value: string;
15
+ isLoading?: boolean;
16
+ isDisabled?: boolean;
17
+ icon?: ReactNode;
18
+ }
19
+
20
+ export const Button: FC<props> = ({
21
+ type = "button",
22
+ classNames = {
23
+ button: "",
24
+ loading: {
25
+ wrapper: "",
26
+ color: ""
27
+ }
28
+ },
29
+ value,
30
+ icon = null,
31
+ isLoading = false,
32
+ isDisabled = false,
33
+ ...otherProps
34
+ }) => {
35
+
36
+ return (
37
+ <button type={type} disabled={isDisabled} {...otherProps}
38
+ className={`nariaButton ${isDisabled ? "nariaButton-disabled" : ""} ${classNames?.button}`}
39
+ data-prop="button"
40
+ >{isLoading ? <Loading classNames={{
41
+ wrapper: classNames.loading.wrapper,
42
+ color: classNames.loading.color
43
+ }} data-prop-wrapper = "wrapper" data-prop-color = "color" /> : icon}{value}</button>
44
+ );
45
+ };
46
+
47
+
@@ -0,0 +1,9 @@
1
+ .nariaButton {
2
+ display: flex;
3
+ align-items: center;
4
+ width: 100%;
5
+ .nariaLoading {
6
+ width: 14px;
7
+ height: 14px;
8
+ }
9
+ }
@@ -0,0 +1 @@
1
+ export { Button } from './Button';
@@ -0,0 +1,66 @@
1
+ import {FC} from "react";
2
+
3
+ export interface props {
4
+ type?: "password" | "text";
5
+ classNames?: {
6
+ wrapper?: string;
7
+ label?: string;
8
+ title?: string;
9
+ input?: string;
10
+ errorText?: string;
11
+ };
12
+ placeholder: string;
13
+ title: string;
14
+ hasError?: string | null;
15
+ register?: any;
16
+ name?: string;
17
+ isDisabled?: boolean;
18
+ autocomplete?: boolean;
19
+ }
20
+
21
+ export const Input: FC<props> = ({
22
+ type = "text",
23
+ placeholder,
24
+ classNames = {
25
+ wrapper: "",
26
+ label: "",
27
+ title: "",
28
+ input: "",
29
+ errorText: "",
30
+ },
31
+ title,
32
+ hasError,
33
+ register, name,
34
+ isDisabled = false,
35
+ autocomplete = false,
36
+ ...otherProps
37
+ }) => {
38
+
39
+ return (
40
+ <div className={`nariaInputWrapper ${classNames.wrapper}`} data-prop = "wrapper">
41
+ <label
42
+ htmlFor={name}
43
+ className={`${classNames.label} ${hasError && "nariaInputLabel-error"}`} data-prop = "label">
44
+ <span className={classNames?.title} data-prop="title">{title}</span>
45
+ <input
46
+ disabled={isDisabled}
47
+ autoComplete={autocomplete ? "on" : "off"}
48
+ id={name}
49
+ {...register}
50
+ {...otherProps}
51
+ type={type}
52
+ name={name}
53
+ className={`${classNames.input} ${hasError && "nariaInput-error"}`}
54
+ placeholder={placeholder}
55
+ data-prop = "input"
56
+ />
57
+ </label>
58
+ {
59
+ hasError &&
60
+ <p className={`nariaInputErrorText ${classNames?.errorText}`} data-prop = "errorText">{hasError}</p>
61
+ }
62
+ </div>
63
+ );
64
+ };
65
+
66
+
@@ -0,0 +1 @@
1
+ export { Input } from './Input';
@@ -0,0 +1,414 @@
1
+ import {FC, useEffect, useRef, useState} from "react";
2
+ import AngleDown from "../../../assets/icons/angle-down.svg?react";
3
+ import Close from '../../../assets/icons/close.svg?react';
4
+ import Search from '../../../assets/icons/search.svg?react';
5
+ import {useWidth} from "../../../hooks/use-width";
6
+ import Loading from "../../../shared/loading/Loading";
7
+ import './select.scss';
8
+ import {addNavigation, onHashChanges, removeNavigation} from "../../../utils/navigator";
9
+ import useClickOutside from "../../../hooks/click-outside";
10
+
11
+ interface Pagination {
12
+ page?: number;
13
+ pageLabel?: string;
14
+ size?: number;
15
+ sizeLabel?: string;
16
+ }
17
+
18
+ interface SDS extends Pagination {
19
+ isLoading?: boolean;
20
+ }
21
+
22
+ export interface props {
23
+ options?: any[];
24
+ label?: string;
25
+ title: string;
26
+ value?: string;
27
+ api?: string;
28
+ hasError?: string | null;
29
+ selected?: any;
30
+ placeholder?: string;
31
+ disabled?: boolean;
32
+ pagination?: Pagination;
33
+ optionFilterLabel?: string;
34
+ hasSearch?: boolean;
35
+ classNames?: {
36
+ wrapper: string;
37
+ label?: string;
38
+ title?: string;
39
+ button?: string;
40
+ input?: string;
41
+ listWrapper?: string;
42
+ list?: string;
43
+ option?: string;
44
+ optionActive?: string;
45
+ mobileHeader?: string;
46
+ errorText?: string;
47
+ };
48
+ onSelectChange?: any;
49
+ }
50
+
51
+ export const Select: FC<props> = ({
52
+ options,
53
+ label,
54
+ hasError,
55
+ title,
56
+ value,
57
+ api,
58
+ selected,
59
+ placeholder,
60
+ disabled = false,
61
+ pagination,
62
+ optionFilterLabel,
63
+ hasSearch = false,
64
+ classNames = {
65
+ wrapper: "",
66
+ label: "",
67
+ title: "",
68
+ button: "",
69
+ input: "",
70
+ listWrapper: "",
71
+ list: "",
72
+ option: "",
73
+ optionActive: "",
74
+ mobileHeader: "",
75
+ errorText: "",
76
+ },
77
+ onSelectChange
78
+ }) => {
79
+ let isSubscribed = true;
80
+ const getDeviceWidth = useWidth();
81
+
82
+ const isHashChanged = onHashChanges('#select');
83
+ const [isShow, setIsShow] = useState(false);
84
+ const [isLoading, setIsLoading] = useState(true);
85
+ const [localSelected, setLocalSelected] = useState<string | null>(null);
86
+ const [localOptions, setLocalOptions] = useState(null);
87
+ const [searchTerm, setSearchTerm] = useState("");
88
+ const [localPagination, setLocalPagination] = useState<SDS>({
89
+ page: 1,
90
+ pageLabel: 'page',
91
+ size: 20,
92
+ sizeLabel: 'size',
93
+ isLoading: false
94
+ });
95
+ const localApi = useRef<string | undefined>(undefined);
96
+ const wrapperRef = useRef(undefined);
97
+ const handlerRef = useRef(undefined);
98
+
99
+ const getData = async () => {
100
+ if (localApi?.current) {
101
+ try {
102
+ const response = await fetch(localApi?.current);
103
+ if (!response.ok) {
104
+ throw new Error(`Response status: ${response.status}`);
105
+ }
106
+ return await response.json();
107
+ } catch (error) {
108
+ console.error(error.message);
109
+ }
110
+ }
111
+
112
+ }
113
+
114
+ useEffect(() => {
115
+ return () => {
116
+ isSubscribed = false;
117
+ };
118
+ }, [])
119
+ useEffect(() => {
120
+ if (api?.length) {
121
+ localApi.current = api;
122
+ if (localApi.current.includes(pagination?.pageLabel || 'page')) {
123
+ const url = new URL(api);
124
+ url.searchParams.set(pagination?.pageLabel || 'page', (pagination?.page || localPagination.page).toString());
125
+ url.searchParams.set(pagination?.sizeLabel || 'size', (pagination?.size || localPagination.size).toString());
126
+ localApi.current = url.href;
127
+ }
128
+ setIsLoading(true);
129
+ getData().then((res) => {
130
+ if (isSubscribed) {
131
+ setIsLoading(false);
132
+ setLocalOptions(res);
133
+ }
134
+ })
135
+ }
136
+ }, [api, pagination]);
137
+
138
+ useEffect(() => {
139
+ if (localPagination.isLoading) {
140
+ if (localApi.current.includes(pagination?.pageLabel || 'page')) {
141
+ const url = new URL(localApi.current);
142
+ url.searchParams.set(pagination?.pageLabel || 'page', (localPagination.page).toString());
143
+ localApi.current = url.href;
144
+ }
145
+ getData().then((res) => {
146
+ if (isSubscribed) {
147
+ setIsLoading(false);
148
+ setLocalPagination({
149
+ ...localPagination,
150
+ isLoading: false
151
+ })
152
+ setLocalOptions([
153
+ ...localOptions,
154
+ ...res
155
+ ]);
156
+ }
157
+ })
158
+ }
159
+ }, [localPagination]);
160
+ useEffect(() => {
161
+ if (getDeviceWidth < 768) {
162
+ if (isShow) {
163
+ addNavigation('select');
164
+ document.body.style.overflow = 'hidden';
165
+ handlerRef.current?.focus();
166
+ } else {
167
+ if (window.location.hash && !document.referrer.includes('#')) {
168
+ removeNavigation();
169
+ }
170
+ document.body.style.overflow = 'auto';
171
+ }
172
+ }
173
+ }, [isShow]);
174
+
175
+ useEffect(() => {
176
+ if (selected && options?.length) {
177
+ if (options?.find(item => item[label] === selected)) {
178
+ setLocalSelected(options?.find(item => item[label] === selected));
179
+ } else {
180
+ setLocalSelected(selected);
181
+ }
182
+ }
183
+ }, [selected]);
184
+
185
+ useEffect(() => {
186
+ if (localSelected) {
187
+ if (hasSearch) {
188
+ if (value?.length && localOptions?.find(item => item[label] === localSelected[label])) {
189
+ setSearchTerm(localOptions?.find(item => item[label] === localSelected[label])[value] || '');
190
+ } else {
191
+ setSearchTerm(localSelected);
192
+ }
193
+ }
194
+ }
195
+ }, [localSelected]);
196
+
197
+ useEffect(() => {
198
+ if (isHashChanged) {
199
+ setIsShow(false)
200
+ }
201
+ }, [isHashChanged])
202
+
203
+
204
+ useEffect(() => {
205
+ if (options?.length) {
206
+ setLocalOptions(options)
207
+ }
208
+ }, [options]);
209
+
210
+ const onToggle = () => {
211
+ if (hasSearch) {
212
+ setLocalOptions(options)
213
+ }
214
+ setIsShow(prevState => !prevState);
215
+ }
216
+ const onClose = () => {
217
+ if (hasSearch) {
218
+ setLocalOptions(options)
219
+ if (typeof localSelected === "string") {
220
+ setSearchTerm(localSelected);
221
+ } else {
222
+ setSearchTerm(localSelected ? localSelected[value] : "")
223
+ }
224
+ }
225
+ setIsShow(false);
226
+ }
227
+ const onSelect = (item) => {
228
+ if (hasSearch) {
229
+ if (value?.length) {
230
+ setSearchTerm(item[value]);
231
+ } else {
232
+ setSearchTerm(item);
233
+ }
234
+ }
235
+ setLocalSelected(item);
236
+ onToggle();
237
+ if (onSelectChange) {
238
+ onSelectChange(item);
239
+ }
240
+ }
241
+
242
+ const getActiveClass = (item) => {
243
+ if (!localSelected) {
244
+ return "";
245
+ }
246
+ if (label?.length && item[label] === localSelected[label]) {
247
+ return `nariaSelectOption-active ${classNames?.optionActive}`
248
+ }
249
+ if (item === localSelected) {
250
+ return `nariaSelectOption-active ${classNames?.optionActive}`
251
+ }
252
+ }
253
+ const onScroll = (e) => {
254
+ if (api?.length && localOptions?.length && !localPagination.isLoading) {
255
+ const bottom = e.target.offsetHeight + e.target.scrollTop >= e.target.scrollHeight - 100;
256
+
257
+ if (bottom) {
258
+ setLocalPagination({
259
+ page: localPagination.page + 1,
260
+ isLoading: true
261
+ })
262
+ }
263
+ }
264
+
265
+ }
266
+ const onSearch = (e) => {
267
+ const tempList = e?.target?.value?.length ? options.filter(val => typeof val === "object" ? val[(optionFilterLabel?.length ? optionFilterLabel : value)].includes(e?.target?.value) : val.includes(e?.target?.value)) : options
268
+ setLocalOptions(tempList)
269
+ setSearchTerm(e?.target?.value)
270
+ if (!isShow) {
271
+ setIsShow(true)
272
+ }
273
+ }
274
+ useClickOutside(wrapperRef, handlerRef, onClose);
275
+ return (
276
+ <div className={`nariaSelect ${disabled ? 'nariaSelect-disabled' : ''} ${classNames?.wrapper}`}
277
+ data-prop="wrapper">
278
+ <label
279
+ className={`${hasError && "!text-danger-100"}
280
+ ${classNames?.label}`} data-prop="label">
281
+ <span className={classNames?.title} data-prop="title">{title}</span>
282
+ {
283
+ hasSearch ? (
284
+ <div className="nariaSearchInput">
285
+ <input ref={handlerRef}
286
+ placeholder={placeholder?.length ? placeholder : "Select"}
287
+ className={`${localSelected ? "text-dark-100" : "text-grey-300"}
288
+ ${hasError && "!border-danger-100 focus:border-danger-100 outline-danger-100"} ${classNames?.input}`}
289
+ value={searchTerm}
290
+ disabled={disabled} type="text" onClick={onToggle} onChange={onSearch}
291
+ data-prop="input"/>
292
+ {
293
+ isShow ? (
294
+ <Search
295
+ className="nariaSearchIcon"/>
296
+ ) : (
297
+ <AngleDown
298
+ className={`nariaArrowIcon ${isShow ? "nariaArrowIcon-rotate-180" : ""}`}/>
299
+ )
300
+ }
301
+
302
+
303
+ </div>
304
+ ) : (
305
+ <button type="button"
306
+ ref={handlerRef}
307
+ disabled={disabled}
308
+ className={`nariaHandler ${localSelected ? "text-dark-100" : "text-grey-300"}
309
+ ${hasError && "!border-danger-100 focus:border-danger-100 outline-danger-100"} ${classNames?.button}`}
310
+ data-prop="button"
311
+ onClick={onToggle}>
312
+ {
313
+ localSelected ? (
314
+ value?.length ? localSelected[value] : localSelected
315
+ ) : (placeholder?.length ? placeholder : "Select")
316
+ } <AngleDown
317
+ className={`nariaArrowIcon ${isShow ? "nariaArrowIcon-rotate-180" : ""}`}/>
318
+ </button>
319
+ )
320
+ }
321
+
322
+ </label>
323
+
324
+ {
325
+ isShow ? (
326
+ <div
327
+ className={`nariaListWrapper ${getDeviceWidth < 768 ? "nariaListWrapper-mobile" : ""} ${classNames?.listWrapper}`}
328
+ data-prop="listWrapper"
329
+ ref={wrapperRef}>
330
+ <div
331
+ className={`nariaList ${getDeviceWidth < 768 ? "nariaList-mobile" : `nariaList-desktop`} ${classNames?.list}`}
332
+ data-prop="input"
333
+ onScroll={onScroll}>
334
+ {
335
+ api && isLoading ? (
336
+ <div className="nariaLoadingWrapper">
337
+ <Loading/>
338
+ </div>
339
+ ) : (
340
+ <>
341
+ {
342
+ getDeviceWidth < 768 ? (
343
+ <div className={`nariaSelectMobileHeader ${classNames?.mobileHeader}`}
344
+ data-prop="mobileHeader">
345
+ {
346
+ hasSearch ? (
347
+ <div className="nariaSearchInput">
348
+ <input ref={handlerRef}
349
+ placeholder={placeholder?.length ? placeholder : "Select"}
350
+ className={`${localSelected ? "text-dark-100" : "text-grey-300"}
351
+ ${hasError && "!border-danger-100 focus:border-danger-100 outline-danger-100"} ${classNames?.input}`}
352
+ data-prop="input"
353
+ value={searchTerm}
354
+ disabled={disabled} type="text"
355
+ onChange={onSearch}/>
356
+ <Search
357
+ className="nariaSearchIcon"/>
358
+ </div>
359
+ ) : undefined
360
+ }
361
+ <button className="p-3" onClick={onClose} disabled={disabled}>
362
+ <Close className="w-6"/>
363
+ </button>
364
+ </div>
365
+ ) : undefined
366
+ }
367
+ {
368
+ localOptions?.length ? (
369
+ <>
370
+ {
371
+ localOptions?.map((item, index) => {
372
+ return (
373
+ <button type="button" onClick={() => onSelect(item)}
374
+ disabled={disabled}
375
+ key={index.toString()}
376
+ className={`nariaSelectOption ${classNames?.option} ${getActiveClass(item)}`}
377
+ data-prop="option"
378
+ data-prop-active="optionActive">
379
+ {value?.length ? item[value] : item}
380
+ </button>
381
+ )
382
+ })
383
+ }
384
+ </>
385
+ ) : (
386
+ <div>
387
+ No Data
388
+ </div>
389
+ )
390
+ }
391
+
392
+
393
+ {
394
+ localPagination.isLoading ? (
395
+ <div className="nariaLoadingMoreWrapper">
396
+ <Loading/>
397
+ </div>
398
+ ) : undefined
399
+ }
400
+ </>
401
+ )
402
+ }
403
+ </div>
404
+ </div>
405
+ ) : undefined
406
+ }
407
+ {
408
+ hasError &&
409
+ <p className={`nariaSelectErrorText ${classNames?.errorText}`} data-prop = "errorText">{hasError}</p>
410
+ }
411
+
412
+ </div>
413
+ );
414
+ };
@@ -0,0 +1 @@
1
+ export { Select } from './Select';