@openrails/contentkit-ui 0.99.2 → 0.100.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 +8 -2
- package/dist/client/generated/wire.d.ts +1 -0
- package/dist/client/generated/wire.js.map +1 -1
- package/dist/components/admin/group-manager.js +124 -117
- package/dist/components/admin/group-manager.js.map +1 -1
- package/dist/components/admin/user-comment-standing.js +8 -6
- package/dist/components/admin/user-comment-standing.js.map +1 -1
- package/dist/components/content/card.js +2 -2
- package/dist/components/content/card.js.map +1 -1
- package/dist/components/content/editors.d.ts +2 -2
- package/dist/components/content/editors.js +447 -328
- package/dist/components/content/editors.js.map +1 -1
- package/dist/components/content/filters.js +36 -18
- package/dist/components/content/filters.js.map +1 -1
- package/dist/components/content/grid.js +1 -1
- package/dist/components/content/grid.js.map +1 -1
- package/dist/components/groups/directory.js +13 -7
- package/dist/components/groups/directory.js.map +1 -1
- package/dist/components/groups/memberships.js +13 -7
- package/dist/components/groups/memberships.js.map +1 -1
- package/dist/components/rendition-img.js +73 -55
- package/dist/components/rendition-img.js.map +1 -1
- package/dist/components/social/moderation.js +14 -5
- package/dist/components/social/moderation.js.map +1 -1
- package/dist/react/read.d.ts +3 -2
- package/dist/react/read.js +68 -61
- package/dist/react/read.js.map +1 -1
- package/package.json +1 -1
|
@@ -100,13 +100,19 @@ function p(p) {
|
|
|
100
100
|
role: "status",
|
|
101
101
|
children: h("groups.empty")
|
|
102
102
|
}),
|
|
103
|
-
b.hasMore && /* @__PURE__ */
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
103
|
+
b.hasMore && /* @__PURE__ */ d("div", {
|
|
104
|
+
className: "grid justify-items-center gap-2",
|
|
105
|
+
children: [b.error && /* @__PURE__ */ u("p", {
|
|
106
|
+
role: "alert",
|
|
107
|
+
className: "text-destructive",
|
|
108
|
+
children: a(m, b.error)
|
|
109
|
+
}), /* @__PURE__ */ u(r, {
|
|
110
|
+
variant: "outline",
|
|
111
|
+
size: "sm",
|
|
112
|
+
disabled: b.loadingMore,
|
|
113
|
+
onClick: () => void b.loadMore(),
|
|
114
|
+
children: b.loadingMore ? h("groups.loading") : b.error ? h("common.retry") : h("groups.loadMore")
|
|
115
|
+
})]
|
|
110
116
|
})
|
|
111
117
|
]
|
|
112
118
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"directory.js","names":[],"sources":["../../../src/components/groups/directory.tsx"],"sourcesContent":["import { cn } from \"cn\";\nimport { useState, type ReactNode } from \"react\";\nimport type { ContentKitUiAppearance } from \"../../appearance.js\";\nimport type { ContentKitClient } from \"../../client/client.js\";\nimport { LETTERS } from \"../../client/group-fields.js\";\nimport type { GroupCard } from \"../../client/generated/wire.js\";\nimport { useMessages } from \"../../i18n/context.js\";\nimport { useGroups, type GroupSort } from \"../../react/groups.js\";\nimport { ContentKitUiRoot } from \"../../scope.js\";\nimport { Button } from \"#ckui/ui/button\";\nimport { Skeleton } from \"#ckui/ui/skeleton\";\nimport { contentError } from \"../social/parts.js\";\nimport { GroupCover, GroupLink, type GroupLike } from \"./parts.js\";\n\nexport interface GroupDirectoryProps {\n /** The group kind listed: tag, artist, series. */\n kind: string;\n /** Names, counts and paths in this language; default the provider's. */\n language?: string;\n /** Count contents of this kind only; default every kind. */\n contentKind?: string;\n /** Children of this group. */\n parent?: string;\n /** Groups scoped by this group (characters of a series). */\n scope?: string;\n /** Default \"name\". */\n sort?: GroupSort;\n /** The letter bucket shown, a-z or \"#\", null for every group. With onLetterChange the host keeps it (in its URL). */\n letter?: string | null;\n onLetterChange?: (letter: string | null) => void;\n /** Hide the A-Z bar. */\n letters?: boolean;\n /** \"list\" (names with counts, default) or \"grid\" (covers). */\n layout?: \"list\" | \"grid\";\n /** A group's link; default its canonical path. */\n href?: (group: GroupLike) => string | undefined;\n /** A group's entry instead of the default one. */\n renderGroup?: (group: GroupCard) => ReactNode;\n pageSize?: number;\n client?: ContentKitClient;\n className?: string;\n appearance?: ContentKitUiAppearance;\n}\n\n/** A directory of one kind's groups: A-Z buckets, names with content counts or covers, paged. */\nexport function GroupDirectory(p: GroupDirectoryProps) {\n const m = useMessages();\n const { t } = m;\n const [own, setOwn] = useState<string | null>(null);\n const letter = p.letter !== undefined ? p.letter : own;\n const choose = (l: string | null) => (p.onLetterChange ? p.onLetterChange(l) : setOwn(l));\n const list = useGroups(\n { kind: p.kind, language: p.language, contentKind: p.contentKind, parent: p.parent, scope: p.scope, sort: p.sort, letter: letter ?? undefined, pageSize: p.pageSize },\n { client: p.client },\n );\n const grid = p.layout === \"grid\";\n const count = (n: number) => new Intl.NumberFormat(m.language).format(n);\n return (\n <ContentKitUiRoot appearance={p.appearance} className={cn(\"grid gap-4 text-sm\", p.className)} data-ckui=\"group-directory\" data-kind={p.kind}>\n {p.letters !== false && (\n <nav aria-label={t(\"groups.byLetter\")} className=\"flex flex-wrap gap-1\" data-ckui=\"letters\">\n {[null, ...LETTERS].map((l) => (\n <Button\n key={l ?? \"all\"}\n size=\"xs\"\n variant={letter === l ? \"default\" : \"ghost\"}\n aria-pressed={letter === l}\n aria-label={l === null ? undefined : l === \"#\" ? t(\"groups.otherLetters\") : l.toUpperCase()}\n className=\"min-w-7\"\n onClick={() => choose(l)}\n >\n {l === null ? t(\"groups.all\") : l.toUpperCase()}\n </Button>\n ))}\n </nav>\n )}\n {list.loading && !list.items.length ? (\n <div className={grid ? \"grid grid-cols-[repeat(auto-fill,minmax(9rem,1fr))] gap-3\" : \"grid gap-2\"} aria-busy>\n {Array.from({ length: 6 }, (_, i) => (\n <Skeleton key={i} className={grid ? \"aspect-[3/4] w-full\" : \"h-6 w-48\"} />\n ))}\n </div>\n ) : list.error && !list.items.length ? (\n <div role=\"alert\" className=\"grid justify-items-start gap-2\">\n <p className=\"text-destructive\">{contentError(m, list.error)}</p>\n <Button size=\"sm\" variant=\"outline\" onClick={list.reload}>\n {t(\"common.retry\")}\n </Button>\n </div>\n ) : !list.items.length ? (\n <p className=\"text-muted-foreground\" role=\"status\">\n {t(\"groups.empty\")}\n </p>\n ) : (\n <ul className={grid ? \"grid grid-cols-[repeat(auto-fill,minmax(9rem,1fr))] gap-3\" : \"flex flex-wrap gap-2\"} data-ckui=\"groups\">\n {list.items.map((g) => (\n <li key={g.id} data-ckui=\"group\" data-slug={g.slug}>\n {p.renderGroup ? (\n p.renderGroup(g)\n ) : grid ? (\n <GroupLink group={g} href={p.href} className=\"group grid gap-1.5\">\n <GroupCover group={g} className=\"aspect-[3/4] w-full\" />\n <span className=\"font-medium break-words group-hover:underline\">{g.name || g.slug}</span>\n <span className=\"text-xs text-muted-foreground tabular-nums\">{m.plural(\"groups.items\", g.count)}</span>\n </GroupLink>\n ) : (\n <GroupLink group={g} href={p.href} className=\"inline-flex items-center gap-1.5 rounded-md border border-border px-2 py-1 hover:bg-muted\">\n <span className=\"break-words\">{g.name || g.slug}</span>\n <span className=\"text-xs text-muted-foreground tabular-nums\" aria-label={m.plural(\"groups.items\", g.count)}>\n {count(g.count)}\n </span>\n </GroupLink>\n )}\n </li>\n ))}\n </ul>\n )}\n {list.hasMore && (\n <
|
|
1
|
+
{"version":3,"file":"directory.js","names":[],"sources":["../../../src/components/groups/directory.tsx"],"sourcesContent":["import { cn } from \"cn\";\nimport { useState, type ReactNode } from \"react\";\nimport type { ContentKitUiAppearance } from \"../../appearance.js\";\nimport type { ContentKitClient } from \"../../client/client.js\";\nimport { LETTERS } from \"../../client/group-fields.js\";\nimport type { GroupCard } from \"../../client/generated/wire.js\";\nimport { useMessages } from \"../../i18n/context.js\";\nimport { useGroups, type GroupSort } from \"../../react/groups.js\";\nimport { ContentKitUiRoot } from \"../../scope.js\";\nimport { Button } from \"#ckui/ui/button\";\nimport { Skeleton } from \"#ckui/ui/skeleton\";\nimport { contentError } from \"../social/parts.js\";\nimport { GroupCover, GroupLink, type GroupLike } from \"./parts.js\";\n\nexport interface GroupDirectoryProps {\n /** The group kind listed: tag, artist, series. */\n kind: string;\n /** Names, counts and paths in this language; default the provider's. */\n language?: string;\n /** Count contents of this kind only; default every kind. */\n contentKind?: string;\n /** Children of this group. */\n parent?: string;\n /** Groups scoped by this group (characters of a series). */\n scope?: string;\n /** Default \"name\". */\n sort?: GroupSort;\n /** The letter bucket shown, a-z or \"#\", null for every group. With onLetterChange the host keeps it (in its URL). */\n letter?: string | null;\n onLetterChange?: (letter: string | null) => void;\n /** Hide the A-Z bar. */\n letters?: boolean;\n /** \"list\" (names with counts, default) or \"grid\" (covers). */\n layout?: \"list\" | \"grid\";\n /** A group's link; default its canonical path. */\n href?: (group: GroupLike) => string | undefined;\n /** A group's entry instead of the default one. */\n renderGroup?: (group: GroupCard) => ReactNode;\n pageSize?: number;\n client?: ContentKitClient;\n className?: string;\n appearance?: ContentKitUiAppearance;\n}\n\n/** A directory of one kind's groups: A-Z buckets, names with content counts or covers, paged. */\nexport function GroupDirectory(p: GroupDirectoryProps) {\n const m = useMessages();\n const { t } = m;\n const [own, setOwn] = useState<string | null>(null);\n const letter = p.letter !== undefined ? p.letter : own;\n const choose = (l: string | null) => (p.onLetterChange ? p.onLetterChange(l) : setOwn(l));\n const list = useGroups(\n { kind: p.kind, language: p.language, contentKind: p.contentKind, parent: p.parent, scope: p.scope, sort: p.sort, letter: letter ?? undefined, pageSize: p.pageSize },\n { client: p.client },\n );\n const grid = p.layout === \"grid\";\n const count = (n: number) => new Intl.NumberFormat(m.language).format(n);\n return (\n <ContentKitUiRoot appearance={p.appearance} className={cn(\"grid gap-4 text-sm\", p.className)} data-ckui=\"group-directory\" data-kind={p.kind}>\n {p.letters !== false && (\n <nav aria-label={t(\"groups.byLetter\")} className=\"flex flex-wrap gap-1\" data-ckui=\"letters\">\n {[null, ...LETTERS].map((l) => (\n <Button\n key={l ?? \"all\"}\n size=\"xs\"\n variant={letter === l ? \"default\" : \"ghost\"}\n aria-pressed={letter === l}\n aria-label={l === null ? undefined : l === \"#\" ? t(\"groups.otherLetters\") : l.toUpperCase()}\n className=\"min-w-7\"\n onClick={() => choose(l)}\n >\n {l === null ? t(\"groups.all\") : l.toUpperCase()}\n </Button>\n ))}\n </nav>\n )}\n {list.loading && !list.items.length ? (\n <div className={grid ? \"grid grid-cols-[repeat(auto-fill,minmax(9rem,1fr))] gap-3\" : \"grid gap-2\"} aria-busy>\n {Array.from({ length: 6 }, (_, i) => (\n <Skeleton key={i} className={grid ? \"aspect-[3/4] w-full\" : \"h-6 w-48\"} />\n ))}\n </div>\n ) : list.error && !list.items.length ? (\n <div role=\"alert\" className=\"grid justify-items-start gap-2\">\n <p className=\"text-destructive\">{contentError(m, list.error)}</p>\n <Button size=\"sm\" variant=\"outline\" onClick={list.reload}>\n {t(\"common.retry\")}\n </Button>\n </div>\n ) : !list.items.length ? (\n <p className=\"text-muted-foreground\" role=\"status\">\n {t(\"groups.empty\")}\n </p>\n ) : (\n <ul className={grid ? \"grid grid-cols-[repeat(auto-fill,minmax(9rem,1fr))] gap-3\" : \"flex flex-wrap gap-2\"} data-ckui=\"groups\">\n {list.items.map((g) => (\n <li key={g.id} data-ckui=\"group\" data-slug={g.slug}>\n {p.renderGroup ? (\n p.renderGroup(g)\n ) : grid ? (\n <GroupLink group={g} href={p.href} className=\"group grid gap-1.5\">\n <GroupCover group={g} className=\"aspect-[3/4] w-full\" />\n <span className=\"font-medium break-words group-hover:underline\">{g.name || g.slug}</span>\n <span className=\"text-xs text-muted-foreground tabular-nums\">{m.plural(\"groups.items\", g.count)}</span>\n </GroupLink>\n ) : (\n <GroupLink group={g} href={p.href} className=\"inline-flex items-center gap-1.5 rounded-md border border-border px-2 py-1 hover:bg-muted\">\n <span className=\"break-words\">{g.name || g.slug}</span>\n <span className=\"text-xs text-muted-foreground tabular-nums\" aria-label={m.plural(\"groups.items\", g.count)}>\n {count(g.count)}\n </span>\n </GroupLink>\n )}\n </li>\n ))}\n </ul>\n )}\n {list.hasMore && (\n <div className=\"grid justify-items-center gap-2\">\n {list.error && <p role=\"alert\" className=\"text-destructive\">{contentError(m, list.error)}</p>}\n <Button variant=\"outline\" size=\"sm\" disabled={list.loadingMore} onClick={() => void list.loadMore()}>\n {list.loadingMore ? t(\"groups.loading\") : list.error ? t(\"common.retry\") : t(\"groups.loadMore\")}\n </Button>\n </div>\n )}\n </ContentKitUiRoot>\n );\n}\n"],"mappings":"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"}
|
|
@@ -428,13 +428,19 @@ function B(n) {
|
|
|
428
428
|
className: "text-muted-foreground",
|
|
429
429
|
children: l("memberships.noMembers")
|
|
430
430
|
}),
|
|
431
|
-
f.hasMore && /* @__PURE__ */
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
431
|
+
f.hasMore && /* @__PURE__ */ j("div", {
|
|
432
|
+
className: "grid justify-items-center gap-2",
|
|
433
|
+
children: [f.error && /* @__PURE__ */ A("p", {
|
|
434
|
+
role: "alert",
|
|
435
|
+
className: "text-destructive",
|
|
436
|
+
children: _(c, f.error)
|
|
437
|
+
}), /* @__PURE__ */ A(a, {
|
|
438
|
+
variant: "outline",
|
|
439
|
+
size: "sm",
|
|
440
|
+
disabled: f.loadingMore,
|
|
441
|
+
onClick: () => void f.loadMore(),
|
|
442
|
+
children: f.loadingMore ? l("groups.loading") : f.error ? l("common.retry") : l("groups.loadMore")
|
|
443
|
+
})]
|
|
438
444
|
}),
|
|
439
445
|
/* @__PURE__ */ A(H, {
|
|
440
446
|
spec: d,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"memberships.js","names":[],"sources":["../../../src/components/groups/memberships.tsx"],"sourcesContent":["import { cn } from \"cn\";\nimport { useEffect, useId, useMemo, useRef, useState, type ReactNode } from \"react\";\nimport type { ContentKitUiAppearance } from \"../../appearance.js\";\nimport type { ContentKitClient } from \"../../client/client.js\";\nimport { fromLocalInput, toLocalInput } from \"../../client/group-fields.js\";\nimport type { ContentMemberships, GroupCard, GroupDetail, GroupKind, Membership } from \"../../client/generated/wire.js\";\nimport { useMessages } from \"../../i18n/context.js\";\nimport type { ContentKitErrorHandler } from \"../../react/context.js\";\nimport { useContentGroups, useGroupMembers, useKinds, type Member } from \"../../react/groups.js\";\nimport { ContentKitUiRoot } from \"../../scope.js\";\nimport { Badge } from \"#ckui/ui/badge\";\nimport { Button } from \"#ckui/ui/button\";\nimport { Input } from \"#ckui/ui/input\";\nimport { Label } from \"#ckui/ui/label\";\nimport { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from \"#ckui/ui/select\";\nimport { Skeleton } from \"#ckui/ui/skeleton\";\nimport { SortableList } from \"../sortable-list.js\";\nimport { contentError, ErrorLine, formatDate, useAction } from \"../social/parts.js\";\nimport { GroupPicker, labelOf, type Labels } from \"./parts.js\";\n\nconst NONE = \"__none__\";\n\n/** A version a membership may target. */\nexport interface VersionChoice {\n id: string;\n label: string;\n}\n\nexport interface MembershipEditorProps {\n /** The content whose memberships are edited, its versions' included. */\n content: string;\n /** Its kind: the group kinds it joins. */\n contentKind: string;\n /** Staff lookup, including internal classifications. */\n management?: boolean;\n /** Its versions, for version-level memberships (voice actors, version-only tags). */\n versions?: readonly VersionChoice[];\n /** Only these group kinds; default every kind its kind joins. */\n groupKinds?: readonly string[];\n labels?: Labels;\n /** Group names in this language; default the provider's. */\n language?: string;\n onSaved?: (saved: ContentMemberships) => void;\n client?: ContentKitClient;\n onError?: ContentKitErrorHandler;\n className?: string;\n appearance?: ContentKitUiAppearance;\n}\n\ntype Draft = Membership & { key: number };\n\nconst strip = ({ key: _key, ...m }: Draft): Membership => m;\nconst same = (a: Membership[], b: Membership[]) => JSON.stringify(a) === JSON.stringify(b);\n\n/**\n * Staff: a content's groups, per group kind: add and remove groups, and per\n * membership the version it targets, its role, its position in an ordered\n * group, its window and acceptance of a proposed one. Saved in one write per\n * content for the kinds shown.\n */\nexport function MembershipEditor(p: MembershipEditorProps) {\n const m = useMessages();\n const { t } = m;\n const { kinds, loading: kindsLoading } = useKinds({ client: p.client });\n const cg = useContentGroups(p.content, { language: p.language, client: p.client });\n const groupKinds = useMemo(() => p.groupKinds ?? kinds?.kinds[p.contentKind]?.entities ?? [], [p.groupKinds, kinds, p.contentKind]);\n const [picked, setPicked] = useState<ReadonlyMap<string, GroupCard>>(new Map());\n const cards = useMemo(() => new Map([...cg.entities, ...picked]), [cg.entities, picked]);\n const seq = useRef(0);\n const initial = useMemo(\n () => cg.memberships.filter((x) => groupKinds.includes(cg.entities.get(x.group_id ?? \"\")?.kind ?? \"\")).map((x) => ({ ...x, content_id: undefined })),\n [cg.memberships, cg.entities, groupKinds],\n );\n const [draft, setDraft] = useState<Draft[]>([]);\n const dirty = !same(draft.map(strip), initial);\n const dirtyRef = useRef(dirty);\n dirtyRef.current = dirty;\n useEffect(() => {\n if (!dirtyRef.current || !draft.length) setDraft(initial.map((x) => ({ ...x, key: ++seq.current })));\n // Server data replaces an untouched draft only.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [initial]);\n const save = useAction(\"membership.save\", p.onError);\n const [saved, setSaved] = useState(false);\n const change = (key: number, patch: Partial<Membership>) => {\n setSaved(false);\n setDraft((d) => d.map((x) => (x.key === key ? { ...x, ...patch } : x)));\n };\n const root = (children: ReactNode) => (\n <ContentKitUiRoot appearance={p.appearance} className={cn(\"grid gap-4 text-sm\", p.className)} data-ckui=\"membership-editor\">\n {children}\n </ContentKitUiRoot>\n );\n if (kindsLoading || (cg.loading && !cg.memberships.length)) return root(<Skeleton className=\"h-32 w-full\" />);\n if (cg.error && !cg.memberships.length)\n return root(\n <div role=\"alert\" className=\"grid justify-items-start gap-2\">\n <p className=\"text-destructive\">{contentError(m, cg.error)}</p>\n <Button size=\"sm\" variant=\"outline\" onClick={cg.reload}>\n {t(\"common.retry\")}\n </Button>\n </div>,\n );\n const versionLabel = (id: string) => p.versions?.find((v) => v.id === id)?.label ?? id.slice(0, 8);\n return root(\n <form\n className=\"grid gap-5\"\n onSubmit={(e) => {\n e.preventDefault();\n setSaved(false);\n void save.run(() => cg.set(draft.map(strip), [...groupKinds])).then((out) => {\n if (!out) return;\n setSaved(true);\n setDraft(out.memberships.filter((x) => groupKinds.includes(out.entities.find((g) => g.id === x.group_id)?.kind ?? \"\")).map((x) => ({ ...x, content_id: undefined, key: ++seq.current })));\n p.onSaved?.(out);\n });\n }}\n >\n {groupKinds.map((kind) => {\n const spec: GroupKind = kinds?.entity_kinds?.[kind] ?? {};\n const rows = draft.filter((x) => cards.get(x.group_id ?? \"\")?.kind === kind);\n const label = labelOf(p.labels, kind);\n return (\n <fieldset key={kind} className=\"grid gap-2\" data-ckui=\"membership-kind\" data-group-kind={kind}>\n <legend className=\"mb-1 font-medium\">{label}</legend>\n {rows.length > 0 && (\n <ul className=\"grid gap-2\">\n {rows.map((x) => (\n <MembershipRow\n key={x.key}\n m={x}\n card={cards.get(x.group_id ?? \"\")}\n spec={spec}\n labels={p.labels}\n versions={p.versions}\n versionLabel={versionLabel}\n onChange={(patch) => change(x.key, patch)}\n onRemove={() => {\n setSaved(false);\n setDraft((d) => d.filter((y) => y.key !== x.key));\n }}\n />\n ))}\n </ul>\n )}\n <GroupPicker\n management={p.management}\n kind={kind}\n language={p.language}\n label={t(\"memberships.add\", { kind: label })}\n exclude={rows.filter((x) => !x.version_id && !x.role).map((x) => x.group_id!)}\n client={p.client}\n onPick={(g) => {\n setSaved(false);\n setPicked((all) => new Map(all).set(g.id, g));\n setDraft((d) => [...d, { group_id: g.id, key: ++seq.current }]);\n }}\n />\n </fieldset>\n );\n })}\n {!groupKinds.length && <p className=\"text-muted-foreground\">{t(\"memberships.noKinds\")}</p>}\n <ErrorLine error={save.error} />\n <div className=\"flex items-center gap-3\">\n <Button type=\"submit\" size=\"sm\" disabled={save.pending || !dirty}>\n {save.pending ? t(\"common.saving\") : t(\"common.save\")}\n </Button>\n {dirty && (\n <Button type=\"button\" size=\"sm\" variant=\"ghost\" disabled={save.pending} onClick={() => setDraft(initial.map((x) => ({ ...x, key: ++seq.current })))}>\n {t(\"memberships.discard\")}\n </Button>\n )}\n {saved && !dirty && (\n <span role=\"status\" className=\"text-muted-foreground\">\n {t(\"memberships.saved\")}\n </span>\n )}\n </div>\n </form>,\n );\n}\n\nfunction MembershipRow({\n m: x,\n card,\n spec,\n labels,\n versions,\n versionLabel,\n onChange,\n onRemove,\n}: {\n m: Membership;\n card?: GroupCard;\n spec: GroupKind;\n labels?: Labels;\n versions?: readonly VersionChoice[];\n versionLabel: (id: string) => string;\n onChange: (patch: Partial<Membership>) => void;\n onRemove: () => void;\n}) {\n const { t } = useMessages();\n const id = useId();\n const name = card ? card.name || card.slug : (x.group_id ?? \"\");\n const versionIds = [...new Set([...(versions ?? []).map((v) => v.id), ...(x.version_id ? [x.version_id] : [])])];\n return (\n <li className=\"flex flex-wrap items-center gap-2 rounded-md border border-border p-2\" data-ckui=\"membership\" data-group={card?.slug} data-state={x.state ?? \"active\"}>\n <span className=\"min-w-0 flex-1 font-medium break-words\">{name}</span>\n {x.state === \"proposed\" && (\n <>\n <Badge variant=\"secondary\">{t(\"memberships.proposed\")}</Badge>\n <Button type=\"button\" size=\"xs\" variant=\"outline\" onClick={() => onChange({ state: \"active\" })}>\n {t(\"memberships.accept\")}\n </Button>\n </>\n )}\n {spec.version_level && versionIds.length > 0 && (\n <Select value={x.version_id ?? NONE} onValueChange={(v) => onChange({ version_id: v === NONE ? undefined : String(v) })}>\n <SelectTrigger size=\"sm\" aria-label={t(\"memberships.versionOf\", { name })}>\n <SelectValue>{(v: string) => (v === NONE ? t(\"memberships.wholeContent\") : versionLabel(v))}</SelectValue>\n </SelectTrigger>\n <SelectContent>\n <SelectItem value={NONE}>{t(\"memberships.wholeContent\")}</SelectItem>\n {versionIds.map((v) => (\n <SelectItem key={v} value={v}>\n {versionLabel(v)}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n )}\n {!!spec.roles?.length && (\n <Select value={x.role || NONE} onValueChange={(v) => onChange({ role: v === NONE ? undefined : String(v) })}>\n <SelectTrigger size=\"sm\" aria-label={t(\"memberships.roleOf\", { name })}>\n <SelectValue>{(v: string) => (v === NONE ? t(\"memberships.noRole\") : labelOf(labels, v))}</SelectValue>\n </SelectTrigger>\n <SelectContent>\n <SelectItem value={NONE}>{t(\"memberships.noRole\")}</SelectItem>\n {spec.roles.map((r) => (\n <SelectItem key={r} value={r}>\n {labelOf(labels, r)}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n )}\n {spec.ordered && (\n <div className=\"flex items-center gap-1\">\n <Label htmlFor={`${id}-pos`} className=\"text-xs text-muted-foreground\">\n {t(\"memberships.position\")}\n </Label>\n <Input\n id={`${id}-pos`}\n className=\"h-8 w-20\"\n type=\"number\"\n min={0}\n step={1}\n value={x.position ?? \"\"}\n placeholder={t(\"memberships.last\")}\n onChange={(e) => onChange({ position: e.target.value === \"\" ? undefined : Math.max(0, Math.trunc(Number(e.target.value))) })}\n />\n </div>\n )}\n {spec.windows && <WindowFields from={x.active_from} until={x.active_until} name={name} onChange={onChange} />}\n <Button type=\"button\" size=\"xs\" variant=\"ghost\" aria-label={t(\"memberships.remove\", { name })} onClick={onRemove}>\n {t(\"common.remove\")}\n </Button>\n </li>\n );\n}\n\nfunction WindowFields({ from, until, name, onChange }: { from?: string; until?: string; name: string; onChange: (patch: Partial<Membership>) => void }) {\n const { t } = useMessages();\n const id = useId();\n return (\n <div className=\"flex flex-wrap items-center gap-1\" data-ckui=\"membership-window\">\n <Label htmlFor={`${id}-from`} className=\"text-xs text-muted-foreground\">\n {t(\"memberships.from\")}\n </Label>\n <Input\n id={`${id}-from`}\n className=\"h-8 w-48\"\n type=\"datetime-local\"\n aria-label={t(\"memberships.fromOf\", { name })}\n value={toLocalInput(from)}\n onChange={(e) => onChange({ active_from: fromLocalInput(e.target.value) })}\n />\n <Label htmlFor={`${id}-until`} className=\"text-xs text-muted-foreground\">\n {t(\"memberships.until\")}\n </Label>\n <Input\n id={`${id}-until`}\n className=\"h-8 w-48\"\n type=\"datetime-local\"\n aria-label={t(\"memberships.untilOf\", { name })}\n value={toLocalInput(until)}\n onChange={(e) => onChange({ active_until: fromLocalInput(e.target.value) })}\n />\n </div>\n );\n}\n\nexport interface GroupMembersProps {\n group: Pick<GroupDetail, \"id\" | \"kind\" | \"name\" | \"slug\" | \"cover\">;\n labels?: Labels;\n /** One member, e.g. a link with its title; default its content id. */\n renderContent?: (member: Membership) => ReactNode;\n /** Select a member's cover as the group's. */\n onUseCover?: (contentId: string) => Promise<unknown>;\n pageSize?: number;\n client?: ContentKitClient;\n onError?: ContentKitErrorHandler;\n className?: string;\n appearance?: ContentKitUiAppearance;\n}\n\nconst refKey = (x: Membership) => `${x.content_id}|${x.version_id ?? \"\"}`;\n\n/**\n * Staff: a group's members in member order: add by content (and version),\n * remove, reorder an ordered group, edit windows, accept proposed members,\n * and use a member's cover as the group's.\n */\nexport function GroupMembers(p: GroupMembersProps) {\n const m = useMessages();\n const { t } = m;\n const { kinds } = useKinds({ client: p.client });\n const spec: GroupKind = kinds?.entity_kinds?.[p.group.kind] ?? {};\n const members = useGroupMembers(p.group.id, { pageSize: p.pageSize, client: p.client });\n const save = useAction(\"membership.save\", p.onError);\n const [editing, setEditing] = useState<string | null>(null);\n const [win, setWin] = useState<{ from?: string; until?: string }>({});\n const describe = (x: Membership) => (p.renderContent ? p.renderContent(x) : <span className=\"font-mono text-xs break-all\">{x.content_id}</span>);\n const spoken = (x: Member) => `${x.content_id}${x.version_id ? ` ${x.version_id}` : \"\"}`;\n // Every role of one member shares its place: order unique content and version pairs.\n const order = (items: Member[]) => [...new Map(items.map((x) => [refKey(x), { content_id: x.content_id!, version_id: x.version_id }])).values()];\n const strip = ({ id: _id, ...x }: Member): Membership => x;\n const row = (x: Member, handle?: ReactNode) => (\n <div className=\"flex flex-wrap items-center gap-2\" data-ckui=\"group-member\" data-content={x.content_id} data-state={x.state ?? \"active\"}>\n {handle}\n {spec.ordered && x.position !== undefined && <span className=\"w-8 text-xs text-muted-foreground tabular-nums\">{x.position}</span>}\n <span className=\"min-w-0 flex-1\">{describe(x)}</span>\n {x.version_id && <Badge variant=\"outline\">{t(\"memberships.version\")}</Badge>}\n {x.role && <Badge variant=\"secondary\">{labelOf(p.labels, x.role)}</Badge>}\n {x.state === \"proposed\" && (\n <>\n <Badge variant=\"secondary\">{t(\"memberships.proposed\")}</Badge>\n <Button size=\"xs\" variant=\"outline\" disabled={save.pending} onClick={() => void save.run(() => members.add([{ ...strip(x), state: \"active\" }]))}>\n {t(\"memberships.accept\")}\n </Button>\n </>\n )}\n {spec.windows &&\n (editing === x.id ? (\n <span className=\"flex flex-wrap items-center gap-1\">\n <WindowFields from={win.from} until={win.until} name={spoken(x)} onChange={(w) => setWin((cur) => ({ from: \"active_from\" in w ? w.active_from : cur.from, until: \"active_until\" in w ? w.active_until : cur.until }))} />\n <Button\n size=\"xs\"\n disabled={save.pending}\n onClick={() =>\n void save.run(() => members.add([{ ...strip(x), active_from: win.from, active_until: win.until }])).then((d) => d !== undefined && setEditing(null))\n }\n >\n {t(\"common.save\")}\n </Button>\n <Button size=\"xs\" variant=\"ghost\" onClick={() => setEditing(null)}>\n {t(\"common.cancel\")}\n </Button>\n </span>\n ) : (\n <>\n <span className=\"text-xs text-muted-foreground\" data-ckui=\"member-window\">\n {x.active_from || x.active_until\n ? t(\"memberships.window\", { from: x.active_from ? formatDate(m, x.active_from) : \"…\", until: x.active_until ? formatDate(m, x.active_until) : \"…\" })\n : t(\"memberships.always\")}\n </span>\n <Button\n size=\"xs\"\n variant=\"ghost\"\n onClick={() => {\n setWin({ from: x.active_from, until: x.active_until });\n setEditing(x.id);\n }}\n >\n {t(\"memberships.editWindow\")}\n </Button>\n </>\n ))}\n {p.onUseCover && !x.version_id && (\n <Button size=\"xs\" variant=\"ghost\" disabled={save.pending || (p.group.cover?.content_id === x.content_id && !p.group.cover?.auto)} onClick={() => void save.run(() => p.onUseCover!(x.content_id!))}>\n {t(\"memberships.useCover\")}\n </Button>\n )}\n <Button size=\"xs\" variant=\"ghost\" disabled={save.pending} aria-label={t(\"memberships.remove\", { name: spoken(x) })} onClick={() => void save.run(() => members.remove([strip(x)]))}>\n {t(\"common.remove\")}\n </Button>\n </div>\n );\n return (\n <ContentKitUiRoot appearance={p.appearance} className={cn(\"grid gap-3 text-sm\", p.className)} data-ckui=\"group-members\">\n <h3 className=\"font-medium\">{t(\"memberships.members\")}</h3>\n {members.loading && !members.items.length ? (\n <Skeleton className=\"h-20 w-full\" />\n ) : members.error && !members.items.length ? (\n <div role=\"alert\" className=\"grid justify-items-start gap-2\">\n <p className=\"text-destructive\">{contentError(m, members.error)}</p>\n <Button size=\"sm\" variant=\"outline\" onClick={members.reload}>\n {t(\"common.retry\")}\n </Button>\n </div>\n ) : !members.items.length ? (\n <p className=\"text-muted-foreground\">{t(\"memberships.noMembers\")}</p>\n ) : spec.ordered ? (\n <SortableList\n items={members.items}\n id={(x) => x.id}\n name={spoken}\n label={t(\"memberships.members\")}\n disabled={save.pending}\n onMove={(from, to) => {\n const items = [...members.items];\n const [moved] = items.splice(from, 1);\n items.splice(to, 0, moved!);\n void save.run(() => members.reorder(order(items)));\n }}\n >\n {(x, handle) => row(x, handle)}\n </SortableList>\n ) : (\n <ul className=\"grid divide-y divide-border rounded-lg border border-border\">\n {members.items.map((x) => (\n <li key={x.id} className=\"p-2\">\n {row(x)}\n </li>\n ))}\n </ul>\n )}\n {members.hasMore && (\n <Button variant=\"outline\" size=\"sm\" className=\"justify-self-center\" disabled={members.loadingMore} onClick={() => void members.loadMore()}>\n {t(\"groups.loadMore\")}\n </Button>\n )}\n <AddMember spec={spec} labels={p.labels} onAdd={(x) => save.run(() => members.add([x]))} />\n <ErrorLine error={save.error} />\n </ContentKitUiRoot>\n );\n}\n\nconst ID = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/;\n\nfunction AddMember({ spec, labels, onAdd }: { spec: GroupKind; labels?: Labels; onAdd: (m: Membership) => Promise<unknown> }) {\n const { t } = useMessages();\n const id = useId();\n const [content, setContent] = useState(\"\");\n const [version, setVersion] = useState(\"\");\n const [role, setRole] = useState(\"\");\n const [from, setFrom] = useState<string>();\n const [until, setUntil] = useState<string>();\n const ok = ID.test(content.trim()) && (!version.trim() || ID.test(version.trim()));\n return (\n <form\n className=\"flex flex-wrap items-end gap-2\"\n data-ckui=\"add-member\"\n onSubmit={(e) => {\n e.preventDefault();\n if (!ok) return;\n void onAdd({ content_id: content.trim(), version_id: version.trim() || undefined, role: role || undefined, active_from: from, active_until: until }).then((d) => {\n if (d === undefined) return;\n setContent(\"\");\n setVersion(\"\");\n });\n }}\n >\n <div className=\"grid gap-1\">\n <Label htmlFor={`${id}-c`} className=\"text-xs text-muted-foreground\">\n {t(\"memberships.contentId\")}\n </Label>\n <Input id={`${id}-c`} className=\"h-8 w-80 max-w-full font-mono\" value={content} onChange={(e) => setContent(e.target.value)} />\n </div>\n {spec.version_level && (\n <div className=\"grid gap-1\">\n <Label htmlFor={`${id}-v`} className=\"text-xs text-muted-foreground\">\n {t(\"memberships.versionId\")}\n </Label>\n <Input id={`${id}-v`} className=\"h-8 w-80 max-w-full font-mono\" value={version} onChange={(e) => setVersion(e.target.value)} />\n </div>\n )}\n {!!spec.roles?.length && (\n <Select value={role || NONE} onValueChange={(v) => setRole(v === NONE ? \"\" : String(v))}>\n <SelectTrigger size=\"sm\" aria-label={t(\"memberships.role\")}>\n <SelectValue>{(v: string) => (v === NONE ? t(\"memberships.noRole\") : labelOf(labels, v))}</SelectValue>\n </SelectTrigger>\n <SelectContent>\n <SelectItem value={NONE}>{t(\"memberships.noRole\")}</SelectItem>\n {spec.roles.map((r) => (\n <SelectItem key={r} value={r}>\n {labelOf(labels, r)}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n )}\n {spec.windows && (\n <WindowFields\n from={from}\n until={until}\n name={t(\"memberships.newMember\")}\n onChange={(w) => {\n if (\"active_from\" in w) setFrom(w.active_from);\n if (\"active_until\" in w) setUntil(w.active_until);\n }}\n />\n )}\n <Button type=\"submit\" size=\"sm\" variant=\"outline\" disabled={!ok}>\n {t(\"memberships.addMember\")}\n </Button>\n </form>\n );\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"memberships.js","names":[],"sources":["../../../src/components/groups/memberships.tsx"],"sourcesContent":["import { cn } from \"cn\";\nimport { useEffect, useId, useMemo, useRef, useState, type ReactNode } from \"react\";\nimport type { ContentKitUiAppearance } from \"../../appearance.js\";\nimport type { ContentKitClient } from \"../../client/client.js\";\nimport { fromLocalInput, toLocalInput } from \"../../client/group-fields.js\";\nimport type { ContentMemberships, GroupCard, GroupDetail, GroupKind, Membership } from \"../../client/generated/wire.js\";\nimport { useMessages } from \"../../i18n/context.js\";\nimport type { ContentKitErrorHandler } from \"../../react/context.js\";\nimport { useContentGroups, useGroupMembers, useKinds, type Member } from \"../../react/groups.js\";\nimport { ContentKitUiRoot } from \"../../scope.js\";\nimport { Badge } from \"#ckui/ui/badge\";\nimport { Button } from \"#ckui/ui/button\";\nimport { Input } from \"#ckui/ui/input\";\nimport { Label } from \"#ckui/ui/label\";\nimport { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from \"#ckui/ui/select\";\nimport { Skeleton } from \"#ckui/ui/skeleton\";\nimport { SortableList } from \"../sortable-list.js\";\nimport { contentError, ErrorLine, formatDate, useAction } from \"../social/parts.js\";\nimport { GroupPicker, labelOf, type Labels } from \"./parts.js\";\n\nconst NONE = \"__none__\";\n\n/** A version a membership may target. */\nexport interface VersionChoice {\n id: string;\n label: string;\n}\n\nexport interface MembershipEditorProps {\n /** The content whose memberships are edited, its versions' included. */\n content: string;\n /** Its kind: the group kinds it joins. */\n contentKind: string;\n /** Staff lookup, including internal classifications. */\n management?: boolean;\n /** Its versions, for version-level memberships (voice actors, version-only tags). */\n versions?: readonly VersionChoice[];\n /** Only these group kinds; default every kind its kind joins. */\n groupKinds?: readonly string[];\n labels?: Labels;\n /** Group names in this language; default the provider's. */\n language?: string;\n onSaved?: (saved: ContentMemberships) => void;\n client?: ContentKitClient;\n onError?: ContentKitErrorHandler;\n className?: string;\n appearance?: ContentKitUiAppearance;\n}\n\ntype Draft = Membership & { key: number };\n\nconst strip = ({ key: _key, ...m }: Draft): Membership => m;\nconst same = (a: Membership[], b: Membership[]) => JSON.stringify(a) === JSON.stringify(b);\n\n/**\n * Staff: a content's groups, per group kind: add and remove groups, and per\n * membership the version it targets, its role, its position in an ordered\n * group, its window and acceptance of a proposed one. Saved in one write per\n * content for the kinds shown.\n */\nexport function MembershipEditor(p: MembershipEditorProps) {\n const m = useMessages();\n const { t } = m;\n const { kinds, loading: kindsLoading } = useKinds({ client: p.client });\n const cg = useContentGroups(p.content, { language: p.language, client: p.client });\n const groupKinds = useMemo(() => p.groupKinds ?? kinds?.kinds[p.contentKind]?.entities ?? [], [p.groupKinds, kinds, p.contentKind]);\n const [picked, setPicked] = useState<ReadonlyMap<string, GroupCard>>(new Map());\n const cards = useMemo(() => new Map([...cg.entities, ...picked]), [cg.entities, picked]);\n const seq = useRef(0);\n const initial = useMemo(\n () => cg.memberships.filter((x) => groupKinds.includes(cg.entities.get(x.group_id ?? \"\")?.kind ?? \"\")).map((x) => ({ ...x, content_id: undefined })),\n [cg.memberships, cg.entities, groupKinds],\n );\n const [draft, setDraft] = useState<Draft[]>([]);\n const dirty = !same(draft.map(strip), initial);\n const dirtyRef = useRef(dirty);\n dirtyRef.current = dirty;\n useEffect(() => {\n if (!dirtyRef.current || !draft.length) setDraft(initial.map((x) => ({ ...x, key: ++seq.current })));\n // Server data replaces an untouched draft only.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [initial]);\n const save = useAction(\"membership.save\", p.onError);\n const [saved, setSaved] = useState(false);\n const change = (key: number, patch: Partial<Membership>) => {\n setSaved(false);\n setDraft((d) => d.map((x) => (x.key === key ? { ...x, ...patch } : x)));\n };\n const root = (children: ReactNode) => (\n <ContentKitUiRoot appearance={p.appearance} className={cn(\"grid gap-4 text-sm\", p.className)} data-ckui=\"membership-editor\">\n {children}\n </ContentKitUiRoot>\n );\n if (kindsLoading || (cg.loading && !cg.memberships.length)) return root(<Skeleton className=\"h-32 w-full\" />);\n if (cg.error && !cg.memberships.length)\n return root(\n <div role=\"alert\" className=\"grid justify-items-start gap-2\">\n <p className=\"text-destructive\">{contentError(m, cg.error)}</p>\n <Button size=\"sm\" variant=\"outline\" onClick={cg.reload}>\n {t(\"common.retry\")}\n </Button>\n </div>,\n );\n const versionLabel = (id: string) => p.versions?.find((v) => v.id === id)?.label ?? id.slice(0, 8);\n return root(\n <form\n className=\"grid gap-5\"\n onSubmit={(e) => {\n e.preventDefault();\n setSaved(false);\n void save.run(() => cg.set(draft.map(strip), [...groupKinds])).then((out) => {\n if (!out) return;\n setSaved(true);\n setDraft(out.memberships.filter((x) => groupKinds.includes(out.entities.find((g) => g.id === x.group_id)?.kind ?? \"\")).map((x) => ({ ...x, content_id: undefined, key: ++seq.current })));\n p.onSaved?.(out);\n });\n }}\n >\n {groupKinds.map((kind) => {\n const spec: GroupKind = kinds?.entity_kinds?.[kind] ?? {};\n const rows = draft.filter((x) => cards.get(x.group_id ?? \"\")?.kind === kind);\n const label = labelOf(p.labels, kind);\n return (\n <fieldset key={kind} className=\"grid gap-2\" data-ckui=\"membership-kind\" data-group-kind={kind}>\n <legend className=\"mb-1 font-medium\">{label}</legend>\n {rows.length > 0 && (\n <ul className=\"grid gap-2\">\n {rows.map((x) => (\n <MembershipRow\n key={x.key}\n m={x}\n card={cards.get(x.group_id ?? \"\")}\n spec={spec}\n labels={p.labels}\n versions={p.versions}\n versionLabel={versionLabel}\n onChange={(patch) => change(x.key, patch)}\n onRemove={() => {\n setSaved(false);\n setDraft((d) => d.filter((y) => y.key !== x.key));\n }}\n />\n ))}\n </ul>\n )}\n <GroupPicker\n management={p.management}\n kind={kind}\n language={p.language}\n label={t(\"memberships.add\", { kind: label })}\n exclude={rows.filter((x) => !x.version_id && !x.role).map((x) => x.group_id!)}\n client={p.client}\n onPick={(g) => {\n setSaved(false);\n setPicked((all) => new Map(all).set(g.id, g));\n setDraft((d) => [...d, { group_id: g.id, key: ++seq.current }]);\n }}\n />\n </fieldset>\n );\n })}\n {!groupKinds.length && <p className=\"text-muted-foreground\">{t(\"memberships.noKinds\")}</p>}\n <ErrorLine error={save.error} />\n <div className=\"flex items-center gap-3\">\n <Button type=\"submit\" size=\"sm\" disabled={save.pending || !dirty}>\n {save.pending ? t(\"common.saving\") : t(\"common.save\")}\n </Button>\n {dirty && (\n <Button type=\"button\" size=\"sm\" variant=\"ghost\" disabled={save.pending} onClick={() => setDraft(initial.map((x) => ({ ...x, key: ++seq.current })))}>\n {t(\"memberships.discard\")}\n </Button>\n )}\n {saved && !dirty && (\n <span role=\"status\" className=\"text-muted-foreground\">\n {t(\"memberships.saved\")}\n </span>\n )}\n </div>\n </form>,\n );\n}\n\nfunction MembershipRow({\n m: x,\n card,\n spec,\n labels,\n versions,\n versionLabel,\n onChange,\n onRemove,\n}: {\n m: Membership;\n card?: GroupCard;\n spec: GroupKind;\n labels?: Labels;\n versions?: readonly VersionChoice[];\n versionLabel: (id: string) => string;\n onChange: (patch: Partial<Membership>) => void;\n onRemove: () => void;\n}) {\n const { t } = useMessages();\n const id = useId();\n const name = card ? card.name || card.slug : (x.group_id ?? \"\");\n const versionIds = [...new Set([...(versions ?? []).map((v) => v.id), ...(x.version_id ? [x.version_id] : [])])];\n return (\n <li className=\"flex flex-wrap items-center gap-2 rounded-md border border-border p-2\" data-ckui=\"membership\" data-group={card?.slug} data-state={x.state ?? \"active\"}>\n <span className=\"min-w-0 flex-1 font-medium break-words\">{name}</span>\n {x.state === \"proposed\" && (\n <>\n <Badge variant=\"secondary\">{t(\"memberships.proposed\")}</Badge>\n <Button type=\"button\" size=\"xs\" variant=\"outline\" onClick={() => onChange({ state: \"active\" })}>\n {t(\"memberships.accept\")}\n </Button>\n </>\n )}\n {spec.version_level && versionIds.length > 0 && (\n <Select value={x.version_id ?? NONE} onValueChange={(v) => onChange({ version_id: v === NONE ? undefined : String(v) })}>\n <SelectTrigger size=\"sm\" aria-label={t(\"memberships.versionOf\", { name })}>\n <SelectValue>{(v: string) => (v === NONE ? t(\"memberships.wholeContent\") : versionLabel(v))}</SelectValue>\n </SelectTrigger>\n <SelectContent>\n <SelectItem value={NONE}>{t(\"memberships.wholeContent\")}</SelectItem>\n {versionIds.map((v) => (\n <SelectItem key={v} value={v}>\n {versionLabel(v)}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n )}\n {!!spec.roles?.length && (\n <Select value={x.role || NONE} onValueChange={(v) => onChange({ role: v === NONE ? undefined : String(v) })}>\n <SelectTrigger size=\"sm\" aria-label={t(\"memberships.roleOf\", { name })}>\n <SelectValue>{(v: string) => (v === NONE ? t(\"memberships.noRole\") : labelOf(labels, v))}</SelectValue>\n </SelectTrigger>\n <SelectContent>\n <SelectItem value={NONE}>{t(\"memberships.noRole\")}</SelectItem>\n {spec.roles.map((r) => (\n <SelectItem key={r} value={r}>\n {labelOf(labels, r)}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n )}\n {spec.ordered && (\n <div className=\"flex items-center gap-1\">\n <Label htmlFor={`${id}-pos`} className=\"text-xs text-muted-foreground\">\n {t(\"memberships.position\")}\n </Label>\n <Input\n id={`${id}-pos`}\n className=\"h-8 w-20\"\n type=\"number\"\n min={0}\n step={1}\n value={x.position ?? \"\"}\n placeholder={t(\"memberships.last\")}\n onChange={(e) => onChange({ position: e.target.value === \"\" ? undefined : Math.max(0, Math.trunc(Number(e.target.value))) })}\n />\n </div>\n )}\n {spec.windows && <WindowFields from={x.active_from} until={x.active_until} name={name} onChange={onChange} />}\n <Button type=\"button\" size=\"xs\" variant=\"ghost\" aria-label={t(\"memberships.remove\", { name })} onClick={onRemove}>\n {t(\"common.remove\")}\n </Button>\n </li>\n );\n}\n\nfunction WindowFields({ from, until, name, onChange }: { from?: string; until?: string; name: string; onChange: (patch: Partial<Membership>) => void }) {\n const { t } = useMessages();\n const id = useId();\n return (\n <div className=\"flex flex-wrap items-center gap-1\" data-ckui=\"membership-window\">\n <Label htmlFor={`${id}-from`} className=\"text-xs text-muted-foreground\">\n {t(\"memberships.from\")}\n </Label>\n <Input\n id={`${id}-from`}\n className=\"h-8 w-48\"\n type=\"datetime-local\"\n aria-label={t(\"memberships.fromOf\", { name })}\n value={toLocalInput(from)}\n onChange={(e) => onChange({ active_from: fromLocalInput(e.target.value) })}\n />\n <Label htmlFor={`${id}-until`} className=\"text-xs text-muted-foreground\">\n {t(\"memberships.until\")}\n </Label>\n <Input\n id={`${id}-until`}\n className=\"h-8 w-48\"\n type=\"datetime-local\"\n aria-label={t(\"memberships.untilOf\", { name })}\n value={toLocalInput(until)}\n onChange={(e) => onChange({ active_until: fromLocalInput(e.target.value) })}\n />\n </div>\n );\n}\n\nexport interface GroupMembersProps {\n group: Pick<GroupDetail, \"id\" | \"kind\" | \"name\" | \"slug\" | \"cover\">;\n labels?: Labels;\n /** One member, e.g. a link with its title; default its content id. */\n renderContent?: (member: Membership) => ReactNode;\n /** Select a member's cover as the group's. */\n onUseCover?: (contentId: string) => Promise<unknown>;\n pageSize?: number;\n client?: ContentKitClient;\n onError?: ContentKitErrorHandler;\n className?: string;\n appearance?: ContentKitUiAppearance;\n}\n\nconst refKey = (x: Membership) => `${x.content_id}|${x.version_id ?? \"\"}`;\n\n/**\n * Staff: a group's members in member order: add by content (and version),\n * remove, reorder an ordered group, edit windows, accept proposed members,\n * and use a member's cover as the group's.\n */\nexport function GroupMembers(p: GroupMembersProps) {\n const m = useMessages();\n const { t } = m;\n const { kinds } = useKinds({ client: p.client });\n const spec: GroupKind = kinds?.entity_kinds?.[p.group.kind] ?? {};\n const members = useGroupMembers(p.group.id, { pageSize: p.pageSize, client: p.client });\n const save = useAction(\"membership.save\", p.onError);\n const [editing, setEditing] = useState<string | null>(null);\n const [win, setWin] = useState<{ from?: string; until?: string }>({});\n const describe = (x: Membership) => (p.renderContent ? p.renderContent(x) : <span className=\"font-mono text-xs break-all\">{x.content_id}</span>);\n const spoken = (x: Member) => `${x.content_id}${x.version_id ? ` ${x.version_id}` : \"\"}`;\n // Every role of one member shares its place: order unique content and version pairs.\n const order = (items: Member[]) => [...new Map(items.map((x) => [refKey(x), { content_id: x.content_id!, version_id: x.version_id }])).values()];\n const strip = ({ id: _id, ...x }: Member): Membership => x;\n const row = (x: Member, handle?: ReactNode) => (\n <div className=\"flex flex-wrap items-center gap-2\" data-ckui=\"group-member\" data-content={x.content_id} data-state={x.state ?? \"active\"}>\n {handle}\n {spec.ordered && x.position !== undefined && <span className=\"w-8 text-xs text-muted-foreground tabular-nums\">{x.position}</span>}\n <span className=\"min-w-0 flex-1\">{describe(x)}</span>\n {x.version_id && <Badge variant=\"outline\">{t(\"memberships.version\")}</Badge>}\n {x.role && <Badge variant=\"secondary\">{labelOf(p.labels, x.role)}</Badge>}\n {x.state === \"proposed\" && (\n <>\n <Badge variant=\"secondary\">{t(\"memberships.proposed\")}</Badge>\n <Button size=\"xs\" variant=\"outline\" disabled={save.pending} onClick={() => void save.run(() => members.add([{ ...strip(x), state: \"active\" }]))}>\n {t(\"memberships.accept\")}\n </Button>\n </>\n )}\n {spec.windows &&\n (editing === x.id ? (\n <span className=\"flex flex-wrap items-center gap-1\">\n <WindowFields from={win.from} until={win.until} name={spoken(x)} onChange={(w) => setWin((cur) => ({ from: \"active_from\" in w ? w.active_from : cur.from, until: \"active_until\" in w ? w.active_until : cur.until }))} />\n <Button\n size=\"xs\"\n disabled={save.pending}\n onClick={() =>\n void save.run(() => members.add([{ ...strip(x), active_from: win.from, active_until: win.until }])).then((d) => d !== undefined && setEditing(null))\n }\n >\n {t(\"common.save\")}\n </Button>\n <Button size=\"xs\" variant=\"ghost\" onClick={() => setEditing(null)}>\n {t(\"common.cancel\")}\n </Button>\n </span>\n ) : (\n <>\n <span className=\"text-xs text-muted-foreground\" data-ckui=\"member-window\">\n {x.active_from || x.active_until\n ? t(\"memberships.window\", { from: x.active_from ? formatDate(m, x.active_from) : \"…\", until: x.active_until ? formatDate(m, x.active_until) : \"…\" })\n : t(\"memberships.always\")}\n </span>\n <Button\n size=\"xs\"\n variant=\"ghost\"\n onClick={() => {\n setWin({ from: x.active_from, until: x.active_until });\n setEditing(x.id);\n }}\n >\n {t(\"memberships.editWindow\")}\n </Button>\n </>\n ))}\n {p.onUseCover && !x.version_id && (\n <Button size=\"xs\" variant=\"ghost\" disabled={save.pending || (p.group.cover?.content_id === x.content_id && !p.group.cover?.auto)} onClick={() => void save.run(() => p.onUseCover!(x.content_id!))}>\n {t(\"memberships.useCover\")}\n </Button>\n )}\n <Button size=\"xs\" variant=\"ghost\" disabled={save.pending} aria-label={t(\"memberships.remove\", { name: spoken(x) })} onClick={() => void save.run(() => members.remove([strip(x)]))}>\n {t(\"common.remove\")}\n </Button>\n </div>\n );\n return (\n <ContentKitUiRoot appearance={p.appearance} className={cn(\"grid gap-3 text-sm\", p.className)} data-ckui=\"group-members\">\n <h3 className=\"font-medium\">{t(\"memberships.members\")}</h3>\n {members.loading && !members.items.length ? (\n <Skeleton className=\"h-20 w-full\" />\n ) : members.error && !members.items.length ? (\n <div role=\"alert\" className=\"grid justify-items-start gap-2\">\n <p className=\"text-destructive\">{contentError(m, members.error)}</p>\n <Button size=\"sm\" variant=\"outline\" onClick={members.reload}>\n {t(\"common.retry\")}\n </Button>\n </div>\n ) : !members.items.length ? (\n <p className=\"text-muted-foreground\">{t(\"memberships.noMembers\")}</p>\n ) : spec.ordered ? (\n <SortableList\n items={members.items}\n id={(x) => x.id}\n name={spoken}\n label={t(\"memberships.members\")}\n disabled={save.pending}\n onMove={(from, to) => {\n const items = [...members.items];\n const [moved] = items.splice(from, 1);\n items.splice(to, 0, moved!);\n void save.run(() => members.reorder(order(items)));\n }}\n >\n {(x, handle) => row(x, handle)}\n </SortableList>\n ) : (\n <ul className=\"grid divide-y divide-border rounded-lg border border-border\">\n {members.items.map((x) => (\n <li key={x.id} className=\"p-2\">\n {row(x)}\n </li>\n ))}\n </ul>\n )}\n {members.hasMore && (\n <div className=\"grid justify-items-center gap-2\">\n {members.error && <p role=\"alert\" className=\"text-destructive\">{contentError(m, members.error)}</p>}\n <Button variant=\"outline\" size=\"sm\" disabled={members.loadingMore} onClick={() => void members.loadMore()}>\n {members.loadingMore ? t(\"groups.loading\") : members.error ? t(\"common.retry\") : t(\"groups.loadMore\")}\n </Button>\n </div>\n )}\n <AddMember spec={spec} labels={p.labels} onAdd={(x) => save.run(() => members.add([x]))} />\n <ErrorLine error={save.error} />\n </ContentKitUiRoot>\n );\n}\n\nconst ID = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/;\n\nfunction AddMember({ spec, labels, onAdd }: { spec: GroupKind; labels?: Labels; onAdd: (m: Membership) => Promise<unknown> }) {\n const { t } = useMessages();\n const id = useId();\n const [content, setContent] = useState(\"\");\n const [version, setVersion] = useState(\"\");\n const [role, setRole] = useState(\"\");\n const [from, setFrom] = useState<string>();\n const [until, setUntil] = useState<string>();\n const ok = ID.test(content.trim()) && (!version.trim() || ID.test(version.trim()));\n return (\n <form\n className=\"flex flex-wrap items-end gap-2\"\n data-ckui=\"add-member\"\n onSubmit={(e) => {\n e.preventDefault();\n if (!ok) return;\n void onAdd({ content_id: content.trim(), version_id: version.trim() || undefined, role: role || undefined, active_from: from, active_until: until }).then((d) => {\n if (d === undefined) return;\n setContent(\"\");\n setVersion(\"\");\n });\n }}\n >\n <div className=\"grid gap-1\">\n <Label htmlFor={`${id}-c`} className=\"text-xs text-muted-foreground\">\n {t(\"memberships.contentId\")}\n </Label>\n <Input id={`${id}-c`} className=\"h-8 w-80 max-w-full font-mono\" value={content} onChange={(e) => setContent(e.target.value)} />\n </div>\n {spec.version_level && (\n <div className=\"grid gap-1\">\n <Label htmlFor={`${id}-v`} className=\"text-xs text-muted-foreground\">\n {t(\"memberships.versionId\")}\n </Label>\n <Input id={`${id}-v`} className=\"h-8 w-80 max-w-full font-mono\" value={version} onChange={(e) => setVersion(e.target.value)} />\n </div>\n )}\n {!!spec.roles?.length && (\n <Select value={role || NONE} onValueChange={(v) => setRole(v === NONE ? \"\" : String(v))}>\n <SelectTrigger size=\"sm\" aria-label={t(\"memberships.role\")}>\n <SelectValue>{(v: string) => (v === NONE ? t(\"memberships.noRole\") : labelOf(labels, v))}</SelectValue>\n </SelectTrigger>\n <SelectContent>\n <SelectItem value={NONE}>{t(\"memberships.noRole\")}</SelectItem>\n {spec.roles.map((r) => (\n <SelectItem key={r} value={r}>\n {labelOf(labels, r)}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n )}\n {spec.windows && (\n <WindowFields\n from={from}\n until={until}\n name={t(\"memberships.newMember\")}\n onChange={(w) => {\n if (\"active_from\" in w) setFrom(w.active_from);\n if (\"active_until\" in w) setUntil(w.active_until);\n }}\n />\n )}\n <Button type=\"submit\" size=\"sm\" variant=\"outline\" disabled={!ok}>\n {t(\"memberships.addMember\")}\n </Button>\n </form>\n );\n}\n"],"mappings":"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"}
|
|
@@ -1,78 +1,96 @@
|
|
|
1
1
|
import { DEFAULT_DENSITY as e, densityFor as t, pickRendition as n, sortRenditions as r } from "../client/rendition.js";
|
|
2
2
|
import { useReducedMotion as i } from "../react/inline-preview.js";
|
|
3
|
-
import { createContext as a,
|
|
4
|
-
import { Fragment as
|
|
3
|
+
import { createContext as a, createElement as o, useCallback as s, useContext as c, useEffect as l, useLayoutEffect as u, useMemo as d, useRef as f, useState as p } from "react";
|
|
4
|
+
import { Fragment as m, jsx as h } from "react/jsx-runtime";
|
|
5
5
|
//#region src/components/rendition-img.tsx
|
|
6
|
-
var
|
|
7
|
-
function
|
|
8
|
-
let a =
|
|
9
|
-
|
|
10
|
-
if (!
|
|
11
|
-
let e =
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
6
|
+
var g = a(e), _ = typeof window > "u" ? l : u;
|
|
7
|
+
function v(e, i = {}) {
|
|
8
|
+
let a = c(g), o = i.density ?? a, [u, m] = p(null), [h, v] = p(-1);
|
|
9
|
+
_(() => {
|
|
10
|
+
if (!u) return;
|
|
11
|
+
let e = !0, t = () => {
|
|
12
|
+
e && v((e) => Math.max(e, u.getBoundingClientRect().width));
|
|
13
|
+
};
|
|
14
|
+
t();
|
|
15
|
+
let n = typeof ResizeObserver == "function" ? new ResizeObserver(t) : void 0;
|
|
16
|
+
return n?.observe(u), () => {
|
|
17
|
+
e = !1, n?.disconnect();
|
|
18
|
+
};
|
|
19
|
+
}, [u]);
|
|
20
|
+
let y = d(() => r(e), [e]), b = h >= 0 ? n(y, h, t(o)) : void 0, [x, S] = p(void 0), C = f(void 0), w = f(null), T = y.find((e) => e.url === x), E = b?.url, D = b?.w ?? 0, O = T?.url, k = T?.w ?? 0;
|
|
21
|
+
l(() => {
|
|
22
|
+
if (!E || E === O) return;
|
|
23
|
+
if (!O || C.current !== O) {
|
|
24
|
+
S(E);
|
|
21
25
|
return;
|
|
22
26
|
}
|
|
23
|
-
if (
|
|
24
|
-
let e = !0, t = new Image()
|
|
25
|
-
|
|
26
|
-
|
|
27
|
+
if (D <= k || w.current === E) return;
|
|
28
|
+
let e = !0, t = new Image(), n = () => {
|
|
29
|
+
e && S(E);
|
|
30
|
+
};
|
|
31
|
+
return t.onload = n, t.onerror = () => {
|
|
32
|
+
e && (w.current = E);
|
|
33
|
+
}, t.src = E, t.complete && t.naturalWidth > 0 && n(), () => {
|
|
34
|
+
e = !1, t.onload = null, t.onerror = null;
|
|
27
35
|
};
|
|
28
|
-
}, [
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
36
|
+
}, [
|
|
37
|
+
E,
|
|
38
|
+
D,
|
|
39
|
+
O,
|
|
40
|
+
k
|
|
41
|
+
]);
|
|
42
|
+
let A = s(() => {
|
|
43
|
+
C.current = O ?? E;
|
|
44
|
+
}, [O, E]);
|
|
32
45
|
return {
|
|
33
46
|
ref: m,
|
|
34
|
-
rendition:
|
|
35
|
-
onLoad:
|
|
47
|
+
rendition: T ?? b,
|
|
48
|
+
onLoad: A
|
|
36
49
|
};
|
|
37
50
|
}
|
|
38
|
-
var
|
|
39
|
-
function
|
|
40
|
-
let { ref:
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
}, [
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
let
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
51
|
+
var y = { backgroundColor: "var(--ckui-muted, rgb(127 127 127 / 0.15))" }, b = "ckui-pulse 2s cubic-bezier(0.4, 0, 0.6, 1) infinite";
|
|
52
|
+
function x({ outputs: e, density: t, onLoad: n, onError: a, alt: c = "", fallback: l, skeleton: u, fit: g, style: x, ...S }) {
|
|
53
|
+
let { ref: C, rendition: w, onLoad: T } = v(e, { density: t }), E = d(() => r(e), [e]), D = E[0], O = w ?? D, k = i(), [A, j] = p([]), M = O && A.includes(O.url) ? D && D.w < O.w && !A.includes(D.url) ? D : void 0 : O, [N, P] = p(null), [F, I] = p(null), L = f(null), R = w ? M?.url : void 0;
|
|
54
|
+
_(() => {
|
|
55
|
+
F && R && F.getAttribute("src") === R && F.complete && F.naturalWidth > 0 && (T(), P(R));
|
|
56
|
+
}, [
|
|
57
|
+
F,
|
|
58
|
+
R,
|
|
59
|
+
T
|
|
60
|
+
]);
|
|
61
|
+
let z = s((e) => {
|
|
62
|
+
L.current = e, C(e), I(e);
|
|
63
|
+
}, [C]);
|
|
64
|
+
if (!M) return /* @__PURE__ */ h(m, { children: l ?? null });
|
|
65
|
+
let B = u && N !== R;
|
|
66
|
+
return /* @__PURE__ */ o("img", {
|
|
67
|
+
...S,
|
|
68
|
+
key: R,
|
|
69
|
+
ref: z,
|
|
70
|
+
alt: c,
|
|
71
|
+
src: R,
|
|
72
|
+
width: M.w,
|
|
73
|
+
height: M.h || void 0,
|
|
56
74
|
decoding: "async",
|
|
57
|
-
"data-rendition":
|
|
58
|
-
"data-loading":
|
|
75
|
+
"data-rendition": w ? M.w : void 0,
|
|
76
|
+
"data-loading": B ? "" : void 0,
|
|
59
77
|
style: {
|
|
60
|
-
...
|
|
61
|
-
...
|
|
62
|
-
...
|
|
63
|
-
animation:
|
|
78
|
+
...g ? { objectFit: g } : {},
|
|
79
|
+
...B ? {
|
|
80
|
+
...y,
|
|
81
|
+
animation: k ? void 0 : b
|
|
64
82
|
} : {},
|
|
65
|
-
...
|
|
83
|
+
...x
|
|
66
84
|
},
|
|
67
85
|
onLoad: (e) => {
|
|
68
|
-
|
|
86
|
+
L.current === e.currentTarget && (T(), R && P(R), n?.(e));
|
|
69
87
|
},
|
|
70
88
|
onError: (e) => {
|
|
71
|
-
|
|
89
|
+
L.current === e.currentTarget && (R && j((e) => [...e.filter((e) => E.some((t) => t.url === e)), R]), a?.(e));
|
|
72
90
|
}
|
|
73
91
|
});
|
|
74
92
|
}
|
|
75
93
|
//#endregion
|
|
76
|
-
export {
|
|
94
|
+
export { g as DensityContext, x as RenditionImg, v as useRendition };
|
|
77
95
|
|
|
78
96
|
//# sourceMappingURL=rendition-img.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"rendition-img.js","names":[],"sources":["../../src/components/rendition-img.tsx"],"sourcesContent":["import { createContext, useCallback, useContext, useEffect, useLayoutEffect, useMemo, useRef, useState, type ComponentProps, type CSSProperties, type ReactNode } from \"react\";\nimport { DEFAULT_DENSITY, densityFor, pickRendition, sortRenditions, type DensityRange, type Rendition } from \"../client/rendition.js\";\nimport { useReducedMotion } from \"../react/inline-preview.js\";\n\nexport const DensityContext = createContext<DensityRange>(DEFAULT_DENSITY);\n\nconst useIsoLayoutEffect = typeof window === \"undefined\" ? useEffect : useLayoutEffect;\n\nexport interface UseRenditionOptions {\n /** Density range; default the provider's (1–3×). */\n density?: DensityRange;\n}\n\n/**\n * Picks a rendition for the element `ref` (a callback ref) is attached to: the narrowest at\n * least its rendered width × density. It re-picks on resize (fullscreen,\n * window changes), never steps down, and keeps the shown rendition until a\n * wider one has loaded, so nothing flickers.\n */\nexport function useRendition<T extends Rendition, E extends HTMLElement = HTMLImageElement>(outputs: readonly T[] | null | undefined, o: UseRenditionOptions = {}) {\n const provided = useContext(DensityContext);\n const range = o.density ?? provided;\n const [el, ref] = useState<E | null>(null);\n // -1 until measured; a hidden element measures 0 and gets the narrowest.\n const [width, setWidth] = useState(-1);\n useIsoLayoutEffect(() => {\n if (!el) return;\n const measure = () => setWidth((w) => Math.max(w, el.getBoundingClientRect().width));\n measure();\n
|
|
1
|
+
{"version":3,"file":"rendition-img.js","names":[],"sources":["../../src/components/rendition-img.tsx"],"sourcesContent":["import { createContext, useCallback, useContext, useEffect, useLayoutEffect, useMemo, useRef, useState, type ComponentProps, type CSSProperties, type ReactNode } from \"react\";\nimport { DEFAULT_DENSITY, densityFor, pickRendition, sortRenditions, type DensityRange, type Rendition } from \"../client/rendition.js\";\nimport { useReducedMotion } from \"../react/inline-preview.js\";\n\nexport const DensityContext = createContext<DensityRange>(DEFAULT_DENSITY);\n\nconst useIsoLayoutEffect = typeof window === \"undefined\" ? useEffect : useLayoutEffect;\n\nexport interface UseRenditionOptions {\n /** Density range; default the provider's (1–3×). */\n density?: DensityRange;\n}\n\n/**\n * Picks a rendition for the element `ref` (a callback ref) is attached to: the narrowest at\n * least its rendered width × density. It re-picks on resize (fullscreen,\n * window changes), never steps down, and keeps the shown rendition until a\n * wider one has loaded, so nothing flickers.\n */\nexport function useRendition<T extends Rendition, E extends HTMLElement = HTMLImageElement>(outputs: readonly T[] | null | undefined, o: UseRenditionOptions = {}) {\n const provided = useContext(DensityContext);\n const range = o.density ?? provided;\n const [el, ref] = useState<E | null>(null);\n // -1 until measured; a hidden element measures 0 and gets the narrowest.\n const [width, setWidth] = useState(-1);\n useIsoLayoutEffect(() => {\n if (!el) return;\n let live = true;\n const measure = () => { if (live) setWidth((w) => Math.max(w, el.getBoundingClientRect().width)); };\n measure();\n const ro = typeof ResizeObserver === \"function\" ? new ResizeObserver(measure) : undefined;\n ro?.observe(el);\n return () => { live = false; ro?.disconnect(); };\n }, [el]);\n const sorted = useMemo(() => sortRenditions(outputs), [outputs]);\n const want = width >= 0 ? pickRendition(sorted, width, densityFor(range)) : undefined;\n const [shownURL, setShownURL] = useState<string | undefined>(undefined);\n const loaded = useRef<string | undefined>(undefined);\n const failedUpgrade = useRef<string | null>(null);\n const current = sorted.find((r) => r.url === shownURL);\n const wantURL = want?.url;\n const wantWidth = want?.w ?? 0;\n const currentURL = current?.url;\n const currentWidth = current?.w ?? 0;\n useEffect(() => {\n if (!wantURL || wantURL === currentURL) return;\n // First pick, a new set, or before anything loaded: show it now.\n if (!currentURL || loaded.current !== currentURL) {\n setShownURL(wantURL);\n return;\n }\n if (wantWidth <= currentWidth || failedUpgrade.current === wantURL) return;\n let live = true;\n const img = new Image();\n const show = () => { if (live) setShownURL(wantURL); };\n img.onload = show;\n img.onerror = () => { if (live) failedUpgrade.current = wantURL; };\n img.src = wantURL;\n if (img.complete && img.naturalWidth > 0) show();\n return () => {\n live = false;\n img.onload = null;\n img.onerror = null;\n };\n }, [wantURL, wantWidth, currentURL, currentWidth]);\n const onLoad = useCallback(() => {\n loaded.current = currentURL ?? wantURL;\n }, [currentURL, wantURL]);\n return { ref, rendition: current ?? want, onLoad };\n}\n\nexport interface RenditionImgProps extends Omit<ComponentProps<\"img\">, \"src\" | \"srcSet\" | \"sizes\" | \"width\" | \"height\"> {\n outputs: readonly Rendition[] | null | undefined;\n density?: DensityRange;\n /** Rendered instead when there are no renditions or the image fails to load (a 404). */\n fallback?: ReactNode;\n /** A pulsing muted fill until the image has loaded. */\n skeleton?: boolean;\n /** object-fit of the image in its box. */\n fit?: \"cover\" | \"contain\";\n}\n\nconst SKELETON: CSSProperties = { backgroundColor: \"var(--ckui-muted, rgb(127 127 127 / 0.15))\" };\nconst PULSE = \"ckui-pulse 2s cubic-bezier(0.4, 0, 0.6, 1) infinite\";\n\n/**\n * An `<img>` showing the rendition its rendered size × density needs (see\n * useRendition), with a fallback for none or a failed load and an optional\n * loading skeleton.\n */\nexport function RenditionImg({ outputs, density, onLoad, onError, alt = \"\", fallback, skeleton, fit, style, ...img }: RenditionImgProps) {\n const { ref, rendition, onLoad: loaded } = useRendition(outputs, { density });\n const sorted = useMemo(() => sortRenditions(outputs), [outputs]);\n const first = sorted[0];\n const selected = rendition ?? first;\n const reduced = useReducedMotion();\n const [failed, setFailed] = useState<readonly string[]>([]);\n // One smaller fallback only: do not walk every variant or retry a broken\n // source on resize/rerender. A new output URL or deliberate remount retries.\n const r = selected && failed.includes(selected.url)\n ? first && first.w < selected.w && !failed.includes(first.url) ? first : undefined\n : selected;\n const [done, setDone] = useState<string | null>(null);\n const [el, setEl] = useState<HTMLImageElement | null>(null);\n const activeImage = useRef<HTMLImageElement | null>(null);\n const src = rendition ? r?.url : undefined;\n // A cached image is complete before its load event; settle it before paint.\n useIsoLayoutEffect(() => {\n if (el && src && el.getAttribute(\"src\") === src && el.complete && el.naturalWidth > 0) {\n loaded();\n setDone(src);\n }\n }, [el, src, loaded]);\n const attach = useCallback(\n (node: HTMLImageElement | null) => {\n activeImage.current = node;\n ref(node);\n setEl(node);\n },\n [ref],\n );\n if (!r) return <>{fallback ?? null}</>;\n const loading = skeleton && done !== src;\n return (\n <img\n {...img}\n key={src}\n ref={attach}\n alt={alt}\n src={src}\n width={r.w}\n height={r.h || undefined}\n decoding=\"async\"\n data-rendition={rendition ? r.w : undefined}\n data-loading={loading ? \"\" : undefined}\n style={{ ...(fit ? { objectFit: fit } : {}), ...(loading ? { ...SKELETON, animation: reduced ? undefined : PULSE } : {}), ...style }}\n onLoad={(e) => {\n if (activeImage.current !== e.currentTarget) return;\n loaded();\n if (src) setDone(src);\n onLoad?.(e);\n }}\n onError={(e) => {\n if (activeImage.current !== e.currentTarget) return;\n if (src) setFailed((previous) => [...previous.filter((url) => sorted.some((r) => r.url === url)), src]);\n onError?.(e);\n }}\n />\n );\n}\n"],"mappings":"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"}
|
|
@@ -332,11 +332,11 @@ function Z({ loc: e, view: n, ...r }) {
|
|
|
332
332
|
}, t))
|
|
333
333
|
}),
|
|
334
334
|
/* @__PURE__ */ H($, {
|
|
335
|
-
loading: o.loading,
|
|
335
|
+
loading: o.loading || o.loadingMore,
|
|
336
336
|
error: o.error,
|
|
337
337
|
empty: i("moderation.queueEmpty"),
|
|
338
338
|
count: o.items.length,
|
|
339
|
-
reload: o.reload,
|
|
339
|
+
reload: o.items.length && o.hasMore ? () => void o.loadMore() : o.reload,
|
|
340
340
|
children: o.items.map((e) => /* @__PURE__ */ H(Q, {
|
|
341
341
|
item: e,
|
|
342
342
|
itemHref: r.itemHref,
|
|
@@ -346,7 +346,7 @@ function Z({ loc: e, view: n, ...r }) {
|
|
|
346
346
|
onError: r.onError
|
|
347
347
|
}, e.id))
|
|
348
348
|
}),
|
|
349
|
-
o.hasMore && /* @__PURE__ */ H(s, {
|
|
349
|
+
o.hasMore && !o.error && /* @__PURE__ */ H(s, {
|
|
350
350
|
variant: "outline",
|
|
351
351
|
className: "justify-self-center",
|
|
352
352
|
disabled: o.loadingMore,
|
|
@@ -467,10 +467,19 @@ function $(e) {
|
|
|
467
467
|
onClick: e.reload,
|
|
468
468
|
children: r("common.retry")
|
|
469
469
|
})]
|
|
470
|
-
}) : e.count ? /* @__PURE__ */ H("ul", {
|
|
470
|
+
}) : e.count ? /* @__PURE__ */ U(V, { children: [/* @__PURE__ */ H("ul", {
|
|
471
471
|
className: "grid divide-y divide-border rounded-lg border border-border",
|
|
472
472
|
children: e.children
|
|
473
|
-
})
|
|
473
|
+
}), e.error && /* @__PURE__ */ U("div", {
|
|
474
|
+
className: "grid justify-items-center gap-2",
|
|
475
|
+
children: [/* @__PURE__ */ H(v, { error: e.error }), /* @__PURE__ */ H(s, {
|
|
476
|
+
size: "sm",
|
|
477
|
+
variant: "outline",
|
|
478
|
+
disabled: e.loading,
|
|
479
|
+
onClick: e.reload,
|
|
480
|
+
children: r("common.retry")
|
|
481
|
+
})]
|
|
482
|
+
})] }) : /* @__PURE__ */ H("p", {
|
|
474
483
|
className: "text-muted-foreground",
|
|
475
484
|
children: e.empty
|
|
476
485
|
});
|