@openrails/contentkit-ui 0.103.1 → 0.103.2
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/dist/components/admin/content-manager.d.ts +1 -1
- package/dist/components/admin/content-manager.js +346 -304
- package/dist/components/admin/content-manager.js.map +1 -1
- package/dist/components/admin/page-review.js +106 -97
- package/dist/components/admin/page-review.js.map +1 -1
- package/dist/components/admin/reader-content-editor.d.ts +6 -0
- package/dist/components/admin/reader-content-editor.js +709 -0
- package/dist/components/admin/reader-content-editor.js.map +1 -0
- package/dist/components/admin/reader-manifest.js +120 -105
- package/dist/components/admin/reader-manifest.js.map +1 -1
- package/dist/components/content/editor-save.d.ts +32 -0
- package/dist/components/content/editor-save.js +51 -0
- package/dist/components/content/editor-save.js.map +1 -0
- package/dist/components/content/editors.d.ts +17 -2
- package/dist/components/content/editors.js +359 -328
- package/dist/components/content/editors.js.map +1 -1
- package/dist/components/content/offer-fields.d.ts +1 -1
- package/dist/components/content/offer-fields.js +86 -64
- package/dist/components/content/offer-fields.js.map +1 -1
- package/dist/components/groups/memberships.d.ts +11 -1
- package/dist/components/groups/memberships.js +1 -1
- package/dist/components/groups/memberships.js.map +1 -1
- package/dist/components/media-folder-editor.d.ts +4 -0
- package/dist/components/media-folder-editor.js +177 -167
- package/dist/components/media-folder-editor.js.map +1 -1
- package/dist/index.js +1 -1
- package/dist/locales/admin/de.js +25 -0
- package/dist/locales/admin/de.js.map +1 -1
- package/dist/locales/admin/en.d.ts +25 -0
- package/dist/locales/admin/en.js +25 -0
- package/dist/locales/admin/en.js.map +1 -1
- package/dist/locales/admin/es.js +25 -0
- package/dist/locales/admin/es.js.map +1 -1
- package/dist/locales/admin/ja.js +25 -0
- package/dist/locales/admin/ja.js.map +1 -1
- package/dist/locales/admin/ko.js +25 -0
- package/dist/locales/admin/ko.js.map +1 -1
- package/dist/locales/admin/zh.js +25 -0
- package/dist/locales/admin/zh.js.map +1 -1
- package/dist/locales/en.d.ts +25 -0
- package/dist/react/page-review.d.ts +1 -1
- package/dist/react/page-review.js +6 -5
- package/dist/react/page-review.js.map +1 -1
- package/dist/react/use-draft.d.ts +8 -0
- package/dist/react/use-draft.js +35 -0
- package/dist/react/use-draft.js.map +1 -0
- package/dist/styles.css +1 -1
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"reader-manifest.js","names":[],"sources":["../../../src/components/admin/reader-manifest.tsx"],"sourcesContent":["import { cn } from \"cn\";\nimport { useId, useMemo, useState, type ReactNode } from \"react\";\nimport type { ContentKitUiAppearance } from \"../../appearance.js\";\nimport type { ContentKitClient } from \"../../client/client.js\";\nimport type { Anchor, BackgroundCue, ForegroundCue, ReaderMeta, ReaderPlan } from \"../../client/generated/wire.js\";\nimport { emptyReaderMeta, matchAudio, readerMetaProblems, readerNames, type AudioMatch, type ReaderMetaProblem, type ReaderNames } from \"../../client/reader-meta.js\";\nimport { useMessages } from \"../../i18n/context.js\";\nimport { useContentKitClient, type ContentKitErrorHandler } from \"../../react/context.js\";\nimport { useReaderPlan } from \"../../react/versions.js\";\nimport { ContentKitUiRoot } from \"../../scope.js\";\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 { ErrorLine, useAction } from \"../social/parts.js\";\nimport { LoadFailed, Rows } from \"./shell.js\";\n\nexport interface ReaderManifestEditorProps {\n content: string;\n version: string;\n client?: ContentKitClient;\n onError?: ContentKitErrorHandler;\n className?: string;\n appearance?: ContentKitUiAppearance;\n}\n\nconst NONE = \"__none__\";\n\n/** A page or an anchor as one select value. */\nconst placeOf = (page?: string, anchor?: string) => (anchor !== undefined ? `anchor:${anchor}` : page !== undefined ? `page:${page}` : NONE);\nconst fromPlace = (v: string): { page?: string; anchor?: string } =>\n v.startsWith(\"anchor:\") ? { anchor: v.slice(7) } : v.startsWith(\"page:\") ? { page: v.slice(5) } : {};\n\n/** Only what the server stores: no empty layers, defaults or lists. */\nfunction clean(meta: ReaderMeta): ReaderMeta {\n const auto = meta.defaults?.auto_advance_seconds;\n return {\n schema_version: 1,\n ...(auto !== undefined ? { defaults: { auto_advance_seconds: auto } } : {}),\n anchors: (meta.anchors ?? []).map((a) => ({ id: a.id.trim(), page: a.page, offset_percent: a.offset_percent, ...(a.duration_seconds !== undefined ? { duration_seconds: a.duration_seconds } : {}) })),\n background: (meta.background ?? []).map((c) => {\n const layer = c.layer?.trim();\n return { ...c, ...(layer ? { layer } : { layer: undefined }) };\n }),\n foreground: meta.foreground ?? [],\n };\n}\n\nconst num = (v: string): number => (v.trim() === \"\" ? Number.NaN : Number(v));\nconst shown = (n: number | undefined) => (n === undefined || Number.isNaN(n) ? \"\" : String(n));\n\n/**\n * Editors: a reader version's manifest over its published pages and audio:\n * scroll anchors, foreground cues (one track at a page or anchor, matched\n * from file names in one step), background tracks over a range, and the\n * auto-advance default. Page order is the version's media order.\n */\nexport function ReaderManifestEditor({ content, version, client: own, onError, className, appearance }: ReaderManifestEditorProps) {\n const { t } = useMessages();\n const client = useContentKitClient(own);\n const plan = useReaderPlan(content, version, { client });\n const names = useMemo<ReaderNames>(() => (plan.plan ? readerNames(plan.plan) : { pages: [], files: [] }), [plan.plan]);\n const [basis, setBasis] = useState<ReaderPlan | null>(null);\n const [meta, setMeta] = useState<ReaderMeta | null>(null);\n const [dirty, setDirty] = useState(false);\n const [saved, setSaved] = useState(false);\n const [matched, setMatched] = useState<AudioMatch | null>(null);\n const save = useAction(\"reader.save\", onError);\n // A fresh plan replaces the draft unless it has unsaved edits.\n if (plan.plan && plan.plan !== basis && !dirty) {\n setBasis(plan.plan);\n setMeta(plan.plan.reader ? structuredClone(plan.plan.reader) : emptyReaderMeta());\n }\n const problems = useMemo(() => (meta ? readerMetaProblems(meta, names) : []), [meta, names]);\n const edit = (fn: (m: ReaderMeta) => ReaderMeta) => {\n setMeta((m) => (m ? fn(m) : m));\n setDirty(true);\n setSaved(false);\n };\n const body = (() => {\n if (plan.loading && !plan.plan && !plan.pending) return <Rows count={2} />;\n if (plan.pending) return <p className=\"text-muted-foreground\">{t(\"readerManifest.pending\")}</p>;\n if (plan.error && !plan.plan) return <LoadFailed error={plan.error} message={t(\"readerManifest.loadFailed\")} retry={plan.reload} />;\n if (!meta) return null;\n const anchors = meta.anchors ?? [];\n const anchorIds = anchors.map((a) => a.id).filter(Boolean);\n return (\n <form\n className=\"grid gap-4\"\n onSubmit={(e) => {\n e.preventDefault();\n if (problems.length) return;\n setSaved(false);\n void save\n .run(async () => {\n await client.versions.setReader(content, version, clean(meta));\n return true;\n })\n .then((ok) => {\n if (!ok) return;\n setDirty(false);\n setSaved(true);\n });\n }}\n >\n <p className=\"text-muted-foreground\">{t(\"readerManifest.summary\", { pages: names.pages.length, files: names.files.length })}</p>\n <Defaults meta={meta} edit={edit} />\n <Group title={t(\"readerManifest.anchors\")} add={t(\"readerManifest.addAnchor\")} disabled={!names.pages.length}\n onAdd={() => edit((m) => ({ ...m, anchors: [...(m.anchors ?? []), { id: nextId(m.anchors ?? []), page: names.pages[0]!, offset_percent: 0 }] }))}>\n {anchors.map((a, i) => (\n <AnchorRow key={i} index={i} anchor={a} pages={names.pages} onChange={(next) => edit((m) => ({ ...m, anchors: replace(m.anchors, i, next) }))}\n onRemove={() => edit((m) => ({ ...m, anchors: drop(m.anchors, i) }))} />\n ))}\n </Group>\n <Group title={t(\"readerManifest.foreground\")} add={t(\"readerManifest.addCue\")} disabled={!names.files.length || !names.pages.length}\n onAdd={() => edit((m) => ({ ...m, foreground: [...(m.foreground ?? []), { file: names.files[0]!, page: names.pages[0]! }] }))}\n extra={\n <Button type=\"button\" size=\"sm\" variant=\"outline\" disabled={!names.files.length} onClick={() => {\n const r = matchAudio(names, anchorIds);\n setMatched(r);\n if (r.foreground.length) edit((m) => ({ ...m, foreground: r.foreground }));\n }}>\n {t(\"readerManifest.match\")}\n </Button>\n }>\n {matched && <MatchReport match={matched} />}\n {(meta.foreground ?? []).map((c, i) => (\n <ForegroundRow key={i} index={i} cue={c} names={names} anchors={anchorIds} onChange={(next) => edit((m) => ({ ...m, foreground: replace(m.foreground, i, next) }))}\n onRemove={() => edit((m) => ({ ...m, foreground: drop(m.foreground, i) }))} />\n ))}\n </Group>\n <Group title={t(\"readerManifest.background\")} add={t(\"readerManifest.addTrack\")} disabled={!names.files.length}\n onAdd={() => edit((m) => ({ ...m, background: [...(m.background ?? []), { file: names.files[0]! }] }))}>\n {(meta.background ?? []).map((c, i) => (\n <BackgroundRow key={i} index={i} cue={c} names={names} anchors={anchorIds} onChange={(next) => edit((m) => ({ ...m, background: replace(m.background, i, next) }))}\n onRemove={() => edit((m) => ({ ...m, background: drop(m.background, i) }))} />\n ))}\n </Group>\n {problems.length > 0 && <Problems problems={problems} />}\n <ErrorLine error={save.error} />\n <div className=\"flex flex-wrap items-center gap-3\">\n <Button type=\"submit\" size=\"sm\" disabled={save.pending || !dirty || problems.length > 0}>\n {save.pending ? t(\"common.saving\") : t(\"common.save\")}\n </Button>\n {dirty && (\n <Button type=\"button\" size=\"sm\" variant=\"ghost\" onClick={() => {\n setDirty(false);\n setBasis(null);\n setMatched(null);\n }}>\n {t(\"readerManifest.revert\")}\n </Button>\n )}\n {saved && <span role=\"status\" className=\"text-muted-foreground\">{t(\"readerManifest.saved\")}</span>}\n </div>\n </form>\n );\n })();\n return (\n <ContentKitUiRoot appearance={appearance} className={cn(\"grid gap-3 text-sm\", className)} data-ckui=\"reader-manifest\">\n <h4 className=\"font-medium\">{t(\"readerManifest.title\")}</h4>\n {body}\n </ContentKitUiRoot>\n );\n}\n\nfunction nextId(anchors: readonly Anchor[]): string {\n const taken = new Set(anchors.map((a) => a.id));\n let n = anchors.length + 1;\n while (taken.has(`a${n}`)) n++;\n return `a${n}`;\n}\n\nconst replace = <T,>(list: T[] | undefined, i: number, next: T): T[] => (list ?? []).map((x, j) => (j === i ? next : x));\nconst drop = <T,>(list: T[] | undefined, i: number): T[] => (list ?? []).filter((_, j) => j !== i);\n\nfunction Group({ title, add, disabled, onAdd, extra, children }: { title: string; add: string; disabled: boolean; onAdd: () => void; extra?: ReactNode; children: ReactNode }) {\n return (\n <fieldset className=\"grid gap-2 rounded-md border border-border p-3\">\n <legend className=\"px-1 font-medium\">{title}</legend>\n {children}\n <div className=\"flex flex-wrap gap-2\">\n <Button type=\"button\" size=\"sm\" variant=\"outline\" disabled={disabled} onClick={onAdd}>\n {add}\n </Button>\n {extra}\n </div>\n </fieldset>\n );\n}\n\nfunction Defaults({ meta, edit }: { meta: ReaderMeta; edit: (fn: (m: ReaderMeta) => ReaderMeta) => void }) {\n const { t } = useMessages();\n const id = useId();\n const auto = meta.defaults?.auto_advance_seconds;\n return (\n <div className=\"grid max-w-xs gap-1.5\">\n <Label htmlFor={`${id}-auto`}>{t(\"readerManifest.autoAdvance\")}</Label>\n <Input id={`${id}-auto`} className=\"h-8\" type=\"number\" min={0} step=\"any\" value={shown(auto)}\n onChange={(e) => edit((m) => ({ ...m, defaults: e.target.value.trim() === \"\" ? undefined : { auto_advance_seconds: num(e.target.value) } }))} />\n </div>\n );\n}\n\nfunction NameSelect({ label, value, names, onChange }: { label: string; value: string; names: readonly string[]; onChange: (v: string) => void }) {\n return (\n <Select value={value} onValueChange={(v) => onChange(String(v))}>\n <SelectTrigger size=\"sm\" aria-label={label}>\n <SelectValue>{(v: string) => v}</SelectValue>\n </SelectTrigger>\n <SelectContent>\n {names.map((n) => (\n <SelectItem key={n} value={n}>\n {n}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n );\n}\n\nfunction PlaceSelect({ label, value, pages, anchors, none, onChange }: { label: string; value: string; pages: readonly string[]; anchors: readonly string[]; none?: string; onChange: (v: string) => void }) {\n const { t } = useMessages();\n const text = (v: string) => (v === NONE ? (none ?? \"\") : v.startsWith(\"anchor:\") ? t(\"readerManifest.anchorNamed\", { id: v.slice(7) }) : t(\"readerManifest.pageNamed\", { name: v.slice(5) }));\n return (\n <Select value={value} onValueChange={(v) => onChange(String(v))}>\n <SelectTrigger size=\"sm\" aria-label={label}>\n <SelectValue>{text}</SelectValue>\n </SelectTrigger>\n <SelectContent>\n {none !== undefined && <SelectItem value={NONE}>{none}</SelectItem>}\n {anchors.map((a) => (\n <SelectItem key={`a-${a}`} value={`anchor:${a}`}>\n {text(`anchor:${a}`)}\n </SelectItem>\n ))}\n {pages.map((p) => (\n <SelectItem key={`p-${p}`} value={`page:${p}`}>\n {text(`page:${p}`)}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n );\n}\n\nfunction Remove({ label, onRemove }: { label: string; onRemove: () => void }) {\n const { t } = useMessages();\n return (\n <Button type=\"button\" size=\"sm\" variant=\"ghost\" aria-label={label} onClick={onRemove}>\n {t(\"common.remove\")}\n </Button>\n );\n}\n\nfunction AnchorRow({ index, anchor: a, pages, onChange, onRemove }: { index: number; anchor: Anchor; pages: readonly string[]; onChange: (a: Anchor) => void; onRemove: () => void }) {\n const { t } = useMessages();\n const n = index + 1;\n return (\n <div className=\"flex flex-wrap items-center gap-2\" data-ckui=\"reader-anchor\">\n <Input className=\"h-8 w-28\" aria-label={t(\"readerManifest.anchorId\", { n })} value={a.id} onChange={(e) => onChange({ ...a, id: e.target.value })} />\n <NameSelect label={t(\"readerManifest.anchorPage\", { n })} value={a.page} names={pages} onChange={(page) => onChange({ ...a, page })} />\n <Input className=\"h-8 w-24\" type=\"number\" min={0} max={100} step=\"any\" aria-label={t(\"readerManifest.offset\", { n })} value={shown(a.offset_percent)}\n onChange={(e) => onChange({ ...a, offset_percent: num(e.target.value) })} />\n <Input className=\"h-8 w-28\" type=\"number\" min={0} step=\"any\" aria-label={t(\"readerManifest.duration\", { n })} placeholder={t(\"readerManifest.durationPlaceholder\")}\n value={shown(a.duration_seconds)} onChange={(e) => onChange({ ...a, duration_seconds: e.target.value.trim() === \"\" ? undefined : num(e.target.value) })} />\n <Remove label={t(\"readerManifest.removeAnchor\", { n })} onRemove={onRemove} />\n </div>\n );\n}\n\nfunction ForegroundRow({ index, cue: c, names, anchors, onChange, onRemove }: { index: number; cue: ForegroundCue; names: ReaderNames; anchors: readonly string[]; onChange: (c: ForegroundCue) => void; onRemove: () => void }) {\n const { t } = useMessages();\n const n = index + 1;\n return (\n <div className=\"flex flex-wrap items-center gap-2\" data-ckui=\"reader-foreground\">\n <NameSelect label={t(\"readerManifest.cueFile\", { n })} value={c.file} names={names.files} onChange={(file) => onChange({ ...c, file })} />\n <PlaceSelect label={t(\"readerManifest.cueAt\", { n })} value={placeOf(c.page, c.anchor)} pages={names.pages} anchors={anchors} onChange={(v) => onChange({ file: c.file, ...fromPlace(v) })} />\n <Remove label={t(\"readerManifest.removeCue\", { n })} onRemove={onRemove} />\n </div>\n );\n}\n\nfunction BackgroundRow({ index, cue: c, names, anchors, onChange, onRemove }: { index: number; cue: BackgroundCue; names: ReaderNames; anchors: readonly string[]; onChange: (c: BackgroundCue) => void; onRemove: () => void }) {\n const { t } = useMessages();\n const n = index + 1;\n const from = fromPlace(placeOf(c.from_page, c.from_anchor));\n const to = fromPlace(placeOf(c.to_page, c.to_anchor));\n const set = (f: typeof from, tt: typeof to) => onChange({ file: c.file, loop: c.loop, layer: c.layer, from_page: f.page, from_anchor: f.anchor, to_page: tt.page, to_anchor: tt.anchor });\n return (\n <div className=\"flex flex-wrap items-center gap-2\" data-ckui=\"reader-background\">\n <NameSelect label={t(\"readerManifest.trackFile\", { n })} value={c.file} names={names.files} onChange={(file) => onChange({ ...c, file })} />\n <PlaceSelect label={t(\"readerManifest.trackFrom\", { n })} none={t(\"readerManifest.start\")} value={placeOf(c.from_page, c.from_anchor)} pages={names.pages} anchors={anchors}\n onChange={(v) => set(fromPlace(v), to)} />\n <PlaceSelect label={t(\"readerManifest.trackTo\", { n })} none={t(\"readerManifest.end\")} value={placeOf(c.to_page, c.to_anchor)} pages={names.pages} anchors={anchors}\n onChange={(v) => set(from, fromPlace(v))} />\n <label className=\"flex items-center gap-1.5\">\n <Switch size=\"sm\" checked={!!c.loop} onCheckedChange={(on) => onChange({ ...c, loop: on || undefined })} aria-label={t(\"readerManifest.loopN\", { n })} />\n {t(\"readerManifest.loop\")}\n </label>\n <Input className=\"h-8 w-28\" aria-label={t(\"readerManifest.layer\", { n })} placeholder={t(\"readerManifest.layerPlaceholder\")} value={c.layer ?? \"\"}\n onChange={(e) => onChange({ ...c, layer: e.target.value || undefined })} />\n <Remove label={t(\"readerManifest.removeTrack\", { n })} onRemove={onRemove} />\n </div>\n );\n}\n\nfunction MatchReport({ match }: { match: AudioMatch }) {\n const { t } = useMessages();\n return (\n <div className=\"grid gap-1 rounded-md bg-muted p-2 text-xs\" role=\"status\">\n <p>{match.foreground.length ? t(\"readerManifest.matched\", { count: match.foreground.length }) : t(\"readerManifest.matchedNone\")}</p>\n {match.unmatchedPages.length > 0 && <p>{t(\"readerManifest.pagesWithoutAudio\", { names: match.unmatchedPages.join(\", \") })}</p>}\n {match.unmatchedFiles.length > 0 && <p>{t(\"readerManifest.audioWithoutPlace\", { names: match.unmatchedFiles.join(\", \") })}</p>}\n </div>\n );\n}\n\nfunction Problems({ problems }: { problems: ReaderMetaProblem[] }) {\n const { t } = useMessages();\n const where = (p: ReaderMetaProblem) => t(`readerManifest.at_${p.at}`, { n: p.index + 1 });\n return (\n <ul className=\"grid gap-0.5 text-destructive\" role=\"alert\" data-ckui=\"reader-problems\">\n {problems.map((p, i) => (\n <li key={i}>{t(`readerManifest.problem_${p.problem}`, { where: where(p) })}</li>\n ))}\n </ul>\n );\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"reader-manifest.js","names":[],"sources":["../../../src/components/admin/reader-manifest.tsx"],"sourcesContent":["import { cn } from \"cn\";\nimport { useId, useMemo, useRef, useState, type ReactNode } from \"react\";\nimport type { ContentKitUiAppearance } from \"../../appearance.js\";\nimport type { ContentKitClient } from \"../../client/client.js\";\nimport type { Anchor, BackgroundCue, ForegroundCue, ReaderMeta, ReaderPlan } from \"../../client/generated/wire.js\";\nimport { emptyReaderMeta, matchAudio, readerMetaProblems, readerNames, type AudioMatch, type ReaderMetaProblem, type ReaderNames } from \"../../client/reader-meta.js\";\nimport { useMessages } from \"../../i18n/context.js\";\nimport { useContentKitClient, type ContentKitErrorHandler } from \"../../react/context.js\";\nimport { useReaderPlan } from \"../../react/versions.js\";\nimport { ContentKitUiRoot } from \"../../scope.js\";\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 { ErrorLine, useAction } from \"../social/parts.js\";\nimport { useEditorSaveTask } from \"../content/editor-save.js\";\nimport { LoadFailed, Rows } from \"./shell.js\";\n\nexport interface ReaderManifestEditorProps {\n content: string;\n version: string;\n client?: ContentKitClient;\n onError?: ContentKitErrorHandler;\n className?: string;\n appearance?: ContentKitUiAppearance;\n}\n\nconst NONE = \"__none__\";\n\n/** A page or an anchor as one select value. */\nconst placeOf = (page?: string, anchor?: string) => (anchor !== undefined ? `anchor:${anchor}` : page !== undefined ? `page:${page}` : NONE);\nconst fromPlace = (v: string): { page?: string; anchor?: string } =>\n v.startsWith(\"anchor:\") ? { anchor: v.slice(7) } : v.startsWith(\"page:\") ? { page: v.slice(5) } : {};\n\n/** Only what the server stores: no empty layers, defaults or lists. */\nfunction clean(meta: ReaderMeta): ReaderMeta {\n const auto = meta.defaults?.auto_advance_seconds;\n return {\n schema_version: 1,\n ...(auto !== undefined ? { defaults: { auto_advance_seconds: auto } } : {}),\n anchors: (meta.anchors ?? []).map((a) => ({ id: a.id.trim(), page: a.page, offset_percent: a.offset_percent, ...(a.duration_seconds !== undefined ? { duration_seconds: a.duration_seconds } : {}) })),\n background: (meta.background ?? []).map((c) => {\n const layer = c.layer?.trim();\n return { ...c, ...(layer ? { layer } : { layer: undefined }) };\n }),\n foreground: meta.foreground ?? [],\n };\n}\n\nconst num = (v: string): number => (v.trim() === \"\" ? Number.NaN : Number(v));\nconst shown = (n: number | undefined) => (n === undefined || Number.isNaN(n) ? \"\" : String(n));\n\n/**\n * Editors: a reader version's manifest over its published pages and audio:\n * scroll anchors, foreground cues (one track at a page or anchor, matched\n * from file names in one step), background tracks over a range, and the\n * auto-advance default. Page order is the version's media order.\n */\nexport function ReaderManifestEditor({ content, version, client: own, onError, className, appearance }: ReaderManifestEditorProps) {\n const { t } = useMessages();\n const client = useContentKitClient(own);\n const plan = useReaderPlan(content, version, { client });\n const names = useMemo<ReaderNames>(() => (plan.plan ? readerNames(plan.plan) : { pages: [], files: [] }), [plan.plan]);\n const [basis, setBasis] = useState<ReaderPlan | null>(null);\n const [meta, setMeta] = useState<ReaderMeta | null>(null);\n const [dirty, setDirty] = useState(false);\n const [saved, setSaved] = useState(false);\n const [matched, setMatched] = useState<AudioMatch | null>(null);\n const save = useAction(\"reader.save\", onError);\n // A fresh plan replaces the draft unless it has unsaved edits.\n if (plan.plan && plan.plan !== basis && !dirty) {\n setBasis(plan.plan);\n setMeta(plan.plan.reader ? structuredClone(plan.plan.reader) : emptyReaderMeta());\n }\n const problems = useMemo(() => (meta ? readerMetaProblems(meta, names) : []), [meta, names]);\n const edit = (fn: (m: ReaderMeta) => ReaderMeta) => {\n setMeta((m) => (m ? fn(m) : m));\n setDirty(true);\n setSaved(false);\n };\n const latest=useRef(meta);latest.current=meta;\n const submit=async()=>{\n if(!meta||problems.length)return false;\n setSaved(false);const snapshot=meta;\n const ok=await save.run(async()=>{await client.versions.setReader(content,version,clean(snapshot));return true;});\n if(!ok||latest.current!==snapshot)return false;\n setDirty(false);setSaved(true);return true;\n };\n useEditorSaveTask(`reader-meta:${version}`,{label:t(\"readerManifest.title\"),dirty,pending:save.pending,valid:!problems.length,save:submit,order:30});\n const body = (() => {\n if (plan.loading && !plan.plan && !plan.pending) return <Rows count={2} />;\n if (plan.pending) return <p className=\"text-muted-foreground\">{t(\"readerManifest.pending\")}</p>;\n if (plan.error && !plan.plan) return <LoadFailed error={plan.error} message={t(\"readerManifest.loadFailed\")} retry={plan.reload} />;\n if (!meta) return null;\n const anchors = meta.anchors ?? [];\n const anchorIds = anchors.map((a) => a.id).filter(Boolean);\n return (\n <form className=\"grid gap-4\" onSubmit={(event)=>{event.preventDefault();void submit();}}>\n <p className=\"text-muted-foreground\">{t(\"readerManifest.summary\", { pages: names.pages.length, files: names.files.length })}</p>\n <Defaults meta={meta} edit={edit} />\n <Group title={t(\"readerManifest.anchors\")} add={t(\"readerManifest.addAnchor\")} disabled={!names.pages.length}\n onAdd={() => edit((m) => ({ ...m, anchors: [...(m.anchors ?? []), { id: nextId(m.anchors ?? []), page: names.pages[0]!, offset_percent: 0 }] }))}>\n {anchors.map((a, i) => (\n <AnchorRow key={i} index={i} anchor={a} pages={names.pages} onChange={(next) => edit((m) => ({ ...m, anchors: replace(m.anchors, i, next) }))}\n onRemove={() => edit((m) => ({ ...m, anchors: drop(m.anchors, i) }))} />\n ))}\n </Group>\n <Group title={t(\"readerManifest.foreground\")} add={t(\"readerManifest.addCue\")} disabled={!names.files.length || !names.pages.length}\n onAdd={() => edit((m) => ({ ...m, foreground: [...(m.foreground ?? []), { file: names.files[0]!, page: names.pages[0]! }] }))}\n extra={\n <Button type=\"button\" size=\"sm\" variant=\"outline\" disabled={!names.files.length} onClick={() => {\n const r = matchAudio(names, anchorIds);\n setMatched(r);\n if (r.foreground.length) edit((m) => ({ ...m, foreground: r.foreground }));\n }}>\n {t(\"readerManifest.match\")}\n </Button>\n }>\n {matched && <MatchReport match={matched} />}\n {(meta.foreground ?? []).map((c, i) => (\n <ForegroundRow key={i} index={i} cue={c} names={names} anchors={anchorIds} onChange={(next) => edit((m) => ({ ...m, foreground: replace(m.foreground, i, next) }))}\n onRemove={() => edit((m) => ({ ...m, foreground: drop(m.foreground, i) }))} />\n ))}\n </Group>\n <Group title={t(\"readerManifest.background\")} add={t(\"readerManifest.addTrack\")} disabled={!names.files.length}\n onAdd={() => edit((m) => ({ ...m, background: [...(m.background ?? []), { file: names.files[0]! }] }))}>\n {(meta.background ?? []).map((c, i) => (\n <BackgroundRow key={i} index={i} cue={c} names={names} anchors={anchorIds} onChange={(next) => edit((m) => ({ ...m, background: replace(m.background, i, next) }))}\n onRemove={() => edit((m) => ({ ...m, background: drop(m.background, i) }))} />\n ))}\n </Group>\n {problems.length > 0 && <Problems problems={problems} />}\n <ErrorLine error={save.error} />\n <div className=\"flex flex-wrap items-center gap-3\">\n <Button type=\"submit\" size=\"sm\" disabled={save.pending || !dirty || problems.length > 0}>\n {save.pending ? t(\"common.saving\") : t(\"common.save\")}\n </Button>\n {dirty && (\n <Button type=\"button\" size=\"sm\" variant=\"ghost\" onClick={() => {\n setDirty(false);\n setBasis(null);\n setMatched(null);\n }}>\n {t(\"readerManifest.revert\")}\n </Button>\n )}\n {saved && <span role=\"status\" className=\"text-muted-foreground\">{t(\"readerManifest.saved\")}</span>}\n </div>\n </form>\n );\n })();\n return (\n <ContentKitUiRoot appearance={appearance} className={cn(\"grid gap-3 text-sm\", className)} data-ckui=\"reader-manifest\">\n <h4 className=\"font-medium\">{t(\"readerManifest.title\")}</h4>\n {body}\n </ContentKitUiRoot>\n );\n}\n\nfunction nextId(anchors: readonly Anchor[]): string {\n const taken = new Set(anchors.map((a) => a.id));\n let n = anchors.length + 1;\n while (taken.has(`a${n}`)) n++;\n return `a${n}`;\n}\n\nconst replace = <T,>(list: T[] | undefined, i: number, next: T): T[] => (list ?? []).map((x, j) => (j === i ? next : x));\nconst drop = <T,>(list: T[] | undefined, i: number): T[] => (list ?? []).filter((_, j) => j !== i);\n\nfunction Group({ title, add, disabled, onAdd, extra, children }: { title: string; add: string; disabled: boolean; onAdd: () => void; extra?: ReactNode; children: ReactNode }) {\n return (\n <fieldset className=\"grid gap-2 rounded-md border border-border p-3\">\n <legend className=\"px-1 font-medium\">{title}</legend>\n {children}\n <div className=\"flex flex-wrap gap-2\">\n <Button type=\"button\" size=\"sm\" variant=\"outline\" disabled={disabled} onClick={onAdd}>\n {add}\n </Button>\n {extra}\n </div>\n </fieldset>\n );\n}\n\nfunction Defaults({ meta, edit }: { meta: ReaderMeta; edit: (fn: (m: ReaderMeta) => ReaderMeta) => void }) {\n const { t } = useMessages();\n const id = useId();\n const auto = meta.defaults?.auto_advance_seconds;\n return (\n <div className=\"grid max-w-xs gap-1.5\">\n <Label htmlFor={`${id}-auto`}>{t(\"readerManifest.autoAdvance\")}</Label>\n <Input id={`${id}-auto`} className=\"h-8\" type=\"number\" min={0} step=\"any\" value={shown(auto)}\n onChange={(e) => edit((m) => ({ ...m, defaults: e.target.value.trim() === \"\" ? undefined : { auto_advance_seconds: num(e.target.value) } }))} />\n </div>\n );\n}\n\nfunction NameSelect({ label, value, names, onChange }: { label: string; value: string; names: readonly string[]; onChange: (v: string) => void }) {\n return (\n <Select value={value} onValueChange={(v) => onChange(String(v))}>\n <SelectTrigger size=\"sm\" aria-label={label}>\n <SelectValue>{(v: string) => v}</SelectValue>\n </SelectTrigger>\n <SelectContent>\n {names.map((n) => (\n <SelectItem key={n} value={n}>\n {n}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n );\n}\n\nfunction PlaceSelect({ label, value, pages, anchors, none, onChange }: { label: string; value: string; pages: readonly string[]; anchors: readonly string[]; none?: string; onChange: (v: string) => void }) {\n const { t } = useMessages();\n const text = (v: string) => (v === NONE ? (none ?? \"\") : v.startsWith(\"anchor:\") ? t(\"readerManifest.anchorNamed\", { id: v.slice(7) }) : t(\"readerManifest.pageNamed\", { name: v.slice(5) }));\n return (\n <Select value={value} onValueChange={(v) => onChange(String(v))}>\n <SelectTrigger size=\"sm\" aria-label={label}>\n <SelectValue>{text}</SelectValue>\n </SelectTrigger>\n <SelectContent>\n {none !== undefined && <SelectItem value={NONE}>{none}</SelectItem>}\n {anchors.map((a) => (\n <SelectItem key={`a-${a}`} value={`anchor:${a}`}>\n {text(`anchor:${a}`)}\n </SelectItem>\n ))}\n {pages.map((p) => (\n <SelectItem key={`p-${p}`} value={`page:${p}`}>\n {text(`page:${p}`)}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n );\n}\n\nfunction Remove({ label, onRemove }: { label: string; onRemove: () => void }) {\n const { t } = useMessages();\n return (\n <Button type=\"button\" size=\"sm\" variant=\"ghost\" aria-label={label} onClick={onRemove}>\n {t(\"common.remove\")}\n </Button>\n );\n}\n\nfunction AnchorRow({ index, anchor: a, pages, onChange, onRemove }: { index: number; anchor: Anchor; pages: readonly string[]; onChange: (a: Anchor) => void; onRemove: () => void }) {\n const { t } = useMessages();\n const n = index + 1;\n return (\n <div className=\"flex flex-wrap items-center gap-2\" data-ckui=\"reader-anchor\">\n <Input className=\"h-8 w-28\" aria-label={t(\"readerManifest.anchorId\", { n })} value={a.id} onChange={(e) => onChange({ ...a, id: e.target.value })} />\n <NameSelect label={t(\"readerManifest.anchorPage\", { n })} value={a.page} names={pages} onChange={(page) => onChange({ ...a, page })} />\n <Input className=\"h-8 w-24\" type=\"number\" min={0} max={100} step=\"any\" aria-label={t(\"readerManifest.offset\", { n })} value={shown(a.offset_percent)}\n onChange={(e) => onChange({ ...a, offset_percent: num(e.target.value) })} />\n <Input className=\"h-8 w-28\" type=\"number\" min={0} step=\"any\" aria-label={t(\"readerManifest.duration\", { n })} placeholder={t(\"readerManifest.durationPlaceholder\")}\n value={shown(a.duration_seconds)} onChange={(e) => onChange({ ...a, duration_seconds: e.target.value.trim() === \"\" ? undefined : num(e.target.value) })} />\n <Remove label={t(\"readerManifest.removeAnchor\", { n })} onRemove={onRemove} />\n </div>\n );\n}\n\nfunction ForegroundRow({ index, cue: c, names, anchors, onChange, onRemove }: { index: number; cue: ForegroundCue; names: ReaderNames; anchors: readonly string[]; onChange: (c: ForegroundCue) => void; onRemove: () => void }) {\n const { t } = useMessages();\n const n = index + 1;\n return (\n <div className=\"flex flex-wrap items-center gap-2\" data-ckui=\"reader-foreground\">\n <NameSelect label={t(\"readerManifest.cueFile\", { n })} value={c.file} names={names.files} onChange={(file) => onChange({ ...c, file })} />\n <PlaceSelect label={t(\"readerManifest.cueAt\", { n })} value={placeOf(c.page, c.anchor)} pages={names.pages} anchors={anchors} onChange={(v) => onChange({ file: c.file, ...fromPlace(v) })} />\n <Remove label={t(\"readerManifest.removeCue\", { n })} onRemove={onRemove} />\n </div>\n );\n}\n\nfunction BackgroundRow({ index, cue: c, names, anchors, onChange, onRemove }: { index: number; cue: BackgroundCue; names: ReaderNames; anchors: readonly string[]; onChange: (c: BackgroundCue) => void; onRemove: () => void }) {\n const { t } = useMessages();\n const n = index + 1;\n const from = fromPlace(placeOf(c.from_page, c.from_anchor));\n const to = fromPlace(placeOf(c.to_page, c.to_anchor));\n const set = (f: typeof from, tt: typeof to) => onChange({ file: c.file, loop: c.loop, layer: c.layer, from_page: f.page, from_anchor: f.anchor, to_page: tt.page, to_anchor: tt.anchor });\n return (\n <div className=\"flex flex-wrap items-center gap-2\" data-ckui=\"reader-background\">\n <NameSelect label={t(\"readerManifest.trackFile\", { n })} value={c.file} names={names.files} onChange={(file) => onChange({ ...c, file })} />\n <PlaceSelect label={t(\"readerManifest.trackFrom\", { n })} none={t(\"readerManifest.start\")} value={placeOf(c.from_page, c.from_anchor)} pages={names.pages} anchors={anchors}\n onChange={(v) => set(fromPlace(v), to)} />\n <PlaceSelect label={t(\"readerManifest.trackTo\", { n })} none={t(\"readerManifest.end\")} value={placeOf(c.to_page, c.to_anchor)} pages={names.pages} anchors={anchors}\n onChange={(v) => set(from, fromPlace(v))} />\n <label className=\"flex items-center gap-1.5\">\n <Switch size=\"sm\" checked={!!c.loop} onCheckedChange={(on) => onChange({ ...c, loop: on || undefined })} aria-label={t(\"readerManifest.loopN\", { n })} />\n {t(\"readerManifest.loop\")}\n </label>\n <Input className=\"h-8 w-28\" aria-label={t(\"readerManifest.layer\", { n })} placeholder={t(\"readerManifest.layerPlaceholder\")} value={c.layer ?? \"\"}\n onChange={(e) => onChange({ ...c, layer: e.target.value || undefined })} />\n <Remove label={t(\"readerManifest.removeTrack\", { n })} onRemove={onRemove} />\n </div>\n );\n}\n\nfunction MatchReport({ match }: { match: AudioMatch }) {\n const { t } = useMessages();\n return (\n <div className=\"grid gap-1 rounded-md bg-muted p-2 text-xs\" role=\"status\">\n <p>{match.foreground.length ? t(\"readerManifest.matched\", { count: match.foreground.length }) : t(\"readerManifest.matchedNone\")}</p>\n {match.unmatchedPages.length > 0 && <p>{t(\"readerManifest.pagesWithoutAudio\", { names: match.unmatchedPages.join(\", \") })}</p>}\n {match.unmatchedFiles.length > 0 && <p>{t(\"readerManifest.audioWithoutPlace\", { names: match.unmatchedFiles.join(\", \") })}</p>}\n </div>\n );\n}\n\nfunction Problems({ problems }: { problems: ReaderMetaProblem[] }) {\n const { t } = useMessages();\n const where = (p: ReaderMetaProblem) => t(`readerManifest.at_${p.at}`, { n: p.index + 1 });\n return (\n <ul className=\"grid gap-0.5 text-destructive\" role=\"alert\" data-ckui=\"reader-problems\">\n {problems.map((p, i) => (\n <li key={i}>{t(`readerManifest.problem_${p.problem}`, { where: where(p) })}</li>\n ))}\n </ul>\n );\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { RefObject } from 'react';
|
|
2
|
+
import { ContentKitClient } from '../../client/client.js';
|
|
3
|
+
import { RefBody } from '../../client/generated/wire.js';
|
|
4
|
+
interface EditorTask {
|
|
5
|
+
label: string;
|
|
6
|
+
dirty: boolean;
|
|
7
|
+
pending: boolean;
|
|
8
|
+
valid: boolean;
|
|
9
|
+
save: () => Promise<boolean>;
|
|
10
|
+
order?: number;
|
|
11
|
+
}
|
|
12
|
+
interface EditorTasks {
|
|
13
|
+
register: (id: string, task: RefObject<EditorTask>) => () => void;
|
|
14
|
+
changed: () => void;
|
|
15
|
+
}
|
|
16
|
+
/** Optional coordination for an editor's existing independently usable tools. */
|
|
17
|
+
export declare const EditorSaveContext: import('react').Context<EditorTasks | null>;
|
|
18
|
+
export declare function useEditorSaveTask(id: string, task: EditorTask): void;
|
|
19
|
+
/** Save only dirty tools, before publication; a refused save never publishes. */
|
|
20
|
+
export declare function useEditorSaveCoordinator(): {
|
|
21
|
+
context: {
|
|
22
|
+
register: (id: string, task: RefObject<EditorTask>) => () => void;
|
|
23
|
+
changed: () => void;
|
|
24
|
+
};
|
|
25
|
+
problem: () => string | undefined;
|
|
26
|
+
save: (current: () => boolean) => Promise<string | undefined>;
|
|
27
|
+
pending: boolean;
|
|
28
|
+
dirty: boolean;
|
|
29
|
+
};
|
|
30
|
+
/** Check every metadata window, not only the first page of a long gallery. */
|
|
31
|
+
export declare function readerMediaReady(client: ContentKitClient, ref: RefBody): Promise<boolean>;
|
|
32
|
+
export {};
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { isProcessing as e } from "../../client/media/windows.js";
|
|
2
|
+
import { createContext as t, useCallback as n, useContext as r, useLayoutEffect as i, useRef as a, useState as o } from "react";
|
|
3
|
+
//#region src/components/content/editor-save.tsx
|
|
4
|
+
var s = t(null);
|
|
5
|
+
function c(e, t) {
|
|
6
|
+
let n = r(s), o = n?.register, c = n?.changed, l = a(t);
|
|
7
|
+
l.current = t, i(() => o?.(e, l), [o, e]), i(() => c?.(), [
|
|
8
|
+
c,
|
|
9
|
+
t.dirty,
|
|
10
|
+
t.pending,
|
|
11
|
+
t.valid
|
|
12
|
+
]);
|
|
13
|
+
}
|
|
14
|
+
function l() {
|
|
15
|
+
let e = a(/* @__PURE__ */ new Map()), [, t] = o(0), r = n(() => t((e) => e + 1), []), i = n((t, n) => (e.current.set(t, n), r(), () => {
|
|
16
|
+
e.current.delete(t), r();
|
|
17
|
+
}), [r]), s = () => [...e.current.values()].map((e) => e.current).find((e) => e.pending || e.dirty && !e.valid)?.label;
|
|
18
|
+
return {
|
|
19
|
+
context: {
|
|
20
|
+
register: i,
|
|
21
|
+
changed: r
|
|
22
|
+
},
|
|
23
|
+
problem: s,
|
|
24
|
+
save: async (t) => {
|
|
25
|
+
let n = s();
|
|
26
|
+
if (n) return n;
|
|
27
|
+
let r = [...e.current.values()].sort((e, t) => (e.current.order ?? 0) - (t.current.order ?? 0));
|
|
28
|
+
for (let e of r) if (!t() || e.current.dirty && !await e.current.save()) return e.current.label;
|
|
29
|
+
},
|
|
30
|
+
pending: [...e.current.values()].some((e) => e.current.pending),
|
|
31
|
+
dirty: [...e.current.values()].some((e) => e.current.dirty)
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
async function u(t, n) {
|
|
35
|
+
if (!n.version || !(await t.versions.pages(n.id, n.version)).selected) return !1;
|
|
36
|
+
let r = 0, i;
|
|
37
|
+
do {
|
|
38
|
+
let a = await t.media.read(n, {
|
|
39
|
+
editor: !0,
|
|
40
|
+
offset: r,
|
|
41
|
+
limit: 200
|
|
42
|
+
});
|
|
43
|
+
if (a.files.some((t) => !!t.failed || e(t))) return !1;
|
|
44
|
+
i = a.total, r += a.limit || 200;
|
|
45
|
+
} while (r < i);
|
|
46
|
+
return i > 0;
|
|
47
|
+
}
|
|
48
|
+
//#endregion
|
|
49
|
+
export { s as EditorSaveContext, u as readerMediaReady, l as useEditorSaveCoordinator, c as useEditorSaveTask };
|
|
50
|
+
|
|
51
|
+
//# sourceMappingURL=editor-save.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"editor-save.js","names":[],"sources":["../../../src/components/content/editor-save.tsx"],"sourcesContent":["import { createContext, useCallback, useContext, useLayoutEffect, useRef, useState, type RefObject } from \"react\";\nimport type { ContentKitClient } from \"../../client/client.js\";\nimport type { RefBody } from \"../../client/generated/wire.js\";\nimport { isProcessing } from \"../../client/media/windows.js\";\n\ninterface EditorTask {\n label: string;\n dirty: boolean;\n pending: boolean;\n valid: boolean;\n save: () => Promise<boolean>;\n order?: number;\n}\n\ninterface EditorTasks {\n register: (id: string, task: RefObject<EditorTask>) => () => void;\n changed: () => void;\n}\n\n/** Optional coordination for an editor's existing independently usable tools. */\nexport const EditorSaveContext = createContext<EditorTasks | null>(null);\n\nexport function useEditorSaveTask(id: string, task: EditorTask) {\n const context = useContext(EditorSaveContext);\n const register = context?.register;\n const changed = context?.changed;\n const current = useRef(task);\n current.current = task;\n useLayoutEffect(() => register?.(id, current), [register, id]);\n useLayoutEffect(() => changed?.(), [changed, task.dirty, task.pending, task.valid]);\n}\n\n/** Save only dirty tools, before publication; a refused save never publishes. */\nexport function useEditorSaveCoordinator() {\n const tasks = useRef(new Map<string, RefObject<EditorTask>>());\n const [, refresh] = useState(0);\n const changed = useCallback(() => refresh((value) => value + 1), []);\n const register = useCallback(\n (id: string, task: RefObject<EditorTask>) => {\n tasks.current.set(id, task);\n changed();\n return () => {\n tasks.current.delete(id);\n changed();\n };\n },\n [changed],\n );\n const problem = () => [...tasks.current.values()].map((r) => r.current).find((t) => t.pending || (t.dirty && !t.valid))?.label;\n const save = async (current: () => boolean) => {\n const invalid = problem();\n if (invalid) return invalid;\n const ordered = [...tasks.current.values()].sort((a, b) => (a.current.order ?? 0) - (b.current.order ?? 0));\n for (const ref of ordered) {\n if (!current()) return ref.current.label;\n if (ref.current.dirty && !(await ref.current.save())) return ref.current.label;\n }\n return undefined;\n };\n return {\n context: { register, changed },\n problem,\n save,\n pending: [...tasks.current.values()].some((t) => t.current.pending),\n dirty: [...tasks.current.values()].some((t) => t.current.dirty),\n };\n}\n\n/** Check every metadata window, not only the first page of a long gallery. */\nexport async function readerMediaReady(client: ContentKitClient, ref: RefBody): Promise<boolean> {\n if (!ref.version) return false;\n const pages = await client.versions.pages(ref.id, ref.version);\n if (!pages.selected) return false;\n let offset = 0;\n let total: number;\n do {\n const read = await client.media.read(ref, { editor: true, offset, limit: 200 });\n if (read.files.some((file) => !!file.failed || isProcessing(file))) return false;\n total = read.total;\n offset += read.limit || 200;\n } while (offset < total);\n return total > 0;\n}\n"],"mappings":";;;AAoBA,IAAa,IAAoB,EAAkC,IAAI;AAEvE,SAAgB,EAAkB,GAAY,GAAkB;CAC9D,IAAM,IAAU,EAAW,CAAiB,GACtC,IAAW,GAAS,UACpB,IAAU,GAAS,SACnB,IAAU,EAAO,CAAI;CAG3B,AAFA,EAAQ,UAAU,GAClB,QAAsB,IAAW,GAAI,CAAO,GAAG,CAAC,GAAU,CAAE,CAAC,GAC7D,QAAsB,IAAU,GAAG;EAAC;EAAS,EAAK;EAAO,EAAK;EAAS,EAAK;CAAK,CAAC;AACpF;AAGA,SAAgB,IAA2B;CACzC,IAAM,IAAQ,kBAAO,IAAI,IAAmC,CAAC,GACvD,GAAG,KAAW,EAAS,CAAC,GACxB,IAAU,QAAkB,GAAS,MAAU,IAAQ,CAAC,GAAG,CAAC,CAAC,GAC7D,IAAW,GACd,GAAY,OACX,EAAM,QAAQ,IAAI,GAAI,CAAI,GAC1B,EAAQ,SACK;EAEX,AADA,EAAM,QAAQ,OAAO,CAAE,GACvB,EAAQ;CACV,IAEF,CAAC,CAAO,CACV,GACM,UAAgB,CAAC,GAAG,EAAM,QAAQ,OAAO,CAAC,CAAC,CAAC,KAAK,MAAM,EAAE,OAAO,CAAC,CAAC,MAAM,MAAM,EAAE,WAAY,EAAE,SAAS,CAAC,EAAE,KAAM,CAAC,EAAE;CAWzH,OAAO;EACL,SAAS;GAAE;GAAU;EAAQ;EAC7B;EACA,aAbkB,MAA2B;GAC7C,IAAM,IAAU,EAAQ;GACxB,IAAI,GAAS,OAAO;GACpB,IAAM,IAAU,CAAC,GAAG,EAAM,QAAQ,OAAO,CAAC,CAAC,CAAC,MAAM,GAAG,OAAO,EAAE,QAAQ,SAAS,MAAM,EAAE,QAAQ,SAAS,EAAE;GAC1G,KAAK,IAAM,KAAO,GAEhB,IADI,CAAC,EAAQ,KACT,EAAI,QAAQ,SAAS,CAAE,MAAM,EAAI,QAAQ,KAAK,GAAI,OAAO,EAAI,QAAQ;EAG7E;EAKE,SAAS,CAAC,GAAG,EAAM,QAAQ,OAAO,CAAC,CAAC,CAAC,MAAM,MAAM,EAAE,QAAQ,OAAO;EAClE,OAAO,CAAC,GAAG,EAAM,QAAQ,OAAO,CAAC,CAAC,CAAC,MAAM,MAAM,EAAE,QAAQ,KAAK;CAChE;AACF;AAGA,eAAsB,EAAiB,GAA0B,GAAgC;CAG/F,IAFI,CAAC,EAAI,WAEL,EAAC,MADe,EAAO,SAAS,MAAM,EAAI,IAAI,EAAI,OAAO,EAAA,CAClD,UAAU,OAAO;CAC5B,IAAI,IAAS,GACT;CACJ,GAAG;EACD,IAAM,IAAO,MAAM,EAAO,MAAM,KAAK,GAAK;GAAE,QAAQ;GAAM;GAAQ,OAAO;EAAI,CAAC;EAC9E,IAAI,EAAK,MAAM,MAAM,MAAS,CAAC,CAAC,EAAK,UAAU,EAAa,CAAI,CAAC,GAAG,OAAO;EAE3E,AADA,IAAQ,EAAK,OACb,KAAU,EAAK,SAAS;CAC1B,SAAS,IAAS;CAClB,OAAO,IAAQ;AACjB"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { ContentKitClient } from '../../client/client.js';
|
|
2
|
-
import { Content, Version } from '../../client/generated/wire.js';
|
|
2
|
+
import { Content, ContentModel, Rule, Version } from '../../client/generated/wire.js';
|
|
3
3
|
import { ContentKitErrorHandler } from '../../react/context.js';
|
|
4
4
|
import { Labels } from '../groups/parts.js';
|
|
5
5
|
interface Common {
|
|
@@ -11,6 +11,20 @@ interface Common {
|
|
|
11
11
|
export declare function ContentDetailsEditor(p: Common & {
|
|
12
12
|
content: Content;
|
|
13
13
|
}): import('react').JSX.Element;
|
|
14
|
+
/** A rule's form: level, tiers, group (the content's owner group by default), the preview its kind has and when it turns free. */
|
|
15
|
+
export declare function RuleFields({ value, onChange, model, kind, owner, labels, client }: {
|
|
16
|
+
value: Rule;
|
|
17
|
+
onChange: (r: Rule) => void;
|
|
18
|
+
model: ContentModel | null;
|
|
19
|
+
kind: string;
|
|
20
|
+
owner?: string;
|
|
21
|
+
labels?: Labels;
|
|
22
|
+
client: ContentKitClient;
|
|
23
|
+
}): import('react').JSX.Element;
|
|
24
|
+
/** A rule the server takes: a group level names its group. */
|
|
25
|
+
export declare const complete: (r: Rule) => boolean;
|
|
26
|
+
/** A rule as stored: empty previews and absent fields left out. */
|
|
27
|
+
export declare function cleanRule(r: Rule): Rule;
|
|
14
28
|
/** Who may open the content and what it sells for. */
|
|
15
29
|
export declare function AccessEditor(p: Common & {
|
|
16
30
|
content: Content;
|
|
@@ -23,9 +37,10 @@ export declare function versionLabel(v: Version, languageName: (l: string) => st
|
|
|
23
37
|
* the version's media folder; add and delete. A kind whose one version is
|
|
24
38
|
* hidden shows only that version's segments and media.
|
|
25
39
|
*/
|
|
26
|
-
export declare function VersionsEditor({ content, media, ...p }: Common & {
|
|
40
|
+
export declare function VersionsEditor({ content, media, activeVersion, ...p }: Common & {
|
|
27
41
|
content: Content;
|
|
28
42
|
media?: boolean;
|
|
43
|
+
activeVersion?: string;
|
|
29
44
|
}): import('react').JSX.Element | null;
|
|
30
45
|
/**
|
|
31
46
|
* A version's own cover, where its kind has covers: the cover upload its
|