@ctlyst.id/internal-ui 3.4.6 → 3.5.1

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
  }
@@ -2751,17 +2746,29 @@ var Datepicker = ({
2751
2746
  const hasMultipleMonthShow = ((_b = props == null ? void 0 : props.monthsShown) != null ? _b : 1) < 2;
2752
2747
  const component = /* @__PURE__ */ jsxs10(Fragment2, { children: [
2753
2748
  /* @__PURE__ */ jsx27(styles_default, { showHeader: !hasMultipleMonthShow }),
2754
- /* @__PURE__ */ jsx27(
2749
+ /* @__PURE__ */ jsx27(field_default, { label, isRequired, isError, children: /* @__PURE__ */ jsx27(
2755
2750
  ReactDatePicker,
2756
2751
  {
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
  {
2763
- label,
2764
- isRequired,
2765
2772
  autoComplete: "off",
2766
2773
  isError,
2767
2774
  addOnRight: /* @__PURE__ */ jsxs10(InputRightElement, { alignSelf: "center", bottom: 0, flexDir: "row-reverse", width: "auto", mr: 2, gap: 2, children: [
@@ -2796,7 +2803,7 @@ var Datepicker = ({
2796
2803
  ...getTimeProps(),
2797
2804
  ...props
2798
2805
  }
2799
- )
2806
+ ) })
2800
2807
  ] });
2801
2808
  if (props.inline) {
2802
2809
  return component;
@@ -5638,7 +5645,7 @@ import {
5638
5645
  UnorderedList as UnorderedList2
5639
5646
  } from "@chakra-ui/react";
5640
5647
  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";
5648
+ import { useCallback as useCallback2, useEffect as useEffect4, useState as useState5 } from "react";
5642
5649
  import { useDropzone } from "react-dropzone";
5643
5650
 
5644
5651
  // src/components/uploader/constants.ts
@@ -5667,9 +5674,48 @@ var concatList = (list) => {
5667
5674
  };
5668
5675
  var formatValidationMessage = (extension) => `Foto harus dalam format ${concatList(extension.map((ext) => `.${ext}`))}.`;
5669
5676
 
5677
+ // src/components/uploader/utils/error-code.ts
5678
+ var ErrorCode = /* @__PURE__ */ ((ErrorCode2) => {
5679
+ ErrorCode2["FileInvalidType"] = "file-invalid-type";
5680
+ ErrorCode2["FileTooLarge"] = "file-too-large";
5681
+ ErrorCode2["FileTooSmall"] = "file-too-small";
5682
+ ErrorCode2["TooManyFiles"] = "too-many-files";
5683
+ ErrorCode2["FileInvalidDimension"] = "file-invalid-dimension";
5684
+ return ErrorCode2;
5685
+ })(ErrorCode || {});
5686
+ var error_code_default = ErrorCode;
5687
+
5688
+ // src/components/uploader/utils/handler.ts
5689
+ var defaultOnHandleRejections = (fileRejection, config2, handleRejection) => {
5690
+ var _a, _b, _c, _d;
5691
+ const { file, errors: errors3 } = fileRejection[0];
5692
+ switch (errors3[0].code) {
5693
+ case error_code_default.FileInvalidType: {
5694
+ const fileFormat = file.name.split(".").pop();
5695
+ if (!(config2 == null ? void 0 : config2.acceptFormat)) return;
5696
+ if (!((_a = config2 == null ? void 0 : config2.acceptFormat) == null ? void 0 : _a.validate.includes(fileFormat))) {
5697
+ handleRejection(
5698
+ (_d = (_b = config2.acceptFormat) == null ? void 0 : _b.message) != null ? _d : formatValidationMessage((_c = config2.acceptFormat) == null ? void 0 : _c.validate),
5699
+ file,
5700
+ null
5701
+ );
5702
+ }
5703
+ break;
5704
+ }
5705
+ case error_code_default.FileTooLarge: {
5706
+ if (config2.maxFileSize) {
5707
+ handleRejection(config2.maxFileSize.message, file, null);
5708
+ }
5709
+ break;
5710
+ }
5711
+ default:
5712
+ handleRejection(errors3[0].message, file, null);
5713
+ break;
5714
+ }
5715
+ };
5716
+
5670
5717
  // src/components/uploader/components/uploader.tsx
5671
5718
  import { Fragment as Fragment12, jsx as jsx66, jsxs as jsxs31 } from "react/jsx-runtime";
5672
- import { createElement } from "react";
5673
5719
  var Uploader = ({
5674
5720
  onHandleUploadFile,
5675
5721
  onHandleRejections,
@@ -5696,9 +5742,9 @@ var Uploader = ({
5696
5742
  errorText,
5697
5743
  isShowReupload = true,
5698
5744
  size: size2 = "lg",
5745
+ validatorExt,
5699
5746
  ...props
5700
5747
  }) => {
5701
- const inputRef = useRef3(null);
5702
5748
  const [filePreview, setFilePreview] = useState5();
5703
5749
  const toast2 = useToast();
5704
5750
  const handleRejection = useCallback2(
@@ -5713,33 +5759,21 @@ var Uploader = ({
5713
5759
  // eslint-disable-next-line react-hooks/exhaustive-deps
5714
5760
  [onHandleRejections]
5715
5761
  );
5716
- const onDrop = useCallback2(
5762
+ const onDropAccepted = useCallback2(
5717
5763
  (files) => {
5718
- var _a;
5719
5764
  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
5765
  const imageUrl = URL.createObjectURL(file);
5725
5766
  const img = new Image();
5726
5767
  img.src = imageUrl;
5727
5768
  img.onload = () => {
5728
- var _a2;
5729
5769
  const imgWidth = img.width;
5730
5770
  const imgheight = img.height;
5731
5771
  if (customValidation && customValidation(file, img) !== null) {
5732
5772
  return handleRejection(customValidation(file, img), file, img);
5733
5773
  }
5734
- if (!acceptFormat.validate.includes(fileFormat)) {
5735
- return handleRejection((_a2 = acceptFormat.message) != null ? _a2 : formatValidationMessage(acceptFormat.validate), file, img);
5736
- }
5737
5774
  if (dimension && (imgWidth !== dimension.validate[0] || imgheight !== dimension.validate[1])) {
5738
5775
  return handleRejection(dimension.message, file, img);
5739
5776
  }
5740
- if (maxFileSize && file.size > maxFileSize.validate) {
5741
- return handleRejection(maxFileSize.message, file, null);
5742
- }
5743
5777
  onHandleUploadFile == null ? void 0 : onHandleUploadFile(file, img);
5744
5778
  setFilePreview(URL.createObjectURL(file));
5745
5779
  return null;
@@ -5748,11 +5782,36 @@ var Uploader = ({
5748
5782
  },
5749
5783
  [acceptFormat, customValidation, dimension, handleRejection, maxFileSize, onHandleUploadFile]
5750
5784
  );
5751
- const { getRootProps, getInputProps, isDragActive, acceptedFiles } = useDropzone({
5752
- onDrop,
5785
+ const onDropRejected = useCallback2((fileRejections) => {
5786
+ defaultOnHandleRejections(fileRejections, { acceptFormat, maxFileSize }, handleRejection);
5787
+ }, []);
5788
+ const validator = useCallback2(
5789
+ (file) => {
5790
+ if (validatorExt) {
5791
+ const result = [];
5792
+ validatorExt.forEach((validatorFn) => {
5793
+ const error = validatorFn(file);
5794
+ if (Array.isArray(error)) {
5795
+ result.push(...error);
5796
+ } else if (error) result.push(error);
5797
+ });
5798
+ return result;
5799
+ }
5800
+ return null;
5801
+ },
5802
+ [validatorExt]
5803
+ );
5804
+ const { getRootProps, getInputProps, isDragActive, acceptedFiles, open } = useDropzone({
5805
+ onDropAccepted,
5806
+ onDropRejected,
5807
+ accept: {
5808
+ "image/*": [...acceptFormat.validate]
5809
+ },
5753
5810
  maxFiles: 1,
5811
+ maxSize: maxFileSize == null ? void 0 : maxFileSize.validate,
5754
5812
  noClick: isDisabled,
5755
- noDrag: isDisabled
5813
+ noDrag: isDisabled,
5814
+ validator
5756
5815
  });
5757
5816
  const renderHelperText = () => {
5758
5817
  if (Array.isArray(helperText)) {
@@ -5873,13 +5932,10 @@ var Uploader = ({
5873
5932
  ]
5874
5933
  }
5875
5934
  ),
5876
- /* @__PURE__ */ createElement(
5935
+ /* @__PURE__ */ jsx66(
5877
5936
  "input",
5878
5937
  {
5879
5938
  ...getInputProps(),
5880
- key: Math.random(),
5881
- ref: inputRef,
5882
- accept: "image/*",
5883
5939
  "data-test-id": `CT_component_base-image-uploader_change-img${testId ? `_${testId}` : ""}`
5884
5940
  }
5885
5941
  ),
@@ -5890,10 +5946,7 @@ var Uploader = ({
5890
5946
  type: "button",
5891
5947
  size: "sm",
5892
5948
  variant: "outline",
5893
- onClick: () => {
5894
- var _a;
5895
- (_a = inputRef == null ? void 0 : inputRef.current) == null ? void 0 : _a.click();
5896
- },
5949
+ onClick: open,
5897
5950
  children: "Ubah Foto"
5898
5951
  }
5899
5952
  ) }),
@@ -5903,6 +5956,36 @@ var Uploader = ({
5903
5956
  };
5904
5957
  var uploader_default = Uploader;
5905
5958
 
5959
+ // src/components/uploader/utils/is-ratio-equal.ts
5960
+ var isRatioEqual = (base, img) => {
5961
+ const baseRatio = (base.width / base.height).toFixed(2);
5962
+ const imgRatio = (img.width / img.height).toFixed(2);
5963
+ return baseRatio === imgRatio;
5964
+ };
5965
+
5966
+ // src/components/uploader/components/validator.ts
5967
+ var dimensionValidator = (dimension, message) => {
5968
+ return (file) => {
5969
+ const imageUrl = URL.createObjectURL(file);
5970
+ const img = new Image();
5971
+ img.src = imageUrl;
5972
+ img.onload = () => {
5973
+ };
5974
+ const isRatioValid = isRatioEqual(
5975
+ { width: dimension[0], height: dimension[1] },
5976
+ { width: img.width, height: img.height }
5977
+ );
5978
+ console.log("log", isRatioValid);
5979
+ if (isRatioValid) {
5980
+ return null;
5981
+ }
5982
+ return {
5983
+ code: error_code_default.FileInvalidDimension,
5984
+ message: message != null ? message : "File has invalid dimension"
5985
+ };
5986
+ };
5987
+ };
5988
+
5906
5989
  // src/components/index.ts
5907
5990
  import {
5908
5991
  Avatar as Avatar2,
@@ -7599,7 +7682,7 @@ import { useMemo as useMemo5 } from "react";
7599
7682
 
7600
7683
  // src/provider/components/provider.tsx
7601
7684
  import axios from "axios";
7602
- import { createContext as createContext2, useContext, useEffect as useEffect5, useMemo as useMemo4, useRef as useRef4 } from "react";
7685
+ import { createContext as createContext2, useContext, useEffect as useEffect5, useMemo as useMemo4, useRef as useRef3 } from "react";
7603
7686
  import { ToastContainer as ToastContainer2 } from "react-toastify";
7604
7687
  import { jsx as jsx67, jsxs as jsxs32 } from "react/jsx-runtime";
7605
7688
  var ProviderContext = createContext2({
@@ -7610,7 +7693,7 @@ var useInternalUI = () => {
7610
7693
  return { instance };
7611
7694
  };
7612
7695
  var Provider = ({ children, config: config2, requestInterceptors, responseInterceptors }) => {
7613
- const instanceRef = useRef4(axios.create(config2));
7696
+ const instanceRef = useRef3(axios.create(config2));
7614
7697
  useEffect5(() => {
7615
7698
  requestInterceptors == null ? void 0 : requestInterceptors.forEach((interceptor) => {
7616
7699
  instanceRef.current.interceptors.request.use(interceptor);
@@ -7760,6 +7843,7 @@ export {
7760
7843
  DrawerProps,
7761
7844
  DropdownIndicator,
7762
7845
  empty_state_default as EmptyState,
7846
+ error_code_default as ErrorCode,
7763
7847
  Fade,
7764
7848
  FadeProps,
7765
7849
  field_default as Field,
@@ -7983,12 +8067,15 @@ export {
7983
8067
  WrapProps,
7984
8068
  XMSLogo,
7985
8069
  createExtendTheme,
8070
+ defaultOnHandleRejections,
8071
+ dimensionValidator,
7986
8072
  extendTheme,
7987
8073
  forwardRef13 as forwardRef,
7988
8074
  getSelectAllCheckboxState,
7989
8075
  getTheme,
7990
8076
  id,
7991
8077
  isCellDisabled,
8078
+ isRatioEqual,
7992
8079
  selectStyles,
7993
8080
  theme4 as theme,
7994
8081
  themeSelect,