@juspay/svelte-ui-components 1.7.0 → 1.9.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.
@@ -192,6 +192,7 @@ $: {
192
192
  .input-container {
193
193
  display: flex;
194
194
  flex-direction: column;
195
+ margin: var(--input-container-margin);
195
196
  }
196
197
 
197
198
  .label {
@@ -21,6 +21,11 @@ function leftButtonClick(event) {
21
21
  event.preventDefault();
22
22
  dispatch("leftButtonClick");
23
23
  }
24
+ function bottomButtonClick() {
25
+ if (state === "Valid") {
26
+ dispatch("bottomButtonClick", { value: properties.inputProperties.value });
27
+ }
28
+ }
24
29
  function triggerRightClickIfValid(event) {
25
30
  if (event?.key === "Enter") {
26
31
  rightButtonClick();
@@ -32,6 +37,9 @@ function handleState(event) {
32
37
  }
33
38
  dispatch("stateChange", event);
34
39
  }
40
+ function onFocusOut(event) {
41
+ dispatch("focusout", event);
42
+ }
35
43
  </script>
36
44
 
37
45
  {#if properties.inputProperties.label && properties.inputProperties.label !== ''}
@@ -55,6 +63,7 @@ function handleState(event) {
55
63
  on:keyup={triggerRightClickIfValid}
56
64
  on:stateChange={handleState}
57
65
  on:input={(event) => dispatch('input', event)}
66
+ on:focusout={onFocusOut}
58
67
  on:focus
59
68
  --input-width="auto"
60
69
  />
@@ -65,6 +74,11 @@ function handleState(event) {
65
74
  </div>
66
75
  {/if}
67
76
  </div>
77
+ {#if properties.bottomButtonProperties != null}
78
+ <div class="bottom-button">
79
+ <Button properties={properties.bottomButtonProperties} on:click={bottomButtonClick} />
80
+ </div>
81
+ {/if}
68
82
  </div>
69
83
  {#if properties.inputProperties.message.onError !== '' && state === 'Invalid'}
70
84
  <div class="error-message">
@@ -87,6 +101,7 @@ function handleState(event) {
87
101
  --button-width: 100%;
88
102
  --input-border: none;
89
103
  --input-focus-border: none;
104
+ border: var(--input-button-container-border);
90
105
  }
91
106
 
92
107
  .input-button {
@@ -110,6 +125,20 @@ function handleState(event) {
110
125
  --button-height: 54px;
111
126
  }
112
127
 
128
+ .bottom-button {
129
+ padding: var(--input-bottom-btn-padding, 10px 0px);
130
+ --cursor: var(--bottom-button-cursor);
131
+ --button-color: var(--bottom-button-color);
132
+ --button-text-color: var(--bottom-button-text-color);
133
+ --button-font-family: var(--bottom-button-font-family);
134
+ --button-font-weight: var(--bottom-button-font-weight);
135
+ --button-font-size: var(--bottom-button-font-size);
136
+ --button-height: var(--bottom-button-height, 54px);
137
+ --button-padding: var(--bottom-button-padding);
138
+ --button-border-radius: var(--bottom-button-border-radius);
139
+ --button-width: var(--bottom-button-width);
140
+ }
141
+
113
142
  .label {
114
143
  font-weight: var(--input-label-msg-text-weight, 400);
115
144
  font-size: var(--input-label-msg-text-size, 12px);
@@ -9,7 +9,9 @@ declare const __propDef: {
9
9
  input: CustomEvent<any>;
10
10
  rightButtonClick: CustomEvent<any>;
11
11
  leftButtonClick: CustomEvent<any>;
12
+ bottomButtonClick: CustomEvent<any>;
12
13
  stateChange: CustomEvent<any>;
14
+ focusout: CustomEvent<any>;
13
15
  } & {
14
16
  [evt: string]: CustomEvent<any>;
15
17
  };
@@ -4,5 +4,6 @@ export type InputButtonProperties = {
4
4
  inputProperties: InputProperties;
5
5
  rightButtonProperties: ButtonProperties | null;
6
6
  leftButtonProperties: ButtonProperties | null;
7
+ bottomButtonProperties?: ButtonProperties | null;
7
8
  };
8
9
  export declare const defaultInputButtonProperties: InputButtonProperties;
@@ -13,5 +13,6 @@ const rightButtonProperties = {
13
13
  export const defaultInputButtonProperties = {
14
14
  inputProperties,
15
15
  rightButtonProperties,
16
- leftButtonProperties: null
16
+ leftButtonProperties: null,
17
+ bottomButtonProperties: null
17
18
  };
@@ -154,14 +154,17 @@ onDestroy(() => {
154
154
 
155
155
  .small {
156
156
  height: var(--modal-small-height, 20vh);
157
+ width: var(--modal-small-width);
157
158
  }
158
159
 
159
160
  .medium {
160
161
  height: var(--modal-medium-height, 50vh);
162
+ width: var(--modal-medium-width);
161
163
  }
162
164
 
163
165
  .large {
164
166
  height: var(--modal-large-height, 80vh);
167
+ width: var(--modal-large-width);
165
168
  }
166
169
 
167
170
  .fit-content {
@@ -14,13 +14,15 @@ export let properties = {
14
14
  leftIcon: null
15
15
  };
16
16
  const dropDownIcon = properties.dropDownIcon ?? "https://sdk.breeze.in/gallery/icons/down-arrow.svg";
17
- const applyButtonProps = {
18
- text: "Apply",
19
- enable: true,
20
- showLoader: false,
21
- loaderType: null,
22
- type: "submit"
23
- };
17
+ let applyButtonProps;
18
+ $:
19
+ applyButtonProps = {
20
+ text: `Select (${properties.selectedItem.length})`,
21
+ enable: properties.selectedItem.length > 0,
22
+ showLoader: false,
23
+ loaderType: null,
24
+ type: "submit"
25
+ };
24
26
  const selectAllButtonProps = {
25
27
  text: "Select All",
26
28
  enable: true,
@@ -41,9 +43,16 @@ $:
41
43
  nonSelectedItems = properties.allItems.filter(
42
44
  (item) => properties.selectMultipleItems ? !properties.selectedItem.includes(item) : item !== properties.selectedItem
43
45
  );
46
+ function isSelected(selectedItem, item) {
47
+ if (Array.isArray(selectedItem)) {
48
+ return selectedItem.includes(item);
49
+ } else {
50
+ return selectedItem.trim() === item.trim();
51
+ }
52
+ }
44
53
  function selectItem(item) {
45
54
  if (properties.selectMultipleItems && Array.isArray(properties.selectedItemLabel) && Array.isArray(properties.selectedItem)) {
46
- if (properties.selectedItem.includes(item)) {
55
+ if (isSelected(properties.selectedItem, item)) {
47
56
  properties.selectedItem = properties.selectedItem.filter(
48
57
  (selectedItem) => selectedItem !== item
49
58
  );
@@ -56,6 +65,7 @@ function selectItem(item) {
56
65
  }
57
66
  } else {
58
67
  properties.selectedItem = [item];
68
+ properties.selectedItemLabel = [item];
59
69
  }
60
70
  if (!properties.selectMultipleItems) {
61
71
  toggleSelect();
@@ -64,6 +74,7 @@ function selectItem(item) {
64
74
  }
65
75
  function dispatchEvent() {
66
76
  dispatch("message", { selectedItems: properties.selectedItem });
77
+ isSelectOpen = false;
67
78
  }
68
79
  function toggleSelect() {
69
80
  isSelectOpen = !isSelectOpen;
@@ -120,21 +131,23 @@ onDestroy(() => {
120
131
  <Img {...properties.leftIcon} />
121
132
  </div>
122
133
  {/if}
123
- {#if properties.selectMultipleItems && Array.isArray(properties.selectedItemLabel) && Array.isArray(properties.selectedItem)}
124
- {#if properties.selectedItem.length === 0}
134
+ <div class="selected-content">
135
+ {#if properties.selectMultipleItems && Array.isArray(properties.selectedItemLabel) && Array.isArray(properties.selectedItem)}
136
+ {#if properties.selectedItem.length === 0}
137
+ {properties.placeholder}
138
+ {:else if properties.selectedItemLabel?.length === 0 || properties.showSelectedItemInDropdown}
139
+ {properties.selectedItem.join(', ')}
140
+ {:else}
141
+ {properties.selectedItemLabel.join(', ')}
142
+ {/if}
143
+ {:else if properties.selectedItem === ''}
125
144
  {properties.placeholder}
126
- {:else if properties.selectedItemLabel?.length === 0 || properties.showSelectedItemInDropdown}
127
- {properties.selectedItem.join(', ')}
145
+ {:else if properties.selectedItemLabel === null || properties.selectedItemLabel === ''}
146
+ {properties.selectedItem}
128
147
  {:else}
129
- {properties.selectedItemLabel.join(', ')}
148
+ {properties.selectedItemLabel}
130
149
  {/if}
131
- {:else if properties.selectedItem === ''}
132
- {properties.placeholder}
133
- {:else if properties.selectedItemLabel === null || properties.selectedItemLabel === ''}
134
- {properties.selectedItem}
135
- {:else}
136
- {properties.selectedItemLabel}
137
- {/if}
150
+ </div>
138
151
  <div class="filler" />
139
152
  {#if !properties.hideDropDownIcon}
140
153
  <img
@@ -148,9 +161,8 @@ onDestroy(() => {
148
161
  class="non-selected-items"
149
162
  style="--non-selected-display:{isSelectOpen ? 'inline-block' : 'none'};"
150
163
  >
151
- {#if properties.selectMultipleItems}
164
+ {#if properties.selectMultipleItems && !properties.showSingleSelectButton}
152
165
  <div class="multipleSelect-btn">
153
- <Button properties={applyButtonProps} on:click={dispatchEvent} />
154
166
  <Button properties={selectAllButtonProps} on:click={selectAllItems} />
155
167
  <Button properties={clearAllButtonProps} on:click={clearAllItems} />
156
168
  </div>
@@ -162,7 +174,7 @@ onDestroy(() => {
162
174
  on:click={() => {
163
175
  selectItem(item);
164
176
  }}
165
- class="item {properties.selectedItem.includes(item) ? 'selected item-selected' : ''}"
177
+ class="item {isSelected(properties.selectedItem, item) ? ' item-selected' : ''}"
166
178
  role="button"
167
179
  tabindex="0"
168
180
  >
@@ -170,6 +182,14 @@ onDestroy(() => {
170
182
  </div>
171
183
  {/each}
172
184
  </div>
185
+ {#if $$slots.bottomContent}
186
+ <slot name="bottomContent" />
187
+ {/if}
188
+ {#if properties.selectMultipleItems}
189
+ <div class="apply-btn-container">
190
+ <Button properties={applyButtonProps} on:click={dispatchEvent} />
191
+ </div>
192
+ {/if}
173
193
  </div>
174
194
  </div>
175
195
  {/if}
@@ -186,16 +206,16 @@ onDestroy(() => {
186
206
  min-width: var(--select-min-width);
187
207
  box-shadow: var(--select-box-shadow, 0px 1px 8px #2f537733);
188
208
  -webkit-appearance: none !important; /* For Safari MWeb */
189
- outline: none;
190
- cursor: pointer;
191
- border: var(--select-border);
192
- word-break: var(--select-word-break, break-word);
209
+ outline: var(--select-outline, none);
193
210
  resize: none;
194
- position: relative;
195
- white-space: var(--select-white-space);
196
- color: var(--select-color);
197
- --button-margin: 1px;
198
- --button-border-radius: 2px;
211
+ cursor: pointer;
212
+ border: var(--select-border, 1px solid #ccc);
213
+ position: var(--select-position, relative);
214
+ color: var(--select-color, #333);
215
+ display: var(--select-display, inline-block);
216
+ --button-margin: var(--select-btn-margin, 1px);
217
+ --button-border-radius: var(--select-btn-border-radius, 2px);
218
+ --input-button-margin: var(--select-input-button-margin, 10px);
199
219
  }
200
220
 
201
221
  .select:hover {
@@ -206,6 +226,8 @@ onDestroy(() => {
206
226
  height: var(--dropdown-arrow-icon-height, 16px);
207
227
  width: var(--dropdown-arrow-icon-width, 16px);
208
228
  transition: transform 0.1s;
229
+ position: absolute;
230
+ right: 10px;
209
231
  }
210
232
 
211
233
  .active {
@@ -213,8 +235,11 @@ onDestroy(() => {
213
235
  }
214
236
 
215
237
  .item {
216
- padding: var(--item-padding, 8px);
217
- border-radius: 4px;
238
+ padding: var(--item-padding, 8px 16px);
239
+ background-color: var(--item-background-color, #fff);
240
+ border-radius: var(--item-border-radius);
241
+ cursor: pointer;
242
+ position: relative;
218
243
  }
219
244
 
220
245
  .filler {
@@ -222,15 +247,27 @@ onDestroy(() => {
222
247
  }
223
248
 
224
249
  .item:hover {
225
- background-color: var(--non-selected-hover-bg, #00000010);
250
+ background-color: var(--non-selected-hover-bg, #f0f0f0);
226
251
  color: var(--non-selected-hover-color);
227
252
  }
228
253
 
229
254
  .selected {
230
- margin: 0px;
231
255
  display: flex;
232
- justify-content: flex-start;
233
- align-items: center;
256
+ align-items: var(--selected-align-items, center);
257
+ margin: var(--selected-margin, 0px 0px 0px 0px);
258
+ justify-content: var(--selected-justify-content, flex-start);
259
+ background-color: var(--selected-item-background-color, #f9f9f9);
260
+ white-space: var(--selected-item-white-space, nowrap);
261
+ overflow: var(--selected-item-overflow, hidden);
262
+ text-overflow: var(--selected-item-text-overflow, ellipsis);
263
+ max-width: var(--selected-item-max-widhh, 100%);
264
+ }
265
+
266
+ .selected-content {
267
+ white-space: nowrap;
268
+ overflow: hidden;
269
+ text-overflow: ellipsis;
270
+ max-width: calc(100% - 20px);
234
271
  }
235
272
 
236
273
  .selected:hover {
@@ -243,50 +280,81 @@ onDestroy(() => {
243
280
  background-color: var(--non-selected-item-bgcolor, #ffffff);
244
281
  color: var(--non-selected-item-color);
245
282
  box-shadow: 0px 1px 8px #2f537733;
246
- width: var(--non-selected-width, fit-content);
283
+ width: var(--non-selected-width, 100%);
247
284
  min-width: var(--non-selected-min-width, 100%);
248
- position: absolute;
249
- border-radius: var(--non-selected-border-radius, 4px);
250
- margin: var(--non-selected-margin, 4px 0px 0px 0px);
251
- z-index: 10;
252
285
  word-wrap: var(--non-selected-word-break, break-word);
253
- white-space: var(--non-selected-white-space);
286
+ position: var(--non-selected-items-position, absolute);
287
+ border-radius: var(--non-selected-items-border-radius, 4px);
288
+ margin: var(--non-selected-margin, 4px 0px 0px 0px);
254
289
  font-weight: var(--non-select-font-weight, 500);
255
290
  left: var(--non-selected-left);
256
291
  right: var(--non-selected-right);
257
292
  top: var(--non-selected-top);
258
293
  bottom: var(--non-selected-bottom);
294
+ z-index: 10;
295
+ overflow-y: auto;
259
296
  }
260
297
 
261
298
  ::-webkit-scrollbar {
262
- width: 0;
299
+ width: var(--scrollbar-width, 0);
263
300
  }
264
301
 
265
302
  .item-list {
266
- max-height: var(--non-selected-max-height, 135px);
303
+ max-height: var(--non-selected-max-height, 165px);
267
304
  overflow-y: auto;
268
- position: relative;
269
305
  }
270
306
 
271
307
  .item-selected::after {
272
308
  content: var(--selected-option-icon, '✔');
273
309
  position: absolute;
274
310
  right: 7px;
311
+ color: var(--item-selected-icon-color);
275
312
  }
276
313
 
277
314
  .label-container {
278
315
  font-weight: var(--label-text-weight, 400);
279
316
  font-size: var(--label-text-size, 12px);
280
- color: var(--label-text-color, #000000);
281
- margin-bottom: 4px;
282
- display: inline-block;
317
+ color: var(--label-text-color, #333);
318
+ margin-bottom: var(--label-container-margin-bottom, 4px);
319
+ display: var(--label-container-display, inline-block);
283
320
  }
284
321
 
285
322
  .multipleSelect-btn {
286
323
  display: flex;
287
- width: var(--multipleSelect-btn-width, 100%);
324
+ width: var(--multipleSelect-btn-width, 99%);
288
325
  white-space: var(--multipleSelect-btn-white-space, nowrap);
289
- padding: var(--multipleSelect-btn-padding, 2px);
326
+ padding: var(--multipleSelect-btn-padding, 1px);
327
+ --button-border: var(--multipleSelect-btn-border, 1px solid white);
328
+ --button-font-size: var(--multipleSelect-btn-font-size, 12px);
329
+ --button-width: var(--multipleSelect-btn-width, 100%);
330
+ }
331
+
332
+ .icon-container {
333
+ width: var(--select-icon-container-width, fit-content);
334
+ height: var(--select-icon-container-height, fit-content);
335
+ border-radius: var(--select-icon-container-border-radius);
336
+ opacity: var(--select-icon-container-opacity);
337
+ background: var(--select-icon-container-background);
338
+ display: flex;
339
+ align-items: center;
340
+ justify-content: center;
341
+ margin: var(--select-icon-container-margin, 0px 8px 0px 0px);
342
+ padding: var(--select-icon-container-padding);
343
+ --image-height: var(--select-icon-height);
344
+ --image-width: var(--select-icon-height);
345
+ }
346
+
347
+ .apply-btn-container {
348
+ padding: var(--apply-btn-container-padding, 5px);
349
+ border-top: var(--apply-btn-container-border-top, 1px solid #ddd);
350
+ background-color: var(--apply-btn-container-background-color, #f9f9f9);
351
+ position: var(--apply-btn-container-position, sticky);
352
+ width: var(--apply-btn-container-width, 94%);
353
+ display: var(--apply-btn-display, flex);
354
+ flex-direction: var(--apply-btn-flex-direction, column);
355
+ --button-width: var(--apply-btn-width, 100%);
356
+ --button-padding: var(--apply-btn-padding, 10px);
357
+ --button-font-size: var(--apply-btn-font-size, 14px);
290
358
  }
291
359
 
292
360
  .icon-container {
@@ -12,7 +12,9 @@ declare const __propDef: {
12
12
  } & {
13
13
  [evt: string]: CustomEvent<any>;
14
14
  };
15
- slots: {};
15
+ slots: {
16
+ bottomContent: {};
17
+ };
16
18
  };
17
19
  export type SelectProps = typeof __propDef.props;
18
20
  export type SelectEvents = typeof __propDef.events;
@@ -10,4 +10,5 @@ export type SelectProperties = {
10
10
  hideDropDownIcon?: boolean;
11
11
  dropDownIcon?: string;
12
12
  leftIcon: ImgProps | null;
13
+ showSingleSelectButton?: boolean | null;
13
14
  };
@@ -3,6 +3,10 @@ import { fly } from "svelte/transition";
3
3
  import { defaultToastProperties } from "./properties";
4
4
  export let properties = defaultToastProperties;
5
5
  const dispatch = createEventDispatcher();
6
+ const animationConfig = getAnimationConfig(
7
+ properties.direction,
8
+ properties.overlapPage ?? true
9
+ );
6
10
  let showToast = false;
7
11
  let timeoutId = null;
8
12
  function hideToast() {
@@ -11,6 +15,43 @@ function hideToast() {
11
15
  function handleAnimationEnd() {
12
16
  dispatch("onToastHide");
13
17
  }
18
+ function getAnimationConfig(toastDirection = null, overlapPage) {
19
+ let inX = 0;
20
+ let inY = 0;
21
+ let outX = 0;
22
+ let outY = 0;
23
+ switch (toastDirection) {
24
+ case "left-to-right":
25
+ inX = -1 * (properties.inAnimationOffset ?? 500);
26
+ outX = -1 * (properties.outAnimationOffset ?? 500);
27
+ break;
28
+ case "right-to-left":
29
+ inX = properties.inAnimationOffset ?? 500;
30
+ outX = properties.outAnimationOffset ?? 500;
31
+ break;
32
+ case "bottom-to-top":
33
+ inY = properties.inAnimationOffset ?? (overlapPage ? 500 : 20);
34
+ outY = properties.outAnimationOffset ?? (overlapPage ? 500 : 20);
35
+ break;
36
+ case "top-to-bottom":
37
+ default:
38
+ inY = -1 * (properties.inAnimationOffset ?? (overlapPage ? 500 : 20));
39
+ outY = -1 * (properties.outAnimationOffset ?? (overlapPage ? 100 : 20));
40
+ break;
41
+ }
42
+ return {
43
+ in: {
44
+ x: inX,
45
+ y: inY,
46
+ duration: properties.inAnimationDuration ?? 400
47
+ },
48
+ out: {
49
+ x: outX,
50
+ y: outY,
51
+ duration: properties.outAnimationDuration ?? 800
52
+ }
53
+ };
54
+ }
14
55
  onMount(() => {
15
56
  showToast = true;
16
57
  timeoutId = setTimeout(hideToast, properties.duration);
@@ -25,8 +66,9 @@ onDestroy(() => {
25
66
  {#if showToast}
26
67
  <div
27
68
  class="toast {properties.type ?? ''}"
28
- in:fly={{ x: 500, y: 0, duration: 400 }}
29
- out:fly={{ x: 500, y: 0, duration: 800 }}
69
+ class:no-page-overlap={!(properties?.overlapPage ?? true)}
70
+ in:fly={animationConfig.in}
71
+ out:fly={animationConfig.out}
30
72
  on:outroend={handleAnimationEnd}
31
73
  >
32
74
  {#if properties.leftIcon}
@@ -60,10 +102,16 @@ onDestroy(() => {
60
102
  z-index: var(--toast-z-index, 1000);
61
103
  display: var(--taost-dispay, flex);
62
104
  position: var(--toast-position, absolute);
105
+ top: var(--toast-top, 10px);
63
106
  left: var(--toast-left, 0);
64
107
  right: var(--toast-right, 0);
65
108
  background-color: var(--default-background-color, #87ceeb);
66
109
  }
110
+
111
+ .no-page-overlap {
112
+ position: var(--toast-position, relative);
113
+ }
114
+
67
115
  .toast-icon-wrapper {
68
116
  width: var(--toast-icon-wrapper-width, 20px);
69
117
  height: var(--toast-icon-wrapper-height, 20px);
@@ -1,9 +1,16 @@
1
1
  export type ToastType = 'success' | 'error' | 'info' | 'warn';
2
+ export type ToastDirection = 'left-to-right' | 'right-to-left' | 'top-to-bottom' | 'bottom-to-top';
2
3
  export type ToastProperties = {
3
4
  duration: number;
4
5
  leftIcon?: string;
5
6
  message: string;
6
7
  rightIcon?: string;
7
8
  type?: ToastType;
9
+ direction?: ToastDirection;
10
+ overlapPage?: boolean;
11
+ inAnimationOffset?: number;
12
+ inAnimationDuration?: number;
13
+ outAnimationOffset?: number;
14
+ outAnimationDuration?: number;
8
15
  };
9
16
  export declare const defaultToastProperties: ToastProperties;
package/dist/index.d.ts CHANGED
@@ -30,6 +30,7 @@ export type { InputDataType } from './types';
30
30
  export type { AutoCompleteType } from './types';
31
31
  export type { CustomValidator } from './types';
32
32
  export type { ValidationState } from './types';
33
+ export type { FlyAnimationConfig } from './types';
33
34
  export type { IconProperties } from './Icon/properties';
34
35
  export type { BrandLoaderProperties } from './BrandLoader/properties';
35
36
  export type { StatusProperties } from './Status/properties';
package/dist/types.d.ts CHANGED
@@ -1,3 +1,4 @@
1
+ import type { FlyParams } from 'svelte/transition';
1
2
  /**
2
3
  * @name InputDataType
3
4
  * @description Different types of input data which can be passed to the Input Component
@@ -18,3 +19,10 @@ export type TextTransformer = (text: string) => string;
18
19
  * @description Type Map for All possible output of an Input Filed Validation
19
20
  */
20
21
  export type ValidationState = 'Valid' | 'InProgress' | 'Invalid';
22
+ /**
23
+ * @description Type for animation configuration
24
+ */
25
+ export type FlyAnimationConfig = {
26
+ in: FlyParams;
27
+ out: FlyParams;
28
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@juspay/svelte-ui-components",
3
- "version": "1.7.0",
3
+ "version": "1.9.0",
4
4
  "scripts": {
5
5
  "dev": "vite dev",
6
6
  "build": "vite build && npm run package",