iryx-ui 0.5.0 → 0.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (42) hide show
  1. package/README.md +205 -3
  2. package/dist/component-names.d.ts +1 -1
  3. package/dist/components/Alert.vue.d.ts +19 -4
  4. package/dist/components/Badge.vue.d.ts +4 -3
  5. package/dist/components/Banner.vue.d.ts +81 -0
  6. package/dist/components/Combobox.vue.d.ts +3 -3
  7. package/dist/components/DropdownMenu.vue.d.ts +1 -1
  8. package/dist/components/Pagination.vue.d.ts +2 -0
  9. package/dist/components/Select.vue.d.ts +2 -2
  10. package/dist/components/Table.vue.d.ts +131 -0
  11. package/dist/components/index.d.ts +2 -0
  12. package/dist/composables/data-table.d.ts +93 -0
  13. package/dist/index.d.ts +3 -0
  14. package/dist/index.js +65 -60
  15. package/dist/node_modules/.pnpm/@hugeicons_core-free-icons@4.2.3/node_modules/@hugeicons/core-free-icons/dist/esm/index.js +15 -1
  16. package/dist/packages/iryx-ui/src/component-names.js +1 -1
  17. package/dist/packages/iryx-ui/src/components/Alert.vue_vue_type_script_setup_true_lang.js +51 -35
  18. package/dist/packages/iryx-ui/src/components/Badge.vue_vue_type_script_setup_true_lang.js +1 -2
  19. package/dist/packages/iryx-ui/src/components/Banner.js +5 -0
  20. package/dist/packages/iryx-ui/src/components/Banner.vue_vue_type_script_setup_true_lang.js +93 -0
  21. package/dist/packages/iryx-ui/src/components/Pagination.vue_vue_type_script_setup_true_lang.js +5 -1
  22. package/dist/packages/iryx-ui/src/components/Table.js +5 -0
  23. package/dist/packages/iryx-ui/src/components/Table.vue_vue_type_script_setup_true_lang.js +217 -0
  24. package/dist/packages/iryx-ui/src/components/index.js +62 -58
  25. package/dist/packages/iryx-ui/src/composables/data-table.js +106 -0
  26. package/dist/packages/iryx-ui/src/theme/alert.js +10 -21
  27. package/dist/packages/iryx-ui/src/theme/badge.js +37 -37
  28. package/dist/packages/iryx-ui/src/theme/banner.js +62 -0
  29. package/dist/packages/iryx-ui/src/theme/pagination.js +23 -13
  30. package/dist/packages/iryx-ui/src/theme/stat.js +4 -4
  31. package/dist/packages/iryx-ui/src/theme/table.js +62 -0
  32. package/dist/packages/iryx-ui/src/theme/toast.js +11 -26
  33. package/dist/theme/alert.d.ts +6 -12
  34. package/dist/theme/badge.d.ts +15 -12
  35. package/dist/theme/banner.d.ts +185 -0
  36. package/dist/theme/index.d.ts +2 -0
  37. package/dist/theme/pagination.d.ts +33 -0
  38. package/dist/theme/stat.d.ts +0 -3
  39. package/dist/theme/table.d.ts +230 -0
  40. package/dist/theme/toast.d.ts +0 -15
  41. package/package.json +1 -1
  42. package/theme.css +10 -0
package/README.md CHANGED
@@ -197,6 +197,24 @@ For a static re-brand, plain CSS works too — tokens are just variables:
197
197
  }
198
198
  ```
199
199
 
200
+ ### Typeface
201
+
202
+ The library ships **no webfont** — that would put font files, a licence and a
203
+ network request into every app whether it wanted them or not. It reads one
204
+ variable, defaulting to the system stack. Point it at your own family and
205
+ everything follows, including Tailwind's `font-sans`:
206
+
207
+ ```css
208
+ @import "@fontsource-variable/instrument-sans"; /* or a <link>, or self-hosted */
209
+
210
+ :root {
211
+ --iryx-font-sans: "Instrument Sans", ui-sans-serif, system-ui, sans-serif;
212
+ }
213
+ ```
214
+
215
+ Unlike the colour tokens, this one is not mode-specific — there is no `.dark`
216
+ counterpart to keep in sync.
217
+
200
218
  Available tokens, each usable as a Tailwind color (`bg-primary`,
201
219
  `text-muted-foreground`, …):
202
220
 
@@ -292,8 +310,9 @@ app.use(createIryxUi({ unstyled: true }))
292
310
 
293
311
  | Component | Description |
294
312
  | --- | --- |
295
- | `IAlert` | Inline banner in four variants, with a variant icon and optional dismiss |
296
- | `IBadge` | Status pillfive variants × `soft`/`solid` tones × three sizes, optional `dot` |
313
+ | `IAlert` | Inline, contextual message in four variants variant icon, `actions` slot, optional dismiss |
314
+ | `IBanner` | Page-level announcementfull-bleed, six variants, sticky top or fixed bottom |
315
+ | `IBadge` | Status pill — five variants × three sizes; `dot` moves the colour onto a leading dot |
297
316
  | `IToaster` | Host for `useToast()`; six viewport positions, stacking, action buttons |
298
317
  | `IDialog` | Modal with header/body/footer slots, `dismissible` and `showClose` |
299
318
  | `IConfirmDialog` | Host for `useConfirm()` — renders the promise-based confirmation |
@@ -308,9 +327,10 @@ app.use(createIryxUi({ unstyled: true }))
308
327
  | --- | --- |
309
328
  | `ITabs` | `solid` or `line` variants with an animated indicator, horizontal or vertical |
310
329
  | `IBreadcrumb` | Trail from an `items` array; the last crumb is marked as the current page |
311
- | `IPagination` | Page list with ellipsis, edge pages and prev/next controls |
330
+ | `IPagination` | Page list with ellipsis, edge pages and prev/next controls; `align` places it, `size` sets the button scale |
312
331
  | `IStepper` | Multi-step progress, horizontal or vertical, optional `linear` ordering |
313
332
  | `IStat` | KPI tile — label, value, signed delta with trend colour, and a hint |
333
+ | `ITable` | Data table — sorting, selection, expansion and per-cell slots, client- or server-driven |
314
334
 
315
335
  Every component supports `unstyled` and a `class` override; multi-part ones take a `ui` prop for per-slot classes.
316
336
 
@@ -607,6 +627,188 @@ The control inside a field automatically inherits its `id`, invalid styling and
607
627
 
608
628
  Use the `#label` / `#description` slots instead of the props when you need markup (a link, a badge) inside the text.
609
629
 
630
+ ### Alerts and banners
631
+
632
+ They look similar and do different jobs, so they're separate components.
633
+
634
+ **`IAlert` is contextual.** It sits in the flow next to the thing it's about —
635
+ a failed upload, a form that won't submit — boxed, with an icon and a title.
636
+ Danger and warning variants take `role="alert"` so a screen reader interrupts,
637
+ because the user caused it and needs to know now.
638
+
639
+ **`IBanner` is page-level.** It spans the full width and announces something
640
+ that isn't about any one element: a trial ending, scheduled maintenance. It's a
641
+ labelled `role="region"`, never an alert — it's ambient, so interrupting
642
+ someone mid-task would be wrong.
643
+
644
+ ```vue
645
+ <IBanner
646
+ v-model:open="showTrial"
647
+ variant="primary"
648
+ position="top"
649
+ title="Trial ends in 3 days."
650
+ description="Upgrade to keep your data."
651
+ closable
652
+ label="Trial notice"
653
+ >
654
+ <template #actions>
655
+ <IButton size="sm" variant="outline">Upgrade</IButton>
656
+ </template>
657
+ </IBanner>
658
+ ```
659
+
660
+ `position` is `static` (in flow), `top` (sticky) or `bottom` (fixed to the
661
+ viewport, with the rule moved to its top edge). `contained` keeps the text at a
662
+ readable measure while the fill still spans the window.
663
+
664
+ Both dismiss through `v-model:open`, so the usual case is one binding instead
665
+ of a `close` handler plus a `v-if`. `close` still fires if you need to persist
666
+ or confirm first:
667
+
668
+ ```vue
669
+ <IAlert v-model:open="visible" variant="danger" title="Upload failed" closable>
670
+ The file was larger than 10 MB.
671
+ <template #actions>
672
+ <IButton size="sm" @click="retry()">Retry</IButton>
673
+ </template>
674
+ </IAlert>
675
+ ```
676
+
677
+ ### Tables
678
+
679
+ `ITable` takes `rows` and `columns` and renders a real `<table>`. Columns are
680
+ plain objects — no render functions — and anything beyond the raw value is a
681
+ slot:
682
+
683
+ ```vue
684
+ <script setup>
685
+ const columns = [
686
+ { key: 'number', label: 'Invoice', sortable: true },
687
+ { key: 'customer.name', label: 'Customer', sortable: true, sortKey: 'customer_name' },
688
+ { key: 'total', label: 'Total', sortable: true, numeric: true },
689
+ { key: 'status', label: 'Status' },
690
+ ]
691
+ </script>
692
+
693
+ <template>
694
+ <ITable :rows="invoices" :columns="columns" label="Invoices">
695
+ <template #cell-total="{ value }">
696
+ {{ formatMoney(value) }}
697
+ </template>
698
+ <template #cell-status="{ row }">
699
+ <IBadge :variant="row.paid ? 'success' : 'warning'">
700
+ {{ row.paid ? 'Paid' : 'Due' }}
701
+ </IBadge>
702
+ </template>
703
+ </ITable>
704
+ </template>
705
+ ```
706
+
707
+ `key` doubles as the accessor (dot-notation reaches nested values) and the slot
708
+ suffix, so `#cell-customer.name` targets that column. `#header-<key>` replaces a
709
+ header the same way.
710
+
711
+ `numeric` gives a column tabular figures and end alignment, so amounts line up
712
+ digit-for-digit down the column instead of wandering with each glyph's width.
713
+ Set `align` alongside it to keep the figures but place the column differently.
714
+
715
+ #### Client or server
716
+
717
+ **The table never fetches.** It renders what you give it and emits what the
718
+ user did, so caching, cancellation and auth stay in your data layer.
719
+
720
+ Which mode it runs in is decided by one prop. Omit `total` and it sorts and
721
+ paginates `rows` itself. Provide `total` and it does neither — the rows you
722
+ passed are already the page the server returned, so it only reflects state and
723
+ emits changes:
724
+
725
+ ```vue
726
+ <ITable
727
+ v-model:sort="sort"
728
+ v-model:page="page"
729
+ :rows="data.rows"
730
+ :columns="columns"
731
+ :total="data.total"
732
+ :loading="pending"
733
+ />
734
+ ```
735
+
736
+ Watch those models and refetch. Sorting a column resets `page` to 1, since the
737
+ old page number means nothing against a reordered list.
738
+
739
+ #### State ownership
740
+
741
+ Every model is optional. Bind one and you own that state — put it in the URL, a
742
+ store, or `useState`. Leave it unbound and the table keeps it internally, so the
743
+ simple case needs no wiring:
744
+
745
+ | Model | Type |
746
+ | --- | --- |
747
+ | `v-model:sort` | `{ key, order } \| null` — `null` is "unsorted", distinct from never-sorted |
748
+ | `v-model:page` | `number`, 1-indexed |
749
+ | `v-model:perPage` | `number` |
750
+ | `v-model:selection` | `(string \| number)[]` of row keys |
751
+ | `v-model:expanded` | `(string \| number)[]` of row keys |
752
+
753
+ #### Selection and expansion
754
+
755
+ `selectable` adds a checkbox column whose header is tri-state over the rows on
756
+ screen. Selection is held as **row keys** (`rowKey`, default `'id'`), and
757
+ select-all only touches the current page, so selections made on other pages
758
+ survive. `isRowSelectable` vetoes a row — its checkbox is hidden and the header
759
+ skips it.
760
+
761
+ `expandable` adds a disclosure column and renders the `#expanded` slot beneath
762
+ an open row; `canExpandRow` vetoes it per row.
763
+
764
+ ```vue
765
+ <ITable
766
+ v-model:selection="selected"
767
+ :rows="rows"
768
+ :columns="columns"
769
+ selectable
770
+ expandable
771
+ :is-row-selectable="row => !row.locked"
772
+ >
773
+ <template #expanded="{ row }">
774
+ <div class="p-4">{{ row.notes }}</div>
775
+ </template>
776
+ </ITable>
777
+ ```
778
+
779
+ #### States and props
780
+
781
+ `loading` sets `aria-busy` and, when there is nothing to show yet, renders
782
+ `loadingRows` skeleton rows instead of the empty message. With rows already on
783
+ screen it leaves them in place, so a refetch doesn't blank the table. Otherwise
784
+ `emptyText` — or the `#empty` slot — takes over.
785
+
786
+ | Prop | What it does |
787
+ | --- | --- |
788
+ | `rowKey` | Field identifying a row. Default `'id'` |
789
+ | `clickableRows` | Emits `rowClick` and shows a pointer cursor |
790
+ | `striped` / `hoverable` / `stickyHeader` | Row and header treatment |
791
+ | `size` | `sm` / `md` / `lg` row density |
792
+ | `label` / `caption` | Accessible name, and an optional visible caption |
793
+
794
+ Headers are real `<button>`s, sorted columns carry `aria-sort`, and the table is
795
+ a plain `<table>`, so screen readers and keyboard users get the semantics for
796
+ free. Give it a `label` (or a `caption`) — a table with no accessible name is
797
+ hard to place when tabbing through a page.
798
+
799
+ #### Without the markup
800
+
801
+ `useDataTable()` holds the whole state machine — sorting, paging, selection,
802
+ expansion — and renders nothing, if you want the logic under your own markup:
803
+
804
+ ```ts
805
+ const table = useDataTable({
806
+ rows: () => rows.value,
807
+ columns: () => columns,
808
+ })
809
+ // table.pageRows, table.toggleSort, table.headerSelection, …
810
+ ```
811
+
610
812
  ## License
611
813
 
612
814
  [MIT](https://github.com/therok1/iryx-ui/blob/main/LICENSE)
@@ -3,5 +3,5 @@
3
3
  * Consumed by the Vue plugin (global registration) and the Nuxt module
4
4
  * (auto-imports). Keep in sync with `src/components/index.ts`.
5
5
  */
6
- export declare const componentNames: readonly ["Alert", "App", "Badge", "Breadcrumb", "Button", "ButtonGroup", "Card", "Checkbox", "Combobox", "ConfirmDialog", "Dialog", "DropdownMenu", "EmptyState", "Form", "FormField", "Input", "Label", "NumberInput", "Pagination", "Progress", "RadioGroup", "Select", "Separator", "Skeleton", "Stat", "Stepper", "Switch", "Tabs", "Textarea", "Toaster", "Tooltip"];
6
+ export declare const componentNames: readonly ["Alert", "App", "Badge", "Banner", "Breadcrumb", "Button", "ButtonGroup", "Card", "Checkbox", "Combobox", "ConfirmDialog", "Dialog", "DropdownMenu", "EmptyState", "Form", "FormField", "Input", "Label", "NumberInput", "Pagination", "Progress", "RadioGroup", "Select", "Separator", "Skeleton", "Stat", "Stepper", "Switch", "Table", "Tabs", "Textarea", "Toaster", "Tooltip"];
7
7
  export type ComponentName = (typeof componentNames)[number];
@@ -26,10 +26,21 @@ export interface AlertProps {
26
26
  content?: string;
27
27
  title?: string;
28
28
  description?: string;
29
+ actions?: string;
29
30
  close?: string;
30
31
  };
31
32
  }
32
- declare var __VLS_8: {}, __VLS_15: {}, __VLS_17: {}, __VLS_19: {};
33
+ type __VLS_Props = AlertProps;
34
+ type __VLS_ModelProps = {
35
+ /**
36
+ * Dismissal as a model, so the common case is one binding rather than a
37
+ * `close` handler plus a `v-if` in every consumer. `close` still fires, for
38
+ * callers that want to confirm or persist before it goes.
39
+ */
40
+ 'open'?: boolean;
41
+ };
42
+ type __VLS_PublicProps = __VLS_Props & __VLS_ModelProps;
43
+ declare var __VLS_8: {}, __VLS_15: {}, __VLS_17: {}, __VLS_19: {}, __VLS_21: {};
33
44
  type __VLS_Slots = {} & {
34
45
  icon?: (props: typeof __VLS_8) => any;
35
46
  } & {
@@ -37,12 +48,16 @@ type __VLS_Slots = {} & {
37
48
  } & {
38
49
  default?: (props: typeof __VLS_17) => any;
39
50
  } & {
40
- close?: (props: typeof __VLS_19) => any;
51
+ actions?: (props: typeof __VLS_19) => any;
52
+ } & {
53
+ close?: (props: typeof __VLS_21) => any;
41
54
  };
42
- declare const __VLS_base: import("vue").DefineComponent<AlertProps, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
55
+ declare const __VLS_base: import("vue").DefineComponent<__VLS_PublicProps, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
43
56
  close: () => any;
44
- }, string, import("vue").PublicProps, Readonly<AlertProps> & Readonly<{
57
+ "update:open": (value: boolean) => any;
58
+ }, string, import("vue").PublicProps, Readonly<__VLS_PublicProps> & Readonly<{
45
59
  onClose?: (() => any) | undefined;
60
+ "onUpdate:open"?: ((value: boolean) => any) | undefined;
46
61
  }>, {
47
62
  icon: IconLike | false;
48
63
  as: string;
@@ -4,10 +4,11 @@ export interface BadgeProps {
4
4
  /** Merge props onto the immediate child instead of rendering an element. */
5
5
  asChild?: boolean;
6
6
  variant?: 'neutral' | 'success' | 'warning' | 'danger' | 'info';
7
- /** `soft` is a tinted background; `solid` is a filled block of colour. */
8
- tone?: 'soft' | 'solid';
9
7
  size?: 'sm' | 'md' | 'lg';
10
- /** Show a small leading dot in the current text colour. */
8
+ /**
9
+ * Show a leading status dot. This also switches the look: the badge goes
10
+ * neutral and the dot alone carries the variant's colour.
11
+ */
11
12
  dot?: boolean;
12
13
  /** Text content. Ignored when the default slot is used. */
13
14
  label?: string;
@@ -0,0 +1,81 @@
1
+ import type { IconLike } from '../composables/icon';
2
+ export interface BannerProps {
3
+ /** Render as a different element or component. */
4
+ as?: string;
5
+ variant?: 'neutral' | 'info' | 'success' | 'warning' | 'danger' | 'primary';
6
+ /**
7
+ * `static` sits in the flow, `top` sticks to the top of the scroll
8
+ * container, `bottom` pins to the bottom of the viewport.
9
+ */
10
+ position?: 'static' | 'top' | 'bottom';
11
+ /** Bold lead-in before the message. */
12
+ title?: string;
13
+ /** Message text. Ignored when the default slot is used. */
14
+ description?: string;
15
+ /** Leading icon. None by default — a banner is ambient, not a status report. */
16
+ icon?: IconLike;
17
+ /** Constrain the text to a readable measure while the fill still spans full width. */
18
+ contained?: boolean;
19
+ align?: 'start' | 'center';
20
+ /** Render a dismiss button. */
21
+ closable?: boolean;
22
+ /** Accessible name for the dismiss button — override for non-English apps. */
23
+ closeLabel?: string;
24
+ /**
25
+ * Accessible name for the landmark. A banner is a region rather than an
26
+ * alert: it is ambient, so it must not interrupt a screen reader mid-task.
27
+ */
28
+ label?: string;
29
+ /** Skip built-in classes; you take over styling entirely. */
30
+ unstyled?: boolean;
31
+ class?: string;
32
+ /** Override classes per slot, e.g. `{ container: 'max-w-3xl' }`. */
33
+ ui?: {
34
+ root?: string;
35
+ container?: string;
36
+ icon?: string;
37
+ content?: string;
38
+ title?: string;
39
+ actions?: string;
40
+ close?: string;
41
+ };
42
+ }
43
+ type __VLS_Props = BannerProps;
44
+ type __VLS_ModelProps = {
45
+ /** Dismissal as a model, matching IAlert — bind it, or let the banner hide itself. */
46
+ 'open'?: boolean;
47
+ };
48
+ type __VLS_PublicProps = __VLS_Props & __VLS_ModelProps;
49
+ declare var __VLS_8: {}, __VLS_15: {}, __VLS_17: {}, __VLS_19: {}, __VLS_21: {};
50
+ type __VLS_Slots = {} & {
51
+ icon?: (props: typeof __VLS_8) => any;
52
+ } & {
53
+ title?: (props: typeof __VLS_15) => any;
54
+ } & {
55
+ default?: (props: typeof __VLS_17) => any;
56
+ } & {
57
+ actions?: (props: typeof __VLS_19) => any;
58
+ } & {
59
+ close?: (props: typeof __VLS_21) => any;
60
+ };
61
+ declare const __VLS_base: import("vue").DefineComponent<__VLS_PublicProps, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
62
+ close: () => any;
63
+ "update:open": (value: boolean) => any;
64
+ }, string, import("vue").PublicProps, Readonly<__VLS_PublicProps> & Readonly<{
65
+ onClose?: (() => any) | undefined;
66
+ "onUpdate:open"?: ((value: boolean) => any) | undefined;
67
+ }>, {
68
+ as: string;
69
+ closeLabel: string;
70
+ unstyled: boolean;
71
+ label: string;
72
+ contained: boolean;
73
+ }, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
74
+ declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
75
+ declare const _default: typeof __VLS_export;
76
+ export default _default;
77
+ type __VLS_WithSlots<T, S> = T & {
78
+ new (): {
79
+ $slots: S;
80
+ };
81
+ };
@@ -74,23 +74,24 @@ type __VLS_Slots = {} & {
74
74
  create?: (props: typeof __VLS_139) => any;
75
75
  };
76
76
  declare const __VLS_base: import("vue").DefineComponent<ComboboxProps, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
77
+ "update:open": (value: boolean) => any;
77
78
  "update:modelValue": (value: AcceptableValue) => any;
78
79
  create: (query: string) => any;
79
80
  highlight: (payload: {
80
81
  ref: HTMLElement;
81
82
  value: AcceptableValue;
82
83
  } | undefined) => any;
83
- "update:open": (value: boolean) => any;
84
84
  }, string, import("vue").PublicProps, Readonly<ComboboxProps> & Readonly<{
85
+ "onUpdate:open"?: ((value: boolean) => any) | undefined;
85
86
  "onUpdate:modelValue"?: ((value: AcceptableValue) => any) | undefined;
86
87
  onCreate?: ((query: string) => any) | undefined;
87
88
  onHighlight?: ((payload: {
88
89
  ref: HTMLElement;
89
90
  value: AcceptableValue;
90
91
  } | undefined) => any) | undefined;
91
- "onUpdate:open"?: ((value: boolean) => any) | undefined;
92
92
  }>, {
93
93
  unstyled: boolean;
94
+ open: boolean;
94
95
  disabled: boolean;
95
96
  invalid: boolean;
96
97
  emptyText: string;
@@ -99,7 +100,6 @@ declare const __VLS_base: import("vue").DefineComponent<ComboboxProps, {}, {}, {
99
100
  virtual: boolean;
100
101
  estimateSize: number;
101
102
  overscan: number;
102
- open: boolean;
103
103
  defaultOpen: boolean;
104
104
  }, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
105
105
  declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
@@ -36,8 +36,8 @@ declare const __VLS_base: import("vue").DefineComponent<__VLS_PublicProps, {}, {
36
36
  "onUpdate:open"?: ((value: boolean) => any) | undefined;
37
37
  }>, {
38
38
  unstyled: boolean;
39
- sideOffset: number;
40
39
  align: "start" | "center" | "end";
40
+ sideOffset: number;
41
41
  }, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
42
42
  declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
43
43
  declare const _default: typeof __VLS_export;
@@ -7,6 +7,8 @@ export interface PaginationProps {
7
7
  /** Keep the first and last page visible however far away they are. */
8
8
  showEdges?: boolean;
9
9
  size?: 'sm' | 'md' | 'lg';
10
+ /** Where the control sits in its container. Centred by default. */
11
+ align?: 'start' | 'center' | 'end';
10
12
  /** Accessible names — override for non-English apps. */
11
13
  prevLabel?: string;
12
14
  nextLabel?: string;
@@ -35,11 +35,11 @@ type __VLS_Slots = {} & {
35
35
  default?: (props: typeof __VLS_48) => any;
36
36
  };
37
37
  declare const __VLS_base: import("vue").DefineComponent<SelectProps, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
38
- "update:modelValue": (value: import("reka-ui").AcceptableValue) => any;
39
38
  "update:open": (value: boolean) => any;
39
+ "update:modelValue": (value: import("reka-ui").AcceptableValue) => any;
40
40
  }, string, import("vue").PublicProps, Readonly<SelectProps> & Readonly<{
41
- "onUpdate:modelValue"?: ((value: import("reka-ui").AcceptableValue) => any) | undefined;
42
41
  "onUpdate:open"?: ((value: boolean) => any) | undefined;
42
+ "onUpdate:modelValue"?: ((value: import("reka-ui").AcceptableValue) => any) | undefined;
43
43
  }>, {
44
44
  unstyled: boolean;
45
45
  }, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
@@ -0,0 +1,131 @@
1
+ import type { TableColumn, TableSort } from '../composables/data-table';
2
+ export interface TableProps<Row = any> {
3
+ /** The rows to render. In server mode this is already the page the server returned. */
4
+ rows?: Row[];
5
+ columns?: TableColumn<Row>[];
6
+ /**
7
+ * Total rows on the server. Providing it switches to server mode: the table
8
+ * stops sorting and slicing locally and only emits state, because the rows
9
+ * it was given are already the requested page.
10
+ */
11
+ total?: number;
12
+ /** Field identifying a row, used for selection and expansion. */
13
+ rowKey?: string;
14
+ loading?: boolean;
15
+ /** Rows of skeletons while `loading` and there is nothing to show yet. */
16
+ loadingRows?: number;
17
+ selectable?: boolean;
18
+ /** Veto selection per row — the checkbox is hidden and the header skips it. */
19
+ isRowSelectable?: (row: Row) => boolean;
20
+ expandable?: boolean;
21
+ /** Veto expansion per row; the chevron is hidden. */
22
+ canExpandRow?: (row: Row) => boolean;
23
+ /** Emit `rowClick` and show a pointer cursor. */
24
+ clickableRows?: boolean;
25
+ striped?: boolean;
26
+ hoverable?: boolean;
27
+ stickyHeader?: boolean;
28
+ size?: 'sm' | 'md' | 'lg';
29
+ /** Text when there are no rows. Overridden by the `empty` slot. */
30
+ emptyText?: string;
31
+ /** Accessible name for the table, since a visible caption is optional. */
32
+ label?: string;
33
+ caption?: string;
34
+ /** Skip built-in classes; you take over styling entirely. */
35
+ unstyled?: boolean;
36
+ class?: string;
37
+ /** Override classes per slot, e.g. `{ td: 'py-1' }`. */
38
+ ui?: {
39
+ root?: string;
40
+ table?: string;
41
+ thead?: string;
42
+ tbody?: string;
43
+ tr?: string;
44
+ th?: string;
45
+ td?: string;
46
+ empty?: string;
47
+ caption?: string;
48
+ };
49
+ }
50
+ declare const __VLS_export: <T = any>(__VLS_props: NonNullable<Awaited<typeof __VLS_setup>>["props"], __VLS_ctx?: __VLS_PrettifyLocal<Pick<NonNullable<Awaited<typeof __VLS_setup>>, "attrs" | "emit" | "slots">>, __VLS_exposed?: NonNullable<Awaited<typeof __VLS_setup>>["expose"], __VLS_setup?: Promise<{
51
+ props: import("vue").PublicProps & __VLS_PrettifyLocal<(TableProps<T> & {
52
+ sort?: TableSort | null;
53
+ page?: number;
54
+ perPage?: number;
55
+ selection?: (string | number)[];
56
+ expanded?: (string | number)[];
57
+ }) & {
58
+ "onUpdate:page"?: ((value: number) => any) | undefined;
59
+ onRowClick?: ((row: T) => any) | undefined;
60
+ "onUpdate:sort"?: ((value: TableSort | null) => any) | undefined;
61
+ "onUpdate:perPage"?: ((value: number) => any) | undefined;
62
+ "onUpdate:selection"?: ((value: (string | number)[]) => any) | undefined;
63
+ "onUpdate:expanded"?: ((value: (string | number)[]) => any) | undefined;
64
+ }> & (typeof globalThis extends {
65
+ __VLS_PROPS_FALLBACK: infer P;
66
+ } ? P : {});
67
+ expose: (exposed: import("vue").ShallowUnwrapRef<{
68
+ table: {
69
+ sort: {
70
+ value: TableSort | null;
71
+ };
72
+ page: {
73
+ value: number;
74
+ };
75
+ perPage: {
76
+ value: number;
77
+ };
78
+ selection: {
79
+ value: (string | number)[];
80
+ };
81
+ expanded: {
82
+ value: (string | number)[];
83
+ };
84
+ isServerMode: import("vue").ComputedRef<boolean>;
85
+ visibleColumns: import("vue").ComputedRef<TableColumn<T>[]>;
86
+ pageRows: import("vue").ComputedRef<T[]>;
87
+ total: import("vue").ComputedRef<number>;
88
+ pageCount: import("vue").ComputedRef<number>;
89
+ keyOf: (row: T) => string | number;
90
+ toggleSort: (column: TableColumn<T>) => void;
91
+ sortOrderFor: (column: TableColumn<T>) => import("..").SortOrder | null;
92
+ headerSelection: import("vue").ComputedRef<boolean | "indeterminate">;
93
+ isSelected: (row: T) => boolean;
94
+ toggleRow: (row: T) => void;
95
+ toggleAll: (value: boolean | "indeterminate") => void;
96
+ isExpanded: (row: T) => boolean;
97
+ toggleExpanded: (row: T) => void;
98
+ getRowValue: typeof import("..").getRowValue;
99
+ };
100
+ }>) => void;
101
+ attrs: any;
102
+ slots: {
103
+ [x: `header-${string}`]: ((props: {
104
+ column: TableColumn<T>;
105
+ }) => any) | undefined;
106
+ } & {
107
+ [x: `cell-${string}`]: ((props: {
108
+ row: T;
109
+ column: TableColumn<T>;
110
+ value: unknown;
111
+ }) => any) | undefined;
112
+ } & {
113
+ caption?: (props: {}) => any;
114
+ } & {
115
+ empty?: (props: {}) => any;
116
+ } & {
117
+ expanded?: (props: {
118
+ row: T;
119
+ }) => any;
120
+ };
121
+ emit: ((evt: "rowClick", row: T) => void) & (((event: "update:page", value: number) => void) & ((event: "update:sort", value: TableSort | null) => void) & ((event: "update:perPage", value: number) => void) & ((event: "update:selection", value: (string | number)[]) => void) & ((event: "update:expanded", value: (string | number)[]) => void));
122
+ }>) => import("vue").VNode & {
123
+ __ctx?: Awaited<typeof __VLS_setup>;
124
+ };
125
+ declare const _default: typeof __VLS_export;
126
+ export default _default;
127
+ type __VLS_PrettifyLocal<T> = (T extends any ? {
128
+ [K in keyof T]: T[K];
129
+ } : {
130
+ [K in keyof T as K]: T[K];
131
+ }) & {};
@@ -1,6 +1,7 @@
1
1
  export { default as Alert } from './Alert.vue';
2
2
  export { default as App } from './App.vue';
3
3
  export { default as Badge } from './Badge.vue';
4
+ export { default as Banner } from './Banner.vue';
4
5
  export { default as Breadcrumb } from './Breadcrumb.vue';
5
6
  export { default as Button } from './Button.vue';
6
7
  export { default as ButtonGroup } from './ButtonGroup.vue';
@@ -25,6 +26,7 @@ export { default as Skeleton } from './Skeleton.vue';
25
26
  export { default as Stat } from './Stat.vue';
26
27
  export { default as Stepper } from './Stepper.vue';
27
28
  export { default as Switch } from './Switch.vue';
29
+ export { default as Table } from './Table.vue';
28
30
  export { default as Tabs } from './Tabs.vue';
29
31
  export { default as Textarea } from './Textarea.vue';
30
32
  export { default as Toaster } from './Toaster.vue';