@openrails/contentkit-ui 0.80.0 → 0.82.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +82 -54
- package/dist/client/beacons.d.ts +53 -0
- package/dist/client/beacons.js +72 -0
- package/dist/client/beacons.js.map +1 -0
- package/dist/client/catalog.d.ts +2 -2
- package/dist/client/catalog.js +1 -1
- package/dist/client/catalog.js.map +1 -1
- package/dist/client/client.d.ts +24 -11
- package/dist/client/client.js +37 -29
- package/dist/client/client.js.map +1 -1
- package/dist/client/content/comments.d.ts +12 -8
- package/dist/client/content/comments.js +33 -20
- package/dist/client/content/comments.js.map +1 -1
- package/dist/client/content/favorites.d.ts +24 -9
- package/dist/client/content/favorites.js +21 -22
- package/dist/client/content/favorites.js.map +1 -1
- package/dist/client/content/moderation.d.ts +1 -1
- package/dist/client/content/moderation.js.map +1 -1
- package/dist/client/content/reactions.d.ts +11 -6
- package/dist/client/content/reactions.js +23 -18
- package/dist/client/content/reactions.js.map +1 -1
- package/dist/client/content/types.d.ts +40 -21
- package/dist/client/content/types.js +5 -2
- package/dist/client/content/types.js.map +1 -1
- package/dist/client/contents.d.ts +55 -0
- package/dist/client/contents.js +144 -0
- package/dist/client/contents.js.map +1 -0
- package/dist/client/discovery.d.ts +126 -0
- package/dist/client/discovery.js +125 -0
- package/dist/client/discovery.js.map +1 -0
- package/dist/client/generated/error-codes.d.ts +1 -1
- package/dist/client/generated/error-codes.js +8 -0
- package/dist/client/generated/error-codes.js.map +1 -1
- package/dist/client/generated/routes.d.ts +1244 -370
- package/dist/client/generated/routes.js +1861 -554
- package/dist/client/generated/routes.js.map +1 -1
- package/dist/client/generated/wire.d.ts +960 -134
- package/dist/client/generated/wire.js.map +1 -1
- package/dist/client/group-fields.d.ts +25 -0
- package/dist/client/group-fields.js +63 -0
- package/dist/client/group-fields.js.map +1 -0
- package/dist/client/groups.d.ts +58 -0
- package/dist/client/groups.js +119 -0
- package/dist/client/groups.js.map +1 -0
- package/dist/client/http.d.ts +24 -12
- package/dist/client/http.js +20 -24
- package/dist/client/http.js.map +1 -1
- package/dist/client/index.d.ts +11 -6
- package/dist/client/media/api.d.ts +1 -1
- package/dist/client/media/api.js +4 -2
- package/dist/client/media/api.js.map +1 -1
- package/dist/client/media/client.d.ts +8 -9
- package/dist/client/media/client.js +58 -71
- package/dist/client/media/client.js.map +1 -1
- package/dist/client/media/ref.d.ts +30 -0
- package/dist/client/media/ref.js +10 -3
- package/dist/client/media/ref.js.map +1 -1
- package/dist/client/offers.d.ts +41 -0
- package/dist/client/offers.js +66 -0
- package/dist/client/offers.js.map +1 -0
- package/dist/client/route.d.ts +2 -0
- package/dist/client/route.js +2 -1
- package/dist/client/route.js.map +1 -1
- package/dist/client/versions.d.ts +20 -0
- package/dist/client/versions.js +53 -0
- package/dist/client/versions.js.map +1 -0
- package/dist/client.js +35 -30
- package/dist/components/admin/content-manager.d.ts +80 -0
- package/dist/components/admin/content-manager.js +591 -0
- package/dist/components/admin/content-manager.js.map +1 -0
- package/dist/components/admin/group-manager.d.ts +24 -0
- package/dist/components/admin/group-manager.js +244 -0
- package/dist/components/admin/group-manager.js.map +1 -0
- package/dist/components/admin/media-item-panel.js +1 -1
- package/dist/components/admin/media-item-panel.js.map +1 -1
- package/dist/components/content/card.d.ts +44 -0
- package/dist/components/content/card.js +285 -0
- package/dist/components/content/card.js.map +1 -0
- package/dist/components/content/editors.d.ts +40 -0
- package/dist/components/content/editors.js +764 -0
- package/dist/components/content/editors.js.map +1 -0
- package/dist/components/content/filters.d.ts +28 -0
- package/dist/components/content/filters.js +134 -0
- package/dist/components/content/filters.js.map +1 -0
- package/dist/components/content/grid.d.ts +62 -0
- package/dist/components/content/grid.js +233 -0
- package/dist/components/content/grid.js.map +1 -0
- package/dist/components/content/index.d.ts +8 -0
- package/dist/components/content/listing.d.ts +20 -0
- package/dist/components/content/listing.js +150 -0
- package/dist/components/content/listing.js.map +1 -0
- package/dist/components/content/offer-fields.d.ts +8 -0
- package/dist/components/content/offer-fields.js +127 -0
- package/dist/components/content/offer-fields.js.map +1 -0
- package/dist/components/content/paywall.d.ts +53 -0
- package/dist/components/content/paywall.js +221 -0
- package/dist/components/content/paywall.js.map +1 -0
- package/dist/components/content/search.d.ts +27 -0
- package/dist/components/content/search.js +164 -0
- package/dist/components/content/search.js.map +1 -0
- package/dist/components/groups/banner.d.ts +51 -0
- package/dist/components/groups/banner.js +194 -0
- package/dist/components/groups/banner.js.map +1 -0
- package/dist/components/groups/directory.d.ts +37 -0
- package/dist/components/groups/directory.js +117 -0
- package/dist/components/groups/directory.js.map +1 -0
- package/dist/components/groups/editor.d.ts +44 -0
- package/dist/components/groups/editor.js +860 -0
- package/dist/components/groups/editor.js.map +1 -0
- package/dist/components/groups/fields.d.ts +13 -0
- package/dist/components/groups/fields.js +68 -0
- package/dist/components/groups/fields.js.map +1 -0
- package/dist/components/groups/header.d.ts +25 -0
- package/dist/components/groups/header.js +131 -0
- package/dist/components/groups/header.js.map +1 -0
- package/dist/components/groups/index.d.ts +6 -0
- package/dist/components/groups/memberships.d.ts +55 -0
- package/dist/components/groups/memberships.js +527 -0
- package/dist/components/groups/memberships.js.map +1 -0
- package/dist/components/groups/parts.d.ts +49 -0
- package/dist/components/groups/parts.js +172 -0
- package/dist/components/groups/parts.js.map +1 -0
- package/dist/components/media-folder-editor.js +153 -152
- package/dist/components/media-folder-editor.js.map +1 -1
- package/dist/components/social/comments.d.ts +7 -5
- package/dist/components/social/comments.js +6 -2
- package/dist/components/social/comments.js.map +1 -1
- package/dist/components/social/engagement.d.ts +4 -3
- package/dist/components/social/engagement.js.map +1 -1
- package/dist/components/social/moderation.d.ts +1 -1
- package/dist/components/social/moderation.js +3 -3
- package/dist/components/social/moderation.js.map +1 -1
- package/dist/editor/rich-text-editor.d.ts +4 -4
- package/dist/editor/rich-text-editor.js.map +1 -1
- package/dist/index.d.ts +4 -2
- package/dist/index.js +23 -9
- package/dist/locales/admin/de.js +5 -66
- package/dist/locales/admin/de.js.map +1 -1
- package/dist/locales/admin/en.d.ts +5 -66
- package/dist/locales/admin/en.js +19 -80
- package/dist/locales/admin/en.js.map +1 -1
- package/dist/locales/admin/es.js +5 -66
- package/dist/locales/admin/es.js.map +1 -1
- package/dist/locales/admin/ja.js +5 -66
- package/dist/locales/admin/ja.js.map +1 -1
- package/dist/locales/admin/ko.js +5 -66
- package/dist/locales/admin/ko.js.map +1 -1
- package/dist/locales/admin/zh.js +5 -66
- package/dist/locales/admin/zh.js.map +1 -1
- package/dist/locales/content/de.d.ts +2 -0
- package/dist/locales/content/de.js +98 -0
- package/dist/locales/content/de.js.map +1 -0
- package/dist/locales/content/en.d.ts +93 -0
- package/dist/locales/content/en.js +98 -0
- package/dist/locales/content/en.js.map +1 -0
- package/dist/locales/content/es.d.ts +2 -0
- package/dist/locales/content/es.js +98 -0
- package/dist/locales/content/es.js.map +1 -0
- package/dist/locales/content/ja.d.ts +2 -0
- package/dist/locales/content/ja.js +98 -0
- package/dist/locales/content/ja.js.map +1 -0
- package/dist/locales/content/ko.d.ts +2 -0
- package/dist/locales/content/ko.js +98 -0
- package/dist/locales/content/ko.js.map +1 -0
- package/dist/locales/content/zh.d.ts +2 -0
- package/dist/locales/content/zh.js +98 -0
- package/dist/locales/content/zh.js.map +1 -0
- package/dist/locales/de.js +10 -2
- package/dist/locales/de.js.map +1 -1
- package/dist/locales/discovery/de.d.ts +2 -0
- package/dist/locales/discovery/de.js +68 -0
- package/dist/locales/discovery/de.js.map +1 -0
- package/dist/locales/discovery/en.d.ts +63 -0
- package/dist/locales/discovery/en.js +68 -0
- package/dist/locales/discovery/en.js.map +1 -0
- package/dist/locales/discovery/es.d.ts +2 -0
- package/dist/locales/discovery/es.js +68 -0
- package/dist/locales/discovery/es.js.map +1 -0
- package/dist/locales/discovery/ja.d.ts +2 -0
- package/dist/locales/discovery/ja.js +68 -0
- package/dist/locales/discovery/ja.js.map +1 -0
- package/dist/locales/discovery/ko.d.ts +2 -0
- package/dist/locales/discovery/ko.js +68 -0
- package/dist/locales/discovery/ko.js.map +1 -0
- package/dist/locales/discovery/zh.d.ts +2 -0
- package/dist/locales/discovery/zh.js +68 -0
- package/dist/locales/discovery/zh.js.map +1 -0
- package/dist/locales/en.d.ts +287 -67
- package/dist/locales/en.js +10 -2
- package/dist/locales/en.js.map +1 -1
- package/dist/locales/es.js +10 -2
- package/dist/locales/es.js.map +1 -1
- package/dist/locales/groups/de.d.ts +2 -0
- package/dist/locales/groups/de.js +133 -0
- package/dist/locales/groups/de.js.map +1 -0
- package/dist/locales/groups/en.d.ts +128 -0
- package/dist/locales/groups/en.js +133 -0
- package/dist/locales/groups/en.js.map +1 -0
- package/dist/locales/groups/es.d.ts +2 -0
- package/dist/locales/groups/es.js +133 -0
- package/dist/locales/groups/es.js.map +1 -0
- package/dist/locales/groups/ja.d.ts +2 -0
- package/dist/locales/groups/ja.js +133 -0
- package/dist/locales/groups/ja.js.map +1 -0
- package/dist/locales/groups/ko.d.ts +2 -0
- package/dist/locales/groups/ko.js +133 -0
- package/dist/locales/groups/ko.js.map +1 -0
- package/dist/locales/groups/zh.d.ts +2 -0
- package/dist/locales/groups/zh.js +133 -0
- package/dist/locales/groups/zh.js.map +1 -0
- package/dist/locales/ja.js +10 -2
- package/dist/locales/ja.js.map +1 -1
- package/dist/locales/ko.js +10 -2
- package/dist/locales/ko.js.map +1 -1
- package/dist/locales/social/de.js +2 -1
- package/dist/locales/social/de.js.map +1 -1
- package/dist/locales/social/en.d.ts +2 -1
- package/dist/locales/social/en.js +2 -1
- package/dist/locales/social/en.js.map +1 -1
- package/dist/locales/social/es.js +2 -1
- package/dist/locales/social/es.js.map +1 -1
- package/dist/locales/social/ja.js +2 -1
- package/dist/locales/social/ja.js.map +1 -1
- package/dist/locales/social/ko.js +2 -1
- package/dist/locales/social/ko.js.map +1 -1
- package/dist/locales/social/zh.js +2 -1
- package/dist/locales/social/zh.js.map +1 -1
- package/dist/locales/zh.js +10 -2
- package/dist/locales/zh.js.map +1 -1
- package/dist/react/admin.d.ts +1 -1
- package/dist/react/admin.js +8 -6
- package/dist/react/admin.js.map +1 -1
- package/dist/react/comments.d.ts +9 -7
- package/dist/react/comments.js +42 -27
- package/dist/react/comments.js.map +1 -1
- package/dist/react/contents.d.ts +57 -0
- package/dist/react/contents.js +214 -0
- package/dist/react/contents.js.map +1 -0
- package/dist/react/context.d.ts +1 -1
- package/dist/react/context.js.map +1 -1
- package/dist/react/crop.js +45 -44
- package/dist/react/crop.js.map +1 -1
- package/dist/react/detail.d.ts +30 -0
- package/dist/react/detail.js +42 -0
- package/dist/react/detail.js.map +1 -0
- package/dist/react/discovery.d.ts +138 -0
- package/dist/react/discovery.js +299 -0
- package/dist/react/discovery.js.map +1 -0
- package/dist/react/engagement.d.ts +5 -5
- package/dist/react/engagement.js +55 -41
- package/dist/react/engagement.js.map +1 -1
- package/dist/react/folder.js +54 -53
- package/dist/react/folder.js.map +1 -1
- package/dist/react/groups.d.ts +115 -0
- package/dist/react/groups.js +229 -0
- package/dist/react/groups.js.map +1 -0
- package/dist/react/index.d.ts +5 -1
- package/dist/react/public.d.ts +6 -5
- package/dist/react/public.js +19 -22
- package/dist/react/public.js.map +1 -1
- package/dist/react/read.js +105 -106
- package/dist/react/read.js.map +1 -1
- package/dist/react/resources.d.ts +2 -2
- package/dist/react/resources.js +69 -40
- package/dist/react/resources.js.map +1 -1
- package/dist/react/store.js +41 -39
- package/dist/react/store.js.map +1 -1
- package/dist/react/upload.js +54 -53
- package/dist/react/upload.js.map +1 -1
- package/dist/react/use-resource.d.ts +2 -1
- package/dist/react/use-resource.js +1 -0
- package/dist/react/use-resource.js.map +1 -1
- package/dist/react/versions.d.ts +57 -0
- package/dist/react/versions.js +94 -0
- package/dist/react/versions.js.map +1 -0
- package/dist/react/video.js +87 -86
- package/dist/react/video.js.map +1 -1
- package/dist/react.js +9 -5
- package/dist/styles.css +1 -1
- package/package.json +1 -1
- package/dist/client/content/posts.d.ts +0 -52
- package/dist/client/content/posts.js +0 -84
- package/dist/client/content/posts.js.map +0 -1
- package/dist/client/taxonomy.d.ts +0 -34
- package/dist/client/taxonomy.js +0 -84
- package/dist/client/taxonomy.js.map +0 -1
- package/dist/components/admin/post-manager.d.ts +0 -45
- package/dist/components/admin/post-manager.js +0 -602
- package/dist/components/admin/post-manager.js.map +0 -1
- package/dist/components/admin/taxonomy-manager.d.ts +0 -54
- package/dist/components/admin/taxonomy-manager.js +0 -976
- package/dist/components/admin/taxonomy-manager.js.map +0 -1
- package/dist/react/posts.d.ts +0 -61
- package/dist/react/posts.js +0 -183
- package/dist/react/posts.js.map +0 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"editors.js","names":[],"sources":["../../../src/components/content/editors.tsx"],"sourcesContent":["import { cn } from \"cn\";\nimport { useEffect, useId, useMemo, 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 { useMessages } from \"../../i18n/context.js\";\nimport { useContentKitClient, type ContentKitErrorHandler } from \"../../react/context.js\";\nimport { useKinds } from \"../../react/groups.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 { MediaFolderEditor } from \"../media-folder-editor.js\";\nimport { SortableList } from \"../sortable-list.js\";\nimport { ErrorLine, useAction } from \"../social/parts.js\";\nimport { GroupPicker, labelOf, useGroupNames, useLanguageName, 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\"];\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, preview and when it turns free. */\nfunction RuleFields({ value, onChange, model, labels, client }: { value: Rule; onChange: (r: Rule) => void; model: ContentModel | null; labels?: Labels; client: ContentKitClient }) {\n const { t } = useMessages();\n const id = useId();\n const tiers = model?.tiers ?? [];\n const groupKinds = Object.entries(model?.group_kinds ?? {})\n .filter(([, g]) => g.sellable || g.auth_scope)\n .map(([k]) => k);\n const [groupKind, setGroupKind] = useState(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 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 value={value.level} onValueChange={(v) => onChange({ level: v as Rule[\"level\"], preview: value.preview, free_after: value.free_after })}>\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 {(value.level === \"group\" || value.level === \"group_ppv\") && (\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 <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 <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 <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 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} 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}>\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.\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?.versions.hidden) return null;\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 languages={languages} many={spec?.versions.languages === \"many\"} pending={add.pending} onAdd={(input) => void add.run(() => client.contents.addVersion(content.id, input))} />\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} 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}>\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 && <MediaFolderEditor item={{ kind: content.kind, id: content.id, version: v.id }} label={t(\"contentEditor.media\")} />}\n </div>\n );\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?.groups?.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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"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { ContentKitUiAppearance } from '../../appearance.js';
|
|
2
|
+
import { ContentKitClient } from '../../client/client.js';
|
|
3
|
+
import { ReleaseDatesQuery } from '../../client/discovery.js';
|
|
4
|
+
import { ContentKitErrorHandler } from '../../react/context.js';
|
|
5
|
+
export interface ContentFilterSettingsProps {
|
|
6
|
+
/** Labels and group names in this language; default the provider's. */
|
|
7
|
+
language?: string;
|
|
8
|
+
/** Offer listing deleted content the reader holds. Default true. */
|
|
9
|
+
includeDeleted?: boolean;
|
|
10
|
+
client?: ContentKitClient;
|
|
11
|
+
onError?: ContentKitErrorHandler;
|
|
12
|
+
className?: string;
|
|
13
|
+
appearance?: ContentKitUiAppearance;
|
|
14
|
+
}
|
|
15
|
+
/** The signed-in reader's content filters: show or hide each configured group, and go back to its default. */
|
|
16
|
+
export declare function ContentFilterSettings(p: ContentFilterSettingsProps): import('react').JSX.Element;
|
|
17
|
+
export interface ReleaseDateIndexProps {
|
|
18
|
+
/** Which contents count: the listing's filters. */
|
|
19
|
+
query?: ReleaseDatesQuery;
|
|
20
|
+
/** The bucket chosen (a day YYYY-MM-DD or month YYYY-MM): list with released_on set to it. */
|
|
21
|
+
selected?: string;
|
|
22
|
+
onSelect?: (date: string) => void;
|
|
23
|
+
client?: ContentKitClient;
|
|
24
|
+
className?: string;
|
|
25
|
+
appearance?: ContentKitUiAppearance;
|
|
26
|
+
}
|
|
27
|
+
/** The release date index: per month or day, newest first, how many contents and how many free. */
|
|
28
|
+
export declare function ReleaseDateIndex({ query, selected, onSelect, client, className, appearance }: ReleaseDateIndexProps): import('react').JSX.Element;
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
import { useMessages as e } from "../../i18n/context.js";
|
|
2
|
+
import { ContentKitUiRoot as t } from "../../scope.js";
|
|
3
|
+
import { ContentKitContext as n } from "../../react/context.js";
|
|
4
|
+
import { Button as r } from "../../ui/button.js";
|
|
5
|
+
import { Label as i } from "../../ui/label.js";
|
|
6
|
+
import { Skeleton as a } from "../../ui/skeleton.js";
|
|
7
|
+
import { ErrorLine as o, contentError as s, useAction as c } from "../social/parts.js";
|
|
8
|
+
import { Switch as l } from "../../ui/switch.js";
|
|
9
|
+
import { useContentFilters as u, useReleaseDates as d } from "../../react/discovery.js";
|
|
10
|
+
import { useContext as f, useId as p } from "react";
|
|
11
|
+
import { Fragment as m, jsx as h, jsxs as g } from "react/jsx-runtime";
|
|
12
|
+
import { cn as _ } from "cn";
|
|
13
|
+
//#region src/components/content/filters.tsx
|
|
14
|
+
function v(d) {
|
|
15
|
+
let v = e(), { t: y } = v, b = p(), x = f(n), S = u({
|
|
16
|
+
language: d.language,
|
|
17
|
+
client: d.client
|
|
18
|
+
}), C = c("filters.save", d.onError), w = (e) => /* @__PURE__ */ h(t, {
|
|
19
|
+
appearance: d.appearance,
|
|
20
|
+
className: _("grid gap-3 text-sm", d.className),
|
|
21
|
+
"data-ckui": "content-filters",
|
|
22
|
+
children: e
|
|
23
|
+
});
|
|
24
|
+
if (x?.viewer === null) return w(/* @__PURE__ */ h("p", {
|
|
25
|
+
className: "text-muted-foreground",
|
|
26
|
+
children: y("contents.filtersSignedOut")
|
|
27
|
+
}));
|
|
28
|
+
if (!S.filters) return S.error ? w(/* @__PURE__ */ h(o, { children: s(v, S.error) })) : w(/* @__PURE__ */ h(a, { className: "h-24 w-full" }));
|
|
29
|
+
let T = S.filters;
|
|
30
|
+
return w(/* @__PURE__ */ g(m, { children: [
|
|
31
|
+
T.filters.length ? /* @__PURE__ */ h("ul", {
|
|
32
|
+
className: "grid divide-y divide-border rounded-lg border border-border",
|
|
33
|
+
children: T.filters.map((e) => /* @__PURE__ */ g("li", {
|
|
34
|
+
className: "flex flex-wrap items-center gap-3 p-3",
|
|
35
|
+
"data-ckui": "content-filter",
|
|
36
|
+
"data-slug": e.group.slug,
|
|
37
|
+
"data-visible": e.visible,
|
|
38
|
+
children: [
|
|
39
|
+
/* @__PURE__ */ h(l, {
|
|
40
|
+
id: `${b}-${e.group.id}`,
|
|
41
|
+
checked: e.visible,
|
|
42
|
+
disabled: C.pending,
|
|
43
|
+
onCheckedChange: (t) => void C.run(() => S.setVisible(e.group.id, t))
|
|
44
|
+
}),
|
|
45
|
+
/* @__PURE__ */ h(i, {
|
|
46
|
+
htmlFor: `${b}-${e.group.id}`,
|
|
47
|
+
className: "min-w-0 flex-1",
|
|
48
|
+
children: e.label || e.group.name
|
|
49
|
+
}),
|
|
50
|
+
/* @__PURE__ */ h("span", {
|
|
51
|
+
className: "text-xs text-muted-foreground",
|
|
52
|
+
children: y(e.visible ? "contents.shown" : "contents.hidden")
|
|
53
|
+
}),
|
|
54
|
+
e.overridden && /* @__PURE__ */ h(r, {
|
|
55
|
+
size: "xs",
|
|
56
|
+
variant: "ghost",
|
|
57
|
+
disabled: C.pending,
|
|
58
|
+
onClick: () => void C.run(() => S.save({
|
|
59
|
+
filters: T.filters.filter((t) => t.overridden && t.group.id !== e.group.id).map((e) => ({
|
|
60
|
+
group_id: e.group.id,
|
|
61
|
+
visible: e.visible
|
|
62
|
+
})),
|
|
63
|
+
include_deleted: T.include_deleted
|
|
64
|
+
})),
|
|
65
|
+
children: y("contents.useDefault")
|
|
66
|
+
})
|
|
67
|
+
]
|
|
68
|
+
}, e.group.id))
|
|
69
|
+
}) : /* @__PURE__ */ h("p", {
|
|
70
|
+
className: "text-muted-foreground",
|
|
71
|
+
children: y("contents.noFilters")
|
|
72
|
+
}),
|
|
73
|
+
d.includeDeleted !== !1 && /* @__PURE__ */ g("div", {
|
|
74
|
+
className: "flex items-center gap-3",
|
|
75
|
+
children: [/* @__PURE__ */ h(l, {
|
|
76
|
+
id: `${b}-deleted`,
|
|
77
|
+
checked: T.include_deleted,
|
|
78
|
+
disabled: C.pending,
|
|
79
|
+
onCheckedChange: (e) => void C.run(() => S.setIncludeDeleted(e))
|
|
80
|
+
}), /* @__PURE__ */ h(i, {
|
|
81
|
+
htmlFor: `${b}-deleted`,
|
|
82
|
+
children: y("contents.includeDeleted")
|
|
83
|
+
})]
|
|
84
|
+
}),
|
|
85
|
+
/* @__PURE__ */ h(o, { error: C.error })
|
|
86
|
+
] }));
|
|
87
|
+
}
|
|
88
|
+
function y({ query: n = {}, selected: i, onSelect: c, client: l, className: u, appearance: f }) {
|
|
89
|
+
let p = e(), { t: m } = p, v = d(n, { client: l }), y = (e) => {
|
|
90
|
+
let [t, n, r] = e.split("-").map(Number), i = new Date(Date.UTC(t, (n ?? 1) - 1, r ?? 1));
|
|
91
|
+
return new Intl.DateTimeFormat(p.language, r ? {
|
|
92
|
+
dateStyle: "medium",
|
|
93
|
+
timeZone: "UTC"
|
|
94
|
+
} : {
|
|
95
|
+
year: "numeric",
|
|
96
|
+
month: "long",
|
|
97
|
+
timeZone: "UTC"
|
|
98
|
+
}).format(i);
|
|
99
|
+
};
|
|
100
|
+
return /* @__PURE__ */ g(t, {
|
|
101
|
+
appearance: f,
|
|
102
|
+
className: _("grid gap-2 text-sm", u),
|
|
103
|
+
"data-ckui": "release-dates",
|
|
104
|
+
children: [v.loading && !v.items.length ? /* @__PURE__ */ h(a, { className: "h-24 w-full" }) : v.error && !v.items.length ? /* @__PURE__ */ h(o, { children: s(p, v.error) }) : v.items.length ? /* @__PURE__ */ h("ul", {
|
|
105
|
+
className: "grid gap-1",
|
|
106
|
+
children: v.items.map((e) => /* @__PURE__ */ h("li", { children: /* @__PURE__ */ g("button", {
|
|
107
|
+
type: "button",
|
|
108
|
+
"aria-pressed": i === e.date,
|
|
109
|
+
className: _("flex w-full items-center justify-between gap-3 rounded-md px-2 py-1.5 text-start hover:bg-muted", i === e.date && "bg-muted font-medium"),
|
|
110
|
+
onClick: () => c?.(e.date),
|
|
111
|
+
"data-ckui": "release-date",
|
|
112
|
+
"data-date": e.date,
|
|
113
|
+
children: [/* @__PURE__ */ h("span", { children: y(e.date) }), /* @__PURE__ */ g("span", {
|
|
114
|
+
className: "text-xs text-muted-foreground tabular-nums",
|
|
115
|
+
children: [p.plural("contents.items", e.count), e.free < e.count && ` · ${p.plural("contents.free", e.free)}`]
|
|
116
|
+
})]
|
|
117
|
+
}) }, e.date))
|
|
118
|
+
}) : /* @__PURE__ */ h("p", {
|
|
119
|
+
className: "text-muted-foreground",
|
|
120
|
+
children: m("contents.noDates")
|
|
121
|
+
}), v.hasMore && /* @__PURE__ */ h(r, {
|
|
122
|
+
variant: "outline",
|
|
123
|
+
size: "sm",
|
|
124
|
+
className: "justify-self-center",
|
|
125
|
+
disabled: v.loadingMore,
|
|
126
|
+
onClick: () => void v.loadMore(),
|
|
127
|
+
children: m("contents.loadMore")
|
|
128
|
+
})]
|
|
129
|
+
});
|
|
130
|
+
}
|
|
131
|
+
//#endregion
|
|
132
|
+
export { v as ContentFilterSettings, y as ReleaseDateIndex };
|
|
133
|
+
|
|
134
|
+
//# sourceMappingURL=filters.js.map
|
|
@@ -0,0 +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/** The signed-in reader's content filters: show or hide each configured group, and go back to its default. */\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 (ctx?.viewer === null) return root(<p className=\"text-muted-foreground\">{t(\"contents.filtersSignedOut\")}</p>);\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 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.group.id} className=\"flex flex-wrap items-center gap-3 p-3\" data-ckui=\"content-filter\" data-slug={x.group.slug} data-visible={x.visible}>\n <Switch id={`${id}-${x.group.id}`} checked={x.visible} disabled={save.pending} onCheckedChange={(v) => void save.run(() => f.setVisible(x.group.id, v))} />\n <Label htmlFor={`${id}-${x.group.id}`} className=\"min-w-0 flex-1\">\n {x.label || x.group.name}\n </Label>\n <span className=\"text-xs text-muted-foreground\">{t(x.visible ? \"contents.shown\" : \"contents.hidden\")}</span>\n {x.overridden && (\n <Button\n size=\"xs\"\n variant=\"ghost\"\n disabled={save.pending}\n onClick={() =>\n void save.run(() =>\n f.save({\n filters: filters.filters.filter((y) => y.overridden && y.group.id !== x.group.id).map((y) => ({ group_id: y.group.id, visible: y.visible })),\n include_deleted: filters.include_deleted,\n }),\n )\n }\n >\n {t(\"contents.useDefault\")}\n </Button>\n )}\n </li>\n ))}\n </ul>\n ) : (\n <p className=\"text-muted-foreground\">{t(\"contents.noFilters\")}</p>\n )}\n {p.includeDeleted !== false && (\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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"}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { ReactNode } from 'react';
|
|
2
|
+
import { ContentKitUiAppearance } from '../../appearance.js';
|
|
3
|
+
import { ContentKitClient } from '../../client/client.js';
|
|
4
|
+
import { ContentQuery, HistoryQuery, RailQuery, SearchQuery } from '../../client/discovery.js';
|
|
5
|
+
import { Card } from '../../client/generated/wire.js';
|
|
6
|
+
import { UseList } from '../../react/use-resource.js';
|
|
7
|
+
import { ContentCardProps } from './card.js';
|
|
8
|
+
export interface CardListProps extends Omit<ContentCardProps, "card" | "onOpen" | "children" | "className"> {
|
|
9
|
+
/** Where the list is, for exposures and click attribution: "home", "search", "similar". */
|
|
10
|
+
surface?: string;
|
|
11
|
+
/** Loads the next page as the end nears, instead of a button. */
|
|
12
|
+
infinite?: boolean;
|
|
13
|
+
/** A card's entry instead of ContentCard. */
|
|
14
|
+
renderCard?: (card: Card, position: number) => ReactNode;
|
|
15
|
+
/** Shown when nothing matches. */
|
|
16
|
+
empty?: ReactNode;
|
|
17
|
+
pageSize?: number;
|
|
18
|
+
client?: ContentKitClient;
|
|
19
|
+
className?: string;
|
|
20
|
+
appearance?: ContentKitUiAppearance;
|
|
21
|
+
}
|
|
22
|
+
/** A list's cards in a responsive grid, paged, with exposures and click signals. */
|
|
23
|
+
export declare function CardGrid({ list, render, ...p }: CardListProps & {
|
|
24
|
+
list: UseList<Card>;
|
|
25
|
+
render: string;
|
|
26
|
+
}): import('react').JSX.Element;
|
|
27
|
+
/** Contents as cards (GET /v1/contents): any sort and filter, paged. */
|
|
28
|
+
export declare function ContentGrid({ query, ...p }: CardListProps & {
|
|
29
|
+
query: ContentQuery;
|
|
30
|
+
}): import('react').JSX.Element;
|
|
31
|
+
/** Search results as cards; nothing until the query has text. */
|
|
32
|
+
export declare function SearchResults({ query, ...p }: CardListProps & {
|
|
33
|
+
query: SearchQuery;
|
|
34
|
+
}): import('react').JSX.Element | null;
|
|
35
|
+
/** The signed-in reader's history as cards, each removable, with a clear-all. */
|
|
36
|
+
export declare function ContentHistory({ query, ...p }: CardListProps & {
|
|
37
|
+
query?: HistoryQuery;
|
|
38
|
+
}): import('react').JSX.Element;
|
|
39
|
+
export interface ContentRailProps extends Omit<CardListProps, "infinite" | "empty"> {
|
|
40
|
+
/** The rail's heading. */
|
|
41
|
+
title: ReactNode;
|
|
42
|
+
/** Contents like this one. */
|
|
43
|
+
similar?: string;
|
|
44
|
+
/** For the signed-in reader. */
|
|
45
|
+
recommendations?: boolean;
|
|
46
|
+
/** The reader's history: { status: "in_progress" } is a continue-watching rail. */
|
|
47
|
+
history?: HistoryQuery;
|
|
48
|
+
/** An ordered group's members in its order: a featured rail (its windows apply). */
|
|
49
|
+
group?: string;
|
|
50
|
+
/** Any list: a sort and filters. */
|
|
51
|
+
list?: ContentQuery;
|
|
52
|
+
/** Filters and reader options of a similar or recommended rail. */
|
|
53
|
+
query?: RailQuery;
|
|
54
|
+
/** A link beside the heading, e.g. to the whole list. */
|
|
55
|
+
more?: ReactNode;
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* A horizontal row of contents: similar, recommended, the reader's history,
|
|
59
|
+
* an ordered group's members or any list. It hides itself when it has none or
|
|
60
|
+
* the site runs without what it needs.
|
|
61
|
+
*/
|
|
62
|
+
export declare function ContentRail({ title, similar, recommendations, history, group, list: listQuery, query, more, ...p }: ContentRailProps): import('react').JSX.Element | null;
|
|
@@ -0,0 +1,233 @@
|
|
|
1
|
+
import { useMessages as e } from "../../i18n/context.js";
|
|
2
|
+
import { ContentKitUiRoot as t } from "../../scope.js";
|
|
3
|
+
import { ContentKitContext as n } from "../../react/context.js";
|
|
4
|
+
import { Button as r } from "../../ui/button.js";
|
|
5
|
+
import { useNearViewport as i } from "../../react/viewport.js";
|
|
6
|
+
import { Skeleton as a } from "../../ui/skeleton.js";
|
|
7
|
+
import { contentError as o, useAction as s } from "../social/parts.js";
|
|
8
|
+
import { useKinds as c } from "../../react/groups.js";
|
|
9
|
+
import { useContents as l, useExposure as u, useHistory as d, useRecommendations as f, useSearch as p, useSimilar as m } from "../../react/discovery.js";
|
|
10
|
+
import { ContentCard as h } from "./card.js";
|
|
11
|
+
import { useContext as g, useEffect as _, useMemo as v } from "react";
|
|
12
|
+
import { jsx as y, jsxs as b } from "react/jsx-runtime";
|
|
13
|
+
import { cn as x } from "cn";
|
|
14
|
+
//#region src/components/content/grid.tsx
|
|
15
|
+
var S = "grid grid-cols-[repeat(auto-fill,minmax(min(100%,10rem),1fr))] gap-x-4 gap-y-6";
|
|
16
|
+
function C({ list: n, render: s, ...l }) {
|
|
17
|
+
let d = e(), { t: f } = d, { kinds: p } = c({ client: l.client }), m = u(n.items, {
|
|
18
|
+
surface: l.surface ?? "list",
|
|
19
|
+
render: s,
|
|
20
|
+
client: l.client
|
|
21
|
+
}), [g, v] = i({
|
|
22
|
+
margin: "600px 0px",
|
|
23
|
+
leaveMargin: "1200px 0px"
|
|
24
|
+
}), { hasMore: C, loadingMore: w, loadMore: T } = n;
|
|
25
|
+
_(() => {
|
|
26
|
+
l.infinite && v && C && !w && T();
|
|
27
|
+
}, [
|
|
28
|
+
l.infinite,
|
|
29
|
+
v,
|
|
30
|
+
C,
|
|
31
|
+
w,
|
|
32
|
+
T
|
|
33
|
+
]);
|
|
34
|
+
let E = l.tiers ?? p?.tiers;
|
|
35
|
+
return /* @__PURE__ */ b(t, {
|
|
36
|
+
appearance: l.appearance,
|
|
37
|
+
className: x("grid gap-4 text-sm", l.className),
|
|
38
|
+
"data-ckui": "content-grid",
|
|
39
|
+
"aria-busy": n.loading,
|
|
40
|
+
children: [n.loading && !n.items.length ? /* @__PURE__ */ y("div", {
|
|
41
|
+
className: S,
|
|
42
|
+
children: Array.from({ length: 8 }, (e, t) => /* @__PURE__ */ y(a, { className: l.shape === "landscape" ? "aspect-video w-full" : "aspect-[3/4] w-full" }, t))
|
|
43
|
+
}) : n.error && !n.items.length ? /* @__PURE__ */ b("div", {
|
|
44
|
+
role: "alert",
|
|
45
|
+
className: "grid justify-items-start gap-2",
|
|
46
|
+
children: [/* @__PURE__ */ y("p", {
|
|
47
|
+
className: "text-destructive",
|
|
48
|
+
children: o(d, n.error)
|
|
49
|
+
}), /* @__PURE__ */ y(r, {
|
|
50
|
+
size: "sm",
|
|
51
|
+
variant: "outline",
|
|
52
|
+
onClick: n.reload,
|
|
53
|
+
children: f("common.retry")
|
|
54
|
+
})]
|
|
55
|
+
}) : n.items.length ? /* @__PURE__ */ y("ol", {
|
|
56
|
+
className: S,
|
|
57
|
+
children: n.items.map((e, t) => /* @__PURE__ */ y("li", {
|
|
58
|
+
ref: m.track(e.id, t + 1),
|
|
59
|
+
children: l.renderCard ? l.renderCard(e, t + 1) : /* @__PURE__ */ y(h, {
|
|
60
|
+
card: e,
|
|
61
|
+
href: l.href,
|
|
62
|
+
shape: l.shape,
|
|
63
|
+
groupKinds: l.groupKinds,
|
|
64
|
+
chips: l.chips,
|
|
65
|
+
tiers: E,
|
|
66
|
+
labels: l.labels,
|
|
67
|
+
owner: l.owner,
|
|
68
|
+
ownerHref: l.ownerHref,
|
|
69
|
+
onOpen: () => m.click(e.id, t + 1)
|
|
70
|
+
})
|
|
71
|
+
}, e.id))
|
|
72
|
+
}) : /* @__PURE__ */ y("div", {
|
|
73
|
+
className: "text-muted-foreground",
|
|
74
|
+
role: "status",
|
|
75
|
+
children: l.empty ?? f("contents.empty")
|
|
76
|
+
}), n.hasMore && /* @__PURE__ */ y("div", {
|
|
77
|
+
ref: g,
|
|
78
|
+
className: "grid justify-items-center",
|
|
79
|
+
children: /* @__PURE__ */ y(r, {
|
|
80
|
+
variant: "outline",
|
|
81
|
+
size: "sm",
|
|
82
|
+
disabled: n.loadingMore,
|
|
83
|
+
onClick: () => void n.loadMore(),
|
|
84
|
+
children: n.loadingMore ? f("contents.loading") : f("contents.loadMore")
|
|
85
|
+
})
|
|
86
|
+
})]
|
|
87
|
+
});
|
|
88
|
+
}
|
|
89
|
+
function w({ query: e, ...t }) {
|
|
90
|
+
let n = v(() => ({
|
|
91
|
+
...e,
|
|
92
|
+
limit: e.limit ?? t.pageSize
|
|
93
|
+
}), [e, t.pageSize]), r = l(n, { client: t.client });
|
|
94
|
+
return /* @__PURE__ */ y(C, {
|
|
95
|
+
...t,
|
|
96
|
+
list: r,
|
|
97
|
+
render: JSON.stringify(n)
|
|
98
|
+
});
|
|
99
|
+
}
|
|
100
|
+
function T({ query: t, ...n }) {
|
|
101
|
+
let { t: r } = e(), i = v(() => ({
|
|
102
|
+
...t,
|
|
103
|
+
limit: t.limit ?? n.pageSize
|
|
104
|
+
}), [t, n.pageSize]), a = p(i, { client: n.client });
|
|
105
|
+
return t.q.trim() ? /* @__PURE__ */ y(C, {
|
|
106
|
+
surface: "search",
|
|
107
|
+
empty: r("contents.noResults", { q: t.q.trim() }),
|
|
108
|
+
...n,
|
|
109
|
+
list: a,
|
|
110
|
+
render: JSON.stringify(i)
|
|
111
|
+
}) : null;
|
|
112
|
+
}
|
|
113
|
+
function E({ query: t = {}, ...i }) {
|
|
114
|
+
let { t: a } = e(), o = g(n), c = v(() => ({
|
|
115
|
+
...t,
|
|
116
|
+
limit: t.limit ?? i.pageSize
|
|
117
|
+
}), [t, i.pageSize]), l = d(c, { client: i.client }), u = s("history.forget");
|
|
118
|
+
return o?.viewer === null ? /* @__PURE__ */ y("p", {
|
|
119
|
+
className: "text-muted-foreground",
|
|
120
|
+
children: a("contents.historySignedOut")
|
|
121
|
+
}) : /* @__PURE__ */ b("div", {
|
|
122
|
+
className: "grid gap-3",
|
|
123
|
+
"data-ckui": "content-history",
|
|
124
|
+
children: [l.items.length > 0 && /* @__PURE__ */ y(r, {
|
|
125
|
+
size: "sm",
|
|
126
|
+
variant: "outline",
|
|
127
|
+
className: "justify-self-end",
|
|
128
|
+
disabled: u.pending,
|
|
129
|
+
onClick: () => void u.run(() => l.forget(t.kind ? { kind: t.kind } : {})),
|
|
130
|
+
children: a("contents.clearHistory")
|
|
131
|
+
}), /* @__PURE__ */ y(C, {
|
|
132
|
+
surface: "history",
|
|
133
|
+
empty: a("contents.historyEmpty"),
|
|
134
|
+
...i,
|
|
135
|
+
list: l,
|
|
136
|
+
render: JSON.stringify(c),
|
|
137
|
+
renderCard: i.renderCard ?? ((e) => /* @__PURE__ */ y(h, {
|
|
138
|
+
card: e,
|
|
139
|
+
href: i.href,
|
|
140
|
+
shape: i.shape,
|
|
141
|
+
groupKinds: i.groupKinds,
|
|
142
|
+
chips: i.chips,
|
|
143
|
+
tiers: i.tiers,
|
|
144
|
+
labels: i.labels,
|
|
145
|
+
owner: i.owner,
|
|
146
|
+
ownerHref: i.ownerHref,
|
|
147
|
+
children: /* @__PURE__ */ y(r, {
|
|
148
|
+
size: "xs",
|
|
149
|
+
variant: "ghost",
|
|
150
|
+
className: "justify-self-start",
|
|
151
|
+
disabled: u.pending,
|
|
152
|
+
onClick: () => void u.run(() => l.forget({ content_id: e.id })),
|
|
153
|
+
children: a("contents.removeFromHistory")
|
|
154
|
+
})
|
|
155
|
+
}))
|
|
156
|
+
})]
|
|
157
|
+
});
|
|
158
|
+
}
|
|
159
|
+
function D({ title: e, similar: n, recommendations: r, history: i, group: o, list: s, query: p = {}, more: g, ..._ }) {
|
|
160
|
+
let S = p.limit ?? _.pageSize ?? 12, C = v(() => ({
|
|
161
|
+
...p,
|
|
162
|
+
limit: S
|
|
163
|
+
}), [p, S]), w = v(() => s ? {
|
|
164
|
+
...s,
|
|
165
|
+
limit: s.limit ?? S
|
|
166
|
+
} : o ? {
|
|
167
|
+
groups: [o],
|
|
168
|
+
sort: "position",
|
|
169
|
+
limit: S
|
|
170
|
+
} : null, [
|
|
171
|
+
s,
|
|
172
|
+
o,
|
|
173
|
+
S
|
|
174
|
+
]), T = m(r || i || w ? null : n, C, { client: _.client }), E = f(r ? C : null, { client: _.client }), D = d(i ? {
|
|
175
|
+
...i,
|
|
176
|
+
limit: i.limit ?? S
|
|
177
|
+
} : null, { client: _.client }), O = l(w, { client: _.client }), k = r ? E : i || w ? (() => {
|
|
178
|
+
let e = i ? D : O;
|
|
179
|
+
return {
|
|
180
|
+
items: e.items,
|
|
181
|
+
loading: e.loading,
|
|
182
|
+
error: e.error,
|
|
183
|
+
unavailable: e.error?.code === "not_configured",
|
|
184
|
+
reload: e.reload
|
|
185
|
+
};
|
|
186
|
+
})() : T, { kinds: A } = c({ client: _.client }), j = _.surface ?? (r ? "recommendations" : i ? "history" : o ? "featured" : w ? "list" : "similar"), M = u(k.items, {
|
|
187
|
+
surface: j,
|
|
188
|
+
render: JSON.stringify([
|
|
189
|
+
n,
|
|
190
|
+
r,
|
|
191
|
+
i,
|
|
192
|
+
o,
|
|
193
|
+
w,
|
|
194
|
+
C
|
|
195
|
+
]),
|
|
196
|
+
client: _.client
|
|
197
|
+
});
|
|
198
|
+
return !(n || r || i || o || w) || k.unavailable || !k.loading && !k.items.length ? null : /* @__PURE__ */ b(t, {
|
|
199
|
+
appearance: _.appearance,
|
|
200
|
+
className: x("grid gap-3 text-sm", _.className),
|
|
201
|
+
"data-ckui": "content-rail",
|
|
202
|
+
"data-surface": j,
|
|
203
|
+
children: [/* @__PURE__ */ b("div", {
|
|
204
|
+
className: "flex items-baseline justify-between gap-2",
|
|
205
|
+
children: [/* @__PURE__ */ y("h2", {
|
|
206
|
+
className: "text-base font-semibold",
|
|
207
|
+
children: e
|
|
208
|
+
}), g]
|
|
209
|
+
}), /* @__PURE__ */ y("ol", {
|
|
210
|
+
className: "flex snap-x gap-4 overflow-x-auto pb-2",
|
|
211
|
+
children: (k.loading && !k.items.length ? Array.from({ length: 6 }, () => null) : k.items).map((e, t) => /* @__PURE__ */ y("li", {
|
|
212
|
+
className: "w-36 shrink-0 snap-start sm:w-44",
|
|
213
|
+
ref: e ? M.track(e.id, t + 1) : void 0,
|
|
214
|
+
children: e ? _.renderCard ? _.renderCard(e, t + 1) : /* @__PURE__ */ y(h, {
|
|
215
|
+
card: e,
|
|
216
|
+
href: _.href,
|
|
217
|
+
shape: _.shape,
|
|
218
|
+
groupKinds: _.groupKinds,
|
|
219
|
+
chips: _.chips,
|
|
220
|
+
tiers: _.tiers ?? A?.tiers,
|
|
221
|
+
labels: _.labels,
|
|
222
|
+
owner: _.owner,
|
|
223
|
+
ownerHref: _.ownerHref,
|
|
224
|
+
onOpen: () => M.click(e.id, t + 1)
|
|
225
|
+
}) : /* @__PURE__ */ y(a, { className: _.shape === "landscape" ? "aspect-video w-full" : "aspect-[3/4] w-full" })
|
|
226
|
+
}, e?.id ?? t))
|
|
227
|
+
})]
|
|
228
|
+
});
|
|
229
|
+
}
|
|
230
|
+
//#endregion
|
|
231
|
+
export { C as CardGrid, w as ContentGrid, E as ContentHistory, D as ContentRail, T as SearchResults };
|
|
232
|
+
|
|
233
|
+
//# sourceMappingURL=grid.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"grid.js","names":[],"sources":["../../../src/components/content/grid.tsx"],"sourcesContent":["import { cn } from \"cn\";\nimport { useContext, useEffect, useMemo, type ReactNode } from \"react\";\nimport type { ContentKitUiAppearance } from \"../../appearance.js\";\nimport type { ContentKitClient } from \"../../client/client.js\";\nimport type { ContentQuery, HistoryQuery, RailQuery, SearchQuery } from \"../../client/discovery.js\";\nimport type { Card } from \"../../client/generated/wire.js\";\nimport { useMessages } from \"../../i18n/context.js\";\nimport { ContentKitContext } from \"../../react/context.js\";\nimport { useContents, useExposure, useHistory, useRecommendations, useSearch, useSimilar, type UseRail } from \"../../react/discovery.js\";\nimport { useKinds } from \"../../react/groups.js\";\nimport type { UseList } from \"../../react/use-resource.js\";\nimport { useNearViewport } from \"../../react/viewport.js\";\nimport { ContentKitUiRoot } from \"../../scope.js\";\nimport { Button } from \"#ckui/ui/button\";\nimport { Skeleton } from \"#ckui/ui/skeleton\";\nimport { contentError, useAction } from \"../social/parts.js\";\nimport { ContentCard, type ContentCardProps } from \"./card.js\";\n\nexport interface CardListProps extends Omit<ContentCardProps, \"card\" | \"onOpen\" | \"children\" | \"className\"> {\n /** Where the list is, for exposures and click attribution: \"home\", \"search\", \"similar\". */\n surface?: string;\n /** Loads the next page as the end nears, instead of a button. */\n infinite?: boolean;\n /** A card's entry instead of ContentCard. */\n renderCard?: (card: Card, position: number) => ReactNode;\n /** Shown when nothing matches. */\n empty?: ReactNode;\n pageSize?: number;\n client?: ContentKitClient;\n className?: string;\n appearance?: ContentKitUiAppearance;\n}\n\nconst GRID = \"grid grid-cols-[repeat(auto-fill,minmax(min(100%,10rem),1fr))] gap-x-4 gap-y-6\";\n\n/** A list's cards in a responsive grid, paged, with exposures and click signals. */\nexport function CardGrid({ list, render, ...p }: CardListProps & { list: UseList<Card>; render: string }) {\n const m = useMessages();\n const { t } = m;\n const { kinds } = useKinds({ client: p.client });\n const exposure = useExposure(list.items, { surface: p.surface ?? \"list\", render, client: p.client });\n const [sentinel, near] = useNearViewport({ margin: \"600px 0px\", leaveMargin: \"1200px 0px\" });\n const { hasMore, loadingMore, loadMore } = list;\n useEffect(() => {\n if (p.infinite && near && hasMore && !loadingMore) void loadMore();\n }, [p.infinite, near, hasMore, loadingMore, loadMore]);\n const tiers = p.tiers ?? kinds?.tiers;\n return (\n <ContentKitUiRoot appearance={p.appearance} className={cn(\"grid gap-4 text-sm\", p.className)} data-ckui=\"content-grid\" aria-busy={list.loading}>\n {list.loading && !list.items.length ? (\n <div className={GRID}>\n {Array.from({ length: 8 }, (_, i) => (\n <Skeleton key={i} className={p.shape === \"landscape\" ? \"aspect-video w-full\" : \"aspect-[3/4] w-full\"} />\n ))}\n </div>\n ) : list.error && !list.items.length ? (\n <div role=\"alert\" className=\"grid justify-items-start gap-2\">\n <p className=\"text-destructive\">{contentError(m, list.error)}</p>\n <Button size=\"sm\" variant=\"outline\" onClick={list.reload}>\n {t(\"common.retry\")}\n </Button>\n </div>\n ) : !list.items.length ? (\n <div className=\"text-muted-foreground\" role=\"status\">\n {p.empty ?? t(\"contents.empty\")}\n </div>\n ) : (\n <ol className={GRID}>\n {list.items.map((card, i) => (\n <li key={card.id} ref={exposure.track(card.id, i + 1)}>\n {p.renderCard ? (\n p.renderCard(card, i + 1)\n ) : (\n <ContentCard\n card={card}\n href={p.href}\n shape={p.shape}\n groupKinds={p.groupKinds}\n chips={p.chips}\n tiers={tiers}\n labels={p.labels}\n owner={p.owner}\n ownerHref={p.ownerHref}\n onOpen={() => exposure.click(card.id, i + 1)}\n />\n )}\n </li>\n ))}\n </ol>\n )}\n {list.hasMore && (\n <div ref={sentinel} className=\"grid justify-items-center\">\n <Button variant=\"outline\" size=\"sm\" disabled={list.loadingMore} onClick={() => void list.loadMore()}>\n {list.loadingMore ? t(\"contents.loading\") : t(\"contents.loadMore\")}\n </Button>\n </div>\n )}\n </ContentKitUiRoot>\n );\n}\n\n/** Contents as cards (GET /v1/contents): any sort and filter, paged. */\nexport function ContentGrid({ query, ...p }: CardListProps & { query: ContentQuery }) {\n const q = useMemo(() => ({ ...query, limit: query.limit ?? p.pageSize }), [query, p.pageSize]);\n const list = useContents(q, { client: p.client });\n return <CardGrid {...p} list={list} render={JSON.stringify(q)} />;\n}\n\n/** Search results as cards; nothing until the query has text. */\nexport function SearchResults({ query, ...p }: CardListProps & { query: SearchQuery }) {\n const { t } = useMessages();\n const q = useMemo(() => ({ ...query, limit: query.limit ?? p.pageSize }), [query, p.pageSize]);\n const list = useSearch(q, { client: p.client });\n if (!query.q.trim()) return null;\n return <CardGrid surface=\"search\" empty={t(\"contents.noResults\", { q: query.q.trim() })} {...p} list={list} render={JSON.stringify(q)} />;\n}\n\n/** The signed-in reader's history as cards, each removable, with a clear-all. */\nexport function ContentHistory({ query = {}, ...p }: CardListProps & { query?: HistoryQuery }) {\n const { t } = useMessages();\n const ctx = useContext(ContentKitContext);\n const q = useMemo(() => ({ ...query, limit: query.limit ?? p.pageSize }), [query, p.pageSize]);\n const list = useHistory(q, { client: p.client });\n const forget = useAction(\"history.forget\");\n if (ctx?.viewer === null) return <p className=\"text-muted-foreground\">{t(\"contents.historySignedOut\")}</p>;\n return (\n <div className=\"grid gap-3\" data-ckui=\"content-history\">\n {list.items.length > 0 && (\n <Button size=\"sm\" variant=\"outline\" className=\"justify-self-end\" disabled={forget.pending} onClick={() => void forget.run(() => list.forget(query.kind ? { kind: query.kind } : {}))}>\n {t(\"contents.clearHistory\")}\n </Button>\n )}\n <CardGrid\n surface=\"history\"\n empty={t(\"contents.historyEmpty\")}\n {...p}\n list={list}\n render={JSON.stringify(q)}\n renderCard={\n p.renderCard ??\n ((card) => (\n <ContentCard\n card={card}\n href={p.href}\n shape={p.shape}\n groupKinds={p.groupKinds}\n chips={p.chips}\n tiers={p.tiers}\n labels={p.labels}\n owner={p.owner}\n ownerHref={p.ownerHref}\n >\n <Button size=\"xs\" variant=\"ghost\" className=\"justify-self-start\" disabled={forget.pending} onClick={() => void forget.run(() => list.forget({ content_id: card.id }))}>\n {t(\"contents.removeFromHistory\")}\n </Button>\n </ContentCard>\n ))\n }\n />\n </div>\n );\n}\n\nexport interface ContentRailProps extends Omit<CardListProps, \"infinite\" | \"empty\"> {\n /** The rail's heading. */\n title: ReactNode;\n /** Contents like this one. */\n similar?: string;\n /** For the signed-in reader. */\n recommendations?: boolean;\n /** The reader's history: { status: \"in_progress\" } is a continue-watching rail. */\n history?: HistoryQuery;\n /** An ordered group's members in its order: a featured rail (its windows apply). */\n group?: string;\n /** Any list: a sort and filters. */\n list?: ContentQuery;\n /** Filters and reader options of a similar or recommended rail. */\n query?: RailQuery;\n /** A link beside the heading, e.g. to the whole list. */\n more?: ReactNode;\n}\n\n/**\n * A horizontal row of contents: similar, recommended, the reader's history,\n * an ordered group's members or any list. It hides itself when it has none or\n * the site runs without what it needs.\n */\nexport function ContentRail({ title, similar, recommendations, history, group, list: listQuery, query = {}, more, ...p }: ContentRailProps) {\n const limit = query.limit ?? p.pageSize ?? 12;\n const q = useMemo(() => ({ ...query, limit }), [query, limit]);\n const listing = useMemo(\n () => (listQuery ? { ...listQuery, limit: listQuery.limit ?? limit } : group ? { groups: [group], sort: \"position\" as const, limit } : null),\n [listQuery, group, limit],\n );\n const like = useSimilar(recommendations || history || listing ? null : similar, q, { client: p.client });\n const mine = useRecommendations(recommendations ? q : null, { client: p.client });\n const seen = useHistory(history ? { ...history, limit: history.limit ?? limit } : null, { client: p.client });\n const listed = useContents(listing, { client: p.client });\n const rail: UseRail = recommendations\n ? mine\n : history || listing\n ? (() => {\n const l = history ? seen : listed;\n return { items: l.items, loading: l.loading, error: l.error, unavailable: l.error?.code === \"not_configured\", reload: l.reload };\n })()\n : like;\n const { kinds } = useKinds({ client: p.client });\n const surface = p.surface ?? (recommendations ? \"recommendations\" : history ? \"history\" : group ? \"featured\" : listing ? \"list\" : \"similar\");\n const exposure = useExposure(rail.items, { surface, render: JSON.stringify([similar, recommendations, history, group, listing, q]), client: p.client });\n const source = similar || recommendations || history || group || listing;\n if (!source || rail.unavailable || (!rail.loading && !rail.items.length)) return null;\n return (\n <ContentKitUiRoot appearance={p.appearance} className={cn(\"grid gap-3 text-sm\", p.className)} data-ckui=\"content-rail\" data-surface={surface}>\n <div className=\"flex items-baseline justify-between gap-2\">\n <h2 className=\"text-base font-semibold\">{title}</h2>\n {more}\n </div>\n <ol className=\"flex snap-x gap-4 overflow-x-auto pb-2\">\n {(rail.loading && !rail.items.length ? Array.from({ length: 6 }, () => null) : rail.items).map((card, i) => (\n <li key={card?.id ?? i} className=\"w-36 shrink-0 snap-start sm:w-44\" ref={card ? exposure.track(card.id, i + 1) : undefined}>\n {!card ? (\n <Skeleton className={p.shape === \"landscape\" ? \"aspect-video w-full\" : \"aspect-[3/4] w-full\"} />\n ) : p.renderCard ? (\n p.renderCard(card, i + 1)\n ) : (\n <ContentCard\n card={card}\n href={p.href}\n shape={p.shape}\n groupKinds={p.groupKinds}\n chips={p.chips}\n tiers={p.tiers ?? kinds?.tiers}\n labels={p.labels}\n owner={p.owner}\n ownerHref={p.ownerHref}\n onOpen={() => exposure.click(card.id, i + 1)}\n />\n )}\n </li>\n ))}\n </ol>\n </ContentKitUiRoot>\n );\n}\n"],"mappings":"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"}
|