@openrails/contentkit-ui 0.96.0 → 0.97.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (65) hide show
  1. package/README.md +9 -1
  2. package/dist/client/discovery.d.ts +2 -1
  3. package/dist/client/discovery.js.map +1 -1
  4. package/dist/client/entities.d.ts +6 -0
  5. package/dist/client/entities.js +13 -0
  6. package/dist/client/entities.js.map +1 -1
  7. package/dist/client/generated/routes.d.ts +26 -0
  8. package/dist/client/generated/routes.js +44 -0
  9. package/dist/client/generated/routes.js.map +1 -1
  10. package/dist/client/generated/wire.d.ts +7 -10
  11. package/dist/client/generated/wire.js.map +1 -1
  12. package/dist/client/http.d.ts +1 -0
  13. package/dist/client/http.js +5 -4
  14. package/dist/client/http.js.map +1 -1
  15. package/dist/client/index.d.ts +1 -1
  16. package/dist/client/reader-preferences.js +3 -7
  17. package/dist/client/reader-preferences.js.map +1 -1
  18. package/dist/components/admin/content-manager.d.ts +3 -1
  19. package/dist/components/admin/content-manager.js +241 -239
  20. package/dist/components/admin/content-manager.js.map +1 -1
  21. package/dist/components/admin/group-manager.js +133 -119
  22. package/dist/components/admin/group-manager.js.map +1 -1
  23. package/dist/components/content/editors.d.ts +1 -0
  24. package/dist/components/content/editors.js +1 -0
  25. package/dist/components/content/editors.js.map +1 -1
  26. package/dist/components/content/filters.d.ts +1 -1
  27. package/dist/components/content/filters.js +1 -1
  28. package/dist/components/content/filters.js.map +1 -1
  29. package/dist/components/content/popular.js +37 -32
  30. package/dist/components/content/popular.js.map +1 -1
  31. package/dist/components/groups/banner.d.ts +3 -1
  32. package/dist/components/groups/banner.js +29 -26
  33. package/dist/components/groups/banner.js.map +1 -1
  34. package/dist/components/groups/editor.d.ts +4 -1
  35. package/dist/components/groups/editor.js +369 -315
  36. package/dist/components/groups/editor.js.map +1 -1
  37. package/dist/components/groups/memberships.d.ts +2 -0
  38. package/dist/components/groups/memberships.js +1 -0
  39. package/dist/components/groups/memberships.js.map +1 -1
  40. package/dist/components/groups/parts.d.ts +4 -1
  41. package/dist/components/groups/parts.js +32 -30
  42. package/dist/components/groups/parts.js.map +1 -1
  43. package/dist/index.js +1 -1
  44. package/dist/locales/en.d.ts +2 -0
  45. package/dist/locales/groups/de.js +2 -0
  46. package/dist/locales/groups/de.js.map +1 -1
  47. package/dist/locales/groups/en.d.ts +2 -0
  48. package/dist/locales/groups/en.js +2 -0
  49. package/dist/locales/groups/en.js.map +1 -1
  50. package/dist/locales/groups/es.js +2 -0
  51. package/dist/locales/groups/es.js.map +1 -1
  52. package/dist/locales/groups/ja.js +2 -0
  53. package/dist/locales/groups/ja.js.map +1 -1
  54. package/dist/locales/groups/ko.js +2 -0
  55. package/dist/locales/groups/ko.js.map +1 -1
  56. package/dist/locales/groups/zh.js +2 -0
  57. package/dist/locales/groups/zh.js.map +1 -1
  58. package/dist/react/discovery.d.ts +2 -1
  59. package/dist/react/discovery.js +54 -29
  60. package/dist/react/discovery.js.map +1 -1
  61. package/dist/react/groups.d.ts +3 -1
  62. package/dist/react/groups.js +7 -7
  63. package/dist/react/groups.js.map +1 -1
  64. package/dist/styles.css +1 -1
  65. package/package.json +1 -1
@@ -1 +1 @@
1
- {"version":3,"file":"group-manager.js","names":[],"sources":["../../../src/components/admin/group-manager.tsx"],"sourcesContent":["import { useMemo, type ReactNode } from \"react\";\nimport type { ContentKitClient } from \"../../client/client.js\";\nimport { LETTERS } from \"../../client/group-fields.js\";\nimport type { ContentModel, Membership } from \"../../client/generated/wire.js\";\nimport { useLanguageName, useMessages } from \"../../i18n/context.js\";\nimport { useAdminLocation, useFlowClient, useStaffAccess, type AdminLocation, type FlowClientOptions, type StaffAccess } from \"../../react/admin.js\";\nimport { useGroups, useKinds, type GroupSort } from \"../../react/groups.js\";\nimport { Button } from \"#ckui/ui/button\";\nimport { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from \"#ckui/ui/select\";\nimport { Tabs, TabsList, TabsTrigger } from \"#ckui/ui/tabs\";\nimport { GroupEditor } from \"../groups/editor.js\";\nimport { GroupMembers } from \"../groups/memberships.js\";\nimport { labelOf, type Labels } from \"../groups/parts.js\";\nimport { AdminRoot, LoadFailed, NoAccess, Rows, type AdminFlowProps, type AdminRouteProps } from \"./shell.js\";\n\nexport interface GroupManagerProps extends AdminFlowProps, AdminRouteProps {\n /** The group kinds managed, in tab order; default the content model's site-owned kinds. */\n groupKinds?: readonly string[];\n /** Display names of kinds, attributes, roles and values by identifier. */\n labels?: Labels;\n /** Counts of this content kind; default every kind. */\n contentKind?: string;\n /** One member, e.g. a link with its title; default its content id. */\n renderContent?: (member: Membership) => ReactNode;\n pageSize?: number;\n}\n\n/** Whether the caller may manage groups (root:groups:write). */\nexport function useGroupManagerAccess(o: FlowClientOptions = {}): StaffAccess<\"groups\"> {\n return useStaffAccess([\"groups\"] as const, o);\n}\n\nconst SORTS: readonly GroupSort[] = [\"name\", \"count\", \"newest\"];\n\n/**\n * Staff: groups per kind. A kind's groups by letter, order and language; a\n * new group; a group's editor (GroupEditor) and its members (GroupMembers).\n * Kinds are at basePath/{kind}, a group at basePath/{kind}/{id}, filters in the query.\n */\nexport function GroupManager({ client: own, baseUrl, auth, guard, appearance, className, language, messages, ...p }: GroupManagerProps) {\n const client = useFlowClient({ client: own, baseUrl, auth });\n return (\n <AdminRoot flow=\"group-manager\" appearance={appearance} className={className} language={language} messages={messages} guard={guard}>\n <Manager {...p} client={client} />\n </AdminRoot>\n );\n}\n\ntype Inner = Omit<GroupManagerProps, \"client\" | \"baseUrl\" | \"auth\" | \"guard\" | \"appearance\" | \"className\" | \"language\" | \"messages\"> & { client: ContentKitClient };\ntype Ctx = Inner & { loc: AdminLocation; kind: string; kinds: ContentModel };\n\nfunction Manager({ basePath, navigation, ...p }: Inner) {\n const { t } = useMessages();\n const loc = useAdminLocation(basePath, navigation);\n const access = useGroupManagerAccess({ client: p.client });\n const model = useKinds({ client: p.client });\n const kinds = model.kinds;\n const list = useMemo(\n () =>\n p.groupKinds ??\n Object.entries(kinds?.entity_kinds ?? {})\n .filter(([, k]) => k.owner !== \"user\")\n .map(([name]) => name)\n .sort(),\n [p.groupKinds, kinds],\n );\n if (access.loading || model.loading) return <Rows />;\n if (!access.allowed.groups) return <NoAccess>{t(\"groupManager.noAccess\")}</NoAccess>;\n if (!kinds) return <LoadFailed error={model.error} message={t(\"groupManager.kindsFailed\")} retry={model.reload} />;\n if (!list.length) return <p className=\"text-muted-foreground\">{t(\"groupManager.noKinds\")}</p>;\n const [k, sub] = loc.view.split(\"/\");\n const kind = list.includes(k ?? \"\") ? k! : list[0]!;\n const ctx: Ctx = { ...p, loc, kind, kinds };\n return (\n <>\n {list.length > 1 && (\n <Tabs value={kind} onValueChange={(v) => loc.go(String(v))}>\n <TabsList className=\"flex-wrap group-data-horizontal/tabs:h-auto\">\n {list.map((x) => (\n <TabsTrigger key={x} value={x} className=\"h-7.5\">\n {labelOf(p.labels, x)}\n </TabsTrigger>\n ))}\n </TabsList>\n </Tabs>\n )}\n {!sub ? <List key={kind} {...ctx} /> : sub === \"new\" ? <Create key={kind} {...ctx} /> : <Edit key={sub} {...ctx} id={sub} />}\n </>\n );\n}\n\nfunction Back({ loc, kind }: { loc: AdminLocation; kind: string }) {\n const { t } = useMessages();\n return (\n <Button variant=\"ghost\" size=\"sm\" className=\"justify-self-start\" onClick={() => loc.go(kind)}>\n {t(\"groupManager.back\")}\n </Button>\n );\n}\n\nfunction List({ loc, kind, kinds, client, contentKind, labels, pageSize = 50 }: Ctx) {\n const m = useMessages();\n const { t } = m;\n const languageName = useLanguageName();\n const languages = kinds.languages;\n const letterParam = loc.query.get(\"letter\") ?? \"\";\n const letter = LETTERS.includes(letterParam) ? letterParam : undefined;\n const sortParam = loc.query.get(\"sort\") ?? \"\";\n const sort = (SORTS as readonly string[]).includes(sortParam) ? (sortParam as GroupSort) : \"name\";\n const languageParam = loc.query.get(\"language\") ?? \"\";\n const language = languages.includes(languageParam) ? languageParam : languages[0];\n const filters: { letter?: string; sort?: GroupSort; language?: string } = { letter, sort: sort === \"name\" ? undefined : sort, language: language === languages[0] ? undefined : language };\n const filter = (next: Partial<typeof filters>) => loc.go(kind, { ...filters, ...next });\n const groups = useGroups({ kind, letter, sort, language, contentKind, pageSize }, { client });\n const label = labelOf(labels, kind);\n return (\n <div className=\"grid gap-4\" data-ckui=\"group-list\" data-kind={kind}>\n <div className=\"flex flex-wrap items-center justify-between gap-2\">\n <h2 className=\"text-base font-semibold\">{label}</h2>\n <Button size=\"sm\" onClick={() => loc.go(`${kind}/new`)}>\n {t(\"groupManager.new\", { kind: label })}\n </Button>\n </div>\n <div className=\"flex flex-wrap items-center gap-2\">\n <Select value={sort} onValueChange={(v) => filter({ sort: v === \"name\" ? undefined : (String(v) as GroupSort) })}>\n <SelectTrigger size=\"sm\" aria-label={t(\"groupManager.sort\")}>\n <SelectValue>{(v: string) => t(`groupManager.sort_${v as GroupSort}`)}</SelectValue>\n </SelectTrigger>\n <SelectContent>\n {SORTS.map((s) => (\n <SelectItem key={s} value={s}>\n {t(`groupManager.sort_${s}`)}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n {languages.length > 1 && (\n <Select value={language} onValueChange={(v) => filter({ language: v === languages[0] ? undefined : String(v) })}>\n <SelectTrigger size=\"sm\" aria-label={t(\"groupManager.language\")}>\n <SelectValue>{(v: string) => languageName(v)}</SelectValue>\n </SelectTrigger>\n <SelectContent>\n {languages.map((l) => (\n <SelectItem key={l} value={l}>\n {languageName(l)}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n )}\n </div>\n <nav aria-label={t(\"groups.byLetter\")} className=\"flex flex-wrap gap-1\" data-ckui=\"letters\">\n {[undefined, ...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 === undefined ? undefined : l === \"#\" ? t(\"groups.otherLetters\") : l.toUpperCase()}\n className=\"min-w-7\"\n onClick={() => filter({ letter: l })}\n >\n {l === undefined ? t(\"groups.all\") : l.toUpperCase()}\n </Button>\n ))}\n </nav>\n {groups.loading && !groups.items.length ? (\n <Rows />\n ) : groups.error && !groups.items.length ? (\n <LoadFailed error={groups.error} message={t(\"groupManager.loadFailed\")} retry={groups.reload} />\n ) : !groups.items.length ? (\n <p className=\"text-muted-foreground\">{t(\"groups.empty\")}</p>\n ) : (\n <ul className=\"grid divide-y divide-border rounded-lg border border-border\" aria-busy={groups.loading}>\n {groups.items.map((g) => (\n <li key={g.id} className=\"flex flex-wrap items-center gap-3 p-3\" data-ckui=\"group-row\" data-slug={g.slug}>\n <div className=\"grid min-w-0 flex-1 gap-0.5\">\n <button type=\"button\" className=\"text-left font-medium break-words hover:underline\" onClick={() => loc.go(`${kind}/${g.id}`)}>\n {g.name || g.slug}\n </button>\n <span className=\"text-xs text-muted-foreground\">{g.slug}</span>\n </div>\n <span className=\"text-sm text-muted-foreground tabular-nums\" title={t(\"groupManager.count\")}>\n {new Intl.NumberFormat(m.language).format(g.count)}\n </span>\n </li>\n ))}\n </ul>\n )}\n {groups.hasMore && (\n <Button variant=\"outline\" size=\"sm\" className=\"justify-self-center\" disabled={groups.loadingMore} onClick={() => void groups.loadMore()}>\n {groups.loadingMore ? t(\"groups.loading\") : t(\"groups.loadMore\")}\n </Button>\n )}\n </div>\n );\n}\n\nfunction Create({ loc, kind, client, labels, onError }: Ctx) {\n return (\n <div className=\"grid gap-4\">\n <Back loc={loc} kind={kind} />\n <GroupEditor\n id={null}\n kind={kind}\n labels={labels}\n client={client}\n onError={onError}\n onCreated={(g) => loc.go(`${kind}/${g.id}`, undefined, { replace: true })}\n />\n </div>\n );\n}\n\nfunction Edit({ loc, kind, client, labels, onError, renderContent, id }: Ctx & { id: string }) {\n return (\n <div className=\"grid gap-4\">\n <Back loc={loc} kind={kind} />\n <GroupEditor\n id={id}\n kind={kind}\n labels={labels}\n client={client}\n onError={onError}\n onMerged={(r) => loc.go(`${kind}/${r.into}`, undefined, { replace: true })}\n >\n {(group) => (\n <GroupMembers\n group={group}\n labels={labels}\n client={client}\n onError={onError}\n renderContent={renderContent}\n onUseCover={(content) => client.entities.update(group.id, { cover: { content_id: content } })}\n />\n )}\n </GroupEditor>\n </div>\n );\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"group-manager.js","names":[],"sources":["../../../src/components/admin/group-manager.tsx"],"sourcesContent":["import { useMemo, type ReactNode } from \"react\";\nimport type { ContentKitClient } from \"../../client/client.js\";\nimport { LETTERS } from \"../../client/group-fields.js\";\nimport type { ContentModel, Membership } from \"../../client/generated/wire.js\";\nimport { useLanguageName, useMessages } from \"../../i18n/context.js\";\nimport { useAdminLocation, useFlowClient, useStaffAccess, type AdminLocation, type FlowClientOptions, type StaffAccess } from \"../../react/admin.js\";\nimport { useGroups, useKinds, type GroupSort } from \"../../react/groups.js\";\nimport { Badge } from \"#ckui/ui/badge\";\nimport { Button } from \"#ckui/ui/button\";\nimport { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from \"#ckui/ui/select\";\nimport { Tabs, TabsList, TabsTrigger } from \"#ckui/ui/tabs\";\nimport { GroupEditor } from \"../groups/editor.js\";\nimport { GroupMembers } from \"../groups/memberships.js\";\nimport { labelOf, type Labels } from \"../groups/parts.js\";\nimport { AdminRoot, LoadFailed, NoAccess, Rows, type AdminFlowProps, type AdminRouteProps } from \"./shell.js\";\n\nexport interface GroupManagerProps extends AdminFlowProps, AdminRouteProps {\n /** The group kinds managed, in tab order; default the content model's site-owned kinds. */\n groupKinds?: readonly string[];\n /** Display names of kinds, attributes, roles and values by identifier. */\n labels?: Labels;\n /** Counts of this content kind; default every kind. */\n contentKind?: string;\n /** One member, e.g. a link with its title; default its content id. */\n renderContent?: (member: Membership) => ReactNode;\n pageSize?: number;\n}\n\n/** Whether the caller may manage groups (root:groups:write). */\nexport function useGroupManagerAccess(o: FlowClientOptions = {}): StaffAccess<\"groups\"> {\n return useStaffAccess([\"groups\"] as const, o);\n}\n\nconst SORTS: readonly GroupSort[] = [\"name\", \"count\", \"newest\"];\n\n/**\n * Staff: groups per kind. A kind's groups by letter, order and language; a\n * new group; a group's editor (GroupEditor) and its members (GroupMembers).\n * Kinds are at basePath/{kind}, a group at basePath/{kind}/{id}, filters in the query.\n */\nexport function GroupManager({ client: own, baseUrl, auth, guard, appearance, className, language, messages, ...p }: GroupManagerProps) {\n const client = useFlowClient({ client: own, baseUrl, auth });\n return (\n <AdminRoot flow=\"group-manager\" appearance={appearance} className={className} language={language} messages={messages} guard={guard}>\n <Manager {...p} client={client} />\n </AdminRoot>\n );\n}\n\ntype Inner = Omit<GroupManagerProps, \"client\" | \"baseUrl\" | \"auth\" | \"guard\" | \"appearance\" | \"className\" | \"language\" | \"messages\"> & { client: ContentKitClient };\ntype Ctx = Inner & { loc: AdminLocation; kind: string; kinds: ContentModel };\n\nfunction Manager({ basePath, navigation, ...p }: Inner) {\n const { t } = useMessages();\n const loc = useAdminLocation(basePath, navigation);\n const access = useGroupManagerAccess({ client: p.client });\n const model = useKinds({ client: p.client });\n const kinds = model.kinds;\n const list = useMemo(\n () =>\n p.groupKinds ??\n Object.entries(kinds?.entity_kinds ?? {})\n .filter(([, k]) => k.owner !== \"user\")\n .map(([name]) => name)\n .sort(),\n [p.groupKinds, kinds],\n );\n if (access.loading || model.loading) return <Rows />;\n if (!access.allowed.groups) return <NoAccess>{t(\"groupManager.noAccess\")}</NoAccess>;\n if (!kinds) return <LoadFailed error={model.error} message={t(\"groupManager.kindsFailed\")} retry={model.reload} />;\n if (!list.length) return <p className=\"text-muted-foreground\">{t(\"groupManager.noKinds\")}</p>;\n const [k, sub] = loc.view.split(\"/\");\n const kind = list.includes(k ?? \"\") ? k! : list[0]!;\n const ctx: Ctx = { ...p, loc, kind, kinds };\n return (\n <>\n {list.length > 1 && (\n <Tabs value={kind} onValueChange={(v) => loc.go(String(v))}>\n <TabsList className=\"flex-wrap group-data-horizontal/tabs:h-auto\">\n {list.map((x) => (\n <TabsTrigger key={x} value={x} className=\"h-7.5\">\n {labelOf(p.labels, x)}\n </TabsTrigger>\n ))}\n </TabsList>\n </Tabs>\n )}\n {!sub ? <List key={kind} {...ctx} /> : sub === \"new\" ? <Create key={kind} {...ctx} /> : <Edit key={sub} {...ctx} id={sub} />}\n </>\n );\n}\n\nfunction Back({ loc, kind }: { loc: AdminLocation; kind: string }) {\n const { t } = useMessages();\n return (\n <Button variant=\"ghost\" size=\"sm\" className=\"justify-self-start\" onClick={() => loc.go(kind)}>\n {t(\"groupManager.back\")}\n </Button>\n );\n}\n\nfunction List({ loc, kind, kinds, client, contentKind, labels, pageSize = 50 }: Ctx) {\n const m = useMessages();\n const { t } = m;\n const languageName = useLanguageName();\n const languages = kinds.languages;\n const letterParam = loc.query.get(\"letter\") ?? \"\";\n const letter = LETTERS.includes(letterParam) ? letterParam : undefined;\n const sortParam = loc.query.get(\"sort\") ?? \"\";\n const sort = (SORTS as readonly string[]).includes(sortParam) ? (sortParam as GroupSort) : \"name\";\n const languageParam = loc.query.get(\"language\") ?? \"\";\n const language = languages.includes(languageParam) ? languageParam : languages[0];\n const filters: { letter?: string; sort?: GroupSort; language?: string } = { letter, sort: sort === \"name\" ? undefined : sort, language: language === languages[0] ? undefined : language };\n const filter = (next: Partial<typeof filters>) => loc.go(kind, { ...filters, ...next });\n const groups = useGroups({ kind, letter, sort, language, contentKind, pageSize }, { client, management: true });\n const label = labelOf(labels, kind);\n return (\n <div className=\"grid gap-4\" data-ckui=\"group-list\" data-kind={kind}>\n <div className=\"flex flex-wrap items-center justify-between gap-2\">\n <h2 className=\"text-base font-semibold\">{label}</h2>\n <Button size=\"sm\" onClick={() => loc.go(`${kind}/new`)}>\n {t(\"groupManager.new\", { kind: label })}\n </Button>\n </div>\n <div className=\"flex flex-wrap items-center gap-2\">\n <Select value={sort} onValueChange={(v) => filter({ sort: v === \"name\" ? undefined : (String(v) as GroupSort) })}>\n <SelectTrigger size=\"sm\" aria-label={t(\"groupManager.sort\")}>\n <SelectValue>{(v: string) => t(`groupManager.sort_${v as GroupSort}`)}</SelectValue>\n </SelectTrigger>\n <SelectContent>\n {SORTS.map((s) => (\n <SelectItem key={s} value={s}>\n {t(`groupManager.sort_${s}`)}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n {languages.length > 1 && (\n <Select value={language} onValueChange={(v) => filter({ language: v === languages[0] ? undefined : String(v) })}>\n <SelectTrigger size=\"sm\" aria-label={t(\"groupManager.language\")}>\n <SelectValue>{(v: string) => languageName(v)}</SelectValue>\n </SelectTrigger>\n <SelectContent>\n {languages.map((l) => (\n <SelectItem key={l} value={l}>\n {languageName(l)}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n )}\n </div>\n <nav aria-label={t(\"groups.byLetter\")} className=\"flex flex-wrap gap-1\" data-ckui=\"letters\">\n {[undefined, ...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 === undefined ? undefined : l === \"#\" ? t(\"groups.otherLetters\") : l.toUpperCase()}\n className=\"min-w-7\"\n onClick={() => filter({ letter: l })}\n >\n {l === undefined ? t(\"groups.all\") : l.toUpperCase()}\n </Button>\n ))}\n </nav>\n {groups.loading && !groups.items.length ? (\n <Rows />\n ) : groups.error && !groups.items.length ? (\n <LoadFailed error={groups.error} message={t(\"groupManager.loadFailed\")} retry={groups.reload} />\n ) : !groups.items.length ? (\n <p className=\"text-muted-foreground\">{t(\"groups.empty\")}</p>\n ) : (\n <ul className=\"grid divide-y divide-border rounded-lg border border-border\" aria-busy={groups.loading}>\n {groups.items.map((g) => (\n <li key={g.id} className=\"flex flex-wrap items-center gap-3 p-3\" data-ckui=\"group-row\" data-slug={g.slug}>\n <div className=\"grid min-w-0 flex-1 gap-0.5\">\n <button type=\"button\" className=\"text-left font-medium break-words hover:underline\" onClick={() => loc.go(`${kind}/${g.id}`)}>\n {g.name || g.slug}\n </button>\n <span className=\"text-xs text-muted-foreground\">{g.slug}</span>\n {g.internal && <Badge variant=\"secondary\" className=\"justify-self-start\">{t(\"groupEditor.internal\")}</Badge>}\n </div>\n <span className=\"text-sm text-muted-foreground tabular-nums\" title={t(\"groupManager.count\")}>\n {new Intl.NumberFormat(m.language).format(g.count)}\n </span>\n </li>\n ))}\n </ul>\n )}\n {groups.hasMore && (\n <Button variant=\"outline\" size=\"sm\" className=\"justify-self-center\" disabled={groups.loadingMore} onClick={() => void groups.loadMore()}>\n {groups.loadingMore ? t(\"groups.loading\") : t(\"groups.loadMore\")}\n </Button>\n )}\n </div>\n );\n}\n\nfunction Create({ loc, kind, client, labels, onError }: Ctx) {\n return (\n <div className=\"grid gap-4\">\n <Back loc={loc} kind={kind} />\n <GroupEditor\n management\n id={null}\n kind={kind}\n labels={labels}\n client={client}\n onError={onError}\n onCreated={(g) => loc.go(`${kind}/${g.id}`, undefined, { replace: true })}\n />\n </div>\n );\n}\n\nfunction Edit({ loc, kind, client, labels, onError, renderContent, id }: Ctx & { id: string }) {\n return (\n <div className=\"grid gap-4\">\n <Back loc={loc} kind={kind} />\n <GroupEditor\n management\n id={id}\n kind={kind}\n labels={labels}\n client={client}\n onError={onError}\n onMerged={(r) => loc.go(`${kind}/${r.into}`, undefined, { replace: true })}\n >\n {(group) => (\n <GroupMembers\n group={group}\n labels={labels}\n client={client}\n onError={onError}\n renderContent={renderContent}\n onUseCover={(content) => client.entities.update(group.id, { cover: { content_id: content } })}\n />\n )}\n </GroupEditor>\n </div>\n );\n}\n"],"mappings":"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"}
@@ -45,5 +45,6 @@ export declare function ContentSections({ content, ...p }: Common & {
45
45
  content: Content;
46
46
  media?: boolean;
47
47
  className?: string;
48
+ management?: boolean;
48
49
  }): import('react').JSX.Element;
49
50
  export {};
@@ -880,6 +880,7 @@ function le({ content: t, ...n }) {
880
880
  className: "grid gap-3 border-t border-border pt-4",
881
881
  "data-ckui": "content-groups",
882
882
  children: /* @__PURE__ */ L(A, {
883
+ management: n.management,
883
884
  content: t.id,
884
885
  contentKind: t.kind,
885
886
  versions: a.versions.hidden ? void 0 : i,
@@ -1 +1 @@
1
- {"version":3,"file":"editors.js","names":[],"sources":["../../../src/components/content/editors.tsx"],"sourcesContent":["import { cn } from \"cn\";\nimport { useEffect, useId, useMemo, useRef, useState, type ReactNode } from \"react\";\nimport type { ContentKitClient } from \"../../client/client.js\";\nimport { fromLocalInput, parseAttributes, toLocalInput } from \"../../client/group-fields.js\";\nimport type { Content, ContentModel, Listing, Rule, Segment, Version } from \"../../client/generated/wire.js\";\nimport { useLanguageName, useMessages } from \"../../i18n/context.js\";\nimport { useContentKitClient, type ContentKitErrorHandler } from \"../../react/context.js\";\nimport { useKinds } from \"../../react/groups.js\";\nimport { useMediaRead } from \"../../react/read.js\";\nimport { usePresets } from \"../../react/public.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 { Switch } from \"#ckui/ui/switch\";\nimport { ReaderManifestEditor } from \"../admin/reader-manifest.js\";\nimport { VideoMediaEditor, videoPaths } from \"../admin/media-item-panel.js\";\nimport { Skeleton } from \"#ckui/ui/skeleton\";\nimport { MediaFolderEditor } from \"../media-folder-editor.js\";\nimport { SortableList } from \"../sortable-list.js\";\nimport { ErrorLine, useAction } from \"../social/parts.js\";\nimport { GroupPicker, labelOf, useGroupNames, type Labels } from \"../groups/parts.js\";\nimport { AttributeFields, formOf } from \"../groups/fields.js\";\nimport { MembershipEditor } from \"../groups/memberships.js\";\nimport { OfferFields } from \"./offer-fields.js\";\n\ninterface Common {\n client?: ContentKitClient;\n onError?: ContentKitErrorHandler;\n labels?: Labels;\n}\n\nconst NONE = \"__none__\";\nconst LISTINGS: readonly Listing[] = [\"listed\", \"members\", \"unlisted\"];\nconst COMMENTS = [\"open\", \"closed\", \"hidden\"] as const;\ntype Comments = (typeof COMMENTS)[number];\nconst LEVELS: readonly Rule[\"level\"][] = [\"public\", \"tier\", \"ppv\", \"group\", \"group_ppv\"];\nconst grouped = (l: Rule[\"level\"]) => l === \"group\" || l === \"group_ppv\";\n\nfunction Section({ title, ckui, children }: { title: ReactNode; ckui: string; children: ReactNode }) {\n return (\n <section className=\"grid gap-3 border-t border-border pt-4\" data-ckui={ckui}>\n <h3 className=\"font-medium\">{title}</h3>\n {children}\n </section>\n );\n}\n\nfunction Saved({ show }: { show: boolean }) {\n const { t } = useMessages();\n return show ? (\n <span role=\"status\" className=\"text-muted-foreground\">\n {t(\"contentEditor.saved\")}\n </span>\n ) : null;\n}\n\n/** The content model's kind, when it loaded. */\nfunction useKind(kind: string, client?: ContentKitClient): { model: ContentModel | null; spec: ContentModel[\"kinds\"][string] | undefined } {\n const { kinds } = useKinds({ client });\n return { model: kinds, spec: kinds?.kinds[kind] };\n}\n\n/** Listing and the kind's declared attributes. */\nexport function ContentDetailsEditor({ content, ...p }: Common & { content: Content }) {\n const { t } = useMessages();\n const client = useContentKitClient(p.client);\n const { spec } = useKind(content.kind, p.client);\n const declared = useMemo(() => spec?.attributes ?? {}, [spec]);\n const [listing, setListing] = useState<Listing>(content.listing);\n const [comments, setComments] = useState(content.comments);\n const [attrs, setAttrs] = useState<Record<string, string | boolean>>({});\n useEffect(() => {\n setListing(content.listing);\n setComments(content.comments);\n setAttrs(formOf(declared, content.attributes));\n }, [content.revision, content.listing, content.comments, content.attributes, declared]);\n const [invalid, setInvalid] = useState<string | null>(null);\n const [saved, setSaved] = useState(false);\n const save = useAction(\"content.save\", p.onError);\n return (\n <Section title={t(\"contentEditor.details\")} ckui=\"content-details\">\n <form\n className=\"grid gap-3\"\n onSubmit={(e) => {\n e.preventDefault();\n setInvalid(null);\n setSaved(false);\n let attributes: Record<string, unknown>;\n try {\n attributes = parseAttributes(declared, attrs);\n } catch (err) {\n return setInvalid((err as Error).message);\n }\n void save.run(() => client.contents.update(content.id, { listing, comments, attributes, revision: content.revision })).then((d) => d && setSaved(true));\n }}\n >\n <div className=\"grid gap-1.5 sm:max-w-xs\">\n <Label>{t(\"contentEditor.listing\")}</Label>\n <Select value={listing} onValueChange={(v) => setListing(v as Listing)}>\n <SelectTrigger size=\"sm\" aria-label={t(\"contentEditor.listing\")}>\n <SelectValue>{(v: string) => t(`contentEditor.listing_${v as Listing}`)}</SelectValue>\n </SelectTrigger>\n <SelectContent>\n {LISTINGS.map((l) => (\n <SelectItem key={l} value={l}>\n {t(`contentEditor.listing_${l}`)}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </div>\n <div className=\"grid gap-1.5 sm:max-w-xs\">\n <Label>{t(\"contentEditor.comments\")}</Label>\n <Select value={comments} onValueChange={(v) => setComments(v as Comments)}>\n <SelectTrigger size=\"sm\" aria-label={t(\"contentEditor.comments\")}>\n <SelectValue>{(v: string) => t(`contentEditor.comments_${v as Comments}`)}</SelectValue>\n </SelectTrigger>\n <SelectContent>\n {COMMENTS.map((c) => (\n <SelectItem key={c} value={c}>\n {t(`contentEditor.comments_${c}`)}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </div>\n <AttributeFields declared={declared} form={attrs} onChange={(n, v) => setAttrs((a) => ({ ...a, [n]: v }))} labels={p.labels} />\n {invalid && <ErrorLine>{invalid}</ErrorLine>}\n <ErrorLine error={save.error} />\n <div className=\"flex items-center gap-3\">\n <Button type=\"submit\" size=\"sm\" disabled={save.pending}>\n {save.pending ? t(\"common.saving\") : t(\"common.save\")}\n </Button>\n <Saved show={saved} />\n </div>\n </form>\n </Section>\n );\n}\n\n/** A rule's form: level, tiers, group (the content's owner group by default), the preview its kind has and when it turns free. */\nfunction RuleFields({ value, onChange, model, kind, owner, labels, client }: { value: Rule; onChange: (r: Rule) => void; model: ContentModel | null; kind: string; owner?: string; labels?: Labels; client: ContentKitClient }) {\n const { t } = useMessages();\n const id = useId();\n const tiers = model?.tiers ?? [];\n const spec = model?.kinds[kind];\n const groupKinds = Object.entries(model?.entity_kinds ?? {})\n .filter(([, g]) => g.sellable || g.auth_scope)\n .map(([k]) => k);\n // Picked once the model has loaded: its first group kind until one is chosen.\n const [chosenKind, setGroupKind] = useState<string>();\n const groupKind = chosenKind ?? groupKinds[0] ?? \"\";\n const named = useGroupNames(value.group_id ? [value.group_id] : [], { client });\n const group = value.group_id ? named.get(value.group_id) : undefined;\n const set = (patch: Partial<Rule>) => onChange({ ...value, ...patch });\n const pages = spec?.presentation === \"reader\";\n const segments = !!spec?.segments;\n return (\n <div className=\"grid gap-3\" data-ckui=\"rule-fields\">\n <div className=\"grid gap-1.5 sm:max-w-xs\">\n <Label>{t(\"contentEditor.access\")}</Label>\n <Select\n value={value.level}\n onValueChange={(v) => {\n const level = v as Rule[\"level\"];\n onChange({ level, group_id: grouped(level) ? value.group_id || owner : undefined, preview: value.preview, free_after: value.free_after });\n }}\n >\n <SelectTrigger size=\"sm\" aria-label={t(\"contentEditor.access\")}>\n <SelectValue>{(v: string) => t(`contentEditor.level_${v as Rule[\"level\"]}`)}</SelectValue>\n </SelectTrigger>\n <SelectContent>\n {LEVELS.filter((l) => (l !== \"tier\" || tiers.length) && (!l.startsWith(\"group\") || groupKinds.length)).map((l) => (\n <SelectItem key={l} value={l}>\n {t(`contentEditor.level_${l}`)}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </div>\n {value.level === \"tier\" && (\n <fieldset className=\"flex flex-wrap gap-3\">\n <legend className=\"sr-only\">{t(\"contentEditor.tiers\")}</legend>\n {tiers.map((tier) => (\n <label key={tier} className=\"flex items-center gap-2\">\n <Switch\n checked={value.tiers?.includes(tier) ?? false}\n onCheckedChange={(on) => set({ tiers: on ? [...(value.tiers ?? []), tier] : (value.tiers ?? []).filter((x) => x !== tier) })}\n aria-label={labelOf(labels, tier)}\n />\n {labelOf(labels, tier)}\n </label>\n ))}\n </fieldset>\n )}\n {grouped(value.level) && (\n <div className=\"flex flex-wrap items-end gap-2\">\n {group || value.group_id ? (\n <span className=\"rounded-md border border-border px-2 py-0.5\" data-ckui=\"rule-group\">\n {group ? group.name || group.slug : value.group_id}\n </span>\n ) : null}\n {groupKinds.length > 1 && (\n <Select value={groupKind} onValueChange={(v) => setGroupKind(String(v))}>\n <SelectTrigger size=\"sm\" aria-label={t(\"groupEditor.edgeKind\")}>\n <SelectValue>{(v: string) => labelOf(labels, v)}</SelectValue>\n </SelectTrigger>\n <SelectContent>\n {groupKinds.map((k) => (\n <SelectItem key={k} value={k}>\n {labelOf(labels, k)}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n )}\n {groupKind && <GroupPicker key={groupKind} kind={groupKind} label={t(\"contentEditor.group\")} client={client} onPick={(g) => set({ group_id: g.id })} />}\n </div>\n )}\n {value.level !== \"public\" && (\n <div className=\"grid gap-3 sm:grid-cols-3\">\n {pages && (\n <div className=\"grid gap-1.5\">\n <Label htmlFor={`${id}-pages`}>{t(\"contentEditor.previewPages\")}</Label>\n <Input\n id={`${id}-pages`}\n className=\"h-8\"\n type=\"number\"\n min={0}\n value={value.preview?.pages ?? \"\"}\n onChange={(e) => set({ preview: { ...value.preview, pages: e.target.value ? Math.max(0, Math.trunc(Number(e.target.value))) : undefined } })}\n />\n </div>\n )}\n {segments && (\n <div className=\"grid gap-1.5\">\n <Label htmlFor={`${id}-segments`}>{t(\"contentEditor.previewSegments\")}</Label>\n <Input\n id={`${id}-segments`}\n className=\"h-8\"\n type=\"number\"\n min={0}\n value={value.preview?.segments ?? \"\"}\n onChange={(e) => set({ preview: { ...value.preview, segments: e.target.value ? Math.max(0, Math.trunc(Number(e.target.value))) : undefined } })}\n />\n </div>\n )}\n <div className=\"grid gap-1.5\">\n <Label htmlFor={`${id}-free`}>{t(\"contentEditor.freeAfter\")}</Label>\n <Input id={`${id}-free`} className=\"h-8\" type=\"datetime-local\" value={toLocalInput(value.free_after)} onChange={(e) => set({ free_after: fromLocalInput(e.target.value) })} />\n </div>\n </div>\n )}\n </div>\n );\n}\n\n/** A rule the server takes: a group level names its group. */\nconst complete = (r: Rule) => !grouped(r.level) || !!r.group_id;\n\n/** A rule as stored: empty previews and absent fields left out. */\nfunction cleanRule(r: Rule): Rule {\n const preview = r.preview && (r.preview.pages || r.preview.segments) ? { pages: r.preview.pages || undefined, segments: r.preview.segments || undefined } : undefined;\n return {\n level: r.level,\n tiers: r.level === \"tier\" ? r.tiers : undefined,\n group_id: r.level === \"group\" || r.level === \"group_ppv\" ? r.group_id : undefined,\n preview: r.level === \"public\" ? undefined : preview,\n free_after: r.level === \"public\" ? undefined : r.free_after,\n };\n}\n\n/** Who may open the content and what it sells for. */\nexport function AccessEditor({ content, ...p }: Common & { content: Content }) {\n const { t } = useMessages();\n const client = useContentKitClient(p.client);\n const { model } = useKind(content.kind, p.client);\n const [rule, setRule] = useState<Rule>(content.access);\n useEffect(() => setRule(content.access), [content.revision, content.access]);\n const [saved, setSaved] = useState(false);\n const save = useAction(\"content.save\", p.onError);\n const offer = useAction(\"offer.save\", p.onError);\n return (\n <Section title={t(\"contentEditor.accessTitle\")} ckui=\"access-editor\">\n <form\n className=\"grid gap-3\"\n onSubmit={(e) => {\n e.preventDefault();\n setSaved(false);\n void save.run(() => client.contents.update(content.id, { access: cleanRule(rule), revision: content.revision })).then((d) => d && setSaved(true));\n }}\n >\n <RuleFields value={rule} onChange={setRule} model={model} kind={content.kind} owner={content.owner_group_id} labels={p.labels} client={client} />\n <ErrorLine error={save.error} />\n <div className=\"flex items-center gap-3\">\n <Button type=\"submit\" size=\"sm\" disabled={save.pending || !complete(rule)}>\n {save.pending ? t(\"common.saving\") : t(\"common.save\")}\n </Button>\n <Saved show={saved} />\n </div>\n </form>\n <OfferFields\n offer={content.offer}\n pending={offer.pending}\n onSell={(terms) => void offer.run(() => client.offers.sell({ content: content.id }, terms))}\n onWithdraw={() => void offer.run(() => client.offers.withdraw({ content: content.id }))}\n />\n <ErrorLine error={offer.error} />\n </Section>\n );\n}\n\n/** A version's name in the editor: its label, else its languages and traits. */\nexport function versionLabel(v: Version, languageName: (l: string) => string, labels?: Labels): string {\n return v.label || [...v.languages.map(languageName), ...v.traits.map((x) => labelOf(labels, x))].join(\" · \");\n}\n\n/**\n * A content's versions: order, languages, traits, label, state and\n * schedule, an access override and its own offer, segments (chapters) and\n * the version's media folder; add and delete. A kind whose one version is\n * hidden shows only that version's segments and media.\n */\nexport function VersionsEditor({ content, media = true, ...p }: Common & { content: Content; media?: boolean }) {\n const { t } = useMessages();\n const client = useContentKitClient(p.client);\n const languageName = useLanguageName();\n const { model, spec } = useKind(content.kind, p.client);\n const order = useAction(\"content.save\", p.onError);\n const add = useAction(\"content.save\", p.onError);\n const [open, setOpen] = useState<string | null>(null);\n const versions = useMemo(() => [...content.versions].sort((a, b) => a.position - b.position), [content.versions]);\n if (!spec) return null;\n if (spec.versions.hidden) {\n const only = versions[0];\n if (!only || (!media && !spec.segments)) return null;\n return (\n <Section title={t(\"contentEditor.media\")} ckui=\"version-media\">\n {spec.segments && <SegmentsEditor content={content} version={only} {...p} />}\n {media && <VersionMedia content={content} version={only} model={model} {...p} />}\n </Section>\n );\n }\n const languages = model?.languages ?? [];\n return (\n <Section title={t(\"contentEditor.versions\")} ckui=\"versions-editor\">\n <SortableList\n items={versions}\n id={(v) => v.id}\n name={(v) => versionLabel(v, languageName, p.labels)}\n label={t(\"contentEditor.versions\")}\n disabled={order.pending || versions.length < 2}\n onMove={(from, to) => {\n const ids = versions.map((v) => v.id);\n const [moved] = ids.splice(from, 1);\n ids.splice(to, 0, moved!);\n void order.run(() => client.contents.orderVersions(content.id, ids));\n }}\n >\n {(v, handle) => (\n <div className=\"grid gap-2 rounded-md border border-border p-2\" data-ckui=\"version-row\" data-version={v.id}>\n <div className=\"flex flex-wrap items-center gap-2\">\n {versions.length > 1 && handle}\n <span className=\"min-w-0 flex-1 font-medium break-words\">{versionLabel(v, languageName, p.labels)}</span>\n <Badge variant={v.live ? \"default\" : \"outline\"}>{t(v.live ? \"contentEditor.live\" : v.state === \"draft\" ? \"contentManager.draft\" : \"contentManager.scheduled\")}</Badge>\n {v.access && <Badge variant=\"secondary\">{t(`contentEditor.level_${v.access.level}`)}</Badge>}\n {v.pages ? <span className=\"text-xs text-muted-foreground\">{t(\"contentEditor.pageCount\", { count: v.pages })}</span> : null}\n <Button type=\"button\" size=\"xs\" variant=\"ghost\" aria-expanded={open === v.id} onClick={() => setOpen(open === v.id ? null : v.id)}>\n {t(open === v.id ? \"contentEditor.close\" : \"contentEditor.edit\")}\n </Button>\n </div>\n {open === v.id && <VersionForm content={content} version={v} model={model} media={media} {...p} />}\n </div>\n )}\n </SortableList>\n <ErrorLine error={order.error} />\n <AddVersion\n languages={languages}\n many={spec?.versions.languages === \"many\"}\n pending={add.pending}\n // A new version is a draft: open it for its media.\n onAdd={(input) => void add.run(() => client.contents.addVersion(content.id, input)).then((v) => v && setOpen(v.id))}\n />\n <ErrorLine error={add.error} />\n </Section>\n );\n}\n\nfunction LanguageFields({ languages, value, many, onChange }: { languages: readonly string[]; value: readonly string[]; many: boolean; onChange: (v: string[]) => void }) {\n const { t } = useMessages();\n const languageName = useLanguageName();\n if (!many)\n return (\n <Select value={value[0] ?? NONE} onValueChange={(v) => onChange(v === NONE ? [] : [String(v)])}>\n <SelectTrigger size=\"sm\" aria-label={t(\"contentEditor.versionLanguage\")}>\n <SelectValue>{(v: string) => (v === NONE ? t(\"contentEditor.chooseLanguage\") : languageName(v))}</SelectValue>\n </SelectTrigger>\n <SelectContent>\n {languages.map((l) => (\n <SelectItem key={l} value={l}>\n {languageName(l)}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n );\n return (\n <fieldset className=\"flex flex-wrap gap-3\">\n <legend className=\"sr-only\">{t(\"contentEditor.versionLanguages\")}</legend>\n {languages.map((l) => (\n <label key={l} className=\"flex items-center gap-1.5\">\n <Switch size=\"sm\" checked={value.includes(l)} onCheckedChange={(on) => onChange(on ? [...value, l] : value.filter((x) => x !== l))} aria-label={languageName(l)} />\n {languageName(l)}\n </label>\n ))}\n </fieldset>\n );\n}\n\nfunction AddVersion({ languages, many, pending, onAdd }: { languages: readonly string[]; many: boolean; pending: boolean; onAdd: (v: { languages: string[] }) => void }) {\n const { t } = useMessages();\n const [langs, setLangs] = useState<string[]>([]);\n return (\n <div className=\"flex flex-wrap items-center gap-2\" data-ckui=\"add-version\">\n <LanguageFields languages={languages} value={langs} many={many} onChange={setLangs} />\n <Button\n type=\"button\"\n size=\"sm\"\n variant=\"outline\"\n disabled={pending || !langs.length}\n onClick={() => {\n onAdd({ languages: langs });\n setLangs([]);\n }}\n >\n {t(\"contentEditor.addVersion\")}\n </Button>\n </div>\n );\n}\n\nfunction VersionForm({ content, version: v, model, media, ...p }: Common & { content: Content; version: Version; model: ContentModel | null; media: boolean }) {\n const { t } = useMessages();\n const id = useId();\n const client = useContentKitClient(p.client);\n const spec = model?.kinds[content.kind];\n const [langs, setLangs] = useState<string[]>(v.languages);\n const [traits, setTraits] = useState<string[]>(v.traits);\n const [label, setLabel] = useState(v.label ?? \"\");\n const [draft, setDraft] = useState(v.state === \"draft\");\n const [at, setAt] = useState(toLocalInput(v.publish_at));\n const [own, setOwn] = useState(!!v.access);\n const [rule, setRule] = useState<Rule>(v.access ?? content.access);\n const [saved, setSaved] = useState(false);\n const save = useAction(\"content.save\", p.onError);\n const remove = useAction(\"content.save\", p.onError);\n const offer = useAction(\"offer.save\", p.onError);\n return (\n <div className=\"grid gap-4 pt-2\">\n <form\n className=\"grid gap-3\"\n onSubmit={(e) => {\n e.preventDefault();\n setSaved(false);\n void save\n .run(() =>\n client.contents.updateVersion(content.id, v.id, {\n languages: langs,\n traits,\n label: label.trim(),\n state: draft ? \"draft\" : \"published\",\n publish_at: fromLocalInput(at),\n ...(own ? { access: cleanRule(rule) } : { clear_access: !!v.access }),\n }),\n )\n .then((d) => d && setSaved(true));\n }}\n >\n <LanguageFields languages={model?.languages ?? []} value={langs} many={spec?.versions.languages === \"many\"} onChange={setLangs} />\n {!!spec?.versions.traits?.length && (\n <fieldset className=\"flex flex-wrap gap-3\">\n <legend className=\"sr-only\">{t(\"contentEditor.traits\")}</legend>\n {spec.versions.traits.map((x) => (\n <label key={x} className=\"flex items-center gap-1.5\">\n <Switch size=\"sm\" checked={traits.includes(x)} onCheckedChange={(on) => setTraits(on ? [...traits, x] : traits.filter((y) => y !== x))} aria-label={labelOf(p.labels, x)} />\n {labelOf(p.labels, x)}\n </label>\n ))}\n </fieldset>\n )}\n <div className=\"grid gap-3 sm:grid-cols-2\">\n <div className=\"grid gap-1.5\">\n <Label htmlFor={`${id}-label`}>{t(\"contentEditor.versionLabel\")}</Label>\n <Input id={`${id}-label`} className=\"h-8\" value={label} onChange={(e) => setLabel(e.target.value)} />\n </div>\n <div className=\"grid gap-1.5\">\n <Label htmlFor={`${id}-at`}>{t(\"contentEditor.versionPublishAt\")}</Label>\n <Input id={`${id}-at`} className=\"h-8\" type=\"datetime-local\" value={at} onChange={(e) => setAt(e.target.value)} />\n </div>\n </div>\n <label className=\"flex items-center gap-2\">\n <Switch size=\"sm\" checked={draft} onCheckedChange={setDraft} />\n {t(\"contentEditor.versionDraft\")}\n </label>\n <label className=\"flex items-center gap-2\">\n <Switch size=\"sm\" checked={own} onCheckedChange={setOwn} />\n {t(\"contentEditor.ownAccess\")}\n </label>\n {own && <RuleFields value={rule} onChange={setRule} model={model} kind={content.kind} owner={content.owner_group_id} labels={p.labels} client={client} />}\n <ErrorLine error={save.error} />\n <div className=\"flex flex-wrap items-center gap-3\">\n <Button type=\"submit\" size=\"sm\" disabled={save.pending || !langs.length || (own && !complete(rule))}>\n {save.pending ? t(\"common.saving\") : t(\"common.save\")}\n </Button>\n <Saved show={saved} />\n <Button type=\"button\" size=\"sm\" variant=\"destructive\" className=\"ms-auto\" disabled={remove.pending} onClick={() => void remove.run(() => client.contents.removeVersion(content.id, v.id))}>\n {t(\"contentEditor.deleteVersion\")}\n </Button>\n </div>\n <ErrorLine error={remove.error} />\n </form>\n <OfferFields\n offer={v.offer}\n pending={offer.pending}\n onSell={(terms) => void offer.run(() => client.offers.sell({ content: content.id, version: v.id }, terms))}\n onWithdraw={() => void offer.run(() => client.offers.withdraw({ content: content.id, version: v.id }))}\n />\n <ErrorLine error={offer.error} />\n {spec?.segments && <SegmentsEditor content={content} version={v} {...p} />}\n {media && <VersionCover content={content} version={v} {...p} />}\n {media && <VersionMedia content={content} version={v} model={model} {...p} />}\n {media && spec?.presentation === \"reader\" && <ReaderManifestEditor content={content.id} version={v.id} client={p.client} onError={p.onError} />}\n </div>\n );\n}\n\n/**\n * A version's own cover, where its kind has covers: the cover upload its\n * editors selected, else its first. Versions share no files.\n */\nexport function VersionCover({ content, version: v, ...p }: Common & { content: Content; version: Version }) {\n const { t } = useMessages();\n const client = useContentKitClient(p.client);\n const { presets } = usePresets({ client });\n const save = useAction(\"content.save\", p.onError);\n const input = useRef<HTMLInputElement>(null);\n const [fresh, setFresh] = useState<string | null>(null);\n useEffect(() => () => void (fresh && URL.revokeObjectURL(fresh)), [fresh]);\n if (!presets.some((r) => r.kind === content.kind && r.name === \"cover\")) return null;\n const src = fresh ?? v.cover?.url;\n const pick = (file: File | null) =>\n void save.run(async () => {\n if (!file) {\n setFresh(null);\n return client.contents.setCover(content.id, v.id, null);\n }\n const ref = { kind: content.kind, id: content.id, version: v.id };\n const up = await client.media.uploadNamed(ref, file, { path: await client.media.presetPath(content.kind, \"cover\", file) });\n const saved = await client.contents.setCover(content.id, v.id, up.name);\n if (typeof URL.createObjectURL === \"function\") setFresh(URL.createObjectURL(file));\n return saved;\n });\n return (\n <div className=\"grid gap-1.5\" data-ckui=\"version-cover\">\n <span className=\"text-sm font-medium\">{t(\"contentManager.cover\")}</span>\n <div className=\"flex flex-wrap items-center gap-3\">\n {src ? <img src={src} alt=\"\" className=\"h-20 w-36 rounded-md border border-border object-cover\" /> : <span className=\"text-muted-foreground\">{t(\"contentManager.noCover\")}</span>}\n <Button type=\"button\" size=\"sm\" variant=\"outline\" disabled={save.pending} onClick={() => input.current?.click()}>\n {t(src ? \"pollEditor.replaceImage\" : \"contentManager.addCover\")}\n </Button>\n {v.cover?.image && (\n <Button type=\"button\" size=\"sm\" variant=\"ghost\" disabled={save.pending} onClick={() => pick(null)}>\n {t(\"pollEditor.removeImage\")}\n </Button>\n )}\n <input\n ref={input}\n type=\"file\"\n accept=\"image/*\"\n hidden\n aria-label={t(\"contentManager.cover\")}\n onChange={(e) => {\n const f = e.target.files?.[0];\n e.target.value = \"\";\n if (f) pick(f);\n }}\n />\n </div>\n <ErrorLine error={save.error} />\n </div>\n );\n}\n\n/**\n * A version's media: a video kind's source, poster and subtitles (by its\n * upload rules), else its upload folders. Uploads to a version that is not\n * live are added as they finish; a live one's wait for \"Add\".\n */\nfunction VersionMedia({ content, version, model, ...p }: Common & { content: Content; version: Version; model: ContentModel | null }) {\n const { t } = useMessages();\n const languageName = useLanguageName();\n const item = useMemo(() => ({ kind: content.kind, id: content.id, version: version.id }), [content.kind, content.id, version.id]);\n const r = useMediaRead(item, { editor: true, client: p.client });\n const languages = useMemo(() => (model?.languages ?? []).map((l) => ({ value: l, label: languageName(l) })), [model, languageName]);\n if (!r.read && r.loading) return <Skeleton className=\"h-24 w-full\" />;\n if (r.read?.uploads && videoPaths(r.read.uploads).source) return <VideoMediaEditor item={item} languages={languages} client={p.client} onError={p.onError} />;\n return <MediaFolderEditor item={item} commit={version.live ? \"manual\" : \"auto\"} label={t(\"contentEditor.media\")} client={p.client} onError={p.onError} />;\n}\n\ntype Row = { title: string; start: string; end: string; release: string };\n\n/** A version's segments (chapters): page ranges with titles and release times. */\nexport function SegmentsEditor({ content, version, ...p }: Common & { content: Content; version: Version }) {\n const { t } = useMessages();\n const client = useContentKitClient(p.client);\n const seed = () => version.segments.map((s) => ({ title: s.title ?? \"\", start: String(s.start), end: String(s.end), release: toLocalInput(s.release_at) }));\n const [rows, setRows] = useState<Row[]>(seed);\n // Seeded again when the stored segments change.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n useEffect(() => setRows(seed()), [JSON.stringify(version.segments)]);\n const [saved, setSaved] = useState(false);\n const save = useAction(\"content.save\", p.onError);\n const set = (i: number, patch: Partial<Row>) => {\n setSaved(false);\n setRows((r) => r.map((x, j) => (j === i ? { ...x, ...patch } : x)));\n };\n const valid = rows.every((r) => /^\\d+$/.test(r.start) && /^\\d+$/.test(r.end) && Number(r.end) > Number(r.start));\n return (\n <div className=\"grid gap-2\" data-ckui=\"segments-editor\">\n <h4 className=\"text-sm font-medium\">{t(\"contentEditor.segments\")}</h4>\n {rows.length === 0 && <p className=\"text-muted-foreground\">{t(\"contentEditor.noSegments\")}</p>}\n {rows.map((r, i) => (\n <div key={i} className=\"flex flex-wrap items-center gap-2\" data-ckui=\"segment-row\">\n <span className=\"w-6 text-xs text-muted-foreground tabular-nums\">{i + 1}</span>\n <Input className=\"h-8 w-40\" aria-label={t(\"contentEditor.segmentTitle\", { n: i + 1 })} placeholder={t(\"contentEditor.segmentTitlePlaceholder\")} value={r.title} onChange={(e) => set(i, { title: e.target.value })} />\n <Input className=\"h-8 w-20\" type=\"number\" min={0} aria-label={t(\"contentEditor.segmentStart\", { n: i + 1 })} value={r.start} onChange={(e) => set(i, { start: e.target.value })} />\n <span aria-hidden>–</span>\n <Input className=\"h-8 w-20\" type=\"number\" min={1} aria-label={t(\"contentEditor.segmentEnd\", { n: i + 1 })} value={r.end} onChange={(e) => set(i, { end: e.target.value })} />\n <Input className=\"h-8 w-48\" type=\"datetime-local\" aria-label={t(\"contentEditor.segmentRelease\", { n: i + 1 })} value={r.release} onChange={(e) => set(i, { release: e.target.value })} />\n <Button type=\"button\" size=\"xs\" variant=\"ghost\" onClick={() => setRows((x) => x.filter((_, j) => j !== i))}>\n {t(\"common.remove\")}\n </Button>\n </div>\n ))}\n <div className=\"flex flex-wrap items-center gap-2\">\n <Button\n type=\"button\"\n size=\"sm\"\n variant=\"outline\"\n onClick={() => {\n const last = rows.at(-1);\n const start = last ? Number(last.end) || 0 : 0;\n setRows((x) => [...x, { title: \"\", start: String(start), end: String(start + 1), release: \"\" }]);\n }}\n >\n {t(\"contentEditor.addSegment\")}\n </Button>\n <Button\n type=\"button\"\n size=\"sm\"\n disabled={save.pending || !valid}\n onClick={() => {\n setSaved(false);\n const segments: Segment[] = rows.map((r, i) => ({ position: i + 1, title: r.title.trim() || undefined, start: Number(r.start), end: Number(r.end), release_at: fromLocalInput(r.release), released: false }));\n void save.run(() => client.contents.setSegments(content.id, version.id, segments)).then((d) => d && setSaved(true));\n }}\n >\n {t(\"contentEditor.saveSegments\")}\n </Button>\n <Saved show={saved} />\n </div>\n <ErrorLine error={save.error} />\n </div>\n );\n}\n\n/** Every editor section of an existing content: details, access and price, versions, groups. */\nexport function ContentSections({ content, ...p }: Common & { content: Content; media?: boolean; className?: string }) {\n const languageName = useLanguageName();\n const versions = useMemo(() => content.versions.map((v) => ({ id: v.id, label: versionLabel(v, languageName, p.labels) })), [content.versions, languageName, p.labels]);\n const { spec } = useKind(content.kind, p.client);\n return (\n <div className={cn(\"grid gap-6\", p.className)} data-ckui=\"content-sections\">\n <ContentDetailsEditor content={content} {...p} />\n <AccessEditor content={content} {...p} />\n <VersionsEditor content={content} {...p} />\n {!!spec?.entities?.length && (\n <section className=\"grid gap-3 border-t border-border pt-4\" data-ckui=\"content-groups\">\n <MembershipEditor content={content.id} contentKind={content.kind} versions={spec.versions.hidden ? undefined : versions} labels={p.labels} client={p.client} onError={p.onError} />\n </section>\n )}\n </div>\n );\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"editors.js","names":[],"sources":["../../../src/components/content/editors.tsx"],"sourcesContent":["import { cn } from \"cn\";\nimport { useEffect, useId, useMemo, useRef, useState, type ReactNode } from \"react\";\nimport type { ContentKitClient } from \"../../client/client.js\";\nimport { fromLocalInput, parseAttributes, toLocalInput } from \"../../client/group-fields.js\";\nimport type { Content, ContentModel, Listing, Rule, Segment, Version } from \"../../client/generated/wire.js\";\nimport { useLanguageName, useMessages } from \"../../i18n/context.js\";\nimport { useContentKitClient, type ContentKitErrorHandler } from \"../../react/context.js\";\nimport { useKinds } from \"../../react/groups.js\";\nimport { useMediaRead } from \"../../react/read.js\";\nimport { usePresets } from \"../../react/public.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 { Switch } from \"#ckui/ui/switch\";\nimport { ReaderManifestEditor } from \"../admin/reader-manifest.js\";\nimport { VideoMediaEditor, videoPaths } from \"../admin/media-item-panel.js\";\nimport { Skeleton } from \"#ckui/ui/skeleton\";\nimport { MediaFolderEditor } from \"../media-folder-editor.js\";\nimport { SortableList } from \"../sortable-list.js\";\nimport { ErrorLine, useAction } from \"../social/parts.js\";\nimport { GroupPicker, labelOf, useGroupNames, type Labels } from \"../groups/parts.js\";\nimport { AttributeFields, formOf } from \"../groups/fields.js\";\nimport { MembershipEditor } from \"../groups/memberships.js\";\nimport { OfferFields } from \"./offer-fields.js\";\n\ninterface Common {\n client?: ContentKitClient;\n onError?: ContentKitErrorHandler;\n labels?: Labels;\n}\n\nconst NONE = \"__none__\";\nconst LISTINGS: readonly Listing[] = [\"listed\", \"members\", \"unlisted\"];\nconst COMMENTS = [\"open\", \"closed\", \"hidden\"] as const;\ntype Comments = (typeof COMMENTS)[number];\nconst LEVELS: readonly Rule[\"level\"][] = [\"public\", \"tier\", \"ppv\", \"group\", \"group_ppv\"];\nconst grouped = (l: Rule[\"level\"]) => l === \"group\" || l === \"group_ppv\";\n\nfunction Section({ title, ckui, children }: { title: ReactNode; ckui: string; children: ReactNode }) {\n return (\n <section className=\"grid gap-3 border-t border-border pt-4\" data-ckui={ckui}>\n <h3 className=\"font-medium\">{title}</h3>\n {children}\n </section>\n );\n}\n\nfunction Saved({ show }: { show: boolean }) {\n const { t } = useMessages();\n return show ? (\n <span role=\"status\" className=\"text-muted-foreground\">\n {t(\"contentEditor.saved\")}\n </span>\n ) : null;\n}\n\n/** The content model's kind, when it loaded. */\nfunction useKind(kind: string, client?: ContentKitClient): { model: ContentModel | null; spec: ContentModel[\"kinds\"][string] | undefined } {\n const { kinds } = useKinds({ client });\n return { model: kinds, spec: kinds?.kinds[kind] };\n}\n\n/** Listing and the kind's declared attributes. */\nexport function ContentDetailsEditor({ content, ...p }: Common & { content: Content }) {\n const { t } = useMessages();\n const client = useContentKitClient(p.client);\n const { spec } = useKind(content.kind, p.client);\n const declared = useMemo(() => spec?.attributes ?? {}, [spec]);\n const [listing, setListing] = useState<Listing>(content.listing);\n const [comments, setComments] = useState(content.comments);\n const [attrs, setAttrs] = useState<Record<string, string | boolean>>({});\n useEffect(() => {\n setListing(content.listing);\n setComments(content.comments);\n setAttrs(formOf(declared, content.attributes));\n }, [content.revision, content.listing, content.comments, content.attributes, declared]);\n const [invalid, setInvalid] = useState<string | null>(null);\n const [saved, setSaved] = useState(false);\n const save = useAction(\"content.save\", p.onError);\n return (\n <Section title={t(\"contentEditor.details\")} ckui=\"content-details\">\n <form\n className=\"grid gap-3\"\n onSubmit={(e) => {\n e.preventDefault();\n setInvalid(null);\n setSaved(false);\n let attributes: Record<string, unknown>;\n try {\n attributes = parseAttributes(declared, attrs);\n } catch (err) {\n return setInvalid((err as Error).message);\n }\n void save.run(() => client.contents.update(content.id, { listing, comments, attributes, revision: content.revision })).then((d) => d && setSaved(true));\n }}\n >\n <div className=\"grid gap-1.5 sm:max-w-xs\">\n <Label>{t(\"contentEditor.listing\")}</Label>\n <Select value={listing} onValueChange={(v) => setListing(v as Listing)}>\n <SelectTrigger size=\"sm\" aria-label={t(\"contentEditor.listing\")}>\n <SelectValue>{(v: string) => t(`contentEditor.listing_${v as Listing}`)}</SelectValue>\n </SelectTrigger>\n <SelectContent>\n {LISTINGS.map((l) => (\n <SelectItem key={l} value={l}>\n {t(`contentEditor.listing_${l}`)}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </div>\n <div className=\"grid gap-1.5 sm:max-w-xs\">\n <Label>{t(\"contentEditor.comments\")}</Label>\n <Select value={comments} onValueChange={(v) => setComments(v as Comments)}>\n <SelectTrigger size=\"sm\" aria-label={t(\"contentEditor.comments\")}>\n <SelectValue>{(v: string) => t(`contentEditor.comments_${v as Comments}`)}</SelectValue>\n </SelectTrigger>\n <SelectContent>\n {COMMENTS.map((c) => (\n <SelectItem key={c} value={c}>\n {t(`contentEditor.comments_${c}`)}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </div>\n <AttributeFields declared={declared} form={attrs} onChange={(n, v) => setAttrs((a) => ({ ...a, [n]: v }))} labels={p.labels} />\n {invalid && <ErrorLine>{invalid}</ErrorLine>}\n <ErrorLine error={save.error} />\n <div className=\"flex items-center gap-3\">\n <Button type=\"submit\" size=\"sm\" disabled={save.pending}>\n {save.pending ? t(\"common.saving\") : t(\"common.save\")}\n </Button>\n <Saved show={saved} />\n </div>\n </form>\n </Section>\n );\n}\n\n/** A rule's form: level, tiers, group (the content's owner group by default), the preview its kind has and when it turns free. */\nfunction RuleFields({ value, onChange, model, kind, owner, labels, client }: { value: Rule; onChange: (r: Rule) => void; model: ContentModel | null; kind: string; owner?: string; labels?: Labels; client: ContentKitClient }) {\n const { t } = useMessages();\n const id = useId();\n const tiers = model?.tiers ?? [];\n const spec = model?.kinds[kind];\n const groupKinds = Object.entries(model?.entity_kinds ?? {})\n .filter(([, g]) => g.sellable || g.auth_scope)\n .map(([k]) => k);\n // Picked once the model has loaded: its first group kind until one is chosen.\n const [chosenKind, setGroupKind] = useState<string>();\n const groupKind = chosenKind ?? groupKinds[0] ?? \"\";\n const named = useGroupNames(value.group_id ? [value.group_id] : [], { client });\n const group = value.group_id ? named.get(value.group_id) : undefined;\n const set = (patch: Partial<Rule>) => onChange({ ...value, ...patch });\n const pages = spec?.presentation === \"reader\";\n const segments = !!spec?.segments;\n return (\n <div className=\"grid gap-3\" data-ckui=\"rule-fields\">\n <div className=\"grid gap-1.5 sm:max-w-xs\">\n <Label>{t(\"contentEditor.access\")}</Label>\n <Select\n value={value.level}\n onValueChange={(v) => {\n const level = v as Rule[\"level\"];\n onChange({ level, group_id: grouped(level) ? value.group_id || owner : undefined, preview: value.preview, free_after: value.free_after });\n }}\n >\n <SelectTrigger size=\"sm\" aria-label={t(\"contentEditor.access\")}>\n <SelectValue>{(v: string) => t(`contentEditor.level_${v as Rule[\"level\"]}`)}</SelectValue>\n </SelectTrigger>\n <SelectContent>\n {LEVELS.filter((l) => (l !== \"tier\" || tiers.length) && (!l.startsWith(\"group\") || groupKinds.length)).map((l) => (\n <SelectItem key={l} value={l}>\n {t(`contentEditor.level_${l}`)}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </div>\n {value.level === \"tier\" && (\n <fieldset className=\"flex flex-wrap gap-3\">\n <legend className=\"sr-only\">{t(\"contentEditor.tiers\")}</legend>\n {tiers.map((tier) => (\n <label key={tier} className=\"flex items-center gap-2\">\n <Switch\n checked={value.tiers?.includes(tier) ?? false}\n onCheckedChange={(on) => set({ tiers: on ? [...(value.tiers ?? []), tier] : (value.tiers ?? []).filter((x) => x !== tier) })}\n aria-label={labelOf(labels, tier)}\n />\n {labelOf(labels, tier)}\n </label>\n ))}\n </fieldset>\n )}\n {grouped(value.level) && (\n <div className=\"flex flex-wrap items-end gap-2\">\n {group || value.group_id ? (\n <span className=\"rounded-md border border-border px-2 py-0.5\" data-ckui=\"rule-group\">\n {group ? group.name || group.slug : value.group_id}\n </span>\n ) : null}\n {groupKinds.length > 1 && (\n <Select value={groupKind} onValueChange={(v) => setGroupKind(String(v))}>\n <SelectTrigger size=\"sm\" aria-label={t(\"groupEditor.edgeKind\")}>\n <SelectValue>{(v: string) => labelOf(labels, v)}</SelectValue>\n </SelectTrigger>\n <SelectContent>\n {groupKinds.map((k) => (\n <SelectItem key={k} value={k}>\n {labelOf(labels, k)}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n )}\n {groupKind && <GroupPicker key={groupKind} kind={groupKind} label={t(\"contentEditor.group\")} client={client} onPick={(g) => set({ group_id: g.id })} />}\n </div>\n )}\n {value.level !== \"public\" && (\n <div className=\"grid gap-3 sm:grid-cols-3\">\n {pages && (\n <div className=\"grid gap-1.5\">\n <Label htmlFor={`${id}-pages`}>{t(\"contentEditor.previewPages\")}</Label>\n <Input\n id={`${id}-pages`}\n className=\"h-8\"\n type=\"number\"\n min={0}\n value={value.preview?.pages ?? \"\"}\n onChange={(e) => set({ preview: { ...value.preview, pages: e.target.value ? Math.max(0, Math.trunc(Number(e.target.value))) : undefined } })}\n />\n </div>\n )}\n {segments && (\n <div className=\"grid gap-1.5\">\n <Label htmlFor={`${id}-segments`}>{t(\"contentEditor.previewSegments\")}</Label>\n <Input\n id={`${id}-segments`}\n className=\"h-8\"\n type=\"number\"\n min={0}\n value={value.preview?.segments ?? \"\"}\n onChange={(e) => set({ preview: { ...value.preview, segments: e.target.value ? Math.max(0, Math.trunc(Number(e.target.value))) : undefined } })}\n />\n </div>\n )}\n <div className=\"grid gap-1.5\">\n <Label htmlFor={`${id}-free`}>{t(\"contentEditor.freeAfter\")}</Label>\n <Input id={`${id}-free`} className=\"h-8\" type=\"datetime-local\" value={toLocalInput(value.free_after)} onChange={(e) => set({ free_after: fromLocalInput(e.target.value) })} />\n </div>\n </div>\n )}\n </div>\n );\n}\n\n/** A rule the server takes: a group level names its group. */\nconst complete = (r: Rule) => !grouped(r.level) || !!r.group_id;\n\n/** A rule as stored: empty previews and absent fields left out. */\nfunction cleanRule(r: Rule): Rule {\n const preview = r.preview && (r.preview.pages || r.preview.segments) ? { pages: r.preview.pages || undefined, segments: r.preview.segments || undefined } : undefined;\n return {\n level: r.level,\n tiers: r.level === \"tier\" ? r.tiers : undefined,\n group_id: r.level === \"group\" || r.level === \"group_ppv\" ? r.group_id : undefined,\n preview: r.level === \"public\" ? undefined : preview,\n free_after: r.level === \"public\" ? undefined : r.free_after,\n };\n}\n\n/** Who may open the content and what it sells for. */\nexport function AccessEditor({ content, ...p }: Common & { content: Content }) {\n const { t } = useMessages();\n const client = useContentKitClient(p.client);\n const { model } = useKind(content.kind, p.client);\n const [rule, setRule] = useState<Rule>(content.access);\n useEffect(() => setRule(content.access), [content.revision, content.access]);\n const [saved, setSaved] = useState(false);\n const save = useAction(\"content.save\", p.onError);\n const offer = useAction(\"offer.save\", p.onError);\n return (\n <Section title={t(\"contentEditor.accessTitle\")} ckui=\"access-editor\">\n <form\n className=\"grid gap-3\"\n onSubmit={(e) => {\n e.preventDefault();\n setSaved(false);\n void save.run(() => client.contents.update(content.id, { access: cleanRule(rule), revision: content.revision })).then((d) => d && setSaved(true));\n }}\n >\n <RuleFields value={rule} onChange={setRule} model={model} kind={content.kind} owner={content.owner_group_id} labels={p.labels} client={client} />\n <ErrorLine error={save.error} />\n <div className=\"flex items-center gap-3\">\n <Button type=\"submit\" size=\"sm\" disabled={save.pending || !complete(rule)}>\n {save.pending ? t(\"common.saving\") : t(\"common.save\")}\n </Button>\n <Saved show={saved} />\n </div>\n </form>\n <OfferFields\n offer={content.offer}\n pending={offer.pending}\n onSell={(terms) => void offer.run(() => client.offers.sell({ content: content.id }, terms))}\n onWithdraw={() => void offer.run(() => client.offers.withdraw({ content: content.id }))}\n />\n <ErrorLine error={offer.error} />\n </Section>\n );\n}\n\n/** A version's name in the editor: its label, else its languages and traits. */\nexport function versionLabel(v: Version, languageName: (l: string) => string, labels?: Labels): string {\n return v.label || [...v.languages.map(languageName), ...v.traits.map((x) => labelOf(labels, x))].join(\" · \");\n}\n\n/**\n * A content's versions: order, languages, traits, label, state and\n * schedule, an access override and its own offer, segments (chapters) and\n * the version's media folder; add and delete. A kind whose one version is\n * hidden shows only that version's segments and media.\n */\nexport function VersionsEditor({ content, media = true, ...p }: Common & { content: Content; media?: boolean }) {\n const { t } = useMessages();\n const client = useContentKitClient(p.client);\n const languageName = useLanguageName();\n const { model, spec } = useKind(content.kind, p.client);\n const order = useAction(\"content.save\", p.onError);\n const add = useAction(\"content.save\", p.onError);\n const [open, setOpen] = useState<string | null>(null);\n const versions = useMemo(() => [...content.versions].sort((a, b) => a.position - b.position), [content.versions]);\n if (!spec) return null;\n if (spec.versions.hidden) {\n const only = versions[0];\n if (!only || (!media && !spec.segments)) return null;\n return (\n <Section title={t(\"contentEditor.media\")} ckui=\"version-media\">\n {spec.segments && <SegmentsEditor content={content} version={only} {...p} />}\n {media && <VersionMedia content={content} version={only} model={model} {...p} />}\n </Section>\n );\n }\n const languages = model?.languages ?? [];\n return (\n <Section title={t(\"contentEditor.versions\")} ckui=\"versions-editor\">\n <SortableList\n items={versions}\n id={(v) => v.id}\n name={(v) => versionLabel(v, languageName, p.labels)}\n label={t(\"contentEditor.versions\")}\n disabled={order.pending || versions.length < 2}\n onMove={(from, to) => {\n const ids = versions.map((v) => v.id);\n const [moved] = ids.splice(from, 1);\n ids.splice(to, 0, moved!);\n void order.run(() => client.contents.orderVersions(content.id, ids));\n }}\n >\n {(v, handle) => (\n <div className=\"grid gap-2 rounded-md border border-border p-2\" data-ckui=\"version-row\" data-version={v.id}>\n <div className=\"flex flex-wrap items-center gap-2\">\n {versions.length > 1 && handle}\n <span className=\"min-w-0 flex-1 font-medium break-words\">{versionLabel(v, languageName, p.labels)}</span>\n <Badge variant={v.live ? \"default\" : \"outline\"}>{t(v.live ? \"contentEditor.live\" : v.state === \"draft\" ? \"contentManager.draft\" : \"contentManager.scheduled\")}</Badge>\n {v.access && <Badge variant=\"secondary\">{t(`contentEditor.level_${v.access.level}`)}</Badge>}\n {v.pages ? <span className=\"text-xs text-muted-foreground\">{t(\"contentEditor.pageCount\", { count: v.pages })}</span> : null}\n <Button type=\"button\" size=\"xs\" variant=\"ghost\" aria-expanded={open === v.id} onClick={() => setOpen(open === v.id ? null : v.id)}>\n {t(open === v.id ? \"contentEditor.close\" : \"contentEditor.edit\")}\n </Button>\n </div>\n {open === v.id && <VersionForm content={content} version={v} model={model} media={media} {...p} />}\n </div>\n )}\n </SortableList>\n <ErrorLine error={order.error} />\n <AddVersion\n languages={languages}\n many={spec?.versions.languages === \"many\"}\n pending={add.pending}\n // A new version is a draft: open it for its media.\n onAdd={(input) => void add.run(() => client.contents.addVersion(content.id, input)).then((v) => v && setOpen(v.id))}\n />\n <ErrorLine error={add.error} />\n </Section>\n );\n}\n\nfunction LanguageFields({ languages, value, many, onChange }: { languages: readonly string[]; value: readonly string[]; many: boolean; onChange: (v: string[]) => void }) {\n const { t } = useMessages();\n const languageName = useLanguageName();\n if (!many)\n return (\n <Select value={value[0] ?? NONE} onValueChange={(v) => onChange(v === NONE ? [] : [String(v)])}>\n <SelectTrigger size=\"sm\" aria-label={t(\"contentEditor.versionLanguage\")}>\n <SelectValue>{(v: string) => (v === NONE ? t(\"contentEditor.chooseLanguage\") : languageName(v))}</SelectValue>\n </SelectTrigger>\n <SelectContent>\n {languages.map((l) => (\n <SelectItem key={l} value={l}>\n {languageName(l)}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n );\n return (\n <fieldset className=\"flex flex-wrap gap-3\">\n <legend className=\"sr-only\">{t(\"contentEditor.versionLanguages\")}</legend>\n {languages.map((l) => (\n <label key={l} className=\"flex items-center gap-1.5\">\n <Switch size=\"sm\" checked={value.includes(l)} onCheckedChange={(on) => onChange(on ? [...value, l] : value.filter((x) => x !== l))} aria-label={languageName(l)} />\n {languageName(l)}\n </label>\n ))}\n </fieldset>\n );\n}\n\nfunction AddVersion({ languages, many, pending, onAdd }: { languages: readonly string[]; many: boolean; pending: boolean; onAdd: (v: { languages: string[] }) => void }) {\n const { t } = useMessages();\n const [langs, setLangs] = useState<string[]>([]);\n return (\n <div className=\"flex flex-wrap items-center gap-2\" data-ckui=\"add-version\">\n <LanguageFields languages={languages} value={langs} many={many} onChange={setLangs} />\n <Button\n type=\"button\"\n size=\"sm\"\n variant=\"outline\"\n disabled={pending || !langs.length}\n onClick={() => {\n onAdd({ languages: langs });\n setLangs([]);\n }}\n >\n {t(\"contentEditor.addVersion\")}\n </Button>\n </div>\n );\n}\n\nfunction VersionForm({ content, version: v, model, media, ...p }: Common & { content: Content; version: Version; model: ContentModel | null; media: boolean }) {\n const { t } = useMessages();\n const id = useId();\n const client = useContentKitClient(p.client);\n const spec = model?.kinds[content.kind];\n const [langs, setLangs] = useState<string[]>(v.languages);\n const [traits, setTraits] = useState<string[]>(v.traits);\n const [label, setLabel] = useState(v.label ?? \"\");\n const [draft, setDraft] = useState(v.state === \"draft\");\n const [at, setAt] = useState(toLocalInput(v.publish_at));\n const [own, setOwn] = useState(!!v.access);\n const [rule, setRule] = useState<Rule>(v.access ?? content.access);\n const [saved, setSaved] = useState(false);\n const save = useAction(\"content.save\", p.onError);\n const remove = useAction(\"content.save\", p.onError);\n const offer = useAction(\"offer.save\", p.onError);\n return (\n <div className=\"grid gap-4 pt-2\">\n <form\n className=\"grid gap-3\"\n onSubmit={(e) => {\n e.preventDefault();\n setSaved(false);\n void save\n .run(() =>\n client.contents.updateVersion(content.id, v.id, {\n languages: langs,\n traits,\n label: label.trim(),\n state: draft ? \"draft\" : \"published\",\n publish_at: fromLocalInput(at),\n ...(own ? { access: cleanRule(rule) } : { clear_access: !!v.access }),\n }),\n )\n .then((d) => d && setSaved(true));\n }}\n >\n <LanguageFields languages={model?.languages ?? []} value={langs} many={spec?.versions.languages === \"many\"} onChange={setLangs} />\n {!!spec?.versions.traits?.length && (\n <fieldset className=\"flex flex-wrap gap-3\">\n <legend className=\"sr-only\">{t(\"contentEditor.traits\")}</legend>\n {spec.versions.traits.map((x) => (\n <label key={x} className=\"flex items-center gap-1.5\">\n <Switch size=\"sm\" checked={traits.includes(x)} onCheckedChange={(on) => setTraits(on ? [...traits, x] : traits.filter((y) => y !== x))} aria-label={labelOf(p.labels, x)} />\n {labelOf(p.labels, x)}\n </label>\n ))}\n </fieldset>\n )}\n <div className=\"grid gap-3 sm:grid-cols-2\">\n <div className=\"grid gap-1.5\">\n <Label htmlFor={`${id}-label`}>{t(\"contentEditor.versionLabel\")}</Label>\n <Input id={`${id}-label`} className=\"h-8\" value={label} onChange={(e) => setLabel(e.target.value)} />\n </div>\n <div className=\"grid gap-1.5\">\n <Label htmlFor={`${id}-at`}>{t(\"contentEditor.versionPublishAt\")}</Label>\n <Input id={`${id}-at`} className=\"h-8\" type=\"datetime-local\" value={at} onChange={(e) => setAt(e.target.value)} />\n </div>\n </div>\n <label className=\"flex items-center gap-2\">\n <Switch size=\"sm\" checked={draft} onCheckedChange={setDraft} />\n {t(\"contentEditor.versionDraft\")}\n </label>\n <label className=\"flex items-center gap-2\">\n <Switch size=\"sm\" checked={own} onCheckedChange={setOwn} />\n {t(\"contentEditor.ownAccess\")}\n </label>\n {own && <RuleFields value={rule} onChange={setRule} model={model} kind={content.kind} owner={content.owner_group_id} labels={p.labels} client={client} />}\n <ErrorLine error={save.error} />\n <div className=\"flex flex-wrap items-center gap-3\">\n <Button type=\"submit\" size=\"sm\" disabled={save.pending || !langs.length || (own && !complete(rule))}>\n {save.pending ? t(\"common.saving\") : t(\"common.save\")}\n </Button>\n <Saved show={saved} />\n <Button type=\"button\" size=\"sm\" variant=\"destructive\" className=\"ms-auto\" disabled={remove.pending} onClick={() => void remove.run(() => client.contents.removeVersion(content.id, v.id))}>\n {t(\"contentEditor.deleteVersion\")}\n </Button>\n </div>\n <ErrorLine error={remove.error} />\n </form>\n <OfferFields\n offer={v.offer}\n pending={offer.pending}\n onSell={(terms) => void offer.run(() => client.offers.sell({ content: content.id, version: v.id }, terms))}\n onWithdraw={() => void offer.run(() => client.offers.withdraw({ content: content.id, version: v.id }))}\n />\n <ErrorLine error={offer.error} />\n {spec?.segments && <SegmentsEditor content={content} version={v} {...p} />}\n {media && <VersionCover content={content} version={v} {...p} />}\n {media && <VersionMedia content={content} version={v} model={model} {...p} />}\n {media && spec?.presentation === \"reader\" && <ReaderManifestEditor content={content.id} version={v.id} client={p.client} onError={p.onError} />}\n </div>\n );\n}\n\n/**\n * A version's own cover, where its kind has covers: the cover upload its\n * editors selected, else its first. Versions share no files.\n */\nexport function VersionCover({ content, version: v, ...p }: Common & { content: Content; version: Version }) {\n const { t } = useMessages();\n const client = useContentKitClient(p.client);\n const { presets } = usePresets({ client });\n const save = useAction(\"content.save\", p.onError);\n const input = useRef<HTMLInputElement>(null);\n const [fresh, setFresh] = useState<string | null>(null);\n useEffect(() => () => void (fresh && URL.revokeObjectURL(fresh)), [fresh]);\n if (!presets.some((r) => r.kind === content.kind && r.name === \"cover\")) return null;\n const src = fresh ?? v.cover?.url;\n const pick = (file: File | null) =>\n void save.run(async () => {\n if (!file) {\n setFresh(null);\n return client.contents.setCover(content.id, v.id, null);\n }\n const ref = { kind: content.kind, id: content.id, version: v.id };\n const up = await client.media.uploadNamed(ref, file, { path: await client.media.presetPath(content.kind, \"cover\", file) });\n const saved = await client.contents.setCover(content.id, v.id, up.name);\n if (typeof URL.createObjectURL === \"function\") setFresh(URL.createObjectURL(file));\n return saved;\n });\n return (\n <div className=\"grid gap-1.5\" data-ckui=\"version-cover\">\n <span className=\"text-sm font-medium\">{t(\"contentManager.cover\")}</span>\n <div className=\"flex flex-wrap items-center gap-3\">\n {src ? <img src={src} alt=\"\" className=\"h-20 w-36 rounded-md border border-border object-cover\" /> : <span className=\"text-muted-foreground\">{t(\"contentManager.noCover\")}</span>}\n <Button type=\"button\" size=\"sm\" variant=\"outline\" disabled={save.pending} onClick={() => input.current?.click()}>\n {t(src ? \"pollEditor.replaceImage\" : \"contentManager.addCover\")}\n </Button>\n {v.cover?.image && (\n <Button type=\"button\" size=\"sm\" variant=\"ghost\" disabled={save.pending} onClick={() => pick(null)}>\n {t(\"pollEditor.removeImage\")}\n </Button>\n )}\n <input\n ref={input}\n type=\"file\"\n accept=\"image/*\"\n hidden\n aria-label={t(\"contentManager.cover\")}\n onChange={(e) => {\n const f = e.target.files?.[0];\n e.target.value = \"\";\n if (f) pick(f);\n }}\n />\n </div>\n <ErrorLine error={save.error} />\n </div>\n );\n}\n\n/**\n * A version's media: a video kind's source, poster and subtitles (by its\n * upload rules), else its upload folders. Uploads to a version that is not\n * live are added as they finish; a live one's wait for \"Add\".\n */\nfunction VersionMedia({ content, version, model, ...p }: Common & { content: Content; version: Version; model: ContentModel | null }) {\n const { t } = useMessages();\n const languageName = useLanguageName();\n const item = useMemo(() => ({ kind: content.kind, id: content.id, version: version.id }), [content.kind, content.id, version.id]);\n const r = useMediaRead(item, { editor: true, client: p.client });\n const languages = useMemo(() => (model?.languages ?? []).map((l) => ({ value: l, label: languageName(l) })), [model, languageName]);\n if (!r.read && r.loading) return <Skeleton className=\"h-24 w-full\" />;\n if (r.read?.uploads && videoPaths(r.read.uploads).source) return <VideoMediaEditor item={item} languages={languages} client={p.client} onError={p.onError} />;\n return <MediaFolderEditor item={item} commit={version.live ? \"manual\" : \"auto\"} label={t(\"contentEditor.media\")} client={p.client} onError={p.onError} />;\n}\n\ntype Row = { title: string; start: string; end: string; release: string };\n\n/** A version's segments (chapters): page ranges with titles and release times. */\nexport function SegmentsEditor({ content, version, ...p }: Common & { content: Content; version: Version }) {\n const { t } = useMessages();\n const client = useContentKitClient(p.client);\n const seed = () => version.segments.map((s) => ({ title: s.title ?? \"\", start: String(s.start), end: String(s.end), release: toLocalInput(s.release_at) }));\n const [rows, setRows] = useState<Row[]>(seed);\n // Seeded again when the stored segments change.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n useEffect(() => setRows(seed()), [JSON.stringify(version.segments)]);\n const [saved, setSaved] = useState(false);\n const save = useAction(\"content.save\", p.onError);\n const set = (i: number, patch: Partial<Row>) => {\n setSaved(false);\n setRows((r) => r.map((x, j) => (j === i ? { ...x, ...patch } : x)));\n };\n const valid = rows.every((r) => /^\\d+$/.test(r.start) && /^\\d+$/.test(r.end) && Number(r.end) > Number(r.start));\n return (\n <div className=\"grid gap-2\" data-ckui=\"segments-editor\">\n <h4 className=\"text-sm font-medium\">{t(\"contentEditor.segments\")}</h4>\n {rows.length === 0 && <p className=\"text-muted-foreground\">{t(\"contentEditor.noSegments\")}</p>}\n {rows.map((r, i) => (\n <div key={i} className=\"flex flex-wrap items-center gap-2\" data-ckui=\"segment-row\">\n <span className=\"w-6 text-xs text-muted-foreground tabular-nums\">{i + 1}</span>\n <Input className=\"h-8 w-40\" aria-label={t(\"contentEditor.segmentTitle\", { n: i + 1 })} placeholder={t(\"contentEditor.segmentTitlePlaceholder\")} value={r.title} onChange={(e) => set(i, { title: e.target.value })} />\n <Input className=\"h-8 w-20\" type=\"number\" min={0} aria-label={t(\"contentEditor.segmentStart\", { n: i + 1 })} value={r.start} onChange={(e) => set(i, { start: e.target.value })} />\n <span aria-hidden>–</span>\n <Input className=\"h-8 w-20\" type=\"number\" min={1} aria-label={t(\"contentEditor.segmentEnd\", { n: i + 1 })} value={r.end} onChange={(e) => set(i, { end: e.target.value })} />\n <Input className=\"h-8 w-48\" type=\"datetime-local\" aria-label={t(\"contentEditor.segmentRelease\", { n: i + 1 })} value={r.release} onChange={(e) => set(i, { release: e.target.value })} />\n <Button type=\"button\" size=\"xs\" variant=\"ghost\" onClick={() => setRows((x) => x.filter((_, j) => j !== i))}>\n {t(\"common.remove\")}\n </Button>\n </div>\n ))}\n <div className=\"flex flex-wrap items-center gap-2\">\n <Button\n type=\"button\"\n size=\"sm\"\n variant=\"outline\"\n onClick={() => {\n const last = rows.at(-1);\n const start = last ? Number(last.end) || 0 : 0;\n setRows((x) => [...x, { title: \"\", start: String(start), end: String(start + 1), release: \"\" }]);\n }}\n >\n {t(\"contentEditor.addSegment\")}\n </Button>\n <Button\n type=\"button\"\n size=\"sm\"\n disabled={save.pending || !valid}\n onClick={() => {\n setSaved(false);\n const segments: Segment[] = rows.map((r, i) => ({ position: i + 1, title: r.title.trim() || undefined, start: Number(r.start), end: Number(r.end), release_at: fromLocalInput(r.release), released: false }));\n void save.run(() => client.contents.setSegments(content.id, version.id, segments)).then((d) => d && setSaved(true));\n }}\n >\n {t(\"contentEditor.saveSegments\")}\n </Button>\n <Saved show={saved} />\n </div>\n <ErrorLine error={save.error} />\n </div>\n );\n}\n\n/** Every editor section of an existing content: details, access and price, versions, groups. */\nexport function ContentSections({ content, ...p }: Common & { content: Content; media?: boolean; className?: string; management?: boolean }) {\n const languageName = useLanguageName();\n const versions = useMemo(() => content.versions.map((v) => ({ id: v.id, label: versionLabel(v, languageName, p.labels) })), [content.versions, languageName, p.labels]);\n const { spec } = useKind(content.kind, p.client);\n return (\n <div className={cn(\"grid gap-6\", p.className)} data-ckui=\"content-sections\">\n <ContentDetailsEditor content={content} {...p} />\n <AccessEditor content={content} {...p} />\n <VersionsEditor content={content} {...p} />\n {!!spec?.entities?.length && (\n <section className=\"grid gap-3 border-t border-border pt-4\" data-ckui=\"content-groups\">\n <MembershipEditor management={p.management} content={content.id} contentKind={content.kind} versions={spec.versions.hidden ? undefined : versions} labels={p.labels} client={p.client} onError={p.onError} />\n </section>\n )}\n </div>\n );\n}\n"],"mappings":"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"}
@@ -3,7 +3,7 @@ import { ContentKitClient } from '../../client/client.js';
3
3
  import { ReleaseDatesQuery } from '../../client/discovery.js';
4
4
  import { ContentKitErrorHandler } from '../../react/context.js';
5
5
  export interface ContentFilterSettingsProps {
6
- /** Labels and group names in this language; default the provider's. */
6
+ /** Entity names in this language; default the provider's. */
7
7
  language?: string;
8
8
  /** Offer listing deleted content the reader holds. Default true. */
9
9
  includeDeleted?: boolean;
@@ -39,7 +39,7 @@ function v(r) {
39
39
  }), /* @__PURE__ */ h(i, {
40
40
  htmlFor: `${y}-${e.entity.id}`,
41
41
  className: "min-w-0 flex-1",
42
- children: e.label || e.entity.name
42
+ children: e.entity.name || e.entity.slug
43
43
  })]
44
44
  }, e.entity.id))
45
45
  }) : null,
@@ -1 +1 @@
1
- {"version":3,"file":"filters.js","names":[],"sources":["../../../src/components/content/filters.tsx"],"sourcesContent":["import { cn } from \"cn\";\nimport { useContext, useId } from \"react\";\nimport type { ContentKitUiAppearance } from \"../../appearance.js\";\nimport type { ContentKitClient } from \"../../client/client.js\";\nimport type { ReleaseDatesQuery } from \"../../client/discovery.js\";\nimport { useMessages } from \"../../i18n/context.js\";\nimport { ContentKitContext, type ContentKitErrorHandler } from \"../../react/context.js\";\nimport { useContentFilters, useReleaseDates } from \"../../react/discovery.js\";\nimport { ContentKitUiRoot } from \"../../scope.js\";\nimport { Button } from \"#ckui/ui/button\";\nimport { Label } from \"#ckui/ui/label\";\nimport { Skeleton } from \"#ckui/ui/skeleton\";\nimport { Switch } from \"#ckui/ui/switch\";\nimport { contentError, ErrorLine, useAction } from \"../social/parts.js\";\n\nexport interface ContentFilterSettingsProps {\n /** Labels and group names in this language; default the provider's. */\n language?: string;\n /** Offer listing deleted content the reader holds. Default true. */\n includeDeleted?: boolean;\n client?: ContentKitClient;\n onError?: ContentKitErrorHandler;\n className?: string;\n appearance?: ContentKitUiAppearance;\n}\n\n/** Show or hide configured content for this browser or signed-in account. */\nexport function ContentFilterSettings(p: ContentFilterSettingsProps) {\n const m = useMessages();\n const { t } = m;\n const id = useId();\n const ctx = useContext(ContentKitContext);\n const f = useContentFilters({ language: p.language, client: p.client });\n const save = useAction(\"filters.save\", p.onError);\n const root = (children: React.ReactNode) => (\n <ContentKitUiRoot appearance={p.appearance} className={cn(\"grid gap-3 text-sm\", p.className)} data-ckui=\"content-filters\">\n {children}\n </ContentKitUiRoot>\n );\n if (!f.filters) {\n if (f.error) return root(<ErrorLine>{contentError(m, f.error)}</ErrorLine>);\n return root(<Skeleton className=\"h-24 w-full\" />);\n }\n const filters = f.filters;\n if (!filters.filters.length && p.includeDeleted === false) return null;\n return root(\n <>\n {filters.filters.length ? (\n <ul className=\"grid divide-y divide-border rounded-lg border border-border\">\n {filters.filters.map((x) => (\n <li key={x.entity.id} className=\"flex flex-wrap items-center gap-3 p-3\" data-ckui=\"content-filter\" data-slug={x.entity.slug} data-visible={x.visible}>\n <Switch id={`${id}-${x.entity.id}`} checked={x.visible} disabled={save.pending} onCheckedChange={(v) => void save.run(() => f.setVisible(x.entity.id, v))} />\n <Label htmlFor={`${id}-${x.entity.id}`} className=\"min-w-0 flex-1\">\n {x.label || x.entity.name}\n </Label>\n </li>\n ))}\n </ul>\n ) : null}\n {p.includeDeleted !== false && ctx?.viewer !== null && (\n <div className=\"flex items-center gap-3\">\n <Switch id={`${id}-deleted`} checked={filters.include_deleted} disabled={save.pending} onCheckedChange={(v) => void save.run(() => f.setIncludeDeleted(v))} />\n <Label htmlFor={`${id}-deleted`}>{t(\"contents.includeDeleted\")}</Label>\n </div>\n )}\n <ErrorLine error={save.error} />\n </>,\n );\n}\n\nexport interface ReleaseDateIndexProps {\n /** Which contents count: the listing's filters. */\n query?: ReleaseDatesQuery;\n /** The bucket chosen (a day YYYY-MM-DD or month YYYY-MM): list with released_on set to it. */\n selected?: string;\n onSelect?: (date: string) => void;\n client?: ContentKitClient;\n className?: string;\n appearance?: ContentKitUiAppearance;\n}\n\n/** The release date index: per month or day, newest first, how many contents and how many free. */\nexport function ReleaseDateIndex({ query = {}, selected, onSelect, client, className, appearance }: ReleaseDateIndexProps) {\n const m = useMessages();\n const { t } = m;\n const dates = useReleaseDates(query, { client });\n const label = (date: string) => {\n const [y, mo, d] = date.split(\"-\").map(Number);\n const at = new Date(Date.UTC(y!, (mo ?? 1) - 1, d ?? 1));\n return new Intl.DateTimeFormat(m.language, d ? { dateStyle: \"medium\", timeZone: \"UTC\" } : { year: \"numeric\", month: \"long\", timeZone: \"UTC\" }).format(at);\n };\n return (\n <ContentKitUiRoot appearance={appearance} className={cn(\"grid gap-2 text-sm\", className)} data-ckui=\"release-dates\">\n {dates.loading && !dates.items.length ? (\n <Skeleton className=\"h-24 w-full\" />\n ) : dates.error && !dates.items.length ? (\n <ErrorLine>{contentError(m, dates.error)}</ErrorLine>\n ) : !dates.items.length ? (\n <p className=\"text-muted-foreground\">{t(\"contents.noDates\")}</p>\n ) : (\n <ul className=\"grid gap-1\">\n {dates.items.map((d) => (\n <li key={d.date}>\n <button\n type=\"button\"\n aria-pressed={selected === d.date}\n className={cn(\"flex w-full items-center justify-between gap-3 rounded-md px-2 py-1.5 text-start hover:bg-muted\", selected === d.date && \"bg-muted font-medium\")}\n onClick={() => onSelect?.(d.date)}\n data-ckui=\"release-date\"\n data-date={d.date}\n >\n <span>{label(d.date)}</span>\n <span className=\"text-xs text-muted-foreground tabular-nums\">\n {m.plural(\"contents.items\", d.count)}\n {d.free < d.count && ` · ${m.plural(\"contents.free\", d.free)}`}\n </span>\n </button>\n </li>\n ))}\n </ul>\n )}\n {dates.hasMore && (\n <Button variant=\"outline\" size=\"sm\" className=\"justify-self-center\" disabled={dates.loadingMore} onClick={() => void dates.loadMore()}>\n {t(\"contents.loadMore\")}\n </Button>\n )}\n </ContentKitUiRoot>\n );\n}\n"],"mappings":";;;;;;;;;;;;;AA2BA,SAAgB,EAAsB,GAA+B;CACnE,IAAM,IAAI,EAAY,GAChB,EAAE,SAAM,GACR,IAAK,EAAM,GACX,IAAM,EAAW,CAAiB,GAClC,IAAI,EAAkB;EAAE,UAAU,EAAE;EAAU,QAAQ,EAAE;CAAO,CAAC,GAChE,IAAO,EAAU,gBAAgB,EAAE,OAAO,GAC1C,KAAQ,MACZ,kBAAC,GAAD;EAAkB,YAAY,EAAE;EAAY,WAAW,EAAG,sBAAsB,EAAE,SAAS;EAAG,aAAU;EACrG;CACe,CAAA;CAEpB,IAAI,CAAC,EAAE,SAEL,OADI,EAAE,QAAc,EAAK,kBAAC,GAAD,EAAA,UAAY,EAAa,GAAG,EAAE,KAAK,EAAa,CAAA,CAAC,IACnE,EAAK,kBAAC,GAAD,EAAU,WAAU,cAAe,CAAA,CAAC;CAElD,IAAM,IAAU,EAAE;CAElB,OADI,CAAC,EAAQ,QAAQ,UAAU,EAAE,mBAAmB,KAAc,OAC3D,EACL,kBAAA,GAAA,EAAA,UAAA;EACG,EAAQ,QAAQ,SACf,kBAAC,MAAD;GAAI,WAAU;GACX,UAAA,EAAQ,QAAQ,KAAK,MACpB,kBAAC,MAAD;IAAsB,WAAU;IAAwC,aAAU;IAAiB,aAAW,EAAE,OAAO;IAAM,gBAAc,EAAE;IAA7I,UAAA,CACE,kBAAC,GAAD;KAAQ,IAAI,GAAG,EAAG,GAAG,EAAE,OAAO;KAAM,SAAS,EAAE;KAAS,UAAU,EAAK;KAAS,kBAAkB,MAAM,KAAK,EAAK,UAAU,EAAE,WAAW,EAAE,OAAO,IAAI,CAAC,CAAC;IAAI,CAAA,GAC5J,kBAAC,GAAD;KAAO,SAAS,GAAG,EAAG,GAAG,EAAE,OAAO;KAAM,WAAU;KAC/C,UAAA,EAAE,SAAS,EAAE,OAAO;IAChB,CAAA,CACL;GALK,GAAA,EAAE,OAAO,EAKd,CACL;EACC,CAAA,IACF;EACH,EAAE,mBAAmB,MAAS,GAAK,WAAW,QAC7C,kBAAC,OAAD;GAAK,WAAU;GAAf,UAAA,CACE,kBAAC,GAAD;IAAQ,IAAI,GAAG,EAAG;IAAW,SAAS,EAAQ;IAAiB,UAAU,EAAK;IAAS,kBAAkB,MAAM,KAAK,EAAK,UAAU,EAAE,kBAAkB,CAAC,CAAC;GAAI,CAAA,GAC7J,kBAAC,GAAD;IAAO,SAAS,GAAG,EAAG;IAAY,UAAA,EAAE,yBAAyB;GAAS,CAAA,CACnE;;EAEP,kBAAC,GAAD,EAAW,OAAO,EAAK,MAAQ,CAAA;CAC/B,EAAA,CAAA,CACJ;AACF;AAcA,SAAgB,EAAiB,EAAE,WAAQ,CAAC,GAAG,aAAU,aAAU,WAAQ,cAAW,iBAAqC;CACzH,IAAM,IAAI,EAAY,GAChB,EAAE,SAAM,GACR,IAAQ,EAAgB,GAAO,EAAE,UAAO,CAAC,GACzC,KAAS,MAAiB;EAC9B,IAAM,CAAC,GAAG,GAAI,KAAK,EAAK,MAAM,GAAG,CAAC,CAAC,IAAI,MAAM,GACvC,IAAK,IAAI,KAAK,KAAK,IAAI,IAAK,KAAM,KAAK,GAAG,KAAK,CAAC,CAAC;EACvD,OAAO,IAAI,KAAK,eAAe,EAAE,UAAU,IAAI;GAAE,WAAW;GAAU,UAAU;EAAM,IAAI;GAAE,MAAM;GAAW,OAAO;GAAQ,UAAU;EAAM,CAAC,CAAC,CAAC,OAAO,CAAE;CAC1J;CACA,OACE,kBAAC,GAAD;EAA8B;EAAY,WAAW,EAAG,sBAAsB,CAAS;EAAG,aAAU;EAApG,UAAA,CACG,EAAM,WAAW,CAAC,EAAM,MAAM,SAC7B,kBAAC,GAAD,EAAU,WAAU,cAAe,CAAA,IACjC,EAAM,SAAS,CAAC,EAAM,MAAM,SAC9B,kBAAC,GAAD,EAAA,UAAY,EAAa,GAAG,EAAM,KAAK,EAAa,CAAA,IACjD,EAAM,MAAM,SAGf,kBAAC,MAAD;GAAI,WAAU;GACX,UAAA,EAAM,MAAM,KAAK,MAChB,kBAAC,MAAD,EAAA,UACE,kBAAC,UAAD;IACE,MAAK;IACL,gBAAc,MAAa,EAAE;IAC7B,WAAW,EAAG,mGAAmG,MAAa,EAAE,QAAQ,sBAAsB;IAC9J,eAAe,IAAW,EAAE,IAAI;IAChC,aAAU;IACV,aAAW,EAAE;IANf,UAAA,CAQE,kBAAC,QAAD,EAAA,UAAO,EAAM,EAAE,IAAI,EAAQ,CAAA,GAC3B,kBAAC,QAAD;KAAM,WAAU;KAAhB,UAAA,CACG,EAAE,OAAO,kBAAkB,EAAE,KAAK,GAClC,EAAE,OAAO,EAAE,SAAS,MAAM,EAAE,OAAO,iBAAiB,EAAE,IAAI,GACvD;IACA,CAAA,CAAA;GACN,CAAA,EAAA,GAfK,EAAE,IAeP,CACL;EACC,CAAA,IArBJ,kBAAC,KAAD;GAAG,WAAU;GAAyB,UAAA,EAAE,kBAAkB;EAAK,CAAA,GAuBhE,EAAM,WACL,kBAAC,GAAD;GAAQ,SAAQ;GAAU,MAAK;GAAK,WAAU;GAAsB,UAAU,EAAM;GAAa,eAAe,KAAK,EAAM,SAAS;GACjI,UAAA,EAAE,mBAAmB;EAChB,CAAA,CAEM;;AAEtB"}
1
+ {"version":3,"file":"filters.js","names":[],"sources":["../../../src/components/content/filters.tsx"],"sourcesContent":["import { cn } from \"cn\";\nimport { useContext, useId } from \"react\";\nimport type { ContentKitUiAppearance } from \"../../appearance.js\";\nimport type { ContentKitClient } from \"../../client/client.js\";\nimport type { ReleaseDatesQuery } from \"../../client/discovery.js\";\nimport { useMessages } from \"../../i18n/context.js\";\nimport { ContentKitContext, type ContentKitErrorHandler } from \"../../react/context.js\";\nimport { useContentFilters, useReleaseDates } from \"../../react/discovery.js\";\nimport { ContentKitUiRoot } from \"../../scope.js\";\nimport { Button } from \"#ckui/ui/button\";\nimport { Label } from \"#ckui/ui/label\";\nimport { Skeleton } from \"#ckui/ui/skeleton\";\nimport { Switch } from \"#ckui/ui/switch\";\nimport { contentError, ErrorLine, useAction } from \"../social/parts.js\";\n\nexport interface ContentFilterSettingsProps {\n /** Entity names in this language; default the provider's. */\n language?: string;\n /** Offer listing deleted content the reader holds. Default true. */\n includeDeleted?: boolean;\n client?: ContentKitClient;\n onError?: ContentKitErrorHandler;\n className?: string;\n appearance?: ContentKitUiAppearance;\n}\n\n/** Show or hide configured content for this browser or signed-in account. */\nexport function ContentFilterSettings(p: ContentFilterSettingsProps) {\n const m = useMessages();\n const { t } = m;\n const id = useId();\n const ctx = useContext(ContentKitContext);\n const f = useContentFilters({ language: p.language, client: p.client });\n const save = useAction(\"filters.save\", p.onError);\n const root = (children: React.ReactNode) => (\n <ContentKitUiRoot appearance={p.appearance} className={cn(\"grid gap-3 text-sm\", p.className)} data-ckui=\"content-filters\">\n {children}\n </ContentKitUiRoot>\n );\n if (!f.filters) {\n if (f.error) return root(<ErrorLine>{contentError(m, f.error)}</ErrorLine>);\n return root(<Skeleton className=\"h-24 w-full\" />);\n }\n const filters = f.filters;\n if (!filters.filters.length && p.includeDeleted === false) return null;\n return root(\n <>\n {filters.filters.length ? (\n <ul className=\"grid divide-y divide-border rounded-lg border border-border\">\n {filters.filters.map((x) => (\n <li key={x.entity.id} className=\"flex flex-wrap items-center gap-3 p-3\" data-ckui=\"content-filter\" data-slug={x.entity.slug} data-visible={x.visible}>\n <Switch id={`${id}-${x.entity.id}`} checked={x.visible} disabled={save.pending} onCheckedChange={(v) => void save.run(() => f.setVisible(x.entity.id, v))} />\n <Label htmlFor={`${id}-${x.entity.id}`} className=\"min-w-0 flex-1\">\n {x.entity.name || x.entity.slug}\n </Label>\n </li>\n ))}\n </ul>\n ) : null}\n {p.includeDeleted !== false && ctx?.viewer !== null && (\n <div className=\"flex items-center gap-3\">\n <Switch id={`${id}-deleted`} checked={filters.include_deleted} disabled={save.pending} onCheckedChange={(v) => void save.run(() => f.setIncludeDeleted(v))} />\n <Label htmlFor={`${id}-deleted`}>{t(\"contents.includeDeleted\")}</Label>\n </div>\n )}\n <ErrorLine error={save.error} />\n </>,\n );\n}\n\nexport interface ReleaseDateIndexProps {\n /** Which contents count: the listing's filters. */\n query?: ReleaseDatesQuery;\n /** The bucket chosen (a day YYYY-MM-DD or month YYYY-MM): list with released_on set to it. */\n selected?: string;\n onSelect?: (date: string) => void;\n client?: ContentKitClient;\n className?: string;\n appearance?: ContentKitUiAppearance;\n}\n\n/** The release date index: per month or day, newest first, how many contents and how many free. */\nexport function ReleaseDateIndex({ query = {}, selected, onSelect, client, className, appearance }: ReleaseDateIndexProps) {\n const m = useMessages();\n const { t } = m;\n const dates = useReleaseDates(query, { client });\n const label = (date: string) => {\n const [y, mo, d] = date.split(\"-\").map(Number);\n const at = new Date(Date.UTC(y!, (mo ?? 1) - 1, d ?? 1));\n return new Intl.DateTimeFormat(m.language, d ? { dateStyle: \"medium\", timeZone: \"UTC\" } : { year: \"numeric\", month: \"long\", timeZone: \"UTC\" }).format(at);\n };\n return (\n <ContentKitUiRoot appearance={appearance} className={cn(\"grid gap-2 text-sm\", className)} data-ckui=\"release-dates\">\n {dates.loading && !dates.items.length ? (\n <Skeleton className=\"h-24 w-full\" />\n ) : dates.error && !dates.items.length ? (\n <ErrorLine>{contentError(m, dates.error)}</ErrorLine>\n ) : !dates.items.length ? (\n <p className=\"text-muted-foreground\">{t(\"contents.noDates\")}</p>\n ) : (\n <ul className=\"grid gap-1\">\n {dates.items.map((d) => (\n <li key={d.date}>\n <button\n type=\"button\"\n aria-pressed={selected === d.date}\n className={cn(\"flex w-full items-center justify-between gap-3 rounded-md px-2 py-1.5 text-start hover:bg-muted\", selected === d.date && \"bg-muted font-medium\")}\n onClick={() => onSelect?.(d.date)}\n data-ckui=\"release-date\"\n data-date={d.date}\n >\n <span>{label(d.date)}</span>\n <span className=\"text-xs text-muted-foreground tabular-nums\">\n {m.plural(\"contents.items\", d.count)}\n {d.free < d.count && ` · ${m.plural(\"contents.free\", d.free)}`}\n </span>\n </button>\n </li>\n ))}\n </ul>\n )}\n {dates.hasMore && (\n <Button variant=\"outline\" size=\"sm\" className=\"justify-self-center\" disabled={dates.loadingMore} onClick={() => void dates.loadMore()}>\n {t(\"contents.loadMore\")}\n </Button>\n )}\n </ContentKitUiRoot>\n );\n}\n"],"mappings":"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"}
@@ -1,49 +1,54 @@
1
1
  import { useMessages as e } from "../../i18n/context.js";
2
2
  import { ContentKitUiRoot as t } from "../../scope.js";
3
- import { Select as n, SelectContent as r, SelectItem as i, SelectTrigger as a, SelectValue as o } from "../../ui/select.js";
4
- import { popularQuery as s } from "../../client/discovery.js";
5
- import { ContentGrid as c } from "./grid.js";
6
- import { useMemo as l, useState as u } from "react";
7
- import { jsx as d, jsxs as f } from "react/jsx-runtime";
8
- import { cn as p } from "cn";
3
+ import { popularQuery as n } from "../../client/discovery.js";
4
+ import { Tabs as r, TabsContent as i, TabsList as a, TabsTrigger as o } from "../../ui/tabs.js";
5
+ import { ContentGrid as s } from "./grid.js";
6
+ import { useMemo as c, useState as l } from "react";
7
+ import { jsx as u, jsxs as d } from "react/jsx-runtime";
8
+ import { cn as f } from "cn";
9
9
  //#region src/components/content/popular.tsx
10
- var m = [
10
+ var p = [
11
11
  "7d",
12
12
  "90d",
13
13
  "365d",
14
14
  "all"
15
15
  ];
16
- function h({ query: h, period: g, onPeriodChange: _, locked: v, ...y }) {
17
- let b = e(), [x, S] = u("7d"), C = g ?? x, w = l(() => s(C, h), [C, h]), T = (e) => e === "all" ? b.t("listing.period_all") : b.plural("listing.pastDays", Number(e.slice(0, -1)));
18
- return /* @__PURE__ */ f(t, {
19
- appearance: y.appearance,
20
- className: p("grid gap-4 text-sm", y.className),
16
+ function m({ query: m, period: h, onPeriodChange: g, locked: _, ...v }) {
17
+ let y = e(), [b, x] = l("7d"), S = h ?? b, C = c(() => n(S, m), [S, m]), w = (e) => e === "all" ? y.t("listing.period_all") : y.plural("listing.pastDays", Number(e.slice(0, -1)));
18
+ return /* @__PURE__ */ u(t, {
19
+ appearance: v.appearance,
20
+ className: f("grid gap-4 text-sm", v.className),
21
21
  "data-ckui": "popular-grid",
22
- children: [/* @__PURE__ */ f(n, {
23
- value: C,
22
+ children: /* @__PURE__ */ d(r, {
23
+ value: S,
24
24
  onValueChange: (e) => {
25
- if (!e || !m.includes(e)) return;
25
+ if (!e || !p.includes(e)) return;
26
26
  let t = e;
27
- g === void 0 && S(t), _?.(t);
27
+ h === void 0 && x(t), g?.(t);
28
28
  },
29
- children: [/* @__PURE__ */ d(a, {
30
- className: "w-fit min-w-40",
31
- "aria-label": b.t("listing.popularPeriod"),
32
- children: /* @__PURE__ */ d(o, { children: T(C) })
33
- }), /* @__PURE__ */ d(r, { children: m.map((e) => /* @__PURE__ */ d(i, {
34
- value: e,
35
- children: T(e)
36
- }, e)) })]
37
- }), /* @__PURE__ */ d(c, {
38
- ...y,
39
- surface: y.surface ?? "popular",
40
- query: w,
41
- locked: v,
42
- infinite: !0
43
- })]
29
+ className: "gap-4",
30
+ children: [/* @__PURE__ */ u(a, {
31
+ "aria-label": y.t("listing.popularPeriod"),
32
+ className: "grid w-full grid-cols-4 group-data-horizontal/tabs:h-auto sm:w-fit",
33
+ children: p.map((e) => /* @__PURE__ */ u(o, {
34
+ value: e,
35
+ className: "min-h-10 whitespace-normal px-3 py-2 text-center",
36
+ children: w(e)
37
+ }, e))
38
+ }), /* @__PURE__ */ u(i, {
39
+ value: S,
40
+ children: /* @__PURE__ */ u(s, {
41
+ ...v,
42
+ surface: v.surface ?? "popular",
43
+ query: C,
44
+ locked: _,
45
+ infinite: !0
46
+ })
47
+ })]
48
+ })
44
49
  });
45
50
  }
46
51
  //#endregion
47
- export { h as PopularContentGrid };
52
+ export { m as PopularContentGrid };
48
53
 
49
54
  //# sourceMappingURL=popular.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"popular.js","names":[],"sources":["../../../src/components/content/popular.tsx"],"sourcesContent":["import { cn } from \"cn\";\nimport { useMemo, useState } from \"react\";\nimport { popularQuery, type PopularPeriod, type PopularQuery } from \"../../client/discovery.js\";\nimport { useMessages } from \"../../i18n/context.js\";\nimport { ContentKitUiRoot } from \"../../scope.js\";\nimport { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from \"#ckui/ui/select\";\nimport { ContentGrid, type CardListProps, type LockedCards } from \"./grid.js\";\n\nexport interface PopularContentGridProps extends Omit<CardListProps, \"infinite\"> {\n query?: PopularQuery;\n /** Controlled period; otherwise the selector starts at 7d. */\n period?: PopularPeriod;\n onPeriodChange?: (period: PopularPeriod) => void;\n locked?: LockedCards;\n}\n\nconst PERIODS: readonly PopularPeriod[] = [\"7d\", \"90d\", \"365d\", \"all\"];\n\n/** A popularity listing with matched score/age windows and infinite paging. */\nexport function PopularContentGrid({ query, period, onPeriodChange, locked, ...p }: PopularContentGridProps) {\n const m = useMessages();\n const [ownPeriod, setOwnPeriod] = useState<PopularPeriod>(\"7d\");\n const current = period ?? ownPeriod;\n const list = useMemo(() => popularQuery(current, query), [current, query]);\n const label = (value: PopularPeriod) => value === \"all\" ? m.t(\"listing.period_all\") : m.plural(\"listing.pastDays\", Number(value.slice(0, -1)));\n return (\n <ContentKitUiRoot appearance={p.appearance} className={cn(\"grid gap-4 text-sm\", p.className)} data-ckui=\"popular-grid\">\n <Select value={current} onValueChange={(value) => {\n if (!value || !PERIODS.includes(value as PopularPeriod)) return;\n const next = value as PopularPeriod;\n if (period === undefined) setOwnPeriod(next);\n onPeriodChange?.(next);\n }}>\n <SelectTrigger className=\"w-fit min-w-40\" aria-label={m.t(\"listing.popularPeriod\")}><SelectValue>{label(current)}</SelectValue></SelectTrigger>\n <SelectContent>{PERIODS.map((value) => <SelectItem key={value} value={value}>{label(value)}</SelectItem>)}</SelectContent>\n </Select>\n <ContentGrid {...p} surface={p.surface ?? \"popular\"} query={list} locked={locked} infinite />\n </ContentKitUiRoot>\n );\n}\n"],"mappings":";;;;;;;;;AAgBA,IAAM,IAAoC;CAAC;CAAM;CAAO;CAAQ;AAAK;AAGrE,SAAgB,EAAmB,EAAE,UAAO,WAAQ,mBAAgB,WAAQ,GAAG,KAA8B;CAC3G,IAAM,IAAI,EAAY,GAChB,CAAC,GAAW,KAAgB,EAAwB,IAAI,GACxD,IAAU,KAAU,GACpB,IAAO,QAAc,EAAa,GAAS,CAAK,GAAG,CAAC,GAAS,CAAK,CAAC,GACnE,KAAS,MAAyB,MAAU,QAAQ,EAAE,EAAE,oBAAoB,IAAI,EAAE,OAAO,oBAAoB,OAAO,EAAM,MAAM,GAAG,EAAE,CAAC,CAAC;CAC7I,OACE,kBAAC,GAAD;EAAkB,YAAY,EAAE;EAAY,WAAW,EAAG,sBAAsB,EAAE,SAAS;EAAG,aAAU;EAAxG,UAAA,CACE,kBAAC,GAAD;GAAQ,OAAO;GAAS,gBAAgB,MAAU;IAChD,IAAI,CAAC,KAAS,CAAC,EAAQ,SAAS,CAAsB,GAAG;IACzD,IAAM,IAAO;IAEb,AADI,MAAW,KAAA,KAAW,EAAa,CAAI,GAC3C,IAAiB,CAAI;GACvB;GALA,UAAA,CAME,kBAAC,GAAD;IAAe,WAAU;IAAiB,cAAY,EAAE,EAAE,uBAAuB;IAAG,UAAA,kBAAC,GAAD,EAAA,UAAc,EAAM,CAAO,EAAe,CAAA;GAAgB,CAAA,GAC9I,kBAAC,GAAD,EAAA,UAAgB,EAAQ,KAAK,MAAU,kBAAC,GAAD;IAA+B;IAAQ,UAAA,EAAM,CAAK;GAAc,GAA/C,CAA+C,CAAC,EAAiB,CAAA,CACnH;EACR,CAAA,GAAA,kBAAC,GAAD;GAAa,GAAI;GAAG,SAAS,EAAE,WAAW;GAAW,OAAO;GAAc;GAAQ,UAAA;EAAU,CAAA,CAC5E;;AAEtB"}
1
+ {"version":3,"file":"popular.js","names":[],"sources":["../../../src/components/content/popular.tsx"],"sourcesContent":["import { cn } from \"cn\";\nimport { useMemo, useState } from \"react\";\nimport { popularQuery, type PopularPeriod, type PopularQuery } from \"../../client/discovery.js\";\nimport { useMessages } from \"../../i18n/context.js\";\nimport { ContentKitUiRoot } from \"../../scope.js\";\nimport { Tabs, TabsContent, TabsList, TabsTrigger } from \"#ckui/ui/tabs\";\nimport { ContentGrid, type CardListProps, type LockedCards } from \"./grid.js\";\n\nexport interface PopularContentGridProps extends Omit<CardListProps, \"infinite\"> {\n query?: PopularQuery;\n /** Controlled period; otherwise the selector starts at 7d. */\n period?: PopularPeriod;\n onPeriodChange?: (period: PopularPeriod) => void;\n locked?: LockedCards;\n}\n\nconst PERIODS: readonly PopularPeriod[] = [\"7d\", \"90d\", \"365d\", \"all\"];\n\n/** A popularity listing with matched score/age windows and infinite paging. */\nexport function PopularContentGrid({ query, period, onPeriodChange, locked, ...p }: PopularContentGridProps) {\n const m = useMessages();\n const [ownPeriod, setOwnPeriod] = useState<PopularPeriod>(\"7d\");\n const current = period ?? ownPeriod;\n const list = useMemo(() => popularQuery(current, query), [current, query]);\n const label = (value: PopularPeriod) => value === \"all\" ? m.t(\"listing.period_all\") : m.plural(\"listing.pastDays\", Number(value.slice(0, -1)));\n return (\n <ContentKitUiRoot appearance={p.appearance} className={cn(\"grid gap-4 text-sm\", p.className)} data-ckui=\"popular-grid\">\n <Tabs value={current} onValueChange={(value) => {\n if (!value || !PERIODS.includes(value as PopularPeriod)) return;\n const next = value as PopularPeriod;\n if (period === undefined) setOwnPeriod(next);\n onPeriodChange?.(next);\n }} className=\"gap-4\">\n <TabsList aria-label={m.t(\"listing.popularPeriod\")} className=\"grid w-full grid-cols-4 group-data-horizontal/tabs:h-auto sm:w-fit\">\n {PERIODS.map((value) => (\n <TabsTrigger key={value} value={value} className=\"min-h-10 whitespace-normal px-3 py-2 text-center\">\n {label(value)}\n </TabsTrigger>\n ))}\n </TabsList>\n <TabsContent value={current}>\n <ContentGrid {...p} surface={p.surface ?? \"popular\"} query={list} locked={locked} infinite />\n </TabsContent>\n </Tabs>\n </ContentKitUiRoot>\n );\n}\n"],"mappings":";;;;;;;;;AAgBA,IAAM,IAAoC;CAAC;CAAM;CAAO;CAAQ;AAAK;AAGrE,SAAgB,EAAmB,EAAE,UAAO,WAAQ,mBAAgB,WAAQ,GAAG,KAA8B;CAC3G,IAAM,IAAI,EAAY,GAChB,CAAC,GAAW,KAAgB,EAAwB,IAAI,GACxD,IAAU,KAAU,GACpB,IAAO,QAAc,EAAa,GAAS,CAAK,GAAG,CAAC,GAAS,CAAK,CAAC,GACnE,KAAS,MAAyB,MAAU,QAAQ,EAAE,EAAE,oBAAoB,IAAI,EAAE,OAAO,oBAAoB,OAAO,EAAM,MAAM,GAAG,EAAE,CAAC,CAAC;CAC7I,OACE,kBAAC,GAAD;EAAkB,YAAY,EAAE;EAAY,WAAW,EAAG,sBAAsB,EAAE,SAAS;EAAG,aAAU;EACtG,UAAA,kBAAC,GAAD;GAAM,OAAO;GAAS,gBAAgB,MAAU;IAC9C,IAAI,CAAC,KAAS,CAAC,EAAQ,SAAS,CAAsB,GAAG;IACzD,IAAM,IAAO;IAEb,AADI,MAAW,KAAA,KAAW,EAAa,CAAI,GAC3C,IAAiB,CAAI;GACvB;GAAG,WAAU;GALb,UAAA,CAME,kBAAC,GAAD;IAAU,cAAY,EAAE,EAAE,uBAAuB;IAAG,WAAU;IAC3D,UAAA,EAAQ,KAAK,MACZ,kBAAC,GAAD;KAAgC;KAAO,WAAU;KAC9C,UAAA,EAAM,CAAK;IACD,GAFK,CAEL,CACd;GACO,CAAA,GACV,kBAAC,GAAD;IAAa,OAAO;IAClB,UAAA,kBAAC,GAAD;KAAa,GAAI;KAAG,SAAS,EAAE,WAAW;KAAW,OAAO;KAAc;KAAQ,UAAA;IAAU,CAAA;GACjF,CAAA,CACT;;CACU,CAAA;AAEtB"}
@@ -39,6 +39,8 @@ export interface GroupBannerProps {
39
39
  export declare function GroupBanner(p: GroupBannerProps): import('react').JSX.Element;
40
40
  export interface GroupImageEditorProps {
41
41
  group: GroupLike;
42
+ /** Read the entity through the staff management API, including internal entities. */
43
+ management?: boolean;
42
44
  /** The cover, or a user-owned kind's avatar. */
43
45
  slot: EntityImageSlot;
44
46
  /** Crop before uploading. Default true. */
@@ -48,4 +50,4 @@ export interface GroupImageEditorProps {
48
50
  className?: string;
49
51
  }
50
52
  /** A group's cover or avatar for its editors: pick (and crop) an image, upload it and select it; or go back to none (a cover: automatic). */
51
- export declare function GroupImageEditor({ group, slot, crop, client, onError, className }: GroupImageEditorProps): import('react').JSX.Element;
53
+ export declare function GroupImageEditor({ group, slot, crop, client, onError, className, management }: GroupImageEditorProps): import('react').JSX.Element;