@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,589 @@
1
+ <script lang="ts">
2
+ import type { EventHandler, FocusEventHandler, MouseEventHandler } from 'svelte/elements';
3
+ import type { NeoInputHTMLElement } from './common/neo-input.model.js';
4
+ import type { NeoPinContext, NeoPinProps } from './neo-pin.model.js';
5
+ import type { SvelteEvent } from '../utils/html-element.utils.js';
6
+
7
+ import IconMinus from '../icons/IconMinus.svelte';
8
+ import NeoAffix from './common/NeoAffix.svelte';
9
+ import NeoInput from './common/NeoInput.svelte';
10
+ import NeoInputValidation from './common/NeoInputValidation.svelte';
11
+ import NeoLabel from './common/NeoLabel.svelte';
12
+ import { toAction, toActionProps, toTransition, toTransitionProps } from '../utils/action.utils.js';
13
+ import { ArrowPrefix } from '../utils/regex.utils.js';
14
+ import { DefaultShadowElevation } from '../utils/shadow.utils.js';
15
+ import { doubleBind } from '../utils/utils.svelte.js';
16
+
17
+ /* eslint-disable prefer-const -- necessary for binding checked */
18
+ let {
19
+ // Snippets
20
+ label,
21
+ before,
22
+ after,
23
+ message,
24
+ error,
25
+ icon,
26
+
27
+ // State
28
+ id = label ? `neo-pin-input-${crypto.randomUUID()}` : undefined,
29
+ ref = $bindable(),
30
+ value = $bindable(''),
31
+ valid = $bindable(),
32
+ dirty = $bindable(false),
33
+ touched = $bindable(false),
34
+ hovered = $bindable(false),
35
+ focused = $bindable(false),
36
+ loading,
37
+ clearable,
38
+
39
+ // Validation
40
+ step = 1,
41
+ min = 0,
42
+ max = 9,
43
+ required,
44
+ pattern,
45
+ minlength = 6,
46
+ maxlength,
47
+ dirtyOnInput,
48
+ validateOnInput,
49
+
50
+ // Styles
51
+ groups = 1,
52
+ count = 4,
53
+ separator,
54
+ validation,
55
+ vertical = groups > 1,
56
+
57
+ // Transition
58
+ in: inAction,
59
+ out: outAction,
60
+ transition: transitionAction,
61
+
62
+ // Actions
63
+ use,
64
+
65
+ // Events
66
+ oninput,
67
+ onchange,
68
+ oninvalid,
69
+
70
+ // Other props
71
+ labelRef = $bindable(),
72
+ labelProps,
73
+ afterProps,
74
+ afterTag = 'div',
75
+ beforeProps,
76
+ beforeTag = 'div',
77
+ containerProps,
78
+ containerTag = 'div',
79
+ wrapperProps,
80
+ wrapperTag,
81
+ messageProps,
82
+ messageTag,
83
+ groupProps,
84
+ ...rest
85
+ }: NeoPinProps = $props();
86
+ /* eslint-enable prefer-const */
87
+
88
+ const refs = $state<NeoInputHTMLElement[][]>(Array(Number(groups)).fill([]));
89
+ const values = $state<string[][]>(Array(Number(groups)).fill(Array(Number(count)).fill('')));
90
+ const touches = $state<boolean[][]>(Array(Number(groups)).fill(Array(Number(count)).fill(false)));
91
+ const dirtiness = $state<boolean[][]>(Array(Number(groups)).fill(Array(Number(count)).fill(false)));
92
+
93
+ const initial = $state(value);
94
+ let validationMessage: string | undefined = $state(ref?.validationMessage);
95
+
96
+ const validate = () => {
97
+ dirty = value !== initial;
98
+ valid = ref?.checkValidity();
99
+ validationMessage = ref?.validationMessage;
100
+ return { touched, dirty, valid, value, initial };
101
+ };
102
+
103
+ const focus = (i = 0, j = 0, options: { previous?: boolean; last?: boolean; select?: boolean } = {}) => {
104
+ let _group = i;
105
+ let _count = j;
106
+
107
+ if (options?.previous) {
108
+ _group = j ? i : i - 1;
109
+ _count = j ? j - 1 : count - 1;
110
+ } else if (options.last) {
111
+ values.findIndex((group, _i) => {
112
+ const _j = group.findIndex(val => !val?.length);
113
+ if (_j === -1) return false;
114
+ _group = _i;
115
+ _count = _j;
116
+ return true;
117
+ });
118
+ } else {
119
+ _group = j < count - 1 ? i : i + 1;
120
+ _count = j < count - 1 ? j + 1 : 0;
121
+ }
122
+
123
+ refs?.[_group]?.[_count]?.focus();
124
+ if (options?.select) refs?.[_group]?.[_count]?.select();
125
+ };
126
+
127
+ const onInput = (i: number, j: number) => {
128
+ if (!values?.[i]?.[j]?.length) return;
129
+ focus(i, j);
130
+ };
131
+
132
+ const arrow = (e: KeyboardEvent, i: number, j: number) => {
133
+ e.preventDefault();
134
+ if (e.key === 'ArrowLeft') return focus(i, j, { previous: true, select: e.shiftKey });
135
+ if (e.key === 'ArrowRight') return focus(i, j, { select: e.shiftKey });
136
+ const _value = values?.[i]?.[j];
137
+ let data: string = '';
138
+ if (e.key === 'ArrowUp') data = !Number.isNaN(Number(_value)) ? String(Math.min(Number(_value) + 1, Number(max))) : _value.toUpperCase();
139
+ if (e.key === 'ArrowDown') data = !Number.isNaN(Number(_value)) ? String(Math.max(Number(_value) - 1, Number(min))) : _value.toLowerCase();
140
+ if (!data?.length) return;
141
+ return refs?.[i]?.[j]?.change?.(
142
+ data,
143
+ new InputEvent('input', {
144
+ bubbles: true,
145
+ cancelable: false,
146
+ data,
147
+ inputType: 'insertText',
148
+ }),
149
+ );
150
+ };
151
+
152
+ const onKeydown = (e: KeyboardEvent, i: number, j: number) => {
153
+ if (ArrowPrefix.test(e.key)) return arrow(e, i, j);
154
+
155
+ if (e.key !== 'Backspace') return;
156
+ if (!j && !i) return;
157
+ if (values?.[i]?.[j]?.length) return;
158
+
159
+ e.preventDefault();
160
+
161
+ const _group = !j ? i - 1 : i;
162
+ const _count = !j ? count - 1 : j - 1;
163
+
164
+ refs?.[_group]?.[_count]?.clear?.(
165
+ undefined,
166
+ new InputEvent('input', {
167
+ bubbles: true,
168
+ cancelable: false,
169
+ data: '',
170
+ inputType: 'deleteContentBackward',
171
+ }),
172
+ );
173
+ };
174
+
175
+ const clear = async () => {
176
+ await Promise.all(refs?.map(group => group?.map(input => input?.clear?.())));
177
+ focus(0, 0, { last: true });
178
+ };
179
+
180
+ const paste = (data: string, i = 0, j = 0) => {
181
+ let _group = i;
182
+ let _count = j;
183
+
184
+ if (!data?.length) return;
185
+
186
+ data?.split('').forEach((char, index) => {
187
+ if (char === separator && index % count === 0) return;
188
+ if (_group >= groups) return;
189
+
190
+ refs?.[_group]?.[_count]?.change?.(
191
+ char,
192
+ new InputEvent('input', {
193
+ bubbles: true,
194
+ cancelable: false,
195
+ data: char,
196
+ inputType: 'insertText',
197
+ }),
198
+ );
199
+ _group = _count < count - 1 ? _group : _group + 1;
200
+ _count = _count < count - 1 ? _count + 1 : 0;
201
+ });
202
+ };
203
+
204
+ const onPaste = (e: ClipboardEvent, i: number, j: number) => {
205
+ const data = e.clipboardData?.getData('text');
206
+ if (!data?.length) return;
207
+ e.preventDefault();
208
+ paste(data, i, j);
209
+ };
210
+
211
+ const _separator = $derived.by(() => {
212
+ if (typeof separator === 'string') return separator;
213
+ return separator ? '-' : '';
214
+ });
215
+
216
+ const mergedValues = $derived(values.map(group => group.join('')).join(_separator));
217
+ doubleBind({
218
+ outer: () => value,
219
+ input: () => {
220
+ clear();
221
+ paste(value);
222
+ },
223
+ inner: () => mergedValues,
224
+ output: () => {
225
+ value = mergedValues;
226
+
227
+ if (validateOnInput) validate();
228
+
229
+ const event: SvelteEvent<InputEvent> = new InputEvent('input', {
230
+ bubbles: true,
231
+ cancelable: false,
232
+ data: value,
233
+ inputType: 'insertText',
234
+ });
235
+ oninput?.(event);
236
+ },
237
+ });
238
+
239
+ const mergedTouched = $derived(touches.some(group => group.some(Boolean)));
240
+ doubleBind({
241
+ outer: () => touched,
242
+ input: () => {
243
+ if (touched) return;
244
+ refs?.forEach(group => group?.forEach(input => input?.mark?.({ touched: false })));
245
+ },
246
+ inner: () => mergedTouched,
247
+ output: () => {
248
+ touched = mergedTouched;
249
+ },
250
+ });
251
+
252
+ const mergedDirty = $derived(dirtiness.some(group => group.some(Boolean)));
253
+ doubleBind({
254
+ outer: () => dirty,
255
+ input: () => {
256
+ if (dirty) return;
257
+ refs?.forEach(group => group?.forEach(input => input?.mark?.({ dirty: false })));
258
+ },
259
+ inner: () => mergedDirty,
260
+ output: () => {
261
+ if (!dirtyOnInput) return;
262
+ dirty = mergedDirty;
263
+ },
264
+ });
265
+
266
+ let changed = value;
267
+ let timeout: ReturnType<typeof setTimeout>;
268
+ const onFocusIn: FocusEventHandler<HTMLDivElement> = e => {
269
+ clearTimeout(timeout);
270
+ focused = true;
271
+ containerProps?.onfocusin?.(e);
272
+ };
273
+ const onFocusOut: FocusEventHandler<HTMLDivElement> = e => {
274
+ timeout = setTimeout(() => {
275
+ focused = false;
276
+ containerProps?.onfocusout?.(e);
277
+
278
+ if (changed === value) return;
279
+ validate();
280
+ dirty = mergedDirty;
281
+
282
+ const event: SvelteEvent<InputEvent> = new InputEvent('change', {
283
+ bubbles: true,
284
+ cancelable: false,
285
+ data: value,
286
+ inputType: 'insertText',
287
+ });
288
+ onchange?.(event);
289
+ changed = value;
290
+ }, 0);
291
+ };
292
+
293
+ const onInvalid: EventHandler<Event, HTMLInputElement> = e => {
294
+ valid = false;
295
+ validationMessage = ref?.validationMessage;
296
+ e.preventDefault();
297
+ oninvalid?.(e);
298
+ };
299
+
300
+ const onMouseEnter: MouseEventHandler<HTMLDivElement> = e => {
301
+ hovered = true;
302
+ containerProps?.onmouseenter?.(e);
303
+ };
304
+ const onMouseLeave: MouseEventHandler<HTMLDivElement> = e => {
305
+ hovered = false;
306
+ containerProps?.onmouseleave?.(e);
307
+ };
308
+
309
+ const affix = $derived(clearable || loading !== undefined || validation);
310
+ const hasValue = $derived(value !== undefined && (typeof value === 'string' ? !!value.length : value !== null));
311
+ const close = $derived(clearable && (focused || hovered) && hasValue && !rest.disabled && !rest.readonly);
312
+
313
+ let visible = $state(false);
314
+ let messageId = $state(`neo-pin-message-${crypto.randomUUID()}`);
315
+
316
+ const elevation = $derived(rest?.elevation ?? DefaultShadowElevation);
317
+
318
+ const context = $derived<NeoPinContext>({
319
+ // Ref
320
+ ref,
321
+
322
+ // State
323
+ initial,
324
+ value,
325
+ touched,
326
+ dirty,
327
+ valid,
328
+ disabled: rest.disabled,
329
+ readonly: rest.readonly,
330
+
331
+ // Methods
332
+ clear,
333
+ });
334
+
335
+ const inFn = $derived(toTransition(inAction ?? transitionAction));
336
+ const inProps = $derived(toTransitionProps(inAction ?? transitionAction));
337
+ const outFn = $derived(toTransition(outAction ?? transitionAction));
338
+ const outProps = $derived(toTransitionProps(outAction ?? transitionAction));
339
+
340
+ const useFn = $derived(toAction(use));
341
+ const useProps = $derived(toActionProps(use));
342
+ </script>
343
+
344
+ {#snippet group()}
345
+ <svelte:element
346
+ this={containerTag}
347
+ role="none"
348
+ class:neo-pin-container={true}
349
+ class:neo-deep={elevation < -3}
350
+ class:neo-raised={elevation > 3}
351
+ class:neo-pressed={rest.pressed}
352
+ class:neo-after={after}
353
+ data-touched={touched}
354
+ data-dirty={dirty}
355
+ data-valid={valid}
356
+ use:useFn={useProps}
357
+ out:outFn={outProps}
358
+ in:inFn={inProps}
359
+ {...containerProps}
360
+ onfocusin={onFocusIn}
361
+ onfocusout={onFocusOut}
362
+ onmouseenter={onMouseEnter}
363
+ onmouseleave={onMouseLeave}
364
+ >
365
+ {#if before}
366
+ <svelte:element this={beforeTag} class:neo-pin-before={true} class:neo-vertical={vertical} {...beforeProps}>
367
+ {@render before(context)}
368
+ </svelte:element>
369
+ {/if}
370
+ <div class="neo-pin-group-wrapper" class:neo-vertical={vertical}>
371
+ <input
372
+ class="neo-pin-hidden"
373
+ bind:this={ref}
374
+ {id}
375
+ aria-hidden="true"
376
+ aria-invalid={valid === undefined ? undefined : !valid}
377
+ aria-describedby={visible ? messageId : undefined}
378
+ hidden
379
+ type="text"
380
+ tabindex="-1"
381
+ {step}
382
+ {min}
383
+ {max}
384
+ {required}
385
+ {minlength}
386
+ {maxlength}
387
+ {pattern}
388
+ bind:value
389
+ oninvalid={onInvalid}
390
+ />
391
+ {#each Array(Number(groups)) as _, i}
392
+ <div class="neo-pin-group">
393
+ {#each Array(Number(count)) as __, j}
394
+ <NeoInput
395
+ bind:ref={refs[i][j]}
396
+ bind:value={values[i][j]}
397
+ bind:dirty={dirtiness[i][j]}
398
+ bind:touched={touches[i][j]}
399
+ size={1}
400
+ maxlength={1}
401
+ minlength={1}
402
+ {step}
403
+ {min}
404
+ {max}
405
+ type="text"
406
+ containerProps={groupProps}
407
+ {...rest}
408
+ oninput={() => onInput(i, j)}
409
+ onkeydown={e => onKeydown(e, i, j)}
410
+ onpaste={e => onPaste(e, i, j)}
411
+ />
412
+ {/each}
413
+ </div>
414
+ {#if i < groups - 1}
415
+ <div class="neo-pin-separator">
416
+ {#if icon}
417
+ {@render icon()}
418
+ {:else if typeof separator === 'string'}
419
+ {separator}
420
+ {:else}
421
+ <IconMinus />
422
+ {/if}
423
+ </div>
424
+ {/if}
425
+ {/each}
426
+ </div>
427
+ {#if affix || after}
428
+ <svelte:element this={afterTag} class:neo-pin-after={true} class:neo-vertical={vertical} {...afterProps}>
429
+ <!-- Affix (loafing, clear, placeholder) -->
430
+ {#if affix}
431
+ <NeoAffix
432
+ {loading}
433
+ {close}
434
+ valid={validation ? valid : undefined}
435
+ disabled={rest.disabled}
436
+ skeleton={rest.skeleton}
437
+ closeProps={{ onclick: () => clear() }}
438
+ onclick={() => focus(0, 0, { last: true })}
439
+ />
440
+ {/if}
441
+ {@render after?.(context)}
442
+ </svelte:element>
443
+ {/if}
444
+ </svelte:element>
445
+ {/snippet}
446
+
447
+ {#snippet validationGroup()}
448
+ <NeoInputValidation
449
+ tag={wrapperTag}
450
+ bind:visible
451
+ bind:messageId
452
+ {valid}
453
+ {validation}
454
+ {validationMessage}
455
+ {error}
456
+ rounded={rest.rounded}
457
+ {context}
458
+ {message}
459
+ {messageTag}
460
+ {messageProps}
461
+ in={inAction}
462
+ out={outAction}
463
+ transition={transitionAction}
464
+ {...wrapperProps}
465
+ >
466
+ {@render group()}
467
+ </NeoInputValidation>
468
+ {/snippet}
469
+
470
+ {#snippet labelGroup()}
471
+ {#if typeof label === 'string'}
472
+ {label}
473
+ {:else if label}
474
+ {@render label(context)}
475
+ {/if}
476
+ {/snippet}
477
+
478
+ {#if label}
479
+ <NeoLabel
480
+ for={id}
481
+ bind:ref={labelRef}
482
+ {required}
483
+ label={labelGroup}
484
+ {...labelProps}
485
+ onclick={e => {
486
+ focus(0, 0, { last: true });
487
+ labelProps?.onclick?.(e);
488
+ }}
489
+ >
490
+ {@render validationGroup()}
491
+ </NeoLabel>
492
+ {:else}
493
+ {@render validationGroup()}
494
+ {/if}
495
+
496
+ <style>.neo-pin-container,
497
+ .neo-pin-group-wrapper,
498
+ .neo-pin-group,
499
+ .neo-pin-separator,
500
+ .neo-pin-before,
501
+ .neo-pin-after {
502
+ display: inline-flex;
503
+ align-items: center;
504
+ }
505
+
506
+ .neo-pin-hidden {
507
+ display: none;
508
+ }
509
+
510
+ .neo-pin-group-wrapper,
511
+ .neo-pin-group {
512
+ flex-wrap: wrap;
513
+ justify-content: center;
514
+ }
515
+
516
+ .neo-pin-separator {
517
+ justify-content: center;
518
+ min-width: 2rem;
519
+ }
520
+
521
+ .neo-pin-spacer {
522
+ flex: 1 1 auto;
523
+ }
524
+
525
+ .neo-pin-before,
526
+ .neo-pin-after {
527
+ align-self: stretch;
528
+ justify-content: space-between;
529
+ margin: var(--neo-shadow-margin);
530
+ }
531
+
532
+ .neo-vertical {
533
+ flex-direction: column;
534
+ }
535
+
536
+ .neo-pin-container {
537
+ margin: var(--neo-shadow-margin, 0.625rem);
538
+ }
539
+ .neo-pin-container :global(.neo-input) {
540
+ width: 2.125rem;
541
+ padding: 0.5rem;
542
+ text-align: center;
543
+ }
544
+ .neo-pin-container :global(.neo-input[type="number"]) {
545
+ /* Hide arrows -Firefox */
546
+ appearance: textfield;
547
+ /* Hide arrows - Chrome, Safari, Edge, Opera */
548
+ }
549
+ .neo-pin-container :global(.neo-input[type="number"])::-webkit-outer-spin-button, .neo-pin-container :global(.neo-input[type="number"])::-webkit-inner-spin-button {
550
+ margin: 0;
551
+ appearance: none;
552
+ }
553
+ .neo-pin-container :global(.neo-input-group.neo-rounded .neo-input) {
554
+ width: 2.25rem;
555
+ padding: 0.5rem;
556
+ }
557
+ .neo-pin-container :global(.neo-input[type="password"]:not(:placeholder-shown)) {
558
+ -webkit-text-stroke-width: 0.1em;
559
+ letter-spacing: 0;
560
+ }
561
+ @supports (-webkit-touch-callout: none) {
562
+ .neo-pin-container :global(.neo-input[type="password"]:not(:placeholder-shown)) {
563
+ font: small-caption;
564
+ font-size: var(--neo-font-size, 1rem);
565
+ }
566
+ }
567
+ .neo-pin-container .neo-pin-after {
568
+ --neo-affix-padding: 0.75rem 0;
569
+ }
570
+ .neo-pin-container .neo-pin-after :global(.neo-password-toggle) {
571
+ min-width: 2.25rem;
572
+ min-height: 2.25rem;
573
+ margin: 0.125rem 0;
574
+ }
575
+ .neo-pin-container.neo-raised .neo-pin-after, .neo-pin-container.neo-deep.neo-pressed .neo-pin-after {
576
+ --neo-affix-padding: var(--neo-shadow-margin-lg, 1.125rem) 0;
577
+ }
578
+ .neo-pin-container.neo-raised .neo-pin-after :global(.neo-password-toggle), .neo-pin-container.neo-deep.neo-pressed .neo-pin-after :global(.neo-password-toggle) {
579
+ margin: 0.625rem 0;
580
+ }
581
+ .neo-pin-container.neo-deep :global(.neo-input) {
582
+ aspect-ratio: 1;
583
+ }
584
+ .neo-pin-container.neo-after:not(.neo-vertical) .neo-pin-after {
585
+ gap: 1.125rem;
586
+ }
587
+ .neo-pin-container.neo-raised.neo-after:not(.neo-vertical) .neo-pin-after {
588
+ gap: 1.5rem;
589
+ }</style>
@@ -0,0 +1,19 @@
1
+ import type { NeoPinProps } from './neo-pin.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 NeoPin: $$__sveltets_2_IsomorphicComponent<NeoPinProps, {
16
+ [evt: string]: CustomEvent<any>;
17
+ }, {}, {}, "value" | "ref" | "hovered" | "focused" | "touched" | "dirty" | "valid" | "labelRef">;
18
+ type NeoPin = InstanceType<typeof NeoPin>;
19
+ export default NeoPin;