@abpjs/theme-shared 0.7.6 → 0.9.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
@@ -9,6 +9,94 @@ var Toaster;
9
9
  })(Status = Toaster2.Status || (Toaster2.Status = {}));
10
10
  })(Toaster || (Toaster = {}));
11
11
 
12
+ // src/constants/styles.ts
13
+ var DEFAULT_STYLES = `
14
+ .is-invalid .form-control {
15
+ border-color: #dc3545;
16
+ border-style: solid !important;
17
+ }
18
+
19
+ .is-invalid .invalid-feedback,
20
+ .is-invalid + * .invalid-feedback {
21
+ display: block;
22
+ }
23
+
24
+ .data-tables-filter {
25
+ text-align: right;
26
+ }
27
+
28
+ .pointer {
29
+ cursor: pointer;
30
+ }
31
+
32
+ .navbar .dropdown-submenu a::after {
33
+ transform: rotate(-90deg);
34
+ position: absolute;
35
+ right: 16px;
36
+ top: 18px;
37
+ }
38
+
39
+ .modal {
40
+ background-color: rgba(0, 0, 0, .6);
41
+ }
42
+
43
+ .abp-ellipsis {
44
+ display: inline-block;
45
+ overflow: hidden;
46
+ text-overflow: ellipsis;
47
+ white-space: nowrap;
48
+ }
49
+
50
+ /* <animations */
51
+
52
+ .fade-in-top {
53
+ animation: fadeInTop 0.4s ease-in-out;
54
+ }
55
+
56
+ .fade-out-top {
57
+ animation: fadeOutTop 0.4s ease-in-out;
58
+ }
59
+
60
+ @keyframes fadeInTop {
61
+ from {
62
+ transform: translateY(-5px);
63
+ opacity: 0;
64
+ }
65
+
66
+ to {
67
+ transform: translateY(5px);
68
+ opacity: 1;
69
+ }
70
+ }
71
+
72
+ @keyframes fadeOutTop {
73
+ to {
74
+ transform: translateY(-5px);
75
+ opacity: 0;
76
+ }
77
+ }
78
+
79
+ /* </animations */
80
+
81
+ /* Loader bar styles */
82
+ .abp-loader-bar {
83
+ position: fixed;
84
+ top: 0;
85
+ left: 0;
86
+ right: 0;
87
+ height: 3px;
88
+ z-index: 9999;
89
+ background-color: rgba(0, 0, 0, 0.1);
90
+ overflow: hidden;
91
+ }
92
+
93
+ .abp-progress {
94
+ height: 100%;
95
+ background-color: #3182ce;
96
+ transition: width 0.3s ease-out;
97
+ }
98
+ `;
99
+
12
100
  // src/contexts/toaster.context.tsx
13
101
  import {
14
102
  createContext,
@@ -241,7 +329,7 @@ function useConfirmationContext() {
241
329
  }
242
330
 
243
331
  // src/handlers/error.handler.ts
244
- import { useCallback as useCallback3 } from "react";
332
+ import { useCallback as useCallback3, useState as useState3 } from "react";
245
333
  var DEFAULT_ERROR_MESSAGES = {
246
334
  400: "AbpUi::DefaultErrorMessage400",
247
335
  401: "AbpUi::DefaultErrorMessage401",
@@ -253,6 +341,7 @@ var DEFAULT_ERROR_MESSAGES = {
253
341
  function useErrorHandler(options = {}) {
254
342
  const { navigate, loginPath = "/account/login" } = options;
255
343
  const confirmation = useConfirmation();
344
+ const [errorComponentProps, setErrorComponentProps] = useState3(null);
256
345
  const navigateToLogin = useCallback3(() => {
257
346
  if (navigate) {
258
347
  navigate(loginPath);
@@ -264,6 +353,22 @@ function useErrorHandler(options = {}) {
264
353
  },
265
354
  [confirmation]
266
355
  );
356
+ const clearErrorComponent = useCallback3(() => {
357
+ setErrorComponentProps(null);
358
+ }, []);
359
+ const createErrorComponent = useCallback3(
360
+ (instance) => {
361
+ const props = {
362
+ title: instance.title || "Error",
363
+ details: instance.details || "An error has occurred.",
364
+ onDestroy: clearErrorComponent,
365
+ showCloseButton: true
366
+ };
367
+ setErrorComponentProps(props);
368
+ return props;
369
+ },
370
+ [clearErrorComponent]
371
+ );
267
372
  const handleError = useCallback3(
268
373
  async (error) => {
269
374
  if (error.status === 401) {
@@ -287,7 +392,10 @@ function useErrorHandler(options = {}) {
287
392
  return {
288
393
  handleError,
289
394
  showError,
290
- navigateToLogin
395
+ navigateToLogin,
396
+ createErrorComponent,
397
+ errorComponentProps,
398
+ clearErrorComponent
291
399
  };
292
400
  }
293
401
  function createErrorInterceptor(errorHandler) {
@@ -585,17 +693,141 @@ function ConfirmationDialog({ className }) {
585
693
  );
586
694
  }
587
695
 
696
+ // src/components/errors/ErrorComponent.tsx
697
+ import { Heading, Text as Text2, VStack, Button as Button2, Container } from "@chakra-ui/react";
698
+ import { jsx as jsx5, jsxs as jsxs3 } from "react/jsx-runtime";
699
+ function ErrorComponent({
700
+ title = "Error",
701
+ details = "An error has occurred.",
702
+ onDestroy,
703
+ showCloseButton = true,
704
+ closeButtonText = "Go Back"
705
+ }) {
706
+ return /* @__PURE__ */ jsx5(Container, { maxW: "container.md", py: 20, children: /* @__PURE__ */ jsxs3(VStack, { gap: 6, textAlign: "center", children: [
707
+ /* @__PURE__ */ jsx5(
708
+ Heading,
709
+ {
710
+ size: "4xl",
711
+ color: "red.500",
712
+ fontWeight: "bold",
713
+ children: title
714
+ }
715
+ ),
716
+ /* @__PURE__ */ jsx5(Text2, { fontSize: "lg", color: "gray.600", children: details }),
717
+ showCloseButton && onDestroy && /* @__PURE__ */ jsx5(
718
+ Button2,
719
+ {
720
+ colorPalette: "blue",
721
+ size: "lg",
722
+ onClick: onDestroy,
723
+ children: closeButtonText
724
+ }
725
+ )
726
+ ] }) });
727
+ }
728
+
729
+ // src/components/loader-bar/LoaderBar.tsx
730
+ import { useEffect as useEffect2, useRef as useRef5, useState as useState4 } from "react";
731
+ import { useLoader } from "@abpjs/core";
732
+ import { jsx as jsx6 } from "react/jsx-runtime";
733
+ function LoaderBar({
734
+ containerClass = "abp-loader-bar",
735
+ progressClass = "abp-progress",
736
+ filter
737
+ }) {
738
+ const { loading } = useLoader();
739
+ const [isLoading, setIsLoading] = useState4(false);
740
+ const [progressLevel, setProgressLevel] = useState4(0);
741
+ const intervalRef = useRef5(null);
742
+ useEffect2(() => {
743
+ if (loading) {
744
+ startLoading();
745
+ } else {
746
+ stopLoading();
747
+ }
748
+ }, [loading]);
749
+ useEffect2(() => {
750
+ return () => {
751
+ if (intervalRef.current) {
752
+ clearInterval(intervalRef.current);
753
+ }
754
+ };
755
+ }, []);
756
+ const startLoading = () => {
757
+ setIsLoading(true);
758
+ setProgressLevel(0);
759
+ if (intervalRef.current) {
760
+ clearInterval(intervalRef.current);
761
+ }
762
+ intervalRef.current = setInterval(() => {
763
+ setProgressLevel((prev) => {
764
+ if (prev >= 90) {
765
+ return prev + 0.5;
766
+ } else if (prev >= 75) {
767
+ return prev + 2;
768
+ } else if (prev >= 50) {
769
+ return prev + 5;
770
+ }
771
+ return prev + 10;
772
+ });
773
+ }, 300);
774
+ };
775
+ const stopLoading = () => {
776
+ setProgressLevel(100);
777
+ if (intervalRef.current) {
778
+ clearInterval(intervalRef.current);
779
+ intervalRef.current = null;
780
+ }
781
+ setTimeout(() => {
782
+ setIsLoading(false);
783
+ setProgressLevel(0);
784
+ }, 400);
785
+ };
786
+ if (!isLoading && progressLevel === 0) {
787
+ return null;
788
+ }
789
+ return /* @__PURE__ */ jsx6(
790
+ "div",
791
+ {
792
+ className: containerClass,
793
+ style: {
794
+ position: "fixed",
795
+ top: 0,
796
+ left: 0,
797
+ right: 0,
798
+ height: "3px",
799
+ zIndex: 9999,
800
+ backgroundColor: "rgba(0, 0, 0, 0.1)",
801
+ overflow: "hidden"
802
+ },
803
+ children: /* @__PURE__ */ jsx6(
804
+ "div",
805
+ {
806
+ className: progressClass,
807
+ style: {
808
+ height: "100%",
809
+ backgroundColor: "#3182ce",
810
+ transition: "width 0.3s ease-out",
811
+ width: `${Math.min(progressLevel, 100)}%`
812
+ }
813
+ }
814
+ )
815
+ }
816
+ );
817
+ }
818
+
588
819
  // src/components/modal/Modal.tsx
820
+ import React6 from "react";
589
821
  import {
590
822
  Dialog as Dialog2,
591
823
  Portal as Portal3,
592
- Box as Box2,
824
+ Box as Box3,
593
825
  Flex as Flex3,
594
- Text as Text2,
826
+ Text as Text3,
595
827
  Separator,
596
828
  CloseButton as CloseButton2
597
829
  } from "@chakra-ui/react";
598
- import { Fragment, jsx as jsx5, jsxs as jsxs3 } from "react/jsx-runtime";
830
+ import { Fragment, jsx as jsx7, jsxs as jsxs4 } from "react/jsx-runtime";
599
831
  function getSizeWidth(size) {
600
832
  switch (size) {
601
833
  case "sm":
@@ -615,9 +847,12 @@ function getSizeWidth(size) {
615
847
  function Modal({
616
848
  visible,
617
849
  onVisibleChange,
850
+ busy = false,
618
851
  size = "md",
619
852
  centered = true,
620
853
  modalClass,
854
+ height,
855
+ minHeight,
621
856
  header,
622
857
  children,
623
858
  footer,
@@ -627,44 +862,61 @@ function Modal({
627
862
  scrollBehavior = "inside",
628
863
  motionPreset = "scale",
629
864
  trapFocus = true,
630
- preventScroll = true
865
+ preventScroll = true,
866
+ onInit
631
867
  }) {
868
+ const prevVisibleRef = React6.useRef(false);
869
+ const onInitRef = React6.useRef(onInit);
870
+ React6.useEffect(() => {
871
+ onInitRef.current = onInit;
872
+ }, [onInit]);
873
+ React6.useEffect(() => {
874
+ if (visible && !prevVisibleRef.current && onInitRef.current) {
875
+ onInitRef.current();
876
+ }
877
+ prevVisibleRef.current = visible;
878
+ }, [visible]);
632
879
  const handleOpenChange = (details) => {
880
+ if (busy && !details.open) {
881
+ return;
882
+ }
633
883
  onVisibleChange?.(details.open);
634
884
  };
635
- return /* @__PURE__ */ jsx5(
885
+ return /* @__PURE__ */ jsx7(
636
886
  Dialog2.Root,
637
887
  {
638
888
  open: visible,
639
889
  onOpenChange: handleOpenChange,
640
890
  placement: centered ? "center" : "top",
641
- closeOnInteractOutside: closeOnOverlayClick,
642
- closeOnEscape,
891
+ closeOnInteractOutside: closeOnOverlayClick && !busy,
892
+ closeOnEscape: closeOnEscape && !busy,
643
893
  scrollBehavior,
644
894
  motionPreset,
645
895
  trapFocus,
646
896
  preventScroll,
647
- children: /* @__PURE__ */ jsxs3(Portal3, { children: [
648
- /* @__PURE__ */ jsx5(Dialog2.Backdrop, {}),
649
- /* @__PURE__ */ jsx5(Dialog2.Positioner, { children: /* @__PURE__ */ jsxs3(
897
+ children: /* @__PURE__ */ jsxs4(Portal3, { children: [
898
+ /* @__PURE__ */ jsx7(Dialog2.Backdrop, {}),
899
+ /* @__PURE__ */ jsx7(Dialog2.Positioner, { children: /* @__PURE__ */ jsxs4(
650
900
  Dialog2.Content,
651
901
  {
652
902
  className: modalClass,
653
903
  width: getSizeWidth(size),
654
904
  maxWidth: size === "full" ? "100vw" : void 0,
655
905
  maxHeight: size === "full" ? "100vh" : void 0,
906
+ height,
907
+ minHeight,
656
908
  children: [
657
- (header || showCloseButton) && /* @__PURE__ */ jsxs3(Fragment, { children: [
658
- /* @__PURE__ */ jsx5(Dialog2.Header, { children: /* @__PURE__ */ jsxs3(Flex3, { justify: "space-between", align: "center", width: "100%", children: [
659
- header && /* @__PURE__ */ jsx5(Dialog2.Title, { children: /* @__PURE__ */ jsx5(Text2, { fontWeight: "bold", fontSize: "lg", children: header }) }),
660
- showCloseButton && /* @__PURE__ */ jsx5(Dialog2.CloseTrigger, { asChild: true, children: /* @__PURE__ */ jsx5(CloseButton2, { size: "sm" }) })
909
+ (header || showCloseButton) && /* @__PURE__ */ jsxs4(Fragment, { children: [
910
+ /* @__PURE__ */ jsx7(Dialog2.Header, { children: /* @__PURE__ */ jsxs4(Flex3, { justify: "space-between", align: "center", width: "100%", children: [
911
+ header && /* @__PURE__ */ jsx7(Dialog2.Title, { children: /* @__PURE__ */ jsx7(Text3, { fontWeight: "bold", fontSize: "lg", children: header }) }),
912
+ showCloseButton && /* @__PURE__ */ jsx7(Dialog2.CloseTrigger, { asChild: true, children: /* @__PURE__ */ jsx7(CloseButton2, { size: "sm" }) })
661
913
  ] }) }),
662
- /* @__PURE__ */ jsx5(Separator, {})
914
+ /* @__PURE__ */ jsx7(Separator, {})
663
915
  ] }),
664
- children && /* @__PURE__ */ jsx5(Dialog2.Body, { py: 4, children }),
665
- footer && /* @__PURE__ */ jsxs3(Fragment, { children: [
666
- /* @__PURE__ */ jsx5(Separator, {}),
667
- /* @__PURE__ */ jsx5(Dialog2.Footer, { children: /* @__PURE__ */ jsx5(Flex3, { gap: 3, justify: "flex-end", w: "100%", children: footer }) })
916
+ children && /* @__PURE__ */ jsx7(Dialog2.Body, { py: 4, children }),
917
+ footer && /* @__PURE__ */ jsxs4(Fragment, { children: [
918
+ /* @__PURE__ */ jsx7(Separator, {}),
919
+ /* @__PURE__ */ jsx7(Dialog2.Footer, { children: /* @__PURE__ */ jsx7(Flex3, { gap: 3, justify: "flex-end", w: "100%", children: footer }) })
668
920
  ] })
669
921
  ]
670
922
  }
@@ -674,18 +926,18 @@ function Modal({
674
926
  );
675
927
  }
676
928
  function AbpModalHeader({ children, className }) {
677
- return /* @__PURE__ */ jsx5(Text2, { fontWeight: "bold", fontSize: "lg", className, children });
929
+ return /* @__PURE__ */ jsx7(Text3, { fontWeight: "bold", fontSize: "lg", className, children });
678
930
  }
679
931
  function AbpModalBody({ children, className }) {
680
- return /* @__PURE__ */ jsx5(Box2, { color: "gray.600", className, children });
932
+ return /* @__PURE__ */ jsx7(Box3, { color: "gray.600", className, children });
681
933
  }
682
934
  function AbpModalFooter({ children, className }) {
683
- return /* @__PURE__ */ jsx5(Flex3, { gap: 3, justify: "flex-end", className, children });
935
+ return /* @__PURE__ */ jsx7(Flex3, { gap: 3, justify: "flex-end", className, children });
684
936
  }
685
937
 
686
938
  // src/components/ui/Alert.tsx
687
939
  import { Alert as ChakraAlert } from "@chakra-ui/react";
688
- import { Fragment as Fragment2, jsx as jsx6, jsxs as jsxs4 } from "react/jsx-runtime";
940
+ import { Fragment as Fragment2, jsx as jsx8, jsxs as jsxs5 } from "react/jsx-runtime";
689
941
  function Alert({
690
942
  status = "info",
691
943
  children,
@@ -696,7 +948,7 @@ function Alert({
696
948
  mb,
697
949
  borderRadius = "md"
698
950
  }) {
699
- return /* @__PURE__ */ jsxs4(
951
+ return /* @__PURE__ */ jsxs5(
700
952
  ChakraAlert.Root,
701
953
  {
702
954
  status,
@@ -704,11 +956,11 @@ function Alert({
704
956
  mb,
705
957
  borderRadius,
706
958
  children: [
707
- showIcon && /* @__PURE__ */ jsx6(ChakraAlert.Indicator, {}),
708
- title ? /* @__PURE__ */ jsxs4(Fragment2, { children: [
709
- /* @__PURE__ */ jsx6(ChakraAlert.Title, { children: title }),
710
- (description || children) && /* @__PURE__ */ jsx6(ChakraAlert.Description, { children: description || children })
711
- ] }) : /* @__PURE__ */ jsx6(ChakraAlert.Title, { children })
959
+ showIcon && /* @__PURE__ */ jsx8(ChakraAlert.Indicator, {}),
960
+ title ? /* @__PURE__ */ jsxs5(Fragment2, { children: [
961
+ /* @__PURE__ */ jsx8(ChakraAlert.Title, { children: title }),
962
+ (description || children) && /* @__PURE__ */ jsx8(ChakraAlert.Description, { children: description || children })
963
+ ] }) : /* @__PURE__ */ jsx8(ChakraAlert.Title, { children })
712
964
  ]
713
965
  }
714
966
  );
@@ -717,9 +969,9 @@ function Alert({
717
969
  // src/components/ui/Button.tsx
718
970
  import { forwardRef } from "react";
719
971
  import { Button as ChakraButton } from "@chakra-ui/react";
720
- import { jsx as jsx7 } from "react/jsx-runtime";
721
- var Button2 = forwardRef(
722
- function Button3({
972
+ import { jsx as jsx9 } from "react/jsx-runtime";
973
+ var Button3 = forwardRef(
974
+ function Button4({
723
975
  children,
724
976
  type = "button",
725
977
  variant = "solid",
@@ -734,7 +986,7 @@ var Button2 = forwardRef(
734
986
  mr,
735
987
  ml
736
988
  }, ref) {
737
- return /* @__PURE__ */ jsx7(
989
+ return /* @__PURE__ */ jsx9(
738
990
  ChakraButton,
739
991
  {
740
992
  ref,
@@ -759,7 +1011,7 @@ var Button2 = forwardRef(
759
1011
  // src/components/ui/Checkbox.tsx
760
1012
  import { forwardRef as forwardRef2 } from "react";
761
1013
  import { Checkbox as ChakraCheckbox } from "@chakra-ui/react";
762
- import { jsx as jsx8, jsxs as jsxs5 } from "react/jsx-runtime";
1014
+ import { jsx as jsx10, jsxs as jsxs6 } from "react/jsx-runtime";
763
1015
  var Checkbox = forwardRef2(
764
1016
  function Checkbox2({
765
1017
  children,
@@ -777,7 +1029,7 @@ var Checkbox = forwardRef2(
777
1029
  onChange,
778
1030
  className
779
1031
  }, ref) {
780
- return /* @__PURE__ */ jsxs5(
1032
+ return /* @__PURE__ */ jsxs6(
781
1033
  ChakraCheckbox.Root,
782
1034
  {
783
1035
  checked,
@@ -790,7 +1042,7 @@ var Checkbox = forwardRef2(
790
1042
  size,
791
1043
  className,
792
1044
  children: [
793
- /* @__PURE__ */ jsx8(
1045
+ /* @__PURE__ */ jsx10(
794
1046
  ChakraCheckbox.HiddenInput,
795
1047
  {
796
1048
  ref,
@@ -800,8 +1052,8 @@ var Checkbox = forwardRef2(
800
1052
  onChange
801
1053
  }
802
1054
  ),
803
- /* @__PURE__ */ jsx8(ChakraCheckbox.Control, {}),
804
- children && /* @__PURE__ */ jsx8(ChakraCheckbox.Label, { children })
1055
+ /* @__PURE__ */ jsx10(ChakraCheckbox.Control, {}),
1056
+ children && /* @__PURE__ */ jsx10(ChakraCheckbox.Label, { children })
805
1057
  ]
806
1058
  }
807
1059
  );
@@ -810,7 +1062,7 @@ var Checkbox = forwardRef2(
810
1062
 
811
1063
  // src/components/ui/FormField.tsx
812
1064
  import { Field } from "@chakra-ui/react";
813
- import { jsx as jsx9, jsxs as jsxs6 } from "react/jsx-runtime";
1065
+ import { jsx as jsx11, jsxs as jsxs7 } from "react/jsx-runtime";
814
1066
  function FormField({
815
1067
  label,
816
1068
  invalid = false,
@@ -822,15 +1074,365 @@ function FormField({
822
1074
  htmlFor,
823
1075
  className
824
1076
  }) {
825
- return /* @__PURE__ */ jsxs6(Field.Root, { invalid, disabled, className, children: [
826
- label && /* @__PURE__ */ jsxs6(Field.Label, { htmlFor, children: [
1077
+ return /* @__PURE__ */ jsxs7(Field.Root, { invalid, disabled, className, children: [
1078
+ label && /* @__PURE__ */ jsxs7(Field.Label, { htmlFor, children: [
827
1079
  label,
828
- required && /* @__PURE__ */ jsx9(Field.RequiredIndicator, {})
1080
+ required && /* @__PURE__ */ jsx11(Field.RequiredIndicator, {})
829
1081
  ] }),
830
1082
  children,
831
- helperText && !invalid && /* @__PURE__ */ jsx9(Field.HelperText, { children: helperText }),
832
- invalid && errorText && /* @__PURE__ */ jsx9(Field.ErrorText, { children: errorText })
1083
+ helperText && !invalid && /* @__PURE__ */ jsx11(Field.HelperText, { children: helperText }),
1084
+ invalid && errorText && /* @__PURE__ */ jsx11(Field.ErrorText, { children: errorText })
1085
+ ] });
1086
+ }
1087
+
1088
+ // src/components/change-password/ChangePassword.tsx
1089
+ import { useEffect as useEffect3 } from "react";
1090
+ import {
1091
+ Button as Button5,
1092
+ VStack as VStack2,
1093
+ Input,
1094
+ Field as Field2
1095
+ } from "@chakra-ui/react";
1096
+ import { useForm } from "react-hook-form";
1097
+ import { useLocalization as useLocalization3, useProfile } from "@abpjs/core";
1098
+ import { Check } from "lucide-react";
1099
+ import { Fragment as Fragment3, jsx as jsx12, jsxs as jsxs8 } from "react/jsx-runtime";
1100
+ function ChangePassword({
1101
+ visible,
1102
+ onVisibleChange
1103
+ }) {
1104
+ const { t } = useLocalization3();
1105
+ const { changePassword } = useProfile();
1106
+ const toaster = useToaster();
1107
+ const {
1108
+ register,
1109
+ handleSubmit,
1110
+ watch,
1111
+ reset,
1112
+ formState: { errors, isSubmitting }
1113
+ } = useForm({
1114
+ defaultValues: {
1115
+ password: "",
1116
+ newPassword: "",
1117
+ repeatNewPassword: ""
1118
+ }
1119
+ });
1120
+ const newPassword = watch("newPassword");
1121
+ useEffect3(() => {
1122
+ if (visible) {
1123
+ reset();
1124
+ }
1125
+ }, [visible, reset]);
1126
+ const onSubmit = async (data) => {
1127
+ try {
1128
+ await changePassword({
1129
+ currentPassword: data.password,
1130
+ newPassword: data.newPassword
1131
+ });
1132
+ toaster.success(
1133
+ t("AbpIdentity::PasswordChangedMessage") || "Password changed successfully",
1134
+ t("AbpUi::Success") || "Success"
1135
+ );
1136
+ onVisibleChange(false);
1137
+ } catch (error) {
1138
+ toaster.error(
1139
+ error instanceof Error ? error.message : "An error occurred",
1140
+ t("AbpIdentity::PasswordChangeFailed") || "Failed to change password"
1141
+ );
1142
+ }
1143
+ };
1144
+ const handleClose = () => {
1145
+ if (!isSubmitting) {
1146
+ onVisibleChange(false);
1147
+ }
1148
+ };
1149
+ const passwordValidation = {
1150
+ required: t("AbpIdentity::ThisFieldIsRequired") || "This field is required",
1151
+ minLength: {
1152
+ value: 6,
1153
+ message: t("AbpIdentity::PasswordTooShort") || "Password must be at least 6 characters"
1154
+ },
1155
+ validate: {
1156
+ hasLowercase: (value) => /[a-z]/.test(value) || t("AbpIdentity::PasswordRequiresLower") || "Password must contain a lowercase letter",
1157
+ hasUppercase: (value) => /[A-Z]/.test(value) || t("AbpIdentity::PasswordRequiresUpper") || "Password must contain an uppercase letter",
1158
+ hasNumber: (value) => /[0-9]/.test(value) || t("AbpIdentity::PasswordRequiresDigit") || "Password must contain a number",
1159
+ hasSpecial: (value) => /[!@#$%^&*(),.?":{}|<>]/.test(value) || t("AbpIdentity::PasswordRequiresNonAlphanumeric") || "Password must contain a special character"
1160
+ }
1161
+ };
1162
+ const modalFooter = /* @__PURE__ */ jsxs8(Fragment3, { children: [
1163
+ /* @__PURE__ */ jsx12(Button5, { variant: "ghost", mr: 3, onClick: handleClose, disabled: isSubmitting, children: t("AbpIdentity::Cancel") || "Cancel" }),
1164
+ /* @__PURE__ */ jsxs8(
1165
+ Button5,
1166
+ {
1167
+ colorPalette: "blue",
1168
+ type: "submit",
1169
+ loading: isSubmitting,
1170
+ form: "change-password-form",
1171
+ children: [
1172
+ /* @__PURE__ */ jsx12(Check, { size: 16 }),
1173
+ t("AbpIdentity::Save") || "Save"
1174
+ ]
1175
+ }
1176
+ )
833
1177
  ] });
1178
+ return /* @__PURE__ */ jsx12(
1179
+ Modal,
1180
+ {
1181
+ visible,
1182
+ onVisibleChange,
1183
+ busy: isSubmitting,
1184
+ header: t("AbpIdentity::ChangePassword") || "Change Password",
1185
+ footer: modalFooter,
1186
+ centered: true,
1187
+ children: /* @__PURE__ */ jsx12("form", { id: "change-password-form", onSubmit: handleSubmit(onSubmit), children: /* @__PURE__ */ jsxs8(VStack2, { gap: 4, children: [
1188
+ /* @__PURE__ */ jsxs8(Field2.Root, { invalid: !!errors.password, children: [
1189
+ /* @__PURE__ */ jsxs8(Field2.Label, { children: [
1190
+ t("AbpIdentity::DisplayName:CurrentPassword") || "Current Password",
1191
+ /* @__PURE__ */ jsx12(Field2.RequiredIndicator, {})
1192
+ ] }),
1193
+ /* @__PURE__ */ jsx12(
1194
+ Input,
1195
+ {
1196
+ type: "password",
1197
+ ...register("password", {
1198
+ required: t("AbpIdentity::ThisFieldIsRequired") || "This field is required"
1199
+ })
1200
+ }
1201
+ ),
1202
+ /* @__PURE__ */ jsx12(Field2.ErrorText, { children: errors.password?.message })
1203
+ ] }),
1204
+ /* @__PURE__ */ jsxs8(Field2.Root, { invalid: !!errors.newPassword, children: [
1205
+ /* @__PURE__ */ jsxs8(Field2.Label, { children: [
1206
+ t("AbpIdentity::DisplayName:NewPassword") || "New Password",
1207
+ /* @__PURE__ */ jsx12(Field2.RequiredIndicator, {})
1208
+ ] }),
1209
+ /* @__PURE__ */ jsx12(
1210
+ Input,
1211
+ {
1212
+ type: "password",
1213
+ ...register("newPassword", passwordValidation)
1214
+ }
1215
+ ),
1216
+ /* @__PURE__ */ jsx12(Field2.ErrorText, { children: errors.newPassword?.message })
1217
+ ] }),
1218
+ /* @__PURE__ */ jsxs8(Field2.Root, { invalid: !!errors.repeatNewPassword, children: [
1219
+ /* @__PURE__ */ jsxs8(Field2.Label, { children: [
1220
+ t("AbpIdentity::DisplayName:NewPasswordConfirm") || "Confirm New Password",
1221
+ /* @__PURE__ */ jsx12(Field2.RequiredIndicator, {})
1222
+ ] }),
1223
+ /* @__PURE__ */ jsx12(
1224
+ Input,
1225
+ {
1226
+ type: "password",
1227
+ ...register("repeatNewPassword", {
1228
+ required: t("AbpIdentity::ThisFieldIsRequired") || "This field is required",
1229
+ validate: (value) => value === newPassword || t("AbpIdentity::Identity.PasswordConfirmationFailed") || "Passwords do not match"
1230
+ })
1231
+ }
1232
+ ),
1233
+ /* @__PURE__ */ jsx12(Field2.ErrorText, { children: errors.repeatNewPassword?.message })
1234
+ ] })
1235
+ ] }) })
1236
+ }
1237
+ );
1238
+ }
1239
+
1240
+ // src/components/profile/Profile.tsx
1241
+ import { useEffect as useEffect4 } from "react";
1242
+ import {
1243
+ Button as Button6,
1244
+ VStack as VStack3,
1245
+ HStack,
1246
+ Input as Input2,
1247
+ Field as Field3
1248
+ } from "@chakra-ui/react";
1249
+ import { useForm as useForm2 } from "react-hook-form";
1250
+ import { useLocalization as useLocalization4, useProfile as useProfile2 } from "@abpjs/core";
1251
+ import { Check as Check2 } from "lucide-react";
1252
+ import { Fragment as Fragment4, jsx as jsx13, jsxs as jsxs9 } from "react/jsx-runtime";
1253
+ function Profile({
1254
+ visible,
1255
+ onVisibleChange
1256
+ }) {
1257
+ const { t } = useLocalization4();
1258
+ const { profile, fetchProfile, updateProfile, loading } = useProfile2();
1259
+ const toaster = useToaster();
1260
+ const {
1261
+ register,
1262
+ handleSubmit,
1263
+ reset,
1264
+ formState: { errors, isSubmitting }
1265
+ } = useForm2({
1266
+ defaultValues: {
1267
+ userName: "",
1268
+ email: "",
1269
+ name: "",
1270
+ surname: "",
1271
+ phoneNumber: ""
1272
+ }
1273
+ });
1274
+ const modalBusy = isSubmitting || loading;
1275
+ useEffect4(() => {
1276
+ if (visible) {
1277
+ fetchProfile().then(() => {
1278
+ });
1279
+ }
1280
+ }, [visible, fetchProfile]);
1281
+ useEffect4(() => {
1282
+ if (profile) {
1283
+ reset({
1284
+ userName: profile.userName || "",
1285
+ email: profile.email || "",
1286
+ name: profile.name || "",
1287
+ surname: profile.surname || "",
1288
+ phoneNumber: profile.phoneNumber || ""
1289
+ });
1290
+ }
1291
+ }, [profile, reset]);
1292
+ const onSubmit = async (data) => {
1293
+ try {
1294
+ await updateProfile(data);
1295
+ toaster.success(
1296
+ t("AbpIdentity::ProfileUpdatedMessage") || "Profile updated successfully",
1297
+ t("AbpUi::Success") || "Success"
1298
+ );
1299
+ onVisibleChange(false);
1300
+ } catch (error) {
1301
+ toaster.error(
1302
+ error instanceof Error ? error.message : "An error occurred",
1303
+ t("AbpIdentity::ProfileUpdateFailed") || "Failed to update profile"
1304
+ );
1305
+ }
1306
+ };
1307
+ const handleClose = () => {
1308
+ if (!modalBusy) {
1309
+ onVisibleChange(false);
1310
+ }
1311
+ };
1312
+ const modalFooter = /* @__PURE__ */ jsxs9(Fragment4, { children: [
1313
+ /* @__PURE__ */ jsx13(Button6, { variant: "ghost", mr: 3, onClick: handleClose, disabled: modalBusy, children: t("AbpIdentity::Cancel") || "Cancel" }),
1314
+ /* @__PURE__ */ jsxs9(
1315
+ Button6,
1316
+ {
1317
+ colorPalette: "blue",
1318
+ type: "submit",
1319
+ loading: modalBusy,
1320
+ form: "profile-form",
1321
+ children: [
1322
+ /* @__PURE__ */ jsx13(Check2, { size: 16 }),
1323
+ t("AbpIdentity::Save") || "Save"
1324
+ ]
1325
+ }
1326
+ )
1327
+ ] });
1328
+ return /* @__PURE__ */ jsx13(
1329
+ Modal,
1330
+ {
1331
+ visible,
1332
+ onVisibleChange,
1333
+ busy: modalBusy,
1334
+ header: t("AbpIdentity::PersonalInfo") || "Personal Info",
1335
+ footer: modalFooter,
1336
+ size: "lg",
1337
+ centered: true,
1338
+ children: /* @__PURE__ */ jsx13("form", { id: "profile-form", onSubmit: handleSubmit(onSubmit), children: /* @__PURE__ */ jsxs9(VStack3, { gap: 4, children: [
1339
+ /* @__PURE__ */ jsxs9(Field3.Root, { invalid: !!errors.userName, children: [
1340
+ /* @__PURE__ */ jsxs9(Field3.Label, { children: [
1341
+ t("AbpIdentity::DisplayName:UserName") || "Username",
1342
+ /* @__PURE__ */ jsx13(Field3.RequiredIndicator, {})
1343
+ ] }),
1344
+ /* @__PURE__ */ jsx13(
1345
+ Input2,
1346
+ {
1347
+ type: "text",
1348
+ ...register("userName", {
1349
+ required: t("AbpIdentity::ThisFieldIsRequired") || "This field is required",
1350
+ maxLength: {
1351
+ value: 256,
1352
+ message: "Maximum 256 characters"
1353
+ }
1354
+ })
1355
+ }
1356
+ ),
1357
+ /* @__PURE__ */ jsx13(Field3.ErrorText, { children: errors.userName?.message })
1358
+ ] }),
1359
+ /* @__PURE__ */ jsxs9(HStack, { gap: 4, w: "full", children: [
1360
+ /* @__PURE__ */ jsxs9(Field3.Root, { invalid: !!errors.name, flex: 1, children: [
1361
+ /* @__PURE__ */ jsx13(Field3.Label, { children: t("AbpIdentity::DisplayName:Name") || "Name" }),
1362
+ /* @__PURE__ */ jsx13(
1363
+ Input2,
1364
+ {
1365
+ type: "text",
1366
+ ...register("name", {
1367
+ maxLength: {
1368
+ value: 64,
1369
+ message: "Maximum 64 characters"
1370
+ }
1371
+ })
1372
+ }
1373
+ ),
1374
+ /* @__PURE__ */ jsx13(Field3.ErrorText, { children: errors.name?.message })
1375
+ ] }),
1376
+ /* @__PURE__ */ jsxs9(Field3.Root, { invalid: !!errors.surname, flex: 1, children: [
1377
+ /* @__PURE__ */ jsx13(Field3.Label, { children: t("AbpIdentity::DisplayName:Surname") || "Surname" }),
1378
+ /* @__PURE__ */ jsx13(
1379
+ Input2,
1380
+ {
1381
+ type: "text",
1382
+ ...register("surname", {
1383
+ maxLength: {
1384
+ value: 64,
1385
+ message: "Maximum 64 characters"
1386
+ }
1387
+ })
1388
+ }
1389
+ ),
1390
+ /* @__PURE__ */ jsx13(Field3.ErrorText, { children: errors.surname?.message })
1391
+ ] })
1392
+ ] }),
1393
+ /* @__PURE__ */ jsxs9(Field3.Root, { invalid: !!errors.email, children: [
1394
+ /* @__PURE__ */ jsxs9(Field3.Label, { children: [
1395
+ t("AbpIdentity::DisplayName:EmailAddress") || "Email Address",
1396
+ /* @__PURE__ */ jsx13(Field3.RequiredIndicator, {})
1397
+ ] }),
1398
+ /* @__PURE__ */ jsx13(
1399
+ Input2,
1400
+ {
1401
+ type: "email",
1402
+ ...register("email", {
1403
+ required: t("AbpIdentity::ThisFieldIsRequired") || "This field is required",
1404
+ pattern: {
1405
+ value: /^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}$/i,
1406
+ message: t("AbpIdentity::InvalidEmail") || "Invalid email address"
1407
+ },
1408
+ maxLength: {
1409
+ value: 256,
1410
+ message: "Maximum 256 characters"
1411
+ }
1412
+ })
1413
+ }
1414
+ ),
1415
+ /* @__PURE__ */ jsx13(Field3.ErrorText, { children: errors.email?.message })
1416
+ ] }),
1417
+ /* @__PURE__ */ jsxs9(Field3.Root, { invalid: !!errors.phoneNumber, children: [
1418
+ /* @__PURE__ */ jsx13(Field3.Label, { children: t("AbpIdentity::DisplayName:PhoneNumber") || "Phone Number" }),
1419
+ /* @__PURE__ */ jsx13(
1420
+ Input2,
1421
+ {
1422
+ type: "tel",
1423
+ ...register("phoneNumber", {
1424
+ maxLength: {
1425
+ value: 16,
1426
+ message: "Maximum 16 characters"
1427
+ }
1428
+ })
1429
+ }
1430
+ ),
1431
+ /* @__PURE__ */ jsx13(Field3.ErrorText, { children: errors.phoneNumber?.message })
1432
+ ] })
1433
+ ] }) })
1434
+ }
1435
+ );
834
1436
  }
835
1437
 
836
1438
  // src/providers/ThemeSharedProvider.tsx
@@ -1071,11 +1673,11 @@ var abpSystem = createAbpSystem();
1071
1673
  // src/components/ui/color-mode.tsx
1072
1674
  import { ClientOnly, IconButton, Skeleton, Span } from "@chakra-ui/react";
1073
1675
  import { ThemeProvider, useTheme } from "next-themes";
1074
- import * as React7 from "react";
1676
+ import * as React11 from "react";
1075
1677
  import { Moon, Sun } from "lucide-react";
1076
- import { jsx as jsx10 } from "react/jsx-runtime";
1678
+ import { jsx as jsx14 } from "react/jsx-runtime";
1077
1679
  function ColorModeProvider(props) {
1078
- return /* @__PURE__ */ jsx10(ThemeProvider, { attribute: "class", disableTransitionOnChange: true, ...props });
1680
+ return /* @__PURE__ */ jsx14(ThemeProvider, { attribute: "class", disableTransitionOnChange: true, ...props });
1079
1681
  }
1080
1682
  function useColorMode() {
1081
1683
  const { resolvedTheme, setTheme, forcedTheme } = useTheme();
@@ -1091,11 +1693,11 @@ function useColorMode() {
1091
1693
  }
1092
1694
  function ColorModeIcon() {
1093
1695
  const { colorMode } = useColorMode();
1094
- return colorMode === "dark" ? /* @__PURE__ */ jsx10(Moon, {}) : /* @__PURE__ */ jsx10(Sun, {});
1696
+ return colorMode === "dark" ? /* @__PURE__ */ jsx14(Moon, {}) : /* @__PURE__ */ jsx14(Sun, {});
1095
1697
  }
1096
- var ColorModeButton = React7.forwardRef(function ColorModeButton2(props, ref) {
1698
+ var ColorModeButton = React11.forwardRef(function ColorModeButton2(props, ref) {
1097
1699
  const { toggleColorMode } = useColorMode();
1098
- return /* @__PURE__ */ jsx10(ClientOnly, { fallback: /* @__PURE__ */ jsx10(Skeleton, { boxSize: "9" }), children: /* @__PURE__ */ jsx10(
1700
+ return /* @__PURE__ */ jsx14(ClientOnly, { fallback: /* @__PURE__ */ jsx14(Skeleton, { boxSize: "9" }), children: /* @__PURE__ */ jsx14(
1099
1701
  IconButton,
1100
1702
  {
1101
1703
  onClick: toggleColorMode,
@@ -1110,13 +1712,13 @@ var ColorModeButton = React7.forwardRef(function ColorModeButton2(props, ref) {
1110
1712
  height: "5"
1111
1713
  }
1112
1714
  },
1113
- children: /* @__PURE__ */ jsx10(ColorModeIcon, {})
1715
+ children: /* @__PURE__ */ jsx14(ColorModeIcon, {})
1114
1716
  }
1115
1717
  ) });
1116
1718
  });
1117
- var LightMode = React7.forwardRef(
1719
+ var LightMode = React11.forwardRef(
1118
1720
  function LightMode2(props, ref) {
1119
- return /* @__PURE__ */ jsx10(
1721
+ return /* @__PURE__ */ jsx14(
1120
1722
  Span,
1121
1723
  {
1122
1724
  color: "fg",
@@ -1130,9 +1732,9 @@ var LightMode = React7.forwardRef(
1130
1732
  );
1131
1733
  }
1132
1734
  );
1133
- var DarkMode = React7.forwardRef(
1735
+ var DarkMode = React11.forwardRef(
1134
1736
  function DarkMode2(props, ref) {
1135
- return /* @__PURE__ */ jsx10(
1737
+ return /* @__PURE__ */ jsx14(
1136
1738
  Span,
1137
1739
  {
1138
1740
  color: "fg",
@@ -1149,7 +1751,7 @@ var DarkMode = React7.forwardRef(
1149
1751
 
1150
1752
  // src/providers/ThemeSharedProvider.tsx
1151
1753
  import { useDirection } from "@abpjs/core";
1152
- import { jsx as jsx11, jsxs as jsxs7 } from "react/jsx-runtime";
1754
+ import { jsx as jsx15, jsxs as jsxs10 } from "react/jsx-runtime";
1153
1755
  function ThemeSharedProvider({
1154
1756
  children,
1155
1757
  renderToasts = true,
@@ -1163,13 +1765,13 @@ function ThemeSharedProvider({
1163
1765
  const system = themeOverrides ? createAbpSystem(themeOverrides) : abpSystem;
1164
1766
  const { endSide } = useDirection();
1165
1767
  toastPosition = `bottom-${endSide}`;
1166
- const content = /* @__PURE__ */ jsx11(ToasterProvider, { children: /* @__PURE__ */ jsxs7(ConfirmationProvider, { children: [
1768
+ const content = /* @__PURE__ */ jsx15(ToasterProvider, { children: /* @__PURE__ */ jsxs10(ConfirmationProvider, { children: [
1167
1769
  children,
1168
- renderToasts && /* @__PURE__ */ jsx11(ToastContainer, { position: toastPosition }),
1169
- renderConfirmation && /* @__PURE__ */ jsx11(ConfirmationDialog, {})
1770
+ renderToasts && /* @__PURE__ */ jsx15(ToastContainer, { position: toastPosition }),
1771
+ renderConfirmation && /* @__PURE__ */ jsx15(ConfirmationDialog, {})
1170
1772
  ] }) });
1171
1773
  const colorModeProps = enableColorMode ? { defaultTheme: defaultColorMode } : { forcedTheme: "light" };
1172
- return /* @__PURE__ */ jsx11(ChakraProvider, { value: system, children: /* @__PURE__ */ jsx11(LocaleProvider, { locale, children: /* @__PURE__ */ jsx11(ColorModeProvider, { ...colorModeProps, children: content }) }) });
1774
+ return /* @__PURE__ */ jsx15(ChakraProvider, { value: system, children: /* @__PURE__ */ jsx15(LocaleProvider, { locale, children: /* @__PURE__ */ jsx15(ColorModeProvider, { ...colorModeProps, children: content }) }) });
1173
1775
  }
1174
1776
 
1175
1777
  // src/utils/styles.ts
@@ -1247,16 +1849,21 @@ export {
1247
1849
  AbpModalFooter,
1248
1850
  AbpModalHeader,
1249
1851
  Alert,
1250
- Button2 as Button,
1852
+ Button3 as Button,
1251
1853
  Dialog2 as ChakraDialog,
1854
+ ChangePassword,
1252
1855
  Checkbox,
1253
1856
  ConfirmationDialog,
1254
1857
  ConfirmationProvider,
1858
+ DEFAULT_STYLES,
1859
+ ErrorComponent,
1255
1860
  FormField,
1861
+ LoaderBar,
1256
1862
  Modal,
1257
1863
  AbpModalBody as ModalBody,
1258
1864
  AbpModalFooter as ModalFooter,
1259
1865
  AbpModalHeader as ModalHeader,
1866
+ Profile,
1260
1867
  THEME_SHARED_STYLES,
1261
1868
  ThemeSharedProvider,
1262
1869
  ToastContainer,