@infonomic/uikit 6.4.0 → 6.5.1

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 (29) hide show
  1. package/dist/components/inputs/@types/autocomplete.d.ts +35 -0
  2. package/dist/components/inputs/@types/autocomplete.d.ts.map +1 -0
  3. package/dist/components/inputs/@types/autocomplete.js +11 -0
  4. package/dist/components/inputs/autocomplete.d.ts +42 -0
  5. package/dist/components/inputs/autocomplete.d.ts.map +1 -0
  6. package/dist/components/inputs/autocomplete.js +87 -0
  7. package/dist/components/inputs/autocomplete.module.css +371 -0
  8. package/dist/components/inputs/autocomplete.module.js +36 -0
  9. package/dist/components/inputs/autocomplete_module.css +312 -0
  10. package/dist/components/inputs/calendar.js +2 -2
  11. package/dist/components/inputs/index.js +1 -0
  12. package/dist/components/notifications/@types/alert.js +1 -0
  13. package/dist/components/notifications/@types/toast.js +1 -0
  14. package/dist/components/pager/hooks/types/usePagination.js +1 -0
  15. package/dist/components/tooltip/tooltip_module.css +1 -1
  16. package/dist/icons/types/icon.js +1 -0
  17. package/dist/loaders/@types/index.js +1 -0
  18. package/dist/react.d.ts +1 -0
  19. package/dist/react.d.ts.map +1 -1
  20. package/dist/react.js +1 -0
  21. package/dist/utils/polymorphic.js +1 -0
  22. package/package.json +23 -19
  23. package/src/components/inputs/@types/autocomplete.ts +39 -0
  24. package/src/components/inputs/autocomplete.module.css +371 -0
  25. package/src/components/inputs/autocomplete.stories.tsx +184 -0
  26. package/src/components/inputs/autocomplete.tsx +173 -0
  27. package/src/components/inputs/index.tsx +1 -0
  28. package/src/react.ts +1 -0
  29. package/dist/tsconfig.build.tsbuildinfo +0 -1
@@ -0,0 +1,371 @@
1
+ @layer infonomic-base,
2
+ infonomic-functional,
3
+ infonomic-utilities,
4
+ infonomic-theme,
5
+ infonomic-typography,
6
+ infonomic-components;
7
+
8
+ @layer infonomic-components {
9
+
10
+ /* ── Wrapper ── */
11
+
12
+ .autocomplete-wrapper,
13
+ :global(.infonomic-autocomplete-wrapper) {
14
+ display: flex;
15
+ flex-direction: column;
16
+ gap: var(--gap-1);
17
+ }
18
+
19
+ /* ── Input ── */
20
+
21
+ .input,
22
+ :global(.infonomic-autocomplete-input) {
23
+ border: none;
24
+ outline: 1px solid transparent;
25
+ outline-offset: 2px;
26
+ font-weight: normal;
27
+ display: inline-flex;
28
+ gap: var(--gap-2);
29
+ align-items: center;
30
+ width: 100%;
31
+ transition: all var(--transition-normal);
32
+ border-radius: var(--border-radius-sm);
33
+ }
34
+
35
+ .input:focus,
36
+ .input:active,
37
+ :global(.infonomic-autocomplete-input):focus,
38
+ :global(.infonomic-autocomplete-input):active {
39
+ outline-color: var(--ring-color);
40
+ }
41
+
42
+ .input:disabled,
43
+ .input[disabled],
44
+ :global(.infonomic-autocomplete-input):disabled,
45
+ :global(.infonomic-autocomplete-input)[disabled] {
46
+ pointer-events: none;
47
+ }
48
+
49
+ /* ── Sizes ── */
50
+
51
+ .sm,
52
+ :global(.infonomic-autocomplete-input-sm) {
53
+ min-height: 32px;
54
+ font-size: 0.875rem;
55
+ line-height: 0;
56
+ padding: 0.25rem 0.5rem;
57
+ }
58
+
59
+ .md,
60
+ :global(.infonomic-autocomplete-input-md) {
61
+ min-height: 36px;
62
+ font-size: 1rem;
63
+ line-height: 0;
64
+ padding: 0.3rem 0.5rem;
65
+ }
66
+
67
+ .lg,
68
+ :global(.infonomic-autocomplete-input-lg) {
69
+ min-height: 40px;
70
+ font-size: 1.175rem;
71
+ line-height: 0;
72
+ padding: 0.4rem 0.5rem;
73
+ }
74
+
75
+ /* ── Variants ── */
76
+
77
+ .outlined,
78
+ :global(.infonomic-autocomplete-input-outlined) {
79
+ border: 1px solid var(--input-variant-outlined-border);
80
+ background-color: transparent;
81
+ }
82
+
83
+ .outlined:hover,
84
+ :global(.infonomic-autocomplete-input-outlined):hover {
85
+ border: 1px solid var(--input-variant-outlined-hover-border);
86
+ }
87
+
88
+ .outlined:focus,
89
+ .outlined:active,
90
+ :global(.infonomic-autocomplete-input-outlined):focus,
91
+ :global(.infonomic-autocomplete-input-outlined):active {
92
+ --ring-color: var(--input-variant-outline-ring-color);
93
+ }
94
+
95
+ .underlined,
96
+ :global(.infonomic-autocomplete-input-underlined) {
97
+ border-bottom: 1px solid var(--input-variant-underlined-border);
98
+ border-radius: 0;
99
+ gap: var(--gap-1);
100
+ background-color: var(--input-variant-underlined);
101
+ }
102
+
103
+ .underlined.sm,
104
+ :global(.infonomic-autocomplete-input-underlined.infonomic-autocomplete-input-sm) {
105
+ padding: 0.25rem 0.1rem;
106
+ min-height: 26px;
107
+ }
108
+
109
+ .underlined.md,
110
+ :global(.infonomic-autocomplete-input-underlined.infonomic-autocomplete-input-md) {
111
+ padding: 0.25rem 0.1rem;
112
+ min-height: 30px;
113
+ }
114
+
115
+ .underlined.lg,
116
+ :global(.infonomic-autocomplete-input-underlined.infonomic-autocomplete-input-lg) {
117
+ padding: 0 0.1rem;
118
+ min-height: 34px;
119
+ }
120
+
121
+ .underlined:hover,
122
+ :global(.infonomic-autocomplete-input-underlined):hover {
123
+ border-bottom: 1px solid var(--input-variant-underlined-hover-border);
124
+ }
125
+
126
+ .underlined:focus,
127
+ .underlined:active,
128
+ :global(.infonomic-autocomplete-input-underlined):focus,
129
+ :global(.infonomic-autocomplete-input-underlined):active {
130
+ outline: none;
131
+ }
132
+
133
+ .filled,
134
+ :global(.infonomic-autocomplete-input-filled) {
135
+ background-color: var(--input-variant-filled);
136
+ }
137
+
138
+ /* ── Error ── */
139
+
140
+ .error,
141
+ :global(.infonomic-autocomplete-input-error) {
142
+ border: 1px solid var(--red-400);
143
+ }
144
+
145
+ .error:hover,
146
+ :global(.infonomic-autocomplete-input-error):hover {
147
+ border: 1px solid var(--red-400);
148
+ }
149
+
150
+ .error:focus,
151
+ .error:active,
152
+ :global(.infonomic-autocomplete-input-error):focus,
153
+ :global(.infonomic-autocomplete-input-error):active {
154
+ --ring-color: var(--red-300);
155
+ }
156
+
157
+ /* ── Intents ── */
158
+
159
+ .primary,
160
+ :global(.infonomic-autocomplete-input-primary) {
161
+ --input-variant-outlined-border: var(--stroke-primary);
162
+ --input-variant-outlined-hover-border: var(--stroke-primary-hover);
163
+ --input-variant-outline-ring-color: var(--ring-primary);
164
+ --input-variant-underlined-border: var(--stroke-primary);
165
+ --input-variant-underlined-hover-border: var(--stroke-primary-hover);
166
+ --input-variant-filled: var(--fill-primary-weak);
167
+ }
168
+
169
+ .secondary,
170
+ :global(.infonomic-autocomplete-input-secondary) {
171
+ --input-variant-outlined-border: var(--stroke-secondary);
172
+ --input-variant-outlined-hover-border: var(--stroke-secondary-hover);
173
+ --input-variant-outline-ring-color: var(--ring-secondary);
174
+ --input-variant-underlined-border: var(--stroke-secondary);
175
+ --input-variant-underlined-hover-border: var(--stroke-secondary-hover);
176
+ --input-variant-filled: var(--fill-secondary-weak);
177
+ }
178
+
179
+ .noeffect,
180
+ :global(.infonomic-autocomplete-input-noeffect) {
181
+ --input-variant-outlined-border: var(--stroke-noeffect);
182
+ --input-variant-outlined-hover-border: var(--stroke-noeffect-hover);
183
+ --input-variant-outline-ring-color: var(--ring-noeffect);
184
+ --input-variant-underlined-border: var(--stroke-noeffect);
185
+ --input-variant-underlined-hover-border: var(--stroke-noeffect-hover);
186
+ --input-variant-filled: var(--fill-noeffect-weak);
187
+ }
188
+
189
+ .success,
190
+ :global(.infonomic-autocomplete-input-success) {
191
+ --input-variant-outlined-border: var(--stroke-success);
192
+ --input-variant-outlined-hover-border: var(--stroke-success-hover);
193
+ --input-variant-outline-ring-color: var(--ring-success);
194
+ --input-variant-underlined-border: var(--stroke-success);
195
+ --input-variant-underlined-hover-border: var(--stroke-success-hover);
196
+ --input-variant-filled: var(--fill-success-weak);
197
+ }
198
+
199
+ .info,
200
+ :global(.infonomic-autocomplete-input-info) {
201
+ --input-variant-outlined-border: var(--stroke-info);
202
+ --input-variant-outlined-hover-border: var(--stroke-info-hover);
203
+ --input-variant-outline-ring-color: var(--ring-info);
204
+ --input-variant-underlined-border: var(--stroke-info);
205
+ --input-variant-underlined-hover-border: var(--stroke-info-hover);
206
+ --input-variant-filled: var(--fill-info-weak);
207
+ }
208
+
209
+ .warning,
210
+ :global(.infonomic-autocomplete-input-warning) {
211
+ --input-variant-outlined-border: var(--stroke-warning);
212
+ --input-variant-outlined-hover-border: var(--stroke-warning-hover);
213
+ --input-variant-outline-ring-color: var(--ring-warning);
214
+ --input-variant-underlined-border: var(--stroke-warning);
215
+ --input-variant-underlined-hover-border: var(--stroke-warning-hover);
216
+ --input-variant-filled: var(--fill-warning-weak);
217
+ }
218
+
219
+ .danger,
220
+ :global(.infonomic-autocomplete-input-danger) {
221
+ --input-variant-outlined-border: var(--stroke-danger);
222
+ --input-variant-outlined-hover-border: var(--stroke-danger-hover);
223
+ --input-variant-outline-ring-color: var(--ring-danger);
224
+ --input-variant-underlined-border: var(--stroke-danger);
225
+ --input-variant-underlined-hover-border: var(--stroke-danger-hover);
226
+ --input-variant-filled: var(--fill-danger-weak);
227
+ }
228
+
229
+ /* ── Positioner ── */
230
+
231
+ .positioner,
232
+ :global(.infonomic-autocomplete-positioner) {
233
+ z-index: 50;
234
+ outline: 0;
235
+ }
236
+
237
+ /* ── Popup ── */
238
+
239
+ .popup,
240
+ :global(.infonomic-autocomplete-popup) {
241
+ z-index: 50;
242
+ margin-top: 2px;
243
+ border: 1px solid var(--surface-panel-border);
244
+ box-shadow: var(--shadow-md);
245
+ border-radius: var(--border-radius-md);
246
+ background-color: var(--surface-panel-elevated);
247
+ padding: 6px;
248
+ width: var(--anchor-width);
249
+ max-height: min(23rem, var(--available-height));
250
+ max-width: var(--available-width);
251
+ }
252
+
253
+ .popup-sm {
254
+ padding: 4px;
255
+ }
256
+
257
+ .popup-md {
258
+ padding: 6px;
259
+ }
260
+
261
+ .popup-lg {
262
+ padding: 8px;
263
+ }
264
+
265
+ /* ── List ── */
266
+
267
+ .list,
268
+ :global(.infonomic-autocomplete-list) {
269
+ box-sizing: border-box;
270
+ overflow-y: auto;
271
+ overscroll-behavior: contain;
272
+ padding-block: 0.25rem;
273
+ scroll-padding-block: 0.25rem;
274
+ outline: 0;
275
+ max-height: min(23rem, var(--available-height));
276
+ }
277
+
278
+ .list[data-empty],
279
+ :global(.infonomic-autocomplete-list)[data-empty] {
280
+ padding: 0;
281
+ }
282
+
283
+ /* ── Item ── */
284
+
285
+ .autocomplete-item,
286
+ :global(.infonomic-autocomplete-item) {
287
+ position: relative;
288
+ user-select: none;
289
+ cursor: default;
290
+ outline: 0;
291
+ color: var(--surface-item-text);
292
+ background-color: var(--surface-item);
293
+ font-size: 1rem;
294
+ line-height: 1;
295
+ padding-block: 0.5rem;
296
+ padding-left: 0.75rem;
297
+ padding-right: 0.75rem;
298
+ display: flex;
299
+ align-items: center;
300
+ border-radius: 6px;
301
+ }
302
+
303
+ .autocomplete-item[data-disabled],
304
+ :global(.infonomic-autocomplete-item[data-disabled]) {
305
+ color: var(--surface-item-text-disabled);
306
+ pointer-events: none;
307
+ }
308
+
309
+ .autocomplete-item[data-highlighted],
310
+ :global(.infonomic-autocomplete-item[data-highlighted]) {
311
+ outline: none;
312
+ background-color: var(--surface-item-hover);
313
+ color: var(--surface-item-text-hover);
314
+ }
315
+
316
+ /* ── Size-scoped items ── */
317
+
318
+ .popup-sm .autocomplete-item {
319
+ font-size: 0.75rem;
320
+ padding-block: 0.375rem;
321
+ padding-left: 0.5rem;
322
+ padding-right: 0.5rem;
323
+ border-radius: 4px;
324
+ }
325
+
326
+ .popup-md .autocomplete-item {
327
+ font-size: 0.875rem;
328
+ }
329
+
330
+ .popup-lg .autocomplete-item {
331
+ font-size: 1.125rem;
332
+ padding-block: 0.625rem;
333
+ padding-left: 1rem;
334
+ padding-right: 1rem;
335
+ border-radius: 8px;
336
+ }
337
+
338
+ /* ── Group label ── */
339
+
340
+ .group-label,
341
+ :global(.infonomic-autocomplete-group-label) {
342
+ padding: 0.375rem 0.75rem;
343
+ font-size: 0.75rem;
344
+ font-weight: 600;
345
+ color: var(--muted);
346
+ text-transform: uppercase;
347
+ letter-spacing: 0.05em;
348
+ }
349
+
350
+ /* ── Separator ── */
351
+
352
+ .separator,
353
+ :global(.infonomic-autocomplete-separator) {
354
+ margin: 0.375rem 0.75rem;
355
+ height: 1px;
356
+ background-color: var(--surface-panel-border);
357
+ }
358
+
359
+ /* ── Empty ── */
360
+
361
+ .empty:not(:empty),
362
+ :global(.infonomic-autocomplete-empty):not(:empty) {
363
+ box-sizing: border-box;
364
+ padding: 1rem;
365
+ font-size: 0.925rem;
366
+ line-height: 1;
367
+ color: var(--muted);
368
+ }
369
+
370
+ /* Dark mode handled by semantic tokens in theme layer */
371
+ }
@@ -0,0 +1,184 @@
1
+ import type React from 'react'
2
+
3
+ import { capitalize } from '../../utils/capitalize.js'
4
+ import { intent } from '../@types/shared.js'
5
+ import { size, variant } from './@types/autocomplete.js'
6
+ import { Autocomplete, AutocompleteItem } from './autocomplete.js'
7
+
8
+ export default {
9
+ title: 'Components/Inputs/Autocomplete',
10
+ component: Autocomplete,
11
+ argTypes: {},
12
+ }
13
+
14
+ interface Tag {
15
+ id: string
16
+ value: string
17
+ }
18
+
19
+ const tags: Tag[] = [
20
+ { id: 't1', value: 'feature' },
21
+ { id: 't2', value: 'fix' },
22
+ { id: 't3', value: 'bug' },
23
+ { id: 't4', value: 'docs' },
24
+ { id: 't5', value: 'internal' },
25
+ { id: 't6', value: 'mobile' },
26
+ { id: 'c-accordion', value: 'component: accordion' },
27
+ { id: 'c-alert-dialog', value: 'component: alert dialog' },
28
+ { id: 'c-autocomplete', value: 'component: autocomplete' },
29
+ { id: 'c-avatar', value: 'component: avatar' },
30
+ { id: 'c-checkbox', value: 'component: checkbox' },
31
+ { id: 'c-dialog', value: 'component: dialog' },
32
+ { id: 'c-input', value: 'component: input' },
33
+ { id: 'c-select', value: 'component: select' },
34
+ { id: 'c-tabs', value: 'component: tabs' },
35
+ { id: 'c-toast', value: 'component: toast' },
36
+ { id: 'c-tooltip', value: 'component: tooltip' },
37
+ ]
38
+
39
+ export const Default = (): React.JSX.Element => {
40
+ return (
41
+ <div style={{ maxWidth: '600px', margin: '2rem auto' }}>
42
+ <Autocomplete<Tag>
43
+ id="tags-default"
44
+ label="Search tags"
45
+ placeholder="e.g. feature"
46
+ helpText="Start typing to filter tags."
47
+ items={tags}
48
+ >
49
+ {(tag: Tag) => (
50
+ <AutocompleteItem key={tag.id} value={tag}>
51
+ {tag.value}
52
+ </AutocompleteItem>
53
+ )}
54
+ </Autocomplete>
55
+ </div>
56
+ )
57
+ }
58
+
59
+ export const Variants = (): React.JSX.Element => {
60
+ return (
61
+ <div style={{ maxWidth: '1100px', margin: '0 auto' }}>
62
+ {variant.map((v) => {
63
+ return (
64
+ <div
65
+ key={v}
66
+ style={{ marginBottom: '2rem' }}
67
+ className="grid grid-cols-4 items-center gap-12"
68
+ >
69
+ {size.map((s) => {
70
+ return (
71
+ <Autocomplete<Tag>
72
+ key={`${v}-${s}`}
73
+ id={`${v}-${s}`}
74
+ variant={v}
75
+ inputSize={s}
76
+ label={`${capitalize(v)} ${s.toUpperCase()}`}
77
+ placeholder={`${capitalize(v)} ${s.toUpperCase()}`}
78
+ helpText={`${capitalize(v)} variant, ${s.toUpperCase()} size.`}
79
+ items={tags}
80
+ >
81
+ {(tag: Tag) => (
82
+ <AutocompleteItem key={tag.id} value={tag}>
83
+ {tag.value}
84
+ </AutocompleteItem>
85
+ )}
86
+ </Autocomplete>
87
+ )
88
+ })}
89
+ <Autocomplete<Tag>
90
+ key={`${v}-disabled`}
91
+ id={`${v}-disabled`}
92
+ variant={v}
93
+ disabled
94
+ label={`${capitalize(v)} Disabled`}
95
+ placeholder={`${capitalize(v)} disabled`}
96
+ helpText={`${capitalize(v)} variant, disabled.`}
97
+ items={tags}
98
+ >
99
+ {(tag: Tag) => (
100
+ <AutocompleteItem key={tag.id} value={tag}>
101
+ {tag.value}
102
+ </AutocompleteItem>
103
+ )}
104
+ </Autocomplete>
105
+ </div>
106
+ )
107
+ })}
108
+ </div>
109
+ )
110
+ }
111
+
112
+ export const Intents = (): React.JSX.Element => {
113
+ return (
114
+ <div style={{ maxWidth: '800px', margin: '0 auto' }}>
115
+ {intent.map((i) => {
116
+ return (
117
+ <div key={i} style={{ marginBottom: '12px' }}>
118
+ <Autocomplete<Tag>
119
+ id={`intent-${i}`}
120
+ variant="outlined"
121
+ intent={i}
122
+ inputSize="md"
123
+ label={capitalize(i)}
124
+ placeholder={capitalize(i)}
125
+ helpText={`${capitalize(i)} intent autocomplete.`}
126
+ items={tags}
127
+ >
128
+ {(tag: Tag) => (
129
+ <AutocompleteItem key={tag.id} value={tag}>
130
+ {tag.value}
131
+ </AutocompleteItem>
132
+ )}
133
+ </Autocomplete>
134
+ </div>
135
+ )
136
+ })}
137
+ </div>
138
+ )
139
+ }
140
+
141
+ // biome-ignore lint/suspicious/noShadowRestrictedNames: storybook convention
142
+ export const Error = (): React.JSX.Element => {
143
+ return (
144
+ <div style={{ maxWidth: '600px', margin: '0 auto' }}>
145
+ <Autocomplete<Tag>
146
+ id="tags-error"
147
+ required
148
+ label="Search tags"
149
+ placeholder="e.g. feature"
150
+ helpText="Please select a tag."
151
+ error={true}
152
+ errorText="Please select a valid tag."
153
+ items={tags}
154
+ >
155
+ {(tag: Tag) => (
156
+ <AutocompleteItem key={tag.id} value={tag}>
157
+ {tag.value}
158
+ </AutocompleteItem>
159
+ )}
160
+ </Autocomplete>
161
+ </div>
162
+ )
163
+ }
164
+
165
+ export const WithoutCustomItem = (): React.JSX.Element => {
166
+ const fruits = ['Apple', 'Banana', 'Cherry', 'Date', 'Elderberry', 'Fig', 'Grape']
167
+ return (
168
+ <div style={{ maxWidth: '600px', margin: '2rem auto' }}>
169
+ <Autocomplete<string>
170
+ id="fruits"
171
+ label="Search fruits"
172
+ placeholder="e.g. Apple"
173
+ helpText="Using plain strings without AutocompleteItem wrapper."
174
+ items={fruits}
175
+ >
176
+ {(fruit: string) => (
177
+ <AutocompleteItem key={fruit} value={fruit}>
178
+ {fruit}
179
+ </AutocompleteItem>
180
+ )}
181
+ </Autocomplete>
182
+ </div>
183
+ )
184
+ }