@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.
Files changed (65) hide show
  1. package/dist/components/admin/VertebrAdmin.d.ts.map +1 -1
  2. package/dist/components/admin/VertebrAdmin.js +1 -1
  3. package/dist/components/config/EnumInput.d.ts +10 -0
  4. package/dist/components/config/EnumInput.d.ts.map +1 -0
  5. package/dist/components/config/EnumInput.js +19 -0
  6. package/dist/components/config/EnumListInput.d.ts +10 -0
  7. package/dist/components/config/EnumListInput.d.ts.map +1 -0
  8. package/dist/components/config/EnumListInput.js +46 -0
  9. package/dist/components/config/VisibilityEye.d.ts +8 -0
  10. package/dist/components/config/VisibilityEye.d.ts.map +1 -0
  11. package/dist/components/config/VisibilityEye.js +18 -0
  12. package/dist/components/config/form/ConfigField.d.ts +2 -1
  13. package/dist/components/config/form/ConfigField.d.ts.map +1 -1
  14. package/dist/components/config/form/ConfigField.js +9 -4
  15. package/dist/components/config/form/ConfigForm.d.ts +1 -1
  16. package/dist/components/config/form/ConfigForm.d.ts.map +1 -1
  17. package/dist/components/config/form/ConfigForm.js +14 -9
  18. package/dist/components/config/form/ConfigFormActions.d.ts +2 -1
  19. package/dist/components/config/form/ConfigFormActions.d.ts.map +1 -1
  20. package/dist/components/config/form/ConfigFormActions.js +2 -2
  21. package/dist/components/config/form/RecordConfigForm.d.ts +2 -1
  22. package/dist/components/config/form/RecordConfigForm.d.ts.map +1 -1
  23. package/dist/components/config/form/RecordConfigForm.js +16 -8
  24. package/dist/components/config/form/SettingsConfigForm.d.ts +2 -1
  25. package/dist/components/config/form/SettingsConfigForm.d.ts.map +1 -1
  26. package/dist/components/config/form/SettingsConfigForm.js +2 -2
  27. package/dist/components/config/form/helpers/fields.d.ts +7 -0
  28. package/dist/components/config/form/helpers/fields.d.ts.map +1 -0
  29. package/dist/components/config/form/helpers/fields.js +31 -0
  30. package/dist/components/config/form/helpers/groups.d.ts +4 -0
  31. package/dist/components/config/form/helpers/groups.d.ts.map +1 -0
  32. package/dist/components/config/form/helpers/groups.js +107 -0
  33. package/dist/components/config/form/helpers/images.d.ts +4 -0
  34. package/dist/components/config/form/helpers/images.d.ts.map +1 -0
  35. package/dist/components/config/form/helpers/images.js +27 -0
  36. package/dist/components/config/form/helpers/index.d.ts +7 -0
  37. package/dist/components/config/form/helpers/index.d.ts.map +1 -0
  38. package/dist/components/config/form/helpers/index.js +6 -0
  39. package/dist/components/config/form/helpers/labels.d.ts +5 -0
  40. package/dist/components/config/form/helpers/labels.d.ts.map +1 -0
  41. package/dist/components/config/form/helpers/labels.js +28 -0
  42. package/dist/components/config/form/helpers/schema.d.ts +8 -0
  43. package/dist/components/config/form/helpers/schema.d.ts.map +1 -0
  44. package/dist/components/config/form/helpers/schema.js +30 -0
  45. package/dist/components/config/form/helpers/visibility.d.ts +13 -0
  46. package/dist/components/config/form/helpers/visibility.d.ts.map +1 -0
  47. package/dist/components/config/form/helpers/visibility.js +86 -0
  48. package/dist/components/config/form/types.d.ts +2 -0
  49. package/dist/components/config/form/types.d.ts.map +1 -1
  50. package/dist/components/resources/ResourceCreateModal.d.ts +18 -0
  51. package/dist/components/resources/ResourceCreateModal.d.ts.map +1 -0
  52. package/dist/components/resources/ResourceCreateModal.js +22 -0
  53. package/dist/components/resources/ResourceTable.d.ts +3 -1
  54. package/dist/components/resources/ResourceTable.d.ts.map +1 -1
  55. package/dist/components/resources/ResourceTable.js +40 -4
  56. package/dist/index.d.ts +4 -0
  57. package/dist/index.d.ts.map +1 -1
  58. package/dist/index.js +2 -0
  59. package/dist/styles/form.css +145 -0
  60. package/dist/styles/modal.css +18 -0
  61. package/dist/styles/panel.css +6 -0
  62. package/package.json +2 -2
  63. package/dist/components/config/form/helpers.d.ts +0 -16
  64. package/dist/components/config/form/helpers.d.ts.map +0 -1
  65. package/dist/components/config/form/helpers.js +0 -186
@@ -25,6 +25,24 @@
25
25
  font-family: var(--vb-font);
26
26
  }
27
27
 
28
+ .vertebr-modal-form {
29
+ width: min(100%, 960px);
30
+ max-height: min(92vh, 920px);
31
+ }
32
+
33
+ .vertebr-modal-form .vertebr-modal-body {
34
+ padding: 0;
35
+ min-height: 0;
36
+ flex: 1 1 auto;
37
+ display: flex;
38
+ flex-direction: column;
39
+ overflow: hidden;
40
+ }
41
+
42
+ .vertebr-modal-form .vertebr-form {
43
+ min-height: 0;
44
+ }
45
+
28
46
  .vertebr-modal-head {
29
47
  display: flex;
30
48
  align-items: flex-start;
@@ -33,6 +33,12 @@
33
33
  color: var(--vb-text-subtle);
34
34
  }
35
35
 
36
+ .vertebr-panel-head-actions {
37
+ display: inline-flex;
38
+ align-items: center;
39
+ gap: 0.55rem;
40
+ }
41
+
36
42
  .vertebr-count {
37
43
  font-family: var(--vb-mono);
38
44
  font-size: 0.7rem;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vertebr/react",
3
- "version": "0.3.0",
3
+ "version": "0.4.0",
4
4
  "description": "Vertebr admin dashboard UI",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -18,7 +18,7 @@
18
18
  "dist"
19
19
  ],
20
20
  "scripts": {
21
- "build": "tsc -p tsconfig.json && rm -rf dist/styles dist/themes && cp src/styles.css dist/styles.css && cp -R src/styles dist/styles && cp -R src/themes dist/themes",
21
+ "build": "rm -rf dist && tsc -p tsconfig.json && cp src/styles.css dist/styles.css && cp -R src/styles dist/styles && cp -R src/themes dist/themes",
22
22
  "typecheck": "tsc -p tsconfig.json --noEmit",
23
23
  "prepublishOnly": "npm run typecheck && npm run build"
24
24
  },
@@ -1,16 +0,0 @@
1
- import { z } from "zod";
2
- import type { FieldSchema } from "@vertebr/client";
3
- import type { ConfigFormVariant, FieldGroup } from "./types";
4
- export declare function buildZodSchema(schema: Record<string, FieldSchema>): z.ZodObject<Record<string, z.ZodTypeAny>, "strip", z.ZodTypeAny, {
5
- [x: string]: any;
6
- }, {
7
- [x: string]: any;
8
- }>;
9
- export declare function humanizeKey(key: string): string;
10
- export declare function isStockField(key: string, field?: FieldSchema): boolean;
11
- export declare function spanFor(key: string, field: FieldSchema, variant: ConfigFormVariant): "wide" | "full" | undefined;
12
- export declare function displayLabel(key: string, field: FieldSchema, group: string): string;
13
- export declare function groupFields(schema: Record<string, FieldSchema>, variant: ConfigFormVariant): FieldGroup[];
14
- export declare function firstImageUrl(value: unknown): string | null;
15
- export declare function findPrimaryImageKey(schema: Record<string, FieldSchema>, values: Record<string, unknown> | undefined): string | null;
16
- //# sourceMappingURL=helpers.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"helpers.d.ts","sourceRoot":"","sources":["../../../../src/components/config/form/helpers.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAGnD,OAAO,KAAK,EACV,iBAAiB,EAEjB,UAAU,EACX,MAAM,SAAS,CAAC;AAWjB,wBAAgB,cAAc,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC;;;;GAyBjE;AAED,wBAAgB,WAAW,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAK/C;AAMD,wBAAgB,YAAY,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,WAAW,GAAG,OAAO,CAGtE;AAED,wBAAgB,OAAO,CACrB,GAAG,EAAE,MAAM,EACX,KAAK,EAAE,WAAW,EAClB,OAAO,EAAE,iBAAiB,GACzB,MAAM,GAAG,MAAM,GAAG,SAAS,CAK7B;AA0CD,wBAAgB,YAAY,CAC1B,GAAG,EAAE,MAAM,EACX,KAAK,EAAE,WAAW,EAClB,KAAK,EAAE,MAAM,GACZ,MAAM,CAcR;AAgBD,wBAAgB,WAAW,CACzB,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,EACnC,OAAO,EAAE,iBAAiB,GACzB,UAAU,EAAE,CA4Cd;AAED,wBAAgB,aAAa,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,GAAG,IAAI,CAU3D;AAED,wBAAgB,mBAAmB,CACjC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,EACnC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,GAC1C,MAAM,GAAG,IAAI,CASf"}
@@ -1,186 +0,0 @@
1
- import { z } from "zod";
2
- import { isDescriptionField } from "../../../lib/description";
3
- import { isImageField, looksLikeUrl } from "../../../lib/images";
4
- const RECORD_GROUP_ORDER = [
5
- "Details",
6
- "Content",
7
- "Pricing",
8
- "Inventory",
9
- "Media",
10
- "Status",
11
- ];
12
- export function buildZodSchema(schema) {
13
- const shape = {};
14
- for (const [key, field] of Object.entries(schema)) {
15
- let zodField;
16
- switch (field.type) {
17
- case "number":
18
- zodField = z.number();
19
- if (field.min != null)
20
- zodField = zodField.min(field.min);
21
- if (field.max != null)
22
- zodField = zodField.max(field.max);
23
- break;
24
- case "boolean":
25
- zodField = z.boolean();
26
- break;
27
- case "file[]":
28
- zodField = z.array(z.string());
29
- break;
30
- default:
31
- zodField = z.string();
32
- }
33
- if (!field.required) {
34
- zodField = zodField.optional();
35
- }
36
- shape[key] = zodField;
37
- }
38
- return z.object(shape);
39
- }
40
- export function humanizeKey(key) {
41
- return key
42
- .replace(/([a-z])([A-Z])/g, "$1 $2")
43
- .replace(/[_-]+/g, " ")
44
- .trim();
45
- }
46
- function escapeRegExp(value) {
47
- return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
48
- }
49
- export function isStockField(key, field) {
50
- const hay = `${key} ${field?.label ?? ""}`;
51
- return /(stock|inventory|qty|quantity)/i.test(hay);
52
- }
53
- export function spanFor(key, field, variant) {
54
- if (field.type === "boolean")
55
- return "full";
56
- if (field.type === "richtext" || isDescriptionField(key, field))
57
- return "full";
58
- if (variant === "record" && isImageField(key, field))
59
- return "full";
60
- return undefined;
61
- }
62
- function inferConfigGroup(key, field) {
63
- if (field.group?.trim())
64
- return field.group.trim();
65
- const source = field.label?.trim() || humanizeKey(key);
66
- const words = source.split(/\s+/).filter(Boolean);
67
- if (words.length >= 2)
68
- return words[0];
69
- return "General";
70
- }
71
- function inferRecordGroup(key, field) {
72
- if (field.group?.trim())
73
- return field.group.trim();
74
- const k = key.toLowerCase();
75
- const label = (field.label ?? "").toLowerCase();
76
- const hay = `${k} ${label}`;
77
- if (/(image|img|photo|avatar|thumbnail|thumb|cover|media_url)/i.test(hay)) {
78
- return "Media";
79
- }
80
- if (/(price|cost|cents|amount|msrp)/i.test(hay)) {
81
- return "Pricing";
82
- }
83
- if (/(stock|inventory|qty|quantity)/i.test(hay)) {
84
- return "Inventory";
85
- }
86
- if (field.type === "boolean" ||
87
- /(^|_)(active|enabled|published|status|visible)(_|$)/i.test(k) ||
88
- /^(active|enabled|published|status|visible)$/i.test(label)) {
89
- return "Status";
90
- }
91
- if (field.type === "richtext" ||
92
- /(description|body|content|summary|bio)/i.test(hay)) {
93
- return "Content";
94
- }
95
- return "Details";
96
- }
97
- export function displayLabel(key, field, group) {
98
- const label = field.label?.trim() || humanizeKey(key);
99
- const stripped = label.replace(new RegExp(`^${escapeRegExp(group)}\\s+`, "i"), "");
100
- if (/^inventory$/i.test(group)) {
101
- const stock = label.replace(/^stock\s+/i, "").trim();
102
- if (stock && stock !== label)
103
- return stock;
104
- }
105
- if (/^pricing$/i.test(group) && /cents/i.test(label)) {
106
- return label.replace(/\s*\(cents\)/i, "").trim() || label;
107
- }
108
- return stripped || label;
109
- }
110
- function sortGroups(groups, variant) {
111
- if (variant !== "record")
112
- return groups;
113
- const rank = (id) => {
114
- const index = RECORD_GROUP_ORDER.indexOf(id);
115
- return index === -1 ? RECORD_GROUP_ORDER.length + 1 : index;
116
- };
117
- return [...groups].sort((a, b) => rank(a.id) - rank(b.id));
118
- }
119
- export function groupFields(schema, variant) {
120
- const order = [];
121
- const map = new Map();
122
- const explicit = new Set();
123
- for (const entry of Object.entries(schema)) {
124
- const [key, field] = entry;
125
- const group = variant === "record"
126
- ? inferRecordGroup(key, field)
127
- : inferConfigGroup(key, field);
128
- if (field.group?.trim())
129
- explicit.add(group);
130
- if (!map.has(group)) {
131
- map.set(group, []);
132
- order.push(group);
133
- }
134
- map.get(group).push(entry);
135
- }
136
- if (variant === "config") {
137
- for (const [group, fields] of [...map.entries()]) {
138
- if (fields.length > 1 || explicit.has(group) || group === "General") {
139
- continue;
140
- }
141
- if (!map.has("General")) {
142
- map.set("General", []);
143
- order.unshift("General");
144
- }
145
- map.get("General").push(...fields);
146
- map.delete(group);
147
- const idx = order.indexOf(group);
148
- if (idx >= 0)
149
- order.splice(idx, 1);
150
- }
151
- }
152
- const groups = order
153
- .filter((id) => map.has(id))
154
- .map((id) => ({
155
- id,
156
- label: id,
157
- fields: map.get(id),
158
- }));
159
- return sortGroups(groups, variant);
160
- }
161
- export function firstImageUrl(value) {
162
- const items = Array.isArray(value) ? value : [value];
163
- for (const item of items) {
164
- if (typeof item === "string" && looksLikeUrl(item))
165
- return item;
166
- if (item && typeof item === "object" && "url" in item) {
167
- const url = item.url;
168
- if (typeof url === "string" && looksLikeUrl(url))
169
- return url;
170
- }
171
- }
172
- return null;
173
- }
174
- export function findPrimaryImageKey(schema, values) {
175
- for (const [key, field] of Object.entries(schema)) {
176
- if (!isImageField(key, field))
177
- continue;
178
- if (firstImageUrl(values?.[key]))
179
- return key;
180
- }
181
- for (const [key, field] of Object.entries(schema)) {
182
- if (isImageField(key, field))
183
- return key;
184
- }
185
- return null;
186
- }