@doneisbetter/gds-core 2.6.4 → 2.6.6

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/dist/server.mjs CHANGED
@@ -37,6 +37,9 @@ import {
37
37
  PublicProductCard,
38
38
  PublicShell,
39
39
  PublicSiteFooter,
40
+ ReferenceLinkGrid,
41
+ ReferenceLocaleNotice,
42
+ ReferenceSection,
40
43
  SectionPanel,
41
44
  SimpleDataTable,
42
45
  SocialAuthButtons,
@@ -60,7 +63,7 @@ import {
60
63
  resolveAccentPanelStyles,
61
64
  resolveSemanticActionConfig,
62
65
  ru
63
- } from "./chunk-BAS4ZGKL.mjs";
66
+ } from "./chunk-IAP3JU55.mjs";
64
67
  export {
65
68
  AccentPanel,
66
69
  AccessSummary,
@@ -100,6 +103,9 @@ export {
100
103
  PublicProductCard,
101
104
  PublicShell,
102
105
  PublicSiteFooter,
106
+ ReferenceLinkGrid,
107
+ ReferenceLocaleNotice,
108
+ ReferenceSection,
103
109
  SectionPanel,
104
110
  SimpleDataTable,
105
111
  SocialAuthButtons,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@doneisbetter/gds-core",
3
- "version": "2.6.4",
3
+ "version": "2.6.6",
4
4
  "main": "./dist/index.js",
5
5
  "module": "./dist/index.mjs",
6
6
  "types": "./dist/index.d.ts",
@@ -38,7 +38,7 @@
38
38
  "dev": "tsup --watch"
39
39
  },
40
40
  "peerDependencies": {
41
- "@doneisbetter/gds-theme": "^2.6.4",
41
+ "@doneisbetter/gds-theme": "^2.6.6",
42
42
  "@mantine/core": "^7.9.0 || ^8.3.0 || ^9.0.0",
43
43
  "@mantine/hooks": "^7.9.0 || ^8.3.0 || ^9.0.0",
44
44
  "@tabler/icons-react": "^3.5.0",
@@ -1,585 +0,0 @@
1
- import {
2
- GdsIcons,
3
- StateBlock,
4
- getSemanticActionLabel,
5
- resolveSemanticActionConfig
6
- } from "./chunk-BAS4ZGKL.mjs";
7
-
8
- // src/SemanticButton.tsx
9
- import { useEffect, useState } from "react";
10
- import { Button } from "@mantine/core";
11
- import { useGdsTranslation } from "@doneisbetter/gds-theme";
12
- import { IconCheck, IconX } from "@tabler/icons-react";
13
- import { jsx } from "react/jsx-runtime";
14
- function SemanticButton({
15
- action,
16
- loading,
17
- feedbackState,
18
- feedbackText,
19
- prerenderLabelOnly = true,
20
- vocabularyPacks = [],
21
- ...props
22
- }) {
23
- const { t } = useGdsTranslation();
24
- const config = resolveSemanticActionConfig(action, vocabularyPacks);
25
- const [mounted, setMounted] = useState(!prerenderLabelOnly);
26
- const [internalFeedback, setInternalFeedback] = useState(null);
27
- useEffect(() => {
28
- if (prerenderLabelOnly) {
29
- setMounted(true);
30
- }
31
- }, [prerenderLabelOnly]);
32
- useEffect(() => {
33
- if (feedbackState) {
34
- setInternalFeedback(feedbackState);
35
- const timer = setTimeout(() => setInternalFeedback(null), 2e3);
36
- return () => clearTimeout(timer);
37
- }
38
- }, [feedbackState]);
39
- let Icon = config.icon;
40
- let label = getSemanticActionLabel(action, t, vocabularyPacks);
41
- let color = props.color;
42
- if (!mounted) {
43
- const { leftSection, ...buttonProps } = props;
44
- return /* @__PURE__ */ jsx(Button, { loading, color, ...buttonProps, children: getSemanticActionLabel(action, void 0, vocabularyPacks) });
45
- }
46
- if (internalFeedback === "success") {
47
- const defaultFeedback = config.feedback ?? { icon: IconCheck, color: "teal", messageId: "gds.feedback.saved" };
48
- Icon = defaultFeedback.icon;
49
- label = feedbackText || t(defaultFeedback.messageId, "Success");
50
- color = defaultFeedback.color;
51
- } else if (internalFeedback === "error") {
52
- Icon = IconX;
53
- label = feedbackText || t("gds.feedback.error", "Something went wrong");
54
- color = "red";
55
- }
56
- return /* @__PURE__ */ jsx(
57
- Button,
58
- {
59
- leftSection: /* @__PURE__ */ jsx(Icon, { size: "1rem" }),
60
- loading,
61
- color,
62
- ...props,
63
- children: label
64
- }
65
- );
66
- }
67
-
68
- // src/ConfirmDialog.tsx
69
- import { Modal, Group, Text } from "@mantine/core";
70
- import { jsx as jsx2, jsxs } from "react/jsx-runtime";
71
- function ConfirmDialog({
72
- opened,
73
- onClose,
74
- onConfirm,
75
- title,
76
- children,
77
- confirmAction = "confirm",
78
- cancelAction = "cancel",
79
- isDanger = true,
80
- loading = false
81
- }) {
82
- return /* @__PURE__ */ jsxs(Modal, { opened, onClose, title, centered: true, trapFocus: true, children: [
83
- /* @__PURE__ */ jsx2(Text, { size: "sm", mb: "xl", children }),
84
- /* @__PURE__ */ jsxs(Group, { justify: "flex-end", children: [
85
- /* @__PURE__ */ jsx2(SemanticButton, { action: cancelAction, variant: "default", onClick: onClose, disabled: loading }),
86
- /* @__PURE__ */ jsx2(SemanticButton, { action: confirmAction, color: isDanger ? "red" : "violet", onClick: onConfirm, loading })
87
- ] })
88
- ] });
89
- }
90
-
91
- // src/ThemeToggle.tsx
92
- import { ActionIcon, useMantineColorScheme, useComputedColorScheme } from "@mantine/core";
93
- import { useGdsTranslation as useGdsTranslation2 } from "@doneisbetter/gds-theme";
94
- import { jsx as jsx3 } from "react/jsx-runtime";
95
- function ThemeToggle({ size = "md" }) {
96
- const { setColorScheme } = useMantineColorScheme();
97
- const computedColorScheme = useComputedColorScheme("light", { getInitialValueInEffect: true });
98
- const { t } = useGdsTranslation2();
99
- const toggleColorScheme = () => {
100
- setColorScheme(computedColorScheme === "dark" ? "light" : "dark");
101
- };
102
- const isDark = computedColorScheme === "dark";
103
- return /* @__PURE__ */ jsx3(
104
- ActionIcon,
105
- {
106
- onClick: toggleColorScheme,
107
- variant: "default",
108
- size,
109
- "aria-label": t("gds.aria.themeToggle", "Toggle color scheme"),
110
- children: isDark ? /* @__PURE__ */ jsx3(GdsIcons.Sun, { size: "1.2rem" }) : /* @__PURE__ */ jsx3(GdsIcons.Moon, { size: "1.2rem" })
111
- }
112
- );
113
- }
114
-
115
- // src/GameBoardTile.tsx
116
- import { Center, Paper, Text as Text2, UnstyledButton, useMantineTheme } from "@mantine/core";
117
- import { useMediaQuery } from "@mantine/hooks";
118
- import { jsx as jsx4 } from "react/jsx-runtime";
119
- function GameBoardTile({
120
- face,
121
- revealed,
122
- matched,
123
- disabled,
124
- onPress,
125
- highlightColor
126
- }) {
127
- const theme = useMantineTheme();
128
- const reduceMotion = useMediaQuery("(prefers-reduced-motion: reduce)");
129
- const highlighted = revealed && !matched;
130
- const revealBg = highlightColor ?? (typeof theme.primaryColor === "string" ? `${theme.primaryColor}.5` : "violet.5");
131
- return /* @__PURE__ */ jsx4(UnstyledButton, { w: "100%", disabled, onClick: onPress, "aria-pressed": revealed, children: /* @__PURE__ */ jsx4(
132
- Paper,
133
- {
134
- withBorder: true,
135
- radius: "md",
136
- p: "md",
137
- bg: revealed ? revealBg : "dark.6",
138
- styles: {
139
- root: {
140
- aspectRatio: "1",
141
- opacity: matched ? 0.55 : 1,
142
- cursor: disabled ? "not-allowed" : "pointer",
143
- transition: reduceMotion ? "opacity 0.2s ease" : "transform 0.25s ease, background-color 0.25s ease, opacity 0.25s ease",
144
- transform: reduceMotion || !highlighted ? "scale(1)" : "scale(1.02)"
145
- }
146
- },
147
- children: /* @__PURE__ */ jsx4(Center, { h: "100%", children: /* @__PURE__ */ jsx4(Text2, { size: "xl", fw: 700, children: face }) })
148
- }
149
- ) });
150
- }
151
-
152
- // src/DiscoveryShell.tsx
153
- import { AppShell as MantineAppShell, Box, Burger, Group as Group2, ScrollArea } from "@mantine/core";
154
- import { useDisclosure } from "@mantine/hooks";
155
- import { jsx as jsx5, jsxs as jsxs2 } from "react/jsx-runtime";
156
- function DiscoveryShell({
157
- header,
158
- sidebar,
159
- footer,
160
- children,
161
- mobileNavigationLabel = "Toggle navigation",
162
- defaultSidebarOpen = false,
163
- stickySidebar = true,
164
- sidebarWidth = 280,
165
- headerHeight = 60,
166
- shellPadding = "md",
167
- collapseBreakpoint = "sm"
168
- }) {
169
- const [opened, { toggle, close }] = useDisclosure(defaultSidebarOpen);
170
- return /* @__PURE__ */ jsxs2(
171
- MantineAppShell,
172
- {
173
- header: { height: headerHeight },
174
- footer: footer ? { height: 68 } : void 0,
175
- navbar: {
176
- width: sidebarWidth,
177
- breakpoint: collapseBreakpoint,
178
- collapsed: { mobile: !opened }
179
- },
180
- padding: shellPadding,
181
- children: [
182
- /* @__PURE__ */ jsx5(MantineAppShell.Header, { children: /* @__PURE__ */ jsxs2(Group2, { h: "100%", px: "md", gap: "sm", wrap: "nowrap", children: [
183
- /* @__PURE__ */ jsx5(
184
- Burger,
185
- {
186
- opened,
187
- onClick: toggle,
188
- hiddenFrom: collapseBreakpoint,
189
- size: "sm",
190
- "aria-label": mobileNavigationLabel
191
- }
192
- ),
193
- /* @__PURE__ */ jsx5(Box, { style: { flex: 1, minWidth: 0 }, children: header })
194
- ] }) }),
195
- /* @__PURE__ */ jsx5(MantineAppShell.Navbar, { p: "md", "data-sticky-sidebar": stickySidebar || void 0, children: /* @__PURE__ */ jsx5(ScrollArea, { h: "100%", type: "auto", children: /* @__PURE__ */ jsx5(
196
- Box,
197
- {
198
- h: "100%",
199
- style: stickySidebar ? {
200
- display: "flex",
201
- flexDirection: "column"
202
- } : void 0,
203
- children: sidebar
204
- }
205
- ) }) }),
206
- footer ? /* @__PURE__ */ jsx5(MantineAppShell.Footer, { children: /* @__PURE__ */ jsx5(Group2, { h: "100%", px: "md", justify: "space-around", wrap: "nowrap", children: footer }) }) : null,
207
- /* @__PURE__ */ jsx5(MantineAppShell.Main, { onClick: () => close(), children })
208
- ]
209
- }
210
- );
211
- }
212
-
213
- // src/SidebarNav.tsx
214
- import { forwardRef } from "react";
215
- import { Box as Box2, NavLink, Stack, Text as Text3, createPolymorphicComponent } from "@mantine/core";
216
- import { useGdsTranslation as useGdsTranslation3 } from "@doneisbetter/gds-theme";
217
- import { jsx as jsx6, jsxs as jsxs3 } from "react/jsx-runtime";
218
- function SidebarNav({ children, ariaLabel = "Primary navigation", gap = "md" }) {
219
- return /* @__PURE__ */ jsx6(Stack, { component: "nav", "aria-label": ariaLabel, gap, h: "100%", children });
220
- }
221
- function SidebarNavSection({ label, children, pushToBottom = false }) {
222
- return /* @__PURE__ */ jsxs3(Stack, { gap: "xs", mt: pushToBottom ? "auto" : void 0, children: [
223
- label ? /* @__PURE__ */ jsx6(Text3, { size: "xs", fw: 700, c: "dimmed", children: label }) : null,
224
- /* @__PURE__ */ jsx6(Stack, { gap: 4, children })
225
- ] });
226
- }
227
- var _SidebarNavItem = forwardRef(
228
- ({
229
- action,
230
- label,
231
- description,
232
- badge,
233
- icon,
234
- "aria-label": ariaLabel,
235
- "aria-current": ariaCurrent,
236
- vocabularyPacks = [],
237
- ...props
238
- }, ref) => {
239
- const { t } = useGdsTranslation3();
240
- const config = action ? resolveSemanticActionConfig(action, vocabularyPacks) : null;
241
- const Icon = config?.icon;
242
- const resolvedLabel = label ?? (action ? getSemanticActionLabel(action, t, vocabularyPacks) : void 0);
243
- return /* @__PURE__ */ jsx6(
244
- NavLink,
245
- {
246
- ref,
247
- label: resolvedLabel,
248
- description,
249
- leftSection: icon ?? (Icon ? /* @__PURE__ */ jsx6(Icon, { size: "1rem", stroke: 1.5 }) : void 0),
250
- rightSection: badge ? /* @__PURE__ */ jsx6(Box2, { children: badge }) : props.rightSection,
251
- "aria-label": ariaLabel ?? (typeof resolvedLabel === "string" ? resolvedLabel : void 0),
252
- "aria-current": props.active ? "page" : ariaCurrent,
253
- ...props
254
- }
255
- );
256
- }
257
- );
258
- var SidebarNavItem = createPolymorphicComponent(_SidebarNavItem);
259
-
260
- // src/DocsCodeBlock.tsx
261
- import { useState as useState2 } from "react";
262
- import { ActionIcon as ActionIcon2, Code, Group as Group3, Paper as Paper2, Stack as Stack2, Text as Text4 } from "@mantine/core";
263
- import { jsx as jsx7, jsxs as jsxs4 } from "react/jsx-runtime";
264
- function DocsCodeBlock({ code, language, title, withCopy = true }) {
265
- const [copied, setCopied] = useState2(false);
266
- const handleCopy = async () => {
267
- if (!navigator?.clipboard) {
268
- return;
269
- }
270
- await navigator.clipboard.writeText(code);
271
- setCopied(true);
272
- window.setTimeout(() => setCopied(false), 1200);
273
- };
274
- return /* @__PURE__ */ jsx7(Paper2, { withBorder: true, radius: "lg", p: "md", children: /* @__PURE__ */ jsxs4(Stack2, { gap: "sm", children: [
275
- title || withCopy ? /* @__PURE__ */ jsxs4(Group3, { justify: "space-between", align: "center", children: [
276
- /* @__PURE__ */ jsxs4(Stack2, { gap: 0, children: [
277
- title ? /* @__PURE__ */ jsx7(Text4, { fw: 600, children: title }) : null,
278
- language ? /* @__PURE__ */ jsx7(Text4, { size: "xs", c: "dimmed", children: language }) : null
279
- ] }),
280
- withCopy ? /* @__PURE__ */ jsx7(
281
- ActionIcon2,
282
- {
283
- variant: "subtle",
284
- "aria-label": copied ? "Copied code block" : "Copy code block",
285
- onClick: () => {
286
- void handleCopy();
287
- },
288
- children: /* @__PURE__ */ jsx7(GdsIcons.Copy, { size: "1rem" })
289
- }
290
- ) : null
291
- ] }) : null,
292
- /* @__PURE__ */ jsx7(Code, { block: true, children: code })
293
- ] }) });
294
- }
295
-
296
- // src/ShareButtonGroup.tsx
297
- import { useState as useState3 } from "react";
298
- import { ActionIcon as ActionIcon3, Button as Button2, Group as Group4, Stack as Stack3, Text as Text5 } from "@mantine/core";
299
- import { jsx as jsx8, jsxs as jsxs5 } from "react/jsx-runtime";
300
- var channelLabels = {
301
- native: "Share",
302
- copy: "Copy link",
303
- mail: "Email",
304
- message: "Message",
305
- x: "Share on X",
306
- facebook: "Share on Facebook",
307
- linkedin: "Share on LinkedIn",
308
- whatsapp: "Share on WhatsApp",
309
- telegram: "Share on Telegram"
310
- };
311
- function encodeShare(url, title, text) {
312
- const safeUrl = encodeURIComponent(url);
313
- const safeTitle = encodeURIComponent(title ?? "");
314
- const safeText = encodeURIComponent(text ?? title ?? "");
315
- return {
316
- mail: `mailto:?subject=${safeTitle}&body=${safeText ? `${safeText}%0A%0A` : ""}${safeUrl}`,
317
- message: `sms:?&body=${safeText ? `${safeText}%20` : ""}${safeUrl}`,
318
- x: `https://x.com/intent/tweet?text=${safeText ? `${safeText}%20` : ""}${safeUrl}`,
319
- facebook: `https://www.facebook.com/sharer/sharer.php?u=${safeUrl}`,
320
- linkedin: `https://www.linkedin.com/sharing/share-offsite/?url=${safeUrl}`,
321
- whatsapp: `https://wa.me/?text=${safeText ? `${safeText}%20` : ""}${safeUrl}`,
322
- telegram: `https://t.me/share/url?url=${safeUrl}&text=${safeText}`
323
- };
324
- }
325
- function ShareAction({
326
- channel,
327
- compact,
328
- href,
329
- onClick
330
- }) {
331
- const label = channelLabels[channel];
332
- const Icon = channel === "copy" ? GdsIcons.Copy : channel === "mail" ? GdsIcons.Mail : channel === "message" ? GdsIcons.Message : GdsIcons.Refer;
333
- if (compact) {
334
- return href ? /* @__PURE__ */ jsx8(ActionIcon3, { component: "a", href, target: "_blank", rel: "noreferrer", variant: "subtle", size: "lg", "aria-label": label, children: /* @__PURE__ */ jsx8(Icon, { size: "1rem", stroke: 1.75 }) }) : /* @__PURE__ */ jsx8(ActionIcon3, { variant: "subtle", size: "lg", "aria-label": label, onClick, children: /* @__PURE__ */ jsx8(Icon, { size: "1rem", stroke: 1.75 }) });
335
- }
336
- return href ? /* @__PURE__ */ jsx8(Button2, { component: "a", href, target: "_blank", rel: "noreferrer", variant: "default", leftSection: /* @__PURE__ */ jsx8(Icon, { size: "1rem", stroke: 1.75 }), children: label }) : /* @__PURE__ */ jsx8(Button2, { variant: "default", leftSection: /* @__PURE__ */ jsx8(Icon, { size: "1rem", stroke: 1.75 }), onClick, children: label });
337
- }
338
- function ShareButtonGroup({
339
- url,
340
- title,
341
- text,
342
- channels = ["native", "copy", "mail"],
343
- compact = false,
344
- label = "Share this",
345
- description
346
- }) {
347
- const [copied, setCopied] = useState3(false);
348
- const [shared, setShared] = useState3(false);
349
- const hrefs = encodeShare(url, title, text);
350
- async function handleCopy() {
351
- await navigator.clipboard?.writeText?.(url);
352
- setCopied(true);
353
- setTimeout(() => setCopied(false), 1800);
354
- }
355
- async function handleNativeShare() {
356
- if (navigator.share) {
357
- await navigator.share({ url, title, text });
358
- setShared(true);
359
- setTimeout(() => setShared(false), 1800);
360
- return;
361
- }
362
- await handleCopy();
363
- }
364
- return /* @__PURE__ */ jsxs5(Stack3, { gap: "sm", children: [
365
- /* @__PURE__ */ jsxs5(Stack3, { gap: 2, children: [
366
- /* @__PURE__ */ jsx8(Text5, { fw: 600, children: label }),
367
- description ? /* @__PURE__ */ jsx8(Text5, { size: "sm", c: "dimmed", children: description }) : null
368
- ] }),
369
- /* @__PURE__ */ jsx8(Group4, { gap: "sm", wrap: "wrap", children: channels.map((channel) => {
370
- if (channel === "copy") {
371
- return /* @__PURE__ */ jsx8(ShareAction, { channel, compact, onClick: () => void handleCopy() }, channel);
372
- }
373
- if (channel === "native") {
374
- return /* @__PURE__ */ jsx8(ShareAction, { channel, compact, onClick: () => void handleNativeShare() }, channel);
375
- }
376
- return /* @__PURE__ */ jsx8(ShareAction, { channel, compact, href: hrefs[channel] }, channel);
377
- }) }),
378
- copied ? /* @__PURE__ */ jsx8(Text5, { size: "sm", c: "teal", children: "Link copied." }) : null,
379
- shared ? /* @__PURE__ */ jsx8(Text5, { size: "sm", c: "teal", children: "Share sheet opened." }) : null
380
- ] });
381
- }
382
-
383
- // src/UploadDropzone.tsx
384
- import { useRef, useState as useState4 } from "react";
385
- import { Box as Box3, Button as Button3, Group as Group5, Stack as Stack4, Text as Text6 } from "@mantine/core";
386
- import { jsx as jsx9, jsxs as jsxs6 } from "react/jsx-runtime";
387
- function UploadDropzone({
388
- title,
389
- description,
390
- onFilesSelected,
391
- accept,
392
- multiple = true,
393
- actionLabel = "Choose files",
394
- mode = "panel"
395
- }) {
396
- const inputRef = useRef(null);
397
- const [dragging, setDragging] = useState4(false);
398
- const UploadIcon = GdsIcons.Upload;
399
- const forwardFiles = (files) => {
400
- if (!files?.length || !onFilesSelected) {
401
- return;
402
- }
403
- onFilesSelected(Array.from(files));
404
- };
405
- return /* @__PURE__ */ jsxs6(
406
- Box3,
407
- {
408
- onDragOver: (event) => {
409
- event.preventDefault();
410
- setDragging(true);
411
- },
412
- onDragLeave: () => setDragging(false),
413
- onDrop: (event) => {
414
- event.preventDefault();
415
- setDragging(false);
416
- forwardFiles(event.dataTransfer.files);
417
- },
418
- p: mode === "inline" ? "md" : "xl",
419
- style: {
420
- border: `1px dashed var(${dragging ? "--mantine-color-violet-6" : "--mantine-color-default-border"})`,
421
- borderRadius: "var(--mantine-radius-lg)",
422
- background: dragging ? "var(--mantine-color-violet-light)" : "transparent"
423
- },
424
- children: [
425
- /* @__PURE__ */ jsx9(
426
- "input",
427
- {
428
- ref: inputRef,
429
- type: "file",
430
- hidden: true,
431
- accept,
432
- multiple,
433
- onChange: (event) => forwardFiles(event.currentTarget.files)
434
- }
435
- ),
436
- /* @__PURE__ */ jsxs6(Stack4, { align: mode === "inline" ? "flex-start" : "center", ta: mode === "inline" ? "left" : "center", gap: "sm", children: [
437
- /* @__PURE__ */ jsx9(UploadIcon, { size: "1.5rem" }),
438
- /* @__PURE__ */ jsx9(Text6, { fw: 600, children: title }),
439
- description ? /* @__PURE__ */ jsx9(Text6, { size: "sm", c: "dimmed", children: description }) : null,
440
- /* @__PURE__ */ jsx9(Group5, { children: /* @__PURE__ */ jsx9(Button3, { variant: "light", onClick: () => inputRef.current?.click(), children: actionLabel }) })
441
- ] })
442
- ]
443
- }
444
- );
445
- }
446
-
447
- // src/AccessRecoveryPanel.tsx
448
- import { Group as Group6 } from "@mantine/core";
449
- import { useGdsTranslation as useGdsTranslation4 } from "@doneisbetter/gds-theme";
450
- import { jsx as jsx10 } from "react/jsx-runtime";
451
- var stateBlockVariantByState = {
452
- unauthenticated: "permission",
453
- "expired-session": "info",
454
- forbidden: "permission",
455
- missing: "error",
456
- unavailable: "error"
457
- };
458
- var defaultCopyByState = {
459
- unauthenticated: {
460
- title: "Sign in required",
461
- description: "Please sign in to continue to this content."
462
- },
463
- "expired-session": {
464
- title: "Session expired",
465
- description: "Sign in again or retry to continue where you left off."
466
- },
467
- forbidden: {
468
- title: "You do not have access",
469
- description: "This content is outside your current permissions or scope."
470
- },
471
- missing: {
472
- title: "Content not found",
473
- description: "The resource may have moved, been deleted, or never existed in this scope."
474
- },
475
- unavailable: {
476
- title: "Content is temporarily unavailable",
477
- description: "Try again in a moment or return to a safe destination."
478
- }
479
- };
480
- function defaultActionsForState(state, {
481
- onRetry,
482
- onSignIn,
483
- onBack,
484
- supportAction
485
- }) {
486
- const signInAction = onSignIn ? { action: "login", onClick: onSignIn } : null;
487
- const retryAction = onRetry ? { action: "refresh", onClick: onRetry, variant: "light" } : null;
488
- const backAction = onBack ? { action: "back", onClick: onBack, variant: "default" } : null;
489
- switch (state) {
490
- case "unauthenticated":
491
- return { primary: signInAction, secondary: backAction, tertiary: supportAction ?? null };
492
- case "expired-session":
493
- return {
494
- primary: signInAction ?? retryAction,
495
- secondary: retryAction && signInAction ? retryAction : backAction,
496
- tertiary: supportAction ?? null
497
- };
498
- case "forbidden":
499
- return { primary: backAction, secondary: supportAction ?? null, tertiary: null };
500
- case "missing":
501
- return { primary: backAction, secondary: supportAction ?? null, tertiary: null };
502
- case "unavailable":
503
- return {
504
- primary: retryAction ?? backAction,
505
- secondary: retryAction && backAction ? backAction : supportAction ?? null,
506
- tertiary: retryAction && backAction ? supportAction ?? null : null
507
- };
508
- }
509
- }
510
- function ActionGroup({
511
- primaryAction,
512
- secondaryAction,
513
- tertiaryAction
514
- }) {
515
- const actions = [primaryAction, secondaryAction, tertiaryAction].filter(Boolean);
516
- if (actions.length === 0) {
517
- return null;
518
- }
519
- return /* @__PURE__ */ jsx10(Group6, { gap: "sm", justify: "center", wrap: "wrap", children: actions.map((actionConfig, index) => /* @__PURE__ */ jsx10(
520
- SemanticButton,
521
- {
522
- action: actionConfig.action,
523
- onClick: actionConfig.onClick,
524
- loading: actionConfig.loading,
525
- disabled: actionConfig.disabled,
526
- color: actionConfig.color,
527
- variant: actionConfig.variant ?? (index === 0 ? "filled" : "default")
528
- },
529
- `${actionConfig.action}-${index}`
530
- )) });
531
- }
532
- function AccessRecoveryPanel({
533
- state,
534
- title,
535
- description,
536
- primaryAction,
537
- secondaryAction,
538
- tertiaryAction,
539
- onRetry,
540
- onSignIn,
541
- onBack,
542
- supportAction,
543
- compact = false
544
- }) {
545
- const { t } = useGdsTranslation4();
546
- const defaultCopy = defaultCopyByState[state];
547
- const defaults = defaultActionsForState(state, {
548
- onRetry,
549
- onSignIn,
550
- onBack,
551
- supportAction
552
- });
553
- return /* @__PURE__ */ jsx10(
554
- StateBlock,
555
- {
556
- variant: stateBlockVariantByState[state],
557
- compact,
558
- title: title ?? t(`gds.accessRecovery.${state}.title`, defaultCopy.title),
559
- description: description ?? t(`gds.accessRecovery.${state}.description`, defaultCopy.description),
560
- action: /* @__PURE__ */ jsx10(
561
- ActionGroup,
562
- {
563
- primaryAction: primaryAction ?? defaults.primary,
564
- secondaryAction: secondaryAction ?? defaults.secondary,
565
- tertiaryAction: tertiaryAction ?? defaults.tertiary
566
- }
567
- )
568
- }
569
- );
570
- }
571
-
572
- export {
573
- SemanticButton,
574
- ConfirmDialog,
575
- ThemeToggle,
576
- GameBoardTile,
577
- DiscoveryShell,
578
- SidebarNav,
579
- SidebarNavSection,
580
- SidebarNavItem,
581
- DocsCodeBlock,
582
- ShareButtonGroup,
583
- UploadDropzone,
584
- AccessRecoveryPanel
585
- };