@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
@@ -1,750 +0,0 @@
1
- <script lang="ts">
2
- import { wait } from '@dvcol/common-utils/common/promise';
3
- import { fade } from 'svelte/transition';
4
-
5
- import type { EventHandler, FocusEventHandler, FormEventHandler, MouseEventHandler } from 'svelte/elements';
6
-
7
- import IconAlert from '../icons/IconAlert.svelte';
8
- import IconCircleLoading from '../icons/IconCircleLoading.svelte';
9
- import IconClear from '../icons/IconClear.svelte';
10
- import IconConfirm from '../icons/IconConfirm.svelte';
11
- import NeoValidation from './NeoValidation.svelte';
12
- import {
13
- type NeoInputContext,
14
- NeoInputLabelPosition,
15
- type NeoInputMethods,
16
- type NeoInputProps,
17
- type NeoInputState,
18
- } from './neo-input.model.js';
19
- import { toAction, toActionProps, toTransition, toTransitionProps } from '../utils/action.utils.js';
20
- import { computeGlassFilter, computeHoverShadowElevation, computeShadowElevation } from '../utils/shadow.utils.js';
21
- import { enterDefaultTransition, leaveDefaultTransition } from '../utils/transition.utils.js';
22
-
23
- /* eslint-disable prefer-const -- necessary for binding checked */
24
- let {
25
- // Snippets
26
- label,
27
- prefix,
28
- suffix,
29
- message,
30
- error,
31
-
32
- // States
33
- id = label ? `neo-input-${crypto.randomUUID()}` : undefined,
34
- ref = $bindable(),
35
- value = $bindable(''),
36
- valid = $bindable(undefined),
37
- dirty = $bindable(false),
38
- touched = $bindable(false),
39
- disabled,
40
- readonly,
41
- loading,
42
- clearable,
43
- dirtyOnInput,
44
- validateOnInput,
45
- position = NeoInputLabelPosition.Inside,
46
-
47
- // Styles
48
- elevation = 3,
49
- hover = -1,
50
- borderless,
51
- rounded,
52
- glass,
53
- start,
54
- floating = true,
55
- skeleton,
56
- validation,
57
-
58
- // Transition
59
- in: inAction,
60
- out: outAction,
61
- transition: transitionAction,
62
-
63
- // Actions
64
- use,
65
-
66
- // Events
67
- oninput,
68
- onfocus,
69
- onblur,
70
- onmark,
71
- onclear,
72
- onchange,
73
- oninvalid,
74
-
75
- // Other props
76
- labelRef = $bindable(),
77
- labelProps,
78
- suffixProps,
79
- suffixTag = suffixProps?.onclick ? 'button' : 'span',
80
- prefixProps,
81
- prefixTag = prefixProps?.onclick ? 'button' : 'span',
82
- containerProps,
83
- containerTag = 'div',
84
- wrapperProps,
85
- wrapperTag = 'div',
86
- messageProps,
87
- messageTag = 'div',
88
- ...rest
89
- }: NeoInputProps = $props();
90
- /* eslint-enable prefer-const */
91
-
92
- let initial = $state(value);
93
- let validationMessage: string | undefined = $state(ref?.validationMessage);
94
-
95
- const filter = $derived.by(() => computeGlassFilter(elevation, glass));
96
- const boxShadow = $derived.by(() => computeShadowElevation(elevation, glass));
97
- const hoverShadow = $derived.by(() => computeHoverShadowElevation(elevation, hover, glass) ?? boxShadow);
98
-
99
- const hoverFlat = $derived(boxShadow.endsWith('flat') && !hoverShadow.endsWith('flat'));
100
- const flatHover = $derived(hoverShadow.endsWith('flat') && !boxShadow.endsWith('flat'));
101
-
102
- let hovered = $state(false);
103
- const onMouseEnter: MouseEventHandler<HTMLDivElement> = e => {
104
- hovered = true;
105
- containerProps?.onmouseenter?.(e);
106
- };
107
-
108
- const onMouseLeave: MouseEventHandler<HTMLDivElement> = e => {
109
- hovered = false;
110
- containerProps?.onmouseleave?.(e);
111
- };
112
-
113
- let focused = $state(false);
114
- const onFocus: FocusEventHandler<HTMLInputElement> = e => {
115
- focused = true;
116
- touched = true;
117
- onfocus?.(e);
118
- };
119
-
120
- const onBlur: FocusEventHandler<HTMLInputElement> = e => {
121
- focused = false;
122
- onblur?.(e);
123
- };
124
-
125
- const checkValidity = (update: { dirty?: boolean; valid?: boolean } = { dirty: true, valid: true }) => {
126
- if (update.dirty) dirty = value !== initial;
127
- if (!update.valid) return;
128
- valid = ref?.checkValidity();
129
- validationMessage = ref?.validationMessage;
130
- };
131
-
132
- const onInput: FormEventHandler<HTMLInputElement> = e => {
133
- checkValidity({ dirty: dirtyOnInput, valid: validateOnInput });
134
- oninput?.(e);
135
- };
136
-
137
- const onChange: FormEventHandler<HTMLInputElement> = e => {
138
- checkValidity();
139
- onchange?.(e);
140
- };
141
-
142
- const onInvalid: EventHandler<Event, HTMLInputElement> = e => {
143
- valid = false;
144
- validationMessage = ref?.validationMessage;
145
- e.preventDefault();
146
- oninvalid?.(e);
147
- };
148
-
149
- /**
150
- * Change the state of the input
151
- * @param state
152
- */
153
- export const mark: NeoInputMethods<HTMLInputElement>['mark'] = (state: NeoInputState) => {
154
- if (state.touched !== undefined) touched = state.touched;
155
- if (state.valid !== undefined) valid = state.valid;
156
- if (state.dirty === undefined) return onmark?.({ touched, dirty, valid, value });
157
- dirty = state.dirty;
158
- if (!dirty) initial = value;
159
- return onmark?.({ touched, dirty, valid, value });
160
- };
161
-
162
- const focus = () => {
163
- if (focused) return;
164
- ref?.focus();
165
- };
166
-
167
- /**
168
- * Clear the input state
169
- */
170
- export const clear: NeoInputMethods<HTMLInputElement>['clear'] = (state?: NeoInputState) => {
171
- value = '';
172
- focus();
173
- if (!state) {
174
- setTimeout(() => checkValidity());
175
- return onclear?.({ touched, dirty, valid, value });
176
- }
177
- initial = value;
178
- setTimeout(() => mark({ touched: false, dirty: false, ...state }));
179
- return onclear?.({ touched, dirty, valid, value });
180
- };
181
-
182
- const affix = $derived(clearable || loading !== undefined || validation);
183
- const close = $derived(clearable && (focused || hovered) && value?.length && !disabled && !readonly);
184
- const isFloating = $derived(floating && !focused && !value?.length && !disabled && !readonly);
185
-
186
- let labelHeight = $state<string>();
187
- let labelWidth = $state<string>();
188
-
189
- let first = $state(true);
190
- // Skip enter transition on first render for floating label
191
- const waitForTick = async () => {
192
- if (!first) return;
193
- await wait();
194
- first = false;
195
- };
196
-
197
- $effect(() => {
198
- if (first) waitForTick();
199
- if (!labelRef) return;
200
- if (position === NeoInputLabelPosition.Inside && !floating) return;
201
- labelHeight = `${labelRef?.clientHeight ?? 0}px`;
202
- if (position === NeoInputLabelPosition.Left || position === NeoInputLabelPosition.Right) return;
203
- labelWidth = `${labelRef?.clientWidth ?? 0}px`;
204
- });
205
-
206
- const errorMessage = $derived.by(() => {
207
- if (valid || valid === undefined) return;
208
- if (error) return error;
209
- if (!validation) return;
210
- return error ?? validationMessage;
211
- });
212
-
213
- const showMessage = $derived(message || errorMessage || error || validation);
214
- const messageId = $derived(showMessage ? (messageProps?.id ?? `neo-input-message-${crypto.randomUUID()}`) : undefined);
215
-
216
- const context = $derived<NeoInputContext<HTMLInputElement>>({
217
- // Ref
218
- ref,
219
-
220
- // Methods
221
- mark,
222
- clear,
223
-
224
- // State
225
- value,
226
- touched,
227
- dirty,
228
- valid,
229
- readonly,
230
- disabled,
231
-
232
- // Styles
233
- elevation,
234
- hover,
235
- borderless,
236
- rounded,
237
- glass,
238
- start,
239
- skeleton,
240
- });
241
-
242
- const inFn = $derived(toTransition(inAction ?? transitionAction));
243
- const inProps = $derived(toTransitionProps(inAction ?? transitionAction));
244
- const outFn = $derived(toTransition(outAction ?? transitionAction));
245
- const outProps = $derived(toTransitionProps(outAction ?? transitionAction));
246
-
247
- const useFn = $derived(toAction(use));
248
- const useProps = $derived(toActionProps(use));
249
- </script>
250
-
251
- {#snippet before()}
252
- {#if prefix}
253
- <svelte:element this={prefixTag} class:neo-input-prefix={true} {disabled} {readonly} {...prefixProps}>
254
- {@render prefix(context)}
255
- </svelte:element>
256
- {/if}
257
- {/snippet}
258
-
259
- {#snippet after()}
260
- <!-- Affix (loafing, clear, placeholder) -->
261
- {#if affix}
262
- <span class="neo-input-affix" class:suffix role="none" onclick={focus}>
263
- {#if loading}
264
- <span out:fade={enterDefaultTransition}>
265
- <IconCircleLoading width="1.1875rem" height="1.1875rem" />
266
- </span>
267
- {:else if close}
268
- <button class="neo-input-clear" aria-label="clear" in:fade out:fade={enterDefaultTransition} onclick={() => clear()}>
269
- <IconClear width="1.1875rem" height="1.1875rem" />
270
- </button>
271
- {:else}
272
- <span class="neo-input-affix-validation" in:fade={leaveDefaultTransition}>
273
- {#if validation && valid === false}
274
- <IconAlert width="1.1875rem" height="1.1875rem" />
275
- {:else if validation && valid === true && touched}
276
- <IconConfirm width="1.1875rem" height="1.1875rem" />
277
- {/if}
278
- </span>
279
- {/if}
280
- </span>
281
- {/if}
282
- <!-- Suffix -->
283
- {#if suffix}
284
- <svelte:element this={suffixTag} class:neo-input-suffix={true} {disabled} {readonly} {...suffixProps}>
285
- {@render suffix(context)}
286
- </svelte:element>
287
- {/if}
288
- {/snippet}
289
-
290
- {#snippet input()}
291
- <input
292
- {id}
293
- {disabled}
294
- {readonly}
295
- aria-invalid={valid === undefined ? undefined : !valid}
296
- aria-describedby={messageId}
297
- bind:this={ref}
298
- bind:value
299
- class:neo-input={true}
300
- class:suffix={suffix || affix}
301
- class:prefix
302
- onblur={onBlur}
303
- onfocus={onFocus}
304
- oninput={onInput}
305
- onchange={onChange}
306
- oninvalid={onInvalid}
307
- use:useFn={useProps}
308
- {...rest}
309
- />
310
- {/snippet}
311
-
312
- {#snippet inputGroup()}
313
- <svelte:element
314
- this={containerTag}
315
- role="none"
316
- data-position={position}
317
- data-touched={touched}
318
- data-dirty={dirty}
319
- data-valid={valid}
320
- class:neo-input-group={true}
321
- class:readonly
322
- class:borderless
323
- class:rounded
324
- class:glass
325
- class:hover
326
- class:start
327
- class:skeleton
328
- class:validation
329
- class:disabled
330
- class:raised={elevation > 3 || elevation + hover > 3}
331
- class:inset={elevation < -3 || elevation + hover < -3}
332
- class:flat={!elevation}
333
- class:hover-flat={hoverFlat}
334
- class:flat-hover={flatHover}
335
- style:--neo-input-glass-blur={filter}
336
- style:--neo-input-box-shadow={boxShadow}
337
- style:--neo-input-hover-shadow={hoverShadow}
338
- style:--neo-input-label-height={labelHeight}
339
- style:--neo-input-label-width={labelWidth}
340
- out:outFn={outProps}
341
- in:inFn={inProps}
342
- onmouseenter={onMouseEnter}
343
- onmouseleave={onMouseLeave}
344
- {...containerProps}
345
- >
346
- {@render before()}
347
- {#if label}
348
- <div class="neo-input-label-container" class:prefix class:floating={isFloating} role="none" onclick={focus}>
349
- <label
350
- bind:this={labelRef}
351
- for={id}
352
- class:neo-input-label={true}
353
- class:first
354
- class:prefix
355
- class:rounded
356
- class:required={rest.required}
357
- {...labelProps}
358
- >
359
- {#if typeof label === 'string'}
360
- {label}
361
- {:else}
362
- {@render label(context)}
363
- {/if}
364
- </label>
365
- {@render input()}
366
- </div>
367
- {:else}
368
- {@render input()}
369
- {/if}
370
- {@render after()}
371
- </svelte:element>
372
- {/snippet}
373
-
374
- {#if showMessage}
375
- <NeoValidation
376
- tag={wrapperTag}
377
- error={errorMessage}
378
- {context}
379
- {message}
380
- {messageId}
381
- {messageTag}
382
- {messageProps}
383
- in={inAction}
384
- out={outAction}
385
- transition={transitionAction}
386
- {...wrapperProps}
387
- >
388
- {@render inputGroup()}
389
- </NeoValidation>
390
- {:else}
391
- {@render inputGroup()}
392
- {/if}
393
-
394
- <style>.neo-input-group,
395
- .neo-input,
396
- .neo-input-clear,
397
- .neo-input-affix,
398
- .neo-input-prefix,
399
- .neo-input-suffix {
400
- display: flex;
401
- box-sizing: border-box;
402
- font: inherit;
403
- text-decoration: none;
404
- outline: none;
405
- transition: color 0.3s ease, margin 0.3s ease, padding 0.3s ease, background-color 0.3s ease, backdrop-filter 0.3s ease, border-color 0.3s ease, border-radius 0.3s ease, box-shadow 0.3s ease-out;
406
- }
407
-
408
- .neo-input {
409
- flex: 1 1 auto;
410
- align-self: center;
411
- min-width: fit-content;
412
- max-width: 100%;
413
- min-height: fit-content;
414
- padding: 0.75rem;
415
- color: inherit;
416
- text-overflow: ellipsis;
417
- background-color: transparent;
418
- border: none;
419
- border-radius: var(--neo-input-border-radius, var(--neo-border-radius));
420
- outline: none;
421
- }
422
- .neo-input-prefix, .neo-input-suffix, .neo-input-affix {
423
- align-items: center;
424
- }
425
- .neo-input-prefix {
426
- color: var(--neo-input-prefix-color, inherit);
427
- background-color: var(--neo-input-prefix-bg-color, transparent);
428
- border: none;
429
- border-right: var(--neo-border-width, 1px) var(--neo-input-prefix-border-color, transparent) solid;
430
- border-radius: var(--neo-input-border-radius, var(--neo-border-radius)) 0 0 var(--neo-input-border-radius, var(--neo-border-radius));
431
- }
432
- .neo-input.prefix {
433
- margin-left: -0.9rem;
434
- }
435
- .neo-input.suffix {
436
- margin-right: -0.9rem;
437
- }
438
- .neo-input-suffix {
439
- color: var(--neo-input-suffix-color, inherit);
440
- background-color: var(--neo-input-suffix-bg-color, transparent);
441
- border: none;
442
- border-left: var(--neo-border-width, 1px) var(--neo-input-suffix-border-color, transparent) solid;
443
- border-radius: 0 var(--neo-input-border-radius, var(--neo-border-radius)) var(--neo-input-border-radius, var(--neo-border-radius)) 0;
444
- }
445
- .neo-input-affix {
446
- display: inline-grid;
447
- grid-template-areas: "affix";
448
- min-width: 2.75rem;
449
- min-height: calc(var(--neo-line-height) + 1rem);
450
- padding: 0.75rem;
451
- border: none;
452
- border-left: var(--neo-border-width, 1px) var(--neo-input-suffix-border-color, transparent) solid;
453
- }
454
- .neo-input-affix > * {
455
- grid-area: affix;
456
- }
457
- .neo-input-affix-validation {
458
- width: 100%;
459
- height: 100%;
460
- }
461
- .neo-input-affix.suffix {
462
- min-width: 2rem;
463
- margin-right: -0.25rem;
464
- padding-right: 0;
465
- }
466
- .neo-input::placeholder {
467
- color: var(--neo-input-placeholder-color, var(--neo-text-color-disabled));
468
- transition: opacity 0.3s ease;
469
- }
470
- .neo-input:read-only {
471
- cursor: initial;
472
- }
473
- .neo-input:disabled {
474
- color: var(--neo-text-color-disabled);
475
- cursor: not-allowed;
476
- }
477
-
478
- .neo-input-prefix:is(button, a),
479
- .neo-input-suffix:is(button, a), .neo-input-clear {
480
- cursor: pointer;
481
- }
482
- .neo-input-prefix:focus-visible:is(button, a),
483
- .neo-input-suffix:focus-visible:is(button, a), .neo-input-clear:focus-visible {
484
- color: var(--neo-input-focus-color, var(--neo-text-color-focused));
485
- }
486
- .neo-input-prefix:hover:is(button, a),
487
- .neo-input-suffix:hover:is(button, a), .neo-input-clear:hover {
488
- color: var(--neo-input-hover-color, var(--neo-text-color-hover));
489
- }
490
- .neo-input-prefix:active:is(button, a),
491
- .neo-input-suffix:active:is(button, a), .neo-input-clear:active {
492
- color: var(--neo-input-active-color, var(--neo-text-color-hover-active));
493
- scale: 0.9;
494
- }
495
- .neo-input-prefix:disabled:is(button, a),
496
- .neo-input-suffix:disabled:is(button, a), .neo-input-clear:disabled {
497
- color: var(--neo-text-color-disabled);
498
- cursor: not-allowed;
499
- scale: 1;
500
- }
501
-
502
- .neo-input-clear {
503
- align-items: center;
504
- justify-content: center;
505
- color: var(--neo-input-clear-color, inherit);
506
- background-color: var(--neo-background-color-darker);
507
- border: none;
508
- border-radius: 50%;
509
- aspect-ratio: 1;
510
- }
511
- .neo-input-clear:focus-visible {
512
- color: var(--neo-close-color-focused, rgba(255, 0, 0, 0.75));
513
- background-color: var(--neo-close-bg-color-focused, rgba(255, 0, 0, 0.05));
514
- }
515
- .neo-input-clear:hover {
516
- color: var(--neo-color-warning, rgba(255, 0, 0, 0.75));
517
- background-color: var(--neo-close-bg-color-focused, rgba(255, 0, 0, 0.05));
518
- }
519
- .neo-input-clear:disabled {
520
- color: var(--neo-text-color-disabled);
521
- cursor: not-allowed;
522
- }
523
-
524
- .neo-input-prefix,
525
- .neo-input-suffix {
526
- padding: 0.75rem;
527
- }
528
- .neo-input-label-container {
529
- display: flex;
530
- flex: 1 1 auto;
531
- flex-direction: column;
532
- width: 100%;
533
- }
534
- .neo-input-label-container .neo-input-label {
535
- display: flex;
536
- min-height: var(--neo-input-label-height);
537
- padding: 0 0.75rem;
538
- overflow: hidden;
539
- color: var(--neo-input-label-color, inherit);
540
- text-wrap: stable;
541
- text-overflow: ellipsis;
542
- cursor: inherit;
543
- transition: padding 0.3s ease, color 0.3s ease, font-size 0.3s ease, line-height 0.3s ease, top 0.3s ease, left 0.3s ease, right 0.3s ease, translate 0.3s ease;
544
- }
545
- .neo-input-label-container .neo-input-label.first {
546
- transition: none;
547
- }
548
- .neo-input-label-container .neo-input-label.required::after {
549
- margin-left: 0.1rem;
550
- color: var(--neo-input-required-color, var(--neo-color-error-75));
551
- font-size: var(--neo-font-size);
552
- content: "*";
553
- }
554
- .neo-input-label-container.floating .neo-input-label {
555
- color: var(--neo-input-floating-label-color, var(--neo-text-color-disabled));
556
- translate: 0 calc(50% + 0.7rem - var(--neo-input-label-height) / 2);
557
- }
558
- .neo-input-label-container.floating .neo-input-label.required::after {
559
- color: var(--neo-input-required-color, var(--neo-color-error-50));
560
- }
561
- .neo-input-label-container.floating ::placeholder {
562
- opacity: 0;
563
- }
564
-
565
- .neo-input-group {
566
- position: relative;
567
- margin: var(--neo-shadow-margin, 0.6rem);
568
- color: var(--neo-input-text-color, inherit);
569
- background-color: var(--neo-input-bg-color, inherit);
570
- border: var(--neo-border-width, 1px) var(--neo-input-border-color, transparent) solid;
571
- border-radius: var(--neo-input-border-radius, var(--neo-border-radius));
572
- box-shadow: var(--neo-input-box-shadow, var(--neo-box-shadow-flat));
573
- cursor: text;
574
- }
575
- .neo-input-group.readonly {
576
- cursor: initial;
577
- }
578
- .neo-input-group.borderless {
579
- border-color: transparent !important;
580
- }
581
- .neo-input-group.raised {
582
- margin: var(--neo-shadow-margin-lg, 1.125rem);
583
- }
584
- .neo-input-group.inset {
585
- padding: 0.25rem;
586
- }
587
- .neo-input-group.hover.flat-hover:hover, .neo-input-group.hover.flat-hover:focus-within, .neo-input-group.flat:not(.borderless, .hover-flat:hover, .hover-flat:focus-within) {
588
- border-color: var(--neo-input-border-color, var(--neo-border-color));
589
- }
590
- .neo-input-group:focus-within, .neo-input-group.hover:hover {
591
- box-shadow: var(--neo-input-hover-shadow, var(--neo-box-shadow-flat));
592
- }
593
- .neo-input-group.disabled {
594
- box-shadow: var(--neo-box-shadow-flat) !important;
595
- opacity: var(--neo-input-opacity-disabled, var(--neo-opacity-disabled));
596
- }
597
- .neo-input-group.disabled:not(.borderless) {
598
- border-color: var(--neo-btn-border-color-disabled, var(--neo-border-color-disabled)) !important;
599
- }
600
- .neo-input-group.disabled .neo-input-label {
601
- color: unset;
602
- }
603
- .neo-input-group.rounded {
604
- border-radius: var(--neo-input-border-radius-lg, var(--neo-border-radius-lg));
605
- }
606
- .neo-input-group.rounded .neo-input {
607
- padding: 0.75rem 1rem;
608
- border-radius: var(--neo-input-border-radius-lg, var(--neo-border-radius-lg));
609
- }
610
- .neo-input-group.rounded .neo-input.prefix {
611
- margin-left: -1.25rem;
612
- }
613
- .neo-input-group.rounded .neo-input-prefix {
614
- padding: 0.75rem 0.75rem 0.75rem 1rem;
615
- }
616
- .neo-input-group.rounded .neo-input.suffix {
617
- margin-right: -1.25rem;
618
- }
619
- .neo-input-group.rounded .neo-input-suffix {
620
- padding: 0.75rem 1rem 0.75rem 0.75rem;
621
- }
622
- .neo-input-group.rounded .neo-input-affix:not(.suffix) {
623
- margin-right: 0.25rem;
624
- }
625
- .neo-input-group.rounded .neo-input-label-container:not(.prefix) {
626
- padding-left: 0.5rem;
627
- }
628
- .neo-input-group.rounded .neo-input-label-container .neo-input-label {
629
- padding: 0 1rem;
630
- }
631
- .neo-input-group[data-position=top] {
632
- --neo-input-margin-top: calc(var(--neo-shadow-margin, 0.6rem) + var(--neo-input-label-height, var(--neo-line-height)));
633
- margin-top: var(--neo-input-margin-top);
634
- }
635
- .neo-input-group[data-position=top] .neo-input-label-container .neo-input-label {
636
- position: absolute;
637
- top: calc(0% - var(--neo-input-margin-top));
638
- }
639
- .neo-input-group[data-position=left] {
640
- --neo-input-margin-left: calc(var(--neo-shadow-margin, 0.6rem) + var(--neo-input-label-width, auto));
641
- margin-left: var(--neo-input-margin-left);
642
- }
643
- .neo-input-group[data-position=left] .neo-input-label-container .neo-input-label {
644
- position: absolute;
645
- top: calc(50% - var(--neo-input-label-height) / 2);
646
- left: calc(0% - var(--neo-input-margin-left));
647
- }
648
- .neo-input-group[data-position=right] {
649
- --neo-input-margin-right: calc(var(--shadow-margin, 0.6rem) + var(--neo-input-label-width, auto));
650
- margin-right: var(--neo-input-margin-right);
651
- }
652
- .neo-input-group[data-position=right] .neo-input-label-container .neo-input-label {
653
- position: absolute;
654
- top: calc(50% - var(--neo-input-label-height) / 2);
655
- right: calc(0% - var(--neo-input-margin-right));
656
- }
657
- .neo-input-group[data-position=inside] .neo-input-label-container .neo-input {
658
- padding: 0 1rem 0.5rem;
659
- }
660
- .neo-input-group[data-position=inside] .neo-input-label-container .neo-input-label {
661
- padding: 0.75rem 1rem 0.2rem;
662
- line-height: var(--neo-line-height-xs, 1rem);
663
- }
664
- .neo-input-group[data-position=inside] .neo-input-label-container .neo-input-label.prefix {
665
- padding-left: 0.15rem;
666
- }
667
- .neo-input-group[data-position=inside] .neo-input-label-container:not(.floating) .neo-input-label {
668
- font-size: var(--neo-font-size-sm, 0.875rem);
669
- }
670
- .neo-input-group[data-position=top] .neo-input-label-container.floating .neo-input-label, .neo-input-group[data-position=left] .neo-input-label-container.floating .neo-input-label, .neo-input-group[data-position=right] .neo-input-label-container.floating .neo-input-label {
671
- top: calc(50% - 0.65rem - var(--neo-input-label-height) / 2);
672
- }
673
- .neo-input-group[data-position=left] .neo-input-label-container.floating .neo-input-label {
674
- left: 0.5rem;
675
- }
676
- .neo-input-group[data-position=right] .neo-input-label-container.floating .neo-input-label {
677
- right: calc(100% - var(--neo-input-label-width) - 0.5rem);
678
- }
679
- .neo-input-group.glass {
680
- --neo-skeleton-color: var(--neo-glass-skeleton-color);
681
- background-color: var(--neo-input-bg-color, var(--neo-glass-background-color));
682
- border-color: var(--neo-input-border-color, var(--neo-glass-top-border-color) var(--neo-glass-right-border-color) var(--neo-glass-bottom-border-color) var(--neo-glass-left-border-color));
683
- backdrop-filter: var(--neo-input-glass-blur, var(--neo-blur-4) var(--neo-saturate-2));
684
- }
685
- .neo-input-group.validation[data-valid=false] {
686
- --neo-input-label-color: var(--neo-input-label-color-error, var(--neo-color-error));
687
- --neo-input-floating-label-color: var(--neo-input-floating-label-color-error, var(--neo-color-error-50));
688
- }
689
- .neo-input-group.validation[data-valid=false] .neo-input-affix-validation {
690
- color: var(--neo-input-validation-color-error, var(--neo-color-error));
691
- }
692
- .neo-input-group.validation[data-valid=true] {
693
- --neo-input-label-color: var(--neo-input-label-color-success, var(--neo-color-success));
694
- --neo-input-floating-label-color: var(--neo-input-floating-label-color-success, var(--neo-color-success-50));
695
- }
696
- .neo-input-group.validation[data-valid=true] .neo-input-affix-validation {
697
- color: var(--neo-input-validation-color-success, var(--neo-color-success));
698
- }
699
- @starting-style {
700
- .neo-input-group.start {
701
- box-shadow: var(--neo-box-shadow-flat);
702
- }
703
- .neo-input-group.start:not(.borderless) {
704
- border-color: var(--neo-input-border-color, var(--neo-border-color));
705
- }
706
- }
707
- .neo-input-group.skeleton {
708
- box-shadow: var(--neo-box-shadow-flat);
709
- pointer-events: none;
710
- --neo-skeleton-color-start: var(--neo-skeleton-color);
711
- --neo-skeleton-color-end: oklch(from var(--neo-skeleton-color) calc(l - var(--neo-skeleton-color-step, 0.05)) c h);
712
- color: var(--neo-skeleton-color-start);
713
- background-color: var(--neo-skeleton-color-start);
714
- border-color: var(--neo-skeleton-color-start);
715
- transition: background-color 1s ease, color 1s ease, border-color 1s ease;
716
- animation: skeleton 3s var(--neo-transition-skeleton) infinite;
717
- animation-delay: 1s;
718
- }
719
- .neo-input-group.skeleton::before, .neo-input-group.skeleton::after,
720
- .neo-input-group.skeleton :global(> *::before),
721
- .neo-input-group.skeleton :global(> *::after),
722
- .neo-input-group.skeleton :global(> *) {
723
- visibility: hidden;
724
- pointer-events: none;
725
- }
726
- @keyframes skeleton {
727
- 0% {
728
- color: var(--neo-skeleton-color-start);
729
- background-color: var(--neo-skeleton-color-start);
730
- border-color: var(--neo-skeleton-color-start);
731
- }
732
- 40% {
733
- color: var(--neo-skeleton-color-end);
734
- background-color: var(--neo-skeleton-color-end);
735
- border-color: var(--neo-skeleton-color-end);
736
- }
737
- 80% {
738
- color: var(--neo-skeleton-color-start);
739
- background-color: var(--neo-skeleton-color-start);
740
- border-color: var(--neo-skeleton-color-start);
741
- }
742
- 100% {
743
- color: var(--neo-skeleton-color-start);
744
- background-color: var(--neo-skeleton-color-start);
745
- border-color: var(--neo-skeleton-color-start);
746
- }
747
- }
748
- .neo-input-group.skeleton.glass {
749
- --neo-skeleton-color: var(--neo-glass-skeleton-color);
750
- }</style>