lightnet 3.6.1 → 3.8.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 +59 -0
- package/README.md +23 -11
- package/__e2e__/fixtures/basics/node_modules/.bin/astro +7 -3
- package/__e2e__/fixtures/basics/node_modules/.bin/tailwind +5 -1
- package/__e2e__/fixtures/basics/node_modules/.bin/tailwindcss +5 -1
- package/__e2e__/fixtures/basics/node_modules/.bin/tsc +7 -3
- package/__e2e__/fixtures/basics/node_modules/.bin/tsserver +7 -3
- package/__e2e__/fixtures/basics/package.json +10 -7
- package/__tests__/utils/markdown.spec.ts +4 -0
- package/__tests__/utils/urls.spec.ts +27 -0
- package/exports/experimental-components.ts +1 -0
- package/package.json +19 -12
- package/src/astro-integration/integration.ts +6 -0
- package/src/components/CarouselSection.astro +182 -0
- package/src/components/CategoriesSection.astro +96 -47
- package/src/components/MediaGallery.astro +1 -1
- package/src/components/SearchInput.astro +1 -0
- package/src/components/SearchSection.astro +9 -4
- package/src/components/Section.astro +31 -17
- package/src/content/get-categories.ts +1 -1
- package/src/i18n/translations/README.md +1 -1
- package/src/i18n/translations/ar.yml +2 -0
- package/src/i18n/translations/bn.yml +2 -0
- package/src/i18n/translations/de.yml +2 -0
- package/src/i18n/translations/en.yml +12 -0
- package/src/i18n/translations/es.yml +2 -0
- package/src/i18n/translations/fi.yml +2 -0
- package/src/i18n/translations/fr.yml +2 -0
- package/src/i18n/translations/hi.yml +2 -0
- package/src/i18n/translations/pt.yml +2 -0
- package/src/i18n/translations/ru.yml +2 -0
- package/src/i18n/translations/uk.yml +2 -0
- package/src/i18n/translations/zh.yml +2 -0
- package/src/i18n/translations.ts +2 -0
- package/src/layouts/Page.astro +2 -3
- package/src/layouts/components/Header.astro +1 -4
- package/src/layouts/components/ViewTransition.astro +9 -0
- package/src/pages/api/versions.ts +7 -0
- package/src/pages/details-page/AudioDetailsPage.astro +4 -9
- package/src/pages/details-page/DefaultDetailsPage.astro +6 -6
- package/src/pages/details-page/components/AudioPanel.astro +64 -0
- package/src/pages/details-page/components/{main-details/AudioPlayer.astro → AudioPlayer.astro} +1 -1
- package/src/pages/details-page/components/ContentSection.astro +5 -2
- package/src/pages/details-page/components/DescriptionSection.astro +1 -1
- package/src/pages/details-page/components/MainDetailsSection.astro +8 -5
- package/src/pages/details-page/components/VideoDetailsSection.astro +1 -1
- package/src/pages/details-page/components/main-details/Authors.astro +2 -2
- package/src/pages/details-page/components/main-details/OpenButton.astro +3 -1
- package/src/pages/details-page/components/main-details/ShareButton.astro +21 -33
- package/src/pages/details-page/components/main-details/{Cover.astro → Thumbnail.astro} +14 -3
- package/src/pages/search-page/components/SearchList.tsx +0 -1
- package/src/pages/search-page/hooks/use-search.ts +2 -33
- package/src/utils/paths.ts +15 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,64 @@
|
|
|
1
1
|
# lightnet
|
|
2
2
|
|
|
3
|
+
## 3.8.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- [#299](https://github.com/LightNetDev/LightNet/pull/299) [`ecaf1f6`](https://github.com/LightNetDev/LightNet/commit/ecaf1f698231c3e4eec700ca07cb78d1dbf4378c) Thanks [@smn-cds](https://github.com/smn-cds)! - Added a new `titleHref` prop to the `Section` component.
|
|
8
|
+
|
|
9
|
+
This enables section titles to act as anchors, allowing navigation to dedicated pages for expanded content. Useful for situations where content previews need to link to full listings.
|
|
10
|
+
|
|
11
|
+
- [#297](https://github.com/LightNetDev/LightNet/pull/297) [`537f6e5`](https://github.com/LightNetDev/LightNet/commit/537f6e50c8bbf7d9a22a17773acddf79fbd11c21) Thanks [@smn-cds](https://github.com/smn-cds)! - Add /api/versions.json endpoint to return the LightNet version.
|
|
12
|
+
|
|
13
|
+
- [#299](https://github.com/LightNetDev/LightNet/pull/299) [`ecaf1f6`](https://github.com/LightNetDev/LightNet/commit/ecaf1f698231c3e4eec700ca07cb78d1dbf4378c) Thanks [@smn-cds](https://github.com/smn-cds)! - Added filter parameters (`type`, `language`, `search`) to `searchPagePath` function.
|
|
14
|
+
|
|
15
|
+
- [#298](https://github.com/LightNetDev/LightNet/pull/298) [`b5c3c7a`](https://github.com/LightNetDev/LightNet/commit/b5c3c7a6637b9973acdbd34af3db1de5ed01c9f5) Thanks [@smn-cds](https://github.com/smn-cds)! - Remove client router
|
|
16
|
+
|
|
17
|
+
We have been relying on [Astro's ClientRouter](https://docs.astro.build/en/reference/modules/astro-transitions/#clientrouter-) for
|
|
18
|
+
view transitions between different pages.
|
|
19
|
+
With this release we remove the use of ClientRouter and switch to the browser built-in [ViewTransitions API](https://developer.mozilla.org/en-US/docs/Web/API/View_Transition_API).
|
|
20
|
+
|
|
21
|
+
- [#299](https://github.com/LightNetDev/LightNet/pull/299) [`ecaf1f6`](https://github.com/LightNetDev/LightNet/commit/ecaf1f698231c3e4eec700ca07cb78d1dbf4378c) Thanks [@smn-cds](https://github.com/smn-cds)! - ⚠️ Added new translations
|
|
22
|
+
- ln.previous: "Previous"
|
|
23
|
+
- ln.next: "Next"
|
|
24
|
+
|
|
25
|
+
- [#299](https://github.com/LightNetDev/LightNet/pull/299) [`ecaf1f6`](https://github.com/LightNetDev/LightNet/commit/ecaf1f698231c3e4eec700ca07cb78d1dbf4378c) Thanks [@smn-cds](https://github.com/smn-cds)! - Improved CategorySection
|
|
26
|
+
- added `carousel` layout
|
|
27
|
+
- replaced `image-grid` layout with `grid`
|
|
28
|
+
- ⚠️ removed `button-grid`
|
|
29
|
+
- ⚠️ changed the default layout from `button-grid` to `carousel`
|
|
30
|
+
|
|
31
|
+
### Patch Changes
|
|
32
|
+
|
|
33
|
+
- [#299](https://github.com/LightNetDev/LightNet/pull/299) [`ecaf1f6`](https://github.com/LightNetDev/LightNet/commit/ecaf1f698231c3e4eec700ca07cb78d1dbf4378c) Thanks [@smn-cds](https://github.com/smn-cds)! - ⚠️ Removed `disableHorizontalPadding` property from Section component.
|
|
34
|
+
|
|
35
|
+
- [#299](https://github.com/LightNetDev/LightNet/pull/299) [`ecaf1f6`](https://github.com/LightNetDev/LightNet/commit/ecaf1f698231c3e4eec700ca07cb78d1dbf4378c) Thanks [@smn-cds](https://github.com/smn-cds)! - Accessibility improvements
|
|
36
|
+
- set `role=search` for SearchInput component
|
|
37
|
+
- set aria-label for Section component
|
|
38
|
+
|
|
39
|
+
## 3.7.0
|
|
40
|
+
|
|
41
|
+
### Minor Changes
|
|
42
|
+
|
|
43
|
+
- [#288](https://github.com/LightNetDev/LightNet/pull/288) [`008553f`](https://github.com/LightNetDev/LightNet/commit/008553f7c016931b617ba2c632e0b473e32bad8d) Thanks [@smn-cds](https://github.com/smn-cds)! - Improves support for media items with more than one audio file
|
|
44
|
+
- Audio details page shows embedded player for each mp3 inside the media item's content array
|
|
45
|
+
- Audio player stops playing a mp3 when the next is started
|
|
46
|
+
- Audio player resumes with next mp3 when one mp3 ends
|
|
47
|
+
|
|
48
|
+
### Patch Changes
|
|
49
|
+
|
|
50
|
+
- [#288](https://github.com/LightNetDev/LightNet/pull/288) [`008553f`](https://github.com/LightNetDev/LightNet/commit/008553f7c016931b617ba2c632e0b473e32bad8d) Thanks [@smn-cds](https://github.com/smn-cds)! - Reorganized dependencies
|
|
51
|
+
|
|
52
|
+
If you are using npm as the package manager, you can remove these
|
|
53
|
+
dependencies from your `package.json`.
|
|
54
|
+
- sharp
|
|
55
|
+
- @astrojs/react
|
|
56
|
+
- @astrojs/tailwind
|
|
57
|
+
|
|
58
|
+
- [#288](https://github.com/LightNetDev/LightNet/pull/288) [`008553f`](https://github.com/LightNetDev/LightNet/commit/008553f7c016931b617ba2c632e0b473e32bad8d) Thanks [@smn-cds](https://github.com/smn-cds)! - ‼️ Breaking changes on experimental custom details page components
|
|
59
|
+
- Design of `ShareButton` has changed from a gray button to a underlined text
|
|
60
|
+
- `MainDetailsSection` now already contains the `ShareButton`
|
|
61
|
+
|
|
3
62
|
## 3.6.1
|
|
4
63
|
|
|
5
64
|
### Patch Changes
|
package/README.md
CHANGED
|
@@ -1,25 +1,37 @@
|
|
|
1
|
-
|
|
1
|
+

|
|
2
2
|
|
|
3
|
-
Share the
|
|
3
|
+
Share the gospel and strengthen believers in your community.
|
|
4
4
|
|
|
5
|
-
LightNet
|
|
5
|
+
LightNet makes it easy to **run your own digital media library**, so more people can find what they need and grow in faith.
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
Built as an integration for the [Astro framework](https://astro.build), LightNet enables the creation of fast, statically generated websites that can be easily hosted on any file server.
|
|
8
|
+
|
|
9
|
+
Learn more on the [LightNet homepage](https://lightnet.community).
|
|
10
|
+
|
|
11
|
+
## Start Your Own Library
|
|
12
|
+
|
|
13
|
+
Get up and running quickly with LightNet by exploring its features and best practices. You can build your own media library by starting with the [LightNet example template](https://github.com/LightNetDev/example-template), which creates a local copy of a demo site for a fictional skateboard ministry. This beginner-friendly template serves as a great starting point for developers.
|
|
14
|
+
|
|
15
|
+
To get started, simply run the following command in your terminal:
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
npm create astro@latest -- --template LightNetDev/example-template
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
This will set up the demo site that you can customize and expand to meet your community’s needs.
|
|
8
22
|
|
|
9
23
|
## Documentation
|
|
10
24
|
|
|
11
|
-
[
|
|
25
|
+
Need help? [Explore the LightNet developer docs](https://docs.lightnet.community) for everything you need to get started and make the most of LightNet.
|
|
12
26
|
|
|
13
|
-
##
|
|
27
|
+
## Showcase
|
|
14
28
|
|
|
15
|
-
[
|
|
29
|
+
Want to see LightNet in action? [Visit the MediaWorks digital library](https://library.mediaworks.global) and see how it powers a real-world digital library.
|
|
16
30
|
|
|
17
31
|
## Contributing
|
|
18
32
|
|
|
19
|
-
|
|
33
|
+
Want to help improve LightNet? [Check out the contribution guide](https://github.com/LightNetDev/lightnet/blob/main/CONTRIBUTING.md) to learn how you can get involved and make a difference!
|
|
20
34
|
|
|
21
35
|
## License
|
|
22
36
|
|
|
23
|
-
MIT
|
|
24
|
-
|
|
25
|
-
Copyright (c) 2024–present [LightNet contributors](https://github.com/LightNetDev/LightNet/graphs/contributors)
|
|
37
|
+
LightNet is licensed under the MIT License. See the full details in the [LICENSE](https://github.com/LightNetDev/lightnet/blob/main/LICENSE) file.
|
|
@@ -2,13 +2,17 @@
|
|
|
2
2
|
basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')")
|
|
3
3
|
|
|
4
4
|
case `uname` in
|
|
5
|
-
*CYGWIN*)
|
|
5
|
+
*CYGWIN*|*MINGW*|*MSYS*)
|
|
6
|
+
if command -v cygpath > /dev/null 2>&1; then
|
|
7
|
+
basedir=`cygpath -w "$basedir"`
|
|
8
|
+
fi
|
|
9
|
+
;;
|
|
6
10
|
esac
|
|
7
11
|
|
|
8
12
|
if [ -z "$NODE_PATH" ]; then
|
|
9
|
-
export NODE_PATH="/home/runner/work/LightNet/LightNet/node_modules/.pnpm/astro@5.
|
|
13
|
+
export NODE_PATH="/home/runner/work/LightNet/LightNet/node_modules/.pnpm/astro@5.12.8_@types+node@24.2.0_jiti@2.4.2_lightningcss@1.29.1_rollup@4.46.2_terser@5.39.0_typescript@5.9.2_yaml@2.8.1/node_modules/astro/node_modules:/home/runner/work/LightNet/LightNet/node_modules/.pnpm/astro@5.12.8_@types+node@24.2.0_jiti@2.4.2_lightningcss@1.29.1_rollup@4.46.2_terser@5.39.0_typescript@5.9.2_yaml@2.8.1/node_modules:/home/runner/work/LightNet/LightNet/node_modules/.pnpm/node_modules"
|
|
10
14
|
else
|
|
11
|
-
export NODE_PATH="/home/runner/work/LightNet/LightNet/node_modules/.pnpm/astro@5.
|
|
15
|
+
export NODE_PATH="/home/runner/work/LightNet/LightNet/node_modules/.pnpm/astro@5.12.8_@types+node@24.2.0_jiti@2.4.2_lightningcss@1.29.1_rollup@4.46.2_terser@5.39.0_typescript@5.9.2_yaml@2.8.1/node_modules/astro/node_modules:/home/runner/work/LightNet/LightNet/node_modules/.pnpm/astro@5.12.8_@types+node@24.2.0_jiti@2.4.2_lightningcss@1.29.1_rollup@4.46.2_terser@5.39.0_typescript@5.9.2_yaml@2.8.1/node_modules:/home/runner/work/LightNet/LightNet/node_modules/.pnpm/node_modules:$NODE_PATH"
|
|
12
16
|
fi
|
|
13
17
|
if [ -x "$basedir/node" ]; then
|
|
14
18
|
exec "$basedir/node" "$basedir/../astro/astro.js" "$@"
|
|
@@ -2,7 +2,11 @@
|
|
|
2
2
|
basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')")
|
|
3
3
|
|
|
4
4
|
case `uname` in
|
|
5
|
-
*CYGWIN*)
|
|
5
|
+
*CYGWIN*|*MINGW*|*MSYS*)
|
|
6
|
+
if command -v cygpath > /dev/null 2>&1; then
|
|
7
|
+
basedir=`cygpath -w "$basedir"`
|
|
8
|
+
fi
|
|
9
|
+
;;
|
|
6
10
|
esac
|
|
7
11
|
|
|
8
12
|
if [ -z "$NODE_PATH" ]; then
|
|
@@ -2,7 +2,11 @@
|
|
|
2
2
|
basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')")
|
|
3
3
|
|
|
4
4
|
case `uname` in
|
|
5
|
-
*CYGWIN*)
|
|
5
|
+
*CYGWIN*|*MINGW*|*MSYS*)
|
|
6
|
+
if command -v cygpath > /dev/null 2>&1; then
|
|
7
|
+
basedir=`cygpath -w "$basedir"`
|
|
8
|
+
fi
|
|
9
|
+
;;
|
|
6
10
|
esac
|
|
7
11
|
|
|
8
12
|
if [ -z "$NODE_PATH" ]; then
|
|
@@ -2,13 +2,17 @@
|
|
|
2
2
|
basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')")
|
|
3
3
|
|
|
4
4
|
case `uname` in
|
|
5
|
-
*CYGWIN*)
|
|
5
|
+
*CYGWIN*|*MINGW*|*MSYS*)
|
|
6
|
+
if command -v cygpath > /dev/null 2>&1; then
|
|
7
|
+
basedir=`cygpath -w "$basedir"`
|
|
8
|
+
fi
|
|
9
|
+
;;
|
|
6
10
|
esac
|
|
7
11
|
|
|
8
12
|
if [ -z "$NODE_PATH" ]; then
|
|
9
|
-
export NODE_PATH="/home/runner/work/LightNet/LightNet/node_modules/.pnpm/typescript@5.
|
|
13
|
+
export NODE_PATH="/home/runner/work/LightNet/LightNet/node_modules/.pnpm/typescript@5.9.2/node_modules/typescript/bin/node_modules:/home/runner/work/LightNet/LightNet/node_modules/.pnpm/typescript@5.9.2/node_modules/typescript/node_modules:/home/runner/work/LightNet/LightNet/node_modules/.pnpm/typescript@5.9.2/node_modules:/home/runner/work/LightNet/LightNet/node_modules/.pnpm/node_modules"
|
|
10
14
|
else
|
|
11
|
-
export NODE_PATH="/home/runner/work/LightNet/LightNet/node_modules/.pnpm/typescript@5.
|
|
15
|
+
export NODE_PATH="/home/runner/work/LightNet/LightNet/node_modules/.pnpm/typescript@5.9.2/node_modules/typescript/bin/node_modules:/home/runner/work/LightNet/LightNet/node_modules/.pnpm/typescript@5.9.2/node_modules/typescript/node_modules:/home/runner/work/LightNet/LightNet/node_modules/.pnpm/typescript@5.9.2/node_modules:/home/runner/work/LightNet/LightNet/node_modules/.pnpm/node_modules:$NODE_PATH"
|
|
12
16
|
fi
|
|
13
17
|
if [ -x "$basedir/node" ]; then
|
|
14
18
|
exec "$basedir/node" "$basedir/../typescript/bin/tsc" "$@"
|
|
@@ -2,13 +2,17 @@
|
|
|
2
2
|
basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')")
|
|
3
3
|
|
|
4
4
|
case `uname` in
|
|
5
|
-
*CYGWIN*)
|
|
5
|
+
*CYGWIN*|*MINGW*|*MSYS*)
|
|
6
|
+
if command -v cygpath > /dev/null 2>&1; then
|
|
7
|
+
basedir=`cygpath -w "$basedir"`
|
|
8
|
+
fi
|
|
9
|
+
;;
|
|
6
10
|
esac
|
|
7
11
|
|
|
8
12
|
if [ -z "$NODE_PATH" ]; then
|
|
9
|
-
export NODE_PATH="/home/runner/work/LightNet/LightNet/node_modules/.pnpm/typescript@5.
|
|
13
|
+
export NODE_PATH="/home/runner/work/LightNet/LightNet/node_modules/.pnpm/typescript@5.9.2/node_modules/typescript/bin/node_modules:/home/runner/work/LightNet/LightNet/node_modules/.pnpm/typescript@5.9.2/node_modules/typescript/node_modules:/home/runner/work/LightNet/LightNet/node_modules/.pnpm/typescript@5.9.2/node_modules:/home/runner/work/LightNet/LightNet/node_modules/.pnpm/node_modules"
|
|
10
14
|
else
|
|
11
|
-
export NODE_PATH="/home/runner/work/LightNet/LightNet/node_modules/.pnpm/typescript@5.
|
|
15
|
+
export NODE_PATH="/home/runner/work/LightNet/LightNet/node_modules/.pnpm/typescript@5.9.2/node_modules/typescript/bin/node_modules:/home/runner/work/LightNet/LightNet/node_modules/.pnpm/typescript@5.9.2/node_modules/typescript/node_modules:/home/runner/work/LightNet/LightNet/node_modules/.pnpm/typescript@5.9.2/node_modules:/home/runner/work/LightNet/LightNet/node_modules/.pnpm/node_modules:$NODE_PATH"
|
|
12
16
|
fi
|
|
13
17
|
if [ -x "$basedir/node" ]; then
|
|
14
18
|
exec "$basedir/node" "$basedir/../typescript/bin/tsserver" "$@"
|
|
@@ -6,13 +6,16 @@
|
|
|
6
6
|
"dependencies": {
|
|
7
7
|
"@astrojs/react": "^4.3.0",
|
|
8
8
|
"@astrojs/tailwind": "^6.0.2",
|
|
9
|
-
"@lightnet/decap-admin": "^3.1.
|
|
10
|
-
"astro": "^5.
|
|
11
|
-
"lightnet": "^3.
|
|
12
|
-
"react": "^19.1.
|
|
13
|
-
"react-dom": "^19.1.
|
|
14
|
-
"sharp": "^0.
|
|
9
|
+
"@lightnet/decap-admin": "^3.1.2",
|
|
10
|
+
"astro": "^5.12.8",
|
|
11
|
+
"lightnet": "^3.8.0",
|
|
12
|
+
"react": "^19.1.1",
|
|
13
|
+
"react-dom": "^19.1.1",
|
|
14
|
+
"sharp": "^0.34.3",
|
|
15
15
|
"tailwindcss": "^3.4.17",
|
|
16
|
-
"typescript": "^5.
|
|
16
|
+
"typescript": "^5.9.2"
|
|
17
|
+
},
|
|
18
|
+
"engines": {
|
|
19
|
+
"node": ">=22"
|
|
17
20
|
}
|
|
18
21
|
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import config from "virtual:lightnet/config"
|
|
2
|
+
import projectContext from "virtual:lightnet/project-context"
|
|
3
|
+
import { expect, test } from "vitest"
|
|
4
|
+
|
|
5
|
+
import { isExternalUrl } from "../../src/utils/urls"
|
|
6
|
+
|
|
7
|
+
// relative path should be treated as internal
|
|
8
|
+
test("Should treat relative paths as internal", () => {
|
|
9
|
+
expect(isExternalUrl("/page")).toBe(false)
|
|
10
|
+
})
|
|
11
|
+
|
|
12
|
+
// absolute url that matches the configured site should be internal
|
|
13
|
+
test("Should treat URLs matching projectContext.site as internal", () => {
|
|
14
|
+
expect(isExternalUrl(`${projectContext.site}/page`)).toBe(false)
|
|
15
|
+
})
|
|
16
|
+
|
|
17
|
+
// domains listed in internalDomains should be treated as internal
|
|
18
|
+
test("Should treat configured internalDomains as internal", () => {
|
|
19
|
+
config.internalDomains.push("internal.test")
|
|
20
|
+
expect(isExternalUrl("https://internal.test/foo")).toBe(false)
|
|
21
|
+
config.internalDomains.pop()
|
|
22
|
+
})
|
|
23
|
+
|
|
24
|
+
// any other absolute url should be external
|
|
25
|
+
test("Should treat other absolute URLs as external", () => {
|
|
26
|
+
expect(isExternalUrl("https://example.com")).toBe(true)
|
|
27
|
+
})
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default as CarouselSection } from "../src/components/CarouselSection.astro"
|
package/package.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"name": "lightnet",
|
|
3
3
|
"type": "module",
|
|
4
4
|
"license": "MIT",
|
|
5
|
-
"version": "3.
|
|
5
|
+
"version": "3.8.0",
|
|
6
6
|
"repository": {
|
|
7
7
|
"type": "git",
|
|
8
8
|
"url": "https://github.com/LightNetDev/lightnet",
|
|
@@ -20,6 +20,7 @@
|
|
|
20
20
|
"./content": "./exports/content.ts",
|
|
21
21
|
"./utils": "./exports/utils.ts",
|
|
22
22
|
"./components": "./exports/components.ts",
|
|
23
|
+
"./experimental-components": "./exports/experimental-components.ts",
|
|
23
24
|
"./experimental-details-page": "./exports/details-page.ts",
|
|
24
25
|
"./i18n": "./exports/i18n.ts",
|
|
25
26
|
"./locals": "./src/i18n/locals.ts",
|
|
@@ -29,35 +30,41 @@
|
|
|
29
30
|
"./pages/RootRoute.astro": "./src/pages/RootRoute.astro",
|
|
30
31
|
"./pages/SearchPageRoute.astro": "./src/pages/search-page/SearchPageRoute.astro",
|
|
31
32
|
"./pages/DetailsPageRoute.astro": "./src/pages/details-page/DetailsPageRoute.astro",
|
|
32
|
-
"./pages/api/search.ts": "./src/pages/api/search.ts"
|
|
33
|
+
"./pages/api/search.ts": "./src/pages/api/search.ts",
|
|
34
|
+
"./pages/api/versions.ts": "./src/pages/api/versions.ts"
|
|
33
35
|
},
|
|
34
36
|
"peerDependencies": {
|
|
35
|
-
"@astrojs/react": "^4.1.0",
|
|
36
|
-
"@astrojs/tailwind": "^6.0.0",
|
|
37
37
|
"astro": "^5.1.0",
|
|
38
38
|
"react": "^19.0.0",
|
|
39
39
|
"react-dom": "^19.0.0",
|
|
40
|
-
"
|
|
41
|
-
"tailwindcss": "^3.4.17",
|
|
42
|
-
"typescript": "^5.5.3"
|
|
40
|
+
"tailwindcss": ">=3.4.0 <4.0.0"
|
|
43
41
|
},
|
|
44
42
|
"dependencies": {
|
|
43
|
+
"@astrojs/react": "^4.3.0",
|
|
44
|
+
"@astrojs/tailwind": "^6.0.2",
|
|
45
45
|
"@iconify-json/mdi": "^1.2.3",
|
|
46
46
|
"@iconify/tailwind": "^1.2.0",
|
|
47
47
|
"@tailwindcss/typography": "^0.5.16",
|
|
48
48
|
"@tanstack/react-virtual": "^3.13.12",
|
|
49
|
-
"@types/react": "^19.1.8",
|
|
50
49
|
"daisyui": "^4.12.24",
|
|
50
|
+
"embla-carousel": "^8.6.0",
|
|
51
|
+
"embla-carousel-auto-height": "^8.6.0",
|
|
52
|
+
"embla-carousel-wheel-gestures": "^8.0.2",
|
|
51
53
|
"fuse.js": "^7.1.0",
|
|
52
54
|
"i18next": "^25.3.2",
|
|
53
|
-
"marked": "^16.
|
|
54
|
-
"yaml": "^2.8.
|
|
55
|
+
"marked": "^16.1.2",
|
|
56
|
+
"yaml": "^2.8.1"
|
|
55
57
|
},
|
|
56
58
|
"devDependencies": {
|
|
57
|
-
"@playwright/test": "^1.
|
|
58
|
-
"@types/node": "^22.
|
|
59
|
+
"@playwright/test": "^1.54.2",
|
|
60
|
+
"@types/node": "^22.17.0",
|
|
61
|
+
"@types/react": "^19.1.9",
|
|
62
|
+
"typescript": "^5.9.2",
|
|
59
63
|
"vitest": "^3.2.4"
|
|
60
64
|
},
|
|
65
|
+
"engines": {
|
|
66
|
+
"node": ">=22"
|
|
67
|
+
},
|
|
61
68
|
"scripts": {
|
|
62
69
|
"test": "vitest",
|
|
63
70
|
"e2e": "playwright install --with-deps chromium && playwright test"
|
|
@@ -51,6 +51,12 @@ export function lightnet(lightnetConfig: LightnetConfig): AstroIntegration {
|
|
|
51
51
|
prerender: true,
|
|
52
52
|
})
|
|
53
53
|
|
|
54
|
+
injectRoute({
|
|
55
|
+
pattern: "/api/versions.json",
|
|
56
|
+
entrypoint: "lightnet/pages/api/versions.ts",
|
|
57
|
+
prerender: true,
|
|
58
|
+
})
|
|
59
|
+
|
|
54
60
|
injectRoute({
|
|
55
61
|
pattern: "/[locale]/media/[mediaId]",
|
|
56
62
|
entrypoint: "lightnet/pages/DetailsPageRoute.astro",
|
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
---
|
|
2
|
+
import Icon from "./Icon"
|
|
3
|
+
import Section, { type Props as SectionProps } from "./Section.astro"
|
|
4
|
+
|
|
5
|
+
type Props = SectionProps
|
|
6
|
+
|
|
7
|
+
const { titleClass = "", ...props } = Astro.props
|
|
8
|
+
const { t, direction } = Astro.locals.i18n
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
<Section {...props} titleClass={"!mb-8 sm:!-mb-1 " + titleClass}>
|
|
12
|
+
<ln-carousel data-direction={direction} aria-roledescription="carousel">
|
|
13
|
+
<div class="mb-2 hidden justify-end gap-1 sm:flex">
|
|
14
|
+
<button
|
|
15
|
+
data-button-prev
|
|
16
|
+
aria-label={t("ln.previous")}
|
|
17
|
+
class="flex h-9 w-9 items-center justify-center rounded-full border-2 border-gray-200 bg-gray-200 text-gray-600 transition-colors ease-in-out hover:border-gray-400 disabled:bg-transparent disabled:text-gray-300 disabled:hover:border-gray-200"
|
|
18
|
+
><Icon
|
|
19
|
+
className="mdi--chevron-left"
|
|
20
|
+
ariaLabel=""
|
|
21
|
+
flipIcon={direction === "rtl"}
|
|
22
|
+
/></button
|
|
23
|
+
>
|
|
24
|
+
<button
|
|
25
|
+
data-button-next
|
|
26
|
+
aria-label={t("ln.next")}
|
|
27
|
+
class="flex h-9 w-9 items-center justify-center rounded-full border-2 border-gray-200 bg-gray-200 text-gray-600 transition-colors ease-in-out hover:border-gray-400 disabled:bg-transparent disabled:text-gray-300 disabled:hover:border-gray-200"
|
|
28
|
+
><Icon
|
|
29
|
+
className="mdi--chevron-right"
|
|
30
|
+
ariaLabel=""
|
|
31
|
+
flipIcon={direction === "rtl"}
|
|
32
|
+
/></button
|
|
33
|
+
>
|
|
34
|
+
</div>
|
|
35
|
+
|
|
36
|
+
<div data-carousel class="-m-4 overflow-hidden p-4">
|
|
37
|
+
<ol
|
|
38
|
+
class="flex items-end gap-4 md:gap-8"
|
|
39
|
+
aria-atomic="false"
|
|
40
|
+
aria-live="polite"
|
|
41
|
+
data-carousel-container
|
|
42
|
+
>
|
|
43
|
+
<slot />
|
|
44
|
+
</ol>
|
|
45
|
+
</div>
|
|
46
|
+
</ln-carousel>
|
|
47
|
+
|
|
48
|
+
<script>
|
|
49
|
+
import EmblaCarousel from "embla-carousel"
|
|
50
|
+
import AutoHeightPlugin from "embla-carousel-auto-height"
|
|
51
|
+
import { WheelGesturesPlugin } from "embla-carousel-wheel-gestures"
|
|
52
|
+
|
|
53
|
+
class Carousel extends HTMLElement {
|
|
54
|
+
preloadIndex = 0
|
|
55
|
+
|
|
56
|
+
connectedCallback() {
|
|
57
|
+
const carouselNode = this.querySelector(
|
|
58
|
+
"[data-carousel]",
|
|
59
|
+
) as HTMLElement
|
|
60
|
+
const direction = this.dataset.direction as "ltr" | "rtl"
|
|
61
|
+
const carousel = EmblaCarousel(
|
|
62
|
+
carouselNode,
|
|
63
|
+
{
|
|
64
|
+
slidesToScroll: "auto",
|
|
65
|
+
skipSnaps: true,
|
|
66
|
+
direction,
|
|
67
|
+
},
|
|
68
|
+
[AutoHeightPlugin(), WheelGesturesPlugin({ forceWheelAxis: "x" })],
|
|
69
|
+
)
|
|
70
|
+
const prevBtn = this.querySelector(
|
|
71
|
+
"[data-button-prev]",
|
|
72
|
+
) as HTMLButtonElement
|
|
73
|
+
const nextBtn = this.querySelector(
|
|
74
|
+
"[data-button-next]",
|
|
75
|
+
) as HTMLButtonElement
|
|
76
|
+
|
|
77
|
+
prevBtn.addEventListener("click", () => carousel.scrollPrev())
|
|
78
|
+
nextBtn.addEventListener("click", () => carousel.scrollNext())
|
|
79
|
+
|
|
80
|
+
const updateArrowButtons = () => {
|
|
81
|
+
if (carousel.canScrollPrev()) {
|
|
82
|
+
prevBtn.removeAttribute("disabled")
|
|
83
|
+
} else {
|
|
84
|
+
prevBtn.setAttribute("disabled", "disabled")
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
if (carousel.canScrollNext()) {
|
|
88
|
+
nextBtn.removeAttribute("disabled")
|
|
89
|
+
} else {
|
|
90
|
+
nextBtn.setAttribute("disabled", "disabled")
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
carousel
|
|
94
|
+
.on("init", updateArrowButtons)
|
|
95
|
+
.on("select", updateArrowButtons)
|
|
96
|
+
.on("reInit", updateArrowButtons)
|
|
97
|
+
|
|
98
|
+
// when images are set to loading=lazy, safari and
|
|
99
|
+
// firefox fail to preload them before they are
|
|
100
|
+
// visible. We improve the browser heuristics
|
|
101
|
+
// by setting the next chunk of images to load
|
|
102
|
+
// eagerly.
|
|
103
|
+
const slideNodes =
|
|
104
|
+
this.querySelector("[data-carousel-container]")?.children ?? []
|
|
105
|
+
const preloadNextSlides = () => {
|
|
106
|
+
const slidesInView = carousel.slidesInView()
|
|
107
|
+
slidesInView.forEach((slideIndex) => {
|
|
108
|
+
const preloadIndex = slideIndex + slidesInView.length
|
|
109
|
+
if (preloadIndex > this.preloadIndex) {
|
|
110
|
+
this.preloadIndex = preloadIndex
|
|
111
|
+
const node = slideNodes[preloadIndex]
|
|
112
|
+
node?.querySelectorAll("img").forEach((img) => {
|
|
113
|
+
img.loading = "eager"
|
|
114
|
+
})
|
|
115
|
+
}
|
|
116
|
+
})
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
// start preloading once the carousel enters the viewport
|
|
120
|
+
const observer = new IntersectionObserver(([target]) => {
|
|
121
|
+
if (!target.isIntersecting) {
|
|
122
|
+
return
|
|
123
|
+
}
|
|
124
|
+
preloadNextSlides()
|
|
125
|
+
carousel.on("slidesInView", () => preloadNextSlides())
|
|
126
|
+
observer.unobserve(target.target)
|
|
127
|
+
})
|
|
128
|
+
observer.observe(carouselNode)
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
customElements.define("ln-carousel", Carousel)
|
|
132
|
+
</script>
|
|
133
|
+
</Section>
|
|
134
|
+
<style is:global>
|
|
135
|
+
.carousel-item--wide {
|
|
136
|
+
flex: 0 0 auto;
|
|
137
|
+
/* 1 column + part of the next */
|
|
138
|
+
width: 85%;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
.carousel-item--narrow {
|
|
142
|
+
flex: 0 0 auto;
|
|
143
|
+
/* 2 columns + part of the next */
|
|
144
|
+
width: calc((100% - 1rem) / 2.3);
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
/* sm */
|
|
148
|
+
@media (min-width: 640px) {
|
|
149
|
+
.carousel-item--wide {
|
|
150
|
+
/* 2 columns */
|
|
151
|
+
width: calc((100% - 1rem) / 2);
|
|
152
|
+
}
|
|
153
|
+
.carousel-item--narrow {
|
|
154
|
+
/* 3 columns */
|
|
155
|
+
width: calc((100% - 2rem) / 3);
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
/* md */
|
|
160
|
+
@media (min-width: 768px) {
|
|
161
|
+
.carousel-item--wide {
|
|
162
|
+
/* 3 columns */
|
|
163
|
+
width: calc((100% - 4rem) / 3);
|
|
164
|
+
}
|
|
165
|
+
.carousel-item--narrow {
|
|
166
|
+
/* 4 columns */
|
|
167
|
+
width: calc((100% - 6rem) / 4);
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
/* lg */
|
|
172
|
+
@media (min-width: 1024px) {
|
|
173
|
+
.carousel-item--wide {
|
|
174
|
+
/* 4 columns */
|
|
175
|
+
width: calc((100% - 6rem) / 4);
|
|
176
|
+
}
|
|
177
|
+
.carousel-item--narrow {
|
|
178
|
+
/* 5 columns */
|
|
179
|
+
width: calc((100% - 8rem) / 5);
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
</style>
|