nexus-shared 1.1.17 → 1.1.19

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.
Files changed (58) hide show
  1. package/package.json +1 -1
  2. package/src/api-services/system-service.tsx +1 -2
  3. package/src/client.ts +3 -2
  4. package/src/components/documents/button.tsx +5 -1
  5. package/src/components/inputs/input-box.tsx +4 -2
  6. package/src/components/inputs/input-form.tsx +126 -14
  7. package/src/components/layouts/global-layout.tsx +4 -2
  8. package/src/components/layouts/layout-helpers.tsx +23 -23
  9. package/src/helpers/browser-helpers.tsx +41 -1
  10. package/src/helpers/input-helpers.tsx +34 -4
  11. package/src/helpers/utility-helpers.tsx +1 -0
  12. package/src/helpers/validation-helpers.tsx +302 -0
  13. package/src/index.ts +3 -18
  14. package/src/interface.ts +4 -1
  15. package/src/interfaces/button-interfaces.tsx +2 -2
  16. package/src/interfaces/exception-interfaces.tsx +99 -0
  17. package/src/interfaces/http-interfaces.tsx +120 -3
  18. package/src/interfaces/input-interfaces.tsx +61 -11
  19. package/src/interfaces/message-interfaces.tsx +32 -0
  20. package/src/interfaces/permission-interfaces.tsx +4 -4
  21. package/src/interfaces/storage-interfaces.tsx +1 -0
  22. package/src/interfaces/system-interfaces.tsx +2 -2
  23. package/src/interfaces/type-interfaces.tsx +8 -2
  24. package/src/interfaces/user-interfaces.tsx +17 -0
  25. package/src/nexus.environments.tsx +27 -17
  26. package/src/proxy-api/proxy-backend.tsx +60 -0
  27. package/src/proxy-api/proxy-constants.tsx +28 -0
  28. package/src/proxy-api/proxy-helpers.tsx +91 -0
  29. package/src/proxy-api-client.tsx +1 -0
  30. package/src/proxy-api-server.tsx +2 -0
  31. package/src/services/http-client-services.tsx +75 -0
  32. package/src/services/http-services.tsx +158 -0
  33. package/src/services/loader-service.tsx +5 -4
  34. package/src/services/localstorage-service.tsx +59 -0
  35. package/src/services/message-services.tsx +383 -0
  36. package/src/sso-config/auth-token-validation.ts +20 -0
  37. package/src/sso-config/callback-route.tsx +34 -0
  38. package/src/sso-config/cookie-encryption.ts +51 -0
  39. package/src/sso-config/cookie-helpers.tsx +77 -0
  40. package/src/sso-config/forgot-password-route.tsx +36 -0
  41. package/src/sso-config/oauth-callback-state.ts +58 -0
  42. package/src/sso-config/pkce-helpers.ts +16 -0
  43. package/src/sso-config/provider-complete-route.tsx +15 -0
  44. package/src/sso-config/redirect-context-actions.tsx +46 -0
  45. package/src/sso-config/redirect-context-helpers.tsx +144 -0
  46. package/src/sso-config/redirect-context-persist.tsx +18 -0
  47. package/src/sso-config/redirect-context-route.tsx +45 -0
  48. package/src/sso-config/refresh-route.tsx +22 -0
  49. package/src/sso-config/sign-in-route.tsx +69 -0
  50. package/src/sso-config/sign-out-route.tsx +53 -0
  51. package/src/sso-config/sign-up-route.tsx +46 -0
  52. package/src/sso-config/sso-backend-flow.ts +45 -0
  53. package/src/sso-config/sso-complete-route.tsx +46 -0
  54. package/src/sso-config/sso-config.ts +57 -0
  55. package/src/sso-config/sso-interfaces.tsx +68 -0
  56. package/src/sso-config/sso-response-helpers.tsx +20 -0
  57. package/src/sso-server.tsx +21 -1
  58. package/src/styles/nexus.dialog.css +3 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nexus-shared",
3
- "version": "1.1.17",
3
+ "version": "1.1.19",
4
4
  "description": "Nexus shared React components for Next.js",
5
5
  "type": "module",
6
6
  "sideEffects": [
@@ -1,6 +1,5 @@
1
1
  import { EIcons } from "../interfaces/icon-interfaces";
2
- import { EMenuTargets, EMenuVisibility, IClientMenu, IPanelMenu, IUtilityMenu } from "../interfaces/menu-interfaces";
3
- import { ENexusModules } from "../interfaces/system-interfaces";
2
+ import { EMenuVisibility, IClientMenu, IPanelMenu, IUtilityMenu } from "../interfaces/menu-interfaces";
4
3
 
5
4
  export const GetClientMenus = async (): Promise<IClientMenu[]> => {
6
5
  return [
package/src/client.ts CHANGED
@@ -21,11 +21,12 @@ export * from "./components/inputs/input";
21
21
  export * from "./components/inputs/input-box";
22
22
  export * from "./components/inputs/input-element";
23
23
  export * from "./helpers/browser-helpers";
24
+ export * from "./services/http-client-services";
24
25
  export * from "./services/loader-service";
25
26
  export * from "./services/localstorage-service";
27
+ export * from "./services/message-services";
26
28
  export * from "./services/theme-service";
27
-
28
29
  // Core
29
30
  export * from "./nexus-client";
31
+ export * from "./proxy-api-client";
30
32
  export * from "./sso-client";
31
-
@@ -42,11 +42,15 @@ export const CreateButton = (param: IButton, parent?: HTMLElement | UN, styles?:
42
42
 
43
43
  SetElementStyles(button, styles);
44
44
 
45
- button.className = DEFAULT_BUTTON_CLASS(param.columnSize, undefined, param.borderSize, param.background ?? NEXUS_CONFIG.DEFAULT_BACKGROUND, undefined, needColumnSize);
45
+ button.className = DEFAULT_BUTTON_CLASS(param.columnSize ?? 0, 0, param.borderSize, param.background ?? NEXUS_CONFIG.DEFAULT_BACKGROUND, param.defaultClass, needColumnSize);
46
46
  const span = document.createElement("span");
47
47
  span.textContent = param.label instanceof Function ? (param.label(param.data) ?? null) : (param.label ?? null);
48
48
  button.appendChild(span);
49
49
  button.onclick = (e) => param.onClick?.(e, button, param.data, param.displayOrder);
50
+ button.style.height = "var(--IH)";
51
+
52
+ button.classList.add("df", "ac", "pl5", "pr5");
53
+
50
54
  if (param.url) {
51
55
  (button as HTMLAnchorElement).href = param.url;
52
56
  (button as HTMLAnchorElement).target = param.target ?? ETargets.Blank;
@@ -1,3 +1,4 @@
1
+ import { INPUT_ICON_BOX_CLASS } from "../../helpers/input-helpers";
1
2
  import { DEFAULT_INPUT_BORDER_SIZE, IInputRootParameters, REQUIRED_TEXT1 } from "../../interfaces/input-interfaces";
2
3
  import { EBackgrounds } from "../../interfaces/theme-interfaces";
3
4
  import { NEXUS_CONFIG } from "../../nexus.environments";
@@ -16,7 +17,7 @@ export const CreateInputBox = (param: IInputRootParameters<any>, child: HTMLElem
16
17
  if (param.label && !isTabular) {
17
18
  const label = document.createElement("label");
18
19
  label.className = "pa t50 ty50 left ilb en anim ml2";
19
- label.innerHTML = param.label + ((param as any).isRequired ? `<span class="tx21 fs-08 ml1">${REQUIRED_TEXT1}</span>` : "");
20
+ label.innerHTML = param.label + ((param as any).isRequired ? `<span style="color: var(--B13)" class="fs-08 ml1">${REQUIRED_TEXT1}</span>` : "");
20
21
  label.htmlFor = param.id;
21
22
  box.appendChild(label);
22
23
  }
@@ -24,7 +25,8 @@ export const CreateInputBox = (param: IInputRootParameters<any>, child: HTMLElem
24
25
  if (param.icon) {
25
26
  box.classList.add("df", "ac");
26
27
  const I = param.icon;
27
- CreateIconBox(I.icon, box, null, null, I.type, I.background ?? param.background ?? EBackgrounds.None, I.boxSize, I.iconSize, null, null, null, null, I.opacity, null, null, null, null, I.onClicked, I.onMouseEnter, (I.onClicked || I.onMouseEnter) !== undefined);
28
+ const iconBox = CreateIconBox(I.icon, box, null, null, I.type, I.background ?? param.background ?? EBackgrounds.None, I.boxSize, I.iconSize, null, null, null, null, I.opacity, null, null, null, null, I.onClicked, I.onMouseEnter, (I.onClicked || I.onMouseEnter) !== undefined);
29
+ iconBox.classList.add(INPUT_ICON_BOX_CLASS);
28
30
  }
29
31
 
30
32
  if (parent) parent.appendChild(box);
@@ -1,8 +1,13 @@
1
- 'use client';
1
+ "use client";
2
2
 
3
3
  import React, { useEffect } from "react";
4
- import { GetInputId } from "../../helpers/input-helpers";
5
- import { IForm, IFormCreateResults, IInputCreateResults } from "../../interfaces/input-interfaces";
4
+ import { HideLoader, ShowLoader, SubmitApi, WarningMessage } from "../../client";
5
+ import { GetInputId, SetResponseErrorMessage } from "../../helpers/input-helpers";
6
+ import { IsValidInputs } from "../../helpers/validation-helpers";
7
+ import { EActions, EAnimationClasses, EBackgrounds, EButtonTypes, EFlexPositions, EIcons, EIconTypes, ESizes, GetApiInformations, GetButton, UN, VoidCallbackHandler } from "../../interface";
8
+ import { DEFAULT_ROW_GAP, EInputTypes, GetForms, IApiForm, IForm, IFormCreateResults, IInputCreateResults, ISubmitForm, ISubmitFormCreateResults, OnFormChangeHandler, OnFormSubmitHandler } from "../../interfaces/input-interfaces";
9
+ import { GetFormButtonPosition } from "../../services/localstorage-service";
10
+ import { CreateButton } from "../documents/button";
6
11
  import { CreateInputs, DisposeInputs } from "./input";
7
12
 
8
13
  const forceChangeDefaultValue = (inputResults: IInputCreateResults[], newDefaultValue: any): boolean => {
@@ -16,37 +21,144 @@ const forceChangeDefaultValue = (inputResults: IInputCreateResults[], newDefault
16
21
  }
17
22
  return isChanged;
18
23
  };
19
- export const CreateForm = (param: IForm, rowGap?: number): IFormCreateResults | null => {
20
- const { inputs, onChanged, index, isTabularForm, parentIdentifier } = param;
24
+ export const CreateForm = (param: IForm, parentIdentifier: HTMLElement | string | UN, rowGap?: number, onFormRendered?: VoidCallbackHandler): IFormCreateResults | null => {
25
+ const { inputs, onChanged, index, isTabularForm, defaultValue } = param;
21
26
  const parentElement = typeof parentIdentifier === "string" ? document.getElementById(parentIdentifier) : parentIdentifier;
22
27
 
23
28
  if (!parentElement || inputs.length === 0 || !onChanged) {
24
29
  //TODO: WarningMessage("Invalid Inputs", "Please provide valid inputs, onChanged function and parent element.");
25
30
  return null;
26
31
  }
32
+ const rowElement = document.createElement("div");
33
+ if (parentElement) parentElement.appendChild(rowElement);
27
34
 
28
- const parent = document.createElement("div");
29
- parent.className = `row g${rowGap ?? 3} sb fg`;
30
- parent.style.paddingTop = "var(--IEM)";
31
- if (parentElement) parentElement.appendChild(parent);
35
+ rowElement.className = `row g${rowGap ?? DEFAULT_ROW_GAP} sb fg`;
36
+ rowElement.style.paddingTop = "var(--IEM)";
32
37
 
33
- const inputResults = CreateInputs(inputs, onChanged, index, isTabularForm, parent, param.defaultValue);
38
+ const inputResults = CreateInputs(inputs, onChanged, index, isTabularForm, rowElement, defaultValue);
39
+
40
+ onFormRendered?.(inputResults);
34
41
 
35
42
  return {
36
43
  inputResults: inputResults,
37
- formElement: parent,
44
+ formElement: rowElement,
38
45
  dispose: (invokeOnChanged?: boolean) => {
39
46
  DisposeInputs(inputResults, invokeOnChanged);
40
- parent.remove();
47
+ rowElement.remove();
41
48
  },
42
49
  forceChangeDefaultValue: (newDefaultValue: any) => forceChangeDefaultValue(inputResults, newDefaultValue),
43
50
  } as IFormCreateResults;
44
51
  };
45
52
 
46
- export const Form = ({ param, rowGap }: { param: IForm; rowGap?: number }): React.ReactNode => {
53
+ export const Form = ({ param, parentIdentifier, rowGap, onFormRendered }: { param: IForm; parentIdentifier: HTMLElement | string | UN; rowGap?: number; onFormRendered?: VoidCallbackHandler }): React.ReactNode => {
47
54
  useEffect(() => {
48
- const formResults = CreateForm(param, rowGap);
55
+ const formResults = CreateForm(param, parentIdentifier, rowGap, onFormRendered);
49
56
  return () => formResults?.dispose();
50
57
  }, [param, rowGap]);
51
58
  return <React.Fragment></React.Fragment>;
52
59
  };
60
+
61
+ export const CreateSubmitForm = (param: ISubmitForm, parentIdentifier: HTMLElement | string | UN, rowGap?: number, buttonPosition?: EFlexPositions, formAction?: EActions | UN, onFormRendered?: VoidCallbackHandler): ISubmitFormCreateResults | null => {
62
+ const parentElement = typeof parentIdentifier === "string" ? document.getElementById(parentIdentifier) : parentIdentifier;
63
+ buttonPosition = buttonPosition ?? GetFormButtonPosition();
64
+
65
+ if (!parentElement || !param.inputs || param.inputs.length === 0 || !param.onSubmit) return null;
66
+
67
+ let formValue: any | UN;
68
+ let defaultValue: any | UN = GetApiInformations.IS_API(param.defaultValue) ? null : param.defaultValue;
69
+ const onChangedHandler: OnFormChangeHandler = (currentValue, isInitilizing, isForcedChanged, isDisposed, currentKey, index, type, dataSource) => {
70
+ formValue = currentValue;
71
+ if (param.onChanged) param.onChanged(currentValue, isInitilizing, isForcedChanged, isDisposed, currentKey, index, type, dataSource);
72
+ };
73
+ const onFormSubmit = async (event: Event) => {
74
+ event.preventDefault();
75
+ const isValidForm = IsValidInputs(formResults?.inputResults, formValue, true, true);
76
+ const isValid = param.overrideValidation ? await param.overrideValidation(formValue, isValidForm, formResults, formAction) : isValidForm;
77
+
78
+ param.onSubmit({ ...formValue }, isValidForm, event, formResults!, defaultValue);
79
+ if (!isValid) WarningMessage("Invalid Inputs", "Please fill all required fields correctly.");
80
+ };
81
+ const formParameters = GetForms.FORM(param.inputs, onChangedHandler, defaultValue);
82
+ const formElement = document.createElement("form");
83
+ parentElement.appendChild(formElement);
84
+ const formResults = CreateForm(formParameters, formElement, rowGap, onFormRendered);
85
+ if (!formResults) return null;
86
+ formResults.formElement.classList.add("h100", "fg");
87
+
88
+ const submitButton = param.inputs.find((input) => input.inputType === EInputTypes.SubmitButton);
89
+ if (!submitButton) {
90
+ const buttonStyle: React.CSSProperties = {
91
+ width: "fit-content",
92
+ };
93
+ const DEFAULT_BUTTON_CLASS = "col- jc r";
94
+ rowGap = rowGap ?? DEFAULT_ROW_GAP;
95
+ const PADDING = rowGap * 2;
96
+
97
+ const buttonParam = GetButton("Submit", null, null, EIcons.SAVE, null, null, EBackgrounds.PrimaryColor, DEFAULT_BUTTON_CLASS, null, EIconTypes.FILLED, null, 0, null, EButtonTypes.SUBMIT);
98
+ const buttonContainer = document.createElement("div");
99
+ buttonContainer.className = `df ac pt1 pb5 ${buttonPosition} bb pr${PADDING} pl${PADDING}`;
100
+ buttonContainer.style.minHeight = "calc(var(--IH) * 1.5)";
101
+
102
+ formElement.appendChild(buttonContainer);
103
+ CreateButton(buttonParam, buttonContainer, buttonStyle, false);
104
+
105
+ if (param.onCancelClick) {
106
+ const buttonParam = GetButton("Cancel", null, null, EIcons.CLOSE, param.onCancelClick, null, EBackgrounds.ErrorColor, DEFAULT_BUTTON_CLASS + ` ml${PADDING}`, null, EIconTypes.FILLED, null, 0, null, EButtonTypes.BUTTON);
107
+ CreateButton(buttonParam, buttonContainer, buttonStyle, false);
108
+ }
109
+ }
110
+
111
+ formElement.className = `df ddc w100 h100 oh fg pr`;
112
+ formElement.addEventListener("submit", onFormSubmit);
113
+
114
+ const onDispose = () => {
115
+ formResults?.dispose();
116
+ formElement.remove();
117
+ };
118
+
119
+ return {
120
+ formElement: formElement,
121
+ dispose: () => onDispose(),
122
+ formObject: formResults,
123
+ };
124
+ };
125
+
126
+ export const SubmitForm = ({ param, parentIdentifier, rowGap, buttonPosition, formAction, onFormRendered }: { param: ISubmitForm; parentIdentifier: HTMLElement | string | UN; rowGap?: number; buttonPosition?: EFlexPositions; formAction?: EActions | UN; onFormRendered?: VoidCallbackHandler }): React.ReactNode => {
127
+ useEffect(() => {
128
+ const submitForm = CreateSubmitForm(param, parentIdentifier, rowGap, buttonPosition, formAction, onFormRendered);
129
+ return () => submitForm?.dispose();
130
+ }, [param, parentIdentifier, rowGap, buttonPosition, formAction]);
131
+ return <React.Fragment></React.Fragment>;
132
+ };
133
+
134
+ export const CreateApiForm = (param: IApiForm, parentIdentifier: HTMLElement | string | UN, rowGap?: number, buttonPosition?: EFlexPositions, formAction?: EActions | UN, overrideLoaderParend?: HTMLElement | string | UN, successMessage?: boolean | UN, errorMessage?: boolean | UN, onFormRendered?: VoidCallbackHandler): ISubmitFormCreateResults | null => {
135
+ let isLoading = false;
136
+ const onFormSubmit: OnFormSubmitHandler = async (currentValue, isValidForm, event, form, defaultValue) => {
137
+ if (isLoading) return;
138
+ isLoading = true;
139
+
140
+ if (param.onSubmit) param.onSubmit(currentValue, isValidForm, event, form, defaultValue);
141
+ if (!isValidForm) return;
142
+
143
+ const loaderParent = overrideLoaderParend ?? submitForm?.formElement ?? parentIdentifier;
144
+ ShowLoader(loaderParent, EAnimationClasses.SPIN, true, ESizes.Normal, null, null, null, "r");
145
+ const apiResponse = await SubmitApi(param.api, currentValue, successMessage, errorMessage);
146
+ if (!apiResponse.isSuccess) SetResponseErrorMessage(apiResponse, submitForm?.formObject.inputResults);
147
+ HideLoader(loaderParent);
148
+ param.onApiSubmit(currentValue, apiResponse, submitForm!, defaultValue);
149
+ isLoading = false;
150
+ };
151
+ const submitFormParam = GetForms.SUBMITFORM(param?.inputs, onFormSubmit, param?.defaultValue, param?.overrideValidation, param?.onChanged, param?.onCancelClick);
152
+ const submitForm = CreateSubmitForm(submitFormParam, parentIdentifier, rowGap, buttonPosition, formAction, onFormRendered);
153
+ if (!submitForm) return null;
154
+
155
+ return submitForm;
156
+ };
157
+
158
+ export const ApiForm = ({ param, parentIdentifier, rowGap, buttonPosition, formAction, overrideLoaderParend, successMessage, errorMessage, onFormRendered }: { param: IApiForm; parentIdentifier: HTMLElement | string | UN; rowGap?: number; buttonPosition?: EFlexPositions; formAction?: EActions | UN; overrideLoaderParend?: HTMLElement | string | UN; successMessage?: boolean | UN; errorMessage?: boolean | UN; onFormRendered?: VoidCallbackHandler }): React.ReactNode => {
159
+ useEffect(() => {
160
+ const apiForm = CreateApiForm(param, parentIdentifier, rowGap, buttonPosition, formAction, overrideLoaderParend, successMessage, errorMessage, onFormRendered);
161
+ return () => apiForm?.dispose();
162
+ }, [param, parentIdentifier, rowGap, buttonPosition, formAction, overrideLoaderParend, successMessage, errorMessage]);
163
+ return <React.Fragment></React.Fragment>;
164
+ };
@@ -39,11 +39,13 @@ export const GlobalLayout = async ({ children, globalLayout }: Readonly<{ childr
39
39
  display: "flex",
40
40
  justifyContent: "center",
41
41
  alignItems: "center",
42
- backgroundColor: "rgb(40, 40, 40)",
42
+ backgroundColor: "rgb(60, 60, 60)",
43
43
  }}
44
44
  id={ROOT_LOADER_IDENTITY}
45
45
  >
46
- <img src={FILES.LOGO.ICON} alt={"logo"} style={{ minHeight: "3rem", minWidth: "3rem", width: "3rem", height: "3rem" }} />
46
+ <a href={"/"} className="p5 h r bg52" style={{ marginTop: "8rem" }} title="Visit Home Page">
47
+ <img src={FILES.LOGO.ICON} alt={"logo"} style={{ minHeight: "3rem", minWidth: "3rem", width: "3rem", height: "3rem" }} />
48
+ </a>
47
49
  </div>
48
50
  {children}
49
51
  <Script type="module" src="https://cdn.jsdelivr.net/npm/ionicons@5.5.2/dist/ionicons/ionicons.esm.js" strategy="lazyOnload"></Script>
@@ -1,23 +1,23 @@
1
- 'use client';
2
-
3
- import { useEffect } from "react";
4
- import { RemoveElement } from "../../helpers/browser-helpers";
5
- import { IGlobalLayout, ROOT_LOADER_IDENTITY } from "../../interfaces/layout-interfaces";
6
- import { DEFAULT_THEME_INFORMATIONS } from "../../interfaces/theme-interfaces";
7
- import { O } from "../../nexus-client";
8
- import { InitializeStyles } from "../../services/theme-service";
9
-
10
- export const LayoutHelpers = ({ globalLayout }: Readonly<{ globalLayout: IGlobalLayout }>) => {
11
- useEffect(() => {
12
- globalLayout.systemThemes = DEFAULT_THEME_INFORMATIONS;
13
- O.systemThemes = DEFAULT_THEME_INFORMATIONS;
14
-
15
- const timeout = setTimeout(() => {
16
- clearTimeout(timeout);
17
- RemoveElement(ROOT_LOADER_IDENTITY, 500);
18
- InitializeStyles();
19
- }, 50);
20
- }, []);
21
-
22
- return <div className="nexus-popup-container"></div>;
23
- };
1
+ "use client";
2
+
3
+ import { useEffect } from "react";
4
+ import { RemoveElement } from "../../helpers/browser-helpers";
5
+ import { IGlobalLayout, ROOT_LOADER_IDENTITY } from "../../interfaces/layout-interfaces";
6
+ import { DEFAULT_THEME_INFORMATIONS } from "../../interfaces/theme-interfaces";
7
+ import { O } from "../../nexus-client";
8
+ import { InitializeStyles } from "../../services/theme-service";
9
+
10
+ export const LayoutHelpers = ({ globalLayout }: Readonly<{ globalLayout: IGlobalLayout }>) => {
11
+ useEffect(() => {
12
+ globalLayout.systemThemes = DEFAULT_THEME_INFORMATIONS;
13
+ O.systemThemes = DEFAULT_THEME_INFORMATIONS;
14
+
15
+ const timeout = setTimeout(() => {
16
+ clearTimeout(timeout);
17
+ RemoveElement(ROOT_LOADER_IDENTITY, 500);
18
+ InitializeStyles();
19
+ }, 50);
20
+ }, [globalLayout]);
21
+
22
+ return <div className="nexus-popup-container"></div>;
23
+ };
@@ -1,3 +1,4 @@
1
+ import { UN } from "../interface";
1
2
  import { EAnimationClasses } from "../interfaces/layout-interfaces";
2
3
  import { NEXUS_INFO } from "../nexus.environments";
3
4
  import { EKeyModifier, EKeys } from "./../interfaces/browser-interfaces";
@@ -6,7 +7,7 @@ import { Debounce } from "./utility-helpers";
6
7
 
7
8
  export const IsBrowser = (): boolean => typeof window !== "undefined" && typeof document !== "undefined";
8
9
 
9
- export const RemoveElement = async (elementIdentity: string | HTMLElement, timeout?: number, animation?: EAnimationClasses): Promise<boolean> => {
10
+ export const RemoveElement = async (elementIdentity: string | HTMLElement, timeout?: number | UN, animation?: EAnimationClasses | UN): Promise<boolean> => {
10
11
  return new Promise(async (resolve) => {
11
12
  if (!IsBrowser() || !elementIdentity) return resolve(false);
12
13
  else if (typeof elementIdentity === "string") {
@@ -69,3 +70,42 @@ export const FindChildElements = (parent: HTMLElement, childSelector: string, sh
69
70
  return children.length > 0 ? [children[0]] : [];
70
71
  }
71
72
  };
73
+ export const PxToRem = (px: number): number => {
74
+ const fontSize = parseFloat(getComputedStyle(document.documentElement).fontSize) || 16;
75
+ return Math.round((px / fontSize) * 1000) / 1000;
76
+ };
77
+
78
+ export const ConvertColorToRGBA = (color: string, alpha: number = 0.1): string => {
79
+ if (!color) return "rgba(0, 0, 0, 0.1)";
80
+
81
+ let finalColor = color.trim();
82
+ if (finalColor.startsWith("var(")) finalColor = finalColor.replace(/^var\(\s*/, "").replace(/\s*\)$/, "");
83
+ // CSS Variable Support
84
+ if (finalColor.startsWith("--")) finalColor = getComputedStyle(document.documentElement).getPropertyValue(finalColor).trim();
85
+
86
+ // Create temporary element for browser auto parsing
87
+ const temp = document.createElement("div");
88
+ temp.style.color = finalColor;
89
+
90
+ document.body.appendChild(temp);
91
+
92
+ const computed = getComputedStyle(temp).color;
93
+
94
+ document.body.removeChild(temp);
95
+
96
+ // computed => rgb(...) or rgba(...)
97
+ const match = computed.match(/rgba?\(\s*(\d+)[,\s]+(\d+)[,\s]+(\d+)(?:[,\s\/]+([\d.]+))?\s*\)/i);
98
+
99
+ if (!match) return "rgba(0, 0, 0, 1)";
100
+
101
+ const r = parseInt(match[1], 10);
102
+ const g = parseInt(match[2], 10);
103
+ const b = parseInt(match[3], 10);
104
+
105
+ let a = match[4] !== undefined ? parseFloat(match[4]) : 1;
106
+
107
+ // Override alpha if provided
108
+ if (alpha) a = alpha;
109
+
110
+ return `rgba(${r}, ${g}, ${b}, ${a})`;
111
+ };
@@ -1,8 +1,10 @@
1
- import { DEFAULT_ICON_ELEMENT_NAME } from "../interface";
1
+ import { DEFAULT_ICON_ELEMENT_NAME, IErrorRespose } from "../interface";
2
2
  import { EValueChangeTypes, IInputCreateResults, IInputRootParameters } from "../interfaces/input-interfaces";
3
3
  import { ESizes } from "../interfaces/layout-interfaces";
4
4
  import { UN } from "../interfaces/type-interfaces";
5
+ import { AddRemoveErrorFromInput } from "./validation-helpers";
5
6
 
7
+ export const INPUT_ICON_BOX_CLASS = "input-icon-box";
6
8
  export const GetParentKey = (parentKey?: string | null) => {
7
9
  if (parentKey) return parentKey.split("|")[0];
8
10
  return undefined;
@@ -23,22 +25,50 @@ export const ForceSetValue = (input?: IInputCreateResults | null, value?: any |
23
25
  clearTimeout(timeoutValue);
24
26
  }, timeout ?? 0);
25
27
  };
28
+
29
+ export const ApplyPasswordInputs = (inputResults: IInputCreateResults[] | UN, selectors: string[] | UN) => {
30
+ if (!inputResults || inputResults.length === 0 || !selectors || selectors.length === 0) return;
31
+ for (const selector of selectors) {
32
+ const input = inputResults.find((x) => x.input.id === selector);
33
+ if (input) ApplyPasswordInput(input.rootElement.querySelector(`div.ib.${INPUT_ICON_BOX_CLASS}`), input.inputElement);
34
+ }
35
+ };
36
+
26
37
  export const ApplyPasswordInput = (iconbox: HTMLElement | null, inputElement: HTMLElement | null) => {
27
38
  const input = inputElement as HTMLInputElement | undefined;
28
39
  if (!input || !iconbox) return;
40
+
41
+ if (!iconbox.classList.contains("h")) iconbox.classList.add("h");
42
+
29
43
  const icon = iconbox.querySelector(DEFAULT_ICON_ELEMENT_NAME) as HTMLElement | null;
30
- if (icon) icon.setAttribute("name", "eye");
44
+ if (!icon) return;
31
45
  const onMouseLeave = () => {
32
46
  iconbox.removeEventListener("mouseleave", onMouseLeave);
33
47
  iconbox.removeEventListener("click", onClicked);
34
48
  input.type = "password";
35
49
  if (icon) icon.setAttribute("name", "key");
36
50
  };
51
+ const onMouseEnter = () => {
52
+ icon.setAttribute("name", "eye");
53
+ iconbox.addEventListener("mouseleave", onMouseLeave);
54
+ iconbox.addEventListener("click", onClicked);
55
+ };
37
56
  const onClicked = () => {
38
57
  const isPassword = input.type === "password";
39
58
  input.type = isPassword ? "text" : "password";
40
59
  if (icon) icon.setAttribute("name", isPassword ? "eye-off" : "eye");
41
60
  };
42
- iconbox.addEventListener("mouseleave", onMouseLeave);
43
- iconbox.addEventListener("click", onClicked);
61
+ iconbox.addEventListener("mouseenter", onMouseEnter);
62
+ };
63
+
64
+ export const SetResponseErrorMessage = (apiResponse: IErrorRespose, inputResults: IInputCreateResults[] | UN) => {
65
+ if (!apiResponse || !inputResults || inputResults.length === 0 || !apiResponse.inputName) return;
66
+
67
+ const inputKeys = apiResponse.inputName.toLowerCase().split("|");
68
+ let isFirstElement = true;
69
+ for (const inputKey of inputKeys) {
70
+ const input = inputResults.find((x) => GetInputId(x.input).toLowerCase() === inputKey);
71
+ if (input) AddRemoveErrorFromInput(input.input, input.inputElement, true, apiResponse.message, isFirstElement);
72
+ isFirstElement = false;
73
+ }
44
74
  };
@@ -42,3 +42,4 @@ export function Debounce<T extends (...args: any[]) => void>(func: T, delay?: nu
42
42
 
43
43
  return debounced;
44
44
  }
45
+ export const Delay = (ms: number) => new Promise((resolve) => setTimeout(resolve, ms));