@djangocfg/layouts 2.1.166 → 2.1.168

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.
package/README.md CHANGED
@@ -466,16 +466,37 @@ export default function Page() {
466
466
  import {
467
467
  ErrorTrackingProvider,
468
468
  useErrors,
469
- ErrorButtons,
470
- ErrorToast
471
- } from '@djangocfg/layouts/components/errors/ErrorsTracker';
469
+ useErrorEmitter,
470
+ emitRuntimeError,
471
+ } from '@djangocfg/layouts';
472
472
 
473
+ // Wrap your app
473
474
  <ErrorTrackingProvider>
474
475
  <YourApp />
475
476
  </ErrorTrackingProvider>
476
477
 
477
- // In components
478
- const { addError, clearErrors, errors } = useErrors();
478
+ // In React components - use hook
479
+ function MyComponent() {
480
+ const { emitError } = useErrorEmitter('MyComponent');
481
+
482
+ try {
483
+ doSomething();
484
+ } catch (error) {
485
+ emitError('Something failed', error);
486
+ }
487
+ }
488
+
489
+ // Outside React (utilities, libraries) - use standalone function
490
+ import { emitRuntimeError } from '@djangocfg/layouts';
491
+
492
+ try {
493
+ doSomething();
494
+ } catch (error) {
495
+ emitRuntimeError('MyUtility', 'Something failed', error);
496
+ }
497
+
498
+ // Access errors
499
+ const { errors, clearErrors } = useErrors();
479
500
  ```
480
501
 
481
502
  ### Update Notifier
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@djangocfg/layouts",
3
- "version": "2.1.166",
3
+ "version": "2.1.168",
4
4
  "description": "Simple, straightforward layout components for Next.js - import and use with props",
5
5
  "keywords": [
6
6
  "layouts",
@@ -74,12 +74,12 @@
74
74
  "check": "tsc --noEmit"
75
75
  },
76
76
  "peerDependencies": {
77
- "@djangocfg/api": "^2.1.166",
78
- "@djangocfg/centrifugo": "^2.1.166",
79
- "@djangocfg/i18n": "^2.1.166",
80
- "@djangocfg/ui-core": "^2.1.166",
81
- "@djangocfg/ui-nextjs": "^2.1.166",
82
- "@djangocfg/ui-tools": "^2.1.166",
77
+ "@djangocfg/api": "^2.1.168",
78
+ "@djangocfg/centrifugo": "^2.1.168",
79
+ "@djangocfg/i18n": "^2.1.168",
80
+ "@djangocfg/ui-core": "^2.1.168",
81
+ "@djangocfg/ui-nextjs": "^2.1.168",
82
+ "@djangocfg/ui-tools": "^2.1.168",
83
83
  "@hookform/resolvers": "^5.2.2",
84
84
  "consola": "^3.4.2",
85
85
  "lucide-react": "^0.545.0",
@@ -102,13 +102,13 @@
102
102
  "uuid": "^11.1.0"
103
103
  },
104
104
  "devDependencies": {
105
- "@djangocfg/api": "^2.1.166",
106
- "@djangocfg/i18n": "^2.1.166",
107
- "@djangocfg/centrifugo": "^2.1.166",
108
- "@djangocfg/typescript-config": "^2.1.166",
109
- "@djangocfg/ui-core": "^2.1.166",
110
- "@djangocfg/ui-nextjs": "^2.1.166",
111
- "@djangocfg/ui-tools": "^2.1.166",
105
+ "@djangocfg/api": "^2.1.168",
106
+ "@djangocfg/i18n": "^2.1.168",
107
+ "@djangocfg/centrifugo": "^2.1.168",
108
+ "@djangocfg/typescript-config": "^2.1.168",
109
+ "@djangocfg/ui-core": "^2.1.168",
110
+ "@djangocfg/ui-nextjs": "^2.1.168",
111
+ "@djangocfg/ui-tools": "^2.1.168",
112
112
  "@types/node": "^24.7.2",
113
113
  "@types/react": "^19.1.0",
114
114
  "@types/react-dom": "^19.1.0",
@@ -16,10 +16,12 @@ import type {
16
16
  CORSErrorDetail,
17
17
  NetworkErrorDetail,
18
18
  CentrifugoErrorDetail,
19
+ RuntimeErrorDetail,
19
20
  ValidationErrorConfig,
20
21
  CORSErrorConfig,
21
22
  NetworkErrorConfig,
22
23
  CentrifugoErrorConfig,
24
+ RuntimeErrorConfig,
23
25
  } from '../types';
24
26
  /**
25
27
  * Build validation error description
@@ -151,12 +153,32 @@ function buildCentrifugoDescription(
151
153
  );
152
154
  }
153
155
 
156
+ /**
157
+ * Build runtime error description
158
+ */
159
+ function buildRuntimeDescription(
160
+ detail: RuntimeErrorDetail,
161
+ config: Required<RuntimeErrorConfig>
162
+ ): React.ReactNode {
163
+ return (
164
+ <div className="flex flex-col gap-2 text-sm">
165
+ {config.showSource && (
166
+ <div className="font-mono text-xs opacity-90">
167
+ Source: {detail.source}
168
+ </div>
169
+ )}
170
+
171
+ <div className="opacity-90">{detail.message}</div>
172
+ </div>
173
+ );
174
+ }
175
+
154
176
  /**
155
177
  * Create toast options for any error type
156
178
  */
157
179
  export function createErrorToast(
158
- detail: ValidationErrorDetail | CORSErrorDetail | NetworkErrorDetail | CentrifugoErrorDetail,
159
- config: Required<ValidationErrorConfig | CORSErrorConfig | NetworkErrorConfig | CentrifugoErrorConfig>
180
+ detail: ValidationErrorDetail | CORSErrorDetail | NetworkErrorDetail | CentrifugoErrorDetail | RuntimeErrorDetail,
181
+ config: Required<ValidationErrorConfig | CORSErrorConfig | NetworkErrorConfig | CentrifugoErrorConfig | RuntimeErrorConfig>
160
182
  ) {
161
183
  let description: React.ReactNode;
162
184
 
@@ -167,6 +189,8 @@ export function createErrorToast(
167
189
  description = buildCORSDescription(detail, config as Required<CORSErrorConfig>);
168
190
  } else if (detail.type === 'centrifugo') {
169
191
  description = buildCentrifugoDescription(detail, config as Required<CentrifugoErrorConfig>);
192
+ } else if (detail.type === 'runtime') {
193
+ description = buildRuntimeDescription(detail, config as Required<RuntimeErrorConfig>);
170
194
  } else {
171
195
  description = buildNetworkDescription(detail, config as Required<NetworkErrorConfig>);
172
196
  }
@@ -0,0 +1,72 @@
1
+ /**
2
+ * useErrorEmitter - Universal error emitter hook
3
+ *
4
+ * Emits runtime errors that are caught by ErrorTrackingProvider
5
+ * and displayed as toasts.
6
+ *
7
+ * @example
8
+ * ```tsx
9
+ * function MyComponent() {
10
+ * const { emitError } = useErrorEmitter('tour');
11
+ *
12
+ * useEffect(() => {
13
+ * try {
14
+ * document.querySelectorAll(invalidSelector);
15
+ * } catch (error) {
16
+ * emitError('Invalid selector', error);
17
+ * }
18
+ * }, []);
19
+ * }
20
+ * ```
21
+ */
22
+
23
+ 'use client';
24
+
25
+ import { useCallback } from 'react';
26
+
27
+ import { ERROR_EVENTS } from '../types';
28
+
29
+ export interface EmitErrorOptions {
30
+ /** Additional context data */
31
+ context?: Record<string, unknown>;
32
+ }
33
+
34
+ export interface ErrorEmitter {
35
+ /**
36
+ * Emit an error to be shown as a toast
37
+ * @param message - Human-readable error message
38
+ * @param error - Original Error object (optional)
39
+ * @param options - Additional options
40
+ */
41
+ emitError: (message: string, error?: Error, options?: EmitErrorOptions) => void;
42
+ }
43
+
44
+ /**
45
+ * Hook to emit runtime errors
46
+ *
47
+ * @param source - Error source identifier (e.g., 'tour', 'form', 'api')
48
+ */
49
+ export function useErrorEmitter(source: string): ErrorEmitter {
50
+ const emitError = useCallback(
51
+ (message: string, error?: Error, options?: EmitErrorOptions) => {
52
+ if (typeof window === 'undefined') return;
53
+
54
+ const event = new CustomEvent(ERROR_EVENTS.RUNTIME, {
55
+ detail: {
56
+ source,
57
+ message,
58
+ error,
59
+ context: options?.context,
60
+ timestamp: new Date(),
61
+ },
62
+ });
63
+
64
+ window.dispatchEvent(event);
65
+ },
66
+ [source]
67
+ );
68
+
69
+ return { emitError };
70
+ }
71
+
72
+ export default useErrorEmitter;
@@ -5,6 +5,8 @@
5
5
  */
6
6
 
7
7
  export { useErrors } from './providers/ErrorTrackingProvider';
8
+ export { useErrorEmitter } from './hooks/useErrorEmitter';
9
+ export type { ErrorEmitter, EmitErrorOptions } from './hooks/useErrorEmitter';
8
10
 
9
11
  // Type exports for convenience
10
12
  export type { ErrorTrackingContextValue } from './types';
@@ -1,13 +1,20 @@
1
1
  /**
2
2
  * Error Tracking - Unified error tracking for all error types
3
3
  *
4
- * Single provider and hook for validation, CORS, network, and Centrifugo errors
4
+ * Single provider and hook for validation, CORS, network, Centrifugo, and runtime errors
5
5
  */
6
6
 
7
7
  // Main provider and hook
8
8
  export { ErrorTrackingProvider } from './providers/ErrorTrackingProvider';
9
9
  export { useErrors } from './hooks';
10
10
 
11
+ // Error emitter hook (for emitting runtime errors from React components)
12
+ export { useErrorEmitter } from './hooks';
13
+ export type { ErrorEmitter, EmitErrorOptions } from './hooks';
14
+
15
+ // Re-export standalone emitRuntimeError from ui-core (for use outside React)
16
+ export { emitRuntimeError } from '@djangocfg/ui-core/utils';
17
+
11
18
  // Types
12
19
  export type {
13
20
  ErrorDetail,
@@ -15,15 +22,20 @@ export type {
15
22
  CORSErrorDetail,
16
23
  NetworkErrorDetail,
17
24
  CentrifugoErrorDetail,
25
+ RuntimeErrorDetail,
18
26
  StoredError,
19
27
  ErrorTrackingConfig,
20
28
  ValidationErrorConfig,
21
29
  CORSErrorConfig,
22
30
  NetworkErrorConfig,
23
31
  CentrifugoErrorConfig,
32
+ RuntimeErrorConfig,
24
33
  ErrorTrackingContextValue,
25
34
  } from './types';
26
35
 
36
+ // Event names (for manual event dispatching)
37
+ export { ERROR_EVENTS } from './types';
38
+
27
39
  // Components
28
40
  export { ErrorButtons } from './components/ErrorButtons';
29
41
  export { createErrorToast } from './components/ErrorToast';
@@ -35,6 +47,7 @@ export {
35
47
  formatCORSErrorForClipboard,
36
48
  formatNetworkErrorForClipboard,
37
49
  formatCentrifugoErrorForClipboard,
50
+ formatRuntimeErrorForClipboard,
38
51
  formatErrorTitle,
39
52
  extractDomain,
40
53
  } from './utils/formatters';
@@ -37,6 +37,7 @@ import {
37
37
  DEFAULT_CENTRIFUGO_CONFIG,
38
38
  DEFAULT_CORS_CONFIG,
39
39
  DEFAULT_NETWORK_CONFIG,
40
+ DEFAULT_RUNTIME_CONFIG,
40
41
  DEFAULT_VALIDATION_CONFIG,
41
42
  ERROR_EVENTS
42
43
  } from '../types';
@@ -48,10 +49,12 @@ import type {
48
49
  CORSErrorConfig,
49
50
  NetworkErrorConfig,
50
51
  CentrifugoErrorConfig,
52
+ RuntimeErrorConfig,
51
53
  ValidationErrorDetail,
52
54
  CORSErrorDetail,
53
55
  NetworkErrorDetail,
54
56
  CentrifugoErrorDetail,
57
+ RuntimeErrorDetail,
55
58
  ErrorTrackingContextValue,
56
59
  } from '../types';
57
60
  const ErrorTrackingContext = createContext<ErrorTrackingContextValue | undefined>(undefined);
@@ -78,6 +81,8 @@ function getErrorDedupeKey(detail: ErrorDetail): string {
78
81
  return `network:${detail.url}:${detail.statusCode || 'unknown'}`;
79
82
  case 'centrifugo':
80
83
  return `centrifugo:${detail.method}:${detail.code || 'unknown'}`;
84
+ case 'runtime':
85
+ return `runtime:${detail.source}:${detail.message.slice(0, 50)}`;
81
86
  default:
82
87
  return `unknown:${Date.now()}`;
83
88
  }
@@ -148,6 +153,7 @@ export interface ErrorTrackingProviderProps {
148
153
  cors?: Partial<CORSErrorConfig>;
149
154
  network?: Partial<NetworkErrorConfig>;
150
155
  centrifugo?: Partial<CentrifugoErrorConfig>;
156
+ runtime?: Partial<RuntimeErrorConfig>;
151
157
  onError?: (error: ErrorDetail) => boolean | void;
152
158
  }
153
159
 
@@ -162,6 +168,7 @@ export function ErrorTrackingProvider({
162
168
  cors: userCorsConfig,
163
169
  network: userNetworkConfig,
164
170
  centrifugo: userCentrifugoConfig,
171
+ runtime: userRuntimeConfig,
165
172
  onError,
166
173
  }: ErrorTrackingProviderProps) {
167
174
  const [errors, setErrors] = useState<StoredError[]>([]);
@@ -187,6 +194,11 @@ export function ErrorTrackingProvider({
187
194
  ...userCentrifugoConfig,
188
195
  };
189
196
 
197
+ const runtimeConfig: Required<RuntimeErrorConfig> = {
198
+ ...DEFAULT_RUNTIME_CONFIG,
199
+ ...userRuntimeConfig,
200
+ };
201
+
190
202
  /**
191
203
  * Clear all errors
192
204
  */
@@ -212,7 +224,7 @@ export function ErrorTrackingProvider({
212
224
  * Handle any error event
213
225
  */
214
226
  const handleError = useCallback(
215
- (detail: ErrorDetail, config: Required<ValidationErrorConfig | CORSErrorConfig | NetworkErrorConfig | CentrifugoErrorConfig>) => {
227
+ (detail: ErrorDetail, config: Required<ValidationErrorConfig | CORSErrorConfig | NetworkErrorConfig | CentrifugoErrorConfig | RuntimeErrorConfig>) => {
216
228
  // Check for duplicate errors (within deduplication window)
217
229
  const isUnique = shouldShowError(detail);
218
230
 
@@ -314,19 +326,38 @@ export function ErrorTrackingProvider({
314
326
  handlers.push({ event: ERROR_EVENTS.CENTRIFUGO, handler });
315
327
  }
316
328
 
329
+ // Runtime errors (generic JS errors from anywhere in the app)
330
+ if (runtimeConfig.enabled) {
331
+ const handler = (event: Event) => {
332
+ if (!(event instanceof CustomEvent)) return;
333
+ const detail: RuntimeErrorDetail = {
334
+ type: 'runtime' as const,
335
+ source: event.detail.source || 'unknown',
336
+ message: event.detail.message || 'Unknown error',
337
+ error: event.detail.error,
338
+ context: event.detail.context,
339
+ timestamp: event.detail.timestamp || new Date(),
340
+ };
341
+ handleError(detail, runtimeConfig);
342
+ };
343
+ window.addEventListener(ERROR_EVENTS.RUNTIME, handler);
344
+ handlers.push({ event: ERROR_EVENTS.RUNTIME, handler });
345
+ }
346
+
317
347
  // Cleanup
318
348
  return () => {
319
349
  handlers.forEach(({ event, handler }) => {
320
350
  window.removeEventListener(event, handler);
321
351
  });
322
352
  };
323
- }, [handleError, validationConfig, corsConfig, networkConfig, centrifugoConfig]);
353
+ }, [handleError, validationConfig, corsConfig, networkConfig, centrifugoConfig, runtimeConfig]);
324
354
 
325
355
  // Filter errors by type
326
356
  const validationErrors = errors.filter((e) => e.type === 'validation') as StoredError<ValidationErrorDetail>[];
327
357
  const corsErrors = errors.filter((e) => e.type === 'cors') as StoredError<CORSErrorDetail>[];
328
358
  const networkErrors = errors.filter((e) => e.type === 'network') as StoredError<NetworkErrorDetail>[];
329
359
  const centrifugoErrors = errors.filter((e) => e.type === 'centrifugo') as StoredError<CentrifugoErrorDetail>[];
360
+ const runtimeErrors = errors.filter((e) => e.type === 'runtime') as StoredError<RuntimeErrorDetail>[];
330
361
 
331
362
  const value: ErrorTrackingContextValue = {
332
363
  errors,
@@ -334,6 +365,7 @@ export function ErrorTrackingProvider({
334
365
  corsErrors,
335
366
  networkErrors,
336
367
  centrifugoErrors,
368
+ runtimeErrors,
337
369
  clearErrors,
338
370
  clearErrorsByType,
339
371
  clearError,
@@ -344,6 +376,7 @@ export function ErrorTrackingProvider({
344
376
  cors: corsConfig,
345
377
  network: networkConfig,
346
378
  centrifugo: centrifugoConfig,
379
+ runtime: runtimeConfig,
347
380
  },
348
381
  };
349
382
 
@@ -74,10 +74,26 @@ export interface CentrifugoErrorDetail extends BaseErrorDetail {
74
74
  data?: any;
75
75
  }
76
76
 
77
+ /**
78
+ * Runtime/generic error detail (from runtime-error event)
79
+ * Used for any JS errors that need to be shown to user (e.g., Tour selector errors)
80
+ */
81
+ export interface RuntimeErrorDetail extends BaseErrorDetail {
82
+ type: 'runtime';
83
+ /** Error source/category (e.g., 'tour', 'component', etc.) */
84
+ source: string;
85
+ /** Error message */
86
+ message: string;
87
+ /** Original error object if available */
88
+ error?: Error;
89
+ /** Additional context data */
90
+ context?: Record<string, unknown>;
91
+ }
92
+
77
93
  /**
78
94
  * Union type of all error details
79
95
  */
80
- export type ErrorDetail = ValidationErrorDetail | CORSErrorDetail | NetworkErrorDetail | CentrifugoErrorDetail;
96
+ export type ErrorDetail = ValidationErrorDetail | CORSErrorDetail | NetworkErrorDetail | CentrifugoErrorDetail | RuntimeErrorDetail;
81
97
 
82
98
  /**
83
99
  * Stored error with unique ID
@@ -202,6 +218,17 @@ export interface CentrifugoErrorConfig extends ErrorTypeConfig {
202
218
  showCode?: boolean;
203
219
  }
204
220
 
221
+ /**
222
+ * Runtime error specific config
223
+ */
224
+ export interface RuntimeErrorConfig extends ErrorTypeConfig {
225
+ /**
226
+ * Show error source in toast
227
+ * @default true
228
+ */
229
+ showSource?: boolean;
230
+ }
231
+
205
232
  /**
206
233
  * Complete error tracking configuration
207
234
  */
@@ -226,6 +253,11 @@ export interface ErrorTrackingConfig {
226
253
  */
227
254
  centrifugo?: CentrifugoErrorConfig;
228
255
 
256
+ /**
257
+ * Runtime error tracking configuration
258
+ */
259
+ runtime?: RuntimeErrorConfig;
260
+
229
261
  /**
230
262
  * Custom error handler (called before toast for all errors)
231
263
  * Return false to prevent default toast notification
@@ -252,11 +284,14 @@ export interface ErrorTrackingContextValue {
252
284
  /** Centrifugo errors only */
253
285
  centrifugoErrors: StoredError<CentrifugoErrorDetail>[];
254
286
 
287
+ /** Runtime errors only */
288
+ runtimeErrors: StoredError<RuntimeErrorDetail>[];
289
+
255
290
  /** Clear all errors */
256
291
  clearErrors: () => void;
257
292
 
258
293
  /** Clear errors by type */
259
- clearErrorsByType: (type: 'validation' | 'cors' | 'network' | 'centrifugo') => void;
294
+ clearErrorsByType: (type: 'validation' | 'cors' | 'network' | 'centrifugo' | 'runtime') => void;
260
295
 
261
296
  /** Clear specific error by ID */
262
297
  clearError: (id: string) => void;
@@ -273,6 +308,7 @@ export interface ErrorTrackingContextValue {
273
308
  cors: Required<CORSErrorConfig>;
274
309
  network: Required<NetworkErrorConfig>;
275
310
  centrifugo: Required<CentrifugoErrorConfig>;
311
+ runtime: Required<RuntimeErrorConfig>;
276
312
  };
277
313
  }
278
314
 
@@ -285,6 +321,8 @@ export const ERROR_EVENTS = {
285
321
  NETWORK: 'network-error',
286
322
  /** Unified Centrifugo event - filter by detail.type === 'error' */
287
323
  CENTRIFUGO: 'centrifugo',
324
+ /** Runtime/generic errors (Tour, components, etc.) */
325
+ RUNTIME: 'runtime-error',
288
326
  } as const;
289
327
 
290
328
  /**
@@ -326,3 +364,9 @@ export const DEFAULT_CENTRIFUGO_CONFIG: Required<CentrifugoErrorConfig> = {
326
364
  showMethod: true,
327
365
  showCode: true,
328
366
  };
367
+
368
+ export const DEFAULT_RUNTIME_CONFIG: Required<RuntimeErrorConfig> = {
369
+ ...DEFAULT_ERROR_CONFIG,
370
+ duration: 8000,
371
+ showSource: true,
372
+ };
@@ -5,7 +5,7 @@
5
5
  */
6
6
 
7
7
  import type { ZodError } from 'zod';
8
- import type { ValidationErrorDetail, CORSErrorDetail, NetworkErrorDetail, CentrifugoErrorDetail } from '../types';
8
+ import type { ValidationErrorDetail, CORSErrorDetail, NetworkErrorDetail, CentrifugoErrorDetail, RuntimeErrorDetail } from '../types';
9
9
 
10
10
  /**
11
11
  * Format Zod error issues for display
@@ -111,10 +111,30 @@ export function extractDomain(url: string): string {
111
111
  }
112
112
  }
113
113
 
114
+ /**
115
+ * Format runtime error for clipboard
116
+ */
117
+ export function formatRuntimeErrorForClipboard(detail: RuntimeErrorDetail): string {
118
+ const errorData = {
119
+ type: 'runtime',
120
+ timestamp: detail.timestamp.toISOString(),
121
+ source: detail.source,
122
+ message: detail.message,
123
+ ...(detail.error && {
124
+ errorName: detail.error.name,
125
+ errorMessage: detail.error.message,
126
+ stack: detail.error.stack,
127
+ }),
128
+ ...(detail.context && { context: detail.context }),
129
+ };
130
+
131
+ return JSON.stringify(errorData, null, 2);
132
+ }
133
+
114
134
  /**
115
135
  * Format error title based on type
116
136
  */
117
- export function formatErrorTitle(detail: ValidationErrorDetail | CORSErrorDetail | NetworkErrorDetail | CentrifugoErrorDetail): string {
137
+ export function formatErrorTitle(detail: ValidationErrorDetail | CORSErrorDetail | NetworkErrorDetail | CentrifugoErrorDetail | RuntimeErrorDetail): string {
118
138
  switch (detail.type) {
119
139
  case 'validation':
120
140
  return `❌ Validation Error in ${detail.operation}`;
@@ -128,6 +148,8 @@ export function formatErrorTitle(detail: ValidationErrorDetail | CORSErrorDetail
128
148
  return detail.code !== undefined
129
149
  ? `🔌 Centrifugo Error (${detail.code})`
130
150
  : '🔌 Centrifugo Error';
151
+ case 'runtime':
152
+ return `⚠️ ${detail.source} Error`;
131
153
  default:
132
154
  return '❌ Error';
133
155
  }
@@ -118,6 +118,8 @@ export interface LocaleSwitcherProps {
118
118
  showIcon?: boolean;
119
119
  /** Show flag emoji (default: true) */
120
120
  showFlag?: boolean;
121
+ /** Show label text in trigger button (default: true) */
122
+ showTriggerLabel?: boolean;
121
123
  /** Custom className */
122
124
  className?: string;
123
125
  }
@@ -132,6 +134,7 @@ export function LocaleSwitcher({
132
134
  size = 'sm',
133
135
  showIcon = true,
134
136
  showFlag = true,
137
+ showTriggerLabel = true,
135
138
  className,
136
139
  }: LocaleSwitcherProps) {
137
140
  const allLabels = { ...DEFAULT_LABELS, ...labels };
@@ -157,9 +160,9 @@ export function LocaleSwitcher({
157
160
  <DropdownMenu>
158
161
  <DropdownMenuTrigger asChild>
159
162
  <Button variant={variant} size={size} className={className}>
160
- {showIcon && !currentFlag && <Globe className="h-4 w-4 mr-1" />}
161
- {currentFlag && <span className="mr-1">{currentFlag}</span>}
162
- <span>{currentLabel}</span>
163
+ {showIcon && !currentFlag && <Globe className={showTriggerLabel ? "h-4 w-4 mr-1" : "h-4 w-4"} />}
164
+ {currentFlag && <span className={showTriggerLabel ? "mr-1" : ""}>{currentFlag}</span>}
165
+ {showTriggerLabel && <span>{currentLabel}</span>}
163
166
  </Button>
164
167
  </DropdownMenuTrigger>
165
168
  <DropdownMenuContent align="end">