nexus-shared 1.1.5 → 1.1.6

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 (70) hide show
  1. package/package.json +8 -4
  2. package/src/api-services/preference-service.tsx +5 -0
  3. package/src/api-services/system-service.tsx +322 -0
  4. package/src/components/documents/button.tsx +136 -0
  5. package/src/components/documents/icon-box.tsx +92 -0
  6. package/src/components/documents/page-title.tsx +7 -0
  7. package/src/components/documents/tab-button.tsx +169 -0
  8. package/src/components/index.js +0 -0
  9. package/src/components/inputs/checkbox-input.tsx +66 -0
  10. package/src/components/inputs/input-box.tsx +45 -0
  11. package/src/components/inputs/input-element.tsx +65 -0
  12. package/src/components/inputs/input-form.tsx +50 -0
  13. package/src/components/inputs/input.tsx +181 -0
  14. package/src/components/inputs/number-input.tsx +108 -0
  15. package/src/components/inputs/radiobox-input.tsx +53 -0
  16. package/src/components/inputs/textarea-input.tsx +47 -0
  17. package/src/components/inputs/textbox-input.tsx +45 -0
  18. package/src/components/layouts/global-dialogbox.tsx +433 -0
  19. package/src/components/layouts/global-layout.tsx +63 -0
  20. package/src/components/layouts/layout-helpers.tsx +23 -0
  21. package/src/components/layouts/utility-menu.tsx +71 -0
  22. package/src/components/panels/theme-panel.tsx +44 -0
  23. package/src/helpers/bitwise-helpers.tsx +11 -0
  24. package/src/helpers/browser-helpers.tsx +73 -0
  25. package/src/helpers/datasource-helpers.tsx +99 -0
  26. package/src/helpers/element-helpers.tsx +57 -0
  27. package/src/helpers/input-helpers.tsx +24 -0
  28. package/src/helpers/string-helpers.tsx +28 -0
  29. package/src/helpers/utility-helpers.tsx +44 -0
  30. package/src/index.ts +0 -11
  31. package/src/interfaces/browser-interfaces.tsx +23 -0
  32. package/src/interfaces/button-interfaces.tsx +63 -0
  33. package/src/interfaces/datasource-interfaces.tsx +22 -0
  34. package/src/interfaces/datatable-interfaces.tsx +25 -0
  35. package/src/interfaces/dialogbox-interfaces.tsx +5 -0
  36. package/src/interfaces/http-interfaces.tsx +15 -0
  37. package/src/interfaces/icon-interfaces.tsx +126 -0
  38. package/src/interfaces/input-interfaces.tsx +360 -0
  39. package/src/interfaces/layout-interfaces.tsx +191 -0
  40. package/src/interfaces/menu-interfaces.tsx +36 -0
  41. package/src/interfaces/permission-interfaces.tsx +9 -0
  42. package/src/interfaces/storage-interfaces.tsx +3 -0
  43. package/src/interfaces/system-interfaces.tsx +22 -0
  44. package/src/interfaces/theme-interfaces.tsx +209 -0
  45. package/src/interfaces/type-interfaces.tsx +22 -0
  46. package/src/nexus-client.tsx +23 -0
  47. package/src/nexus.environments.tsx +34 -0
  48. package/src/services/loader-service.tsx +168 -0
  49. package/src/services/localstorage-service.tsx +45 -0
  50. package/src/services/theme-service.tsx +149 -0
  51. package/src/styles/nexus.animation.css +269 -0
  52. package/src/styles/nexus.core.css +119 -0
  53. package/src/styles/nexus.dialog.css +141 -0
  54. package/src/styles/nexus.icon.css +50 -0
  55. package/src/styles/nexus.input.css +207 -0
  56. package/src/styles/nexus.loader.css +11 -0
  57. package/src/styles/nexus.logic.css +18 -0
  58. package/src/styles/nexus.utility.css +347 -0
  59. package/src/client/index.ts +0 -1
  60. package/src/client/nexus-selectable-list.css +0 -131
  61. package/src/client/nexus-selectable-list.tsx +0 -111
  62. package/src/client.ts +0 -7
  63. package/src/interface.ts +0 -5
  64. package/src/interfaces/index.ts +0 -6
  65. package/src/interfaces/nexus-base.ts +0 -5
  66. package/src/interfaces/nexus-list.ts +0 -24
  67. package/src/server/index.ts +0 -1
  68. package/src/server/nexus-stat-list.css +0 -92
  69. package/src/server/nexus-stat-list.tsx +0 -46
  70. package/src/server.ts +0 -7
@@ -0,0 +1,168 @@
1
+ import { FindChildElement, IsBrowser, RemoveElement } from "../helpers/browser-helpers";
2
+ import { EAnimationClasses, ESizes } from "../interfaces/layout-interfaces";
3
+ import { EBackgrounds } from "../interfaces/theme-interfaces";
4
+ import { UN } from "../interfaces/type-interfaces";
5
+ import { FILES } from "../nexus.environments";
6
+
7
+ const DEFAULT_LOADER_TYPE = EAnimationClasses.SPIN;
8
+ const DEFAULT_LOADER_SIZE = ESizes.Medium;
9
+ const DEFAULT_LOADER_DELAY = 0;
10
+ const LOADER_IDENTITY = "nexus-loader";
11
+ const LOADER_DATA_COUNT_ATTRIBUTE = "data-count";
12
+ const LOADER_DATA_TYPE_ATTRIBUTE = "data-type";
13
+ const LOADER_DATA_SIZE_ATTRIBUTE = "data-size";
14
+ const LOADER_DATA_DISABLED_INPUTS_ATTRIBUTE = "data-disabled-inputs";
15
+ const DISPOSED_LOADER_CLASS = "disposed";
16
+ const DEFAULT_LOADER_BACKGROUND = EBackgrounds.PopupBackgroundColor;
17
+ /**
18
+ *
19
+ * @param parent - Parent element to show loader on
20
+ * @param type - Animation type to use for showing loader
21
+ * @param disabledInputs - If true, all inputs will be disabled
22
+ * @param size - Size of the loader
23
+ * @param delay - Delay in milliseconds
24
+ * @returns - Returns the loader element
25
+ */
26
+
27
+ const _findParentElement = (parent: String | HTMLElement | UN): HTMLElement => {
28
+ if (parent) {
29
+ if (typeof parent === "string") return document.getElementById(parent) ?? document.body;
30
+ else if (parent instanceof HTMLElement) return parent ?? document.body;
31
+ }
32
+
33
+ return document.body;
34
+ };
35
+ const _findExistingLoader = (parent: HTMLElement): HTMLElement | null => {
36
+ const loaderElement = FindChildElement(parent, `#${LOADER_IDENTITY}`);
37
+ return loaderElement as HTMLElement | null;
38
+ };
39
+ const _updateLoaderProperties = (loaderElement: HTMLElement, type: EAnimationClasses, size: ESizes) => {
40
+ if (type === EAnimationClasses.SPIN) {
41
+ if (size === ESizes.VeryTiny) {
42
+ loaderElement.style.setProperty("--SPIN_BOX_SIZE", "2.5rem");
43
+ loaderElement.style.setProperty("--SPIN_BOX_BORDER_SIZE", "0.34rem");
44
+ } else if (size === ESizes.Tiny) {
45
+ loaderElement.style.setProperty("--SPIN_BOX_SIZE", "2.8rem");
46
+ loaderElement.style.setProperty("--SPIN_BOX_BORDER_SIZE", "0.36rem");
47
+ } else if (size === ESizes.VerySmall) {
48
+ loaderElement.style.setProperty("--SPIN_BOX_SIZE", "3rem");
49
+ loaderElement.style.setProperty("--SPIN_BOX_BORDER_SIZE", "0.38rem");
50
+ } else if (size === ESizes.Small) {
51
+ loaderElement.style.setProperty("--SPIN_BOX_SIZE", "3.5rem");
52
+ loaderElement.style.setProperty("--SPIN_BOX_BORDER_SIZE", "0.45rem");
53
+ } else if (size === ESizes.Medium) {
54
+ loaderElement.style.setProperty("--SPIN_BOX_SIZE", "4rem");
55
+ loaderElement.style.setProperty("--SPIN_BOX_BORDER_SIZE", "0.5rem");
56
+ } else if (size === ESizes.Large) {
57
+ loaderElement.style.setProperty("--SPIN_BOX_SIZE", "4.8rem");
58
+ loaderElement.style.setProperty("--SPIN_BOX_BORDER_SIZE", "0.55rem");
59
+ } else if (size === ESizes.ExtraLarge) {
60
+ loaderElement.style.setProperty("--SPIN_BOX_SIZE", "5.5rem");
61
+ loaderElement.style.setProperty("--SPIN_BOX_BORDER_SIZE", "0.6rem");
62
+ } else if (size === ESizes.VeryExtraLarge) {
63
+ loaderElement.style.setProperty("--SPIN_BOX_SIZE", "6.5rem");
64
+ loaderElement.style.setProperty("--SPIN_BOX_BORDER_SIZE", "0.7rem");
65
+ } else if (size === ESizes.FullSize) {
66
+ loaderElement.style.setProperty("--SPIN_BOX_SIZE", "8rem");
67
+ loaderElement.style.setProperty("--SPIN_BOX_BORDER_SIZE", "0.8rem");
68
+ }
69
+ }
70
+ };
71
+ const _updateLoaderAttributes = (loaderElement: HTMLElement, type: EAnimationClasses, size: ESizes, disabledInputs: boolean, count: number) => {
72
+ loaderElement.setAttribute(LOADER_DATA_COUNT_ATTRIBUTE, count.toString());
73
+ loaderElement.setAttribute(LOADER_DATA_TYPE_ATTRIBUTE, type);
74
+ loaderElement.setAttribute(LOADER_DATA_SIZE_ATTRIBUTE, size);
75
+ loaderElement.setAttribute(LOADER_DATA_DISABLED_INPUTS_ATTRIBUTE, disabledInputs ? "true" : "false");
76
+ };
77
+ const _createLoaderElement = (parent: HTMLElement, type: EAnimationClasses, size: ESizes, showLogo: boolean, disabledInputs: boolean, background: EBackgrounds): HTMLElement | null => {
78
+ const loaderElement = _findExistingLoader(parent);
79
+ if (loaderElement && !loaderElement.classList.contains(DISPOSED_LOADER_CLASS)) {
80
+ const count = parseInt(loaderElement.getAttribute(LOADER_DATA_COUNT_ATTRIBUTE) ?? "0") + 1;
81
+ _updateLoaderAttributes(loaderElement, type, size, disabledInputs, count);
82
+ _updateLoaderProperties(loaderElement, type, size);
83
+ return loaderElement as HTMLElement;
84
+ }
85
+
86
+ const newLoaderElement = document.createElement("div");
87
+ newLoaderElement.id = LOADER_IDENTITY;
88
+ newLoaderElement.classList.add("nexus-container", "o0", EAnimationClasses.FADE_IN, background);
89
+ _updateLoaderAttributes(newLoaderElement, type, size, disabledInputs, 1);
90
+
91
+ const loader = document.createElement("div");
92
+ newLoaderElement.appendChild(loader);
93
+ loader.classList.add(size, type);
94
+
95
+ const isTextLoader = (type === EAnimationClasses.BOUNCE || type === EAnimationClasses.FADE_IN_OUT || type === EAnimationClasses.PULSE_IN_OUT) && parent === document.body;
96
+ if (isTextLoader && !showLogo) {
97
+ loader.innerText = "Loading...";
98
+ loader.classList.add("tx52");
99
+ loader.style.fontSize = "1.5rem";
100
+ } else if (showLogo) {
101
+ _updateLoaderProperties(newLoaderElement, type, size);
102
+
103
+ const logoElement = document.createElement("img");
104
+ logoElement.src = FILES.LOGO.ICON;
105
+ logoElement.alt = "Logo";
106
+ logoElement.className = "pa bg52";
107
+ logoElement.style.width = "calc(var(--SPIN_BOX_SIZE) - var(--SPIN_BOX_BORDER_SIZE))";
108
+ logoElement.style.height = "calc(var(--SPIN_BOX_SIZE) - var(--SPIN_BOX_BORDER_SIZE))";
109
+ logoElement.style.zIndex = "-1";
110
+
111
+ if (isTextLoader) {
112
+ logoElement.style.padding = `var(--SPIN_BOX_BORDER_SIZE)`;
113
+ logoElement.classList.add("txy50", "r2");
114
+ loader.appendChild(logoElement);
115
+ } else {
116
+ logoElement.style.padding = `calc(var(--SPIN_BOX_BORDER_SIZE) * 1.3)`;
117
+ logoElement.style.borderRadius = `35%`;
118
+ newLoaderElement.appendChild(logoElement);
119
+ }
120
+ }
121
+
122
+ parent.appendChild(newLoaderElement);
123
+ return newLoaderElement;
124
+ };
125
+
126
+ export const ShowLoader = async (parent?: String | HTMLElement | UN, type?: EAnimationClasses | UN, disabledInputs?: boolean | UN, size?: ESizes | UN, delay?: number | UN, showLogo?: boolean | UN, background?: EBackgrounds | UN): Promise<HTMLElement | null> => {
127
+ if (!IsBrowser()) return Promise.resolve(null);
128
+ type = type ?? DEFAULT_LOADER_TYPE;
129
+ size = size ?? DEFAULT_LOADER_SIZE;
130
+ background = background ?? DEFAULT_LOADER_BACKGROUND;
131
+
132
+ return new Promise((resolve) => {
133
+ const timeout = setTimeout(() => {
134
+ clearTimeout(timeout);
135
+ const parentElement = _findParentElement(parent);
136
+ const loaderElement = _createLoaderElement(parentElement, type, size, showLogo ?? true, disabledInputs ?? false, background);
137
+ resolve(loaderElement);
138
+ }, delay ?? DEFAULT_LOADER_DELAY);
139
+ });
140
+ };
141
+
142
+ /**
143
+ * Hide loader if it is visible
144
+ * @param parent - Parent element to hide loader from
145
+ * @param type - Animation type to use for hiding loader
146
+ * @param force - This will dispose all loader elements
147
+ * @param delay - Delay in milliseconds
148
+ */
149
+ export const HideLoader = (parent?: String | HTMLElement | UN, force?: boolean | UN, delay?: number | UN): Promise<boolean> => {
150
+ if (!IsBrowser()) return Promise.resolve(false);
151
+ const parentElement = _findParentElement(parent);
152
+
153
+ return new Promise((resolve) => {
154
+ const timeout = setTimeout(() => {
155
+ clearTimeout(timeout);
156
+
157
+ const loaderElement = _findExistingLoader(parentElement);
158
+ if (!loaderElement) return resolve(false);
159
+
160
+ const count = parseInt(loaderElement.getAttribute(LOADER_DATA_COUNT_ATTRIBUTE) ?? "0");
161
+
162
+ if (force || count <= 1) {
163
+ RemoveElement(loaderElement, 300);
164
+ } else loaderElement.setAttribute(LOADER_DATA_COUNT_ATTRIBUTE, (count - 1).toString());
165
+ return resolve(true);
166
+ }, delay ?? DEFAULT_LOADER_DELAY);
167
+ });
168
+ };
@@ -0,0 +1,45 @@
1
+ "use client";
2
+
3
+ import { CreateUpdatePreference } from "../api-services/preference-service";
4
+ import { IsBrowser } from "../helpers/browser-helpers";
5
+ import { Debounce } from "../helpers/utility-helpers";
6
+ import { LOCAL_STORAGE_KEYS } from "../interfaces/storage-interfaces";
7
+ import { EPreferenceTargets } from "../interfaces/system-interfaces";
8
+ import { IThemeInformation } from "../interfaces/theme-interfaces";
9
+ import { O } from "../nexus-client";
10
+
11
+ const _createUpdatePreferenceDebounce = Debounce(CreateUpdatePreference, 1000);
12
+
13
+ const _syncStorageToServer = async (key: string, value: string | null, isSyncWithServer?: boolean, target?: EPreferenceTargets) => {
14
+ if (!IsBrowser() || !isSyncWithServer || !target) return;
15
+
16
+ await _createUpdatePreferenceDebounce(target, key, value);
17
+ };
18
+
19
+ export const SetLocalStorage = (key: string, value: string, isSyncWithServer?: boolean, target?: EPreferenceTargets) => {
20
+ if (!IsBrowser()) return;
21
+
22
+ _syncStorageToServer(key, value, isSyncWithServer, target);
23
+ localStorage.setItem(key, value);
24
+ };
25
+ export const RemoveLocalStorage = (key: string, isSyncWithServer?: boolean, target?: EPreferenceTargets) => {
26
+ _syncStorageToServer(key, null, isSyncWithServer, target);
27
+ localStorage.removeItem(key);
28
+ };
29
+
30
+ export function GetLocalStorage(key: string): string | null {
31
+ if (!IsBrowser()) return null;
32
+ const data = localStorage.getItem(key);
33
+ if (!data) return null;
34
+ return data;
35
+ }
36
+
37
+ export const SetCurrentTheme = (themeCode: string) => SetLocalStorage(LOCAL_STORAGE_KEYS.ACTIVE_THEME, themeCode, true, EPreferenceTargets.User);
38
+ export const GetCurrentTheme = (): IThemeInformation => {
39
+ const themeInformations = O.systemThemes;
40
+ if (!themeInformations || themeInformations.length === 0) throw new Error("No theme information found");
41
+ const activeTheme = GetLocalStorage(LOCAL_STORAGE_KEYS.ACTIVE_THEME);
42
+ if (!activeTheme) return themeInformations[0];
43
+ return themeInformations.find((theme) => theme.systemName === activeTheme) || themeInformations[0];
44
+ };
45
+ export const GetCurrentThemeName = (): string => GetCurrentTheme().systemName;
@@ -0,0 +1,149 @@
1
+ "use client";
2
+
3
+ import { DEFAULT_SMALL_ICON_BOX_SIZE } from "../interfaces/icon-interfaces";
4
+ import { DEFAULT_FONT_WEIGHTS } from "../interfaces/layout-interfaces";
5
+ import { O } from "../nexus-client";
6
+ import { IThemeColors, IThemeInformation } from "./../interfaces/theme-interfaces";
7
+ import { GetCurrentTheme, SetCurrentTheme } from "./localstorage-service";
8
+
9
+ const I = "!important;";
10
+
11
+ const _setVariable = (key: string, value: string | null) => {
12
+ if (value) document.documentElement.style.setProperty(key, value);
13
+ };
14
+
15
+ const _initializeThemes = (themeInformations: IThemeInformation[]): boolean => {
16
+ if (!themeInformations || themeInformations.length === 0) return false;
17
+
18
+ const activeTheme = GetCurrentTheme();
19
+ return _initializeTheme(activeTheme!);
20
+ };
21
+ const _setRule = (sheet: CSSStyleSheet, s: string, r: string) => sheet.insertRule(`${s} { ${r} }`, sheet.cssRules.length);
22
+ const _setResponsiveRule = (sheet: CSSStyleSheet, i: number, max: number, pre: string, w: string, g?: number) => sheet.insertRule(`@media (max-width: ${max}px) { ${g !== undefined ? `.g${g} > ` : ""}.col-${pre}-${i} { width: ${w}${I} } }`, sheet.cssRules.length);
23
+ const _initializeTheme = (theme: IThemeInformation): boolean => {
24
+ if (!theme) return false;
25
+ SetCurrentTheme(theme.systemName);
26
+
27
+ const THEME_KEYS = Object.keys(theme.themeColors);
28
+ for (const key of THEME_KEYS) {
29
+ const color = theme.themeColors[key as keyof IThemeColors];
30
+ const [background, hover, focus, text] = color.split("|");
31
+
32
+ if (!background) continue;
33
+ const keyNumber = key.replace("C", "");
34
+
35
+ if (background !== "NULL") _setVariable(`--B${keyNumber}`, background);
36
+ if (hover !== "NULL") _setVariable(`--H${keyNumber}`, hover);
37
+ if (focus !== "NULL") _setVariable(`--F${keyNumber}`, focus);
38
+ if (text !== "NULL") _setVariable(`--T${keyNumber}`, text);
39
+ }
40
+
41
+ return true;
42
+ };
43
+ export const InitializeStyles = () => {
44
+ const el = document.getElementById("nexus-styles") as HTMLStyleElement;
45
+ if (!el || !el.classList.contains("nexus-styles")) el.classList.add("nexus-styles");
46
+ const sheet = el.sheet as CSSStyleSheet;
47
+ const themeInformations = O.systemThemes;
48
+ if (!themeInformations || themeInformations.length === 0) return;
49
+ _initializeThemes(themeInformations);
50
+
51
+ const BREAK_POINTS = { xl: 1200, lg: 1050, med: 900, nr: 800, sm: 700, xs: 600 } as any;
52
+ const SUFFIXES = ["", "-top", "-right", "-bottom", "-left"];
53
+ const DIRECTIONS = ["", "t", "r", "b", "l"];
54
+
55
+ Array.from({ length: 12 }, (_, i) => i + 1).forEach((i) => {
56
+ const w = `${(i / 12) * 100}%`;
57
+ _setRule(sheet, `.col-${i}`, `float: left; box-sizing: border-box; width: ${w};`);
58
+ Object.keys(BREAK_POINTS).forEach((b) => _setResponsiveRule(sheet, i, BREAK_POINTS[b], b, w));
59
+ });
60
+
61
+ Array.from({ length: 10 }, (_, i) => i + 1).forEach((i) => {
62
+ const m = 0.2 * i,
63
+ w = `calc((100% / 12) * ${i} - ${m * 2}rem)`;
64
+ _setRule(sheet, `.g${i}`, `padding: 0 ${m}rem;`);
65
+ _setRule(sheet, `.g${i} > [class*='col-']`, `margin: 0 ${m}rem; float: left; box-sizing: border-box;`);
66
+ _setRule(sheet, `.g${i} > .col-12`, `width: ${w}; float: left; box-sizing: border-box;`);
67
+ Array.from({ length: 12 }, (_, j) => j + 1).forEach((j) => {
68
+ const wj = `calc((100% / 12) * ${j} - ${m * 2}rem)`;
69
+ _setRule(sheet, `.g${i} > .col-${j}`, `width: ${wj}; float: left; box-sizing: border-box;`);
70
+ Object.keys(BREAK_POINTS).forEach((b) => _setResponsiveRule(sheet, j, BREAK_POINTS[b], b, wj, i));
71
+ });
72
+ });
73
+ Array.from({ length: 11 }, (_, i) => {
74
+ const v = 0.2 * (10 - i);
75
+ DIRECTIONS.forEach((d, idx) => {
76
+ const imp = d ? I : ";";
77
+ _setRule(sheet, `.m${d}${10 - i}`, `margin${SUFFIXES[idx]}: ${v}rem${imp}`);
78
+ _setRule(sheet, `.p${d}${10 - i}`, `padding${SUFFIXES[idx]}: ${v}rem${imp}`);
79
+ });
80
+ _setRule(sheet, `.g${10 - i}`, `gap: ${v}rem;`);
81
+ _setRule(sheet, `.cg${10 - i}`, `column-gap: ${v}rem;`);
82
+ _setRule(sheet, `.rg${10 - i}`, `row-gap: ${v}rem;`);
83
+ if (i > 0 && i <= 6) _setRule(sheet, `.h${i}, h${i}`, `font-size: ${(6 - i) * 0.3 + 1}rem;font-weight: 600;`);
84
+ });
85
+ Array.from({ length: 13 }, (_, i) => 0.6 + 0.1 * i).forEach((v) => _setRule(sheet, `.fs-${v.toFixed(1).replace(".", "")}`, `font-size: ${v.toFixed(1)}rem;`));
86
+ Array.from({ length: 4 }, (_, i) => 0.5 + 0.1 * i).forEach((v) => _setRule(sheet, `.o${v.toFixed(1).replace(".", "")}`, `opacity: ${v.toFixed(1)};`));
87
+ Array.from({ length: 9 }, (_, i) => {
88
+ _setRule(sheet, `.tl${i}`, `display: -webkit-box; -webkit-box-orient: vertical; overflow: hidden; text-overflow: ellipsis; -webkit-line-clamp: ${i};`);
89
+ if (i <= 8) _setRule(sheet, `.bs${i}`, `box-shadow: var(--BS${i});`);
90
+ });
91
+
92
+ DEFAULT_FONT_WEIGHTS.forEach((weight) => _setRule(sheet, `.fw${weight}`, `font-weight: ${weight};`));
93
+
94
+ [90, 180, 270].forEach((r) => _setRule(sheet, `.r${r}`, `transform: rotate(${r}deg);`));
95
+ [1, 2, 3].forEach((s) => {
96
+ const b = `var(--BRD${s}) solid var(--B30)`;
97
+ DIRECTIONS.forEach((d, i) => _setRule(sheet, `.b${d}${s}`, `border${SUFFIXES[i]}: ${b}${d ? ` ${I}` : ""}`));
98
+ _setRule(sheet, `.bat${s}`, `border: var(--BRD${s}) solid transparent`);
99
+ });
100
+
101
+ const THEME_KEYS = Object.keys(themeInformations[0].themeColors);
102
+ for (const key of THEME_KEYS) {
103
+ const keyNumber = key.replace("C", "");
104
+ _setRule(sheet, `.bg${keyNumber}`, `background-color: var(--B${keyNumber}) ${I}; color: var(--T${keyNumber});`);
105
+ _setRule(sheet, `.h.bg${keyNumber}:hover`, `background-color: var(--H${keyNumber}) ${I}`);
106
+ _setRule(sheet, `.h.bg${keyNumber}:focus`, `background-color: var(--F${keyNumber}) ${I}`);
107
+ _setRule(sheet, `.tx${keyNumber}`, `color: var(--T${keyNumber}) ${I}`);
108
+ }
109
+
110
+ const ICON_SIZES = {
111
+ xxs: 0.8,
112
+ xs: 1,
113
+ ssm: 1.25,
114
+ sm: 1.4,
115
+ nr: 1.55,
116
+ med: 1.75,
117
+ lg: 1.95,
118
+ xl: 2.2,
119
+ xxl: 2.5,
120
+ fs: 2.85,
121
+ };
122
+
123
+ const ICON_BOX_SCALES = {
124
+ xxs: 1 / 1.7,
125
+ xs: 1 / 1.5,
126
+ sm: DEFAULT_SMALL_ICON_BOX_SIZE,
127
+ ssm: 1 / 1.35,
128
+ lg: 1.25,
129
+ med: 1.1,
130
+ xl: 1.5,
131
+ xxl: 1.8,
132
+ };
133
+ Object.entries(ICON_SIZES).forEach(([k, v]) => _setRule(sheet, `.icon.${k}`, `font-size: ${v}rem;`));
134
+
135
+ Object.entries(ICON_BOX_SCALES).forEach(([k, s]) => {
136
+ const size = `calc(var(--IH) * ${s})`;
137
+ const css = `min-width: ${size} ${I}; min-height: ${size} ${I}; max-width: ${size} ${I}; max-height: ${size} ${I};`;
138
+ _setRule(sheet, `.ib.${k}`, css);
139
+ });
140
+ };
141
+ export const SwitchTheme = (themeCode: string): boolean => {
142
+ const themeInformations = O.systemThemes;
143
+ if (!themeInformations || themeInformations.length === 0) return false;
144
+
145
+ const theme = themeInformations.find((theme) => theme.systemName === themeCode);
146
+ if (!theme) return false;
147
+ SetCurrentTheme(theme.systemName);
148
+ return _initializeTheme(theme);
149
+ };
@@ -0,0 +1,269 @@
1
+ /**
2
+ * EAnimations / EAnimationClasses — nexus.shared/interfaces/layout-interfaces.tsx
3
+ * Legacy transition tokens (nexus.utility `.h`, `.anim`): --ANIM_SPD, --ANIM
4
+ */
5
+
6
+ :root {
7
+ --ANIM_SPD: 300ms;
8
+ --anim-ease: cubic-bezier(0.33, 1, 0.68, 1);
9
+ --anim-ease-out: cubic-bezier(0.16, 1, 0.3, 1);
10
+ --anim-ease-in: cubic-bezier(0.32, 0, 0.67, 0);
11
+ --ANIM: all var(--ANIM_SPD);
12
+
13
+ --SPIN_BOX_SIZE: 3.5rem;
14
+ --SPIN_BOX_BORDER_SIZE: 0.45rem;
15
+ }
16
+
17
+ /* ----- One-shot: fade / pulse ----- */
18
+
19
+ .an-fa,
20
+ .an-fo,
21
+ .an-fio,
22
+ .an-pi,
23
+ .an-po {
24
+ animation-duration: var(--ANIM_SPD);
25
+ animation-timing-function: var(--anim-ease-out);
26
+ animation-fill-mode: both;
27
+ }
28
+
29
+ .an-fa {
30
+ animation-name: fadeIn;
31
+ }
32
+
33
+ .an-fo {
34
+ animation-name: fadeOut;
35
+ animation-timing-function: var(--anim-ease-in);
36
+ animation-fill-mode: forwards;
37
+ }
38
+
39
+ .an-fio {
40
+ animation-name: fadeInOut;
41
+ animation-duration: calc(var(--ANIM_SPD) * 2);
42
+ animation-timing-function: var(--anim-ease);
43
+ animation-iteration-count: 1;
44
+ animation-fill-mode: both;
45
+ animation: fadeInOut calc(var(--ANIM_SPD) * 6) ease-in-out infinite;
46
+ }
47
+
48
+ .an-pi {
49
+ animation-name: pulseIn;
50
+ }
51
+
52
+ .an-po {
53
+ animation-name: pulseOut;
54
+ animation-timing-function: var(--anim-ease-in);
55
+ animation-fill-mode: forwards;
56
+ }
57
+
58
+ .an-pio {
59
+ animation-name: pulseInOut;
60
+ animation-duration: calc(var(--ANIM_SPD) * 2);
61
+ animation-iteration-count: infinite;
62
+ animation-direction: alternate;
63
+ animation-timing-function: var(--anim-ease);
64
+ animation-fill-mode: none;
65
+ }
66
+
67
+ /* ----- Infinite: bounce (vertical), spin (ring), slide bar (L → R) ----- */
68
+
69
+ .an-bounce {
70
+ animation-name: bounce;
71
+ animation-duration: calc(var(--ANIM_SPD) * 4);
72
+ animation-timing-function: linear;
73
+ animation-iteration-count: infinite;
74
+ }
75
+
76
+ .an-spin {
77
+ display: inline-block;
78
+ box-sizing: border-box;
79
+ width: var(--SPIN_BOX_SIZE);
80
+ height: var(--SPIN_BOX_SIZE);
81
+ vertical-align: middle;
82
+ border-radius: 50%;
83
+ border-style: solid;
84
+ border-width: var(--SPIN_BOX_BORDER_SIZE);
85
+ border-color: var(--B30);
86
+ border-top-color: var(--B20);
87
+ animation-name: spin;
88
+ animation-duration: calc(var(--ANIM_SPD) * 5);
89
+ animation-timing-function: linear;
90
+ animation-iteration-count: infinite;
91
+ }
92
+
93
+ .an-sbar {
94
+ position: relative;
95
+ display: block;
96
+ width: 100%;
97
+ max-width: 14rem;
98
+ height: 0.28rem;
99
+ min-height: 0.28rem;
100
+ overflow: hidden;
101
+ border-radius: 999px;
102
+ background-color: var(--B30);
103
+ }
104
+
105
+ .an-sbar::after {
106
+ content: "";
107
+ position: absolute;
108
+ top: 0;
109
+ left: -45%;
110
+ width: 45%;
111
+ height: 100%;
112
+ border-radius: inherit;
113
+ background: linear-gradient(90deg, var(--B400), var(--B20), var(--B600), var(--B400));
114
+ background-size: 200% 100%;
115
+ animation: slideBarSweep calc(var(--ANIM_SPD) * 5) ease-in-out infinite;
116
+ }
117
+
118
+ /**
119
+ * Pill runs between track walls (alternate = return trip, no jump to 0).
120
+ * --bbar-ball-pct: segment width (unitless %). --bbar-dur: one leg duration.
121
+ * --bbar-ease: slightly slower near each wall; middle stays quicker.
122
+ */
123
+ .an-bbar {
124
+ position: relative;
125
+ display: block;
126
+ width: 100%;
127
+ max-width: 14rem;
128
+ height: 0.28rem;
129
+ min-height: 0.28rem;
130
+ overflow: hidden;
131
+ border-radius: 999px;
132
+ background-color: var(--B30);
133
+ --bbar-ball-pct: 40;
134
+ --bbar-dur: 1s;
135
+ /** Slight slowdown at each wall (start, far end, and same on the return leg). */
136
+ --bbar-ease: cubic-bezier(0.45, 0.1, 0.55, 0.9);
137
+ }
138
+
139
+ .an-bbar::after {
140
+ content: "";
141
+ position: absolute;
142
+ top: 0;
143
+ left: 0;
144
+ width: calc(var(--bbar-ball-pct) * 1%);
145
+ height: 100%;
146
+ border-radius: inherit;
147
+ background: linear-gradient(90deg, var(--B400), var(--B20), var(--B600), var(--B400));
148
+ background-size: 200% 100%;
149
+ will-change: transform;
150
+ animation-name: bounceBarBall;
151
+ animation-duration: var(--bbar-dur);
152
+ animation-timing-function: var(--bbar-ease);
153
+ animation-iteration-count: infinite;
154
+ animation-direction: alternate;
155
+ }
156
+
157
+ /* ----- Keyframes ----- */
158
+
159
+ @keyframes fadeIn {
160
+ from {
161
+ opacity: 0;
162
+ }
163
+
164
+ to {
165
+ opacity: 1;
166
+ }
167
+ }
168
+
169
+ @keyframes fadeOut {
170
+ from {
171
+ opacity: 1;
172
+ }
173
+
174
+ to {
175
+ opacity: 0;
176
+ }
177
+ }
178
+
179
+ @keyframes fadeInOut {
180
+ 0% {
181
+ opacity: 1;
182
+ }
183
+
184
+ 50% {
185
+ opacity: 0.6;
186
+ }
187
+
188
+ 100% {
189
+ opacity: 1;
190
+ }
191
+ }
192
+
193
+ @keyframes pulseInOut {
194
+ from {
195
+ transform: scale3d(1, 1, 1);
196
+ }
197
+
198
+ to {
199
+ transform: scale3d(1.04, 1.04, 1);
200
+ }
201
+ }
202
+
203
+ @keyframes bounce {
204
+ 0%,
205
+ 20%,
206
+ 50%,
207
+ 80%,
208
+ 100% {
209
+ transform: translate3d(0, 0, 0);
210
+ }
211
+
212
+ 40% {
213
+ transform: translate3d(0, -0.5rem, 0);
214
+ }
215
+
216
+ 60% {
217
+ transform: translate3d(0, -0.25rem, 0);
218
+ }
219
+ }
220
+
221
+ @keyframes spin {
222
+ 0% {
223
+ transform: rotate3d(0, 0, 1, 0deg);
224
+ border-top-color: var(--B20);
225
+ }
226
+
227
+ 50% {
228
+ border-top-color: var(--B400);
229
+ }
230
+
231
+ 75% {
232
+ border-top-color: var(--B600);
233
+ }
234
+
235
+ 100% {
236
+ transform: rotate3d(0, 0, 1, 360deg);
237
+ border-top-color: var(--B20);
238
+ }
239
+ }
240
+
241
+ @keyframes slideBarSweep {
242
+ 0% {
243
+ transform: translate3d(0, 0, 0);
244
+ background-position: 0% 50%;
245
+ opacity: 0.85;
246
+ }
247
+
248
+ 50% {
249
+ opacity: 1;
250
+ }
251
+
252
+ 100% {
253
+ transform: translate3d(320%, 0, 0);
254
+ background-position: 100% 50%;
255
+ opacity: 0.9;
256
+ }
257
+ }
258
+
259
+ @keyframes bounceBarBall {
260
+ 0% {
261
+ transform: translate3d(0, 0, 0);
262
+ background-position: 0% 50%;
263
+ }
264
+
265
+ 100% {
266
+ transform: translate3d(calc((100 - var(--bbar-ball-pct)) / var(--bbar-ball-pct) * 100%), 0, 0);
267
+ background-position: 100% 50%;
268
+ }
269
+ }