lightnet 4.5.1 → 4.6.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/CHANGELOG.md +18 -0
- package/package.json +13 -13
- package/src/components/CategoriesSection.astro +68 -72
- package/src/components/HeroSection.astro +23 -29
- package/src/components/HighlightSection.astro +22 -28
- package/src/components/MediaGallerySection.astro +52 -58
- package/src/components/MediaList.astro +56 -58
- package/src/components/Section.astro +19 -21
- package/src/components/VideoPlayer.astro +55 -57
- package/src/layouts/MarkdownPage.astro +2 -1
- package/src/layouts/Page.astro +4 -8
- package/src/layouts/components/footer/Footer.astro +33 -36
- package/src/layouts/components/footer/LanguageSelectionMenu.astro +9 -9
- package/src/layouts/components/header/LanguageSelectionMenu.astro +10 -12
- package/src/layouts/components/header/PageNavigation.astro +26 -30
- package/src/layouts/components/header/PageTitle.astro +15 -20
- package/src/layouts/components/meta/Favicon.astro +3 -5
- package/src/layouts/components/meta/ViewTransition.astro +0 -1
- package/src/pages/404Route.astro +2 -1
- package/src/pages/details-page/DetailsPageRoute.astro +3 -5
- package/src/pages/details-page/components/AudioPanel.astro +6 -8
- package/src/pages/details-page/components/AudioPlayer.astro +28 -30
- package/src/pages/details-page/components/ContentSection.astro +37 -41
- package/src/pages/details-page/components/DescriptionSection.astro +9 -11
- package/src/pages/details-page/components/MainDetailsSection.astro +1 -3
- package/src/pages/details-page/components/MediaCollectionsSection.astro +3 -5
- package/src/pages/details-page/components/VideoDetailsSection.astro +1 -3
- package/src/pages/details-page/components/main-details/Authors.astro +5 -7
- package/src/pages/details-page/components/main-details/EditButton.astro +3 -2
- package/src/pages/details-page/components/main-details/OpenButton.astro +3 -5
- package/src/pages/details-page/components/main-details/ShareButton.astro +3 -2
- package/src/pages/details-page/components/more-details/Categories.astro +18 -20
- package/src/pages/details-page/components/more-details/Languages.astro +10 -12
- package/src/utils/verify-schema.ts +2 -2
|
@@ -93,62 +93,60 @@ async function parseUrl(
|
|
|
93
93
|
---
|
|
94
94
|
|
|
95
95
|
<div class="aspect-video w-full overflow-hidden bg-black md:rounded-lg">
|
|
96
|
-
{
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
<
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
<
|
|
131
|
-
<span class="text-sm font-medium">{t("ln.external-link")}</span>
|
|
132
|
-
</div>
|
|
133
|
-
)}
|
|
134
|
-
<div class="absolute inset-0 z-10 bg-black/35 transition group-hover:bg-black/50" />
|
|
135
|
-
<div class="absolute inset-0 z-20 flex items-center justify-center">
|
|
136
|
-
<span class="flex h-14 w-14 items-center justify-center rounded-full bg-white/90 text-black shadow-lg transition group-hover:scale-105">
|
|
137
|
-
<svg
|
|
138
|
-
class="h-7 w-7"
|
|
139
|
-
viewBox="0 0 24 24"
|
|
140
|
-
fill="currentColor"
|
|
141
|
-
aria-hidden="true"
|
|
142
|
-
>
|
|
143
|
-
<path d="M8 5v14l11-7z" />
|
|
144
|
-
</svg>
|
|
145
|
-
</span>
|
|
96
|
+
{host === "youtube" ? (
|
|
97
|
+
<iframe
|
|
98
|
+
class="h-full w-full"
|
|
99
|
+
src={`https://www.youtube-nocookie.com/embed/${id}`}
|
|
100
|
+
title={title}
|
|
101
|
+
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share"
|
|
102
|
+
referrerpolicy="strict-origin-when-cross-origin"
|
|
103
|
+
allowfullscreen
|
|
104
|
+
></iframe>
|
|
105
|
+
) : host === "vimeo" ? (
|
|
106
|
+
<iframe
|
|
107
|
+
class="h-full w-full"
|
|
108
|
+
title={title}
|
|
109
|
+
src={`https://player.vimeo.com/video/${id}`}
|
|
110
|
+
allow="autoplay; fullscreen; picture-in-picture"
|
|
111
|
+
allowfullscreen
|
|
112
|
+
></iframe>
|
|
113
|
+
) : host === "mp4" ? (
|
|
114
|
+
<video class="h-full w-full" controls preload="auto" poster={image}>
|
|
115
|
+
<source src={id} type="video/mp4" />
|
|
116
|
+
</video>
|
|
117
|
+
) : (
|
|
118
|
+
<a
|
|
119
|
+
class="group relative flex h-full w-full items-center justify-center focus:outline-none focus-visible:ring-2 focus-visible:ring-white/80 focus-visible:ring-offset-2 focus-visible:ring-offset-black"
|
|
120
|
+
{...getLinkAttributes(href ?? url)}
|
|
121
|
+
>
|
|
122
|
+
{imageMetadata ? (
|
|
123
|
+
<Image
|
|
124
|
+
src={imageMetadata}
|
|
125
|
+
alt={title ?? ""}
|
|
126
|
+
class="h-full w-full object-cover"
|
|
127
|
+
/>
|
|
128
|
+
) : (
|
|
129
|
+
<div class="flex h-full w-full items-center justify-center bg-gray-900 text-gray-200">
|
|
130
|
+
<span class="text-sm font-medium">{t("ln.external-link")}</span>
|
|
146
131
|
</div>
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
132
|
+
)}
|
|
133
|
+
<div class="absolute inset-0 z-10 bg-black/35 transition group-hover:bg-black/50" />
|
|
134
|
+
<div class="absolute inset-0 z-20 flex items-center justify-center">
|
|
135
|
+
<span class="flex h-14 w-14 items-center justify-center rounded-full bg-white/90 text-black shadow-lg transition group-hover:scale-105">
|
|
136
|
+
<svg
|
|
137
|
+
class="h-7 w-7"
|
|
138
|
+
viewBox="0 0 24 24"
|
|
139
|
+
fill="currentColor"
|
|
140
|
+
aria-hidden="true"
|
|
141
|
+
>
|
|
142
|
+
<path d="M8 5v14l11-7z" />
|
|
143
|
+
</svg>
|
|
144
|
+
</span>
|
|
145
|
+
</div>
|
|
146
|
+
<div class="absolute bottom-0 end-0 start-0 z-20 flex items-center gap-2 rounded bg-black/70 px-4 py-4 text-sm font-medium text-white backdrop-blur md:text-sm">
|
|
147
|
+
<ExternalLinkIcon className="shrink-0 rtl:scale-x-[-1]" />
|
|
148
|
+
{t("ln.external-link")}
|
|
149
|
+
</div>
|
|
150
|
+
</a>
|
|
151
|
+
)}
|
|
154
152
|
</div>
|
|
@@ -3,11 +3,12 @@ import Page, { type Props as PageProps } from "./Page.astro"
|
|
|
3
3
|
|
|
4
4
|
type Props = PageProps & {
|
|
5
5
|
className?: string
|
|
6
|
+
frontmatter: PageProps
|
|
6
7
|
}
|
|
7
8
|
const { className, ...pageProps } = Astro.props
|
|
8
9
|
---
|
|
9
10
|
|
|
10
|
-
<Page {...pageProps}>
|
|
11
|
+
<Page {...pageProps} {...pageProps.frontmatter}>
|
|
11
12
|
<article
|
|
12
13
|
class="prose mx-auto mt-8 max-w-screen-md px-4 prose-img:rounded-md sm:mt-16 md:px-8"
|
|
13
14
|
class:list={[className]}
|
package/src/layouts/Page.astro
CHANGED
|
@@ -72,11 +72,9 @@ const { direction } = resolveLanguage(currentLocale)
|
|
|
72
72
|
<head>
|
|
73
73
|
<meta charset="UTF-8" />
|
|
74
74
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
75
|
-
{
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
)
|
|
79
|
-
}
|
|
75
|
+
{(disallowSearchIndexing ?? config.disallowSearchIndexing) && (
|
|
76
|
+
<meta name="robots" content="noindex" />
|
|
77
|
+
)}
|
|
80
78
|
{CustomHead && <CustomHead />}
|
|
81
79
|
<title>{title ? `${title} | ${configTitle}` : configTitle}</title>
|
|
82
80
|
{description && <meta name="description" content={description} />}
|
|
@@ -85,9 +83,7 @@ const { direction } = resolveLanguage(currentLocale)
|
|
|
85
83
|
<Favicon />
|
|
86
84
|
<ViewTransition />
|
|
87
85
|
</head>
|
|
88
|
-
<body
|
|
89
|
-
class="flex min-h-screen flex-col overflow-y-scroll bg-gray-50 text-gray-900"
|
|
90
|
-
>
|
|
86
|
+
<body class="flex min-h-screen flex-col overflow-y-scroll bg-gray-50 text-gray-900">
|
|
91
87
|
<Header />
|
|
92
88
|
<main class={`grow pb-8 pt-14 sm:py-20 ${mainClass ?? ""}`}>
|
|
93
89
|
<slot />
|
|
@@ -46,43 +46,40 @@ const footerItems = [
|
|
|
46
46
|
<footer class="w-full border-t border-gray-200 bg-white text-sm text-gray-800">
|
|
47
47
|
<div
|
|
48
48
|
class="mx-auto flex w-full max-w-screen-xl px-4 py-4 md:px-8 md:py-6"
|
|
49
|
-
class:list={
|
|
50
|
-
|
|
51
|
-
|
|
49
|
+
class:list={
|
|
50
|
+
footerItems.length === 0
|
|
51
|
+
? "flex-col justify-between gap-4 sm:flex-row sm:items-center"
|
|
52
|
+
: "flex-col gap-2"
|
|
53
|
+
}
|
|
52
54
|
>
|
|
53
55
|
{shouldShowLanguageSelectionMenu && <LanguageSelectionMenu />}
|
|
54
|
-
{
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
{item.
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
)}
|
|
83
|
-
{config.credits && <Credits />}
|
|
84
|
-
</div>
|
|
85
|
-
)
|
|
86
|
-
}
|
|
56
|
+
{(footerItems.length > 0 || config.credits) && (
|
|
57
|
+
<div class="flex shrink flex-col gap-6 md:flex-row md:items-start md:justify-between">
|
|
58
|
+
{footerItems.length > 0 && (
|
|
59
|
+
<div class="flex w-full min-w-0 flex-1 shrink flex-wrap">
|
|
60
|
+
{footerItems.map((item, index) => (
|
|
61
|
+
<span class="inline-flex">
|
|
62
|
+
{item.type === "text" ? (
|
|
63
|
+
<span>{item.label}</span>
|
|
64
|
+
) : (
|
|
65
|
+
<a
|
|
66
|
+
{...getLinkAttributes(item.href)}
|
|
67
|
+
class="underline-offset-4 hover:underline"
|
|
68
|
+
>
|
|
69
|
+
{item.label}
|
|
70
|
+
</a>
|
|
71
|
+
)}
|
|
72
|
+
{index !== footerItems.length - 1 && (
|
|
73
|
+
<span class="shrink-0 px-2 text-gray-400" aria-hidden="true">
|
|
74
|
+
·
|
|
75
|
+
</span>
|
|
76
|
+
)}
|
|
77
|
+
</span>
|
|
78
|
+
))}
|
|
79
|
+
</div>
|
|
80
|
+
)}
|
|
81
|
+
{config.credits && <Credits />}
|
|
82
|
+
</div>
|
|
83
|
+
)}
|
|
87
84
|
</div>
|
|
88
85
|
</footer>
|
|
@@ -10,23 +10,23 @@ const { links: languageMenuItems } = getLanguageSelectionMenuItems({
|
|
|
10
10
|
pathname: Astro.url.pathname,
|
|
11
11
|
tConfigField,
|
|
12
12
|
})
|
|
13
|
+
const currentLanguage = languageMenuItems.find(({ active }) => active)
|
|
13
14
|
---
|
|
14
15
|
|
|
15
|
-
<label class="inline-flex items-center gap-2 py-2 font-medium">
|
|
16
|
+
<label class="relative inline-flex self-start items-center gap-2 rounded py-2 font-medium focus-within:ring-2 focus-within:ring-gray-900 focus-within:ring-offset-2">
|
|
16
17
|
<GlobeIcon className="h-5 w-5 shrink-0 text-gray-600" aria-hidden="true" />
|
|
18
|
+
<span aria-hidden="true">{currentLanguage?.label}</span>
|
|
17
19
|
<span class="sr-only">{t("ln.select-language")}</span>
|
|
18
20
|
<select
|
|
19
|
-
class="
|
|
21
|
+
class="absolute inset-0 h-full w-full cursor-pointer appearance-none opacity-0"
|
|
20
22
|
aria-label={t("ln.select-language")}
|
|
21
23
|
data-footer-language-select
|
|
22
24
|
>
|
|
23
|
-
{
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
))
|
|
29
|
-
}
|
|
25
|
+
{languageMenuItems.map(({ href, label, locale, active }) => (
|
|
26
|
+
<option value={href} selected={active} lang={locale}>
|
|
27
|
+
{label}
|
|
28
|
+
</option>
|
|
29
|
+
))}
|
|
30
30
|
</select>
|
|
31
31
|
</label>
|
|
32
32
|
<script>
|
|
@@ -20,15 +20,13 @@ const {
|
|
|
20
20
|
const disabled = !hasLocale && currentPath !== "/"
|
|
21
21
|
---
|
|
22
22
|
|
|
23
|
-
{
|
|
24
|
-
|
|
25
|
-
<
|
|
26
|
-
|
|
27
|
-
{
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
)
|
|
34
|
-
}
|
|
23
|
+
{translations.length > 1 && (
|
|
24
|
+
<Menu disabled={disabled} label="ln.select-language">
|
|
25
|
+
<GlobeIcon slot="icon" />
|
|
26
|
+
{translations.map(({ label, locale, active, href }) => (
|
|
27
|
+
<MenuItem href={href} hreflang={locale} active={active}>
|
|
28
|
+
{label}
|
|
29
|
+
</MenuItem>
|
|
30
|
+
))}
|
|
31
|
+
</Menu>
|
|
32
|
+
)}
|
|
@@ -40,39 +40,35 @@ const items = (config.mainMenu ?? []).map(({ href, label, requiresLocale }) => {
|
|
|
40
40
|
>
|
|
41
41
|
<SquarePenIcon />
|
|
42
42
|
</a>
|
|
43
|
-
{
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
)
|
|
54
|
-
}
|
|
43
|
+
{!config.searchPage?.hideHeaderSearchIcon && (
|
|
44
|
+
<a
|
|
45
|
+
class="flex p-3 text-gray-600 hover:text-primary"
|
|
46
|
+
aria-label={t("ln.search.title")}
|
|
47
|
+
data-astro-prefetch="viewport"
|
|
48
|
+
href={searchPagePath(currentLocale)}
|
|
49
|
+
>
|
|
50
|
+
<SearchIcon />
|
|
51
|
+
</a>
|
|
52
|
+
)}
|
|
55
53
|
|
|
56
54
|
<LanguageSelectionMenu />
|
|
57
55
|
|
|
58
|
-
{
|
|
59
|
-
|
|
60
|
-
<
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
)
|
|
75
|
-
}
|
|
56
|
+
{!!items.length && (
|
|
57
|
+
<Menu label="ln.header.open-main-menu">
|
|
58
|
+
<MenuIcon slot="icon" />
|
|
59
|
+
{items.map(({ labelText, href, isActive, isExternal }) => (
|
|
60
|
+
<MenuItem href={href} active={isActive}>
|
|
61
|
+
{labelText}
|
|
62
|
+
{isExternal && (
|
|
63
|
+
<ExternalLinkIcon
|
|
64
|
+
size="1.2rem"
|
|
65
|
+
className="shrink-0 rtl:scale-x-[-1]"
|
|
66
|
+
/>
|
|
67
|
+
)}
|
|
68
|
+
</MenuItem>
|
|
69
|
+
))}
|
|
70
|
+
</Menu>
|
|
71
|
+
)}
|
|
76
72
|
</nav>
|
|
77
73
|
<script>
|
|
78
74
|
const initAdminButton = () => {
|
|
@@ -31,23 +31,18 @@ const logoAlt = (() => {
|
|
|
31
31
|
class="flex items-center gap-3 font-bold text-gray-600 md:text-lg"
|
|
32
32
|
href={localizePath(currentLocale, "/")}
|
|
33
33
|
>
|
|
34
|
-
{
|
|
35
|
-
logo
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
loading="eager"
|
|
50
|
-
/>
|
|
51
|
-
))
|
|
52
|
-
}{!config.logo?.replacesTitle && tConfigField(config.title, config)}</a
|
|
53
|
-
>
|
|
34
|
+
{logo &&
|
|
35
|
+
(logo.format === "svg" ? (
|
|
36
|
+
<img src={logo.src} alt={logoAlt} style={`width:${getWidth(logo)}px;`} />
|
|
37
|
+
) : (
|
|
38
|
+
<Image
|
|
39
|
+
src={logo}
|
|
40
|
+
alt={logoAlt}
|
|
41
|
+
style={`width:${getWidth(logo)}px;`}
|
|
42
|
+
width={getWidth(logo)}
|
|
43
|
+
densities={[1.5, 2, 3]}
|
|
44
|
+
loading="eager"
|
|
45
|
+
/>
|
|
46
|
+
))}
|
|
47
|
+
{!config.logo?.replacesTitle && tConfigField(config.title, config)}
|
|
48
|
+
</a>
|
|
@@ -25,8 +25,6 @@ const favicons = config.favicon?.map((favicon) => {
|
|
|
25
25
|
})
|
|
26
26
|
---
|
|
27
27
|
|
|
28
|
-
{
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
))
|
|
32
|
-
}
|
|
28
|
+
{favicons?.map(({ rel, type, href, sizes }) => (
|
|
29
|
+
<link rel={rel} type={type} href={href} sizes={sizes} />
|
|
30
|
+
))}
|
package/src/pages/404Route.astro
CHANGED
|
@@ -11,7 +11,8 @@ import { localizePath } from "../utils/paths"
|
|
|
11
11
|
<a
|
|
12
12
|
href={localizePath(Astro.locals.i18n.defaultLocale, "/")}
|
|
13
13
|
class="rounded-2xl bg-gray-200 px-8 py-4 text-sm font-bold transition-colors ease-in-out hover:bg-gray-400"
|
|
14
|
-
>{Astro.locals.i18n.t("ln.404.go-to-the-home-page")}</a
|
|
15
14
|
>
|
|
15
|
+
{Astro.locals.i18n.t("ln.404.go-to-the-home-page")}
|
|
16
|
+
</a>
|
|
16
17
|
</div>
|
|
17
18
|
</Page>
|
|
@@ -41,11 +41,9 @@ if (detailsPage?.layout === "custom") {
|
|
|
41
41
|
}
|
|
42
42
|
---
|
|
43
43
|
|
|
44
|
-
{
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
)
|
|
48
|
-
}
|
|
44
|
+
{layout === "default" && (
|
|
45
|
+
<DefaultDetailsPage mediaId={mediaId} {...detailsPage} />
|
|
46
|
+
)}
|
|
49
47
|
{layout === "video" && <VideoDetailsPage mediaId={mediaId} {...detailsPage} />}
|
|
50
48
|
{layout === "audio" && <AudioDetailsPage mediaId={mediaId} {...detailsPage} />}
|
|
51
49
|
{CustomDetails && <CustomDetails mediaId={mediaId} {...detailsPage} />}
|
|
@@ -26,14 +26,12 @@ const content = item.data.content.map(({ url, label }) =>
|
|
|
26
26
|
class:list={[className]}
|
|
27
27
|
id="audio-panel"
|
|
28
28
|
>
|
|
29
|
-
{
|
|
30
|
-
|
|
31
|
-
<
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
))
|
|
36
|
-
}
|
|
29
|
+
{content.map((c) => (
|
|
30
|
+
<li>
|
|
31
|
+
{content.length > 1 && <div class="mb-3 font-bold">{c.labelText}</div>}
|
|
32
|
+
<AudioPlayer className="w-full" src={c.url} />
|
|
33
|
+
</li>
|
|
34
|
+
))}
|
|
37
35
|
</ol>
|
|
38
36
|
<script>
|
|
39
37
|
const audioPanel = document.getElementById("audio-panel")
|
|
@@ -15,38 +15,36 @@ const audioExtension = normalizedSrc.split("?")[0].split("#")[0].toLowerCase()
|
|
|
15
15
|
const isMp3 = audioExtension.endsWith(".mp3")
|
|
16
16
|
---
|
|
17
17
|
|
|
18
|
-
{
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
>
|
|
28
|
-
<
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
18
|
+
{isMp3 ? (
|
|
19
|
+
<audio class="rounded-2xl" class:list={[className]} src={src} controls />
|
|
20
|
+
) : (
|
|
21
|
+
<a
|
|
22
|
+
class="group flex w-full items-center gap-4 rounded-2xl border border-gray-200 bg-white px-4 py-4 shadow-sm transition hover:border-gray-300 hover:bg-gray-50 focus:outline-none focus-visible:ring-2 focus-visible:ring-gray-900/70"
|
|
23
|
+
class:list={[className]}
|
|
24
|
+
{...getLinkAttributes(src)}
|
|
25
|
+
aria-label={t("ln.external-link")}
|
|
26
|
+
>
|
|
27
|
+
<span class="flex h-12 w-12 items-center justify-center rounded-full border border-gray-700 text-gray-700 shadow-sm transition group-hover:scale-105">
|
|
28
|
+
<svg
|
|
29
|
+
class="h-6 w-6"
|
|
30
|
+
viewBox="0 0 24 24"
|
|
31
|
+
fill="currentColor"
|
|
32
|
+
aria-hidden="true"
|
|
33
|
+
>
|
|
34
|
+
<path d="M8 5v14l11-7z" />
|
|
35
|
+
</svg>
|
|
36
|
+
</span>
|
|
37
|
+
<div class="flex h-full grow flex-col gap-3">
|
|
38
|
+
<span class="flex items-center gap-2 font-semibold text-gray-900">
|
|
39
|
+
<ExternalLinkIcon className="shrink-0 rtl:scale-x-[-1]" />
|
|
40
|
+
{t("ln.external-link")}
|
|
37
41
|
</span>
|
|
38
|
-
<div class="
|
|
39
|
-
<
|
|
40
|
-
<ExternalLinkIcon className="shrink-0 rtl:scale-x-[-1]" />
|
|
41
|
-
{t("ln.external-link")}
|
|
42
|
-
</span>
|
|
43
|
-
<div class="h-2 w-full rounded-full bg-gray-200">
|
|
44
|
-
<div class="h-full w-2 rounded-full bg-gray-400" />
|
|
45
|
-
</div>
|
|
42
|
+
<div class="h-2 w-full rounded-full bg-gray-200">
|
|
43
|
+
<div class="h-full w-2 rounded-full bg-gray-400" />
|
|
46
44
|
</div>
|
|
47
|
-
</
|
|
48
|
-
|
|
49
|
-
}
|
|
45
|
+
</div>
|
|
46
|
+
</a>
|
|
47
|
+
)}
|
|
50
48
|
|
|
51
49
|
<style>
|
|
52
50
|
audio::-webkit-media-controls-enclosure {
|
|
@@ -51,48 +51,44 @@ const typeIcons: Record<UrlType, LucideIcon> = {
|
|
|
51
51
|
const iconDirectionClass = direction === "rtl" ? "scale-x-[-1]" : ""
|
|
52
52
|
---
|
|
53
53
|
|
|
54
|
-
<ol
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
{
|
|
58
|
-
content.map(({ extension, labelText, type, isDownload, url }, index) => {
|
|
59
|
-
const TypeIcon = typeIcons[type]
|
|
54
|
+
<ol class="mx-auto mt-16 max-w-screen-md overflow-hidden bg-gray-200 md:mt-20 md:rounded-xl">
|
|
55
|
+
{content.map(({ extension, labelText, type, isDownload, url }, index) => {
|
|
56
|
+
const TypeIcon = typeIcons[type]
|
|
60
57
|
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
58
|
+
return (
|
|
59
|
+
<li class="group -mt-px px-4 transition-colors ease-in-out hover:bg-gray-300 md:px-8">
|
|
60
|
+
<a
|
|
61
|
+
{...getLinkAttributes(url)}
|
|
62
|
+
class="flex items-center justify-between py-8"
|
|
63
|
+
>
|
|
64
|
+
<span class="flex h-10 w-10 shrink-0 items-center justify-center rounded-full bg-gray-800 text-gray-200">
|
|
65
|
+
<TypeIcon size="1.2rem" />
|
|
66
|
+
</span>
|
|
70
67
|
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
)}
|
|
90
|
-
</a>
|
|
91
|
-
{index !== content.length - 1 && (
|
|
92
|
-
<div class="h-px w-full bg-gray-300" />
|
|
68
|
+
<div class="ms-4 line-clamp-1 shrink grow overflow-hidden sm:ms-8">
|
|
69
|
+
{labelText}
|
|
70
|
+
</div>
|
|
71
|
+
<div class="me-4 ms-2 shrink-0 font-bold uppercase text-gray-600 sm:me-8">
|
|
72
|
+
{extension}
|
|
73
|
+
</div>
|
|
74
|
+
{isDownload ? (
|
|
75
|
+
<>
|
|
76
|
+
<DownloadIcon className="shrink-0 text-gray-600 group-hover:text-gray-800" />
|
|
77
|
+
<span class="sr-only">{t("ln.details.download")}</span>
|
|
78
|
+
</>
|
|
79
|
+
) : (
|
|
80
|
+
<>
|
|
81
|
+
<ChevronRightIcon
|
|
82
|
+
className={`shrink-0 text-gray-600 group-hover:text-gray-800 ${iconDirectionClass}`}
|
|
83
|
+
/>
|
|
84
|
+
<span class="sr-only">{t("ln.details.open")}</span>
|
|
85
|
+
</>
|
|
93
86
|
)}
|
|
94
|
-
</
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
87
|
+
</a>
|
|
88
|
+
{index !== content.length - 1 && (
|
|
89
|
+
<div class="h-px w-full bg-gray-300" />
|
|
90
|
+
)}
|
|
91
|
+
</li>
|
|
92
|
+
)
|
|
93
|
+
})}
|
|
98
94
|
</ol>
|