cloud-ide-layout 0.0.1 → 1.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (81) hide show
  1. package/README.md +466 -13
  2. package/esm2022/lib/cloud-ide-layout.routes.mjs +24 -10
  3. package/esm2022/lib/layout/console/console-wrapper/console-wrapper.component.mjs +6 -6
  4. package/esm2022/lib/layout/console/console.service.mjs +28 -0
  5. package/esm2022/lib/layout/footer/footer-wrapper/footer-wrapper.component.mjs +16 -8
  6. package/esm2022/lib/layout/footer/footer.service.mjs +28 -0
  7. package/esm2022/lib/layout/header/header-wrapper/header-wrapper.component.mjs +69 -18
  8. package/esm2022/lib/layout/header/header.service.mjs +17 -6
  9. package/esm2022/lib/layout/home/home-wrapper/home-wrapper.component.mjs +194 -7
  10. package/esm2022/lib/layout/layout/layout-wrapper/layout-wrapper.component.mjs +18 -9
  11. package/esm2022/lib/layout/request/request-wrapper/request-wrapper.component.mjs +54 -6
  12. package/esm2022/lib/layout/request/request.service.mjs +235 -0
  13. package/esm2022/lib/layout/request/tab-content/tab-content.component.mjs +84 -0
  14. package/esm2022/lib/layout/shared/shared-wrapper/shared-wrapper.component.mjs +32 -20
  15. package/esm2022/lib/layout/shared/shared.service.mjs +490 -14
  16. package/esm2022/lib/layout/sidebar/sidebar-wrapper/sidebar-wrapper.component.mjs +480 -15
  17. package/esm2022/lib/layout/sidebar/sidebar.service.mjs +20 -7
  18. package/esm2022/lib/layout/sidedrawer/cide-lyt-drawer-base.class.mjs +40 -0
  19. package/esm2022/lib/layout/sidedrawer/drawer-theme/drawer-theme.component.mjs +296 -0
  20. package/esm2022/lib/layout/sidedrawer/sidedrawer-notes/sidedrawer-notes.component.mjs +175 -0
  21. package/esm2022/lib/layout/sidedrawer/sidedrawer-notes/sidedrawer-notes.service.mjs +51 -0
  22. package/esm2022/lib/layout/sidedrawer/sidedrawer-wrapper/sidedrawer-wrapper.component.mjs +254 -9
  23. package/esm2022/lib/layout/sidedrawer/sidedrawer.service.mjs +70 -0
  24. package/esm2022/lib/services/app-state/app-state-helper.service.mjs +222 -0
  25. package/esm2022/lib/services/app-state/app-state.service.mjs +256 -0
  26. package/esm2022/lib/services/app-state/index.mjs +3 -0
  27. package/esm2022/lib/services/cache-manager/cache-manager.service.mjs +112 -0
  28. package/esm2022/lib/services/file-manager/file-manager.service.mjs +7 -7
  29. package/esm2022/lib/services/tab-state.service.mjs +128 -0
  30. package/esm2022/lib/services/theme/theme.service.mjs +151 -0
  31. package/esm2022/lib/services/user-status/user-status.service.mjs +135 -0
  32. package/esm2022/lib/utils/custom-route-reuse-strategy.mjs +61 -0
  33. package/esm2022/lib/utils/index.mjs +2 -0
  34. package/esm2022/public-api.mjs +7 -1
  35. package/fesm2022/cloud-ide-layout-cloud-ide-layout-DqL3A73V.mjs +2914 -0
  36. package/fesm2022/cloud-ide-layout-cloud-ide-layout-DqL3A73V.mjs.map +1 -0
  37. package/fesm2022/cloud-ide-layout-drawer-theme.component-xd8IG3WP.mjs +443 -0
  38. package/fesm2022/cloud-ide-layout-drawer-theme.component-xd8IG3WP.mjs.map +1 -0
  39. package/fesm2022/cloud-ide-layout-home-wrapper.component-DEdsEiaq.mjs +197 -0
  40. package/fesm2022/cloud-ide-layout-home-wrapper.component-DEdsEiaq.mjs.map +1 -0
  41. package/fesm2022/cloud-ide-layout-sidedrawer-notes.component-ds12wZbh.mjs +260 -0
  42. package/fesm2022/cloud-ide-layout-sidedrawer-notes.component-ds12wZbh.mjs.map +1 -0
  43. package/fesm2022/cloud-ide-layout.mjs +1 -261
  44. package/fesm2022/cloud-ide-layout.mjs.map +1 -1
  45. package/lib/cloud-ide-layout.routes.d.ts +1 -0
  46. package/lib/layout/console/console-wrapper/console-wrapper.component.d.ts +3 -3
  47. package/lib/layout/console/console.service.d.ts +9 -0
  48. package/lib/layout/footer/footer-wrapper/footer-wrapper.component.d.ts +7 -3
  49. package/lib/layout/footer/footer.service.d.ts +9 -0
  50. package/lib/layout/header/header-wrapper/header-wrapper.component.d.ts +17 -9
  51. package/lib/layout/header/header.service.d.ts +4 -3
  52. package/lib/layout/home/home-wrapper/home-wrapper.component.d.ts +90 -1
  53. package/lib/layout/request/request-wrapper/request-wrapper.component.d.ts +10 -1
  54. package/lib/layout/request/request.service.d.ts +60 -0
  55. package/lib/layout/request/tab-content/tab-content.component.d.ts +19 -0
  56. package/lib/layout/shared/shared-wrapper/shared-wrapper.component.d.ts +4 -5
  57. package/lib/layout/shared/shared.service.d.ts +104 -6
  58. package/lib/layout/sidebar/sidebar-wrapper/sidebar-wrapper.component.d.ts +135 -6
  59. package/lib/layout/sidebar/sidebar.service.d.ts +3 -2
  60. package/lib/layout/sidedrawer/cide-lyt-drawer-base.class.d.ts +16 -0
  61. package/lib/layout/sidedrawer/drawer-theme/drawer-theme.component.d.ts +71 -0
  62. package/lib/layout/sidedrawer/sidedrawer-notes/sidedrawer-notes.component.d.ts +48 -0
  63. package/lib/layout/sidedrawer/sidedrawer-notes/sidedrawer-notes.service.d.ts +13 -0
  64. package/lib/layout/sidedrawer/sidedrawer-wrapper/sidedrawer-wrapper.component.d.ts +28 -3
  65. package/lib/layout/sidedrawer/sidedrawer.service.d.ts +30 -0
  66. package/lib/services/app-state/app-state-helper.service.d.ts +150 -0
  67. package/lib/services/app-state/app-state.service.d.ts +85 -0
  68. package/lib/services/app-state/index.d.ts +3 -0
  69. package/lib/services/cache-manager/cache-manager.service.d.ts +64 -0
  70. package/lib/services/file-manager/file-manager.service.d.ts +0 -2
  71. package/lib/services/tab-state.service.d.ts +79 -0
  72. package/lib/services/theme/theme.service.d.ts +71 -0
  73. package/lib/services/user-status/user-status.service.d.ts +57 -0
  74. package/lib/utils/custom-route-reuse-strategy.d.ts +15 -0
  75. package/lib/utils/index.d.ts +1 -0
  76. package/package.json +2 -2
  77. package/public-api.d.ts +4 -0
  78. package/src/lib/assets/css/cide-lyt-style.scss +182 -0
  79. package/src/lib/assets/css/cide-lyt-variable.scss +119 -0
  80. package/fesm2022/cloud-ide-layout-home-wrapper.component-BV7ptL0Y.mjs +0 -14
  81. package/fesm2022/cloud-ide-layout-home-wrapper.component-BV7ptL0Y.mjs.map +0 -1
@@ -0,0 +1,443 @@
1
+ import { isPlatformBrowser, NgFor, NgIf, NgClass } from '@angular/common';
2
+ import * as i0 from '@angular/core';
3
+ import { InjectionToken, signal, inject, PLATFORM_ID, Injectable, Component, Inject } from '@angular/core';
4
+ import * as i2 from '@angular/forms';
5
+ import { FormsModule } from '@angular/forms';
6
+ import { CideSelectComponent, CideEleButtonComponent } from 'cloud-ide-element';
7
+ import { HttpClient } from '@angular/common/http';
8
+ import { tap } from 'rxjs/operators';
9
+ import { of } from 'rxjs';
10
+ import { cidePath, hostManagerRoutesUrl, designConfigRoutesUrl } from 'cloud-ide-lms-model';
11
+ import _, { cloneDeep, isEqual } from 'lodash';
12
+ import { A as AppStateHelperService } from './cloud-ide-layout-cloud-ide-layout-DqL3A73V.mjs';
13
+
14
+ // Define an InjectionToken for the environment configuration
15
+ // This is needed to inject environment variables into services provided in 'root'
16
+ const ENVIRONMENT_CONFIG = new InjectionToken('ENVIRONMENT_CONFIG');
17
+ /**
18
+ * Utility function to convert database format keys to CSS format and handle units
19
+ * @param key - The database format key (e.g., 'font_size_xxxl')
20
+ * @param value - The value to be set
21
+ * @returns Object with cssVarName and processed value
22
+ */
23
+ function processThemeVariable(key, value) {
24
+ // 1. Convert the key from the DB format to the CSS format.
25
+ const cssVarName = `${key.replace(/_/g, '-')}`;
26
+ // 2. Append the font_size and line_height value to rem
27
+ let processedValue = value;
28
+ if (cssVarName.includes('font-size') || cssVarName.includes('line-height')) {
29
+ processedValue = parseFloat(value) + 'rem';
30
+ }
31
+ return { cssVarName, processedValue: processedValue };
32
+ }
33
+ /**
34
+ * Sets a single CSS variable on the document root element
35
+ * @param key - The database format key (e.g., 'font_size_xxxl')
36
+ * @param value - The value to be set
37
+ * @param platformId - Platform ID for browser check
38
+ */
39
+ function setCSSVariable(key, value, platformId) {
40
+ if (isPlatformBrowser(platformId)) {
41
+ const { cssVarName, processedValue } = processThemeVariable(key, value);
42
+ const root = document.documentElement;
43
+ root.style.setProperty(cssVarName, processedValue);
44
+ }
45
+ }
46
+ class CideLytThemeService {
47
+ constructor() {
48
+ // Modern Angular signals for reactive state management
49
+ this.selectedThemeSignal = signal("");
50
+ this.selectedTheme = this.selectedThemeSignal.asReadonly();
51
+ // Modern dependency injection
52
+ this.http = inject(HttpClient);
53
+ this.platformId = inject(PLATFORM_ID);
54
+ this.environment = inject(ENVIRONMENT_CONFIG);
55
+ }
56
+ /**
57
+ * Fetches the theme from the API and applies it to the document.
58
+ * This method is intended to be called when the theme should actually be applied.
59
+ */
60
+ fetchAndApplyTheme() {
61
+ console.log('Fetching and applying theme via CideLytThemeService...');
62
+ return this.loadTheme(); // Use the existing loadTheme logic
63
+ }
64
+ /**
65
+ * Fetches the list of system themes from the API.
66
+ */
67
+ fetchSystemThemesList() {
68
+ return this.http.get(cidePath.join([
69
+ hostManagerRoutesUrl.cideSuiteHost,
70
+ designConfigRoutesUrl?.module,
71
+ designConfigRoutesUrl?.getSystemThemesList
72
+ ]));
73
+ }
74
+ /**
75
+ * Internal method to fetch the theme from the API and apply it.
76
+ */
77
+ loadTheme() {
78
+ return this.http.post(cidePath.join([hostManagerRoutesUrl.cideSuiteHost, designConfigRoutesUrl?.module, designConfigRoutesUrl?.getSystemTheme]), { syupth_user_id_user: "659a7ea0a1f0e08246661766" }).pipe(tap(theme => {
79
+ console.log("Applying theme:", theme);
80
+ this.applyTheme(theme?.data);
81
+ }));
82
+ }
83
+ /**
84
+ * Sets the CSS variables on the root element.
85
+ * @param theme - An object where keys are CSS variable names (e.g., '--color-text-body')
86
+ * and values are the color strings (e.g., '#ffffff').
87
+ */
88
+ applyTheme(theme) {
89
+ console.log("Applying theme:", theme);
90
+ let merged = {};
91
+ if (theme?.core_system_themes?.syth_properties) {
92
+ merged = { ...merged, ...theme.core_system_themes.syth_properties };
93
+ this.selectedThemeSignal.set(theme.core_system_themes._id);
94
+ }
95
+ if (theme?.core_system_organization_themes?.syoth_overrides) {
96
+ merged = { ...merged, ...theme.core_system_organization_themes.syoth_overrides };
97
+ }
98
+ if (theme?.core_system_theme_user_preferences?.syupth_overrides) {
99
+ merged = { ...merged, ...theme.core_system_theme_user_preferences.syupth_overrides };
100
+ }
101
+ console.log("Merged theme:", merged);
102
+ // Check if the code is running in a browser environment.
103
+ if (isPlatformBrowser(this.platformId)) {
104
+ const root = document.documentElement;
105
+ for (const [key, value] of Object.entries(merged)) {
106
+ const { cssVarName, processedValue } = processThemeVariable(key, value);
107
+ // Set the CSS custom property on the root element.
108
+ root.style.setProperty(cssVarName, processedValue);
109
+ }
110
+ }
111
+ }
112
+ /**
113
+ * Saves the system theme user preferences.
114
+ * @param themeVars - The theme variables to save.
115
+ * @returns An observable of the system theme user preferences.
116
+ */
117
+ saveSystemThemeUserPreferences(themeVars) {
118
+ return this.http.post(cidePath.join([hostManagerRoutesUrl.cideSuiteHost, designConfigRoutesUrl?.module, designConfigRoutesUrl?.systemThemeUserPreferences]), themeVars);
119
+ }
120
+ /**
121
+ * Updates a single CSS variable using the utility function
122
+ * @param key - The database format key (e.g., 'font_size_xxxl')
123
+ * @param value - The value to be set
124
+ */
125
+ updateCSSVariable(key, value) {
126
+ setCSSVariable(key, value, this.platformId);
127
+ }
128
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.7", ngImport: i0, type: CideLytThemeService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
129
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.7", ngImport: i0, type: CideLytThemeService, providedIn: 'root' }); }
130
+ }
131
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.7", ngImport: i0, type: CideLytThemeService, decorators: [{
132
+ type: Injectable,
133
+ args: [{
134
+ providedIn: 'root'
135
+ }]
136
+ }] });
137
+ /**
138
+ * Factory function for APP_INITIALIZER.
139
+ * This function is used in your app.config.ts.
140
+ * It conditionally triggers theme loading based on the environment setting.
141
+ */
142
+ function themeFactory(themeService, environmentConfig) {
143
+ return () => {
144
+ if (!environmentConfig.applyThemeOnLogin) {
145
+ // If theme should be applied on app initialize, fetch and apply it.
146
+ console.log('APP_INITIALIZER: Applying theme...');
147
+ return themeService.fetchAndApplyTheme();
148
+ }
149
+ else {
150
+ // If theme should be applied on login, APP_INITIALIZER does nothing for the theme.
151
+ // We return an observable that immediately completes.
152
+ console.log('APP_INITIALIZER: Theme application deferred to after login (per environment config).');
153
+ return of(undefined); // Return an observable that completes immediately
154
+ }
155
+ };
156
+ }
157
+
158
+ class CideLytDrawerThemeComponent {
159
+ constructor(themeService, platformId) {
160
+ this.themeService = themeService;
161
+ this.platformId = platformId;
162
+ this.appState = inject(AppStateHelperService);
163
+ // Preset themes
164
+ this.presetThemes = [];
165
+ this.selectedTheme = '';
166
+ this.isLoadingThemes = false;
167
+ this.themeLoadError = '';
168
+ this.mergedTheme = {};
169
+ this.isRTL = false;
170
+ this.originalThemeGroupValues = [];
171
+ this.originalApiThemeValues = {}; // Store original API values
172
+ this.themeGroups = [
173
+ {
174
+ label: 'Brand Colors',
175
+ items: [
176
+ { label: 'Primary', varName: '--cide-theme-color-brand-primary', value: '#4f46e5', type: 'text' },
177
+ { label: 'Accent', varName: '--cide-theme-color-brand-accent', value: '#4338ca', type: 'text' },
178
+ { label: 'Separator', varName: '--cide-theme-color-brand-separator', value: '#e5e7eb', type: 'text' }
179
+ ]
180
+ },
181
+ {
182
+ label: 'Text Colors',
183
+ items: [
184
+ { label: 'Body Text', varName: '--cide-theme-color-text-body', value: '#374151', type: 'text' },
185
+ { label: 'Heading Text', varName: '--cide-theme-color-text-heading', value: '#111827', type: 'text' },
186
+ { label: 'Link Text', varName: '--cide-theme-color-text-link', value: '#3b82f6', type: 'text' },
187
+ { label: 'Muted Text', varName: '--cide-theme-color-text-muted', value: '#6b7280', type: 'text' }
188
+ ]
189
+ },
190
+ {
191
+ label: 'Background Colors',
192
+ items: [
193
+ { label: 'Body Background', varName: '--cide-theme-color-background-body', value: '#ffffff', type: 'text' }
194
+ ]
195
+ },
196
+ {
197
+ label: 'Layout Dimensions',
198
+ items: [
199
+ { label: 'Stack Wrapper Width', varName: '--cide-lyt-stack-wrapper-width', value: '60', type: 'number', min: 20, max: 120 }
200
+ ]
201
+ },
202
+ {
203
+ label: 'Font Sizes',
204
+ items: [
205
+ { label: 'XXXL Font Size', varName: '--cide-theme-font-size-xxxl', value: '3.052', type: 'number', min: 1, max: 10 },
206
+ { label: 'XXL Font Size', varName: '--cide-theme-font-size-xxl', value: '2.441', type: 'number', min: 1, max: 10 },
207
+ { label: 'XL Font Size', varName: '--cide-theme-font-size-xl', value: '1.953', type: 'number', min: 1, max: 10 },
208
+ { label: 'LG Font Size', varName: '--cide-theme-font-size-lg', value: '1.563', type: 'number', min: 1, max: 10 },
209
+ { label: 'MD Font Size', varName: '--cide-theme-font-size-md', value: '1.25', type: 'number', min: 1, max: 10 },
210
+ { label: 'Paragraph Font Size', varName: '--cide-theme-font-size-p', value: '1', type: 'number', min: 0.5, max: 5 },
211
+ { label: 'SM Font Size', varName: '--cide-theme-font-size-sm', value: '0.9', type: 'number', min: 0.5, max: 5 },
212
+ { label: 'XS Font Size', varName: '--cide-theme-font-size-xs', value: '0.8', type: 'number', min: 0.5, max: 5 }
213
+ ]
214
+ },
215
+ {
216
+ label: 'Line Heights',
217
+ items: [
218
+ { label: 'Body Line Height', varName: '--cide-theme-line-height-body', value: '1.6', type: 'number', min: 1, max: 3 },
219
+ { label: 'Heading Line Height', varName: '--cide-theme-line-height-heading', value: '1.2', type: 'number', min: 1, max: 3 }
220
+ ]
221
+ }
222
+ ];
223
+ }
224
+ ngOnInit() {
225
+ // Modern Angular v20 pattern: Use Signals directly
226
+ this.selectedTheme = this.themeService.selectedTheme();
227
+ // fetch the system themes list
228
+ this.isLoadingThemes = true;
229
+ this.themeService.fetchSystemThemesList().subscribe({
230
+ next: (res) => {
231
+ const themes = res?.data?.core_system_themes || [];
232
+ this.presetThemes = themes.map((theme) => ({
233
+ value: theme._id || '',
234
+ label: theme.syth_theme_name || theme.syth_theme_id || '',
235
+ theme
236
+ }));
237
+ this.isLoadingThemes = false;
238
+ // If user has no theme set, select and apply the default theme
239
+ if (!this.selectedTheme) {
240
+ const defaultTheme = this.presetThemes.find(t => t.theme.syth_is_default);
241
+ if (defaultTheme) {
242
+ this.selectedTheme = defaultTheme.value;
243
+ // Apply the default theme as CSS variables
244
+ if (defaultTheme.theme.syth_properties) {
245
+ Object.entries(defaultTheme.theme.syth_properties).forEach(([varName, value]) => {
246
+ this.updateVar(varName, value);
247
+ });
248
+ }
249
+ }
250
+ }
251
+ },
252
+ error: () => {
253
+ this.themeLoadError = 'Failed to load themes';
254
+ this.isLoadingThemes = false;
255
+ }
256
+ });
257
+ this.loadAndApplyUserTheme();
258
+ }
259
+ loadAndApplyUserTheme() {
260
+ this.themeService.loadTheme().subscribe({
261
+ next: (res) => {
262
+ const base = res?.data?.core_system_themes;
263
+ const org = res?.data?.core_system_organization_themes;
264
+ const user = res?.data?.core_system_theme_user_preferences;
265
+ // Start with base theme properties
266
+ let merged = { ...(base?.syth_properties || {}) };
267
+ // Override with org overrides
268
+ if (org?.syoth_overrides) {
269
+ merged = { ...merged, ...org.syoth_overrides };
270
+ }
271
+ // Override with user overrides
272
+ if (user?.syupth_overrides) {
273
+ merged = { ...merged, ...user.syupth_overrides };
274
+ }
275
+ this.mergedTheme = merged;
276
+ // Store original API values for reset functionality
277
+ this.originalApiThemeValues = { ...merged };
278
+ // Apply merged theme as CSS variables
279
+ Object.entries(this.mergedTheme).forEach(([varName, value]) => {
280
+ this.updateVar(varName, value);
281
+ });
282
+ for (const group of this.themeGroups) {
283
+ for (const item of group.items) {
284
+ const key = item.varName.replace(/-/g, '_');
285
+ item.value = merged[item.varName] || merged[key] || item.value;
286
+ if (key.includes('font_size') || key.includes('line_height')) {
287
+ item.value = parseFloat(item.value);
288
+ }
289
+ }
290
+ }
291
+ // Store a deep copy of the current values for reset
292
+ this.originalThemeGroupValues = cloneDeep(this.themeGroups);
293
+ },
294
+ error: () => {
295
+ // handle error if needed
296
+ }
297
+ });
298
+ }
299
+ // Update CSS variable in real time
300
+ updateVar(varName, value) {
301
+ // You can use either the utility function directly or the service method
302
+ setCSSVariable(varName, value, this.platformId);
303
+ // Alternative: this.themeService.updateCSSVariable(varName, value);
304
+ }
305
+ onThemeChange(event) {
306
+ this.selectedTheme = event.value;
307
+ const selected = this.presetThemes.find(t => t.value === this.selectedTheme);
308
+ if (selected && selected.theme && selected.theme.syth_properties) {
309
+ // here we will check the theme selected by organization is same if yes then overide also for user preferences
310
+ if (this.themeService.selectedTheme() === selected.theme._id) {
311
+ this.loadAndApplyUserTheme();
312
+ }
313
+ else {
314
+ // Store original API values for the selected theme
315
+ this.originalApiThemeValues = _.cloneDeep(selected.theme.syth_properties);
316
+ // Update all group values from the selected theme
317
+ for (const group of this.themeGroups) {
318
+ for (const item of group.items) {
319
+ const key = item.varName.replace(/-/g, '_');
320
+ item.value = selected.theme.syth_properties[item.varName] ||
321
+ selected.theme.syth_properties[key] ||
322
+ item.value;
323
+ this.updateVar(item.varName, item.value);
324
+ if (key.includes('font_size') || key.includes('line_height')) {
325
+ item.value = parseFloat(item.value);
326
+ }
327
+ }
328
+ }
329
+ // Store a deep copy of the current values for reset
330
+ this.originalThemeGroupValues = cloneDeep(this.themeGroups);
331
+ }
332
+ }
333
+ }
334
+ onReset() {
335
+ // Restore all values from the original API values
336
+ for (const group of this.themeGroups) {
337
+ for (const item of group.items) {
338
+ const key = item.varName.replace(/-/g, '_');
339
+ // Get the original API value
340
+ const originalValue = this.originalApiThemeValues[item.varName] ||
341
+ this.originalApiThemeValues[key] ||
342
+ item.value;
343
+ // Update the item value
344
+ item.value = originalValue;
345
+ // Apply the CSS variable
346
+ this.updateVar(item.varName, item.value);
347
+ if (key.includes('font_size') || key.includes('line_height')) {
348
+ item.value = parseFloat(item.value);
349
+ }
350
+ }
351
+ }
352
+ // Update the originalThemeGroupValues to reflect the reset state
353
+ this.originalThemeGroupValues = cloneDeep(this.themeGroups);
354
+ }
355
+ onSave() {
356
+ // Collect all current values
357
+ const themeVars = {};
358
+ for (const group of this.themeGroups) {
359
+ for (const item of group.items) {
360
+ themeVars[item.varName?.replaceAll('-', '_')] = item.value;
361
+ }
362
+ }
363
+ const systemThemePreferences = {
364
+ syupth_overrides: {
365
+ ...themeVars
366
+ },
367
+ syupth_system_theme_id_syth: this.selectedTheme, // LATER: need to upadate LATER
368
+ syupth_user_id_user: this.appState.currentUser()?._id || '', // LATER: need to get user id from user
369
+ syupth_entity_id_syen: this.appState.getActiveEntityId() || '', // LATER: need to get entity id from user
370
+ syth_theme_id: "" // need to upadate LATER
371
+ };
372
+ // TODO: Send themeVars to backend or emit event by designConfigRoutesUrl?.systemThemeUserPreferences
373
+ this.themeService.saveSystemThemeUserPreferences(systemThemePreferences).subscribe({
374
+ next: (res) => {
375
+ console.log('Theme saved:', res);
376
+ // Modern Angular v20 pattern: Update Signal through service method
377
+ // Note: The theme service should provide a method to update the selected theme
378
+ // For now, we'll just log the change since the service doesn't expose a setter
379
+ console.log('Theme selected:', this.selectedTheme);
380
+ },
381
+ error: (error) => {
382
+ console.error('Error saving theme:', error);
383
+ }
384
+ });
385
+ }
386
+ hasUnsavedChanges() {
387
+ // chec selected theme is different
388
+ if (this.themeService.selectedTheme() !== this.selectedTheme) {
389
+ return true;
390
+ }
391
+ // check the theme groups are different
392
+ return !isEqual(this.themeGroups, this.originalThemeGroupValues);
393
+ }
394
+ /**
395
+ * Check if current values differ from the original API values
396
+ * This is useful for determining if reset should be enabled
397
+ */
398
+ hasChangesFromOriginal() {
399
+ for (const group of this.themeGroups) {
400
+ for (const item of group.items) {
401
+ const key = item.varName.replace(/-/g, '_');
402
+ const originalValue = this.originalApiThemeValues[item.varName] ||
403
+ this.originalApiThemeValues[key];
404
+ if (originalValue !== undefined && item.value !== originalValue) {
405
+ return true;
406
+ }
407
+ }
408
+ }
409
+ return false;
410
+ }
411
+ onColorChange(event, color) {
412
+ const input = event.target;
413
+ color.value = input.value;
414
+ this.updateVar(color.varName, color.value);
415
+ }
416
+ onTypographyChange(event, setting) {
417
+ const input = event.target;
418
+ setting.value = input.value;
419
+ this.updateVar(setting.varName, setting.type === 'number' ? setting.value : setting.value);
420
+ }
421
+ onLayoutChange(event, setting) {
422
+ const input = event.target;
423
+ setting.value = input.value;
424
+ // For layout dimensions, append 'px' unit to the value
425
+ this.updateVar(setting.varName, setting.value + 'px');
426
+ }
427
+ onDirectionToggle(event) {
428
+ this.isRTL = event.target.checked;
429
+ document.documentElement.dir = this.isRTL ? 'rtl' : 'ltr';
430
+ }
431
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.7", ngImport: i0, type: CideLytDrawerThemeComponent, deps: [{ token: CideLytThemeService }, { token: PLATFORM_ID }], target: i0.ɵɵFactoryTarget.Component }); }
432
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.7", type: CideLytDrawerThemeComponent, isStandalone: true, selector: "cide-lyt-drawer-theme", ngImport: i0, template: "<div class=\"tw-relative tw-h-full tw-bg-white tw-overflow-hidden tw-flex tw-flex-col\">\n <!-- STICKY HEADER SECTION -->\n <div class=\"tw-bg-white tw-sticky tw-top-0 tw-border-b tw-border-gray-200 tw-z-10 tw-flex-shrink-0\">\n <!-- DYNAMIC HEADING -->\n <div class=\"tw-flex tw-justify-between tw-items-center tw-p-2 tw-bg-white tw-border-b tw-border-gray-200\">\n <h6 class=\"tw-font-semibold tw-text-gray-800\">Preset Theme</h6>\n </div>\n </div>\n\n <!-- SCROLLABLE CONTENT AREA -->\n <div class=\"tw-flex-1 tw-overflow-y-auto tw-scroll-smooth tw-p-2 tw-flex tw-flex-col tw-gap-5 tw-text-sm tw-pb-3 theme-scroll-container\">\n <!-- Preset Theme -->\n <section>\n <cide-ele-select id=\"theme-selector\" [(ngModel)]=\"selectedTheme\" (change)=\"onThemeChange($event)\"\n [options]=\"presetThemes\" [size]=\"'sm'\"></cide-ele-select>\n </section>\n\n <!-- Direction Toggle -->\n <section>\n <div class=\"tw-flex tw-justify-between tw-items-center tw-mb-2\">\n <h2 class=\"tw-text-md tw-font-semibold tw-text-gray-800\">Text Direction</h2>\n <div class=\"tw-flex tw-items-center tw-gap-1\">\n <span class=\"tw-text-xs tw-text-gray-500\">LTR</span>\n <label for=\"direction-toggle\" class=\"tw-relative tw-inline-block tw-w-9 tw-h-5\">\n <input type=\"checkbox\" id=\"direction-toggle\" class=\"tw-opacity-0 tw-w-0 tw-h-0\" [(ngModel)]=\"isRTL\"\n (change)=\"onDirectionToggle($event)\">\n <span\n class=\"tw-absolute tw-cursor-pointer tw-top-0 tw-left-0 tw-right-0 tw-bottom-0 tw-bg-gray-300 tw-rounded-full tw-transition-colors checked:tw-bg-blue-500 before:tw-absolute before:tw-content-[''] before:tw-h-4 before:tw-w-4 before:tw-left-0.5 before:tw-bottom-0.5 before:tw-bg-white before:tw-rounded-full before:tw-transition-transform checked:before:tw-translate-x-4\"></span>\n </label>\n <span class=\"tw-text-xs tw-text-gray-500\">RTL</span>\n </div>\n </div>\n </section>\n\n <!-- Theme Property Groups (Brand, Text, Background, Font Sizes, Line Heights) -->\n <section *ngFor=\"let group of themeGroups\" class=\"theme-section\">\n <h2 class=\"tw-text-md tw-font-semibold tw-mb-2 tw-text-gray-800\">{{ group.label }}</h2>\n <div class=\"tw-grid tw-grid-cols-2 tw-gap-2 tw-gap-x-4\">\n <div *ngFor=\"let item of group.items\"\n class=\"tw-flex tw-items-center tw-gap-2 tw-p-1 tw-rounded-lg tw-bg-gray-50\"\n [ngClass]=\"{'tw-flex-col tw-items-stretch': (group.label === 'Font Sizes' || group.label === 'Line Heights' || group.label === 'Layout Dimensions')}\">\n <!-- Font Sizes: label on top, input in middle, unit at bottom -->\n <ng-container *ngIf=\"group.label === 'Font Sizes'\">\n <label [for]=\"item.varName\" class=\"tw-text-sm tw-font-medium tw-text-gray-700 tw-text-left\">{{ item.label\n }}</label>\n <div class=\"tw-flex tw-items-start\">\n <input [id]=\"item.varName\" type=\"number\" step=\"0.001\" [min]=\"item.min ?? null\" [max]=\"item.max ?? null\"\n [(ngModel)]=\"item.value\" (input)=\"onTypographyChange($event, item)\"\n class=\"tw-w-18 tw-text-right tw-text-sm tw-border tw-border-gray-300 tw-rounded tw-px-2 tw-py-1 focus:tw-outline-none focus:tw-ring-2 focus:tw-ring-blue-500 focus:tw-border-transparent theme-input\">\n <span class=\"tw-text-xs tw-text-gray-400\">rem</span>\n </div>\n </ng-container>\n <!-- Line Heights: label on top, input and unit on same line -->\n <ng-container *ngIf=\"group.label === 'Line Heights'\">\n <label [for]=\"item.varName\" class=\"tw-text-sm tw-font-medium tw-text-gray-700 tw-text-left\">{{ item.label\n }}</label>\n <div class=\"tw-flex tw-items-start\">\n <input [id]=\"item.varName\" type=\"number\" step=\"0.1\" [min]=\"item.min ?? null\" [max]=\"item.max ?? null\"\n [(ngModel)]=\"item.value\" (input)=\"onTypographyChange($event, item)\"\n class=\"tw-w-18 tw-text-right tw-text-sm tw-border tw-border-gray-300 tw-rounded tw-px-2 tw-py-1 focus:tw-outline-none focus:tw-ring-2 focus:tw-ring-blue-500 focus:tw-border-transparent theme-input\">\n <span class=\"tw-text-xs tw-text-gray-400\">unitless</span>\n </div>\n </ng-container>\n <!-- Layout Dimensions: label on top, input in middle, px unit at bottom -->\n <ng-container *ngIf=\"group.label === 'Layout Dimensions'\">\n <label [for]=\"item.varName\" class=\"tw-text-sm tw-font-medium tw-text-gray-700 tw-text-left\">{{ item.label\n }}</label>\n <div class=\"tw-flex tw-items-start\">\n <input [id]=\"item.varName\" type=\"number\" step=\"1\" [min]=\"item.min ?? null\" [max]=\"item.max ?? null\"\n [(ngModel)]=\"item.value\" (input)=\"onLayoutChange($event, item)\"\n class=\"tw-w-18 tw-text-right tw-text-sm tw-border tw-border-gray-300 tw-rounded tw-px-2 tw-py-1 focus:tw-outline-none focus:tw-ring-2 focus:tw-ring-blue-500 focus:tw-border-transparent theme-input\">\n <span class=\"tw-text-xs tw-text-gray-400\">px</span>\n </div>\n </ng-container>\n <!-- Other groups: keep previous layout -->\n <ng-container *ngIf=\"group.label !== 'Font Sizes' && group.label !== 'Line Heights' && group.label !== 'Layout Dimensions'\">\n <!-- Color input for color variables -->\n <ng-container *ngIf=\"item.varName.includes('color')\">\n <input [id]=\"item.varName\" [attr.data-variable]=\"item.varName\" type=\"color\" [(ngModel)]=\"item.value\"\n (input)=\"onColorChange($event, item)\"\n class=\"tw-appearance-none tw-border-2 tw-border-gray-200 tw-rounded tw-w-8 tw-h-8 tw-p-0 tw-bg-none tw-shadow-none tw-cursor-pointer tw-transition-colors focus:tw-border-blue-500 color-input\">\n </ng-container>\n <!-- Number input for line heights -->\n <ng-container\n *ngIf=\"!item.varName.includes('color') && item.type === 'number' && group.label !== 'Font Sizes'\">\n <input [id]=\"item.varName\" type=\"number\" [step]=\"item.varName.includes('line-height') ? 0.1 : 0.001\"\n [min]=\"item.min ?? null\" [max]=\"item.max ?? null\" [(ngModel)]=\"item.value\"\n (input)=\"onTypographyChange($event, item)\"\n class=\"tw-w-16 tw-text-right tw-text-sm tw-border tw-border-gray-300 tw-rounded tw-px-2 tw-py-1 focus:tw-outline-none focus:tw-ring-2 focus:tw-ring-blue-500 focus:tw-border-transparent theme-input\">\n <span class=\"tw-text-xs tw-text-gray-400\" *ngIf=\"!item.varName.includes('line-height')\">rem</span>\n </ng-container>\n <!-- Text input fallback (if needed) -->\n <ng-container *ngIf=\"!item.varName.includes('color') && item.type !== 'number'\">\n <input [id]=\"item.varName\" type=\"text\" [(ngModel)]=\"item.value\" (input)=\"onTypographyChange($event, item)\"\n class=\"tw-w-24 tw-text-sm tw-border tw-border-gray-300 tw-rounded tw-px-2 tw-py-1 focus:tw-outline-none focus:tw-ring-2 focus:tw-ring-blue-500 focus:tw-border-transparent theme-input\">\n </ng-container>\n <div class=\"tw-flex tw-flex-col tw-gap-0.5\">\n <label [for]=\"item.varName\" class=\"tw-text-sm tw-font-medium tw-text-gray-700\">{{ item.label }}</label>\n <span class=\"tw-text-xs tw-text-gray-500 tw-font-mono\">{{ item.value }}</span>\n </div>\n </ng-container>\n </div>\n </div>\n </section>\n </div>\n\n <!-- STICKY ACTION BUTTONS SECTION -->\n <div class=\"tw-bg-white tw-sticky tw-bottom-0 tw-border-t tw-border-gray-200 tw-z-10 tw-flex-shrink-0 tw-p-3 tw-shadow-lg sticky-action-buttons\">\n <div class=\"tw-flex tw-gap-2 tw-justify-end\">\n <button cideEleButton \n variant=\"outline\" \n size=\"sm\" \n (btnClick)=\"onReset()\" \n [disabled]=\"!hasChangesFromOriginal()\"\n class=\"tw-transition-all tw-duration-200 hover:tw-scale-105 action-button\">\n Reset to Original\n </button>\n <button cideEleButton \n variant=\"primary\" \n size=\"sm\" \n (btnClick)=\"onSave()\" \n [disabled]=\"!hasUnsavedChanges()\"\n class=\"tw-transition-all tw-duration-200 hover:tw-scale-105 action-button\">\n Save Changes\n </button>\n </div>\n </div>\n</div>", styles: [".theme-scroll-container{scroll-behavior:smooth;-webkit-overflow-scrolling:touch}.theme-scroll-container::-webkit-scrollbar{width:6px}.theme-scroll-container::-webkit-scrollbar-track{background:#f8fafc;border-radius:3px}.theme-scroll-container::-webkit-scrollbar-thumb{background:#cbd5e1;border-radius:3px;transition:background-color .2s ease}.theme-scroll-container::-webkit-scrollbar-thumb:hover{background:#94a3b8}.sticky-action-buttons{-webkit-backdrop-filter:blur(8px);backdrop-filter:blur(8px);background-color:#fffffff2;border-top:1px solid #e2e8f0;box-shadow:0 -4px 6px -1px #0000001a}.action-button{transition:all .2s ease-in-out}.action-button:hover:not(:disabled){transform:translateY(-1px);box-shadow:0 4px 8px #00000026}.action-button:active:not(:disabled){transform:translateY(0)}.action-button:disabled{opacity:.5;cursor:not-allowed;transform:none!important;box-shadow:none!important}.theme-input:focus{transform:scale(1.02);transition:transform .2s ease-in-out}.color-input{transition:all .2s ease-in-out}.color-input:hover{transform:scale(1.1);box-shadow:0 4px 8px #0003}.theme-section{transition:all .3s ease-in-out}.theme-section:hover{background-color:#f8fafc;border-radius:8px;padding:8px;margin:-8px}@media (max-width: 640px){.sticky-action-buttons{padding:12px}.action-button{font-size:14px;padding:8px 12px}}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i2.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i2.NumberValueAccessor, selector: "input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]" }, { kind: "directive", type: i2.CheckboxControlValueAccessor, selector: "input[type=checkbox][formControlName],input[type=checkbox][formControl],input[type=checkbox][ngModel]" }, { kind: "directive", type: i2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2.MinValidator, selector: "input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]", inputs: ["min"] }, { kind: "directive", type: i2.MaxValidator, selector: "input[type=number][max][formControlName],input[type=number][max][formControl],input[type=number][max][ngModel]", inputs: ["max"] }, { kind: "directive", type: i2.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "directive", type: NgFor, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "component", type: CideSelectComponent, selector: "cide-ele-select", inputs: ["label", "labelHide", "placeholder", "helperText", "errorText", "required", "disabled", "id", "ngModel", "size", "fill", "labelPlacement", "labelDir", "leadingIcon", "trailingIcon", "clearInput", "options", "multiple", "searchable", "showSearchInput", "loading"], outputs: ["ngModelChange", "change", "searchChange"] }, { kind: "component", type: CideEleButtonComponent, selector: "button[cideEleButton], a[cideEleButton]", inputs: ["label", "variant", "size", "type", "shape", "elevation", "disabled", "id", "loading", "fullWidth", "leftIcon", "rightIcon", "customClass", "tooltip", "ariaLabel", "testId", "routerLink", "routerExtras", "preventDoubleClick", "animated"], outputs: ["btnClick", "doubleClick"] }] }); }
433
+ }
434
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.7", ngImport: i0, type: CideLytDrawerThemeComponent, decorators: [{
435
+ type: Component,
436
+ args: [{ selector: 'cide-lyt-drawer-theme', standalone: true, imports: [FormsModule, NgFor, NgIf, NgClass, CideSelectComponent, CideEleButtonComponent], template: "<div class=\"tw-relative tw-h-full tw-bg-white tw-overflow-hidden tw-flex tw-flex-col\">\n <!-- STICKY HEADER SECTION -->\n <div class=\"tw-bg-white tw-sticky tw-top-0 tw-border-b tw-border-gray-200 tw-z-10 tw-flex-shrink-0\">\n <!-- DYNAMIC HEADING -->\n <div class=\"tw-flex tw-justify-between tw-items-center tw-p-2 tw-bg-white tw-border-b tw-border-gray-200\">\n <h6 class=\"tw-font-semibold tw-text-gray-800\">Preset Theme</h6>\n </div>\n </div>\n\n <!-- SCROLLABLE CONTENT AREA -->\n <div class=\"tw-flex-1 tw-overflow-y-auto tw-scroll-smooth tw-p-2 tw-flex tw-flex-col tw-gap-5 tw-text-sm tw-pb-3 theme-scroll-container\">\n <!-- Preset Theme -->\n <section>\n <cide-ele-select id=\"theme-selector\" [(ngModel)]=\"selectedTheme\" (change)=\"onThemeChange($event)\"\n [options]=\"presetThemes\" [size]=\"'sm'\"></cide-ele-select>\n </section>\n\n <!-- Direction Toggle -->\n <section>\n <div class=\"tw-flex tw-justify-between tw-items-center tw-mb-2\">\n <h2 class=\"tw-text-md tw-font-semibold tw-text-gray-800\">Text Direction</h2>\n <div class=\"tw-flex tw-items-center tw-gap-1\">\n <span class=\"tw-text-xs tw-text-gray-500\">LTR</span>\n <label for=\"direction-toggle\" class=\"tw-relative tw-inline-block tw-w-9 tw-h-5\">\n <input type=\"checkbox\" id=\"direction-toggle\" class=\"tw-opacity-0 tw-w-0 tw-h-0\" [(ngModel)]=\"isRTL\"\n (change)=\"onDirectionToggle($event)\">\n <span\n class=\"tw-absolute tw-cursor-pointer tw-top-0 tw-left-0 tw-right-0 tw-bottom-0 tw-bg-gray-300 tw-rounded-full tw-transition-colors checked:tw-bg-blue-500 before:tw-absolute before:tw-content-[''] before:tw-h-4 before:tw-w-4 before:tw-left-0.5 before:tw-bottom-0.5 before:tw-bg-white before:tw-rounded-full before:tw-transition-transform checked:before:tw-translate-x-4\"></span>\n </label>\n <span class=\"tw-text-xs tw-text-gray-500\">RTL</span>\n </div>\n </div>\n </section>\n\n <!-- Theme Property Groups (Brand, Text, Background, Font Sizes, Line Heights) -->\n <section *ngFor=\"let group of themeGroups\" class=\"theme-section\">\n <h2 class=\"tw-text-md tw-font-semibold tw-mb-2 tw-text-gray-800\">{{ group.label }}</h2>\n <div class=\"tw-grid tw-grid-cols-2 tw-gap-2 tw-gap-x-4\">\n <div *ngFor=\"let item of group.items\"\n class=\"tw-flex tw-items-center tw-gap-2 tw-p-1 tw-rounded-lg tw-bg-gray-50\"\n [ngClass]=\"{'tw-flex-col tw-items-stretch': (group.label === 'Font Sizes' || group.label === 'Line Heights' || group.label === 'Layout Dimensions')}\">\n <!-- Font Sizes: label on top, input in middle, unit at bottom -->\n <ng-container *ngIf=\"group.label === 'Font Sizes'\">\n <label [for]=\"item.varName\" class=\"tw-text-sm tw-font-medium tw-text-gray-700 tw-text-left\">{{ item.label\n }}</label>\n <div class=\"tw-flex tw-items-start\">\n <input [id]=\"item.varName\" type=\"number\" step=\"0.001\" [min]=\"item.min ?? null\" [max]=\"item.max ?? null\"\n [(ngModel)]=\"item.value\" (input)=\"onTypographyChange($event, item)\"\n class=\"tw-w-18 tw-text-right tw-text-sm tw-border tw-border-gray-300 tw-rounded tw-px-2 tw-py-1 focus:tw-outline-none focus:tw-ring-2 focus:tw-ring-blue-500 focus:tw-border-transparent theme-input\">\n <span class=\"tw-text-xs tw-text-gray-400\">rem</span>\n </div>\n </ng-container>\n <!-- Line Heights: label on top, input and unit on same line -->\n <ng-container *ngIf=\"group.label === 'Line Heights'\">\n <label [for]=\"item.varName\" class=\"tw-text-sm tw-font-medium tw-text-gray-700 tw-text-left\">{{ item.label\n }}</label>\n <div class=\"tw-flex tw-items-start\">\n <input [id]=\"item.varName\" type=\"number\" step=\"0.1\" [min]=\"item.min ?? null\" [max]=\"item.max ?? null\"\n [(ngModel)]=\"item.value\" (input)=\"onTypographyChange($event, item)\"\n class=\"tw-w-18 tw-text-right tw-text-sm tw-border tw-border-gray-300 tw-rounded tw-px-2 tw-py-1 focus:tw-outline-none focus:tw-ring-2 focus:tw-ring-blue-500 focus:tw-border-transparent theme-input\">\n <span class=\"tw-text-xs tw-text-gray-400\">unitless</span>\n </div>\n </ng-container>\n <!-- Layout Dimensions: label on top, input in middle, px unit at bottom -->\n <ng-container *ngIf=\"group.label === 'Layout Dimensions'\">\n <label [for]=\"item.varName\" class=\"tw-text-sm tw-font-medium tw-text-gray-700 tw-text-left\">{{ item.label\n }}</label>\n <div class=\"tw-flex tw-items-start\">\n <input [id]=\"item.varName\" type=\"number\" step=\"1\" [min]=\"item.min ?? null\" [max]=\"item.max ?? null\"\n [(ngModel)]=\"item.value\" (input)=\"onLayoutChange($event, item)\"\n class=\"tw-w-18 tw-text-right tw-text-sm tw-border tw-border-gray-300 tw-rounded tw-px-2 tw-py-1 focus:tw-outline-none focus:tw-ring-2 focus:tw-ring-blue-500 focus:tw-border-transparent theme-input\">\n <span class=\"tw-text-xs tw-text-gray-400\">px</span>\n </div>\n </ng-container>\n <!-- Other groups: keep previous layout -->\n <ng-container *ngIf=\"group.label !== 'Font Sizes' && group.label !== 'Line Heights' && group.label !== 'Layout Dimensions'\">\n <!-- Color input for color variables -->\n <ng-container *ngIf=\"item.varName.includes('color')\">\n <input [id]=\"item.varName\" [attr.data-variable]=\"item.varName\" type=\"color\" [(ngModel)]=\"item.value\"\n (input)=\"onColorChange($event, item)\"\n class=\"tw-appearance-none tw-border-2 tw-border-gray-200 tw-rounded tw-w-8 tw-h-8 tw-p-0 tw-bg-none tw-shadow-none tw-cursor-pointer tw-transition-colors focus:tw-border-blue-500 color-input\">\n </ng-container>\n <!-- Number input for line heights -->\n <ng-container\n *ngIf=\"!item.varName.includes('color') && item.type === 'number' && group.label !== 'Font Sizes'\">\n <input [id]=\"item.varName\" type=\"number\" [step]=\"item.varName.includes('line-height') ? 0.1 : 0.001\"\n [min]=\"item.min ?? null\" [max]=\"item.max ?? null\" [(ngModel)]=\"item.value\"\n (input)=\"onTypographyChange($event, item)\"\n class=\"tw-w-16 tw-text-right tw-text-sm tw-border tw-border-gray-300 tw-rounded tw-px-2 tw-py-1 focus:tw-outline-none focus:tw-ring-2 focus:tw-ring-blue-500 focus:tw-border-transparent theme-input\">\n <span class=\"tw-text-xs tw-text-gray-400\" *ngIf=\"!item.varName.includes('line-height')\">rem</span>\n </ng-container>\n <!-- Text input fallback (if needed) -->\n <ng-container *ngIf=\"!item.varName.includes('color') && item.type !== 'number'\">\n <input [id]=\"item.varName\" type=\"text\" [(ngModel)]=\"item.value\" (input)=\"onTypographyChange($event, item)\"\n class=\"tw-w-24 tw-text-sm tw-border tw-border-gray-300 tw-rounded tw-px-2 tw-py-1 focus:tw-outline-none focus:tw-ring-2 focus:tw-ring-blue-500 focus:tw-border-transparent theme-input\">\n </ng-container>\n <div class=\"tw-flex tw-flex-col tw-gap-0.5\">\n <label [for]=\"item.varName\" class=\"tw-text-sm tw-font-medium tw-text-gray-700\">{{ item.label }}</label>\n <span class=\"tw-text-xs tw-text-gray-500 tw-font-mono\">{{ item.value }}</span>\n </div>\n </ng-container>\n </div>\n </div>\n </section>\n </div>\n\n <!-- STICKY ACTION BUTTONS SECTION -->\n <div class=\"tw-bg-white tw-sticky tw-bottom-0 tw-border-t tw-border-gray-200 tw-z-10 tw-flex-shrink-0 tw-p-3 tw-shadow-lg sticky-action-buttons\">\n <div class=\"tw-flex tw-gap-2 tw-justify-end\">\n <button cideEleButton \n variant=\"outline\" \n size=\"sm\" \n (btnClick)=\"onReset()\" \n [disabled]=\"!hasChangesFromOriginal()\"\n class=\"tw-transition-all tw-duration-200 hover:tw-scale-105 action-button\">\n Reset to Original\n </button>\n <button cideEleButton \n variant=\"primary\" \n size=\"sm\" \n (btnClick)=\"onSave()\" \n [disabled]=\"!hasUnsavedChanges()\"\n class=\"tw-transition-all tw-duration-200 hover:tw-scale-105 action-button\">\n Save Changes\n </button>\n </div>\n </div>\n</div>", styles: [".theme-scroll-container{scroll-behavior:smooth;-webkit-overflow-scrolling:touch}.theme-scroll-container::-webkit-scrollbar{width:6px}.theme-scroll-container::-webkit-scrollbar-track{background:#f8fafc;border-radius:3px}.theme-scroll-container::-webkit-scrollbar-thumb{background:#cbd5e1;border-radius:3px;transition:background-color .2s ease}.theme-scroll-container::-webkit-scrollbar-thumb:hover{background:#94a3b8}.sticky-action-buttons{-webkit-backdrop-filter:blur(8px);backdrop-filter:blur(8px);background-color:#fffffff2;border-top:1px solid #e2e8f0;box-shadow:0 -4px 6px -1px #0000001a}.action-button{transition:all .2s ease-in-out}.action-button:hover:not(:disabled){transform:translateY(-1px);box-shadow:0 4px 8px #00000026}.action-button:active:not(:disabled){transform:translateY(0)}.action-button:disabled{opacity:.5;cursor:not-allowed;transform:none!important;box-shadow:none!important}.theme-input:focus{transform:scale(1.02);transition:transform .2s ease-in-out}.color-input{transition:all .2s ease-in-out}.color-input:hover{transform:scale(1.1);box-shadow:0 4px 8px #0003}.theme-section{transition:all .3s ease-in-out}.theme-section:hover{background-color:#f8fafc;border-radius:8px;padding:8px;margin:-8px}@media (max-width: 640px){.sticky-action-buttons{padding:12px}.action-button{font-size:14px;padding:8px 12px}}\n"] }]
437
+ }], ctorParameters: () => [{ type: CideLytThemeService }, { type: undefined, decorators: [{
438
+ type: Inject,
439
+ args: [PLATFORM_ID]
440
+ }] }] });
441
+
442
+ export { CideLytDrawerThemeComponent };
443
+ //# sourceMappingURL=cloud-ide-layout-drawer-theme.component-xd8IG3WP.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cloud-ide-layout-drawer-theme.component-xd8IG3WP.mjs","sources":["../../../projects/cloud-ide-layout/src/lib/services/theme/theme.service.ts","../../../projects/cloud-ide-layout/src/lib/layout/sidedrawer/drawer-theme/drawer-theme.component.ts","../../../projects/cloud-ide-layout/src/lib/layout/sidedrawer/drawer-theme/drawer-theme.component.html"],"sourcesContent":["\nimport { Injectable, PLATFORM_ID, InjectionToken, signal, inject } from '@angular/core';\nimport { HttpClient } from '@angular/common/http';\nimport { tap } from 'rxjs/operators';\nimport { Observable, of } from 'rxjs';\nimport { cidePath, designConfigRoutesUrl, hostManagerRoutesUrl, SystemThemeControllerRespoonse, SystemThemesListControllerRespoonse, IEnvironmentConfig, SystemThemeUserPreferencesControllerRespoonse, MSystemThemeUserPreferencesRequest, SystemThemeControllerRespoonseData } from 'cloud-ide-lms-model';\nimport { isPlatformBrowser } from '@angular/common';\n\n// Define an InjectionToken for the environment configuration\n// This is needed to inject environment variables into services provided in 'root'\nexport const ENVIRONMENT_CONFIG = new InjectionToken<IEnvironmentConfig>('ENVIRONMENT_CONFIG');\n\n// Define an interface for your theme for type safety\nexport interface Theme {\n [key: string]: string; // Allows any string key, e.g., 'color-text-body'\n}\n\n/**\n * Utility function to convert database format keys to CSS format and handle units\n * @param key - The database format key (e.g., 'font_size_xxxl')\n * @param value - The value to be set\n * @returns Object with cssVarName and processed value\n */\nexport function processThemeVariable(key: string, value: string): { cssVarName: string; processedValue: string } {\n // 1. Convert the key from the DB format to the CSS format.\n const cssVarName = `${key.replace(/_/g, '-')}`;\n\n // 2. Append the font_size and line_height value to rem\n let processedValue = value;\n if (cssVarName.includes('font-size') || cssVarName.includes('line-height')) {\n processedValue = parseFloat(value) + 'rem';\n }\n\n return { cssVarName, processedValue: processedValue };\n}\n\n/**\n * Sets a single CSS variable on the document root element\n * @param key - The database format key (e.g., 'font_size_xxxl')\n * @param value - The value to be set\n * @param platformId - Platform ID for browser check\n */\nexport function setCSSVariable(key: string, value: string, platformId: object): void {\n if (isPlatformBrowser(platformId)) {\n const { cssVarName, processedValue } = processThemeVariable(key, value);\n const root = document.documentElement;\n root.style.setProperty(cssVarName, processedValue);\n }\n}\n\n@Injectable({\n providedIn: 'root'\n})\nexport class CideLytThemeService {\n // Modern Angular signals for reactive state management\n private selectedThemeSignal = signal<string>(\"\");\n public selectedTheme = this.selectedThemeSignal.asReadonly();\n \n // Modern dependency injection\n private http = inject(HttpClient);\n private platformId = inject(PLATFORM_ID);\n private environment = inject(ENVIRONMENT_CONFIG);\n\n /**\n * Fetches the theme from the API and applies it to the document.\n * This method is intended to be called when the theme should actually be applied.\n */\n public fetchAndApplyTheme(): Observable<SystemThemeControllerRespoonse> {\n console.log('Fetching and applying theme via CideLytThemeService...');\n return this.loadTheme(); // Use the existing loadTheme logic\n }\n\n /**\n * Fetches the list of system themes from the API.\n */\n public fetchSystemThemesList(): Observable<SystemThemesListControllerRespoonse> {\n return this.http.get<SystemThemesListControllerRespoonse>(\n cidePath.join([\n hostManagerRoutesUrl.cideSuiteHost,\n designConfigRoutesUrl?.module,\n designConfigRoutesUrl?.getSystemThemesList\n ]));\n }\n\n /**\n * Internal method to fetch the theme from the API and apply it.\n */\n loadTheme() {\n return this.http.post<SystemThemeControllerRespoonse>(cidePath.join([hostManagerRoutesUrl.cideSuiteHost, designConfigRoutesUrl?.module, designConfigRoutesUrl?.getSystemTheme]), { syupth_user_id_user: \"659a7ea0a1f0e08246661766\" }).pipe(\n tap(theme => {\n console.log(\"Applying theme:\", theme);\n this.applyTheme(theme?.data as SystemThemeControllerRespoonseData);\n })\n );\n }\n\n /**\n * Sets the CSS variables on the root element.\n * @param theme - An object where keys are CSS variable names (e.g., '--color-text-body')\n * and values are the color strings (e.g., '#ffffff').\n */\n private applyTheme(theme: SystemThemeControllerRespoonseData): void {\n console.log(\"Applying theme:\", theme);\n let merged = {};\n if (theme?.core_system_themes?.syth_properties) {\n merged = { ...merged, ...theme.core_system_themes.syth_properties };\n this.selectedThemeSignal.set(theme.core_system_themes._id as string);\n }\n if (theme?.core_system_organization_themes?.syoth_overrides) {\n merged = { ...merged, ...theme.core_system_organization_themes.syoth_overrides };\n }\n if (theme?.core_system_theme_user_preferences?.syupth_overrides) {\n merged = { ...merged, ...theme.core_system_theme_user_preferences.syupth_overrides };\n }\n console.log(\"Merged theme:\", merged);\n // Check if the code is running in a browser environment.\n if (isPlatformBrowser(this.platformId)) {\n const root = document.documentElement;\n\n for (const [key, value] of Object.entries(merged)) {\n const { cssVarName, processedValue } = processThemeVariable(key, value as string);\n // Set the CSS custom property on the root element.\n root.style.setProperty(cssVarName, processedValue);\n }\n }\n }\n\n /**\n * Saves the system theme user preferences.\n * @param themeVars - The theme variables to save.\n * @returns An observable of the system theme user preferences.\n */\n saveSystemThemeUserPreferences(themeVars: MSystemThemeUserPreferencesRequest): Observable<SystemThemeUserPreferencesControllerRespoonse> {\n return this.http.post<SystemThemeUserPreferencesControllerRespoonse>(cidePath.join([hostManagerRoutesUrl.cideSuiteHost, designConfigRoutesUrl?.module, designConfigRoutesUrl?.systemThemeUserPreferences]), themeVars);\n }\n\n /**\n * Updates a single CSS variable using the utility function\n * @param key - The database format key (e.g., 'font_size_xxxl')\n * @param value - The value to be set\n */\n updateCSSVariable(key: string, value: string): void {\n setCSSVariable(key, value, this.platformId);\n }\n}\n\n/**\n * Factory function for APP_INITIALIZER.\n * This function is used in your app.config.ts.\n * It conditionally triggers theme loading based on the environment setting.\n */\nexport function themeFactory(themeService: CideLytThemeService, environmentConfig: IEnvironmentConfig): () => Observable<SystemThemeControllerRespoonse | undefined> {\n return () => {\n if (!environmentConfig.applyThemeOnLogin) {\n // If theme should be applied on app initialize, fetch and apply it.\n console.log('APP_INITIALIZER: Applying theme...');\n return themeService.fetchAndApplyTheme();\n } else {\n // If theme should be applied on login, APP_INITIALIZER does nothing for the theme.\n // We return an observable that immediately completes.\n console.log('APP_INITIALIZER: Theme application deferred to after login (per environment config).');\n return of(undefined); // Return an observable that completes immediately\n }\n };\n}","import { NgFor, NgIf } from '@angular/common';\nimport { NgClass } from '@angular/common';\nimport { Component, OnInit, PLATFORM_ID, Inject, inject } from '@angular/core';\nimport { FormsModule } from '@angular/forms';\nimport { CideSelectComponent, SelectOption, CideEleButtonComponent } from 'cloud-ide-element';\nimport { CideLytThemeService, Theme, setCSSVariable } from '../../../services/theme/theme.service';\nimport type { MSystemThemeUserPreferencesRequest, SystemThemesListControllerRespoonse, SystemThemeUserPreferencesControllerRespoonse } from 'cloud-ide-lms-model';\nimport type { SystemThemeControllerRespoonse } from 'cloud-ide-lms-model';\nimport type { ICoreSyth, ICoreSyoth, ICoreSyupth } from 'cloud-ide-lms-model';\nimport { isEqual, cloneDeep } from 'lodash';\nimport _ from 'lodash';\nimport { AppStateHelperService } from '../../../services/app-state';\n\ninterface ThemeColor {\n label: string;\n varName: string;\n value: string;\n}\n\ninterface TypographySetting {\n label: string;\n varName: string;\n value: string;\n type: 'number' | 'text';\n min?: number;\n max?: number;\n}\n\ntype ThemeGroup = {\n label: string;\n items: Array<{\n label: string;\n varName: string;\n value: string;\n type: 'number' | 'text';\n min?: number;\n max?: number;\n }>;\n};\n\n@Component({\n selector: 'cide-lyt-drawer-theme',\n standalone: true,\n imports: [FormsModule, NgFor, NgIf, NgClass, CideSelectComponent, CideEleButtonComponent],\n templateUrl: './drawer-theme.component.html',\n styleUrl: './drawer-theme.component.scss'\n})\nexport class CideLytDrawerThemeComponent implements OnInit {\n private readonly appState = inject(AppStateHelperService);\n // Preset themes\n presetThemes: { value: string, label: string, theme: ICoreSyth }[] = [];\n selectedTheme = '';\n isLoadingThemes = false;\n themeLoadError = '';\n mergedTheme: { [key: string]: string } = {};\n isRTL = false;\n originalThemeGroupValues: ThemeGroup[] = [];\n originalApiThemeValues: { [key: string]: string } = {}; // Store original API values\n\n themeGroups: ThemeGroup[] = [\n {\n label: 'Brand Colors',\n items: [\n { label: 'Primary', varName: '--cide-theme-color-brand-primary', value: '#4f46e5', type: 'text' },\n { label: 'Accent', varName: '--cide-theme-color-brand-accent', value: '#4338ca', type: 'text' },\n { label: 'Separator', varName: '--cide-theme-color-brand-separator', value: '#e5e7eb', type: 'text' }\n ]\n },\n {\n label: 'Text Colors',\n items: [\n { label: 'Body Text', varName: '--cide-theme-color-text-body', value: '#374151', type: 'text' },\n { label: 'Heading Text', varName: '--cide-theme-color-text-heading', value: '#111827', type: 'text' },\n { label: 'Link Text', varName: '--cide-theme-color-text-link', value: '#3b82f6', type: 'text' },\n { label: 'Muted Text', varName: '--cide-theme-color-text-muted', value: '#6b7280', type: 'text' }\n ]\n },\n {\n label: 'Background Colors',\n items: [\n { label: 'Body Background', varName: '--cide-theme-color-background-body', value: '#ffffff', type: 'text' }\n ]\n },\n {\n label: 'Layout Dimensions',\n items: [\n { label: 'Stack Wrapper Width', varName: '--cide-lyt-stack-wrapper-width', value: '60', type: 'number', min: 20, max: 120 }\n ]\n },\n {\n label: 'Font Sizes',\n items: [\n { label: 'XXXL Font Size', varName: '--cide-theme-font-size-xxxl', value: '3.052', type: 'number', min: 1, max: 10 },\n { label: 'XXL Font Size', varName: '--cide-theme-font-size-xxl', value: '2.441', type: 'number', min: 1, max: 10 },\n { label: 'XL Font Size', varName: '--cide-theme-font-size-xl', value: '1.953', type: 'number', min: 1, max: 10 },\n { label: 'LG Font Size', varName: '--cide-theme-font-size-lg', value: '1.563', type: 'number', min: 1, max: 10 },\n { label: 'MD Font Size', varName: '--cide-theme-font-size-md', value: '1.25', type: 'number', min: 1, max: 10 },\n { label: 'Paragraph Font Size', varName: '--cide-theme-font-size-p', value: '1', type: 'number', min: 0.5, max: 5 },\n { label: 'SM Font Size', varName: '--cide-theme-font-size-sm', value: '0.9', type: 'number', min: 0.5, max: 5 },\n { label: 'XS Font Size', varName: '--cide-theme-font-size-xs', value: '0.8', type: 'number', min: 0.5, max: 5 }\n ]\n },\n {\n label: 'Line Heights',\n items: [\n { label: 'Body Line Height', varName: '--cide-theme-line-height-body', value: '1.6', type: 'number', min: 1, max: 3 },\n { label: 'Heading Line Height', varName: '--cide-theme-line-height-heading', value: '1.2', type: 'number', min: 1, max: 3 }\n ]\n }\n ];\n\n constructor(\n private themeService: CideLytThemeService,\n @Inject(PLATFORM_ID) private platformId: object\n ) { }\n\n ngOnInit(): void {\n // Modern Angular v20 pattern: Use Signals directly\n this.selectedTheme = this.themeService.selectedTheme();\n\n // fetch the system themes list\n this.isLoadingThemes = true;\n this.themeService.fetchSystemThemesList().subscribe({\n next: (res: SystemThemesListControllerRespoonse) => {\n const themes: ICoreSyth[] = res?.data?.core_system_themes || [];\n this.presetThemes = themes.map((theme: ICoreSyth) => ({\n value: theme._id || '',\n label: theme.syth_theme_name || theme.syth_theme_id || '',\n theme\n }));\n this.isLoadingThemes = false;\n // If user has no theme set, select and apply the default theme\n if (!this.selectedTheme) {\n const defaultTheme = this.presetThemes.find(t => t.theme.syth_is_default);\n if (defaultTheme) {\n this.selectedTheme = defaultTheme.value;\n // Apply the default theme as CSS variables\n if (defaultTheme.theme.syth_properties) {\n Object.entries(defaultTheme.theme.syth_properties).forEach(([varName, value]) => {\n this.updateVar(varName, value as string);\n });\n }\n }\n }\n },\n error: () => {\n this.themeLoadError = 'Failed to load themes';\n this.isLoadingThemes = false;\n }\n });\n this.loadAndApplyUserTheme();\n }\n\n loadAndApplyUserTheme(): void {\n this.themeService.loadTheme().subscribe({\n next: (res: SystemThemeControllerRespoonse) => {\n const base: ICoreSyth | undefined = res?.data?.core_system_themes;\n const org: ICoreSyoth | undefined = res?.data?.core_system_organization_themes;\n const user: ICoreSyupth | undefined = res?.data?.core_system_theme_user_preferences;\n // Start with base theme properties\n let merged = { ...(base?.syth_properties || {}) };\n // Override with org overrides\n if (org?.syoth_overrides) {\n merged = { ...merged, ...org.syoth_overrides };\n }\n // Override with user overrides\n if (user?.syupth_overrides) {\n merged = { ...merged, ...user.syupth_overrides };\n }\n this.mergedTheme = merged;\n\n // Store original API values for reset functionality\n this.originalApiThemeValues = { ...merged };\n\n // Apply merged theme as CSS variables\n Object.entries(this.mergedTheme).forEach(([varName, value]) => {\n this.updateVar(varName, value as string);\n });\n\n for (const group of this.themeGroups) {\n for (const item of group.items) {\n const key = item.varName.replace(/-/g, '_');\n item.value = merged[item.varName] || merged[key] || item.value;\n\n if (key.includes('font_size') || key.includes('line_height')) {\n item.value = parseFloat(item.value) as unknown as string;\n }\n }\n }\n // Store a deep copy of the current values for reset\n this.originalThemeGroupValues = cloneDeep(this.themeGroups);\n },\n error: () => {\n // handle error if needed\n }\n });\n }\n\n // Update CSS variable in real time\n updateVar(varName: string, value: string) {\n // You can use either the utility function directly or the service method\n setCSSVariable(varName, value, this.platformId);\n // Alternative: this.themeService.updateCSSVariable(varName, value);\n }\n\n onThemeChange(event: SelectOption) {\n this.selectedTheme = event.value as string;\n const selected = this.presetThemes.find(t => t.value === this.selectedTheme);\n if (selected && selected.theme && selected.theme.syth_properties) {\n // here we will check the theme selected by organization is same if yes then overide also for user preferences\n if (this.themeService.selectedTheme() === selected.theme._id) {\n this.loadAndApplyUserTheme();\n } else {\n // Store original API values for the selected theme\n this.originalApiThemeValues = _.cloneDeep(selected.theme.syth_properties);\n\n // Update all group values from the selected theme\n for (const group of this.themeGroups) {\n for (const item of group.items) {\n const key = item.varName.replace(/-/g, '_');\n item.value = selected.theme.syth_properties[item.varName] ||\n selected.theme.syth_properties[key] ||\n item.value;\n\n this.updateVar(item.varName, item.value);\n\n if (key.includes('font_size') || key.includes('line_height')) {\n item.value = parseFloat(item.value) as unknown as string;\n }\n }\n }\n // Store a deep copy of the current values for reset\n this.originalThemeGroupValues = cloneDeep(this.themeGroups);\n }\n }\n }\n\n onReset() {\n // Restore all values from the original API values\n for (const group of this.themeGroups) {\n for (const item of group.items) {\n const key = item.varName.replace(/-/g, '_');\n // Get the original API value\n const originalValue = this.originalApiThemeValues[item.varName] ||\n this.originalApiThemeValues[key] ||\n item.value;\n\n // Update the item value\n item.value = originalValue;\n\n // Apply the CSS variable\n this.updateVar(item.varName, item.value);\n\n if (key.includes('font_size') || key.includes('line_height')) {\n item.value = parseFloat(item.value) as unknown as string;\n }\n }\n }\n\n // Update the originalThemeGroupValues to reflect the reset state\n this.originalThemeGroupValues = cloneDeep(this.themeGroups);\n }\n\n onSave() {\n // Collect all current values\n const themeVars: Theme = {\n\n };\n for (const group of this.themeGroups) {\n for (const item of group.items) {\n themeVars[item.varName?.replaceAll('-', '_')] = item.value;\n }\n }\n\n const systemThemePreferences: MSystemThemeUserPreferencesRequest = {\n syupth_overrides: {\n ...themeVars\n },\n syupth_system_theme_id_syth: this.selectedTheme, // LATER: need to upadate LATER\n syupth_user_id_user: this.appState.currentUser()?._id || '', // LATER: need to get user id from user\n syupth_entity_id_syen: this.appState.getActiveEntityId() || '', // LATER: need to get entity id from user\n syth_theme_id: \"\" // need to upadate LATER\n };\n\n // TODO: Send themeVars to backend or emit event by designConfigRoutesUrl?.systemThemeUserPreferences\n this.themeService.saveSystemThemeUserPreferences(systemThemePreferences).subscribe({\n next: (res: SystemThemeUserPreferencesControllerRespoonse) => {\n console.log('Theme saved:', res);\n // Modern Angular v20 pattern: Update Signal through service method\n // Note: The theme service should provide a method to update the selected theme\n // For now, we'll just log the change since the service doesn't expose a setter\n console.log('Theme selected:', this.selectedTheme);\n },\n error: (error) => {\n console.error('Error saving theme:', error);\n }\n });\n }\n\n hasUnsavedChanges(): boolean {\n // chec selected theme is different\n if (this.themeService.selectedTheme() !== this.selectedTheme) {\n return true;\n }\n // check the theme groups are different\n return !isEqual(this.themeGroups, this.originalThemeGroupValues);\n }\n\n /**\n * Check if current values differ from the original API values\n * This is useful for determining if reset should be enabled\n */\n hasChangesFromOriginal(): boolean {\n for (const group of this.themeGroups) {\n for (const item of group.items) {\n const key = item.varName.replace(/-/g, '_');\n const originalValue = this.originalApiThemeValues[item.varName] ||\n this.originalApiThemeValues[key];\n\n if (originalValue !== undefined && item.value !== originalValue) {\n return true;\n }\n }\n }\n return false;\n }\n\n onColorChange(event: Event, color: ThemeColor) {\n const input = event.target as HTMLInputElement;\n color.value = input.value;\n this.updateVar(color.varName, color.value);\n }\n\n onTypographyChange(event: Event, setting: TypographySetting) {\n const input = event.target as HTMLInputElement;\n setting.value = input.value;\n this.updateVar(setting.varName, setting.type === 'number' ? setting.value : setting.value);\n }\n\n onLayoutChange(event: Event, setting: TypographySetting) {\n const input = event.target as HTMLInputElement;\n setting.value = input.value;\n // For layout dimensions, append 'px' unit to the value\n this.updateVar(setting.varName, setting.value + 'px');\n }\n\n onDirectionToggle(event: Event) {\n this.isRTL = (event.target as HTMLInputElement).checked;\n document.documentElement.dir = this.isRTL ? 'rtl' : 'ltr';\n }\n}\n","<div class=\"tw-relative tw-h-full tw-bg-white tw-overflow-hidden tw-flex tw-flex-col\">\n <!-- STICKY HEADER SECTION -->\n <div class=\"tw-bg-white tw-sticky tw-top-0 tw-border-b tw-border-gray-200 tw-z-10 tw-flex-shrink-0\">\n <!-- DYNAMIC HEADING -->\n <div class=\"tw-flex tw-justify-between tw-items-center tw-p-2 tw-bg-white tw-border-b tw-border-gray-200\">\n <h6 class=\"tw-font-semibold tw-text-gray-800\">Preset Theme</h6>\n </div>\n </div>\n\n <!-- SCROLLABLE CONTENT AREA -->\n <div class=\"tw-flex-1 tw-overflow-y-auto tw-scroll-smooth tw-p-2 tw-flex tw-flex-col tw-gap-5 tw-text-sm tw-pb-3 theme-scroll-container\">\n <!-- Preset Theme -->\n <section>\n <cide-ele-select id=\"theme-selector\" [(ngModel)]=\"selectedTheme\" (change)=\"onThemeChange($event)\"\n [options]=\"presetThemes\" [size]=\"'sm'\"></cide-ele-select>\n </section>\n\n <!-- Direction Toggle -->\n <section>\n <div class=\"tw-flex tw-justify-between tw-items-center tw-mb-2\">\n <h2 class=\"tw-text-md tw-font-semibold tw-text-gray-800\">Text Direction</h2>\n <div class=\"tw-flex tw-items-center tw-gap-1\">\n <span class=\"tw-text-xs tw-text-gray-500\">LTR</span>\n <label for=\"direction-toggle\" class=\"tw-relative tw-inline-block tw-w-9 tw-h-5\">\n <input type=\"checkbox\" id=\"direction-toggle\" class=\"tw-opacity-0 tw-w-0 tw-h-0\" [(ngModel)]=\"isRTL\"\n (change)=\"onDirectionToggle($event)\">\n <span\n class=\"tw-absolute tw-cursor-pointer tw-top-0 tw-left-0 tw-right-0 tw-bottom-0 tw-bg-gray-300 tw-rounded-full tw-transition-colors checked:tw-bg-blue-500 before:tw-absolute before:tw-content-[''] before:tw-h-4 before:tw-w-4 before:tw-left-0.5 before:tw-bottom-0.5 before:tw-bg-white before:tw-rounded-full before:tw-transition-transform checked:before:tw-translate-x-4\"></span>\n </label>\n <span class=\"tw-text-xs tw-text-gray-500\">RTL</span>\n </div>\n </div>\n </section>\n\n <!-- Theme Property Groups (Brand, Text, Background, Font Sizes, Line Heights) -->\n <section *ngFor=\"let group of themeGroups\" class=\"theme-section\">\n <h2 class=\"tw-text-md tw-font-semibold tw-mb-2 tw-text-gray-800\">{{ group.label }}</h2>\n <div class=\"tw-grid tw-grid-cols-2 tw-gap-2 tw-gap-x-4\">\n <div *ngFor=\"let item of group.items\"\n class=\"tw-flex tw-items-center tw-gap-2 tw-p-1 tw-rounded-lg tw-bg-gray-50\"\n [ngClass]=\"{'tw-flex-col tw-items-stretch': (group.label === 'Font Sizes' || group.label === 'Line Heights' || group.label === 'Layout Dimensions')}\">\n <!-- Font Sizes: label on top, input in middle, unit at bottom -->\n <ng-container *ngIf=\"group.label === 'Font Sizes'\">\n <label [for]=\"item.varName\" class=\"tw-text-sm tw-font-medium tw-text-gray-700 tw-text-left\">{{ item.label\n }}</label>\n <div class=\"tw-flex tw-items-start\">\n <input [id]=\"item.varName\" type=\"number\" step=\"0.001\" [min]=\"item.min ?? null\" [max]=\"item.max ?? null\"\n [(ngModel)]=\"item.value\" (input)=\"onTypographyChange($event, item)\"\n class=\"tw-w-18 tw-text-right tw-text-sm tw-border tw-border-gray-300 tw-rounded tw-px-2 tw-py-1 focus:tw-outline-none focus:tw-ring-2 focus:tw-ring-blue-500 focus:tw-border-transparent theme-input\">\n <span class=\"tw-text-xs tw-text-gray-400\">rem</span>\n </div>\n </ng-container>\n <!-- Line Heights: label on top, input and unit on same line -->\n <ng-container *ngIf=\"group.label === 'Line Heights'\">\n <label [for]=\"item.varName\" class=\"tw-text-sm tw-font-medium tw-text-gray-700 tw-text-left\">{{ item.label\n }}</label>\n <div class=\"tw-flex tw-items-start\">\n <input [id]=\"item.varName\" type=\"number\" step=\"0.1\" [min]=\"item.min ?? null\" [max]=\"item.max ?? null\"\n [(ngModel)]=\"item.value\" (input)=\"onTypographyChange($event, item)\"\n class=\"tw-w-18 tw-text-right tw-text-sm tw-border tw-border-gray-300 tw-rounded tw-px-2 tw-py-1 focus:tw-outline-none focus:tw-ring-2 focus:tw-ring-blue-500 focus:tw-border-transparent theme-input\">\n <span class=\"tw-text-xs tw-text-gray-400\">unitless</span>\n </div>\n </ng-container>\n <!-- Layout Dimensions: label on top, input in middle, px unit at bottom -->\n <ng-container *ngIf=\"group.label === 'Layout Dimensions'\">\n <label [for]=\"item.varName\" class=\"tw-text-sm tw-font-medium tw-text-gray-700 tw-text-left\">{{ item.label\n }}</label>\n <div class=\"tw-flex tw-items-start\">\n <input [id]=\"item.varName\" type=\"number\" step=\"1\" [min]=\"item.min ?? null\" [max]=\"item.max ?? null\"\n [(ngModel)]=\"item.value\" (input)=\"onLayoutChange($event, item)\"\n class=\"tw-w-18 tw-text-right tw-text-sm tw-border tw-border-gray-300 tw-rounded tw-px-2 tw-py-1 focus:tw-outline-none focus:tw-ring-2 focus:tw-ring-blue-500 focus:tw-border-transparent theme-input\">\n <span class=\"tw-text-xs tw-text-gray-400\">px</span>\n </div>\n </ng-container>\n <!-- Other groups: keep previous layout -->\n <ng-container *ngIf=\"group.label !== 'Font Sizes' && group.label !== 'Line Heights' && group.label !== 'Layout Dimensions'\">\n <!-- Color input for color variables -->\n <ng-container *ngIf=\"item.varName.includes('color')\">\n <input [id]=\"item.varName\" [attr.data-variable]=\"item.varName\" type=\"color\" [(ngModel)]=\"item.value\"\n (input)=\"onColorChange($event, item)\"\n class=\"tw-appearance-none tw-border-2 tw-border-gray-200 tw-rounded tw-w-8 tw-h-8 tw-p-0 tw-bg-none tw-shadow-none tw-cursor-pointer tw-transition-colors focus:tw-border-blue-500 color-input\">\n </ng-container>\n <!-- Number input for line heights -->\n <ng-container\n *ngIf=\"!item.varName.includes('color') && item.type === 'number' && group.label !== 'Font Sizes'\">\n <input [id]=\"item.varName\" type=\"number\" [step]=\"item.varName.includes('line-height') ? 0.1 : 0.001\"\n [min]=\"item.min ?? null\" [max]=\"item.max ?? null\" [(ngModel)]=\"item.value\"\n (input)=\"onTypographyChange($event, item)\"\n class=\"tw-w-16 tw-text-right tw-text-sm tw-border tw-border-gray-300 tw-rounded tw-px-2 tw-py-1 focus:tw-outline-none focus:tw-ring-2 focus:tw-ring-blue-500 focus:tw-border-transparent theme-input\">\n <span class=\"tw-text-xs tw-text-gray-400\" *ngIf=\"!item.varName.includes('line-height')\">rem</span>\n </ng-container>\n <!-- Text input fallback (if needed) -->\n <ng-container *ngIf=\"!item.varName.includes('color') && item.type !== 'number'\">\n <input [id]=\"item.varName\" type=\"text\" [(ngModel)]=\"item.value\" (input)=\"onTypographyChange($event, item)\"\n class=\"tw-w-24 tw-text-sm tw-border tw-border-gray-300 tw-rounded tw-px-2 tw-py-1 focus:tw-outline-none focus:tw-ring-2 focus:tw-ring-blue-500 focus:tw-border-transparent theme-input\">\n </ng-container>\n <div class=\"tw-flex tw-flex-col tw-gap-0.5\">\n <label [for]=\"item.varName\" class=\"tw-text-sm tw-font-medium tw-text-gray-700\">{{ item.label }}</label>\n <span class=\"tw-text-xs tw-text-gray-500 tw-font-mono\">{{ item.value }}</span>\n </div>\n </ng-container>\n </div>\n </div>\n </section>\n </div>\n\n <!-- STICKY ACTION BUTTONS SECTION -->\n <div class=\"tw-bg-white tw-sticky tw-bottom-0 tw-border-t tw-border-gray-200 tw-z-10 tw-flex-shrink-0 tw-p-3 tw-shadow-lg sticky-action-buttons\">\n <div class=\"tw-flex tw-gap-2 tw-justify-end\">\n <button cideEleButton \n variant=\"outline\" \n size=\"sm\" \n (btnClick)=\"onReset()\" \n [disabled]=\"!hasChangesFromOriginal()\"\n class=\"tw-transition-all tw-duration-200 hover:tw-scale-105 action-button\">\n Reset to Original\n </button>\n <button cideEleButton \n variant=\"primary\" \n size=\"sm\" \n (btnClick)=\"onSave()\" \n [disabled]=\"!hasUnsavedChanges()\"\n class=\"tw-transition-all tw-duration-200 hover:tw-scale-105 action-button\">\n Save Changes\n </button>\n </div>\n </div>\n</div>"],"names":[],"mappings":";;;;;;;;;;;;;AAQA;AACA;AACO,MAAM,kBAAkB,GAAG,IAAI,cAAc,CAAqB,oBAAoB,CAAC,CAAC;AAO/F;;;;;AAKG;AACa,SAAA,oBAAoB,CAAC,GAAW,EAAE,KAAa,EAAA;;AAE7D,IAAA,MAAM,UAAU,GAAG,CAAG,EAAA,GAAG,CAAC,OAAO,CAAC,IAAI,EAAE,GAAG,CAAC,CAAA,CAAE,CAAC;;IAG/C,IAAI,cAAc,GAAG,KAAK,CAAC;AAC3B,IAAA,IAAI,UAAU,CAAC,QAAQ,CAAC,WAAW,CAAC,IAAI,UAAU,CAAC,QAAQ,CAAC,aAAa,CAAC,EAAE;AAC1E,QAAA,cAAc,GAAG,UAAU,CAAC,KAAK,CAAC,GAAG,KAAK,CAAC;KAC5C;AAED,IAAA,OAAO,EAAE,UAAU,EAAE,cAAc,EAAE,cAAc,EAAE,CAAC;AACxD,CAAC;AAED;;;;;AAKG;SACa,cAAc,CAAC,GAAW,EAAE,KAAa,EAAE,UAAkB,EAAA;AAC3E,IAAA,IAAI,iBAAiB,CAAC,UAAU,CAAC,EAAE;AACjC,QAAA,MAAM,EAAE,UAAU,EAAE,cAAc,EAAE,GAAG,oBAAoB,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;AACxE,QAAA,MAAM,IAAI,GAAG,QAAQ,CAAC,eAAe,CAAC;QACtC,IAAI,CAAC,KAAK,CAAC,WAAW,CAAC,UAAU,EAAE,cAAc,CAAC,CAAC;KACpD;AACH,CAAC;MAKY,mBAAmB,CAAA;AAHhC,IAAA,WAAA,GAAA;;AAKU,QAAA,IAAA,CAAA,mBAAmB,GAAG,MAAM,CAAS,EAAE,CAAC,CAAC;AAC1C,QAAA,IAAA,CAAA,aAAa,GAAG,IAAI,CAAC,mBAAmB,CAAC,UAAU,EAAE,CAAC;;AAGrD,QAAA,IAAA,CAAA,IAAI,GAAG,MAAM,CAAC,UAAU,CAAC,CAAC;AAC1B,QAAA,IAAA,CAAA,UAAU,GAAG,MAAM,CAAC,WAAW,CAAC,CAAC;AACjC,QAAA,IAAA,CAAA,WAAW,GAAG,MAAM,CAAC,kBAAkB,CAAC,CAAC;AAmFlD,KAAA;AAjFC;;;AAGG;IACI,kBAAkB,GAAA;AACvB,QAAA,OAAO,CAAC,GAAG,CAAC,wDAAwD,CAAC,CAAC;AACtE,QAAA,OAAO,IAAI,CAAC,SAAS,EAAE,CAAC;KACzB;AAED;;AAEG;IACI,qBAAqB,GAAA;QAC1B,OAAO,IAAI,CAAC,IAAI,CAAC,GAAG,CAClB,QAAQ,CAAC,IAAI,CAAC;AACZ,YAAA,oBAAoB,CAAC,aAAa;AAClC,YAAA,qBAAqB,EAAE,MAAM;AAC7B,YAAA,qBAAqB,EAAE,mBAAmB;AAC3C,SAAA,CAAC,CAAC,CAAC;KACP;AAED;;AAEG;IACH,SAAS,GAAA;AACP,QAAA,OAAO,IAAI,CAAC,IAAI,CAAC,IAAI,CAAiC,QAAQ,CAAC,IAAI,CAAC,CAAC,oBAAoB,CAAC,aAAa,EAAE,qBAAqB,EAAE,MAAM,EAAE,qBAAqB,EAAE,cAAc,CAAC,CAAC,EAAE,EAAE,mBAAmB,EAAE,0BAA0B,EAAE,CAAC,CAAC,IAAI,CACxO,GAAG,CAAC,KAAK,IAAG;AACV,YAAA,OAAO,CAAC,GAAG,CAAC,iBAAiB,EAAE,KAAK,CAAC,CAAC;AACtC,YAAA,IAAI,CAAC,UAAU,CAAC,KAAK,EAAE,IAA0C,CAAC,CAAC;SACpE,CAAC,CACH,CAAC;KACH;AAED;;;;AAIG;AACK,IAAA,UAAU,CAAC,KAAyC,EAAA;AAC1D,QAAA,OAAO,CAAC,GAAG,CAAC,iBAAiB,EAAE,KAAK,CAAC,CAAC;QACtC,IAAI,MAAM,GAAG,EAAE,CAAC;AAChB,QAAA,IAAI,KAAK,EAAE,kBAAkB,EAAE,eAAe,EAAE;AAC9C,YAAA,MAAM,GAAG,EAAE,GAAG,MAAM,EAAE,GAAG,KAAK,CAAC,kBAAkB,CAAC,eAAe,EAAE,CAAC;YACpE,IAAI,CAAC,mBAAmB,CAAC,GAAG,CAAC,KAAK,CAAC,kBAAkB,CAAC,GAAa,CAAC,CAAC;SACtE;AACD,QAAA,IAAI,KAAK,EAAE,+BAA+B,EAAE,eAAe,EAAE;AAC3D,YAAA,MAAM,GAAG,EAAE,GAAG,MAAM,EAAE,GAAG,KAAK,CAAC,+BAA+B,CAAC,eAAe,EAAE,CAAC;SAClF;AACD,QAAA,IAAI,KAAK,EAAE,kCAAkC,EAAE,gBAAgB,EAAE;AAC/D,YAAA,MAAM,GAAG,EAAE,GAAG,MAAM,EAAE,GAAG,KAAK,CAAC,kCAAkC,CAAC,gBAAgB,EAAE,CAAC;SACtF;AACD,QAAA,OAAO,CAAC,GAAG,CAAC,eAAe,EAAE,MAAM,CAAC,CAAC;;AAErC,QAAA,IAAI,iBAAiB,CAAC,IAAI,CAAC,UAAU,CAAC,EAAE;AACtC,YAAA,MAAM,IAAI,GAAG,QAAQ,CAAC,eAAe,CAAC;AAEtC,YAAA,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE;AACjD,gBAAA,MAAM,EAAE,UAAU,EAAE,cAAc,EAAE,GAAG,oBAAoB,CAAC,GAAG,EAAE,KAAe,CAAC,CAAC;;gBAElF,IAAI,CAAC,KAAK,CAAC,WAAW,CAAC,UAAU,EAAE,cAAc,CAAC,CAAC;aACpD;SACF;KACF;AAED;;;;AAIG;AACH,IAAA,8BAA8B,CAAC,SAA6C,EAAA;QAC1E,OAAO,IAAI,CAAC,IAAI,CAAC,IAAI,CAAgD,QAAQ,CAAC,IAAI,CAAC,CAAC,oBAAoB,CAAC,aAAa,EAAE,qBAAqB,EAAE,MAAM,EAAE,qBAAqB,EAAE,0BAA0B,CAAC,CAAC,EAAE,SAAS,CAAC,CAAC;KACxN;AAED;;;;AAIG;IACH,iBAAiB,CAAC,GAAW,EAAE,KAAa,EAAA;QAC1C,cAAc,CAAC,GAAG,EAAE,KAAK,EAAE,IAAI,CAAC,UAAU,CAAC,CAAC;KAC7C;8GA1FU,mBAAmB,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,UAAA,EAAA,CAAA,CAAA,EAAA;AAAnB,IAAA,SAAA,IAAA,CAAA,KAAA,GAAA,EAAA,CAAA,qBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,QAAA,EAAA,QAAA,EAAA,EAAA,EAAA,IAAA,EAAA,mBAAmB,cAFlB,MAAM,EAAA,CAAA,CAAA,EAAA;;2FAEP,mBAAmB,EAAA,UAAA,EAAA,CAAA;kBAH/B,UAAU;AAAC,YAAA,IAAA,EAAA,CAAA;AACV,oBAAA,UAAU,EAAE,MAAM;AACnB,iBAAA,CAAA;;AA8FD;;;;AAIG;AACa,SAAA,YAAY,CAAC,YAAiC,EAAE,iBAAqC,EAAA;AACnG,IAAA,OAAO,MAAK;AACV,QAAA,IAAI,CAAC,iBAAiB,CAAC,iBAAiB,EAAE;;AAExC,YAAA,OAAO,CAAC,GAAG,CAAC,oCAAoC,CAAC,CAAC;AAClD,YAAA,OAAO,YAAY,CAAC,kBAAkB,EAAE,CAAC;SAC1C;aAAM;;;AAGL,YAAA,OAAO,CAAC,GAAG,CAAC,sFAAsF,CAAC,CAAC;AACpG,YAAA,OAAO,EAAE,CAAC,SAAS,CAAC,CAAC;SACtB;AACH,KAAC,CAAC;AACJ;;MCrHa,2BAA2B,CAAA;IAgEtC,WACU,CAAA,YAAiC,EACZ,UAAkB,EAAA;QADvC,IAAY,CAAA,YAAA,GAAZ,YAAY,CAAqB;QACZ,IAAU,CAAA,UAAA,GAAV,UAAU,CAAQ;AAjEhC,QAAA,IAAA,CAAA,QAAQ,GAAG,MAAM,CAAC,qBAAqB,CAAC,CAAC;;QAE1D,IAAY,CAAA,YAAA,GAAyD,EAAE,CAAC;QACxE,IAAa,CAAA,aAAA,GAAG,EAAE,CAAC;QACnB,IAAe,CAAA,eAAA,GAAG,KAAK,CAAC;QACxB,IAAc,CAAA,cAAA,GAAG,EAAE,CAAC;QACpB,IAAW,CAAA,WAAA,GAA8B,EAAE,CAAC;QAC5C,IAAK,CAAA,KAAA,GAAG,KAAK,CAAC;QACd,IAAwB,CAAA,wBAAA,GAAiB,EAAE,CAAC;AAC5C,QAAA,IAAA,CAAA,sBAAsB,GAA8B,EAAE,CAAC;AAEvD,QAAA,IAAA,CAAA,WAAW,GAAiB;AAC1B,YAAA;AACE,gBAAA,KAAK,EAAE,cAAc;AACrB,gBAAA,KAAK,EAAE;AACL,oBAAA,EAAE,KAAK,EAAE,SAAS,EAAE,OAAO,EAAE,kCAAkC,EAAE,KAAK,EAAE,SAAS,EAAE,IAAI,EAAE,MAAM,EAAE;AACjG,oBAAA,EAAE,KAAK,EAAE,QAAQ,EAAE,OAAO,EAAE,iCAAiC,EAAE,KAAK,EAAE,SAAS,EAAE,IAAI,EAAE,MAAM,EAAE;AAC/F,oBAAA,EAAE,KAAK,EAAE,WAAW,EAAE,OAAO,EAAE,oCAAoC,EAAE,KAAK,EAAE,SAAS,EAAE,IAAI,EAAE,MAAM,EAAE;AACtG,iBAAA;AACF,aAAA;AACD,YAAA;AACE,gBAAA,KAAK,EAAE,aAAa;AACpB,gBAAA,KAAK,EAAE;AACL,oBAAA,EAAE,KAAK,EAAE,WAAW,EAAE,OAAO,EAAE,8BAA8B,EAAE,KAAK,EAAE,SAAS,EAAE,IAAI,EAAE,MAAM,EAAE;AAC/F,oBAAA,EAAE,KAAK,EAAE,cAAc,EAAE,OAAO,EAAE,iCAAiC,EAAE,KAAK,EAAE,SAAS,EAAE,IAAI,EAAE,MAAM,EAAE;AACrG,oBAAA,EAAE,KAAK,EAAE,WAAW,EAAE,OAAO,EAAE,8BAA8B,EAAE,KAAK,EAAE,SAAS,EAAE,IAAI,EAAE,MAAM,EAAE;AAC/F,oBAAA,EAAE,KAAK,EAAE,YAAY,EAAE,OAAO,EAAE,+BAA+B,EAAE,KAAK,EAAE,SAAS,EAAE,IAAI,EAAE,MAAM,EAAE;AAClG,iBAAA;AACF,aAAA;AACD,YAAA;AACE,gBAAA,KAAK,EAAE,mBAAmB;AAC1B,gBAAA,KAAK,EAAE;AACL,oBAAA,EAAE,KAAK,EAAE,iBAAiB,EAAE,OAAO,EAAE,oCAAoC,EAAE,KAAK,EAAE,SAAS,EAAE,IAAI,EAAE,MAAM,EAAE;AAC5G,iBAAA;AACF,aAAA;AACD,YAAA;AACE,gBAAA,KAAK,EAAE,mBAAmB;AAC1B,gBAAA,KAAK,EAAE;oBACL,EAAE,KAAK,EAAE,qBAAqB,EAAE,OAAO,EAAE,gCAAgC,EAAE,KAAK,EAAE,IAAI,EAAE,IAAI,EAAE,QAAQ,EAAE,GAAG,EAAE,EAAE,EAAE,GAAG,EAAE,GAAG,EAAE;AAC5H,iBAAA;AACF,aAAA;AACD,YAAA;AACE,gBAAA,KAAK,EAAE,YAAY;AACnB,gBAAA,KAAK,EAAE;oBACL,EAAE,KAAK,EAAE,gBAAgB,EAAE,OAAO,EAAE,6BAA6B,EAAE,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,GAAG,EAAE,CAAC,EAAE,GAAG,EAAE,EAAE,EAAE;oBACpH,EAAE,KAAK,EAAE,eAAe,EAAE,OAAO,EAAE,4BAA4B,EAAE,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,GAAG,EAAE,CAAC,EAAE,GAAG,EAAE,EAAE,EAAE;oBAClH,EAAE,KAAK,EAAE,cAAc,EAAE,OAAO,EAAE,2BAA2B,EAAE,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,GAAG,EAAE,CAAC,EAAE,GAAG,EAAE,EAAE,EAAE;oBAChH,EAAE,KAAK,EAAE,cAAc,EAAE,OAAO,EAAE,2BAA2B,EAAE,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,GAAG,EAAE,CAAC,EAAE,GAAG,EAAE,EAAE,EAAE;oBAChH,EAAE,KAAK,EAAE,cAAc,EAAE,OAAO,EAAE,2BAA2B,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,QAAQ,EAAE,GAAG,EAAE,CAAC,EAAE,GAAG,EAAE,EAAE,EAAE;oBAC/G,EAAE,KAAK,EAAE,qBAAqB,EAAE,OAAO,EAAE,0BAA0B,EAAE,KAAK,EAAE,GAAG,EAAE,IAAI,EAAE,QAAQ,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC,EAAE;oBACnH,EAAE,KAAK,EAAE,cAAc,EAAE,OAAO,EAAE,2BAA2B,EAAE,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC,EAAE;oBAC/G,EAAE,KAAK,EAAE,cAAc,EAAE,OAAO,EAAE,2BAA2B,EAAE,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC,EAAE;AAChH,iBAAA;AACF,aAAA;AACD,YAAA;AACE,gBAAA,KAAK,EAAE,cAAc;AACrB,gBAAA,KAAK,EAAE;oBACL,EAAE,KAAK,EAAE,kBAAkB,EAAE,OAAO,EAAE,+BAA+B,EAAE,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,GAAG,EAAE,CAAC,EAAE,GAAG,EAAE,CAAC,EAAE;oBACrH,EAAE,KAAK,EAAE,qBAAqB,EAAE,OAAO,EAAE,kCAAkC,EAAE,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,GAAG,EAAE,CAAC,EAAE,GAAG,EAAE,CAAC,EAAE;AAC5H,iBAAA;AACF,aAAA;SACF,CAAC;KAKG;IAEL,QAAQ,GAAA;;QAEN,IAAI,CAAC,aAAa,GAAG,IAAI,CAAC,YAAY,CAAC,aAAa,EAAE,CAAC;;AAGvD,QAAA,IAAI,CAAC,eAAe,GAAG,IAAI,CAAC;AAC5B,QAAA,IAAI,CAAC,YAAY,CAAC,qBAAqB,EAAE,CAAC,SAAS,CAAC;AAClD,YAAA,IAAI,EAAE,CAAC,GAAwC,KAAI;gBACjD,MAAM,MAAM,GAAgB,GAAG,EAAE,IAAI,EAAE,kBAAkB,IAAI,EAAE,CAAC;AAChE,gBAAA,IAAI,CAAC,YAAY,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC,KAAgB,MAAM;AACpD,oBAAA,KAAK,EAAE,KAAK,CAAC,GAAG,IAAI,EAAE;oBACtB,KAAK,EAAE,KAAK,CAAC,eAAe,IAAI,KAAK,CAAC,aAAa,IAAI,EAAE;oBACzD,KAAK;AACN,iBAAA,CAAC,CAAC,CAAC;AACJ,gBAAA,IAAI,CAAC,eAAe,GAAG,KAAK,CAAC;;AAE7B,gBAAA,IAAI,CAAC,IAAI,CAAC,aAAa,EAAE;AACvB,oBAAA,MAAM,YAAY,GAAG,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,eAAe,CAAC,CAAC;oBAC1E,IAAI,YAAY,EAAE;AAChB,wBAAA,IAAI,CAAC,aAAa,GAAG,YAAY,CAAC,KAAK,CAAC;;AAExC,wBAAA,IAAI,YAAY,CAAC,KAAK,CAAC,eAAe,EAAE;AACtC,4BAAA,MAAM,CAAC,OAAO,CAAC,YAAY,CAAC,KAAK,CAAC,eAAe,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,OAAO,EAAE,KAAK,CAAC,KAAI;AAC9E,gCAAA,IAAI,CAAC,SAAS,CAAC,OAAO,EAAE,KAAe,CAAC,CAAC;AAC3C,6BAAC,CAAC,CAAC;yBACJ;qBACF;iBACF;aACF;YACD,KAAK,EAAE,MAAK;AACV,gBAAA,IAAI,CAAC,cAAc,GAAG,uBAAuB,CAAC;AAC9C,gBAAA,IAAI,CAAC,eAAe,GAAG,KAAK,CAAC;aAC9B;AACF,SAAA,CAAC,CAAC;QACH,IAAI,CAAC,qBAAqB,EAAE,CAAC;KAC9B;IAED,qBAAqB,GAAA;AACnB,QAAA,IAAI,CAAC,YAAY,CAAC,SAAS,EAAE,CAAC,SAAS,CAAC;AACtC,YAAA,IAAI,EAAE,CAAC,GAAmC,KAAI;AAC5C,gBAAA,MAAM,IAAI,GAA0B,GAAG,EAAE,IAAI,EAAE,kBAAkB,CAAC;AAClE,gBAAA,MAAM,GAAG,GAA2B,GAAG,EAAE,IAAI,EAAE,+BAA+B,CAAC;AAC/E,gBAAA,MAAM,IAAI,GAA4B,GAAG,EAAE,IAAI,EAAE,kCAAkC,CAAC;;AAEpF,gBAAA,IAAI,MAAM,GAAG,EAAE,IAAI,IAAI,EAAE,eAAe,IAAI,EAAE,CAAC,EAAE,CAAC;;AAElD,gBAAA,IAAI,GAAG,EAAE,eAAe,EAAE;oBACxB,MAAM,GAAG,EAAE,GAAG,MAAM,EAAE,GAAG,GAAG,CAAC,eAAe,EAAE,CAAC;iBAChD;;AAED,gBAAA,IAAI,IAAI,EAAE,gBAAgB,EAAE;oBAC1B,MAAM,GAAG,EAAE,GAAG,MAAM,EAAE,GAAG,IAAI,CAAC,gBAAgB,EAAE,CAAC;iBAClD;AACD,gBAAA,IAAI,CAAC,WAAW,GAAG,MAAM,CAAC;;AAG1B,gBAAA,IAAI,CAAC,sBAAsB,GAAG,EAAE,GAAG,MAAM,EAAE,CAAC;;AAG5C,gBAAA,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,OAAO,EAAE,KAAK,CAAC,KAAI;AAC5D,oBAAA,IAAI,CAAC,SAAS,CAAC,OAAO,EAAE,KAAe,CAAC,CAAC;AAC3C,iBAAC,CAAC,CAAC;AAEH,gBAAA,KAAK,MAAM,KAAK,IAAI,IAAI,CAAC,WAAW,EAAE;AACpC,oBAAA,KAAK,MAAM,IAAI,IAAI,KAAK,CAAC,KAAK,EAAE;AAC9B,wBAAA,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;AAC5C,wBAAA,IAAI,CAAC,KAAK,GAAG,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,MAAM,CAAC,GAAG,CAAC,IAAI,IAAI,CAAC,KAAK,CAAC;AAE/D,wBAAA,IAAI,GAAG,CAAC,QAAQ,CAAC,WAAW,CAAC,IAAI,GAAG,CAAC,QAAQ,CAAC,aAAa,CAAC,EAAE;4BAC5D,IAAI,CAAC,KAAK,GAAG,UAAU,CAAC,IAAI,CAAC,KAAK,CAAsB,CAAC;yBAC1D;qBACF;iBACF;;gBAED,IAAI,CAAC,wBAAwB,GAAG,SAAS,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;aAC7D;YACD,KAAK,EAAE,MAAK;;aAEX;AACF,SAAA,CAAC,CAAC;KACJ;;IAGD,SAAS,CAAC,OAAe,EAAE,KAAa,EAAA;;QAEtC,cAAc,CAAC,OAAO,EAAE,KAAK,EAAE,IAAI,CAAC,UAAU,CAAC,CAAC;;KAEjD;AAED,IAAA,aAAa,CAAC,KAAmB,EAAA;AAC/B,QAAA,IAAI,CAAC,aAAa,GAAG,KAAK,CAAC,KAAe,CAAC;QAC3C,MAAM,QAAQ,GAAG,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,KAAK,KAAK,IAAI,CAAC,aAAa,CAAC,CAAC;AAC7E,QAAA,IAAI,QAAQ,IAAI,QAAQ,CAAC,KAAK,IAAI,QAAQ,CAAC,KAAK,CAAC,eAAe,EAAE;;AAEhE,YAAA,IAAI,IAAI,CAAC,YAAY,CAAC,aAAa,EAAE,KAAK,QAAQ,CAAC,KAAK,CAAC,GAAG,EAAE;gBAC5D,IAAI,CAAC,qBAAqB,EAAE,CAAC;aAC9B;iBAAM;;AAEL,gBAAA,IAAI,CAAC,sBAAsB,GAAG,CAAC,CAAC,SAAS,CAAC,QAAQ,CAAC,KAAK,CAAC,eAAe,CAAC,CAAC;;AAG1E,gBAAA,KAAK,MAAM,KAAK,IAAI,IAAI,CAAC,WAAW,EAAE;AACpC,oBAAA,KAAK,MAAM,IAAI,IAAI,KAAK,CAAC,KAAK,EAAE;AAC9B,wBAAA,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;AAC5C,wBAAA,IAAI,CAAC,KAAK,GAAG,QAAQ,CAAC,KAAK,CAAC,eAAe,CAAC,IAAI,CAAC,OAAO,CAAC;AACvD,4BAAA,QAAQ,CAAC,KAAK,CAAC,eAAe,CAAC,GAAG,CAAC;4BACnC,IAAI,CAAC,KAAK,CAAC;wBAEb,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,OAAO,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC;AAEzC,wBAAA,IAAI,GAAG,CAAC,QAAQ,CAAC,WAAW,CAAC,IAAI,GAAG,CAAC,QAAQ,CAAC,aAAa,CAAC,EAAE;4BAC5D,IAAI,CAAC,KAAK,GAAG,UAAU,CAAC,IAAI,CAAC,KAAK,CAAsB,CAAC;yBAC1D;qBACF;iBACF;;gBAED,IAAI,CAAC,wBAAwB,GAAG,SAAS,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;aAC7D;SACF;KACF;IAED,OAAO,GAAA;;AAEL,QAAA,KAAK,MAAM,KAAK,IAAI,IAAI,CAAC,WAAW,EAAE;AACpC,YAAA,KAAK,MAAM,IAAI,IAAI,KAAK,CAAC,KAAK,EAAE;AAC9B,gBAAA,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;;gBAE5C,MAAM,aAAa,GAAG,IAAI,CAAC,sBAAsB,CAAC,IAAI,CAAC,OAAO,CAAC;AAC7D,oBAAA,IAAI,CAAC,sBAAsB,CAAC,GAAG,CAAC;oBAChC,IAAI,CAAC,KAAK,CAAC;;AAGb,gBAAA,IAAI,CAAC,KAAK,GAAG,aAAa,CAAC;;gBAG3B,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,OAAO,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC;AAEzC,gBAAA,IAAI,GAAG,CAAC,QAAQ,CAAC,WAAW,CAAC,IAAI,GAAG,CAAC,QAAQ,CAAC,aAAa,CAAC,EAAE;oBAC5D,IAAI,CAAC,KAAK,GAAG,UAAU,CAAC,IAAI,CAAC,KAAK,CAAsB,CAAC;iBAC1D;aACF;SACF;;QAGD,IAAI,CAAC,wBAAwB,GAAG,SAAS,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;KAC7D;IAED,MAAM,GAAA;;QAEJ,MAAM,SAAS,GAAU,EAExB,CAAC;AACF,QAAA,KAAK,MAAM,KAAK,IAAI,IAAI,CAAC,WAAW,EAAE;AACpC,YAAA,KAAK,MAAM,IAAI,IAAI,KAAK,CAAC,KAAK,EAAE;AAC9B,gBAAA,SAAS,CAAC,IAAI,CAAC,OAAO,EAAE,UAAU,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC;aAC5D;SACF;AAED,QAAA,MAAM,sBAAsB,GAAuC;AACjE,YAAA,gBAAgB,EAAE;AAChB,gBAAA,GAAG,SAAS;AACb,aAAA;AACD,YAAA,2BAA2B,EAAE,IAAI,CAAC,aAAa;AAC/C,YAAA,mBAAmB,EAAE,IAAI,CAAC,QAAQ,CAAC,WAAW,EAAE,EAAE,GAAG,IAAI,EAAE;YAC3D,qBAAqB,EAAE,IAAI,CAAC,QAAQ,CAAC,iBAAiB,EAAE,IAAI,EAAE;YAC9D,aAAa,EAAE,EAAE;SAClB,CAAC;;QAGF,IAAI,CAAC,YAAY,CAAC,8BAA8B,CAAC,sBAAsB,CAAC,CAAC,SAAS,CAAC;AACjF,YAAA,IAAI,EAAE,CAAC,GAAkD,KAAI;AAC3D,gBAAA,OAAO,CAAC,GAAG,CAAC,cAAc,EAAE,GAAG,CAAC,CAAC;;;;gBAIjC,OAAO,CAAC,GAAG,CAAC,iBAAiB,EAAE,IAAI,CAAC,aAAa,CAAC,CAAC;aACpD;AACD,YAAA,KAAK,EAAE,CAAC,KAAK,KAAI;AACf,gBAAA,OAAO,CAAC,KAAK,CAAC,qBAAqB,EAAE,KAAK,CAAC,CAAC;aAC7C;AACF,SAAA,CAAC,CAAC;KACJ;IAED,iBAAiB,GAAA;;QAEf,IAAI,IAAI,CAAC,YAAY,CAAC,aAAa,EAAE,KAAK,IAAI,CAAC,aAAa,EAAE;AAC5D,YAAA,OAAO,IAAI,CAAC;SACb;;QAED,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,WAAW,EAAE,IAAI,CAAC,wBAAwB,CAAC,CAAC;KAClE;AAED;;;AAGG;IACH,sBAAsB,GAAA;AACpB,QAAA,KAAK,MAAM,KAAK,IAAI,IAAI,CAAC,WAAW,EAAE;AACpC,YAAA,KAAK,MAAM,IAAI,IAAI,KAAK,CAAC,KAAK,EAAE;AAC9B,gBAAA,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;gBAC5C,MAAM,aAAa,GAAG,IAAI,CAAC,sBAAsB,CAAC,IAAI,CAAC,OAAO,CAAC;AAC7D,oBAAA,IAAI,CAAC,sBAAsB,CAAC,GAAG,CAAC,CAAC;gBAEnC,IAAI,aAAa,KAAK,SAAS,IAAI,IAAI,CAAC,KAAK,KAAK,aAAa,EAAE;AAC/D,oBAAA,OAAO,IAAI,CAAC;iBACb;aACF;SACF;AACD,QAAA,OAAO,KAAK,CAAC;KACd;IAED,aAAa,CAAC,KAAY,EAAE,KAAiB,EAAA;AAC3C,QAAA,MAAM,KAAK,GAAG,KAAK,CAAC,MAA0B,CAAC;AAC/C,QAAA,KAAK,CAAC,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC;QAC1B,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,OAAO,EAAE,KAAK,CAAC,KAAK,CAAC,CAAC;KAC5C;IAED,kBAAkB,CAAC,KAAY,EAAE,OAA0B,EAAA;AACzD,QAAA,MAAM,KAAK,GAAG,KAAK,CAAC,MAA0B,CAAC;AAC/C,QAAA,OAAO,CAAC,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC;QAC5B,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,OAAO,EAAE,OAAO,CAAC,IAAI,KAAK,QAAQ,GAAG,OAAO,CAAC,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC;KAC5F;IAED,cAAc,CAAC,KAAY,EAAE,OAA0B,EAAA;AACrD,QAAA,MAAM,KAAK,GAAG,KAAK,CAAC,MAA0B,CAAC;AAC/C,QAAA,OAAO,CAAC,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC;;AAE5B,QAAA,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,OAAO,EAAE,OAAO,CAAC,KAAK,GAAG,IAAI,CAAC,CAAC;KACvD;AAED,IAAA,iBAAiB,CAAC,KAAY,EAAA;QAC5B,IAAI,CAAC,KAAK,GAAI,KAAK,CAAC,MAA2B,CAAC,OAAO,CAAC;AACxD,QAAA,QAAQ,CAAC,eAAe,CAAC,GAAG,GAAG,IAAI,CAAC,KAAK,GAAG,KAAK,GAAG,KAAK,CAAC;KAC3D;AA9SU,IAAA,SAAA,IAAA,CAAA,IAAA,GAAA,EAAA,CAAA,kBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,QAAA,EAAA,QAAA,EAAA,EAAA,EAAA,IAAA,EAAA,2BAA2B,kDAkE5B,WAAW,EAAA,CAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA,CAAA,EAAA;AAlEV,IAAA,SAAA,IAAA,CAAA,IAAA,GAAA,EAAA,CAAA,oBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,QAAA,EAAA,IAAA,EAAA,2BAA2B,EC/CxC,YAAA,EAAA,IAAA,EAAA,QAAA,EAAA,uBAAA,EAAA,QAAA,EAAA,EAAA,EAAA,QAAA,EAAA,wgRA+HM,EDpFM,MAAA,EAAA,CAAA,uzCAAA,CAAA,EAAA,YAAA,EAAA,CAAA,EAAA,IAAA,EAAA,UAAA,EAAA,IAAA,EAAA,WAAW,EAAE,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAAA,EAAA,CAAA,oBAAA,EAAA,QAAA,EAAA,8MAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAAA,EAAA,CAAA,mBAAA,EAAA,QAAA,EAAA,iGAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAAA,EAAA,CAAA,4BAAA,EAAA,QAAA,EAAA,uGAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAAA,EAAA,CAAA,eAAA,EAAA,QAAA,EAAA,2CAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAAA,EAAA,CAAA,YAAA,EAAA,QAAA,EAAA,gHAAA,EAAA,MAAA,EAAA,CAAA,KAAA,CAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAAA,EAAA,CAAA,YAAA,EAAA,QAAA,EAAA,gHAAA,EAAA,MAAA,EAAA,CAAA,KAAA,CAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAAA,EAAA,CAAA,OAAA,EAAA,QAAA,EAAA,qDAAA,EAAA,MAAA,EAAA,CAAA,MAAA,EAAA,UAAA,EAAA,SAAA,EAAA,gBAAA,CAAA,EAAA,OAAA,EAAA,CAAA,eAAA,CAAA,EAAA,QAAA,EAAA,CAAA,SAAA,CAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAAA,KAAK,EAAE,QAAA,EAAA,kBAAA,EAAA,MAAA,EAAA,CAAA,SAAA,EAAA,cAAA,EAAA,eAAA,CAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAAA,IAAI,EAAE,QAAA,EAAA,QAAA,EAAA,MAAA,EAAA,CAAA,MAAA,EAAA,UAAA,EAAA,UAAA,CAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAAA,OAAO,EAAE,QAAA,EAAA,WAAA,EAAA,MAAA,EAAA,CAAA,OAAA,EAAA,SAAA,CAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAAA,mBAAmB,mYAAE,sBAAsB,EAAA,QAAA,EAAA,yCAAA,EAAA,MAAA,EAAA,CAAA,OAAA,EAAA,SAAA,EAAA,MAAA,EAAA,MAAA,EAAA,OAAA,EAAA,WAAA,EAAA,UAAA,EAAA,IAAA,EAAA,SAAA,EAAA,WAAA,EAAA,UAAA,EAAA,WAAA,EAAA,aAAA,EAAA,SAAA,EAAA,WAAA,EAAA,QAAA,EAAA,YAAA,EAAA,cAAA,EAAA,oBAAA,EAAA,UAAA,CAAA,EAAA,OAAA,EAAA,CAAA,UAAA,EAAA,aAAA,CAAA,EAAA,CAAA,EAAA,CAAA,CAAA,EAAA;;2FAI7E,2BAA2B,EAAA,UAAA,EAAA,CAAA;kBAPvC,SAAS;AACE,YAAA,IAAA,EAAA,CAAA,EAAA,QAAA,EAAA,uBAAuB,EACrB,UAAA,EAAA,IAAI,EACP,OAAA,EAAA,CAAC,WAAW,EAAE,KAAK,EAAE,IAAI,EAAE,OAAO,EAAE,mBAAmB,EAAE,sBAAsB,CAAC,EAAA,QAAA,EAAA,wgRAAA,EAAA,MAAA,EAAA,CAAA,uzCAAA,CAAA,EAAA,CAAA;;0BAsEtF,MAAM;2BAAC,WAAW,CAAA;;;;;"}