@admin-layout/tailwind-design-pro 12.0.16-alpha.87 → 12.0.16-alpha.88

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 (115) hide show
  1. package/lib/components/Layout/BasicLayout/index.d.ts.map +1 -1
  2. package/lib/components/Layout/BasicLayout/index.js.map +1 -1
  3. package/lib/components/Layout/TailwindLayout.js +1 -1
  4. package/lib/components/Layout/TailwindLayout.js.map +1 -1
  5. package/lib/components/SettingDrawer/SettingDrawer.d.ts +1 -3
  6. package/lib/components/SettingDrawer/SettingDrawer.d.ts.map +1 -1
  7. package/lib/components/SettingDrawer/SettingDrawer.js +88 -665
  8. package/lib/components/SettingDrawer/SettingDrawer.js.map +1 -1
  9. package/lib/components/SettingDrawer/components/ApplyToAllRoutesToggle.d.ts +7 -0
  10. package/lib/components/SettingDrawer/components/ApplyToAllRoutesToggle.d.ts.map +1 -0
  11. package/lib/components/SettingDrawer/components/ApplyToAllRoutesToggle.js +30 -0
  12. package/lib/components/SettingDrawer/components/ApplyToAllRoutesToggle.js.map +1 -0
  13. package/lib/components/SettingDrawer/components/CheckBoxTheme.d.ts +3 -0
  14. package/lib/components/SettingDrawer/components/CheckBoxTheme.d.ts.map +1 -0
  15. package/lib/components/SettingDrawer/{CheckBoxTheme.js → components/CheckBoxTheme.js} +2 -2
  16. package/lib/components/SettingDrawer/components/CheckBoxTheme.js.map +1 -0
  17. package/lib/components/SettingDrawer/components/DeviceTabs.d.ts +7 -0
  18. package/lib/components/SettingDrawer/components/DeviceTabs.d.ts.map +1 -0
  19. package/lib/components/SettingDrawer/components/DeviceTabs.js +82 -0
  20. package/lib/components/SettingDrawer/components/DeviceTabs.js.map +1 -0
  21. package/lib/components/SettingDrawer/components/InvitationSettings.d.ts +3 -0
  22. package/lib/components/SettingDrawer/components/InvitationSettings.d.ts.map +1 -0
  23. package/lib/components/SettingDrawer/{InvitationSettings.js → components/InvitationSettings.js} +2 -2
  24. package/lib/components/SettingDrawer/components/InvitationSettings.js.map +1 -0
  25. package/lib/components/SettingDrawer/components/LayoutChange.d.ts +3 -0
  26. package/lib/components/SettingDrawer/components/LayoutChange.d.ts.map +1 -0
  27. package/lib/components/SettingDrawer/{LayoutChange.js → components/LayoutChange.js} +2 -2
  28. package/lib/components/SettingDrawer/components/LayoutChange.js.map +1 -0
  29. package/lib/components/SettingDrawer/{MenuVisibilitySettings.d.ts → components/MenuVisibilitySettings.d.ts} +1 -1
  30. package/lib/components/SettingDrawer/components/MenuVisibilitySettings.d.ts.map +1 -0
  31. package/lib/components/SettingDrawer/{MenuVisibilitySettings.js → components/MenuVisibilitySettings.js} +44 -45
  32. package/lib/components/SettingDrawer/components/MenuVisibilitySettings.js.map +1 -0
  33. package/lib/components/SettingDrawer/components/NavigationsModes.d.ts +3 -0
  34. package/lib/components/SettingDrawer/components/NavigationsModes.d.ts.map +1 -0
  35. package/lib/components/SettingDrawer/{NavigationsModes.js → components/NavigationsModes.js} +2 -2
  36. package/lib/components/SettingDrawer/components/NavigationsModes.js.map +1 -0
  37. package/lib/components/SettingDrawer/components/RegionalSettings.d.ts +3 -0
  38. package/lib/components/SettingDrawer/components/RegionalSettings.d.ts.map +1 -0
  39. package/lib/components/SettingDrawer/{RegionalSettings.js → components/RegionalSettings.js} +2 -2
  40. package/lib/components/SettingDrawer/components/RegionalSettings.js.map +1 -0
  41. package/lib/components/SettingDrawer/components/SettingsActions.d.ts +12 -0
  42. package/lib/components/SettingDrawer/components/SettingsActions.d.ts.map +1 -0
  43. package/lib/components/SettingDrawer/components/SettingsActions.js +69 -0
  44. package/lib/components/SettingDrawer/components/SettingsActions.js.map +1 -0
  45. package/lib/components/SettingDrawer/components/SettingsDrawerHeader.d.ts +4 -0
  46. package/lib/components/SettingDrawer/components/SettingsDrawerHeader.d.ts.map +1 -0
  47. package/lib/components/SettingDrawer/components/SettingsDrawerHeader.js +25 -0
  48. package/lib/components/SettingDrawer/components/SettingsDrawerHeader.js.map +1 -0
  49. package/lib/components/SettingDrawer/{Switch/index.d.ts → components/Switch.d.ts} +2 -2
  50. package/lib/components/SettingDrawer/components/Switch.d.ts.map +1 -0
  51. package/lib/components/SettingDrawer/{Switch/index.js → components/Switch.js} +1 -1
  52. package/lib/components/SettingDrawer/components/Switch.js.map +1 -0
  53. package/lib/components/SettingDrawer/components/ThemeColor.d.ts +3 -0
  54. package/lib/components/SettingDrawer/components/ThemeColor.d.ts.map +1 -0
  55. package/lib/components/SettingDrawer/{ThemeColor.js → components/ThemeColor.js} +2 -2
  56. package/lib/components/SettingDrawer/components/ThemeColor.js.map +1 -0
  57. package/lib/components/SettingDrawer/{ThemeSelector.d.ts → components/ThemeSelector.d.ts} +1 -1
  58. package/lib/components/SettingDrawer/components/ThemeSelector.d.ts.map +1 -0
  59. package/lib/components/SettingDrawer/components/ThemeSelector.js.map +1 -0
  60. package/lib/components/SettingDrawer/components/WebFontsSelector.d.ts +3 -0
  61. package/lib/components/SettingDrawer/components/WebFontsSelector.d.ts.map +1 -0
  62. package/lib/components/SettingDrawer/components/WebFontsSelector.js.map +1 -0
  63. package/lib/components/SettingDrawer/hooks/useSettingsOperations.d.ts +18 -0
  64. package/lib/components/SettingDrawer/hooks/useSettingsOperations.d.ts.map +1 -0
  65. package/lib/components/SettingDrawer/hooks/useSettingsOperations.js +117 -0
  66. package/lib/components/SettingDrawer/hooks/useSettingsOperations.js.map +1 -0
  67. package/lib/components/SettingDrawer/utils/constants.d.ts +11 -0
  68. package/lib/components/SettingDrawer/utils/constants.d.ts.map +1 -0
  69. package/lib/components/SettingDrawer/utils/constants.js +77 -0
  70. package/lib/components/SettingDrawer/utils/constants.js.map +1 -0
  71. package/lib/components/SettingDrawer/utils/helper.d.ts +37 -0
  72. package/lib/components/SettingDrawer/utils/helper.d.ts.map +1 -0
  73. package/lib/components/SettingDrawer/utils/helper.js +243 -0
  74. package/lib/components/SettingDrawer/utils/helper.js.map +1 -0
  75. package/lib/components/SettingDrawer/utils/transformers.d.ts +15 -0
  76. package/lib/components/SettingDrawer/utils/transformers.d.ts.map +1 -0
  77. package/lib/components/SettingDrawer/utils/transformers.js +76 -0
  78. package/lib/components/SettingDrawer/utils/transformers.js.map +1 -0
  79. package/lib/components/SettingDrawer/utils/types.d.ts.map +1 -0
  80. package/lib/machines/settingsMachine.js +6 -9
  81. package/lib/machines/settingsMachine.js.map +1 -1
  82. package/lib/machines/types.d.ts +1 -0
  83. package/lib/machines/types.d.ts.map +1 -1
  84. package/package.json +4 -4
  85. package/lib/components/SettingDrawer/CheckBoxTheme.d.ts +0 -3
  86. package/lib/components/SettingDrawer/CheckBoxTheme.d.ts.map +0 -1
  87. package/lib/components/SettingDrawer/CheckBoxTheme.js.map +0 -1
  88. package/lib/components/SettingDrawer/InvitationSettings.d.ts +0 -3
  89. package/lib/components/SettingDrawer/InvitationSettings.d.ts.map +0 -1
  90. package/lib/components/SettingDrawer/InvitationSettings.js.map +0 -1
  91. package/lib/components/SettingDrawer/LayoutChange.d.ts +0 -3
  92. package/lib/components/SettingDrawer/LayoutChange.d.ts.map +0 -1
  93. package/lib/components/SettingDrawer/LayoutChange.js.map +0 -1
  94. package/lib/components/SettingDrawer/MenuVisibilitySettings.d.ts.map +0 -1
  95. package/lib/components/SettingDrawer/MenuVisibilitySettings.js.map +0 -1
  96. package/lib/components/SettingDrawer/NavigationsModes.d.ts +0 -3
  97. package/lib/components/SettingDrawer/NavigationsModes.d.ts.map +0 -1
  98. package/lib/components/SettingDrawer/NavigationsModes.js.map +0 -1
  99. package/lib/components/SettingDrawer/RegionalSettings.d.ts +0 -3
  100. package/lib/components/SettingDrawer/RegionalSettings.d.ts.map +0 -1
  101. package/lib/components/SettingDrawer/RegionalSettings.js.map +0 -1
  102. package/lib/components/SettingDrawer/Switch/index.d.ts.map +0 -1
  103. package/lib/components/SettingDrawer/Switch/index.js.map +0 -1
  104. package/lib/components/SettingDrawer/ThemeColor.d.ts +0 -3
  105. package/lib/components/SettingDrawer/ThemeColor.d.ts.map +0 -1
  106. package/lib/components/SettingDrawer/ThemeColor.js.map +0 -1
  107. package/lib/components/SettingDrawer/ThemeSelector.d.ts.map +0 -1
  108. package/lib/components/SettingDrawer/ThemeSelector.js.map +0 -1
  109. package/lib/components/SettingDrawer/WebFontsSelector.d.ts +0 -3
  110. package/lib/components/SettingDrawer/WebFontsSelector.d.ts.map +0 -1
  111. package/lib/components/SettingDrawer/WebFontsSelector.js.map +0 -1
  112. package/lib/components/SettingDrawer/types.d.ts.map +0 -1
  113. /package/lib/components/SettingDrawer/{ThemeSelector.js → components/ThemeSelector.js} +0 -0
  114. /package/lib/components/SettingDrawer/{WebFontsSelector.js → components/WebFontsSelector.js} +0 -0
  115. /package/lib/components/SettingDrawer/{types.d.ts → utils/types.d.ts} +0 -0
@@ -1,305 +1,4 @@
1
- import {jsx,Fragment,jsxs}from'react/jsx-runtime';import {useSelector}from'@xstate/react';import clsx from'clsx';import {parse}from'qs';import*as React from'react';import {useState,useRef,useEffect}from'react';import {useTranslation}from'react-i18next';import'@react-icons/all-files/fa/FaMoon.js';import'@react-icons/all-files/fa/FaSun.js';import {useMediaQuery}from'../../hooks/useMediaQuery.js';import {icons}from'../../icons.js';import isBrowser from'../../utils/isBrowser/index.js';import {getDefaultApplyToAllRoutes,getSettingValue}from'../../utils/settingsUtils.js';import'@common-stack/components-pro';import {AdditionalSettingsSlot}from'../Layout/slot-fill/AdditionalSettings.js';import'reflect-metadata';import'@admin-layout/client/lib/constants/layout.js';import CheckBoxTheme from'./CheckBoxTheme.js';import InvitationSettings from'./InvitationSettings.js';import LayoutChange from'./LayoutChange.js';import MenuVisibilitySettings from'./MenuVisibilitySettings.js';import NavigationModes from'./NavigationsModes.js';import RegionalSettings from'./RegionalSettings.js';import ThemeColor from'./ThemeColor.js';import {ThemeSelector}from'./ThemeSelector.js';import {WebFontsSelector}from'./WebFontsSelector.js';import {useWriteSettingsMutation,useResetApplicationUiSettingsMutation}from'common/lib/generated/generated.js';import {ConfigCollectionName,ConfigFragmentName}from'common/lib/generated/generated-models.js';import {generateCdecodeUri,DEFAULT_CONTRIBUTION_TENANT_ID}from'@adminide-stack/core';import {config}from'../../config/env-config.js';const updateTheme = (dark, color, publicPath = '/theme') => {
2
- // ssr
3
- if (typeof window === 'undefined' || !window.umi_plugin_ant_themeVar) {
4
- return;
5
- }
6
- const href = dark ? `${publicPath}/dark` : `${publicPath}/`;
7
- // If it is DARK, and is color = daybreak, there is no need to splice
8
- let colorFileName = dark && color ? `-${encodeURIComponent(color)}` : encodeURIComponent(color || '');
9
- if (color === 'daybreak' && dark) {
10
- colorFileName = '';
11
- }
12
- const dom = document.getElementById('theme-style');
13
- // If these two are empty
14
- if (!href && !colorFileName) {
15
- if (dom) {
16
- dom.remove();
17
- localStorage.removeItem('site-theme');
18
- }
19
- return;
20
- }
21
- const url = `${href}${colorFileName || ''}.css`;
22
- if (dom) {
23
- dom.onload = () => {
24
- window.setTimeout(() => {});
25
- };
26
- dom.href = url;
27
- } else {
28
- const style = document.createElement('link');
29
- style.type = 'text/css';
30
- style.rel = 'stylesheet';
31
- style.id = 'theme-style';
32
- style.onload = () => {
33
- window.setTimeout(() => {});
34
- };
35
- style.href = url;
36
- if (document.body.append) {
37
- document.body.append(style);
38
- } else {
39
- document.body.appendChild(style);
40
- }
41
- }
42
- // localStorage.setItem('site-theme', dark ? 'dark' : 'light');
43
- };
44
- const initState = (settings, onSettingChange, publicPath, oldSetting) => {
45
- if (!isBrowser()) {
46
- return;
47
- }
48
- let loadedStyle = false;
49
- if (window.location.search) {
50
- const params = parse(window.location.search.replace('?', ''));
51
- const replaceSetting = {};
52
- Object.keys(params).forEach(key => {
53
- if (settings[key] !== undefined || settings[key] === undefined) {
54
- replaceSetting[key] = params[key];
55
- if (key.includes('Render')) {
56
- replaceSetting[key] = params[key] === 'false' ? false : undefined;
57
- }
58
- }
59
- });
60
- // Only call onSettingChange if we have actual URL parameters to apply
61
- if (onSettingChange && Object.keys(replaceSetting).length > 0) {
62
- console.log('✅ initState: Calling onSettingChange with URL params:', replaceSetting);
63
- onSettingChange({
64
- ...settings,
65
- ...replaceSetting
66
- });
67
- } else {
68
- console.log('⏭️ initState: Skipping onSettingChange - no valid URL params to apply');
69
- }
70
- // Set the topic in the URL and load it once.
71
- if (oldSetting?.navTheme !== params.navTheme && params.navTheme) {
72
- updateTheme(settings.navTheme === 'realDark', params.primaryColor, publicPath);
73
- loadedStyle = true;
74
- }
75
- }
76
- if (loadedStyle) {
77
- return;
78
- }
79
- // If there is no topic in the URL, and no load in the URL is loaded.
80
- if (oldSetting?.navTheme !== settings.navTheme && settings.navTheme) {
81
- updateTheme(settings.navTheme === 'realDark', settings.primaryColor, publicPath);
82
- }
83
- };
84
- const getThemeList = (settings, location, routePattern) => {
85
- const {
86
- t
87
- } = useTranslation('settings');
88
- const {
89
- isMobile
90
- } = useMediaQuery();
91
- const currentRoute = routePattern || location?.pathname || '/';
92
- const deviceType = isMobile ? 'mobile' : 'desktop';
93
- // Helper function to get value from settings with route/device override support
94
- const getUILayoutValue = path => {
95
- const routeDeviceKey = `[${currentRoute}][${deviceType}]`;
96
- const uiOverride = settings?.uiSettings?.[routeDeviceKey];
97
- if (uiOverride) {
98
- const value = path.split('.').reduce((obj, key) => obj?.[key], uiOverride);
99
- if (value !== undefined) return value;
100
- }
101
- return path.split('.').reduce((obj, key) => obj?.[key], settings);
102
- };
103
- const deviceLayout = {
104
- navigationMode: getUILayoutValue('navigationMode'),
105
- sideMenuType: getUILayoutValue('sideMenuType'),
106
- contentWidth: getUILayoutValue('contentWidth'),
107
- fixedHeader: getUILayoutValue('fixedHeader'),
108
- fixedSidebar: getUILayoutValue('fixedSidebar'),
109
- splitMenus: getUILayoutValue('splitMenus')
110
- };
111
- let list = [];
112
- const defaultList = [
113
- //@sri following are needed otherwise we need make above plugin to work
114
- {
115
- key: 'dust',
116
- fileName: 'dust.css',
117
- modifyVars: {
118
- '@primary-color': '#F5222D'
119
- }
120
- }, {
121
- key: 'volcano',
122
- fileName: 'volcano.css',
123
- modifyVars: {
124
- '@primary-color': '#FA541C'
125
- }
126
- }, {
127
- key: 'sunset',
128
- fileName: 'sunset.css',
129
- modifyVars: {
130
- '@primary-color': '#FAAD14'
131
- }
132
- }, {
133
- key: 'cyan',
134
- fileName: 'cyan.css',
135
- modifyVars: {
136
- '@primary-color': '#13C2C2'
137
- }
138
- }, {
139
- key: 'green',
140
- fileName: 'green.css',
141
- modifyVars: {
142
- '@primary-color': '#52C41A'
143
- }
144
- }, {
145
- key: 'geekblue',
146
- fileName: 'geekblue.css',
147
- modifyVars: {
148
- '@primary-color': '#2F54EB'
149
- }
150
- }, {
151
- key: 'purple',
152
- fileName: 'purple.css',
153
- modifyVars: {
154
- '@primary-color': '#722ED1'
155
- }
156
- }];
157
- // ssr
158
- if (typeof window === 'undefined') {
159
- list = defaultList;
160
- } else {
161
- list = window.umi_plugin_ant_themeVar || defaultList;
162
- }
163
- const themeList = [{
164
- key: 'light',
165
- title: t('light')
166
- }];
167
- const darkColorList = [{
168
- key: 'daybreak',
169
- color: '#1890ff',
170
- theme: 'dark'
171
- }];
172
- const lightColorList = [{
173
- key: 'daybreak',
174
- color: '#1890ff',
175
- theme: 'dark'
176
- }];
177
- if (deviceLayout.navigationMode !== 'mixed') {
178
- themeList.push({
179
- key: 'dark',
180
- title: t('dark')
181
- });
182
- }
183
- if (list.find(item => item.theme === 'dark')) {
184
- themeList.push({
185
- key: 'realDark',
186
- title: t('dark')
187
- });
188
- }
189
- // insert theme color List
190
- list.forEach(item => {
191
- const color = (item.modifyVars || {})['@primary-color'];
192
- if (item.theme === 'dark' && color) {
193
- darkColorList.push({
194
- color,
195
- ...item
196
- });
197
- }
198
- if (!item.theme || item.theme === 'light') {
199
- lightColorList.push({
200
- color,
201
- ...item
202
- });
203
- }
204
- });
205
- return {
206
- colorList: {
207
- dark: darkColorList,
208
- light: lightColorList
209
- },
210
- themeList
211
- };
212
- };
213
- const themeOptions = [{
214
- key: 'default',
215
- title: 'Default'
216
- }, {
217
- key: 'github',
218
- title: 'Github Theme'
219
- }, {
220
- key: 'slack',
221
- title: 'Slack Theme'
222
- }, {
223
- key: 'airbnb',
224
- title: 'Airbnb Theme'
225
- }, {
226
- key: 'spotify',
227
- title: 'Spotify Theme'
228
- }];
229
- const fontOptions = [{
230
- key: 'Poppins, sans-serif',
231
- title: 'Poppins'
232
- }, {
233
- key: 'Roboto, sans-serif',
234
- title: 'Roboto'
235
- }, {
236
- key: 'Open Sans, sans-serif',
237
- title: 'Open Sans'
238
- }, {
239
- key: 'Montserrat, sans-serif',
240
- title: 'Montserrat'
241
- }, {
242
- key: 'Lato, sans-serif',
243
- title: 'Lato'
244
- }, {
245
- key: 'Nunito, sans-serif',
246
- title: 'Nunito'
247
- }, {
248
- key: 'Ubuntu, sans-serif',
249
- title: 'Ubuntu'
250
- }, {
251
- key: 'Inter, sans-serif',
252
- title: 'Inter'
253
- }, {
254
- key: 'Arial, sans-serif',
255
- title: 'Arial'
256
- }, {
257
- key: 'Helvetica, sans-serif',
258
- title: 'Helvetica'
259
- }, {
260
- key: 'Tahoma, sans-serif',
261
- title: 'Tahoma'
262
- }, {
263
- key: 'Trebuchet MS, sans-serif',
264
- title: 'Trebuchet MS'
265
- }, {
266
- key: 'Georgia, serif',
267
- title: 'Georgia'
268
- }, {
269
- key: 'Bookman, serif',
270
- title: 'Bookman'
271
- }, {
272
- key: 'Geneva, sans-serif',
273
- title: 'Geneva'
274
- }, {
275
- key: 'Lucida Console, monospace',
276
- title: 'Lucida Console'
277
- }, {
278
- key: 'Courier New, monospace',
279
- title: 'Courier New'
280
- }, {
281
- key: 'Lucida Sans, sans-serif',
282
- title: 'Lucida Sans'
283
- }];
284
- function parseSettingPath(path, value) {
285
- const keys = path.split('.');
286
- // Base case: no nesting
287
- if (keys.length === 1) {
288
- return {
289
- [path]: value
290
- };
291
- }
292
- // Build nested object
293
- let result = {};
294
- let current = result;
295
- for (let i = 0; i < keys.length - 1; i++) {
296
- current[keys[i]] = {};
297
- current = current[keys[i]];
298
- }
299
- current[keys[keys.length - 1]] = value;
300
- return result;
301
- }
302
- const SettingDrawer = props => {
1
+ import {jsx,Fragment,jsxs}from'react/jsx-runtime';import {useSelector}from'@xstate/react';import clsx from'clsx';import*as React from'react';import {useRef,useState,useEffect}from'react';import {useTranslation}from'react-i18next';import'@react-icons/all-files/fa/FaMoon.js';import'@react-icons/all-files/fa/FaSun.js';import {useMediaQuery}from'../../hooks/useMediaQuery.js';import {icons}from'../../icons.js';import isBrowser from'../../utils/isBrowser/index.js';import {getDefaultApplyToAllRoutes,getSettingValue}from'../../utils/settingsUtils.js';import'@common-stack/components-pro';import {AdditionalSettingsSlot}from'../Layout/slot-fill/AdditionalSettings.js';import'reflect-metadata';import'@admin-layout/client/lib/constants/layout.js';import {ApplyToAllRoutesToggle}from'./components/ApplyToAllRoutesToggle.js';import {CheckBoxTheme}from'./components/CheckBoxTheme.js';import {DeviceTabs}from'./components/DeviceTabs.js';import {InvitationSettings}from'./components/InvitationSettings.js';import {LayoutChange}from'./components/LayoutChange.js';import {MenuVisibilitySettings}from'./components/MenuVisibilitySettings.js';import {NavigationModes}from'./components/NavigationsModes.js';import {RegionalSettings}from'./components/RegionalSettings.js';import {SettingsActions}from'./components/SettingsActions.js';import {SettingsDrawerHeader}from'./components/SettingsDrawerHeader.js';import {ThemeColor}from'./components/ThemeColor.js';import {ThemeSelector}from'./components/ThemeSelector.js';import {WebFontsSelector}from'./components/WebFontsSelector.js';import {useSettingsOperations}from'./hooks/useSettingsOperations.js';import {THEME_OPTIONS,FONT_OPTIONS}from'./utils/constants.js';import {getThemeList,initState,parseSettingPath}from'./utils/helper.js';function SettingDrawer(props) {
303
2
  const {
304
3
  onSettingChange,
305
4
  hideLoading,
@@ -315,48 +14,55 @@ const SettingDrawer = props => {
315
14
  fullMenuData,
316
15
  routePattern
317
16
  } = props;
318
- // Don't use useLayoutSettings() - it pulls from Redux which may be stale
319
- // Use settingState from XState actor instead (line 393)
320
17
  const {
321
18
  CloseIcon,
322
- Settings5FillIcon,
323
- CopyIcon,
324
- CheckIcon
19
+ Settings5FillIcon
325
20
  } = icons;
326
- const [show, setShow] = useState(false);
21
+ // Refs
22
+ const hasInitializedRef = useRef(false);
23
+ const btnRef = useRef();
24
+ const prevSettingsRef = useRef();
25
+ // Hooks
327
26
  const {
328
27
  isMobile
329
28
  } = useMediaQuery();
330
- const [copied, setCopied] = useState(false);
331
- const [copiedModified, setCopiedModified] = useState(false);
332
- const [activeDeviceTab, setActiveDeviceTab] = useState(isMobile ? 'mobile' : 'desktop');
333
- const [applyToAllRoutes, setApplyToAllRoutes] = useState(false);
334
29
  const {
335
30
  t
336
31
  } = useTranslation('settings');
337
- // Track if we've already initialized to prevent loops
338
- const hasInitializedRef = useRef(false);
339
- const resource = generateCdecodeUri(DEFAULT_CONTRIBUTION_TENANT_ID, {
340
- resourceType: ConfigCollectionName.Applications,
341
- resourceId: config.APPLICATION_ID,
342
- idField: 'appId'
343
- }, {}, ConfigFragmentName.UiSettings);
344
- const [writeSettingsMutation, {
345
- client
346
- }] = useWriteSettingsMutation();
347
- const [resetApplicationSettings] = useResetApplicationUiSettingsMutation();
348
- const btnRef = useRef();
349
- // REVOLUTIONARY APPROACH: Use stable selectors instead of raw context access
350
- // This completely eliminates the infinite loop problem because:
351
- // 1. selectPublicSettings only returns context.public (no internal state)
352
- // 2. useSelector memoizes the result - only re-renders if PUBLIC settings actually change
353
- // 3. configModel reference changes are isolated in context.internal, never seen here
354
- // 4. No filtering logic needed - separation is built into the machine
32
+ // State
33
+ const [show, setShow] = useState(false);
34
+ const [activeDeviceTab, setActiveDeviceTab] = useState(isMobile ? 'mobile' : 'desktop');
35
+ const [applyToAllRoutes, setApplyToAllRoutes] = useState(false);
36
+ // Selectors
355
37
  const settingState = useSelector(actor, state => state.context.public);
356
38
  const changedSettings = useSelector(actor, state => state.context.internal.changedSettings);
357
- useSelector(actor, state => state.context.internal.deviceType);
358
- // Track previous settings to detect meaningful changes
359
- const prevSettingsRef = useRef();
39
+ // Custom hooks
40
+ const {
41
+ copied,
42
+ copiedModified,
43
+ handleCopySettings,
44
+ handleCopyModifiedSettings,
45
+ handleSaveSettings,
46
+ handleResetSettings
47
+ } = useSettingsOperations({
48
+ actor,
49
+ settingState,
50
+ changedSettings
51
+ });
52
+ // Computed values
53
+ const currentRoute = routePattern || location?.pathname || '/';
54
+ const deviceType = activeDeviceTab;
55
+ const currentPathname = isBrowser() ? window.location.pathname : pathname || '';
56
+ const themeList = getThemeList(settingState, location, routePattern);
57
+ // Derived state
58
+ const defaultApplyToAllRoutes = React.useMemo(() => {
59
+ return getDefaultApplyToAllRoutes(settingState, currentRoute, deviceType);
60
+ }, [settingState, currentRoute, deviceType]);
61
+ const settingsForComponents = settingState;
62
+ // Effects
63
+ useEffect(() => {
64
+ setApplyToAllRoutes(defaultApplyToAllRoutes);
65
+ }, [defaultApplyToAllRoutes]);
360
66
  useEffect(() => {
361
67
  const prevSettings = prevSettingsRef.current;
362
68
  const currentSettings = settingState;
@@ -376,172 +82,9 @@ const SettingDrawer = props => {
376
82
  }
377
83
  prevSettingsRef.current = JSON.parse(JSON.stringify(currentSettings));
378
84
  }, [settingState]);
379
- const currentRoute = routePattern || location?.pathname || '/';
380
- // Use activeDeviceTab instead of isMobile for device type
381
- const deviceType = activeDeviceTab;
382
- // Calculate the default value for applyToAllRoutes based on what overrides exist
383
- const defaultApplyToAllRoutes = React.useMemo(() => {
384
- return getDefaultApplyToAllRoutes(settingState, currentRoute, deviceType);
385
- }, [settingState, currentRoute, deviceType]);
386
- // Update applyToAllRoutes when route or device changes
387
- useEffect(() => {
388
- setApplyToAllRoutes(defaultApplyToAllRoutes);
389
- }, [defaultApplyToAllRoutes]);
390
- // Pass settingState directly - child components will use getSettingValue internally
391
- // with the applyToAllRoutes prop to get the correct scoped values
392
- const settingsForComponents = settingState;
393
- // Helper to get theme value with overrides applied
394
- const getThemeValue = () => getSettingValue(settingState, 'theme', applyToAllRoutes, currentRoute, deviceType, 'default');
395
- // Helper to get font family value with overrides applied
396
- const getFontFamilyValue = () => getSettingValue(settingState, 'fontFamily', applyToAllRoutes, currentRoute, deviceType, 'Poppins, sans-serif');
397
- const themeList = getThemeList(settingState, location, routePattern);
398
- const handleSettingChange = (key, value) => {
399
- // Menu visibility and applyToAllRoutes are always global
400
- const isGlobalSetting = key === 'hiddenMenuKeys' || key === 'hiddenMenuCategories' || key === 'applyToAllRoutes';
401
- if (isGlobalSetting) {
402
- console.log('🌐 Sending GLOBAL setting to actor:', {
403
- key,
404
- value
405
- });
406
- actor.send({
407
- type: 'UISETTING_UPDATE',
408
- value: {
409
- [key]: value
410
- }
411
- });
412
- return;
413
- }
414
- const bracketKey = applyToAllRoutes ? `[${deviceType}]` : `[${currentRoute}][${deviceType}]`;
415
- const settingObject = parseSettingPath(key, value);
416
- const nestedValue = {
417
- [bracketKey]: settingObject
418
- };
419
- console.log('0️⃣ handleSettingChange with value: ', nestedValue);
420
- actor.send({
421
- type: 'UISETTING_UPDATE',
422
- value: nestedValue
423
- });
424
- };
425
- const handleCopySettings = async () => {
426
- if (!isBrowser()) return;
427
- try {
428
- const settings = JSON.stringify(settingState, null, 2);
429
- await navigator.clipboard.writeText(settings);
430
- setCopied(true);
431
- setTimeout(() => setCopied(false), 2000);
432
- } catch (err) {
433
- console.error('Failed to copy settings:', err);
434
- }
435
- };
436
- const handleCopyModifiedSettings = async () => {
437
- if (!isBrowser()) return;
438
- try {
439
- const settingsCookie = document.cookie.split(';').find(cookie => cookie.startsWith(' settings='));
440
- if (!settingsCookie) {
441
- console.log('settings Cookie not found, ', settingsCookie);
442
- return;
443
- }
444
- const settingsValue = settingsCookie.split('=')[1];
445
- const decodedComponent = decodeURIComponent(settingsValue);
446
- const parsedSettings = JSON.parse(atob(decodedComponent));
447
- console.log('Settings in cookies : ', parsedSettings);
448
- navigator.clipboard.writeText(JSON.stringify(parsedSettings, null, 2));
449
- } catch (err) {
450
- console.error('Failed to copy modified settings:', err);
451
- }
452
- };
453
- const handleSaveSettings = async () => {
454
- if (!isBrowser()) return;
455
- try {
456
- // Transform changedSettings to wrap in uilayout structure for backend
457
- const wrappedSettings = {};
458
- Object.keys(changedSettings || {}).forEach(key => {
459
- const value = changedSettings[key];
460
- // Skip route paths
461
- if (key.startsWith('/')) return;
462
- // Check if it's a bracket key like [device].settingName or [route][device].settingName
463
- if (key.startsWith('[')) {
464
- // Extract bracket pattern and setting name
465
- // e.g., "[desktop].theme" or "[/route][desktop].navTheme"
466
- const match = key.match(/^(\[.+?\](?:\[.+?\])?)\.(.+)$/);
467
- if (match) {
468
- const bracketKey = match[1]; // e.g., "[desktop]" or "[/route][desktop]"
469
- const settingName = match[2]; // e.g., "theme"
470
- // Wrap in uilayout structure: [desktop].uilayout.theme
471
- const wrappedKey = `${bracketKey}.uilayout.${settingName}`;
472
- wrappedSettings[wrappedKey] = value;
473
- } else {
474
- // If pattern doesn't match, keep as is
475
- wrappedSettings[key] = value;
476
- }
477
- } else {
478
- // Non-bracket keys (like hiddenMenuKeys) - keep as is
479
- wrappedSettings[key] = value;
480
- }
481
- });
482
- // Prepare mutation variables
483
- const variables = {
484
- editingUri: resource,
485
- settings: wrappedSettings
486
- };
487
- const response = await writeSettingsMutation({
488
- variables
489
- });
490
- if (response.data) {
491
- console.log('Settings saved successfully');
492
- // Reset XState changedSettings (this will disable save button)
493
- actor.send({
494
- type: 'UISETTING_RESET_CHANGED_SETTINGS'
495
- });
496
- }
497
- } catch (err) {
498
- console.error('Failed to save settings:', err);
499
- }
500
- };
501
- const handleResetSettings = async () => {
502
- if (!isBrowser()) return;
503
- const confirmed = window.confirm('Are you sure you want to reset all settings? This will delete all customizations from database and cookies, then reload the page.');
504
- if (!confirmed) return;
505
- try {
506
- console.log('🔥 Resetting all settings...');
507
- // Step 1: Delete uiSettings from database using the resetApplicationSettings mutation
508
- try {
509
- await resetApplicationSettings({
510
- variables: {
511
- appId: config.APPLICATION_ID
512
- }
513
- });
514
- console.log('✅ Database uiSettings deleted');
515
- } catch (dbErr) {
516
- console.error('⚠️ Failed to delete database uiSettings:', dbErr);
517
- // Continue anyway to clear cookies
518
- }
519
- // Step 2: Clear cookies by sending DELETE request
520
- try {
521
- const response = await fetch('/resources/settings', {
522
- method: 'DELETE',
523
- headers: {
524
- 'Content-Type': 'application/json'
525
- }
526
- });
527
- const result = await response.json();
528
- console.log('✅ Settings cookies cleared');
529
- } catch (cookieErr) {
530
- console.error('⚠️ Failed to clear cookies:', cookieErr);
531
- }
532
- // Step 3: Reset XState machine
533
- actor.send({
534
- type: 'UISETTING_RESET_CHANGED_SETTINGS'
535
- });
536
- } catch (err) {
537
- console.error('❌ Error resetting settings:', err);
538
- alert('Failed to reset settings. Please try again.');
539
- }
540
- };
541
85
  useEffect(() => {
542
86
  if (isBrowser()) {
543
87
  const hasUrlParams = !!window.location.search;
544
- // Only call initState on first mount OR if there are URL params
545
88
  const shouldInit = !hasInitializedRef.current || hasUrlParams;
546
89
  if (shouldInit) {
547
90
  console.log('🔥 Calling initState:', {
@@ -553,12 +96,10 @@ const SettingDrawer = props => {
553
96
  console.log('⏭️ Skipping initState - already initialized and no URL params');
554
97
  }
555
98
  }
556
- }, [settingState, props.publicPath]); // settingState only changes when PUBLIC settings change
557
- // Update activeDeviceTab when isMobile changes
99
+ }, [settingState, props.publicPath]);
558
100
  useEffect(() => {
559
101
  setActiveDeviceTab(isMobile ? 'mobile' : 'desktop');
560
102
  }, [isMobile]);
561
- // Update machine when device tab changes
562
103
  useEffect(() => {
563
104
  if (actor) {
564
105
  actor.send({
@@ -567,7 +108,35 @@ const SettingDrawer = props => {
567
108
  });
568
109
  }
569
110
  }, [activeDeviceTab, actor]);
570
- const currentPathname = isBrowser() ? window.location.pathname : pathname || '';
111
+ // Helper functions
112
+ function handleSettingChange(key, value) {
113
+ const isGlobalSetting = key === 'hiddenMenuKeys' || key === 'hiddenMenuCategories' || key === 'applyToAllRoutes';
114
+ if (isGlobalSetting) {
115
+ console.log('🌐 Sending GLOBAL setting to actor:', {
116
+ key,
117
+ value
118
+ });
119
+ actor.send({
120
+ type: 'UISETTING_UPDATE',
121
+ value: {
122
+ [key]: value
123
+ }
124
+ });
125
+ return;
126
+ }
127
+ const bracketKey = applyToAllRoutes ? `[${deviceType}]` : `[${currentRoute}][${deviceType}]`;
128
+ const settingObject = parseSettingPath(key, value);
129
+ const nestedValue = {
130
+ [bracketKey]: settingObject
131
+ };
132
+ console.log('0️⃣ handleSettingChange with value: ', nestedValue);
133
+ actor.send({
134
+ type: 'UISETTING_UPDATE',
135
+ value: nestedValue
136
+ });
137
+ }
138
+ const getThemeValue = () => getSettingValue(settingState, 'theme', applyToAllRoutes, currentRoute, deviceType, 'default');
139
+ const getFontFamilyValue = () => getSettingValue(settingState, 'fontFamily', applyToAllRoutes, currentRoute, deviceType, 'Poppins, sans-serif');
571
140
  return jsx(Fragment, {
572
141
  children: settingState?.showSettingPanel && jsxs(Fragment, {
573
142
  children: [jsx("button", {
@@ -589,120 +158,20 @@ const SettingDrawer = props => {
589
158
  })
590
159
  }), jsxs("div", {
591
160
  className: clsx('fixed right-0 top-0 w-[20rem] transition-all duration-500 overflow-hidden overflow-y-auto z-50 p-4 min-h-full max-h-full', 'bg-white dark:bg-[#1f1f1f]', show ? 'opacity-100 visible' : 'w-0 opacity-0 invisible', 'shadow-lg'),
592
- children: [jsxs("div", {
593
- className: "flex flex-row items-center",
594
- children: [jsx("p", {
595
- className: "text-2xl mb-0 text-black dark:text-white",
596
- children: t('setting')
597
- }), jsx("div", {
598
- className: "flex-grow"
599
- }), jsx("button", {
600
- onClick: () => setShow(false),
601
- className: "bg-transparent border-none rounded-lg w-10 h-10 cursor-pointer mb-2 hover:bg-gray-200 dark:hover:bg-[#2a2a2a]",
602
- children: jsx(CloseIcon, {
603
- fontSize: '36px'
604
- })
605
- })]
161
+ children: [jsx(SettingsDrawerHeader, {
162
+ onClose: () => setShow(false)
606
163
  }), jsxs("div", {
607
164
  className: "mt-8 pb-8 border-b border-black dark:border-[#2a2b2a]",
608
165
  children: [jsx(MenuVisibilitySettings, {
609
166
  fullMenuData: fullMenuData,
610
167
  settings: settingState,
611
168
  changeSetting: handleSettingChange
612
- }), jsxs("div", {
613
- className: "flex items-center justify-between",
614
- children: [jsxs("div", {
615
- children: [jsx("p", {
616
- className: "text-sm text-black dark:text-white font-medium",
617
- children: "Apply to All Routes"
618
- }), jsx("p", {
619
- className: "text-xs text-gray-600 dark:text-gray-400",
620
- children: "When enabled, route-specific settings will apply to all routes instead of just the current route"
621
- })]
622
- }), jsxs("label", {
623
- className: "relative inline-flex items-center cursor-pointer",
624
- children: [jsx("input", {
625
- type: "checkbox",
626
- className: "sr-only peer",
627
- checked: applyToAllRoutes,
628
- onChange: e => setApplyToAllRoutes(e.target.checked)
629
- }), jsx("div", {
630
- className: "w-11 h-6 bg-gray-200 peer-focus:outline-none peer-focus:ring-4 peer-focus:ring-blue-300 dark:peer-focus:ring-blue-800 rounded-full peer dark:bg-gray-700 peer-checked:after:translate-x-full peer-checked:after:border-white after:content-[''] after:absolute after:top-[2px] after:left-[2px] after:bg-white after:border-gray-300 after:border after:rounded-full after:h-5 after:w-5 after:transition-all dark:border-gray-600 peer-checked:bg-blue-600"
631
- })]
632
- })]
633
- }), jsx("div", {
634
- className: "mt-4",
635
- children: jsxs("div", {
636
- className: "flex mb-4",
637
- children: [jsx("button", {
638
- className: `flex-1 py-2 px-4 text-sm font-medium transition-colors duration-200 rounded-l-lg border border-r-0 border-gray-300 ${activeDeviceTab === 'desktop' ? 'bg-blue-500 text-white border-blue-500' : 'bg-white text-gray-700 hover:bg-gray-50 dark:bg-gray-800 dark:text-gray-300 dark:hover:bg-gray-700'}`,
639
- onClick: () => setActiveDeviceTab('desktop'),
640
- children: jsxs("span", {
641
- className: "flex items-center justify-center",
642
- children: [jsxs("svg", {
643
- xmlns: "http://www.w3.org/2000/svg",
644
- width: "16",
645
- height: "16",
646
- viewBox: "0 0 24 24",
647
- fill: "none",
648
- stroke: "currentColor",
649
- strokeWidth: "2",
650
- strokeLinecap: "round",
651
- strokeLinejoin: "round",
652
- className: "mr-1",
653
- children: [jsx("rect", {
654
- x: "2",
655
- y: "3",
656
- width: "20",
657
- height: "14",
658
- rx: "2",
659
- ry: "2"
660
- }), jsx("line", {
661
- x1: "8",
662
- y1: "21",
663
- x2: "16",
664
- y2: "21"
665
- }), jsx("line", {
666
- x1: "12",
667
- y1: "17",
668
- x2: "12",
669
- y2: "21"
670
- })]
671
- }), t('desktop_tab')]
672
- })
673
- }), jsx("button", {
674
- className: `flex-1 py-2 px-4 text-sm font-medium transition-colors duration-200 rounded-r-lg border border-gray-300 ${activeDeviceTab === 'mobile' ? 'bg-blue-500 text-white border-blue-500' : 'bg-white text-gray-700 hover:bg-gray-50 dark:bg-gray-800 dark:text-gray-300 dark:hover:bg-gray-700'}`,
675
- onClick: () => setActiveDeviceTab('mobile'),
676
- children: jsxs("span", {
677
- className: "flex items-center justify-center",
678
- children: [jsxs("svg", {
679
- xmlns: "http://www.w3.org/2000/svg",
680
- width: "16",
681
- height: "16",
682
- viewBox: "0 0 24 24",
683
- fill: "none",
684
- stroke: "currentColor",
685
- strokeWidth: "2",
686
- strokeLinecap: "round",
687
- strokeLinejoin: "round",
688
- className: "mr-1",
689
- children: [jsx("rect", {
690
- x: "5",
691
- y: "2",
692
- width: "14",
693
- height: "20",
694
- rx: "2",
695
- ry: "2"
696
- }), jsx("line", {
697
- x1: "12",
698
- y1: "18",
699
- x2: "12",
700
- y2: "18"
701
- })]
702
- }), t('mobile_tab')]
703
- })
704
- })]
705
- })
169
+ }), jsx(ApplyToAllRoutesToggle, {
170
+ checked: applyToAllRoutes,
171
+ onChange: setApplyToAllRoutes
172
+ }), jsx(DeviceTabs, {
173
+ activeTab: activeDeviceTab,
174
+ onTabChange: setActiveDeviceTab
706
175
  })]
707
176
  }), jsxs("div", {
708
177
  className: "mt-8 pb-8 border-b border-black dark:border-[#2a2b2a]",
@@ -726,7 +195,7 @@ const SettingDrawer = props => {
726
195
  }), jsx(ThemeSelector, {
727
196
  value: getThemeValue(),
728
197
  onChange: value => handleSettingChange('theme', value),
729
- options: themeOptions
198
+ options: THEME_OPTIONS
730
199
  })]
731
200
  }), jsxs("div", {
732
201
  className: "mt-8 dark:border-[#2a2b2a]",
@@ -749,7 +218,7 @@ const SettingDrawer = props => {
749
218
  }), jsx(WebFontsSelector, {
750
219
  value: getFontFamilyValue(),
751
220
  onChange: value => handleSettingChange('fontFamily', value),
752
- options: fontOptions
221
+ options: FONT_OPTIONS
753
222
  })]
754
223
  })]
755
224
  }), jsxs("div", {
@@ -792,62 +261,16 @@ const SettingDrawer = props => {
792
261
  onSettingsChange: handleSettingChange,
793
262
  pathname: currentPathname
794
263
  })
795
- }), jsxs("div", {
796
- className: "bg-yellow-50 dark:bg-yellow-900 border border-yellow-200 dark:border-yellow-700 rounded-lg p-4 mt-4",
797
- children: [jsx("p", {
798
- className: "text-sm text-yellow-700 dark:text-yellow-200",
799
- children: "Setting panel shows in development environment only, please manually modify"
800
- }), jsxs("div", {
801
- className: "flex flex-wrap gap-2 mt-2",
802
- children: [jsx("button", {
803
- disabled: !changedSettings || Object.keys(changedSettings).length === 0,
804
- className: clsx('flex-1 min-w-[140px] sm:flex-none sm:w-auto px-4 py-2 rounded-lg border text-sm font-medium shadow-sm transition-all duration-200 focus:outline-none focus:ring-2 focus:ring-offset-2', !changedSettings || Object.keys(changedSettings).length === 0 ? 'border-gray-300 text-gray-500 bg-gray-50 cursor-not-allowed dark:border-gray-600 dark:text-gray-400 dark:bg-gray-800' : 'border-yellow-300 text-yellow-700 bg-yellow-50 hover:bg-yellow-100 active:bg-yellow-200 dark:border-yellow-600 dark:text-yellow-200 dark:bg-yellow-900/50 dark:hover:bg-yellow-900'),
805
- onClick: handleSaveSettings,
806
- children: jsx("span", {
807
- children: !changedSettings || Object.keys(changedSettings).length === 0 ? 'No Changes' : 'Save Settings'
808
- })
809
- }), jsx("button", {
810
- className: clsx('flex-1 min-w-[140px] sm:flex-none sm:w-auto px-4 py-2 rounded-lg border text-sm font-medium shadow-sm transition-all duration-200 focus:outline-none focus:ring-2 focus:ring-offset-2', copied ? 'border-green-300 text-green-700 bg-green-50 dark:border-green-600 dark:text-green-200 dark:bg-green-900' : 'border-yellow-300 text-yellow-700 bg-yellow-50 hover:bg-yellow-100 active:bg-yellow-200 dark:border-yellow-600 dark:text-yellow-200 dark:bg-yellow-900/50 dark:hover:bg-yellow-900'),
811
- onClick: handleCopySettings,
812
- children: copied ? jsxs(Fragment, {
813
- children: [jsx(CheckIcon, {
814
- className: "w-4 h-4"
815
- }), jsx("span", {
816
- children: "Copied!"
817
- })]
818
- }) : jsxs(Fragment, {
819
- children: [jsx(CopyIcon, {
820
- className: "w-4 h-4"
821
- }), jsx("span", {
822
- children: "Copy All Settings"
823
- })]
824
- })
825
- }), jsx("button", {
826
- className: clsx('flex-1 min-w-[140px] sm:flex-none sm:w-auto px-4 py-2 rounded-lg border text-sm font-medium shadow-sm transition-all duration-200 focus:outline-none focus:ring-2 focus:ring-offset-2', copiedModified ? 'border-green-300 text-green-700 bg-green-50 dark:border-green-600 dark:text-green-200 dark:bg-green-900' : 'border-blue-300 text-blue-700 bg-blue-50 hover:bg-blue-100 active:bg-blue-200 dark:border-blue-600 dark:text-blue-200 dark:bg-blue-900/50 dark:hover:bg-blue-900'),
827
- onClick: handleCopyModifiedSettings,
828
- children: copiedModified ? jsxs(Fragment, {
829
- children: [jsx(CheckIcon, {
830
- className: "w-4 h-4"
831
- }), jsx("span", {
832
- children: "Copied!"
833
- })]
834
- }) : jsxs(Fragment, {
835
- children: [jsx(CopyIcon, {
836
- className: "w-4 h-4"
837
- }), jsx("span", {
838
- children: "Copy Modified Settings"
839
- })]
840
- })
841
- }), jsx("button", {
842
- className: "flex-1 min-w-[140px] sm:flex-none sm:w-auto px-4 py-2 rounded-lg border border-red-300 text-red-700 bg-red-50 hover:bg-red-100 active:bg-red-200 dark:border-red-600 dark:text-red-200 dark:bg-red-900/50 dark:hover:bg-red-900 text-sm font-medium shadow-sm transition-all duration-200 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-red-500",
843
- onClick: handleResetSettings,
844
- children: jsx("span", {
845
- children: "\uD83D\uDD04 Reset All Settings"
846
- })
847
- })]
848
- })]
264
+ }), jsx(SettingsActions, {
265
+ hasChanges: changedSettings && Object.keys(changedSettings).length > 0,
266
+ copied: copied,
267
+ copiedModified: copiedModified,
268
+ onSave: handleSaveSettings,
269
+ onCopyAll: handleCopySettings,
270
+ onCopyModified: handleCopyModifiedSettings,
271
+ onReset: handleResetSettings
849
272
  })]
850
273
  })]
851
274
  })
852
275
  });
853
- };export{SettingDrawer};//# sourceMappingURL=SettingDrawer.js.map
276
+ }export{SettingDrawer};//# sourceMappingURL=SettingDrawer.js.map