@bison-lab/payload-blocks 3.2.0 → 3.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/README.md +167 -18
- package/dist/admin.d.mts +5 -2
- package/dist/admin.d.mts.map +1 -1
- package/dist/admin.mjs +362 -4
- package/dist/admin.mjs.map +1 -1
- package/dist/index.d.mts +139 -21
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +373 -46
- package/dist/index.mjs.map +1 -1
- package/dist/link-CnwLtm47.mjs +41 -0
- package/dist/link-CnwLtm47.mjs.map +1 -0
- package/dist/react.d.mts +78 -8
- package/dist/react.d.mts.map +1 -1
- package/dist/react.mjs +222 -146
- package/dist/react.mjs.map +1 -1
- package/dist/rich-text.d.mts +40 -14
- package/dist/rich-text.d.mts.map +1 -1
- package/dist/rich-text.mjs +81 -18
- package/dist/rich-text.mjs.map +1 -1
- package/dist/seam-CmLb3BSo.mjs +99 -0
- package/dist/seam-CmLb3BSo.mjs.map +1 -0
- package/dist/{types-CJAvoZMk.d.mts → types-ODMRyOpH.d.mts} +134 -18
- package/dist/types-ODMRyOpH.d.mts.map +1 -0
- package/package.json +2 -2
- package/dist/cx-BKHSv3xT.mjs +0 -17
- package/dist/cx-BKHSv3xT.mjs.map +0 -1
- package/dist/types-CJAvoZMk.d.mts.map +0 -1
package/dist/index.mjs
CHANGED
|
@@ -19,30 +19,125 @@ function imageField(overrides = {}) {
|
|
|
19
19
|
//#endregion
|
|
20
20
|
//#region src/fields/link.ts
|
|
21
21
|
/**
|
|
22
|
-
* The
|
|
22
|
+
* The import-map path of the link picker, `LinkField` in
|
|
23
|
+
* `@bison-lab/payload-blocks/admin`.
|
|
23
24
|
*
|
|
24
|
-
*
|
|
25
|
-
*
|
|
26
|
-
*
|
|
27
|
-
*
|
|
25
|
+
* It sits on the row that holds a link's `type`, `page` and `href`, and
|
|
26
|
+
* replaces those three inputs with one box: type to search published pages,
|
|
27
|
+
* or paste a URL. Referenced here by package specifier, like
|
|
28
|
+
* `MIN_ROWS_ARRAY_FIELD`; a site picks it up with `payload generate:importmap`.
|
|
29
|
+
* Until it does, Payload logs the missing entry and renders the row as
|
|
30
|
+
* nothing (a custom `Field` with no component behind it is an empty element,
|
|
31
|
+
* not the stock fields), so the step is part of adopting this release.
|
|
32
|
+
*/
|
|
33
|
+
const LINK_FIELD = "@bison-lab/payload-blocks/admin#LinkField";
|
|
34
|
+
/**
|
|
35
|
+
* The package's resolver: a published, populated page is `/<slug>`; an
|
|
36
|
+
* external link is its `href` as typed.
|
|
37
|
+
*
|
|
38
|
+
* A page that did not populate is `null`: Payload hands the public read the
|
|
39
|
+
* bare id when the reader may not see the page, which is what an unpublished
|
|
40
|
+
* page looks like from the site. A populated page whose `_status` is `draft`
|
|
41
|
+
* is `null` too, for a read that can see drafts. A row from before links had
|
|
42
|
+
* a `type` is an external link by `linkTypeOf`, here, in the stock fields'
|
|
43
|
+
* conditions and in the picker alike: the site keeps rendering its `href`,
|
|
44
|
+
* the admin shows it as an External chip, and the site's migration to
|
|
45
|
+
* `type: external` only makes the stored row say what every reader already
|
|
46
|
+
* assumes.
|
|
47
|
+
*/
|
|
48
|
+
function resolveLink(link) {
|
|
49
|
+
if (!link) return null;
|
|
50
|
+
if (linkTypeOf(link) === "page") {
|
|
51
|
+
const page = link.page;
|
|
52
|
+
if (!page || typeof page !== "object") return null;
|
|
53
|
+
if (page._status === "draft") return null;
|
|
54
|
+
return page.slug ? `/${page.slug}` : null;
|
|
55
|
+
}
|
|
56
|
+
return link.href ? link.href : null;
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Which of the two stored destinations a row is using. `type` decides; a row
|
|
60
|
+
* with no `type` yet (saved before links had one) is read by what it holds,
|
|
61
|
+
* an `href` making it external, the same reading `resolveLink` and the picker
|
|
62
|
+
* make, so all three agree on every row.
|
|
63
|
+
*/
|
|
64
|
+
function linkTypeOf(link) {
|
|
65
|
+
if (link?.type === "external") return "external";
|
|
66
|
+
if (link?.type === "page") return "page";
|
|
67
|
+
return link?.href ? "external" : "page";
|
|
68
|
+
}
|
|
69
|
+
const whenPage = (_data, siblingData) => linkTypeOf(siblingData) === "page";
|
|
70
|
+
const whenExternal = (_data, siblingData) => linkTypeOf(siblingData) === "external";
|
|
71
|
+
/**
|
|
72
|
+
* Where a link goes, as stored: `type`, `page` and `href` in one row.
|
|
73
|
+
*
|
|
74
|
+
* The row carries the picker (`LINK_FIELD`), which replaces all three inputs
|
|
75
|
+
* with one box. The stored fields are the website template's shape and stay
|
|
76
|
+
* editable on their own: `page` shows for a page link, `href` for an external
|
|
77
|
+
* one, and `required` binds whichever is active, since Payload skips
|
|
78
|
+
* validation on a field whose condition is false. `page` offers published
|
|
79
|
+
* rows only, and Payload re-checks that on publish, so a page that was
|
|
80
|
+
* unpublished after being picked has to be picked again or republished.
|
|
81
|
+
*/
|
|
82
|
+
function linkDestinationFields({ required = false, pagesCollection = "pages" } = {}) {
|
|
83
|
+
return [{
|
|
84
|
+
type: "row",
|
|
85
|
+
admin: { components: { Field: LINK_FIELD } },
|
|
86
|
+
fields: [
|
|
87
|
+
{
|
|
88
|
+
name: "type",
|
|
89
|
+
type: "radio",
|
|
90
|
+
label: "Goes to",
|
|
91
|
+
defaultValue: "page",
|
|
92
|
+
options: [{
|
|
93
|
+
label: "Page",
|
|
94
|
+
value: "page"
|
|
95
|
+
}, {
|
|
96
|
+
label: "URL",
|
|
97
|
+
value: "external"
|
|
98
|
+
}],
|
|
99
|
+
admin: { layout: "horizontal" }
|
|
100
|
+
},
|
|
101
|
+
{
|
|
102
|
+
name: "page",
|
|
103
|
+
type: "relationship",
|
|
104
|
+
relationTo: pagesCollection,
|
|
105
|
+
required,
|
|
106
|
+
filterOptions: { _status: { equals: "published" } },
|
|
107
|
+
admin: { condition: whenPage }
|
|
108
|
+
},
|
|
109
|
+
{
|
|
110
|
+
name: "href",
|
|
111
|
+
type: "text",
|
|
112
|
+
label: "URL",
|
|
113
|
+
required,
|
|
114
|
+
admin: {
|
|
115
|
+
condition: whenExternal,
|
|
116
|
+
description: "A full URL (\"https://example.com\"), \"mailto:\" or \"tel:\", or a site path (\"/contact\")."
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
]
|
|
120
|
+
}];
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* The fields a call to action is made of, unwrapped: the destination row,
|
|
124
|
+
* then the label and the new-tab flag.
|
|
28
125
|
*
|
|
29
126
|
* `newTab` drives `target="_blank"` *and* the matching `rel`, which is why no
|
|
30
127
|
* renderer takes one without the other.
|
|
31
128
|
*/
|
|
32
|
-
function linkFields({ required = false, labelFieldLabel = "Label" } = {}) {
|
|
129
|
+
function linkFields({ required = false, labelFieldLabel = "Label", pagesCollection } = {}) {
|
|
33
130
|
return [
|
|
131
|
+
...linkDestinationFields({
|
|
132
|
+
required,
|
|
133
|
+
pagesCollection
|
|
134
|
+
}),
|
|
34
135
|
{
|
|
35
136
|
name: "label",
|
|
36
137
|
type: "text",
|
|
37
138
|
label: labelFieldLabel,
|
|
38
139
|
required
|
|
39
140
|
},
|
|
40
|
-
{
|
|
41
|
-
name: "href",
|
|
42
|
-
type: "text",
|
|
43
|
-
required,
|
|
44
|
-
admin: { description: "A site path (\"/contact\") or a full URL (\"https://example.com\")." }
|
|
45
|
-
},
|
|
46
141
|
{
|
|
47
142
|
name: "newTab",
|
|
48
143
|
type: "checkbox",
|
|
@@ -323,21 +418,27 @@ const ProcessStepsBlock = {
|
|
|
323
418
|
* puts the least-optional copy behind a click. The field names match the
|
|
324
419
|
* `@bison-lab/ui` prop names so the renderers stay a pass-through.
|
|
325
420
|
*/
|
|
326
|
-
function headingFields({ required = true, eyebrowDescription = "Small label above the heading. Leave empty to hide the row." } = {}) {
|
|
421
|
+
function headingFields({ required = true, eyebrowDescription = "Small label above the heading. Leave empty to hide the row.", condition } = {}) {
|
|
422
|
+
const when = condition ? { condition } : {};
|
|
327
423
|
return [
|
|
328
424
|
{
|
|
329
425
|
name: "eyebrow",
|
|
330
426
|
type: "text",
|
|
331
|
-
admin: {
|
|
427
|
+
admin: {
|
|
428
|
+
description: eyebrowDescription,
|
|
429
|
+
...when
|
|
430
|
+
}
|
|
332
431
|
},
|
|
333
432
|
{
|
|
334
433
|
name: "title",
|
|
335
434
|
type: "text",
|
|
336
|
-
required
|
|
435
|
+
required,
|
|
436
|
+
admin: when
|
|
337
437
|
},
|
|
338
438
|
{
|
|
339
439
|
name: "description",
|
|
340
|
-
type: "textarea"
|
|
440
|
+
type: "textarea",
|
|
441
|
+
admin: when
|
|
341
442
|
}
|
|
342
443
|
];
|
|
343
444
|
}
|
|
@@ -389,10 +490,7 @@ const FaqColumnsBlock = {
|
|
|
389
490
|
name: "linkText",
|
|
390
491
|
type: "text"
|
|
391
492
|
},
|
|
392
|
-
|
|
393
|
-
name: "href",
|
|
394
|
-
type: "text"
|
|
395
|
-
},
|
|
493
|
+
...linkDestinationFields(),
|
|
396
494
|
{
|
|
397
495
|
name: "newTab",
|
|
398
496
|
type: "checkbox",
|
|
@@ -641,6 +739,177 @@ const NapBlock = {
|
|
|
641
739
|
]
|
|
642
740
|
};
|
|
643
741
|
//#endregion
|
|
742
|
+
//#region src/fields/row-limits.ts
|
|
743
|
+
/**
|
|
744
|
+
* A custom `validate` replaces Payload's stock array check, so any array
|
|
745
|
+
* with its own rule re-applies the row limits first or `minRows` and
|
|
746
|
+
* `maxRows` stop being enforced. Same messages as the stock check, through
|
|
747
|
+
* the request's translator when the admin supplies one.
|
|
748
|
+
*/
|
|
749
|
+
function rowLimits(value, { minRows, maxRows, required, req }) {
|
|
750
|
+
const count = value?.length ?? 0;
|
|
751
|
+
const t = req?.t;
|
|
752
|
+
if (required && count === 0) return t ? t("validation:required") : "This field is required.";
|
|
753
|
+
if (minRows && count < minRows) return t ? t("validation:requiresAtLeast", {
|
|
754
|
+
count: minRows,
|
|
755
|
+
label: t("general:rows")
|
|
756
|
+
}) : `This field requires at least ${minRows} rows.`;
|
|
757
|
+
if (maxRows && count > maxRows) return t ? t("validation:requiresNoMoreThan", {
|
|
758
|
+
count: maxRows,
|
|
759
|
+
label: t("general:rows")
|
|
760
|
+
}) : `This field requires no more than ${maxRows} rows.`;
|
|
761
|
+
return true;
|
|
762
|
+
}
|
|
763
|
+
//#endregion
|
|
764
|
+
//#region src/blocks/stats-band/config.ts
|
|
765
|
+
/**
|
|
766
|
+
* The rule on `wide`: on phones the band is two per row, so only an odd
|
|
767
|
+
* count has a stat on a row of its own, only one stat can take it, and it
|
|
768
|
+
* has to be a stat that starts a row (the 1st, 3rd or 5th), since a full-row
|
|
769
|
+
* cell beside another cell would leave a hole. The array's own `validate`,
|
|
770
|
+
* so the editor sees the message as they build, and Payload runs it again on
|
|
771
|
+
* publish.
|
|
772
|
+
*/
|
|
773
|
+
const validateWideFlag = (value, options) => {
|
|
774
|
+
const limits = rowLimits(value, options);
|
|
775
|
+
if (limits !== true) return limits;
|
|
776
|
+
const rows = value ?? [];
|
|
777
|
+
const wide = rows.flatMap((row, i) => row?.wide ? [i] : []);
|
|
778
|
+
if (wide.length > 1) return "Only one stat can be full width on phones.";
|
|
779
|
+
if (wide.length === 0) return true;
|
|
780
|
+
if (rows.length % 2 === 0) return "Full width on phones only applies to an odd number of stats. With an even count every row is already full.";
|
|
781
|
+
if (wide[0] % 2 !== 0) return "Only a stat that starts a phone row can be full width: the 1st, 3rd or 5th. Move it up or down one place, or flag another.";
|
|
782
|
+
return true;
|
|
783
|
+
};
|
|
784
|
+
/**
|
|
785
|
+
* An overlapping band is headless: it floats across the seam as a card, and a
|
|
786
|
+
* heading pulled up into the block above would land on the wrong surface.
|
|
787
|
+
* The heading fields disappear from the admin the moment `overlap` is on,
|
|
788
|
+
* and the renderer ignores them if they were filled in first.
|
|
789
|
+
*/
|
|
790
|
+
const unlessOverlap = (_data, siblingData) => !siblingData?.overlap;
|
|
791
|
+
/**
|
|
792
|
+
* A strip of figures: the facts a visitor should take in at a glance.
|
|
793
|
+
*
|
|
794
|
+
* The count, the order and the desktop column count are the editor's. The
|
|
795
|
+
* phone and tablet layouts are the library's: two per row and three per row,
|
|
796
|
+
* with `wide` naming the one stat that takes a full phone row when the count
|
|
797
|
+
* is odd.
|
|
798
|
+
*/
|
|
799
|
+
const StatsBandBlock = {
|
|
800
|
+
slug: "statsBand",
|
|
801
|
+
interfaceName: "StatsBandBlock",
|
|
802
|
+
labels: {
|
|
803
|
+
singular: "Stats Band",
|
|
804
|
+
plural: "Stats Bands"
|
|
805
|
+
},
|
|
806
|
+
fields: [
|
|
807
|
+
...headingFields({
|
|
808
|
+
required: false,
|
|
809
|
+
eyebrowDescription: "Small label above the heading. The heading and eyebrow are optional; without them the band stands alone.",
|
|
810
|
+
condition: unlessOverlap
|
|
811
|
+
}),
|
|
812
|
+
{
|
|
813
|
+
name: "items",
|
|
814
|
+
type: "array",
|
|
815
|
+
required: true,
|
|
816
|
+
minRows: 2,
|
|
817
|
+
maxRows: 6,
|
|
818
|
+
defaultValue: emptyRows(2),
|
|
819
|
+
labels: {
|
|
820
|
+
singular: "Stat",
|
|
821
|
+
plural: "Stats"
|
|
822
|
+
},
|
|
823
|
+
admin: { components: { Field: MIN_ROWS_ARRAY_FIELD } },
|
|
824
|
+
validate: validateWideFlag,
|
|
825
|
+
fields: [
|
|
826
|
+
{
|
|
827
|
+
name: "value",
|
|
828
|
+
type: "text",
|
|
829
|
+
required: true,
|
|
830
|
+
admin: { description: "The figure, as it should read: \"98%\", \"12,000+\", \"L1–S1\"." }
|
|
831
|
+
},
|
|
832
|
+
{
|
|
833
|
+
name: "label",
|
|
834
|
+
type: "textarea",
|
|
835
|
+
required: true
|
|
836
|
+
},
|
|
837
|
+
{
|
|
838
|
+
name: "href",
|
|
839
|
+
type: "text",
|
|
840
|
+
admin: { description: "Optional. Makes the whole stat a link: a site path (\"/outcomes\") or a full URL." }
|
|
841
|
+
},
|
|
842
|
+
{
|
|
843
|
+
name: "wide",
|
|
844
|
+
type: "checkbox",
|
|
845
|
+
label: "Full width on phones",
|
|
846
|
+
defaultValue: false,
|
|
847
|
+
admin: { description: "Phones show two per row. With an odd number of stats, this one takes a row to itself. Only the 1st, 3rd or 5th stat can." }
|
|
848
|
+
}
|
|
849
|
+
]
|
|
850
|
+
},
|
|
851
|
+
{
|
|
852
|
+
name: "columns",
|
|
853
|
+
type: "select",
|
|
854
|
+
defaultValue: "4",
|
|
855
|
+
options: [
|
|
856
|
+
{
|
|
857
|
+
label: "2",
|
|
858
|
+
value: "2"
|
|
859
|
+
},
|
|
860
|
+
{
|
|
861
|
+
label: "3",
|
|
862
|
+
value: "3"
|
|
863
|
+
},
|
|
864
|
+
{
|
|
865
|
+
label: "4",
|
|
866
|
+
value: "4"
|
|
867
|
+
},
|
|
868
|
+
{
|
|
869
|
+
label: "5",
|
|
870
|
+
value: "5"
|
|
871
|
+
},
|
|
872
|
+
{
|
|
873
|
+
label: "6",
|
|
874
|
+
value: "6"
|
|
875
|
+
}
|
|
876
|
+
],
|
|
877
|
+
admin: { description: "From large screens up, and never more than there are stats. Phones show two per row and tablets three." }
|
|
878
|
+
},
|
|
879
|
+
{
|
|
880
|
+
name: "tone",
|
|
881
|
+
type: "select",
|
|
882
|
+
defaultValue: "card",
|
|
883
|
+
options: [{
|
|
884
|
+
label: "Card (bordered, raised)",
|
|
885
|
+
value: "card"
|
|
886
|
+
}, {
|
|
887
|
+
label: "Plain (dividers only)",
|
|
888
|
+
value: "plain"
|
|
889
|
+
}]
|
|
890
|
+
},
|
|
891
|
+
{
|
|
892
|
+
name: "align",
|
|
893
|
+
type: "select",
|
|
894
|
+
defaultValue: "start",
|
|
895
|
+
options: [{
|
|
896
|
+
label: "Left",
|
|
897
|
+
value: "start"
|
|
898
|
+
}, {
|
|
899
|
+
label: "Centred",
|
|
900
|
+
value: "center"
|
|
901
|
+
}]
|
|
902
|
+
},
|
|
903
|
+
{
|
|
904
|
+
name: "overlap",
|
|
905
|
+
type: "checkbox",
|
|
906
|
+
label: "Float over the seam with the block above",
|
|
907
|
+
defaultValue: false,
|
|
908
|
+
admin: { description: "The band sits across the join between the block above and the block below. Both make room for it automatically. A floating band is headless: the heading fields above are hidden while this is on." }
|
|
909
|
+
}
|
|
910
|
+
]
|
|
911
|
+
};
|
|
912
|
+
//#endregion
|
|
644
913
|
//#region src/blocks/mega-menu/rem-width.ts
|
|
645
914
|
/**
|
|
646
915
|
* The one rule for a typed panel width, shared by the config's validator and
|
|
@@ -676,25 +945,6 @@ const TWELFTHS = {
|
|
|
676
945
|
"100": 12
|
|
677
946
|
};
|
|
678
947
|
/**
|
|
679
|
-
* A custom `validate` replaces Payload's stock array check, so the row limits
|
|
680
|
-
* are re-applied here or five columns would pass. Same messages as the stock
|
|
681
|
-
* check, through the request's translator when the admin supplies one.
|
|
682
|
-
*/
|
|
683
|
-
function rowLimits(value, { minRows, maxRows, required, req }) {
|
|
684
|
-
const count = value?.length ?? 0;
|
|
685
|
-
const t = req?.t;
|
|
686
|
-
if (required && count === 0) return t ? t("validation:required") : "This field is required.";
|
|
687
|
-
if (minRows && count < minRows) return t ? t("validation:requiresAtLeast", {
|
|
688
|
-
count: minRows,
|
|
689
|
-
label: t("general:rows")
|
|
690
|
-
}) : `This field requires at least ${minRows} rows.`;
|
|
691
|
-
if (maxRows && count > maxRows) return t ? t("validation:requiresNoMoreThan", {
|
|
692
|
-
count: maxRows,
|
|
693
|
-
label: t("general:rows")
|
|
694
|
-
}) : `This field requires no more than ${maxRows} rows.`;
|
|
695
|
-
return true;
|
|
696
|
-
}
|
|
697
|
-
/**
|
|
698
948
|
* The rule on `columns`: read as fractions, the widths must total 100%. It is
|
|
699
949
|
* the array's own `validate`, so the editor sees the message as they build,
|
|
700
950
|
* and Payload runs field validation again on publish (only draft saves skip
|
|
@@ -990,6 +1240,7 @@ const faqColumnsSample = {
|
|
|
990
1240
|
cta: {
|
|
991
1241
|
title: "Still have questions?",
|
|
992
1242
|
linkText: "Call the front desk",
|
|
1243
|
+
type: "external",
|
|
993
1244
|
href: "tel:+13035550142",
|
|
994
1245
|
newTab: false
|
|
995
1246
|
},
|
|
@@ -1044,12 +1295,19 @@ const heroSample = {
|
|
|
1044
1295
|
alt: "A bright, open treatment room"
|
|
1045
1296
|
}),
|
|
1046
1297
|
links: [{
|
|
1298
|
+
type: "page",
|
|
1299
|
+
page: {
|
|
1300
|
+
id: "sample-page-book",
|
|
1301
|
+
title: "Book an assessment",
|
|
1302
|
+
slug: "book",
|
|
1303
|
+
_status: "published"
|
|
1304
|
+
},
|
|
1047
1305
|
label: "Book an assessment",
|
|
1048
|
-
href: "/book",
|
|
1049
1306
|
newTab: false
|
|
1050
1307
|
}, {
|
|
1051
|
-
|
|
1308
|
+
type: "external",
|
|
1052
1309
|
href: "https://example.com/approach",
|
|
1310
|
+
label: "See our approach",
|
|
1053
1311
|
newTab: true
|
|
1054
1312
|
}]
|
|
1055
1313
|
};
|
|
@@ -1080,7 +1338,10 @@ const megaMenuSampleOptions = {
|
|
|
1080
1338
|
* Spinal Simplicity's Patients panel as a saved row: two featured territories
|
|
1081
1339
|
* in a 75% column, two rail sections in a divided 25% column, overview and
|
|
1082
1340
|
* CTA. Every field is set at least once; the Advanced fields are set but off,
|
|
1083
|
-
* so the percent widths are what renders.
|
|
1341
|
+
* so the percent widths are what renders. Most links are site paths typed as
|
|
1342
|
+
* external links; Testimonials and the overview are page links carried
|
|
1343
|
+
* inline, as `depth: 1` would populate them, so the preview needs no pages
|
|
1344
|
+
* collection.
|
|
1084
1345
|
*/
|
|
1085
1346
|
const megaMenuSample = {
|
|
1086
1347
|
id: "sample-mega-menu",
|
|
@@ -1102,6 +1363,7 @@ const megaMenuSample = {
|
|
|
1102
1363
|
links: [{
|
|
1103
1364
|
id: "lumbar",
|
|
1104
1365
|
label: "Low Back Pain",
|
|
1366
|
+
type: "external",
|
|
1105
1367
|
href: "/patients/low-back-pain",
|
|
1106
1368
|
newTab: false,
|
|
1107
1369
|
description: "Persistent low back pain from lumbar instability, often with leg pain that limits standing or walking.",
|
|
@@ -1109,6 +1371,7 @@ const megaMenuSample = {
|
|
|
1109
1371
|
}, {
|
|
1110
1372
|
id: "si",
|
|
1111
1373
|
label: "Hip Pain",
|
|
1374
|
+
type: "external",
|
|
1112
1375
|
href: "/patients/hip-pain",
|
|
1113
1376
|
newTab: false,
|
|
1114
1377
|
description: "Pain centered on the sacroiliac joint, often worse with sitting or climbing stairs.",
|
|
@@ -1129,18 +1392,26 @@ const megaMenuSample = {
|
|
|
1129
1392
|
{
|
|
1130
1393
|
id: "stories",
|
|
1131
1394
|
label: "Testimonials",
|
|
1132
|
-
|
|
1395
|
+
type: "page",
|
|
1396
|
+
page: {
|
|
1397
|
+
id: "sample-page-stories",
|
|
1398
|
+
title: "Testimonials",
|
|
1399
|
+
slug: "patients/stories",
|
|
1400
|
+
_status: "published"
|
|
1401
|
+
},
|
|
1133
1402
|
newTab: false
|
|
1134
1403
|
},
|
|
1135
1404
|
{
|
|
1136
1405
|
id: "research",
|
|
1137
1406
|
label: "Research",
|
|
1407
|
+
type: "external",
|
|
1138
1408
|
href: "/patients/research",
|
|
1139
1409
|
newTab: false
|
|
1140
1410
|
},
|
|
1141
1411
|
{
|
|
1142
1412
|
id: "path",
|
|
1143
1413
|
label: "Path to Relief",
|
|
1414
|
+
type: "external",
|
|
1144
1415
|
href: "/patients/path-to-relief",
|
|
1145
1416
|
newTab: false
|
|
1146
1417
|
}
|
|
@@ -1153,6 +1424,7 @@ const megaMenuSample = {
|
|
|
1153
1424
|
links: [{
|
|
1154
1425
|
id: "faqs",
|
|
1155
1426
|
label: "FAQs",
|
|
1427
|
+
type: "external",
|
|
1156
1428
|
href: "/patients/faqs",
|
|
1157
1429
|
newTab: false,
|
|
1158
1430
|
description: "Short answers to the questions patients ask first.",
|
|
@@ -1160,6 +1432,7 @@ const megaMenuSample = {
|
|
|
1160
1432
|
}, {
|
|
1161
1433
|
id: "contact",
|
|
1162
1434
|
label: "Contact",
|
|
1435
|
+
type: "external",
|
|
1163
1436
|
href: "https://example.com/contact",
|
|
1164
1437
|
newTab: true,
|
|
1165
1438
|
icon: "mail"
|
|
@@ -1169,11 +1442,18 @@ const megaMenuSample = {
|
|
|
1169
1442
|
footer: {
|
|
1170
1443
|
overview: {
|
|
1171
1444
|
label: "All patient resources",
|
|
1172
|
-
|
|
1445
|
+
type: "page",
|
|
1446
|
+
page: {
|
|
1447
|
+
id: "sample-page-patients",
|
|
1448
|
+
title: "Patients",
|
|
1449
|
+
slug: "patients",
|
|
1450
|
+
_status: "published"
|
|
1451
|
+
},
|
|
1173
1452
|
newTab: false
|
|
1174
1453
|
},
|
|
1175
1454
|
cta: {
|
|
1176
1455
|
label: "Find a Doctor",
|
|
1456
|
+
type: "external",
|
|
1177
1457
|
href: "/find-a-doctor",
|
|
1178
1458
|
newTab: false
|
|
1179
1459
|
}
|
|
@@ -1187,6 +1467,7 @@ const navLinkSample = {
|
|
|
1187
1467
|
id: "sample-nav-link",
|
|
1188
1468
|
blockType: "navLink",
|
|
1189
1469
|
label: "Contact",
|
|
1470
|
+
type: "external",
|
|
1190
1471
|
href: "/contact",
|
|
1191
1472
|
newTab: false
|
|
1192
1473
|
};
|
|
@@ -1422,6 +1703,50 @@ const showcasePanelsSample = {
|
|
|
1422
1703
|
defaultActiveIndex: 0
|
|
1423
1704
|
};
|
|
1424
1705
|
//#endregion
|
|
1706
|
+
//#region src/blocks/stats-band/sample.ts
|
|
1707
|
+
/**
|
|
1708
|
+
* Four figures, the count the strip was designed around: one row on a
|
|
1709
|
+
* desktop, two by two on a tablet and a phone. `wide` is set (to `false`) so
|
|
1710
|
+
* the preview exercises the field, and an even count is where it is ignored.
|
|
1711
|
+
* `overlap` is off so the heading shows: a floating band is headless, and a
|
|
1712
|
+
* preview page has no hero for it to float over.
|
|
1713
|
+
*/
|
|
1714
|
+
const statsBandSample = {
|
|
1715
|
+
id: "sample-stats-band",
|
|
1716
|
+
blockType: "statsBand",
|
|
1717
|
+
eyebrow: "At a glance",
|
|
1718
|
+
title: "The clinic in numbers",
|
|
1719
|
+
description: "What a year looks like across our two rooms, counted from the front desk rather than estimated.",
|
|
1720
|
+
items: [
|
|
1721
|
+
{
|
|
1722
|
+
id: "sample-stat-pain",
|
|
1723
|
+
value: "94%",
|
|
1724
|
+
label: "of patients report less pain by their sixth session.",
|
|
1725
|
+
href: "/outcomes",
|
|
1726
|
+
wide: false
|
|
1727
|
+
},
|
|
1728
|
+
{
|
|
1729
|
+
id: "sample-stat-visits",
|
|
1730
|
+
value: "4,200+",
|
|
1731
|
+
label: "appointments a year across two treatment rooms."
|
|
1732
|
+
},
|
|
1733
|
+
{
|
|
1734
|
+
id: "sample-stat-wait",
|
|
1735
|
+
value: "15 min",
|
|
1736
|
+
label: "average wait from the front desk to the treatment room."
|
|
1737
|
+
},
|
|
1738
|
+
{
|
|
1739
|
+
id: "sample-stat-years",
|
|
1740
|
+
value: "12",
|
|
1741
|
+
label: "years in the same building, on the same street."
|
|
1742
|
+
}
|
|
1743
|
+
],
|
|
1744
|
+
columns: "4",
|
|
1745
|
+
tone: "card",
|
|
1746
|
+
align: "start",
|
|
1747
|
+
overlap: false
|
|
1748
|
+
};
|
|
1749
|
+
//#endregion
|
|
1425
1750
|
//#region src/blocks/testimonial-masonry/sample.ts
|
|
1426
1751
|
function avatar(name) {
|
|
1427
1752
|
return sampleImage({
|
|
@@ -1512,18 +1837,20 @@ const blockSamples = {
|
|
|
1512
1837
|
}
|
|
1513
1838
|
],
|
|
1514
1839
|
link: {
|
|
1515
|
-
|
|
1840
|
+
type: "external",
|
|
1516
1841
|
href: "https://example.com/reviews",
|
|
1842
|
+
label: "Read every review",
|
|
1517
1843
|
newTab: true
|
|
1518
1844
|
},
|
|
1519
1845
|
minItemsForFade: 6,
|
|
1520
1846
|
maxVisibleRows: 2
|
|
1521
1847
|
},
|
|
1522
1848
|
nap: napSample,
|
|
1849
|
+
statsBand: statsBandSample,
|
|
1523
1850
|
megaMenu: megaMenuSample,
|
|
1524
1851
|
navLink: navLinkSample
|
|
1525
1852
|
};
|
|
1526
1853
|
//#endregion
|
|
1527
|
-
export { FaqColumnsBlock, HeroBlock, LinkBlock, MEGA_MENU_WIDTHS, MIN_ROWS_ARRAY_FIELD, NapBlock, ProcessStepsBlock, RichTextBlock, ShowcasePanelsBlock, TestimonialMasonryBlock, blockSamples, emptyRows, headingFields, imageField, linkField, linkFields, megaMenuBlock, megaMenuSampleOptions, resolveMedia, sampleImage, validateColumnWidths, validateRemWidth };
|
|
1854
|
+
export { FaqColumnsBlock, HeroBlock, LINK_FIELD, LinkBlock, MEGA_MENU_WIDTHS, MIN_ROWS_ARRAY_FIELD, NapBlock, ProcessStepsBlock, RichTextBlock, ShowcasePanelsBlock, StatsBandBlock, TestimonialMasonryBlock, blockSamples, emptyRows, headingFields, imageField, linkDestinationFields, linkField, linkFields, linkTypeOf, megaMenuBlock, megaMenuSampleOptions, resolveLink, resolveMedia, sampleImage, validateColumnWidths, validateRemWidth };
|
|
1528
1855
|
|
|
1529
1856
|
//# sourceMappingURL=index.mjs.map
|