@jhits/plugin-website 0.0.16 → 0.0.17

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (70) hide show
  1. package/dist/131._entry.js +2 -0
  2. package/dist/131._entry.js.LICENSE.txt +6 -0
  3. package/dist/303._entry.js +1 -0
  4. package/dist/_entry.js +2 -0
  5. package/dist/_entry.js.LICENSE.txt +6 -0
  6. package/dist/api/handler.d.ts.map +1 -1
  7. package/dist/api/handler.js +15 -4
  8. package/dist/remoteEntry.js +1 -0
  9. package/dist/server.js +232 -0
  10. package/dist/types/settings.d.ts +18 -11
  11. package/dist/types/settings.d.ts.map +1 -1
  12. package/dist/views/Settings/components/ContactInfoSection.d.ts +12 -0
  13. package/dist/views/Settings/components/ContactInfoSection.d.ts.map +1 -0
  14. package/dist/views/Settings/components/ContactInfoSection.js +14 -0
  15. package/dist/views/Settings/components/DomainLanguagesCard.d.ts +8 -0
  16. package/dist/views/Settings/components/DomainLanguagesCard.d.ts.map +1 -0
  17. package/dist/views/Settings/components/DomainLanguagesCard.js +12 -0
  18. package/dist/views/Settings/components/DomainLanguagesModal.d.ts +12 -0
  19. package/dist/views/Settings/components/DomainLanguagesModal.d.ts.map +1 -0
  20. package/dist/views/Settings/components/DomainLanguagesModal.js +38 -0
  21. package/dist/views/Settings/components/FlagIcon.d.ts +6 -0
  22. package/dist/views/Settings/components/FlagIcon.d.ts.map +1 -0
  23. package/dist/views/Settings/components/FlagIcon.js +11 -0
  24. package/dist/views/Settings/components/LaunchDateSection.d.ts +8 -0
  25. package/dist/views/Settings/components/LaunchDateSection.d.ts.map +1 -0
  26. package/dist/views/Settings/components/LaunchDateSection.js +22 -0
  27. package/dist/views/Settings/components/LocalesManagementCard.d.ts +8 -0
  28. package/dist/views/Settings/components/LocalesManagementCard.d.ts.map +1 -0
  29. package/dist/views/Settings/components/LocalesManagementCard.js +66 -0
  30. package/dist/views/Settings/components/LocalizedContentSection.d.ts +12 -0
  31. package/dist/views/Settings/components/LocalizedContentSection.d.ts.map +1 -0
  32. package/dist/views/Settings/components/LocalizedContentSection.js +17 -0
  33. package/dist/views/Settings/components/SeoIdentitySection.d.ts +9 -0
  34. package/dist/views/Settings/components/SeoIdentitySection.d.ts.map +1 -0
  35. package/dist/views/Settings/components/SeoIdentitySection.js +12 -0
  36. package/dist/views/Settings/components/SocialLinksSection.d.ts +13 -0
  37. package/dist/views/Settings/components/SocialLinksSection.d.ts.map +1 -0
  38. package/dist/views/Settings/components/SocialLinksSection.js +13 -0
  39. package/dist/views/Settings/components/StatusSection.d.ts +8 -0
  40. package/dist/views/Settings/components/StatusSection.d.ts.map +1 -0
  41. package/dist/views/Settings/components/StatusSection.js +27 -0
  42. package/dist/views/Settings/constants.d.ts +12 -0
  43. package/dist/views/Settings/constants.d.ts.map +1 -0
  44. package/dist/views/Settings/constants.js +23 -0
  45. package/dist/views/Settings/hooks/useWebsiteSettings.d.ts +24 -0
  46. package/dist/views/Settings/hooks/useWebsiteSettings.d.ts.map +1 -0
  47. package/dist/views/Settings/hooks/useWebsiteSettings.js +217 -0
  48. package/dist/views/Settings/types.d.ts +5 -0
  49. package/dist/views/Settings/types.d.ts.map +1 -0
  50. package/dist/views/Settings/types.js +1 -0
  51. package/dist/views/SettingsView.d.ts +3 -6
  52. package/dist/views/SettingsView.d.ts.map +1 -1
  53. package/dist/views/SettingsView.js +59 -262
  54. package/package.json +14 -10
  55. package/src/api/handler.ts +41 -4
  56. package/src/types/settings.ts +28 -12
  57. package/src/views/Settings/components/ContactInfoSection.tsx +109 -0
  58. package/src/views/Settings/components/DomainLanguagesCard.tsx +91 -0
  59. package/src/views/Settings/components/DomainLanguagesModal.tsx +216 -0
  60. package/src/views/Settings/components/FlagIcon.tsx +20 -0
  61. package/src/views/Settings/components/LaunchDateSection.tsx +111 -0
  62. package/src/views/Settings/components/LocalesManagementCard.tsx +198 -0
  63. package/src/views/Settings/components/LocalizedContentSection.tsx +155 -0
  64. package/src/views/Settings/components/SeoIdentitySection.tsx +98 -0
  65. package/src/views/Settings/components/SocialLinksSection.tsx +98 -0
  66. package/src/views/Settings/components/StatusSection.tsx +181 -0
  67. package/src/views/Settings/constants.ts +26 -0
  68. package/src/views/Settings/hooks/useWebsiteSettings.ts +240 -0
  69. package/src/views/Settings/types.ts +4 -0
  70. package/src/views/SettingsView.tsx +226 -674
@@ -0,0 +1,181 @@
1
+ import React from 'react';
2
+ import { motion } from 'framer-motion';
3
+ import { Settings2, Rocket, ShieldAlert, Cpu } from 'lucide-react';
4
+ import { WebsiteSettings } from '../../../types/settings';
5
+ import { clsx, type ClassValue } from 'clsx';
6
+ import { twMerge } from 'tailwind-merge';
7
+
8
+ function cn(...inputs: ClassValue[]) {
9
+ return twMerge(clsx(inputs));
10
+ }
11
+
12
+ interface StatusSectionProps {
13
+ settings: WebsiteSettings;
14
+ onUpdate: (updates: Partial<WebsiteSettings>) => void;
15
+ }
16
+
17
+ export function StatusSection({ settings, onUpdate }: StatusSectionProps) {
18
+ const isDev = process.env.NODE_ENV === 'development';
19
+
20
+ // Virtualize the published state if the date has passed
21
+ const hasLaunchDatePassed = settings.launch_date && new Date(settings.launch_date).getTime() <= Date.now();
22
+ const isLaunched = settings.launched || hasLaunchDatePassed;
23
+ const isMaintenance = hasLaunchDatePassed ? false : settings.maintenanceMode;
24
+
25
+ // AUTO-RELEASE UI REFRESH
26
+ React.useEffect(() => {
27
+ if (!settings.launch_date || hasLaunchDatePassed) return;
28
+ const launchTime = new Date(settings.launch_date).getTime();
29
+ if (launchTime <= Date.now()) return; // Already passed
30
+
31
+ const timer = setInterval(() => {
32
+ if (new Date(settings.launch_date!).getTime() <= Date.now()) {
33
+ // Time is up! Trigger a re-fetch of the settings to get the virtualized/persisted state
34
+ window.location.reload();
35
+ clearInterval(timer);
36
+ }
37
+ }, 1000);
38
+
39
+ return () => clearInterval(timer);
40
+ }, [settings.launch_date]);
41
+
42
+ const handleToggleLaunch = () => {
43
+ const newLaunched = !settings.launched;
44
+ onUpdate({
45
+ launched: newLaunched,
46
+ maintenanceMode: newLaunched ? false : settings.maintenanceMode
47
+ });
48
+ };
49
+
50
+ return (
51
+ <section className="space-y-12">
52
+ <div className="flex items-center gap-6">
53
+ <div className="size-14 rounded-2xl bg-primary/10 flex items-center justify-center text-primary border border-primary/20 shadow-inner">
54
+ <Settings2 size={28} />
55
+ </div>
56
+ <h3 className="text-4xl lg:text-5xl font-bold text-dashboard-text leading-none">
57
+ Site <span className="text-primary">Status</span>
58
+ </h3>
59
+ </div>
60
+
61
+ <div className="grid grid-cols-1 md:grid-cols-2 gap-8">
62
+ {/* 1. Launch Status */}
63
+ <motion.div
64
+ initial={{ opacity: 0, y: 20 }}
65
+ animate={{ opacity: 1, y: 0 }}
66
+ className="bg-dashboard-card/50 border border-dashboard-border/50 p-10 rounded-[3rem] group relative overflow-hidden"
67
+ >
68
+ <div className="absolute top-0 right-0 w-32 h-32 blur-3xl opacity-0 group-hover:opacity-10 transition-opacity bg-primary pointer-events-none" />
69
+
70
+ <div className="flex items-center justify-between mb-10">
71
+ <div className={cn(
72
+ "size-16 rounded-2xl flex items-center justify-center transition-all duration-500 border relative overflow-hidden shadow-inner",
73
+ isLaunched
74
+ ? "bg-emerald-500/10 border-emerald-500/20 text-emerald-500"
75
+ : "bg-neutral-500/5 border-neutral-500/10 text-neutral-400"
76
+ )}>
77
+ <Rocket size={28} className={cn("relative z-10 transition-transform duration-500 group-hover:scale-110", isLaunched && "animate-pulse")} />
78
+ </div>
79
+ <button
80
+ onClick={handleToggleLaunch}
81
+ className={cn(
82
+ "relative w-16 h-8 rounded-full transition-all duration-500 p-1 shadow-inner",
83
+ isLaunched ? "bg-emerald-500" : "bg-neutral-200 dark:bg-neutral-800"
84
+ )}
85
+ >
86
+ <div className={cn(
87
+ "w-6 h-6 bg-white rounded-full transition-transform duration-500 shadow-lg",
88
+ isLaunched ? "translate-x-8" : "translate-x-0"
89
+ )} />
90
+ </button>
91
+ </div>
92
+
93
+ <div>
94
+ <span className="text-[10px] font-bold text-primary uppercase tracking-[0.3em] mb-3 block opacity-60">Deployment Vector</span>
95
+ <h4 className="text-2xl font-bold text-dashboard-text mb-3">
96
+ {isLaunched ? 'System Published' : 'Private Mode'}
97
+ </h4>
98
+ <p className="text-sm text-neutral-500 dark:text-neutral-400 font-medium leading-relaxed">
99
+ {isLaunched
100
+ ? 'Your website is live and visible to all users across the world.'
101
+ : 'The website is currently restricted to internal use and development.'}
102
+ </p>
103
+ </div>
104
+ </motion.div>
105
+
106
+ {/* 2. Maintenance Status */}
107
+ <motion.div
108
+ initial={{ opacity: 0, y: 20 }}
109
+ animate={{ opacity: 1, y: 0 }}
110
+ transition={{ delay: 0.1 }}
111
+ className={cn(
112
+ "bg-dashboard-card/50 border border-dashboard-border/50 p-10 rounded-[3rem] group relative overflow-hidden transition-all duration-500",
113
+ isMaintenance && "border-orange-500/30 bg-orange-500/10"
114
+ )}
115
+ >
116
+ <div className="absolute top-0 right-0 w-32 h-32 blur-3xl opacity-0 group-hover:opacity-10 transition-opacity bg-orange-500 pointer-events-none" />
117
+
118
+ <div className="flex items-center justify-between mb-10">
119
+ <div className={cn(
120
+ "size-16 rounded-2xl flex items-center justify-center transition-all duration-500 border relative overflow-hidden shadow-inner",
121
+ isMaintenance
122
+ ? "bg-orange-500/10 border-orange-500/20 text-orange-500"
123
+ : "bg-neutral-500/5 border-neutral-500/10 text-neutral-400"
124
+ )}>
125
+ <ShieldAlert size={28} className="relative z-10 transition-transform duration-500 group-hover:scale-110" />
126
+ </div>
127
+ <button
128
+ onClick={() => onUpdate({ maintenanceMode: !settings.maintenanceMode })}
129
+ className={cn(
130
+ "relative w-16 h-8 rounded-full transition-all duration-500 p-1 shadow-inner",
131
+ isMaintenance ? "bg-orange-500" : "bg-neutral-200 dark:bg-neutral-800"
132
+ )}
133
+ >
134
+ <div className={cn(
135
+ "w-6 h-6 bg-white rounded-full transition-transform duration-500 shadow-lg",
136
+ isMaintenance ? "translate-x-8" : "translate-x-0"
137
+ )} />
138
+ </button>
139
+ </div>
140
+
141
+ <div>
142
+ <span className="text-[10px] font-bold text-orange-500 uppercase tracking-[0.3em] mb-3 block opacity-60">Operational Mode</span>
143
+ <h4 className="text-2xl font-bold text-dashboard-text mb-3">
144
+ Maintenance
145
+ </h4>
146
+ <p className="text-sm text-neutral-500 dark:text-neutral-400 font-medium leading-relaxed">
147
+ {isMaintenance
148
+ ? 'Visitors see a maintenance screen. You can still access the dashboard.'
149
+ : 'System is running normally. All features are available to public users.'}
150
+ </p>
151
+ </div>
152
+ </motion.div>
153
+ </div>
154
+
155
+ {/* 3. Developer Mode Info */}
156
+ {isDev && (
157
+ <motion.div
158
+ initial={{ opacity: 0 }}
159
+ animate={{ opacity: 1 }}
160
+ transition={{ delay: 0.2 }}
161
+ className="bg-dashboard-card/50 border border-dashboard-border/50 p-10 rounded-[3rem] relative overflow-hidden group"
162
+ >
163
+ <div className="absolute top-0 right-0 p-10 opacity-[0.03] group-hover:opacity-[0.07] transition-opacity">
164
+ <Cpu size={160} />
165
+ </div>
166
+ <div className="flex flex-col md:flex-row items-start md:items-center gap-8 relative z-10">
167
+ <div className="size-14 rounded-2xl bg-primary/10 flex items-center justify-center text-primary shrink-0 border border-primary/20">
168
+ <Cpu size={24} />
169
+ </div>
170
+ <div>
171
+ <span className="text-[10px] font-bold uppercase tracking-[0.4em] text-primary mb-2 block">Developer Engine Protocol</span>
172
+ <p className="text-sm text-neutral-500 dark:text-neutral-400 font-medium leading-relaxed max-w-3xl">
173
+ Authentication and status checks are bypassed during development. Changes made here will affect the production environment once deployed.
174
+ </p>
175
+ </div>
176
+ </div>
177
+ </motion.div>
178
+ )}
179
+ </section>
180
+ );
181
+ }
@@ -0,0 +1,26 @@
1
+ import React from 'react';
2
+ import { FaFacebook, FaInstagram, FaLinkedin, FaPinterest, FaTiktok } from 'react-icons/fa';
3
+ import { FaXTwitter } from 'react-icons/fa6';
4
+ import { LocaleDefinition } from '../../types/settings';
5
+
6
+ /**
7
+ * Popular Locale Suggestions
8
+ * These are used for "Quick Add" in the UI.
9
+ */
10
+ export const GLOBAL_LOCALE_DATABASE: LocaleDefinition[] = [
11
+ { code: 'en', name: 'English', countryCode: 'gb' },
12
+ { code: 'sv', name: 'Swedish', countryCode: 'se' },
13
+ { code: 'nl', name: 'Dutch', countryCode: 'nl' },
14
+ { code: 'de', name: 'German', countryCode: 'de' },
15
+ { code: 'fr', name: 'French', countryCode: 'fr' },
16
+ { code: 'es', name: 'Spanish', countryCode: 'es' },
17
+ ];
18
+
19
+ export const AVAILABLE_PLATFORMS = [
20
+ { name: 'Instagram', icon: React.createElement(FaInstagram, { size: 18 }) },
21
+ { name: 'Facebook', icon: React.createElement(FaFacebook, { size: 18 }) },
22
+ { name: 'Twitter', icon: React.createElement(FaXTwitter, { size: 18 }) },
23
+ { name: 'Pinterest', icon: React.createElement(FaPinterest, { size: 18 }) },
24
+ { name: 'LinkedIn', icon: React.createElement(FaLinkedin, { size: 18 }) },
25
+ { name: 'TikTok', icon: React.createElement(FaTiktok, { size: 18 }) },
26
+ ];
@@ -0,0 +1,240 @@
1
+ import { useState, useEffect } from 'react';
2
+ import {
3
+ WebsiteSettings,
4
+ LocalizedContactInfo,
5
+ LocalizedSocialLink,
6
+ DomainLocaleConfig,
7
+ LocaleDefinition,
8
+ LocalizedIdentity
9
+ } from '../../../types/settings';
10
+
11
+ export function useWebsiteSettings(siteId: string) {
12
+ const [isLoading, setIsLoading] = useState(true);
13
+ const [isSaving, setIsSaving] = useState(false);
14
+ const [showSuccess, setShowSuccess] = useState(false);
15
+ const [activeTab, setActiveTab] = useState<string>('');
16
+ const [showDomainModal, setShowDomainModal] = useState(false);
17
+
18
+ // Initial data from server to compare for "dirty" state
19
+ const [initialSettings, setInitialSettings] = useState<string>('');
20
+
21
+ const [settings, setSettings] = useState<WebsiteSettings>({
22
+ identifier: 'site_config',
23
+ contactEmail: '',
24
+ smtpUser: '',
25
+ maintenanceMode: false,
26
+ launched: false,
27
+ launch_date: '',
28
+ supportedLocales: [],
29
+ localizedIdentity: {},
30
+ localizedContactInfo: {},
31
+ localizedSocials: {},
32
+ domainLocaleConfig: [],
33
+ });
34
+
35
+ const isDirty = initialSettings !== JSON.stringify(settings);
36
+ const activeLocales = settings.supportedLocales;
37
+
38
+ // Ensure activeTab is always valid
39
+ useEffect(() => {
40
+ if (activeLocales.length > 0) {
41
+ if (!activeTab || !activeLocales.some(l => l.code === activeTab)) {
42
+ setActiveTab(activeLocales[0].code);
43
+ }
44
+ }
45
+ }, [activeLocales, activeTab]);
46
+
47
+ // Fetch settings on load
48
+ useEffect(() => {
49
+ const fetchSettings = async () => {
50
+ try {
51
+ setIsLoading(true);
52
+ const response = await fetch('/api/plugin-website/settings', {
53
+ credentials: 'include',
54
+ cache: 'no-store'
55
+ });
56
+ if (!response.ok) throw new Error('Failed to fetch settings');
57
+ const data = await response.json();
58
+
59
+ if (data && data.identifier) {
60
+ let launchDate = '';
61
+ if (data.launch_date) {
62
+ const date = new Date(data.launch_date);
63
+ if (!isNaN(date.getTime())) {
64
+ const year = date.getFullYear();
65
+ const month = String(date.getMonth() + 1).padStart(2, '0');
66
+ const day = String(date.getDate()).padStart(2, '0');
67
+ const hours = String(date.getHours()).padStart(2, '0');
68
+ const minutes = String(date.getMinutes()).padStart(2, '0');
69
+ launchDate = `${year}-${month}-${day}T${hours}:${minutes}`;
70
+ }
71
+ }
72
+
73
+ const loaded = {
74
+ ...data,
75
+ launch_date: launchDate,
76
+ supportedLocales: data.supportedLocales || [],
77
+ localizedIdentity: data.localizedIdentity || {},
78
+ localizedContactInfo: data.localizedContactInfo || {},
79
+ localizedSocials: data.localizedSocials || {},
80
+ domainLocaleConfig: data.domainLocaleConfig || [],
81
+ };
82
+
83
+ setSettings(loaded);
84
+ setInitialSettings(JSON.stringify(loaded));
85
+
86
+ if (loaded.supportedLocales.length > 0) {
87
+ setActiveTab(loaded.supportedLocales[0].code);
88
+ }
89
+ }
90
+ } catch (error) {
91
+ console.error('Failed to load settings:', error);
92
+ } finally {
93
+ setIsLoading(false);
94
+ }
95
+ };
96
+ fetchSettings();
97
+ }, [siteId]);
98
+
99
+ const handleUpdateSettings = (updates: Partial<WebsiteSettings>) => {
100
+ setSettings(prev => ({ ...prev, ...updates }));
101
+ };
102
+
103
+ const handleUpdateLocalizedIdentity = (field: keyof LocalizedIdentity, value: string) => {
104
+ if (!activeTab) return;
105
+ setSettings(prev => ({
106
+ ...prev,
107
+ localizedIdentity: {
108
+ ...prev.localizedIdentity,
109
+ [activeTab]: { ...(prev.localizedIdentity?.[activeTab] || {}), [field]: value },
110
+ },
111
+ }));
112
+ };
113
+
114
+ const handleUpdateLocalizedContact = (field: keyof LocalizedContactInfo, value: string) => {
115
+ if (!activeTab) return;
116
+ setSettings(prev => ({
117
+ ...prev,
118
+ localizedContactInfo: {
119
+ ...prev.localizedContactInfo,
120
+ [activeTab]: { ...(prev.localizedContactInfo?.[activeTab] || {}), [field]: value },
121
+ },
122
+ }));
123
+ };
124
+
125
+ const handleAddLocalizedSocial = () => {
126
+ if (!activeTab) return;
127
+ const currentSocials = settings.localizedSocials?.[activeTab] || [];
128
+ const newId = Date.now();
129
+ setSettings(prev => ({
130
+ ...prev,
131
+ localizedSocials: {
132
+ ...prev.localizedSocials,
133
+ [activeTab]: [...currentSocials, { id: newId, platform: '', url: '' }],
134
+ },
135
+ }));
136
+ };
137
+
138
+ const handleUpdateLocalizedSocial = (id: number, field: string, value: string) => {
139
+ if (!activeTab) return;
140
+ const currentSocials = settings.localizedSocials?.[activeTab] || [];
141
+ setSettings(prev => ({
142
+ ...prev,
143
+ localizedSocials: {
144
+ ...prev.localizedSocials,
145
+ [activeTab]: currentSocials.map(s => s.id === id ? { ...s, [field]: value } : s),
146
+ },
147
+ }));
148
+ };
149
+
150
+ const handleRemoveLocalizedSocial = (id: number) => {
151
+ if (!activeTab) return;
152
+ const currentSocials = settings.localizedSocials?.[activeTab] || [];
153
+ setSettings(prev => ({
154
+ ...prev,
155
+ localizedSocials: {
156
+ ...prev.localizedSocials,
157
+ [activeTab]: currentSocials.filter(s => s.id !== id),
158
+ },
159
+ }));
160
+ };
161
+
162
+ const handleUpdateLocales = (locales: LocaleDefinition[]) => {
163
+ setSettings(prev => ({ ...prev, supportedLocales: locales }));
164
+ };
165
+
166
+ const handleReset = () => {
167
+ if (initialSettings) {
168
+ setSettings(JSON.parse(initialSettings));
169
+ }
170
+ };
171
+
172
+ const handleSave = async () => {
173
+ if (settings.supportedLocales.length === 0) {
174
+ alert('At least one language must be enabled.');
175
+ return;
176
+ }
177
+
178
+ try {
179
+ setIsSaving(true);
180
+ const response = await fetch('/api/plugin-website/settings', {
181
+ method: 'POST',
182
+ headers: { 'Content-Type': 'application/json' },
183
+ credentials: 'include',
184
+ body: JSON.stringify(settings),
185
+ });
186
+
187
+ if (!response.ok) throw new Error('Failed to save settings');
188
+
189
+ setInitialSettings(JSON.stringify(settings));
190
+ setShowSuccess(true);
191
+ setTimeout(() => setShowSuccess(false), 3000);
192
+ } catch (error: any) {
193
+ console.error('Failed to save settings:', error);
194
+ } finally {
195
+ setIsSaving(false);
196
+ }
197
+ };
198
+
199
+ const saveDomainConfigAndClose = async (config: DomainLocaleConfig[]) => {
200
+ const newSettings = { ...settings, domainLocaleConfig: config };
201
+ setSettings(newSettings);
202
+ setShowDomainModal(false);
203
+ try {
204
+ await fetch('/api/plugin-website/settings', {
205
+ method: 'POST',
206
+ headers: { 'Content-Type': 'application/json' },
207
+ credentials: 'include',
208
+ body: JSON.stringify(newSettings),
209
+ });
210
+ setInitialSettings(JSON.stringify(newSettings));
211
+ setShowSuccess(true);
212
+ setTimeout(() => setShowSuccess(false), 3000);
213
+ } catch (e) {
214
+ console.error('Auto-save failed');
215
+ }
216
+ };
217
+
218
+ return {
219
+ settings,
220
+ isLoading,
221
+ isSaving,
222
+ isDirty,
223
+ showSuccess,
224
+ activeTab,
225
+ setActiveTab,
226
+ activeLocales,
227
+ showDomainModal,
228
+ setShowDomainModal,
229
+ handleUpdateSettings,
230
+ handleUpdateLocalizedIdentity,
231
+ handleUpdateLocalizedContact,
232
+ handleAddLocalizedSocial,
233
+ handleUpdateLocalizedSocial,
234
+ handleRemoveLocalizedSocial,
235
+ handleUpdateLocales,
236
+ handleSave,
237
+ handleReset,
238
+ saveDomainConfigAndClose
239
+ };
240
+ }
@@ -0,0 +1,4 @@
1
+ export interface SettingsViewProps {
2
+ siteId: string;
3
+ locale: string;
4
+ }