@arkyn/components 1.3.116 → 1.3.118

Sign up to get free protection for your applications and to get access to all the features.
@@ -6,9 +6,10 @@ type RichTextProps = {
6
6
  enforceCharacterLimit?: boolean;
7
7
  defaultValue?: string;
8
8
  isError?: boolean;
9
+ onChangeCharactersCount: (e: number) => void;
9
10
  onChange?: (value: Descendant[]) => void;
10
11
  onValueChange?: (value: string) => void;
11
12
  };
12
- declare function RichText({ name, defaultValue, enforceCharacterLimit, maxLimit, onValueChange, onChange, isError: baseIsError, }: RichTextProps): import("react/jsx-runtime").JSX.Element;
13
+ declare function RichText({ name, defaultValue, enforceCharacterLimit, onChangeCharactersCount, maxLimit, onValueChange, onChange, isError: baseIsError, }: RichTextProps): import("react/jsx-runtime").JSX.Element;
13
14
  export { RichText };
14
15
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/RichText/index.tsx"],"names":[],"mappings":"AAeA,OAAO,EAAgB,UAAU,EAAoB,MAAM,OAAO,CAAC;AAanE,OAAO,cAAc,CAAC;AAGtB,KAAK,aAAa,GAAG;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,qBAAqB,CAAC,EAAE,OAAO,CAAC;IAChC,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,UAAU,EAAE,KAAK,IAAI,CAAC;IACzC,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;CACzC,CAAC;AAEF,iBAAS,QAAQ,CAAC,EAChB,IAAI,EACJ,YAAY,EACZ,qBAA6B,EAC7B,QAAe,EACf,aAAa,EACb,QAAQ,EACR,OAAO,EAAE,WAAW,GACrB,EAAE,aAAa,2CA8Gf;AAED,OAAO,EAAE,QAAQ,EAAE,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/RichText/index.tsx"],"names":[],"mappings":"AAeA,OAAO,EAAgB,UAAU,EAAoB,MAAM,OAAO,CAAC;AAanE,OAAO,cAAc,CAAC;AAGtB,KAAK,aAAa,GAAG;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,qBAAqB,CAAC,EAAE,OAAO,CAAC;IAChC,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,uBAAuB,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,IAAI,CAAC;IAC7C,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,UAAU,EAAE,KAAK,IAAI,CAAC;IACzC,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;CACzC,CAAC;AAEF,iBAAS,QAAQ,CAAC,EAChB,IAAI,EACJ,YAAY,EACZ,qBAA6B,EAC7B,uBAAuB,EACvB,QAAe,EACf,aAAa,EACb,QAAQ,EACR,OAAO,EAAE,WAAW,GACrB,EAAE,aAAa,2CAqHf;AAED,OAAO,EAAE,QAAQ,EAAE,CAAC"}
@@ -1,4 +1,5 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import isHotkey from "is-hotkey";
2
3
  import { AlignCenter, AlignJustify, AlignLeft, AlignRight, Bold, Code, Heading1, Heading2, Italic, Quote, Underline, } from "lucide-react";
3
4
  import { useCallback, useMemo, useRef, useState } from "react";
4
5
  import { createEditor, Transforms, Node } from "slate";
@@ -9,12 +10,18 @@ import { Element } from "./components/Element";
9
10
  import { Leaf } from "./components/Leaf";
10
11
  import { MarkButton } from "./components/MarkButton";
11
12
  import { Toolbar } from "./components/Toolbar";
13
+ import { toggleMark } from "./functions/toggleMark";
14
+ import { HOTKEYS } from "./template/HOTKEYS";
12
15
  import { INITIAL_VALUE } from "./template/INITIAL_VALUE";
13
16
  import "./styles.css";
14
17
  import { useFormController } from "../Form/FormController";
15
- function RichText({ name, defaultValue, enforceCharacterLimit = false, maxLimit = 2000, onValueChange, onChange, isError: baseIsError, }) {
16
- const [charactersCount, setCharactersCount] = useState(0);
17
- const [editorValue, setEditorValue] = useState(defaultValue ? JSON.parse(defaultValue) : INITIAL_VALUE);
18
+ function RichText({ name, defaultValue, enforceCharacterLimit = false, onChangeCharactersCount, maxLimit = 2000, onValueChange, onChange, isError: baseIsError, }) {
19
+ function extractText(nodes) {
20
+ return nodes.map((n) => Node.string(n)).join("");
21
+ }
22
+ const defaultNodes = defaultValue ? JSON.parse(defaultValue) : INITIAL_VALUE;
23
+ const [charactersCount, setCharactersCount] = useState(extractText(defaultNodes).length);
24
+ const [editorValue, setEditorValue] = useState(defaultNodes);
18
25
  const [onFocus, setOnFocus] = useState(false);
19
26
  const { id, inputRef, error } = useFormController();
20
27
  const baseRef = useRef(null);
@@ -23,12 +30,10 @@ function RichText({ name, defaultValue, enforceCharacterLimit = false, maxLimit
23
30
  const editor = useMemo(() => withHistory(withReact(createEditor())), []);
24
31
  const renderLeaf = useCallback(Leaf, []);
25
32
  const renderElement = useCallback(Element, []);
26
- function extractText(nodes) {
27
- return nodes.map((n) => Node.string(n)).join("");
28
- }
29
33
  function handleChange(value) {
30
34
  const text = extractText(value);
31
35
  setCharactersCount(text.length);
36
+ onChangeCharactersCount && onChangeCharactersCount(text.length);
32
37
  if (enforceCharacterLimit && text.length >= maxLimit) {
33
38
  return;
34
39
  }
@@ -43,11 +48,19 @@ function RichText({ name, defaultValue, enforceCharacterLimit = false, maxLimit
43
48
  const focusClass = onFocus ? "focusTrue" : "focusFalse";
44
49
  const errorClass = isError
45
50
  ? "errorTrue"
46
- : maxLimit === charactersCount
51
+ : maxLimit < charactersCount
47
52
  ? "errorTrue"
48
53
  : "errorFalse";
49
54
  const className = `arkynRichText ${errorClass} ${focusClass}`;
50
55
  const restatesCharacters = maxLimit - charactersCount;
51
- return (_jsxs(Slate, { editor: editor, initialValue: defaultValue ? JSON.parse(defaultValue) : INITIAL_VALUE, onChange: handleChange, onValueChange: handleChange, children: [_jsxs("div", { className: className, children: [_jsxs(Toolbar, { children: [_jsx(BlockButton, { format: "headingOne", icon: Heading1 }), _jsx(BlockButton, { format: "headingTwo", icon: Heading2 }), _jsx(BlockButton, { format: "blockQuote", icon: Quote }), _jsx(MarkButton, { format: "bold", icon: Bold }), _jsx(MarkButton, { format: "italic", icon: Italic }), _jsx(MarkButton, { format: "underline", icon: Underline }), _jsx(MarkButton, { format: "code", icon: Code }), _jsx(BlockButton, { format: "left", icon: AlignLeft }), _jsx(BlockButton, { format: "right", icon: AlignRight }), _jsx(BlockButton, { format: "center", icon: AlignCenter }), _jsx(BlockButton, { format: "justify", icon: AlignJustify })] }), _jsx(Editable, { className: "editorContainer", renderElement: renderElement, renderLeaf: renderLeaf, spellCheck: true, id: id, onFocus: () => setOnFocus(true), onBlur: () => setOnFocus(false) }), restatesCharacters < 0 && (_jsx("div", { className: "restatesCharacters", children: restatesCharacters }))] }), _jsx("input", { ref: ref, type: "hidden", name: name, value: JSON.stringify(editorValue) })] }));
56
+ return (_jsxs(Slate, { editor: editor, initialValue: defaultValue ? JSON.parse(defaultValue) : INITIAL_VALUE, onChange: handleChange, onValueChange: handleChange, children: [_jsxs("div", { className: className, children: [_jsxs(Toolbar, { children: [_jsx(BlockButton, { format: "headingOne", icon: Heading1 }), _jsx(BlockButton, { format: "headingTwo", icon: Heading2 }), _jsx(BlockButton, { format: "blockQuote", icon: Quote }), _jsx(MarkButton, { format: "bold", icon: Bold }), _jsx(MarkButton, { format: "italic", icon: Italic }), _jsx(MarkButton, { format: "underline", icon: Underline }), _jsx(MarkButton, { format: "code", icon: Code }), _jsx(BlockButton, { format: "left", icon: AlignLeft }), _jsx(BlockButton, { format: "right", icon: AlignRight }), _jsx(BlockButton, { format: "center", icon: AlignCenter }), _jsx(BlockButton, { format: "justify", icon: AlignJustify })] }), _jsx(Editable, { className: "editorContainer", renderElement: renderElement, renderLeaf: renderLeaf, spellCheck: true, id: id, onFocus: () => setOnFocus(true), onBlur: () => setOnFocus(false), onKeyDown: (event) => {
57
+ for (const hotkey in HOTKEYS) {
58
+ if (isHotkey(hotkey, event)) {
59
+ event.preventDefault();
60
+ const mark = HOTKEYS[hotkey];
61
+ toggleMark(editor, mark);
62
+ }
63
+ }
64
+ } }), restatesCharacters < 0 && (_jsx("div", { className: "restatesCharacters", children: restatesCharacters }))] }), _jsx("input", { ref: ref, type: "hidden", name: name, value: JSON.stringify(editorValue) }), _jsx("input", { type: "hidden", name: `${name}Count`, value: charactersCount })] }));
52
65
  }
53
66
  export { RichText };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@arkyn/components",
3
- "version": "1.3.116",
3
+ "version": "1.3.118",
4
4
  "main": "./dist/bundle.js",
5
5
  "types": "./dist/index.d.ts",
6
6
  "author": "Lucas Gonçalves",
@@ -35,6 +35,7 @@ type RichTextProps = {
35
35
  enforceCharacterLimit?: boolean;
36
36
  defaultValue?: string;
37
37
  isError?: boolean;
38
+ onChangeCharactersCount: (e: number) => void;
38
39
  onChange?: (value: Descendant[]) => void;
39
40
  onValueChange?: (value: string) => void;
40
41
  };
@@ -43,15 +44,23 @@ function RichText({
43
44
  name,
44
45
  defaultValue,
45
46
  enforceCharacterLimit = false,
47
+ onChangeCharactersCount,
46
48
  maxLimit = 2000,
47
49
  onValueChange,
48
50
  onChange,
49
51
  isError: baseIsError,
50
52
  }: RichTextProps) {
51
- const [charactersCount, setCharactersCount] = useState(0);
52
- const [editorValue, setEditorValue] = useState<Descendant[]>(
53
- defaultValue ? JSON.parse(defaultValue) : INITIAL_VALUE
53
+ function extractText(nodes: Descendant[]) {
54
+ return nodes.map((n) => Node.string(n)).join("");
55
+ }
56
+
57
+ const defaultNodes = defaultValue ? JSON.parse(defaultValue) : INITIAL_VALUE;
58
+
59
+ const [charactersCount, setCharactersCount] = useState(
60
+ extractText(defaultNodes).length
54
61
  );
62
+
63
+ const [editorValue, setEditorValue] = useState<Descendant[]>(defaultNodes);
55
64
  const [onFocus, setOnFocus] = useState(false);
56
65
 
57
66
  const { id, inputRef, error } = useFormController();
@@ -66,14 +75,12 @@ function RichText({
66
75
  const renderLeaf = useCallback(Leaf, []);
67
76
  const renderElement = useCallback(Element, []);
68
77
 
69
- function extractText(nodes: Descendant[]) {
70
- return nodes.map((n) => Node.string(n)).join("");
71
- }
72
-
73
78
  function handleChange(value: Descendant[]) {
74
79
  const text = extractText(value);
75
80
  setCharactersCount(text.length);
76
81
 
82
+ onChangeCharactersCount && onChangeCharactersCount(text.length);
83
+
77
84
  if (enforceCharacterLimit && text.length >= maxLimit) {
78
85
  return;
79
86
  } else {
@@ -90,7 +97,7 @@ function RichText({
90
97
  const focusClass = onFocus ? "focusTrue" : "focusFalse";
91
98
  const errorClass = isError
92
99
  ? "errorTrue"
93
- : maxLimit === charactersCount
100
+ : maxLimit < charactersCount
94
101
  ? "errorTrue"
95
102
  : "errorFalse";
96
103
 
@@ -133,15 +140,15 @@ function RichText({
133
140
  id={id}
134
141
  onFocus={() => setOnFocus(true)}
135
142
  onBlur={() => setOnFocus(false)}
136
- // onKeyDown={(event) => {
137
- // for (const hotkey in HOTKEYS) {
138
- // if (isHotkey(hotkey, event as any)) {
139
- // event.preventDefault();
140
- // const mark = HOTKEYS[hotkey as keyof typeof HOTKEYS];
141
- // toggleMark(editor, mark);
142
- // }
143
- // }
144
- // }}
143
+ onKeyDown={(event) => {
144
+ for (const hotkey in HOTKEYS) {
145
+ if (isHotkey(hotkey, event as any)) {
146
+ event.preventDefault();
147
+ const mark = HOTKEYS[hotkey as keyof typeof HOTKEYS];
148
+ toggleMark(editor, mark);
149
+ }
150
+ }
151
+ }}
145
152
  />
146
153
 
147
154
  {restatesCharacters < 0 && (
@@ -155,6 +162,8 @@ function RichText({
155
162
  name={name}
156
163
  value={JSON.stringify(editorValue)}
157
164
  />
165
+
166
+ <input type="hidden" name={`${name}Count`} value={charactersCount} />
158
167
  </Slate>
159
168
  );
160
169
  }