UNPKG

payload-lexical-typography

Version:
1,359 lines (1,332 loc) 80.3 kB
"use strict"; "use client"; var __defProp = Object.defineProperty; var __getOwnPropDesc = Object.getOwnPropertyDescriptor; var __getOwnPropNames = Object.getOwnPropertyNames; var __hasOwnProp = Object.prototype.hasOwnProperty; var __export = (target, all) => { for (var name in all) __defProp(target, name, { get: all[name], enumerable: true }); }; var __copyProps = (to, from, except, desc) => { if (from && typeof from === "object" || typeof from === "function") { for (let key of __getOwnPropNames(from)) if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); } return to; }; var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); // src/client.ts var client_exports = {}; __export(client_exports, { TextColorClientFeature: () => TextColorClientFeature, TextFontFamilyClientFeature: () => TextFontFamilyClientFeature, TextLetterSpacingClientFeature: () => TextLetterSpacingClientFeature, TextLineHeightClientFeature: () => TextLineHeightClientFeature, TextSizeClientFeature: () => TextSizeClientFeature }); module.exports = __toCommonJS(client_exports); // src/features/textColor/feature.client.tsx var import_client = require("@payloadcms/richtext-lexical/client"); var import_lexical4 = require("@payloadcms/richtext-lexical/lexical"); var import_LexicalComposerContext2 = require("@payloadcms/richtext-lexical/lexical/react/LexicalComposerContext"); var import_selection2 = require("@payloadcms/richtext-lexical/lexical/selection"); var import_react5 = require("react"); // src/features/textColor/command.ts var import_lexical = require("@payloadcms/richtext-lexical/lexical"); var TEXT_COLOR_COMMAND = (0, import_lexical.createCommand)("TEXT_COLOR_COMMAND"); // src/features/textColor/components/TextColorDropdown.tsx var import_react3 = require("react"); // src/features/textColor/components/TextColorPicker.tsx var import_react2 = require("react"); var import_react_colorful = require("react-colorful"); // src/utils/usePreventInlineToolbarClose.ts var import_react = require("react"); var usePreventInlineToolbarClose = () => { const containerRef = (0, import_react.useRef)(null); (0, import_react.useEffect)(() => { const container = containerRef.current; if (!container) return; const handleSelectionChange = (e) => { const activeElement = document.activeElement; if (activeElement && container.contains(activeElement)) { e.stopImmediatePropagation(); } }; const handleMouseUp = (e) => { if (container.contains(e.target)) { e.stopImmediatePropagation(); } }; document.addEventListener("selectionchange", handleSelectionChange, true); document.addEventListener("mouseup", handleMouseUp, true); return () => { document.removeEventListener("selectionchange", handleSelectionChange, true); document.removeEventListener("mouseup", handleMouseUp, true); }; }, []); const handleInputInteraction = (e) => { e.stopPropagation(); const selection = window.getSelection(); if (selection && selection.rangeCount > 0) { const range = selection.getRangeAt(0); e.currentTarget.dataset.editorRange = JSON.stringify({ startContainer: range.startContainer.textContent, startOffset: range.startOffset, endContainer: range.endContainer.textContent, endOffset: range.endOffset }); } }; const handleInputBlur = (e) => { setTimeout(() => { const activeElement = document.activeElement; if (!containerRef.current?.contains(activeElement)) { const rangeData = e.currentTarget.dataset.editorRange; if (rangeData) { delete e.currentTarget.dataset.editorRange; } } }, 10); }; const containerProps = { ref: containerRef, onMouseDown: (e) => e.stopPropagation(), onMouseMove: (e) => e.stopPropagation() }; const inputProps = { onFocus: handleInputInteraction, onBlur: handleInputBlur, onMouseDown: handleInputInteraction }; return { containerProps, inputProps }; }; // src/features/textColor/components/TextColorPicker.tsx var import_jsx_runtime = require("react/jsx-runtime"); var injectStyles = () => { const style = document.createElement("style"); style.innerHTML = ` div.react-colorful .react-colorful__pointer { width: 20px; height: 20px; } div.react-colorful .react-colorful__hue { height: 22px; } `; document.head.appendChild(style); }; var TextColorPicker = ({ color, applyColor, onChange, colors = [], hideAttribution = false, colorPicker = true, listView, handleReset }) => { const { containerProps, inputProps } = usePreventInlineToolbarClose(); const [predefinedColors, setPredefinedColors] = (0, import_react2.useState)(true); (0, import_react2.useEffect)(() => { injectStyles(); }, []); const isGridView = listView === false || listView !== true && typeof colors[0] === "string"; return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)( "div", { ...containerProps, style: { display: "flex", flexDirection: "column", maxWidth: "165px", width: "100%" }, children: [ !predefinedColors && colorPicker ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)( "div", { onClick: (e) => { e.preventDefault(); e.stopPropagation(); }, style: { width: "100%", paddingTop: "8px", paddingLeft: "8px", paddingRight: "8px", paddingBottom: "0px", display: "flex", flexDirection: "column", alignItems: "center" }, children: [ /* @__PURE__ */ (0, import_jsx_runtime.jsx)( import_react_colorful.HexColorPicker, { style: { maxWidth: "100%", height: "min-content", aspectRatio: "1" }, color, onChange } ), /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "field-type text", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)( "input", { style: { width: "100%", margin: "8px 0", height: "25px", paddingTop: "0", paddingBottom: "1px", paddingLeft: "10px" }, type: "text", value: color, onChange: (e) => { e.preventDefault(); e.stopPropagation(); onChange(e.target.value); }, ...inputProps } ) }) ] } ) : /* @__PURE__ */ (0, import_jsx_runtime.jsxs)( "div", { style: { display: isGridView ? "grid" : "flex", gridTemplateColumns: isGridView ? "repeat(5, 1fr)" : void 0, flexDirection: isGridView ? void 0 : "column", gap: isGridView ? "4px" : "6px", padding: "8px", overflowY: isGridView ? void 0 : "auto", maxHeight: isGridView ? void 0 : "266px" }, children: [ colors.map((unionC) => { const c = typeof unionC === "string" ? unionC : unionC.value; return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)( "button", { onClick: () => { applyColor(c); }, style: { display: "flex", gap: isGridView ? "4px" : "6px", alignItems: "center", cursor: "pointer", background: "transparent", border: "none", padding: "0" }, children: [ /* @__PURE__ */ (0, import_jsx_runtime.jsx)( "div", { style: { backgroundColor: c, width: "26px", height: "26px", borderRadius: "50%", border: color === c ? "2px solid var(--theme-elevation-900)" : "2px solid var(--theme-elevation-150)" } } ), !isGridView && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { children: typeof unionC === "string" ? unionC : unionC.label }) ] }, c ); }), /* @__PURE__ */ (0, import_jsx_runtime.jsxs)( "button", { onClick: () => handleReset(), style: { display: "flex", gap: isGridView ? "4px" : "6px", alignItems: "center", cursor: "pointer", background: "transparent", border: "none", padding: "0" }, children: [ /* @__PURE__ */ (0, import_jsx_runtime.jsx)( "div", { style: { width: "26px", height: "26px", borderRadius: "50%", border: "2px solid var(--theme-elevation-150)", position: "relative", cursor: "pointer" }, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)( "div", { style: { position: "absolute", width: "100%", height: "2px", backgroundColor: "#FF0000", top: "50%", left: "50%", transform: "translate(-50%,-50%) rotate(45deg)" } } ) } ), !isGridView && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { children: "Reset" }) ] } ) ] } ), !predefinedColors && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: { display: "flex", gap: "8px" }, children: [ /* @__PURE__ */ (0, import_jsx_runtime.jsx)( "button", { onClick: (e) => { e.preventDefault(); e.stopPropagation(); handleReset(); }, className: "btn btn--icon-style-without-border btn--size-small btn--withoutPopup btn--style-pill btn--withoutPopup", style: { marginLeft: "auto", margin: "0", cursor: "pointer", flex: 1 }, children: "Reset" } ), /* @__PURE__ */ (0, import_jsx_runtime.jsx)( "button", { onClick: (e) => { e.preventDefault(); e.stopPropagation(); applyColor(); }, className: "btn btn--icon-style-without-border btn--size-small btn--withoutPopup btn--style-pill btn--withoutPopup", style: { marginLeft: "auto", margin: "0", cursor: "pointer", flex: 1 }, children: "Apply" } ) ] }), /* @__PURE__ */ (0, import_jsx_runtime.jsxs)( "div", { style: { width: "100%", padding: "8px", display: "flex", gap: "8px", flexDirection: "column", alignItems: "center" }, children: [ colorPicker && /* @__PURE__ */ (0, import_jsx_runtime.jsx)( "button", { onClick: (e) => { e.preventDefault(); e.stopPropagation(); setPredefinedColors((prev) => !prev); }, className: "btn btn--icon-style-without-border btn--size-small btn--withoutPopup btn--style-pill btn--withoutPopup", style: { margin: 0 }, children: predefinedColors ? "Color picker" : "Predefined colors" } ), !hideAttribution && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)( "p", { style: { color: "var(--theme-elevation-650)", fontSize: "10px" }, children: [ "Made with \u2764\uFE0F by", " ", /* @__PURE__ */ (0, import_jsx_runtime.jsx)("a", { target: "_blank", href: "https://github.com/AdrianMaj", children: "@AdrianMaj" }) ] } ) ] } ) ] } ); }; // src/features/textColor/components/TextColorDropdown.tsx var import_jsx_runtime2 = require("react/jsx-runtime"); var TextColorDropdown = ({ editor, item }) => { const [activeColor, setActiveColor] = (0, import_react3.useState)(""); const onChange = (color) => { setActiveColor(color || ""); }; const applyColor = (color) => { editor.dispatchCommand(item.command, { color: color ?? activeColor }); }; const handleReset = () => { editor.dispatchCommand(item.command, { color: "" }); setActiveColor(""); }; (0, import_react3.useEffect)(() => { editor.read(() => { const current = item.current ? item.current() : null; if (current) setActiveColor(current); }); }, [editor, item]); return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)( TextColorPicker, { color: activeColor, applyColor, onChange, colors: item.colors, hideAttribution: item.hideAttribution, colorPicker: item.colorPicker, listView: item.listView, handleReset } ); }; // src/features/textColor/components/TextColorIcon.tsx var import_lexical3 = require("@payloadcms/richtext-lexical/lexical"); var import_LexicalComposerContext = require("@payloadcms/richtext-lexical/lexical/react/LexicalComposerContext"); var import_selection = require("@payloadcms/richtext-lexical/lexical/selection"); var import_react4 = require("react"); // src/utils/getSelection.ts var import_lexical2 = require("@payloadcms/richtext-lexical/lexical"); var getSelection = (selection = (0, import_lexical2.$getSelection)()) => { if ((0, import_lexical2.$isRangeSelection)(selection)) { return selection; } return null; }; // src/features/textColor/components/TextColorIcon.tsx var import_jsx_runtime3 = require("react/jsx-runtime"); var TextColorIcon = () => { const [color, setColor] = (0, import_react4.useState)(""); const [editor] = (0, import_LexicalComposerContext.useLexicalComposerContext)(); const updateCurrentColor = () => { const selection = getSelection(); if (selection) setColor((0, import_selection.$getSelectionStyleValueForProperty)(selection, "color", "")); return false; }; (0, import_react4.useEffect)(() => { return editor.registerCommand( TEXT_COLOR_COMMAND, (payload) => { setColor(payload.color); editor.update(() => { const selection = getSelection(); if (selection) (0, import_selection.$patchStyleText)(selection, { color: payload.color || "" }); }); return false; }, import_lexical3.COMMAND_PRIORITY_CRITICAL ); }, [editor]); (0, import_react4.useEffect)(() => { setTimeout(() => { return editor.read(updateCurrentColor); }); return editor.registerCommand(import_lexical3.SELECTION_CHANGE_COMMAND, updateCurrentColor, import_lexical3.COMMAND_PRIORITY_CRITICAL); }, [editor]); return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)( "svg", { xmlns: "http://www.w3.org/2000/svg", width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("path", { d: "M4 20h16", style: { color } }), /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("path", { d: "m6 16 6-12 6 12" }), /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("path", { d: "M8 12h8" }) ] } ); }; // src/features/textColor/feature.client.tsx var TextColorClientFeature = (0, import_client.createClientFeature)( ({ props }) => { const colors = props?.colors && props?.colors.length > 0 ? props.colors : ["#FF0000", "#00FF00", "#0000FF", "#FFFF00", "#FF00FF"]; const DropdownComponent = { type: "dropdown", ChildComponent: TextColorIcon, isEnabled({ selection }) { return !!getSelection(selection); }, items: [ { Component: () => { const [editor] = (0, import_LexicalComposerContext2.useLexicalComposerContext)(); return TextColorDropdown({ editor, item: { command: TEXT_COLOR_COMMAND, current() { const selection = getSelection(); return selection ? (0, import_selection2.$getSelectionStyleValueForProperty)(selection, "color", "") : null; }, colors, listView: props?.listView, hideAttribution: props?.hideAttribution, colorPicker: props?.colorPicker, key: "textColor" } }); }, key: "textColor" } ], key: "textColorDropdown", order: 60 }; return { plugins: [ { Component: () => { const [editor] = (0, import_LexicalComposerContext2.useLexicalComposerContext)(); (0, import_react5.useEffect)(() => { return editor.registerCommand( TEXT_COLOR_COMMAND, (payload) => { editor.update(() => { const selection = getSelection(); if (selection) { (0, import_selection2.$patchStyleText)(selection, { color: payload.color || "" }); } }); return true; }, import_lexical4.COMMAND_PRIORITY_CRITICAL ); }, [editor]); return null; }, position: "normal" } ], toolbarFixed: { groups: [DropdownComponent] }, toolbarInline: { groups: [DropdownComponent] } }; } ); // src/features/textSize/feature.client.tsx var import_client2 = require("@payloadcms/richtext-lexical/client"); var import_lexical7 = require("@payloadcms/richtext-lexical/lexical"); var import_LexicalComposerContext4 = require("@payloadcms/richtext-lexical/lexical/react/LexicalComposerContext"); var import_selection4 = require("@payloadcms/richtext-lexical/lexical/selection"); var import_react9 = require("react"); // src/features/textSize/command.ts var import_lexical5 = require("@payloadcms/richtext-lexical/lexical"); var TEXT_SIZE_COMMAND = (0, import_lexical5.createCommand)("TEXT_SIZE_COMMAND"); // src/features/textSize/components/TextSizeDropdown.tsx var import_react7 = require("react"); // src/features/textSize/components/TextSizePicker.tsx var import_react6 = require("react"); var import_jsx_runtime4 = require("react/jsx-runtime"); var SizePicker = ({ size, onChange, hideAttribution, sizes, method = "replace", scroll = true, customSize = true }) => { const isEditingRef = (0, import_react6.useRef)(false); const { containerProps, inputProps } = usePreventInlineToolbarClose(); const defaultSizeOptions = [ { value: "0.875rem", label: "Small" }, { value: "1.25rem", label: "Normal" }, { value: "1.875rem", label: "Large" }, { value: "3rem", label: "Huge" } ]; const options = method === "replace" ? sizes ?? defaultSizeOptions : [...defaultSizeOptions, ...sizes ?? []]; const units = ["px", "rem", "em", "vh", "vw", "%"]; const [displayValue, setDisplayValue] = (0, import_react6.useState)(size || ""); const [appliedValue, setAppliedValue] = (0, import_react6.useState)(size || ""); const [isCustomMode, setIsCustomMode] = (0, import_react6.useState)(false); const [customNumberValue, setCustomNumberValue] = (0, import_react6.useState)(""); const [customUnit, setCustomUnit] = (0, import_react6.useState)("px"); const parseSizeValue = (sizeVal) => { const numericPart = parseFloat(sizeVal.replace(/[^0-9.]/g, "")); const unitPart = sizeVal.replace(/[0-9.]/g, ""); return { number: isNaN(numericPart) ? "" : numericPart.toString(), unit: units.includes(unitPart) ? unitPart : "px" }; }; (0, import_react6.useEffect)(() => { if (isEditingRef.current) return; if (!size) { setDisplayValue(""); setAppliedValue(""); setIsCustomMode(true); setCustomNumberValue(""); setCustomUnit("px"); return; } setDisplayValue(size); setAppliedValue(size); const { number, unit } = parseSizeValue(size); setCustomNumberValue(number); setCustomUnit(unit); const matchingOption = options.find((option) => option.value === size); setIsCustomMode(!matchingOption); }, [size, options]); const handleSizeSelect = (value) => { setDisplayValue(value); setAppliedValue(value); onChange(value); setIsCustomMode(false); const { number, unit } = parseSizeValue(value); setCustomNumberValue(number); setCustomUnit(unit); }; const handleCustomNumberChange = (e) => { e.preventDefault(); e.stopPropagation(); isEditingRef.current = true; const numValue = e.target.value; setCustomNumberValue(numValue); const newValue = `${numValue}${customUnit}`; setDisplayValue(newValue); setIsCustomMode(true); }; const handleCustomUnitChange = (e) => { e.preventDefault(); e.stopPropagation(); isEditingRef.current = true; const unitValue = e.target.value; setCustomUnit(unitValue); const newValue = `${customNumberValue}${unitValue}`; setDisplayValue(newValue); setIsCustomMode(true); }; const applyCustomSize = () => { isEditingRef.current = false; setAppliedValue(displayValue); onChange(displayValue); }; const handleReset = () => { isEditingRef.current = false; setDisplayValue(""); setAppliedValue(""); setCustomNumberValue(""); setCustomUnit("px"); onChange(""); }; return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)( "div", { ...containerProps, style: { padding: "8px", display: "flex", flexDirection: "column", gap: "8px" }, children: [ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)( "div", { style: { display: "grid", gridTemplateColumns: "1fr 1fr", gap: "12px", maxHeight: scroll && options.length > 4 ? "64px" : "none", overflowY: scroll && options.length > 4 ? "auto" : "visible", paddingRight: scroll && options.length > 4 ? "8px" : "0" }, children: options.map((option, index) => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)( "button", { className: "btn btn--icon-style-without-border btn--size-small btn--withoutPopup btn--style-pill btn--withoutPopup", style: { cursor: "pointer", margin: "0", border: appliedValue === option.value && !isCustomMode ? "1px solid var(--theme-elevation-900)" : "1px solid transparent" }, onClick: (e) => { e.preventDefault(); e.stopPropagation(); handleSizeSelect(option.value); }, children: option.label }, `${option.value}-${index}` )) } ), customSize && /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { style: { display: "flex", alignItems: "center" }, children: [ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { style: { marginRight: "8px" }, children: "Custom: " }), /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)( "div", { style: { display: "flex", alignItems: "center", width: "140px" }, children: [ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)( "div", { className: "field-type number", onClick: (e) => { e.stopPropagation(); }, style: { flex: 1 }, children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)( "input", { style: { width: "100%", margin: "8px 0", borderRight: "0", height: "25px", borderTopRightRadius: "0", borderBottomRightRadius: "0", paddingTop: "0", paddingBottom: "1px", paddingLeft: "4px", paddingRight: "4px" }, type: "number", min: 1, max: 999, value: customNumberValue, onChange: handleCustomNumberChange, onClick: (e) => e.stopPropagation(), ...inputProps } ) } ), /* @__PURE__ */ (0, import_jsx_runtime4.jsx)( "select", { value: customUnit, onChange: handleCustomUnitChange, onClick: (e) => e.stopPropagation(), style: { paddingLeft: "4px", paddingRight: "4px", width: "56px", boxShadow: "0 2px 2px -1px #0000001a", fontFamily: "var(--font-body)", border: "1px solid var(--theme-elevation-150)", borderRadius: "var(--style-radius-s)", background: "var(--theme-input-bg)", color: "var(--theme-elevation-800)", fontSize: "1rem", height: "25px", lineHeight: "20px", transitionProperty: "border, box-shadow, background-color", transitionDuration: ".1s, .1s, .5s", transitionTimingFunction: "cubic-bezier(0,.2,.2,1)", borderLeft: "0", transform: "translateX(-1px)", borderTopLeftRadius: "0", borderBottomLeftRadius: "0", outline: "none" }, children: units.map((unit, index) => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("option", { value: unit, children: unit }, `${unit}-${index}`)) } ) ] } ) ] }), /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { style: { display: "flex", gap: "8px" }, children: [ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)( "button", { onClick: (e) => { e.preventDefault(); e.stopPropagation(); handleReset(); }, className: "btn btn--icon-style-without-border btn--size-small btn--withoutPopup btn--style-pill btn--withoutPopup", style: { marginLeft: "auto", margin: "0", cursor: "pointer", flex: 1 }, children: "Reset" } ), customSize && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)( "button", { onClick: (e) => { e.preventDefault(); e.stopPropagation(); applyCustomSize(); }, className: "btn btn--icon-style-without-border btn--size-small btn--withoutPopup btn--style-pill btn--withoutPopup", style: { marginLeft: "auto", margin: "0", cursor: "pointer", flex: 1 }, children: "Apply" } ) ] }), !hideAttribution && /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)( "p", { style: { color: "var(--theme-elevation-650)", fontSize: "10px", textAlign: "center" }, children: [ "Made with \u2764\uFE0F by", " ", /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("a", { target: "_blank", href: "https://github.com/AdrianMaj", children: "@AdrianMaj" }) ] } ) ] } ); }; // src/features/textSize/components/TextSizeDropdown.tsx var import_jsx_runtime5 = require("react/jsx-runtime"); var Dropdown = ({ editor, item }) => { const [activeSize, setActiveSize] = (0, import_react7.useState)(""); const onChange = (size) => { editor.dispatchCommand(item.command, { size }); setActiveSize(size || ""); }; (0, import_react7.useEffect)(() => { editor.read(() => { const current = item.current ? item.current() : null; if (current) setActiveSize(current); }); }, [editor, item]); return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)( SizePicker, { size: activeSize, onChange, hideAttribution: item.hideAttribution, method: item.method, scroll: item.scroll, sizes: item.sizes, customSize: item.customSize } ); }; // src/features/textSize/components/TextSizeIcon.tsx var import_lexical6 = require("@payloadcms/richtext-lexical/lexical"); var import_LexicalComposerContext3 = require("@payloadcms/richtext-lexical/lexical/react/LexicalComposerContext"); var import_selection3 = require("@payloadcms/richtext-lexical/lexical/selection"); var import_react8 = require("react"); var import_jsx_runtime6 = require("react/jsx-runtime"); var TextSizeIcon = () => { const [editor] = (0, import_LexicalComposerContext3.useLexicalComposerContext)(); (0, import_react8.useEffect)(() => { return editor.registerCommand( TEXT_SIZE_COMMAND, (payload) => { editor.update(() => { const selection = getSelection(); if (selection) (0, import_selection3.$patchStyleText)(selection, { size: payload.size || "" }); }); return false; }, import_lexical6.COMMAND_PRIORITY_CRITICAL ); }, [editor]); return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)( "svg", { xmlns: "http://www.w3.org/2000/svg", width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("path", { d: "M21 14h-5" }), /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("path", { d: "M16 16v-3.5a2.5 2.5 0 0 1 5 0V16" }), /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("path", { d: "M4.5 13h6" }), /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("path", { d: "m3 16 4.5-9 4.5 9" }) ] } ); }; // src/features/textSize/feature.client.tsx var TextSizeClientFeature = (0, import_client2.createClientFeature)(({ props }) => { const DropdownComponent = { type: "dropdown", ChildComponent: TextSizeIcon, isEnabled({ selection }) { return !!getSelection(selection); }, items: [ { Component: () => { const [editor] = (0, import_LexicalComposerContext4.useLexicalComposerContext)(); return Dropdown({ editor, item: { command: TEXT_SIZE_COMMAND, current() { const selection = getSelection(); return selection ? (0, import_selection4.$getSelectionStyleValueForProperty)(selection, "font-size", "") : null; }, hideAttribution: props?.hideAttribution, sizes: props?.sizes, method: props?.method, scroll: props?.scroll, customSize: props?.customSize, key: "textSize" } }); }, key: "textSize" } ], key: "textSizeDropdown", order: 60 }; return { plugins: [ { Component: () => { const [editor] = (0, import_LexicalComposerContext4.useLexicalComposerContext)(); (0, import_react9.useEffect)(() => { return editor.registerCommand( TEXT_SIZE_COMMAND, (payload) => { editor.update(() => { const selection = getSelection(); if (selection) { (0, import_selection4.$patchStyleText)(selection, { "font-size": payload.size || "" }); } }); return true; }, import_lexical7.COMMAND_PRIORITY_CRITICAL ); }, [editor]); return null; }, position: "normal" } ], toolbarFixed: { groups: [DropdownComponent] }, toolbarInline: { groups: [DropdownComponent] } }; }); // src/features/textLetterSpacing/feature.client.tsx var import_client3 = require("@payloadcms/richtext-lexical/client"); var import_lexical10 = require("@payloadcms/richtext-lexical/lexical"); var import_LexicalComposerContext6 = require("@payloadcms/richtext-lexical/lexical/react/LexicalComposerContext"); var import_selection6 = require("@payloadcms/richtext-lexical/lexical/selection"); var import_react13 = require("react"); // src/features/textLetterSpacing/command.ts var import_lexical8 = require("@payloadcms/richtext-lexical/lexical"); var TEXT_LETTER_SPACING_COMMAND = (0, import_lexical8.createCommand)("TEXT_LETTER_SPACING_COMMAND"); // src/features/textLetterSpacing/components/TextLetterSpacingDropdown.tsx var import_react11 = require("react"); // src/features/textLetterSpacing/components/TextLetterSpacingPicker.tsx var import_react10 = require("react"); var import_jsx_runtime7 = require("react/jsx-runtime"); var SpacingPicker = ({ spacing, onChange, hideAttribution, spacings, method = "replace", scroll = true, customSpacing = true }) => { const { containerProps, inputProps } = usePreventInlineToolbarClose(); const isEditingRef = (0, import_react10.useRef)(false); const defaultSpacingOptions = [ { value: "-0.05em", label: "Tighter" }, { value: "-0.025em", label: "Tight" }, { value: "0em", label: "Normal" }, { value: "0.025em", label: "Wide" }, { value: "0.05em", label: "Wider" }, { value: "0.1em", label: "Widest" } ]; const options = method === "replace" ? spacings ?? defaultSpacingOptions : [...defaultSpacingOptions, ...spacings ?? []]; const units = ["px", "rem", "em", "%"]; const [displayValue, setDisplayValue] = (0, import_react10.useState)(spacing || ""); const [appliedValue, setAppliedValue] = (0, import_react10.useState)(spacing || ""); const [isCustomMode, setIsCustomMode] = (0, import_react10.useState)(false); const [customNumberValue, setCustomNumberValue] = (0, import_react10.useState)(""); const [customUnit, setCustomUnit] = (0, import_react10.useState)("em"); const parseSpacingValue = (spacingVal) => { const sign = spacingVal.startsWith("-") ? "-" : ""; const cleanedVal = spacingVal.replace(/^-?/, "").replace(/[^0-9.]/g, ""); const numericPart = parseFloat(sign + cleanedVal); const unitPart = spacingVal.replace(/^-?[0-9.]/g, ""); return { number: isNaN(numericPart) ? "" : numericPart.toString(), unit: units.includes(unitPart) ? unitPart : "em" }; }; (0, import_react10.useEffect)(() => { if (isEditingRef.current) return; if (!spacing) { setDisplayValue(""); setAppliedValue(""); setIsCustomMode(true); setCustomNumberValue(""); setCustomUnit("em"); return; } setDisplayValue(spacing); setAppliedValue(spacing); const { number, unit } = parseSpacingValue(spacing); setCustomNumberValue(number); setCustomUnit(unit); const matchingOption = options.find((option) => option.value === spacing); setIsCustomMode(!matchingOption); }, [spacing, options]); const handleSpacingSelect = (value) => { setDisplayValue(value); setAppliedValue(value); onChange(value); setIsCustomMode(false); const { number, unit } = parseSpacingValue(value); setCustomNumberValue(number); setCustomUnit(unit); }; const handleCustomNumberChange = (e) => { e.preventDefault(); e.stopPropagation(); isEditingRef.current = true; const numValue = e.target.value; setCustomNumberValue(numValue); const newValue = `${numValue}${customUnit}`; setDisplayValue(newValue); setIsCustomMode(true); }; const handleCustomUnitChange = (e) => { e.preventDefault(); e.stopPropagation(); isEditingRef.current = true; const unitValue = e.target.value; setCustomUnit(unitValue); const newValue = `${customNumberValue}${unitValue}`; setDisplayValue(newValue); setIsCustomMode(true); }; const applyCustomSpacing = () => { isEditingRef.current = false; setAppliedValue(displayValue); onChange(displayValue); }; const handleReset = () => { isEditingRef.current = false; setDisplayValue(""); setAppliedValue(""); setCustomNumberValue(""); setCustomUnit("em"); onChange(""); }; return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)( "div", { ...containerProps, style: { padding: "8px", display: "flex", flexDirection: "column", gap: "8px" }, children: [ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)( "div", { style: { display: "grid", gridTemplateColumns: "1fr 1fr", gap: "12px", maxHeight: scroll && options.length > 4 ? "64px" : "none", overflowY: scroll && options.length > 4 ? "auto" : "visible", paddingRight: scroll && options.length > 4 ? "8px" : "0" }, children: options.map((option, index) => /* @__PURE__ */ (0, import_jsx_runtime7.jsx)( "button", { className: "btn btn--icon-style-without-border btn--size-small btn--withoutPopup btn--style-pill btn--withoutPopup", style: { cursor: "pointer", margin: "0", border: appliedValue === option.value && !isCustomMode ? "1px solid var(--theme-elevation-900)" : "1px solid transparent" }, onClick: (e) => { e.preventDefault(); e.stopPropagation(); handleSpacingSelect(option.value); }, children: option.label }, `${option.value}-${index}` )) } ), customSpacing && /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { style: { display: "flex", alignItems: "center" }, children: [ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { style: { marginRight: "8px" }, children: "Custom: " }), /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)( "div", { style: { display: "flex", alignItems: "center", width: "140px" }, children: [ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)( "div", { className: "field-type number", onClick: (e) => { e.stopPropagation(); }, style: { flex: 1 }, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)( "input", { style: { width: "100%", margin: "8px 0", borderRight: "0", height: "25px", borderTopRightRadius: "0", borderBottomRightRadius: "0", paddingTop: "0", paddingBottom: "1px", paddingLeft: "4px", paddingRight: "4px" }, type: "number", min: 0, step: 0.01, max: 10, value: customNumberValue, onChange: handleCustomNumberChange, onClick: (e) => e.stopPropagation(), ...inputProps } ) } ), /* @__PURE__ */ (0, import_jsx_runtime7.jsx)( "select", { value: customUnit, onChange: handleCustomUnitChange, onClick: (e) => e.stopPropagation(), style: { paddingLeft: "4px", paddingRight: "4px", width: "56px", boxShadow: "0 2px 2px -1px #0000001a", fontFamily: "var(--font-body)", border: "1px solid var(--theme-elevation-150)", borderRadius: "var(--style-radius-s)", background: "var(--theme-input-bg)", color: "var(--theme-elevation-800)", fontSize: "1rem", height: "25px", lineHeight: "20px", transitionProperty: "border, box-shadow, background-color", transitionDuration: ".1s, .1s, .5s", transitionTimingFunction: "cubic-bezier(0,.2,.2,1)", borderLeft: "0", transform: "translateX(-1px)", borderTopLeftRadius: "0", borderBottomLeftRadius: "0", outline: "none" }, children: units.map((unit, index) => /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("option", { value: unit, children: unit }, `${unit}-${index}`)) } ) ] } ) ] }), /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { style: { display: "flex", gap: "8px" }, children: [ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)( "button", { onClick: (e) => { e.preventDefault(); e.stopPropagation(); handleReset(); }, className: "btn btn--icon-style-without-border btn--size-small btn--withoutPopup btn--style-pill btn--withoutPopup", style: { marginLeft: "auto", margin: "0", cursor: "pointer", flex: 1 }, children: "Reset" } ), customSpacing && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)( "button", { onClick: (e) => { e.preventDefault(); e.stopPropagation(); applyCustomSpacing(); }, className: "btn btn--icon-style-without-border btn--size-small btn--withoutPopup btn--style-pill btn--withoutPopup", style: { marginLeft: "auto", margin: "0", cursor: "pointer", flex: 1 }, children: "Apply" } ) ] }), !hideAttribution && /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)( "p", { style: { color: "var(--theme-elevation-650)", fontSize: "10px", textAlign: "center" }, children: [ "Made with \u2764\uFE0F by", " ", /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("a", { target: "_blank", href: "https://github.com/AdrianMaj", children: "@AdrianMaj" }) ] } ) ] } ); }; // src/features/textLetterSpacing/components/TextLetterSpacingDropdown.tsx var import_jsx_runtime8 = require("react/jsx-runtime"); var Dropdown2 = ({ editor, item }) => { const [activeSpacing, setActiveSpacing] = (0, import_react11.useState)(""); const onChange = (spacing) => { editor.dispatchCommand(item.command, { spacing }); setActiveSpacing(spacing || ""); }; (0, import_react11.useEffect)(() => { editor.read(() => { const current = item.current ? item.current() : null; if (current) setActiveSpacing(current); }); }, [editor, item]); return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)( SpacingPicker, { spacing: activeSpacing, onChange, hideAttribution: item.hideAttribution, method: item.method, scroll: item.scroll, spacings: item.spacings, customSpacing: item.customSpacing } ); }; // src/features/textLetterSpacing/components/TextLetterSpacingIcon.tsx var import_lexical9 = require("@payloadcms/richtext-lexical/lexical"); var import_LexicalComposerContext5 = require("@payloadcms/richtext-lexical/lexical/react/LexicalComposerContext"); var import_selection5 = require("@payloadcms/richtext-lexical/lexical/selection"); var import_react12 = require("react"); var import_jsx_runtime9 = require("react/jsx-runtime"); var TextLetterSpacingIcon = () => { const [editor] = (0, import_LexicalComposerContext5.useLexicalComposerContext)(); (0, import_react12.useEffect)(() => { return editor.registerCommand( TEXT_LETTER_SPACING_COMMAND, (payload) => { editor.update(() => { const selection = getSelection(); if (selection) (0, import_selection5.$patchStyleText)(selection, { "letter-spacing": payload.spacing || "" }); }); return false; }, import_lexical9.COMMAND_PRIORITY_CRITICAL ); }, [editor]); return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)( "svg", { xmlns: "http://www.w3.org/2000/svg", width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("path", { d: "M2 18h2" }), /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("path", { d: "M20 18h2" }), /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("path", { d: "M4 7v11" }), /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("path", { d: "M20 7v11" }), /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("path", { d: "M12 20v2" }), /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("path", { d: "M12 14v2" }), /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("path", { d: "M12 8v2" }), /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("path", { d: "M12 2v2" }) ] } ); }; // src/features/textLetterSpacing/feature.client.tsx var TextLetterSpacingClientFeature = (0, import_client3.createClientFeature)(({ props }) => { const DropdownComponent = { type: "dropdown", ChildComponent: TextLetterSpacingIcon, isEnabled({ selection }) { return !!getSelection(selection); }, items: [ { Component: () => { const [editor] = (0, import_LexicalComposerContext6.useLexicalComposerContext)(); return Dropdown2({ editor, item: { command: TEXT_LETTER_SPACING_COMMAND, current() { const selection = getSelection(); return selection ? (0, import_selection6.$getSelectionStyleValueForProperty)(selection, "letter-spacing", "") : null; }, hideAttribution: props?.hideAttribution, spacings: props?.spacings, method: props?.method, scroll: props?.scroll, customSpacing: props?.customSpacing,