rei-kit 2.6.0 → 2.7.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/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # rei-kit
2
2
 
3
- **One kit. Every look.** 67 accessible components for Vue 3 and Tailwind 4.
3
+ **One kit. Every look.** 77 accessible components for Vue 3 and Tailwind 4.
4
4
  Change the **material** with one attribute and the **palette** with another —
5
5
  every component follows, and none of them knows your brand.
6
6
 
@@ -112,7 +112,7 @@ Each claim here is enforced by something that fails, not by a promise.
112
112
 
113
113
  | Standard | How it is held |
114
114
  | ---------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
115
- | **Open for extension, closed for edits** | A new look is a token, a material or a palette — never an edit to a component. Materials and palettes restyle all 67 without touching one, and a test fails if a component holds a colour. |
115
+ | **Open for extension, closed for edits** | A new look is a token, a material or a palette — never an edit to a component. Materials and palettes restyle all 77 without touching one, and a test fails if a component holds a colour. |
116
116
  | **Single responsibility** | One part, one job. Label-and-error wiring lives in `FormField`, not in five inputs; taking the page behind a layer out of reach lives in one helper the modal, the sheet and the guide share. |
117
117
  | **Depend on roles, not values** | Components read `primary`, `surface`, `--shadow-card` — never a hex or a pixel shadow. An app's brand wins in both modes, tested. |
118
118
  | **WAI-ARIA Authoring Practices** | Menus, comboboxes, tabs, sliders, dialogs and accordions follow their APG pattern: arrows move, Tab leaves, Escape closes, focus returns. Behaviour tests drive each with the keyboard. |
@@ -124,11 +124,11 @@ Each claim here is enforced by something that fails, not by a promise.
124
124
 
125
125
  ## Status
126
126
 
127
- **v2.6.0 — three consumers.**
127
+ **v2.7.0 — three consumers.**
128
128
 
129
129
  | | |
130
130
  | ------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
131
- | Components | 67 (`AuthForm`, `BaseTable`, `BaseCombobox`, `BaseSlider`, `TabShell`, `BaseModal`, `BaseTabs`, `BaseTooltip`, `BasePagination`, `BaseBreadcrumb`, `BaseDisclosure`, `BaseAccordion`, `NavLinks`, `OfflineBanner`, `FabButton`, `BaseButton`, `BaseCard`, `BaseInput`, `BaseSelect`, `BaseTextarea`, `BaseCheckbox`, `BaseSwitch`, `BaseRadioGroup`, `BaseMenu`, `BaseAvatar`, `BaseSpinner`, `BaseAlert`, `BaseBadge`, `BaseSheet`, `ProgressBar`, `PriceCard`, `ToastHost`, `TabBar`, `GoogleButton`, `LocaleLinks`, `LocaleSheet`, `AuthShell`, `TourShell`, `InstallPrompt`, `UpdatePrompt`, `InstallSettings`, `SkeletonList`, `PageContainer`, `ErrorBoundary`, etc.) |
131
+ | Components | 77 (`AuthForm`, `BaseTable`, `BaseCombobox`, `BaseSlider`, `TabShell`, `BaseModal`, `BaseTabs`, `BaseTooltip`, `BasePagination`, `BaseBreadcrumb`, `BaseDisclosure`, `BaseAccordion`, `NavLinks`, `OfflineBanner`, `FabButton`, `BaseButton`, `BaseCard`, `BaseInput`, `BaseSelect`, `BaseTextarea`, `BaseCheckbox`, `BaseSwitch`, `BaseRadioGroup`, `BaseMenu`, `BaseAvatar`, `BaseSpinner`, `BaseAlert`, `BaseBadge`, `BaseSheet`, `ProgressBar`, `PriceCard`, `ToastHost`, `TabBar`, `GoogleButton`, `LocaleLinks`, `LocaleSheet`, `AuthShell`, `TourShell`, `InstallPrompt`, `UpdatePrompt`, `InstallSettings`, `SkeletonList`, `PageContainer`, `ErrorBoundary`, etc.) |
132
132
  | Composables | 16 (`useToast`, `useTheme`, `useMaterial`, `usePalette`, `useToday`, `useMediaQuery`, `useInstall`, `watchInstallability`, `createTabTransition`, `useThemeSync`, `useVisualViewport`, etc.) |
133
133
  | Utilities | 33 (`applyTheme`, `applyMaterial`, `applyPalette`, `MATERIALS`, `PALETTES`, `formatDate`, `fieldErrors`, `toAuthMessageKey`, `createAuthGuard`, `createQueryDefaults`, `createWriteReport`, `toRedirectPath`, `Supabase error mapper`, i18n runtime, etc.) |
134
134
  | Entry Points | `rei-kit`, `rei-kit/app`, `rei-kit/web`, `rei-kit/pwa`, `rei-kit/supabase`, `rei-kit/mobile.css`, `rei-kit/web.css`, and each stylesheet on its own |
@@ -0,0 +1,24 @@
1
+ /**
2
+ * The people on a thing, overlapped: who is in a conversation, who shares a
3
+ * list.
4
+ *
5
+ * Past `max` it stops drawing faces and says how many are left, because ten
6
+ * overlapping circles are neither ten faces nor a number. The whole stack is
7
+ * one thing to a screen reader — `label` names it, usually with the count in
8
+ * it, which is what somebody listening actually needs.
9
+ */
10
+ type __VLS_Props = {
11
+ /** Each person's name, and a picture where there is one. */
12
+ people: readonly {
13
+ name: string;
14
+ src?: string | undefined;
15
+ }[];
16
+ /** The stack's accessible name: "Shared with 6 people". Already translated. */
17
+ label: string;
18
+ /** How many faces before the rest become a number. */
19
+ max?: number | undefined;
20
+ size?: 'sm' | 'md' | 'lg' | undefined;
21
+ };
22
+ declare const __VLS_export: import('vue').DefineComponent<__VLS_Props, {}, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {}, string, import('vue').PublicProps, Readonly<__VLS_Props> & Readonly<{}>, {}, {}, {}, {}, string, import('vue').ComponentProvideOptions, false, {}, any>;
23
+ declare const _default: typeof __VLS_export;
24
+ export default _default;
@@ -0,0 +1,32 @@
1
+ import { Component } from 'vue';
2
+ /**
3
+ * A short label with, when it is one of a set someone assembled, a way to
4
+ * take it off: a filter, a recipient, a tag.
5
+ *
6
+ * Next to `BaseBadge`, which is a standing label and never a control. A chip
7
+ * is removable, or selectable, or both. If it neither removes nor selects,
8
+ * reach for the badge.
9
+ *
10
+ * `removeLabel` is required when it can be removed, because "×" alone is a
11
+ * button a screen reader reads as "times".
12
+ */
13
+ type __VLS_Props = {
14
+ /** The text. Already translated. */
15
+ label: string;
16
+ icon?: Component | undefined;
17
+ tone?: 'neutral' | 'primary' | 'success' | 'warning' | 'danger' | undefined;
18
+ /** Given, the chip grows a remove button. Its accessible name. */
19
+ removeLabel?: string | undefined;
20
+ /** Given, the whole chip is a toggle and this is its state. */
21
+ selected?: boolean | undefined;
22
+ disabled?: boolean | undefined;
23
+ };
24
+ declare const __VLS_export: import('vue').DefineComponent<__VLS_Props, {}, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {
25
+ select: () => any;
26
+ remove: () => any;
27
+ }, string, import('vue').PublicProps, Readonly<__VLS_Props> & Readonly<{
28
+ onSelect?: () => any;
29
+ onRemove?: () => any;
30
+ }>, {}, {}, {}, {}, string, import('vue').ComponentProvideOptions, false, {}, any>;
31
+ declare const _default: typeof __VLS_export;
32
+ export default _default;
@@ -0,0 +1,21 @@
1
+ /**
2
+ * A keyboard key, or a chord of them: `⌘ K`, `Ctrl Shift P`.
3
+ *
4
+ * `<kbd>` is the element the browser and assistive tech already understand,
5
+ * so this is that element with the kit's surface on it. A chord is separate
6
+ * keys with a joiner between them rather than one long key, which is how a
7
+ * screen reader reads it as three things to press.
8
+ *
9
+ * The keys are the app's words — `⌘` on a Mac and `Ctrl` elsewhere is a
10
+ * decision about the reader's machine, not about this component.
11
+ */
12
+ type __VLS_Props = {
13
+ /** One key, or the keys of a chord: `['⌘', 'K']`. */
14
+ keys: string | readonly string[];
15
+ /** Drawn between the keys — "+", "then". Empty, they simply sit apart. */
16
+ joiner?: string | undefined;
17
+ size?: 'sm' | 'md' | undefined;
18
+ };
19
+ declare const __VLS_export: import('vue').DefineComponent<__VLS_Props, {}, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {}, string, import('vue').PublicProps, Readonly<__VLS_Props> & Readonly<{}>, {}, {}, {}, {}, string, import('vue').ComponentProvideOptions, false, {}, any>;
20
+ declare const _default: typeof __VLS_export;
21
+ export default _default;
@@ -0,0 +1,33 @@
1
+ /**
2
+ * A link in a sentence — the one thing a button is not.
3
+ *
4
+ * `BaseButton` has a `link` variant for an action that should read as text;
5
+ * this is the other way round: a real link, to a real place, that navigates.
6
+ * If pressing it does something rather than goes somewhere, it is a button.
7
+ *
8
+ * `to` routes and `href` leaves. A link that leaves in a new tab carries the
9
+ * mark that says so, and `rel="noopener"`, which is not a nicety: without it
10
+ * the page that opens can reach back through `window.opener`.
11
+ */
12
+ type __VLS_Props = {
13
+ /** A route. Uses `RouterLink`, so the app needs vue-router. */
14
+ to?: string | Record<string, unknown> | undefined;
15
+ /** A URL. Anything not on this site should be `external`. */
16
+ href?: string | undefined;
17
+ /** Opens in a new tab, with the mark and the `rel` that belong to that. */
18
+ external?: boolean | undefined;
19
+ tone?: 'primary' | 'ink' | undefined;
20
+ underline?: 'always' | 'hover' | 'none' | undefined;
21
+ };
22
+ type __VLS_Slots = {
23
+ default: () => unknown;
24
+ };
25
+ declare const __VLS_base: import('vue').DefineComponent<__VLS_Props, {}, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {}, string, import('vue').PublicProps, Readonly<__VLS_Props> & Readonly<{}>, {}, {}, {}, {}, string, import('vue').ComponentProvideOptions, false, {}, any>;
26
+ declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
27
+ declare const _default: typeof __VLS_export;
28
+ export default _default;
29
+ type __VLS_WithSlots<T, S> = T & {
30
+ new (): {
31
+ $slots: S;
32
+ };
33
+ };
@@ -0,0 +1,35 @@
1
+ /**
2
+ * A score out of five, given or shown.
3
+ *
4
+ * Two components in one, and the difference is `readonly`: given, it is a
5
+ * slider you can drag with the arrow keys; read-only, it is an image with
6
+ * the score as its name, and nothing to Tab into. A row of five buttons that
7
+ * do nothing is five stops in the tab order for a number.
8
+ *
9
+ * `valueLabel` builds the spoken name — "4 out of 5" — because the words and
10
+ * their order are the app's language, not the kit's.
11
+ */
12
+ type __VLS_Props = {
13
+ max?: number | undefined;
14
+ /** What is being rated: "Difficulty", "Your rating". Already translated. */
15
+ label: string;
16
+ /** The spoken value: `(value, max) => \`${value} out of ${max}\`.` */
17
+ valueLabel: (value: number, max: number) => string;
18
+ /** Shows a score rather than asks for one. */
19
+ readonly?: boolean | undefined;
20
+ size?: 'sm' | 'md' | 'lg' | undefined;
21
+ /** Pressing the current score again clears it. */
22
+ allowClear?: boolean | undefined;
23
+ };
24
+ type __VLS_ModelProps = {
25
+ /** The score, with `v-model`. `0` is none given. */
26
+ modelValue?: number;
27
+ };
28
+ type __VLS_PublicProps = __VLS_Props & __VLS_ModelProps;
29
+ declare const __VLS_export: import('vue').DefineComponent<__VLS_PublicProps, {}, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {
30
+ "update:modelValue": (value: number) => any;
31
+ }, string, import('vue').PublicProps, Readonly<__VLS_PublicProps> & Readonly<{
32
+ "onUpdate:modelValue"?: (value: number) => any;
33
+ }>, {}, {}, {}, {}, string, import('vue').ComponentProvideOptions, false, {}, any>;
34
+ declare const _default: typeof __VLS_export;
35
+ export default _default;
@@ -0,0 +1,20 @@
1
+ /**
2
+ * A line between things — with, when it helps, a word on it.
3
+ *
4
+ * `role="separator"` when it only divides, and nothing at all to assistive
5
+ * tech when it carries a label, because then the text is the point and the
6
+ * line is decoration around it.
7
+ *
8
+ * Vertical needs a height from its parent: inside a flex row, that is
9
+ * `align-items: stretch`, which is the default.
10
+ */
11
+ type __VLS_Props = {
12
+ orientation?: 'horizontal' | 'vertical' | undefined;
13
+ /** A word in the middle of the line: "or", "Today". Already translated. */
14
+ label?: string | undefined;
15
+ /** Room around it. `none` for a divider inside a list that has its own. */
16
+ spacing?: 'none' | 'sm' | 'md' | undefined;
17
+ };
18
+ declare const __VLS_export: import('vue').DefineComponent<__VLS_Props, {}, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {}, string, import('vue').PublicProps, Readonly<__VLS_Props> & Readonly<{}>, {}, {}, {}, {}, string, import('vue').ComponentProvideOptions, false, {}, any>;
19
+ declare const _default: typeof __VLS_export;
20
+ export default _default;
@@ -0,0 +1,25 @@
1
+ /**
2
+ * One grey box standing in for content that has not arrived.
3
+ *
4
+ * `SkeletonList` is rows of these for a list; this is the primitive, for the
5
+ * shapes a list does not cover — an avatar, a heading, a chart.
6
+ *
7
+ * A height is a CSS length, never a class: `h-4` inside a component the app
8
+ * does not control would render at zero the day that utility is not in the
9
+ * app's stylesheet, which is exactly how every skeleton in one app came out
10
+ * invisible.
11
+ *
12
+ * It is hidden from assistive tech. The thing that is loading says so —
13
+ * through `aria-busy`, or a status message — and a screen reader reading
14
+ * "blank, blank, blank" helps nobody.
15
+ */
16
+ type __VLS_Props = {
17
+ /** Any CSS length: `12rem`, `60%`, `8ch`. */
18
+ width?: string | undefined;
19
+ height?: string | undefined;
20
+ /** `circle` makes a round one and squares the width to the height. */
21
+ shape?: 'block' | 'text' | 'circle' | undefined;
22
+ };
23
+ declare const __VLS_export: import('vue').DefineComponent<__VLS_Props, {}, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {}, string, import('vue').PublicProps, Readonly<__VLS_Props> & Readonly<{}>, {}, {}, {}, {}, string, import('vue').ComponentProvideOptions, false, {}, any>;
24
+ declare const _default: typeof __VLS_export;
25
+ export default _default;
@@ -0,0 +1,33 @@
1
+ /**
2
+ * Copies a piece of text, and says that it did.
3
+ *
4
+ * The saying is the part that is usually missing: a copy button that changes
5
+ * nothing leaves the reader pressing it twice. This swaps its icon and its
6
+ * accessible name for two seconds, and announces the change politely — which
7
+ * is what tells somebody who cannot see the tick.
8
+ *
9
+ * A refusal is reported too, through `error`: a browser without clipboard
10
+ * permission fails silently otherwise, and the next paste is whatever was
11
+ * there before.
12
+ */
13
+ type __VLS_Props = {
14
+ /** What lands on the clipboard. */
15
+ text: string;
16
+ /** The button's name at rest, e.g. "Copy the key". */
17
+ copyLabel: string;
18
+ /** Its name for the two seconds after, e.g. "Copied". */
19
+ copiedLabel: string;
20
+ /** Said when the browser refuses. Unset, a refusal only leaves it unchanged. */
21
+ errorLabel?: string | undefined;
22
+ /** Show the label beside the icon, rather than only to assistive tech. */
23
+ withText?: boolean | undefined;
24
+ };
25
+ declare const __VLS_export: import('vue').DefineComponent<__VLS_Props, {}, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {
26
+ failed: () => any;
27
+ copied: () => any;
28
+ }, string, import('vue').PublicProps, Readonly<__VLS_Props> & Readonly<{
29
+ onFailed?: () => any;
30
+ onCopied?: () => any;
31
+ }>, {}, {}, {}, {}, string, import('vue').ComponentProvideOptions, false, {}, any>;
32
+ declare const _default: typeof __VLS_export;
33
+ export default _default;
@@ -0,0 +1,45 @@
1
+ /**
2
+ * Files, dropped on or chosen from a real file input.
3
+ *
4
+ * The input is the control; the box around it is a label. That is not a
5
+ * detail: a `<div>` with a click handler cannot be reached with Tab, opened
6
+ * with Enter, or announced as "choose file", and dragging is a pointer
7
+ * gesture that a keyboard has no version of. Everything here works without a
8
+ * drag.
9
+ *
10
+ * It holds files, not uploads. Sending them, the progress and the failures
11
+ * are the app's — the kit does not know your endpoint, and a component that
12
+ * guessed it would be wrong everywhere.
13
+ */
14
+ type __VLS_Props = {
15
+ /** The instruction in the box: "Drop a receipt here". Already translated. */
16
+ label: string;
17
+ /** A line under it: what is accepted, how big. */
18
+ hint?: string | undefined;
19
+ /** The button inside the box, e.g. "Browse". */
20
+ browseLabel: string;
21
+ /** Accessible name of each file's remove button. */
22
+ removeLabel: string;
23
+ /** Passed to the input: `image/*`, `.pdf`. */
24
+ accept?: string | undefined;
25
+ multiple?: boolean | undefined;
26
+ /** In bytes. Anything larger is refused and reported through `rejected`. */
27
+ maxSize?: number | undefined;
28
+ /** Shown under the box when a file was too large. */
29
+ tooLargeLabel?: string | undefined;
30
+ disabled?: boolean | undefined;
31
+ };
32
+ type __VLS_ModelProps = {
33
+ /** The files held, with `v-model`. */
34
+ modelValue?: File[];
35
+ };
36
+ type __VLS_PublicProps = __VLS_Props & __VLS_ModelProps;
37
+ declare const __VLS_export: import('vue').DefineComponent<__VLS_PublicProps, {}, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {
38
+ "update:modelValue": (value: File[]) => any;
39
+ rejected: (files: File[]) => any;
40
+ }, string, import('vue').PublicProps, Readonly<__VLS_PublicProps> & Readonly<{
41
+ "onUpdate:modelValue"?: (value: File[]) => any;
42
+ onRejected?: (files: File[]) => any;
43
+ }>, {}, {}, {}, {}, string, import('vue').ComponentProvideOptions, false, {}, any>;
44
+ declare const _default: typeof __VLS_export;
45
+ export default _default;
@@ -0,0 +1,38 @@
1
+ /**
2
+ * A field that holds several short values: recipients, labels, skills.
3
+ *
4
+ * Enter and a comma commit what has been typed; Backspace on an empty field
5
+ * takes the last one back, which is the shortcut everybody tries. The chips
6
+ * are before the field rather than beside it, so the caret is always at the
7
+ * end of the line the way it is in a mail client.
8
+ *
9
+ * `removeLabel` builds each chip's remove button name from the tag, so a
10
+ * screen reader hears "Remove: design" rather than five buttons called "×".
11
+ */
12
+ type __VLS_Props = {
13
+ label: string;
14
+ /** `(tag) => \`Remove ${tag}\`` — already translated. */
15
+ removeLabel: (tag: string) => string;
16
+ placeholder?: string | undefined;
17
+ hint?: string | undefined;
18
+ error?: string | undefined;
19
+ /** How many tags at most. The field stops taking them at the limit. */
20
+ max?: number | undefined;
21
+ /** By default the same tag twice is ignored. */
22
+ allowDuplicates?: boolean | undefined;
23
+ size?: 'sm' | 'md' | undefined;
24
+ labelHidden?: boolean | undefined;
25
+ disabled?: boolean | undefined;
26
+ };
27
+ type __VLS_ModelProps = {
28
+ /** The tags, with `v-model`. */
29
+ modelValue?: string[];
30
+ };
31
+ type __VLS_PublicProps = __VLS_Props & __VLS_ModelProps;
32
+ declare const __VLS_export: import('vue').DefineComponent<__VLS_PublicProps, {}, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {
33
+ "update:modelValue": (value: string[]) => any;
34
+ }, string, import('vue').PublicProps, Readonly<__VLS_PublicProps> & Readonly<{
35
+ "onUpdate:modelValue"?: (value: string[]) => any;
36
+ }>, {}, {}, {}, {}, string, import('vue').ComponentProvideOptions, false, {}, any>;
37
+ declare const _default: typeof __VLS_export;
38
+ export default _default;
package/dist/index.d.ts CHANGED
@@ -85,7 +85,17 @@ export { default as LocaleLinks } from './components/LocaleLinks.vue';
85
85
  export { default as GoogleButton } from './components/GoogleButton.vue';
86
86
  export { default as TabBar } from './components/TabBar.vue';
87
87
  export type { TabItem } from './components/TabBar.vue';
88
+ export { default as AvatarStack } from './components/AvatarStack.vue';
88
89
  export { default as BaseCalendar } from './components/BaseCalendar.vue';
90
+ export { default as BaseChip } from './components/BaseChip.vue';
91
+ export { default as BaseKbd } from './components/BaseKbd.vue';
92
+ export { default as BaseLink } from './components/BaseLink.vue';
93
+ export { default as BaseRating } from './components/BaseRating.vue';
94
+ export { default as BaseSeparator } from './components/BaseSeparator.vue';
95
+ export { default as BaseSkeleton } from './components/BaseSkeleton.vue';
96
+ export { default as CopyButton } from './components/CopyButton.vue';
97
+ export { default as FileDrop } from './components/FileDrop.vue';
98
+ export { default as TagsInput } from './components/TagsInput.vue';
89
99
  export type { DateRange } from './components/BaseCalendar.vue';
90
100
  export { default as BaseDatePicker } from './components/BaseDatePicker.vue';
91
101
  export type { DatePreset } from './components/BaseDatePicker.vue';