@webiny/lexical-editor 6.4.0-beta.3 → 6.4.0-beta.4

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.
@@ -241,12 +241,6 @@
241
241
  margin: 0 4px;
242
242
  }
243
243
 
244
- .lexical-dropdown-container {
245
- position: absolute;
246
- bottom: -5px;
247
- left: 0;
248
- }
249
-
250
244
  .static-toolbar button.item i {
251
245
  opacity: 0.6;
252
246
  }
@@ -357,16 +351,8 @@ i.font-color,
357
351
  margin: 0 4px;
358
352
  }
359
353
 
360
- .lexical-dropdown-container {
361
- position: absolute;
362
- bottom: -5px;
363
- left: 0;
364
- }
365
-
366
354
  .lexical-dropdown {
367
- z-index: 10;
368
355
  display: block;
369
- position: fixed;
370
356
  box-shadow:
371
357
  0 12px 28px 0 rgba(0, 0, 0, 0.2),
372
358
  0 2px 4px 0 rgba(0, 0, 0, 0.1),
@@ -0,0 +1,2 @@
1
+ import React from "react";
2
+ export declare const FontSizeAction: () => React.JSX.Element | null;
@@ -0,0 +1,71 @@
1
+ import react, { useCallback, useMemo } from "react";
2
+ import { $getSelection, $isRangeSelection } from "lexical";
3
+ import { $getSelectionStyleValueForProperty, $patchStyleText } from "@lexical/selection";
4
+ import { useDeriveValueFromSelection } from "../../hooks/useCurrentSelection.js";
5
+ import { useRichTextEditor } from "../../hooks/index.js";
6
+ import { DropDown, DropDownItem } from "../../ui/DropDown.js";
7
+ const FontSizeDropdown = ({ sizes })=>{
8
+ const { editor } = useRichTextEditor();
9
+ const fontSizeOptions = useMemo(()=>[
10
+ {
11
+ value: "inherit",
12
+ label: "Auto"
13
+ },
14
+ ...sizes.map((size)=>({
15
+ value: size,
16
+ label: `${size}`
17
+ }))
18
+ ], [
19
+ sizes
20
+ ]);
21
+ const selectedFontSize = useDeriveValueFromSelection(({ rangeSelection })=>{
22
+ if (!rangeSelection) return "inherit";
23
+ return $getSelectionStyleValueForProperty(rangeSelection, "font-size", "inherit");
24
+ });
25
+ const onFontSizeSelect = useCallback((size)=>{
26
+ editor.update(()=>{
27
+ if (editor.isEditable()) {
28
+ const selection = $getSelection();
29
+ if (null === selection) return;
30
+ if ($isRangeSelection(selection) && selection.isCollapsed()) {
31
+ const anchor = selection.anchor.getNode();
32
+ const topElement = anchor.getTopLevelElementOrThrow();
33
+ topElement.select(0, topElement.getChildrenSize());
34
+ const expanded = $getSelection();
35
+ if (null !== expanded) $patchStyleText(expanded, {
36
+ "font-size": size
37
+ });
38
+ } else $patchStyleText(selection, {
39
+ "font-size": size
40
+ });
41
+ }
42
+ });
43
+ }, [
44
+ editor
45
+ ]);
46
+ const selectedOption = fontSizeOptions.find((option)=>option.value === selectedFontSize);
47
+ return /*#__PURE__*/ react.createElement(DropDown, {
48
+ buttonClassName: "toolbar-item typography-dropdown",
49
+ buttonAriaLabel: "Typography formatting options",
50
+ buttonLabel: selectedOption?.label || "Auto",
51
+ stopCloseOnClickSelf: true,
52
+ disabled: false,
53
+ showScroll: true
54
+ }, fontSizeOptions.map((option)=>/*#__PURE__*/ react.createElement(DropDownItem, {
55
+ className: `item typography-item ${selectedFontSize === option.value ? "active dropdown-item-active" : ""}`,
56
+ onClick: ()=>onFontSizeSelect(option.value),
57
+ key: option.value
58
+ }, /*#__PURE__*/ react.createElement("span", {
59
+ className: "text"
60
+ }, option.label))));
61
+ };
62
+ const FontSizeAction = ()=>{
63
+ const { theme } = useRichTextEditor();
64
+ if (!theme.fontSizes || 0 === theme.fontSizes.length) return null;
65
+ return /*#__PURE__*/ react.createElement(FontSizeDropdown, {
66
+ sizes: theme.fontSizes
67
+ });
68
+ };
69
+ export { FontSizeAction };
70
+
71
+ //# sourceMappingURL=FontSizeAction.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"components/ToolbarActions/FontSizeAction.js","sources":["../../../src/components/ToolbarActions/FontSizeAction.tsx"],"sourcesContent":["import React, { useCallback, useMemo } from \"react\";\nimport { $getSelection, $isRangeSelection } from \"lexical\";\nimport { $patchStyleText } from \"@lexical/selection\";\nimport { $getSelectionStyleValueForProperty } from \"@lexical/selection\";\nimport { useDeriveValueFromSelection } from \"~/hooks/useCurrentSelection.js\";\nimport { useRichTextEditor } from \"~/hooks/index.js\";\nimport { DropDown } from \"~/ui/DropDown.js\";\nimport { DropDownItem } from \"~/ui/DropDown.js\";\n\ninterface FontSizeDropdownProps {\n sizes: string[];\n}\n\nconst FontSizeDropdown = ({ sizes }: FontSizeDropdownProps) => {\n const { editor } = useRichTextEditor();\n\n const fontSizeOptions = useMemo(() => {\n return [\n {\n value: \"inherit\",\n label: \"Auto\"\n },\n ...sizes.map(size => {\n return {\n value: size,\n label: `${size}`\n };\n })\n ];\n }, [sizes]);\n\n const selectedFontSize = useDeriveValueFromSelection(({ rangeSelection }) => {\n if (!rangeSelection) {\n return \"inherit\";\n }\n return $getSelectionStyleValueForProperty(rangeSelection, \"font-size\", \"inherit\");\n });\n\n const onFontSizeSelect = useCallback(\n (size: string) => {\n editor.update(() => {\n if (editor.isEditable()) {\n const selection = $getSelection();\n if (selection === null) {\n return;\n }\n\n if ($isRangeSelection(selection) && selection.isCollapsed()) {\n const anchor = selection.anchor.getNode();\n const topElement = anchor.getTopLevelElementOrThrow();\n topElement.select(0, topElement.getChildrenSize());\n const expanded = $getSelection();\n if (expanded !== null) {\n $patchStyleText(expanded, { \"font-size\": size });\n }\n } else {\n $patchStyleText(selection, { \"font-size\": size });\n }\n }\n });\n },\n [editor]\n );\n\n const selectedOption = fontSizeOptions.find(option => option.value === selectedFontSize);\n\n return (\n <DropDown\n buttonClassName=\"toolbar-item typography-dropdown\"\n buttonAriaLabel={\"Typography formatting options\"}\n buttonLabel={selectedOption?.label || \"Auto\"}\n stopCloseOnClickSelf={true}\n disabled={false}\n showScroll={true}\n >\n {fontSizeOptions.map(option => (\n <DropDownItem\n className={`item typography-item ${\n selectedFontSize === option.value ? \"active dropdown-item-active\" : \"\"\n }`}\n onClick={() => onFontSizeSelect(option.value)}\n key={option.value}\n >\n <span className=\"text\">{option.label}</span>\n </DropDownItem>\n ))}\n </DropDown>\n );\n};\n\nexport const FontSizeAction = () => {\n const { theme } = useRichTextEditor();\n\n if (!theme.fontSizes || theme.fontSizes.length === 0) {\n return null;\n }\n\n return <FontSizeDropdown sizes={theme.fontSizes} />;\n};\n"],"names":["FontSizeDropdown","sizes","editor","useRichTextEditor","fontSizeOptions","useMemo","size","selectedFontSize","useDeriveValueFromSelection","rangeSelection","$getSelectionStyleValueForProperty","onFontSizeSelect","useCallback","selection","$getSelection","$isRangeSelection","anchor","topElement","expanded","$patchStyleText","selectedOption","option","DropDown","DropDownItem","FontSizeAction","theme"],"mappings":";;;;;;AAaA,MAAMA,mBAAmB,CAAC,EAAEC,KAAK,EAAyB;IACtD,MAAM,EAAEC,MAAM,EAAE,GAAGC;IAEnB,MAAMC,kBAAkBC,QAAQ,IACrB;YACH;gBACI,OAAO;gBACP,OAAO;YACX;eACGJ,MAAM,GAAG,CAACK,CAAAA,OACF;oBACH,OAAOA;oBACP,OAAO,GAAGA,MAAM;gBACpB;SAEP,EACF;QAACL;KAAM;IAEV,MAAMM,mBAAmBC,4BAA4B,CAAC,EAAEC,cAAc,EAAE;QACpE,IAAI,CAACA,gBACD,OAAO;QAEX,OAAOC,mCAAmCD,gBAAgB,aAAa;IAC3E;IAEA,MAAME,mBAAmBC,YACrB,CAACN;QACGJ,OAAO,MAAM,CAAC;YACV,IAAIA,OAAO,UAAU,IAAI;gBACrB,MAAMW,YAAYC;gBAClB,IAAID,AAAc,SAAdA,WACA;gBAGJ,IAAIE,kBAAkBF,cAAcA,UAAU,WAAW,IAAI;oBACzD,MAAMG,SAASH,UAAU,MAAM,CAAC,OAAO;oBACvC,MAAMI,aAAaD,OAAO,yBAAyB;oBACnDC,WAAW,MAAM,CAAC,GAAGA,WAAW,eAAe;oBAC/C,MAAMC,WAAWJ;oBACjB,IAAII,AAAa,SAAbA,UACAC,gBAAgBD,UAAU;wBAAE,aAAaZ;oBAAK;gBAEtD,OACIa,gBAAgBN,WAAW;oBAAE,aAAaP;gBAAK;YAEvD;QACJ;IACJ,GACA;QAACJ;KAAO;IAGZ,MAAMkB,iBAAiBhB,gBAAgB,IAAI,CAACiB,CAAAA,SAAUA,OAAO,KAAK,KAAKd;IAEvE,OAAO,WAAP,GACI,oBAACe,UAAQA;QACL,iBAAgB;QAChB,iBAAiB;QACjB,aAAaF,gBAAgB,SAAS;QACtC,sBAAsB;QACtB,UAAU;QACV,YAAY;OAEXhB,gBAAgB,GAAG,CAACiB,CAAAA,SAAAA,WAAAA,GACjB,oBAACE,cAAYA;YACT,WAAW,CAAC,qBAAqB,EAC7BhB,qBAAqBc,OAAO,KAAK,GAAG,gCAAgC,IACtE;YACF,SAAS,IAAMV,iBAAiBU,OAAO,KAAK;YAC5C,KAAKA,OAAO,KAAK;yBAEjB,oBAAC;YAAK,WAAU;WAAQA,OAAO,KAAK;AAKxD;AAEO,MAAMG,iBAAiB;IAC1B,MAAM,EAAEC,KAAK,EAAE,GAAGtB;IAElB,IAAI,CAACsB,MAAM,SAAS,IAAIA,AAA2B,MAA3BA,MAAM,SAAS,CAAC,MAAM,EAC1C,OAAO;IAGX,OAAO,WAAP,GAAO,oBAACzB,kBAAgBA;QAAC,OAAOyB,MAAM,SAAS;;AACnD"}
@@ -7,6 +7,8 @@ const RichTextEditorProvider = ({ theme, toolbarActionPlugins = [], children })=
7
7
  const getOverlaysElement = useCallback(()=>{
8
8
  const rootElement = editor.getRootElement();
9
9
  if (!rootElement) return document.body;
10
+ const dialogContent = rootElement.closest("[role='dialog']");
11
+ if (dialogContent) return dialogContent;
10
12
  const shell = rootElement.closest(".editor-shell");
11
13
  if (!shell) return document.body;
12
14
  const overlays = shell.previousElementSibling;
@@ -14,7 +16,12 @@ const RichTextEditorProvider = ({ theme, toolbarActionPlugins = [], children })=
14
16
  }, [
15
17
  editor
16
18
  ]);
17
- const internalTheme = useMemo(()=>new Theme(theme.colors, theme.typography, theme.tokens), [
19
+ const internalTheme = useMemo(()=>new Theme({
20
+ colors: theme.colors,
21
+ typography: theme.typography,
22
+ fontSizes: theme.fontSizes,
23
+ tokens: theme.tokens
24
+ }), [
18
25
  theme
19
26
  ]);
20
27
  return /*#__PURE__*/ react.createElement(RichTextEditorContext.Provider, {
@@ -1 +1 @@
1
- {"version":3,"file":"context/RichTextEditorContext.js","sources":["../../src/context/RichTextEditorContext.tsx"],"sourcesContent":["import React, { createContext, useCallback, useMemo } from \"react\";\nimport type { LexicalEditor } from \"lexical\";\nimport { useLexicalComposerContext } from \"@lexical/react/LexicalComposerContext\";\nimport { type EditorTheme, Theme } from \"@webiny/lexical-theme\";\nimport type { ToolbarActionPlugin } from \"~/types.js\";\n\nexport interface RichTextEditorContext {\n editor: LexicalEditor;\n getOverlaysElement: () => HTMLElement;\n toolbarActionPlugins: ToolbarActionPlugin[];\n theme: Theme;\n}\n\nexport const RichTextEditorContext = createContext<RichTextEditorContext | undefined>(undefined);\n\ninterface RichTextEditorProviderProps {\n theme: EditorTheme;\n toolbarActionPlugins?: ToolbarActionPlugin[];\n children?: React.ReactNode | React.ReactNode[];\n}\n\nexport const RichTextEditorProvider = ({\n theme,\n toolbarActionPlugins = [],\n children\n}: RichTextEditorProviderProps) => {\n const [editor] = useLexicalComposerContext();\n\n const getOverlaysElement = useCallback(() => {\n const rootElement = editor.getRootElement();\n if (!rootElement) {\n return document.body;\n }\n\n const shell = rootElement.closest(\".editor-shell\");\n if (!shell) {\n return document.body;\n }\n const overlays = shell.previousElementSibling;\n\n return (overlays ?? document.body) as HTMLElement;\n }, [editor]);\n\n const internalTheme = useMemo(\n () => new Theme(theme.colors, theme.typography, theme.tokens),\n [theme]\n );\n\n return (\n <RichTextEditorContext.Provider\n value={{\n editor,\n getOverlaysElement,\n theme: internalTheme,\n toolbarActionPlugins\n }}\n >\n {children}\n </RichTextEditorContext.Provider>\n );\n};\n"],"names":["RichTextEditorContext","createContext","undefined","RichTextEditorProvider","theme","toolbarActionPlugins","children","editor","useLexicalComposerContext","getOverlaysElement","useCallback","rootElement","document","shell","overlays","internalTheme","useMemo","Theme"],"mappings":";;;AAaO,MAAMA,wBAAwB,WAAHA,GAAGC,cAAiDC;AAQ/E,MAAMC,yBAAyB,CAAC,EACnCC,KAAK,EACLC,uBAAuB,EAAE,EACzBC,QAAQ,EACkB;IAC1B,MAAM,CAACC,OAAO,GAAGC;IAEjB,MAAMC,qBAAqBC,YAAY;QACnC,MAAMC,cAAcJ,OAAO,cAAc;QACzC,IAAI,CAACI,aACD,OAAOC,SAAS,IAAI;QAGxB,MAAMC,QAAQF,YAAY,OAAO,CAAC;QAClC,IAAI,CAACE,OACD,OAAOD,SAAS,IAAI;QAExB,MAAME,WAAWD,MAAM,sBAAsB;QAE7C,OAAQC,YAAYF,SAAS,IAAI;IACrC,GAAG;QAACL;KAAO;IAEX,MAAMQ,gBAAgBC,QAClB,IAAM,IAAIC,MAAMb,MAAM,MAAM,EAAEA,MAAM,UAAU,EAAEA,MAAM,MAAM,GAC5D;QAACA;KAAM;IAGX,OAAO,WAAP,GACI,oBAACJ,sBAAsB,QAAQ;QAC3B,OAAO;YACHO;YACAE;YACA,OAAOM;YACPV;QACJ;OAECC;AAGb"}
1
+ {"version":3,"file":"context/RichTextEditorContext.js","sources":["../../src/context/RichTextEditorContext.tsx"],"sourcesContent":["import React, { createContext, useCallback, useMemo } from \"react\";\nimport type { LexicalEditor } from \"lexical\";\nimport { useLexicalComposerContext } from \"@lexical/react/LexicalComposerContext\";\nimport { type EditorTheme, Theme } from \"@webiny/lexical-theme\";\nimport type { ToolbarActionPlugin } from \"~/types.js\";\n\nexport interface RichTextEditorContext {\n editor: LexicalEditor;\n getOverlaysElement: () => HTMLElement;\n toolbarActionPlugins: ToolbarActionPlugin[];\n theme: Theme;\n}\n\nexport const RichTextEditorContext = createContext<RichTextEditorContext | undefined>(undefined);\n\ninterface RichTextEditorProviderProps {\n theme: EditorTheme;\n toolbarActionPlugins?: ToolbarActionPlugin[];\n children?: React.ReactNode | React.ReactNode[];\n}\n\nexport const RichTextEditorProvider = ({\n theme,\n toolbarActionPlugins = [],\n children\n}: RichTextEditorProviderProps) => {\n const [editor] = useLexicalComposerContext();\n\n const getOverlaysElement = useCallback(() => {\n const rootElement = editor.getRootElement();\n if (!rootElement) {\n return document.body;\n }\n\n const dialogContent = rootElement.closest(\"[role='dialog']\");\n if (dialogContent) {\n return dialogContent as HTMLElement;\n }\n\n const shell = rootElement.closest(\".editor-shell\");\n if (!shell) {\n return document.body;\n }\n const overlays = shell.previousElementSibling;\n\n return (overlays ?? document.body) as HTMLElement;\n }, [editor]);\n\n const internalTheme = useMemo(\n () =>\n new Theme({\n colors: theme.colors,\n typography: theme.typography,\n fontSizes: theme.fontSizes,\n tokens: theme.tokens\n }),\n [theme]\n );\n\n return (\n <RichTextEditorContext.Provider\n value={{\n editor,\n getOverlaysElement,\n theme: internalTheme,\n toolbarActionPlugins\n }}\n >\n {children}\n </RichTextEditorContext.Provider>\n );\n};\n"],"names":["RichTextEditorContext","createContext","undefined","RichTextEditorProvider","theme","toolbarActionPlugins","children","editor","useLexicalComposerContext","getOverlaysElement","useCallback","rootElement","document","dialogContent","shell","overlays","internalTheme","useMemo","Theme"],"mappings":";;;AAaO,MAAMA,wBAAwB,WAAHA,GAAGC,cAAiDC;AAQ/E,MAAMC,yBAAyB,CAAC,EACnCC,KAAK,EACLC,uBAAuB,EAAE,EACzBC,QAAQ,EACkB;IAC1B,MAAM,CAACC,OAAO,GAAGC;IAEjB,MAAMC,qBAAqBC,YAAY;QACnC,MAAMC,cAAcJ,OAAO,cAAc;QACzC,IAAI,CAACI,aACD,OAAOC,SAAS,IAAI;QAGxB,MAAMC,gBAAgBF,YAAY,OAAO,CAAC;QAC1C,IAAIE,eACA,OAAOA;QAGX,MAAMC,QAAQH,YAAY,OAAO,CAAC;QAClC,IAAI,CAACG,OACD,OAAOF,SAAS,IAAI;QAExB,MAAMG,WAAWD,MAAM,sBAAsB;QAE7C,OAAQC,YAAYH,SAAS,IAAI;IACrC,GAAG;QAACL;KAAO;IAEX,MAAMS,gBAAgBC,QAClB,IACI,IAAIC,MAAM;YACN,QAAQd,MAAM,MAAM;YACpB,YAAYA,MAAM,UAAU;YAC5B,WAAWA,MAAM,SAAS;YAC1B,QAAQA,MAAM,MAAM;QACxB,IACJ;QAACA;KAAM;IAGX,OAAO,WAAP,GACI,oBAACJ,sBAAsB,QAAQ;QAC3B,OAAO;YACHO;YACAE;YACA,OAAOO;YACPX;QACJ;OAECC;AAGb"}
package/index.d.ts CHANGED
@@ -7,6 +7,7 @@ export { BoldAction } from "./components/ToolbarActions/BoldAction.js";
7
7
  export { BulletListAction } from "./components/ToolbarActions/BulletListAction.js";
8
8
  export { CodeHighlightAction } from "./components/ToolbarActions/CodeHighlightAction.js";
9
9
  export { FontColorAction } from "./components/ToolbarActions/FontColorAction.js";
10
+ export { FontSizeAction } from "./components/ToolbarActions/FontSizeAction.js";
10
11
  export { ItalicAction } from "./components/ToolbarActions/ItalicAction.js";
11
12
  export { LinkAction } from "./components/ToolbarActions/LinkAction.js";
12
13
  export { NumberedListAction } from "./components/ToolbarActions/NumberedListAction.js";
package/index.js CHANGED
@@ -8,6 +8,7 @@ export { BoldAction } from "./components/ToolbarActions/BoldAction.js";
8
8
  export { BulletListAction } from "./components/ToolbarActions/BulletListAction.js";
9
9
  export { CodeHighlightAction } from "./components/ToolbarActions/CodeHighlightAction.js";
10
10
  export { FontColorAction } from "./components/ToolbarActions/FontColorAction.js";
11
+ export { FontSizeAction } from "./components/ToolbarActions/FontSizeAction.js";
11
12
  export { ItalicAction } from "./components/ToolbarActions/ItalicAction.js";
12
13
  export { LinkAction } from "./components/ToolbarActions/LinkAction.js";
13
14
  export { NumberedListAction } from "./components/ToolbarActions/NumberedListAction.js";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@webiny/lexical-editor",
3
- "version": "6.4.0-beta.3",
3
+ "version": "6.4.0-beta.4",
4
4
  "type": "module",
5
5
  "exports": {
6
6
  ".": "./index.js",
@@ -12,7 +12,6 @@
12
12
  },
13
13
  "license": "MIT",
14
14
  "dependencies": {
15
- "@floating-ui/dom": "1.7.6",
16
15
  "@lexical/code": "0.44.0",
17
16
  "@lexical/history": "0.44.0",
18
17
  "@lexical/react": "0.44.0",
@@ -20,21 +19,23 @@
20
19
  "@lexical/selection": "0.44.0",
21
20
  "@lexical/text": "0.44.0",
22
21
  "@lexical/utils": "0.44.0",
23
- "@webiny/lexical-nodes": "6.4.0-beta.3",
24
- "@webiny/lexical-theme": "6.4.0-beta.3",
25
- "@webiny/react-composition": "6.4.0-beta.3",
26
- "@webiny/react-properties": "6.4.0-beta.3",
22
+ "@webiny/lexical-nodes": "6.4.0-beta.4",
23
+ "@webiny/lexical-theme": "6.4.0-beta.4",
24
+ "@webiny/react-composition": "6.4.0-beta.4",
25
+ "@webiny/react-properties": "6.4.0-beta.4",
27
26
  "lexical": "0.44.0",
28
27
  "lodash": "4.18.1",
28
+ "radix-ui": "1.4.3",
29
29
  "react": "18.3.1",
30
30
  "react-dom": "18.3.1"
31
31
  },
32
32
  "devDependencies": {
33
- "@webiny/build-tools": "6.4.0-beta.3"
33
+ "@webiny/build-tools": "6.4.0-beta.4"
34
34
  },
35
35
  "publishConfig": {
36
- "access": "public",
37
- "directory": "dist"
36
+ "access": "public"
38
37
  },
39
- "gitHead": "2e58681d4344024bfb60e6180338e2f154ec87f0"
38
+ "webiny": {
39
+ "publishFrom": "dist"
40
+ }
40
41
  }
@@ -7,7 +7,7 @@ function FloatingLinkEditor({ editor, isVisible, LinkForm }) {
7
7
  className: "z-dialog absolute link-editor",
8
8
  style: {
9
9
  opacity: isVisible ? 1 : 0,
10
- pointerEvents: isVisible ? "auto" : "none"
10
+ pointerEvents: isVisible ? "all" : "none"
11
11
  }
12
12
  }, isVisible ? /*#__PURE__*/ react.createElement(LinkForm, {
13
13
  linkData: linkData,
@@ -1 +1 @@
1
- {"version":3,"file":"plugins/FloatingLinkEditorPlugin/FloatingLinkEditor.js","sources":["../../../src/plugins/FloatingLinkEditorPlugin/FloatingLinkEditor.tsx"],"sourcesContent":["import React from \"react\";\nimport type { LexicalEditor } from \"lexical\";\nimport { LinkFormProps } from \"./types.js\";\nimport { useFloatingLinkEditor } from \"./useFloatingLinkEditor.js\";\n\ninterface FloatingLinkEditorProps {\n editor: LexicalEditor;\n isVisible: boolean;\n LinkForm: React.FunctionComponent<LinkFormProps>;\n}\n\nexport function FloatingLinkEditor({ editor, isVisible, LinkForm }: FloatingLinkEditorProps) {\n const { editorRef, linkData, applyChanges, removeLink } = useFloatingLinkEditor(editor);\n\n return (\n <div\n ref={editorRef}\n className=\"z-dialog absolute link-editor\"\n style={{ opacity: isVisible ? 1 : 0, pointerEvents: isVisible ? \"auto\" : \"none\" }}\n >\n {isVisible ? (\n <LinkForm linkData={linkData} onSave={applyChanges} removeLink={removeLink} />\n ) : null}\n </div>\n );\n}\n"],"names":["FloatingLinkEditor","editor","isVisible","LinkForm","editorRef","linkData","applyChanges","removeLink","useFloatingLinkEditor"],"mappings":";;AAWO,SAASA,mBAAmB,EAAEC,MAAM,EAAEC,SAAS,EAAEC,QAAQ,EAA2B;IACvF,MAAM,EAAEC,SAAS,EAAEC,QAAQ,EAAEC,YAAY,EAAEC,UAAU,EAAE,GAAGC,sBAAsBP;IAEhF,OAAO,WAAP,GACI,oBAAC;QACG,KAAKG;QACL,WAAU;QACV,OAAO;YAAE,SAASF,YAAY,IAAI;YAAG,eAAeA,YAAY,SAAS;QAAO;OAE/EA,YAAY,WAAZA,GACG,oBAACC,UAAAA;QAAS,UAAUE;QAAU,QAAQC;QAAc,YAAYC;SAChE;AAGhB"}
1
+ {"version":3,"file":"plugins/FloatingLinkEditorPlugin/FloatingLinkEditor.js","sources":["../../../src/plugins/FloatingLinkEditorPlugin/FloatingLinkEditor.tsx"],"sourcesContent":["import React from \"react\";\nimport type { LexicalEditor } from \"lexical\";\nimport { LinkFormProps } from \"./types.js\";\nimport { useFloatingLinkEditor } from \"./useFloatingLinkEditor.js\";\n\ninterface FloatingLinkEditorProps {\n editor: LexicalEditor;\n isVisible: boolean;\n LinkForm: React.FunctionComponent<LinkFormProps>;\n}\n\nexport function FloatingLinkEditor({ editor, isVisible, LinkForm }: FloatingLinkEditorProps) {\n const { editorRef, linkData, applyChanges, removeLink } = useFloatingLinkEditor(editor);\n\n return (\n <div\n ref={editorRef}\n className=\"z-dialog absolute link-editor\"\n style={{ opacity: isVisible ? 1 : 0, pointerEvents: isVisible ? \"all\" : \"none\" }}\n >\n {isVisible ? (\n <LinkForm linkData={linkData} onSave={applyChanges} removeLink={removeLink} />\n ) : null}\n </div>\n );\n}\n"],"names":["FloatingLinkEditor","editor","isVisible","LinkForm","editorRef","linkData","applyChanges","removeLink","useFloatingLinkEditor"],"mappings":";;AAWO,SAASA,mBAAmB,EAAEC,MAAM,EAAEC,SAAS,EAAEC,QAAQ,EAA2B;IACvF,MAAM,EAAEC,SAAS,EAAEC,QAAQ,EAAEC,YAAY,EAAEC,UAAU,EAAE,GAAGC,sBAAsBP;IAEhF,OAAO,WAAP,GACI,oBAAC;QACG,KAAKG;QACL,WAAU;QACV,OAAO;YAAE,SAASF,YAAY,IAAI;YAAG,eAAeA,YAAY,QAAQ;QAAO;OAE9EA,YAAY,WAAZA,GACG,oBAACC,UAAAA;QAAS,UAAUE;QAAU,QAAQC;QAAc,YAAYC;SAChE;AAGhB"}
package/ui/DropDown.d.ts CHANGED
@@ -1,10 +1,3 @@
1
- /**
2
- * Copyright (c) Meta Platforms, Inc. and affiliates.
3
- *
4
- * This source code is licensed under the MIT license found in the
5
- * LICENSE file in the root directory of this source tree.
6
- *
7
- */
8
1
  import type { ReactNode } from "react";
9
2
  import * as React from "react";
10
3
  export declare function DropDownItem({ children, className, onClick, title }: {
@@ -13,7 +6,7 @@ export declare function DropDownItem({ children, className, onClick, title }: {
13
6
  onClick: (event: React.MouseEvent<HTMLButtonElement>) => void;
14
7
  title?: string;
15
8
  }): React.JSX.Element;
16
- export declare function DropDown({ disabled, buttonLabel, buttonAriaLabel, buttonClassName, buttonIconClassName, children, stopCloseOnClickSelf, showScroll }: {
9
+ interface DropDownProps {
17
10
  disabled?: boolean;
18
11
  buttonAriaLabel?: string;
19
12
  buttonClassName: string;
@@ -22,4 +15,6 @@ export declare function DropDown({ disabled, buttonLabel, buttonAriaLabel, butto
22
15
  children: ReactNode;
23
16
  stopCloseOnClickSelf?: boolean;
24
17
  showScroll?: boolean;
25
- }): React.JSX.Element;
18
+ }
19
+ export declare function DropDown({ disabled, buttonLabel, buttonAriaLabel, buttonClassName, buttonIconClassName, children, showScroll }: DropDownProps): React.JSX.Element;
20
+ export {};
package/ui/DropDown.js CHANGED
@@ -1,152 +1,41 @@
1
+ import { DropdownMenu } from "radix-ui";
1
2
  import * as __rspack_external_react from "react";
2
- const DropDownContext = /*#__PURE__*/ __rspack_external_react.createContext(null);
3
3
  function DropDownItem({ children, className, onClick, title }) {
4
- const ref = (0, __rspack_external_react.useRef)(null);
5
- const dropDownContext = __rspack_external_react.useContext(DropDownContext);
6
- if (null === dropDownContext) throw new Error("DropDownItem must be used within a DropDown");
7
- const { registerItem } = dropDownContext;
8
- (0, __rspack_external_react.useEffect)(()=>{
9
- if (!ref.current) return;
10
- registerItem(ref);
11
- }, [
12
- ref,
13
- registerItem
14
- ]);
15
4
  return /*#__PURE__*/ __rspack_external_react.createElement("button", {
16
5
  className: className,
17
6
  onClick: onClick,
18
- ref: ref,
19
7
  title: title,
20
8
  type: "button"
21
9
  }, children);
22
10
  }
23
- function DropDownItems({ children, dropDownRef, showScroll = true, onClose }) {
24
- const [items, setItems] = (0, __rspack_external_react.useState)();
25
- const [highlightedItem, setHighlightedItem] = (0, __rspack_external_react.useState)();
26
- const registerItem = (0, __rspack_external_react.useCallback)((itemRef)=>{
27
- setItems((prev)=>prev ? [
28
- ...prev,
29
- itemRef
30
- ] : [
31
- itemRef
32
- ]);
33
- }, [
34
- setItems
35
- ]);
36
- const handleKeyDown = (event)=>{
37
- if (!items) return;
38
- const key = event.key;
39
- if ([
40
- "Escape",
41
- "ArrowUp",
42
- "ArrowDown",
43
- "Tab"
44
- ].includes(key)) event.preventDefault();
45
- if ("Escape" === key || "Tab" === key) onClose();
46
- else if ("ArrowUp" === key) setHighlightedItem((prev)=>{
47
- if (!prev) return items[0];
48
- const index = items.indexOf(prev) - 1;
49
- return items[-1 === index ? items.length - 1 : index];
50
- });
51
- else if ("ArrowDown" === key) setHighlightedItem((prev)=>{
52
- if (!prev) return items[0];
53
- return items[items.indexOf(prev) + 1];
54
- });
55
- };
56
- const contextValue = (0, __rspack_external_react.useMemo)(()=>({
57
- registerItem
58
- }), [
59
- registerItem
60
- ]);
61
- (0, __rspack_external_react.useEffect)(()=>{
62
- if (items && !highlightedItem) setHighlightedItem(items[0]);
63
- if (highlightedItem && highlightedItem.current) highlightedItem.current.focus();
64
- }, [
65
- items,
66
- highlightedItem
67
- ]);
68
- return /*#__PURE__*/ __rspack_external_react.createElement(DropDownContext.Provider, {
69
- value: contextValue
70
- }, /*#__PURE__*/ __rspack_external_react.createElement("div", {
71
- className: `lexical-dropdown ${showScroll ? "" : "no-scroll"}`,
72
- ref: dropDownRef,
73
- onKeyDown: handleKeyDown
74
- }, children));
75
- }
76
- function DropDown({ disabled = false, buttonLabel, buttonAriaLabel, buttonClassName, buttonIconClassName, children, stopCloseOnClickSelf, showScroll = true }) {
77
- const dropDownRef = (0, __rspack_external_react.useRef)(null);
78
- const buttonRef = (0, __rspack_external_react.useRef)(null);
79
- const [positionIsCalculated, setPositionIsCalculated] = (0, __rspack_external_react.useState)(false);
80
- const [showDropDown, setShowDropDown] = (0, __rspack_external_react.useState)(false);
81
- const handleClose = ()=>{
82
- setPositionIsCalculated(false);
83
- setShowDropDown(false);
84
- if (buttonRef && buttonRef.current) buttonRef.current.focus();
85
- };
86
- (0, __rspack_external_react.useEffect)(()=>{
87
- const button = buttonRef.current;
88
- const dropDown = dropDownRef.current;
89
- if (showDropDown && button && dropDown) {
90
- dropDown.style.top = "44px";
91
- dropDown.style.left = `${button.offsetLeft}px`;
92
- setPositionIsCalculated(true);
93
- }
94
- }, [
95
- dropDownRef,
96
- buttonRef,
97
- showDropDown
98
- ]);
99
- (0, __rspack_external_react.useEffect)(()=>{
100
- const button = buttonRef.current;
101
- if (button && showDropDown) {
102
- const handle = (event)=>{
103
- const target = event.target;
104
- if (stopCloseOnClickSelf) {
105
- if (dropDownRef.current && dropDownRef.current.contains(target)) return;
106
- }
107
- if (!button.contains(target)) setShowDropDown(false);
108
- };
109
- document.addEventListener("click", handle);
110
- return ()=>{
111
- document.removeEventListener("click", handle);
112
- };
113
- }
114
- }, [
115
- dropDownRef,
116
- buttonRef,
117
- showDropDown,
118
- stopCloseOnClickSelf
119
- ]);
120
- const displayContainer = (0, __rspack_external_react.useMemo)(()=>positionIsCalculated ? {
121
- display: "block"
122
- } : {
123
- display: "none"
124
- }, [
125
- positionIsCalculated
126
- ]);
127
- return /*#__PURE__*/ __rspack_external_react.createElement(__rspack_external_react.Fragment, null, /*#__PURE__*/ __rspack_external_react.createElement("button", {
11
+ function DropDown({ disabled = false, buttonLabel, buttonAriaLabel, buttonClassName, buttonIconClassName, children, showScroll = true }) {
12
+ return /*#__PURE__*/ __rspack_external_react.createElement(DropdownMenu.Root, null, /*#__PURE__*/ __rspack_external_react.createElement(DropdownMenu.Trigger, {
13
+ asChild: true
14
+ }, /*#__PURE__*/ __rspack_external_react.createElement("button", {
128
15
  style: {
129
16
  position: "relative"
130
17
  },
131
18
  disabled: disabled,
132
19
  "aria-label": buttonAriaLabel || buttonLabel,
133
- className: buttonClassName,
134
- onClick: ()=>setShowDropDown(!showDropDown),
135
- ref: buttonRef
20
+ className: buttonClassName
136
21
  }, buttonIconClassName && /*#__PURE__*/ __rspack_external_react.createElement("span", {
137
22
  className: buttonIconClassName
138
23
  }), buttonLabel && /*#__PURE__*/ __rspack_external_react.createElement("span", {
139
24
  className: "text dropdown-button-text"
140
25
  }, buttonLabel), /*#__PURE__*/ __rspack_external_react.createElement("i", {
141
26
  className: "chevron-down"
142
- })), showDropDown && /*#__PURE__*/ __rspack_external_react.createElement("div", {
143
- className: "lexical-dropdown-container",
144
- style: displayContainer
145
- }, /*#__PURE__*/ __rspack_external_react.createElement(DropDownItems, {
146
- showScroll: showScroll,
147
- dropDownRef: dropDownRef,
148
- onClose: handleClose
149
- }, children)));
27
+ }))), /*#__PURE__*/ __rspack_external_react.createElement(DropdownMenu.Portal, null, /*#__PURE__*/ __rspack_external_react.createElement(DropdownMenu.Content, {
28
+ className: `lexical-dropdown z-overlay ${showScroll ? "" : "no-scroll"}`,
29
+ sideOffset: 4,
30
+ collisionPadding: 8,
31
+ onCloseAutoFocus: (e)=>e.preventDefault()
32
+ }, /*#__PURE__*/ __rspack_external_react.createElement("div", {
33
+ className: showScroll ? "lexical-dropdown-scroll" : "",
34
+ style: showScroll ? {
35
+ maxHeight: 250,
36
+ overflowY: "auto"
37
+ } : void 0
38
+ }, children))));
150
39
  }
151
40
  export { DropDown, DropDownItem };
152
41
 
@@ -1 +1 @@
1
- {"version":3,"file":"ui/DropDown.js","sources":["../../src/ui/DropDown.tsx"],"sourcesContent":["/**\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n */\n\nimport type { ReactNode, RefObject } from \"react\";\nimport * as React from \"react\";\nimport { useCallback, useEffect, useMemo, useRef, useState } from \"react\";\n\ntype DropDownContextType = {\n registerItem: (ref: React.RefObject<HTMLButtonElement>) => void;\n};\n\nconst DropDownContext = React.createContext<DropDownContextType | null>(null);\n\nexport function DropDownItem({\n children,\n className,\n onClick,\n title\n}: {\n children: React.ReactNode;\n className: string;\n onClick: (event: React.MouseEvent<HTMLButtonElement>) => void;\n title?: string;\n}) {\n const ref = useRef<HTMLButtonElement>(null);\n\n const dropDownContext = React.useContext(DropDownContext);\n\n if (dropDownContext === null) {\n throw new Error(\"DropDownItem must be used within a DropDown\");\n }\n\n const { registerItem } = dropDownContext;\n\n useEffect(() => {\n if (!ref.current) {\n return;\n }\n\n registerItem(ref as RefObject<HTMLButtonElement>);\n }, [ref, registerItem]);\n\n return (\n <button className={className} onClick={onClick} ref={ref} title={title} type=\"button\">\n {children}\n </button>\n );\n}\n\nfunction DropDownItems({\n children,\n dropDownRef,\n showScroll = true,\n onClose\n}: {\n children: React.ReactNode;\n dropDownRef?: React.Ref<HTMLDivElement>;\n showScroll?: boolean;\n onClose: () => void;\n}) {\n const [items, setItems] = useState<React.RefObject<HTMLButtonElement>[]>();\n const [highlightedItem, setHighlightedItem] = useState<React.RefObject<HTMLButtonElement>>();\n\n const registerItem = useCallback(\n (itemRef: React.RefObject<HTMLButtonElement>) => {\n setItems(prev => (prev ? [...prev, itemRef] : [itemRef]));\n },\n [setItems]\n );\n\n const handleKeyDown = (event: React.KeyboardEvent<HTMLDivElement>) => {\n if (!items) {\n return;\n }\n\n const key = event.key;\n\n if ([\"Escape\", \"ArrowUp\", \"ArrowDown\", \"Tab\"].includes(key)) {\n event.preventDefault();\n }\n\n if (key === \"Escape\" || key === \"Tab\") {\n onClose();\n } else if (key === \"ArrowUp\") {\n setHighlightedItem(prev => {\n if (!prev) {\n return items[0];\n }\n const index = items.indexOf(prev) - 1;\n return items[index === -1 ? items.length - 1 : index];\n });\n } else if (key === \"ArrowDown\") {\n setHighlightedItem(prev => {\n if (!prev) {\n return items[0];\n }\n return items[items.indexOf(prev) + 1];\n });\n }\n };\n\n const contextValue = useMemo(\n () => ({\n registerItem\n }),\n [registerItem]\n );\n\n useEffect(() => {\n if (items && !highlightedItem) {\n setHighlightedItem(items[0]);\n }\n\n if (highlightedItem && highlightedItem.current) {\n highlightedItem.current.focus();\n }\n }, [items, highlightedItem]);\n\n return (\n <DropDownContext.Provider value={contextValue}>\n <div\n className={`lexical-dropdown ${showScroll ? \"\" : \"no-scroll\"}`}\n ref={dropDownRef}\n onKeyDown={handleKeyDown}\n >\n {children}\n </div>\n </DropDownContext.Provider>\n );\n}\n\nexport function DropDown({\n disabled = false,\n buttonLabel,\n buttonAriaLabel,\n buttonClassName,\n buttonIconClassName,\n children,\n stopCloseOnClickSelf,\n showScroll = true\n}: {\n disabled?: boolean;\n buttonAriaLabel?: string;\n buttonClassName: string;\n buttonIconClassName?: string;\n buttonLabel?: string;\n children: ReactNode;\n stopCloseOnClickSelf?: boolean;\n showScroll?: boolean;\n}): React.JSX.Element {\n const dropDownRef = useRef<HTMLDivElement>(null);\n const buttonRef = useRef<HTMLButtonElement>(null);\n // Used to prevent flickering of the dropdown while calculating the dropdown position.\n const [positionIsCalculated, setPositionIsCalculated] = useState(false);\n const [showDropDown, setShowDropDown] = useState(false);\n\n const handleClose = () => {\n setPositionIsCalculated(false);\n setShowDropDown(false);\n if (buttonRef && buttonRef.current) {\n buttonRef.current.focus();\n }\n };\n\n useEffect(() => {\n const button = buttonRef.current;\n const dropDown = dropDownRef.current;\n\n if (showDropDown && button && dropDown) {\n dropDown.style.top = \"44px\";\n dropDown.style.left = `${button.offsetLeft}px`;\n setPositionIsCalculated(true);\n }\n }, [dropDownRef, buttonRef, showDropDown]);\n\n useEffect(() => {\n const button = buttonRef.current;\n if (button && showDropDown) {\n const handle = (event: MouseEvent) => {\n const target = event.target;\n if (stopCloseOnClickSelf) {\n if (dropDownRef.current && dropDownRef.current.contains(target as Node)) {\n return;\n }\n }\n\n if (!button.contains(target as Node)) {\n setShowDropDown(false);\n }\n };\n document.addEventListener(\"click\", handle);\n return () => {\n document.removeEventListener(\"click\", handle);\n };\n }\n return;\n }, [dropDownRef, buttonRef, showDropDown, stopCloseOnClickSelf]);\n\n const displayContainer = useMemo(() => {\n // To prevent blinking, we show the container only when the dropdown position is calculated.\n // Without this, window would be visible first on left (0px), and after a millisecond on the right side.\n return positionIsCalculated ? { display: \"block\" } : { display: \"none\" };\n }, [positionIsCalculated]);\n\n return (\n <>\n <button\n style={{ position: \"relative\" }}\n disabled={disabled}\n aria-label={buttonAriaLabel || buttonLabel}\n className={buttonClassName}\n onClick={() => setShowDropDown(!showDropDown)}\n ref={buttonRef}\n >\n {buttonIconClassName && <span className={buttonIconClassName} />}\n {buttonLabel && <span className=\"text dropdown-button-text\">{buttonLabel}</span>}\n <i className=\"chevron-down\" />\n </button>\n {showDropDown && (\n <div className={\"lexical-dropdown-container\"} style={displayContainer}>\n <DropDownItems\n showScroll={showScroll}\n dropDownRef={dropDownRef}\n onClose={handleClose}\n >\n {children}\n </DropDownItems>\n </div>\n )}\n </>\n );\n}\n"],"names":["DropDownContext","React","DropDownItem","children","className","onClick","title","ref","useRef","dropDownContext","Error","registerItem","useEffect","DropDownItems","dropDownRef","showScroll","onClose","items","setItems","useState","highlightedItem","setHighlightedItem","useCallback","itemRef","prev","handleKeyDown","event","key","index","contextValue","useMemo","DropDown","disabled","buttonLabel","buttonAriaLabel","buttonClassName","buttonIconClassName","stopCloseOnClickSelf","buttonRef","positionIsCalculated","setPositionIsCalculated","showDropDown","setShowDropDown","handleClose","button","dropDown","handle","target","document","displayContainer"],"mappings":"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"}
1
+ {"version":3,"file":"ui/DropDown.js","sources":["../../src/ui/DropDown.tsx"],"sourcesContent":["import type { ReactNode } from \"react\";\nimport * as React from \"react\";\nimport { DropdownMenu } from \"radix-ui\";\n\nexport function DropDownItem({\n children,\n className,\n onClick,\n title\n}: {\n children: React.ReactNode;\n className: string;\n onClick: (event: React.MouseEvent<HTMLButtonElement>) => void;\n title?: string;\n}) {\n return (\n <button className={className} onClick={onClick} title={title} type=\"button\">\n {children}\n </button>\n );\n}\n\ninterface DropDownProps {\n disabled?: boolean;\n buttonAriaLabel?: string;\n buttonClassName: string;\n buttonIconClassName?: string;\n buttonLabel?: string;\n children: ReactNode;\n stopCloseOnClickSelf?: boolean;\n showScroll?: boolean;\n}\n\nexport function DropDown({\n disabled = false,\n buttonLabel,\n buttonAriaLabel,\n buttonClassName,\n buttonIconClassName,\n children,\n showScroll = true\n}: DropDownProps): React.JSX.Element {\n return (\n <DropdownMenu.Root>\n <DropdownMenu.Trigger asChild>\n <button\n style={{ position: \"relative\" }}\n disabled={disabled}\n aria-label={buttonAriaLabel || buttonLabel}\n className={buttonClassName}\n >\n {buttonIconClassName && <span className={buttonIconClassName} />}\n {buttonLabel && (\n <span className=\"text dropdown-button-text\">{buttonLabel}</span>\n )}\n <i className=\"chevron-down\" />\n </button>\n </DropdownMenu.Trigger>\n <DropdownMenu.Portal>\n <DropdownMenu.Content\n className={`lexical-dropdown z-overlay ${showScroll ? \"\" : \"no-scroll\"}`}\n sideOffset={4}\n collisionPadding={8}\n onCloseAutoFocus={e => e.preventDefault()}\n >\n <div\n className={showScroll ? \"lexical-dropdown-scroll\" : \"\"}\n style={showScroll ? { maxHeight: 250, overflowY: \"auto\" } : undefined}\n >\n {children}\n </div>\n </DropdownMenu.Content>\n </DropdownMenu.Portal>\n </DropdownMenu.Root>\n );\n}\n"],"names":["DropDownItem","children","className","onClick","title","DropDown","disabled","buttonLabel","buttonAriaLabel","buttonClassName","buttonIconClassName","showScroll","DropdownMenu","e","undefined"],"mappings":";;AAIO,SAASA,aAAa,EACzBC,QAAQ,EACRC,SAAS,EACTC,OAAO,EACPC,KAAK,EAMR;IACG,OAAO,WAAP,GACI,sCAAC;QAAO,WAAWF;QAAW,SAASC;QAAS,OAAOC;QAAO,MAAK;OAC9DH;AAGb;AAaO,SAASI,SAAS,EACrBC,WAAW,KAAK,EAChBC,WAAW,EACXC,eAAe,EACfC,eAAe,EACfC,mBAAmB,EACnBT,QAAQ,EACRU,aAAa,IAAI,EACL;IACZ,OAAO,WAAP,GACI,sCAACC,aAAa,IAAI,sBACd,sCAACA,aAAa,OAAO;QAAC;qBAClB,sCAAC;QACG,OAAO;YAAE,UAAU;QAAW;QAC9B,UAAUN;QACV,cAAYE,mBAAmBD;QAC/B,WAAWE;OAEVC,uBAAuB,WAAvBA,GAAuB,sCAAC;QAAK,WAAWA;QACxCH,eAAe,WAAfA,GACG,sCAAC;QAAK,WAAU;OAA6BA,cAAAA,WAAAA,GAEjD,sCAAC;QAAE,WAAU;wBAGrB,sCAACK,aAAa,MAAM,sBAChB,sCAACA,aAAa,OAAO;QACjB,WAAW,CAAC,2BAA2B,EAAED,aAAa,KAAK,aAAa;QACxE,YAAY;QACZ,kBAAkB;QAClB,kBAAkBE,CAAAA,IAAKA,EAAE,cAAc;qBAEvC,sCAAC;QACG,WAAWF,aAAa,4BAA4B;QACpD,OAAOA,aAAa;YAAE,WAAW;YAAK,WAAW;QAAO,IAAIG;OAE3Db;AAMzB"}
@@ -1,25 +1,30 @@
1
- import { computePosition, flip, offset, shift } from "@floating-ui/dom";
2
1
  const GAP = 10;
3
2
  function setFloatingElemPosition(basePosition, elementToPosition) {
4
3
  setTimeout(()=>{
5
- if (null === basePosition) {
6
- elementToPosition.style.transform = "translate(-10000px, -10000px)";
7
- return;
8
- }
9
- const virtualElement = {
10
- getBoundingClientRect: ()=>basePosition.getBoundingClientRect()
4
+ if (null === basePosition) return void Object.assign(elementToPosition.style, {
5
+ position: "fixed",
6
+ left: "-10000px",
7
+ top: "-10000px",
8
+ transform: "none"
9
+ });
10
+ const rangeRect = basePosition.getBoundingClientRect();
11
+ const containerRect = elementToPosition.offsetParent?.getBoundingClientRect() ?? {
12
+ left: 0,
13
+ top: 0
11
14
  };
12
- computePosition(virtualElement, elementToPosition, {
13
- placement: "bottom",
14
- middleware: [
15
- offset(GAP),
16
- flip(),
17
- shift({
18
- padding: GAP
19
- })
20
- ]
21
- }).then(({ x, y })=>{
22
- elementToPosition.style.transform = `translate(${x}px, ${y}px)`;
15
+ const elWidth = elementToPosition.offsetWidth;
16
+ const elHeight = elementToPosition.offsetHeight;
17
+ const viewportWidth = window.innerWidth;
18
+ const viewportHeight = window.innerHeight;
19
+ let left = rangeRect.left - containerRect.left;
20
+ let top = rangeRect.bottom + GAP - containerRect.top;
21
+ if (rangeRect.left + elWidth > viewportWidth - GAP) left = viewportWidth - elWidth - GAP - containerRect.left;
22
+ if (rangeRect.bottom + GAP + elHeight > viewportHeight - GAP) top = rangeRect.top - elHeight - GAP - containerRect.top;
23
+ Object.assign(elementToPosition.style, {
24
+ position: "absolute",
25
+ left: `${left}px`,
26
+ top: `${top}px`,
27
+ transform: "none"
23
28
  });
24
29
  }, 10);
25
30
  }
@@ -1 +1 @@
1
- {"version":3,"file":"utils/setFloatingElemPosition.js","sources":["../../src/utils/setFloatingElemPosition.ts"],"sourcesContent":["import { computePosition, flip, offset, shift } from \"@floating-ui/dom\";\n\nconst GAP = 10;\n\nexport function setFloatingElemPosition(\n basePosition: Range | null,\n elementToPosition: HTMLElement\n): void {\n // A small timeout gives enough time for DOM to update and provides us with correct bounding rect values.\n setTimeout(() => {\n if (basePosition === null) {\n elementToPosition.style.transform = \"translate(-10000px, -10000px)\";\n return;\n }\n\n const virtualElement = {\n getBoundingClientRect: () => basePosition.getBoundingClientRect()\n };\n\n computePosition(virtualElement, elementToPosition, {\n placement: \"bottom\",\n middleware: [\n offset(GAP), // adds gap between anchor and popup\n flip(), // switches to the opposite side if no room (bottom top)\n shift({ padding: GAP }) // slides along the axis to stay within viewport\n ]\n }).then(({ x, y }) => {\n elementToPosition.style.transform = `translate(${x}px, ${y}px)`;\n });\n }, 10);\n}\n"],"names":["GAP","setFloatingElemPosition","basePosition","elementToPosition","setTimeout","virtualElement","computePosition","offset","flip","shift","x","y"],"mappings":";AAEA,MAAMA,MAAM;AAEL,SAASC,wBACZC,YAA0B,EAC1BC,iBAA8B;IAG9BC,WAAW;QACP,IAAIF,AAAiB,SAAjBA,cAAuB;YACvBC,kBAAkB,KAAK,CAAC,SAAS,GAAG;YACpC;QACJ;QAEA,MAAME,iBAAiB;YACnB,uBAAuB,IAAMH,aAAa,qBAAqB;QACnE;QAEAI,gBAAgBD,gBAAgBF,mBAAmB;YAC/C,WAAW;YACX,YAAY;gBACRI,OAAOP;gBACPQ;gBACAC,MAAM;oBAAE,SAAST;gBAAI;aACxB;QACL,GAAG,IAAI,CAAC,CAAC,EAAEU,CAAC,EAAEC,CAAC,EAAE;YACbR,kBAAkB,KAAK,CAAC,SAAS,GAAG,CAAC,UAAU,EAAEO,EAAE,IAAI,EAAEC,EAAE,GAAG,CAAC;QACnE;IACJ,GAAG;AACP"}
1
+ {"version":3,"file":"utils/setFloatingElemPosition.js","sources":["../../src/utils/setFloatingElemPosition.ts"],"sourcesContent":["const GAP = 10;\n\nexport function setFloatingElemPosition(\n basePosition: Range | null,\n elementToPosition: HTMLElement\n): void {\n setTimeout(() => {\n if (basePosition === null) {\n Object.assign(elementToPosition.style, {\n position: \"fixed\",\n left: \"-10000px\",\n top: \"-10000px\",\n transform: \"none\"\n });\n return;\n }\n\n const rangeRect = basePosition.getBoundingClientRect();\n const containerRect = elementToPosition.offsetParent?.getBoundingClientRect() ?? {\n left: 0,\n top: 0\n };\n\n const elWidth = elementToPosition.offsetWidth;\n const elHeight = elementToPosition.offsetHeight;\n const viewportWidth = window.innerWidth;\n const viewportHeight = window.innerHeight;\n\n let left = rangeRect.left - containerRect.left;\n let top = rangeRect.bottom + GAP - containerRect.top;\n\n if (rangeRect.left + elWidth > viewportWidth - GAP) {\n left = viewportWidth - elWidth - GAP - containerRect.left;\n }\n\n if (rangeRect.bottom + GAP + elHeight > viewportHeight - GAP) {\n top = rangeRect.top - elHeight - GAP - containerRect.top;\n }\n\n Object.assign(elementToPosition.style, {\n position: \"absolute\",\n left: `${left}px`,\n top: `${top}px`,\n transform: \"none\"\n });\n }, 10);\n}\n"],"names":["GAP","setFloatingElemPosition","basePosition","elementToPosition","setTimeout","Object","rangeRect","containerRect","elWidth","elHeight","viewportWidth","window","viewportHeight","left","top"],"mappings":"AAAA,MAAMA,MAAM;AAEL,SAASC,wBACZC,YAA0B,EAC1BC,iBAA8B;IAE9BC,WAAW;QACP,IAAIF,AAAiB,SAAjBA,cAAuB,YACvBG,OAAO,MAAM,CAACF,kBAAkB,KAAK,EAAE;YACnC,UAAU;YACV,MAAM;YACN,KAAK;YACL,WAAW;QACf;QAIJ,MAAMG,YAAYJ,aAAa,qBAAqB;QACpD,MAAMK,gBAAgBJ,kBAAkB,YAAY,EAAE,2BAA2B;YAC7E,MAAM;YACN,KAAK;QACT;QAEA,MAAMK,UAAUL,kBAAkB,WAAW;QAC7C,MAAMM,WAAWN,kBAAkB,YAAY;QAC/C,MAAMO,gBAAgBC,OAAO,UAAU;QACvC,MAAMC,iBAAiBD,OAAO,WAAW;QAEzC,IAAIE,OAAOP,UAAU,IAAI,GAAGC,cAAc,IAAI;QAC9C,IAAIO,MAAMR,UAAU,MAAM,GAAGN,MAAMO,cAAc,GAAG;QAEpD,IAAID,UAAU,IAAI,GAAGE,UAAUE,gBAAgBV,KAC3Ca,OAAOH,gBAAgBF,UAAUR,MAAMO,cAAc,IAAI;QAG7D,IAAID,UAAU,MAAM,GAAGN,MAAMS,WAAWG,iBAAiBZ,KACrDc,MAAMR,UAAU,GAAG,GAAGG,WAAWT,MAAMO,cAAc,GAAG;QAG5DF,OAAO,MAAM,CAACF,kBAAkB,KAAK,EAAE;YACnC,UAAU;YACV,MAAM,GAAGU,KAAK,EAAE,CAAC;YACjB,KAAK,GAAGC,IAAI,EAAE,CAAC;YACf,WAAW;QACf;IACJ,GAAG;AACP"}