@openrails/contentkit-ui 0.94.0 → 0.95.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +58 -1
- package/dist/client/discovery.d.ts +14 -1
- package/dist/client/discovery.js +27 -14
- package/dist/client/discovery.js.map +1 -1
- package/dist/client/generated/routes.d.ts +18 -5
- package/dist/client/generated/routes.js +39 -0
- package/dist/client/generated/routes.js.map +1 -1
- package/dist/client/generated/wire.d.ts +10 -0
- package/dist/client/generated/wire.js.map +1 -1
- package/dist/client/index.d.ts +1 -1
- package/dist/client.js +17 -17
- package/dist/components/content/card.d.ts +28 -6
- package/dist/components/content/card.js +158 -132
- package/dist/components/content/card.js.map +1 -1
- package/dist/components/content/daily-releases.d.ts +15 -0
- package/dist/components/content/daily-releases.js +173 -0
- package/dist/components/content/daily-releases.js.map +1 -0
- package/dist/components/content/grid.d.ts +14 -1
- package/dist/components/content/grid.js +75 -34
- package/dist/components/content/grid.js.map +1 -1
- package/dist/components/content/index.d.ts +4 -2
- package/dist/components/content/popular.d.ts +11 -0
- package/dist/components/content/popular.js +49 -0
- package/dist/components/content/popular.js.map +1 -0
- package/dist/index.js +22 -20
- package/dist/locales/discovery/de.js +4 -0
- package/dist/locales/discovery/de.js.map +1 -1
- package/dist/locales/discovery/en.d.ts +4 -0
- package/dist/locales/discovery/en.js +4 -0
- package/dist/locales/discovery/en.js.map +1 -1
- package/dist/locales/discovery/es.js +4 -0
- package/dist/locales/discovery/es.js.map +1 -1
- package/dist/locales/discovery/ja.js +4 -0
- package/dist/locales/discovery/ja.js.map +1 -1
- package/dist/locales/discovery/ko.js +4 -0
- package/dist/locales/discovery/ko.js.map +1 -1
- package/dist/locales/discovery/zh.js +4 -0
- package/dist/locales/discovery/zh.js.map +1 -1
- package/dist/locales/en.d.ts +4 -0
- package/dist/react/discovery.d.ts +12 -2
- package/dist/react/discovery.js +32 -23
- package/dist/react/discovery.js.map +1 -1
- package/dist/react/index.d.ts +1 -1
- package/dist/react/resources.js +11 -11
- package/dist/react/resources.js.map +1 -1
- package/dist/react.js +10 -10
- package/dist/styles.css +1 -1
- package/package.json +1 -1
|
@@ -12,12 +12,12 @@ import { cn as _ } from "cn";
|
|
|
12
12
|
import { FavouriteIcon as v, LockIcon as y, ThumbsUpIcon as b } from "@hugeicons/core-free-icons";
|
|
13
13
|
import { HugeiconsIcon as x } from "@hugeicons/react";
|
|
14
14
|
//#region src/components/content/card.tsx
|
|
15
|
-
function S({ card: e, decorate: t }) {
|
|
16
|
-
let
|
|
17
|
-
return
|
|
18
|
-
className: "pointer-events-none absolute inset-0",
|
|
15
|
+
function S({ card: e, decorate: t, aboveTitle: n }) {
|
|
16
|
+
let r = t?.(e);
|
|
17
|
+
return r == null || r === !1 ? null : /* @__PURE__ */ h("span", {
|
|
18
|
+
className: _("pointer-events-none absolute inset-0", n && "z-20"),
|
|
19
19
|
"data-ckui": "card-decorations",
|
|
20
|
-
children:
|
|
20
|
+
children: r
|
|
21
21
|
});
|
|
22
22
|
}
|
|
23
23
|
var C = (e, t) => new Intl.NumberFormat(t, {
|
|
@@ -42,127 +42,148 @@ function T(e, t) {
|
|
|
42
42
|
t
|
|
43
43
|
]);
|
|
44
44
|
}
|
|
45
|
-
function E({ card: r, href: o, onOpen: c, shape: l = "portrait",
|
|
46
|
-
let
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
45
|
+
function E({ card: r, href: o, onOpen: c, shape: l = "portrait", aspectRatio: d, titlePosition: p = "below", loadMedia: E = !0, groupKinds: k, chips: A = 3, filterEntity: j, entityStyle: M = "chips", metadata: N, showCounts: ee = !0, tiers: P, labels: F, owner: I = !0, ownerHref: L, decorate: R, children: z, className: te }) {
|
|
46
|
+
let B = n(), { t: V } = B, ne = t(), H = o ? o(r) : r.path, U = T(H, f(() => c?.(r), [c, r])), W = w(B, r.access, P, F), G = r.version, K = r.viewer && r.viewer.progress_max > 0 ? Math.min(1, r.viewer.progress / r.viewer.progress_max) : 0, q = (k ?? Object.keys(r.entities)).flatMap((e) => (r.entities[e] ?? []).filter((t) => !j || j(t, e)).slice(0, A).map((t) => ({
|
|
47
|
+
kind: e,
|
|
48
|
+
entity: t
|
|
49
|
+
}))), J = G.duration_ms ? Math.round(G.duration_ms / 6e4) : 0, Y = N?.traits, re = Y === !1 ? [] : Array.isArray(Y) ? G.traits.filter((e) => Y.includes(e)) : G.traits, X = [
|
|
50
|
+
...N?.languages === !1 ? [] : G.languages.map(ne),
|
|
51
|
+
...re.map((e) => u(F, e)),
|
|
52
|
+
N?.pages !== !1 && G.pages ? B.plural("contents.pages", G.pages) : null,
|
|
53
|
+
N?.duration !== !1 && J ? B.plural("contents.minutes", J) : null
|
|
54
|
+
].filter(Boolean), Z = r.title || r.code, Q = q.length > 0 ? /* @__PURE__ */ h("ul", {
|
|
55
|
+
className: _("flex flex-wrap", M === "text" ? "gap-x-2 gap-y-1" : "gap-1"),
|
|
56
|
+
"data-ckui": "card-groups",
|
|
57
|
+
children: q.map(({ kind: e, entity: t }) => /* @__PURE__ */ h("li", {
|
|
58
|
+
"data-kind": e,
|
|
59
|
+
children: /* @__PURE__ */ h(O, {
|
|
60
|
+
url: t.path,
|
|
61
|
+
name: t.name || t.slug,
|
|
62
|
+
variant: M
|
|
63
|
+
})
|
|
64
|
+
}, `${e}:${t.id}`))
|
|
65
|
+
}) : null, $ = /* @__PURE__ */ g("a", {
|
|
66
|
+
href: H,
|
|
67
|
+
onClick: U,
|
|
68
|
+
className: _("font-medium break-words focus-visible:underline", p === "cover" ? "absolute inset-x-0 bottom-0 z-10 bg-linear-to-t from-black/90 via-black/60 to-transparent px-3 pt-10 pb-3 text-white hover:underline" : "hover:underline"),
|
|
69
|
+
"data-ckui": "card-title",
|
|
70
|
+
children: [/* @__PURE__ */ h("span", {
|
|
71
|
+
className: "line-clamp-2",
|
|
72
|
+
children: Z
|
|
73
|
+
}), W && /* @__PURE__ */ g("span", {
|
|
74
|
+
className: "sr-only",
|
|
75
|
+
children: [
|
|
76
|
+
" (",
|
|
77
|
+
W,
|
|
78
|
+
")"
|
|
79
|
+
]
|
|
80
|
+
})]
|
|
81
|
+
}), [ie, ae] = m(null);
|
|
52
82
|
return /* @__PURE__ */ g("article", {
|
|
53
|
-
ref:
|
|
54
|
-
className: _("group/card grid content-start gap-2",
|
|
83
|
+
ref: ae,
|
|
84
|
+
className: _("group/card grid content-start gap-2", te),
|
|
55
85
|
"data-ckui": "content-card",
|
|
56
86
|
"data-id": r.id,
|
|
57
|
-
"data-locked":
|
|
87
|
+
"data-locked": W ? "" : void 0,
|
|
58
88
|
lang: r.language || void 0,
|
|
59
89
|
children: [/* @__PURE__ */ g("div", {
|
|
60
90
|
className: "relative overflow-hidden rounded-lg",
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
91
|
+
"data-ckui": "card-cover",
|
|
92
|
+
children: [
|
|
93
|
+
/* @__PURE__ */ g("a", {
|
|
94
|
+
href: H,
|
|
95
|
+
onClick: U,
|
|
96
|
+
className: "relative block overflow-hidden rounded-lg bg-muted",
|
|
97
|
+
tabIndex: -1,
|
|
98
|
+
"aria-hidden": !0,
|
|
99
|
+
children: [
|
|
100
|
+
/* @__PURE__ */ h("div", {
|
|
101
|
+
"data-ckui": "card-cover-frame",
|
|
102
|
+
className: d === void 0 ? l === "landscape" ? "aspect-video" : "aspect-[3/4]" : void 0,
|
|
103
|
+
style: d === void 0 ? void 0 : { aspectRatio: d },
|
|
104
|
+
children: E ? /* @__PURE__ */ h(e, {
|
|
105
|
+
outputs: r.cover,
|
|
106
|
+
alt: "",
|
|
107
|
+
fit: "cover",
|
|
108
|
+
skeleton: !0,
|
|
109
|
+
loading: "lazy",
|
|
110
|
+
className: "size-full transition-transform group-hover/card:scale-[1.02]",
|
|
111
|
+
fallback: /* @__PURE__ */ h("span", {
|
|
112
|
+
className: "grid size-full place-items-center text-2xl font-semibold text-muted-foreground",
|
|
113
|
+
children: Z.charAt(0).toUpperCase()
|
|
114
|
+
})
|
|
115
|
+
}) : /* @__PURE__ */ h("span", {
|
|
116
|
+
className: "block size-full bg-muted",
|
|
117
|
+
"aria-hidden": !0
|
|
118
|
+
})
|
|
119
|
+
}),
|
|
120
|
+
E && G.hls && /* @__PURE__ */ h(i, {
|
|
121
|
+
item: {
|
|
122
|
+
kind: r.kind,
|
|
123
|
+
id: r.id,
|
|
124
|
+
version: G.id
|
|
125
|
+
},
|
|
126
|
+
dir: G.hls,
|
|
127
|
+
duration: G.duration_ms ? G.duration_ms / 1e3 : void 0,
|
|
128
|
+
target: ie
|
|
129
|
+
}),
|
|
130
|
+
W && /* @__PURE__ */ g("span", {
|
|
131
|
+
className: "absolute top-2 left-2 inline-flex items-center gap-1 rounded-md bg-background/85 px-1.5 py-0.5 text-xs font-medium text-foreground shadow-sm",
|
|
132
|
+
"data-ckui": "card-lock",
|
|
133
|
+
children: [/* @__PURE__ */ h(x, {
|
|
134
|
+
icon: y,
|
|
135
|
+
strokeWidth: 2,
|
|
136
|
+
className: "size-3.5",
|
|
137
|
+
"aria-hidden": !0
|
|
138
|
+
}), W]
|
|
139
|
+
}),
|
|
140
|
+
K > 0 && /* @__PURE__ */ h("span", {
|
|
141
|
+
className: _("absolute inset-x-0 bottom-0 h-1 bg-background/60", p === "cover" && "z-20"),
|
|
142
|
+
"data-ckui": "card-progress",
|
|
143
|
+
children: /* @__PURE__ */ h("span", {
|
|
144
|
+
className: "block h-full bg-primary",
|
|
145
|
+
style: { width: `${Math.round(K * 100)}%` }
|
|
79
146
|
})
|
|
80
147
|
})
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
target: q
|
|
91
|
-
}),
|
|
92
|
-
B && /* @__PURE__ */ g("span", {
|
|
93
|
-
className: "absolute top-2 left-2 inline-flex items-center gap-1 rounded-md bg-background/85 px-1.5 py-0.5 text-xs font-medium text-foreground shadow-sm",
|
|
94
|
-
"data-ckui": "card-lock",
|
|
95
|
-
children: [/* @__PURE__ */ h(x, {
|
|
96
|
-
icon: y,
|
|
97
|
-
strokeWidth: 2,
|
|
98
|
-
className: "size-3.5",
|
|
99
|
-
"aria-hidden": !0
|
|
100
|
-
}), B]
|
|
101
|
-
}),
|
|
102
|
-
H > 0 && /* @__PURE__ */ h("span", {
|
|
103
|
-
className: "absolute inset-x-0 bottom-0 h-1 bg-background/60",
|
|
104
|
-
"data-ckui": "card-progress",
|
|
105
|
-
children: /* @__PURE__ */ h("span", {
|
|
106
|
-
className: "block h-full bg-primary",
|
|
107
|
-
style: { width: `${Math.round(H * 100)}%` }
|
|
108
|
-
})
|
|
109
|
-
})
|
|
110
|
-
]
|
|
111
|
-
}), /* @__PURE__ */ h(S, {
|
|
112
|
-
card: r,
|
|
113
|
-
decorate: M
|
|
114
|
-
})]
|
|
148
|
+
]
|
|
149
|
+
}),
|
|
150
|
+
p === "cover" && $,
|
|
151
|
+
E && /* @__PURE__ */ h(S, {
|
|
152
|
+
card: r,
|
|
153
|
+
decorate: R,
|
|
154
|
+
aboveTitle: p === "cover"
|
|
155
|
+
})
|
|
156
|
+
]
|
|
115
157
|
}), /* @__PURE__ */ g("div", {
|
|
116
158
|
className: "grid gap-1",
|
|
117
159
|
children: [
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
className: "line-clamp-2 font-medium break-words hover:underline",
|
|
122
|
-
"data-ckui": "card-title",
|
|
123
|
-
children: [K, B && /* @__PURE__ */ g("span", {
|
|
124
|
-
className: "sr-only",
|
|
125
|
-
children: [
|
|
126
|
-
" (",
|
|
127
|
-
B,
|
|
128
|
-
")"
|
|
129
|
-
]
|
|
130
|
-
})]
|
|
131
|
-
}),
|
|
132
|
-
A && r.owner && /* @__PURE__ */ h(D, {
|
|
160
|
+
p === "below" && $,
|
|
161
|
+
M === "text" && Q,
|
|
162
|
+
I && r.owner && /* @__PURE__ */ h(D, {
|
|
133
163
|
group: r.owner,
|
|
134
|
-
href:
|
|
164
|
+
href: L,
|
|
165
|
+
loadMedia: E
|
|
135
166
|
}),
|
|
136
|
-
|
|
167
|
+
X.length > 0 && /* @__PURE__ */ h("p", {
|
|
137
168
|
className: "text-xs text-muted-foreground",
|
|
138
|
-
children:
|
|
169
|
+
children: X.join(" · ")
|
|
139
170
|
}),
|
|
140
171
|
r.viewer?.completed && /* @__PURE__ */ h(a, {
|
|
141
172
|
variant: "secondary",
|
|
142
173
|
className: "justify-self-start",
|
|
143
|
-
children:
|
|
174
|
+
children: V("contents.completed")
|
|
144
175
|
}),
|
|
145
176
|
!r.access.allowed && r.access.free_after && /* @__PURE__ */ h("p", {
|
|
146
177
|
className: "text-xs text-muted-foreground",
|
|
147
|
-
children:
|
|
148
|
-
}),
|
|
149
|
-
U.some((e) => r.entities[e]?.length) && /* @__PURE__ */ h("ul", {
|
|
150
|
-
className: "flex flex-wrap gap-1",
|
|
151
|
-
"data-ckui": "card-groups",
|
|
152
|
-
children: U.flatMap((e) => (r.entities[e] ?? []).slice(0, p).map((t) => /* @__PURE__ */ h("li", {
|
|
153
|
-
"data-kind": e,
|
|
154
|
-
children: /* @__PURE__ */ h(O, {
|
|
155
|
-
url: t.path,
|
|
156
|
-
name: t.name || t.slug
|
|
157
|
-
})
|
|
158
|
-
}, `${e}:${t.id}`)))
|
|
178
|
+
children: V("contents.freeFrom", { date: s(B, r.access.free_after, !1) })
|
|
159
179
|
}),
|
|
160
|
-
|
|
180
|
+
M === "chips" && Q,
|
|
181
|
+
ee && (r.counts.favorites !== void 0 || r.counts.likes !== void 0) && /* @__PURE__ */ g("p", {
|
|
161
182
|
className: "flex items-center gap-3 text-xs text-muted-foreground tabular-nums",
|
|
162
183
|
"data-ckui": "card-counts",
|
|
163
184
|
children: [r.counts.favorites !== void 0 && /* @__PURE__ */ g("span", {
|
|
164
185
|
className: "inline-flex items-center gap-1",
|
|
165
|
-
title:
|
|
186
|
+
title: V("contents.favorites"),
|
|
166
187
|
children: [
|
|
167
188
|
/* @__PURE__ */ h(x, {
|
|
168
189
|
icon: v,
|
|
@@ -172,13 +193,13 @@ function E({ card: r, href: o, onOpen: c, shape: l = "portrait", groupKinds: d,
|
|
|
172
193
|
}),
|
|
173
194
|
/* @__PURE__ */ h("span", {
|
|
174
195
|
className: "sr-only",
|
|
175
|
-
children:
|
|
196
|
+
children: V("contents.favorites")
|
|
176
197
|
}),
|
|
177
|
-
C(r.counts.favorites,
|
|
198
|
+
C(r.counts.favorites, B.language)
|
|
178
199
|
]
|
|
179
200
|
}), r.counts.likes !== void 0 && /* @__PURE__ */ g("span", {
|
|
180
201
|
className: "inline-flex items-center gap-1",
|
|
181
|
-
title:
|
|
202
|
+
title: V("contents.likes"),
|
|
182
203
|
children: [
|
|
183
204
|
/* @__PURE__ */ h(x, {
|
|
184
205
|
icon: b,
|
|
@@ -188,18 +209,18 @@ function E({ card: r, href: o, onOpen: c, shape: l = "portrait", groupKinds: d,
|
|
|
188
209
|
}),
|
|
189
210
|
/* @__PURE__ */ h("span", {
|
|
190
211
|
className: "sr-only",
|
|
191
|
-
children:
|
|
212
|
+
children: V("contents.likes")
|
|
192
213
|
}),
|
|
193
|
-
C(r.counts.likes,
|
|
214
|
+
C(r.counts.likes, B.language)
|
|
194
215
|
]
|
|
195
216
|
})]
|
|
196
217
|
}),
|
|
197
|
-
|
|
218
|
+
z
|
|
198
219
|
]
|
|
199
220
|
})]
|
|
200
221
|
});
|
|
201
222
|
}
|
|
202
|
-
function D({ group: e, href: t, className: n }) {
|
|
223
|
+
function D({ group: e, href: t, className: n, loadMedia: r = !0 }) {
|
|
203
224
|
return /* @__PURE__ */ h("span", {
|
|
204
225
|
className: _("flex min-w-0 text-xs text-muted-foreground", n),
|
|
205
226
|
"data-ckui": "card-owner",
|
|
@@ -208,9 +229,12 @@ function D({ group: e, href: t, className: n }) {
|
|
|
208
229
|
group: e,
|
|
209
230
|
href: t,
|
|
210
231
|
className: "inline-flex min-w-0 items-center gap-1.5 hover:text-foreground",
|
|
211
|
-
children: [/* @__PURE__ */ h(c, {
|
|
232
|
+
children: [r ? /* @__PURE__ */ h(c, {
|
|
212
233
|
group: e,
|
|
213
234
|
className: "size-5 shrink-0 text-[0.625rem]"
|
|
235
|
+
}) : /* @__PURE__ */ h("span", {
|
|
236
|
+
className: "size-5 shrink-0 rounded-full bg-muted",
|
|
237
|
+
"aria-hidden": !0
|
|
214
238
|
}), /* @__PURE__ */ h("span", {
|
|
215
239
|
className: "truncate",
|
|
216
240
|
children: e.name || e.slug
|
|
@@ -218,55 +242,57 @@ function D({ group: e, href: t, className: n }) {
|
|
|
218
242
|
})
|
|
219
243
|
});
|
|
220
244
|
}
|
|
221
|
-
function O({ url: e, name: t }) {
|
|
222
|
-
let
|
|
245
|
+
function O({ url: e, name: t, variant: n = "chips" }) {
|
|
246
|
+
let r = T(e), i = n === "text" ? "text-sm text-muted-foreground" : "inline-block rounded-md border border-border px-1.5 py-0.5 text-xs text-muted-foreground";
|
|
223
247
|
return e ? /* @__PURE__ */ h("a", {
|
|
224
248
|
href: e,
|
|
225
|
-
onClick:
|
|
226
|
-
className: _(
|
|
249
|
+
onClick: r,
|
|
250
|
+
className: _(i, "hover:text-foreground", n === "text" ? "hover:underline" : "hover:bg-muted"),
|
|
227
251
|
children: t
|
|
228
252
|
}) : /* @__PURE__ */ h("span", {
|
|
229
|
-
className:
|
|
253
|
+
className: i,
|
|
230
254
|
children: t
|
|
231
255
|
});
|
|
232
256
|
}
|
|
233
|
-
function k({ card: t, href: r, onOpen: i, tiers: a, labels: s, byline: c, owner: l = !0, ownerHref: u,
|
|
234
|
-
let
|
|
257
|
+
function k({ card: t, href: r, onOpen: i, tiers: a, labels: s, byline: c, owner: l = !0, ownerHref: u, loadMedia: d = !0, showCounts: p = !0, decorate: m, children: b, className: E }) {
|
|
258
|
+
let O = n(), k = r ? r(t) : t.path, A = T(k, f(() => i?.(t), [i, t])), j = w(O, t.access, a, s), M = t.title || t.code;
|
|
235
259
|
return /* @__PURE__ */ g("article", {
|
|
236
|
-
className: _("grid gap-3 rounded-lg border border-border p-3",
|
|
260
|
+
className: _("grid gap-3 rounded-lg border border-border p-3", E),
|
|
237
261
|
"data-ckui": "post-card",
|
|
238
262
|
"data-id": t.id,
|
|
239
|
-
"data-locked":
|
|
263
|
+
"data-locked": j ? "" : void 0,
|
|
240
264
|
lang: t.language || void 0,
|
|
241
265
|
children: [
|
|
242
266
|
c ?? (l && t.owner && /* @__PURE__ */ h(D, {
|
|
243
267
|
group: t.owner,
|
|
244
268
|
href: u,
|
|
269
|
+
loadMedia: d,
|
|
245
270
|
className: "text-sm"
|
|
246
271
|
})),
|
|
247
272
|
/* @__PURE__ */ g("a", {
|
|
248
|
-
href:
|
|
249
|
-
onClick:
|
|
273
|
+
href: k,
|
|
274
|
+
onClick: A,
|
|
250
275
|
className: "grid gap-2",
|
|
251
276
|
children: [/* @__PURE__ */ h("span", {
|
|
252
277
|
className: "font-medium break-words hover:underline",
|
|
253
278
|
"data-ckui": "card-title",
|
|
254
|
-
children:
|
|
279
|
+
children: M
|
|
255
280
|
}), t.cover.length > 0 && /* @__PURE__ */ g("span", {
|
|
256
281
|
className: "relative block aspect-video overflow-hidden rounded-md bg-muted",
|
|
257
282
|
children: [
|
|
258
|
-
/* @__PURE__ */ h(e, {
|
|
283
|
+
d && /* @__PURE__ */ h(e, {
|
|
259
284
|
outputs: t.cover,
|
|
260
285
|
alt: "",
|
|
261
286
|
fit: "cover",
|
|
262
287
|
skeleton: !0,
|
|
263
|
-
|
|
288
|
+
loading: "lazy",
|
|
289
|
+
className: _("size-full", j && "blur-md")
|
|
264
290
|
}),
|
|
265
|
-
/* @__PURE__ */ h(S, {
|
|
291
|
+
d && /* @__PURE__ */ h(S, {
|
|
266
292
|
card: t,
|
|
267
|
-
decorate:
|
|
293
|
+
decorate: m
|
|
268
294
|
}),
|
|
269
|
-
|
|
295
|
+
j && /* @__PURE__ */ h("span", {
|
|
270
296
|
className: "absolute inset-0 grid place-items-center",
|
|
271
297
|
children: /* @__PURE__ */ g("span", {
|
|
272
298
|
className: "inline-flex items-center gap-1 rounded-md bg-background/85 px-2 py-1 text-xs font-medium shadow-sm",
|
|
@@ -276,7 +302,7 @@ function k({ card: t, href: r, onOpen: i, tiers: a, labels: s, byline: c, owner:
|
|
|
276
302
|
strokeWidth: 2,
|
|
277
303
|
className: "size-3.5",
|
|
278
304
|
"aria-hidden": !0
|
|
279
|
-
}),
|
|
305
|
+
}), j]
|
|
280
306
|
})
|
|
281
307
|
})
|
|
282
308
|
]
|
|
@@ -286,11 +312,11 @@ function k({ card: t, href: r, onOpen: i, tiers: a, labels: s, byline: c, owner:
|
|
|
286
312
|
className: "flex flex-wrap items-center gap-3 text-xs text-muted-foreground",
|
|
287
313
|
children: [
|
|
288
314
|
t.published_at && /* @__PURE__ */ h(o, { at: t.published_at }),
|
|
289
|
-
!t.cover.length &&
|
|
315
|
+
!t.cover.length && j && /* @__PURE__ */ h("span", {
|
|
290
316
|
"data-ckui": "card-lock",
|
|
291
|
-
children:
|
|
317
|
+
children: j
|
|
292
318
|
}),
|
|
293
|
-
t.counts.favorites !== void 0 && /* @__PURE__ */ g("span", {
|
|
319
|
+
p && t.counts.favorites !== void 0 && /* @__PURE__ */ g("span", {
|
|
294
320
|
className: "inline-flex items-center gap-1 tabular-nums",
|
|
295
321
|
"data-ckui": "card-counts",
|
|
296
322
|
children: [
|
|
@@ -302,14 +328,14 @@ function k({ card: t, href: r, onOpen: i, tiers: a, labels: s, byline: c, owner:
|
|
|
302
328
|
}),
|
|
303
329
|
/* @__PURE__ */ h("span", {
|
|
304
330
|
className: "sr-only",
|
|
305
|
-
children:
|
|
331
|
+
children: O.t("contents.favorites")
|
|
306
332
|
}),
|
|
307
|
-
C(t.counts.favorites,
|
|
333
|
+
C(t.counts.favorites, O.language)
|
|
308
334
|
]
|
|
309
335
|
})
|
|
310
336
|
]
|
|
311
337
|
}),
|
|
312
|
-
|
|
338
|
+
b
|
|
313
339
|
]
|
|
314
340
|
});
|
|
315
341
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"card.js","names":[],"sources":["../../../src/components/content/card.tsx"],"sourcesContent":["import { FavouriteIcon, LockIcon, ThumbsUpIcon } from \"@hugeicons/core-free-icons\";\nimport { HugeiconsIcon } from \"@hugeicons/react\";\nimport { cn } from \"cn\";\nimport { useCallback, useContext, useState, type MouseEvent, type ReactNode } from \"react\";\nimport type { Card, CardAccess } from \"../../client/generated/wire.js\";\nimport { useLanguageName, useMessages } from \"../../i18n/context.js\";\nimport type { Translator } from \"../../i18n/messages.js\";\nimport { ContentKitContext } from \"../../react/context.js\";\nimport { Badge } from \"#ckui/ui/badge\";\nimport { HoverPreview } from \"../hover-preview.js\";\nimport { RenditionImg } from \"../rendition-img.js\";\nimport { formatDate, RelativeTime } from \"../social/parts.js\";\nimport { GroupAvatar, GroupLink, labelOf, type GroupLike, type Labels } from \"../groups/parts.js\";\nimport { priceLabel } from \"./paywall.js\";\n\nexport interface ContentCardProps {\n card: Card;\n /** The card's link; default its canonical path. */\n href?: (card: Card) => string | undefined;\n /** Before the card's link is followed: a click signal. */\n onOpen?: (card: Card) => void;\n /** Cover shape: \"portrait\" (3:4, readers) or \"landscape\" (16:9, players). Default portrait. */\n shape?: \"portrait\" | \"landscape\";\n /** The group kinds whose chips show, in order; default every kind the card names. */\n groupKinds?: readonly string[];\n /** Chips per group kind. Default 3. */\n chips?: number;\n /** Tiers the site sells, so a lock names them; others show as \"for sale\". */\n tiers?: readonly string[];\n /** Display names of kinds, traits and tiers by identifier. */\n labels?: Labels;\n /** Show the owner group (a channel) when the card has one; default true, false on that group's own feed. */\n owner?: boolean;\n /** The owner group's link; default its canonical path. */\n ownerHref?: (g: GroupLike) => string | undefined;\n /** Over the cover: the host's badges for the card, placed in the cover's box; clicks reach the card. */\n decorate?: (card: Card) => ReactNode;\n /** Below the meta line: the host's own. */\n children?: ReactNode;\n className?: string;\n}\n\n/** The host's badges over a cover. */\nfunction Decorations({ card, decorate }: { card: Card; decorate?: (card: Card) => ReactNode }) {\n const badges = decorate?.(card);\n if (badges == null || badges === false) return null;\n return (\n <span className=\"pointer-events-none absolute inset-0\" data-ckui=\"card-decorations\">\n {badges}\n </span>\n );\n}\n\nconst compact = (n: number, language?: string) => new Intl.NumberFormat(language, { notation: \"compact\", maximumFractionDigits: 1 }).format(n);\n\n/** Why a card is locked, in words (its price when it is on sale); null when it opens. */\nexport function lockLabel(m: Translator, a: CardAccess, tiers: readonly string[] = [], labels?: Labels): string | null {\n if (a.allowed) return null;\n if (a.unknown) return m.t(\"contents.unknownAccess\");\n const offer = a.offers?.[0];\n if (offer) return offer.target.kind === \"group\" && Number(offer.terms.amount) === 0 ? m.t(\"contents.joinFree\") : priceLabel(m, offer.terms);\n const tier = a.sell?.find((k) => tiers.includes(k));\n if (tier) return labelOf(labels, tier);\n if (a.sell?.some((k) => k.includes(\":group:\"))) return m.t(\"contents.members\");\n if (a.sell?.length) return m.t(\"contents.forSale\");\n return m.t(\"contents.locked\");\n}\n\n/** A link followed in-app through the provider's navigate. */\nfunction useLink(url: string | undefined, before?: () => void) {\n const navigate = useContext(ContentKitContext)?.navigate;\n return useCallback(\n (e: MouseEvent<HTMLAnchorElement>) => {\n before?.();\n if (!navigate || !url || e.defaultPrevented || e.button !== 0 || e.metaKey || e.ctrlKey || e.shiftKey || e.altKey) return;\n e.preventDefault();\n navigate(url);\n },\n [navigate, url, before],\n );\n}\n\n/** One content in a listing: cover (a video the reader opens previews over it on hover), title, version, groups, counts, the reader's progress and why it is locked; what its kind's locked view hides is absent. */\nexport function ContentCard({ card, href, onOpen, shape = \"portrait\", groupKinds, chips = 3, tiers, labels, owner = true, ownerHref, decorate, children, className }: ContentCardProps) {\n const m = useMessages();\n const { t } = m;\n const languageName = useLanguageName();\n const url = href ? href(card) : card.path;\n const open = useCallback(() => onOpen?.(card), [onOpen, card]);\n const onClick = useLink(url, open);\n const lock = lockLabel(m, card.access, tiers, labels);\n const v = card.version;\n const progress = card.viewer && card.viewer.progress_max > 0 ? Math.min(1, card.viewer.progress / card.viewer.progress_max) : 0;\n const kinds = groupKinds ?? Object.keys(card.entities);\n const minutes = v.duration_ms ? Math.round(v.duration_ms / 60_000) : 0;\n const meta = [\n ...v.languages.map(languageName),\n ...v.traits.map((x) => labelOf(labels, x)),\n v.pages ? m.plural(\"contents.pages\", v.pages) : null,\n minutes ? m.plural(\"contents.minutes\", minutes) : null,\n ].filter(Boolean);\n const title = card.title || card.code;\n const [article, setArticle] = useState<HTMLElement | null>(null);\n return (\n <article ref={setArticle} className={cn(\"group/card grid content-start gap-2\", className)} data-ckui=\"content-card\" data-id={card.id} data-locked={lock ? \"\" : undefined} lang={card.language || undefined}>\n <div className=\"relative overflow-hidden rounded-lg\">\n <a href={url} onClick={onClick} className=\"relative block overflow-hidden rounded-lg bg-muted\" tabIndex={-1} aria-hidden>\n <div className={shape === \"landscape\" ? \"aspect-video\" : \"aspect-[3/4]\"}>\n <RenditionImg\n outputs={card.cover}\n alt=\"\"\n fit=\"cover\"\n skeleton\n className=\"size-full transition-transform group-hover/card:scale-[1.02]\"\n fallback={<span className=\"grid size-full place-items-center text-2xl font-semibold text-muted-foreground\">{title.charAt(0).toUpperCase()}</span>}\n />\n </div>\n {v.hls && <HoverPreview item={{ kind: card.kind, id: card.id, version: v.id }} dir={v.hls} duration={v.duration_ms ? v.duration_ms / 1000 : undefined} target={article} />}\n {lock && (\n <span className=\"absolute top-2 left-2 inline-flex items-center gap-1 rounded-md bg-background/85 px-1.5 py-0.5 text-xs font-medium text-foreground shadow-sm\" data-ckui=\"card-lock\">\n <HugeiconsIcon icon={LockIcon} strokeWidth={2} className=\"size-3.5\" aria-hidden />\n {lock}\n </span>\n )}\n {progress > 0 && (\n <span className=\"absolute inset-x-0 bottom-0 h-1 bg-background/60\" data-ckui=\"card-progress\">\n <span className=\"block h-full bg-primary\" style={{ width: `${Math.round(progress * 100)}%` }} />\n </span>\n )}\n </a>\n <Decorations card={card} decorate={decorate} />\n </div>\n <div className=\"grid gap-1\">\n <a href={url} onClick={onClick} className=\"line-clamp-2 font-medium break-words hover:underline\" data-ckui=\"card-title\">\n {title}\n {lock && <span className=\"sr-only\"> ({lock})</span>}\n </a>\n {owner && card.owner && <OwnerChip group={card.owner} href={ownerHref} />}\n {meta.length > 0 && <p className=\"text-xs text-muted-foreground\">{meta.join(\" · \")}</p>}\n {card.viewer?.completed && (\n <Badge variant=\"secondary\" className=\"justify-self-start\">\n {t(\"contents.completed\")}\n </Badge>\n )}\n {!card.access.allowed && card.access.free_after && <p className=\"text-xs text-muted-foreground\">{t(\"contents.freeFrom\", { date: formatDate(m, card.access.free_after, false) })}</p>}\n {kinds.some((k) => card.entities[k]?.length) && (\n <ul className=\"flex flex-wrap gap-1\" data-ckui=\"card-groups\">\n {kinds.flatMap((k) =>\n (card.entities[k] ?? []).slice(0, chips).map((g) => (\n <li key={`${k}:${g.id}`} data-kind={k}>\n <Chip url={g.path} name={g.name || g.slug} />\n </li>\n )),\n )}\n </ul>\n )}\n {(card.counts.favorites !== undefined || card.counts.likes !== undefined) && (\n <p className=\"flex items-center gap-3 text-xs text-muted-foreground tabular-nums\" data-ckui=\"card-counts\">\n {card.counts.favorites !== undefined && (\n <span className=\"inline-flex items-center gap-1\" title={t(\"contents.favorites\")}>\n <HugeiconsIcon icon={FavouriteIcon} strokeWidth={2} className={cn(\"size-3.5\", card.viewer?.favorited && \"fill-current text-primary\")} aria-hidden />\n <span className=\"sr-only\">{t(\"contents.favorites\")}</span>\n {compact(card.counts.favorites, m.language)}\n </span>\n )}\n {card.counts.likes !== undefined && (\n <span className=\"inline-flex items-center gap-1\" title={t(\"contents.likes\")}>\n <HugeiconsIcon icon={ThumbsUpIcon} strokeWidth={2} className=\"size-3.5\" aria-hidden />\n <span className=\"sr-only\">{t(\"contents.likes\")}</span>\n {compact(card.counts.likes, m.language)}\n </span>\n )}\n </p>\n )}\n {children}\n </div>\n </article>\n );\n}\n\n/** The group that owns a content (a channel): its avatar and name, linking to its page. */\nexport function OwnerChip({ group, href, className }: { group: GroupLike; href?: (g: GroupLike) => string | undefined; className?: string }) {\n return (\n <span className={cn(\"flex min-w-0 text-xs text-muted-foreground\", className)} data-ckui=\"card-owner\" data-id={group.id}>\n <GroupLink group={group} href={href} className=\"inline-flex min-w-0 items-center gap-1.5 hover:text-foreground\">\n <GroupAvatar group={group} className=\"size-5 shrink-0 text-[0.625rem]\" />\n <span className=\"truncate\">{group.name || group.slug}</span>\n </GroupLink>\n </span>\n );\n}\n\nfunction Chip({ url, name }: { url?: string; name: string }) {\n const onClick = useLink(url);\n const cls = \"inline-block rounded-md border border-border px-1.5 py-0.5 text-xs text-muted-foreground\";\n return url ? (\n <a href={url} onClick={onClick} className={cn(cls, \"hover:bg-muted hover:text-foreground\")}>\n {name}\n </a>\n ) : (\n <span className={cls}>{name}</span>\n );\n}\n\nexport interface PostCardProps extends Omit<ContentCardProps, \"shape\" | \"chips\" | \"groupKinds\"> {\n /** Above the title: the post's channel or author; default its owner group's chip. */\n byline?: ReactNode;\n}\n\n/** A post in a feed: a wide cover, its title, when it was published and what unlocking it costs. */\nexport function PostCard({ card, href, onOpen, tiers, labels, byline, owner = true, ownerHref, decorate, children, className }: PostCardProps) {\n const m = useMessages();\n const url = href ? href(card) : card.path;\n const open = useCallback(() => onOpen?.(card), [onOpen, card]);\n const onClick = useLink(url, open);\n const lock = lockLabel(m, card.access, tiers, labels);\n const title = card.title || card.code;\n return (\n <article className={cn(\"grid gap-3 rounded-lg border border-border p-3\", className)} data-ckui=\"post-card\" data-id={card.id} data-locked={lock ? \"\" : undefined} lang={card.language || undefined}>\n {byline ?? (owner && card.owner && <OwnerChip group={card.owner} href={ownerHref} className=\"text-sm\" />)}\n <a href={url} onClick={onClick} className=\"grid gap-2\">\n <span className=\"font-medium break-words hover:underline\" data-ckui=\"card-title\">\n {title}\n </span>\n {card.cover.length > 0 && (\n <span className=\"relative block aspect-video overflow-hidden rounded-md bg-muted\">\n <RenditionImg outputs={card.cover} alt=\"\" fit=\"cover\" skeleton className={cn(\"size-full\", lock && \"blur-md\")} />\n <Decorations card={card} decorate={decorate} />\n {lock && (\n <span className=\"absolute inset-0 grid place-items-center\">\n <span className=\"inline-flex items-center gap-1 rounded-md bg-background/85 px-2 py-1 text-xs font-medium shadow-sm\" data-ckui=\"card-lock\">\n <HugeiconsIcon icon={LockIcon} strokeWidth={2} className=\"size-3.5\" aria-hidden />\n {lock}\n </span>\n </span>\n )}\n </span>\n )}\n </a>\n <p className=\"flex flex-wrap items-center gap-3 text-xs text-muted-foreground\">\n {card.published_at && <RelativeTime at={card.published_at} />}\n {!card.cover.length && lock && <span data-ckui=\"card-lock\">{lock}</span>}\n {card.counts.favorites !== undefined && (\n <span className=\"inline-flex items-center gap-1 tabular-nums\" data-ckui=\"card-counts\">\n <HugeiconsIcon icon={FavouriteIcon} strokeWidth={2} className={cn(\"size-3.5\", card.viewer?.favorited && \"fill-current text-primary\")} aria-hidden />\n <span className=\"sr-only\">{m.t(\"contents.favorites\")}</span>\n {compact(card.counts.favorites, m.language)}\n </span>\n )}\n </p>\n {children}\n </article>\n );\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"card.js","names":[],"sources":["../../../src/components/content/card.tsx"],"sourcesContent":["import { FavouriteIcon, LockIcon, ThumbsUpIcon } from \"@hugeicons/core-free-icons\";\nimport { HugeiconsIcon } from \"@hugeicons/react\";\nimport { cn } from \"cn\";\nimport { useCallback, useContext, useState, type CSSProperties, type MouseEvent, type ReactNode } from \"react\";\nimport type { Card, CardAccess, Chip as EntityChip } from \"../../client/generated/wire.js\";\nimport { useLanguageName, useMessages } from \"../../i18n/context.js\";\nimport type { Translator } from \"../../i18n/messages.js\";\nimport { ContentKitContext } from \"../../react/context.js\";\nimport { Badge } from \"#ckui/ui/badge\";\nimport { HoverPreview } from \"../hover-preview.js\";\nimport { RenditionImg } from \"../rendition-img.js\";\nimport { formatDate, RelativeTime } from \"../social/parts.js\";\nimport { GroupAvatar, GroupLink, labelOf, type GroupLike, type Labels } from \"../groups/parts.js\";\nimport { priceLabel } from \"./paywall.js\";\n\nexport interface ContentCardProps {\n card: Card;\n /** The card's link; default its canonical path. */\n href?: (card: Card) => string | undefined;\n /** Before the card's link is followed: a click signal. */\n onOpen?: (card: Card) => void;\n /** Cover shape: \"portrait\" (3:4, readers) or \"landscape\" (16:9, players). Default portrait. */\n shape?: \"portrait\" | \"landscape\";\n /** A CSS aspect ratio overriding shape, such as \"182 / 260\". */\n aspectRatio?: CSSProperties[\"aspectRatio\"];\n /** Place the title below the cover (default), or over its bottom gradient. */\n titlePosition?: \"below\" | \"cover\";\n /** Mount images and previews. False keeps the card's text and reserved cover space. */\n loadMedia?: boolean;\n /** The group kinds whose chips show, in order; default every kind the card names. */\n groupKinds?: readonly string[];\n /** Chips per group kind. Default 3. */\n chips?: number;\n /** Select which entity chips appear, before the per-kind chip limit. */\n filterEntity?: (entity: EntityChip, kind: string) => boolean;\n /** Bordered chips (default) or plain linked text. */\n entityStyle?: \"chips\" | \"text\";\n /** Metadata fields to show; omitted fields keep their defaults. */\n metadata?: CardMetadata;\n /** Show like and favorite totals. Default true. */\n showCounts?: boolean;\n /** Tiers the site sells, so a lock names them; others show as \"for sale\". */\n tiers?: readonly string[];\n /** Display names of kinds, traits and tiers by identifier. */\n labels?: Labels;\n /** Show the owner group (a channel) when the card has one; default true, false on that group's own feed. */\n owner?: boolean;\n /** The owner group's link; default its canonical path. */\n ownerHref?: (g: GroupLike) => string | undefined;\n /** Over the cover: the host's badges for the card, placed in the cover's box; clicks reach the card. */\n decorate?: (card: Card) => ReactNode;\n /** Below the meta line: the host's own. */\n children?: ReactNode;\n className?: string;\n}\n\nexport interface CardMetadata {\n languages?: boolean;\n /** True shows all traits; an array selects specific trait identifiers. */\n traits?: boolean | readonly string[];\n pages?: boolean;\n duration?: boolean;\n}\n\n/** The host's badges over a cover. */\nfunction Decorations({ card, decorate, aboveTitle }: { card: Card; decorate?: (card: Card) => ReactNode; aboveTitle?: boolean }) {\n const badges = decorate?.(card);\n if (badges == null || badges === false) return null;\n return (\n <span className={cn(\"pointer-events-none absolute inset-0\", aboveTitle && \"z-20\")} data-ckui=\"card-decorations\">\n {badges}\n </span>\n );\n}\n\nconst compact = (n: number, language?: string) => new Intl.NumberFormat(language, { notation: \"compact\", maximumFractionDigits: 1 }).format(n);\n\n/** Why a card is locked, in words (its price when it is on sale); null when it opens. */\nexport function lockLabel(m: Translator, a: CardAccess, tiers: readonly string[] = [], labels?: Labels): string | null {\n if (a.allowed) return null;\n if (a.unknown) return m.t(\"contents.unknownAccess\");\n const offer = a.offers?.[0];\n if (offer) return offer.target.kind === \"group\" && Number(offer.terms.amount) === 0 ? m.t(\"contents.joinFree\") : priceLabel(m, offer.terms);\n const tier = a.sell?.find((k) => tiers.includes(k));\n if (tier) return labelOf(labels, tier);\n if (a.sell?.some((k) => k.includes(\":group:\"))) return m.t(\"contents.members\");\n if (a.sell?.length) return m.t(\"contents.forSale\");\n return m.t(\"contents.locked\");\n}\n\n/** A link followed in-app through the provider's navigate. */\nfunction useLink(url: string | undefined, before?: () => void) {\n const navigate = useContext(ContentKitContext)?.navigate;\n return useCallback(\n (e: MouseEvent<HTMLAnchorElement>) => {\n before?.();\n if (!navigate || !url || e.defaultPrevented || e.button !== 0 || e.metaKey || e.ctrlKey || e.shiftKey || e.altKey) return;\n e.preventDefault();\n navigate(url);\n },\n [navigate, url, before],\n );\n}\n\n/** One content in a listing: cover (a video the reader opens previews over it on hover), title, version, groups, counts, the reader's progress and why it is locked; what its kind's locked view hides is absent. */\nexport function ContentCard({ card, href, onOpen, shape = \"portrait\", aspectRatio, titlePosition = \"below\", loadMedia = true, groupKinds, chips = 3, filterEntity, entityStyle = \"chips\", metadata, showCounts = true, tiers, labels, owner = true, ownerHref, decorate, children, className }: ContentCardProps) {\n const m = useMessages();\n const { t } = m;\n const languageName = useLanguageName();\n const url = href ? href(card) : card.path;\n const open = useCallback(() => onOpen?.(card), [onOpen, card]);\n const onClick = useLink(url, open);\n const lock = lockLabel(m, card.access, tiers, labels);\n const v = card.version;\n const progress = card.viewer && card.viewer.progress_max > 0 ? Math.min(1, card.viewer.progress / card.viewer.progress_max) : 0;\n const kinds = groupKinds ?? Object.keys(card.entities);\n const entities = kinds.flatMap((kind) => (card.entities[kind] ?? []).filter((entity) => !filterEntity || filterEntity(entity, kind)).slice(0, chips).map((entity) => ({ kind, entity })));\n const minutes = v.duration_ms ? Math.round(v.duration_ms / 60_000) : 0;\n const selectedTraits = metadata?.traits;\n const traits = selectedTraits === false ? [] : Array.isArray(selectedTraits) ? v.traits.filter((trait) => selectedTraits.includes(trait)) : v.traits;\n const meta = [\n ...(metadata?.languages === false ? [] : v.languages.map(languageName)),\n ...traits.map((x) => labelOf(labels, x)),\n metadata?.pages !== false && v.pages ? m.plural(\"contents.pages\", v.pages) : null,\n metadata?.duration !== false && minutes ? m.plural(\"contents.minutes\", minutes) : null,\n ].filter(Boolean);\n const title = card.title || card.code;\n const entityList = entities.length > 0 ? <ul className={cn(\"flex flex-wrap\", entityStyle === \"text\" ? \"gap-x-2 gap-y-1\" : \"gap-1\")} data-ckui=\"card-groups\">\n {entities.map(({ kind, entity }) => <li key={`${kind}:${entity.id}`} data-kind={kind}><Chip url={entity.path} name={entity.name || entity.slug} variant={entityStyle} /></li>)}\n </ul> : null;\n const titleLink = <a href={url} onClick={onClick} className={cn(\"font-medium break-words focus-visible:underline\", titlePosition === \"cover\" ? \"absolute inset-x-0 bottom-0 z-10 bg-linear-to-t from-black/90 via-black/60 to-transparent px-3 pt-10 pb-3 text-white hover:underline\" : \"hover:underline\")} data-ckui=\"card-title\">\n <span className=\"line-clamp-2\">{title}</span>\n {lock && <span className=\"sr-only\"> ({lock})</span>}\n </a>;\n const [article, setArticle] = useState<HTMLElement | null>(null);\n return (\n <article ref={setArticle} className={cn(\"group/card grid content-start gap-2\", className)} data-ckui=\"content-card\" data-id={card.id} data-locked={lock ? \"\" : undefined} lang={card.language || undefined}>\n <div className=\"relative overflow-hidden rounded-lg\" data-ckui=\"card-cover\">\n <a href={url} onClick={onClick} className=\"relative block overflow-hidden rounded-lg bg-muted\" tabIndex={-1} aria-hidden>\n <div data-ckui=\"card-cover-frame\" className={aspectRatio === undefined ? shape === \"landscape\" ? \"aspect-video\" : \"aspect-[3/4]\" : undefined} style={aspectRatio === undefined ? undefined : { aspectRatio }}>\n {loadMedia ? <RenditionImg\n outputs={card.cover}\n alt=\"\"\n fit=\"cover\"\n skeleton\n loading=\"lazy\"\n className=\"size-full transition-transform group-hover/card:scale-[1.02]\"\n fallback={<span className=\"grid size-full place-items-center text-2xl font-semibold text-muted-foreground\">{title.charAt(0).toUpperCase()}</span>}\n /> : <span className=\"block size-full bg-muted\" aria-hidden />}\n </div>\n {loadMedia && v.hls && <HoverPreview item={{ kind: card.kind, id: card.id, version: v.id }} dir={v.hls} duration={v.duration_ms ? v.duration_ms / 1000 : undefined} target={article} />}\n {lock && (\n <span className=\"absolute top-2 left-2 inline-flex items-center gap-1 rounded-md bg-background/85 px-1.5 py-0.5 text-xs font-medium text-foreground shadow-sm\" data-ckui=\"card-lock\">\n <HugeiconsIcon icon={LockIcon} strokeWidth={2} className=\"size-3.5\" aria-hidden />\n {lock}\n </span>\n )}\n {progress > 0 && (\n <span className={cn(\"absolute inset-x-0 bottom-0 h-1 bg-background/60\", titlePosition === \"cover\" && \"z-20\")} data-ckui=\"card-progress\">\n <span className=\"block h-full bg-primary\" style={{ width: `${Math.round(progress * 100)}%` }} />\n </span>\n )}\n </a>\n {titlePosition === \"cover\" && titleLink}\n {loadMedia && <Decorations card={card} decorate={decorate} aboveTitle={titlePosition === \"cover\"} />}\n </div>\n <div className=\"grid gap-1\">\n {titlePosition === \"below\" && titleLink}\n {entityStyle === \"text\" && entityList}\n {owner && card.owner && <OwnerChip group={card.owner} href={ownerHref} loadMedia={loadMedia} />}\n {meta.length > 0 && <p className=\"text-xs text-muted-foreground\">{meta.join(\" · \")}</p>}\n {card.viewer?.completed && (\n <Badge variant=\"secondary\" className=\"justify-self-start\">\n {t(\"contents.completed\")}\n </Badge>\n )}\n {!card.access.allowed && card.access.free_after && <p className=\"text-xs text-muted-foreground\">{t(\"contents.freeFrom\", { date: formatDate(m, card.access.free_after, false) })}</p>}\n {entityStyle === \"chips\" && entityList}\n {showCounts && (card.counts.favorites !== undefined || card.counts.likes !== undefined) && (\n <p className=\"flex items-center gap-3 text-xs text-muted-foreground tabular-nums\" data-ckui=\"card-counts\">\n {card.counts.favorites !== undefined && (\n <span className=\"inline-flex items-center gap-1\" title={t(\"contents.favorites\")}>\n <HugeiconsIcon icon={FavouriteIcon} strokeWidth={2} className={cn(\"size-3.5\", card.viewer?.favorited && \"fill-current text-primary\")} aria-hidden />\n <span className=\"sr-only\">{t(\"contents.favorites\")}</span>\n {compact(card.counts.favorites, m.language)}\n </span>\n )}\n {card.counts.likes !== undefined && (\n <span className=\"inline-flex items-center gap-1\" title={t(\"contents.likes\")}>\n <HugeiconsIcon icon={ThumbsUpIcon} strokeWidth={2} className=\"size-3.5\" aria-hidden />\n <span className=\"sr-only\">{t(\"contents.likes\")}</span>\n {compact(card.counts.likes, m.language)}\n </span>\n )}\n </p>\n )}\n {children}\n </div>\n </article>\n );\n}\n\n/** The group that owns a content (a channel): its avatar and name, linking to its page. */\nexport function OwnerChip({ group, href, className, loadMedia = true }: { group: GroupLike; href?: (g: GroupLike) => string | undefined; className?: string; loadMedia?: boolean }) {\n return (\n <span className={cn(\"flex min-w-0 text-xs text-muted-foreground\", className)} data-ckui=\"card-owner\" data-id={group.id}>\n <GroupLink group={group} href={href} className=\"inline-flex min-w-0 items-center gap-1.5 hover:text-foreground\">\n {loadMedia ? <GroupAvatar group={group} className=\"size-5 shrink-0 text-[0.625rem]\" /> : <span className=\"size-5 shrink-0 rounded-full bg-muted\" aria-hidden />}\n <span className=\"truncate\">{group.name || group.slug}</span>\n </GroupLink>\n </span>\n );\n}\n\nfunction Chip({ url, name, variant = \"chips\" }: { url?: string; name: string; variant?: \"chips\" | \"text\" }) {\n const onClick = useLink(url);\n const cls = variant === \"text\" ? \"text-sm text-muted-foreground\" : \"inline-block rounded-md border border-border px-1.5 py-0.5 text-xs text-muted-foreground\";\n return url ? (\n <a href={url} onClick={onClick} className={cn(cls, \"hover:text-foreground\", variant === \"text\" ? \"hover:underline\" : \"hover:bg-muted\")}>\n {name}\n </a>\n ) : (\n <span className={cls}>{name}</span>\n );\n}\n\nexport interface PostCardProps extends Omit<ContentCardProps, \"shape\" | \"aspectRatio\" | \"titlePosition\" | \"chips\" | \"groupKinds\" | \"filterEntity\" | \"entityStyle\" | \"metadata\"> {\n /** Above the title: the post's channel or author; default its owner group's chip. */\n byline?: ReactNode;\n}\n\n/** A post in a feed: a wide cover, its title, when it was published and what unlocking it costs. */\nexport function PostCard({ card, href, onOpen, tiers, labels, byline, owner = true, ownerHref, loadMedia = true, showCounts = true, decorate, children, className }: PostCardProps) {\n const m = useMessages();\n const url = href ? href(card) : card.path;\n const open = useCallback(() => onOpen?.(card), [onOpen, card]);\n const onClick = useLink(url, open);\n const lock = lockLabel(m, card.access, tiers, labels);\n const title = card.title || card.code;\n return (\n <article className={cn(\"grid gap-3 rounded-lg border border-border p-3\", className)} data-ckui=\"post-card\" data-id={card.id} data-locked={lock ? \"\" : undefined} lang={card.language || undefined}>\n {byline ?? (owner && card.owner && <OwnerChip group={card.owner} href={ownerHref} loadMedia={loadMedia} className=\"text-sm\" />)}\n <a href={url} onClick={onClick} className=\"grid gap-2\">\n <span className=\"font-medium break-words hover:underline\" data-ckui=\"card-title\">\n {title}\n </span>\n {card.cover.length > 0 && (\n <span className=\"relative block aspect-video overflow-hidden rounded-md bg-muted\">\n {loadMedia && <RenditionImg outputs={card.cover} alt=\"\" fit=\"cover\" skeleton loading=\"lazy\" className={cn(\"size-full\", lock && \"blur-md\")} />}\n {loadMedia && <Decorations card={card} decorate={decorate} />}\n {lock && (\n <span className=\"absolute inset-0 grid place-items-center\">\n <span className=\"inline-flex items-center gap-1 rounded-md bg-background/85 px-2 py-1 text-xs font-medium shadow-sm\" data-ckui=\"card-lock\">\n <HugeiconsIcon icon={LockIcon} strokeWidth={2} className=\"size-3.5\" aria-hidden />\n {lock}\n </span>\n </span>\n )}\n </span>\n )}\n </a>\n <p className=\"flex flex-wrap items-center gap-3 text-xs text-muted-foreground\">\n {card.published_at && <RelativeTime at={card.published_at} />}\n {!card.cover.length && lock && <span data-ckui=\"card-lock\">{lock}</span>}\n {showCounts && card.counts.favorites !== undefined && (\n <span className=\"inline-flex items-center gap-1 tabular-nums\" data-ckui=\"card-counts\">\n <HugeiconsIcon icon={FavouriteIcon} strokeWidth={2} className={cn(\"size-3.5\", card.viewer?.favorited && \"fill-current text-primary\")} aria-hidden />\n <span className=\"sr-only\">{m.t(\"contents.favorites\")}</span>\n {compact(card.counts.favorites, m.language)}\n </span>\n )}\n </p>\n {children}\n </article>\n );\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { DailyReleasesQuery } from '../../client/discovery.js';
|
|
2
|
+
import { CardListProps } from './grid.js';
|
|
3
|
+
export interface DailyReleasesProps extends Omit<CardListProps, "infinite" | "pageSize" | "renderCard" | "loadMedia"> {
|
|
4
|
+
/** One complete calendar window. Defaults to 10 days in the browser's time zone. */
|
|
5
|
+
query?: DailyReleasesQuery;
|
|
6
|
+
/** Cards initially revealed across the whole window, allocated newest first. Default 30. */
|
|
7
|
+
initialVisible?: number;
|
|
8
|
+
/** Additional cached cards revealed by a day's Show more button. Default 30. */
|
|
9
|
+
revealStep?: number;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* One metadata request for a calendar window, with no requests when a day is
|
|
13
|
+
* opened or expanded. Only revealed, visible cards mount images and previews.
|
|
14
|
+
*/
|
|
15
|
+
export declare function DailyReleases({ query, initialVisible, revealStep, ...p }: DailyReleasesProps): import('react').JSX.Element;
|