@haklex/rich-ext-dynamic 0.25.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.
@@ -0,0 +1,14 @@
1
+ import { CommandItemConfig } from '@haklex/rich-editor/commands';
2
+ import { EditorConfig, LexicalEditor, LexicalNode, NodeKey } from 'lexical';
3
+ import { ReactElement } from 'react';
4
+ import { DynamicNodePayload, SerializedDynamicNode, DynamicNode } from './DynamicNode';
5
+ export declare class DynamicEditNode extends DynamicNode {
6
+ static commandItems: CommandItemConfig[];
7
+ static clone(node: DynamicEditNode): DynamicEditNode;
8
+ constructor(url: string, props?: Record<string, unknown>, initialHeight?: number, key?: NodeKey);
9
+ static importJSON(serializedNode: SerializedDynamicNode): DynamicEditNode;
10
+ decorate(editor: LexicalEditor, config: EditorConfig): ReactElement;
11
+ }
12
+ export declare function $createDynamicEditNode(payload?: Partial<DynamicNodePayload>): DynamicEditNode;
13
+ export declare function $isDynamicEditNode(node: LexicalNode | null | undefined): node is DynamicEditNode;
14
+ //# sourceMappingURL=DynamicEditNode.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"DynamicEditNode.d.ts","sourceRoot":"","sources":["../src/DynamicEditNode.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,8BAA8B,CAAC;AACtE,OAAO,KAAK,EAAE,YAAY,EAAE,aAAa,EAAE,WAAW,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAGjF,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,OAAO,CAAC;AAG1C,OAAO,KAAK,EAAE,kBAAkB,EAAE,qBAAqB,EAAE,MAAM,eAAe,CAAC;AAC/E,OAAO,EAA0B,WAAW,EAAE,MAAM,eAAe,CAAC;AAQpE,qBAAa,eAAgB,SAAQ,WAAW;IAC9C,MAAM,CAAC,YAAY,EAAE,iBAAiB,EAAE,CAetC;IAEF,MAAM,CAAC,KAAK,CAAC,IAAI,EAAE,eAAe,GAAG,eAAe;gBAKlD,GAAG,EAAE,MAAM,EACX,KAAK,GAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAM,EACnC,aAAa,GAAE,MAA+B,EAC9C,GAAG,CAAC,EAAE,OAAO;IAKf,MAAM,CAAC,UAAU,CAAC,cAAc,EAAE,qBAAqB,GAAG,eAAe;IAQzE,QAAQ,CAAC,MAAM,EAAE,aAAa,EAAE,MAAM,EAAE,YAAY,GAAG,YAAY;CAqBpE;AAED,wBAAgB,sBAAsB,CAAC,OAAO,GAAE,OAAO,CAAC,kBAAkB,CAAM,GAAG,eAAe,CAMjG;AAED,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,WAAW,GAAG,IAAI,GAAG,SAAS,GAAG,IAAI,IAAI,eAAe,CAEhG"}
@@ -0,0 +1,7 @@
1
+ import { NodeKey } from 'lexical';
2
+ import { DynamicSlotProps } from './slot';
3
+ export interface DynamicEditRendererProps extends DynamicSlotProps {
4
+ nodeKey: NodeKey;
5
+ }
6
+ export declare function DynamicEditRenderer(props: DynamicEditRendererProps): import("react/jsx-runtime").JSX.Element;
7
+ //# sourceMappingURL=DynamicEditRenderer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"DynamicEditRenderer.d.ts","sourceRoot":"","sources":["../src/DynamicEditRenderer.tsx"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AASvC,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,QAAQ,CAAC;AAG/C,MAAM,WAAW,wBAAyB,SAAQ,gBAAgB;IAChE,OAAO,EAAE,OAAO,CAAC;CAClB;AAED,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,wBAAwB,2CAclE"}
@@ -0,0 +1,6 @@
1
+ import { DynamicSlotProps } from './slot';
2
+ export interface DynamicHostRendererProps extends DynamicSlotProps {
3
+ validateUrl?: (url: string) => boolean;
4
+ }
5
+ export declare function DynamicHostRenderer({ url, componentProps, initialHeight, validateUrl, }: DynamicHostRendererProps): import("react/jsx-runtime").JSX.Element;
6
+ //# sourceMappingURL=DynamicHostRenderer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"DynamicHostRenderer.d.ts","sourceRoot":"","sources":["../src/DynamicHostRenderer.tsx"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,QAAQ,CAAC;AAG/C,MAAM,WAAW,wBAAyB,SAAQ,gBAAgB;IAChE,WAAW,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC;CACxC;AAaD,wBAAgB,mBAAmB,CAAC,EAClC,GAAG,EACH,cAAc,EACd,aAAa,EACb,WAAW,GACZ,EAAE,wBAAwB,2CAgH1B"}
@@ -0,0 +1,283 @@
1
+ import { DecoratorNode } from "lexical";
2
+ import { useEffect, useRef, useState } from "react";
3
+ import { createRendererDecoration, useColorScheme } from "@haklex/rich-editor/static";
4
+ import { ViewportGate } from "@haklex/rich-editor-ui";
5
+ import { isDynamicComponentModule } from "@haklex/rich-dynamic-protocol";
6
+ import { jsx, jsxs } from "react/jsx-runtime";
7
+ //#region src/styles.css.ts
8
+ var semanticClassNames = {
9
+ root: "rich-dynamic-root",
10
+ host: "rich-dynamic-host",
11
+ placeholder: "rich-dynamic-placeholder",
12
+ error: "rich-dynamic-error",
13
+ settingsButton: "rich-dynamic-settings-button",
14
+ editPanel: "rich-dynamic-edit-panel",
15
+ editField: "rich-dynamic-edit-field",
16
+ editFieldIcon: "rich-dynamic-edit-field-icon",
17
+ editInput: "rich-dynamic-edit-input",
18
+ editTextarea: "rich-dynamic-edit-textarea",
19
+ editError: "rich-dynamic-edit-error"
20
+ };
21
+ var root = "_1b17zou0";
22
+ var host = "_1b17zou1";
23
+ var overlay = "_1b17zou2";
24
+ var settingsButton = "_1b17zou5";
25
+ var editPanel = "_1b17zou6";
26
+ var editField = "_1b17zou7";
27
+ var editFieldIcon = "_1b17zou8";
28
+ var editInput = "_1b17zou9";
29
+ var editTextarea = "_1b17zoua";
30
+ var editError = "_1b17zoub";
31
+ //#endregion
32
+ //#region src/DynamicHostRenderer.tsx
33
+ function parseProps(json) {
34
+ try {
35
+ const value = JSON.parse(json);
36
+ return value && typeof value === "object" ? value : {};
37
+ } catch {
38
+ return {};
39
+ }
40
+ }
41
+ function DynamicHostRenderer({ url, componentProps, initialHeight, validateUrl }) {
42
+ const hostRef = useRef(null);
43
+ const handleRef = useRef(null);
44
+ const latestInputRef = useRef(null);
45
+ const [status, setStatus] = useState("loading");
46
+ const [attempt, setAttempt] = useState(0);
47
+ const theme = useColorScheme();
48
+ const propsJson = JSON.stringify(componentProps ?? {});
49
+ useEffect(() => {
50
+ const input = {
51
+ props: parseProps(propsJson),
52
+ host: { theme }
53
+ };
54
+ latestInputRef.current = input;
55
+ handleRef.current?.update?.(input);
56
+ }, [propsJson, theme]);
57
+ useEffect(() => {
58
+ const container = hostRef.current?.shadowRoot?.firstElementChild;
59
+ if (container instanceof HTMLElement) container.style.minHeight = `${initialHeight}px`;
60
+ }, [initialHeight]);
61
+ useEffect(() => {
62
+ const hostEl = hostRef.current;
63
+ if (!hostEl || !url) return;
64
+ if (validateUrl && !validateUrl(url)) {
65
+ setStatus("error");
66
+ return;
67
+ }
68
+ let cancelled = false;
69
+ setStatus("loading");
70
+ const shadow = hostEl.shadowRoot ?? hostEl.attachShadow({ mode: "open" });
71
+ shadow.replaceChildren();
72
+ const container = document.createElement("div");
73
+ container.style.minHeight = `${initialHeight}px`;
74
+ shadow.append(container);
75
+ import(
76
+ /* @vite-ignore */
77
+ url
78
+ ).then((mod) => {
79
+ if (cancelled) return;
80
+ const component = mod?.default;
81
+ if (!isDynamicComponentModule(component)) throw new Error("module default export does not implement the dynamic mount protocol");
82
+ const input = latestInputRef.current ?? {
83
+ props: parseProps(propsJson),
84
+ host: { theme }
85
+ };
86
+ handleRef.current = component.mount(container, input);
87
+ setStatus("mounted");
88
+ }).catch((error) => {
89
+ if (cancelled) return;
90
+ console.error("[DynamicHostRenderer]", error);
91
+ setStatus("error");
92
+ });
93
+ return () => {
94
+ cancelled = true;
95
+ try {
96
+ handleRef.current?.unmount();
97
+ } catch (error) {
98
+ console.error("[DynamicHostRenderer]", error);
99
+ }
100
+ handleRef.current = null;
101
+ };
102
+ }, [
103
+ url,
104
+ attempt,
105
+ validateUrl
106
+ ]);
107
+ if (!url) return /* @__PURE__ */ jsx("div", {
108
+ className: `${root} ${semanticClassNames.root}`,
109
+ style: { minHeight: initialHeight },
110
+ children: /* @__PURE__ */ jsx("div", {
111
+ className: `${overlay} ${semanticClassNames.placeholder}`,
112
+ children: /* @__PURE__ */ jsx("span", { children: "No component URL" })
113
+ })
114
+ });
115
+ return /* @__PURE__ */ jsxs("div", {
116
+ className: `${root} ${semanticClassNames.root}`,
117
+ style: { minHeight: initialHeight },
118
+ children: [
119
+ /* @__PURE__ */ jsx("div", {
120
+ className: `${host} ${semanticClassNames.host}`,
121
+ ref: hostRef
122
+ }),
123
+ status === "loading" && /* @__PURE__ */ jsx("div", {
124
+ className: `_1b17zou2 ${semanticClassNames.placeholder}`,
125
+ children: /* @__PURE__ */ jsx("span", { children: "Loading component…" })
126
+ }),
127
+ status === "error" && /* @__PURE__ */ jsxs("div", {
128
+ className: `_1b17zou2 ${semanticClassNames.error}`,
129
+ children: [
130
+ /* @__PURE__ */ jsx("span", { children: "Failed to load component" }),
131
+ /* @__PURE__ */ jsx("span", {
132
+ className: "_1b17zou4",
133
+ children: url
134
+ }),
135
+ /* @__PURE__ */ jsx("button", {
136
+ className: "_1b17zou3",
137
+ type: "button",
138
+ onClick: () => setAttempt((n) => n + 1),
139
+ children: "Retry"
140
+ })
141
+ ]
142
+ })
143
+ ]
144
+ });
145
+ }
146
+ //#endregion
147
+ //#region src/DynamicSSRRenderer.tsx
148
+ var DynamicPlaceholder = ({ initialHeight }) => /* @__PURE__ */ jsx("div", {
149
+ "aria-label": "Interactive component",
150
+ className: `${root} ${semanticClassNames.root}`,
151
+ style: { minHeight: initialHeight },
152
+ children: /* @__PURE__ */ jsx("div", {
153
+ className: `${overlay} ${semanticClassNames.placeholder}`,
154
+ children: /* @__PURE__ */ jsx("span", { children: "Interactive component" })
155
+ })
156
+ });
157
+ var DynamicSSRRenderer = (props) => {
158
+ return /* @__PURE__ */ jsx(ViewportGate, {
159
+ fallback: /* @__PURE__ */ jsx(DynamicPlaceholder, { initialHeight: props.initialHeight }),
160
+ children: /* @__PURE__ */ jsx(DynamicHostRenderer, { ...props })
161
+ });
162
+ };
163
+ //#endregion
164
+ //#region src/slot.ts
165
+ var DYNAMIC_NODE_KEY = "Dynamic";
166
+ //#endregion
167
+ //#region \0@oxc-project+runtime@0.132.0/helpers/typeof.js
168
+ function _typeof(o) {
169
+ "@babel/helpers - typeof";
170
+ return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function(o) {
171
+ return typeof o;
172
+ } : function(o) {
173
+ return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o;
174
+ }, _typeof(o);
175
+ }
176
+ //#endregion
177
+ //#region \0@oxc-project+runtime@0.132.0/helpers/toPrimitive.js
178
+ function toPrimitive(t, r) {
179
+ if ("object" != _typeof(t) || !t) return t;
180
+ var e = t[Symbol.toPrimitive];
181
+ if (void 0 !== e) {
182
+ var i = e.call(t, r || "default");
183
+ if ("object" != _typeof(i)) return i;
184
+ throw new TypeError("@@toPrimitive must return a primitive value.");
185
+ }
186
+ return ("string" === r ? String : Number)(t);
187
+ }
188
+ //#endregion
189
+ //#region \0@oxc-project+runtime@0.132.0/helpers/toPropertyKey.js
190
+ function toPropertyKey(t) {
191
+ var i = toPrimitive(t, "string");
192
+ return "symbol" == _typeof(i) ? i : i + "";
193
+ }
194
+ //#endregion
195
+ //#region \0@oxc-project+runtime@0.132.0/helpers/defineProperty.js
196
+ function _defineProperty(e, r, t) {
197
+ return (r = toPropertyKey(r)) in e ? Object.defineProperty(e, r, {
198
+ value: t,
199
+ enumerable: !0,
200
+ configurable: !0,
201
+ writable: !0
202
+ }) : e[r] = t, e;
203
+ }
204
+ //#endregion
205
+ //#region src/DynamicNode.ts
206
+ var DEFAULT_DYNAMIC_HEIGHT = 320;
207
+ var DynamicNode = class DynamicNode extends DecoratorNode {
208
+ static getType() {
209
+ return "dynamic";
210
+ }
211
+ static clone(node) {
212
+ return new DynamicNode(node.__url, node.__props, node.__initialHeight, node.__key);
213
+ }
214
+ constructor(url, props = {}, initialHeight = 320, key) {
215
+ super(key);
216
+ _defineProperty(this, "__url", void 0);
217
+ _defineProperty(this, "__props", void 0);
218
+ _defineProperty(this, "__initialHeight", void 0);
219
+ this.__url = url;
220
+ this.__props = props;
221
+ this.__initialHeight = initialHeight;
222
+ }
223
+ createDOM(_config) {
224
+ const div = document.createElement("div");
225
+ div.className = "rich-dynamic-wrapper";
226
+ return div;
227
+ }
228
+ updateDOM() {
229
+ return false;
230
+ }
231
+ isInline() {
232
+ return false;
233
+ }
234
+ static importJSON(serializedNode) {
235
+ return $createDynamicNode(serializedNode);
236
+ }
237
+ exportJSON() {
238
+ return {
239
+ ...super.exportJSON(),
240
+ type: "dynamic",
241
+ url: this.__url,
242
+ props: this.__props,
243
+ initialHeight: this.__initialHeight,
244
+ version: 1
245
+ };
246
+ }
247
+ getUrl() {
248
+ return this.getLatest().__url;
249
+ }
250
+ setUrl(url) {
251
+ const writable = this.getWritable();
252
+ writable.__url = url;
253
+ }
254
+ getProps() {
255
+ return this.getLatest().__props;
256
+ }
257
+ setProps(props) {
258
+ const writable = this.getWritable();
259
+ writable.__props = props;
260
+ }
261
+ getInitialHeight() {
262
+ return this.getLatest().__initialHeight;
263
+ }
264
+ setInitialHeight(initialHeight) {
265
+ const writable = this.getWritable();
266
+ writable.__initialHeight = initialHeight;
267
+ }
268
+ decorate(_editor, _config) {
269
+ return createRendererDecoration(DYNAMIC_NODE_KEY, DynamicSSRRenderer, {
270
+ url: this.__url,
271
+ componentProps: this.__props,
272
+ initialHeight: this.__initialHeight
273
+ });
274
+ }
275
+ };
276
+ function $createDynamicNode(payload = {}) {
277
+ return new DynamicNode(payload.url ?? "", payload.props ?? {}, payload.initialHeight ?? 320);
278
+ }
279
+ function $isDynamicNode(node) {
280
+ return node instanceof DynamicNode;
281
+ }
282
+ //#endregion
283
+ export { semanticClassNames as _, _defineProperty as a, DynamicHostRenderer as c, editFieldIcon as d, editInput as f, root as g, overlay as h, DynamicNode as i, editError as l, editTextarea as m, $isDynamicNode as n, DYNAMIC_NODE_KEY as o, editPanel as p, DEFAULT_DYNAMIC_HEIGHT as r, DynamicSSRRenderer as s, $createDynamicNode as t, editField as u, settingsButton as v };
@@ -0,0 +1,32 @@
1
+ import { EditorConfig, LexicalEditor, LexicalNode, NodeKey, SerializedLexicalNode, Spread, DecoratorNode } from 'lexical';
2
+ import { ReactElement } from 'react';
3
+ export interface DynamicNodePayload {
4
+ initialHeight: number;
5
+ props: Record<string, unknown>;
6
+ url: string;
7
+ }
8
+ export type SerializedDynamicNode = Spread<DynamicNodePayload, SerializedLexicalNode>;
9
+ export declare const DEFAULT_DYNAMIC_HEIGHT = 320;
10
+ export declare class DynamicNode extends DecoratorNode<ReactElement> {
11
+ __url: string;
12
+ __props: Record<string, unknown>;
13
+ __initialHeight: number;
14
+ static getType(): string;
15
+ static clone(node: DynamicNode): DynamicNode;
16
+ constructor(url: string, props?: Record<string, unknown>, initialHeight?: number, key?: NodeKey);
17
+ createDOM(_config: EditorConfig): HTMLElement;
18
+ updateDOM(): boolean;
19
+ isInline(): boolean;
20
+ static importJSON(serializedNode: SerializedDynamicNode): DynamicNode;
21
+ exportJSON(): SerializedDynamicNode;
22
+ getUrl(): string;
23
+ setUrl(url: string): void;
24
+ getProps(): Record<string, unknown>;
25
+ setProps(props: Record<string, unknown>): void;
26
+ getInitialHeight(): number;
27
+ setInitialHeight(initialHeight: number): void;
28
+ decorate(_editor: LexicalEditor, _config: EditorConfig): ReactElement;
29
+ }
30
+ export declare function $createDynamicNode(payload?: Partial<DynamicNodePayload>): DynamicNode;
31
+ export declare function $isDynamicNode(node: LexicalNode | null | undefined): node is DynamicNode;
32
+ //# sourceMappingURL=DynamicNode.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"DynamicNode.d.ts","sourceRoot":"","sources":["../src/DynamicNode.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,YAAY,EACZ,aAAa,EACb,WAAW,EACX,OAAO,EACP,qBAAqB,EACrB,MAAM,EACP,MAAM,SAAS,CAAC;AACjB,OAAO,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AACxC,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,OAAO,CAAC;AAK1C,MAAM,WAAW,kBAAkB;IACjC,aAAa,EAAE,MAAM,CAAC;IACtB,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC/B,GAAG,EAAE,MAAM,CAAC;CACb;AAED,MAAM,MAAM,qBAAqB,GAAG,MAAM,CAAC,kBAAkB,EAAE,qBAAqB,CAAC,CAAC;AAEtF,eAAO,MAAM,sBAAsB,MAAM,CAAC;AAE1C,qBAAa,WAAY,SAAQ,aAAa,CAAC,YAAY,CAAC;IAC1D,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACjC,eAAe,EAAE,MAAM,CAAC;IAExB,MAAM,CAAC,OAAO,IAAI,MAAM;IAIxB,MAAM,CAAC,KAAK,CAAC,IAAI,EAAE,WAAW,GAAG,WAAW;gBAK1C,GAAG,EAAE,MAAM,EACX,KAAK,GAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAM,EACnC,aAAa,GAAE,MAA+B,EAC9C,GAAG,CAAC,EAAE,OAAO;IAQf,SAAS,CAAC,OAAO,EAAE,YAAY,GAAG,WAAW;IAM7C,SAAS,IAAI,OAAO;IAIpB,QAAQ,IAAI,OAAO;IAInB,MAAM,CAAC,UAAU,CAAC,cAAc,EAAE,qBAAqB,GAAG,WAAW;IAIrE,UAAU,IAAI,qBAAqB;IAWnC,MAAM,IAAI,MAAM;IAIhB,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI;IAKzB,QAAQ,IAAI,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;IAInC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI;IAK9C,gBAAgB,IAAI,MAAM;IAI1B,gBAAgB,CAAC,aAAa,EAAE,MAAM,GAAG,IAAI;IAK7C,QAAQ,CAAC,OAAO,EAAE,aAAa,EAAE,OAAO,EAAE,YAAY,GAAG,YAAY;CAOtE;AAED,wBAAgB,kBAAkB,CAAC,OAAO,GAAE,OAAO,CAAC,kBAAkB,CAAM,GAAG,WAAW,CAMzF;AAED,wBAAgB,cAAc,CAAC,IAAI,EAAE,WAAW,GAAG,IAAI,GAAG,SAAS,GAAG,IAAI,IAAI,WAAW,CAExF"}
@@ -0,0 +1,4 @@
1
+ import { DynamicNodePayload } from './DynamicNode';
2
+ export declare const INSERT_DYNAMIC_COMMAND: import('lexical').LexicalCommand<Partial<DynamicNodePayload> | undefined>;
3
+ export declare function DynamicPlugin(): null;
4
+ //# sourceMappingURL=DynamicPlugin.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"DynamicPlugin.d.ts","sourceRoot":"","sources":["../src/DynamicPlugin.tsx"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAC;AAExD,eAAO,MAAM,sBAAsB,2EAElC,CAAC;AAEF,wBAAgB,aAAa,SAgB5B"}
@@ -0,0 +1,5 @@
1
+ import { FC } from 'react';
2
+ import { DynamicHostRendererProps } from './DynamicHostRenderer';
3
+ export type DynamicSSRRendererProps = DynamicHostRendererProps;
4
+ export declare const DynamicSSRRenderer: FC<DynamicSSRRendererProps>;
5
+ //# sourceMappingURL=DynamicSSRRenderer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"DynamicSSRRenderer.d.ts","sourceRoot":"","sources":["../src/DynamicSSRRenderer.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,EAAE,EAAE,MAAM,OAAO,CAAC;AAEhC,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,uBAAuB,CAAC;AAItE,MAAM,MAAM,uBAAuB,GAAG,wBAAwB,CAAC;AAc/D,eAAO,MAAM,kBAAkB,EAAE,EAAE,CAAC,uBAAuB,CAM1D,CAAC"}
@@ -0,0 +1,13 @@
1
+ export { $createDynamicEditNode, $isDynamicEditNode, DynamicEditNode } from './DynamicEditNode';
2
+ export type { DynamicEditRendererProps } from './DynamicEditRenderer';
3
+ export { DynamicEditRenderer } from './DynamicEditRenderer';
4
+ export type { DynamicHostRendererProps } from './DynamicHostRenderer';
5
+ export { DynamicHostRenderer } from './DynamicHostRenderer';
6
+ export type { DynamicNodePayload, SerializedDynamicNode } from './DynamicNode';
7
+ export { $createDynamicNode, $isDynamicNode, DEFAULT_DYNAMIC_HEIGHT, DynamicNode, } from './DynamicNode';
8
+ export { DynamicPlugin, INSERT_DYNAMIC_COMMAND } from './DynamicPlugin';
9
+ export type { DynamicSSRRendererProps } from './DynamicSSRRenderer';
10
+ export { DynamicSSRRenderer } from './DynamicSSRRenderer';
11
+ export type { DynamicSlotProps } from './slot';
12
+ export { DYNAMIC_NODE_KEY } from './slot';
13
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,sBAAsB,EAAE,kBAAkB,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAChG,YAAY,EAAE,wBAAwB,EAAE,MAAM,uBAAuB,CAAC;AACtE,OAAO,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAC;AAC5D,YAAY,EAAE,wBAAwB,EAAE,MAAM,uBAAuB,CAAC;AACtE,OAAO,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAC;AAC5D,YAAY,EAAE,kBAAkB,EAAE,qBAAqB,EAAE,MAAM,eAAe,CAAC;AAC/E,OAAO,EACL,kBAAkB,EAClB,cAAc,EACd,sBAAsB,EACtB,WAAW,GACZ,MAAM,eAAe,CAAC;AACvB,OAAO,EAAE,aAAa,EAAE,sBAAsB,EAAE,MAAM,iBAAiB,CAAC;AACxE,YAAY,EAAE,uBAAuB,EAAE,MAAM,sBAAsB,CAAC;AACpE,OAAO,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAC1D,YAAY,EAAE,gBAAgB,EAAE,MAAM,QAAQ,CAAC;AAC/C,OAAO,EAAE,gBAAgB,EAAE,MAAM,QAAQ,CAAC"}
package/dist/index.mjs ADDED
@@ -0,0 +1,245 @@
1
+ import { _ as semanticClassNames, a as _defineProperty, c as DynamicHostRenderer, d as editFieldIcon, f as editInput, g as root, h as overlay, i as DynamicNode, m as editTextarea, n as $isDynamicNode, o as DYNAMIC_NODE_KEY, p as editPanel, r as DEFAULT_DYNAMIC_HEIGHT, s as DynamicSSRRenderer, t as $createDynamicNode, u as editField, v as settingsButton } from "./DynamicNode-BVlebpiA.js";
2
+ import { $getNodeByKey, $insertNodes, COMMAND_PRIORITY_EDITOR, createCommand } from "lexical";
3
+ import { Boxes, Braces, Link2, Ruler, Settings2, Trash2 } from "lucide-react";
4
+ import { Suspense, createElement, lazy, useCallback, useEffect, useState } from "react";
5
+ import { useRendererMode } from "@haklex/rich-editor/static";
6
+ import { ActionBar, ActionButton, Popover, PopoverPanel, PopoverTrigger } from "@haklex/rich-editor-ui";
7
+ import { jsx, jsxs } from "react/jsx-runtime";
8
+ import { useLexicalComposerContext } from "@lexical/react/LexicalComposerContext";
9
+ //#region \0rolldown/runtime.js
10
+ var __defProp = Object.defineProperty;
11
+ var __exportAll = (all, no_symbols) => {
12
+ let target = {};
13
+ for (var name in all) __defProp(target, name, {
14
+ get: all[name],
15
+ enumerable: true
16
+ });
17
+ if (!no_symbols) __defProp(target, Symbol.toStringTag, { value: "Module" });
18
+ return target;
19
+ };
20
+ //#endregion
21
+ //#region src/DynamicEditNode.ts
22
+ var LazyEditRenderer = lazy(() => Promise.resolve().then(() => DynamicEditRenderer_exports).then((m) => ({ default: m.DynamicEditRenderer })));
23
+ var DynamicEditNode = class DynamicEditNode extends DynamicNode {
24
+ static clone(node) {
25
+ return new DynamicEditNode(node.__url, node.__props, node.__initialHeight, node.__key);
26
+ }
27
+ constructor(url, props = {}, initialHeight = 320, key) {
28
+ super(url, props, initialHeight, key);
29
+ }
30
+ static importJSON(serializedNode) {
31
+ return new DynamicEditNode(serializedNode.url, serializedNode.props, serializedNode.initialHeight);
32
+ }
33
+ decorate(editor, config) {
34
+ if (!editor.isEditable()) return super.decorate(editor, config);
35
+ return createElement(Suspense, { fallback: createElement("div", {
36
+ className: "rich-dynamic-loading",
37
+ style: {
38
+ minHeight: this.__initialHeight,
39
+ margin: "1.25rem 0"
40
+ }
41
+ }) }, createElement(LazyEditRenderer, {
42
+ url: this.__url,
43
+ componentProps: this.__props,
44
+ initialHeight: this.__initialHeight,
45
+ nodeKey: this.__key
46
+ }));
47
+ }
48
+ };
49
+ _defineProperty(DynamicEditNode, "commandItems", [{
50
+ title: "Dynamic Component",
51
+ icon: createElement(Boxes, { size: 20 }),
52
+ description: "Embed an external interactive component",
53
+ keywords: [
54
+ "dynamic",
55
+ "component",
56
+ "widget",
57
+ "interactive",
58
+ "external"
59
+ ],
60
+ section: "MEDIA",
61
+ placement: ["slash", "toolbar"],
62
+ group: "insert",
63
+ onSelect: (editor) => {
64
+ editor.update(() => {
65
+ $insertNodes([$createDynamicEditNode()]);
66
+ });
67
+ }
68
+ }]);
69
+ function $createDynamicEditNode(payload = {}) {
70
+ return new DynamicEditNode(payload.url ?? "", payload.props ?? {}, payload.initialHeight ?? 320);
71
+ }
72
+ function $isDynamicEditNode(node) {
73
+ return node instanceof DynamicEditNode;
74
+ }
75
+ //#endregion
76
+ //#region src/DynamicEditRenderer.tsx
77
+ var DynamicEditRenderer_exports = /* @__PURE__ */ __exportAll({ DynamicEditRenderer: () => DynamicEditRenderer });
78
+ function DynamicEditRenderer(props) {
79
+ if (useRendererMode() !== "editor") return /* @__PURE__ */ jsx(DynamicSSRRenderer, {
80
+ componentProps: props.componentProps,
81
+ initialHeight: props.initialHeight,
82
+ url: props.url
83
+ });
84
+ return /* @__PURE__ */ jsx(DynamicEditRendererInner, { ...props });
85
+ }
86
+ function DynamicEditRendererInner({ url, componentProps, initialHeight, nodeKey }) {
87
+ const [editor] = useLexicalComposerContext();
88
+ const [open, setOpen] = useState(!url);
89
+ const [editUrl, setEditUrl] = useState(url);
90
+ const [editHeight, setEditHeight] = useState(String(initialHeight));
91
+ const [editProps, setEditProps] = useState(() => JSON.stringify(componentProps ?? {}, null, 2));
92
+ const [propsError, setPropsError] = useState(null);
93
+ const resetDraft = useCallback(() => {
94
+ setEditUrl(url);
95
+ setEditHeight(String(initialHeight));
96
+ setEditProps(JSON.stringify(componentProps ?? {}, null, 2));
97
+ setPropsError(null);
98
+ }, [
99
+ url,
100
+ initialHeight,
101
+ componentProps
102
+ ]);
103
+ useEffect(() => {
104
+ resetDraft();
105
+ }, [resetDraft]);
106
+ const commitChanges = useCallback(() => {
107
+ let parsedProps;
108
+ try {
109
+ const value = JSON.parse(editProps.trim() || "{}");
110
+ if (!value || typeof value !== "object" || Array.isArray(value)) {
111
+ setPropsError("Props must be a JSON object");
112
+ return;
113
+ }
114
+ parsedProps = value;
115
+ } catch {
116
+ setPropsError("Invalid JSON");
117
+ return;
118
+ }
119
+ const parsedHeight = Number(editHeight);
120
+ const nextHeight = Number.isFinite(parsedHeight) && parsedHeight > 0 ? parsedHeight : 320;
121
+ editor.update(() => {
122
+ const node = $getNodeByKey(nodeKey);
123
+ if (!$isDynamicNode(node)) return;
124
+ const dynamicNode = node;
125
+ dynamicNode.setUrl(editUrl.trim());
126
+ dynamicNode.setProps(parsedProps);
127
+ dynamicNode.setInitialHeight(nextHeight);
128
+ });
129
+ setPropsError(null);
130
+ setOpen(false);
131
+ }, [
132
+ editor,
133
+ nodeKey,
134
+ editUrl,
135
+ editHeight,
136
+ editProps
137
+ ]);
138
+ const handleDelete = useCallback(() => {
139
+ editor.update(() => {
140
+ $getNodeByKey(nodeKey)?.remove();
141
+ });
142
+ setOpen(false);
143
+ }, [editor, nodeKey]);
144
+ return /* @__PURE__ */ jsxs("div", {
145
+ className: `${root} ${semanticClassNames.root}`,
146
+ children: [url ? /* @__PURE__ */ jsx(DynamicHostRenderer, {
147
+ componentProps,
148
+ initialHeight,
149
+ url
150
+ }) : /* @__PURE__ */ jsx("div", {
151
+ style: {
152
+ minHeight: initialHeight,
153
+ position: "relative"
154
+ },
155
+ children: /* @__PURE__ */ jsx("div", {
156
+ className: `${overlay} ${semanticClassNames.placeholder}`,
157
+ children: /* @__PURE__ */ jsx("span", { children: "Dynamic component — configure a module URL" })
158
+ })
159
+ }), /* @__PURE__ */ jsxs(Popover, {
160
+ open,
161
+ onOpenChange: (nextOpen) => {
162
+ setOpen(nextOpen);
163
+ if (!nextOpen) resetDraft();
164
+ },
165
+ children: [/* @__PURE__ */ jsx(PopoverTrigger, {
166
+ "aria-label": "Dynamic component settings",
167
+ className: `${settingsButton} ${semanticClassNames.settingsButton}`,
168
+ children: /* @__PURE__ */ jsx(Settings2, { size: 14 })
169
+ }), /* @__PURE__ */ jsxs(PopoverPanel, {
170
+ className: `${editPanel} ${semanticClassNames.editPanel}`,
171
+ side: "bottom",
172
+ sideOffset: 8,
173
+ children: [
174
+ /* @__PURE__ */ jsxs("div", {
175
+ className: `${editField} ${semanticClassNames.editField}`,
176
+ children: [/* @__PURE__ */ jsx(Link2, {
177
+ className: `${editFieldIcon} ${semanticClassNames.editFieldIcon}`,
178
+ size: 14
179
+ }), /* @__PURE__ */ jsx("input", {
180
+ className: `${editInput} ${semanticClassNames.editInput}`,
181
+ placeholder: "Module URL (ESM)",
182
+ type: "url",
183
+ value: editUrl,
184
+ onChange: (e) => setEditUrl(e.target.value)
185
+ })]
186
+ }),
187
+ /* @__PURE__ */ jsxs("div", {
188
+ className: `${editField} ${semanticClassNames.editField}`,
189
+ children: [/* @__PURE__ */ jsx(Ruler, {
190
+ className: `${editFieldIcon} ${semanticClassNames.editFieldIcon}`,
191
+ size: 14
192
+ }), /* @__PURE__ */ jsx("input", {
193
+ className: `${editInput} ${semanticClassNames.editInput}`,
194
+ min: 0,
195
+ placeholder: "Initial height (px)",
196
+ type: "number",
197
+ value: editHeight,
198
+ onChange: (e) => setEditHeight(e.target.value)
199
+ })]
200
+ }),
201
+ /* @__PURE__ */ jsxs("div", {
202
+ className: `${editField} ${semanticClassNames.editField}`,
203
+ children: [/* @__PURE__ */ jsx(Braces, {
204
+ className: `${editFieldIcon} ${semanticClassNames.editFieldIcon}`,
205
+ size: 14
206
+ }), /* @__PURE__ */ jsx("textarea", {
207
+ className: `${editTextarea} ${semanticClassNames.editTextarea}`,
208
+ placeholder: "Props JSON, e.g. {\"level\": 1}",
209
+ spellCheck: false,
210
+ value: editProps,
211
+ onChange: (e) => setEditProps(e.target.value)
212
+ })]
213
+ }),
214
+ propsError && /* @__PURE__ */ jsx("span", {
215
+ className: `_1b17zoub ${semanticClassNames.editError}`,
216
+ children: propsError
217
+ }),
218
+ /* @__PURE__ */ jsxs(ActionBar, { children: [/* @__PURE__ */ jsx(ActionButton, {
219
+ onClick: commitChanges,
220
+ children: "Apply"
221
+ }), /* @__PURE__ */ jsxs(ActionButton, {
222
+ danger: true,
223
+ onClick: handleDelete,
224
+ children: [/* @__PURE__ */ jsx(Trash2, { size: 14 }), "Remove"]
225
+ })] })
226
+ ]
227
+ })]
228
+ })]
229
+ });
230
+ }
231
+ //#endregion
232
+ //#region src/DynamicPlugin.tsx
233
+ var INSERT_DYNAMIC_COMMAND = createCommand("INSERT_DYNAMIC");
234
+ function DynamicPlugin() {
235
+ const [editor] = useLexicalComposerContext();
236
+ useEffect(() => {
237
+ return editor.registerCommand(INSERT_DYNAMIC_COMMAND, (payload) => {
238
+ $insertNodes([$createDynamicEditNode(payload ?? {})]);
239
+ return true;
240
+ }, COMMAND_PRIORITY_EDITOR);
241
+ }, [editor]);
242
+ return null;
243
+ }
244
+ //#endregion
245
+ export { $createDynamicEditNode, $createDynamicNode, $isDynamicEditNode, $isDynamicNode, DEFAULT_DYNAMIC_HEIGHT, DYNAMIC_NODE_KEY, DynamicEditNode, DynamicEditRenderer, DynamicHostRenderer, DynamicNode, DynamicPlugin, DynamicSSRRenderer, INSERT_DYNAMIC_COMMAND };
@@ -0,0 +1,2 @@
1
+ :root{--rc-text:#000;--rc-text-secondary:#262626;--rc-text-tertiary:#737373;--rc-text-quaternary:#a3a3a3;--rc-bg:#fff;--rc-bg-secondary:#fafafa;--rc-bg-tertiary:#f5f5f5;--rc-fill:#e8e8e8;--rc-fill-secondary:#eee;--rc-fill-tertiary:#f5f5f5;--rc-fill-quaternary:#fafafa;--rc-border:#f5f5f5;--rc-accent:#2563eb;--rc-accent-light:#2563eb20;--rc-link:#2563eb;--rc-code-text:#404040;--rc-code-bg:#f5f5f5;--rc-hr-border:#e5e5e5;--rc-quote-border:#2563eb;--rc-quote-bg:#f5f5f5;--rc-alert-info:#006bb7;--rc-alert-warning:#c50;--rc-alert-tip:#1c0;--rc-alert-caution:#c01;--rc-alert-important:#50c;--rc-max-width:700px;--rc-shadow-top-bar:0 8px 30px #0000001f, 0 2px 8px #0000000f;--rc-shadow-modal:0 10px 15px -3px #0000001a, 0 4px 6px -4px #0000001a;--rc-shadow-menu:0 1px 4px #0000000a, 0 4px 16px #00000014;--rc-space-xs:4px;--rc-space-sm:8px;--rc-space-md:16px;--rc-space-lg:24px;--rc-space-xl:32px;--rc-font-family-sans:"PingFang SC", "Microsoft YaHei", "Segoe UI", Roboto, Helvetica, "noto sans sc", "hiragino sans gb", -apple-system, system-ui, sans-serif, Apple Color Emoji, Segoe UI Emoji, Not Color Emoji;--rc-font-family-serif:"Noto Serif CJK SC", "Source Han Serif SC", "Source Han Serif", "source-han-serif-sc", "Songti SC", STSong, "华文宋体", serif;--rc-font-family-kai:"楷体", KaiTi, STKaiti, "Kaiti SC", "LXGW WenKai", "霞鹜文楷", "Noto Serif CJK SC", serif;--rc-font-mono:"SF Mono", SFMono-Regular, ui-monospace, "DejaVu Sans Mono", Menlo, Consolas, monospace;--rc-font-size-2xs:.625em;--rc-font-size-xs:.75em;--rc-font-size-sm:.8125em;--rc-font-size-md:.875em;--rc-font-size-lg:1.25em;--rc-font-size-base:16px;--rc-font-size-small:14px;--rc-line-height:1.7;--rc-line-height-tight:1.4;--rc-font-family:"PingFang SC", "Microsoft YaHei", "Segoe UI", Roboto, Helvetica, "noto sans sc", "hiragino sans gb", -apple-system, system-ui, sans-serif, Apple Color Emoji, Segoe UI Emoji, Not Color Emoji;--rc-radius-sm:4px;--rc-radius-md:8px;--rc-radius-lg:12px}:root.dark,[data-theme=dark]{--rc-text:#fafafa;--rc-text-secondary:#a3a3a3;--rc-text-tertiary:#737373;--rc-text-quaternary:#525252;--rc-bg:#0a0a0a;--rc-bg-secondary:#171717;--rc-bg-tertiary:#262626;--rc-fill:#2a2a2a;--rc-fill-secondary:#222;--rc-fill-tertiary:#1a1a1a;--rc-fill-quaternary:#141414;--rc-border:#262626;--rc-accent:#60a5fa;--rc-accent-light:#60a5fa20;--rc-link:#60a5fa;--rc-code-text:#d4d4d4;--rc-code-bg:#262626;--rc-hr-border:#262626;--rc-quote-border:#60a5fa;--rc-quote-bg:#262626;--rc-alert-info:#7db9e5;--rc-alert-warning:#da864a;--rc-alert-tip:#54da48;--rc-alert-caution:#e16973;--rc-alert-important:#9966e0;--rc-shadow-top-bar:0 8px 30px #00000073, 0 2px 8px #0000004d;--rc-shadow-modal:0 10px 15px -3px #0006, 0 4px 6px -4px #00000059;--rc-shadow-menu:0 1px 4px #00000040, 0 4px 16px #0006}.gk60bp0{--rc-text:#000;--rc-text-secondary:#262626;--rc-text-tertiary:#737373;--rc-text-quaternary:#a3a3a3;--rc-bg:#fff;--rc-bg-secondary:#fafafa;--rc-bg-tertiary:#f5f5f5;--rc-fill:#e8e8e8;--rc-fill-secondary:#eee;--rc-fill-tertiary:#f5f5f5;--rc-fill-quaternary:#fafafa;--rc-border:#f5f5f5;--rc-accent:#2563eb;--rc-accent-light:#2563eb20;--rc-link:#2563eb;--rc-code-text:#404040;--rc-code-bg:#f5f5f5;--rc-hr-border:#e5e5e5;--rc-quote-border:#2563eb;--rc-quote-bg:#f5f5f5;--rc-alert-info:#006bb7;--rc-alert-warning:#c50;--rc-alert-tip:#1c0;--rc-alert-caution:#c01;--rc-alert-important:#50c;--rc-max-width:700px;--rc-shadow-top-bar:0 8px 30px #0000001f, 0 2px 8px #0000000f;--rc-shadow-modal:0 10px 15px -3px #0000001a, 0 4px 6px -4px #0000001a;--rc-shadow-menu:0 1px 4px #0000000a, 0 4px 16px #00000014;--rc-space-xs:4px;--rc-space-sm:8px;--rc-space-md:16px;--rc-space-lg:24px;--rc-space-xl:32px;--rc-font-family-sans:"PingFang SC", "Microsoft YaHei", "Segoe UI", Roboto, Helvetica, "noto sans sc", "hiragino sans gb", -apple-system, system-ui, sans-serif, Apple Color Emoji, Segoe UI Emoji, Not Color Emoji;--rc-font-family-serif:"Noto Serif CJK SC", "Source Han Serif SC", "Source Han Serif", "source-han-serif-sc", "Songti SC", STSong, "华文宋体", serif;--rc-font-family-kai:"楷体", KaiTi, STKaiti, "Kaiti SC", "LXGW WenKai", "霞鹜文楷", "Noto Serif CJK SC", serif;--rc-font-mono:"SF Mono", SFMono-Regular, ui-monospace, "DejaVu Sans Mono", Menlo, Consolas, monospace;--rc-font-size-2xs:.625em;--rc-font-size-xs:.75em;--rc-font-size-sm:.8125em;--rc-font-size-md:.875em;--rc-font-size-lg:1.25em;--rc-font-size-base:16px;--rc-font-size-small:14px;--rc-line-height:1.7;--rc-line-height-tight:1.4;--rc-font-family:"PingFang SC", "Microsoft YaHei", "Segoe UI", Roboto, Helvetica, "noto sans sc", "hiragino sans gb", -apple-system, system-ui, sans-serif, Apple Color Emoji, Segoe UI Emoji, Not Color Emoji;--rc-radius-sm:4px;--rc-radius-md:8px;--rc-radius-lg:12px}.gk60bp1{--rc-text:#000;--rc-text-secondary:#262626;--rc-text-tertiary:#737373;--rc-text-quaternary:#a3a3a3;--rc-bg:#fff;--rc-bg-secondary:#fafafa;--rc-bg-tertiary:#f5f5f5;--rc-fill:#e8e8e8;--rc-fill-secondary:#eee;--rc-fill-tertiary:#f5f5f5;--rc-fill-quaternary:#fafafa;--rc-border:#f5f5f5;--rc-accent:#2563eb;--rc-accent-light:#2563eb20;--rc-link:#2563eb;--rc-code-text:#404040;--rc-code-bg:#f5f5f5;--rc-hr-border:#e5e5e5;--rc-quote-border:#2563eb;--rc-quote-bg:#f5f5f5;--rc-alert-info:#006bb7;--rc-alert-warning:#c50;--rc-alert-tip:#1c0;--rc-alert-caution:#c01;--rc-alert-important:#50c;--rc-max-width:700px;--rc-shadow-top-bar:0 8px 30px #0000001f, 0 2px 8px #0000000f;--rc-shadow-modal:0 10px 15px -3px #0000001a, 0 4px 6px -4px #0000001a;--rc-shadow-menu:0 1px 4px #0000000a, 0 4px 16px #00000014;--rc-space-xs:4px;--rc-space-sm:8px;--rc-space-md:16px;--rc-space-lg:24px;--rc-space-xl:32px;--rc-font-family-sans:"PingFang SC", "Microsoft YaHei", "Segoe UI", Roboto, Helvetica, "noto sans sc", "hiragino sans gb", -apple-system, system-ui, sans-serif, Apple Color Emoji, Segoe UI Emoji, Not Color Emoji;--rc-font-family-serif:"Noto Serif CJK SC", "Source Han Serif SC", "Source Han Serif", "source-han-serif-sc", "Songti SC", STSong, "华文宋体", serif;--rc-font-family-kai:"楷体", KaiTi, STKaiti, "Kaiti SC", "LXGW WenKai", "霞鹜文楷", "Noto Serif CJK SC", serif;--rc-font-mono:"SF Mono", SFMono-Regular, ui-monospace, "DejaVu Sans Mono", Menlo, Consolas, monospace;--rc-font-size-2xs:.625em;--rc-font-size-xs:.75em;--rc-font-size-sm:.8125em;--rc-font-size-md:.875em;--rc-font-size-lg:1.25em;--rc-font-size-base:16px;--rc-font-size-small:14px;--rc-line-height:1.8;--rc-line-height-tight:1.4;--rc-font-family:"Noto Serif CJK SC", "Source Han Serif SC", "Source Han Serif", "source-han-serif-sc", "Songti SC", STSong, "华文宋体", serif;--rc-radius-sm:4px;--rc-radius-md:8px;--rc-radius-lg:12px}.gk60bp2{--rc-text:#000;--rc-text-secondary:#262626;--rc-text-tertiary:#737373;--rc-text-quaternary:#a3a3a3;--rc-bg:#fff;--rc-bg-secondary:#fafafa;--rc-bg-tertiary:#f5f5f5;--rc-fill:#e8e8e8;--rc-fill-secondary:#eee;--rc-fill-tertiary:#f5f5f5;--rc-fill-quaternary:#fafafa;--rc-border:#f5f5f5;--rc-accent:#2563eb;--rc-accent-light:#2563eb20;--rc-link:#2563eb;--rc-code-text:#404040;--rc-code-bg:#f5f5f5;--rc-hr-border:#e5e5e5;--rc-quote-border:#a3a3a3;--rc-quote-bg:#fafafa;--rc-alert-info:#006bb7;--rc-alert-warning:#c50;--rc-alert-tip:#1c0;--rc-alert-caution:#c01;--rc-alert-important:#50c;--rc-max-width:none;--rc-shadow-top-bar:0 8px 30px #0000001f, 0 2px 8px #0000000f;--rc-shadow-modal:0 10px 15px -3px #0000001a, 0 4px 6px -4px #0000001a;--rc-shadow-menu:0 1px 4px #0000000a, 0 4px 16px #00000014;--rc-space-xs:2px;--rc-space-sm:4px;--rc-space-md:10px;--rc-space-lg:16px;--rc-space-xl:20px;--rc-font-family-sans:"PingFang SC", "Microsoft YaHei", "Segoe UI", Roboto, Helvetica, "noto sans sc", "hiragino sans gb", -apple-system, system-ui, sans-serif, Apple Color Emoji, Segoe UI Emoji, Not Color Emoji;--rc-font-family-serif:"Noto Serif CJK SC", "Source Han Serif SC", "Source Han Serif", "source-han-serif-sc", "Songti SC", STSong, "华文宋体", serif;--rc-font-family-kai:"楷体", KaiTi, STKaiti, "Kaiti SC", "LXGW WenKai", "霞鹜文楷", "Noto Serif CJK SC", serif;--rc-font-mono:"SF Mono", SFMono-Regular, ui-monospace, "DejaVu Sans Mono", Menlo, Consolas, monospace;--rc-font-size-2xs:.625em;--rc-font-size-xs:.75em;--rc-font-size-sm:.8125em;--rc-font-size-md:.875em;--rc-font-size-lg:1.25em;--rc-font-size-base:14px;--rc-font-size-small:12px;--rc-line-height:1.5;--rc-line-height-tight:1.3;--rc-font-family:"PingFang SC", "Microsoft YaHei", "Segoe UI", Roboto, Helvetica, "noto sans sc", "hiragino sans gb", -apple-system, system-ui, sans-serif, Apple Color Emoji, Segoe UI Emoji, Not Color Emoji;--rc-radius-sm:3px;--rc-radius-md:6px;--rc-radius-lg:12px}.dark .gk60bp0,[data-theme=dark] .gk60bp0,.dark.gk60bp0,[data-theme=dark].gk60bp0,.dark .gk60bp1,[data-theme=dark] .gk60bp1,.dark.gk60bp1,[data-theme=dark].gk60bp1,.dark .gk60bp2,[data-theme=dark] .gk60bp2,.dark.gk60bp2,[data-theme=dark].gk60bp2{--rc-text:#fafafa;--rc-text-secondary:#a3a3a3;--rc-text-tertiary:#737373;--rc-text-quaternary:#525252;--rc-bg:#0a0a0a;--rc-bg-secondary:#171717;--rc-bg-tertiary:#262626;--rc-fill:#2a2a2a;--rc-fill-secondary:#222;--rc-fill-tertiary:#1a1a1a;--rc-fill-quaternary:#141414;--rc-border:#262626;--rc-accent:#60a5fa;--rc-accent-light:#60a5fa20;--rc-link:#60a5fa;--rc-code-text:#d4d4d4;--rc-code-bg:#262626;--rc-hr-border:#262626;--rc-quote-border:#60a5fa;--rc-quote-bg:#262626;--rc-alert-info:#7db9e5;--rc-alert-warning:#da864a;--rc-alert-tip:#54da48;--rc-alert-caution:#e16973;--rc-alert-important:#9966e0;--rc-shadow-top-bar:0 8px 30px #00000073, 0 2px 8px #0000004d;--rc-shadow-modal:0 10px 15px -3px #0006, 0 4px 6px -4px #00000059;--rc-shadow-menu:0 1px 4px #00000040, 0 4px 16px #0006}._1b17zou0{margin:1.25rem 0;position:relative}._1b17zou1{width:100%}._1b17zou2{border-radius:var(--rc-radius-md);border:1px dashed var(--rc-border);background-color:var(--rc-bg-secondary);color:var(--rc-text-tertiary);font-family:var(--rc-font-family-sans);font-size:var(--rc-font-size-sm);flex-direction:column;justify-content:center;align-items:center;gap:8px;display:flex;position:absolute;top:0;bottom:0;left:0;right:0}._1b17zou3{-webkit-appearance:none;appearance:none;border:1px solid var(--rc-border);border-radius:var(--rc-radius-sm);background-color:var(--rc-bg);color:var(--rc-text-secondary);font-size:var(--rc-font-size-sm);cursor:pointer;padding:4px 12px}._1b17zou3:hover{background-color:var(--rc-fill-secondary)}._1b17zou4{text-overflow:ellipsis;white-space:nowrap;max-width:80%;font-family:var(--rc-font-mono);font-size:var(--rc-font-size-xs);color:var(--rc-text-quaternary);overflow:hidden}._1b17zou5{z-index:1;-webkit-appearance:none;appearance:none;border:1px solid var(--rc-border);border-radius:var(--rc-radius-sm);background-color:var(--rc-bg);width:28px;height:28px;color:var(--rc-text-secondary);cursor:pointer;opacity:0;justify-content:center;align-items:center;transition:opacity .15s;display:inline-flex;position:absolute;top:8px;right:8px}._1b17zou0:hover ._1b17zou5,._1b17zou5[data-popup-open]{opacity:1}._1b17zou5:focus-visible{opacity:1}._1b17zou6{width:340px;font-family:var(--rc-font-family-sans);flex-direction:column;gap:8px;padding:12px;display:flex}._1b17zou7{background-color:var(--rc-bg-secondary);border-radius:6px;align-items:center;gap:8px;min-width:0;padding:6px 10px;display:flex}._1b17zou8{color:var(--rc-text-secondary);flex-shrink:0}._1b17zou9{-webkit-appearance:none;appearance:none;color:inherit;font-size:var(--rc-font-size-sm);background-color:#0000;border:none;outline:none;flex:1;min-width:0;padding:0}._1b17zou9::placeholder{color:var(--rc-text-secondary)}._1b17zoua{resize:vertical;-webkit-appearance:none;appearance:none;background-color:var(--rc-bg-secondary);width:100%;min-height:72px;color:inherit;font-family:var(--rc-font-mono);font-size:var(--rc-font-size-xs);border:none;border-radius:6px;outline:none;padding:6px 10px}._1b17zoua::placeholder{color:var(--rc-text-secondary);font-family:var(--rc-font-family-sans)}._1b17zoub{color:var(--rc-alert-caution);font-size:var(--rc-font-size-sm)}
2
+ /*$vite$:1*/
package/dist/slot.d.ts ADDED
@@ -0,0 +1,13 @@
1
+ import { ComponentType } from 'react';
2
+ export declare const DYNAMIC_NODE_KEY: "Dynamic";
3
+ export interface DynamicSlotProps {
4
+ componentProps: Record<string, unknown>;
5
+ initialHeight: number;
6
+ url: string;
7
+ }
8
+ declare module '@haklex/rich-editor/static' {
9
+ interface RendererConfig {
10
+ Dynamic?: ComponentType<DynamicSlotProps>;
11
+ }
12
+ }
13
+ //# sourceMappingURL=slot.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"slot.d.ts","sourceRoot":"","sources":["../src/slot.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,OAAO,CAAC;AAE3C,eAAO,MAAM,gBAAgB,EAAG,SAAkB,CAAC;AAEnD,MAAM,WAAW,gBAAgB;IAC/B,cAAc,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACxC,aAAa,EAAE,MAAM,CAAC;IACtB,GAAG,EAAE,MAAM,CAAC;CACb;AAED,OAAO,QAAQ,4BAA4B,CAAC;IAC1C,UAAU,cAAc;QACtB,OAAO,CAAC,EAAE,aAAa,CAAC,gBAAgB,CAAC,CAAC;KAC3C;CACF"}
@@ -0,0 +1,9 @@
1
+ export type { DynamicHostRendererProps } from './DynamicHostRenderer';
2
+ export { DynamicHostRenderer } from './DynamicHostRenderer';
3
+ export type { DynamicNodePayload, SerializedDynamicNode } from './DynamicNode';
4
+ export { $createDynamicNode, $isDynamicNode, DEFAULT_DYNAMIC_HEIGHT, DynamicNode, } from './DynamicNode';
5
+ export type { DynamicSSRRendererProps } from './DynamicSSRRenderer';
6
+ export { DynamicSSRRenderer } from './DynamicSSRRenderer';
7
+ export type { DynamicSlotProps } from './slot';
8
+ export { DYNAMIC_NODE_KEY } from './slot';
9
+ //# sourceMappingURL=static.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"static.d.ts","sourceRoot":"","sources":["../src/static.ts"],"names":[],"mappings":"AAAA,YAAY,EAAE,wBAAwB,EAAE,MAAM,uBAAuB,CAAC;AACtE,OAAO,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAC;AAC5D,YAAY,EAAE,kBAAkB,EAAE,qBAAqB,EAAE,MAAM,eAAe,CAAC;AAC/E,OAAO,EACL,kBAAkB,EAClB,cAAc,EACd,sBAAsB,EACtB,WAAW,GACZ,MAAM,eAAe,CAAC;AACvB,YAAY,EAAE,uBAAuB,EAAE,MAAM,sBAAsB,CAAC;AACpE,OAAO,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAC1D,YAAY,EAAE,gBAAgB,EAAE,MAAM,QAAQ,CAAC;AAC/C,OAAO,EAAE,gBAAgB,EAAE,MAAM,QAAQ,CAAC"}
@@ -0,0 +1,2 @@
1
+ import { c as DynamicHostRenderer, i as DynamicNode, n as $isDynamicNode, o as DYNAMIC_NODE_KEY, r as DEFAULT_DYNAMIC_HEIGHT, s as DynamicSSRRenderer, t as $createDynamicNode } from "./DynamicNode-BVlebpiA.js";
2
+ export { $createDynamicNode, $isDynamicNode, DEFAULT_DYNAMIC_HEIGHT, DYNAMIC_NODE_KEY, DynamicHostRenderer, DynamicNode, DynamicSSRRenderer };
@@ -0,0 +1,26 @@
1
+ export declare const semanticClassNames: {
2
+ readonly root: "rich-dynamic-root";
3
+ readonly host: "rich-dynamic-host";
4
+ readonly placeholder: "rich-dynamic-placeholder";
5
+ readonly error: "rich-dynamic-error";
6
+ readonly settingsButton: "rich-dynamic-settings-button";
7
+ readonly editPanel: "rich-dynamic-edit-panel";
8
+ readonly editField: "rich-dynamic-edit-field";
9
+ readonly editFieldIcon: "rich-dynamic-edit-field-icon";
10
+ readonly editInput: "rich-dynamic-edit-input";
11
+ readonly editTextarea: "rich-dynamic-edit-textarea";
12
+ readonly editError: "rich-dynamic-edit-error";
13
+ };
14
+ export declare const root: string;
15
+ export declare const host: string;
16
+ export declare const overlay: string;
17
+ export declare const retryButton: string;
18
+ export declare const errorUrl: string;
19
+ export declare const settingsButton: string;
20
+ export declare const editPanel: string;
21
+ export declare const editField: string;
22
+ export declare const editFieldIcon: string;
23
+ export declare const editInput: string;
24
+ export declare const editTextarea: string;
25
+ export declare const editError: string;
26
+ //# sourceMappingURL=styles.css.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"styles.css.d.ts","sourceRoot":"","sources":["../src/styles.css.ts"],"names":[],"mappings":"AAGA,eAAO,MAAM,kBAAkB;;;;;;;;;;;;CAYrB,CAAC;AAEX,eAAO,MAAM,IAAI,QAGf,CAAC;AAEH,eAAO,MAAM,IAAI,QAEf,CAAC;AAEH,eAAO,MAAM,OAAO,QAclB,CAAC;AAEH,eAAO,MAAM,WAAW,QActB,CAAC;AAEH,eAAO,MAAM,QAAQ,QAQnB,CAAC;AAEH,eAAO,MAAM,cAAc,QAuBzB,CAAC;AAEH,eAAO,MAAM,SAAS,QAOpB,CAAC;AAEH,eAAO,MAAM,SAAS,QAQpB,CAAC;AAEH,eAAO,MAAM,aAAa,QAGxB,CAAC;AAEH,eAAO,MAAM,SAAS,QAepB,CAAC;AAEH,eAAO,MAAM,YAAY,QAmBvB,CAAC;AAEH,eAAO,MAAM,SAAS,QAGpB,CAAC"}
package/package.json ADDED
@@ -0,0 +1,62 @@
1
+ {
2
+ "name": "@haklex/rich-ext-dynamic",
3
+ "version": "0.25.0",
4
+ "description": "Dynamic external component extension",
5
+ "repository": {
6
+ "type": "git",
7
+ "url": "https://github.com/Innei/haklex.git",
8
+ "directory": "packages/rich-ext-dynamic"
9
+ },
10
+ "license": "MIT",
11
+ "type": "module",
12
+ "exports": {
13
+ ".": {
14
+ "import": "./dist/index.mjs",
15
+ "types": "./dist/index.d.ts"
16
+ },
17
+ "./static": {
18
+ "import": "./dist/static.mjs",
19
+ "types": "./dist/static.d.ts"
20
+ },
21
+ "./style.css": "./dist/rich-ext-dynamic.css"
22
+ },
23
+ "main": "./dist/index.mjs",
24
+ "files": [
25
+ "dist"
26
+ ],
27
+ "dependencies": {
28
+ "@haklex/rich-dynamic-protocol": "0.25.0"
29
+ },
30
+ "devDependencies": {
31
+ "@lexical/react": "^0.45.0",
32
+ "@types/react": "^19.2.15",
33
+ "@types/react-dom": "^19.2.3",
34
+ "@vanilla-extract/css": "^1.20.1",
35
+ "@vanilla-extract/vite-plugin": "^5.2.2",
36
+ "lexical": "^0.45.0",
37
+ "lucide-react": "^1.17.0",
38
+ "react": "19.2.6",
39
+ "react-dom": "19.2.6",
40
+ "typescript": "^5.9.3",
41
+ "unplugin-dts": "^1.0.1",
42
+ "vite": "^8.0.14"
43
+ },
44
+ "peerDependencies": {
45
+ "@lexical/react": "^0.45.0",
46
+ "lexical": "^0.45.0",
47
+ "lucide-react": "^1.0.0",
48
+ "react": ">=19",
49
+ "react-dom": ">=19",
50
+ "@haklex/rich-editor": "0.25.0",
51
+ "@haklex/rich-editor-ui": "0.25.0",
52
+ "@haklex/rich-style-token": "0.25.0"
53
+ },
54
+ "publishConfig": {
55
+ "access": "public"
56
+ },
57
+ "scripts": {
58
+ "build": "vite build",
59
+ "dev:build": "vite build --watch"
60
+ },
61
+ "types": "./dist/index.d.ts"
62
+ }