@orion-studios/payload-blocks 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/dist/index.mjs ADDED
@@ -0,0 +1,803 @@
1
+ // src/blocks/adminComponents.ts
2
+ var builderBlockLabelComponent = {
3
+ exportName: "BuilderBlockLabel",
4
+ path: "./components/admin/BuilderBlockLabel.tsx"
5
+ };
6
+
7
+ // src/blocks/BookingEmbed.ts
8
+ var BookingEmbedBlock = {
9
+ slug: "bookingEmbed",
10
+ imageURL: "/images/service-removal.svg",
11
+ imageAltText: "Booking embed section preview",
12
+ admin: {
13
+ components: {
14
+ Label: builderBlockLabelComponent
15
+ }
16
+ },
17
+ labels: {
18
+ singular: "Booking Embed",
19
+ plural: "Booking Embeds"
20
+ },
21
+ fields: [
22
+ {
23
+ name: "title",
24
+ type: "text"
25
+ },
26
+ {
27
+ name: "description",
28
+ type: "textarea"
29
+ },
30
+ {
31
+ name: "buttonLabel",
32
+ type: "text",
33
+ defaultValue: "Book Consultation"
34
+ },
35
+ {
36
+ name: "buttonHref",
37
+ type: "text",
38
+ defaultValue: "/contact"
39
+ }
40
+ ]
41
+ };
42
+
43
+ // src/blocks/Cta.ts
44
+ var CtaBlock = {
45
+ slug: "cta",
46
+ imageURL: "/images/logo-mark.svg",
47
+ imageAltText: "Call to action section preview",
48
+ admin: {
49
+ components: {
50
+ Label: builderBlockLabelComponent
51
+ }
52
+ },
53
+ labels: {
54
+ singular: "CTA",
55
+ plural: "CTAs"
56
+ },
57
+ fields: [
58
+ {
59
+ name: "headline",
60
+ type: "text",
61
+ required: true
62
+ },
63
+ {
64
+ name: "description",
65
+ type: "textarea"
66
+ },
67
+ {
68
+ name: "buttonLabel",
69
+ type: "text"
70
+ },
71
+ {
72
+ name: "buttonHref",
73
+ type: "text",
74
+ admin: {
75
+ description: "Use internal links like /contact."
76
+ }
77
+ },
78
+ {
79
+ name: "style",
80
+ type: "select",
81
+ defaultValue: "light",
82
+ options: [
83
+ {
84
+ label: "Light",
85
+ value: "light"
86
+ },
87
+ {
88
+ label: "Dark",
89
+ value: "dark"
90
+ }
91
+ ]
92
+ },
93
+ {
94
+ name: "backgroundColor",
95
+ type: "text",
96
+ admin: {
97
+ description: "Optional background color override for the CTA strip (example: #124a37)."
98
+ }
99
+ }
100
+ ]
101
+ };
102
+
103
+ // src/blocks/Faq.ts
104
+ var FaqBlock = {
105
+ slug: "faq",
106
+ imageURL: "/images/project-before-2.svg",
107
+ imageAltText: "FAQ section preview",
108
+ admin: {
109
+ components: {
110
+ Label: builderBlockLabelComponent
111
+ }
112
+ },
113
+ labels: {
114
+ singular: "FAQ",
115
+ plural: "FAQs"
116
+ },
117
+ fields: [
118
+ {
119
+ name: "title",
120
+ type: "text",
121
+ required: true
122
+ },
123
+ {
124
+ name: "items",
125
+ type: "array",
126
+ minRows: 1,
127
+ maxRows: 12,
128
+ fields: [
129
+ {
130
+ name: "question",
131
+ type: "text",
132
+ required: true
133
+ },
134
+ {
135
+ name: "answer",
136
+ type: "textarea",
137
+ required: true
138
+ }
139
+ ]
140
+ }
141
+ ]
142
+ };
143
+
144
+ // src/blocks/FeatureGrid.ts
145
+ var FeatureGridBlock = {
146
+ slug: "featureGrid",
147
+ imageURL: "/images/service-trimming.svg",
148
+ imageAltText: "Feature grid section preview",
149
+ admin: {
150
+ components: {
151
+ Label: builderBlockLabelComponent
152
+ }
153
+ },
154
+ labels: {
155
+ singular: "Feature Grid",
156
+ plural: "Feature Grids"
157
+ },
158
+ fields: [
159
+ {
160
+ name: "title",
161
+ type: "text",
162
+ required: true
163
+ },
164
+ {
165
+ name: "items",
166
+ type: "array",
167
+ minRows: 1,
168
+ maxRows: 6,
169
+ fields: [
170
+ {
171
+ name: "title",
172
+ type: "text",
173
+ required: true
174
+ },
175
+ {
176
+ name: "description",
177
+ type: "textarea"
178
+ },
179
+ {
180
+ name: "icon",
181
+ type: "text",
182
+ admin: {
183
+ description: 'Optional short icon label (e.g. "01", "Leaf", "Star").'
184
+ }
185
+ }
186
+ ]
187
+ },
188
+ {
189
+ name: "variant",
190
+ type: "select",
191
+ defaultValue: "cards",
192
+ options: [
193
+ {
194
+ label: "Cards",
195
+ value: "cards"
196
+ },
197
+ {
198
+ label: "Highlight",
199
+ value: "highlight"
200
+ }
201
+ ]
202
+ },
203
+ {
204
+ name: "backgroundColor",
205
+ type: "text",
206
+ admin: {
207
+ description: "Optional background color override when using the Highlight variant (example: #1f684f)."
208
+ }
209
+ }
210
+ ]
211
+ };
212
+
213
+ // src/blocks/FormEmbed.ts
214
+ var FormEmbedBlock = {
215
+ slug: "formEmbed",
216
+ imageURL: "/images/map-placeholder.svg",
217
+ imageAltText: "Form embed section preview",
218
+ admin: {
219
+ components: {
220
+ Label: builderBlockLabelComponent
221
+ }
222
+ },
223
+ labels: {
224
+ singular: "Form Embed",
225
+ plural: "Form Embeds"
226
+ },
227
+ fields: [
228
+ {
229
+ name: "title",
230
+ type: "text"
231
+ },
232
+ {
233
+ name: "description",
234
+ type: "textarea"
235
+ },
236
+ {
237
+ name: "formType",
238
+ type: "select",
239
+ defaultValue: "quote",
240
+ options: [
241
+ {
242
+ label: "Quote Form",
243
+ value: "quote"
244
+ }
245
+ ]
246
+ }
247
+ ]
248
+ };
249
+
250
+ // src/blocks/Hero.ts
251
+ var HeroBlock = {
252
+ slug: "hero",
253
+ imageURL: "/images/hero-tree.svg",
254
+ imageAltText: "Hero section preview",
255
+ admin: {
256
+ components: {
257
+ Label: builderBlockLabelComponent
258
+ }
259
+ },
260
+ labels: {
261
+ singular: "Hero",
262
+ plural: "Hero Sections"
263
+ },
264
+ fields: [
265
+ {
266
+ name: "kicker",
267
+ type: "text",
268
+ admin: {
269
+ description: "Optional short label above the headline."
270
+ }
271
+ },
272
+ {
273
+ name: "headline",
274
+ type: "text",
275
+ required: true
276
+ },
277
+ {
278
+ name: "subheadline",
279
+ type: "textarea"
280
+ },
281
+ {
282
+ name: "primaryLabel",
283
+ type: "text"
284
+ },
285
+ {
286
+ name: "primaryHref",
287
+ type: "text",
288
+ admin: {
289
+ description: "Use internal links like /contact."
290
+ }
291
+ },
292
+ {
293
+ name: "secondaryLabel",
294
+ type: "text"
295
+ },
296
+ {
297
+ name: "secondaryHref",
298
+ type: "text",
299
+ admin: {
300
+ description: "Use internal links like /services."
301
+ }
302
+ },
303
+ {
304
+ name: "media",
305
+ type: "upload",
306
+ relationTo: "media"
307
+ },
308
+ {
309
+ name: "backgroundImageURL",
310
+ type: "text",
311
+ admin: {
312
+ description: "Optional external/background image URL override for this hero section."
313
+ }
314
+ },
315
+ {
316
+ name: "backgroundColor",
317
+ type: "text",
318
+ admin: {
319
+ description: "Optional background color override (example: #124a37)."
320
+ }
321
+ },
322
+ {
323
+ name: "variant",
324
+ type: "select",
325
+ defaultValue: "default",
326
+ options: [
327
+ {
328
+ label: "Default",
329
+ value: "default"
330
+ },
331
+ {
332
+ label: "Centered",
333
+ value: "centered"
334
+ }
335
+ ]
336
+ }
337
+ ]
338
+ };
339
+
340
+ // src/blocks/Media.ts
341
+ var MediaBlock = {
342
+ slug: "media",
343
+ imageURL: "/images/project-after-1.svg",
344
+ imageAltText: "Media section preview",
345
+ admin: {
346
+ components: {
347
+ Label: builderBlockLabelComponent
348
+ }
349
+ },
350
+ labels: {
351
+ singular: "Media",
352
+ plural: "Media Sections"
353
+ },
354
+ fields: [
355
+ {
356
+ name: "image",
357
+ type: "upload",
358
+ relationTo: "media",
359
+ required: true
360
+ },
361
+ {
362
+ name: "caption",
363
+ type: "text"
364
+ },
365
+ {
366
+ name: "size",
367
+ type: "select",
368
+ defaultValue: "default",
369
+ options: [
370
+ {
371
+ label: "Default",
372
+ value: "default"
373
+ },
374
+ {
375
+ label: "Wide",
376
+ value: "wide"
377
+ }
378
+ ]
379
+ }
380
+ ]
381
+ };
382
+
383
+ // src/blocks/RichText.ts
384
+ var RichTextBlock = {
385
+ slug: "richText",
386
+ imageURL: "/window.svg",
387
+ imageAltText: "Rich text section preview",
388
+ admin: {
389
+ components: {
390
+ Label: builderBlockLabelComponent
391
+ }
392
+ },
393
+ labels: {
394
+ singular: "Rich Text",
395
+ plural: "Rich Text Sections"
396
+ },
397
+ fields: [
398
+ {
399
+ name: "title",
400
+ type: "text"
401
+ },
402
+ {
403
+ name: "content",
404
+ type: "richText",
405
+ required: true
406
+ },
407
+ {
408
+ name: "width",
409
+ type: "select",
410
+ defaultValue: "normal",
411
+ options: [
412
+ {
413
+ label: "Normal",
414
+ value: "normal"
415
+ },
416
+ {
417
+ label: "Narrow",
418
+ value: "narrow"
419
+ }
420
+ ]
421
+ }
422
+ ]
423
+ };
424
+
425
+ // src/blocks/Testimonials.ts
426
+ var TestimonialsBlock = {
427
+ slug: "testimonials",
428
+ imageURL: "/images/project-after-2.svg",
429
+ imageAltText: "Testimonials section preview",
430
+ admin: {
431
+ components: {
432
+ Label: builderBlockLabelComponent
433
+ }
434
+ },
435
+ labels: {
436
+ singular: "Testimonials",
437
+ plural: "Testimonials"
438
+ },
439
+ fields: [
440
+ {
441
+ name: "title",
442
+ type: "text",
443
+ required: true
444
+ },
445
+ {
446
+ name: "items",
447
+ type: "array",
448
+ minRows: 1,
449
+ maxRows: 6,
450
+ fields: [
451
+ {
452
+ name: "quote",
453
+ type: "textarea",
454
+ required: true
455
+ },
456
+ {
457
+ name: "name",
458
+ type: "text",
459
+ required: true
460
+ },
461
+ {
462
+ name: "location",
463
+ type: "text"
464
+ }
465
+ ]
466
+ }
467
+ ]
468
+ };
469
+
470
+ // src/components/BuilderBlockLabel.tsx
471
+ import { jsx, jsxs } from "react/jsx-runtime";
472
+ var blockTitles = {
473
+ bookingEmbed: "Booking Embed",
474
+ cta: "Call to Action",
475
+ faq: "FAQ",
476
+ featureGrid: "Feature Grid",
477
+ formEmbed: "Form Embed",
478
+ hero: "Hero",
479
+ media: "Media",
480
+ richText: "Rich Text",
481
+ testimonials: "Testimonials"
482
+ };
483
+ var blockEmojis = {
484
+ bookingEmbed: "Calendar",
485
+ cta: "Action",
486
+ faq: "FAQ",
487
+ featureGrid: "Grid",
488
+ formEmbed: "Form",
489
+ hero: "Hero",
490
+ media: "Media",
491
+ richText: "Text",
492
+ testimonials: "Reviews"
493
+ };
494
+ function BuilderBlockLabel({ blockType, rowLabel, rowNumber }) {
495
+ const fallbackTitle = blockTitles[blockType] || blockType;
496
+ const title = rowLabel && rowLabel.trim().length > 0 ? rowLabel : fallbackTitle;
497
+ const tag = blockEmojis[blockType] || "Section";
498
+ return /* @__PURE__ */ jsxs("div", { style: { alignItems: "center", display: "flex", gap: 8 }, children: [
499
+ /* @__PURE__ */ jsx(
500
+ "span",
501
+ {
502
+ style: {
503
+ background: "var(--theme-elevation-100)",
504
+ border: "1px solid var(--theme-elevation-200)",
505
+ borderRadius: 999,
506
+ color: "var(--theme-text-muted)",
507
+ fontSize: 11,
508
+ fontWeight: 700,
509
+ padding: "2px 8px"
510
+ },
511
+ children: tag
512
+ }
513
+ ),
514
+ /* @__PURE__ */ jsxs("span", { style: { fontWeight: 700 }, children: [
515
+ typeof rowNumber === "number" ? `${rowNumber + 1}. ` : "",
516
+ title
517
+ ] })
518
+ ] });
519
+ }
520
+
521
+ // src/presets/index.ts
522
+ var sectionPresets = [
523
+ {
524
+ id: "hero-conversion",
525
+ title: "Hero + Conversion CTA",
526
+ description: "Lead section with headline and primary conversion strip.",
527
+ blocks: [
528
+ {
529
+ blockType: "hero",
530
+ kicker: "Licensed + Insured",
531
+ headline: "Expert Tree Care for Central Texas",
532
+ subheadline: "Reliable trimming, safe removals, and stump grinding for residential and commercial properties.",
533
+ primaryLabel: "Get Your Free Quote",
534
+ primaryHref: "/contact",
535
+ secondaryLabel: "See Our Work",
536
+ secondaryHref: "/portfolio"
537
+ },
538
+ {
539
+ blockType: "cta",
540
+ headline: "Need a quote this week?",
541
+ description: "Call (512) 555-0149 or request an on-site estimate online.",
542
+ buttonLabel: "Contact Us",
543
+ buttonHref: "/contact",
544
+ style: "light"
545
+ }
546
+ ]
547
+ },
548
+ {
549
+ id: "services-grid",
550
+ title: "Services Grid",
551
+ description: "Three-card services section for fast offer communication.",
552
+ blocks: [
553
+ {
554
+ blockType: "featureGrid",
555
+ title: "Our Services",
556
+ variant: "cards",
557
+ items: [
558
+ {
559
+ title: "Tree Trimming & Pruning",
560
+ description: "Canopy balancing, deadwood removal, and seasonal pruning.",
561
+ icon: "Trim"
562
+ },
563
+ {
564
+ title: "Safe Tree Removal",
565
+ description: "Controlled removal for hazardous or unstable trees.",
566
+ icon: "Remove"
567
+ },
568
+ {
569
+ title: "Stump Grinding",
570
+ description: "Below-grade stump grinding and cleanup.",
571
+ icon: "Stump"
572
+ }
573
+ ]
574
+ }
575
+ ]
576
+ },
577
+ {
578
+ id: "social-proof",
579
+ title: "Testimonials + FAQ",
580
+ description: "Trust-building section with reviews and common questions.",
581
+ blocks: [
582
+ {
583
+ blockType: "testimonials",
584
+ title: "What Homeowners Say",
585
+ items: [
586
+ {
587
+ quote: "Great communication, fair pricing, and the cleanup was perfect. We will use them again.",
588
+ name: "Katie M.",
589
+ location: "Austin, TX"
590
+ },
591
+ {
592
+ quote: "They removed a dangerous limb over our driveway quickly and safely.",
593
+ name: "James R.",
594
+ location: "Round Rock, TX"
595
+ }
596
+ ]
597
+ },
598
+ {
599
+ blockType: "faq",
600
+ title: "Common Questions",
601
+ items: [
602
+ {
603
+ question: "How quickly can you schedule service?",
604
+ answer: "Most estimate requests are scheduled within 24 hours."
605
+ },
606
+ {
607
+ question: "Do you provide cleanup?",
608
+ answer: "Yes. Debris haul-off and cleanup are included in quoted scopes."
609
+ }
610
+ ]
611
+ }
612
+ ]
613
+ },
614
+ {
615
+ id: "lead-capture",
616
+ title: "Lead Capture",
617
+ description: "Quote form and consultation CTA for conversion pages.",
618
+ blocks: [
619
+ {
620
+ blockType: "formEmbed",
621
+ title: "Request a Quote",
622
+ description: "Share your project details and we will follow up quickly.",
623
+ formType: "quote"
624
+ },
625
+ {
626
+ blockType: "bookingEmbed",
627
+ title: "Prefer to book a consultation?",
628
+ description: "Choose a time window and we will confirm availability.",
629
+ buttonLabel: "Book Consultation",
630
+ buttonHref: "/contact"
631
+ }
632
+ ]
633
+ }
634
+ ];
635
+ var templateStarterPresets = {
636
+ contact: [
637
+ {
638
+ blockType: "hero",
639
+ headline: "Contact Us",
640
+ subheadline: "Request a quote, ask a question, or book a consultation window.",
641
+ primaryLabel: "Call (512) 555-0149",
642
+ primaryHref: "tel:+15125550149"
643
+ },
644
+ {
645
+ blockType: "formEmbed",
646
+ title: "Request a Quote",
647
+ description: "Tell us about your project and we will follow up quickly.",
648
+ formType: "quote"
649
+ },
650
+ {
651
+ blockType: "faq",
652
+ title: "Common Questions",
653
+ items: [
654
+ {
655
+ question: "How quickly can you provide an estimate?",
656
+ answer: "Most estimates are scheduled within 24 hours."
657
+ }
658
+ ]
659
+ }
660
+ ],
661
+ landing: [
662
+ {
663
+ blockType: "hero",
664
+ kicker: "Locally Owned",
665
+ headline: "Expert Tree Care for Central Texas",
666
+ subheadline: "Premium trimming, removal, and cleanup with safety-first execution.",
667
+ primaryLabel: "Get Your Free Quote",
668
+ primaryHref: "/contact",
669
+ secondaryLabel: "View Services",
670
+ secondaryHref: "/services"
671
+ },
672
+ {
673
+ blockType: "featureGrid",
674
+ title: "Why Homeowners Choose Us",
675
+ variant: "highlight",
676
+ items: [
677
+ { title: "Transparent Pricing", description: "Clear written estimates.", icon: "01" },
678
+ { title: "Safety-First Crew", description: "Property protection and planning.", icon: "02" },
679
+ { title: "Fast Scheduling", description: "Quick estimates and service windows.", icon: "03" }
680
+ ]
681
+ },
682
+ {
683
+ blockType: "cta",
684
+ headline: "Need a quote this week?",
685
+ description: "Call (512) 555-0149 or request an estimate online.",
686
+ buttonLabel: "Contact Us",
687
+ buttonHref: "/contact",
688
+ style: "light"
689
+ }
690
+ ],
691
+ services: [
692
+ {
693
+ blockType: "hero",
694
+ headline: "Tree Services Built for Safety and Curb Appeal",
695
+ subheadline: "Core offerings first, with clear scopes and scheduling.",
696
+ primaryLabel: "Schedule Estimate",
697
+ primaryHref: "/contact"
698
+ },
699
+ {
700
+ blockType: "featureGrid",
701
+ title: "Core Services",
702
+ variant: "cards",
703
+ items: [
704
+ {
705
+ title: "Tree Trimming & Pruning",
706
+ description: "Selective pruning for structure, clearance, and health.",
707
+ icon: "Trim"
708
+ },
709
+ {
710
+ title: "Tree Removal",
711
+ description: "Controlled removal for unstable or hazardous trees.",
712
+ icon: "Remove"
713
+ },
714
+ {
715
+ title: "Stump Grinding",
716
+ description: "Below-grade grinding and cleanup.",
717
+ icon: "Stump"
718
+ }
719
+ ]
720
+ },
721
+ {
722
+ blockType: "faq",
723
+ title: "Frequently Asked Questions",
724
+ items: [
725
+ {
726
+ question: "Do you handle storm cleanup?",
727
+ answer: "Yes. We prioritize urgent hazards after severe weather."
728
+ }
729
+ ]
730
+ }
731
+ ],
732
+ standard: [
733
+ {
734
+ blockType: "hero",
735
+ headline: "Page Headline",
736
+ subheadline: "Use this page to communicate your primary message clearly."
737
+ },
738
+ {
739
+ blockType: "richText",
740
+ title: "Section Heading",
741
+ width: "normal",
742
+ content: {
743
+ root: {
744
+ children: [
745
+ {
746
+ children: [{ detail: 0, format: 0, mode: "normal", style: "", text: "", type: "text", version: 1 }],
747
+ direction: "ltr",
748
+ format: "",
749
+ indent: 0,
750
+ type: "paragraph",
751
+ version: 1
752
+ }
753
+ ],
754
+ direction: "ltr",
755
+ format: "",
756
+ indent: 0,
757
+ type: "root",
758
+ version: 1
759
+ }
760
+ }
761
+ },
762
+ {
763
+ blockType: "cta",
764
+ headline: "Ready to take the next step?",
765
+ buttonLabel: "Contact Us",
766
+ buttonHref: "/contact",
767
+ style: "light"
768
+ }
769
+ ]
770
+ };
771
+ function clonePresetBlocks(blocks) {
772
+ return JSON.parse(JSON.stringify(blocks));
773
+ }
774
+
775
+ // src/index.ts
776
+ var defaultPageLayoutBlocks = [
777
+ HeroBlock,
778
+ RichTextBlock,
779
+ FeatureGridBlock,
780
+ MediaBlock,
781
+ TestimonialsBlock,
782
+ FaqBlock,
783
+ FormEmbedBlock,
784
+ BookingEmbedBlock,
785
+ CtaBlock
786
+ ];
787
+ export {
788
+ BookingEmbedBlock,
789
+ BuilderBlockLabel,
790
+ CtaBlock,
791
+ FaqBlock,
792
+ FeatureGridBlock,
793
+ FormEmbedBlock,
794
+ HeroBlock,
795
+ MediaBlock,
796
+ RichTextBlock,
797
+ TestimonialsBlock,
798
+ builderBlockLabelComponent,
799
+ clonePresetBlocks,
800
+ defaultPageLayoutBlocks,
801
+ sectionPresets,
802
+ templateStarterPresets
803
+ };