@blocklet/discuss-kit-post 2.4.35 → 2.4.37

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/api.d.ts CHANGED
@@ -1,13 +0,0 @@
1
- import { Post } from './types';
2
- export declare const api: import('axios').AxiosInstance;
3
- export declare const fetchPost: (postId: string, locale: string) => Promise<Post | null>;
4
- export declare const updatePostContent: (id: string, payload: {
5
- title: string;
6
- content: string;
7
- contentVersion: number;
8
- locale?: string;
9
- }) => Promise<any>;
10
- export declare const fetchPaymentLink: (params: {
11
- type: 'blog' | 'post' | 'bookmark' | 'doc';
12
- redirect: string;
13
- }) => Promise<any>;
package/dist/api.mjs ADDED
@@ -0,0 +1,25 @@
1
+ import { createAxios } from "@blocklet/js-sdk";
2
+ import { joinURL, withQuery } from "ufo";
3
+ import { discussKitApiPrefix } from "./utils.mjs";
4
+ export const api = createAxios({
5
+ baseURL: discussKitApiPrefix,
6
+ timeout: 2e4
7
+ });
8
+ export const fetchPost = async (postId, locale) => {
9
+ const url = withQuery(joinURL("/posts/slug", postId), { locale });
10
+ try {
11
+ const result = await api.get(url).then((res) => res.data);
12
+ return result;
13
+ } catch (e) {
14
+ console.error(e);
15
+ return null;
16
+ }
17
+ };
18
+ export const updatePostContent = async (id, payload) => {
19
+ const { data } = await api.put(`/posts/${id}/content`, payload);
20
+ return data;
21
+ };
22
+ export const fetchPaymentLink = async (params) => {
23
+ const { data } = await api.get("/subscriptions/payment-link", { params });
24
+ return data;
25
+ };
@@ -1,4 +1,4 @@
1
- import { SetState } from 'ahooks/lib/useSetState';
1
+ import type { SetState } from 'ahooks/lib/useSetState';
2
2
  export type Status = 'idle' | 'saving' | 'saved';
3
3
  type SaveAction<S, T> = (s: S) => Promise<T>;
4
4
  interface Option<S, T> {
@@ -0,0 +1,94 @@
1
+ import { useRequest, useSetState, useGetState, useThrottleEffect, useTimeout, useDocumentVisibility } from "ahooks";
2
+ import { useCallback, useEffect, useRef, useState } from "react";
3
+ import { DirtyPromptContainer, utils, toast, useEventCallback } from "@blocklet/discuss-kit-ux";
4
+ import { useLocaleContext } from "@arcblock/ux/lib/Locale/context";
5
+ const useStatus = (saving) => {
6
+ const [status, setStatus] = useState("idle");
7
+ useEffect(() => {
8
+ if (saving) {
9
+ setStatus("saving");
10
+ } else {
11
+ setStatus((prev) => prev === "saving" ? "saved" : "idle");
12
+ }
13
+ }, [saving]);
14
+ useTimeout(
15
+ () => {
16
+ setStatus("idle");
17
+ },
18
+ status === "saved" ? 1500 : void 0
19
+ );
20
+ return status;
21
+ };
22
+ const useAutoSaveState = (initialState, { save, paused, wait = 1e4 }) => {
23
+ const [state, setStateInternal] = useSetState(initialState);
24
+ const [pendingState, setPendingState, getPendingState] = useGetState();
25
+ const latestState = pendingState || state;
26
+ const isInitialState = useRef(true);
27
+ const [error, setError] = useState(null);
28
+ const documentVisibility = useDocumentVisibility();
29
+ const { dirty, reset, markDirty } = DirtyPromptContainer.useContainer();
30
+ const { t } = useLocaleContext();
31
+ const handleSave = async (s) => {
32
+ try {
33
+ const result = await utils.minDelay(save(s), 1500);
34
+ const pendingState2 = getPendingState();
35
+ if (pendingState2) {
36
+ setStateInternal(pendingState2);
37
+ setPendingState(null);
38
+ } else {
39
+ reset();
40
+ setError(null);
41
+ }
42
+ return result;
43
+ } catch (e) {
44
+ setError(e);
45
+ toast.error(t("draftStatus.error"));
46
+ throw e;
47
+ }
48
+ };
49
+ const { data: saved, loading, run, runAsync } = useRequest(handleSave, { manual: true });
50
+ const status = useStatus(loading);
51
+ const canSave = !isInitialState.current && !paused && !loading && dirty;
52
+ useThrottleEffect(
53
+ () => {
54
+ if (paused || loading || !dirty || isInitialState.current) {
55
+ return;
56
+ }
57
+ run(state);
58
+ },
59
+ [state, paused],
60
+ { wait, leading: false }
61
+ );
62
+ const setState = (s) => {
63
+ if (loading) {
64
+ setPendingState({ ...state, ...s });
65
+ } else {
66
+ setStateInternal(s);
67
+ }
68
+ if (isInitialState.current) {
69
+ isInitialState.current = false;
70
+ }
71
+ if (!isInitialState.current) {
72
+ markDirty();
73
+ }
74
+ };
75
+ const setInitialState = useCallback(
76
+ (s) => {
77
+ setStateInternal(s);
78
+ isInitialState.current = true;
79
+ },
80
+ [setStateInternal]
81
+ );
82
+ const saveNow = useEventCallback(async () => {
83
+ if (canSave) {
84
+ await runAsync(state);
85
+ }
86
+ });
87
+ useEffect(() => {
88
+ if (documentVisibility === "hidden") {
89
+ saveNow();
90
+ }
91
+ }, [documentVisibility, saveNow]);
92
+ return { state: latestState, setState, setInitialState, status, saved, saveNow, error };
93
+ };
94
+ export { useAutoSaveState };
@@ -0,0 +1,8 @@
1
+ import { AxiosRequestConfig as OriginalAxiosRequestConfig } from 'axios';
2
+
3
+ // https://github.com/axios/axios/pull/1964#issuecomment-903983962
4
+ declare module 'axios' {
5
+ export interface AxiosRequestConfig extends OriginalAxiosRequestConfig {
6
+ muteError?: boolean;
7
+ }
8
+ }
@@ -1,8 +1,9 @@
1
- import { Status } from './auto-save';
1
+ /// <reference types="react" />
2
+ import type { Status } from './auto-save';
2
3
  interface Props {
3
4
  status: Status;
4
5
  error?: Error | null;
5
6
  [key: string]: any;
6
7
  }
7
- export default function DraftStatus({ status, error, ...rest }: Props): import("react/jsx-runtime").JSX.Element | null;
8
+ export default function DraftStatus({ status, error, ...rest }: Props): import("react").JSX.Element | null;
8
9
  export {};
@@ -0,0 +1,14 @@
1
+ import { jsx, jsxs } from "react/jsx-runtime";
2
+ import { Box, CircularProgress, Tooltip, useMediaQuery } from "@mui/material";
3
+ import { useLocaleContext } from "@arcblock/ux/lib/Locale/context";
4
+ export default function DraftStatus({ status, error, ...rest }) {
5
+ const { t } = useLocaleContext();
6
+ const downMd = useMediaQuery((theme) => theme.breakpoints.down("md"));
7
+ if (downMd) {
8
+ return status !== "idle" ? /* @__PURE__ */ jsx(Box, { sx: { display: { xs: "inline-block", md: "none", lineHeight: 1 } }, component: CircularProgress, size: 16 }) : null;
9
+ }
10
+ return /* @__PURE__ */ jsxs(Box, { sx: { display: "flex", alignItems: "center", gap: 1 }, ...rest, children: [
11
+ /* @__PURE__ */ jsx(Tooltip, { title: error?.message, children: /* @__PURE__ */ jsx(Box, { sx: { width: 8, height: 8, borderRadius: "100%", bgcolor: error ? "error.main" : "success.main" } }) }),
12
+ /* @__PURE__ */ jsx(Box, { sx: { color: "grey.600", fontSize: 13, lineHeight: 1 }, component: "span", className: "draft-status-text", children: error ? t("draftStatus.error") : t(`draftStatus.${status}`) })
13
+ ] });
14
+ }
package/dist/edit.d.ts CHANGED
@@ -1,3 +1,4 @@
1
+ /// <reference types="react" />
1
2
  import { Post } from './types';
2
3
  interface Props {
3
4
  post: Post;
@@ -5,5 +6,5 @@ interface Props {
5
6
  onUpdate: (post: Post) => void;
6
7
  onCancel: () => void;
7
8
  }
8
- export declare function PostEdit(props: Props): import("react/jsx-runtime").JSX.Element;
9
+ export declare function PostEdit(props: Props): import("react").JSX.Element;
9
10
  export {};
package/dist/edit.mjs ADDED
@@ -0,0 +1,85 @@
1
+ import { jsx, jsxs } from "react/jsx-runtime";
2
+ import { Box, Button, Stack } from "@mui/material";
3
+ import { LazyEditor, DirtyPromptContainer } from "@blocklet/discuss-kit-ux";
4
+ import { useLocaleContext } from "@arcblock/ux/lib/Locale/context";
5
+ import { updatePostContent } from "./api.mjs";
6
+ import { useAutoSaveState } from "./auto-save.mjs";
7
+ import DraftStatus from "./draft-status.mjs";
8
+ function InternalPostEdit({ post, onSave, onUpdate, onCancel, ...rest }) {
9
+ const { t } = useLocaleContext();
10
+ const { reset, check } = DirtyPromptContainer.useContainer();
11
+ const save = async (state) => {
12
+ if (!post) {
13
+ throw new Error("Invalid state");
14
+ }
15
+ try {
16
+ const updated = await updatePostContent(post.id, {
17
+ title: state.title,
18
+ content: state.content,
19
+ locale: post.locale,
20
+ contentVersion: post.contentVersion
21
+ });
22
+ onUpdate(updated);
23
+ return updated;
24
+ } catch (e) {
25
+ console.error(e);
26
+ throw e;
27
+ }
28
+ };
29
+ const {
30
+ state: autoSaveState,
31
+ setState,
32
+ status,
33
+ error,
34
+ saveNow
35
+ } = useAutoSaveState({ title: post?.title || "", content: post?.content || "" }, { save });
36
+ const handleContentChange = ({ content }) => {
37
+ setState({ content });
38
+ };
39
+ const handleSave = async () => {
40
+ const updated = await updatePostContent(post.id, {
41
+ title: autoSaveState.title,
42
+ content: autoSaveState.content,
43
+ locale: post.locale,
44
+ contentVersion: post.contentVersion
45
+ });
46
+ onSave(updated);
47
+ };
48
+ const handleCancel = async () => {
49
+ if (await check()) {
50
+ onCancel();
51
+ reset();
52
+ }
53
+ };
54
+ return /* @__PURE__ */ jsxs(Box, { ...rest, children: [
55
+ /* @__PURE__ */ jsxs(
56
+ Stack,
57
+ {
58
+ direction: "row",
59
+ sx: {
60
+ justifyContent: "space-between",
61
+ alignItems: "center"
62
+ },
63
+ children: [
64
+ /* @__PURE__ */ jsxs(Box, { sx: { mb: 1, display: "flex", gap: 1 }, children: [
65
+ /* @__PURE__ */ jsx(Button, { variant: "contained", color: "primary", onClick: () => handleSave(), children: t("save") }),
66
+ /* @__PURE__ */ jsx(Button, { variant: "outlined", onClick: handleCancel, children: t("cancel") })
67
+ ] }),
68
+ /* @__PURE__ */ jsx(DraftStatus, { status, error })
69
+ ]
70
+ }
71
+ ),
72
+ /* @__PURE__ */ jsx(
73
+ LazyEditor,
74
+ {
75
+ initialContent: post.content || "",
76
+ onChange: handleContentChange,
77
+ autoFocus: false,
78
+ onSave: () => saveNow()
79
+ }
80
+ )
81
+ ] });
82
+ }
83
+ export function PostEdit(props) {
84
+ return /* @__PURE__ */ jsx(DirtyPromptContainer.Provider, { children: /* @__PURE__ */ jsx(InternalPostEdit, { ...props }) });
85
+ }
@@ -0,0 +1 @@
1
+ /// <reference path="../../../global.d.ts" />
package/dist/index.d.ts CHANGED
@@ -1,8 +1,9 @@
1
- import { BoxProps } from '@mui/material';
1
+ /// <reference types="react" />
2
+ import { type BoxProps } from '@mui/material';
2
3
  import { PostAutoTranslationContainer } from '@blocklet/discuss-kit-ux';
3
4
  interface PostProps extends BoxProps {
4
5
  postId: string;
5
6
  readonly?: boolean;
6
7
  }
7
- export declare function Post(props: PostProps): import("react/jsx-runtime").JSX.Element | null;
8
+ export declare function Post(props: PostProps): import("react").JSX.Element | null;
8
9
  export { PostAutoTranslationContainer };
package/dist/index.mjs ADDED
@@ -0,0 +1,77 @@
1
+ import { jsx, jsxs } from "react/jsx-runtime";
2
+ import { Box, IconButton } from "@mui/material";
3
+ import { useRequest } from "ahooks";
4
+ import { LocaleProvider, useLocaleContext } from "@arcblock/ux/lib/Locale/context";
5
+ import { SessionContext } from "@arcblock/did-connect-react/lib/Session";
6
+ import { useContext, useState } from "react";
7
+ import {
8
+ EditorPreview,
9
+ InternalThemeProvider,
10
+ UploaderProvider,
11
+ DefaultEditorConfigProvider,
12
+ PostAutoTranslationContainer
13
+ } from "@blocklet/discuss-kit-ux";
14
+ import { Edit as EditIcon } from "@mui/icons-material";
15
+ import { fetchPost, api } from "./api.mjs";
16
+ import { discussKitService } from "./utils.mjs";
17
+ import { PostEdit } from "./edit.mjs";
18
+ import { PostPaywall } from "./post-paywall.mjs";
19
+ import { translations } from "./locales/index.mjs";
20
+ function InternalPost({ postId, sx, readonly, ...rest }) {
21
+ const { locale } = useLocaleContext();
22
+ const sessionCtx = useContext(SessionContext);
23
+ const isAdmin = ["admin", "owner"].includes(sessionCtx?.session?.user?.role);
24
+ const [editable, setEditable] = useState(false);
25
+ const {
26
+ data: post,
27
+ mutate,
28
+ loading
29
+ } = useRequest(() => fetchPost(postId, locale), { refreshDeps: [postId, locale] });
30
+ const { plugin } = PostAutoTranslationContainer.useContainer();
31
+ if (loading) {
32
+ return EditorPreview.fallback;
33
+ }
34
+ if (!post) {
35
+ return null;
36
+ }
37
+ const handleUpdate = (saved) => {
38
+ mutate((prev) => ({
39
+ ...prev,
40
+ content: saved.content,
41
+ contentVersion: saved.contentVersion
42
+ }));
43
+ };
44
+ const handleSave = (saved) => {
45
+ handleUpdate(saved);
46
+ setEditable(false);
47
+ };
48
+ const mergedSx = [
49
+ {
50
+ position: "relative",
51
+ "&:hover .post-component-edit-button": {
52
+ display: "block"
53
+ }
54
+ },
55
+ ...Array.isArray(sx) ? sx : [sx]
56
+ ];
57
+ return /* @__PURE__ */ jsx(InternalThemeProvider, { children: /* @__PURE__ */ jsx(LocaleProvider, { translations, children: /* @__PURE__ */ jsx(UploaderProvider, { children: /* @__PURE__ */ jsx(DefaultEditorConfigProvider, { request: api, children: /* @__PURE__ */ jsxs(Box, { sx: mergedSx, ...rest, children: [
58
+ !readonly && isAdmin && !editable && /* @__PURE__ */ jsx(
59
+ IconButton,
60
+ {
61
+ className: "post-component-edit-button",
62
+ color: "primary",
63
+ sx: { display: "none", position: "absolute", top: 0, right: 0, zIndex: 1e3 },
64
+ onClick: () => setEditable(true),
65
+ children: /* @__PURE__ */ jsx(EditIcon, {})
66
+ }
67
+ ),
68
+ editable ? /* @__PURE__ */ jsx(PostEdit, { post, onSave: handleSave, onUpdate: handleUpdate, onCancel: () => setEditable(false) }) : /* @__PURE__ */ jsx(PostPaywall, { post, children: /* @__PURE__ */ jsx(EditorPreview, { content: post.content || "", prepend: plugin }) })
69
+ ] }) }) }) }) });
70
+ }
71
+ export function Post(props) {
72
+ if (!discussKitService) {
73
+ return null;
74
+ }
75
+ return /* @__PURE__ */ jsx(InternalPost, { ...props });
76
+ }
77
+ export { PostAutoTranslationContainer };
@@ -0,0 +1,21 @@
1
+ export default {
2
+ draftStatus: {
3
+ idle: "Draft",
4
+ saving: "Saving changes...",
5
+ saved: "Draft saved",
6
+ error: "Failed to save"
7
+ },
8
+ paywall: {
9
+ subscription: {
10
+ title: "This post is for paid subscribers only",
11
+ desc: "Subscribe now to read the full story and get access to all paid posts",
12
+ subscribeNow: "Subscribe now",
13
+ alreadySubscribe: "Already subscribe?"
14
+ }
15
+ },
16
+ common: {
17
+ connect: "Connect"
18
+ },
19
+ save: "Save",
20
+ cancel: "Cancel"
21
+ };
@@ -0,0 +1,7 @@
1
+ import flat from "flat";
2
+ import en from "./en.mjs";
3
+ import zh from "./zh.mjs";
4
+ export const translations = {
5
+ zh: flat(zh),
6
+ en: flat(en)
7
+ };
@@ -0,0 +1,21 @@
1
+ export default {
2
+ paywall: {
3
+ subscription: {
4
+ title: "\u6B64\u5E16\u4EC5\u4F9B\u4ED8\u8D39\u8BA2\u9605\u8005\u4F7F\u7528",
5
+ desc: "\u7ACB\u5373\u8BA2\u9605\u4EE5\u9605\u8BFB\u5B8C\u6574\u5185\u5BB9\u5E76\u83B7\u53D6\u6240\u6709\u76F8\u5173\u5185\u5BB9\u7684\u8BBF\u95EE\u6743\u9650\u3002",
6
+ subscribeNow: "\u7ACB\u5373\u8BA2\u9605",
7
+ alreadySubscribe: "\u5DF2\u7ECF\u8BA2\u9605?"
8
+ }
9
+ },
10
+ draftStatus: {
11
+ idle: "\u8349\u7A3F",
12
+ saving: "\u4FDD\u5B58\u4E2D...",
13
+ saved: "\u8349\u7A3F\u5DF2\u4FDD\u5B58",
14
+ error: "\u4FDD\u5B58\u5931\u8D25"
15
+ },
16
+ common: {
17
+ connect: "\u8FDE\u63A5"
18
+ },
19
+ save: "\u4FDD\u5B58",
20
+ cancel: "\u53D6\u6D88"
21
+ };
@@ -1,5 +1,6 @@
1
+ /// <reference types="react" />
1
2
  import { Post } from './types';
2
3
  export declare function PostPaywall({ post, children, ...rest }: {
3
4
  post: Post;
4
5
  children: React.ReactNode;
5
- }): import("react/jsx-runtime").JSX.Element | null;
6
+ }): import("react").JSX.Element | null;
@@ -0,0 +1,12 @@
1
+ import { Fragment, jsx } from "react/jsx-runtime";
2
+ import { SubscriptionPaywall } from "@blocklet/discuss-kit-ux";
3
+ import { fetchPaymentLink } from "./api.mjs";
4
+ export function PostPaywall({ post, children, ...rest }) {
5
+ if (post.accessType === "public") {
6
+ return /* @__PURE__ */ jsx(Fragment, { children });
7
+ }
8
+ if (post.accessType === "paid") {
9
+ return /* @__PURE__ */ jsx(SubscriptionPaywall, { type: post.type, fetchPaymentLink, ...rest, children });
10
+ }
11
+ return null;
12
+ }
@@ -0,0 +1,7 @@
1
+ import 'unstated-next';
2
+
3
+ declare module 'unstated-next' {
4
+ export function createContainer<Value, State = void>(
5
+ useHook: (initialState: State) => Value
6
+ ): Container<Value, State>;
7
+ }
package/dist/types.mjs ADDED
File without changes
package/dist/utils.d.ts CHANGED
@@ -1,3 +1,3 @@
1
- export declare const discussKitService: ComponentMountPoint | undefined;
1
+ export declare const discussKitService: any;
2
2
  export declare const discussKitPrefix: string;
3
3
  export declare const discussKitApiPrefix: string;
package/dist/utils.mjs ADDED
@@ -0,0 +1,6 @@
1
+ import { joinURL } from "ufo";
2
+ export const discussKitService = window.blocklet?.componentMountPoints?.find(
3
+ (x) => x.did === "z8ia1WEiBZ7hxURf6LwH21Wpg99vophFwSJdu"
4
+ );
5
+ export const discussKitPrefix = discussKitService ? joinURL(discussKitService.mountPoint, "/") : "";
6
+ export const discussKitApiPrefix = joinURL(discussKitPrefix, "/api/");
@@ -0,0 +1 @@
1
+ /// <reference types="vite/client" />
package/package.json CHANGED
@@ -1,33 +1,30 @@
1
1
  {
2
2
  "name": "@blocklet/discuss-kit-post",
3
- "version": "2.4.35",
3
+ "version": "2.4.37",
4
4
  "files": [
5
5
  "dist"
6
6
  ],
7
- "main": "./dist/index.umd.js",
8
- "module": "./dist/index.es.js",
9
- "types": "./dist/index.d.ts",
10
7
  "exports": {
11
- ".": {
12
- "import": "./dist/index.es.js",
13
- "require": "./dist/index.umd.js"
14
- },
15
- "./src/*": "./src/*"
8
+ ".": "./dist/index.mjs"
16
9
  },
10
+ "main": "./dist/index.mjs",
11
+ "module": "./dist/index.mjs",
12
+ "types": "./dist/index.d.ts",
13
+ "sideEffects": false,
17
14
  "publishConfig": {
18
15
  "access": "public"
19
16
  },
20
17
  "dependencies": {
21
- "@blocklet/js-sdk": "^1.16.46",
18
+ "@blocklet/js-sdk": "^1.16.47",
22
19
  "@mui/icons-material": "^7.1.2",
23
20
  "ahooks": "^3.8.1",
24
21
  "flat": "^5.0.2",
25
22
  "ufo": "1.3.1",
26
- "@blocklet/discuss-kit-ux": "2.4.35"
23
+ "@blocklet/discuss-kit-ux": "2.4.37"
27
24
  },
28
25
  "peerDependencies": {
29
- "@arcblock/did-connect": "^3.0.1",
30
- "@arcblock/ux": "^3.0.1",
26
+ "@arcblock/did-connect-react": "^3.1.4",
27
+ "@arcblock/ux": "^3.1.4",
31
28
  "@mui/material": "^7.1.2",
32
29
  "react": "^19.1.0",
33
30
  "react-dom": "^19.1.0"
@@ -55,18 +52,14 @@
55
52
  "react-dom": "^19.1.0",
56
53
  "rollup-plugin-node-externals": "^7.1.3",
57
54
  "typescript": "^4.9.5",
55
+ "unbuild": "^3.6.0",
58
56
  "unplugin-icons": "^0.14.15",
59
57
  "vite": "^7.0.0",
60
58
  "vite-plugin-dts": "^4.5.4",
61
59
  "vite-plugin-libcss": "^1.1.2"
62
60
  },
63
61
  "scripts": {
64
- "dev": "npm run storybook",
65
- "build": "tsc && vite build",
66
- "build:watch": "vite build --watch",
67
- "preview": "vite preview",
68
- "storybook": "start-storybook -p 6006",
69
- "build-storybook": "build-storybook",
62
+ "build": "unbuild",
70
63
  "lint": "eslint src --ext .mjs,.js,.jsx,.ts,.tsx",
71
64
  "lint:fix": "eslint src --ext .mjs,.js,.jsx,.ts,.tsx --fix"
72
65
  }
package/dist/index.es.js DELETED
@@ -1,333 +0,0 @@
1
- import { jsx, jsxs, Fragment } from "react/jsx-runtime";
2
- import { useMediaQuery, Box, CircularProgress, Tooltip, Stack, Button, IconButton } from "@mui/material";
3
- import { useSetState, useGetState, useDocumentVisibility, useRequest, useThrottleEffect, useTimeout } from "ahooks";
4
- import { useLocaleContext, LocaleProvider } from "@arcblock/ux/lib/Locale/context";
5
- import { SessionContext } from "@arcblock/did-connect/lib/Session";
6
- import { useRef, useState, useCallback, useEffect, useContext } from "react";
7
- import { DirtyPromptContainer, useEventCallback, utils, toast, LazyEditor, SubscriptionPaywall, PostAutoTranslationContainer, EditorPreview, InternalThemeProvider, UploaderProvider, DefaultEditorConfigProvider } from "@blocklet/discuss-kit-ux";
8
- import { PostAutoTranslationContainer as PostAutoTranslationContainer2 } from "@blocklet/discuss-kit-ux";
9
- import { Edit } from "@mui/icons-material";
10
- import { createAxios } from "@blocklet/js-sdk";
11
- import { joinURL, withQuery } from "ufo";
12
- import flat from "flat";
13
- const discussKitService = window.blocklet?.componentMountPoints?.find(
14
- (x) => x.did === "z8ia1WEiBZ7hxURf6LwH21Wpg99vophFwSJdu"
15
- );
16
- const discussKitPrefix = discussKitService ? joinURL(discussKitService.mountPoint, "/") : "";
17
- const discussKitApiPrefix = joinURL(discussKitPrefix, "/api/");
18
- const api = createAxios({
19
- baseURL: discussKitApiPrefix,
20
- timeout: 2e4
21
- });
22
- const fetchPost = async (postId, locale) => {
23
- const url = withQuery(joinURL("/posts/slug", postId), { locale });
24
- try {
25
- const result = await api.get(url).then((res) => res.data);
26
- return result;
27
- } catch (e) {
28
- console.error(e);
29
- return null;
30
- }
31
- };
32
- const updatePostContent = async (id, payload) => {
33
- const { data } = await api.put(`/posts/${id}/content`, payload);
34
- return data;
35
- };
36
- const fetchPaymentLink = async (params) => {
37
- const { data } = await api.get("/subscriptions/payment-link", { params });
38
- return data;
39
- };
40
- const useStatus = (saving) => {
41
- const [status, setStatus] = useState("idle");
42
- useEffect(() => {
43
- if (saving) {
44
- setStatus("saving");
45
- } else {
46
- setStatus((prev) => prev === "saving" ? "saved" : "idle");
47
- }
48
- }, [saving]);
49
- useTimeout(
50
- () => {
51
- setStatus("idle");
52
- },
53
- status === "saved" ? 1500 : void 0
54
- );
55
- return status;
56
- };
57
- const useAutoSaveState = (initialState, { save, paused, wait = 1e4 }) => {
58
- const [state, setStateInternal] = useSetState(initialState);
59
- const [pendingState, setPendingState, getPendingState] = useGetState();
60
- const latestState = pendingState || state;
61
- const isInitialState = useRef(true);
62
- const [error, setError] = useState(null);
63
- const documentVisibility = useDocumentVisibility();
64
- const { dirty, reset, markDirty } = DirtyPromptContainer.useContainer();
65
- const { t } = useLocaleContext();
66
- const handleSave = async (s) => {
67
- try {
68
- const result = await utils.minDelay(save(s), 1500);
69
- const pendingState2 = getPendingState();
70
- if (pendingState2) {
71
- setStateInternal(pendingState2);
72
- setPendingState(null);
73
- } else {
74
- reset();
75
- setError(null);
76
- }
77
- return result;
78
- } catch (e) {
79
- setError(e);
80
- toast.error(t("draftStatus.error"));
81
- throw e;
82
- }
83
- };
84
- const { data: saved, loading, run, runAsync } = useRequest(handleSave, { manual: true });
85
- const status = useStatus(loading);
86
- const canSave = !isInitialState.current && !paused && !loading && dirty;
87
- useThrottleEffect(
88
- () => {
89
- if (paused || loading || !dirty || isInitialState.current) {
90
- return;
91
- }
92
- run(state);
93
- },
94
- [state, paused],
95
- { wait, leading: false }
96
- );
97
- const setState = (s) => {
98
- if (loading) {
99
- setPendingState({ ...state, ...s });
100
- } else {
101
- setStateInternal(s);
102
- }
103
- if (isInitialState.current) {
104
- isInitialState.current = false;
105
- }
106
- if (!isInitialState.current) {
107
- markDirty();
108
- }
109
- };
110
- const setInitialState = useCallback(
111
- (s) => {
112
- setStateInternal(s);
113
- isInitialState.current = true;
114
- },
115
- [setStateInternal]
116
- );
117
- const saveNow = useEventCallback(async () => {
118
- if (canSave) {
119
- await runAsync(state);
120
- }
121
- });
122
- useEffect(() => {
123
- if (documentVisibility === "hidden") {
124
- saveNow();
125
- }
126
- }, [documentVisibility, saveNow]);
127
- return { state: latestState, setState, setInitialState, status, saved, saveNow, error };
128
- };
129
- function DraftStatus({ status, error, ...rest }) {
130
- const { t } = useLocaleContext();
131
- const downMd = useMediaQuery((theme) => theme.breakpoints.down("md"));
132
- if (downMd) {
133
- return status !== "idle" ? /* @__PURE__ */ jsx(Box, { sx: { display: { xs: "inline-block", md: "none", lineHeight: 1 } }, component: CircularProgress, size: 16 }) : null;
134
- }
135
- return /* @__PURE__ */ jsxs(Box, { sx: { display: "flex", alignItems: "center", gap: 1 }, ...rest, children: [
136
- /* @__PURE__ */ jsx(Tooltip, { title: error?.message, children: /* @__PURE__ */ jsx(Box, { sx: { width: 8, height: 8, borderRadius: "100%", bgcolor: error ? "error.main" : "success.main" } }) }),
137
- /* @__PURE__ */ jsx(Box, { sx: { color: "grey.600", fontSize: 13, lineHeight: 1 }, component: "span", className: "draft-status-text", children: error ? t("draftStatus.error") : t(`draftStatus.${status}`) })
138
- ] });
139
- }
140
- function InternalPostEdit({ post, onSave, onUpdate, onCancel, ...rest }) {
141
- const { t } = useLocaleContext();
142
- const { reset, check } = DirtyPromptContainer.useContainer();
143
- const save = async (state) => {
144
- if (!post) {
145
- throw new Error("Invalid state");
146
- }
147
- try {
148
- const updated = await updatePostContent(post.id, {
149
- title: state.title,
150
- content: state.content,
151
- locale: post.locale,
152
- contentVersion: post.contentVersion
153
- });
154
- onUpdate(updated);
155
- return updated;
156
- } catch (e) {
157
- console.error(e);
158
- throw e;
159
- }
160
- };
161
- const {
162
- state: autoSaveState,
163
- setState,
164
- status,
165
- error,
166
- saveNow
167
- } = useAutoSaveState({ title: post?.title || "", content: post?.content || "" }, { save });
168
- const handleContentChange = ({ content }) => {
169
- setState({ content });
170
- };
171
- const handleSave = async () => {
172
- const updated = await updatePostContent(post.id, {
173
- title: autoSaveState.title,
174
- content: autoSaveState.content,
175
- locale: post.locale,
176
- contentVersion: post.contentVersion
177
- });
178
- onSave(updated);
179
- };
180
- const handleCancel = async () => {
181
- if (await check()) {
182
- onCancel();
183
- reset();
184
- }
185
- };
186
- return /* @__PURE__ */ jsxs(Box, { ...rest, children: [
187
- /* @__PURE__ */ jsxs(
188
- Stack,
189
- {
190
- direction: "row",
191
- sx: {
192
- justifyContent: "space-between",
193
- alignItems: "center"
194
- },
195
- children: [
196
- /* @__PURE__ */ jsxs(Box, { sx: { mb: 1, display: "flex", gap: 1 }, children: [
197
- /* @__PURE__ */ jsx(Button, { variant: "contained", color: "primary", onClick: () => handleSave(), children: t("save") }),
198
- /* @__PURE__ */ jsx(Button, { variant: "outlined", onClick: handleCancel, children: t("cancel") })
199
- ] }),
200
- /* @__PURE__ */ jsx(DraftStatus, { status, error })
201
- ]
202
- }
203
- ),
204
- /* @__PURE__ */ jsx(
205
- LazyEditor,
206
- {
207
- initialContent: post.content || "",
208
- onChange: handleContentChange,
209
- autoFocus: false,
210
- onSave: () => saveNow()
211
- }
212
- )
213
- ] });
214
- }
215
- function PostEdit(props) {
216
- return /* @__PURE__ */ jsx(DirtyPromptContainer.Provider, { children: /* @__PURE__ */ jsx(InternalPostEdit, { ...props }) });
217
- }
218
- function PostPaywall({ post, children, ...rest }) {
219
- if (post.accessType === "public") {
220
- return /* @__PURE__ */ jsx(Fragment, { children });
221
- }
222
- if (post.accessType === "paid") {
223
- return /* @__PURE__ */ jsx(SubscriptionPaywall, { type: post.type, fetchPaymentLink, ...rest, children });
224
- }
225
- return null;
226
- }
227
- const en = {
228
- draftStatus: {
229
- idle: "Draft",
230
- saving: "Saving changes...",
231
- saved: "Draft saved",
232
- error: "Failed to save"
233
- },
234
- paywall: {
235
- subscription: {
236
- title: "This post is for paid subscribers only",
237
- desc: "Subscribe now to read the full story and get access to all paid posts",
238
- subscribeNow: "Subscribe now",
239
- alreadySubscribe: "Already subscribe?"
240
- }
241
- },
242
- common: {
243
- connect: "Connect"
244
- },
245
- save: "Save",
246
- cancel: "Cancel"
247
- };
248
- const zh = {
249
- paywall: {
250
- subscription: {
251
- title: "此帖仅供付费订阅者使用",
252
- desc: "立即订阅以阅读完整内容并获取所有相关内容的访问权限。",
253
- subscribeNow: "立即订阅",
254
- alreadySubscribe: "已经订阅?"
255
- }
256
- },
257
- draftStatus: {
258
- idle: "草稿",
259
- saving: "保存中...",
260
- saved: "草稿已保存",
261
- error: "保存失败"
262
- },
263
- common: {
264
- connect: "连接"
265
- },
266
- save: "保存",
267
- cancel: "取消"
268
- };
269
- const translations = {
270
- zh: flat(zh),
271
- en: flat(en)
272
- };
273
- function InternalPost({ postId, sx, readonly, ...rest }) {
274
- const { locale } = useLocaleContext();
275
- const sessionCtx = useContext(SessionContext);
276
- const isAdmin = ["admin", "owner"].includes(sessionCtx?.session?.user?.role);
277
- const [editable, setEditable] = useState(false);
278
- const {
279
- data: post,
280
- mutate,
281
- loading
282
- } = useRequest(() => fetchPost(postId, locale), { refreshDeps: [postId, locale] });
283
- const { plugin } = PostAutoTranslationContainer.useContainer();
284
- if (loading) {
285
- return EditorPreview.fallback;
286
- }
287
- if (!post) {
288
- return null;
289
- }
290
- const handleUpdate = (saved) => {
291
- mutate((prev) => ({
292
- ...prev,
293
- content: saved.content,
294
- contentVersion: saved.contentVersion
295
- }));
296
- };
297
- const handleSave = (saved) => {
298
- handleUpdate(saved);
299
- setEditable(false);
300
- };
301
- const mergedSx = [
302
- {
303
- position: "relative",
304
- "&:hover .post-component-edit-button": {
305
- display: "block"
306
- }
307
- },
308
- ...Array.isArray(sx) ? sx : [sx]
309
- ];
310
- return /* @__PURE__ */ jsx(InternalThemeProvider, { children: /* @__PURE__ */ jsx(LocaleProvider, { translations, children: /* @__PURE__ */ jsx(UploaderProvider, { children: /* @__PURE__ */ jsx(DefaultEditorConfigProvider, { request: api, children: /* @__PURE__ */ jsxs(Box, { sx: mergedSx, ...rest, children: [
311
- !readonly && isAdmin && !editable && /* @__PURE__ */ jsx(
312
- IconButton,
313
- {
314
- className: "post-component-edit-button",
315
- color: "primary",
316
- sx: { display: "none", position: "absolute", top: 0, right: 0, zIndex: 1e3 },
317
- onClick: () => setEditable(true),
318
- children: /* @__PURE__ */ jsx(Edit, {})
319
- }
320
- ),
321
- editable ? /* @__PURE__ */ jsx(PostEdit, { post, onSave: handleSave, onUpdate: handleUpdate, onCancel: () => setEditable(false) }) : /* @__PURE__ */ jsx(PostPaywall, { post, children: /* @__PURE__ */ jsx(EditorPreview, { content: post.content || "", prepend: plugin }) })
322
- ] }) }) }) }) });
323
- }
324
- function Post(props) {
325
- if (!discussKitService) {
326
- return null;
327
- }
328
- return /* @__PURE__ */ jsx(InternalPost, { ...props });
329
- }
330
- export {
331
- Post,
332
- PostAutoTranslationContainer2 as PostAutoTranslationContainer
333
- };
package/dist/index.umd.js DELETED
@@ -1,328 +0,0 @@
1
- (function(global, factory) {
2
- typeof exports === "object" && typeof module !== "undefined" ? factory(exports, require("react/jsx-runtime"), require("@mui/material"), require("ahooks"), require("@arcblock/ux/lib/Locale/context"), require("@arcblock/did-connect/lib/Session"), require("react"), require("@blocklet/discuss-kit-ux"), require("@mui/icons-material"), require("@blocklet/js-sdk"), require("ufo"), require("flat")) : typeof define === "function" && define.amd ? define(["exports", "react/jsx-runtime", "@mui/material", "ahooks", "@arcblock/ux/lib/Locale/context", "@arcblock/did-connect/lib/Session", "react", "@blocklet/discuss-kit-ux", "@mui/icons-material", "@blocklet/js-sdk", "ufo", "flat"], factory) : (global = typeof globalThis !== "undefined" ? globalThis : global || self, factory(global.DiscussKitPost = {}, global.jsxRuntime, global.material, global.ahooks, global.context, global.Session, global.react, global.discussKitUx, global.iconsMaterial, global.jsSdk, global.ufo, global.flat));
3
- })(this, function(exports2, jsxRuntime, material, ahooks, context, Session, react, discussKitUx, iconsMaterial, jsSdk, ufo, flat) {
4
- "use strict";
5
- const discussKitService = window.blocklet?.componentMountPoints?.find(
6
- (x) => x.did === "z8ia1WEiBZ7hxURf6LwH21Wpg99vophFwSJdu"
7
- );
8
- const discussKitPrefix = discussKitService ? ufo.joinURL(discussKitService.mountPoint, "/") : "";
9
- const discussKitApiPrefix = ufo.joinURL(discussKitPrefix, "/api/");
10
- const api = jsSdk.createAxios({
11
- baseURL: discussKitApiPrefix,
12
- timeout: 2e4
13
- });
14
- const fetchPost = async (postId, locale) => {
15
- const url = ufo.withQuery(ufo.joinURL("/posts/slug", postId), { locale });
16
- try {
17
- const result = await api.get(url).then((res) => res.data);
18
- return result;
19
- } catch (e) {
20
- console.error(e);
21
- return null;
22
- }
23
- };
24
- const updatePostContent = async (id, payload) => {
25
- const { data } = await api.put(`/posts/${id}/content`, payload);
26
- return data;
27
- };
28
- const fetchPaymentLink = async (params) => {
29
- const { data } = await api.get("/subscriptions/payment-link", { params });
30
- return data;
31
- };
32
- const useStatus = (saving) => {
33
- const [status, setStatus] = react.useState("idle");
34
- react.useEffect(() => {
35
- if (saving) {
36
- setStatus("saving");
37
- } else {
38
- setStatus((prev) => prev === "saving" ? "saved" : "idle");
39
- }
40
- }, [saving]);
41
- ahooks.useTimeout(
42
- () => {
43
- setStatus("idle");
44
- },
45
- status === "saved" ? 1500 : void 0
46
- );
47
- return status;
48
- };
49
- const useAutoSaveState = (initialState, { save, paused, wait = 1e4 }) => {
50
- const [state, setStateInternal] = ahooks.useSetState(initialState);
51
- const [pendingState, setPendingState, getPendingState] = ahooks.useGetState();
52
- const latestState = pendingState || state;
53
- const isInitialState = react.useRef(true);
54
- const [error, setError] = react.useState(null);
55
- const documentVisibility = ahooks.useDocumentVisibility();
56
- const { dirty, reset, markDirty } = discussKitUx.DirtyPromptContainer.useContainer();
57
- const { t } = context.useLocaleContext();
58
- const handleSave = async (s) => {
59
- try {
60
- const result = await discussKitUx.utils.minDelay(save(s), 1500);
61
- const pendingState2 = getPendingState();
62
- if (pendingState2) {
63
- setStateInternal(pendingState2);
64
- setPendingState(null);
65
- } else {
66
- reset();
67
- setError(null);
68
- }
69
- return result;
70
- } catch (e) {
71
- setError(e);
72
- discussKitUx.toast.error(t("draftStatus.error"));
73
- throw e;
74
- }
75
- };
76
- const { data: saved, loading, run, runAsync } = ahooks.useRequest(handleSave, { manual: true });
77
- const status = useStatus(loading);
78
- const canSave = !isInitialState.current && !paused && !loading && dirty;
79
- ahooks.useThrottleEffect(
80
- () => {
81
- if (paused || loading || !dirty || isInitialState.current) {
82
- return;
83
- }
84
- run(state);
85
- },
86
- [state, paused],
87
- { wait, leading: false }
88
- );
89
- const setState = (s) => {
90
- if (loading) {
91
- setPendingState({ ...state, ...s });
92
- } else {
93
- setStateInternal(s);
94
- }
95
- if (isInitialState.current) {
96
- isInitialState.current = false;
97
- }
98
- if (!isInitialState.current) {
99
- markDirty();
100
- }
101
- };
102
- const setInitialState = react.useCallback(
103
- (s) => {
104
- setStateInternal(s);
105
- isInitialState.current = true;
106
- },
107
- [setStateInternal]
108
- );
109
- const saveNow = discussKitUx.useEventCallback(async () => {
110
- if (canSave) {
111
- await runAsync(state);
112
- }
113
- });
114
- react.useEffect(() => {
115
- if (documentVisibility === "hidden") {
116
- saveNow();
117
- }
118
- }, [documentVisibility, saveNow]);
119
- return { state: latestState, setState, setInitialState, status, saved, saveNow, error };
120
- };
121
- function DraftStatus({ status, error, ...rest }) {
122
- const { t } = context.useLocaleContext();
123
- const downMd = material.useMediaQuery((theme) => theme.breakpoints.down("md"));
124
- if (downMd) {
125
- return status !== "idle" ? /* @__PURE__ */ jsxRuntime.jsx(material.Box, { sx: { display: { xs: "inline-block", md: "none", lineHeight: 1 } }, component: material.CircularProgress, size: 16 }) : null;
126
- }
127
- return /* @__PURE__ */ jsxRuntime.jsxs(material.Box, { sx: { display: "flex", alignItems: "center", gap: 1 }, ...rest, children: [
128
- /* @__PURE__ */ jsxRuntime.jsx(material.Tooltip, { title: error?.message, children: /* @__PURE__ */ jsxRuntime.jsx(material.Box, { sx: { width: 8, height: 8, borderRadius: "100%", bgcolor: error ? "error.main" : "success.main" } }) }),
129
- /* @__PURE__ */ jsxRuntime.jsx(material.Box, { sx: { color: "grey.600", fontSize: 13, lineHeight: 1 }, component: "span", className: "draft-status-text", children: error ? t("draftStatus.error") : t(`draftStatus.${status}`) })
130
- ] });
131
- }
132
- function InternalPostEdit({ post, onSave, onUpdate, onCancel, ...rest }) {
133
- const { t } = context.useLocaleContext();
134
- const { reset, check } = discussKitUx.DirtyPromptContainer.useContainer();
135
- const save = async (state) => {
136
- if (!post) {
137
- throw new Error("Invalid state");
138
- }
139
- try {
140
- const updated = await updatePostContent(post.id, {
141
- title: state.title,
142
- content: state.content,
143
- locale: post.locale,
144
- contentVersion: post.contentVersion
145
- });
146
- onUpdate(updated);
147
- return updated;
148
- } catch (e) {
149
- console.error(e);
150
- throw e;
151
- }
152
- };
153
- const {
154
- state: autoSaveState,
155
- setState,
156
- status,
157
- error,
158
- saveNow
159
- } = useAutoSaveState({ title: post?.title || "", content: post?.content || "" }, { save });
160
- const handleContentChange = ({ content }) => {
161
- setState({ content });
162
- };
163
- const handleSave = async () => {
164
- const updated = await updatePostContent(post.id, {
165
- title: autoSaveState.title,
166
- content: autoSaveState.content,
167
- locale: post.locale,
168
- contentVersion: post.contentVersion
169
- });
170
- onSave(updated);
171
- };
172
- const handleCancel = async () => {
173
- if (await check()) {
174
- onCancel();
175
- reset();
176
- }
177
- };
178
- return /* @__PURE__ */ jsxRuntime.jsxs(material.Box, { ...rest, children: [
179
- /* @__PURE__ */ jsxRuntime.jsxs(
180
- material.Stack,
181
- {
182
- direction: "row",
183
- sx: {
184
- justifyContent: "space-between",
185
- alignItems: "center"
186
- },
187
- children: [
188
- /* @__PURE__ */ jsxRuntime.jsxs(material.Box, { sx: { mb: 1, display: "flex", gap: 1 }, children: [
189
- /* @__PURE__ */ jsxRuntime.jsx(material.Button, { variant: "contained", color: "primary", onClick: () => handleSave(), children: t("save") }),
190
- /* @__PURE__ */ jsxRuntime.jsx(material.Button, { variant: "outlined", onClick: handleCancel, children: t("cancel") })
191
- ] }),
192
- /* @__PURE__ */ jsxRuntime.jsx(DraftStatus, { status, error })
193
- ]
194
- }
195
- ),
196
- /* @__PURE__ */ jsxRuntime.jsx(
197
- discussKitUx.LazyEditor,
198
- {
199
- initialContent: post.content || "",
200
- onChange: handleContentChange,
201
- autoFocus: false,
202
- onSave: () => saveNow()
203
- }
204
- )
205
- ] });
206
- }
207
- function PostEdit(props) {
208
- return /* @__PURE__ */ jsxRuntime.jsx(discussKitUx.DirtyPromptContainer.Provider, { children: /* @__PURE__ */ jsxRuntime.jsx(InternalPostEdit, { ...props }) });
209
- }
210
- function PostPaywall({ post, children, ...rest }) {
211
- if (post.accessType === "public") {
212
- return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children });
213
- }
214
- if (post.accessType === "paid") {
215
- return /* @__PURE__ */ jsxRuntime.jsx(discussKitUx.SubscriptionPaywall, { type: post.type, fetchPaymentLink, ...rest, children });
216
- }
217
- return null;
218
- }
219
- const en = {
220
- draftStatus: {
221
- idle: "Draft",
222
- saving: "Saving changes...",
223
- saved: "Draft saved",
224
- error: "Failed to save"
225
- },
226
- paywall: {
227
- subscription: {
228
- title: "This post is for paid subscribers only",
229
- desc: "Subscribe now to read the full story and get access to all paid posts",
230
- subscribeNow: "Subscribe now",
231
- alreadySubscribe: "Already subscribe?"
232
- }
233
- },
234
- common: {
235
- connect: "Connect"
236
- },
237
- save: "Save",
238
- cancel: "Cancel"
239
- };
240
- const zh = {
241
- paywall: {
242
- subscription: {
243
- title: "此帖仅供付费订阅者使用",
244
- desc: "立即订阅以阅读完整内容并获取所有相关内容的访问权限。",
245
- subscribeNow: "立即订阅",
246
- alreadySubscribe: "已经订阅?"
247
- }
248
- },
249
- draftStatus: {
250
- idle: "草稿",
251
- saving: "保存中...",
252
- saved: "草稿已保存",
253
- error: "保存失败"
254
- },
255
- common: {
256
- connect: "连接"
257
- },
258
- save: "保存",
259
- cancel: "取消"
260
- };
261
- const translations = {
262
- zh: flat(zh),
263
- en: flat(en)
264
- };
265
- function InternalPost({ postId, sx, readonly, ...rest }) {
266
- const { locale } = context.useLocaleContext();
267
- const sessionCtx = react.useContext(Session.SessionContext);
268
- const isAdmin = ["admin", "owner"].includes(sessionCtx?.session?.user?.role);
269
- const [editable, setEditable] = react.useState(false);
270
- const {
271
- data: post,
272
- mutate,
273
- loading
274
- } = ahooks.useRequest(() => fetchPost(postId, locale), { refreshDeps: [postId, locale] });
275
- const { plugin } = discussKitUx.PostAutoTranslationContainer.useContainer();
276
- if (loading) {
277
- return discussKitUx.EditorPreview.fallback;
278
- }
279
- if (!post) {
280
- return null;
281
- }
282
- const handleUpdate = (saved) => {
283
- mutate((prev) => ({
284
- ...prev,
285
- content: saved.content,
286
- contentVersion: saved.contentVersion
287
- }));
288
- };
289
- const handleSave = (saved) => {
290
- handleUpdate(saved);
291
- setEditable(false);
292
- };
293
- const mergedSx = [
294
- {
295
- position: "relative",
296
- "&:hover .post-component-edit-button": {
297
- display: "block"
298
- }
299
- },
300
- ...Array.isArray(sx) ? sx : [sx]
301
- ];
302
- return /* @__PURE__ */ jsxRuntime.jsx(discussKitUx.InternalThemeProvider, { children: /* @__PURE__ */ jsxRuntime.jsx(context.LocaleProvider, { translations, children: /* @__PURE__ */ jsxRuntime.jsx(discussKitUx.UploaderProvider, { children: /* @__PURE__ */ jsxRuntime.jsx(discussKitUx.DefaultEditorConfigProvider, { request: api, children: /* @__PURE__ */ jsxRuntime.jsxs(material.Box, { sx: mergedSx, ...rest, children: [
303
- !readonly && isAdmin && !editable && /* @__PURE__ */ jsxRuntime.jsx(
304
- material.IconButton,
305
- {
306
- className: "post-component-edit-button",
307
- color: "primary",
308
- sx: { display: "none", position: "absolute", top: 0, right: 0, zIndex: 1e3 },
309
- onClick: () => setEditable(true),
310
- children: /* @__PURE__ */ jsxRuntime.jsx(iconsMaterial.Edit, {})
311
- }
312
- ),
313
- editable ? /* @__PURE__ */ jsxRuntime.jsx(PostEdit, { post, onSave: handleSave, onUpdate: handleUpdate, onCancel: () => setEditable(false) }) : /* @__PURE__ */ jsxRuntime.jsx(PostPaywall, { post, children: /* @__PURE__ */ jsxRuntime.jsx(discussKitUx.EditorPreview, { content: post.content || "", prepend: plugin }) })
314
- ] }) }) }) }) });
315
- }
316
- function Post(props) {
317
- if (!discussKitService) {
318
- return null;
319
- }
320
- return /* @__PURE__ */ jsxRuntime.jsx(InternalPost, { ...props });
321
- }
322
- Object.defineProperty(exports2, "PostAutoTranslationContainer", {
323
- enumerable: true,
324
- get: () => discussKitUx.PostAutoTranslationContainer
325
- });
326
- exports2.Post = Post;
327
- Object.defineProperty(exports2, Symbol.toStringTag, { value: "Module" });
328
- });