@bbki.ng/components 1.5.2 → 1.5.5

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
@@ -1,4 +1,4 @@
1
- import React, { EventHandler, ReactElement, CSSProperties } from 'react';
1
+ import React, { EventHandler, ReactElement, CSSProperties, FunctionComponent } from 'react';
2
2
  import { LinkProps as LinkProps$1 } from 'react-router-dom';
3
3
 
4
4
  declare type ArticleProps = {
@@ -123,4 +123,17 @@ declare type SkeletonProps = {
123
123
  };
124
124
  declare const Skeleton: (props: SkeletonProps) => JSX.Element;
125
125
 
126
- export { Article, ArticleProps, Breadcrumb, BreadcrumbProps, Button, ButtonProps, ButtonType, Link, LinkColor, LinkProps, Logo, LogoProps, Nav, NavProps, Page, Panel, PanelProps, PathObj, PopConfirm, PopConfirmProps, Skeleton, SkeletonColor, SkeletonProps, Table, TableProps, Tag, TagProps, Tags };
126
+ interface ImageDropProps<T> {
127
+ uploader: (file: File, img: HTMLImageElement) => Promise<T>;
128
+ onDrop?: (events: Event, file: File) => void;
129
+ onUploadFinish?: (result: T) => void;
130
+ waitTimeAfterFinish?: number;
131
+ defaultBgColor?: string;
132
+ dragOverBgColor?: string;
133
+ dropAreaStyle?: CSSStyleDeclaration;
134
+ placeholder?: any;
135
+ className?: string;
136
+ }
137
+ declare const DropImage: FunctionComponent<ImageDropProps<any>>;
138
+
139
+ export { Article, ArticleProps, Breadcrumb, BreadcrumbProps, Button, ButtonProps, ButtonType, DropImage, ImageDropProps, Link, LinkColor, LinkProps, Logo, LogoProps, Nav, NavProps, Page, Panel, PanelProps, PathObj, PopConfirm, PopConfirmProps, Skeleton, SkeletonColor, SkeletonProps, Table, TableProps, Tag, TagProps, Tags };
package/dist/index.js CHANGED
@@ -62,6 +62,7 @@ __export(src_exports, {
62
62
  Breadcrumb: () => Breadcrumb,
63
63
  Button: () => Button,
64
64
  ButtonType: () => ButtonType,
65
+ DropImage: () => DropImage,
65
66
  Link: () => Link,
66
67
  LinkColor: () => LinkColor,
67
68
  Logo: () => Logo,
@@ -348,6 +349,175 @@ var Skeleton = (props) => {
348
349
  style: { width, height }
349
350
  });
350
351
  };
352
+
353
+ // src/drop-image/DropImage.tsx
354
+ var import_classnames6 = __toESM(require("classnames"));
355
+ var import_react13 = __toESM(require("react"));
356
+ var import_react14 = require("react");
357
+
358
+ // src/drop-image/utils.ts
359
+ var wait = (d) => new Promise((r) => setTimeout(r, d));
360
+ var noop = () => {
361
+ };
362
+
363
+ // src/drop-image/useDropImage.ts
364
+ var import_react12 = require("react");
365
+ var useDropImage = (params) => {
366
+ const [isDragOver, setIsDragOver] = (0, import_react12.useState)(false);
367
+ const [imageSrc, setImageSrc] = (0, import_react12.useState)("");
368
+ const [imageSize, setImageSize] = (0, import_react12.useState)({ width: 0, height: 0 });
369
+ const imageFile = (0, import_react12.useRef)(null);
370
+ const {
371
+ portraitImageWidth = 384,
372
+ landscapeImageWidth = 500,
373
+ onDrop = () => {
374
+ },
375
+ onImageLoad = () => {
376
+ }
377
+ } = params || {};
378
+ const reset = () => {
379
+ setImageSrc("");
380
+ setImageSize({ width: 0, height: 0 });
381
+ setIsDragOver(false);
382
+ imageFile.current = null;
383
+ };
384
+ const calcDefaultImgSize = (img, defaultWidth) => {
385
+ const { width, height } = img;
386
+ const whRatio = width / height;
387
+ const isHorizontal = width > height;
388
+ const finalWidth = defaultWidth || (isHorizontal ? landscapeImageWidth : portraitImageWidth);
389
+ return {
390
+ width: finalWidth,
391
+ height: finalWidth / whRatio
392
+ };
393
+ };
394
+ const setPreviewImageSrcByFile = (file) => {
395
+ try {
396
+ setImageSrc(URL.createObjectURL(file));
397
+ } catch (e) {
398
+ setImageSrc("");
399
+ }
400
+ };
401
+ const handleDragOver = (0, import_react12.useCallback)((ev) => {
402
+ ev.preventDefault();
403
+ setIsDragOver(true);
404
+ ev.dataTransfer.dropEffect = "move";
405
+ }, []);
406
+ const handleDragLeave = (0, import_react12.useCallback)(() => {
407
+ setIsDragOver(false);
408
+ }, []);
409
+ const handleDrop = (0, import_react12.useCallback)((ev) => {
410
+ ev.preventDefault();
411
+ setIsDragOver(false);
412
+ const file = ev.dataTransfer.files[0];
413
+ imageFile.current = file;
414
+ setPreviewImageSrcByFile(file);
415
+ onDrop(ev, file);
416
+ }, []);
417
+ const handleImgLoad = (img) => {
418
+ const updateFunc = async () => {
419
+ const p = "decode" in img ? img.decode : Promise.resolve;
420
+ try {
421
+ await p();
422
+ } catch (e) {
423
+ }
424
+ setImageSize(calcDefaultImgSize({
425
+ width: img.naturalWidth,
426
+ height: img.naturalHeight
427
+ }));
428
+ if (!imageFile.current) {
429
+ return;
430
+ }
431
+ onImageLoad(img, imageFile.current);
432
+ };
433
+ if (img.complete) {
434
+ updateFunc().then();
435
+ return;
436
+ }
437
+ img.onload = updateFunc;
438
+ };
439
+ const imageRef = (0, import_react12.useCallback)((input) => {
440
+ if (!input) {
441
+ return;
442
+ }
443
+ handleImgLoad(input);
444
+ }, []);
445
+ return {
446
+ isDragOver,
447
+ imageSrc,
448
+ imageRef,
449
+ imageSize,
450
+ handleDragOver,
451
+ handleDragLeave,
452
+ handleDrop,
453
+ reset
454
+ };
455
+ };
456
+
457
+ // src/drop-image/DropImage.tsx
458
+ var DropImage = (props) => {
459
+ const {
460
+ uploader,
461
+ defaultBgColor = "#F3F4F6",
462
+ onDrop,
463
+ dragOverBgColor = "#EFF6FF",
464
+ waitTimeAfterFinish = 2e3,
465
+ placeholder = "",
466
+ className = "",
467
+ onUploadFinish = noop,
468
+ dropAreaStyle = {
469
+ width: 300,
470
+ height: 300
471
+ }
472
+ } = props;
473
+ const [showImagePreviewer, setShowImagePreviewer] = (0, import_react14.useState)(false);
474
+ const {
475
+ handleDragLeave,
476
+ handleDragOver,
477
+ handleDrop,
478
+ imageRef,
479
+ imageSize,
480
+ imageSrc,
481
+ isDragOver,
482
+ reset
483
+ } = useDropImage({
484
+ onDrop,
485
+ onImageLoad: async (image, file) => {
486
+ await wait(500);
487
+ setShowImagePreviewer(true);
488
+ await onUploadFinish(await uploader(file, image));
489
+ await wait(waitTimeAfterFinish);
490
+ setShowImagePreviewer(false);
491
+ await wait(500);
492
+ reset();
493
+ }
494
+ });
495
+ const getDropAreaStyle = () => {
496
+ return Object.assign({}, dropAreaStyle, {
497
+ background: isDragOver ? dragOverBgColor : defaultBgColor,
498
+ width: imageSize.width || dropAreaStyle.width,
499
+ height: imageSize.height || dropAreaStyle.height
500
+ });
501
+ };
502
+ return /* @__PURE__ */ import_react13.default.createElement("div", {
503
+ className: (0, import_classnames6.default)(className, "transition-all items-center justify-center flex duration-200 ease-in-out", {
504
+ "shadow-input": !imageSrc,
505
+ "shadow-empty": imageSrc
506
+ }),
507
+ onDragLeave: handleDragLeave,
508
+ onDragOver: handleDragOver,
509
+ onDrop: handleDrop,
510
+ style: getDropAreaStyle()
511
+ }, /* @__PURE__ */ import_react13.default.createElement("img", {
512
+ className: (0, import_classnames6.default)("max-w-[100%]", "h-[auto]", "duration-300", "transition-opacity", "opacity-100", {
513
+ "opacity-0": !showImagePreviewer
514
+ }),
515
+ ref: imageRef,
516
+ src: imageSrc,
517
+ width: imageSize.width,
518
+ height: imageSize.height
519
+ }), !imageSrc && placeholder);
520
+ };
351
521
  module.exports = __toCommonJS(src_exports);
352
522
  // Annotate the CommonJS export names for ESM import in node:
353
523
  0 && (module.exports = {
@@ -355,6 +525,7 @@ module.exports = __toCommonJS(src_exports);
355
525
  Breadcrumb,
356
526
  Button,
357
527
  ButtonType,
528
+ DropImage,
358
529
  Link,
359
530
  LinkColor,
360
531
  Logo,
package/dist/index.mjs CHANGED
@@ -302,11 +302,181 @@ var Skeleton = (props) => {
302
302
  style: { width, height }
303
303
  });
304
304
  };
305
+
306
+ // src/drop-image/DropImage.tsx
307
+ import cls from "classnames";
308
+ import React13 from "react";
309
+ import { useState as useState3 } from "react";
310
+
311
+ // src/drop-image/utils.ts
312
+ var wait = (d) => new Promise((r) => setTimeout(r, d));
313
+ var noop = () => {
314
+ };
315
+
316
+ // src/drop-image/useDropImage.ts
317
+ import { useState as useState2, useCallback, useRef } from "react";
318
+ var useDropImage = (params) => {
319
+ const [isDragOver, setIsDragOver] = useState2(false);
320
+ const [imageSrc, setImageSrc] = useState2("");
321
+ const [imageSize, setImageSize] = useState2({ width: 0, height: 0 });
322
+ const imageFile = useRef(null);
323
+ const {
324
+ portraitImageWidth = 384,
325
+ landscapeImageWidth = 500,
326
+ onDrop = () => {
327
+ },
328
+ onImageLoad = () => {
329
+ }
330
+ } = params || {};
331
+ const reset = () => {
332
+ setImageSrc("");
333
+ setImageSize({ width: 0, height: 0 });
334
+ setIsDragOver(false);
335
+ imageFile.current = null;
336
+ };
337
+ const calcDefaultImgSize = (img, defaultWidth) => {
338
+ const { width, height } = img;
339
+ const whRatio = width / height;
340
+ const isHorizontal = width > height;
341
+ const finalWidth = defaultWidth || (isHorizontal ? landscapeImageWidth : portraitImageWidth);
342
+ return {
343
+ width: finalWidth,
344
+ height: finalWidth / whRatio
345
+ };
346
+ };
347
+ const setPreviewImageSrcByFile = (file) => {
348
+ try {
349
+ setImageSrc(URL.createObjectURL(file));
350
+ } catch (e) {
351
+ setImageSrc("");
352
+ }
353
+ };
354
+ const handleDragOver = useCallback((ev) => {
355
+ ev.preventDefault();
356
+ setIsDragOver(true);
357
+ ev.dataTransfer.dropEffect = "move";
358
+ }, []);
359
+ const handleDragLeave = useCallback(() => {
360
+ setIsDragOver(false);
361
+ }, []);
362
+ const handleDrop = useCallback((ev) => {
363
+ ev.preventDefault();
364
+ setIsDragOver(false);
365
+ const file = ev.dataTransfer.files[0];
366
+ imageFile.current = file;
367
+ setPreviewImageSrcByFile(file);
368
+ onDrop(ev, file);
369
+ }, []);
370
+ const handleImgLoad = (img) => {
371
+ const updateFunc = async () => {
372
+ const p = "decode" in img ? img.decode : Promise.resolve;
373
+ try {
374
+ await p();
375
+ } catch (e) {
376
+ }
377
+ setImageSize(calcDefaultImgSize({
378
+ width: img.naturalWidth,
379
+ height: img.naturalHeight
380
+ }));
381
+ if (!imageFile.current) {
382
+ return;
383
+ }
384
+ onImageLoad(img, imageFile.current);
385
+ };
386
+ if (img.complete) {
387
+ updateFunc().then();
388
+ return;
389
+ }
390
+ img.onload = updateFunc;
391
+ };
392
+ const imageRef = useCallback((input) => {
393
+ if (!input) {
394
+ return;
395
+ }
396
+ handleImgLoad(input);
397
+ }, []);
398
+ return {
399
+ isDragOver,
400
+ imageSrc,
401
+ imageRef,
402
+ imageSize,
403
+ handleDragOver,
404
+ handleDragLeave,
405
+ handleDrop,
406
+ reset
407
+ };
408
+ };
409
+
410
+ // src/drop-image/DropImage.tsx
411
+ var DropImage = (props) => {
412
+ const {
413
+ uploader,
414
+ defaultBgColor = "#F3F4F6",
415
+ onDrop,
416
+ dragOverBgColor = "#EFF6FF",
417
+ waitTimeAfterFinish = 2e3,
418
+ placeholder = "",
419
+ className = "",
420
+ onUploadFinish = noop,
421
+ dropAreaStyle = {
422
+ width: 300,
423
+ height: 300
424
+ }
425
+ } = props;
426
+ const [showImagePreviewer, setShowImagePreviewer] = useState3(false);
427
+ const {
428
+ handleDragLeave,
429
+ handleDragOver,
430
+ handleDrop,
431
+ imageRef,
432
+ imageSize,
433
+ imageSrc,
434
+ isDragOver,
435
+ reset
436
+ } = useDropImage({
437
+ onDrop,
438
+ onImageLoad: async (image, file) => {
439
+ await wait(500);
440
+ setShowImagePreviewer(true);
441
+ await onUploadFinish(await uploader(file, image));
442
+ await wait(waitTimeAfterFinish);
443
+ setShowImagePreviewer(false);
444
+ await wait(500);
445
+ reset();
446
+ }
447
+ });
448
+ const getDropAreaStyle = () => {
449
+ return Object.assign({}, dropAreaStyle, {
450
+ background: isDragOver ? dragOverBgColor : defaultBgColor,
451
+ width: imageSize.width || dropAreaStyle.width,
452
+ height: imageSize.height || dropAreaStyle.height
453
+ });
454
+ };
455
+ return /* @__PURE__ */ React13.createElement("div", {
456
+ className: cls(className, "transition-all items-center justify-center flex duration-200 ease-in-out", {
457
+ "shadow-input": !imageSrc,
458
+ "shadow-empty": imageSrc
459
+ }),
460
+ onDragLeave: handleDragLeave,
461
+ onDragOver: handleDragOver,
462
+ onDrop: handleDrop,
463
+ style: getDropAreaStyle()
464
+ }, /* @__PURE__ */ React13.createElement("img", {
465
+ className: cls("max-w-[100%]", "h-[auto]", "duration-300", "transition-opacity", "opacity-100", {
466
+ "opacity-0": !showImagePreviewer
467
+ }),
468
+ ref: imageRef,
469
+ src: imageSrc,
470
+ width: imageSize.width,
471
+ height: imageSize.height
472
+ }), !imageSrc && placeholder);
473
+ };
305
474
  export {
306
475
  Article,
307
476
  Breadcrumb,
308
477
  Button,
309
478
  ButtonType,
479
+ DropImage,
310
480
  Link,
311
481
  LinkColor,
312
482
  Logo,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bbki.ng/components",
3
- "version": "1.5.2",
3
+ "version": "1.5.5",
4
4
  "main": "./dist/index.js",
5
5
  "module": "./dist/index.mjs",
6
6
  "types": "./dist/index.d.ts",