@hyphacommerce/app-blocks 0.0.0-stage → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE-APACHE +202 -0
- package/LICENSE-MIT +21 -0
- package/README.md +14 -2
- package/dist/index.d.ts +23 -0
- package/dist/index.js +362 -0
- package/dist/react.d.ts +17 -0
- package/dist/react.js +266 -0
- package/dist/types-CP_jLiHn.d.ts +152 -0
- package/dist/types-DpAvyvPv.js +25 -0
- package/package.json +54 -3
- package/schema/block.v1.json +402 -0
package/dist/react.js
ADDED
|
@@ -0,0 +1,266 @@
|
|
|
1
|
+
import { n as isElementType } from "./types-DpAvyvPv.js";
|
|
2
|
+
import { Badge } from "@astryxdesign/core/Badge";
|
|
3
|
+
import { Banner } from "@astryxdesign/core/Banner";
|
|
4
|
+
import { Button } from "@astryxdesign/core/Button";
|
|
5
|
+
import { Card } from "@astryxdesign/core/Card";
|
|
6
|
+
import { CheckboxInput } from "@astryxdesign/core/CheckboxInput";
|
|
7
|
+
import { Divider } from "@astryxdesign/core/Divider";
|
|
8
|
+
import { Heading } from "@astryxdesign/core/Heading";
|
|
9
|
+
import { HStack, VStack } from "@astryxdesign/core/Layout";
|
|
10
|
+
import { Link } from "@astryxdesign/core/Link";
|
|
11
|
+
import { List, ListItem } from "@astryxdesign/core/List";
|
|
12
|
+
import { MetadataList, MetadataListItem } from "@astryxdesign/core/MetadataList";
|
|
13
|
+
import { NumberInput } from "@astryxdesign/core/NumberInput";
|
|
14
|
+
import { Selector } from "@astryxdesign/core/Selector";
|
|
15
|
+
import { Table } from "@astryxdesign/core/Table";
|
|
16
|
+
import { Text } from "@astryxdesign/core/Text";
|
|
17
|
+
import { TextInput } from "@astryxdesign/core/TextInput";
|
|
18
|
+
import { useState, useTransition } from "react";
|
|
19
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
20
|
+
//#region src/render.tsx
|
|
21
|
+
/** Renders a version-1 tree; anything else, and unknown elements, render nothing. */
|
|
22
|
+
function HyphaBlock({ tree, onAction, onNavigate }) {
|
|
23
|
+
if (tree.version !== 1) {
|
|
24
|
+
warn(`block version ${String(tree.version)} isn't supported: nothing rendered`);
|
|
25
|
+
return null;
|
|
26
|
+
}
|
|
27
|
+
return /* @__PURE__ */ jsx(Element, {
|
|
28
|
+
element: tree.root,
|
|
29
|
+
handlers: {
|
|
30
|
+
onAction,
|
|
31
|
+
onNavigate
|
|
32
|
+
}
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
function warn(message) {
|
|
36
|
+
if (typeof process !== "undefined" && process.env.NODE_ENV === "production") return;
|
|
37
|
+
console.warn(`[@hyphacommerce/app-blocks] ${message}`);
|
|
38
|
+
}
|
|
39
|
+
const STACK_GAP = {
|
|
40
|
+
0: 0,
|
|
41
|
+
1: 1,
|
|
42
|
+
2: 2,
|
|
43
|
+
3: 3,
|
|
44
|
+
4: 4
|
|
45
|
+
};
|
|
46
|
+
function isKnown(element) {
|
|
47
|
+
return isElementType(element.type);
|
|
48
|
+
}
|
|
49
|
+
function Children({ elements, handlers }) {
|
|
50
|
+
return elements.map((child, place) => /* @__PURE__ */ jsx(Element, {
|
|
51
|
+
element: child,
|
|
52
|
+
handlers
|
|
53
|
+
}, `${place}:${child.type}`));
|
|
54
|
+
}
|
|
55
|
+
function Element({ element, handlers }) {
|
|
56
|
+
if (!isKnown(element)) {
|
|
57
|
+
warn(`unknown element type ${JSON.stringify(element.type)}: skipped`);
|
|
58
|
+
return null;
|
|
59
|
+
}
|
|
60
|
+
switch (element.type) {
|
|
61
|
+
case "card": return /* @__PURE__ */ jsx(Card, { children: /* @__PURE__ */ jsxs(VStack, {
|
|
62
|
+
gap: 2,
|
|
63
|
+
children: [element.title ? /* @__PURE__ */ jsx(Heading, {
|
|
64
|
+
level: 3,
|
|
65
|
+
children: element.title
|
|
66
|
+
}) : null, /* @__PURE__ */ jsx(Children, {
|
|
67
|
+
elements: element.children,
|
|
68
|
+
handlers
|
|
69
|
+
})]
|
|
70
|
+
}) });
|
|
71
|
+
case "stack": return /* @__PURE__ */ jsx(VStack, {
|
|
72
|
+
gap: STACK_GAP[element.gap ?? 2],
|
|
73
|
+
children: /* @__PURE__ */ jsx(Children, {
|
|
74
|
+
elements: element.children,
|
|
75
|
+
handlers
|
|
76
|
+
})
|
|
77
|
+
});
|
|
78
|
+
case "row": return /* @__PURE__ */ jsx(HStack, {
|
|
79
|
+
gap: STACK_GAP[element.gap ?? 2],
|
|
80
|
+
hAlign: element.align ?? "start",
|
|
81
|
+
vAlign: "center",
|
|
82
|
+
wrap: "wrap",
|
|
83
|
+
children: /* @__PURE__ */ jsx(Children, {
|
|
84
|
+
elements: element.children,
|
|
85
|
+
handlers
|
|
86
|
+
})
|
|
87
|
+
});
|
|
88
|
+
case "text": return /* @__PURE__ */ jsx(Text, {
|
|
89
|
+
type: element.variant ?? "body",
|
|
90
|
+
weight: element.weight === "semibold" ? "semibold" : void 0,
|
|
91
|
+
children: element.value
|
|
92
|
+
});
|
|
93
|
+
case "heading": return /* @__PURE__ */ jsx(Heading, {
|
|
94
|
+
level: element.level ?? 3,
|
|
95
|
+
children: element.value
|
|
96
|
+
});
|
|
97
|
+
case "badge": return /* @__PURE__ */ jsx(Badge, {
|
|
98
|
+
label: element.value,
|
|
99
|
+
variant: element.tone ?? "neutral"
|
|
100
|
+
});
|
|
101
|
+
case "link":
|
|
102
|
+
if (!element.href.startsWith("https://")) return null;
|
|
103
|
+
return /* @__PURE__ */ jsx(Link, {
|
|
104
|
+
href: element.href,
|
|
105
|
+
isExternalLink: element.external ?? false,
|
|
106
|
+
isStandalone: true,
|
|
107
|
+
children: element.label
|
|
108
|
+
});
|
|
109
|
+
case "button": {
|
|
110
|
+
const variant = element.variant ?? "secondary";
|
|
111
|
+
if (element.navigate !== void 0) {
|
|
112
|
+
const path = element.navigate;
|
|
113
|
+
return /* @__PURE__ */ jsx(Button, {
|
|
114
|
+
label: element.label,
|
|
115
|
+
variant,
|
|
116
|
+
onClick: () => handlers.onNavigate?.(path)
|
|
117
|
+
});
|
|
118
|
+
}
|
|
119
|
+
const action = element.action;
|
|
120
|
+
return /* @__PURE__ */ jsx(Button, {
|
|
121
|
+
label: element.label,
|
|
122
|
+
variant,
|
|
123
|
+
isDisabled: !handlers.onAction,
|
|
124
|
+
clickAction: async () => {
|
|
125
|
+
await handlers.onAction?.(action);
|
|
126
|
+
}
|
|
127
|
+
});
|
|
128
|
+
}
|
|
129
|
+
case "divider": return /* @__PURE__ */ jsx(Divider, {});
|
|
130
|
+
case "image":
|
|
131
|
+
if (!element.src.startsWith("https://")) return null;
|
|
132
|
+
return /* @__PURE__ */ jsx("img", {
|
|
133
|
+
src: element.src,
|
|
134
|
+
alt: element.alt,
|
|
135
|
+
width: element.width,
|
|
136
|
+
height: element.height,
|
|
137
|
+
loading: "lazy",
|
|
138
|
+
style: {
|
|
139
|
+
maxWidth: "100%",
|
|
140
|
+
height: "auto"
|
|
141
|
+
}
|
|
142
|
+
});
|
|
143
|
+
case "list": return /* @__PURE__ */ jsx(List, {
|
|
144
|
+
hasDividers: true,
|
|
145
|
+
children: element.items.map((item, place) => /* @__PURE__ */ jsx(ListItem, {
|
|
146
|
+
label: item.label,
|
|
147
|
+
description: item.description
|
|
148
|
+
}, `${place}:${item.label}`))
|
|
149
|
+
});
|
|
150
|
+
case "table": return /* @__PURE__ */ jsx(BlockTable, { element });
|
|
151
|
+
case "keyvalue": return /* @__PURE__ */ jsx(MetadataList, { children: element.items.map((item, place) => /* @__PURE__ */ jsx(MetadataListItem, {
|
|
152
|
+
label: item.label,
|
|
153
|
+
children: item.value
|
|
154
|
+
}, `${place}:${item.label}`)) });
|
|
155
|
+
case "form": return /* @__PURE__ */ jsx(BlockForm, {
|
|
156
|
+
form: element,
|
|
157
|
+
onAction: handlers.onAction
|
|
158
|
+
});
|
|
159
|
+
case "banner": return /* @__PURE__ */ jsx(Banner, {
|
|
160
|
+
status: element.tone,
|
|
161
|
+
title: element.title,
|
|
162
|
+
description: element.description
|
|
163
|
+
});
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
function BlockTable({ element }) {
|
|
167
|
+
const columns = element.columns.map((column) => ({
|
|
168
|
+
key: column.key,
|
|
169
|
+
header: column.header,
|
|
170
|
+
align: column.align === "end" ? "end" : "start",
|
|
171
|
+
renderCell: (row) => {
|
|
172
|
+
const cell = row[column.key];
|
|
173
|
+
return typeof cell === "string" || typeof cell === "number" ? String(cell) : "—";
|
|
174
|
+
}
|
|
175
|
+
}));
|
|
176
|
+
const data = element.rows.map((row, place) => ({
|
|
177
|
+
...row,
|
|
178
|
+
__row: place
|
|
179
|
+
}));
|
|
180
|
+
return /* @__PURE__ */ jsx(Table, {
|
|
181
|
+
data,
|
|
182
|
+
columns,
|
|
183
|
+
idKey: "__row"
|
|
184
|
+
});
|
|
185
|
+
}
|
|
186
|
+
function initialValues(fields) {
|
|
187
|
+
const values = {};
|
|
188
|
+
for (const field of fields) if (field.input === "checkbox") values[field.name] = field.value ?? false;
|
|
189
|
+
else if (field.input === "number") values[field.name] = field.value ?? null;
|
|
190
|
+
else values[field.name] = field.value ?? "";
|
|
191
|
+
return values;
|
|
192
|
+
}
|
|
193
|
+
function BlockForm({ form, onAction }) {
|
|
194
|
+
const [values, setValues] = useState(() => initialValues(form.fields));
|
|
195
|
+
const [pending, startTransition] = useTransition();
|
|
196
|
+
const set = (name, value) => setValues((current) => ({
|
|
197
|
+
...current,
|
|
198
|
+
[name]: value
|
|
199
|
+
}));
|
|
200
|
+
const submit = (event) => {
|
|
201
|
+
event.preventDefault();
|
|
202
|
+
if (!onAction) return;
|
|
203
|
+
startTransition(async () => {
|
|
204
|
+
await onAction(form.action, values);
|
|
205
|
+
});
|
|
206
|
+
};
|
|
207
|
+
return /* @__PURE__ */ jsx("form", {
|
|
208
|
+
onSubmit: submit,
|
|
209
|
+
children: /* @__PURE__ */ jsxs(VStack, {
|
|
210
|
+
gap: 3,
|
|
211
|
+
children: [form.fields.map((field) => /* @__PURE__ */ jsx(FormField, {
|
|
212
|
+
field,
|
|
213
|
+
value: values[field.name] ?? null,
|
|
214
|
+
onChange: set
|
|
215
|
+
}, field.name)), /* @__PURE__ */ jsx(HStack, {
|
|
216
|
+
hAlign: "end",
|
|
217
|
+
children: /* @__PURE__ */ jsx(Button, {
|
|
218
|
+
type: "submit",
|
|
219
|
+
variant: "primary",
|
|
220
|
+
label: form.submit_label ?? "Save",
|
|
221
|
+
isLoading: pending,
|
|
222
|
+
isDisabled: !onAction
|
|
223
|
+
})
|
|
224
|
+
})]
|
|
225
|
+
})
|
|
226
|
+
});
|
|
227
|
+
}
|
|
228
|
+
function FormField({ field, value, onChange }) {
|
|
229
|
+
const common = {
|
|
230
|
+
label: field.label,
|
|
231
|
+
description: field.description,
|
|
232
|
+
isRequired: field.required ?? false,
|
|
233
|
+
htmlName: field.name
|
|
234
|
+
};
|
|
235
|
+
switch (field.input) {
|
|
236
|
+
case "text": return /* @__PURE__ */ jsx(TextInput, {
|
|
237
|
+
...common,
|
|
238
|
+
placeholder: field.placeholder,
|
|
239
|
+
value: typeof value === "string" ? value : "",
|
|
240
|
+
onChange: (next) => onChange(field.name, next)
|
|
241
|
+
});
|
|
242
|
+
case "number": return /* @__PURE__ */ jsx(NumberInput, {
|
|
243
|
+
...common,
|
|
244
|
+
min: field.min,
|
|
245
|
+
max: field.max,
|
|
246
|
+
value: typeof value === "number" ? value : null,
|
|
247
|
+
onChange: (next) => onChange(field.name, next)
|
|
248
|
+
});
|
|
249
|
+
case "select": return /* @__PURE__ */ jsx(Selector, {
|
|
250
|
+
...common,
|
|
251
|
+
options: field.options,
|
|
252
|
+
value: typeof value === "string" && value !== "" ? value : void 0,
|
|
253
|
+
onChange: (next) => onChange(field.name, next)
|
|
254
|
+
});
|
|
255
|
+
case "checkbox": return /* @__PURE__ */ jsx(CheckboxInput, {
|
|
256
|
+
label: common.label,
|
|
257
|
+
description: common.description,
|
|
258
|
+
isRequired: common.isRequired,
|
|
259
|
+
htmlName: common.htmlName,
|
|
260
|
+
value: value === true,
|
|
261
|
+
onChange: (checked) => onChange(field.name, checked)
|
|
262
|
+
});
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
//#endregion
|
|
266
|
+
export { HyphaBlock };
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
//#region src/types.d.ts
|
|
2
|
+
type Gap = 0 | 1 | 2 | 3 | 4;
|
|
3
|
+
type Tone = "neutral" | "info" | "success" | "warning" | "error";
|
|
4
|
+
type BannerTone = Exclude<Tone, "neutral">;
|
|
5
|
+
interface CardElement {
|
|
6
|
+
type: "card";
|
|
7
|
+
title?: string;
|
|
8
|
+
children: BlockElement[];
|
|
9
|
+
}
|
|
10
|
+
interface StackElement {
|
|
11
|
+
type: "stack";
|
|
12
|
+
gap?: Gap;
|
|
13
|
+
children: BlockElement[];
|
|
14
|
+
}
|
|
15
|
+
interface RowElement {
|
|
16
|
+
type: "row";
|
|
17
|
+
gap?: Gap;
|
|
18
|
+
align?: "start" | "center" | "end" | "between";
|
|
19
|
+
children: BlockElement[];
|
|
20
|
+
}
|
|
21
|
+
interface TextElement {
|
|
22
|
+
type: "text";
|
|
23
|
+
value: string;
|
|
24
|
+
variant?: "body" | "supporting" | "code";
|
|
25
|
+
weight?: "normal" | "semibold";
|
|
26
|
+
}
|
|
27
|
+
interface HeadingElement {
|
|
28
|
+
type: "heading";
|
|
29
|
+
value: string;
|
|
30
|
+
level?: 2 | 3 | 4;
|
|
31
|
+
}
|
|
32
|
+
interface BadgeElement {
|
|
33
|
+
type: "badge";
|
|
34
|
+
value: string;
|
|
35
|
+
tone?: Tone;
|
|
36
|
+
}
|
|
37
|
+
interface LinkElement {
|
|
38
|
+
type: "link";
|
|
39
|
+
label: string;
|
|
40
|
+
/** `https://` only. */
|
|
41
|
+
href: string;
|
|
42
|
+
external?: boolean;
|
|
43
|
+
}
|
|
44
|
+
interface ButtonBase {
|
|
45
|
+
type: "button";
|
|
46
|
+
label: string;
|
|
47
|
+
variant?: "primary" | "secondary" | "destructive";
|
|
48
|
+
}
|
|
49
|
+
/** Runs an action or navigates within the app's page: one of the two. */
|
|
50
|
+
type ButtonElement = (ButtonBase & {
|
|
51
|
+
action: string;
|
|
52
|
+
navigate?: never;
|
|
53
|
+
}) | (ButtonBase & {
|
|
54
|
+
navigate: string;
|
|
55
|
+
action?: never;
|
|
56
|
+
});
|
|
57
|
+
interface DividerElement {
|
|
58
|
+
type: "divider";
|
|
59
|
+
}
|
|
60
|
+
interface ImageElement {
|
|
61
|
+
type: "image";
|
|
62
|
+
/** `https://` only. */
|
|
63
|
+
src: string;
|
|
64
|
+
alt: string;
|
|
65
|
+
width?: number;
|
|
66
|
+
height?: number;
|
|
67
|
+
}
|
|
68
|
+
interface ListElement {
|
|
69
|
+
type: "list";
|
|
70
|
+
items: {
|
|
71
|
+
label: string;
|
|
72
|
+
description?: string;
|
|
73
|
+
}[];
|
|
74
|
+
}
|
|
75
|
+
interface TableElement {
|
|
76
|
+
type: "table";
|
|
77
|
+
columns: {
|
|
78
|
+
key: string;
|
|
79
|
+
header: string;
|
|
80
|
+
align?: "start" | "end";
|
|
81
|
+
}[];
|
|
82
|
+
rows: Record<string, string | number | null>[];
|
|
83
|
+
}
|
|
84
|
+
interface KeyValueElement {
|
|
85
|
+
type: "keyvalue";
|
|
86
|
+
items: {
|
|
87
|
+
label: string;
|
|
88
|
+
value: string;
|
|
89
|
+
}[];
|
|
90
|
+
}
|
|
91
|
+
interface FieldBase {
|
|
92
|
+
type: "field";
|
|
93
|
+
name: string;
|
|
94
|
+
label: string;
|
|
95
|
+
description?: string;
|
|
96
|
+
required?: boolean;
|
|
97
|
+
}
|
|
98
|
+
type FieldElement = (FieldBase & {
|
|
99
|
+
input: "text";
|
|
100
|
+
value?: string;
|
|
101
|
+
placeholder?: string;
|
|
102
|
+
}) | (FieldBase & {
|
|
103
|
+
input: "number";
|
|
104
|
+
value?: number;
|
|
105
|
+
min?: number;
|
|
106
|
+
max?: number;
|
|
107
|
+
}) | (FieldBase & {
|
|
108
|
+
input: "select";
|
|
109
|
+
value?: string;
|
|
110
|
+
options: {
|
|
111
|
+
value: string;
|
|
112
|
+
label: string;
|
|
113
|
+
}[];
|
|
114
|
+
}) | (FieldBase & {
|
|
115
|
+
input: "checkbox";
|
|
116
|
+
value?: boolean;
|
|
117
|
+
});
|
|
118
|
+
interface FormElement {
|
|
119
|
+
type: "form";
|
|
120
|
+
action: string;
|
|
121
|
+
submit_label?: string;
|
|
122
|
+
fields: FieldElement[];
|
|
123
|
+
}
|
|
124
|
+
interface BannerElement {
|
|
125
|
+
type: "banner";
|
|
126
|
+
tone: BannerTone;
|
|
127
|
+
title: string;
|
|
128
|
+
description?: string;
|
|
129
|
+
}
|
|
130
|
+
/** Every element version 1 knows. */
|
|
131
|
+
type KnownElement = CardElement | StackElement | RowElement | TextElement | HeadingElement | BadgeElement | LinkElement | ButtonElement | DividerElement | ImageElement | ListElement | TableElement | KeyValueElement | FormElement | BannerElement;
|
|
132
|
+
type ElementType = KnownElement["type"];
|
|
133
|
+
declare const ELEMENT_TYPES: readonly ElementType[];
|
|
134
|
+
/** Whether version 1 knows the element type `type`. */
|
|
135
|
+
declare function isElementType(type: string): type is ElementType;
|
|
136
|
+
/**
|
|
137
|
+
* An element of a type a newer version added: allowed in a tree, rendered as nothing.
|
|
138
|
+
* (Typed loosely so trees from newer apps still type-check where they're passed through.)
|
|
139
|
+
*/
|
|
140
|
+
interface UnknownElement {
|
|
141
|
+
type: string;
|
|
142
|
+
[key: string]: unknown;
|
|
143
|
+
}
|
|
144
|
+
type BlockElement = KnownElement | UnknownElement;
|
|
145
|
+
interface BlockTree {
|
|
146
|
+
version: 1;
|
|
147
|
+
root: BlockElement;
|
|
148
|
+
}
|
|
149
|
+
/** The values a form submits, by field name. */
|
|
150
|
+
type FormValues = Record<string, string | number | boolean | null>;
|
|
151
|
+
//#endregion
|
|
152
|
+
export { TableElement as C, isElementType as D, UnknownElement as E, StackElement as S, Tone as T, KeyValueElement as _, BlockTree as a, ListElement as b, DividerElement as c, FieldElement as d, FormElement as f, ImageElement as g, HeadingElement as h, BlockElement as i, ELEMENT_TYPES as l, Gap as m, BannerElement as n, ButtonElement as o, FormValues as p, BannerTone as r, CardElement as s, BadgeElement as t, ElementType as u, KnownElement as v, TextElement as w, RowElement as x, LinkElement as y };
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
//#region src/types.ts
|
|
2
|
+
const ELEMENT_TYPES = [
|
|
3
|
+
"card",
|
|
4
|
+
"stack",
|
|
5
|
+
"row",
|
|
6
|
+
"text",
|
|
7
|
+
"heading",
|
|
8
|
+
"badge",
|
|
9
|
+
"link",
|
|
10
|
+
"button",
|
|
11
|
+
"divider",
|
|
12
|
+
"image",
|
|
13
|
+
"list",
|
|
14
|
+
"table",
|
|
15
|
+
"keyvalue",
|
|
16
|
+
"form",
|
|
17
|
+
"banner"
|
|
18
|
+
];
|
|
19
|
+
const KNOWN_TYPES = new Set(ELEMENT_TYPES);
|
|
20
|
+
/** Whether version 1 knows the element type `type`. */
|
|
21
|
+
function isElementType(type) {
|
|
22
|
+
return KNOWN_TYPES.has(type);
|
|
23
|
+
}
|
|
24
|
+
//#endregion
|
|
25
|
+
export { isElementType as n, ELEMENT_TYPES as t };
|
package/package.json
CHANGED
|
@@ -1,6 +1,57 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hyphacommerce/app-blocks",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"
|
|
5
|
-
"
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Hypha's declarative app blocks, version 1: the JSON Schema, TypeScript types, a validator and the reference React renderer on Astryx.",
|
|
5
|
+
"homepage": "https://hyphacommerce.com",
|
|
6
|
+
"bugs": "https://github.com/hyphacommerce/hypha/issues",
|
|
7
|
+
"license": "MIT OR Apache-2.0",
|
|
8
|
+
"repository": {
|
|
9
|
+
"type": "git",
|
|
10
|
+
"url": "git+https://github.com/hyphacommerce/hypha.git",
|
|
11
|
+
"directory": "packages/app-blocks"
|
|
12
|
+
},
|
|
13
|
+
"files": [
|
|
14
|
+
"dist",
|
|
15
|
+
"schema",
|
|
16
|
+
"LICENSE-MIT",
|
|
17
|
+
"LICENSE-APACHE",
|
|
18
|
+
"README.md"
|
|
19
|
+
],
|
|
20
|
+
"type": "module",
|
|
21
|
+
"sideEffects": false,
|
|
22
|
+
"exports": {
|
|
23
|
+
".": {
|
|
24
|
+
"types": "./dist/index.d.ts",
|
|
25
|
+
"default": "./dist/index.js"
|
|
26
|
+
},
|
|
27
|
+
"./react": {
|
|
28
|
+
"types": "./dist/react.d.ts",
|
|
29
|
+
"default": "./dist/react.js"
|
|
30
|
+
},
|
|
31
|
+
"./schema/block.v1.json": "./schema/block.v1.json"
|
|
32
|
+
},
|
|
33
|
+
"publishConfig": {
|
|
34
|
+
"access": "public"
|
|
35
|
+
},
|
|
36
|
+
"devDependencies": {
|
|
37
|
+
"@astryxdesign/core": "0.7.1",
|
|
38
|
+
"@stylexjs/stylex": "0.19.1",
|
|
39
|
+
"@types/node": "26.6.5",
|
|
40
|
+
"@types/react": "19.3.0",
|
|
41
|
+
"@types/react-dom": "19.3.0",
|
|
42
|
+
"ajv": "8.20.0",
|
|
43
|
+
"jiti": "2.7.0",
|
|
44
|
+
"react": "19.3.1",
|
|
45
|
+
"react-dom": "19.3.1",
|
|
46
|
+
"typescript": "5.9.3"
|
|
47
|
+
},
|
|
48
|
+
"peerDependencies": {
|
|
49
|
+
"@astryxdesign/core": "0.7.1",
|
|
50
|
+
"react": ">=19.0.0"
|
|
51
|
+
},
|
|
52
|
+
"scripts": {
|
|
53
|
+
"build": "tsdown",
|
|
54
|
+
"test": "node --test src/*.test.ts",
|
|
55
|
+
"typecheck": "tsc --noEmit"
|
|
56
|
+
}
|
|
6
57
|
}
|