@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,528 @@
1
+ <script lang="ts">
2
+ import { tick } from 'svelte';
3
+
4
+ import type { DragEventHandler, FormEventHandler, MouseEventHandler } from 'svelte/elements';
5
+ import type { NeoButtonProps } from '../buttons/neo-button.model.js';
6
+ import type { NeoInputContext, NeoInputHTMLElement } from './common/neo-input.model.js';
7
+ import type { NeoFilePickerProps } from './neo-file-picker.model.js';
8
+ import type { SvelteEvent } from '../utils/html-element.utils.js';
9
+
10
+ import NeoButton from '../buttons/NeoButton.svelte';
11
+ import IconDownload from '../icons/IconDownload.svelte';
12
+ import IconFileUpload from '../icons/IconFileUpload.svelte';
13
+ import NeoFilePickerCard from './NeoFilePickerCard.svelte';
14
+ import NeoBaseInput from './common/NeoBaseInput.svelte';
15
+ import NeoInput from './common/NeoInput.svelte';
16
+ import NeoInputValidation from './common/NeoInputValidation.svelte';
17
+ import { computeButtonShadows, getDefaultElevation, getDefaultHoverElevation } from '../utils/shadow.utils.js';
18
+
19
+ /* eslint-disable prefer-const -- necessary for binding checked */
20
+ let {
21
+ // Snippets
22
+ children,
23
+ label,
24
+ error,
25
+ message,
26
+ after,
27
+ before,
28
+
29
+ // States
30
+ id = label ? `neo-file-picker-${crypto.randomUUID()}` : undefined,
31
+ ref = $bindable(),
32
+ files = $bindable(),
33
+ value = $bindable(),
34
+ valid = $bindable(),
35
+ dirty = $bindable(false),
36
+ touched = $bindable(false),
37
+ hovered = $bindable(false),
38
+ focused = $bindable(false),
39
+ placeholder = 'Choose a file',
40
+
41
+ loading,
42
+ clearable,
43
+ validation,
44
+ skeleton,
45
+ disabled,
46
+ readonly,
47
+ rounded,
48
+ pressed,
49
+
50
+ elevation = getDefaultElevation(pressed),
51
+ hover = getDefaultHoverElevation(pressed),
52
+
53
+ // File picker
54
+ append,
55
+ multiple,
56
+ expanded = $bindable(false),
57
+ dragging = $bindable(false),
58
+ drop = true,
59
+ dropText = `Drop${multiple ? ' ' : ' a '}File${multiple ? 's' : ''} here`,
60
+ expandText,
61
+ expandHeight,
62
+
63
+ // Events
64
+ oninput,
65
+ onchange,
66
+
67
+ // Actions
68
+ in: inAction,
69
+ out: outAction,
70
+ transition: transitionAction,
71
+
72
+ // Other props
73
+ labelRef = $bindable(),
74
+ labelProps,
75
+ cardProps,
76
+ buttonProps,
77
+ groupProps,
78
+ messageTag = 'div',
79
+ messageProps,
80
+ containerTag = 'div',
81
+ containerProps,
82
+ wrapperTag = 'div',
83
+ wrapperProps,
84
+ ...rest
85
+ }: NeoFilePickerProps = $props();
86
+ /* eslint-enable prefer-const */
87
+
88
+ const text = $derived(elevation >= 0 || !pressed);
89
+ const style = $derived(computeButtonShadows(elevation, text));
90
+ const isDragging = $derived(drop && dragging && !disabled);
91
+
92
+ let dragRef = $state<HTMLDivElement>();
93
+ let dragWith = $state<string | number>();
94
+ let dragHeight = $state<string | number>();
95
+
96
+ let overlayRef = $state<HTMLDivElement>();
97
+ let contentMargin = $state<{ top?: string | number; left?: string | number; right?: string | number; bottom?: string | number }>({});
98
+
99
+ const updateMargin = (target: Element | null | undefined) => {
100
+ if (!target) return;
101
+ const { marginTop, marginLeft, marginRight, marginBottom } = getComputedStyle(target);
102
+ contentMargin = { top: marginTop, left: marginLeft, right: marginRight, bottom: marginBottom };
103
+ };
104
+
105
+ const updateDragState = async (target: Element | null | undefined = dragRef) => {
106
+ if (!drop || !expanded) return;
107
+
108
+ dragWith = target ? `${target.clientWidth}px` : 0;
109
+ dragHeight = target ? `${target.clientHeight}px` : 0;
110
+
111
+ updateMargin(dragRef?.firstElementChild);
112
+ };
113
+
114
+ const onClear: MouseEventHandler<HTMLButtonElement> = e => {
115
+ e?.stopPropagation();
116
+ ref?.clear?.();
117
+ };
118
+
119
+ const onclick = (e: SvelteEvent<MouseEvent>) => {
120
+ if (disabled || skeleton) return;
121
+ e?.stopPropagation();
122
+ ref?.focus?.();
123
+ ref?.click?.();
124
+ buttonProps?.onclick?.(e);
125
+ };
126
+
127
+ const afterProps = $derived<NeoButtonProps>({
128
+ 'aria-label': 'Add files',
129
+ title: 'Add files',
130
+ skeleton,
131
+ disabled,
132
+ rounded: expanded || rounded,
133
+ glass: rest.glass,
134
+ start: rest.start,
135
+ text,
136
+ style,
137
+ ...buttonProps,
138
+ class: ['neo-file-picker-button', buttonProps?.class],
139
+ onclick,
140
+ });
141
+
142
+ type FileEvent = SvelteEvent<InputEvent, HTMLInputElement>;
143
+ const getValue = (e: FileEvent): null | FileList | File => {
144
+ updateDragState();
145
+ if (!e?.currentTarget?.files) return null;
146
+ if (multiple) return e.currentTarget.files;
147
+ return e.currentTarget.files[0];
148
+ };
149
+
150
+ const mirror = (e: FileEvent, cb?: NeoFilePickerProps['oninput'] | NeoFilePickerProps['onchange']) => cb?.(e, getValue(e));
151
+ const mirrorInput: FormEventHandler<HTMLInputElement> = e => mirror(e as FileEvent, oninput);
152
+ const mirrorChange: FormEventHandler<HTMLInputElement> = e => mirror(e as FileEvent, onchange);
153
+
154
+ const emitChange = async () => {
155
+ await tick();
156
+ if (!ref) return;
157
+ const init: InputEventInit = {
158
+ bubbles: true,
159
+ cancelable: false,
160
+ data: multiple ? `${files?.length ?? 0} Files` : files?.[0]?.name,
161
+ inputType: 'insertFromDrop',
162
+ };
163
+ ref.dispatchEvent(new InputEvent('input', init));
164
+ ref.dispatchEvent(new InputEvent('change', init));
165
+ };
166
+
167
+ const mergeLists = (left?: FileList, right?: FileList): FileList | undefined => {
168
+ if (!left?.length && !right?.length) return;
169
+ if (!left?.length) return right;
170
+ if (!right?.length) return left;
171
+ const transfer = new DataTransfer();
172
+ const map = new Map<string, File>();
173
+ let file: File;
174
+ for (let i = 0; i < left.length; i += 1) {
175
+ file = left[i];
176
+ map.set(file.name, file);
177
+ }
178
+ for (let i = 0; i < right.length; i += 1) {
179
+ file = right[i];
180
+ map.set(file.name, file);
181
+ }
182
+ map.forEach(f => transfer.items.add(f));
183
+ return transfer.files;
184
+ };
185
+
186
+ const onDrop: DragEventHandler<HTMLDivElement> = async e => {
187
+ dragging = false;
188
+ e.preventDefault();
189
+ if (disabled || skeleton) return;
190
+ if (!e.dataTransfer?.files?.length) return;
191
+ if (multiple && append) {
192
+ files = mergeLists(files, e.dataTransfer.files);
193
+ } else if (multiple) {
194
+ files = e.dataTransfer.files;
195
+ } else {
196
+ const list = new DataTransfer();
197
+ list.items.add(e.dataTransfer.files[0]);
198
+ files = list.files;
199
+ }
200
+ return emitChange();
201
+ };
202
+
203
+ const onDragOver: DragEventHandler<HTMLDivElement> = e => e.preventDefault();
204
+
205
+ const onDragEnter: DragEventHandler<HTMLDivElement> = e => {
206
+ e.preventDefault();
207
+ updateDragState();
208
+ dragging = true;
209
+ hovered = true;
210
+ };
211
+
212
+ const onDragLeave: DragEventHandler<HTMLDivElement> = e => {
213
+ e.preventDefault();
214
+ hovered = false;
215
+ dragging = false;
216
+ };
217
+
218
+ const removeFile = async (i: number, e?: SvelteEvent<MouseEvent>) => {
219
+ e?.preventDefault();
220
+ e?.stopPropagation();
221
+ if (!ref) return;
222
+ if (!files?.length || i < 0 || i >= files.length) return;
223
+ if (files.length) {
224
+ const transfer = new DataTransfer();
225
+ for (let j = 0; j < files.length; j += 1) {
226
+ if (i !== j) transfer.items.add(files[j]);
227
+ }
228
+ files = transfer.files;
229
+ } else files = new DataTransfer().files;
230
+ return emitChange();
231
+ };
232
+
233
+ let visible = $state(false);
234
+ let messageId = $state(`neo-file-picker-message-${crypto.randomUUID()}`);
235
+ let validationMessage = $state<string>(ref?.validationMessage ?? '');
236
+
237
+ const context = $derived<NeoInputContext<NeoInputHTMLElement>>({
238
+ // Ref
239
+ ref,
240
+
241
+ // Methods
242
+ mark: ref?.mark,
243
+ clear: ref?.clear,
244
+ change: ref?.change,
245
+ validate: ref?.validate,
246
+
247
+ // State
248
+ value: files,
249
+ touched,
250
+ dirty,
251
+ valid,
252
+ readonly,
253
+ disabled,
254
+
255
+ // Styles
256
+ elevation,
257
+ hover,
258
+ pressed,
259
+ borderless: rest.borderless,
260
+ rounded,
261
+ glass: rest.glass,
262
+ start: rest.start,
263
+ skeleton,
264
+ });
265
+ </script>
266
+
267
+ {#snippet upload()}
268
+ <NeoButton {...afterProps}>
269
+ {#snippet icon()}
270
+ {#if isDragging}
271
+ <IconDownload width="1.25rem" height="1.25rem" scale="1.5" stroke="1" />
272
+ {:else}
273
+ <IconFileUpload width="1.25rem" height="1.25rem" scale="var(--neo-input-icon-scale, 1.125)" />
274
+ {/if}
275
+ {/snippet}
276
+ </NeoButton>
277
+ {/snippet}
278
+
279
+ {#snippet input()}
280
+ <NeoInput
281
+ bind:ref
282
+ bind:files
283
+ bind:value
284
+ bind:valid
285
+ bind:dirty
286
+ bind:touched
287
+ bind:hovered
288
+ bind:focused
289
+ bind:labelRef
290
+ type="file"
291
+ {id}
292
+ {label}
293
+ {labelProps}
294
+ {error}
295
+ {message}
296
+ {messageTag}
297
+ {messageProps}
298
+ after={after ?? upload}
299
+ {before}
300
+ {placeholder}
301
+ {loading}
302
+ {clearable}
303
+ {skeleton}
304
+ {disabled}
305
+ {readonly}
306
+ {rounded}
307
+ {pressed}
308
+ {validation}
309
+ {wrapperTag}
310
+ {wrapperProps}
311
+ {elevation}
312
+ {hover}
313
+ {multiple}
314
+ in={inAction}
315
+ out={outAction}
316
+ transition={transitionAction}
317
+ {...rest}
318
+ oninput={mirrorInput}
319
+ onchange={mirrorChange}
320
+ containerProps={{ ...groupProps, class: ['neo-file-picker-input-group', groupProps?.class] }}
321
+ >
322
+ {#if drop}
323
+ <div bind:this={overlayRef} class="neo-drop-overlay">
324
+ {dropText}
325
+ </div>
326
+ {/if}
327
+ </NeoInput>
328
+ {/snippet}
329
+
330
+ {#snippet card()}
331
+ <NeoFilePickerCard
332
+ bind:hovered
333
+ bind:focused
334
+ bind:labelRef
335
+ dragging={isDragging}
336
+ {multiple}
337
+ {append}
338
+ {children}
339
+ {files}
340
+ valid={validation ? valid : undefined}
341
+ {clearable}
342
+ {placeholder}
343
+ {dropText}
344
+ {loading}
345
+ {skeleton}
346
+ {disabled}
347
+ {rounded}
348
+ {pressed}
349
+ {elevation}
350
+ {hover}
351
+ glass={rest.glass}
352
+ start={rest.start}
353
+ required={rest.required}
354
+ maxHeight={expandHeight}
355
+ detailText={expandText}
356
+ {label}
357
+ labelProps={{ for: id, ...labelProps }}
358
+ {...cardProps}
359
+ {onClear}
360
+ onRemove={removeFile}
361
+ onEdit={onclick}
362
+ addButtonProps={afterProps}
363
+ />
364
+ <span class="neo-expanded-input">
365
+ <NeoBaseInput
366
+ bind:ref
367
+ bind:files
368
+ bind:value
369
+ bind:valid
370
+ bind:dirty
371
+ bind:touched
372
+ bind:validationMessage
373
+ type="file"
374
+ aria-invalid={valid === undefined ? undefined : !valid}
375
+ aria-describedby={visible ? messageId : undefined}
376
+ {id}
377
+ {multiple}
378
+ {...rest}
379
+ hidden
380
+ aria-hidden
381
+ tabindex={-1}
382
+ oninput={mirrorInput}
383
+ onchange={mirrorChange}
384
+ />
385
+ </span>
386
+ {/snippet}
387
+
388
+ <!-- Drag & drop -->
389
+ {#snippet drag()}
390
+ <div
391
+ bind:this={dragRef}
392
+ role="region"
393
+ class="neo-drop-container"
394
+ class:neo-expanded={expanded}
395
+ class:neo-dragging={isDragging}
396
+ class:neo-pressed={pressed}
397
+ class:neo-skeleton={skeleton}
398
+ ondrop={onDrop}
399
+ ondragover={onDragOver}
400
+ ondragenter={onDragEnter}
401
+ ondragleave={onDragLeave}
402
+ style:--neo-file-picker-expanded-min-width={dragWith}
403
+ style:--neo-file-picker-expanded-min-height={dragHeight}
404
+ style:--neo-file-picker-drag-margin-top={contentMargin.top}
405
+ style:--neo-file-picker-drag-margin-bottom={contentMargin.bottom}
406
+ >
407
+ {#if expanded}
408
+ {@render card()}
409
+ {:else}
410
+ {@render input()}
411
+ {/if}
412
+ </div>
413
+ {/snippet}
414
+
415
+ <svelte:element this={containerTag} class:neo-file-picker={true} class:neo-expanded={expanded} {...containerProps}>
416
+ {#if drop && expanded}
417
+ <!-- Expanded picker -->
418
+ <NeoInputValidation
419
+ tag={wrapperTag}
420
+ bind:visible
421
+ bind:messageId
422
+ {valid}
423
+ {validation}
424
+ {validationMessage}
425
+ {error}
426
+ {rounded}
427
+ {context}
428
+ {message}
429
+ {messageTag}
430
+ {messageProps}
431
+ in={inAction}
432
+ out={outAction}
433
+ transition={transitionAction}
434
+ {...wrapperProps}
435
+ class={['neo-file-picker-validation', wrapperProps?.class]}
436
+ >
437
+ {@render drag()}
438
+ </NeoInputValidation>
439
+ {:else if drop}
440
+ <!-- Drop support -->
441
+ {@render drag()}
442
+ {:else}
443
+ <!-- No drop support -->
444
+ {@render input()}
445
+ {/if}
446
+ </svelte:element>
447
+
448
+ <style>.neo-file-picker {
449
+ --neo-input-cursor: pointer;
450
+ }
451
+ .neo-file-picker :global(.neo-input::file-selector-button) {
452
+ align-items: center;
453
+ align-self: center;
454
+ width: 0;
455
+ height: 100%;
456
+ margin: 0;
457
+ padding: 0;
458
+ border: none;
459
+ visibility: hidden;
460
+ }
461
+ .neo-file-picker.neo-expanded {
462
+ display: inline-flex;
463
+ flex: 1 1 auto;
464
+ }
465
+ .neo-file-picker .neo-drop-container {
466
+ position: relative;
467
+ display: inline-flex;
468
+ align-items: center;
469
+ justify-content: center;
470
+ box-sizing: border-box;
471
+ min-width: var(--neo-file-picker-expanded-min-width, 0);
472
+ min-height: var(--neo-file-picker-expanded-min-height, 0);
473
+ padding: 0.75rem;
474
+ transition: min-width 0.3s ease, min-height 0.3s ease;
475
+ }
476
+ .neo-file-picker .neo-drop-container .neo-drop-overlay {
477
+ position: absolute;
478
+ z-index: var(--neo-z-index-in-front, 1);
479
+ display: inline-flex;
480
+ align-items: center;
481
+ box-sizing: border-box;
482
+ padding: 0.75rem 1rem;
483
+ border-radius: var(--neo-border-radius);
484
+ opacity: 0;
485
+ transition: opacity 0.3s ease;
486
+ pointer-events: none;
487
+ inset: 0;
488
+ }
489
+ .neo-file-picker .neo-drop-container.neo-expanded {
490
+ width: 100%;
491
+ }
492
+ .neo-file-picker .neo-drop-container .neo-expanded-input {
493
+ display: none;
494
+ }
495
+ .neo-file-picker .neo-drop-container :global(.neo-file-picker-card) {
496
+ gap: var(--neo-gap);
497
+ width: 100%;
498
+ height: calc(100% - var(--neo-file-picker-drag-margin-top, var(--neo-shadow-margin, 0.625rem)) - var(--neo-file-picker-drag-margin-bottom, var(--neo-shadow-margin, 0.625rem)));
499
+ }
500
+ .neo-file-picker .neo-drop-container.neo-dragging:not(.neo-skeleton) .neo-drop-overlay {
501
+ opacity: 1;
502
+ }
503
+ .neo-file-picker .neo-drop-container.neo-dragging:not(.neo-skeleton) :global(.neo-file-picker-card),
504
+ .neo-file-picker .neo-drop-container.neo-dragging:not(.neo-skeleton) :global(.neo-file-picker-input-group) {
505
+ --neo-box-shadow-raised-1: var(--neo-box-shadow-pressed-1);
506
+ --neo-box-shadow-raised-2: var(--neo-box-shadow-pressed-2);
507
+ --neo-box-shadow-raised-3: var(--neo-box-shadow-pressed-3);
508
+ --neo-box-shadow-raised-4: var(--neo-box-shadow-pressed-4);
509
+ --neo-box-shadow-raised-5: var(--neo-box-shadow-pressed-4);
510
+ --neo-glass-box-shadow-raised-1: var(--neo-glass-box-shadow-pressed-1);
511
+ --neo-glass-box-shadow-raised-2: var(--neo-glass-box-shadow-pressed-2);
512
+ --neo-glass-box-shadow-raised-3: var(--neo-glass-box-shadow-pressed-3);
513
+ --neo-glass-box-shadow-raised-4: var(--neo-glass-box-shadow-pressed-4);
514
+ --neo-glass-box-shadow-raised-5: var(--neo-glass-box-shadow-pressed-4);
515
+ }
516
+ .neo-file-picker .neo-drop-container.neo-dragging:not(.neo-skeleton) :global(.neo-file-picker-card) :global(.neo-file-picker-button),
517
+ .neo-file-picker .neo-drop-container.neo-dragging:not(.neo-skeleton) :global(.neo-file-picker-input-group) :global(.neo-file-picker-button) {
518
+ --neo-btn-box-shadow: var(--neo-box-shadow-flat) !important;
519
+ }
520
+ .neo-file-picker .neo-drop-container.neo-dragging:not(.neo-skeleton) :global(> *) {
521
+ pointer-events: none;
522
+ }
523
+ .neo-file-picker .neo-drop-container.neo-dragging:not(.neo-skeleton) :global(*.neo-file-picker-input-group > *:not(.neo-input-after, .neo-drop-overlay)) {
524
+ opacity: 0;
525
+ }
526
+ .neo-file-picker :global(.neo-file-picker-validation) {
527
+ width: 100%;
528
+ }</style>
@@ -0,0 +1,19 @@
1
+ import type { NeoFilePickerProps } 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 NeoFilePicker: $$__sveltets_2_IsomorphicComponent<NeoFilePickerProps, {
16
+ [evt: string]: CustomEvent<any>;
17
+ }, {}, {}, "value" | "ref" | "hovered" | "focused" | "files" | "touched" | "dirty" | "valid" | "labelRef" | "dragging" | "expanded">;
18
+ type NeoFilePicker = InstanceType<typeof NeoFilePicker>;
19
+ export default NeoFilePicker;