@prokodo/ui 0.0.55 β 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/README.md +116 -7
- package/dist/components/image/Image.client.js +39 -0
- package/dist/components/image/Image.js +8 -30
- package/dist/components/image/Image.lazy.js +16 -0
- package/dist/components/image/Image.server.js +88 -0
- package/dist/components/link/Link.client.js +4 -1
- package/dist/components/link/Link.server.js +14 -2
- package/dist/constants/project.js +1 -1
- package/dist/helpers/createIsland.js +11 -20
- package/dist/helpers/runtime.client.js +15 -0
- package/dist/index.js +4 -1
- package/dist/tsconfig.build.tsbuildinfo +1 -1
- package/dist/types/components/image/Image.client.d.ts +4 -0
- package/dist/types/components/image/Image.d.ts +3 -2
- package/dist/types/components/image/Image.lazy.d.ts +5 -0
- package/dist/types/components/image/Image.server.d.ts +4 -0
- package/dist/types/components/link/Link.server.d.ts +1 -1
- package/dist/types/helpers/runtime.client.d.ts +15 -0
- package/dist/types/index.d.ts +1 -0
- package/dist/ui.css +50 -130
- package/package.json +37 -27
package/README.md
CHANGED
|
@@ -8,17 +8,32 @@
|
|
|
8
8
|
|
|
9
9
|
**Modern, customizable UI components built with React and TypeScript β developed by [prokodo](https://www.prokodo.com) for high-performance web interfaces.**
|
|
10
10
|
|
|
11
|
-
> πΊπΈ Need help shipping
|
|
12
|
-
> **prokodo β Next.js
|
|
11
|
+
> πΊπΈ Need help shipping production **Next.js (App Router)** fast?
|
|
12
|
+
> **prokodo β Next.js Agency** β [click here](https://www.prokodo.com/en/next-js-agency/?utm_source=github&utm_medium=readme_top&utm_campaign=ui)
|
|
13
13
|
>
|
|
14
|
-
> π©πͺ Sie suchen eine **Next.js Agentur** (
|
|
15
|
-
> **prokodo β Next.js
|
|
14
|
+
> π©πͺ Sie suchen eine **Next.js Agentur** (App Router, SEO, Performance)?
|
|
15
|
+
> **prokodo β Next.js Agentur** β [hier klicken](https://www.prokodo.com/de/next-js-agentur/?utm_source=github&utm_medium=readme_top&utm_campaign=ui)
|
|
16
|
+
|
|
17
|
+
<details>
|
|
18
|
+
<summary><b>Further reading: Next.js guides</b> (SEO Β· Performance Β· Migration)</summary>
|
|
19
|
+
|
|
20
|
+
- SEO (Metadata API, hreflang):
|
|
21
|
+
https://www.prokodo.com/en/guide/next-js/next-js-seo/?utm_source=github&utm_medium=readme_examples&utm_campaign=ui&utm_content=seo_en
|
|
22
|
+
|
|
23
|
+
- Performance (LCP/INP/CLS, Streaming SSR):
|
|
24
|
+
https://www.prokodo.com/en/guide/next-js/next-js-performance/?utm_source=github&utm_medium=readme_examples&utm_campaign=ui&utm_content=perf_en
|
|
25
|
+
|
|
26
|
+
- Migration Playbook (RACI, Canary, Rollback):
|
|
27
|
+
https://www.prokodo.com/en/guide/next-js/next-js-migration/?utm_source=github&utm_medium=readme_examples&utm_campaign=ui&utm_content=migration_en
|
|
28
|
+
</details>
|
|
16
29
|
|
|
17
30
|
[](https://www.npmjs.com/package/@prokodo/ui)
|
|
18
31
|
[](https://github.com/prokodo-agency/ui/actions/workflows/release.yml)
|
|
19
32
|
[](LICENSE)
|
|
20
33
|
[](https://ui.prokodo.com)
|
|
21
34
|
[](https://bundlephobia.com/result?p=@prokodo/ui)
|
|
35
|
+
[](#)
|
|
36
|
+
[](#)
|
|
22
37
|
|
|
23
38
|
---
|
|
24
39
|
|
|
@@ -31,7 +46,9 @@
|
|
|
31
46
|
- π§ͺ **Reliable**: Fully tested with Jest and Testing Library
|
|
32
47
|
- π **Storybook**: Explore the components at [ui.prokodo.com](https://ui.prokodo.com)
|
|
33
48
|
- π¦ **Ready-to-install**: Distributed via npm for non-production use under the BUSL-1.1 license
|
|
34
|
-
-
|
|
49
|
+
- π **Optimized for Next.js 13β16 out of the box** (App Router, React Server Components)
|
|
50
|
+
- β‘ **Turbopack compatible** (no config required)
|
|
51
|
+
- π **Framework adapters** via `UIRuntimeProvider` for `next/link` & `next/image`
|
|
35
52
|
|
|
36
53
|
## β‘ Lightweight by Design
|
|
37
54
|
|
|
@@ -160,7 +177,7 @@ export default function GalleryPage() {
|
|
|
160
177
|
| Grid/GridRow | β
| β |
|
|
161
178
|
| Headline | β
| - |
|
|
162
179
|
| Icon | β
| β |
|
|
163
|
-
| Image | β
|
|
|
180
|
+
| Image | β
| β
|
|
|
164
181
|
| ImageText | β
| - |
|
|
165
182
|
| Input | β
| β
|
|
|
166
183
|
| Label | β
| β |
|
|
@@ -186,6 +203,80 @@ export default function GalleryPage() {
|
|
|
186
203
|
| Table | β
| β |
|
|
187
204
|
| Teaser | β
| - |
|
|
188
205
|
|
|
206
|
+
## Since Next.js 16
|
|
207
|
+
|
|
208
|
+
- Link/Image runtime provider (required for <Link>/<Image> adapters)
|
|
209
|
+
- For Next.js apps, provide your framework components (next/link, next/image) via a small client provider.
|
|
210
|
+
- Do not pass linkComponent / imageComponent props from pagesβuse the provider instead.
|
|
211
|
+
|
|
212
|
+
### 1. Create a client provider
|
|
213
|
+
|
|
214
|
+
```tsx
|
|
215
|
+
// app/providers/ProkodoUiNextProvider.tsx
|
|
216
|
+
"use client"
|
|
217
|
+
|
|
218
|
+
import NextLink from "next/link"
|
|
219
|
+
import NextImage from "next/image"
|
|
220
|
+
import { UIRuntimeProvider } from "@prokodo/ui/runtime"
|
|
221
|
+
|
|
222
|
+
export function ProkodoUiNextProvider({
|
|
223
|
+
children,
|
|
224
|
+
}: {
|
|
225
|
+
children: React.ReactNode
|
|
226
|
+
}) {
|
|
227
|
+
return (
|
|
228
|
+
<UIRuntimeProvider
|
|
229
|
+
value={{ linkComponent: NextLink, imageComponent: NextImage }}
|
|
230
|
+
>
|
|
231
|
+
{children}
|
|
232
|
+
</UIRuntimeProvider>
|
|
233
|
+
)
|
|
234
|
+
}
|
|
235
|
+
```
|
|
236
|
+
|
|
237
|
+
### 2. Wrap your root layout
|
|
238
|
+
|
|
239
|
+
```tsx
|
|
240
|
+
// app/layout.tsx (server component)
|
|
241
|
+
import { ProkodoUiNextProvider } from "./providers/ProkodoUiNextProvider"
|
|
242
|
+
|
|
243
|
+
export default function RootLayout({
|
|
244
|
+
children,
|
|
245
|
+
}: {
|
|
246
|
+
children: React.ReactNode
|
|
247
|
+
}) {
|
|
248
|
+
return (
|
|
249
|
+
<html lang="en">
|
|
250
|
+
<body>
|
|
251
|
+
<ProkodoUiNextProvider>{children}</ProkodoUiNextProvider>
|
|
252
|
+
</body>
|
|
253
|
+
</html>
|
|
254
|
+
)
|
|
255
|
+
}
|
|
256
|
+
```
|
|
257
|
+
|
|
258
|
+
### 3. Use components normally (no extra props needed)
|
|
259
|
+
|
|
260
|
+
```tsx
|
|
261
|
+
import { Link } from "@prokodo/ui/link"
|
|
262
|
+
import { Image } from "@prokodo/ui/image"
|
|
263
|
+
|
|
264
|
+
export default function Page() {
|
|
265
|
+
return (
|
|
266
|
+
<>
|
|
267
|
+
<Link href="/about">About</Link>
|
|
268
|
+
<Image src="/hero.jpg" alt="Hero" />
|
|
269
|
+
</>
|
|
270
|
+
)
|
|
271
|
+
}
|
|
272
|
+
```
|
|
273
|
+
|
|
274
|
+
**Notes**:
|
|
275
|
+
|
|
276
|
+
- The provider file must be a "use client" module.
|
|
277
|
+
- Remove any linkComponent / imageComponent props you previously passed from server code.
|
|
278
|
+
- Plain React (non-Next) apps donβt need this; just use <a> / <img> or pass your own adapters inside client components.
|
|
279
|
+
|
|
189
280
|
## How to create my own Island Component?
|
|
190
281
|
|
|
191
282
|
### 1. Create your island component (Navbar.tsx):
|
|
@@ -243,11 +334,29 @@ export default createLazyWrapper<NavbarProps>({
|
|
|
243
334
|
|
|
244
335
|
## Examples (Next.js + Headless CMS)
|
|
245
336
|
|
|
337
|
+
Real-world setups we ship:
|
|
338
|
+
|
|
246
339
|
- Next.js + **Strapi** content models
|
|
247
340
|
- Next.js + **Contentful** entries & preview
|
|
248
341
|
- Migration from **Headless WordPress** to Next.js
|
|
249
342
|
|
|
250
|
-
|
|
343
|
+
**Need help or a quick scoping?**
|
|
344
|
+
|
|
345
|
+
- πΊπΈ **Next.js Agency (EN)** β https://www.prokodo.com/en/next-js-agency/?utm_source=github&utm_medium=readme_examples&utm_campaign=ui&utm_content=examples_cta_en
|
|
346
|
+
- π©πͺ **Next.js Agentur (DE)** β https://www.prokodo.com/de/next-js-agentur/?utm_source=github&utm_medium=readme_examples&utm_campaign=ui&utm_content=examples_cta_de
|
|
347
|
+
|
|
348
|
+
<details>
|
|
349
|
+
<summary><b>Further reading: Next.js guides</b> (SEO Β· Performance Β· Migration)</summary>
|
|
350
|
+
|
|
351
|
+
- SEO (Metadata API, hreflang):
|
|
352
|
+
https://www.prokodo.com/en/guide/next-js/next-js-seo/?utm_source=github&utm_medium=readme_examples&utm_campaign=ui&utm_content=seo_en
|
|
353
|
+
|
|
354
|
+
- Performance (LCP/INP/CLS, Streaming SSR):
|
|
355
|
+
https://www.prokodo.com/en/guide/next-js/next-js-performance/?utm_source=github&utm_medium=readme_examples&utm_campaign=ui&utm_content=perf_en
|
|
356
|
+
|
|
357
|
+
- Migration Playbook (RACI, Canary, Rollback):
|
|
358
|
+
https://www.prokodo.com/en/guide/next-js/next-js-migration/?utm_source=github&utm_medium=readme_examples&utm_campaign=ui&utm_content=migration_en
|
|
359
|
+
</details>
|
|
251
360
|
|
|
252
361
|
## π Documentation
|
|
253
362
|
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
|
|
4
|
+
import { jsxs, jsx } from "react/jsx-runtime";
|
|
5
|
+
import { create } from "../../helpers/bem.js";
|
|
6
|
+
import { useUIRuntime } from "../../helpers/runtime.client.js";
|
|
7
|
+
import { isString } from "../../helpers/validations.js";
|
|
8
|
+
import styles from "./Image.module.scss.js";
|
|
9
|
+
const bem = create(styles, "Image");
|
|
10
|
+
const ImageClient = /* @__PURE__ */ __name(({
|
|
11
|
+
alt,
|
|
12
|
+
caption,
|
|
13
|
+
containerClassName,
|
|
14
|
+
captionClassName,
|
|
15
|
+
className,
|
|
16
|
+
imageComponent,
|
|
17
|
+
...props
|
|
18
|
+
}) => {
|
|
19
|
+
const { imageComponent: ctxImage } = useUIRuntime();
|
|
20
|
+
const CustomImage = imageComponent ?? ctxImage ?? "img";
|
|
21
|
+
const renderImage = /* @__PURE__ */ __name(() => /* @__PURE__ */ jsx(
|
|
22
|
+
CustomImage,
|
|
23
|
+
{
|
|
24
|
+
alt: alt ?? "",
|
|
25
|
+
className: bem("image", void 0, className),
|
|
26
|
+
...props
|
|
27
|
+
}
|
|
28
|
+
), "renderImage");
|
|
29
|
+
if (isString(caption)) {
|
|
30
|
+
return /* @__PURE__ */ jsxs("figure", { className: bem(void 0, void 0, containerClassName), children: [
|
|
31
|
+
renderImage(),
|
|
32
|
+
/* @__PURE__ */ jsx("figcaption", { className: bem("caption", void 0, captionClassName), children: caption })
|
|
33
|
+
] });
|
|
34
|
+
}
|
|
35
|
+
return renderImage();
|
|
36
|
+
}, "ImageClient");
|
|
37
|
+
export {
|
|
38
|
+
ImageClient as default
|
|
39
|
+
};
|
|
@@ -1,35 +1,13 @@
|
|
|
1
1
|
var __defProp = Object.defineProperty;
|
|
2
2
|
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
|
|
3
|
-
import {
|
|
4
|
-
import
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
containerClassName,
|
|
12
|
-
captionClassName,
|
|
13
|
-
className,
|
|
14
|
-
imageComponent: CustomImage = "img",
|
|
15
|
-
...props
|
|
16
|
-
}) => {
|
|
17
|
-
const renderImage = /* @__PURE__ */ __name(() => /* @__PURE__ */ jsx(
|
|
18
|
-
CustomImage,
|
|
19
|
-
{
|
|
20
|
-
alt: alt ?? "",
|
|
21
|
-
className: bem("image", void 0, className),
|
|
22
|
-
...props
|
|
23
|
-
}
|
|
24
|
-
), "renderImage");
|
|
25
|
-
if (isString(caption)) {
|
|
26
|
-
return /* @__PURE__ */ jsxs("figure", { className: bem(void 0, void 0, containerClassName), children: [
|
|
27
|
-
renderImage(),
|
|
28
|
-
/* @__PURE__ */ jsx("figcaption", { className: bem("caption", void 0, captionClassName), children: caption })
|
|
29
|
-
] });
|
|
30
|
-
}
|
|
31
|
-
return renderImage();
|
|
32
|
-
}, "Image");
|
|
3
|
+
import { createIsland } from "../../helpers/createIsland.js";
|
|
4
|
+
import ImageServer from "./Image.server.js";
|
|
5
|
+
const Image = createIsland({
|
|
6
|
+
name: "Image",
|
|
7
|
+
Server: ImageServer,
|
|
8
|
+
loadLazy: /* @__PURE__ */ __name(() => import("./Image.lazy.js"), "loadLazy"),
|
|
9
|
+
isInteractive: /* @__PURE__ */ __name((p) => typeof p.imageComponent === "function", "isInteractive")
|
|
10
|
+
});
|
|
33
11
|
export {
|
|
34
12
|
Image
|
|
35
13
|
};
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
|
|
4
|
+
import { createLazyWrapper } from "../../helpers/createLazyWrapper.js";
|
|
5
|
+
import ImageClient from "./Image.client.js";
|
|
6
|
+
import ImageServer from "./Image.server.js";
|
|
7
|
+
const Image_lazy = createLazyWrapper({
|
|
8
|
+
name: "Image",
|
|
9
|
+
Client: ImageClient,
|
|
10
|
+
Server: ImageServer,
|
|
11
|
+
// treat as interactive if a custom image component is a function (e.g. NextImage)
|
|
12
|
+
isInteractive: /* @__PURE__ */ __name((p) => typeof p.imageComponent === "function", "isInteractive")
|
|
13
|
+
});
|
|
14
|
+
export {
|
|
15
|
+
Image_lazy as default
|
|
16
|
+
};
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
var __defProp = Object.defineProperty;
|
|
2
|
+
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
|
|
3
|
+
import { jsxs, jsx } from "react/jsx-runtime";
|
|
4
|
+
import { create } from "../../helpers/bem.js";
|
|
5
|
+
import { isString } from "../../helpers/validations.js";
|
|
6
|
+
import styles from "./Image.module.scss.js";
|
|
7
|
+
const bem = create(styles, "Image");
|
|
8
|
+
function toImgOnlyProps(p) {
|
|
9
|
+
const {
|
|
10
|
+
// Strip next/image-only props so they don't leak onto <img>
|
|
11
|
+
_fill,
|
|
12
|
+
// intentionally unused (name the same to show intent)
|
|
13
|
+
_loader,
|
|
14
|
+
_placeholder,
|
|
15
|
+
_blurDataURL,
|
|
16
|
+
_priority,
|
|
17
|
+
_quality,
|
|
18
|
+
// Note: sizes *is* valid on <img> when it's a string, so we won't strip it
|
|
19
|
+
_onLoadingComplete,
|
|
20
|
+
// our runtime wiring we never want on <img>
|
|
21
|
+
_imageComponent,
|
|
22
|
+
...rest
|
|
23
|
+
} = p;
|
|
24
|
+
let src;
|
|
25
|
+
const rawSrc = rest == null ? void 0 : rest.src;
|
|
26
|
+
if (typeof rawSrc === "string") {
|
|
27
|
+
src = rawSrc;
|
|
28
|
+
} else if (typeof rawSrc === "object" && rawSrc !== null && // explicit property check to satisfy strict-boolean-expressions
|
|
29
|
+
Object.prototype.hasOwnProperty.call(
|
|
30
|
+
rawSrc,
|
|
31
|
+
"src"
|
|
32
|
+
) && typeof rawSrc.src === "string") {
|
|
33
|
+
const rs = rawSrc;
|
|
34
|
+
({ src } = rs);
|
|
35
|
+
} else {
|
|
36
|
+
src = void 0;
|
|
37
|
+
}
|
|
38
|
+
const { width, height } = rest;
|
|
39
|
+
const imgProps = {
|
|
40
|
+
...rest,
|
|
41
|
+
src,
|
|
42
|
+
width,
|
|
43
|
+
height
|
|
44
|
+
};
|
|
45
|
+
return imgProps;
|
|
46
|
+
}
|
|
47
|
+
__name(toImgOnlyProps, "toImgOnlyProps");
|
|
48
|
+
const ImageServer = /* @__PURE__ */ __name(({
|
|
49
|
+
alt,
|
|
50
|
+
caption,
|
|
51
|
+
containerClassName,
|
|
52
|
+
captionClassName,
|
|
53
|
+
className,
|
|
54
|
+
...rawProps
|
|
55
|
+
}) => {
|
|
56
|
+
if (process.env.NODE_ENV !== "production" && typeof rawProps.imageComponent === "function") {
|
|
57
|
+
console.error(
|
|
58
|
+
"[UI] Do not pass function props (imageComponent) to <Image> on the server. Use UIRuntimeProvider in the parent app instead.",
|
|
59
|
+
rawProps
|
|
60
|
+
);
|
|
61
|
+
}
|
|
62
|
+
const {
|
|
63
|
+
imageComponent: _dropImageComponent,
|
|
64
|
+
onClick: _dropClick,
|
|
65
|
+
onKeyDown: _dropKey,
|
|
66
|
+
...rest
|
|
67
|
+
} = rawProps;
|
|
68
|
+
const CustomImage = "img";
|
|
69
|
+
const imgProps = toImgOnlyProps(rest);
|
|
70
|
+
const renderImage = /* @__PURE__ */ __name(() => /* @__PURE__ */ jsx(
|
|
71
|
+
CustomImage,
|
|
72
|
+
{
|
|
73
|
+
alt: alt ?? "",
|
|
74
|
+
className: bem("image", void 0, className),
|
|
75
|
+
...imgProps
|
|
76
|
+
}
|
|
77
|
+
), "renderImage");
|
|
78
|
+
if (isString(caption)) {
|
|
79
|
+
return /* @__PURE__ */ jsxs("figure", { className: bem(void 0, void 0, containerClassName), children: [
|
|
80
|
+
renderImage(),
|
|
81
|
+
/* @__PURE__ */ jsx("figcaption", { className: bem("caption", void 0, captionClassName), children: caption })
|
|
82
|
+
] });
|
|
83
|
+
}
|
|
84
|
+
return renderImage();
|
|
85
|
+
}, "ImageServer");
|
|
86
|
+
export {
|
|
87
|
+
ImageServer as default
|
|
88
|
+
};
|
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { jsx } from "react/jsx-runtime";
|
|
3
3
|
import { memo } from "react";
|
|
4
|
+
import { useUIRuntime } from "../../helpers/runtime.client.js";
|
|
4
5
|
import BaseLinkServer from "../base-link/BaseLink.server.js";
|
|
5
6
|
import { LinkView } from "./Link.view.js";
|
|
6
7
|
const LinkClient = memo((props) => {
|
|
7
8
|
const { href, onClick } = props;
|
|
9
|
+
const { linkComponent: ctxLink } = useUIRuntime();
|
|
8
10
|
const linkTag = onClick && !href ? "span" : "a";
|
|
9
11
|
const hasHandlers = Boolean(onClick) || Boolean(props.onKeyDown);
|
|
10
12
|
return /* @__PURE__ */ jsx(
|
|
@@ -13,7 +15,8 @@ const LinkClient = memo((props) => {
|
|
|
13
15
|
...props,
|
|
14
16
|
BaseLinkComponent: BaseLinkServer,
|
|
15
17
|
hasHandlers,
|
|
16
|
-
LinkTag: linkTag
|
|
18
|
+
LinkTag: linkTag,
|
|
19
|
+
...ctxLink ? { linkComponent: ctxLink } : null
|
|
17
20
|
}
|
|
18
21
|
);
|
|
19
22
|
});
|
|
@@ -3,9 +3,21 @@ var __name = (target, value) => __defProp(target, "name", { value, configurable:
|
|
|
3
3
|
import { jsx } from "react/jsx-runtime";
|
|
4
4
|
import BaseLinkServer from "../base-link/BaseLink.server.js";
|
|
5
5
|
import { LinkView } from "./Link.view.js";
|
|
6
|
-
function LinkServer(
|
|
6
|
+
function LinkServer(rawProps) {
|
|
7
|
+
if (process.env.NODE_ENV !== "production" && typeof (rawProps == null ? void 0 : rawProps.linkComponent) === "function") {
|
|
8
|
+
console.error(
|
|
9
|
+
"[UI] Do not pass function props (linkComponent) to <Link> on the server. Use the UIRuntimeProvider in the parent app instead.",
|
|
10
|
+
rawProps
|
|
11
|
+
);
|
|
12
|
+
}
|
|
13
|
+
const {
|
|
14
|
+
onClick,
|
|
15
|
+
onKeyDown: _onKeyDown,
|
|
16
|
+
linkComponent: _drop,
|
|
17
|
+
...props
|
|
18
|
+
} = rawProps;
|
|
7
19
|
const hasHandlers = false;
|
|
8
|
-
const linkTag =
|
|
20
|
+
const linkTag = onClick && !(props == null ? void 0 : props.href) ? "span" : "a";
|
|
9
21
|
return /* @__PURE__ */ jsx(
|
|
10
22
|
LinkView,
|
|
11
23
|
{
|
|
@@ -2,6 +2,12 @@ var __defProp = Object.defineProperty;
|
|
|
2
2
|
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
|
|
3
3
|
import { jsx } from "react/jsx-runtime";
|
|
4
4
|
import { lazy, Suspense, cloneElement } from "react";
|
|
5
|
+
function stripFnProps(p) {
|
|
6
|
+
return Object.fromEntries(
|
|
7
|
+
Object.entries(p).filter(([, v]) => typeof v !== "function")
|
|
8
|
+
);
|
|
9
|
+
}
|
|
10
|
+
__name(stripFnProps, "stripFnProps");
|
|
5
11
|
function createIsland({
|
|
6
12
|
name,
|
|
7
13
|
Server,
|
|
@@ -13,40 +19,25 @@ function createIsland({
|
|
|
13
19
|
void loadLazy();
|
|
14
20
|
}
|
|
15
21
|
function withIslandAttr(el, priority) {
|
|
16
|
-
var _a;
|
|
17
22
|
const islandName = name.toLowerCase();
|
|
18
|
-
if (typeof process !== "undefined" && typeof ((_a = process == null ? void 0 : process.env) == null ? void 0 : _a.PK_ENABLE_DEBUG_LOGS) === "string") {
|
|
19
|
-
console.debug(
|
|
20
|
-
`[hydrate] createIsland β${name}β rendering as interactive=${Boolean(
|
|
21
|
-
priority
|
|
22
|
-
)}`
|
|
23
|
-
);
|
|
24
|
-
}
|
|
25
23
|
const extra = {
|
|
26
24
|
"data-island": islandName
|
|
27
25
|
};
|
|
28
|
-
if (Boolean(priority))
|
|
29
|
-
extra.priority = priority;
|
|
30
|
-
}
|
|
26
|
+
if (Boolean(priority)) extra.priority = true;
|
|
31
27
|
return cloneElement(el, extra);
|
|
32
28
|
}
|
|
33
29
|
__name(withIslandAttr, "withIslandAttr");
|
|
34
|
-
const Island = /* @__PURE__ */ __name(({
|
|
35
|
-
priority = false,
|
|
36
|
-
...raw
|
|
37
|
-
}) => {
|
|
30
|
+
const Island = /* @__PURE__ */ __name(({ ...raw }) => {
|
|
38
31
|
const props = raw;
|
|
39
32
|
const autoInteractive = Object.entries(props).some(
|
|
40
33
|
([k, v]) => k.startsWith("on") && typeof v === "function"
|
|
41
34
|
) || props.redirect !== void 0;
|
|
42
35
|
const interactive = customInteractive ? customInteractive(props) || autoInteractive : autoInteractive;
|
|
43
|
-
|
|
44
|
-
return withIslandAttr(/* @__PURE__ */ jsx(LazyComp, { ...props }));
|
|
45
|
-
}
|
|
36
|
+
const serverSafe = stripFnProps(props);
|
|
46
37
|
if (!interactive) {
|
|
47
|
-
return withIslandAttr(/* @__PURE__ */ jsx(Server, { ...
|
|
38
|
+
return withIslandAttr(/* @__PURE__ */ jsx(Server, { ...serverSafe }));
|
|
48
39
|
}
|
|
49
|
-
const fallback = withIslandAttr(/* @__PURE__ */ jsx(Server, { ...
|
|
40
|
+
const fallback = withIslandAttr(/* @__PURE__ */ jsx(Server, { ...serverSafe }));
|
|
50
41
|
return /* @__PURE__ */ jsx(Suspense, { fallback, children: withIslandAttr(/* @__PURE__ */ jsx(LazyComp, { ...props })) });
|
|
51
42
|
}, "Island");
|
|
52
43
|
Island.displayName = `${name}Island`;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
|
|
4
|
+
import { jsx } from "react/jsx-runtime";
|
|
5
|
+
import { useContext, createContext } from "react";
|
|
6
|
+
const UIRuntimeContext = createContext({});
|
|
7
|
+
const UIRuntimeProvider = /* @__PURE__ */ __name(({
|
|
8
|
+
value,
|
|
9
|
+
children
|
|
10
|
+
}) => /* @__PURE__ */ jsx(UIRuntimeContext.Provider, { value, children }), "UIRuntimeProvider");
|
|
11
|
+
const useUIRuntime = /* @__PURE__ */ __name(() => useContext(UIRuntimeContext), "useUIRuntime");
|
|
12
|
+
export {
|
|
13
|
+
UIRuntimeProvider,
|
|
14
|
+
useUIRuntime
|
|
15
|
+
};
|
package/dist/index.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { UIRuntimeProvider, useUIRuntime } from "./helpers/runtime.client.js";
|
|
1
2
|
import { Accordion } from "./components/accordion/Accordion.js";
|
|
2
3
|
import { Animated } from "./components/animated/Animated.js";
|
|
3
4
|
import { AnimatedText } from "./components/animatedText/AnimatedText.js";
|
|
@@ -90,5 +91,7 @@ export {
|
|
|
90
91
|
Stepper,
|
|
91
92
|
Switch,
|
|
92
93
|
Table,
|
|
93
|
-
Teaser
|
|
94
|
+
Teaser,
|
|
95
|
+
UIRuntimeProvider,
|
|
96
|
+
useUIRuntime
|
|
94
97
|
};
|