forstok-ui-lib 5.0.2 → 5.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.
@@ -0,0 +1,331 @@
1
+ import { useEffect, useState } from 'react';
2
+ import ReactSelect from 'react-select';
3
+ import type { SingleValueProps, OptionProps, StylesConfig, ActionMeta, ControlProps, MultiValueProps, OnChangeValue, CSSObjectWithLabel } from 'react-select';
4
+ import CreatableSelect from 'react-select/creatable';
5
+ import type { CSSObject } from '@emotion/serialize';
6
+ import { generateMessageQuestion } from '../../assets/javascripts/function';
7
+ import type { TState, TObject } from '../../typeds/base.typed';
8
+ import type { TMessageQuestionFunction } from '../message/typed';
9
+ import type { TOption } from './typed';
10
+
11
+ type TSelect = {
12
+ type?: string
13
+ mode?: string
14
+ isError?: boolean
15
+ name?: string
16
+ customOption?: (arg0: OptionProps) => void
17
+ customLabel?: (arg0: SingleValueProps) => void
18
+ MenuList?: any
19
+ isCreateable?: boolean
20
+ isClearable?: boolean
21
+ selectKey?: string
22
+ disabled?: boolean
23
+ width?: string | number
24
+ reset?: boolean
25
+ setReset?: TState<boolean>
26
+ isForceUpdate?: boolean
27
+ setForceUpdate?: TState<boolean>
28
+ isCheckAutoCopy?: boolean
29
+ isField?: boolean
30
+ isMulti?: boolean
31
+ evCreate?: (value: string) => void
32
+ evChange?: (newValue: OnChangeValue<TOption, boolean>, actionMeta?: ActionMeta<TOption>) => void
33
+ evChangeCustom? : (key: string, value: any) => void
34
+ defaultValue?: OnChangeValue<TOption, boolean>
35
+ options: TOption[] | null
36
+ isMinOption?: boolean
37
+ placeholder?: string
38
+ 'data-qa-id'?: string
39
+ removeMessage?: TObject
40
+ evCreateMessageQuestion?: TMessageQuestionFunction
41
+ }
42
+
43
+ const SelectComponent = ({ type, isError=false, mode, customOption, customLabel, MenuList, isCreateable=false, isClearable=false, selectKey, disabled, defaultValue, width, reset, setReset, isForceUpdate, setForceUpdate, isCheckAutoCopy, evChangeCustom, isField, evCreate, evChange, isMinOption, isMulti=false, options, name, placeholder, removeMessage, evCreateMessageQuestion, ...props }: TSelect) => {
44
+ const [valueState, setValue] = useState<typeof defaultValue>(defaultValue || null)
45
+
46
+ useEffect(()=> {
47
+ if (reset) {
48
+ setValue(null);
49
+ setReset && setReset(false);
50
+ }
51
+ if (isForceUpdate) {
52
+ let changeValue = defaultValue;
53
+ if (isCheckAutoCopy) {
54
+ if (changeValue) {
55
+ let isChanging = false;
56
+ if (isMulti) {
57
+ let _changeValue = changeValue as OnChangeValue<TOption, true>;
58
+ if (Array.isArray(_changeValue) && _changeValue.length) {
59
+ let newValue = [] as OnChangeValue<TOption, true>;
60
+ for (const _value of _changeValue) {
61
+ const optionFilter = options?.filter(opt => (opt.label === _value.label && opt.value === _value.value) );
62
+ if (optionFilter?.length && Array.isArray(newValue)) {
63
+ newValue.push(_value);
64
+ }
65
+ else {
66
+ !isChanging && (isChanging = true);
67
+ }
68
+ }
69
+ newValue.length && (_changeValue = newValue);
70
+ }
71
+ } else {
72
+ let _changeValue = changeValue as OnChangeValue<TOption, false>;
73
+ if (_changeValue) {
74
+ const optionFilter = options?.filter(opt => _changeValue && (opt.label === _changeValue.label && opt.value === _changeValue.value) );
75
+ if (optionFilter?.length) {
76
+ changeValue = null;
77
+ isChanging = true;
78
+ }
79
+ }
80
+ }
81
+ (isChanging && name) && evChangeCustom && evChangeCustom(name, changeValue);
82
+ }
83
+ }
84
+ setValue(changeValue);
85
+ setForceUpdate && setForceUpdate(false);
86
+ }
87
+ }, [defaultValue, evChangeCustom, isCheckAutoCopy, isForceUpdate, isMulti, name, options, reset, setForceUpdate, setReset])
88
+
89
+ const evToogleSelect = () => {
90
+ const containerRef = document.getElementsByClassName('_refContainer is-shown') as HTMLCollectionOf<HTMLElement>;
91
+ if (containerRef.length) {
92
+ for (let i = 0; i < containerRef.length; i++) {
93
+ containerRef[i].classList.remove('is-shown');
94
+ }
95
+ }
96
+ }
97
+
98
+ const handleChange = (value: OnChangeValue<TOption, typeof isMulti>, { action, removedValue, option }: any) => {
99
+ if (isMulti) {
100
+ const newValue = value as OnChangeValue<TOption, true>;
101
+ const removeCallback = () => {
102
+ setValue(newValue);
103
+ evChange && evChange(newValue, { action, removedValue, option });
104
+ }
105
+ switch (action) {
106
+ case 'remove-value':
107
+ if (isMinOption) {
108
+ if (action === 'remove-value' && (Array.isArray(valueState) && valueState.length === 1)) {
109
+ return false;
110
+ }
111
+ }
112
+ if (removedValue.isFixed) {
113
+ return;
114
+ }
115
+ break;
116
+ case 'pop-value':
117
+ if (removedValue.isFixed) {
118
+ return;
119
+ }
120
+ break;
121
+ case 'clear':
122
+ value = options?.filter((v) => v.isFixed) || [];
123
+ break;
124
+ default:
125
+ break;
126
+ }
127
+ if (removeMessage && action === 'remove-value') {
128
+ const _confirm_props = generateMessageQuestion('confirm', removeMessage?.title || '', removeMessage?.subtitle || '', removeCallback);
129
+ evCreateMessageQuestion && evCreateMessageQuestion(_confirm_props);
130
+ return false;
131
+ } else {
132
+ setValue(newValue);
133
+ evChange && evChange(newValue, { action, removedValue, option });
134
+ }
135
+ } else {
136
+ const newValue = value as OnChangeValue<TOption, false>;
137
+ mode === 'paymentReceiveStore' ? setValue(newValue ? { value: newValue.value, label : newValue.label, channel: newValue.channel } : newValue) : setValue(newValue ? { value: newValue.value, label : newValue.label } : newValue);
138
+ evChange && evChange(newValue, { action, removedValue, option });
139
+ }
140
+ (!isMulti && isField && evChangeCustom && name) && evChangeCustom(name, value);
141
+ }
142
+
143
+ const handleBlur = () => {
144
+ (isField && evChangeCustom && name && valueState) && evChangeCustom(name, valueState);
145
+ }
146
+
147
+ const handleCreate = (inputValue: string) => {
148
+ setReset && setReset(false);
149
+ if (isMulti) {
150
+ !Array.isArray(valueState) ? setValue([{ value: inputValue, label : inputValue }]) : setValue([...valueState, { value: inputValue, label : inputValue }]);
151
+ }
152
+ else {
153
+ setValue({ value: inputValue, label : inputValue });
154
+ }
155
+ evCreate && evCreate(inputValue);
156
+ }
157
+
158
+ const isValidNewOption = (inputValue: string, selectOptions: TOption[]) => {
159
+ return !(inputValue.trim().length === 0 || selectOptions.find(option => option.name === inputValue));
160
+ }
161
+
162
+ const customStyles: StylesConfig<TOption, typeof isMulti> = {
163
+ container: (provided: CSSObject) => ({
164
+ ...provided,
165
+ display: 'inline-block',
166
+ width: width ? width+'px' : '100%',
167
+ minHeight: '1px',
168
+ textAlign: 'left',
169
+ border: 'none',
170
+ } as CSSObjectWithLabel),
171
+ control: (provided: CSSObject, state:ControlProps<TOption, typeof isMulti>) => ({
172
+ ...provided,
173
+ borderRadius: mode === 'filter' ? 'var(--sec-rd)' : 'var(--ter-rd)',
174
+ minHeight: mode === 'picklist' ? '30px': '1px',
175
+ height: mode === 'orders' ? '90px' : '30px',
176
+ maxHeight: mode === 'picklist' ? '46px': 'none',
177
+ cursor: 'pointer',
178
+ borderWidth: '1px' ,
179
+ boxShadow: (state.isFocused && mode === 'filter') ? 'var(--act-shd-bx)' : 'none',
180
+ borderColor: ((state.isFocused && mode !== 'filter') && !isError) ? 'var(--pri-clr-ln__fc)' : (isError ? 'var(--err-clr-ln)' : (mode ==='filter' ? 'var(--ter-clr-ln)' : ' var(--ck-clr-ln)' )),
181
+ background: mode ==='filter' ? 'var(--ter-clr-ln)' : '',
182
+ overflow: mode === 'picklist' ? 'hidden': (mode === 'orders' ? 'auto' : 'initial'),
183
+ alignItems: mode === 'orders' ? 'start' : 'center',
184
+ padding: mode === 'orders' ? '6px 0' : 'unset',
185
+ '&:hover': {
186
+ borderColor: ((state.isFocused && mode !== 'filter') && !isError) ? 'var(--pri-clr-ln__fc)' : (isError ? 'var(--err-clr-ln)' : (mode ==='filter' ? 'var(--ter-clr-ln)' : ' var(--ck-clr-ln)' )),
187
+ }
188
+ } as CSSObjectWithLabel),
189
+ placeholder: (provided: CSSObject) => ({
190
+ ...provided,
191
+ fontStyle: 'italic'
192
+ } as CSSObjectWithLabel),
193
+ input: (provided: CSSObject) => ({
194
+ ...provided,
195
+ minHeight: '1px',
196
+ margin: '0 2px',
197
+ padding: '0',
198
+ 'input': {
199
+ boxShadow: 'none !important'
200
+ }
201
+ } as CSSObjectWithLabel),
202
+ dropdownIndicator: (provided: CSSObject) => ({
203
+ ...provided,
204
+ minHeight: '1px',
205
+ paddingTop: '0',
206
+ paddingBottom: '0',
207
+ paddingLeft: '2px',
208
+ paddingRight: '2px',
209
+ color: '#757575',
210
+ alignSelf: mode === 'orders' ? 'start' : 'unset',
211
+ } as CSSObjectWithLabel),
212
+ indicatorSeparator: (provided: CSSObject) => ({
213
+ ...provided,
214
+ minHeight: '1px',
215
+ height: '24px',
216
+ display: (type=== 'tag') ? 'block' : 'none'
217
+ } as CSSObjectWithLabel),
218
+ clearIndicator: (provided: CSSObject) => ({
219
+ ...provided,
220
+ minHeight: '1px',
221
+ marginRight: '-6px',
222
+ padding: '0'
223
+ } as CSSObjectWithLabel),
224
+ valueContainer: (provided: CSSObject) => ({
225
+ ...provided,
226
+ height: '30px',
227
+ maxHeight: mode === 'picklist' ? '46px': 'none',
228
+ minHeight: mode === 'picklist' ? '30px': '1px',
229
+ overflow: mode === 'picklist' ? 'auto': 'initial',
230
+ paddingTop: '0',
231
+ paddingBottom: '0',
232
+ paddingRight: '2px',
233
+ } as CSSObjectWithLabel),
234
+ singleValue: (provided: CSSObject) => ({
235
+ ...provided,
236
+ minHeight: '1px',
237
+ paddingBottom: '2px',
238
+ color: (disabled? '#ADADAD' : (mode === 'form' ? '#2d3c48' : 'initial')),
239
+ opacity: disabled ? '.7' : 1,
240
+ } as CSSObjectWithLabel),
241
+ option: (provided: CSSObject, state: OptionProps<TOption, typeof isMulti>) => ({
242
+ ...provided,
243
+ color: state.isSelected ? '#ffffff' : '#000000',
244
+ backgroundColor: state.isSelected || state.isFocused ? '#fc5c64' : 'transparent',
245
+ cursor: 'pointer',
246
+ '&:hover': {
247
+ backgroundColor: '#ec5b62',
248
+ color: '#ffffff'
249
+ }
250
+ } as CSSObjectWithLabel),
251
+ menu: (provided: CSSObject) => ({
252
+ ...provided,
253
+ borderRadius: mode === 'filter' ? 'var(--sec-rd)' : 'var(--ter-rd)',
254
+ } as CSSObjectWithLabel),
255
+ menuPortal: (provided: CSSObject) => ({
256
+ ...provided,
257
+ zIndex: 9999,
258
+ letterSpacing: 'normal',
259
+ lineHeight: 'normal',
260
+ } as CSSObjectWithLabel),
261
+ multiValue: (base: any, state: MultiValueProps<TOption, typeof isMulti>) => {
262
+ return state.data.isFixed ? { ...base, backgroundColor: 'gray' } : base
263
+ },
264
+ multiValueLabel: (base: any, state: MultiValueProps<TOption, typeof isMulti>) => {
265
+ return state.data.isFixed ? { ...base, fontWeight: 'bold', color: 'white', paddingRight: 6 } : base
266
+ },
267
+ multiValueRemove: (provided: CSSObject, state: MultiValueProps<TOption, typeof isMulti>) => ({
268
+ ...provided,
269
+ display: state.data.isFixed ? 'none' : 'block',
270
+ 'svg': {
271
+ position: 'relative',
272
+ top: '2px'
273
+ }
274
+ } as CSSObjectWithLabel),
275
+ }
276
+
277
+ let SelectEl = isCreateable ?
278
+ <CreatableSelect
279
+ options={options}
280
+ styles={customStyles}
281
+ onMenuOpen={evToogleSelect}
282
+ menuPortalTarget={document.body}
283
+ menuPosition='fixed'
284
+ menuPlacement='auto'
285
+ value={valueState}
286
+ onChange={handleChange}
287
+ // onInputChange={handleInputChange}
288
+ onCreateOption= {handleCreate}
289
+ isValidNewOption={isValidNewOption}
290
+ noOptionsMessage={() => null}
291
+ isClearable={isClearable ? ((Array.isArray(valueState) && valueState.length) ? valueState.some((v) => !v.isFixed) : true) : isClearable}
292
+ {...isMulti && { isMulti: true }}
293
+ {...customOption && { components: { Option: customOption } }}
294
+ {...MenuList && { components: { MenuList, Option: customOption } }}
295
+ {...selectKey && { key: selectKey }}
296
+ {...disabled && { isDisabled: disabled }}
297
+ {...isMulti && { closeMenuOnSelect: false }}
298
+ {...isMulti && { onBlur: handleBlur }}
299
+ {...placeholder && { placeholder }}
300
+ {...props} />
301
+ :
302
+ <ReactSelect
303
+ options={options}
304
+ styles={customStyles}
305
+ onMenuOpen={evToogleSelect}
306
+ menuPortalTarget={document.body}
307
+ menuPosition='fixed'
308
+ menuPlacement='auto'
309
+ value={valueState}
310
+ onChange={handleChange}
311
+ noOptionsMessage={() => null}
312
+ isClearable={isClearable ? ((Array.isArray(valueState) && valueState.length) ? valueState.some((v) => !v.isFixed) : true) : isClearable}
313
+ {...isMulti && { isMulti: true }}
314
+ {...customOption && { components: { Option: customOption } }}
315
+ {...mode === 'paymentReceiveStore' && { components: { Option: customOption, SingleValue: customLabel } }}
316
+ {...MenuList && { components: { MenuList, Option: customOption } }}
317
+ {...selectKey && { key: selectKey }}
318
+ {...disabled && { isDisabled: disabled }}
319
+ {...isMulti && { closeMenuOnSelect: false }}
320
+ {...isMulti && { onBlur: handleBlur }}
321
+ {...placeholder && { placeholder }}
322
+ {...props} />
323
+
324
+ return (
325
+ <section className='_refContainer' {...props}>
326
+ {SelectEl}
327
+ </section>
328
+ )
329
+ }
330
+
331
+ export default SelectComponent
@@ -0,0 +1,5 @@
1
+ import styled from 'styled-components';
2
+
3
+ export const SelectCheckboxContainer = styled.section`
4
+ max-width: 530px;
5
+ `
@@ -0,0 +1,16 @@
1
+ import type { TChannel } from '../../typeds/shares.typed';
2
+
3
+ export type TOption = {
4
+ readonly value: any
5
+ readonly label: string
6
+ readonly name?: string
7
+ readonly isFixed?: boolean
8
+ readonly channel?: Omit<TChannel, 'stores'>
9
+ postalCode?: string
10
+ localId?: string
11
+ option?: {
12
+ readonly value: any
13
+ readonly label: string
14
+ localId?: string
15
+ }[]
16
+ }
@@ -33,4 +33,24 @@ export type THierarchy = {
33
33
  evOpenPopup?: TPopupOpenFunction
34
34
  evCloseDropdown?: TCloseDropdownFunction
35
35
  evCreateMessageQuestion?: TMessageQuestionFunction
36
+ }
37
+ export type TChannel = {
38
+ channelName?: string
39
+ channelInitials?: string
40
+ channelColor?: string
41
+ channelImage?: string
42
+ channelId?: number
43
+ name?: string | null
44
+ initials?: string | null
45
+ color?: string | null
46
+ icon?: string | null
47
+ id?: number | null
48
+ totalStores?: number
49
+ Stores?: {
50
+ id?: number
51
+ storeName?: string
52
+ storeImage?: string
53
+ storeImageName?: string
54
+ }[]
55
+ availableAPI?: boolean | null
36
56
  }
package/tsconfig.json CHANGED
@@ -22,8 +22,7 @@
22
22
  },
23
23
  "include": [
24
24
  "src",
25
- "src/declarations.d.ts"
26
- ],
25
+ "src/declarations.d.ts" ],
27
26
  "exclude": [
28
27
  "node_modules",
29
28
  "dist"