@morphika/andami 0.5.2 → 0.5.3
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 +27 -2
- package/app/admin/layout.tsx +26 -14
- package/app/admin/pages/[slug]/page.tsx +39 -22
- package/app/admin/pages/page.tsx +13 -8
- package/app/admin/projects/page.tsx +17 -8
- package/app/api/admin/assets/register/route.ts +51 -14
- package/app/api/admin/assets/registry/route.ts +4 -1
- package/app/api/admin/assets/relink/confirm/route.ts +4 -1
- package/app/api/admin/assets/relink/route.ts +4 -1
- package/app/api/admin/assets/scan/route.ts +4 -1
- package/app/api/admin/backups/restore-data/route.ts +4 -1
- package/app/api/admin/r2/connect/route.ts +4 -1
- package/app/api/admin/r2/delete/route.ts +4 -1
- package/app/api/admin/r2/rename/route.ts +4 -1
- package/app/api/admin/r2/upload-url/route.ts +4 -1
- package/app/api/admin/revalidate/route.ts +4 -1
- package/app/api/admin/storage/switch/route.ts +4 -1
- package/app/api/custom-sections/[id]/route.ts +5 -6
- package/components/admin/PublishToggle.tsx +2 -2
- package/components/admin/nav-builder/NavGridItem.tsx +4 -2
- package/components/admin/nav-builder/NavSettingsFields.tsx +10 -6
- package/components/admin/styles/ColorsEditor.tsx +7 -6
- package/components/admin/styles/FontsEditor.tsx +3 -1
- package/components/blocks/CoverSectionRenderer.tsx +7 -1
- package/components/blocks/SectionV2Renderer.tsx +8 -1
- package/components/builder/BubbleIcons.tsx +14 -0
- package/components/builder/CanvasMinimap.tsx +66 -49
- package/components/builder/CanvasToolbar.tsx +31 -41
- package/components/builder/SectionEditorBar.tsx +4 -2
- package/components/builder/SectionTypePicker.tsx +4 -2
- package/components/builder/SectionV2Column.tsx +13 -1
- package/components/builder/SettingsPanel.tsx +21 -17
- package/components/builder/SortableBlock.tsx +2 -2
- package/components/builder/SortableRow.tsx +6 -9
- package/components/builder/VirtualAssetGrid.tsx +8 -2
- package/components/builder/asset-browser/R2BrowserContent.tsx +8 -4
- package/components/builder/color-picker/EyedropperButton.tsx +7 -6
- package/components/builder/color-picker/SwatchBar.tsx +11 -6
- package/components/builder/color-picker/UnifiedColorPicker.tsx +11 -6
- package/components/builder/editors/ImageGridBlockEditor.tsx +4 -2
- package/components/builder/editors/MarqueeBlockEditor.tsx +3 -2
- package/components/builder/editors/ProjectGridEditor.tsx +12 -7
- package/components/builder/editors/SpacerBlockEditor.tsx +25 -23
- package/components/builder/editors/TextBlockEditor.tsx +19 -14
- package/components/builder/editors/shared.tsx +4 -2
- package/components/builder/live-preview/LiveImagePreview.tsx +3 -1
- package/components/builder/live-preview/ProjectCardWrapper.tsx +3 -1
- package/components/builder/live-preview/RichTextBubbleMenu.tsx +10 -6
- package/components/builder/live-preview/shared.tsx +5 -2
- package/components/builder/settings-panel/BlockLayoutTab.tsx +4 -2
- package/components/builder/settings-panel/ColumnV2LayoutTab.tsx +242 -0
- package/components/builder/settings-panel/CoverSectionSettings.tsx +4 -2
- package/components/builder/settings-panel/SectionV2Settings.tsx +13 -8
- package/components/builder/settings-panel/index.ts +1 -0
- package/lib/builder/serializer/normalizers.ts +14 -0
- package/lib/builder/serializer/serializers.ts +27 -0
- package/lib/builder/store-sections.ts +21 -0
- package/lib/builder/types-slices.ts +14 -0
- package/lib/sanity/queries.ts +48 -0
- package/lib/sanity/types.ts +14 -0
- package/lib/version.ts +1 -1
- package/package.json +7 -5
- package/sanity/schemas/objects/coverSection.ts +32 -0
- package/sanity/schemas/objects/parallaxSlide.ts +32 -0
- package/sanity/schemas/pageSectionV2.ts +32 -0
|
@@ -31,6 +31,19 @@ export function normalizePageSectionV2(section: Partial<PageSectionV2> & { _key:
|
|
|
31
31
|
// Migrate column-level enter_animation (new field, no old equivalent for columns)
|
|
32
32
|
const colEnterAnimation = colRecord.enter_animation as EnterAnimationConfig | undefined;
|
|
33
33
|
|
|
34
|
+
// Column-level background + border — carry through from Sanity (desktop-only).
|
|
35
|
+
const colLayoutFields: Partial<SectionColumn> = {};
|
|
36
|
+
for (const field of [
|
|
37
|
+
"background_color", "background_opacity", "background_image",
|
|
38
|
+
"background_size", "background_position", "background_repeat",
|
|
39
|
+
"border_color", "border_width", "border_style", "border_sides", "border_radius",
|
|
40
|
+
] as const) {
|
|
41
|
+
const val = colRecord[field];
|
|
42
|
+
if (val !== undefined && val !== null) {
|
|
43
|
+
(colLayoutFields as Record<string, unknown>)[field] = val;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
34
47
|
return {
|
|
35
48
|
_key: col._key || generateKey(),
|
|
36
49
|
grid_column: col.grid_column || 1,
|
|
@@ -55,6 +68,7 @@ export function normalizePageSectionV2(section: Partial<PageSectionV2> & { _key:
|
|
|
55
68
|
return b as ContentBlock;
|
|
56
69
|
}),
|
|
57
70
|
...(colEnterAnimation ? { enter_animation: colEnterAnimation } : {}),
|
|
71
|
+
...colLayoutFields,
|
|
58
72
|
};
|
|
59
73
|
});
|
|
60
74
|
|
|
@@ -134,6 +134,21 @@ function serializePageSectionV2(section: PageSectionV2): Record<string, unknown>
|
|
|
134
134
|
if (col.enter_animation && col.enter_animation.preset && col.enter_animation.preset !== "none") {
|
|
135
135
|
colData.enter_animation = col.enter_animation;
|
|
136
136
|
}
|
|
137
|
+
// Column-level background + border (desktop-only).
|
|
138
|
+
const colLayout = stripUndefined({
|
|
139
|
+
background_color: col.background_color,
|
|
140
|
+
background_opacity: col.background_opacity,
|
|
141
|
+
background_image: col.background_image,
|
|
142
|
+
background_size: col.background_size,
|
|
143
|
+
background_position: col.background_position,
|
|
144
|
+
background_repeat: col.background_repeat,
|
|
145
|
+
border_color: col.border_color,
|
|
146
|
+
border_width: col.border_width,
|
|
147
|
+
border_style: col.border_style,
|
|
148
|
+
border_sides: col.border_sides,
|
|
149
|
+
border_radius: col.border_radius,
|
|
150
|
+
});
|
|
151
|
+
if (colLayout) Object.assign(colData, colLayout);
|
|
137
152
|
return colData;
|
|
138
153
|
}),
|
|
139
154
|
settings: s ? stripUndefined({
|
|
@@ -223,6 +238,18 @@ function serializeCoverSection(section: CoverSection): Record<string, unknown> {
|
|
|
223
238
|
span: col.span,
|
|
224
239
|
blocks: (col.blocks || []).map((b) => serializeBlock(b)),
|
|
225
240
|
enter_animation: col.enter_animation,
|
|
241
|
+
// Column-level background + border (desktop-only).
|
|
242
|
+
background_color: col.background_color,
|
|
243
|
+
background_opacity: col.background_opacity,
|
|
244
|
+
background_image: col.background_image,
|
|
245
|
+
background_size: col.background_size,
|
|
246
|
+
background_position: col.background_position,
|
|
247
|
+
background_repeat: col.background_repeat,
|
|
248
|
+
border_color: col.border_color,
|
|
249
|
+
border_width: col.border_width,
|
|
250
|
+
border_style: col.border_style,
|
|
251
|
+
border_sides: col.border_sides,
|
|
252
|
+
border_radius: col.border_radius,
|
|
226
253
|
} as Record<string, unknown>));
|
|
227
254
|
|
|
228
255
|
return stripUndefined({
|
|
@@ -541,6 +541,27 @@ export function createSectionActions(set: StoreSet, get: StoreGet): SectionSlice
|
|
|
541
541
|
});
|
|
542
542
|
},
|
|
543
543
|
|
|
544
|
+
// Update desktop-level column layout fields (spacing/background/border).
|
|
545
|
+
// Undefined values in `updates` clear that field.
|
|
546
|
+
updateColumnV2Layout: (sectionKey, colKey, updates) => {
|
|
547
|
+
set((state) => {
|
|
548
|
+
const path = findSectionPath(state.rows, sectionKey);
|
|
549
|
+
if (!path) return state;
|
|
550
|
+
const rows = updateSectionAtPath(state.rows, path, (section) => ({
|
|
551
|
+
...section,
|
|
552
|
+
columns: section.columns.map((col) => {
|
|
553
|
+
if (col._key !== colKey) return col;
|
|
554
|
+
const merged = { ...col, ...updates };
|
|
555
|
+
for (const [k, v] of Object.entries(updates)) {
|
|
556
|
+
if (v === undefined) delete (merged as Record<string, unknown>)[k];
|
|
557
|
+
}
|
|
558
|
+
return merged;
|
|
559
|
+
}),
|
|
560
|
+
}));
|
|
561
|
+
return { rows, isDirty: true };
|
|
562
|
+
});
|
|
563
|
+
},
|
|
564
|
+
|
|
544
565
|
// ---- Custom Section Instance operations (Session 108) ----
|
|
545
566
|
|
|
546
567
|
addCustomSectionInstance: (
|
|
@@ -31,6 +31,7 @@ import type {
|
|
|
31
31
|
PageSectionV2,
|
|
32
32
|
SectionV2Settings,
|
|
33
33
|
SectionV2Preset,
|
|
34
|
+
SectionColumn,
|
|
34
35
|
PageMetadata,
|
|
35
36
|
ColorField,
|
|
36
37
|
CoverSection,
|
|
@@ -168,6 +169,19 @@ export interface SectionSliceActions {
|
|
|
168
169
|
colKey: string,
|
|
169
170
|
config: import("../../lib/animation/enter-types").EnterAnimationConfig | undefined,
|
|
170
171
|
) => void;
|
|
172
|
+
/** Update desktop-level layout fields on a V2/cover/parallax-slide column.
|
|
173
|
+
* Columns only support background + border — spacing belongs to the
|
|
174
|
+
* section (row_gap/col_gap) or to block-level padding. */
|
|
175
|
+
updateColumnV2Layout: (
|
|
176
|
+
sectionKey: string,
|
|
177
|
+
colKey: string,
|
|
178
|
+
updates: Partial<Pick<
|
|
179
|
+
SectionColumn,
|
|
180
|
+
| "background_color" | "background_opacity" | "background_image"
|
|
181
|
+
| "background_size" | "background_position" | "background_repeat"
|
|
182
|
+
| "border_color" | "border_width" | "border_style" | "border_sides" | "border_radius"
|
|
183
|
+
>>,
|
|
184
|
+
) => void;
|
|
171
185
|
|
|
172
186
|
/** Select a V2 column — sets selectedRowKey + selectedColumnKey. */
|
|
173
187
|
selectColumnV2: (sectionKey: string | null, columnKey: string | null) => void;
|
package/lib/sanity/queries.ts
CHANGED
|
@@ -20,6 +20,18 @@ const blockExpansion = `
|
|
|
20
20
|
grid_row,
|
|
21
21
|
span,
|
|
22
22
|
enter_animation,
|
|
23
|
+
// Column-level background + border (Session 184)
|
|
24
|
+
background_color,
|
|
25
|
+
background_opacity,
|
|
26
|
+
background_image,
|
|
27
|
+
background_size,
|
|
28
|
+
background_position,
|
|
29
|
+
background_repeat,
|
|
30
|
+
border_color,
|
|
31
|
+
border_width,
|
|
32
|
+
border_style,
|
|
33
|
+
border_sides,
|
|
34
|
+
border_radius,
|
|
23
35
|
blocks[] {
|
|
24
36
|
_type,
|
|
25
37
|
_key,
|
|
@@ -60,6 +72,18 @@ const blockExpansion = `
|
|
|
60
72
|
grid_column,
|
|
61
73
|
grid_row,
|
|
62
74
|
span,
|
|
75
|
+
// Column-level background + border (Session 184)
|
|
76
|
+
background_color,
|
|
77
|
+
background_opacity,
|
|
78
|
+
background_image,
|
|
79
|
+
background_size,
|
|
80
|
+
background_position,
|
|
81
|
+
background_repeat,
|
|
82
|
+
border_color,
|
|
83
|
+
border_width,
|
|
84
|
+
border_style,
|
|
85
|
+
border_sides,
|
|
86
|
+
border_radius,
|
|
63
87
|
blocks[] {
|
|
64
88
|
_type,
|
|
65
89
|
_key,
|
|
@@ -429,6 +453,18 @@ export const customSectionBySlugQuery = groq`
|
|
|
429
453
|
grid_column,
|
|
430
454
|
grid_row,
|
|
431
455
|
span,
|
|
456
|
+
enter_animation,
|
|
457
|
+
background_color,
|
|
458
|
+
background_opacity,
|
|
459
|
+
background_image,
|
|
460
|
+
background_size,
|
|
461
|
+
background_position,
|
|
462
|
+
background_repeat,
|
|
463
|
+
border_color,
|
|
464
|
+
border_width,
|
|
465
|
+
border_style,
|
|
466
|
+
border_sides,
|
|
467
|
+
border_radius,
|
|
432
468
|
blocks[] {
|
|
433
469
|
_type,
|
|
434
470
|
_key,
|
|
@@ -456,6 +492,18 @@ export const customSectionByIdQuery = groq`
|
|
|
456
492
|
grid_column,
|
|
457
493
|
grid_row,
|
|
458
494
|
span,
|
|
495
|
+
enter_animation,
|
|
496
|
+
background_color,
|
|
497
|
+
background_opacity,
|
|
498
|
+
background_image,
|
|
499
|
+
background_size,
|
|
500
|
+
background_position,
|
|
501
|
+
background_repeat,
|
|
502
|
+
border_color,
|
|
503
|
+
border_width,
|
|
504
|
+
border_style,
|
|
505
|
+
border_sides,
|
|
506
|
+
border_radius,
|
|
459
507
|
blocks[] {
|
|
460
508
|
_type,
|
|
461
509
|
_key,
|
package/lib/sanity/types.ts
CHANGED
|
@@ -559,6 +559,20 @@ export interface SectionColumn {
|
|
|
559
559
|
blocks: ContentBlock[]; // same block types as today
|
|
560
560
|
// NEW (Session 116) — column-level enter animation for 4-level cascade
|
|
561
561
|
enter_animation?: import("../../lib/animation/enter-types").EnterAnimationConfig;
|
|
562
|
+
// Column-level layout — desktop-only for now. Background + border only
|
|
563
|
+
// (no spacing — section row_gap/col_gap + block padding cover that).
|
|
564
|
+
// Viewport overrides are TBD: the current ColumnOverride type is position-only.
|
|
565
|
+
background_color?: string;
|
|
566
|
+
background_opacity?: number;
|
|
567
|
+
background_image?: string;
|
|
568
|
+
background_size?: string;
|
|
569
|
+
background_position?: string;
|
|
570
|
+
background_repeat?: string;
|
|
571
|
+
border_color?: string;
|
|
572
|
+
border_width?: string;
|
|
573
|
+
border_style?: string;
|
|
574
|
+
border_sides?: string;
|
|
575
|
+
border_radius?: string;
|
|
562
576
|
}
|
|
563
577
|
|
|
564
578
|
export interface ColumnOverride {
|
package/lib/version.ts
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@morphika/andami",
|
|
3
|
-
"version": "0.5.
|
|
3
|
+
"version": "0.5.3",
|
|
4
4
|
"description": "Visual Page Builder — core library. A reusable website builder with visual editing, CMS integration, and asset management.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -193,7 +193,6 @@
|
|
|
193
193
|
"react-dom": ">=19.0.0"
|
|
194
194
|
},
|
|
195
195
|
"dependencies": {
|
|
196
|
-
"archiver": "^7.0.1",
|
|
197
196
|
"@aws-sdk/client-s3": "^3.1021.0",
|
|
198
197
|
"@aws-sdk/s3-request-presigner": "^3.1021.0",
|
|
199
198
|
"@dnd-kit/core": "^6.3.1",
|
|
@@ -210,10 +209,11 @@
|
|
|
210
209
|
"@tiptap/starter-kit": "^2.12.0",
|
|
211
210
|
"@types/archiver": "^6.0.3",
|
|
212
211
|
"@types/unzipper": "^0.10.10",
|
|
212
|
+
"archiver": "^7.0.1",
|
|
213
213
|
"jszip": "^3.10.1",
|
|
214
|
-
"next-sanity": "^12.
|
|
214
|
+
"next-sanity": "^12.3.0",
|
|
215
215
|
"ogl": "^1.0.8",
|
|
216
|
-
"sanity": "^5.
|
|
216
|
+
"sanity": "^5.21.0",
|
|
217
217
|
"unzipper": "^0.12.3",
|
|
218
218
|
"zustand": "^5.0.12"
|
|
219
219
|
},
|
|
@@ -228,10 +228,12 @@
|
|
|
228
228
|
"@types/react-dom": "^19",
|
|
229
229
|
"eslint": "^9",
|
|
230
230
|
"eslint-config-next": "16.2.1",
|
|
231
|
+
"framer-motion": "^12.38.0",
|
|
231
232
|
"jsdom": "^26.1.0",
|
|
232
|
-
"next": "16.2.
|
|
233
|
+
"next": "^16.2.4",
|
|
233
234
|
"react": "19.2.4",
|
|
234
235
|
"react-dom": "19.2.4",
|
|
236
|
+
"styled-components": "^6.4.0",
|
|
235
237
|
"tailwindcss": "^4",
|
|
236
238
|
"typescript": "^5",
|
|
237
239
|
"vitest": "^4.1.2"
|
|
@@ -50,6 +50,38 @@ const columnFields = [
|
|
|
50
50
|
title: "Enter Animation",
|
|
51
51
|
type: "enterAnimationConfig",
|
|
52
52
|
}),
|
|
53
|
+
// Column-level layout — desktop-only, background + border only.
|
|
54
|
+
defineField({ name: "background_color", title: "Background Color", type: "string" }),
|
|
55
|
+
defineField({ name: "background_opacity", title: "Background Opacity", type: "number" }),
|
|
56
|
+
defineField({ name: "background_image", title: "Background Image", type: "string" }),
|
|
57
|
+
defineField({
|
|
58
|
+
name: "background_size",
|
|
59
|
+
title: "Background Size",
|
|
60
|
+
type: "string",
|
|
61
|
+
options: { list: ["cover", "contain", "auto"] },
|
|
62
|
+
}),
|
|
63
|
+
defineField({ name: "background_position", title: "Background Position", type: "string" }),
|
|
64
|
+
defineField({
|
|
65
|
+
name: "background_repeat",
|
|
66
|
+
title: "Background Repeat",
|
|
67
|
+
type: "string",
|
|
68
|
+
options: { list: ["no-repeat", "repeat", "repeat-x", "repeat-y"] },
|
|
69
|
+
}),
|
|
70
|
+
defineField({ name: "border_color", title: "Border Color", type: "string" }),
|
|
71
|
+
defineField({ name: "border_width", title: "Border Width", type: "string" }),
|
|
72
|
+
defineField({
|
|
73
|
+
name: "border_style",
|
|
74
|
+
title: "Border Style",
|
|
75
|
+
type: "string",
|
|
76
|
+
options: { list: ["none", "solid", "dashed", "dotted"] },
|
|
77
|
+
}),
|
|
78
|
+
defineField({
|
|
79
|
+
name: "border_sides",
|
|
80
|
+
title: "Border Sides",
|
|
81
|
+
type: "string",
|
|
82
|
+
options: { list: ["all", "top", "right", "bottom", "left", "top-bottom", "left-right"] },
|
|
83
|
+
}),
|
|
84
|
+
defineField({ name: "border_radius", title: "Border Radius", type: "string" }),
|
|
53
85
|
];
|
|
54
86
|
|
|
55
87
|
const responsiveColumnOverrideFields = [
|
|
@@ -115,6 +115,38 @@ export default defineType({
|
|
|
115
115
|
title: "Enter Animation",
|
|
116
116
|
type: "enterAnimationConfig",
|
|
117
117
|
}),
|
|
118
|
+
// Column-level layout — desktop-only, background + border only.
|
|
119
|
+
defineField({ name: "background_color", title: "Background Color", type: "string" }),
|
|
120
|
+
defineField({ name: "background_opacity", title: "Background Opacity", type: "number" }),
|
|
121
|
+
defineField({ name: "background_image", title: "Background Image", type: "string" }),
|
|
122
|
+
defineField({
|
|
123
|
+
name: "background_size",
|
|
124
|
+
title: "Background Size",
|
|
125
|
+
type: "string",
|
|
126
|
+
options: { list: ["cover", "contain", "auto"] },
|
|
127
|
+
}),
|
|
128
|
+
defineField({ name: "background_position", title: "Background Position", type: "string" }),
|
|
129
|
+
defineField({
|
|
130
|
+
name: "background_repeat",
|
|
131
|
+
title: "Background Repeat",
|
|
132
|
+
type: "string",
|
|
133
|
+
options: { list: ["no-repeat", "repeat", "repeat-x", "repeat-y"] },
|
|
134
|
+
}),
|
|
135
|
+
defineField({ name: "border_color", title: "Border Color", type: "string" }),
|
|
136
|
+
defineField({ name: "border_width", title: "Border Width", type: "string" }),
|
|
137
|
+
defineField({
|
|
138
|
+
name: "border_style",
|
|
139
|
+
title: "Border Style",
|
|
140
|
+
type: "string",
|
|
141
|
+
options: { list: ["none", "solid", "dashed", "dotted"] },
|
|
142
|
+
}),
|
|
143
|
+
defineField({
|
|
144
|
+
name: "border_sides",
|
|
145
|
+
title: "Border Sides",
|
|
146
|
+
type: "string",
|
|
147
|
+
options: { list: ["all", "top", "right", "bottom", "left", "top-bottom", "left-right"] },
|
|
148
|
+
}),
|
|
149
|
+
defineField({ name: "border_radius", title: "Border Radius", type: "string" }),
|
|
118
150
|
],
|
|
119
151
|
},
|
|
120
152
|
],
|
|
@@ -76,6 +76,38 @@ export default defineType({
|
|
|
76
76
|
title: "Enter Animation",
|
|
77
77
|
type: "enterAnimationConfig",
|
|
78
78
|
}),
|
|
79
|
+
// Column-level layout — desktop-only, background + border only.
|
|
80
|
+
defineField({ name: "background_color", title: "Background Color", type: "string" }),
|
|
81
|
+
defineField({ name: "background_opacity", title: "Background Opacity", type: "number" }),
|
|
82
|
+
defineField({ name: "background_image", title: "Background Image", type: "string" }),
|
|
83
|
+
defineField({
|
|
84
|
+
name: "background_size",
|
|
85
|
+
title: "Background Size",
|
|
86
|
+
type: "string",
|
|
87
|
+
options: { list: ["cover", "contain", "auto"] },
|
|
88
|
+
}),
|
|
89
|
+
defineField({ name: "background_position", title: "Background Position", type: "string" }),
|
|
90
|
+
defineField({
|
|
91
|
+
name: "background_repeat",
|
|
92
|
+
title: "Background Repeat",
|
|
93
|
+
type: "string",
|
|
94
|
+
options: { list: ["no-repeat", "repeat", "repeat-x", "repeat-y"] },
|
|
95
|
+
}),
|
|
96
|
+
defineField({ name: "border_color", title: "Border Color", type: "string" }),
|
|
97
|
+
defineField({ name: "border_width", title: "Border Width", type: "string" }),
|
|
98
|
+
defineField({
|
|
99
|
+
name: "border_style",
|
|
100
|
+
title: "Border Style",
|
|
101
|
+
type: "string",
|
|
102
|
+
options: { list: ["none", "solid", "dashed", "dotted"] },
|
|
103
|
+
}),
|
|
104
|
+
defineField({
|
|
105
|
+
name: "border_sides",
|
|
106
|
+
title: "Border Sides",
|
|
107
|
+
type: "string",
|
|
108
|
+
options: { list: ["all", "top", "right", "bottom", "left", "top-bottom", "left-right"] },
|
|
109
|
+
}),
|
|
110
|
+
defineField({ name: "border_radius", title: "Border Radius", type: "string" }),
|
|
79
111
|
],
|
|
80
112
|
},
|
|
81
113
|
],
|