@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.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, defaultImage, initials: _initials, }: AvatarEditorProps): react_jsx_runtime.JSX.Element;
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: _placeholder, editLabel, dialogTitle, acceptText, cancelText, successMessage, errorMessage, className, }: AvatarEditorDialogProps): react_jsx_runtime.JSX.Element;
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, defaultImage, initials: _initials, }: AvatarEditorProps): react_jsx_runtime.JSX.Element;
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: _placeholder, editLabel, dialogTitle, acceptText, cancelText, successMessage, errorMessage, className, }: AvatarEditorDialogProps): react_jsx_runtime.JSX.Element;
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/react';
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.imageSmoothingEnabled = true;
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.imageSmoothingEnabled = true;
3910
- ctx.imageSmoothingQuality = "high";
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
- setMatches(media.matches);
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: _placeholder = "Add Photo",
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__ */ jsx("div", { className: "flex items-center justify-center text-muted-foreground", children: /* @__PURE__ */ jsx(User, { className: "w-10 h-10" }) })
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,