@openrails/contentkit-ui 0.87.0-rc.1 → 0.88.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +18 -11
- package/dist/client/beacons.js +5 -1
- package/dist/client/beacons.js.map +1 -1
- package/dist/client/contents.d.ts +8 -6
- package/dist/client/contents.js +10 -7
- package/dist/client/contents.js.map +1 -1
- package/dist/client/errors.d.ts +15 -3
- package/dist/client/errors.js +40 -14
- package/dist/client/errors.js.map +1 -1
- package/dist/client/generated/routes.d.ts +1 -1
- package/dist/client/generated/routes.js +1 -1
- package/dist/client/generated/routes.js.map +1 -1
- package/dist/client/generated/wire.d.ts +12 -3
- package/dist/client/generated/wire.js.map +1 -1
- package/dist/client/http.js +27 -27
- package/dist/client/http.js.map +1 -1
- package/dist/client/index.d.ts +2 -2
- package/dist/client/media/client.d.ts +10 -4
- package/dist/client/media/client.js +33 -7
- package/dist/client/media/client.js.map +1 -1
- package/dist/client/media/rules.d.ts +1 -1
- package/dist/client/media/rules.js +6 -6
- package/dist/client/media/rules.js.map +1 -1
- package/dist/client/media/transport.d.ts +1 -1
- package/dist/client/media/transport.js +16 -16
- package/dist/client/media/transport.js.map +1 -1
- package/dist/client/public.d.ts +2 -2
- package/dist/client/public.js +2 -2
- package/dist/client/public.js.map +1 -1
- package/dist/client.js +25 -25
- package/dist/components/admin/content-manager.js +233 -232
- package/dist/components/admin/content-manager.js.map +1 -1
- package/dist/components/content/card.d.ts +1 -1
- package/dist/components/content/card.js +132 -120
- package/dist/components/content/card.js.map +1 -1
- package/dist/components/content/editors.d.ts +8 -0
- package/dist/components/content/editors.js +299 -229
- package/dist/components/content/editors.js.map +1 -1
- package/dist/components/content/index.d.ts +1 -1
- package/dist/components/content/paywall.js +61 -61
- package/dist/components/content/paywall.js.map +1 -1
- package/dist/i18n/messages.js +49 -46
- package/dist/i18n/messages.js.map +1 -1
- package/dist/index.js +11 -11
- package/dist/locales/de.js +2 -1
- package/dist/locales/de.js.map +1 -1
- package/dist/locales/en.d.ts +1 -0
- package/dist/locales/en.js +2 -1
- package/dist/locales/en.js.map +1 -1
- package/dist/locales/es.js +2 -1
- package/dist/locales/es.js.map +1 -1
- package/dist/locales/ja.js +2 -1
- package/dist/locales/ja.js.map +1 -1
- package/dist/locales/ko.js +2 -1
- package/dist/locales/ko.js.map +1 -1
- package/dist/locales/zh.js +2 -1
- package/dist/locales/zh.js.map +1 -1
- package/dist/react/contents.d.ts +13 -5
- package/dist/react/contents.js +163 -149
- package/dist/react/contents.js.map +1 -1
- package/dist/react/detail.d.ts +7 -1
- package/dist/react/detail.js +9 -6
- package/dist/react/detail.js.map +1 -1
- package/dist/react/index.d.ts +1 -1
- package/dist/react/public.js +17 -16
- package/dist/react/public.js.map +1 -1
- package/dist/react.js +8 -8
- package/package.json +1 -1
|
@@ -1,39 +1,40 @@
|
|
|
1
1
|
import { RenditionImg as e } from "../rendition-img.js";
|
|
2
2
|
import { useLanguageName as t, useMessages as n } from "../../i18n/context.js";
|
|
3
3
|
import { ContentKitContext as r } from "../../react/context.js";
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
11
|
-
import {
|
|
12
|
-
import {
|
|
4
|
+
import { HoverPreview as i } from "../hover-preview.js";
|
|
5
|
+
import { Badge as a } from "../../ui/badge.js";
|
|
6
|
+
import { RelativeTime as o, formatDate as s } from "../social/parts.js";
|
|
7
|
+
import { GroupAvatar as c, GroupLink as l, labelOf as u } from "../groups/parts.js";
|
|
8
|
+
import { priceLabel as d } from "./paywall.js";
|
|
9
|
+
import { useCallback as f, useContext as p, useState as m } from "react";
|
|
10
|
+
import { jsx as h, jsxs as g } from "react/jsx-runtime";
|
|
11
|
+
import { cn as _ } from "cn";
|
|
12
|
+
import { FavouriteIcon as v, LockIcon as y, ThumbsUpIcon as b } from "@hugeicons/core-free-icons";
|
|
13
|
+
import { HugeiconsIcon as x } from "@hugeicons/react";
|
|
13
14
|
//#region src/components/content/card.tsx
|
|
14
|
-
function
|
|
15
|
+
function S({ card: e, decorate: t }) {
|
|
15
16
|
let n = t?.(e);
|
|
16
|
-
return n == null || n === !1 ? null : /* @__PURE__ */
|
|
17
|
+
return n == null || n === !1 ? null : /* @__PURE__ */ h("span", {
|
|
17
18
|
className: "pointer-events-none absolute inset-0",
|
|
18
19
|
"data-ckui": "card-decorations",
|
|
19
20
|
children: n
|
|
20
21
|
});
|
|
21
22
|
}
|
|
22
|
-
var
|
|
23
|
+
var C = (e, t) => new Intl.NumberFormat(t, {
|
|
23
24
|
notation: "compact",
|
|
24
25
|
maximumFractionDigits: 1
|
|
25
26
|
}).format(e);
|
|
26
|
-
function
|
|
27
|
+
function w(e, t, n = [], r) {
|
|
27
28
|
if (t.allowed) return null;
|
|
28
29
|
if (t.unknown) return e.t("contents.unknownAccess");
|
|
29
30
|
let i = t.offers?.[0];
|
|
30
|
-
if (i) return i.target.kind === "group" && Number(i.terms.amount) === 0 ? e.t("contents.joinFree") :
|
|
31
|
+
if (i) return i.target.kind === "group" && Number(i.terms.amount) === 0 ? e.t("contents.joinFree") : d(e, i.terms);
|
|
31
32
|
let a = t.sell?.find((e) => n.includes(e));
|
|
32
|
-
return a ?
|
|
33
|
+
return a ? u(r, a) : t.sell?.some((e) => e.includes(":group:")) ? e.t("contents.members") : t.sell?.length ? e.t("contents.forSale") : e.t("contents.locked");
|
|
33
34
|
}
|
|
34
|
-
function
|
|
35
|
-
let n =
|
|
36
|
-
return
|
|
35
|
+
function T(e, t) {
|
|
36
|
+
let n = p(r)?.navigate;
|
|
37
|
+
return f((r) => {
|
|
37
38
|
t?.(), !(!n || !e || r.defaultPrevented || r.button !== 0 || r.metaKey || r.ctrlKey || r.shiftKey || r.altKey) && (r.preventDefault(), n(e));
|
|
38
39
|
}, [
|
|
39
40
|
n,
|
|
@@ -41,226 +42,237 @@ function C(e, t) {
|
|
|
41
42
|
t
|
|
42
43
|
]);
|
|
43
44
|
}
|
|
44
|
-
function
|
|
45
|
-
let
|
|
46
|
-
...
|
|
47
|
-
...
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
].filter(Boolean),
|
|
51
|
-
return /* @__PURE__ */
|
|
52
|
-
|
|
45
|
+
function E({ card: r, href: o, onOpen: c, shape: l = "portrait", groupKinds: d, chips: p = 3, tiers: E, labels: k, owner: A = !0, ownerHref: j, decorate: M, children: N, className: P }) {
|
|
46
|
+
let F = n(), { t: I } = F, L = t(), R = o ? o(r) : r.path, z = T(R, f(() => c?.(r), [c, r])), B = w(F, r.access, E, k), V = r.version, H = r.viewer && r.viewer.progress_max > 0 ? Math.min(1, r.viewer.progress / r.viewer.progress_max) : 0, U = d ?? Object.keys(r.groups), W = V.duration_ms ? Math.round(V.duration_ms / 6e4) : 0, G = [
|
|
47
|
+
...V.languages.map(L),
|
|
48
|
+
...V.traits.map((e) => u(k, e)),
|
|
49
|
+
V.pages ? F.plural("contents.pages", V.pages) : null,
|
|
50
|
+
W ? F.plural("contents.minutes", W) : null
|
|
51
|
+
].filter(Boolean), K = r.title || r.code, [q, J] = m(null);
|
|
52
|
+
return /* @__PURE__ */ g("article", {
|
|
53
|
+
ref: J,
|
|
54
|
+
className: _("group/card grid content-start gap-2", P),
|
|
53
55
|
"data-ckui": "content-card",
|
|
54
56
|
"data-id": r.id,
|
|
55
|
-
"data-locked":
|
|
57
|
+
"data-locked": B ? "" : void 0,
|
|
56
58
|
lang: r.language || void 0,
|
|
57
|
-
children: [/* @__PURE__ */
|
|
59
|
+
children: [/* @__PURE__ */ g("div", {
|
|
58
60
|
className: "relative overflow-hidden rounded-lg",
|
|
59
|
-
children: [/* @__PURE__ */
|
|
60
|
-
href:
|
|
61
|
-
onClick:
|
|
61
|
+
children: [/* @__PURE__ */ g("a", {
|
|
62
|
+
href: R,
|
|
63
|
+
onClick: z,
|
|
62
64
|
className: "relative block overflow-hidden rounded-lg bg-muted",
|
|
63
65
|
tabIndex: -1,
|
|
64
66
|
"aria-hidden": !0,
|
|
65
67
|
children: [
|
|
66
|
-
/* @__PURE__ */
|
|
67
|
-
className:
|
|
68
|
-
children: /* @__PURE__ */
|
|
68
|
+
/* @__PURE__ */ h("div", {
|
|
69
|
+
className: l === "landscape" ? "aspect-video" : "aspect-[3/4]",
|
|
70
|
+
children: /* @__PURE__ */ h(e, {
|
|
69
71
|
outputs: r.cover,
|
|
70
72
|
alt: "",
|
|
71
73
|
fit: "cover",
|
|
72
74
|
skeleton: !0,
|
|
73
75
|
className: "size-full transition-transform group-hover/card:scale-[1.02]",
|
|
74
|
-
fallback: /* @__PURE__ */
|
|
76
|
+
fallback: /* @__PURE__ */ h("span", {
|
|
75
77
|
className: "grid size-full place-items-center text-2xl font-semibold text-muted-foreground",
|
|
76
|
-
children:
|
|
78
|
+
children: K.charAt(0).toUpperCase()
|
|
77
79
|
})
|
|
78
80
|
})
|
|
79
81
|
}),
|
|
80
|
-
|
|
82
|
+
V.hls && /* @__PURE__ */ h(i, {
|
|
83
|
+
item: {
|
|
84
|
+
kind: r.kind,
|
|
85
|
+
id: r.id,
|
|
86
|
+
version: V.id
|
|
87
|
+
},
|
|
88
|
+
dir: V.hls,
|
|
89
|
+
duration: V.duration_ms ? V.duration_ms / 1e3 : void 0,
|
|
90
|
+
target: q
|
|
91
|
+
}),
|
|
92
|
+
B && /* @__PURE__ */ g("span", {
|
|
81
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",
|
|
82
94
|
"data-ckui": "card-lock",
|
|
83
|
-
children: [/* @__PURE__ */
|
|
84
|
-
icon:
|
|
95
|
+
children: [/* @__PURE__ */ h(x, {
|
|
96
|
+
icon: y,
|
|
85
97
|
strokeWidth: 2,
|
|
86
98
|
className: "size-3.5",
|
|
87
99
|
"aria-hidden": !0
|
|
88
|
-
}),
|
|
100
|
+
}), B]
|
|
89
101
|
}),
|
|
90
|
-
|
|
102
|
+
H > 0 && /* @__PURE__ */ h("span", {
|
|
91
103
|
className: "absolute inset-x-0 bottom-0 h-1 bg-background/60",
|
|
92
104
|
"data-ckui": "card-progress",
|
|
93
|
-
children: /* @__PURE__ */
|
|
105
|
+
children: /* @__PURE__ */ h("span", {
|
|
94
106
|
className: "block h-full bg-primary",
|
|
95
|
-
style: { width: `${Math.round(
|
|
107
|
+
style: { width: `${Math.round(H * 100)}%` }
|
|
96
108
|
})
|
|
97
109
|
})
|
|
98
110
|
]
|
|
99
|
-
}), /* @__PURE__ */
|
|
111
|
+
}), /* @__PURE__ */ h(S, {
|
|
100
112
|
card: r,
|
|
101
|
-
decorate:
|
|
113
|
+
decorate: M
|
|
102
114
|
})]
|
|
103
|
-
}), /* @__PURE__ */
|
|
115
|
+
}), /* @__PURE__ */ g("div", {
|
|
104
116
|
className: "grid gap-1",
|
|
105
117
|
children: [
|
|
106
|
-
/* @__PURE__ */
|
|
107
|
-
href:
|
|
108
|
-
onClick:
|
|
118
|
+
/* @__PURE__ */ g("a", {
|
|
119
|
+
href: R,
|
|
120
|
+
onClick: z,
|
|
109
121
|
className: "line-clamp-2 font-medium break-words hover:underline",
|
|
110
122
|
"data-ckui": "card-title",
|
|
111
|
-
children: [
|
|
123
|
+
children: [K, B && /* @__PURE__ */ g("span", {
|
|
112
124
|
className: "sr-only",
|
|
113
125
|
children: [
|
|
114
126
|
" (",
|
|
115
|
-
|
|
127
|
+
B,
|
|
116
128
|
")"
|
|
117
129
|
]
|
|
118
130
|
})]
|
|
119
131
|
}),
|
|
120
|
-
|
|
132
|
+
A && r.owner && /* @__PURE__ */ h(D, {
|
|
121
133
|
group: r.owner,
|
|
122
|
-
href:
|
|
134
|
+
href: j
|
|
123
135
|
}),
|
|
124
|
-
|
|
136
|
+
G.length > 0 && /* @__PURE__ */ h("p", {
|
|
125
137
|
className: "text-xs text-muted-foreground",
|
|
126
|
-
children:
|
|
138
|
+
children: G.join(" · ")
|
|
127
139
|
}),
|
|
128
|
-
r.viewer?.completed && /* @__PURE__ */
|
|
140
|
+
r.viewer?.completed && /* @__PURE__ */ h(a, {
|
|
129
141
|
variant: "secondary",
|
|
130
142
|
className: "justify-self-start",
|
|
131
|
-
children:
|
|
143
|
+
children: I("contents.completed")
|
|
132
144
|
}),
|
|
133
|
-
!r.access.allowed && r.access.free_after && /* @__PURE__ */
|
|
145
|
+
!r.access.allowed && r.access.free_after && /* @__PURE__ */ h("p", {
|
|
134
146
|
className: "text-xs text-muted-foreground",
|
|
135
|
-
children:
|
|
147
|
+
children: I("contents.freeFrom", { date: s(F, r.access.free_after, !1) })
|
|
136
148
|
}),
|
|
137
|
-
|
|
149
|
+
U.some((e) => r.groups[e]?.length) && /* @__PURE__ */ h("ul", {
|
|
138
150
|
className: "flex flex-wrap gap-1",
|
|
139
151
|
"data-ckui": "card-groups",
|
|
140
|
-
children:
|
|
152
|
+
children: U.flatMap((e) => (r.groups[e] ?? []).slice(0, p).map((t) => /* @__PURE__ */ h("li", {
|
|
141
153
|
"data-kind": e,
|
|
142
|
-
children: /* @__PURE__ */
|
|
154
|
+
children: /* @__PURE__ */ h(O, {
|
|
143
155
|
url: t.path,
|
|
144
156
|
name: t.name || t.slug
|
|
145
157
|
})
|
|
146
158
|
}, `${e}:${t.id}`)))
|
|
147
159
|
}),
|
|
148
|
-
(r.counts.favorites !== void 0 || r.counts.likes !== void 0) && /* @__PURE__ */
|
|
160
|
+
(r.counts.favorites !== void 0 || r.counts.likes !== void 0) && /* @__PURE__ */ g("p", {
|
|
149
161
|
className: "flex items-center gap-3 text-xs text-muted-foreground tabular-nums",
|
|
150
162
|
"data-ckui": "card-counts",
|
|
151
|
-
children: [r.counts.favorites !== void 0 && /* @__PURE__ */
|
|
163
|
+
children: [r.counts.favorites !== void 0 && /* @__PURE__ */ g("span", {
|
|
152
164
|
className: "inline-flex items-center gap-1",
|
|
153
|
-
title:
|
|
165
|
+
title: I("contents.favorites"),
|
|
154
166
|
children: [
|
|
155
|
-
/* @__PURE__ */
|
|
156
|
-
icon:
|
|
167
|
+
/* @__PURE__ */ h(x, {
|
|
168
|
+
icon: v,
|
|
157
169
|
strokeWidth: 2,
|
|
158
|
-
className:
|
|
170
|
+
className: _("size-3.5", r.viewer?.favorited && "fill-current text-primary"),
|
|
159
171
|
"aria-hidden": !0
|
|
160
172
|
}),
|
|
161
|
-
/* @__PURE__ */
|
|
173
|
+
/* @__PURE__ */ h("span", {
|
|
162
174
|
className: "sr-only",
|
|
163
|
-
children:
|
|
175
|
+
children: I("contents.favorites")
|
|
164
176
|
}),
|
|
165
|
-
|
|
177
|
+
C(r.counts.favorites, F.language)
|
|
166
178
|
]
|
|
167
|
-
}), r.counts.likes !== void 0 && /* @__PURE__ */
|
|
179
|
+
}), r.counts.likes !== void 0 && /* @__PURE__ */ g("span", {
|
|
168
180
|
className: "inline-flex items-center gap-1",
|
|
169
|
-
title:
|
|
181
|
+
title: I("contents.likes"),
|
|
170
182
|
children: [
|
|
171
|
-
/* @__PURE__ */
|
|
172
|
-
icon:
|
|
183
|
+
/* @__PURE__ */ h(x, {
|
|
184
|
+
icon: b,
|
|
173
185
|
strokeWidth: 2,
|
|
174
186
|
className: "size-3.5",
|
|
175
187
|
"aria-hidden": !0
|
|
176
188
|
}),
|
|
177
|
-
/* @__PURE__ */
|
|
189
|
+
/* @__PURE__ */ h("span", {
|
|
178
190
|
className: "sr-only",
|
|
179
|
-
children:
|
|
191
|
+
children: I("contents.likes")
|
|
180
192
|
}),
|
|
181
|
-
|
|
193
|
+
C(r.counts.likes, F.language)
|
|
182
194
|
]
|
|
183
195
|
})]
|
|
184
196
|
}),
|
|
185
|
-
|
|
197
|
+
N
|
|
186
198
|
]
|
|
187
199
|
})]
|
|
188
200
|
});
|
|
189
201
|
}
|
|
190
|
-
function
|
|
191
|
-
return /* @__PURE__ */
|
|
192
|
-
className:
|
|
202
|
+
function D({ group: e, href: t, className: n }) {
|
|
203
|
+
return /* @__PURE__ */ h("span", {
|
|
204
|
+
className: _("flex min-w-0 text-xs text-muted-foreground", n),
|
|
193
205
|
"data-ckui": "card-owner",
|
|
194
206
|
"data-id": e.id,
|
|
195
|
-
children: /* @__PURE__ */
|
|
207
|
+
children: /* @__PURE__ */ g(l, {
|
|
196
208
|
group: e,
|
|
197
209
|
href: t,
|
|
198
210
|
className: "inline-flex min-w-0 items-center gap-1.5 hover:text-foreground",
|
|
199
|
-
children: [/* @__PURE__ */
|
|
211
|
+
children: [/* @__PURE__ */ h(c, {
|
|
200
212
|
group: e,
|
|
201
213
|
className: "size-5 shrink-0 text-[0.625rem]"
|
|
202
|
-
}), /* @__PURE__ */
|
|
214
|
+
}), /* @__PURE__ */ h("span", {
|
|
203
215
|
className: "truncate",
|
|
204
216
|
children: e.name || e.slug
|
|
205
217
|
})]
|
|
206
218
|
})
|
|
207
219
|
});
|
|
208
220
|
}
|
|
209
|
-
function
|
|
210
|
-
let n =
|
|
211
|
-
return e ? /* @__PURE__ */
|
|
221
|
+
function O({ url: e, name: t }) {
|
|
222
|
+
let n = T(e), r = "inline-block rounded-md border border-border px-1.5 py-0.5 text-xs text-muted-foreground";
|
|
223
|
+
return e ? /* @__PURE__ */ h("a", {
|
|
212
224
|
href: e,
|
|
213
225
|
onClick: n,
|
|
214
|
-
className:
|
|
226
|
+
className: _(r, "hover:bg-muted hover:text-foreground"),
|
|
215
227
|
children: t
|
|
216
|
-
}) : /* @__PURE__ */
|
|
228
|
+
}) : /* @__PURE__ */ h("span", {
|
|
217
229
|
className: r,
|
|
218
230
|
children: t
|
|
219
231
|
});
|
|
220
232
|
}
|
|
221
|
-
function
|
|
222
|
-
let
|
|
223
|
-
return /* @__PURE__ */
|
|
224
|
-
className:
|
|
233
|
+
function k({ card: t, href: r, onOpen: i, tiers: a, labels: s, byline: c, owner: l = !0, ownerHref: u, decorate: d, children: p, className: m }) {
|
|
234
|
+
let b = n(), E = r ? r(t) : t.path, O = T(E, f(() => i?.(t), [i, t])), k = w(b, t.access, a, s), A = t.title || t.code;
|
|
235
|
+
return /* @__PURE__ */ g("article", {
|
|
236
|
+
className: _("grid gap-3 rounded-lg border border-border p-3", m),
|
|
225
237
|
"data-ckui": "post-card",
|
|
226
238
|
"data-id": t.id,
|
|
227
239
|
"data-locked": k ? "" : void 0,
|
|
228
240
|
lang: t.language || void 0,
|
|
229
241
|
children: [
|
|
230
|
-
c ?? (l && t.owner && /* @__PURE__ */
|
|
242
|
+
c ?? (l && t.owner && /* @__PURE__ */ h(D, {
|
|
231
243
|
group: t.owner,
|
|
232
244
|
href: u,
|
|
233
245
|
className: "text-sm"
|
|
234
246
|
})),
|
|
235
|
-
/* @__PURE__ */
|
|
236
|
-
href:
|
|
247
|
+
/* @__PURE__ */ g("a", {
|
|
248
|
+
href: E,
|
|
237
249
|
onClick: O,
|
|
238
250
|
className: "grid gap-2",
|
|
239
|
-
children: [/* @__PURE__ */
|
|
251
|
+
children: [/* @__PURE__ */ h("span", {
|
|
240
252
|
className: "font-medium break-words hover:underline",
|
|
241
253
|
"data-ckui": "card-title",
|
|
242
254
|
children: A
|
|
243
|
-
}), t.cover.length > 0 && /* @__PURE__ */
|
|
255
|
+
}), t.cover.length > 0 && /* @__PURE__ */ g("span", {
|
|
244
256
|
className: "relative block aspect-video overflow-hidden rounded-md bg-muted",
|
|
245
257
|
children: [
|
|
246
|
-
/* @__PURE__ */
|
|
258
|
+
/* @__PURE__ */ h(e, {
|
|
247
259
|
outputs: t.cover,
|
|
248
260
|
alt: "",
|
|
249
261
|
fit: "cover",
|
|
250
262
|
skeleton: !0,
|
|
251
|
-
className:
|
|
263
|
+
className: _("size-full", k && "blur-md")
|
|
252
264
|
}),
|
|
253
|
-
/* @__PURE__ */
|
|
265
|
+
/* @__PURE__ */ h(S, {
|
|
254
266
|
card: t,
|
|
255
|
-
decorate:
|
|
267
|
+
decorate: d
|
|
256
268
|
}),
|
|
257
|
-
k && /* @__PURE__ */
|
|
269
|
+
k && /* @__PURE__ */ h("span", {
|
|
258
270
|
className: "absolute inset-0 grid place-items-center",
|
|
259
|
-
children: /* @__PURE__ */
|
|
271
|
+
children: /* @__PURE__ */ g("span", {
|
|
260
272
|
className: "inline-flex items-center gap-1 rounded-md bg-background/85 px-2 py-1 text-xs font-medium shadow-sm",
|
|
261
273
|
"data-ckui": "card-lock",
|
|
262
|
-
children: [/* @__PURE__ */
|
|
263
|
-
icon:
|
|
274
|
+
children: [/* @__PURE__ */ h(x, {
|
|
275
|
+
icon: y,
|
|
264
276
|
strokeWidth: 2,
|
|
265
277
|
className: "size-3.5",
|
|
266
278
|
"aria-hidden": !0
|
|
@@ -270,38 +282,38 @@ function D({ card: t, href: r, onOpen: i, tiers: o, labels: s, byline: c, owner:
|
|
|
270
282
|
]
|
|
271
283
|
})]
|
|
272
284
|
}),
|
|
273
|
-
/* @__PURE__ */
|
|
285
|
+
/* @__PURE__ */ g("p", {
|
|
274
286
|
className: "flex flex-wrap items-center gap-3 text-xs text-muted-foreground",
|
|
275
287
|
children: [
|
|
276
|
-
t.published_at && /* @__PURE__ */
|
|
277
|
-
!t.cover.length && k && /* @__PURE__ */
|
|
288
|
+
t.published_at && /* @__PURE__ */ h(o, { at: t.published_at }),
|
|
289
|
+
!t.cover.length && k && /* @__PURE__ */ h("span", {
|
|
278
290
|
"data-ckui": "card-lock",
|
|
279
291
|
children: k
|
|
280
292
|
}),
|
|
281
|
-
t.counts.favorites !== void 0 && /* @__PURE__ */
|
|
293
|
+
t.counts.favorites !== void 0 && /* @__PURE__ */ g("span", {
|
|
282
294
|
className: "inline-flex items-center gap-1 tabular-nums",
|
|
283
295
|
"data-ckui": "card-counts",
|
|
284
296
|
children: [
|
|
285
|
-
/* @__PURE__ */
|
|
286
|
-
icon:
|
|
297
|
+
/* @__PURE__ */ h(x, {
|
|
298
|
+
icon: v,
|
|
287
299
|
strokeWidth: 2,
|
|
288
|
-
className:
|
|
300
|
+
className: _("size-3.5", t.viewer?.favorited && "fill-current text-primary"),
|
|
289
301
|
"aria-hidden": !0
|
|
290
302
|
}),
|
|
291
|
-
/* @__PURE__ */
|
|
303
|
+
/* @__PURE__ */ h("span", {
|
|
292
304
|
className: "sr-only",
|
|
293
|
-
children:
|
|
305
|
+
children: b.t("contents.favorites")
|
|
294
306
|
}),
|
|
295
|
-
|
|
307
|
+
C(t.counts.favorites, b.language)
|
|
296
308
|
]
|
|
297
309
|
})
|
|
298
310
|
]
|
|
299
311
|
}),
|
|
300
|
-
|
|
312
|
+
p
|
|
301
313
|
]
|
|
302
314
|
});
|
|
303
315
|
}
|
|
304
316
|
//#endregion
|
|
305
|
-
export {
|
|
317
|
+
export { E as ContentCard, D as OwnerChip, k as PostCard, w as lockLabel };
|
|
306
318
|
|
|
307
319
|
//# sourceMappingURL=card.js.map
|
|
@@ -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, 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 { 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, 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.groups);\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 return (\n <article 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 {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.groups[k]?.length) && (\n <ul className=\"flex flex-wrap gap-1\" data-ckui=\"card-groups\">\n {kinds.flatMap((k) =>\n (card.groups[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 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.groups);\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.groups[k]?.length) && (\n <ul className=\"flex flex-wrap gap-1\" data-ckui=\"card-groups\">\n {kinds.flatMap((k) =>\n (card.groups[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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"}
|
|
@@ -27,6 +27,14 @@ export declare function VersionsEditor({ content, media, ...p }: Common & {
|
|
|
27
27
|
content: Content;
|
|
28
28
|
media?: boolean;
|
|
29
29
|
}): import('react').JSX.Element | null;
|
|
30
|
+
/**
|
|
31
|
+
* A version's own cover, where its kind has covers: the cover upload its
|
|
32
|
+
* editors selected, else its first. Versions share no files.
|
|
33
|
+
*/
|
|
34
|
+
export declare function VersionCover({ content, version: v, ...p }: Common & {
|
|
35
|
+
content: Content;
|
|
36
|
+
version: Version;
|
|
37
|
+
}): import('react').JSX.Element | null;
|
|
30
38
|
/** A version's segments (chapters): page ranges with titles and release times. */
|
|
31
39
|
export declare function SegmentsEditor({ content, version, ...p }: Common & {
|
|
32
40
|
content: Content;
|