@lexibase/rdx-ui 3.2.1 → 3.3.0
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/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lexibase/rdx-ui",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.3.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"engines": {
|
|
6
6
|
"node": "^22.18.0 || ^24.11.0"
|
|
@@ -37,7 +37,7 @@
|
|
|
37
37
|
"tailwind-merge": "^3.7.0",
|
|
38
38
|
"tailwindcss": "^4.3.3",
|
|
39
39
|
"tw-animate-css": "^1.4.0",
|
|
40
|
-
"@lexibase/rdx-types": "2.
|
|
40
|
+
"@lexibase/rdx-types": "2.1.0"
|
|
41
41
|
},
|
|
42
42
|
"peerDependencies": {
|
|
43
43
|
"next": "^16.4.2",
|
|
@@ -56,8 +56,8 @@
|
|
|
56
56
|
"react-dom": "19.3.1",
|
|
57
57
|
"tailwindcss": "^4.3.3",
|
|
58
58
|
"typescript": "6.0.3",
|
|
59
|
-
"@rdx/
|
|
60
|
-
"@rdx/
|
|
59
|
+
"@rdx/eslint-config": "1.0.0",
|
|
60
|
+
"@rdx/typescript-config": "1.0.0"
|
|
61
61
|
},
|
|
62
62
|
"exports": {
|
|
63
63
|
"./globals.css": {
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
'use client'
|
|
2
|
+
|
|
3
|
+
import { ExternalLink, Languages } from 'lucide-react'
|
|
4
|
+
import Link from 'next/link'
|
|
5
|
+
import { Button } from './button'
|
|
6
|
+
import {
|
|
7
|
+
DropdownMenu,
|
|
8
|
+
DropdownMenuContent,
|
|
9
|
+
DropdownMenuGroup,
|
|
10
|
+
DropdownMenuLinkItem,
|
|
11
|
+
DropdownMenuSeparator,
|
|
12
|
+
DropdownMenuTrigger,
|
|
13
|
+
} from './dropdown-menu'
|
|
14
|
+
import { getMessages } from '../lib/i18n'
|
|
15
|
+
|
|
16
|
+
/** Locale navigation composes the shared shadcn/ui Base UI menu. */
|
|
17
|
+
export function LanguageDropdown({
|
|
18
|
+
options,
|
|
19
|
+
current,
|
|
20
|
+
lang,
|
|
21
|
+
contributionUrl,
|
|
22
|
+
}: {
|
|
23
|
+
options: { code: string; label: string; href: string }[]
|
|
24
|
+
current: string
|
|
25
|
+
lang?: string
|
|
26
|
+
contributionUrl?: string
|
|
27
|
+
}) {
|
|
28
|
+
const selected = options.find((option) => option.code === current)
|
|
29
|
+
if (!selected) return null
|
|
30
|
+
const messages = getMessages(lang)
|
|
31
|
+
return (
|
|
32
|
+
<DropdownMenu>
|
|
33
|
+
<DropdownMenuTrigger
|
|
34
|
+
render={
|
|
35
|
+
<Button
|
|
36
|
+
variant="outline"
|
|
37
|
+
size="sm"
|
|
38
|
+
aria-label={`${getMessages(lang).documentationLanguage}: ${selected.label}`}
|
|
39
|
+
data-rdx-language-trigger
|
|
40
|
+
/>
|
|
41
|
+
}
|
|
42
|
+
>
|
|
43
|
+
<Languages className="size-4" aria-hidden="true" />
|
|
44
|
+
<span className="hidden sm:inline">{selected.label}</span>
|
|
45
|
+
<span className="sm:hidden">{selected.code}</span>
|
|
46
|
+
</DropdownMenuTrigger>
|
|
47
|
+
<DropdownMenuContent align="end" collisionPadding={8}>
|
|
48
|
+
<DropdownMenuGroup>
|
|
49
|
+
{options.map((option) => (
|
|
50
|
+
<DropdownMenuLinkItem
|
|
51
|
+
key={option.code}
|
|
52
|
+
className={option.code === current ? 'bg-accent/30' : undefined}
|
|
53
|
+
closeOnClick
|
|
54
|
+
render={<Link href={option.href} hrefLang={option.code} />}
|
|
55
|
+
aria-current={option.code === current ? 'true' : undefined}
|
|
56
|
+
>
|
|
57
|
+
{option.label}
|
|
58
|
+
</DropdownMenuLinkItem>
|
|
59
|
+
))}
|
|
60
|
+
</DropdownMenuGroup>
|
|
61
|
+
{contributionUrl && (
|
|
62
|
+
<>
|
|
63
|
+
<DropdownMenuSeparator />
|
|
64
|
+
<DropdownMenuLinkItem
|
|
65
|
+
closeOnClick
|
|
66
|
+
render={
|
|
67
|
+
<a
|
|
68
|
+
href={contributionUrl}
|
|
69
|
+
target="_blank"
|
|
70
|
+
rel="noopener noreferrer"
|
|
71
|
+
/>
|
|
72
|
+
}
|
|
73
|
+
data-rdx-help-translate
|
|
74
|
+
>
|
|
75
|
+
{messages.helpTranslate}
|
|
76
|
+
<ExternalLink className="ml-auto size-3.5" aria-hidden="true" />
|
|
77
|
+
<span className="sr-only"> ({messages.opensInNewTab})</span>
|
|
78
|
+
</DropdownMenuLinkItem>
|
|
79
|
+
</>
|
|
80
|
+
)}
|
|
81
|
+
</DropdownMenuContent>
|
|
82
|
+
</DropdownMenu>
|
|
83
|
+
)
|
|
84
|
+
}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
'use client'
|
|
2
|
+
|
|
3
|
+
import type { ComponentProps, ReactNode } from 'react'
|
|
4
|
+
import { useParams } from 'next/navigation'
|
|
5
|
+
import { Navbar } from './navbar'
|
|
6
|
+
import { NotFound } from './not-found'
|
|
7
|
+
import { LanguageDropdown } from './language-dropdown'
|
|
8
|
+
|
|
9
|
+
/** Error boundaries do not receive server route params; use Next's route context. */
|
|
10
|
+
export function LocalizedNotFound({
|
|
11
|
+
locales,
|
|
12
|
+
defaultLocale,
|
|
13
|
+
brand,
|
|
14
|
+
homepage,
|
|
15
|
+
}: {
|
|
16
|
+
locales: { code: string; path: string; label: string }[]
|
|
17
|
+
defaultLocale: string
|
|
18
|
+
brand: Pick<
|
|
19
|
+
ComponentProps<typeof Navbar>,
|
|
20
|
+
'title' | 'siteTitle' | 'github' | 'showToggleMode'
|
|
21
|
+
> & { logo: ReactNode }
|
|
22
|
+
homepage: boolean
|
|
23
|
+
}) {
|
|
24
|
+
const params = useParams<{ locale?: string }>()
|
|
25
|
+
const selected =
|
|
26
|
+
locales.find((locale) => locale.path === params.locale) ??
|
|
27
|
+
locales.find((locale) => locale.code === defaultLocale)!
|
|
28
|
+
const docsHref = `/${selected.path}/docs`
|
|
29
|
+
return (
|
|
30
|
+
<>
|
|
31
|
+
<Navbar
|
|
32
|
+
{...brand}
|
|
33
|
+
lang={selected.code}
|
|
34
|
+
homeHref={homepage ? '/' : docsHref}
|
|
35
|
+
docsHref={docsHref}
|
|
36
|
+
languageMenu={
|
|
37
|
+
<LanguageDropdown
|
|
38
|
+
lang={selected.code}
|
|
39
|
+
current={selected.code}
|
|
40
|
+
options={locales.map((locale) => ({
|
|
41
|
+
...locale,
|
|
42
|
+
href: `/${locale.path}/docs`,
|
|
43
|
+
}))}
|
|
44
|
+
/>
|
|
45
|
+
}
|
|
46
|
+
/>
|
|
47
|
+
<NotFound lang={selected.code} href={docsHref} />
|
|
48
|
+
</>
|
|
49
|
+
)
|
|
50
|
+
}
|
|
@@ -17,6 +17,7 @@ export function Navbar({
|
|
|
17
17
|
docsHref = '/docs',
|
|
18
18
|
docsLink,
|
|
19
19
|
versionMenu,
|
|
20
|
+
languageMenu,
|
|
20
21
|
search,
|
|
21
22
|
github,
|
|
22
23
|
showToggleMode = false,
|
|
@@ -29,6 +30,7 @@ export function Navbar({
|
|
|
29
30
|
docsHref?: string
|
|
30
31
|
docsLink?: ReactNode
|
|
31
32
|
versionMenu?: ReactNode
|
|
33
|
+
languageMenu?: ReactNode
|
|
32
34
|
search?: ReactNode
|
|
33
35
|
github?: { visible: boolean; url: string }
|
|
34
36
|
showToggleMode?: boolean
|
|
@@ -55,6 +57,7 @@ export function Navbar({
|
|
|
55
57
|
<div className="flex items-center gap-x-1 md:gap-x-2 h-4">
|
|
56
58
|
{search}
|
|
57
59
|
{versionMenu}
|
|
60
|
+
{languageMenu}
|
|
58
61
|
{docsLink ?? (
|
|
59
62
|
<Button variant="link" size="sm" href={docsHref}>
|
|
60
63
|
{messages.docs}
|
package/src/lib/i18n.ts
CHANGED
|
@@ -1,5 +1,13 @@
|
|
|
1
1
|
/** Shared labels only: document content and author-provided names stay untouched. */
|
|
2
2
|
const en = {
|
|
3
|
+
documentationLanguage: 'Documentation language',
|
|
4
|
+
translationUnavailable: 'Translation unavailable',
|
|
5
|
+
translationFallback:
|
|
6
|
+
'This page is not available in {requested}. You are reading the {original} version.',
|
|
7
|
+
viewOriginal: 'View the original page',
|
|
8
|
+
helpTranslate: 'Help translate',
|
|
9
|
+
translateThisPage: 'Translate this page',
|
|
10
|
+
opensInNewTab: 'opens in a new tab',
|
|
3
11
|
keyboardJoiner: ' plus ',
|
|
4
12
|
keyboardControl: 'Control',
|
|
5
13
|
keyboardShift: 'Shift',
|
|
@@ -93,6 +101,14 @@ export type InterfaceMessages = { [Key in keyof typeof en]: string }
|
|
|
93
101
|
export type InterfaceLocale = 'en' | 'pt-BR'
|
|
94
102
|
|
|
95
103
|
const ptBR = {
|
|
104
|
+
documentationLanguage: 'Idioma da documentação',
|
|
105
|
+
translationUnavailable: 'Tradução indisponível',
|
|
106
|
+
translationFallback:
|
|
107
|
+
'Esta página não está disponível em {requested}. Você está lendo a versão em {original}.',
|
|
108
|
+
viewOriginal: 'Ver a página original',
|
|
109
|
+
helpTranslate: 'Ajude a traduzir',
|
|
110
|
+
translateThisPage: 'Traduza esta página',
|
|
111
|
+
opensInNewTab: 'abre em uma nova aba',
|
|
96
112
|
keyboardJoiner: ' mais ',
|
|
97
113
|
keyboardControl: 'Control',
|
|
98
114
|
keyboardShift: 'Shift',
|