beez-ui 0.8.2 → 0.9.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 (48) hide show
  1. package/CHANGELOG.md +20 -0
  2. package/README.md +11 -9
  3. package/dist/components/filter-presets-bar.d.ts +71 -0
  4. package/dist/components/filter-presets-bar.js +508 -0
  5. package/dist/components/reaction-button.d.ts +7 -2
  6. package/dist/components/reaction-button.js +59 -48
  7. package/dist/hooks.d.ts +10 -0
  8. package/dist/hooks.js +10 -0
  9. package/dist/index.d.ts +1 -23
  10. package/dist/index.js +1 -23
  11. package/dist/styles.css +1 -1
  12. package/package.json +11 -126
  13. package/dist/components/bouncing-dots-loader.d.ts +0 -19
  14. package/dist/components/bouncing-dots-loader.js +0 -47
  15. package/dist/components/confirm-delete-button.d.ts +0 -29
  16. package/dist/components/confirm-delete-button.js +0 -254
  17. package/dist/components/empty-state.d.ts +0 -24
  18. package/dist/components/empty-state.js +0 -37
  19. package/dist/components/error-state.d.ts +0 -20
  20. package/dist/components/error-state.js +0 -145
  21. package/dist/components/external-browser-handoff.d.ts +0 -27
  22. package/dist/components/external-browser-handoff.js +0 -306
  23. package/dist/components/info-popover.d.ts +0 -23
  24. package/dist/components/info-popover.js +0 -158
  25. package/dist/components/month-calendar-header.d.ts +0 -65
  26. package/dist/components/month-calendar-header.js +0 -337
  27. package/dist/components/month-grid.d.ts +0 -59
  28. package/dist/components/month-grid.js +0 -301
  29. package/dist/components/notification-bell.d.ts +0 -50
  30. package/dist/components/notification-bell.js +0 -338
  31. package/dist/components/notification-panel.d.ts +0 -56
  32. package/dist/components/notification-panel.js +0 -281
  33. package/dist/components/open-in-browser-cta.d.ts +0 -22
  34. package/dist/components/open-in-browser-cta.js +0 -61
  35. package/dist/components/pwa-update-control.d.ts +0 -18
  36. package/dist/components/pwa-update-control.js +0 -119
  37. package/dist/emoji-picker.d.ts +0 -27
  38. package/dist/emoji-picker.js +0 -283
  39. package/dist/hooks/use-minute-clock.d.ts +0 -23
  40. package/dist/hooks/use-minute-clock.js +0 -147
  41. package/dist/hooks/use-month-transition-direction.d.ts +0 -21
  42. package/dist/hooks/use-month-transition-direction.js +0 -110
  43. package/dist/lib/browser-navigation.d.ts +0 -21
  44. package/dist/lib/browser-navigation.js +0 -42
  45. package/dist/lib/in-app-browser.d.ts +0 -35
  46. package/dist/lib/in-app-browser.js +0 -80
  47. package/dist/lib/month-grid.d.ts +0 -42
  48. package/dist/lib/month-grid.js +0 -74
@@ -1,65 +0,0 @@
1
- /**
2
- * Month calendar toolbar: previous/next month navigation with an animated title, a "today"
3
- * shortcut with an optional clock label, an optional view toggle and slots for actions and filters.
4
- */
5
- import { type ComponentType, type ReactNode, type SVGProps } from "react";
6
- import type { MonthTransitionDirection } from "../hooks/use-month-transition-direction.js";
7
- export interface MonthCalendarHeaderLabels {
8
- previousMonth: string;
9
- nextMonth: string;
10
- today: string;
11
- viewMode: string;
12
- }
13
- /** One option of the view toggle, such as list or calendar. */
14
- export interface MonthCalendarViewOption<TView extends string> {
15
- value: TView;
16
- label: string;
17
- icon: ComponentType<SVGProps<SVGSVGElement>>;
18
- }
19
- /** Navigation target: a URL rendered as a link, or a callback rendered as a button. */
20
- export type MonthCalendarNavigation = {
21
- href: string;
22
- onSelect?: never;
23
- } | {
24
- href?: never;
25
- onSelect: () => void;
26
- };
27
- export interface MonthCalendarHeaderProps<TView extends string> {
28
- /** Visible `YYYY-MM` month. */
29
- month: string;
30
- previousMonth: MonthCalendarNavigation;
31
- nextMonth: MonthCalendarNavigation;
32
- today?: MonthCalendarNavigation;
33
- /** Title of the month. Defaults to the localized month and year, such as "Mayo de 2026". */
34
- title?: ReactNode;
35
- titleAs?: "h1" | "h2";
36
- /** Side the title slides in from after a month change (see `useMonthTransitionDirection`). */
37
- monthTransitionDirection?: MonthTransitionDirection;
38
- /** Clock label next to the "today" shortcut, or null before hydration. */
39
- timeLabel?: string | null;
40
- viewOptions?: readonly MonthCalendarViewOption<TView>[];
41
- view?: TView;
42
- onViewChange?: (view: TView) => void;
43
- /** Glide the active view marker; turn off while the view still follows the viewport. */
44
- shouldAnimateView?: boolean;
45
- actions?: ReactNode;
46
- /** Rendered as the last row, such as filter chips. */
47
- filters?: ReactNode;
48
- locale?: string;
49
- labels?: Partial<MonthCalendarHeaderLabels>;
50
- className?: string;
51
- }
52
- /**
53
- * Formats a month key as a capitalized month and year.
54
- * @param month - `YYYY-MM` month key.
55
- * @param locale - BCP 47 locale.
56
- * @returns For example "Mayo de 2026".
57
- */
58
- export declare function formatMonthTitle(month: string, locale?: string): string;
59
- /**
60
- * Renders the header of a month calendar. The title is keyed by month so it replays its entrance,
61
- * and the view marker glides between the toggle buttons.
62
- * @param props - Month, navigation targets, optional view toggle, actions and labels.
63
- * @returns The calendar header.
64
- */
65
- export declare function MonthCalendarHeader<TView extends string>({ month, previousMonth, nextMonth, today, title, titleAs: TitleElement, monthTransitionDirection, timeLabel, viewOptions, view, onViewChange, shouldAnimateView, actions, filters, locale, labels, className, }: MonthCalendarHeaderProps<TView>): import("react").JSX.Element;
@@ -1,337 +0,0 @@
1
- "use client";
2
- import { c as _c } from "react/compiler-runtime";
3
- /**
4
- * Month calendar toolbar: previous/next month navigation with an animated title, a "today"
5
- * shortcut with an optional clock label, an optional view toggle and slots for actions and filters.
6
- */
7
- import { useId } from "react";
8
- import { motion } from "motion/react";
9
- import { ChevronLeftIcon, ChevronRightIcon } from "lucide-react";
10
- import { usePrefersReducedMotion } from "../hooks/use-prefers-reduced-motion.js";
11
- import { cn } from "../lib/utils.js";
12
- import { SPRING_LAYOUT } from "../motion/tokens.js";
13
- import { Button } from "./button.js";
14
- import { Link } from "./link.js";
15
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
16
- const DEFAULT_LOCALE = "es-AR";
17
- const MONTH_KEY_FIRST_DAY_SUFFIX = "-01T12:00:00Z";
18
- /** Moves the view marker without animation (for example while the view follows the viewport). */
19
- const INSTANT_TRANSITION = { duration: 0 };
20
- const MONTH_CALENDAR_HEADER_DEFAULT_LABELS = {
21
- previousMonth: "Mes anterior",
22
- nextMonth: "Mes siguiente",
23
- today: "Hoy",
24
- viewMode: "Vista"
25
- };
26
- /**
27
- * Formats a month key as a capitalized month and year.
28
- * @param month - `YYYY-MM` month key.
29
- * @param locale - BCP 47 locale.
30
- * @returns For example "Mayo de 2026".
31
- */
32
- export function formatMonthTitle(month, locale = DEFAULT_LOCALE) {
33
- const monthTitle = new Intl.DateTimeFormat(locale, {
34
- month: "long",
35
- year: "numeric",
36
- timeZone: "UTC"
37
- }).format(new Date(month + MONTH_KEY_FIRST_DAY_SUFFIX));
38
- return monthTitle.charAt(0).toLocaleUpperCase(locale) + monthTitle.slice(1);
39
- }
40
- const PILL_LINK_CLASS_NAME = "inline-flex items-center justify-center rounded-full border border-border bg-background font-semibold text-foreground no-underline [-webkit-tap-highlight-color:transparent] transition-[border-color,background-color,scale] hover:border-[color-mix(in_oklab,var(--foreground)_24%,var(--border))] hover:bg-accent active:scale-[0.96] focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-ring";
41
- /**
42
- * Renders a navigation target as a router link or a button.
43
- * @param props - Target, class name, accessible name and content.
44
- * @returns The control.
45
- */
46
- function NavigationControl(t0) {
47
- const $ = _c(12);
48
- const { navigation, className, ariaLabel, children } = t0;
49
- if (navigation.href !== undefined) {
50
- let t1;
51
- if ($[0] !== ariaLabel || $[1] !== children || $[2] !== className || $[3] !== navigation.href) {
52
- t1 = /* @__PURE__ */ _jsx(Link, {
53
- "aria-label": ariaLabel,
54
- className,
55
- href: navigation.href,
56
- children
57
- });
58
- $[0] = ariaLabel;
59
- $[1] = children;
60
- $[2] = className;
61
- $[3] = navigation.href;
62
- $[4] = t1;
63
- } else {
64
- t1 = $[4];
65
- }
66
- return t1;
67
- }
68
- let t1;
69
- if ($[5] !== className) {
70
- t1 = cn("cursor-pointer", className);
71
- $[5] = className;
72
- $[6] = t1;
73
- } else {
74
- t1 = $[6];
75
- }
76
- let t2;
77
- if ($[7] !== ariaLabel || $[8] !== children || $[9] !== navigation.onSelect || $[10] !== t1) {
78
- t2 = /* @__PURE__ */ _jsx("button", {
79
- "aria-label": ariaLabel,
80
- className: t1,
81
- type: "button",
82
- onClick: navigation.onSelect,
83
- children
84
- });
85
- $[7] = ariaLabel;
86
- $[8] = children;
87
- $[9] = navigation.onSelect;
88
- $[10] = t1;
89
- $[11] = t2;
90
- } else {
91
- t2 = $[11];
92
- }
93
- return t2;
94
- }
95
- /**
96
- * Renders the header of a month calendar. The title is keyed by month so it replays its entrance,
97
- * and the view marker glides between the toggle buttons.
98
- * @param props - Month, navigation targets, optional view toggle, actions and labels.
99
- * @returns The calendar header.
100
- */
101
- export function MonthCalendarHeader(t0) {
102
- const $ = _c(47);
103
- const { month, previousMonth, nextMonth, today, title, titleAs: t1, monthTransitionDirection, timeLabel, viewOptions, view, onViewChange, shouldAnimateView: t2, actions, filters, locale: t3, labels, className } = t0;
104
- const TitleElement = t1 === undefined ? "h1" : t1;
105
- const shouldAnimateView = t2 === undefined ? true : t2;
106
- const locale = t3 === undefined ? DEFAULT_LOCALE : t3;
107
- let t4;
108
- if ($[0] !== labels) {
109
- t4 = {
110
- ...MONTH_CALENDAR_HEADER_DEFAULT_LABELS,
111
- ...labels
112
- };
113
- $[0] = labels;
114
- $[1] = t4;
115
- } else {
116
- t4 = $[1];
117
- }
118
- const resolvedLabels = t4;
119
- const shouldReduceMotion = usePrefersReducedMotion();
120
- const viewIndicatorLayoutId = useId();
121
- const hasToolbar = Boolean(today || timeLabel || viewOptions && viewOptions.length > 0 || actions);
122
- const viewIndicatorTransition = shouldAnimateView && !shouldReduceMotion ? SPRING_LAYOUT : INSTANT_TRANSITION;
123
- let t5;
124
- if ($[2] !== className) {
125
- t5 = cn("grid grid-cols-[minmax(0,1fr)] items-center gap-x-6 gap-y-3 border-b border-border/75 pb-4 lg:grid-cols-[auto_minmax(0,1fr)]", className);
126
- $[2] = className;
127
- $[3] = t5;
128
- } else {
129
- t5 = $[3];
130
- }
131
- const t6 = resolvedLabels.previousMonth;
132
- let t7;
133
- if ($[4] === Symbol.for("react.memo_cache_sentinel")) {
134
- t7 = cn(PILL_LINK_CLASS_NAME, "group/previous size-9 flex-none");
135
- $[4] = t7;
136
- } else {
137
- t7 = $[4];
138
- }
139
- let t8;
140
- if ($[5] === Symbol.for("react.memo_cache_sentinel")) {
141
- t8 = /* @__PURE__ */ _jsx(ChevronLeftIcon, {
142
- "aria-hidden": true,
143
- className: "size-[1.1rem] transition-transform [@media(hover:hover)_and_(pointer:fine)]:group-hover/previous:-translate-x-0.5"
144
- });
145
- $[5] = t8;
146
- } else {
147
- t8 = $[5];
148
- }
149
- let t9;
150
- if ($[6] !== previousMonth || $[7] !== resolvedLabels.previousMonth) {
151
- t9 = /* @__PURE__ */ _jsx(NavigationControl, {
152
- ariaLabel: t6,
153
- className: t7,
154
- navigation: previousMonth,
155
- children: t8
156
- });
157
- $[6] = previousMonth;
158
- $[7] = resolvedLabels.previousMonth;
159
- $[8] = t9;
160
- } else {
161
- t9 = $[8];
162
- }
163
- let t10;
164
- if ($[9] === Symbol.for("react.memo_cache_sentinel")) {
165
- t10 = cn("m-0 min-w-0 text-center font-display text-[clamp(1.6rem,4vw,2.25rem)] leading-[1.1] font-semibold text-foreground [overflow-wrap:anywhere] lg:px-1 lg:text-left", "data-[month-transition=next]:[--beez-month-enter-offset:10px] data-[month-transition=previous]:[--beez-month-enter-offset:-10px]", "data-[month-transition=next]:animate-[beez-month-title-enter_280ms_cubic-bezier(0.16,1,0.3,1)_both] data-[month-transition=previous]:animate-[beez-month-title-enter_280ms_cubic-bezier(0.16,1,0.3,1)_both]");
166
- $[9] = t10;
167
- } else {
168
- t10 = $[9];
169
- }
170
- let t11;
171
- if ($[10] !== locale || $[11] !== month || $[12] !== title) {
172
- t11 = title ?? formatMonthTitle(month, locale);
173
- $[10] = locale;
174
- $[11] = month;
175
- $[12] = title;
176
- $[13] = t11;
177
- } else {
178
- t11 = $[13];
179
- }
180
- let t12;
181
- if ($[14] !== TitleElement || $[15] !== month || $[16] !== monthTransitionDirection || $[17] !== t11) {
182
- t12 = /* @__PURE__ */ _jsx(TitleElement, {
183
- className: t10,
184
- "data-month-transition": monthTransitionDirection,
185
- children: t11
186
- }, month);
187
- $[14] = TitleElement;
188
- $[15] = month;
189
- $[16] = monthTransitionDirection;
190
- $[17] = t11;
191
- $[18] = t12;
192
- } else {
193
- t12 = $[18];
194
- }
195
- const t13 = resolvedLabels.nextMonth;
196
- let t14;
197
- if ($[19] === Symbol.for("react.memo_cache_sentinel")) {
198
- t14 = cn(PILL_LINK_CLASS_NAME, "group/next size-9 flex-none");
199
- $[19] = t14;
200
- } else {
201
- t14 = $[19];
202
- }
203
- let t15;
204
- if ($[20] === Symbol.for("react.memo_cache_sentinel")) {
205
- t15 = /* @__PURE__ */ _jsx(ChevronRightIcon, {
206
- "aria-hidden": true,
207
- className: "size-[1.1rem] transition-transform [@media(hover:hover)_and_(pointer:fine)]:group-hover/next:translate-x-0.5"
208
- });
209
- $[20] = t15;
210
- } else {
211
- t15 = $[20];
212
- }
213
- let t16;
214
- if ($[21] !== nextMonth || $[22] !== resolvedLabels.nextMonth) {
215
- t16 = /* @__PURE__ */ _jsx(NavigationControl, {
216
- ariaLabel: t13,
217
- className: t14,
218
- navigation: nextMonth,
219
- children: t15
220
- });
221
- $[21] = nextMonth;
222
- $[22] = resolvedLabels.nextMonth;
223
- $[23] = t16;
224
- } else {
225
- t16 = $[23];
226
- }
227
- let t17;
228
- if ($[24] !== t12 || $[25] !== t16 || $[26] !== t9) {
229
- t17 = /* @__PURE__ */ _jsxs("div", {
230
- className: "grid min-w-0 grid-cols-[auto_minmax(0,1fr)_auto] items-center gap-2 lg:grid-cols-[auto_auto_auto]",
231
- children: [
232
- t9,
233
- t12,
234
- t16
235
- ]
236
- });
237
- $[24] = t12;
238
- $[25] = t16;
239
- $[26] = t9;
240
- $[27] = t17;
241
- } else {
242
- t17 = $[27];
243
- }
244
- let t18;
245
- if ($[28] !== actions || $[29] !== hasToolbar || $[30] !== onViewChange || $[31] !== resolvedLabels.today || $[32] !== resolvedLabels.viewMode || $[33] !== timeLabel || $[34] !== today || $[35] !== view || $[36] !== viewIndicatorLayoutId || $[37] !== viewIndicatorTransition || $[38] !== viewOptions) {
246
- t18 = hasToolbar ? /* @__PURE__ */ _jsxs("div", {
247
- className: "flex min-w-0 flex-wrap items-center justify-between gap-3 lg:justify-end",
248
- children: [today || timeLabel ? /* @__PURE__ */ _jsxs("div", {
249
- className: "flex min-w-0 flex-wrap items-center gap-[0.6rem]",
250
- children: [today ? /* @__PURE__ */ _jsx(NavigationControl, {
251
- className: cn(PILL_LINK_CLASS_NAME, "min-h-9 px-[0.9rem] text-[0.9rem]"),
252
- navigation: today,
253
- children: resolvedLabels.today
254
- }) : null, timeLabel ? /* @__PURE__ */ _jsx("p", {
255
- className: "m-0 text-[0.85rem] text-muted-foreground tabular-nums",
256
- children: timeLabel
257
- }) : null]
258
- }) : null, /* @__PURE__ */ _jsxs("div", {
259
- className: "flex min-w-0 flex-wrap items-center gap-[0.6rem]",
260
- children: [viewOptions && viewOptions.length > 0 ? /* @__PURE__ */ _jsx("div", {
261
- "aria-label": resolvedLabels.viewMode,
262
- className: "isolate inline-flex gap-1 rounded-xl border border-border p-[0.2rem]",
263
- role: "group",
264
- children: viewOptions.map((option) => {
265
- const isActive = view === option.value;
266
- const ViewIcon = option.icon;
267
- return /* @__PURE__ */ _jsxs("span", {
268
- className: "relative inline-flex",
269
- children: [isActive ? /* @__PURE__ */ _jsx(motion.span, {
270
- "aria-hidden": true,
271
- className: "pointer-events-none absolute inset-0 -z-10 rounded-(--radius) bg-secondary",
272
- layoutId: viewIndicatorLayoutId,
273
- transition: viewIndicatorTransition
274
- }) : null, /* @__PURE__ */ _jsxs(Button, {
275
- "aria-pressed": isActive,
276
- className: cn(isActive && "bg-transparent text-secondary-foreground hover:bg-transparent"),
277
- size: "icon",
278
- type: "button",
279
- variant: "ghost",
280
- onClick: () => onViewChange?.(option.value),
281
- children: [/* @__PURE__ */ _jsx(ViewIcon, { "aria-hidden": true }), /* @__PURE__ */ _jsx("span", {
282
- className: "sr-only",
283
- children: option.label
284
- })]
285
- })]
286
- }, option.value);
287
- })
288
- }) : null, actions]
289
- })]
290
- }) : null;
291
- $[28] = actions;
292
- $[29] = hasToolbar;
293
- $[30] = onViewChange;
294
- $[31] = resolvedLabels.today;
295
- $[32] = resolvedLabels.viewMode;
296
- $[33] = timeLabel;
297
- $[34] = today;
298
- $[35] = view;
299
- $[36] = viewIndicatorLayoutId;
300
- $[37] = viewIndicatorTransition;
301
- $[38] = viewOptions;
302
- $[39] = t18;
303
- } else {
304
- t18 = $[39];
305
- }
306
- let t19;
307
- if ($[40] !== filters) {
308
- t19 = filters ? /* @__PURE__ */ _jsx("div", {
309
- className: "col-span-full min-w-0",
310
- children: filters
311
- }) : null;
312
- $[40] = filters;
313
- $[41] = t19;
314
- } else {
315
- t19 = $[41];
316
- }
317
- let t20;
318
- if ($[42] !== t17 || $[43] !== t18 || $[44] !== t19 || $[45] !== t5) {
319
- t20 = /* @__PURE__ */ _jsxs("header", {
320
- "data-slot": "month-calendar-header",
321
- className: t5,
322
- children: [
323
- t17,
324
- t18,
325
- t19
326
- ]
327
- });
328
- $[42] = t17;
329
- $[43] = t18;
330
- $[44] = t19;
331
- $[45] = t5;
332
- $[46] = t20;
333
- } else {
334
- t20 = $[46];
335
- }
336
- return t20;
337
- }
@@ -1,59 +0,0 @@
1
- /**
2
- * Month grid of dated items, such as events or deadlines. Wide screens show one pill per item;
3
- * phones show one dot per item and list the selected day under the grid.
4
- */
5
- import { type ReactNode } from "react";
6
- import { type CalendarWeekStart } from "../lib/month-grid.js";
7
- /** Presentation of one dated item, already resolved by the application. */
8
- export interface MonthGridItem {
9
- id: string;
10
- /** `YYYY-MM-DD` day the item belongs to, in the zone the application displays. */
11
- dateKey: string;
12
- title: string;
13
- /** Short start time, such as "18:00". */
14
- timeLabel?: string;
15
- /** Past items are muted. */
16
- isPast?: boolean;
17
- /** Cancelled items are struck through, muted and labelled. */
18
- isCancelled?: boolean;
19
- /** CSS color of the dot and the pill accent. Defaults to the primary color. */
20
- accentColor?: string;
21
- /** CSS color of the pill surface. Defaults to the background. */
22
- surfaceColor?: string;
23
- /** Leading content of the pill, such as a type badge or icon. */
24
- leading?: ReactNode;
25
- }
26
- export interface MonthGridLabels {
27
- table: string;
28
- today: string;
29
- cancelled: string;
30
- /** Accessible name of the phone summary of the selected day. */
31
- dayItems: string;
32
- /** Accessible name of a phone day button. */
33
- dayButton: (dayLabel: string, itemCount: number) => string;
34
- /** Seven weekday headers, Monday first; rotated when the week starts on Sunday. */
35
- weekDays: readonly string[];
36
- }
37
- export interface MonthGridProps<TItem extends MonthGridItem> {
38
- /** Visible `YYYY-MM` month. */
39
- month: string;
40
- items: readonly TItem[];
41
- onSelectItem: (item: TItem) => void;
42
- /** `YYYY-MM-DD` key of today, or null before hydration. */
43
- todayKey?: string | null;
44
- weekStartsOn?: CalendarWeekStart;
45
- /** Day whose items are listed under the grid on phones. */
46
- activeDayKey?: string | null;
47
- onSelectDay?: (dayKey: string) => void;
48
- /** Renders the phone summary of the selected day. Defaults to a list of item buttons. */
49
- renderDaySummary?: (dayKey: string, dayItems: readonly TItem[]) => ReactNode;
50
- locale?: string;
51
- labels?: Partial<MonthGridLabels>;
52
- className?: string;
53
- }
54
- /**
55
- * Renders the month as an accessible table with today marked (`aria-current="date"`).
56
- * @param props - Month, items, selection callbacks and optional labels.
57
- * @returns The month grid and its phone day summary.
58
- */
59
- export declare function MonthGrid<TItem extends MonthGridItem>({ month, items, onSelectItem, todayKey, weekStartsOn, activeDayKey, onSelectDay, renderDaySummary, locale, labels, className, }: MonthGridProps<TItem>): import("react").JSX.Element;