@valbuild/next 0.66.0 → 0.67.1
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
CHANGED
|
@@ -50,7 +50,7 @@ This version of Val is currently an alpha version - the API can be considered re
|
|
|
50
50
|
- [String](#string)
|
|
51
51
|
- [Number](#number)
|
|
52
52
|
- [Boolean](#boolean)
|
|
53
|
-
- [
|
|
53
|
+
- [Nullable](#nullable)
|
|
54
54
|
- [Array](#array)
|
|
55
55
|
- [Record](#record)
|
|
56
56
|
- [Object](#object)
|
|
@@ -60,7 +60,7 @@ This version of Val is currently an alpha version - the API can be considered re
|
|
|
60
60
|
|
|
61
61
|
## Installation
|
|
62
62
|
|
|
63
|
-
- Make sure you have TypeScript 5+, Next
|
|
63
|
+
- Make sure you have TypeScript 5+, Next 14+, React 18.20.+
|
|
64
64
|
- Install the packages (@valbuild/eslint-plugin is recommended but not required):
|
|
65
65
|
|
|
66
66
|
```sh
|
|
@@ -73,146 +73,136 @@ npm install @valbuild/core@latest @valbuild/next@latest @valbuild/eslint-plugin@
|
|
|
73
73
|
npx @valbuild/init@latest
|
|
74
74
|
```
|
|
75
75
|
|
|
76
|
-
|
|
76
|
+
**NOTE** if your Next.js project is using
|
|
77
77
|
|
|
78
|
-
|
|
78
|
+
## Getting started
|
|
79
79
|
|
|
80
|
-
|
|
80
|
+
### Create your first Val content file
|
|
81
81
|
|
|
82
|
-
|
|
82
|
+
Content in Val is always defined in `.val.ts` (or `.js`) files.
|
|
83
83
|
|
|
84
|
-
**
|
|
84
|
+
**NOTE**: the init script will generate an example Val content file (unless you opt out of it).
|
|
85
85
|
|
|
86
|
-
|
|
86
|
+
Val content files are _evaluated_ by Val, therefore they have a specific set of requirements:
|
|
87
87
|
|
|
88
|
-
|
|
88
|
+
- they must export a default content definition (`c.define`) where the first argument equals the path of the file relative to the `val.config.ts` file; and
|
|
89
|
+
- they must have a default export that is `c.define; and
|
|
90
|
+
- they can only import Val related files and / or types
|
|
89
91
|
|
|
90
|
-
|
|
92
|
+
If you use the eslint plugins these requirements will be enforced. You can also validate val files using the @valbuild/cli: `npx -p @valbuild/cli val validate --fix`
|
|
91
93
|
|
|
92
|
-
|
|
93
|
-
- `VAL_SECRET`: this is a random secret you can generate. It is used for communication between the UX client and your Next.js application.
|
|
94
|
+
### Adding Val content file to val.modules
|
|
94
95
|
|
|
95
|
-
|
|
96
|
+
Once you have created your Val content file, it must be declared in the `val.modules.ts` (or `.js`) file.
|
|
96
97
|
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
98
|
+
Example:
|
|
99
|
+
|
|
100
|
+
```ts
|
|
101
|
+
import { modules } from "@valbuild/next";
|
|
102
|
+
import { config } from "./val.config";
|
|
100
103
|
|
|
101
|
-
|
|
104
|
+
export default modules(config, [
|
|
105
|
+
// Add your modules here
|
|
106
|
+
{ def: () => import("./examples/val/example.val") },
|
|
107
|
+
]);
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
### Example of a `.val.ts` file
|
|
102
111
|
|
|
103
112
|
```ts
|
|
104
|
-
|
|
113
|
+
// ./examples/val/example.val.ts
|
|
114
|
+
import { s /* s = schema */, c /* c = content */ } from "../../val.config";
|
|
105
115
|
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
116
|
+
/**
|
|
117
|
+
* This is the schema for the content. It defines the structure of the content and the types of each field.
|
|
118
|
+
*/
|
|
119
|
+
export const schema = s.object({
|
|
120
|
+
/**
|
|
121
|
+
* Basic text field
|
|
122
|
+
*/
|
|
123
|
+
text: s.string(),
|
|
110
124
|
});
|
|
111
125
|
|
|
112
|
-
|
|
113
|
-
|
|
126
|
+
/**
|
|
127
|
+
* This is the content definition. Add your content below.
|
|
128
|
+
*
|
|
129
|
+
* NOTE: the first argument is the path of the file.
|
|
130
|
+
*/
|
|
131
|
+
export default c.define("/examples/val/example.val.ts", schema, {
|
|
132
|
+
text: "Basic text content",
|
|
133
|
+
});
|
|
114
134
|
```
|
|
115
135
|
|
|
116
|
-
|
|
136
|
+
### Using Val in Client Components
|
|
117
137
|
|
|
118
|
-
|
|
138
|
+
In client components you can access your content with the `useVal` hook:
|
|
119
139
|
|
|
120
|
-
|
|
140
|
+
```tsx
|
|
141
|
+
// ./app/page.tsx
|
|
142
|
+
"use client";
|
|
143
|
+
import { useVal } from "../val/val.client";
|
|
144
|
+
import exampleVal from "../examples/val/example.val";
|
|
121
145
|
|
|
122
|
-
|
|
146
|
+
export default function Home() {
|
|
147
|
+
const { text } = useVal(exampleVal);
|
|
148
|
+
return <main>{text}</main>;
|
|
149
|
+
}
|
|
150
|
+
```
|
|
123
151
|
|
|
124
|
-
|
|
152
|
+
### Using Val in React Server Components
|
|
125
153
|
|
|
126
|
-
|
|
154
|
+
In React Server components you can access your content with the `fetchVal` function:
|
|
127
155
|
|
|
128
|
-
|
|
129
|
-
|
|
156
|
+
```tsx
|
|
157
|
+
// ./app/page.tsx
|
|
158
|
+
"use server";
|
|
159
|
+
import { fetchVal } from "../val/val.rsc";
|
|
160
|
+
import exampleVal from "../examples/val/example.val";
|
|
161
|
+
|
|
162
|
+
export default async function Home() {
|
|
163
|
+
const { text } = await fetchVal(exampleVal);
|
|
164
|
+
return <main>{text}</main>;
|
|
165
|
+
}
|
|
166
|
+
```
|
|
130
167
|
|
|
131
|
-
|
|
168
|
+
# Remote Mode
|
|
132
169
|
|
|
133
|
-
|
|
134
|
-
// ./src/app/content.val.ts
|
|
170
|
+
Enable remote mode to allow editors to update content online (outside of local development) by creating a project at [app.val.build](https://app.val.build).
|
|
135
171
|
|
|
136
|
-
|
|
172
|
+
**NOTE**: Your content remains yours. Hosting content from your repository does not require a subscription. However, to edit content online, a subscription is needed — unless your project is a public repository or qualifies for the free tier. Visit the [pricing page](https://val.build/pricing) for details.
|
|
137
173
|
|
|
138
|
-
|
|
139
|
-
title: s.string().optional(), // <- NOTE: optional()
|
|
140
|
-
sections: s.array(
|
|
141
|
-
s.object({
|
|
142
|
-
title: s.string(),
|
|
143
|
-
text: s.richtext({
|
|
144
|
-
style: {
|
|
145
|
-
bold: true, // <- Enables bold in richtext
|
|
146
|
-
},
|
|
147
|
-
}),
|
|
148
|
-
}),
|
|
149
|
-
),
|
|
150
|
-
});
|
|
174
|
+
**WHY**: Updating code involves creating a commit, which requires a server. We offer a hosted service for simplicity and efficiency, as self-hosted solutions takes time to setup and maintain. Additionally, the [val.build](https://val.build) team funds the ongoing development of this library.
|
|
151
175
|
|
|
152
|
-
|
|
153
|
-
"/src/app/content", // <- NOTE: this must be the same path as the file
|
|
154
|
-
schema,
|
|
155
|
-
{
|
|
156
|
-
title: "My Page",
|
|
157
|
-
sections: [
|
|
158
|
-
{
|
|
159
|
-
title: "Section 1",
|
|
160
|
-
text: [
|
|
161
|
-
{
|
|
162
|
-
tag: "p",
|
|
163
|
-
children: [
|
|
164
|
-
"Val is",
|
|
165
|
-
{ tag: "span", styles: ["bold"], children: ["awesome"] },
|
|
166
|
-
],
|
|
167
|
-
},
|
|
168
|
-
],
|
|
169
|
-
},
|
|
170
|
-
],
|
|
171
|
-
},
|
|
172
|
-
);
|
|
173
|
-
```
|
|
176
|
+
## Remote Mode Configuration
|
|
174
177
|
|
|
175
|
-
|
|
178
|
+
Once your project is set up in [app.val.build](https://app.val.build), configure your application to use it by setting the following:
|
|
176
179
|
|
|
177
|
-
|
|
180
|
+
### Environment Variables
|
|
178
181
|
|
|
179
|
-
|
|
182
|
+
- **`VAL_API_KEY`**: Obtain this from your project's configuration page.
|
|
183
|
+
- **`VAL_SECRET`**: Generate a random secret to secure communication between the UX client and your Next.js application.
|
|
180
184
|
|
|
181
|
-
|
|
182
|
-
// ./src/app/page.tsx
|
|
183
|
-
"use client";
|
|
184
|
-
import { NextPage } from "next";
|
|
185
|
-
import { useVal } from "./val/val.client";
|
|
186
|
-
import contentVal from "./content.val";
|
|
185
|
+
### `val.config` Properties
|
|
187
186
|
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
<section>
|
|
199
|
-
<h2>{section.title}</h2>
|
|
200
|
-
<ValRichText
|
|
201
|
-
theme={{
|
|
202
|
-
style: {
|
|
203
|
-
bold: "font-bold",
|
|
204
|
-
},
|
|
205
|
-
}}
|
|
206
|
-
>
|
|
207
|
-
{section.text}
|
|
208
|
-
</ValRichText>
|
|
209
|
-
</section>
|
|
210
|
-
))}
|
|
211
|
-
</main>
|
|
212
|
-
);
|
|
213
|
-
};
|
|
187
|
+
Set these properties in the `val.config` file:
|
|
188
|
+
|
|
189
|
+
- **`project`**: The fully qualified name of your project, formatted as `<team>/<name>`.
|
|
190
|
+
- **`gitBranch`**: The Git branch your application uses. For Vercel, use `VERCEL_GIT_COMMIT_REF`.
|
|
191
|
+
- **`gitCommit`**: The current Git commit your application is running on. For Vercel, use `VERCEL_GIT_COMMIT_SHA`.
|
|
192
|
+
|
|
193
|
+
### Example `val.config.ts`
|
|
194
|
+
|
|
195
|
+
```ts
|
|
196
|
+
import { initVal } from "@valbuild/next";
|
|
214
197
|
|
|
215
|
-
|
|
198
|
+
const { s, c, val, config } = initVal({
|
|
199
|
+
project: "myteam/myproject",
|
|
200
|
+
gitBranch: process.env.VERCEL_GIT_COMMIT_REF,
|
|
201
|
+
gitCommit: process.env.VERCEL_GIT_COMMIT_SHA,
|
|
202
|
+
});
|
|
203
|
+
|
|
204
|
+
export type { t } from "@valbuild/next";
|
|
205
|
+
export { s, c, val, config };
|
|
216
206
|
```
|
|
217
207
|
|
|
218
208
|
# Schema types
|
|
@@ -241,14 +231,14 @@ import { s } from "./val.config";
|
|
|
241
231
|
s.boolean(); // <- Schema<boolean>
|
|
242
232
|
```
|
|
243
233
|
|
|
244
|
-
##
|
|
234
|
+
## Nullable
|
|
245
235
|
|
|
246
|
-
All schema types can be optional.
|
|
236
|
+
All schema types can be nullable (optional). A nullable schema creates a union of the type and `null`.
|
|
247
237
|
|
|
248
238
|
```ts
|
|
249
239
|
import { s } from "./val.config";
|
|
250
240
|
|
|
251
|
-
s.string().
|
|
241
|
+
s.string().nullable(); // <- Schema<string | null>
|
|
252
242
|
```
|
|
253
243
|
|
|
254
244
|
## Array
|
|
@@ -384,7 +374,7 @@ To add classes to `ValRichText` you can use the theme property:
|
|
|
384
374
|
</ValRichText>
|
|
385
375
|
```
|
|
386
376
|
|
|
387
|
-
**NOTE**: if a theme is defined, you must define a mapping for every tag that the you get. What tags you have is decided based on the `options` defined on the `s.richtext()` schema. For example: `s.richtext({
|
|
377
|
+
**NOTE**: if a theme is defined, you must define a mapping for every tag that the you get. What tags you have is decided based on the `options` defined on the `s.richtext()` schema. For example: `s.richtext({ style: { bold: true } })` requires that you add a `bold` theme.
|
|
388
378
|
|
|
389
379
|
```tsx
|
|
390
380
|
<ValRichText
|
|
@@ -394,7 +384,7 @@ To add classes to `ValRichText` you can use the theme property:
|
|
|
394
384
|
img: null, // either a string or null is required
|
|
395
385
|
}}
|
|
396
386
|
>
|
|
397
|
-
{content
|
|
387
|
+
{content}
|
|
398
388
|
</ValRichText>
|
|
399
389
|
```
|
|
400
390
|
|
|
@@ -404,7 +394,7 @@ To add classes to `ValRichText` you can use the theme property:
|
|
|
404
394
|
|
|
405
395
|
Vals `RichText` type maps RichText 1-to-1 with semantic HTML5.
|
|
406
396
|
|
|
407
|
-
If you want to customize the type of elements which are rendered, you can use the `transform` property.
|
|
397
|
+
If you want to customize / override the type of elements which are rendered, you can use the `transform` property.
|
|
408
398
|
|
|
409
399
|
```tsx
|
|
410
400
|
<ValRichText
|
|
@@ -506,14 +496,14 @@ s.image();
|
|
|
506
496
|
|
|
507
497
|
### Initializing image content
|
|
508
498
|
|
|
509
|
-
Local images must be stored under the
|
|
499
|
+
Local images must be stored under the `/public/val` folder.
|
|
510
500
|
|
|
511
501
|
```ts
|
|
512
502
|
import { s, c } from "../val.config";
|
|
513
503
|
|
|
514
504
|
export const schema = s.image();
|
|
515
505
|
|
|
516
|
-
export default c.define("/image", schema, c.
|
|
506
|
+
export default c.define("/image", schema, c.image("/public/myfile.jpg"));
|
|
517
507
|
```
|
|
518
508
|
|
|
519
509
|
**NOTE**: This will not validate, since images requires `width`, `height` and `mimeType`. You can fix validation errors like this by using the CLI or by using the VS Code plugin.
|
|
@@ -525,9 +515,9 @@ The `ValImage` component is a wrapper around `next/image` that accepts a Val `Im
|
|
|
525
515
|
You can use it like this:
|
|
526
516
|
|
|
527
517
|
```tsx
|
|
528
|
-
const content = useVal(contentVal);
|
|
518
|
+
const content = useVal(contentVal); // schema of contentVal: s.object({ image: s.image() })
|
|
529
519
|
|
|
530
|
-
return <ValImage src={content.image}
|
|
520
|
+
return <ValImage src={content.image} />;
|
|
531
521
|
```
|
|
532
522
|
|
|
533
523
|
### Using images in components
|
|
@@ -585,7 +575,22 @@ s.union(
|
|
|
585
575
|
|
|
586
576
|
## KeyOf
|
|
587
577
|
|
|
588
|
-
|
|
578
|
+
You can use `keyOf` to reference a key in a record of a Val module.
|
|
579
|
+
|
|
580
|
+
**NOTE**: currently you must reference keys in Val modules, you cannot reference keys of values nested inside a Val module. This is a feature on the roadmap.
|
|
581
|
+
|
|
582
|
+
```ts
|
|
583
|
+
const schema = s.record(s.object({ nested: s.record(s.string()) }));
|
|
584
|
+
|
|
585
|
+
export default c.define("/keyof.val.ts", schema, {
|
|
586
|
+
"you-can-reference-me": {
|
|
587
|
+
// <- this can be referenced
|
|
588
|
+
nested: {
|
|
589
|
+
"but-not-me": ":(", // <- this cannot be referenced
|
|
590
|
+
},
|
|
591
|
+
},
|
|
592
|
+
});
|
|
593
|
+
```
|
|
589
594
|
|
|
590
595
|
### KeyOf Schema
|
|
591
596
|
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import NextImage from "next/image";
|
|
2
2
|
import { Image } from "@valbuild/react/stega";
|
|
3
|
-
export type ValImageProps = Omit<React.ComponentProps<typeof NextImage>, "src" | "srcset" | "layout" | "objectFit" | "objectPosition" | "lazyBoundary" | "lazyRoot"> & {
|
|
3
|
+
export type ValImageProps = Omit<React.ComponentProps<typeof NextImage>, "src" | "alt" | "srcset" | "layout" | "objectFit" | "objectPosition" | "lazyBoundary" | "lazyRoot"> & {
|
|
4
|
+
alt?: string;
|
|
4
5
|
src: Image;
|
|
5
6
|
disableHotspot?: boolean;
|
|
6
7
|
};
|
|
@@ -118,7 +118,7 @@ function _objectWithoutProperties(e, t) {
|
|
|
118
118
|
|
|
119
119
|
var _excluded = ["src", "alt", "style", "width", "disableHotspot", "height"];
|
|
120
120
|
function ValImage(props) {
|
|
121
|
-
var _src$metadata, _src$metadata2, _src$metadata3, _src$metadata4;
|
|
121
|
+
var _src$metadata, _src$metadata2, _src$metadata3, _src$metadata4, _src$metadata5, _src$metadata6;
|
|
122
122
|
var src = props.src,
|
|
123
123
|
alt = props.alt,
|
|
124
124
|
style = props.style,
|
|
@@ -150,10 +150,10 @@ function ValImage(props) {
|
|
|
150
150
|
"data-val-attr-alt": maybeValPathOfAlt,
|
|
151
151
|
"data-val-attr-src": valPathOfUrl,
|
|
152
152
|
style: imageStyle,
|
|
153
|
-
alt: raw(alt),
|
|
153
|
+
alt: alt ? raw(alt) : (_src$metadata3 = src.metadata) !== null && _src$metadata3 !== void 0 && _src$metadata3.alt ? raw((_src$metadata4 = src.metadata) === null || _src$metadata4 === void 0 ? void 0 : _src$metadata4.alt) : "",
|
|
154
154
|
fill: rest.fill,
|
|
155
|
-
width: preferMetadataDims ? (_src$
|
|
156
|
-
height: preferMetadataDims ? (_src$
|
|
155
|
+
width: preferMetadataDims ? (_src$metadata5 = src.metadata) === null || _src$metadata5 === void 0 ? void 0 : _src$metadata5.width : width,
|
|
156
|
+
height: preferMetadataDims ? (_src$metadata6 = src.metadata) === null || _src$metadata6 === void 0 ? void 0 : _src$metadata6.height : height,
|
|
157
157
|
unoptimized: isUnoptimized
|
|
158
158
|
}));
|
|
159
159
|
}
|
|
@@ -118,7 +118,7 @@ function _objectWithoutProperties(e, t) {
|
|
|
118
118
|
|
|
119
119
|
var _excluded = ["src", "alt", "style", "width", "disableHotspot", "height"];
|
|
120
120
|
function ValImage(props) {
|
|
121
|
-
var _src$metadata, _src$metadata2, _src$metadata3, _src$metadata4;
|
|
121
|
+
var _src$metadata, _src$metadata2, _src$metadata3, _src$metadata4, _src$metadata5, _src$metadata6;
|
|
122
122
|
var src = props.src,
|
|
123
123
|
alt = props.alt,
|
|
124
124
|
style = props.style,
|
|
@@ -150,10 +150,10 @@ function ValImage(props) {
|
|
|
150
150
|
"data-val-attr-alt": maybeValPathOfAlt,
|
|
151
151
|
"data-val-attr-src": valPathOfUrl,
|
|
152
152
|
style: imageStyle,
|
|
153
|
-
alt: raw(alt),
|
|
153
|
+
alt: alt ? raw(alt) : (_src$metadata3 = src.metadata) !== null && _src$metadata3 !== void 0 && _src$metadata3.alt ? raw((_src$metadata4 = src.metadata) === null || _src$metadata4 === void 0 ? void 0 : _src$metadata4.alt) : "",
|
|
154
154
|
fill: rest.fill,
|
|
155
|
-
width: preferMetadataDims ? (_src$
|
|
156
|
-
height: preferMetadataDims ? (_src$
|
|
155
|
+
width: preferMetadataDims ? (_src$metadata5 = src.metadata) === null || _src$metadata5 === void 0 ? void 0 : _src$metadata5.width : width,
|
|
156
|
+
height: preferMetadataDims ? (_src$metadata6 = src.metadata) === null || _src$metadata6 === void 0 ? void 0 : _src$metadata6.height : height,
|
|
157
157
|
unoptimized: isUnoptimized
|
|
158
158
|
}));
|
|
159
159
|
}
|
|
@@ -94,7 +94,7 @@ function _objectWithoutProperties(e, t) {
|
|
|
94
94
|
|
|
95
95
|
var _excluded = ["src", "alt", "style", "width", "disableHotspot", "height"];
|
|
96
96
|
function ValImage(props) {
|
|
97
|
-
var _src$metadata, _src$metadata2, _src$metadata3, _src$metadata4;
|
|
97
|
+
var _src$metadata, _src$metadata2, _src$metadata3, _src$metadata4, _src$metadata5, _src$metadata6;
|
|
98
98
|
var src = props.src,
|
|
99
99
|
alt = props.alt,
|
|
100
100
|
style = props.style,
|
|
@@ -126,10 +126,10 @@ function ValImage(props) {
|
|
|
126
126
|
"data-val-attr-alt": maybeValPathOfAlt,
|
|
127
127
|
"data-val-attr-src": valPathOfUrl,
|
|
128
128
|
style: imageStyle,
|
|
129
|
-
alt: raw(alt),
|
|
129
|
+
alt: alt ? raw(alt) : (_src$metadata3 = src.metadata) !== null && _src$metadata3 !== void 0 && _src$metadata3.alt ? raw((_src$metadata4 = src.metadata) === null || _src$metadata4 === void 0 ? void 0 : _src$metadata4.alt) : "",
|
|
130
130
|
fill: rest.fill,
|
|
131
|
-
width: preferMetadataDims ? (_src$
|
|
132
|
-
height: preferMetadataDims ? (_src$
|
|
131
|
+
width: preferMetadataDims ? (_src$metadata5 = src.metadata) === null || _src$metadata5 === void 0 ? void 0 : _src$metadata5.width : width,
|
|
132
|
+
height: preferMetadataDims ? (_src$metadata6 = src.metadata) === null || _src$metadata6 === void 0 ? void 0 : _src$metadata6.height : height,
|
|
133
133
|
unoptimized: isUnoptimized
|
|
134
134
|
}));
|
|
135
135
|
}
|
package/package.json
CHANGED
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
"next",
|
|
9
9
|
"react"
|
|
10
10
|
],
|
|
11
|
-
"version": "0.
|
|
11
|
+
"version": "0.67.1",
|
|
12
12
|
"scripts": {
|
|
13
13
|
"typecheck": "tsc --noEmit",
|
|
14
14
|
"test": "jest"
|
|
@@ -45,11 +45,11 @@
|
|
|
45
45
|
"exports": true
|
|
46
46
|
},
|
|
47
47
|
"dependencies": {
|
|
48
|
-
"@valbuild/core": "~0.
|
|
49
|
-
"@valbuild/react": "~0.
|
|
50
|
-
"@valbuild/server": "~0.
|
|
51
|
-
"@valbuild/shared": "~0.
|
|
52
|
-
"@valbuild/ui": "~0.
|
|
48
|
+
"@valbuild/core": "~0.67.1",
|
|
49
|
+
"@valbuild/react": "~0.67.0",
|
|
50
|
+
"@valbuild/server": "~0.67.1",
|
|
51
|
+
"@valbuild/shared": "~0.67.1",
|
|
52
|
+
"@valbuild/ui": "~0.67.1",
|
|
53
53
|
"client-only": "^0.0.1",
|
|
54
54
|
"server-only": "^0.0.1"
|
|
55
55
|
},
|