@lolyjs/core 0.3.0-alpha.5 → 0.4.0-alpha.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/README.md +162 -0
- package/dist/{bootstrap-BfGTMUkj.d.mts → bootstrap-B6W6XoI5.d.mts} +6 -0
- package/dist/{bootstrap-BfGTMUkj.d.ts → bootstrap-B6W6XoI5.d.ts} +6 -0
- package/dist/cli.cjs +3362 -867
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.mjs +3442 -952
- package/dist/cli.mjs.map +1 -1
- package/dist/index.cjs +3622 -897
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.mts +27 -1
- package/dist/index.d.ts +27 -1
- package/dist/index.mjs +3598 -879
- package/dist/index.mjs.map +1 -1
- package/dist/react/cache.cjs.map +1 -1
- package/dist/react/cache.mjs.map +1 -1
- package/dist/react/components.cjs +138 -5
- package/dist/react/components.cjs.map +1 -1
- package/dist/react/components.d.mts +58 -6
- package/dist/react/components.d.ts +58 -6
- package/dist/react/components.mjs +138 -6
- package/dist/react/components.mjs.map +1 -1
- package/dist/react/hooks.cjs +24 -0
- package/dist/react/hooks.cjs.map +1 -1
- package/dist/react/hooks.d.mts +49 -1
- package/dist/react/hooks.d.ts +49 -1
- package/dist/react/hooks.mjs +22 -0
- package/dist/react/hooks.mjs.map +1 -1
- package/dist/react/themes.cjs +0 -169
- package/dist/react/themes.cjs.map +1 -1
- package/dist/react/themes.d.mts +18 -11
- package/dist/react/themes.d.ts +18 -11
- package/dist/react/themes.mjs +0 -159
- package/dist/react/themes.mjs.map +1 -1
- package/dist/runtime.cjs +268 -24
- package/dist/runtime.cjs.map +1 -1
- package/dist/runtime.d.mts +2 -2
- package/dist/runtime.d.ts +2 -2
- package/dist/runtime.mjs +255 -15
- package/dist/runtime.mjs.map +1 -1
- package/package.json +4 -2
package/README.md
CHANGED
|
@@ -43,6 +43,7 @@ Loly is a full-stack React framework that combines the simplicity of file-based
|
|
|
43
43
|
- 🛡️ **Security First** - Built-in rate limiting, validation, sanitization, and security headers
|
|
44
44
|
- ⚡ **Performance** - Fast bundling with Rspack and optimized code splitting
|
|
45
45
|
- 📦 **Full ESM Support** - Native ES modules with top-level await, dynamic imports, and `import.meta.url`
|
|
46
|
+
- 🖼️ **Image Optimization** - Automatic image optimization with WebP/AVIF support, lazy loading, and responsive images
|
|
46
47
|
|
|
47
48
|
---
|
|
48
49
|
|
|
@@ -848,6 +849,79 @@ export default {
|
|
|
848
849
|
} satisfies Partial<FrameworkConfig>;
|
|
849
850
|
```
|
|
850
851
|
|
|
852
|
+
### 🖼️ Image Optimization
|
|
853
|
+
|
|
854
|
+
Loly includes a powerful image optimization system similar to Next.js Image, with automatic optimization, lazy loading, responsive images, and remote image support.
|
|
855
|
+
|
|
856
|
+
**Basic Usage:**
|
|
857
|
+
|
|
858
|
+
```tsx
|
|
859
|
+
import { Image } from "@lolyjs/core/components";
|
|
860
|
+
|
|
861
|
+
export default function MyPage() {
|
|
862
|
+
return (
|
|
863
|
+
<Image
|
|
864
|
+
src="/assets/hero.jpg"
|
|
865
|
+
alt="Hero image"
|
|
866
|
+
width={800}
|
|
867
|
+
height={600}
|
|
868
|
+
/>
|
|
869
|
+
);
|
|
870
|
+
}
|
|
871
|
+
```
|
|
872
|
+
|
|
873
|
+
**Remote Images:**
|
|
874
|
+
|
|
875
|
+
```tsx
|
|
876
|
+
<Image
|
|
877
|
+
src="https://images.unsplash.com/photo-123"
|
|
878
|
+
alt="Photo"
|
|
879
|
+
width={1200}
|
|
880
|
+
height={800}
|
|
881
|
+
quality={85}
|
|
882
|
+
format="webp"
|
|
883
|
+
/>
|
|
884
|
+
```
|
|
885
|
+
|
|
886
|
+
**Features:**
|
|
887
|
+
|
|
888
|
+
- ✅ Automatic optimization (resize, compress, format conversion)
|
|
889
|
+
- ✅ Modern formats (WebP, AVIF)
|
|
890
|
+
- ✅ Lazy loading by default
|
|
891
|
+
- ✅ Responsive images with automatic srcset
|
|
892
|
+
- ✅ Remote image support (with domain whitelist)
|
|
893
|
+
- ✅ Cache optimization
|
|
894
|
+
- ✅ CLS prevention
|
|
895
|
+
|
|
896
|
+
**Configuration:**
|
|
897
|
+
|
|
898
|
+
Configure allowed remote domains in `loly.config.ts`:
|
|
899
|
+
|
|
900
|
+
```tsx
|
|
901
|
+
import type { FrameworkConfig } from "@lolyjs/core";
|
|
902
|
+
|
|
903
|
+
export default {
|
|
904
|
+
images: {
|
|
905
|
+
remotePatterns: [
|
|
906
|
+
{
|
|
907
|
+
protocol: "https",
|
|
908
|
+
hostname: "images.unsplash.com",
|
|
909
|
+
},
|
|
910
|
+
{
|
|
911
|
+
protocol: "https",
|
|
912
|
+
hostname: "**.unsplash.com", // Wildcard for subdomains
|
|
913
|
+
},
|
|
914
|
+
],
|
|
915
|
+
formats: ["image/webp", "image/avif"],
|
|
916
|
+
quality: 75,
|
|
917
|
+
deviceSizes: [640, 750, 828, 1080, 1200, 1920, 2048, 3840],
|
|
918
|
+
imageSizes: [16, 32, 48, 64, 96, 128, 256, 384],
|
|
919
|
+
},
|
|
920
|
+
} satisfies Partial<FrameworkConfig>;
|
|
921
|
+
```
|
|
922
|
+
|
|
923
|
+
For complete documentation, see [Image Optimization Documentation](https://github.com/MenvielleValen/loly-framework/blob/main/docs/17-image-optimization.md).
|
|
924
|
+
|
|
851
925
|
### 🔌 API Routes
|
|
852
926
|
|
|
853
927
|
Create RESTful APIs with flexible middleware support:
|
|
@@ -1302,6 +1376,94 @@ export default function Navigation() {
|
|
|
1302
1376
|
}
|
|
1303
1377
|
```
|
|
1304
1378
|
|
|
1379
|
+
### 🎨 Global Theme API
|
|
1380
|
+
|
|
1381
|
+
Loly provides a global theme system that works without React Context, using BroadcastChannel for cross-tab synchronization. The theme is automatically applied to the `<body>` element on the server, and you can update it from anywhere in your application using the global API.
|
|
1382
|
+
|
|
1383
|
+
**Usage:**
|
|
1384
|
+
|
|
1385
|
+
```tsx
|
|
1386
|
+
// In any client component or vanilla JavaScript
|
|
1387
|
+
export default function ThemeSwitch() {
|
|
1388
|
+
const handleToggle = () => {
|
|
1389
|
+
const current = window.loly?.theme?.get() || "light";
|
|
1390
|
+
const next = current === "dark" ? "light" : "dark";
|
|
1391
|
+
window.loly?.theme?.set(next);
|
|
1392
|
+
};
|
|
1393
|
+
|
|
1394
|
+
return <button onClick={handleToggle}>Toggle Theme</button>;
|
|
1395
|
+
}
|
|
1396
|
+
```
|
|
1397
|
+
|
|
1398
|
+
**Reading the theme:**
|
|
1399
|
+
|
|
1400
|
+
```tsx
|
|
1401
|
+
// Get current theme
|
|
1402
|
+
const currentTheme = window.loly?.theme?.get(); // "light" | "dark"
|
|
1403
|
+
|
|
1404
|
+
// Or read from body class (SSR-safe)
|
|
1405
|
+
const themeFromDOM = document.body.classList.contains("dark") ? "dark" : "light";
|
|
1406
|
+
```
|
|
1407
|
+
|
|
1408
|
+
**Server-side theme:**
|
|
1409
|
+
|
|
1410
|
+
The theme is automatically applied to the `<body>` element on the server. You can pass the theme from your layout server hook:
|
|
1411
|
+
|
|
1412
|
+
```tsx
|
|
1413
|
+
// app/layout.server.hook.ts
|
|
1414
|
+
import type { ServerLoader } from "@lolyjs/core";
|
|
1415
|
+
|
|
1416
|
+
export const getServerSideProps: ServerLoader = async (ctx) => {
|
|
1417
|
+
// Get theme from cookie, user preference, etc.
|
|
1418
|
+
const theme = ctx.req.cookies?.theme || "light";
|
|
1419
|
+
|
|
1420
|
+
return {
|
|
1421
|
+
props: {},
|
|
1422
|
+
metadata: {
|
|
1423
|
+
// Theme is automatically applied to body via inline script
|
|
1424
|
+
},
|
|
1425
|
+
};
|
|
1426
|
+
};
|
|
1427
|
+
```
|
|
1428
|
+
|
|
1429
|
+
**Key Features:**
|
|
1430
|
+
|
|
1431
|
+
- ✅ **No React Context required** - Works with server components
|
|
1432
|
+
- ✅ **Cross-tab synchronization** - Uses BroadcastChannel
|
|
1433
|
+
- ✅ **SSR-safe** - Theme applied on server to prevent flash
|
|
1434
|
+
- ✅ **Cookie persistence** - Theme preference saved automatically
|
|
1435
|
+
- ✅ **Simple API** - `window.loly.theme.set()` and `window.loly.theme.get()`
|
|
1436
|
+
|
|
1437
|
+
**React hook example (optional):**
|
|
1438
|
+
|
|
1439
|
+
```tsx
|
|
1440
|
+
import { useEffect, useState } from "react";
|
|
1441
|
+
|
|
1442
|
+
function useTheme() {
|
|
1443
|
+
const [theme, setTheme] = useState<"light" | "dark">(() => {
|
|
1444
|
+
if (typeof window === "undefined") return "light";
|
|
1445
|
+
return window.loly?.theme?.get() || "light";
|
|
1446
|
+
});
|
|
1447
|
+
|
|
1448
|
+
useEffect(() => {
|
|
1449
|
+
const channel = new BroadcastChannel("loly_theme_channel");
|
|
1450
|
+
channel.onmessage = (event) => {
|
|
1451
|
+
if (event.data?.theme) {
|
|
1452
|
+
setTheme(event.data.theme);
|
|
1453
|
+
}
|
|
1454
|
+
};
|
|
1455
|
+
return () => channel.close();
|
|
1456
|
+
}, []);
|
|
1457
|
+
|
|
1458
|
+
const changeTheme = (newTheme: "light" | "dark") => {
|
|
1459
|
+
window.loly?.theme?.set(newTheme);
|
|
1460
|
+
setTheme(newTheme);
|
|
1461
|
+
};
|
|
1462
|
+
|
|
1463
|
+
return { theme, changeTheme };
|
|
1464
|
+
}
|
|
1465
|
+
```
|
|
1466
|
+
|
|
1305
1467
|
---
|
|
1306
1468
|
|
|
1307
1469
|
## Configuration
|
|
@@ -33,6 +33,12 @@ declare global {
|
|
|
33
33
|
type ClientLoadedComponents = {
|
|
34
34
|
Page: React.ComponentType<any>;
|
|
35
35
|
layouts: React.ComponentType<any>[];
|
|
36
|
+
isPageClientComponent?: boolean;
|
|
37
|
+
isLayoutClientComponent?: boolean[];
|
|
38
|
+
clientComponentFilePaths?: {
|
|
39
|
+
page?: string;
|
|
40
|
+
layouts?: (string | undefined)[];
|
|
41
|
+
};
|
|
36
42
|
};
|
|
37
43
|
type ClientRouteLoaded = {
|
|
38
44
|
pattern: string;
|
|
@@ -33,6 +33,12 @@ declare global {
|
|
|
33
33
|
type ClientLoadedComponents = {
|
|
34
34
|
Page: React.ComponentType<any>;
|
|
35
35
|
layouts: React.ComponentType<any>[];
|
|
36
|
+
isPageClientComponent?: boolean;
|
|
37
|
+
isLayoutClientComponent?: boolean[];
|
|
38
|
+
clientComponentFilePaths?: {
|
|
39
|
+
page?: string;
|
|
40
|
+
layouts?: (string | undefined)[];
|
|
41
|
+
};
|
|
36
42
|
};
|
|
37
43
|
type ClientRouteLoaded = {
|
|
38
44
|
pattern: string;
|