rei-kit 2.19.0 → 2.21.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 +3 -3
- package/dist/components/ActivityGrid.vue.d.ts +52 -0
- package/dist/components/ScrollArea.vue.d.ts +68 -0
- package/dist/components/VirtualList.vue.d.ts +37 -0
- package/dist/composables/use-virtual-window.d.ts +39 -0
- package/dist/index.d.ts +17 -0
- package/dist/index.js +633 -170
- package/dist/index.js.map +1 -1
- package/dist/styles.css +141 -25
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# rei-kit
|
|
2
2
|
|
|
3
|
-
**One kit. Every look.**
|
|
3
|
+
**One kit. Every look.** 99 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
|
|
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 99 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. |
|
|
@@ -128,7 +128,7 @@ Each claim here is enforced by something that fails, not by a promise.
|
|
|
128
128
|
|
|
129
129
|
| | |
|
|
130
130
|
| ------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
131
|
-
| Components |
|
|
131
|
+
| Components | 99 (`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,52 @@
|
|
|
1
|
+
import { WeekStart } from '../utils/date';
|
|
2
|
+
/**
|
|
3
|
+
* A year of days, as a grid you can read at a glance.
|
|
4
|
+
*
|
|
5
|
+
* ## It is a table, and that is not a detail
|
|
6
|
+
*
|
|
7
|
+
* Weekdays are the rows and weeks are the columns, so the markup is a
|
|
8
|
+
* `<table>` and the visual layout falls out of it. The obvious way — one
|
|
9
|
+
* CSS grid flowing column by column — puts the DOM in a different order
|
|
10
|
+
* from the picture, and anything laid over that order afterwards
|
|
11
|
+
* (`role="grid"`, arrow keys, a reader's own table navigation) then
|
|
12
|
+
* describes a shape that is not on screen.
|
|
13
|
+
*
|
|
14
|
+
* ## One stop, not three hundred and sixty-five
|
|
15
|
+
*
|
|
16
|
+
* Every day is reachable, and the whole grid is a single stop in the tab
|
|
17
|
+
* order: the arrows move between days, Home and End go to the ends of a
|
|
18
|
+
* week, and Enter chooses. A grid of focusable cells is the other way this
|
|
19
|
+
* is written, and it costs somebody using a keyboard a year of presses to
|
|
20
|
+
* get past a picture.
|
|
21
|
+
*
|
|
22
|
+
* ## The colours are yours
|
|
23
|
+
*
|
|
24
|
+
* `levelFor` returns a class, the same contract as `ToneDot`'s `fill` and
|
|
25
|
+
* `BaseTimeline`'s: the kit does not know whether four of something is a
|
|
26
|
+
* lot, or which hue your product uses for "done". `dayLabel` is the same
|
|
27
|
+
* for words — the kit has no language, and a date reads differently in
|
|
28
|
+
* every one.
|
|
29
|
+
*/
|
|
30
|
+
type __VLS_Props = {
|
|
31
|
+
/** The days to draw, as `YYYY-MM-DD`, oldest first. */
|
|
32
|
+
days: readonly string[];
|
|
33
|
+
/** Names the grid, e.g. "Your year". Already translated. */
|
|
34
|
+
label: string;
|
|
35
|
+
/** A class for one day's square, e.g. `bg-positive/40`. */
|
|
36
|
+
levelFor: (key: string) => string;
|
|
37
|
+
/** What a reader hears on a day: the date, and what happened. Translated. */
|
|
38
|
+
dayLabel: (key: string) => string;
|
|
39
|
+
/** Which days lead somewhere. Unset, the grid is a picture and nothing else. */
|
|
40
|
+
isSelectable?: ((key: string) => boolean) | undefined;
|
|
41
|
+
/** `1` Monday, `0` Sunday. */
|
|
42
|
+
weekStartsOn?: WeekStart | undefined;
|
|
43
|
+
/** Open on the most recent weeks — a year otherwise starts far off-screen. */
|
|
44
|
+
startAtEnd?: boolean | undefined;
|
|
45
|
+
};
|
|
46
|
+
declare const __VLS_export: import('vue').DefineComponent<__VLS_Props, {}, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {
|
|
47
|
+
select: (key: string) => any;
|
|
48
|
+
}, string, import('vue').PublicProps, Readonly<__VLS_Props> & Readonly<{
|
|
49
|
+
onSelect?: (key: string) => any;
|
|
50
|
+
}>, {}, {}, {}, {}, string, import('vue').ComponentProvideOptions, false, {}, any>;
|
|
51
|
+
declare const _default: typeof __VLS_export;
|
|
52
|
+
export default _default;
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A box that scrolls, with the two things a hand-written one leaves out.
|
|
3
|
+
*
|
|
4
|
+
* ## The edge fade is the affordance `no-scrollbar` takes away
|
|
5
|
+
*
|
|
6
|
+
* Every app here hides the scrollbar on a horizontal row — a strip of
|
|
7
|
+
* months, a row of filter chips — because a native bar under a 40px row is
|
|
8
|
+
* louder than the row. What goes with it is the only sign on screen that
|
|
9
|
+
* there is anything further along. So the fades are driven by the actual
|
|
10
|
+
* scroll position: one appears at an edge exactly when there is content
|
|
11
|
+
* past it, and both are gone when everything fits.
|
|
12
|
+
*
|
|
13
|
+
* ## A focus stop, but only when there is no other way in
|
|
14
|
+
*
|
|
15
|
+
* A box that scrolls and cannot take focus cannot be scrolled by a
|
|
16
|
+
* keyboard, so the far end is simply unreachable. That is the fault
|
|
17
|
+
* `CodeBlock` was written for, and it is not about code: it is true of any
|
|
18
|
+
* scrolling box whose contents are not focusable.
|
|
19
|
+
*
|
|
20
|
+
* But it is *only* true of those. A row of buttons already moves under the
|
|
21
|
+
* keyboard — Tab scrolls the next one into view — and giving that row a
|
|
22
|
+
* stop of its own costs a press for nothing, on every row. So this checks:
|
|
23
|
+
* it becomes a named region when it overflows **and** holds nothing
|
|
24
|
+
* focusable, and stays out of the tab order otherwise.
|
|
25
|
+
*
|
|
26
|
+
* The check runs when the box or its contents resize, which covers a list
|
|
27
|
+
* that arrives from a server. A swap that changes neither size — the same
|
|
28
|
+
* number of rows, buttons turned into plain text — will not be noticed;
|
|
29
|
+
* that is a trade against watching every mutation of a scroll container,
|
|
30
|
+
* and the shape it misses is a rare one.
|
|
31
|
+
*/
|
|
32
|
+
type __VLS_Props = {
|
|
33
|
+
/**
|
|
34
|
+
* Names the box, e.g. "Categories".
|
|
35
|
+
*
|
|
36
|
+
* Required because this becomes a region a reader can land in, and an
|
|
37
|
+
* unnamed region is announced as nothing at all. It is only used when
|
|
38
|
+
* that happens, so it costs nothing in the common case.
|
|
39
|
+
*/
|
|
40
|
+
label: string;
|
|
41
|
+
/** Which way it scrolls. */
|
|
42
|
+
axis?: 'x' | 'y' | 'both' | undefined;
|
|
43
|
+
/** `hidden` takes the native bar away; the fades stay either way. */
|
|
44
|
+
scrollbar?: 'auto' | 'hidden' | undefined;
|
|
45
|
+
/** The gradient at an edge with more content past it. */
|
|
46
|
+
fade?: boolean | undefined;
|
|
47
|
+
/** Drag to scroll sideways, for a page that has claimed horizontal gestures. */
|
|
48
|
+
drag?: boolean | undefined;
|
|
49
|
+
};
|
|
50
|
+
type __VLS_Slots = {
|
|
51
|
+
default: () => unknown;
|
|
52
|
+
};
|
|
53
|
+
declare const __VLS_base: import('vue').DefineComponent<__VLS_Props, {
|
|
54
|
+
/** The element that actually scrolls, for a parent that has to measure it. */
|
|
55
|
+
viewport: Readonly<import('vue').ShallowRef<HTMLElement | null>>;
|
|
56
|
+
}, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {
|
|
57
|
+
scroll: (event: Event) => any;
|
|
58
|
+
}, string, import('vue').PublicProps, Readonly<__VLS_Props> & Readonly<{
|
|
59
|
+
onScroll?: (event: Event) => any;
|
|
60
|
+
}>, {}, {}, {}, {}, string, import('vue').ComponentProvideOptions, false, {}, any>;
|
|
61
|
+
declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
|
|
62
|
+
declare const _default: typeof __VLS_export;
|
|
63
|
+
export default _default;
|
|
64
|
+
type __VLS_WithSlots<T, S> = T & {
|
|
65
|
+
new (): {
|
|
66
|
+
$slots: S;
|
|
67
|
+
};
|
|
68
|
+
};
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
declare const __VLS_export: <T>(__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<{
|
|
2
|
+
props: import('vue').PublicProps & __VLS_PrettifyLocal<{
|
|
3
|
+
/** The whole list. Only the rows near the viewport are rendered. */
|
|
4
|
+
items: readonly T[];
|
|
5
|
+
/** Every row is this tall, in pixels. */
|
|
6
|
+
rowHeight: number;
|
|
7
|
+
/** Names the list, e.g. "Bütün kayıtlar". Already translated. */
|
|
8
|
+
label: string;
|
|
9
|
+
/** Below this many rows the list is not windowed at all. */
|
|
10
|
+
virtualizeAfter?: number | undefined;
|
|
11
|
+
/** Passed to the scroll area: `hidden` takes the native bar away. */
|
|
12
|
+
scrollbar?: "auto" | "hidden" | undefined;
|
|
13
|
+
}> & (typeof globalThis extends {
|
|
14
|
+
__VLS_PROPS_FALLBACK: infer P;
|
|
15
|
+
} ? P : {});
|
|
16
|
+
expose: (exposed: import('vue').ShallowUnwrapRef<{
|
|
17
|
+
scrollToIndex: (index: number) => void;
|
|
18
|
+
}>) => void;
|
|
19
|
+
attrs: any;
|
|
20
|
+
slots: {
|
|
21
|
+
/** One row. `index` is its place in the whole list, not in the window. */
|
|
22
|
+
default: (props: {
|
|
23
|
+
item: T;
|
|
24
|
+
index: number;
|
|
25
|
+
}) => unknown;
|
|
26
|
+
};
|
|
27
|
+
emit: {};
|
|
28
|
+
}>) => import('vue').VNode & {
|
|
29
|
+
__ctx?: NonNullable<Awaited<typeof __VLS_setup>>;
|
|
30
|
+
};
|
|
31
|
+
declare const _default: typeof __VLS_export;
|
|
32
|
+
export default _default;
|
|
33
|
+
type __VLS_PrettifyLocal<T> = (T extends any ? {
|
|
34
|
+
[K in keyof T]: T[K];
|
|
35
|
+
} : {
|
|
36
|
+
[K in keyof T as K]: T[K];
|
|
37
|
+
}) & {};
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { Ref } from 'vue';
|
|
2
|
+
export interface VirtualWindowOptions {
|
|
3
|
+
/** How many rows there are in total. */
|
|
4
|
+
count: Ref<number>;
|
|
5
|
+
/** Every row is this tall, in pixels. Fixed — that is what makes the
|
|
6
|
+
* arithmetic possible without measuring each one. */
|
|
7
|
+
rowHeight: Ref<number>;
|
|
8
|
+
/**
|
|
9
|
+
* Below this many rows the window is the whole list and the padding is
|
|
10
|
+
* zero, so a short list renders exactly as it would without any of this.
|
|
11
|
+
*/
|
|
12
|
+
threshold: Ref<number>;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* The arithmetic behind a windowed list: which rows are near the viewport,
|
|
16
|
+
* and how much empty space stands in for the rest.
|
|
17
|
+
*
|
|
18
|
+
* This is the part `BaseCombobox` and `VirtualList` share. It was written
|
|
19
|
+
* inside the combobox first, and pulling it out here is the reason there is
|
|
20
|
+
* one copy of it rather than two — the second would have drifted, and the
|
|
21
|
+
* half that drifts silently is the padding, which is what keeps the
|
|
22
|
+
* scrollbar honest about how long the list is.
|
|
23
|
+
*
|
|
24
|
+
* There is no clock and no observer in here: it is a function of the scroll
|
|
25
|
+
* position, and the component that owns the element is what tells it where
|
|
26
|
+
* that is. That is also what makes it testable without a layout.
|
|
27
|
+
*/
|
|
28
|
+
export declare function useVirtualWindow({ count, rowHeight, threshold }: VirtualWindowOptions): {
|
|
29
|
+
active: import('vue').ComputedRef<boolean>;
|
|
30
|
+
window: import('vue').ComputedRef<{
|
|
31
|
+
start: number;
|
|
32
|
+
end: number;
|
|
33
|
+
}>;
|
|
34
|
+
padTop: import('vue').ComputedRef<number>;
|
|
35
|
+
padBottom: import('vue').ComputedRef<number>;
|
|
36
|
+
scrollTop: Ref<number, number>;
|
|
37
|
+
viewportHeight: Ref<number, number>;
|
|
38
|
+
onScroll: (event: Event) => void;
|
|
39
|
+
};
|
package/dist/index.d.ts
CHANGED
|
@@ -90,6 +90,23 @@ export { default as LocaleLinks } from './components/LocaleLinks.vue';
|
|
|
90
90
|
export { default as GoogleButton } from './components/GoogleButton.vue';
|
|
91
91
|
export { default as TabBar } from './components/TabBar.vue';
|
|
92
92
|
export type { TabItem } from './components/TabBar.vue';
|
|
93
|
+
/**
|
|
94
|
+
* `ActivityGrid`, a year at a glance — a real table, so the DOM order is
|
|
95
|
+
* the picture's order, and one tab stop rather than three hundred odd.
|
|
96
|
+
*/
|
|
97
|
+
export { default as ActivityGrid } from './components/ActivityGrid.vue';
|
|
98
|
+
/**
|
|
99
|
+
* `ScrollArea`, a scrolling box with the two things a hand-written one
|
|
100
|
+
* leaves out: a fade at whichever edge has more content past it, and a
|
|
101
|
+
* focus stop — but only when nothing inside it can take focus.
|
|
102
|
+
*/
|
|
103
|
+
export { default as ScrollArea } from './components/ScrollArea.vue';
|
|
104
|
+
/**
|
|
105
|
+
* `VirtualList`, a long list where only the rows near the viewport exist —
|
|
106
|
+
* and every one of them states its place in the whole, which is the half
|
|
107
|
+
* that is usually dropped.
|
|
108
|
+
*/
|
|
109
|
+
export { default as VirtualList } from './components/VirtualList.vue';
|
|
93
110
|
export { default as AvatarStack } from './components/AvatarStack.vue';
|
|
94
111
|
export { default as BaseCalendar } from './components/BaseCalendar.vue';
|
|
95
112
|
export { default as BaseChip } from './components/BaseChip.vue';
|