react-native-richify 1.0.0

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.
Files changed (172) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +231 -0
  3. package/lib/commonjs/components/OverlayText.d.js +6 -0
  4. package/lib/commonjs/components/OverlayText.d.js.map +1 -0
  5. package/lib/commonjs/components/OverlayText.js +45 -0
  6. package/lib/commonjs/components/OverlayText.js.map +1 -0
  7. package/lib/commonjs/components/RichTextInput.d.js +6 -0
  8. package/lib/commonjs/components/RichTextInput.d.js.map +1 -0
  9. package/lib/commonjs/components/RichTextInput.js +160 -0
  10. package/lib/commonjs/components/RichTextInput.js.map +1 -0
  11. package/lib/commonjs/components/Toolbar.d.js +6 -0
  12. package/lib/commonjs/components/Toolbar.d.js.map +1 -0
  13. package/lib/commonjs/components/Toolbar.js +99 -0
  14. package/lib/commonjs/components/Toolbar.js.map +1 -0
  15. package/lib/commonjs/components/ToolbarButton.d.js +6 -0
  16. package/lib/commonjs/components/ToolbarButton.d.js.map +1 -0
  17. package/lib/commonjs/components/ToolbarButton.js +63 -0
  18. package/lib/commonjs/components/ToolbarButton.js.map +1 -0
  19. package/lib/commonjs/constants/defaultStyles.d.js +6 -0
  20. package/lib/commonjs/constants/defaultStyles.d.js.map +1 -0
  21. package/lib/commonjs/constants/defaultStyles.js +172 -0
  22. package/lib/commonjs/constants/defaultStyles.js.map +1 -0
  23. package/lib/commonjs/context/RichTextContext.d.js +6 -0
  24. package/lib/commonjs/context/RichTextContext.d.js.map +1 -0
  25. package/lib/commonjs/context/RichTextContext.js +61 -0
  26. package/lib/commonjs/context/RichTextContext.js.map +1 -0
  27. package/lib/commonjs/hooks/useFormatting.d.js +6 -0
  28. package/lib/commonjs/hooks/useFormatting.d.js.map +1 -0
  29. package/lib/commonjs/hooks/useFormatting.js +82 -0
  30. package/lib/commonjs/hooks/useFormatting.js.map +1 -0
  31. package/lib/commonjs/hooks/useRichText.d.js +6 -0
  32. package/lib/commonjs/hooks/useRichText.d.js.map +1 -0
  33. package/lib/commonjs/hooks/useRichText.js +136 -0
  34. package/lib/commonjs/hooks/useRichText.js.map +1 -0
  35. package/lib/commonjs/hooks/useSelection.d.js +6 -0
  36. package/lib/commonjs/hooks/useSelection.d.js.map +1 -0
  37. package/lib/commonjs/hooks/useSelection.js +39 -0
  38. package/lib/commonjs/hooks/useSelection.js.map +1 -0
  39. package/lib/commonjs/index.d.js +186 -0
  40. package/lib/commonjs/index.d.js.map +1 -0
  41. package/lib/commonjs/index.js +186 -0
  42. package/lib/commonjs/index.js.map +1 -0
  43. package/lib/commonjs/package.json +1 -0
  44. package/lib/commonjs/types/index.d.js +6 -0
  45. package/lib/commonjs/types/index.d.js.map +1 -0
  46. package/lib/commonjs/types/index.js +6 -0
  47. package/lib/commonjs/types/index.js.map +1 -0
  48. package/lib/commonjs/utils/formatter.d.js +13 -0
  49. package/lib/commonjs/utils/formatter.d.js.map +1 -0
  50. package/lib/commonjs/utils/formatter.js +229 -0
  51. package/lib/commonjs/utils/formatter.js.map +1 -0
  52. package/lib/commonjs/utils/parser.d.js +6 -0
  53. package/lib/commonjs/utils/parser.d.js.map +1 -0
  54. package/lib/commonjs/utils/parser.js +221 -0
  55. package/lib/commonjs/utils/parser.js.map +1 -0
  56. package/lib/commonjs/utils/styleMapper.d.js +6 -0
  57. package/lib/commonjs/utils/styleMapper.d.js.map +1 -0
  58. package/lib/commonjs/utils/styleMapper.js +87 -0
  59. package/lib/commonjs/utils/styleMapper.js.map +1 -0
  60. package/lib/module/components/OverlayText.d.js +4 -0
  61. package/lib/module/components/OverlayText.d.js.map +1 -0
  62. package/lib/module/components/OverlayText.js +41 -0
  63. package/lib/module/components/OverlayText.js.map +1 -0
  64. package/lib/module/components/RichTextInput.d.js +4 -0
  65. package/lib/module/components/RichTextInput.d.js.map +1 -0
  66. package/lib/module/components/RichTextInput.js +155 -0
  67. package/lib/module/components/RichTextInput.js.map +1 -0
  68. package/lib/module/components/Toolbar.d.js +4 -0
  69. package/lib/module/components/Toolbar.d.js.map +1 -0
  70. package/lib/module/components/Toolbar.js +95 -0
  71. package/lib/module/components/Toolbar.js.map +1 -0
  72. package/lib/module/components/ToolbarButton.d.js +4 -0
  73. package/lib/module/components/ToolbarButton.d.js.map +1 -0
  74. package/lib/module/components/ToolbarButton.js +59 -0
  75. package/lib/module/components/ToolbarButton.js.map +1 -0
  76. package/lib/module/constants/defaultStyles.d.js +4 -0
  77. package/lib/module/constants/defaultStyles.d.js.map +1 -0
  78. package/lib/module/constants/defaultStyles.js +168 -0
  79. package/lib/module/constants/defaultStyles.js.map +1 -0
  80. package/lib/module/context/RichTextContext.d.js +4 -0
  81. package/lib/module/context/RichTextContext.d.js.map +1 -0
  82. package/lib/module/context/RichTextContext.js +55 -0
  83. package/lib/module/context/RichTextContext.js.map +1 -0
  84. package/lib/module/hooks/useFormatting.d.js +11 -0
  85. package/lib/module/hooks/useFormatting.d.js.map +1 -0
  86. package/lib/module/hooks/useFormatting.js +78 -0
  87. package/lib/module/hooks/useFormatting.js.map +1 -0
  88. package/lib/module/hooks/useRichText.d.js +4 -0
  89. package/lib/module/hooks/useRichText.d.js.map +1 -0
  90. package/lib/module/hooks/useRichText.js +132 -0
  91. package/lib/module/hooks/useRichText.js.map +1 -0
  92. package/lib/module/hooks/useSelection.d.js +4 -0
  93. package/lib/module/hooks/useSelection.d.js.map +1 -0
  94. package/lib/module/hooks/useSelection.js +35 -0
  95. package/lib/module/hooks/useSelection.js.map +1 -0
  96. package/lib/module/index.d.js +15 -0
  97. package/lib/module/index.d.js.map +1 -0
  98. package/lib/module/index.js +25 -0
  99. package/lib/module/index.js.map +1 -0
  100. package/lib/module/types/index.d.js +4 -0
  101. package/lib/module/types/index.d.js.map +1 -0
  102. package/lib/module/types/index.js +4 -0
  103. package/lib/module/types/index.js.map +1 -0
  104. package/lib/module/utils/formatter.d.js +30 -0
  105. package/lib/module/utils/formatter.d.js.map +1 -0
  106. package/lib/module/utils/formatter.js +217 -0
  107. package/lib/module/utils/formatter.js.map +1 -0
  108. package/lib/module/utils/parser.d.js +4 -0
  109. package/lib/module/utils/parser.d.js.map +1 -0
  110. package/lib/module/utils/parser.js +211 -0
  111. package/lib/module/utils/parser.js.map +1 -0
  112. package/lib/module/utils/styleMapper.d.js +4 -0
  113. package/lib/module/utils/styleMapper.d.js.map +1 -0
  114. package/lib/module/utils/styleMapper.js +82 -0
  115. package/lib/module/utils/styleMapper.js.map +1 -0
  116. package/lib/typescript/src/components/OverlayText.d.ts +11 -0
  117. package/lib/typescript/src/components/OverlayText.d.ts.map +1 -0
  118. package/lib/typescript/src/components/RichTextInput.d.ts +21 -0
  119. package/lib/typescript/src/components/RichTextInput.d.ts.map +1 -0
  120. package/lib/typescript/src/components/Toolbar.d.ts +13 -0
  121. package/lib/typescript/src/components/Toolbar.d.ts.map +1 -0
  122. package/lib/typescript/src/components/ToolbarButton.d.ts +8 -0
  123. package/lib/typescript/src/components/ToolbarButton.d.ts.map +1 -0
  124. package/lib/typescript/src/constants/defaultStyles.d.ts +46 -0
  125. package/lib/typescript/src/constants/defaultStyles.d.ts.map +1 -0
  126. package/lib/typescript/src/context/RichTextContext.d.ts +31 -0
  127. package/lib/typescript/src/context/RichTextContext.d.ts.map +1 -0
  128. package/lib/typescript/src/hooks/useFormatting.d.ts +26 -0
  129. package/lib/typescript/src/hooks/useFormatting.d.ts.map +1 -0
  130. package/lib/typescript/src/hooks/useRichText.d.ts +17 -0
  131. package/lib/typescript/src/hooks/useRichText.d.ts.map +1 -0
  132. package/lib/typescript/src/hooks/useSelection.d.ts +14 -0
  133. package/lib/typescript/src/hooks/useSelection.d.ts.map +1 -0
  134. package/lib/typescript/src/index.d.ts +16 -0
  135. package/lib/typescript/src/index.d.ts.map +1 -0
  136. package/lib/typescript/src/types/index.d.ts +245 -0
  137. package/lib/typescript/src/types/index.d.ts.map +1 -0
  138. package/lib/typescript/src/utils/formatter.d.ts +29 -0
  139. package/lib/typescript/src/utils/formatter.d.ts.map +1 -0
  140. package/lib/typescript/src/utils/parser.d.ts +46 -0
  141. package/lib/typescript/src/utils/parser.d.ts.map +1 -0
  142. package/lib/typescript/src/utils/styleMapper.d.ts +16 -0
  143. package/lib/typescript/src/utils/styleMapper.d.ts.map +1 -0
  144. package/package.json +83 -0
  145. package/src/components/OverlayText.d.ts +10 -0
  146. package/src/components/OverlayText.tsx +46 -0
  147. package/src/components/RichTextInput.d.ts +20 -0
  148. package/src/components/RichTextInput.tsx +174 -0
  149. package/src/components/Toolbar.d.ts +12 -0
  150. package/src/components/Toolbar.tsx +100 -0
  151. package/src/components/ToolbarButton.d.ts +7 -0
  152. package/src/components/ToolbarButton.tsx +65 -0
  153. package/src/constants/defaultStyles.d.ts +45 -0
  154. package/src/constants/defaultStyles.ts +144 -0
  155. package/src/context/RichTextContext.d.ts +30 -0
  156. package/src/context/RichTextContext.tsx +63 -0
  157. package/src/hooks/useFormatting.d.ts +25 -0
  158. package/src/hooks/useFormatting.ts +135 -0
  159. package/src/hooks/useRichText.d.ts +16 -0
  160. package/src/hooks/useRichText.ts +171 -0
  161. package/src/hooks/useSelection.d.ts +13 -0
  162. package/src/hooks/useSelection.ts +40 -0
  163. package/src/index.d.ts +15 -0
  164. package/src/index.ts +68 -0
  165. package/src/types/index.d.ts +244 -0
  166. package/src/types/index.ts +295 -0
  167. package/src/utils/formatter.d.ts +28 -0
  168. package/src/utils/formatter.ts +276 -0
  169. package/src/utils/parser.d.ts +45 -0
  170. package/src/utils/parser.ts +252 -0
  171. package/src/utils/styleMapper.d.ts +15 -0
  172. package/src/utils/styleMapper.ts +92 -0
@@ -0,0 +1,135 @@
1
+ import { useCallback } from 'react';
2
+ import type {
3
+ StyledSegment,
4
+ FormatType,
5
+ FormatStyle,
6
+ HeadingLevel,
7
+ SelectionRange,
8
+ } from '@/types';
9
+ import {
10
+ toggleFormatOnSelection,
11
+ setStyleOnSelection,
12
+ setHeadingOnLine,
13
+ isFormatActiveInSelection,
14
+ getSelectionStyle,
15
+ } from '@/utils/formatter';
16
+
17
+ interface UseFormattingOptions {
18
+ segments: StyledSegment[];
19
+ selection: SelectionRange;
20
+ activeStyles: FormatStyle;
21
+ onSegmentsChange: (segments: StyledSegment[]) => void;
22
+ onActiveStylesChange: (styles: FormatStyle) => void;
23
+ }
24
+
25
+ /**
26
+ * Hook that provides formatting commands for the rich text editor.
27
+ *
28
+ * Handles both selection-based formatting (when text is selected)
29
+ * and active-style updates (when no text is selected — affects next typed text).
30
+ */
31
+ export function useFormatting({
32
+ segments,
33
+ selection,
34
+ activeStyles,
35
+ onSegmentsChange,
36
+ onActiveStylesChange,
37
+ }: UseFormattingOptions) {
38
+ const toggleFormat = useCallback(
39
+ (format: FormatType) => {
40
+ if (selection.start === selection.end) {
41
+ // No selection — toggle active style for next typed text
42
+ onActiveStylesChange({
43
+ ...activeStyles,
44
+ [format]: !activeStyles[format],
45
+ });
46
+ } else {
47
+ // Has selection — toggle format on selected text
48
+ const newSegments = toggleFormatOnSelection(
49
+ segments,
50
+ selection,
51
+ format,
52
+ );
53
+ onSegmentsChange(newSegments);
54
+ }
55
+ },
56
+ [segments, selection, activeStyles, onSegmentsChange, onActiveStylesChange],
57
+ );
58
+
59
+ const setStyleProperty = useCallback(
60
+ <K extends keyof FormatStyle>(key: K, value: FormatStyle[K]) => {
61
+ if (selection.start === selection.end) {
62
+ onActiveStylesChange({
63
+ ...activeStyles,
64
+ [key]: value,
65
+ });
66
+ } else {
67
+ const newSegments = setStyleOnSelection(
68
+ segments,
69
+ selection,
70
+ key,
71
+ value,
72
+ );
73
+ onSegmentsChange(newSegments);
74
+ }
75
+ },
76
+ [segments, selection, activeStyles, onSegmentsChange, onActiveStylesChange],
77
+ );
78
+
79
+ const setHeading = useCallback(
80
+ (level: HeadingLevel) => {
81
+ const newSegments = setHeadingOnLine(segments, selection, level);
82
+ onSegmentsChange(newSegments);
83
+ },
84
+ [segments, selection, onSegmentsChange],
85
+ );
86
+
87
+ const setColor = useCallback(
88
+ (color: string) => {
89
+ setStyleProperty('color', color);
90
+ },
91
+ [setStyleProperty],
92
+ );
93
+
94
+ const setBackgroundColor = useCallback(
95
+ (color: string) => {
96
+ setStyleProperty('backgroundColor', color);
97
+ },
98
+ [setStyleProperty],
99
+ );
100
+
101
+ const setFontSize = useCallback(
102
+ (size: number) => {
103
+ setStyleProperty('fontSize', size);
104
+ },
105
+ [setStyleProperty],
106
+ );
107
+
108
+ const isFormatActive = useCallback(
109
+ (format: FormatType): boolean => {
110
+ if (selection.start === selection.end) {
111
+ return !!activeStyles[format];
112
+ }
113
+ return isFormatActiveInSelection(segments, selection, format);
114
+ },
115
+ [segments, selection, activeStyles],
116
+ );
117
+
118
+ const currentSelectionStyle = useCallback((): FormatStyle => {
119
+ if (selection.start === selection.end) {
120
+ return activeStyles;
121
+ }
122
+ return getSelectionStyle(segments, selection);
123
+ }, [segments, selection, activeStyles]);
124
+
125
+ return {
126
+ toggleFormat,
127
+ setStyleProperty,
128
+ setHeading,
129
+ setColor,
130
+ setBackgroundColor,
131
+ setFontSize,
132
+ isFormatActive,
133
+ currentSelectionStyle,
134
+ };
135
+ }
@@ -0,0 +1,16 @@
1
+ import type { StyledSegment, UseRichTextReturn } from '@/types';
2
+ export interface UseRichTextOptions {
3
+ /** Initial segments to populate the editor with. */
4
+ initialSegments?: StyledSegment[];
5
+ /** Callback when segments change. */
6
+ onChangeSegments?: (segments: StyledSegment[]) => void;
7
+ /** Callback when plain text changes. */
8
+ onChangeText?: (text: string) => void;
9
+ }
10
+ /**
11
+ * Main hook for the rich text editor.
12
+ *
13
+ * Manages the complete editor state (segments, selection, active styles)
14
+ * and exposes all actions needed to build a rich text UI.
15
+ */
16
+ export declare function useRichText(options?: UseRichTextOptions): UseRichTextReturn;
@@ -0,0 +1,171 @@
1
+ import { useState, useCallback, useRef, useEffect } from 'react';
2
+ import type {
3
+ StyledSegment,
4
+ FormatType,
5
+ FormatStyle,
6
+ HeadingLevel,
7
+ SelectionRange,
8
+ RichTextState,
9
+ RichTextActions,
10
+ UseRichTextReturn,
11
+ } from '@/types';
12
+ import { EMPTY_FORMAT_STYLE } from '@/constants/defaultStyles';
13
+ import {
14
+ createSegment,
15
+ segmentsToPlainText,
16
+ reconcileTextChange,
17
+ findPositionInSegments,
18
+ } from '@/utils/parser';
19
+ import { useSelection } from '@/hooks/useSelection';
20
+ import { useFormatting } from '@/hooks/useFormatting';
21
+
22
+ export interface UseRichTextOptions {
23
+ /** Initial segments to populate the editor with. */
24
+ initialSegments?: StyledSegment[];
25
+ /** Callback when segments change. */
26
+ onChangeSegments?: (segments: StyledSegment[]) => void;
27
+ /** Callback when plain text changes. */
28
+ onChangeText?: (text: string) => void;
29
+ }
30
+
31
+ /**
32
+ * Main hook for the rich text editor.
33
+ *
34
+ * Manages the complete editor state (segments, selection, active styles)
35
+ * and exposes all actions needed to build a rich text UI.
36
+ */
37
+ export function useRichText(
38
+ options: UseRichTextOptions = {},
39
+ ): UseRichTextReturn {
40
+ const { initialSegments, onChangeSegments, onChangeText } = options;
41
+
42
+ // ─── State ───────────────────────────────────────────────────────────────
43
+
44
+ const [segments, setSegments] = useState<StyledSegment[]>(() => {
45
+ if (initialSegments && initialSegments.length > 0) {
46
+ return initialSegments;
47
+ }
48
+ return [createSegment('')];
49
+ });
50
+
51
+ const [activeStyles, setActiveStyles] = useState<FormatStyle>({
52
+ ...EMPTY_FORMAT_STYLE,
53
+ });
54
+
55
+ const { selection, handleSelectionChange } = useSelection();
56
+
57
+ // Refs for stable access in callbacks
58
+ const segmentsRef = useRef(segments);
59
+ segmentsRef.current = segments;
60
+ const activeStylesRef = useRef(activeStyles);
61
+ activeStylesRef.current = activeStyles;
62
+
63
+ // ─── Segment Change Handler ──────────────────────────────────────────────
64
+
65
+ const updateSegments = useCallback(
66
+ (newSegments: StyledSegment[]) => {
67
+ setSegments(newSegments);
68
+ onChangeSegments?.(newSegments);
69
+ onChangeText?.(segmentsToPlainText(newSegments));
70
+ },
71
+ [onChangeSegments, onChangeText],
72
+ );
73
+
74
+ // ─── Formatting ──────────────────────────────────────────────────────────
75
+
76
+ const formatting = useFormatting({
77
+ segments,
78
+ selection,
79
+ activeStyles,
80
+ onSegmentsChange: updateSegments,
81
+ onActiveStylesChange: setActiveStyles,
82
+ });
83
+
84
+ // ─── Text Change Handler ─────────────────────────────────────────────────
85
+
86
+ const handleTextChange = useCallback(
87
+ (newText: string) => {
88
+ const currentSegments = segmentsRef.current;
89
+ const currentActiveStyles = activeStylesRef.current;
90
+
91
+ const newSegments = reconcileTextChange(
92
+ currentSegments,
93
+ newText,
94
+ currentActiveStyles,
95
+ );
96
+
97
+ updateSegments(newSegments);
98
+ },
99
+ [updateSegments],
100
+ );
101
+
102
+ // ─── Selection Change Handler ────────────────────────────────────────────
103
+
104
+ const onSelectionChange = useCallback(
105
+ (newSelection: SelectionRange) => {
106
+ handleSelectionChange(newSelection);
107
+
108
+ // Update active styles based on cursor position
109
+ if (newSelection.start === newSelection.end) {
110
+ const pos = findPositionInSegments(
111
+ segmentsRef.current,
112
+ newSelection.start,
113
+ );
114
+ if (segmentsRef.current.length > 0) {
115
+ const seg = segmentsRef.current[pos.segmentIndex];
116
+ setActiveStyles({ ...seg.styles });
117
+ }
118
+ }
119
+ },
120
+ [handleSelectionChange],
121
+ );
122
+
123
+ // ─── Export / Import ─────────────────────────────────────────────────────
124
+
125
+ const getPlainText = useCallback((): string => {
126
+ return segmentsToPlainText(segmentsRef.current);
127
+ }, []);
128
+
129
+ const exportJSON = useCallback((): StyledSegment[] => {
130
+ return JSON.parse(JSON.stringify(segmentsRef.current));
131
+ }, []);
132
+
133
+ const importJSON = useCallback(
134
+ (newSegments: StyledSegment[]) => {
135
+ const safeSegments =
136
+ newSegments.length > 0 ? newSegments : [createSegment('')];
137
+ updateSegments(safeSegments);
138
+ },
139
+ [updateSegments],
140
+ );
141
+
142
+ const clear = useCallback(() => {
143
+ updateSegments([createSegment('')]);
144
+ setActiveStyles({ ...EMPTY_FORMAT_STYLE });
145
+ }, [updateSegments]);
146
+
147
+ // ─── Build Return Value ──────────────────────────────────────────────────
148
+
149
+ const state: RichTextState = {
150
+ segments,
151
+ selection,
152
+ activeStyles,
153
+ };
154
+
155
+ const actions: RichTextActions = {
156
+ toggleFormat: formatting.toggleFormat,
157
+ setStyleProperty: formatting.setStyleProperty,
158
+ setHeading: formatting.setHeading,
159
+ setColor: formatting.setColor,
160
+ setBackgroundColor: formatting.setBackgroundColor,
161
+ setFontSize: formatting.setFontSize,
162
+ handleTextChange,
163
+ handleSelectionChange: onSelectionChange,
164
+ getPlainText,
165
+ exportJSON,
166
+ importJSON,
167
+ clear,
168
+ };
169
+
170
+ return { state, actions };
171
+ }
@@ -0,0 +1,13 @@
1
+ import type { SelectionRange } from '@/types';
2
+ /**
3
+ * Hook for tracking TextInput selection state.
4
+ *
5
+ * Returns the current selection and a handler to update it.
6
+ */
7
+ export declare function useSelection(initialSelection?: SelectionRange): {
8
+ selection: SelectionRange;
9
+ setSelection: import("react").Dispatch<import("react").SetStateAction<SelectionRange>>;
10
+ handleSelectionChange: (newSelection: SelectionRange) => void;
11
+ getSelection: () => SelectionRange;
12
+ hasSelection: () => boolean;
13
+ };
@@ -0,0 +1,40 @@
1
+ import { useState, useCallback, useRef } from 'react';
2
+ import type { SelectionRange } from '@/types';
3
+
4
+ /**
5
+ * Hook for tracking TextInput selection state.
6
+ *
7
+ * Returns the current selection and a handler to update it.
8
+ */
9
+ export function useSelection(initialSelection?: SelectionRange) {
10
+ const [selection, setSelection] = useState<SelectionRange>(
11
+ initialSelection ?? { start: 0, end: 0 },
12
+ );
13
+
14
+ // Use a ref to avoid stale closures in callbacks
15
+ const selectionRef = useRef(selection);
16
+ selectionRef.current = selection;
17
+
18
+ const handleSelectionChange = useCallback(
19
+ (newSelection: SelectionRange) => {
20
+ setSelection(newSelection);
21
+ },
22
+ [],
23
+ );
24
+
25
+ const getSelection = useCallback((): SelectionRange => {
26
+ return selectionRef.current;
27
+ }, []);
28
+
29
+ const hasSelection = useCallback((): boolean => {
30
+ return selectionRef.current.start !== selectionRef.current.end;
31
+ }, []);
32
+
33
+ return {
34
+ selection,
35
+ setSelection,
36
+ handleSelectionChange,
37
+ getSelection,
38
+ hasSelection,
39
+ };
40
+ }
package/src/index.d.ts ADDED
@@ -0,0 +1,15 @@
1
+ export { RichTextInput } from '@/components/RichTextInput';
2
+ export { OverlayText } from '@/components/OverlayText';
3
+ export { Toolbar } from '@/components/Toolbar';
4
+ export { ToolbarButton } from '@/components/ToolbarButton';
5
+ export { useRichText } from '@/hooks/useRichText';
6
+ export type { UseRichTextOptions } from '@/hooks/useRichText';
7
+ export { useSelection } from '@/hooks/useSelection';
8
+ export { useFormatting } from '@/hooks/useFormatting';
9
+ export { RichTextProvider, useRichTextContext, } from '@/context/RichTextContext';
10
+ export type { RichTextProviderProps } from '@/context/RichTextContext';
11
+ export { createSegment, segmentsToPlainText, getTotalLength, mergeAdjacentSegments, reconcileTextChange, } from '@/utils/parser';
12
+ export { toggleFormatOnSelection, setStyleOnSelection, setHeadingOnLine, isFormatActiveInSelection, getSelectionStyle, } from '@/utils/formatter';
13
+ export { formatStyleToTextStyle, segmentToTextStyle, segmentsToTextStyles, } from '@/utils/styleMapper';
14
+ export { DEFAULT_COLORS, DEFAULT_THEME, DEFAULT_TOOLBAR_ITEMS, DEFAULT_BASE_TEXT_STYLE, HEADING_FONT_SIZES, EMPTY_FORMAT_STYLE, } from '@/constants/defaultStyles';
15
+ export type { FormatType, HeadingLevel, ListType, FormatStyle, StyledSegment, SelectionRange, RichTextState, RichTextActions, UseRichTextReturn, RichTextTheme, ToolbarItem, OverlayTextProps, ToolbarButtonProps, ToolbarProps, RichTextInputProps, } from '@/types';
package/src/index.ts ADDED
@@ -0,0 +1,68 @@
1
+ // ─── Components ──────────────────────────────────────────────────────────────
2
+ export { RichTextInput } from '@/components/RichTextInput';
3
+ export { OverlayText } from '@/components/OverlayText';
4
+ export { Toolbar } from '@/components/Toolbar';
5
+ export { ToolbarButton } from '@/components/ToolbarButton';
6
+
7
+ // ─── Hooks ───────────────────────────────────────────────────────────────────
8
+ export { useRichText } from '@/hooks/useRichText';
9
+ export type { UseRichTextOptions } from '@/hooks/useRichText';
10
+ export { useSelection } from '@/hooks/useSelection';
11
+ export { useFormatting } from '@/hooks/useFormatting';
12
+
13
+ // ─── Context ─────────────────────────────────────────────────────────────────
14
+ export {
15
+ RichTextProvider,
16
+ useRichTextContext,
17
+ } from '@/context/RichTextContext';
18
+ export type { RichTextProviderProps } from '@/context/RichTextContext';
19
+
20
+ // ─── Utilities ───────────────────────────────────────────────────────────────
21
+ export {
22
+ createSegment,
23
+ segmentsToPlainText,
24
+ getTotalLength,
25
+ mergeAdjacentSegments,
26
+ reconcileTextChange,
27
+ } from '@/utils/parser';
28
+ export {
29
+ toggleFormatOnSelection,
30
+ setStyleOnSelection,
31
+ setHeadingOnLine,
32
+ isFormatActiveInSelection,
33
+ getSelectionStyle,
34
+ } from '@/utils/formatter';
35
+ export {
36
+ formatStyleToTextStyle,
37
+ segmentToTextStyle,
38
+ segmentsToTextStyles,
39
+ } from '@/utils/styleMapper';
40
+
41
+ // ─── Constants ───────────────────────────────────────────────────────────────
42
+ export {
43
+ DEFAULT_COLORS,
44
+ DEFAULT_THEME,
45
+ DEFAULT_TOOLBAR_ITEMS,
46
+ DEFAULT_BASE_TEXT_STYLE,
47
+ HEADING_FONT_SIZES,
48
+ EMPTY_FORMAT_STYLE,
49
+ } from '@/constants/defaultStyles';
50
+
51
+ // ─── Types ───────────────────────────────────────────────────────────────────
52
+ export type {
53
+ FormatType,
54
+ HeadingLevel,
55
+ ListType,
56
+ FormatStyle,
57
+ StyledSegment,
58
+ SelectionRange,
59
+ RichTextState,
60
+ RichTextActions,
61
+ UseRichTextReturn,
62
+ RichTextTheme,
63
+ ToolbarItem,
64
+ OverlayTextProps,
65
+ ToolbarButtonProps,
66
+ ToolbarProps,
67
+ RichTextInputProps,
68
+ } from '@/types';