@openrails/contentkit-ui 0.85.1 → 0.87.0-rc.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +28 -7
- package/dist/client/beacons.d.ts +13 -4
- package/dist/client/beacons.js +14 -7
- package/dist/client/beacons.js.map +1 -1
- package/dist/client/client.d.ts +3 -0
- package/dist/client/client.js +29 -27
- package/dist/client/client.js.map +1 -1
- package/dist/client/codes.d.ts +6 -1
- package/dist/client/codes.js +4 -1
- package/dist/client/codes.js.map +1 -1
- package/dist/client/content/types.d.ts +4 -2
- package/dist/client/content/types.js.map +1 -1
- package/dist/client/discovery.js +3 -0
- package/dist/client/discovery.js.map +1 -1
- package/dist/client/errors.d.ts +6 -0
- package/dist/client/errors.js +6 -2
- package/dist/client/errors.js.map +1 -1
- package/dist/client/gallery.d.ts +3 -5
- package/dist/client/gallery.js +16 -20
- package/dist/client/gallery.js.map +1 -1
- package/dist/client/generated/error-codes.d.ts +1 -1
- package/dist/client/generated/error-codes.js +9 -1
- package/dist/client/generated/error-codes.js.map +1 -1
- package/dist/client/generated/routes.d.ts +29 -3
- package/dist/client/generated/routes.js +44 -3
- package/dist/client/generated/routes.js.map +1 -1
- package/dist/client/generated/wire.d.ts +60 -10
- package/dist/client/generated/wire.js.map +1 -1
- package/dist/client/index.d.ts +2 -1
- package/dist/client/media/queue.d.ts +4 -2
- package/dist/client/media/queue.js +18 -12
- package/dist/client/media/queue.js.map +1 -1
- package/dist/client/media/rules.d.ts +7 -1
- package/dist/client/media/rules.js +27 -21
- package/dist/client/media/rules.js.map +1 -1
- package/dist/client/media/windows.js +1 -1
- package/dist/client/media/windows.js.map +1 -1
- package/dist/client/stats.d.ts +32 -0
- package/dist/client/stats.js +35 -0
- package/dist/client/stats.js.map +1 -0
- package/dist/client/versions.d.ts +6 -4
- package/dist/client/versions.js +24 -26
- package/dist/client/versions.js.map +1 -1
- package/dist/client.js +30 -29
- package/dist/components/admin/content-manager.js +206 -206
- package/dist/components/admin/content-manager.js.map +1 -1
- package/dist/components/admin/group-manager.js +71 -70
- package/dist/components/admin/group-manager.js.map +1 -1
- package/dist/components/admin/media-item-panel.d.ts +24 -7
- package/dist/components/admin/media-item-panel.js +209 -197
- package/dist/components/admin/media-item-panel.js.map +1 -1
- package/dist/components/admin/poll-manager.js +25 -25
- package/dist/components/admin/stats-dashboard.d.ts +22 -0
- package/dist/components/admin/stats-dashboard.js +257 -0
- package/dist/components/admin/stats-dashboard.js.map +1 -0
- package/dist/components/content/card.d.ts +5 -3
- package/dist/components/content/card.js +155 -133
- package/dist/components/content/card.js.map +1 -1
- package/dist/components/content/download-button.d.ts +26 -0
- package/dist/components/content/download-button.js +51 -0
- package/dist/components/content/download-button.js.map +1 -0
- package/dist/components/content/editors.js +455 -427
- package/dist/components/content/editors.js.map +1 -1
- package/dist/components/content/grid.d.ts +8 -1
- package/dist/components/content/grid.js +153 -104
- package/dist/components/content/grid.js.map +1 -1
- package/dist/components/content/index.d.ts +4 -2
- package/dist/components/content/listing.d.ts +3 -1
- package/dist/components/content/listing.js +34 -34
- package/dist/components/content/listing.js.map +1 -1
- package/dist/components/content/paywall.d.ts +17 -5
- package/dist/components/content/paywall.js +115 -100
- package/dist/components/content/paywall.js.map +1 -1
- package/dist/components/content/reader-stats.d.ts +12 -0
- package/dist/components/content/reader-stats.js +47 -0
- package/dist/components/content/reader-stats.js.map +1 -0
- package/dist/components/groups/banner.js +33 -33
- package/dist/components/groups/directory.js +11 -11
- package/dist/components/groups/editor.js +293 -293
- package/dist/components/groups/editor.js.map +1 -1
- package/dist/components/groups/header.js +27 -27
- package/dist/components/groups/header.js.map +1 -1
- package/dist/components/groups/memberships.js +180 -180
- package/dist/components/groups/parts.d.ts +0 -2
- package/dist/components/groups/parts.js +9 -27
- package/dist/components/groups/parts.js.map +1 -1
- package/dist/components/media-folder-editor.js +239 -189
- package/dist/components/media-folder-editor.js.map +1 -1
- package/dist/components/media-gallery.d.ts +1 -4
- package/dist/components/media-gallery.js +19 -34
- package/dist/components/media-gallery.js.map +1 -1
- package/dist/components/notifications.js +17 -17
- package/dist/components/slot-upload.d.ts +2 -2
- package/dist/components/slot-upload.js +84 -79
- package/dist/components/slot-upload.js.map +1 -1
- package/dist/components/social/bans.js +34 -34
- package/dist/components/social/comments.js +1 -1
- package/dist/components/social/comments.js.map +1 -1
- package/dist/components/social/engagement.d.ts +2 -1
- package/dist/components/social/engagement.js +5 -3
- package/dist/components/social/engagement.js.map +1 -1
- package/dist/components/social/moderation.js +52 -48
- package/dist/components/social/moderation.js.map +1 -1
- package/dist/components/video-player.d.ts +2 -0
- package/dist/components/video-player.js +318 -314
- package/dist/components/video-player.js.map +1 -1
- package/dist/i18n/context.d.ts +2 -0
- package/dist/i18n/context.js +23 -5
- package/dist/i18n/context.js.map +1 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.js +13 -10
- package/dist/locales/admin/de.js +27 -0
- package/dist/locales/admin/de.js.map +1 -1
- package/dist/locales/admin/en.d.ts +27 -0
- package/dist/locales/admin/en.js +27 -0
- package/dist/locales/admin/en.js.map +1 -1
- package/dist/locales/admin/es.js +27 -0
- package/dist/locales/admin/es.js.map +1 -1
- package/dist/locales/admin/ja.js +27 -0
- package/dist/locales/admin/ja.js.map +1 -1
- package/dist/locales/admin/ko.js +27 -0
- package/dist/locales/admin/ko.js.map +1 -1
- package/dist/locales/admin/zh.js +27 -0
- package/dist/locales/admin/zh.js.map +1 -1
- package/dist/locales/content/de.js +6 -0
- package/dist/locales/content/de.js.map +1 -1
- package/dist/locales/content/en.d.ts +6 -0
- package/dist/locales/content/en.js +6 -0
- package/dist/locales/content/en.js.map +1 -1
- package/dist/locales/content/es.js +6 -0
- package/dist/locales/content/es.js.map +1 -1
- package/dist/locales/content/ja.js +6 -0
- package/dist/locales/content/ja.js.map +1 -1
- package/dist/locales/content/ko.js +6 -0
- package/dist/locales/content/ko.js.map +1 -1
- package/dist/locales/content/zh.js +6 -0
- package/dist/locales/content/zh.js.map +1 -1
- package/dist/locales/de.js +14 -2
- package/dist/locales/de.js.map +1 -1
- package/dist/locales/discovery/de.js +3 -0
- package/dist/locales/discovery/de.js.map +1 -1
- package/dist/locales/discovery/en.d.ts +3 -0
- package/dist/locales/discovery/en.js +3 -0
- package/dist/locales/discovery/en.js.map +1 -1
- package/dist/locales/discovery/es.js +3 -0
- package/dist/locales/discovery/es.js.map +1 -1
- package/dist/locales/discovery/ja.js +3 -0
- package/dist/locales/discovery/ja.js.map +1 -1
- package/dist/locales/discovery/ko.js +3 -0
- package/dist/locales/discovery/ko.js.map +1 -1
- package/dist/locales/discovery/zh.js +3 -0
- package/dist/locales/discovery/zh.js.map +1 -1
- package/dist/locales/en.d.ts +50 -2
- package/dist/locales/en.js +14 -2
- package/dist/locales/en.js.map +1 -1
- package/dist/locales/es.js +14 -2
- package/dist/locales/es.js.map +1 -1
- package/dist/locales/ja.js +14 -2
- package/dist/locales/ja.js.map +1 -1
- package/dist/locales/ko.js +14 -2
- package/dist/locales/ko.js.map +1 -1
- package/dist/locales/zh.js +14 -2
- package/dist/locales/zh.js.map +1 -1
- package/dist/react/admin.js +22 -23
- package/dist/react/admin.js.map +1 -1
- package/dist/react/canonical.d.ts +4 -3
- package/dist/react/canonical.js +34 -33
- package/dist/react/canonical.js.map +1 -1
- package/dist/react/comments.d.ts +1 -1
- package/dist/react/comments.js +3 -2
- package/dist/react/comments.js.map +1 -1
- package/dist/react/contents.js +144 -144
- package/dist/react/contents.js.map +1 -1
- package/dist/react/context.d.ts +1 -1
- package/dist/react/context.js.map +1 -1
- package/dist/react/detail.d.ts +12 -6
- package/dist/react/detail.js +31 -24
- package/dist/react/detail.js.map +1 -1
- package/dist/react/discovery.d.ts +11 -0
- package/dist/react/discovery.js +49 -30
- package/dist/react/discovery.js.map +1 -1
- package/dist/react/engagement.d.ts +6 -2
- package/dist/react/engagement.js +2 -6
- package/dist/react/engagement.js.map +1 -1
- package/dist/react/folder.d.ts +7 -2
- package/dist/react/folder.js +165 -147
- package/dist/react/folder.js.map +1 -1
- package/dist/react/groups.d.ts +0 -1
- package/dist/react/groups.js +13 -12
- package/dist/react/groups.js.map +1 -1
- package/dist/react/index.d.ts +6 -4
- package/dist/react/location.d.ts +11 -0
- package/dist/react/location.js +18 -0
- package/dist/react/location.js.map +1 -0
- package/dist/react/public.d.ts +8 -0
- package/dist/react/public.js +32 -27
- package/dist/react/public.js.map +1 -1
- package/dist/react/stats.d.ts +24 -0
- package/dist/react/stats.js +28 -0
- package/dist/react/stats.js.map +1 -0
- package/dist/react/use-resource.js +8 -7
- package/dist/react/use-resource.js.map +1 -1
- package/dist/react/versions.d.ts +25 -5
- package/dist/react/versions.js +61 -40
- package/dist/react/versions.js.map +1 -1
- package/dist/react.js +26 -24
- package/dist/styles.css +1 -1
- package/dist/urls/index.d.ts +35 -10
- package/dist/urls.js +100 -70
- package/dist/urls.js.map +1 -1
- package/package.json +1 -1
|
@@ -9,8 +9,6 @@ export type GroupLike = Pick<GroupCard, "id" | "kind" | "name" | "slug" | "path"
|
|
|
9
9
|
/** Display names of kinds, attributes, roles and values by identifier; a missing one shows the identifier humanized. */
|
|
10
10
|
export type Labels = Readonly<Record<string, string>>;
|
|
11
11
|
export declare const labelOf: (labels: Labels | undefined, id: string) => string;
|
|
12
|
-
/** A language's name in the UI's language ("ja" → "Japanese"). */
|
|
13
|
-
export declare function useLanguageName(): (code: string) => string;
|
|
14
12
|
export interface GroupCoverProps {
|
|
15
13
|
group: GroupLike;
|
|
16
14
|
/** Shown instead, e.g. a cover just uploaded. */
|
|
@@ -11,25 +11,7 @@ import { jsx as h, jsxs as g } from "react/jsx-runtime";
|
|
|
11
11
|
import { cn as _ } from "cn";
|
|
12
12
|
//#region src/components/groups/parts.tsx
|
|
13
13
|
var v = (e, t) => e?.[t] ?? s(t);
|
|
14
|
-
function y() {
|
|
15
|
-
let { language: e } = t();
|
|
16
|
-
return p(() => {
|
|
17
|
-
let t;
|
|
18
|
-
try {
|
|
19
|
-
t = new Intl.DisplayNames(e ? [e] : void 0, { type: "language" });
|
|
20
|
-
} catch {
|
|
21
|
-
t = void 0;
|
|
22
|
-
}
|
|
23
|
-
return (e) => {
|
|
24
|
-
try {
|
|
25
|
-
return t?.of(e) ?? e;
|
|
26
|
-
} catch {
|
|
27
|
-
return e;
|
|
28
|
-
}
|
|
29
|
-
};
|
|
30
|
-
}, [e]);
|
|
31
|
-
}
|
|
32
|
-
function b({ group: t, src: r, className: i, shape: a, slot: o }) {
|
|
14
|
+
function y({ group: t, src: r, className: i, shape: a, slot: o }) {
|
|
33
15
|
let s = n(), c = _(s.className, "overflow-hidden bg-muted", a, i), l = {
|
|
34
16
|
"data-ckui-theme": s["data-ckui-theme"],
|
|
35
17
|
style: s.style,
|
|
@@ -55,21 +37,21 @@ function b({ group: t, src: r, className: i, shape: a, slot: o }) {
|
|
|
55
37
|
fallback: u
|
|
56
38
|
}) : u;
|
|
57
39
|
}
|
|
58
|
-
function
|
|
59
|
-
return /* @__PURE__ */ h(
|
|
40
|
+
function b(e) {
|
|
41
|
+
return /* @__PURE__ */ h(y, {
|
|
60
42
|
...e,
|
|
61
43
|
shape: "rounded-md",
|
|
62
44
|
slot: "group-cover"
|
|
63
45
|
});
|
|
64
46
|
}
|
|
65
|
-
function
|
|
66
|
-
return /* @__PURE__ */ h(
|
|
47
|
+
function x(e) {
|
|
48
|
+
return /* @__PURE__ */ h(y, {
|
|
67
49
|
...e,
|
|
68
50
|
shape: "aspect-square rounded-full",
|
|
69
51
|
slot: "group-avatar"
|
|
70
52
|
});
|
|
71
53
|
}
|
|
72
|
-
function
|
|
54
|
+
function S({ group: e, href: t, className: n, children: i }) {
|
|
73
55
|
let a = u(r)?.navigate, o = t ? t(e) : e.path, s = l((e) => {
|
|
74
56
|
!a || !o || e.defaultPrevented || e.button !== 0 || e.metaKey || e.ctrlKey || e.shiftKey || e.altKey || (e.preventDefault(), a(o));
|
|
75
57
|
}, [a, o]);
|
|
@@ -83,7 +65,7 @@ function C({ group: e, href: t, className: n, children: i }) {
|
|
|
83
65
|
children: i
|
|
84
66
|
});
|
|
85
67
|
}
|
|
86
|
-
function
|
|
68
|
+
function C({ kind: e, language: n, exclude: r, label: i, onPick: s, client: l, autoFocus: u, className: v }) {
|
|
87
69
|
let { t: y } = t(), b = f(), [x, S] = m(""), [C, w] = m(0), T = c(x, {
|
|
88
70
|
group_kinds: [e],
|
|
89
71
|
display_language: n,
|
|
@@ -151,7 +133,7 @@ function w({ kind: e, language: n, exclude: r, label: i, onPick: s, client: l, a
|
|
|
151
133
|
]
|
|
152
134
|
});
|
|
153
135
|
}
|
|
154
|
-
function
|
|
136
|
+
function w(e, t = {}) {
|
|
155
137
|
let n = i(t.client), [r, a] = m(/* @__PURE__ */ new Map()), o = [...new Set(e)].sort().join(",");
|
|
156
138
|
return d(() => {
|
|
157
139
|
if (!o) return;
|
|
@@ -166,6 +148,6 @@ function T(e, t = {}) {
|
|
|
166
148
|
]), r;
|
|
167
149
|
}
|
|
168
150
|
//#endregion
|
|
169
|
-
export {
|
|
151
|
+
export { x as GroupAvatar, b as GroupCover, S as GroupLink, C as GroupPicker, v as labelOf, w as useGroupNames };
|
|
170
152
|
|
|
171
153
|
//# sourceMappingURL=parts.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"parts.js","names":[],"sources":["../../../src/components/groups/parts.tsx"],"sourcesContent":["import { cn } from \"cn\";\nimport { useCallback, useContext, useEffect, useId, useMemo, useState, type MouseEvent, type ReactNode } from \"react\";\nimport type { ContentKitClient } from \"../../client/client.js\";\nimport { humanize } from \"../../client/group-fields.js\";\nimport type { Avatar, GroupCard, GroupDetail, GroupsCover } from \"../../client/generated/wire.js\";\nimport { useMessages } from \"../../i18n/context.js\";\nimport { ContentKitContext, useContentKitClient } from \"../../react/context.js\";\nimport { useTypeahead } from \"../../react/discovery.js\";\nimport { Input } from \"#ckui/ui/input\";\nimport { useScopeProps } from \"../../scope.js\";\nimport { RenditionImg } from \"../rendition-img.js\";\nimport { ErrorLine } from \"../social/parts.js\";\n\n/** A group as covers and links need it. */\nexport type GroupLike = Pick<GroupCard, \"id\" | \"kind\" | \"name\" | \"slug\" | \"path\"> & { cover?: GroupsCover; avatar?: Avatar };\n\n/** Display names of kinds, attributes, roles and values by identifier; a missing one shows the identifier humanized. */\nexport type Labels = Readonly<Record<string, string>>;\n\nexport const labelOf = (labels: Labels | undefined, id: string) => labels?.[id] ?? humanize(id);\n\n/** A language's name in the UI's language (\"ja\" → \"Japanese\"). */\nexport function useLanguageName(): (code: string) => string {\n const { language } = useMessages();\n return useMemo(() => {\n let names: Intl.DisplayNames | undefined;\n try {\n names = new Intl.DisplayNames(language ? [language] : undefined, { type: \"language\" });\n } catch {\n names = undefined;\n }\n return (code: string) => {\n try {\n return names?.of(code) ?? code;\n } catch {\n return code;\n }\n };\n }, [language]);\n}\n\nexport interface GroupCoverProps {\n group: GroupLike;\n /** Shown instead, e.g. a cover just uploaded. */\n src?: string;\n className?: string;\n}\n\n/** A group's cover or avatar image; its own styling root, so it renders anywhere in the host. */\nfunction GroupImage({ group, src, className, shape, slot }: GroupCoverProps & { shape: string; slot: \"group-cover\" | \"group-avatar\" }) {\n const scope = useScopeProps();\n const box = cn(scope.className, \"overflow-hidden bg-muted\", shape, className);\n const root = { \"data-ckui-theme\": scope[\"data-ckui-theme\"], style: scope.style, \"data-ckui\": slot };\n const initial = (\n <span {...root} className={cn(box, \"grid place-items-center font-semibold text-muted-foreground\", slot === \"group-cover\" && \"text-lg\")}>\n {(group.name || group.slug).trim().charAt(0).toUpperCase() || \"?\"}\n </span>\n );\n if (src) return <img {...root} src={src} alt=\"\" className={cn(box, \"object-cover\")} />;\n const renditions = (slot === \"group-cover\" ? group.cover : group.avatar)?.renditions;\n if (renditions?.length) return <RenditionImg {...root} outputs={renditions} fit=\"cover\" skeleton className={box} fallback={initial} />;\n return initial;\n}\n\n/** A group's cover: its renditions, else its initial on a muted tile. */\nexport function GroupCover(p: GroupCoverProps) {\n return <GroupImage {...p} shape=\"rounded-md\" slot=\"group-cover\" />;\n}\n\n/** A group's avatar: its renditions, else its initial in a circle. */\nexport function GroupAvatar(p: GroupCoverProps) {\n return <GroupImage {...p} shape=\"aspect-square rounded-full\" slot=\"group-avatar\" />;\n}\n\n/** A link to a group's page: `href`, else its canonical path; in-app through the provider's navigate. */\nexport function GroupLink({ group, href, className, children }: { group: GroupLike; href?: (g: GroupLike) => string | undefined; className?: string; children: ReactNode }) {\n const navigate = useContext(ContentKitContext)?.navigate;\n const url = href ? href(group) : group.path;\n const onClick = useCallback(\n (e: MouseEvent<HTMLAnchorElement>) => {\n if (!navigate || !url || e.defaultPrevented || e.button !== 0 || e.metaKey || e.ctrlKey || e.shiftKey || e.altKey) return;\n e.preventDefault();\n navigate(url);\n },\n [navigate, url],\n );\n if (!url) return <span className={className}>{children}</span>;\n return (\n <a href={url} className={className} onClick={onClick}>\n {children}\n </a>\n );\n}\n\nexport interface GroupPickerProps {\n kind: string;\n /** Names in this language. */\n language?: string;\n /** Groups not offered, by id. */\n exclude?: readonly string[];\n label: string;\n onPick: (group: GroupCard) => void;\n client?: ContentKitClient;\n autoFocus?: boolean;\n className?: string;\n}\n\n/** A typeahead over one kind's groups (GET /v1/typeahead). */\nexport function GroupPicker({ kind, language, exclude, label, onPick, client, autoFocus, className }: GroupPickerProps) {\n const { t } = useMessages();\n const id = useId();\n const [text, setText] = useState(\"\");\n const [active, setActive] = useState(0);\n const found = useTypeahead(text, { group_kinds: [kind], display_language: language, limit: 10, client });\n const results = useMemo(() => found.groups.filter((g) => g.kind === kind && !exclude?.includes(g.id)).slice(0, 8), [found.groups, kind, exclude]);\n const q = text.trim();\n useEffect(() => setActive(0), [q]);\n const pick = (g: GroupCard) => {\n setText(\"\");\n onPick(g);\n };\n const open = results.length > 0;\n return (\n <div className={cn(\"relative grid min-w-48 flex-1 gap-1\", className)} data-ckui=\"group-picker\">\n <Input\n role=\"combobox\"\n aria-label={label}\n aria-expanded={open}\n aria-controls={`${id}-list`}\n aria-activedescendant={open ? `${id}-${active}` : undefined}\n aria-autocomplete=\"list\"\n autoComplete=\"off\"\n className=\"h-8\"\n value={text}\n placeholder={t(\"groups.searchPlaceholder\")}\n autoFocus={autoFocus}\n onChange={(e) => setText(e.target.value)}\n onKeyDown={(e) => {\n if (!open) return;\n if (e.key === \"ArrowDown\") {\n e.preventDefault();\n setActive((a) => Math.min(results.length - 1, a + 1));\n } else if (e.key === \"ArrowUp\") {\n e.preventDefault();\n setActive((a) => Math.max(0, a - 1));\n } else if (e.key === \"Enter\") {\n e.preventDefault();\n pick(results[active]!);\n } else if (e.key === \"Escape\") setText(\"\");\n }}\n />\n {open && (\n <ul id={`${id}-list`} role=\"listbox\" aria-label={label} className=\"absolute top-full z-10 mt-1 grid w-full overflow-hidden rounded-md border border-border bg-popover text-popover-foreground shadow-md\">\n {results.map((g, i) => (\n <li\n key={g.id}\n id={`${id}-${i}`}\n role=\"option\"\n aria-selected={i === active}\n className={cn(\"flex cursor-pointer items-baseline justify-between gap-2 px-3 py-1.5\", i === active && \"bg-accent text-accent-foreground\")}\n onMouseEnter={() => setActive(i)}\n onMouseDown={(e) => {\n e.preventDefault();\n pick(g);\n }}\n >\n <span className=\"min-w-0 truncate\">{g.name || g.slug}</span>\n <span className=\"text-xs text-muted-foreground\">{g.slug}</span>\n </li>\n ))}\n </ul>\n )}\n {q && !open && found.query === q && !found.loading && !found.error && (\n <p className=\"text-xs text-muted-foreground\" role=\"status\">\n {t(\"groups.noMatch\")}\n </p>\n )}\n <ErrorLine error={found.error} />\n </div>\n );\n}\n\n/** Groups read by id, for names where only ids are at hand (edges); a missing or deleted one is left out. */\nexport function useGroupNames(ids: readonly string[], o: { language?: string; client?: ContentKitClient } = {}): ReadonlyMap<string, GroupDetail> {\n const client = useContentKitClient(o.client);\n const [found, setFound] = useState<ReadonlyMap<string, GroupDetail>>(new Map());\n const key = [...new Set(ids)].sort().join(\",\");\n useEffect(() => {\n if (!key) return;\n const ctl = new AbortController();\n const list = key.split(\",\");\n // A merged group answers as its survivor: keep it under the id asked for.\n Promise.all(list.map((id) => client.groups.get(id, o.language, ctl.signal).catch(() => null))).then((all) => {\n if (!ctl.signal.aborted) setFound(new Map(all.flatMap((g, i) => (g ? [[list[i]!, g] as const] : []))));\n });\n return () => ctl.abort();\n }, [key, client, o.language]);\n return found;\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"parts.js","names":[],"sources":["../../../src/components/groups/parts.tsx"],"sourcesContent":["import { cn } from \"cn\";\nimport { useCallback, useContext, useEffect, useId, useMemo, useState, type MouseEvent, type ReactNode } from \"react\";\nimport type { ContentKitClient } from \"../../client/client.js\";\nimport { humanize } from \"../../client/group-fields.js\";\nimport type { Avatar, GroupCard, GroupDetail, GroupsCover } from \"../../client/generated/wire.js\";\nimport { useMessages } from \"../../i18n/context.js\";\nimport { ContentKitContext, useContentKitClient } from \"../../react/context.js\";\nimport { useTypeahead } from \"../../react/discovery.js\";\nimport { Input } from \"#ckui/ui/input\";\nimport { useScopeProps } from \"../../scope.js\";\nimport { RenditionImg } from \"../rendition-img.js\";\nimport { ErrorLine } from \"../social/parts.js\";\n\n/** A group as covers and links need it. */\nexport type GroupLike = Pick<GroupCard, \"id\" | \"kind\" | \"name\" | \"slug\" | \"path\"> & { cover?: GroupsCover; avatar?: Avatar };\n\n/** Display names of kinds, attributes, roles and values by identifier; a missing one shows the identifier humanized. */\nexport type Labels = Readonly<Record<string, string>>;\n\nexport const labelOf = (labels: Labels | undefined, id: string) => labels?.[id] ?? humanize(id);\n\n\nexport interface GroupCoverProps {\n group: GroupLike;\n /** Shown instead, e.g. a cover just uploaded. */\n src?: string;\n className?: string;\n}\n\n/** A group's cover or avatar image; its own styling root, so it renders anywhere in the host. */\nfunction GroupImage({ group, src, className, shape, slot }: GroupCoverProps & { shape: string; slot: \"group-cover\" | \"group-avatar\" }) {\n const scope = useScopeProps();\n const box = cn(scope.className, \"overflow-hidden bg-muted\", shape, className);\n const root = { \"data-ckui-theme\": scope[\"data-ckui-theme\"], style: scope.style, \"data-ckui\": slot };\n const initial = (\n <span {...root} className={cn(box, \"grid place-items-center font-semibold text-muted-foreground\", slot === \"group-cover\" && \"text-lg\")}>\n {(group.name || group.slug).trim().charAt(0).toUpperCase() || \"?\"}\n </span>\n );\n if (src) return <img {...root} src={src} alt=\"\" className={cn(box, \"object-cover\")} />;\n const renditions = (slot === \"group-cover\" ? group.cover : group.avatar)?.renditions;\n if (renditions?.length) return <RenditionImg {...root} outputs={renditions} fit=\"cover\" skeleton className={box} fallback={initial} />;\n return initial;\n}\n\n/** A group's cover: its renditions, else its initial on a muted tile. */\nexport function GroupCover(p: GroupCoverProps) {\n return <GroupImage {...p} shape=\"rounded-md\" slot=\"group-cover\" />;\n}\n\n/** A group's avatar: its renditions, else its initial in a circle. */\nexport function GroupAvatar(p: GroupCoverProps) {\n return <GroupImage {...p} shape=\"aspect-square rounded-full\" slot=\"group-avatar\" />;\n}\n\n/** A link to a group's page: `href`, else its canonical path; in-app through the provider's navigate. */\nexport function GroupLink({ group, href, className, children }: { group: GroupLike; href?: (g: GroupLike) => string | undefined; className?: string; children: ReactNode }) {\n const navigate = useContext(ContentKitContext)?.navigate;\n const url = href ? href(group) : group.path;\n const onClick = useCallback(\n (e: MouseEvent<HTMLAnchorElement>) => {\n if (!navigate || !url || e.defaultPrevented || e.button !== 0 || e.metaKey || e.ctrlKey || e.shiftKey || e.altKey) return;\n e.preventDefault();\n navigate(url);\n },\n [navigate, url],\n );\n if (!url) return <span className={className}>{children}</span>;\n return (\n <a href={url} className={className} onClick={onClick}>\n {children}\n </a>\n );\n}\n\nexport interface GroupPickerProps {\n kind: string;\n /** Names in this language. */\n language?: string;\n /** Groups not offered, by id. */\n exclude?: readonly string[];\n label: string;\n onPick: (group: GroupCard) => void;\n client?: ContentKitClient;\n autoFocus?: boolean;\n className?: string;\n}\n\n/** A typeahead over one kind's groups (GET /v1/typeahead). */\nexport function GroupPicker({ kind, language, exclude, label, onPick, client, autoFocus, className }: GroupPickerProps) {\n const { t } = useMessages();\n const id = useId();\n const [text, setText] = useState(\"\");\n const [active, setActive] = useState(0);\n const found = useTypeahead(text, { group_kinds: [kind], display_language: language, limit: 10, client });\n const results = useMemo(() => found.groups.filter((g) => g.kind === kind && !exclude?.includes(g.id)).slice(0, 8), [found.groups, kind, exclude]);\n const q = text.trim();\n useEffect(() => setActive(0), [q]);\n const pick = (g: GroupCard) => {\n setText(\"\");\n onPick(g);\n };\n const open = results.length > 0;\n return (\n <div className={cn(\"relative grid min-w-48 flex-1 gap-1\", className)} data-ckui=\"group-picker\">\n <Input\n role=\"combobox\"\n aria-label={label}\n aria-expanded={open}\n aria-controls={`${id}-list`}\n aria-activedescendant={open ? `${id}-${active}` : undefined}\n aria-autocomplete=\"list\"\n autoComplete=\"off\"\n className=\"h-8\"\n value={text}\n placeholder={t(\"groups.searchPlaceholder\")}\n autoFocus={autoFocus}\n onChange={(e) => setText(e.target.value)}\n onKeyDown={(e) => {\n if (!open) return;\n if (e.key === \"ArrowDown\") {\n e.preventDefault();\n setActive((a) => Math.min(results.length - 1, a + 1));\n } else if (e.key === \"ArrowUp\") {\n e.preventDefault();\n setActive((a) => Math.max(0, a - 1));\n } else if (e.key === \"Enter\") {\n e.preventDefault();\n pick(results[active]!);\n } else if (e.key === \"Escape\") setText(\"\");\n }}\n />\n {open && (\n <ul id={`${id}-list`} role=\"listbox\" aria-label={label} className=\"absolute top-full z-10 mt-1 grid w-full overflow-hidden rounded-md border border-border bg-popover text-popover-foreground shadow-md\">\n {results.map((g, i) => (\n <li\n key={g.id}\n id={`${id}-${i}`}\n role=\"option\"\n aria-selected={i === active}\n className={cn(\"flex cursor-pointer items-baseline justify-between gap-2 px-3 py-1.5\", i === active && \"bg-accent text-accent-foreground\")}\n onMouseEnter={() => setActive(i)}\n onMouseDown={(e) => {\n e.preventDefault();\n pick(g);\n }}\n >\n <span className=\"min-w-0 truncate\">{g.name || g.slug}</span>\n <span className=\"text-xs text-muted-foreground\">{g.slug}</span>\n </li>\n ))}\n </ul>\n )}\n {q && !open && found.query === q && !found.loading && !found.error && (\n <p className=\"text-xs text-muted-foreground\" role=\"status\">\n {t(\"groups.noMatch\")}\n </p>\n )}\n <ErrorLine error={found.error} />\n </div>\n );\n}\n\n/** Groups read by id, for names where only ids are at hand (edges); a missing or deleted one is left out. */\nexport function useGroupNames(ids: readonly string[], o: { language?: string; client?: ContentKitClient } = {}): ReadonlyMap<string, GroupDetail> {\n const client = useContentKitClient(o.client);\n const [found, setFound] = useState<ReadonlyMap<string, GroupDetail>>(new Map());\n const key = [...new Set(ids)].sort().join(\",\");\n useEffect(() => {\n if (!key) return;\n const ctl = new AbortController();\n const list = key.split(\",\");\n // A merged group answers as its survivor: keep it under the id asked for.\n Promise.all(list.map((id) => client.groups.get(id, o.language, ctl.signal).catch(() => null))).then((all) => {\n if (!ctl.signal.aborted) setFound(new Map(all.flatMap((g, i) => (g ? [[list[i]!, g] as const] : []))));\n });\n return () => ctl.abort();\n }, [key, client, o.language]);\n return found;\n}\n"],"mappings":"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"}
|