@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,4 +1,4 @@
1
- import { type NeoInputMethods, type NeoTextareaProps } from './neo-input.model.js';
1
+ import { type NeoInputMethods, type NeoTextareaProps } from './common/neo-input.model.js';
2
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
3
  new (options: import('svelte').ComponentConstructorOptions<Props>): import('svelte').SvelteComponent<Props, Events, Slots> & {
4
4
  $$bindings?: Bindings;
@@ -22,6 +22,9 @@ declare const NeoTextarea: $$__sveltets_2_IsomorphicComponent<NeoTextareaProps,
22
22
  /**
23
23
  * Clear the input state
24
24
  */ clear: NeoInputMethods<HTMLTextAreaElement>["clear"];
25
- }, "value" | "ref" | "valid" | "dirty" | "touched" | "labelRef">;
25
+ /**
26
+ * Change the value of the input
27
+ */ change: NeoInputMethods<HTMLTextAreaElement>["change"];
28
+ }, "value" | "ref" | "hovered" | "focused" | "touched" | "dirty" | "valid" | "labelRef" | "afterRef">;
26
29
  type NeoTextarea = InstanceType<typeof NeoTextarea>;
27
30
  export default NeoTextarea;
@@ -0,0 +1,166 @@
1
+ <script lang="ts">
2
+ import { fade } from 'svelte/transition';
3
+
4
+ import type { NeoAffixProps } from './neo-affix.model.js';
5
+
6
+ import IconAlert from '../../icons/IconAlert.svelte';
7
+ import IconCircleLoading from '../../icons/IconCircleLoading.svelte';
8
+ import IconClear from '../../icons/IconClear.svelte';
9
+ import IconConfirm from '../../icons/IconConfirm.svelte';
10
+ import { leaveDefaultTransition } from '../../utils/transition.utils.js';
11
+
12
+ /* eslint-disable prefer-const -- necessary for binding checked */
13
+ let {
14
+ // States
15
+ ref = $bindable(),
16
+ loading,
17
+ close,
18
+ valid,
19
+ skeleton,
20
+ disabled,
21
+
22
+ // Styles
23
+ size = '1.25rem',
24
+
25
+ // Other props
26
+ closeProps,
27
+ ...rest
28
+ }: NeoAffixProps = $props();
29
+ /* eslint-enable prefer-const */
30
+
31
+ const leave = $derived(!loading && !close && valid === undefined ? undefined : leaveDefaultTransition);
32
+ </script>
33
+
34
+ <span bind:this={ref} class:neo-affix-container={true} class:neo-skeleton={skeleton} style:--neo-affix-size={size} role="none" {...rest}>
35
+ {#if loading}
36
+ <span class="neo-affix-loading" out:fade={leave}>
37
+ <IconCircleLoading width={size} height={size} />
38
+ </span>
39
+ {:else if close && !disabled}
40
+ <button {disabled} class:neo-affix-clear={true} aria-label="clear" in:fade out:fade={leave} {...closeProps}>
41
+ <IconClear width={size} height={size} />
42
+ </button>
43
+ {:else}
44
+ <span class="neo-affix-validation" data-valid={valid} in:fade={leave}>
45
+ {#if valid !== undefined}
46
+ {#if valid}
47
+ <IconConfirm width={size} height={size} />
48
+ {:else}
49
+ <IconAlert width={size} height={size} />
50
+ {/if}
51
+ {/if}
52
+ </span>
53
+ {/if}
54
+ </span>
55
+
56
+ <style>.neo-affix-validation,
57
+ .neo-affix-loading,
58
+ .neo-affix-clear {
59
+ display: inline-flex;
60
+ box-sizing: border-box;
61
+ width: var(--neo-affix-size, 1.25rem);
62
+ height: var(--neo-affix-size, 1.25rem);
63
+ font: inherit;
64
+ text-decoration: none;
65
+ outline: none;
66
+ }
67
+
68
+ .neo-affix-container {
69
+ display: inline-grid;
70
+ grid-template-areas: "affix";
71
+ align-items: center;
72
+ box-sizing: border-box;
73
+ min-width: max-content;
74
+ min-height: max-content;
75
+ padding: var(--neo-affix-padding, 0.75rem);
76
+ border: none;
77
+ }
78
+ .neo-affix-container > * {
79
+ grid-area: affix;
80
+ }
81
+ .neo-affix-container .neo-affix-validation {
82
+ display: inline-flex;
83
+ align-items: center;
84
+ }
85
+ .neo-affix-container .neo-affix-validation[data-valid=true] {
86
+ color: var(--neo-affix-validation-color-success, var(--neo-color-success));
87
+ }
88
+ .neo-affix-container .neo-affix-validation[data-valid=false] {
89
+ color: var(--neo-affix-validation-color-error, var(--neo-color-error));
90
+ }
91
+ .neo-affix-container .neo-affix-clear {
92
+ align-items: center;
93
+ justify-content: center;
94
+ margin: 0;
95
+ padding: 0;
96
+ color: var(--neo-affix-clear-color, inherit);
97
+ background-color: var(--neo-background-color-darker);
98
+ border: none;
99
+ border-radius: 50%;
100
+ aspect-ratio: 1;
101
+ cursor: pointer;
102
+ transition: opacity 0.2s ease-in, color 0.3s ease, background-color 0.3s ease;
103
+ }
104
+ .neo-affix-container .neo-affix-clear :global(svg) {
105
+ width: 100%;
106
+ height: 100%;
107
+ margin: -0.05rem;
108
+ padding: 0.05rem;
109
+ }
110
+ .neo-affix-container .neo-affix-clear:focus-visible {
111
+ color: var(--neo-close-color-focused, rgba(255, 0, 0, 0.5));
112
+ background-color: var(--neo-close-bg-color-focused, rgba(255, 0, 0, 0.05));
113
+ }
114
+ .neo-affix-container .neo-affix-clear:hover {
115
+ color: var(--neo-close-color-hover, rgba(255, 0, 0, 0.75));
116
+ background-color: var(--neo-close-bg-color-hover, rgba(255, 0, 0, 0.07));
117
+ }
118
+ .neo-affix-container .neo-affix-clear:active {
119
+ color: var(--neo-affix-active-color, var(--neo-text-color-hover-active));
120
+ scale: 0.9;
121
+ }
122
+ .neo-affix-container .neo-affix-clear:disabled {
123
+ color: var(--neo-text-color-disabled);
124
+ cursor: not-allowed;
125
+ scale: 1;
126
+ }
127
+ .neo-affix-container.neo-skeleton > * {
128
+ border-radius: 50%;
129
+ --neo-skeleton-color-start: var(--neo-skeleton-color);
130
+ --neo-skeleton-color-end: oklch(from var(--neo-skeleton-color) calc(l - var(--neo-skeleton-color-step, 0.05)) c h);
131
+ color: var(--neo-skeleton-color-start);
132
+ background-color: var(--neo-skeleton-color-start);
133
+ border-color: var(--neo-skeleton-color-start);
134
+ transition: background-color 1s ease, color 1s ease, border-color 1s ease;
135
+ animation: skeleton 3s var(--neo-transition-skeleton) infinite;
136
+ animation-delay: 1s;
137
+ }
138
+ .neo-affix-container.neo-skeleton > *::before, .neo-affix-container.neo-skeleton > *::after,
139
+ .neo-affix-container.neo-skeleton > * :global(> *::before),
140
+ .neo-affix-container.neo-skeleton > * :global(> *::after),
141
+ .neo-affix-container.neo-skeleton > * :global(> *) {
142
+ visibility: hidden;
143
+ pointer-events: none;
144
+ }
145
+ @keyframes skeleton {
146
+ 0% {
147
+ color: var(--neo-skeleton-color-start);
148
+ background-color: var(--neo-skeleton-color-start);
149
+ border-color: var(--neo-skeleton-color-start);
150
+ }
151
+ 40% {
152
+ color: var(--neo-skeleton-color-end);
153
+ background-color: var(--neo-skeleton-color-end);
154
+ border-color: var(--neo-skeleton-color-end);
155
+ }
156
+ 80% {
157
+ color: var(--neo-skeleton-color-start);
158
+ background-color: var(--neo-skeleton-color-start);
159
+ border-color: var(--neo-skeleton-color-start);
160
+ }
161
+ 100% {
162
+ color: var(--neo-skeleton-color-start);
163
+ background-color: var(--neo-skeleton-color-start);
164
+ border-color: var(--neo-skeleton-color-start);
165
+ }
166
+ }</style>
@@ -0,0 +1,19 @@
1
+ import type { NeoAffixProps } from './neo-affix.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 NeoAffix: $$__sveltets_2_IsomorphicComponent<NeoAffixProps, {
16
+ [evt: string]: CustomEvent<any>;
17
+ }, {}, {}, "ref">;
18
+ type NeoAffix = InstanceType<typeof NeoAffix>;
19
+ export default NeoAffix;
@@ -0,0 +1,338 @@
1
+ <script lang="ts">
2
+ import { tick } from 'svelte';
3
+
4
+ import type { EventHandler, FocusEventHandler, FormEventHandler } from 'svelte/elements';
5
+
6
+ import type { SvelteEvent } from '../../utils/html-element.utils.js';
7
+
8
+ import { type NeoBaseInputProps, type NeoInputMethods, type NeoInputState, type NeoInputValue } from './neo-input.model.js';
9
+ import { toAction, toActionProps } from '../../utils/action.utils.js';
10
+
11
+ /* eslint-disable prefer-const -- necessary for binding checked */
12
+ let {
13
+ // States
14
+ id,
15
+ ref = $bindable(),
16
+
17
+ files = $bindable(), // type="file"
18
+ value = $bindable(),
19
+ group = $bindable(), // type="radio"
20
+ checked = $bindable(), // type="checkbox"
21
+ indeterminate = $bindable(), // type="checkbox"
22
+
23
+ initial = $bindable(),
24
+ touched = $bindable(false),
25
+ valid = $bindable(),
26
+ dirty = $bindable(false),
27
+ focused = $bindable(false),
28
+ disabled,
29
+ readonly,
30
+ nullable = true,
31
+
32
+ dirtyOnInput,
33
+ dirtyOnBlur,
34
+ validateOnInput,
35
+ validateOnBlur,
36
+ validationMessage = $bindable(),
37
+
38
+ // Styles
39
+ before,
40
+ after,
41
+
42
+ // Actions
43
+ use,
44
+
45
+ // Events
46
+ onblur,
47
+ onfocus,
48
+ oninput,
49
+ onchange,
50
+ oninvalid,
51
+
52
+ onclear,
53
+ onmark,
54
+
55
+ // Other props
56
+ ...rest
57
+ }: NeoBaseInputProps = $props();
58
+ /* eslint-enable prefer-const */
59
+
60
+ const getValue = () => {
61
+ if (rest.type === 'file') return files;
62
+ if (rest.type === 'checkbox' || rest.type === 'radio') return checked;
63
+ return value;
64
+ };
65
+
66
+ const typedValue = $derived(getValue());
67
+ const hasValue = () => {
68
+ if (rest?.type === 'file') return !!files?.length;
69
+ if (rest?.type === 'checkbox' || rest.type === 'radio') return checked !== undefined;
70
+ if (typeof value === 'string') return !!value.length;
71
+ return value !== undefined && value !== null;
72
+ };
73
+ const fallback = () => {
74
+ if (nullable) return value;
75
+ if (rest?.defaultValue === undefined) return value;
76
+ if (rest.type && ['file', 'checkbox', 'radio'].includes(rest.type)) return value;
77
+ if (hasValue()) return value;
78
+ value = rest?.defaultValue;
79
+ return value;
80
+ };
81
+
82
+ const reset = () => {
83
+ if (rest.type === 'checkbox' || rest.type === 'radio') {
84
+ checked = rest?.defaultChecked ?? rest?.defaultValue ?? false;
85
+ if (rest.type === 'checkbox') indeterminate = false;
86
+ return;
87
+ }
88
+ value = nullable ? '' : (rest?.defaultValue ?? '');
89
+ if (rest.type === 'file') files = new DataTransfer().files;
90
+ };
91
+
92
+ const currentState = $derived<NeoInputState<HTMLInputElement>>({ touched, dirty, valid, value: typedValue, initial });
93
+
94
+ const validate: NeoInputMethods<HTMLInputElement>['validate'] = (update: { dirty?: boolean; valid?: boolean } = { dirty: true, valid: true }) => {
95
+ if (update.dirty) dirty = typedValue !== initial;
96
+ if (!update.valid) return { ...currentState };
97
+ valid = ref?.checkValidity();
98
+ validationMessage = ref?.validationMessage;
99
+ return { ...currentState };
100
+ };
101
+
102
+ /**
103
+ * Change the state of the input
104
+ * @param state
105
+ */
106
+ export const mark: NeoInputMethods<HTMLInputElement>['mark'] = (state: NeoInputState<HTMLInputElement>) => {
107
+ if (state.touched !== undefined) touched = state.touched;
108
+ if (state.valid !== undefined) valid = state.valid;
109
+ if (state.dirty === undefined) return onmark?.({ ...currentState });
110
+ dirty = state.dirty;
111
+ if (!dirty) initial = typedValue;
112
+ return onmark?.({ ...currentState });
113
+ };
114
+
115
+ const focus = () => {
116
+ if (focused || disabled || readonly) return;
117
+ ref?.focus();
118
+ };
119
+
120
+ /**
121
+ * Clear the input state
122
+ */
123
+ export const clear: NeoInputMethods<HTMLInputElement>['clear'] = async (
124
+ state?: NeoInputState<HTMLInputElement>,
125
+ event?: InputEvent | SvelteEvent<InputEvent>,
126
+ ) => {
127
+ reset();
128
+ await tick();
129
+ focus();
130
+ if (state) mark({ touched: false, dirty: false, ...state });
131
+ else validate();
132
+ onclear?.({ ...currentState }, event);
133
+ if (event) return ref?.dispatchEvent(event);
134
+ const _event: InputEventInit = { bubbles: true, cancelable: false, data: value, inputType: 'clear' };
135
+ oninput?.(new InputEvent('input', _event) as SvelteEvent<InputEvent, any>);
136
+ };
137
+
138
+ /**
139
+ * Change the state of the input
140
+ */
141
+ export const change: NeoInputMethods<HTMLInputElement>['change'] = (_value: NeoInputValue<HTMLInputElement>, event?: InputEvent) => {
142
+ if (rest.type === 'checkbox' || rest.type === 'radio') {
143
+ checked = !!_value;
144
+ } else {
145
+ value = _value?.toString();
146
+ }
147
+ focus();
148
+ if (event) ref?.dispatchEvent(event);
149
+ return validate();
150
+ };
151
+
152
+ const onFocus: FocusEventHandler<HTMLInputElement> = e => {
153
+ focused = true;
154
+ touched = true;
155
+ onfocus?.(e);
156
+ };
157
+
158
+ const onBlur: FocusEventHandler<HTMLInputElement> = e => {
159
+ focused = false;
160
+ validate({ dirty: dirtyOnBlur, valid: validateOnBlur });
161
+ onblur?.(e);
162
+ };
163
+
164
+ const onInput: FormEventHandler<HTMLInputElement> = e => {
165
+ touched = true;
166
+ validate({ dirty: dirtyOnInput, valid: validateOnInput });
167
+ oninput?.(e);
168
+ };
169
+
170
+ const onChange: FormEventHandler<HTMLInputElement> = e => {
171
+ touched = true;
172
+ validate();
173
+ fallback();
174
+ onchange?.(e);
175
+ };
176
+
177
+ const onInvalid: EventHandler<Event, HTMLInputElement> = e => {
178
+ valid = false;
179
+ validationMessage = ref?.validationMessage;
180
+ e.preventDefault();
181
+ oninvalid?.(e);
182
+ };
183
+
184
+ $effect(() => {
185
+ if (!ref) return;
186
+ Object.assign(ref, { mark, clear, change, validate });
187
+ });
188
+
189
+ $effect(() => {
190
+ if (group === undefined) return;
191
+ checked = !!ref?.checked;
192
+ });
193
+
194
+ const useFn = $derived(toAction(use));
195
+ const useProps = $derived(toActionProps(use));
196
+ </script>
197
+
198
+ {#if rest.type === 'file'}
199
+ <input
200
+ aria-invalid={valid === undefined ? undefined : !valid}
201
+ type="file"
202
+ {id}
203
+ {disabled}
204
+ {readonly}
205
+ bind:this={ref}
206
+ bind:files
207
+ bind:value
208
+ bind:group
209
+ bind:indeterminate
210
+ class:neo-input={true}
211
+ class:neo-after={after}
212
+ class:neo-before={before}
213
+ onblur={onBlur}
214
+ onfocus={onFocus}
215
+ oninput={onInput}
216
+ onchange={onChange}
217
+ oninvalid={onInvalid}
218
+ use:useFn={useProps}
219
+ {...rest}
220
+ />
221
+ {:else if rest.type === 'checkbox'}
222
+ <input
223
+ aria-invalid={valid === undefined ? undefined : !valid}
224
+ type="checkbox"
225
+ {id}
226
+ {disabled}
227
+ {readonly}
228
+ {value}
229
+ bind:this={ref}
230
+ bind:group
231
+ bind:checked
232
+ bind:indeterminate
233
+ class:neo-input={true}
234
+ class:neo-after={after}
235
+ class:neo-before={before}
236
+ onblur={onBlur}
237
+ onfocus={onFocus}
238
+ oninput={onInput}
239
+ onchange={onChange}
240
+ oninvalid={onInvalid}
241
+ use:useFn={useProps}
242
+ {...rest}
243
+ />
244
+ {:else if rest.type === 'radio'}
245
+ <input
246
+ type="radio"
247
+ {id}
248
+ {disabled}
249
+ {readonly}
250
+ {value}
251
+ bind:this={ref}
252
+ bind:group
253
+ bind:indeterminate
254
+ class:neo-input={true}
255
+ class:neo-after={after}
256
+ class:neo-before={before}
257
+ onblur={onBlur}
258
+ onfocus={onFocus}
259
+ oninput={onInput}
260
+ onchange={onChange}
261
+ oninvalid={onInvalid}
262
+ use:useFn={useProps}
263
+ {...rest}
264
+ />
265
+ {:else}
266
+ <input
267
+ aria-invalid={valid === undefined ? undefined : !valid}
268
+ {id}
269
+ {disabled}
270
+ {readonly}
271
+ bind:this={ref}
272
+ bind:value
273
+ bind:group
274
+ bind:indeterminate
275
+ class:neo-input={true}
276
+ class:neo-after={after}
277
+ class:neo-before={before}
278
+ onblur={onBlur}
279
+ onfocus={onFocus}
280
+ oninput={onInput}
281
+ onchange={onChange}
282
+ oninvalid={onInvalid}
283
+ use:useFn={useProps}
284
+ {...rest}
285
+ />
286
+ {/if}
287
+
288
+ <style>.neo-input {
289
+ display: inline-flex;
290
+ flex: 1 1 auto;
291
+ align-self: center;
292
+ box-sizing: border-box;
293
+ width: 100%;
294
+ min-width: var(--neo-input-min-width, 1ch);
295
+ max-width: 100%;
296
+ min-height: var(--neo-input-min-height, fit-content);
297
+ padding: var(--neo-input-padding, 0.75rem);
298
+ color: inherit;
299
+ font: inherit;
300
+ text-decoration: none;
301
+ text-overflow: ellipsis;
302
+ background-color: transparent;
303
+ border: none;
304
+ border-radius: var(--neo-input-border-radius, var(--neo-border-radius));
305
+ outline: none;
306
+ 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;
307
+ }
308
+ .neo-input.neo-before {
309
+ padding-left: 0;
310
+ border-top-left-radius: 0;
311
+ border-bottom-left-radius: 0;
312
+ }
313
+ .neo-input.neo-after {
314
+ padding-right: 0;
315
+ border-top-right-radius: 0;
316
+ border-bottom-right-radius: 0;
317
+ }
318
+ .neo-input::placeholder {
319
+ color: var(--neo-input-placeholder-color, var(--neo-text-color-disabled));
320
+ transition: opacity 0.3s ease;
321
+ }
322
+ .neo-input:read-only {
323
+ cursor: inherit;
324
+ }
325
+ .neo-input:disabled {
326
+ color: var(--neo-text-color-disabled);
327
+ cursor: not-allowed;
328
+ }
329
+ .neo-input[type=password]:not(:placeholder-shown) {
330
+ letter-spacing: 0.2em;
331
+ -webkit-text-stroke-width: 0.15em;
332
+ }
333
+ @supports (-webkit-touch-callout: none) {
334
+ .neo-input[type=password]:not(:placeholder-shown) {
335
+ font: small-caption;
336
+ font-size: var(--neo-font-size-xs, 0.75rem);
337
+ }
338
+ }</style>
@@ -0,0 +1,30 @@
1
+ import { type NeoBaseInputProps, type NeoInputMethods } 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;
12
+ };
13
+ z_$$bindings?: Bindings;
14
+ }
15
+ declare const NeoBaseInput: $$__sveltets_2_IsomorphicComponent<NeoBaseInputProps, {
16
+ [evt: string]: CustomEvent<any>;
17
+ }, {}, {
18
+ /**
19
+ * Change the state of the input
20
+ * @param state
21
+ */ mark: NeoInputMethods<HTMLInputElement>["mark"];
22
+ /**
23
+ * Clear the input state
24
+ */ clear: NeoInputMethods<HTMLInputElement>["clear"];
25
+ /**
26
+ * Change the state of the input
27
+ */ change: NeoInputMethods<HTMLInputElement>["change"];
28
+ }, "value" | "group" | "ref" | "checked" | "focused" | "validationMessage" | "files" | "indeterminate" | "touched" | "dirty" | "valid" | "initial">;
29
+ type NeoBaseInput = InstanceType<typeof NeoBaseInput>;
30
+ export default NeoBaseInput;