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.
- package/package.json +1 -1
- package/src/api-services/system-service.tsx +1 -2
- package/src/client.ts +3 -2
- package/src/components/documents/button.tsx +5 -1
- package/src/components/inputs/input-box.tsx +4 -2
- package/src/components/inputs/input-form.tsx +126 -14
- package/src/components/layouts/global-layout.tsx +4 -2
- package/src/components/layouts/layout-helpers.tsx +23 -23
- package/src/helpers/browser-helpers.tsx +41 -1
- package/src/helpers/input-helpers.tsx +34 -4
- package/src/helpers/utility-helpers.tsx +1 -0
- package/src/helpers/validation-helpers.tsx +302 -0
- package/src/index.ts +3 -18
- package/src/interface.ts +4 -1
- package/src/interfaces/button-interfaces.tsx +2 -2
- package/src/interfaces/exception-interfaces.tsx +99 -0
- package/src/interfaces/http-interfaces.tsx +120 -3
- package/src/interfaces/input-interfaces.tsx +61 -11
- package/src/interfaces/message-interfaces.tsx +32 -0
- package/src/interfaces/permission-interfaces.tsx +4 -4
- package/src/interfaces/storage-interfaces.tsx +1 -0
- package/src/interfaces/system-interfaces.tsx +2 -2
- package/src/interfaces/type-interfaces.tsx +8 -2
- package/src/interfaces/user-interfaces.tsx +17 -0
- package/src/nexus.environments.tsx +27 -17
- package/src/proxy-api/proxy-backend.tsx +60 -0
- package/src/proxy-api/proxy-constants.tsx +28 -0
- package/src/proxy-api/proxy-helpers.tsx +91 -0
- package/src/proxy-api-client.tsx +1 -0
- package/src/proxy-api-server.tsx +2 -0
- package/src/services/http-client-services.tsx +75 -0
- package/src/services/http-services.tsx +158 -0
- package/src/services/loader-service.tsx +5 -4
- package/src/services/localstorage-service.tsx +59 -0
- package/src/services/message-services.tsx +383 -0
- package/src/sso-config/auth-token-validation.ts +20 -0
- package/src/sso-config/callback-route.tsx +34 -0
- package/src/sso-config/cookie-encryption.ts +51 -0
- package/src/sso-config/cookie-helpers.tsx +77 -0
- package/src/sso-config/forgot-password-route.tsx +36 -0
- package/src/sso-config/oauth-callback-state.ts +58 -0
- package/src/sso-config/pkce-helpers.ts +16 -0
- package/src/sso-config/provider-complete-route.tsx +15 -0
- package/src/sso-config/redirect-context-actions.tsx +46 -0
- package/src/sso-config/redirect-context-helpers.tsx +144 -0
- package/src/sso-config/redirect-context-persist.tsx +18 -0
- package/src/sso-config/redirect-context-route.tsx +45 -0
- package/src/sso-config/refresh-route.tsx +22 -0
- package/src/sso-config/sign-in-route.tsx +69 -0
- package/src/sso-config/sign-out-route.tsx +53 -0
- package/src/sso-config/sign-up-route.tsx +46 -0
- package/src/sso-config/sso-backend-flow.ts +45 -0
- package/src/sso-config/sso-complete-route.tsx +46 -0
- package/src/sso-config/sso-config.ts +57 -0
- package/src/sso-config/sso-interfaces.tsx +68 -0
- package/src/sso-config/sso-response-helpers.tsx +20 -0
- package/src/sso-server.tsx +21 -1
- package/src/styles/nexus.dialog.css +3 -0
package/package.json
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { EIcons } from "../interfaces/icon-interfaces";
|
|
2
|
-
import {
|
|
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,
|
|
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="
|
|
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
|
-
|
|
1
|
+
"use client";
|
|
2
2
|
|
|
3
3
|
import React, { useEffect } from "react";
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
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,
|
|
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
|
-
|
|
29
|
-
|
|
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,
|
|
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:
|
|
44
|
+
formElement: rowElement,
|
|
38
45
|
dispose: (invokeOnChanged?: boolean) => {
|
|
39
46
|
DisposeInputs(inputResults, invokeOnChanged);
|
|
40
|
-
|
|
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(
|
|
42
|
+
backgroundColor: "rgb(60, 60, 60)",
|
|
43
43
|
}}
|
|
44
44
|
id={ROOT_LOADER_IDENTITY}
|
|
45
45
|
>
|
|
46
|
-
<
|
|
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
|
-
|
|
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)
|
|
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("
|
|
43
|
-
|
|
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
|
};
|