@janovix/blocks 1.2.0-rc.22 → 1.2.0-rc.23
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.cjs +31 -103
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +2 -6
- package/dist/index.d.ts +2 -6
- package/dist/index.js +19 -91
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
package/dist/index.d.cts
CHANGED
|
@@ -193,12 +193,8 @@ interface AvatarEditorProps {
|
|
|
193
193
|
className?: string;
|
|
194
194
|
/** Control size variant - 'default' for desktop, 'large' for mobile/touch devices */
|
|
195
195
|
controlSize?: "default" | "large";
|
|
196
|
-
/** @deprecated Use value instead. Default image URL to load */
|
|
197
|
-
defaultImage?: string;
|
|
198
|
-
/** Initials to show in the placeholder (for backward compatibility, not displayed in current UI) */
|
|
199
|
-
initials?: string;
|
|
200
196
|
}
|
|
201
|
-
declare function AvatarEditor({ value, onChange, size, showGrid: initialShowGrid, outputSize, outputFormat, outputQuality, className, controlSize,
|
|
197
|
+
declare function AvatarEditor({ value: _value, onChange, size, showGrid: initialShowGrid, outputSize, outputFormat, outputQuality, className, controlSize, }: AvatarEditorProps): react_jsx_runtime.JSX.Element;
|
|
202
198
|
|
|
203
199
|
interface AvatarEditorDialogProps {
|
|
204
200
|
/** Current avatar URL or data URL */
|
|
@@ -230,7 +226,7 @@ interface AvatarEditorDialogProps {
|
|
|
230
226
|
/** Additional class names */
|
|
231
227
|
className?: string;
|
|
232
228
|
}
|
|
233
|
-
declare function AvatarEditorDialog({ value, onChange, onSave, displaySize, editorSize, outputSize, placeholder
|
|
229
|
+
declare function AvatarEditorDialog({ value, onChange, onSave, displaySize, editorSize, outputSize, placeholder, editLabel, dialogTitle, acceptText, cancelText, successMessage, errorMessage, className, }: AvatarEditorDialogProps): react_jsx_runtime.JSX.Element;
|
|
234
230
|
|
|
235
231
|
/**
|
|
236
232
|
* NotificationsWidget - A compact notification bell for navigation bars
|
package/dist/index.d.ts
CHANGED
|
@@ -193,12 +193,8 @@ interface AvatarEditorProps {
|
|
|
193
193
|
className?: string;
|
|
194
194
|
/** Control size variant - 'default' for desktop, 'large' for mobile/touch devices */
|
|
195
195
|
controlSize?: "default" | "large";
|
|
196
|
-
/** @deprecated Use value instead. Default image URL to load */
|
|
197
|
-
defaultImage?: string;
|
|
198
|
-
/** Initials to show in the placeholder (for backward compatibility, not displayed in current UI) */
|
|
199
|
-
initials?: string;
|
|
200
196
|
}
|
|
201
|
-
declare function AvatarEditor({ value, onChange, size, showGrid: initialShowGrid, outputSize, outputFormat, outputQuality, className, controlSize,
|
|
197
|
+
declare function AvatarEditor({ value: _value, onChange, size, showGrid: initialShowGrid, outputSize, outputFormat, outputQuality, className, controlSize, }: AvatarEditorProps): react_jsx_runtime.JSX.Element;
|
|
202
198
|
|
|
203
199
|
interface AvatarEditorDialogProps {
|
|
204
200
|
/** Current avatar URL or data URL */
|
|
@@ -230,7 +226,7 @@ interface AvatarEditorDialogProps {
|
|
|
230
226
|
/** Additional class names */
|
|
231
227
|
className?: string;
|
|
232
228
|
}
|
|
233
|
-
declare function AvatarEditorDialog({ value, onChange, onSave, displaySize, editorSize, outputSize, placeholder
|
|
229
|
+
declare function AvatarEditorDialog({ value, onChange, onSave, displaySize, editorSize, outputSize, placeholder, editLabel, dialogTitle, acceptText, cancelText, successMessage, errorMessage, className, }: AvatarEditorDialogProps): react_jsx_runtime.JSX.Element;
|
|
234
230
|
|
|
235
231
|
/**
|
|
236
232
|
* NotificationsWidget - A compact notification bell for navigation bars
|
package/dist/index.js
CHANGED
|
@@ -2,7 +2,7 @@ import * as React2 from 'react';
|
|
|
2
2
|
import { createContext, useContext, useState, useCallback, useEffect, useRef } from 'react';
|
|
3
3
|
import { useTheme } from 'next-themes';
|
|
4
4
|
import { CheckIcon, CircleIcon, ChevronRightIcon, Monitor, Sun, Moon, Languages, Upload, Move, ZoomOut, ZoomIn, RotateCcw, RotateCw, Grid3X3, RefreshCw, X, XIcon, User, Pencil, Check, Loader2, Bell, CheckCheck, XCircle, AlertTriangle, CheckCircle, Info, Trash2 } from 'lucide-react';
|
|
5
|
-
import { AnimatePresence, motion } from 'motion
|
|
5
|
+
import { AnimatePresence, motion } from 'framer-motion';
|
|
6
6
|
import * as DropdownMenuPrimitive from '@radix-ui/react-dropdown-menu';
|
|
7
7
|
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
8
8
|
import { Slot } from '@radix-ui/react-slot';
|
|
@@ -3796,7 +3796,7 @@ function Toggle({
|
|
|
3796
3796
|
);
|
|
3797
3797
|
}
|
|
3798
3798
|
function AvatarEditor({
|
|
3799
|
-
value,
|
|
3799
|
+
value: _value,
|
|
3800
3800
|
onChange,
|
|
3801
3801
|
size = 280,
|
|
3802
3802
|
showGrid: initialShowGrid = false,
|
|
@@ -3804,14 +3804,11 @@ function AvatarEditor({
|
|
|
3804
3804
|
outputFormat = "png",
|
|
3805
3805
|
outputQuality = 0.92,
|
|
3806
3806
|
className,
|
|
3807
|
-
controlSize = "default"
|
|
3808
|
-
defaultImage,
|
|
3809
|
-
initials: _initials
|
|
3807
|
+
controlSize = "default"
|
|
3810
3808
|
}) {
|
|
3811
3809
|
const canvasRef = useRef(null);
|
|
3812
3810
|
const fileInputRef = useRef(null);
|
|
3813
3811
|
const containerRef = useRef(null);
|
|
3814
|
-
const imageSource = value ?? defaultImage;
|
|
3815
3812
|
const [image, setImage] = useState(null);
|
|
3816
3813
|
const [imageLoaded, setImageLoaded] = useState(false);
|
|
3817
3814
|
const [zoom, setZoom] = useState(1);
|
|
@@ -3820,83 +3817,17 @@ function AvatarEditor({
|
|
|
3820
3817
|
const [isDragging, setIsDragging] = useState(false);
|
|
3821
3818
|
const [dragStart, setDragStart] = useState({ x: 0, y: 0 });
|
|
3822
3819
|
const [showGrid, setShowGrid] = useState(initialShowGrid);
|
|
3823
|
-
useEffect(() => {
|
|
3824
|
-
if (imageSource) {
|
|
3825
|
-
const img = new Image();
|
|
3826
|
-
if (!imageSource.startsWith("data:")) {
|
|
3827
|
-
img.crossOrigin = "anonymous";
|
|
3828
|
-
}
|
|
3829
|
-
img.onload = () => {
|
|
3830
|
-
setImage(img);
|
|
3831
|
-
setImageLoaded(true);
|
|
3832
|
-
setZoom(1);
|
|
3833
|
-
setRotation(0);
|
|
3834
|
-
setPosition({ x: 0, y: 0 });
|
|
3835
|
-
};
|
|
3836
|
-
img.src = imageSource;
|
|
3837
|
-
} else {
|
|
3838
|
-
setImage(null);
|
|
3839
|
-
setImageLoaded(false);
|
|
3840
|
-
setZoom(1);
|
|
3841
|
-
setRotation(0);
|
|
3842
|
-
setPosition({ x: 0, y: 0 });
|
|
3843
|
-
}
|
|
3844
|
-
}, [imageSource]);
|
|
3845
3820
|
const generateOutput = useCallback(() => {
|
|
3846
|
-
if (!image) return null;
|
|
3821
|
+
if (!canvasRef.current || !image) return null;
|
|
3847
3822
|
const outputCanvas = document.createElement("canvas");
|
|
3848
3823
|
outputCanvas.width = outputSize;
|
|
3849
3824
|
outputCanvas.height = outputSize;
|
|
3850
3825
|
const ctx = outputCanvas.getContext("2d");
|
|
3851
3826
|
if (!ctx) return null;
|
|
3852
|
-
ctx.
|
|
3853
|
-
ctx.imageSmoothingQuality = "high";
|
|
3854
|
-
if (outputFormat === "jpeg") {
|
|
3855
|
-
ctx.fillStyle = "#ffffff";
|
|
3856
|
-
ctx.fillRect(0, 0, outputSize, outputSize);
|
|
3857
|
-
}
|
|
3858
|
-
ctx.imageSmoothingEnabled = true;
|
|
3859
|
-
ctx.imageSmoothingQuality = "high";
|
|
3860
|
-
ctx.save();
|
|
3861
|
-
ctx.translate(outputSize / 2, outputSize / 2);
|
|
3862
|
-
ctx.rotate(rotation * Math.PI / 180);
|
|
3863
|
-
const scale = zoom;
|
|
3864
|
-
const imgAspect = image.width / image.height;
|
|
3865
|
-
let drawWidth, drawHeight;
|
|
3866
|
-
if (imgAspect > 1) {
|
|
3867
|
-
drawHeight = outputSize * scale;
|
|
3868
|
-
drawWidth = drawHeight * imgAspect;
|
|
3869
|
-
} else {
|
|
3870
|
-
drawWidth = outputSize * scale;
|
|
3871
|
-
drawHeight = drawWidth / imgAspect;
|
|
3872
|
-
}
|
|
3873
|
-
const positionScale = outputSize / size;
|
|
3874
|
-
const scaledPosX = position.x * positionScale;
|
|
3875
|
-
const scaledPosY = position.y * positionScale;
|
|
3876
|
-
ctx.drawImage(
|
|
3877
|
-
image,
|
|
3878
|
-
-drawWidth / 2 + scaledPosX,
|
|
3879
|
-
-drawHeight / 2 + scaledPosY,
|
|
3880
|
-
drawWidth,
|
|
3881
|
-
drawHeight
|
|
3882
|
-
);
|
|
3883
|
-
ctx.restore();
|
|
3884
|
-
ctx.globalCompositeOperation = "destination-in";
|
|
3885
|
-
ctx.beginPath();
|
|
3886
|
-
ctx.arc(outputSize / 2, outputSize / 2, outputSize / 2, 0, Math.PI * 2);
|
|
3887
|
-
ctx.fill();
|
|
3827
|
+
ctx.drawImage(canvasRef.current, 0, 0, outputSize, outputSize);
|
|
3888
3828
|
const mimeType = `image/${outputFormat}`;
|
|
3889
3829
|
return outputCanvas.toDataURL(mimeType, outputQuality);
|
|
3890
|
-
}, [
|
|
3891
|
-
image,
|
|
3892
|
-
outputSize,
|
|
3893
|
-
outputFormat,
|
|
3894
|
-
outputQuality,
|
|
3895
|
-
zoom,
|
|
3896
|
-
rotation,
|
|
3897
|
-
position,
|
|
3898
|
-
size
|
|
3899
|
-
]);
|
|
3830
|
+
}, [image, outputSize, outputFormat, outputQuality]);
|
|
3900
3831
|
useEffect(() => {
|
|
3901
3832
|
if (!canvasRef.current || !image || !imageLoaded) return;
|
|
3902
3833
|
const canvas = canvasRef.current;
|
|
@@ -3906,8 +3837,8 @@ function AvatarEditor({
|
|
|
3906
3837
|
canvas.width = displaySize;
|
|
3907
3838
|
canvas.height = displaySize;
|
|
3908
3839
|
ctx.clearRect(0, 0, displaySize, displaySize);
|
|
3909
|
-
ctx.
|
|
3910
|
-
ctx.
|
|
3840
|
+
ctx.fillStyle = "#1a1a2e";
|
|
3841
|
+
ctx.fillRect(0, 0, displaySize, displaySize);
|
|
3911
3842
|
ctx.save();
|
|
3912
3843
|
ctx.translate(displaySize / 2, displaySize / 2);
|
|
3913
3844
|
ctx.rotate(rotation * Math.PI / 180);
|
|
@@ -4025,7 +3956,6 @@ function AvatarEditor({
|
|
|
4025
3956
|
const handleTouchMove = useCallback(
|
|
4026
3957
|
(e) => {
|
|
4027
3958
|
if (!isDragging) return;
|
|
4028
|
-
e.preventDefault();
|
|
4029
3959
|
const touch = e.touches[0];
|
|
4030
3960
|
setPosition({
|
|
4031
3961
|
x: touch.clientX - dragStart.x,
|
|
@@ -4608,13 +4538,14 @@ function DrawerDescription({
|
|
|
4608
4538
|
function useMediaQuery(query) {
|
|
4609
4539
|
const [matches, setMatches] = useState(false);
|
|
4610
4540
|
useEffect(() => {
|
|
4611
|
-
if (typeof window === "undefined") return;
|
|
4612
4541
|
const media = window.matchMedia(query);
|
|
4613
|
-
|
|
4542
|
+
if (media.matches !== matches) {
|
|
4543
|
+
setMatches(media.matches);
|
|
4544
|
+
}
|
|
4614
4545
|
const listener = () => setMatches(media.matches);
|
|
4615
4546
|
media.addEventListener("change", listener);
|
|
4616
4547
|
return () => media.removeEventListener("change", listener);
|
|
4617
|
-
}, [query]);
|
|
4548
|
+
}, [matches, query]);
|
|
4618
4549
|
return matches;
|
|
4619
4550
|
}
|
|
4620
4551
|
function AvatarEditorDialog({
|
|
@@ -4624,7 +4555,7 @@ function AvatarEditorDialog({
|
|
|
4624
4555
|
displaySize = 120,
|
|
4625
4556
|
editorSize = 280,
|
|
4626
4557
|
outputSize = 256,
|
|
4627
|
-
placeholder
|
|
4558
|
+
placeholder = "Add Photo",
|
|
4628
4559
|
editLabel = "Edit avatar",
|
|
4629
4560
|
dialogTitle = "Edit Avatar",
|
|
4630
4561
|
acceptText = "Accept",
|
|
@@ -4637,15 +4568,7 @@ function AvatarEditorDialog({
|
|
|
4637
4568
|
const [editedValue, setEditedValue] = useState(value ?? null);
|
|
4638
4569
|
const [isSaving, setIsSaving] = useState(false);
|
|
4639
4570
|
const [feedback, setFeedback] = useState(null);
|
|
4640
|
-
const [mobileEditorSize, setMobileEditorSize] = useState(editorSize);
|
|
4641
4571
|
const isMobile = useMediaQuery("(max-width: 640px)");
|
|
4642
|
-
useEffect(() => {
|
|
4643
|
-
if (typeof window !== "undefined" && isMobile) {
|
|
4644
|
-
setMobileEditorSize(Math.min(editorSize + 40, window.innerWidth - 48));
|
|
4645
|
-
} else {
|
|
4646
|
-
setMobileEditorSize(editorSize);
|
|
4647
|
-
}
|
|
4648
|
-
}, [isMobile, editorSize]);
|
|
4649
4572
|
const handleOpenChange = useCallback(
|
|
4650
4573
|
(open) => {
|
|
4651
4574
|
if (open) {
|
|
@@ -4664,6 +4587,7 @@ function AvatarEditorDialog({
|
|
|
4664
4587
|
if (onSave) {
|
|
4665
4588
|
const result = await onSave(editedValue);
|
|
4666
4589
|
if (result) {
|
|
4590
|
+
onChange?.(editedValue);
|
|
4667
4591
|
setFeedback({ type: "success", message: successMessage });
|
|
4668
4592
|
setTimeout(() => {
|
|
4669
4593
|
setIsOpen(false);
|
|
@@ -4704,7 +4628,10 @@ function AvatarEditorDialog({
|
|
|
4704
4628
|
alt: "Avatar",
|
|
4705
4629
|
className: "w-full h-full object-cover"
|
|
4706
4630
|
}
|
|
4707
|
-
) : /* @__PURE__ */
|
|
4631
|
+
) : /* @__PURE__ */ jsxs("div", { className: "flex flex-col items-center justify-center text-muted-foreground gap-1", children: [
|
|
4632
|
+
/* @__PURE__ */ jsx(User, { className: "w-1/3 h-1/3" }),
|
|
4633
|
+
/* @__PURE__ */ jsx("span", { className: "text-xs", children: placeholder })
|
|
4634
|
+
] })
|
|
4708
4635
|
}
|
|
4709
4636
|
),
|
|
4710
4637
|
/* @__PURE__ */ jsx(
|
|
@@ -4720,6 +4647,7 @@ function AvatarEditorDialog({
|
|
|
4720
4647
|
]
|
|
4721
4648
|
}
|
|
4722
4649
|
);
|
|
4650
|
+
const mobileEditorSize = isMobile ? Math.min(editorSize + 40, window.innerWidth - 48) : editorSize;
|
|
4723
4651
|
const EditorContent = /* @__PURE__ */ jsxs("div", { className: "flex flex-col items-center gap-4", children: [
|
|
4724
4652
|
/* @__PURE__ */ jsx(
|
|
4725
4653
|
AvatarEditor,
|