@collagejs/core 0.1.0 → 0.1.2

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 CHANGED
@@ -1,21 +1,21 @@
1
- MIT License
2
-
3
- Copyright (c) 2025 collagejs
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.
1
+ MIT License
2
+
3
+ Copyright (c) 2025 collagejs
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,88 +1,146 @@
1
- # <img src="src/logos/collagejs-48.svg" alt="Svelte Router Logo" width="48" height="48" align="left">&nbsp;CollageJS
2
-
3
- > Micro library for framework-agnostic micro-frontends
4
-
5
- **🚧🚧 YOU'RE EARLY. WORK IN PROGRESS... 🚧🚧**
6
-
7
- *If you would like to express youself, head to the [Discussions board](https://github.com/collagejs/collagejs/discussions).*
8
-
9
- [Full Documentation](https://collagejs.dev)
10
-
11
- *CollageJS* is a very, very small library that enables the composition of a web user interface with micro-frontends created with any technology (Svelte, React, Vue, Solid, HTMX, etc.). It is heavily inspired by the *parcel* concept in the excellent `single-spa` routing library.
12
-
13
- ## How It Works
14
-
15
- *CollageJS* defines a contract that must be fulfilled by an object. This contract is defined as the following TypeScript types (simplified):
16
-
17
- ```typescript
18
- type UnmountFn = () => Promise<void>;
19
- type MountFn<TProps> = (target: HTMLElement, props?: TProps) => Promise<UnmountFn>;
20
- type Mount<TProps> = MountFn<TProps> | MountFn<TProps>[] | Mount<TProps>[];
21
- type UpdateFn<TProps> = (props: TProps) => Promise<void>;
22
- type Update<TProps> = UpdateFn<TProps> | UpdateFn<TProps>[] | Update[];
23
-
24
- interface CorePiece<TProps> {
25
- mount: Mount<TProps>;
26
- update?: Update<TProps>;
27
- };
28
- ```
29
- > â„šī¸ These types were simplified. See the real ones after installing the library.
30
-
31
- In short: Micro-frontend creators must simply provide a way to generate an object that fulfills the above `CorePiece` interface, where:
32
-
33
- - `mount` mounts the micro-frontend user interface in the document
34
- - `update` updates the properties given to the micro-frontend
35
-
36
- The `update` function is optional. The `mount` function must return a cleanup function that, ideally, reverts the mounting process.
37
-
38
- This object, once obtained by the consuming project/micro-frontend, is given to the `<Piece>` component. The implementation of this component is framework-specific. For example, the `<Piece>` component found in the `@collagejs/svelte` package is a **Svelte** component.
39
-
40
- ## Router Needs
41
-
42
- As you may (or may not) know, `single-spa` is a client-side router that defines a contract similar to `CorePiece` above. *CollageJS*, on the other hand, doesn't provide a router. Use whichever client-side router you wish in your micro-frontend projects.
43
-
44
- ### Why No Router
45
-
46
- There are 2 reasons. The first one is quite simple: A router is not mandatory to implement and use micro-frontends. Micro-frontends can come and go for any reason, such as the user clicking a button, a timer running out, etc. The "micro-frontend" concept is not tied to routing.
47
-
48
- The second reason is maintenance: Historically, the `single-spa` router has had a tough time pleasing everyone because most often than not, micro-frontends come with their own "sub-routers" installed. MFE's created in React usually come featuring the `react-router` router; SolidJS MFE's come with `@solidjs/router`, etc. and the mixture has sometimes caused problems. Furthermore, `single-spa` provides a web component to configure the router in markup format, which has caused even more issues. Moreover, this layout component lacks features people are used to having within their own frameworks of choice.
49
-
50
- In light of this: **Bring Your Own Router**. It is just better. There are routers out there supported by entire teams with great many features, and developers probably learned to use them already. Not providing a router (unlike `single-spa`) is one less thing to learn for consumers of this library.
51
-
52
- Do you disagree with this? Perhaps you need one and don't know which one would work best? No problem! We can recommend one: Create a "root" **Vite + Svelte** project and use `@svelte-router/core` ([documentation](https://svelte-router.dev)). This is a multi-route-matching router designed for micro-frontends. It is very simple to use and learn, even if you have never used Svelte before.
53
-
54
- **"But I don't want to learn Svelte"**, you might say. Well, it's understandable. However, if you're coming from a `single-spa` experience, learning a bit of Svelte to configure the root router is no different than learning `single-spa`'s layout web component.
55
-
56
- In the end, it is your choice.
57
-
58
- ## For the `single-spa` Savvy
59
-
60
- If you know/are used to `single-spa`, you're almost up to speed with *CollageJS*. Basically, there's no concept of a "root config" project, but of course, there's always a "root" project. Use whatever framework/technology you want to produce it.
61
-
62
- Then the micro-frontends: The concept doesn't exist. At this point (after creating a root UI project), you're 100% free to do as you wish. Just mount *CollageJS pieces*, which are basically the equivalent of `single-spa` parcels. You don't get a router provided, you bring your own, or don't bring a router. No worries. Who says that a router is required? Not us. You can trigger "parcel" loading by any means at your disposal: Button clicks, timers, window events, and yes, also location URL changes (routing) if you want.
63
-
64
- ### Technical Differences
65
-
66
- While `single-spa` asks you to shape your module exports in a particular way (the lifecycle functions), *CollageJS* imposes no such restriction. It is just not necessary. Just make sure you can get an object of type `CorePiece` to the `<Piece>` component of your preferred framework. Then use your framework's marvels to make the `<Piece>` component appear or disappear.
67
-
68
- Yes, you can still use import maps, and can even continue using the excellent `import-map-overrides` package. It is encouraged.
69
-
70
- #### Where Did the `unmount` Lifecycle Function Go?
71
-
72
- In *CollageJS*, `CorePiece.mount()` returns the clean-up (unmounting) function.
73
-
74
- #### And What About `bootstrap`?
75
-
76
- Gone. There's no equivalent in *CollageJS*, as experience with `single-spa` has demonstrated that is rarely needed, and if needed, one can do this initialization easily without having to impose the function requirement. At least for now, there's no foreseeable future where an initialization function similar to `single-spa`'s `bootstrap()` will be defined.
77
-
78
- ## Packages
79
-
80
- | Package | Status | Description |
81
- | - | - | - |
82
- | `@collagejs/core` | âœ”ī¸ | Core functionality. Provides the general mounting and unmouting logic. |
83
- | `@collagejs/vite` | ❌ | Vite plug-in that offers a CSS-mounting algorithm that is fully compatible with Vite's CSS bundling, including split CSS. |
84
- | `@collagejs/svelte` | âœ”ī¸ | Svelte component library that can be used to create `CorePiece`-compliant objects and to mount `CorePiece` objects (of any technology) by providing the `<Piece>` component. |
85
- | `@collagejs/react` | ❌ | React component library that can be used to create `CorePiece`-compliant objects and to mount `CorePiece` objects (of any technology) by providing the `<Piece>` component. |
86
- | `@collagejs/solidjs` | ❌ | SolidJS component library that can be used to create `CorePiece`-compliant objects and to mount `CorePiece` objects (of any technology) by providing the `<Piece>` component. |
87
- | `@collagejs/vue` | ❌ | VueJS component library that can be used to create `CorePiece`-compliant objects and to mount `CorePiece` objects (of any technology) by providing the `<Piece>` component. |
88
- | `@collagejs/angular` | ❌ | **External help needed.** We don't have expertise in Angular, nor do we want to acquire it. If you're an Angular developer, please consider contributing. |
1
+ # <img src="src/logos/collagejs-48.svg" alt="Svelte Router Logo" width="48" height="48" align="left">&nbsp;CollageJS
2
+
3
+ > Micro library for framework-agnostic micro-frontends
4
+
5
+ **🚧🚧 YOU'RE EARLY. WORK IN PROGRESS... ETA: Early January, 2026 🚧🚧**
6
+
7
+ **If you're interested, star the repository to get updates on the progress in your GH homepage.**
8
+
9
+ *If you would like to express youself, head to the [Discussions board](https://github.com/collagejs/collagejs/discussions).*
10
+
11
+ [Full Documentation](https://collagejs.dev)
12
+
13
+ *CollageJS* is a very, very small library that enables the composition of a web user interface with micro-frontends created with any technology (Svelte, React, Vue, Solid, HTMX, etc.). It is heavily inspired by the *parcel* concept in the excellent `single-spa` routing library.
14
+
15
+ ## How It Works
16
+
17
+ *CollageJS* defines a contract that must be fulfilled by an object. This contract is defined by the following TypeScript interface (simplified):
18
+
19
+ ```typescript
20
+ type UnmountFn = () => Promise<void>;
21
+ type MountFn<TProps> = (target: HTMLElement, props?: TProps) => Promise<UnmountFn>;
22
+ type Mount<TProps> = MountFn<TProps> | MountFn<TProps>[] | Mount<TProps>[];
23
+ type UpdateFn<TProps> = (props: TProps) => Promise<void>;
24
+ type Update<TProps> = UpdateFn<TProps> | UpdateFn<TProps>[] | Update[];
25
+
26
+ interface CorePiece<TProps> {
27
+ mount: Mount<TProps>;
28
+ update?: Update<TProps>;
29
+ };
30
+ ```
31
+ > â„šī¸ These types were simplified. See the real ones after installing the library.
32
+
33
+ In short: Micro-frontend creators must simply provide a way to generate an object that fulfills the above `CorePiece` interface, where:
34
+
35
+ - `mount` mounts the micro-frontend user interface in the document
36
+ - `update` updates the properties given to the micro-frontend
37
+
38
+ The `update` function is optional. The `mount` function must return a cleanup function that, ideally, reverts the mounting process.
39
+
40
+ This object, once obtained by the consuming project/micro-frontend, is given to the `<Piece>` component. The implementation of this component is framework-specific. For example, the `<Piece>` component found in the `@collagejs/svelte` package is a **Svelte** component.
41
+
42
+ ### Example
43
+
44
+ This is a simple example that shows a tiny, yet complete micro-frontend made with vanilla TypeScript. It is used to unit-test the `@collagejs/svelte` NPM package:
45
+
46
+ ```typescript
47
+ export function buildTestPiece<TProps extends Record<string, any> = Record<string, any>>(
48
+ callbacks?: {
49
+ mount: (target: HTMLElement, props?: MountProps<TProps>) => void | (() => void);
50
+ unmount: () => void;
51
+ update: (props: TProps) => void;
52
+ }
53
+ ): CorePiece<TProps> {
54
+ let pre: HTMLElement;
55
+ return {
56
+ async mount(target: HTMLElement, props?: MountProps<TProps>) {
57
+ const delayMountCb = callbacks?.mount?.(target, props);
58
+ pre = document.createElement('pre');
59
+ pre.setAttribute('data-testid', pieceTestId);
60
+ pre.textContent = JSON.stringify(props, null, 2);
61
+ target.appendChild(pre);
62
+ if (delayMountCb) {
63
+ await delay();
64
+ delayMountCb();
65
+ }
66
+ return () => {
67
+ callbacks?.unmount?.();
68
+ target.removeChild(pre);
69
+ return Promise.resolve();
70
+ };
71
+ },
72
+ update(props: TProps) {
73
+ callbacks?.update?.(props);
74
+ pre.textContent = JSON.stringify(props, null, 2);
75
+ return Promise.resolve();
76
+ }
77
+ };
78
+ }
79
+ ```
80
+ > *Ignore the callbacks thing. Those exist for unit-testing purposes only.*
81
+
82
+ The key learnings here are:
83
+
84
+ 1. We can export functions that create *CollageJS* pieces. This is the simplest and most flexible approach: **Factory functions**.
85
+ 2. We do whatever we need to do to mount our user interface inside the target element.
86
+ 3. We return a cleanup function that unmounts the user interface.
87
+ 4. We optionally provide the `update()` method for property reactivity.
88
+
89
+ You can export from a single project as many of these factory functions as desired. You are not constrained to expose just one *CollageJS* piece per project. Export as many as needed.
90
+
91
+ This is how packages like `@collagejs/svelte` work: When mounting, it calls Svelte's `mount()` function with the given options (if any are given), and returns a cleanup function that calls `unmount()` on the component. Updating properties is as simple as using a reactive object, at which point Svelte itself takes over the reacting part.
92
+
93
+ ## Router Needs
94
+
95
+ As you may (or may not) know, `single-spa` is a client-side router that defines a contract similar to `CorePiece` above. *CollageJS*, on the other hand, doesn't provide a router. Use whichever client-side router you wish in your micro-frontend projects.
96
+
97
+ ### Why No Router
98
+
99
+ There are 2 reasons:
100
+
101
+ 1. The concept of "micro-frontend" is not tied to routing
102
+ 2. Maintenance
103
+
104
+ Yes, it is very handy to mount/dismount MFE's as the location URL changes. This makes routing a popular choice, but not a mandatory one. MFE's can come and go for any reason, like button clicks, timers or anything a developer can imagine.
105
+
106
+ Maintenance is an issue. The `single-spa` core team has had hard times trying to accommodate everyone's needs, especially when dealing with clashing behavior between their router and some framework's router, because people create MFE's with their own router built-in. On top of this, `single-spa`'s layout web component, which is a "define your routes in markup" helper, lacks features that people want because they exist in other router engines.
107
+
108
+ So, the conclusion here is: *CollageJS* takes care of micro-frontends. Just that.
109
+
110
+ Do you disagree with this? Perhaps you need a router and don't know which one would work best? No problem! We can recommend one: Create a "root" **Vite + Svelte** project and use `@svelte-router/core` ([documentation](https://svelte-router.dev)). This is a multi-route-matching router designed for micro-frontends. It is very simple to use and learn, even if you have never used Svelte before.
111
+
112
+ **"But I don't want to learn Svelte"**, you might say. Well, it's understandable. However, if you're coming from a `single-spa` experience, learning a bit of Svelte to configure the root router is no different than learning `single-spa`'s layout web component. Furthermore, the author of *CollageJS* is the author of `@svelte-router/core` as well.
113
+
114
+ In the end, it is your choice.
115
+
116
+ ## For the `single-spa` Savvy
117
+
118
+ If you know/are used to `single-spa`, you're almost up to speed with *CollageJS*. Basically, there's no concept of a "root config" project, but of course, there's always a "root" project. Use whatever framework/technology you want to produce it.
119
+
120
+ Then the micro-frontends: The concept doesn't exist. At this point (after creating a root UI project), you're 100% free to do as you wish. Just mount *CollageJS pieces*, which are basically the equivalent of `single-spa` parcels. You don't get a router provided, you bring your own, or don't bring a router. No worries. Who says that a router is required? Not us. You can trigger "parcel" loading by any means at your disposal: Button clicks, timers, window events, and yes, also location URL changes (routing) if you want.
121
+
122
+ ### Technical Differences
123
+
124
+ While `single-spa` asks you to shape your module exports in a particular way (the lifecycle functions), *CollageJS* imposes no such restriction. It is just not necessary. Just make sure you can get an object of type `CorePiece` to the `<Piece>` component of your preferred framework. Then use your framework's marvels to make the `<Piece>` component appear or disappear.
125
+
126
+ Yes, you can still use import maps, and can even continue using the excellent `import-map-overrides` package. It is encouraged.
127
+
128
+ #### Where Did the `unmount` Lifecycle Function Go?
129
+
130
+ In *CollageJS*, `CorePiece.mount()` returns the clean-up (unmounting) function.
131
+
132
+ #### And What About `bootstrap`?
133
+
134
+ Gone. There's no equivalent in *CollageJS*, as experience with `single-spa` has demonstrated that is rarely needed, and if needed, one can do this initialization easily without having to impose the function requirement. At least for now, there's no foreseeable future where an initialization function similar to `single-spa`'s `bootstrap()` will be defined. But we agree: *Never say NEVER*.
135
+
136
+ ## Packages
137
+
138
+ | Package | Status | Links | Description |
139
+ | - | - | - | - |
140
+ | `@collagejs/core` | âœ”ī¸ | (This repo) | Core functionality. Provides the general mounting and unmouting logic. |
141
+ | `@collagejs/vite` | 🚧 | [Repo](https://github.com/collagejs/vite) | **Coming soon**. Vite plug-in that offers a CSS-mounting algorithm that is fully compatible with Vite's CSS bundling, including split CSS. |
142
+ | `@collagejs/svelte` | âœ”ī¸ | [Repo](https://github.com/collagejs/svelte) | Svelte component library that can be used to create `CorePiece`-compliant objects and to mount `CorePiece` objects (of any technology) by providing the `<Piece>` component. |
143
+ | `@collagejs/react` | ❌ | [Repo](https://github.com/collagejs/react) | **Next priority**. React component library that can be used to create `CorePiece`-compliant objects and to mount `CorePiece` objects (of any technology) by providing the `<Piece>` component. |
144
+ | `@collagejs/solidjs` | ❌ | [Repo](https://github.com/collagejs/vite) | SolidJS component library that can be used to create `CorePiece`-compliant objects and to mount `CorePiece` objects (of any technology) by providing the `<Piece>` component. |
145
+ | `@collagejs/vue` | ❌ | [Repo](https://github.com/collagejs/vue) | VueJS component library that can be used to create `CorePiece`-compliant objects and to mount `CorePiece` objects (of any technology) by providing the `<Piece>` component. |
146
+ | `@collagejs/angular` | ❌ | | **External help needed.** We don't have expertise in Angular, nor do we want to acquire it. If you're an Angular developer, please consider contributing. |
@@ -1,66 +1,66 @@
1
- <?xml version="1.0" encoding="UTF-8"?>
2
- <svg width="128" height="128" viewBox="0 0 128 128" xmlns="http://www.w3.org/2000/svg">
3
- <defs>
4
- <linearGradient id="primaryGrad" x1="0%" y1="0%" x2="100%" y2="100%">
5
- <stop offset="0%" stop-color="#4F46E5"/>
6
- <stop offset="100%" stop-color="#7C3AED"/>
7
- </linearGradient>
8
- <linearGradient id="secondaryGrad" x1="0%" y1="0%" x2="100%" y2="100%">
9
- <stop offset="0%" stop-color="#06B6D4"/>
10
- <stop offset="100%" stop-color="#0EA5E9"/>
11
- </linearGradient>
12
- <linearGradient id="accentGrad" x1="0%" y1="0%" x2="100%" y2="100%">
13
- <stop offset="0%" stop-color="#10B981"/>
14
- <stop offset="100%" stop-color="#059669"/>
15
- </linearGradient>
16
- <linearGradient id="warningGrad" x1="0%" y1="0%" x2="100%" y2="100%">
17
- <stop offset="0%" stop-color="#F59E0B"/>
18
- <stop offset="100%" stop-color="#D97706"/>
19
- </linearGradient>
20
- <filter id="dropShadow" x="-20%" y="-20%" width="140%" height="140%">
21
- <feDropShadow dx="1" dy="2" stdDeviation="2" flood-opacity="0.2"/>
22
- </filter>
23
- </defs>
24
-
25
- <!-- No background - clean floating pieces -->
26
-
27
- <!-- Simplified collage pieces -->
28
- <!-- Main piece (top-left) -->
29
- <path d="M20 30 L55 25 L60 45 L50 60 L30 55 L20 40 Z"
30
- fill="url(#primaryGrad)"
31
- filter="url(#dropShadow)"
32
- opacity="0.9"/>
33
-
34
- <!-- Secondary piece (top-right) -->
35
- <path d="M70 20 L105 30 L100 50 L90 45 L80 35 L70 30 Z"
36
- fill="url(#secondaryGrad)"
37
- filter="url(#dropShadow)"
38
- opacity="0.85"/>
39
-
40
- <!-- Third piece (center-left) -->
41
- <path d="M15 65 L45 60 L50 80 L40 90 L25 85 L15 75 Z"
42
- fill="url(#accentGrad)"
43
- filter="url(#dropShadow)"
44
- opacity="0.8"/>
45
-
46
- <!-- Fourth piece (bottom-right) -->
47
- <path d="M55 75 L95 80 L90 100 L75 105 L60 95 L55 85 Z"
48
- fill="url(#warningGrad)"
49
- filter="url(#dropShadow)"
50
- opacity="0.85"/>
51
-
52
- <!-- Small connecting dots for detail -->
53
- <circle cx="60" cy="50" r="4" fill="url(#secondaryGrad)" opacity="0.8"/>
54
- <circle cx="80" cy="65" r="3" fill="url(#accentGrad)" opacity="0.8"/>
55
-
56
- <!-- Central JS text with enhanced visibility -->
57
- <text x="64" y="74"
58
- font-family="'SF Pro Display', 'Segoe UI', -apple-system, sans-serif"
59
- font-size="24"
60
- font-weight="700"
61
- text-anchor="middle"
62
- fill="url(#primaryGrad)"
63
- stroke="#FFFFFF"
64
- stroke-width="1"
65
- paint-order="stroke fill">JS</text>
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <svg width="128" height="128" viewBox="0 0 128 128" xmlns="http://www.w3.org/2000/svg">
3
+ <defs>
4
+ <linearGradient id="primaryGrad" x1="0%" y1="0%" x2="100%" y2="100%">
5
+ <stop offset="0%" stop-color="#4F46E5"/>
6
+ <stop offset="100%" stop-color="#7C3AED"/>
7
+ </linearGradient>
8
+ <linearGradient id="secondaryGrad" x1="0%" y1="0%" x2="100%" y2="100%">
9
+ <stop offset="0%" stop-color="#06B6D4"/>
10
+ <stop offset="100%" stop-color="#0EA5E9"/>
11
+ </linearGradient>
12
+ <linearGradient id="accentGrad" x1="0%" y1="0%" x2="100%" y2="100%">
13
+ <stop offset="0%" stop-color="#10B981"/>
14
+ <stop offset="100%" stop-color="#059669"/>
15
+ </linearGradient>
16
+ <linearGradient id="warningGrad" x1="0%" y1="0%" x2="100%" y2="100%">
17
+ <stop offset="0%" stop-color="#F59E0B"/>
18
+ <stop offset="100%" stop-color="#D97706"/>
19
+ </linearGradient>
20
+ <filter id="dropShadow" x="-20%" y="-20%" width="140%" height="140%">
21
+ <feDropShadow dx="1" dy="2" stdDeviation="2" flood-opacity="0.2"/>
22
+ </filter>
23
+ </defs>
24
+
25
+ <!-- No background - clean floating pieces -->
26
+
27
+ <!-- Simplified collage pieces -->
28
+ <!-- Main piece (top-left) -->
29
+ <path d="M20 30 L55 25 L60 45 L50 60 L30 55 L20 40 Z"
30
+ fill="url(#primaryGrad)"
31
+ filter="url(#dropShadow)"
32
+ opacity="0.9"/>
33
+
34
+ <!-- Secondary piece (top-right) -->
35
+ <path d="M70 20 L105 30 L100 50 L90 45 L80 35 L70 30 Z"
36
+ fill="url(#secondaryGrad)"
37
+ filter="url(#dropShadow)"
38
+ opacity="0.85"/>
39
+
40
+ <!-- Third piece (center-left) -->
41
+ <path d="M15 65 L45 60 L50 80 L40 90 L25 85 L15 75 Z"
42
+ fill="url(#accentGrad)"
43
+ filter="url(#dropShadow)"
44
+ opacity="0.8"/>
45
+
46
+ <!-- Fourth piece (bottom-right) -->
47
+ <path d="M55 75 L95 80 L90 100 L75 105 L60 95 L55 85 Z"
48
+ fill="url(#warningGrad)"
49
+ filter="url(#dropShadow)"
50
+ opacity="0.85"/>
51
+
52
+ <!-- Small connecting dots for detail -->
53
+ <circle cx="60" cy="50" r="4" fill="url(#secondaryGrad)" opacity="0.8"/>
54
+ <circle cx="80" cy="65" r="3" fill="url(#accentGrad)" opacity="0.8"/>
55
+
56
+ <!-- Central JS text with enhanced visibility -->
57
+ <text x="64" y="74"
58
+ font-family="'SF Pro Display', 'Segoe UI', -apple-system, sans-serif"
59
+ font-size="24"
60
+ font-weight="700"
61
+ text-anchor="middle"
62
+ fill="url(#primaryGrad)"
63
+ stroke="#FFFFFF"
64
+ stroke-width="1"
65
+ paint-order="stroke fill">JS</text>
66
66
  </svg>
@@ -1,19 +1,19 @@
1
- <?xml version="1.0" encoding="UTF-8"?>
2
- <svg width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
3
- <defs>
4
- <linearGradient id="primaryGrad" x1="0%" y1="0%" x2="100%" y2="100%">
5
- <stop offset="0%" stop-color="#4F46E5"/>
6
- <stop offset="100%" stop-color="#7C3AED"/>
7
- </linearGradient>
8
- <linearGradient id="warningGrad" x1="0%" y1="0%" x2="100%" y2="100%">
9
- <stop offset="0%" stop-color="#F59E0B"/>
10
- <stop offset="100%" stop-color="#D97706"/>
11
- </linearGradient>
12
- </defs>
13
-
14
- <!-- Pure geometric representation -->
15
- <path d="M3 4 L7 3 L8 6 L6 8 L4 7 L3 5 Z" fill="url(#primaryGrad)" opacity="0.9"/>
16
- <path d="M9 3 L13 4 L12 7 L10 6 L9 5 Z" fill="#06B6D4" opacity="0.8"/>
17
- <path d="M2 9 L6 8 L7 11 L5 13 L3 12 L2 10 Z" fill="#10B981" opacity="0.8"/>
18
- <rect x="8" y="9" width="6" height="4" rx="1" fill="url(#warningGrad)" opacity="0.8"/>
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <svg width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
3
+ <defs>
4
+ <linearGradient id="primaryGrad" x1="0%" y1="0%" x2="100%" y2="100%">
5
+ <stop offset="0%" stop-color="#4F46E5"/>
6
+ <stop offset="100%" stop-color="#7C3AED"/>
7
+ </linearGradient>
8
+ <linearGradient id="warningGrad" x1="0%" y1="0%" x2="100%" y2="100%">
9
+ <stop offset="0%" stop-color="#F59E0B"/>
10
+ <stop offset="100%" stop-color="#D97706"/>
11
+ </linearGradient>
12
+ </defs>
13
+
14
+ <!-- Pure geometric representation -->
15
+ <path d="M3 4 L7 3 L8 6 L6 8 L4 7 L3 5 Z" fill="url(#primaryGrad)" opacity="0.9"/>
16
+ <path d="M9 3 L13 4 L12 7 L10 6 L9 5 Z" fill="#06B6D4" opacity="0.8"/>
17
+ <path d="M2 9 L6 8 L7 11 L5 13 L3 12 L2 10 Z" fill="#10B981" opacity="0.8"/>
18
+ <rect x="8" y="9" width="6" height="4" rx="1" fill="url(#warningGrad)" opacity="0.8"/>
19
19
  </svg>
@@ -1,50 +1,50 @@
1
- <?xml version="1.0" encoding="UTF-8"?>
2
- <svg width="48" height="48" viewBox="0 0 48 48" xmlns="http://www.w3.org/2000/svg">
3
- <defs>
4
- <linearGradient id="primaryGrad" x1="0%" y1="0%" x2="100%" y2="100%">
5
- <stop offset="0%" stop-color="#4F46E5"/>
6
- <stop offset="100%" stop-color="#7C3AED"/>
7
- </linearGradient>
8
- <linearGradient id="secondaryGrad" x1="0%" y1="0%" x2="100%" y2="100%">
9
- <stop offset="0%" stop-color="#06B6D4"/>
10
- <stop offset="100%" stop-color="#0EA5E9"/>
11
- </linearGradient>
12
- <linearGradient id="accentGrad" x1="0%" y1="0%" x2="100%" y2="100%">
13
- <stop offset="0%" stop-color="#10B981"/>
14
- <stop offset="100%" stop-color="#059669"/>
15
- </linearGradient>
16
- <linearGradient id="warningGrad" x1="0%" y1="0%" x2="100%" y2="100%">
17
- <stop offset="0%" stop-color="#F59E0B"/>
18
- <stop offset="100%" stop-color="#D97706"/>
19
- </linearGradient>
20
- </defs>
21
-
22
- <!-- No background - ultra minimal -->
23
-
24
- <!-- Very simplified geometric shapes -->
25
- <path d="M8 12 L20 10 L22 18 L18 22 L12 20 L8 16 Z"
26
- fill="url(#primaryGrad)"
27
- opacity="0.9"/>
28
-
29
- <path d="M26 8 L38 12 L36 20 L32 18 L28 14 L26 12 Z"
30
- fill="url(#secondaryGrad)"
31
- opacity="0.85"/>
32
-
33
- <path d="M6 26 L18 24 L20 32 L16 36 L10 34 L6 30 Z"
34
- fill="url(#accentGrad)"
35
- opacity="0.8"/>
36
-
37
- <rect x="24" y="28" width="16" height="12" rx="2"
38
- fill="url(#warningGrad)"
39
- opacity="0.85"/>
40
-
41
- <!-- Enhanced JS text with stroke -->
42
- <text x="24" y="28"
43
- font-family="'SF Pro Display', 'Segoe UI', -apple-system, sans-serif"
44
- font-size="10"
45
- font-weight="700"
46
- text-anchor="middle"
47
- fill="#FFFFFF"
48
- stroke="url(#primaryGrad)"
49
- stroke-width="0.5">JS</text>
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <svg width="48" height="48" viewBox="0 0 48 48" xmlns="http://www.w3.org/2000/svg">
3
+ <defs>
4
+ <linearGradient id="primaryGrad" x1="0%" y1="0%" x2="100%" y2="100%">
5
+ <stop offset="0%" stop-color="#4F46E5"/>
6
+ <stop offset="100%" stop-color="#7C3AED"/>
7
+ </linearGradient>
8
+ <linearGradient id="secondaryGrad" x1="0%" y1="0%" x2="100%" y2="100%">
9
+ <stop offset="0%" stop-color="#06B6D4"/>
10
+ <stop offset="100%" stop-color="#0EA5E9"/>
11
+ </linearGradient>
12
+ <linearGradient id="accentGrad" x1="0%" y1="0%" x2="100%" y2="100%">
13
+ <stop offset="0%" stop-color="#10B981"/>
14
+ <stop offset="100%" stop-color="#059669"/>
15
+ </linearGradient>
16
+ <linearGradient id="warningGrad" x1="0%" y1="0%" x2="100%" y2="100%">
17
+ <stop offset="0%" stop-color="#F59E0B"/>
18
+ <stop offset="100%" stop-color="#D97706"/>
19
+ </linearGradient>
20
+ </defs>
21
+
22
+ <!-- No background - ultra minimal -->
23
+
24
+ <!-- Very simplified geometric shapes -->
25
+ <path d="M8 12 L20 10 L22 18 L18 22 L12 20 L8 16 Z"
26
+ fill="url(#primaryGrad)"
27
+ opacity="0.9"/>
28
+
29
+ <path d="M26 8 L38 12 L36 20 L32 18 L28 14 L26 12 Z"
30
+ fill="url(#secondaryGrad)"
31
+ opacity="0.85"/>
32
+
33
+ <path d="M6 26 L18 24 L20 32 L16 36 L10 34 L6 30 Z"
34
+ fill="url(#accentGrad)"
35
+ opacity="0.8"/>
36
+
37
+ <rect x="24" y="28" width="16" height="12" rx="2"
38
+ fill="url(#warningGrad)"
39
+ opacity="0.85"/>
40
+
41
+ <!-- Enhanced JS text with stroke -->
42
+ <text x="24" y="28"
43
+ font-family="'SF Pro Display', 'Segoe UI', -apple-system, sans-serif"
44
+ font-size="10"
45
+ font-weight="700"
46
+ text-anchor="middle"
47
+ fill="#FFFFFF"
48
+ stroke="url(#primaryGrad)"
49
+ stroke-width="0.5">JS</text>
50
50
  </svg>
@@ -1,99 +1,99 @@
1
- <?xml version="1.0" encoding="UTF-8"?>
2
- <svg width="512" height="512" viewBox="0 0 512 512" xmlns="http://www.w3.org/2000/svg">
3
- <defs>
4
- <!-- Gradients for depth and modern look -->
5
- <linearGradient id="primaryGrad" x1="0%" y1="0%" x2="100%" y2="100%">
6
- <stop offset="0%" stop-color="#4F46E5"/>
7
- <stop offset="100%" stop-color="#7C3AED"/>
8
- </linearGradient>
9
- <linearGradient id="secondaryGrad" x1="0%" y1="0%" x2="100%" y2="100%">
10
- <stop offset="0%" stop-color="#06B6D4"/>
11
- <stop offset="100%" stop-color="#0EA5E9"/>
12
- </linearGradient>
13
- <linearGradient id="accentGrad" x1="0%" y1="0%" x2="100%" y2="100%">
14
- <stop offset="0%" stop-color="#10B981"/>
15
- <stop offset="100%" stop-color="#059669"/>
16
- </linearGradient>
17
- <linearGradient id="warningGrad" x1="0%" y1="0%" x2="100%" y2="100%">
18
- <stop offset="0%" stop-color="#F59E0B"/>
19
- <stop offset="100%" stop-color="#D97706"/>
20
- </linearGradient>
21
- <!-- Drop shadows -->
22
- <filter id="dropShadow" x="-20%" y="-20%" width="140%" height="140%">
23
- <feDropShadow dx="4" dy="6" stdDeviation="8" flood-opacity="0.15"/>
24
- </filter>
25
- <filter id="glow" x="-50%" y="-50%" width="200%" height="200%">
26
- <feGaussianBlur stdDeviation="3" result="coloredBlur"/>
27
- <feMerge>
28
- <feMergeNode in="coloredBlur"/>
29
- <feMergeNode in="SourceGraphic"/>
30
- </feMerge>
31
- </filter>
32
- </defs>
33
-
34
- <!-- No background - pieces float freely -->
35
-
36
- <!-- Main collage pieces - representing micro-frontend components -->
37
- <!-- Large primary piece (top-left) -->
38
- <path d="M80 120 L220 100 L240 180 L200 240 L120 220 L80 160 Z"
39
- fill="url(#primaryGrad)"
40
- filter="url(#glow)"
41
- opacity="0.95"/>
42
-
43
- <!-- Secondary piece (top-right) -->
44
- <path d="M280 80 L420 120 L400 200 L360 180 L320 140 L280 120 Z"
45
- fill="url(#secondaryGrad)"
46
- filter="url(#dropShadow)"
47
- opacity="0.85"/>
48
-
49
- <!-- Third piece (center-left) -->
50
- <path d="M60 260 L180 240 L200 320 L160 360 L100 340 L60 300 Z"
51
- fill="url(#accentGrad)"
52
- filter="url(#dropShadow)"
53
- opacity="0.8"/>
54
-
55
- <!-- Fourth piece (bottom-center) -->
56
- <path d="M220 300 L380 320 L360 400 L300 420 L240 380 L220 340 Z"
57
- fill="url(#warningGrad)"
58
- filter="url(#dropShadow)"
59
- opacity="0.85"/>
60
-
61
- <!-- Fifth piece (right) -->
62
- <path d="M380 200 L460 240 L440 320 L400 300 L380 260 Z"
63
- fill="url(#primaryGrad)"
64
- filter="url(#dropShadow)"
65
- opacity="0.7"/>
66
-
67
- <!-- Small connecting pieces for detail -->
68
- <circle cx="240" cy="200" r="16" fill="url(#secondaryGrad)" opacity="0.8"/>
69
- <circle cx="320" cy="260" r="12" fill="url(#accentGrad)" opacity="0.8"/>
70
- <circle cx="180" cy="300" r="10" fill="url(#primaryGrad)" opacity="0.8"/>
71
-
72
- <!-- Stylized "JS" text with enhanced visibility -->
73
- <g transform="translate(256, 400)">
74
- <text x="0" y="0"
75
- font-family="'SF Pro Display', 'Segoe UI', -apple-system, sans-serif"
76
- font-size="72"
77
- font-weight="700"
78
- text-anchor="middle"
79
- fill="url(#primaryGrad)"
80
- stroke="#FFFFFF"
81
- stroke-width="2"
82
- paint-order="stroke fill">JS</text>
83
- </g>
84
-
85
- <!-- CollageJS text -->
86
- <g transform="translate(256, 450)">
87
- <text x="0" y="0"
88
- font-family="'SF Pro Display', 'Segoe UI', -apple-system, sans-serif"
89
- font-size="28"
90
- font-weight="500"
91
- text-anchor="middle"
92
- fill="#374151">Collage</text>
93
- </g>
94
-
95
- <!-- Subtle connection lines showing pieces working together -->
96
- <line x1="150" y1="160" x2="200" y2="200" stroke="url(#primaryGrad)" stroke-width="3" opacity="0.3"/>
97
- <line x1="280" y1="140" x2="320" y2="180" stroke="url(#secondaryGrad)" stroke-width="3" opacity="0.3"/>
98
- <line x1="200" y1="280" x2="280" y2="300" stroke="url(#accentGrad)" stroke-width="3" opacity="0.3"/>
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <svg width="512" height="512" viewBox="0 0 512 512" xmlns="http://www.w3.org/2000/svg">
3
+ <defs>
4
+ <!-- Gradients for depth and modern look -->
5
+ <linearGradient id="primaryGrad" x1="0%" y1="0%" x2="100%" y2="100%">
6
+ <stop offset="0%" stop-color="#4F46E5"/>
7
+ <stop offset="100%" stop-color="#7C3AED"/>
8
+ </linearGradient>
9
+ <linearGradient id="secondaryGrad" x1="0%" y1="0%" x2="100%" y2="100%">
10
+ <stop offset="0%" stop-color="#06B6D4"/>
11
+ <stop offset="100%" stop-color="#0EA5E9"/>
12
+ </linearGradient>
13
+ <linearGradient id="accentGrad" x1="0%" y1="0%" x2="100%" y2="100%">
14
+ <stop offset="0%" stop-color="#10B981"/>
15
+ <stop offset="100%" stop-color="#059669"/>
16
+ </linearGradient>
17
+ <linearGradient id="warningGrad" x1="0%" y1="0%" x2="100%" y2="100%">
18
+ <stop offset="0%" stop-color="#F59E0B"/>
19
+ <stop offset="100%" stop-color="#D97706"/>
20
+ </linearGradient>
21
+ <!-- Drop shadows -->
22
+ <filter id="dropShadow" x="-20%" y="-20%" width="140%" height="140%">
23
+ <feDropShadow dx="4" dy="6" stdDeviation="8" flood-opacity="0.15"/>
24
+ </filter>
25
+ <filter id="glow" x="-50%" y="-50%" width="200%" height="200%">
26
+ <feGaussianBlur stdDeviation="3" result="coloredBlur"/>
27
+ <feMerge>
28
+ <feMergeNode in="coloredBlur"/>
29
+ <feMergeNode in="SourceGraphic"/>
30
+ </feMerge>
31
+ </filter>
32
+ </defs>
33
+
34
+ <!-- No background - pieces float freely -->
35
+
36
+ <!-- Main collage pieces - representing micro-frontend components -->
37
+ <!-- Large primary piece (top-left) -->
38
+ <path d="M80 120 L220 100 L240 180 L200 240 L120 220 L80 160 Z"
39
+ fill="url(#primaryGrad)"
40
+ filter="url(#glow)"
41
+ opacity="0.95"/>
42
+
43
+ <!-- Secondary piece (top-right) -->
44
+ <path d="M280 80 L420 120 L400 200 L360 180 L320 140 L280 120 Z"
45
+ fill="url(#secondaryGrad)"
46
+ filter="url(#dropShadow)"
47
+ opacity="0.85"/>
48
+
49
+ <!-- Third piece (center-left) -->
50
+ <path d="M60 260 L180 240 L200 320 L160 360 L100 340 L60 300 Z"
51
+ fill="url(#accentGrad)"
52
+ filter="url(#dropShadow)"
53
+ opacity="0.8"/>
54
+
55
+ <!-- Fourth piece (bottom-center) -->
56
+ <path d="M220 300 L380 320 L360 400 L300 420 L240 380 L220 340 Z"
57
+ fill="url(#warningGrad)"
58
+ filter="url(#dropShadow)"
59
+ opacity="0.85"/>
60
+
61
+ <!-- Fifth piece (right) -->
62
+ <path d="M380 200 L460 240 L440 320 L400 300 L380 260 Z"
63
+ fill="url(#primaryGrad)"
64
+ filter="url(#dropShadow)"
65
+ opacity="0.7"/>
66
+
67
+ <!-- Small connecting pieces for detail -->
68
+ <circle cx="240" cy="200" r="16" fill="url(#secondaryGrad)" opacity="0.8"/>
69
+ <circle cx="320" cy="260" r="12" fill="url(#accentGrad)" opacity="0.8"/>
70
+ <circle cx="180" cy="300" r="10" fill="url(#primaryGrad)" opacity="0.8"/>
71
+
72
+ <!-- Stylized "JS" text with enhanced visibility -->
73
+ <g transform="translate(256, 400)">
74
+ <text x="0" y="0"
75
+ font-family="'SF Pro Display', 'Segoe UI', -apple-system, sans-serif"
76
+ font-size="72"
77
+ font-weight="700"
78
+ text-anchor="middle"
79
+ fill="url(#primaryGrad)"
80
+ stroke="#FFFFFF"
81
+ stroke-width="2"
82
+ paint-order="stroke fill">JS</text>
83
+ </g>
84
+
85
+ <!-- CollageJS text -->
86
+ <g transform="translate(256, 450)">
87
+ <text x="0" y="0"
88
+ font-family="'SF Pro Display', 'Segoe UI', -apple-system, sans-serif"
89
+ font-size="28"
90
+ font-weight="500"
91
+ text-anchor="middle"
92
+ fill="#374151">Collage</text>
93
+ </g>
94
+
95
+ <!-- Subtle connection lines showing pieces working together -->
96
+ <line x1="150" y1="160" x2="200" y2="200" stroke="url(#primaryGrad)" stroke-width="3" opacity="0.3"/>
97
+ <line x1="280" y1="140" x2="320" y2="180" stroke="url(#secondaryGrad)" stroke-width="3" opacity="0.3"/>
98
+ <line x1="200" y1="280" x2="280" y2="300" stroke="url(#accentGrad)" stroke-width="3" opacity="0.3"/>
99
99
  </svg>
@@ -1,54 +1,54 @@
1
- <?xml version="1.0" encoding="UTF-8"?>
2
- <svg width="64" height="64" viewBox="0 0 64 64" xmlns="http://www.w3.org/2000/svg">
3
- <defs>
4
- <linearGradient id="primaryGrad" x1="0%" y1="0%" x2="100%" y2="100%">
5
- <stop offset="0%" stop-color="#4F46E5"/>
6
- <stop offset="100%" stop-color="#7C3AED"/>
7
- </linearGradient>
8
- <linearGradient id="secondaryGrad" x1="0%" y1="0%" x2="100%" y2="100%">
9
- <stop offset="0%" stop-color="#06B6D4"/>
10
- <stop offset="100%" stop-color="#0EA5E9"/>
11
- </linearGradient>
12
- <linearGradient id="accentGrad" x1="0%" y1="0%" x2="100%" y2="100%">
13
- <stop offset="0%" stop-color="#10B981"/>
14
- <stop offset="100%" stop-color="#059669"/>
15
- </linearGradient>
16
- <linearGradient id="warningGrad" x1="0%" y1="0%" x2="100%" y2="100%">
17
- <stop offset="0%" stop-color="#F59E0B"/>
18
- <stop offset="100%" stop-color="#D97706"/>
19
- </linearGradient>
20
- </defs>
21
-
22
- <!-- No background - minimal clean design -->
23
-
24
- <!-- Simplified geometric pieces -->
25
- <path d="M10 15 L28 12 L30 22 L25 30 L15 28 L10 20 Z"
26
- fill="url(#primaryGrad)"
27
- opacity="0.9"/>
28
-
29
- <path d="M35 10 L52 15 L50 25 L45 22 L40 17 L35 15 Z"
30
- fill="url(#secondaryGrad)"
31
- opacity="0.85"/>
32
-
33
- <path d="M8 32 L22 30 L25 40 L20 45 L12 42 L8 37 Z"
34
- fill="url(#accentGrad)"
35
- opacity="0.8"/>
36
-
37
- <path d="M28 37 L47 40 L45 50 L37 52 L30 47 L28 42 Z"
38
- fill="url(#warningGrad)"
39
- opacity="0.85"/>
40
-
41
- <!-- Small connecting dot for detail -->
42
- <circle cx="40" cy="32" r="2" fill="url(#secondaryGrad)" opacity="0.8"/>
43
-
44
- <!-- Central JS with stroke for visibility -->
45
- <text x="32" y="37"
46
- font-family="'SF Pro Display', 'Segoe UI', -apple-system, sans-serif"
47
- font-size="12"
48
- font-weight="700"
49
- text-anchor="middle"
50
- fill="url(#primaryGrad)"
51
- stroke="#FFFFFF"
52
- stroke-width="0.8"
53
- paint-order="stroke fill">JS</text>
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <svg width="64" height="64" viewBox="0 0 64 64" xmlns="http://www.w3.org/2000/svg">
3
+ <defs>
4
+ <linearGradient id="primaryGrad" x1="0%" y1="0%" x2="100%" y2="100%">
5
+ <stop offset="0%" stop-color="#4F46E5"/>
6
+ <stop offset="100%" stop-color="#7C3AED"/>
7
+ </linearGradient>
8
+ <linearGradient id="secondaryGrad" x1="0%" y1="0%" x2="100%" y2="100%">
9
+ <stop offset="0%" stop-color="#06B6D4"/>
10
+ <stop offset="100%" stop-color="#0EA5E9"/>
11
+ </linearGradient>
12
+ <linearGradient id="accentGrad" x1="0%" y1="0%" x2="100%" y2="100%">
13
+ <stop offset="0%" stop-color="#10B981"/>
14
+ <stop offset="100%" stop-color="#059669"/>
15
+ </linearGradient>
16
+ <linearGradient id="warningGrad" x1="0%" y1="0%" x2="100%" y2="100%">
17
+ <stop offset="0%" stop-color="#F59E0B"/>
18
+ <stop offset="100%" stop-color="#D97706"/>
19
+ </linearGradient>
20
+ </defs>
21
+
22
+ <!-- No background - minimal clean design -->
23
+
24
+ <!-- Simplified geometric pieces -->
25
+ <path d="M10 15 L28 12 L30 22 L25 30 L15 28 L10 20 Z"
26
+ fill="url(#primaryGrad)"
27
+ opacity="0.9"/>
28
+
29
+ <path d="M35 10 L52 15 L50 25 L45 22 L40 17 L35 15 Z"
30
+ fill="url(#secondaryGrad)"
31
+ opacity="0.85"/>
32
+
33
+ <path d="M8 32 L22 30 L25 40 L20 45 L12 42 L8 37 Z"
34
+ fill="url(#accentGrad)"
35
+ opacity="0.8"/>
36
+
37
+ <path d="M28 37 L47 40 L45 50 L37 52 L30 47 L28 42 Z"
38
+ fill="url(#warningGrad)"
39
+ opacity="0.85"/>
40
+
41
+ <!-- Small connecting dot for detail -->
42
+ <circle cx="40" cy="32" r="2" fill="url(#secondaryGrad)" opacity="0.8"/>
43
+
44
+ <!-- Central JS with stroke for visibility -->
45
+ <text x="32" y="37"
46
+ font-family="'SF Pro Display', 'Segoe UI', -apple-system, sans-serif"
47
+ font-size="12"
48
+ font-weight="700"
49
+ text-anchor="middle"
50
+ fill="url(#primaryGrad)"
51
+ stroke="#FFFFFF"
52
+ stroke-width="0.8"
53
+ paint-order="stroke fill">JS</text>
54
54
  </svg>
@@ -1,70 +1,70 @@
1
- <?xml version="1.0" encoding="UTF-8"?>
2
- <svg width="256" height="256" viewBox="0 0 256 256" xmlns="http://www.w3.org/2000/svg">
3
- <defs>
4
- <linearGradient id="primaryGrad" x1="0%" y1="0%" x2="100%" y2="100%">
5
- <stop offset="0%" stop-color="#4F46E5"/>
6
- <stop offset="100%" stop-color="#7C3AED"/>
7
- </linearGradient>
8
- <linearGradient id="secondaryGrad" x1="0%" y1="0%" x2="100%" y2="100%">
9
- <stop offset="0%" stop-color="#06B6D4"/>
10
- <stop offset="100%" stop-color="#0EA5E9"/>
11
- </linearGradient>
12
- <linearGradient id="accentGrad" x1="0%" y1="0%" x2="100%" y2="100%">
13
- <stop offset="0%" stop-color="#10B981"/>
14
- <stop offset="100%" stop-color="#059669"/>
15
- </linearGradient>
16
- <linearGradient id="warningGrad" x1="0%" y1="0%" x2="100%" y2="100%">
17
- <stop offset="0%" stop-color="#F59E0B"/>
18
- <stop offset="100%" stop-color="#D97706"/>
19
- </linearGradient>
20
- <filter id="dropShadow" x="-20%" y="-20%" width="140%" height="140%">
21
- <feDropShadow dx="2" dy="3" stdDeviation="4" flood-opacity="0.15"/>
22
- </filter>
23
- </defs>
24
-
25
- <!-- Subtle universal background -->
26
- <defs>
27
- <radialGradient id="universalBg" cx="50%" cy="50%" r="70%">
28
- <stop offset="0%" stop-color="#F8FAFC" stop-opacity="0.9"/>
29
- <stop offset="100%" stop-color="#E2E8F0" stop-opacity="0.7"/>
30
- </radialGradient>
31
- </defs>
32
- <rect width="256" height="256" fill="url(#universalBg)"/>
33
-
34
- <!-- Stylized collage pieces arranged in a pleasing composition -->
35
- <path d="M40 60 L110 50 L120 90 L100 120 L60 110 L40 80 Z"
36
- fill="url(#primaryGrad)"
37
- filter="url(#dropShadow)"
38
- opacity="0.9"/>
39
-
40
- <path d="M140 40 L210 60 L200 100 L180 90 L160 70 L140 60 Z"
41
- fill="url(#secondaryGrad)"
42
- filter="url(#dropShadow)"
43
- opacity="0.85"/>
44
-
45
- <path d="M30 130 L90 120 L100 160 L80 180 L50 170 L30 150 Z"
46
- fill="url(#accentGrad)"
47
- filter="url(#dropShadow)"
48
- opacity="0.8"/>
49
-
50
- <path d="M110 150 L190 160 L180 200 L150 210 L120 190 L110 170 Z"
51
- fill="url(#warningGrad)"
52
- filter="url(#dropShadow)"
53
- opacity="0.85"/>
54
-
55
- <path d="M190 100 L230 120 L220 160 L200 150 L190 130 Z"
56
- fill="url(#primaryGrad)"
57
- filter="url(#dropShadow)"
58
- opacity="0.7"/>
59
-
60
- <!-- Central focus point -->
61
- <circle cx="128" cy="128" r="8" fill="url(#secondaryGrad)" opacity="0.8"/>
62
-
63
- <!-- Clean, modern "JS" -->
64
- <text x="128" y="145"
65
- font-family="'SF Pro Display', 'Segoe UI', -apple-system, sans-serif"
66
- font-size="36"
67
- font-weight="700"
68
- text-anchor="middle"
69
- fill="url(#primaryGrad)">JS</text>
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <svg width="256" height="256" viewBox="0 0 256 256" xmlns="http://www.w3.org/2000/svg">
3
+ <defs>
4
+ <linearGradient id="primaryGrad" x1="0%" y1="0%" x2="100%" y2="100%">
5
+ <stop offset="0%" stop-color="#4F46E5"/>
6
+ <stop offset="100%" stop-color="#7C3AED"/>
7
+ </linearGradient>
8
+ <linearGradient id="secondaryGrad" x1="0%" y1="0%" x2="100%" y2="100%">
9
+ <stop offset="0%" stop-color="#06B6D4"/>
10
+ <stop offset="100%" stop-color="#0EA5E9"/>
11
+ </linearGradient>
12
+ <linearGradient id="accentGrad" x1="0%" y1="0%" x2="100%" y2="100%">
13
+ <stop offset="0%" stop-color="#10B981"/>
14
+ <stop offset="100%" stop-color="#059669"/>
15
+ </linearGradient>
16
+ <linearGradient id="warningGrad" x1="0%" y1="0%" x2="100%" y2="100%">
17
+ <stop offset="0%" stop-color="#F59E0B"/>
18
+ <stop offset="100%" stop-color="#D97706"/>
19
+ </linearGradient>
20
+ <filter id="dropShadow" x="-20%" y="-20%" width="140%" height="140%">
21
+ <feDropShadow dx="2" dy="3" stdDeviation="4" flood-opacity="0.15"/>
22
+ </filter>
23
+ </defs>
24
+
25
+ <!-- Subtle universal background -->
26
+ <defs>
27
+ <radialGradient id="universalBg" cx="50%" cy="50%" r="70%">
28
+ <stop offset="0%" stop-color="#F8FAFC" stop-opacity="0.9"/>
29
+ <stop offset="100%" stop-color="#E2E8F0" stop-opacity="0.7"/>
30
+ </radialGradient>
31
+ </defs>
32
+ <rect width="256" height="256" fill="url(#universalBg)"/>
33
+
34
+ <!-- Stylized collage pieces arranged in a pleasing composition -->
35
+ <path d="M40 60 L110 50 L120 90 L100 120 L60 110 L40 80 Z"
36
+ fill="url(#primaryGrad)"
37
+ filter="url(#dropShadow)"
38
+ opacity="0.9"/>
39
+
40
+ <path d="M140 40 L210 60 L200 100 L180 90 L160 70 L140 60 Z"
41
+ fill="url(#secondaryGrad)"
42
+ filter="url(#dropShadow)"
43
+ opacity="0.85"/>
44
+
45
+ <path d="M30 130 L90 120 L100 160 L80 180 L50 170 L30 150 Z"
46
+ fill="url(#accentGrad)"
47
+ filter="url(#dropShadow)"
48
+ opacity="0.8"/>
49
+
50
+ <path d="M110 150 L190 160 L180 200 L150 210 L120 190 L110 170 Z"
51
+ fill="url(#warningGrad)"
52
+ filter="url(#dropShadow)"
53
+ opacity="0.85"/>
54
+
55
+ <path d="M190 100 L230 120 L220 160 L200 150 L190 130 Z"
56
+ fill="url(#primaryGrad)"
57
+ filter="url(#dropShadow)"
58
+ opacity="0.7"/>
59
+
60
+ <!-- Central focus point -->
61
+ <circle cx="128" cy="128" r="8" fill="url(#secondaryGrad)" opacity="0.8"/>
62
+
63
+ <!-- Clean, modern "JS" -->
64
+ <text x="128" y="145"
65
+ font-family="'SF Pro Display', 'Segoe UI', -apple-system, sans-serif"
66
+ font-size="36"
67
+ font-weight="700"
68
+ text-anchor="middle"
69
+ fill="url(#primaryGrad)">JS</text>
70
70
  </svg>
@@ -1,24 +1,24 @@
1
- declare module "@collagejs/core/logo/16" {
2
- const content: string;
3
- export default content;
4
- }
5
-
6
- declare module "@collagejs/core/logo/48" {
7
- const content: string;
8
- export default content;
9
- }
10
-
11
- declare module "@collagejs/core/logo/64" {
12
- const content: string;
13
- export default content;
14
- }
15
-
16
- declare module "@collagejs/core/logo/128" {
17
- const content: string;
18
- export default content;
19
- }
20
-
21
- declare module "@collagejs/core/logo/512" {
22
- const content: string;
23
- export default content;
24
- }
1
+ declare module "@collagejs/core/logo/16" {
2
+ const content: string;
3
+ export default content;
4
+ }
5
+
6
+ declare module "@collagejs/core/logo/48" {
7
+ const content: string;
8
+ export default content;
9
+ }
10
+
11
+ declare module "@collagejs/core/logo/64" {
12
+ const content: string;
13
+ export default content;
14
+ }
15
+
16
+ declare module "@collagejs/core/logo/128" {
17
+ const content: string;
18
+ export default content;
19
+ }
20
+
21
+ declare module "@collagejs/core/logo/512" {
22
+ const content: string;
23
+ export default content;
24
+ }
@@ -1,10 +1,18 @@
1
1
  import { MountedPiece } from "./MountedPiece.js";
2
- import type { CorePiece } from "./types.js";
3
- export declare function mountPieceCore<TProps extends Record<string, any> = Record<string, any>>(this: MountedPiece | undefined, piece: CorePiece<TProps>, target: HTMLElement, props?: TProps): Promise<MountedPiece<TProps>>;
2
+ import type { CorePiece, MountPiece } from "./types.js";
3
+ /**
4
+ * Constructor type for MountedPiece classes.
5
+ *
6
+ * This exists merely to allow unit testing.
7
+ */
8
+ export interface MountedPieceConstructor {
9
+ new <TProps extends Record<string, any> = Record<string, any>>(piece: CorePiece<TProps>, mountPiece: MountPiece<any>, parent?: MountedPiece<any>): MountedPiece<TProps>;
10
+ }
11
+ export declare function mountPieceCore<TProps extends Record<string, any> = Record<string, any>>(this: MountedPiece | undefined, piece: CorePiece<TProps> | Promise<CorePiece<TProps>>, target: HTMLElement, props?: TProps, MountedPieceClass?: MountedPieceConstructor): Promise<MountedPiece<TProps>>;
4
12
  /**
5
13
  * Mounts the CollageJS piece as a child of the target element.
6
14
  * @param piece The CollageJS piece to mount.
7
15
  * @param target The target element to mount the piece to.
8
16
  * @param props The properties to pass to the piece.
9
17
  */
10
- export declare function mountPiece<TProps extends Record<string, any> = Record<string, any>>(piece: CorePiece<TProps>, target: HTMLElement, props?: TProps): Promise<import("./types.js").MountedPiece<TProps>>;
18
+ export declare function mountPiece<TProps extends Record<string, any> = Record<string, any>>(piece: CorePiece<TProps>, target: HTMLElement, props?: TProps): Promise<MountedPiece<TProps>>;
@@ -1,6 +1,9 @@
1
1
  import { MountedPiece, mountKey } from "./MountedPiece.js";
2
- export async function mountPieceCore(piece, target, props) {
3
- const mp = new MountedPiece(piece, (mountPieceCore), this);
2
+ export async function mountPieceCore(piece, target, props, MountedPieceClass = MountedPiece) {
3
+ if (piece instanceof Promise) {
4
+ piece = await piece;
5
+ }
6
+ const mp = new MountedPieceClass(piece, (mountPieceCore), this);
4
7
  await mp[mountKey](target, props);
5
8
  return mp;
6
9
  }
@@ -11,5 +14,5 @@ export async function mountPieceCore(piece, target, props) {
11
14
  * @param props The properties to pass to the piece.
12
15
  */
13
16
  export function mountPiece(piece, target, props) {
14
- return (mountPieceCore.bind(undefined))(piece, target, props);
17
+ return mountPieceCore.call(undefined, piece, target, props);
15
18
  }
package/dist/types.d.ts CHANGED
@@ -22,4 +22,4 @@ export interface MountedPiece<TProps extends Record<string, any> = Record<string
22
22
  unmount: UnmountFn;
23
23
  mountPiece: MountPiece<TProps>;
24
24
  }
25
- export type MountPiece<TProps extends Record<string, any> = Record<string, any>> = (piece: CorePiece<TProps>, target: HTMLElement, props?: TProps) => Promise<MountedPiece<TProps>>;
25
+ export type MountPiece<TProps extends Record<string, any> = Record<string, any>> = (piece: CorePiece<TProps> | Promise<CorePiece<TProps>>, target: HTMLElement, props?: TProps) => Promise<MountedPiece<TProps>>;
package/package.json CHANGED
@@ -1,11 +1,11 @@
1
1
  {
2
2
  "name": "@collagejs/core",
3
- "version": "0.1.0",
3
+ "version": "0.1.2",
4
4
  "description": "Core functionality for CollageJS.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
7
7
  "scripts": {
8
- "test": "npm run test:unit && npm run test:types",
8
+ "test": "npm run check && npm run test:unit && npm run test:types",
9
9
  "test:unit": "ts-mocha -n loader=ts-node/esm -p ./tsconfig.json --require ./tests/setup.ts ./tests/ut/**/*.test.ts",
10
10
  "test:watch": "ts-mocha -n loader=ts-node/esm -p ./tsconfig.json --require ./tests/setup.ts ./tests/ut/**/*.test.ts --watch",
11
11
  "test:types": "tstyche ./tests/typetests",
@@ -20,10 +20,10 @@
20
20
  ],
21
21
  "repository": {
22
22
  "type": "git",
23
- "url": "git+https://github.com/collagejs/core.git"
23
+ "url": "git+https://github.com/collagejs/collagejs.git"
24
24
  },
25
25
  "bugs": {
26
- "url": "https://github.com/collagejs/core/issues"
26
+ "url": "https://github.com/collagejs/collagejs/issues"
27
27
  },
28
28
  "homepage": "https://collagejs.dev",
29
29
  "author": {