@apliteni/apliteni-ui 0.45.0 → 0.47.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.
- package/package.json +1 -1
- package/react/README.md +43 -0
- package/react/dist/index.css +370 -0
- package/react/dist/index.d.ts +39 -2
- package/react/dist/index.js +160 -5
- package/src/styles/input.css +1 -1
package/package.json
CHANGED
package/react/README.md
CHANGED
|
@@ -364,3 +364,46 @@ opens, focus goes to the safe action. It renders an `alertdialog`, named by its
|
|
|
364
364
|
and described by its body. Modal also accepts
|
|
365
365
|
`initialFocusRef` for a mounted, focusable element inside its panel. Without it, Modal
|
|
366
366
|
uses its normal opening focus.
|
|
367
|
+
|
|
368
|
+
## Timeline
|
|
369
|
+
|
|
370
|
+
`Timeline` displays a record’s events in the order provided. Pass events from oldest
|
|
371
|
+
to newest, with stable IDs, machine-readable `dateTime` values, and formatted
|
|
372
|
+
`timestamp` text.
|
|
373
|
+
Descriptions should say what changed and to where.
|
|
374
|
+
|
|
375
|
+
```tsx
|
|
376
|
+
<Timeline aria-label="Record history" events={[
|
|
377
|
+
{
|
|
378
|
+
id: 'created', actor: 'Demo operator', dateTime: '2026-09-01T09:00:00Z',
|
|
379
|
+
timestamp: '1 Sep, 09:00 UTC', description: 'Created the record in Unassigned.',
|
|
380
|
+
meta: 'Batch DEMO-12',
|
|
381
|
+
},
|
|
382
|
+
]} />
|
|
383
|
+
```
|
|
384
|
+
|
|
385
|
+
Omit `undo` for read-only events. For a reversible batch, pass
|
|
386
|
+
`undo: { label: 'Undo batch DEMO-12', onUndo }`. The app checks permissions,
|
|
387
|
+
asks for confirmation when the batch affects finalized records, reverses the
|
|
388
|
+
entire batch, and adds a new event. Timeline only calls `onUndo`; it does not
|
|
389
|
+
modify history.
|
|
390
|
+
Import both the kit CSS and React CSS. The Privileged story shows confirmation
|
|
391
|
+
and a reversing event.
|
|
392
|
+
|
|
393
|
+
## Fields
|
|
394
|
+
|
|
395
|
+
`TextField`, `TextArea`, `SelectField`, and `FileField` pair a label with a native
|
|
396
|
+
control. Each creates its own IDs and links hints or errors automatically. Use
|
|
397
|
+
native control props. `SelectField` accepts option children.
|
|
398
|
+
|
|
399
|
+
```tsx
|
|
400
|
+
<TextField label="Weight" type="number" unit="kg" required />
|
|
401
|
+
<TextArea label="Notes" hint="Optional" />
|
|
402
|
+
<SelectField label="Currency"><option>EUR</option><option>USD</option></SelectField>
|
|
403
|
+
<FileField label="Attachment" accept=".pdf" hint="PDF, up to 5 MB."
|
|
404
|
+
onFileChange={file => setAttachment(file)} />
|
|
405
|
+
```
|
|
406
|
+
|
|
407
|
+
`FileField` accepts one file from a picker or a drop and reports it through
|
|
408
|
+
`onFileChange`. Use `accept` and `hint` to describe allowed file types and size.
|
|
409
|
+
Your application must validate files before upload.
|
package/react/dist/index.css
CHANGED
|
@@ -142,3 +142,373 @@
|
|
|
142
142
|
display: block;
|
|
143
143
|
}
|
|
144
144
|
}
|
|
145
|
+
|
|
146
|
+
/* src/Timeline.css */
|
|
147
|
+
.ui-timeline {
|
|
148
|
+
margin: 0;
|
|
149
|
+
padding: 0;
|
|
150
|
+
list-style: none;
|
|
151
|
+
color: var(--text);
|
|
152
|
+
font-size: var(--text-sm);
|
|
153
|
+
line-height: 1.5;
|
|
154
|
+
}
|
|
155
|
+
.ui-timeline__event {
|
|
156
|
+
position: relative;
|
|
157
|
+
padding-inline-start: var(--space-6);
|
|
158
|
+
padding-block-end: var(--space-6);
|
|
159
|
+
overflow-wrap: anywhere;
|
|
160
|
+
}
|
|
161
|
+
.ui-timeline__event:last-child {
|
|
162
|
+
padding-block-end: 0;
|
|
163
|
+
}
|
|
164
|
+
.ui-timeline__event::before {
|
|
165
|
+
content: "";
|
|
166
|
+
position: absolute;
|
|
167
|
+
inset-inline-start: calc(var(--space-2) / 2);
|
|
168
|
+
inset-block-start: 0.75em;
|
|
169
|
+
inset-block-end: -0.75em;
|
|
170
|
+
width: 1px;
|
|
171
|
+
background: var(--border);
|
|
172
|
+
}
|
|
173
|
+
.ui-timeline__event:last-child::before {
|
|
174
|
+
display: none;
|
|
175
|
+
}
|
|
176
|
+
.ui-timeline__event::after {
|
|
177
|
+
content: "";
|
|
178
|
+
position: absolute;
|
|
179
|
+
inset-inline-start: 0;
|
|
180
|
+
inset-block-start: calc(0.75em - var(--space-2) / 2);
|
|
181
|
+
width: var(--space-2);
|
|
182
|
+
height: var(--space-2);
|
|
183
|
+
border-radius: 50%;
|
|
184
|
+
background: var(--accent);
|
|
185
|
+
}
|
|
186
|
+
.ui-timeline__head,
|
|
187
|
+
.ui-timeline__meta {
|
|
188
|
+
display: flex;
|
|
189
|
+
flex-wrap: wrap;
|
|
190
|
+
align-items: baseline;
|
|
191
|
+
column-gap: var(--space-3);
|
|
192
|
+
row-gap: var(--space-1);
|
|
193
|
+
}
|
|
194
|
+
.ui-timeline__actor {
|
|
195
|
+
font-weight: var(--weight-semibold);
|
|
196
|
+
}
|
|
197
|
+
.ui-timeline__head time,
|
|
198
|
+
.ui-timeline__meta {
|
|
199
|
+
font-size: var(--text-xs);
|
|
200
|
+
}
|
|
201
|
+
.ui-timeline__description {
|
|
202
|
+
margin: var(--space-1) 0;
|
|
203
|
+
}
|
|
204
|
+
.ui-timeline__undo {
|
|
205
|
+
white-space: normal;
|
|
206
|
+
}
|
|
207
|
+
.ui-timeline__undo:hover,
|
|
208
|
+
.ui-timeline__undo:focus-visible {
|
|
209
|
+
color: var(--pink);
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
/* ../src/styles/input.css */
|
|
213
|
+
.ui-field {
|
|
214
|
+
display: block;
|
|
215
|
+
}
|
|
216
|
+
.ui-field__label {
|
|
217
|
+
display: block;
|
|
218
|
+
color: var(--strong);
|
|
219
|
+
font-size: var(--text-base);
|
|
220
|
+
font-weight: var(--weight-medium);
|
|
221
|
+
margin-bottom: 8px;
|
|
222
|
+
}
|
|
223
|
+
.ui-field__req {
|
|
224
|
+
color: var(--pink);
|
|
225
|
+
margin-left: 4px;
|
|
226
|
+
}
|
|
227
|
+
.ui-field__hint {
|
|
228
|
+
color: var(--text);
|
|
229
|
+
font-size: var(--text-sm);
|
|
230
|
+
margin-top: 7px;
|
|
231
|
+
line-height: 1.5;
|
|
232
|
+
}
|
|
233
|
+
.ui-field__error {
|
|
234
|
+
color: var(--pink);
|
|
235
|
+
font-size: var(--text-sm);
|
|
236
|
+
margin-top: 7px;
|
|
237
|
+
display: flex;
|
|
238
|
+
align-items: center;
|
|
239
|
+
gap: 6px;
|
|
240
|
+
}
|
|
241
|
+
.ui-field__error svg {
|
|
242
|
+
width: 16px;
|
|
243
|
+
height: 16px;
|
|
244
|
+
flex: none;
|
|
245
|
+
stroke-width: 2.4;
|
|
246
|
+
}
|
|
247
|
+
.ui-input,
|
|
248
|
+
.ui-textarea,
|
|
249
|
+
.ui-select {
|
|
250
|
+
font-family: var(--font-sans);
|
|
251
|
+
font-size: var(--text-base);
|
|
252
|
+
color: var(--strong);
|
|
253
|
+
background: var(--surface-2);
|
|
254
|
+
border: 1px solid var(--border);
|
|
255
|
+
border-radius: var(--radius-md);
|
|
256
|
+
padding: 12px 15px;
|
|
257
|
+
width: 100%;
|
|
258
|
+
transition: border-color var(--dur-med) var(--ease), box-shadow var(--dur-med) var(--ease);
|
|
259
|
+
}
|
|
260
|
+
.ui-textarea {
|
|
261
|
+
resize: vertical;
|
|
262
|
+
min-height: 96px;
|
|
263
|
+
line-height: 1.55;
|
|
264
|
+
}
|
|
265
|
+
.ui-input:hover,
|
|
266
|
+
.ui-textarea:hover,
|
|
267
|
+
.ui-select:hover {
|
|
268
|
+
border-color: var(--border-strong);
|
|
269
|
+
}
|
|
270
|
+
.ui-input:focus-visible,
|
|
271
|
+
.ui-textarea:focus-visible,
|
|
272
|
+
.ui-select:focus-visible {
|
|
273
|
+
outline: 2px solid transparent;
|
|
274
|
+
border-color: var(--accent);
|
|
275
|
+
box-shadow: var(--ring);
|
|
276
|
+
}
|
|
277
|
+
.ui-input::placeholder,
|
|
278
|
+
.ui-textarea::placeholder {
|
|
279
|
+
color: var(--muted);
|
|
280
|
+
opacity: 0.9;
|
|
281
|
+
}
|
|
282
|
+
.ui-input:disabled,
|
|
283
|
+
.ui-select:disabled,
|
|
284
|
+
.ui-textarea:disabled {
|
|
285
|
+
background: var(--disabled-surface);
|
|
286
|
+
border-color: var(--disabled-border);
|
|
287
|
+
color: var(--disabled-ink);
|
|
288
|
+
cursor: not-allowed;
|
|
289
|
+
}
|
|
290
|
+
.ui-input.is-invalid,
|
|
291
|
+
.ui-select.is-invalid,
|
|
292
|
+
.ui-textarea.is-invalid {
|
|
293
|
+
border-color: var(--pink);
|
|
294
|
+
}
|
|
295
|
+
.ui-input-group {
|
|
296
|
+
position: relative;
|
|
297
|
+
display: flex;
|
|
298
|
+
align-items: center;
|
|
299
|
+
}
|
|
300
|
+
.ui-input-group .ui-input {
|
|
301
|
+
padding-left: 42px;
|
|
302
|
+
}
|
|
303
|
+
.ui-input-group__icon {
|
|
304
|
+
position: absolute;
|
|
305
|
+
left: 14px;
|
|
306
|
+
width: 17px;
|
|
307
|
+
height: 17px;
|
|
308
|
+
color: var(--muted);
|
|
309
|
+
pointer-events: none;
|
|
310
|
+
}
|
|
311
|
+
.ui-input-group__icon svg {
|
|
312
|
+
width: 100%;
|
|
313
|
+
height: 100%;
|
|
314
|
+
stroke: currentColor;
|
|
315
|
+
fill: none;
|
|
316
|
+
stroke-width: 2.2;
|
|
317
|
+
}
|
|
318
|
+
.ui-select {
|
|
319
|
+
appearance: none;
|
|
320
|
+
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 24 24' fill='none' stroke='%23a29db6' stroke-width='2.4' stroke-linecap='round'%3E%3Cpath d='M6 9l6 6 6-6'/%3E%3C/svg%3E");
|
|
321
|
+
background-repeat: no-repeat;
|
|
322
|
+
background-position: right 15px center;
|
|
323
|
+
padding-right: 40px;
|
|
324
|
+
cursor: pointer;
|
|
325
|
+
}
|
|
326
|
+
:root[data-theme=light] .ui-select {
|
|
327
|
+
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 24 24' fill='none' stroke='%235c6270' stroke-width='2.4' stroke-linecap='round'%3E%3Cpath d='M6 9l6 6 6-6'/%3E%3C/svg%3E");
|
|
328
|
+
}
|
|
329
|
+
.ui-check {
|
|
330
|
+
display: inline-flex;
|
|
331
|
+
align-items: flex-start;
|
|
332
|
+
gap: 11px;
|
|
333
|
+
cursor: pointer;
|
|
334
|
+
font-size: var(--text-base);
|
|
335
|
+
color: var(--text);
|
|
336
|
+
line-height: 1.5;
|
|
337
|
+
}
|
|
338
|
+
.ui-check input {
|
|
339
|
+
appearance: none;
|
|
340
|
+
width: 19px;
|
|
341
|
+
height: 19px;
|
|
342
|
+
flex: none;
|
|
343
|
+
margin-top: 1px;
|
|
344
|
+
border: 1.5px solid var(--border-strong);
|
|
345
|
+
border-radius: var(--radius-xs);
|
|
346
|
+
background: var(--surface-2);
|
|
347
|
+
cursor: pointer;
|
|
348
|
+
transition: border-color var(--dur-fast) var(--ease), background var(--dur-fast) var(--ease);
|
|
349
|
+
position: relative;
|
|
350
|
+
}
|
|
351
|
+
.ui-check input::before {
|
|
352
|
+
content: "";
|
|
353
|
+
position: absolute;
|
|
354
|
+
left: 50%;
|
|
355
|
+
top: 50%;
|
|
356
|
+
width: 24px;
|
|
357
|
+
height: 24px;
|
|
358
|
+
transform: translate(-50%, -50%);
|
|
359
|
+
}
|
|
360
|
+
.ui-check input[type=radio] {
|
|
361
|
+
border-radius: 50%;
|
|
362
|
+
}
|
|
363
|
+
.ui-check input:hover {
|
|
364
|
+
border-color: var(--accent);
|
|
365
|
+
}
|
|
366
|
+
.ui-check input:checked {
|
|
367
|
+
background: var(--accent);
|
|
368
|
+
border-color: var(--accent);
|
|
369
|
+
}
|
|
370
|
+
.ui-check input[type=checkbox]:checked::after {
|
|
371
|
+
content: "";
|
|
372
|
+
position: absolute;
|
|
373
|
+
left: 5px;
|
|
374
|
+
top: 1.5px;
|
|
375
|
+
width: 5px;
|
|
376
|
+
height: 10px;
|
|
377
|
+
border: solid var(--accent-contrast);
|
|
378
|
+
border-width: 0 2px 2px 0;
|
|
379
|
+
transform: rotate(45deg);
|
|
380
|
+
}
|
|
381
|
+
.ui-check input[type=radio]:checked::after {
|
|
382
|
+
content: "";
|
|
383
|
+
position: absolute;
|
|
384
|
+
inset: 4px;
|
|
385
|
+
border-radius: 50%;
|
|
386
|
+
background: var(--accent-contrast);
|
|
387
|
+
}
|
|
388
|
+
.ui-check input:focus-visible {
|
|
389
|
+
outline: 2px solid transparent;
|
|
390
|
+
box-shadow: var(--ring);
|
|
391
|
+
}
|
|
392
|
+
.ui-switch {
|
|
393
|
+
--sw-w: 44px;
|
|
394
|
+
--sw-h: 26px;
|
|
395
|
+
position: relative;
|
|
396
|
+
display: inline-block;
|
|
397
|
+
width: var(--sw-w);
|
|
398
|
+
height: var(--sw-h);
|
|
399
|
+
flex: none;
|
|
400
|
+
}
|
|
401
|
+
.ui-switch input {
|
|
402
|
+
position: absolute;
|
|
403
|
+
opacity: 0;
|
|
404
|
+
width: 0;
|
|
405
|
+
height: 0;
|
|
406
|
+
}
|
|
407
|
+
.ui-switch__track {
|
|
408
|
+
position: absolute;
|
|
409
|
+
inset: 0;
|
|
410
|
+
background: var(--surface-3);
|
|
411
|
+
border-radius: var(--radius-pill);
|
|
412
|
+
cursor: pointer;
|
|
413
|
+
transition: background var(--dur-med) var(--ease);
|
|
414
|
+
}
|
|
415
|
+
.ui-switch__track::before {
|
|
416
|
+
content: "";
|
|
417
|
+
position: absolute;
|
|
418
|
+
top: 3px;
|
|
419
|
+
left: 3px;
|
|
420
|
+
width: calc(var(--sw-h) - 6px);
|
|
421
|
+
height: calc(var(--sw-h) - 6px);
|
|
422
|
+
background: var(--control-knob);
|
|
423
|
+
border: 1px solid var(--border-strong);
|
|
424
|
+
box-sizing: border-box;
|
|
425
|
+
border-radius: 50%;
|
|
426
|
+
transition: transform var(--dur-med) var(--ease);
|
|
427
|
+
}
|
|
428
|
+
.ui-switch input:checked + .ui-switch__track {
|
|
429
|
+
background: var(--accent);
|
|
430
|
+
}
|
|
431
|
+
.ui-switch input:checked + .ui-switch__track::before {
|
|
432
|
+
transform: translateX(calc(var(--sw-w) - var(--sw-h)));
|
|
433
|
+
}
|
|
434
|
+
.ui-switch input:focus-visible + .ui-switch__track {
|
|
435
|
+
outline: 2px solid transparent;
|
|
436
|
+
box-shadow: var(--ring);
|
|
437
|
+
}
|
|
438
|
+
.ui-switch input:disabled + .ui-switch__track {
|
|
439
|
+
opacity: 0.5;
|
|
440
|
+
cursor: not-allowed;
|
|
441
|
+
}
|
|
442
|
+
|
|
443
|
+
/* src/Field.css */
|
|
444
|
+
.ui-field-number {
|
|
445
|
+
display: flex;
|
|
446
|
+
align-items: center;
|
|
447
|
+
position: relative;
|
|
448
|
+
}
|
|
449
|
+
.ui-field-number .ui-input {
|
|
450
|
+
padding-right: 4.5em;
|
|
451
|
+
}
|
|
452
|
+
.ui-field-number__unit {
|
|
453
|
+
position: absolute;
|
|
454
|
+
right: 15px;
|
|
455
|
+
color: var(--text);
|
|
456
|
+
pointer-events: none;
|
|
457
|
+
}
|
|
458
|
+
.ui-file {
|
|
459
|
+
display: flex;
|
|
460
|
+
flex-direction: column;
|
|
461
|
+
align-items: center;
|
|
462
|
+
gap: 8px;
|
|
463
|
+
padding: 24px;
|
|
464
|
+
border: 1px dashed var(--border);
|
|
465
|
+
border-radius: var(--radius-md);
|
|
466
|
+
background: var(--surface-2);
|
|
467
|
+
color: var(--text);
|
|
468
|
+
font-size: var(--text-base);
|
|
469
|
+
text-align: center;
|
|
470
|
+
overflow-wrap: anywhere;
|
|
471
|
+
}
|
|
472
|
+
.ui-file:hover {
|
|
473
|
+
border-color: var(--border-strong);
|
|
474
|
+
}
|
|
475
|
+
.ui-file:focus-within,
|
|
476
|
+
.ui-file.is-dragging {
|
|
477
|
+
border-color: var(--accent);
|
|
478
|
+
box-shadow: var(--ring);
|
|
479
|
+
outline: 2px solid transparent;
|
|
480
|
+
}
|
|
481
|
+
.ui-file.is-invalid {
|
|
482
|
+
border-color: var(--pink);
|
|
483
|
+
}
|
|
484
|
+
.ui-file__glyph {
|
|
485
|
+
display: flex;
|
|
486
|
+
padding: 12px;
|
|
487
|
+
border-radius: var(--radius-md);
|
|
488
|
+
background: var(--surface-3);
|
|
489
|
+
}
|
|
490
|
+
.ui-file__glyph svg {
|
|
491
|
+
width: 24px;
|
|
492
|
+
height: 24px;
|
|
493
|
+
}
|
|
494
|
+
.ui-file__choose {
|
|
495
|
+
position: relative;
|
|
496
|
+
display: inline-flex;
|
|
497
|
+
margin-top: 8px;
|
|
498
|
+
}
|
|
499
|
+
.ui-file__input {
|
|
500
|
+
position: absolute;
|
|
501
|
+
inset: 0;
|
|
502
|
+
width: 100%;
|
|
503
|
+
height: 100%;
|
|
504
|
+
opacity: 0;
|
|
505
|
+
cursor: pointer;
|
|
506
|
+
}
|
|
507
|
+
.ui-file.is-disabled {
|
|
508
|
+
background: var(--disabled-surface);
|
|
509
|
+
border-color: var(--disabled-border);
|
|
510
|
+
color: var(--disabled-ink);
|
|
511
|
+
}
|
|
512
|
+
.ui-file.is-disabled .ui-file__input {
|
|
513
|
+
cursor: not-allowed;
|
|
514
|
+
}
|
package/react/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as react from 'react';
|
|
2
|
-
import { ReactNode, ButtonHTMLAttributes, RefObject, MouseEvent, ElementType, ComponentPropsWithoutRef } from 'react';
|
|
2
|
+
import { ReactNode, ButtonHTMLAttributes, RefObject, MouseEvent, ElementType, ComponentPropsWithoutRef, InputHTMLAttributes, SelectHTMLAttributes, TextareaHTMLAttributes } from 'react';
|
|
3
3
|
|
|
4
4
|
declare function Icon({ name }: {
|
|
5
5
|
name: string;
|
|
@@ -489,7 +489,44 @@ type TabsProps = {
|
|
|
489
489
|
};
|
|
490
490
|
declare function Tabs({ items, value, onChange, label }: TabsProps): react.JSX.Element;
|
|
491
491
|
|
|
492
|
+
type TimelineEvent = {
|
|
493
|
+
id: string;
|
|
494
|
+
actor: string;
|
|
495
|
+
dateTime: string;
|
|
496
|
+
timestamp: string;
|
|
497
|
+
description: string;
|
|
498
|
+
meta?: ReactNode;
|
|
499
|
+
undo?: {
|
|
500
|
+
label: string;
|
|
501
|
+
onUndo: () => void;
|
|
502
|
+
};
|
|
503
|
+
};
|
|
504
|
+
type TimelineProps = Omit<ComponentPropsWithoutRef<'ol'>, 'children' | 'reversed' | 'start'> & {
|
|
505
|
+
events: readonly TimelineEvent[];
|
|
506
|
+
};
|
|
507
|
+
declare function Timeline({ events, className, ...rest }: TimelineProps): react.JSX.Element;
|
|
508
|
+
|
|
509
|
+
type FieldMessage = {
|
|
510
|
+
label: string;
|
|
511
|
+
hint?: string;
|
|
512
|
+
error?: string;
|
|
513
|
+
};
|
|
514
|
+
type Wiring = 'id' | 'aria-describedby' | 'aria-invalid';
|
|
515
|
+
type TextFieldProps = FieldMessage & Omit<InputHTMLAttributes<HTMLInputElement>, Wiring | 'type'> & {
|
|
516
|
+
type?: 'text' | 'number' | 'email';
|
|
517
|
+
unit?: string;
|
|
518
|
+
};
|
|
519
|
+
declare function TextField({ label, hint, error, required, type, unit, className, ...props }: TextFieldProps): react.JSX.Element;
|
|
520
|
+
type TextAreaProps = FieldMessage & Omit<TextareaHTMLAttributes<HTMLTextAreaElement>, Wiring>;
|
|
521
|
+
declare function TextArea({ label, hint, error, required, className, ...props }: TextAreaProps): react.JSX.Element;
|
|
522
|
+
type SelectFieldProps = FieldMessage & Omit<SelectHTMLAttributes<HTMLSelectElement>, Wiring>;
|
|
523
|
+
declare function SelectField({ label, hint, error, required, className, children, ...props }: SelectFieldProps): react.JSX.Element;
|
|
524
|
+
type FileFieldProps = FieldMessage & Omit<InputHTMLAttributes<HTMLInputElement>, Wiring | 'type' | 'multiple' | 'value' | 'defaultValue' | 'onChange'> & {
|
|
525
|
+
onFileChange?: (file: File | null) => void;
|
|
526
|
+
};
|
|
527
|
+
declare function FileField({ label, hint, error, required, disabled, onFileChange, className, ...props }: FileFieldProps): react.JSX.Element;
|
|
528
|
+
|
|
492
529
|
declare const PAGE_SIZES: readonly number[];
|
|
493
530
|
declare const DEFAULT_PAGE_SIZE: number;
|
|
494
531
|
|
|
495
|
-
export { BackLink, type BackLinkOwnProps, type BackLinkProps, Badge, BusyRegion, type BusyRegionProps, Button, type ButtonProps, Card, type Column, type CommandGroup, type CommandItem, CommandPalette, type CommandPaletteProps, Confirm, type ConfirmProps, DEFAULT_PAGE_SIZE, DataTable, type DataTableProps, DeltaValue, type DeltaValueProps, Denied, type DeniedProps, Drawer, type DrawerProps, DrawerSection, type DrawerSectionProps, Dropdown, type DropdownBadge, type DropdownEntry, type DropdownItem, type DropdownProps, type DropdownRowProps, type DropdownSearch, type DropdownSection, type DropdownSeparator, type Filter, FilterBar, type FilterBarProps, Icon, KeyValueList, type KeyValueListProps, type KeyValueRow, Modal, type ModalProps, NumericValue, type NumericValueProps, PAGE_SIZES, Pagination, type PaginationProps, RowIdentity, type RowIdentityProps, type SegmentOption, Segmented, type SegmentedProps, Skeleton, type SkeletonProps, SkeletonTable, type SkeletonTableProps, Snippet, type SnippetProps, StatBand, type StatBandProps, type StatDelta, type StatFigure, type StatTone, type StatVariant, type TabItem, type TableSort, Tabs, type TabsProps, sortTableRows };
|
|
532
|
+
export { BackLink, type BackLinkOwnProps, type BackLinkProps, Badge, BusyRegion, type BusyRegionProps, Button, type ButtonProps, Card, type Column, type CommandGroup, type CommandItem, CommandPalette, type CommandPaletteProps, Confirm, type ConfirmProps, DEFAULT_PAGE_SIZE, DataTable, type DataTableProps, DeltaValue, type DeltaValueProps, Denied, type DeniedProps, Drawer, type DrawerProps, DrawerSection, type DrawerSectionProps, Dropdown, type DropdownBadge, type DropdownEntry, type DropdownItem, type DropdownProps, type DropdownRowProps, type DropdownSearch, type DropdownSection, type DropdownSeparator, FileField, type FileFieldProps, type Filter, FilterBar, type FilterBarProps, Icon, KeyValueList, type KeyValueListProps, type KeyValueRow, Modal, type ModalProps, NumericValue, type NumericValueProps, PAGE_SIZES, Pagination, type PaginationProps, RowIdentity, type RowIdentityProps, type SegmentOption, Segmented, type SegmentedProps, SelectField, type SelectFieldProps, Skeleton, type SkeletonProps, SkeletonTable, type SkeletonTableProps, Snippet, type SnippetProps, StatBand, type StatBandProps, type StatDelta, type StatFigure, type StatTone, type StatVariant, type TabItem, type TableSort, Tabs, type TabsProps, TextArea, type TextAreaProps, TextField, type TextFieldProps, Timeline, type TimelineEvent, type TimelineProps, sortTableRows };
|
package/react/dist/index.js
CHANGED
|
@@ -51,7 +51,7 @@ var cx = (...a) => a.filter(Boolean).join(" ");
|
|
|
51
51
|
var Button = forwardRef(function Button2({
|
|
52
52
|
variant = "secondary",
|
|
53
53
|
size = "md",
|
|
54
|
-
icon:
|
|
54
|
+
icon: icon5,
|
|
55
55
|
iconRight,
|
|
56
56
|
iconOnly,
|
|
57
57
|
block,
|
|
@@ -107,7 +107,7 @@ var Button = forwardRef(function Button2({
|
|
|
107
107
|
iconOnly && "ui-btn--icon"
|
|
108
108
|
);
|
|
109
109
|
const labelled = rest["aria-label"] != null || rest["aria-labelledby"] != null;
|
|
110
|
-
const fallback = typeof children === "string" && children.trim() ? children.trim() :
|
|
110
|
+
const fallback = typeof children === "string" && children.trim() ? children.trim() : icon5;
|
|
111
111
|
const named = iconOnly && !labelled && fallback ? { "aria-label": fallback, title: rest.title ?? fallback } : {};
|
|
112
112
|
return /* @__PURE__ */ jsxs(
|
|
113
113
|
"button",
|
|
@@ -141,7 +141,7 @@ var Button = forwardRef(function Button2({
|
|
|
141
141
|
if (!blockKey(event)) onKeyUp?.(event);
|
|
142
142
|
},
|
|
143
143
|
children: [
|
|
144
|
-
|
|
144
|
+
icon5 && /* @__PURE__ */ jsx2(Icon, { name: icon5 }),
|
|
145
145
|
!iconOnly && renderedChildren != null && /* @__PURE__ */ jsx2("span", { className: "ui-btn__label-slot", children: /* @__PURE__ */ jsx2("span", { className: "ui-btn__label", ref: labelRef, children: renderedChildren }) }),
|
|
146
146
|
iconRight && /* @__PURE__ */ jsx2(Icon, { name: iconRight }),
|
|
147
147
|
busy && /* @__PURE__ */ jsxs("span", { className: "ui-btn__dots", "aria-hidden": "true", children: [
|
|
@@ -1200,12 +1200,12 @@ function Denied({
|
|
|
1200
1200
|
title = "You don\u2019t have access",
|
|
1201
1201
|
sub,
|
|
1202
1202
|
need,
|
|
1203
|
-
icon:
|
|
1203
|
+
icon: icon5 = "lock",
|
|
1204
1204
|
className,
|
|
1205
1205
|
children
|
|
1206
1206
|
}) {
|
|
1207
1207
|
return /* @__PURE__ */ jsxs10("div", { className: cx4("ui-denied", className), children: [
|
|
1208
|
-
/* @__PURE__ */ jsx12("div", { className: "ui-denied__seal", children: /* @__PURE__ */ jsx12(Icon, { name:
|
|
1208
|
+
/* @__PURE__ */ jsx12("div", { className: "ui-denied__seal", children: /* @__PURE__ */ jsx12(Icon, { name: icon5 }) }),
|
|
1209
1209
|
/* @__PURE__ */ jsx12("div", { className: "ui-denied__title", children: title }),
|
|
1210
1210
|
sub && /* @__PURE__ */ jsx12("div", { className: "ui-denied__sub", children: sub }),
|
|
1211
1211
|
need && /* @__PURE__ */ jsxs10("div", { className: "ui-denied__need", children: [
|
|
@@ -1876,6 +1876,156 @@ function Tabs({ items, value, onChange, label }) {
|
|
|
1876
1876
|
] });
|
|
1877
1877
|
}
|
|
1878
1878
|
|
|
1879
|
+
// src/Timeline.tsx
|
|
1880
|
+
import { jsx as jsx21, jsxs as jsxs17 } from "react/jsx-runtime";
|
|
1881
|
+
function Timeline({ events, className, ...rest }) {
|
|
1882
|
+
return /* @__PURE__ */ jsx21("ol", { ...rest, role: "list", className: ["ui-timeline", className].filter(Boolean).join(" "), children: events.map((event) => /* @__PURE__ */ jsxs17("li", { className: "ui-timeline__event", children: [
|
|
1883
|
+
/* @__PURE__ */ jsxs17("div", { className: "ui-timeline__head", children: [
|
|
1884
|
+
/* @__PURE__ */ jsx21("span", { className: "ui-timeline__actor", children: event.actor }),
|
|
1885
|
+
/* @__PURE__ */ jsx21("time", { dateTime: event.dateTime, children: event.timestamp })
|
|
1886
|
+
] }),
|
|
1887
|
+
/* @__PURE__ */ jsx21("p", { className: "ui-timeline__description", children: event.description }),
|
|
1888
|
+
(event.meta != null || event.undo) && /* @__PURE__ */ jsxs17("div", { className: "ui-timeline__meta", children: [
|
|
1889
|
+
event.meta != null && /* @__PURE__ */ jsx21("span", { children: event.meta }),
|
|
1890
|
+
event.undo && /* @__PURE__ */ jsx21(Button, { variant: "ghost", size: "xs", className: "ui-btn ui-btn--ghost ui-btn--xs ui-timeline__undo", "aria-label": event.undo.label, onClick: event.undo.onUndo, children: "Undo" })
|
|
1891
|
+
] })
|
|
1892
|
+
] }, event.id)) });
|
|
1893
|
+
}
|
|
1894
|
+
|
|
1895
|
+
// src/Field.tsx
|
|
1896
|
+
import { useEffect as useEffect7, useId as useId8, useRef as useRef12, useState as useState7 } from "react";
|
|
1897
|
+
import { esc, icon as icon4 } from "@apliteni/apliteni-ui";
|
|
1898
|
+
import { jsx as jsx22, jsxs as jsxs18 } from "react/jsx-runtime";
|
|
1899
|
+
function Frame({ id, label, hint, error, required, children }) {
|
|
1900
|
+
return /* @__PURE__ */ jsxs18("div", { className: "ui-field", children: [
|
|
1901
|
+
/* @__PURE__ */ jsxs18("label", { className: "ui-field__label", htmlFor: id, children: [
|
|
1902
|
+
label,
|
|
1903
|
+
required && /* @__PURE__ */ jsx22("span", { className: "ui-field__req", "aria-hidden": "true", children: "*" })
|
|
1904
|
+
] }),
|
|
1905
|
+
children,
|
|
1906
|
+
(error || hint) && /* @__PURE__ */ jsx22(
|
|
1907
|
+
"div",
|
|
1908
|
+
{
|
|
1909
|
+
id: `${id}-message`,
|
|
1910
|
+
className: error ? "ui-field__error" : "ui-field__hint",
|
|
1911
|
+
dangerouslySetInnerHTML: { __html: (error ? icon4("alert") : "") + esc(error || hint) }
|
|
1912
|
+
}
|
|
1913
|
+
)
|
|
1914
|
+
] });
|
|
1915
|
+
}
|
|
1916
|
+
function wiring(id, hint, error) {
|
|
1917
|
+
return { id, "aria-describedby": error || hint ? `${id}-message` : void 0, "aria-invalid": error ? true : void 0 };
|
|
1918
|
+
}
|
|
1919
|
+
function TextField({ label, hint, error, required, type = "text", unit, className = "", ...props }) {
|
|
1920
|
+
const id = useId8();
|
|
1921
|
+
const hasUnit = type === "number" && !!unit;
|
|
1922
|
+
const describedBy = [error || hint ? `${id}-message` : "", hasUnit ? `${id}-unit` : ""].filter(Boolean).join(" ") || void 0;
|
|
1923
|
+
const control = /* @__PURE__ */ jsx22(
|
|
1924
|
+
"input",
|
|
1925
|
+
{
|
|
1926
|
+
...props,
|
|
1927
|
+
...wiring(id, hint, error),
|
|
1928
|
+
required,
|
|
1929
|
+
type,
|
|
1930
|
+
"aria-describedby": describedBy,
|
|
1931
|
+
inputMode: type === "number" ? "decimal" : props.inputMode,
|
|
1932
|
+
className: `ui-input${error ? " is-invalid" : ""} ${className}`
|
|
1933
|
+
}
|
|
1934
|
+
);
|
|
1935
|
+
return /* @__PURE__ */ jsx22(Frame, { ...{ id, label, hint, error, required }, children: hasUnit ? /* @__PURE__ */ jsxs18("div", { className: "ui-field-number", children: [
|
|
1936
|
+
control,
|
|
1937
|
+
/* @__PURE__ */ jsx22("span", { id: `${id}-unit`, className: "ui-field-number__unit", children: unit })
|
|
1938
|
+
] }) : control });
|
|
1939
|
+
}
|
|
1940
|
+
function TextArea({ label, hint, error, required, className = "", ...props }) {
|
|
1941
|
+
const id = useId8();
|
|
1942
|
+
return /* @__PURE__ */ jsx22(Frame, { ...{ id, label, hint, error, required }, children: /* @__PURE__ */ jsx22(
|
|
1943
|
+
"textarea",
|
|
1944
|
+
{
|
|
1945
|
+
rows: 4,
|
|
1946
|
+
...props,
|
|
1947
|
+
...wiring(id, hint, error),
|
|
1948
|
+
required,
|
|
1949
|
+
className: `ui-textarea${error ? " is-invalid" : ""} ${className}`
|
|
1950
|
+
}
|
|
1951
|
+
) });
|
|
1952
|
+
}
|
|
1953
|
+
function SelectField({ label, hint, error, required, className = "", children, ...props }) {
|
|
1954
|
+
const id = useId8();
|
|
1955
|
+
return /* @__PURE__ */ jsx22(Frame, { ...{ id, label, hint, error, required }, children: /* @__PURE__ */ jsx22(
|
|
1956
|
+
"select",
|
|
1957
|
+
{
|
|
1958
|
+
...props,
|
|
1959
|
+
...wiring(id, hint, error),
|
|
1960
|
+
required,
|
|
1961
|
+
className: `ui-select${error ? " is-invalid" : ""} ${className}`,
|
|
1962
|
+
children
|
|
1963
|
+
}
|
|
1964
|
+
) });
|
|
1965
|
+
}
|
|
1966
|
+
function FileField({ label, hint, error, required, disabled, onFileChange, className = "", ...props }) {
|
|
1967
|
+
const id = useId8();
|
|
1968
|
+
const input = useRef12(null);
|
|
1969
|
+
const [file, setFile] = useState7(null);
|
|
1970
|
+
const [dragging, setDragging] = useState7(false);
|
|
1971
|
+
useEffect7(() => {
|
|
1972
|
+
const form = input.current?.form;
|
|
1973
|
+
const reset = () => {
|
|
1974
|
+
setFile(null);
|
|
1975
|
+
setDragging(false);
|
|
1976
|
+
};
|
|
1977
|
+
form?.addEventListener("reset", reset);
|
|
1978
|
+
return () => form?.removeEventListener("reset", reset);
|
|
1979
|
+
}, []);
|
|
1980
|
+
const update = (next) => {
|
|
1981
|
+
setFile(next);
|
|
1982
|
+
onFileChange?.(next);
|
|
1983
|
+
};
|
|
1984
|
+
return /* @__PURE__ */ jsx22(Frame, { ...{ id, label, hint, error, required }, children: /* @__PURE__ */ jsxs18(
|
|
1985
|
+
"div",
|
|
1986
|
+
{
|
|
1987
|
+
className: `ui-file${dragging && !disabled ? " is-dragging" : ""}${file ? " has-file" : ""}${error ? " is-invalid" : ""}${disabled ? " is-disabled" : ""}`,
|
|
1988
|
+
onDragOver: (event) => {
|
|
1989
|
+
event.preventDefault();
|
|
1990
|
+
if (!disabled) setDragging(true);
|
|
1991
|
+
},
|
|
1992
|
+
onDragLeave: (event) => {
|
|
1993
|
+
if (!event.currentTarget.contains(event.relatedTarget)) setDragging(false);
|
|
1994
|
+
},
|
|
1995
|
+
onDrop: (event) => {
|
|
1996
|
+
event.preventDefault();
|
|
1997
|
+
setDragging(false);
|
|
1998
|
+
if (disabled || !event.dataTransfer.files.length || !input.current) return;
|
|
1999
|
+
const transfer = new DataTransfer();
|
|
2000
|
+
transfer.items.add(event.dataTransfer.files[0]);
|
|
2001
|
+
input.current.files = transfer.files;
|
|
2002
|
+
update(transfer.files[0]);
|
|
2003
|
+
},
|
|
2004
|
+
children: [
|
|
2005
|
+
/* @__PURE__ */ jsx22("span", { className: "ui-file__glyph", children: /* @__PURE__ */ jsx22(Icon, { name: "upload" }) }),
|
|
2006
|
+
/* @__PURE__ */ jsx22("div", { "aria-live": "polite", children: file ? file.name : "Drop a file here" }),
|
|
2007
|
+
/* @__PURE__ */ jsx22("div", { children: "or choose one from your device" }),
|
|
2008
|
+
/* @__PURE__ */ jsxs18("span", { className: "ui-file__choose", children: [
|
|
2009
|
+
/* @__PURE__ */ jsx22("span", { className: "ui-btn ui-btn--secondary ui-btn--sm", "aria-hidden": "true", "aria-disabled": disabled || void 0, children: file ? "Replace file" : "Choose file" }),
|
|
2010
|
+
/* @__PURE__ */ jsx22(
|
|
2011
|
+
"input",
|
|
2012
|
+
{
|
|
2013
|
+
...props,
|
|
2014
|
+
...wiring(id, hint, error),
|
|
2015
|
+
ref: input,
|
|
2016
|
+
type: "file",
|
|
2017
|
+
required,
|
|
2018
|
+
disabled,
|
|
2019
|
+
className: `ui-file__input ${className}`,
|
|
2020
|
+
onChange: (event) => update(event.currentTarget.files?.[0] ?? null)
|
|
2021
|
+
}
|
|
2022
|
+
)
|
|
2023
|
+
] })
|
|
2024
|
+
]
|
|
2025
|
+
}
|
|
2026
|
+
) });
|
|
2027
|
+
}
|
|
2028
|
+
|
|
1879
2029
|
// src/index.ts
|
|
1880
2030
|
var PAGE_SIZES = KIT_PAGE_SIZES;
|
|
1881
2031
|
var DEFAULT_PAGE_SIZE3 = KIT_DEFAULT_PAGE_SIZE;
|
|
@@ -1894,6 +2044,7 @@ export {
|
|
|
1894
2044
|
Drawer,
|
|
1895
2045
|
DrawerSection,
|
|
1896
2046
|
Dropdown,
|
|
2047
|
+
FileField,
|
|
1897
2048
|
FilterBar,
|
|
1898
2049
|
Icon,
|
|
1899
2050
|
KeyValueList,
|
|
@@ -1903,10 +2054,14 @@ export {
|
|
|
1903
2054
|
Pagination,
|
|
1904
2055
|
RowIdentity,
|
|
1905
2056
|
Segmented,
|
|
2057
|
+
SelectField,
|
|
1906
2058
|
Skeleton,
|
|
1907
2059
|
SkeletonTable,
|
|
1908
2060
|
Snippet,
|
|
1909
2061
|
StatBand,
|
|
1910
2062
|
Tabs,
|
|
2063
|
+
TextArea,
|
|
2064
|
+
TextField,
|
|
2065
|
+
Timeline,
|
|
1911
2066
|
sortTableRows
|
|
1912
2067
|
};
|
package/src/styles/input.css
CHANGED