@sentropic/design-system-svelte 0.3.0 → 0.4.0

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 (37) hide show
  1. package/dist/Accordion.svelte +187 -0
  2. package/dist/Accordion.svelte.d.ts +20 -0
  3. package/dist/Accordion.svelte.d.ts.map +1 -0
  4. package/dist/Combobox.svelte +390 -0
  5. package/dist/Combobox.svelte.d.ts +28 -0
  6. package/dist/Combobox.svelte.d.ts.map +1 -0
  7. package/dist/DataTable.svelte +543 -0
  8. package/dist/DataTable.svelte.d.ts +50 -0
  9. package/dist/DataTable.svelte.d.ts.map +1 -0
  10. package/dist/MultiSelect.svelte +427 -0
  11. package/dist/MultiSelect.svelte.d.ts +28 -0
  12. package/dist/MultiSelect.svelte.d.ts.map +1 -0
  13. package/dist/NumberInput.svelte +256 -0
  14. package/dist/NumberInput.svelte.d.ts +19 -0
  15. package/dist/NumberInput.svelte.d.ts.map +1 -0
  16. package/dist/PasswordInput.svelte +205 -0
  17. package/dist/PasswordInput.svelte.d.ts +17 -0
  18. package/dist/PasswordInput.svelte.d.ts.map +1 -0
  19. package/dist/ProgressBar.svelte +176 -0
  20. package/dist/ProgressBar.svelte.d.ts +17 -0
  21. package/dist/ProgressBar.svelte.d.ts.map +1 -0
  22. package/dist/Search.svelte +218 -0
  23. package/dist/Search.svelte.d.ts +16 -0
  24. package/dist/Search.svelte.d.ts.map +1 -0
  25. package/dist/Slider.svelte +279 -0
  26. package/dist/Slider.svelte.d.ts +20 -0
  27. package/dist/Slider.svelte.d.ts.map +1 -0
  28. package/dist/Tag.svelte +140 -0
  29. package/dist/Tag.svelte.d.ts +16 -0
  30. package/dist/Tag.svelte.d.ts.map +1 -0
  31. package/dist/Toggle.svelte +135 -0
  32. package/dist/Toggle.svelte.d.ts +14 -0
  33. package/dist/Toggle.svelte.d.ts.map +1 -0
  34. package/dist/index.d.ts +15 -0
  35. package/dist/index.d.ts.map +1 -1
  36. package/dist/index.js +11 -0
  37. package/package.json +2 -2
@@ -0,0 +1,19 @@
1
+ import type { HTMLInputAttributes } from "svelte/elements";
2
+ type NumberInputProps = Omit<HTMLInputAttributes, "class" | "size" | "type" | "value"> & {
3
+ label?: string;
4
+ helperText?: string;
5
+ errorText?: string;
6
+ invalid?: boolean;
7
+ size?: "sm" | "md" | "lg";
8
+ value?: number | null;
9
+ min?: number;
10
+ max?: number;
11
+ step?: number;
12
+ incrementLabel?: string;
13
+ decrementLabel?: string;
14
+ class?: string;
15
+ };
16
+ declare const NumberInput: import("svelte").Component<NumberInputProps, {}, "value">;
17
+ type NumberInput = ReturnType<typeof NumberInput>;
18
+ export default NumberInput;
19
+ //# sourceMappingURL=NumberInput.svelte.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"NumberInput.svelte.d.ts","sourceRoot":"","sources":["../src/lib/NumberInput.svelte.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,iBAAiB,CAAC;AAGzD,KAAK,gBAAgB,GAAG,IAAI,CAAC,mBAAmB,EAAE,OAAO,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC,GAAG;IACvF,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,IAAI,CAAC,EAAE,IAAI,GAAG,IAAI,GAAG,IAAI,CAAC;IAC1B,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,CAAC;AAkFJ,QAAA,MAAM,WAAW,2DAAwC,CAAC;AAC1D,KAAK,WAAW,GAAG,UAAU,CAAC,OAAO,WAAW,CAAC,CAAC;AAClD,eAAe,WAAW,CAAC"}
@@ -0,0 +1,205 @@
1
+ <script lang="ts">
2
+ import type { HTMLInputAttributes } from "svelte/elements";
3
+
4
+ type PasswordInputProps = Omit<HTMLInputAttributes, "class" | "size" | "type" | "value"> & {
5
+ label?: string;
6
+ helperText?: string;
7
+ errorText?: string;
8
+ invalid?: boolean;
9
+ size?: "sm" | "md" | "lg";
10
+ value?: string;
11
+ showLabel?: string;
12
+ hideLabel?: string;
13
+ visible?: boolean;
14
+ class?: string;
15
+ };
16
+
17
+ let {
18
+ label,
19
+ helperText,
20
+ errorText,
21
+ invalid = false,
22
+ size = "md",
23
+ value = $bindable(""),
24
+ showLabel = "Show password",
25
+ hideLabel = "Hide password",
26
+ visible = $bindable(false),
27
+ disabled,
28
+ class: className,
29
+ ...rest
30
+ }: PasswordInputProps = $props();
31
+
32
+ const fieldClasses = () => ["st-field", className].filter(Boolean).join(" ");
33
+ const groupClasses = () => ["st-passwordInput", `st-passwordInput--${size}`].join(" ");
34
+ const isInvalid = () => invalid || Boolean(errorText);
35
+
36
+ function toggle() {
37
+ visible = !visible;
38
+ }
39
+ </script>
40
+
41
+ <div class={fieldClasses()}>
42
+ <label class="st-field__control">
43
+ {#if label}<span class="st-field__label">{label}</span>{/if}
44
+ <span class={groupClasses()}>
45
+ <input
46
+ {...rest}
47
+ type={visible ? "text" : "password"}
48
+ class="st-passwordInput__control"
49
+ bind:value
50
+ {disabled}
51
+ aria-invalid={isInvalid() ? "true" : undefined}
52
+ autocomplete="current-password"
53
+ />
54
+ <button
55
+ type="button"
56
+ class="st-passwordInput__toggle"
57
+ aria-label={visible ? hideLabel : showLabel}
58
+ aria-pressed={visible ? "true" : "false"}
59
+ {disabled}
60
+ onclick={toggle}
61
+ >
62
+ {#if visible}
63
+ <svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.4" width="16" height="16" aria-hidden="true">
64
+ <path d="M2 8s2-4 6-4 6 4 6 4-2 4-6 4-6-4-6-4Z" />
65
+ <circle cx="8" cy="8" r="2" />
66
+ <path d="M2 2l12 12" stroke-linecap="round" />
67
+ </svg>
68
+ {:else}
69
+ <svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.4" width="16" height="16" aria-hidden="true">
70
+ <path d="M2 8s2-4 6-4 6 4 6 4-2 4-6 4-6-4-6-4Z" />
71
+ <circle cx="8" cy="8" r="2" />
72
+ </svg>
73
+ {/if}
74
+ </button>
75
+ </span>
76
+ </label>
77
+ {#if errorText}
78
+ <span class="st-field__error">{errorText}</span>
79
+ {:else if helperText}
80
+ <span class="st-field__help">{helperText}</span>
81
+ {/if}
82
+ </div>
83
+
84
+ <style>
85
+ .st-field {
86
+ color: var(--st-component-field-labelText, var(--st-semantic-text-primary));
87
+ display: grid;
88
+ gap: var(--st-component-field-gap, 0.5rem);
89
+ max-width: var(--st-component-field-maxWidth, 28rem);
90
+ }
91
+
92
+ .st-field__control {
93
+ display: grid;
94
+ gap: var(--st-component-field-gap, 0.5rem);
95
+ }
96
+
97
+ .st-field__label {
98
+ font-size: 0.875rem;
99
+ font-weight: 600;
100
+ }
101
+
102
+ .st-field__help,
103
+ .st-field__error {
104
+ font-size: 0.8125rem;
105
+ line-height: 1.4;
106
+ }
107
+
108
+ .st-field__help {
109
+ color: var(--st-component-field-helpText, var(--st-semantic-text-secondary));
110
+ }
111
+
112
+ .st-field__error {
113
+ color: var(--st-component-field-errorText, var(--st-semantic-feedback-error));
114
+ }
115
+
116
+ .st-passwordInput {
117
+ align-items: center;
118
+ background: var(--st-component-control-background, var(--st-semantic-surface-default));
119
+ border: 1px solid var(--st-component-control-border, var(--st-semantic-border-subtle));
120
+ border-radius: var(--st-component-control-radius, 0.375rem);
121
+ color: var(--st-component-control-text, var(--st-semantic-text-primary));
122
+ display: inline-flex;
123
+ transition:
124
+ border-color var(--st-motion-fast, 120ms) var(--st-motion-easing, ease),
125
+ box-shadow var(--st-motion-fast, 120ms) var(--st-motion-easing, ease);
126
+ width: 100%;
127
+ }
128
+
129
+ .st-passwordInput--sm {
130
+ min-height: var(--st-component-control-smHeight, 2rem);
131
+ }
132
+
133
+ .st-passwordInput--md {
134
+ min-height: var(--st-component-control-mdHeight, 2.5rem);
135
+ }
136
+
137
+ .st-passwordInput--lg {
138
+ min-height: var(--st-component-control-lgHeight, 3rem);
139
+ }
140
+
141
+ .st-passwordInput:hover:not(:has(input:disabled)) {
142
+ border-color: var(--st-component-control-hoverBorder, var(--st-semantic-border-strong));
143
+ }
144
+
145
+ .st-passwordInput:focus-within {
146
+ border-color: var(--st-component-control-focusRing, var(--st-semantic-border-interactive));
147
+ box-shadow: 0 0 0 2px var(--st-component-control-focusRing, var(--st-semantic-border-interactive));
148
+ }
149
+
150
+ .st-passwordInput:has([aria-invalid="true"]) {
151
+ border-color: var(--st-component-control-invalidBorder, var(--st-semantic-feedback-error));
152
+ }
153
+
154
+ .st-passwordInput__control {
155
+ background: transparent;
156
+ border: 0;
157
+ color: inherit;
158
+ flex: 1 1 auto;
159
+ font: inherit;
160
+ min-width: 0;
161
+ padding: 0 0.75rem;
162
+ width: 100%;
163
+ }
164
+
165
+ .st-passwordInput__control:focus {
166
+ outline: none;
167
+ }
168
+
169
+ .st-passwordInput__control::placeholder {
170
+ color: var(--st-component-control-placeholderText, var(--st-semantic-text-muted));
171
+ }
172
+
173
+ .st-passwordInput__control:disabled {
174
+ color: var(--st-component-control-disabledText, var(--st-semantic-text-muted));
175
+ cursor: not-allowed;
176
+ }
177
+
178
+ .st-passwordInput__toggle {
179
+ align-items: center;
180
+ background: transparent;
181
+ border: 0;
182
+ color: var(--st-semantic-text-secondary);
183
+ cursor: pointer;
184
+ display: inline-flex;
185
+ flex: 0 0 auto;
186
+ font: inherit;
187
+ height: 100%;
188
+ justify-content: center;
189
+ padding: 0 0.625rem;
190
+ transition: background-color var(--st-motion-fast, 120ms) var(--st-motion-easing, ease);
191
+ }
192
+
193
+ .st-passwordInput__toggle:hover:not(:disabled) {
194
+ background: var(--st-component-control-hoverBackground, var(--st-semantic-surface-subtle));
195
+ }
196
+
197
+ .st-passwordInput__toggle:focus-visible {
198
+ outline: 2px solid var(--st-component-control-focusRing, var(--st-semantic-border-interactive));
199
+ outline-offset: -2px;
200
+ }
201
+
202
+ .st-passwordInput__toggle:disabled {
203
+ cursor: not-allowed;
204
+ }
205
+ </style>
@@ -0,0 +1,17 @@
1
+ import type { HTMLInputAttributes } from "svelte/elements";
2
+ type PasswordInputProps = Omit<HTMLInputAttributes, "class" | "size" | "type" | "value"> & {
3
+ label?: string;
4
+ helperText?: string;
5
+ errorText?: string;
6
+ invalid?: boolean;
7
+ size?: "sm" | "md" | "lg";
8
+ value?: string;
9
+ showLabel?: string;
10
+ hideLabel?: string;
11
+ visible?: boolean;
12
+ class?: string;
13
+ };
14
+ declare const PasswordInput: import("svelte").Component<PasswordInputProps, {}, "value" | "visible">;
15
+ type PasswordInput = ReturnType<typeof PasswordInput>;
16
+ export default PasswordInput;
17
+ //# sourceMappingURL=PasswordInput.svelte.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PasswordInput.svelte.d.ts","sourceRoot":"","sources":["../src/lib/PasswordInput.svelte.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,iBAAiB,CAAC;AAGzD,KAAK,kBAAkB,GAAG,IAAI,CAAC,mBAAmB,EAAE,OAAO,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC,GAAG;IACzF,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,IAAI,CAAC,EAAE,IAAI,GAAG,IAAI,GAAG,IAAI,CAAC;IAC1B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,CAAC;AA6DJ,QAAA,MAAM,aAAa,yEAAwC,CAAC;AAC5D,KAAK,aAAa,GAAG,UAAU,CAAC,OAAO,aAAa,CAAC,CAAC;AACtD,eAAe,aAAa,CAAC"}
@@ -0,0 +1,176 @@
1
+ <script lang="ts">
2
+ import type { HTMLAttributes } from "svelte/elements";
3
+
4
+ type ProgressBarProps = Omit<HTMLAttributes<HTMLDivElement>, "class"> & {
5
+ label?: string;
6
+ helperText?: string;
7
+ value?: number;
8
+ max?: number;
9
+ indeterminate?: boolean;
10
+ tone?: "neutral" | "success" | "warning" | "error";
11
+ size?: "sm" | "md" | "lg";
12
+ showValue?: boolean;
13
+ valueText?: string;
14
+ class?: string;
15
+ };
16
+
17
+ let {
18
+ label,
19
+ helperText,
20
+ value = 0,
21
+ max = 100,
22
+ indeterminate = false,
23
+ tone = "neutral",
24
+ size = "md",
25
+ showValue = false,
26
+ valueText,
27
+ class: className,
28
+ ...rest
29
+ }: ProgressBarProps = $props();
30
+
31
+ const wrapperClasses = () => ["st-progressBar", className].filter(Boolean).join(" ");
32
+ const trackClasses = () =>
33
+ [
34
+ "st-progressBar__track",
35
+ `st-progressBar__track--${size}`,
36
+ `st-progressBar__track--${tone}`,
37
+ indeterminate ? "st-progressBar__track--indeterminate" : null
38
+ ]
39
+ .filter(Boolean)
40
+ .join(" ");
41
+
42
+ const clampedValue = () => {
43
+ if (max <= 0) return 0;
44
+ if (value < 0) return 0;
45
+ if (value > max) return max;
46
+ return value;
47
+ };
48
+
49
+ const percent = () => (indeterminate ? 0 : (clampedValue() / max) * 100);
50
+ const displayValue = () => {
51
+ if (valueText) return valueText;
52
+ if (indeterminate) return "";
53
+ return `${Math.round(percent())}%`;
54
+ };
55
+ </script>
56
+
57
+ <div {...rest} class={wrapperClasses()}>
58
+ {#if label || (showValue && !indeterminate)}
59
+ <div class="st-progressBar__header">
60
+ {#if label}<span class="st-progressBar__label">{label}</span>{/if}
61
+ {#if showValue && !indeterminate}
62
+ <span class="st-progressBar__value" aria-hidden="true">{displayValue()}</span>
63
+ {/if}
64
+ </div>
65
+ {/if}
66
+ <div
67
+ class={trackClasses()}
68
+ role="progressbar"
69
+ aria-valuemin={indeterminate ? undefined : 0}
70
+ aria-valuemax={indeterminate ? undefined : max}
71
+ aria-valuenow={indeterminate ? undefined : clampedValue()}
72
+ aria-valuetext={indeterminate ? undefined : displayValue()}
73
+ aria-label={label}
74
+ >
75
+ <div class="st-progressBar__fill" style="--st-progressBar-pct: {percent()}%"></div>
76
+ </div>
77
+ {#if helperText}<span class="st-progressBar__help">{helperText}</span>{/if}
78
+ </div>
79
+
80
+ <style>
81
+ .st-progressBar {
82
+ color: var(--st-semantic-text-primary);
83
+ display: grid;
84
+ gap: 0.375rem;
85
+ width: 100%;
86
+ }
87
+
88
+ .st-progressBar__header {
89
+ align-items: baseline;
90
+ display: flex;
91
+ gap: 0.75rem;
92
+ justify-content: space-between;
93
+ }
94
+
95
+ .st-progressBar__label {
96
+ font-size: 0.875rem;
97
+ font-weight: 600;
98
+ }
99
+
100
+ .st-progressBar__value {
101
+ color: var(--st-semantic-text-secondary);
102
+ font-size: 0.8125rem;
103
+ font-variant-numeric: tabular-nums;
104
+ }
105
+
106
+ .st-progressBar__help {
107
+ color: var(--st-component-field-helpText, var(--st-semantic-text-secondary));
108
+ font-size: 0.8125rem;
109
+ }
110
+
111
+ .st-progressBar__track {
112
+ background: var(--st-semantic-surface-subtle);
113
+ border-radius: var(--st-radius-pill, 999px);
114
+ overflow: hidden;
115
+ position: relative;
116
+ width: 100%;
117
+ }
118
+
119
+ .st-progressBar__track--sm {
120
+ height: 0.25rem;
121
+ }
122
+
123
+ .st-progressBar__track--md {
124
+ height: 0.5rem;
125
+ }
126
+
127
+ .st-progressBar__track--lg {
128
+ height: 0.75rem;
129
+ }
130
+
131
+ .st-progressBar__fill {
132
+ background: var(--st-progressBar-color, var(--st-semantic-action-primary));
133
+ border-radius: inherit;
134
+ height: 100%;
135
+ transform-origin: left center;
136
+ transition: width var(--st-motion-fast, 120ms) var(--st-motion-easing, ease);
137
+ width: var(--st-progressBar-pct, 0%);
138
+ }
139
+
140
+ .st-progressBar__track--neutral .st-progressBar__fill {
141
+ background: var(--st-semantic-action-primary);
142
+ }
143
+
144
+ .st-progressBar__track--success .st-progressBar__fill {
145
+ background: var(--st-semantic-feedback-success);
146
+ }
147
+
148
+ .st-progressBar__track--warning .st-progressBar__fill {
149
+ background: var(--st-semantic-feedback-warning);
150
+ }
151
+
152
+ .st-progressBar__track--error .st-progressBar__fill {
153
+ background: var(--st-semantic-feedback-error);
154
+ }
155
+
156
+ .st-progressBar__track--indeterminate .st-progressBar__fill {
157
+ animation: st-progressBar-indeterminate 1.4s ease-in-out infinite;
158
+ width: 30%;
159
+ }
160
+
161
+ @keyframes st-progressBar-indeterminate {
162
+ 0% {
163
+ transform: translateX(-100%);
164
+ }
165
+ 100% {
166
+ transform: translateX(380%);
167
+ }
168
+ }
169
+
170
+ @media (prefers-reduced-motion: reduce) {
171
+ .st-progressBar__track--indeterminate .st-progressBar__fill {
172
+ animation: none;
173
+ width: 100%;
174
+ }
175
+ }
176
+ </style>
@@ -0,0 +1,17 @@
1
+ import type { HTMLAttributes } from "svelte/elements";
2
+ type ProgressBarProps = Omit<HTMLAttributes<HTMLDivElement>, "class"> & {
3
+ label?: string;
4
+ helperText?: string;
5
+ value?: number;
6
+ max?: number;
7
+ indeterminate?: boolean;
8
+ tone?: "neutral" | "success" | "warning" | "error";
9
+ size?: "sm" | "md" | "lg";
10
+ showValue?: boolean;
11
+ valueText?: string;
12
+ class?: string;
13
+ };
14
+ declare const ProgressBar: import("svelte").Component<ProgressBarProps, {}, "">;
15
+ type ProgressBar = ReturnType<typeof ProgressBar>;
16
+ export default ProgressBar;
17
+ //# sourceMappingURL=ProgressBar.svelte.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ProgressBar.svelte.d.ts","sourceRoot":"","sources":["../src/lib/ProgressBar.svelte.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAGpD,KAAK,gBAAgB,GAAG,IAAI,CAAC,cAAc,CAAC,cAAc,CAAC,EAAE,OAAO,CAAC,GAAG;IACtE,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,IAAI,CAAC,EAAE,SAAS,GAAG,SAAS,GAAG,SAAS,GAAG,OAAO,CAAC;IACnD,IAAI,CAAC,EAAE,IAAI,GAAG,IAAI,GAAG,IAAI,CAAC;IAC1B,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,CAAC;AAgEJ,QAAA,MAAM,WAAW,sDAAwC,CAAC;AAC1D,KAAK,WAAW,GAAG,UAAU,CAAC,OAAO,WAAW,CAAC,CAAC;AAClD,eAAe,WAAW,CAAC"}
@@ -0,0 +1,218 @@
1
+ <script lang="ts">
2
+ import type { HTMLInputAttributes } from "svelte/elements";
3
+
4
+ type SearchProps = Omit<HTMLInputAttributes, "class" | "size" | "type" | "value"> & {
5
+ label?: string;
6
+ helperText?: string;
7
+ errorText?: string;
8
+ invalid?: boolean;
9
+ size?: "sm" | "md" | "lg";
10
+ value?: string;
11
+ placeholder?: string;
12
+ clearLabel?: string;
13
+ class?: string;
14
+ };
15
+
16
+ let {
17
+ label,
18
+ helperText,
19
+ errorText,
20
+ invalid = false,
21
+ size = "md",
22
+ value = $bindable(""),
23
+ placeholder = "Search",
24
+ clearLabel = "Clear search",
25
+ disabled,
26
+ class: className,
27
+ ...rest
28
+ }: SearchProps = $props();
29
+
30
+ const fieldClasses = () => ["st-field", className].filter(Boolean).join(" ");
31
+ const groupClasses = () => ["st-search", `st-search--${size}`].join(" ");
32
+ const isInvalid = () => invalid || Boolean(errorText);
33
+
34
+ function clear() {
35
+ value = "";
36
+ }
37
+ </script>
38
+
39
+ <div class={fieldClasses()}>
40
+ <label class="st-field__control">
41
+ {#if label}<span class="st-field__label">{label}</span>{/if}
42
+ <span class={groupClasses()}>
43
+ <span class="st-search__icon" aria-hidden="true">
44
+ <svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5" width="16" height="16">
45
+ <circle cx="7" cy="7" r="4.5" />
46
+ <path d="m13 13-2.6-2.6" stroke-linecap="round" />
47
+ </svg>
48
+ </span>
49
+ <input
50
+ {...rest}
51
+ type="search"
52
+ role="searchbox"
53
+ class="st-search__control"
54
+ bind:value
55
+ {placeholder}
56
+ {disabled}
57
+ aria-invalid={isInvalid() ? "true" : undefined}
58
+ />
59
+ {#if value}
60
+ <button
61
+ type="button"
62
+ class="st-search__clear"
63
+ aria-label={clearLabel}
64
+ {disabled}
65
+ onclick={clear}
66
+ >
67
+ <span aria-hidden="true">×</span>
68
+ </button>
69
+ {/if}
70
+ </span>
71
+ </label>
72
+ {#if errorText}
73
+ <span class="st-field__error">{errorText}</span>
74
+ {:else if helperText}
75
+ <span class="st-field__help">{helperText}</span>
76
+ {/if}
77
+ </div>
78
+
79
+ <style>
80
+ .st-field {
81
+ color: var(--st-component-field-labelText, var(--st-semantic-text-primary));
82
+ display: grid;
83
+ gap: var(--st-component-field-gap, 0.5rem);
84
+ max-width: var(--st-component-field-maxWidth, 28rem);
85
+ }
86
+
87
+ .st-field__control {
88
+ display: grid;
89
+ gap: var(--st-component-field-gap, 0.5rem);
90
+ }
91
+
92
+ .st-field__label {
93
+ font-size: 0.875rem;
94
+ font-weight: 600;
95
+ }
96
+
97
+ .st-field__help,
98
+ .st-field__error {
99
+ font-size: 0.8125rem;
100
+ line-height: 1.4;
101
+ }
102
+
103
+ .st-field__help {
104
+ color: var(--st-component-field-helpText, var(--st-semantic-text-secondary));
105
+ }
106
+
107
+ .st-field__error {
108
+ color: var(--st-component-field-errorText, var(--st-semantic-feedback-error));
109
+ }
110
+
111
+ .st-search {
112
+ align-items: center;
113
+ background: var(--st-component-control-background, var(--st-semantic-surface-default));
114
+ border: 1px solid var(--st-component-control-border, var(--st-semantic-border-subtle));
115
+ border-radius: var(--st-component-control-radius, 0.375rem);
116
+ color: var(--st-component-control-text, var(--st-semantic-text-primary));
117
+ display: inline-flex;
118
+ transition:
119
+ border-color var(--st-motion-fast, 120ms) var(--st-motion-easing, ease),
120
+ box-shadow var(--st-motion-fast, 120ms) var(--st-motion-easing, ease);
121
+ width: 100%;
122
+ }
123
+
124
+ .st-search--sm {
125
+ min-height: var(--st-component-control-smHeight, 2rem);
126
+ }
127
+
128
+ .st-search--md {
129
+ min-height: var(--st-component-control-mdHeight, 2.5rem);
130
+ }
131
+
132
+ .st-search--lg {
133
+ min-height: var(--st-component-control-lgHeight, 3rem);
134
+ }
135
+
136
+ .st-search:hover:not(:has(input:disabled)) {
137
+ border-color: var(--st-component-control-hoverBorder, var(--st-semantic-border-strong));
138
+ }
139
+
140
+ .st-search:focus-within {
141
+ border-color: var(--st-component-control-focusRing, var(--st-semantic-border-interactive));
142
+ box-shadow: 0 0 0 2px var(--st-component-control-focusRing, var(--st-semantic-border-interactive));
143
+ }
144
+
145
+ .st-search:has([aria-invalid="true"]) {
146
+ border-color: var(--st-component-control-invalidBorder, var(--st-semantic-feedback-error));
147
+ }
148
+
149
+ .st-search__icon {
150
+ align-items: center;
151
+ color: var(--st-semantic-text-muted);
152
+ display: inline-flex;
153
+ flex: 0 0 auto;
154
+ justify-content: center;
155
+ padding-inline-start: 0.625rem;
156
+ }
157
+
158
+ .st-search__control {
159
+ background: transparent;
160
+ border: 0;
161
+ color: inherit;
162
+ flex: 1 1 auto;
163
+ font: inherit;
164
+ min-width: 0;
165
+ padding: 0 0.5rem;
166
+ width: 100%;
167
+ }
168
+
169
+ .st-search__control:focus {
170
+ outline: none;
171
+ }
172
+
173
+ .st-search__control::placeholder {
174
+ color: var(--st-component-control-placeholderText, var(--st-semantic-text-muted));
175
+ }
176
+
177
+ .st-search__control::-webkit-search-cancel-button {
178
+ appearance: none;
179
+ }
180
+
181
+ .st-search__control:disabled {
182
+ color: var(--st-component-control-disabledText, var(--st-semantic-text-muted));
183
+ cursor: not-allowed;
184
+ }
185
+
186
+ .st-search__clear {
187
+ align-items: center;
188
+ background: transparent;
189
+ border: 0;
190
+ border-radius: 50%;
191
+ color: inherit;
192
+ cursor: pointer;
193
+ display: inline-flex;
194
+ flex: 0 0 auto;
195
+ font: inherit;
196
+ font-size: 1.125rem;
197
+ height: 1.5rem;
198
+ justify-content: center;
199
+ line-height: 1;
200
+ margin-inline-end: 0.375rem;
201
+ padding: 0;
202
+ transition: background-color var(--st-motion-fast, 120ms) var(--st-motion-easing, ease);
203
+ width: 1.5rem;
204
+ }
205
+
206
+ .st-search__clear:hover:not(:disabled) {
207
+ background: var(--st-component-control-hoverBackground, var(--st-semantic-surface-subtle));
208
+ }
209
+
210
+ .st-search__clear:focus-visible {
211
+ outline: 2px solid var(--st-component-control-focusRing, var(--st-semantic-border-interactive));
212
+ outline-offset: 1px;
213
+ }
214
+
215
+ .st-search__clear:disabled {
216
+ cursor: not-allowed;
217
+ }
218
+ </style>
@@ -0,0 +1,16 @@
1
+ import type { HTMLInputAttributes } from "svelte/elements";
2
+ type SearchProps = Omit<HTMLInputAttributes, "class" | "size" | "type" | "value"> & {
3
+ label?: string;
4
+ helperText?: string;
5
+ errorText?: string;
6
+ invalid?: boolean;
7
+ size?: "sm" | "md" | "lg";
8
+ value?: string;
9
+ placeholder?: string;
10
+ clearLabel?: string;
11
+ class?: string;
12
+ };
13
+ declare const Search: import("svelte").Component<SearchProps, {}, "value">;
14
+ type Search = ReturnType<typeof Search>;
15
+ export default Search;
16
+ //# sourceMappingURL=Search.svelte.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Search.svelte.d.ts","sourceRoot":"","sources":["../src/lib/Search.svelte.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,iBAAiB,CAAC;AAGzD,KAAK,WAAW,GAAG,IAAI,CAAC,mBAAmB,EAAE,OAAO,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC,GAAG;IAClF,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,IAAI,CAAC,EAAE,IAAI,GAAG,IAAI,GAAG,IAAI,CAAC;IAC1B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,CAAC;AAyDJ,QAAA,MAAM,MAAM,sDAAwC,CAAC;AACrD,KAAK,MAAM,GAAG,UAAU,CAAC,OAAO,MAAM,CAAC,CAAC;AACxC,eAAe,MAAM,CAAC"}