@sustaina/shared-ui 1.13.2 → 1.14.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.
package/dist/index.mjs CHANGED
@@ -8138,6 +8138,31 @@ function SidebarLayout({
8138
8138
  ] }) });
8139
8139
  }
8140
8140
 
8141
+ // src/components/cropperModal/type.ts
8142
+ var CropperModalError = class extends Error {
8143
+ constructor(errorType, message) {
8144
+ super(message);
8145
+ this.error = errorType;
8146
+ }
8147
+ };
8148
+ var ErrorGeneratingBlob = new CropperModalError(
8149
+ "ERROR_GENERATE_BLOB",
8150
+ "failed to generate a valid Blob"
8151
+ );
8152
+ var ErrorCreateCanvas = new CropperModalError("ERROR_CREATE_CANVAS", "Failed to create canvas");
8153
+ var ErrorInvalidSVG = new CropperModalError(
8154
+ "ERROR_INVALID_SVG",
8155
+ "The file is not a valid SVG document root"
8156
+ );
8157
+ var ErrorCompression = new CropperModalError(
8158
+ "ERROR_COMPRESSION",
8159
+ "Compression failed to generate a valid Blob"
8160
+ );
8161
+ var ErrorSVGExceedSize = new CropperModalError(
8162
+ "ERROR_SVG_EXCEED_SIZE",
8163
+ "The SVG file is too large"
8164
+ );
8165
+
8141
8166
  // src/components/cropperModal/helper.ts
8142
8167
  var createImage = (url) => new Promise((resolve, reject) => {
8143
8168
  const image = new Image();
@@ -8146,12 +8171,38 @@ var createImage = (url) => new Promise((resolve, reject) => {
8146
8171
  image.setAttribute("crossOrigin", "anonymous");
8147
8172
  image.src = url;
8148
8173
  });
8149
- async function getCroppedImg(imageSrc, pixelCrop, desiredDimension) {
8174
+ function toBlobPromise(canvas, quality) {
8175
+ return new Promise((resolve) => {
8176
+ canvas.toBlob((blob) => resolve(blob), "image/jpeg", quality);
8177
+ });
8178
+ }
8179
+ async function resizeImage(canvas, targetSizeKB) {
8180
+ const targetSizeBytes = targetSizeKB * 1024;
8181
+ let quality = 1;
8182
+ const qualityStep = 0.05;
8183
+ let compressedBlob = null;
8184
+ let currentSize = Infinity;
8185
+ while (currentSize > targetSizeBytes && quality > 0) {
8186
+ compressedBlob = await toBlobPromise(canvas, quality);
8187
+ if (compressedBlob === null) {
8188
+ throw ErrorCompression;
8189
+ }
8190
+ currentSize = compressedBlob.size;
8191
+ if (currentSize > targetSizeBytes) {
8192
+ quality = Math.max(0, quality - qualityStep);
8193
+ }
8194
+ }
8195
+ if (compressedBlob && currentSize <= targetSizeBytes) {
8196
+ return URL.createObjectURL(compressedBlob);
8197
+ }
8198
+ throw ErrorCompression;
8199
+ }
8200
+ async function getCroppedImg(imageSrc, pixelCrop, desiredDimension, targetSizeKB = Infinity) {
8150
8201
  const image = await createImage(imageSrc);
8151
8202
  const canvas = document.createElement("canvas");
8152
8203
  const ctx = canvas.getContext("2d");
8153
8204
  if (!ctx) {
8154
- throw new Error("can not create canvas");
8205
+ throw ErrorCreateCanvas;
8155
8206
  }
8156
8207
  canvas.width = image.width;
8157
8208
  canvas.height = image.height;
@@ -8159,7 +8210,7 @@ async function getCroppedImg(imageSrc, pixelCrop, desiredDimension) {
8159
8210
  const croppedCanvas = document.createElement("canvas");
8160
8211
  const croppedCtx = croppedCanvas.getContext("2d");
8161
8212
  if (!croppedCtx) {
8162
- throw new Error("can not create canvas");
8213
+ throw ErrorCreateCanvas;
8163
8214
  }
8164
8215
  croppedCanvas.width = desiredDimension?.width ?? pixelCrop.width;
8165
8216
  croppedCanvas.height = desiredDimension?.height ?? pixelCrop.height;
@@ -8174,17 +8225,9 @@ async function getCroppedImg(imageSrc, pixelCrop, desiredDimension) {
8174
8225
  desiredDimension?.width ?? pixelCrop.width,
8175
8226
  desiredDimension?.height ?? pixelCrop.height
8176
8227
  );
8177
- return new Promise((resolve, reject) => {
8178
- croppedCanvas.toBlob((file) => {
8179
- if (file) {
8180
- resolve(URL.createObjectURL(file));
8181
- } else {
8182
- reject("croppedCanvas gave null object");
8183
- }
8184
- }, "image/png");
8185
- });
8228
+ return resizeImage(croppedCanvas, targetSizeKB);
8186
8229
  }
8187
- async function getCroppedSVG(imageSrc, pixelCrop, desiredDimension) {
8230
+ async function getCroppedSVG(imageSrc, pixelCrop, desiredDimension, targetSizeKB = Infinity) {
8188
8231
  let svgString;
8189
8232
  const parts = imageSrc.split(",");
8190
8233
  const meta = parts[0];
@@ -8198,7 +8241,7 @@ async function getCroppedSVG(imageSrc, pixelCrop, desiredDimension) {
8198
8241
  const svgDoc = parser.parseFromString(svgString, "image/svg+xml");
8199
8242
  const svgElement = svgDoc.documentElement;
8200
8243
  if (svgElement.tagName.toLowerCase() !== "svg") {
8201
- throw new Error("The file is not a valid SVG document root.");
8244
+ throw ErrorInvalidSVG;
8202
8245
  }
8203
8246
  const newViewBox = `${pixelCrop.x} ${pixelCrop.y} ${pixelCrop.width} ${pixelCrop.height}`;
8204
8247
  svgElement.setAttribute("viewBox", newViewBox);
@@ -8209,6 +8252,10 @@ async function getCroppedSVG(imageSrc, pixelCrop, desiredDimension) {
8209
8252
  const serializer = new XMLSerializer();
8210
8253
  const croppedSvgString = serializer.serializeToString(svgElement);
8211
8254
  const blob = new Blob([croppedSvgString], { type: "image/svg+xml" });
8255
+ const targetSizeBytes = targetSizeKB * 1024;
8256
+ if (blob.size > targetSizeBytes) {
8257
+ throw ErrorSVGExceedSize;
8258
+ }
8212
8259
  return URL.createObjectURL(blob);
8213
8260
  }
8214
8261
  var CropperModal = ({
@@ -8221,6 +8268,7 @@ var CropperModal = ({
8221
8268
  onError,
8222
8269
  cropSize,
8223
8270
  outputExactCropSize,
8271
+ targetFileSizeKB,
8224
8272
  generateBlobUrlOutput,
8225
8273
  title,
8226
8274
  props
@@ -8257,7 +8305,7 @@ var CropperModal = ({
8257
8305
  setIsLoading(true);
8258
8306
  try {
8259
8307
  const desiredDimension = outputExactCropSize ? cropSize : void 0;
8260
- const croppedImage = isSVG ? await getCroppedSVG(imageSrc, croppedAreaPixels, desiredDimension) : await getCroppedImg(imageSrc, croppedAreaPixels, desiredDimension);
8308
+ const croppedImage = isSVG ? await getCroppedSVG(imageSrc, croppedAreaPixels, desiredDimension, targetFileSizeKB) : await getCroppedImg(imageSrc, croppedAreaPixels, desiredDimension, targetFileSizeKB);
8261
8309
  onConfirm({ crop, croppedAreaPixels, croppedImageBlobUrl: croppedImage });
8262
8310
  } catch (e) {
8263
8311
  if (onError) {
@@ -8333,6 +8381,6 @@ var CropperModal = ({
8333
8381
  );
8334
8382
  };
8335
8383
 
8336
- export { Accordion, AccordionContent, AccordionItem, AccordionTrigger, AdvanceSearch_default as AdvanceSearch, arrow_default as ArrowIcon, Button, Checkbox, Collapsible, CollapsibleContent2 as CollapsibleContent, CollapsibleTrigger2 as CollapsibleTrigger, CropperModal, DIALOG_ALERT_I18N_NAMESPACE, DataTable_default as DataTable, DatePicker2 as DatePicker, Dialog, DialogAlert, DialogAlertProvider, DialogContent, DialogDescription, DialogFooter, DialogTitle, DialogTrigger, Form, FormControl, FormDescription, FormField, FormItem, FormLabel, FormMessage, GridSettingsModal_default as GridSettingsModal, HeaderCell_default as HeaderCell, Input, Label2 as Label, List_default as List, container_default as ListContainer, header_default as ListHeader, table_default as ListTable, LookupSelect, MonthPicker2 as MonthPicker, navbar_default as Navbar, not_found_default as NotFoundIcon, Popover, PopoverAnchor, PopoverArrow, PopoverContent, PopoverTrigger, PreventPageLeave_default as PreventPageLeave, RadioGroupItem, RadioGroupRoot, RadioLabel, RichText, Select, SelectContent, SelectGroup, SelectItem, SelectLabel, SelectScrollDownButton, SelectScrollUpButton, SelectSeparator, SelectTrigger, SelectValue, Separator2 as Separator, Sheet, SheetClose, SheetContent, SheetDescription, SheetFooter, SheetHeader, SheetTitle, SheetTrigger, Sidebar, SidebarContent, SidebarFooter, SidebarGroup, SidebarGroupAction, SidebarGroupContent, SidebarGroupLabel, SidebarHeader, SidebarInput, SidebarInset, SidebarLayout, SidebarMenu, SidebarMenuAction, SidebarMenuBadge, SidebarMenuButton, SidebarMenuItem, SidebarMenuSkeleton, SidebarMenuSub, SidebarMenuSubButton, SidebarMenuSubItem, SidebarProvider, SidebarRail, SidebarSeparator, SidebarTrigger, Skeleton, calendar_default as SuiCalendarIcon, check_default as SuiCheckIcon, dots_vertical_default as SuiDotsVerticalIcon, empty_data_default as SuiEmptyDataIcon, expand_default as SuiExpandIcon, filter_default as SuiFilterIcon, setting_default as SuiSettingIcon, triangle_down_default as SuiTriangleDownIcon, warning_default as SuiWarningIcon, Switch, Textarea, Tooltip, TooltipArrow, TooltipContent, TooltipProvider, TooltipTrigger, ui_exports as UI, booleanToSelectValue, buttonVariants, cn, compareAlphanumeric, debounce, getDialogAlertControls, getDialogTemplates, inputVariants, isDefined, isEmptyObject, selectValueToBoolean, stripNullishObject, throttle, useFormField, useGridSettingsStore_default as useGridSettingsStore, useHover_default as useHover, useIntersectionObserver_default as useIntersectionObserver, useMediaQuery_default as useMediaQuery, usePreventPageLeave_default as usePreventPageLeave, usePreventPageLeaveStore_default as usePreventPageLeaveStore, useScreenSize_default as useScreenSize, useSidebar, useTruncated_default as useTruncated };
8384
+ export { Accordion, AccordionContent, AccordionItem, AccordionTrigger, AdvanceSearch_default as AdvanceSearch, arrow_default as ArrowIcon, Button, Checkbox, Collapsible, CollapsibleContent2 as CollapsibleContent, CollapsibleTrigger2 as CollapsibleTrigger, CropperModal, CropperModalError, DIALOG_ALERT_I18N_NAMESPACE, DataTable_default as DataTable, DatePicker2 as DatePicker, Dialog, DialogAlert, DialogAlertProvider, DialogContent, DialogDescription, DialogFooter, DialogTitle, DialogTrigger, ErrorCompression, ErrorCreateCanvas, ErrorGeneratingBlob, ErrorInvalidSVG, ErrorSVGExceedSize, Form, FormControl, FormDescription, FormField, FormItem, FormLabel, FormMessage, GridSettingsModal_default as GridSettingsModal, HeaderCell_default as HeaderCell, Input, Label2 as Label, List_default as List, container_default as ListContainer, header_default as ListHeader, table_default as ListTable, LookupSelect, MonthPicker2 as MonthPicker, navbar_default as Navbar, not_found_default as NotFoundIcon, Popover, PopoverAnchor, PopoverArrow, PopoverContent, PopoverTrigger, PreventPageLeave_default as PreventPageLeave, RadioGroupItem, RadioGroupRoot, RadioLabel, RichText, Select, SelectContent, SelectGroup, SelectItem, SelectLabel, SelectScrollDownButton, SelectScrollUpButton, SelectSeparator, SelectTrigger, SelectValue, Separator2 as Separator, Sheet, SheetClose, SheetContent, SheetDescription, SheetFooter, SheetHeader, SheetTitle, SheetTrigger, Sidebar, SidebarContent, SidebarFooter, SidebarGroup, SidebarGroupAction, SidebarGroupContent, SidebarGroupLabel, SidebarHeader, SidebarInput, SidebarInset, SidebarLayout, SidebarMenu, SidebarMenuAction, SidebarMenuBadge, SidebarMenuButton, SidebarMenuItem, SidebarMenuSkeleton, SidebarMenuSub, SidebarMenuSubButton, SidebarMenuSubItem, SidebarProvider, SidebarRail, SidebarSeparator, SidebarTrigger, Skeleton, Spinner, calendar_default as SuiCalendarIcon, check_default as SuiCheckIcon, dots_vertical_default as SuiDotsVerticalIcon, empty_data_default as SuiEmptyDataIcon, expand_default as SuiExpandIcon, filter_default as SuiFilterIcon, setting_default as SuiSettingIcon, triangle_down_default as SuiTriangleDownIcon, warning_default as SuiWarningIcon, Switch, Textarea, Tooltip, TooltipArrow, TooltipContent, TooltipProvider, TooltipTrigger, ui_exports as UI, booleanToSelectValue, buttonVariants, cn, compareAlphanumeric, debounce, getDialogAlertControls, getDialogTemplates, inputVariants, isDefined, isEmptyObject, selectValueToBoolean, spinnerVariants, stripNullishObject, throttle, useFormField, useGridSettingsStore_default as useGridSettingsStore, useHover_default as useHover, useIntersectionObserver_default as useIntersectionObserver, useMediaQuery_default as useMediaQuery, usePreventPageLeave_default as usePreventPageLeave, usePreventPageLeaveStore_default as usePreventPageLeaveStore, useScreenSize_default as useScreenSize, useSidebar, useTruncated_default as useTruncated };
8337
8385
  //# sourceMappingURL=index.mjs.map
8338
8386
  //# sourceMappingURL=index.mjs.map