@arkyn/components 3.0.5 → 3.0.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/richText/index.d.ts +1 -0
- package/dist/components/richText/index.d.ts.map +1 -1
- package/dist/index.js +163 -154
- package/dist/index.js.map +1 -1
- package/dist/modules/components/richText/index.js +73 -71
- package/dist/modules/components/richText/index.js.map +1 -1
- package/dist/modules/services/clearLinkMarkAtBoundary.js +12 -0
- package/dist/modules/services/clearLinkMarkAtBoundary.js.map +1 -0
- package/dist/services/clearLinkMarkAtBoundary.d.ts +4 -0
- package/dist/services/clearLinkMarkAtBoundary.d.ts.map +1 -0
- package/package.json +1 -1
|
@@ -1,139 +1,141 @@
|
|
|
1
1
|
import { useForm as e } from "../../hooks/useForm.js";
|
|
2
2
|
import { FieldTemplate as t } from "../../services/fieldTemplate.js";
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
3
|
+
import { clearLinkMarkAtBoundary as n } from "../../services/clearLinkMarkAtBoundary.js";
|
|
4
|
+
import { extractTextFromNode as r } from "../../services/extractTextFromNode.js";
|
|
5
|
+
import { toggleMark as i } from "../../services/toggleMark.js";
|
|
6
|
+
import { hotKeys as a, initialValue as o } from "../../templates/richTextTemplates.js";
|
|
7
|
+
import { BlockButton as s } from "./blockButton/index.js";
|
|
8
|
+
import { Element as c } from "./element/index.js";
|
|
9
|
+
import { InsertImage as l } from "./insertImage/index.js";
|
|
9
10
|
import { InsertLink as ee } from "./insertLink/index.js";
|
|
10
11
|
import { InsertVideo as te } from "./insertVideo/index.js";
|
|
11
12
|
import { Leaf as ne } from "./leaf/index.js";
|
|
12
|
-
import { MarkButton as
|
|
13
|
-
import { Toolbar as
|
|
13
|
+
import { MarkButton as u } from "./markButton/index.js";
|
|
14
|
+
import { Toolbar as d } from "./toolbar/index.js";
|
|
14
15
|
/* empty css */
|
|
15
|
-
import { useCallback as
|
|
16
|
-
import { jsx as
|
|
17
|
-
import { AlignCenter as ie, AlignJustify as ae, AlignLeft as oe, AlignRight as se, Bold as ce, Code as
|
|
18
|
-
import
|
|
19
|
-
import { createEditor as
|
|
20
|
-
import { withHistory as
|
|
21
|
-
import { Editable as
|
|
16
|
+
import { useCallback as f, useId as p, useMemo as m, useRef as re, useState as h } from "react";
|
|
17
|
+
import { jsx as g, jsxs as _ } from "react/jsx-runtime";
|
|
18
|
+
import { AlignCenter as ie, AlignJustify as ae, AlignLeft as oe, AlignRight as se, Bold as ce, Code as v, Heading1 as y, Heading2 as b, Italic as x, Quote as S, Underline as C } from "lucide-react";
|
|
19
|
+
import { isHotkey as w } from "is-hotkey";
|
|
20
|
+
import { createEditor as T } from "slate";
|
|
21
|
+
import { withHistory as E } from "slate-history";
|
|
22
|
+
import { Editable as D, Slate as O, withReact as k } from "slate-react";
|
|
22
23
|
//#region src/components/richText/index.tsx
|
|
23
|
-
function
|
|
24
|
-
let { name:
|
|
24
|
+
function A(A) {
|
|
25
|
+
let { name: j, hiddenButtons: M, imageConfig: N, videoConfig: P, linkConfig: F, className: I = "", defaultValue: L = "[]", enforceCharacterLimit: R = !1, onChangeCharactersCount: z, baseErrorMessage: B, maxLimit: V = 1e4, onChange: le, isError: H, label: U, showAsterisk: W, id: ue, orientation: de = "vertical", unShowFieldTemplate: fe = !1 } = A, G = m(() => E(k(T())), []), { fieldErrors: pe } = e(), K = m(() => {
|
|
25
26
|
try {
|
|
26
|
-
let e = JSON.parse(
|
|
27
|
-
return !Array.isArray(e) || e.length === 0 ? structuredClone(
|
|
27
|
+
let e = JSON.parse(L);
|
|
28
|
+
return !Array.isArray(e) || e.length === 0 ? structuredClone(o) : e.every((e) => typeof e == "object" && !!e && "type" in e && "children" in e) ? e : structuredClone(o);
|
|
28
29
|
} catch {
|
|
29
|
-
return structuredClone(
|
|
30
|
+
return structuredClone(o);
|
|
30
31
|
}
|
|
31
|
-
}, [
|
|
32
|
+
}, [L]), [q, me] = h(r(K).length), [he, ge] = h(JSON.stringify(K) || "[]"), [_e, J] = h(!1), Y = re(null), ve = p(), ye = ue || ve, X = B || pe?.[j], be = H || !!X, xe = f(ne, []), Se = f(c, []);
|
|
32
33
|
function Z(e) {
|
|
33
|
-
let t =
|
|
34
|
-
|
|
34
|
+
let t = r(e);
|
|
35
|
+
me(t.length), z?.(t.length), !(R && t.length >= V) && (ge(JSON.stringify(e)), le?.(e));
|
|
35
36
|
}
|
|
36
|
-
let
|
|
37
|
+
let Ce = `arkynRichText ${be || V < q ? "errorTrue" : "errorFalse"} ${_e ? "focusTrue" : "focusFalse"}`, Q = V - q;
|
|
37
38
|
function $(e) {
|
|
38
|
-
return !
|
|
39
|
+
return !M?.includes(e);
|
|
39
40
|
}
|
|
40
|
-
return /* @__PURE__ */
|
|
41
|
-
name:
|
|
42
|
-
label:
|
|
43
|
-
showAsterisk:
|
|
44
|
-
className:
|
|
41
|
+
return /* @__PURE__ */ g(t, {
|
|
42
|
+
name: j,
|
|
43
|
+
label: U,
|
|
44
|
+
showAsterisk: W,
|
|
45
|
+
className: I,
|
|
45
46
|
errorMessage: X,
|
|
46
|
-
unShowFieldTemplate:
|
|
47
|
-
orientation:
|
|
48
|
-
children: /* @__PURE__ */
|
|
47
|
+
unShowFieldTemplate: fe,
|
|
48
|
+
orientation: de,
|
|
49
|
+
children: /* @__PURE__ */ _(O, {
|
|
49
50
|
editor: G,
|
|
50
51
|
initialValue: K,
|
|
51
52
|
onChange: Z,
|
|
52
53
|
onValueChange: Z,
|
|
53
54
|
children: [
|
|
54
|
-
/* @__PURE__ */
|
|
55
|
-
className:
|
|
55
|
+
/* @__PURE__ */ _("div", {
|
|
56
|
+
className: Ce,
|
|
56
57
|
children: [
|
|
57
|
-
/* @__PURE__ */
|
|
58
|
-
$("headingOne") && /* @__PURE__ */
|
|
58
|
+
/* @__PURE__ */ _(d, { children: [
|
|
59
|
+
$("headingOne") && /* @__PURE__ */ g(s, {
|
|
59
60
|
format: "headingOne",
|
|
60
|
-
icon:
|
|
61
|
+
icon: y
|
|
61
62
|
}),
|
|
62
|
-
$("headingTwo") && /* @__PURE__ */
|
|
63
|
+
$("headingTwo") && /* @__PURE__ */ g(s, {
|
|
63
64
|
format: "headingTwo",
|
|
64
|
-
icon:
|
|
65
|
+
icon: b
|
|
65
66
|
}),
|
|
66
|
-
$("blockQuote") && /* @__PURE__ */
|
|
67
|
+
$("blockQuote") && /* @__PURE__ */ g(s, {
|
|
67
68
|
format: "blockQuote",
|
|
68
|
-
icon:
|
|
69
|
+
icon: S
|
|
69
70
|
}),
|
|
70
|
-
$("bold") && /* @__PURE__ */
|
|
71
|
+
$("bold") && /* @__PURE__ */ g(u, {
|
|
71
72
|
format: "bold",
|
|
72
73
|
icon: ce
|
|
73
74
|
}),
|
|
74
|
-
$("italic") && /* @__PURE__ */
|
|
75
|
+
$("italic") && /* @__PURE__ */ g(u, {
|
|
75
76
|
format: "italic",
|
|
76
|
-
icon:
|
|
77
|
+
icon: x
|
|
77
78
|
}),
|
|
78
|
-
$("underline") && /* @__PURE__ */
|
|
79
|
+
$("underline") && /* @__PURE__ */ g(u, {
|
|
79
80
|
format: "underline",
|
|
80
|
-
icon:
|
|
81
|
+
icon: C
|
|
81
82
|
}),
|
|
82
|
-
$("code") && /* @__PURE__ */
|
|
83
|
+
$("code") && /* @__PURE__ */ g(u, {
|
|
83
84
|
format: "code",
|
|
84
|
-
icon:
|
|
85
|
+
icon: v
|
|
85
86
|
}),
|
|
86
|
-
$("left") && /* @__PURE__ */
|
|
87
|
+
$("left") && /* @__PURE__ */ g(s, {
|
|
87
88
|
format: "left",
|
|
88
89
|
icon: oe
|
|
89
90
|
}),
|
|
90
|
-
$("right") && /* @__PURE__ */
|
|
91
|
+
$("right") && /* @__PURE__ */ g(s, {
|
|
91
92
|
format: "right",
|
|
92
93
|
icon: se
|
|
93
94
|
}),
|
|
94
|
-
$("center") && /* @__PURE__ */
|
|
95
|
+
$("center") && /* @__PURE__ */ g(s, {
|
|
95
96
|
format: "center",
|
|
96
97
|
icon: ie
|
|
97
98
|
}),
|
|
98
|
-
$("justify") && /* @__PURE__ */
|
|
99
|
+
$("justify") && /* @__PURE__ */ g(s, {
|
|
99
100
|
format: "justify",
|
|
100
101
|
icon: ae
|
|
101
102
|
}),
|
|
102
|
-
|
|
103
|
-
$("video") && /* @__PURE__ */
|
|
104
|
-
$("link") && /* @__PURE__ */
|
|
103
|
+
N && $("image") && /* @__PURE__ */ g(l, { ...N }),
|
|
104
|
+
$("video") && /* @__PURE__ */ g(te, { ...P }),
|
|
105
|
+
$("link") && /* @__PURE__ */ g(ee, { ...F })
|
|
105
106
|
] }),
|
|
106
|
-
/* @__PURE__ */
|
|
107
|
+
/* @__PURE__ */ g(D, {
|
|
107
108
|
className: "editorContainer",
|
|
108
|
-
renderElement:
|
|
109
|
-
renderLeaf:
|
|
109
|
+
renderElement: Se,
|
|
110
|
+
renderLeaf: xe,
|
|
110
111
|
spellCheck: !0,
|
|
111
|
-
ref:
|
|
112
|
-
id:
|
|
112
|
+
ref: Y,
|
|
113
|
+
id: ye,
|
|
113
114
|
onFocus: () => J(!0),
|
|
114
115
|
onBlur: () => J(!1),
|
|
115
116
|
onKeyDown: (e) => {
|
|
116
|
-
|
|
117
|
+
(e.key === " " || e.key === "Enter") && n(G);
|
|
118
|
+
for (let t in a) if (w(t, e)) {
|
|
117
119
|
e.preventDefault();
|
|
118
|
-
let n =
|
|
119
|
-
|
|
120
|
+
let n = a[t];
|
|
121
|
+
i(G, n);
|
|
120
122
|
}
|
|
121
123
|
}
|
|
122
124
|
}),
|
|
123
|
-
Q < 0 && /* @__PURE__ */
|
|
125
|
+
Q < 0 && /* @__PURE__ */ g("div", {
|
|
124
126
|
className: "restatesCharacters",
|
|
125
127
|
children: Q
|
|
126
128
|
})
|
|
127
129
|
]
|
|
128
130
|
}),
|
|
129
|
-
/* @__PURE__ */
|
|
131
|
+
/* @__PURE__ */ g("input", {
|
|
130
132
|
type: "hidden",
|
|
131
|
-
name:
|
|
132
|
-
value:
|
|
133
|
+
name: j,
|
|
134
|
+
value: he.slice(0, V)
|
|
133
135
|
}),
|
|
134
|
-
/* @__PURE__ */
|
|
136
|
+
/* @__PURE__ */ g("input", {
|
|
135
137
|
type: "hidden",
|
|
136
|
-
name: `${
|
|
138
|
+
name: `${j}Count`,
|
|
137
139
|
value: q
|
|
138
140
|
})
|
|
139
141
|
]
|
|
@@ -141,6 +143,6 @@ function k(k) {
|
|
|
141
143
|
});
|
|
142
144
|
}
|
|
143
145
|
//#endregion
|
|
144
|
-
export {
|
|
146
|
+
export { A as RichText };
|
|
145
147
|
|
|
146
148
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":[],"sources":["../../../../src/components/richText/index.tsx"],"sourcesContent":["import isHotkey from \"is-hotkey\";\nimport {\n\tAlignCenter,\n\tAlignJustify,\n\tAlignLeft,\n\tAlignRight,\n\tBold,\n\tCode,\n\tHeading1,\n\tHeading2,\n\tItalic,\n\tQuote,\n\tUnderline,\n} from \"lucide-react\";\nimport { useCallback, useId, useMemo, useRef, useState } from \"react\";\nimport { createEditor, type Descendant } from \"slate\";\nimport { withHistory } from \"slate-history\";\nimport { Editable, Slate, withReact } from \"slate-react\";\nimport { useForm } from \"../../hooks/useForm\";\nimport { extractTextFromNode } from \"../../services/extractTextFromNode\";\nimport { FieldTemplate } from \"../../services/fieldTemplate\";\nimport { toggleMark } from \"../../services/toggleMark\";\nimport { hotKeys, initialValue } from \"../../templates/richTextTemplates\";\nimport type {\n\tRichTextHiddenButtonKey,\n\tRichTextProps,\n} from \"../../types/richTextTypes\";\nimport { BlockButton } from \"./blockButton\";\nimport { Element } from \"./element\";\nimport { InsertImage } from \"./insertImage\";\nimport { InsertLink } from \"./insertLink\";\nimport { InsertVideo } from \"./insertVideo\";\nimport { Leaf } from \"./leaf\";\nimport { MarkButton } from \"./markButton\";\nimport { Toolbar } from \"./toolbar\";\nimport \"./styles.css\";\n\n/**\n * RichText, WYSIWYG rich-text editor built on Slate.js with a configurable toolbar.\n *\n * **Toolbar features:** bold, italic, underline, code, H1/H2, block quote, alignment (left/center/right/justify), image, video, and link insertion.\n *\n * Editor content is stored as a Slate JSON string in a hidden `<input>` for form submission.\n * Integrates with `useForm` to display validation errors by field name.\n *\n * @param props.name - Field name for form submission. Required.\n * @param props.label - Label text displayed above the editor.\n * @param props.hiddenButtons - Toolbar button keys to hide (e.g. `[\"image\", \"code\"]`).\n * @param props.imageConfig - Enables image insertion; contains the upload endpoint and modal labels.\n * @param props.videoConfig - Customizes the video insertion modal labels.\n * @param props.linkConfig - Customizes the link insertion modal labels.\n * @param props.defaultValue - Initial editor content as a Slate JSON string. Default: \"[]\"\n * @param props.maxLimit - Maximum character count. Default: 10000\n * @param props.enforceCharacterLimit - Prevents typing past `maxLimit`. Default: false\n * @param props.onChangeCharactersCount - Callback fired on every keystroke, receives the current character count.\n * @param props.onChange - Callback fired when editor content changes, receives the Slate `Descendant[]`.\n * @param props.baseErrorMessage - Custom error message (overrides `useForm` context error).\n * @param props.isError - Forces the error visual state.\n * @param props.id - Custom id for the editable area element.\n * @param props.showAsterisk - Appends `*` to the label.\n * @param props.orientation - Layout direction. Default: \"horizontal\"\n * @param props.unShowFieldTemplate - Skips wrapper, label, and error rendering. Default: false\n *\n * @returns RichText JSX element wrapped in `FieldTemplate`.\n *\n * @example\n * ```tsx\n * // Basic\n * <RichText name=\"content\" />\n *\n * // With character limit and hidden toolbar buttons\n * <RichText\n * name=\"description\"\n * label=\"Description\"\n * maxLimit={500}\n * enforceCharacterLimit\n * hiddenButtons={[\"image\", \"video\", \"code\"]}\n * onChangeCharactersCount={(n) => setCharCount(n)}\n * />\n *\n * // With image upload support\n * <RichText\n * name=\"article\"\n * label=\"Article Body\"\n * imageConfig={{ action: \"/api/upload\" }}\n * />\n *\n * // With custom link insertion modal labels\n * <RichText\n * name=\"article\"\n * label=\"Article Body\"\n * linkConfig={{ modalTitle: \"Add a link\" }}\n * />\n * ```\n */\n\nfunction RichText(props: RichTextProps) {\n\tconst {\n\t\tname,\n\t\thiddenButtons,\n\t\timageConfig,\n\t\tvideoConfig,\n\t\tlinkConfig,\n\t\tclassName: wrapperClassName = \"\",\n\t\tdefaultValue = \"[]\",\n\t\tenforceCharacterLimit = false,\n\t\tonChangeCharactersCount,\n\t\tbaseErrorMessage,\n\t\tmaxLimit = 10000,\n\t\tonChange,\n\t\tisError: baseIsError,\n\t\tlabel,\n\t\tshowAsterisk,\n\t\tid,\n\t\torientation = \"vertical\",\n\t\tunShowFieldTemplate = false,\n\t} = props;\n\n\tconst editor = useMemo(() => withHistory(withReact(createEditor())), []);\n\n\tconst { fieldErrors } = useForm();\n\n\tconst defaultNodes = useMemo((): Descendant[] => {\n\t\ttry {\n\t\t\tconst parsedNodes = JSON.parse(defaultValue);\n\t\t\tif (!Array.isArray(parsedNodes) || parsedNodes.length === 0) {\n\t\t\t\treturn structuredClone(initialValue);\n\t\t\t}\n\n\t\t\tconst isValidNodes = parsedNodes.every(\n\t\t\t\t(node) =>\n\t\t\t\t\ttypeof node === \"object\" &&\n\t\t\t\t\tnode !== null &&\n\t\t\t\t\t\"type\" in node &&\n\t\t\t\t\t\"children\" in node,\n\t\t\t);\n\n\t\t\treturn isValidNodes ? parsedNodes : structuredClone(initialValue);\n\t\t} catch (_error) {\n\t\t\treturn structuredClone(initialValue);\n\t\t}\n\t}, [defaultValue]);\n\n\tconst textFromNodes = extractTextFromNode(defaultNodes);\n\n\tconst [charactersCount, setCharactersCount] = useState(textFromNodes.length);\n\tconst [inputValue, setInputValue] = useState(\n\t\tJSON.stringify(defaultNodes) || \"[]\",\n\t);\n\n\tconst [onFocus, setOnFocus] = useState(false);\n\n\tconst ref = useRef<HTMLInputElement>(null);\n\tconst generatedId = useId();\n\tconst inputId = id || generatedId;\n\n\tconst errorMessage = baseErrorMessage || fieldErrors?.[name];\n\tconst isError = baseIsError || !!errorMessage;\n\n\tconst renderLeaf = useCallback(Leaf, []);\n\tconst renderElement = useCallback(Element, []);\n\n\tfunction handleChange(value: Descendant[]) {\n\t\tconst text = extractTextFromNode(value);\n\n\t\tsetCharactersCount(text.length);\n\t\tonChangeCharactersCount?.(text.length);\n\n\t\tif (enforceCharacterLimit && text.length >= maxLimit) {\n\t\t\treturn;\n\t\t}\n\n\t\tsetInputValue(JSON.stringify(value));\n\t\tonChange?.(value);\n\t}\n\n\tconst focusClass = onFocus ? \"focusTrue\" : \"focusFalse\";\n\tconst errorClass = isError\n\t\t? \"errorTrue\"\n\t\t: maxLimit < charactersCount\n\t\t\t? \"errorTrue\"\n\t\t\t: \"errorFalse\";\n\n\tconst className = `arkynRichText ${errorClass} ${focusClass}`;\n\n\tconst restatesCharacters = maxLimit - charactersCount;\n\n\tfunction buttonIsNotHidden(format: RichTextHiddenButtonKey) {\n\t\treturn !hiddenButtons?.includes(format);\n\t}\n\n\treturn (\n\t\t<FieldTemplate\n\t\t\tname={name}\n\t\t\tlabel={label}\n\t\t\tshowAsterisk={showAsterisk}\n\t\t\tclassName={wrapperClassName}\n\t\t\terrorMessage={errorMessage}\n\t\t\tunShowFieldTemplate={unShowFieldTemplate}\n\t\t\torientation={orientation}\n\t\t>\n\t\t\t<Slate\n\t\t\t\teditor={editor}\n\t\t\t\tinitialValue={defaultNodes}\n\t\t\t\tonChange={handleChange}\n\t\t\t\tonValueChange={handleChange}\n\t\t\t>\n\t\t\t\t<div className={className}>\n\t\t\t\t\t<Toolbar>\n\t\t\t\t\t\t{buttonIsNotHidden(\"headingOne\") && (\n\t\t\t\t\t\t\t<BlockButton format=\"headingOne\" icon={Heading1} />\n\t\t\t\t\t\t)}\n\n\t\t\t\t\t\t{buttonIsNotHidden(\"headingTwo\") && (\n\t\t\t\t\t\t\t<BlockButton format=\"headingTwo\" icon={Heading2} />\n\t\t\t\t\t\t)}\n\n\t\t\t\t\t\t{buttonIsNotHidden(\"blockQuote\") && (\n\t\t\t\t\t\t\t<BlockButton format=\"blockQuote\" icon={Quote} />\n\t\t\t\t\t\t)}\n\n\t\t\t\t\t\t{buttonIsNotHidden(\"bold\") && (\n\t\t\t\t\t\t\t<MarkButton format=\"bold\" icon={Bold} />\n\t\t\t\t\t\t)}\n\n\t\t\t\t\t\t{buttonIsNotHidden(\"italic\") && (\n\t\t\t\t\t\t\t<MarkButton format=\"italic\" icon={Italic} />\n\t\t\t\t\t\t)}\n\n\t\t\t\t\t\t{buttonIsNotHidden(\"underline\") && (\n\t\t\t\t\t\t\t<MarkButton format=\"underline\" icon={Underline} />\n\t\t\t\t\t\t)}\n\n\t\t\t\t\t\t{buttonIsNotHidden(\"code\") && (\n\t\t\t\t\t\t\t<MarkButton format=\"code\" icon={Code} />\n\t\t\t\t\t\t)}\n\n\t\t\t\t\t\t{buttonIsNotHidden(\"left\") && (\n\t\t\t\t\t\t\t<BlockButton format=\"left\" icon={AlignLeft} />\n\t\t\t\t\t\t)}\n\n\t\t\t\t\t\t{buttonIsNotHidden(\"right\") && (\n\t\t\t\t\t\t\t<BlockButton format=\"right\" icon={AlignRight} />\n\t\t\t\t\t\t)}\n\n\t\t\t\t\t\t{buttonIsNotHidden(\"center\") && (\n\t\t\t\t\t\t\t<BlockButton format=\"center\" icon={AlignCenter} />\n\t\t\t\t\t\t)}\n\n\t\t\t\t\t\t{buttonIsNotHidden(\"justify\") && (\n\t\t\t\t\t\t\t<BlockButton format=\"justify\" icon={AlignJustify} />\n\t\t\t\t\t\t)}\n\n\t\t\t\t\t\t{imageConfig && buttonIsNotHidden(\"image\") && (\n\t\t\t\t\t\t\t<InsertImage {...imageConfig} />\n\t\t\t\t\t\t)}\n\n\t\t\t\t\t\t{buttonIsNotHidden(\"video\") && <InsertVideo {...videoConfig} />}\n\n\t\t\t\t\t\t{buttonIsNotHidden(\"link\") && <InsertLink {...linkConfig} />}\n\t\t\t\t\t</Toolbar>\n\n\t\t\t\t\t<Editable\n\t\t\t\t\t\tclassName=\"editorContainer\"\n\t\t\t\t\t\trenderElement={renderElement}\n\t\t\t\t\t\trenderLeaf={renderLeaf}\n\t\t\t\t\t\tspellCheck\n\t\t\t\t\t\tref={ref}\n\t\t\t\t\t\tid={inputId}\n\t\t\t\t\t\tonFocus={() => setOnFocus(true)}\n\t\t\t\t\t\tonBlur={() => setOnFocus(false)}\n\t\t\t\t\t\tonKeyDown={(event) => {\n\t\t\t\t\t\t\tfor (const hotkey in hotKeys) {\n\t\t\t\t\t\t\t\t// biome-ignore lint/suspicious/noExplicitAny: intentional\n\t\t\t\t\t\t\t\tif (isHotkey(hotkey, event as any)) {\n\t\t\t\t\t\t\t\t\tevent.preventDefault();\n\t\t\t\t\t\t\t\t\tconst mark = hotKeys[hotkey as keyof typeof hotKeys];\n\t\t\t\t\t\t\t\t\ttoggleMark(editor, mark);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}}\n\t\t\t\t\t/>\n\n\t\t\t\t\t{restatesCharacters < 0 && (\n\t\t\t\t\t\t<div className=\"restatesCharacters\">{restatesCharacters}</div>\n\t\t\t\t\t)}\n\t\t\t\t</div>\n\n\t\t\t\t<input\n\t\t\t\t\ttype=\"hidden\"\n\t\t\t\t\tname={name}\n\t\t\t\t\tvalue={inputValue.slice(0, maxLimit)}\n\t\t\t\t/>\n\n\t\t\t\t<input type=\"hidden\" name={`${name}Count`} value={charactersCount} />\n\t\t\t</Slate>\n\t\t</FieldTemplate>\n\t);\n}\n\nexport { RichText };\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../../../../src/components/richText/index.tsx"],"sourcesContent":["import { isHotkey } from \"is-hotkey\";\nimport {\n\tAlignCenter,\n\tAlignJustify,\n\tAlignLeft,\n\tAlignRight,\n\tBold,\n\tCode,\n\tHeading1,\n\tHeading2,\n\tItalic,\n\tQuote,\n\tUnderline,\n} from \"lucide-react\";\nimport { useCallback, useId, useMemo, useRef, useState } from \"react\";\nimport { createEditor, type Descendant } from \"slate\";\nimport { withHistory } from \"slate-history\";\nimport { Editable, Slate, withReact } from \"slate-react\";\nimport { useForm } from \"../../hooks/useForm\";\nimport { clearLinkMarkAtBoundary } from \"../../services/clearLinkMarkAtBoundary\";\nimport { extractTextFromNode } from \"../../services/extractTextFromNode\";\nimport { FieldTemplate } from \"../../services/fieldTemplate\";\nimport { toggleMark } from \"../../services/toggleMark\";\nimport { hotKeys, initialValue } from \"../../templates/richTextTemplates\";\nimport type {\n\tRichTextHiddenButtonKey,\n\tRichTextProps,\n} from \"../../types/richTextTypes\";\nimport { BlockButton } from \"./blockButton\";\nimport { Element } from \"./element\";\nimport { InsertImage } from \"./insertImage\";\nimport { InsertLink } from \"./insertLink\";\nimport { InsertVideo } from \"./insertVideo\";\nimport { Leaf } from \"./leaf\";\nimport { MarkButton } from \"./markButton\";\nimport { Toolbar } from \"./toolbar\";\nimport \"./styles.css\";\n\n/**\n * RichText, WYSIWYG rich-text editor built on Slate.js with a configurable toolbar.\n *\n * **Toolbar features:** bold, italic, underline, code, H1/H2, block quote, alignment (left/center/right/justify), image, video, and link insertion.\n * Pressing Space or Enter right after a link automatically stops new text from continuing to be part of that link.\n *\n * Editor content is stored as a Slate JSON string in a hidden `<input>` for form submission.\n * Integrates with `useForm` to display validation errors by field name.\n *\n * @param props.name - Field name for form submission. Required.\n * @param props.label - Label text displayed above the editor.\n * @param props.hiddenButtons - Toolbar button keys to hide (e.g. `[\"image\", \"code\"]`).\n * @param props.imageConfig - Enables image insertion; contains the upload endpoint and modal labels.\n * @param props.videoConfig - Customizes the video insertion modal labels.\n * @param props.linkConfig - Customizes the link insertion modal labels.\n * @param props.defaultValue - Initial editor content as a Slate JSON string. Default: \"[]\"\n * @param props.maxLimit - Maximum character count. Default: 10000\n * @param props.enforceCharacterLimit - Prevents typing past `maxLimit`. Default: false\n * @param props.onChangeCharactersCount - Callback fired on every keystroke, receives the current character count.\n * @param props.onChange - Callback fired when editor content changes, receives the Slate `Descendant[]`.\n * @param props.baseErrorMessage - Custom error message (overrides `useForm` context error).\n * @param props.isError - Forces the error visual state.\n * @param props.id - Custom id for the editable area element.\n * @param props.showAsterisk - Appends `*` to the label.\n * @param props.orientation - Layout direction. Default: \"horizontal\"\n * @param props.unShowFieldTemplate - Skips wrapper, label, and error rendering. Default: false\n *\n * @returns RichText JSX element wrapped in `FieldTemplate`.\n *\n * @example\n * ```tsx\n * // Basic\n * <RichText name=\"content\" />\n *\n * // With character limit and hidden toolbar buttons\n * <RichText\n * name=\"description\"\n * label=\"Description\"\n * maxLimit={500}\n * enforceCharacterLimit\n * hiddenButtons={[\"image\", \"video\", \"code\"]}\n * onChangeCharactersCount={(n) => setCharCount(n)}\n * />\n *\n * // With image upload support\n * <RichText\n * name=\"article\"\n * label=\"Article Body\"\n * imageConfig={{ action: \"/api/upload\" }}\n * />\n *\n * // With custom link insertion modal labels\n * <RichText\n * name=\"article\"\n * label=\"Article Body\"\n * linkConfig={{ modalTitle: \"Add a link\" }}\n * />\n * ```\n */\n\nfunction RichText(props: RichTextProps) {\n\tconst {\n\t\tname,\n\t\thiddenButtons,\n\t\timageConfig,\n\t\tvideoConfig,\n\t\tlinkConfig,\n\t\tclassName: wrapperClassName = \"\",\n\t\tdefaultValue = \"[]\",\n\t\tenforceCharacterLimit = false,\n\t\tonChangeCharactersCount,\n\t\tbaseErrorMessage,\n\t\tmaxLimit = 10000,\n\t\tonChange,\n\t\tisError: baseIsError,\n\t\tlabel,\n\t\tshowAsterisk,\n\t\tid,\n\t\torientation = \"vertical\",\n\t\tunShowFieldTemplate = false,\n\t} = props;\n\n\tconst editor = useMemo(() => withHistory(withReact(createEditor())), []);\n\n\tconst { fieldErrors } = useForm();\n\n\tconst defaultNodes = useMemo((): Descendant[] => {\n\t\ttry {\n\t\t\tconst parsedNodes = JSON.parse(defaultValue);\n\t\t\tif (!Array.isArray(parsedNodes) || parsedNodes.length === 0) {\n\t\t\t\treturn structuredClone(initialValue);\n\t\t\t}\n\n\t\t\tconst isValidNodes = parsedNodes.every(\n\t\t\t\t(node) =>\n\t\t\t\t\ttypeof node === \"object\" &&\n\t\t\t\t\tnode !== null &&\n\t\t\t\t\t\"type\" in node &&\n\t\t\t\t\t\"children\" in node,\n\t\t\t);\n\n\t\t\treturn isValidNodes ? parsedNodes : structuredClone(initialValue);\n\t\t} catch (_error) {\n\t\t\treturn structuredClone(initialValue);\n\t\t}\n\t}, [defaultValue]);\n\n\tconst textFromNodes = extractTextFromNode(defaultNodes);\n\n\tconst [charactersCount, setCharactersCount] = useState(textFromNodes.length);\n\tconst [inputValue, setInputValue] = useState(\n\t\tJSON.stringify(defaultNodes) || \"[]\",\n\t);\n\n\tconst [onFocus, setOnFocus] = useState(false);\n\n\tconst ref = useRef<HTMLInputElement>(null);\n\tconst generatedId = useId();\n\tconst inputId = id || generatedId;\n\n\tconst errorMessage = baseErrorMessage || fieldErrors?.[name];\n\tconst isError = baseIsError || !!errorMessage;\n\n\tconst renderLeaf = useCallback(Leaf, []);\n\tconst renderElement = useCallback(Element, []);\n\n\tfunction handleChange(value: Descendant[]) {\n\t\tconst text = extractTextFromNode(value);\n\n\t\tsetCharactersCount(text.length);\n\t\tonChangeCharactersCount?.(text.length);\n\n\t\tif (enforceCharacterLimit && text.length >= maxLimit) {\n\t\t\treturn;\n\t\t}\n\n\t\tsetInputValue(JSON.stringify(value));\n\t\tonChange?.(value);\n\t}\n\n\tconst focusClass = onFocus ? \"focusTrue\" : \"focusFalse\";\n\tconst errorClass = isError\n\t\t? \"errorTrue\"\n\t\t: maxLimit < charactersCount\n\t\t\t? \"errorTrue\"\n\t\t\t: \"errorFalse\";\n\n\tconst className = `arkynRichText ${errorClass} ${focusClass}`;\n\n\tconst restatesCharacters = maxLimit - charactersCount;\n\n\tfunction buttonIsNotHidden(format: RichTextHiddenButtonKey) {\n\t\treturn !hiddenButtons?.includes(format);\n\t}\n\n\treturn (\n\t\t<FieldTemplate\n\t\t\tname={name}\n\t\t\tlabel={label}\n\t\t\tshowAsterisk={showAsterisk}\n\t\t\tclassName={wrapperClassName}\n\t\t\terrorMessage={errorMessage}\n\t\t\tunShowFieldTemplate={unShowFieldTemplate}\n\t\t\torientation={orientation}\n\t\t>\n\t\t\t<Slate\n\t\t\t\teditor={editor}\n\t\t\t\tinitialValue={defaultNodes}\n\t\t\t\tonChange={handleChange}\n\t\t\t\tonValueChange={handleChange}\n\t\t\t>\n\t\t\t\t<div className={className}>\n\t\t\t\t\t<Toolbar>\n\t\t\t\t\t\t{buttonIsNotHidden(\"headingOne\") && (\n\t\t\t\t\t\t\t<BlockButton format=\"headingOne\" icon={Heading1} />\n\t\t\t\t\t\t)}\n\n\t\t\t\t\t\t{buttonIsNotHidden(\"headingTwo\") && (\n\t\t\t\t\t\t\t<BlockButton format=\"headingTwo\" icon={Heading2} />\n\t\t\t\t\t\t)}\n\n\t\t\t\t\t\t{buttonIsNotHidden(\"blockQuote\") && (\n\t\t\t\t\t\t\t<BlockButton format=\"blockQuote\" icon={Quote} />\n\t\t\t\t\t\t)}\n\n\t\t\t\t\t\t{buttonIsNotHidden(\"bold\") && (\n\t\t\t\t\t\t\t<MarkButton format=\"bold\" icon={Bold} />\n\t\t\t\t\t\t)}\n\n\t\t\t\t\t\t{buttonIsNotHidden(\"italic\") && (\n\t\t\t\t\t\t\t<MarkButton format=\"italic\" icon={Italic} />\n\t\t\t\t\t\t)}\n\n\t\t\t\t\t\t{buttonIsNotHidden(\"underline\") && (\n\t\t\t\t\t\t\t<MarkButton format=\"underline\" icon={Underline} />\n\t\t\t\t\t\t)}\n\n\t\t\t\t\t\t{buttonIsNotHidden(\"code\") && (\n\t\t\t\t\t\t\t<MarkButton format=\"code\" icon={Code} />\n\t\t\t\t\t\t)}\n\n\t\t\t\t\t\t{buttonIsNotHidden(\"left\") && (\n\t\t\t\t\t\t\t<BlockButton format=\"left\" icon={AlignLeft} />\n\t\t\t\t\t\t)}\n\n\t\t\t\t\t\t{buttonIsNotHidden(\"right\") && (\n\t\t\t\t\t\t\t<BlockButton format=\"right\" icon={AlignRight} />\n\t\t\t\t\t\t)}\n\n\t\t\t\t\t\t{buttonIsNotHidden(\"center\") && (\n\t\t\t\t\t\t\t<BlockButton format=\"center\" icon={AlignCenter} />\n\t\t\t\t\t\t)}\n\n\t\t\t\t\t\t{buttonIsNotHidden(\"justify\") && (\n\t\t\t\t\t\t\t<BlockButton format=\"justify\" icon={AlignJustify} />\n\t\t\t\t\t\t)}\n\n\t\t\t\t\t\t{imageConfig && buttonIsNotHidden(\"image\") && (\n\t\t\t\t\t\t\t<InsertImage {...imageConfig} />\n\t\t\t\t\t\t)}\n\n\t\t\t\t\t\t{buttonIsNotHidden(\"video\") && <InsertVideo {...videoConfig} />}\n\n\t\t\t\t\t\t{buttonIsNotHidden(\"link\") && <InsertLink {...linkConfig} />}\n\t\t\t\t\t</Toolbar>\n\n\t\t\t\t\t<Editable\n\t\t\t\t\t\tclassName=\"editorContainer\"\n\t\t\t\t\t\trenderElement={renderElement}\n\t\t\t\t\t\trenderLeaf={renderLeaf}\n\t\t\t\t\t\tspellCheck\n\t\t\t\t\t\tref={ref}\n\t\t\t\t\t\tid={inputId}\n\t\t\t\t\t\tonFocus={() => setOnFocus(true)}\n\t\t\t\t\t\tonBlur={() => setOnFocus(false)}\n\t\t\t\t\t\tonKeyDown={(event) => {\n\t\t\t\t\t\t\tif (event.key === \" \" || event.key === \"Enter\") {\n\t\t\t\t\t\t\t\tclearLinkMarkAtBoundary(editor);\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tfor (const hotkey in hotKeys) {\n\t\t\t\t\t\t\t\t// biome-ignore lint/suspicious/noExplicitAny: intentional\n\t\t\t\t\t\t\t\tif (isHotkey(hotkey, event as any)) {\n\t\t\t\t\t\t\t\t\tevent.preventDefault();\n\t\t\t\t\t\t\t\t\tconst mark = hotKeys[hotkey as keyof typeof hotKeys];\n\t\t\t\t\t\t\t\t\ttoggleMark(editor, mark);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}}\n\t\t\t\t\t/>\n\n\t\t\t\t\t{restatesCharacters < 0 && (\n\t\t\t\t\t\t<div className=\"restatesCharacters\">{restatesCharacters}</div>\n\t\t\t\t\t)}\n\t\t\t\t</div>\n\n\t\t\t\t<input\n\t\t\t\t\ttype=\"hidden\"\n\t\t\t\t\tname={name}\n\t\t\t\t\tvalue={inputValue.slice(0, maxLimit)}\n\t\t\t\t/>\n\n\t\t\t\t<input type=\"hidden\" name={`${name}Count`} value={charactersCount} />\n\t\t\t</Slate>\n\t\t</FieldTemplate>\n\t);\n}\n\nexport { RichText };\n"],"mappings":"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"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { Editor as e, Range as t } from "slate";
|
|
2
|
+
//#region src/services/clearLinkMarkAtBoundary.ts
|
|
3
|
+
function n(n) {
|
|
4
|
+
let { selection: r } = n;
|
|
5
|
+
if (!r || !t.isCollapsed(r)) return;
|
|
6
|
+
let [i, a] = e.leaf(n, r.anchor);
|
|
7
|
+
i.link && e.isEnd(n, r.anchor, a) && (e.removeMark(n, "link"), e.removeMark(n, "href"));
|
|
8
|
+
}
|
|
9
|
+
//#endregion
|
|
10
|
+
export { n as clearLinkMarkAtBoundary };
|
|
11
|
+
|
|
12
|
+
//# sourceMappingURL=clearLinkMarkAtBoundary.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"clearLinkMarkAtBoundary.js","names":[],"sources":["../../../src/services/clearLinkMarkAtBoundary.ts"],"sourcesContent":["import { Editor, Range } from \"slate\";\n\nfunction clearLinkMarkAtBoundary(editor: Editor) {\n\tconst { selection } = editor;\n\tif (!selection || !Range.isCollapsed(selection)) return;\n\n\tconst [node, path] = Editor.leaf(editor, selection.anchor);\n\tif (!node.link) return;\n\tif (!Editor.isEnd(editor, selection.anchor, path)) return;\n\n\tEditor.removeMark(editor, \"link\");\n\tEditor.removeMark(editor, \"href\");\n}\n\nexport { clearLinkMarkAtBoundary };\n"],"mappings":";;AAEA,SAAS,EAAwB,GAAgB;CAChD,IAAM,EAAE,iBAAc;CACtB,IAAI,CAAC,KAAa,CAAC,EAAM,YAAY,CAAS,GAAG;CAEjD,IAAM,CAAC,GAAM,KAAQ,EAAO,KAAK,GAAQ,EAAU,MAAM;CACpD,EAAK,QACL,EAAO,MAAM,GAAQ,EAAU,QAAQ,CAAI,MAEhD,EAAO,WAAW,GAAQ,MAAM,GAChC,EAAO,WAAW,GAAQ,MAAM;AACjC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"clearLinkMarkAtBoundary.d.ts","sourceRoot":"","sources":["../../src/services/clearLinkMarkAtBoundary.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAS,MAAM,OAAO,CAAC;AAEtC,iBAAS,uBAAuB,CAAC,MAAM,EAAE,MAAM,QAU9C;AAED,OAAO,EAAE,uBAAuB,EAAE,CAAC"}
|