astro-async-loader 0.0.0 β†’ 0.1.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/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 Jonas FrΓΆller
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -1,17 +1,9 @@
1
- # Astro Component Template πŸ§‘β€πŸš€
1
+ # Astro Async-Loader
2
2
 
3
- This is [an unofficial template](#how-is-this-different-from-the-official-component-template) meant to ease the development of components for [Astro](https://astro.build/) that are intended for distribution. It does so by providing you with:
4
-
5
- - A clear default directory structure
6
- - Proper TypeScript settings for working with Astro
7
- - Default settings for ESLint, Prettier and EditorConfig inspired by the formatting used in the Astro project itself (also, [the config files are typed πŸ‘€](https://princesseuh.netlify.app/article/youshouldtypeyourconfigfiles/))
8
- - Ready-to-use testing tools powered by the libraries also used by the Astro project (Mocha and Chai), also contains [astro-component-tester](https://github.com/Princesseuh/astro-component-tester) to help you test the output of your component(s)
9
- - Preconfigured VS Code workspace settings file with settings meant to make development cozy and nice
10
- - Use a example folder to help previewing the Component without npm link
11
-
12
- Hopefully, all of this together will provide you with a fun and comfortable development environnement for working on your Astro component! πŸš€ Also, never forget that this is only a template to get you started, if you don't agree with any of the choices made, feel free to change it to fit your project better!
13
-
14
- **⚠️ Don't forget:** You should edit `package.json` with the info relevant to your project, such as a proper `name`, a license, a link to the repository for the npm website and other settings. You should also adjust the Astro `peerDependency` to the lowest version of Astro you support.
3
+ [![npm](https://badgen.net/badge/icon/npm?icon=npm&label)](https://www.npmjs.com)
4
+ [![total npm downloads](https://badgen.net/npm/dt/astro-async-loader)](https://www.npmjs.com/package/astro-async-loader)
5
+ [![latest npm release](https://img.shields.io/npm/v/astro-async-loader)](https://www.npmjs.com/package/astro-async-loader?activeTab=versions)
6
+ [![npm package license](https://badgen.net/npm/license/astro-async-loader)](https://www.npmjs.com/package/astro-async-loader)
15
7
 
16
8
  ## Folder Structure
17
9
 
@@ -42,34 +34,3 @@ The following npm scripts are provided to lint and format your project:
42
34
  | `npm run dev` | Run dev inside example project |
43
35
 
44
36
  In VS Code, you can access those commands in the Explorer in the `NPM Scripts` section.
45
-
46
- ## Frequently asked questions
47
-
48
- ### How is this different from [the official component template](https://github.com/withastro/astro/tree/main/examples/component)?
49
-
50
- At the end of the day, they both have the same goal: Giving you a template to start from to build a component for Astro. However, they have slightly different philosophies.
51
-
52
- Notably, the official template uses a mono-repo structure, whereas this template uses a normal, straightforward repo. Additionally, this template is a bit more opinionated than the official one, giving you preconfigured support for ESLint, Prettier, VS Code and EditorConfig, as well as testing support.
53
-
54
- It's up to you to choose which one you prefer, they're both good options!
55
-
56
- ### How do I try my component in development?
57
-
58
- > `npm` is used here for brevity, the same concept applies to other package managers!
59
-
60
- This template is a normal npm package, which mean that you can install it as a local folder or using [npm link](https://docs.npmjs.com/cli/v8/commands/npm-link).
61
-
62
- For example, with the following folder structure:
63
-
64
- ```plaintext
65
- β”œβ”€β”€ component/ # Your component using this template
66
- └── project/ # A standard Astro project
67
- ```
68
-
69
- You can go into `project` and type the following command: `npm link ../component`. Changes to your component will be automatically reflected in your Astro project!
70
-
71
- ### Which package manager should I use?
72
-
73
- The one you prefer! This template makes no assumption.
74
-
75
- The only package-manager-related thing in this repo is that the prettier plugin has the proper configuration needed to work with pnpm (but it works with the other too, pnpm just needs [additional settings](https://github.com/withastro/prettier-plugin-astro#pnpm-support)).
package/package.json CHANGED
@@ -1,8 +1,11 @@
1
1
  {
2
2
  "name": "astro-async-loader",
3
- "version": "0.0.0",
3
+ "version": "0.1.0",
4
4
  "description": "Astro components for elements, that load asynchronously, and should have loading indicators.",
5
- "repository": "https://github.com/jonasfroeller/astro.async.loader",
5
+ "repository": {
6
+ "type": "git",
7
+ "url": "git+https://github.com/jonasfroeller/astro.async.loader.git"
8
+ },
6
9
  "license": "MIT",
7
10
  "type": "module",
8
11
  "exports": {
@@ -16,25 +19,27 @@
16
19
  "astro-component"
17
20
  ],
18
21
  "scripts": {
19
- "test": "mocha --parallel --timeout 15000",
22
+ "test": "npx playwright test",
20
23
  "format": "prettier -w .",
21
24
  "lint": "eslint . --ext .ts,.js,.astro src",
22
25
  "dev": "cd example && astro dev"
23
26
  },
24
27
  "devDependencies": {
28
+ "@playwright/test": "^1.57.0",
25
29
  "@types/chai": "^5.0.1",
26
30
  "@types/eslint": "^9.6.1",
27
31
  "@types/mocha": "^10.0.10",
28
- "@types/node": "^22.10.5",
29
- "@types/prettier": "^3.0.0",
32
+ "@types/node": "^25.0.3",
30
33
  "@typescript-eslint/parser": "^8.19.0",
31
34
  "astro": "^5.1.2",
32
- "chai": "^5.1.2",
35
+ "astro-component-tester": "^0.8.0",
36
+ "chai": "^6.2.2",
33
37
  "eslint": "^9.17.0",
34
38
  "eslint-plugin-astro": "^1.3.1",
35
39
  "mocha": "^11.0.1",
40
+ "playwright": "^1.57.0",
36
41
  "prettier": "^3.4.2",
37
42
  "prettier-plugin-astro": "^0.14.1",
38
43
  "typescript": "^5.7.2"
39
44
  }
40
- }
45
+ }
@@ -1,93 +1,96 @@
1
- <div class="async-iframe-wrapper">
2
- <div class="loader-container">
3
- <div class="loader"></div>
1
+ <div class="async-iframe__wrapper">
2
+ <div class="async-iframe__loader-container">
3
+ <div class="async-iframe__loader"></div>
4
4
  </div>
5
5
 
6
- <div class="iframe-container">
6
+ <div class="async-iframe__container">
7
7
  <slot />
8
8
  </div>
9
9
  </div>
10
10
 
11
11
  <script>
12
- function setupIframe() {
13
- const wrapper = document.getElementsByClassName('async-iframe-wrapper')[0];
14
- const loaderContainer = wrapper.getElementsByClassName('loader-container')[0];
15
- const iframe = wrapper.querySelector('iframe');
16
-
17
- if (iframe && loaderContainer) {
18
- const handleLoad = () => {
19
- loaderContainer.classList.add('hidden');
20
- iframe.removeEventListener('load', handleLoad);
21
- };
22
-
23
- iframe.addEventListener('load', handleLoad);
12
+ function setupIframes() {
13
+ const wrappers = document.getElementsByClassName('async-iframe__wrapper');
14
+
15
+ for (let i = 0; i < wrappers.length; i++) {
16
+ const wrapper = wrappers[i];
17
+ const loaderContainer = wrapper.getElementsByClassName('async-iframe__loader-container')[0];
18
+ const iframe = wrapper.getElementsByTagName('iframe')[0];
19
+
20
+ if (iframe && loaderContainer) {
21
+ const handleLoad = () => {
22
+ loaderContainer.classList.add('async-iframe__hidden');
23
+ iframe.removeEventListener('load', handleLoad);
24
+ };
25
+
26
+ iframe.addEventListener('load', handleLoad);
27
+ }
24
28
  }
25
29
  }
26
30
 
27
31
  if (document.readyState === 'loading') {
28
32
  const handleDOMContentLoaded = () => {
29
- setupIframe();
33
+ setupIframes();
30
34
  document.removeEventListener('DOMContentLoaded', handleDOMContentLoaded);
31
35
  };
32
36
 
33
37
  document.addEventListener('DOMContentLoaded', handleDOMContentLoaded);
34
38
  } else {
35
- setupIframe();
39
+ setupIframes();
36
40
  }
37
41
  </script>
38
42
 
39
43
  <style>
40
- .async-iframe-wrapper {
44
+ .async-iframe__wrapper {
41
45
  position: relative;
42
46
  padding-top: 85%;
43
47
  height: 0;
44
48
  overflow: hidden;
45
49
  }
46
50
 
47
- .loader-container {
51
+ .async-iframe__loader-container {
48
52
  position: absolute;
49
- top: 0;
50
- left: 0;
51
- right: 0;
52
- bottom: 0;
53
- display: flex;
54
- align-items: center;
55
- justify-content: center;
56
- z-index: 10;
53
+ inset: 0;
54
+ display: grid;
55
+ place-items: center;
56
+ z-index: 5;
57
+ background: rgba(255, 255, 255, 0.9);
57
58
  }
58
59
 
59
- .loader {
60
+ .async-iframe__loader {
60
61
  width: 2rem;
61
62
  height: 2rem;
62
63
  border-radius: 50%;
63
64
  border: 0.125rem solid transparent;
64
65
  border-top-color: #3b82f6;
65
- animation: spin 1s linear infinite;
66
+ animation: async-iframe__spin 1s linear infinite;
66
67
  }
67
68
 
68
- @keyframes spin {
69
+ @keyframes async-iframe__spin {
69
70
  0% { transform: rotate(0deg); }
70
71
  100% { transform: rotate(360deg); }
71
72
  }
72
73
 
73
- .iframe-container {
74
+ .async-iframe__container {
74
75
  position: absolute;
75
- top: 0px;
76
- left: 0px;
77
- right: 0px;
78
- bottom: 0px;
76
+ inset: 0;
79
77
  }
80
78
 
81
79
  :global(iframe) {
82
80
  position: absolute;
83
- top: 0px;
84
- left: 0px;
81
+ inset: 0;
85
82
  width: 100%;
86
83
  height: 100%;
87
- border: 0px;
84
+ border: 0;
85
+ opacity: 0;
86
+ transition: opacity 0.3s ease-in-out;
88
87
  }
89
88
 
90
- .hidden {
89
+ .async-iframe__hidden {
91
90
  display: none !important;
92
91
  }
92
+
93
+ .async-iframe__hidden + .async-iframe__container :global(iframe) {
94
+ opacity: 1;
95
+ }
93
96
  </style>