@ctlyst.id/internal-ui 3.4.6 → 3.5.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
@@ -1289,6 +1289,7 @@ var data_table_default = DataTable;
1289
1289
  import { FormControl as FormControl3, FormErrorMessage as FormErrorMessage3, FormHelperText as FormHelperText3, IconButton as IconButton4 } from "@chakra-ui/react";
1290
1290
  import { cx as cx8 } from "@chakra-ui/shared-utils";
1291
1291
  import { Calendar, Close as Close3 } from "@ctlyst.id/internal-icon";
1292
+ import { offset } from "@floating-ui/react";
1292
1293
  import ReactDatePicker from "react-datepicker";
1293
1294
 
1294
1295
  // ../../node_modules/.pnpm/date-fns@3.6.0/node_modules/date-fns/locale/_lib/buildFormatLongFn.mjs
@@ -1941,16 +1942,10 @@ var Styles = ({ showHeader }) => {
1941
1942
  .react-datepicker-popper {
1942
1943
  z-index: 1;
1943
1944
  }
1944
- .react-datepicker-popper[data-placement^=bottom] {
1945
- padding-top: 10px;
1946
- }
1947
1945
  .react-datepicker-popper[data-placement=bottom-end] .react-datepicker__triangle, .react-datepicker-popper[data-placement=top-end] .react-datepicker__triangle {
1948
1946
  left: auto;
1949
1947
  right: 50px;
1950
1948
  }
1951
- .react-datepicker-popper[data-placement^=top] {
1952
- padding-bottom: 10px;
1953
- }
1954
1949
  .react-datepicker-popper[data-placement^=right] {
1955
1950
  padding-left: 8px;
1956
1951
  }
@@ -2757,6 +2752,20 @@ var Datepicker = ({
2757
2752
  id: id2,
2758
2753
  name,
2759
2754
  selected,
2755
+ popperModifiers: [
2756
+ offset(4),
2757
+ {
2758
+ name: "placement",
2759
+ fn: (state) => {
2760
+ const { placement, y } = state;
2761
+ return {
2762
+ ...state,
2763
+ y: placement.startsWith("bottom") ? y - 10 : y + 10
2764
+ // condition for auto placement
2765
+ };
2766
+ }
2767
+ }
2768
+ ],
2760
2769
  customInput: /* @__PURE__ */ jsx27(
2761
2770
  input_field_default,
2762
2771
  {
@@ -5638,7 +5647,7 @@ import {
5638
5647
  UnorderedList as UnorderedList2
5639
5648
  } from "@chakra-ui/react";
5640
5649
  import { Close as X, Plus } from "@ctlyst.id/internal-icon";
5641
- import { useCallback as useCallback2, useEffect as useEffect4, useRef as useRef3, useState as useState5 } from "react";
5650
+ import { useCallback as useCallback2, useEffect as useEffect4, useState as useState5 } from "react";
5642
5651
  import { useDropzone } from "react-dropzone";
5643
5652
 
5644
5653
  // src/components/uploader/constants.ts
@@ -5667,9 +5676,48 @@ var concatList = (list) => {
5667
5676
  };
5668
5677
  var formatValidationMessage = (extension) => `Foto harus dalam format ${concatList(extension.map((ext) => `.${ext}`))}.`;
5669
5678
 
5679
+ // src/components/uploader/utils/error-code.ts
5680
+ var ErrorCode = /* @__PURE__ */ ((ErrorCode2) => {
5681
+ ErrorCode2["FileInvalidType"] = "file-invalid-type";
5682
+ ErrorCode2["FileTooLarge"] = "file-too-large";
5683
+ ErrorCode2["FileTooSmall"] = "file-too-small";
5684
+ ErrorCode2["TooManyFiles"] = "too-many-files";
5685
+ ErrorCode2["FileInvalidDimension"] = "file-invalid-dimension";
5686
+ return ErrorCode2;
5687
+ })(ErrorCode || {});
5688
+ var error_code_default = ErrorCode;
5689
+
5690
+ // src/components/uploader/utils/handler.ts
5691
+ var defaultOnHandleRejections = (fileRejection, config2, handleRejection) => {
5692
+ var _a, _b, _c, _d;
5693
+ const { file, errors: errors3 } = fileRejection[0];
5694
+ switch (errors3[0].code) {
5695
+ case error_code_default.FileInvalidType: {
5696
+ const fileFormat = file.name.split(".").pop();
5697
+ if (!(config2 == null ? void 0 : config2.acceptFormat)) return;
5698
+ if (!((_a = config2 == null ? void 0 : config2.acceptFormat) == null ? void 0 : _a.validate.includes(fileFormat))) {
5699
+ handleRejection(
5700
+ (_d = (_b = config2.acceptFormat) == null ? void 0 : _b.message) != null ? _d : formatValidationMessage((_c = config2.acceptFormat) == null ? void 0 : _c.validate),
5701
+ file,
5702
+ null
5703
+ );
5704
+ }
5705
+ break;
5706
+ }
5707
+ case error_code_default.FileTooLarge: {
5708
+ if (config2.maxFileSize) {
5709
+ handleRejection(config2.maxFileSize.message, file, null);
5710
+ }
5711
+ break;
5712
+ }
5713
+ default:
5714
+ handleRejection(errors3[0].message, file, null);
5715
+ break;
5716
+ }
5717
+ };
5718
+
5670
5719
  // src/components/uploader/components/uploader.tsx
5671
5720
  import { Fragment as Fragment12, jsx as jsx66, jsxs as jsxs31 } from "react/jsx-runtime";
5672
- import { createElement } from "react";
5673
5721
  var Uploader = ({
5674
5722
  onHandleUploadFile,
5675
5723
  onHandleRejections,
@@ -5696,9 +5744,9 @@ var Uploader = ({
5696
5744
  errorText,
5697
5745
  isShowReupload = true,
5698
5746
  size: size2 = "lg",
5747
+ validatorExt,
5699
5748
  ...props
5700
5749
  }) => {
5701
- const inputRef = useRef3(null);
5702
5750
  const [filePreview, setFilePreview] = useState5();
5703
5751
  const toast2 = useToast();
5704
5752
  const handleRejection = useCallback2(
@@ -5713,33 +5761,21 @@ var Uploader = ({
5713
5761
  // eslint-disable-next-line react-hooks/exhaustive-deps
5714
5762
  [onHandleRejections]
5715
5763
  );
5716
- const onDrop = useCallback2(
5764
+ const onDropAccepted = useCallback2(
5717
5765
  (files) => {
5718
- var _a;
5719
5766
  const file = files[0];
5720
- const fileFormat = file.name.split(".").pop();
5721
- if (!(acceptFormat == null ? void 0 : acceptFormat.validate.includes(fileFormat))) {
5722
- return handleRejection((_a = acceptFormat.message) != null ? _a : formatValidationMessage(acceptFormat.validate), file, null);
5723
- }
5724
5767
  const imageUrl = URL.createObjectURL(file);
5725
5768
  const img = new Image();
5726
5769
  img.src = imageUrl;
5727
5770
  img.onload = () => {
5728
- var _a2;
5729
5771
  const imgWidth = img.width;
5730
5772
  const imgheight = img.height;
5731
5773
  if (customValidation && customValidation(file, img) !== null) {
5732
5774
  return handleRejection(customValidation(file, img), file, img);
5733
5775
  }
5734
- if (!acceptFormat.validate.includes(fileFormat)) {
5735
- return handleRejection((_a2 = acceptFormat.message) != null ? _a2 : formatValidationMessage(acceptFormat.validate), file, img);
5736
- }
5737
5776
  if (dimension && (imgWidth !== dimension.validate[0] || imgheight !== dimension.validate[1])) {
5738
5777
  return handleRejection(dimension.message, file, img);
5739
5778
  }
5740
- if (maxFileSize && file.size > maxFileSize.validate) {
5741
- return handleRejection(maxFileSize.message, file, null);
5742
- }
5743
5779
  onHandleUploadFile == null ? void 0 : onHandleUploadFile(file, img);
5744
5780
  setFilePreview(URL.createObjectURL(file));
5745
5781
  return null;
@@ -5748,11 +5784,36 @@ var Uploader = ({
5748
5784
  },
5749
5785
  [acceptFormat, customValidation, dimension, handleRejection, maxFileSize, onHandleUploadFile]
5750
5786
  );
5751
- const { getRootProps, getInputProps, isDragActive, acceptedFiles } = useDropzone({
5752
- onDrop,
5787
+ const onDropRejected = useCallback2((fileRejections) => {
5788
+ defaultOnHandleRejections(fileRejections, { acceptFormat, maxFileSize }, handleRejection);
5789
+ }, []);
5790
+ const validator = useCallback2(
5791
+ (file) => {
5792
+ if (validatorExt) {
5793
+ const result = [];
5794
+ validatorExt.forEach((validatorFn) => {
5795
+ const error = validatorFn(file);
5796
+ if (Array.isArray(error)) {
5797
+ result.push(...error);
5798
+ } else if (error) result.push(error);
5799
+ });
5800
+ return result;
5801
+ }
5802
+ return null;
5803
+ },
5804
+ [validatorExt]
5805
+ );
5806
+ const { getRootProps, getInputProps, isDragActive, acceptedFiles, open } = useDropzone({
5807
+ onDropAccepted,
5808
+ onDropRejected,
5809
+ accept: {
5810
+ "image/*": [...acceptFormat.validate]
5811
+ },
5753
5812
  maxFiles: 1,
5813
+ maxSize: maxFileSize == null ? void 0 : maxFileSize.validate,
5754
5814
  noClick: isDisabled,
5755
- noDrag: isDisabled
5815
+ noDrag: isDisabled,
5816
+ validator
5756
5817
  });
5757
5818
  const renderHelperText = () => {
5758
5819
  if (Array.isArray(helperText)) {
@@ -5873,13 +5934,10 @@ var Uploader = ({
5873
5934
  ]
5874
5935
  }
5875
5936
  ),
5876
- /* @__PURE__ */ createElement(
5937
+ /* @__PURE__ */ jsx66(
5877
5938
  "input",
5878
5939
  {
5879
5940
  ...getInputProps(),
5880
- key: Math.random(),
5881
- ref: inputRef,
5882
- accept: "image/*",
5883
5941
  "data-test-id": `CT_component_base-image-uploader_change-img${testId ? `_${testId}` : ""}`
5884
5942
  }
5885
5943
  ),
@@ -5890,10 +5948,7 @@ var Uploader = ({
5890
5948
  type: "button",
5891
5949
  size: "sm",
5892
5950
  variant: "outline",
5893
- onClick: () => {
5894
- var _a;
5895
- (_a = inputRef == null ? void 0 : inputRef.current) == null ? void 0 : _a.click();
5896
- },
5951
+ onClick: open,
5897
5952
  children: "Ubah Foto"
5898
5953
  }
5899
5954
  ) }),
@@ -5903,6 +5958,36 @@ var Uploader = ({
5903
5958
  };
5904
5959
  var uploader_default = Uploader;
5905
5960
 
5961
+ // src/components/uploader/utils/is-ratio-equal.ts
5962
+ var isRatioEqual = (base, img) => {
5963
+ const baseRatio = (base.width / base.height).toFixed(2);
5964
+ const imgRatio = (img.width / img.height).toFixed(2);
5965
+ return baseRatio === imgRatio;
5966
+ };
5967
+
5968
+ // src/components/uploader/components/validator.ts
5969
+ var dimensionValidator = (dimension, message) => {
5970
+ return (file) => {
5971
+ const imageUrl = URL.createObjectURL(file);
5972
+ const img = new Image();
5973
+ img.src = imageUrl;
5974
+ img.onload = () => {
5975
+ };
5976
+ const isRatioValid = isRatioEqual(
5977
+ { width: dimension[0], height: dimension[1] },
5978
+ { width: img.width, height: img.height }
5979
+ );
5980
+ console.log("log", isRatioValid);
5981
+ if (isRatioValid) {
5982
+ return null;
5983
+ }
5984
+ return {
5985
+ code: error_code_default.FileInvalidDimension,
5986
+ message: message != null ? message : "File has invalid dimension"
5987
+ };
5988
+ };
5989
+ };
5990
+
5906
5991
  // src/components/index.ts
5907
5992
  import {
5908
5993
  Avatar as Avatar2,
@@ -7599,7 +7684,7 @@ import { useMemo as useMemo5 } from "react";
7599
7684
 
7600
7685
  // src/provider/components/provider.tsx
7601
7686
  import axios from "axios";
7602
- import { createContext as createContext2, useContext, useEffect as useEffect5, useMemo as useMemo4, useRef as useRef4 } from "react";
7687
+ import { createContext as createContext2, useContext, useEffect as useEffect5, useMemo as useMemo4, useRef as useRef3 } from "react";
7603
7688
  import { ToastContainer as ToastContainer2 } from "react-toastify";
7604
7689
  import { jsx as jsx67, jsxs as jsxs32 } from "react/jsx-runtime";
7605
7690
  var ProviderContext = createContext2({
@@ -7610,7 +7695,7 @@ var useInternalUI = () => {
7610
7695
  return { instance };
7611
7696
  };
7612
7697
  var Provider = ({ children, config: config2, requestInterceptors, responseInterceptors }) => {
7613
- const instanceRef = useRef4(axios.create(config2));
7698
+ const instanceRef = useRef3(axios.create(config2));
7614
7699
  useEffect5(() => {
7615
7700
  requestInterceptors == null ? void 0 : requestInterceptors.forEach((interceptor) => {
7616
7701
  instanceRef.current.interceptors.request.use(interceptor);
@@ -7760,6 +7845,7 @@ export {
7760
7845
  DrawerProps,
7761
7846
  DropdownIndicator,
7762
7847
  empty_state_default as EmptyState,
7848
+ error_code_default as ErrorCode,
7763
7849
  Fade,
7764
7850
  FadeProps,
7765
7851
  field_default as Field,
@@ -7983,12 +8069,15 @@ export {
7983
8069
  WrapProps,
7984
8070
  XMSLogo,
7985
8071
  createExtendTheme,
8072
+ defaultOnHandleRejections,
8073
+ dimensionValidator,
7986
8074
  extendTheme,
7987
8075
  forwardRef13 as forwardRef,
7988
8076
  getSelectAllCheckboxState,
7989
8077
  getTheme,
7990
8078
  id,
7991
8079
  isCellDisabled,
8080
+ isRatioEqual,
7992
8081
  selectStyles,
7993
8082
  theme4 as theme,
7994
8083
  themeSelect,