@dvcol/neo-svelte 0.1.2 → 0.1.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 (152) hide show
  1. package/CHANGELOG.md +83 -0
  2. package/README.md +25 -26
  3. package/dist/buttons/NeoButton.svelte +140 -128
  4. package/dist/buttons/NeoButtonGroup.svelte +99 -108
  5. package/dist/buttons/neo-button-group.model.d.ts +18 -19
  6. package/dist/buttons/neo-button.model.d.ts +6 -10
  7. package/dist/cards/NeoCard.svelte +176 -73
  8. package/dist/cards/NeoCard.svelte.d.ts +1 -1
  9. package/dist/cards/neo-card.model.d.ts +29 -1
  10. package/dist/containers/NeoTransitionContainer.svelte +13 -2
  11. package/dist/containers/neo-transition-container.model.d.ts +9 -1
  12. package/dist/divider/NeoDivider.svelte +11 -11
  13. package/dist/icons/IconAccount.svelte +10 -2
  14. package/dist/icons/IconAdd.svelte +10 -2
  15. package/dist/icons/IconAlert.svelte +2 -2
  16. package/dist/icons/IconCalendar.svelte +23 -0
  17. package/dist/icons/IconCalendar.svelte.d.ts +26 -0
  18. package/dist/icons/IconCheckbox.svelte +87 -0
  19. package/dist/icons/IconCheckbox.svelte.d.ts +55 -0
  20. package/dist/icons/IconCircleLoading.svelte +2 -2
  21. package/dist/icons/IconClear.svelte +10 -2
  22. package/dist/icons/IconClose.svelte +2 -2
  23. package/dist/icons/IconConfirm.svelte +2 -2
  24. package/dist/icons/IconDownload.svelte +17 -0
  25. package/dist/icons/IconDownload.svelte.d.ts +26 -0
  26. package/dist/icons/IconEmpty.svelte +2 -2
  27. package/dist/icons/IconFileUpload.svelte +2 -2
  28. package/dist/icons/IconGithub.svelte +2 -2
  29. package/dist/icons/IconImage.svelte +2 -2
  30. package/dist/icons/IconMinus.svelte +2 -2
  31. package/dist/icons/IconMoon.svelte +2 -2
  32. package/dist/icons/IconPaint.svelte +19 -0
  33. package/dist/icons/{IconSunrise.svelte.d.ts → IconPaint.svelte.d.ts} +3 -3
  34. package/dist/icons/IconPencil.svelte +13 -0
  35. package/dist/icons/IconPencil.svelte.d.ts +26 -0
  36. package/dist/icons/IconRadio.svelte +14 -0
  37. package/dist/icons/IconRadio.svelte.d.ts +22 -0
  38. package/dist/icons/IconSave.svelte +1 -1
  39. package/dist/icons/IconSave.svelte.d.ts +3 -3
  40. package/dist/icons/IconSaveOff.svelte +1 -1
  41. package/dist/icons/IconSaveOff.svelte.d.ts +3 -3
  42. package/dist/icons/IconSearch.svelte +2 -2
  43. package/dist/icons/IconSun.svelte +3 -3
  44. package/dist/icons/{IconSunrise.svelte → IconSunFull.svelte} +5 -4
  45. package/dist/icons/IconSunFull.svelte.d.ts +26 -0
  46. package/dist/icons/IconVideo.svelte +2 -2
  47. package/dist/icons/IconWatch.svelte +2 -2
  48. package/dist/icons/IconWatchOff.svelte +2 -2
  49. package/dist/inputs/NeoCheckbox.svelte +316 -0
  50. package/dist/inputs/NeoCheckbox.svelte.d.ts +19 -0
  51. package/dist/inputs/NeoColorPicker.svelte +140 -0
  52. package/dist/inputs/NeoColorPicker.svelte.d.ts +19 -0
  53. package/dist/inputs/NeoDateTime.svelte +96 -0
  54. package/dist/inputs/NeoDateTime.svelte.d.ts +19 -0
  55. package/dist/inputs/NeoFilePicker.svelte +528 -0
  56. package/dist/inputs/NeoFilePicker.svelte.d.ts +19 -0
  57. package/dist/inputs/NeoFilePickerCard.svelte +314 -0
  58. package/dist/inputs/NeoFilePickerCard.svelte.d.ts +19 -0
  59. package/dist/inputs/NeoNumberStep.svelte +174 -0
  60. package/dist/inputs/NeoNumberStep.svelte.d.ts +19 -0
  61. package/dist/inputs/NeoPassword.svelte +86 -17
  62. package/dist/inputs/NeoPassword.svelte.d.ts +19 -16
  63. package/dist/inputs/NeoPin.svelte +589 -0
  64. package/dist/inputs/NeoPin.svelte.d.ts +19 -0
  65. package/dist/inputs/NeoRadio.svelte +254 -0
  66. package/dist/inputs/NeoRadio.svelte.d.ts +19 -0
  67. package/dist/inputs/NeoRange.svelte +518 -0
  68. package/dist/inputs/NeoRange.svelte.d.ts +18 -0
  69. package/dist/inputs/NeoSwitch.svelte +373 -0
  70. package/dist/inputs/NeoSwitch.svelte.d.ts +19 -0
  71. package/dist/inputs/NeoTextarea.svelte +335 -301
  72. package/dist/inputs/NeoTextarea.svelte.d.ts +5 -2
  73. package/dist/inputs/common/NeoAffix.svelte +166 -0
  74. package/dist/inputs/common/NeoAffix.svelte.d.ts +19 -0
  75. package/dist/inputs/common/NeoBaseInput.svelte +338 -0
  76. package/dist/inputs/common/NeoBaseInput.svelte.d.ts +30 -0
  77. package/dist/inputs/common/NeoInput.svelte +684 -0
  78. package/dist/inputs/{NeoInput.svelte.d.ts → common/NeoInput.svelte.d.ts} +2 -10
  79. package/dist/inputs/common/NeoInputValidation.svelte +45 -0
  80. package/dist/inputs/common/NeoInputValidation.svelte.d.ts +22 -0
  81. package/dist/inputs/common/NeoLabel.svelte +93 -0
  82. package/dist/inputs/common/NeoLabel.svelte.d.ts +19 -0
  83. package/dist/inputs/{NeoValidation.svelte → common/NeoValidation.svelte} +9 -16
  84. package/dist/inputs/common/NeoValidation.svelte.d.ts +22 -0
  85. package/dist/inputs/common/neo-affix.model.d.ts +32 -0
  86. package/dist/inputs/common/neo-input-validation.model.d.ts +20 -0
  87. package/dist/inputs/common/neo-input-validation.model.js +1 -0
  88. package/dist/inputs/{neo-input.model.d.ts → common/neo-input.model.d.ts} +148 -68
  89. package/dist/inputs/common/neo-label.model.d.ts +36 -0
  90. package/dist/inputs/common/neo-label.model.js +1 -0
  91. package/dist/inputs/common/neo-validation.model.d.ts +70 -0
  92. package/dist/inputs/common/neo-validation.model.js +1 -0
  93. package/dist/inputs/index.d.ts +2 -2
  94. package/dist/inputs/index.js +1 -1
  95. package/dist/inputs/neo-checkbox.model.d.ts +9 -0
  96. package/dist/inputs/neo-checkbox.model.js +1 -0
  97. package/dist/inputs/neo-color-picker.model.d.ts +17 -0
  98. package/dist/inputs/neo-color-picker.model.js +1 -0
  99. package/dist/inputs/neo-date-time.model.d.ts +8 -0
  100. package/dist/inputs/neo-date-time.model.js +1 -0
  101. package/dist/inputs/neo-file-picker.model.d.ts +138 -0
  102. package/dist/inputs/neo-file-picker.model.js +1 -0
  103. package/dist/inputs/neo-number-step.model.d.ts +24 -0
  104. package/dist/inputs/neo-number-step.model.js +1 -0
  105. package/dist/inputs/neo-password.model.d.ts +13 -0
  106. package/dist/inputs/neo-password.model.js +1 -0
  107. package/dist/inputs/neo-pin.model.d.ts +47 -0
  108. package/dist/inputs/neo-pin.model.js +1 -0
  109. package/dist/inputs/neo-radio.model.d.ts +3 -0
  110. package/dist/inputs/neo-radio.model.js +1 -0
  111. package/dist/inputs/neo-switch.model.d.ts +9 -0
  112. package/dist/inputs/neo-switch.model.js +1 -0
  113. package/dist/nav/NeoTab.svelte +29 -25
  114. package/dist/nav/NeoTabPanel.svelte +1 -1
  115. package/dist/nav/NeoTabs.svelte +51 -44
  116. package/dist/nav/NeoTabsCard.svelte +8 -10
  117. package/dist/nav/neo-tabs-context.svelte.d.ts +2 -11
  118. package/dist/nav/neo-tabs-context.svelte.js +1 -41
  119. package/dist/nav/neo-tabs.model.d.ts +6 -0
  120. package/dist/providers/NeoThemeProvider.svelte +417 -305
  121. package/dist/providers/NeoThemeSelector.svelte +10 -10
  122. package/dist/providers/neo-theme-provider-context.svelte.js +16 -15
  123. package/dist/providers/neo-theme-provider.model.d.ts +6 -6
  124. package/dist/providers/neo-theme-provider.model.js +17 -12
  125. package/dist/providers/neo-theme-selector.model.d.ts +2 -2
  126. package/dist/skeletons/NeoSkeletonMedia.svelte +4 -4
  127. package/dist/skeletons/NeoSkeletonText.svelte +12 -12
  128. package/dist/styles/common/colors.scss +85 -97
  129. package/dist/styles/common/filters.scss +17 -0
  130. package/dist/styles/common/shadows.scss +531 -293
  131. package/dist/styles/common/spacing.scss +7 -3
  132. package/dist/styles/common/typography.scss +1 -1
  133. package/dist/styles/common/utils.scss +1 -1
  134. package/dist/styles/common/z-index.scss +1 -1
  135. package/dist/styles/mixin.scss +80 -27
  136. package/dist/styles/reset.scss +8 -1
  137. package/dist/styles/theme.scss +39 -16
  138. package/dist/utils/html-element.utils.d.ts +3 -0
  139. package/dist/utils/regex.utils.d.ts +3 -0
  140. package/dist/utils/regex.utils.js +3 -0
  141. package/dist/utils/shadow.utils.d.ts +30 -3
  142. package/dist/utils/shadow.utils.js +41 -14
  143. package/dist/utils/transition.utils.d.ts +4 -0
  144. package/dist/utils/transition.utils.js +10 -1
  145. package/dist/utils/utils.svelte.d.ts +6 -0
  146. package/dist/utils/utils.svelte.js +13 -0
  147. package/package.json +13 -12
  148. package/dist/inputs/NeoInput.svelte +0 -750
  149. package/dist/inputs/NeoValidation.svelte.d.ts +0 -22
  150. package/dist/inputs/neo-validation.model.d.ts +0 -40
  151. /package/dist/inputs/{neo-validation.model.js → common/neo-affix.model.js} +0 -0
  152. /package/dist/inputs/{neo-input.model.js → common/neo-input.model.js} +0 -0
@@ -0,0 +1,314 @@
1
+ <script lang="ts">
2
+ import { flip } from 'svelte/animate';
3
+ import { fade } from 'svelte/transition';
4
+
5
+ import type { NeoFilePickerCardProps } from './neo-file-picker.model.js';
6
+
7
+ import NeoButton from '../buttons/NeoButton.svelte';
8
+ import NeoCard from '../cards/NeoCard.svelte';
9
+ import IconAdd from '../icons/IconAdd.svelte';
10
+ import IconCircleLoading from '../icons/IconCircleLoading.svelte';
11
+ import IconClear from '../icons/IconClear.svelte';
12
+ import IconDownload from '../icons/IconDownload.svelte';
13
+ import IconPencil from '../icons/IconPencil.svelte';
14
+ import NeoAffix from './common/NeoAffix.svelte';
15
+ import NeoLabel from './common/NeoLabel.svelte';
16
+ import { enterDefaultTransition, leaveDefaultFadeTransition } from '../utils/transition.utils.js';
17
+
18
+ /* eslint-disable prefer-const -- necessary for binding checked */
19
+ let {
20
+ // Snippets
21
+ children,
22
+ label,
23
+
24
+ // States
25
+ ref = $bindable(),
26
+ hovered = $bindable(false),
27
+ focused = $bindable(false),
28
+
29
+ files,
30
+ valid,
31
+ clearable,
32
+ dragging,
33
+ multiple,
34
+ append,
35
+ placeholder,
36
+ dropText = placeholder,
37
+ detailText,
38
+
39
+ required,
40
+ loading,
41
+ rounded,
42
+ disabled,
43
+ skeleton,
44
+
45
+ // Style
46
+ maxHeight = '20rem',
47
+
48
+ // Events
49
+ onClear,
50
+ onRemove,
51
+ onEdit,
52
+
53
+ // Other props
54
+ labelRef = $bindable(),
55
+ labelProps,
56
+ addButtonProps,
57
+ editButtonProps,
58
+ removeButtonProps,
59
+
60
+ ...rest
61
+ }: NeoFilePickerCardProps = $props();
62
+ /* eslint-enable prefer-const */
63
+
64
+ const detail = $derived(detailText || `${files?.length ?? 0} file${files?.length !== 1 ? 's' : ''}`);
65
+
66
+ const close = $derived(clearable && !!files?.length && (hovered || focused));
67
+ </script>
68
+
69
+ {#snippet labelGroup()}
70
+ <div class="neo-expanded-count" class:neo-label={label}>
71
+ <NeoLabel bind:ref={labelRef} {label} {disabled} onclick={e => e.preventDefault()} {...labelProps}>
72
+ <span class="neo-expanded-detail">{detail}</span>
73
+ </NeoLabel>
74
+
75
+ <NeoAffix
76
+ {loading}
77
+ {valid}
78
+ {close}
79
+ {skeleton}
80
+ {disabled}
81
+ size="1.375rem"
82
+ closeProps={{
83
+ onclick: onClear,
84
+ }}
85
+ />
86
+ </div>
87
+ {/snippet}
88
+
89
+ <NeoCard
90
+ bind:ref
91
+ bind:hovered
92
+ bind:focused
93
+ {rounded}
94
+ {disabled}
95
+ {skeleton}
96
+ out={leaveDefaultFadeTransition}
97
+ flex="1 1 auto"
98
+ {...rest}
99
+ class={['neo-file-picker-card', rest?.class]}
100
+ >
101
+ {#if children}
102
+ {@render children({
103
+ dragging,
104
+ multiple,
105
+ append,
106
+ files,
107
+ })}
108
+ {:else if files?.length}
109
+ {@render labelGroup()}
110
+ <div class="neo-expanded-list" class:neo-rounded={rounded} style:--neo-file-picker-card-max-height={maxHeight}>
111
+ <div class="neo-expanded-scroll">
112
+ {#each files as file, i (file)}
113
+ <div class="neo-file" transition:fade={{ duration: 200 }} animate:flip={{ duration: 200, delay: 100 }}>
114
+ <span class="neo-file-name" title={file.name}>{file.name}</span>
115
+ {#if clearable}
116
+ <span class="neo-file-remove">
117
+ <NeoButton
118
+ text
119
+ rounded
120
+ {disabled}
121
+ onclickcapture={e => onRemove?.(i, e)}
122
+ title="Remove file"
123
+ aria-label="Remove file"
124
+ {...removeButtonProps}
125
+ class={['neo-file-remove-button', removeButtonProps?.class]}
126
+ >
127
+ {#snippet icon()}
128
+ <IconClear width="1rem" height="1rem" scale="1.5" stroke="1" />
129
+ {/snippet}
130
+ </NeoButton>
131
+ </span>
132
+ {/if}
133
+ </div>
134
+ {/each}
135
+ </div>
136
+ </div>
137
+ <div class="neo-expanded-edit">
138
+ <span>{placeholder}</span>
139
+ <NeoButton {disabled} rounded text onclick={onEdit} title="Edit files" aria-label="Edit files" {...editButtonProps}>
140
+ {#snippet icon()}
141
+ <IconPencil width="1.25rem" height="1.25rem" scale="1" />
142
+ {/snippet}
143
+ </NeoButton>
144
+ </div>
145
+ {:else}
146
+ {#if label}
147
+ {@render labelGroup()}
148
+ {/if}
149
+ <div
150
+ role="none"
151
+ class="neo-expanded-empty"
152
+ class:neo-dragging={dragging}
153
+ class:neo-rounded={rounded}
154
+ class:neo-disabled={disabled}
155
+ class:neo-label={label}
156
+ onclick={onEdit}
157
+ in:fade={enterDefaultTransition}
158
+ >
159
+ <div class="neo-expanded-button">
160
+ <NeoButton aria-label="Add files" title="Add files" text rounded {skeleton} {disabled} onclick={onEdit} {...addButtonProps}>
161
+ {#snippet icon()}
162
+ {#if dragging}
163
+ <IconDownload width="2.5rem" height="2.5rem" scale="1.25" stroke="0.5" />
164
+ {:else if loading}
165
+ <IconCircleLoading width="2.5rem" height="2.5rem" scale="1" />
166
+ {:else}
167
+ <IconAdd width="2.5rem" height="2.5rem" scale="1" stroke="0.5" />
168
+ {/if}
169
+ {/snippet}
170
+ </NeoButton>
171
+ </div>
172
+ <div class="neo-expanded-placeholder" style:min-width="max({dropText?.length ?? 0}ch,{placeholder?.length ?? 0}ch)">
173
+ {#if dragging}
174
+ <span class="neo-expanded-placeholder-drop">{dropText}</span>
175
+ {:else}
176
+ <span class="neo-expanded-placeholder-select">{placeholder}</span>
177
+ {/if}
178
+ </div>
179
+ </div>
180
+ {/if}
181
+ </NeoCard>
182
+
183
+ <style>.neo-expanded-placeholder, .neo-expanded-button {
184
+ align-self: center;
185
+ width: fit-content;
186
+ }
187
+ .neo-expanded-placeholder {
188
+ text-align: center;
189
+ }
190
+ .neo-expanded-empty, .neo-expanded-scroll {
191
+ min-width: var(--neo-file-picker-card-min-width);
192
+ }
193
+ .neo-expanded-empty {
194
+ position: relative;
195
+ display: inline-flex;
196
+ flex-direction: column;
197
+ align-items: center;
198
+ justify-content: center;
199
+ box-sizing: border-box;
200
+ width: 100%;
201
+ height: 100%;
202
+ padding: 1rem;
203
+ cursor: pointer;
204
+ transition: color 0.3s ease;
205
+ }
206
+ .neo-expanded-empty::before {
207
+ position: absolute;
208
+ margin: -0.5rem;
209
+ border: var(--neo-border-width) dashed var(--neo-grey-soft);
210
+ border-radius: var(--neo-border-radius);
211
+ transition: margin 0.3s ease;
212
+ content: "";
213
+ inset: 0;
214
+ }
215
+ .neo-expanded-empty.neo-rounded::before {
216
+ border-radius: var(--neo-border-radius-md);
217
+ }
218
+ .neo-expanded-empty.neo-disabled {
219
+ cursor: no-drop;
220
+ }
221
+ .neo-expanded-empty.neo-dragging::before {
222
+ margin: -0.25rem;
223
+ }
224
+ .neo-expanded-empty.neo-label {
225
+ margin-top: 0.25rem;
226
+ }
227
+ .neo-expanded-edit, .neo-expanded-count {
228
+ display: inline-flex;
229
+ align-items: center;
230
+ justify-content: space-between;
231
+ }
232
+ .neo-expanded-edit {
233
+ margin-top: 0.25rem;
234
+ }
235
+ .neo-expanded-count {
236
+ --neo-label-margin: 0;
237
+ --neo-label-padding: 0;
238
+ }
239
+ .neo-expanded-count.neo-label {
240
+ margin-bottom: 0.5rem;
241
+ }
242
+ .neo-expanded-count.neo-label .neo-expanded-detail {
243
+ color: var(--neo-text-color-secondary);
244
+ font-size: var(--neo-font-size-sm);
245
+ line-height: var(--neo-line-height-sm);
246
+ }
247
+ .neo-expanded-list {
248
+ display: inline-flex;
249
+ flex: 1 1 auto;
250
+ margin: 0 var(--neo-shadow-margin, 0.625rem);
251
+ padding: 0 0.5rem;
252
+ border-radius: var(--neo-border-radius);
253
+ box-shadow: var(--neo-box-shadow-inset-1);
254
+ }
255
+ .neo-expanded-list.neo-rounded {
256
+ border-radius: var(--neo-border-radius-md);
257
+ }
258
+ .neo-expanded-list .neo-file {
259
+ display: inline-flex;
260
+ align-items: center;
261
+ justify-content: space-between;
262
+ transition: color 0.1s ease;
263
+ }
264
+ .neo-expanded-list .neo-file-name {
265
+ display: -webkit-box;
266
+ overflow: hidden;
267
+ -webkit-line-clamp: 2;
268
+ line-clamp: 2;
269
+ -webkit-box-orient: vertical;
270
+ }
271
+ .neo-expanded-list .neo-file-remove {
272
+ flex: 0 0 auto;
273
+ }
274
+ .neo-expanded-list .neo-file:hover {
275
+ color: var(--neo-text-color-highlight);
276
+ }
277
+ .neo-expanded-scroll {
278
+ --neo-scrollbar-button-height: 0.375rem;
279
+ position: relative;
280
+ display: inline-flex;
281
+ flex: 1 1 auto;
282
+ flex-direction: column;
283
+ gap: var(--neo-gap-xxs);
284
+ max-height: var(--neo-file-picker-card-max-height);
285
+ padding: 0.625rem 0.25rem;
286
+ overflow: auto;
287
+ mask-image: linear-gradient(to top, transparent, transparent 1rem, black 1rem, black calc(100% - 1rem), transparent), linear-gradient(to bottom, transparent, transparent 1rem, black 1rem, black calc(100% - 1rem), transparent);
288
+ scrollbar-gutter: stable both-edges;
289
+ }
290
+ .neo-expanded-scroll::-webkit-scrollbar {
291
+ width: var(--neo-scrollbar-width, 0.375rem);
292
+ background-color: transparent;
293
+ border: none;
294
+ cursor: pointer;
295
+ }
296
+ .neo-expanded-scroll::-webkit-scrollbar-button {
297
+ height: var(--neo-scrollbar-button-height, 2px);
298
+ }
299
+ .neo-expanded-scroll::-webkit-scrollbar-thumb {
300
+ background-color: var(--neo-scrollbar-color);
301
+ border: none;
302
+ border-radius: var(--neo-border-radius);
303
+ cursor: pointer;
304
+ }
305
+ .neo-expanded-scroll::-webkit-scrollbar-corner {
306
+ background-color: transparent;
307
+ background-clip: border-box;
308
+ border: none;
309
+ outline: none;
310
+ }
311
+ .neo-expanded-scroll::-webkit-resizer {
312
+ background: url("../assets/neo-icon-resizer-bottom-right.svg") no-repeat bottom;
313
+ background-clip: border-box;
314
+ }</style>
@@ -0,0 +1,19 @@
1
+ import type { NeoFilePickerCardProps } from './neo-file-picker.model.js';
2
+ interface $$__sveltets_2_IsomorphicComponent<Props extends Record<string, any> = any, Events extends Record<string, any> = any, Slots extends Record<string, any> = any, Exports = {}, Bindings = string> {
3
+ new (options: import('svelte').ComponentConstructorOptions<Props>): import('svelte').SvelteComponent<Props, Events, Slots> & {
4
+ $$bindings?: Bindings;
5
+ } & Exports;
6
+ (internal: unknown, props: Props & {
7
+ $$events?: Events;
8
+ $$slots?: Slots;
9
+ }): Exports & {
10
+ $set?: any;
11
+ $on?: any;
12
+ };
13
+ z_$$bindings?: Bindings;
14
+ }
15
+ declare const NeoFilePickerCard: $$__sveltets_2_IsomorphicComponent<NeoFilePickerCardProps, {
16
+ [evt: string]: CustomEvent<any>;
17
+ }, {}, {}, "ref" | "hovered" | "focused" | "labelRef">;
18
+ type NeoFilePickerCard = InstanceType<typeof NeoFilePickerCard>;
19
+ export default NeoFilePickerCard;
@@ -0,0 +1,174 @@
1
+ <script lang="ts">
2
+ import type { FocusEventHandler } from 'svelte/elements';
3
+ import type { NeoButtonProps } from '../buttons/neo-button.model.js';
4
+ import type { NeoNumberStepProps } from './neo-number-step.model.js';
5
+
6
+ import NeoButton from '../buttons/NeoButton.svelte';
7
+ import IconAdd from '../icons/IconAdd.svelte';
8
+ import IconMinus from '../icons/IconMinus.svelte';
9
+ import NeoInput from './common/NeoInput.svelte';
10
+ import { toTransition, toTransitionProps } from '../utils/action.utils.js';
11
+ import { computeButtonShadows, DefaultShadowElevation } from '../utils/shadow.utils.js';
12
+
13
+ /* eslint-disable prefer-const -- necessary for binding checked */
14
+ let {
15
+ // Snippets
16
+ label,
17
+
18
+ // State
19
+ defaultValue = 0,
20
+ ref = $bindable(),
21
+ value = $bindable(defaultValue),
22
+ valid = $bindable(),
23
+ dirty = $bindable(false),
24
+ touched = $bindable(false),
25
+ hovered = $bindable(false),
26
+ focused = $bindable(false),
27
+ type = 'number',
28
+ placeholder = '0',
29
+ center = !label,
30
+
31
+ // Transition
32
+ in: inAction,
33
+ out: outAction,
34
+ transition: transitionAction,
35
+
36
+ // Events
37
+ onStepUp,
38
+ onStepDown,
39
+
40
+ // Other props
41
+ labelRef = $bindable(),
42
+ buttonProps,
43
+ groupProps,
44
+ containerTag = 'div',
45
+ containerProps,
46
+ ...rest
47
+ }: NeoNumberStepProps = $props();
48
+ /* eslint-enable prefer-const */
49
+
50
+ const increment = (e: MouseEvent) => {
51
+ if (!ref || ref?.disabled) return;
52
+ ref.stepUp();
53
+ ref.dispatchEvent(
54
+ new InputEvent('input', {
55
+ bubbles: true,
56
+ cancelable: false,
57
+ data: ref?.valueAsNumber?.toString(),
58
+ inputType: 'stepUp',
59
+ }),
60
+ );
61
+ onStepUp?.(e, ref.valueAsNumber, ref.step);
62
+ };
63
+
64
+ const decrement = (e: MouseEvent) => {
65
+ if (!ref || ref?.disabled) return;
66
+ ref.stepDown();
67
+ ref.dispatchEvent(
68
+ new InputEvent('input', {
69
+ bubbles: true,
70
+ cancelable: false,
71
+ data: ref?.valueAsNumber?.toString(),
72
+ inputType: 'stepDown',
73
+ }),
74
+ );
75
+ onStepDown?.(e, ref.valueAsNumber, ref.step);
76
+ };
77
+
78
+ const elevation = $derived(rest?.elevation ?? DefaultShadowElevation);
79
+ const text = $derived(elevation >= 0 || !rest.pressed);
80
+ const style = $derived(computeButtonShadows(elevation, text));
81
+ const buttonsProps = $derived<NeoButtonProps>({
82
+ skeleton: rest.skeleton,
83
+ disabled: rest.disabled,
84
+ rounded: rest.rounded,
85
+ glass: rest.glass,
86
+ start: rest.start,
87
+ text,
88
+ style,
89
+ ...buttonProps,
90
+ });
91
+
92
+ let timeout: ReturnType<typeof setTimeout>;
93
+ const onFocusIn: FocusEventHandler<HTMLDivElement> = e => {
94
+ clearTimeout(timeout);
95
+ containerProps?.onfocusin?.(e);
96
+ };
97
+ const onFocusOut: FocusEventHandler<HTMLDivElement> = e => {
98
+ timeout = setTimeout(() => {
99
+ ref?.validate?.();
100
+ containerProps?.onfocusout?.(e);
101
+ }, 0);
102
+ };
103
+
104
+ const affix = $derived(rest.clearable || rest.loading !== undefined || rest.validation);
105
+
106
+ const inFn = $derived(toTransition(inAction ?? transitionAction));
107
+ const inProps = $derived(toTransitionProps(inAction ?? transitionAction));
108
+ const outFn = $derived(toTransition(outAction ?? transitionAction));
109
+ const outProps = $derived(toTransitionProps(outAction ?? transitionAction));
110
+ </script>
111
+
112
+ {#snippet before()}
113
+ <NeoButton aria-label="Decrement number" title="Decrement number" onclick={decrement} {...buttonsProps}>
114
+ {#snippet icon()}
115
+ <IconMinus width="1.25rem" height="1.25rem" />
116
+ {/snippet}
117
+ </NeoButton>
118
+ {/snippet}
119
+
120
+ {#snippet after()}
121
+ <NeoButton aria-label="Increment number" title="Increment number" onclick={increment} {...buttonsProps}>
122
+ {#snippet icon()}
123
+ <IconAdd width="1.25rem" height="1.25rem" />
124
+ {/snippet}
125
+ </NeoButton>
126
+ {/snippet}
127
+
128
+ <svelte:element
129
+ this={containerTag}
130
+ class:neo-number-step={true}
131
+ class:neo-label={label}
132
+ class:neo-center={center}
133
+ class:neo-affix={affix}
134
+ out:outFn={outProps}
135
+ in:inFn={inProps}
136
+ {...containerProps}
137
+ onfocusin={onFocusIn}
138
+ onfocusout={onFocusOut}
139
+ >
140
+ <NeoInput
141
+ bind:ref
142
+ bind:labelRef
143
+ bind:value
144
+ bind:valid
145
+ bind:dirty
146
+ bind:touched
147
+ bind:hovered
148
+ bind:focused
149
+ {type}
150
+ {placeholder}
151
+ {before}
152
+ {after}
153
+ {label}
154
+ {defaultValue}
155
+ containerProps={groupProps}
156
+ {...rest}
157
+ />
158
+ </svelte:element>
159
+
160
+ <style>.neo-number-step :global(.neo-input[type="number"]) {
161
+ /* Hide arrows -Firefox */
162
+ appearance: textfield;
163
+ /* Hide arrows - Chrome, Safari, Edge, Opera */
164
+ }
165
+ .neo-number-step :global(.neo-input[type="number"])::-webkit-outer-spin-button, .neo-number-step :global(.neo-input[type="number"])::-webkit-inner-spin-button {
166
+ margin: 0;
167
+ appearance: none;
168
+ }
169
+ .neo-number-step.neo-center :global(.neo-input) {
170
+ text-align: center;
171
+ }
172
+ .neo-number-step.neo-center.neo-affix :global(.neo-input-before) {
173
+ margin-right: 1.75rem;
174
+ }</style>
@@ -0,0 +1,19 @@
1
+ import type { NeoNumberStepProps } from './neo-number-step.model.js';
2
+ interface $$__sveltets_2_IsomorphicComponent<Props extends Record<string, any> = any, Events extends Record<string, any> = any, Slots extends Record<string, any> = any, Exports = {}, Bindings = string> {
3
+ new (options: import('svelte').ComponentConstructorOptions<Props>): import('svelte').SvelteComponent<Props, Events, Slots> & {
4
+ $$bindings?: Bindings;
5
+ } & Exports;
6
+ (internal: unknown, props: Props & {
7
+ $$events?: Events;
8
+ $$slots?: Slots;
9
+ }): Exports & {
10
+ $set?: any;
11
+ $on?: any;
12
+ };
13
+ z_$$bindings?: Bindings;
14
+ }
15
+ declare const NeoNumberStep: $$__sveltets_2_IsomorphicComponent<NeoNumberStepProps, {
16
+ [evt: string]: CustomEvent<any>;
17
+ }, {}, {}, "value" | "ref" | "hovered" | "focused" | "touched" | "dirty" | "valid" | "labelRef">;
18
+ type NeoNumberStep = InstanceType<typeof NeoNumberStep>;
19
+ export default NeoNumberStep;
@@ -1,31 +1,100 @@
1
- <script lang="ts">
2
- import type { NeoInputProps } from './neo-input.model.js';
1
+ <script lang="ts" generics="T extends boolean = false">
2
+ import type { NeoButtonProps } from '../buttons/index.js';
3
+ import type { NeoPasswordProps } from './neo-password.model.js';
3
4
 
5
+ import NeoButton from '../buttons/NeoButton.svelte';
4
6
  import IconWatch from '../icons/IconWatch.svelte';
5
7
  import IconWatchOff from '../icons/IconWatchOff.svelte';
6
- import NeoInput from './NeoInput.svelte';
8
+ import NeoPin from './NeoPin.svelte';
9
+ import NeoInput from './common/NeoInput.svelte';
10
+ import { computeButtonShadows, getDefaultElevation } from '../utils/shadow.utils.js';
7
11
 
8
- const { type = 'password', placeholder = 'Enter your password', ...rest }: NeoInputProps = $props();
12
+ /* eslint-disable prefer-const -- necessary for binding checked */
13
+ let {
14
+ // Styles
15
+ pin,
16
+
17
+ // State
18
+ ref = $bindable(),
19
+ value = $bindable(),
20
+ valid = $bindable(),
21
+ dirty = $bindable(false),
22
+ touched = $bindable(false),
23
+ hovered = $bindable(false),
24
+ focused = $bindable(false),
25
+ type = 'password',
26
+ placeholder = pin ? undefined : 'Enter your password',
27
+
28
+ // Other props
29
+ labelRef = $bindable(),
30
+ buttonProps,
31
+ ...rest
32
+ }: NeoPasswordProps<T> = $props();
33
+ /* eslint-enable prefer-const */
9
34
 
10
35
  let show = $state(false);
11
- const toggle = () => {
12
- show = !show;
13
- };
14
36
 
15
37
  const _type = $derived(show ? 'text' : type);
16
- const _suffixProps = $derived({
17
- onclick: toggle,
38
+
39
+ const elevation = $derived(rest?.elevation ?? getDefaultElevation(rest?.pressed));
40
+ const text = $derived(elevation >= 0 || !rest.pressed || pin);
41
+ const style = $derived(computeButtonShadows(elevation, text));
42
+ const afterProps = $derived<NeoButtonProps>({
18
43
  'aria-label': 'Toggle password visibility',
19
- ...rest.suffixProps,
44
+ title: 'Toggle password visibility',
45
+ skeleton: rest.skeleton,
46
+ disabled: rest.disabled,
47
+ rounded: rest.rounded,
48
+ glass: rest.glass,
49
+ start: rest.start,
50
+ text,
51
+ style,
52
+ ...buttonProps,
53
+ toggle: true,
54
+ class: ['neo-password-toggle', buttonProps?.class],
20
55
  });
21
56
  </script>
22
57
 
23
- {#snippet suffix()}
24
- {#if show}
25
- <IconWatch width="1.75rem" height="1.75rem" />
26
- {:else}
27
- <IconWatchOff width="1.75rem" height="1.75rem" />
28
- {/if}
58
+ {#snippet after()}
59
+ <NeoButton bind:checked={show} {...afterProps}>
60
+ {#snippet icon()}
61
+ {#if show}
62
+ <IconWatchOff width="1.25rem" height="1.25rem" scale="var(--neo-input-icon-scale, 1.125)" />
63
+ {:else}
64
+ <IconWatch width="1.25rem" height="1.25rem" scale="var(--neo-input-icon-scale, 1.125)" />
65
+ {/if}
66
+ {/snippet}
67
+ </NeoButton>
29
68
  {/snippet}
30
69
 
31
- <NeoInput type={_type} {placeholder} {suffix} suffixProps={_suffixProps} {...rest} />
70
+ {#if pin}
71
+ <NeoPin
72
+ bind:ref
73
+ bind:labelRef
74
+ bind:value
75
+ bind:valid
76
+ bind:dirty
77
+ bind:touched
78
+ bind:hovered
79
+ bind:focused
80
+ type={_type}
81
+ {placeholder}
82
+ {after}
83
+ {...rest}
84
+ />
85
+ {:else}
86
+ <NeoInput
87
+ bind:ref
88
+ bind:labelRef
89
+ bind:value
90
+ bind:valid
91
+ bind:dirty
92
+ bind:touched
93
+ bind:hovered
94
+ bind:focused
95
+ type={_type}
96
+ {placeholder}
97
+ {after}
98
+ {...rest}
99
+ />
100
+ {/if}
@@ -1,19 +1,22 @@
1
- import type { NeoInputProps } from './neo-input.model.js';
2
- interface $$__sveltets_2_IsomorphicComponent<Props extends Record<string, any> = any, Events extends Record<string, any> = any, Slots extends Record<string, any> = any, Exports = {}, Bindings = string> {
3
- new (options: import('svelte').ComponentConstructorOptions<Props>): import('svelte').SvelteComponent<Props, Events, Slots> & {
4
- $$bindings?: Bindings;
5
- } & Exports;
6
- (internal: unknown, props: Props & {
7
- $$events?: Events;
8
- $$slots?: Slots;
9
- }): Exports & {
10
- $set?: any;
11
- $on?: any;
1
+ import type { NeoPasswordProps } from './neo-password.model.js';
2
+ declare class __sveltets_Render<T extends boolean = false> {
3
+ props(): NeoPasswordProps<T>;
4
+ events(): {} & {
5
+ [evt: string]: CustomEvent<any>;
12
6
  };
13
- z_$$bindings?: Bindings;
7
+ slots(): {};
8
+ bindings(): "value" | "ref" | "hovered" | "focused" | "touched" | "dirty" | "valid" | "labelRef";
9
+ exports(): {};
14
10
  }
15
- declare const NeoPassword: $$__sveltets_2_IsomorphicComponent<NeoInputProps, {
16
- [evt: string]: CustomEvent<any>;
17
- }, {}, {}, "">;
18
- type NeoPassword = InstanceType<typeof NeoPassword>;
11
+ interface $$IsomorphicComponent {
12
+ new <T extends boolean = false>(options: import('svelte').ComponentConstructorOptions<ReturnType<__sveltets_Render<T>['props']>>): import('svelte').SvelteComponent<ReturnType<__sveltets_Render<T>['props']>, ReturnType<__sveltets_Render<T>['events']>, ReturnType<__sveltets_Render<T>['slots']>> & {
13
+ $$bindings?: ReturnType<__sveltets_Render<T>['bindings']>;
14
+ } & ReturnType<__sveltets_Render<T>['exports']>;
15
+ <T extends boolean = false>(internal: unknown, props: ReturnType<__sveltets_Render<T>['props']> & {
16
+ $$events?: ReturnType<__sveltets_Render<T>['events']>;
17
+ }): ReturnType<__sveltets_Render<T>['exports']>;
18
+ z_$$bindings?: ReturnType<__sveltets_Render<any>['bindings']>;
19
+ }
20
+ declare const NeoPassword: $$IsomorphicComponent;
21
+ type NeoPassword<T extends boolean = false> = InstanceType<typeof NeoPassword<T>>;
19
22
  export default NeoPassword;