@justanarthur/payload-www 0.1.1 → 0.2.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 +2 -1
- package/dist/collections.d.ts +31 -2
- package/dist/collections.js +30 -11
- package/dist/config.d.ts +8 -0
- package/dist/config.js +37 -15
- package/dist/core-fields.d.ts +8 -0
- package/dist/core-fields.js +5 -1
- package/dist/data-collections.d.ts +31 -2
- package/dist/data-collections.js +30 -11
- package/dist/data-test.js +37 -15
- package/dist/fields.d.ts +8 -0
- package/dist/fields.js +5 -1
- package/dist/globals.d.ts +23 -2
- package/dist/globals.js +21 -7
- package/dist/pages.d.ts +14 -1
- package/dist/pages.js +8 -8
- package/dist/render-pages.d.ts +14 -1
- package/dist/render-pages.js +8 -8
- package/dist/render-utils.d.ts +8 -0
- package/dist/render-utils.js +4 -2
- package/dist/server.d.ts +65 -7
- package/dist/server.js +45 -23
- package/dist/test.js +37 -15
- package/dist/with-www-config.d.ts +8 -0
- package/dist/with-www-config.js +37 -15
- package/package.json +4 -4
package/README.md
CHANGED
|
@@ -11,7 +11,7 @@ language switcher share a single source of truth with the rest of your app.
|
|
|
11
11
|
|
|
12
12
|
- **Composer** — `createWWWConfig({ locales, blocks, defaultPlugins? })` returns `{ withWWWConfig }`. One composer call is enough for the most common cases.
|
|
13
13
|
- **Collections** — `Pages` (title, blocks tab, slug, drafts, revalidation hook), `Posts` (title, excerpt, richText, drafts, revalidation hook), `StaticPages` (system pages — 404, 500, search-empty, … — addressed by a `kind` discriminator, not a slug)
|
|
14
|
-
- **Globals** — `Header` and `Footer` (both `nav` blocks with `navColumn` / `navItem`)
|
|
14
|
+
- **Globals** — `Header` and `Footer` (both `nav` blocks with `navColumn` / `navItem`). Extend the nav link schema (e.g. a `description` or a `navHover` mega-menu group) via `createHeaderGlobal({ navColumnLinkFields, navItemLinkFields })` / `createFooterGlobal({ … })`, or `link({ extraFields })` directly.
|
|
15
15
|
- **Default render components** — `PagesPage`, `HeaderPage`, `FooterPage` Server Components. Override any of them by setting a different `custom.path` on the collection / global.
|
|
16
16
|
- **LivePreviewListener** — built in. The lib's `createCollectionPageExports` default page renders it (via `React.lazy` so the server dist stays free of `'use client'` imports) whenever Next.js draft mode is on. Hosts get live preview automatically — no opt-in required. The component itself is also exported from `/render-components` for hosts that want to mount it elsewhere.
|
|
17
17
|
- **Hooks** — `createRevalidateCollectionHook(opts)` (canonical factory for **all** collections: Pages, Posts, host-defined; per-locale `revalidatePath` fan-out + `revalidateTag('collection_<slug>_<id>', 'max')` + sitemap tag, with a `pathMode: 'tag-only'` mode for collections without a URL like `staticPages`), `createRevalidatePageHooks()` (deprecated alias for Pages preset), `createRevalidateGlobalHook(slug)` (per-locale tag for globals)
|
|
@@ -308,6 +308,7 @@ Subpath imports:
|
|
|
308
308
|
| `blocks` | `Block[]` | yes | Blocks the Pages collection accepts. |
|
|
309
309
|
| `linkRelationTo` | `string[]` | no | Collection slugs the Header / Footer nav links can reference. Default: `['pages']`. |
|
|
310
310
|
| `registerPosts` | `boolean` | no | Register the lib's Posts collection. Default `true`. |
|
|
311
|
+
| `nested` | `boolean` | no | Enable nested Pages slugs (`about_us` → `/about/us`). Relaxes the Pages slug validation to accept the `_` divider. Pass the same `nested: true` to `createCollectionPageExports` on the Pages route (and `nested: { pages: true }` to `createSitemapFile`). Default `false`. |
|
|
311
312
|
| StaticPages | — | yes | Always registered (every site has 404). Hosts filter it out in `collections:` to opt. |
|
|
312
313
|
| `defaultPlugins` | `(defaults: Plugin[]) => Plugin[]`| no | Final say on the default `[seoPlugin, imageHashPlugin, translator]` list. |
|
|
313
314
|
|
package/dist/collections.d.ts
CHANGED
|
@@ -76,6 +76,14 @@ type CreatePagesCollectionOptions = {
|
|
|
76
76
|
* when omitted.
|
|
77
77
|
*/
|
|
78
78
|
defaultLocale?: CreateRevalidateCollectionHookOptions["defaultLocale"];
|
|
79
|
+
/**
|
|
80
|
+
* Enable nested (hierarchical) slugs. When `true`, the slug field
|
|
81
|
+
* additionally accepts the `_` nesting divider (so `about_us`
|
|
82
|
+
* renders at `/about/us`) and the admin description documents the
|
|
83
|
+
* convention. Pair with `createCollectionPageExports({ nested: true })`
|
|
84
|
+
* on the matching route. Default: `false` (flat, hyphen-only slugs).
|
|
85
|
+
*/
|
|
86
|
+
nested?: boolean;
|
|
79
87
|
};
|
|
80
88
|
declare const createPagesCollection: (blocks: Block[], options?: Omit<CreatePagesCollectionOptions, "blocks">) => CollectionConfig;
|
|
81
89
|
import { CollectionConfig as CollectionConfig2 } from "payload";
|
|
@@ -134,7 +142,7 @@ type CreateStaticPagesCollectionOptions = {
|
|
|
134
142
|
blocks: Block2[];
|
|
135
143
|
};
|
|
136
144
|
declare const createStaticPagesCollection: (blocks: Block2[]) => CollectionConfig3;
|
|
137
|
-
import { GlobalConfig } from "payload";
|
|
145
|
+
import { Field, GlobalConfig } from "payload";
|
|
138
146
|
type CreateHeaderGlobalOptions = {
|
|
139
147
|
/**
|
|
140
148
|
* Optional override for the `custom.path` Payload uses to resolve
|
|
@@ -148,6 +156,17 @@ type CreateHeaderGlobalOptions = {
|
|
|
148
156
|
* different list when your host has additional linkable collections.
|
|
149
157
|
*/
|
|
150
158
|
linkRelationTo?: string[];
|
|
159
|
+
/**
|
|
160
|
+
* Extra fields appended to each `navColumn` link — e.g. a
|
|
161
|
+
* `description` text field or a `navHover` group for a mega-menu.
|
|
162
|
+
* Lets hosts enrich the column-link schema without redefining the
|
|
163
|
+
* whole nav.
|
|
164
|
+
*/
|
|
165
|
+
navColumnLinkFields?: Field[];
|
|
166
|
+
/**
|
|
167
|
+
* Extra fields appended to each top-level `navItem` link.
|
|
168
|
+
*/
|
|
169
|
+
navItemLinkFields?: Field[];
|
|
151
170
|
};
|
|
152
171
|
/**
|
|
153
172
|
* Build the Header global. The lib's default shape: a `nav` blocks
|
|
@@ -155,7 +174,7 @@ type CreateHeaderGlobalOptions = {
|
|
|
155
174
|
* and `navItem` (a single link).
|
|
156
175
|
*/
|
|
157
176
|
declare const createHeaderGlobal: (options?: CreateHeaderGlobalOptions) => GlobalConfig;
|
|
158
|
-
import { GlobalConfig as GlobalConfig2 } from "payload";
|
|
177
|
+
import { Field as Field2, GlobalConfig as GlobalConfig2 } from "payload";
|
|
159
178
|
type CreateFooterGlobalOptions = {
|
|
160
179
|
/**
|
|
161
180
|
* Optional override for the `custom.path` Payload uses to resolve
|
|
@@ -169,6 +188,16 @@ type CreateFooterGlobalOptions = {
|
|
|
169
188
|
* different list when your host has additional linkable collections.
|
|
170
189
|
*/
|
|
171
190
|
linkRelationTo?: string[];
|
|
191
|
+
/**
|
|
192
|
+
* Extra fields appended to each `navColumn` link — e.g. a
|
|
193
|
+
* `description` text field. Lets hosts enrich the column-link
|
|
194
|
+
* schema without redefining the whole nav.
|
|
195
|
+
*/
|
|
196
|
+
navColumnLinkFields?: Field2[];
|
|
197
|
+
/**
|
|
198
|
+
* Extra fields appended to each top-level `navItem` link.
|
|
199
|
+
*/
|
|
200
|
+
navItemLinkFields?: Field2[];
|
|
172
201
|
};
|
|
173
202
|
/**
|
|
174
203
|
* Build the Footer global. The lib's default shape mirrors the
|
package/dist/collections.js
CHANGED
|
@@ -195,20 +195,25 @@ var createPagesCollection = (blocks, options = {}) => {
|
|
|
195
195
|
renderPath = PAGES_RENDER_PATH,
|
|
196
196
|
slug: collectionSlug = PAGES_SLUG2,
|
|
197
197
|
localePrefix,
|
|
198
|
-
defaultLocale
|
|
198
|
+
defaultLocale,
|
|
199
|
+
nested = false
|
|
199
200
|
} = options;
|
|
201
|
+
const slugPattern = nested ? /^[a-z0-9_-]+$/ : /^[a-z0-9-]+$/;
|
|
200
202
|
const slugField = {
|
|
201
203
|
name: "slug",
|
|
202
204
|
type: "text",
|
|
203
205
|
required: true,
|
|
204
206
|
unique: true,
|
|
205
207
|
index: true,
|
|
206
|
-
admin: {
|
|
208
|
+
admin: {
|
|
209
|
+
position: "sidebar",
|
|
210
|
+
...nested ? { description: "Lowercase, hyphens for words. Use the `_` divider for nesting, e.g. `about_us` → `/about/us`." } : {}
|
|
211
|
+
},
|
|
207
212
|
validate: (value) => {
|
|
208
213
|
if (typeof value !== "string")
|
|
209
214
|
return "Slug must be a string";
|
|
210
|
-
if (value !== "" &&
|
|
211
|
-
return "Slug must be lowercase, with hyphens (no spaces or special characters)";
|
|
215
|
+
if (value !== "" && !slugPattern.test(value)) {
|
|
216
|
+
return nested ? "Slug must be lowercase, with hyphens or the `_` nesting divider (no spaces or other special characters)" : "Slug must be lowercase, with hyphens (no spaces or special characters)";
|
|
212
217
|
}
|
|
213
218
|
return true;
|
|
214
219
|
}
|
|
@@ -420,7 +425,8 @@ var link = (options = {}) => {
|
|
|
420
425
|
disableLabel = false,
|
|
421
426
|
relationTo = [PAGES_SLUG],
|
|
422
427
|
localized = false,
|
|
423
|
-
overrides = {}
|
|
428
|
+
overrides = {},
|
|
429
|
+
extraFields = []
|
|
424
430
|
} = options;
|
|
425
431
|
const result = {
|
|
426
432
|
name: "link",
|
|
@@ -497,6 +503,9 @@ var link = (options = {}) => {
|
|
|
497
503
|
options: opts
|
|
498
504
|
});
|
|
499
505
|
}
|
|
506
|
+
if (extraFields.length) {
|
|
507
|
+
result.fields.push(...extraFields);
|
|
508
|
+
}
|
|
500
509
|
return { ...result, ...overrides };
|
|
501
510
|
};
|
|
502
511
|
|
|
@@ -516,17 +525,22 @@ function createRevalidateGlobalHook(slug) {
|
|
|
516
525
|
|
|
517
526
|
// src/data/collections/globals/Header/config.ts
|
|
518
527
|
var createHeaderGlobal = (options = {}) => {
|
|
519
|
-
const {
|
|
528
|
+
const {
|
|
529
|
+
renderPath = HEADER_RENDER_PATH,
|
|
530
|
+
linkRelationTo = [PAGES_SLUG],
|
|
531
|
+
navColumnLinkFields = [],
|
|
532
|
+
navItemLinkFields = []
|
|
533
|
+
} = options;
|
|
520
534
|
const navColumnBlock = {
|
|
521
535
|
slug: "navColumn",
|
|
522
536
|
fields: [
|
|
523
537
|
{ name: "title", type: "text", required: true, localized: true },
|
|
524
|
-
{ name: "links", type: "array", fields: [link({ appearances: false, localized: true, relationTo: linkRelationTo })] }
|
|
538
|
+
{ name: "links", type: "array", fields: [link({ appearances: false, localized: true, relationTo: linkRelationTo, extraFields: navColumnLinkFields })] }
|
|
525
539
|
]
|
|
526
540
|
};
|
|
527
541
|
const navItemBlock = {
|
|
528
542
|
slug: "navItem",
|
|
529
|
-
fields: [link({ appearances: false, localized: true, relationTo: linkRelationTo })]
|
|
543
|
+
fields: [link({ appearances: false, localized: true, relationTo: linkRelationTo, extraFields: navItemLinkFields })]
|
|
530
544
|
};
|
|
531
545
|
return {
|
|
532
546
|
slug: "header",
|
|
@@ -548,17 +562,22 @@ var createHeaderGlobal = (options = {}) => {
|
|
|
548
562
|
|
|
549
563
|
// src/data/collections/globals/Footer/config.ts
|
|
550
564
|
var createFooterGlobal = (options = {}) => {
|
|
551
|
-
const {
|
|
565
|
+
const {
|
|
566
|
+
renderPath = FOOTER_RENDER_PATH,
|
|
567
|
+
linkRelationTo = [PAGES_SLUG],
|
|
568
|
+
navColumnLinkFields = [],
|
|
569
|
+
navItemLinkFields = []
|
|
570
|
+
} = options;
|
|
552
571
|
const navColumnBlock = {
|
|
553
572
|
slug: "navColumn",
|
|
554
573
|
fields: [
|
|
555
574
|
{ name: "title", type: "text", required: true, localized: true },
|
|
556
|
-
{ name: "links", type: "array", fields: [link({ appearances: false, localized: true, relationTo: linkRelationTo })] }
|
|
575
|
+
{ name: "links", type: "array", fields: [link({ appearances: false, localized: true, relationTo: linkRelationTo, extraFields: navColumnLinkFields })] }
|
|
557
576
|
]
|
|
558
577
|
};
|
|
559
578
|
const navItemBlock = {
|
|
560
579
|
slug: "navItem",
|
|
561
|
-
fields: [link({ appearances: false, localized: true, relationTo: linkRelationTo })]
|
|
580
|
+
fields: [link({ appearances: false, localized: true, relationTo: linkRelationTo, extraFields: navItemLinkFields })]
|
|
562
581
|
};
|
|
563
582
|
return {
|
|
564
583
|
slug: "footer",
|
package/dist/config.d.ts
CHANGED
|
@@ -58,6 +58,14 @@ type WWWConfigOptions = {
|
|
|
58
58
|
*/
|
|
59
59
|
registerPosts?: boolean;
|
|
60
60
|
/**
|
|
61
|
+
* Enable nested (hierarchical) Pages slugs. When `true`, the lib's
|
|
62
|
+
* Pages collection accepts the `_` nesting divider in its slug
|
|
63
|
+
* (`about_us` → `/about/us`). Pass the same `nested: true` to
|
|
64
|
+
* `createCollectionPageExports` on the Pages route so URL building,
|
|
65
|
+
* hreflang, and static params expand the divider. Default: `false`.
|
|
66
|
+
*/
|
|
67
|
+
nested?: boolean;
|
|
68
|
+
/**
|
|
61
69
|
* Final say on the lib's default plugin list. Receives the
|
|
62
70
|
* `[seoPlugin, imageHashPlugin, translator]` array; return the
|
|
63
71
|
* list to apply. Common uses: drop the translator (no AI
|
package/dist/config.js
CHANGED
|
@@ -195,20 +195,25 @@ var createPagesCollection = (blocks, options = {}) => {
|
|
|
195
195
|
renderPath = PAGES_RENDER_PATH,
|
|
196
196
|
slug: collectionSlug = PAGES_SLUG2,
|
|
197
197
|
localePrefix,
|
|
198
|
-
defaultLocale
|
|
198
|
+
defaultLocale,
|
|
199
|
+
nested = false
|
|
199
200
|
} = options;
|
|
201
|
+
const slugPattern = nested ? /^[a-z0-9_-]+$/ : /^[a-z0-9-]+$/;
|
|
200
202
|
const slugField = {
|
|
201
203
|
name: "slug",
|
|
202
204
|
type: "text",
|
|
203
205
|
required: true,
|
|
204
206
|
unique: true,
|
|
205
207
|
index: true,
|
|
206
|
-
admin: {
|
|
208
|
+
admin: {
|
|
209
|
+
position: "sidebar",
|
|
210
|
+
...nested ? { description: "Lowercase, hyphens for words. Use the `_` divider for nesting, e.g. `about_us` → `/about/us`." } : {}
|
|
211
|
+
},
|
|
207
212
|
validate: (value) => {
|
|
208
213
|
if (typeof value !== "string")
|
|
209
214
|
return "Slug must be a string";
|
|
210
|
-
if (value !== "" &&
|
|
211
|
-
return "Slug must be lowercase, with hyphens (no spaces or special characters)";
|
|
215
|
+
if (value !== "" && !slugPattern.test(value)) {
|
|
216
|
+
return nested ? "Slug must be lowercase, with hyphens or the `_` nesting divider (no spaces or other special characters)" : "Slug must be lowercase, with hyphens (no spaces or special characters)";
|
|
212
217
|
}
|
|
213
218
|
return true;
|
|
214
219
|
}
|
|
@@ -420,7 +425,8 @@ var link = (options = {}) => {
|
|
|
420
425
|
disableLabel = false,
|
|
421
426
|
relationTo = [PAGES_SLUG],
|
|
422
427
|
localized = false,
|
|
423
|
-
overrides = {}
|
|
428
|
+
overrides = {},
|
|
429
|
+
extraFields = []
|
|
424
430
|
} = options;
|
|
425
431
|
const result = {
|
|
426
432
|
name: "link",
|
|
@@ -497,6 +503,9 @@ var link = (options = {}) => {
|
|
|
497
503
|
options: opts
|
|
498
504
|
});
|
|
499
505
|
}
|
|
506
|
+
if (extraFields.length) {
|
|
507
|
+
result.fields.push(...extraFields);
|
|
508
|
+
}
|
|
500
509
|
return { ...result, ...overrides };
|
|
501
510
|
};
|
|
502
511
|
|
|
@@ -516,17 +525,22 @@ function createRevalidateGlobalHook(slug) {
|
|
|
516
525
|
|
|
517
526
|
// src/data/collections/globals/Header/config.ts
|
|
518
527
|
var createHeaderGlobal = (options = {}) => {
|
|
519
|
-
const {
|
|
528
|
+
const {
|
|
529
|
+
renderPath = HEADER_RENDER_PATH,
|
|
530
|
+
linkRelationTo = [PAGES_SLUG],
|
|
531
|
+
navColumnLinkFields = [],
|
|
532
|
+
navItemLinkFields = []
|
|
533
|
+
} = options;
|
|
520
534
|
const navColumnBlock = {
|
|
521
535
|
slug: "navColumn",
|
|
522
536
|
fields: [
|
|
523
537
|
{ name: "title", type: "text", required: true, localized: true },
|
|
524
|
-
{ name: "links", type: "array", fields: [link({ appearances: false, localized: true, relationTo: linkRelationTo })] }
|
|
538
|
+
{ name: "links", type: "array", fields: [link({ appearances: false, localized: true, relationTo: linkRelationTo, extraFields: navColumnLinkFields })] }
|
|
525
539
|
]
|
|
526
540
|
};
|
|
527
541
|
const navItemBlock = {
|
|
528
542
|
slug: "navItem",
|
|
529
|
-
fields: [link({ appearances: false, localized: true, relationTo: linkRelationTo })]
|
|
543
|
+
fields: [link({ appearances: false, localized: true, relationTo: linkRelationTo, extraFields: navItemLinkFields })]
|
|
530
544
|
};
|
|
531
545
|
return {
|
|
532
546
|
slug: "header",
|
|
@@ -548,17 +562,22 @@ var createHeaderGlobal = (options = {}) => {
|
|
|
548
562
|
|
|
549
563
|
// src/data/collections/globals/Footer/config.ts
|
|
550
564
|
var createFooterGlobal = (options = {}) => {
|
|
551
|
-
const {
|
|
565
|
+
const {
|
|
566
|
+
renderPath = FOOTER_RENDER_PATH,
|
|
567
|
+
linkRelationTo = [PAGES_SLUG],
|
|
568
|
+
navColumnLinkFields = [],
|
|
569
|
+
navItemLinkFields = []
|
|
570
|
+
} = options;
|
|
552
571
|
const navColumnBlock = {
|
|
553
572
|
slug: "navColumn",
|
|
554
573
|
fields: [
|
|
555
574
|
{ name: "title", type: "text", required: true, localized: true },
|
|
556
|
-
{ name: "links", type: "array", fields: [link({ appearances: false, localized: true, relationTo: linkRelationTo })] }
|
|
575
|
+
{ name: "links", type: "array", fields: [link({ appearances: false, localized: true, relationTo: linkRelationTo, extraFields: navColumnLinkFields })] }
|
|
557
576
|
]
|
|
558
577
|
};
|
|
559
578
|
const navItemBlock = {
|
|
560
579
|
slug: "navItem",
|
|
561
|
-
fields: [link({ appearances: false, localized: true, relationTo: linkRelationTo })]
|
|
580
|
+
fields: [link({ appearances: false, localized: true, relationTo: linkRelationTo, extraFields: navItemLinkFields })]
|
|
562
581
|
};
|
|
563
582
|
return {
|
|
564
583
|
slug: "footer",
|
|
@@ -756,6 +775,7 @@ function createSitemapFile(options) {
|
|
|
756
775
|
const collectionDefaults = options.perCollection?.[collectionSlug] ?? {};
|
|
757
776
|
const urlPrefix = (options.urlPrefixes?.[collectionSlug] ?? "").replace(/\/$/, "");
|
|
758
777
|
const siteUrl = options.getServerSideURL().replace(/\/$/, "");
|
|
778
|
+
const isNested = options.nested?.[collectionSlug] ?? false;
|
|
759
779
|
for (const locale of activeLocales) {
|
|
760
780
|
const docs = await queryAllDocs({
|
|
761
781
|
collectionSlug,
|
|
@@ -771,13 +791,14 @@ function createSitemapFile(options) {
|
|
|
771
791
|
if (seen.has(dedupeKey))
|
|
772
792
|
continue;
|
|
773
793
|
seen.add(dedupeKey);
|
|
774
|
-
const
|
|
794
|
+
const slugPath = isNested ? storedSlug.replaceAll("_", "/") : storedSlug;
|
|
795
|
+
const url = `${siteUrl}${prefixFor(locale, defaultLocale, options.localePrefix ?? "always")}${urlPrefix}/${slugPath}`;
|
|
775
796
|
const languages = await buildHreflangAlternates({
|
|
776
797
|
siteUrl,
|
|
777
798
|
locale,
|
|
778
799
|
urlPrefix,
|
|
779
800
|
storedSlug,
|
|
780
|
-
nested:
|
|
801
|
+
nested: isNested,
|
|
781
802
|
homeSlug: "",
|
|
782
803
|
defaultLocale,
|
|
783
804
|
locales: activeLocales,
|
|
@@ -808,7 +829,7 @@ function createSitemapFile(options) {
|
|
|
808
829
|
}
|
|
809
830
|
// src/config/createWWWConfig.ts
|
|
810
831
|
function createWWWConfig(options) {
|
|
811
|
-
const { locales, routing, blocks, linkRelationTo, registerPosts = true, defaultPlugins } = options;
|
|
832
|
+
const { locales, routing, blocks, linkRelationTo, registerPosts = true, nested = false, defaultPlugins } = options;
|
|
812
833
|
const defaultLocale = routing?.defaultLocale ?? locales[0] ?? "";
|
|
813
834
|
const localePrefixMode = (() => {
|
|
814
835
|
const raw = routing?.localePrefix;
|
|
@@ -821,7 +842,8 @@ function createWWWConfig(options) {
|
|
|
821
842
|
}
|
|
822
843
|
const buildPagesCollection = () => createPagesCollection(blocks, {
|
|
823
844
|
localePrefix: localePrefixMode,
|
|
824
|
-
defaultLocale
|
|
845
|
+
defaultLocale,
|
|
846
|
+
nested
|
|
825
847
|
});
|
|
826
848
|
const buildPostsCollection = () => createPostsCollection({
|
|
827
849
|
localePrefix: localePrefixMode,
|
package/dist/core-fields.d.ts
CHANGED
|
@@ -20,6 +20,14 @@ type LinkOptions = {
|
|
|
20
20
|
overrides?: Partial<GroupField>;
|
|
21
21
|
/** Legacy alias for the host's custom field overrides. */
|
|
22
22
|
linkOverrides?: Partial<GroupField>;
|
|
23
|
+
/**
|
|
24
|
+
* Extra fields appended to the link group — e.g. a `description`
|
|
25
|
+
* text field or a `navHover` group for a mega-menu. Lets hosts
|
|
26
|
+
* extend the nav link schema without re-implementing the whole
|
|
27
|
+
* `link` field. Appended after the standard type/label/appearance
|
|
28
|
+
* fields.
|
|
29
|
+
*/
|
|
30
|
+
extraFields?: Field[];
|
|
23
31
|
};
|
|
24
32
|
declare const link: (options?: LinkOptions) => Field;
|
|
25
33
|
import { Field as Field2 } from "payload";
|
package/dist/core-fields.js
CHANGED
|
@@ -36,7 +36,8 @@ var link = (options = {}) => {
|
|
|
36
36
|
disableLabel = false,
|
|
37
37
|
relationTo = [PAGES_SLUG],
|
|
38
38
|
localized = false,
|
|
39
|
-
overrides = {}
|
|
39
|
+
overrides = {},
|
|
40
|
+
extraFields = []
|
|
40
41
|
} = options;
|
|
41
42
|
const result = {
|
|
42
43
|
name: "link",
|
|
@@ -113,6 +114,9 @@ var link = (options = {}) => {
|
|
|
113
114
|
options: opts
|
|
114
115
|
});
|
|
115
116
|
}
|
|
117
|
+
if (extraFields.length) {
|
|
118
|
+
result.fields.push(...extraFields);
|
|
119
|
+
}
|
|
116
120
|
return { ...result, ...overrides };
|
|
117
121
|
};
|
|
118
122
|
|
|
@@ -76,6 +76,14 @@ type CreatePagesCollectionOptions = {
|
|
|
76
76
|
* when omitted.
|
|
77
77
|
*/
|
|
78
78
|
defaultLocale?: CreateRevalidateCollectionHookOptions["defaultLocale"];
|
|
79
|
+
/**
|
|
80
|
+
* Enable nested (hierarchical) slugs. When `true`, the slug field
|
|
81
|
+
* additionally accepts the `_` nesting divider (so `about_us`
|
|
82
|
+
* renders at `/about/us`) and the admin description documents the
|
|
83
|
+
* convention. Pair with `createCollectionPageExports({ nested: true })`
|
|
84
|
+
* on the matching route. Default: `false` (flat, hyphen-only slugs).
|
|
85
|
+
*/
|
|
86
|
+
nested?: boolean;
|
|
79
87
|
};
|
|
80
88
|
declare const createPagesCollection: (blocks: Block[], options?: Omit<CreatePagesCollectionOptions, "blocks">) => CollectionConfig;
|
|
81
89
|
import { CollectionConfig as CollectionConfig2 } from "payload";
|
|
@@ -134,7 +142,7 @@ type CreateStaticPagesCollectionOptions = {
|
|
|
134
142
|
blocks: Block2[];
|
|
135
143
|
};
|
|
136
144
|
declare const createStaticPagesCollection: (blocks: Block2[]) => CollectionConfig3;
|
|
137
|
-
import { GlobalConfig } from "payload";
|
|
145
|
+
import { Field, GlobalConfig } from "payload";
|
|
138
146
|
type CreateHeaderGlobalOptions = {
|
|
139
147
|
/**
|
|
140
148
|
* Optional override for the `custom.path` Payload uses to resolve
|
|
@@ -148,6 +156,17 @@ type CreateHeaderGlobalOptions = {
|
|
|
148
156
|
* different list when your host has additional linkable collections.
|
|
149
157
|
*/
|
|
150
158
|
linkRelationTo?: string[];
|
|
159
|
+
/**
|
|
160
|
+
* Extra fields appended to each `navColumn` link — e.g. a
|
|
161
|
+
* `description` text field or a `navHover` group for a mega-menu.
|
|
162
|
+
* Lets hosts enrich the column-link schema without redefining the
|
|
163
|
+
* whole nav.
|
|
164
|
+
*/
|
|
165
|
+
navColumnLinkFields?: Field[];
|
|
166
|
+
/**
|
|
167
|
+
* Extra fields appended to each top-level `navItem` link.
|
|
168
|
+
*/
|
|
169
|
+
navItemLinkFields?: Field[];
|
|
151
170
|
};
|
|
152
171
|
/**
|
|
153
172
|
* Build the Header global. The lib's default shape: a `nav` blocks
|
|
@@ -155,7 +174,7 @@ type CreateHeaderGlobalOptions = {
|
|
|
155
174
|
* and `navItem` (a single link).
|
|
156
175
|
*/
|
|
157
176
|
declare const createHeaderGlobal: (options?: CreateHeaderGlobalOptions) => GlobalConfig;
|
|
158
|
-
import { GlobalConfig as GlobalConfig2 } from "payload";
|
|
177
|
+
import { Field as Field2, GlobalConfig as GlobalConfig2 } from "payload";
|
|
159
178
|
type CreateFooterGlobalOptions = {
|
|
160
179
|
/**
|
|
161
180
|
* Optional override for the `custom.path` Payload uses to resolve
|
|
@@ -169,6 +188,16 @@ type CreateFooterGlobalOptions = {
|
|
|
169
188
|
* different list when your host has additional linkable collections.
|
|
170
189
|
*/
|
|
171
190
|
linkRelationTo?: string[];
|
|
191
|
+
/**
|
|
192
|
+
* Extra fields appended to each `navColumn` link — e.g. a
|
|
193
|
+
* `description` text field. Lets hosts enrich the column-link
|
|
194
|
+
* schema without redefining the whole nav.
|
|
195
|
+
*/
|
|
196
|
+
navColumnLinkFields?: Field2[];
|
|
197
|
+
/**
|
|
198
|
+
* Extra fields appended to each top-level `navItem` link.
|
|
199
|
+
*/
|
|
200
|
+
navItemLinkFields?: Field2[];
|
|
172
201
|
};
|
|
173
202
|
/**
|
|
174
203
|
* Build the Footer global. The lib's default shape mirrors the
|
package/dist/data-collections.js
CHANGED
|
@@ -195,20 +195,25 @@ var createPagesCollection = (blocks, options = {}) => {
|
|
|
195
195
|
renderPath = PAGES_RENDER_PATH,
|
|
196
196
|
slug: collectionSlug = PAGES_SLUG2,
|
|
197
197
|
localePrefix,
|
|
198
|
-
defaultLocale
|
|
198
|
+
defaultLocale,
|
|
199
|
+
nested = false
|
|
199
200
|
} = options;
|
|
201
|
+
const slugPattern = nested ? /^[a-z0-9_-]+$/ : /^[a-z0-9-]+$/;
|
|
200
202
|
const slugField = {
|
|
201
203
|
name: "slug",
|
|
202
204
|
type: "text",
|
|
203
205
|
required: true,
|
|
204
206
|
unique: true,
|
|
205
207
|
index: true,
|
|
206
|
-
admin: {
|
|
208
|
+
admin: {
|
|
209
|
+
position: "sidebar",
|
|
210
|
+
...nested ? { description: "Lowercase, hyphens for words. Use the `_` divider for nesting, e.g. `about_us` → `/about/us`." } : {}
|
|
211
|
+
},
|
|
207
212
|
validate: (value) => {
|
|
208
213
|
if (typeof value !== "string")
|
|
209
214
|
return "Slug must be a string";
|
|
210
|
-
if (value !== "" &&
|
|
211
|
-
return "Slug must be lowercase, with hyphens (no spaces or special characters)";
|
|
215
|
+
if (value !== "" && !slugPattern.test(value)) {
|
|
216
|
+
return nested ? "Slug must be lowercase, with hyphens or the `_` nesting divider (no spaces or other special characters)" : "Slug must be lowercase, with hyphens (no spaces or special characters)";
|
|
212
217
|
}
|
|
213
218
|
return true;
|
|
214
219
|
}
|
|
@@ -420,7 +425,8 @@ var link = (options = {}) => {
|
|
|
420
425
|
disableLabel = false,
|
|
421
426
|
relationTo = [PAGES_SLUG],
|
|
422
427
|
localized = false,
|
|
423
|
-
overrides = {}
|
|
428
|
+
overrides = {},
|
|
429
|
+
extraFields = []
|
|
424
430
|
} = options;
|
|
425
431
|
const result = {
|
|
426
432
|
name: "link",
|
|
@@ -497,6 +503,9 @@ var link = (options = {}) => {
|
|
|
497
503
|
options: opts
|
|
498
504
|
});
|
|
499
505
|
}
|
|
506
|
+
if (extraFields.length) {
|
|
507
|
+
result.fields.push(...extraFields);
|
|
508
|
+
}
|
|
500
509
|
return { ...result, ...overrides };
|
|
501
510
|
};
|
|
502
511
|
|
|
@@ -516,17 +525,22 @@ function createRevalidateGlobalHook(slug) {
|
|
|
516
525
|
|
|
517
526
|
// src/data/collections/globals/Header/config.ts
|
|
518
527
|
var createHeaderGlobal = (options = {}) => {
|
|
519
|
-
const {
|
|
528
|
+
const {
|
|
529
|
+
renderPath = HEADER_RENDER_PATH,
|
|
530
|
+
linkRelationTo = [PAGES_SLUG],
|
|
531
|
+
navColumnLinkFields = [],
|
|
532
|
+
navItemLinkFields = []
|
|
533
|
+
} = options;
|
|
520
534
|
const navColumnBlock = {
|
|
521
535
|
slug: "navColumn",
|
|
522
536
|
fields: [
|
|
523
537
|
{ name: "title", type: "text", required: true, localized: true },
|
|
524
|
-
{ name: "links", type: "array", fields: [link({ appearances: false, localized: true, relationTo: linkRelationTo })] }
|
|
538
|
+
{ name: "links", type: "array", fields: [link({ appearances: false, localized: true, relationTo: linkRelationTo, extraFields: navColumnLinkFields })] }
|
|
525
539
|
]
|
|
526
540
|
};
|
|
527
541
|
const navItemBlock = {
|
|
528
542
|
slug: "navItem",
|
|
529
|
-
fields: [link({ appearances: false, localized: true, relationTo: linkRelationTo })]
|
|
543
|
+
fields: [link({ appearances: false, localized: true, relationTo: linkRelationTo, extraFields: navItemLinkFields })]
|
|
530
544
|
};
|
|
531
545
|
return {
|
|
532
546
|
slug: "header",
|
|
@@ -548,17 +562,22 @@ var createHeaderGlobal = (options = {}) => {
|
|
|
548
562
|
|
|
549
563
|
// src/data/collections/globals/Footer/config.ts
|
|
550
564
|
var createFooterGlobal = (options = {}) => {
|
|
551
|
-
const {
|
|
565
|
+
const {
|
|
566
|
+
renderPath = FOOTER_RENDER_PATH,
|
|
567
|
+
linkRelationTo = [PAGES_SLUG],
|
|
568
|
+
navColumnLinkFields = [],
|
|
569
|
+
navItemLinkFields = []
|
|
570
|
+
} = options;
|
|
552
571
|
const navColumnBlock = {
|
|
553
572
|
slug: "navColumn",
|
|
554
573
|
fields: [
|
|
555
574
|
{ name: "title", type: "text", required: true, localized: true },
|
|
556
|
-
{ name: "links", type: "array", fields: [link({ appearances: false, localized: true, relationTo: linkRelationTo })] }
|
|
575
|
+
{ name: "links", type: "array", fields: [link({ appearances: false, localized: true, relationTo: linkRelationTo, extraFields: navColumnLinkFields })] }
|
|
557
576
|
]
|
|
558
577
|
};
|
|
559
578
|
const navItemBlock = {
|
|
560
579
|
slug: "navItem",
|
|
561
|
-
fields: [link({ appearances: false, localized: true, relationTo: linkRelationTo })]
|
|
580
|
+
fields: [link({ appearances: false, localized: true, relationTo: linkRelationTo, extraFields: navItemLinkFields })]
|
|
562
581
|
};
|
|
563
582
|
return {
|
|
564
583
|
slug: "footer",
|