rei-kit 0.12.0 → 0.13.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/dist/_plugin-vue_export-helper-3AcMDTtW.js +339 -0
- package/dist/_plugin-vue_export-helper-3AcMDTtW.js.map +1 -0
- package/dist/app/AuthShell.vue.d.ts +29 -0
- package/dist/app/index.d.ts +16 -0
- package/dist/app/use-tab-transition.d.ts +52 -0
- package/dist/app/use-theme-sync.d.ts +23 -0
- package/dist/app.js +140 -0
- package/dist/app.js.map +1 -0
- package/dist/components/BaseCard.vue.d.ts +11 -2
- package/dist/index.js +22 -436
- package/dist/index.js.map +1 -1
- package/dist/pwa/InstallPrompt.vue.d.ts +26 -0
- package/dist/pwa/UpdatePrompt.vue.d.ts +48 -0
- package/dist/pwa/index.d.ts +15 -0
- package/dist/pwa/use-install.d.ts +41 -0
- package/dist/pwa/use-snooze.d.ts +22 -0
- package/dist/pwa.js +236 -0
- package/dist/pwa.js.map +1 -0
- package/dist/styles.css +69 -0
- package/dist/use-theme-_MnaDD5v.js +94 -0
- package/dist/use-theme-_MnaDD5v.js.map +1 -0
- package/package.json +9 -1
package/dist/index.js
CHANGED
|
@@ -1,158 +1,10 @@
|
|
|
1
|
+
import { a as needsIosInstall, c as fromDateKey, d as startOfWeek, f as toDateKey, i as isInstalled, l as lastNDays, n as BaseButton_default, o as addDays, p as todayKey, r as isApplePortable, s as eachDayOfYear, t as _plugin_vue_export_helper_default, u as leadingBlanks } from "./_plugin-vue_export-helper-3AcMDTtW.js";
|
|
1
2
|
import { n as registerErrorMapper, r as toAppError, t as AppError } from "./app-error-DF9cijE0.js";
|
|
3
|
+
import { a as useTheme, i as setThemeStorageKey, n as isThemePreference, r as readStoredTheme, t as applyTheme } from "./use-theme-_MnaDD5v.js";
|
|
2
4
|
import { Fragment, Teleport, Transition, TransitionGroup, computed, createBlock, createCommentVNode, createElementBlock, createElementVNode, createStaticVNode, createTextVNode, createVNode, defineComponent, mergeModels, mergeProps, nextTick, normalizeClass, normalizeStyle, onBeforeUnmount, onErrorCaptured, onMounted, onScopeDispose, onUnmounted, openBlock, readonly, ref, renderList, renderSlot, resolveDynamicComponent, toDisplayString, unref, useId, useModel, vModelCheckbox, vModelDynamic, vModelRadio, vModelSelect, vModelText, watch, watchEffect, withCtx, withDirectives } from "vue";
|
|
3
5
|
import { ArrowDown, ArrowRight, ArrowUp, CheckCircle2, ChevronDown, ChevronRight, Info, TriangleAlert, X, XCircle } from "lucide-vue-next";
|
|
4
6
|
import { RouterLink } from "vue-router";
|
|
5
7
|
import { createI18n } from "vue-i18n";
|
|
6
|
-
//#region src/utils/date.ts
|
|
7
|
-
/**
|
|
8
|
-
* Local calendar-day helpers.
|
|
9
|
-
*
|
|
10
|
-
* Every function is pure and works on `YYYY-MM-DD` keys, the same shape as the
|
|
11
|
-
* `date` columns in Postgres. Nothing here calls `toISOString`: that converts to
|
|
12
|
-
* UTC, so in a UTC+9 timezone every entry made between midnight and 09:00 would
|
|
13
|
-
* be written to the previous day.
|
|
14
|
-
*/
|
|
15
|
-
/**
|
|
16
|
-
* Formats a `Date` as a local `YYYY-MM-DD` key.
|
|
17
|
-
*
|
|
18
|
-
* @param date - Any `Date`; only its local year, month and day are read.
|
|
19
|
-
* @returns The calendar day in the runtime's own timezone.
|
|
20
|
-
*
|
|
21
|
-
* @example
|
|
22
|
-
* ```ts
|
|
23
|
-
* // 2026-08-23 01:30 in Tokyo
|
|
24
|
-
* toDateKey(new Date()) // '2026-08-23'
|
|
25
|
-
* new Date().toISOString() // '2026-08-22T16:30…' ← the bug
|
|
26
|
-
* ```
|
|
27
|
-
*/
|
|
28
|
-
function toDateKey(date) {
|
|
29
|
-
return `${String(date.getFullYear()).padStart(4, "0")}-${String(date.getMonth() + 1).padStart(2, "0")}-${String(date.getDate()).padStart(2, "0")}`;
|
|
30
|
-
}
|
|
31
|
-
/** Today's key in the user's own timezone. */
|
|
32
|
-
function todayKey() {
|
|
33
|
-
return toDateKey(/* @__PURE__ */ new Date());
|
|
34
|
-
}
|
|
35
|
-
/**
|
|
36
|
-
* Parses a `YYYY-MM-DD` key into a `Date` at local midnight.
|
|
37
|
-
*
|
|
38
|
-
* @param key - A key produced by {@link toDateKey}.
|
|
39
|
-
* @returns Local midnight of that calendar day.
|
|
40
|
-
* @throws If the key is not three numeric parts.
|
|
41
|
-
*
|
|
42
|
-
* @example
|
|
43
|
-
* ```ts
|
|
44
|
-
* fromDateKey('2026-08-23') // local midnight, correct
|
|
45
|
-
* new Date('2026-08-23') // UTC midnight — shifts a day in some zones
|
|
46
|
-
* ```
|
|
47
|
-
*/
|
|
48
|
-
function fromDateKey(key) {
|
|
49
|
-
const [year, month, day] = key.split("-").map(Number);
|
|
50
|
-
if (year === void 0 || month === void 0 || day === void 0) throw new Error(`Invalid date key: ${key}`);
|
|
51
|
-
return new Date(year, month - 1, day);
|
|
52
|
-
}
|
|
53
|
-
/**
|
|
54
|
-
* Shifts a date key by whole calendar days.
|
|
55
|
-
*
|
|
56
|
-
* Uses `setDate`, which is calendar-aware: it rolls over month and year ends,
|
|
57
|
-
* and stays correct across daylight-saving transitions. Adding
|
|
58
|
-
* `days * 86_400_000` milliseconds would not — a DST day is 23 or 25 hours long.
|
|
59
|
-
*
|
|
60
|
-
* @param key - Starting `YYYY-MM-DD` key.
|
|
61
|
-
* @param days - Days to add; negative goes back.
|
|
62
|
-
* @returns The resulting key.
|
|
63
|
-
*
|
|
64
|
-
* @example
|
|
65
|
-
* ```ts
|
|
66
|
-
* addDays('2026-01-31', 1) // '2026-02-01'
|
|
67
|
-
* addDays('2026-01-01', -1) // '2025-12-31'
|
|
68
|
-
* addDays('2028-02-28', 1) // '2028-02-29' — leap year
|
|
69
|
-
* ```
|
|
70
|
-
*/
|
|
71
|
-
function addDays(key, days) {
|
|
72
|
-
const date = fromDateKey(key);
|
|
73
|
-
date.setDate(date.getDate() + days);
|
|
74
|
-
return toDateKey(date);
|
|
75
|
-
}
|
|
76
|
-
/**
|
|
77
|
-
* The last `count` days ending today, oldest first.
|
|
78
|
-
*
|
|
79
|
-
* `today` is a parameter so the function stays pure and testable; call sites
|
|
80
|
-
* normally omit it.
|
|
81
|
-
*
|
|
82
|
-
* @param count - How many days to return, including `today`.
|
|
83
|
-
* @param today - End of the range. Defaults to the real today.
|
|
84
|
-
* @returns Keys in ascending order.
|
|
85
|
-
*
|
|
86
|
-
* @example
|
|
87
|
-
* ```ts
|
|
88
|
-
* lastNDays(3, '2026-08-23') // ['2026-08-21', '2026-08-22', '2026-08-23']
|
|
89
|
-
* ```
|
|
90
|
-
*/
|
|
91
|
-
function lastNDays(count, today = todayKey()) {
|
|
92
|
-
const keys = [];
|
|
93
|
-
for (let offset = count - 1; offset >= 0; offset -= 1) keys.push(addDays(today, -offset));
|
|
94
|
-
return keys;
|
|
95
|
-
}
|
|
96
|
-
/**
|
|
97
|
-
* The first day of the week containing `key`.
|
|
98
|
-
*
|
|
99
|
-
* The user's preference is a parameter, not a module-level setting: changing it
|
|
100
|
-
* in Profile has to re-render the week grid and the year heatmap immediately,
|
|
101
|
-
* and a global would make that a hidden dependency.
|
|
102
|
-
*
|
|
103
|
-
* @param key - Any day in the week.
|
|
104
|
-
* @param weekStartsOn - 0 for Sunday, 1 for Monday.
|
|
105
|
-
* @returns Key of that week's first day.
|
|
106
|
-
*
|
|
107
|
-
* @example
|
|
108
|
-
* ```ts
|
|
109
|
-
* // 2026-08-23 is a Sunday
|
|
110
|
-
* startOfWeek('2026-08-23', 1) // '2026-08-17' — previous Monday
|
|
111
|
-
* startOfWeek('2026-08-23', 0) // '2026-08-23' — already Sunday
|
|
112
|
-
* ```
|
|
113
|
-
*/
|
|
114
|
-
function startOfWeek(key, weekStartsOn) {
|
|
115
|
-
return addDays(key, -((fromDateKey(key).getDay() - weekStartsOn + 7) % 7));
|
|
116
|
-
}
|
|
117
|
-
/**
|
|
118
|
-
* Every day of a calendar year, in order.
|
|
119
|
-
*
|
|
120
|
-
* Leap years fall out of the loop for free: it walks day by day until the year
|
|
121
|
-
* rolls over, so February 29 is included when it exists.
|
|
122
|
-
*
|
|
123
|
-
* @param year - Four-digit year.
|
|
124
|
-
* @returns 365 or 366 keys, oldest first.
|
|
125
|
-
*/
|
|
126
|
-
function eachDayOfYear(year) {
|
|
127
|
-
const keys = [];
|
|
128
|
-
const date = new Date(year, 0, 1);
|
|
129
|
-
while (date.getFullYear() === year) {
|
|
130
|
-
keys.push(toDateKey(date));
|
|
131
|
-
date.setDate(date.getDate() + 1);
|
|
132
|
-
}
|
|
133
|
-
return keys;
|
|
134
|
-
}
|
|
135
|
-
/**
|
|
136
|
-
* Empty cells before a block's first day in a seven-row column grid.
|
|
137
|
-
*
|
|
138
|
-
* The grid fills column by column, so the first column is only partly used
|
|
139
|
-
* unless the block starts exactly on the week's first day. An off-by-one here
|
|
140
|
-
* shifts the whole block by a row, so this is unit tested.
|
|
141
|
-
*
|
|
142
|
-
* @param firstDayKey - First day of the block, e.g. `'2026-02-01'`.
|
|
143
|
-
* @param weekStartsOn - 0 for Sunday, 1 for Monday.
|
|
144
|
-
* @returns 0-6 blank cells.
|
|
145
|
-
*
|
|
146
|
-
* @example
|
|
147
|
-
* ```ts
|
|
148
|
-
* leadingBlanks('2026-01-01', 1) // 3 — a Thursday, Mon-Wed are blank
|
|
149
|
-
* leadingBlanks('2024-01-01', 1) // 0 — a Monday
|
|
150
|
-
* ```
|
|
151
|
-
*/
|
|
152
|
-
function leadingBlanks(firstDayKey, weekStartsOn) {
|
|
153
|
-
return (fromDateKey(firstDayKey).getDay() - weekStartsOn + 7) % 7;
|
|
154
|
-
}
|
|
155
|
-
//#endregion
|
|
156
8
|
//#region src/utils/format.ts
|
|
157
9
|
/**
|
|
158
10
|
* The locale `Intl` formatting uses.
|
|
@@ -300,129 +152,6 @@ function tapFeedback(duration = 10) {
|
|
|
300
152
|
navigator.vibrate?.(duration);
|
|
301
153
|
}
|
|
302
154
|
//#endregion
|
|
303
|
-
//#region src/utils/platform.ts
|
|
304
|
-
/**
|
|
305
|
-
* Whether the app is running from the Home Screen rather than a browser tab.
|
|
306
|
-
*
|
|
307
|
-
* Two checks because iOS predates the standard one: `display-mode: standalone`
|
|
308
|
-
* is the modern signal, `navigator.standalone` is Safari's own.
|
|
309
|
-
*/
|
|
310
|
-
function isInstalled() {
|
|
311
|
-
if (typeof window === "undefined") return false;
|
|
312
|
-
return window.matchMedia("(display-mode: standalone)").matches || navigator.standalone === true;
|
|
313
|
-
}
|
|
314
|
-
/** iPhone and iPad, including iPadOS reporting itself as a Mac. */
|
|
315
|
-
function isApplePortable() {
|
|
316
|
-
if (typeof window === "undefined") return false;
|
|
317
|
-
return /iPad|iPhone|iPod/.test(navigator.userAgent) || navigator.platform === "MacIntel" && navigator.maxTouchPoints > 1;
|
|
318
|
-
}
|
|
319
|
-
/**
|
|
320
|
-
* Whether this device can only receive notifications once the app is installed.
|
|
321
|
-
*
|
|
322
|
-
* Safari on iOS grants notification permission to an installed web app and to
|
|
323
|
-
* nothing else — in a normal tab the request does not even prompt. Telling the
|
|
324
|
-
* user to allow notifications there is asking for something the browser will
|
|
325
|
-
* not offer, so the UI has to say "add to Home Screen" instead.
|
|
326
|
-
*
|
|
327
|
-
* @example
|
|
328
|
-
* ```ts
|
|
329
|
-
* if (needsIosInstall()) // show the Home Screen instruction, not the button
|
|
330
|
-
* ```
|
|
331
|
-
*/
|
|
332
|
-
function needsIosInstall() {
|
|
333
|
-
return isApplePortable() && !isInstalled();
|
|
334
|
-
}
|
|
335
|
-
//#endregion
|
|
336
|
-
//#region src/composables/use-theme.ts
|
|
337
|
-
/**
|
|
338
|
-
* Namespaced by the app, not by this package.
|
|
339
|
-
*
|
|
340
|
-
* Two rei-kit apps served from the same origin would otherwise share one theme
|
|
341
|
-
* setting — and during development on localhost, they will be.
|
|
342
|
-
*/
|
|
343
|
-
var storageKey = "rei-theme";
|
|
344
|
-
function isThemePreference(value) {
|
|
345
|
-
return value === "system" || value === "light" || value === "dark";
|
|
346
|
-
}
|
|
347
|
-
/** Reads the stored preference, falling back to `system`. */
|
|
348
|
-
function readStoredTheme() {
|
|
349
|
-
try {
|
|
350
|
-
const stored = localStorage.getItem(storageKey);
|
|
351
|
-
return isThemePreference(stored) ? stored : "system";
|
|
352
|
-
} catch {
|
|
353
|
-
return "system";
|
|
354
|
-
}
|
|
355
|
-
}
|
|
356
|
-
function storeTheme(preference) {
|
|
357
|
-
try {
|
|
358
|
-
localStorage.setItem(storageKey, preference);
|
|
359
|
-
} catch {}
|
|
360
|
-
}
|
|
361
|
-
/**
|
|
362
|
-
* Does the environment prefer a dark scheme?
|
|
363
|
-
*
|
|
364
|
-
* `matchMedia` is checked for on its own rather than inferred from `document`.
|
|
365
|
-
* Having one does not imply having the other: jsdom supplies a document and no
|
|
366
|
-
* `matchMedia`, so a consumer's component test that so much as mounts something
|
|
367
|
-
* calling `useTheme` threw — and some embedded webviews are the same. Where
|
|
368
|
-
* there is nothing to ask, the answer is no rather than an exception.
|
|
369
|
-
*/
|
|
370
|
-
function prefersDarkScheme() {
|
|
371
|
-
return typeof window !== "undefined" && typeof window.matchMedia === "function" ? window.matchMedia("(prefers-color-scheme: dark)").matches : false;
|
|
372
|
-
}
|
|
373
|
-
/**
|
|
374
|
-
* Adds or removes `.dark` on `<html>`, resolving `system` against the OS.
|
|
375
|
-
*
|
|
376
|
-
* A no-op without a document. There is no OS preference to read on a server and
|
|
377
|
-
* no `<html>` to write to, so a prerender leaves the class off and the app
|
|
378
|
-
* decides the theme before hydration — see the note in the README.
|
|
379
|
-
*/
|
|
380
|
-
function applyTheme(preference) {
|
|
381
|
-
if (typeof document === "undefined") return;
|
|
382
|
-
const isDark = preference === "dark" || preference === "system" && prefersDarkScheme();
|
|
383
|
-
document.documentElement.classList.toggle("dark", isDark);
|
|
384
|
-
}
|
|
385
|
-
/**
|
|
386
|
-
* The shared preference, created on first use rather than at import.
|
|
387
|
-
*
|
|
388
|
-
* Lazy on purpose: reading storage at import time would lock in the default key
|
|
389
|
-
* before an app had a chance to set its own, leaving the controller reading one
|
|
390
|
-
* key and writing another.
|
|
391
|
-
*/
|
|
392
|
-
var preference = null;
|
|
393
|
-
function controller() {
|
|
394
|
-
if (preference) return preference;
|
|
395
|
-
preference = ref(readStoredTheme());
|
|
396
|
-
watch(preference, (next) => {
|
|
397
|
-
storeTheme(next);
|
|
398
|
-
applyTheme(next);
|
|
399
|
-
}, { immediate: true });
|
|
400
|
-
if (typeof window !== "undefined" && typeof window.matchMedia === "function") window.matchMedia("(prefers-color-scheme: dark)").addEventListener("change", () => {
|
|
401
|
-
if (preference?.value === "system") applyTheme("system");
|
|
402
|
-
});
|
|
403
|
-
return preference;
|
|
404
|
-
}
|
|
405
|
-
/**
|
|
406
|
-
* Sets where the preference is stored.
|
|
407
|
-
*
|
|
408
|
-
* Safe in either order: called before the first `useTheme()` it simply changes
|
|
409
|
-
* the key, and called after it re-reads under the new one, so the controller
|
|
410
|
-
* never reads from one key while writing to another.
|
|
411
|
-
*
|
|
412
|
-
* @example
|
|
413
|
-
* ```ts
|
|
414
|
-
* setThemeStorageKey('hibi-theme') // once, at startup
|
|
415
|
-
* ```
|
|
416
|
-
*/
|
|
417
|
-
function setThemeStorageKey(key) {
|
|
418
|
-
storageKey = key;
|
|
419
|
-
if (preference) preference.value = readStoredTheme();
|
|
420
|
-
}
|
|
421
|
-
/** @returns The shared preference ref; assigning to it stores and applies it. */
|
|
422
|
-
function useTheme() {
|
|
423
|
-
return controller();
|
|
424
|
-
}
|
|
425
|
-
//#endregion
|
|
426
155
|
//#region src/composables/use-today.ts
|
|
427
156
|
/**
|
|
428
157
|
* Today's date key, kept current while the app stays open.
|
|
@@ -838,7 +567,7 @@ function useToast() {
|
|
|
838
567
|
}
|
|
839
568
|
//#endregion
|
|
840
569
|
//#region src/components/BaseAlert.vue?vue&type=script&setup=true&lang.ts
|
|
841
|
-
var _hoisted_1$
|
|
570
|
+
var _hoisted_1$21 = ["role", "aria-live"];
|
|
842
571
|
var _hoisted_2$16 = { class: "min-w-0 flex-1" };
|
|
843
572
|
var _hoisted_3$11 = {
|
|
844
573
|
key: 0,
|
|
@@ -883,7 +612,7 @@ var BaseAlert_default = /* @__PURE__ */ defineComponent({
|
|
|
883
612
|
}, [renderSlot(_ctx.$slots, "mark")], 2)) : createCommentVNode("", true),
|
|
884
613
|
createElementVNode("div", _hoisted_2$16, [_ctx.$slots.title ? (openBlock(), createElementBlock("p", _hoisted_3$11, [renderSlot(_ctx.$slots, "title")])) : createCommentVNode("", true), createElementVNode("div", { class: normalizeClass(_ctx.$slots.title ? "mt-1" : "") }, [renderSlot(_ctx.$slots, "default")], 2)]),
|
|
885
614
|
renderSlot(_ctx.$slots, "action")
|
|
886
|
-
], 10, _hoisted_1$
|
|
615
|
+
], 10, _hoisted_1$21);
|
|
887
616
|
};
|
|
888
617
|
}
|
|
889
618
|
});
|
|
@@ -907,151 +636,6 @@ var BaseBadge_default = /* @__PURE__ */ defineComponent({
|
|
|
907
636
|
}
|
|
908
637
|
});
|
|
909
638
|
//#endregion
|
|
910
|
-
//#region src/components/BaseButton.vue?vue&type=script&setup=true&lang.ts
|
|
911
|
-
var _hoisted_1$21 = {
|
|
912
|
-
key: 0,
|
|
913
|
-
class: "size-4 animate-spin rounded-full border-2 border-current border-t-transparent",
|
|
914
|
-
"aria-hidden": "true"
|
|
915
|
-
};
|
|
916
|
-
//#endregion
|
|
917
|
-
//#region src/components/BaseButton.vue
|
|
918
|
-
var BaseButton_default = /* @__PURE__ */ defineComponent({
|
|
919
|
-
__name: "BaseButton",
|
|
920
|
-
props: {
|
|
921
|
-
as: { default: "button" },
|
|
922
|
-
variant: { default: "primary" },
|
|
923
|
-
size: { default: "md" },
|
|
924
|
-
loading: {
|
|
925
|
-
type: Boolean,
|
|
926
|
-
default: false
|
|
927
|
-
},
|
|
928
|
-
disabled: {
|
|
929
|
-
type: Boolean,
|
|
930
|
-
default: false
|
|
931
|
-
},
|
|
932
|
-
type: { default: "button" },
|
|
933
|
-
icon: {
|
|
934
|
-
type: Boolean,
|
|
935
|
-
default: false
|
|
936
|
-
},
|
|
937
|
-
block: {
|
|
938
|
-
type: Boolean,
|
|
939
|
-
default: false
|
|
940
|
-
},
|
|
941
|
-
to: { default: () => void 0 },
|
|
942
|
-
href: { default: () => void 0 },
|
|
943
|
-
pill: {
|
|
944
|
-
type: Boolean,
|
|
945
|
-
default: false
|
|
946
|
-
},
|
|
947
|
-
pressed: {
|
|
948
|
-
type: Boolean,
|
|
949
|
-
default: () => void 0
|
|
950
|
-
}
|
|
951
|
-
},
|
|
952
|
-
setup(__props) {
|
|
953
|
-
const VARIANT_CLASS = {
|
|
954
|
-
primary: "bg-primary text-white hover:bg-primary/90",
|
|
955
|
-
secondary: "border-hair bg-surface text-ink border hover:bg-muted",
|
|
956
|
-
ghost: "bg-transparent text-ink hover:bg-muted",
|
|
957
|
-
destructive: "bg-transparent text-ink-soft hover:text-negative",
|
|
958
|
-
row: "w-full justify-start text-left bg-transparent text-ink hover:bg-muted",
|
|
959
|
-
quiet: "bg-transparent text-ink-soft hover:bg-muted hover:text-ink",
|
|
960
|
-
danger: "bg-negative text-white hover:bg-negative/90",
|
|
961
|
-
positive: "bg-positive text-white hover:bg-positive/90",
|
|
962
|
-
warning: "bg-warning text-white hover:bg-warning/90",
|
|
963
|
-
accent: "bg-accent text-white hover:bg-accent/90",
|
|
964
|
-
link: "bg-transparent underline underline-offset-2 hover:opacity-80",
|
|
965
|
-
unstyled: ""
|
|
966
|
-
};
|
|
967
|
-
const SIZE_CLASS = {
|
|
968
|
-
xs: "h-8 px-3 text-xs",
|
|
969
|
-
sm: "h-9 px-3 text-sm",
|
|
970
|
-
md: "h-11 px-4 text-base",
|
|
971
|
-
lg: "h-14 px-6 text-lg"
|
|
972
|
-
};
|
|
973
|
-
const ICON_SIZE_CLASS = {
|
|
974
|
-
xs: "size-8 text-xs",
|
|
975
|
-
sm: "size-9 text-sm",
|
|
976
|
-
md: "size-11 text-base",
|
|
977
|
-
lg: "size-14 text-lg"
|
|
978
|
-
};
|
|
979
|
-
const ROW_SIZE_CLASS = {
|
|
980
|
-
xs: "px-2 py-1.5 text-xs",
|
|
981
|
-
sm: "px-3 py-2 text-sm",
|
|
982
|
-
md: "px-3 py-2.5 text-base",
|
|
983
|
-
lg: "px-4 py-3 text-lg"
|
|
984
|
-
};
|
|
985
|
-
const LINK_SIZE_CLASS = {
|
|
986
|
-
xs: "text-xs",
|
|
987
|
-
sm: "text-sm",
|
|
988
|
-
md: "text-base",
|
|
989
|
-
lg: "text-lg"
|
|
990
|
-
};
|
|
991
|
-
const sizing = computed(() => {
|
|
992
|
-
if (__props.variant === "unstyled") return "";
|
|
993
|
-
if (__props.variant === "link") return LINK_SIZE_CLASS[__props.size];
|
|
994
|
-
if (__props.variant === "row") return ROW_SIZE_CLASS[__props.size];
|
|
995
|
-
return __props.icon ? ICON_SIZE_CLASS[__props.size] : SIZE_CLASS[__props.size];
|
|
996
|
-
});
|
|
997
|
-
const PRESSED_CLASS = {
|
|
998
|
-
ghost: "bg-primary text-white hover:bg-primary/90",
|
|
999
|
-
quiet: "bg-primary text-white hover:bg-primary/90",
|
|
1000
|
-
secondary: "bg-primary border-primary text-white hover:bg-primary/90",
|
|
1001
|
-
row: "w-full justify-start text-left bg-muted text-ink hover:bg-muted"
|
|
1002
|
-
};
|
|
1003
|
-
const surface = computed(() => {
|
|
1004
|
-
if (__props.pressed === true) return PRESSED_CLASS[__props.variant] ?? VARIANT_CLASS[__props.variant];
|
|
1005
|
-
if (__props.variant === "destructive") return `${VARIANT_CLASS.destructive} hover:bg-negative/10`;
|
|
1006
|
-
return VARIANT_CLASS[__props.variant];
|
|
1007
|
-
});
|
|
1008
|
-
const shell = computed(() => {
|
|
1009
|
-
if (__props.variant === "unstyled") return "";
|
|
1010
|
-
const feel = "transition-[transform,color,background-color,border-color] duration-100 select-none";
|
|
1011
|
-
if (__props.variant === "row") return `inline-flex items-center gap-2 font-medium ${feel}`;
|
|
1012
|
-
return `inline-flex items-center justify-center gap-2 font-medium ${feel} active:scale-95`;
|
|
1013
|
-
});
|
|
1014
|
-
const radius = computed(() => {
|
|
1015
|
-
if (__props.variant === "unstyled") return "";
|
|
1016
|
-
if (__props.variant === "link") return "rounded-xs";
|
|
1017
|
-
return __props.pill ? "rounded-full" : "rounded-card";
|
|
1018
|
-
});
|
|
1019
|
-
/** Anything that is not a `<button>` cannot be `disabled`; it has to be told. */
|
|
1020
|
-
const inactive = computed(() => __props.disabled || __props.loading);
|
|
1021
|
-
const linkProps = computed(() => {
|
|
1022
|
-
if (__props.as === "router-link") return { to: __props.to };
|
|
1023
|
-
if (__props.as === "a") return inactive.value ? {} : { href: __props.href };
|
|
1024
|
-
return {};
|
|
1025
|
-
});
|
|
1026
|
-
return (_ctx, _cache) => {
|
|
1027
|
-
return openBlock(), createBlock(resolveDynamicComponent(__props.as), mergeProps(linkProps.value, {
|
|
1028
|
-
type: __props.as === "button" ? __props.type : void 0,
|
|
1029
|
-
disabled: __props.as === "button" ? inactive.value : void 0,
|
|
1030
|
-
"aria-disabled": __props.as !== "button" && inactive.value ? "true" : void 0,
|
|
1031
|
-
"aria-busy": __props.loading,
|
|
1032
|
-
"aria-pressed": __props.pressed === void 0 ? void 0 : String(__props.pressed),
|
|
1033
|
-
class: ["focus-visible:outline-primary focus-visible:outline-2 focus-visible:outline-offset-2 disabled:pointer-events-none disabled:opacity-50 aria-disabled:pointer-events-none aria-disabled:opacity-50", [
|
|
1034
|
-
shell.value,
|
|
1035
|
-
surface.value,
|
|
1036
|
-
sizing.value,
|
|
1037
|
-
radius.value,
|
|
1038
|
-
__props.block ? "w-full" : ""
|
|
1039
|
-
]]
|
|
1040
|
-
}), {
|
|
1041
|
-
default: withCtx(() => [__props.loading ? (openBlock(), createElementBlock("span", _hoisted_1$21)) : createCommentVNode("", true), renderSlot(_ctx.$slots, "default")]),
|
|
1042
|
-
_: 3
|
|
1043
|
-
}, 16, [
|
|
1044
|
-
"type",
|
|
1045
|
-
"disabled",
|
|
1046
|
-
"aria-disabled",
|
|
1047
|
-
"aria-busy",
|
|
1048
|
-
"aria-pressed",
|
|
1049
|
-
"class"
|
|
1050
|
-
]);
|
|
1051
|
-
};
|
|
1052
|
-
}
|
|
1053
|
-
});
|
|
1054
|
-
//#endregion
|
|
1055
639
|
//#region src/components/FormField.vue?vue&type=script&setup=true&lang.ts
|
|
1056
640
|
var _hoisted_1$20 = ["for"];
|
|
1057
641
|
//#endregion
|
|
@@ -1175,7 +759,9 @@ var _hoisted_6$2 = {
|
|
|
1175
759
|
class: "text-ink-soft mt-1 text-sm leading-snug"
|
|
1176
760
|
};
|
|
1177
761
|
var _hoisted_7$2 = { class: "min-h-0 flex-1 overflow-y-auto px-6 pb-[calc(2rem+env(safe-area-inset-bottom,0px))]" };
|
|
1178
|
-
|
|
762
|
+
//#endregion
|
|
763
|
+
//#region src/components/BaseSheet.vue
|
|
764
|
+
var BaseSheet_default = /*#__PURE__*/ _plugin_vue_export_helper_default(/* @__PURE__ */ defineComponent({
|
|
1179
765
|
__name: "BaseSheet",
|
|
1180
766
|
props: /*@__PURE__*/ mergeModels({
|
|
1181
767
|
title: {},
|
|
@@ -1276,17 +862,7 @@ var BaseSheet_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ define
|
|
|
1276
862
|
})]);
|
|
1277
863
|
};
|
|
1278
864
|
}
|
|
1279
|
-
});
|
|
1280
|
-
//#endregion
|
|
1281
|
-
//#region \0plugin-vue:export-helper
|
|
1282
|
-
var _plugin_vue_export_helper_default = (sfc, props) => {
|
|
1283
|
-
const target = sfc.__vccOpts || sfc;
|
|
1284
|
-
for (const [key, val] of props) target[key] = val;
|
|
1285
|
-
return target;
|
|
1286
|
-
};
|
|
1287
|
-
//#endregion
|
|
1288
|
-
//#region src/components/BaseSheet.vue
|
|
1289
|
-
var BaseSheet_default = /*#__PURE__*/ _plugin_vue_export_helper_default(BaseSheet_vue_vue_type_script_setup_true_lang_default, [["__scopeId", "data-v-51709579"]]);
|
|
865
|
+
}), [["__scopeId", "data-v-51709579"]]);
|
|
1290
866
|
//#endregion
|
|
1291
867
|
//#region src/components/BaseCard.vue
|
|
1292
868
|
var BaseCard_default = /* @__PURE__ */ defineComponent({
|
|
@@ -1308,6 +884,13 @@ var BaseCard_default = /* @__PURE__ */ defineComponent({
|
|
|
1308
884
|
* so a card on one screen had a heavier border than a card on the next and
|
|
1309
885
|
* nobody could say why.
|
|
1310
886
|
*
|
|
887
|
+
* With no head and no foot there is no wrapper div: the padding lands on the
|
|
888
|
+
* card itself and the card *is* the element. That matters more than a saved
|
|
889
|
+
* node — most cards in the apps lay their contents out (`flex items-center
|
|
890
|
+
* gap-4`, `flex flex-col gap-3`), and with a wrapper in the way those classes
|
|
891
|
+
* reach the border and not the content, so the app has to add back the div
|
|
892
|
+
* this component exists to remove. One that makes you do that is one you skip.
|
|
893
|
+
*
|
|
1311
894
|
* `interactive` is for a card that is a link or a button: it adds the lift and
|
|
1312
895
|
* the press, and it is opt-in because a card holding a form should not move
|
|
1313
896
|
* when the pointer crosses it.
|
|
@@ -1325,15 +908,18 @@ var BaseCard_default = /* @__PURE__ */ defineComponent({
|
|
|
1325
908
|
lg: "px-5 py-4"
|
|
1326
909
|
};
|
|
1327
910
|
return (_ctx, _cache) => {
|
|
1328
|
-
return openBlock(), createBlock(resolveDynamicComponent(__props.as), { class: normalizeClass(["border-hair bg-surface rounded-card border", __props.interactive ? "transition-[transform,box-shadow] duration-300 ease-out hover:-translate-y-0.5 hover:shadow-lg active:translate-y-0 active:shadow-sm" : ""]) }, {
|
|
911
|
+
return openBlock(), createBlock(resolveDynamicComponent(__props.as), { class: normalizeClass(["border-hair bg-surface rounded-card border", [__props.interactive ? "transition-[transform,box-shadow] duration-300 ease-out hover:-translate-y-0.5 hover:shadow-lg active:translate-y-0 active:shadow-sm" : "", _ctx.$slots.head || _ctx.$slots.foot ? "" : BODY[__props.padding]]]) }, {
|
|
1329
912
|
default: withCtx(() => [
|
|
1330
913
|
_ctx.$slots.head ? (openBlock(), createElementBlock("div", {
|
|
1331
914
|
key: 0,
|
|
1332
915
|
class: normalizeClass(["border-hair/70 border-b", HEAD[__props.padding]])
|
|
1333
916
|
}, [renderSlot(_ctx.$slots, "head")], 2)) : createCommentVNode("", true),
|
|
1334
|
-
|
|
1335
|
-
_ctx.$slots.foot ? (openBlock(), createElementBlock("div", {
|
|
917
|
+
_ctx.$slots.head || _ctx.$slots.foot ? (openBlock(), createElementBlock("div", {
|
|
1336
918
|
key: 1,
|
|
919
|
+
class: normalizeClass(BODY[__props.padding])
|
|
920
|
+
}, [renderSlot(_ctx.$slots, "default")], 2)) : renderSlot(_ctx.$slots, "default", {}, void 0, void 0, 2),
|
|
921
|
+
_ctx.$slots.foot ? (openBlock(), createElementBlock("div", {
|
|
922
|
+
key: 3,
|
|
1337
923
|
class: normalizeClass(["border-hair/70 bg-muted/30 border-t", HEAD[__props.padding]])
|
|
1338
924
|
}, [renderSlot(_ctx.$slots, "foot")], 2)) : createCommentVNode("", true)
|
|
1339
925
|
]),
|
|
@@ -2427,7 +2013,7 @@ function createI18nRuntime(options) {
|
|
|
2427
2013
|
*
|
|
2428
2014
|
* The fallback keeps `vitest` and `vite dev` honest, where no define runs.
|
|
2429
2015
|
*/
|
|
2430
|
-
var VERSION = "0.
|
|
2016
|
+
var VERSION = "0.13.0";
|
|
2431
2017
|
//#endregion
|
|
2432
2018
|
export { AppError, BaseAlert_default as BaseAlert, BaseBadge_default as BaseBadge, BaseButton_default as BaseButton, BaseCard_default as BaseCard, BaseCheckbox_default as BaseCheckbox, BaseInput_default as BaseInput, BaseRadioGroup_default as BaseRadioGroup, BaseSelect_default as BaseSelect, BaseSheet_default as BaseSheet, BaseTextarea_default as BaseTextarea, EmptyState_default as EmptyState, ErrorBoundary_default as ErrorBoundary, FormField_default as FormField, GoogleButton_default as GoogleButton, LocaleLinks_default as LocaleLinks, PageContainer_default as PageContainer, PageHeader_default as PageHeader, PriceCard_default as PriceCard, ProgressBar_default as ProgressBar, SectionHeading_default as SectionHeading, SegmentedControl_default as SegmentedControl, SettingsGroup_default as SettingsGroup, SettingsRow_default as SettingsRow, SkeletonList_default as SkeletonList, StatCard_default as StatCard, TabBar_default as TabBar, ToastHost_default as ToastHost, ToneDot_default as ToneDot, VERSION, addDays, applyTheme, createI18nRuntime, downloadJson, eachDayOfYear, formatDate, fromDateKey, isApplePortable, isInstalled, isThemePreference, lastNDays, leadingBlanks, needsIosInstall, readStoredTheme, registerErrorMapper, relativeDayLabel, safeRedirect, setFormatLocale, setThemeStorageKey, startOfWeek, tapFeedback, toAppError, toDateKey, todayKey, useDebouncedCallback, useDragScroll, useMediaQuery, useOnline, useTheme, useToast, useToday, useVisualViewport };
|
|
2433
2019
|
|