@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
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { useMessages as e } from "../i18n/context.js";
|
|
2
2
|
import { ContentKitUiRoot as t, useScopeProps as n } from "../scope.js";
|
|
3
3
|
import { useErrorReporter as r } from "../react/context.js";
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
4
|
+
import { useContentScope as i } from "../react/use-resource.js";
|
|
5
|
+
import { Button as a } from "../ui/button.js";
|
|
6
6
|
import { Badge as o } from "../ui/badge.js";
|
|
7
7
|
import { Skeleton as s } from "../ui/skeleton.js";
|
|
8
8
|
import { ErrorLine as c, RelativeTime as l, useAction as u } from "./social/parts.js";
|
|
@@ -21,7 +21,7 @@ function T({ renderItem: n, renderActions: o, client: l, pageSize: u, initialFil
|
|
|
21
21
|
unread: j === "unread",
|
|
22
22
|
dismissed: j === "archived",
|
|
23
23
|
refreshInterval: x
|
|
24
|
-
}), { onSignIn: P } =
|
|
24
|
+
}), { onSignIn: P } = i(l), F = w ?? P, I = h(null), L = r(T);
|
|
25
25
|
return p(() => {
|
|
26
26
|
N.error && L(N.error, "notifications.load");
|
|
27
27
|
}, [N.error, L]), /* @__PURE__ */ y(t, {
|
|
@@ -36,7 +36,7 @@ function T({ renderItem: n, renderActions: o, client: l, pageSize: u, initialFil
|
|
|
36
36
|
id: A,
|
|
37
37
|
className: "text-base font-semibold",
|
|
38
38
|
children: k("notifications.title")
|
|
39
|
-
}), !N.signedOut && /* @__PURE__ */ v(
|
|
39
|
+
}), !N.signedOut && /* @__PURE__ */ v(a, {
|
|
40
40
|
size: "icon-sm",
|
|
41
41
|
variant: "ghost",
|
|
42
42
|
"aria-label": k("notifications.refresh"),
|
|
@@ -49,7 +49,7 @@ function T({ renderItem: n, renderActions: o, client: l, pageSize: u, initialFil
|
|
|
49
49
|
})]
|
|
50
50
|
}), N.signedOut ? /* @__PURE__ */ y("div", {
|
|
51
51
|
className: "grid justify-items-start gap-3 py-4 text-muted-foreground",
|
|
52
|
-
children: [/* @__PURE__ */ v("p", { children: k("notifications.signInHint") }), F && /* @__PURE__ */ v(
|
|
52
|
+
children: [/* @__PURE__ */ v("p", { children: k("notifications.signInHint") }), F && /* @__PURE__ */ v(a, {
|
|
53
53
|
variant: "outline",
|
|
54
54
|
onClick: F,
|
|
55
55
|
children: k("notifications.signIn")
|
|
@@ -63,7 +63,7 @@ function T({ renderItem: n, renderActions: o, client: l, pageSize: u, initialFil
|
|
|
63
63
|
"all",
|
|
64
64
|
"unread",
|
|
65
65
|
"archived"
|
|
66
|
-
].map((e) => /* @__PURE__ */ v(
|
|
66
|
+
].map((e) => /* @__PURE__ */ v(a, {
|
|
67
67
|
ref: j === e ? I : void 0,
|
|
68
68
|
size: "sm",
|
|
69
69
|
variant: j === e ? "secondary" : "ghost",
|
|
@@ -74,7 +74,7 @@ function T({ renderItem: n, renderActions: o, client: l, pageSize: u, initialFil
|
|
|
74
74
|
}),
|
|
75
75
|
N.error && /* @__PURE__ */ y("div", {
|
|
76
76
|
className: "grid justify-items-start gap-2",
|
|
77
|
-
children: [/* @__PURE__ */ v(c, { children: k("notifications.loadFailed") }), /* @__PURE__ */ v(
|
|
77
|
+
children: [/* @__PURE__ */ v(c, { children: k("notifications.loadFailed") }), /* @__PURE__ */ v(a, {
|
|
78
78
|
size: "sm",
|
|
79
79
|
variant: "outline",
|
|
80
80
|
onClick: N.reload,
|
|
@@ -108,7 +108,7 @@ function T({ renderItem: n, renderActions: o, client: l, pageSize: u, initialFil
|
|
|
108
108
|
onError: T
|
|
109
109
|
}, e.id))
|
|
110
110
|
}),
|
|
111
|
-
N.hasMore && /* @__PURE__ */ v(
|
|
111
|
+
N.hasMore && /* @__PURE__ */ v(a, {
|
|
112
112
|
variant: "outline",
|
|
113
113
|
disabled: N.loadingMore || N.loading,
|
|
114
114
|
onClick: () => void N.loadMore(),
|
|
@@ -117,7 +117,7 @@ function T({ renderItem: n, renderActions: o, client: l, pageSize: u, initialFil
|
|
|
117
117
|
] })]
|
|
118
118
|
});
|
|
119
119
|
}
|
|
120
|
-
function E({ item: t, renderItem: n, renderActions: r, onRead:
|
|
120
|
+
function E({ item: t, renderItem: n, renderActions: r, onRead: i, onDismiss: s, onError: d }) {
|
|
121
121
|
let { t: f } = e(), p = u("notifications.read", d), h = u("notifications.dismiss", d), g = m(), _ = t.status === "open" ? f("notifications.open") : t.status === "resolved" ? f("notifications.resolved") : t.status === "dismissed" ? f("notifications.dismissed") : void 0;
|
|
122
122
|
return /* @__PURE__ */ y("li", {
|
|
123
123
|
className: b("grid gap-3 p-4", !t.read_at && "bg-primary/5"),
|
|
@@ -147,15 +147,15 @@ function E({ item: t, renderItem: n, renderActions: r, onRead: a, onDismiss: s,
|
|
|
147
147
|
className: "flex flex-wrap items-center gap-2",
|
|
148
148
|
children: [
|
|
149
149
|
r?.(t),
|
|
150
|
-
/* @__PURE__ */ v(
|
|
150
|
+
/* @__PURE__ */ v(a, {
|
|
151
151
|
size: "sm",
|
|
152
152
|
variant: "ghost",
|
|
153
153
|
"aria-describedby": g,
|
|
154
154
|
disabled: p.pending || h.pending,
|
|
155
|
-
onClick: () => void p.run(() =>
|
|
155
|
+
onClick: () => void p.run(() => i(t.id, !t.read_at)),
|
|
156
156
|
children: f(t.read_at ? "notifications.markUnread" : "notifications.markRead")
|
|
157
157
|
}),
|
|
158
|
-
/* @__PURE__ */ v(
|
|
158
|
+
/* @__PURE__ */ v(a, {
|
|
159
159
|
size: "sm",
|
|
160
160
|
variant: "ghost",
|
|
161
161
|
"aria-describedby": g,
|
|
@@ -169,11 +169,11 @@ function E({ item: t, renderItem: n, renderActions: r, onRead: a, onDismiss: s,
|
|
|
169
169
|
]
|
|
170
170
|
});
|
|
171
171
|
}
|
|
172
|
-
function D({ appearance:
|
|
172
|
+
function D({ appearance: i, className: o, unreadRefreshInterval: s, ...c }) {
|
|
173
173
|
let { t: l } = e(), u = d({
|
|
174
174
|
client: c.client,
|
|
175
175
|
refreshInterval: s
|
|
176
|
-
}), f = n(
|
|
176
|
+
}), f = n(i), m = r(c.onError);
|
|
177
177
|
return p(() => {
|
|
178
178
|
u.error && m(u.error, "notifications.load");
|
|
179
179
|
}, [u.error, m]), /* @__PURE__ */ y(w.Root, {
|
|
@@ -181,11 +181,11 @@ function D({ appearance: a, className: o, unreadRefreshInterval: s, ...c }) {
|
|
|
181
181
|
e && u.reload();
|
|
182
182
|
},
|
|
183
183
|
children: [/* @__PURE__ */ v(t, {
|
|
184
|
-
appearance:
|
|
184
|
+
appearance: i,
|
|
185
185
|
className: b("inline-flex", o),
|
|
186
186
|
"data-ckui": "notification-bell",
|
|
187
187
|
children: /* @__PURE__ */ y(w.Trigger, {
|
|
188
|
-
render: /* @__PURE__ */ v(
|
|
188
|
+
render: /* @__PURE__ */ v(a, {
|
|
189
189
|
variant: "ghost",
|
|
190
190
|
size: "icon"
|
|
191
191
|
}),
|
|
@@ -210,7 +210,7 @@ function D({ appearance: a, className: o, unreadRefreshInterval: s, ...c }) {
|
|
|
210
210
|
"aria-label": l("notifications.title"),
|
|
211
211
|
children: /* @__PURE__ */ v(T, {
|
|
212
212
|
...c,
|
|
213
|
-
appearance:
|
|
213
|
+
appearance: i
|
|
214
214
|
})
|
|
215
215
|
})
|
|
216
216
|
}) })]
|
|
@@ -5,8 +5,8 @@ import { CropSource } from '../client/image.js';
|
|
|
5
5
|
import { PublicPreset } from '../client/public.js';
|
|
6
6
|
import { FileInfo, ReadResult, RefBody } from '../client/generated/wire.js';
|
|
7
7
|
export interface SlotUploadProps {
|
|
8
|
-
/** The item that owns the upload. */
|
|
9
|
-
item
|
|
8
|
+
/** The item that owns the upload; an AvatarUpload's default is the viewer's avatar (the content model's `avatars`), on whichever site holds it. */
|
|
9
|
+
item?: RefBody;
|
|
10
10
|
/** The upload path; default "avatar" or "cover". */
|
|
11
11
|
path?: string;
|
|
12
12
|
/** The public preset showing it. */
|
|
@@ -2,41 +2,46 @@ import { ratio as e } from "../client/aspect.js";
|
|
|
2
2
|
import { presetFor as t } from "../client/media/rules.js";
|
|
3
3
|
import { useMessages as n } from "../i18n/context.js";
|
|
4
4
|
import { ContentKitUiRoot as r } from "../scope.js";
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
11
|
-
import {
|
|
12
|
-
import {
|
|
13
|
-
import {
|
|
5
|
+
import { useContentScope as i } from "../react/use-resource.js";
|
|
6
|
+
import { useKinds as a } from "../react/groups.js";
|
|
7
|
+
import { usePresets as o } from "../react/public.js";
|
|
8
|
+
import { Button as s } from "../ui/button.js";
|
|
9
|
+
import { SlotImage as c } from "./slot-image.js";
|
|
10
|
+
import { SlotEditError as l, SlotEditor as u, useSlotEditor as d } from "./slot-editor.js";
|
|
11
|
+
import { useState as f } from "react";
|
|
12
|
+
import { Fragment as p, jsx as m, jsxs as h } from "react/jsx-runtime";
|
|
13
|
+
import { cn as g } from "cn";
|
|
14
|
+
import { Camera01Icon as _, CropIcon as v, Delete02Icon as y, ImageUpload01Icon as b, Loading03Icon as x } from "@hugeicons/core-free-icons";
|
|
15
|
+
import { HugeiconsIcon as S } from "@hugeicons/react";
|
|
14
16
|
//#region src/components/slot-upload.tsx
|
|
15
|
-
function
|
|
16
|
-
return /* @__PURE__ */
|
|
17
|
+
function C(e) {
|
|
18
|
+
return /* @__PURE__ */ m(T, {
|
|
17
19
|
...e,
|
|
18
20
|
variant: "avatar"
|
|
19
21
|
});
|
|
20
22
|
}
|
|
21
|
-
function
|
|
22
|
-
return /* @__PURE__ */
|
|
23
|
+
function w(e) {
|
|
24
|
+
return /* @__PURE__ */ m(T, {
|
|
23
25
|
...e,
|
|
24
26
|
variant: "cover"
|
|
25
27
|
});
|
|
26
28
|
}
|
|
27
|
-
function
|
|
28
|
-
let
|
|
29
|
-
|
|
30
|
-
|
|
29
|
+
function T({ variant: e, ...n }) {
|
|
30
|
+
let s = n.path ?? e, { presets: c } = o({ client: n.client }), { kinds: l } = a({ client: n.client }), { viewer: d } = i(n.client), f = e === "avatar" ? l?.avatars : void 0, p = n.item ?? (f && d ? {
|
|
31
|
+
kind: f.kind,
|
|
32
|
+
id: d
|
|
33
|
+
} : void 0), h = p && (t(c, p.kind, s, n.image?.preset) ?? (f?.kind === p.kind ? f : void 0));
|
|
34
|
+
return p ? /* @__PURE__ */ m(r, {
|
|
35
|
+
className: g("text-sm", n.className),
|
|
31
36
|
"data-ckui": e === "avatar" ? "avatar-upload" : "cover-upload",
|
|
32
|
-
children: /* @__PURE__ */
|
|
33
|
-
item:
|
|
34
|
-
path:
|
|
37
|
+
children: /* @__PURE__ */ m(u, {
|
|
38
|
+
item: p,
|
|
39
|
+
path: s,
|
|
35
40
|
image: n.image,
|
|
36
41
|
client: n.client,
|
|
37
42
|
read: n.read,
|
|
38
43
|
onChange: n.onChange,
|
|
39
|
-
aspect: n.aspect || n.image?.aspect ||
|
|
44
|
+
aspect: n.aspect || n.image?.aspect || h?.aspect || (e === "avatar" ? "1:1" : "3:1"),
|
|
40
45
|
minWidth: n.minWidth,
|
|
41
46
|
animation: n.animation,
|
|
42
47
|
targetWidth: n.targetWidth ?? (e === "avatar" ? 512 : 3e3),
|
|
@@ -45,171 +50,171 @@ function C({ variant: e, ...n }) {
|
|
|
45
50
|
disabled: n.disabled,
|
|
46
51
|
removable: n.removable ?? e === "avatar",
|
|
47
52
|
decode: n.decode,
|
|
48
|
-
children: /* @__PURE__ */
|
|
53
|
+
children: /* @__PURE__ */ m(E, {
|
|
49
54
|
...n,
|
|
50
55
|
variant: e
|
|
51
56
|
})
|
|
52
57
|
})
|
|
53
|
-
});
|
|
58
|
+
}) : null;
|
|
54
59
|
}
|
|
55
|
-
function
|
|
56
|
-
let { t: i } = n(),
|
|
60
|
+
function E({ variant: t, ...r }) {
|
|
61
|
+
let { t: i } = n(), a = d(), { crop: o, has: u, busy: C, disabled: w } = a, T = {
|
|
57
62
|
preset: r.image?.preset ?? t,
|
|
58
|
-
aspect:
|
|
59
|
-
renditions:
|
|
60
|
-
}, [
|
|
63
|
+
aspect: a.image.aspect,
|
|
64
|
+
renditions: a.image.renditions
|
|
65
|
+
}, [E, O] = f(!1), k = o.aspect, A = r.targetWidth ?? (t === "avatar" ? 512 : 3e3), j = (e) => {
|
|
61
66
|
e.preventDefault(), O(!1);
|
|
62
67
|
let t = [...e.dataTransfer.files].find((e) => e.type.startsWith("image/")) ?? e.dataTransfer.files[0];
|
|
63
|
-
t &&
|
|
68
|
+
t && a.pick(t);
|
|
64
69
|
}, M = r.hint ?? (t === "avatar" ? i("avatar.hint", { size: A }) : i("cover.hint", {
|
|
65
70
|
width: A,
|
|
66
71
|
height: Math.round(A / (e(k) ?? 3))
|
|
67
|
-
})), N = r.label ?? i(t === "avatar" ? "avatar.label" : "cover.label"), P = (e) => /* @__PURE__ */ p
|
|
68
|
-
/* @__PURE__ */
|
|
69
|
-
variant: e &&
|
|
72
|
+
})), N = r.label ?? i(t === "avatar" ? "avatar.label" : "cover.label"), P = (e) => /* @__PURE__ */ h(p, { children: [
|
|
73
|
+
/* @__PURE__ */ h(s, {
|
|
74
|
+
variant: e && u ? "secondary" : "outline",
|
|
70
75
|
size: "sm",
|
|
71
76
|
disabled: w,
|
|
72
|
-
onClick:
|
|
77
|
+
onClick: a.choose,
|
|
73
78
|
"data-ckui": "change",
|
|
74
|
-
children: [/* @__PURE__ */
|
|
75
|
-
icon: C ?
|
|
79
|
+
children: [/* @__PURE__ */ m(S, {
|
|
80
|
+
icon: C ? x : _,
|
|
76
81
|
strokeWidth: 2,
|
|
77
82
|
"data-icon": "inline-start",
|
|
78
83
|
className: C ? "animate-spin" : void 0
|
|
79
|
-
}), i(
|
|
84
|
+
}), i(u ? "common.change" : "common.upload")]
|
|
80
85
|
}),
|
|
81
|
-
|
|
86
|
+
u && o.canRecrop && /* @__PURE__ */ h(s, {
|
|
82
87
|
variant: e ? "secondary" : "ghost",
|
|
83
88
|
size: "sm",
|
|
84
89
|
disabled: w,
|
|
85
|
-
onClick:
|
|
90
|
+
onClick: a.recrop,
|
|
86
91
|
"data-ckui": "edit-crop",
|
|
87
|
-
children: [/* @__PURE__ */
|
|
88
|
-
icon:
|
|
92
|
+
children: [/* @__PURE__ */ m(S, {
|
|
93
|
+
icon: v,
|
|
89
94
|
strokeWidth: 2,
|
|
90
95
|
"data-icon": "inline-start"
|
|
91
96
|
}), i("common.editCrop")]
|
|
92
97
|
}),
|
|
93
|
-
|
|
98
|
+
u && a.removable && /* @__PURE__ */ h(s, {
|
|
94
99
|
variant: e ? "secondary" : "ghost",
|
|
95
100
|
size: "sm",
|
|
96
101
|
disabled: w,
|
|
97
|
-
onClick:
|
|
102
|
+
onClick: a.remove,
|
|
98
103
|
"data-ckui": "remove",
|
|
99
|
-
children: [/* @__PURE__ */
|
|
100
|
-
icon:
|
|
104
|
+
children: [/* @__PURE__ */ m(S, {
|
|
105
|
+
icon: y,
|
|
101
106
|
strokeWidth: 2,
|
|
102
107
|
"data-icon": "inline-start"
|
|
103
108
|
}), i("common.remove")]
|
|
104
109
|
})
|
|
105
110
|
] });
|
|
106
|
-
return t === "avatar" ? /* @__PURE__ */
|
|
111
|
+
return t === "avatar" ? /* @__PURE__ */ h("div", {
|
|
107
112
|
className: "flex items-center gap-4",
|
|
108
|
-
children: [/* @__PURE__ */
|
|
113
|
+
children: [/* @__PURE__ */ h("div", {
|
|
109
114
|
className: "relative size-20 shrink-0",
|
|
110
|
-
children: [/* @__PURE__ */
|
|
111
|
-
image:
|
|
115
|
+
children: [/* @__PURE__ */ m(c, {
|
|
116
|
+
image: u ? T : null,
|
|
112
117
|
round: !0,
|
|
113
118
|
emptyLabel: i("avatar.empty"),
|
|
114
119
|
className: "size-full ring-1 ring-foreground/10"
|
|
115
|
-
}), C && /* @__PURE__ */
|
|
120
|
+
}), C && /* @__PURE__ */ m(D, {
|
|
116
121
|
round: !0,
|
|
117
|
-
label: i(
|
|
122
|
+
label: i(o.status === "decoding" ? "progress.decoding" : "common.saving")
|
|
118
123
|
})]
|
|
119
|
-
}), /* @__PURE__ */
|
|
124
|
+
}), /* @__PURE__ */ h("div", {
|
|
120
125
|
className: "grid min-w-0 gap-1",
|
|
121
126
|
children: [
|
|
122
|
-
/* @__PURE__ */
|
|
127
|
+
/* @__PURE__ */ m("div", {
|
|
123
128
|
className: "font-medium",
|
|
124
129
|
children: N
|
|
125
130
|
}),
|
|
126
|
-
/* @__PURE__ */
|
|
131
|
+
/* @__PURE__ */ m("div", {
|
|
127
132
|
className: "text-xs text-muted-foreground",
|
|
128
133
|
children: M
|
|
129
134
|
}),
|
|
130
|
-
/* @__PURE__ */
|
|
135
|
+
/* @__PURE__ */ m("div", {
|
|
131
136
|
className: "mt-1.5 flex flex-wrap gap-2",
|
|
132
137
|
children: P(!1)
|
|
133
138
|
}),
|
|
134
|
-
/* @__PURE__ */
|
|
139
|
+
/* @__PURE__ */ m(l, {})
|
|
135
140
|
]
|
|
136
141
|
})]
|
|
137
|
-
}) : /* @__PURE__ */
|
|
142
|
+
}) : /* @__PURE__ */ h("div", {
|
|
138
143
|
className: "grid gap-2",
|
|
139
144
|
children: [
|
|
140
|
-
/* @__PURE__ */
|
|
141
|
-
className:
|
|
145
|
+
/* @__PURE__ */ h("div", {
|
|
146
|
+
className: g("group/cover relative overflow-hidden rounded-xl ring-1 ring-foreground/10 transition-shadow", E && "ring-2 ring-ring"),
|
|
142
147
|
onDragOver: (e) => {
|
|
143
148
|
e.preventDefault(), w || O(!0);
|
|
144
149
|
},
|
|
145
150
|
onDragLeave: () => O(!1),
|
|
146
151
|
onDrop: j,
|
|
147
152
|
children: [
|
|
148
|
-
/* @__PURE__ */
|
|
149
|
-
image:
|
|
153
|
+
/* @__PURE__ */ m(c, {
|
|
154
|
+
image: u ? T : null,
|
|
150
155
|
aspect: k,
|
|
151
156
|
className: "w-full rounded-none",
|
|
152
|
-
fallback: /* @__PURE__ */
|
|
157
|
+
fallback: /* @__PURE__ */ h("div", {
|
|
153
158
|
"aria-label": i("cover.empty"),
|
|
154
159
|
role: "group",
|
|
155
160
|
className: "absolute inset-0 flex flex-col items-center justify-center gap-1.5 bg-[repeating-linear-gradient(135deg,transparent_0_10px,color-mix(in_oklch,var(--ckui-foreground)_3%,transparent)_10px_20px)] p-4 text-center",
|
|
156
161
|
children: [
|
|
157
|
-
/* @__PURE__ */
|
|
158
|
-
icon:
|
|
162
|
+
/* @__PURE__ */ m(S, {
|
|
163
|
+
icon: b,
|
|
159
164
|
strokeWidth: 1.5,
|
|
160
165
|
className: "size-7 text-muted-foreground"
|
|
161
166
|
}),
|
|
162
|
-
/* @__PURE__ */
|
|
167
|
+
/* @__PURE__ */ m("span", {
|
|
163
168
|
className: "hidden text-xs text-muted-foreground sm:block",
|
|
164
169
|
children: i("cover.drop")
|
|
165
170
|
}),
|
|
166
|
-
/* @__PURE__ */
|
|
171
|
+
/* @__PURE__ */ m("div", {
|
|
167
172
|
className: "mt-1 flex gap-2",
|
|
168
173
|
children: P(!1)
|
|
169
174
|
})
|
|
170
175
|
]
|
|
171
176
|
})
|
|
172
177
|
}),
|
|
173
|
-
C && /* @__PURE__ */
|
|
174
|
-
|
|
178
|
+
C && /* @__PURE__ */ m(D, { label: i(o.status === "decoding" ? "progress.decoding" : "common.saving") }),
|
|
179
|
+
u && /* @__PURE__ */ m("div", {
|
|
175
180
|
className: "absolute right-2 bottom-2 flex gap-2 max-sm:hidden [&_button]:bg-background/80 [&_button]:backdrop-blur-sm",
|
|
176
181
|
children: P(!0)
|
|
177
182
|
})
|
|
178
183
|
]
|
|
179
184
|
}),
|
|
180
|
-
/* @__PURE__ */
|
|
185
|
+
/* @__PURE__ */ h("div", {
|
|
181
186
|
className: "flex flex-wrap items-center justify-between gap-x-3 gap-y-1.5",
|
|
182
|
-
children: [/* @__PURE__ */
|
|
187
|
+
children: [/* @__PURE__ */ h("div", {
|
|
183
188
|
className: "grid min-w-0 gap-0.5 sm:flex sm:flex-1 sm:items-baseline sm:justify-between sm:gap-3",
|
|
184
|
-
children: [/* @__PURE__ */
|
|
189
|
+
children: [/* @__PURE__ */ m("div", {
|
|
185
190
|
className: "font-medium",
|
|
186
191
|
children: N
|
|
187
|
-
}), /* @__PURE__ */
|
|
192
|
+
}), /* @__PURE__ */ m("div", {
|
|
188
193
|
className: "text-xs text-muted-foreground sm:truncate",
|
|
189
194
|
children: M
|
|
190
195
|
})]
|
|
191
|
-
}),
|
|
196
|
+
}), u && /* @__PURE__ */ m("div", {
|
|
192
197
|
className: "flex gap-2 sm:hidden",
|
|
193
198
|
children: P(!1)
|
|
194
199
|
})]
|
|
195
200
|
}),
|
|
196
|
-
/* @__PURE__ */
|
|
201
|
+
/* @__PURE__ */ m(l, {})
|
|
197
202
|
]
|
|
198
203
|
});
|
|
199
204
|
}
|
|
200
|
-
function
|
|
201
|
-
return /* @__PURE__ */
|
|
205
|
+
function D({ round: e, label: t }) {
|
|
206
|
+
return /* @__PURE__ */ m("div", {
|
|
202
207
|
role: "status",
|
|
203
208
|
"aria-label": t,
|
|
204
|
-
className:
|
|
205
|
-
children: /* @__PURE__ */
|
|
206
|
-
icon:
|
|
209
|
+
className: g("absolute inset-0 flex items-center justify-center bg-background/60 backdrop-blur-[1px]", e && "rounded-full"),
|
|
210
|
+
children: /* @__PURE__ */ m(S, {
|
|
211
|
+
icon: x,
|
|
207
212
|
strokeWidth: 2,
|
|
208
213
|
className: "size-5 animate-spin text-foreground"
|
|
209
214
|
})
|
|
210
215
|
});
|
|
211
216
|
}
|
|
212
217
|
//#endregion
|
|
213
|
-
export {
|
|
218
|
+
export { C as AvatarUpload, w as CoverUpload };
|
|
214
219
|
|
|
215
220
|
//# sourceMappingURL=slot-upload.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"slot-upload.js","names":[],"sources":["../../src/components/slot-upload.tsx"],"sourcesContent":["import { ratio, type AspectRatio } from \"../client/aspect.js\";\nimport { Camera01Icon, CropIcon, Delete02Icon, ImageUpload01Icon, Loading03Icon } from \"@hugeicons/core-free-icons\";\nimport { HugeiconsIcon } from \"@hugeicons/react\";\nimport { cn } from \"cn\";\nimport { useState, type DragEvent, type ReactNode } from \"react\";\nimport type { ContentKitClient } from \"../client/client.js\";\nimport { useMessages } from \"../i18n/context.js\";\nimport type { CropSource } from \"../client/image.js\";\nimport { ContentKitUiRoot } from \"../scope.js\";\nimport type { PublicPreset } from \"../client/public.js\";\nimport type { FileInfo, ReadResult, RefBody } from \"../client/generated/wire.js\";\nimport { presetFor } from \"../client/media/rules.js\";\nimport { usePresets } from \"../react/public.js\";\nimport { Button } from \"#ckui/ui/button\";\nimport { SlotEditError, SlotEditor, useSlotEditor } from \"./slot-editor.js\";\nimport { SlotImage } from \"./slot-image.js\";\n\nexport interface SlotUploadProps {\n /** The item that owns the upload. */\n item: RefBody;\n /** The upload path; default \"avatar\" or \"cover\". */\n path?: string;\n /** The public preset showing it. */\n image?: PublicPreset | null;\n client?: ContentKitClient;\n /** An editor read of the item from the host; otherwise fetched. */\n read?: ReadResult | null;\n /** Called with the processed upload after every save, null after a removal. */\n onChange?: (file: FileInfo | null) => void;\n /** The output's \"W:H\"; default the preset's aspect, else \"1:1\" (avatar) or \"3:1\" (cover). */\n aspect?: AspectRatio;\n /** The narrowest edit the server accepts (the preset's Image.MinWidth). */\n minWidth?: number;\n /** \"reject\" refuses animated images before uploading. */\n animation?: \"reject\";\n /** Crops narrower than this many source pixels get a sharpness warning; default 512 (avatar) or 3000 (cover). */\n targetWidth?: number;\n /** `accept` of the file input. Default \"image/*\". */\n accept?: string;\n disabled?: boolean;\n /** Offers Remove once set; default true for avatars, false for covers. */\n removable?: boolean;\n label?: ReactNode;\n hint?: ReactNode;\n className?: string;\n /** Replaces decodeImage (tests). */\n decode?: (file: File) => Promise<CropSource>;\n}\n\ntype Variant = \"avatar\" | \"cover\";\n\n/** Round 1:1 avatar field: image, label, hint, Change / Edit crop, crop dialog, progress, errors. For custom layouts use SlotEditor. */\nexport function AvatarUpload(p: SlotUploadProps) {\n return <SlotUpload {...p} variant=\"avatar\" />;\n}\n\n/** Wide cover field at the preset's aspect (e.g. 3:1), with drop-to-upload. For custom layouts use SlotEditor. */\nexport function CoverUpload(p: SlotUploadProps) {\n return <SlotUpload {...p} variant=\"cover\" />;\n}\n\nfunction SlotUpload({ variant, ...p }: SlotUploadProps & { variant: Variant }) {\n const path = p.path ?? variant;\n const { presets } = usePresets({ client: p.client });\n const rule = presetFor(presets, p.item.kind, path, p.image?.preset);\n return (\n <ContentKitUiRoot className={cn(\"text-sm\", p.className)} data-ckui={variant === \"avatar\" ? \"avatar-upload\" : \"cover-upload\"}>\n <SlotEditor\n item={p.item}\n path={path}\n image={p.image}\n client={p.client}\n read={p.read}\n onChange={p.onChange}\n aspect={p.aspect || p.image?.aspect || rule?.aspect || (variant === \"avatar\" ? \"1:1\" : \"3:1\")}\n minWidth={p.minWidth}\n animation={p.animation}\n targetWidth={p.targetWidth ?? (variant === \"avatar\" ? 512 : 3000)}\n round={variant === \"avatar\"}\n accept={p.accept}\n disabled={p.disabled}\n removable={p.removable ?? variant === \"avatar\"}\n decode={p.decode}\n >\n <SlotUploadLayout {...p} variant={variant} />\n </SlotEditor>\n </ContentKitUiRoot>\n );\n}\n\nfunction SlotUploadLayout({ variant, ...p }: SlotUploadProps & { variant: Variant }) {\n const { t } = useMessages();\n const s = useSlotEditor();\n const { crop, has, busy, disabled } = s;\n const image = { preset: p.image?.preset ?? variant, aspect: s.image.aspect, renditions: s.image.renditions };\n const [dragging, setDragging] = useState(false);\n const aspect = crop.aspect;\n const target = p.targetWidth ?? (variant === \"avatar\" ? 512 : 3000);\n const onDrop = (e: DragEvent) => {\n e.preventDefault();\n setDragging(false);\n const f = [...e.dataTransfer.files].find((f) => f.type.startsWith(\"image/\")) ?? e.dataTransfer.files[0];\n if (f) s.pick(f);\n };\n\n const hint =\n p.hint ?? (variant === \"avatar\" ? t(\"avatar.hint\", { size: target }) : t(\"cover.hint\", { width: target, height: Math.round(target / (ratio(aspect) ?? 3)) }));\n const label = p.label ?? t(variant === \"avatar\" ? \"avatar.label\" : \"cover.label\");\n\n // overlay: buttons on top of the cover image; otherwise a plain row.\n const actions = (overlay: boolean) => (\n <>\n <Button variant={overlay && has ? \"secondary\" : \"outline\"} size=\"sm\" disabled={disabled} onClick={s.choose} data-ckui=\"change\">\n <HugeiconsIcon icon={busy ? Loading03Icon : Camera01Icon} strokeWidth={2} data-icon=\"inline-start\" className={busy ? \"animate-spin\" : undefined} />\n {has ? t(\"common.change\") : t(\"common.upload\")}\n </Button>\n {has && crop.canRecrop && (\n <Button variant={overlay ? \"secondary\" : \"ghost\"} size=\"sm\" disabled={disabled} onClick={s.recrop} data-ckui=\"edit-crop\">\n <HugeiconsIcon icon={CropIcon} strokeWidth={2} data-icon=\"inline-start\" />\n {t(\"common.editCrop\")}\n </Button>\n )}\n {has && s.removable && (\n <Button variant={overlay ? \"secondary\" : \"ghost\"} size=\"sm\" disabled={disabled} onClick={s.remove} data-ckui=\"remove\">\n <HugeiconsIcon icon={Delete02Icon} strokeWidth={2} data-icon=\"inline-start\" />\n {t(\"common.remove\")}\n </Button>\n )}\n </>\n );\n\n return variant === \"avatar\" ? (\n <div className=\"flex items-center gap-4\">\n <div className=\"relative size-20 shrink-0\">\n <SlotImage image={has ? image : null} round emptyLabel={t(\"avatar.empty\")} className=\"size-full ring-1 ring-foreground/10\" />\n {busy && <BusyOverlay round label={t(crop.status === \"decoding\" ? \"progress.decoding\" : \"common.saving\")} />}\n </div>\n <div className=\"grid min-w-0 gap-1\">\n <div className=\"font-medium\">{label}</div>\n <div className=\"text-xs text-muted-foreground\">{hint}</div>\n <div className=\"mt-1.5 flex flex-wrap gap-2\">{actions(false)}</div>\n <SlotEditError />\n </div>\n </div>\n ) : (\n <div className=\"grid gap-2\">\n <div\n className={cn(\n \"group/cover relative overflow-hidden rounded-xl ring-1 ring-foreground/10 transition-shadow\",\n dragging && \"ring-2 ring-ring\",\n )}\n onDragOver={(e) => {\n e.preventDefault();\n if (!disabled) setDragging(true);\n }}\n onDragLeave={() => setDragging(false)}\n onDrop={onDrop}\n >\n <SlotImage\n image={has ? image : null}\n aspect={aspect}\n className=\"w-full rounded-none\"\n fallback={\n <div aria-label={t(\"cover.empty\")} role=\"group\" className=\"absolute inset-0 flex flex-col items-center justify-center gap-1.5 bg-[repeating-linear-gradient(135deg,transparent_0_10px,color-mix(in_oklch,var(--ckui-foreground)_3%,transparent)_10px_20px)] p-4 text-center\">\n <HugeiconsIcon icon={ImageUpload01Icon} strokeWidth={1.5} className=\"size-7 text-muted-foreground\" />\n <span className=\"hidden text-xs text-muted-foreground sm:block\">{t(\"cover.drop\")}</span>\n <div className=\"mt-1 flex gap-2\">{actions(false)}</div>\n </div>\n }\n />\n {busy && <BusyOverlay label={t(crop.status === \"decoding\" ? \"progress.decoding\" : \"common.saving\")} />}\n {has && (\n <div className=\"absolute right-2 bottom-2 flex gap-2 max-sm:hidden [&_button]:bg-background/80 [&_button]:backdrop-blur-sm\">\n {actions(true)}\n </div>\n )}\n </div>\n <div className=\"flex flex-wrap items-center justify-between gap-x-3 gap-y-1.5\">\n <div className=\"grid min-w-0 gap-0.5 sm:flex sm:flex-1 sm:items-baseline sm:justify-between sm:gap-3\">\n <div className=\"font-medium\">{label}</div>\n <div className=\"text-xs text-muted-foreground sm:truncate\">{hint}</div>\n </div>\n {has && <div className=\"flex gap-2 sm:hidden\">{actions(false)}</div>}\n </div>\n <SlotEditError />\n </div>\n );\n}\n\nfunction BusyOverlay({ round, label }: { round?: boolean; label: string }) {\n return (\n <div role=\"status\" aria-label={label} className={cn(\"absolute inset-0 flex items-center justify-center bg-background/60 backdrop-blur-[1px]\", round && \"rounded-full\")}>\n <HugeiconsIcon icon={Loading03Icon} strokeWidth={2} className=\"size-5 animate-spin text-foreground\" />\n </div>\n );\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"slot-upload.js","names":[],"sources":["../../src/components/slot-upload.tsx"],"sourcesContent":["import { ratio, type AspectRatio } from \"../client/aspect.js\";\nimport { Camera01Icon, CropIcon, Delete02Icon, ImageUpload01Icon, Loading03Icon } from \"@hugeicons/core-free-icons\";\nimport { HugeiconsIcon } from \"@hugeicons/react\";\nimport { cn } from \"cn\";\nimport { useState, type DragEvent, type ReactNode } from \"react\";\nimport type { ContentKitClient } from \"../client/client.js\";\nimport { useMessages } from \"../i18n/context.js\";\nimport type { CropSource } from \"../client/image.js\";\nimport { ContentKitUiRoot } from \"../scope.js\";\nimport type { PublicPreset } from \"../client/public.js\";\nimport type { FileInfo, ReadResult, RefBody } from \"../client/generated/wire.js\";\nimport { presetFor } from \"../client/media/rules.js\";\nimport { useKinds } from \"../react/groups.js\";\nimport { usePresets } from \"../react/public.js\";\nimport { useContentScope } from \"../react/use-resource.js\";\nimport { Button } from \"#ckui/ui/button\";\nimport { SlotEditError, SlotEditor, useSlotEditor } from \"./slot-editor.js\";\nimport { SlotImage } from \"./slot-image.js\";\n\nexport interface SlotUploadProps {\n /** The item that owns the upload; an AvatarUpload's default is the viewer's avatar (the content model's `avatars`), on whichever site holds it. */\n item?: RefBody;\n /** The upload path; default \"avatar\" or \"cover\". */\n path?: string;\n /** The public preset showing it. */\n image?: PublicPreset | null;\n client?: ContentKitClient;\n /** An editor read of the item from the host; otherwise fetched. */\n read?: ReadResult | null;\n /** Called with the processed upload after every save, null after a removal. */\n onChange?: (file: FileInfo | null) => void;\n /** The output's \"W:H\"; default the preset's aspect, else \"1:1\" (avatar) or \"3:1\" (cover). */\n aspect?: AspectRatio;\n /** The narrowest edit the server accepts (the preset's Image.MinWidth). */\n minWidth?: number;\n /** \"reject\" refuses animated images before uploading. */\n animation?: \"reject\";\n /** Crops narrower than this many source pixels get a sharpness warning; default 512 (avatar) or 3000 (cover). */\n targetWidth?: number;\n /** `accept` of the file input. Default \"image/*\". */\n accept?: string;\n disabled?: boolean;\n /** Offers Remove once set; default true for avatars, false for covers. */\n removable?: boolean;\n label?: ReactNode;\n hint?: ReactNode;\n className?: string;\n /** Replaces decodeImage (tests). */\n decode?: (file: File) => Promise<CropSource>;\n}\n\ntype Variant = \"avatar\" | \"cover\";\n\n/** Round 1:1 avatar field: image, label, hint, Change / Edit crop, crop dialog, progress, errors. For custom layouts use SlotEditor. */\nexport function AvatarUpload(p: SlotUploadProps) {\n return <SlotUpload {...p} variant=\"avatar\" />;\n}\n\n/** Wide cover field at the preset's aspect (e.g. 3:1), with drop-to-upload. For custom layouts use SlotEditor. */\nexport function CoverUpload(p: SlotUploadProps) {\n return <SlotUpload {...p} variant=\"cover\" />;\n}\n\nfunction SlotUpload({ variant, ...p }: SlotUploadProps & { variant: Variant }) {\n const path = p.path ?? variant;\n const { presets } = usePresets({ client: p.client });\n const { kinds } = useKinds({ client: p.client });\n const { viewer } = useContentScope(p.client);\n // Another site's avatars: the site forwards their writes, and its presets lack the kind.\n const avatars = variant === \"avatar\" ? kinds?.avatars : undefined;\n const item = p.item ?? (avatars && viewer ? { kind: avatars.kind, id: viewer } : undefined);\n const rule = item && (presetFor(presets, item.kind, path, p.image?.preset) ?? (avatars?.kind === item.kind ? avatars : undefined));\n if (!item) return null;\n return (\n <ContentKitUiRoot className={cn(\"text-sm\", p.className)} data-ckui={variant === \"avatar\" ? \"avatar-upload\" : \"cover-upload\"}>\n <SlotEditor\n item={item}\n path={path}\n image={p.image}\n client={p.client}\n read={p.read}\n onChange={p.onChange}\n aspect={p.aspect || p.image?.aspect || rule?.aspect || (variant === \"avatar\" ? \"1:1\" : \"3:1\")}\n minWidth={p.minWidth}\n animation={p.animation}\n targetWidth={p.targetWidth ?? (variant === \"avatar\" ? 512 : 3000)}\n round={variant === \"avatar\"}\n accept={p.accept}\n disabled={p.disabled}\n removable={p.removable ?? variant === \"avatar\"}\n decode={p.decode}\n >\n <SlotUploadLayout {...p} variant={variant} />\n </SlotEditor>\n </ContentKitUiRoot>\n );\n}\n\nfunction SlotUploadLayout({ variant, ...p }: SlotUploadProps & { variant: Variant }) {\n const { t } = useMessages();\n const s = useSlotEditor();\n const { crop, has, busy, disabled } = s;\n const image = { preset: p.image?.preset ?? variant, aspect: s.image.aspect, renditions: s.image.renditions };\n const [dragging, setDragging] = useState(false);\n const aspect = crop.aspect;\n const target = p.targetWidth ?? (variant === \"avatar\" ? 512 : 3000);\n const onDrop = (e: DragEvent) => {\n e.preventDefault();\n setDragging(false);\n const f = [...e.dataTransfer.files].find((f) => f.type.startsWith(\"image/\")) ?? e.dataTransfer.files[0];\n if (f) s.pick(f);\n };\n\n const hint =\n p.hint ?? (variant === \"avatar\" ? t(\"avatar.hint\", { size: target }) : t(\"cover.hint\", { width: target, height: Math.round(target / (ratio(aspect) ?? 3)) }));\n const label = p.label ?? t(variant === \"avatar\" ? \"avatar.label\" : \"cover.label\");\n\n // overlay: buttons on top of the cover image; otherwise a plain row.\n const actions = (overlay: boolean) => (\n <>\n <Button variant={overlay && has ? \"secondary\" : \"outline\"} size=\"sm\" disabled={disabled} onClick={s.choose} data-ckui=\"change\">\n <HugeiconsIcon icon={busy ? Loading03Icon : Camera01Icon} strokeWidth={2} data-icon=\"inline-start\" className={busy ? \"animate-spin\" : undefined} />\n {has ? t(\"common.change\") : t(\"common.upload\")}\n </Button>\n {has && crop.canRecrop && (\n <Button variant={overlay ? \"secondary\" : \"ghost\"} size=\"sm\" disabled={disabled} onClick={s.recrop} data-ckui=\"edit-crop\">\n <HugeiconsIcon icon={CropIcon} strokeWidth={2} data-icon=\"inline-start\" />\n {t(\"common.editCrop\")}\n </Button>\n )}\n {has && s.removable && (\n <Button variant={overlay ? \"secondary\" : \"ghost\"} size=\"sm\" disabled={disabled} onClick={s.remove} data-ckui=\"remove\">\n <HugeiconsIcon icon={Delete02Icon} strokeWidth={2} data-icon=\"inline-start\" />\n {t(\"common.remove\")}\n </Button>\n )}\n </>\n );\n\n return variant === \"avatar\" ? (\n <div className=\"flex items-center gap-4\">\n <div className=\"relative size-20 shrink-0\">\n <SlotImage image={has ? image : null} round emptyLabel={t(\"avatar.empty\")} className=\"size-full ring-1 ring-foreground/10\" />\n {busy && <BusyOverlay round label={t(crop.status === \"decoding\" ? \"progress.decoding\" : \"common.saving\")} />}\n </div>\n <div className=\"grid min-w-0 gap-1\">\n <div className=\"font-medium\">{label}</div>\n <div className=\"text-xs text-muted-foreground\">{hint}</div>\n <div className=\"mt-1.5 flex flex-wrap gap-2\">{actions(false)}</div>\n <SlotEditError />\n </div>\n </div>\n ) : (\n <div className=\"grid gap-2\">\n <div\n className={cn(\n \"group/cover relative overflow-hidden rounded-xl ring-1 ring-foreground/10 transition-shadow\",\n dragging && \"ring-2 ring-ring\",\n )}\n onDragOver={(e) => {\n e.preventDefault();\n if (!disabled) setDragging(true);\n }}\n onDragLeave={() => setDragging(false)}\n onDrop={onDrop}\n >\n <SlotImage\n image={has ? image : null}\n aspect={aspect}\n className=\"w-full rounded-none\"\n fallback={\n <div aria-label={t(\"cover.empty\")} role=\"group\" className=\"absolute inset-0 flex flex-col items-center justify-center gap-1.5 bg-[repeating-linear-gradient(135deg,transparent_0_10px,color-mix(in_oklch,var(--ckui-foreground)_3%,transparent)_10px_20px)] p-4 text-center\">\n <HugeiconsIcon icon={ImageUpload01Icon} strokeWidth={1.5} className=\"size-7 text-muted-foreground\" />\n <span className=\"hidden text-xs text-muted-foreground sm:block\">{t(\"cover.drop\")}</span>\n <div className=\"mt-1 flex gap-2\">{actions(false)}</div>\n </div>\n }\n />\n {busy && <BusyOverlay label={t(crop.status === \"decoding\" ? \"progress.decoding\" : \"common.saving\")} />}\n {has && (\n <div className=\"absolute right-2 bottom-2 flex gap-2 max-sm:hidden [&_button]:bg-background/80 [&_button]:backdrop-blur-sm\">\n {actions(true)}\n </div>\n )}\n </div>\n <div className=\"flex flex-wrap items-center justify-between gap-x-3 gap-y-1.5\">\n <div className=\"grid min-w-0 gap-0.5 sm:flex sm:flex-1 sm:items-baseline sm:justify-between sm:gap-3\">\n <div className=\"font-medium\">{label}</div>\n <div className=\"text-xs text-muted-foreground sm:truncate\">{hint}</div>\n </div>\n {has && <div className=\"flex gap-2 sm:hidden\">{actions(false)}</div>}\n </div>\n <SlotEditError />\n </div>\n );\n}\n\nfunction BusyOverlay({ round, label }: { round?: boolean; label: string }) {\n return (\n <div role=\"status\" aria-label={label} className={cn(\"absolute inset-0 flex items-center justify-center bg-background/60 backdrop-blur-[1px]\", round && \"rounded-full\")}>\n <HugeiconsIcon icon={Loading03Icon} strokeWidth={2} className=\"size-5 animate-spin text-foreground\" />\n </div>\n );\n}\n"],"mappings":";;;;;;;;;;;;;;;;AAsDA,SAAgB,EAAa,GAAoB;CAC/C,OAAO,kBAAC,GAAD;EAAY,GAAI;EAAG,SAAQ;CAAU,CAAA;AAC9C;AAGA,SAAgB,EAAY,GAAoB;CAC9C,OAAO,kBAAC,GAAD;EAAY,GAAI;EAAG,SAAQ;CAAS,CAAA;AAC7C;AAEA,SAAS,EAAW,EAAE,YAAS,GAAG,KAA6C;CAC7E,IAAM,IAAO,EAAE,QAAQ,GACjB,EAAE,eAAY,EAAW,EAAE,QAAQ,EAAE,OAAO,CAAC,GAC7C,EAAE,aAAU,EAAS,EAAE,QAAQ,EAAE,OAAO,CAAC,GACzC,EAAE,cAAW,EAAgB,EAAE,MAAM,GAErC,IAAU,MAAY,WAAW,GAAO,UAAU,KAAA,GAClD,IAAO,EAAE,SAAS,KAAW,IAAS;EAAE,MAAM,EAAQ;EAAM,IAAI;CAAO,IAAI,KAAA,IAC3E,IAAO,MAAS,EAAU,GAAS,EAAK,MAAM,GAAM,EAAE,OAAO,MAAM,MAAM,GAAS,SAAS,EAAK,OAAO,IAAU,KAAA;CAEvH,OADK,IAEH,kBAAC,GAAD;EAAkB,WAAW,EAAG,WAAW,EAAE,SAAS;EAAG,aAAW,MAAY,WAAW,kBAAkB;EAC3G,UAAA,kBAAC,GAAD;GACQ;GACA;GACN,OAAO,EAAE;GACT,QAAQ,EAAE;GACV,MAAM,EAAE;GACR,UAAU,EAAE;GACZ,QAAQ,EAAE,UAAU,EAAE,OAAO,UAAU,GAAM,WAAW,MAAY,WAAW,QAAQ;GACvF,UAAU,EAAE;GACZ,WAAW,EAAE;GACb,aAAa,EAAE,gBAAgB,MAAY,WAAW,MAAM;GAC5D,OAAO,MAAY;GACnB,QAAQ,EAAE;GACV,UAAU,EAAE;GACZ,WAAW,EAAE,aAAa,MAAY;GACtC,QAAQ,EAAE;GAEV,UAAA,kBAAC,GAAD;IAAkB,GAAI;IAAY;GAAU,CAAA;EAClC,CAAA;CACI,CAAA,IAtBF;AAwBpB;AAEA,SAAS,EAAiB,EAAE,YAAS,GAAG,KAA6C;CACnF,IAAM,EAAE,SAAM,EAAY,GACpB,IAAI,EAAc,GAClB,EAAE,SAAM,QAAK,SAAM,gBAAa,GAChC,IAAQ;EAAE,QAAQ,EAAE,OAAO,UAAU;EAAS,QAAQ,EAAE,MAAM;EAAQ,YAAY,EAAE,MAAM;CAAW,GACrG,CAAC,GAAU,KAAe,EAAS,EAAK,GACxC,IAAS,EAAK,QACd,IAAS,EAAE,gBAAgB,MAAY,WAAW,MAAM,MACxD,KAAU,MAAiB;EAE/B,AADA,EAAE,eAAe,GACjB,EAAY,EAAK;EACjB,IAAM,IAAI,CAAC,GAAG,EAAE,aAAa,KAAK,CAAC,CAAC,MAAM,MAAM,EAAE,KAAK,WAAW,QAAQ,CAAC,KAAK,EAAE,aAAa,MAAM;EACrG,AAAI,KAAG,EAAE,KAAK,CAAC;CACjB,GAEM,IACJ,EAAE,SAAS,MAAY,WAAW,EAAE,eAAe,EAAE,MAAM,EAAO,CAAC,IAAI,EAAE,cAAc;EAAE,OAAO;EAAQ,QAAQ,KAAK,MAAM,KAAU,EAAM,CAAM,KAAK,EAAE;CAAE,CAAC,IACvJ,IAAQ,EAAE,SAAS,EAAE,MAAY,WAAW,iBAAiB,aAAa,GAG1E,KAAW,MACf,kBAAA,GAAA,EAAA,UAAA;EACE,kBAAC,GAAD;GAAQ,SAAS,KAAW,IAAM,cAAc;GAAW,MAAK;GAAe;GAAU,SAAS,EAAE;GAAQ,aAAU;GAAtH,UAAA,CACE,kBAAC,GAAD;IAAe,MAAM,IAAO,IAAgB;IAAc,aAAa;IAAG,aAAU;IAAe,WAAW,IAAO,iBAAiB,KAAA;GAAY,CAAA,GAC3I,EAAN,IAAQ,kBAAqB,eAAe,CACvC;;EACP,KAAO,EAAK,aACX,kBAAC,GAAD;GAAQ,SAAS,IAAU,cAAc;GAAS,MAAK;GAAe;GAAU,SAAS,EAAE;GAAQ,aAAU;GAA7G,UAAA,CACE,kBAAC,GAAD;IAAe,MAAM;IAAU,aAAa;IAAG,aAAU;GAAgB,CAAA,GACxE,EAAE,iBAAiB,CACd;;EAET,KAAO,EAAE,aACR,kBAAC,GAAD;GAAQ,SAAS,IAAU,cAAc;GAAS,MAAK;GAAe;GAAU,SAAS,EAAE;GAAQ,aAAU;GAA7G,UAAA,CACE,kBAAC,GAAD;IAAe,MAAM;IAAc,aAAa;IAAG,aAAU;GAAgB,CAAA,GAC5E,EAAE,eAAe,CACZ;;CAEV,EAAA,CAAA;CAGJ,OAAO,MAAY,WACjB,kBAAC,OAAD;EAAK,WAAU;EAAf,UAAA,CACE,kBAAC,OAAD;GAAK,WAAU;GAAf,UAAA,CACE,kBAAC,GAAD;IAAW,OAAO,IAAM,IAAQ;IAAM,OAAA;IAAM,YAAY,EAAE,cAAc;IAAG,WAAU;GAAuC,CAAA,GAC3H,KAAQ,kBAAC,GAAD;IAAa,OAAA;IAAM,OAAO,EAAE,EAAK,WAAW,aAAa,sBAAsB,eAAe;GAAI,CAAA,CACxG;EACL,CAAA,GAAA,kBAAC,OAAD;GAAK,WAAU;GAAf,UAAA;IACE,kBAAC,OAAD;KAAK,WAAU;KAAe,UAAA;IAAW,CAAA;IACzC,kBAAC,OAAD;KAAK,WAAU;KAAiC,UAAA;IAAU,CAAA;IAC1D,kBAAC,OAAD;KAAK,WAAU;KAA+B,UAAA,EAAQ,EAAK;IAAO,CAAA;IAClE,kBAAC,GAAD,CAAgB,CAAA;GACb;EACF,CAAA,CAAA;CAEL,CAAA,IAAA,kBAAC,OAAD;EAAK,WAAU;EAAf,UAAA;GACE,kBAAC,OAAD;IACE,WAAW,EACT,+FACA,KAAY,kBACd;IACA,aAAa,MAAM;KAEjB,AADA,EAAE,eAAe,GACZ,KAAU,EAAY,EAAI;IACjC;IACA,mBAAmB,EAAY,EAAK;IAC5B;IAVV,UAAA;KAYE,kBAAC,GAAD;MACE,OAAO,IAAM,IAAQ;MACb;MACR,WAAU;MACV,UACE,kBAAC,OAAD;OAAK,cAAY,EAAE,aAAa;OAAG,MAAK;OAAQ,WAAU;OAA1D,UAAA;QACE,kBAAC,GAAD;SAAe,MAAM;SAAmB,aAAa;SAAK,WAAU;QAAgC,CAAA;QACpG,kBAAC,QAAD;SAAM,WAAU;SAAiD,UAAA,EAAE,YAAY;QAAQ,CAAA;QACvF,kBAAC,OAAD;SAAK,WAAU;SAAmB,UAAA,EAAQ,EAAK;QAAO,CAAA;OACnD;;KAER,CAAA;KACA,KAAQ,kBAAC,GAAD,EAAa,OAAO,EAAE,EAAK,WAAW,aAAa,sBAAsB,eAAe,EAAI,CAAA;KACpG,KACC,kBAAC,OAAD;MAAK,WAAU;MACZ,UAAA,EAAQ,EAAI;KACV,CAAA;IAEJ;;GACL,kBAAC,OAAD;IAAK,WAAU;IAAf,UAAA,CACE,kBAAC,OAAD;KAAK,WAAU;KAAf,UAAA,CACE,kBAAC,OAAD;MAAK,WAAU;MAAe,UAAA;KAAW,CAAA,GACzC,kBAAC,OAAD;MAAK,WAAU;MAA6C,UAAA;KAAU,CAAA,CACnE;IACJ,CAAA,GAAA,KAAO,kBAAC,OAAD;KAAK,WAAU;KAAwB,UAAA,EAAQ,EAAK;IAAO,CAAA,CAChE;;GACL,kBAAC,GAAD,CAAgB,CAAA;EACb;;AAET;AAEA,SAAS,EAAY,EAAE,UAAO,YAA6C;CACzE,OACE,kBAAC,OAAD;EAAK,MAAK;EAAS,cAAY;EAAO,WAAW,EAAG,0FAA0F,KAAS,cAAc;EACnK,UAAA,kBAAC,GAAD;GAAe,MAAM;GAAe,aAAa;GAAG,WAAU;EAAuC,CAAA;CAClG,CAAA;AAET"}
|