my-animated-components 1.4.0 → 1.4.2

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.ts CHANGED
@@ -458,24 +458,12 @@ interface OffcanvasHeaderProps extends BaseProps, WithChildren {
458
458
  declare const OffcanvasHeader: React$1.FC<OffcanvasHeaderProps>;
459
459
 
460
460
  type Color$5 = 'primary' | 'secondary' | 'success' | 'danger' | 'warning' | 'info';
461
- type PaginationSize = 'sm' | 'md' | 'lg';
462
- interface PaginationProps extends BaseProps, HTMLMotionProps<'nav'> {
461
+ interface PaginationProps extends BaseProps {
463
462
  currentPage: number;
464
463
  totalPages: number;
465
464
  onPageChange: (page: number) => void;
466
465
  color?: Color$5;
467
- size?: PaginationSize;
468
466
  motionVariant?: keyof typeof motionVariants;
469
- showFirstLast?: boolean;
470
- maxVisiblePages?: number;
471
- showPageNumbers?: boolean;
472
- previousLabel?: React$1.ReactNode;
473
- nextLabel?: React$1.ReactNode;
474
- firstLabel?: React$1.ReactNode;
475
- lastLabel?: React$1.ReactNode;
476
- buttonProps?: HTMLMotionProps<'button'>;
477
- activeButtonProps?: HTMLMotionProps<'button'>;
478
- disabledButtonProps?: HTMLMotionProps<'button'>;
479
467
  }
480
468
  declare const Pagination: React$1.FC<PaginationProps>;
481
469
 
@@ -607,4 +595,12 @@ interface TextProps extends BaseProps, WithChildren, SizeProps {
607
595
  }
608
596
  declare const Text: React$1.FC<TextProps>;
609
597
 
610
- export { Accordion, Alert, Avatar, Badge, Breadcrumb, Button, Card, CardBody, CardFooter, CardHeader, Checkbox, Container, Dropdown, DropdownItem, FileUpload, Flex, Grid, Heading, IconButton, Input, List, ListItem, Modal, ModalBody, ModalFooter, ModalHeader, NavItem, Navbar, Offcanvas, OffcanvasBody, OffcanvasHeader, Pagination, ProgressBar, Radio, RangeSlider, Select, Skeleton, Slider, Stepper, Switch, Table, TableBody, TableCell, TableHead, TableRow, Tabs, Text, Textarea, Tooltip, motionVariants };
598
+ interface ImageEditorProps {
599
+ imageFile: File;
600
+ onSave: (file: File) => void;
601
+ onCancel: () => void;
602
+ className?: string;
603
+ }
604
+ declare const ImageEditor: React$1.FC<ImageEditorProps>;
605
+
606
+ export { Accordion, Alert, Avatar, Badge, Breadcrumb, Button, Card, CardBody, CardFooter, CardHeader, Checkbox, Container, Dropdown, DropdownItem, FileUpload, Flex, Grid, Heading, IconButton, ImageEditor, Input, List, ListItem, Modal, ModalBody, ModalFooter, ModalHeader, NavItem, Navbar, Offcanvas, OffcanvasBody, OffcanvasHeader, Pagination, ProgressBar, Radio, RangeSlider, Select, Skeleton, Slider, Stepper, Switch, Table, TableBody, TableCell, TableHead, TableRow, Tabs, Text, Textarea, Tooltip, motionVariants };
package/dist/index.js CHANGED
@@ -2,6 +2,7 @@
2
2
 
3
3
  var React = require('react');
4
4
  var framerMotion = require('framer-motion');
5
+ var reactDom = require('react-dom');
5
6
 
6
7
  function getVariantVisible(variantKey) {
7
8
  const variant = motionVariants[variantKey]?.visible;
@@ -1132,24 +1133,12 @@ const OffcanvasHeader = ({ children, className = '', onClose }) => {
1132
1133
  React.createElement("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M6 18L18 6M6 6l12 12" })))));
1133
1134
  };
1134
1135
 
1135
- const Pagination = ({ className = '', currentPage, totalPages, onPageChange, color = 'primary', size = 'md', motionVariant = 'fadeIn', showFirstLast = false, maxVisiblePages = 5, showPageNumbers = true, previousLabel = 'Previous', nextLabel = 'Next', firstLabel = '«', lastLabel = '»', buttonProps = {}, activeButtonProps = {}, disabledButtonProps = {}, ...restProps }) => {
1136
- // Generate array of page numbers to display
1137
- const getPageRange = () => {
1138
- if (totalPages <= maxVisiblePages) {
1139
- return Array.from({ length: totalPages }, (_, i) => i + 1);
1140
- }
1141
- // Calculate the range to show
1142
- let startPage = Math.max(1, currentPage - Math.floor(maxVisiblePages / 2));
1143
- let endPage = startPage + maxVisiblePages - 1;
1144
- // Adjust if end page exceeds total pages
1145
- if (endPage > totalPages) {
1146
- endPage = totalPages;
1147
- startPage = Math.max(1, endPage - maxVisiblePages + 1);
1148
- }
1149
- return Array.from({ length: endPage - startPage + 1 }, (_, i) => startPage + i);
1150
- };
1151
- const pageNumbers = getPageRange();
1152
- // Color classes for different states
1136
+ const Pagination = ({ className = '', currentPage, totalPages, onPageChange, color = 'primary', motionVariant = 'fadeIn', // Default motion variant
1137
+ }) => {
1138
+ const pageNumbers = [];
1139
+ for (let i = 1; i <= totalPages; i++) {
1140
+ pageNumbers.push(i);
1141
+ }
1153
1142
  const colorClasses = {
1154
1143
  primary: 'text-blue-600 bg-blue-50 hover:bg-blue-100 hover:text-blue-700',
1155
1144
  secondary: 'text-gray-600 bg-gray-50 hover:bg-gray-100 hover:text-gray-700',
@@ -1158,88 +1147,16 @@ const Pagination = ({ className = '', currentPage, totalPages, onPageChange, col
1158
1147
  warning: 'text-yellow-600 bg-yellow-50 hover:bg-yellow-100 hover:text-yellow-700',
1159
1148
  info: 'text-blue-400 bg-blue-50 hover:bg-blue-100 hover:text-blue-500',
1160
1149
  };
1161
- // Size classes
1162
- const sizeClasses = {
1163
- sm: 'px-2 py-1 text-xs',
1164
- md: 'px-3 py-2 text-sm',
1165
- lg: 'px-4 py-3 text-base',
1166
- };
1167
- // Active page classes
1168
- const activeClasses = {
1169
- primary: 'bg-blue-600 text-white hover:bg-blue-700',
1170
- secondary: 'bg-gray-600 text-white hover:bg-gray-700',
1171
- success: 'bg-green-600 text-white hover:bg-green-700',
1172
- danger: 'bg-red-600 text-white hover:bg-red-700',
1173
- warning: 'bg-yellow-600 text-white hover:bg-yellow-700',
1174
- info: 'bg-blue-500 text-white hover:bg-blue-600',
1175
- };
1176
- // Base button classes
1177
- const baseButtonClasses = `
1178
- border border-gray-300
1179
- transition-colors duration-200 ease-in-out
1180
- focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500
1181
- ${sizeClasses[size]}
1182
- `;
1183
- return (React.createElement(framerMotion.motion.nav, { className: `flex flex-wrap justify-center ${className}`, variants: motionVariants[motionVariant], initial: "hidden", animate: "visible", transition: { duration: 0.5, staggerChildren: 0.05 }, ...restProps },
1184
- React.createElement("ul", { className: "flex flex-wrap items-center space-x-1 md:space-x-2" },
1185
- showFirstLast && (React.createElement("li", null,
1186
- React.createElement(framerMotion.motion.button, { onClick: () => onPageChange(1), disabled: currentPage === 1, className: `
1187
- ${baseButtonClasses}
1188
- ${colorClasses[color]}
1189
- rounded-l-lg md:rounded-lg
1190
- ${currentPage === 1 ? 'cursor-not-allowed opacity-50' : ''}
1191
- `, variants: motionVariants[motionVariant], initial: "hidden", animate: "visible", ...buttonProps, ...(currentPage === 1 ? disabledButtonProps : {}), "aria-label": "Go to first page" }, firstLabel))),
1150
+ return (React.createElement(framerMotion.motion.nav, { className: `flex justify-center ${className}`, initial: { opacity: 0, y: -50 }, animate: { opacity: 1, y: 0 }, transition: { duration: 0.5 }, variants: motionVariants[motionVariant] },
1151
+ React.createElement("ul", { className: "flex items-center -space-x-px" },
1192
1152
  React.createElement("li", null,
1193
- React.createElement(framerMotion.motion.button, { onClick: () => onPageChange(currentPage - 1), disabled: currentPage === 1, className: `
1194
- ${baseButtonClasses}
1195
- ${colorClasses[color]}
1196
- ${!showFirstLast ? 'rounded-l-lg' : ''}
1197
- ${currentPage === 1 ? 'cursor-not-allowed opacity-50' : ''}
1198
- hidden sm:block
1199
- `, variants: motionVariants[motionVariant], initial: "hidden", animate: "visible", ...buttonProps, ...(currentPage === 1 ? disabledButtonProps : {}), "aria-label": "Go to previous page" }, previousLabel),
1200
- React.createElement(framerMotion.motion.button, { onClick: () => onPageChange(currentPage - 1), disabled: currentPage === 1, className: `
1201
- ${baseButtonClasses}
1202
- ${colorClasses[color]}
1203
- ${!showFirstLast ? 'rounded-l-lg' : ''}
1204
- ${currentPage === 1 ? 'cursor-not-allowed opacity-50' : ''}
1205
- sm:hidden
1206
- `, variants: motionVariants[motionVariant], initial: "hidden", animate: "visible", ...buttonProps, ...(currentPage === 1 ? disabledButtonProps : {}), "aria-label": "Go to previous page" }, "<")),
1207
- showPageNumbers && pageNumbers.map((number) => (React.createElement("li", { key: number, className: "hidden sm:block" },
1208
- React.createElement(framerMotion.motion.button, { onClick: () => onPageChange(number), className: `
1209
- ${baseButtonClasses}
1210
- ${currentPage === number ? activeClasses[color] : colorClasses[color]}
1211
- `, variants: motionVariants[motionVariant], initial: "hidden", animate: "visible", ...buttonProps, ...(currentPage === number ? activeButtonProps : {}), "aria-label": `Page ${number}`, "aria-current": currentPage === number ? 'page' : undefined }, number)))),
1212
- React.createElement("li", { className: "block sm:hidden" },
1213
- React.createElement(framerMotion.motion.span, { className: `
1214
- ${baseButtonClasses}
1215
- ${activeClasses[color]}
1216
- flex items-center justify-center
1217
- `, variants: motionVariants[motionVariant], initial: "hidden", animate: "visible" },
1218
- currentPage,
1219
- " / ",
1220
- totalPages)),
1153
+ React.createElement(framerMotion.motion.button, { onClick: () => onPageChange(currentPage - 1), disabled: currentPage === 1, className: `block px-3 py-2 ml-0 leading-tight border border-gray-300 rounded-l-lg ${colorClasses[color]} ${currentPage === 1 && 'cursor-not-allowed opacity-50'}`, variants: motionVariants[motionVariant], initial: "hidden", animate: "visible" }, "Previous")),
1154
+ pageNumbers.map((number) => (React.createElement("li", { key: number },
1155
+ React.createElement(framerMotion.motion.button, { onClick: () => onPageChange(number), className: `px-3 py-2 leading-tight border border-gray-300 ${colorClasses[color]} ${currentPage === number
1156
+ ? 'bg-blue-100 text-blue-700 hover:bg-blue-200'
1157
+ : 'bg-white hover:bg-gray-100'}`, variants: motionVariants[motionVariant], initial: "hidden", animate: "visible" }, number)))),
1221
1158
  React.createElement("li", null,
1222
- React.createElement(framerMotion.motion.button, { onClick: () => onPageChange(currentPage + 1), disabled: currentPage === totalPages, className: `
1223
- ${baseButtonClasses}
1224
- ${colorClasses[color]}
1225
- ${!showFirstLast ? 'rounded-r-lg' : ''}
1226
- ${currentPage === totalPages ? 'cursor-not-allowed opacity-50' : ''}
1227
- hidden sm:block
1228
- `, variants: motionVariants[motionVariant], initial: "hidden", animate: "visible", ...buttonProps, ...(currentPage === totalPages ? disabledButtonProps : {}), "aria-label": "Go to next page" }, nextLabel),
1229
- React.createElement(framerMotion.motion.button, { onClick: () => onPageChange(currentPage + 1), disabled: currentPage === totalPages, className: `
1230
- ${baseButtonClasses}
1231
- ${colorClasses[color]}
1232
- ${!showFirstLast ? 'rounded-r-lg' : ''}
1233
- ${currentPage === totalPages ? 'cursor-not-allowed opacity-50' : ''}
1234
- sm:hidden
1235
- `, variants: motionVariants[motionVariant], initial: "hidden", animate: "visible", ...buttonProps, ...(currentPage === totalPages ? disabledButtonProps : {}), "aria-label": "Go to next page" }, ">")),
1236
- showFirstLast && (React.createElement("li", null,
1237
- React.createElement(framerMotion.motion.button, { onClick: () => onPageChange(totalPages), disabled: currentPage === totalPages, className: `
1238
- ${baseButtonClasses}
1239
- ${colorClasses[color]}
1240
- rounded-r-lg md:rounded-lg
1241
- ${currentPage === totalPages ? 'cursor-not-allowed opacity-50' : ''}
1242
- `, variants: motionVariants[motionVariant], initial: "hidden", animate: "visible", ...buttonProps, ...(currentPage === totalPages ? disabledButtonProps : {}), "aria-label": "Go to last page" }, lastLabel))))));
1159
+ React.createElement(framerMotion.motion.button, { onClick: () => onPageChange(currentPage + 1), disabled: currentPage === totalPages, className: `block px-3 py-2 leading-tight border border-gray-300 rounded-r-lg ${colorClasses[color]} ${currentPage === totalPages && 'cursor-not-allowed opacity-50'}`, variants: motionVariants[motionVariant], initial: "hidden", animate: "visible" }, "Next")))));
1243
1160
  };
1244
1161
 
1245
1162
  const ProgressBar = ({ className = '', value, max = 100, color = 'primary', heightClass = 'h-2.5', containerBgClass = 'bg-gray-200', barBgClass, motionVariant = 'fadeIn', duration = 0.5, loop = false, showLabel = false, labelClassName = 'text-xs font-medium text-gray-700 ml-2', ...rest }) => {
@@ -1493,6 +1410,544 @@ const Text = ({ children, className = '', size = 'md', weight = 'normal', ...res
1493
1410
  return (React.createElement("p", { ...rest, className: `${sizeClasses[size]} ${weightClasses[weight]} ${className}` }, children));
1494
1411
  };
1495
1412
 
1413
+ // Custom SVG Icons
1414
+ const CropIcon = ({ size = 16, className = "" }) => (React.createElement("svg", { width: size, height: size, viewBox: "0 0 24 24", fill: "none", className: className },
1415
+ React.createElement("path", { d: "M6 2V6H2", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" }),
1416
+ React.createElement("path", { d: "M18 2V6H22", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" }),
1417
+ React.createElement("path", { d: "M18 22V18H22", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" }),
1418
+ React.createElement("path", { d: "M6 22V18H2", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" }),
1419
+ React.createElement("rect", { x: "8", y: "8", width: "8", height: "8", stroke: "currentColor", strokeWidth: "2" })));
1420
+ const PaletteIcon = ({ size = 16, className = "" }) => (React.createElement("svg", { width: size, height: size, viewBox: "0 0 24 24", fill: "none", className: className },
1421
+ React.createElement("path", { d: "M12 2C13.1 2 14 2.9 14 4C14 5.1 13.1 6 12 6C10.9 6 10 5.1 10 4C10 2.9 10.9 2 12 2Z", stroke: "currentColor", strokeWidth: "2" }),
1422
+ React.createElement("path", { d: "M20 12C21.1 12 22 12.9 22 14C22 15.1 21.1 16 20 16C18.9 16 18 15.1 18 14C18 12.9 18.9 12 20 12Z", stroke: "currentColor", strokeWidth: "2" }),
1423
+ React.createElement("path", { d: "M4 12C5.1 12 6 12.9 6 14C6 15.1 5.1 16 4 16C2.9 16 2 15.1 2 14C2 12.9 2.9 12 4 12Z", stroke: "currentColor", strokeWidth: "2" }),
1424
+ React.createElement("path", { d: "M12 20C13.1 20 14 20.9 14 22C14 23.1 13.1 24 12 24C10.9 24 10 23.1 10 22C10 20.9 10.9 20 12 20Z", stroke: "currentColor", strokeWidth: "2" }),
1425
+ React.createElement("path", { d: "M7 7C8.1 7 9 7.9 9 9C9 10.1 8.1 11 7 11C5.9 11 5 10.1 5 9C5 7.9 5.9 7 7 7Z", stroke: "currentColor", strokeWidth: "2" }),
1426
+ React.createElement("path", { d: "M17 7C18.1 7 19 7.9 19 9C19 10.1 18.1 11 17 11C15.9 11 15 10.1 15 9C15 7.9 15.9 7 17 7Z", stroke: "currentColor", strokeWidth: "2" }),
1427
+ React.createElement("path", { d: "M7 17C8.1 17 9 17.9 9 19C9 20.1 8.1 21 7 21C5.9 21 5 20.1 5 19C5 17.9 5.9 17 7 17Z", stroke: "currentColor", strokeWidth: "2" }),
1428
+ React.createElement("path", { d: "M17 17C18.1 17 19 17.9 19 19C19 20.1 18.1 21 17 21C15.9 21 15 20.1 15 19C15 17.9 15.9 17 17 17Z", stroke: "currentColor", strokeWidth: "2" })));
1429
+ const SparklesIcon = ({ size = 16, className = "" }) => (React.createElement("svg", { width: size, height: size, viewBox: "0 0 24 24", fill: "none", className: className },
1430
+ React.createElement("path", { d: "M9.5 1L11 4.5L14.5 6L11 7.5L9.5 11L8 7.5L4.5 6L8 4.5L9.5 1Z", stroke: "currentColor", strokeWidth: "2" }),
1431
+ React.createElement("path", { d: "M17.5 8L18.5 10.5L21 11.5L18.5 12.5L17.5 15L16.5 12.5L14 11.5L16.5 10.5L17.5 8Z", stroke: "currentColor", strokeWidth: "2" }),
1432
+ React.createElement("path", { d: "M5.5 13L6.5 15.5L9 16.5L6.5 17.5L5.5 20L4.5 17.5L2 16.5L4.5 15.5L5.5 13Z", stroke: "currentColor", strokeWidth: "2" })));
1433
+ const RotateIcon = ({ size = 16, className = "" }) => (React.createElement("svg", { width: size, height: size, viewBox: "0 0 24 24", fill: "none", className: className },
1434
+ React.createElement("path", { d: "M23 4V10H17", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" }),
1435
+ React.createElement("path", { d: "M1 20V14H7", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" }),
1436
+ React.createElement("path", { d: "M3.51 9C4.01717 7.56678 4.87913 6.2854 6.01547 5.27542C7.1518 4.26543 8.52547 3.55976 10.0083 3.22426C11.4911 2.88875 13.0348 2.93434 14.4952 3.35677C15.9556 3.77921 17.2853 4.56471 18.36 5.64L23 10M1 14L5.64 18.36C6.71475 19.4353 8.04437 20.2208 9.50481 20.6432C10.9652 21.0657 12.5089 21.1113 13.9917 20.7757C15.4745 20.4402 16.8482 19.7346 17.9845 18.7246C19.1209 17.7146 19.9828 16.4332 20.49 15", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" })));
1437
+ const FlipHorizontalIcon = ({ size = 16, className = "" }) => (React.createElement("svg", { width: size, height: size, viewBox: "0 0 24 24", fill: "none", className: className },
1438
+ React.createElement("path", { d: "M3 12H21", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round" }),
1439
+ React.createElement("path", { d: "M12 3V21", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round" }),
1440
+ React.createElement("path", { d: "M7 7L3 12L7 17", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" }),
1441
+ React.createElement("path", { d: "M17 7L21 12L17 17", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" })));
1442
+ const FlipVerticalIcon = ({ size = 16, className = "" }) => (React.createElement("svg", { width: size, height: size, viewBox: "0 0 24 24", fill: "none", className: className },
1443
+ React.createElement("path", { d: "M12 3V21", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round" }),
1444
+ React.createElement("path", { d: "M3 12H21", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round" }),
1445
+ React.createElement("path", { d: "M7 7L12 3L17 7", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" }),
1446
+ React.createElement("path", { d: "M7 17L12 21L17 17", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" })));
1447
+ const ZoomInIcon = ({ size = 16, className = "" }) => (React.createElement("svg", { width: size, height: size, viewBox: "0 0 24 24", fill: "none", className: className },
1448
+ React.createElement("circle", { cx: "11", cy: "11", r: "8", stroke: "currentColor", strokeWidth: "2" }),
1449
+ React.createElement("path", { d: "M21 21L16.65 16.65", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round" }),
1450
+ React.createElement("path", { d: "M11 8V14", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round" }),
1451
+ React.createElement("path", { d: "M8 11H14", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round" })));
1452
+ const SunIcon = ({ size = 16, className = "" }) => (React.createElement("svg", { width: size, height: size, viewBox: "0 0 24 24", fill: "none", className: className },
1453
+ React.createElement("circle", { cx: "12", cy: "12", r: "5", stroke: "currentColor", strokeWidth: "2" }),
1454
+ React.createElement("path", { d: "M12 1V3", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round" }),
1455
+ React.createElement("path", { d: "M12 21V23", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round" }),
1456
+ React.createElement("path", { d: "M4.22 4.22L5.64 5.64", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round" }),
1457
+ React.createElement("path", { d: "M18.36 18.36L19.78 19.78", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round" }),
1458
+ React.createElement("path", { d: "M1 12H3", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round" }),
1459
+ React.createElement("path", { d: "M21 12H23", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round" }),
1460
+ React.createElement("path", { d: "M4.22 19.78L5.64 18.36", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round" }),
1461
+ React.createElement("path", { d: "M18.36 5.64L19.78 4.22", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round" })));
1462
+ const ContrastIcon = ({ size = 16, className = "" }) => (React.createElement("svg", { width: size, height: size, viewBox: "0 0 24 24", fill: "none", className: className },
1463
+ React.createElement("circle", { cx: "12", cy: "12", r: "10", stroke: "currentColor", strokeWidth: "2" }),
1464
+ React.createElement("path", { d: "M12 18C15.3137 18 18 15.3137 18 12C18 8.68629 15.3137 6 12 6C8.68629 6 6 8.68629 6 12C6 15.3137 8.68629 18 12 18Z", stroke: "currentColor", strokeWidth: "2" })));
1465
+ const DropletIcon = ({ size = 16, className = "" }) => (React.createElement("svg", { width: size, height: size, viewBox: "0 0 24 24", fill: "none", className: className },
1466
+ React.createElement("path", { d: "M12 22C16.4183 22 20 18.4183 20 14C20 8 12 2 12 2C12 2 4 8 4 14C4 18.4183 7.58172 22 12 22Z", stroke: "currentColor", strokeWidth: "2" })));
1467
+ const ApertureIcon = ({ size = 16, className = "" }) => (React.createElement("svg", { width: size, height: size, viewBox: "0 0 24 24", fill: "none", className: className },
1468
+ React.createElement("circle", { cx: "12", cy: "12", r: "10", stroke: "currentColor", strokeWidth: "2" }),
1469
+ React.createElement("path", { d: "M14.31 8L20.05 17.94", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round" }),
1470
+ React.createElement("path", { d: "M9.69 8L3.95 17.94", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round" }),
1471
+ React.createElement("path", { d: "M18.62 15L5.38 15", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round" }),
1472
+ React.createElement("path", { d: "M12 2V22", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round" })));
1473
+ const XIcon = ({ size = 16, className = "" }) => (React.createElement("svg", { width: size, height: size, viewBox: "0 0 24 24", fill: "none", className: className },
1474
+ React.createElement("path", { d: "M18 6L6 18", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" }),
1475
+ React.createElement("path", { d: "M6 6L18 18", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" })));
1476
+ const CheckIcon = ({ size = 16, className = "" }) => (React.createElement("svg", { width: size, height: size, viewBox: "0 0 24 24", fill: "none", className: className },
1477
+ React.createElement("path", { d: "M20 6L9 17L4 12", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" })));
1478
+ const ChevronLeftIcon = ({ size = 16, className = "" }) => (React.createElement("svg", { width: size, height: size, viewBox: "0 0 24 24", fill: "none", className: className },
1479
+ React.createElement("path", { d: "M15 18L9 12L15 6", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" })));
1480
+ const ChevronRightIcon = ({ size = 16, className = "" }) => (React.createElement("svg", { width: size, height: size, viewBox: "0 0 24 24", fill: "none", className: className },
1481
+ React.createElement("path", { d: "M9 18L15 12L9 6", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" })));
1482
+ const ImageEditor = ({ imageFile, onSave, onCancel, className = "" }) => {
1483
+ const canvasRef = React.useRef(null);
1484
+ const [activeTab, setActiveTab] = React.useState('crop');
1485
+ const [originalImage, setOriginalImage] = React.useState(null);
1486
+ const [isPanelOpen, setIsPanelOpen] = React.useState(true);
1487
+ const [cropArea, setCropArea] = React.useState({ x: 0, y: 0, width: 100, height: 100 });
1488
+ const [aspectRatio, setAspectRatio] = React.useState('free');
1489
+ const [isDragging, setIsDragging] = React.useState(false);
1490
+ const [dragStart, setDragStart] = React.useState({ x: 0, y: 0 });
1491
+ const [rotation, setRotation] = React.useState(0);
1492
+ const [flipH, setFlipH] = React.useState(false);
1493
+ const [flipV, setFlipV] = React.useState(false);
1494
+ const [zoom, setZoom] = React.useState(1);
1495
+ const [brightness, setBrightness] = React.useState(100);
1496
+ const [contrast, setContrast] = React.useState(100);
1497
+ const [saturation, setSaturation] = React.useState(100);
1498
+ const [blur, setBlur] = React.useState(0);
1499
+ const [hue, setHue] = React.useState(0);
1500
+ const [history, setHistory] = React.useState([]);
1501
+ const [historyIndex, setHistoryIndex] = React.useState(-1);
1502
+ const aspectRatios = [
1503
+ { id: 'free', label: 'Free', ratio: null },
1504
+ { id: '1:1', label: '1:1', ratio: 1 },
1505
+ { id: '16:9', label: '16:9 H', ratio: 16 / 9 },
1506
+ { id: '9:16', label: '9:16 V', ratio: 9 / 16 },
1507
+ { id: '4:3', label: '4:3 H', ratio: 4 / 3 },
1508
+ { id: '3:4', label: '3:4 V', ratio: 3 / 4 },
1509
+ { id: '4:5', label: '4:5 V', ratio: 4 / 5 },
1510
+ { id: '5:4', label: '5:4 H', ratio: 5 / 4 },
1511
+ ];
1512
+ const filters = [
1513
+ { id: 'none', name: 'Original', values: { brightness: 100, contrast: 100, saturation: 100, blur: 0, hue: 0 } },
1514
+ { id: 'vivid', name: 'Vivid', values: { brightness: 110, contrast: 120, saturation: 140, blur: 0, hue: 0 } },
1515
+ { id: 'warm', name: 'Warm', values: { brightness: 105, contrast: 105, saturation: 110, blur: 0, hue: 10 } },
1516
+ { id: 'cool', name: 'Cool', values: { brightness: 100, contrast: 110, saturation: 90, blur: 0, hue: -10 } },
1517
+ { id: 'bw', name: 'B&W', values: { brightness: 100, contrast: 120, saturation: 0, blur: 0, hue: 0 } },
1518
+ { id: 'vintage', name: 'Vintage', values: { brightness: 95, contrast: 90, saturation: 80, blur: 0.5, hue: 15 } },
1519
+ ];
1520
+ const getCurrentState = React.useCallback(() => ({
1521
+ rotation,
1522
+ flipH,
1523
+ flipV,
1524
+ zoom,
1525
+ brightness,
1526
+ contrast,
1527
+ saturation,
1528
+ blur,
1529
+ hue,
1530
+ cropArea
1531
+ }), [rotation, flipH, flipV, zoom, brightness, contrast, saturation, blur, hue, cropArea]);
1532
+ const saveToHistory = React.useCallback((state) => {
1533
+ const currentState = state || getCurrentState();
1534
+ const newHistory = history.slice(0, historyIndex + 1);
1535
+ newHistory.push(currentState);
1536
+ setHistory(newHistory);
1537
+ setHistoryIndex(newHistory.length - 1);
1538
+ }, [history, historyIndex, getCurrentState]);
1539
+ React.useCallback(() => {
1540
+ if (historyIndex > 0) {
1541
+ const prevState = history[historyIndex - 1];
1542
+ applyState(prevState);
1543
+ setHistoryIndex(historyIndex - 1);
1544
+ }
1545
+ }, [historyIndex, history]);
1546
+ React.useCallback(() => {
1547
+ if (historyIndex < history.length - 1) {
1548
+ const nextState = history[historyIndex + 1];
1549
+ applyState(nextState);
1550
+ setHistoryIndex(historyIndex + 1);
1551
+ }
1552
+ }, [historyIndex, history]);
1553
+ const applyState = React.useCallback((state) => {
1554
+ setRotation(state.rotation);
1555
+ setFlipH(state.flipH);
1556
+ setFlipV(state.flipV);
1557
+ setZoom(state.zoom);
1558
+ setBrightness(state.brightness);
1559
+ setContrast(state.contrast);
1560
+ setSaturation(state.saturation);
1561
+ setBlur(state.blur);
1562
+ setHue(state.hue);
1563
+ setCropArea(state.cropArea);
1564
+ }, []);
1565
+ // Initialize with first state
1566
+ React.useEffect(() => {
1567
+ if (imageFile && !originalImage) {
1568
+ const img = new Image();
1569
+ img.src = URL.createObjectURL(imageFile);
1570
+ img.onload = () => {
1571
+ setOriginalImage(img);
1572
+ const initialState = {
1573
+ rotation: 0,
1574
+ flipH: false,
1575
+ flipV: false,
1576
+ zoom: 1,
1577
+ brightness: 100,
1578
+ contrast: 100,
1579
+ saturation: 100,
1580
+ blur: 0,
1581
+ hue: 0,
1582
+ cropArea: { x: 0, y: 0, width: 100, height: 100 }
1583
+ };
1584
+ setHistory([initialState]);
1585
+ setHistoryIndex(0);
1586
+ drawCanvas(img);
1587
+ };
1588
+ }
1589
+ }, [imageFile, originalImage]);
1590
+ // Draw canvas when state changes
1591
+ React.useEffect(() => {
1592
+ if (originalImage) {
1593
+ drawCanvas(originalImage, getCurrentState());
1594
+ }
1595
+ }, [rotation, flipH, flipV, zoom, brightness, contrast, saturation, blur, hue, originalImage, getCurrentState]);
1596
+ const drawCanvas = (img, state) => {
1597
+ const canvas = canvasRef.current;
1598
+ if (!canvas || !img)
1599
+ return;
1600
+ const ctx = canvas.getContext("2d");
1601
+ if (!ctx)
1602
+ return;
1603
+ const maxWidth = 1200;
1604
+ const maxHeight = 800;
1605
+ let width = img.width;
1606
+ let height = img.height;
1607
+ if (width > maxWidth || height > maxHeight) {
1608
+ const ratio = Math.min(maxWidth / width, maxHeight / height);
1609
+ width *= ratio;
1610
+ height *= ratio;
1611
+ }
1612
+ canvas.width = width;
1613
+ canvas.height = height;
1614
+ ctx.save();
1615
+ ctx.clearRect(0, 0, canvas.width, canvas.height);
1616
+ ctx.filter = `brightness(${brightness}%) contrast(${contrast}%) saturate(${saturation}%) blur(${blur}px) hue-rotate(${hue}deg)`;
1617
+ ctx.translate(canvas.width / 2, canvas.height / 2);
1618
+ ctx.rotate((rotation * Math.PI) / 180);
1619
+ ctx.scale(flipH ? -1 : 1, flipV ? -1 : 1);
1620
+ ctx.scale(zoom, zoom);
1621
+ ctx.drawImage(img, -width / 2, -height / 2, width, height);
1622
+ ctx.restore();
1623
+ };
1624
+ const handleCropMouseDown = (e) => {
1625
+ if (activeTab !== 'crop')
1626
+ return;
1627
+ const canvas = canvasRef.current;
1628
+ if (!canvas)
1629
+ return;
1630
+ const rect = canvas.getBoundingClientRect();
1631
+ const x = ((e.clientX - rect.left) / rect.width) * 100;
1632
+ const y = ((e.clientY - rect.top) / rect.height) * 100;
1633
+ setIsDragging(true);
1634
+ setDragStart({ x, y });
1635
+ setCropArea({ x, y, width: 0, height: 0 });
1636
+ };
1637
+ const handleCropMouseMove = (e) => {
1638
+ if (!isDragging || activeTab !== 'crop')
1639
+ return;
1640
+ const canvas = canvasRef.current;
1641
+ if (!canvas)
1642
+ return;
1643
+ const rect = canvas.getBoundingClientRect();
1644
+ const x = ((e.clientX - rect.left) / rect.width) * 100;
1645
+ const y = ((e.clientY - rect.top) / rect.height) * 100;
1646
+ let width = x - dragStart.x;
1647
+ let height = y - dragStart.y;
1648
+ if (aspectRatio !== 'free') {
1649
+ const ratio = aspectRatios.find(r => r.id === aspectRatio)?.ratio;
1650
+ if (ratio) {
1651
+ const absWidth = Math.abs(width);
1652
+ height = (width < 0 ? -1 : 1) * (absWidth / ratio);
1653
+ }
1654
+ }
1655
+ setCropArea({
1656
+ x: width < 0 ? x : dragStart.x,
1657
+ y: height < 0 ? y : dragStart.y,
1658
+ width: Math.abs(width),
1659
+ height: Math.abs(height)
1660
+ });
1661
+ };
1662
+ const handleCropMouseUp = () => {
1663
+ setIsDragging(false);
1664
+ };
1665
+ const applyCrop = () => {
1666
+ const canvas = canvasRef.current;
1667
+ if (!canvas)
1668
+ return;
1669
+ const ctx = canvas.getContext('2d');
1670
+ if (!ctx)
1671
+ return;
1672
+ const cropX = (cropArea.x / 100) * canvas.width;
1673
+ const cropY = (cropArea.y / 100) * canvas.height;
1674
+ const cropWidth = (cropArea.width / 100) * canvas.width;
1675
+ const cropHeight = (cropArea.height / 100) * canvas.height;
1676
+ const imageData = ctx.getImageData(cropX, cropY, cropWidth, cropHeight);
1677
+ canvas.width = cropWidth;
1678
+ canvas.height = cropHeight;
1679
+ ctx.putImageData(imageData, 0, 0);
1680
+ setCropArea({ x: 0, y: 0, width: 100, height: 100 });
1681
+ // Save new state after crop
1682
+ const newState = {
1683
+ ...getCurrentState(),
1684
+ cropArea: { x: 0, y: 0, width: 100, height: 100 }
1685
+ };
1686
+ saveToHistory(newState);
1687
+ };
1688
+ const applyFilter = (filter) => {
1689
+ const newState = {
1690
+ ...getCurrentState(),
1691
+ brightness: filter.values.brightness,
1692
+ contrast: filter.values.contrast,
1693
+ saturation: filter.values.saturation,
1694
+ blur: filter.values.blur,
1695
+ hue: filter.values.hue
1696
+ };
1697
+ applyState(newState);
1698
+ saveToHistory(newState);
1699
+ };
1700
+ const handleSave = () => {
1701
+ const canvas = canvasRef.current;
1702
+ if (!canvas)
1703
+ return;
1704
+ canvas.toBlob((blob) => {
1705
+ if (blob) {
1706
+ const file = new File([blob], imageFile.name, { type: 'image/png' });
1707
+ onSave(file);
1708
+ }
1709
+ });
1710
+ };
1711
+ const handleSliderChange = (setter, value) => {
1712
+ setter(value);
1713
+ };
1714
+ const handleSliderChangeEnd = () => {
1715
+ saveToHistory();
1716
+ };
1717
+ const tabs = [
1718
+ { id: 'crop', label: 'Crop', icon: CropIcon },
1719
+ { id: 'adjust', label: 'Adjust', icon: PaletteIcon },
1720
+ { id: 'filters', label: 'Filters', icon: SparklesIcon },
1721
+ { id: 'transform', label: 'Transform', icon: RotateIcon }
1722
+ ];
1723
+ return reactDom.createPortal(React.createElement("div", { style: { position: 'fixed', inset: 0, zIndex: 50, display: 'flex', height: '100vh', width: '100vw', backgroundColor: '#0f0f0f' }, className: "dark" },
1724
+ React.createElement("div", { style: { flex: 1, display: 'flex', flexDirection: 'column' } },
1725
+ React.createElement("div", { style: { display: 'flex', alignItems: 'center', justifyContent: 'space-between', padding: '12px', borderBottom: '1px solid #2a2a2a', backgroundColor: '#1a1a1a' } },
1726
+ React.createElement("div", { style: { display: 'flex', alignItems: 'center', gap: '12px' } },
1727
+ React.createElement(ApertureIcon, { className: "text-blue-500" }),
1728
+ React.createElement("h2", { style: { fontSize: '14px', fontWeight: 600, color: '#ffffff' } }, "Image Editor")),
1729
+ React.createElement("div", { style: { display: 'flex', alignItems: 'center', gap: '4px' } },
1730
+ React.createElement("div", { style: { width: '1px', height: '20px', backgroundColor: '#2a2a2a', margin: '0 4px' } }),
1731
+ React.createElement("button", { onClick: handleSave, style: {
1732
+ padding: '6px 12px',
1733
+ borderRadius: '8px',
1734
+ backgroundColor: '#3b82f6',
1735
+ color: '#ffffff',
1736
+ border: 'none',
1737
+ cursor: 'pointer',
1738
+ fontSize: '14px',
1739
+ fontWeight: 500,
1740
+ display: 'flex',
1741
+ alignItems: 'center',
1742
+ gap: '6px'
1743
+ }, onMouseEnter: (e) => e.currentTarget.style.opacity = '0.9', onMouseLeave: (e) => e.currentTarget.style.opacity = '1' },
1744
+ React.createElement(CheckIcon, null),
1745
+ "Save"),
1746
+ React.createElement("button", { onClick: onCancel, style: {
1747
+ padding: '8px',
1748
+ borderRadius: '8px',
1749
+ backgroundColor: 'transparent',
1750
+ border: 'none',
1751
+ cursor: 'pointer',
1752
+ color: '#e5e5e5'
1753
+ }, onMouseEnter: (e) => { e.currentTarget.style.backgroundColor = 'rgba(239, 68, 68, 0.1)'; e.currentTarget.style.color = '#ef4444'; }, onMouseLeave: (e) => { e.currentTarget.style.backgroundColor = 'transparent'; e.currentTarget.style.color = '#e5e5e5'; }, title: "Cancel" },
1754
+ React.createElement(XIcon, null)))),
1755
+ React.createElement("div", { style: { flex: 1, display: 'flex', alignItems: 'center', justifyContent: 'center', padding: '16px', overflow: 'auto' } },
1756
+ React.createElement("div", { style: { position: 'relative' } },
1757
+ React.createElement("canvas", { ref: canvasRef, style: {
1758
+ maxWidth: '100%',
1759
+ maxHeight: 'calc(100vh - 12rem)',
1760
+ border: '1px solid #2a2a2a',
1761
+ borderRadius: '8px',
1762
+ boxShadow: '0 25px 50px -12px rgba(0, 0, 0, 0.5)',
1763
+ cursor: activeTab === 'crop' ? 'crosshair' : 'default'
1764
+ }, onMouseDown: handleCropMouseDown, onMouseMove: handleCropMouseMove, onMouseUp: handleCropMouseUp, onMouseLeave: handleCropMouseUp }),
1765
+ activeTab === 'crop' && cropArea.width > 0 && cropArea.height > 0 && (React.createElement("div", { style: {
1766
+ position: 'absolute',
1767
+ left: `${cropArea.x}%`,
1768
+ top: `${cropArea.y}%`,
1769
+ width: `${cropArea.width}%`,
1770
+ height: `${cropArea.height}%`,
1771
+ border: '2px solid #3b82f6',
1772
+ boxShadow: '0 0 0 9999px rgba(0,0,0,0.5)',
1773
+ pointerEvents: 'none'
1774
+ } },
1775
+ React.createElement("div", { style: { position: 'absolute', inset: 0, display: 'grid', gridTemplateColumns: 'repeat(3, 1fr)', gridTemplateRows: 'repeat(3, 1fr)' } }, [...Array(9)].map((_, i) => (React.createElement("div", { key: i, style: { border: '1px solid rgba(59, 130, 246, 0.3)' } })))))))),
1776
+ React.createElement("div", { style: { borderTop: '1px solid #2a2a2a', backgroundColor: '#1a1a1a', padding: '12px' } },
1777
+ React.createElement("div", { style: { display: 'flex', alignItems: 'center', gap: '8px', overflowX: 'auto' } }, tabs.map(tab => (React.createElement("button", { key: tab.id, onClick: () => setActiveTab(tab.id), style: {
1778
+ display: 'flex',
1779
+ alignItems: 'center',
1780
+ gap: '6px',
1781
+ padding: '6px 12px',
1782
+ borderRadius: '8px',
1783
+ backgroundColor: activeTab === tab.id ? '#3b82f6' : 'transparent',
1784
+ color: activeTab === tab.id ? '#ffffff' : '#e5e5e5',
1785
+ border: 'none',
1786
+ cursor: 'pointer',
1787
+ fontSize: '14px',
1788
+ fontWeight: 500,
1789
+ whiteSpace: 'nowrap'
1790
+ }, onMouseEnter: (e) => { if (activeTab !== tab.id)
1791
+ e.currentTarget.style.backgroundColor = '#2a2a2a'; }, onMouseLeave: (e) => { if (activeTab !== tab.id)
1792
+ e.currentTarget.style.backgroundColor = 'transparent'; } },
1793
+ React.createElement(tab.icon, null),
1794
+ tab.label)))))),
1795
+ React.createElement(framerMotion.AnimatePresence, null, isPanelOpen && (React.createElement(framerMotion.motion.div, { initial: { width: 0, opacity: 0 }, animate: { width: 280, opacity: 1 }, exit: { width: 0, opacity: 0 }, transition: { duration: 0.2 }, style: { borderLeft: '1px solid #2a2a2a', backgroundColor: '#1a1a1a', overflow: 'hidden' } },
1796
+ React.createElement("div", { style: { width: 280, height: '100%', overflowY: 'auto', padding: '16px' } },
1797
+ React.createElement(framerMotion.AnimatePresence, { mode: "wait" },
1798
+ activeTab === 'crop' && (React.createElement(framerMotion.motion.div, { key: "crop", initial: { opacity: 0, x: 10 }, animate: { opacity: 1, x: 0 }, exit: { opacity: 0, x: -10 }, style: { display: 'flex', flexDirection: 'column', gap: '12px' } },
1799
+ React.createElement("div", null,
1800
+ React.createElement("label", { style: { fontSize: '12px', fontWeight: 500, marginBottom: '8px', display: 'block', color: '#e5e5e5' } }, "Aspect Ratio"),
1801
+ React.createElement("div", { style: { display: 'grid', gridTemplateColumns: 'repeat(3, 1fr)', gap: '6px' } }, aspectRatios.map(ratio => (React.createElement("button", { key: ratio.id, onClick: () => setAspectRatio(ratio.id), style: {
1802
+ padding: '6px 8px',
1803
+ borderRadius: '6px',
1804
+ fontSize: '12px',
1805
+ fontWeight: 500,
1806
+ backgroundColor: aspectRatio === ratio.id ? '#3b82f6' : '#2a2a2a',
1807
+ color: aspectRatio === ratio.id ? '#ffffff' : '#e5e5e5',
1808
+ border: 'none',
1809
+ cursor: 'pointer'
1810
+ }, onMouseEnter: (e) => { if (aspectRatio !== ratio.id)
1811
+ e.currentTarget.style.backgroundColor = '#3a3a3a'; }, onMouseLeave: (e) => { if (aspectRatio !== ratio.id)
1812
+ e.currentTarget.style.backgroundColor = '#2a2a2a'; } }, ratio.label))))),
1813
+ cropArea.width > 0 && (React.createElement("button", { onClick: applyCrop, style: {
1814
+ width: '100%',
1815
+ backgroundColor: '#3b82f6',
1816
+ color: '#ffffff',
1817
+ padding: '8px 12px',
1818
+ borderRadius: '8px',
1819
+ fontSize: '14px',
1820
+ fontWeight: 500,
1821
+ border: 'none',
1822
+ cursor: 'pointer',
1823
+ display: 'flex',
1824
+ alignItems: 'center',
1825
+ justifyContent: 'center',
1826
+ gap: '6px'
1827
+ }, onMouseEnter: (e) => e.currentTarget.style.opacity = '0.9', onMouseLeave: (e) => e.currentTarget.style.opacity = '1' },
1828
+ React.createElement(CropIcon, null),
1829
+ "Apply Crop")))),
1830
+ activeTab === 'adjust' && (React.createElement(framerMotion.motion.div, { key: "adjust", initial: { opacity: 0, x: 10 }, animate: { opacity: 1, x: 0 }, exit: { opacity: 0, x: -10 }, style: { display: 'flex', flexDirection: 'column', gap: '12px' } },
1831
+ React.createElement(SliderControl, { icon: React.createElement(SunIcon, { className: "text-yellow-500" }), label: "Brightness", value: brightness, onChange: (value) => handleSliderChange(setBrightness, value), onChangeEnd: handleSliderChangeEnd, min: 0, max: 200, unit: "%" }),
1832
+ React.createElement(SliderControl, { icon: React.createElement(ContrastIcon, { className: "text-purple-500" }), label: "Contrast", value: contrast, onChange: (value) => handleSliderChange(setContrast, value), onChangeEnd: handleSliderChangeEnd, min: 0, max: 200, unit: "%" }),
1833
+ React.createElement(SliderControl, { icon: React.createElement(DropletIcon, { className: "text-blue-500" }), label: "Saturation", value: saturation, onChange: (value) => handleSliderChange(setSaturation, value), onChangeEnd: handleSliderChangeEnd, min: 0, max: 200, unit: "%" }),
1834
+ React.createElement(SliderControl, { icon: React.createElement(ApertureIcon, { className: "text-gray-500" }), label: "Blur", value: blur, onChange: (value) => handleSliderChange(setBlur, value), onChangeEnd: handleSliderChangeEnd, min: 0, max: 10, step: 0.1, unit: "px" }),
1835
+ React.createElement(SliderControl, { icon: React.createElement(PaletteIcon, { className: "text-pink-500" }), label: "Hue", value: hue, onChange: (value) => handleSliderChange(setHue, value), onChangeEnd: handleSliderChangeEnd, min: -180, max: 180, unit: "\u00B0" }))),
1836
+ activeTab === 'filters' && (React.createElement(framerMotion.motion.div, { key: "filters", initial: { opacity: 0, x: 10 }, animate: { opacity: 1, x: 0 }, exit: { opacity: 0, x: -10 }, style: { display: 'flex', flexDirection: 'column', gap: '6px' } }, filters.map(filter => (React.createElement("button", { key: filter.id, onClick: () => applyFilter(filter), style: {
1837
+ width: '100%',
1838
+ textAlign: 'left',
1839
+ padding: '8px 12px',
1840
+ borderRadius: '8px',
1841
+ backgroundColor: '#2a2a2a',
1842
+ color: '#e5e5e5',
1843
+ border: 'none',
1844
+ cursor: 'pointer',
1845
+ fontSize: '14px',
1846
+ fontWeight: 500
1847
+ }, onMouseEnter: (e) => e.currentTarget.style.backgroundColor = '#3a3a3a', onMouseLeave: (e) => e.currentTarget.style.backgroundColor = '#2a2a2a' }, filter.name))))),
1848
+ activeTab === 'transform' && (React.createElement(framerMotion.motion.div, { key: "transform", initial: { opacity: 0, x: 10 }, animate: { opacity: 1, x: 0 }, exit: { opacity: 0, x: -10 }, style: { display: 'flex', flexDirection: 'column', gap: '12px' } },
1849
+ React.createElement(SliderControl, { icon: React.createElement(RotateIcon, null), label: "Rotation", value: rotation, onChange: (value) => handleSliderChange(setRotation, value), onChangeEnd: handleSliderChangeEnd, min: 0, max: 360, unit: "\u00B0" }),
1850
+ React.createElement("div", { style: { display: 'flex', gap: '8px' } },
1851
+ React.createElement("button", { onClick: () => {
1852
+ setFlipH(!flipH);
1853
+ handleSliderChangeEnd();
1854
+ }, style: {
1855
+ flex: 1,
1856
+ padding: '8px 12px',
1857
+ borderRadius: '8px',
1858
+ fontSize: '14px',
1859
+ fontWeight: 500,
1860
+ backgroundColor: flipH ? '#3b82f6' : '#2a2a2a',
1861
+ color: flipH ? '#ffffff' : '#e5e5e5',
1862
+ border: 'none',
1863
+ cursor: 'pointer',
1864
+ display: 'flex',
1865
+ alignItems: 'center',
1866
+ justifyContent: 'center',
1867
+ gap: '6px'
1868
+ }, onMouseEnter: (e) => { if (!flipH)
1869
+ e.currentTarget.style.backgroundColor = '#3a3a3a'; }, onMouseLeave: (e) => { if (!flipH)
1870
+ e.currentTarget.style.backgroundColor = '#2a2a2a'; } },
1871
+ React.createElement(FlipHorizontalIcon, null),
1872
+ "Flip H"),
1873
+ React.createElement("button", { onClick: () => {
1874
+ setFlipV(!flipV);
1875
+ handleSliderChangeEnd();
1876
+ }, style: {
1877
+ flex: 1,
1878
+ padding: '8px 12px',
1879
+ borderRadius: '8px',
1880
+ fontSize: '14px',
1881
+ fontWeight: 500,
1882
+ backgroundColor: flipV ? '#3b82f6' : '#2a2a2a',
1883
+ color: flipV ? '#ffffff' : '#e5e5e5',
1884
+ border: 'none',
1885
+ cursor: 'pointer',
1886
+ display: 'flex',
1887
+ alignItems: 'center',
1888
+ justifyContent: 'center',
1889
+ gap: '6px'
1890
+ }, onMouseEnter: (e) => { if (!flipV)
1891
+ e.currentTarget.style.backgroundColor = '#3a3a3a'; }, onMouseLeave: (e) => { if (!flipV)
1892
+ e.currentTarget.style.backgroundColor = '#2a2a2a'; } },
1893
+ React.createElement(FlipVerticalIcon, null),
1894
+ "Flip V")),
1895
+ React.createElement(SliderControl, { icon: React.createElement(ZoomInIcon, null), label: "Zoom", value: zoom, onChange: (value) => handleSliderChange(setZoom, value), onChangeEnd: handleSliderChangeEnd, min: 0.5, max: 3, step: 0.1, unit: "x" })))))))),
1896
+ React.createElement("button", { onClick: () => setIsPanelOpen(!isPanelOpen), style: {
1897
+ position: 'absolute',
1898
+ right: isPanelOpen ? '280px' : '0',
1899
+ top: '50%',
1900
+ transform: 'translateY(-50%)',
1901
+ backgroundColor: '#1a1a1a',
1902
+ border: '1px solid #2a2a2a',
1903
+ borderTopLeftRadius: '8px',
1904
+ borderBottomLeftRadius: '8px',
1905
+ padding: '4px',
1906
+ cursor: 'pointer',
1907
+ color: '#e5e5e5'
1908
+ }, onMouseEnter: (e) => e.currentTarget.style.backgroundColor = '#2a2a2a', onMouseLeave: (e) => e.currentTarget.style.backgroundColor = '#1a1a1a' }, isPanelOpen ? React.createElement(ChevronRightIcon, null) : React.createElement(ChevronLeftIcon, null))), document.body);
1909
+ };
1910
+ const SliderControl = ({ icon, label, value, onChange, onChangeEnd, min, max, step = 1, unit }) => {
1911
+ return (React.createElement("div", null,
1912
+ React.createElement("div", { style: { display: 'flex', alignItems: 'center', justifyContent: 'space-between', marginBottom: '6px' } },
1913
+ React.createElement("label", { style: { fontSize: '12px', fontWeight: 500, display: 'flex', alignItems: 'center', gap: '6px', color: '#e5e5e5' } },
1914
+ icon,
1915
+ label),
1916
+ React.createElement("span", { style: { fontSize: '12px', color: '#a3a3a3' } },
1917
+ Math.round(value * 10) / 10,
1918
+ unit)),
1919
+ React.createElement("input", { type: "range", min: min, max: max, step: step, value: value, onChange: (e) => onChange(Number(e.target.value)), onMouseUp: onChangeEnd, onTouchEnd: onChangeEnd, style: {
1920
+ width: '100%',
1921
+ height: '6px',
1922
+ backgroundColor: '#2a2a2a',
1923
+ borderRadius: '8px',
1924
+ outline: 'none',
1925
+ cursor: 'pointer',
1926
+ WebkitAppearance: 'none',
1927
+ MozAppearance: 'none',
1928
+ appearance: 'none'
1929
+ } }),
1930
+ React.createElement("style", null, `
1931
+ input[type="range"]::-webkit-slider-thumb {
1932
+ -webkit-appearance: none;
1933
+ appearance: none;
1934
+ width: 14px;
1935
+ height: 14px;
1936
+ border-radius: 50%;
1937
+ background: #3b82f6;
1938
+ cursor: pointer;
1939
+ }
1940
+ input[type="range"]::-moz-range-thumb {
1941
+ width: 14px;
1942
+ height: 14px;
1943
+ border-radius: 50%;
1944
+ background: #3b82f6;
1945
+ cursor: pointer;
1946
+ border: none;
1947
+ }
1948
+ `)));
1949
+ };
1950
+
1496
1951
  exports.Accordion = Accordion;
1497
1952
  exports.Alert = Alert;
1498
1953
  exports.Avatar = Avatar;
@@ -1512,6 +1967,7 @@ exports.Flex = Flex;
1512
1967
  exports.Grid = Grid;
1513
1968
  exports.Heading = Heading;
1514
1969
  exports.IconButton = IconButton;
1970
+ exports.ImageEditor = ImageEditor;
1515
1971
  exports.Input = Input;
1516
1972
  exports.List = List;
1517
1973
  exports.ListItem = ListItem;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "my-animated-components",
3
- "version": "1.4.0",
3
+ "version": "1.4.2",
4
4
  "type": "module",
5
5
  "description": "",
6
6
  "main": "dist/index.js",