@moontra/moonui-pro 2.8.10 → 2.8.11
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/index.mjs +114 -56
- package/package.json +1 -1
- package/src/components/rich-text-editor/index.tsx +108 -24
package/dist/index.mjs
CHANGED
|
@@ -4044,7 +4044,7 @@ var me = t.forwardRef((r2, o) => {
|
|
|
4044
4044
|
var e;
|
|
4045
4045
|
return Array.from(((e = I.current) == null ? void 0 : e.querySelectorAll(ce)) || []);
|
|
4046
4046
|
}
|
|
4047
|
-
function
|
|
4047
|
+
function X20(e) {
|
|
4048
4048
|
let s = V()[e];
|
|
4049
4049
|
s && E.setState("value", s.getAttribute(T));
|
|
4050
4050
|
}
|
|
@@ -4059,10 +4059,10 @@ var me = t.forwardRef((r2, o) => {
|
|
|
4059
4059
|
s = e > 0 ? we(s, N) : De(s, N), i = s == null ? void 0 : s.querySelector(ce);
|
|
4060
4060
|
i ? E.setState("value", i.getAttribute(T)) : Q(e);
|
|
4061
4061
|
}
|
|
4062
|
-
let oe = () =>
|
|
4062
|
+
let oe = () => X20(V().length - 1), ie3 = (e) => {
|
|
4063
4063
|
e.preventDefault(), e.metaKey ? oe() : e.altKey ? re(1) : Q(1);
|
|
4064
4064
|
}, se = (e) => {
|
|
4065
|
-
e.preventDefault(), e.metaKey ?
|
|
4065
|
+
e.preventDefault(), e.metaKey ? X20(0) : e.altKey ? re(-1) : Q(-1);
|
|
4066
4066
|
};
|
|
4067
4067
|
return t.createElement(Primitive2.div, { ref: o, tabIndex: -1, ...O, "cmdk-root": "", onKeyDown: (e) => {
|
|
4068
4068
|
var s;
|
|
@@ -4089,7 +4089,7 @@ var me = t.forwardRef((r2, o) => {
|
|
|
4089
4089
|
break;
|
|
4090
4090
|
}
|
|
4091
4091
|
case "Home": {
|
|
4092
|
-
e.preventDefault(),
|
|
4092
|
+
e.preventDefault(), X20(0);
|
|
4093
4093
|
break;
|
|
4094
4094
|
}
|
|
4095
4095
|
case "End": {
|
|
@@ -50283,53 +50283,78 @@ var EditorColorPicker = ({
|
|
|
50283
50283
|
onColorSelect,
|
|
50284
50284
|
currentColor = "#000000"
|
|
50285
50285
|
}) => {
|
|
50286
|
-
|
|
50287
|
-
|
|
50288
|
-
|
|
50289
|
-
|
|
50290
|
-
|
|
50291
|
-
|
|
50292
|
-
|
|
50293
|
-
|
|
50294
|
-
|
|
50295
|
-
|
|
50296
|
-
|
|
50297
|
-
|
|
50298
|
-
|
|
50299
|
-
|
|
50300
|
-
|
|
50301
|
-
|
|
50302
|
-
|
|
50303
|
-
|
|
50304
|
-
|
|
50305
|
-
|
|
50306
|
-
|
|
50307
|
-
|
|
50308
|
-
"
|
|
50309
|
-
|
|
50310
|
-
|
|
50311
|
-
|
|
50312
|
-
|
|
50313
|
-
|
|
50314
|
-
|
|
50315
|
-
|
|
50316
|
-
|
|
50317
|
-
|
|
50318
|
-
|
|
50319
|
-
|
|
50320
|
-
|
|
50321
|
-
|
|
50322
|
-
|
|
50323
|
-
|
|
50324
|
-
|
|
50325
|
-
|
|
50326
|
-
|
|
50327
|
-
|
|
50328
|
-
|
|
50329
|
-
|
|
50330
|
-
|
|
50331
|
-
|
|
50332
|
-
|
|
50286
|
+
const [showAdvanced, setShowAdvanced] = t__default.useState(false);
|
|
50287
|
+
const quickColors = [
|
|
50288
|
+
"#000000",
|
|
50289
|
+
// Black
|
|
50290
|
+
"#ef4444",
|
|
50291
|
+
// Red
|
|
50292
|
+
"#f59e0b",
|
|
50293
|
+
// Orange
|
|
50294
|
+
"#10b981",
|
|
50295
|
+
// Green
|
|
50296
|
+
"#3b82f6",
|
|
50297
|
+
// Blue
|
|
50298
|
+
"#8b5cf6",
|
|
50299
|
+
// Purple
|
|
50300
|
+
"#6b7280",
|
|
50301
|
+
// Gray
|
|
50302
|
+
"#ec4899"
|
|
50303
|
+
// Pink
|
|
50304
|
+
];
|
|
50305
|
+
if (showAdvanced) {
|
|
50306
|
+
return /* @__PURE__ */ jsxs("div", { className: "p-4 w-64", children: [
|
|
50307
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between mb-3", children: [
|
|
50308
|
+
/* @__PURE__ */ jsx("span", { className: "text-sm font-medium", children: "Choose Color" }),
|
|
50309
|
+
/* @__PURE__ */ jsx(
|
|
50310
|
+
MoonUIButtonPro,
|
|
50311
|
+
{
|
|
50312
|
+
size: "sm",
|
|
50313
|
+
variant: "ghost",
|
|
50314
|
+
onClick: () => setShowAdvanced(false),
|
|
50315
|
+
children: "Back"
|
|
50316
|
+
}
|
|
50317
|
+
)
|
|
50318
|
+
] }),
|
|
50319
|
+
/* @__PURE__ */ jsx(
|
|
50320
|
+
MoonUIColorPickerPro,
|
|
50321
|
+
{
|
|
50322
|
+
value: currentColor,
|
|
50323
|
+
onChange: (color) => {
|
|
50324
|
+
onColorSelect(color);
|
|
50325
|
+
setShowAdvanced(false);
|
|
50326
|
+
},
|
|
50327
|
+
showInput: true,
|
|
50328
|
+
showPresets: false,
|
|
50329
|
+
size: "sm"
|
|
50330
|
+
}
|
|
50331
|
+
)
|
|
50332
|
+
] });
|
|
50333
|
+
}
|
|
50334
|
+
return /* @__PURE__ */ jsx("div", { className: "p-3 w-36", children: /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-3 gap-2", children: [
|
|
50335
|
+
quickColors.map((color) => /* @__PURE__ */ jsx(
|
|
50336
|
+
"button",
|
|
50337
|
+
{
|
|
50338
|
+
onClick: () => onColorSelect(color),
|
|
50339
|
+
className: cn(
|
|
50340
|
+
"w-10 h-10 rounded-md border-2 hover:scale-110 transition-transform",
|
|
50341
|
+
currentColor === color ? "border-primary" : "border-transparent"
|
|
50342
|
+
),
|
|
50343
|
+
style: { backgroundColor: color },
|
|
50344
|
+
title: color
|
|
50345
|
+
},
|
|
50346
|
+
color
|
|
50347
|
+
)),
|
|
50348
|
+
/* @__PURE__ */ jsx(
|
|
50349
|
+
"button",
|
|
50350
|
+
{
|
|
50351
|
+
onClick: () => setShowAdvanced(true),
|
|
50352
|
+
className: "w-10 h-10 rounded-md border-2 border-dashed border-muted-foreground/50 hover:border-primary transition-colors flex items-center justify-center",
|
|
50353
|
+
title: "More colors",
|
|
50354
|
+
children: /* @__PURE__ */ jsx(Palette, { className: "w-5 h-5 text-muted-foreground" })
|
|
50355
|
+
}
|
|
50356
|
+
)
|
|
50357
|
+
] }) });
|
|
50333
50358
|
};
|
|
50334
50359
|
var ToolbarButton = ({
|
|
50335
50360
|
active,
|
|
@@ -50434,6 +50459,8 @@ function RichTextEditor({
|
|
|
50434
50459
|
const [isTyping, setIsTyping] = useState(false);
|
|
50435
50460
|
const typingIntervalRef = useRef(null);
|
|
50436
50461
|
const [currentAction, setCurrentAction] = useState("");
|
|
50462
|
+
const [remainingText, setRemainingText] = useState("");
|
|
50463
|
+
const isTypingRef = useRef(false);
|
|
50437
50464
|
const [isSourceView, setIsSourceView] = useState(false);
|
|
50438
50465
|
const [sourceContent, setSourceContent] = useState("");
|
|
50439
50466
|
const [currentTextColor, setCurrentTextColor] = useState("#000000");
|
|
@@ -50451,6 +50478,20 @@ function RichTextEditor({
|
|
|
50451
50478
|
}
|
|
50452
50479
|
};
|
|
50453
50480
|
}, []);
|
|
50481
|
+
const stopTyping = () => {
|
|
50482
|
+
if (typingIntervalRef.current) {
|
|
50483
|
+
clearTimeout(typingIntervalRef.current);
|
|
50484
|
+
typingIntervalRef.current = null;
|
|
50485
|
+
}
|
|
50486
|
+
setIsTyping(false);
|
|
50487
|
+
isTypingRef.current = false;
|
|
50488
|
+
setTypingText("");
|
|
50489
|
+
setRemainingText("");
|
|
50490
|
+
toast({
|
|
50491
|
+
title: "AI typing stopped",
|
|
50492
|
+
description: "The AI response was interrupted."
|
|
50493
|
+
});
|
|
50494
|
+
};
|
|
50454
50495
|
const slashCommands = [
|
|
50455
50496
|
{
|
|
50456
50497
|
id: "rewrite",
|
|
@@ -50732,6 +50773,7 @@ function RichTextEditor({
|
|
|
50732
50773
|
processingToast.dismiss();
|
|
50733
50774
|
if (result) {
|
|
50734
50775
|
setIsTyping(true);
|
|
50776
|
+
isTypingRef.current = true;
|
|
50735
50777
|
setTypingText("");
|
|
50736
50778
|
if (selectedText) {
|
|
50737
50779
|
editor.chain().focus().deleteSelection().run();
|
|
@@ -50739,19 +50781,24 @@ function RichTextEditor({
|
|
|
50739
50781
|
let currentIndex = 0;
|
|
50740
50782
|
const typeSpeed = 30;
|
|
50741
50783
|
const typeNextChar = () => {
|
|
50742
|
-
if (currentIndex < result.length) {
|
|
50784
|
+
if (currentIndex < result.length && isTypingRef.current) {
|
|
50743
50785
|
const nextChar = result[currentIndex];
|
|
50744
50786
|
setTypingText((prev) => prev + nextChar);
|
|
50745
50787
|
editor.chain().focus().insertContent(nextChar).run();
|
|
50746
50788
|
currentIndex++;
|
|
50789
|
+
setRemainingText(result.substring(currentIndex));
|
|
50747
50790
|
typingIntervalRef.current = setTimeout(typeNextChar, typeSpeed);
|
|
50748
50791
|
} else {
|
|
50749
50792
|
setIsTyping(false);
|
|
50793
|
+
isTypingRef.current = false;
|
|
50750
50794
|
setTypingText("");
|
|
50751
|
-
|
|
50752
|
-
|
|
50753
|
-
|
|
50754
|
-
|
|
50795
|
+
setRemainingText("");
|
|
50796
|
+
if (currentIndex >= result.length) {
|
|
50797
|
+
toast({
|
|
50798
|
+
title: "AI action completed",
|
|
50799
|
+
description: "Your text has been updated successfully."
|
|
50800
|
+
});
|
|
50801
|
+
}
|
|
50755
50802
|
}
|
|
50756
50803
|
};
|
|
50757
50804
|
typeNextChar();
|
|
@@ -51301,6 +51348,17 @@ function RichTextEditor({
|
|
|
51301
51348
|
]
|
|
51302
51349
|
}
|
|
51303
51350
|
) }),
|
|
51351
|
+
isTyping && /* @__PURE__ */ jsx(
|
|
51352
|
+
MoonUIButtonPro,
|
|
51353
|
+
{
|
|
51354
|
+
variant: "destructive",
|
|
51355
|
+
size: "sm",
|
|
51356
|
+
className: "h-8 px-2",
|
|
51357
|
+
onClick: stopTyping,
|
|
51358
|
+
title: "Stop AI typing",
|
|
51359
|
+
children: /* @__PURE__ */ jsx(X, { className: "w-4 h-4" })
|
|
51360
|
+
}
|
|
51361
|
+
),
|
|
51304
51362
|
/* @__PURE__ */ jsxs(MoonUIDropdownMenuContentPro, { className: "w-64", children: [
|
|
51305
51363
|
/* @__PURE__ */ jsxs("div", { className: "px-2 py-1.5 text-xs font-semibold text-muted-foreground flex items-center gap-2", children: [
|
|
51306
51364
|
/* @__PURE__ */ jsx(Wand2, { className: "w-3 h-3" }),
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@moontra/moonui-pro",
|
|
3
|
-
"version": "2.8.
|
|
3
|
+
"version": "2.8.11",
|
|
4
4
|
"description": "Premium React components for MoonUI - Advanced UI library with 50+ pro components including performance, interactive, and gesture components",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.mjs",
|
|
@@ -73,7 +73,8 @@ import {
|
|
|
73
73
|
Heart,
|
|
74
74
|
GraduationCap,
|
|
75
75
|
Zap,
|
|
76
|
-
Lightbulb
|
|
76
|
+
Lightbulb,
|
|
77
|
+
X
|
|
77
78
|
} from 'lucide-react';
|
|
78
79
|
import { cn } from '../../lib/utils';
|
|
79
80
|
import { Button } from '../ui/button';
|
|
@@ -218,23 +219,71 @@ const EditorColorPicker = ({
|
|
|
218
219
|
onColorSelect: (color: string) => void;
|
|
219
220
|
currentColor?: string;
|
|
220
221
|
}) => {
|
|
222
|
+
const [showAdvanced, setShowAdvanced] = React.useState(false);
|
|
223
|
+
|
|
224
|
+
// Quick colors - 3x3 grid of 8 colors + 1 advanced button
|
|
225
|
+
const quickColors = [
|
|
226
|
+
'#000000', // Black
|
|
227
|
+
'#ef4444', // Red
|
|
228
|
+
'#f59e0b', // Orange
|
|
229
|
+
'#10b981', // Green
|
|
230
|
+
'#3b82f6', // Blue
|
|
231
|
+
'#8b5cf6', // Purple
|
|
232
|
+
'#6b7280', // Gray
|
|
233
|
+
'#ec4899', // Pink
|
|
234
|
+
];
|
|
235
|
+
|
|
236
|
+
if (showAdvanced) {
|
|
237
|
+
return (
|
|
238
|
+
<div className="p-4 w-64">
|
|
239
|
+
<div className="flex items-center justify-between mb-3">
|
|
240
|
+
<span className="text-sm font-medium">Choose Color</span>
|
|
241
|
+
<Button
|
|
242
|
+
size="sm"
|
|
243
|
+
variant="ghost"
|
|
244
|
+
onClick={() => setShowAdvanced(false)}
|
|
245
|
+
>
|
|
246
|
+
Back
|
|
247
|
+
</Button>
|
|
248
|
+
</div>
|
|
249
|
+
<ColorPicker
|
|
250
|
+
value={currentColor}
|
|
251
|
+
onChange={(color) => {
|
|
252
|
+
onColorSelect(color);
|
|
253
|
+
setShowAdvanced(false);
|
|
254
|
+
}}
|
|
255
|
+
showInput={true}
|
|
256
|
+
showPresets={false}
|
|
257
|
+
size="sm"
|
|
258
|
+
/>
|
|
259
|
+
</div>
|
|
260
|
+
);
|
|
261
|
+
}
|
|
262
|
+
|
|
221
263
|
return (
|
|
222
|
-
<
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
264
|
+
<div className="p-3 w-36">
|
|
265
|
+
<div className="grid grid-cols-3 gap-2">
|
|
266
|
+
{quickColors.map((color) => (
|
|
267
|
+
<button
|
|
268
|
+
key={color}
|
|
269
|
+
onClick={() => onColorSelect(color)}
|
|
270
|
+
className={cn(
|
|
271
|
+
"w-10 h-10 rounded-md border-2 hover:scale-110 transition-transform",
|
|
272
|
+
currentColor === color ? "border-primary" : "border-transparent"
|
|
273
|
+
)}
|
|
274
|
+
style={{ backgroundColor: color }}
|
|
275
|
+
title={color}
|
|
276
|
+
/>
|
|
277
|
+
))}
|
|
278
|
+
<button
|
|
279
|
+
onClick={() => setShowAdvanced(true)}
|
|
280
|
+
className="w-10 h-10 rounded-md border-2 border-dashed border-muted-foreground/50 hover:border-primary transition-colors flex items-center justify-center"
|
|
281
|
+
title="More colors"
|
|
282
|
+
>
|
|
283
|
+
<Palette className="w-5 h-5 text-muted-foreground" />
|
|
284
|
+
</button>
|
|
285
|
+
</div>
|
|
286
|
+
</div>
|
|
238
287
|
);
|
|
239
288
|
};
|
|
240
289
|
|
|
@@ -379,6 +428,8 @@ export function RichTextEditor({
|
|
|
379
428
|
const [isTyping, setIsTyping] = useState(false);
|
|
380
429
|
const typingIntervalRef = useRef<NodeJS.Timeout | null>(null);
|
|
381
430
|
const [currentAction, setCurrentAction] = useState('');
|
|
431
|
+
const [remainingText, setRemainingText] = useState(''); // To store remaining text when stopped
|
|
432
|
+
const isTypingRef = useRef(false); // Ref to track typing state in closure
|
|
382
433
|
const [isSourceView, setIsSourceView] = useState(false);
|
|
383
434
|
const [sourceContent, setSourceContent] = useState('');
|
|
384
435
|
const [currentTextColor, setCurrentTextColor] = useState('#000000');
|
|
@@ -399,6 +450,22 @@ export function RichTextEditor({
|
|
|
399
450
|
}
|
|
400
451
|
};
|
|
401
452
|
}, []);
|
|
453
|
+
|
|
454
|
+
// Stop typing function
|
|
455
|
+
const stopTyping = () => {
|
|
456
|
+
if (typingIntervalRef.current) {
|
|
457
|
+
clearTimeout(typingIntervalRef.current);
|
|
458
|
+
typingIntervalRef.current = null;
|
|
459
|
+
}
|
|
460
|
+
setIsTyping(false);
|
|
461
|
+
isTypingRef.current = false;
|
|
462
|
+
setTypingText('');
|
|
463
|
+
setRemainingText('');
|
|
464
|
+
toast({
|
|
465
|
+
title: "AI typing stopped",
|
|
466
|
+
description: "The AI response was interrupted.",
|
|
467
|
+
});
|
|
468
|
+
};
|
|
402
469
|
|
|
403
470
|
// Slash commands tanımları
|
|
404
471
|
const slashCommands: SlashCommand[] = [
|
|
@@ -699,6 +766,7 @@ export function RichTextEditor({
|
|
|
699
766
|
if (result) {
|
|
700
767
|
// Start typewriter effect
|
|
701
768
|
setIsTyping(true);
|
|
769
|
+
isTypingRef.current = true;
|
|
702
770
|
setTypingText('');
|
|
703
771
|
|
|
704
772
|
if (selectedText) {
|
|
@@ -709,22 +777,27 @@ export function RichTextEditor({
|
|
|
709
777
|
const typeSpeed = 30; // ms per character
|
|
710
778
|
|
|
711
779
|
const typeNextChar = () => {
|
|
712
|
-
if (currentIndex < result.length) {
|
|
780
|
+
if (currentIndex < result.length && isTypingRef.current) {
|
|
713
781
|
const nextChar = result[currentIndex];
|
|
714
782
|
setTypingText(prev => prev + nextChar);
|
|
715
783
|
editor.chain().focus().insertContent(nextChar).run();
|
|
716
784
|
currentIndex++;
|
|
785
|
+
setRemainingText(result.substring(currentIndex));
|
|
717
786
|
typingIntervalRef.current = setTimeout(typeNextChar, typeSpeed);
|
|
718
787
|
} else {
|
|
719
|
-
// Typing complete
|
|
788
|
+
// Typing complete or stopped
|
|
720
789
|
setIsTyping(false);
|
|
790
|
+
isTypingRef.current = false;
|
|
721
791
|
setTypingText('');
|
|
792
|
+
setRemainingText('');
|
|
722
793
|
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
794
|
+
if (currentIndex >= result.length) {
|
|
795
|
+
// Success toast only if completed
|
|
796
|
+
toast({
|
|
797
|
+
title: "AI action completed",
|
|
798
|
+
description: "Your text has been updated successfully.",
|
|
799
|
+
});
|
|
800
|
+
}
|
|
728
801
|
}
|
|
729
802
|
};
|
|
730
803
|
|
|
@@ -1364,6 +1437,17 @@ export function RichTextEditor({
|
|
|
1364
1437
|
{isTyping ? 'Typing...' : 'AI Tools'}
|
|
1365
1438
|
</Button>
|
|
1366
1439
|
</DropdownMenuTrigger>
|
|
1440
|
+
{isTyping && (
|
|
1441
|
+
<Button
|
|
1442
|
+
variant="destructive"
|
|
1443
|
+
size="sm"
|
|
1444
|
+
className="h-8 px-2"
|
|
1445
|
+
onClick={stopTyping}
|
|
1446
|
+
title="Stop AI typing"
|
|
1447
|
+
>
|
|
1448
|
+
<X className="w-4 h-4" />
|
|
1449
|
+
</Button>
|
|
1450
|
+
)}
|
|
1367
1451
|
<DropdownMenuContent className="w-64">
|
|
1368
1452
|
<div className="px-2 py-1.5 text-xs font-semibold text-muted-foreground flex items-center gap-2">
|
|
1369
1453
|
<Wand2 className="w-3 h-3" />
|