@haklex/rich-renderer-linkcard 0.0.8 → 0.0.10

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,9 @@
1
+ import { PluginRegistry } from './types';
2
+ export interface ConvertToLinkCardActionProps {
3
+ url: string;
4
+ linkKey: string;
5
+ pluginRegistry?: PluginRegistry;
6
+ className?: string;
7
+ }
8
+ export declare function ConvertToLinkCardAction({ url, linkKey, pluginRegistry, className, }: ConvertToLinkCardActionProps): import("react/jsx-runtime").JSX.Element | null;
9
+ //# sourceMappingURL=ConvertToLinkCardAction.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ConvertToLinkCardAction.d.ts","sourceRoot":"","sources":["../src/ConvertToLinkCardAction.tsx"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,SAAS,CAAA;AAE7C,MAAM,WAAW,4BAA4B;IAC3C,GAAG,EAAE,MAAM,CAAA;IACX,OAAO,EAAE,MAAM,CAAA;IACf,cAAc,CAAC,EAAE,cAAc,CAAA;IAC/B,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB;AAED,wBAAgB,uBAAuB,CAAC,EACtC,GAAG,EACH,OAAO,EACP,cAAc,EACd,SAAS,GACV,EAAE,4BAA4B,kDA+B9B"}
@@ -1 +1 @@
1
- {"version":3,"file":"LinkCardEditDecorator.d.ts","sourceRoot":"","sources":["../src/LinkCardEditDecorator.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAmB,KAAK,mBAAmB,EAAE,MAAM,qBAAqB,CAAA;AAK/E,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,OAAO,CAAA;AAKzC,UAAU,0BAA0B;IAClC,OAAO,EAAE,MAAM,CAAA;IACf,OAAO,EAAE,mBAAmB,CAAA;IAC5B,QAAQ,EAAE,YAAY,CAAA;CACvB;AAED,wBAAgB,qBAAqB,CAAC,EACpC,OAAO,EACP,OAAO,EACP,QAAQ,GACT,EAAE,0BAA0B,2CA+H5B"}
1
+ {"version":3,"file":"LinkCardEditDecorator.d.ts","sourceRoot":"","sources":["../src/LinkCardEditDecorator.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAmB,KAAK,mBAAmB,EAAE,MAAM,qBAAqB,CAAA;AAM/E,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,OAAO,CAAA;AAKzC,UAAU,0BAA0B;IAClC,OAAO,EAAE,MAAM,CAAA;IACf,OAAO,EAAE,mBAAmB,CAAA;IAC5B,QAAQ,EAAE,YAAY,CAAA;CACvB;AAED,wBAAgB,qBAAqB,CAAC,EACpC,OAAO,EACP,OAAO,EACP,QAAQ,GACT,EAAE,0BAA0B,2CAuJ5B"}
@@ -1,10 +1,12 @@
1
- import { LinkCardNode, SerializedLinkCardNode } from '@haklex/rich-editor';
1
+ import { LinkCardNode, LinkCardNodePayload, SerializedLinkCardNode, SlashMenuItemConfig } from '@haklex/rich-editor';
2
2
  import { EditorConfig, Klass, LexicalEditor, LexicalNode } from 'lexical';
3
3
  import { ReactElement } from 'react';
4
4
  export declare class LinkCardEditNode extends LinkCardNode {
5
+ static slashMenuItems: SlashMenuItemConfig[];
5
6
  static clone(node: LinkCardEditNode): LinkCardEditNode;
6
7
  static importJSON(serializedNode: SerializedLinkCardNode): LinkCardEditNode;
7
8
  decorate(_editor: LexicalEditor, _config: EditorConfig): ReactElement;
8
9
  }
10
+ export declare function $createLinkCardEditNode(payload: LinkCardNodePayload): LinkCardEditNode;
9
11
  export declare const linkCardEditNodes: Array<Klass<LexicalNode>>;
10
12
  //# sourceMappingURL=LinkCardEditNode.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"LinkCardEditNode.d.ts","sourceRoot":"","sources":["../src/LinkCardEditNode.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,YAAY,EAEZ,KAAK,sBAAsB,EAC5B,MAAM,qBAAqB,CAAA;AAC5B,OAAO,KAAK,EAAE,YAAY,EAAE,KAAK,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,SAAS,CAAA;AAC9E,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,OAAO,CAAA;AAKzC,qBAAa,gBAAiB,SAAQ,YAAY;IAChD,MAAM,CAAC,KAAK,CAAC,IAAI,EAAE,gBAAgB,GAAG,gBAAgB;IAatD,MAAM,CAAC,UAAU,CAAC,cAAc,EAAE,sBAAsB,GAAG,gBAAgB;IAU3E,QAAQ,CAAC,OAAO,EAAE,aAAa,EAAE,OAAO,EAAE,YAAY,GAAG,YAAY;CAmBtE;AAED,eAAO,MAAM,iBAAiB,EAAE,KAAK,CAAC,KAAK,CAAC,WAAW,CAAC,CAAsB,CAAA"}
1
+ {"version":3,"file":"LinkCardEditNode.d.ts","sourceRoot":"","sources":["../src/LinkCardEditNode.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,YAAY,EACZ,KAAK,mBAAmB,EAExB,KAAK,sBAAsB,EAC3B,KAAK,mBAAmB,EACzB,MAAM,qBAAqB,CAAA;AAC5B,OAAO,KAAK,EAAE,YAAY,EAAE,KAAK,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,SAAS,CAAA;AAG9E,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,OAAO,CAAA;AAKzC,qBAAa,gBAAiB,SAAQ,YAAY;IAChD,MAAM,CAAC,cAAc,EAAE,mBAAmB,EAAE,CAa3C;IAED,MAAM,CAAC,KAAK,CAAC,IAAI,EAAE,gBAAgB,GAAG,gBAAgB;IAatD,MAAM,CAAC,UAAU,CAAC,cAAc,EAAE,sBAAsB,GAAG,gBAAgB;IAU3E,QAAQ,CAAC,OAAO,EAAE,aAAa,EAAE,OAAO,EAAE,YAAY,GAAG,YAAY;CAmBtE;AAED,wBAAgB,uBAAuB,CACrC,OAAO,EAAE,mBAAmB,GAC3B,gBAAgB,CAElB;AAED,eAAO,MAAM,iBAAiB,EAAE,KAAK,CAAC,KAAK,CAAC,WAAW,CAAC,CAAsB,CAAA"}
@@ -0,0 +1,6 @@
1
+ import { PluginRegistry } from './types';
2
+ export interface PasteLinkCardPluginProps {
3
+ pluginRegistry?: PluginRegistry;
4
+ }
5
+ export declare function PasteLinkCardPlugin({ pluginRegistry, }: PasteLinkCardPluginProps): null;
6
+ //# sourceMappingURL=PasteLinkCardPlugin.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PasteLinkCardPlugin.d.ts","sourceRoot":"","sources":["../src/PasteLinkCardPlugin.tsx"],"names":[],"mappings":"AAYA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,SAAS,CAAA;AAE7C,MAAM,WAAW,wBAAwB;IACvC,cAAc,CAAC,EAAE,cAAc,CAAA;CAChC;AAED,wBAAgB,mBAAmB,CAAC,EAClC,cAAc,GACf,EAAE,wBAAwB,QAmC1B"}
@@ -3,5 +3,6 @@ export interface UrlMatchInfo {
3
3
  plugin: LinkCardPlugin;
4
4
  match: UrlMatchResult;
5
5
  }
6
+ export declare function matchUrl(url: string, pluginRegistry?: PluginRegistry): UrlMatchInfo | null;
6
7
  export declare function useUrlMatcher(url: string | undefined, pluginRegistry?: PluginRegistry): UrlMatchInfo | null;
7
8
  //# sourceMappingURL=useUrlMatcher.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"useUrlMatcher.d.ts","sourceRoot":"","sources":["../../src/hooks/useUrlMatcher.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,cAAc,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,UAAU,CAAA;AAE9E,MAAM,WAAW,YAAY;IAC3B,MAAM,EAAE,cAAc,CAAA;IACtB,KAAK,EAAE,cAAc,CAAA;CACtB;AAED,wBAAgB,aAAa,CAC3B,GAAG,EAAE,MAAM,GAAG,SAAS,EACvB,cAAc,GAAE,cAA+B,GAC9C,YAAY,GAAG,IAAI,CAcrB"}
1
+ {"version":3,"file":"useUrlMatcher.d.ts","sourceRoot":"","sources":["../../src/hooks/useUrlMatcher.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,cAAc,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,UAAU,CAAA;AAE9E,MAAM,WAAW,YAAY;IAC3B,MAAM,EAAE,cAAc,CAAA;IACtB,KAAK,EAAE,cAAc,CAAA;CACtB;AAED,wBAAgB,QAAQ,CACtB,GAAG,EAAE,MAAM,EACX,cAAc,GAAE,cAA+B,GAC9C,YAAY,GAAG,IAAI,CAWrB;AAED,wBAAgB,aAAa,CAC3B,GAAG,EAAE,MAAM,GAAG,SAAS,EACvB,cAAc,GAAE,cAA+B,GAC9C,YAAY,GAAG,IAAI,CAKrB"}
package/dist/index.d.ts CHANGED
@@ -1,10 +1,14 @@
1
+ export type { ConvertToLinkCardActionProps } from './ConvertToLinkCardAction';
2
+ export { ConvertToLinkCardAction } from './ConvertToLinkCardAction';
1
3
  export type { UrlMatchInfo } from './hooks/useUrlMatcher';
2
- export { useUrlMatcher } from './hooks/useUrlMatcher';
4
+ export { matchUrl, useUrlMatcher } from './hooks/useUrlMatcher';
3
5
  export { LinkCardEditDecorator } from './LinkCardEditDecorator';
4
- export { LinkCardEditNode, linkCardEditNodes } from './LinkCardEditNode';
6
+ export { $createLinkCardEditNode, LinkCardEditNode, linkCardEditNodes, } from './LinkCardEditNode';
5
7
  export type { EnhancedLinkCardProps } from './LinkCardRenderer';
6
8
  export { LinkCardRenderer } from './LinkCardRenderer';
7
9
  export { LinkCardSkeleton } from './LinkCardSkeleton';
10
+ export type { PasteLinkCardPluginProps } from './PasteLinkCardPlugin';
11
+ export { PasteLinkCardPlugin } from './PasteLinkCardPlugin';
8
12
  export { getPluginByName, pluginMap, plugins } from './plugins';
9
13
  export { arxivPlugin, bangumiPlugin, githubCommitPlugin, githubDiscussionPlugin, githubIssuePlugin, githubPrPlugin, githubRepoPlugin, leetcodePlugin, mxSpacePlugin, neteaseMusicPlugin, qqMusicPlugin, tmdbPlugin, } from './plugins';
10
14
  export { createMxSpacePlugin } from './plugins';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,YAAY,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAA;AACzD,OAAO,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAA;AACrD,OAAO,EAAE,qBAAqB,EAAE,MAAM,yBAAyB,CAAA;AAC/D,OAAO,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAA;AACxE,YAAY,EAAE,qBAAqB,EAAE,MAAM,oBAAoB,CAAA;AAC/D,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAA;AACrD,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAA;AACrD,OAAO,EAAE,eAAe,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,WAAW,CAAA;AAC/D,OAAO,EACL,WAAW,EACX,aAAa,EACb,kBAAkB,EAClB,sBAAsB,EACtB,iBAAiB,EACjB,cAAc,EACd,gBAAgB,EAChB,cAAc,EACd,aAAa,EACb,kBAAkB,EAClB,aAAa,EACb,UAAU,GACX,MAAM,WAAW,CAAA;AAClB,OAAO,EAAE,mBAAmB,EAAE,MAAM,WAAW,CAAA;AAC/C,YAAY,EAAE,mBAAmB,EAAE,MAAM,gBAAgB,CAAA;AACzD,YAAY,EACV,kBAAkB,EAClB,YAAY,EACZ,oBAAoB,EACpB,cAAc,EACd,iBAAiB,EACjB,cAAc,EACd,cAAc,GACf,MAAM,SAAS,CAAA;AAChB,OAAO,EACL,aAAa,EACb,cAAc,EACd,oBAAoB,EACpB,aAAa,EACb,kBAAkB,GACnB,MAAM,SAAS,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,YAAY,EAAE,4BAA4B,EAAE,MAAM,2BAA2B,CAAA;AAC7E,OAAO,EAAE,uBAAuB,EAAE,MAAM,2BAA2B,CAAA;AACnE,YAAY,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAA;AACzD,OAAO,EAAE,QAAQ,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAA;AAC/D,OAAO,EAAE,qBAAqB,EAAE,MAAM,yBAAyB,CAAA;AAC/D,OAAO,EACL,uBAAuB,EACvB,gBAAgB,EAChB,iBAAiB,GAClB,MAAM,oBAAoB,CAAA;AAC3B,YAAY,EAAE,qBAAqB,EAAE,MAAM,oBAAoB,CAAA;AAC/D,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAA;AACrD,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAA;AACrD,YAAY,EAAE,wBAAwB,EAAE,MAAM,uBAAuB,CAAA;AACrE,OAAO,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAA;AAC3D,OAAO,EAAE,eAAe,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,WAAW,CAAA;AAC/D,OAAO,EACL,WAAW,EACX,aAAa,EACb,kBAAkB,EAClB,sBAAsB,EACtB,iBAAiB,EACjB,cAAc,EACd,gBAAgB,EAChB,cAAc,EACd,aAAa,EACb,kBAAkB,EAClB,aAAa,EACb,UAAU,GACX,MAAM,WAAW,CAAA;AAClB,OAAO,EAAE,mBAAmB,EAAE,MAAM,WAAW,CAAA;AAC/C,YAAY,EAAE,mBAAmB,EAAE,MAAM,gBAAgB,CAAA;AACzD,YAAY,EACV,kBAAkB,EAClB,YAAY,EACZ,oBAAoB,EACpB,cAAc,EACd,iBAAiB,EACjB,cAAc,EACd,cAAc,GACf,MAAM,SAAS,CAAA;AAChB,OAAO,EACL,aAAa,EACb,cAAc,EACd,oBAAoB,EACpB,aAAa,EACb,kBAAkB,GACnB,MAAM,SAAS,CAAA"}
package/dist/index.mjs CHANGED
@@ -1,10 +1,14 @@
1
- import { useMemo, useState, useRef, useEffect, useCallback, createElement, useLayoutEffect } from "react";
1
+ var __defProp = Object.defineProperty;
2
+ var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
3
+ var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
2
4
  import { jsxs, jsx, Fragment } from "react/jsx-runtime";
3
- import { Star, Link, ExternalLink, Unlink, Globe } from "lucide-react";
5
+ import { $createLinkNode, $isLinkNode } from "@lexical/link";
6
+ import { useLexicalComposerContext } from "@lexical/react/LexicalComposerContext";
7
+ import { $getNodeByKey, $createTextNode, $createParagraphNode, $insertNodes, $createNodeSelection, $setSelection, PASTE_COMMAND, $getSelection, $isRangeSelection, $isParagraphNode, COMMAND_PRIORITY_LOW } from "lexical";
8
+ import { Star, Link, ExternalLink, RemoveFormatting, Unlink, CreditCard, Globe } from "lucide-react";
9
+ import { useMemo, useState, useRef, useEffect, useCallback, createElement, useLayoutEffect } from "react";
4
10
  import { $isLinkCardNode, LinkCardNode, createRendererDecoration, LinkCardRenderer as LinkCardRenderer$1 } from "@haklex/rich-editor";
5
11
  import { Popover, PopoverTrigger, PopoverPanel } from "@haklex/rich-editor-ui";
6
- import { useLexicalComposerContext } from "@lexical/react/LexicalComposerContext";
7
- import { $getNodeByKey } from "lexical";
8
12
  import { useInView } from "react-intersection-observer";
9
13
  const arxivPlugin = {
10
14
  name: "arxiv",
@@ -1013,18 +1017,21 @@ function getPluginByName(name) {
1013
1017
  const pluginMap = new Map(
1014
1018
  plugins.map((p) => [p.name, p])
1015
1019
  );
1020
+ function matchUrl(url, pluginRegistry = plugins) {
1021
+ try {
1022
+ const parsed = new URL(url);
1023
+ for (const plugin of pluginRegistry) {
1024
+ const match = plugin.matchUrl(parsed);
1025
+ if (match) return { plugin, match };
1026
+ }
1027
+ } catch {
1028
+ }
1029
+ return null;
1030
+ }
1016
1031
  function useUrlMatcher(url, pluginRegistry = plugins) {
1017
1032
  return useMemo(() => {
1018
1033
  if (!url) return null;
1019
- try {
1020
- const parsed = new URL(url);
1021
- for (const plugin of pluginRegistry) {
1022
- const match = plugin.matchUrl(parsed);
1023
- if (match) return { plugin, match };
1024
- }
1025
- } catch {
1026
- }
1027
- return null;
1034
+ return matchUrl(url, pluginRegistry);
1028
1035
  }, [url, pluginRegistry]);
1029
1036
  }
1030
1037
  var semanticClassNames = { card: "link-card", cardShortDesc: "link-card--short-desc", cardSkeleton: "link-card--skeleton", cardError: "link-card--error", bg: "link-card__bg", image: "link-card__image", icon: "link-card__icon", content: "link-card__content", title: "link-card__title", titleText: "link-card__title-text", external: "link-card__external", desc: "link-card__desc", desc2: "link-card__desc-2", editWrapper: "rich-link-card-edit-wrapper", editPanel: "rich-link-card-edit-panel", editUrlRow: "rich-link-card-edit-url-row", editLinkIcon: "rich-link-card-edit-link-icon", editInput: "rich-link-card-edit-input", editActions: "rich-link-card-edit-actions", editActionButton: "rich-link-card-edit-action-btn", editActionButtonEnd: "rich-link-card-edit-action-btn--end" };
@@ -1086,6 +1093,21 @@ function LinkCardEditDecorator({
1086
1093
  });
1087
1094
  setOpen(false);
1088
1095
  }, [editor, nodeKey]);
1096
+ const handleConvertToLink = useCallback(() => {
1097
+ editor.update(() => {
1098
+ const node = $getNodeByKey(nodeKey);
1099
+ if (!$isLinkCardNode(node)) return;
1100
+ const nodeUrl = node.getUrl();
1101
+ const { title: title2 } = payload;
1102
+ const linkNode = $createLinkNode(nodeUrl);
1103
+ linkNode.append($createTextNode(title2 || nodeUrl));
1104
+ const paragraph = $createParagraphNode();
1105
+ paragraph.append(linkNode);
1106
+ node.replace(paragraph);
1107
+ paragraph.selectEnd();
1108
+ });
1109
+ setOpen(false);
1110
+ }, [editor, nodeKey, payload]);
1089
1111
  const handleKeyDown = useCallback(
1090
1112
  (e) => {
1091
1113
  if (e.key === "Enter") {
@@ -1182,6 +1204,18 @@ function LinkCardEditDecorator({
1182
1204
  ]
1183
1205
  }
1184
1206
  ),
1207
+ /* @__PURE__ */ jsxs(
1208
+ "button",
1209
+ {
1210
+ className: `${editActionButton} ${semanticClassNames.editActionButton}`,
1211
+ type: "button",
1212
+ onClick: handleConvertToLink,
1213
+ children: [
1214
+ /* @__PURE__ */ jsx(RemoveFormatting, { size: 14 }),
1215
+ "To Link"
1216
+ ]
1217
+ }
1218
+ ),
1185
1219
  /* @__PURE__ */ jsxs(
1186
1220
  "button",
1187
1221
  {
@@ -1204,9 +1238,9 @@ function LinkCardEditDecorator({
1204
1238
  }
1205
1239
  );
1206
1240
  }
1207
- class LinkCardEditNode extends LinkCardNode {
1241
+ const _LinkCardEditNode = class _LinkCardEditNode extends LinkCardNode {
1208
1242
  static clone(node) {
1209
- return new LinkCardEditNode(
1243
+ return new _LinkCardEditNode(
1210
1244
  {
1211
1245
  url: node.__url,
1212
1246
  title: node.__title,
@@ -1218,7 +1252,7 @@ class LinkCardEditNode extends LinkCardNode {
1218
1252
  );
1219
1253
  }
1220
1254
  static importJSON(serializedNode) {
1221
- return new LinkCardEditNode({
1255
+ return new _LinkCardEditNode({
1222
1256
  url: serializedNode.url,
1223
1257
  title: serializedNode.title,
1224
1258
  description: serializedNode.description,
@@ -1245,8 +1279,56 @@ class LinkCardEditNode extends LinkCardNode {
1245
1279
  children: rendererEl
1246
1280
  });
1247
1281
  }
1282
+ };
1283
+ __publicField(_LinkCardEditNode, "slashMenuItems", [
1284
+ {
1285
+ title: "Link Card",
1286
+ icon: createElement(Link, { size: 20 }),
1287
+ description: "Link preview card",
1288
+ keywords: ["link", "card", "bookmark", "embed"],
1289
+ section: "MEDIA",
1290
+ onSelect: (editor) => {
1291
+ editor.update(() => {
1292
+ $insertNodes([$createLinkCardEditNode({ url: "" })]);
1293
+ });
1294
+ }
1295
+ }
1296
+ ]);
1297
+ let LinkCardEditNode = _LinkCardEditNode;
1298
+ function $createLinkCardEditNode(payload) {
1299
+ return new LinkCardEditNode(payload);
1248
1300
  }
1249
1301
  const linkCardEditNodes = [LinkCardEditNode];
1302
+ function ConvertToLinkCardAction({
1303
+ url,
1304
+ linkKey,
1305
+ pluginRegistry,
1306
+ className
1307
+ }) {
1308
+ const [editor] = useLexicalComposerContext();
1309
+ const info = useMemo(
1310
+ () => matchUrl(url, pluginRegistry),
1311
+ [url, pluginRegistry]
1312
+ );
1313
+ if (!info) return null;
1314
+ const handleConvert = () => {
1315
+ editor.update(() => {
1316
+ const linkNode = $getNodeByKey(linkKey);
1317
+ if (!linkNode || !$isLinkNode(linkNode)) return;
1318
+ const topElement = linkNode.getTopLevelElement();
1319
+ if (!topElement) return;
1320
+ const linkCardNode = $createLinkCardEditNode({ url });
1321
+ topElement.replace(linkCardNode);
1322
+ const nodeSelection = $createNodeSelection();
1323
+ nodeSelection.add(linkCardNode.getKey());
1324
+ $setSelection(nodeSelection);
1325
+ });
1326
+ };
1327
+ return /* @__PURE__ */ jsxs("button", { className, type: "button", onClick: handleConvert, children: [
1328
+ /* @__PURE__ */ jsx(CreditCard, { size: 14 }),
1329
+ "To Card"
1330
+ ] });
1331
+ }
1250
1332
  function useCardFetcher(options) {
1251
1333
  const { source, plugin, id, fallbackUrl, enabled = true, context } = options;
1252
1334
  const [loading, setLoading] = useState(true);
@@ -1513,12 +1595,46 @@ const LinkCardRenderer = (props) => {
1513
1595
  }
1514
1596
  );
1515
1597
  };
1598
+ function PasteLinkCardPlugin({
1599
+ pluginRegistry
1600
+ }) {
1601
+ const [editor] = useLexicalComposerContext();
1602
+ useEffect(() => {
1603
+ return editor.registerCommand(
1604
+ PASTE_COMMAND,
1605
+ (event) => {
1606
+ const text = event.clipboardData?.getData("text/plain")?.trim();
1607
+ if (!text) return false;
1608
+ const info = matchUrl(text, pluginRegistry);
1609
+ if (!info) return false;
1610
+ const selection = $getSelection();
1611
+ if (!$isRangeSelection(selection)) return false;
1612
+ const anchorNode = selection.anchor.getNode();
1613
+ const topElement = anchorNode.getTopLevelElement();
1614
+ if (!topElement || !$isParagraphNode(topElement)) return false;
1615
+ const textContent = topElement.getTextContent();
1616
+ if (textContent.trim().length > 0) return false;
1617
+ event.preventDefault();
1618
+ const linkCardNode = $createLinkCardEditNode({
1619
+ url: text
1620
+ });
1621
+ topElement.replace(linkCardNode);
1622
+ return true;
1623
+ },
1624
+ COMMAND_PRIORITY_LOW
1625
+ );
1626
+ }, [editor, pluginRegistry]);
1627
+ return null;
1628
+ }
1516
1629
  export {
1630
+ $createLinkCardEditNode,
1631
+ ConvertToLinkCardAction,
1517
1632
  LanguageToColorMap,
1518
1633
  LinkCardEditDecorator,
1519
1634
  LinkCardEditNode,
1520
1635
  LinkCardRenderer,
1521
1636
  LinkCardSkeleton,
1637
+ PasteLinkCardPlugin,
1522
1638
  arxivPlugin,
1523
1639
  bangumiPlugin,
1524
1640
  camelcaseKeys,
@@ -1534,6 +1650,7 @@ export {
1534
1650
  githubRepoPlugin,
1535
1651
  leetcodePlugin,
1536
1652
  linkCardEditNodes,
1653
+ matchUrl,
1537
1654
  mxSpacePlugin,
1538
1655
  neteaseMusicPlugin,
1539
1656
  pluginMap,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@haklex/rich-renderer-linkcard",
3
- "version": "0.0.8",
3
+ "version": "0.0.10",
4
4
  "license": "MIT",
5
5
  "type": "module",
6
6
  "exports": {
@@ -17,11 +17,12 @@
17
17
  "dependencies": {
18
18
  "lucide-react": "^0.574.0",
19
19
  "react-intersection-observer": "^9.15.1",
20
- "@haklex/rich-editor": "0.0.8",
21
- "@haklex/rich-style-token": "0.0.8",
22
- "@haklex/rich-editor-ui": "0.0.8"
20
+ "@haklex/rich-editor": "0.0.10",
21
+ "@haklex/rich-editor-ui": "0.0.10",
22
+ "@haklex/rich-style-token": "0.0.10"
23
23
  },
24
24
  "devDependencies": {
25
+ "@lexical/link": "^0.40.0",
25
26
  "@lexical/react": "^0.40.0",
26
27
  "@types/react": "^19.0.0",
27
28
  "@types/react-dom": "^19.0.0",
@@ -35,6 +36,7 @@
35
36
  "vite-plugin-dts": "^4.5.0"
36
37
  },
37
38
  "peerDependencies": {
39
+ "@lexical/link": "^0.40.0",
38
40
  "@lexical/react": "^0.40.0",
39
41
  "lexical": "^0.40.0",
40
42
  "react": ">=19",