@shellui/core 0.0.4

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 (247) hide show
  1. package/README.md +17 -0
  2. package/dist/ContentView-CZG-ro_B.js +146 -0
  3. package/dist/ContentView-CZG-ro_B.js.map +1 -0
  4. package/dist/CookiePreferencesView-MhO9FO-4.js +213 -0
  5. package/dist/CookiePreferencesView-MhO9FO-4.js.map +1 -0
  6. package/dist/DefaultLayout-Dbb3uJED.js +394 -0
  7. package/dist/DefaultLayout-Dbb3uJED.js.map +1 -0
  8. package/dist/FullscreenLayout-1SgPHWw-.js +30 -0
  9. package/dist/FullscreenLayout-1SgPHWw-.js.map +1 -0
  10. package/dist/HomeView-DYU-O_Il.js +21 -0
  11. package/dist/HomeView-DYU-O_Il.js.map +1 -0
  12. package/dist/NotFoundView-CeYjJNg0.js +52 -0
  13. package/dist/NotFoundView-CeYjJNg0.js.map +1 -0
  14. package/dist/OverlayShell-pzbqQW25.js +642 -0
  15. package/dist/OverlayShell-pzbqQW25.js.map +1 -0
  16. package/dist/SettingsView-Bndrta44.js +2207 -0
  17. package/dist/SettingsView-Bndrta44.js.map +1 -0
  18. package/dist/ViewRoute-ChSPabOy.js +32 -0
  19. package/dist/ViewRoute-ChSPabOy.js.map +1 -0
  20. package/dist/WindowsLayout-CXGNPKoY.js +633 -0
  21. package/dist/WindowsLayout-CXGNPKoY.js.map +1 -0
  22. package/dist/app.d.ts +3 -0
  23. package/dist/app.d.ts.map +1 -0
  24. package/dist/components/ContentView.d.ts +10 -0
  25. package/dist/components/ContentView.d.ts.map +1 -0
  26. package/dist/components/HomeView.d.ts +2 -0
  27. package/dist/components/HomeView.d.ts.map +1 -0
  28. package/dist/components/LoadingOverlay.d.ts +2 -0
  29. package/dist/components/LoadingOverlay.d.ts.map +1 -0
  30. package/dist/components/NotFoundView.d.ts +2 -0
  31. package/dist/components/NotFoundView.d.ts.map +1 -0
  32. package/dist/components/RouteErrorBoundary.d.ts +2 -0
  33. package/dist/components/RouteErrorBoundary.d.ts.map +1 -0
  34. package/dist/components/ViewRoute.d.ts +7 -0
  35. package/dist/components/ViewRoute.d.ts.map +1 -0
  36. package/dist/components/ui/alert-dialog.d.ts +32 -0
  37. package/dist/components/ui/alert-dialog.d.ts.map +1 -0
  38. package/dist/components/ui/breadcrumb.d.ts +20 -0
  39. package/dist/components/ui/breadcrumb.d.ts.map +1 -0
  40. package/dist/components/ui/button-group.d.ts +7 -0
  41. package/dist/components/ui/button-group.d.ts.map +1 -0
  42. package/dist/components/ui/button.d.ts +12 -0
  43. package/dist/components/ui/button.d.ts.map +1 -0
  44. package/dist/components/ui/dialog.d.ts +24 -0
  45. package/dist/components/ui/dialog.d.ts.map +1 -0
  46. package/dist/components/ui/drawer.d.ts +38 -0
  47. package/dist/components/ui/drawer.d.ts.map +1 -0
  48. package/dist/components/ui/select.d.ts +5 -0
  49. package/dist/components/ui/select.d.ts.map +1 -0
  50. package/dist/components/ui/sidebar.d.ts +46 -0
  51. package/dist/components/ui/sidebar.d.ts.map +1 -0
  52. package/dist/components/ui/sonner.d.ts +6 -0
  53. package/dist/components/ui/sonner.d.ts.map +1 -0
  54. package/dist/components/ui/switch.d.ts +8 -0
  55. package/dist/components/ui/switch.d.ts.map +1 -0
  56. package/dist/constants/urls.d.ts +6 -0
  57. package/dist/constants/urls.d.ts.map +1 -0
  58. package/dist/constants/urls.js +8 -0
  59. package/dist/constants/urls.js.map +1 -0
  60. package/dist/features/alertDialog/DialogContext.d.ts +12 -0
  61. package/dist/features/alertDialog/DialogContext.d.ts.map +1 -0
  62. package/dist/features/config/ConfigProvider.d.ts +15 -0
  63. package/dist/features/config/ConfigProvider.d.ts.map +1 -0
  64. package/dist/features/config/types.d.ts +177 -0
  65. package/dist/features/config/types.d.ts.map +1 -0
  66. package/dist/features/config/useConfig.d.ts +8 -0
  67. package/dist/features/config/useConfig.d.ts.map +1 -0
  68. package/dist/features/cookieConsent/CookieConsentModal.d.ts +6 -0
  69. package/dist/features/cookieConsent/CookieConsentModal.d.ts.map +1 -0
  70. package/dist/features/cookieConsent/CookiePreferencesView.d.ts +2 -0
  71. package/dist/features/cookieConsent/CookiePreferencesView.d.ts.map +1 -0
  72. package/dist/features/cookieConsent/cookieConsent.d.ts +22 -0
  73. package/dist/features/cookieConsent/cookieConsent.d.ts.map +1 -0
  74. package/dist/features/cookieConsent/useCookieConsent.d.ts +15 -0
  75. package/dist/features/cookieConsent/useCookieConsent.d.ts.map +1 -0
  76. package/dist/features/drawer/DrawerContext.d.ts +24 -0
  77. package/dist/features/drawer/DrawerContext.d.ts.map +1 -0
  78. package/dist/features/layouts/AppLayout.d.ts +12 -0
  79. package/dist/features/layouts/AppLayout.d.ts.map +1 -0
  80. package/dist/features/layouts/DefaultLayout.d.ts +10 -0
  81. package/dist/features/layouts/DefaultLayout.d.ts.map +1 -0
  82. package/dist/features/layouts/FullscreenLayout.d.ts +9 -0
  83. package/dist/features/layouts/FullscreenLayout.d.ts.map +1 -0
  84. package/dist/features/layouts/LayoutProviders.d.ts +9 -0
  85. package/dist/features/layouts/LayoutProviders.d.ts.map +1 -0
  86. package/dist/features/layouts/OverlayShell.d.ts +10 -0
  87. package/dist/features/layouts/OverlayShell.d.ts.map +1 -0
  88. package/dist/features/layouts/WindowsLayout.d.ts +24 -0
  89. package/dist/features/layouts/WindowsLayout.d.ts.map +1 -0
  90. package/dist/features/layouts/utils.d.ts +16 -0
  91. package/dist/features/layouts/utils.d.ts.map +1 -0
  92. package/dist/features/modal/ModalContext.d.ts +20 -0
  93. package/dist/features/modal/ModalContext.d.ts.map +1 -0
  94. package/dist/features/sentry/initSentry.d.ts +14 -0
  95. package/dist/features/sentry/initSentry.d.ts.map +1 -0
  96. package/dist/features/settings/SettingsContext.d.ts +10 -0
  97. package/dist/features/settings/SettingsContext.d.ts.map +1 -0
  98. package/dist/features/settings/SettingsIcons.d.ts +22 -0
  99. package/dist/features/settings/SettingsIcons.d.ts.map +1 -0
  100. package/dist/features/settings/SettingsProvider.d.ts +5 -0
  101. package/dist/features/settings/SettingsProvider.d.ts.map +1 -0
  102. package/dist/features/settings/SettingsRoutes.d.ts +7 -0
  103. package/dist/features/settings/SettingsRoutes.d.ts.map +1 -0
  104. package/dist/features/settings/SettingsView.d.ts +2 -0
  105. package/dist/features/settings/SettingsView.d.ts.map +1 -0
  106. package/dist/features/settings/components/Advanced.d.ts +2 -0
  107. package/dist/features/settings/components/Advanced.d.ts.map +1 -0
  108. package/dist/features/settings/components/Appearance.d.ts +2 -0
  109. package/dist/features/settings/components/Appearance.d.ts.map +1 -0
  110. package/dist/features/settings/components/DataPrivacy.d.ts +2 -0
  111. package/dist/features/settings/components/DataPrivacy.d.ts.map +1 -0
  112. package/dist/features/settings/components/Develop.d.ts +2 -0
  113. package/dist/features/settings/components/Develop.d.ts.map +1 -0
  114. package/dist/features/settings/components/LanguageAndRegion.d.ts +2 -0
  115. package/dist/features/settings/components/LanguageAndRegion.d.ts.map +1 -0
  116. package/dist/features/settings/components/ServiceWorker.d.ts +2 -0
  117. package/dist/features/settings/components/ServiceWorker.d.ts.map +1 -0
  118. package/dist/features/settings/components/UpdateApp.d.ts +2 -0
  119. package/dist/features/settings/components/UpdateApp.d.ts.map +1 -0
  120. package/dist/features/settings/components/develop/DialogTestButtons.d.ts +2 -0
  121. package/dist/features/settings/components/develop/DialogTestButtons.d.ts.map +1 -0
  122. package/dist/features/settings/components/develop/DrawerTestButtons.d.ts +2 -0
  123. package/dist/features/settings/components/develop/DrawerTestButtons.d.ts.map +1 -0
  124. package/dist/features/settings/components/develop/ModalTestButtons.d.ts +2 -0
  125. package/dist/features/settings/components/develop/ModalTestButtons.d.ts.map +1 -0
  126. package/dist/features/settings/components/develop/ToastTestButtons.d.ts +2 -0
  127. package/dist/features/settings/components/develop/ToastTestButtons.d.ts.map +1 -0
  128. package/dist/features/settings/hooks/useSettings.d.ts +2 -0
  129. package/dist/features/settings/hooks/useSettings.d.ts.map +1 -0
  130. package/dist/features/sonner/SonnerContext.d.ts +29 -0
  131. package/dist/features/sonner/SonnerContext.d.ts.map +1 -0
  132. package/dist/features/theme/ThemeProvider.d.ts +11 -0
  133. package/dist/features/theme/ThemeProvider.d.ts.map +1 -0
  134. package/dist/features/theme/themes.d.ts +114 -0
  135. package/dist/features/theme/themes.d.ts.map +1 -0
  136. package/dist/features/theme/useTheme.d.ts +10 -0
  137. package/dist/features/theme/useTheme.d.ts.map +1 -0
  138. package/dist/i18n/I18nProvider.d.ts +9 -0
  139. package/dist/i18n/I18nProvider.d.ts.map +1 -0
  140. package/dist/i18n/config.d.ts +23 -0
  141. package/dist/i18n/config.d.ts.map +1 -0
  142. package/dist/i18n/translations/en/common.json.d.ts +19 -0
  143. package/dist/i18n/translations/en/cookieConsent.json.d.ts +53 -0
  144. package/dist/i18n/translations/en/settings.json.d.ts +358 -0
  145. package/dist/i18n/translations/fr/common.json.d.ts +19 -0
  146. package/dist/i18n/translations/fr/cookieConsent.json.d.ts +53 -0
  147. package/dist/i18n/translations/fr/settings.json.d.ts +358 -0
  148. package/dist/index-lmRk5L6z.js +2160 -0
  149. package/dist/index-lmRk5L6z.js.map +1 -0
  150. package/dist/index.d.ts +7 -0
  151. package/dist/index.d.ts.map +1 -0
  152. package/dist/index.js +12 -0
  153. package/dist/index.js.map +1 -0
  154. package/dist/lib/utils.d.ts +3 -0
  155. package/dist/lib/utils.d.ts.map +1 -0
  156. package/dist/lib/z-index.d.ts +29 -0
  157. package/dist/lib/z-index.d.ts.map +1 -0
  158. package/dist/router/router.d.ts +3 -0
  159. package/dist/router/router.d.ts.map +1 -0
  160. package/dist/router/routes.d.ts +4 -0
  161. package/dist/router/routes.d.ts.map +1 -0
  162. package/dist/sidebar-ClIeZ2zb.js +303 -0
  163. package/dist/sidebar-ClIeZ2zb.js.map +1 -0
  164. package/dist/style.css +1 -0
  165. package/dist/switch-8SzUJz7Q.js +44 -0
  166. package/dist/switch-8SzUJz7Q.js.map +1 -0
  167. package/dist/types.js +2 -0
  168. package/dist/types.js.map +1 -0
  169. package/package.json +93 -0
  170. package/postcss.config.js +6 -0
  171. package/src/app.tsx +119 -0
  172. package/src/components/ContentView.tsx +258 -0
  173. package/src/components/HomeView.tsx +19 -0
  174. package/src/components/LoadingOverlay.tsx +12 -0
  175. package/src/components/NotFoundView.tsx +84 -0
  176. package/src/components/RouteErrorBoundary.tsx +95 -0
  177. package/src/components/ViewRoute.tsx +47 -0
  178. package/src/components/ui/alert-dialog.tsx +181 -0
  179. package/src/components/ui/breadcrumb.tsx +155 -0
  180. package/src/components/ui/button-group.tsx +52 -0
  181. package/src/components/ui/button.tsx +51 -0
  182. package/src/components/ui/dialog.tsx +160 -0
  183. package/src/components/ui/drawer.tsx +200 -0
  184. package/src/components/ui/select.tsx +24 -0
  185. package/src/components/ui/sidebar.tsx +406 -0
  186. package/src/components/ui/sonner.tsx +36 -0
  187. package/src/components/ui/switch.tsx +45 -0
  188. package/src/constants/urls.ts +4 -0
  189. package/src/features/alertDialog/DialogContext.tsx +468 -0
  190. package/src/features/config/ConfigProvider.ts +96 -0
  191. package/src/features/config/types.ts +195 -0
  192. package/src/features/config/useConfig.ts +15 -0
  193. package/src/features/cookieConsent/CookieConsentModal.tsx +122 -0
  194. package/src/features/cookieConsent/CookiePreferencesView.tsx +328 -0
  195. package/src/features/cookieConsent/cookieConsent.ts +84 -0
  196. package/src/features/cookieConsent/useCookieConsent.ts +39 -0
  197. package/src/features/drawer/DrawerContext.tsx +116 -0
  198. package/src/features/layouts/AppLayout.tsx +63 -0
  199. package/src/features/layouts/DefaultLayout.tsx +625 -0
  200. package/src/features/layouts/FullscreenLayout.tsx +55 -0
  201. package/src/features/layouts/LayoutProviders.tsx +20 -0
  202. package/src/features/layouts/OverlayShell.tsx +171 -0
  203. package/src/features/layouts/WindowsLayout.tsx +860 -0
  204. package/src/features/layouts/utils.ts +99 -0
  205. package/src/features/modal/ModalContext.tsx +112 -0
  206. package/src/features/sentry/initSentry.ts +72 -0
  207. package/src/features/settings/SettingsContext.tsx +19 -0
  208. package/src/features/settings/SettingsIcons.tsx +452 -0
  209. package/src/features/settings/SettingsProvider.tsx +341 -0
  210. package/src/features/settings/SettingsRoutes.tsx +66 -0
  211. package/src/features/settings/SettingsView.tsx +327 -0
  212. package/src/features/settings/components/Advanced.tsx +128 -0
  213. package/src/features/settings/components/Appearance.tsx +306 -0
  214. package/src/features/settings/components/DataPrivacy.tsx +142 -0
  215. package/src/features/settings/components/Develop.tsx +174 -0
  216. package/src/features/settings/components/LanguageAndRegion.tsx +329 -0
  217. package/src/features/settings/components/ServiceWorker.tsx +363 -0
  218. package/src/features/settings/components/UpdateApp.tsx +206 -0
  219. package/src/features/settings/components/develop/DialogTestButtons.tsx +137 -0
  220. package/src/features/settings/components/develop/DrawerTestButtons.tsx +67 -0
  221. package/src/features/settings/components/develop/ModalTestButtons.tsx +30 -0
  222. package/src/features/settings/components/develop/ToastTestButtons.tsx +179 -0
  223. package/src/features/settings/hooks/useSettings.tsx +10 -0
  224. package/src/features/sonner/SonnerContext.tsx +286 -0
  225. package/src/features/theme/ThemeProvider.tsx +16 -0
  226. package/src/features/theme/themes.ts +561 -0
  227. package/src/features/theme/useTheme.tsx +71 -0
  228. package/src/i18n/I18nProvider.tsx +32 -0
  229. package/src/i18n/config.ts +107 -0
  230. package/src/i18n/translations/en/common.json +16 -0
  231. package/src/i18n/translations/en/cookieConsent.json +50 -0
  232. package/src/i18n/translations/en/settings.json +355 -0
  233. package/src/i18n/translations/fr/common.json +16 -0
  234. package/src/i18n/translations/fr/cookieConsent.json +50 -0
  235. package/src/i18n/translations/fr/settings.json +355 -0
  236. package/src/index.css +412 -0
  237. package/src/index.html +100 -0
  238. package/src/index.ts +31 -0
  239. package/src/lib/utils.ts +6 -0
  240. package/src/lib/z-index.ts +29 -0
  241. package/src/main.tsx +26 -0
  242. package/src/router/router.tsx +8 -0
  243. package/src/router/routes.tsx +115 -0
  244. package/src/service-worker/register.ts +1199 -0
  245. package/src/service-worker/sw-dev.ts +87 -0
  246. package/src/service-worker/sw.ts +105 -0
  247. package/tailwind.config.js +60 -0
@@ -0,0 +1,206 @@
1
+ import { useTranslation } from 'react-i18next';
2
+ import { useConfig } from '@/features/config/useConfig';
3
+ import { useSettings } from '../hooks/useSettings';
4
+ import { Button } from '@/components/ui/button';
5
+ import {
6
+ isTauri,
7
+ getServiceWorkerStatus,
8
+ addStatusListener,
9
+ checkForServiceWorkerUpdate,
10
+ updateServiceWorker,
11
+ } from '@/service-worker/register';
12
+ import { shellui, getLogger } from '@shellui/sdk';
13
+ import { CheckIcon } from '../SettingsIcons';
14
+ import { useState, useEffect } from 'react';
15
+
16
+ const logger = getLogger('shellcore');
17
+
18
+ export const UpdateApp = () => {
19
+ const { t } = useTranslation('settings');
20
+ const { config } = useConfig();
21
+ const { settings } = useSettings();
22
+ const [updateAvailable, setUpdateAvailable] = useState(false);
23
+ const [checking, setChecking] = useState(false);
24
+ const [showUpToDateInButton, setShowUpToDateInButton] = useState(false);
25
+ const [checkError, setCheckError] = useState(false);
26
+
27
+ const serviceWorkerEnabled = settings?.serviceWorker?.enabled ?? true;
28
+
29
+ useEffect(() => {
30
+ if (isTauri()) return;
31
+ const load = async () => {
32
+ const status = await getServiceWorkerStatus();
33
+ setUpdateAvailable(status.updateAvailable);
34
+ };
35
+ load();
36
+ const unsubscribe = addStatusListener((status) => {
37
+ setUpdateAvailable(status.updateAvailable);
38
+ // If an update becomes available, hide the "You are up to date" message and clear any errors
39
+ if (status.updateAvailable) {
40
+ setShowUpToDateInButton(false);
41
+ setCheckError(false);
42
+ }
43
+ });
44
+ return unsubscribe;
45
+ }, []);
46
+
47
+ const handleCheckForUpdate = async () => {
48
+ if (isTauri()) return;
49
+ setShowUpToDateInButton(false);
50
+ setCheckError(false);
51
+ setChecking(true);
52
+ try {
53
+ // Check current status before triggering update check
54
+ const initialStatus = await getServiceWorkerStatus();
55
+
56
+ // If update is already available, don't show "You are up to date"
57
+ if (initialStatus.updateAvailable) {
58
+ return;
59
+ }
60
+
61
+ // Trigger update check
62
+ await checkForServiceWorkerUpdate();
63
+
64
+ // Wait a bit for the update check to complete and status to update
65
+ // The status listener will update updateAvailable if an update is found
66
+ await new Promise((resolve) => setTimeout(resolve, 1000));
67
+
68
+ // Check status again after update check
69
+ // Use the state value which may have been updated by the status listener
70
+ // If updateAvailable is true, don't show "You are up to date"
71
+ if (!updateAvailable) {
72
+ // Double-check with API to be sure
73
+ const finalStatus = await getServiceWorkerStatus();
74
+ if (!finalStatus.updateAvailable) {
75
+ setShowUpToDateInButton(true);
76
+ window.setTimeout(() => setShowUpToDateInButton(false), 3000);
77
+ }
78
+ }
79
+ } catch (error) {
80
+ // Error occurred during update check - show error message in button
81
+ setCheckError(true);
82
+ logger.error('Failed to check for service worker update:', { error });
83
+ } finally {
84
+ setChecking(false);
85
+ }
86
+ };
87
+
88
+ const version = config?.version ?? t('updateApp.versionUnknown');
89
+
90
+ if (isTauri()) {
91
+ return (
92
+ <div className="space-y-6">
93
+ <div className="space-y-2">
94
+ <div className="space-y-0.5">
95
+ <label
96
+ className="text-sm font-medium leading-none"
97
+ style={{ fontFamily: 'var(--heading-font-family, inherit)' }}
98
+ >
99
+ {t('updateApp.currentVersion')}
100
+ </label>
101
+ <p className="text-sm text-muted-foreground">{version}</p>
102
+ </div>
103
+ <div className="rounded-lg border border-border bg-muted/30 p-4">
104
+ <p className="text-sm text-muted-foreground">{t('updateApp.tauriComingSoon')}</p>
105
+ </div>
106
+ </div>
107
+ </div>
108
+ );
109
+ }
110
+
111
+ return (
112
+ <div className="space-y-6">
113
+ <div className="space-y-4">
114
+ <div className="space-y-0.5">
115
+ <label
116
+ className="text-sm font-medium leading-none"
117
+ style={{ fontFamily: 'var(--heading-font-family, inherit)' }}
118
+ >
119
+ {t('updateApp.currentVersion')}
120
+ </label>
121
+ <p className="text-sm text-muted-foreground">{version}</p>
122
+ </div>
123
+ {!serviceWorkerEnabled ? (
124
+ <div className="space-y-3">
125
+ <p className="text-sm text-muted-foreground">{t('updateApp.swDisabledMessage')}</p>
126
+ <Button
127
+ variant="outline"
128
+ onClick={() => {
129
+ const sent = shellui.sendMessageToParent({
130
+ type: 'SHELLUI_REFRESH_PAGE',
131
+ payload: {},
132
+ });
133
+ if (!sent) window.location.reload();
134
+ }}
135
+ className="w-full sm:w-auto"
136
+ >
137
+ {t('updateApp.refreshApp')}
138
+ </Button>
139
+ </div>
140
+ ) : (
141
+ <>
142
+ <div className="space-y-2">
143
+ <label
144
+ className="text-sm font-medium leading-none"
145
+ style={{ fontFamily: 'var(--heading-font-family, inherit)' }}
146
+ >
147
+ {t('updateApp.status')}
148
+ </label>
149
+ <div className="flex items-center gap-2 text-sm mt-2">
150
+ {updateAvailable ? (
151
+ <span className="text-blue-600 dark:text-blue-400">
152
+ ● {t('updateApp.statusUpdateAvailable')}
153
+ </span>
154
+ ) : (
155
+ <span className="text-green-600 dark:text-green-400">
156
+ ● {t('updateApp.statusUpToDate')}
157
+ </span>
158
+ )}
159
+ </div>
160
+ </div>
161
+ <div className="flex items-center gap-2 flex-wrap">
162
+ {updateAvailable && (
163
+ <Button
164
+ variant="default"
165
+ onClick={async () => {
166
+ await updateServiceWorker();
167
+ }}
168
+ className="w-full sm:w-auto"
169
+ >
170
+ {t('updateApp.installNow')}
171
+ </Button>
172
+ )}
173
+ <Button
174
+ variant="outline"
175
+ onClick={handleCheckForUpdate}
176
+ disabled={checking || updateAvailable}
177
+ className="w-full sm:w-auto"
178
+ >
179
+ {checking ? (
180
+ <>
181
+ <span
182
+ className="inline-block h-4 w-4 shrink-0 animate-spin rounded-full border-2 border-current border-t-transparent mr-2"
183
+ aria-hidden
184
+ />
185
+ {t('updateApp.checking')}
186
+ </>
187
+ ) : checkError ? (
188
+ <span className="inline-flex items-center gap-2 text-red-600 dark:text-red-400">
189
+ {t('updateApp.checkError')}
190
+ </span>
191
+ ) : showUpToDateInButton && !updateAvailable ? (
192
+ <span className="inline-flex items-center gap-2 text-green-600 dark:text-green-400">
193
+ <CheckIcon />
194
+ {t('updateApp.youAreUpToDate')}
195
+ </span>
196
+ ) : (
197
+ t('updateApp.checkForUpdate')
198
+ )}
199
+ </Button>
200
+ </div>
201
+ </>
202
+ )}
203
+ </div>
204
+ </div>
205
+ );
206
+ };
@@ -0,0 +1,137 @@
1
+ import { useTranslation } from 'react-i18next';
2
+ import { Button } from '@/components/ui/button';
3
+ import { shellui } from '@shellui/sdk';
4
+
5
+ export const DialogTestButtons = () => {
6
+ const { t } = useTranslation('settings');
7
+
8
+ return (
9
+ <div>
10
+ <h4
11
+ className="text-sm font-medium mb-2"
12
+ style={{ fontFamily: 'var(--heading-font-family, inherit)' }}
13
+ >
14
+ {t('develop.testing.dialogTesting.title')}
15
+ </h4>
16
+ <div className="flex flex-wrap gap-2">
17
+ <Button
18
+ onClick={() => {
19
+ shellui.dialog({
20
+ title: t('develop.testing.dialogTesting.dialogs.ok.title'),
21
+ description: t('develop.testing.dialogTesting.dialogs.ok.description'),
22
+ mode: 'ok',
23
+ onOk: () => {
24
+ shellui.toast({
25
+ title: t('develop.testing.dialogTesting.toasts.okClicked'),
26
+ type: 'success',
27
+ });
28
+ },
29
+ });
30
+ }}
31
+ variant="outline"
32
+ >
33
+ {t('develop.testing.dialogTesting.buttons.okDialog')}
34
+ </Button>
35
+ <Button
36
+ onClick={() => {
37
+ shellui.dialog({
38
+ title: t('develop.testing.dialogTesting.dialogs.okCancel.title'),
39
+ description: t('develop.testing.dialogTesting.dialogs.okCancel.description'),
40
+ mode: 'okCancel',
41
+ size: 'sm',
42
+ onOk: () => {
43
+ shellui.toast({
44
+ title: t('develop.testing.dialogTesting.toasts.okClicked'),
45
+ type: 'success',
46
+ });
47
+ },
48
+ onCancel: () => {
49
+ shellui.toast({
50
+ title: t('develop.testing.dialogTesting.toasts.cancelClicked'),
51
+ type: 'info',
52
+ });
53
+ },
54
+ });
55
+ }}
56
+ variant="outline"
57
+ >
58
+ {t('develop.testing.dialogTesting.buttons.okCancelDialog')}
59
+ </Button>
60
+ <Button
61
+ onClick={() => {
62
+ shellui.dialog({
63
+ title: t('develop.testing.dialogTesting.dialogs.delete.title'),
64
+ description: t('develop.testing.dialogTesting.dialogs.delete.description'),
65
+ mode: 'delete',
66
+ okLabel: t('develop.testing.dialogTesting.dialogs.delete.okLabel'),
67
+ cancelLabel: t('develop.testing.dialogTesting.dialogs.delete.cancelLabel'),
68
+ size: 'sm',
69
+ onOk: () => {
70
+ shellui.toast({
71
+ title: t('develop.testing.dialogTesting.toasts.itemDeleted'),
72
+ type: 'success',
73
+ });
74
+ },
75
+ onCancel: () => {
76
+ shellui.toast({
77
+ title: t('develop.testing.dialogTesting.toasts.deletionCancelled'),
78
+ type: 'info',
79
+ });
80
+ },
81
+ });
82
+ }}
83
+ variant="outline"
84
+ >
85
+ {t('develop.testing.dialogTesting.buttons.deleteDialog')}
86
+ </Button>
87
+ <Button
88
+ onClick={() => {
89
+ shellui.dialog({
90
+ title: t('develop.testing.dialogTesting.dialogs.confirm.title'),
91
+ description: t('develop.testing.dialogTesting.dialogs.confirm.description'),
92
+ mode: 'confirm',
93
+ okLabel: t('develop.testing.dialogTesting.dialogs.confirm.okLabel'),
94
+ cancelLabel: t('develop.testing.dialogTesting.dialogs.confirm.cancelLabel'),
95
+ size: 'sm',
96
+ onOk: () => {
97
+ shellui.toast({
98
+ title: t('develop.testing.dialogTesting.toasts.actionConfirmed'),
99
+ type: 'success',
100
+ });
101
+ },
102
+ onCancel: () => {
103
+ shellui.toast({
104
+ title: t('develop.testing.dialogTesting.toasts.actionCancelled'),
105
+ type: 'info',
106
+ });
107
+ },
108
+ });
109
+ }}
110
+ variant="outline"
111
+ >
112
+ {t('develop.testing.dialogTesting.buttons.confirmDialog')}
113
+ </Button>
114
+ <Button
115
+ onClick={() => {
116
+ shellui.dialog({
117
+ title: t('develop.testing.dialogTesting.dialogs.onlyCancel.title'),
118
+ description: t('develop.testing.dialogTesting.dialogs.onlyCancel.description'),
119
+ mode: 'onlyCancel',
120
+ cancelLabel: t('develop.testing.dialogTesting.dialogs.onlyCancel.cancelLabel'),
121
+ size: 'sm',
122
+ onCancel: () => {
123
+ shellui.toast({
124
+ title: t('develop.testing.dialogTesting.toasts.dialogClosed'),
125
+ type: 'info',
126
+ });
127
+ },
128
+ });
129
+ }}
130
+ variant="outline"
131
+ >
132
+ {t('develop.testing.dialogTesting.buttons.onlyCancelDialog')}
133
+ </Button>
134
+ </div>
135
+ </div>
136
+ );
137
+ };
@@ -0,0 +1,67 @@
1
+ import { useTranslation } from 'react-i18next';
2
+ import { Button } from '@/components/ui/button';
3
+ import { shellui, type OpenDrawerOptions } from '@shellui/sdk';
4
+ import urls from '@/constants/urls';
5
+
6
+ export const DrawerTestButtons = () => {
7
+ const { t } = useTranslation('settings');
8
+
9
+ const openDrawer = (options: OpenDrawerOptions) => {
10
+ shellui.openDrawer({ url: urls.settings, ...options });
11
+ };
12
+
13
+ return (
14
+ <div>
15
+ <h4
16
+ className="text-sm font-medium mb-2"
17
+ style={{ fontFamily: 'var(--heading-font-family, inherit)' }}
18
+ >
19
+ {t('develop.testing.drawerTesting.title')}
20
+ </h4>
21
+ <div className="flex flex-wrap gap-2">
22
+ <Button
23
+ onClick={() => openDrawer({ position: 'right' })}
24
+ variant="outline"
25
+ >
26
+ {t('develop.testing.drawerTesting.buttons.drawerRight')}
27
+ </Button>
28
+ <Button
29
+ onClick={() => openDrawer({ position: 'left' })}
30
+ variant="outline"
31
+ >
32
+ {t('develop.testing.drawerTesting.buttons.drawerLeft')}
33
+ </Button>
34
+ <Button
35
+ onClick={() => openDrawer({ position: 'top' })}
36
+ variant="outline"
37
+ >
38
+ {t('develop.testing.drawerTesting.buttons.drawerTop')}
39
+ </Button>
40
+ <Button
41
+ onClick={() => openDrawer({ position: 'bottom' })}
42
+ variant="outline"
43
+ >
44
+ {t('develop.testing.drawerTesting.buttons.drawerBottom')}
45
+ </Button>
46
+ <Button
47
+ onClick={() => openDrawer({ position: 'right', size: '400px' })}
48
+ variant="outline"
49
+ >
50
+ {t('develop.testing.drawerTesting.buttons.drawerRightNarrow')}
51
+ </Button>
52
+ <Button
53
+ onClick={() => openDrawer({ position: 'bottom', size: '60vh' })}
54
+ variant="outline"
55
+ >
56
+ {t('develop.testing.drawerTesting.buttons.drawerBottomHalf')}
57
+ </Button>
58
+ <Button
59
+ onClick={() => shellui.closeDrawer()}
60
+ variant="outline"
61
+ >
62
+ {t('develop.testing.drawerTesting.buttons.closeDrawer')}
63
+ </Button>
64
+ </div>
65
+ </div>
66
+ );
67
+ };
@@ -0,0 +1,30 @@
1
+ import { useTranslation } from 'react-i18next';
2
+ import { Button } from '@/components/ui/button';
3
+ import { shellui } from '@shellui/sdk';
4
+ import urls from '@/constants/urls';
5
+
6
+ export const ModalTestButtons = () => {
7
+ const { t } = useTranslation('settings');
8
+
9
+ return (
10
+ <div>
11
+ <h4
12
+ className="text-sm font-medium mb-2"
13
+ style={{ fontFamily: 'var(--heading-font-family, inherit)' }}
14
+ >
15
+ {t('develop.testing.modalTesting.title')}
16
+ </h4>
17
+ <div className="flex flex-wrap gap-2">
18
+ <Button
19
+ onClick={() => shellui.openModal(urls.settings)}
20
+ variant="outline"
21
+ >
22
+ {t('develop.testing.modalTesting.buttons.openModal')}
23
+ </Button>
24
+ </div>
25
+ <p className="text-xs text-muted-foreground mt-2">
26
+ {t('develop.testing.modalTesting.description')}
27
+ </p>
28
+ </div>
29
+ );
30
+ };
@@ -0,0 +1,179 @@
1
+ import { useTranslation } from 'react-i18next';
2
+ import { Button } from '@/components/ui/button';
3
+ import { shellui } from '@shellui/sdk';
4
+
5
+ export const ToastTestButtons = () => {
6
+ const { t } = useTranslation('settings');
7
+
8
+ return (
9
+ <div>
10
+ <h4
11
+ className="text-sm font-medium mb-2"
12
+ style={{ fontFamily: 'var(--heading-font-family, inherit)' }}
13
+ >
14
+ {t('develop.testing.toastNotifications.title')}
15
+ </h4>
16
+ <div className="flex flex-wrap gap-2">
17
+ <Button
18
+ onClick={() => {
19
+ shellui.toast({
20
+ title: t('develop.testing.toastNotifications.messages.success.title'),
21
+ description: t('develop.testing.toastNotifications.messages.success.description'),
22
+ type: 'success',
23
+ });
24
+ }}
25
+ variant="outline"
26
+ >
27
+ {t('develop.testing.toastNotifications.buttons.success')}
28
+ </Button>
29
+ <Button
30
+ onClick={() => {
31
+ shellui.toast({
32
+ title: t('develop.testing.toastNotifications.messages.error.title'),
33
+ description: t('develop.testing.toastNotifications.messages.error.description'),
34
+ type: 'error',
35
+ });
36
+ }}
37
+ variant="outline"
38
+ >
39
+ {t('develop.testing.toastNotifications.buttons.error')}
40
+ </Button>
41
+ <Button
42
+ onClick={() => {
43
+ shellui.toast({
44
+ title: t('develop.testing.toastNotifications.messages.warning.title'),
45
+ description: t('develop.testing.toastNotifications.messages.warning.description'),
46
+ type: 'warning',
47
+ });
48
+ }}
49
+ variant="outline"
50
+ >
51
+ {t('develop.testing.toastNotifications.buttons.warning')}
52
+ </Button>
53
+ <Button
54
+ onClick={() => {
55
+ shellui.toast({
56
+ title: t('develop.testing.toastNotifications.messages.info.title'),
57
+ description: t('develop.testing.toastNotifications.messages.info.description'),
58
+ type: 'info',
59
+ });
60
+ }}
61
+ variant="outline"
62
+ >
63
+ {t('develop.testing.toastNotifications.buttons.info')}
64
+ </Button>
65
+ <Button
66
+ onClick={() => {
67
+ shellui.toast({
68
+ title: t('develop.testing.toastNotifications.messages.default.title'),
69
+ description: t('develop.testing.toastNotifications.messages.default.description'),
70
+ type: 'default',
71
+ });
72
+ }}
73
+ variant="outline"
74
+ >
75
+ {t('develop.testing.toastNotifications.buttons.default')}
76
+ </Button>
77
+ <Button
78
+ onClick={() => {
79
+ const toastId = shellui.toast({
80
+ title: t('develop.testing.toastNotifications.messages.processing.title'),
81
+ description: t('develop.testing.toastNotifications.messages.processing.description'),
82
+ type: 'loading',
83
+ });
84
+
85
+ // Simulate async operation and update toast
86
+ if (typeof toastId === 'string') {
87
+ setTimeout(() => {
88
+ shellui.toast({
89
+ id: toastId,
90
+ type: 'success',
91
+ title: t('develop.testing.toastNotifications.messages.uploadComplete.title'),
92
+ description: t(
93
+ 'develop.testing.toastNotifications.messages.uploadComplete.description',
94
+ ),
95
+ });
96
+ }, 2000);
97
+ }
98
+ }}
99
+ variant="outline"
100
+ >
101
+ {t('develop.testing.toastNotifications.buttons.loadingSuccess')}
102
+ </Button>
103
+ <Button
104
+ onClick={() => {
105
+ shellui.toast({
106
+ title: t('develop.testing.toastNotifications.messages.withAction.title'),
107
+ description: t('develop.testing.toastNotifications.messages.withAction.description'),
108
+ type: 'success',
109
+ action: {
110
+ label: t('develop.testing.toastNotifications.messages.actionLabels.undo'),
111
+ onClick: () => {
112
+ shellui.toast({
113
+ title: t('develop.testing.toastNotifications.messages.undone.title'),
114
+ description: t(
115
+ 'develop.testing.toastNotifications.messages.undone.description',
116
+ ),
117
+ type: 'info',
118
+ });
119
+ },
120
+ },
121
+ });
122
+ }}
123
+ variant="outline"
124
+ >
125
+ {t('develop.testing.toastNotifications.buttons.withAction')}
126
+ </Button>
127
+ <Button
128
+ onClick={() => {
129
+ shellui.toast({
130
+ title: t('develop.testing.toastNotifications.messages.withAction.title'),
131
+ description: t('develop.testing.toastNotifications.messages.withAction.description'),
132
+ type: 'success',
133
+ action: {
134
+ label: t('develop.testing.toastNotifications.messages.actionLabels.undo'),
135
+ onClick: () => {
136
+ shellui.toast({
137
+ title: t('develop.testing.toastNotifications.messages.undone.title'),
138
+ description: t(
139
+ 'develop.testing.toastNotifications.messages.undone.description',
140
+ ),
141
+ type: 'info',
142
+ });
143
+ },
144
+ },
145
+ cancel: {
146
+ label: t('develop.testing.toastNotifications.messages.actionLabels.cancel'),
147
+ onClick: () => {
148
+ shellui.toast({
149
+ title: t('develop.testing.toastNotifications.messages.cancelled.title'),
150
+ description: t(
151
+ 'develop.testing.toastNotifications.messages.cancelled.description',
152
+ ),
153
+ type: 'info',
154
+ });
155
+ },
156
+ },
157
+ });
158
+ }}
159
+ variant="outline"
160
+ >
161
+ {t('develop.testing.toastNotifications.buttons.withActionAndCancel')}
162
+ </Button>
163
+ <Button
164
+ onClick={() => {
165
+ shellui.toast({
166
+ title: t('develop.testing.toastNotifications.messages.persistent.title'),
167
+ description: t('develop.testing.toastNotifications.messages.persistent.description'),
168
+ type: 'info',
169
+ duration: 10000,
170
+ });
171
+ }}
172
+ variant="outline"
173
+ >
174
+ {t('develop.testing.toastNotifications.buttons.longDuration')}
175
+ </Button>
176
+ </div>
177
+ </div>
178
+ );
179
+ };
@@ -0,0 +1,10 @@
1
+ import { useContext } from 'react';
2
+ import { SettingsContext } from '../SettingsContext';
3
+
4
+ export function useSettings() {
5
+ const context = useContext(SettingsContext);
6
+ if (context === undefined) {
7
+ throw new Error('useSettings must be used within a SettingsProvider');
8
+ }
9
+ return context;
10
+ }