lightnet 3.10.8 → 3.12.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/__e2e__/admin.spec.ts +35 -1
- package/__e2e__/fixtures/basics/node_modules/.bin/astro +2 -2
- package/__e2e__/fixtures/basics/node_modules/.bin/tailwind +2 -2
- package/__e2e__/fixtures/basics/node_modules/.bin/tailwindcss +2 -2
- package/__e2e__/fixtures/basics/package.json +5 -5
- package/__tests__/pages/details-page/create-content-metadata.spec.ts +23 -3
- package/package.json +8 -8
- package/src/admin/components/form/DynamicArray.tsx +81 -29
- package/src/admin/components/form/Input.tsx +17 -3
- package/src/admin/components/form/LazyLoadedMarkdownEditor.tsx +12 -5
- package/src/admin/components/form/MarkdownEditor.tsx +12 -4
- package/src/admin/components/form/Select.tsx +25 -13
- package/src/admin/components/form/SubmitButton.tsx +2 -2
- package/src/admin/components/form/atoms/Button.tsx +27 -0
- package/src/admin/components/form/atoms/FileUpload.tsx +124 -49
- package/src/admin/components/form/atoms/Hint.tsx +2 -2
- package/src/admin/components/form/atoms/Label.tsx +17 -6
- package/src/admin/components/form/utils/get-border-class.ts +22 -0
- package/src/admin/i18n/translations/en.yml +19 -3
- package/src/admin/pages/AdminRoute.astro +1 -1
- package/src/admin/pages/media/EditForm.tsx +33 -15
- package/src/admin/pages/media/EditRoute.astro +2 -2
- package/src/admin/pages/media/fields/Authors.tsx +15 -5
- package/src/admin/pages/media/fields/Categories.tsx +17 -5
- package/src/admin/pages/media/fields/Collections.tsx +21 -11
- package/src/admin/pages/media/fields/Content.tsx +150 -0
- package/src/admin/pages/media/fields/Image.tsx +43 -10
- package/src/admin/pages/media/media-item-store.ts +16 -2
- package/src/admin/types/media-item.ts +9 -0
- package/src/components/SearchInput.astro +3 -3
- package/src/components/VideoPlayer.astro +74 -10
- package/src/i18n/react/prepare-i18n-config.ts +1 -1
- package/src/i18n/react/use-i18n.ts +1 -1
- package/src/i18n/translations/TRANSLATION-STATUS.md +4 -0
- package/src/i18n/translations/en.yml +3 -4
- package/src/i18n/translations/ur.yml +25 -0
- package/src/i18n/translations.ts +1 -0
- package/src/layouts/Page.astro +0 -2
- package/src/layouts/components/Menu.astro +1 -1
- package/src/pages/404Route.astro +3 -1
- package/src/pages/details-page/components/AudioPanel.astro +1 -12
- package/src/pages/details-page/components/AudioPlayer.astro +40 -8
- package/src/pages/details-page/utils/create-content-metadata.ts +2 -1
- package/src/pages/search-page/components/LoadingSkeleton.tsx +20 -13
- package/src/pages/search-page/components/SearchFilter.tsx +2 -2
- package/src/pages/search-page/components/SearchList.tsx +33 -29
- package/src/pages/search-page/components/Select.tsx +15 -13
- package/src/layouts/components/PreloadReact.tsx +0 -3
|
@@ -18,6 +18,7 @@ const KNOWN_EXTENSIONS: Record<
|
|
|
18
18
|
php: { type: "link", canBeOpened: true },
|
|
19
19
|
json: { type: "source", canBeOpened: true },
|
|
20
20
|
xml: { type: "source", canBeOpened: true },
|
|
21
|
+
md: { type: "source", canBeOpened: true },
|
|
21
22
|
svg: { type: "image", canBeOpened: true },
|
|
22
23
|
jpg: { type: "image", canBeOpened: true },
|
|
23
24
|
jpeg: { type: "image", canBeOpened: true },
|
|
@@ -62,7 +63,7 @@ export function createContentMetadata({
|
|
|
62
63
|
const fileName = hasExtension
|
|
63
64
|
? lastPathSegment.slice(0, -(extension.length + 1))
|
|
64
65
|
: undefined
|
|
65
|
-
const label = customLabel
|
|
66
|
+
const label = customLabel || fileName || linkName
|
|
66
67
|
const type = KNOWN_EXTENSIONS[extension]?.type ?? "link"
|
|
67
68
|
const canBeOpened =
|
|
68
69
|
!hasExtension || !!KNOWN_EXTENSIONS[extension]?.canBeOpened
|
|
@@ -4,18 +4,25 @@ import { useI18n } from "../../../i18n/react/use-i18n"
|
|
|
4
4
|
export default function LoadingSkeleton() {
|
|
5
5
|
const { direction } = useI18n()
|
|
6
6
|
return (
|
|
7
|
-
<
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
7
|
+
<ul>
|
|
8
|
+
{Array.from({ length: 8 }, (_, index) => (
|
|
9
|
+
<li
|
|
10
|
+
key={index}
|
|
11
|
+
className="flex h-52 animate-pulse items-center overflow-hidden py-2 sm:h-64"
|
|
12
|
+
>
|
|
13
|
+
<div className="h-36 w-36 shrink-0 rounded-md bg-gray-200"></div>
|
|
14
|
+
<div className="ms-5 flex grow flex-col gap-3">
|
|
15
|
+
<div className="h-4 w-1/2 rounded-md bg-gray-200 md:h-6"></div>
|
|
16
|
+
<div className="h-4 w-3/4 rounded-md bg-gray-200 md:h-6"></div>
|
|
17
|
+
<div className="h-4 w-5/6 rounded-md bg-gray-200 md:h-6"></div>
|
|
18
|
+
</div>
|
|
19
|
+
<Icon
|
|
20
|
+
className="my-auto me-4 ms-2 hidden shrink-0 text-2xl text-gray-300 mdi--chevron-right sm:block"
|
|
21
|
+
flipIcon={direction === "rtl"}
|
|
22
|
+
ariaLabel=""
|
|
23
|
+
/>
|
|
24
|
+
</li>
|
|
25
|
+
))}
|
|
26
|
+
</ul>
|
|
20
27
|
)
|
|
21
28
|
}
|
|
@@ -45,10 +45,10 @@ export default function SearchFilter({
|
|
|
45
45
|
|
|
46
46
|
return (
|
|
47
47
|
<>
|
|
48
|
-
<label className="
|
|
48
|
+
<label className="mb-2 flex items-center gap-2 rounded-2xl border border-gray-300 bg-white px-4 py-3 shadow-inner outline outline-2 outline-offset-2 outline-transparent transition-all ease-in-out focus-within:outline-gray-300">
|
|
49
49
|
<input
|
|
50
50
|
type="search"
|
|
51
|
-
className="grow placeholder-gray-500"
|
|
51
|
+
className="grow placeholder-gray-500 focus:outline-none"
|
|
52
52
|
name="search"
|
|
53
53
|
ref={searchInput}
|
|
54
54
|
placeholder={t("ln.search.placeholder")}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { useWindowVirtualizer } from "@tanstack/react-virtual"
|
|
2
|
-
import { useEffect, useRef, useState } from "react"
|
|
2
|
+
import { useCallback, useEffect, useRef, useState } from "react"
|
|
3
3
|
|
|
4
4
|
import {
|
|
5
5
|
createI18n,
|
|
@@ -38,11 +38,15 @@ export default function SearchList({
|
|
|
38
38
|
mediaTypes,
|
|
39
39
|
})
|
|
40
40
|
const count = isLoading ? mediaItemsTotal : results.length
|
|
41
|
+
const getItemKey = useCallback(
|
|
42
|
+
(index: number) => (isLoading ? index : results[index].id),
|
|
43
|
+
[isLoading, results],
|
|
44
|
+
)
|
|
41
45
|
|
|
42
46
|
const virtualizer = useWindowVirtualizer({
|
|
43
47
|
count,
|
|
44
48
|
estimateSize: () => rowHeight,
|
|
45
|
-
getItemKey
|
|
49
|
+
getItemKey,
|
|
46
50
|
overscan: 2,
|
|
47
51
|
scrollMargin: listRef.current?.offsetTop ?? 0,
|
|
48
52
|
})
|
|
@@ -68,28 +72,28 @@ export default function SearchList({
|
|
|
68
72
|
return (
|
|
69
73
|
<I18nContext.Provider value={i18n}>
|
|
70
74
|
<div ref={listRef} className="px-4 md:px-8">
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
75
|
+
{isLoading ? (
|
|
76
|
+
<LoadingSkeleton />
|
|
77
|
+
) : (
|
|
78
|
+
<ol
|
|
79
|
+
className="relative w-full divide-y divide-gray-200"
|
|
80
|
+
style={{
|
|
81
|
+
height: `${virtualizer.getTotalSize()}px`,
|
|
82
|
+
}}
|
|
83
|
+
>
|
|
84
|
+
{virtualizer.getVirtualItems().map((virtualRow) => {
|
|
85
|
+
const item = results[virtualRow.index]
|
|
86
|
+
return (
|
|
87
|
+
<li
|
|
88
|
+
key={virtualRow.key}
|
|
89
|
+
className="absolute left-0 top-0 block w-full"
|
|
90
|
+
style={{
|
|
91
|
+
height: `${virtualRow.size}px`,
|
|
92
|
+
transform: `translateY(${
|
|
93
|
+
virtualRow.start - virtualizer.options.scrollMargin
|
|
94
|
+
}px)`,
|
|
95
|
+
}}
|
|
96
|
+
>
|
|
93
97
|
<SearchListItem
|
|
94
98
|
item={item}
|
|
95
99
|
showLanguage={showLanguage}
|
|
@@ -97,11 +101,11 @@ export default function SearchList({
|
|
|
97
101
|
languages={languages}
|
|
98
102
|
mediaTypes={mediaTypes}
|
|
99
103
|
/>
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
)
|
|
103
|
-
|
|
104
|
-
|
|
104
|
+
</li>
|
|
105
|
+
)
|
|
106
|
+
})}
|
|
107
|
+
</ol>
|
|
108
|
+
)}
|
|
105
109
|
</div>
|
|
106
110
|
{!results.length && !isLoading && (
|
|
107
111
|
<div className="mt-24 text-center font-bold text-gray-500">
|
|
@@ -12,21 +12,23 @@ export default function Select({
|
|
|
12
12
|
options,
|
|
13
13
|
}: Props) {
|
|
14
14
|
return (
|
|
15
|
-
<label
|
|
16
|
-
<span className="
|
|
15
|
+
<label>
|
|
16
|
+
<span className="mb-1 mt-2 block text-xs font-bold uppercase text-gray-600">
|
|
17
17
|
{label}
|
|
18
18
|
</span>
|
|
19
|
-
<
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
{
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
19
|
+
<div className="rounded-2xl border border-gray-300 bg-white px-4 py-3 shadow-sm outline outline-2 outline-offset-2 outline-transparent transition-all ease-in-out focus-within:outline-gray-300 sm:p-2">
|
|
20
|
+
<select
|
|
21
|
+
className="w-full bg-white focus:outline-none sm:text-sm"
|
|
22
|
+
value={initialValue}
|
|
23
|
+
onChange={(e) => valueChange(e.currentTarget.value)}
|
|
24
|
+
>
|
|
25
|
+
{options.map(({ id, labelText }) => (
|
|
26
|
+
<option key={id} value={id}>
|
|
27
|
+
{labelText}
|
|
28
|
+
</option>
|
|
29
|
+
))}
|
|
30
|
+
</select>
|
|
31
|
+
</div>
|
|
30
32
|
</label>
|
|
31
33
|
)
|
|
32
34
|
}
|