@antadesign/anta 0.3.1 → 0.3.3

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 (98) hide show
  1. package/dist/anta_helpers.d.ts +111 -0
  2. package/dist/anta_helpers.js +90 -1
  3. package/dist/calendar-core.d.ts +126 -0
  4. package/dist/calendar-core.js +289 -0
  5. package/dist/components/Button.d.ts +9 -1
  6. package/dist/components/Button.js +12 -18
  7. package/dist/components/Calendar.d.ts +80 -0
  8. package/dist/components/Calendar.js +220 -0
  9. package/dist/components/Checkbox.d.ts +21 -15
  10. package/dist/components/Checkbox.js +17 -7
  11. package/dist/components/Expander.d.ts +7 -1
  12. package/dist/components/Expander.js +4 -2
  13. package/dist/components/Input.d.ts +16 -8
  14. package/dist/components/Input.js +19 -11
  15. package/dist/components/InputDate.d.ts +87 -0
  16. package/dist/components/InputDate.js +278 -0
  17. package/dist/components/InputDate.module.css +1 -0
  18. package/dist/components/Menu.d.ts +5 -1
  19. package/dist/components/Menu.js +6 -2
  20. package/dist/components/MenuItem.d.ts +48 -7
  21. package/dist/components/MenuItem.js +71 -7
  22. package/dist/components/MenuSeparator.d.ts +13 -2
  23. package/dist/components/MenuSeparator.js +12 -2
  24. package/dist/components/Progress.d.ts +4 -1
  25. package/dist/components/Progress.js +4 -3
  26. package/dist/components/RadioGroup.d.ts +17 -15
  27. package/dist/components/RadioGroup.js +8 -8
  28. package/dist/components/Select.d.ts +255 -0
  29. package/dist/components/Select.js +290 -0
  30. package/dist/components/Select.module.css +1 -0
  31. package/dist/components/Tab.d.ts +37 -0
  32. package/dist/components/Tab.js +5 -0
  33. package/dist/components/TabPanel.d.ts +22 -0
  34. package/dist/components/TabPanel.js +5 -0
  35. package/dist/components/Tabs.d.ts +129 -0
  36. package/dist/components/Tabs.js +176 -0
  37. package/dist/components/Tabs.module.css +1 -0
  38. package/dist/components/Tag.d.ts +10 -9
  39. package/dist/components/Tag.js +2 -2
  40. package/dist/components/Text.d.ts +6 -5
  41. package/dist/components/Title.d.ts +4 -2
  42. package/dist/components/Tooltip.d.ts +13 -1
  43. package/dist/components/Tooltip.js +9 -0
  44. package/dist/elements/a-button.css +1 -1
  45. package/dist/elements/a-calendar.css +1 -0
  46. package/dist/elements/a-calendar.d.ts +76 -0
  47. package/dist/elements/a-calendar.js +190 -0
  48. package/dist/elements/a-checkbox.css +1 -1
  49. package/dist/elements/a-checkbox.d.ts +1 -2
  50. package/dist/elements/a-checkbox.js +5 -5
  51. package/dist/elements/a-expander.css +1 -1
  52. package/dist/elements/a-expander.d.ts +16 -5
  53. package/dist/elements/a-expander.js +65 -9
  54. package/dist/elements/a-icon.shapes.css +1 -1
  55. package/dist/elements/a-icon.shapes.d.ts +6 -1
  56. package/dist/elements/a-icon.shapes.js +9 -0
  57. package/dist/elements/a-input.css +1 -1
  58. package/dist/elements/a-input.d.ts +6 -0
  59. package/dist/elements/a-input.js +28 -9
  60. package/dist/elements/a-menu-group.css +1 -1
  61. package/dist/elements/a-menu-item.css +1 -1
  62. package/dist/elements/a-menu-item.d.ts +14 -4
  63. package/dist/elements/a-menu-item.js +17 -0
  64. package/dist/elements/a-menu-separator.css +1 -1
  65. package/dist/elements/a-menu.css +1 -1
  66. package/dist/elements/a-menu.d.ts +51 -8
  67. package/dist/elements/a-menu.js +285 -42
  68. package/dist/elements/a-progress.css +1 -1
  69. package/dist/elements/a-radio-group.d.ts +1 -3
  70. package/dist/elements/a-radio-group.js +13 -13
  71. package/dist/elements/a-radio.css +1 -1
  72. package/dist/elements/a-radio.d.ts +3 -11
  73. package/dist/elements/a-radio.js +3 -34
  74. package/dist/elements/a-tab.css +1 -0
  75. package/dist/elements/a-tab.d.ts +6 -0
  76. package/dist/elements/a-tab.js +15 -0
  77. package/dist/elements/a-tabpanel.css +1 -0
  78. package/dist/elements/a-tabs.css +1 -0
  79. package/dist/elements/a-tabs.d.ts +28 -0
  80. package/dist/elements/a-tabs.js +157 -0
  81. package/dist/elements/a-tag.css +1 -1
  82. package/dist/elements/a-text.css +1 -1
  83. package/dist/elements/a-text.d.ts +14 -13
  84. package/dist/elements/a-text.js +53 -23
  85. package/dist/elements/a-title.css +1 -1
  86. package/dist/elements/a-tooltip.css +1 -1
  87. package/dist/elements/a-tooltip.d.ts +16 -8
  88. package/dist/elements/a-tooltip.js +62 -16
  89. package/dist/elements/index.d.ts +4 -0
  90. package/dist/elements/index.js +10 -0
  91. package/dist/general_types.d.ts +252 -30
  92. package/dist/index.d.ts +15 -1
  93. package/dist/index.js +43 -1
  94. package/dist/jsx-runtime.d.ts +20 -7
  95. package/dist/jsx-runtime.js +6 -0
  96. package/dist/reset.css +1 -1
  97. package/dist/tokens.css +1 -1
  98. package/package.json +4 -2
@@ -13,6 +13,9 @@ export interface BaseProps {
13
13
  title?: string;
14
14
  /** Tab order. Set to `-1` to skip the element when tabbing. */
15
15
  tabIndex?: number;
16
+ /** React/Preact reconciliation key when rendered inside a list. Consumed by the
17
+ * JSX runtime (not forwarded as a DOM attribute). */
18
+ key?: string | number | null;
16
19
  /** Any `data-*` attribute is forwarded to the rendered element. */
17
20
  [key: `data-${string}`]: unknown;
18
21
  /** Any `aria-*` attribute is forwarded to the rendered element. */
@@ -145,6 +148,9 @@ export interface AProgressAttributes extends BaseAttributes {
145
148
  /** Colour variant, or any literal CSS colour for a custom tone (derived in
146
149
  * oklch). Named tones track light/dark automatically. */
147
150
  tone?: 'neutral' | 'brand' | 'info' | 'success' | 'warning' | 'critical' | (string & {});
151
+ /** Fully-round track (`border-radius: 999px`), or a custom radius via a length
152
+ * value (`round="6px"`). Presence-based for the boolean form. */
153
+ round?: boolean | number | string;
148
154
  /** ARIA role — the JSX wrapper sets this to `'progressbar'`. */
149
155
  role?: string;
150
156
  /** ARIA value-now (current). */
@@ -165,8 +171,9 @@ export interface AProgressAttributes extends BaseAttributes {
165
171
  export interface ATextAttributes extends BaseAttributes {
166
172
  /** Visual priority. Maps to text-1..text-5. */
167
173
  priority?: 'primary' | 'secondary' | 'tertiary' | 'quaternary' | 'quinary';
168
- /** Color tint. Applies the matching `--text-{N}-{tone}` palette. */
169
- tone?: 'brand' | 'info' | 'success' | 'warning' | 'critical';
174
+ /** Color tint. `neutral` (default) is the untinted `--text-{N}` scale;
175
+ * the others apply the matching `--text-{N}-{tone}` palette. */
176
+ tone?: 'neutral' | 'brand' | 'info' | 'success' | 'warning' | 'critical';
170
177
  /** Type scale. `small` = 13/16, `medium` (default) = 15/20, `large` = 17/24. */
171
178
  size?: 'small' | 'medium' | 'large';
172
179
  /** Render as inline-block instead of the default block. */
@@ -198,8 +205,9 @@ export interface ATitleAttributes extends BaseAttributes {
198
205
  level?: string;
199
206
  /** Visual priority. Maps to text-1..text-5. */
200
207
  priority?: 'primary' | 'secondary' | 'tertiary' | 'quaternary' | 'quinary';
201
- /** Color tint. Applies the matching `--text-{N}-{tone}` palette. */
202
- tone?: 'brand' | 'info' | 'success' | 'warning' | 'critical';
208
+ /** Color tint. `neutral` (default) is the untinted `--text-{N}` scale;
209
+ * the others apply the matching `--text-{N}-{tone}` palette. */
210
+ tone?: 'neutral' | 'brand' | 'info' | 'success' | 'warning' | 'critical';
203
211
  /** ARIA role — the JSX wrapper sets this to `'heading'`. */
204
212
  role?: string;
205
213
  /** ARIA heading level — the JSX wrapper sets this to match `level`. */
@@ -224,9 +232,9 @@ export interface ATagAttributes extends BaseAttributes {
224
232
  /** Size variant. `small` = 16px tall, `medium` (default) = 20px,
225
233
  * `large` = 24px. */
226
234
  size?: 'small' | 'medium' | 'large';
227
- /** Render in normal case instead of the default uppercase.
235
+ /** Render in all-caps instead of the default normal (mixed) case.
228
236
  * Presence-based (`''` on, omit off). */
229
- nocaps?: boolean | '';
237
+ allcaps?: boolean | '';
230
238
  }
231
239
  /**
232
240
  * Attributes for the `<a-expander>` collapsible disclosure.
@@ -258,6 +266,11 @@ export interface AExpanderAttributes extends BaseAttributes {
258
266
  /** Disables the header: not clickable or focusable, hover affordance
259
267
  * off, text dimmed. The open state freezes as-is. Presence-based. */
260
268
  disabled?: boolean | '';
269
+ /** Round corners sized to half the folded (header) height — a pill when folded,
270
+ * the same radius when expanded (the element measures the header and publishes
271
+ * `--_expander-round-radius`). A length value (`round="12px"`) is a fixed radius
272
+ * that overrides the measurement. Presence-based for the boolean form. */
273
+ round?: boolean | number | string;
261
274
  /** Semantic tone, or any literal CSS color for a one-off custom tone.
262
275
  * Named tones re-point the text + filled surface palette; a custom
263
276
  * color keeps its hue with lightness/chroma pinned. `'neutral'` is the
@@ -321,6 +334,17 @@ export interface ATooltipAttributes extends BaseAttributes {
321
334
  /** Make the bubble hoverable/clickable (pointer events on, stays open while
322
335
  * hovered). Always pinned. Presence-based (`''` on, omit off). */
323
336
  interactive?: boolean | '';
337
+ /** Only show when the measured target is actually truncated/clipped (its text
338
+ * overflows). UI-thread layout read, re-measured per show. Defaults to the
339
+ * nearest Anta ellipsizing label part (`a-tab-label` / `a-button-label`) in the
340
+ * anchor, then the anchor itself. Presence-based (`''` on, omit off). */
341
+ 'truncated-only'?: boolean | '';
342
+ /** Round the bubble (20px radius), or a custom radius via a length value
343
+ * (`round="12px"`). Presence-based for the boolean form. */
344
+ round?: boolean | number | string;
345
+ /** CSS selector (resolved within the anchor) for the element whose overflow a
346
+ * `truncated-only` tooltip measures. */
347
+ 'truncated-selector'?: string;
324
348
  /** HTML `id`. */
325
349
  id?: string;
326
350
  }
@@ -335,16 +359,17 @@ export interface ATooltipAttributes extends BaseAttributes {
335
359
  * `@antadesign/anta`.
336
360
  */
337
361
  export interface ACheckboxAttributes extends BaseAttributes {
338
- /** Colour variant, or any literal CSS color for a one-off custom tone.
339
- * Named tones track light/dark mode automatically via the theme-aware role
340
- * tokens. `'neutral'` is the default (same as omitting it). */
362
+ /** Mark colour in every state checked fill *and* unselected box border — or any
363
+ * literal CSS color for a one-off custom tone. Named tones track light/dark mode
364
+ * automatically. `'neutral'` is the default (same as omitting it). The label + hint
365
+ * stay neutral — recolour them in plain CSS via the `--text-N-{tone}` tokens. */
341
366
  tone?: 'brand' | 'neutral' | 'info' | 'success' | 'warning' | 'critical' | (string & {});
367
+ /** Like `tone`, but coloured onto the checked mark only — the empty box stays
368
+ * neutral grey. Same value set as `tone`; if both are set, `tone` governs the
369
+ * off-state border and `tone-selected` the checked fill. */
370
+ 'tone-selected'?: 'brand' | 'neutral' | 'info' | 'success' | 'warning' | 'critical' | (string & {});
342
371
  /** Size variant. `small` = 14px, `medium` (default) = 16px, `large` = 18px box. */
343
372
  size?: 'small' | 'medium' | 'large';
344
- /** Visual priority. `primary` (default) fills the checked box with the tone
345
- * colour and draws a white checkmark; `secondary` keeps the box unfilled and
346
- * draws the border + checkmark in the tone colour (an outlined look). */
347
- priority?: 'primary' | 'secondary';
348
373
  /** Controlled state — the element reflects changes to this attribute. Use this
349
374
  * (driven from your store) for a controlled checkbox; use `default-state` for
350
375
  * an uncontrolled one. */
@@ -354,6 +379,9 @@ export interface ACheckboxAttributes extends BaseAttributes {
354
379
  'default-state'?: 'checked' | 'unchecked' | 'indeterminate';
355
380
  /** Disabled state. Presence-based (`''` on, omit off). */
356
381
  disabled?: boolean | '';
382
+ /** Round the mark to a circle (`::before` `border-radius: 999px`), or a rounded
383
+ * square via a length value (`round="5px"`). Presence-based for the boolean form. */
384
+ round?: boolean | number | string;
357
385
  /** Form field name — the key this checkbox submits under inside a `<form>`. */
358
386
  name?: string;
359
387
  /** Value submitted when checked. Defaults to `"on"`. */
@@ -414,6 +442,9 @@ export interface AInputAttributes extends BaseAttributes {
414
442
  /** Dim the leading/trailing adornments at rest (0.6); they brighten to full
415
443
  * when the field is hovered or focused. Presence-based. */
416
444
  'dim-actions'?: boolean | '';
445
+ /** Fully-round field (`border-radius: 999px`), or a custom radius via a length
446
+ * value (`round="10px"`). Presence-based for the boolean form. */
447
+ round?: boolean | number | string;
417
448
  /** Size variant. small=24px, medium (default)=28px, large=32px. */
418
449
  size?: 'small' | 'medium' | 'large';
419
450
  /** Single-line input type (ignored when multiline). `search` is intentionally
@@ -447,6 +478,60 @@ export interface AInputAttributes extends BaseAttributes {
447
478
  'aria-invalid'?: 'true' | 'false' | boolean;
448
479
  'aria-label'?: string;
449
480
  }
481
+ /**
482
+ * Attributes for the `<a-calendar>` custom element — a **light-DOM,
483
+ * form-associated** month grid, and the **interaction authority** for it. The
484
+ * element is the grid (a flat 7-column CSS grid whose children are the weekday
485
+ * headers + day cells), owns the submitted form value, and **dispatches the
486
+ * selection (`statechange` / `change`) and navigation (`navigate`) events** plus
487
+ * manages keyboard focus — so it works for a vanilla consumer, not only via the
488
+ * wrapper. It does **not** build or mutate its own contents: whoever renders into
489
+ * it (the `Calendar` JSX wrapper, or a vanilla consumer using the exported
490
+ * `buildMonth` engine) fills it with day cells and *re-renders on its events* —
491
+ * the `<a-radio-group>` model. Controlled by the presence of `value` (a pick only
492
+ * *requests* a change); uncontrolled with `defaultvalue` (a pick self-applies).
493
+ * For the typed, batteries-included wrapper use `Calendar` from `@antadesign/anta`.
494
+ *
495
+ * `:state(filled)` is the styling hook for "has a selection".
496
+ */
497
+ export interface ACalendarAttributes extends BaseAttributes {
498
+ /** Controlled selected date — ISO `YYYY-MM-DD`. Present → controlled (a pick
499
+ * only requests a change). Mirrored to the owning form via `ElementInternals`. */
500
+ value?: string;
501
+ /** Uncontrolled initial date / reset baseline — ISO `YYYY-MM-DD`. */
502
+ defaultvalue?: string;
503
+ /** Form field name — the selected ISO date submits under this key. */
504
+ name?: string;
505
+ /** Disable the whole calendar. Presence-based (`''` on, omit off). */
506
+ disabled?: boolean | '';
507
+ /** Focus signal — `"<iso>#<nonce>"`. When it changes, the element focuses the
508
+ * day cell whose `data-date` matches `<iso>` (set by the renderer after a
509
+ * month-changing keyboard move). */
510
+ 'data-focus'?: string;
511
+ /** Cancelable, bubbling `statechange` fired BEFORE a pick applies. `detail` is
512
+ * `{ next, prev, reason }` — ISO strings (or `null`); `reason` ∈
513
+ * `'user' | 'reset' | 'restore'`. `preventDefault()` vetoes a `'user'` pick in
514
+ * uncontrolled mode. */
515
+ onstatechange?: (e: CustomEvent<{
516
+ next: string | null;
517
+ prev: string | null;
518
+ reason: 'user' | 'reset' | 'restore';
519
+ }>) => void;
520
+ /** Native `change`, fired AFTER a selection applies (uncontrolled) and on
521
+ * reset/restore. */
522
+ onchange?: (e: Event) => void;
523
+ /** Keyboard navigation request — the element handles arrow / Home / End /
524
+ * PageUp / PageDown, focuses the target cell when it's rendered, and emits this
525
+ * bubbling `navigate` `CustomEvent` (`detail: { date }`, ISO) so the renderer can
526
+ * move the roving tab stop and flip the displayed month when needed. */
527
+ onnavigate?: (e: CustomEvent<{
528
+ date: string;
529
+ }>) => void;
530
+ /** ARIA — `role="group"` and the accessible name are set by the renderer (the
531
+ * `Calendar` wrapper wires `aria-labelledby` to the month heading). */
532
+ 'aria-label'?: string;
533
+ 'aria-labelledby'?: string;
534
+ }
450
535
  /**
451
536
  * Attributes for the `<a-menu>` custom element. Placed immediately after the
452
537
  * trigger it anchors to (root menu), or nested inside an `<a-menu-item>`
@@ -467,6 +552,10 @@ export interface AMenuAttributes extends BaseAttributes {
467
552
  * default; this opts out, making the submenu click-only. Presence-based
468
553
  * (`''` on, omit off). */
469
554
  nohover?: boolean | '';
555
+ /** Round: container softens to a 20px radius and its items go fully round. A
556
+ * length value (`round="12px"`) tunes the container radius only (items stay
557
+ * pills). Presence-based for the boolean form. */
558
+ round?: boolean | number | string;
470
559
  /** Gap in pixels between the trigger and the menu. Defaults to 4. */
471
560
  offset?: number | string;
472
561
  /** Controlled open state (`'open'` / `'closed'`). Omit for uncontrolled;
@@ -494,9 +583,15 @@ export interface AMenuAttributes extends BaseAttributes {
494
583
  export interface AMenuItemAttributes extends BaseAttributes {
495
584
  /** Disabled state. Presence-based (`''` on, omit off). */
496
585
  disabled?: boolean | '';
497
- /** Semantic tone. Colors the label, icon, and hover tint. `'neutral'`
498
- * (the default) is the same as omitting it. */
499
- tone?: 'neutral' | 'brand' | 'info' | 'success' | 'warning' | 'critical';
586
+ /** Marks the item as selected a persistent background tint (the same
587
+ * resting look a pressed row shows), for building single- / multi-select
588
+ * menus. Presence-based (`''` on, omit off). */
589
+ selected?: boolean | '';
590
+ /** Semantic tone. Colors the label, icon, and hover/selected tint. A named tone,
591
+ * or any literal CSS color for a one-off custom tone (resolved through
592
+ * `--menu-item-tone-source`, hue/chroma kept, lightness pinned to the brand
593
+ * text). `'neutral'` (the default) is the same as omitting it. */
594
+ tone?: 'neutral' | 'brand' | 'info' | 'success' | 'warning' | 'critical' | (string & {});
500
595
  /** Keep the menu open after this item is chosen (toggles / multi-select),
501
596
  * instead of the default close-on-select. Presence-based (`''` on, omit
502
597
  * off). The universal form is `data-menu-open` (works on any element). */
@@ -545,6 +640,9 @@ export interface AButtonAttributes extends BaseAttributes {
545
640
  disabled?: boolean | '';
546
641
  /** Toggled-on / pressed state. Presence-based (`''` on, omit off). */
547
642
  selected?: boolean | '';
643
+ /** Fully-round (pill / circle) — `border-radius: 999px` — or a custom radius via
644
+ * a length value (`round="20px"`). Presence-based for the boolean form. */
645
+ round?: boolean | number | string;
548
646
  /** Submit/reset semantics. */
549
647
  type?: 'button' | 'submit' | 'reset';
550
648
  /** Associate with a form by id when not nested inside it. */
@@ -565,16 +663,17 @@ export interface AButtonAttributes extends BaseAttributes {
565
663
  export interface ARadioAttributes extends BaseAttributes {
566
664
  /** This option's identity / submitted value. */
567
665
  value?: string;
568
- /** Colour variant, or any literal CSS color for a one-off custom tone.
569
- * Named tones track light/dark mode automatically via the theme-aware role
570
- * tokens. `'neutral'` is the default (same as omitting it). */
666
+ /** Mark colour in every state selected ring fill + dot *and* unselected ring
667
+ * border or any literal CSS color for a one-off custom tone. Named tones track
668
+ * light/dark mode. `'neutral'` is the default. The label + hint stay neutral —
669
+ * recolour them in plain CSS via the `--text-N-{tone}` tokens. */
571
670
  tone?: 'brand' | 'neutral' | 'info' | 'success' | 'warning' | 'critical' | (string & {});
671
+ /** Like `tone`, but coloured onto the selected mark only — an unselected ring stays
672
+ * neutral grey. Same value set as `tone`; if both are set, `tone` governs the
673
+ * off-state border and `tone-selected` the selected fill. */
674
+ 'tone-selected'?: 'brand' | 'neutral' | 'info' | 'success' | 'warning' | 'critical' | (string & {});
572
675
  /** Size variant. small=14px, medium=16px, large=18px control. */
573
676
  size?: 'small' | 'medium' | 'large';
574
- /** Visual priority. `primary` (default) fills the selected ring with the tone
575
- * colour and draws a white dot; `secondary` keeps the ring unfilled and draws
576
- * the border + dot in the tone colour (an outlined look). */
577
- priority?: 'primary' | 'secondary';
578
677
  /** Disabled state. Presence-based (`''` on, omit off). */
579
678
  disabled?: boolean | '';
580
679
  /** Selected state — connect-time seed for the standalone render path (no
@@ -614,16 +713,16 @@ export interface ARadioGroupAttributes extends BaseAttributes {
614
713
  'default-state'?: string;
615
714
  /** Form field name — the group submits `name=value`. */
616
715
  name?: string;
617
- /** Tone cascaded to children that don't set their own, or any literal CSS
618
- * color for a one-off custom tone. Inherits through CSS so every child
619
- * `<a-radio>` picks up the same fill curve. */
716
+ /** Mark tone cascaded to children that don't set their own, or any literal CSS
717
+ * color for a one-off custom tone. Colours every child's ring fill + dot *and*
718
+ * unselected border. The option text stays neutral — recolour it in plain CSS via
719
+ * the `--text-N-{tone}` tokens. */
620
720
  tone?: 'brand' | 'neutral' | 'info' | 'success' | 'warning' | 'critical' | (string & {});
721
+ /** Like `tone`, but coloured onto the selected option only — every unselected ring
722
+ * stays neutral grey. Cascaded to children that don't set their own. */
723
+ 'tone-selected'?: 'brand' | 'neutral' | 'info' | 'success' | 'warning' | 'critical' | (string & {});
621
724
  /** Size cascaded to children that don't set their own. */
622
725
  size?: 'small' | 'medium' | 'large';
623
- /** Visual priority cascaded to children that don't set their own. `primary`
624
- * (default) fills the selected ring with the tone colour; `secondary` keeps it
625
- * unfilled and draws the border + dot in the tone colour (an outlined look). */
626
- priority?: 'primary' | 'secondary';
627
726
  /** Validation/feedback tone for the group hint — same set as `<a-input>`'s
628
727
  * `status`. Recolours `<a-radio-group-hint>`; omit for the neutral default. */
629
728
  status?: 'neutral' | 'brand' | 'info' | 'success' | 'warning' | 'critical';
@@ -656,3 +755,126 @@ export interface ARadioGroupAttributes extends BaseAttributes {
656
755
  'aria-label'?: string;
657
756
  'aria-labelledby'?: string;
658
757
  }
758
+ /**
759
+ * Attributes for the `<a-tab>` custom element — one tab in a tablist. Presentational,
760
+ * the sibling of `<a-radio>`: the parent `<a-tabs>` owns selection, keyboard, and
761
+ * scrolling. The selected look comes from the element's `:state(selected)` (set by the
762
+ * tablist via the `selected` property), not a host attribute. There is no `Tab` web
763
+ * component to render directly — `Tabs` renders these from its `<Tab>` children, and
764
+ * hand-authors write `<a-tab>` directly inside an `<a-tabs>`. Wrap the visible label in
765
+ * `<a-tab-label>` (as `Tabs` does) so it carries the optical baseline nudge, truncates
766
+ * with an ellipsis when constrained, and keeps a sibling `<a-icon>` centered — exactly
767
+ * like `<a-button-label>`.
768
+ */
769
+ export interface ATabAttributes extends BaseAttributes {
770
+ /** This tab's identity / the value reported when it's selected. */
771
+ value?: string;
772
+ /** Per-tab tone override (same vocabulary as `<a-tabs tone>`): colours this tab's
773
+ * label + icons and, when selected, its indicator. Named tones tone the sliding
774
+ * indicator too; a custom literal colour tones the indicator only in `noslide`.
775
+ * Custom tones also set `--tabs-tone-source` on the tab (via the wrapper's style). */
776
+ tone?: 'neutral' | 'brand' | 'info' | 'success' | 'warning' | 'critical' | (string & {});
777
+ /** Selected state — connect-time seed for the standalone render path (no tablist).
778
+ * In an `<a-tabs>`, the tablist drives `:state(selected)` directly and this
779
+ * attribute is ignored. Presence-based (`''` on, omit off). */
780
+ selected?: boolean | '';
781
+ /** Disabled state. Presence-based (`''` on, omit off). */
782
+ disabled?: boolean | '';
783
+ /** Fully-round this tab's box (`--tab-radius: 999px`). `<a-tabs round>` sets it
784
+ * strip-wide instead. Presence-based (`''` on, omit off) — no custom value. */
785
+ round?: boolean | '';
786
+ /** ARIA — `role="tab"` is set by the consumer (`Tabs` on each tab, or a hand-author),
787
+ * and `aria-controls` points at the paired panel. `aria-selected` is published by
788
+ * the element through `ElementInternals` (off the DOM), driven by the `selected`
789
+ * property the tablist sets — not a DOM attribute. `tabindex` (inherited from
790
+ * `BaseAttributes`) is set by `Tabs` — every enabled tab is its own tab stop
791
+ * (`tabindex="0"`) — not by the element. */
792
+ role?: 'tab';
793
+ 'aria-controls'?: string;
794
+ 'aria-disabled'?: 'true' | 'false';
795
+ }
796
+ /**
797
+ * Attributes for the `<a-tabs>` custom element — the tablist + single-select
798
+ * coordinator. No shadow DOM: `<a-tab>` children are plain light-DOM, laid out by
799
+ * `a-tabs.css`, so the strip is restylable with ordinary CSS and usable hand-assembled.
800
+ * Unlike `<a-radio-group>` it is NOT form-associated (a tablist submits nothing), and
801
+ * the panels live outside it (siblings the `Tabs` wrapper shows/hides). The element
802
+ * coordinates **off-DOM only** — selection via each tab's `selected` property, focus via
803
+ * `internals.ariaActiveDescendantElement`, scroll via `scrollIntoView`. Roving
804
+ * `tabindex` (the JSX path) is rendered by the `Tabs` wrapper, not the element. For the
805
+ * typed JSX wrapper use `Tabs` from `@antadesign/anta`.
806
+ */
807
+ export interface ATabsAttributes extends BaseAttributes {
808
+ /** Controlled selected value (the active tab's `value`). Present → controlled: the
809
+ * element reflects changes to this attribute and a pick only dispatches
810
+ * `statechange`. Absent → uncontrolled (seed with `default-state`). */
811
+ state?: string;
812
+ /** Uncontrolled initial selected value — read once on connect. */
813
+ 'default-state'?: string;
814
+ /** Visual priority. `primary` (default) is the raised pill on a recessed track; `secondary`
815
+ * keeps that sizing but drops the track (selected = subtle active background fill, no
816
+ * border); `tertiary` is a bottom-underline under the selected tab only (no track, no rest
817
+ * line). `tone` tints secondary + tertiary; primary stays neutral. */
818
+ priority?: 'primary' | 'secondary' | 'tertiary';
819
+ /** Tone applied to the selected indicator/label, or any literal CSS color for a
820
+ * one-off custom tone (derived in oklch). `'neutral'` is the default. */
821
+ tone?: 'neutral' | 'brand' | 'info' | 'success' | 'warning' | 'critical' | (string & {});
822
+ /** Size variant. small=24px, medium (default)=28px, large=32px tall — matching Button's
823
+ * scale (the label leading runs a touch tighter, offset by 1px more block padding per side). */
824
+ size?: 'small' | 'medium' | 'large';
825
+ /** Layout + arrow-key axis. `'horizontal'` (default) ellipsizes labels when tabs
826
+ * overflow (scrolling is opt-in via CSS); `'vertical'` stacks them. */
827
+ orientation?: 'horizontal' | 'vertical';
828
+ /** Disable the sliding indicator. By default the selected-tab indicator is a single
829
+ * rectangle that animates between tabs via CSS anchor positioning; with `noslide` the
830
+ * highlight is painted on each tab and snaps with no movement (also the automatic
831
+ * fallback where anchor positioning isn't supported). Presence-based (`''` on, omit off). */
832
+ noslide?: boolean | '';
833
+ /** Disable the whole strip. Presence-based (`''` on, omit off). */
834
+ disabled?: boolean | '';
835
+ /** Fully-round tabs + sliding indicator (via `--tab-radius: 999px`) and the primary
836
+ * track well. A length value (`round="10px"`) applies to the top-level track well
837
+ * only (pills + indicator stay full). Presence-based for the boolean form. */
838
+ round?: boolean | number | string;
839
+ /** Fires whenever the active tab changes. `detail` carries `{ next, prev }` (values;
840
+ * `null` = none). Cancelable: a synchronous `preventDefault()` vetoes the pick in
841
+ * uncontrolled mode. All-lowercase to bind across both renderers (like
842
+ * `<a-radio-group>`). */
843
+ onstatechange?: (e: CustomEvent<{
844
+ next: string | null;
845
+ prev: string | null;
846
+ }>) => void;
847
+ /** Native `change`, fired *after* a selection applies (post-apply counterpart to
848
+ * `onstatechange`). Lowercase so both renderers bind the native event. */
849
+ onchange?: (e: Event) => void;
850
+ /** Strip focus enter / leave — wired from the bubbling `focusin` / `focusout` (focus
851
+ * lands on a tab, not the tablist). The `Tabs` wrapper maps its `onFocus`/`onBlur`. */
852
+ onfocusin?: (e: FocusEvent) => void;
853
+ onfocusout?: (e: FocusEvent) => void;
854
+ /** ARIA — set by the `Tabs` wrapper (the element never touches these). */
855
+ role?: 'tablist';
856
+ 'aria-orientation'?: 'horizontal' | 'vertical';
857
+ 'aria-disabled'?: 'true' | 'false';
858
+ 'aria-label'?: string;
859
+ }
860
+ /**
861
+ * Attributes for the `<a-tabpanel>` styled tag.
862
+ *
863
+ * `<a-tabpanel>` has no JS — it's a CSS-only styled element. The `Tabs` wrapper renders
864
+ * it, pairs it to its tab via id, and toggles visibility declaratively: `hidden`
865
+ * (display:none) or `data-hide="visibility"` (keeps the layout box), plus `inert` while
866
+ * hidden. Low-level attributes; for the typed JSX wrapper use `TabPanel` (inside `Tabs`)
867
+ * from `@antadesign/anta`.
868
+ */
869
+ export interface ATabpanelAttributes extends BaseAttributes {
870
+ /** Hidden via `display:none`. Presence-based (`''` on, omit off). */
871
+ hidden?: boolean | '';
872
+ /** Hidden via `visibility:hidden` (keeps the layout box). The `Tabs` wrapper sets
873
+ * this for `mounting="visibility"`. */
874
+ 'data-hide'?: 'visibility';
875
+ /** Removes the hidden panel from focus + the a11y tree. Presence-based. */
876
+ inert?: boolean | '';
877
+ /** ARIA — set by the `Tabs` wrapper. */
878
+ role?: 'tabpanel';
879
+ 'aria-labelledby'?: string;
880
+ }
package/dist/index.d.ts CHANGED
@@ -19,7 +19,7 @@
19
19
  export { Progress } from './components/Progress';
20
20
  export type { ProgressProps } from './components/Progress';
21
21
  export { Text } from './components/Text';
22
- export type { TextProps } from './components/Text';
22
+ export type { TextProps, ExpandMode } from './components/Text';
23
23
  export { Title } from './components/Title';
24
24
  export type { TitleProps } from './components/Title';
25
25
  export { Tag } from './components/Tag';
@@ -45,8 +45,22 @@ export { Expander } from './components/Expander';
45
45
  export type { ExpanderProps } from './components/Expander';
46
46
  export { Input } from './components/Input';
47
47
  export type { InputProps, InputChangeAttrs } from './components/Input';
48
+ export { Calendar } from './components/Calendar';
49
+ export type { CalendarProps, CalendarChangeAttrs } from './components/Calendar';
50
+ export { InputDate } from './components/InputDate';
51
+ export type { InputDateProps, InputDateChangeAttrs } from './components/InputDate';
52
+ export { buildMonth, getWeekdays, firstDayOfWeek, clampDate, isOutOfRange, parseISODate, parseDateInput, formatDateInput, dateFormatPattern, parseTimeInput, parseDateTimeInput, formatDateTimeInput, dateTimeFormatPattern, usesHour12, } from './calendar-core';
53
+ export type { CalendarDay, CalendarWeekday, CalendarMonth, BuildMonthOptions, ParseDateOptions, } from './calendar-core';
48
54
  export { RadioGroup } from './components/RadioGroup';
49
55
  export type { RadioGroupProps, RadioOption } from './components/RadioGroup';
56
+ export { Select } from './components/Select';
57
+ export type { SelectProps, SelectCommonProps, SelectOption, SelectGroup, SelectSubmenu, SelectItem, SelectChangeAttrs, OptionState, TriggerState, EmptyState, } from './components/Select';
58
+ export { Tabs } from './components/Tabs';
59
+ export type { TabsProps, TabsMounting, TabsChangeAttrs } from './components/Tabs';
60
+ export { Tab } from './components/Tab';
61
+ export type { TabProps } from './components/Tab';
62
+ export { TabPanel } from './components/TabPanel';
63
+ export type { TabPanelProps } from './components/TabPanel';
50
64
  export type { BaseProps, BaseAttributes } from './general_types';
51
65
  export { configure } from './jsx-runtime';
52
66
  export type { AntaIntrinsicElements } from './jsx-runtime';
package/dist/index.js CHANGED
@@ -13,25 +13,67 @@ import { MenuSeparator } from "./components/MenuSeparator";
13
13
  import { MenuGroup } from "./components/MenuGroup";
14
14
  import { Expander } from "./components/Expander";
15
15
  import { Input } from "./components/Input";
16
+ import { Calendar } from "./components/Calendar";
17
+ import { InputDate } from "./components/InputDate";
18
+ import {
19
+ buildMonth,
20
+ getWeekdays,
21
+ firstDayOfWeek,
22
+ clampDate,
23
+ isOutOfRange,
24
+ parseISODate,
25
+ parseDateInput,
26
+ formatDateInput,
27
+ dateFormatPattern,
28
+ parseTimeInput,
29
+ parseDateTimeInput,
30
+ formatDateTimeInput,
31
+ dateTimeFormatPattern,
32
+ usesHour12
33
+ } from "./calendar-core";
16
34
  import { RadioGroup } from "./components/RadioGroup";
35
+ import { Select } from "./components/Select";
36
+ import { Tabs } from "./components/Tabs";
37
+ import { Tab } from "./components/Tab";
38
+ import { TabPanel } from "./components/TabPanel";
17
39
  import { configure } from "./jsx-runtime";
18
40
  export {
19
41
  Button,
42
+ Calendar,
20
43
  Checkbox,
21
44
  Expander,
22
45
  ICON_SHAPES,
23
46
  ICON_SYNONYMS,
24
47
  Icon,
25
48
  Input,
49
+ InputDate,
26
50
  Menu,
27
51
  MenuGroup,
28
52
  MenuItem,
29
53
  MenuSeparator,
30
54
  Progress,
31
55
  RadioGroup,
56
+ Select,
57
+ Tab,
58
+ TabPanel,
59
+ Tabs,
32
60
  Tag,
33
61
  Text,
34
62
  Title,
35
63
  Tooltip,
36
- configure
64
+ buildMonth,
65
+ clampDate,
66
+ configure,
67
+ dateFormatPattern,
68
+ dateTimeFormatPattern,
69
+ firstDayOfWeek,
70
+ formatDateInput,
71
+ formatDateTimeInput,
72
+ getWeekdays,
73
+ isOutOfRange,
74
+ parseDateInput,
75
+ parseDateTimeInput,
76
+ parseISODate,
77
+ parseTimeInput,
78
+ usesHour12
37
79
  };
@@ -3,10 +3,11 @@ type ComponentType = string | Function | symbol;
3
3
  type JsxFunction = {
4
4
  h(type: ComponentType, props: Record<string, unknown> | null, ...children: unknown[]): unknown;
5
5
  }['h'];
6
- /** The two hooks the stateful wrappers (currently only `RadioGroup`) need. Typed
7
- * loosely to stay renderer-agnostic — any React-compatible hook implementation. */
6
+ /** The hooks the stateful wrappers need. Typed loosely to stay renderer-agnostic —
7
+ * any React-compatible hook implementation. */
8
8
  type UseState = <S>(initial: S | (() => S)) => [S, (next: S | ((prev: S) => S)) => void];
9
9
  type UseId = () => string;
10
+ type UseMemo = <T>(factory: () => T, deps: unknown[]) => T;
10
11
  declare let _Fragment: ComponentType;
11
12
  /**
12
13
  * Swap the underlying JSX factory (and, optionally, the hooks) used by all anta
@@ -15,32 +16,37 @@ declare let _Fragment: ComponentType;
15
16
  * Not needed for React or Preact-with-compat — those work automatically. Call this
16
17
  * before rendering any anta components when using Preact without compat aliasing,
17
18
  * or a custom JSX runtime. Pass `hooks` when your runtime's hooks don't resolve via
18
- * the `react` specifier (the stateful wrappers — `RadioGroup` — need `useState` /
19
- * `useId`); omit it and they default to whatever `react` resolves to.
19
+ * the `react` specifier (the stateful wrappers — `RadioGroup`, `Calendar`,
20
+ * `InputDate` — need `useState` / `useId` / `useMemo`); omit it and they default
21
+ * to whatever `react` resolves to.
20
22
  *
21
23
  * @example Preact without compat
22
24
  * ```ts
23
25
  * import { configure } from '@antadesign/anta'
24
26
  * import { h, Fragment } from 'preact'
25
- * import { useState, useId } from 'preact/hooks'
26
- * configure(h, Fragment, { useState, useId })
27
+ * import { useState, useId, useMemo } from 'preact/hooks'
28
+ * configure(h, Fragment, { useState, useId, useMemo })
27
29
  * ```
28
30
  */
29
31
  export declare function configure(jsx: JsxFunction, Fragment?: ComponentType, hooks?: {
30
32
  useState?: UseState;
31
33
  useId?: UseId;
34
+ useMemo?: UseMemo;
32
35
  }): void;
33
36
  /** Hooks indirection so wrappers depend on the configured renderer, not a hard
34
37
  * `import … from 'react'`. Call these exactly like the React hooks. */
35
38
  export declare function useState<S>(initial: S | (() => S)): [S, (next: S | ((prev: S) => S)) => void];
36
39
  export declare function useId(): string;
40
+ export declare function useMemo<T>(factory: () => T, deps: unknown[]): T;
37
41
  export declare function jsx(type: ComponentType, props: Record<string, unknown> | null, key?: string | number): unknown;
38
42
  export declare function jsxs(type: ComponentType, props: Record<string, unknown> | null, key?: string | number): unknown;
39
43
  export { _Fragment as Fragment };
40
- import type { AProgressAttributes, ATextAttributes, ATitleAttributes, ATagAttributes, AExpanderAttributes, AIconAttributes, AButtonAttributes, ACheckboxAttributes, ATooltipAttributes, AInputAttributes, ARadioAttributes, ARadioGroupAttributes, AMenuAttributes, AMenuItemAttributes, AMenuGroupAttributes, BaseAttributes } from './general_types';
44
+ import type { AProgressAttributes, ATextAttributes, ATitleAttributes, ATagAttributes, AExpanderAttributes, AIconAttributes, AButtonAttributes, ACheckboxAttributes, ATooltipAttributes, AInputAttributes, ACalendarAttributes, ARadioAttributes, ARadioGroupAttributes, AMenuAttributes, AMenuItemAttributes, AMenuGroupAttributes, ATabsAttributes, ATabAttributes, ATabpanelAttributes, BaseAttributes } from './general_types';
41
45
  export declare namespace JSX {
42
46
  interface IntrinsicElements extends React.JSX.IntrinsicElements, AntaIntrinsicElements {
43
47
  }
48
+ interface IntrinsicAttributes extends React.JSX.IntrinsicAttributes {
49
+ }
44
50
  }
45
51
  export interface AntaIntrinsicElements {
46
52
  'a-progress': AProgressAttributes;
@@ -64,6 +70,7 @@ export interface AntaIntrinsicElements {
64
70
  'a-checkbox-hint': BaseAttributes;
65
71
  'a-tooltip': ATooltipAttributes;
66
72
  'a-input': AInputAttributes;
73
+ 'a-calendar': ACalendarAttributes;
67
74
  'a-radio': ARadioAttributes;
68
75
  'a-radio-group': ARadioGroupAttributes;
69
76
  'a-radio-group-label': BaseAttributes;
@@ -74,7 +81,13 @@ export interface AntaIntrinsicElements {
74
81
  'a-menu': AMenuAttributes;
75
82
  'a-menu-item': AMenuItemAttributes;
76
83
  'a-menu-item-label': BaseAttributes;
84
+ 'a-menu-item-hint': BaseAttributes;
85
+ 'a-menu-item-text': BaseAttributes;
77
86
  'a-menu-separator': BaseAttributes;
78
87
  'a-menu-group': AMenuGroupAttributes;
79
88
  'a-menu-group-label': BaseAttributes;
89
+ 'a-tabs': ATabsAttributes;
90
+ 'a-tab': ATabAttributes;
91
+ 'a-tab-label': BaseAttributes;
92
+ 'a-tabpanel': ATabpanelAttributes;
80
93
  }
@@ -3,11 +3,13 @@ let _jsx = React.createElement;
3
3
  let _Fragment = React.Fragment;
4
4
  let _useState = React.useState;
5
5
  let _useId = React.useId;
6
+ let _useMemo = React.useMemo;
6
7
  function configure(jsx2, Fragment, hooks) {
7
8
  _jsx = jsx2;
8
9
  if (Fragment !== void 0) _Fragment = Fragment;
9
10
  if (hooks?.useState) _useState = hooks.useState;
10
11
  if (hooks?.useId) _useId = hooks.useId;
12
+ if (hooks?.useMemo) _useMemo = hooks.useMemo;
11
13
  }
12
14
  function useState(initial) {
13
15
  return _useState(initial);
@@ -15,6 +17,9 @@ function useState(initial) {
15
17
  function useId() {
16
18
  return _useId();
17
19
  }
20
+ function useMemo(factory, deps) {
21
+ return _useMemo(factory, deps);
22
+ }
18
23
  function jsx(type, props, key) {
19
24
  const { children, ...rest } = props ?? {};
20
25
  const p = key !== void 0 ? { ...rest, key } : rest;
@@ -37,5 +42,6 @@ export {
37
42
  jsx,
38
43
  jsxs,
39
44
  useId,
45
+ useMemo,
40
46
  useState
41
47
  };
package/dist/reset.css CHANGED
@@ -1 +1 @@
1
- @layer anta{*,*:before,*:after{box-sizing:border-box}*{margin:0}img,picture,video,canvas,svg{display:block;max-width:100%}input,button,textarea,select{font:inherit}p,h1,h2,h3,h4,h5,h6{overflow-wrap:break-word}p{text-wrap:pretty}h1,h2,h3,h4,h5,h6{text-wrap:balance}h1,h2,h3,h4,h5,h6{color:var(--text-1);font-weight:584.62;letter-spacing:0}h1{font-size:28px;line-height:32px;margin-block:0 16px}h2{font-size:24px;line-height:28px;margin-block:32px 12px}h3{font-size:20px;line-height:24px;margin-block:24px 12px}h4{font-size:17px;line-height:20px;margin-block:20px 8px}h5{font-size:15px;line-height:20px;margin-block:16px 8px}h6{font-size:13px;line-height:16px;margin-block:16px 4px}strong{font-weight:600}code{line-height:1em}code,kbd,samp,pre{letter-spacing:0}ul,ol{padding-left:3ch}:is(ul,ol)>li{margin-bottom:.5em}:is(ul,ol)>li::marker{color:var(--text-5)}menu{list-style:none;padding:0;margin:0}menu>li{margin:0}a:not(:where([role=button])),a:not(:where([role=button])):link,a:not(:where([role=button])):visited{color:var(--link-color);text-decoration:underline;text-decoration-style:solid;text-decoration-color:color-mix(in srgb,currentColor 75%,transparent);text-decoration-thickness:.5px;text-underline-offset:3px}@media(hover:hover)and (pointer:fine){a:not(:where([role=button])):hover{color:var(--link-color-hover);text-decoration-thickness:1px}}a:not(:where([role=button])):active{text-decoration-color:color-mix(in srgb,currentColor 75%,transparent)}::selection{background:color-mix(in srgb,var(--text-1-brand),transparent 85%)}table{border-collapse:collapse;font-variant-numeric:tabular-nums}caption{text-align:left;color:var(--text-3);padding-left:10px;margin-bottom:.25em}th,td{padding:5px 10px;text-align:left;vertical-align:top;border-bottom:1px solid var(--border-4)}thead th{font-weight:600}tfoot tr:last-child>:is(th,td),table:not(:has(tfoot)) tbody tr:last-child>:is(th,td){border-bottom:none}table[data-bordered]{border-collapse:separate;border-spacing:0;border:1px solid var(--border-4);border-radius:3px}table[data-bordered] :is(th,td){border-right:1px solid var(--border-4)}table[data-bordered] tr>:is(th,td):last-child{border-right:0}}
1
+ @layer anta{*,*:before,*:after{box-sizing:border-box}*{margin:0}img,picture,video,canvas,svg{display:block;max-width:100%}input,button,textarea,select{font:inherit}p,h1,h2,h3,h4,h5,h6{overflow-wrap:break-word}p{text-wrap:pretty}h1,h2,h3,h4,h5,h6{text-wrap:balance}h1,h2,h3,h4,h5,h6{color:var(--text-1);font-weight:584.62;letter-spacing:0}h1{font-size:28px;line-height:32px;margin-block:0 16px}h2{font-size:24px;line-height:28px;margin-block:32px 12px}h3{font-size:20px;line-height:24px;margin-block:24px 12px}h4{font-size:17px;line-height:20px;margin-block:20px 8px}h5{font-size:15px;line-height:20px;margin-block:16px 8px}h6{font-size:13px;line-height:16px;margin-block:16px 4px}strong{font-weight:600}code{line-height:1em}code,kbd,samp,pre{letter-spacing:0}ul,ol{padding-left:3ch}:is(ul,ol)>li{margin-bottom:.5em}:is(ul,ol)>li::marker{color:var(--text-5)}menu{list-style:none;padding:0;margin:0}menu>li{margin:0}a:not(:where([role=button])),a:not(:where([role=button])):link,a:not(:where([role=button])):visited{color:var(--link-color);text-decoration:underline;text-decoration-style:solid;text-decoration-color:color-mix(in srgb,currentColor 75%,transparent);text-decoration-thickness:.5px;text-underline-offset:3px}@media(hover:hover)and (pointer:fine){a:not(:where([role=button])):hover{color:var(--link-color-hover);text-decoration-thickness:1px}}a:not(:where([role=button])):active{text-decoration-color:color-mix(in srgb,currentColor 75%,transparent)}::selection{background:color-mix(in srgb,var(--text-1-brand),transparent 85%)}table{border-collapse:collapse;font-variant-numeric:lining-nums tabular-nums}caption{text-align:left;color:var(--text-3);padding-left:10px;margin-bottom:.25em}th,td{padding:5px 10px;text-align:left;vertical-align:top;border-bottom:1px solid var(--border-4)}thead th{font-weight:600}tfoot tr:last-child>:is(th,td),table:not(:has(tfoot)) tbody tr:last-child>:is(th,td){border-bottom:none}table[data-bordered]{border-collapse:separate;border-spacing:0;border:1px solid var(--border-4);border-radius:3px}table[data-bordered] :is(th,td){border-right:1px solid var(--border-4)}table[data-bordered] tr>:is(th,td):last-child{border-right:0}}