rei-kit 0.1.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/LICENSE +21 -0
- package/README.md +87 -0
- package/dist/app-error-DF9cijE0.js +63 -0
- package/dist/app-error-DF9cijE0.js.map +1 -0
- package/dist/components/BaseButton.vue.d.ts +20 -0
- package/dist/components/BaseInput.vue.d.ts +23 -0
- package/dist/components/BaseSheet.vue.d.ts +32 -0
- package/dist/components/EmptyState.vue.d.ts +19 -0
- package/dist/components/LocaleLinks.vue.d.ts +33 -0
- package/dist/components/PageHeader.vue.d.ts +20 -0
- package/dist/components/SectionHeading.vue.d.ts +26 -0
- package/dist/components/SegmentedControl.vue.d.ts +27 -0
- package/dist/components/SettingsGroup.vue.d.ts +16 -0
- package/dist/components/SettingsRow.vue.d.ts +35 -0
- package/dist/components/SkeletonList.vue.d.ts +8 -0
- package/dist/components/StatCard.vue.d.ts +8 -0
- package/dist/components/ToneDot.vue.d.ts +16 -0
- package/dist/composables/use-debounced-callback.d.ts +23 -0
- package/dist/composables/use-drag-scroll.d.ts +26 -0
- package/dist/composables/use-online.d.ts +18 -0
- package/dist/composables/use-theme.d.ts +23 -0
- package/dist/composables/use-today.d.ts +10 -0
- package/dist/composables/use-visual-viewport.d.ts +29 -0
- package/dist/i18n/runtime.d.ts +53 -0
- package/dist/index.d.ts +47 -0
- package/dist/index.js +1349 -0
- package/dist/index.js.map +1 -0
- package/dist/styles.css +27 -0
- package/dist/supabase/index.d.ts +28 -0
- package/dist/supabase.js +100 -0
- package/dist/supabase.js.map +1 -0
- package/dist/tokens.css +139 -0
- package/dist/utils/app-error.d.ts +58 -0
- package/dist/utils/date.d.ts +122 -0
- package/dist/utils/day-label.d.ts +27 -0
- package/dist/utils/download.d.ts +7 -0
- package/dist/utils/format.d.ts +24 -0
- package/dist/utils/haptics.d.ts +9 -0
- package/dist/utils/platform.d.ts +23 -0
- package/dist/utils/redirect.d.ts +41 -0
- package/package.json +98 -0
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Local calendar-day helpers.
|
|
3
|
+
*
|
|
4
|
+
* Every function is pure and works on `YYYY-MM-DD` keys, the same shape as the
|
|
5
|
+
* `date` columns in Postgres. Nothing here calls `toISOString`: that converts to
|
|
6
|
+
* UTC, so in a UTC+9 timezone every entry made between midnight and 09:00 would
|
|
7
|
+
* be written to the previous day.
|
|
8
|
+
*/
|
|
9
|
+
/**
|
|
10
|
+
* Formats a `Date` as a local `YYYY-MM-DD` key.
|
|
11
|
+
*
|
|
12
|
+
* @param date - Any `Date`; only its local year, month and day are read.
|
|
13
|
+
* @returns The calendar day in the runtime's own timezone.
|
|
14
|
+
*
|
|
15
|
+
* @example
|
|
16
|
+
* ```ts
|
|
17
|
+
* // 2026-08-23 01:30 in Tokyo
|
|
18
|
+
* toDateKey(new Date()) // '2026-08-23'
|
|
19
|
+
* new Date().toISOString() // '2026-08-22T16:30…' ← the bug
|
|
20
|
+
* ```
|
|
21
|
+
*/
|
|
22
|
+
export declare function toDateKey(date: Date): string;
|
|
23
|
+
/** Today's key in the user's own timezone. */
|
|
24
|
+
export declare function todayKey(): string;
|
|
25
|
+
/**
|
|
26
|
+
* Parses a `YYYY-MM-DD` key into a `Date` at local midnight.
|
|
27
|
+
*
|
|
28
|
+
* @param key - A key produced by {@link toDateKey}.
|
|
29
|
+
* @returns Local midnight of that calendar day.
|
|
30
|
+
* @throws If the key is not three numeric parts.
|
|
31
|
+
*
|
|
32
|
+
* @example
|
|
33
|
+
* ```ts
|
|
34
|
+
* fromDateKey('2026-08-23') // local midnight, correct
|
|
35
|
+
* new Date('2026-08-23') // UTC midnight — shifts a day in some zones
|
|
36
|
+
* ```
|
|
37
|
+
*/
|
|
38
|
+
export declare function fromDateKey(key: string): Date;
|
|
39
|
+
/**
|
|
40
|
+
* Shifts a date key by whole calendar days.
|
|
41
|
+
*
|
|
42
|
+
* Uses `setDate`, which is calendar-aware: it rolls over month and year ends,
|
|
43
|
+
* and stays correct across daylight-saving transitions. Adding
|
|
44
|
+
* `days * 86_400_000` milliseconds would not — a DST day is 23 or 25 hours long.
|
|
45
|
+
*
|
|
46
|
+
* @param key - Starting `YYYY-MM-DD` key.
|
|
47
|
+
* @param days - Days to add; negative goes back.
|
|
48
|
+
* @returns The resulting key.
|
|
49
|
+
*
|
|
50
|
+
* @example
|
|
51
|
+
* ```ts
|
|
52
|
+
* addDays('2026-01-31', 1) // '2026-02-01'
|
|
53
|
+
* addDays('2026-01-01', -1) // '2025-12-31'
|
|
54
|
+
* addDays('2028-02-28', 1) // '2028-02-29' — leap year
|
|
55
|
+
* ```
|
|
56
|
+
*/
|
|
57
|
+
export declare function addDays(key: string, days: number): string;
|
|
58
|
+
/**
|
|
59
|
+
* The last `count` days ending today, oldest first.
|
|
60
|
+
*
|
|
61
|
+
* `today` is a parameter so the function stays pure and testable; call sites
|
|
62
|
+
* normally omit it.
|
|
63
|
+
*
|
|
64
|
+
* @param count - How many days to return, including `today`.
|
|
65
|
+
* @param today - End of the range. Defaults to the real today.
|
|
66
|
+
* @returns Keys in ascending order.
|
|
67
|
+
*
|
|
68
|
+
* @example
|
|
69
|
+
* ```ts
|
|
70
|
+
* lastNDays(3, '2026-08-23') // ['2026-08-21', '2026-08-22', '2026-08-23']
|
|
71
|
+
* ```
|
|
72
|
+
*/
|
|
73
|
+
export declare function lastNDays(count: number, today?: string): string[];
|
|
74
|
+
/** 0 = week starts on Sunday, 1 = on Monday. Mirrors `profiles.week_starts_on`. */
|
|
75
|
+
export type WeekStart = 0 | 1;
|
|
76
|
+
/**
|
|
77
|
+
* The first day of the week containing `key`.
|
|
78
|
+
*
|
|
79
|
+
* The user's preference is a parameter, not a module-level setting: changing it
|
|
80
|
+
* in Profile has to re-render the week grid and the year heatmap immediately,
|
|
81
|
+
* and a global would make that a hidden dependency.
|
|
82
|
+
*
|
|
83
|
+
* @param key - Any day in the week.
|
|
84
|
+
* @param weekStartsOn - 0 for Sunday, 1 for Monday.
|
|
85
|
+
* @returns Key of that week's first day.
|
|
86
|
+
*
|
|
87
|
+
* @example
|
|
88
|
+
* ```ts
|
|
89
|
+
* // 2026-08-23 is a Sunday
|
|
90
|
+
* startOfWeek('2026-08-23', 1) // '2026-08-17' — previous Monday
|
|
91
|
+
* startOfWeek('2026-08-23', 0) // '2026-08-23' — already Sunday
|
|
92
|
+
* ```
|
|
93
|
+
*/
|
|
94
|
+
export declare function startOfWeek(key: string, weekStartsOn: WeekStart): string;
|
|
95
|
+
/**
|
|
96
|
+
* Every day of a calendar year, in order.
|
|
97
|
+
*
|
|
98
|
+
* Leap years fall out of the loop for free: it walks day by day until the year
|
|
99
|
+
* rolls over, so February 29 is included when it exists.
|
|
100
|
+
*
|
|
101
|
+
* @param year - Four-digit year.
|
|
102
|
+
* @returns 365 or 366 keys, oldest first.
|
|
103
|
+
*/
|
|
104
|
+
export declare function eachDayOfYear(year: number): string[];
|
|
105
|
+
/**
|
|
106
|
+
* Empty cells before a block's first day in a seven-row column grid.
|
|
107
|
+
*
|
|
108
|
+
* The grid fills column by column, so the first column is only partly used
|
|
109
|
+
* unless the block starts exactly on the week's first day. An off-by-one here
|
|
110
|
+
* shifts the whole block by a row, so this is unit tested.
|
|
111
|
+
*
|
|
112
|
+
* @param firstDayKey - First day of the block, e.g. `'2026-02-01'`.
|
|
113
|
+
* @param weekStartsOn - 0 for Sunday, 1 for Monday.
|
|
114
|
+
* @returns 0-6 blank cells.
|
|
115
|
+
*
|
|
116
|
+
* @example
|
|
117
|
+
* ```ts
|
|
118
|
+
* leadingBlanks('2026-01-01', 1) // 3 — a Thursday, Mon-Wed are blank
|
|
119
|
+
* leadingBlanks('2024-01-01', 1) // 0 — a Monday
|
|
120
|
+
* ```
|
|
121
|
+
*/
|
|
122
|
+
export declare function leadingBlanks(firstDayKey: string, weekStartsOn: WeekStart): number;
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/** The two days worth naming rather than numbering. */
|
|
2
|
+
export interface DayLabels {
|
|
3
|
+
today: string;
|
|
4
|
+
yesterday: string;
|
|
5
|
+
}
|
|
6
|
+
/**
|
|
7
|
+
* A short name for a day, relative to today.
|
|
8
|
+
*
|
|
9
|
+
* "Today" and "Yesterday" are worth spelling out — they are the two a user
|
|
10
|
+
* actually reaches for. Anything older gets its weekday, which inside a
|
|
11
|
+
* five-day window is unambiguous and stays two or three characters in every
|
|
12
|
+
* language.
|
|
13
|
+
*
|
|
14
|
+
* The two words are arguments rather than translated here: a library that calls
|
|
15
|
+
* `t()` forces every consumer onto one i18n setup.
|
|
16
|
+
*
|
|
17
|
+
* @param dateKey - The day to label (`YYYY-MM-DD`).
|
|
18
|
+
* @param today - Today's key, passed in so the caller controls the clock.
|
|
19
|
+
* @param labels - What to call today and yesterday.
|
|
20
|
+
*
|
|
21
|
+
* @example
|
|
22
|
+
* ```ts
|
|
23
|
+
* relativeDayLabel('2026-08-28', '2026-08-31', { today: 'Today', yesterday: 'Yesterday' })
|
|
24
|
+
* // 'Fri'
|
|
25
|
+
* ```
|
|
26
|
+
*/
|
|
27
|
+
export declare function relativeDayLabel(dateKey: string, today: string, labels: DayLabels): string;
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Hands the user a file without a server round trip.
|
|
3
|
+
*
|
|
4
|
+
* @param data - Anything `JSON.stringify` can serialise.
|
|
5
|
+
* @param filename - Suggested name, e.g. `hibi-export-2026-08-24.json`.
|
|
6
|
+
*/
|
|
7
|
+
export declare function downloadJson(data: unknown, filename: string): void;
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Points every formatter at a new locale.
|
|
3
|
+
*
|
|
4
|
+
* @example
|
|
5
|
+
* ```ts
|
|
6
|
+
* setFormatLocale('tr-TR')
|
|
7
|
+
* ```
|
|
8
|
+
*/
|
|
9
|
+
export declare function setFormatLocale(next: string): void;
|
|
10
|
+
/**
|
|
11
|
+
* Formats a date in the active locale.
|
|
12
|
+
*
|
|
13
|
+
* Reading the locale ref here is deliberate: called from a `computed`, the
|
|
14
|
+
* result re-evaluates when the language changes.
|
|
15
|
+
*
|
|
16
|
+
* @param date - Date to format.
|
|
17
|
+
* @param options - Passed straight to `Intl.DateTimeFormat`.
|
|
18
|
+
*
|
|
19
|
+
* @example
|
|
20
|
+
* ```ts
|
|
21
|
+
* formatDate(new Date(), { weekday: 'narrow' }) // 'T'
|
|
22
|
+
* ```
|
|
23
|
+
*/
|
|
24
|
+
export declare function formatDate(date: Date, options: Intl.DateTimeFormatOptions): string;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A short vibration for a confirmed tap.
|
|
3
|
+
*
|
|
4
|
+
* Optional chaining is not decoration: iOS Safari has no `vibrate` at all, and
|
|
5
|
+
* calling it unguarded would throw on every marked day.
|
|
6
|
+
*
|
|
7
|
+
* @param duration - Milliseconds. Keep it under ~15ms; longer reads as an alert.
|
|
8
|
+
*/
|
|
9
|
+
export declare function tapFeedback(duration?: number): void;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Whether the app is running from the Home Screen rather than a browser tab.
|
|
3
|
+
*
|
|
4
|
+
* Two checks because iOS predates the standard one: `display-mode: standalone`
|
|
5
|
+
* is the modern signal, `navigator.standalone` is Safari's own.
|
|
6
|
+
*/
|
|
7
|
+
export declare function isInstalled(): boolean;
|
|
8
|
+
/** iPhone and iPad, including iPadOS reporting itself as a Mac. */
|
|
9
|
+
export declare function isApplePortable(): boolean;
|
|
10
|
+
/**
|
|
11
|
+
* Whether this device can only receive notifications once the app is installed.
|
|
12
|
+
*
|
|
13
|
+
* Safari on iOS grants notification permission to an installed web app and to
|
|
14
|
+
* nothing else — in a normal tab the request does not even prompt. Telling the
|
|
15
|
+
* user to allow notifications there is asking for something the browser will
|
|
16
|
+
* not offer, so the UI has to say "add to Home Screen" instead.
|
|
17
|
+
*
|
|
18
|
+
* @example
|
|
19
|
+
* ```ts
|
|
20
|
+
* if (needsIosInstall()) // show the Home Screen instruction, not the button
|
|
21
|
+
* ```
|
|
22
|
+
*/
|
|
23
|
+
export declare function needsIosInstall(): boolean;
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* What a router hands back for one query key.
|
|
3
|
+
*
|
|
4
|
+
* Inlined rather than imported from vue-router: the shape is `string | null`
|
|
5
|
+
* either way, and a helper this small should not drag a router into the
|
|
6
|
+
* package's dependencies.
|
|
7
|
+
*/
|
|
8
|
+
export type QueryValue = string | null;
|
|
9
|
+
/**
|
|
10
|
+
* Resolves a `?redirect=` query value into a safe in-app path.
|
|
11
|
+
*
|
|
12
|
+
* Only same-origin paths are accepted. Anything else falls back to `/`,
|
|
13
|
+
* so a crafted link cannot bounce a user from the real login page to a
|
|
14
|
+
* phishing clone.
|
|
15
|
+
*
|
|
16
|
+
* Pure: takes the query value instead of reading the router, so it also
|
|
17
|
+
* works inside navigation guards and can be unit tested.
|
|
18
|
+
*
|
|
19
|
+
* @param target - Raw `route.query.redirect` value. May be a string, an
|
|
20
|
+
* array (repeated query key), `null`, or `undefined`.
|
|
21
|
+
* @returns A path starting with a single `/`. Defaults to `/`.
|
|
22
|
+
*
|
|
23
|
+
* @example
|
|
24
|
+
* ```ts
|
|
25
|
+
* // in a view
|
|
26
|
+
* await router.push(safeRedirect(route.query.redirect))
|
|
27
|
+
*
|
|
28
|
+
* // in a guard
|
|
29
|
+
* return safeRedirect(to.query.redirect)
|
|
30
|
+
* ```
|
|
31
|
+
*
|
|
32
|
+
* @example
|
|
33
|
+
* ```ts
|
|
34
|
+
* safeRedirect('/week') // '/week'
|
|
35
|
+
* safeRedirect('https://evil.com') // '/'
|
|
36
|
+
* safeRedirect('//evil.com') // '/' (protocol-relative URL)
|
|
37
|
+
* safeRedirect(['/a', '/b']) // '/'
|
|
38
|
+
* safeRedirect(undefined) // '/'
|
|
39
|
+
* ```
|
|
40
|
+
*/
|
|
41
|
+
export declare function safeRedirect(target: QueryValue | QueryValue[] | undefined): string;
|
package/package.json
ADDED
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "rei-kit",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Vue 3 and Tailwind 4 design system and shared runtime. Extracted from Hibi.",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"author": "Ramazan Doğan",
|
|
7
|
+
"repository": {
|
|
8
|
+
"type": "git",
|
|
9
|
+
"url": "git+https://github.com/ramazandogna/rei-kit.git"
|
|
10
|
+
},
|
|
11
|
+
"type": "module",
|
|
12
|
+
"sideEffects": [
|
|
13
|
+
"**/*.css"
|
|
14
|
+
],
|
|
15
|
+
"files": [
|
|
16
|
+
"dist"
|
|
17
|
+
],
|
|
18
|
+
"exports": {
|
|
19
|
+
".": {
|
|
20
|
+
"types": "./dist/index.d.ts",
|
|
21
|
+
"import": "./dist/index.js"
|
|
22
|
+
},
|
|
23
|
+
"./tokens.css": "./dist/tokens.css",
|
|
24
|
+
"./styles.css": "./dist/styles.css",
|
|
25
|
+
"./supabase": {
|
|
26
|
+
"types": "./dist/supabase/index.d.ts",
|
|
27
|
+
"import": "./dist/supabase.js"
|
|
28
|
+
}
|
|
29
|
+
},
|
|
30
|
+
"engines": {
|
|
31
|
+
"node": "^22.18.0 || >=24.12.0"
|
|
32
|
+
},
|
|
33
|
+
"packageManager": "pnpm@10.34.5",
|
|
34
|
+
"scripts": {
|
|
35
|
+
"dev": "vite build --watch",
|
|
36
|
+
"build": "run-s type-check build-only",
|
|
37
|
+
"build-only": "vite build",
|
|
38
|
+
"type-check": "vue-tsc --build",
|
|
39
|
+
"test:unit": "vitest",
|
|
40
|
+
"test:ci": "vitest run",
|
|
41
|
+
"lint": "run-s \"lint:*\"",
|
|
42
|
+
"lint:oxlint": "oxlint . --fix",
|
|
43
|
+
"lint:eslint": "eslint . --fix --cache",
|
|
44
|
+
"check": "run-s check:format check:lint type-check test:ci build-only",
|
|
45
|
+
"check:format": "prettier --check src/",
|
|
46
|
+
"check:lint": "run-s check:lint:*",
|
|
47
|
+
"check:lint:oxlint": "oxlint .",
|
|
48
|
+
"check:lint:eslint": "eslint .",
|
|
49
|
+
"format": "prettier --write src/",
|
|
50
|
+
"prepublishOnly": "pnpm run build"
|
|
51
|
+
},
|
|
52
|
+
"peerDependencies": {
|
|
53
|
+
"lucide-vue-next": "^1.0.0",
|
|
54
|
+
"tailwindcss": "^4.0.0",
|
|
55
|
+
"vue": "^3.5.0",
|
|
56
|
+
"vue-i18n": "^11.0.0",
|
|
57
|
+
"@supabase/supabase-js": "^2.0.0"
|
|
58
|
+
},
|
|
59
|
+
"peerDependenciesMeta": {
|
|
60
|
+
"vue-i18n": {
|
|
61
|
+
"optional": true
|
|
62
|
+
},
|
|
63
|
+
"@supabase/supabase-js": {
|
|
64
|
+
"optional": true
|
|
65
|
+
}
|
|
66
|
+
},
|
|
67
|
+
"devDependencies": {
|
|
68
|
+
"@supabase/supabase-js": "^2.112.4",
|
|
69
|
+
"@tailwindcss/vite": "^4.3.3",
|
|
70
|
+
"@tsconfig/node24": "^24.0.5",
|
|
71
|
+
"@types/node": "^24.13.3",
|
|
72
|
+
"@vitejs/plugin-vue": "^6.0.8",
|
|
73
|
+
"@vitest/eslint-plugin": "^1.6.27",
|
|
74
|
+
"@vue/eslint-config-typescript": "^14.9.0",
|
|
75
|
+
"@vue/test-utils": "^2.5.0",
|
|
76
|
+
"@vue/tsconfig": "^0.9.1",
|
|
77
|
+
"eslint": "^10.7.0",
|
|
78
|
+
"eslint-config-prettier": "^10.1.8",
|
|
79
|
+
"eslint-plugin-oxlint": "^1.80.0",
|
|
80
|
+
"eslint-plugin-vue": "^10.10.0",
|
|
81
|
+
"jiti": "^2.7.0",
|
|
82
|
+
"jsdom": "^29.1.1",
|
|
83
|
+
"lucide-vue-next": "^1.0.0",
|
|
84
|
+
"npm-run-all2": "^9.0.3",
|
|
85
|
+
"oxlint": "^1.74.0",
|
|
86
|
+
"prettier": "^3.9.5",
|
|
87
|
+
"prettier-plugin-tailwindcss": "^0.8.1",
|
|
88
|
+
"tailwindcss": "^4.3.3",
|
|
89
|
+
"typescript": "^6.0.3",
|
|
90
|
+
"vite": "^8.1.5",
|
|
91
|
+
"vite-plugin-dts": "^5.0.3",
|
|
92
|
+
"vitest": "^4.1.10",
|
|
93
|
+
"vue": "^3.5.40",
|
|
94
|
+
"vue-eslint-parser": "^10.4.1",
|
|
95
|
+
"vue-i18n": "^11.4.10",
|
|
96
|
+
"vue-tsc": "^3.3.7"
|
|
97
|
+
}
|
|
98
|
+
}
|