kofi-stack-template-generator 2.1.27 → 2.1.28

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (76) hide show
  1. package/dist/index.js +336 -9
  2. package/package.json +8 -8
  3. package/src/templates.generated.ts +70 -11
  4. package/templates/marketing/payload/src/Footer/config.ts.hbs +178 -0
  5. package/templates/marketing/payload/src/Footer/hooks/revalidateFooter.ts.hbs +13 -0
  6. package/templates/marketing/payload/src/Footer/index.ts.hbs +1 -0
  7. package/templates/marketing/payload/src/Header/RowLabel.tsx.hbs +21 -0
  8. package/templates/marketing/payload/src/Header/config.ts.hbs +208 -0
  9. package/templates/marketing/payload/src/Header/hooks/revalidateHeader.ts.hbs +13 -0
  10. package/templates/marketing/payload/src/Header/index.ts.hbs +1 -0
  11. package/templates/marketing/payload/src/access/anyone.ts.hbs +3 -0
  12. package/templates/marketing/payload/src/access/authenticated.ts.hbs +9 -0
  13. package/templates/marketing/payload/src/access/authenticatedOrPublished.ts.hbs +13 -0
  14. package/templates/marketing/payload/src/access/index.ts.hbs +3 -0
  15. package/templates/marketing/payload/src/app/(frontend)/next/seed/route.ts.hbs +31 -0
  16. package/templates/marketing/payload/src/collections/Categories/index.ts.hbs +28 -0
  17. package/templates/marketing/payload/src/collections/FAQs/index.ts.hbs +100 -0
  18. package/templates/marketing/payload/src/collections/Media.ts.hbs +148 -28
  19. package/templates/marketing/payload/src/collections/Pages/hooks/revalidatePage.ts.hbs +43 -0
  20. package/templates/marketing/payload/src/collections/Pages/index.ts.hbs +142 -0
  21. package/templates/marketing/payload/src/collections/Posts/hooks/populateAuthors.ts.hbs +41 -0
  22. package/templates/marketing/payload/src/collections/Posts/hooks/revalidatePost.ts.hbs +44 -0
  23. package/templates/marketing/payload/src/collections/Posts/index.ts.hbs +244 -0
  24. package/templates/marketing/payload/src/collections/Users/index.ts.hbs +26 -0
  25. package/templates/marketing/payload/src/collections/index.ts.hbs +6 -4
  26. package/templates/marketing/payload/src/components/BeforeDashboard/SeedButton/index.scss.hbs +12 -0
  27. package/templates/marketing/payload/src/components/BeforeDashboard/SeedButton/index.tsx.hbs +89 -0
  28. package/templates/marketing/payload/src/components/BeforeDashboard/index.scss.hbs +24 -0
  29. package/templates/marketing/payload/src/components/BeforeDashboard/index.tsx.hbs +69 -0
  30. package/templates/marketing/payload/src/components/BeforeLogin/index.tsx.hbs +14 -0
  31. package/templates/marketing/payload/src/components/Link/index.tsx.hbs +79 -0
  32. package/templates/marketing/payload/src/components/Media/index.tsx.hbs +67 -0
  33. package/templates/marketing/payload/src/components/RichText/index.tsx.hbs +44 -0
  34. package/templates/marketing/payload/src/endpoints/seed/home.ts.hbs +76 -0
  35. package/templates/marketing/payload/src/endpoints/seed/image-1.ts.hbs +5 -0
  36. package/templates/marketing/payload/src/endpoints/seed/image-2.ts.hbs +5 -0
  37. package/templates/marketing/payload/src/endpoints/seed/image-hero.ts.hbs +5 -0
  38. package/templates/marketing/payload/src/endpoints/seed/index.ts.hbs +235 -0
  39. package/templates/marketing/payload/src/endpoints/seed/post-1.ts.hbs +252 -0
  40. package/templates/marketing/payload/src/fields/defaultLexical.ts.hbs +73 -0
  41. package/templates/marketing/payload/src/fields/index.ts.hbs +3 -0
  42. package/templates/marketing/payload/src/fields/link.ts.hbs +139 -0
  43. package/templates/marketing/payload/src/fields/linkGroup.ts.hbs +28 -0
  44. package/templates/marketing/payload/src/globals/index.ts.hbs +2 -2
  45. package/templates/marketing/payload/src/heros/HighImpact/index.tsx.hbs +53 -0
  46. package/templates/marketing/payload/src/heros/LowImpact/index.tsx.hbs +48 -0
  47. package/templates/marketing/payload/src/heros/MediumImpact/index.tsx.hbs +46 -0
  48. package/templates/marketing/payload/src/heros/PostHero/index.tsx.hbs +68 -0
  49. package/templates/marketing/payload/src/heros/ProductShowcase/index.tsx.hbs +88 -0
  50. package/templates/marketing/payload/src/heros/RenderHero.tsx.hbs +27 -0
  51. package/templates/marketing/payload/src/heros/config.ts.hbs +112 -0
  52. package/templates/marketing/payload/src/heros/index.ts.hbs +7 -0
  53. package/templates/marketing/payload/src/hooks/index.ts.hbs +2 -0
  54. package/templates/marketing/payload/src/hooks/populatePublishedAt.ts.hbs +15 -0
  55. package/templates/marketing/payload/src/hooks/revalidateRedirects.ts.hbs +11 -0
  56. package/templates/marketing/payload/src/payload.config.ts.hbs +32 -8
  57. package/templates/marketing/payload/src/providers/HeaderTheme/index.tsx.hbs +34 -0
  58. package/templates/marketing/payload/src/providers/Theme/InitTheme/index.tsx.hbs +44 -0
  59. package/templates/marketing/payload/src/providers/Theme/index.tsx.hbs +60 -0
  60. package/templates/marketing/payload/src/providers/Theme/shared.ts.hbs +17 -0
  61. package/templates/marketing/payload/src/providers/Theme/types.ts.hbs +10 -0
  62. package/templates/marketing/payload/src/providers/index.tsx.hbs +18 -0
  63. package/templates/marketing/payload/src/utilities/canUseDOM.ts.hbs +1 -0
  64. package/templates/marketing/payload/src/utilities/deepMerge.ts.hbs +35 -0
  65. package/templates/marketing/payload/src/utilities/formatAuthors.ts.hbs +24 -0
  66. package/templates/marketing/payload/src/utilities/formatDateTime.ts.hbs +13 -0
  67. package/templates/marketing/payload/src/utilities/generateMeta.ts.hbs +87 -0
  68. package/templates/marketing/payload/src/utilities/generatePreviewPath.ts.hbs +33 -0
  69. package/templates/marketing/payload/src/utilities/getURL.ts.hbs +26 -0
  70. package/templates/marketing/payload/src/utilities/index.ts.hbs +8 -0
  71. package/templates/marketing/payload/src/utilities/mergeOpenGraph.ts.hbs +26 -0
  72. package/templates/marketing/payload/src/collections/Pages.ts.hbs +0 -66
  73. package/templates/marketing/payload/src/collections/Posts.ts.hbs +0 -65
  74. package/templates/marketing/payload/src/collections/Users.ts.hbs +0 -25
  75. package/templates/marketing/payload/src/globals/Navigation.ts.hbs +0 -51
  76. package/templates/marketing/payload/src/globals/SiteSettings.ts.hbs +0 -49
@@ -0,0 +1,235 @@
1
+ import type { CollectionSlug, File, Payload, PayloadRequest } from "payload"
2
+
3
+ import { home } from "./home"
4
+ import { image1 } from "./image-1"
5
+ import { image2 } from "./image-2"
6
+ import { imageHero } from "./image-hero"
7
+ import { post1 } from "./post-1"
8
+
9
+ const collections: CollectionSlug[] = [
10
+ "categories",
11
+ "media",
12
+ "pages",
13
+ "posts",
14
+ ]
15
+
16
+ const categories = ["Technology", "News", "Finance", "Design", "Software", "Engineering"]
17
+
18
+ // Next.js revalidation errors are normal when seeding the database without a server running
19
+ // i.e. running `yarn seed` locally instead of using the admin UI within an active app
20
+ // The app is not running to revalidate the pages and so the API routes are not available
21
+ // These error messages can be ignored: `Error hitting revalidate route for...`
22
+ export const seed = async ({
23
+ payload,
24
+ req,
25
+ }: {
26
+ payload: Payload
27
+ req: PayloadRequest
28
+ }): Promise<void> => {
29
+ payload.logger.info("Seeding database...")
30
+
31
+ // we need to clear the media directory before seeding
32
+ // as well as the collections and globals
33
+ // this is because while `yarn seed` drops the database
34
+ // the custom `/api/seed` endpoint does not
35
+ payload.logger.info(`— Clearing collections and globals...`)
36
+
37
+ // clear the database - header
38
+ await payload.updateGlobal({
39
+ slug: "header",
40
+ data: {
41
+ navItems: [],
42
+ },
43
+ depth: 0,
44
+ context: {
45
+ disableRevalidate: true,
46
+ },
47
+ })
48
+
49
+ // clear the database - footer
50
+ await payload.updateGlobal({
51
+ slug: "footer",
52
+ data: {
53
+ columns: [],
54
+ socialLinks: {},
55
+ newsletter: { enabled: false },
56
+ copyrightText: "",
57
+ bottomLinks: [],
58
+ },
59
+ depth: 0,
60
+ context: {
61
+ disableRevalidate: true,
62
+ },
63
+ })
64
+
65
+ await Promise.all(
66
+ collections.map((collection) => payload.db.deleteMany({ collection, req, where: {} })),
67
+ )
68
+
69
+ await Promise.all(
70
+ collections
71
+ .filter((collection) => Boolean(payload.collections[collection].config.versions))
72
+ .map((collection) => payload.db.deleteVersions({ collection, req, where: {} })),
73
+ )
74
+
75
+ payload.logger.info(`— Seeding demo author and user...`)
76
+
77
+ await payload.delete({
78
+ collection: "users",
79
+ depth: 0,
80
+ where: {
81
+ email: {
82
+ equals: "demo-author@example.com",
83
+ },
84
+ },
85
+ })
86
+
87
+ payload.logger.info(`— Seeding media...`)
88
+
89
+ const [image1Buffer, image2Buffer, heroBuffer] = await Promise.all([
90
+ fetchFileByURL(
91
+ "https://raw.githubusercontent.com/payloadcms/payload/refs/heads/main/templates/website/src/endpoints/seed/image-post1.webp",
92
+ ),
93
+ fetchFileByURL(
94
+ "https://raw.githubusercontent.com/payloadcms/payload/refs/heads/main/templates/website/src/endpoints/seed/image-post2.webp",
95
+ ),
96
+ fetchFileByURL(
97
+ "https://raw.githubusercontent.com/payloadcms/payload/refs/heads/main/templates/website/src/endpoints/seed/image-hero1.webp",
98
+ ),
99
+ ])
100
+
101
+ const [demoAuthor, image1Doc, image2Doc, imageHeroDoc] = await Promise.all([
102
+ payload.create({
103
+ collection: "users",
104
+ data: {
105
+ name: "Demo Author",
106
+ email: "demo-author@example.com",
107
+ password: "password",
108
+ },
109
+ }),
110
+ payload.create({
111
+ collection: "media",
112
+ data: image1,
113
+ file: image1Buffer,
114
+ }),
115
+ payload.create({
116
+ collection: "media",
117
+ data: image2,
118
+ file: image2Buffer,
119
+ }),
120
+ payload.create({
121
+ collection: "media",
122
+ data: imageHero,
123
+ file: heroBuffer,
124
+ }),
125
+ ...categories.map((category) =>
126
+ payload.create({
127
+ collection: "categories",
128
+ data: {
129
+ title: category,
130
+ },
131
+ }),
132
+ ),
133
+ ])
134
+
135
+ payload.logger.info(`— Seeding posts...`)
136
+
137
+ const post1Doc = await payload.create({
138
+ collection: "posts",
139
+ depth: 0,
140
+ context: {
141
+ disableRevalidate: true,
142
+ },
143
+ data: post1({ heroImage: image1Doc, author: demoAuthor }),
144
+ })
145
+
146
+ payload.logger.info(`— Seeding pages...`)
147
+
148
+ await payload.create({
149
+ collection: "pages",
150
+ depth: 0,
151
+ data: home({ heroImage: imageHeroDoc }),
152
+ })
153
+
154
+ payload.logger.info(`— Seeding globals...`)
155
+
156
+ await Promise.all([
157
+ payload.updateGlobal({
158
+ slug: "header",
159
+ data: {
160
+ navItems: [
161
+ {
162
+ type: "link",
163
+ label: "Posts",
164
+ link: {
165
+ type: "custom",
166
+ url: "/posts",
167
+ },
168
+ },
169
+ ],
170
+ },
171
+ }),
172
+ payload.updateGlobal({
173
+ slug: "footer",
174
+ data: {
175
+ columns: [
176
+ {
177
+ title: "Resources",
178
+ links: [
179
+ {
180
+ link: {
181
+ type: "custom",
182
+ label: "Admin",
183
+ url: "/admin",
184
+ },
185
+ },
186
+ {
187
+ link: {
188
+ type: "custom",
189
+ label: "Payload Docs",
190
+ newTab: true,
191
+ url: "https://payloadcms.com/docs",
192
+ },
193
+ },
194
+ ],
195
+ },
196
+ ],
197
+ socialLinks: {
198
+ github: "https://github.com/payloadcms/payload",
199
+ twitter: "https://x.com/payloadcms",
200
+ },
201
+ newsletter: {
202
+ enabled: true,
203
+ title: "Newsletter",
204
+ description: "Stay up to date with the latest updates.",
205
+ buttonText: "Subscribe",
206
+ placeholder: "Enter your email",
207
+ },
208
+ copyrightText: "{{projectName}}",
209
+ bottomLinks: [],
210
+ },
211
+ }),
212
+ ])
213
+
214
+ payload.logger.info("Seeded database successfully!")
215
+ }
216
+
217
+ async function fetchFileByURL(url: string): Promise<File> {
218
+ const res = await fetch(url, {
219
+ credentials: "include",
220
+ method: "GET",
221
+ })
222
+
223
+ if (!res.ok) {
224
+ throw new Error(`Failed to fetch file from ${url}, status: ${res.status}`)
225
+ }
226
+
227
+ const data = await res.arrayBuffer()
228
+
229
+ return {
230
+ name: url.split("/").pop() || `file-${Date.now()}`,
231
+ data: Buffer.from(data),
232
+ mimetype: `image/${url.split(".").pop()}`,
233
+ size: data.byteLength,
234
+ }
235
+ }
@@ -0,0 +1,252 @@
1
+ import type { Media, User } from "@/payload-types"
2
+ import type { RequiredDataFromCollectionSlug } from "payload"
3
+
4
+ export type PostArgs = {
5
+ heroImage: Media
6
+ author: User
7
+ }
8
+
9
+ export const post1: (args: PostArgs) => RequiredDataFromCollectionSlug<"posts"> = ({
10
+ heroImage,
11
+ author,
12
+ }) => {
13
+ return {
14
+ slug: "getting-started",
15
+ _status: "published",
16
+ authors: [author],
17
+ content: {
18
+ root: {
19
+ type: "root",
20
+ children: [
21
+ {
22
+ type: "heading",
23
+ children: [
24
+ {
25
+ type: "text",
26
+ detail: 0,
27
+ format: 0,
28
+ mode: "normal",
29
+ style: "",
30
+ text: "Welcome to your new Payload CMS site!",
31
+ version: 1,
32
+ },
33
+ ],
34
+ direction: "ltr",
35
+ format: "",
36
+ indent: 0,
37
+ tag: "h2",
38
+ version: 1,
39
+ },
40
+ {
41
+ type: "paragraph",
42
+ children: [
43
+ {
44
+ type: "text",
45
+ detail: 0,
46
+ format: 0,
47
+ mode: "normal",
48
+ style: "",
49
+ text: "This is a sample post to help you get started. You can edit this post from the admin dashboard or create new ones.",
50
+ version: 1,
51
+ },
52
+ ],
53
+ direction: "ltr",
54
+ format: "",
55
+ indent: 0,
56
+ textFormat: 0,
57
+ version: 1,
58
+ },
59
+ {
60
+ type: "heading",
61
+ children: [
62
+ {
63
+ type: "text",
64
+ detail: 0,
65
+ format: 0,
66
+ mode: "normal",
67
+ style: "",
68
+ text: "Key Features",
69
+ version: 1,
70
+ },
71
+ ],
72
+ direction: "ltr",
73
+ format: "",
74
+ indent: 0,
75
+ tag: "h3",
76
+ version: 1,
77
+ },
78
+ {
79
+ type: "paragraph",
80
+ children: [
81
+ {
82
+ type: "text",
83
+ detail: 0,
84
+ format: 0,
85
+ mode: "normal",
86
+ style: "",
87
+ text: "Payload CMS provides a powerful and flexible content management system that integrates seamlessly with Next.js. Some key features include:",
88
+ version: 1,
89
+ },
90
+ ],
91
+ direction: "ltr",
92
+ format: "",
93
+ indent: 0,
94
+ textFormat: 0,
95
+ version: 1,
96
+ },
97
+ {
98
+ type: "list",
99
+ children: [
100
+ {
101
+ type: "listitem",
102
+ children: [
103
+ {
104
+ type: "text",
105
+ detail: 0,
106
+ format: 0,
107
+ mode: "normal",
108
+ style: "",
109
+ text: "Fully customizable collections and fields",
110
+ version: 1,
111
+ },
112
+ ],
113
+ direction: "ltr",
114
+ format: "",
115
+ indent: 0,
116
+ value: 1,
117
+ version: 1,
118
+ },
119
+ {
120
+ type: "listitem",
121
+ children: [
122
+ {
123
+ type: "text",
124
+ detail: 0,
125
+ format: 0,
126
+ mode: "normal",
127
+ style: "",
128
+ text: "Built-in authentication and access control",
129
+ version: 1,
130
+ },
131
+ ],
132
+ direction: "ltr",
133
+ format: "",
134
+ indent: 0,
135
+ value: 2,
136
+ version: 1,
137
+ },
138
+ {
139
+ type: "listitem",
140
+ children: [
141
+ {
142
+ type: "text",
143
+ detail: 0,
144
+ format: 0,
145
+ mode: "normal",
146
+ style: "",
147
+ text: "Live preview and draft functionality",
148
+ version: 1,
149
+ },
150
+ ],
151
+ direction: "ltr",
152
+ format: "",
153
+ indent: 0,
154
+ value: 3,
155
+ version: 1,
156
+ },
157
+ {
158
+ type: "listitem",
159
+ children: [
160
+ {
161
+ type: "text",
162
+ detail: 0,
163
+ format: 0,
164
+ mode: "normal",
165
+ style: "",
166
+ text: "SEO optimization tools",
167
+ version: 1,
168
+ },
169
+ ],
170
+ direction: "ltr",
171
+ format: "",
172
+ indent: 0,
173
+ value: 4,
174
+ version: 1,
175
+ },
176
+ ],
177
+ direction: "ltr",
178
+ format: "",
179
+ indent: 0,
180
+ listType: "bullet",
181
+ start: 1,
182
+ tag: "ul",
183
+ version: 1,
184
+ },
185
+ {
186
+ type: "paragraph",
187
+ children: [
188
+ {
189
+ type: "text",
190
+ detail: 0,
191
+ format: 0,
192
+ mode: "normal",
193
+ style: "",
194
+ text: "Visit the ",
195
+ version: 1,
196
+ },
197
+ {
198
+ type: "link",
199
+ children: [
200
+ {
201
+ type: "text",
202
+ detail: 0,
203
+ format: 0,
204
+ mode: "normal",
205
+ style: "",
206
+ text: "admin dashboard",
207
+ version: 1,
208
+ },
209
+ ],
210
+ direction: "ltr",
211
+ fields: {
212
+ linkType: "custom",
213
+ newTab: false,
214
+ url: "/admin",
215
+ },
216
+ format: "",
217
+ indent: 0,
218
+ version: 3,
219
+ },
220
+ {
221
+ type: "text",
222
+ detail: 0,
223
+ format: 0,
224
+ mode: "normal",
225
+ style: "",
226
+ text: " to start managing your content.",
227
+ version: 1,
228
+ },
229
+ ],
230
+ direction: "ltr",
231
+ format: "",
232
+ indent: 0,
233
+ textFormat: 0,
234
+ version: 1,
235
+ },
236
+ ],
237
+ direction: "ltr",
238
+ format: "",
239
+ indent: 0,
240
+ version: 1,
241
+ },
242
+ },
243
+ heroImage: heroImage.id,
244
+ meta: {
245
+ description: "Learn how to get started with your new Payload CMS site.",
246
+ image: heroImage.id,
247
+ title: "Getting Started with Payload CMS",
248
+ },
249
+ relatedPosts: [],
250
+ title: "Getting Started with Payload CMS",
251
+ }
252
+ }
@@ -0,0 +1,73 @@
1
+ import {
2
+ AlignFeature,
3
+ BlockquoteFeature,
4
+ BoldFeature,
5
+ ChecklistFeature,
6
+ EXPERIMENTAL_TableFeature,
7
+ IndentFeature,
8
+ InlineCodeFeature,
9
+ ItalicFeature,
10
+ LinkFeature,
11
+ type LinkFields,
12
+ OrderedListFeature,
13
+ ParagraphFeature,
14
+ RelationshipFeature,
15
+ StrikethroughFeature,
16
+ SubscriptFeature,
17
+ SuperscriptFeature,
18
+ UnderlineFeature,
19
+ UnorderedListFeature,
20
+ UploadFeature,
21
+ lexicalEditor,
22
+ } from "@payloadcms/richtext-lexical"
23
+ import type { TextFieldSingleValidation } from "payload"
24
+
25
+ export const defaultLexical = lexicalEditor({
26
+ features: [
27
+ ParagraphFeature(),
28
+ UnderlineFeature(),
29
+ BoldFeature(),
30
+ ItalicFeature(),
31
+ StrikethroughFeature(),
32
+ SubscriptFeature(),
33
+ SuperscriptFeature(),
34
+ InlineCodeFeature(),
35
+ BlockquoteFeature(),
36
+ UnorderedListFeature(),
37
+ OrderedListFeature(),
38
+ ChecklistFeature(),
39
+ AlignFeature(),
40
+ IndentFeature(),
41
+ RelationshipFeature(),
42
+ UploadFeature(),
43
+ EXPERIMENTAL_TableFeature(),
44
+ LinkFeature({
45
+ enabledCollections: ["pages", "posts"],
46
+ fields: ({ defaultFields }) => {
47
+ const defaultFieldsWithoutUrl = defaultFields.filter((field) => {
48
+ if ("name" in field && field.name === "url") return false
49
+ return true
50
+ })
51
+
52
+ return [
53
+ ...defaultFieldsWithoutUrl,
54
+ {
55
+ name: "url",
56
+ type: "text",
57
+ admin: {
58
+ condition: (_data, siblingData) => siblingData?.linkType !== "internal",
59
+ },
60
+ label: ({ t }) => t("fields:enterURL"),
61
+ required: true,
62
+ validate: ((value, options) => {
63
+ if ((options?.siblingData as LinkFields)?.linkType === "internal") {
64
+ return true // no validation needed, as no url should exist for internal links
65
+ }
66
+ return value ? true : "URL is required"
67
+ }) as TextFieldSingleValidation,
68
+ },
69
+ ]
70
+ },
71
+ }),
72
+ ],
73
+ })
@@ -0,0 +1,3 @@
1
+ export { link, appearanceOptions, type LinkAppearances } from "./link"
2
+ export { linkGroup } from "./linkGroup"
3
+ export { defaultLexical } from "./defaultLexical"
@@ -0,0 +1,139 @@
1
+ import type { Field, GroupField } from "payload"
2
+
3
+ import deepMerge from "@/utilities/deepMerge"
4
+
5
+ export type LinkAppearances = "default" | "outline"
6
+
7
+ export const appearanceOptions: Record<LinkAppearances, { label: string; value: string }> = {
8
+ default: {
9
+ label: "Default",
10
+ value: "default",
11
+ },
12
+ outline: {
13
+ label: "Outline",
14
+ value: "outline",
15
+ },
16
+ }
17
+
18
+ type LinkType = (options?: {
19
+ appearances?: LinkAppearances[] | false
20
+ disableLabel?: boolean
21
+ overrides?: Partial<GroupField>
22
+ }) => Field
23
+
24
+ export const link: LinkType = ({ appearances, disableLabel = false, overrides = {} } = {}) => {
25
+ const linkResult: GroupField = {
26
+ name: "link",
27
+ type: "group",
28
+ admin: {
29
+ hideGutter: true,
30
+ },
31
+ fields: [
32
+ {
33
+ type: "row",
34
+ fields: [
35
+ {
36
+ name: "type",
37
+ type: "radio",
38
+ admin: {
39
+ layout: "horizontal",
40
+ width: "50%",
41
+ },
42
+ defaultValue: "reference",
43
+ options: [
44
+ {
45
+ label: "Internal link",
46
+ value: "reference",
47
+ },
48
+ {
49
+ label: "Custom URL",
50
+ value: "custom",
51
+ },
52
+ ],
53
+ },
54
+ {
55
+ name: "newTab",
56
+ type: "checkbox",
57
+ admin: {
58
+ style: {
59
+ alignSelf: "flex-end",
60
+ },
61
+ width: "50%",
62
+ },
63
+ label: "Open in new tab",
64
+ },
65
+ ],
66
+ },
67
+ ],
68
+ }
69
+
70
+ const linkTypes: Field[] = [
71
+ {
72
+ name: "reference",
73
+ type: "relationship",
74
+ admin: {
75
+ condition: (_, siblingData) => siblingData?.type === "reference",
76
+ },
77
+ label: "Document to link to",
78
+ relationTo: ["pages", "posts"],
79
+ required: true,
80
+ },
81
+ {
82
+ name: "url",
83
+ type: "text",
84
+ admin: {
85
+ condition: (_, siblingData) => siblingData?.type === "custom",
86
+ },
87
+ label: "Custom URL",
88
+ required: true,
89
+ },
90
+ ]
91
+
92
+ if (!disableLabel) {
93
+ linkTypes.map((linkType) => ({
94
+ ...linkType,
95
+ admin: {
96
+ ...linkType.admin,
97
+ width: "50%",
98
+ },
99
+ }))
100
+
101
+ linkResult.fields.push({
102
+ type: "row",
103
+ fields: [
104
+ ...linkTypes,
105
+ {
106
+ name: "label",
107
+ type: "text",
108
+ admin: {
109
+ width: "50%",
110
+ },
111
+ label: "Label",
112
+ required: true,
113
+ },
114
+ ],
115
+ })
116
+ } else {
117
+ linkResult.fields = [...linkResult.fields, ...linkTypes]
118
+ }
119
+
120
+ if (appearances !== false) {
121
+ let appearanceOptionsToUse = [appearanceOptions.default, appearanceOptions.outline]
122
+
123
+ if (appearances) {
124
+ appearanceOptionsToUse = appearances.map((appearance) => appearanceOptions[appearance])
125
+ }
126
+
127
+ linkResult.fields.push({
128
+ name: "appearance",
129
+ type: "select",
130
+ admin: {
131
+ description: "Choose how the link should be rendered.",
132
+ },
133
+ defaultValue: "default",
134
+ options: appearanceOptionsToUse,
135
+ })
136
+ }
137
+
138
+ return deepMerge(linkResult, overrides)
139
+ }