@vertebr/react 0.3.0 → 0.4.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/dist/components/admin/VertebrAdmin.d.ts.map +1 -1
- package/dist/components/admin/VertebrAdmin.js +1 -1
- package/dist/components/config/EnumInput.d.ts +10 -0
- package/dist/components/config/EnumInput.d.ts.map +1 -0
- package/dist/components/config/EnumInput.js +19 -0
- package/dist/components/config/EnumListInput.d.ts +10 -0
- package/dist/components/config/EnumListInput.d.ts.map +1 -0
- package/dist/components/config/EnumListInput.js +46 -0
- package/dist/components/config/VisibilityEye.d.ts +8 -0
- package/dist/components/config/VisibilityEye.d.ts.map +1 -0
- package/dist/components/config/VisibilityEye.js +18 -0
- package/dist/components/config/form/ConfigField.d.ts +2 -1
- package/dist/components/config/form/ConfigField.d.ts.map +1 -1
- package/dist/components/config/form/ConfigField.js +9 -4
- package/dist/components/config/form/ConfigForm.d.ts +1 -1
- package/dist/components/config/form/ConfigForm.d.ts.map +1 -1
- package/dist/components/config/form/ConfigForm.js +14 -9
- package/dist/components/config/form/ConfigFormActions.d.ts +2 -1
- package/dist/components/config/form/ConfigFormActions.d.ts.map +1 -1
- package/dist/components/config/form/ConfigFormActions.js +2 -2
- package/dist/components/config/form/RecordConfigForm.d.ts +2 -1
- package/dist/components/config/form/RecordConfigForm.d.ts.map +1 -1
- package/dist/components/config/form/RecordConfigForm.js +16 -8
- package/dist/components/config/form/SettingsConfigForm.d.ts +2 -1
- package/dist/components/config/form/SettingsConfigForm.d.ts.map +1 -1
- package/dist/components/config/form/SettingsConfigForm.js +2 -2
- package/dist/components/config/form/helpers/fields.d.ts +7 -0
- package/dist/components/config/form/helpers/fields.d.ts.map +1 -0
- package/dist/components/config/form/helpers/fields.js +31 -0
- package/dist/components/config/form/helpers/groups.d.ts +4 -0
- package/dist/components/config/form/helpers/groups.d.ts.map +1 -0
- package/dist/components/config/form/helpers/groups.js +107 -0
- package/dist/components/config/form/helpers/images.d.ts +4 -0
- package/dist/components/config/form/helpers/images.d.ts.map +1 -0
- package/dist/components/config/form/helpers/images.js +27 -0
- package/dist/components/config/form/helpers/index.d.ts +7 -0
- package/dist/components/config/form/helpers/index.d.ts.map +1 -0
- package/dist/components/config/form/helpers/index.js +6 -0
- package/dist/components/config/form/helpers/labels.d.ts +5 -0
- package/dist/components/config/form/helpers/labels.d.ts.map +1 -0
- package/dist/components/config/form/helpers/labels.js +28 -0
- package/dist/components/config/form/helpers/schema.d.ts +8 -0
- package/dist/components/config/form/helpers/schema.d.ts.map +1 -0
- package/dist/components/config/form/helpers/schema.js +30 -0
- package/dist/components/config/form/helpers/visibility.d.ts +13 -0
- package/dist/components/config/form/helpers/visibility.d.ts.map +1 -0
- package/dist/components/config/form/helpers/visibility.js +86 -0
- package/dist/components/config/form/types.d.ts +2 -0
- package/dist/components/config/form/types.d.ts.map +1 -1
- package/dist/components/resources/ResourceCreateModal.d.ts +18 -0
- package/dist/components/resources/ResourceCreateModal.d.ts.map +1 -0
- package/dist/components/resources/ResourceCreateModal.js +22 -0
- package/dist/components/resources/ResourceTable.d.ts +3 -1
- package/dist/components/resources/ResourceTable.d.ts.map +1 -1
- package/dist/components/resources/ResourceTable.js +40 -4
- package/dist/index.d.ts +4 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -0
- package/dist/styles/form.css +145 -0
- package/dist/styles/modal.css +18 -0
- package/dist/styles/panel.css +6 -0
- package/package.json +2 -2
- package/dist/components/config/form/helpers.d.ts +0 -16
- package/dist/components/config/form/helpers.d.ts.map +0 -1
- package/dist/components/config/form/helpers.js +0 -186
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { isImageField, looksLikeUrl } from "../../../../lib/images";
|
|
2
|
+
export function firstImageUrl(value) {
|
|
3
|
+
const items = Array.isArray(value) ? value : [value];
|
|
4
|
+
for (const item of items) {
|
|
5
|
+
if (typeof item === "string" && looksLikeUrl(item))
|
|
6
|
+
return item;
|
|
7
|
+
if (item && typeof item === "object" && "url" in item) {
|
|
8
|
+
const url = item.url;
|
|
9
|
+
if (typeof url === "string" && looksLikeUrl(url))
|
|
10
|
+
return url;
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
return null;
|
|
14
|
+
}
|
|
15
|
+
export function findPrimaryImageKey(schema, values) {
|
|
16
|
+
for (const [key, field] of Object.entries(schema)) {
|
|
17
|
+
if (!isImageField(key, field))
|
|
18
|
+
continue;
|
|
19
|
+
if (firstImageUrl(values?.[key]))
|
|
20
|
+
return key;
|
|
21
|
+
}
|
|
22
|
+
for (const [key, field] of Object.entries(schema)) {
|
|
23
|
+
if (isImageField(key, field))
|
|
24
|
+
return key;
|
|
25
|
+
}
|
|
26
|
+
return null;
|
|
27
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export { buildZodSchema } from "./schema";
|
|
2
|
+
export { displayLabel, humanizeKey, optionLabel, } from "./labels";
|
|
3
|
+
export { isMultilineField, isSpecsField, isStockField, spanFor, } from "./fields";
|
|
4
|
+
export { fieldVisibilityKey, groupVisibilityKey, isPairedVisibilityField, showFlagKey, visibilityToggleKey, withSpecVisibility, withSpecVisibilityValues, } from "./visibility";
|
|
5
|
+
export { groupFields } from "./groups";
|
|
6
|
+
export { findPrimaryImageKey, firstImageUrl } from "./images";
|
|
7
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/components/config/form/helpers/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,UAAU,CAAC;AAC1C,OAAO,EACL,YAAY,EACZ,WAAW,EACX,WAAW,GACZ,MAAM,UAAU,CAAC;AAClB,OAAO,EACL,gBAAgB,EAChB,YAAY,EACZ,YAAY,EACZ,OAAO,GACR,MAAM,UAAU,CAAC;AAClB,OAAO,EACL,kBAAkB,EAClB,kBAAkB,EAClB,uBAAuB,EACvB,WAAW,EACX,mBAAmB,EACnB,kBAAkB,EAClB,wBAAwB,GACzB,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AACvC,OAAO,EAAE,mBAAmB,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export { buildZodSchema } from "./schema";
|
|
2
|
+
export { displayLabel, humanizeKey, optionLabel, } from "./labels";
|
|
3
|
+
export { isMultilineField, isSpecsField, isStockField, spanFor, } from "./fields";
|
|
4
|
+
export { fieldVisibilityKey, groupVisibilityKey, isPairedVisibilityField, showFlagKey, visibilityToggleKey, withSpecVisibility, withSpecVisibilityValues, } from "./visibility";
|
|
5
|
+
export { groupFields } from "./groups";
|
|
6
|
+
export { findPrimaryImageKey, firstImageUrl } from "./images";
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { FieldSchema } from "@vertebr/client";
|
|
2
|
+
export declare function humanizeKey(key: string): string;
|
|
3
|
+
export declare function optionLabel(value: string, field?: FieldSchema): string;
|
|
4
|
+
export declare function displayLabel(key: string, field: FieldSchema, group: string): string;
|
|
5
|
+
//# sourceMappingURL=labels.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"labels.d.ts","sourceRoot":"","sources":["../../../../../src/components/config/form/helpers/labels.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAEnD,wBAAgB,WAAW,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAK/C;AAED,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,WAAW,GAAG,MAAM,CAItE;AAMD,wBAAgB,YAAY,CAC1B,GAAG,EAAE,MAAM,EACX,KAAK,EAAE,WAAW,EAClB,KAAK,EAAE,MAAM,GACZ,MAAM,CAcR"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
export function humanizeKey(key) {
|
|
2
|
+
return key
|
|
3
|
+
.replace(/([a-z])([A-Z])/g, "$1 $2")
|
|
4
|
+
.replace(/[_-]+/g, " ")
|
|
5
|
+
.trim();
|
|
6
|
+
}
|
|
7
|
+
export function optionLabel(value, field) {
|
|
8
|
+
const labeled = field?.optionLabels?.[value]?.trim();
|
|
9
|
+
if (labeled)
|
|
10
|
+
return labeled;
|
|
11
|
+
return humanizeKey(value);
|
|
12
|
+
}
|
|
13
|
+
function escapeRegExp(value) {
|
|
14
|
+
return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
15
|
+
}
|
|
16
|
+
export function displayLabel(key, field, group) {
|
|
17
|
+
const label = field.label?.trim() || humanizeKey(key);
|
|
18
|
+
const stripped = label.replace(new RegExp(`^${escapeRegExp(group)}\\s+`, "i"), "");
|
|
19
|
+
if (/^inventory$/i.test(group)) {
|
|
20
|
+
const stock = label.replace(/^stock\s+/i, "").trim();
|
|
21
|
+
if (stock && stock !== label)
|
|
22
|
+
return stock;
|
|
23
|
+
}
|
|
24
|
+
if (/^pricing$/i.test(group) && /cents/i.test(label)) {
|
|
25
|
+
return label.replace(/\s*\(cents\)/i, "").trim() || label;
|
|
26
|
+
}
|
|
27
|
+
return stripped || label;
|
|
28
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import type { FieldSchema } from "@vertebr/client";
|
|
3
|
+
export declare function buildZodSchema(schema: Record<string, FieldSchema>): z.ZodObject<Record<string, z.ZodTypeAny>, "strip", z.ZodTypeAny, {
|
|
4
|
+
[x: string]: any;
|
|
5
|
+
}, {
|
|
6
|
+
[x: string]: any;
|
|
7
|
+
}>;
|
|
8
|
+
//# sourceMappingURL=schema.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../../../../../src/components/config/form/helpers/schema.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAEnD,wBAAgB,cAAc,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC;;;;GA0BjE"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
export function buildZodSchema(schema) {
|
|
3
|
+
const shape = {};
|
|
4
|
+
for (const [key, field] of Object.entries(schema)) {
|
|
5
|
+
let zodField;
|
|
6
|
+
switch (field.type) {
|
|
7
|
+
case "number":
|
|
8
|
+
zodField = z.number();
|
|
9
|
+
if (field.min != null)
|
|
10
|
+
zodField = zodField.min(field.min);
|
|
11
|
+
if (field.max != null)
|
|
12
|
+
zodField = zodField.max(field.max);
|
|
13
|
+
break;
|
|
14
|
+
case "boolean":
|
|
15
|
+
zodField = z.boolean();
|
|
16
|
+
break;
|
|
17
|
+
case "file[]":
|
|
18
|
+
case "enum[]":
|
|
19
|
+
zodField = z.array(z.string());
|
|
20
|
+
break;
|
|
21
|
+
default:
|
|
22
|
+
zodField = z.string();
|
|
23
|
+
}
|
|
24
|
+
if (!field.required) {
|
|
25
|
+
zodField = zodField.optional();
|
|
26
|
+
}
|
|
27
|
+
shape[key] = zodField;
|
|
28
|
+
}
|
|
29
|
+
return z.object(shape);
|
|
30
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { FieldSchema } from "@vertebr/client";
|
|
2
|
+
export declare function showFlagKey(fieldKey: string): string;
|
|
3
|
+
/** Ensure each Specs field has a paired `showX` boolean in the editor schema. */
|
|
4
|
+
export declare function withSpecVisibility(schema: Record<string, FieldSchema>): Record<string, FieldSchema>;
|
|
5
|
+
export declare function withSpecVisibilityValues(schema: Record<string, FieldSchema>, value: Record<string, unknown>): Record<string, unknown>;
|
|
6
|
+
/** `showMaterial` paired with `material`, `showPrice` with `priceCents`. */
|
|
7
|
+
export declare function visibilityToggleKey(fieldKey: string, schema: Record<string, FieldSchema>): string | null;
|
|
8
|
+
export declare function isPairedVisibilityField(key: string, schema: Record<string, FieldSchema>): boolean;
|
|
9
|
+
/** Section-level storefront flag, e.g. Pricing → `showPrice`. */
|
|
10
|
+
export declare function groupVisibilityKey(groupId: string, schema: Record<string, FieldSchema>): string | null;
|
|
11
|
+
/** Field-level flag, skipped when the section header already owns it. */
|
|
12
|
+
export declare function fieldVisibilityKey(fieldKey: string, schema: Record<string, FieldSchema>, groupId?: string): string | null;
|
|
13
|
+
//# sourceMappingURL=visibility.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"visibility.d.ts","sourceRoot":"","sources":["../../../../../src/components/config/form/helpers/visibility.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAInD,wBAAgB,WAAW,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAEpD;AAED,iFAAiF;AACjF,wBAAgB,kBAAkB,CAChC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,GAClC,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,CAc7B;AAED,wBAAgB,wBAAwB,CACtC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,EACnC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC7B,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CASzB;AAMD,4EAA4E;AAC5E,wBAAgB,mBAAmB,CACjC,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,GAClC,MAAM,GAAG,IAAI,CASf;AAcD,wBAAgB,uBAAuB,CACrC,GAAG,EAAE,MAAM,EACX,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,GAClC,OAAO,CAMT;AAED,iEAAiE;AACjE,wBAAgB,kBAAkB,CAChC,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,GAClC,MAAM,GAAG,IAAI,CAIf;AAED,yEAAyE;AACzE,wBAAgB,kBAAkB,CAChC,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,EACnC,OAAO,CAAC,EAAE,MAAM,GACf,MAAM,GAAG,IAAI,CAKf"}
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import { isSpecsField } from "./fields";
|
|
2
|
+
import { humanizeKey } from "./labels";
|
|
3
|
+
export function showFlagKey(fieldKey) {
|
|
4
|
+
return `show${fieldKey.charAt(0).toUpperCase()}${fieldKey.slice(1)}`;
|
|
5
|
+
}
|
|
6
|
+
/** Ensure each Specs field has a paired `showX` boolean in the editor schema. */
|
|
7
|
+
export function withSpecVisibility(schema) {
|
|
8
|
+
const next = { ...schema };
|
|
9
|
+
for (const [key, field] of Object.entries(schema)) {
|
|
10
|
+
if (field.type === "boolean" || !isSpecsField(key, field))
|
|
11
|
+
continue;
|
|
12
|
+
const flag = showFlagKey(key);
|
|
13
|
+
if (!next[flag]) {
|
|
14
|
+
next[flag] = {
|
|
15
|
+
type: "boolean",
|
|
16
|
+
default: true,
|
|
17
|
+
label: `Show ${field.label ?? humanizeKey(key)}`,
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
return next;
|
|
22
|
+
}
|
|
23
|
+
export function withSpecVisibilityValues(schema, value) {
|
|
24
|
+
const next = { ...value };
|
|
25
|
+
for (const [key, field] of Object.entries(schema)) {
|
|
26
|
+
if (field.type === "boolean" || !isSpecsField(key, field))
|
|
27
|
+
continue;
|
|
28
|
+
const flag = showFlagKey(key);
|
|
29
|
+
if (!(flag in next) || next[flag] == null)
|
|
30
|
+
next[flag] = true;
|
|
31
|
+
else
|
|
32
|
+
next[flag] = next[flag] !== false;
|
|
33
|
+
}
|
|
34
|
+
return next;
|
|
35
|
+
}
|
|
36
|
+
function pascalToCamel(value) {
|
|
37
|
+
return value.charAt(0).toLowerCase() + value.slice(1);
|
|
38
|
+
}
|
|
39
|
+
/** `showMaterial` paired with `material`, `showPrice` with `priceCents`. */
|
|
40
|
+
export function visibilityToggleKey(fieldKey, schema) {
|
|
41
|
+
const flag = showFlagKey(fieldKey);
|
|
42
|
+
const candidates = [flag];
|
|
43
|
+
if (fieldKey === "priceCents")
|
|
44
|
+
candidates.push("showPrice");
|
|
45
|
+
for (const key of candidates) {
|
|
46
|
+
if (schema[key]?.type === "boolean")
|
|
47
|
+
return key;
|
|
48
|
+
}
|
|
49
|
+
if (isSpecsField(fieldKey, schema[fieldKey]))
|
|
50
|
+
return flag;
|
|
51
|
+
return null;
|
|
52
|
+
}
|
|
53
|
+
const GROUP_VISIBILITY = {
|
|
54
|
+
Pricing: "showPrice",
|
|
55
|
+
Inventory: "showStock",
|
|
56
|
+
Content: "showDescription",
|
|
57
|
+
};
|
|
58
|
+
function groupVisibilityKeyFromField(key) {
|
|
59
|
+
return Object.keys(GROUP_VISIBILITY).find((group) => GROUP_VISIBILITY[group] === key);
|
|
60
|
+
}
|
|
61
|
+
export function isPairedVisibilityField(key, schema) {
|
|
62
|
+
if (!/^show[A-Z]/.test(key) || schema[key]?.type !== "boolean")
|
|
63
|
+
return false;
|
|
64
|
+
if (groupVisibilityKeyFromField(key))
|
|
65
|
+
return true;
|
|
66
|
+
const target = pascalToCamel(key.slice(4));
|
|
67
|
+
if (schema[target])
|
|
68
|
+
return true;
|
|
69
|
+
return key === "showPrice" && Boolean(schema.priceCents);
|
|
70
|
+
}
|
|
71
|
+
/** Section-level storefront flag, e.g. Pricing → `showPrice`. */
|
|
72
|
+
export function groupVisibilityKey(groupId, schema) {
|
|
73
|
+
const key = GROUP_VISIBILITY[groupId];
|
|
74
|
+
if (key && schema[key]?.type === "boolean")
|
|
75
|
+
return key;
|
|
76
|
+
return null;
|
|
77
|
+
}
|
|
78
|
+
/** Field-level flag, skipped when the section header already owns it. */
|
|
79
|
+
export function fieldVisibilityKey(fieldKey, schema, groupId) {
|
|
80
|
+
const paired = visibilityToggleKey(fieldKey, schema);
|
|
81
|
+
if (!paired)
|
|
82
|
+
return null;
|
|
83
|
+
if (groupId && groupVisibilityKey(groupId, schema) === paired)
|
|
84
|
+
return null;
|
|
85
|
+
return paired;
|
|
86
|
+
}
|
|
@@ -4,6 +4,8 @@ export type ConfigFormProps = {
|
|
|
4
4
|
schema: Record<string, FieldSchema>;
|
|
5
5
|
value: Record<string, unknown>;
|
|
6
6
|
onSave: (value: Record<string, unknown>) => Promise<void>;
|
|
7
|
+
/** Primary submit button label. @default "Save changes" */
|
|
8
|
+
submitLabel?: string;
|
|
7
9
|
/** `record` uses a dense product-style editor. */
|
|
8
10
|
variant?: ConfigFormVariant;
|
|
9
11
|
/** Field-keyed upload capabilities from the host resource. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../../src/components/config/form/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,WAAW,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAC;AAEpF,MAAM,MAAM,iBAAiB,GAAG,QAAQ,GAAG,QAAQ,CAAC;AAEpD,MAAM,MAAM,eAAe,GAAG;IAC5B,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;IACpC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC/B,MAAM,EAAE,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAC1D,kDAAkD;IAClD,OAAO,CAAC,EAAE,iBAAiB,CAAC;IAC5B,8DAA8D;IAC9D,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,kBAAkB,CAAC,CAAC;IAC7C,sDAAsD;IACtD,QAAQ,CAAC,EAAE,CACT,KAAK,EAAE,MAAM,EACb,KAAK,EAAE,IAAI,EAAE,KACV,OAAO,CAAC,KAAK,CAAC;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC,CAAC;IACpD,aAAa,CAAC,EAAE,IAAI,CAAC,kBAAkB,EAAE,QAAQ,GAAG,UAAU,CAAC,CAAC;IAChE,aAAa,CAAC,EAAE,MAAM,OAAO,CAAC,WAAW,EAAE,CAAC,CAAC;IAC7C,eAAe,CAAC,EAAE,CAAC,KAAK,EAAE,IAAI,EAAE,KAAK,OAAO,CAAC,WAAW,EAAE,CAAC,CAAC;CAC7D,CAAC;AAEF,MAAM,MAAM,UAAU,GAAG,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;AAE/C,MAAM,MAAM,UAAU,GAAG;IACvB,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,UAAU,EAAE,CAAC;CACtB,CAAC;AAEF,MAAM,MAAM,eAAe,GAAG,IAAI,CAChC,eAAe,EACf,eAAe,GAAG,eAAe,GAAG,iBAAiB,CACtD,CAAC"}
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../../src/components/config/form/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,WAAW,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAC;AAEpF,MAAM,MAAM,iBAAiB,GAAG,QAAQ,GAAG,QAAQ,CAAC;AAEpD,MAAM,MAAM,eAAe,GAAG;IAC5B,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;IACpC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC/B,MAAM,EAAE,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAC1D,2DAA2D;IAC3D,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,kDAAkD;IAClD,OAAO,CAAC,EAAE,iBAAiB,CAAC;IAC5B,8DAA8D;IAC9D,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,kBAAkB,CAAC,CAAC;IAC7C,sDAAsD;IACtD,QAAQ,CAAC,EAAE,CACT,KAAK,EAAE,MAAM,EACb,KAAK,EAAE,IAAI,EAAE,KACV,OAAO,CAAC,KAAK,CAAC;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC,CAAC;IACpD,aAAa,CAAC,EAAE,IAAI,CAAC,kBAAkB,EAAE,QAAQ,GAAG,UAAU,CAAC,CAAC;IAChE,aAAa,CAAC,EAAE,MAAM,OAAO,CAAC,WAAW,EAAE,CAAC,CAAC;IAC7C,eAAe,CAAC,EAAE,CAAC,KAAK,EAAE,IAAI,EAAE,KAAK,OAAO,CAAC,WAAW,EAAE,CAAC,CAAC;CAC7D,CAAC;AAEF,MAAM,MAAM,UAAU,GAAG,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;AAE/C,MAAM,MAAM,UAAU,GAAG;IACvB,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,UAAU,EAAE,CAAC;CACtB,CAAC;AAEF,MAAM,MAAM,eAAe,GAAG,IAAI,CAChC,eAAe,EACf,eAAe,GAAG,eAAe,GAAG,iBAAiB,CACtD,CAAC"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { FieldSchema, GalleryItem, ResourceUploadMeta } from "@vertebr/client";
|
|
2
|
+
export type ResourceCreateModalProps = {
|
|
3
|
+
title: string;
|
|
4
|
+
schema: Record<string, FieldSchema>;
|
|
5
|
+
value: Record<string, unknown>;
|
|
6
|
+
uploads?: Record<string, ResourceUploadMeta>;
|
|
7
|
+
onUpload?: (field: string, files: File[]) => Promise<Array<{
|
|
8
|
+
url: string;
|
|
9
|
+
name?: string;
|
|
10
|
+
}>>;
|
|
11
|
+
galleryUpload?: Pick<ResourceUploadMeta, "accept" | "maxBytes">;
|
|
12
|
+
onListGallery?: () => Promise<GalleryItem[]>;
|
|
13
|
+
onUploadGallery?: (files: File[]) => Promise<GalleryItem[]>;
|
|
14
|
+
onClose: () => void;
|
|
15
|
+
onCreate: (value: Record<string, unknown>) => Promise<void>;
|
|
16
|
+
};
|
|
17
|
+
export declare function ResourceCreateModal({ title, schema, value, uploads, onUpload, galleryUpload, onListGallery, onUploadGallery, onClose, onCreate, }: ResourceCreateModalProps): import("react").JSX.Element;
|
|
18
|
+
//# sourceMappingURL=ResourceCreateModal.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ResourceCreateModal.d.ts","sourceRoot":"","sources":["../../../src/components/resources/ResourceCreateModal.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,WAAW,EACX,WAAW,EACX,kBAAkB,EACnB,MAAM,iBAAiB,CAAC;AAGzB,MAAM,MAAM,wBAAwB,GAAG;IACrC,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;IACpC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC/B,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,kBAAkB,CAAC,CAAC;IAC7C,QAAQ,CAAC,EAAE,CACT,KAAK,EAAE,MAAM,EACb,KAAK,EAAE,IAAI,EAAE,KACV,OAAO,CAAC,KAAK,CAAC;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC,CAAC;IACpD,aAAa,CAAC,EAAE,IAAI,CAAC,kBAAkB,EAAE,QAAQ,GAAG,UAAU,CAAC,CAAC;IAChE,aAAa,CAAC,EAAE,MAAM,OAAO,CAAC,WAAW,EAAE,CAAC,CAAC;IAC7C,eAAe,CAAC,EAAE,CAAC,KAAK,EAAE,IAAI,EAAE,KAAK,OAAO,CAAC,WAAW,EAAE,CAAC,CAAC;IAC5D,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB,QAAQ,EAAE,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CAC7D,CAAC;AAEF,wBAAgB,mBAAmB,CAAC,EAClC,KAAK,EACL,MAAM,EACN,KAAK,EACL,OAAO,EACP,QAAQ,EACR,aAAa,EACb,aAAa,EACb,eAAe,EACf,OAAO,EACP,QAAQ,GACT,EAAE,wBAAwB,+BA+D1B"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useEffect } from "react";
|
|
3
|
+
import { ConfigForm } from "../config/ConfigForm";
|
|
4
|
+
export function ResourceCreateModal({ title, schema, value, uploads, onUpload, galleryUpload, onListGallery, onUploadGallery, onClose, onCreate, }) {
|
|
5
|
+
useEffect(() => {
|
|
6
|
+
const onKeyDown = (event) => {
|
|
7
|
+
if (event.key === "Escape")
|
|
8
|
+
onClose();
|
|
9
|
+
};
|
|
10
|
+
window.addEventListener("keydown", onKeyDown);
|
|
11
|
+
const previous = document.body.style.overflow;
|
|
12
|
+
document.body.style.overflow = "hidden";
|
|
13
|
+
return () => {
|
|
14
|
+
window.removeEventListener("keydown", onKeyDown);
|
|
15
|
+
document.body.style.overflow = previous;
|
|
16
|
+
};
|
|
17
|
+
}, [onClose]);
|
|
18
|
+
return (_jsx("div", { className: "vertebr-modal-backdrop", role: "presentation", onClick: onClose, children: _jsxs("div", { className: "vertebr-modal vertebr-modal-form", role: "dialog", "aria-modal": "true", "aria-label": title, onClick: (event) => event.stopPropagation(), children: [_jsxs("header", { className: "vertebr-modal-head", children: [_jsxs("div", { className: "vertebr-modal-heading", children: [_jsx("p", { className: "vertebr-modal-eyebrow", children: "New record" }), _jsx("h2", { children: title })] }), _jsx("div", { className: "vertebr-modal-actions", children: _jsx("button", { type: "button", className: "vertebr-btn", onClick: onClose, "aria-label": "Close", children: "Close" }) })] }), _jsx("div", { className: "vertebr-modal-body", children: _jsx(ConfigForm, { variant: "record", schema: schema, value: value, uploads: uploads, onUpload: onUpload, galleryUpload: galleryUpload, onListGallery: onListGallery, onUploadGallery: onUploadGallery, submitLabel: title, onSave: async (next) => {
|
|
19
|
+
await onCreate(next);
|
|
20
|
+
onClose();
|
|
21
|
+
} }) })] }) }));
|
|
22
|
+
}
|
|
@@ -8,6 +8,8 @@ type ResourcePanelProps = {
|
|
|
8
8
|
delete?: boolean;
|
|
9
9
|
};
|
|
10
10
|
actions?: Record<string, ResourceActionMeta>;
|
|
11
|
+
/** Resource label, e.g. `"Products"` → Add product. */
|
|
12
|
+
label?: string;
|
|
11
13
|
uploads?: Record<string, ResourceUploadMeta>;
|
|
12
14
|
rowIdKeys?: string[];
|
|
13
15
|
/** Persist column visibility under this key (e.g. resource id). */
|
|
@@ -24,7 +26,7 @@ type ResourcePanelProps = {
|
|
|
24
26
|
onListGallery?: () => Promise<GalleryItem[]>;
|
|
25
27
|
onUploadGallery?: (files: File[]) => Promise<GalleryItem[]>;
|
|
26
28
|
};
|
|
27
|
-
export declare function ResourcePanel({ schema, items, permissions, actions, uploads, rowIdKeys, storageKey, onUpdate, onCreate, onDelete, onAction, onUpload, galleryUpload, onListGallery, onUploadGallery, }: ResourcePanelProps): import("react").JSX.Element;
|
|
29
|
+
export declare function ResourcePanel({ schema, items, permissions, actions, label, uploads, rowIdKeys, storageKey, onUpdate, onCreate, onDelete, onAction, onUpload, galleryUpload, onListGallery, onUploadGallery, }: ResourcePanelProps): import("react").JSX.Element;
|
|
28
30
|
/** @deprecated Prefer ResourcePanel */
|
|
29
31
|
export declare function ResourceTable(props: {
|
|
30
32
|
schema: Record<string, FieldSchema>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ResourceTable.d.ts","sourceRoot":"","sources":["../../../src/components/resources/ResourceTable.tsx"],"names":[],"mappings":"AASA,OAAO,KAAK,EACV,WAAW,EACX,WAAW,EACX,kBAAkB,EAClB,kBAAkB,EACnB,MAAM,iBAAiB,CAAC;
|
|
1
|
+
{"version":3,"file":"ResourceTable.d.ts","sourceRoot":"","sources":["../../../src/components/resources/ResourceTable.tsx"],"names":[],"mappings":"AASA,OAAO,KAAK,EACV,WAAW,EACX,WAAW,EACX,kBAAkB,EAClB,kBAAkB,EACnB,MAAM,iBAAiB,CAAC;AAOzB,KAAK,kBAAkB,GAAG;IACxB,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;IACpC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,CAAC;IACjC,WAAW,CAAC,EAAE;QACZ,MAAM,CAAC,EAAE,OAAO,CAAC;QACjB,MAAM,CAAC,EAAE,OAAO,CAAC;QACjB,MAAM,CAAC,EAAE,OAAO,CAAC;KAClB,CAAC;IACF,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,kBAAkB,CAAC,CAAC;IAC7C,uDAAuD;IACvD,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,kBAAkB,CAAC,CAAC;IAC7C,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC;IACrB,mEAAmE;IACnE,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,EAAE,CACT,KAAK,EAAE,MAAM,EACb,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAC3B,OAAO,CAAC,IAAI,CAAC,CAAC;IACnB,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAC7D,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAC5C,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAC9D,QAAQ,CAAC,EAAE,CACT,KAAK,EAAE,MAAM,EACb,KAAK,EAAE,IAAI,EAAE,KACV,OAAO,CAAC,KAAK,CAAC;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC,CAAC;IACpD,aAAa,CAAC,EAAE,IAAI,CAAC,kBAAkB,EAAE,QAAQ,GAAG,UAAU,CAAC,CAAC;IAChE,aAAa,CAAC,EAAE,MAAM,OAAO,CAAC,WAAW,EAAE,CAAC,CAAC;IAC7C,eAAe,CAAC,EAAE,CAAC,KAAK,EAAE,IAAI,EAAE,KAAK,OAAO,CAAC,WAAW,EAAE,CAAC,CAAC;CAC7D,CAAC;AA0EF,wBAAgB,aAAa,CAAC,EAC5B,MAAM,EACN,KAAK,EACL,WAAW,EACX,OAAY,EACZ,KAAK,EACL,OAAO,EACP,SAA0C,EAC1C,UAAU,EACV,QAAQ,EACR,QAAQ,EACR,QAAQ,EACR,QAAQ,EACR,QAAQ,EACR,aAAa,EACb,aAAa,EACb,eAAe,GAChB,EAAE,kBAAkB,+BAqdpB;AAED,uCAAuC;AACvC,wBAAgB,aAAa,CAAC,KAAK,EAAE;IACnC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;IACpC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,CAAC;CAClC,+BAEA"}
|
|
@@ -5,6 +5,7 @@ import { ConfigForm } from "../config/ConfigForm";
|
|
|
5
5
|
import { BulkImageUploadModal } from "./BulkImageUploadModal";
|
|
6
6
|
import { ColumnVisibilityMenu } from "./ColumnVisibilityMenu";
|
|
7
7
|
import { ResourceCell } from "./ResourceCell";
|
|
8
|
+
import { ResourceCreateModal } from "./ResourceCreateModal";
|
|
8
9
|
import { ResourceViewModal } from "./ResourceViewModal";
|
|
9
10
|
function resolveRowId(row, keys) {
|
|
10
11
|
for (const key of keys) {
|
|
@@ -57,6 +58,17 @@ function writeVisibility(storageKey, value) {
|
|
|
57
58
|
/* ignore quota / private mode */
|
|
58
59
|
}
|
|
59
60
|
}
|
|
61
|
+
function addRecordLabel(resourceLabel) {
|
|
62
|
+
const name = resourceLabel?.trim();
|
|
63
|
+
if (!name)
|
|
64
|
+
return "Add record";
|
|
65
|
+
const singular = /ies$/i.test(name)
|
|
66
|
+
? name.replace(/ies$/i, "y")
|
|
67
|
+
: /s$/i.test(name)
|
|
68
|
+
? name.slice(0, -1)
|
|
69
|
+
: name;
|
|
70
|
+
return `Add ${singular.toLowerCase()}`;
|
|
71
|
+
}
|
|
60
72
|
function titleFromFilename(name) {
|
|
61
73
|
return name
|
|
62
74
|
.replace(/\.[^.]+$/, "")
|
|
@@ -64,8 +76,9 @@ function titleFromFilename(name) {
|
|
|
64
76
|
.replace(/\s+/g, " ")
|
|
65
77
|
.trim();
|
|
66
78
|
}
|
|
67
|
-
export function ResourcePanel({ schema, items, permissions, actions = {}, uploads, rowIdKeys = ["id", "slug", "uid", "email"], storageKey, onUpdate, onCreate, onDelete, onAction, onUpload, galleryUpload, onListGallery, onUploadGallery, }) {
|
|
79
|
+
export function ResourcePanel({ schema, items, permissions, actions = {}, label, uploads, rowIdKeys = ["id", "slug", "uid", "email"], storageKey, onUpdate, onCreate, onDelete, onAction, onUpload, galleryUpload, onListGallery, onUploadGallery, }) {
|
|
68
80
|
const [editing, setEditing] = useState(null);
|
|
81
|
+
const [creating, setCreating] = useState(false);
|
|
69
82
|
const [viewing, setViewing] = useState(null);
|
|
70
83
|
const [bulkOpen, setBulkOpen] = useState(false);
|
|
71
84
|
const [busyAction, setBusyAction] = useState(null);
|
|
@@ -79,6 +92,7 @@ export function ResourcePanel({ schema, items, permissions, actions = {}, upload
|
|
|
79
92
|
const canUpdate = Boolean(permissions?.update && onUpdate);
|
|
80
93
|
const canCreate = Boolean(permissions?.create && onCreate);
|
|
81
94
|
const canDelete = Boolean(permissions?.delete && onDelete);
|
|
95
|
+
const createLabel = addRecordLabel(label);
|
|
82
96
|
const canUpload = Boolean(uploads && onUpload && Object.keys(uploads).length);
|
|
83
97
|
const actionEntries = Object.entries(actions);
|
|
84
98
|
const fieldKeys = Object.keys(schema);
|
|
@@ -191,6 +205,23 @@ export function ResourcePanel({ schema, items, permissions, actions = {}, upload
|
|
|
191
205
|
getCoreRowModel: getCoreRowModel(),
|
|
192
206
|
});
|
|
193
207
|
const editingId = editing ? resolveRowId(editing, rowIdKeys) : null;
|
|
208
|
+
const createSchema = Object.fromEntries(Object.entries(schema)
|
|
209
|
+
.filter(([, field]) => !field.readOnly || field.required)
|
|
210
|
+
.map(([key, field]) => [
|
|
211
|
+
key,
|
|
212
|
+
field.readOnly ? { ...field, readOnly: false } : field,
|
|
213
|
+
]));
|
|
214
|
+
const createDefaults = Object.fromEntries(Object.entries(createSchema).map(([key, field]) => [
|
|
215
|
+
key,
|
|
216
|
+
field.default ??
|
|
217
|
+
(field.type === "boolean"
|
|
218
|
+
? false
|
|
219
|
+
: field.type === "number"
|
|
220
|
+
? undefined
|
|
221
|
+
: field.type === "file[]"
|
|
222
|
+
? []
|
|
223
|
+
: ""),
|
|
224
|
+
]));
|
|
194
225
|
if (editing && editingId && onUpdate) {
|
|
195
226
|
const editableSchema = Object.fromEntries(Object.entries(schema).filter(([, field]) => !field.readOnly));
|
|
196
227
|
const title = rowTitle(editing, rowIdKeys);
|
|
@@ -215,10 +246,12 @@ export function ResourcePanel({ schema, items, permissions, actions = {}, upload
|
|
|
215
246
|
}
|
|
216
247
|
}
|
|
217
248
|
: undefined })) : null;
|
|
249
|
+
const createModal = creating && onCreate ? (_jsx(ResourceCreateModal, { title: createLabel, schema: createSchema, value: createDefaults, uploads: uploads, onUpload: onUpload, galleryUpload: galleryUpload, onListGallery: onListGallery, onUploadGallery: onUploadGallery, onClose: () => setCreating(false), onCreate: onCreate })) : null;
|
|
250
|
+
const recordsHead = (_jsxs("div", { className: "vertebr-panel-head", children: [_jsx("h2", { children: "Records" }), _jsxs("div", { className: "vertebr-panel-head-actions", children: [canCreate ? (_jsxs("button", { type: "button", className: "vertebr-btn vertebr-btn-quiet vertebr-btn-icon", onClick: () => setCreating(true), children: [_jsx(PlusIcon, {}), createLabel] })) : null, _jsx("span", { className: "vertebr-count", children: items.length })] })] }));
|
|
218
251
|
if (items.length === 0) {
|
|
219
|
-
return (_jsxs("div", { className: "vertebr-resource-body", children: [
|
|
252
|
+
return (_jsxs("div", { className: "vertebr-resource-body", children: [recordsHead, canUpload || columnOptions.length > 0 ? toolbar : null, _jsx("div", { className: "vertebr-empty", children: "No rows yet." }), bulkModal, createModal] }));
|
|
220
253
|
}
|
|
221
|
-
return (_jsxs("div", { className: "vertebr-resource-body", children: [
|
|
254
|
+
return (_jsxs("div", { className: "vertebr-resource-body", children: [recordsHead, toolbar, _jsx("div", { className: "vertebr-table-wrap", ref: tableWrapRef, "data-overflow": tableOverflow.overflow ? "true" : undefined, "data-overflow-left": tableOverflow.canLeft ? "true" : undefined, "data-overflow-right": tableOverflow.canRight ? "true" : undefined, children: _jsxs("table", { className: "vertebr-table", children: [_jsx("thead", { children: table.getHeaderGroups().map((headerGroup) => (_jsx("tr", { children: headerGroup.headers.map((header) => (_jsx("th", { className: header.column.id === "_actions"
|
|
222
255
|
? "vertebr-col-actions"
|
|
223
256
|
: undefined, children: header.isPlaceholder
|
|
224
257
|
? null
|
|
@@ -232,12 +265,15 @@ export function ResourcePanel({ schema, items, permissions, actions = {}, upload
|
|
|
232
265
|
: undefined, children: flexRender(cell.column.columnDef.cell, cell.getContext()) }, cell.id))) }, row.id))) })] }) }), viewing ? (_jsx(ResourceViewModal, { schema: schema, row: viewing, title: rowTitle(viewing, rowIdKeys), canEdit: canUpdate, onClose: () => setViewing(null), onEdit: () => {
|
|
233
266
|
setEditing(viewing);
|
|
234
267
|
setViewing(null);
|
|
235
|
-
} })) : null, bulkModal] }));
|
|
268
|
+
} })) : null, bulkModal, createModal] }));
|
|
236
269
|
}
|
|
237
270
|
/** @deprecated Prefer ResourcePanel */
|
|
238
271
|
export function ResourceTable(props) {
|
|
239
272
|
return _jsx(ResourcePanel, { ...props });
|
|
240
273
|
}
|
|
274
|
+
function PlusIcon() {
|
|
275
|
+
return (_jsxs("svg", { className: "vertebr-btn-glyph", width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": "true", children: [_jsx("path", { d: "M12 5v14" }), _jsx("path", { d: "M5 12h14" })] }));
|
|
276
|
+
}
|
|
241
277
|
function ChevronLeftIcon() {
|
|
242
278
|
return (_jsx("svg", { className: "vertebr-btn-glyph", width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": "true", children: _jsx("path", { d: "m15 18-6-6 6-6" }) }));
|
|
243
279
|
}
|
package/dist/index.d.ts
CHANGED
|
@@ -17,5 +17,9 @@ export type { VertebrControlsProviderProps } from "./hooks/useVertebrControls";
|
|
|
17
17
|
export { createVertebrClient, VERTEBR_ENV_HEADER, renderMarkdown, } from "@vertebr/client";
|
|
18
18
|
export { VertebrMarkdown } from "@vertebr/client/react";
|
|
19
19
|
export type { VertebrMarkdownProps } from "@vertebr/client/react";
|
|
20
|
+
export { createVertebrCatalog, catalogHref, catalogMatch, } from "@vertebr/client";
|
|
21
|
+
export type { VertebrCatalog, VertebrCatalogOptions, PublicResourceResponse, } from "@vertebr/client";
|
|
22
|
+
export { VertebrCatalogProvider, useVertebrCatalog, useVertebrCatalogItem, } from "@vertebr/client/react";
|
|
23
|
+
export type { VertebrCatalogProviderProps, VertebrCatalogState, } from "@vertebr/client/react";
|
|
20
24
|
export type { VertebrClient, VertebrClientOptions, VertebrReadOptions, AdminEnvironment, BootstrapResponse, CatalogResponse, CatalogResource, CatalogConfig, CatalogConfigSection, EnvironmentAuthPublic, FieldSchema, FieldType, GalleryItem, GalleryMeta, GalleryResponse, MetricCard, MetricsResponse, ResourceListResponse, ResourceActionMeta, ResourceUploadMeta, ResourceUploadResponse, ResourceBulkUploadResponse, ConfigResponse, VertebrControlsMap, } from "@vertebr/client";
|
|
21
25
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,iCAAiC,CAAC;AAC/D,YAAY,EAAE,iBAAiB,EAAE,MAAM,iCAAiC,CAAC;AACzE,OAAO,EAAE,YAAY,EAAE,MAAM,mCAAmC,CAAC;AACjE,OAAO,EAAE,YAAY,EAAE,MAAM,mCAAmC,CAAC;AACjE,OAAO,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,sCAAsC,CAAC;AACpF,OAAO,EAAE,WAAW,EAAE,MAAM,gCAAgC,CAAC;AAC7D,YAAY,EAAE,gBAAgB,EAAE,MAAM,gCAAgC,CAAC;AACvE,OAAO,EAAE,UAAU,EAAE,MAAM,gCAAgC,CAAC;AAC5D,OAAO,EACL,WAAW,EACX,gBAAgB,EAChB,eAAe,EACf,YAAY,EACZ,YAAY,GACb,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,kBAAkB,EAClB,gBAAgB,EAChB,aAAa,GACd,MAAM,mBAAmB,CAAC;AAC3B,YAAY,EAAE,eAAe,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACvE,OAAO,EAAE,SAAS,EAAE,MAAM,4BAA4B,CAAC;AACvD,OAAO,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAC1D,YAAY,EAAE,OAAO,EAAE,MAAM,yBAAyB,CAAC;AACvD,OAAO,EACL,uBAAuB,EACvB,gBAAgB,EAChB,kBAAkB,GACnB,MAAM,4BAA4B,CAAC;AACpC,YAAY,EAAE,4BAA4B,EAAE,MAAM,4BAA4B,CAAC;AAG/E,OAAO,EACL,mBAAmB,EACnB,kBAAkB,EAClB,cAAc,GACf,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AACxD,YAAY,EAAE,oBAAoB,EAAE,MAAM,uBAAuB,CAAC;AAClE,YAAY,EACV,aAAa,EACb,oBAAoB,EACpB,kBAAkB,EAClB,gBAAgB,EAChB,iBAAiB,EACjB,eAAe,EACf,eAAe,EACf,aAAa,EACb,oBAAoB,EACpB,qBAAqB,EACrB,WAAW,EACX,SAAS,EACT,WAAW,EACX,WAAW,EACX,eAAe,EACf,UAAU,EACV,eAAe,EACf,oBAAoB,EACpB,kBAAkB,EAClB,kBAAkB,EAClB,sBAAsB,EACtB,0BAA0B,EAC1B,cAAc,EACd,kBAAkB,GACnB,MAAM,iBAAiB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,iCAAiC,CAAC;AAC/D,YAAY,EAAE,iBAAiB,EAAE,MAAM,iCAAiC,CAAC;AACzE,OAAO,EAAE,YAAY,EAAE,MAAM,mCAAmC,CAAC;AACjE,OAAO,EAAE,YAAY,EAAE,MAAM,mCAAmC,CAAC;AACjE,OAAO,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,sCAAsC,CAAC;AACpF,OAAO,EAAE,WAAW,EAAE,MAAM,gCAAgC,CAAC;AAC7D,YAAY,EAAE,gBAAgB,EAAE,MAAM,gCAAgC,CAAC;AACvE,OAAO,EAAE,UAAU,EAAE,MAAM,gCAAgC,CAAC;AAC5D,OAAO,EACL,WAAW,EACX,gBAAgB,EAChB,eAAe,EACf,YAAY,EACZ,YAAY,GACb,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,kBAAkB,EAClB,gBAAgB,EAChB,aAAa,GACd,MAAM,mBAAmB,CAAC;AAC3B,YAAY,EAAE,eAAe,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACvE,OAAO,EAAE,SAAS,EAAE,MAAM,4BAA4B,CAAC;AACvD,OAAO,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAC1D,YAAY,EAAE,OAAO,EAAE,MAAM,yBAAyB,CAAC;AACvD,OAAO,EACL,uBAAuB,EACvB,gBAAgB,EAChB,kBAAkB,GACnB,MAAM,4BAA4B,CAAC;AACpC,YAAY,EAAE,4BAA4B,EAAE,MAAM,4BAA4B,CAAC;AAG/E,OAAO,EACL,mBAAmB,EACnB,kBAAkB,EAClB,cAAc,GACf,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AACxD,YAAY,EAAE,oBAAoB,EAAE,MAAM,uBAAuB,CAAC;AAClE,OAAO,EACL,oBAAoB,EACpB,WAAW,EACX,YAAY,GACb,MAAM,iBAAiB,CAAC;AACzB,YAAY,EACV,cAAc,EACd,qBAAqB,EACrB,sBAAsB,GACvB,MAAM,iBAAiB,CAAC;AACzB,OAAO,EACL,sBAAsB,EACtB,iBAAiB,EACjB,qBAAqB,GACtB,MAAM,uBAAuB,CAAC;AAC/B,YAAY,EACV,2BAA2B,EAC3B,mBAAmB,GACpB,MAAM,uBAAuB,CAAC;AAC/B,YAAY,EACV,aAAa,EACb,oBAAoB,EACpB,kBAAkB,EAClB,gBAAgB,EAChB,iBAAiB,EACjB,eAAe,EACf,eAAe,EACf,aAAa,EACb,oBAAoB,EACpB,qBAAqB,EACrB,WAAW,EACX,SAAS,EACT,WAAW,EACX,WAAW,EACX,eAAe,EACf,UAAU,EACV,eAAe,EACf,oBAAoB,EACpB,kBAAkB,EAClB,kBAAkB,EAClB,sBAAsB,EACtB,0BAA0B,EAC1B,cAAc,EACd,kBAAkB,GACnB,MAAM,iBAAiB,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -12,3 +12,5 @@ export { VertebrControlsProvider, useVertebrConfig, useVertebrControls, } from "
|
|
|
12
12
|
// Re-export the framework-agnostic client for convenience.
|
|
13
13
|
export { createVertebrClient, VERTEBR_ENV_HEADER, renderMarkdown, } from "@vertebr/client";
|
|
14
14
|
export { VertebrMarkdown } from "@vertebr/client/react";
|
|
15
|
+
export { createVertebrCatalog, catalogHref, catalogMatch, } from "@vertebr/client";
|
|
16
|
+
export { VertebrCatalogProvider, useVertebrCatalog, useVertebrCatalogItem, } from "@vertebr/client/react";
|
package/dist/styles/form.css
CHANGED
|
@@ -84,6 +84,23 @@
|
|
|
84
84
|
gap: 0.65rem;
|
|
85
85
|
}
|
|
86
86
|
|
|
87
|
+
.vertebr-form-fields[data-layout="specs"] {
|
|
88
|
+
grid-template-columns: 1fr 1fr;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
.vertebr-form-fields[data-layout="specs"] .vertebr-field[data-span="full"] {
|
|
92
|
+
grid-column: 1 / -1;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
.vertebr-form-fields[data-layout="specs"] .vertebr-field-head {
|
|
96
|
+
min-height: 1.55rem;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
.vertebr-form-fields[data-layout="specs"] .vertebr-visibility-btn {
|
|
100
|
+
width: 1.85rem;
|
|
101
|
+
height: 1.85rem;
|
|
102
|
+
}
|
|
103
|
+
|
|
87
104
|
.vertebr-form-fields[data-layout="chips"] .vertebr-field label {
|
|
88
105
|
font-family: var(--vb-mono);
|
|
89
106
|
font-size: 0.7rem;
|
|
@@ -164,6 +181,10 @@
|
|
|
164
181
|
}
|
|
165
182
|
|
|
166
183
|
.vertebr-record-block-label {
|
|
184
|
+
display: flex;
|
|
185
|
+
align-items: center;
|
|
186
|
+
justify-content: space-between;
|
|
187
|
+
gap: 0.5rem;
|
|
167
188
|
font-family: var(--vb-mono);
|
|
168
189
|
font-size: 0.68rem;
|
|
169
190
|
font-weight: 500;
|
|
@@ -174,6 +195,40 @@
|
|
|
174
195
|
border-bottom: 1px solid var(--vb-border);
|
|
175
196
|
}
|
|
176
197
|
|
|
198
|
+
.vertebr-record-block[data-storefront="off"] {
|
|
199
|
+
opacity: 0.55;
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
.vertebr-visibility-btn {
|
|
203
|
+
appearance: none;
|
|
204
|
+
flex: none;
|
|
205
|
+
display: inline-flex;
|
|
206
|
+
align-items: center;
|
|
207
|
+
justify-content: center;
|
|
208
|
+
width: 1.7rem;
|
|
209
|
+
height: 1.7rem;
|
|
210
|
+
margin: -0.25rem 0;
|
|
211
|
+
padding: 0;
|
|
212
|
+
border: 0;
|
|
213
|
+
border-radius: 6px;
|
|
214
|
+
background: transparent;
|
|
215
|
+
color: var(--vb-text-subtle);
|
|
216
|
+
cursor: pointer;
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
.vertebr-visibility-btn:hover {
|
|
220
|
+
color: var(--vb-text);
|
|
221
|
+
background: var(--vb-surface-tint);
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
.vertebr-visibility-btn[aria-pressed="true"] {
|
|
225
|
+
color: var(--vb-accent);
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
.vertebr-visibility-btn[aria-pressed="false"] {
|
|
229
|
+
color: var(--vb-text-subtle);
|
|
230
|
+
}
|
|
231
|
+
|
|
177
232
|
.vertebr-form[data-variant="record"] .vertebr-form-fields {
|
|
178
233
|
padding: 0;
|
|
179
234
|
gap: 0.75rem 0.9rem;
|
|
@@ -199,6 +254,96 @@
|
|
|
199
254
|
grid-column: 1 / -1;
|
|
200
255
|
}
|
|
201
256
|
|
|
257
|
+
.vertebr-field-head {
|
|
258
|
+
display: flex;
|
|
259
|
+
align-items: center;
|
|
260
|
+
justify-content: space-between;
|
|
261
|
+
gap: 0.35rem;
|
|
262
|
+
min-height: 1.4rem;
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
.vertebr-field-head label {
|
|
266
|
+
min-width: 0;
|
|
267
|
+
flex: 1 1 auto;
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
.vertebr-field[data-storefront="off"] {
|
|
271
|
+
opacity: 0.55;
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
.vertebr-enum-list {
|
|
275
|
+
margin: 0;
|
|
276
|
+
padding: 0;
|
|
277
|
+
list-style: none;
|
|
278
|
+
display: flex;
|
|
279
|
+
flex-direction: column;
|
|
280
|
+
gap: 0.35rem;
|
|
281
|
+
border: 1px solid var(--vb-border);
|
|
282
|
+
border-radius: var(--vb-radius-sm);
|
|
283
|
+
background: var(--vb-bg);
|
|
284
|
+
overflow: hidden;
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
.vertebr-enum-list-row {
|
|
288
|
+
display: flex;
|
|
289
|
+
align-items: center;
|
|
290
|
+
justify-content: space-between;
|
|
291
|
+
gap: 0.5rem;
|
|
292
|
+
padding: 0.45rem 0.55rem;
|
|
293
|
+
border-bottom: 1px solid var(--vb-border);
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
.vertebr-enum-list-row:last-child {
|
|
297
|
+
border-bottom: 0;
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
.vertebr-enum-list-row[data-on="false"] {
|
|
301
|
+
opacity: 0.55;
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
.vertebr-enum-list-label {
|
|
305
|
+
display: flex;
|
|
306
|
+
align-items: center;
|
|
307
|
+
gap: 0.55rem;
|
|
308
|
+
min-width: 0;
|
|
309
|
+
font-size: 0.86rem;
|
|
310
|
+
font-weight: 500;
|
|
311
|
+
color: var(--vb-text);
|
|
312
|
+
cursor: pointer;
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
.vertebr-enum-list-label input {
|
|
316
|
+
width: 0.95rem;
|
|
317
|
+
height: 0.95rem;
|
|
318
|
+
accent-color: var(--vb-accent);
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
.vertebr-enum-list-move {
|
|
322
|
+
display: flex;
|
|
323
|
+
gap: 0.2rem;
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
.vertebr-enum-list-move button {
|
|
327
|
+
appearance: none;
|
|
328
|
+
width: 1.7rem;
|
|
329
|
+
height: 1.7rem;
|
|
330
|
+
border: 1px solid var(--vb-border);
|
|
331
|
+
border-radius: 6px;
|
|
332
|
+
background: var(--vb-bg-elevated);
|
|
333
|
+
color: var(--vb-text-muted);
|
|
334
|
+
cursor: pointer;
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
.vertebr-enum-list-move button:hover:not(:disabled) {
|
|
338
|
+
color: var(--vb-text);
|
|
339
|
+
border-color: var(--vb-border-strong);
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
.vertebr-enum-list-move button:disabled {
|
|
343
|
+
opacity: 0.4;
|
|
344
|
+
cursor: default;
|
|
345
|
+
}
|
|
346
|
+
|
|
202
347
|
.vertebr-field label,
|
|
203
348
|
.vertebr-field > span {
|
|
204
349
|
font-size: 0.78rem;
|