@openrails/contentkit-ui 0.98.5 → 0.99.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 +26 -0
- package/dist/client/content/comments.d.ts +4 -2
- package/dist/client/content/comments.js +10 -6
- package/dist/client/content/comments.js.map +1 -1
- package/dist/client/generated/routes.d.ts +28 -2
- package/dist/client/generated/routes.js +39 -2
- package/dist/client/generated/routes.js.map +1 -1
- package/dist/client/generated/wire.d.ts +85 -0
- package/dist/client/generated/wire.js.map +1 -1
- package/dist/client/media/client.d.ts +4 -0
- package/dist/client/media/client.js +8 -4
- package/dist/client/media/client.js.map +1 -1
- package/dist/client/media/queue.js +42 -26
- package/dist/client/media/queue.js.map +1 -1
- package/dist/client/media/rules.d.ts +6 -0
- package/dist/client/media/rules.js +64 -10
- package/dist/client/media/rules.js.map +1 -1
- package/dist/client/versions.d.ts +6 -2
- package/dist/client/versions.js +26 -0
- package/dist/client/versions.js.map +1 -1
- package/dist/components/admin/page-review.d.ts +13 -0
- package/dist/components/admin/page-review.js +216 -0
- package/dist/components/admin/page-review.js.map +1 -0
- package/dist/components/content/card.js +98 -103
- package/dist/components/content/card.js.map +1 -1
- package/dist/components/content/daily-releases.d.ts +8 -1
- package/dist/components/content/daily-releases.js +291 -133
- package/dist/components/content/daily-releases.js.map +1 -1
- package/dist/components/content/editors.js +216 -210
- package/dist/components/content/editors.js.map +1 -1
- package/dist/components/content/filter-dialog.d.ts +11 -0
- package/dist/components/content/filter-dialog.js +29 -0
- package/dist/components/content/filter-dialog.js.map +1 -0
- package/dist/components/content/filters.d.ts +10 -0
- package/dist/components/content/filters.js +5 -2
- package/dist/components/content/filters.js.map +1 -1
- package/dist/components/content/grid.js +19 -14
- package/dist/components/content/grid.js.map +1 -1
- package/dist/components/content/index.d.ts +2 -1
- package/dist/components/content/release-reveal.d.ts +5 -0
- package/dist/components/content/release-reveal.js +62 -0
- package/dist/components/content/release-reveal.js.map +1 -0
- package/dist/components/content/search.js +95 -107
- package/dist/components/content/search.js.map +1 -1
- package/dist/components/social/comments.d.ts +1 -1
- package/dist/components/social/comments.js +15 -15
- package/dist/components/social/comments.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.js +24 -22
- package/dist/locales/admin/de.js +23 -0
- package/dist/locales/admin/de.js.map +1 -1
- package/dist/locales/admin/en.d.ts +23 -0
- package/dist/locales/admin/en.js +23 -0
- package/dist/locales/admin/en.js.map +1 -1
- package/dist/locales/admin/es.js +23 -0
- package/dist/locales/admin/es.js.map +1 -1
- package/dist/locales/admin/ja.js +23 -0
- package/dist/locales/admin/ja.js.map +1 -1
- package/dist/locales/admin/ko.js +23 -0
- package/dist/locales/admin/ko.js.map +1 -1
- package/dist/locales/admin/zh.js +23 -0
- package/dist/locales/admin/zh.js.map +1 -1
- package/dist/locales/discovery/de.js +11 -0
- package/dist/locales/discovery/de.js.map +1 -1
- package/dist/locales/discovery/en.d.ts +11 -0
- package/dist/locales/discovery/en.js +11 -0
- package/dist/locales/discovery/en.js.map +1 -1
- package/dist/locales/discovery/es.js +11 -0
- package/dist/locales/discovery/es.js.map +1 -1
- package/dist/locales/discovery/ja.js +11 -0
- package/dist/locales/discovery/ja.js.map +1 -1
- package/dist/locales/discovery/ko.js +11 -0
- package/dist/locales/discovery/ko.js.map +1 -1
- package/dist/locales/discovery/zh.js +11 -0
- package/dist/locales/discovery/zh.js.map +1 -1
- package/dist/locales/en.d.ts +34 -0
- package/dist/locales/social/en.js +2 -2
- package/dist/locales/social/en.js.map +1 -1
- package/dist/react/comments.d.ts +2 -1
- package/dist/react/comments.js +10 -8
- package/dist/react/comments.js.map +1 -1
- package/dist/react/folder.js +39 -39
- package/dist/react/folder.js.map +1 -1
- package/dist/react/index.d.ts +1 -0
- package/dist/react/page-review.d.ts +14 -0
- package/dist/react/page-review.js +36 -0
- package/dist/react/page-review.js.map +1 -0
- package/dist/react/public.d.ts +3 -1
- package/dist/react/public.js +76 -72
- package/dist/react/public.js.map +1 -1
- package/dist/react/resources.d.ts +5 -13
- package/dist/react/resources.js +58 -49
- package/dist/react/resources.js.map +1 -1
- package/dist/react/use-resource.d.ts +1 -1
- package/dist/react/use-resource.js +23 -13
- package/dist/react/use-resource.js.map +1 -1
- package/dist/react/versions.js +70 -42
- package/dist/react/versions.js.map +1 -1
- package/dist/react.js +8 -7
- package/dist/styles.css +1 -1
- package/package.json +1 -1
|
@@ -11,10 +11,10 @@ import { priceLabel as p } from "./paywall.js";
|
|
|
11
11
|
import { useCallback as m, useContext as h, useState as g } from "react";
|
|
12
12
|
import { jsx as _, jsxs as v } from "react/jsx-runtime";
|
|
13
13
|
import { cn as y } from "cn";
|
|
14
|
-
import { FavouriteIcon as b, LockIcon as
|
|
15
|
-
import { HugeiconsIcon as
|
|
14
|
+
import { FavouriteIcon as b, LockIcon as ee, ThumbsUpIcon as x } from "@hugeicons/core-free-icons";
|
|
15
|
+
import { HugeiconsIcon as S } from "@hugeicons/react";
|
|
16
16
|
//#region src/components/content/card.tsx
|
|
17
|
-
function
|
|
17
|
+
function C({ card: e, decorate: t, aboveTitle: n }) {
|
|
18
18
|
let r = t?.(e);
|
|
19
19
|
return r == null || r === !1 ? null : /* @__PURE__ */ _("span", {
|
|
20
20
|
className: y("pointer-events-none absolute inset-0", n && "z-20"),
|
|
@@ -22,11 +22,11 @@ function w({ card: e, decorate: t, aboveTitle: n }) {
|
|
|
22
22
|
children: r
|
|
23
23
|
});
|
|
24
24
|
}
|
|
25
|
-
var
|
|
25
|
+
var w = (e, t) => new Intl.NumberFormat(t, {
|
|
26
26
|
notation: "compact",
|
|
27
27
|
maximumFractionDigits: 1
|
|
28
28
|
}).format(e);
|
|
29
|
-
function
|
|
29
|
+
function T(e, t, n = [], r) {
|
|
30
30
|
if (t.allowed) return null;
|
|
31
31
|
if (t.unknown) return e.t("contents.unknownAccess");
|
|
32
32
|
let i = t.offers?.[0];
|
|
@@ -34,7 +34,7 @@ function E(e, t, n = [], r) {
|
|
|
34
34
|
let a = t.sell?.find((e) => n.includes(e));
|
|
35
35
|
return a ? f(r, a) : t.sell?.some((e) => e.includes(":group:")) ? e.t("contents.members") : t.sell?.length ? e.t("contents.forSale") : e.t("contents.locked");
|
|
36
36
|
}
|
|
37
|
-
function
|
|
37
|
+
function E(e, t) {
|
|
38
38
|
let n = h(i)?.navigate;
|
|
39
39
|
return m((r) => {
|
|
40
40
|
t?.(), !(!n || !e || r.defaultPrevented || r.button !== 0 || r.metaKey || r.ctrlKey || r.shiftKey || r.altKey) && (r.preventDefault(), n(e));
|
|
@@ -44,77 +44,77 @@ function D(e, t) {
|
|
|
44
44
|
t
|
|
45
45
|
]);
|
|
46
46
|
}
|
|
47
|
-
function
|
|
48
|
-
let
|
|
47
|
+
function D({ card: i, client: c, href: u, onOpen: d, shape: p = "portrait", aspectRatio: h, titlePosition: D = "below", loadMedia: A = !0, groupKinds: j, chips: te = 3, filterEntity: M, entityStyle: N = "chips", entityLayout: ne = "inline", metadata: P, showCounts: re = !0, tiers: ie, labels: F, owner: ae = !0, ownerHref: oe, decorate: se, children: ce, className: le }) {
|
|
48
|
+
let I = r(), { presets: ue } = a({ client: c }), L = h ?? t(ue.find((e) => e.kind === i.kind && e.name === "cover")?.aspect), { t: R } = I, de = n(), z = u ? u(i) : i.path, B = E(z, m(() => d?.(i), [d, i])), V = T(I, i.access, ie, F), H = i.version, U = i.viewer?.completed ? 1 : i.viewer && i.viewer.progress_max > 0 ? Math.min(1, i.viewer.progress / i.viewer.progress_max) : 0, W = (j ?? Object.keys(i.entities)).map((e) => ({
|
|
49
49
|
kind: e,
|
|
50
|
-
entities: (i.entities[e] ?? []).filter((t) => !
|
|
51
|
-
})).filter(({ entities: e }) => e.length > 0),
|
|
52
|
-
...
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
].filter(Boolean),
|
|
50
|
+
entities: (i.entities[e] ?? []).filter((t) => !M || M(t, e)).slice(0, te)
|
|
51
|
+
})).filter(({ entities: e }) => e.length > 0), G = H.duration_ms ? Math.round(H.duration_ms / 6e4) : 0, K = P?.traits, q = K === !1 ? [] : Array.isArray(K) ? H.traits.filter((e) => K.includes(e)) : H.traits, J = [
|
|
52
|
+
...P?.languages === !1 ? [] : H.languages.map(de),
|
|
53
|
+
P?.pages !== !1 && H.pages ? I.plural("contents.pages", H.pages) : null,
|
|
54
|
+
P?.duration !== !1 && G ? I.plural("contents.minutes", G) : null
|
|
55
|
+
].filter(Boolean), Y = i.title || i.code, X = y("flex flex-wrap", N === "text" ? "gap-x-2 gap-y-1" : "gap-1"), Z = (e, t) => t.map((t) => /* @__PURE__ */ _("li", {
|
|
56
56
|
"data-kind": e,
|
|
57
|
-
children: /* @__PURE__ */ _(
|
|
57
|
+
children: /* @__PURE__ */ _(k, {
|
|
58
58
|
url: t.path,
|
|
59
59
|
name: t.name || t.slug,
|
|
60
|
-
variant:
|
|
60
|
+
variant: N
|
|
61
61
|
})
|
|
62
|
-
}, `${e}:${t.id}`)),
|
|
62
|
+
}, `${e}:${t.id}`)), Q = W.length > 0 ? ne === "rows" ? /* @__PURE__ */ _("div", {
|
|
63
63
|
className: "grid gap-1",
|
|
64
64
|
"data-ckui": "card-groups",
|
|
65
65
|
"data-layout": "rows",
|
|
66
|
-
children:
|
|
67
|
-
className:
|
|
68
|
-
"aria-label": f(
|
|
66
|
+
children: W.map(({ kind: e, entities: t }) => /* @__PURE__ */ _("ul", {
|
|
67
|
+
className: X,
|
|
68
|
+
"aria-label": f(F, e),
|
|
69
69
|
"data-ckui": "card-group-row",
|
|
70
70
|
"data-kind": e,
|
|
71
|
-
children:
|
|
71
|
+
children: Z(e, t)
|
|
72
72
|
}, e))
|
|
73
73
|
}) : /* @__PURE__ */ _("ul", {
|
|
74
|
-
className:
|
|
74
|
+
className: X,
|
|
75
75
|
"data-ckui": "card-groups",
|
|
76
76
|
"data-layout": "inline",
|
|
77
|
-
children:
|
|
78
|
-
}) : null,
|
|
79
|
-
href:
|
|
80
|
-
onClick:
|
|
81
|
-
className: y("text-lg leading-snug font-medium break-words focus-visible:underline sm:text-xl",
|
|
77
|
+
children: W.flatMap(({ kind: e, entities: t }) => Z(e, t))
|
|
78
|
+
}) : null, $ = /* @__PURE__ */ v("a", {
|
|
79
|
+
href: z,
|
|
80
|
+
onClick: B,
|
|
81
|
+
className: y("text-lg leading-snug font-medium break-words focus-visible:underline sm:text-xl", D === "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"),
|
|
82
82
|
"data-ckui": "card-title",
|
|
83
83
|
children: [/* @__PURE__ */ _("span", {
|
|
84
84
|
className: "line-clamp-2",
|
|
85
|
-
children:
|
|
86
|
-
}),
|
|
85
|
+
children: Y
|
|
86
|
+
}), V && /* @__PURE__ */ v("span", {
|
|
87
87
|
className: "sr-only",
|
|
88
88
|
children: [
|
|
89
89
|
" (",
|
|
90
|
-
|
|
90
|
+
V,
|
|
91
91
|
")"
|
|
92
92
|
]
|
|
93
93
|
})]
|
|
94
94
|
}), [fe, pe] = g(null);
|
|
95
95
|
return /* @__PURE__ */ v("article", {
|
|
96
96
|
ref: pe,
|
|
97
|
-
className: y("group/card grid content-start gap-2",
|
|
97
|
+
className: y("group/card grid content-start gap-2", le),
|
|
98
98
|
"data-ckui": "content-card",
|
|
99
99
|
"data-id": i.id,
|
|
100
|
-
"data-locked":
|
|
100
|
+
"data-locked": V ? "" : void 0,
|
|
101
101
|
lang: i.language || void 0,
|
|
102
102
|
children: [/* @__PURE__ */ v("div", {
|
|
103
103
|
className: "relative overflow-hidden rounded-lg",
|
|
104
104
|
"data-ckui": "card-cover",
|
|
105
105
|
children: [
|
|
106
106
|
/* @__PURE__ */ v("a", {
|
|
107
|
-
href:
|
|
108
|
-
onClick:
|
|
107
|
+
href: z,
|
|
108
|
+
onClick: B,
|
|
109
109
|
className: "relative block overflow-hidden rounded-lg bg-muted",
|
|
110
110
|
tabIndex: -1,
|
|
111
111
|
"aria-hidden": !0,
|
|
112
112
|
children: [
|
|
113
113
|
/* @__PURE__ */ _("div", {
|
|
114
114
|
"data-ckui": "card-cover-frame",
|
|
115
|
-
className:
|
|
116
|
-
style:
|
|
117
|
-
children:
|
|
115
|
+
className: L === void 0 ? p === "landscape" ? "aspect-video" : "aspect-[3/4]" : void 0,
|
|
116
|
+
style: L === void 0 ? void 0 : { aspectRatio: L },
|
|
117
|
+
children: A ? /* @__PURE__ */ _(e, {
|
|
118
118
|
outputs: i.cover,
|
|
119
119
|
alt: "",
|
|
120
120
|
fit: "cover",
|
|
@@ -123,93 +123,88 @@ function O({ card: i, client: c, href: u, onOpen: d, shape: p = "portrait", aspe
|
|
|
123
123
|
className: "size-full transition-transform group-hover/card:scale-[1.02]",
|
|
124
124
|
fallback: /* @__PURE__ */ _("span", {
|
|
125
125
|
className: "grid size-full place-items-center text-2xl font-semibold text-muted-foreground",
|
|
126
|
-
children:
|
|
126
|
+
children: Y.charAt(0).toUpperCase()
|
|
127
127
|
})
|
|
128
128
|
}) : /* @__PURE__ */ _("span", {
|
|
129
129
|
className: "block size-full bg-muted",
|
|
130
130
|
"aria-hidden": !0
|
|
131
131
|
})
|
|
132
132
|
}),
|
|
133
|
-
|
|
133
|
+
A && H.hls && /* @__PURE__ */ _(o, {
|
|
134
134
|
item: {
|
|
135
135
|
kind: i.kind,
|
|
136
136
|
id: i.id,
|
|
137
|
-
version:
|
|
137
|
+
version: H.id
|
|
138
138
|
},
|
|
139
|
-
dir:
|
|
140
|
-
duration:
|
|
139
|
+
dir: H.hls,
|
|
140
|
+
duration: H.duration_ms ? H.duration_ms / 1e3 : void 0,
|
|
141
141
|
target: fe
|
|
142
142
|
}),
|
|
143
|
-
|
|
143
|
+
V && /* @__PURE__ */ v("span", {
|
|
144
144
|
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",
|
|
145
145
|
"data-ckui": "card-lock",
|
|
146
|
-
children: [/* @__PURE__ */ _(
|
|
147
|
-
icon:
|
|
146
|
+
children: [/* @__PURE__ */ _(S, {
|
|
147
|
+
icon: ee,
|
|
148
148
|
strokeWidth: 2,
|
|
149
149
|
className: "size-3.5",
|
|
150
150
|
"aria-hidden": !0
|
|
151
|
-
}),
|
|
151
|
+
}), V]
|
|
152
152
|
}),
|
|
153
|
-
|
|
154
|
-
className: y("absolute inset-x-0 bottom-0 h-1 bg-background/60",
|
|
153
|
+
U > 0 && /* @__PURE__ */ _("span", {
|
|
154
|
+
className: y("absolute inset-x-0 bottom-0 h-1 bg-background/60", D === "cover" && "z-20"),
|
|
155
155
|
"data-ckui": "card-progress",
|
|
156
156
|
children: /* @__PURE__ */ _("span", {
|
|
157
157
|
className: "block h-full bg-primary",
|
|
158
|
-
style: { width: `${Math.round(
|
|
158
|
+
style: { width: `${Math.round(U * 100)}%` }
|
|
159
159
|
})
|
|
160
160
|
})
|
|
161
161
|
]
|
|
162
162
|
}),
|
|
163
|
-
|
|
164
|
-
|
|
163
|
+
D === "cover" && $,
|
|
164
|
+
A && /* @__PURE__ */ _(C, {
|
|
165
165
|
card: i,
|
|
166
|
-
decorate:
|
|
167
|
-
aboveTitle:
|
|
166
|
+
decorate: se,
|
|
167
|
+
aboveTitle: D === "cover"
|
|
168
168
|
})
|
|
169
169
|
]
|
|
170
170
|
}), /* @__PURE__ */ v("div", {
|
|
171
171
|
className: "grid gap-1",
|
|
172
172
|
children: [
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
173
|
+
D === "below" && $,
|
|
174
|
+
N === "text" && Q,
|
|
175
|
+
ae && i.owner && /* @__PURE__ */ _(O, {
|
|
176
176
|
group: i.owner,
|
|
177
|
-
href:
|
|
178
|
-
loadMedia:
|
|
177
|
+
href: oe,
|
|
178
|
+
loadMedia: A
|
|
179
179
|
}),
|
|
180
|
-
|
|
180
|
+
q.length > 0 && /* @__PURE__ */ _("div", {
|
|
181
181
|
className: "flex flex-wrap gap-1",
|
|
182
182
|
"data-ckui": "card-traits",
|
|
183
|
-
children:
|
|
183
|
+
children: q.map((e) => /* @__PURE__ */ _(s, {
|
|
184
184
|
variant: "outline",
|
|
185
185
|
className: "h-auto rounded-md text-sm text-muted-foreground",
|
|
186
186
|
"data-ckui": "card-trait",
|
|
187
187
|
"data-trait": e,
|
|
188
|
-
children: f(
|
|
188
|
+
children: f(F, e)
|
|
189
189
|
}, e))
|
|
190
190
|
}),
|
|
191
|
-
|
|
191
|
+
J.length > 0 && /* @__PURE__ */ _("p", {
|
|
192
192
|
className: "text-xs text-muted-foreground",
|
|
193
|
-
children:
|
|
194
|
-
}),
|
|
195
|
-
i.viewer?.completed && /* @__PURE__ */ _(s, {
|
|
196
|
-
variant: "secondary",
|
|
197
|
-
className: "justify-self-start",
|
|
198
|
-
children: z("contents.completed")
|
|
193
|
+
children: J.join(" · ")
|
|
199
194
|
}),
|
|
200
195
|
!i.access.allowed && i.access.free_after && /* @__PURE__ */ _("p", {
|
|
201
196
|
className: "text-xs text-muted-foreground",
|
|
202
|
-
children:
|
|
197
|
+
children: R("contents.freeFrom", { date: l(I, i.access.free_after, !1) })
|
|
203
198
|
}),
|
|
204
|
-
|
|
205
|
-
|
|
199
|
+
N === "chips" && Q,
|
|
200
|
+
re && (i.counts.favorites !== void 0 || i.counts.likes !== void 0) && /* @__PURE__ */ v("p", {
|
|
206
201
|
className: "flex items-center gap-3 text-xs text-muted-foreground tabular-nums",
|
|
207
202
|
"data-ckui": "card-counts",
|
|
208
203
|
children: [i.counts.favorites !== void 0 && /* @__PURE__ */ v("span", {
|
|
209
204
|
className: "inline-flex items-center gap-1",
|
|
210
|
-
title:
|
|
205
|
+
title: R("contents.favorites"),
|
|
211
206
|
children: [
|
|
212
|
-
/* @__PURE__ */ _(
|
|
207
|
+
/* @__PURE__ */ _(S, {
|
|
213
208
|
icon: b,
|
|
214
209
|
strokeWidth: 2,
|
|
215
210
|
className: y("size-3.5", i.viewer?.favorited && "fill-current text-primary"),
|
|
@@ -217,34 +212,34 @@ function O({ card: i, client: c, href: u, onOpen: d, shape: p = "portrait", aspe
|
|
|
217
212
|
}),
|
|
218
213
|
/* @__PURE__ */ _("span", {
|
|
219
214
|
className: "sr-only",
|
|
220
|
-
children:
|
|
215
|
+
children: R("contents.favorites")
|
|
221
216
|
}),
|
|
222
|
-
|
|
217
|
+
w(i.counts.favorites, I.language)
|
|
223
218
|
]
|
|
224
219
|
}), i.counts.likes !== void 0 && /* @__PURE__ */ v("span", {
|
|
225
220
|
className: "inline-flex items-center gap-1",
|
|
226
|
-
title:
|
|
221
|
+
title: R("contents.likes"),
|
|
227
222
|
children: [
|
|
228
|
-
/* @__PURE__ */ _(
|
|
229
|
-
icon:
|
|
223
|
+
/* @__PURE__ */ _(S, {
|
|
224
|
+
icon: x,
|
|
230
225
|
strokeWidth: 2,
|
|
231
226
|
className: "size-3.5",
|
|
232
227
|
"aria-hidden": !0
|
|
233
228
|
}),
|
|
234
229
|
/* @__PURE__ */ _("span", {
|
|
235
230
|
className: "sr-only",
|
|
236
|
-
children:
|
|
231
|
+
children: R("contents.likes")
|
|
237
232
|
}),
|
|
238
|
-
|
|
233
|
+
w(i.counts.likes, I.language)
|
|
239
234
|
]
|
|
240
235
|
})]
|
|
241
236
|
}),
|
|
242
|
-
|
|
237
|
+
ce
|
|
243
238
|
]
|
|
244
239
|
})]
|
|
245
240
|
});
|
|
246
241
|
}
|
|
247
|
-
function
|
|
242
|
+
function O({ group: e, href: t, className: n, loadMedia: r = !0 }) {
|
|
248
243
|
return /* @__PURE__ */ _("span", {
|
|
249
244
|
className: y("flex min-w-0 text-xs text-muted-foreground", n),
|
|
250
245
|
"data-ckui": "card-owner",
|
|
@@ -266,8 +261,8 @@ function k({ group: e, href: t, className: n, loadMedia: r = !0 }) {
|
|
|
266
261
|
})
|
|
267
262
|
});
|
|
268
263
|
}
|
|
269
|
-
function
|
|
270
|
-
let r =
|
|
264
|
+
function k({ url: e, name: t, variant: n = "chips" }) {
|
|
265
|
+
let r = E(e), i = n === "text" ? "text-sm text-muted-foreground" : "inline-block rounded-md border border-border px-1.5 py-0.5 text-sm text-muted-foreground";
|
|
271
266
|
return e ? /* @__PURE__ */ _("a", {
|
|
272
267
|
href: e,
|
|
273
268
|
onClick: r,
|
|
@@ -278,29 +273,29 @@ function A({ url: e, name: t, variant: n = "chips" }) {
|
|
|
278
273
|
children: t
|
|
279
274
|
});
|
|
280
275
|
}
|
|
281
|
-
function
|
|
282
|
-
let
|
|
276
|
+
function A({ card: t, href: n, onOpen: i, tiers: a, labels: o, byline: s, owner: l = !0, ownerHref: u, loadMedia: d = !0, showCounts: f = !0, decorate: p, children: h, className: g }) {
|
|
277
|
+
let x = r(), D = n ? n(t) : t.path, k = E(D, m(() => i?.(t), [i, t])), A = T(x, t.access, a, o), j = t.title || t.code;
|
|
283
278
|
return /* @__PURE__ */ v("article", {
|
|
284
279
|
className: y("grid gap-3 rounded-lg border border-border p-3", g),
|
|
285
280
|
"data-ckui": "post-card",
|
|
286
281
|
"data-id": t.id,
|
|
287
|
-
"data-locked":
|
|
282
|
+
"data-locked": A ? "" : void 0,
|
|
288
283
|
lang: t.language || void 0,
|
|
289
284
|
children: [
|
|
290
|
-
s ?? (l && t.owner && /* @__PURE__ */ _(
|
|
285
|
+
s ?? (l && t.owner && /* @__PURE__ */ _(O, {
|
|
291
286
|
group: t.owner,
|
|
292
287
|
href: u,
|
|
293
288
|
loadMedia: d,
|
|
294
289
|
className: "text-sm"
|
|
295
290
|
})),
|
|
296
291
|
/* @__PURE__ */ v("a", {
|
|
297
|
-
href:
|
|
298
|
-
onClick:
|
|
292
|
+
href: D,
|
|
293
|
+
onClick: k,
|
|
299
294
|
className: "grid gap-2",
|
|
300
295
|
children: [/* @__PURE__ */ _("span", {
|
|
301
296
|
className: "font-medium break-words hover:underline",
|
|
302
297
|
"data-ckui": "card-title",
|
|
303
|
-
children:
|
|
298
|
+
children: j
|
|
304
299
|
}), t.cover.length > 0 && /* @__PURE__ */ v("span", {
|
|
305
300
|
className: "relative block aspect-video overflow-hidden rounded-md bg-muted",
|
|
306
301
|
children: [
|
|
@@ -310,23 +305,23 @@ function j({ card: t, href: n, onOpen: i, tiers: a, labels: o, byline: s, owner:
|
|
|
310
305
|
fit: "cover",
|
|
311
306
|
skeleton: !0,
|
|
312
307
|
loading: "lazy",
|
|
313
|
-
className: y("size-full",
|
|
308
|
+
className: y("size-full", A && "blur-md")
|
|
314
309
|
}),
|
|
315
|
-
d && /* @__PURE__ */ _(
|
|
310
|
+
d && /* @__PURE__ */ _(C, {
|
|
316
311
|
card: t,
|
|
317
312
|
decorate: p
|
|
318
313
|
}),
|
|
319
|
-
|
|
314
|
+
A && /* @__PURE__ */ _("span", {
|
|
320
315
|
className: "absolute inset-0 grid place-items-center",
|
|
321
316
|
children: /* @__PURE__ */ v("span", {
|
|
322
317
|
className: "inline-flex items-center gap-1 rounded-md bg-background/85 px-2 py-1 text-xs font-medium shadow-sm",
|
|
323
318
|
"data-ckui": "card-lock",
|
|
324
|
-
children: [/* @__PURE__ */ _(
|
|
325
|
-
icon:
|
|
319
|
+
children: [/* @__PURE__ */ _(S, {
|
|
320
|
+
icon: ee,
|
|
326
321
|
strokeWidth: 2,
|
|
327
322
|
className: "size-3.5",
|
|
328
323
|
"aria-hidden": !0
|
|
329
|
-
}),
|
|
324
|
+
}), A]
|
|
330
325
|
})
|
|
331
326
|
})
|
|
332
327
|
]
|
|
@@ -336,15 +331,15 @@ function j({ card: t, href: n, onOpen: i, tiers: a, labels: o, byline: s, owner:
|
|
|
336
331
|
className: "flex flex-wrap items-center gap-3 text-xs text-muted-foreground",
|
|
337
332
|
children: [
|
|
338
333
|
t.published_at && /* @__PURE__ */ _(c, { at: t.published_at }),
|
|
339
|
-
!t.cover.length &&
|
|
334
|
+
!t.cover.length && A && /* @__PURE__ */ _("span", {
|
|
340
335
|
"data-ckui": "card-lock",
|
|
341
|
-
children:
|
|
336
|
+
children: A
|
|
342
337
|
}),
|
|
343
338
|
f && t.counts.favorites !== void 0 && /* @__PURE__ */ v("span", {
|
|
344
339
|
className: "inline-flex items-center gap-1 tabular-nums",
|
|
345
340
|
"data-ckui": "card-counts",
|
|
346
341
|
children: [
|
|
347
|
-
/* @__PURE__ */ _(
|
|
342
|
+
/* @__PURE__ */ _(S, {
|
|
348
343
|
icon: b,
|
|
349
344
|
strokeWidth: 2,
|
|
350
345
|
className: y("size-3.5", t.viewer?.favorited && "fill-current text-primary"),
|
|
@@ -352,9 +347,9 @@ function j({ card: t, href: n, onOpen: i, tiers: a, labels: o, byline: s, owner:
|
|
|
352
347
|
}),
|
|
353
348
|
/* @__PURE__ */ _("span", {
|
|
354
349
|
className: "sr-only",
|
|
355
|
-
children:
|
|
350
|
+
children: x.t("contents.favorites")
|
|
356
351
|
}),
|
|
357
|
-
|
|
352
|
+
w(t.counts.favorites, x.language)
|
|
358
353
|
]
|
|
359
354
|
})
|
|
360
355
|
]
|
|
@@ -364,6 +359,6 @@ function j({ card: t, href: n, onOpen: i, tiers: a, labels: o, byline: s, owner:
|
|
|
364
359
|
});
|
|
365
360
|
}
|
|
366
361
|
//#endregion
|
|
367
|
-
export {
|
|
362
|
+
export { D as ContentCard, O as OwnerChip, A as PostCard, T as lockLabel };
|
|
368
363
|
|
|
369
364
|
//# 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, useState, type CSSProperties, type MouseEvent, type ReactNode } from \"react\";\nimport type { Card, CardAccess, Chip as EntityChip } from \"../../client/generated/wire.js\";\nimport type { ContentKitClient } from \"../../client/client.js\";\nimport { ratio } from \"../../client/aspect.js\";\nimport { useLanguageName, useMessages } from \"../../i18n/context.js\";\nimport type { Translator } from \"../../i18n/messages.js\";\nimport { ContentKitContext } from \"../../react/context.js\";\nimport { usePresets } from \"../../react/public.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 /** Overrides the provider's client for this card's public media configuration. */\n client?: ContentKitClient;\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 /** Fallback cover shape when the server declares no preset aspect. Default portrait (3:4). */\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 /** One inline list (default), or a separate row for each group kind. */\n entityLayout?: \"inline\" | \"rows\";\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, client, href, onOpen, shape = \"portrait\", aspectRatio, titlePosition = \"below\", loadMedia = true, groupKinds, chips = 3, filterEntity, entityStyle = \"chips\", entityLayout = \"inline\", metadata, showCounts = true, tiers, labels, owner = true, ownerHref, decorate, children, className }: ContentCardProps) {\n const m = useMessages();\n const { presets } = usePresets({ client });\n const coverAspect = aspectRatio ?? ratio(presets.find((p) => p.kind === card.kind && p.name === \"cover\")?.aspect);\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 entityGroups = kinds.map((kind) => ({ kind, entities: (card.entities[kind] ?? []).filter((entity) => !filterEntity || filterEntity(entity, kind)).slice(0, chips) })).filter(({ entities }) => entities.length > 0);\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 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 entityClassName = cn(\"flex flex-wrap\", entityStyle === \"text\" ? \"gap-x-2 gap-y-1\" : \"gap-1\");\n const entityItems = (kind: string, entities: EntityChip[]) => entities.map((entity) => <li key={`${kind}:${entity.id}`} data-kind={kind}><Chip url={entity.path} name={entity.name || entity.slug} variant={entityStyle} /></li>);\n const entityList = entityGroups.length > 0 ? entityLayout === \"rows\" ? (\n <div className=\"grid gap-1\" data-ckui=\"card-groups\" data-layout=\"rows\">\n {entityGroups.map(({ kind, entities }) => <ul key={kind} className={entityClassName} aria-label={labelOf(labels, kind)} data-ckui=\"card-group-row\" data-kind={kind}>{entityItems(kind, entities)}</ul>)}\n </div>\n ) : (\n <ul className={entityClassName} data-ckui=\"card-groups\" data-layout=\"inline\">\n {entityGroups.flatMap(({ kind, entities }) => entityItems(kind, entities))}\n </ul>\n ) : null;\n const titleLink = <a href={url} onClick={onClick} className={cn(\"text-lg leading-snug font-medium break-words focus-visible:underline sm:text-xl\", 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={coverAspect === undefined ? shape === \"landscape\" ? \"aspect-video\" : \"aspect-[3/4]\" : undefined} style={coverAspect === undefined ? undefined : { aspectRatio: coverAspect }}>\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 {traits.length > 0 && <div className=\"flex flex-wrap gap-1\" data-ckui=\"card-traits\">\n {traits.map((trait) => <Badge key={trait} variant=\"outline\" className=\"h-auto rounded-md text-sm text-muted-foreground\" data-ckui=\"card-trait\" data-trait={trait}>{labelOf(labels, trait)}</Badge>)}\n </div>}\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-sm 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\" | \"entityLayout\" | \"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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"}
|
|
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 type { ContentKitClient } from \"../../client/client.js\";\nimport { ratio } from \"../../client/aspect.js\";\nimport { useLanguageName, useMessages } from \"../../i18n/context.js\";\nimport type { Translator } from \"../../i18n/messages.js\";\nimport { ContentKitContext } from \"../../react/context.js\";\nimport { usePresets } from \"../../react/public.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 /** Overrides the provider's client for this card's public media configuration. */\n client?: ContentKitClient;\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 /** Fallback cover shape when the server declares no preset aspect. Default portrait (3:4). */\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 /** One inline list (default), or a separate row for each group kind. */\n entityLayout?: \"inline\" | \"rows\";\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, client, href, onOpen, shape = \"portrait\", aspectRatio, titlePosition = \"below\", loadMedia = true, groupKinds, chips = 3, filterEntity, entityStyle = \"chips\", entityLayout = \"inline\", metadata, showCounts = true, tiers, labels, owner = true, ownerHref, decorate, children, className }: ContentCardProps) {\n const m = useMessages();\n const { presets } = usePresets({ client });\n const coverAspect = aspectRatio ?? ratio(presets.find((p) => p.kind === card.kind && p.name === \"cover\")?.aspect);\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?.completed ? 1 : 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 entityGroups = kinds.map((kind) => ({ kind, entities: (card.entities[kind] ?? []).filter((entity) => !filterEntity || filterEntity(entity, kind)).slice(0, chips) })).filter(({ entities }) => entities.length > 0);\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 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 entityClassName = cn(\"flex flex-wrap\", entityStyle === \"text\" ? \"gap-x-2 gap-y-1\" : \"gap-1\");\n const entityItems = (kind: string, entities: EntityChip[]) => entities.map((entity) => <li key={`${kind}:${entity.id}`} data-kind={kind}><Chip url={entity.path} name={entity.name || entity.slug} variant={entityStyle} /></li>);\n const entityList = entityGroups.length > 0 ? entityLayout === \"rows\" ? (\n <div className=\"grid gap-1\" data-ckui=\"card-groups\" data-layout=\"rows\">\n {entityGroups.map(({ kind, entities }) => <ul key={kind} className={entityClassName} aria-label={labelOf(labels, kind)} data-ckui=\"card-group-row\" data-kind={kind}>{entityItems(kind, entities)}</ul>)}\n </div>\n ) : (\n <ul className={entityClassName} data-ckui=\"card-groups\" data-layout=\"inline\">\n {entityGroups.flatMap(({ kind, entities }) => entityItems(kind, entities))}\n </ul>\n ) : null;\n const titleLink = <a href={url} onClick={onClick} className={cn(\"text-lg leading-snug font-medium break-words focus-visible:underline sm:text-xl\", 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={coverAspect === undefined ? shape === \"landscape\" ? \"aspect-video\" : \"aspect-[3/4]\" : undefined} style={coverAspect === undefined ? undefined : { aspectRatio: coverAspect }}>\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 {traits.length > 0 && <div className=\"flex flex-wrap gap-1\" data-ckui=\"card-traits\">\n {traits.map((trait) => <Badge key={trait} variant=\"outline\" className=\"h-auto rounded-md text-sm text-muted-foreground\" data-ckui=\"card-trait\" data-trait={trait}>{labelOf(labels, trait)}</Badge>)}\n </div>}\n {meta.length > 0 && <p className=\"text-xs text-muted-foreground\">{meta.join(\" · \")}</p>}\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-sm 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\" | \"entityLayout\" | \"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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"}
|
|
@@ -5,6 +5,13 @@ export interface DailyReleasesProps extends Omit<CardListProps, "infinite" | "pa
|
|
|
5
5
|
query?: DailyReleasesQuery;
|
|
6
6
|
/** Cards initially revealed across the whole window, allocated newest first. Default 30. */
|
|
7
7
|
initialVisible?: number;
|
|
8
|
+
/** Collapse locked tier previews per day; expansion never grants access. Default false. */
|
|
9
|
+
collapsePremium?: boolean;
|
|
10
|
+
/** Host-specific nouns; defaults use localized generic item labels. */
|
|
11
|
+
summaryLabels?: {
|
|
12
|
+
premium?: (count: number) => string;
|
|
13
|
+
filtered?: (count: number) => string;
|
|
14
|
+
};
|
|
8
15
|
/** Additional cached cards revealed by a day's Show more button. Default 30. */
|
|
9
16
|
revealStep?: number;
|
|
10
17
|
}
|
|
@@ -12,4 +19,4 @@ export interface DailyReleasesProps extends Omit<CardListProps, "infinite" | "pa
|
|
|
12
19
|
* One metadata request for a calendar window, with no requests when a day is
|
|
13
20
|
* opened or expanded. Only revealed, visible cards mount images and previews.
|
|
14
21
|
*/
|
|
15
|
-
export declare function DailyReleases({ query, initialVisible, revealStep, ...p }: DailyReleasesProps): import('react').JSX.Element;
|
|
22
|
+
export declare function DailyReleases({ query, initialVisible, revealStep, collapsePremium, summaryLabels, ...p }: DailyReleasesProps): import('react').JSX.Element;
|