@openrails/contentkit-ui 0.0.0-stage → 0.68.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +425 -2
- package/dist/appearance.d.ts +38 -0
- package/dist/appearance.js +15 -0
- package/dist/appearance.js.map +1 -0
- package/dist/assets/hash.worker-BYfo-7MQ.js.map +1 -0
- package/dist/client/aspect.d.ts +6 -0
- package/dist/client/aspect.js +17 -0
- package/dist/client/aspect.js.map +1 -0
- package/dist/client/client.d.ts +51 -0
- package/dist/client/client.js +35 -0
- package/dist/client/client.js.map +1 -0
- package/dist/client/codes.d.ts +12 -0
- package/dist/client/codes.js +19 -0
- package/dist/client/codes.js.map +1 -0
- package/dist/client/content/bans.d.ts +15 -0
- package/dist/client/content/bans.js +40 -0
- package/dist/client/content/bans.js.map +1 -0
- package/dist/client/content/comments.d.ts +36 -0
- package/dist/client/content/comments.js +93 -0
- package/dist/client/content/comments.js.map +1 -0
- package/dist/client/content/favorites.d.ts +14 -0
- package/dist/client/content/favorites.js +42 -0
- package/dist/client/content/favorites.js.map +1 -0
- package/dist/client/content/moderation.d.ts +18 -0
- package/dist/client/content/moderation.js +37 -0
- package/dist/client/content/moderation.js.map +1 -0
- package/dist/client/content/polls.d.ts +47 -0
- package/dist/client/content/polls.js +148 -0
- package/dist/client/content/polls.js.map +1 -0
- package/dist/client/content/posts.d.ts +44 -0
- package/dist/client/content/posts.js +91 -0
- package/dist/client/content/posts.js.map +1 -0
- package/dist/client/content/reactions.d.ts +12 -0
- package/dist/client/content/reactions.js +36 -0
- package/dist/client/content/reactions.js.map +1 -0
- package/dist/client/content/types.d.ts +91 -0
- package/dist/client/content/types.js +8 -0
- package/dist/client/content/types.js.map +1 -0
- package/dist/client/crop.d.ts +32 -0
- package/dist/client/crop.js +103 -0
- package/dist/client/crop.js.map +1 -0
- package/dist/client/errors.d.ts +54 -0
- package/dist/client/errors.js +80 -0
- package/dist/client/errors.js.map +1 -0
- package/dist/client/gallery.d.ts +43 -0
- package/dist/client/gallery.js +86 -0
- package/dist/client/gallery.js.map +1 -0
- package/dist/client/generated/error-codes.d.ts +5 -0
- package/dist/client/generated/error-codes.js +131 -0
- package/dist/client/generated/error-codes.js.map +1 -0
- package/dist/client/generated/routes.d.ts +1086 -0
- package/dist/client/generated/routes.js +1400 -0
- package/dist/client/generated/routes.js.map +1 -0
- package/dist/client/generated/wire.d.ts +630 -0
- package/dist/client/generated/wire.js +6 -0
- package/dist/client/generated/wire.js.map +1 -0
- package/dist/client/http.d.ts +79 -0
- package/dist/client/http.js +74 -0
- package/dist/client/http.js.map +1 -0
- package/dist/client/image.d.ts +24 -0
- package/dist/client/image.js +65 -0
- package/dist/client/image.js.map +1 -0
- package/dist/client/index.d.ts +33 -0
- package/dist/client/media/api.d.ts +36 -0
- package/dist/client/media/api.js +61 -0
- package/dist/client/media/api.js.map +1 -0
- package/dist/client/media/client.d.ts +247 -0
- package/dist/client/media/client.js +407 -0
- package/dist/client/media/client.js.map +1 -0
- package/dist/client/media/encode.d.ts +3 -0
- package/dist/client/media/encode.js +8 -0
- package/dist/client/media/encode.js.map +1 -0
- package/dist/client/media/hash-stream.d.ts +6 -0
- package/dist/client/media/hash-stream.js +16 -0
- package/dist/client/media/hash-stream.js.map +1 -0
- package/dist/client/media/hash.d.ts +12 -0
- package/dist/client/media/hash.js +48 -0
- package/dist/client/media/hash.js.map +1 -0
- package/dist/client/media/hash.worker-inline.js +18 -0
- package/dist/client/media/hash.worker-inline.js.map +1 -0
- package/dist/client/media/pacer.d.ts +21 -0
- package/dist/client/media/pacer.js +25 -0
- package/dist/client/media/pacer.js.map +1 -0
- package/dist/client/media/queue.d.ts +112 -0
- package/dist/client/media/queue.js +274 -0
- package/dist/client/media/queue.js.map +1 -0
- package/dist/client/media/ref.d.ts +6 -0
- package/dist/client/media/ref.js +10 -0
- package/dist/client/media/ref.js.map +1 -0
- package/dist/client/media/rules.d.ts +52 -0
- package/dist/client/media/rules.js +139 -0
- package/dist/client/media/rules.js.map +1 -0
- package/dist/client/media/transport.d.ts +13 -0
- package/dist/client/media/transport.js +33 -0
- package/dist/client/media/transport.js.map +1 -0
- package/dist/client/media/windows.d.ts +15 -0
- package/dist/client/media/windows.js +39 -0
- package/dist/client/media/windows.js.map +1 -0
- package/dist/client/playback.d.ts +200 -0
- package/dist/client/playback.js +142 -0
- package/dist/client/playback.js.map +1 -0
- package/dist/client/player.d.ts +102 -0
- package/dist/client/player.js +155 -0
- package/dist/client/player.js.map +1 -0
- package/dist/client/public.d.ts +25 -0
- package/dist/client/public.js +18 -0
- package/dist/client/public.js.map +1 -0
- package/dist/client/rendition.d.ts +19 -0
- package/dist/client/rendition.js +16 -0
- package/dist/client/rendition.js.map +1 -0
- package/dist/client/route.d.ts +39 -0
- package/dist/client/route.js +31 -0
- package/dist/client/route.js.map +1 -0
- package/dist/client/taxonomy.d.ts +30 -0
- package/dist/client/taxonomy.js +77 -0
- package/dist/client/taxonomy.js.map +1 -0
- package/dist/client.js +33 -0
- package/dist/components/encode-progress.d.ts +15 -0
- package/dist/components/encode-progress.js +49 -0
- package/dist/components/encode-progress.js.map +1 -0
- package/dist/components/hover-preview.d.ts +29 -0
- package/dist/components/hover-preview.js +49 -0
- package/dist/components/hover-preview.js.map +1 -0
- package/dist/components/image-crop-dialog.d.ts +48 -0
- package/dist/components/image-crop-dialog.js +359 -0
- package/dist/components/image-crop-dialog.js.map +1 -0
- package/dist/components/lazy-mount.d.ts +10 -0
- package/dist/components/lazy-mount.js +22 -0
- package/dist/components/lazy-mount.js.map +1 -0
- package/dist/components/media-folder-editor.d.ts +45 -0
- package/dist/components/media-folder-editor.js +564 -0
- package/dist/components/media-folder-editor.js.map +1 -0
- package/dist/components/media-gallery.d.ts +54 -0
- package/dist/components/media-gallery.js +597 -0
- package/dist/components/media-gallery.js.map +1 -0
- package/dist/components/media-readiness-notice.d.ts +24 -0
- package/dist/components/media-readiness-notice.js +61 -0
- package/dist/components/media-readiness-notice.js.map +1 -0
- package/dist/components/player-controls.d.ts +71 -0
- package/dist/components/player-controls.js +264 -0
- package/dist/components/player-controls.js.map +1 -0
- package/dist/components/progress.d.ts +5 -0
- package/dist/components/progress.js +14 -0
- package/dist/components/progress.js.map +1 -0
- package/dist/components/rendition-img.d.ts +34 -0
- package/dist/components/rendition-img.js +78 -0
- package/dist/components/rendition-img.js.map +1 -0
- package/dist/components/slot-editor.d.ts +95 -0
- package/dist/components/slot-editor.js +182 -0
- package/dist/components/slot-editor.js.map +1 -0
- package/dist/components/slot-image.d.ts +23 -0
- package/dist/components/slot-image.js +48 -0
- package/dist/components/slot-image.js.map +1 -0
- package/dist/components/slot-upload.d.ts +41 -0
- package/dist/components/slot-upload.js +213 -0
- package/dist/components/slot-upload.js.map +1 -0
- package/dist/components/social/bans.d.ts +42 -0
- package/dist/components/social/bans.js +300 -0
- package/dist/components/social/bans.js.map +1 -0
- package/dist/components/social/comments.d.ts +42 -0
- package/dist/components/social/comments.js +517 -0
- package/dist/components/social/comments.js.map +1 -0
- package/dist/components/social/engagement.d.ts +45 -0
- package/dist/components/social/engagement.js +129 -0
- package/dist/components/social/engagement.js.map +1 -0
- package/dist/components/social/index.d.ts +6 -0
- package/dist/components/social/moderation.d.ts +32 -0
- package/dist/components/social/moderation.js +383 -0
- package/dist/components/social/moderation.js.map +1 -0
- package/dist/components/social/parts.d.ts +50 -0
- package/dist/components/social/parts.js +106 -0
- package/dist/components/social/parts.js.map +1 -0
- package/dist/components/social/poll-editor.d.ts +34 -0
- package/dist/components/social/poll-editor.js +567 -0
- package/dist/components/social/poll-editor.js.map +1 -0
- package/dist/components/social/poll.d.ts +30 -0
- package/dist/components/social/poll.js +252 -0
- package/dist/components/social/poll.js.map +1 -0
- package/dist/components/sortable-list.d.ts +29 -0
- package/dist/components/sortable-list.js +121 -0
- package/dist/components/sortable-list.js.map +1 -0
- package/dist/components/video-mini-player.d.ts +35 -0
- package/dist/components/video-mini-player.js +236 -0
- package/dist/components/video-mini-player.js.map +1 -0
- package/dist/components/video-player.d.ts +146 -0
- package/dist/components/video-player.js +630 -0
- package/dist/components/video-player.js.map +1 -0
- package/dist/components/video-poster-picker.d.ts +59 -0
- package/dist/components/video-poster-picker.js +335 -0
- package/dist/components/video-poster-picker.js.map +1 -0
- package/dist/components/video-poster.d.ts +24 -0
- package/dist/components/video-poster.js +46 -0
- package/dist/components/video-poster.js.map +1 -0
- package/dist/i18n/context.d.ts +4 -0
- package/dist/i18n/context.js +11 -0
- package/dist/i18n/context.js.map +1 -0
- package/dist/i18n/messages.d.ts +40 -0
- package/dist/i18n/messages.js +94 -0
- package/dist/i18n/messages.js.map +1 -0
- package/dist/index.d.ts +23 -0
- package/dist/index.js +41 -0
- package/dist/locales/de.d.ts +2 -0
- package/dist/locales/de.js +271 -0
- package/dist/locales/de.js.map +1 -0
- package/dist/locales/en.d.ts +457 -0
- package/dist/locales/en.js +271 -0
- package/dist/locales/en.js.map +1 -0
- package/dist/locales/es.d.ts +2 -0
- package/dist/locales/es.js +271 -0
- package/dist/locales/es.js.map +1 -0
- package/dist/locales/ja.d.ts +2 -0
- package/dist/locales/ja.js +271 -0
- package/dist/locales/ja.js.map +1 -0
- package/dist/locales/ko.d.ts +2 -0
- package/dist/locales/ko.js +271 -0
- package/dist/locales/ko.js.map +1 -0
- package/dist/locales/social/de.d.ts +2 -0
- package/dist/locales/social/de.js +198 -0
- package/dist/locales/social/de.js.map +1 -0
- package/dist/locales/social/en.d.ts +195 -0
- package/dist/locales/social/en.js +198 -0
- package/dist/locales/social/en.js.map +1 -0
- package/dist/locales/social/es.d.ts +2 -0
- package/dist/locales/social/es.js +198 -0
- package/dist/locales/social/es.js.map +1 -0
- package/dist/locales/social/ja.d.ts +2 -0
- package/dist/locales/social/ja.js +198 -0
- package/dist/locales/social/ja.js.map +1 -0
- package/dist/locales/social/ko.d.ts +2 -0
- package/dist/locales/social/ko.js +198 -0
- package/dist/locales/social/ko.js.map +1 -0
- package/dist/locales/social/zh.d.ts +2 -0
- package/dist/locales/social/zh.js +198 -0
- package/dist/locales/social/zh.js.map +1 -0
- package/dist/locales/zh.d.ts +2 -0
- package/dist/locales/zh.js +271 -0
- package/dist/locales/zh.js.map +1 -0
- package/dist/provider.d.ts +22 -0
- package/dist/provider.js +59 -0
- package/dist/provider.js.map +1 -0
- package/dist/react/canonical.d.ts +33 -0
- package/dist/react/canonical.js +88 -0
- package/dist/react/canonical.js.map +1 -0
- package/dist/react/comments.d.ts +82 -0
- package/dist/react/comments.js +147 -0
- package/dist/react/comments.js.map +1 -0
- package/dist/react/config.d.ts +13 -0
- package/dist/react/config.js +14 -0
- package/dist/react/config.js.map +1 -0
- package/dist/react/context.d.ts +48 -0
- package/dist/react/context.js +37 -0
- package/dist/react/context.js.map +1 -0
- package/dist/react/crop.d.ts +49 -0
- package/dist/react/crop.js +107 -0
- package/dist/react/crop.js.map +1 -0
- package/dist/react/engagement.d.ts +38 -0
- package/dist/react/engagement.js +88 -0
- package/dist/react/engagement.js.map +1 -0
- package/dist/react/folder.d.ts +83 -0
- package/dist/react/folder.js +183 -0
- package/dist/react/folder.js.map +1 -0
- package/dist/react/gallery.d.ts +140 -0
- package/dist/react/gallery.js +477 -0
- package/dist/react/gallery.js.map +1 -0
- package/dist/react/index.d.ts +21 -0
- package/dist/react/inline-preview.d.ts +24 -0
- package/dist/react/inline-preview.js +76 -0
- package/dist/react/inline-preview.js.map +1 -0
- package/dist/react/player.d.ts +70 -0
- package/dist/react/player.js +214 -0
- package/dist/react/player.js.map +1 -0
- package/dist/react/polls.d.ts +74 -0
- package/dist/react/polls.js +176 -0
- package/dist/react/polls.js.map +1 -0
- package/dist/react/posts.d.ts +59 -0
- package/dist/react/posts.js +149 -0
- package/dist/react/posts.js.map +1 -0
- package/dist/react/provider.d.ts +23 -0
- package/dist/react/provider.js +35 -0
- package/dist/react/provider.js.map +1 -0
- package/dist/react/public.d.ts +39 -0
- package/dist/react/public.js +70 -0
- package/dist/react/public.js.map +1 -0
- package/dist/react/read.d.ts +52 -0
- package/dist/react/read.js +143 -0
- package/dist/react/read.js.map +1 -0
- package/dist/react/resources.d.ts +70 -0
- package/dist/react/resources.js +247 -0
- package/dist/react/resources.js.map +1 -0
- package/dist/react/slot.d.ts +102 -0
- package/dist/react/slot.js +181 -0
- package/dist/react/slot.js.map +1 -0
- package/dist/react/store.d.ts +51 -0
- package/dist/react/store.js +164 -0
- package/dist/react/store.js.map +1 -0
- package/dist/react/upload.d.ts +85 -0
- package/dist/react/upload.js +150 -0
- package/dist/react/upload.js.map +1 -0
- package/dist/react/use-resource.d.ts +43 -0
- package/dist/react/use-resource.js +66 -0
- package/dist/react/use-resource.js.map +1 -0
- package/dist/react/video.d.ts +118 -0
- package/dist/react/video.js +184 -0
- package/dist/react/video.js.map +1 -0
- package/dist/react/viewport.d.ts +19 -0
- package/dist/react/viewport.js +30 -0
- package/dist/react/viewport.js.map +1 -0
- package/dist/react.js +21 -0
- package/dist/scope.d.ts +14 -0
- package/dist/scope.js +30 -0
- package/dist/scope.js.map +1 -0
- package/dist/styles.css +3 -0
- package/dist/ui/alert-dialog.d.ts +18 -0
- package/dist/ui/alert-dialog.js +86 -0
- package/dist/ui/alert-dialog.js.map +1 -0
- package/dist/ui/alert.d.ts +10 -0
- package/dist/ui/alert.js +38 -0
- package/dist/ui/alert.js.map +1 -0
- package/dist/ui/avatar.d.ts +11 -0
- package/dist/ui/avatar.js +31 -0
- package/dist/ui/avatar.js.map +1 -0
- package/dist/ui/badge.d.ts +7 -0
- package/dist/ui/badge.js +31 -0
- package/dist/ui/badge.js.map +1 -0
- package/dist/ui/button.d.ts +8 -0
- package/dist/ui/button.js +46 -0
- package/dist/ui/button.js.map +1 -0
- package/dist/ui/dialog.d.ts +17 -0
- package/dist/ui/dialog.js +91 -0
- package/dist/ui/dialog.js.map +1 -0
- package/dist/ui/dropdown-menu.d.ts +15 -0
- package/dist/ui/dropdown-menu.js +105 -0
- package/dist/ui/dropdown-menu.js.map +1 -0
- package/dist/ui/input.d.ts +3 -0
- package/dist/ui/input.js +17 -0
- package/dist/ui/input.js.map +1 -0
- package/dist/ui/label.d.ts +3 -0
- package/dist/ui/label.js +15 -0
- package/dist/ui/label.js.map +1 -0
- package/dist/ui/progress.d.ts +7 -0
- package/dist/ui/progress.js +31 -0
- package/dist/ui/progress.js.map +1 -0
- package/dist/ui/select.d.ts +15 -0
- package/dist/ui/select.js +98 -0
- package/dist/ui/select.js.map +1 -0
- package/dist/ui/skeleton.d.ts +2 -0
- package/dist/ui/skeleton.js +14 -0
- package/dist/ui/skeleton.js.map +1 -0
- package/dist/ui/slider.d.ts +3 -0
- package/dist/ui/slider.js +35 -0
- package/dist/ui/slider.js.map +1 -0
- package/dist/ui/switch.d.ts +5 -0
- package/dist/ui/switch.js +20 -0
- package/dist/ui/switch.js.map +1 -0
- package/dist/ui/tabs.d.ts +10 -0
- package/dist/ui/tabs.js +47 -0
- package/dist/ui/tabs.js.map +1 -0
- package/dist/ui/textarea.d.ts +3 -0
- package/dist/ui/textarea.js +15 -0
- package/dist/ui/textarea.js.map +1 -0
- package/dist/ui/toggle-group.d.ts +5 -0
- package/dist/ui/toggle-group.js +23 -0
- package/dist/ui/toggle-group.js.map +1 -0
- package/dist/urls/index.d.ts +100 -0
- package/dist/urls.js +118 -0
- package/dist/urls.js.map +1 -0
- package/package.json +118 -3
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { ContentKitClient } from '../../client/client.js';
|
|
2
|
+
import { ReactionCounts, RefBody } from '../../client/generated/wire.js';
|
|
3
|
+
import { ContentKitUiAppearance } from '../../appearance.js';
|
|
4
|
+
import { ContentKitErrorHandler } from '../../react/context.js';
|
|
5
|
+
export interface ReactionButtonsProps {
|
|
6
|
+
item: RefBody;
|
|
7
|
+
/** Counts the host already has, used instead of reading them. */
|
|
8
|
+
counts?: ReactionCounts;
|
|
9
|
+
/** Offer dislike too. Default true. */
|
|
10
|
+
dislike?: boolean;
|
|
11
|
+
/** Asks a signed-out visitor to sign in where the server takes no anonymous reactions (default the provider's). */
|
|
12
|
+
onSignIn?: () => void;
|
|
13
|
+
size?: "sm" | "default";
|
|
14
|
+
client?: ContentKitClient;
|
|
15
|
+
onError?: ContentKitErrorHandler;
|
|
16
|
+
className?: string;
|
|
17
|
+
appearance?: ContentKitUiAppearance;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Like and dislike toggles with counts: they change at once and roll back if
|
|
21
|
+
* the server refuses. Signed out, they react anonymously where the server
|
|
22
|
+
* allows it (`Config.anonymous.reactions`) and ask to sign in elsewhere.
|
|
23
|
+
*/
|
|
24
|
+
export declare function ReactionButtons({ item, counts: initial, dislike, onSignIn, size, client, onError, className, appearance }: ReactionButtonsProps): import('react').JSX.Element;
|
|
25
|
+
export interface FavoriteButtonProps {
|
|
26
|
+
item: RefBody;
|
|
27
|
+
/** Whether it is favorited and the item's count, as the host already has them: both given, nothing is read. */
|
|
28
|
+
favorited?: boolean;
|
|
29
|
+
count?: number;
|
|
30
|
+
/** Show the item's favorite count. Default true. */
|
|
31
|
+
showCount?: boolean;
|
|
32
|
+
/** Show the label beside the icon. Default true. */
|
|
33
|
+
label?: boolean;
|
|
34
|
+
/** Asks a signed-out visitor to sign in (default the provider's). */
|
|
35
|
+
onSignIn?: () => void;
|
|
36
|
+
/** After each saved change. */
|
|
37
|
+
onChange?: (favorited: boolean) => void;
|
|
38
|
+
size?: "sm" | "default";
|
|
39
|
+
client?: ContentKitClient;
|
|
40
|
+
onError?: ContentKitErrorHandler;
|
|
41
|
+
className?: string;
|
|
42
|
+
appearance?: ContentKitUiAppearance;
|
|
43
|
+
}
|
|
44
|
+
/** Adds the item to the signed-in visitor's favorites, or removes it, with the server's count; changes at once and rolls back if refused. */
|
|
45
|
+
export declare function FavoriteButton({ item, favorited, count, showCount, label, onSignIn, onChange, size, client, onError, className, appearance }: FavoriteButtonProps): import('react').JSX.Element;
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
import { toContentKitError as e } from "../../client/errors.js";
|
|
2
|
+
import { useMessages as t } from "../../i18n/context.js";
|
|
3
|
+
import { ContentKitUiRoot as n } from "../../scope.js";
|
|
4
|
+
import { ContentKitContext as r, useErrorReporter as i } from "../../react/context.js";
|
|
5
|
+
import { Button as a } from "../../ui/button.js";
|
|
6
|
+
import { useContentConfig as o } from "../../react/config.js";
|
|
7
|
+
import { contentError as s } from "./parts.js";
|
|
8
|
+
import { useFavorite as c, useReaction as l } from "../../react/engagement.js";
|
|
9
|
+
import { useContext as u, useState as d } from "react";
|
|
10
|
+
import { jsx as f, jsxs as p } from "react/jsx-runtime";
|
|
11
|
+
import { cn as m } from "cn";
|
|
12
|
+
import { FavouriteIcon as h, ThumbsDownIcon as g, ThumbsUpIcon as _ } from "@hugeicons/core-free-icons";
|
|
13
|
+
import { HugeiconsIcon as v } from "@hugeicons/react";
|
|
14
|
+
//#region src/components/social/engagement.tsx
|
|
15
|
+
var y = (e, t) => new Intl.NumberFormat(t, {
|
|
16
|
+
notation: "compact",
|
|
17
|
+
maximumFractionDigits: 1
|
|
18
|
+
}).format(e);
|
|
19
|
+
function b({ item: c, counts: h, dislike: b = !0, onSignIn: x, size: S = "default", client: C, onError: w, className: T, appearance: E }) {
|
|
20
|
+
let D = t(), { t: O } = D, k = l(c, {
|
|
21
|
+
initial: h,
|
|
22
|
+
client: C
|
|
23
|
+
}), A = u(r), { config: j } = o({ client: C }), M = x ?? A?.onSignIn, N = A?.viewer === null && j?.anonymous.reactions === !1, P = i(w), [F, I] = d(null), L = (t) => {
|
|
24
|
+
if (N) return M?.();
|
|
25
|
+
I(null), k.toggle(t).catch((t) => {
|
|
26
|
+
let n = e(t);
|
|
27
|
+
if (n.code === "unauthorized" && M) return M();
|
|
28
|
+
I(n), P(n, "reaction.save");
|
|
29
|
+
});
|
|
30
|
+
}, R = S === "sm" ? "sm" : "default", z = N ? O("reactions.signIn") : void 0, B = N && !M;
|
|
31
|
+
return /* @__PURE__ */ p(n, {
|
|
32
|
+
appearance: E,
|
|
33
|
+
className: m("inline-flex flex-wrap items-center gap-1 text-sm", T),
|
|
34
|
+
"data-ckui": "reaction-buttons",
|
|
35
|
+
children: [/* @__PURE__ */ p("div", {
|
|
36
|
+
className: "inline-flex items-center gap-1",
|
|
37
|
+
children: [/* @__PURE__ */ p(a, {
|
|
38
|
+
variant: k.counts.mine === 1 ? "secondary" : "ghost",
|
|
39
|
+
size: R,
|
|
40
|
+
"aria-pressed": k.counts.mine === 1,
|
|
41
|
+
"aria-label": O("reactions.like"),
|
|
42
|
+
title: z,
|
|
43
|
+
disabled: B,
|
|
44
|
+
onClick: () => L(1),
|
|
45
|
+
children: [/* @__PURE__ */ f(v, {
|
|
46
|
+
icon: _,
|
|
47
|
+
strokeWidth: 2
|
|
48
|
+
}), /* @__PURE__ */ f("span", { children: y(k.counts.likes, D.language) })]
|
|
49
|
+
}), b && /* @__PURE__ */ p(a, {
|
|
50
|
+
variant: k.counts.mine === -1 ? "secondary" : "ghost",
|
|
51
|
+
size: R,
|
|
52
|
+
"aria-pressed": k.counts.mine === -1,
|
|
53
|
+
"aria-label": O("reactions.dislike"),
|
|
54
|
+
title: z,
|
|
55
|
+
disabled: B,
|
|
56
|
+
onClick: () => L(-1),
|
|
57
|
+
children: [/* @__PURE__ */ f(v, {
|
|
58
|
+
icon: g,
|
|
59
|
+
strokeWidth: 2
|
|
60
|
+
}), /* @__PURE__ */ f("span", { children: y(k.counts.dislikes, D.language) })]
|
|
61
|
+
})]
|
|
62
|
+
}), F && /* @__PURE__ */ f("span", {
|
|
63
|
+
role: "alert",
|
|
64
|
+
className: "text-xs text-destructive",
|
|
65
|
+
children: F.code === "rate_limited" || F.code === "forbidden" ? s(D, F) : O("reactions.failed")
|
|
66
|
+
})]
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
function x({ item: o, favorited: l, count: g, showCount: _ = !0, label: b = !0, onSignIn: x, onChange: S, size: C = "default", client: w, onError: T, className: E, appearance: D }) {
|
|
70
|
+
let O = t(), { t: k } = O, A = u(r), j = c(o, {
|
|
71
|
+
initial: l !== void 0 && g !== void 0 ? {
|
|
72
|
+
favorited: l,
|
|
73
|
+
count: g
|
|
74
|
+
} : void 0,
|
|
75
|
+
client: w
|
|
76
|
+
}), M = x ?? A?.onSignIn, N = i(T), [P, F] = d(null), [I, L] = d(""), R = _ ? j.count : void 0, z = () => {
|
|
77
|
+
if (A?.viewer === null) return M?.();
|
|
78
|
+
F(null);
|
|
79
|
+
let t = !j.favorited;
|
|
80
|
+
j.set(t).then(() => {
|
|
81
|
+
L(k(t ? "favorites.added" : "favorites.removed")), S?.(t);
|
|
82
|
+
}, (t) => {
|
|
83
|
+
let n = e(t);
|
|
84
|
+
if (n.code === "unauthorized" && M) return M();
|
|
85
|
+
F(n), N(n, "favorite.save");
|
|
86
|
+
});
|
|
87
|
+
}, B = k(A?.viewer === null && M ? "favorites.signIn" : j.favorited ? "favorites.remove" : "favorites.add");
|
|
88
|
+
return /* @__PURE__ */ p(n, {
|
|
89
|
+
appearance: D,
|
|
90
|
+
className: m("inline-flex flex-wrap items-center gap-2 text-sm", E),
|
|
91
|
+
"data-ckui": "favorite-button",
|
|
92
|
+
children: [
|
|
93
|
+
/* @__PURE__ */ p(a, {
|
|
94
|
+
variant: j.favorited ? "secondary" : "outline",
|
|
95
|
+
size: b ? C === "sm" ? "sm" : "default" : C === "sm" ? "icon-sm" : "icon",
|
|
96
|
+
"aria-pressed": j.favorited,
|
|
97
|
+
"aria-label": b ? void 0 : B,
|
|
98
|
+
disabled: j.pending,
|
|
99
|
+
onClick: z,
|
|
100
|
+
children: [
|
|
101
|
+
/* @__PURE__ */ f(v, {
|
|
102
|
+
icon: h,
|
|
103
|
+
strokeWidth: 2,
|
|
104
|
+
className: m(j.favorited && "fill-current text-destructive")
|
|
105
|
+
}),
|
|
106
|
+
b && /* @__PURE__ */ f("span", { children: B }),
|
|
107
|
+
R !== void 0 && /* @__PURE__ */ f("span", {
|
|
108
|
+
className: "tabular-nums text-muted-foreground",
|
|
109
|
+
children: y(Math.max(0, R), O.language)
|
|
110
|
+
})
|
|
111
|
+
]
|
|
112
|
+
}),
|
|
113
|
+
/* @__PURE__ */ f("span", {
|
|
114
|
+
className: "sr-only",
|
|
115
|
+
role: "status",
|
|
116
|
+
children: I
|
|
117
|
+
}),
|
|
118
|
+
P && /* @__PURE__ */ f("span", {
|
|
119
|
+
role: "alert",
|
|
120
|
+
className: "text-xs text-destructive",
|
|
121
|
+
children: s(O, P)
|
|
122
|
+
})
|
|
123
|
+
]
|
|
124
|
+
});
|
|
125
|
+
}
|
|
126
|
+
//#endregion
|
|
127
|
+
export { x as FavoriteButton, b as ReactionButtons };
|
|
128
|
+
|
|
129
|
+
//# sourceMappingURL=engagement.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"engagement.js","names":[],"sources":["../../../src/components/social/engagement.tsx"],"sourcesContent":["import { FavouriteIcon, ThumbsDownIcon, ThumbsUpIcon } from \"@hugeicons/core-free-icons\";\nimport { HugeiconsIcon } from \"@hugeicons/react\";\nimport { cn } from \"cn\";\nimport { useContext, useState } from \"react\";\nimport type { ContentKitClient } from \"../../client/client.js\";\nimport type { ContentKitError } from \"../../client/errors.js\";\nimport { toContentKitError } from \"../../client/errors.js\";\nimport type { ReactionCounts, RefBody } from \"../../client/generated/wire.js\";\nimport type { ContentKitUiAppearance } from \"../../appearance.js\";\nimport { useMessages } from \"../../i18n/context.js\";\nimport { ContentKitContext, useErrorReporter, type ContentKitErrorHandler } from \"../../react/context.js\";\nimport { useContentConfig } from \"../../react/config.js\";\nimport { useFavorite, useReaction } from \"../../react/engagement.js\";\nimport { ContentKitUiRoot } from \"../../scope.js\";\nimport { Button } from \"#ckui/ui/button\";\nimport { contentError } from \"./parts.js\";\n\n\nconst compact = (n: number, language?: string) => new Intl.NumberFormat(language, { notation: \"compact\", maximumFractionDigits: 1 }).format(n);\n\nexport interface ReactionButtonsProps {\n item: RefBody;\n /** Counts the host already has, used instead of reading them. */\n counts?: ReactionCounts;\n /** Offer dislike too. Default true. */\n dislike?: boolean;\n /** Asks a signed-out visitor to sign in where the server takes no anonymous reactions (default the provider's). */\n onSignIn?: () => void;\n size?: \"sm\" | \"default\";\n client?: ContentKitClient;\n onError?: ContentKitErrorHandler;\n className?: string;\n appearance?: ContentKitUiAppearance;\n}\n\n/**\n * Like and dislike toggles with counts: they change at once and roll back if\n * the server refuses. Signed out, they react anonymously where the server\n * allows it (`Config.anonymous.reactions`) and ask to sign in elsewhere.\n */\nexport function ReactionButtons({ item, counts: initial, dislike = true, onSignIn, size = \"default\", client, onError, className, appearance }: ReactionButtonsProps) {\n const m = useMessages();\n const { t } = m;\n const r = useReaction(item, { initial, client });\n const ctx = useContext(ContentKitContext);\n const { config } = useContentConfig({ client });\n const signIn = onSignIn ?? ctx?.onSignIn;\n // Signed out where the server takes no anonymous reactions.\n const mustSignIn = ctx?.viewer === null && config?.anonymous.reactions === false;\n const report = useErrorReporter(onError);\n const [error, setError] = useState<ContentKitError | null>(null);\n const toggle = (v: 1 | -1) => {\n if (mustSignIn) return signIn?.();\n setError(null);\n r.toggle(v).catch((e) => {\n const err = toContentKitError(e);\n if (err.code === \"unauthorized\" && signIn) return signIn();\n setError(err);\n report(err, \"reaction.save\");\n });\n };\n const btn = size === \"sm\" ? \"sm\" : \"default\";\n const hint = mustSignIn ? t(\"reactions.signIn\") : undefined;\n const disabled = mustSignIn && !signIn;\n return (\n <ContentKitUiRoot appearance={appearance} className={cn(\"inline-flex flex-wrap items-center gap-1 text-sm\", className)} data-ckui=\"reaction-buttons\">\n <div className=\"inline-flex items-center gap-1\">\n <Button variant={r.counts.mine === 1 ? \"secondary\" : \"ghost\"} size={btn} aria-pressed={r.counts.mine === 1} aria-label={t(\"reactions.like\")} title={hint} disabled={disabled} onClick={() => toggle(1)}>\n <HugeiconsIcon icon={ThumbsUpIcon} strokeWidth={2} />\n <span>{compact(r.counts.likes, m.language)}</span>\n </Button>\n {dislike && (\n <Button variant={r.counts.mine === -1 ? \"secondary\" : \"ghost\"} size={btn} aria-pressed={r.counts.mine === -1} aria-label={t(\"reactions.dislike\")} title={hint} disabled={disabled} onClick={() => toggle(-1)}>\n <HugeiconsIcon icon={ThumbsDownIcon} strokeWidth={2} />\n <span>{compact(r.counts.dislikes, m.language)}</span>\n </Button>\n )}\n </div>\n {error && (\n <span role=\"alert\" className=\"text-xs text-destructive\">\n {error.code === \"rate_limited\" || error.code === \"forbidden\" ? contentError(m, error) : t(\"reactions.failed\")}\n </span>\n )}\n </ContentKitUiRoot>\n );\n}\n\nexport interface FavoriteButtonProps {\n item: RefBody;\n /** Whether it is favorited and the item's count, as the host already has them: both given, nothing is read. */\n favorited?: boolean;\n count?: number;\n /** Show the item's favorite count. Default true. */\n showCount?: boolean;\n /** Show the label beside the icon. Default true. */\n label?: boolean;\n /** Asks a signed-out visitor to sign in (default the provider's). */\n onSignIn?: () => void;\n /** After each saved change. */\n onChange?: (favorited: boolean) => void;\n size?: \"sm\" | \"default\";\n client?: ContentKitClient;\n onError?: ContentKitErrorHandler;\n className?: string;\n appearance?: ContentKitUiAppearance;\n}\n\n/** Adds the item to the signed-in visitor's favorites, or removes it, with the server's count; changes at once and rolls back if refused. */\nexport function FavoriteButton({ item, favorited, count, showCount = true, label = true, onSignIn, onChange, size = \"default\", client, onError, className, appearance }: FavoriteButtonProps) {\n const m = useMessages();\n const { t } = m;\n const ctx = useContext(ContentKitContext);\n const f = useFavorite(item, { initial: favorited !== undefined && count !== undefined ? { favorited, count } : undefined, client });\n const signIn = onSignIn ?? ctx?.onSignIn;\n const report = useErrorReporter(onError);\n const [error, setError] = useState<ContentKitError | null>(null);\n const [status, setStatus] = useState(\"\");\n const shown = showCount ? f.count : undefined;\n const click = () => {\n if (ctx?.viewer === null) return signIn?.();\n setError(null);\n const next = !f.favorited;\n f.set(next).then(\n () => {\n setStatus(t(next ? \"favorites.added\" : \"favorites.removed\"));\n onChange?.(next);\n },\n (e) => {\n const err = toContentKitError(e);\n if (err.code === \"unauthorized\" && signIn) return signIn();\n setError(err);\n report(err, \"favorite.save\");\n },\n );\n };\n const text = t(ctx?.viewer === null && signIn ? \"favorites.signIn\" : f.favorited ? \"favorites.remove\" : \"favorites.add\");\n return (\n <ContentKitUiRoot appearance={appearance} className={cn(\"inline-flex flex-wrap items-center gap-2 text-sm\", className)} data-ckui=\"favorite-button\">\n <Button\n variant={f.favorited ? \"secondary\" : \"outline\"}\n size={label ? (size === \"sm\" ? \"sm\" : \"default\") : size === \"sm\" ? \"icon-sm\" : \"icon\"}\n aria-pressed={f.favorited}\n aria-label={label ? undefined : text}\n disabled={f.pending}\n onClick={click}\n >\n <HugeiconsIcon icon={FavouriteIcon} strokeWidth={2} className={cn(f.favorited && \"fill-current text-destructive\")} />\n {label && <span>{text}</span>}\n {shown !== undefined && <span className=\"tabular-nums text-muted-foreground\">{compact(Math.max(0, shown), m.language)}</span>}\n </Button>\n <span className=\"sr-only\" role=\"status\">\n {status}\n </span>\n {error && (\n <span role=\"alert\" className=\"text-xs text-destructive\">\n {contentError(m, error)}\n </span>\n )}\n </ContentKitUiRoot>\n );\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export { Comments, type CommentsProps } from './comments.js';
|
|
2
|
+
export { BanNotice, CommentBanDialog, CommentBans, type CommentBanDialogProps, type CommentBansProps } from './bans.js';
|
|
3
|
+
export { FavoriteButton, ReactionButtons, type FavoriteButtonProps, type ReactionButtonsProps } from './engagement.js';
|
|
4
|
+
export { Poll, type PollProps } from './poll.js';
|
|
5
|
+
export { PollEditor, type PollEditorProps } from './poll-editor.js';
|
|
6
|
+
export { CommentModeration, type CommentModerationProps, type ModerationSection } from './moderation.js';
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { ContentKitClient } from '../../client/client.js';
|
|
2
|
+
import { PublicUser } from '../../client/generated/wire.js';
|
|
3
|
+
import { ContentKitUiAppearance } from '../../appearance.js';
|
|
4
|
+
import { ContentKitErrorHandler } from '../../react/context.js';
|
|
5
|
+
export type ModerationSection = "comments" | "queue" | "bans";
|
|
6
|
+
export interface CommentModerationProps {
|
|
7
|
+
/** Content kinds offered as a filter of the comment list: codes, or codes with labels. */
|
|
8
|
+
contentKinds?: readonly (string | {
|
|
9
|
+
value: string;
|
|
10
|
+
label: string;
|
|
11
|
+
})[];
|
|
12
|
+
/** A link to a commented item. */
|
|
13
|
+
itemHref?: (item: {
|
|
14
|
+
kind: string;
|
|
15
|
+
id: string;
|
|
16
|
+
}) => string | undefined;
|
|
17
|
+
userHref?: (user: PublicUser) => string | undefined;
|
|
18
|
+
/** The sections, in order. Default all: every comment, the review queue, the site's bans. */
|
|
19
|
+
sections?: readonly ModerationSection[];
|
|
20
|
+
pageSize?: number;
|
|
21
|
+
client?: ContentKitClient;
|
|
22
|
+
onError?: ContentKitErrorHandler;
|
|
23
|
+
className?: string;
|
|
24
|
+
appearance?: ContentKitUiAppearance;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Staff: every comment (deleted, held and rejected ones with their text) to
|
|
28
|
+
* delete, restore or ban its author; the review queue of held comments and
|
|
29
|
+
* posts to approve or reject; and the site's comment bans. Each section
|
|
30
|
+
* shows what the caller's permissions allow and says so when they don't.
|
|
31
|
+
*/
|
|
32
|
+
export declare function CommentModeration({ sections, className, appearance, ...p }: CommentModerationProps): import('react').JSX.Element;
|
|
@@ -0,0 +1,383 @@
|
|
|
1
|
+
import { toContentKitError as e } from "../../client/errors.js";
|
|
2
|
+
import { useMessages as t } from "../../i18n/context.js";
|
|
3
|
+
import { ContentKitUiRoot as n } from "../../scope.js";
|
|
4
|
+
import { useErrorReporter as r } from "../../react/context.js";
|
|
5
|
+
import { Button as i } from "../../ui/button.js";
|
|
6
|
+
import { useAdminComments as a, useModerationQueue as o } from "../../react/comments.js";
|
|
7
|
+
import { Badge as s } from "../../ui/badge.js";
|
|
8
|
+
import { Input as c } from "../../ui/input.js";
|
|
9
|
+
import { Select as l, SelectContent as u, SelectItem as d, SelectTrigger as f, SelectValue as p } from "../../ui/select.js";
|
|
10
|
+
import { Skeleton as m } from "../../ui/skeleton.js";
|
|
11
|
+
import { ErrorLine as h, RelativeTime as g, UserAvatar as _, UserName as v, contentError as y } from "./parts.js";
|
|
12
|
+
import { CommentBanDialog as b, CommentBans as x } from "./bans.js";
|
|
13
|
+
import { Tabs as S, TabsContent as C, TabsList as w, TabsTrigger as T } from "../../ui/tabs.js";
|
|
14
|
+
import { useMemo as E, useState as D } from "react";
|
|
15
|
+
import { jsx as O, jsxs as k } from "react/jsx-runtime";
|
|
16
|
+
import { cn as A } from "cn";
|
|
17
|
+
//#region src/components/social/moderation.tsx
|
|
18
|
+
function j({ sections: e = [
|
|
19
|
+
"comments",
|
|
20
|
+
"queue",
|
|
21
|
+
"bans"
|
|
22
|
+
], className: r, appearance: i, ...a }) {
|
|
23
|
+
let { t: o } = t(), [s, c] = D(e[0] ?? "comments"), l = {
|
|
24
|
+
comments: o("moderation.all"),
|
|
25
|
+
queue: o("moderation.queue"),
|
|
26
|
+
bans: o("moderation.bans")
|
|
27
|
+
};
|
|
28
|
+
return /* @__PURE__ */ k(n, {
|
|
29
|
+
appearance: i,
|
|
30
|
+
className: A("grid gap-4 text-sm", r),
|
|
31
|
+
"data-ckui": "comment-moderation",
|
|
32
|
+
children: [/* @__PURE__ */ O("h2", {
|
|
33
|
+
className: "text-base font-semibold",
|
|
34
|
+
children: o("moderation.title")
|
|
35
|
+
}), /* @__PURE__ */ k(S, {
|
|
36
|
+
value: s,
|
|
37
|
+
onValueChange: (e) => c(e),
|
|
38
|
+
children: [
|
|
39
|
+
e.length > 1 && /* @__PURE__ */ O(w, { children: e.map((e) => /* @__PURE__ */ O(T, {
|
|
40
|
+
value: e,
|
|
41
|
+
children: l[e]
|
|
42
|
+
}, e)) }),
|
|
43
|
+
e.includes("comments") && /* @__PURE__ */ O(C, {
|
|
44
|
+
value: "comments",
|
|
45
|
+
className: "pt-3",
|
|
46
|
+
children: /* @__PURE__ */ O(N, { ...a })
|
|
47
|
+
}),
|
|
48
|
+
e.includes("queue") && /* @__PURE__ */ O(C, {
|
|
49
|
+
value: "queue",
|
|
50
|
+
className: "pt-3",
|
|
51
|
+
children: /* @__PURE__ */ O(P, { ...a })
|
|
52
|
+
}),
|
|
53
|
+
e.includes("bans") && /* @__PURE__ */ O(C, {
|
|
54
|
+
value: "bans",
|
|
55
|
+
className: "pt-3",
|
|
56
|
+
children: /* @__PURE__ */ O(x, {
|
|
57
|
+
scope: "global",
|
|
58
|
+
pageSize: a.pageSize,
|
|
59
|
+
userHref: a.userHref,
|
|
60
|
+
client: a.client,
|
|
61
|
+
onError: a.onError
|
|
62
|
+
})
|
|
63
|
+
})
|
|
64
|
+
]
|
|
65
|
+
})]
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
function M(e) {
|
|
69
|
+
return e.deleted ? "deleted" : e.moderation === "held" ? "held" : e.moderation === "rejected" ? "rejected" : "published";
|
|
70
|
+
}
|
|
71
|
+
function N(n) {
|
|
72
|
+
let { t: o } = t(), c = E(() => (n.contentKinds ?? []).map((e) => typeof e == "string" ? {
|
|
73
|
+
value: e,
|
|
74
|
+
label: e
|
|
75
|
+
} : e), [n.contentKinds]), [m, y] = D(""), x = a({
|
|
76
|
+
contentKind: m,
|
|
77
|
+
pageSize: n.pageSize,
|
|
78
|
+
client: n.client
|
|
79
|
+
}), S = r(n.onError), [C, w] = D(null), [T, j] = D(null), N = (t, n) => {
|
|
80
|
+
w(null), n().catch((n) => {
|
|
81
|
+
let r = e(n);
|
|
82
|
+
w(r), S(r, t);
|
|
83
|
+
});
|
|
84
|
+
};
|
|
85
|
+
return /* @__PURE__ */ k("div", {
|
|
86
|
+
className: "grid gap-3",
|
|
87
|
+
children: [
|
|
88
|
+
c.length > 0 && /* @__PURE__ */ k(l, {
|
|
89
|
+
value: m,
|
|
90
|
+
onValueChange: (e) => y(String(e ?? "")),
|
|
91
|
+
children: [/* @__PURE__ */ O(f, {
|
|
92
|
+
size: "sm",
|
|
93
|
+
"aria-label": o("moderation.kind"),
|
|
94
|
+
children: /* @__PURE__ */ O(p, { children: (e) => e ? c.find((t) => t.value === e)?.label ?? e : o("moderation.allKinds") })
|
|
95
|
+
}), /* @__PURE__ */ k(u, { children: [/* @__PURE__ */ O(d, {
|
|
96
|
+
value: "",
|
|
97
|
+
children: o("moderation.allKinds")
|
|
98
|
+
}), c.map((e) => /* @__PURE__ */ O(d, {
|
|
99
|
+
value: e.value,
|
|
100
|
+
children: e.label
|
|
101
|
+
}, e.value))] })]
|
|
102
|
+
}),
|
|
103
|
+
/* @__PURE__ */ O(h, { error: C }),
|
|
104
|
+
/* @__PURE__ */ O(I, {
|
|
105
|
+
loading: x.loading,
|
|
106
|
+
error: x.error,
|
|
107
|
+
empty: o("moderation.empty"),
|
|
108
|
+
count: x.items.length,
|
|
109
|
+
reload: x.reload,
|
|
110
|
+
children: x.items.map((e) => {
|
|
111
|
+
let t = e.author?.username ?? e.anon_name ?? e.user_id ?? o("comments.anonymous"), r = M(e), a = n.itemHref?.({
|
|
112
|
+
kind: e.content_kind,
|
|
113
|
+
id: e.content_id
|
|
114
|
+
});
|
|
115
|
+
return /* @__PURE__ */ k("li", {
|
|
116
|
+
className: "grid gap-2 p-3",
|
|
117
|
+
"data-ckui": "admin-comment",
|
|
118
|
+
"data-status": r,
|
|
119
|
+
children: [
|
|
120
|
+
/* @__PURE__ */ k("div", {
|
|
121
|
+
className: "flex flex-wrap items-center gap-x-2 gap-y-1",
|
|
122
|
+
children: [
|
|
123
|
+
/* @__PURE__ */ O(_, {
|
|
124
|
+
user: e.author,
|
|
125
|
+
name: t,
|
|
126
|
+
size: "sm"
|
|
127
|
+
}),
|
|
128
|
+
/* @__PURE__ */ O(v, {
|
|
129
|
+
user: e.author,
|
|
130
|
+
name: t,
|
|
131
|
+
href: n.userHref
|
|
132
|
+
}),
|
|
133
|
+
/* @__PURE__ */ O(g, {
|
|
134
|
+
at: e.created_at,
|
|
135
|
+
className: "text-xs text-muted-foreground"
|
|
136
|
+
}),
|
|
137
|
+
/* @__PURE__ */ O(s, {
|
|
138
|
+
variant: r === "published" ? "outline" : r === "held" ? "secondary" : "destructive",
|
|
139
|
+
children: o(`moderation.${r}`)
|
|
140
|
+
}),
|
|
141
|
+
e.reply_to_id && /* @__PURE__ */ O(s, {
|
|
142
|
+
variant: "outline",
|
|
143
|
+
children: o("moderation.reply")
|
|
144
|
+
}),
|
|
145
|
+
/* @__PURE__ */ k("span", {
|
|
146
|
+
className: "text-xs text-muted-foreground",
|
|
147
|
+
children: [
|
|
148
|
+
o("moderation.on"),
|
|
149
|
+
" ",
|
|
150
|
+
a ? /* @__PURE__ */ k("a", {
|
|
151
|
+
className: "hover:underline",
|
|
152
|
+
href: a,
|
|
153
|
+
children: [
|
|
154
|
+
e.content_kind,
|
|
155
|
+
"/",
|
|
156
|
+
e.content_id
|
|
157
|
+
]
|
|
158
|
+
}) : `${e.content_kind}/${e.content_id}`
|
|
159
|
+
]
|
|
160
|
+
})
|
|
161
|
+
]
|
|
162
|
+
}),
|
|
163
|
+
/* @__PURE__ */ O("p", {
|
|
164
|
+
className: A("line-clamp-4 break-words whitespace-pre-wrap", e.deleted && "text-muted-foreground line-through"),
|
|
165
|
+
children: e.body
|
|
166
|
+
}),
|
|
167
|
+
e.moderation_reason && /* @__PURE__ */ O("p", {
|
|
168
|
+
className: "text-xs text-muted-foreground",
|
|
169
|
+
children: o("moderation.heldBecause", { reason: e.moderation_reason })
|
|
170
|
+
}),
|
|
171
|
+
/* @__PURE__ */ k("div", {
|
|
172
|
+
className: "flex flex-wrap gap-2",
|
|
173
|
+
children: [e.deleted ? /* @__PURE__ */ O(i, {
|
|
174
|
+
size: "sm",
|
|
175
|
+
variant: "outline",
|
|
176
|
+
onClick: () => N("comment.restore", () => x.restore(e.id)),
|
|
177
|
+
children: o("moderation.restore")
|
|
178
|
+
}) : /* @__PURE__ */ O(i, {
|
|
179
|
+
size: "sm",
|
|
180
|
+
variant: "destructive",
|
|
181
|
+
onClick: () => N("comment.delete", () => x.remove(e.id)),
|
|
182
|
+
children: o("moderation.delete")
|
|
183
|
+
}), e.user_id && /* @__PURE__ */ O(i, {
|
|
184
|
+
size: "sm",
|
|
185
|
+
variant: "ghost",
|
|
186
|
+
onClick: () => j({
|
|
187
|
+
id: e.user_id,
|
|
188
|
+
name: t
|
|
189
|
+
}),
|
|
190
|
+
children: o("comments.ban")
|
|
191
|
+
})]
|
|
192
|
+
})
|
|
193
|
+
]
|
|
194
|
+
}, e.id);
|
|
195
|
+
})
|
|
196
|
+
}),
|
|
197
|
+
x.hasMore && /* @__PURE__ */ O(i, {
|
|
198
|
+
variant: "outline",
|
|
199
|
+
className: "justify-self-center",
|
|
200
|
+
disabled: x.loadingMore,
|
|
201
|
+
onClick: () => void x.loadMore(),
|
|
202
|
+
children: o("moderation.loadMore")
|
|
203
|
+
}),
|
|
204
|
+
T && /* @__PURE__ */ O(b, {
|
|
205
|
+
open: !0,
|
|
206
|
+
onOpenChange: (e) => !e && j(null),
|
|
207
|
+
user: T,
|
|
208
|
+
scopes: ["global"],
|
|
209
|
+
client: n.client,
|
|
210
|
+
onError: n.onError
|
|
211
|
+
})
|
|
212
|
+
]
|
|
213
|
+
});
|
|
214
|
+
}
|
|
215
|
+
function P(e) {
|
|
216
|
+
let { t: n } = t(), [r, a] = D("comment"), s = o({
|
|
217
|
+
kind: r,
|
|
218
|
+
pageSize: e.pageSize,
|
|
219
|
+
client: e.client
|
|
220
|
+
});
|
|
221
|
+
return /* @__PURE__ */ k("div", {
|
|
222
|
+
className: "grid gap-3",
|
|
223
|
+
children: [
|
|
224
|
+
/* @__PURE__ */ O("div", {
|
|
225
|
+
className: "flex gap-2",
|
|
226
|
+
role: "group",
|
|
227
|
+
"aria-label": n("moderation.queue"),
|
|
228
|
+
children: ["comment", "post"].map((e) => /* @__PURE__ */ O(i, {
|
|
229
|
+
size: "sm",
|
|
230
|
+
variant: r === e ? "default" : "outline",
|
|
231
|
+
"aria-pressed": r === e,
|
|
232
|
+
onClick: () => a(e),
|
|
233
|
+
children: n(e === "post" ? "moderation.queuePosts" : "moderation.queueComments")
|
|
234
|
+
}, e))
|
|
235
|
+
}),
|
|
236
|
+
/* @__PURE__ */ O(I, {
|
|
237
|
+
loading: s.loading,
|
|
238
|
+
error: s.error,
|
|
239
|
+
empty: n("moderation.queueEmpty"),
|
|
240
|
+
count: s.items.length,
|
|
241
|
+
reload: s.reload,
|
|
242
|
+
children: s.items.map((t) => /* @__PURE__ */ O(F, {
|
|
243
|
+
item: t,
|
|
244
|
+
itemHref: e.itemHref,
|
|
245
|
+
userHref: e.userHref,
|
|
246
|
+
onResolve: s.resolve,
|
|
247
|
+
reload: s.reload,
|
|
248
|
+
onError: e.onError
|
|
249
|
+
}, t.id))
|
|
250
|
+
}),
|
|
251
|
+
s.hasMore && /* @__PURE__ */ O(i, {
|
|
252
|
+
variant: "outline",
|
|
253
|
+
className: "justify-self-center",
|
|
254
|
+
disabled: s.loadingMore,
|
|
255
|
+
onClick: () => void s.loadMore(),
|
|
256
|
+
children: n("moderation.loadMore")
|
|
257
|
+
})
|
|
258
|
+
]
|
|
259
|
+
});
|
|
260
|
+
}
|
|
261
|
+
function F(n) {
|
|
262
|
+
let a = t(), { t: o } = a, s = r(n.onError), { item: l } = n, [u, d] = D(!1), [f, p] = D(""), [m, b] = D(!1), [x, S] = D(null), C = l.author?.username ?? l.anon_name ?? l.author_id ?? o("comments.anonymous"), w = n.itemHref?.({
|
|
263
|
+
kind: l.ref.content_kind,
|
|
264
|
+
id: l.ref.content_id
|
|
265
|
+
}), T = async (t) => {
|
|
266
|
+
b(!0), S(null);
|
|
267
|
+
try {
|
|
268
|
+
await n.onResolve(l, t, t === "reject" && f.trim() || void 0);
|
|
269
|
+
} catch (t) {
|
|
270
|
+
let r = e(t);
|
|
271
|
+
s(r, "moderation.resolve"), r.code === "not_found" || r.code === "conflict" ? (S(o("moderation.stale")), n.reload()) : S(y(a, r));
|
|
272
|
+
} finally {
|
|
273
|
+
b(!1);
|
|
274
|
+
}
|
|
275
|
+
};
|
|
276
|
+
return /* @__PURE__ */ k("li", {
|
|
277
|
+
className: "grid gap-2 p-3",
|
|
278
|
+
"data-ckui": "held-item",
|
|
279
|
+
children: [
|
|
280
|
+
/* @__PURE__ */ k("div", {
|
|
281
|
+
className: "flex flex-wrap items-center gap-x-2 gap-y-1",
|
|
282
|
+
children: [
|
|
283
|
+
/* @__PURE__ */ O(_, {
|
|
284
|
+
user: l.author,
|
|
285
|
+
name: C,
|
|
286
|
+
size: "sm"
|
|
287
|
+
}),
|
|
288
|
+
/* @__PURE__ */ O(v, {
|
|
289
|
+
user: l.author,
|
|
290
|
+
name: C,
|
|
291
|
+
href: n.userHref
|
|
292
|
+
}),
|
|
293
|
+
/* @__PURE__ */ O(g, {
|
|
294
|
+
at: l.held_at,
|
|
295
|
+
className: "text-xs text-muted-foreground"
|
|
296
|
+
}),
|
|
297
|
+
w && /* @__PURE__ */ k("a", {
|
|
298
|
+
className: "text-xs text-muted-foreground hover:underline",
|
|
299
|
+
href: w,
|
|
300
|
+
children: [
|
|
301
|
+
o("moderation.on"),
|
|
302
|
+
" ",
|
|
303
|
+
l.ref.content_kind,
|
|
304
|
+
"/",
|
|
305
|
+
l.ref.content_id
|
|
306
|
+
]
|
|
307
|
+
})
|
|
308
|
+
]
|
|
309
|
+
}),
|
|
310
|
+
l.title && /* @__PURE__ */ O("p", {
|
|
311
|
+
className: "font-medium",
|
|
312
|
+
children: l.title
|
|
313
|
+
}),
|
|
314
|
+
/* @__PURE__ */ O("p", {
|
|
315
|
+
className: "line-clamp-6 break-words whitespace-pre-wrap",
|
|
316
|
+
children: l.body
|
|
317
|
+
}),
|
|
318
|
+
(l.reason || l.error) && /* @__PURE__ */ O("p", {
|
|
319
|
+
className: "text-xs text-muted-foreground",
|
|
320
|
+
children: o("moderation.heldBecause", { reason: l.reason || l.error || "" })
|
|
321
|
+
}),
|
|
322
|
+
u && /* @__PURE__ */ O(c, {
|
|
323
|
+
value: f,
|
|
324
|
+
maxLength: 500,
|
|
325
|
+
placeholder: o("moderation.rejectReason"),
|
|
326
|
+
"aria-label": o("moderation.rejectReason"),
|
|
327
|
+
onChange: (e) => p(e.target.value),
|
|
328
|
+
autoFocus: !0
|
|
329
|
+
}),
|
|
330
|
+
/* @__PURE__ */ k("div", {
|
|
331
|
+
className: "flex flex-wrap gap-2",
|
|
332
|
+
children: [
|
|
333
|
+
/* @__PURE__ */ O(i, {
|
|
334
|
+
size: "sm",
|
|
335
|
+
disabled: m,
|
|
336
|
+
onClick: () => void T("approve"),
|
|
337
|
+
children: o("moderation.approve")
|
|
338
|
+
}),
|
|
339
|
+
/* @__PURE__ */ O(i, {
|
|
340
|
+
size: "sm",
|
|
341
|
+
variant: "destructive",
|
|
342
|
+
disabled: m,
|
|
343
|
+
onClick: () => u ? void T("reject") : d(!0),
|
|
344
|
+
children: o("moderation.reject")
|
|
345
|
+
}),
|
|
346
|
+
u && /* @__PURE__ */ O(i, {
|
|
347
|
+
size: "sm",
|
|
348
|
+
variant: "ghost",
|
|
349
|
+
onClick: () => d(!1),
|
|
350
|
+
children: o("common.cancel")
|
|
351
|
+
})
|
|
352
|
+
]
|
|
353
|
+
}),
|
|
354
|
+
x && /* @__PURE__ */ O(h, { children: x })
|
|
355
|
+
]
|
|
356
|
+
});
|
|
357
|
+
}
|
|
358
|
+
function I(e) {
|
|
359
|
+
let n = t(), { t: r } = n;
|
|
360
|
+
return e.loading && !e.count ? /* @__PURE__ */ k("div", {
|
|
361
|
+
className: "grid gap-3",
|
|
362
|
+
"aria-busy": !0,
|
|
363
|
+
children: [/* @__PURE__ */ O(m, { className: "h-16 w-full" }), /* @__PURE__ */ O(m, { className: "h-16 w-full" })]
|
|
364
|
+
}) : e.error && !e.count ? /* @__PURE__ */ k("div", {
|
|
365
|
+
className: "grid justify-items-start gap-2",
|
|
366
|
+
children: [/* @__PURE__ */ O(h, { children: e.error.code === "forbidden" || e.error.code === "unauthorized" ? y(n, e.error) : r("moderation.loadFailed") }), /* @__PURE__ */ O(i, {
|
|
367
|
+
size: "sm",
|
|
368
|
+
variant: "outline",
|
|
369
|
+
onClick: e.reload,
|
|
370
|
+
children: r("common.retry")
|
|
371
|
+
})]
|
|
372
|
+
}) : e.count ? /* @__PURE__ */ O("ul", {
|
|
373
|
+
className: "grid divide-y divide-border rounded-lg border border-border",
|
|
374
|
+
children: e.children
|
|
375
|
+
}) : /* @__PURE__ */ O("p", {
|
|
376
|
+
className: "text-muted-foreground",
|
|
377
|
+
children: e.empty
|
|
378
|
+
});
|
|
379
|
+
}
|
|
380
|
+
//#endregion
|
|
381
|
+
export { j as CommentModeration };
|
|
382
|
+
|
|
383
|
+
//# sourceMappingURL=moderation.js.map
|