@bearmenu/ui 0.8.6 → 0.8.7
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/components/alert.d.ts +2 -2
- package/dist/components/badge.d.ts +1 -1
- package/dist/components/button.d.ts +1 -1
- package/dist/components/card.d.ts +2 -2
- package/dist/components/command.d.ts +15 -15
- package/dist/components/date-input.d.ts +1 -1
- package/dist/components/event-card.js +5 -2
- package/dist/components/event-compact-row.d.ts +2 -1
- package/dist/components/event-compact-row.js +3 -2
- package/dist/components/event-types.d.ts +5 -1
- package/dist/components/item.d.ts +2 -2
- package/dist/components/spinner.d.ts +2 -2
- package/dist/components/tag.d.ts +2 -2
- package/dist/components/text.d.ts +3 -3
- package/package.json +1 -1
- package/src/components/event-card.test.tsx +11 -0
- package/src/components/event-card.tsx +12 -4
- package/src/components/event-compact-row.test.tsx +51 -0
- package/src/components/event-compact-row.tsx +5 -3
- package/src/components/event-types.ts +5 -1
|
@@ -3,10 +3,10 @@ import * as React from 'react';
|
|
|
3
3
|
import { VariantProps } from 'class-variance-authority';
|
|
4
4
|
|
|
5
5
|
declare const alertVariants: (props?: ({
|
|
6
|
-
variant?: "default" | "destructive" | "
|
|
6
|
+
variant?: "default" | "destructive" | "success" | "warning" | null | undefined;
|
|
7
7
|
} & class_variance_authority_types.ClassProp) | undefined) => string;
|
|
8
8
|
declare const Alert: React.ForwardRefExoticComponent<React.HTMLAttributes<HTMLDivElement> & VariantProps<(props?: ({
|
|
9
|
-
variant?: "default" | "destructive" | "
|
|
9
|
+
variant?: "default" | "destructive" | "success" | "warning" | null | undefined;
|
|
10
10
|
} & class_variance_authority_types.ClassProp) | undefined) => string> & React.RefAttributes<HTMLDivElement>>;
|
|
11
11
|
declare const AlertTitle: React.ForwardRefExoticComponent<React.HTMLAttributes<HTMLHeadingElement> & React.RefAttributes<HTMLParagraphElement>>;
|
|
12
12
|
declare const AlertDescription: React.ForwardRefExoticComponent<React.HTMLAttributes<HTMLParagraphElement> & React.RefAttributes<HTMLParagraphElement>>;
|
|
@@ -4,7 +4,7 @@ import * as React from 'react';
|
|
|
4
4
|
import { VariantProps } from 'class-variance-authority';
|
|
5
5
|
|
|
6
6
|
declare const badgeVariants: (props?: ({
|
|
7
|
-
variant?: "default" | "destructive" | "
|
|
7
|
+
variant?: "default" | "destructive" | "outline" | "secondary" | "glass" | "overlay" | "brown" | "success" | "warning" | null | undefined;
|
|
8
8
|
live?: boolean | null | undefined;
|
|
9
9
|
} & class_variance_authority_types.ClassProp) | undefined) => string;
|
|
10
10
|
interface BadgeProps extends React.HTMLAttributes<HTMLDivElement>, VariantProps<typeof badgeVariants> {
|
|
@@ -3,7 +3,7 @@ import * as React from 'react';
|
|
|
3
3
|
import { VariantProps } from 'class-variance-authority';
|
|
4
4
|
|
|
5
5
|
declare const buttonVariants: (props?: ({
|
|
6
|
-
variant?: "
|
|
6
|
+
variant?: "link" | "default" | "destructive" | "outline" | "secondary" | "ghost" | "glass" | "overlay" | "brown" | "antagonist" | null | undefined;
|
|
7
7
|
size?: "default" | "xs" | "sm" | "lg" | "icon" | "icon-xs" | "icon-sm" | "icon-lg" | null | undefined;
|
|
8
8
|
fullWidth?: boolean | null | undefined;
|
|
9
9
|
} & class_variance_authority_types.ClassProp) | undefined) => string;
|
|
@@ -3,12 +3,12 @@ import * as React from 'react';
|
|
|
3
3
|
import { VariantProps } from 'class-variance-authority';
|
|
4
4
|
|
|
5
5
|
declare const cardVariants: (props?: ({
|
|
6
|
-
variant?: "
|
|
6
|
+
variant?: "outline" | "glass" | "muted" | "surface" | "elevated" | "elevatedPanel" | null | undefined;
|
|
7
7
|
size?: "default" | "sm" | "lg" | null | undefined;
|
|
8
8
|
interactive?: boolean | null | undefined;
|
|
9
9
|
} & class_variance_authority_types.ClassProp) | undefined) => string;
|
|
10
10
|
declare const Card: React.ForwardRefExoticComponent<React.HTMLAttributes<HTMLDivElement> & VariantProps<(props?: ({
|
|
11
|
-
variant?: "
|
|
11
|
+
variant?: "outline" | "glass" | "muted" | "surface" | "elevated" | "elevatedPanel" | null | undefined;
|
|
12
12
|
size?: "default" | "sm" | "lg" | null | undefined;
|
|
13
13
|
interactive?: boolean | null | undefined;
|
|
14
14
|
} & class_variance_authority_types.ClassProp) | undefined) => string> & React.RefAttributes<HTMLDivElement>>;
|
|
@@ -4,11 +4,11 @@ import { DialogProps } from '@radix-ui/react-dialog';
|
|
|
4
4
|
|
|
5
5
|
declare const Command: React.ForwardRefExoticComponent<Omit<{
|
|
6
6
|
children?: React.ReactNode;
|
|
7
|
-
} & Pick<Pick<React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement>, keyof React.HTMLAttributes<HTMLDivElement
|
|
7
|
+
} & Pick<Pick<React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement>, "key" | keyof React.HTMLAttributes<HTMLDivElement>> & {
|
|
8
8
|
ref?: React.Ref<HTMLDivElement>;
|
|
9
9
|
} & {
|
|
10
10
|
asChild?: boolean;
|
|
11
|
-
}, keyof React.HTMLAttributes<HTMLDivElement> | "asChild"
|
|
11
|
+
}, "key" | keyof React.HTMLAttributes<HTMLDivElement> | "asChild"> & {
|
|
12
12
|
label?: string;
|
|
13
13
|
shouldFilter?: boolean;
|
|
14
14
|
filter?: (value: string, search: string, keywords?: string[]) => number;
|
|
@@ -28,61 +28,61 @@ declare const CommandInput: React.ForwardRefExoticComponent<Omit<Omit<Pick<Pick<
|
|
|
28
28
|
ref?: React.Ref<HTMLInputElement>;
|
|
29
29
|
} & {
|
|
30
30
|
asChild?: boolean;
|
|
31
|
-
}, "
|
|
31
|
+
}, "key" | "asChild" | keyof React.InputHTMLAttributes<HTMLInputElement>>, "onChange" | "type" | "value"> & {
|
|
32
32
|
value?: string;
|
|
33
33
|
onValueChange?: (search: string) => void;
|
|
34
34
|
} & React.RefAttributes<HTMLInputElement>, "ref"> & React.RefAttributes<HTMLInputElement>>;
|
|
35
35
|
declare const CommandList: React.ForwardRefExoticComponent<Omit<{
|
|
36
36
|
children?: React.ReactNode;
|
|
37
|
-
} & Pick<Pick<React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement>, keyof React.HTMLAttributes<HTMLDivElement
|
|
37
|
+
} & Pick<Pick<React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement>, "key" | keyof React.HTMLAttributes<HTMLDivElement>> & {
|
|
38
38
|
ref?: React.Ref<HTMLDivElement>;
|
|
39
39
|
} & {
|
|
40
40
|
asChild?: boolean;
|
|
41
|
-
}, keyof React.HTMLAttributes<HTMLDivElement> | "asChild"
|
|
41
|
+
}, "key" | keyof React.HTMLAttributes<HTMLDivElement> | "asChild"> & {
|
|
42
42
|
label?: string;
|
|
43
43
|
} & React.RefAttributes<HTMLDivElement>, "ref"> & React.RefAttributes<HTMLDivElement>>;
|
|
44
44
|
declare const CommandEmpty: React.ForwardRefExoticComponent<Omit<{
|
|
45
45
|
children?: React.ReactNode;
|
|
46
|
-
} & Pick<Pick<React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement>, keyof React.HTMLAttributes<HTMLDivElement
|
|
46
|
+
} & Pick<Pick<React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement>, "key" | keyof React.HTMLAttributes<HTMLDivElement>> & {
|
|
47
47
|
ref?: React.Ref<HTMLDivElement>;
|
|
48
48
|
} & {
|
|
49
49
|
asChild?: boolean;
|
|
50
|
-
}, keyof React.HTMLAttributes<HTMLDivElement> | "asChild"
|
|
50
|
+
}, "key" | keyof React.HTMLAttributes<HTMLDivElement> | "asChild"> & React.RefAttributes<HTMLDivElement>, "ref"> & React.RefAttributes<HTMLDivElement>>;
|
|
51
51
|
declare const CommandLoading: React.ForwardRefExoticComponent<Omit<{
|
|
52
52
|
children?: React.ReactNode;
|
|
53
|
-
} & Pick<Pick<React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement>, keyof React.HTMLAttributes<HTMLDivElement
|
|
53
|
+
} & Pick<Pick<React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement>, "key" | keyof React.HTMLAttributes<HTMLDivElement>> & {
|
|
54
54
|
ref?: React.Ref<HTMLDivElement>;
|
|
55
55
|
} & {
|
|
56
56
|
asChild?: boolean;
|
|
57
|
-
}, keyof React.HTMLAttributes<HTMLDivElement> | "asChild"
|
|
57
|
+
}, "key" | keyof React.HTMLAttributes<HTMLDivElement> | "asChild"> & {
|
|
58
58
|
progress?: number;
|
|
59
59
|
label?: string;
|
|
60
60
|
} & React.RefAttributes<HTMLDivElement>, "ref"> & React.RefAttributes<HTMLDivElement>>;
|
|
61
61
|
declare const CommandGroup: React.ForwardRefExoticComponent<Omit<{
|
|
62
62
|
children?: React.ReactNode;
|
|
63
|
-
} & Omit<Pick<Pick<React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement>, keyof React.HTMLAttributes<HTMLDivElement
|
|
63
|
+
} & Omit<Pick<Pick<React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement>, "key" | keyof React.HTMLAttributes<HTMLDivElement>> & {
|
|
64
64
|
ref?: React.Ref<HTMLDivElement>;
|
|
65
65
|
} & {
|
|
66
66
|
asChild?: boolean;
|
|
67
|
-
}, keyof React.HTMLAttributes<HTMLDivElement> | "asChild"
|
|
67
|
+
}, "key" | keyof React.HTMLAttributes<HTMLDivElement> | "asChild">, "heading" | "value"> & {
|
|
68
68
|
heading?: React.ReactNode;
|
|
69
69
|
value?: string;
|
|
70
70
|
forceMount?: boolean;
|
|
71
71
|
} & React.RefAttributes<HTMLDivElement>, "ref"> & React.RefAttributes<HTMLDivElement>>;
|
|
72
|
-
declare const CommandSeparator: React.ForwardRefExoticComponent<Omit<Pick<Pick<React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement>, keyof React.HTMLAttributes<HTMLDivElement
|
|
72
|
+
declare const CommandSeparator: React.ForwardRefExoticComponent<Omit<Pick<Pick<React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement>, "key" | keyof React.HTMLAttributes<HTMLDivElement>> & {
|
|
73
73
|
ref?: React.Ref<HTMLDivElement>;
|
|
74
74
|
} & {
|
|
75
75
|
asChild?: boolean;
|
|
76
|
-
}, keyof React.HTMLAttributes<HTMLDivElement> | "asChild"
|
|
76
|
+
}, "key" | keyof React.HTMLAttributes<HTMLDivElement> | "asChild"> & {
|
|
77
77
|
alwaysRender?: boolean;
|
|
78
78
|
} & React.RefAttributes<HTMLDivElement>, "ref"> & React.RefAttributes<HTMLDivElement>>;
|
|
79
79
|
declare const CommandItem: React.ForwardRefExoticComponent<Omit<{
|
|
80
80
|
children?: React.ReactNode;
|
|
81
|
-
} & Omit<Pick<Pick<React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement>, keyof React.HTMLAttributes<HTMLDivElement
|
|
81
|
+
} & Omit<Pick<Pick<React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement>, "key" | keyof React.HTMLAttributes<HTMLDivElement>> & {
|
|
82
82
|
ref?: React.Ref<HTMLDivElement>;
|
|
83
83
|
} & {
|
|
84
84
|
asChild?: boolean;
|
|
85
|
-
}, keyof React.HTMLAttributes<HTMLDivElement> | "asChild"
|
|
85
|
+
}, "key" | keyof React.HTMLAttributes<HTMLDivElement> | "asChild">, "onSelect" | "disabled" | "value"> & {
|
|
86
86
|
disabled?: boolean;
|
|
87
87
|
onSelect?: (value: string) => void;
|
|
88
88
|
value?: string;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
2
|
|
|
3
|
-
declare const DateInput: React.ForwardRefExoticComponent<Omit<React.InputHTMLAttributes<HTMLInputElement>, "
|
|
3
|
+
declare const DateInput: React.ForwardRefExoticComponent<Omit<React.InputHTMLAttributes<HTMLInputElement>, "type" | "size"> & {
|
|
4
4
|
/** Native input type. Defaults to "date". */
|
|
5
5
|
type?: "date" | "datetime-local" | "time" | "month" | "week";
|
|
6
6
|
size?: "sm" | "default" | "lg";
|
|
@@ -36,6 +36,7 @@ var EventCard = memo(function EventCard2({
|
|
|
36
36
|
}) {
|
|
37
37
|
var _a;
|
|
38
38
|
const [imgError, setImgError] = useState(false);
|
|
39
|
+
const time = hideWhen ? "" : formatters.time(event.starts_at);
|
|
39
40
|
const fee = resolveEventEntryFee(event);
|
|
40
41
|
const showPoster = !!event.poster_url && !imgError;
|
|
41
42
|
const venue = (_a = event.place_name) != null ? _a : event.location;
|
|
@@ -90,8 +91,10 @@ var EventCard = memo(function EventCard2({
|
|
|
90
91
|
] }),
|
|
91
92
|
!hideWhen && /* @__PURE__ */ jsxs("div", { className: "mt-[3px] flex items-center gap-1.5 text-xs text-muted-foreground", children: [
|
|
92
93
|
/* @__PURE__ */ jsx("span", { children: dayLabel != null ? dayLabel : formatters.day(event.starts_at) }),
|
|
93
|
-
/* @__PURE__ */
|
|
94
|
-
|
|
94
|
+
time && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
95
|
+
/* @__PURE__ */ jsx("span", { className: "text-border", "aria-hidden": true, children: "\xB7" }),
|
|
96
|
+
/* @__PURE__ */ jsx("span", { children: time })
|
|
97
|
+
] }),
|
|
95
98
|
showPrice && fee.kind === "paid" && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
96
99
|
/* @__PURE__ */ jsx("span", { className: "text-border", "aria-hidden": true, children: "\xB7" }),
|
|
97
100
|
/* @__PURE__ */ jsx("span", { children: formatters.price(fee.amountRon) })
|
|
@@ -32,7 +32,8 @@ type EventCompactRowProps = {
|
|
|
32
32
|
event: EventPreview;
|
|
33
33
|
labels: EventCardLabels;
|
|
34
34
|
formatters: EventFormatters;
|
|
35
|
-
/** Drops the leading time from the sub line.
|
|
35
|
+
/** Drops the leading time from the sub line. An empty `formatters.time`
|
|
36
|
+
* result (hour unknown) drops it the same way, without the prop. */
|
|
36
37
|
hideTime?: boolean;
|
|
37
38
|
/**
|
|
38
39
|
* Replaces the default "time · venue" sub-line entirely. For surfaces where
|
|
@@ -33,6 +33,7 @@ var EventCompactRow = memo(function EventCompactRow2({
|
|
|
33
33
|
const fee = resolveEventEntryFee(event);
|
|
34
34
|
const showPoster = !!event.poster_url && !imgError;
|
|
35
35
|
const venue = (_a = event.place_name) != null ? _a : event.location;
|
|
36
|
+
const time = formatters.time(event.starts_at);
|
|
36
37
|
const body = /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
37
38
|
/* @__PURE__ */ jsx("div", { className: "relative aspect-[4/5] w-16 shrink-0 overflow-hidden rounded-[9px] bg-muted", children: showPoster ? (
|
|
38
39
|
// eslint-disable-next-line @next/next/no-img-element
|
|
@@ -68,8 +69,8 @@ var EventCompactRow = memo(function EventCompactRow2({
|
|
|
68
69
|
}
|
|
69
70
|
),
|
|
70
71
|
/* @__PURE__ */ jsx("div", { className: "truncate text-[11.5px] text-muted-foreground", children: subtitle ? subtitle : /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
71
|
-
!hideTime && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
72
|
-
/* @__PURE__ */ jsx("span", { className: "font-mono tabular-nums", children:
|
|
72
|
+
!hideTime && time && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
73
|
+
/* @__PURE__ */ jsx("span", { className: "font-mono tabular-nums", children: time }),
|
|
73
74
|
/* @__PURE__ */ jsx("span", { "aria-hidden": true, children: " \xB7 " })
|
|
74
75
|
] }),
|
|
75
76
|
venue
|
|
@@ -71,7 +71,11 @@ declare function resolveEventEntryFee(event: EventPreview): EventEntryFee;
|
|
|
71
71
|
* locale and no currency of its own.
|
|
72
72
|
*/
|
|
73
73
|
type EventFormatters = {
|
|
74
|
-
/**
|
|
74
|
+
/**
|
|
75
|
+
* e.g. `"20:00"`. Return `""` when the event's hour is not known: the card
|
|
76
|
+
* and the compact row then print the day (or the venue) ALONE, with no
|
|
77
|
+
* separator — never a placeholder word and never "00:00".
|
|
78
|
+
*/
|
|
75
79
|
time: (isoDateTime: string) => string;
|
|
76
80
|
/** e.g. `"Sat, Sep 5"` — used when a card appears outside its own day section. */
|
|
77
81
|
day: (isoDateTime: string) => string;
|
|
@@ -3,12 +3,12 @@ import * as React from 'react';
|
|
|
3
3
|
import { VariantProps } from 'class-variance-authority';
|
|
4
4
|
|
|
5
5
|
declare const itemVariants: (props?: ({
|
|
6
|
-
variant?: "default" | "
|
|
6
|
+
variant?: "default" | "outline" | "muted" | null | undefined;
|
|
7
7
|
size?: "default" | "sm" | "lg" | null | undefined;
|
|
8
8
|
interactive?: boolean | null | undefined;
|
|
9
9
|
} & class_variance_authority_types.ClassProp) | undefined) => string;
|
|
10
10
|
declare const Item: React.ForwardRefExoticComponent<React.HTMLAttributes<HTMLDivElement> & VariantProps<(props?: ({
|
|
11
|
-
variant?: "default" | "
|
|
11
|
+
variant?: "default" | "outline" | "muted" | null | undefined;
|
|
12
12
|
size?: "default" | "sm" | "lg" | null | undefined;
|
|
13
13
|
interactive?: boolean | null | undefined;
|
|
14
14
|
} & class_variance_authority_types.ClassProp) | undefined) => string> & {
|
|
@@ -4,11 +4,11 @@ import { VariantProps } from 'class-variance-authority';
|
|
|
4
4
|
|
|
5
5
|
declare const spinnerVariants: (props?: ({
|
|
6
6
|
size?: "default" | "xs" | "sm" | "lg" | "xl" | null | undefined;
|
|
7
|
-
tone?: "
|
|
7
|
+
tone?: "inherit" | "default" | "destructive" | "primary" | null | undefined;
|
|
8
8
|
} & class_variance_authority_types.ClassProp) | undefined) => string;
|
|
9
9
|
declare const Spinner: React.ForwardRefExoticComponent<React.HTMLAttributes<HTMLSpanElement> & VariantProps<(props?: ({
|
|
10
10
|
size?: "default" | "xs" | "sm" | "lg" | "xl" | null | undefined;
|
|
11
|
-
tone?: "
|
|
11
|
+
tone?: "inherit" | "default" | "destructive" | "primary" | null | undefined;
|
|
12
12
|
} & class_variance_authority_types.ClassProp) | undefined) => string> & {
|
|
13
13
|
/** Visually-hidden label for screen readers. Defaults to "Loading". */
|
|
14
14
|
label?: string;
|
package/dist/components/tag.d.ts
CHANGED
|
@@ -3,11 +3,11 @@ import * as React from 'react';
|
|
|
3
3
|
import { VariantProps } from 'class-variance-authority';
|
|
4
4
|
|
|
5
5
|
declare const tagVariants: (props?: ({
|
|
6
|
-
variant?: "default" | "destructive" | "
|
|
6
|
+
variant?: "default" | "destructive" | "outline" | "success" | "warning" | "primary" | "quiet" | null | undefined;
|
|
7
7
|
size?: "default" | "sm" | "lg" | null | undefined;
|
|
8
8
|
} & class_variance_authority_types.ClassProp) | undefined) => string;
|
|
9
9
|
declare const Tag: React.ForwardRefExoticComponent<React.HTMLAttributes<HTMLSpanElement> & VariantProps<(props?: ({
|
|
10
|
-
variant?: "default" | "destructive" | "
|
|
10
|
+
variant?: "default" | "destructive" | "outline" | "success" | "warning" | "primary" | "quiet" | null | undefined;
|
|
11
11
|
size?: "default" | "sm" | "lg" | null | undefined;
|
|
12
12
|
} & class_variance_authority_types.ClassProp) | undefined) => string> & {
|
|
13
13
|
onRemove?: () => void;
|
|
@@ -22,9 +22,9 @@ import { VariantProps } from 'class-variance-authority';
|
|
|
22
22
|
* Weights are 400 / 600 / 700. 500 is not in the system.
|
|
23
23
|
*/
|
|
24
24
|
declare const textVariants: (props?: ({
|
|
25
|
-
variant?: "
|
|
26
|
-
color?: "
|
|
27
|
-
weight?: "bold" | "
|
|
25
|
+
variant?: "h2" | "h3" | "label" | "body" | "caption" | "h1" | "h4" | "small" | "display" | "body-lg" | "body-sm" | "overline" | null | undefined;
|
|
26
|
+
color?: "inherit" | "default" | "destructive" | "muted" | "primary" | "primary-foreground" | null | undefined;
|
|
27
|
+
weight?: "bold" | "medium" | "normal" | "semibold" | null | undefined;
|
|
28
28
|
leading?: "none" | "normal" | "tight" | "snug" | "relaxed" | "loose" | null | undefined;
|
|
29
29
|
tracking?: "normal" | "tight" | "wide" | "wider" | null | undefined;
|
|
30
30
|
wrap?: "balance" | "pretty" | "nowrap" | null | undefined;
|
package/package.json
CHANGED
|
@@ -108,6 +108,17 @@ describe("EventCard", () => {
|
|
|
108
108
|
expect(screen.queryByText("Sat, Sep 5")).not.toBeInTheDocument();
|
|
109
109
|
});
|
|
110
110
|
|
|
111
|
+
it("prints the day alone, with no separator, when the time formatter returns an empty string", () => {
|
|
112
|
+
// "" is the formatter's way of saying the hour is unknown; the card must
|
|
113
|
+
// not print a dangling "·" or invent a placeholder for it.
|
|
114
|
+
const { container } = renderCard({
|
|
115
|
+
formatters: { ...formatters, time: () => "" },
|
|
116
|
+
});
|
|
117
|
+
expect(screen.getByText("Sat, Sep 5")).toBeInTheDocument();
|
|
118
|
+
expect(container.textContent).not.toContain("·");
|
|
119
|
+
expect(container.textContent).not.toContain("20:00");
|
|
120
|
+
});
|
|
121
|
+
|
|
111
122
|
it("hides the whole meta line when hideWhen is set", () => {
|
|
112
123
|
renderCard({ hideWhen: true });
|
|
113
124
|
expect(screen.queryByText("20:00")).not.toBeInTheDocument();
|
|
@@ -118,6 +118,7 @@ export const EventCard = memo(function EventCard({
|
|
|
118
118
|
fallback = <EventPosterFallback />,
|
|
119
119
|
}: EventCardProps) {
|
|
120
120
|
const [imgError, setImgError] = useState(false);
|
|
121
|
+
const time = hideWhen ? "" : formatters.time(event.starts_at);
|
|
121
122
|
|
|
122
123
|
const fee = resolveEventEntryFee(event);
|
|
123
124
|
const showPoster = !!event.poster_url && !imgError;
|
|
@@ -193,10 +194,17 @@ export const EventCard = memo(function EventCard({
|
|
|
193
194
|
{!hideWhen && (
|
|
194
195
|
<div className="mt-[3px] flex items-center gap-1.5 text-xs text-muted-foreground">
|
|
195
196
|
<span>{dayLabel ?? formatters.day(event.starts_at)}</span>
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
197
|
+
{/* An empty time is "hour unknown" (see `EventFormatters.time`): the
|
|
198
|
+
day stands alone, no dangling separator. Consumers used to have
|
|
199
|
+
to `hideWhen` these cards and lose the day with the time. */}
|
|
200
|
+
{time && (
|
|
201
|
+
<>
|
|
202
|
+
<span className="text-border" aria-hidden>
|
|
203
|
+
·
|
|
204
|
+
</span>
|
|
205
|
+
<span>{time}</span>
|
|
206
|
+
</>
|
|
207
|
+
)}
|
|
200
208
|
{showPrice && fee.kind === "paid" && (
|
|
201
209
|
<>
|
|
202
210
|
<span className="text-border" aria-hidden>
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { describe, it, expect } from "vitest";
|
|
2
|
+
import { render, screen } from "@testing-library/react";
|
|
3
|
+
import { EventCompactRow } from "./event-compact-row";
|
|
4
|
+
import type { EventCardLabels, EventFormatters, EventPreview } from "./event-types";
|
|
5
|
+
|
|
6
|
+
const labels: EventCardLabels = { free: "Free", liveNow: "Live now" };
|
|
7
|
+
|
|
8
|
+
const formatters: EventFormatters = {
|
|
9
|
+
time: () => "20:00",
|
|
10
|
+
day: () => "Sat, Sep 5",
|
|
11
|
+
price: (amount) => `${amount} RON`,
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
const event: EventPreview = {
|
|
15
|
+
id: "e1",
|
|
16
|
+
title: "Psihotrop Live",
|
|
17
|
+
location: "Atelier Cafe",
|
|
18
|
+
starts_at: "2026-09-05T20:00:00Z",
|
|
19
|
+
place_name: "Atelier Cafe",
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
describe("EventCompactRow sub line", () => {
|
|
23
|
+
it("leads with the time and the venue by default", () => {
|
|
24
|
+
const { container } = render(
|
|
25
|
+
<EventCompactRow event={event} labels={labels} formatters={formatters} />
|
|
26
|
+
);
|
|
27
|
+
expect(screen.getByText("20:00")).toBeInTheDocument();
|
|
28
|
+
expect(container.textContent).toContain("·");
|
|
29
|
+
expect(screen.getByText("Atelier Cafe")).toBeInTheDocument();
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
it("prints the venue alone when the time formatter returns an empty string (hour unknown)", () => {
|
|
33
|
+
const { container } = render(
|
|
34
|
+
<EventCompactRow
|
|
35
|
+
event={event}
|
|
36
|
+
labels={labels}
|
|
37
|
+
formatters={{ ...formatters, time: () => "" }}
|
|
38
|
+
/>
|
|
39
|
+
);
|
|
40
|
+
expect(container.textContent).not.toContain("·");
|
|
41
|
+
expect(screen.getByText("Atelier Cafe")).toBeInTheDocument();
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
it("still honours hideTime for callers that know the hour is stated elsewhere", () => {
|
|
45
|
+
const { container } = render(
|
|
46
|
+
<EventCompactRow event={event} labels={labels} formatters={formatters} hideTime />
|
|
47
|
+
);
|
|
48
|
+
expect(container.textContent).not.toContain("20:00");
|
|
49
|
+
expect(container.textContent).not.toContain("·");
|
|
50
|
+
});
|
|
51
|
+
});
|
|
@@ -49,7 +49,8 @@ export type EventCompactRowProps = {
|
|
|
49
49
|
event: EventPreview;
|
|
50
50
|
labels: EventCardLabels;
|
|
51
51
|
formatters: EventFormatters;
|
|
52
|
-
/** Drops the leading time from the sub line.
|
|
52
|
+
/** Drops the leading time from the sub line. An empty `formatters.time`
|
|
53
|
+
* result (hour unknown) drops it the same way, without the prop. */
|
|
53
54
|
hideTime?: boolean;
|
|
54
55
|
/**
|
|
55
56
|
* Replaces the default "time · venue" sub-line entirely. For surfaces where
|
|
@@ -99,6 +100,7 @@ export const EventCompactRow = memo(function EventCompactRow({
|
|
|
99
100
|
const fee = resolveEventEntryFee(event);
|
|
100
101
|
const showPoster = !!event.poster_url && !imgError;
|
|
101
102
|
const venue = event.place_name ?? event.location;
|
|
103
|
+
const time = formatters.time(event.starts_at);
|
|
102
104
|
|
|
103
105
|
const body = (
|
|
104
106
|
<>
|
|
@@ -157,9 +159,9 @@ export const EventCompactRow = memo(function EventCompactRow({
|
|
|
157
159
|
subtitle
|
|
158
160
|
) : (
|
|
159
161
|
<>
|
|
160
|
-
{!hideTime && (
|
|
162
|
+
{!hideTime && time && (
|
|
161
163
|
<>
|
|
162
|
-
<span className="font-mono tabular-nums">{
|
|
164
|
+
<span className="font-mono tabular-nums">{time}</span>
|
|
163
165
|
<span aria-hidden> · </span>
|
|
164
166
|
</>
|
|
165
167
|
)}
|
|
@@ -76,7 +76,11 @@ export function resolveEventEntryFee(event: EventPreview): EventEntryFee {
|
|
|
76
76
|
* locale and no currency of its own.
|
|
77
77
|
*/
|
|
78
78
|
export type EventFormatters = {
|
|
79
|
-
/**
|
|
79
|
+
/**
|
|
80
|
+
* e.g. `"20:00"`. Return `""` when the event's hour is not known: the card
|
|
81
|
+
* and the compact row then print the day (or the venue) ALONE, with no
|
|
82
|
+
* separator — never a placeholder word and never "00:00".
|
|
83
|
+
*/
|
|
80
84
|
time: (isoDateTime: string) => string;
|
|
81
85
|
/** e.g. `"Sat, Sep 5"` — used when a card appears outside its own day section. */
|
|
82
86
|
day: (isoDateTime: string) => string;
|